Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions core/core_constants.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -570,6 +570,16 @@ void register_global_constants() {
BIND_CORE_ENUM_CLASS_CONSTANT(JoyAxis, JOY_AXIS, SDL_MAX);
BIND_CORE_ENUM_CLASS_CONSTANT(JoyAxis, JOY_AXIS, MAX);

BIND_CORE_ENUM_CLASS_CONSTANT(JoyPowerState, JOY_POWER, UNKNOWN);
BIND_CORE_ENUM_CLASS_CONSTANT(JoyPowerState, JOY_POWER, ON_BATTERY);
BIND_CORE_ENUM_CLASS_CONSTANT(JoyPowerState, JOY_POWER, NO_BATTERY);
BIND_CORE_ENUM_CLASS_CONSTANT(JoyPowerState, JOY_POWER, CHARGING);
BIND_CORE_ENUM_CLASS_CONSTANT(JoyPowerState, JOY_POWER, FULL_BATTERY);

BIND_CORE_ENUM_CLASS_CONSTANT(JoyConnectionState, JOY_CONNECTION, UNKNOWN);
BIND_CORE_ENUM_CLASS_CONSTANT(JoyConnectionState, JOY_CONNECTION, WIRED);
BIND_CORE_ENUM_CLASS_CONSTANT(JoyConnectionState, JOY_CONNECTION, WIRELESS);

BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, NONE);
BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, NOTE_OFF);
BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, NOTE_ON);
Expand Down
57 changes: 57 additions & 0 deletions core/input/input.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,9 @@ 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("get_joy_power_state", "device"), &Input::get_joy_power_state);
ClassDB::bind_method(D_METHOD("get_joy_battery_percent", "device"), &Input::get_joy_battery_percent);
ClassDB::bind_method(D_METHOD("get_joy_connection_state", "device"), &Input::get_joy_connection_state);
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);
Expand Down Expand Up @@ -798,6 +801,33 @@ Vector3 Input::get_gyroscope() const {
return gyroscope;
}

JoyPowerState Input::get_joy_power_state(int p_device) const {
_THREAD_SAFE_METHOD_
const Joypad *joypad = joy_names.getptr(p_device);
if (joypad == nullptr) {
return JoyPowerState::UNKNOWN;
}
return joypad->power_state;
}

int Input::get_joy_battery_percent(int p_device) const {
_THREAD_SAFE_METHOD_
const Joypad *joypad = joy_names.getptr(p_device);
if (joypad == nullptr) {
return -1;
}
return joypad->battery_percent;
}

JoyConnectionState Input::get_joy_connection_state(int p_device) const {
_THREAD_SAFE_METHOD_
const Joypad *joypad = joy_names.getptr(p_device);
if (joypad == nullptr) {
return JoyConnectionState::UNKNOWN;
}
return joypad->connection_state;
}

