Merge pull request #21041 from hrydgard/control-mappings-ui

Fix touch controls and control mappings UI in portrait
This commit is contained in:
Henrik Rydgård
2025-11-25 20:25:17 +01:00
committed by GitHub
15 changed files with 151 additions and 137 deletions
+43 -38
View File
@@ -57,7 +57,7 @@ using KeyMap::MultiInputMapping;
class SingleControlMapper : public UI::LinearLayout {
public:
SingleControlMapper(int pspKey, std::string keyName, ScreenManager *scrm, UI::LinearLayoutParams *layoutParams = nullptr);
SingleControlMapper(int pspKey, std::string keyName, bool portrait, ScreenManager *scrm, UI::LinearLayoutParams *layoutParams = nullptr);
~SingleControlMapper() {
g_IsMappingMouseInput = false;
}
@@ -79,10 +79,11 @@ private:
std::vector<UI::View *> rows_;
std::string keyName_;
ScreenManager *scrm_;
bool portrait_;
};
SingleControlMapper::SingleControlMapper(int pspKey, std::string keyName, ScreenManager *scrm, UI::LinearLayoutParams *layoutParams)
: UI::LinearLayout(ORIENT_VERTICAL, layoutParams), pspKey_(pspKey), keyName_(keyName), scrm_(scrm) {
SingleControlMapper::SingleControlMapper(int pspKey, std::string keyName, bool portrait, ScreenManager *scrm, UI::LinearLayoutParams *layoutParams)
: UI::LinearLayout(ORIENT_VERTICAL, layoutParams), pspKey_(pspKey), keyName_(keyName), scrm_(scrm), portrait_(portrait) {
Refresh();
}
@@ -106,7 +107,7 @@ void SingleControlMapper::Refresh() {
float itemH = 55.0f;
float leftColumnWidth = 200;
float rightColumnWidth = 350; // TODO: Should be flexible somehow. Maybe we need to implement Measure.
float rightColumnWidth = 350;
LinearLayout *root = Add(new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT)));
root->SetSpacing(3.0f);
@@ -129,7 +130,7 @@ void SingleControlMapper::Refresh() {
p->OnClick.Handle(this, &SingleControlMapper::OnAddMouse);
}
LinearLayout *rightColumn = root->Add(new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(rightColumnWidth, WRAP_CONTENT)));
LinearLayout *rightColumn = root->Add(new LinearLayout(ORIENT_VERTICAL, portrait_ ? new LinearLayoutParams(1.0f) : new LinearLayoutParams(rightColumnWidth, WRAP_CONTENT)));
rightColumn->SetSpacing(2.0f);
std::vector<MultiInputMapping> mappings;
KeyMap::InputMappingsFromPspButton(pspKey_, &mappings, false);
@@ -232,59 +233,63 @@ static const BindingCategory cats[] = {
{}, // sentinel
};
void ControlMappingScreen::CreateExtraButtons(UI::ViewGroup *verticalLayout, int margins) {
void ControlMappingScreen::CreateSettingsViews(UI::ViewGroup *parent) {
using namespace UI;
auto km = GetI18NCategory(I18NCat::KEYMAPPING);
verticalLayout->Add(new Choice(km->T("Clear All")))->OnClick.Add([](UI::EventParams &) {
parent->Add(new Choice(km->T("Clear All")))->OnClick.Add([](UI::EventParams &) {
KeyMap::ClearAllMappings();
});
verticalLayout->Add(new Choice(km->T("Default All")))->OnClick.Add([](UI::EventParams &) {
parent->Add(new Choice(km->T("Default All")))->OnClick.Add([](UI::EventParams &) {
KeyMap::RestoreDefault();
});
std::string sysName = System_GetProperty(SYSPROP_NAME);
// If there's a builtin controller, restore to default should suffice. No need to conf the controller on top.
if (!KeyMap::HasBuiltinController(sysName) && KeyMap::GetSeenPads().size()) {
verticalLayout->Add(new Choice(km->T("Autoconfigure")))->OnClick.Handle(this, &ControlMappingScreen::OnAutoConfigure);
parent->Add(new Choice(km->T("Autoconfigure")))->OnClick.Handle(this, &ControlMappingScreen::OnAutoConfigure);
}
verticalLayout->Add(new CheckBox(&g_Config.bAllowMappingCombos, km->T("Allow combo mappings")));
verticalLayout->Add(new CheckBox(&g_Config.bStrictComboOrder, km->T("Strict combo input order")));
verticalLayout->Add(new Spacer(12.0f));
parent->Add(new CheckBox(&g_Config.bAllowMappingCombos, km->T("Allow combo mappings")));
parent->Add(new CheckBox(&g_Config.bStrictComboOrder, km->T("Strict combo input order")));
}
void ControlMappingScreen::CreateTabs() {
std::string_view ControlMappingScreen::GetTitle() const {
auto co = GetI18NCategory(I18NCat::CONTROLS);
return co->T("Control mapping");
}
void ControlMappingScreen::CreateContentViews(UI::ViewGroup *parent) {
using namespace UI;
LinearLayout *rootLayout = parent->Add(new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT)));
mappers_.clear();
size_t numMappableKeys = 0;
const KeyMap::KeyMap_IntStrPair *mappableKeys = KeyMap::GetMappableKeys(&numMappableKeys);
auto km = GetI18NCategory(I18NCat::KEYMAPPING);
AddTab("keymap", "Control mapping", [this](UI::LinearLayout *parent) {
size_t numMappableKeys = 0;
const KeyMap::KeyMap_IntStrPair *mappableKeys = KeyMap::GetMappableKeys(&numMappableKeys);
bool portrait = GetDeviceOrientation() == DeviceOrientation::Portrait;
auto km = GetI18NCategory(I18NCat::KEYMAPPING);
int curCat = -1;
CollapsibleSection *curSection = nullptr;
for (size_t i = 0; i < numMappableKeys; i++) {
if (curCat < (int)ARRAY_SIZE(cats) && mappableKeys[i].key == cats[curCat + 1].firstKey) {
if (curCat >= 0) {
curSection->SetOpenPtr(&categoryToggles_[curCat]);
}
curCat++;
curSection = parent->Add(new CollapsibleSection(km->T(cats[curCat].catName)));
curSection->SetSpacing(6.0f);
int curCat = -1;
CollapsibleSection *curSection = nullptr;
for (size_t i = 0; i < numMappableKeys; i++) {
if (curCat < (int)ARRAY_SIZE(cats) && mappableKeys[i].key == cats[curCat + 1].firstKey) {
if (curCat >= 0) {
curSection->SetOpenPtr(&categoryToggles_[curCat]);
}
SingleControlMapper *mapper = curSection->Add(
new SingleControlMapper(mappableKeys[i].key, mappableKeys[i].name, screenManager(),
new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT)));
mapper->SetTag(StringFromFormat("KeyMap%s", mappableKeys[i].name));
mappers_.push_back(mapper);
curCat++;
curSection = rootLayout->Add(new CollapsibleSection(km->T(cats[curCat].catName)));
curSection->SetSpacing(6.0f);
}
if (curCat >= 0 && curSection) {
curSection->SetOpenPtr(&categoryToggles_[curCat]);
}
_dbg_assert_(curCat == ARRAY_SIZE(cats) - 2); // count the sentinel
}, TabFlags::Default);
SingleControlMapper *mapper = curSection->Add(
new SingleControlMapper(mappableKeys[i].key, mappableKeys[i].name, portrait, screenManager()));
mapper->SetTag(StringFromFormat("KeyMap%s", mappableKeys[i].name));
mappers_.push_back(mapper);
}
if (curCat >= 0 && curSection) {
curSection->SetOpenPtr(&categoryToggles_[curCat]);
}
_dbg_assert_(curCat == ARRAY_SIZE(cats) - 2); // count the sentinel
keyMapGeneration_ = KeyMap::g_controllerMapGeneration;
}
+6 -5
View File
@@ -37,9 +37,9 @@
class SingleControlMapper;
class ControlMappingScreen : public UITabbedBaseDialogScreen {
class ControlMappingScreen : public UITwoPaneBaseDialogScreen {
public:
ControlMappingScreen(const Path &gamePath) : UITabbedBaseDialogScreen(gamePath, TabDialogFlags::ContextMenuInPortrait) {
ControlMappingScreen(const Path &gamePath) : UITwoPaneBaseDialogScreen(gamePath, TwoPaneFlags::SettingsInContextMenu | TwoPaneFlags::ContentsCanScroll) {
categoryToggles_[0] = true;
categoryToggles_[1] = true;
categoryToggles_[2] = true;
@@ -48,13 +48,14 @@ public:
const char *tag() const override { return "ControlMapping"; }
protected:
void CreateTabs() override;
void CreateExtraButtons(UI::ViewGroup *verticalLayout, int margins) override;
void CreateSettingsViews(UI::ViewGroup *parent) override;
void CreateContentViews(UI::ViewGroup *parent) override;
void update() override;
std::string_view GetTitle() const override;
private:
void OnAutoConfigure(UI::EventParams &params);
bool ShowSearchControls() const override { return false; }
void dialogFinished(const Screen *dialog, DialogResult result) override;
+7 -8
View File
@@ -121,15 +121,13 @@ std::string_view CustomButtonMappingScreen::GetTitle() const {
return co->T("Custom touch button setup");
}
void CustomButtonMappingScreen::CreateViews() {
void CustomButtonMappingScreen::CreateDialogViews(UI::ViewGroup *parent) {
using namespace UI;
using namespace CustomKeyData;
auto co = GetI18NCategory(I18NCat::CONTROLS);
auto mc = GetI18NCategory(I18NCat::MAPPABLECONTROLS);
root_ = new LinearLayout(ORIENT_VERTICAL);
root_->Add(new ItemHeader(GetTitle()));
LinearLayout *root__ = new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(1.0));
root_->Add(root__);
LinearLayout *root__ = new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(FILL_PARENT, FILL_PARENT, 1.0));
parent->Add(root__);
LinearLayout *leftColumn = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(120, FILL_PARENT));
auto di = GetI18NCategory(I18NCat::DIALOG);
@@ -143,13 +141,14 @@ void CustomButtonMappingScreen::CreateViews() {
for (int i = 0; i < ARRAY_SIZE(g_customKeyList); i++)
array[i] = (0x01 == ((g_Config.CustomButton[id_].key >> i) & 0x01));
// TODO: Less hacky layout work
const Bounds layoutBounds = screenManager()->getUIContext()->GetLayoutBounds();
leftColumn->Add(new ButtonPreview(g_Config.iTouchButtonStyle == 0 ? customKeyShapes[cfg->shape].i : customKeyShapes[cfg->shape].l,
customKeyImages[cfg->image].i, customKeyImages[cfg->image].r, customKeyShapes[cfg->shape].f, customKeyShapes[cfg->shape].r, 62, 82));
customKeyImages[cfg->image].i, customKeyImages[cfg->image].r, customKeyShapes[cfg->shape].f, customKeyShapes[cfg->shape].r, layoutBounds.x + 62, layoutBounds.y + 102));
root__->Add(leftColumn);
ScrollView *rightScroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(WRAP_CONTENT, WRAP_CONTENT, 1.0f));
leftColumn->Add(new Spacer(new LinearLayoutParams(1.0f)));
leftColumn->Add(new Choice(di->T("Back")))->OnClick.Handle<UIScreen>(this, &UIScreen::OnBack);
root__->Add(rightScroll);
LinearLayout *vertLayout = new LinearLayout(ORIENT_VERTICAL);
+6 -4
View File
@@ -19,23 +19,25 @@
#include "UI/BaseScreens.h"
#include "UI/GamepadEmu.h"
#include "UI/SimpleDialogScreen.h"
namespace UI {
class CheckBox;
}
class CustomButtonMappingScreen : public UIBaseDialogScreen {
class CustomButtonMappingScreen : public UISimpleBaseDialogScreen {
public:
CustomButtonMappingScreen(DeviceOrientation deviceOrientation, const Path &gamePath, int id) : UIBaseDialogScreen(gamePath), deviceOrientation_(deviceOrientation), id_(id) {}
CustomButtonMappingScreen(DeviceOrientation deviceOrientation, const Path &gamePath, int id) : UISimpleBaseDialogScreen(gamePath, SimpleDialogFlags::Default), deviceOrientation_(deviceOrientation), id_(id) {}
const char *tag() const override { return "CustomButton"; }
void CreateViews() override;
void CreateDialogViews(UI::ViewGroup *parent) override;
void onFinish(DialogResult result) override;
protected:
void dialogFinished(const Screen *dialog, DialogResult result) override;
std::string_view GetTitle() const;
std::string_view GetTitle() const override;
private:
void saveArray();
+1 -2
View File
@@ -119,13 +119,12 @@ private:
class CreditsScreen : public UISimpleBaseDialogScreen {
public:
CreditsScreen() : UISimpleBaseDialogScreen() {}
CreditsScreen() : UISimpleBaseDialogScreen(Path(), SimpleDialogFlags::Default) {}
void update() override;
protected:
std::string_view GetTitle() const override;
void CreateDialogViews(UI::ViewGroup *parent) override;
bool CanScroll() const override { return false; }
const char *tag() const override { return "Credits"; }
};
+22 -12
View File
@@ -419,6 +419,10 @@ void GamePauseScreen::CreateViews() {
root_ = new LinearLayout(portrait ? ORIENT_VERTICAL : ORIENT_HORIZONTAL);
if (portrait) {
((LinearLayout *)root_)->SetSpacing(0);
}
if (portrait) {
// We have room for a title bar. Use the game DB title if available.
std::string title;
@@ -533,9 +537,12 @@ void GamePauseScreen::CreateViews() {
ViewGroup *buttonColumn = nullptr;
if (portrait) {
buttonColumn = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT));
middleColumn = new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(FILL_PARENT, ITEM_HEIGHT, Margins(10, 10, 10, 10)));
root_->Add(middleColumn);
root_->Add(buttonColumn);
} else {
middleColumn = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(64, FILL_PARENT, Margins(0, 10, 0, 15)));
middleColumn = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(ITEM_HEIGHT, FILL_PARENT, Margins(0, 10, 0, 15)));
root_->Add(middleColumn);
middleColumn->SetSpacing(0.0f);
@@ -559,15 +566,11 @@ void GamePauseScreen::CreateViews() {
Choice *continueChoice = rightColumnItems->Add(new Choice(pa->T("Continue"), ImageID("I_PLAY")));
root_->SetDefaultFocusView(continueChoice);
continueChoice->OnClick.Handle<UIScreen>(this, &UIScreen::OnBack);
rightColumnItems->Add(new Spacer(20.0));
}
rightColumnItems->Add(new Spacer(20.0));
if (g_paramSFO.IsValid() && g_Config.HasGameConfig(g_paramSFO.GetDiscID())) {
rightColumnItems->Add(new Choice(pa->T("Game Settings"), ImageID("I_GEAR")))->OnClick.Handle(this, &GamePauseScreen::OnGameSettings);
Choice *delGameConfig = rightColumnItems->Add(new Choice(pa->T("Delete Game Config")));
delGameConfig->OnClick.Handle(this, &GamePauseScreen::OnDeleteConfig);
delGameConfig->SetEnabled(!bootPending_);
} else if (PSP_CoreParameter().fileType != IdentifiedFileType::PPSSPP_GE_DUMP) {
rightColumnItems->Add(new Choice(pa->T("Settings"), ImageID("I_GEAR")))->OnClick.Handle(this, &GamePauseScreen::OnGameSettings);
Choice *createGameConfig = rightColumnItems->Add(new Choice(pa->T("Create Game Config"), ImageID("I_GEAR_STAR")));
@@ -628,7 +631,7 @@ void GamePauseScreen::CreateViews() {
exit->SetEnabled(!bootPending_);
if (middleColumn) {
middleColumn->SetSpacing(20.0f);
middleColumn->SetSpacing(portrait ? 8.0f : 20.0f);
playButton_ = middleColumn->Add(new Button("", g_Config.bRunBehindPauseMenu ? ImageID("I_PAUSE") : ImageID("I_PLAY"), new LinearLayoutParams(64, 64)));
playButton_->OnClick.Add([=](UI::EventParams &e) {
g_Config.bRunBehindPauseMenu = !g_Config.bRunBehindPauseMenu;
@@ -643,11 +646,12 @@ void GamePauseScreen::CreateViews() {
screenManager()->push(new GameScreen(gamePath_, true));
});
Button *menuButton = middleColumn->Add(new Button("", ImageID("I_THREE_DOTS"), new LinearLayoutParams(64, 64)));
menuButton->OnClick.Add([this, menuButton, portrait](UI::EventParams &e) {
ShowContextMenu(menuButton, portrait);
});
if (!portrait) {
Button *menuButton = middleColumn->Add(new Button("", ImageID("I_THREE_DOTS"), new LinearLayoutParams(64, 64)));
menuButton->OnClick.Add([this, menuButton, portrait](UI::EventParams &e) {
ShowContextMenu(menuButton, portrait);
});
}
} else {
playButton_ = nullptr;
}
@@ -671,6 +675,12 @@ void GamePauseScreen::ShowContextMenu(UI::View *menuButton, bool portrait) {
}
});
auto pa = GetI18NCategory(I18NCat::PAUSE);
Choice *delGameConfig = parent->Add(new Choice(pa->T("Delete Game Config")));
delGameConfig->OnClick.Handle(this, &GamePauseScreen::OnDeleteConfig);
delGameConfig->SetEnabled(!bootPending_);
if (portrait) {
// Add some other options that are removed from the main screen in portrait mode.
if (Reporting::IsSupported() && g_paramSFO.GetValueString("DISC_ID").size()) {
+1 -1
View File
@@ -418,7 +418,7 @@ void ReportScreen::HandleBrowser(UI::EventParams &e) {
}
ReportFinishScreen::ReportFinishScreen(const Path &gamePath, ReportingOverallScore score)
: UISimpleBaseDialogScreen(), gamePath_(gamePath), score_(score) {
: UISimpleBaseDialogScreen(Path(), SimpleDialogFlags::ContentsCanScroll), gamePath_(gamePath), score_(score) {
}
std::string_view ReportFinishScreen::GetTitle() const {
+11 -3
View File
@@ -7,7 +7,7 @@
void UISimpleBaseDialogScreen::CreateViews() {
using namespace UI;
const bool canScroll = CanScroll();
const bool canScroll = flags_ & SimpleDialogFlags::ContentsCanScroll;
ignoreBottomInset_ = canScroll;
const bool portrait = GetDeviceOrientation() == DeviceOrientation::Portrait;
@@ -36,9 +36,17 @@ void UITwoPaneBaseDialogScreen::CreateViews() {
BeforeCreateViews();
auto createContentViews = [this](UI::ViewGroup *parent) {
auto createContentViews = [this, portrait](UI::ViewGroup *parent) {
if (flags_ & TwoPaneFlags::ContentsCanScroll) {
ScrollView *contentScroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, FILL_PARENT, 1.0f, Margins(8)));
Margins margins(8, 8, 8, 0);
if (flags_ & TwoPaneFlags::SettingsToTheRight) {
// If settings are in context menu, we want to avoid double margins on the sides.
margins.left = 0;
} else {
margins.right = 0;
}
ScrollView *contentScroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, FILL_PARENT, 1.0f, margins));
parent->Add(contentScroll);
CreateContentViews(contentScroll);
} else {
+8 -3
View File
@@ -5,11 +5,17 @@
#include "UI/BaseScreens.h"
enum class SimpleDialogFlags {
Default = 0,
ContentsCanScroll = 8,
};
ENUM_CLASS_BITOPS(SimpleDialogFlags);
// The simpler cousin of TabbedDialogScreen, without tabs or the other bling,
// but with a consistent portrait-compatible back button and title.
class UISimpleBaseDialogScreen : public UIBaseDialogScreen {
public:
UISimpleBaseDialogScreen(const Path &gamePath = Path()) : UIBaseDialogScreen(gamePath) {
UISimpleBaseDialogScreen(const Path &gamePath, SimpleDialogFlags flags) : UIBaseDialogScreen(gamePath), flags_(flags) {
// We need to check CanScroll before we know whether to ignore
// bottom inset. Can't do that here, we do it in CreateViews
}
@@ -17,11 +23,10 @@ public:
// Override this, don't override CreateViews. And don't touch root_ directly.
virtual void CreateDialogViews(UI::ViewGroup *parent) = 0;
virtual std::string_view GetTitle() const { return ""; }
protected:
virtual bool CanScroll() const { return true; }
private:
void CreateViews() override;
SimpleDialogFlags flags_;
};
enum class TwoPaneFlags {
+1 -1
View File
@@ -422,7 +422,7 @@ void ProductView::OnLaunchClick(UI::EventParams &e) {
OnClickLaunch.Trigger(e2);
}
StoreScreen::StoreScreen() {
StoreScreen::StoreScreen() : UISimpleBaseDialogScreen(Path(), SimpleDialogFlags::Default) {
lang_ = g_Config.sLanguageIni;
loading_ = true;
-1
View File
@@ -76,7 +76,6 @@ protected:
void OnGameLaunch(UI::EventParams &e);
std::string_view GetTitle() const override;
bool CanScroll() const override { return false; } // does its own scrolling
private:
void ParseListing(const std::string &json);
ProductItemView *GetSelectedItem();
+1 -1
View File
@@ -676,7 +676,7 @@ void TouchControlLayoutScreen::CreateViews() {
leftColumn->Add(new Spacer(0.0f));
LinearLayout* rightColumn = root_->Add(new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(1.0f, Margins(0.0f, 12.0f, 12.0f, 12.0f))));
rightColumn->Add(new TextView(co->T(DeviceOrientationToString(orientation))));
rightColumn->Add(new TextView(co->T(DeviceOrientationToString(orientation))))->SetTextSize(TextSize::Small);
rightColumn->Add(new Spacer(new LinearLayoutParams(1.0)));
float previewHeight = bounds.h * layoutAreaScale;
layoutView_ = rightColumn->Add(new ControlLayoutView(GetDeviceOrientation(), new LinearLayoutParams(FILL_PARENT, previewHeight)));
+33 -46
View File
@@ -46,15 +46,27 @@ private:
UI::CheckBox *checkbox_;
};
void TouchControlVisibilityScreen::CreateTabs() {
std::string_view TouchControlVisibilityScreen::GetTitle() const {
auto co = GetI18NCategory(I18NCat::CONTROLS);
return co->T("Touch Control Visibility");
}
AddTab("Visibility", co->T("Visibility"), [this](UI::LinearLayout *contents) {
CreateVisibilityTab(contents);
void TouchControlVisibilityScreen::CreateSettingsViews(UI::ViewGroup *parent) {
using namespace UI;
auto di = GetI18NCategory(I18NCat::DIALOG);
Choice *toggleAll = parent->Add(new Choice(di->T("Toggle All")));
toggleAll->OnClick.Add([this](UI::EventParams &e) {
// TODO: Is this a meaningful operation to support?
for (auto toggle : toggles_) {
*toggle.show = nextToggleAll_;
}
nextToggleAll_ = !nextToggleAll_;
});
}
void TouchControlVisibilityScreen::CreateVisibilityTab(UI::LinearLayout *vert) {
void TouchControlVisibilityScreen::CreateContentViews(UI::ViewGroup *parent) {
using namespace UI;
using namespace CustomKeyData;
@@ -63,25 +75,10 @@ void TouchControlVisibilityScreen::CreateVisibilityTab(UI::LinearLayout *vert) {
const bool portrait = GetDeviceOrientation() == DeviceOrientation::Portrait;
Choice *toggleAll = new Choice(di->T("Toggle All"), "", false, new AnchorLayoutParams(leftColumnWidth - 10, WRAP_CONTENT, 10, NONE, NONE, 84));
vert->SetSpacing(0);
vert->Add(toggleAll)->OnClick.Add([this](UI::EventParams &e) {
// TODO: Is this a meaningful operation to support?
for (auto toggle : toggles_) {
*toggle.show = nextToggleAll_;
}
nextToggleAll_ = !nextToggleAll_;
});
vert->Add(new ItemHeader(co->T("Touch Control Visibility")));
const int cellSize = portrait ? std::min((g_display.dp_xres / 2 - 10), 290) : 380;
UI::GridLayoutSettings gridsettings(cellSize, 64, 5);
gridsettings.fillCells = true;
GridLayout *grid = vert->Add(new GridLayoutList(gridsettings, new LayoutParams(FILL_PARENT, WRAP_CONTENT)));
GridLayout *grid = parent->Add(new GridLayoutList(gridsettings, new LayoutParams(FILL_PARENT, WRAP_CONTENT)));
TouchControlConfig &touch = g_Config.GetTouchControlsConfig(GetDeviceOrientation());
@@ -152,7 +149,12 @@ void TouchControlVisibilityScreen::onFinish(DialogResult result) {
g_Config.Save("TouchControlVisibilityScreen::onFinish");
}
void RightAnalogMappingScreen::CreateViews() {
std::string_view RightAnalogMappingScreen::GetTitle() const {
auto mc = GetI18NCategory(I18NCat::MAPPABLECONTROLS);
return mc->T("Right Analog Stick");
}
void RightAnalogMappingScreen::CreateDialogViews(UI::ViewGroup *parent) {
using namespace UI;
auto di = GetI18NCategory(I18NCat::DIALOG);
@@ -161,34 +163,19 @@ void RightAnalogMappingScreen::CreateViews() {
TouchControlConfig &touch = g_Config.GetTouchControlsConfig(GetDeviceOrientation());
root_ = new AnchorLayout(new LayoutParams(FILL_PARENT, FILL_PARENT));
Choice *back = new Choice(di->T("Back"), ImageID("I_NAVIGATE_BACK"), new AnchorLayoutParams(leftColumnWidth - 10, WRAP_CONTENT, 10, NONE, NONE, 10));
root_->Add(back)->OnClick.Handle<UIScreen>(this, &UIScreen::OnBack);
TabHolder *tabHolder = new TabHolder(ORIENT_VERTICAL, leftColumnWidth, TabHolderFlags::Default, nullptr, nullptr, new AnchorLayoutParams(10, 0, 10, 0, Centering::None));
root_->Add(tabHolder);
ScrollView *rightPanel = new ScrollView(ORIENT_VERTICAL);
tabHolder->AddTab(co->T("Binds"), ImageID::invalid(), rightPanel);
LinearLayout *vert = rightPanel->Add(new LinearLayout(ORIENT_VERTICAL, new LayoutParams(FILL_PARENT, FILL_PARENT)));
vert->SetSpacing(0);
static const char *rightAnalogButton[] = {"None", "L", "R", "Square", "Triangle", "Circle", "Cross", "D-pad up", "D-pad down", "D-pad left", "D-pad right", "Start", "Select", "RightAn.Up", "RightAn.Down", "RightAn.Left", "RightAn.Right", "An.Up", "An.Down", "An.Left", "An.Right"};
vert->Add(new ItemHeader(co->T("Analog Style")));
vert->Add(new CheckBox(&touch.touchRightAnalogStick.show, co->T("Visible")));
vert->Add(new CheckBox(&g_Config.bRightAnalogCustom, co->T("Use custom right analog")));
vert->Add(new CheckBox(&g_Config.bRightAnalogDisableDiagonal, co->T("Disable diagonal input")))->SetEnabledPtr(&g_Config.bRightAnalogCustom);
parent->Add(new ItemHeader(co->T("Analog Style")));
parent->Add(new CheckBox(&touch.touchRightAnalogStick.show, co->T("Visible")));
parent->Add(new CheckBox(&g_Config.bRightAnalogCustom, co->T("Use custom right analog")));
parent->Add(new CheckBox(&g_Config.bRightAnalogDisableDiagonal, co->T("Disable diagonal input")))->SetEnabledPtr(&g_Config.bRightAnalogCustom);
vert->Add(new ItemHeader(co->T("Analog Binding")));
PopupMultiChoice *rightAnalogUp = vert->Add(new PopupMultiChoice(&g_Config.iRightAnalogUp, mc->T("RightAn.Up"), rightAnalogButton, 0, ARRAY_SIZE(rightAnalogButton), I18NCat::MAPPABLECONTROLS, screenManager()));
PopupMultiChoice *rightAnalogDown = vert->Add(new PopupMultiChoice(&g_Config.iRightAnalogDown, mc->T("RightAn.Down"), rightAnalogButton, 0, ARRAY_SIZE(rightAnalogButton), I18NCat::MAPPABLECONTROLS, screenManager()));
PopupMultiChoice *rightAnalogLeft = vert->Add(new PopupMultiChoice(&g_Config.iRightAnalogLeft, mc->T("RightAn.Left"), rightAnalogButton, 0, ARRAY_SIZE(rightAnalogButton), I18NCat::MAPPABLECONTROLS, screenManager()));
PopupMultiChoice *rightAnalogRight = vert->Add(new PopupMultiChoice(&g_Config.iRightAnalogRight, mc->T("RightAn.Right"), rightAnalogButton, 0, ARRAY_SIZE(rightAnalogButton), I18NCat::MAPPABLECONTROLS, screenManager()));
PopupMultiChoice *rightAnalogPress = vert->Add(new PopupMultiChoice(&g_Config.iRightAnalogPress, co->T("Keep this button pressed when right analog is pressed"), rightAnalogButton, 0, ARRAY_SIZE(rightAnalogButton) - 8, I18NCat::MAPPABLECONTROLS, screenManager()));
rightAnalogUp->SetEnabledPtr(&g_Config.bRightAnalogCustom);
rightAnalogDown->SetEnabledPtr(&g_Config.bRightAnalogCustom);
rightAnalogLeft->SetEnabledPtr(&g_Config.bRightAnalogCustom);
rightAnalogRight->SetEnabledPtr(&g_Config.bRightAnalogCustom);
rightAnalogPress->SetEnabledPtr(&g_Config.bRightAnalogCustom);
parent->Add(new ItemHeader(co->T("Analog Binding")));
parent->Add(new PopupMultiChoice(&g_Config.iRightAnalogUp, mc->T("RightAn.Up"), rightAnalogButton, 0, ARRAY_SIZE(rightAnalogButton), I18NCat::MAPPABLECONTROLS, screenManager()))->SetEnabledPtr(&g_Config.bRightAnalogCustom);
parent->Add(new PopupMultiChoice(&g_Config.iRightAnalogDown, mc->T("RightAn.Down"), rightAnalogButton, 0, ARRAY_SIZE(rightAnalogButton), I18NCat::MAPPABLECONTROLS, screenManager()))->SetEnabledPtr(&g_Config.bRightAnalogCustom);
parent->Add(new PopupMultiChoice(&g_Config.iRightAnalogLeft, mc->T("RightAn.Left"), rightAnalogButton, 0, ARRAY_SIZE(rightAnalogButton), I18NCat::MAPPABLECONTROLS, screenManager()))->SetEnabledPtr(&g_Config.bRightAnalogCustom);
parent->Add(new PopupMultiChoice(&g_Config.iRightAnalogRight, mc->T("RightAn.Right"), rightAnalogButton, 0, ARRAY_SIZE(rightAnalogButton), I18NCat::MAPPABLECONTROLS, screenManager()))->SetEnabledPtr(&g_Config.bRightAnalogCustom);
parent->Add(new PopupMultiChoice(&g_Config.iRightAnalogPress, co->T("Keep this button pressed when right analog is pressed"), rightAnalogButton, 0, ARRAY_SIZE(rightAnalogButton) - 8, I18NCat::MAPPABLECONTROLS, screenManager()))->SetEnabledPtr(&g_Config.bRightAnalogCustom);
}
void CheckBoxChoice::HandleClick(UI::EventParams &e) {
+10 -11
View File
@@ -21,7 +21,7 @@
#include <string>
#include "Common/Render/TextureAtlas.h"
#include "UI/BaseScreens.h"
#include "UI/TabbedDialogScreen.h"
#include "UI/SimpleDialogScreen.h"
namespace UI {
class CheckBox;
@@ -34,27 +34,26 @@ struct TouchButtonToggle {
std::function<void(UI::EventParams&)> handle;
};
class TouchControlVisibilityScreen : public UITabbedBaseDialogScreen {
class TouchControlVisibilityScreen : public UITwoPaneBaseDialogScreen {
public:
TouchControlVisibilityScreen(const Path &gamePath) : UITabbedBaseDialogScreen(gamePath) {}
void CreateTabs() override;
TouchControlVisibilityScreen(const Path &gamePath) : UITwoPaneBaseDialogScreen(gamePath, TwoPaneFlags::SettingsInContextMenu | TwoPaneFlags::ContentsCanScroll) {}
void CreateContentViews(UI::ViewGroup *parent) override;
void CreateSettingsViews(UI::ViewGroup *parent) override;
void onFinish(DialogResult result) override;
const char *tag() const override { return "TouchControlVisibility"; }
protected:
bool ShowSearchControls() const override { return false; }
void CreateVisibilityTab(UI::LinearLayout *contents);
std::string_view GetTitle() const override;
private:
std::vector<TouchButtonToggle> toggles_;
bool nextToggleAll_ = true;
};
class RightAnalogMappingScreen : public UIBaseDialogScreen {
class RightAnalogMappingScreen : public UISimpleBaseDialogScreen {
public:
RightAnalogMappingScreen(const Path &gamePath) : UIBaseDialogScreen(gamePath) {}
void CreateViews() override;
RightAnalogMappingScreen(const Path &gamePath) : UISimpleBaseDialogScreen(gamePath, SimpleDialogFlags::ContentsCanScroll) {}
void CreateDialogViews(UI::ViewGroup *parent) override;
std::string_view GetTitle() const override;
const char *tag() const override { return "RightAnalogMapping"; }
};
+1 -1
View File
@@ -9,7 +9,7 @@
#include "UI/UploadScreen.h"
#include "UI/MiscViews.h"
UploadScreen::UploadScreen(const Path &targetFolder) : targetFolder_(targetFolder) {
UploadScreen::UploadScreen(const Path &targetFolder) : UISimpleBaseDialogScreen(Path(), SimpleDialogFlags::Default), targetFolder_(targetFolder) {
std::vector<std::string> ips;
net::GetLocalIP4List(ips);
localIPs_.clear();