Skip to content

Commit ce6c3c5

Browse files
committed
Merge pull request godotengine#100556 from KoBeWi/unlimited_contextizer
Add more menus support to EditorContextMenuPlugin
2 parents 7bbdcc8 + ba54a28 commit ce6c3c5

File tree

7 files changed

+93
-3
lines changed

7 files changed

+93
-3
lines changed

doc/classes/EditorContextMenuPlugin.xml

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,11 +85,30 @@
8585
<constant name="CONTEXT_SLOT_FILESYSTEM" value="1" enum="ContextMenuSlot">
8686
Context menu of FileSystem dock. [method _popup_menu] and option callback will be called with list of paths of the currently selected files.
8787
</constant>
88+
<constant name="CONTEXT_SLOT_SCRIPT_EDITOR" value="2" enum="ContextMenuSlot">
89+
Context menu of Script editor's script tabs. [method _popup_menu] will be called with the path to the currently edited script, while option callback will receive reference to that script.
90+
</constant>
8891
<constant name="CONTEXT_SLOT_FILESYSTEM_CREATE" value="3" enum="ContextMenuSlot">
8992
The "Create..." submenu of FileSystem dock's context menu. [method _popup_menu] and option callback will be called with list of paths of the currently selected files.
9093
</constant>
91-
<constant name="CONTEXT_SLOT_SCRIPT_EDITOR" value="2" enum="ContextMenuSlot">
92-
Context menu of Scene dock. [method _popup_menu] will be called with the path to the currently edited script, while option callback will receive reference to that script.
94+
<constant name="CONTEXT_SLOT_SCRIPT_EDITOR_CODE" value="4" enum="ContextMenuSlot">
95+
Context menu of Script editor's code editor. [method _popup_menu] will be called with the path to the [CodeEdit] node. You can fetch it using this code:
96+
[codeblock]
97+
func _popup_menu(paths):
98+
var code_edit = Engine.get_main_loop().root.get_node(paths[0]);
99+
[/codeblock]
100+
The option callback will receive reference to that node. You can use [CodeEdit] methods to perform symbol lookups etc.
101+
</constant>
102+
<constant name="CONTEXT_SLOT_SCENE_TABS" value="5" enum="ContextMenuSlot">
103+
Context menu of scene tabs. [method _popup_menu] will be called with the path of the clicked scene, or empty [PackedStringArray] if the menu was opened on empty space. The option callback will receive the path of the clicked scene, or empty [String] if none was clicked.
104+
</constant>
105+
<constant name="CONTEXT_SLOT_2D_EDITOR" value="6" enum="ContextMenuSlot">
106+
Context menu of 2D editor's basic right-click menu. [method _popup_menu] will be called with paths to all [CanvasItem] nodes under the cursor. You can fetch them using this code:
107+
[codeblock]
108+
func _popup_menu(paths):
109+
var canvas_item = Engine.get_main_loop().root.get_node(paths[0]); # Replace 0 with the desired index.
110+
[/codeblock]
111+
The paths array is empty if there weren't any nodes under cursor. The option callback will receive a typed array of [CanvasItem] nodes.
93112
</constant>
94113
</constants>
95114
</class>

editor/gui/editor_scene_tabs.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include "editor/editor_undo_redo_manager.h"
3939
#include "editor/gui/editor_run_bar.h"
4040
#include "editor/inspector_dock.h"
41+
#include "editor/plugins/editor_context_menu_plugin.h"
4142
#include "editor/themes/editor_scale.h"
4243
#include "scene/gui/box_container.h"
4344
#include "scene/gui/button.h"
@@ -205,7 +206,13 @@ void EditorSceneTabs::_update_context_menu() {
205206
scene_tabs_context_menu->add_item(TTR("Close Tabs to the Right"), EditorNode::FILE_CLOSE_RIGHT);
206207
_disable_menu_option_if(EditorNode::FILE_CLOSE_RIGHT, EditorNode::get_editor_data().get_edited_scene_count() == tab_id + 1);
207208
scene_tabs_context_menu->add_item(TTR("Close All Tabs"), EditorNode::FILE_CLOSE_ALL);
209+
210+
const PackedStringArray paths = { EditorNode::get_editor_data().get_scene_path(tab_id) };
211+
EditorContextMenuPluginManager::get_singleton()->add_options_from_plugins(scene_tabs_context_menu, EditorContextMenuPlugin::CONTEXT_SLOT_SCENE_TABS, paths);
212+
} else {
213+
EditorContextMenuPluginManager::get_singleton()->add_options_from_plugins(scene_tabs_context_menu, EditorContextMenuPlugin::CONTEXT_SLOT_SCENE_TABS, {});
208214
}
215+
last_hovered_tab = tab_id;
209216
}
210217

211218
void EditorSceneTabs::_disable_menu_option_if(int p_option, bool p_condition) {
@@ -214,6 +221,12 @@ void EditorSceneTabs::_disable_menu_option_if(int p_option, bool p_condition) {
214221
}
215222
}
216223

