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

Print suggestions when requesting a nonexistent InputMap action (3.2) #45902

Merged
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
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