diff --git a/Common/KeyMap.cpp b/Common/KeyMap.cpp index ec94c89797..102e2a6b02 100644 --- a/Common/KeyMap.cpp +++ b/Common/KeyMap.cpp @@ -700,6 +700,8 @@ const KeyMap_IntStrPair psp_button_names[] = { {VIRTKEY_TEXTURE_REPLACE, "Texture Replacement"}, {VIRTKEY_SCREENSHOT, "Screenshot"}, {VIRTKEY_MUTE_TOGGLE, "Mute toggle"}, + {VIRTKEY_ANALOG_ROTATE_CW, "Rotate Analog (CW)"}, + {VIRTKEY_ANALOG_ROTATE_CCW, "Rotate Analog (CCW)"}, {CTRL_HOME, "Home"}, {CTRL_HOLD, "Hold"}, diff --git a/Common/KeyMap.h b/Common/KeyMap.h index 87493ea415..86883a9e98 100644 --- a/Common/KeyMap.h +++ b/Common/KeyMap.h @@ -59,6 +59,8 @@ enum { VIRTKEY_SCREENSHOT = 0x4000001B, VIRTKEY_MUTE_TOGGLE = 0x4000001C, VIRTKEY_OPENCHAT = 0x4000001D, + VIRTKEY_ANALOG_ROTATE_CW = 0x4000001E, + VIRTKEY_ANALOG_ROTATE_CCW = 0x4000001F, VIRTKEY_LAST, VIRTKEY_COUNT = VIRTKEY_LAST - VIRTKEY_FIRST }; diff --git a/Core/Config.cpp b/Core/Config.cpp index b20b7f62e6..84be966e6a 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -866,6 +866,7 @@ static ConfigSetting controlSettings[] = { ConfigSetting("TouchButtonOpacity", &g_Config.iTouchButtonOpacity, 65, true, true), ConfigSetting("TouchButtonHideSeconds", &g_Config.iTouchButtonHideSeconds, 20, true, true), ConfigSetting("AutoCenterTouchAnalog", &g_Config.bAutoCenterTouchAnalog, false, true, true), + ConfigSetting("AnalogAutoRotSpeed", &g_Config.fAnalogAutoRotSpeed, 15.0f, true, true), // Snap touch control position ConfigSetting("TouchSnapToGrid", &g_Config.bTouchSnapToGrid, false, true, true), @@ -894,6 +895,8 @@ static ConfigSetting controlSettings[] = { ConfigSetting("Speed1KeyX", "Speed1KeyY", "Speed1KeyScale", "ShowSpeed1Key", &g_Config.touchSpeed1Key, defaultTouchPosHide, true, true), ConfigSetting("Speed2KeyX", "Speed2KeyY", "Speed2KeyScale", "ShowSpeed2Key", &g_Config.touchSpeed2Key, defaultTouchPosHide, true, true), ConfigSetting("RapidFireKeyX", "RapidFireKeyY", "RapidFireKeyScale", "ShowRapidFireKey", &g_Config.touchRapidFireKey, defaultTouchPosHide, true, true), + ConfigSetting("AnalogRotationCWKeyX", "AnalogRotationKeyCWY", "AnalogRotationKeyCWScale", "ShowAnalogRotationCWKey", &g_Config.touchAnalogRotationCWKey, defaultTouchPosHide, true, true), + ConfigSetting("AnalogRotationCCWKeyX", "AnalogRotationKeyCCWY", "AnalogRotationKeyCCWScale", "ShowAnalogRotationCCWKey", &g_Config.touchAnalogRotationCCWKey, defaultTouchPosHide, true, true), #ifdef _WIN32 ConfigSetting("DInputAnalogDeadzone", &g_Config.fDInputAnalogDeadzone, 0.1f, true, true), @@ -1629,6 +1632,8 @@ void Config::ResetControlLayout() { reset(g_Config.touchSpeed1Key); reset(g_Config.touchSpeed2Key); reset(g_Config.touchRapidFireKey); + reset(g_Config.touchAnalogRotationCWKey); + reset(g_Config.touchAnalogRotationCCWKey); } void Config::GetReportingInfo(UrlEncoder &data) { diff --git a/Core/Config.h b/Core/Config.h index d8a52cccde..1c73b7e51d 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -292,6 +292,8 @@ public: int iTouchButtonStyle; int iTouchButtonOpacity; int iTouchButtonHideSeconds; + // Auto rotation speed + float fAnalogAutoRotSpeed; // Snap touch control position bool bTouchSnapToGrid; @@ -325,6 +327,8 @@ public: ConfigTouchPos touchSpeed1Key; ConfigTouchPos touchSpeed2Key; ConfigTouchPos touchRapidFireKey; + ConfigTouchPos touchAnalogRotationCWKey; + ConfigTouchPos touchAnalogRotationCCWKey; // Controls Visibility bool bShowTouchControls; diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index d56d8dd9a5..09e431a8c1 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -665,6 +665,14 @@ void EmuScreen::onVKeyDown(int virtualKeyCode) { case VIRTKEY_MUTE_TOGGLE: g_Config.bEnableSound = !g_Config.bEnableSound; break; + case VIRTKEY_ANALOG_ROTATE_CW: + autoRotatingAnalogCW_ = true; + autoRotatingAnalogCCW_ = false; + break; + case VIRTKEY_ANALOG_ROTATE_CCW: + autoRotatingAnalogCW_ = false; + autoRotatingAnalogCCW_ = true; + break; } } @@ -718,6 +726,18 @@ void EmuScreen::onVKeyUp(int virtualKeyCode) { __CtrlSetRapidFire(false); break; + case VIRTKEY_ANALOG_ROTATE_CW: + autoRotatingAnalogCW_ = false; + __CtrlSetAnalogX(0.0f, 0); + __CtrlSetAnalogY(0.0f, 0); + break; + + case VIRTKEY_ANALOG_ROTATE_CCW: + autoRotatingAnalogCCW_ = false; + __CtrlSetAnalogX(0.0f, 0); + __CtrlSetAnalogY(0.0f, 0); + break; + default: break; } @@ -1163,6 +1183,16 @@ void EmuScreen::update() { if (invalid_) return; + if (autoRotatingAnalogCW_) { + const float now = time_now_d(); + __CtrlSetAnalogX(cos(now*-g_Config.fAnalogAutoRotSpeed), 0); + __CtrlSetAnalogY(sin(now*-g_Config.fAnalogAutoRotSpeed), 0); + } else if (autoRotatingAnalogCCW_) { + const float now = time_now_d(); + __CtrlSetAnalogX(cos(now*g_Config.fAnalogAutoRotSpeed), 0); + __CtrlSetAnalogY(sin(now*g_Config.fAnalogAutoRotSpeed), 0); + } + // This is here to support the iOS on screen back button. if (pauseTrigger_) { pauseTrigger_ = false; diff --git a/UI/EmuScreen.h b/UI/EmuScreen.h index 1c371140a7..9279944c6e 100644 --- a/UI/EmuScreen.h +++ b/UI/EmuScreen.h @@ -106,4 +106,6 @@ private: UI::TextView *loadingTextView_ = nullptr; UI::Button *cardboardDisableButton_ = nullptr; + bool autoRotatingAnalogCW_ = false; + bool autoRotatingAnalogCCW_ = false; }; diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index e4dd17d0c1..dc139e0353 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -641,6 +641,7 @@ void GameSettingsScreen::CreateViews() { #else controlsSettings->Add(new PopupSliderChoiceFloat(&g_Config.fXInputAnalogSensitivity, 0.0f, 10.0f, co->T("Analog Axis Sensitivity", "Analog Axis Sensitivity"), 0.01f, screenManager(), "x")); #endif + controlsSettings->Add(new PopupSliderChoiceFloat(&g_Config.fAnalogAutoRotSpeed, 0.0f, 25.0f, co->T("Analog auto-rotation speed"), 1.0f, screenManager())); controlsSettings->Add(new ItemHeader(co->T("Keyboard", "Keyboard Control Settings"))); #if defined(USING_WIN_UI) diff --git a/UI/GamepadEmu.cpp b/UI/GamepadEmu.cpp index 421914a7b2..312f488b57 100644 --- a/UI/GamepadEmu.cpp +++ b/UI/GamepadEmu.cpp @@ -162,6 +162,10 @@ void FPSLimitButton::Touch(const TouchInput &input) { } } +bool FPSLimitButton::IsDown() { + return PSP_CoreParameter().fpsLimit == limit_; +} + void RapidFireButton::Touch(const TouchInput &input) { bool lastDown = pointerDownMask_ != 0; MultiTouchButton::Touch(input); @@ -175,8 +179,32 @@ bool RapidFireButton::IsDown() { return __CtrlGetRapidFire(); } -bool FPSLimitButton::IsDown() { - return PSP_CoreParameter().fpsLimit == limit_; +void AnalogRotationButton::Touch(const TouchInput &input) { + bool lastDown = pointerDownMask_ != 0; + MultiTouchButton::Touch(input); + bool down = pointerDownMask_ != 0; + if (down && !lastDown) { + autoRotating_ = true; + } else if (lastDown && !down) { + autoRotating_ = false; + __CtrlSetAnalogX(0.0f, 0); + __CtrlSetAnalogY(0.0f, 0); + } +} + +void AnalogRotationButton::Update() { + const float now = time_now(); + float delta = now - lastFrameTime_; + if (delta > 0) { + secondsWithoutTouch_ += delta; + } + lastFrameTime_ = now; + + if (autoRotating_) { + float speed = clockWise_ ? -g_Config.fAnalogAutoRotSpeed : g_Config.fAnalogAutoRotSpeed; + __CtrlSetAnalogX(cos(now*speed), 0); + __CtrlSetAnalogY(sin(now*speed), 0); + } } void PSPButton::Touch(const TouchInput &input) { @@ -533,6 +561,8 @@ void InitPadLayout(float xres, float yres, float globalScale) { initTouchPos(g_Config.touchSpeed1Key, unthrottle_key_X, unthrottle_key_Y - 60 * scale); initTouchPos(g_Config.touchSpeed2Key, unthrottle_key_X + bottom_key_spacing * scale, unthrottle_key_Y - 60 * scale); initTouchPos(g_Config.touchRapidFireKey, unthrottle_key_X + 2*bottom_key_spacing * scale, unthrottle_key_Y - 60 * scale); + initTouchPos(g_Config.touchAnalogRotationCCWKey, unthrottle_key_X, unthrottle_key_Y - 120 * scale); + initTouchPos(g_Config.touchAnalogRotationCWKey, unthrottle_key_X + bottom_key_spacing * scale, unthrottle_key_Y - 120 * scale); // L and R------------------------------------------------------------ // Put them above the analog stick / above the buttons to the right. @@ -661,6 +691,16 @@ UI::ViewGroup *CreatePadLayout(float xres, float yres, bool *pause) { rapidFire->SetAngle(90.0f, 180.0f); } + if (g_Config.touchAnalogRotationCWKey.show) { + auto analogRotationCC = root->Add(new AnalogRotationButton(true, rectImage, ImageID("I_RECT"), ImageID("I_ARROW"), g_Config.touchAnalogRotationCWKey.scale, buttonLayoutParams(g_Config.touchAnalogRotationCWKey))); + analogRotationCC->SetAngle(190.0f, 180.0f); + } + + if (g_Config.touchAnalogRotationCCWKey.show) { + auto analogRotationCCW = root->Add(new AnalogRotationButton(false, rectImage, ImageID("I_RECT"), ImageID("I_ARROW"), g_Config.touchAnalogRotationCCWKey.scale, buttonLayoutParams(g_Config.touchAnalogRotationCCWKey))); + analogRotationCCW->SetAngle(350.0f, 180.0f); + } + FPSLimitButton *speed1 = addFPSLimitButton(FPSLimit::CUSTOM1, rectImage, ImageID("I_RECT"), ImageID("I_ARROW"), g_Config.touchSpeed1Key); if (speed1) speed1->SetAngle(170.0f, 180.0f); diff --git a/UI/GamepadEmu.h b/UI/GamepadEmu.h index 892abaa83a..5e0cf4c6e4 100644 --- a/UI/GamepadEmu.h +++ b/UI/GamepadEmu.h @@ -106,6 +106,19 @@ public: bool IsDown() override; }; +class AnalogRotationButton : public MultiTouchButton { +public: + AnalogRotationButton(bool clockWise, ImageID bgImg, ImageID bgDownImg, ImageID img, float scale, UI::LayoutParams *layoutParams) + : MultiTouchButton(bgImg, bgDownImg, img, scale, layoutParams), clockWise_(clockWise) { + } + void Touch(const TouchInput &input) override; + void Update() override; + +private: + bool autoRotating_ = false; + bool clockWise_; +}; + class PSPButton : public MultiTouchButton { public: PSPButton(int pspButtonBit, ImageID bgImg, ImageID bgDownImg, ImageID img, float scale, UI::LayoutParams *layoutParams) diff --git a/UI/TouchControlLayoutScreen.cpp b/UI/TouchControlLayoutScreen.cpp index 69092ea667..62bb4c0497 100644 --- a/UI/TouchControlLayoutScreen.cpp +++ b/UI/TouchControlLayoutScreen.cpp @@ -454,6 +454,18 @@ void TouchControlLayoutScreen::CreateViews() { controls_.push_back(rapidFire); } + if (g_Config.touchAnalogRotationCWKey.show) { + DragDropButton *analogRotationCW = new DragDropButton(g_Config.touchAnalogRotationCWKey, rectImage, ImageID("I_ARROW")); + analogRotationCW->SetAngle(190.0f, 180.0f); + controls_.push_back(analogRotationCW); + } + + if (g_Config.touchAnalogRotationCCWKey.show) { + DragDropButton *analogRotationCCW = new DragDropButton(g_Config.touchAnalogRotationCCWKey, rectImage, ImageID("I_ARROW")); + analogRotationCCW->SetAngle(350.0f, 180.0f); + controls_.push_back(analogRotationCCW); + } + if (g_Config.touchLKey.show) { controls_.push_back(new DragDropButton(g_Config.touchLKey, shoulderImage, ImageID("I_L"))); } diff --git a/UI/TouchControlVisibilityScreen.cpp b/UI/TouchControlVisibilityScreen.cpp index 04b68b4abd..31cd45d761 100644 --- a/UI/TouchControlVisibilityScreen.cpp +++ b/UI/TouchControlVisibilityScreen.cpp @@ -91,6 +91,8 @@ void TouchControlVisibilityScreen::CreateViews() { toggles_.push_back({ "Alt speed 1", &g_Config.touchSpeed1Key.show, ImageID::invalid() }); toggles_.push_back({ "Alt speed 2", &g_Config.touchSpeed2Key.show, ImageID::invalid() }); toggles_.push_back({ "RapidFire", &g_Config.touchRapidFireKey.show, ImageID::invalid() }); + toggles_.push_back({ "Auto Analog Rotation (CW)", &g_Config.touchAnalogRotationCWKey.show, ImageID::invalid() }); + toggles_.push_back({ "Auto Analog Rotation (CCW)", &g_Config.touchAnalogRotationCCWKey.show, ImageID::invalid() }); auto mc = GetI18NCategory("MappableControls");