Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support virtual button in touch gesture #14782

Merged
merged 3 commits into from
Aug 30, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Core/KeyMap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,13 @@ std::string GetPspButtonName(int btn) {
return FindName(btn, psp_button_names, ARRAY_SIZE(psp_button_names));
}

const char* GetPspButtonNameCharPointer(int btn) {
for (size_t i = 0; i < ARRAY_SIZE(psp_button_names); i++)
if (psp_button_names[i].key == btn)
return psp_button_names[i].name;
return nullptr;
}

std::vector<KeyMap_IntStrPair> GetMappableKeys() {
std::vector<KeyMap_IntStrPair> temp;
for (size_t i = 0; i < ARRAY_SIZE(psp_button_names); i++) {
Expand Down
1 change: 1 addition & 0 deletions Core/KeyMap.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ namespace KeyMap {
std::string GetKeyOrAxisName(int keyCode);
std::string GetAxisName(int axisId);
std::string GetPspButtonName(int btn);
const char* GetPspButtonNameCharPointer(int btn);

std::vector<KeyMap_IntStrPair> GetMappableKeys();

Expand Down
4 changes: 2 additions & 2 deletions UI/ComboKeyMappingScreen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ void ComboKeyScreen::CreateViews() {
gridsettings.fillCells = true;
GridLayout *grid = vertLayout->Add(new GridLayout(gridsettings, new LayoutParams(FILL_PARENT, WRAP_CONTENT)));

// Button name, image and action are defined in GamepadEmu.h
// Button image and action are defined in GamepadEmu.h
for (int i = 0; i < ARRAY_SIZE(comboKeyList); ++i) {
LinearLayout *row = new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT));
row->SetSpacing(0);
Expand All @@ -190,7 +190,7 @@ void ComboKeyScreen::CreateViews() {
if (comboKeyList[i].i.isValid()) {
choice = new Choice(comboKeyList[i].i, new LinearLayoutParams(1.0f));
} else {
choice = new Choice(mc->T(comboKeyList[i].n), new LinearLayoutParams(1.0f));
choice = new Choice(mc->T(KeyMap::GetPspButtonNameCharPointer(comboKeyList[i].c)), new LinearLayoutParams(1.0f));
}

ChoiceEventHandler *choiceEventHandler = new ChoiceEventHandler(checkbox);
Expand Down
15 changes: 13 additions & 2 deletions UI/GameSettingsScreen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -729,10 +729,12 @@ void GameSettingsScreen::CreateViews() {
static const char *touchControlStyles[] = {"Classic", "Thin borders", "Glowing borders"};
View *style = controlsSettings->Add(new PopupMultiChoice(&g_Config.iTouchButtonStyle, co->T("Button style"), touchControlStyles, 0, ARRAY_SIZE(touchControlStyles), co->GetName(), screenManager()));
style->SetEnabledPtr(&g_Config.bShowTouchControls);
controlsSettings->Add(new Choice(co->T("Gesture mapping")))->OnClick.Add([=](EventParams &e) {
Choice *gesture = controlsSettings->Add(new Choice(co->T("Gesture mapping")));
gesture->OnClick.Add([=](EventParams &e) {
screenManager()->push(new GestureMappingScreen());
return UI::EVENT_DONE;
});
gesture->SetEnabledPtr(&g_Config.bShowTouchControls);
}

controlsSettings->Add(new ItemHeader(co->T("Keyboard", "Keyboard Control Settings")));
Expand Down Expand Up @@ -2007,14 +2009,23 @@ void GestureMappingScreen::CreateViews() {
LinearLayout *vert = rightPanel->Add(new LinearLayout(ORIENT_VERTICAL, new LayoutParams(FILL_PARENT, FILL_PARENT)));
vert->SetSpacing(0);

static const char *gestureButton[] = {"None", "L", "R", "Square", "Triangle", "Circle", "Cross", "D-pad up", "D-pad down", "D-pad left", "D-pad right", "Start", "Select"};
static const char *gestureButton[ARRAY_SIZE(GestureKey::keyList)+1];
gestureButton[0] = "None";
for (int i = 1; i < ARRAY_SIZE(gestureButton); ++i) {
gestureButton[i] = KeyMap::GetPspButtonNameCharPointer(GestureKey::keyList[i-1]);
}

vert->Add(new CheckBox(&g_Config.bGestureControlEnabled, co->T("Enable gesture control")));

vert->Add(new ItemHeader(co->T("Swipe")));
vert->Add(new PopupMultiChoice(&g_Config.iSwipeUp, mc->T("Swipe Up"), gestureButton, 0, ARRAY_SIZE(gestureButton), mc->GetName(), screenManager()))->SetEnabledPtr(&g_Config.bGestureControlEnabled);
vert->Add(new PopupMultiChoice(&g_Config.iSwipeDown, mc->T("Swipe Down"), gestureButton, 0, ARRAY_SIZE(gestureButton), mc->GetName(), screenManager()))->SetEnabledPtr(&g_Config.bGestureControlEnabled);
vert->Add(new PopupMultiChoice(&g_Config.iSwipeLeft, mc->T("Swipe Left"), gestureButton, 0, ARRAY_SIZE(gestureButton), mc->GetName(), screenManager()))->SetEnabledPtr(&g_Config.bGestureControlEnabled);
vert->Add(new PopupMultiChoice(&g_Config.iSwipeRight, mc->T("Swipe Right"), gestureButton, 0, ARRAY_SIZE(gestureButton), mc->GetName(), screenManager()))->SetEnabledPtr(&g_Config.bGestureControlEnabled);
vert->Add(new PopupSliderChoiceFloat(&g_Config.fSwipeSensitivity, 0.01f, 1.0f, co->T("Swipe sensitivity"), 0.01f, screenManager(), "x"))->SetEnabledPtr(&g_Config.bGestureControlEnabled);
vert->Add(new PopupSliderChoiceFloat(&g_Config.fSwipeSmoothing, 0.0f, 0.95f, co->T("Swipe smoothing"), 0.05f, screenManager(), "x"))->SetEnabledPtr(&g_Config.bGestureControlEnabled);

vert->Add(new ItemHeader(co->T("Double tap")));
vert->Add(new PopupMultiChoice(&g_Config.iDoubleTapGesture, mc->T("Double tap button"), gestureButton, 0, ARRAY_SIZE(gestureButton), mc->GetName(), screenManager()))->SetEnabledPtr(&g_Config.bGestureControlEnabled);
}

26 changes: 11 additions & 15 deletions UI/GamepadEmu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -827,15 +827,13 @@ UI::ViewGroup *CreatePadLayout(float xres, float yres, bool *pause, bool showPau
addComboKey(g_Config.CustomKey9, "Custom 10 button", g_Config.touchCombo9);

if (g_Config.bGestureControlEnabled)
root->Add(new GestureGamepad());
root->Add(new GestureGamepad(controllMapper));

return root;
}


void GestureGamepad::Touch(const TouchInput &input) {
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 (usedPointerMask & (1 << input.id)) {
if (input.id == dragPointerId_)
dragPointerId_ = -1;
Expand All @@ -856,7 +854,7 @@ void GestureGamepad::Touch(const TouchInput &input) {
const float now = time_now_d();
if (now - lastTapRelease_ < 0.3f && !haveDoubleTapped_) {
if (g_Config.iDoubleTapGesture != 0 )
__CtrlButtonDown(button[g_Config.iDoubleTapGesture-1]);
controllMapper_->pspKey(GestureKey::keyList[g_Config.iDoubleTapGesture-1], KEY_DOWN);
haveDoubleTapped_ = true;
}

Expand All @@ -879,52 +877,50 @@ void GestureGamepad::Touch(const TouchInput &input) {

if (haveDoubleTapped_) {
if (g_Config.iDoubleTapGesture != 0)
__CtrlButtonUp(button[g_Config.iDoubleTapGesture-1]);
controllMapper_->pspKey(GestureKey::keyList[g_Config.iDoubleTapGesture-1], KEY_UP);
haveDoubleTapped_ = false;
}
}
}
}

void GestureGamepad::Update() {
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};

const float th = 1.0f;
float dx = deltaX_ * g_dpi_scale_x * g_Config.fSwipeSensitivity;
float dy = deltaY_ * g_dpi_scale_y * g_Config.fSwipeSensitivity;
if (g_Config.iSwipeRight != 0) {
if (dx > th) {
__CtrlButtonDown(button[g_Config.iSwipeRight-1]);
controllMapper_->pspKey(GestureKey::keyList[g_Config.iSwipeRight-1], KEY_DOWN);
swipeRightReleased_ = false;
} else if (!swipeRightReleased_) {
__CtrlButtonUp(button[g_Config.iSwipeRight-1]);
controllMapper_->pspKey(GestureKey::keyList[g_Config.iSwipeRight-1], KEY_UP);
swipeRightReleased_ = true;
}
}
if (g_Config.iSwipeLeft != 0) {
if (dx < -th) {
__CtrlButtonDown(button[g_Config.iSwipeLeft-1]);
controllMapper_->pspKey(GestureKey::keyList[g_Config.iSwipeLeft-1], KEY_DOWN);
swipeLeftReleased_ = false;
} else if (!swipeLeftReleased_) {
__CtrlButtonUp(button[g_Config.iSwipeLeft-1]);
controllMapper_->pspKey(GestureKey::keyList[g_Config.iSwipeLeft-1], KEY_UP);
swipeLeftReleased_ = true;
}
}
if (g_Config.iSwipeUp != 0) {
if (dy < -th) {
__CtrlButtonDown(button[g_Config.iSwipeUp-1]);
controllMapper_->pspKey(GestureKey::keyList[g_Config.iSwipeUp-1], KEY_DOWN);
swipeUpReleased_ = false;
} else if (!swipeUpReleased_) {
__CtrlButtonUp(button[g_Config.iSwipeUp-1]);
controllMapper_->pspKey(GestureKey::keyList[g_Config.iSwipeUp-1], KEY_UP);
swipeUpReleased_ = true;
}
}
if (g_Config.iSwipeDown != 0) {
if (dy > th) {
__CtrlButtonDown(button[g_Config.iSwipeDown-1]);
controllMapper_->pspKey(GestureKey::keyList[g_Config.iSwipeDown-1], KEY_DOWN);
swipeDownReleased_ = false;
} else if (!swipeDownReleased_) {
__CtrlButtonUp(button[g_Config.iSwipeDown-1]);
controllMapper_->pspKey(GestureKey::keyList[g_Config.iSwipeDown-1], KEY_UP);
swipeDownReleased_ = true;
}
}
Expand Down
148 changes: 93 additions & 55 deletions UI/GamepadEmu.h
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,30 @@ class ComboKey : public MultiTouchButton {
bool invertedContextDimension_; // Swap width and height
};

class GestureGamepad : public UI::View {
public:
GestureGamepad(ControlMapper* controllMapper) : controllMapper_(controllMapper) {};

void Touch(const TouchInput &input) override;
void Update() override;

protected:

float lastX_ = 0.0f;
float lastY_ = 0.0f;
float deltaX_ = 0.0f;
float deltaY_ = 0.0f;
float lastTapRelease_ = 0.0f;
float lastTouchDown_ = 0.0f;
int dragPointerId_ = -1;
bool swipeLeftReleased_ = true;
bool swipeRightReleased_ = true;
bool swipeUpReleased_ = true;
bool swipeDownReleased_ = true;
bool haveDoubleTapped_ = false;
ControlMapper* controllMapper_;
};

// Just edit this to add new image, shape or button function
namespace CustomKey {
// Image list
Expand Down Expand Up @@ -246,68 +270,82 @@ namespace CustomKey {

// Button list
struct keyList {
const char* n; // UI name
ImageID i; // UI ImageID
uint32_t c; // Key code
};
static const keyList comboKeyList[] = {
{ "Square", ImageID("I_SQUARE"), CTRL_SQUARE },
{ "Triangle", ImageID("I_TRIANGLE"), CTRL_TRIANGLE },
{ "Circle", ImageID("I_CIRCLE"), CTRL_CIRCLE },
{ "Cross", ImageID("I_CROSS"), CTRL_CROSS },
{ "Up", ImageID::invalid(), CTRL_UP },
{ "Down", ImageID::invalid(), CTRL_DOWN },
{ "Left", ImageID::invalid(), CTRL_LEFT },
{ "Right", ImageID::invalid(), CTRL_RIGHT },
{ "Start", ImageID("I_START"), CTRL_START },
{ "Select", ImageID("I_SELECT"), CTRL_SELECT },
{ "L", ImageID("I_L"), CTRL_LTRIGGER },
{ "R", ImageID("I_R"), CTRL_RTRIGGER },
{ "RapidFire", ImageID::invalid(), VIRTKEY_RAPID_FIRE },
{ "Fast-forward", ImageID::invalid(), VIRTKEY_FASTFORWARD },
{ "SpeedToggle", ImageID::invalid(), VIRTKEY_SPEED_TOGGLE },
{ "Rewind", ImageID::invalid(), VIRTKEY_REWIND },
{ "Save State", ImageID::invalid(), VIRTKEY_SAVE_STATE },
{ "Load State", ImageID::invalid(), VIRTKEY_LOAD_STATE },
{ "Next Slot", ImageID::invalid(), VIRTKEY_NEXT_SLOT },
{ "Toggle Fullscreen", ImageID::invalid(), VIRTKEY_TOGGLE_FULLSCREEN },
{ "Alt speed 1", ImageID::invalid(), VIRTKEY_SPEED_CUSTOM1 },
{ "Alt speed 2", ImageID::invalid(), VIRTKEY_SPEED_CUSTOM2 },
{ "Texture Dumping", ImageID::invalid(), VIRTKEY_TEXTURE_DUMP },
{ "Texture Replacement", ImageID::invalid(), VIRTKEY_TEXTURE_REPLACE },
{ "Screenshot", ImageID::invalid(), VIRTKEY_SCREENSHOT },
{ "Mute toggle", ImageID::invalid(), VIRTKEY_MUTE_TOGGLE },
{ "OpenChat", ImageID::invalid(), VIRTKEY_OPENCHAT },
{ "Auto Analog Rotation (CW)", ImageID::invalid(), VIRTKEY_ANALOG_ROTATE_CW },
{ "Auto Analog Rotation (CCW)", ImageID::invalid(), VIRTKEY_ANALOG_ROTATE_CCW },
{ "Pause", ImageID::invalid(), VIRTKEY_PAUSE },
{ "DevMenu", ImageID::invalid(), VIRTKEY_DEVMENU },
{ ImageID("I_SQUARE"), CTRL_SQUARE },
{ ImageID("I_TRIANGLE"), CTRL_TRIANGLE },
{ ImageID("I_CIRCLE"), CTRL_CIRCLE },
{ ImageID("I_CROSS"), CTRL_CROSS },
{ ImageID::invalid(), CTRL_UP },
{ ImageID::invalid(), CTRL_DOWN },
{ ImageID::invalid(), CTRL_LEFT },
{ ImageID::invalid(), CTRL_RIGHT },
{ ImageID("I_START"), CTRL_START },
{ ImageID("I_SELECT"), CTRL_SELECT },
{ ImageID("I_L"), CTRL_LTRIGGER },
{ ImageID("I_R"), CTRL_RTRIGGER },
{ ImageID::invalid(), VIRTKEY_RAPID_FIRE },
{ ImageID::invalid(), VIRTKEY_FASTFORWARD },
{ ImageID::invalid(), VIRTKEY_SPEED_TOGGLE },
{ ImageID::invalid(), VIRTKEY_REWIND },
{ ImageID::invalid(), VIRTKEY_SAVE_STATE },
{ ImageID::invalid(), VIRTKEY_LOAD_STATE },
{ ImageID::invalid(), VIRTKEY_NEXT_SLOT },
{ ImageID::invalid(), VIRTKEY_TOGGLE_FULLSCREEN },
{ ImageID::invalid(), VIRTKEY_SPEED_CUSTOM1 },
{ ImageID::invalid(), VIRTKEY_SPEED_CUSTOM2 },
{ ImageID::invalid(), VIRTKEY_TEXTURE_DUMP },
{ ImageID::invalid(), VIRTKEY_TEXTURE_REPLACE },
{ ImageID::invalid(), VIRTKEY_SCREENSHOT },
{ ImageID::invalid(), VIRTKEY_MUTE_TOGGLE },
{ ImageID::invalid(), VIRTKEY_OPENCHAT },
{ ImageID::invalid(), VIRTKEY_ANALOG_ROTATE_CW },
{ ImageID::invalid(), VIRTKEY_ANALOG_ROTATE_CCW },
{ ImageID::invalid(), VIRTKEY_PAUSE },
{ ImageID::invalid(), VIRTKEY_DEVMENU },
#ifndef MOBILE_DEVICE
{ "Record", ImageID::invalid(), VIRTKEY_RECORD },
{ ImageID::invalid(), VIRTKEY_RECORD },
#endif
};
static_assert(ARRAY_SIZE(comboKeyList) <= 64, "Too many key for a uint64_t bit mask");
};

class GestureGamepad : public UI::View {
public:
GestureGamepad() {};

void Touch(const TouchInput &input) override;
void Update() override;

protected:

float lastX_ = 0.0f;
float lastY_ = 0.0f;
float deltaX_ = 0.0f;
float deltaY_ = 0.0f;
float lastTapRelease_ = 0.0f;
float lastTouchDown_ = 0.0f;
int dragPointerId_ = -1;
bool swipeLeftReleased_ = true;
bool swipeRightReleased_ = true;
bool swipeUpReleased_ = true;
bool swipeDownReleased_ = true;
bool haveDoubleTapped_ = false;
};
// Gesture key only have virtual button that can work without constant press
namespace GestureKey {
static const uint32_t keyList[] = {
CTRL_SQUARE,
CTRL_TRIANGLE,
CTRL_CIRCLE,
CTRL_CROSS,
CTRL_UP,
CTRL_DOWN,
CTRL_LEFT,
CTRL_RIGHT,
CTRL_START,
CTRL_SELECT,
CTRL_LTRIGGER,
CTRL_RTRIGGER,
VIRTKEY_AXIS_Y_MAX,
VIRTKEY_AXIS_Y_MIN,
VIRTKEY_AXIS_X_MIN,
VIRTKEY_AXIS_X_MAX,
VIRTKEY_SPEED_TOGGLE,
VIRTKEY_REWIND,
VIRTKEY_SAVE_STATE,
VIRTKEY_LOAD_STATE,
VIRTKEY_NEXT_SLOT,
VIRTKEY_TOGGLE_FULLSCREEN,
VIRTKEY_TEXTURE_DUMP,
VIRTKEY_TEXTURE_REPLACE,
VIRTKEY_SCREENSHOT,
VIRTKEY_MUTE_TOGGLE,
VIRTKEY_OPENCHAT,
VIRTKEY_PAUSE,
VIRTKEY_DEVMENU,
#ifndef MOBILE_DEVICE
VIRTKEY_RECORD,
#endif
};
}