Skip to content

Commit

Permalink
Merge pull request godotengine#45902 from Calinou/inputmap-nonexisten…
Browse files Browse the repository at this point in the history
…t-suggestions-3.2

Print suggestions when requesting a nonexistent InputMap action (3.2)
  • Loading branch information
akien-mga authored Feb 12, 2021
2 parents 9918fd7 + 28127ce commit 83e4e4d
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 10 deletions.
50 changes: 40 additions & 10 deletions core/input_map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,38 @@ void InputMap::_bind_methods() {
ClassDB::bind_method(D_METHOD("load_from_globals"), &InputMap::load_from_globals);
}

/**
* Returns an nonexistent action error message with a suggestion of the closest
* matching action name (if possible).
*/
String InputMap::_suggest_actions(const StringName &p_action) const {

List<StringName> actions = get_actions();
StringName closest_action;
float closest_similarity = 0.0;

// Find the most action with the most similar name.
for (List<StringName>::Element *E = actions.front(); E; E = E->next()) {
const float similarity = String(E->get()).similarity(p_action);

if (similarity > closest_similarity) {
closest_action = E->get();
closest_similarity = similarity;
}
}

String error_message = vformat("The InputMap action \"%s\" doesn't exist.", p_action);

if (closest_similarity >= 0.4) {
// Only include a suggestion in the error message if it's similar enough.
error_message += vformat(" Did you mean \"%s\"?", closest_action);
}
return error_message;
}

void InputMap::add_action(const StringName &p_action, float p_deadzone) {

ERR_FAIL_COND_MSG(input_map.has(p_action), "InputMap already has action '" + String(p_action) + "'.");
ERR_FAIL_COND_MSG(input_map.has(p_action), "InputMap already has action \"" + String(p_action) + "\".");
input_map[p_action] = Action();
static int last_id = 1;
input_map[p_action].id = last_id;
Expand All @@ -67,7 +96,8 @@ void InputMap::add_action(const StringName &p_action, float p_deadzone) {

void InputMap::erase_action(const StringName &p_action) {

ERR_FAIL_COND_MSG(!input_map.has(p_action), "Request for nonexistent InputMap action '" + String(p_action) + "'.");
ERR_FAIL_COND_MSG(!input_map.has(p_action), _suggest_actions(p_action));

input_map.erase(p_action);
}

Expand Down Expand Up @@ -128,15 +158,16 @@ bool InputMap::has_action(const StringName &p_action) const {

void InputMap::action_set_deadzone(const StringName &p_action, float p_deadzone) {

ERR_FAIL_COND_MSG(!input_map.has(p_action), "Request for nonexistent InputMap action '" + String(p_action) + "'.");
ERR_FAIL_COND_MSG(!input_map.has(p_action), _suggest_actions(p_action));

input_map[p_action].deadzone = p_deadzone;
}

void InputMap::action_add_event(const StringName &p_action, const Ref<InputEvent> &p_event) {

ERR_FAIL_COND_MSG(p_event.is_null(), "It's not a reference to a valid InputEvent object.");
ERR_FAIL_COND_MSG(!input_map.has(p_action), "Request for nonexistent InputMap action '" + String(p_action) + "'.");
ERR_FAIL_COND_MSG(!input_map.has(p_action), _suggest_actions(p_action));

if (_find_event(input_map[p_action], p_event))
return; //already gots

Expand All @@ -145,13 +176,14 @@ void InputMap::action_add_event(const StringName &p_action, const Ref<InputEvent

bool InputMap::action_has_event(const StringName &p_action, const Ref<InputEvent> &p_event) {

ERR_FAIL_COND_V_MSG(!input_map.has(p_action), false, "Request for nonexistent InputMap action '" + String(p_action) + "'.");
ERR_FAIL_COND_V_MSG(!input_map.has(p_action), false, _suggest_actions(p_action));

return (_find_event(input_map[p_action], p_event) != NULL);
}

void InputMap::action_erase_event(const StringName &p_action, const Ref<InputEvent> &p_event) {

ERR_FAIL_COND_MSG(!input_map.has(p_action), "Request for nonexistent InputMap action '" + String(p_action) + "'.");
ERR_FAIL_COND_MSG(!input_map.has(p_action), _suggest_actions(p_action));

List<Ref<InputEvent> >::Element *E = _find_event(input_map[p_action], p_event);
if (E) {
Expand All @@ -164,7 +196,7 @@ void InputMap::action_erase_event(const StringName &p_action, const Ref<InputEve

void InputMap::action_erase_events(const StringName &p_action) {

ERR_FAIL_COND_MSG(!input_map.has(p_action), "Request for nonexistent InputMap action '" + String(p_action) + "'.");
ERR_FAIL_COND_MSG(!input_map.has(p_action), _suggest_actions(p_action));

input_map[p_action].inputs.clear();
}
Expand Down Expand Up @@ -198,7 +230,7 @@ bool InputMap::event_is_action(const Ref<InputEvent> &p_event, const StringName

bool InputMap::event_get_action_status(const Ref<InputEvent> &p_event, const StringName &p_action, bool *p_pressed, float *p_strength) const {
Map<StringName, Action>::Element *E = input_map.find(p_action);
ERR_FAIL_COND_V_MSG(!E, false, "Request for nonexistent InputMap action '" + String(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()) {
Expand Down Expand Up @@ -333,8 +365,6 @@ void InputMap::load_default() {
key.instance();
key->set_scancode(KEY_END);
action_add_event("ui_end", key);

//set("display/window/handheld/orientation", "landscape");
}

InputMap::InputMap() {
Expand Down
1 change: 1 addition & 0 deletions core/input_map.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ class InputMap : public Object {

Array _get_action_list(const StringName &p_action);
Array _get_actions();
String _suggest_actions(const StringName &p_action) const;

protected:
static void _bind_methods();
Expand Down

0 comments on commit 83e4e4d

Please sign in to comment.