From 37462a0c5f87aa0c22e5990c01398e1f92aa226c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 29 Oct 2025 10:14:19 +0100 Subject: [PATCH] Add new TwoPane screen type, use for tilt controls. Adapts to portrait/landscape nicely. --- UI/SimpleDialogScreen.cpp | 39 +++++++++++++++++++++++++++ UI/SimpleDialogScreen.h | 20 ++++++++++++++ UI/TiltAnalogSettingsScreen.cpp | 48 +++++++++++---------------------- UI/TiltAnalogSettingsScreen.h | 13 +++++---- 4 files changed, 82 insertions(+), 38 deletions(-) diff --git a/UI/SimpleDialogScreen.cpp b/UI/SimpleDialogScreen.cpp index ec44e8609a..a019a7fec2 100644 --- a/UI/SimpleDialogScreen.cpp +++ b/UI/SimpleDialogScreen.cpp @@ -1,4 +1,5 @@ #include "Common/UI/ScrollView.h" +#include "Common/Data/Text/I18n.h" #include "UI/SimpleDialogScreen.h" #include "UI/MiscViews.h" @@ -25,3 +26,41 @@ void UISimpleBaseDialogScreen::CreateViews() { } } +void UITwoPaneBaseDialogScreen::CreateViews() { + using namespace UI; + + const bool portrait = UsePortraitLayout(); + + auto di = GetI18NCategory(I18NCat::DIALOG); + + if (portrait) { + // Portrait layout is just a vertical stack. + ignoreBottomInset_ = true; + LinearLayout *root = new LinearLayout(ORIENT_VERTICAL, new LayoutParams(FILL_PARENT, FILL_PARENT)); + root->Add(new TopBar(*screenManager()->getUIContext(), portrait, GetTitle())); + root->SetSpacing(0); + CreateContentViews(root); + + ScrollView *settingsScroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, FILL_PARENT, 1.0f)); + LinearLayout *settingsPane = new LinearLayout(ORIENT_VERTICAL); + settingsScroll->Add(settingsPane); + CreateSettingsViews(settingsPane); + root->Add(settingsScroll); + + root_ = root; + } else { + ignoreBottomInset_ = false; + LinearLayout *root = new LinearLayout(ORIENT_HORIZONTAL, new LayoutParams(FILL_PARENT, FILL_PARENT)); + // root_->Add(new TopBar(*screenManager()->getUIContext(), portrait, GetTitle(), new LayoutParams(FILL_PARENT, FILL_PARENT))); + LinearLayout *settingsPane = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(400.0f, FILL_PARENT)); + settingsPane->SetSpacing(0); + CreateSettingsViews(settingsPane); + settingsPane->Add(new BorderView(BORDER_BOTTOM, BorderStyle::HEADER_FG, 2.0f, new LayoutParams(FILL_PARENT, 40.0f))); + settingsPane->Add(new Choice(di->T("Back"), ImageID("I_NAVIGATE_BACK")))->OnClick.Handle(this, &UIScreen::OnBack); + root->Add(settingsPane); + CreateContentViews(root); + + root_ = root; + } +} + diff --git a/UI/SimpleDialogScreen.h b/UI/SimpleDialogScreen.h index 1602132d83..bff9cd6cdf 100644 --- a/UI/SimpleDialogScreen.h +++ b/UI/SimpleDialogScreen.h @@ -23,3 +23,23 @@ protected: private: void CreateViews() override; }; + +// A two-pane version of the above, where settings are meant to go in the settings pane, +// and contents in the content pane. Will generate nice layouts for portrait and landscape. +// but with a consistent portrait-compatible back button and title. +// The settings pane is scrollable while the other is not. +class UITwoPaneBaseDialogScreen : public UIBaseDialogScreen { +public: + UITwoPaneBaseDialogScreen(const Path &gamePath = Path()) : UIBaseDialogScreen(gamePath) { + // We need to check CanScroll before we know whether to ignore + // bottom inset. Can't do that here, we do it in CreateViews + } + + // Override this, don't override CreateViews. And don't touch root_ directly. + virtual void CreateSettingsViews(UI::LinearLayout *parent) = 0; + virtual void CreateContentViews(UI::LinearLayout *parent) = 0; + virtual std::string_view GetTitle() const { return ""; } + +private: + void CreateViews() override; +}; diff --git a/UI/TiltAnalogSettingsScreen.cpp b/UI/TiltAnalogSettingsScreen.cpp index 5a4093d430..70f4088c5c 100644 --- a/UI/TiltAnalogSettingsScreen.cpp +++ b/UI/TiltAnalogSettingsScreen.cpp @@ -78,42 +78,29 @@ void TiltAnalogSettingsScreen::CreateCalibrationView(UI::ViewGroup *parent, UI:: } } -void TiltAnalogSettingsScreen::CreateViews() { - using namespace UI; - +std::string_view TiltAnalogSettingsScreen::GetTitle() const { auto co = GetI18NCategory(I18NCat::CONTROLS); - auto di = GetI18NCategory(I18NCat::DIALOG); + return co->T("Tilt control setup"); +} + +void TiltAnalogSettingsScreen::CreateContentViews(UI::LinearLayout *parent) { + using namespace UI; + CreateCalibrationView(parent, new LinearLayoutParams(300.0f, 300.0f, 1.0f, G_CENTER)); +} + +void TiltAnalogSettingsScreen::CreateSettingsViews(UI::LinearLayout *settings) { + using namespace UI; + auto co = GetI18NCategory(I18NCat::CONTROLS); + GamepadUpdateOpacity(1.0f); - bool portrait = UsePortraitLayout(); - - root_ = new LinearLayout(portrait ? ORIENT_VERTICAL : ORIENT_HORIZONTAL); - root_->SetTag("TiltAnalogSettings"); - - LinearLayout *settings = new LinearLayoutList(ORIENT_VERTICAL); - if (portrait) { - LinearLayout *topBar = root_->Add(new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT))); - topBar->Add(new Choice(ImageID("I_NAVIGATE_BACK"), new LinearLayoutParams(64, WRAP_CONTENT)))->OnClick.Handle(this, &UIScreen::OnBack); - CreateCalibrationView(root_, new LinearLayoutParams(250, 250, 0.0f, UI::G_HCENTER)); - ViewGroup *menuRoot = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(1.0f)); - menuRoot->Add(settings); - root_->Add(menuRoot); - } else { - ViewGroup *menuRoot = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(600, FILL_PARENT)); - root_->Add(menuRoot); - menuRoot->Add(settings); - CreateCalibrationView(root_, new LinearLayoutParams(1.0)); - } - auto enabledFunc = [=]() -> bool { return g_Config.iTiltInputType != 0; }; - settings->SetSpacing(0); - settings->Add(new ItemHeader(co->T("Tilt control setup"))); settings->Add(new PopupMultiChoice(&g_Config.iTiltInputType, co->T("Tilt Input Type"), g_tiltTypes, 0, g_numTiltTypes, I18NCat::CONTROLS, screenManager()))->OnChoice.Add( - [=](UI::EventParams &p) { + [this](UI::EventParams &p) { //when the tilt event type is modified, we need to reset all tilt settings. //refer to the ResetTiltEvents() function for a detailed explanation. TiltEventProcessor::ResetTiltEvents(); @@ -141,11 +128,6 @@ void TiltAnalogSettingsScreen::CreateViews() { settings->Add(new ItemHeader(co->T("Invert Axes"))); settings->Add(new CheckBox(&g_Config.bInvertTiltX, co->T("Invert Tilt along X axis")))->SetEnabledFunc(enabledFunc); settings->Add(new CheckBox(&g_Config.bInvertTiltY, co->T("Invert Tilt along Y axis")))->SetEnabledFunc(enabledFunc); - - if (!portrait) { - settings->Add(new BorderView(BORDER_BOTTOM, BorderStyle::HEADER_FG, 2.0f, new LayoutParams(FILL_PARENT, 40.0f))); - settings->Add(new Choice(di->T("Back")))->OnClick.Handle(this, &UIScreen::OnBack); - } } void TiltAnalogSettingsScreen::OnCalibrate(UI::EventParams &e) { @@ -153,7 +135,7 @@ void TiltAnalogSettingsScreen::OnCalibrate(UI::EventParams &e) { } void TiltAnalogSettingsScreen::update() { - UIBaseDialogScreen::update(); + UITwoPaneBaseDialogScreen::update(); if (tilt_) { tilt_->SetXY( Clamp(TiltEventProcessor::rawTiltAnalogX, -1.0f, 1.0f), diff --git a/UI/TiltAnalogSettingsScreen.h b/UI/TiltAnalogSettingsScreen.h index a28ea659f6..539a811ed9 100644 --- a/UI/TiltAnalogSettingsScreen.h +++ b/UI/TiltAnalogSettingsScreen.h @@ -19,23 +19,26 @@ #include "Common/Math/math_util.h" #include "Common/UI/View.h" -#include "BaseScreens.h" +#include "SimpleDialogScreen.h" class JoystickHistoryView; class GamepadView; -class TiltAnalogSettingsScreen : public UIBaseDialogScreen { +class TiltAnalogSettingsScreen : public UITwoPaneBaseDialogScreen { public: - TiltAnalogSettingsScreen(const Path &gamePath) : UIBaseDialogScreen(gamePath) {} + TiltAnalogSettingsScreen(const Path &gamePath) : UITwoPaneBaseDialogScreen(gamePath) {} + + void CreateSettingsViews(UI::LinearLayout *parent) override; + void CreateContentViews(UI::LinearLayout *parent) override; + std::string_view GetTitle() const override; - void CreateViews() override; void update() override; const char *tag() const override { return "TiltAnalogSettings"; } private: void OnCalibrate(UI::EventParams &e); void CreateCalibrationView(UI::ViewGroup *parent, UI::LayoutParams *layoutParams); - + Lin::Vec3 down_{}; JoystickHistoryView *tilt_ = nullptr; };