From 24aa8c782fb0e341d2565250c8ce53173bd45b4a Mon Sep 17 00:00:00 2001 From: stephena Date: Mon, 9 Jan 2006 19:30:04 +0000 Subject: [PATCH] Second pass at joystick hat support. It seems to be working fine in emulation mode, but it's somewhat sensitive in GUI navigation (could be my cheap gamepad). Remapping is mostly complete, except for assignment of hats to analog events. Some more thought is required for this one. git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@946 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba --- stella/src/emucore/EventHandler.cxx | 144 ++++++++++++++++++++++++-- stella/src/emucore/EventHandler.hxx | 14 ++- stella/src/gui/DialogContainer.cxx | 42 +++++++- stella/src/gui/EventMappingWidget.cxx | 17 ++- stella/src/gui/EventMappingWidget.hxx | 3 +- stella/src/gui/InputDialog.cxx | 12 ++- stella/src/gui/InputDialog.hxx | 3 +- 7 files changed, 214 insertions(+), 21 deletions(-) diff --git a/stella/src/emucore/EventHandler.cxx b/stella/src/emucore/EventHandler.cxx index c8569fff8..a5e45e356 100644 --- a/stella/src/emucore/EventHandler.cxx +++ b/stella/src/emucore/EventHandler.cxx @@ -13,7 +13,7 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: EventHandler.cxx,v 1.144 2006-01-09 16:50:01 stephena Exp $ +// $Id: EventHandler.cxx,v 1.145 2006-01-09 19:30:04 stephena Exp $ //============================================================================ #include @@ -673,6 +673,7 @@ void EventHandler::poll(uInt32 time) handleJoyEvent(stick, button, state); break; } + break; // Regular button } case JT_STELLADAPTOR_LEFT: @@ -783,10 +784,22 @@ void EventHandler::poll(uInt32 time) if(stick >= kNumJoysticks || hat >= kNumJoyHats) break; - if(myState == S_EMULATE) - handleJoyHatEvent(stick, hat, value); - else if(myOverlay != NULL) - myOverlay->handleJoyHatEvent(stick, hat, value); + // Preprocess all hat events, converting to Stella JoyHat type + // Generate two equivalent hat events representing combined direction + // when we get a diagonal hat event + if(value == SDL_HAT_CENTERED) + handleJoyHatEvent(stick, hat, kJHatCentered); + else + { + if(value & SDL_HAT_UP) + handleJoyHatEvent(stick, hat, kJHatUp); + if(value & SDL_HAT_RIGHT) + handleJoyHatEvent(stick, hat, kJHatRight); + if(value & SDL_HAT_DOWN) + handleJoyHatEvent(stick, hat, kJHatDown); + if(value & SDL_HAT_LEFT) + handleJoyHatEvent(stick, hat, kJHatLeft); + } break; // SDL_JOYHATMOTION } #endif // JOYSTICK_SUPPORT @@ -950,7 +963,72 @@ void EventHandler::handleJoyAxisEvent(int stick, int axis, int value) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void EventHandler::handleJoyHatEvent(int stick, int hat, int value) { -cerr << "stick = " << stick << ", hat = " << hat << ", value = " << value << endl; + if(myState == S_EMULATE) + { + cerr << "stick = " << stick << ", hat = " << hat; +switch(value) { +case kJHatCentered: cerr << " centered\n"; break; +case kJHatUp: cerr << " up\n"; break; +case kJHatDown: cerr << " down\n"; break; +case kJHatLeft: cerr << " left\n"; break; +case kJHatRight: cerr << " right\n"; break; +} + + // Treat hats as pairs of directions, similar to joystick axes + // Every hat pair has two associated values, negative and positive + // Analog events are stored in the negative portion + Event::Type eventHatAnalog; + switch(value) + { + case kJHatUp: + case kJHatDown: + eventHatAnalog = myJoyHatTable[stick][hat][0]; + break; + case kJHatLeft: + case kJHatRight: + eventHatAnalog = myJoyHatTable[stick][hat][2]; + break; + default: + eventHatAnalog = Event::NoType; + break; + } + // Check for analog events, which are handled differently + switch((int)eventHatAnalog) + { + case Event::PaddleZeroAnalog: + myEvent->set(Event::PaddleZeroResistance, + (int)(1000000.0 * (32767 - value) / 65534)); + break; + case Event::PaddleOneAnalog: + myEvent->set(Event::PaddleOneResistance, + (int)(1000000.0 * (32767 - value) / 65534)); + break; + case Event::PaddleTwoAnalog: + myEvent->set(Event::PaddleTwoResistance, + (int)(1000000.0 * (32767 - value) / 65534)); + break; + case Event::PaddleThreeAnalog: + myEvent->set(Event::PaddleThreeResistance, + (int)(1000000.0 * (32767 - value) / 65534)); + break; + default: + // Otherwise, we know the event is digital + if(value == kJHatCentered) + { + // Turn off all associated events, since we don't know exactly + // which one was previously activated. + handleEvent(myJoyHatTable[stick][hat][0], 0); + handleEvent(myJoyHatTable[stick][hat][1], 0); + handleEvent(myJoyHatTable[stick][hat][2], 0); + handleEvent(myJoyHatTable[stick][hat][3], 0); + } + else + handleEvent(myJoyHatTable[stick][hat][value] , 1); + break; + } + } + else if(myOverlay != NULL) + myOverlay->handleJoyHatEvent(stick, hat, value); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1241,7 +1319,7 @@ void EventHandler::createMouseButtonEvent(int x, int y, int state) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void EventHandler::setActionMappings() { - int i, j, stick, button, axis, dir; + int i, j, stick, button, axis, hat, dir; ostringstream buf; // Fill the ActionList with the current key and joystick mappings @@ -1305,8 +1383,43 @@ void EventHandler::setActionMappings() } } } - -// FIXME - add joy hat labeling + // Joystick hat mapping/labeling + for(stick = 0; stick < kNumJoysticks; ++stick) + { + for(hat = 0; hat < kNumJoyHats; ++hat) + { + for(dir = 0; dir < 4; ++dir) + { + if(myJoyHatTable[stick][hat][dir] == event) + { + buf.str(""); + buf << "J" << stick << " hat " << hat; + switch(dir) + { + case kJHatUp: buf << " up"; break; + case kJHatDown: buf << " down"; break; + case kJHatLeft: buf << " left"; break; + case kJHatRight: buf << " right"; break; + } +/* FIXME - figure out how to combine analog & hats + if(eventIsAnalog(event)) + { + dir = 2; // Immediately exit the inner loop after this iteration + buf << " abs"; + } + else if(dir == 0) + buf << " neg"; + else + buf << " pos"; +*/ + if(key == "") + key = key + buf.str(); + else + key = key + ", " + buf.str(); + } + } + } + } // There are some keys which are hardcoded. These should be represented too. string prepend = ""; @@ -1474,8 +1587,17 @@ void EventHandler::setDefaultJoyHatMapping(Event::Type event, int stick, hat >= 0 && hat < kNumJoyHats && event >= 0 && event < Event::LastType) { -cerr << "add mapping for stick = " << stick << ", hat = " << hat << ", value = " << value << endl; -/* + switch(value) + { + case kJHatUp: + case kJHatDown: + case kJHatLeft: + case kJHatRight: + myJoyHatTable[stick][hat][value] = event; + break; + } + +/* FIXME - deal with assignment of analog events // This confusing code is because each axis has two associated values, // but analog events only affect one of the axis. if(eventIsAnalog(event)) diff --git a/stella/src/emucore/EventHandler.hxx b/stella/src/emucore/EventHandler.hxx index 0ec6d3614..dede4113e 100644 --- a/stella/src/emucore/EventHandler.hxx +++ b/stella/src/emucore/EventHandler.hxx @@ -13,7 +13,7 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: EventHandler.hxx,v 1.74 2006-01-09 16:50:01 stephena Exp $ +// $Id: EventHandler.hxx,v 1.75 2006-01-09 19:30:04 stephena Exp $ //============================================================================ #ifndef EVENTHANDLER_HXX @@ -60,6 +60,16 @@ enum { #endif }; +// A wrapper around SDL hat events, so we don't drag SDL +// through all the child classes +enum JoyHat { + kJHatUp, + kJHatDown, + kJHatLeft, + kJHatRight, + kJHatCentered +}; + enum MouseButton { EVENT_LBUTTONDOWN, EVENT_LBUTTONUP, @@ -123,7 +133,7 @@ struct JoyMouse { mapping can take place. @author Stephen Anthony - @version $Id: EventHandler.hxx,v 1.74 2006-01-09 16:50:01 stephena Exp $ + @version $Id: EventHandler.hxx,v 1.75 2006-01-09 19:30:04 stephena Exp $ */ class EventHandler { diff --git a/stella/src/gui/DialogContainer.cxx b/stella/src/gui/DialogContainer.cxx index b7a543405..98f26df3c 100644 --- a/stella/src/gui/DialogContainer.cxx +++ b/stella/src/gui/DialogContainer.cxx @@ -13,7 +13,7 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: DialogContainer.cxx,v 1.29 2006-01-09 16:50:01 stephena Exp $ +// $Id: DialogContainer.cxx,v 1.30 2006-01-09 19:30:04 stephena Exp $ //============================================================================ #include "OSystem.hxx" @@ -389,8 +389,44 @@ void DialogContainer::handleJoyAxisEvent(int stick, int axis, int value) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void DialogContainer::handleJoyHatEvent(int stick, int hat, int value) { -cerr << "received hat event in dialogcontainer:" << endl - << "stick = " << stick << ", hat = " << hat << ", value = " << value << endl; + if(myDialogStack.empty()) + return; + + // Send the event to the dialog box on the top of the stack + Dialog* activeDialog = myDialogStack.top(); + + // Only preprocess hat events if the dialog absolutely doesn't want them + // Translate to axis events for movement + if(!activeDialog->wantsAllEvents()) + { + bool handled = true; + switch(value) + { + case kJHatCentered: + handleJoyAxisEvent(stick, 0, 0); + handleJoyAxisEvent(stick, 1, 0); // axis 0 & 1, 0 ==> OFF + break; + case kJHatUp: + handleJoyAxisEvent(stick, 1, -32767); // axis 1, -value ==> UP + break; + case kJHatLeft: + handleJoyAxisEvent(stick, 0, -32767); // axis 0, -value ==> LEFT + break; + case kJHatDown: + handleJoyAxisEvent(stick, 1, 32767); // axis 1, +value ==> DOWN + break; + case kJHatRight: + handleJoyAxisEvent(stick, 0, 32767); // axis 0, +value ==> RIGHT + break; + default: + handled = false; + } + if(handled) + return; + } + + if(activeDialog->wantsEvents()) + activeDialog->handleJoyHat(stick, hat, value); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/stella/src/gui/EventMappingWidget.cxx b/stella/src/gui/EventMappingWidget.cxx index b0124b7c3..71769d2e2 100644 --- a/stella/src/gui/EventMappingWidget.cxx +++ b/stella/src/gui/EventMappingWidget.cxx @@ -13,7 +13,7 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: EventMappingWidget.cxx,v 1.8 2006-01-08 02:28:03 stephena Exp $ +// $Id: EventMappingWidget.cxx,v 1.9 2006-01-09 19:30:04 stephena Exp $ // // Based on code from ScummVM - Scumm Interpreter // Copyright (C) 2002-2004 The ScummVM project @@ -208,7 +208,7 @@ void EventMappingWidget::handleJoyDown(int stick, int button) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void EventMappingWidget::handleJoyAxis(int stick, int axis, int value) { - // Remap joystick buttons in remap mode + // Remap joystick axes in remap mode if(myRemapStatus && myActionSelected >= 0) { Event::Type event = EventHandler::ourActionList[ myActionSelected ].event; @@ -218,6 +218,19 @@ void EventMappingWidget::handleJoyAxis(int stick, int axis, int value) } } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void EventMappingWidget::handleJoyHat(int stick, int hat, int value) +{ + // Remap joystick hats in remap mode + if(myRemapStatus && myActionSelected >= 0) + { + Event::Type event = EventHandler::ourActionList[ myActionSelected ].event; + instance()->eventHandler().addJoyHatMapping(event, stick, hat, value); + + stopRemapping(); + } +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void EventMappingWidget::handleCommand(CommandSender* sender, int cmd, int data, int id) diff --git a/stella/src/gui/EventMappingWidget.hxx b/stella/src/gui/EventMappingWidget.hxx index 24583135a..259b780bc 100644 --- a/stella/src/gui/EventMappingWidget.hxx +++ b/stella/src/gui/EventMappingWidget.hxx @@ -13,7 +13,7 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: EventMappingWidget.hxx,v 1.4 2005-12-24 22:09:36 stephena Exp $ +// $Id: EventMappingWidget.hxx,v 1.5 2006-01-09 19:30:04 stephena Exp $ // // Based on code from ScummVM - Scumm Interpreter // Copyright (C) 2002-2004 The ScummVM project @@ -47,6 +47,7 @@ class EventMappingWidget : public Widget, public CommandSender virtual bool handleKeyDown(int ascii, int keycode, int modifiers); virtual void handleJoyDown(int stick, int button); virtual void handleJoyAxis(int stick, int axis, int value); + virtual void handleJoyHat(int stick, int hat, int value); bool remapMode() { return myRemapStatus; } diff --git a/stella/src/gui/InputDialog.cxx b/stella/src/gui/InputDialog.cxx index aa384c65b..f1c82f5fd 100644 --- a/stella/src/gui/InputDialog.cxx +++ b/stella/src/gui/InputDialog.cxx @@ -13,7 +13,7 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: InputDialog.cxx,v 1.8 2005-12-21 01:50:16 stephena Exp $ +// $Id: InputDialog.cxx,v 1.9 2006-01-09 19:30:04 stephena Exp $ //============================================================================ #include "OSystem.hxx" @@ -250,6 +250,16 @@ void InputDialog::handleJoyAxis(int stick, int axis, int value) Dialog::handleJoyAxis(stick, axis, value); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void InputDialog::handleJoyHat(int stick, int hat, int value) +{ + // Remap joystick hat in remap mode, otherwise pass to listwidget + if(myEventMapper->remapMode()) + myEventMapper->handleJoyHat(stick, hat, value); + else + Dialog::handleJoyHat(stick, hat, value); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void InputDialog::handleCommand(CommandSender* sender, int cmd, int data, int id) diff --git a/stella/src/gui/InputDialog.hxx b/stella/src/gui/InputDialog.hxx index 530d307d1..c6511a0ca 100644 --- a/stella/src/gui/InputDialog.hxx +++ b/stella/src/gui/InputDialog.hxx @@ -13,7 +13,7 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: InputDialog.hxx,v 1.4 2005-12-16 14:41:15 stephena Exp $ +// $Id: InputDialog.hxx,v 1.5 2006-01-09 19:30:04 stephena Exp $ //============================================================================ #ifndef INPUT_DIALOG_HXX @@ -42,6 +42,7 @@ class InputDialog : public Dialog virtual void handleKeyDown(int ascii, int keycode, int modifiers); virtual void handleJoyDown(int stick, int button); virtual void handleJoyAxis(int stick, int axis, int value); + virtual void handleJoyHat(int stick, int hat, int value); virtual void handleCommand(CommandSender* sender, int cmd, int data, int id); void loadConfig();