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
84 changes: 84 additions & 0 deletions core/input/input.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,10 @@ void Input::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_joy_motion_sensors_calibration", "device", "calibration_info"), &Input::set_joy_motion_sensors_calibration);
ClassDB::bind_method(D_METHOD("is_joy_motion_sensors_calibrated", "device"), &Input::is_joy_motion_sensors_calibrated);
ClassDB::bind_method(D_METHOD("is_joy_motion_sensors_calibrating", "device"), &Input::is_joy_motion_sensors_calibrating);
ClassDB::bind_method(D_METHOD("get_joy_touchpad_finger_position", "device", "finger", "touchpad"), &Input::get_joy_touchpad_finger_position, DEFVAL(0));
ClassDB::bind_method(D_METHOD("get_joy_touchpad_finger_pressure", "device", "finger", "touchpad"), &Input::get_joy_touchpad_finger_pressure, DEFVAL(0));
ClassDB::bind_method(D_METHOD("get_joy_touchpad_fingers", "device", "touchpad"), &Input::get_joy_touchpad_fingers);
ClassDB::bind_method(D_METHOD("get_joy_num_touchpads", "device"), &Input::get_joy_num_touchpads);
ClassDB::bind_method(D_METHOD("set_gravity", "value"), &Input::set_gravity);
ClassDB::bind_method(D_METHOD("set_accelerometer", "value"), &Input::set_accelerometer);
ClassDB::bind_method(D_METHOD("set_magnetometer", "value"), &Input::set_magnetometer);
Expand Down Expand Up @@ -798,6 +802,64 @@ Vector3 Input::get_gyroscope() const {
return gyroscope;
}

Vector2 Input::get_joy_touchpad_finger_position(int p_device, int p_finger, int p_touchpad) const {
_THREAD_SAFE_METHOD_
const TouchpadInfo *touch = joy_touch.getptr(p_device);
if (touch == nullptr) {
return Vector2();
}

uint16_t index = p_finger | (p_touchpad << 8);
const TouchpadFingerInfo *finger_info = touch->finger_info.getptr(index);
if (finger_info == nullptr) {
return Vector2();
}

return finger_info->position;
}

float Input::get_joy_touchpad_finger_pressure(int p_device, int p_finger, int p_touchpad) const {
_THREAD_SAFE_METHOD_
const TouchpadInfo *touch = joy_touch.getptr(p_device);
if (touch == nullptr) {
return 0.0f;
}

uint16_t index = p_finger | (p_touchpad << 8);
const TouchpadFingerInfo *finger_info = touch->finger_info.getptr(index);
if (finger_info == nullptr) {
return 0.0f;
}

return finger_info->pressure;
}

PackedInt32Array Input::get_joy_touchpad_fingers(int p_device, int p_touchpad) const {
_THREAD_SAFE_METHOD_
const TouchpadInfo *touch = joy_touch.getptr(p_device);
if (touch == nullptr) {
return PackedInt32Array();
}

PackedInt32Array result;
for (const KeyValue<uint16_t, TouchpadFingerInfo> &index : touch->finger_info) {
int touchpad = index.key >> 8;
if (touchpad == p_touchpad) {
result.append(index.key & 0xFF);
}
}
return result;
}

