mirror of
https://github.com/Relintai/pandemonium_engine.git
synced 2025-01-03 09:29:38 +01:00
Ported from godot: Input - fix just pressed and released with short presses
Previously if an action was both pressed and released on the same tick or frame, `is_action_just_pressed()` would return false, resulting in missed input.
This PR separately the timestamp for pressing and releasing so each can be tested independently.
- lawnjelly
63d208d1b0
This commit is contained in:
parent
83468ef10b
commit
ee54ca3808
@ -861,6 +861,11 @@
|
||||
Enabling this can greatly improve the responsiveness to input, specially in devices that need to run multiple physics frames per visible (idle) frame, because they can't run at the target frame rate.
|
||||
[b]Note:[/b] Currently implemented only in Android.
|
||||
</member>
|
||||
<member name="input_devices/compatibility/legacy_just_pressed_behavior" type="bool" setter="" getter="" default="false">
|
||||
If [code]true[/code], [method Input.is_action_just_pressed] and [method Input.is_action_just_released] will only return [code]true[/code] if the action is still in the respective state, i.e. an action that is pressed [i]and[/i] released on the same frame will be missed.
|
||||
If [code]false[/code], no input will be lost.
|
||||
[b]Note:[/b] You should in nearly all cases prefer the [code]false[/code] setting. The legacy behavior is to enable supporting old projects that rely on the old logic, without changes to script.
|
||||
</member>
|
||||
<member name="input_devices/pointing/emulate_mouse_from_touch" type="bool" setter="" getter="" default="true">
|
||||
If [code]true[/code], sends mouse input events when tapping or swiping on the touchscreen.
|
||||
</member>
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include "core/input/default_controller_mappings.h"
|
||||
#include "core/input/input_map.h"
|
||||
#include "core/os/os.h"
|
||||
#include "core/config/project_settings.h"
|
||||
#include "scene/resources/texture.h"
|
||||
#include "servers/rendering_server.h"
|
||||
|
||||
@ -124,10 +125,13 @@ bool InputDefault::is_action_just_pressed(const StringName &p_action, bool p_exa
|
||||
return false;
|
||||
}
|
||||
|
||||
// Backward compatibility for legacy behavior, only return true if currently pressed.
|
||||
bool pressed_requirement = legacy_just_pressed_behavior ? E->get().pressed : true;
|
||||
|
||||
if (Engine::get_singleton()->is_in_physics_frame()) {
|
||||
return E->get().pressed && E->get().physics_frame == Engine::get_singleton()->get_physics_frames();
|
||||
return pressed_requirement && E->get().pressed_physics_frame == Engine::get_singleton()->get_physics_frames();
|
||||
} else {
|
||||
return E->get().pressed && E->get().idle_frame == Engine::get_singleton()->get_idle_frames();
|
||||
return pressed_requirement && E->get().pressed_idle_frame == Engine::get_singleton()->get_idle_frames();
|
||||
}
|
||||
}
|
||||
|
||||
@ -142,10 +146,13 @@ bool InputDefault::is_action_just_released(const StringName &p_action, bool p_ex
|
||||
return false;
|
||||
}
|
||||
|
||||
// Backward compatibility for legacy behavior, only return true if currently released.
|
||||
bool released_requirement = legacy_just_pressed_behavior ? !E->get().pressed : true;
|
||||
|
||||
if (Engine::get_singleton()->is_in_physics_frame()) {
|
||||
return !E->get().pressed && E->get().physics_frame == Engine::get_singleton()->get_physics_frames();
|
||||
return released_requirement && E->get().released_physics_frame == Engine::get_singleton()->get_physics_frames();
|
||||
} else {
|
||||
return !E->get().pressed && E->get().idle_frame == Engine::get_singleton()->get_idle_frames();
|
||||
return released_requirement && E->get().released_idle_frame == Engine::get_singleton()->get_idle_frames();
|
||||
}
|
||||
}
|
||||
|
||||
@ -499,19 +506,27 @@ void InputDefault::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool
|
||||
|
||||
for (const RBMap<StringName, InputMap::Action>::Element *E = InputMap::get_singleton()->get_action_map().front(); E; E = E->next()) {
|
||||
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())) {
|
||||
Action action;
|
||||
action.physics_frame = Engine::get_singleton()->get_physics_frames();
|
||||
action.idle_frame = Engine::get_singleton()->get_idle_frames();
|
||||
action.pressed = p_event->is_action_pressed(E->key());
|
||||
if (p_event->is_action_pressed(E->key())) {
|
||||
action.pressed = true;
|
||||
action.pressed_physics_frame = Engine::get_singleton()->get_physics_frames();
|
||||
action.pressed_idle_frame = Engine::get_singleton()->get_idle_frames();
|
||||
} else {
|
||||
action.pressed = false;
|
||||
action.released_physics_frame = Engine::get_singleton()->get_physics_frames();
|
||||
action.released_idle_frame = Engine::get_singleton()->get_idle_frames();
|
||||
}
|
||||
|
||||
action.strength = 0.0f;
|
||||
action.raw_strength = 0.0f;
|
||||
action.exact = InputMap::get_singleton()->event_is_action(p_event, E->key(), true);
|
||||
action_state[E->key()] = action;
|
||||
}
|
||||
action_state[E->key()].strength = p_event->get_action_strength(E->key());
|
||||
action_state[E->key()].raw_strength = p_event->get_action_raw_strength(E->key());
|
||||
|
||||
action.strength = p_event->get_action_strength(E->key());
|
||||
action.raw_strength = p_event->get_action_raw_strength(E->key());
|
||||
}
|
||||
}
|
||||
|
||||
@ -632,29 +647,27 @@ void InputDefault::iteration(float p_step) {
|
||||
}
|
||||
|
||||
void InputDefault::action_press(const StringName &p_action, float p_strength) {
|
||||
Action action;
|
||||
// Create or retrieve existing action.
|
||||
Action &action = action_state[p_action];
|
||||
|
||||
action.physics_frame = Engine::get_singleton()->get_physics_frames();
|
||||
action.idle_frame = Engine::get_singleton()->get_idle_frames();
|
||||
action.pressed_physics_frame = Engine::get_singleton()->get_physics_frames();
|
||||
action.pressed_idle_frame = Engine::get_singleton()->get_idle_frames();
|
||||
action.pressed = true;
|
||||
action.exact = true;
|
||||
action.strength = p_strength;
|
||||
action.raw_strength = p_strength;
|
||||
action.exact = true;
|
||||
|
||||
action_state[p_action] = action;
|
||||
}
|
||||
|
||||
void InputDefault::action_release(const StringName &p_action) {
|
||||
Action action;
|
||||
// Create or retrieve existing action.
|
||||
Action &action = action_state[p_action];
|
||||
|
||||
action.physics_frame = Engine::get_singleton()->get_physics_frames();
|
||||
action.idle_frame = Engine::get_singleton()->get_idle_frames();
|
||||
action.released_physics_frame = Engine::get_singleton()->get_physics_frames();
|
||||
action.released_idle_frame = Engine::get_singleton()->get_idle_frames();
|
||||
action.pressed = false;
|
||||
action.strength = 0.f;
|
||||
action.raw_strength = 0.f;
|
||||
action.exact = true;
|
||||
|
||||
action_state[p_action] = action;
|
||||
action.strength = 0.0f;
|
||||
action.raw_strength = 0.0f;
|
||||
}
|
||||
|
||||
void InputDefault::set_emulate_touch_from_mouse(bool p_emulate) {
|
||||
@ -798,9 +811,16 @@ InputDefault::InputDefault() {
|
||||
mouse_from_touch_index = -1;
|
||||
main_loop = nullptr;
|
||||
default_shape = CURSOR_ARROW;
|
||||
legacy_just_pressed_behavior = false;
|
||||
|
||||
fallback_mapping = -1;
|
||||
|
||||
legacy_just_pressed_behavior = GLOBAL_DEF("input_devices/compatibility/legacy_just_pressed_behavior", false);
|
||||
if (Engine::get_singleton()->is_editor_hint()) {
|
||||
// Always use standard behaviour in the editor.
|
||||
legacy_just_pressed_behavior = false;
|
||||
}
|
||||
|
||||
// Parse default mappings.
|
||||
{
|
||||
int i = 0;
|
||||
|
@ -49,14 +49,28 @@ class InputDefault : public Input {
|
||||
Vector3 gyroscope;
|
||||
Vector2 mouse_pos;
|
||||
MainLoop *main_loop;
|
||||
bool legacy_just_pressed_behavior;
|
||||
|
||||
struct Action {
|
||||
uint64_t physics_frame;
|
||||
uint64_t idle_frame;
|
||||
uint64_t pressed_physics_frame;
|
||||
uint64_t pressed_idle_frame;
|
||||
uint64_t released_physics_frame;
|
||||
uint64_t released_idle_frame;
|
||||
bool pressed;
|
||||
bool exact;
|
||||
float strength;
|
||||
float raw_strength;
|
||||
|
||||
Action() {
|
||||
pressed_physics_frame = UINT64_MAX;
|
||||
pressed_idle_frame = UINT64_MAX;
|
||||
released_physics_frame = UINT64_MAX;
|
||||
released_idle_frame = UINT64_MAX;
|
||||
pressed = false;
|
||||
exact = true;
|
||||
strength = 0.0f;
|
||||
raw_strength = 0.0f;
|
||||
}
|
||||
};
|
||||
|
||||
RBMap<StringName, Action> action_state;
|
||||
|
Loading…
Reference in New Issue
Block a user