From d7fd44280a5b5c3aee238e1db308fd5fdaf462c4 Mon Sep 17 00:00:00 2001 From: Katharine Chui Date: Tue, 16 Jul 2024 15:45:33 +0200 Subject: [PATCH] allow binding custom right stick to analog --- Core/HLE/sceCtrl.cpp | 13 +++++ Core/HLE/sceCtrl.h | 2 + UI/GamepadEmu.cpp | 77 +++++++++++++++++++++++++++-- UI/GamepadEmu.h | 2 +- UI/TouchControlVisibilityScreen.cpp | 6 +-- 5 files changed, 92 insertions(+), 8 deletions(-) diff --git a/Core/HLE/sceCtrl.cpp b/Core/HLE/sceCtrl.cpp index 7bca2772fd..9d86f47bbf 100644 --- a/Core/HLE/sceCtrl.cpp +++ b/Core/HLE/sceCtrl.cpp @@ -225,6 +225,19 @@ void __CtrlSetAnalogXY(int stick, float x, float y) ctrlCurrent.analog[stick][CTRL_ANALOG_Y] = scaledY; } +// not making XY to use these due to mutex guard usage +void __CtrlSetAnalogX(int stick, float x) { + u8 scaledX = clamp_u8((int)ceilf(x * 127.5f + 127.5f)); + std::lock_guard guard(ctrlMutex); + ctrlCurrent.analog[stick][CTRL_ANALOG_X] = scaledX; +} + +void __CtrlSetAnalogY(int stick, float y) { + u8 scaledY = clamp_u8((int)ceilf(-y * 127.5f + 127.5f)); + std::lock_guard guard(ctrlMutex); + ctrlCurrent.analog[stick][CTRL_ANALOG_Y] = scaledY; +} + void __CtrlSetRapidFire(bool state, int interval) { emuRapidFire = state; diff --git a/Core/HLE/sceCtrl.h b/Core/HLE/sceCtrl.h index e633dd62de..f4a65b6760 100644 --- a/Core/HLE/sceCtrl.h +++ b/Core/HLE/sceCtrl.h @@ -71,6 +71,8 @@ void __CtrlUpdateButtons(u32 bitsToSet, u32 bitsToClear); // X and Y values should be from -1 to 1, inclusive, in a square (no need to force to a circle.) // No deadzone filtering is done (but note that this applies to the actual PSP as well.) void __CtrlSetAnalogXY(int stick, float x, float y); +void __CtrlSetAnalogX(int stick, float x); +void __CtrlSetAnalogY(int stick, float y); // Call this to enable rapid-fire. This will cause buttons other than arrows to alternate. void __CtrlSetRapidFire(bool state, int interval); diff --git a/UI/GamepadEmu.cpp b/UI/GamepadEmu.cpp index e176c222ca..6b73c452b1 100644 --- a/UI/GamepadEmu.cpp +++ b/UI/GamepadEmu.cpp @@ -521,8 +521,8 @@ void PSPStick::ProcessTouch(float x, float y, bool down) { } } -PSPCustomStick::PSPCustomStick(ImageID bgImg, const char *key, ImageID stickImg, ImageID stickDownImg, float scale, UI::LayoutParams *layoutParams) - : PSPStick(bgImg, key, stickImg, stickDownImg, -1, scale, layoutParams) { +PSPCustomStick::PSPCustomStick(ImageID bgImg, const char *key, ImageID stickImg, ImageID stickDownImg, int stick, float scale, UI::LayoutParams *layoutParams) + : PSPStick(bgImg, key, stickImg, stickDownImg, stick, scale, layoutParams) { } void PSPCustomStick::Draw(UIContext &dc) { @@ -607,7 +607,7 @@ bool PSPCustomStick::Touch(const TouchInput &input) { void PSPCustomStick::ProcessTouch(float x, float y, bool down) { static const int buttons[] = {0, CTRL_LTRIGGER, CTRL_RTRIGGER, CTRL_SQUARE, CTRL_TRIANGLE, CTRL_CIRCLE, CTRL_CROSS, CTRL_UP, CTRL_DOWN, CTRL_LEFT, CTRL_RIGHT, CTRL_START, CTRL_SELECT}; - + static const int analogs[] = {VIRTKEY_AXIS_RIGHT_Y_MAX, VIRTKEY_AXIS_RIGHT_Y_MIN, VIRTKEY_AXIS_RIGHT_X_MIN, VIRTKEY_AXIS_RIGHT_X_MAX, VIRTKEY_AXIS_Y_MAX, VIRTKEY_AXIS_Y_MIN, VIRTKEY_AXIS_X_MIN, VIRTKEY_AXIS_X_MAX}; u32 press = 0; u32 release = 0; @@ -621,6 +621,71 @@ void PSPCustomStick::ProcessTouch(float x, float y, bool down) { release |= buttons[config]; }; + auto analog = [&](float dx, float dy) { + if (g_Config.bRightAnalogDisableDiagonal) { + if (fabs(dx) > fabs(dy)) { + dy = 0.0f; + } else { + dx = 0.0f; + } + } + + auto assign = [&](int config, float value) { + if (config < ARRAY_SIZE(buttons) || config >= ARRAY_SIZE(buttons) + ARRAY_SIZE(analogs)) { + return; + } + switch(analogs[config - ARRAY_SIZE(buttons)]) { + case VIRTKEY_AXIS_Y_MAX: + __CtrlSetAnalogY(0, value); + break; + case VIRTKEY_AXIS_Y_MIN: + __CtrlSetAnalogY(0, value * -1.0f); + break; + case VIRTKEY_AXIS_X_MIN: + __CtrlSetAnalogX(0, value * -1.0f); + break; + case VIRTKEY_AXIS_X_MAX: + __CtrlSetAnalogX(0, value); + break; + case VIRTKEY_AXIS_RIGHT_Y_MAX: + __CtrlSetAnalogY(1, value); + break; + case VIRTKEY_AXIS_RIGHT_Y_MIN: + __CtrlSetAnalogY(1, value * -1.0f); + break; + case VIRTKEY_AXIS_RIGHT_X_MIN: + __CtrlSetAnalogX(1, value * -1.0f); + break; + case VIRTKEY_AXIS_RIGHT_X_MAX: + __CtrlSetAnalogX(1, value); + break; + } + }; + + // if/when we ever get iLeftAnalog settings, check stick_ for the config to use + // let 0.0f through during centering + if (dy >= 0.0f) { + // down + assign(g_Config.iRightAnalogUp, 0.0f); + assign(g_Config.iRightAnalogDown, dy); + } + if (dy <= 0.0f) { + // up + assign(g_Config.iRightAnalogDown, 0.0f); + assign(g_Config.iRightAnalogUp, dy * -1.0f); + } + if (dx <= 0.0f) { + // left + assign(g_Config.iRightAnalogRight, 0.0f); + assign(g_Config.iRightAnalogLeft, dx * -1.0f); + } + if (dx >= 0.0f) { + // right + assign(g_Config.iRightAnalogLeft, 0.0f); + assign(g_Config.iRightAnalogRight, dx); + } + }; + if (down && centerX_ >= 0.0f) { float inv_stick_size = 1.0f / (stick_size_ * scale_); @@ -636,6 +701,8 @@ void PSPCustomStick::ProcessTouch(float x, float y, bool down) { toggle(g_Config.iRightAnalogDown, dy > 0.5f, fabs(dx) <= fabs(dy)); toggle(g_Config.iRightAnalogPress, true); + analog(dx, dy); + posX_ = dx; posY_ = dy; @@ -646,6 +713,8 @@ void PSPCustomStick::ProcessTouch(float x, float y, bool down) { toggle(g_Config.iRightAnalogDown, false); toggle(g_Config.iRightAnalogPress, false); + analog(0.0f, 0.0f); + posX_ = 0.0f; posY_ = 0.0f; } @@ -866,7 +935,7 @@ UI::ViewGroup *CreatePadLayout(float xres, float yres, bool *pause, bool showPau if (g_Config.touchRightAnalogStick.show) { if (g_Config.bRightAnalogCustom) - root->Add(new PSPCustomStick(stickBg, "Right analog stick", stickImage, ImageID("I_STICK"), g_Config.touchRightAnalogStick.scale, buttonLayoutParams(g_Config.touchRightAnalogStick))); + root->Add(new PSPCustomStick(stickBg, "Right analog stick", stickImage, ImageID("I_STICK"), 1, g_Config.touchRightAnalogStick.scale, buttonLayoutParams(g_Config.touchRightAnalogStick))); else root->Add(new PSPStick(stickBg, "Right analog stick", stickImage, ImageID("I_STICK"), 1, g_Config.touchRightAnalogStick.scale, buttonLayoutParams(g_Config.touchRightAnalogStick))); } diff --git a/UI/GamepadEmu.h b/UI/GamepadEmu.h index d110a527d4..875f20c78e 100644 --- a/UI/GamepadEmu.h +++ b/UI/GamepadEmu.h @@ -142,7 +142,7 @@ private: class PSPCustomStick : public PSPStick { public: - PSPCustomStick(ImageID bgImg, const char *key, ImageID stickImg, ImageID stickDownImg, float scale, UI::LayoutParams *layoutParams); + PSPCustomStick(ImageID bgImg, const char *key, ImageID stickImg, ImageID stickDownImg, int stick, float scale, UI::LayoutParams *layoutParams); bool Touch(const TouchInput &input) override; void Draw(UIContext &dc) override; diff --git a/UI/TouchControlVisibilityScreen.cpp b/UI/TouchControlVisibilityScreen.cpp index d96951fbfb..34b8c620b5 100644 --- a/UI/TouchControlVisibilityScreen.cpp +++ b/UI/TouchControlVisibilityScreen.cpp @@ -151,8 +151,8 @@ void RightAnalogMappingScreen::CreateViews() { 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"}; - + 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(&g_Config.touchRightAnalogStick.show, co->T("Visible"))); vert->Add(new CheckBox(&g_Config.bRightAnalogCustom, co->T("Use custom right analog"))); @@ -163,7 +163,7 @@ void RightAnalogMappingScreen::CreateViews() { 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), 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);