diff options
Diffstat (limited to 'src/frontend/qt_sdl/InputConfig/MapButton.h')
-rw-r--r-- | src/frontend/qt_sdl/InputConfig/MapButton.h | 355 |
1 files changed, 355 insertions, 0 deletions
diff --git a/src/frontend/qt_sdl/InputConfig/MapButton.h b/src/frontend/qt_sdl/InputConfig/MapButton.h new file mode 100644 index 0000000..a1b1a16 --- /dev/null +++ b/src/frontend/qt_sdl/InputConfig/MapButton.h @@ -0,0 +1,355 @@ +/* + Copyright 2016-2021 Arisotura + + This file is part of melonDS. + + melonDS is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + melonDS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#ifndef MAPBUTTON_H +#define MAPBUTTON_H + +#include <QPushButton> + +#include <SDL2/SDL.h> + +#include "Input.h" + +class KeyMapButton : public QPushButton +{ + Q_OBJECT + +public: + KeyMapButton(int* mapping, bool hotkey) : QPushButton() + { + this->mapping = mapping; + this->isHotkey = hotkey; + + setCheckable(true); + setText(mappingText()); + setFocusPolicy(Qt::StrongFocus); //Fixes binding keys in macOS + + connect(this, &KeyMapButton::clicked, this, &KeyMapButton::onClick); + } + + ~KeyMapButton() + { + } + +protected: + void keyPressEvent(QKeyEvent* event) override + { + if (!isChecked()) return QPushButton::keyPressEvent(event); + + printf("KEY PRESSED = %08X %08X | %08X %08X %08X\n", event->key(), (int)event->modifiers(), event->nativeVirtualKey(), event->nativeModifiers(), event->nativeScanCode()); + + int key = event->key(); + int mod = event->modifiers(); + bool ismod = (key == Qt::Key_Control || + key == Qt::Key_Alt || + key == Qt::Key_AltGr || + key == Qt::Key_Shift || + key == Qt::Key_Meta); + + if (!mod) + { + if (key == Qt::Key_Escape) { click(); return; } + if (key == Qt::Key_Backspace) { *mapping = -1; click(); return; } + } + + if (isHotkey) + { + if (ismod) + return; + } + + if (!ismod) + key |= mod; + else if (Input::IsRightModKey(event)) + key |= (1<<31); + + *mapping = key; + click(); + } + + void focusOutEvent(QFocusEvent* event) override + { + if (isChecked()) + { + // if we lost the focus while mapping, consider it 'done' + click(); + } + + QPushButton::focusOutEvent(event); + } + + bool focusNextPrevChild(bool next) override { return false; } + +private slots: + void onClick() + { + if (isChecked()) + { + setText("[press key]"); + } + else + { + setText(mappingText()); + } + } + +private: + QString mappingText() + { + int key = *mapping; + + if (key == -1) return "None"; + + QString isright = (key & (1<<31)) ? "Right " : "Left "; + key &= ~(1<<31); + + #ifndef __APPLE__ + switch (key) + { + case Qt::Key_Control: return isright + "Ctrl"; + case Qt::Key_Alt: return "Alt"; + case Qt::Key_AltGr: return "AltGr"; + case Qt::Key_Shift: return isright + "Shift"; + case Qt::Key_Meta: return "Meta"; + } + #else + switch (key) + { + case Qt::Key_Control: return isright + "⌘"; + case Qt::Key_Alt: return isright + "⌥"; + case Qt::Key_Shift: return isright + "⇧"; + case Qt::Key_Meta: return isright + "⌃"; + } + #endif + + QKeySequence seq(key); + QString ret = seq.toString(QKeySequence::NativeText); + + // weak attempt at detecting garbage key names + //if (ret.length() == 2 && ret[0].unicode() > 0xFF) + // return QString("[%1]").arg(key, 8, 16); + + return ret.replace("&", "&&"); + } + + int* mapping; + bool isHotkey; +}; + +class JoyMapButton : public QPushButton +{ + Q_OBJECT + +public: + JoyMapButton(int* mapping, bool hotkey) : QPushButton() + { + this->mapping = mapping; + this->isHotkey = hotkey; + + setCheckable(true); + setText(mappingText()); + + connect(this, &JoyMapButton::clicked, this, &JoyMapButton::onClick); + + timerID = 0; + } + + ~JoyMapButton() + { + } + +protected: + void keyPressEvent(QKeyEvent* event) override + { + if (!isChecked()) return QPushButton::keyPressEvent(event); + + int key = event->key(); + int mod = event->modifiers(); + + if (!mod) + { + if (key == Qt::Key_Escape) { click(); return; } + if (key == Qt::Key_Backspace) { *mapping = -1; click(); return; } + } + } + + void focusOutEvent(QFocusEvent* event) override + { + if (isChecked()) + { + // if we lost the focus while mapping, consider it 'done' + click(); + } + + QPushButton::focusOutEvent(event); + } + + void timerEvent(QTimerEvent* event) override + { + SDL_Joystick* joy = Input::Joystick; + if (!joy) { click(); return; } + if (!SDL_JoystickGetAttached(joy)) { click(); return; } + + int oldmap; + if (*mapping == -1) oldmap = 0xFFFF; + else oldmap = *mapping; + + int nbuttons = SDL_JoystickNumButtons(joy); + for (int i = 0; i < nbuttons; i++) + { + if (SDL_JoystickGetButton(joy, i)) + { + *mapping = (oldmap & 0xFFFF0000) | i; + click(); + return; + } + } + + int nhats = SDL_JoystickNumHats(joy); + if (nhats > 16) nhats = 16; + for (int i = 0; i < nhats; i++) + { + Uint8 blackhat = SDL_JoystickGetHat(joy, i); + if (blackhat) + { + if (blackhat & 0x1) blackhat = 0x1; + else if (blackhat & 0x2) blackhat = 0x2; + else if (blackhat & 0x4) blackhat = 0x4; + else blackhat = 0x8; + + *mapping = (oldmap & 0xFFFF0000) | 0x100 | blackhat | (i << 4); + click(); + return; + } + } + + int naxes = SDL_JoystickNumAxes(joy); + if (naxes > 16) naxes = 16; + for (int i = 0; i < naxes; i++) + { + Sint16 axisval = SDL_JoystickGetAxis(joy, i); + int diff = abs(axisval - axesRest[i]); + + if (axesRest[i] < -16384 && axisval >= 0) + { + *mapping = (oldmap & 0xFFFF) | 0x10000 | (2 << 20) | (i << 24); + click(); + return; + } + else if (diff > 16384) + { + int axistype; + if (axisval > 0) axistype = 0; + else axistype = 1; + + *mapping = (oldmap & 0xFFFF) | 0x10000 | (axistype << 20) | (i << 24); + click(); + return; + } + } + } + + bool focusNextPrevChild(bool next) override { return false; } + +private slots: + void onClick() + { + if (isChecked()) + { + setText("[press button/axis]"); + timerID = startTimer(50); + + memset(axesRest, 0, sizeof(axesRest)); + if (Input::Joystick && SDL_JoystickGetAttached(Input::Joystick)) + { + int naxes = SDL_JoystickNumAxes(Input::Joystick); + if (naxes > 16) naxes = 16; + for (int a = 0; a < naxes; a++) + { + axesRest[a] = SDL_JoystickGetAxis(Input::Joystick, a); + } + } + } + else + { + setText(mappingText()); + if (timerID) { killTimer(timerID); timerID = 0; } + } + } + +private: + QString mappingText() + { + int id = *mapping; + + if (id == -1) return "None"; + + bool hasbtn = ((id & 0xFFFF) != 0xFFFF); + QString str; + + if (hasbtn) + { + if (id & 0x100) + { + int hatnum = ((id >> 4) & 0xF) + 1; + + switch (id & 0xF) + { + case 0x1: str = "Hat %1 up"; break; + case 0x2: str = "Hat %1 right"; break; + case 0x4: str = "Hat %1 down"; break; + case 0x8: str = "Hat %1 left"; break; + } + + str = str.arg(hatnum); + } + else + { + str = QString("Button %1").arg((id & 0xFFFF) + 1); + } + } + else + { + str = ""; + } + + if (id & 0x10000) + { + int axisnum = ((id >> 24) & 0xF) + 1; + + if (hasbtn) str += " / "; + + switch ((id >> 20) & 0xF) + { + case 0: str += QString("Axis %1 +").arg(axisnum); break; + case 1: str += QString("Axis %1 -").arg(axisnum); break; + case 2: str += QString("Trigger %1").arg(axisnum); break; + } + } + + return str; + } + + int* mapping; + bool isHotkey; + + int timerID; + int axesRest[16]; +}; + +#endif // MAPBUTTON_H
\ No newline at end of file |