-
-
Notifications
You must be signed in to change notification settings - Fork 97
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
Allow plugins to register shortcuts in the editor menu #2024
Comments
How could As for registering shortcuts, I find this useful. Afaik, there is no way to register shortcuts in the editor yet :( |
It's already there?! :-X I suspected the shortcuts could be there, but couldn't find anything; but then I did not expect that settings would be there, if the shortcuts are not. So, we already have the settings - the shortcuts could be implemented in a similar way! |
register_shortcut(shortcut: InputEventKey, obj:Object, method:String)`
register_shortcut(shortcut: InputEventKey, obj:Object, method:String, args:Array = [])`
EditorShortcuts get_editor_interface().get_editor_shortcuts() |
Currently, I have to do it like this: # CTRL + K
var key = InputEventKey.new()
key.scancode = KEY_K
key.control = true
var sh = ShortCut.new()
sh.shortcut = key
self.shortcut = sh I don't really understand why do we need a Now that I think about it, there is a simple way to register shortcuts for anything that can currently have shortcuts (Buttons and PopupMenu items). var sh = ShortCut.new()
sh.shortcut = key
sh.description = "Commit" # If this is not set, the shortcut is not registered in the editor
self.shortcut = sh This is actually what I originally wanted, so the "I have a problem that needs a solution" part ends here. Now, it would be pretty cool to be able to register a shortcut that calls any method using the existing signal system. However:
|
I would really appreciate a way to add a shortcut option to something like the InputMap so I can allow users of my plugin tools to set their own shortcut key combinations. Currently I've set one on a button but it requires users to mess with the internals of the tools I give them which can lead to its own obvious problems. |
Btw actions can be added to
|
Hm, indeed, I forgot that we have InputMap for games. But it is unsuitable for tool scripts for the above reasons. So... would it make more sense to modify the behavior of InputMap for addons, or is that too unintuitive, and tools are better off just registering shortcuts?.. |
I have revised my views (see my first comment). Here are my thoughts at the moment:
(same as implemented in Shortcuts and InputMap)
I also find it useful to have an API for working with
void PluginShortcuts.add_shortcut (plugin_id, action_name: String, shortcut: Shortcut) Not sure if there is a more reliable and convenient plugin ID than the plugin name or plugin path. Also here I have doubts which type of shortcut argument would be preferable:
void PluginShortcuts.remove_action (plugin_id, action_name: String, shortcut: Shortcut)
Shortcut PluginShortcuts.get_shortcut (plugin_id, action_name: String)
void PluginShortcuts.set_shortcut (plugin_id, action_name, shortcut)
void PluginShortcuts.set_default (plugin_id, action_name, shortcut)
Shortcut PluginShortcuts.get_default (plugin_id, action_name)
PoolStringArray PluginShortcuts.get_actions (plugin_id)
I think it is wiser to have these settings at the project level (and therefore in
|
If we get #831 , "editor addons" will be "potentially for all projects". But there are also "normal addons", which are a part of your project - like what we have now. Since they are a part of your project, their shortcuts should be stored in the project, but for global addons, it's certainly better to store them in the editor settings. I guess that will come with their implementation.
I think the plugin name is good enough - I would even suggest that you don't have to pass it; instead, it's automatically derived from your plugin. You should probably not be able to assign a shortcut for a different plugin, and this way, the user can always be sure it's a setting from this plugin, even if they fork it under a different name. I like this implementation - I think it's even better than what I had in mind. Additionally, since we also have "shortcuts" for Buttons and PopupMenus that work differently, maybe giving them a capability to easily auto-register those shortcuts would be an easy-to-implement nice-to-have?.. |
@CodeDarigan This is an option but it gives UI with many settings instead of (more convenient) "Press Any Key" popup. You need to type scancode number which is inconvenient. Another sad thing is that plugin developers will create different |
My current solution:
func _input(event: InputEvent) -> void:
if shortcut and shortcut.matches_event(event):
print("wowie") # Do whatever you want here
var shortcut := _get_or_set_shortcut()
const PLUGIN_ID := "my_plugin"
const PLUGIN_PATH := "plugins/"+PLUGIN_ID
static func _get_or_set_shortcut() -> Shortcut:
var key := PLUGIN_PATH + "/shortcut"
if not ProjectSettings.has_setting(key):
var default_shortcut := preload("./default_shortcut.tres")
var property_info := {
"name": key,
"type": TYPE_OBJECT,
"hint": PROPERTY_HINT_RESOURCE_TYPE,
"hint_string": "Shortcut"
}
ProjectSettings.set_setting(key, default_shortcut)
ProjectSettings.add_property_info(property_info)
var loaded_shortcut: Shortcut = ProjectSettings.get_setting(key)
return loaded_shortcut note: make sure to tick the "advanced settings" switch of the project settings dialog. This solution, while not perfect, allows consumers of the plugin to change the key easily by directly editing the It can also be adapted to use multiple shortcuts easily if one wanted to. Edit: Spoken too early, in Beta 11 (and 9), doing this makes the project crash with the message:
If I edit In the meantime, here's a workaround to the workaround: static func _get_or_set_shortcut() -> Shortcut:
var key := PLUGIN_PATH + "/shortcut"
if not ProjectSettings.has_setting(key):
var default_shortcut := preload("./default_shortcut.tres")
var path := default_shortcut.resource_path
var property_info := {
"name": key,
"type": TYPE_STRING,
"hint": PROPERTY_HINT_FILE,
"hint_string": "*.tres"
}
# store path instead of resource itself
ProjectSettings.set_setting(key, path)
ProjectSettings.add_property_info(property_info)
var shortcut_path: String = ProjectSettings.get_setting(key)
if shortcut_path == "":
return null
var loaded_shortcut: Shortcut = load(shortcut_path)
return loaded_shortcut |
I've been playing around with your solution, and I don't know if what you found was indeed a bug or you just forgot to deactivate the plugin. Tested with Godot 4, 4.2.2, and 4.3.beta2 and worked in all of them: # You can create as many shortcuts as you wish
var shortcut: Shortcut
# Path the user will have to do on Project -> Project Settings -> ...
const PLUGIN_PATH := "plugins/my_plugin/shortcut"
# Remember to create the Shortcut Resource and name it correctly bellow
var shortcut_res: Shortcut = preload("res://addons/myplugin/default_shortcut.tres")
func _enter_tree():
# On startup or activation, set shortcut
shortcut = set_shortcut(PLUGIN_PATH, shortcut_res)
func _exit_tree():
# On exit or deactivation, remove shortcut and ProjectSetting path
shortcut = null
ProjectSettings.clear(PLUGIN_PATH)
ProjectSettings.save()
# Handles shortcuts
func _shortcut_input(event: InputEvent) -> void:
# Will only be called once when pressed
if not event.is_pressed() or event.is_echo(): return
if shortcut.matches_event(event):
print("wowie") # Do whatever you want here
func set_shortcut(project_setting_path: String, resource: Shortcut) -> Shortcut:
ProjectSettings.set_setting(PLUGIN_PATH, resource)
return resource It also works with EditorSettings instead of ProjectSetting, but you will need to get the editor: In the end, this is the final result: It is way nicer than the user go to your code or search your files to change a shortcut, but it would still be better if we could have access to Editor Settings -> Shortcuts tab or add something similar on our tab to be cleaner Edit: to be fair, if you try to open two instances of the project, since the code is not yet removed from project.godot, the resource_loader will still bug trying to infer what type of resource it is. Have @Xananax opened a bug reported about it? It doesn't bug if you use Editor Setting instead of Project Setting though |
At a high level a lot of the friendly tools for creating a shortcut that are used within the godot c++ sources are not exposed to gdscript or gdextension. An equivalent of For anyone trying to use the workaround of adding a EditorSettings setting containing a Shortcut, the following code does it. It's the equivalent of everything called by Ref<Shortcut>
TestNodeEditorPlugin::editor_shortcut(const String &p_path, const String &p_name, Key p_keycode, bool p_physical) {
Ref<EditorSettings> editor_settings = get_editor_interface()->get_editor_settings();
Array events;
Ref<InputEventKey> input_event_key;
if (p_keycode != KEY_NONE) {
input_event_key.instantiate();
if (p_physical) {
input_event_key->set_physical_keycode((Key)(p_keycode & KEY_CODE_MASK));
} else {
input_event_key->set_keycode((Key)(p_keycode & KEY_CODE_MASK));
}
if ((p_keycode & KEY_MASK_SHIFT) != 0) {
input_event_key->set_shift_pressed(true);
}
if ((p_keycode & KEY_MASK_ALT) != 0) {
input_event_key->set_alt_pressed(true);
}
if ((p_keycode & KEY_MASK_CMD_OR_CTRL) != 0) {
input_event_key->set_command_or_control_autoremap(true);
} else if ((p_keycode & KEY_MASK_CTRL) != 0) {
input_event_key->set_ctrl_pressed(true);
} else if ((p_keycode & KEY_MASK_META) != 0) {
input_event_key->set_meta_pressed(true);
}
events.push_back(input_event_key);
}
Ref<Shortcut> shortcut = editor_settings->get_setting(p_path);
if (shortcut.is_valid()) {
shortcut->set_name(p_name);
shortcut->set_meta("original", events.duplicate(true));
} else {
shortcut.instantiate();
shortcut->set_name(p_name);
shortcut->set_events(events);
shortcut->set_meta("original", events.duplicate(true));
editor_settings->set_setting(p_path, shortcut);
}
return shortcut;
}
TestNodeEditorPlugin::TestNodeEditorPlugin() {
editor_shortcut("test_node/test_setting", "TestNode Test Setting", (Key)(KEY_C | godot::KEY_CTRL), true);
} |
Describe the project you are working on
An editor plugin (a better Git integration attempt).
Describe the problem or limitation you are having in your project
I have a shortcut that opens the plugin window (and probably other shortcuts in the future). Currently, I have to either hard-code it, or create a Settings dialog with all the interface to customize the shortcut.
Describe the feature / enhancement and how it helps to overcome the problem or limitation
Being able to register at least shortcuts and maybe also settings would make them easier to implement, and also easier for the user to find all shortcuts in one place. We already have a "Shortcuts" menu and a "Settings" in the editor; we should not be having separate "Shortcuts" and "Settings" menus for each plugin.
Also, if we get #831 that helps make addons "a part of the editor", then this would greatly improve usability and the experience that addons really feel like an optional part of the editor.
Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams
We could have
get_editor_interface().register_shortcut(myshortcut, "self.show")
that adds a new shortcut to the list of editor shortcuts under a separate "My plugin" group.The same goes for settings. We could have
get_editor_interface().register_setting("Auto-add new files", TYPE_BOOL, self.autoadd)
to register the plugin settings, which would then be added to the editor settings in a "My plugin" group.If this enhancement will not be used often, can it be worked around with a few lines of script?
We can create "Settings" dialogs in each plugin, and find a way to let the user find them easily, while the user is not even intuitively aware that there are more settings than in the editor settings menu. Then we have to code a shortcut picker, which has no way to detect clashes with other registered shortcuts. This is more then "a few lines", but it's possible.
Is there a reason why this should be core and not an add-on in the asset library?
If such things were possible to implement with an addon, this wouldn't have been a problem in the first place. :)
The text was updated successfully, but these errors were encountered: