From 30109816fe3a0dae80795483ff28e9a50e6009a4 Mon Sep 17 00:00:00 2001 From: Cameron Cawley <ccawley2011@gmail.com> Date: Sun, 16 Jun 2019 23:26:49 +0100 Subject: [PATCH] SDL: Initial implementation of joystick events --- backends/events/sdl/sdl-events.cpp | 101 +++++++++++++++++++++++++++++ backends/events/sdl/sdl-events.h | 4 ++ common/events.h | 53 ++++++++++++++- engines/engine.h | 10 ++- 4 files changed, 166 insertions(+), 2 deletions(-) diff --git a/backends/events/sdl/sdl-events.cpp b/backends/events/sdl/sdl-events.cpp index 29be7d4e746..494e1bf8cd9 100644 --- a/backends/events/sdl/sdl-events.cpp +++ b/backends/events/sdl/sdl-events.cpp @@ -30,6 +30,8 @@ #include "common/config-manager.h" #include "common/textconsole.h" #include "common/fs.h" +#include "engines/engine.h" +#include "gui/gui-manager.h" // FIXME move joystick defines out and replace with confile file options // we should really allow users to map any key to a joystick button @@ -902,7 +904,45 @@ void SdlEventSource::closeJoystick() { } } +bool SdlEventSource::shouldGenerateMouseEvents() { + // Engine doesn't support joystick -> emulate mouse events + if (g_engine && !g_engine->hasFeature(Engine::kSupportsJoystick)) { + return true; + } + if (g_gui.isActive()) { + return true; + } + return false; +} + +int SdlEventSource::mapSDLJoystickButtonToOSystem(Uint8 sdlButton) { + Common::JoystickButton osystemButtons[] = { + Common::JOYSTICK_BUTTON_A, + Common::JOYSTICK_BUTTON_B, + Common::JOYSTICK_BUTTON_X, + Common::JOYSTICK_BUTTON_Y, + Common::JOYSTICK_BUTTON_LEFT_SHOULDER, + Common::JOYSTICK_BUTTON_RIGHT_SHOULDER, + Common::JOYSTICK_BUTTON_BACK, + Common::JOYSTICK_BUTTON_START, + Common::JOYSTICK_BUTTON_LEFT_STICK, + Common::JOYSTICK_BUTTON_RIGHT_STICK + }; + + if (sdlButton >= ARRAYSIZE(osystemButtons)) { + return -1; + } + + return osystemButtons[sdlButton]; +} + bool SdlEventSource::handleJoyButtonDown(SDL_Event &ev, Common::Event &event) { + if (!shouldGenerateMouseEvents()) { + event.type = Common::EVENT_JOYBUTTON_DOWN; + event.joystick.button = mapSDLJoystickButtonToOSystem(ev.jbutton.button); + return true; + } + if (ev.jbutton.button == JOY_BUT_LMOUSE) { event.type = Common::EVENT_LBUTTONDOWN; return processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER); @@ -939,6 +979,12 @@ bool SdlEventSource::handleJoyButtonDown(SDL_Event &ev, Common::Event &event) { } bool SdlEventSource::handleJoyButtonUp(SDL_Event &ev, Common::Event &event) { + if (!shouldGenerateMouseEvents()) { + event.type = Common::EVENT_JOYBUTTON_UP; + event.joystick.button = mapSDLJoystickButtonToOSystem(ev.jbutton.button); + return true; + } + if (ev.jbutton.button == JOY_BUT_LMOUSE) { event.type = Common::EVENT_LBUTTONUP; return processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER); @@ -975,6 +1021,16 @@ bool SdlEventSource::handleJoyButtonUp(SDL_Event &ev, Common::Event &event) { } bool SdlEventSource::handleJoyAxisMotion(SDL_Event &ev, Common::Event &event) { + // TODO: move handleAxisToMouseMotion to Common? +#if 0 + if (!shouldGenerateMouseEvents()) { + event.type = Common::EVENT_JOYAXIS_MOTION; + event.joystick.axis = ev.jaxis.axis; + event.joystick.position = ev.jaxis.value; + return true; + } +#endif + if (ev.jaxis.axis == JOY_XAXIS) { _km.joy_x = ev.jaxis.value; return handleAxisToMouseMotion(_km.joy_x, _km.joy_y); @@ -1024,6 +1080,32 @@ bool SdlEventSource::handleJoystickRemoved(const SDL_JoyDeviceEvent &device) { return false; } +int SdlEventSource::mapSDLControllerButtonToOSystem(Uint8 sdlButton) { + Common::JoystickButton osystemButtons[] = { + Common::JOYSTICK_BUTTON_A, + Common::JOYSTICK_BUTTON_B, + Common::JOYSTICK_BUTTON_X, + Common::JOYSTICK_BUTTON_Y, + Common::JOYSTICK_BUTTON_BACK, + Common::JOYSTICK_BUTTON_GUIDE, + Common::JOYSTICK_BUTTON_START, + Common::JOYSTICK_BUTTON_LEFT_STICK, + Common::JOYSTICK_BUTTON_RIGHT_STICK, + Common::JOYSTICK_BUTTON_LEFT_SHOULDER, + Common::JOYSTICK_BUTTON_RIGHT_SHOULDER, + Common::JOYSTICK_BUTTON_DPAD_UP, + Common::JOYSTICK_BUTTON_DPAD_DOWN, + Common::JOYSTICK_BUTTON_DPAD_LEFT, + Common::JOYSTICK_BUTTON_DPAD_RIGHT + }; + + if (sdlButton >= ARRAYSIZE(osystemButtons)) { + return -1; + } + + return osystemButtons[sdlButton]; +} + bool SdlEventSource::handleControllerButton(const SDL_Event &ev, Common::Event &event, bool buttonUp) { using namespace Common; @@ -1071,6 +1153,15 @@ bool SdlEventSource::handleControllerButton(const SDL_Event &ev, Common::Event & { EVENT_KEYDOWN, KeyState(KEYCODE_KP6, 0), EVENT_KEYDOWN, KeyState(KEYCODE_KP3, 0) } }; + if (!shouldGenerateMouseEvents()) { + event.type = buttonUp ? Common::EVENT_JOYBUTTON_UP : Common::EVENT_JOYBUTTON_DOWN; + event.joystick.button = mapSDLControllerButtonToOSystem(ev.cbutton.button); + if (event.joystick.button == -1) + return false; + + return true; + } + if (ev.cbutton.button > SDL_CONTROLLER_BUTTON_DPAD_RIGHT) { warning("Unknown SDL controller button: '%d'", ev.cbutton.button); return false; @@ -1115,6 +1206,16 @@ bool SdlEventSource::handleControllerButton(const SDL_Event &ev, Common::Event & } bool SdlEventSource::handleControllerAxisMotion(const SDL_Event &ev, Common::Event &event) { + // TODO: move handleAxisToMouseMotion to Common? +#if 0 + if (!shouldGenerateMouseEvents()) { + event.type = Common::EVENT_JOYAXIS_MOTION; + event.joystick.axis = ev.caxis.axis; + event.joystick.position = ev.caxis.value; + return true; + } +#endif + if (ev.caxis.axis == SDL_CONTROLLER_AXIS_LEFTX) { _km.joy_x = ev.caxis.value; return handleAxisToMouseMotion(_km.joy_x, _km.joy_y); diff --git a/backends/events/sdl/sdl-events.h b/backends/events/sdl/sdl-events.h index c2ae0023ceb..6050c802972 100644 --- a/backends/events/sdl/sdl-events.h +++ b/backends/events/sdl/sdl-events.h @@ -139,6 +139,7 @@ protected: virtual bool handleMouseButtonDown(SDL_Event &ev, Common::Event &event); virtual bool handleMouseButtonUp(SDL_Event &ev, Common::Event &event); virtual bool handleSysWMEvent(SDL_Event &ev, Common::Event &event); + virtual int mapSDLJoystickButtonToOSystem(Uint8 sdlButton); virtual bool handleJoyButtonDown(SDL_Event &ev, Common::Event &event); virtual bool handleJoyButtonUp(SDL_Event &ev, Common::Event &event); virtual bool handleJoyAxisMotion(SDL_Event &ev, Common::Event &event); @@ -148,10 +149,13 @@ protected: #if SDL_VERSION_ATLEAST(2, 0, 0) virtual bool handleJoystickAdded(const SDL_JoyDeviceEvent &event); virtual bool handleJoystickRemoved(const SDL_JoyDeviceEvent &device); + virtual int mapSDLControllerButtonToOSystem(Uint8 sdlButton); virtual bool handleControllerButton(const SDL_Event &ev, Common::Event &event, bool buttonUp); virtual bool handleControllerAxisMotion(const SDL_Event &ev, Common::Event &event); #endif + bool shouldGenerateMouseEvents(); + //@} /** diff --git a/common/events.h b/common/events.h index 4b357252253..ff5d2874f41 100644 --- a/common/events.h +++ b/common/events.h @@ -86,7 +86,52 @@ enum EventType { EVENT_VIRTUAL_KEYBOARD = 20, #endif - EVENT_DROP_FILE = 23 + EVENT_DROP_FILE = 23, + + EVENT_JOYAXIS_MOTION = 24, + EVENT_JOYBUTTON_DOWN = 25, + EVENT_JOYBUTTON_UP = 26 +}; + +const int16 JOYAXIS_MIN = -32768; +const int16 JOYAXIS_MAX = 32767; + +/** + * Data structure for joystick events + */ +struct JoystickState { + /** The axis for EVENT_JOYAXIS_MOTION events */ + byte axis; + /** The new axis position for EVENT_JOYAXIS_MOTION events */ + int16 position; + /** + * The button index for EVENT_JOYBUTTON_DOWN/UP events + * + * Some of the button indices match well-known game controller + * buttons. See JoystickButton. + */ + byte button; +}; + +/** + * The list named buttons available from a joystick + */ +enum JoystickButton { + JOYSTICK_BUTTON_A, + JOYSTICK_BUTTON_B, + JOYSTICK_BUTTON_X, + JOYSTICK_BUTTON_Y, + JOYSTICK_BUTTON_BACK, + JOYSTICK_BUTTON_GUIDE, + JOYSTICK_BUTTON_START, + JOYSTICK_BUTTON_LEFT_STICK, + JOYSTICK_BUTTON_RIGHT_STICK, + JOYSTICK_BUTTON_LEFT_SHOULDER, + JOYSTICK_BUTTON_RIGHT_SHOULDER, + JOYSTICK_BUTTON_DPAD_UP, + JOYSTICK_BUTTON_DPAD_DOWN, + JOYSTICK_BUTTON_DPAD_LEFT, + JOYSTICK_BUTTON_DPAD_RIGHT }; typedef uint32 CustomEventType; @@ -130,6 +175,12 @@ struct Event { /* The path of the file or directory dragged to the ScummVM window */ Common::String path; + /** + * Joystick data; only valid for joystick events (EVENT_JOYAXIS_MOTION, + * EVENT_JOYBUTTON_DOWN and EVENT_JOYBUTTON_UP). + */ + JoystickState joystick; + Event() : type(EVENT_INVALID), kbdRepeat(false) { #ifdef ENABLE_KEYMAPPER customType = 0; diff --git a/engines/engine.h b/engines/engine.h index d004c29f844..cc7994e047e 100644 --- a/engines/engine.h +++ b/engines/engine.h @@ -132,7 +132,15 @@ public: * If this feature is supported, then the corresponding MetaEngine *must* * support the kSupportsListSaves feature. */ - kSupportsSavingDuringRuntime + kSupportsSavingDuringRuntime, + + /** + * Engine must receive joystick events because the game uses them. + * For engines which have not this feature, joystick events are converted + * to mouse events. + */ + kSupportsJoystick + };