From f0bc5c9cbf3d589239d18d6b29e5072a0b77d7da Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 16 May 2022 07:21:28 -0700 Subject: [PATCH] Added effects support for virtual controllers --- include/SDL_joystick.h | 6 ++++ src/joystick/virtual/SDL_virtualjoystick.c | 41 +++++++++++++++++++++- test/testgamecontroller.c | 27 ++++++++++++++ 3 files changed, 73 insertions(+), 1 deletion(-) diff --git a/include/SDL_joystick.h b/include/SDL_joystick.h index 277e29a37..9825b5be6 100644 --- a/include/SDL_joystick.h +++ b/include/SDL_joystick.h @@ -352,6 +352,7 @@ extern DECLSPEC int SDLCALL SDL_JoystickAttachVirtual(SDL_JoystickType type, * The structure that defines an extended virtual joystick description * * The caller must zero the structure and then initialize the version with `SDL_VIRTUAL_JOYSTICK_DESC_VERSION` before passing it to SDL_JoystickAttachVirtualEx() + * All other elements of this structure are optional and can be left 0. * * \sa SDL_JoystickAttachVirtualEx */ @@ -373,6 +374,11 @@ typedef struct SDL_VirtualJoystickDesc void *userdata; /**< User data pointer passed to callbacks */ void (*Update)(void *userdata); /**< Called when the joystick state should be updated */ + void (*SetPlayerIndex)(void *userdata, int player_index); /**< Called when the player index is set */ + int (*Rumble)(void *userdata, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble); /**< Implements SDL_JoystickRumble() */ + int (*RumbleTriggers)(void *userdata, Uint16 left_rumble, Uint16 right_rumble); /**< Implements SDL_JoystickRumbleTriggers() */ + int (*SetLED)(void *userdata, Uint8 red, Uint8 green, Uint8 blue); /**< Implements SDL_JoystickSetLED() */ + int (*SendEffect)(void *userdata, const void *data, int size); /**< Implements SDL_JoystickSendEffect() */ } SDL_VirtualJoystickDesc; diff --git a/src/joystick/virtual/SDL_virtualjoystick.c b/src/joystick/virtual/SDL_virtualjoystick.c index 6e80d385b..4449d0af0 100644 --- a/src/joystick/virtual/SDL_virtualjoystick.c +++ b/src/joystick/virtual/SDL_virtualjoystick.c @@ -395,6 +395,11 @@ VIRTUAL_JoystickGetDevicePlayerIndex(int device_index) static void VIRTUAL_JoystickSetDevicePlayerIndex(int device_index, int player_index) { + joystick_hwdata *hwdata = VIRTUAL_HWDataForIndex(device_index); + + if (hwdata && hwdata->desc.SetPlayerIndex) { + hwdata->desc.SetPlayerIndex(hwdata->desc.userdata, player_index); + } } @@ -446,12 +451,22 @@ VIRTUAL_JoystickOpen(SDL_Joystick *joystick, int device_index) static int VIRTUAL_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble) { + joystick_hwdata *hwdata = joystick->hwdata; + + if (hwdata && hwdata->desc.Rumble) { + return hwdata->desc.Rumble(hwdata->desc.userdata, low_frequency_rumble, high_frequency_rumble); + } return SDL_Unsupported(); } static int VIRTUAL_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble) { + joystick_hwdata *hwdata = joystick->hwdata; + + if (hwdata && hwdata->desc.RumbleTriggers) { + return hwdata->desc.RumbleTriggers(hwdata->desc.userdata, left_rumble, right_rumble); + } return SDL_Unsupported(); } @@ -459,19 +474,43 @@ VIRTUAL_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint1 static Uint32 VIRTUAL_JoystickGetCapabilities(SDL_Joystick *joystick) { - return 0; + joystick_hwdata *hwdata = joystick->hwdata; + Uint32 caps = 0; + + if (hwdata) { + if (hwdata->desc.Rumble) { + caps |= SDL_JOYCAP_RUMBLE; + } + if (hwdata->desc.RumbleTriggers) { + caps |= SDL_JOYCAP_RUMBLE_TRIGGERS; + } + if (hwdata->desc.SetLED) { + caps |= SDL_JOYCAP_LED; + } + } + return caps; } static int VIRTUAL_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue) { + joystick_hwdata *hwdata = joystick->hwdata; + + if (hwdata && hwdata->desc.SetLED) { + return hwdata->desc.SetLED(hwdata->desc.userdata, red, green, blue); + } return SDL_Unsupported(); } static int VIRTUAL_JoystickSendEffect(SDL_Joystick *joystick, const void *data, int size) { + joystick_hwdata *hwdata = joystick->hwdata; + + if (hwdata && hwdata->desc.SendEffect) { + return hwdata->desc.SendEffect(hwdata->desc.userdata, data, size); + } return SDL_Unsupported(); } diff --git a/test/testgamecontroller.c b/test/testgamecontroller.c index 086a34041..b24581598 100644 --- a/test/testgamecontroller.c +++ b/test/testgamecontroller.c @@ -312,6 +312,29 @@ static SDL_bool ShowingFront() return showing_front; } +static void VirtualControllerSetPlayerIndex(void *userdata, int player_index) +{ + SDL_Log("Virtual Controller: player index set to %d\n", player_index); +} + +static int VirtualControllerRumble(void *userdata, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble) +{ + SDL_Log("Virtual Controller: rumble set to %d/%d\n", low_frequency_rumble, high_frequency_rumble); + return 0; +} + +static int VirtualControllerRumbleTriggers(void *userdata, Uint16 left_rumble, Uint16 right_rumble) +{ + SDL_Log("Virtual Controller: trigger rumble set to %d/%d\n", left_rumble, right_rumble); + return 0; +} + +static int VirtualControllerSetLED(void *userdata, Uint8 red, Uint8 green, Uint8 blue) +{ + SDL_Log("Virtual Controller: LED set to RGB %d,%d,%d\n", red, green, blue); + return 0; +} + static int OpenVirtualController() { SDL_VirtualJoystickDesc desc; @@ -321,6 +344,10 @@ static int OpenVirtualController() desc.type = SDL_JOYSTICK_TYPE_GAMECONTROLLER; desc.naxes = SDL_CONTROLLER_AXIS_MAX; desc.nbuttons = SDL_CONTROLLER_BUTTON_MAX; + desc.SetPlayerIndex = VirtualControllerSetPlayerIndex; + desc.Rumble = VirtualControllerRumble; + desc.RumbleTriggers = VirtualControllerRumbleTriggers; + desc.SetLED = VirtualControllerSetLED; return SDL_JoystickAttachVirtualEx(&desc); }