Skip to content

Commit

Permalink
DPad Analog
Browse files Browse the repository at this point in the history
Better multiple analog handling

More customizzable analog

RightAnalog mode fix

Remove now unused branch

Fix bad undefinite behavious

Update

try to fix submodule

Renamed Right analog button on press option

Fix start position of custom analog

Double disabling condition

Make right analog press work even with default right analog stick

Fix tab

Removed another tab

Fix race

Customizzable right analog

Little fix

Separate custom analog from sceCtrl

Minor
  • Loading branch information
iota97 committed Feb 9, 2020
1 parent 84c1fc8 commit 717c66c
Show file tree
Hide file tree
Showing 6 changed files with 254 additions and 12 deletions.
6 changes: 6 additions & 0 deletions Core/Config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,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 @@ -269,6 +269,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
159 changes: 157 additions & 2 deletions UI/GamepadEmu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "base/timeutil.h"
#include "math/math_util.h"
#include "ui/ui_context.h"
#include "Core/Util/AudioFormat.h" // for clamp_u8

static u32 GetButtonColor() {
return g_Config.iTouchButtonStyle != 0 ? 0xFFFFFF : 0xc0b080;
Expand Down Expand Up @@ -452,6 +453,156 @@ void PSPStick::ProcessTouch(float x, float y, bool down) {
}
}

PSPCustomStick::PSPCustomStick(int bgImg, int stickImg, int stickDownImg, float scale, UI::LayoutParams *layoutParams)
: GamepadView(layoutParams), dragPointerId_(-1), bgImg_(bgImg), stickImageIndex_(stickImg), stickDownImg_(stickDownImg), scale_(scale), centerX_(-1), centerY_(-1) {
stick_size_ = 50;
posX_ = clamp_u8((int)ceilf(127.5f));
posY_ = clamp_u8((int)ceilf(127.5f));
}

void PSPCustomStick::GetContentDimensions(const UIContext &dc, float &w, float &h) const {
const AtlasImage &image = dc.Draw()->GetAtlas()->images[bgImg_];
w = image.w;
h = image.h;
}

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_ - 127.5f) / 127.5f;
dy = -(posY_ - 127.5f) / 127.5f;

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_ = clamp_u8((int)ceilf(127.5f));
posY_ = clamp_u8((int)ceilf(127.5f));
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;
// Do not clamp to a circle! The PSP has nearly square range!

// Old code to clamp to a circle
// float len = sqrtf(dx * dx + dy * dy);
// if (len > 1.0f) {
// dx /= len;
// dy /= len;
//}

// Still need to clamp to a square
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_ = clamp_u8((int)ceilf(dx * 127.5f + 127.5f));
posY_ = clamp_u8((int)ceilf(dy * 127.5f + 127.5f));

} 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_ = clamp_u8((int)ceilf(127.5f));
posY_ = clamp_u8((int)ceilf(127.5f));
}
}

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

if (g_Config.touchRightAnalogStick.show)
root->Add(new PSPStick(stickBg, stickImage, 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, I_STICK, g_Config.touchRightAnalogStick.scale, buttonLayoutParams(g_Config.touchRightAnalogStick)));
else
root->Add(new PSPStick(stickBg, stickImage, I_STICK, 1, g_Config.touchRightAnalogStick.scale, buttonLayoutParams(g_Config.touchRightAnalogStick)));
}

addComboKey(g_Config.iCombokey0, roundImage, I_ROUND, comboKeyImages[0], g_Config.touchCombo0);
addComboKey(g_Config.iCombokey1, roundImage, I_ROUND, comboKeyImages[1], g_Config.touchCombo1);
Expand Down
24 changes: 24 additions & 0 deletions UI/GamepadEmu.h
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,30 @@ class PSPStick : public GamepadView {
float centerY_;
};

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

void Touch(const TouchInput &input) override;
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);

int dragPointerId_;
int bgImg_;
int stickImageIndex_;
int stickDownImg_;
float stick_size_;
float scale_;

float centerX_;
float centerY_;
u8 posX_;
u8 posY_;
};

//initializes the layout from Config. if a default layout does not exist,
//it sets up default values
void InitPadLayout(float xres, float yres, float globalScale = 1.15f);
Expand Down
63 changes: 53 additions & 10 deletions UI/TouchControlVisibilityScreen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ void TouchControlVisibilityScreen::CreateViews() {
gridsettings.fillCells = true;
GridLayout *grid = vert->Add(new GridLayout(gridsettings, new LayoutParams(FILL_PARENT, WRAP_CONTENT)));

static const char* rightAnalogString = "Right Analog Stick (tap to customize)";
toggles_.clear();
toggles_.push_back({ "Circle", &g_Config.bShowTouchCircle, I_CIRCLE });
toggles_.push_back({ "Cross", &g_Config.bShowTouchCross, I_CROSS });
Expand All @@ -80,7 +81,7 @@ void TouchControlVisibilityScreen::CreateViews() {
toggles_.push_back({ "Select", &g_Config.touchSelectKey.show, I_SELECT });
toggles_.push_back({ "Dpad", &g_Config.touchDpad.show, -1 });
toggles_.push_back({ "Analog Stick", &g_Config.touchAnalogStick.show, -1 });
toggles_.push_back({ "Right Analog Stick\n(not used by most games)", &g_Config.touchRightAnalogStick.show, -1 });
toggles_.push_back({ rightAnalogString, &g_Config.touchRightAnalogStick.show, -1 });
toggles_.push_back({ "Unthrottle", &g_Config.touchUnthrottleKey.show, -1 });
toggles_.push_back({ "Combo0", &g_Config.touchCombo0.show, I_1 });
toggles_.push_back({ "Combo1", &g_Config.touchCombo1.show, I_2 });
Expand All @@ -90,7 +91,7 @@ void TouchControlVisibilityScreen::CreateViews() {
toggles_.push_back({ "Alt speed 1", &g_Config.touchSpeed1Key.show, -1 });
toggles_.push_back({ "Alt speed 2", &g_Config.touchSpeed2Key.show, -1 });
toggles_.push_back({ "Rapid Fire", &g_Config.touchRapidFireKey.show, -1 });

toggles_.push_back({ "Right Analog Stick", &g_Config.touchRightAnalogStick.show, -1 });
auto mc = GetI18NCategory("MappableControls");

for (auto toggle : toggles_) {
Expand All @@ -100,16 +101,20 @@ void TouchControlVisibilityScreen::CreateViews() {
CheckBox *checkbox = new CheckBox(toggle.show, "", "", new LinearLayoutParams(50, WRAP_CONTENT));
row->Add(checkbox);

Choice *choice;
if (toggle.img != -1) {
choice = new CheckBoxChoice(toggle.img, checkbox, new LinearLayoutParams(1.0f));
if (toggle.key == rightAnalogString) {
Choice *rightAnalog = new Choice(co->T(rightAnalogString), "", 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 != -1) {
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 @@ -118,6 +123,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 @@ -127,6 +164,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 @@ -36,8 +36,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 717c66c

Please sign in to comment.