Allow checking for exact matches with Action events.

Added additional param to action related methods to test for exactness.
If "p_exact_match" is true, then the action will only be "matched" if the provided input event *exactly* matches with the action event.

Before:
* Action Event = KEY_S
* Input Event = KEY_CONTROL + KEY_S
* Is Action Pressed = True

Now:
You can still do the above, however you can optionally check that the input is exactly what the action event is:
* Action Event = KEY_S
* Input Event = KEY_CONTROL + KEY_S
* p_exact_match = True
* Is Action Pressed = False
* If the Input Event was only KEY_S, then the result would be true.

Usage:

```gdscript
Input.is_action_pressed(action_name: String, exact_match: bool)
Input.is_action_pressed("my_action", true)

InputMap.event_is_action(p_event, "my_action", true)

func _input(event: InputEvent):
  event.is_action_pressed("my_action", false, true) # false = "allow_echo", true = "exact_match"
  event.is_action("my_action", true)
```

Co-authored-by: Eric M <itsjusteza@gmail.com>
This commit is contained in:
EricEzaM
2020-12-14 00:22:42 +10:00
committed by Raul Santos
parent 7075bb6129
commit 0e5c6e0d55
11 changed files with 106 additions and 56 deletions

View File

@ -90,15 +90,15 @@ bool InputDefault::is_joy_button_pressed(int p_device, int p_button) const {
return joy_buttons_pressed.has(_combine_device(p_button, p_device));
}
bool InputDefault::is_action_pressed(const StringName &p_action) const {
bool InputDefault::is_action_pressed(const StringName &p_action, bool p_exact) const {
#ifdef DEBUG_ENABLED
bool has_action = InputMap::get_singleton()->has_action(p_action);
ERR_FAIL_COND_V_MSG(!has_action, false, "Request for nonexistent InputMap action '" + String(p_action) + "'.");
#endif
return action_state.has(p_action) && action_state[p_action].pressed;
return action_state.has(p_action) && action_state[p_action].pressed && (p_exact ? action_state[p_action].exact : true);
}
bool InputDefault::is_action_just_pressed(const StringName &p_action) const {
bool InputDefault::is_action_just_pressed(const StringName &p_action, bool p_exact) const {
#ifdef DEBUG_ENABLED
bool has_action = InputMap::get_singleton()->has_action(p_action);
ERR_FAIL_COND_V_MSG(!has_action, false, "Request for nonexistent InputMap action '" + String(p_action) + "'.");
@ -108,6 +108,10 @@ bool InputDefault::is_action_just_pressed(const StringName &p_action) const {
return false;
}
if (p_exact && E->get().exact == false) {
return false;
}
if (Engine::get_singleton()->is_in_physics_frame()) {
return E->get().pressed && E->get().physics_frame == Engine::get_singleton()->get_physics_frames();
} else {
@ -115,7 +119,7 @@ bool InputDefault::is_action_just_pressed(const StringName &p_action) const {
}
}
bool InputDefault::is_action_just_released(const StringName &p_action) const {
bool InputDefault::is_action_just_released(const StringName &p_action, bool p_exact) const {
#ifdef DEBUG_ENABLED
bool has_action = InputMap::get_singleton()->has_action(p_action);
ERR_FAIL_COND_V_MSG(!has_action, false, "Request for nonexistent InputMap action '" + String(p_action) + "'.");
@ -125,6 +129,10 @@ bool InputDefault::is_action_just_released(const StringName &p_action) const {
return false;
}
if (p_exact && E->get().exact == false) {
return false;
}
if (Engine::get_singleton()->is_in_physics_frame()) {
return !E->get().pressed && E->get().physics_frame == Engine::get_singleton()->get_physics_frames();
} else {
@ -132,7 +140,7 @@ bool InputDefault::is_action_just_released(const StringName &p_action) const {
}
}
float InputDefault::get_action_strength(const StringName &p_action) const {
float InputDefault::get_action_strength(const StringName &p_action, bool p_exact) const {
#ifdef DEBUG_ENABLED
bool has_action = InputMap::get_singleton()->has_action(p_action);
ERR_FAIL_COND_V_MSG(!has_action, false, "Request for nonexistent InputMap action '" + String(p_action) + "'.");
@ -142,10 +150,14 @@ float InputDefault::get_action_strength(const StringName &p_action) const {
return 0.0f;
}
if (p_exact && E->get().exact == false) {
return 0.0f;
}
return E->get().strength;
}
float InputDefault::get_action_raw_strength(const StringName &p_action) const {
float InputDefault::get_action_raw_strength(const StringName &p_action, bool p_exact) const {
#ifdef DEBUG_ENABLED
bool has_action = InputMap::get_singleton()->has_action(p_action);
ERR_FAIL_COND_V_MSG(!has_action, false, "Request for nonexistent InputMap action '" + String(p_action) + "'.");
@ -155,6 +167,10 @@ float InputDefault::get_action_raw_strength(const StringName &p_action) const {
return 0.0f;
}
if (p_exact && E->get().exact == false) {
return 0.0f;
}
return E->get().raw_strength;
}
@ -462,14 +478,15 @@ void InputDefault::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool
for (const Map<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())) {
// Save the action's state
if (!p_event->is_echo() && is_action_pressed(E->key()) != p_event->is_action_pressed(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());
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());