allow binding custom right stick to analog

This commit is contained in:
Katharine Chui 2024-07-16 15:45:33 +02:00
parent e01ca5b057
commit d7fd44280a
5 changed files with 92 additions and 8 deletions

View File

@ -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<std::mutex> 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<std::mutex> guard(ctrlMutex);
ctrlCurrent.analog[stick][CTRL_ANALOG_Y] = scaledY;
}
void __CtrlSetRapidFire(bool state, int interval)
{
emuRapidFire = state;

View File

@ -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);

View File

@ -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)));
}

View File

@ -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;

View File

@ -151,7 +151,7 @@ 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")));
@ -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);