Added the option for GameInput support to the Win32 SDL build

GameInput is designed to be used by Win32 C applications, so no need to restrict it to the GDK build.
main
Sam Lantinga 2024-02-17 14:07:42 -08:00
parent 534f753e20
commit fee140bdfe
8 changed files with 90 additions and 80 deletions

View File

@ -425,6 +425,7 @@
<ClInclude Include="..\..\src\hidapi\hidapi\hidapi.h" />
<ClInclude Include="..\..\src\hidapi\SDL_hidapi_c.h" />
<ClInclude Include="..\..\src\joystick\controller_type.h" />
<ClInclude Include="..\..\src\joystick\gdk\SDL_gameinputjoystick_c.h" />
<ClInclude Include="..\..\src\joystick\hidapi\SDL_hidapijoystick_c.h" />
<ClInclude Include="..\..\src\joystick\hidapi\SDL_hidapi_rumble.h" />
<ClInclude Include="..\..\src\joystick\SDL_gamepad_c.h" />
@ -438,7 +439,6 @@
<ClInclude Include="..\..\src\joystick\windows\SDL_rawinputjoystick_c.h" />
<ClInclude Include="..\..\src\joystick\windows\SDL_windowsjoystick_c.h" />
<ClInclude Include="..\..\src\joystick\windows\SDL_xinputjoystick_c.h" />
<ClInclude Include="..\..\src\joystick\gdk\SDL_gameinputjoystick_c.h" />
<ClInclude Include="..\..\src\libm\math_libm.h" />
<ClInclude Include="..\..\src\libm\math_private.h" />
<ClInclude Include="..\..\src\locale\SDL_syslocale.h" />
@ -646,6 +646,7 @@
<ClCompile Include="..\..\src\hidapi\SDL_hidapi.c" />
<ClCompile Include="..\..\src\joystick\controller_type.c" />
<ClCompile Include="..\..\src\joystick\dummy\SDL_sysjoystick.c" />
<ClCompile Include="..\..\src\joystick\gdk\SDL_gameinputjoystick.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapijoystick.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_combined.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_gamecube.c" />
@ -690,10 +691,6 @@
<CompileAs Condition="'$(Configuration)|$(Platform)'=='Release|Gaming.Xbox.Scarlett.x64'">CompileAsCpp</CompileAs>
<CompileAs Condition="'$(Configuration)|$(Platform)'=='Release|Gaming.Xbox.XboxOne.x64'">CompileAsCpp</CompileAs>
</ClCompile>
<ClCompile Include="..\..\src\joystick\gdk\SDL_gameinputjoystick.cpp">
<PrecompiledHeaderOutputFile Condition="'$(Configuration)|$(Platform)'=='Debug|Gaming.Desktop.x64'">$(IntDir)$(TargetName)_cpp.pch</PrecompiledHeaderOutputFile>
<PrecompiledHeaderOutputFile Condition="'$(Configuration)|$(Platform)'=='Release|Gaming.Desktop.x64'">$(IntDir)$(TargetName)_cpp.pch</PrecompiledHeaderOutputFile>
</ClCompile>
<ClCompile Include="..\..\src\libm\e_atan2.c" />
<ClCompile Include="..\..\src\libm\e_exp.c" />
<ClCompile Include="..\..\src\libm\e_fmod.c" />

View File

@ -52,6 +52,7 @@
<ClCompile Include="..\..\src\hidapi\SDL_hidapi.c" />
<ClCompile Include="..\..\src\joystick\controller_type.c" />
<ClCompile Include="..\..\src\joystick\dummy\SDL_sysjoystick.c" />
<ClCompile Include="..\..\src\joystick\gdk\SDL_gameinputjoystick.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapijoystick.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_combined.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_gamecube.c" />
@ -319,6 +320,7 @@
<ClInclude Include="..\..\src\hidapi\hidapi\hidapi.h" />
<ClInclude Include="..\..\src\hidapi\SDL_hidapi_c.h" />
<ClInclude Include="..\..\src\joystick\controller_type.h" />
<ClInclude Include="..\..\src\joystick\gdk\SDL_gameinputjoystick_c.h" />
<ClInclude Include="..\..\src\joystick\hidapi\SDL_hidapijoystick_c.h" />
<ClInclude Include="..\..\src\joystick\hidapi\SDL_hidapi_rumble.h" />
<ClInclude Include="..\..\src\joystick\SDL_gamepad_c.h" />

View File

