diff options
| author | Arisotura <thetotalworm@gmail.com> | 2020-05-19 20:48:52 +0200 | 
|---|---|---|
| committer | Arisotura <thetotalworm@gmail.com> | 2020-05-19 20:48:52 +0200 | 
| commit | 34506ff2bb1be880cf260e0c1b09efede14ac0d8 (patch) | |
| tree | eed432ef9eaf56dbb5368b54f1d71863368ea87c /src | |
| parent | 920ff9778d3fbdd18576ab473cca6212ee387cb1 (diff) | |
actually complete the input config dialog
Diffstat (limited to 'src')
| -rw-r--r-- | src/frontend/qt_sdl/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | src/frontend/qt_sdl/Input.cpp | 119 | ||||
| -rw-r--r-- | src/frontend/qt_sdl/Input.h | 40 | ||||
| -rw-r--r-- | src/frontend/qt_sdl/InputConfigDialog.cpp | 283 | ||||
| -rw-r--r-- | src/frontend/qt_sdl/InputConfigDialog.h | 32 | ||||
| -rw-r--r-- | src/frontend/qt_sdl/main.cpp | 15 | ||||
| -rw-r--r-- | src/frontend/qt_sdl/main.h | 21 | 
7 files changed, 425 insertions, 86 deletions
| diff --git a/src/frontend/qt_sdl/CMakeLists.txt b/src/frontend/qt_sdl/CMakeLists.txt index da3bb1d..42cf912 100644 --- a/src/frontend/qt_sdl/CMakeLists.txt +++ b/src/frontend/qt_sdl/CMakeLists.txt @@ -4,6 +4,7 @@ SET(SOURCES_QT_SDL  	main.cpp  	EmuSettingsDialog.cpp  	InputConfigDialog.cpp +	Input.cpp  	Platform.cpp  	PlatformConfig.cpp diff --git a/src/frontend/qt_sdl/Input.cpp b/src/frontend/qt_sdl/Input.cpp new file mode 100644 index 0000000..7caf24a --- /dev/null +++ b/src/frontend/qt_sdl/Input.cpp @@ -0,0 +1,119 @@ +/* +    Copyright 2016-2020 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/. +*/ + +#include <QKeyEvent> +#include <SDL2/SDL.h> + +#include "Input.h" +#include "PlatformConfig.h" + + +namespace Input +{ + +int JoystickID; +SDL_Joystick* Joystick = nullptr; + +u32 KeyInputMask, JoyInputMask; +u32 KeyHotkeyMask, JoyHotkeyMask; +u32 HotkeyMask, LastHotkeyMask; +u32 HotkeyPress, HotkeyRelease; + + +void OpenJoystick() +{ +    if (Joystick) SDL_JoystickClose(Joystick); + +    int num = SDL_NumJoysticks(); +    if (num < 1) +    { +        Joystick = nullptr; +        return; +    } + +    if (JoystickID >= num) +        JoystickID = 0; + +    Joystick = SDL_JoystickOpen(JoystickID); +} + +void CloseJoystick() +{ +    if (Joystick) +    { +        SDL_JoystickClose(Joystick); +        Joystick = nullptr; +    } +} + + +void Process() +{ +    SDL_JoystickUpdate(); + +    if (Joystick) +    { +        if (!SDL_JoystickGetAttached(Joystick)) +        { +            SDL_JoystickClose(Joystick); +            Joystick = NULL; +        } +    } +    if (!Joystick && (SDL_NumJoysticks() > 0)) +    { +        JoystickID = Config::JoystickID; +        OpenJoystick(); +    } + +    /*JoyInputMask = 0xFFF; +    for (int i = 0; i < 12; i++) +        if (JoystickButtonDown(Config::JoyMapping[i])) +            JoyInputMask &= ~(1<<i); + +    JoyHotkeyMask = 0; +    for (int i = 0; i < HK_MAX; i++) +        if (JoystickButtonDown(Config::HKJoyMapping[i])) +            JoyHotkeyMask |= (1<<i); + +    HotkeyMask = KeyHotkeyMask | JoyHotkeyMask; +    HotkeyPress = HotkeyMask & ~LastHotkeyMask; +    HotkeyRelease = LastHotkeyMask & ~HotkeyMask; +    LastHotkeyMask = HotkeyMask;*/ +} + + +// TODO: MacOS version of this! +// distinguish between left and right modifier keys (Ctrl, Alt, Shift) +// Qt provides no real cross-platform way to do this, so here we go +// for Windows and Linux we can distinguish via scancodes (but both +// provide different scancodes) +#ifdef __WIN32__ +bool IsRightModKey(QKeyEvent* event) +{ +    quint32 scan = event->nativeScanCode(); +    return (scan == 0x11D || scan == 0x138 || scan == 0x36); +} +#else +bool IsRightModKey(QKeyEvent* event) +{ +    quint32 scan = event->nativeScanCode(); +    return (scan == 0x69 || scan == 0x6C || scan == 0x3E); +} +#endif + +} diff --git a/src/frontend/qt_sdl/Input.h b/src/frontend/qt_sdl/Input.h new file mode 100644 index 0000000..24ec3a7 --- /dev/null +++ b/src/frontend/qt_sdl/Input.h @@ -0,0 +1,40 @@ +/* +    Copyright 2016-2020 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 INPUT_H +#define INPUT_H + +#include "types.h" + +namespace Input +{ + +extern int JoystickID; +extern SDL_Joystick* Joystick; + +// set joystickID before calling openJoystick() +void OpenJoystick(); +void CloseJoystick(); + +void Process(); + +bool IsRightModKey(QKeyEvent* event); + +} + +#endif // INPUT_H diff --git a/src/frontend/qt_sdl/InputConfigDialog.cpp b/src/frontend/qt_sdl/InputConfigDialog.cpp index 93204aa..2c0afc4 100644 --- a/src/frontend/qt_sdl/InputConfigDialog.cpp +++ b/src/frontend/qt_sdl/InputConfigDialog.cpp @@ -20,11 +20,13 @@  #include <QLabel>  #include <QKeyEvent> +#include <SDL2/SDL.h> +  #include "types.h"  #include "Config.h"  #include "PlatformConfig.h" -#include "main.h" +#include "Input.h"  #include "InputConfigDialog.h"  #include "ui_InputConfigDialog.h" @@ -93,6 +95,22 @@ InputConfigDialog::InputConfigDialog(QWidget* parent) : QDialog(parent), ui(new      populatePage(ui->tabInput, 12, dskeylabels, keypadKeyMap, keypadJoyMap);      populatePage(ui->tabAddons, 2, hk_addons_labels, addonsKeyMap, addonsJoyMap);      populatePage(ui->tabHotkeysGeneral, 6, hk_general_labels, hkGeneralKeyMap, hkGeneralJoyMap); + +    int njoy = SDL_NumJoysticks(); +    if (njoy > 0) +    { +        for (int i = 0; i < njoy; i++) +        { +            const char* name = SDL_JoystickNameForIndex(i); +            ui->cbxJoystick->addItem(QString(name)); +        } +        ui->cbxJoystick->setCurrentIndex(Input::JoystickID); +    } +    else +    { +        ui->cbxJoystick->addItem("(no joysticks available)"); +        ui->cbxJoystick->setEnabled(false); +    }  }  InputConfigDialog::~InputConfigDialog() @@ -117,7 +135,7 @@ void InputConfigDialog::populatePage(QWidget* page, int num, const char** labels      for (int i = 0; i < num; i++)      {          QLabel* label = new QLabel(QString(labels[i])+":"); -        KeyMapButton* btn = new KeyMapButton(nullptr, &keymap[i], ishotkey); +        KeyMapButton* btn = new KeyMapButton(&keymap[i], ishotkey);          group_layout->addWidget(label, i, 0);          group_layout->addWidget(btn, i, 1); @@ -133,15 +151,10 @@ void InputConfigDialog::populatePage(QWidget* page, int num, const char** labels      for (int i = 0; i < num; i++)      {          QLabel* label = new QLabel(QString(labels[i])+":"); -        QPushButton* btn = new QPushButton(); +        JoyMapButton* btn = new JoyMapButton(&joymap[i], ishotkey);          group_layout->addWidget(label, i, 0);          group_layout->addWidget(btn, i, 1); - -        btn->setText(joyMappingName(joymap[i])); - -        //btn->setProperty("mapping", QVariant(&joymap[i])); -        //btn->setProperty("isHotkey", QVariant(ishotkey));      }      group_layout->setRowStretch(num, 1);      group->setLayout(group_layout); @@ -150,71 +163,48 @@ void InputConfigDialog::populatePage(QWidget* page, int num, const char** labels      page->setLayout(main_layout);  } -QString InputConfigDialog::joyMappingName(int id) +void InputConfigDialog::on_InputConfigDialog_accepted()  { -    if (id < 0) +    for (int i = 0; i < 12; i++)      { -        return "None"; +        Config::KeyMapping[dskeyorder[i]] = keypadKeyMap[i]; +        Config::JoyMapping[dskeyorder[i]] = keypadJoyMap[i];      } -    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 +    for (int i = 0; i < 2; i++)      { -        str = ""; +        Config::HKKeyMapping[hk_addons[i]] = addonsKeyMap[i]; +        Config::HKJoyMapping[hk_addons[i]] = addonsJoyMap[i];      } -    if (id & 0x10000) +    for (int i = 0; i < 6; i++)      { -        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; -        } +        Config::HKKeyMapping[hk_general[i]] = hkGeneralKeyMap[i]; +        Config::HKJoyMapping[hk_general[i]] = hkGeneralJoyMap[i];      } -    return str; -} +    Config::JoystickID = Input::JoystickID; +    Config::Save(); -void InputConfigDialog::on_InputConfigDialog_accepted() -{      closeDlg();  }  void InputConfigDialog::on_InputConfigDialog_rejected()  { +    Input::JoystickID = Config::JoystickID; +    Input::OpenJoystick(); +      closeDlg();  } +void InputConfigDialog::on_cbxJoystick_currentIndexChanged(int id) +{ +    Input::JoystickID = id; +    Input::OpenJoystick(); +} + -KeyMapButton::KeyMapButton(QWidget* parent, int* mapping, bool hotkey) : QPushButton(parent) +KeyMapButton::KeyMapButton(int* mapping, bool hotkey) : QPushButton()  {      this->mapping = mapping;      this->isHotkey = hotkey; @@ -257,7 +247,7 @@ void KeyMapButton::keyPressEvent(QKeyEvent* event)      if (!ismod)          key |= mod; -    else if (IsRightModKey(event)) +    else if (Input::IsRightModKey(event))          key |= (1<<31);      *mapping = key; @@ -314,3 +304,188 @@ QString KeyMapButton::mappingText()      return ret.replace("&", "&&");  } + + +JoyMapButton::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::~JoyMapButton() +{ +} + +void JoyMapButton::keyPressEvent(QKeyEvent* event) +{ +    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 JoyMapButton::focusOutEvent(QFocusEvent* event) +{ +    if (isChecked()) +    { +        // if we lost the focus while mapping, consider it 'done' +        click(); +    } + +    QPushButton::focusOutEvent(event); +} + +void JoyMapButton::timerEvent(QTimerEvent* event) +{ +    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; +        } +    } +} + +void JoyMapButton::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; } +    } +} + +QString JoyMapButton::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; +} diff --git a/src/frontend/qt_sdl/InputConfigDialog.h b/src/frontend/qt_sdl/InputConfigDialog.h index b2ca3f2..82e37bc 100644 --- a/src/frontend/qt_sdl/InputConfigDialog.h +++ b/src/frontend/qt_sdl/InputConfigDialog.h @@ -55,13 +55,11 @@ private slots:      void on_InputConfigDialog_accepted();      void on_InputConfigDialog_rejected(); -    // +    void on_cbxJoystick_currentIndexChanged(int id);  private:      void populatePage(QWidget* page, int num, const char** labels, int* keymap, int* joymap); -    QString joyMappingName(int id); -      Ui::InputConfigDialog* ui;      int keypadKeyMap[12],   keypadJoyMap[12]; @@ -75,7 +73,7 @@ class KeyMapButton : public QPushButton      Q_OBJECT  public: -    explicit KeyMapButton(QWidget* parent, int* mapping, bool hotkey); +    explicit KeyMapButton(int* mapping, bool hotkey);      ~KeyMapButton();  protected: @@ -92,4 +90,30 @@ private:      bool isHotkey;  }; +class JoyMapButton : public QPushButton +{ +    Q_OBJECT + +public: +    explicit JoyMapButton(int* mapping, bool hotkey); +    ~JoyMapButton(); + +protected: +    void keyPressEvent(QKeyEvent* event) override; +    void focusOutEvent(QFocusEvent* event) override; +    void timerEvent(QTimerEvent* event) override; + +private slots: +    void onClick(); + +private: +    QString mappingText(); + +    int* mapping; +    bool isHotkey; + +    int timerID; +    int axesRest[16]; +}; +  #endif // INPUTCONFIGDIALOG_H diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index 7b50af4..8fe776e 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -27,10 +27,12 @@  #include <QFileDialog>  #include <QPaintEvent>  #include <QPainter> +#include <QKeyEvent>  #include <SDL2/SDL.h>  #include "main.h" +#include "Input.h"  #include "EmuSettingsDialog.h"  #include "InputConfigDialog.h" @@ -136,12 +138,6 @@ void EmuThread::run()      }      /*Touching = false; -    KeyInputMask = 0xFFF; -    JoyInputMask = 0xFFF; -    KeyHotkeyMask = 0; -    JoyHotkeyMask = 0; -    HotkeyMask = 0; -    LastHotkeyMask = 0;      LidStatus = false;*/      u32 nframes = 0; @@ -154,6 +150,7 @@ void EmuThread::run()      while (EmuRunning != 0)      { +        Input::Process();          /*ProcessInput();          if (HotkeyPressed(HK_FastForwardToggle)) @@ -999,6 +996,9 @@ int main(int argc, char** argv)      Frontend::Init_ROM();      Frontend::Init_Audio(audioFreq); +    Input::JoystickID = Config::JoystickID; +    Input::OpenJoystick(); +      mainWindow = new MainWindow();      mainWindow->show(); @@ -1047,7 +1047,8 @@ int main(int argc, char** argv)      emuThread->wait();      delete emuThread; -    //if (Joystick) SDL_JoystickClose(Joystick); +    Input::CloseJoystick(); +      if (audioDevice) SDL_CloseAudioDevice(audioDevice);      //if (MicDevice)   SDL_CloseAudioDevice(MicDevice); diff --git a/src/frontend/qt_sdl/main.h b/src/frontend/qt_sdl/main.h index 5d6638c..4553875 100644 --- a/src/frontend/qt_sdl/main.h +++ b/src/frontend/qt_sdl/main.h @@ -23,7 +23,6 @@  #include <QWidget>  #include <QMainWindow>  #include <QImage> -#include <QKeyEvent>  class EmuThread : public QThread @@ -132,24 +131,4 @@ private:      QAction* actInputConfig;  }; - -// TODO: MacOS version of this! -// distinguish between left and right modifier keys (Ctrl, Alt, Shift) -// Qt provides no real cross-platform way to do this, so here we go -// for Windows and Linux we can distinguish via scancodes (but both -// provide different scancodes) -#ifdef __WIN32__ -inline bool IsRightModKey(QKeyEvent* event) -{ -    quint32 scan = event->nativeScanCode(); -    return (scan == 0x11D || scan == 0x138 || scan == 0x36); -} -#else -inline bool IsRightModKey(QKeyEvent* event) -{ -    quint32 scan = event->nativeScanCode(); -    return (scan == 0x69 || scan == 0x6C || scan == 0x3E); -} -#endif -  #endif // MAIN_H |