mirror of
				https://github.com/libsdl-org/SDL.git
				synced 2025-11-04 01:34:38 +00:00 
			
		
		
		
	Fixed bug 5028 - Virtual Joysticks (new joystick backend)
David Ludwig I have created a new driver for SDL's Joystick and Game-Controller subsystem: a Virtual driver. This driver allows one to create a software-based joystick, which to SDL applications will look and react like a real joystick, but whose state can be set programmatically. A primary use case for this is to help enable developers to add touch-screen joysticks to their apps. The driver comes with a set of new, public APIs, with functions to attach and detach joysticks, set virtual-joystick state, and to determine if a joystick is a virtual-one. Use of virtual joysticks goes as such: 1. Attach one or more virtual joysticks by calling SDL_JoystickAttachVirtual. If successful, this returns the virtual-device's joystick-index. 2. Open the virtual joysticks (using indicies returned by SDL_JoystickAttachVirtual). 3. Call any of the SDL_JoystickSetVirtual* functions when joystick-state changes. Please note that virtual-joystick state will only get applied on the next call to SDL_JoystickUpdate, or when pumping or polling for SDL events (via SDL_PumpEvents or SDL_PollEvent). Here is a listing of the new, public APIs, at present and subject to change: ------------------------------------------------------------ /** * Attaches a new virtual joystick. * Returns the joystick's device index, or -1 if an error occurred. */ extern DECLSPEC int SDLCALL SDL_JoystickAttachVirtual(SDL_JoystickType type, int naxes, int nballs, int nbuttons, int nhats); /** * Detaches a virtual joystick * Returns 0 on success, or -1 if an error occurred. */ extern DECLSPEC int SDLCALL SDL_JoystickDetachVirtual(int device_index); /** * Indicates whether or not a virtual-joystick is at a given device index. */ extern DECLSPEC SDL_bool SDLCALL SDL_JoystickIsVirtual(int device_index); /** * Set values on an opened, virtual-joystick's controls. * Returns 0 on success, -1 on error. */ extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualAxis(SDL_Joystick * joystick, int axis, Sint16 value); extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualBall(SDL_Joystick * joystick, int ball, Sint16 xrel, Sint16 yrel); extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualButton(SDL_Joystick * joystick, int button, Uint8 value); extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualHat(SDL_Joystick * joystick, int hat, Uint8 value); ------------------------------------------------------------ Miscellaneous notes on the initial patch, which are also subject to change: 1. no test code is present in SDL, yet. This should, perhaps, change. Initial development was done with an ImGui-based app, which potentially is too thick for use in SDL-official. If tests are to be added, what kind of tests? Automated? Graphical? 2. virtual game controllers can be created by calling SDL_JoystickAttachVirtual with a joystick-type of SDL_JOYSTICK_TYPE_GAME_CONTROLLER, with naxes (num axes) set to SDL_CONTROLLER_AXIS_MAX, and with nbuttons (num buttons) set to SDL_CONTROLLER_BUTTON_MAX. When updating their state, values of type SDL_GameControllerAxis or SDL_GameControllerButton can be casted to an int and used for the control-index (in calls to SDL_JoystickSetVirtual* functions). 3. virtual joysticks' guids are mostly all-zeros with the exception of the last two bytes, the first of which is a 'v', to indicate that the guid is a virtual one, and the second of which is a SDL_JoystickType that has been converted into a Uint8. 4. virtual joysticks are ONLY turned into virtual game-controllers if and when their joystick-type is set to SDL_JOYSTICK_TYPE_GAMECONTROLLER. This is controlled by having SDL's default list of game-controllers have a single entry for a virtual game controller (of guid, "00000000000000000000000000007601", which is subject to the guid-encoding described above). 5. regarding having to call SDL_JoystickUpdate, either directly or indirectly via SDL_PumpEvents or SDL_PollEvents, before new virtual-joystick state becomes active (as specified via SDL_JoystickSetVirtual* function-calls), this was done to match behavior found in SDL's other joystick drivers, almost all of which will only update SDL-state during SDL_JoystickUpdate. 6. the initial patch is based off of SDL 2.0.12 7. the virtual joystick subsystem is disabled by default. It should be possible to enable it by building with SDL_JOYSTICK_VIRTUAL=1 Questions, comments, suggestions, or bug reports very welcome!
This commit is contained in:
		@@ -387,6 +387,7 @@ set_option(VIDEO_OFFSCREEN     "Use offscreen video driver" OFF)
 | 
			
		||||
option_string(BACKGROUNDING_SIGNAL "number to use for magic backgrounding signal or 'OFF'" "OFF")
 | 
			
		||||
option_string(FOREGROUNDING_SIGNAL "number to use for magic foregrounding signal or 'OFF'" "OFF")
 | 
			
		||||
set_option(HIDAPI              "Use HIDAPI for low level joystick drivers" ${OPT_DEF_HIDAPI})
 | 
			
		||||
set_option(JOYSTICK_VIRTUAL    "Enable the virtual-joystick driver" ON)
 | 
			
		||||
 | 
			
		||||
set(SDL_SHARED ${SDL_SHARED_ENABLED_BY_DEFAULT} CACHE BOOL "Build a shared version of the library")
 | 
			
		||||
set(SDL_STATIC ${SDL_STATIC_ENABLED_BY_DEFAULT} CACHE BOOL "Build a static version of the library")
 | 
			
		||||