int Input::get_joy_num_touchpads(int p_device) const {
_THREAD_SAFE_METHOD_
const TouchpadInfo *touch = joy_touch.getptr(p_device);
if (touch == nullptr) {
return 0;
}
return touch->num_touchpads;
}

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 @@ -1620,6 +1682,9 @@ void Input::release_pressed_events() {

for (int device : get_connected_joypads()) {
stop_joy_vibration(device);

TouchpadInfo &touch = joy_touch[device];
touch.finger_info.clear();
}
} else {
for (KeyValue<StringName, Input::ActionState> &E : action_states) {
Expand Down Expand Up @@ -1823,6 +1888,22 @@ void Input::joy_motion_sensors(int p_device, const Vector3 &p_accelerometer, con
motion->gamepad_motion->ProcessMotion(gyro_degrees.x, gyro_degrees.y, gyro_degrees.z, accel_g.x, accel_g.y, accel_g.z, delta_time);
}

void Input::joy_touchpad(int p_device, int p_touchpad, int p_finger, const Vector2 &p_value, float p_pressure) {
_THREAD_SAFE_METHOD_

if (_should_ignore_joypad_events()) {
return;
}

TouchpadInfo &touch = joy_touch[p_device];
uint16_t index = p_finger | (p_touchpad << 8);
if (p_pressure > 0.0) {
touch.finger_info[index] = TouchpadFingerInfo{ p_value, p_pressure };
} else {
touch.finger_info.erase(index);
}
}

void Input::_button_event(int p_device, JoyButton p_index, bool p_pressed) {
Ref<InputEventJoypadButton> ievent;
ievent.instantiate();
Expand Down Expand Up @@ -1887,6 +1968,9 @@ void Input::_update_joypad_features(int p_device) {
}
motion.last_timestamp = OS::get_singleton()->get_ticks_msec();
}
if (joypad->features->get_joy_num_touchpads() > 0) {
joy_touch[p_device].num_touchpads = joypad->features->get_joy_num_touchpads();
}
}

Input::JoyEvent Input::_get_mapped_button_event(const JoyDeviceMapping &mapping, JoyButton p_button) {
Expand Down
21 changes: 21 additions & 0 deletions core/input/input.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ class Input : public Object {

virtual bool has_joy_motion_sensors() const { return false; }
virtual void set_joy_motion_sensors_enabled(bool p_enable) {}

virtual int get_joy_num_touchpads() const { return 0; }
};

static constexpr int32_t JOYPADS_MAX = 16;
Expand Down Expand Up @@ -192,6 +194,18 @@ class Input : public Object {

HashMap<int, MotionInfo> joy_motion;

struct TouchpadFingerInfo {
Vector2 position;
float pressure;
};

struct TouchpadInfo {
int num_touchpads = 0;
HashMap<uint16_t, TouchpadFingerInfo> finger_info;
};

HashMap<int, TouchpadInfo> joy_touch;

struct VelocityTrack {
uint64_t last_tick = 0;
Vector2 velocity;
Expand Down Expand Up @@ -385,6 +399,12 @@ class Input : public Object {
Vector3 get_magnetometer() const;
Vector3 get_gyroscope() const;

Vector2 get_joy_touchpad_finger_position(int p_device, int p_finger, int p_touchpad = 0) const;
float get_joy_touchpad_finger_pressure(int p_device, int p_finger, int p_touchpad = 0) const;
PackedInt32Array get_joy_touchpad_fingers(int p_device, int p_touchpad = 0) const;

int get_joy_num_touchpads(int p_device) const;

Point2 get_mouse_position() const;
Vector2 get_last_mouse_velocity();
Vector2 get_last_mouse_screen_velocity();
Expand Down Expand Up @@ -457,6 +477,7 @@ class Input : public Object {
void joy_axis(int p_device, JoyAxis p_axis, float p_value);
void joy_hat(int p_device, BitField<HatMask> p_val);
void joy_motion_sensors(int p_device, const Vector3 &p_accelerometer, const Vector3 &p_gyroscope);
void joy_touchpad(int p_device, int p_touchpad, int p_finger, const Vector2 &p_position, float p_pressure);

void add_joy_mapping(const String &p_mapping, bool p_update_existing = false);
void remove_joy_mapping(const String &p_guid);
Expand Down
41 changes: 41 additions & 0 deletions doc/classes/Input.xml
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,47 @@
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_num_touchpads" qualifiers="const" experimental="">
<return type="int" />
<param index="0" name="device" type="int" />
<description>
Returns the number of touchpads on the specified joypad, if it has any. Otherwise, the method returns [code]0[/code].
[b]Note:[/b] This feature is only supported on Windows, Linux, macOS, and iOS.
</description>
</method>
<method name="get_joy_touchpad_finger_position" qualifiers="const" experimental="">
<return type="Vector2" />
<param index="0" name="device" type="int" />
<param index="1" name="finger" type="int" />
<param index="2" name="touchpad" type="int" default="0" />
<description>
Returns the position of the specified finger on the specified touchpad on the joypad. The X and Y values are in the range from [code]0.0[/code] to [code]1.0[/code], with [code](0.0, 0.0)[/code] representing the top left corner of the touchpad and [code](1.0, 1.0)[/code] representing the bottom right corner.
If the joypad doesn't have the specified touchpad or the specified finger is not currently touching the touchpad, this method returns [constant Vector2.ZERO].
[b]Note:[/b] This feature is only supported on Windows, Linux, macOS, and iOS.
</description>
</method>
<method name="get_joy_touchpad_finger_pressure" qualifiers="const">
<return type="float" />
<param index="0" name="device" type="int" />
<param index="1" name="finger" type="int" />
<param index="2" name="touchpad" type="int" default="0" />
<description>
Returns the pressure of the specified finger on the specified touchpad on the joypad. The return value is in the range from [code]0.0[/code] to [code]1.0[/code].
If the joypad doesn't have the specified touchpad or the specified finger is not currently touching the touchpad, this method returns [code]0.0[/code].
[b]Note:[/b] This feature is only supported on Windows, Linux, macOS, and iOS.
</description>
</method>
<method name="get_joy_touchpad_fingers" qualifiers="const" experimental="">
<return type="PackedInt32Array" />
<param index="0" name="device" type="int" />
<param index="1" name="touchpad" type="int" />
<description>
Returns an array of finger IDs that are currently touching the specified touchpad on the joypad.
If the joypad doesn't have the specified touchpad or no fingers are currently touching this touchpad, this method returns an empty array.
[b]Note:[/b] To retrieve the positions of the touchpad fingers, use [method get_joy_touchpad_finger_position].
[b]Note:[/b] This feature is only supported on Windows, Linux, macOS, and iOS.
</description>
</method>
<method name="get_joy_vibration_duration">
<return type="float" />
<param index="0" name="device" type="int" />
Expand Down
15 changes: 15 additions & 0 deletions drivers/sdl/joypad_sdl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,17 @@ void JoypadSDL::process_events() {
static_cast<JoyButton>(sdl_event.gbutton.button), // Godot button constants are intentionally the same as SDL's, so we can just straight up use them
sdl_event.gbutton.down);
break;

case SDL_EVENT_GAMEPAD_TOUCHPAD_DOWN:
case SDL_EVENT_GAMEPAD_TOUCHPAD_MOTION:
case SDL_EVENT_GAMEPAD_TOUCHPAD_UP:
Input::get_singleton()->joy_touchpad(
joy_id,
sdl_event.gtouchpad.touchpad,
sdl_event.gtouchpad.finger,
Vector2(sdl_event.gtouchpad.x, sdl_event.gtouchpad.y),
sdl_event.gtouchpad.pressure);
break;
}
}
}
Expand Down Expand Up @@ -346,6 +357,10 @@ bool JoypadSDL::Joypad::has_joy_vibration() const {
return supports_force_feedback;
}

int JoypadSDL::Joypad::get_joy_num_touchpads() const {
return SDL_GetNumGamepadTouchpads(get_sdl_gamepad());
}

SDL_Joystick *JoypadSDL::Joypad::get_sdl_joystick() const {
return SDL_GetJoystickFromID(sdl_instance_idx);
}
Expand Down
2 changes: 2 additions & 0 deletions drivers/sdl/joypad_sdl.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ class JoypadSDL {

virtual bool has_joy_vibration() const override;

virtual int get_joy_num_touchpads() const override;

SDL_Joystick *get_sdl_joystick() const;
SDL_Gamepad *get_sdl_gamepad() const;
};
Expand Down
Loading