Skip to content

Commit 464075f

Browse files
authored
Merge pull request hrydgard#21044 from hrydgard/rotation-lock-ui
Add convenient UI on the pause screen for changing/locking the screen orientation
2 parents 10ec268 + ed25b5e commit 464075f

21 files changed

+247
-87
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ imgui.ini
106106

107107
# debug file
108108
ui_atlas_gen.png
109+
buttons_rasterized.png
109110

110111
# For vim
111112
*.swp

Common/UI/PopupScreens.cpp

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,20 @@ std::string ChopTitle(const std::string &title) {
309309
return title;
310310
}
311311

312+
PopupMultiChoice::PopupMultiChoice(int *value, std::string_view text, const char **choices, int minVal, int numChoices,
313+
I18NCat category, ScreenManager *screenManager, UI::LayoutParams *layoutParams)
314+
: AbstractChoiceWithValueDisplay(text, layoutParams), value_(value), choices_(choices), minVal_(minVal), numChoices_(numChoices), category_(category), screenManager_(screenManager) {
315+
if (choices) {
316+
// If choices is nullptr, we're being called from PopupMultiChoiceDynamic where value doesn't yet point to anything valid.
317+
if (*value >= numChoices + minVal)
318+
*value = numChoices + minVal - 1;
319+
if (*value < minVal)
320+
*value = minVal;
321+
UpdateText();
322+
}
323+
OnClick.Handle(this, &PopupMultiChoice::HandleClick);
324+
}
325+
312326
void PopupMultiChoice::HandleClick(UI::EventParams &e) {
313327
if (!callbackExecuted_ && preOpenCallback_) {
314328
preOpenCallback_(this);
@@ -324,8 +338,7 @@ void PopupMultiChoice::HandleClick(UI::EventParams &e) {
324338
choices.push_back(category ? std::string(category->T(choices_[i])) : std::string(choices_[i]));
325339
}
326340

327-
ListPopupScreen *popupScreen = new ListPopupScreen(ChopTitle(text_), choices, *value_ - minVal_,
328-
std::bind(&PopupMultiChoice::ChoiceCallback, this, std::placeholders::_1));
341+
ListPopupScreen *popupScreen = new ListPopupScreen(ChopTitle(text_), choices, *value_ - minVal_, [this](int num) {ChoiceCallback(num);});
329342
popupScreen->SetHiddenChoices(hidden_);
330343
popupScreen->SetChoiceIcons(icons_);
331344
if (e.v)
@@ -870,6 +883,13 @@ void AbstractChoiceWithValueDisplay::Draw(UIContext &dc) {
870883
dc.SetFontScale(1.0f, 1.0f);
871884
} else {
872885
Choice::Draw(dc);
886+
887+
if (text_.empty() && !image_.isValid()) {
888+
// In this case we only display the image of the choice. Useful for small buttons spawning a popup.
889+
dc.Draw()->DrawImageRotated(ValueImage(), bounds_.centerX(), bounds_.centerY(), imgScale_, imgRot_, style.fgColor, imgFlipH_);
890+
return;
891+
}
892+
873893
float scale = CalculateValueScale(dc, valueText, bounds_.w);
874894
dc.SetFontScale(scale, scale);
875895
dc.DrawTextRect(valueText, bounds_.Expand(-paddingX, 0.0f), style.fgColor, ALIGN_LEFT | ALIGN_VCENTER | FLAG_WRAP_TEXT);

Common/UI/PopupScreens.h

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -282,40 +282,38 @@ class PopupCallbackScreen : public AbstractContextMenuScreen {
282282
class PopupMultiChoice : public AbstractChoiceWithValueDisplay {
283283
public:
284284
PopupMultiChoice(int *value, std::string_view text, const char **choices, int minVal, int numChoices,
285-
I18NCat category, ScreenManager *screenManager, UI::LayoutParams *layoutParams = nullptr)
286-
: AbstractChoiceWithValueDisplay(text, layoutParams), value_(value), choices_(choices), minVal_(minVal), numChoices_(numChoices),
287-
category_(category), screenManager_(screenManager) {
288-
if (choices) {
289-
// If choices is nullptr, we're being called from PopupMultiChoiceDynamic where value doesn't yet point to anything valid.
290-
if (*value >= numChoices + minVal)
291-
*value = numChoices + minVal - 1;
292-
if (*value < minVal)
293-
*value = minVal;
294-
UpdateText();
295-
}
296-
OnClick.Handle(this, &PopupMultiChoice::HandleClick);
297-
}
285+
I18NCat category, ScreenManager *screenManager, UI::LayoutParams *layoutParams = nullptr);
298286

299287
void Update() override;
300288

301289
void HideChoice(int c) {
302290
hidden_.insert(c);
303291
}
304-
void SetChoiceIcon(int c, ImageID id) {
305-
icons_[c] = id;
306-
}
307292
bool IsChoiceHidden(int c) const {
308293
return hidden_.find(c) != hidden_.end();
309294
}
310295

311296
void SetPreOpenCallback(std::function<void(PopupMultiChoice *)> callback) {
312297
preOpenCallback_ = callback;
313298
}
299+
void SetChoiceIcon(int c, ImageID id) {
300+
icons_[c] = id;
301+
}
302+
void SetChoiceIcons(std::map<int, ImageID> icons) {
303+
icons_ = icons;
304+
}
314305

315306
UI::Event OnChoice;
316307

317308
protected:
318309
std::string ValueText() const override;
310+
ImageID ValueImage() const override {
311+
auto iter = icons_.find(*value_);
312+
if (iter != icons_.end()) {
313+
return iter->second;
314+
}
315+
return ImageID::invalid();
316+
}
319317

320318
int *value_;
321319
const char **choices_;
@@ -346,8 +344,7 @@ class PopupMultiChoiceDynamic : public PopupMultiChoice {
346344
// TODO: This all is absolutely terrible, just done this way to be conformant with the internals of PopupMultiChoice.
347345
PopupMultiChoiceDynamic(std::string *value, std::string_view text, const std::vector<std::string> &choices,
348346
I18NCat category, ScreenManager *screenManager, std::vector<std::string> *values = nullptr, UI::LayoutParams *layoutParams = nullptr)
349-
: UI::PopupMultiChoice(&valueInt_, text, nullptr, 0, (int)choices.size(), category, screenManager, layoutParams),
350-
valueStr_(value) {
347+
: UI::PopupMultiChoice(&valueInt_, text, nullptr, 0, (int)choices.size(), category, screenManager, layoutParams), valueStr_(value) {
351348
if (values) {
352349
_dbg_assert_(choices.size() == values->size());
353350
}

Common/UI/ScrollView.cpp

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -574,7 +574,9 @@ void ListView::CreateAllItems() {
574574
imageID = &iter->second;
575575
}
576576
View *v = linLayout_->Add(adaptor_->CreateItemView(i, imageID));
577-
adaptor_->AddEventCallback(v, std::bind(&ListView::OnItemCallback, this, i, std::placeholders::_1));
577+
adaptor_->AddEventCallback(v, [this, i](UI::EventParams &e) {
578+
OnItemCallback(i, e);
579+
});
578580
}
579581
}
580582
}
@@ -601,9 +603,12 @@ void ListView::OnItemCallback(int num, EventParams &e) {
601603
}
602604

603605
View *ChoiceListAdaptor::CreateItemView(int index, ImageID *optionalImageID) {
604-
Choice *choice = new Choice(items_[index]);
606+
Choice *choice;
605607
if (optionalImageID) {
606-
choice->SetIcon(*optionalImageID);
608+
choice = new Choice(items_[index], *optionalImageID);
609+
} else {
610+
choice = new Choice(items_[index]);
611+
//choice->SetIconRight(*optionalImageID);
607612
}
608613
return choice;
609614
}
@@ -614,10 +619,14 @@ void ChoiceListAdaptor::AddEventCallback(View *view, std::function<void(EventPar
614619
}
615620

616621
View *StringVectorListAdaptor::CreateItemView(int index, ImageID *optionalImageID) {
617-
Choice *choice = new Choice(items_[index], "", index == selected_);
622+
ImageID temp;
618623
if (optionalImageID) {
619-
choice->SetIcon(*optionalImageID);
624+
temp = *optionalImageID;
620625
}
626+
Choice *choice = new Choice(items_[index], temp);
627+
// if (optionalImageID) {
628+
// choice->SetIconRight(*optionalImageID);
629+
// }
621630
return choice;
622631
}
623632

Common/UI/View.h

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -706,10 +706,10 @@ class ClickableItem : public Clickable {
706706
class Choice : public ClickableItem {
707707
public:
708708
Choice(std::string_view text, LayoutParams *layoutParams = nullptr)
709-
: Choice(text, "", false, layoutParams) { }
709+
: ClickableItem(layoutParams), text_(text) { }
710710
Choice(std::string_view text, ImageID image, LayoutParams *layoutParams = nullptr)
711711
: ClickableItem(layoutParams), text_(text), image_(image) {}
712-
Choice(std::string_view text, std::string_view smallText, bool selected = false, LayoutParams *layoutParams = nullptr)
712+
Choice(std::string_view text, std::string_view smallText, LayoutParams *layoutParams = nullptr)
713713
: ClickableItem(layoutParams), text_(text), smallText_(smallText), image_(ImageID::invalid()) {}
714714
Choice(ImageID image, LayoutParams *layoutParams = nullptr)
715715
: ClickableItem(layoutParams), image_(image), rightIconImage_(ImageID::invalid()) {}
@@ -725,7 +725,10 @@ class Choice : public ClickableItem {
725725
void SetDrawTextFlags(u32 flags) {
726726
drawTextFlags_ = flags;
727727
}
728-
void SetIcon(ImageID iconImage, float scale = 1.0f, float rot = 0.0f, bool flipH = false, bool keepColor = true) {
728+
void SetIconLeft(ImageID iconImage) {
729+
image_ = iconImage;
730+
}
731+
void SetIconRight(ImageID iconImage, float scale = 1.0f, float rot = 0.0f, bool flipH = false, bool keepColor = true) {
729732
rightIconKeepColor_ = keepColor;
730733
rightIconScale_ = scale;
731734
rightIconRot_ = rot;
@@ -776,7 +779,7 @@ class Choice : public ClickableItem {
776779
class StickyChoice : public Choice {
777780
public:
778781
StickyChoice(std::string_view text, std::string_view smallText = "", LayoutParams *layoutParams = nullptr)
779-
: Choice(text, smallText, false, layoutParams) {}
782+
: Choice(text, smallText, layoutParams) {}
780783
StickyChoice(ImageID buttonImage, LayoutParams *layoutParams = nullptr)
781784
: Choice(buttonImage, layoutParams) {}
782785
StickyChoice(std::string_view text, ImageID image, LayoutParams *layoutParams = nullptr)
@@ -835,8 +838,10 @@ class AbstractChoiceWithValueDisplay : public Choice {
835838
void SetPasswordDisplay() {
836839
passwordMasking_ = true;
837840
}
841+
838842
protected:
839843
virtual std::string ValueText() const = 0;
844+
virtual ImageID ValueImage() const { return ImageID::invalid(); }
840845

841846
float CalculateValueScale(const UIContext &dc, std::string_view valueText, float availWidth) const;
842847

Core/Config.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1511,6 +1511,13 @@ void Config::PostLoadCleanup() {
15111511
if (g_Config.sCustomDriver == "Default") {
15121512
g_Config.sCustomDriver = "";
15131513
}
1514+
1515+
// Squash unsupported screen rotations.
1516+
if (g_Config.iScreenRotation == ROTATION_AUTO_HORIZONTAL) {
1517+
g_Config.iScreenRotation = ROTATION_LOCKED_HORIZONTAL;
1518+
} else if (g_Config.iScreenRotation == ROTATION_LOCKED_VERTICAL180) {
1519+
g_Config.iScreenRotation = ROTATION_LOCKED_VERTICAL;
1520+
}
15141521
}
15151522

15161523
void Config::PreSaveCleanup() {

Core/ConfigValues.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,8 @@ enum {
8484
ROTATION_LOCKED_HORIZONTAL = 1,
8585
ROTATION_LOCKED_VERTICAL = 2,
8686
ROTATION_LOCKED_HORIZONTAL180 = 3,
87-
ROTATION_LOCKED_VERTICAL180 = 4,
88-
ROTATION_AUTO_HORIZONTAL = 5,
87+
ROTATION_LOCKED_VERTICAL180 = 4, // Deprecated
88+
ROTATION_AUTO_HORIZONTAL = 5, // Deprecated
8989
};
9090

9191
enum TextureFiltering {

UI/CustomButtonMappingScreen.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ void CustomButtonMappingScreen::CreateDialogViews(UI::ViewGroup *parent) {
158158
vertLayout->Add(new CheckBox(show, co->T("Visible")));
159159

160160
Choice *icon = vertLayout->Add(new Choice(co->T("Icon")));
161-
icon->SetIcon(ImageID(customKeyImages[cfg->image].i), 1.0f, customKeyImages[cfg->image].r*PI/180, false, false); // Set right icon on the choice
161+
icon->SetIconRight(ImageID(customKeyImages[cfg->image].i), 1.0f, customKeyImages[cfg->image].r*PI/180, false, false); // Set right icon on the choice
162162
icon->OnClick.Add([=](UI::EventParams &e) {
163163
auto iconScreen = new ButtonIconScreen(co->T("Icon"), &(cfg->image));
164164
if (e.v)
@@ -168,7 +168,7 @@ void CustomButtonMappingScreen::CreateDialogViews(UI::ViewGroup *parent) {
168168
});
169169

170170
Choice *shape = vertLayout->Add(new Choice(co->T("Shape")));
171-
shape->SetIcon(ImageID(customKeyShapes[cfg->shape].l), 0.6f, customKeyShapes[cfg->shape].r*PI/180, customKeyShapes[cfg->shape].f, false); // Set right icon on the choice
171+
shape->SetIconRight(ImageID(customKeyShapes[cfg->shape].l), 0.6f, customKeyShapes[cfg->shape].r*PI/180, customKeyShapes[cfg->shape].f, false); // Set right icon on the choice
172172
shape->OnClick.Add([=](UI::EventParams &e) {
173173
auto shape = new ButtonShapeScreen(co->T("Shape"), &(cfg->shape));
174174
if (e.v)

UI/GameSettingsScreen.cpp

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,7 @@ void GameSettingsScreen::CreateGraphicsSettings(UI::ViewGroup *graphicsSettings)
376376
return !g_Config.bSoftwareRendering && !g_Config.bSkipBufferEffects;
377377
});
378378
if (g_Config.iMultiSampleLevel > 1 && draw->GetDeviceCaps().isTilingGPU) {
379-
msaaChoice->SetIcon(ImageID("I_WARNING"), 0.7f);
379+
msaaChoice->SetIconRight(ImageID("I_WARNING"), 0.7f);
380380
}
381381
msaaChoice->SetEnabledFunc([] {
382382
return !g_Config.bSoftwareRendering && !g_Config.bSkipBufferEffects;
@@ -1115,7 +1115,7 @@ void GameSettingsScreen::CreateToolsSettings(UI::ViewGroup *tools) {
11151115
retro->OnClick.Add([=](UI::EventParams &) -> void {
11161116
screenManager()->push(new RetroAchievementsSettingsScreen(gamePath_));
11171117
});
1118-
retro->SetIcon(ImageID("I_RETROACHIEVEMENTS_LOGO"));
1118+
retro->SetIconRight(ImageID("I_RETROACHIEVEMENTS_LOGO"));
11191119
}
11201120

11211121
// These were moved here so use the wrong translation objects, to avoid having to change all inis... This isn't a sustainable situation :P
@@ -1358,15 +1358,7 @@ void GameSettingsScreen::CreateSystemSettings(UI::ViewGroup *systemSettings) {
13581358
if (System_GetPropertyInt(SYSPROP_DEVICE_TYPE) == DEVICE_TYPE_MOBILE) {
13591359
auto co = GetI18NCategory(I18NCat::CONTROLS);
13601360

1361-
static const char *screenRotation[] = { "Auto", "Landscape", "Portrait", "Landscape Reversed", "Portrait Reversed", "Landscape Auto" };
1362-
PopupMultiChoice *rot = systemSettings->Add(new PopupMultiChoice(&g_Config.iScreenRotation, co->T("Screen Rotation"), screenRotation, 0, ARRAY_SIZE(screenRotation), I18NCat::CONTROLS, screenManager()));
1363-
#if PPSSPP_PLATFORM(IOS)
1364-
// Portrait Reversed is not recommended on iPhone (and we also ban it in the plist).
1365-
// However it's recommended to support it on iPad, so maybe we will in the future.
1366-
rot->HideChoice(4);
1367-
#endif
1368-
1369-
rot->OnChoice.Handle(this, &GameSettingsScreen::OnScreenRotation);
1361+
AddRotationPicker(screenManager(), systemSettings, true);
13701362

13711363
if (System_GetPropertyBool(SYSPROP_SUPPORTS_SUSTAINED_PERF_MODE)) {
13721364
systemSettings->Add(new CheckBox(&g_Config.bSustainedPerformanceMode, sy->T("Sustained performance mode")))->OnClick.Handle(this, &GameSettingsScreen::OnSustainedPerformanceModeChange);
@@ -1467,13 +1459,6 @@ void GameSettingsScreen::OnAutoFrameskip(UI::EventParams &e) {
14671459
g_Config.UpdateAfterSettingAutoFrameSkip();
14681460
}
14691461

1470-
void GameSettingsScreen::OnScreenRotation(UI::EventParams &e) {
1471-
INFO_LOG(Log::System, "New display rotation: %d", g_Config.iScreenRotation);
1472-
INFO_LOG(Log::System, "Sending rotate");
1473-
System_Notify(SystemNotification::ROTATE_UPDATED);
1474-
INFO_LOG(Log::System, "Got back from rotate");
1475-
}
1476-
14771462
void GameSettingsScreen::OnAdhocGuides(UI::EventParams &e) {
14781463
auto n = GetI18NCategory(I18NCat::NETWORKING);
14791464
std::string url(n->T("MultiplayerHowToURL", "https://github.com/hrydgard/ppsspp/wiki/How-to-play-multiplayer-games-with-PPSSPP"));

UI/GameSettingsScreen.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,6 @@ class GameSettingsScreen : public UITabbedBaseDialogScreen {
100100
void OnMemoryStickMyDoc(UI::EventParams &e);
101101
void OnMemoryStickOther(UI::EventParams &e);
102102
#endif
103-
void OnScreenRotation(UI::EventParams &e);
104103
void OnImmersiveModeChange(UI::EventParams &e);
105104
void OnSustainedPerformanceModeChange(UI::EventParams &e);
106105

0 commit comments

Comments
 (0)