Skip to content

Commit e11cc60

Browse files
committed
Add support for joypad LED lights
1 parent 36b9212 commit e11cc60

File tree

10 files changed

+613
-3
lines changed

10 files changed

+613
-3
lines changed

core/input/input.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,8 @@ void Input::_bind_methods() {
151151
ClassDB::bind_method(D_METHOD("set_accelerometer", "value"), &Input::set_accelerometer);
152152
ClassDB::bind_method(D_METHOD("set_magnetometer", "value"), &Input::set_magnetometer);
153153
ClassDB::bind_method(D_METHOD("set_gyroscope", "value"), &Input::set_gyroscope);
154+
ClassDB::bind_method(D_METHOD("set_joy_light", "device", "color"), &Input::set_joy_light);
155+
ClassDB::bind_method(D_METHOD("has_joy_light", "device"), &Input::has_joy_light);
154156
ClassDB::bind_method(D_METHOD("get_last_mouse_velocity"), &Input::get_last_mouse_velocity);
155157
ClassDB::bind_method(D_METHOD("get_last_mouse_screen_velocity"), &Input::get_last_mouse_screen_velocity);
156158
ClassDB::bind_method(D_METHOD("get_mouse_button_mask"), &Input::get_mouse_button_mask);
@@ -986,6 +988,28 @@ void Input::set_joy_axis(int p_device, JoyAxis p_axis, float p_value) {
986988
_joy_axis[c] = p_value;
987989
}
988990

991+
void Input::set_joy_features(int p_device, JoypadFeatures *p_features) {
992+
Joypad *joypad = joy_names.getptr(p_device);
993+
if (!joypad) {
994+
return;
995+
}
996+
joypad->features = p_features;
997+
_update_joypad_features(p_device);
998+
}
999+
1000+
bool Input::set_joy_light(int p_device, const Color &p_color) {
1001+
Joypad *joypad = joy_names.getptr(p_device);
1002+
if (!joypad || joypad->features == nullptr) {
1003+
return false;
1004+
}
1005+
return joypad->features->set_joy_light(p_color);
1006+
}
1007+
1008+
bool Input::has_joy_light(int p_device) const {
1009+
const Joypad *joypad = joy_names.getptr(p_device);
1010+
return joypad && joypad->has_light;
1011+
}
1012+
9891013
void Input::start_joy_vibration(int p_device, float p_weak_magnitude, float p_strong_magnitude, float p_duration) {
9901014
_THREAD_SAFE_METHOD_
9911015
if (p_weak_magnitude < 0.f || p_weak_magnitude > 1.f || p_strong_magnitude < 0.f || p_strong_magnitude > 1.f) {
@@ -1478,6 +1502,16 @@ void Input::_update_action_cache(const StringName &p_action_name, ActionState &r
14781502
}
14791503
}
14801504

1505+
void Input::_update_joypad_features(int p_device) {
1506+
Joypad *joypad = joy_names.getptr(p_device);
1507+
if (!joypad || joypad->features == nullptr) {
1508+
return;
1509+
}
1510+
if (joypad->features->has_joy_light()) {
1511+
joypad->has_light = true;
1512+
}
1513+
}
1514+
14811515
Input::JoyEvent Input::_get_mapped_button_event(const JoyDeviceMapping &mapping, JoyButton p_button) {
14821516
JoyEvent event;
14831517

core/input/input.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,14 @@ class Input : public Object {
7979
CURSOR_MAX
8080
};
8181

82+
class JoypadFeatures {
83+
public:
84+
virtual ~JoypadFeatures() {}
85+
86+
virtual bool has_joy_light() const { return false; }
87+
virtual bool set_joy_light(const Color &p_color) { return false; }
88+
};
89+
8290
static constexpr int32_t JOYPADS_MAX = 16;
8391

8492
typedef void (*EventDispatchFunc)(const Ref<InputEvent> &p_event);
@@ -174,6 +182,8 @@ class Input : public Object {
174182
int mapping = -1;
175183
int hat_current = 0;
176184
Dictionary info;
185+
bool has_light = false;
186+
Input::JoypadFeatures *features = nullptr;
177187
};
178188

179189
VelocityTrack mouse_velocity_track;
@@ -253,6 +263,7 @@ class Input : public Object {
253263
void _button_event(int p_device, JoyButton p_index, bool p_pressed);
254264
void _axis_event(int p_device, JoyAxis p_axis, float p_value);
255265
void _update_action_cache(const StringName &p_action_name, ActionState &r_action_state);
266+
void _update_joypad_features(int p_device);
256267

257268
void _parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_emulated);
258269

@@ -346,6 +357,11 @@ class Input : public Object {
346357
void set_gyroscope(const Vector3 &p_gyroscope);
347358
void set_joy_axis(int p_device, JoyAxis p_axis, float p_value);
348359

360+
void set_joy_features(int p_device, JoypadFeatures *p_features);
361+
362+
bool set_joy_light(int p_device, const Color &p_color);
363+
bool has_joy_light(int p_device) const;
364+
349365
void start_joy_vibration(int p_device, float p_weak_magnitude, float p_strong_magnitude, float p_duration = 0);
350366
void stop_joy_vibration(int p_device);
351367
void vibrate_handheld(int p_duration_ms = 500, float p_amplitude = -1.0);

doc/classes/Input.xml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,14 @@
200200
By default, the deadzone is automatically calculated from the average of the action deadzones. However, you can override the deadzone to be whatever you want (on the range of 0 to 1).
201201
</description>
202202
</method>
203+
<method name="has_joy_light" qualifiers="const">
204+
<return type="bool" />
205+
<param index="0" name="device" type="int" />
206+
<description>
207+
Returns [code]true[/code] if the joypad has an LED light that can change colors and/or brightness. See also [method set_joy_light].
208+
[b]Note:[/b] This feature is only supported on Windows, Linux, and macOS.
209+
</description>
210+
</method>
203211
<method name="is_action_just_pressed" qualifiers="const">
204212
<return type="bool" />
205213
<param index="0" name="action" type="StringName" />
@@ -389,6 +397,16 @@
389397
[b]Note:[/b] This value can be immediately overwritten by the hardware sensor value on Android and iOS.
390398
</description>
391399
</method>
400+
<method name="set_joy_light">
401+
<return type="bool" />
402+
<param index="0" name="device" type="int" />
403+
<param index="1" name="color" type="Color" />
404+
<description>
405+
Sets the joypad's LED light, if available, to the specified color. Returns [code]true[/code] if the operation was successful. See also [method has_joy_light].
406+
[b]Note:[/b] There is no way to get the color of the light from a joypad. If you need to know the assigned color, store it separately.
407+
[b]Note:[/b] This feature is only supported on Windows, Linux, and macOS.
408+
</description>
409+
</method>
392410
<method name="set_magnetometer">
393411
<return type="void" />
394412
<param index="0" name="value" type="Vector3" />

drivers/sdl/SCsub

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@ if env["builtin_sdl"]:
178178
"joystick/windows/SDL_xinputjoystick.c",
179179
"thread/generic/SDL_syscond.c",
180180
"thread/generic/SDL_sysrwlock.c",
181+
"sensor/windows/SDL_windowssensor.c",
181182
"thread/windows/SDL_syscond_cv.c",
182183
"thread/windows/SDL_sysmutex.c",
183184
"thread/windows/SDL_sysrwlock_srw.c",

drivers/sdl/SDL_build_config_private.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@
4747
#define SDL_DIALOG_DISABLED 1
4848
#define SDL_FILESYSTEM_DUMMY 1
4949
#define SDL_FSOPS_DUMMY 1
50-
#define SDL_SENSOR_DISABLED 1
5150
#define SDL_GPU_DISABLED 1
5251
#define SDL_RENDER_DISABLED 1
5352
#define SDL_POWER_DISABLED 1
@@ -73,6 +72,7 @@
7372
#define SDL_THREAD_GENERIC_RWLOCK_SUFFIX 1
7473
#define SDL_THREAD_WINDOWS 1
7574
#define SDL_TIMER_WINDOWS 1
75+
#define SDL_SENSOR_WINDOWS 1
7676

7777
// Linux defines
7878
#elif defined(SDL_PLATFORM_LINUX)
@@ -113,6 +113,7 @@
113113
#define SDL_HAPTIC_LINUX 1
114114
#define SDL_TIMER_UNIX 1
115115
#define SDL_JOYSTICK_LINUX 1
116+
#define SDL_JOYSTICK_HIDAPI 1
116117
#define SDL_INPUT_LINUXEV 1
117118
#define SDL_THREAD_PTHREAD 1
118119

@@ -126,8 +127,10 @@
126127
#define SDL_HAPTIC_IOKIT 1
127128
#define SDL_JOYSTICK_IOKIT 1
128129
#define SDL_JOYSTICK_MFI 1
130+
#define SDL_JOYSTICK_HIDAPI 1
129131
#define SDL_TIMER_UNIX 1
130132
#define SDL_THREAD_PTHREAD 1
133+
#define SDL_THREAD_PTHREAD_RECURSIVE_MUTEX 1
131134

132135
// Other platforms are not supported (for now)
133136
#else

drivers/sdl/joypad_sdl.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,8 @@ void JoypadSDL::process_events() {
208208
device_name,
209209
joypads[joy_id].guid,
210210
joypad_info);
211+
212+
Input::get_singleton()->set_joy_features(joy_id, &joypads[joy_id]);
211213
}
212214
// An event for an attached joypad
213215
} 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,25 @@ void JoypadSDL::close_joypad(int p_pad_idx) {
299301
}
300302
}
301303

304+
bool JoypadSDL::Joypad::has_joy_light() const {
305+
SDL_PropertiesID properties_id = SDL_GetJoystickProperties(get_sdl_joystick());
306+
if (properties_id == 0) {
307+
return false;
308+
}
309+
return SDL_GetBooleanProperty(properties_id, SDL_PROP_JOYSTICK_CAP_RGB_LED_BOOLEAN, false) || SDL_GetBooleanProperty(properties_id, SDL_PROP_JOYSTICK_CAP_MONO_LED_BOOLEAN, false);
310+
}
311+
312+
bool JoypadSDL::Joypad::set_joy_light(const Color &p_color) {
313+
Color linear = p_color.srgb_to_linear();
314+
return SDL_SetJoystickLED(get_sdl_joystick(), linear.get_r8(), linear.get_g8(), linear.get_b8());
315+
}
316+
317+
SDL_Joystick *JoypadSDL::Joypad::get_sdl_joystick() const {
318+
return SDL_GetJoystickFromID(sdl_instance_idx);
319+
}
320+
321+
SDL_Gamepad *JoypadSDL::Joypad::get_sdl_gamepad() const {
322+
return SDL_GetGamepadFromID(sdl_instance_idx);
323+
}
324+
302325
#endif // SDL_ENABLED

drivers/sdl/joypad_sdl.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@
3535

3636
typedef uint32_t SDL_JoystickID;
3737
typedef struct HWND__ *HWND;
38+
typedef struct SDL_Joystick SDL_Joystick;
39+
typedef struct SDL_Gamepad SDL_Gamepad;
3840

3941
class JoypadSDL {
4042
public:
@@ -50,14 +52,21 @@ class JoypadSDL {
5052
void process_events();
5153

5254
private:
53-
struct Joypad {
55+
class Joypad : public Input::JoypadFeatures {
56+
public:
5457
bool attached = false;
5558
StringName guid;
5659

5760
SDL_JoystickID sdl_instance_idx;
5861

5962
bool supports_force_feedback = false;
6063
uint64_t ff_effect_timestamp = 0;
64+
65+
virtual bool has_joy_light() const override;
66+
virtual bool set_joy_light(const Color &p_color) override;
67+
68+
SDL_Joystick *get_sdl_joystick() const;
69+
SDL_Gamepad *get_sdl_gamepad() const;
6170
};
6271

6372
static JoypadSDL *singleton;

0 commit comments

Comments
 (0)