diff --git a/core/input/input.cpp b/core/input/input.cpp index 07ed78bf283..934449bd681 100644 --- a/core/input/input.cpp +++ b/core/input/input.cpp @@ -151,6 +151,8 @@ void Input::_bind_methods() { ClassDB::bind_method(D_METHOD("set_accelerometer", "value"), &Input::set_accelerometer); ClassDB::bind_method(D_METHOD("set_magnetometer", "value"), &Input::set_magnetometer); ClassDB::bind_method(D_METHOD("set_gyroscope", "value"), &Input::set_gyroscope); + ClassDB::bind_method(D_METHOD("set_joy_light", "device", "color"), &Input::set_joy_light); + ClassDB::bind_method(D_METHOD("has_joy_light", "device"), &Input::has_joy_light); ClassDB::bind_method(D_METHOD("get_last_mouse_velocity"), &Input::get_last_mouse_velocity); ClassDB::bind_method(D_METHOD("get_last_mouse_screen_velocity"), &Input::get_last_mouse_screen_velocity); ClassDB::bind_method(D_METHOD("get_mouse_button_mask"), &Input::get_mouse_button_mask); @@ -995,6 +997,19 @@ void Input::set_joy_features(int p_device, JoypadFeatures *p_features) { _update_joypad_features(p_device); } +bool Input::set_joy_light(int p_device, const Color &p_color) { + Joypad *joypad = joy_names.getptr(p_device); + if (!joypad || joypad->features == nullptr) { + return false; + } + return joypad->features->set_joy_light(p_color); +} + +bool Input::has_joy_light(int p_device) const { + const Joypad *joypad = joy_names.getptr(p_device); + return joypad && joypad->has_light; +} + 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) { @@ -1492,8 +1507,9 @@ void Input::_update_joypad_features(int 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. + if (joypad->features->has_joy_light()) { + joypad->has_light = true; + } } Input::JoyEvent Input::_get_mapped_button_event(const JoyDeviceMapping &mapping, JoyButton p_button) { diff --git a/core/input/input.h b/core/input/input.h index 88c845420bc..87aae277a37 100644 --- a/core/input/input.h +++ b/core/input/input.h @@ -83,9 +83,8 @@ public: 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; } + virtual bool has_joy_light() const { return false; } + virtual bool set_joy_light(const Color &p_color) { return false; } }; static constexpr int32_t JOYPADS_MAX = 16; @@ -183,6 +182,7 @@ private: int mapping = -1; int hat_current = 0; Dictionary info; + bool has_light = false; Input::JoypadFeatures *features = nullptr; }; @@ -359,6 +359,9 @@ public: void set_joy_features(int p_device, JoypadFeatures *p_features); + bool set_joy_light(int p_device, const Color &p_color); + bool has_joy_light(int p_device) const; + 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); diff --git a/doc/classes/Input.xml b/doc/classes/Input.xml index a8523b3ec7d..805576f1701 100644 --- a/doc/classes/Input.xml +++ b/doc/classes/Input.xml @@ -200,6 +200,14 @@ 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). + + + + + Returns [code]true[/code] if the joypad has an LED light that can change colors and/or brightness. See also [method set_joy_light]. + [b]Note:[/b] This feature is only supported on Windows, Linux, and macOS. + + @@ -389,6 +397,16 @@ [b]Note:[/b] This value can be immediately overwritten by the hardware sensor value on Android and iOS. + + + + + + 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]. + [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. + [b]Note:[/b] This feature is only supported on Windows, Linux, and macOS. + + diff --git a/drivers/sdl/joypad_sdl.cpp b/drivers/sdl/joypad_sdl.cpp index fea0843031a..e51e22e5bf1 100644 --- a/drivers/sdl/joypad_sdl.cpp +++ b/drivers/sdl/joypad_sdl.cpp @@ -301,6 +301,19 @@ void JoypadSDL::close_joypad(int p_pad_idx) { } } +bool JoypadSDL::Joypad::has_joy_light() const { + SDL_PropertiesID properties_id = SDL_GetJoystickProperties(get_sdl_joystick()); + if (properties_id == 0) { + return false; + } + 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); +} + +bool JoypadSDL::Joypad::set_joy_light(const Color &p_color) { + Color linear = p_color.srgb_to_linear(); + return SDL_SetJoystickLED(get_sdl_joystick(), linear.get_r8(), linear.get_g8(), linear.get_b8()); +} + SDL_Joystick *JoypadSDL::Joypad::get_sdl_joystick() const { return SDL_GetJoystickFromID(sdl_instance_idx); } diff --git a/drivers/sdl/joypad_sdl.h b/drivers/sdl/joypad_sdl.h index b95ee813ef2..a399e11caf5 100644 --- a/drivers/sdl/joypad_sdl.h +++ b/drivers/sdl/joypad_sdl.h @@ -62,6 +62,9 @@ private: bool supports_force_feedback = false; uint64_t ff_effect_timestamp = 0; + virtual bool has_joy_light() const override; + virtual bool set_joy_light(const Color &p_color) override; + SDL_Joystick *get_sdl_joystick() const; SDL_Gamepad *get_sdl_gamepad() const; };