void Input::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_emulated) {
// This function does the final delivery of the input event to user land.
// Regardless where the event came from originally, this has to happen on the main thread.
Expand Down Expand Up @@ -1356,6 +1386,33 @@ void Input::set_gyroscope(const Vector3 &p_gyroscope) {
gyroscope = p_gyroscope;
}

void Input::set_joy_power_state(int p_device, JoyPowerState p_state) {
_THREAD_SAFE_METHOD_
Joypad *joypad = joy_names.getptr(p_device);
if (joypad == nullptr) {
return;
}
joypad->power_state = p_state;
}

void Input::set_joy_battery_percent(int p_device, int p_percent) {
_THREAD_SAFE_METHOD_
Joypad *joypad = joy_names.getptr(p_device);
if (joypad == nullptr || p_percent < -1 || p_percent > 100) {
return;
}
joypad->battery_percent = p_percent;
}

void Input::set_joy_connection_state(int p_device, JoyConnectionState p_state) {
_THREAD_SAFE_METHOD_
Joypad *joypad = joy_names.getptr(p_device);
if (joypad == nullptr) {
return;
}
joypad->connection_state = p_state;
}

void Input::set_mouse_position(const Point2 &p_posf) {
mouse_pos = p_posf;
}
Expand Down
12 changes: 12 additions & 0 deletions core/input/input.h
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,9 @@ class Input : public Object {
HatMask last_hat = HatMask::CENTER;
int mapping = -1;
int hat_current = 0;
int8_t battery_percent = -1;
JoyPowerState power_state = JoyPowerState::UNKNOWN;
JoyConnectionState connection_state = JoyConnectionState::UNKNOWN;
Dictionary info;
bool has_light = false;
bool has_vibration = false;
Expand Down Expand Up @@ -385,6 +388,10 @@ class Input : public Object {
Vector3 get_magnetometer() const;
Vector3 get_gyroscope() const;

JoyPowerState get_joy_power_state(int p_device) const;
int get_joy_battery_percent(int p_device) const;
JoyConnectionState get_joy_connection_state(int p_device) const;

Point2 get_mouse_position() const;
Vector2 get_last_mouse_velocity();
Vector2 get_last_mouse_screen_velocity();
Expand All @@ -399,6 +406,11 @@ class Input : public Object {
void set_accelerometer(const Vector3 &p_accel);
void set_magnetometer(const Vector3 &p_magnetometer);
void set_gyroscope(const Vector3 &p_gyroscope);

void set_joy_power_state(int p_device, JoyPowerState p_state);
void set_joy_battery_percent(int p_device, int p_percent);
void set_joy_connection_state(int p_device, JoyConnectionState p_state);

void set_joy_axis(int p_device, JoyAxis p_axis, float p_value);

void set_joy_features(int p_device, JoypadFeatures *p_features);
Expand Down
16 changes: 16 additions & 0 deletions core/input/input_enums.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,22 @@ enum class JoyButton {
MAX = 128, // Android supports up to 36 buttons. DirectInput supports up to 128 buttons.
};

// See SDL_PowerState. SDL_POWERSTATE_ERROR equivalent was omitted for simplicity.
enum class JoyPowerState {
UNKNOWN = 0,
ON_BATTERY = 1,
NO_BATTERY = 2,
CHARGING = 3,
FULL_BATTERY = 4,
};

// See SDL_JoystickConnectionState. SDL_JOYSTICK_CONNECTION_INVALID equivalent was omitted for simplicity.
enum class JoyConnectionState {
UNKNOWN = 0,
WIRED = 1,
WIRELESS = 2,
};

enum class MIDIMessage {
NONE = 0,
NOTE_OFF = 0x8,
Expand Down
4 changes: 4 additions & 0 deletions core/variant/variant_caster.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ enum class HatDir;
enum class HatMask;
enum class JoyAxis;
enum class JoyButton;
enum class JoyPowerState;
enum class JoyConnectionState;

enum class MIDIMessage;
enum class MouseButton;
Expand Down Expand Up @@ -105,6 +107,8 @@ VARIANT_ENUM_CAST(HatDir);
VARIANT_BITFIELD_CAST(HatMask);
VARIANT_ENUM_CAST(JoyAxis);
VARIANT_ENUM_CAST(JoyButton);
VARIANT_ENUM_CAST(JoyPowerState);
VARIANT_ENUM_CAST(JoyConnectionState);

VARIANT_ENUM_CAST(MIDIMessage);
VARIANT_ENUM_CAST(MouseButton);
Expand Down
24 changes: 24 additions & 0 deletions doc/classes/@GlobalScope.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2572,6 +2572,30 @@
<constant name="JOY_AXIS_MAX" value="10" enum="JoyAxis">
The maximum number of game controller axes: OpenVR supports up to 5 Joysticks making a total of 10 axes.
</constant>
<constant name="JOY_POWER_UNKNOWN" value="0" enum="JoyPowerState">
An invalid or unknown joypad power state.
</constant>
<constant name="JOY_POWER_ON_BATTERY" value="1" enum="JoyPowerState">
The joypad is not plugged in and is running on the battery.
</constant>
<constant name="JOY_POWER_NO_BATTERY" value="2" enum="JoyPowerState">
The joypad is plugged in and has no battery available.
</constant>
<constant name="JOY_POWER_CHARGING" value="3" enum="JoyPowerState">
The joypad is plugged in and its battery is currently charging.
</constant>
<constant name="JOY_POWER_FULL_BATTERY" value="4" enum="JoyPowerState">
The joypad is plugged in and its battery is fully charged.
</constant>
<constant name="JOY_CONNECTION_UNKNOWN" value="0" enum="JoyConnectionState">
An invalid or unknown joypad connection state.
</constant>
<constant name="JOY_CONNECTION_WIRED" value="1" enum="JoyConnectionState">
The joypad is currently using a wired connection to the device.
</constant>
<constant name="JOY_CONNECTION_WIRELESS" value="2" enum="JoyConnectionState">
The joypad is currently using a wireless connection to the device.
</constant>
<constant name="MIDI_MESSAGE_NONE" value="0" enum="MIDIMessage">
Does not correspond to any MIDI message. This is the default value of [member InputEventMIDI.message].
</constant>
Expand Down
24 changes: 24 additions & 0 deletions doc/classes/Input.xml
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,22 @@
Returns the current value of the joypad axis at index [param axis].
</description>
</method>
<method name="get_joy_battery_percent" qualifiers="const" experimental="">
<return type="int" />
<param index="0" name="device" type="int" />
<description>
Returns the battery percentage of the requested joypad, if available.
[b]Note:[/b] This feature is only supported on Windows, Linux, and macOS.
</description>
</method>
<method name="get_joy_connection_state" qualifiers="const" experimental="">
<return type="int" enum="JoyConnectionState" />
<param index="0" name="device" type="int" />
<description>
Returns the joypad's connection state (i.e. if it's wired or wireless).
[b]Note:[/b] This feature is only supported on Windows, Linux, and macOS.
</description>
</method>
<method name="get_joy_gravity" qualifiers="const" experimental="">
<return type="Vector3" />
<param index="0" name="device" type="int" />
Expand Down Expand Up @@ -217,6 +233,14 @@
Returns the name of the joypad at the specified device index, e.g. [code]PS4 Controller[/code]. Godot uses the [url=https://github.com/gabomdq/SDL_GameControllerDB]SDL2 game controller database[/url] to determine gamepad names.
</description>
</method>
<method name="get_joy_power_state" qualifiers="const" experimental="">
<return type="int" enum="JoyPowerState" />
<param index="0" name="device" type="int" />
<description>
Returns the joypad's power state (i.e. if it's currently charging, being used on battery, etc.).
[b]Note:[/b] This feature is only supported on Windows, Linux, and macOS.
</description>
</method>
<method name="get_joy_vibration_duration">
<return type="float" />
<param index="0" name="device" type="int" />
Expand Down
28 changes: 28 additions & 0 deletions drivers/sdl/joypad_sdl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -203,12 +203,29 @@ void JoypadSDL::process_events() {
joypads[joy_id].guid,
joypad_info);

// Querying more information about the joypad

int joy_battery_percent;
SDL_PowerState joy_power_state = SDL_GetJoystickPowerInfo(joy, &joy_battery_percent);
SDL_JoystickConnectionState joy_connection_state = SDL_GetJoystickConnectionState(joy);
if (joy_power_state == SDL_POWERSTATE_ERROR) {
joy_power_state = SDL_POWERSTATE_UNKNOWN;
}
if (joy_connection_state == SDL_JOYSTICK_CONNECTION_INVALID) {
joy_connection_state = SDL_JOYSTICK_CONNECTION_UNKNOWN;
}

Input::get_singleton()->set_joy_features(joy_id, &joypads[joy_id]);

if (joypads[joy_id].supports_motion_sensors) {
// Data rate for all sensors should be the same.
Input::get_singleton()->set_joy_motion_sensors_rate(joy_id, SDL_GetGamepadSensorDataRate(gamepad, SDL_SENSOR_ACCEL));
}

// Godot constants are intentionally the same as SDL's
Input::get_singleton()->set_joy_power_state(joy_id, static_cast<JoyPowerState>(joy_power_state));
Input::get_singleton()->set_joy_battery_percent(joy_id, joy_battery_percent);
Input::get_singleton()->set_joy_connection_state(joy_id, static_cast<JoyConnectionState>(joy_connection_state));
}
// 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)) {
Expand Down Expand Up @@ -254,6 +271,17 @@ void JoypadSDL::process_events() {
);
break;

case SDL_EVENT_JOYSTICK_BATTERY_UPDATED: {
// Gamepads also can have battery, so no SKIP_EVENT_FOR_GAMEPAD here

SDL_PowerState joy_power_state = sdl_event.jbattery.state;
if (joy_power_state == SDL_POWERSTATE_ERROR) {
joy_power_state = SDL_POWERSTATE_UNKNOWN;
}
Input::get_singleton()->set_joy_power_state(joy_id, static_cast<JoyPowerState>(sdl_event.jbattery.state)); // Godot constants are intentionally the same as SDL's
Input::get_singleton()->set_joy_battery_percent(joy_id, sdl_event.jbattery.percent);
} break;

case SDL_EVENT_GAMEPAD_AXIS_MOTION: {
float axis_value;

Expand Down
Loading