Add support for joypad vibration checking
This commit is contained in:
parent
8db94f7b5e
commit
c83c672d61
5 changed files with 93 additions and 8 deletions
|
|
@ -146,6 +146,9 @@ void Input::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("get_connected_joypads"), &Input::get_connected_joypads);
|
||||
ClassDB::bind_method(D_METHOD("get_joy_vibration_strength", "device"), &Input::get_joy_vibration_strength);
|
||||
ClassDB::bind_method(D_METHOD("get_joy_vibration_duration", "device"), &Input::get_joy_vibration_duration);
|
||||
ClassDB::bind_method(D_METHOD("get_joy_vibration_remaining_duration", "device"), &Input::get_joy_vibration_remaining_duration);
|
||||
ClassDB::bind_method(D_METHOD("is_joy_vibrating", "device"), &Input::is_joy_vibrating);
|
||||
ClassDB::bind_method(D_METHOD("has_joy_vibration", "device"), &Input::has_joy_vibration);
|
||||
ClassDB::bind_method(D_METHOD("start_joy_vibration", "device", "weak_magnitude", "strong_magnitude", "duration"), &Input::start_joy_vibration, DEFVAL(0));
|
||||
ClassDB::bind_method(D_METHOD("stop_joy_vibration", "device"), &Input::stop_joy_vibration);
|
||||
ClassDB::bind_method(D_METHOD("vibrate_handheld", "duration_ms", "amplitude"), &Input::vibrate_handheld, DEFVAL(500), DEFVAL(-1.0));
|
||||
|
|
@ -625,6 +628,33 @@ float Input::get_joy_vibration_duration(int p_device) {
|
|||
}
|
||||
}
|
||||
|
||||
float Input::get_joy_vibration_remaining_duration(int p_device) {
|
||||
_THREAD_SAFE_METHOD_
|
||||
const Joypad *joypad = joy_names.getptr(p_device);
|
||||
if (joypad == nullptr || !joypad->has_vibration) {
|
||||
return 0.f;
|
||||
}
|
||||
const VibrationInfo *vibration = joy_vibration.getptr(p_device);
|
||||
if (vibration == nullptr || (vibration->weak_magnitude == 0.f && vibration->strong_magnitude == 0.f) || vibration->duration < 0.f) {
|
||||
return 0.f;
|
||||
}
|
||||
float vibration_duration = vibration->duration;
|
||||
if (vibration_duration > 0xFFFF / 1000.f || vibration_duration == 0.f) {
|
||||
vibration_duration = 0xFFFF / 1000.f; // SDL_MAX_RUMBLE_DURATION_MS / 1000.f
|
||||
}
|
||||
return MAX(vibration_duration - (OS::get_singleton()->get_ticks_usec() - vibration->timestamp) / 1e6, 0.f);
|
||||
}
|
||||
|
||||
bool Input::is_joy_vibrating(int p_device) {
|
||||
return get_joy_vibration_remaining_duration(p_device) > 0.0f;
|
||||
}
|
||||
|
||||
bool Input::has_joy_vibration(int p_device) const {
|
||||
_THREAD_SAFE_METHOD_
|
||||
const Joypad *joypad = joy_names.getptr(p_device);
|
||||
return joypad != nullptr && joypad->has_vibration;
|
||||
}
|
||||
|
||||
static String _hex_str(uint8_t p_byte) {
|
||||
static const char *dict = "0123456789abcdef";
|
||||
char ret[3];
|
||||
|
|
@ -1738,6 +1768,9 @@ void Input::_update_joypad_features(int p_device) {
|
|||
if (!joypad || joypad->features == nullptr) {
|
||||
return;
|
||||
}
|
||||
if (joypad->features->has_joy_vibration()) {
|
||||
joypad->has_vibration = true;
|
||||
}
|
||||
if (joypad->features->has_joy_light()) {
|
||||
joypad->has_light = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -91,6 +91,8 @@ public:
|
|||
public:
|
||||
virtual ~JoypadFeatures() {}
|
||||
|
||||
virtual bool has_joy_vibration() const { return false; }
|
||||
|
||||
virtual bool has_joy_light() const { return false; }
|
||||
virtual void set_joy_light(const Color &p_color) {}
|
||||
|
||||
|
|
@ -212,6 +214,7 @@ private:
|
|||
int hat_current = 0;
|
||||
Dictionary info;
|
||||
bool has_light = false;
|
||||
bool has_vibration = false;
|
||||
Input::JoypadFeatures *features = nullptr;
|
||||
};
|
||||
|
||||
|
|
@ -362,7 +365,10 @@ public:
|
|||
TypedArray<int> get_connected_joypads();
|
||||
Vector2 get_joy_vibration_strength(int p_device);
|
||||
float get_joy_vibration_duration(int p_device);
|
||||
float get_joy_vibration_remaining_duration(int p_device);
|
||||
uint64_t get_joy_vibration_timestamp(int p_device);
|
||||
bool is_joy_vibrating(int p_device);
|
||||
bool has_joy_vibration(int p_device) const;
|
||||
void joy_connection_changed(int p_idx, bool p_connected, const String &p_name, const String &p_guid = "", const Dictionary &p_joypad_info = Dictionary());
|
||||
|
||||
Vector3 get_gravity() const;
|
||||
|
|
|
|||
|
|
@ -221,6 +221,15 @@
|
|||
<param index="0" name="device" type="int" />
|
||||
<description>
|
||||
Returns the duration of the current vibration effect in seconds.
|
||||
[b]Note:[/b] This method returns the same value that was passed to [method start_joy_vibration], and this value does [b]not[/b] change when the joypad's vibration runs out, it only gets reset after a call to [method stop_joy_vibration].
|
||||
If you want to check if a joypad is still vibrating, use [method is_joy_vibrating] instead.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_joy_vibration_remaining_duration" experimental="">
|
||||
<return type="float" />
|
||||
<param index="0" name="device" type="int" />
|
||||
<description>
|
||||
Returns the remaining duration of the current vibration effect in seconds.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_joy_vibration_strength">
|
||||
|
|
@ -228,6 +237,8 @@
|
|||
<param index="0" name="device" type="int" />
|
||||
<description>
|
||||
Returns the strength of the joypad vibration: x is the strength of the weak motor, and y is the strength of the strong motor.
|
||||
[b]Note:[/b] This method returns the same values that were passed to [method start_joy_vibration], and these values do [b]not[/b] change when the joypad's vibration runs out, they only get reset after a call to [method stop_joy_vibration].
|
||||
If you want to check if a joypad is still vibrating, use [method is_joy_vibrating] instead.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_last_mouse_screen_velocity">
|
||||
|
|
@ -285,6 +296,14 @@
|
|||
[b]Note:[/b] This feature is only supported on Windows, Linux, and macOS.
|
||||
</description>
|
||||
</method>
|
||||
<method name="has_joy_vibration" qualifiers="const">
|
||||
<return type="bool" />
|
||||
<param index="0" name="device" type="int" />
|
||||
<description>
|
||||
Returns [code]true[/code] if the joypad supports vibration. See also [method start_joy_vibration].
|
||||
[b]Note:[/b] For macOS, vibration is only supported in macOS 11 and later. When connected via USB, vibration is only supported for major brand controllers (except Xbox One and Xbox Series X/S controllers) due to macOS limitations.
|
||||
</description>
|
||||
</method>
|
||||
<method name="is_action_just_pressed" qualifiers="const">
|
||||
<return type="bool" />
|
||||
<param index="0" name="action" type="StringName" />
|
||||
|
|
@ -392,6 +411,14 @@
|
|||
[b]Note:[/b] This feature is only supported on Windows, Linux, and macOS.
|
||||
</description>
|
||||
</method>
|
||||
<method name="is_joy_vibrating" experimental="">
|
||||
<return type="bool" />
|
||||
<param index="0" name="device" type="int" />
|
||||
<description>
|
||||
Returns [code]true[/code] if the joypad is still vibrating after a call to [method start_joy_vibration].
|
||||
Unlike [method get_joy_vibration_strength] and [method get_joy_vibration_duration], this method returns [code]false[/code] after the joypad's vibration runs out.
|
||||
</description>
|
||||
</method>
|
||||
<method name="is_key_label_pressed" qualifiers="const">
|
||||
<return type="bool" />
|
||||
<param index="0" name="keycode" type="int" enum="Key" />
|
||||
|
|
@ -664,8 +691,13 @@
|
|||
<param index="2" name="strong_magnitude" type="float" />
|
||||
<param index="3" name="duration" type="float" default="0" />
|
||||
<description>
|
||||
Starts to vibrate the joypad. Joypads usually come with two rumble motors, a strong and a weak one. [param weak_magnitude] is the strength of the weak motor (between 0 and 1) and [param strong_magnitude] is the strength of the strong motor (between 0 and 1). [param duration] is the duration of the effect in seconds (a duration of 0 will try to play the vibration indefinitely). The vibration can be stopped early by calling [method stop_joy_vibration].
|
||||
[b]Note:[/b] Not every hardware is compatible with long effect durations; it is recommended to restart an effect if it has to be played for more than a few seconds.
|
||||
Starts to vibrate the joypad. See also [method has_joy_vibration] and [method is_joy_vibrating].
|
||||
Joypads usually come with two rumble motors, a strong and a weak one.
|
||||
[param weak_magnitude] is the strength of the weak motor (between [code]0.0[/code] and [code]1.0[/code]).
|
||||
[param strong_magnitude] is the strength of the strong motor (between [code]0.0[/code] and [code]1.0[/code]).
|
||||
[param duration] is the duration of the effect in seconds (a duration of [code]0.0[/code] will try to play the vibration as long as possible, which is about 65 seconds).
|
||||
The vibration can be stopped early by calling [method stop_joy_vibration].
|
||||
See also [method get_joy_vibration_strength] and [method get_joy_vibration_duration].
|
||||
[b]Note:[/b] For macOS, vibration is only supported in macOS 11 and later. When connected via USB, vibration is only supported for major brand controllers (except Xbox One and Xbox Series X/S controllers) due to macOS limitations.
|
||||
</description>
|
||||
</method>
|
||||
|
|
|
|||
|
|
@ -95,6 +95,17 @@ void JoypadSDL::process_events() {
|
|||
|
||||
SDL_Joystick *sdl_joy = SDL_GetJoystickFromID(joypads[i].sdl_instance_idx);
|
||||
Vector2 strength = Input::get_singleton()->get_joy_vibration_strength(i);
|
||||
// Invalid values for strength are filtered by Input::start_joy_vibration().
|
||||
|
||||
float duration = Input::get_singleton()->get_joy_vibration_duration(i);
|
||||
Uint32 duration_ms = 0;
|
||||
if (duration < 0.0f) {
|
||||
continue; // Invalid duration.
|
||||
} else if (duration == 0.0f) {
|
||||
duration_ms = 0xFFFF; // SDL_MAX_RUMBLE_DURATION_MS
|
||||
} else {
|
||||
duration_ms = duration * 1000;
|
||||
}
|
||||
|
||||
/*
|
||||
If the vibration was requested to start, SDL_RumbleJoystick will start it.
|
||||
|
|
@ -103,13 +114,10 @@ void JoypadSDL::process_events() {
|
|||
Here strength.y goes first and then strength.x, because Input.get_joy_vibration_strength().x
|
||||
is vibration's weak magnitude (high frequency rumble), and .y is strong magnitude (low frequency rumble),
|
||||
SDL_RumbleJoystick takes low frequency rumble first and then high frequency rumble.
|
||||
|
||||
Rumble strength goes from 0 to 0xFFFF.
|
||||
*/
|
||||
SDL_RumbleJoystick(
|
||||
sdl_joy,
|
||||
// Rumble strength goes from 0 to 0xFFFF
|
||||
strength.y * UINT16_MAX,
|
||||
strength.x * UINT16_MAX,
|
||||
Input::get_singleton()->get_joy_vibration_duration(i) * 1000);
|
||||
SDL_RumbleJoystick(sdl_joy, strength.y * UINT16_MAX, strength.x * UINT16_MAX, duration_ms);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -333,6 +341,10 @@ void JoypadSDL::Joypad::set_joy_motion_sensors_enabled(bool p_enable) {
|
|||
SDL_SetGamepadSensorEnabled(gamepad, SDL_SENSOR_GYRO, p_enable);
|
||||
}
|
||||
|
||||
bool JoypadSDL::Joypad::has_joy_vibration() const {
|
||||
return supports_force_feedback;
|
||||
}
|
||||
|
||||
SDL_Joystick *JoypadSDL::Joypad::get_sdl_joystick() const {
|
||||
return SDL_GetJoystickFromID(sdl_instance_idx);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,6 +62,8 @@ private:
|
|||
virtual bool has_joy_motion_sensors() const override;
|
||||
virtual void set_joy_motion_sensors_enabled(bool p_enable) override;
|
||||
|
||||
virtual bool has_joy_vibration() const override;
|
||||
|
||||
SDL_Joystick *get_sdl_joystick() const;
|
||||
SDL_Gamepad *get_sdl_gamepad() const;
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue