From 5c28b6dbf7aa20441c8a51f484f4f64b1966f7e3 Mon Sep 17 00:00:00 2001 From: Shamus Hammons Date: Sat, 12 Jan 2013 22:15:25 -0600 Subject: [PATCH] More gamepad work. Gamepad configuration and usability is now working, though there are some limitations: you must be careful to configure the pads you want to be pad 1 & 2. You can mix keyboard keys, but not have multiply defined keys (yet). There is no joypad specific configuration, though that may come in the future if there is demand for it. --- src/gui/app.cpp | 3 + src/gui/controllertab.cpp | 3 + src/gui/controllerwidget.cpp | 27 ++++++++ src/gui/controllerwidget.h | 1 + src/gui/debug/cpubrowser.cpp | 2 +- src/gui/gamepad.cpp | 127 ++++++++++++++++++++++++++++++++++- src/gui/gamepad.h | 34 +++++++--- src/gui/keygrabber.cpp | 42 +++++++++++- src/gui/keygrabber.h | 8 ++- src/gui/mainwin.cpp | 25 +++++-- src/gui/mainwin.h | 1 + 11 files changed, 253 insertions(+), 20 deletions(-) diff --git a/src/gui/app.cpp b/src/gui/app.cpp index cbe6051..3961d31 100644 --- a/src/gui/app.cpp +++ b/src/gui/app.cpp @@ -18,6 +18,7 @@ #include #include +#include "gamepad.h" #include "log.h" #include "mainwin.h" #include "settings.h" @@ -97,7 +98,9 @@ int main(int argc, char * argv[]) { WriteLog("VJ: SDL (joystick, audio) successfully initialized.\n"); App app(argc, argv); // Declare an instance of the application + Gamepad::AllocateJoysticks(); retVal = app.exec(); // And run it! + Gamepad::DeallocateJoysticks(); // Free SDL components last...! SDL_QuitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_AUDIO); diff --git a/src/gui/controllertab.cpp b/src/gui/controllertab.cpp index 957e568..ce09270 100644 --- a/src/gui/controllertab.cpp +++ b/src/gui/controllertab.cpp @@ -33,10 +33,12 @@ ControllerTab::ControllerTab(QWidget * parent/*= 0*/): QWidget(parent) connect(redefineAll, SIGNAL(clicked()), this, SLOT(DefineAllKeys())); } + ControllerTab::~ControllerTab() { } + void ControllerTab::DefineAllKeys(void) { // char jagButtonName[21][10] = { "Up", "Down", "Left", "Right", @@ -60,3 +62,4 @@ void ControllerTab::DefineAllKeys(void) controllerWidget->update(); } } + diff --git a/src/gui/controllerwidget.cpp b/src/gui/controllerwidget.cpp index 25fb8b1..79e91b6 100644 --- a/src/gui/controllerwidget.cpp +++ b/src/gui/controllerwidget.cpp @@ -15,8 +15,10 @@ #include "controllerwidget.h" #include "joystick.h" +#include "gamepad.h" #include "keygrabber.h" + // These tables are used to convert Qt keycodes into human readable form. Note that // a lot of these are just filler. char ControllerWidget::keyName1[96][16] = { @@ -40,6 +42,8 @@ char ControllerWidget::keyName2[64][16] = { "F14", "F15", "F16" }; +char ControllerWidget::hatName[4][16] = { "Up", "Rt", "Dn", "Lf" }; + // This is hard-coded crap. It's crap-tastic! // These are the positions to draw the button names at, ordered by the BUTTON_* sequence // found in joystick.h. @@ -50,6 +54,7 @@ int ControllerWidget::buttonPos[21][2] = { { 74, 32 }, { 71, 67 }, { 53, 49 }, { { 234, 31 }, { 216, 51 }, { 199, 71 }, { 164-11, 101-30 }, { 141-11, 108+13-30 } }; + ControllerWidget::ControllerWidget(QWidget * parent/*= 0*/): QWidget(parent), controllerPic(":/res/controller.png"), widgetSize(controllerPic.size()), keyToHighlight(-1), mouseDown(false) @@ -60,20 +65,24 @@ ControllerWidget::ControllerWidget(QWidget * parent/*= 0*/): QWidget(parent), setMouseTracking(true); } + ControllerWidget::~ControllerWidget() { } + QSize ControllerWidget::sizeHint(void) const { return widgetSize; } + QSizePolicy ControllerWidget::sizePolicy(void) const { return QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); } + void ControllerWidget::paintEvent(QPaintEvent * /*event*/) { QPainter painter(this); @@ -127,17 +136,31 @@ void ControllerWidget::paintEvent(QPaintEvent * /*event*/) DrawBorderedText(painter, buttonPos[i][0], buttonPos[i][1], QString(keyName2[keys[i] & 0x3F])); } +#if 1 + else if (keys[i] & JOY_BUTTON) + { + DrawBorderedText(painter, buttonPos[i][0], buttonPos[i][1], + QString("JB%1").arg(keys[i] & JOY_BUTTON_MASK)); + } + else if (keys[i] & JOY_HAT) + { + DrawBorderedText(painter, buttonPos[i][0], buttonPos[i][1], + QString("j%1").arg(hatName[keys[i] & JOY_BUTTON_MASK])); + } +#endif else DrawBorderedText(painter, buttonPos[i][0], buttonPos[i][1], QString("???")); } } + void ControllerWidget::mousePressEvent(QMouseEvent * /*event*/) { mouseDown = true; update(); } + void ControllerWidget::mouseReleaseEvent(QMouseEvent * /*event*/) { mouseDown = false; @@ -156,6 +179,7 @@ void ControllerWidget::mouseReleaseEvent(QMouseEvent * /*event*/) update(); } + void ControllerWidget::mouseMoveEvent(QMouseEvent * event) { if (mouseDown) @@ -184,12 +208,14 @@ void ControllerWidget::mouseMoveEvent(QMouseEvent * event) update(); } + void ControllerWidget::leaveEvent(QEvent * /*event*/) { keyToHighlight = -1; update(); } + void ControllerWidget::DrawBorderedText(QPainter & painter, int x, int y, QString text) { // Text is drawn centered at (x, y) as well, using a bounding rect for the purpose. @@ -210,3 +236,4 @@ void ControllerWidget::DrawBorderedText(QPainter & painter, int x, int y, QStrin rect.moveCenter(QPoint(x, y)); painter.drawText(rect, Qt::AlignCenter, text); } + diff --git a/src/gui/controllerwidget.h b/src/gui/controllerwidget.h index cf42469..eada2d6 100644 --- a/src/gui/controllerwidget.h +++ b/src/gui/controllerwidget.h @@ -36,6 +36,7 @@ class ControllerWidget: public QWidget // Class data static char keyName1[96][16]; static char keyName2[64][16]; + static char hatName[4][16]; static int buttonPos[21][2]; }; diff --git a/src/gui/debug/cpubrowser.cpp b/src/gui/debug/cpubrowser.cpp index 8df1878..3871dbc 100644 --- a/src/gui/debug/cpubrowser.cpp +++ b/src/gui/debug/cpubrowser.cpp @@ -32,7 +32,7 @@ CPUBrowserWindow::CPUBrowserWindow(QWidget * parent/*= 0*/): QWidget(parent, Qt: // Need to set the size as well... // resize(560, 480); - QFont fixedFont("Lucida Console", 10, QFont::Normal); + QFont fixedFont("Lucida Console", 8, QFont::Normal); text->setFont(fixedFont); //// layout->setSizeConstraint(QLayout::SetFixedSize); setLayout(layout); diff --git a/src/gui/gamepad.cpp b/src/gui/gamepad.cpp index ba8a551..6ca2329 100644 --- a/src/gui/gamepad.cpp +++ b/src/gui/gamepad.cpp @@ -12,19 +12,81 @@ // #include "gamepad.h" +#include "log.h" + + +// Class member initialization +/*static*/ int Gamepad::numJoysticks = 0; +/*static*/ SDL_Joystick * Gamepad::pad[8]; +/*static*/ int Gamepad::numButtons[8]; +/*static*/ int Gamepad::numHats[8]; +/*static*/ bool Gamepad::button[8][256]; +/*static*/ uint8_t Gamepad::hat[8][32]; + + +Gamepad::Gamepad(void)//: numJoysticks(0) +{ + AllocateJoysticks(); +} + + +Gamepad::~Gamepad(void) +{ + DeallocateJoysticks(); +} + + +void Gamepad::AllocateJoysticks(void) +{ +// DeallocateJoysticks(); + numJoysticks = SDL_NumJoysticks(); + + // Sanity check + if (numJoysticks > 8) + numJoysticks = 8; + + for(int i=0; i> 3; - int hatDirection = hatMask[buttonID & JOY_HATBUT_MASK]; + uint8_t hatDirection = hatMask[buttonID & JOY_HATBUT_MASK]; +// uint8 direction = SDL_JoystickGetHat(pad[joystickID], hatNumber); +// return ( + return (hat[joystickID][hatNumber] & hatDirection ? true : false); } // Default == failure @@ -32,14 +94,77 @@ bool Gamepad::GetState(int joystickID, int buttonID) } +int Gamepad::CheckButtonPressed(void) +{ + // This translates the hat direction to a mask index. + int hatNum[16] = { -1, 0, 1, -1, 2, -1, -1, -1, + 3, -1, -1, -1, -1, -1, -1, -1 }; + + // Return single button ID being pressed (if any) + for(int i=0; i - -uint8_t hatMask[8] = { 1, 2, 4, 8, 16, 32, 64, 128 }; +#include "SDL.h" // buttonID is the combination of the type (BUTTON, HAT) and the button # // (0-255 for buttons, 0-31 for hats). Hats also have 0-7 for a button # @@ -31,9 +32,22 @@ class Gamepad Gamepad(); ~Gamepad(); - bool GetState(int joystickID, int buttonID); - int GetButtonID(void); - int GetJoystickID(void); + // Class methods... + static void AllocateJoysticks(void); + static void DeallocateJoysticks(void); + static bool GetState(int joystickID, int buttonID); + static int CheckButtonPressed(void); + static int GetButtonID(void); + static int GetJoystickID(void); + static void Update(void); + + // Support up to 8 gamepads + static int numJoysticks; + static SDL_Joystick * pad[8]; + static int numButtons[8]; + static int numHats[8]; + static bool button[8][256]; + static uint8_t hat[8][32]; }; #endif // __GAMEPAD_H__ diff --git a/src/gui/keygrabber.cpp b/src/gui/keygrabber.cpp index 694be3c..7efe537 100644 --- a/src/gui/keygrabber.cpp +++ b/src/gui/keygrabber.cpp @@ -12,25 +12,32 @@ // #include "keygrabber.h" +#include "gamepad.h" -KeyGrabber::KeyGrabber(QWidget * parent/*= 0*/): QDialog(parent) +KeyGrabber::KeyGrabber(QWidget * parent/*= 0*/): QDialog(parent), + label(new QLabel), timer(new QTimer), buttonDown(false) { - label = new QLabel(this); +// label = new QLabel(this); QVBoxLayout * mainLayout = new QVBoxLayout; mainLayout->addWidget(label); setLayout(mainLayout); setWindowTitle(tr("Grab")); + connect(timer, SIGNAL(timeout()), this, SLOT(CheckGamepad())); + timer->setInterval(100); + timer->start(); // Will this make Mac OSX work??? setFocusPolicy(Qt::StrongFocus); } + KeyGrabber::~KeyGrabber() { + timer->stop(); } -//void KeyGrabber::SetText(QString keyText) + void KeyGrabber::SetKeyText(int keyNum) { char jagButtonName[21][10] = { "Up", "Down", "Left", "Right", @@ -42,6 +49,7 @@ void KeyGrabber::SetKeyText(int keyNum) label->setText(text); } + void KeyGrabber::keyPressEvent(QKeyEvent * e) { key = e->key(); @@ -50,3 +58,31 @@ void KeyGrabber::keyPressEvent(QKeyEvent * e) if (key != Qt::Key_Alt) accept(); } + + +void KeyGrabber::CheckGamepad(void) +{ + // How do we determine which joystick it is, if more than one? + // Possibly by a combobox selecting the stick you want to configure... + Gamepad::Update(); + + if (!buttonDown) + { + button = Gamepad::CheckButtonPressed(); + + if (button == -1) + return; + + buttonDown = true; + } + else + { + if (Gamepad::CheckButtonPressed() == button) + return; + + key = button; + accept(); + buttonDown = false; + } +} + diff --git a/src/gui/keygrabber.h b/src/gui/keygrabber.h index aae5961..cb0abaf 100644 --- a/src/gui/keygrabber.h +++ b/src/gui/keygrabber.h @@ -22,8 +22,14 @@ class KeyGrabber: public QDialog protected: void keyPressEvent(QKeyEvent *); -private: + private slots: + void CheckGamepad(); + + private: QLabel * label; + QTimer * timer; + bool buttonDown; + int button; public: int key; diff --git a/src/gui/mainwin.cpp b/src/gui/mainwin.cpp index 892d5a7..9a73987 100644 --- a/src/gui/mainwin.cpp +++ b/src/gui/mainwin.cpp @@ -35,13 +35,14 @@ #include "SDL.h" #include "app.h" -#include "glwidget.h" #include "about.h" -#include "help.h" -#include "settings.h" -#include "filepicker.h" #include "configdialog.h" +#include "filepicker.h" +#include "gamepad.h" #include "generaltab.h" +#include "glwidget.h" +#include "help.h" +#include "settings.h" #include "version.h" #include "debug/cpubrowser.h" #include "debug/m68kdasmbrowser.h" @@ -503,6 +504,21 @@ void MainWin::HandleKeys(QKeyEvent * e, bool state) } +void MainWin::HandleGamepads(void) +{ + Gamepad::Update(); + + for(int i=BUTTON_FIRST; i<=BUTTON_LAST; i++) + { + if (vjs.p1KeyBindings[i] & (JOY_BUTTON | JOY_HAT)) + joypad_0_buttons[i] = (Gamepad::GetState(0, vjs.p1KeyBindings[i]) ? 0x01 : 0x00); + + if (vjs.p2KeyBindings[i] & (JOY_BUTTON | JOY_HAT)) + joypad_1_buttons[i] = (Gamepad::GetState(1, vjs.p2KeyBindings[i]) ? 0x01 : 0x00); + } +} + + void MainWin::Open(void) { } @@ -606,6 +622,7 @@ void MainWin::Timer(void) else { // Otherwise, run the Jaguar simulation + HandleGamepads(); JaguarExecuteNew(); } diff --git a/src/gui/mainwin.h b/src/gui/mainwin.h index 27c99ce..f7276b8 100644 --- a/src/gui/mainwin.h +++ b/src/gui/mainwin.h @@ -65,6 +65,7 @@ class MainWin: public QMainWindow private: void HandleKeys(QKeyEvent *, bool); + void HandleGamepads(void); void SetFullScreen(bool state = true); void ResizeMainWindow(void); void ReadSettings(void); -- 2.37.2