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
68 changes: 68 additions & 0 deletions core/input/input.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,10 @@ void Input::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_accelerometer"), &Input::get_accelerometer);
ClassDB::bind_method(D_METHOD("get_magnetometer"), &Input::get_magnetometer);
ClassDB::bind_method(D_METHOD("get_gyroscope"), &Input::get_gyroscope);
ClassDB::bind_method(D_METHOD("get_joy_touchpad_finger_position", "device", "touchpad", "finger"), &Input::get_joy_touchpad_finger_position);
ClassDB::bind_method(D_METHOD("get_joy_touchpad_finger_pressure", "device", "touchpad", "finger"), &Input::get_joy_touchpad_finger_pressure);
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 @@ -731,6 +735,43 @@ Vector3 Input::get_gyroscope() const {
return gyroscope;
}

Vector2 Input::get_joy_touchpad_finger_position(int p_device, int p_touchpad, int p_finger) const {
_THREAD_SAFE_METHOD_
if (!joy_touch.has(p_device) || !joy_touch[p_device].touchpad_fingers.has(p_touchpad) || !joy_touch[p_device].touchpad_fingers[p_touchpad].has(p_finger)) {
return Vector2();
}
return joy_touch[p_device].touchpad_fingers[p_touchpad][p_finger].position;
}

float Input::get_joy_touchpad_finger_pressure(int p_device, int p_touchpad, int p_finger) const {
_THREAD_SAFE_METHOD_
if (!joy_touch.has(p_device) || !joy_touch[p_device].touchpad_fingers.has(p_touchpad) || !joy_touch[p_device].touchpad_fingers[p_touchpad].has(p_finger)) {
return 0.0f;
}
return joy_touch[p_device].touchpad_fingers[p_touchpad][p_finger].pressure;
}

TypedArray<int> Input::get_joy_touchpad_fingers(int p_device, int p_touchpad) const {
_THREAD_SAFE_METHOD_
if (!joy_touch.has(p_device) || !joy_touch[p_device].touchpad_fingers.has(p_touchpad)) {
return TypedArray<int>();
}

TypedArray<int> result;
for (auto &i : joy_touch[p_device].touchpad_fingers[p_touchpad]) {
result.append(i.key);
}
return result;
}

int Input::get_joy_num_touchpads(int p_device) const {
_THREAD_SAFE_METHOD_
if (!joy_touch.has(p_device)) {
return 0;
}
return joy_touch[p_device].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 @@ -986,6 +1027,24 @@ void Input::set_joy_axis(int p_device, JoyAxis p_axis, float p_value) {
_joy_axis[c] = p_value;
}

void Input::set_joy_features(int p_device, JoypadFeatures *p_features) {
if (!joy_names.has(p_device)) {
return;
}
joy_names[p_device].features = p_features;
_update_joypad_features(p_device);
}

void Input::set_joy_touchpad_finger(int p_device, int p_touchpad, int p_finger, float p_pressure, Vector2 p_value) {
_THREAD_SAFE_METHOD_
if (p_pressure > 0.0f) {
joy_touch[p_device].touchpad_fingers[p_touchpad][p_finger] = TouchpadFingerInfo{ p_value, p_pressure };
} else {
joy_touch[p_device].touchpad_fingers[p_touchpad].erase(p_finger);
}
// TODO: event
}

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) {
Expand Down Expand Up @@ -1478,6 +1537,15 @@ void Input::_update_action_cache(const StringName &p_action_name, ActionState &r
}
}

void Input::_update_joypad_features(int p_device) {
if (!joy_names.has(p_device) || joy_names[p_device].features == nullptr) {
return;
}
if (joy_names[p_device].features->get_joy_num_touchpads() > 0) {
joy_touch[p_device].num_touchpads = joy_names[p_device].features->get_joy_num_touchpads();
}
}

