Skip to content

Commit

Permalink
Merge pull request #12486 from iota97/dpad
Browse files Browse the repository at this point in the history
Rebindable touch right analog
  • Loading branch information
hrydgard authored May 17, 2020
2 parents 2b605f1 + f460151 commit 2843b8e
Show file tree
Hide file tree
Showing 6 changed files with 228 additions and 15 deletions.
6 changes: 6 additions & 0 deletions Core/Config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,12 @@ static ConfigSetting generalSettings[] = {
ConfigSetting("GridView2", &g_Config.bGridView2, true),
ConfigSetting("GridView3", &g_Config.bGridView3, false),
ConfigSetting("ComboMode", &g_Config.iComboMode, 0),
ConfigSetting("RightAnalogUp", &g_Config.iRightAnalogUp, 0),
ConfigSetting("RightAnalogDown", &g_Config.iRightAnalogDown, 0),
ConfigSetting("RightAnalogLeft", &g_Config.iRightAnalogLeft, 0),
ConfigSetting("RightAnalogRight", &g_Config.iRightAnalogRight, 0),
ConfigSetting("RightAnalogPress", &g_Config.iRightAnalogPress, 0),
ConfigSetting("RightAnalogCustom", &g_Config.bRightAnalogCustom, false),

// "default" means let emulator decide, "" means disable.
ConfigSetting("ReportingHost", &g_Config.sReportHost, "default"),
Expand Down
8 changes: 8 additions & 0 deletions Core/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,14 @@ struct Config {
//Combo key screen flag
int iComboMode;

// Right analog binding
int iRightAnalogUp;
int iRightAnalogDown;
int iRightAnalogLeft;
int iRightAnalogRight;
int iRightAnalogPress;
bool bRightAnalogCustom;

// Disable diagonals
bool bDisableDpadDiagonals;
bool bGamepadOnlyFocused;
Expand Down
140 changes: 138 additions & 2 deletions UI/GamepadEmu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,138 @@ void PSPStick::ProcessTouch(float x, float y, bool down) {
}
}

PSPCustomStick::PSPCustomStick(ImageID bgImg, ImageID stickImg, ImageID stickDownImg, float scale, UI::LayoutParams *layoutParams)
: PSPStick(bgImg, stickImg, stickDownImg, -1, scale, layoutParams) {
}

void PSPCustomStick::Draw(UIContext &dc) {
float opacity = GetButtonOpacity();
if (opacity <= 0.0f)
return;

if (dragPointerId_ != -1 && g_Config.iTouchButtonStyle == 2) {
opacity *= 1.35f;
}

uint32_t colorBg = colorAlpha(GetButtonColor(), opacity);
uint32_t downBg = colorAlpha(0x00FFFFFF, opacity * 0.5f);
uint32_t color = colorAlpha(0x808080, opacity);

if (centerX_ < 0.0f) {
centerX_ = bounds_.centerX();
centerY_ = bounds_.centerY();
}

float stickX = centerX_;
float stickY = centerY_;

float dx, dy;
dx = posX_;
dy = -posY_;

dc.Draw()->DrawImage(bgImg_, stickX, stickY, 1.0f * scale_, colorBg, ALIGN_CENTER);
if (dragPointerId_ != -1 && g_Config.iTouchButtonStyle == 2 && stickDownImg_ != stickImageIndex_)
dc.Draw()->DrawImage(stickDownImg_, stickX + dx * stick_size_ * scale_, stickY - dy * stick_size_ * scale_, 1.0f * scale_, downBg, ALIGN_CENTER);
dc.Draw()->DrawImage(stickImageIndex_, stickX + dx * stick_size_ * scale_, stickY - dy * stick_size_ * scale_, 1.0f * scale_, colorBg, ALIGN_CENTER);
}

void PSPCustomStick::Touch(const TouchInput &input) {
GamepadView::Touch(input);
if (input.flags & TOUCH_RELEASE_ALL) {
dragPointerId_ = -1;
centerX_ = bounds_.centerX();
centerY_ = bounds_.centerY();
posX_ = 0.0f;
posY_ = 0.0f;
return;
}
if (input.flags & TOUCH_DOWN) {
if (dragPointerId_ == -1 && bounds_.Contains(input.x, input.y)) {
if (g_Config.bAutoCenterTouchAnalog) {
centerX_ = input.x;
centerY_ = input.y;
} else {
centerX_ = bounds_.centerX();
centerY_ = bounds_.centerY();
}
dragPointerId_ = input.id;
ProcessTouch(input.x, input.y, true);
}
}
if (input.flags & TOUCH_MOVE) {
if (input.id == dragPointerId_) {
ProcessTouch(input.x, input.y, true);
}
}
if (input.flags & TOUCH_UP) {
if (input.id == dragPointerId_) {
dragPointerId_ = -1;
centerX_ = bounds_.centerX();
centerY_ = bounds_.centerY();
ProcessTouch(input.x, input.y, false);
}
}
}

void PSPCustomStick::ProcessTouch(float x, float y, bool down) {
static const int button[16] = {CTRL_LTRIGGER, CTRL_RTRIGGER, CTRL_SQUARE, CTRL_TRIANGLE, CTRL_CIRCLE, CTRL_CROSS, CTRL_UP, CTRL_DOWN, CTRL_LEFT, CTRL_RIGHT, CTRL_START, CTRL_SELECT};

if (down && centerX_ >= 0.0f) {
float inv_stick_size = 1.0f / (stick_size_ * scale_);

float dx = (x - centerX_) * inv_stick_size;
float dy = (y - centerY_) * inv_stick_size;

dx = std::min(1.0f, std::max(-1.0f, dx));
dy = std::min(1.0f, std::max(-1.0f, dy));

if (g_Config.iRightAnalogRight != 0) {
if (dx > 0.5f)
__CtrlButtonDown(button[g_Config.iRightAnalogRight-1]);
else
__CtrlButtonUp(button[g_Config.iRightAnalogRight-1]);
}
if (g_Config.iRightAnalogLeft != 0) {
if (dx < -0.5f)
__CtrlButtonDown(button[g_Config.iRightAnalogLeft-1]);
else
__CtrlButtonUp(button[g_Config.iRightAnalogLeft-1]);
}
if (g_Config.iRightAnalogUp != 0) {
if (dy < -0.5f)
__CtrlButtonDown(button[g_Config.iRightAnalogUp-1]);
else
__CtrlButtonUp(button[g_Config.iRightAnalogUp-1]);
}
if (g_Config.iRightAnalogDown != 0) {
if (dy > 0.5f)
__CtrlButtonDown(button[g_Config.iRightAnalogDown-1]);
else
__CtrlButtonUp(button[g_Config.iRightAnalogDown-1]);
}
if (g_Config.iRightAnalogPress != 0)
__CtrlButtonDown(button[g_Config.iRightAnalogPress-1]);

posX_ = dx;
posY_ = dy;

} else {
if (g_Config.iRightAnalogUp != 0)
__CtrlButtonUp(button[g_Config.iRightAnalogUp-1]);
if (g_Config.iRightAnalogDown != 0)
__CtrlButtonUp(button[g_Config.iRightAnalogDown-1]);
if (g_Config.iRightAnalogLeft != 0)
__CtrlButtonUp(button[g_Config.iRightAnalogLeft-1]);
if (g_Config.iRightAnalogRight != 0)
__CtrlButtonUp(button[g_Config.iRightAnalogRight-1]);
if (g_Config.iRightAnalogPress != 0)
__CtrlButtonUp(button[g_Config.iRightAnalogPress-1]);

posX_ = 0.0f;
posY_ = 0.0f;
}
}

void InitPadLayout(float xres, float yres, float globalScale) {
const float scale = globalScale;
const int halfW = xres / 2;
Expand Down Expand Up @@ -720,8 +852,12 @@ UI::ViewGroup *CreatePadLayout(float xres, float yres, bool *pause) {
if (g_Config.touchAnalogStick.show)
root->Add(new PSPStick(stickBg, stickImage, ImageID("I_STICK"), 0, g_Config.touchAnalogStick.scale, buttonLayoutParams(g_Config.touchAnalogStick)));

if (g_Config.touchRightAnalogStick.show)
root->Add(new PSPStick(stickBg, stickImage, ImageID("I_STICK"), 1, g_Config.touchRightAnalogStick.scale, buttonLayoutParams(g_Config.touchRightAnalogStick)));
if (g_Config.touchRightAnalogStick.show) {
if (g_Config.bRightAnalogCustom)
root->Add(new PSPCustomStick(stickBg, stickImage, ImageID("I_STICK"), g_Config.touchRightAnalogStick.scale, buttonLayoutParams(g_Config.touchRightAnalogStick)));
else
root->Add(new PSPStick(stickBg, stickImage, ImageID("I_STICK"), 1, g_Config.touchRightAnalogStick.scale, buttonLayoutParams(g_Config.touchRightAnalogStick)));
}

addComboKey(g_Config.iCombokey0, g_Config.bComboToggle0, roundImage, ImageID("I_ROUND"), comboKeyImages[0], g_Config.touchCombo0);
addComboKey(g_Config.iCombokey1, g_Config.bComboToggle1, roundImage, ImageID("I_ROUND"), comboKeyImages[1], g_Config.touchCombo1);
Expand Down
21 changes: 18 additions & 3 deletions UI/GamepadEmu.h
Original file line number Diff line number Diff line change
Expand Up @@ -160,9 +160,7 @@ class PSPStick : public GamepadView {
void Draw(UIContext &dc) override;
void GetContentDimensions(const UIContext &dc, float &w, float &h) const override;

private:
void ProcessTouch(float x, float y, bool down);

protected:
int dragPointerId_;
ImageID bgImg_;
ImageID stickImageIndex_;
Expand All @@ -174,6 +172,23 @@ class PSPStick : public GamepadView {

float centerX_;
float centerY_;

private:
void ProcessTouch(float x, float y, bool down);
};

class PSPCustomStick : public PSPStick {
public:
PSPCustomStick(ImageID bgImg, ImageID stickImg, ImageID stickDownImg, float scale, UI::LayoutParams *layoutParams);

void Touch(const TouchInput &input) override;
void Draw(UIContext &dc) override;

private:
void ProcessTouch(float x, float y, bool down);

float posX_ = 0.0f;
float posY_ = 0.0f;
};

//initializes the layout from Config. if a default layout does not exist,
Expand Down
62 changes: 52 additions & 10 deletions UI/TouchControlVisibilityScreen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ void TouchControlVisibilityScreen::CreateViews() {
gridsettings.fillCells = true;
GridLayout *grid = vert->Add(new GridLayout(gridsettings, new LayoutParams(FILL_PARENT, WRAP_CONTENT)));

static const char* rightAnalogKey = "Right Analog Stick (tap to customize)";
toggles_.clear();
toggles_.push_back({ "Circle", &g_Config.bShowTouchCircle, ImageID("I_CIRCLE") });
toggles_.push_back({ "Cross", &g_Config.bShowTouchCross, ImageID("I_CROSS") });
Expand All @@ -81,7 +82,7 @@ void TouchControlVisibilityScreen::CreateViews() {
toggles_.push_back({ "Select", &g_Config.touchSelectKey.show, ImageID("I_SELECT") });
toggles_.push_back({ "Dpad", &g_Config.touchDpad.show, ImageID::invalid() });
toggles_.push_back({ "Analog Stick", &g_Config.touchAnalogStick.show, ImageID::invalid() });
toggles_.push_back({ "Right Analog Stick\n(not used by most games)", &g_Config.touchRightAnalogStick.show, ImageID::invalid() });
toggles_.push_back({ rightAnalogKey, &g_Config.touchRightAnalogStick.show, ImageID::invalid() });
toggles_.push_back({ "Unthrottle", &g_Config.touchUnthrottleKey.show, ImageID::invalid() });
toggles_.push_back({ "Combo0", &g_Config.touchCombo0.show, ImageID("I_1") });
toggles_.push_back({ "Combo1", &g_Config.touchCombo1.show, ImageID("I_2") });
Expand All @@ -95,24 +96,27 @@ void TouchControlVisibilityScreen::CreateViews() {
toggles_.push_back({ "Auto Analog Rotation (CCW)", &g_Config.touchAnalogRotationCCWKey.show, ImageID::invalid() });

auto mc = GetI18NCategory("MappableControls");

for (auto toggle : toggles_) {
LinearLayout *row = new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT));
row->SetSpacing(0);

CheckBox *checkbox = new CheckBox(toggle.show, "", "", new LinearLayoutParams(50, WRAP_CONTENT));
row->Add(checkbox);

Choice *choice;
if (toggle.img.isValid()) {
choice = new CheckBoxChoice(toggle.img, checkbox, new LinearLayoutParams(1.0f));
if (toggle.key == rightAnalogKey) {
Choice *rightAnalog = new Choice(co->T(rightAnalogKey), "", false, new LinearLayoutParams(1.0f));
rightAnalog->SetCentered(true);
row->Add(rightAnalog)->OnClick.Handle(this, &TouchControlVisibilityScreen::RightAnalogBindScreen);
} else {
choice = new CheckBoxChoice(mc->T(toggle.key), checkbox, new LinearLayoutParams(1.0f));
Choice *choice;
if (toggle.img.isValid()) {
choice = new CheckBoxChoice(toggle.img, checkbox, new LinearLayoutParams(1.0f));
} else {
choice = new CheckBoxChoice(mc->T(toggle.key), checkbox, new LinearLayoutParams(1.0f));
}
choice->SetCentered(true);
row->Add(choice);
}

choice->SetCentered(true);

row->Add(choice);
grid->Add(row);
}
}
Expand All @@ -121,6 +125,38 @@ void TouchControlVisibilityScreen::onFinish(DialogResult result) {
g_Config.Save("TouchControlVisibilityScreen::onFinish");
}

void RightAnalogMappingScreen::CreateViews() {
using namespace UI;

auto di = GetI18NCategory("Dialog");
auto co = GetI18NCategory("Controls");

root_ = new AnchorLayout(new LayoutParams(FILL_PARENT, FILL_PARENT));
Choice *back = new Choice(di->T("Back"), "", false, new AnchorLayoutParams(leftColumnWidth - 10, WRAP_CONTENT, 10, NONE, NONE, 10));
root_->Add(back)->OnClick.Handle<UIScreen>(this, &UIScreen::OnBack);
TabHolder *tabHolder = new TabHolder(ORIENT_VERTICAL, leftColumnWidth, new AnchorLayoutParams(10, 0, 10, 0, false));
root_->Add(tabHolder);
ScrollView *rightPanel = new ScrollView(ORIENT_VERTICAL);
tabHolder->AddTab(co->T("Binds"), rightPanel);
LinearLayout *vert = rightPanel->Add(new LinearLayout(ORIENT_VERTICAL, new LayoutParams(FILL_PARENT, FILL_PARENT)));
vert->SetSpacing(0);

static const char *rightAnalogButton[] = {"None", "Left trigger", "Right trigger", "Square", "Triangle", "Circle", "Cross", "D-PAD Up", "D-PAD Down", "D-PAD Left", "D-PAD Right", "Start", "Select"};

vert->Add(new CheckBox(&g_Config.bRightAnalogCustom, co->T("Use custom right analog")));
PopupMultiChoice *rightAnalogUp = vert->Add(new PopupMultiChoice(&g_Config.iRightAnalogUp, co->T("Right analog up"), rightAnalogButton, 0, ARRAY_SIZE(rightAnalogButton), co->GetName(), screenManager()));
PopupMultiChoice *rightAnalogDown = vert->Add(new PopupMultiChoice(&g_Config.iRightAnalogDown, co->T("Right analog down"), rightAnalogButton, 0, ARRAY_SIZE(rightAnalogButton), co->GetName(), screenManager()));
PopupMultiChoice *rightAnalogLeft = vert->Add(new PopupMultiChoice(&g_Config.iRightAnalogLeft, co->T("Right analog left"), rightAnalogButton, 0, ARRAY_SIZE(rightAnalogButton), co->GetName(), screenManager()));
PopupMultiChoice *rightAnalogRight = vert->Add(new PopupMultiChoice(&g_Config.iRightAnalogRight, co->T("Right analog right"), rightAnalogButton, 0, ARRAY_SIZE(rightAnalogButton), co->GetName(), 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), co->GetName(), screenManager()));
vert->Add(new CheckBox(&g_Config.touchRightAnalogStick.show, co->T("Show right analog")));
rightAnalogUp->SetEnabledPtr(&g_Config.bRightAnalogCustom);
rightAnalogDown->SetEnabledPtr(&g_Config.bRightAnalogCustom);
rightAnalogLeft->SetEnabledPtr(&g_Config.bRightAnalogCustom);
rightAnalogRight->SetEnabledPtr(&g_Config.bRightAnalogCustom);
rightAnalogPress->SetEnabledPtr(&g_Config.bRightAnalogCustom);
}

UI::EventReturn TouchControlVisibilityScreen::OnToggleAll(UI::EventParams &e) {
for (auto toggle : toggles_) {
*toggle.show = nextToggleAll_;
Expand All @@ -130,6 +166,12 @@ UI::EventReturn TouchControlVisibilityScreen::OnToggleAll(UI::EventParams &e) {
return UI::EVENT_DONE;
}

UI::EventReturn TouchControlVisibilityScreen::RightAnalogBindScreen(UI::EventParams &e) {
screenManager()->push(new RightAnalogMappingScreen());

return UI::EVENT_DONE;
}

UI::EventReturn CheckBoxChoice::HandleClick(UI::EventParams &e) {
checkbox_->Toggle();

Expand Down
6 changes: 6 additions & 0 deletions UI/TouchControlVisibilityScreen.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,14 @@ class TouchControlVisibilityScreen : public UIDialogScreenWithBackground {

protected:
UI::EventReturn OnToggleAll(UI::EventParams &e);
UI::EventReturn RightAnalogBindScreen(UI::EventParams &e);

private:
std::vector<TouchButtonToggle> toggles_;
bool nextToggleAll_ = true;
};

class RightAnalogMappingScreen : public UIDialogScreenWithBackground {
public:
void CreateViews() override;
};

0 comments on commit 2843b8e

Please sign in to comment.