Usando un widget de imgui para renderizar el display de chip-8
This commit is contained in:
109
src/Graphics.cpp
109
src/Graphics.cpp
@@ -7,6 +7,10 @@
|
||||
#include <array>
|
||||
#include <iostream>
|
||||
|
||||
#include "imgui.h"
|
||||
#include "imgui_impl_sdl3.h"
|
||||
#include "imgui_impl_sdlrenderer3.h"
|
||||
|
||||
void SDLWindowDestroyer::operator()(SDL_Window* window) const {
|
||||
std::cout << "Destroying window" << std::endl;
|
||||
SDL_DestroyWindow(window);
|
||||
@@ -23,12 +27,13 @@ void SDLTextureDestroyer::operator()(SDL_Texture* texture) const {
|
||||
}
|
||||
|
||||
Graphics::Graphics(std::shared_ptr<MachineState> machine_state): machine_state{std::move(machine_state)},
|
||||
width{64 * 30},
|
||||
height{32 * 30},
|
||||
scale{30} {}
|
||||
window_width{1920},
|
||||
window_height{1080},
|
||||
chip8_width(64),
|
||||
chip8_height(32),
|
||||
main_scale(1.0f) {}
|
||||
|
||||
|
||||
bool Graphics::init() {
|
||||
bool Graphics::init_sdl() {
|
||||
SDL_SetAppMetadata("CHIP-8 Emulator", "0.0.1", "fun.skrd.chip8");
|
||||
|
||||
if (!SDL_Init(SDL_INIT_VIDEO)) {
|
||||
@@ -38,7 +43,11 @@ bool Graphics::init() {
|
||||
|
||||
SDL_Window* raw_window = nullptr;
|
||||
SDL_Renderer* raw_renderer = nullptr;
|
||||
if (!SDL_CreateWindowAndRenderer("CHIP-8 Emulator", width, height, 0, &raw_window, &raw_renderer)) {
|
||||
|
||||
main_scale = SDL_GetDisplayContentScale(SDL_GetPrimaryDisplay());
|
||||
SDL_WindowFlags window_flags = SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIDDEN | SDL_WINDOW_HIGH_PIXEL_DENSITY;
|
||||
|
||||
if (!SDL_CreateWindowAndRenderer("CHIP-8 Emulator", window_width * main_scale, window_height * main_scale, window_flags, &raw_window, &raw_renderer)) {
|
||||
SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
|
||||
return false;
|
||||
}
|
||||
@@ -46,22 +55,74 @@ bool Graphics::init() {
|
||||
this->window = std::unique_ptr<SDL_Window, SDLWindowDestroyer>(raw_window);
|
||||
this->renderer = std::unique_ptr<SDL_Renderer, SDLRendererDestroyer>(raw_renderer);
|
||||
|
||||
SDL_Texture* raw_texture = SDL_CreateTexture(renderer.get(), SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, 64 * scale, 32 * scale);
|
||||
SDL_SetRenderVSync(renderer.get(), 1);
|
||||
SDL_SetWindowPosition(window.get(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
|
||||
SDL_ShowWindow(window.get());
|
||||
|
||||
SDL_Texture* raw_texture = SDL_CreateTexture(renderer.get(), SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, chip8_width, chip8_height);
|
||||
this->texture = std::unique_ptr<SDL_Texture, SDLTextureDestroyer>(raw_texture);
|
||||
SDL_SetTextureScaleMode(texture.get(), SDL_SCALEMODE_NEAREST);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Graphics::init_imgui() {
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGui::CreateContext();
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
|
||||
|
||||
ImGui::StyleColorsDark();
|
||||
ImGuiStyle& style = ImGui::GetStyle();
|
||||
style.ScaleAllSizes(main_scale);
|
||||
style.FontScaleDpi = main_scale;
|
||||
|
||||
ImGui_ImplSDL3_InitForSDLRenderer(window.get(), renderer.get());
|
||||
ImGui_ImplSDLRenderer3_Init(renderer.get());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Graphics::init() {
|
||||
if (!init_sdl()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!init_imgui()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Graphics::draw() {
|
||||
SDL_SetRenderDrawColor(renderer.get(), 0, 0, 0, SDL_ALPHA_OPAQUE);
|
||||
if (SDL_GetWindowFlags(window.get()) & SDL_WINDOW_MINIMIZED) {
|
||||
SDL_Delay(10);
|
||||
}
|
||||
|
||||
build_chip8_texture();
|
||||
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
ImGui_ImplSDLRenderer3_NewFrame();
|
||||
ImGui_ImplSDL3_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
|
||||
draw_chip8_widget();
|
||||
|
||||
ImGui::Render();
|
||||
SDL_SetRenderScale(renderer.get(), io.DisplayFramebufferScale.x, io.DisplayFramebufferScale.y);
|
||||
SDL_SetRenderDrawColor(renderer.get(), 0, 0, 0, 0xFF);
|
||||
SDL_RenderClear(renderer.get());
|
||||
|
||||
draw_display();
|
||||
|
||||
ImGui_ImplSDLRenderer3_RenderDrawData(ImGui::GetDrawData(), renderer.get());
|
||||
SDL_RenderPresent(renderer.get());
|
||||
}
|
||||
|
||||
void Graphics::draw_display() {
|
||||
void Graphics::build_chip8_texture() {
|
||||
SDL_Surface* surface = nullptr;
|
||||
auto& display = machine_state->display;
|
||||
|
||||
@@ -70,10 +131,10 @@ void Graphics::draw_display() {
|
||||
|
||||
for (int i = 0; i < display.size(); i++) {
|
||||
if (display[i]) {
|
||||
int x = (i % 64) * scale;
|
||||
int y = (i / 64) * scale;
|
||||
int x = (i % chip8_width);
|
||||
int y = (i / chip8_width);
|
||||
|
||||
SDL_Rect rect = {x, y, scale, scale};
|
||||
SDL_Rect rect = {x, y, 1, 1};
|
||||
Uint32 color = SDL_MapRGB(
|
||||
SDL_GetPixelFormatDetails(surface->format),
|
||||
nullptr,
|
||||
@@ -88,8 +149,22 @@ void Graphics::draw_display() {
|
||||
}
|
||||
SDL_UnlockTexture(texture.get());
|
||||
}
|
||||
|
||||
SDL_FRect destination_rect{0.0, 0.0, static_cast<float>(64 * scale), static_cast<float>(32 * scale)};
|
||||
SDL_RenderTexture(renderer.get(), texture.get(), nullptr, &destination_rect);
|
||||
}
|
||||
|
||||
void Graphics::draw_chip8_widget() {
|
||||
ImGui::Begin("CHIP-8");
|
||||
|
||||
const ImVec2 available_size = ImGui::GetContentRegionAvail();
|
||||
|
||||
int scale_x = static_cast<int>(available_size.x / chip8_width);
|
||||
int scale_y = static_cast<int>(available_size.y / chip8_height);
|
||||
int scale = std::max(1, std::min(scale_x, scale_y));
|
||||
ImVec2 scaled_size(chip8_width * scale, chip8_height * scale);
|
||||
|
||||
ImVec2 cursor_pos = ImGui::GetCursorPos();
|
||||
ImVec2 center_offset((available_size.x - scaled_size.x) / 2, (available_size.y - scaled_size.y) / 2);
|
||||
ImGui::SetCursorPos(ImVec2(cursor_pos.x + center_offset.x, cursor_pos.y + center_offset.y));
|
||||
|
||||
ImGui::Image((ImTextureID)(intptr_t)texture.get(), scaled_size);
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user