Input::JoyEvent Input::_get_mapped_button_event(const JoyDeviceMapping &mapping, JoyButton p_button) {
JoyEvent event;

Expand Down
32 changes: 32 additions & 0 deletions core/input/input.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,13 @@ class Input : public Object {
CURSOR_MAX
};

class JoypadFeatures {
public:
virtual ~JoypadFeatures() {}

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

static constexpr int32_t JOYPADS_MAX = 16;

typedef void (*EventDispatchFunc)(const Ref<InputEvent> &p_event);
Expand Down Expand Up @@ -149,6 +156,19 @@ class Input : public Object {

HashMap<int, VibrationInfo> joy_vibration;

struct TouchpadFingerInfo {
Vector2 position = Vector2();
float pressure = 0.0f;
};

struct TouchpadInfo {
int num_touchpads = 0;
// The first int index refers to touchpad ID, the second one refers to finger ID on that touchpad.
HashMap<int, HashMap<int, TouchpadFingerInfo>> touchpad_fingers;
};

HashMap<int, TouchpadInfo> joy_touch;

struct VelocityTrack {
uint64_t last_tick = 0;
Vector2 velocity;
Expand All @@ -174,6 +194,7 @@ class Input : public Object {
int mapping = -1;
int hat_current = 0;
Dictionary info;
Input::JoypadFeatures *features;
};

VelocityTrack mouse_velocity_track;
Expand Down Expand Up @@ -253,6 +274,7 @@ class Input : public Object {
void _button_event(int p_device, JoyButton p_index, bool p_pressed);
void _axis_event(int p_device, JoyAxis p_axis, float p_value);
void _update_action_cache(const StringName &p_action_name, ActionState &r_action_state);
void _update_joypad_features(int p_device);

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

Expand Down Expand Up @@ -330,6 +352,12 @@ class Input : public Object {
Vector3 get_magnetometer() const;
Vector3 get_gyroscope() const;

Vector2 get_joy_touchpad_finger_position(int p_device, int p_touchpad, int p_finger) const;
float get_joy_touchpad_finger_pressure(int p_device, int p_touchpad, int p_finger) const;
TypedArray<int> get_joy_touchpad_fingers(int p_device, int p_touchpad) 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 All @@ -346,6 +374,10 @@ class Input : public Object {
void set_gyroscope(const Vector3 &p_gyroscope);
void set_joy_axis(int p_device, JoyAxis p_axis, float p_value);

void set_joy_features(int p_device, JoypadFeatures *p_features);

void set_joy_touchpad_finger(int p_device, int p_touchpad, int p_finger, float p_pressure, Vector2 p_value);

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);
Expand Down
43 changes: 43 additions & 0 deletions doc/classes/Input.xml
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,49 @@
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">
<return type="int" />
<param index="0" name="device" type="int" />
<description>
Returns the number of touchpads on the joypad.
[b]Note:[/b] This method may return inaccurate results if this joypad is not in Godot's controller database.
[b]Note:[/b] This feature is only supported on Windows, Linux, and macOS.
</description>
</method>
<method name="get_joy_touchpad_finger_position" qualifiers="const">
<return type="Vector2" />
<param index="0" name="device" type="int" />
<param index="1" name="touchpad" type="int" />
<param index="2" name="finger" type="int" />
<description>
Returns the position of the specified finger on the specified touchpad on the joypad. The X and Y values are in the range 0.0 to 1.0, 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, and macOS.
</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="touchpad" type="int" />
<param index="2" name="finger" type="int" />
<description>
Returns the pressure of the specified finger on the specified touchpad on the joypad. The pressure values are in range between 0.0 and 1.0.
If the touchpad doesn't support pressure sensitivity and the specified finger is currently touching the touchpad, this method returns [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, and macOS.
</description>
</method>
<method name="get_joy_touchpad_fingers" qualifiers="const">
<return type="int[]" />
<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], and to retrieve their pressure value (if supported), use [method get_joy_touchpad_finger_pressure].
[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
1 change: 1 addition & 0 deletions drivers/sdl/SCsub
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ if env["builtin_sdl"]:
"joystick/windows/SDL_xinputjoystick.c",
"thread/generic/SDL_syscond.c",
"thread/generic/SDL_sysrwlock.c",
"sensor/windows/SDL_windowssensor.c",
"thread/windows/SDL_syscond_cv.c",
"thread/windows/SDL_sysmutex.c",
"thread/windows/SDL_sysrwlock_srw.c",
Expand Down
5 changes: 4 additions & 1 deletion drivers/sdl/SDL_build_config_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@
#define SDL_DIALOG_DISABLED 1
#define SDL_FILESYSTEM_DUMMY 1
#define SDL_FSOPS_DUMMY 1
#define SDL_SENSOR_DISABLED 1
#define SDL_GPU_DISABLED 1
#define SDL_RENDER_DISABLED 1
#define SDL_POWER_DISABLED 1
Expand All @@ -73,6 +72,7 @@
#define SDL_THREAD_GENERIC_RWLOCK_SUFFIX 1
#define SDL_THREAD_WINDOWS 1
#define SDL_TIMER_WINDOWS 1
#define SDL_SENSOR_WINDOWS 1

// Linux defines
#elif defined(SDL_PLATFORM_LINUX)
Expand Down Expand Up @@ -113,6 +113,7 @@
#define SDL_HAPTIC_LINUX 1
#define SDL_TIMER_UNIX 1
#define SDL_JOYSTICK_LINUX 1
#define SDL_JOYSTICK_HIDAPI 1
#define SDL_INPUT_LINUXEV 1
#define SDL_THREAD_PTHREAD 1

Expand All @@ -126,8 +127,10 @@
#define SDL_HAPTIC_IOKIT 1
#define SDL_JOYSTICK_IOKIT 1
#define SDL_JOYSTICK_MFI 1
#define SDL_JOYSTICK_HIDAPI 1
#define SDL_TIMER_UNIX 1
#define SDL_THREAD_PTHREAD 1
#define SDL_THREAD_PTHREAD_RECURSIVE_MUTEX 1

// Other platforms are not supported (for now)
#else
Expand Down
25 changes: 25 additions & 0 deletions drivers/sdl/joypad_sdl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,8 @@ void JoypadSDL::process_events() {
device_name,
joypads[joy_id].guid,
joypad_info);

Input::get_singleton()->set_joy_features(joy_id, &joypads[joy_id]);
}
// 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 @@ -279,6 +281,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()->set_joy_touchpad_finger(
joy_id,
sdl_event.gtouchpad.touchpad,
sdl_event.gtouchpad.finger,
sdl_event.gtouchpad.pressure,
Vector2(sdl_event.gtouchpad.x, sdl_event.gtouchpad.y));
break;
}
}
}
Expand All @@ -299,4 +312,16 @@ void JoypadSDL::close_joypad(int p_pad_idx) {
}
}

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);
}

SDL_Gamepad *JoypadSDL::Joypad::get_sdl_gamepad() const {
return SDL_GetGamepadFromID(sdl_instance_idx);
}

#endif // SDL_ENABLED
10 changes: 9 additions & 1 deletion drivers/sdl/joypad_sdl.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@

typedef uint32_t SDL_JoystickID;
typedef struct HWND__ *HWND;
typedef struct SDL_Joystick SDL_Joystick;
typedef struct SDL_Gamepad SDL_Gamepad;

class JoypadSDL {
public:
Expand All @@ -50,14 +52,20 @@ class JoypadSDL {
void process_events();

private:
struct Joypad {
class Joypad : public Input::JoypadFeatures {
public:
bool attached = false;
StringName guid;

SDL_JoystickID sdl_instance_idx;

bool supports_force_feedback = false;
uint64_t ff_effect_timestamp = 0;

int get_joy_num_touchpads() const override;

SDL_Joystick *get_sdl_joystick() const;
SDL_Gamepad *get_sdl_gamepad() const;
};

static JoypadSDL *singleton;
Expand Down
Loading