224+
void EditorSceneTabs::_custom_menu_option(int p_option) {
225+
if (p_option >= EditorContextMenuPlugin::BASE_ID) {
226+
EditorContextMenuPluginManager::get_singleton()->activate_custom_option(EditorContextMenuPlugin::CONTEXT_SLOT_SCENE_TABS, p_option, last_hovered_tab >= 0 ? EditorNode::get_editor_data().get_scene_path(last_hovered_tab) : String());
227+
}
228+
}
229+
217230
void EditorSceneTabs::update_scene_tabs() {
218231
static bool menu_initialized = false;
219232
tab_preview_panel->hide();
@@ -420,6 +433,7 @@ EditorSceneTabs::EditorSceneTabs() {
420433
scene_tabs_context_menu = memnew(PopupMenu);
421434
tabbar_container->add_child(scene_tabs_context_menu);
422435
scene_tabs_context_menu->connect(SceneStringName(id_pressed), callable_mp(EditorNode::get_singleton(), &EditorNode::trigger_menu_option).bind(false));
436+
scene_tabs_context_menu->connect(SceneStringName(id_pressed), callable_mp(this, &EditorSceneTabs::_custom_menu_option));
423437

424438
scene_tab_add = memnew(Button);
425439
scene_tab_add->set_flat(true);

editor/gui/editor_scene_tabs.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ class EditorSceneTabs : public MarginContainer {
5757
Panel *tab_preview_panel = nullptr;
5858
TextureRect *tab_preview = nullptr;
5959

60+
int last_hovered_tab = -1;
61+
6062
void _scene_tab_changed(int p_tab);
6163
void _scene_tab_script_edited(int p_tab);
6264
void _scene_tab_closed(int p_tab);
@@ -69,6 +71,7 @@ class EditorSceneTabs : public MarginContainer {
6971
void _reposition_active_tab(int p_to_index);
7072
void _update_context_menu();
7173
void _disable_menu_option_if(int p_option, bool p_condition);
74+
void _custom_menu_option(int p_option);
7275

7376
void _tab_preview_done(const String &p_path, const Ref<Texture2D> &p_preview, const Ref<Texture2D> &p_small_preview, const Variant &p_udata);
7477

editor/plugins/canvas_item_editor_plugin.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
#include "editor/gui/editor_toaster.h"
4444
#include "editor/gui/editor_zoom_widget.h"
4545
#include "editor/plugins/animation_player_editor_plugin.h"
46+
#include "editor/plugins/editor_context_menu_plugin.h"
4647
#include "editor/plugins/script_editor_plugin.h"
4748
#include "editor/scene_tree_dock.h"
4849
#include "editor/themes/editor_scale.h"
@@ -991,6 +992,19 @@ void CanvasItemEditor::_add_node_pressed(int p_result) {
991992
undo_redo->commit_action();
992993
_reset_create_position();
993994
} break;
995+
default: {
996+
if (p_result >= EditorContextMenuPlugin::BASE_ID) {
997+
TypedArray<Node> nodes;
998+
nodes.resize(selection_results.size());
999+
1000+
int i = 0;
1001+
for (const _SelectResult &result : selection_results) {
1002+
nodes[i] = result.item;
1003+
i++;
1004+
}
1005+
EditorContextMenuPluginManager::get_singleton()->activate_custom_option(EditorContextMenuPlugin::CONTEXT_SLOT_2D_EDITOR, p_result, nodes);
1006+
}
1007+
}
9941008
}
9951009
}
9961010

@@ -2461,6 +2475,21 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) {
24612475
}
24622476
}
24632477

2478+
// Context menu plugin receives paths of nodes under cursor. It's a complex operation, so perform it only when necessary.
2479+
if (EditorContextMenuPluginManager::get_singleton()->has_plugins_for_slot(EditorContextMenuPlugin::CONTEXT_SLOT_2D_EDITOR)) {
2480+
selection_results.clear();
2481+
_get_canvas_items_at_pos(transform.affine_inverse().xform(viewport->get_local_mouse_position()), selection_results, true);
2482+
2483+
PackedStringArray paths;
2484+
paths.resize(selection_results.size());
2485+
String *paths_write = paths.ptrw();
2486+
2487+
for (int i = 0; i < paths.size(); i++) {
2488+
paths_write[i] = selection_results[i].item->get_path();
2489+
}
2490+
EditorContextMenuPluginManager::get_singleton()->add_options_from_plugins(add_node_menu, EditorContextMenuPlugin::CONTEXT_SLOT_2D_EDITOR, paths);
2491+
}
2492+
24642493
add_node_menu->reset_size();
24652494
add_node_menu->set_position(viewport->get_screen_transform().xform(b->get_position()));
24662495
add_node_menu->popup();

