aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorArisotura <thetotalworm@gmail.com>2020-05-19 20:48:52 +0200
committerArisotura <thetotalworm@gmail.com>2020-05-19 20:48:52 +0200
commit34506ff2bb1be880cf260e0c1b09efede14ac0d8 (patch)
treeeed432ef9eaf56dbb5368b54f1d71863368ea87c /src
parent920ff9778d3fbdd18576ab473cca6212ee387cb1 (diff)
actually complete the input config dialog
Diffstat (limited to 'src')
-rw-r--r--src/frontend/qt_sdl/CMakeLists.txt1
-rw-r--r--src/frontend/qt_sdl/Input.cpp119
-rw-r--r--src/frontend/qt_sdl/Input.h40
-rw-r--r--src/frontend/qt_sdl/InputConfigDialog.cpp283
-rw-r--r--src/frontend/qt_sdl/InputConfigDialog.h32
-rw-r--r--src/frontend/qt_sdl/main.cpp15
-rw-r--r--src/frontend/qt_sdl/main.h21
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