@ -347,6 +347,7 @@
<ClInclude Include="..\..\src\hidapi\hidapi\hidapi.h" />
<ClInclude Include="..\..\src\hidapi\SDL_hidapi_c.h" />
<ClInclude Include="..\..\src\joystick\controller_type.h" />
<ClInclude Include="..\..\src\joystick\gdk\SDL_gameinputjoystick_c.h" />
<ClInclude Include="..\..\src\joystick\hidapi\SDL_hidapijoystick_c.h" />
<ClInclude Include="..\..\src\joystick\hidapi\SDL_hidapi_rumble.h" />
<ClInclude Include="..\..\src\joystick\SDL_gamepad_c.h" />
@ -520,6 +521,7 @@
<ClCompile Include="..\..\src\hidapi\SDL_hidapi.c" />
<ClCompile Include="..\..\src\joystick\controller_type.c" />
<ClCompile Include="..\..\src\joystick\dummy\SDL_sysjoystick.c" />
<ClCompile Include="..\..\src\joystick\gdk\SDL_gameinputjoystick.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapijoystick.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_combined.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_gamecube.c" />

View File

@ -88,6 +88,9 @@
<Filter Include="joystick\dummy">
<UniqueIdentifier>{d008487d-6ed0-4251-848b-79a68e3c1459}</UniqueIdentifier>
</Filter>
<Filter Include="joystick\gdk">
<UniqueIdentifier>{c9e8273e-13ae-47dc-bef8-8ad8e64c9a3e}</UniqueIdentifier>
</Filter>
<Filter Include="joystick\hidapi">
<UniqueIdentifier>{c9e8273e-13ae-47dc-bef8-8ad8e64c9a3d}</UniqueIdentifier>
</Filter>
@ -546,6 +549,9 @@
<ClInclude Include="..\..\src\haptic\windows\SDL_windowshaptic_c.h">
<Filter>haptic\windows</Filter>
</ClInclude>
<ClInclude Include="..\..\src\joystick\gdk\SDL_gameinputjoystick_c.h">
<Filter>joystick\gdk</Filter>
</ClInclude>
<ClInclude Include="..\..\src\joystick\hidapi\SDL_hidapijoystick_c.h">
<Filter>joystick\hidapi</Filter>
</ClInclude>
@ -1063,6 +1069,9 @@
<ClCompile Include="..\..\src\joystick\dummy\SDL_sysjoystick.c">
<Filter>joystick\dummy</Filter>
</ClCompile>
<ClCompile Include="..\..\src\joystick\gdk\SDL_gameinputjoystick.c">
<Filter>joystick\gdk</Filter>
</ClCompile>
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_combined.c">
<Filter>joystick\hidapi</Filter>
</ClCompile>

View File

@ -238,6 +238,7 @@ typedef unsigned int uintptr_t;
/* Enable various input drivers */
#define SDL_JOYSTICK_DINPUT 1
/*#define SDL_JOYSTICK_GAMEINPUT 1*/
#define SDL_JOYSTICK_HIDAPI 1
#ifndef SDL_PLATFORM_WINRT
#define SDL_JOYSTICK_RAWINPUT 1

View File

@ -20,8 +20,6 @@
*/
#include "SDL_internal.h"
#ifndef SDL_JOYSTICK_GAMEINPUT
#include "SDL_xinput.h"
/* Set up for C function definitions, even when using C++ */
@ -144,5 +142,3 @@ void WIN_UnloadXInputDLL(void)
#ifdef __cplusplus
}
#endif
#endif /* !SDL_JOYSTICK_GAMEINPUT */

View File

