From 5549fddae54b413f666ebc5f8f46edf815b4deb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 5 Mar 2025 17:59:36 +0100 Subject: [PATCH] Touch control layout screen: Resize the game image to fit the editing surface Makes it easier to place controls properly. Note, if you have disabled "Transparent UI background" in settings, this won't do much. This is a long-requested feature: #16228 --- GPU/Common/PresentationCommon.cpp | 20 ++++++++++++++------ GPU/Common/PresentationCommon.h | 3 +++ UI/EmuScreen.cpp | 4 +++- UI/NativeApp.cpp | 3 +++ UI/TouchControlLayoutScreen.cpp | 19 +++++++++++++++---- 5 files changed, 38 insertions(+), 11 deletions(-) diff --git a/GPU/Common/PresentationCommon.cpp b/GPU/Common/PresentationCommon.cpp index d4fb9f1fae..e35283684d 100644 --- a/GPU/Common/PresentationCommon.cpp +++ b/GPU/Common/PresentationCommon.cpp @@ -44,7 +44,15 @@ struct Vertex { uint32_t rgba; }; -extern Bounds g_imguiCentralNodeBounds; +static bool g_overrideScreenBounds; +static Bounds g_screenBounds; + +void SetOverrideScreenFrame(const Bounds *bounds) { + g_overrideScreenBounds = bounds != nullptr; + if (bounds) { + g_screenBounds = *bounds; + } +} FRect GetScreenFrame(float pixelWidth, float pixelHeight) { FRect rc = FRect{ @@ -70,12 +78,12 @@ FRect GetScreenFrame(float pixelWidth, float pixelHeight) { rc.h -= (top + bottom); } - if (g_Config.bShowImDebugger) { + if (g_overrideScreenBounds) { // Set rectangle to match central node. Here we ignore bIgnoreScreenInsets. - rc.x = g_imguiCentralNodeBounds.x; - rc.y = g_imguiCentralNodeBounds.y; - rc.w = g_imguiCentralNodeBounds.w; - rc.h = g_imguiCentralNodeBounds.h; + rc.x = g_screenBounds.x; + rc.y = g_screenBounds.y; + rc.w = g_screenBounds.w; + rc.h = g_screenBounds.h; } return rc; diff --git a/GPU/Common/PresentationCommon.h b/GPU/Common/PresentationCommon.h index cfda5b8bc0..6732b053c7 100644 --- a/GPU/Common/PresentationCommon.h +++ b/GPU/Common/PresentationCommon.h @@ -46,7 +46,10 @@ struct FRect { float h; }; +struct Bounds; // from geom2d + FRect GetScreenFrame(float pixelWidth, float pixelHeight); +void SetOverrideScreenFrame(const Bounds *bounds); void CalculateDisplayOutputRect(FRect *rc, float origW, float origH, const FRect &frame, int rotation); namespace Draw { diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index 10ebdec1ab..ca1560f396 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -57,6 +57,7 @@ using namespace std::placeholders; #include "Core/MemFault.h" #include "Core/Reporting.h" #include "Core/System.h" +#include "GPU/Common/PresentationCommon.h" #include "Core/FileSystems/VirtualDiscFileSystem.h" #include "GPU/GPUState.h" #include "GPU/GPUCommon.h" @@ -1787,7 +1788,8 @@ void EmuScreen::runImDebugger() { ImGuiDockNode* node = ImGui::DockBuilderGetCentralNode(dockID); // Not elegant! But don't know how else to pass through the bounds, without making a mess. - g_imguiCentralNodeBounds = Bounds(node->Pos.x, node->Pos.y, node->Size.x, node->Size.y); + Bounds centralNode(node->Pos.x, node->Pos.y, node->Size.x, node->Size.y); + SetOverrideScreenFrame(¢ralNode); if (!io.WantCaptureKeyboard) { // Draw a focus rectangle to indicate inputs will be passed through. diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index eaf06f64de..b81ae6db14 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -112,6 +112,7 @@ #include "Core/ThreadPools.h" #include "GPU/GPUCommon.h" +#include "GPU/Common/PresentationCommon.h" #include "UI/AudioCommon.h" #include "UI/BackgroundAudio.h" #include "UI/ControlMappingScreen.h" @@ -1025,6 +1026,8 @@ void NativeFrame(GraphicsContext *graphicsContext) { ProcessWheelRelease(NKCODE_EXT_MOUSEWHEEL_UP, startTime, false); ProcessWheelRelease(NKCODE_EXT_MOUSEWHEEL_DOWN, startTime, false); + SetOverrideScreenFrame(nullptr); + // it's ok to call this redundantly with DoFrame from EmuScreen Achievements::Idle(); diff --git a/UI/TouchControlLayoutScreen.cpp b/UI/TouchControlLayoutScreen.cpp index 03b6e8548f..7d72b3ef91 100644 --- a/UI/TouchControlLayoutScreen.cpp +++ b/UI/TouchControlLayoutScreen.cpp @@ -29,6 +29,7 @@ #include "Common/Log.h" #include "Core/Config.h" #include "Core/System.h" +#include "GPU/Common/PresentationCommon.h" #include "UI/GamepadEmu.h" #include "UI/TouchControlLayoutScreen.h" #include "UI/TouchControlVisibilityScreen.h" @@ -609,13 +610,23 @@ UI::EventReturn TouchControlLayoutScreen::OnMode(UI::EventParams &e) { void TouchControlLayoutScreen::update() { UIDialogScreenWithGameBackground::update(); + if (!layoutView_) { + return; + } + // TODO: We really, really need a cleaner solution for creating sub-views // of custom compound controls. - if (layoutView_) { - if (!layoutView_->HasCreatedViews()) { - layoutView_->CreateViews(); - } + if (!layoutView_->HasCreatedViews()) { + layoutView_->CreateViews(); } + + Bounds bounds = layoutView_->GetBounds(); + // Convert virtual pixels to real pixels. + bounds.x /= g_display.dpi_scale; + bounds.y /= g_display.dpi_scale; + bounds.w /= g_display.dpi_scale; + bounds.h /= g_display.dpi_scale; + SetOverrideScreenFrame(&bounds); } void TouchControlLayoutScreen::CreateViews() {