From 064a09bda4de40c0bdc3e8b4ffd7e32245d7d6b7 Mon Sep 17 00:00:00 2001 From: Carl Kenner Date: Sat, 26 Sep 2015 22:43:16 +0930 Subject: [PATCH 1/2] Improve PopupSliderChoiceFloat to make it more usable for VR settings. It now has a text input box. +/- buttons are on the next line so you can cursor along slider. And the units are optionally displayed. # Conflicts: # UI/GameSettingsScreen.cpp --- UI/GameSettingsScreen.cpp | 12 +++---- UI/TiltAnalogSettingsScreen.cpp | 2 +- ext/native/ui/ui_screen.cpp | 61 ++++++++++++++++++++++++++++----- ext/native/ui/ui_screen.h | 14 +++++--- 4 files changed, 70 insertions(+), 19 deletions(-) diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index d057c336c310..3dbd0a8e765d 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -441,16 +441,16 @@ void GameSettingsScreen::CreateViews() { static const char *inverseDeadzoneModes[] = { "Off", "X", "Y", "X + Y" }; controlsSettings->Add(new ItemHeader(co->T("DInput Analog Settings", "DInput Analog Settings"))); - controlsSettings->Add(new PopupSliderChoiceFloat(&g_Config.fDInputAnalogDeadzone, 0.0f, 1.0f, co->T("Deadzone Radius"), screenManager())); + controlsSettings->Add(new PopupSliderChoiceFloat(&g_Config.fDInputAnalogDeadzone, 0.0f, 1.0f, co->T("Deadzone Radius"), 0.01f, screenManager())); controlsSettings->Add(new PopupMultiChoice(&g_Config.iDInputAnalogInverseMode, co->T("Analog Mapper Mode"), inverseDeadzoneModes, 0, ARRAY_SIZE(inverseDeadzoneModes), co->GetName(), screenManager())); - controlsSettings->Add(new PopupSliderChoiceFloat(&g_Config.fDInputAnalogInverseDeadzone, 0.0f, 1.0f, co->T("Analog Mapper Low End", "Analog Mapper Low End (Inverse Deadzone)"), screenManager())); - controlsSettings->Add(new PopupSliderChoiceFloat(&g_Config.fDInputAnalogSensitivity, 0.0f, 10.0f, co->T("Analog Mapper High End", "Analog Mapper High End (Axis Sensitivity)"), screenManager())); + controlsSettings->Add(new PopupSliderChoiceFloat(&g_Config.fDInputAnalogInverseDeadzone, 0.0f, 1.0f, co->T("Analog Mapper Low End", "Analog Mapper Low End (Inverse Deadzone)"), 0.01f, screenManager())); + controlsSettings->Add(new PopupSliderChoiceFloat(&g_Config.fDInputAnalogSensitivity, 0.0f, 10.0f, co->T("Analog Mapper High End", "Analog Mapper High End (Axis Sensitivity)"), 0.01f, screenManager())); controlsSettings->Add(new ItemHeader(co->T("XInput Analog Settings", "XInput Analog Settings"))); - controlsSettings->Add(new PopupSliderChoiceFloat(&g_Config.fXInputAnalogDeadzone, 0.0f, 1.0f, co->T("Deadzone Radius"), screenManager())); + controlsSettings->Add(new PopupSliderChoiceFloat(&g_Config.fXInputAnalogDeadzone, 0.0f, 1.0f, co->T("Deadzone Radius"), 0.01f, screenManager())); controlsSettings->Add(new PopupMultiChoice(&g_Config.iXInputAnalogInverseMode, co->T("Analog Mapper Mode"), inverseDeadzoneModes, 0, ARRAY_SIZE(inverseDeadzoneModes), co->GetName(), screenManager())); - controlsSettings->Add(new PopupSliderChoiceFloat(&g_Config.fXInputAnalogInverseDeadzone, 0.0f, 1.0f, co->T("Analog Mapper Low End", "Analog Mapper Low End (Inverse Deadzone)"), screenManager())); - controlsSettings->Add(new PopupSliderChoiceFloat(&g_Config.fXInputAnalogSensitivity, 0.0f, 10.0f, co->T("Analog Mapper High End", "Analog Mapper High End (Axis Sensitivity)"), screenManager())); + controlsSettings->Add(new PopupSliderChoiceFloat(&g_Config.fXInputAnalogInverseDeadzone, 0.0f, 1.0f, co->T("Analog Mapper Low End", "Analog Mapper Low End (Inverse Deadzone)"), 0.01f, screenManager())); + controlsSettings->Add(new PopupSliderChoiceFloat(&g_Config.fXInputAnalogSensitivity, 0.0f, 10.0f, co->T("Analog Mapper High End", "Analog Mapper High End (Axis Sensitivity)"), 0.01f, screenManager())); #endif controlsSettings->Add(new ItemHeader(co->T("Keyboard", "Keyboard Control Settings"))); diff --git a/UI/TiltAnalogSettingsScreen.cpp b/UI/TiltAnalogSettingsScreen.cpp index fc7ae6a8cc40..0cf3ac2825ff 100644 --- a/UI/TiltAnalogSettingsScreen.cpp +++ b/UI/TiltAnalogSettingsScreen.cpp @@ -39,7 +39,7 @@ void TiltAnalogSettingsScreen::CreateViews() { //TODO: allow values greater than 100? I'm not sure if that's needed. settings->Add(new PopupSliderChoice(&g_Config.iTiltSensitivityX, 0, 100, co->T("Tilt Sensitivity along X axis"), screenManager())); settings->Add(new PopupSliderChoice(&g_Config.iTiltSensitivityY, 0, 100, co->T("Tilt Sensitivity along Y axis"), screenManager())); - settings->Add(new PopupSliderChoiceFloat(&g_Config.fDeadzoneRadius, 0.0, 1.0, co->T("Deadzone Radius"), screenManager())); + settings->Add(new PopupSliderChoiceFloat(&g_Config.fDeadzoneRadius, 0.0, 1.0, co->T("Deadzone Radius"), 0.01f, screenManager())); settings->Add(new ItemHeader(co->T("Calibration"))); InfoItem *calibrationInfo = new InfoItem(co->T("To Calibrate", "To calibrate, keep device on a flat surface and press calibrate."), ""); diff --git a/ext/native/ui/ui_screen.cpp b/ext/native/ui/ui_screen.cpp index 052e4695b29b..ca79f42433f2 100644 --- a/ext/native/ui/ui_screen.cpp +++ b/ext/native/ui/ui_screen.cpp @@ -332,13 +332,13 @@ PopupSliderChoice::PopupSliderChoice(int *value, int minValue, int maxValue, con OnClick.Handle(this, &PopupSliderChoice::HandleClick); } -PopupSliderChoiceFloat::PopupSliderChoiceFloat(float *value, float minValue, float maxValue, const std::string &text, ScreenManager *screenManager, LayoutParams *layoutParams) - : Choice(text, "", false, layoutParams), value_(value), minValue_(minValue), maxValue_(maxValue), step_(1.0f), screenManager_(screenManager) { +PopupSliderChoiceFloat::PopupSliderChoiceFloat(float *value, float minValue, float maxValue, const std::string &text, ScreenManager *screenManager, const std::string &units, LayoutParams *layoutParams) + : Choice(text, "", false, layoutParams), value_(value), minValue_(minValue), maxValue_(maxValue), step_(1.0f), screenManager_(screenManager), units_(units) { OnClick.Handle(this, &PopupSliderChoiceFloat::HandleClick); } -PopupSliderChoiceFloat::PopupSliderChoiceFloat(float *value, float minValue, float maxValue, const std::string &text, float step, ScreenManager *screenManager, LayoutParams *layoutParams) - : Choice(text, "", false, layoutParams), value_(value), minValue_(minValue), maxValue_(maxValue), step_(step), screenManager_(screenManager) { +PopupSliderChoiceFloat::PopupSliderChoiceFloat(float *value, float minValue, float maxValue, const std::string &text, float step, ScreenManager *screenManager, const std::string &units, LayoutParams *layoutParams) + : Choice(text, "", false, layoutParams), value_(value), minValue_(minValue), maxValue_(maxValue), step_(step), screenManager_(screenManager), units_(units) { OnClick.Handle(this, &PopupSliderChoiceFloat::HandleClick); } @@ -376,7 +376,7 @@ void PopupSliderChoice::Draw(UIContext &dc) { EventReturn PopupSliderChoiceFloat::HandleClick(EventParams &e) { restoreFocus_ = HasFocus(); - SliderFloatPopupScreen *popupScreen = new SliderFloatPopupScreen(value_, minValue_, maxValue_, text_, step_); + SliderFloatPopupScreen *popupScreen = new SliderFloatPopupScreen(value_, minValue_, maxValue_, text_, step_, units_); popupScreen->OnChange.Handle(this, &PopupSliderChoiceFloat::HandleChange); screenManager_->push(popupScreen); return EVENT_DONE; @@ -431,24 +431,69 @@ void SliderPopupScreen::CreatePopupContents(UI::ViewGroup *parent) { void SliderFloatPopupScreen::CreatePopupContents(UI::ViewGroup *parent) { using namespace UI; sliderValue_ = *value_; - LinearLayout *lin = parent->Add(new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(UI::Margins(10, 5)))); - slider_ = new SliderFloat(&sliderValue_, minValue_, maxValue_, new LinearLayoutParams(1.0f)); - lin->Add(slider_); + LinearLayout *vert = parent->Add(new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(UI::Margins(10, 10)))); + slider_ = new SliderFloat(&sliderValue_, minValue_, maxValue_, new LinearLayoutParams(UI::Margins(10, 10))); + slider_->OnClick.Handle(this, &SliderFloatPopupScreen::OnSliderChange); + vert->Add(slider_); + LinearLayout *lin = vert->Add(new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(UI::Margins(10, 10)))); lin->Add(new Button(" - "))->OnClick.Handle(this, &SliderFloatPopupScreen::OnDecrease); lin->Add(new Button(" + "))->OnClick.Handle(this, &SliderFloatPopupScreen::OnIncrease); + char temp[64]; + sprintf(temp, "%0.3f", sliderValue_); + edit_ = new TextEdit(temp, "", new LinearLayoutParams(10.0f)); + edit_->SetMaxLen(16); + edit_->OnTextChange.Handle(this, &SliderFloatPopupScreen::OnTextChange); + changing_ = false; + lin->Add(edit_); + if (&units_) + lin->Add(new TextView(units_, new LinearLayoutParams(10.0f))); + // slider_ = parent->Add(new SliderFloat(&sliderValue_, minValue_, maxValue_, new LinearLayoutParams(UI::Margins(10, 5)))); UI::SetFocusedView(slider_); } EventReturn SliderFloatPopupScreen::OnDecrease(EventParams ¶ms) { + if (sliderValue_ > minValue_ && sliderValue_ < maxValue_) { + sliderValue_ = step_ * floor((sliderValue_ / step_) + 0.5f); + } sliderValue_ -= step_; slider_->Clamp(); + changing_ = true; + char temp[64]; + sprintf(temp, "%0.3f", sliderValue_); + edit_->SetText(temp); + changing_ = false; return EVENT_DONE; } EventReturn SliderFloatPopupScreen::OnIncrease(EventParams ¶ms) { + if (sliderValue_ > minValue_ && sliderValue_ < maxValue_) { + sliderValue_ = step_ * floor((sliderValue_ / step_) + 0.5f); + } sliderValue_ += step_; slider_->Clamp(); + changing_ = true; + char temp[64]; + sprintf(temp, "%0.3f", sliderValue_); + edit_->SetText(temp); + changing_ = false; + return EVENT_DONE; +} + +EventReturn SliderFloatPopupScreen::OnSliderChange(EventParams ¶ms) { + changing_ = true; + char temp[64]; + sprintf(temp, "%0.3f", sliderValue_); + edit_->SetText(temp); + changing_ = false; + return EVENT_DONE; +} + +EventReturn SliderFloatPopupScreen::OnTextChange(EventParams ¶ms) { + if (!changing_) { + sliderValue_ = atof(edit_->GetText().c_str()); + slider_->Clamp(); + } return EVENT_DONE; } diff --git a/ext/native/ui/ui_screen.h b/ext/native/ui/ui_screen.h index 3f5d35b2ebdc..312485bbf6af 100644 --- a/ext/native/ui/ui_screen.h +++ b/ext/native/ui/ui_screen.h @@ -151,8 +151,8 @@ class SliderPopupScreen : public PopupScreen { class SliderFloatPopupScreen : public PopupScreen { public: - SliderFloatPopupScreen(float *value, float minValue, float maxValue, const std::string &title, float step = 1.0f) - : PopupScreen(title, "OK", "Cancel"), value_(value), minValue_(minValue), maxValue_(maxValue), step_(step) {} + SliderFloatPopupScreen(float *value, float minValue, float maxValue, const std::string &title, float step = 1.0f, const std::string &units = "") + : PopupScreen(title, "OK", "Cancel"), value_(value), minValue_(minValue), maxValue_(maxValue), step_(step), units_(units) {} void CreatePopupContents(UI::ViewGroup *parent) override; Event OnChange; @@ -160,13 +160,18 @@ class SliderFloatPopupScreen : public PopupScreen { private: EventReturn OnIncrease(EventParams ¶ms); EventReturn OnDecrease(EventParams ¶ms); + EventReturn OnTextChange(EventParams ¶ms); + EventReturn OnSliderChange(EventParams ¶ms); virtual void OnCompleted(DialogResult result) override; UI::SliderFloat *slider_; + UI::TextEdit *edit_; + std::string units_; float sliderValue_; float *value_; float minValue_; float maxValue_; float step_; + bool changing_; }; class TextEditPopupScreen : public PopupScreen { @@ -245,8 +250,8 @@ class PopupSliderChoice : public Choice { class PopupSliderChoiceFloat : public Choice { public: - PopupSliderChoiceFloat(float *value, float minValue, float maxValue, const std::string &text, ScreenManager *screenManager, LayoutParams *layoutParams = 0); - PopupSliderChoiceFloat(float *value, float minValue, float maxValue, const std::string &text, float step, ScreenManager *screenManager, LayoutParams *layoutParams = 0); + PopupSliderChoiceFloat(float *value, float minValue, float maxValue, const std::string &text, ScreenManager *screenManager, const std::string &units = "", LayoutParams *layoutParams = 0); + PopupSliderChoiceFloat(float *value, float minValue, float maxValue, const std::string &text, float step, ScreenManager *screenManager, const std::string &units = "", LayoutParams *layoutParams = 0); virtual void Draw(UIContext &dc) override; @@ -259,6 +264,7 @@ class PopupSliderChoiceFloat : public Choice { float minValue_; float maxValue_; float step_; + std::string units_; ScreenManager *screenManager_; bool restoreFocus_; }; From bf84fda05807cf124ce5bfbd1b7e9aaa97b63e0b Mon Sep 17 00:00:00 2001 From: Carl Kenner Date: Fri, 6 Nov 2015 17:55:40 +1030 Subject: [PATCH 2/2] Improve pop-up UI for integer slider screens. Add a text entry box and units. # Conflicts: # UI/GameSettingsScreen.cpp --- UI/GameSettingsScreen.cpp | 28 +++++++-------- UI/TiltAnalogSettingsScreen.cpp | 6 ++-- ext/native/ui/ui_screen.cpp | 60 ++++++++++++++++++++++++++++----- ext/native/ui/ui_screen.h | 14 +++++--- 4 files changed, 79 insertions(+), 29 deletions(-) diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index 3dbd0a8e765d..104b6a82d57d 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -152,7 +152,7 @@ void GameSettingsScreen::CreateViews() { frameSkipAuto_->OnClick.Handle(this, &GameSettingsScreen::OnAutoFrameskip); graphicsSettings->Add(new CheckBox(&cap60FPS_, gr->T("Force max 60 FPS (helps GoW)"))); - graphicsSettings->Add(new PopupSliderChoice(&iAlternateSpeedPercent_, 0, 600, gr->T("Alternative Speed", "Alternative Speed (in %, 0 = unlimited)"), 5, screenManager())); + graphicsSettings->Add(new PopupSliderChoice(&iAlternateSpeedPercent_, 0, 600, gr->T("Alternative Speed", "Alternative Speed (in %, 0 = unlimited)"), 5, screenManager(), "%, 0=unlimited")); graphicsSettings->Add(new ItemHeader(gr->T("Features"))); I18NCategory *ps = GetI18NCategory("PostShaders"); @@ -289,11 +289,11 @@ void GameSettingsScreen::CreateViews() { graphicsSettings->Add(new ItemHeader(gr->T("Cardboard Settings", "Cardboard Settings"))); CheckBox *cardboardMode = graphicsSettings->Add(new CheckBox(&g_Config.bEnableCardboard, gr->T("Enable Cardboard", "Enable Cardboard"))); cardboardMode->SetDisabledPtr(&g_Config.bSoftwareRendering); - PopupSliderChoice * cardboardScreenSize = graphicsSettings->Add(new PopupSliderChoice(&g_Config.iCardboardScreenSize, 30, 100, gr->T("Cardboard Screen Size", "Screen Size (in % of the viewport)"), 1, screenManager())); + PopupSliderChoice * cardboardScreenSize = graphicsSettings->Add(new PopupSliderChoice(&g_Config.iCardboardScreenSize, 30, 100, gr->T("Cardboard Screen Size", "Screen Size (in % of the viewport)"), 1, screenManager(), "% of viewport")); cardboardScreenSize->SetDisabledPtr(&g_Config.bSoftwareRendering); - PopupSliderChoice *cardboardXShift = graphicsSettings->Add(new PopupSliderChoice(&g_Config.iCardboardXShift, -100, 100, gr->T("Cardboard Screen X Shift", "X Shift (in % of the void)"), 1, screenManager())); + PopupSliderChoice *cardboardXShift = graphicsSettings->Add(new PopupSliderChoice(&g_Config.iCardboardXShift, -100, 100, gr->T("Cardboard Screen X Shift", "X Shift (in % of the void)"), 1, screenManager(), "% of the void")); cardboardXShift->SetDisabledPtr(&g_Config.bSoftwareRendering); - PopupSliderChoice *cardboardYShift = graphicsSettings->Add(new PopupSliderChoice(&g_Config.iCardboardYShift, -100, 100, gr->T("Cardboard Screen Y Shift", "Y Shift (in % of the void)"), 1, screenManager())); + PopupSliderChoice *cardboardYShift = graphicsSettings->Add(new PopupSliderChoice(&g_Config.iCardboardYShift, -100, 100, gr->T("Cardboard Screen Y Shift", "Y Shift (in % of the void)"), 1, screenManager(), "% of the void")); cardboardYShift->SetDisabledPtr(&g_Config.bSoftwareRendering); #endif @@ -430,7 +430,7 @@ void GameSettingsScreen::CreateViews() { CheckBox *disableDiags = controlsSettings->Add(new CheckBox(&g_Config.bDisableDpadDiagonals, co->T("Disable D-Pad diagonals (4-way touch)"))); disableDiags->SetEnabledPtr(&g_Config.bShowTouchControls); - View *opacity = controlsSettings->Add(new PopupSliderChoice(&g_Config.iTouchButtonOpacity, 0, 100, co->T("Button Opacity"), screenManager())); + View *opacity = controlsSettings->Add(new PopupSliderChoice(&g_Config.iTouchButtonOpacity, 0, 100, co->T("Button Opacity"), screenManager(),"%")); opacity->SetEnabledPtr(&g_Config.bShowTouchControls); static const char *touchControlStyles[] = {"Classic", "Thin borders"}; View *style = controlsSettings->Add(new PopupMultiChoice(&g_Config.iTouchButtonStyle, co->T("Button style"), touchControlStyles, 0, ARRAY_SIZE(touchControlStyles), co->GetName(), screenManager())); @@ -441,23 +441,23 @@ void GameSettingsScreen::CreateViews() { static const char *inverseDeadzoneModes[] = { "Off", "X", "Y", "X + Y" }; controlsSettings->Add(new ItemHeader(co->T("DInput Analog Settings", "DInput Analog Settings"))); - controlsSettings->Add(new PopupSliderChoiceFloat(&g_Config.fDInputAnalogDeadzone, 0.0f, 1.0f, co->T("Deadzone Radius"), 0.01f, screenManager())); + controlsSettings->Add(new PopupSliderChoiceFloat(&g_Config.fDInputAnalogDeadzone, 0.0f, 1.0f, co->T("Deadzone Radius"), 0.01f, screenManager(), "/ 1.0")); controlsSettings->Add(new PopupMultiChoice(&g_Config.iDInputAnalogInverseMode, co->T("Analog Mapper Mode"), inverseDeadzoneModes, 0, ARRAY_SIZE(inverseDeadzoneModes), co->GetName(), screenManager())); - controlsSettings->Add(new PopupSliderChoiceFloat(&g_Config.fDInputAnalogInverseDeadzone, 0.0f, 1.0f, co->T("Analog Mapper Low End", "Analog Mapper Low End (Inverse Deadzone)"), 0.01f, screenManager())); - controlsSettings->Add(new PopupSliderChoiceFloat(&g_Config.fDInputAnalogSensitivity, 0.0f, 10.0f, co->T("Analog Mapper High End", "Analog Mapper High End (Axis Sensitivity)"), 0.01f, screenManager())); + controlsSettings->Add(new PopupSliderChoiceFloat(&g_Config.fDInputAnalogInverseDeadzone, 0.0f, 1.0f, co->T("Analog Mapper Low End", "Analog Mapper Low End (Inverse Deadzone)"), 0.01f, screenManager(), "/ 1.0")); + controlsSettings->Add(new PopupSliderChoiceFloat(&g_Config.fDInputAnalogSensitivity, 0.0f, 10.0f, co->T("Analog Mapper High End", "Analog Mapper High End (Axis Sensitivity)"), 0.01f, screenManager(), "x")); controlsSettings->Add(new ItemHeader(co->T("XInput Analog Settings", "XInput Analog Settings"))); - controlsSettings->Add(new PopupSliderChoiceFloat(&g_Config.fXInputAnalogDeadzone, 0.0f, 1.0f, co->T("Deadzone Radius"), 0.01f, screenManager())); + controlsSettings->Add(new PopupSliderChoiceFloat(&g_Config.fXInputAnalogDeadzone, 0.0f, 1.0f, co->T("Deadzone Radius"), 0.01f, screenManager(), "/ 1.0")); controlsSettings->Add(new PopupMultiChoice(&g_Config.iXInputAnalogInverseMode, co->T("Analog Mapper Mode"), inverseDeadzoneModes, 0, ARRAY_SIZE(inverseDeadzoneModes), co->GetName(), screenManager())); - controlsSettings->Add(new PopupSliderChoiceFloat(&g_Config.fXInputAnalogInverseDeadzone, 0.0f, 1.0f, co->T("Analog Mapper Low End", "Analog Mapper Low End (Inverse Deadzone)"), 0.01f, screenManager())); - controlsSettings->Add(new PopupSliderChoiceFloat(&g_Config.fXInputAnalogSensitivity, 0.0f, 10.0f, co->T("Analog Mapper High End", "Analog Mapper High End (Axis Sensitivity)"), 0.01f, screenManager())); + controlsSettings->Add(new PopupSliderChoiceFloat(&g_Config.fXInputAnalogInverseDeadzone, 0.0f, 1.0f, co->T("Analog Mapper Low End", "Analog Mapper Low End (Inverse Deadzone)"), 0.01f, screenManager(), "/ 1.0")); + controlsSettings->Add(new PopupSliderChoiceFloat(&g_Config.fXInputAnalogSensitivity, 0.0f, 10.0f, co->T("Analog Mapper High End", "Analog Mapper High End (Axis Sensitivity)"), 0.01f, screenManager(), "x")); #endif controlsSettings->Add(new ItemHeader(co->T("Keyboard", "Keyboard Control Settings"))); #if defined(USING_WIN_UI) controlsSettings->Add(new CheckBox(&g_Config.bIgnoreWindowsKey, co->T("Ignore Windows Key"))); #endif // #if defined(USING_WIN_UI) - controlsSettings->Add(new PopupSliderChoiceFloat(&g_Config.fAnalogLimiterDeadzone, 0.0f, 1.0f, co->T("Analog Limiter"), 0.10f, screenManager())); + controlsSettings->Add(new PopupSliderChoiceFloat(&g_Config.fAnalogLimiterDeadzone, 0.0f, 1.0f, co->T("Analog Limiter"), 0.10f, screenManager(), "/ 1.0")); ViewGroup *networkingSettingsScroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, FILL_PARENT)); LinearLayout *networkingSettings = new LinearLayout(ORIENT_VERTICAL); @@ -517,9 +517,9 @@ void GameSettingsScreen::CreateViews() { View *ioTimingMethod = systemSettings->Add(new PopupMultiChoice(&g_Config.iIOTimingMethod, sy->T("IO timing method"), ioTimingMethods, 0, ARRAY_SIZE(ioTimingMethods), sy->GetName(), screenManager())); ioTimingMethod->SetEnabledPtr(&g_Config.bSeparateIOThread); systemSettings->Add(new CheckBox(&g_Config.bForceLagSync, sy->T("Force real clock sync (slower, less lag)"))); - systemSettings->Add(new PopupSliderChoice(&g_Config.iLockedCPUSpeed, 0, 1000, sy->T("Change CPU Clock", "Change CPU Clock (0 = default) (unstable)"), screenManager())); + systemSettings->Add(new PopupSliderChoice(&g_Config.iLockedCPUSpeed, 0, 1000, sy->T("Change CPU Clock", "Change CPU Clock (0 = default) (unstable)"), screenManager(), "MHz, 0=default")); #ifndef MOBILE_DEVICE - systemSettings->Add(new PopupSliderChoice(&g_Config.iRewindFlipFrequency, 0, 1800, sy->T("Rewind Snapshot Frequency", "Rewind Snapshot Frequency (0 = off, mem hog)"), screenManager())); + systemSettings->Add(new PopupSliderChoice(&g_Config.iRewindFlipFrequency, 0, 1800, sy->T("Rewind Snapshot Frequency", "Rewind Snapshot Frequency (0 = off, mem hog)"), screenManager(), "frames, 0=off")); #endif systemSettings->Add(new ItemHeader(sy->T("General"))); diff --git a/UI/TiltAnalogSettingsScreen.cpp b/UI/TiltAnalogSettingsScreen.cpp index 0cf3ac2825ff..bbbee832ffd6 100644 --- a/UI/TiltAnalogSettingsScreen.cpp +++ b/UI/TiltAnalogSettingsScreen.cpp @@ -37,9 +37,9 @@ void TiltAnalogSettingsScreen::CreateViews() { settings->Add(new ItemHeader(co->T("Sensitivity"))); //TODO: allow values greater than 100? I'm not sure if that's needed. - settings->Add(new PopupSliderChoice(&g_Config.iTiltSensitivityX, 0, 100, co->T("Tilt Sensitivity along X axis"), screenManager())); - settings->Add(new PopupSliderChoice(&g_Config.iTiltSensitivityY, 0, 100, co->T("Tilt Sensitivity along Y axis"), screenManager())); - settings->Add(new PopupSliderChoiceFloat(&g_Config.fDeadzoneRadius, 0.0, 1.0, co->T("Deadzone Radius"), 0.01f, screenManager())); + settings->Add(new PopupSliderChoice(&g_Config.iTiltSensitivityX, 0, 100, co->T("Tilt Sensitivity along X axis"), screenManager(),"%")); + settings->Add(new PopupSliderChoice(&g_Config.iTiltSensitivityY, 0, 100, co->T("Tilt Sensitivity along Y axis"), screenManager(),"%")); + settings->Add(new PopupSliderChoiceFloat(&g_Config.fDeadzoneRadius, 0.0, 1.0, co->T("Deadzone Radius"), 0.01f, screenManager(),"/ 1.0")); settings->Add(new ItemHeader(co->T("Calibration"))); InfoItem *calibrationInfo = new InfoItem(co->T("To Calibrate", "To calibrate, keep device on a flat surface and press calibrate."), ""); diff --git a/ext/native/ui/ui_screen.cpp b/ext/native/ui/ui_screen.cpp index ca79f42433f2..0149371407d6 100644 --- a/ext/native/ui/ui_screen.cpp +++ b/ext/native/ui/ui_screen.cpp @@ -322,13 +322,13 @@ void PopupMultiChoice::Draw(UIContext &dc) { dc.DrawText(valueText_.c_str(), bounds_.x2() - paddingX, bounds_.centerY(), style.fgColor, ALIGN_RIGHT | ALIGN_VCENTER); } -PopupSliderChoice::PopupSliderChoice(int *value, int minValue, int maxValue, const std::string &text, ScreenManager *screenManager, LayoutParams *layoutParams) - : Choice(text, "", false, layoutParams), value_(value), minValue_(minValue), maxValue_(maxValue), step_(1), screenManager_(screenManager) { +PopupSliderChoice::PopupSliderChoice(int *value, int minValue, int maxValue, const std::string &text, ScreenManager *screenManager, const std::string &units, LayoutParams *layoutParams) + : Choice(text, "", false, layoutParams), value_(value), minValue_(minValue), maxValue_(maxValue), step_(1), screenManager_(screenManager), units_(units) { OnClick.Handle(this, &PopupSliderChoice::HandleClick); } -PopupSliderChoice::PopupSliderChoice(int *value, int minValue, int maxValue, const std::string &text, int step, ScreenManager *screenManager, LayoutParams *layoutParams) -: Choice(text, "", false, layoutParams), value_(value), minValue_(minValue), maxValue_(maxValue), step_(step), screenManager_(screenManager) { +PopupSliderChoice::PopupSliderChoice(int *value, int minValue, int maxValue, const std::string &text, int step, ScreenManager *screenManager, const std::string &units, LayoutParams *layoutParams) + : Choice(text, "", false, layoutParams), value_(value), minValue_(minValue), maxValue_(maxValue), step_(step), screenManager_(screenManager), units_(units) { OnClick.Handle(this, &PopupSliderChoice::HandleClick); } @@ -345,7 +345,7 @@ PopupSliderChoiceFloat::PopupSliderChoiceFloat(float *value, float minValue, flo EventReturn PopupSliderChoice::HandleClick(EventParams &e) { restoreFocus_ = HasFocus(); - SliderPopupScreen *popupScreen = new SliderPopupScreen(value_, minValue_, maxValue_, text_, step_); + SliderPopupScreen *popupScreen = new SliderPopupScreen(value_, minValue_, maxValue_, text_, step_, units_); popupScreen->OnChange.Handle(this, &PopupSliderChoice::HandleChange); screenManager_->push(popupScreen); return EVENT_DONE; @@ -405,25 +405,69 @@ void PopupSliderChoiceFloat::Draw(UIContext &dc) { } EventReturn SliderPopupScreen::OnDecrease(EventParams ¶ms) { + if (sliderValue_ > minValue_ && sliderValue_ < maxValue_) { + sliderValue_ = step_ * floor((sliderValue_ / step_) + 0.5f); + } sliderValue_ -= step_; slider_->Clamp(); + changing_ = true; + char temp[64]; + sprintf(temp, "%d", sliderValue_); + edit_->SetText(temp); + changing_ = false; return EVENT_DONE; } EventReturn SliderPopupScreen::OnIncrease(EventParams ¶ms) { + if (sliderValue_ > minValue_ && sliderValue_ < maxValue_) { + sliderValue_ = step_ * floor((sliderValue_ / step_) + 0.5f); + } sliderValue_ += step_; slider_->Clamp(); + changing_ = true; + char temp[64]; + sprintf(temp, "%d", sliderValue_); + edit_->SetText(temp); + changing_ = false; + return EVENT_DONE; +} + +EventReturn SliderPopupScreen::OnSliderChange(EventParams ¶ms) { + changing_ = true; + char temp[64]; + sprintf(temp, "%d", sliderValue_); + edit_->SetText(temp); + changing_ = false; + return EVENT_DONE; +} + +EventReturn SliderPopupScreen::OnTextChange(EventParams ¶ms) { + if (!changing_) { + sliderValue_ = atoi(edit_->GetText().c_str()); + slider_->Clamp(); + } return EVENT_DONE; } void SliderPopupScreen::CreatePopupContents(UI::ViewGroup *parent) { using namespace UI; sliderValue_ = *value_; - LinearLayout *lin = parent->Add(new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(UI::Margins(10, 5)))); - slider_ = new Slider(&sliderValue_, minValue_, maxValue_, step_, new LinearLayoutParams(1.0f)); - lin->Add(slider_); + LinearLayout *vert = parent->Add(new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(UI::Margins(10, 10)))); + slider_ = new Slider(&sliderValue_, minValue_, maxValue_, new LinearLayoutParams(UI::Margins(10, 10))); + slider_->OnClick.Handle(this, &SliderPopupScreen::OnSliderChange); + vert->Add(slider_); + LinearLayout *lin = vert->Add(new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(UI::Margins(10, 10)))); lin->Add(new Button(" - "))->OnClick.Handle(this, &SliderPopupScreen::OnDecrease); lin->Add(new Button(" + "))->OnClick.Handle(this, &SliderPopupScreen::OnIncrease); + char temp[64]; + sprintf(temp, "%d", sliderValue_); + edit_ = new TextEdit(temp, "", new LinearLayoutParams(10.0f)); + edit_->SetMaxLen(16); + edit_->OnTextChange.Handle(this, &SliderPopupScreen::OnTextChange); + changing_ = false; + lin->Add(edit_); + if (&units_) + lin->Add(new TextView(units_, new LinearLayoutParams(10.0f))); UI::SetFocusedView(slider_); } diff --git a/ext/native/ui/ui_screen.h b/ext/native/ui/ui_screen.h index 312485bbf6af..704ef77acd9a 100644 --- a/ext/native/ui/ui_screen.h +++ b/ext/native/ui/ui_screen.h @@ -131,8 +131,8 @@ namespace UI { class SliderPopupScreen : public PopupScreen { public: - SliderPopupScreen(int *value, int minValue, int maxValue, const std::string &title, int step = 1) - : PopupScreen(title, "OK", "Cancel"), value_(value), minValue_(minValue), maxValue_(maxValue), step_(step) {} + SliderPopupScreen(int *value, int minValue, int maxValue, const std::string &title, int step = 1, const std::string &units = "") + : PopupScreen(title, "OK", "Cancel"), value_(value), minValue_(minValue), maxValue_(maxValue), step_(step), units_(units) {} virtual void CreatePopupContents(ViewGroup *parent) override; Event OnChange; @@ -140,13 +140,18 @@ class SliderPopupScreen : public PopupScreen { private: EventReturn OnDecrease(EventParams ¶ms); EventReturn OnIncrease(EventParams ¶ms); + EventReturn OnTextChange(EventParams ¶ms); + EventReturn OnSliderChange(EventParams ¶ms); virtual void OnCompleted(DialogResult result) override; Slider *slider_; + UI::TextEdit *edit_; + std::string units_; int *value_; int sliderValue_; int minValue_; int maxValue_; int step_; + bool changing_; }; class SliderFloatPopupScreen : public PopupScreen { @@ -229,8 +234,8 @@ class PopupMultiChoice : public UI::Choice { class PopupSliderChoice : public Choice { public: - PopupSliderChoice(int *value, int minValue, int maxValue, const std::string &text, ScreenManager *screenManager, LayoutParams *layoutParams = 0); - PopupSliderChoice(int *value, int minValue, int maxValue, const std::string &text, int step, ScreenManager *screenManager, LayoutParams *layoutParams = 0); + PopupSliderChoice(int *value, int minValue, int maxValue, const std::string &text, ScreenManager *screenManager, const std::string &units = "", LayoutParams *layoutParams = 0); + PopupSliderChoice(int *value, int minValue, int maxValue, const std::string &text, int step, ScreenManager *screenManager, const std::string &units = "", LayoutParams *layoutParams = 0); virtual void Draw(UIContext &dc) override; @@ -244,6 +249,7 @@ class PopupSliderChoice : public Choice { int minValue_; int maxValue_; int step_; + std::string units_; ScreenManager *screenManager_; bool restoreFocus_; };