summaryrefslogtreecommitdiffstats
path: root/core/input/input.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'core/input/input.cpp')
-rw-r--r--core/input/input.cpp78
1 files changed, 56 insertions, 22 deletions
diff --git a/core/input/input.cpp b/core/input/input.cpp
index 4a32abfafa..f3f5940118 100644
--- a/core/input/input.cpp
+++ b/core/input/input.cpp
@@ -285,7 +285,7 @@ bool Input::is_joy_button_pressed(int p_device, JoyButton p_button) const {
bool Input::is_action_pressed(const StringName &p_action, bool p_exact) const {
ERR_FAIL_COND_V_MSG(!InputMap::get_singleton()->has_action(p_action), false, InputMap::get_singleton()->suggest_actions(p_action));
- return action_state.has(p_action) && action_state[p_action].pressed && (p_exact ? action_state[p_action].exact : true);
+ return action_state.has(p_action) && action_state[p_action].pressed > 0 && (p_exact ? action_state[p_action].exact : true);
}
bool Input::is_action_just_pressed(const StringName &p_action, bool p_exact) const {
@@ -475,7 +475,8 @@ void Input::joy_connection_changed(int p_idx, bool p_connected, String p_name, S
}
joy_names[p_idx] = js;
- emit_signal(SNAME("joy_connection_changed"), p_idx, p_connected);
+ // Ensure this signal is emitted on the main thread, as some platforms (e.g. Linux) call this from a different thread.
+ call_deferred("emit_signal", SNAME("joy_connection_changed"), p_idx, p_connected);
}
Vector3 Input::get_gravity() const {
@@ -696,23 +697,50 @@ void Input::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_em
for (const KeyValue<StringName, InputMap::Action> &E : InputMap::get_singleton()->get_action_map()) {
if (InputMap::get_singleton()->event_is_action(p_event, E.key)) {
Action &action = action_state[E.key];
- // If not echo and action pressed state has changed
- if (!p_event->is_echo() && is_action_pressed(E.key, false) != p_event->is_action_pressed(E.key)) {
+ bool is_joypad_axis = jm.is_valid();
+ bool is_pressed = false;
+ if (!p_event->is_echo()) {
if (p_event->is_action_pressed(E.key)) {
- action.pressed = true;
- action.pressed_physics_frame = Engine::get_singleton()->get_physics_frames();
- action.pressed_process_frame = Engine::get_singleton()->get_process_frames();
+ bool is_joypad_axis_valid_zone_enter = false;
+ if (is_joypad_axis) {
+ if (!action.axis_pressed) {
+ is_joypad_axis_valid_zone_enter = true;
+ action.pressed++;
+ action.axis_pressed = true;
+ }
+ } else {
+ action.pressed++;
+ }
+ if (action.pressed == 1 && (is_joypad_axis_valid_zone_enter || !is_joypad_axis)) {
+ action.pressed_physics_frame = Engine::get_singleton()->get_physics_frames();
+ action.pressed_process_frame = Engine::get_singleton()->get_process_frames();
+ }
+ is_pressed = true;
} else {
- action.pressed = false;
- action.released_physics_frame = Engine::get_singleton()->get_physics_frames();
- action.released_process_frame = Engine::get_singleton()->get_process_frames();
+ bool is_released = true;
+ if (is_joypad_axis) {
+ if (action.axis_pressed) {
+ action.axis_pressed = false;
+ } else {
+ is_released = false;
+ }
+ }
+
+ if (is_released) {
+ if (action.pressed == 1) {
+ action.released_physics_frame = Engine::get_singleton()->get_physics_frames();
+ action.released_process_frame = Engine::get_singleton()->get_process_frames();
+ }
+ action.pressed = MAX(action.pressed - 1, 0);
+ }
}
- action.strength = 0.0f;
- action.raw_strength = 0.0f;
action.exact = InputMap::get_singleton()->event_is_action(p_event, E.key, true);
}
- action.strength = p_event->get_action_strength(E.key);
- action.raw_strength = p_event->get_action_raw_strength(E.key);
+
+ if (is_pressed || action.pressed == 0) {
+ action.strength = p_event->get_action_strength(E.key);
+ action.raw_strength = p_event->get_action_raw_strength(E.key);
+ }
}
}
@@ -830,9 +858,11 @@ void Input::action_press(const StringName &p_action, float p_strength) {
// Create or retrieve existing action.
Action &action = action_state[p_action];
- action.pressed_physics_frame = Engine::get_singleton()->get_physics_frames();
- action.pressed_process_frame = Engine::get_singleton()->get_process_frames();
- action.pressed = true;
+ action.pressed++;
+ if (action.pressed == 1) {
+ action.pressed_physics_frame = Engine::get_singleton()->get_physics_frames();
+ action.pressed_process_frame = Engine::get_singleton()->get_process_frames();
+ }
action.strength = p_strength;
action.raw_strength = p_strength;
action.exact = true;
@@ -842,9 +872,11 @@ void Input::action_release(const StringName &p_action) {
// Create or retrieve existing action.
Action &action = action_state[p_action];
- action.released_physics_frame = Engine::get_singleton()->get_physics_frames();
- action.released_process_frame = Engine::get_singleton()->get_process_frames();
- action.pressed = false;
+ action.pressed--;
+ if (action.pressed == 0) {
+ action.released_physics_frame = Engine::get_singleton()->get_physics_frames();
+ action.released_process_frame = Engine::get_singleton()->get_process_frames();
+ }
action.strength = 0.0f;
action.raw_strength = 0.0f;
action.exact = true;
@@ -1005,8 +1037,10 @@ void Input::release_pressed_events() {
joy_buttons_pressed.clear();
_joy_axis.clear();
- for (const KeyValue<StringName, Input::Action> &E : action_state) {
- if (E.value.pressed) {
+ for (KeyValue<StringName, Input::Action> &E : action_state) {
+ if (E.value.pressed > 0) {
+ // Make sure the action is really released.
+ E.value.pressed = 1;
action_release(E.key);
}
}