Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix action exact match (Also fixes ui_ focus keys) #54173

Merged
merged 1 commit into from
Jan 26, 2022
Merged
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
106 changes: 55 additions & 51 deletions core/input/input_event.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ Ref<InputEvent> InputEvent::xformed_by(const Transform2D &p_xform, const Vector2
return Ref<InputEvent>((InputEvent *)this);
}

bool InputEvent::action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float *p_raw_strength, float p_deadzone) const {
bool InputEvent::action_match(const Ref<InputEvent> &p_event, bool p_exact_match, float p_deadzone, bool *r_pressed, float *r_strength, float *r_raw_strength) const {
return false;
}

Expand Down Expand Up @@ -412,35 +412,32 @@ Ref<InputEventKey> InputEventKey::create_reference(Key p_keycode) {
return ie;
}

bool InputEventKey::action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float *p_raw_strength, float p_deadzone) const {
bool InputEventKey::action_match(const Ref<InputEvent> &p_event, bool p_exact_match, float p_deadzone, bool *r_pressed, float *r_strength, float *r_raw_strength) const {
Ref<InputEventKey> key = p_event;
if (key.is_null()) {
return false;
}

bool match = false;
if (get_keycode() == Key::NONE) {
Key code = get_physical_keycode_with_modifiers();
Key event_code = key->get_physical_keycode_with_modifiers();

match = get_physical_keycode() == key->get_physical_keycode() && (!key->is_pressed() || (code & event_code) == code);
bool match;
if (keycode != Key::NONE) {
match = keycode == key->keycode;
} else {
Key code = get_keycode_with_modifiers();
Key event_code = key->get_keycode_with_modifiers();

match = get_keycode() == key->get_keycode() && (!key->is_pressed() || (code & event_code) == code);
match = get_physical_keycode() == key->get_physical_keycode();
}
if (p_exact_match) {
match &= get_modifiers_mask() == key->get_modifiers_mask();
}
if (match) {
bool pressed = key->is_pressed();
if (p_pressed != nullptr) {
*p_pressed = pressed;
if (r_pressed != nullptr) {
*r_pressed = pressed;
}
float strength = pressed ? 1.0f : 0.0f;
if (p_strength != nullptr) {
*p_strength = strength;
if (r_strength != nullptr) {
*r_strength = strength;
}
if (p_raw_strength != nullptr) {
*p_raw_strength = strength;
if (r_raw_strength != nullptr) {
*r_raw_strength = strength;
}
}
return match;
Expand Down Expand Up @@ -585,24 +582,27 @@ Ref<InputEvent> InputEventMouseButton::xformed_by(const Transform2D &p_xform, co
return mb;
}

bool InputEventMouseButton::action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float *p_raw_strength, float p_deadzone) const {
bool InputEventMouseButton::action_match(const Ref<InputEvent> &p_event, bool p_exact_match, float p_deadzone, bool *r_pressed, float *r_strength, float *r_raw_strength) const {
Ref<InputEventMouseButton> mb = p_event;
if (mb.is_null()) {
return false;
}

bool match = mb->button_index == button_index;
bool match = button_index == mb->button_index;
if (p_exact_match) {
match &= get_modifiers_mask() == mb->get_modifiers_mask();
}
if (match) {
bool pressed = mb->is_pressed();
if (p_pressed != nullptr) {
*p_pressed = pressed;
if (r_pressed != nullptr) {
*r_pressed = pressed;
}
float strength = pressed ? 1.0f : 0.0f;
if (p_strength != nullptr) {
*p_strength = strength;
if (r_strength != nullptr) {
*r_strength = strength;
}
if (p_raw_strength != nullptr) {
*p_raw_strength = strength;
if (r_raw_strength != nullptr) {
*r_raw_strength = strength;
}
}

Expand Down Expand Up @@ -887,36 +887,40 @@ bool InputEventJoypadMotion::is_pressed() const {
return Math::abs(axis_value) >= 0.5f;
}

bool InputEventJoypadMotion::action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float *p_raw_strength, float p_deadzone) const {
bool InputEventJoypadMotion::action_match(const Ref<InputEvent> &p_event, bool p_exact_match, float p_deadzone, bool *r_pressed, float *r_strength, float *r_raw_strength) const {
Ref<InputEventJoypadMotion> jm = p_event;
if (jm.is_null()) {
return false;
}

bool match = (axis == jm->axis); // Matches even if not in the same direction, but returns a "not pressed" event.
// Matches even if not in the same direction, but returns a "not pressed" event.
bool match = axis == jm->axis;
if (p_exact_match) {
match &= (axis_value < 0) == (jm->axis_value < 0);
}
Comment on lines +896 to +900
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit concerned about the potential impact of this change on joypad motion events.

I guess let's merge and assess while testing whether this is working as expected.

if (match) {
float jm_abs_axis_value = Math::abs(jm->get_axis_value());
bool same_direction = (((axis_value < 0) == (jm->axis_value < 0)) || jm->axis_value == 0);
bool pressed = same_direction && jm_abs_axis_value >= p_deadzone;
if (p_pressed != nullptr) {
*p_pressed = pressed;
if (r_pressed != nullptr) {
*r_pressed = pressed;
}
if (p_strength != nullptr) {
if (r_strength != nullptr) {
if (pressed) {
if (p_deadzone == 1.0f) {
*p_strength = 1.0f;
*r_strength = 1.0f;
} else {
*p_strength = CLAMP(Math::inverse_lerp(p_deadzone, 1.0f, jm_abs_axis_value), 0.0f, 1.0f);
*r_strength = CLAMP(Math::inverse_lerp(p_deadzone, 1.0f, jm_abs_axis_value), 0.0f, 1.0f);
}
} else {
*p_strength = 0.0f;
*r_strength = 0.0f;
}
}
if (p_raw_strength != nullptr) {
if (r_raw_strength != nullptr) {
if (same_direction) { // NOT pressed, because we want to ignore the deadzone.
*p_raw_strength = jm_abs_axis_value;
*r_raw_strength = jm_abs_axis_value;
} else {
*p_raw_strength = 0.0f;
*r_raw_strength = 0.0f;
}
}
}
Expand Down Expand Up @@ -994,7 +998,7 @@ float InputEventJoypadButton::get_pressure() const {
return pressure;
}

bool InputEventJoypadButton::action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float *p_raw_strength, float p_deadzone) const {
bool InputEventJoypadButton::action_match(const Ref<InputEvent> &p_event, bool p_exact_match, float p_deadzone, bool *r_pressed, float *r_strength, float *r_raw_strength) const {
Ref<InputEventJoypadButton> jb = p_event;
if (jb.is_null()) {
return false;
Expand All @@ -1003,15 +1007,15 @@ bool InputEventJoypadButton::action_match(const Ref<InputEvent> &p_event, bool *
bool match = button_index == jb->button_index;
if (match) {
bool pressed = jb->is_pressed();
if (p_pressed != nullptr) {
*p_pressed = pressed;
if (r_pressed != nullptr) {
*r_pressed = pressed;
}
float strength = pressed ? 1.0f : 0.0f;
if (p_strength != nullptr) {
*p_strength = strength;
if (r_strength != nullptr) {
*r_strength = strength;
}
if (p_raw_strength != nullptr) {
*p_raw_strength = strength;
if (r_raw_strength != nullptr) {
*r_raw_strength = strength;
}
}

Expand Down Expand Up @@ -1288,7 +1292,7 @@ bool InputEventAction::is_action(const StringName &p_action) const {
return action == p_action;
}

bool InputEventAction::action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float *p_raw_strength, float p_deadzone) const {
bool InputEventAction::action_match(const Ref<InputEvent> &p_event, bool p_exact_match, float p_deadzone, bool *r_pressed, float *r_strength, float *r_raw_strength) const {
Ref<InputEventAction> act = p_event;
if (act.is_null()) {
return false;
Expand All @@ -1297,15 +1301,15 @@ bool InputEventAction::action_match(const Ref<InputEvent> &p_event, bool *p_pres
bool match = action == act->action;
if (match) {
bool pressed = act->pressed;
if (p_pressed != nullptr) {
*p_pressed = pressed;
if (r_pressed != nullptr) {
*r_pressed = pressed;
}
float strength = pressed ? 1.0f : 0.0f;
if (p_strength != nullptr) {
*p_strength = strength;
if (r_strength != nullptr) {
*r_strength = strength;
}
if (p_raw_strength != nullptr) {
*p_raw_strength = strength;
if (r_raw_strength != nullptr) {
*r_raw_strength = strength;
}
}
return match;
Expand Down
12 changes: 6 additions & 6 deletions core/input/input_event.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ class InputEvent : public Resource {

virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const;

virtual bool action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float *p_raw_strength, float p_deadzone) const;
virtual bool action_match(const Ref<InputEvent> &p_event, bool p_exact_match, float p_deadzone, bool *r_pressed, float *r_strength, float *r_raw_strength) const;
virtual bool is_match(const Ref<InputEvent> &p_event, bool p_exact_match = true) const;

virtual bool is_action_type() const;
Expand Down Expand Up @@ -192,7 +192,7 @@ class InputEventKey : public InputEventWithModifiers {
Key get_keycode_with_modifiers() const;
Key get_physical_keycode_with_modifiers() const;

virtual bool action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float *p_raw_strength, float p_deadzone) const override;
virtual bool action_match(const Ref<InputEvent> &p_event, bool p_exact_match, float p_deadzone, bool *r_pressed, float *r_strength, float *r_raw_strength) const override;
virtual bool is_match(const Ref<InputEvent> &p_event, bool p_exact_match = true) const override;

virtual bool is_action_type() const override { return true; }
Expand Down Expand Up @@ -255,7 +255,7 @@ class InputEventMouseButton : public InputEventMouse {

virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const override;

virtual bool action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float *p_raw_strength, float p_deadzone) const override;
virtual bool action_match(const Ref<InputEvent> &p_event, bool p_exact_match, float p_deadzone, bool *r_pressed, float *r_strength, float *r_raw_strength) const override;
virtual bool is_match(const Ref<InputEvent> &p_event, bool p_exact_match = true) const override;

virtual bool is_action_type() const override { return true; }
Expand Down Expand Up @@ -315,7 +315,7 @@ class InputEventJoypadMotion : public InputEvent {

virtual bool is_pressed() const override;

virtual bool action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float *p_raw_strength, float p_deadzone) const override;
virtual bool action_match(const Ref<InputEvent> &p_event, bool p_exact_match, float p_deadzone, bool *r_pressed, float *r_strength, float *r_raw_strength) const override;
virtual bool is_match(const Ref<InputEvent> &p_event, bool p_exact_match = true) const override;

virtual bool is_action_type() const override { return true; }
Expand Down Expand Up @@ -344,7 +344,7 @@ class InputEventJoypadButton : public InputEvent {
void set_pressure(float p_pressure);
float get_pressure() const;

virtual bool action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float *p_raw_strength, float p_deadzone) const override;
virtual bool action_match(const Ref<InputEvent> &p_event, bool p_exact_match, float p_deadzone, bool *r_pressed, float *r_strength, float *r_raw_strength) const override;
virtual bool is_match(const Ref<InputEvent> &p_event, bool p_exact_match = true) const override;

virtual bool is_action_type() const override { return true; }
Expand Down Expand Up @@ -437,7 +437,7 @@ class InputEventAction : public InputEvent {

virtual bool is_action(const StringName &p_action) const;

virtual bool action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float *p_raw_strength, float p_deadzone) const override;
virtual bool action_match(const Ref<InputEvent> &p_event, bool p_exact_match, float p_deadzone, bool *r_pressed, float *r_strength, float *r_raw_strength) const override;
virtual bool is_match(const Ref<InputEvent> &p_event, bool p_exact_match = true) const override;

virtual bool is_action_type() const override { return true; }
Expand Down
42 changes: 14 additions & 28 deletions core/input/input_map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,15 +126,13 @@ List<StringName> InputMap::get_actions() const {
return actions;
}

List<Ref<InputEvent>>::Element *InputMap::_find_event(Action &p_action, const Ref<InputEvent> &p_event, bool p_exact_match, bool *p_pressed, float *p_strength, float *p_raw_strength) const {
List<Ref<InputEvent>>::Element *InputMap::_find_event(Action &p_action, const Ref<InputEvent> &p_event, bool p_exact_match, bool *r_pressed, float *r_strength, float *r_raw_strength) const {
ERR_FAIL_COND_V(!p_event.is_valid(), nullptr);

for (List<Ref<InputEvent>>::Element *E = p_action.inputs.front(); E; E = E->next()) {
int device = E->get()->get_device();
if (device == ALL_DEVICES || device == p_event->get_device()) {
if (p_exact_match && E->get()->is_match(p_event, true)) {
return E;
} else if (!p_exact_match && E->get()->action_match(p_event, p_pressed, p_strength, p_raw_strength, p_action.deadzone)) {
if (E->get()->action_match(p_event, p_exact_match, p_action.deadzone, r_pressed, r_strength, r_raw_strength)) {
return E;
}
}
Expand Down Expand Up @@ -217,40 +215,28 @@ bool InputMap::event_is_action(const Ref<InputEvent> &p_event, const StringName
return event_get_action_status(p_event, p_action, p_exact_match);
}

bool InputMap::event_get_action_status(const Ref<InputEvent> &p_event, const StringName &p_action, bool p_exact_match, bool *p_pressed, float *p_strength, float *p_raw_strength) const {
bool InputMap::event_get_action_status(const Ref<InputEvent> &p_event, const StringName &p_action, bool p_exact_match, bool *r_pressed, float *r_strength, float *r_raw_strength) const {
OrderedHashMap<StringName, Action>::Element E = input_map.find(p_action);
ERR_FAIL_COND_V_MSG(!E, false, suggest_actions(p_action));

Ref<InputEventAction> input_event_action = p_event;
if (input_event_action.is_valid()) {
bool pressed = input_event_action->is_pressed();
if (p_pressed != nullptr) {
*p_pressed = pressed;
const bool pressed = input_event_action->is_pressed();
if (r_pressed != nullptr) {
*r_pressed = pressed;
}
const float strength = pressed ? input_event_action->get_strength() : 0.0f;
if (r_strength != nullptr) {
*r_strength = strength;
}
if (p_strength != nullptr) {
*p_strength = pressed ? input_event_action->get_strength() : 0.0f;
if (r_raw_strength != nullptr) {
*r_raw_strength = strength;
}
return input_event_action->get_action() == p_action;
}

bool pressed;
float strength;
float raw_strength;
List<Ref<InputEvent>>::Element *event = _find_event(E.get(), p_event, p_exact_match, &pressed, &strength, &raw_strength);
if (event != nullptr) {
if (p_pressed != nullptr) {
*p_pressed = pressed;
}
if (p_strength != nullptr) {
*p_strength = strength;
}
if (p_raw_strength != nullptr) {
*p_raw_strength = raw_strength;
}
return true;
} else {
return false;
}
List<Ref<InputEvent>>::Element *event = _find_event(E.get(), p_event, p_exact_match, r_pressed, r_strength, r_raw_strength);
return event != nullptr;
}

const OrderedHashMap<StringName, InputMap::Action> &InputMap::get_action_map() const {
Expand Down
4 changes: 2 additions & 2 deletions core/input/input_map.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ class InputMap : public Object {
OrderedHashMap<String, List<Ref<InputEvent>>> default_builtin_cache;
OrderedHashMap<String, List<Ref<InputEvent>>> default_builtin_with_overrides_cache;

List<Ref<InputEvent>>::Element *_find_event(Action &p_action, const Ref<InputEvent> &p_event, bool p_exact_match = false, bool *p_pressed = nullptr, float *p_strength = nullptr, float *p_raw_strength = nullptr) const;
List<Ref<InputEvent>>::Element *_find_event(Action &p_action, const Ref<InputEvent> &p_event, bool p_exact_match = false, bool *r_pressed = nullptr, float *r_strength = nullptr, float *r_raw_strength = nullptr) const;

Array _action_get_events(const StringName &p_action);
Array _get_actions();
Expand All @@ -83,7 +83,7 @@ class InputMap : public Object {

const List<Ref<InputEvent>> *action_get_events(const StringName &p_action);
bool event_is_action(const Ref<InputEvent> &p_event, const StringName &p_action, bool p_exact_match = false) const;
bool event_get_action_status(const Ref<InputEvent> &p_event, const StringName &p_action, bool p_exact_match = false, bool *p_pressed = nullptr, float *p_strength = nullptr, float *p_raw_strength = nullptr) const;
bool event_get_action_status(const Ref<InputEvent> &p_event, const StringName &p_action, bool p_exact_match = false, bool *r_pressed = nullptr, float *r_strength = nullptr, float *r_raw_strength = nullptr) const;

const OrderedHashMap<StringName, Action> &get_action_map() const;
void load_from_project_settings();
Expand Down