@@ -905,6 +906,14 @@ if(SDL_DLOPEN)
 | 
			
		||||
  endif()
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
if(SDL_JOYSTICK)
 | 
			
		||||
  if(JOYSTICK_VIRTUAL)
 | 
			
		||||
    set(SDL_JOYSTICK_VIRTUAL 1)
 | 
			
		||||
    file(GLOB JOYSTICK_VIRTUAL_SOURCES ${SDL2_SOURCE_DIR}/src/joystick/virtual/*.c)
 | 
			
		||||
    set(SOURCE_FILES ${SOURCE_FILES} ${JOYSTICK_VIRTUAL_SOURCES})
 | 
			
		||||
  endif()
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
if(SDL_VIDEO)
 | 
			
		||||
  if(VIDEO_DUMMY)
 | 
			
		||||
    set(SDL_VIDEO_DRIVER_DUMMY 1)
 | 
			
		||||
 
 | 
			
		||||
@@ -293,6 +293,7 @@
 | 
			
		||||
#cmakedefine SDL_JOYSTICK_USBHID_MACHINE_JOYSTICK_H @SDL_JOYSTICK_USBHID_MACHINE_JOYSTICK_H@
 | 
			
		||||
#cmakedefine SDL_JOYSTICK_HIDAPI @SDL_JOYSTICK_HIDAPI@
 | 
			
		||||
#cmakedefine SDL_JOYSTICK_EMSCRIPTEN @SDL_JOYSTICK_EMSCRIPTEN@
 | 
			
		||||
#cmakedefine SDL_JOYSTICK_VIRTUAL @SDL_JOYSTICK_VIRTUAL@
 | 
			
		||||
#cmakedefine SDL_HAPTIC_DUMMY @SDL_HAPTIC_DUMMY@
 | 
			
		||||
#cmakedefine SDL_HAPTIC_LINUX @SDL_HAPTIC_LINUX@
 | 
			
		||||
#cmakedefine SDL_HAPTIC_IOKIT @SDL_HAPTIC_IOKIT@
 | 
			
		||||
 
 | 
			
		||||
@@ -64,7 +64,8 @@ typedef enum
 | 
			
		||||
    SDL_CONTROLLER_TYPE_XBOXONE,
 | 
			
		||||
    SDL_CONTROLLER_TYPE_PS3,
 | 
			
		||||
    SDL_CONTROLLER_TYPE_PS4,
 | 
			
		||||
    SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO
 | 
			
		||||
    SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO,
 | 
			
		||||
    SDL_CONTROLLER_TYPE_VIRTUAL
 | 
			
		||||
} SDL_GameControllerType;
 | 
			
		||||
 | 
			
		||||
typedef enum
 | 
			
		||||
 
 | 
			
		||||
@@ -105,6 +105,7 @@ typedef enum
 | 
			
		||||
    SDL_JOYSTICK_POWER_MAX
 | 
			
		||||
} SDL_JoystickPowerLevel;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Function prototypes */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -199,6 +200,36 @@ extern DECLSPEC SDL_Joystick *SDLCALL SDL_JoystickFromInstanceID(SDL_JoystickID
 | 
			
		||||
 */
 | 
			
		||||
extern DECLSPEC SDL_Joystick *SDLCALL SDL_JoystickFromPlayerIndex(int player_index);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Attaches a new virtual joystick.
 | 
			
		||||
 * Returns the joystick's device index, or -1 if an error occurred.
 | 
			
		||||
 */
 | 
			
		||||
extern DECLSPEC int SDLCALL SDL_JoystickAttachVirtual(SDL_JoystickType type,
 | 
			
		||||
                                                      int naxes,
 | 
			
		||||
                                                      int nballs,
 | 
			
		||||
                                                      int nbuttons,
 | 
			
		||||
                                                      int nhats);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Detaches a virtual joystick
 | 
			
		||||
 * Returns 0 on success, or -1 if an error occurred.
 | 
			
		||||
 */
 | 
			
		||||
extern DECLSPEC int SDLCALL SDL_JoystickDetachVirtual(int device_index);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Indicates whether or not a virtual-joystick is at a given device index.
 | 
			
		||||
 */
 | 
			
		||||
extern DECLSPEC SDL_bool SDLCALL SDL_JoystickIsVirtual(int device_index);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Set values on an opened, virtual-joystick's controls.
 | 
			
		||||
 * Returns 0 on success, -1 on error.
 | 
			
		||||
 */
 | 
			
		||||
extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualAxis(SDL_Joystick * joystick, int axis, Sint16 value);
 | 
			
		||||
extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualBall(SDL_Joystick * joystick, int ball, Sint16 xrel, Sint16 yrel);
 | 
			
		||||
extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualButton(SDL_Joystick * joystick, int button, Uint8 value);
 | 
			
		||||
extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualHat(SDL_Joystick * joystick, int hat, Uint8 value);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  Return the name for this currently opened joystick.
 | 
			
		||||
 *  If no name can be found, this function returns NULL.
 | 
			
		||||
 
 | 
			
		||||
@@ -749,3 +749,10 @@
 | 
			
		||||
#define SDL_GetAndroidSDKVersion SDL_GetAndroidSDKVersion_REAL
 | 
			
		||||
#define SDL_isupper SDL_isupper_REAL
 | 
			
		||||
#define SDL_islower SDL_islower_REAL
 | 
			
		||||
#define SDL_JoystickAttachVirtual SDL_JoystickAttachVirtual_REAL
 | 
			
		||||
#define SDL_JoystickDetachVirtual SDL_JoystickDetachVirtual_REAL
 | 
			
		||||
#define SDL_JoystickIsVirtual SDL_JoystickIsVirtual_REAL
 | 
			
		||||
#define SDL_JoystickSetVirtualAxis SDL_JoystickSetVirtualAxis_REAL
 | 
			
		||||
#define SDL_JoystickSetVirtualBall SDL_JoystickSetVirtualBall_REAL
 | 
			
		||||
#define SDL_JoystickSetVirtualButton SDL_JoystickSetVirtualButton_REAL
 | 
			
		||||
#define SDL_JoystickSetVirtualHat SDL_JoystickSetVirtualHat_REAL
 | 
			
		||||
 
 | 
			
		||||
@@ -809,3 +809,10 @@ SDL_DYNAPI_PROC(int,SDL_GetAndroidSDKVersion,(void),(),return)
 | 
			
		||||
#endif
 | 
			
		||||
SDL_DYNAPI_PROC(int,SDL_isupper,(int a),(a),return)
 | 
			
		||||
SDL_DYNAPI_PROC(int,SDL_islower,(int a),(a),return)
 | 
			
		||||
SDL_DYNAPI_PROC(int,SDL_JoystickAttachVirtual,(SDL_JoystickType a, int b, int c, int d, int e),(a,b,c,d,e),return)
 | 
			
		||||
SDL_DYNAPI_PROC(int,SDL_JoystickDetachVirtual,(int a),(a),return)
 | 
			
		||||
SDL_DYNAPI_PROC(SDL_bool,SDL_JoystickIsVirtual,(int a),(a),return)
 | 
			
		||||
SDL_DYNAPI_PROC(int,SDL_JoystickSetVirtualAxis,(SDL_Joystick *a, int b, Sint16 c),(a,b,c),return)
 | 
			
		||||
SDL_DYNAPI_PROC(int,SDL_JoystickSetVirtualBall,(SDL_Joystick *a, int b, Sint16 c, Sint16 d),(a,b,c,d),return)
 | 
			
		||||
SDL_DYNAPI_PROC(int,SDL_JoystickSetVirtualButton,(SDL_Joystick *a, int b, Uint8 c),(a,b,c),return)
 | 
			
		||||
SDL_DYNAPI_PROC(int,SDL_JoystickSetVirtualHat,(SDL_Joystick *a, int b, Uint8 c),(a,b,c),return)
 | 
			
		||||
 
 | 
			
		||||
@@ -707,6 +707,9 @@ static const char *s_ControllerMappings [] =
 | 
			
		||||
    "05000000de2800000611000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,",
 | 
			
		||||
    "050000005e040000e0020000df070000,Xbox Wireless Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,",
 | 
			
		||||
#endif
 | 
			
		||||
#if defined(SDL_JOYSTICK_VIRTUAL)
 | 
			
		||||
    "00000000000000000000000000007601,Virtual Joystick,a:b0,b:b1,x:b2,y:b3,back:b4,guide:b5,start:b6,leftstick:b7,rightstick:b8,leftshoulder:b9,rightshoulder:b10,dpup:b11,dpdown:b12,dpleft:b13,dpright:b14,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5",
 | 
			
		||||
#endif
 | 
			
		||||
#if defined(SDL_JOYSTICK_EMSCRIPTEN)
 | 
			
		||||
    "default,Standard Gamepad,a:b0,b:b1,back:b8,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b16,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,",
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -46,6 +46,10 @@
 | 
			
		||||
#include <tlhelp32.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if SDL_JOYSTICK_VIRTUAL
 | 
			
		||||
#include "./virtual/SDL_sysjoystick_c.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static SDL_JoystickDriver *SDL_joystick_drivers[] = {
 | 
			
		||||
#if defined(SDL_JOYSTICK_DINPUT) || defined(SDL_JOYSTICK_XINPUT)
 | 
			
		||||
    &SDL_WINDOWS_JoystickDriver,
 | 
			
		||||
@@ -74,6 +78,9 @@ static SDL_JoystickDriver *SDL_joystick_drivers[] = {
 | 
			
		||||
#ifdef SDL_JOYSTICK_HIDAPI
 | 
			
		||||
    &SDL_HIDAPI_JoystickDriver,
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef SDL_JOYSTICK_VIRTUAL
 | 
			
		||||
    &SDL_VIRTUAL_JoystickDriver,
 | 
			
		||||
#endif
 | 
			
		||||
#if defined(SDL_JOYSTICK_DUMMY) || defined(SDL_JOYSTICK_DISABLED)
 | 
			
		||||
    &SDL_DUMMY_JoystickDriver
 | 
			
		||||
#endif
 | 
			
		||||
@@ -456,6 +463,115 @@ SDL_JoystickOpen(int device_index)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
SDL_JoystickAttachVirtual(SDL_JoystickType type,
 | 
			
		||||
                          int naxes,
 | 
			
		||||
                          int nballs,
 | 
			
		||||
                          int nbuttons,
 | 
			
		||||
                          int nhats)
 | 
			
		||||
{
 | 
			
		||||
#if SDL_JOYSTICK_VIRTUAL
 | 
			
		||||
    return SDL_JoystickAttachVirtualInner(type,
 | 
			
		||||
                                          naxes,
 | 
			
		||||
                                          nballs,
 | 
			
		||||
                                          nbuttons,
 | 
			
		||||
                                          nhats);
 | 
			
		||||
#else
 | 
			
		||||
    return SDL_SetError("SDL not built with virtual-joystick support");
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
SDL_JoystickDetachVirtual(int device_index)
 | 
			
		||||
{
 | 
			
		||||
#if SDL_JOYSTICK_VIRTUAL
 | 
			
		||||
    SDL_JoystickDriver *driver;
 | 
			
		||||
 | 
			
		||||
    SDL_LockJoysticks();
 | 
			
		||||
    if (SDL_GetDriverAndJoystickIndex(device_index, &driver, &device_index)) {
 | 
			
		||||
        if (driver == &SDL_VIRTUAL_JoystickDriver) {
 | 
			
		||||
            const int result = SDL_JoystickDetachVirtualInner(device_index);
 | 
			
		||||
            SDL_UnlockJoysticks();
 | 
			
		||||
            return result;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    SDL_UnlockJoysticks();
 | 
			
		||||
 | 
			
		||||
    return SDL_SetError("Virtual joystick not found at provided index");
 | 
			
		||||
#else
 | 
			
		||||
    return SDL_SetError("SDL not built with virtual-joystick support");
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
SDL_bool
 | 
			
		||||
SDL_JoystickIsVirtual(int device_index)
 | 
			
		||||
{
 | 
			
		||||
#if SDL_JOYSTICK_VIRTUAL
 | 
			
		||||
    SDL_JoystickDriver *driver;
 | 
			
		||||
    int driver_device_index;
 | 
			
		||||
    SDL_bool is_virtual = SDL_FALSE;
 | 
			
		||||
 | 
			
		||||
    SDL_LockJoysticks();
 | 
			
		||||
    if (SDL_GetDriverAndJoystickIndex(device_index, &driver, &driver_device_index)) {
 | 
			
		||||
        if (driver == &SDL_VIRTUAL_JoystickDriver) {
 | 
			
		||||
            is_virtual = SDL_TRUE;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    SDL_UnlockJoysticks();
 | 
			
		||||
 | 
			
		||||
    return is_virtual;
 | 
			
		||||
#else
 | 
			
		||||
    return SDL_FALSE;
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
SDL_JoystickSetVirtualAxis(SDL_Joystick * joystick, int axis, Sint16 value)
 | 
			
		||||
{
 | 
			
		||||
#if SDL_JOYSTICK_VIRTUAL
 | 
			
		||||
    return SDL_JoystickSetVirtualAxisInner(joystick, axis, value);
 | 
			
		||||
#else
 | 
			
		||||
    return SDL_SetError("SDL not built with virtual-joystick support");
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
SDL_JoystickSetVirtualBall(SDL_Joystick * joystick, int axis, Sint16 xrel, Sint16 yrel)
 | 
			
		||||
{
 | 
			
		||||
#if SDL_JOYSTICK_VIRTUAL
 | 
			
		||||
    return SDL_JoystickSetVirtualBallInner(joystick, axis, xrel, yrel);
 | 
			
		||||
#else
 | 
			
		||||
    return SDL_SetError("SDL not built with virtual-joystick support");
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
SDL_JoystickSetVirtualButton(SDL_Joystick * joystick, int button, Uint8 value)
 | 
			
		||||
{
 | 
			
		||||
#if SDL_JOYSTICK_VIRTUAL
 | 
			
		||||
    return SDL_JoystickSetVirtualButtonInner(joystick, button, value);
 | 
			
		||||
#else
 | 
			
		||||
    return SDL_SetError("SDL not built with virtual-joystick support");
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
SDL_JoystickSetVirtualHat(SDL_Joystick * joystick, int hat, Uint8 value)
 | 
			
		||||
{
 | 
			
		||||
#if SDL_JOYSTICK_VIRTUAL
 | 
			
		||||
    return SDL_JoystickSetVirtualHatInner(joystick, hat, value);
 | 
			
		||||
#else
 | 
			
		||||
    return SDL_SetError("SDL not built with virtual-joystick support");
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Checks to make sure the joystick is valid.
 | 
			
		||||
 */
 | 
			
		||||
@@ -1563,6 +1679,8 @@ SDL_GetJoystickGameControllerType(const char *name, Uint16 vendor, Uint16 produc
 | 
			
		||||
                SDL_strcmp(name, "Wireless Gamepad") == 0) {
 | 
			
		||||
                /* HORI or PowerA Switch Pro Controller clone */
 | 
			
		||||
                type = SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO;
 | 
			
		||||
            } else if (SDL_strcmp(name, "Virtual Joystick") == 0) {
 | 
			
		||||
                type = SDL_CONTROLLER_TYPE_VIRTUAL;
 | 
			
		||||
            } else {
 | 
			
		||||
                type = SDL_CONTROLLER_TYPE_UNKNOWN;
 | 
			
		||||
            }
 | 
			
		||||
@@ -1624,6 +1742,12 @@ SDL_IsJoystickHIDAPI(SDL_JoystickGUID guid)
 | 
			
		||||
    return (guid.data[14] == 'h') ? SDL_TRUE : SDL_FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SDL_bool
 | 
			
		||||
SDL_IsJoystickVirtual(SDL_JoystickGUID guid)
 | 
			
		||||
{
 | 
			
		||||
    return (guid.data[14] == 'v') ? SDL_TRUE : SDL_FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static SDL_bool SDL_IsJoystickProductWheel(Uint32 vidpid)
 | 
			
		||||
{
 | 
			
		||||
    static Uint32 wheel_joysticks[] = {
 | 
			
		||||
@@ -1715,6 +1839,10 @@ static SDL_JoystickType SDL_GetJoystickGUIDType(SDL_JoystickGUID guid)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (SDL_IsJoystickVirtual(guid)) {
 | 
			
		||||
        return (SDL_JoystickType)guid.data[15];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SDL_GetJoystickGUIDInfo(guid, &vendor, &product, NULL);
 | 
			
		||||
    vidpid = MAKE_VIDPID(vendor, product);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -73,6 +73,9 @@ extern SDL_bool SDL_IsJoystickXInput(SDL_JoystickGUID guid);
 | 
			
		||||
/* Function to return whether a joystick guid comes from the HIDAPI driver */
 | 
			
		||||
extern SDL_bool SDL_IsJoystickHIDAPI(SDL_JoystickGUID guid);
 | 
			
		||||
 | 
			
		||||
/* Function to return whether a joystick guid comes from the Virtual driver */
 | 
			
		||||
extern SDL_bool SDL_IsJoystickVirtual(SDL_JoystickGUID guid);
 | 
			
		||||
 | 
			
		||||
/* Function to return whether a joystick should be ignored */
 | 
			
		||||
extern SDL_bool SDL_ShouldIgnoreJoystick(const char *name, SDL_JoystickGUID guid);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -152,6 +152,7 @@ extern SDL_JoystickDriver SDL_HAIKU_JoystickDriver;
 | 
			
		||||
extern SDL_JoystickDriver SDL_HIDAPI_JoystickDriver;
 | 
			
		||||
extern SDL_JoystickDriver SDL_IOS_JoystickDriver;
 | 
			
		||||
extern SDL_JoystickDriver SDL_LINUX_JoystickDriver;
 | 
			
		||||
extern SDL_JoystickDriver SDL_VIRTUAL_JoystickDriver;
 | 
			
		||||
extern SDL_JoystickDriver SDL_WINDOWS_JoystickDriver;
 | 
			
		||||
 | 
			
		||||
#endif /* SDL_sysjoystick_h_ */
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										455
									
								
								src/joystick/virtual/SDL_sysjoystick.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										455
									
								
								src/joystick/virtual/SDL_sysjoystick.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,455 @@
 | 
			
		||||
/*
 | 
			
		||||
  Simple DirectMedia Layer
 | 
			
		||||
  Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
 | 
			
		||||
 | 
			
		||||
  This software is provided 'as-is', without any express or implied
 | 
			
		||||
  warranty.  In no event will the authors be held liable for any damages
 | 
			
		||||
  arising from the use of this software.
 | 
			
		||||
 | 
			
		||||
  Permission is granted to anyone to use this software for any purpose,
 | 
			
		||||
  including commercial applications, and to alter it and redistribute it
 | 
			
		||||
  freely, subject to the following restrictions:
 | 
			
		||||
 | 
			
		||||
  1. The origin of this software must not be misrepresented; you must not
 | 
			
		||||
     claim that you wrote the original software. If you use this software
 | 
			
		||||
     in a product, an acknowledgment in the product documentation would be
 | 
			
		||||
     appreciated but is not required.
 | 
			
		||||
  2. Altered source versions must be plainly marked as such, and must not be
 | 
			
		||||
     misrepresented as being the original software.
 | 
			
		||||
  3. This notice may not be removed or altered from any source distribution.
 | 
			
		||||
*/
 | 
			
		||||
#include "../../SDL_internal.h"
 | 
			
		||||
 | 
			
		||||
#if defined(SDL_JOYSTICK_VIRTUAL)
 | 
			
		||||
 | 
			
		||||
/* This is the virtual implementation of the SDL joystick API */
 | 
			
		||||
 | 
			
		||||
#include "SDL_sysjoystick_c.h"
 | 
			
		||||
#include "../SDL_sysjoystick.h"
 | 
			
		||||
#include "../SDL_joystick_c.h"
 | 
			
		||||
 | 
			
		||||
extern SDL_JoystickDriver SDL_VIRTUAL_JoystickDriver;
 | 
			
		||||
 | 
			
		||||
static joystick_hwdata * g_VJoys = NULL;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static joystick_hwdata *
 | 
			
		||||
VIRTUAL_HWDataForIndex(int device_index)
 | 
			
		||||
{
 | 
			
		||||
    joystick_hwdata *vjoy = g_VJoys;
 | 
			
		||||
    while (vjoy) {
 | 
			
		||||
        if (device_index == 0)
 | 
			
		||||
            break;
 | 
			
		||||
        --device_index;
 | 
			
		||||
        vjoy = vjoy->next;
 | 
			
		||||
    }
 | 
			
		||||
    return vjoy;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
VIRTUAL_FreeHWData(joystick_hwdata *hwdata)
 | 
			
		||||
{
 | 
			
		||||
    if (!hwdata) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    if (hwdata->axes) {
 | 
			
		||||
        SDL_free((void *)hwdata->axes);
 | 
			
		||||
        hwdata->axes = NULL;
 | 
			
		||||
    }
 | 
			
		||||
    if (hwdata->balls) {
 | 
			
		||||
        SDL_free((void *)hwdata->balls);
 | 
			
		||||
        hwdata->balls = NULL;
 | 
			
		||||
    }
 | 
			
		||||
    if (hwdata->buttons) {
 | 
			
		||||
        SDL_free((void *)hwdata->buttons);
 | 
			
		||||
        hwdata->buttons = NULL;
 | 
			
		||||
    }
 | 
			
		||||
    if (hwdata->hats) {
 | 
			
		||||
        SDL_free(hwdata->hats);
 | 
			
		||||
        hwdata->hats = NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Remove hwdata from SDL-global list */
 | 
			
		||||
    joystick_hwdata * cur = g_VJoys;
 | 
			
		||||
    joystick_hwdata * prev = NULL;
 | 
			
		||||
    while (cur) {
 | 
			
		||||
        if (hwdata == cur) {
 | 
			
		||||
            if (prev) {
 | 
			
		||||
                prev->next = cur->next;
 | 
			
		||||
            } else {
 | 
			
		||||
                g_VJoys = cur->next;
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        prev = cur;
 | 
			
		||||
        cur = cur->next;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SDL_free(hwdata);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
SDL_JoystickAttachVirtualInner(SDL_JoystickType type,
 | 
			
		||||
                               int naxes,
 | 
			
		||||
                               int nballs,
 | 
			
		||||
                               int nbuttons,
 | 
			
		||||
                               int nhats)
 | 
			
		||||
{
 | 
			
		||||
    joystick_hwdata *hwdata = NULL;
 | 
			
		||||
    int device_index = -1;
 | 
			
		||||
 | 
			
		||||
    hwdata = SDL_calloc(1, sizeof(joystick_hwdata));
 | 
			
		||||
    if (!hwdata) {
 | 
			
		||||
        VIRTUAL_FreeHWData(hwdata);
 | 
			
		||||
        return SDL_OutOfMemory();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    hwdata->naxes = naxes;
 | 
			
		||||
    hwdata->nballs = nballs;
 | 
			
		||||
    hwdata->nbuttons = nbuttons;
 | 
			
		||||
    hwdata->nhats = nhats;
 | 
			
		||||
    hwdata->name = "Virtual Joystick";
 | 
			
		||||
 | 
			
		||||
    /* Note that this is a Virtual device and what subtype it is */
 | 
			
		||||
    hwdata->guid.data[14] = 'v';
 | 
			
		||||
    hwdata->guid.data[15] = (Uint8)type;
 | 
			
		||||
 | 
			
		||||
    /* Allocate fields for different control-types */
 | 
			
		||||
    if (naxes > 0) {
 | 
			
		||||
        hwdata->axes = SDL_calloc(naxes, sizeof(Sint16));
 | 
			
		||||
        if (!hwdata->axes) {
 | 
			
		||||
            VIRTUAL_FreeHWData(hwdata);
 | 
			
		||||
            return SDL_OutOfMemory();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if (nballs > 0) {
 | 
			
		||||
        hwdata->balls = SDL_calloc(nballs, sizeof(hwdata->balls[0]));
 | 
			
		||||
        if (!hwdata->balls) {
 | 
			
		||||
            VIRTUAL_FreeHWData(hwdata);
 | 
			
		||||
            return SDL_OutOfMemory();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if (nbuttons > 0) {
 | 
			
		||||
        hwdata->buttons = SDL_calloc(nbuttons, sizeof(Uint8));
 | 
			
		||||
        if (!hwdata->buttons) {
 | 
			
		||||
            VIRTUAL_FreeHWData(hwdata);
 | 
			
		||||
            return SDL_OutOfMemory();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if (nhats > 0) {
 | 
			
		||||
        hwdata->hats = SDL_calloc(nhats, sizeof(Uint8));
 | 
			
		||||
        if (!hwdata->hats) {
 | 
			
		||||
            VIRTUAL_FreeHWData(hwdata);
 | 
			
		||||
            return SDL_OutOfMemory();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Allocate an instance ID for this device */
 | 
			
		||||
    hwdata->instance_id = SDL_GetNextJoystickInstanceID();
 | 
			
		||||
 | 
			
		||||
    /* Add virtual joystick to SDL-global lists */
 | 
			
		||||
    hwdata->next = g_VJoys;
 | 
			
		||||
    g_VJoys = hwdata;
 | 
			
		||||
    SDL_PrivateJoystickAdded(hwdata->instance_id);
 | 
			
		||||
 | 
			
		||||
    /* Return the new virtual-device's index */
 | 
			
		||||
    device_index = SDL_JoystickGetDeviceIndexFromInstanceID(hwdata->instance_id);
 | 
			
		||||
    return device_index;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
SDL_JoystickDetachVirtualInner(int device_index)
 | 
			
		||||
{
 | 
			
		||||
    SDL_JoystickID instance_id;
 | 
			
		||||
    joystick_hwdata *hwdata = VIRTUAL_HWDataForIndex(device_index);
 | 
			
		||||
    if (!hwdata) {
 | 
			
		||||
        return SDL_SetError("Virtual joystick data not found");
 | 
			
		||||
    }
 | 
			
		||||
    instance_id = hwdata->instance_id;
 | 
			
		||||
    VIRTUAL_FreeHWData(hwdata);
 | 
			
		||||
    SDL_PrivateJoystickRemoved(instance_id);
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
SDL_JoystickSetVirtualAxisInner(SDL_Joystick * joystick, int axis, Sint16 value)
 | 
			
		||||
{
 | 
			
		||||
    joystick_hwdata *hwdata;
 | 
			
		||||
 | 
			
		||||
    SDL_LockJoysticks();
 | 
			
		||||
 | 
			
		||||
    if (!joystick || !joystick->hwdata) {
 | 
			
		||||
        SDL_UnlockJoysticks();
 | 
			
		||||
        return SDL_SetError("Invalid joystick");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    hwdata = (joystick_hwdata *)joystick->hwdata;
 | 
			
		||||
    if (axis < 0 || axis >= hwdata->nbuttons) {
 | 
			
		||||
        SDL_UnlockJoysticks();
 | 
			
		||||
        return SDL_SetError("Invalid axis index");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    hwdata->axes[axis] = value;
 | 
			
		||||
 | 
			
		||||
    SDL_UnlockJoysticks();
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
SDL_JoystickSetVirtualBallInner(SDL_Joystick * joystick, int ball, Sint16 xrel, Sint16 yrel)
 | 
			
		||||
{
 | 
			
		||||
    joystick_hwdata *hwdata;
 | 
			
		||||
 | 
			
		||||
    SDL_LockJoysticks();
 | 
			
		||||
 | 
			
		||||
    if (!joystick || !joystick->hwdata) {
 | 
			
		||||
        SDL_UnlockJoysticks();
 | 
			
		||||
        return SDL_SetError("Invalid joystick");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    hwdata = (joystick_hwdata *)joystick->hwdata;
 | 
			
		||||
    if (ball < 0 || ball >= hwdata->nbuttons) {
 | 
			
		||||
        SDL_UnlockJoysticks();
 | 
			
		||||
        return SDL_SetError("Invalid ball index");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    hwdata->balls[ball].xrel = xrel;
 | 
			
		||||
    hwdata->balls[ball].yrel = yrel;
 | 
			
		||||
 | 
			
		||||
    SDL_UnlockJoysticks();
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
SDL_JoystickSetVirtualButtonInner(SDL_Joystick * joystick, int button, Uint8 value)
 | 
			
		||||
{
 | 
			
		||||
    joystick_hwdata *hwdata;
 | 
			
		||||
 | 
			
		||||
    SDL_LockJoysticks();
 | 
			
		||||
 | 
			
		||||
    if (!joystick || !joystick->hwdata) {
 | 
			
		||||
        SDL_UnlockJoysticks();
 | 
			
		||||
        return SDL_SetError("Invalid joystick");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    hwdata = (joystick_hwdata *)joystick->hwdata;
 | 
			
		||||
    if (button < 0 || button >= hwdata->nbuttons) {
 | 
			
		||||
        SDL_UnlockJoysticks();
 | 
			
		||||
        return SDL_SetError("Invalid button index");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    hwdata->buttons[button] = value;
 | 
			
		||||
 | 
			
		||||
    SDL_UnlockJoysticks();
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
SDL_JoystickSetVirtualHatInner(SDL_Joystick * joystick, int hat, Uint8 value)
 | 
			
		||||
{
 | 
			
		||||
    joystick_hwdata *hwdata;
 | 
			
		||||
 | 
			
		||||
    SDL_LockJoysticks();
 | 
			
		||||
 | 
			
		||||
    if (!joystick || !joystick->hwdata) {
 | 
			
		||||
        SDL_UnlockJoysticks();
 | 
			
		||||
        return SDL_SetError("Invalid joystick");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    hwdata = (joystick_hwdata *)joystick->hwdata;
 | 
			
		||||
    if (hat < 0 || hat >= hwdata->nbuttons) {
 | 
			
		||||
        SDL_UnlockJoysticks();
 | 
			
		||||
        return SDL_SetError("Invalid hat index");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    hwdata->hats[hat] = value;
 | 
			
		||||
 | 
			
		||||
    SDL_UnlockJoysticks();
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
VIRTUAL_JoystickInit(void)
 | 
			
		||||
{
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
VIRTUAL_JoystickGetCount(void)
 | 
			
		||||
{
 | 
			
		||||
    int count = 0;
 | 
			
		||||
    joystick_hwdata *cur = g_VJoys;
 | 
			
		||||
    while (cur) {
 | 
			
		||||
        ++count;
 | 
			
		||||
        cur = cur->next;
 | 
			
		||||
    }
 | 
			
		||||
    return count;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
VIRTUAL_JoystickDetect(void)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static const char *
 | 
			
		||||
VIRTUAL_JoystickGetDeviceName(int device_index)
 | 
			
		||||
{
 | 
			
		||||
    joystick_hwdata *hwdata = VIRTUAL_HWDataForIndex(device_index);
 | 
			
		||||
    if (!hwdata) {
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
    return hwdata->name ? hwdata->name : "";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
VIRTUAL_JoystickGetDevicePlayerIndex(int device_index)
 | 
			
		||||
{
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
VIRTUAL_JoystickSetDevicePlayerIndex(int device_index, int player_index)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static SDL_JoystickGUID
 | 
			
		||||
VIRTUAL_JoystickGetDeviceGUID(int device_index)
 | 
			
		||||
{
 | 
			
		||||
    joystick_hwdata *hwdata = VIRTUAL_HWDataForIndex(device_index);
 | 
			
		||||
    if (!hwdata) {
 | 
			
		||||
        SDL_JoystickGUID guid;
 | 
			
		||||
        SDL_zero(guid);
 | 
			
		||||
        return guid;
 | 
			
		||||
    }
 | 
			
		||||
    return hwdata->guid;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static SDL_JoystickID
 | 
			
		||||
VIRTUAL_JoystickGetDeviceInstanceID(int device_index)
 | 
			
		||||
{
 | 
			
		||||
    joystick_hwdata *hwdata = VIRTUAL_HWDataForIndex(device_index);
 | 
			
		||||
    if (!hwdata) {
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
    return hwdata->instance_id;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
VIRTUAL_JoystickOpen(SDL_Joystick * joystick, int device_index)
 | 
			
		||||
{
 | 
			
		||||
    joystick_hwdata *hwdata = VIRTUAL_HWDataForIndex(device_index);
 | 
			
		||||
    if (!hwdata) {
 | 
			
		||||
        return SDL_SetError("No such device");
 | 
			
		||||
    }
 | 
			
		||||
    if (hwdata->opened) {
 | 
			
		||||
        return SDL_SetError("Joystick already opened");
 | 
			
		||||
    }
 | 
			
		||||
    joystick->instance_id = hwdata->instance_id;
 | 
			
		||||
    joystick->hwdata = hwdata;
 | 
			
		||||
    joystick->naxes = hwdata->naxes;
 | 
			
		||||
    joystick->nballs = hwdata->nballs;
 | 
			
		||||
    joystick->nbuttons = hwdata->nbuttons;
 | 
			
		||||
    joystick->nhats = hwdata->nhats;
 | 
			
		||||
    hwdata->opened = SDL_TRUE;
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
VIRTUAL_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
 | 
			
		||||
{
 | 
			
		||||
    return SDL_Unsupported();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
VIRTUAL_JoystickUpdate(SDL_Joystick * joystick)
 | 
			
		||||
{
 | 
			
		||||
    joystick_hwdata *hwdata;
 | 
			
		||||
 | 
			
		||||
    if (!joystick) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    if (!joystick->hwdata) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    hwdata = (joystick_hwdata *)joystick->hwdata;
 | 
			
		||||
 | 
			
		||||
    for (int i = 0; i < hwdata->naxes; ++i) {
 | 
			
		||||
        SDL_PrivateJoystickAxis(joystick, i, hwdata->axes[i]);
 | 
			
		||||
    }
 | 
			
		||||
    for (int i = 0; i < hwdata->nballs; ++i) {
 | 
			
		||||
        SDL_PrivateJoystickBall(joystick, i, hwdata->balls[i].xrel, hwdata->balls[i].yrel);
 | 
			
		||||
    }
 | 
			
		||||
    for (int i = 0; i < hwdata->nbuttons; ++i) {
 | 
			
		||||
        SDL_PrivateJoystickButton(joystick, i, hwdata->buttons[i]);
 | 
			
		||||
    }
 | 
			
		||||
    for (int i = 0; i < hwdata->nhats; ++i) {
 | 
			
		||||
        SDL_PrivateJoystickHat(joystick, i, hwdata->hats[i]);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
VIRTUAL_JoystickClose(SDL_Joystick * joystick)
 | 
			
		||||
{
 | 
			
		||||
    joystick_hwdata *hwdata;
 | 
			
		||||
 | 
			
		||||
    if (!joystick) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    if (!joystick->hwdata) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    hwdata = (joystick_hwdata *)joystick->hwdata;
 | 
			
		||||
    hwdata->opened = SDL_FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
VIRTUAL_JoystickQuit(void)
 | 
			
		||||
{
 | 
			
		||||
    while (g_VJoys) {
 | 
			
		||||
        VIRTUAL_FreeHWData(g_VJoys);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
SDL_JoystickDriver SDL_VIRTUAL_JoystickDriver =
 | 
			
		||||
{
 | 
			
		||||
    VIRTUAL_JoystickInit,
 | 
			
		||||
    VIRTUAL_JoystickGetCount,
 | 
			
		||||
    VIRTUAL_JoystickDetect,
 | 
			
		||||
    VIRTUAL_JoystickGetDeviceName,
 | 
			
		||||
    VIRTUAL_JoystickGetDevicePlayerIndex,
 | 
			
		||||
    VIRTUAL_JoystickSetDevicePlayerIndex,
 | 
			
		||||
    VIRTUAL_JoystickGetDeviceGUID,
 | 
			
		||||
    VIRTUAL_JoystickGetDeviceInstanceID,
 | 
			
		||||
    VIRTUAL_JoystickOpen,
 | 
			
		||||
    VIRTUAL_JoystickRumble,
 | 
			
		||||
    VIRTUAL_JoystickUpdate,
 | 
			
		||||
    VIRTUAL_JoystickClose,
 | 
			
		||||
    VIRTUAL_JoystickQuit,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif /* SDL_JOYSTICK_VIRTUAL || SDL_JOYSTICK_DISABLED */
 | 
			
		||||
 | 
			
		||||
/* vi: set ts=4 sw=4 expandtab: */
 | 
			
		||||
							
								
								
									
										69
									
								
								src/joystick/virtual/SDL_sysjoystick_c.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								src/joystick/virtual/SDL_sysjoystick_c.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,69 @@
 | 
			
		||||
/*
 | 
			
		||||
  Simple DirectMedia Layer
 | 
			
		||||
  Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
 | 
			
		||||
 | 
			
		||||
  This software is provided 'as-is', without any express or implied
 | 
			
		||||
  warranty.  In no event will the authors be held liable for any damages
 | 
			
		||||
  arising from the use of this software.
 | 
			
		||||
 | 
			
		||||
  Permission is granted to anyone to use this software for any purpose,
 | 
			
		||||
  including commercial applications, and to alter it and redistribute it
 | 
			
		||||
  freely, subject to the following restrictions:
 | 
			
		||||
 | 
			
		||||
  1. The origin of this software must not be misrepresented; you must not
 | 
			
		||||
     claim that you wrote the original software. If you use this software
 | 
			
		||||
     in a product, an acknowledgment in the product documentation would be
 | 
			
		||||
     appreciated but is not required.
 | 
			
		||||
  2. Altered source versions must be plainly marked as such, and must not be
 | 
			
		||||
     misrepresented as being the original software.
 | 
			
		||||
  3. This notice may not be removed or altered from any source distribution.
 | 
			
		||||
*/
 | 
			
		||||
#include "../../SDL_internal.h"
 | 
			
		||||
 | 
			
		||||
#ifndef SDL_JOYSTICK_VIRTUAL_H
 | 
			
		||||
#define SDL_JOYSTICK_VIRTUAL_H
 | 
			
		||||
 | 
			
		||||
#if SDL_JOYSTICK_VIRTUAL
 | 
			
		||||
 | 
			
		||||
#include "SDL_joystick.h"
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Data for a virtual, software-only joystick.
 | 
			
		||||
 */
 | 
			
		||||
typedef struct joystick_hwdata
 | 
			
		||||
{
 | 
			
		||||
    SDL_JoystickType type;
 | 
			
		||||
    SDL_bool attached;
 | 
			
		||||
    const char *name;
 | 
			
		||||
    SDL_JoystickGUID guid;
 | 
			
		||||
    int naxes;
 | 
			
		||||
    Sint16 *axes;
 | 
			
		||||
    int nballs;
 | 
			
		||||
    struct {
 | 
			
		||||
        Sint16 xrel;
 | 
			
		||||
        Sint16 yrel;
 | 
			
		||||
    } *balls;
 | 
			
		||||
    int nbuttons;
 | 
			
		||||
    Uint8 *buttons;
 | 
			
		||||
    int nhats;
 | 
			
		||||
    Uint8 *hats;
 | 
			
		||||
    SDL_JoystickID instance_id;
 | 
			
		||||
    SDL_bool opened;
 | 
			
		||||
    struct joystick_hwdata *next;
 | 
			
		||||
} joystick_hwdata;
 | 
			
		||||
 | 
			
		||||
int SDL_JoystickAttachVirtualInner(SDL_JoystickType type,
 | 
			
		||||
                                   int naxes,
 | 
			
		||||
                                   int nballs,
 | 
			
		||||
                                   int nbuttons,
 | 
			
		||||
                                   int nhats);
 | 
			
		||||
 | 
			
		||||
int SDL_JoystickDetachVirtualInner(int device_index);
 | 
			
		||||
 | 
			
		||||
int SDL_JoystickSetVirtualAxisInner(SDL_Joystick * joystick, int axis, Sint16 value);
 | 
			
		||||
int SDL_JoystickSetVirtualBallInner(SDL_Joystick * joystick, int ball, Sint16 xrel, Sint16 yrel);
 | 
			
		||||
int SDL_JoystickSetVirtualButtonInner(SDL_Joystick * joystick, int button, Uint8 value);
 | 
			
		||||
int SDL_JoystickSetVirtualHatInner(SDL_Joystick * joystick, int hat, Uint8 value);
 | 
			
		||||
 | 
			
		||||
#endif  /* SDL_JOYSTICK_VIRTUAL */
 | 
			
		||||
#endif  /* SDL_JOYSTICK_VIRTUAL_H */
 | 
			
		||||
@@ -310,6 +310,9 @@ main(int argc, char *argv[])
 | 
			
		||||
            case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO:
 | 
			
		||||
                description = "Nintendo Switch Pro Controller";
 | 
			
		||||
                break;
 | 
			
		||||
            case SDL_CONTROLLER_TYPE_VIRTUAL:
 | 
			
		||||
                description = "Virtual Game Controller";
 | 
			
		||||
                break;
 | 
			
		||||
            default:
 | 
			
		||||
                description = "Game Controller";
 | 
			
		||||
                break;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user