@ -18,6 +18,8 @@
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "SDL_internal.h"
#include "SDL_gameinputjoystick_c.h"
#if defined(SDL_JOYSTICK_GAMEINPUT) && SDL_JOYSTICK_GAMEINPUT
@ -39,9 +41,9 @@ typedef struct GAMEINPUT_InternalDevice
SDL_JoystickGUID joystickGuid; /* generated by SDL. */
SDL_JoystickID instanceId; /* generated by SDL. */
int playerIndex;
Uint32 caps;
GameInputRumbleMotors supportedRumbleMotors;
char devicePath[(APP_LOCAL_DEVICE_ID_SIZE * 2) + 1];
bool isAdded, isDeleteRequested;
SDL_bool isAdded, isDeleteRequested;
} GAMEINPUT_InternalDevice;
typedef struct GAMEINPUT_InternalList
@ -59,6 +61,7 @@ typedef struct joystick_hwdata
static GAMEINPUT_InternalList g_GameInputList = { NULL };
static void *g_hGameInputDLL = NULL;
static IGameInput *g_pGameInput = NULL;
static GameInputCallbackToken g_GameInputCallbackToken = GAMEINPUT_INVALID_CALLBACK_TOKEN_VALUE;
@ -75,7 +78,7 @@ static int GAMEINPUT_InternalAddOrFind(IGameInputDevice *pDevice)
return SDL_SetError("GAMEINPUT_InternalAddOrFind argument pDevice cannot be NULL");
}
devinfo = pDevice->GetDeviceInfo();
devinfo = IGameInputDevice_GetDeviceInfo(pDevice);
if (!devinfo) {
return SDL_SetError("GAMEINPUT_InternalAddOrFind GetDeviceInfo returned NULL");
}
@ -95,8 +98,8 @@ static int GAMEINPUT_InternalAddOrFind(IGameInputDevice *pDevice)
/* generate a device name */
for (idx = 0; idx < APP_LOCAL_DEVICE_ID_SIZE; ++idx) {
(void)SDL_snprintf(tmpbuff, SDL_arraysize(tmpbuff), "%02hhX", devinfo->deviceId.value[idx]);
(void)strncat_s(elem->devicePath, tmpbuff, SDL_arraysize(tmpbuff));
SDL_snprintf(tmpbuff, SDL_arraysize(tmpbuff), "%02hhX", devinfo->deviceId.value[idx]);
SDL_strlcat(elem->devicePath, tmpbuff, SDL_arraysize(tmpbuff));
}
devicelist = (GAMEINPUT_InternalDevice **)SDL_realloc(g_GameInputList.devices, sizeof(elem) * (g_GameInputList.count + 1LL));
@ -106,16 +109,10 @@ static int GAMEINPUT_InternalAddOrFind(IGameInputDevice *pDevice)
}
g_GameInputList.devices = devicelist;
pDevice->AddRef();
IGameInputDevice_AddRef(pDevice);
elem->device = pDevice;
elem->deviceName = "GameInput Gamepad";
elem->caps = 0;
if (devinfo->supportedRumbleMotors & (GameInputRumbleLowFrequency | GameInputRumbleHighFrequency)) {
elem->caps |= SDL_JOYSTICK_CAP_RUMBLE;
}
if (devinfo->supportedRumbleMotors & (GameInputRumbleLeftTrigger | GameInputRumbleRightTrigger)) {
elem->caps |= SDL_JOYSTICK_CAP_TRIGGER_RUMBLE;
}
elem->supportedRumbleMotors = devinfo->supportedRumbleMotors;
elem->joystickGuid = SDL_CreateJoystickGUID(
SDL_HARDWARE_BUS_BLUETOOTH,
USB_VENDOR_MICROSOFT,
@ -142,7 +139,7 @@ static int GAMEINPUT_InternalRemoveByIndex(int idx)
return SDL_SetError("GAMEINPUT_InternalRemoveByIndex argument idx %d is out of range", idx);
}
g_GameInputList.devices[idx]->device->Release();
IGameInputDevice_Release(g_GameInputList.devices[idx]->device);
if (g_GameInputList.devices[idx]) {
SDL_free(g_GameInputList.devices[idx]);
@ -199,7 +196,7 @@ static void CALLBACK GAMEINPUT_InternalJoystickDeviceCallback(
elem = g_GameInputList.devices[idx];
if (elem && elem->device == device) {
/* will be deleted on the next Detect call */
elem->isDeleteRequested = true;
elem->isDeleteRequested = SDL_TRUE;
break;
}
}
@ -212,29 +209,40 @@ static int GAMEINPUT_JoystickInit(void)
{
HRESULT hR;
if (!g_hGameInputDLL) {
g_hGameInputDLL = SDL_LoadObject("gameinput.dll");
if (!g_hGameInputDLL) {
return -1;
}
}
if (!g_pGameInput) {
hR = GameInputCreate(&g_pGameInput);
typedef HRESULT (WINAPI *GameInputCreate_t)(IGameInput * *gameInput);
GameInputCreate_t GameInputCreateFunc = (GameInputCreate_t)SDL_LoadFunction(g_hGameInputDLL, "GameInputCreate");
if (!GameInputCreateFunc) {
return -1;
}
hR = GameInputCreateFunc(&g_pGameInput);
if (FAILED(hR)) {
return SDL_SetError("GameInputCreate failure with HRESULT of %08X", hR);
}
}
hR = g_pGameInput->RegisterDeviceCallback(
nullptr,
GameInputKindGamepad,
GameInputDeviceConnected,
GameInputBlockingEnumeration,
nullptr,
GAMEINPUT_InternalJoystickDeviceCallback,
&g_GameInputCallbackToken
);
hR = IGameInput_RegisterDeviceCallback(g_pGameInput,
NULL,
GameInputKindGamepad,
GameInputDeviceConnected,
GameInputBlockingEnumeration,
NULL,
GAMEINPUT_InternalJoystickDeviceCallback,
&g_GameInputCallbackToken);
if (FAILED(hR)) {
return SDL_SetError("IGameInput::RegisterDeviceCallback failure with HRESULT of %08X", hR);
}
GAMEINPUT_JoystickDetect();
/* no need to free IGameInput on failure. */
return 0;
}
@ -256,10 +264,10 @@ static void GAMEINPUT_JoystickDetect(void)
if (!elem->isAdded) {
SDL_PrivateJoystickAdded(elem->instanceId);
elem->isAdded = true;
elem->isAdded = SDL_TRUE;
}
if (elem->isDeleteRequested || !(elem->device->GetDeviceStatus() & GameInputDeviceConnected)) {
if (elem->isDeleteRequested || !(IGameInputDevice_GetDeviceStatus(elem->device) & GameInputDeviceConnected)) {
SDL_PrivateJoystickRemoved(elem->instanceId);
GAMEINPUT_InternalRemoveByIndex(idx--);
}
@ -332,8 +340,8 @@ static SDL_JoystickGUID GAMEINPUT_JoystickGetDeviceGUID(int device_index)
GAMEINPUT_InternalDevice *elem = GAMEINPUT_InternalFindByIndex(device_index);
if (!elem) {
/* empty guid */
return { { 0 } };
static SDL_JoystickGUID emptyGUID;
return emptyGUID;
}
return elem->joystickGuid;
@ -371,6 +379,13 @@ static int GAMEINPUT_JoystickOpen(SDL_Joystick *joystick, int device_index)
joystick->nbuttons = 11;
joystick->nhats = 1;
if (elem->supportedRumbleMotors & (GameInputRumbleLowFrequency | GameInputRumbleHighFrequency)) {
SDL_SetBooleanProperty(SDL_GetJoystickProperties(joystick), SDL_PROP_JOYSTICK_CAP_RUMBLE_BOOLEAN, SDL_TRUE);
}
if (elem->supportedRumbleMotors & (GameInputRumbleLeftTrigger | GameInputRumbleRightTrigger)) {
SDL_SetBooleanProperty(SDL_GetJoystickProperties(joystick), SDL_PROP_JOYSTICK_CAP_TRIGGER_RUMBLE_BOOLEAN, SDL_TRUE);
}
return 0;
}
@ -381,7 +396,7 @@ static int GAMEINPUT_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency
GameInputRumbleParams *params = &hwdata->rumbleParams;
params->lowFrequency = (float)low_frequency_rumble / (float)SDL_MAX_UINT16;
params->highFrequency = (float)high_frequency_rumble / (float)SDL_MAX_UINT16;
hwdata->devref->device->SetRumbleState(params);
IGameInputDevice_SetRumbleState(hwdata->devref->device, params);
return 0;
}
@ -392,15 +407,10 @@ static int GAMEINPUT_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_
GameInputRumbleParams *params = &hwdata->rumbleParams;
params->leftTrigger = (float)left_rumble / (float)SDL_MAX_UINT16;
params->rightTrigger = (float)right_rumble / (float)SDL_MAX_UINT16;
hwdata->devref->device->SetRumbleState(params);
IGameInputDevice_SetRumbleState(hwdata->devref->device, params);
return 0;
}
static Uint32 GAMEINPUT_JoystickGetCapabilities(SDL_Joystick *joystick)
{
return joystick->hwdata->devref->caps;
}
static int GAMEINPUT_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue)
{
return SDL_Unsupported();
@ -418,7 +428,7 @@ static int GAMEINPUT_JoystickSendEffect(SDL_Joystick *joystick, const void *data
effect = (const GAMEINPUT_JoystickEffectData *)data;
if (effect->type == GAMEINPUT_JoystickEffectDataType_HapticFeedback) {
hR = hwdata->devref->device->SetHapticMotorState(
hR = IGameInputDevice_SetHapticMotorState(hwdata->devref->device,
effect->hapticFeedbackMotorIndex,
&effect->hapticFeedbackParams
);
@ -450,7 +460,7 @@ static void GAMEINPUT_JoystickUpdate(SDL_Joystick *joystick)
IGameInputReading *reading = NULL;
uint64_t ts = 0;
GameInputGamepadState state;
HRESULT hR = g_pGameInput->GetCurrentReading(
HRESULT hR = IGameInput_GetCurrentReading(g_pGameInput,
GameInputKindGamepad,
device,
&reading
@ -463,9 +473,9 @@ static void GAMEINPUT_JoystickUpdate(SDL_Joystick *joystick)
/* GDKX private docs for GetTimestamp: "The microsecond timestamp describing when the input was made." */
/* SDL expects a nanosecond timestamp, so I guess US_TO_NS should be used here? */
ts = SDL_US_TO_NS(reading->GetTimestamp());
ts = SDL_US_TO_NS(IGameInputReading_GetTimestamp(reading));
if (((!hwdata->lastTimestamp) || (ts != hwdata->lastTimestamp)) && reading->GetGamepadState(&state)) {
if (((!hwdata->lastTimestamp) || (ts != hwdata->lastTimestamp)) && IGameInputReading_GetGamepadState(reading, &state)) {
/* `state` is now valid */
#define tosint16(_TheValue) ((Sint16)(((_TheValue) < 0.0f) ? ((_TheValue) * 32768.0f) : ((_TheValue) * 32767.0f)))
@ -507,7 +517,7 @@ static void GAMEINPUT_JoystickUpdate(SDL_Joystick *joystick)
hwdata->lastTimestamp = ts;
}
reading->Release();
IGameInputReading_Release(reading);
}
static void GAMEINPUT_JoystickClose(SDL_Joystick* joystick)
@ -520,26 +530,29 @@ static void GAMEINPUT_JoystickQuit(void)
{
int idx;
if (!g_pGameInput) {
return;
if (g_pGameInput) {
/* free the callback */
IGameInput_UnregisterCallback(g_pGameInput, g_GameInputCallbackToken, /*timeoutInUs:*/ 10000);
g_GameInputCallbackToken = GAMEINPUT_INVALID_CALLBACK_TOKEN_VALUE;
/* free the list */
for (idx = 0; idx < g_GameInputList.count; ++idx) {
IGameInputDevice_Release(g_GameInputList.devices[idx]->device);
SDL_free(g_GameInputList.devices[idx]);
g_GameInputList.devices[idx] = NULL;
}
SDL_free(g_GameInputList.devices);
g_GameInputList.devices = NULL;
g_GameInputList.count = 0;
IGameInput_Release(g_pGameInput);
g_pGameInput = NULL;
}
/* free the callback */
g_pGameInput->UnregisterCallback(g_GameInputCallbackToken, /*timeoutInUs:*/ 10000);
g_GameInputCallbackToken = GAMEINPUT_INVALID_CALLBACK_TOKEN_VALUE;
/* free the list */
for (idx = 0; idx < g_GameInputList.count; ++idx) {
g_GameInputList.devices[idx]->device->Release();
SDL_free(g_GameInputList.devices[idx]);
g_GameInputList.devices[idx] = NULL;
if (g_hGameInputDLL) {
SDL_UnloadObject(g_hGameInputDLL);
g_hGameInputDLL = NULL;
}
SDL_free(g_GameInputList.devices);
g_GameInputList.devices = NULL;
g_GameInputList.count = 0;
g_pGameInput->Release();
g_pGameInput = NULL;
}
static SDL_bool GAMEINPUT_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping *out)
@ -563,7 +576,6 @@ SDL_JoystickDriver SDL_GAMEINPUT_JoystickDriver =
GAMEINPUT_JoystickOpen,
GAMEINPUT_JoystickRumble,
GAMEINPUT_JoystickRumbleTriggers,
GAMEINPUT_JoystickGetCapabilities,
GAMEINPUT_JoystickSetLED,
GAMEINPUT_JoystickSendEffect,
GAMEINPUT_JoystickSetSensorsEnabled,

View File

@ -23,14 +23,10 @@
#if defined(SDL_JOYSTICK_GAMEINPUT) && SDL_JOYSTICK_GAMEINPUT
/* include this file in C++ */
#include <stdbool.h>
#define COBJMACROS
#include <GameInput.h>
/* Set up for C function definitions, even when using C++ */
#ifdef __cplusplus
extern "C" {
#endif
typedef enum GAMEINPUT_JoystickEffectDataType
{
GAMEINPUT_JoystickEffectDataType_HapticFeedback
@ -50,9 +46,4 @@ typedef struct GAMEINPUT_JoystickEffectData
};
} GAMEINPUT_JoystickEffectData;
/* Ends C function definitions when using C++ */
#ifdef __cplusplus
}
#endif
#endif /* defined(SDL_JOYSTICK_GAMEINPUT) && SDL_JOYSTICK_GAMEINPUT */