editor/plugins/editor_context_menu_plugin.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,11 @@ void EditorContextMenuPlugin::_bind_methods() {
8686

8787
BIND_ENUM_CONSTANT(CONTEXT_SLOT_SCENE_TREE);
8888
BIND_ENUM_CONSTANT(CONTEXT_SLOT_FILESYSTEM);
89-
BIND_ENUM_CONSTANT(CONTEXT_SLOT_FILESYSTEM_CREATE);
9089
BIND_ENUM_CONSTANT(CONTEXT_SLOT_SCRIPT_EDITOR);
90+
BIND_ENUM_CONSTANT(CONTEXT_SLOT_FILESYSTEM_CREATE);
91+
BIND_ENUM_CONSTANT(CONTEXT_SLOT_SCRIPT_EDITOR_CODE);
92+
BIND_ENUM_CONSTANT(CONTEXT_SLOT_SCENE_TABS);
93+
BIND_ENUM_CONSTANT(CONTEXT_SLOT_2D_EDITOR);
9194
}
9295

9396
void EditorContextMenuPluginManager::add_plugin(EditorContextMenuPlugin::ContextMenuSlot p_slot, const Ref<EditorContextMenuPlugin> &p_plugin) {
@@ -105,6 +108,15 @@ void EditorContextMenuPluginManager::remove_plugin(const Ref<EditorContextMenuPl
105108
plugin_list.erase(p_plugin);
106109
}
107110

111+
bool EditorContextMenuPluginManager::has_plugins_for_slot(ContextMenuSlot p_slot) {
112+
for (Ref<EditorContextMenuPlugin> &plugin : plugin_list) {
113+
if (plugin->slot == p_slot) {
114+
return true;
115+
}
116+
}
117+
return false;
118+
}
119+
108120
void EditorContextMenuPluginManager::add_options_from_plugins(PopupMenu *p_popup, ContextMenuSlot p_slot, const Vector<String> &p_paths) {
109121
bool separator_added = false;
110122
const int icon_size = p_popup->get_theme_constant(SNAME("class_icon_size"), EditorStringName(Editor));

editor/plugins/editor_context_menu_plugin.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ class EditorContextMenuPlugin : public RefCounted {
5252
CONTEXT_SLOT_FILESYSTEM,
5353
CONTEXT_SLOT_SCRIPT_EDITOR,
5454
CONTEXT_SLOT_FILESYSTEM_CREATE,
55+
CONTEXT_SLOT_SCRIPT_EDITOR_CODE,
56+
CONTEXT_SLOT_SCENE_TABS,
57+
CONTEXT_SLOT_2D_EDITOR,
5558
};
5659
inline static constexpr int BASE_ID = 2000;
5760

@@ -100,6 +103,7 @@ class EditorContextMenuPluginManager : public Object {
100103
void add_plugin(ContextMenuSlot p_slot, const Ref<EditorContextMenuPlugin> &p_plugin);
101104
void remove_plugin(const Ref<EditorContextMenuPlugin> &p_plugin);
102105

106+
bool has_plugins_for_slot(ContextMenuSlot p_slot);
103107
void add_options_from_plugins(PopupMenu *p_popup, ContextMenuSlot p_slot, const Vector<String> &p_paths);
104108
Callable match_custom_shortcut(ContextMenuSlot p_slot, const Ref<InputEvent> &p_event);
105109
bool activate_custom_option(ContextMenuSlot p_slot, int p_option, const Variant &p_arg);

editor/plugins/script_text_editor.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
#include "editor/editor_settings.h"
4242
#include "editor/editor_string_names.h"
4343
#include "editor/gui/editor_toaster.h"
44+
#include "editor/plugins/editor_context_menu_plugin.h"
4445
#include "editor/themes/editor_scale.h"
4546
#include "scene/gui/menu_button.h"
4647
#include "scene/gui/rich_text_label.h"
@@ -1724,6 +1725,11 @@ void ScriptTextEditor::_edit_option(int p_op) {
17241725
_lookup_symbol(text, tx->get_caret_line(0), tx->get_caret_column(0));
17251726
}
17261727
} break;
1728+
default: {
1729+
if (p_op >= EditorContextMenuPlugin::BASE_ID) {
1730+
EditorContextMenuPluginManager::get_singleton()->activate_custom_option(EditorContextMenuPlugin::CONTEXT_SLOT_SCRIPT_EDITOR_CODE, p_op, tx);
1731+
}
1732+
}
17271733
}
17281734
}
17291735

@@ -2313,6 +2319,9 @@ void ScriptTextEditor::_make_context_menu(bool p_selection, bool p_color, bool p
23132319
}
23142320
}
23152321

2322+
const PackedStringArray paths = { code_editor->get_text_editor()->get_path() };
2323+
EditorContextMenuPluginManager::get_singleton()->add_options_from_plugins(context_menu, EditorContextMenuPlugin::CONTEXT_SLOT_SCRIPT_EDITOR_CODE, paths);
2324+
23162325
const CodeEdit *tx = code_editor->get_text_editor();
23172326
context_menu->set_item_disabled(context_menu->get_item_index(EDIT_UNDO), !tx->has_undo());
23182327
context_menu->set_item_disabled(context_menu->get_item_index(EDIT_REDO), !tx->has_redo());

0 commit comments

Comments
 (0)