From 8cc51b82234ac8fa661c540526376ea56b3e4680 Mon Sep 17 00:00:00 2001 From: moonpower Date: Mon, 2 Feb 2026 01:59:36 +0300 Subject: [PATCH] feat: enable stretching ImGui output based on frontend settings and adjust window sizes --- include/frontend_settings.hpp | 4 ++++ src/config.cpp | 4 ++++ src/panda_sdl/frontend_sdl.cpp | 28 ++++++++++++++++++++-------- src/panda_sdl/imgui_layer.cpp | 23 ++++++++++++++++++----- 4 files changed, 46 insertions(+), 13 deletions(-) diff --git a/include/frontend_settings.hpp b/include/frontend_settings.hpp index 6fa8f2e1..2cbe0475 100644 --- a/include/frontend_settings.hpp +++ b/include/frontend_settings.hpp @@ -28,7 +28,11 @@ struct FrontendSettings { WindowIcon icon = WindowIcon::Rpog; std::string language = "en"; bool showImGuiDebugPanel = true; + #ifdef IMGUI_FRONTEND + bool stretchImGuiOutputToWindow = true; + #else bool stretchImGuiOutputToWindow = false; + #endif static Theme themeFromString(std::string inString); static const char* themeToString(Theme theme); diff --git a/src/config.cpp b/src/config.cpp index 6ebfe269..d3321eca 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -153,7 +153,11 @@ void EmulatorConfig::load() { frontendSettings.icon = FrontendSettings::iconFromString(toml::find_or(ui, "WindowIcon", "rpog")); frontendSettings.language = toml::find_or(ui, "Language", "en"); frontendSettings.showImGuiDebugPanel = toml::find_or(ui, "ShowImGuiDebugPanel", true); + #ifdef IMGUI_FRONTEND + frontendSettings.stretchImGuiOutputToWindow = toml::find_or(ui, "StretchImGuiOutputToWindow", true); + #else frontendSettings.stretchImGuiOutputToWindow = toml::find_or(ui, "StretchImGuiOutputToWindow", false); + #endif } } } diff --git a/src/panda_sdl/frontend_sdl.cpp b/src/panda_sdl/frontend_sdl.cpp index a4681f4d..5380cdb1 100644 --- a/src/panda_sdl/frontend_sdl.cpp +++ b/src/panda_sdl/frontend_sdl.cpp @@ -22,8 +22,8 @@ FrontendSDL::FrontendSDL(SDL_Window* existingWindow, SDL_GLContext existingConte FrontendSDL::ImGuiWindowContext FrontendSDL::createImGuiWindowContext(const EmulatorConfig& bootConfig, const char* windowTitle) { int windowX = SDL_WINDOWPOS_CENTERED; int windowY = SDL_WINDOWPOS_CENTERED; - int windowW = 400; - int windowH = 480; + int windowW = 640; + int windowH = 360; if (bootConfig.windowSettings.rememberPosition) { windowX = bootConfig.windowSettings.x; windowY = bootConfig.windowSettings.y; @@ -115,8 +115,13 @@ void FrontendSDL::initialize(SDL_Window* existingWindow, SDL_GLContext existingC } else { windowX = SDL_WINDOWPOS_CENTERED; windowY = SDL_WINDOWPOS_CENTERED; + #ifdef IMGUI_FRONTEND + windowWidth = 640; + windowHeight = 360; + #else windowWidth = 400; windowHeight = 480; + #endif } // Initialize output size and screen layout @@ -309,22 +314,29 @@ void FrontendSDL::run() { keyboardAnalogX = false; keyboardAnalogY = false; holdingRightClick = false; + #ifdef IMGUI_FRONTEND + int lastDrawableW = -1; + int lastDrawableH = -1; + #endif while (programRunning) { #ifdef IMGUI_FRONTEND const auto& cfg = emu.getConfig(); - if (cfg.frontendSettings.stretchImGuiOutputToWindow) { - int drawableW = 0; - int drawableH = 0; - SDL_GL_GetDrawableSize(window, &drawableW, &drawableH); - if (drawableW > 0 && drawableH > 0) { + int drawableW = 0; + int drawableH = 0; + SDL_GL_GetDrawableSize(window, &drawableW, &drawableH); + if (drawableW > 0 && drawableH > 0 && (drawableW != lastDrawableW || drawableH != lastDrawableH)) { + lastDrawableW = drawableW; + lastDrawableH = drawableH; + if (cfg.frontendSettings.stretchImGuiOutputToWindow) { windowWidth = u32(drawableW); windowHeight = u32(drawableH); emu.setOutputSize(windowWidth, windowHeight); + } + if (cfg.frontendSettings.stretchImGuiOutputToWindow) { ScreenLayout::calculateCoordinates( screenCoordinates, windowWidth, windowHeight, cfg.topScreenSize, cfg.screenLayout ); - glViewport(0, 0, drawableW, drawableH); } } #endif diff --git a/src/panda_sdl/imgui_layer.cpp b/src/panda_sdl/imgui_layer.cpp index 9a5b70a4..c8481433 100644 --- a/src/panda_sdl/imgui_layer.cpp +++ b/src/panda_sdl/imgui_layer.cpp @@ -280,11 +280,13 @@ std::optional ImGuiLayer::runGameSelector() { #endif ImGuiWindowFlags flags = ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize; + const float maxW = std::max(200.0f, drawableW * 0.9f); + const float maxH = std::max(150.0f, drawableH * 0.9f); if (showNoRom) { std::string rootLabel = primaryScanRootLabel(); ImGui::SetNextWindowPos(ImVec2(drawableW * 0.5f, drawableH * 0.5f), ImGuiCond_Always, ImVec2(0.5f, 0.5f)); - ImGui::SetNextWindowSize(ImVec2(620, 260), ImGuiCond_Always); + ImGui::SetNextWindowSize(ImVec2(std::min(620.0f, maxW), std::min(260.0f, maxH)), ImGuiCond_Always); ImGui::Begin("No ROMs Found", nullptr, flags); ImGui::TextWrapped( "No ROM inserted!\n\n" @@ -305,7 +307,7 @@ std::optional ImGuiLayer::runGameSelector() { ImGui::End(); } else if (!inSettings) { ImGui::SetNextWindowPos(ImVec2(drawableW * 0.5f, drawableH * 0.5f), ImGuiCond_Always, ImVec2(0.5f, 0.5f)); - ImGui::SetNextWindowSize(ImVec2(800, 600), ImGuiCond_Always); + ImGui::SetNextWindowSize(ImVec2(std::min(800.0f, maxW), std::min(600.0f, maxH)), ImGuiCond_Always); ImGui::Begin("Select Game", nullptr, flags); for (int i = 0; i < (int)games.size(); i++) { @@ -316,7 +318,7 @@ std::optional ImGuiLayer::runGameSelector() { ImGui::Dummy(ImVec2(0, 8)); ImGui::Separator(); ImGui::Dummy(ImVec2(0, 8)); - ImGui::SetCursorPosX((800 - 120) * 0.5f); + ImGui::SetCursorPosX((ImGui::GetWindowWidth() - 120.0f) * 0.5f); if (ImGui::Button("Settings", ImVec2(120, 0))) { inSettings = true; showSettings = true; @@ -360,12 +362,20 @@ void ImGuiLayer::drawDebugPanel() { return; } + int winW = 0; + int winH = 0; + SDL_GL_GetDrawableSize(window, &winW, &winH); + const float maxW = std::max(220.0f, winW * 0.45f); + const float maxH = std::max(120.0f, winH * 0.45f); + ImGui::SetNextWindowSizeConstraints(ImVec2(200.0f, 0.0f), ImVec2(maxW, maxH)); + ImGui::SetNextWindowPos(ImVec2(float(kDebugPadding), float(kDebugPadding)), ImGuiCond_Always); ImGui::SetNextWindowBgAlpha(0.35f); ImGuiWindowFlags flags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoNav | ImGuiWindowFlags_NoSavedSettings; ImGui::Begin("##DebugOverlay", nullptr, flags); + ImGui::PushTextWrapPos(ImGui::GetCursorPosX() + maxW - 20.0f); int major = 0; int minor = 0; glGetIntegerv(GL_MAJOR_VERSION, &major); @@ -377,6 +387,7 @@ void ImGuiLayer::drawDebugPanel() { ImGui::Text("Revision: %s", versionInfo.gitRevision.c_str()); ImGui::Text("FPS : %.1f", ImGui::GetIO().Framerate); ImGui::Text("Paused : %s", isPaused ? "Yes" : "No"); + ImGui::PopTextWrapPos(); ImGui::End(); } @@ -427,8 +438,10 @@ void ImGuiLayer::drawSettingsPanel() { int winW = 0; int winH = 0; SDL_GL_GetDrawableSize(window, &winW, &winH); - const float width = 520.0f; - const float height = 640.0f * 0.65f; + const float maxW = std::max(240.0f, winW * 0.9f); + const float maxH = std::max(200.0f, winH * 0.9f); + const float width = std::min(520.0f, maxW); + const float height = std::min(640.0f * 0.65f, maxH); ImGui::SetNextWindowSize(ImVec2(width, height), ImGuiCond_Always); ImGui::SetNextWindowPos(ImVec2(winW * 0.5f, winH * 0.5f), ImGuiCond_Always, ImVec2(0.5f, 0.5f));