diff --git a/doc/classes/EditorSettings.xml b/doc/classes/EditorSettings.xml
index 4bfa4a5702..72714e3813 100644
--- a/doc/classes/EditorSettings.xml
+++ b/doc/classes/EditorSettings.xml
@@ -69,6 +69,33 @@
[/codeblocks]
+
+
+
+
+
+ Adds a [param shortcut] whose path is specified by [param path].
+ The [param path] determines how the shortcut is organized and displayed in the editor's shortcut settings. The path format affects the display as follows:
+ - [code]"name"[/code] (no slash): Creates a category named [code]name[/code] with the shortcut displayed as [code]name[/code].
+ - [code]"category/name"[/code] (single slash): Displays as [code]name[/code] in the [code]category[/code] section.
+ - [code]"category/name/extra"[/code] (multiple slashes): Extra path components are ignored, so this behaves the same as [code]"category/name"[/code].
+ [b]Note:[/b] Shortcuts are only saved to the editor settings if they differ from their original/default state. This means empty shortcuts that were originally empty will not persist between editor sessions and must be re-added. If a shortcut with the same [param path] already exists, this method will update it with the new [param shortcut] instead of creating a duplicate.
+ [codeblock]
+ # Add a custom shortcut for a plugin action.
+ var my_shortcut = Shortcut.new()
+ var input_event = InputEventKey.new()
+ input_event.keycode = KEY_F5
+ input_event.ctrl_pressed = true
+ my_shortcut.events.append(input_event)
+
+ # This will appear under the "My Plugin" category as "Reload Data".
+ EditorInterface.get_editor_settings().add_shortcut("my_plugin/reload_data", my_shortcut)
+
+ # This will appear under the "Test Action" category as "Test Action".
+ EditorInterface.get_editor_settings().add_shortcut("test_action", my_shortcut)
+ [/codeblock]
+
+
@@ -117,6 +144,19 @@
Returns the value of the setting specified by [param name]. This is equivalent to using [method Object.get] on the EditorSettings instance.
+
+
+
+
+ Returns the shortcut specified by [param path]. Tries to find a built-in action if no shortcut with the provided path is found in the shortcut list. If found, adds it to the list and returns it, otherwise returns [code]null[/code].
+
+
+
+
+
+ Returns the list of stored shortcut paths.
+
+
@@ -124,6 +164,21 @@
Returns [code]true[/code] if the setting specified by [param name] exists, [code]false[/code] otherwise.
+
+
+
+
+ Returns [code]true[/code] if the shortcut specified by [param path] exists, [code]false[/code] otherwise.
+
+
+
+
+
+
+
+ Returns [code]true[/code] if the shortcut specified by [param path] matches the event specified by [param event], [code]false[/code] otherwise.
+
+
@@ -131,6 +186,13 @@
Marks the passed editor setting as being changed, see [method get_changed_settings]. Only settings which exist (see [method has_setting]) will be accepted.
+
+
+
+
+ Removes the shortcut specified by [param path].
+
+
diff --git a/editor/settings/editor_settings.cpp b/editor/settings/editor_settings.cpp
index 6175cc5703..2f2aad9c61 100644
--- a/editor/settings/editor_settings.cpp
+++ b/editor/settings/editor_settings.cpp
@@ -1937,24 +1937,54 @@ float EditorSettings::get_auto_display_scale() {
// Shortcuts
-void EditorSettings::_add_shortcut_default(const String &p_name, const Ref &p_shortcut) {
- shortcuts[p_name] = p_shortcut;
+void EditorSettings::_add_shortcut_default(const String &p_path, const Ref &p_shortcut) {
+ shortcuts[p_path] = p_shortcut;
}
-void EditorSettings::add_shortcut(const String &p_name, const Ref &p_shortcut) {
- shortcuts[p_name] = p_shortcut;
- shortcuts[p_name]->set_meta("customized", true);
+void EditorSettings::add_shortcut(const String &p_path, const Ref &p_shortcut) {
+ Array use_events = p_shortcut->get_events();
+ if (shortcuts.has(p_path)) {
+ Ref existing = shortcuts.get(p_path);
+ if (!existing->has_meta("original")) {
+ // Loaded from editor settings, but plugin not loaded yet.
+ // Keep the events from editor settings but still override the shortcut in the shortcuts map
+ use_events = existing->get_events();
+ } else if (!Shortcut::is_event_array_equal(existing->get_events(), existing->get_meta("original"))) {
+ // Shortcut exists and is customized - don't override with default.
+ return;
+ }
+ }
+
+ p_shortcut->set_meta("original", p_shortcut->get_events());
+ p_shortcut->set_events(use_events);
+ if (p_shortcut->get_name().is_empty()) {
+ String shortcut_name = p_path.get_slicec('/', 1);
+ if (shortcut_name.is_empty()) {
+ shortcut_name = p_path;
+ }
+ p_shortcut->set_name(shortcut_name);
+ }
+ shortcuts[p_path] = p_shortcut;
+ shortcuts[p_path]->set_meta("customized", true);
}
-bool EditorSettings::is_shortcut(const String &p_name, const Ref &p_event) const {
- HashMap>::ConstIterator E = shortcuts.find(p_name);
- ERR_FAIL_COND_V_MSG(!E, false, "Unknown Shortcut: " + p_name + ".");
+void EditorSettings::remove_shortcut(const String &p_path) {
+ shortcuts.erase(p_path);
+}
+
+bool EditorSettings::is_shortcut(const String &p_path, const Ref &p_event) const {
+ HashMap>::ConstIterator E = shortcuts.find(p_path);
+ ERR_FAIL_COND_V_MSG(!E, false, "Unknown Shortcut: " + p_path + ".");
return E->value->matches_event(p_event);
}
-Ref EditorSettings::get_shortcut(const String &p_name) const {
- HashMap>::ConstIterator SC = shortcuts.find(p_name);
+bool EditorSettings::has_shortcut(const String &p_path) const {
+ return get_shortcut(p_path).is_valid();
+}
+
+Ref EditorSettings::get_shortcut(const String &p_path) const {
+ HashMap>::ConstIterator SC = shortcuts.find(p_path);
if (SC) {
return SC->value;
}
@@ -1963,32 +1993,42 @@ Ref EditorSettings::get_shortcut(const String &p_name) const {
// Use the first item in the action list for the shortcut event, since a shortcut can only have 1 linked event.
Ref sc;
- HashMap>>::ConstIterator builtin_override = builtin_action_overrides.find(p_name);
+ HashMap>>::ConstIterator builtin_override = builtin_action_overrides.find(p_path);
if (builtin_override) {
sc.instantiate();
sc->set_events_list(&builtin_override->value);
- sc->set_name(InputMap::get_singleton()->get_builtin_display_name(p_name));
+ sc->set_name(InputMap::get_singleton()->get_builtin_display_name(p_path));
}
// If there was no override, check the default builtins to see if it has an InputEvent for the provided name.
if (sc.is_null()) {
- HashMap>>::ConstIterator builtin_default = InputMap::get_singleton()->get_builtins_with_feature_overrides_applied().find(p_name);
+ HashMap>>::ConstIterator builtin_default = InputMap::get_singleton()->get_builtins_with_feature_overrides_applied().find(p_path);
if (builtin_default) {
sc.instantiate();
sc->set_events_list(&builtin_default->value);
- sc->set_name(InputMap::get_singleton()->get_builtin_display_name(p_name));
+ sc->set_name(InputMap::get_singleton()->get_builtin_display_name(p_path));
}
}
if (sc.is_valid()) {
// Add the shortcut to the list.
- shortcuts[p_name] = sc;
+ shortcuts[p_path] = sc;
return sc;
}
return Ref();
}
+Vector EditorSettings::_get_shortcut_list() {
+ List shortcut_list;
+ get_shortcut_list(&shortcut_list);
+ Vector ret;
+ for (const String &shortcut : shortcut_list) {
+ ret.push_back(shortcut);
+ }
+ return ret;
+}
+
void EditorSettings::get_shortcut_list(List *r_shortcuts) {
for (const KeyValue> &E : shortcuts) {
r_shortcuts->push_back(E.key);
@@ -2241,6 +2281,13 @@ void EditorSettings::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_builtin_action_override", "name", "actions_list"), &EditorSettings::set_builtin_action_override);
+ ClassDB::bind_method(D_METHOD("add_shortcut", "path", "shortcut"), &EditorSettings::add_shortcut);
+ ClassDB::bind_method(D_METHOD("remove_shortcut", "path"), &EditorSettings::remove_shortcut);
+ ClassDB::bind_method(D_METHOD("is_shortcut", "path", "event"), &EditorSettings::is_shortcut);
+ ClassDB::bind_method(D_METHOD("has_shortcut", "path"), &EditorSettings::has_shortcut);
+ ClassDB::bind_method(D_METHOD("get_shortcut", "path"), &EditorSettings::get_shortcut);
+ ClassDB::bind_method(D_METHOD("get_shortcut_list"), &EditorSettings::_get_shortcut_list);
+
ClassDB::bind_method(D_METHOD("check_changed_settings_in_group", "setting_prefix"), &EditorSettings::check_changed_settings_in_group);
ClassDB::bind_method(D_METHOD("get_changed_settings"), &EditorSettings::get_changed_settings);
ClassDB::bind_method(D_METHOD("mark_setting_changed", "setting"), &EditorSettings::mark_setting_changed);
diff --git a/editor/settings/editor_settings.h b/editor/settings/editor_settings.h
index e58eeec586..74d41a9beb 100644
--- a/editor/settings/editor_settings.h
+++ b/editor/settings/editor_settings.h
@@ -128,6 +128,9 @@ private:
void _remove_deprecated_settings();
#endif
+ // Bind helpers.
+ Vector _get_shortcut_list();
+
protected:
static void _bind_methods();
@@ -193,10 +196,12 @@ public:
String get_editor_layouts_config() const;
static float get_auto_display_scale();
- void _add_shortcut_default(const String &p_name, const Ref &p_shortcut);
- void add_shortcut(const String &p_name, const Ref &p_shortcut);
- bool is_shortcut(const String &p_name, const Ref &p_event) const;
- Ref get_shortcut(const String &p_name) const;
+ void _add_shortcut_default(const String &p_path, const Ref &p_shortcut);
+ void add_shortcut(const String &p_path, const Ref &p_shortcut);
+ void remove_shortcut(const String &p_path);
+ bool is_shortcut(const String &p_path, const Ref &p_event) const;
+ bool has_shortcut(const String &p_path) const;
+ Ref get_shortcut(const String &p_path) const;
void get_shortcut_list(List *r_shortcuts);
void set_builtin_action_override(const String &p_name, const TypedArray &p_events);