From 78fd3c0c7d242e6a7e22ceb91cb6eaa0a8559c63 Mon Sep 17 00:00:00 2001 From: stephena Date: Fri, 2 Jul 2010 19:17:57 +0000 Subject: [PATCH] Modified joystick axis event handling, so that digital output is always used when sending axis events to the DialogContainer (ie, all UI-related stuff). The UI code was originally written with this in mind, and wasn't designed for analog input. For normal digital sticks, nothing changes. For analog sticks, values are clamped to 3 points (max, min, off), and repeated consecutive events are ignored. This (partially) fixes bugs in the UI, where pressing an analog stick would cause the current selector to move very fast. Added repeat mode for joystick hats, similar to joystick axes (so holding down a hat will cause continuous events to occur. More testing is required for this, as I don't actually have access to hats right now. git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@2058 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba --- src/common/Version.hxx | 2 +- src/emucore/EventHandler.cxx | 31 +++++++++++++++++++++----- src/emucore/EventHandler.hxx | 4 ++++ src/emucore/Joystick.hxx | 3 +-- src/emucore/OSystem.cxx | 9 +++++++- src/gui/DialogContainer.cxx | 42 ++++++++++++++++++++---------------- 6 files changed, 63 insertions(+), 28 deletions(-) diff --git a/src/common/Version.hxx b/src/common/Version.hxx index 0e2525a1b..4d9e05743 100644 --- a/src/common/Version.hxx +++ b/src/common/Version.hxx @@ -22,7 +22,7 @@ #include -#define STELLA_VERSION "3.2_svn" +#define STELLA_VERSION "3.2_test1" #define STELLA_BUILD atoi("$Rev$"+6) #endif diff --git a/src/emucore/EventHandler.cxx b/src/emucore/EventHandler.cxx index c3543b13e..37bfbdcb9 100644 --- a/src/emucore/EventHandler.cxx +++ b/src/emucore/EventHandler.cxx @@ -85,11 +85,14 @@ EventHandler::EventHandler(OSystem* osystem) for(int j = 0; j < kNumJoyButtons; ++j) myJoyTable[i][j][m] = Event::NoType; - // Erase the joystick axis mapping array - for(int m = 0; m < kNumModes; ++m) - for(int i = 0; i < kNumJoysticks; ++i) - for(int j = 0; j < kNumJoyAxis; ++j) + // Erase the joystick axis mapping array and last axis value + for(int i = 0; i < kNumJoysticks; ++i) + for(int j = 0; j < kNumJoyAxis; ++j) + { + myAxisLastValue[i][j] = 0; + for(int m = 0; m < kNumModes; ++m) myJoyAxisTable[i][j][0][m] = myJoyAxisTable[i][j][1][m] = Event::NoType; + } // Erase the joystick hat mapping array for(int m = 0; m < kNumModes; ++m) @@ -696,7 +699,25 @@ void EventHandler::poll(uInt64 time) if(myState == S_EMULATE) handleJoyAxisEvent(stick, axis, value); else if(myOverlay != NULL) - myOverlay->handleJoyAxisEvent(stick, axis, value); + { + // First, clamp the values to simulate digital input + // (the only thing that the underlying code understands) + if(value > Joystick::deadzone()) + value = 32000; + else if(value < -Joystick::deadzone()) + value = -32000; + else + value = 0; + + // Now filter out consecutive, similar values + // (only pass on the event if the state has changed) + if(value != myAxisLastValue[stick][axis]) + { +// cerr << value << " @ " << COUNTER++ << "(" << stick << "/" << axis << ")" << endl; + myOverlay->handleJoyAxisEvent(stick, axis, value); + myAxisLastValue[stick][axis] = value; + } + } break; // Regular joystick axis case JT_STELLADAPTOR_LEFT: diff --git a/src/emucore/EventHandler.hxx b/src/emucore/EventHandler.hxx index f74f54eed..98613b062 100644 --- a/src/emucore/EventHandler.hxx +++ b/src/emucore/EventHandler.hxx @@ -506,6 +506,10 @@ class EventHandler // Indicates which paddle the mouse currently emulates Int8 myPaddleMode; + // Keeps track of last axis values (used to emulate digital state + // for analog sticks) + int myAxisLastValue[kNumJoysticks][kNumJoyAxis]; + // Holds static strings for the remap menu (emulation and menu events) static ActionList ourEmulActionList[kEmulActionListSize]; static ActionList ourMenuActionList[kMenuActionListSize]; diff --git a/src/emucore/Joystick.hxx b/src/emucore/Joystick.hxx index 5c235aa45..96d4bb136 100644 --- a/src/emucore/Joystick.hxx +++ b/src/emucore/Joystick.hxx @@ -60,7 +60,7 @@ class Joystick : public Controller but it seemed like the best place to put it. */ static void setDeadZone(int deadzone); - inline static int deadzone() { return _DEAD_ZONE; } + inline static int deadzone() { return _DEAD_ZONE; } private: // Pre-compute the events we care about based on given port @@ -68,7 +68,6 @@ class Joystick : public Controller Event::Type myUpEvent, myDownEvent, myLeftEvent, myRightEvent, myXAxisValue, myYAxisValue, myFireEvent; - static int _DEAD_ZONE; }; diff --git a/src/emucore/OSystem.cxx b/src/emucore/OSystem.cxx index 2e34e4ded..d68ee69c5 100644 --- a/src/emucore/OSystem.cxx +++ b/src/emucore/OSystem.cxx @@ -896,7 +896,14 @@ void OSystem::setDefaultJoyAxisMap() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void OSystem::setDefaultJoyHatMap() { -// FIXME - add emul and UI events + // FIXME - add emulation events + EventMode mode; + + mode = kMenuMode; // Default menu/UI events + myEventHandler->setDefaultJoyHatMapping(Event::UILeft, mode, 0, 0, 2); + myEventHandler->setDefaultJoyHatMapping(Event::UIRight, mode, 0, 0, 3); + myEventHandler->setDefaultJoyHatMapping(Event::UIUp, mode, 0, 0, 0); + myEventHandler->setDefaultJoyHatMapping(Event::UIDown, mode, 0, 0, 1); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/gui/DialogContainer.cxx b/src/gui/DialogContainer.cxx index 8243fd42b..e7ba62202 100644 --- a/src/gui/DialogContainer.cxx +++ b/src/gui/DialogContainer.cxx @@ -84,6 +84,14 @@ void DialogContainer::updateTime(uInt64 time) myCurrentAxisDown.value); myAxisRepeatTime = myTime + kRepeatSustainDelay; } + + // Joystick hat still pressed + if(myCurrentHatDown.stick != -1 && myHatRepeatTime < myTime) + { + activeDialog->handleJoyHat(myCurrentHatDown.stick, myCurrentHatDown.hat, + myCurrentHatDown.value); + myHatRepeatTime = myTime + kRepeatSustainDelay; + } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -282,22 +290,9 @@ void DialogContainer::handleJoyEvent(int stick, int button, uInt8 state) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void DialogContainer::handleJoyAxisEvent(int stick, int axis, int value) { -// FIXME - analog axis events cause autofire to inadvertently come on and not go off - if(myDialogStack.empty()) return; - // Send the event to the dialog box on the top of the stack - Dialog* activeDialog = myDialogStack.top(); - - int deadzone = Joystick::deadzone(); - if(value > deadzone) - value -= deadzone; - else if(value < -deadzone ) - value += deadzone; - else - value = 0; - // Only stop firing events if it's the current stick if(myCurrentAxisDown.stick == stick && value == 0) { @@ -311,7 +306,7 @@ void DialogContainer::handleJoyAxisEvent(int stick, int axis, int value) myCurrentAxisDown.value = value; myAxisRepeatTime = myTime + kRepeatInitialDelay; } - activeDialog->handleJoyAxis(stick, axis, value); + myDialogStack.top()->handleJoyAxis(stick, axis, value); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -320,11 +315,20 @@ void DialogContainer::handleJoyHatEvent(int stick, int hat, int value) if(myDialogStack.empty()) return; - // Send the event to the dialog box on the top of the stack - Dialog* activeDialog = myDialogStack.top(); - - // FIXME - add repeat processing, similar to axis/button events - activeDialog->handleJoyHat(stick, hat, value); + // Only stop firing events if it's the current stick + if(myCurrentHatDown.stick == stick && value == 0) + { + myCurrentHatDown.stick = myCurrentHatDown.hat = -1; + } + else + { + // Now account for repeated hat events (press and hold) + myCurrentHatDown.stick = stick; + myCurrentHatDown.hat = hat; + myCurrentHatDown.value = value; + myHatRepeatTime = myTime + kRepeatInitialDelay; + } + myDialogStack.top()->handleJoyHat(stick, hat, value); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -