You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-16 14:00:40 +00:00
Support adding advanced joypad features
This commit is contained in:
@@ -986,6 +986,15 @@ void Input::set_joy_axis(int p_device, JoyAxis p_axis, float p_value) {
|
||||
_joy_axis[c] = p_value;
|
||||
}
|
||||
|
||||
void Input::set_joy_features(int p_device, JoypadFeatures *p_features) {
|
||||
Joypad *joypad = joy_names.getptr(p_device);
|
||||
if (!joypad) {
|
||||
return;
|
||||
}
|
||||
joypad->features = p_features;
|
||||
_update_joypad_features(p_device);
|
||||
}
|
||||
|
||||
void Input::start_joy_vibration(int p_device, float p_weak_magnitude, float p_strong_magnitude, float p_duration) {
|
||||
_THREAD_SAFE_METHOD_
|
||||
if (p_weak_magnitude < 0.f || p_weak_magnitude > 1.f || p_strong_magnitude < 0.f || p_strong_magnitude > 1.f) {
|
||||
@@ -1478,6 +1487,15 @@ void Input::_update_action_cache(const StringName &p_action_name, ActionState &r
|
||||
}
|
||||
}
|
||||
|
||||
void Input::_update_joypad_features(int p_device) {
|
||||
Joypad *joypad = joy_names.getptr(p_device);
|
||||
if (!joypad || joypad->features == nullptr) {
|
||||
return;
|
||||
}
|
||||
// Do something based on the features. For example, we can save the information about
|
||||
// the joypad having motion sensors, LED light, etc.
|
||||
}
|
||||
|
||||
Input::JoyEvent Input::_get_mapped_button_event(const JoyDeviceMapping &mapping, JoyButton p_button) {
|
||||
JoyEvent event;
|
||||
|
||||
|
||||
@@ -79,6 +79,15 @@ public:
|
||||
CURSOR_MAX
|
||||
};
|
||||
|
||||
class JoypadFeatures {
|
||||
public:
|
||||
virtual ~JoypadFeatures() {}
|
||||
|
||||
// None at the moment, but later we can add new features like:
|
||||
// virtual bool has_joy_accelerometer() const { return false; }
|
||||
// virtual bool set_joy_accelerometer_enabled(bool p_enable) { return false; }
|
||||
};
|
||||
|
||||
static constexpr int32_t JOYPADS_MAX = 16;
|
||||
|
||||
typedef void (*EventDispatchFunc)(const Ref<InputEvent> &p_event);
|
||||
@@ -174,6 +183,7 @@ private:
|
||||
int mapping = -1;
|
||||
int hat_current = 0;
|
||||
Dictionary info;
|
||||
Input::JoypadFeatures *features = nullptr;
|
||||
};
|
||||
|
||||
VelocityTrack mouse_velocity_track;
|
||||
@@ -253,6 +263,7 @@ private:
|
||||
void _button_event(int p_device, JoyButton p_index, bool p_pressed);
|
||||
void _axis_event(int p_device, JoyAxis p_axis, float p_value);
|
||||
void _update_action_cache(const StringName &p_action_name, ActionState &r_action_state);
|
||||
void _update_joypad_features(int p_device);
|
||||
|
||||
void _parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_emulated);
|
||||
|
||||
@@ -346,6 +357,8 @@ public:
|
||||
void set_gyroscope(const Vector3 &p_gyroscope);
|
||||
void set_joy_axis(int p_device, JoyAxis p_axis, float p_value);
|
||||
|
||||
void set_joy_features(int p_device, JoypadFeatures *p_features);
|
||||
|
||||
void start_joy_vibration(int p_device, float p_weak_magnitude, float p_strong_magnitude, float p_duration = 0);
|
||||
void stop_joy_vibration(int p_device);
|
||||
void vibrate_handheld(int p_duration_ms = 500, float p_amplitude = -1.0);
|
||||
|
||||
@@ -178,6 +178,7 @@ if env["builtin_sdl"]:
|
||||
"joystick/windows/SDL_xinputjoystick.c",
|
||||
"thread/generic/SDL_syscond.c",
|
||||
"thread/generic/SDL_sysrwlock.c",
|
||||
"sensor/windows/SDL_windowssensor.c",
|
||||
"thread/windows/SDL_syscond_cv.c",
|
||||
"thread/windows/SDL_sysmutex.c",
|
||||
"thread/windows/SDL_sysrwlock_srw.c",
|
||||
|
||||
@@ -47,7 +47,6 @@
|
||||
#define SDL_DIALOG_DISABLED 1
|
||||
#define SDL_FILESYSTEM_DUMMY 1
|
||||
#define SDL_FSOPS_DUMMY 1
|
||||
#define SDL_SENSOR_DISABLED 1
|
||||
#define SDL_GPU_DISABLED 1
|
||||
#define SDL_RENDER_DISABLED 1
|
||||
#define SDL_POWER_DISABLED 1
|
||||
@@ -73,6 +72,7 @@
|
||||
#define SDL_THREAD_GENERIC_RWLOCK_SUFFIX 1
|
||||
#define SDL_THREAD_WINDOWS 1
|
||||
#define SDL_TIMER_WINDOWS 1
|
||||
#define SDL_SENSOR_WINDOWS 1
|
||||
|
||||
// Linux defines
|
||||
#elif defined(SDL_PLATFORM_LINUX)
|
||||
@@ -113,6 +113,7 @@
|
||||
#define SDL_HAPTIC_LINUX 1
|
||||
#define SDL_TIMER_UNIX 1
|
||||
#define SDL_JOYSTICK_LINUX 1
|
||||
#define SDL_JOYSTICK_HIDAPI 1
|
||||
#define SDL_INPUT_LINUXEV 1
|
||||
#define SDL_THREAD_PTHREAD 1
|
||||
|
||||
@@ -126,8 +127,10 @@
|
||||
#define SDL_HAPTIC_IOKIT 1
|
||||
#define SDL_JOYSTICK_IOKIT 1
|
||||
#define SDL_JOYSTICK_MFI 1
|
||||
#define SDL_JOYSTICK_HIDAPI 1
|
||||
#define SDL_TIMER_UNIX 1
|
||||
#define SDL_THREAD_PTHREAD 1
|
||||
#define SDL_THREAD_PTHREAD_RECURSIVE_MUTEX 1
|
||||
|
||||
// Other platforms are not supported (for now)
|
||||
#else
|
||||
|
||||
@@ -208,6 +208,8 @@ void JoypadSDL::process_events() {
|
||||
device_name,
|
||||
joypads[joy_id].guid,
|
||||
joypad_info);
|
||||
|
||||
Input::get_singleton()->set_joy_features(joy_id, &joypads[joy_id]);
|
||||
}
|
||||
// An event for an attached joypad
|
||||
} else if (sdl_event.type >= SDL_EVENT_JOYSTICK_AXIS_MOTION && sdl_event.type < SDL_EVENT_FINGER_DOWN && sdl_instance_id_to_joypad_id.has(sdl_event.jdevice.which)) {
|
||||
@@ -299,4 +301,12 @@ void JoypadSDL::close_joypad(int p_pad_idx) {
|
||||
}
|
||||
}
|
||||
|
||||
SDL_Joystick *JoypadSDL::Joypad::get_sdl_joystick() const {
|
||||
return SDL_GetJoystickFromID(sdl_instance_idx);
|
||||
}
|
||||
|
||||
SDL_Gamepad *JoypadSDL::Joypad::get_sdl_gamepad() const {
|
||||
return SDL_GetGamepadFromID(sdl_instance_idx);
|
||||
}
|
||||
|
||||
#endif // SDL_ENABLED
|
||||
|
||||
@@ -35,6 +35,8 @@
|
||||
|
||||
typedef uint32_t SDL_JoystickID;
|
||||
typedef struct HWND__ *HWND;
|
||||
typedef struct SDL_Joystick SDL_Joystick;
|
||||
typedef struct SDL_Gamepad SDL_Gamepad;
|
||||
|
||||
class JoypadSDL {
|
||||
public:
|
||||
@@ -50,7 +52,8 @@ public:
|
||||
void process_events();
|
||||
|
||||
private:
|
||||
struct Joypad {
|
||||
class Joypad : public Input::JoypadFeatures {
|
||||
public:
|
||||
bool attached = false;
|
||||
StringName guid;
|
||||
|
||||
@@ -58,6 +61,9 @@ private:
|
||||
|
||||
bool supports_force_feedback = false;
|
||||
uint64_t ff_effect_timestamp = 0;
|
||||
|
||||
SDL_Joystick *get_sdl_joystick() const;
|
||||
SDL_Gamepad *get_sdl_gamepad() const;
|
||||
};
|
||||
|
||||
static JoypadSDL *singleton;
|
||||
|
||||
485
thirdparty/sdl/sensor/windows/SDL_windowssensor.c
vendored
Normal file
485
thirdparty/sdl/sensor/windows/SDL_windowssensor.c
vendored
Normal file
@@ -0,0 +1,485 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2025 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"
|
||||
|
||||
#ifdef SDL_SENSOR_WINDOWS
|
||||
|
||||
#include "SDL_windowssensor.h"
|
||||
#include "../SDL_syssensor.h"
|
||||
#include "../../core/windows/SDL_windows.h"
|
||||
|
||||
#define COBJMACROS
|
||||
#include <initguid.h>
|
||||
#include <sensorsapi.h>
|
||||
#include <sensors.h>
|
||||
|
||||
DEFINE_GUID(SDL_CLSID_SensorManager, 0x77A1C827, 0xFCD2, 0x4689, 0x89, 0x15, 0x9D, 0x61, 0x3C, 0xC5, 0xFA, 0x3E);
|
||||
DEFINE_GUID(SDL_IID_SensorManager, 0xBD77DB67, 0x45A8, 0x42DC, 0x8D, 0x00, 0x6D, 0xCF, 0x15, 0xF8, 0x37, 0x7A);
|
||||
DEFINE_GUID(SDL_IID_SensorManagerEvents, 0x9B3B0B86, 0x266A, 0x4AAD, 0xB2, 0x1F, 0xFD, 0xE5, 0x50, 0x10, 0x01, 0xB7);
|
||||
DEFINE_GUID(SDL_IID_SensorEvents, 0x5D8DCC91, 0x4641, 0x47E7, 0xB7, 0xC3, 0xB7, 0x4F, 0x48, 0xA6, 0xC3, 0x91);
|
||||
|
||||
// These constants aren't available in Visual Studio 2015 or earlier Windows SDK
|
||||
DEFINE_PROPERTYKEY(SDL_SENSOR_DATA_TYPE_ANGULAR_VELOCITY_X_DEGREES_PER_SECOND, 0X3F8A69A2, 0X7C5, 0X4E48, 0XA9, 0X65, 0XCD, 0X79, 0X7A, 0XAB, 0X56, 0XD5, 10); //[VT_R8]
|
||||
DEFINE_PROPERTYKEY(SDL_SENSOR_DATA_TYPE_ANGULAR_VELOCITY_Y_DEGREES_PER_SECOND, 0X3F8A69A2, 0X7C5, 0X4E48, 0XA9, 0X65, 0XCD, 0X79, 0X7A, 0XAB, 0X56, 0XD5, 11); //[VT_R8]
|
||||
DEFINE_PROPERTYKEY(SDL_SENSOR_DATA_TYPE_ANGULAR_VELOCITY_Z_DEGREES_PER_SECOND, 0X3F8A69A2, 0X7C5, 0X4E48, 0XA9, 0X65, 0XCD, 0X79, 0X7A, 0XAB, 0X56, 0XD5, 12); //[VT_R8]
|
||||
|
||||
typedef struct
|
||||
{
|
||||
SDL_SensorID id;
|
||||
ISensor *sensor;
|
||||
SENSOR_ID sensor_id;
|
||||
char *name;
|
||||
SDL_SensorType type;
|
||||
SDL_Sensor *sensor_opened;
|
||||
|
||||
} SDL_Windows_Sensor;
|
||||
|
||||
static bool SDL_windowscoinit;
|
||||
static ISensorManager *SDL_sensor_manager;
|
||||
static int SDL_num_sensors;
|
||||
static SDL_Windows_Sensor *SDL_sensors;
|
||||
|
||||
static bool ConnectSensor(ISensor *sensor);
|
||||
static bool DisconnectSensor(ISensor *sensor);
|
||||
|
||||
static HRESULT STDMETHODCALLTYPE ISensorManagerEventsVtbl_QueryInterface(ISensorManagerEvents *This, REFIID riid, void **ppvObject)
|
||||
{
|
||||
if (!ppvObject) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
*ppvObject = NULL;
|
||||
if (WIN_IsEqualIID(riid, &IID_IUnknown) || WIN_IsEqualIID(riid, &SDL_IID_SensorManagerEvents)) {
|
||||
*ppvObject = This;
|
||||
return S_OK;
|
||||
}
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
static ULONG STDMETHODCALLTYPE ISensorManagerEventsVtbl_AddRef(ISensorManagerEvents *This)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static ULONG STDMETHODCALLTYPE ISensorManagerEventsVtbl_Release(ISensorManagerEvents *This)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static HRESULT STDMETHODCALLTYPE ISensorManagerEventsVtbl_OnSensorEnter(ISensorManagerEvents *This, ISensor *pSensor, SensorState state)
|
||||
{
|
||||
ConnectSensor(pSensor);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static ISensorManagerEventsVtbl sensor_manager_events_vtbl = {
|
||||
ISensorManagerEventsVtbl_QueryInterface,
|
||||
ISensorManagerEventsVtbl_AddRef,
|
||||
ISensorManagerEventsVtbl_Release,
|
||||
ISensorManagerEventsVtbl_OnSensorEnter
|
||||
};
|
||||
static ISensorManagerEvents sensor_manager_events = {
|
||||
&sensor_manager_events_vtbl
|
||||
};
|
||||
|
||||
static HRESULT STDMETHODCALLTYPE ISensorEventsVtbl_QueryInterface(ISensorEvents *This, REFIID riid, void **ppvObject)
|
||||
{
|
||||
if (!ppvObject) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
*ppvObject = NULL;
|
||||
if (WIN_IsEqualIID(riid, &IID_IUnknown) || WIN_IsEqualIID(riid, &SDL_IID_SensorEvents)) {
|
||||
*ppvObject = This;
|
||||
return S_OK;
|
||||
}
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
static ULONG STDMETHODCALLTYPE ISensorEventsVtbl_AddRef(ISensorEvents *This)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static ULONG STDMETHODCALLTYPE ISensorEventsVtbl_Release(ISensorEvents *This)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static HRESULT STDMETHODCALLTYPE ISensorEventsVtbl_OnStateChanged(ISensorEvents *This, ISensor *pSensor, SensorState state)
|
||||
{
|
||||
#ifdef DEBUG_SENSORS
|
||||
int i;
|
||||
|
||||
SDL_LockSensors();
|
||||
for (i = 0; i < SDL_num_sensors; ++i) {
|
||||
if (pSensor == SDL_sensors[i].sensor) {
|
||||
SDL_Log("Sensor %s state changed to %d", SDL_sensors[i].name, state);
|
||||
}
|
||||
}
|
||||
SDL_UnlockSensors();
|
||||
#endif
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT STDMETHODCALLTYPE ISensorEventsVtbl_OnDataUpdated(ISensorEvents *This, ISensor *pSensor, ISensorDataReport *pNewData)
|
||||
{
|
||||
int i;
|
||||
Uint64 timestamp = SDL_GetTicksNS();
|
||||
|
||||
SDL_LockSensors();
|
||||
for (i = 0; i < SDL_num_sensors; ++i) {
|
||||
if (pSensor == SDL_sensors[i].sensor) {
|
||||
if (SDL_sensors[i].sensor_opened) {
|
||||
HRESULT hrX, hrY, hrZ;
|
||||
PROPVARIANT valueX = { 0 }, valueY = { 0 }, valueZ = { 0 };
|
||||
SYSTEMTIME sensor_systemtime;
|
||||
FILETIME sensor_filetime;
|
||||
Uint64 sensor_timestamp;
|
||||
|
||||
#ifdef DEBUG_SENSORS
|
||||
SDL_Log("Sensor %s data updated", SDL_sensors[i].name);
|
||||
#endif
|
||||
if (SUCCEEDED(ISensorDataReport_GetTimestamp(pNewData, &sensor_systemtime)) &&
|
||||
SystemTimeToFileTime(&sensor_systemtime, &sensor_filetime)) {
|
||||
ULARGE_INTEGER sensor_time;
|
||||
sensor_time.u.HighPart = sensor_filetime.dwHighDateTime;
|
||||
sensor_time.u.LowPart = sensor_filetime.dwLowDateTime;
|
||||
sensor_timestamp = sensor_time.QuadPart * 100;
|
||||
} else {
|
||||
sensor_timestamp = timestamp;
|
||||
}
|
||||
|
||||
switch (SDL_sensors[i].type) {
|
||||
case SDL_SENSOR_ACCEL:
|
||||
hrX = ISensorDataReport_GetSensorValue(pNewData, &SENSOR_DATA_TYPE_ACCELERATION_X_G, &valueX);
|
||||
hrY = ISensorDataReport_GetSensorValue(pNewData, &SENSOR_DATA_TYPE_ACCELERATION_Y_G, &valueY);
|
||||
hrZ = ISensorDataReport_GetSensorValue(pNewData, &SENSOR_DATA_TYPE_ACCELERATION_Z_G, &valueZ);
|
||||
if (SUCCEEDED(hrX) && SUCCEEDED(hrY) && SUCCEEDED(hrZ) &&
|
||||
valueX.vt == VT_R8 && valueY.vt == VT_R8 && valueZ.vt == VT_R8) {
|
||||
float values[3];
|
||||
|
||||
values[0] = (float)valueX.dblVal * SDL_STANDARD_GRAVITY;
|
||||
values[1] = (float)valueY.dblVal * SDL_STANDARD_GRAVITY;
|
||||
values[2] = (float)valueZ.dblVal * SDL_STANDARD_GRAVITY;
|
||||
SDL_SendSensorUpdate(timestamp, SDL_sensors[i].sensor_opened, sensor_timestamp, values, 3);
|
||||
}
|
||||
break;
|
||||
case SDL_SENSOR_GYRO:
|
||||
hrX = ISensorDataReport_GetSensorValue(pNewData, &SDL_SENSOR_DATA_TYPE_ANGULAR_VELOCITY_X_DEGREES_PER_SECOND, &valueX);
|
||||
hrY = ISensorDataReport_GetSensorValue(pNewData, &SDL_SENSOR_DATA_TYPE_ANGULAR_VELOCITY_Y_DEGREES_PER_SECOND, &valueY);
|
||||
hrZ = ISensorDataReport_GetSensorValue(pNewData, &SDL_SENSOR_DATA_TYPE_ANGULAR_VELOCITY_Z_DEGREES_PER_SECOND, &valueZ);
|
||||
if (SUCCEEDED(hrX) && SUCCEEDED(hrY) && SUCCEEDED(hrZ) &&
|
||||
valueX.vt == VT_R8 && valueY.vt == VT_R8 && valueZ.vt == VT_R8) {
|
||||
const float DEGREES_TO_RADIANS = (SDL_PI_F / 180.0f);
|
||||
float values[3];
|
||||
|
||||
values[0] = (float)valueX.dblVal * DEGREES_TO_RADIANS;
|
||||
values[1] = (float)valueY.dblVal * DEGREES_TO_RADIANS;
|
||||
values[2] = (float)valueZ.dblVal * DEGREES_TO_RADIANS;
|
||||
SDL_SendSensorUpdate(timestamp, SDL_sensors[i].sensor_opened, sensor_timestamp, values, 3);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// FIXME: Need to know how to interpret the data for this sensor
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
SDL_UnlockSensors();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT STDMETHODCALLTYPE ISensorEventsVtbl_OnEvent(ISensorEvents *This, ISensor *pSensor, REFGUID eventID, IPortableDeviceValues *pEventData)
|
||||
{
|
||||
#ifdef DEBUG_SENSORS
|
||||
int i;
|
||||
|
||||
SDL_LockSensors();
|
||||
for (i = 0; i < SDL_num_sensors; ++i) {
|
||||
if (pSensor == SDL_sensors[i].sensor) {
|
||||
SDL_Log("Sensor %s event occurred", SDL_sensors[i].name);
|
||||
}
|
||||
}
|
||||
SDL_UnlockSensors();
|
||||
#endif
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT STDMETHODCALLTYPE ISensorEventsVtbl_OnLeave(ISensorEvents *This, REFSENSOR_ID ID)
|
||||
{
|
||||
int i;
|
||||
|
||||
SDL_LockSensors();
|
||||
for (i = 0; i < SDL_num_sensors; ++i) {
|
||||
if (WIN_IsEqualIID(ID, &SDL_sensors[i].sensor_id)) {
|
||||
#ifdef DEBUG_SENSORS
|
||||
SDL_Log("Sensor %s disconnected", SDL_sensors[i].name);
|
||||
#endif
|
||||
DisconnectSensor(SDL_sensors[i].sensor);
|
||||
}
|
||||
}
|
||||
SDL_UnlockSensors();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static ISensorEventsVtbl sensor_events_vtbl = {
|
||||
ISensorEventsVtbl_QueryInterface,
|
||||
ISensorEventsVtbl_AddRef,
|
||||
ISensorEventsVtbl_Release,
|
||||
ISensorEventsVtbl_OnStateChanged,
|
||||
ISensorEventsVtbl_OnDataUpdated,
|
||||
ISensorEventsVtbl_OnEvent,
|
||||
ISensorEventsVtbl_OnLeave
|
||||
};
|
||||
static ISensorEvents sensor_events = {
|
||||
&sensor_events_vtbl
|
||||
};
|
||||
|
||||
static bool ConnectSensor(ISensor *sensor)
|
||||
{
|
||||
SDL_Windows_Sensor *new_sensor, *new_sensors;
|
||||
HRESULT hr;
|
||||
SENSOR_ID sensor_id;
|
||||
SENSOR_TYPE_ID type_id;
|
||||
SDL_SensorType type;
|
||||
BSTR bstr_name = NULL;
|
||||
char *name;
|
||||
|
||||
hr = ISensor_GetID(sensor, &sensor_id);
|
||||
if (FAILED(hr)) {
|
||||
return WIN_SetErrorFromHRESULT("Couldn't get sensor ID", hr);
|
||||
}
|
||||
|
||||
hr = ISensor_GetType(sensor, &type_id);
|
||||
if (FAILED(hr)) {
|
||||
return WIN_SetErrorFromHRESULT("Couldn't get sensor type", hr);
|
||||
}
|
||||
|
||||
if (WIN_IsEqualIID(&type_id, &SENSOR_TYPE_ACCELEROMETER_3D)) {
|
||||
type = SDL_SENSOR_ACCEL;
|
||||
} else if (WIN_IsEqualIID(&type_id, &SENSOR_TYPE_GYROMETER_3D)) {
|
||||
type = SDL_SENSOR_GYRO;
|
||||
} else {
|
||||
return SDL_SetError("Unknown sensor type");
|
||||
}
|
||||
|
||||
hr = ISensor_GetFriendlyName(sensor, &bstr_name);
|
||||
if (SUCCEEDED(hr) && bstr_name) {
|
||||
name = WIN_StringToUTF8W(bstr_name);
|
||||
} else {
|
||||
name = SDL_strdup("Unknown Sensor");
|
||||
}
|
||||
if (bstr_name != NULL) {
|
||||
SysFreeString(bstr_name);
|
||||
}
|
||||
if (!name) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SDL_LockSensors();
|
||||
new_sensors = (SDL_Windows_Sensor *)SDL_realloc(SDL_sensors, (SDL_num_sensors + 1) * sizeof(SDL_Windows_Sensor));
|
||||
if (!new_sensors) {
|
||||
SDL_UnlockSensors();
|
||||
SDL_free(name);
|
||||
return false;
|
||||
}
|
||||
|
||||
ISensor_AddRef(sensor);
|
||||
ISensor_SetEventSink(sensor, &sensor_events);
|
||||
|
||||
SDL_sensors = new_sensors;
|
||||
new_sensor = &SDL_sensors[SDL_num_sensors];
|
||||
++SDL_num_sensors;
|
||||
|
||||
SDL_zerop(new_sensor);
|
||||
new_sensor->id = SDL_GetNextObjectID();
|
||||
new_sensor->sensor = sensor;
|
||||
new_sensor->type = type;
|
||||
new_sensor->name = name;
|
||||
|
||||
SDL_UnlockSensors();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool DisconnectSensor(ISensor *sensor)
|
||||
{
|
||||
SDL_Windows_Sensor *old_sensor;
|
||||
int i;
|
||||
|
||||
SDL_LockSensors();
|
||||
for (i = 0; i < SDL_num_sensors; ++i) {
|
||||
old_sensor = &SDL_sensors[i];
|
||||
if (sensor == old_sensor->sensor) {
|
||||
/* This call hangs for some reason:
|
||||
* https://github.com/libsdl-org/SDL/issues/5288
|
||||
*/
|
||||
// ISensor_SetEventSink(sensor, NULL);
|
||||
ISensor_Release(sensor);
|
||||
SDL_free(old_sensor->name);
|
||||
--SDL_num_sensors;
|
||||
if (i < SDL_num_sensors) {
|
||||
SDL_memmove(&SDL_sensors[i], &SDL_sensors[i + 1], (SDL_num_sensors - i) * sizeof(SDL_sensors[i]));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
SDL_UnlockSensors();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool SDL_WINDOWS_SensorInit(void)
|
||||
{
|
||||
HRESULT hr;
|
||||
ISensorCollection *sensor_collection = NULL;
|
||||
|
||||
if (WIN_CoInitialize() == S_OK) {
|
||||
SDL_windowscoinit = true;
|
||||
}
|
||||
|
||||
hr = CoCreateInstance(&SDL_CLSID_SensorManager, NULL, CLSCTX_INPROC_SERVER, &SDL_IID_SensorManager, (LPVOID *)&SDL_sensor_manager);
|
||||
if (FAILED(hr)) {
|
||||
// If we can't create a sensor manager (i.e. on Wine), we won't have any sensors, but don't fail the init
|
||||
return true; // WIN_SetErrorFromHRESULT("Couldn't create the sensor manager", hr);
|
||||
}
|
||||
|
||||
hr = ISensorManager_SetEventSink(SDL_sensor_manager, &sensor_manager_events);
|
||||
if (FAILED(hr)) {
|
||||
ISensorManager_Release(SDL_sensor_manager);
|
||||
SDL_sensor_manager = NULL;
|
||||
return WIN_SetErrorFromHRESULT("Couldn't set the sensor manager event sink", hr);
|
||||
}
|
||||
|
||||
hr = ISensorManager_GetSensorsByCategory(SDL_sensor_manager, &SENSOR_CATEGORY_ALL, &sensor_collection);
|
||||
if (SUCCEEDED(hr)) {
|
||||
ULONG i, count;
|
||||
|
||||
hr = ISensorCollection_GetCount(sensor_collection, &count);
|
||||
if (SUCCEEDED(hr)) {
|
||||
for (i = 0; i < count; ++i) {
|
||||
ISensor *sensor;
|
||||
|
||||
hr = ISensorCollection_GetAt(sensor_collection, i, &sensor);
|
||||
if (SUCCEEDED(hr)) {
|
||||
SensorState state;
|
||||
|
||||
hr = ISensor_GetState(sensor, &state);
|
||||
if (SUCCEEDED(hr)) {
|
||||
ISensorManagerEventsVtbl_OnSensorEnter(&sensor_manager_events, sensor, state);
|
||||
}
|
||||
ISensorManager_Release(sensor);
|
||||
}
|
||||
}
|
||||
}
|
||||
ISensorCollection_Release(sensor_collection);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static int SDL_WINDOWS_SensorGetCount(void)
|
||||
{
|
||||
return SDL_num_sensors;
|
||||
}
|
||||
|
||||
static void SDL_WINDOWS_SensorDetect(void)
|
||||
{
|
||||
}
|
||||
|
||||
static const char *SDL_WINDOWS_SensorGetDeviceName(int device_index)
|
||||
{
|
||||
return SDL_sensors[device_index].name;
|
||||
}
|
||||
|
||||
static SDL_SensorType SDL_WINDOWS_SensorGetDeviceType(int device_index)
|
||||
{
|
||||
return SDL_sensors[device_index].type;
|
||||
}
|
||||
|
||||
static int SDL_WINDOWS_SensorGetDeviceNonPortableType(int device_index)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static SDL_SensorID SDL_WINDOWS_SensorGetDeviceInstanceID(int device_index)
|
||||
{
|
||||
return SDL_sensors[device_index].id;
|
||||
}
|
||||
|
||||
static bool SDL_WINDOWS_SensorOpen(SDL_Sensor *sensor, int device_index)
|
||||
{
|
||||
SDL_sensors[device_index].sensor_opened = sensor;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void SDL_WINDOWS_SensorUpdate(SDL_Sensor *sensor)
|
||||
{
|
||||
}
|
||||
|
||||
static void SDL_WINDOWS_SensorClose(SDL_Sensor *sensor)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < SDL_num_sensors; ++i) {
|
||||
if (sensor == SDL_sensors[i].sensor_opened) {
|
||||
SDL_sensors[i].sensor_opened = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void SDL_WINDOWS_SensorQuit(void)
|
||||
{
|
||||
while (SDL_num_sensors > 0) {
|
||||
DisconnectSensor(SDL_sensors[0].sensor);
|
||||
}
|
||||
|
||||
if (SDL_sensor_manager) {
|
||||
ISensorManager_SetEventSink(SDL_sensor_manager, NULL);
|
||||
ISensorManager_Release(SDL_sensor_manager);
|
||||
SDL_sensor_manager = NULL;
|
||||
}
|
||||
|
||||
if (SDL_windowscoinit) {
|
||||
WIN_CoUninitialize();
|
||||
}
|
||||
}
|
||||
|
||||
SDL_SensorDriver SDL_WINDOWS_SensorDriver = {
|
||||
SDL_WINDOWS_SensorInit,
|
||||
SDL_WINDOWS_SensorGetCount,
|
||||
SDL_WINDOWS_SensorDetect,
|
||||
SDL_WINDOWS_SensorGetDeviceName,
|
||||
SDL_WINDOWS_SensorGetDeviceType,
|
||||
SDL_WINDOWS_SensorGetDeviceNonPortableType,
|
||||
SDL_WINDOWS_SensorGetDeviceInstanceID,
|
||||
SDL_WINDOWS_SensorOpen,
|
||||
SDL_WINDOWS_SensorUpdate,
|
||||
SDL_WINDOWS_SensorClose,
|
||||
SDL_WINDOWS_SensorQuit,
|
||||
};
|
||||
|
||||
#endif // SDL_SENSOR_WINDOWS
|
||||
21
thirdparty/sdl/sensor/windows/SDL_windowssensor.h
vendored
Normal file
21
thirdparty/sdl/sensor/windows/SDL_windowssensor.h
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2025 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"
|
||||
2
thirdparty/sdl/update-sdl.sh
vendored
2
thirdparty/sdl/update-sdl.sh
vendored
@@ -61,7 +61,7 @@ mkdir $target/loadso
|
||||
cp -rv loadso/dlopen $target/loadso
|
||||
|
||||
mkdir $target/sensor
|
||||
cp -rv sensor/{*.{c,h},dummy} $target/sensor
|
||||
cp -rv sensor/{*.{c,h},dummy,windows} $target/sensor
|
||||
|
||||
mkdir $target/thread
|
||||
cp -rv thread/{*.{c,h},pthread,windows} $target/thread
|
||||
|
||||
Reference in New Issue
Block a user