From 0831b4b516366a863b4ba041eeb1558bdfc9298f Mon Sep 17 00:00:00 2001 From: Aaron Franke Date: Mon, 25 Aug 2025 15:55:30 -0700 Subject: [PATCH] Make shader editor menu position consistent between shader languages --- editor/shader/shader_editor.h | 5 +- editor/shader/shader_editor_plugin.cpp | 77 ++++--------------- editor/shader/shader_editor_plugin.h | 3 +- editor/shader/text_shader_editor.cpp | 28 ++++--- editor/shader/text_shader_editor.h | 4 +- editor/shader/visual_shader_editor_plugin.cpp | 73 ++++++++++-------- editor/shader/visual_shader_editor_plugin.h | 7 +- 7 files changed, 83 insertions(+), 114 deletions(-) diff --git a/editor/shader/shader_editor.h b/editor/shader/shader_editor.h index d9c6b64a19..de6800403c 100644 --- a/editor/shader/shader_editor.h +++ b/editor/shader/shader_editor.h @@ -33,16 +33,19 @@ #include "scene/gui/control.h" #include "scene/resources/shader.h" +class Button; +class MenuButton; + class ShaderEditor : public Control { GDCLASS(ShaderEditor, Control); public: virtual void edit_shader(const Ref &p_shader) = 0; virtual void edit_shader_include(const Ref &p_shader_inc) {} + virtual void use_menu_bar_items(MenuButton *p_file_menu, Button *p_make_floating) = 0; virtual void apply_shaders() = 0; virtual bool is_unsaved() const = 0; virtual void save_external_data(const String &p_str = "") = 0; virtual void validate_script() = 0; - virtual Control *get_top_bar() = 0; }; diff --git a/editor/shader/shader_editor_plugin.cpp b/editor/shader/shader_editor_plugin.cpp index 8e08536a2e..769ae16175 100644 --- a/editor/shader/shader_editor_plugin.cpp +++ b/editor/shader/shader_editor_plugin.cpp @@ -190,12 +190,6 @@ void ShaderEditorPlugin::edit(Object *p_object) { cte->connect("zoomed", callable_mp(this, &ShaderEditorPlugin::_set_text_shader_zoom_factor)); cte->connect(SceneStringName(visibility_changed), callable_mp(this, &ShaderEditorPlugin::_update_shader_editor_zoom_factor).bind(cte)); } - - if (text_shader_editor->get_top_bar()) { - text_shader_editor->get_top_bar()->set_h_size_flags(Control::SIZE_EXPAND_FILL); - menu_hb->add_child(text_shader_editor->get_top_bar()); - menu_hb->move_child(text_shader_editor->get_top_bar(), 1); - } } shader_tabs->set_current_tab(shader_tabs->get_tab_count() - 1); @@ -459,29 +453,22 @@ void ShaderEditorPlugin::_make_script_list_context_menu() { void ShaderEditorPlugin::_close_shader(int p_index) { ERR_FAIL_INDEX(p_index, shader_tabs->get_tab_count()); - - Control *c = shader_tabs->get_tab_control(p_index); - VisualShaderEditor *vs_editor = Object::cast_to(c); - if (vs_editor) { - vs_editor->save_editor_layout(); + if (file_menu->get_parent() != nullptr) { file_menu->get_parent()->remove_child(file_menu); - menu_hb->add_child(file_menu); - menu_hb->move_child(file_menu, 0); - - make_floating->get_parent()->remove_child(make_floating); - menu_hb->add_child(make_floating); - } else { - memdelete(edited_shaders[p_index].shader_editor->get_top_bar()); } + if (make_floating->get_parent()) { + make_floating->get_parent()->remove_child(make_floating); + } + ShaderEditor *shader_editor = Object::cast_to(shader_tabs->get_tab_control(p_index)); + ERR_FAIL_NULL(shader_editor); - memdelete(c); + memdelete(shader_editor); edited_shaders.remove_at(p_index); _update_shader_list(); EditorUndoRedoManager::get_singleton()->clear_history(); // To prevent undo on deleted graphs. if (shader_tabs->get_tab_count() == 0) { shader_list->show(); // Make sure the panel is visible, because it can't be toggled without open shaders. - menu_spacer->show(); } else { _switch_to_editor(edited_shaders[shader_tabs->get_current_tab()].shader_editor); } @@ -795,44 +782,13 @@ void ShaderEditorPlugin::_update_shader_editor_zoom_factor(CodeTextEditor *p_sha } void ShaderEditorPlugin::_switch_to_editor(ShaderEditor *p_editor) { - Control *bar = p_editor->get_top_bar(); - - VisualShaderEditor *vs_editor = Object::cast_to(p_editor); - if (vs_editor) { + if (file_menu->get_parent() != nullptr) { file_menu->get_parent()->remove_child(file_menu); - file_menu->set_switch_on_hover(false); - bar->add_child(file_menu); - bar->move_child(file_menu, 2); // Toggle Files Panel button + separator. - + } + if (make_floating->get_parent()) { make_floating->get_parent()->remove_child(make_floating); - bar->add_child(make_floating); - } else { - if (menu_spacer->is_visible()) { - menu_spacer->hide(); - } - - // Just swapped from a visual shader editor. - if (file_menu->get_parent() != menu_hb) { - file_menu->get_parent()->remove_child(file_menu); - file_menu->set_switch_on_hover(true); - menu_hb->add_child(file_menu); - menu_hb->move_child(file_menu, 0); - - make_floating->get_parent()->remove_child(make_floating); - menu_hb->add_child(make_floating); - } - } - - for (int i = 0; i < shader_tabs->get_tab_count(); i++) { - ShaderEditor *se = Object::cast_to(shader_tabs->get_tab_control(i)); - if (se && se->get_top_bar()) { - if (se == p_editor) { - se->get_top_bar()->show(); - } else { - se->get_top_bar()->hide(); - } - } } + p_editor->use_menu_bar_items(file_menu, make_floating); } void ShaderEditorPlugin::_file_removed(const String &p_removed_file) { @@ -902,8 +858,6 @@ ShaderEditorPlugin::ShaderEditorPlugin() { files_split->set_split_offset(200 * EDSCALE); files_split->set_v_size_flags(Control::SIZE_EXPAND_FILL); - menu_hb = memnew(HBoxContainer); - main_container->add_child(menu_hb); file_menu = memnew(MenuButton); file_menu->set_flat(false); file_menu->set_theme_type_variation("FlatMenuButton"); @@ -912,7 +866,6 @@ ShaderEditorPlugin::ShaderEditorPlugin() { file_menu->set_shortcut_context(files_split); _setup_popup_menu(FILE, file_menu->get_popup()); file_menu->get_popup()->connect(SceneStringName(id_pressed), callable_mp(this, &ShaderEditorPlugin::_menu_item_pressed)); - menu_hb->add_child(file_menu); _set_file_specific_items_disabled(true); @@ -920,8 +873,6 @@ ShaderEditorPlugin::ShaderEditorPlugin() { add_child(context_menu); context_menu->connect(SceneStringName(id_pressed), callable_mp(this, &ShaderEditorPlugin::_menu_item_pressed)); - menu_spacer = menu_hb->add_spacer(); - make_floating = memnew(ScreenSelect); make_floating->connect("request_open_in_screen", callable_mp(window_wrapper, &WindowWrapper::enable_window_on_screen).bind(true)); if (!make_floating->is_disabled()) { @@ -929,7 +880,6 @@ ShaderEditorPlugin::ShaderEditorPlugin() { make_floating->set_tooltip_text(TTR("Make the shader editor floating.") + "\n" + TTR("Right-click to open the screen selector.")); } - menu_hb->add_child(make_floating); window_wrapper->connect("window_visibility_changed", callable_mp(this, &ShaderEditorPlugin::_window_changed)); shader_list = memnew(ItemList); @@ -962,3 +912,8 @@ ShaderEditorPlugin::ShaderEditorPlugin() { shader_create_dialog->connect("shader_created", callable_mp(this, &ShaderEditorPlugin::_shader_created)); shader_create_dialog->connect("shader_include_created", callable_mp(this, &ShaderEditorPlugin::_shader_include_created)); } + +ShaderEditorPlugin::~ShaderEditorPlugin() { + memdelete(file_menu); + memdelete(make_floating); +} diff --git a/editor/shader/shader_editor_plugin.h b/editor/shader/shader_editor_plugin.h index cb7fe5e043..771025669c 100644 --- a/editor/shader/shader_editor_plugin.h +++ b/editor/shader/shader_editor_plugin.h @@ -83,8 +83,6 @@ class ShaderEditorPlugin : public EditorPlugin { VBoxContainer *main_container = nullptr; HSplitContainer *files_split = nullptr; - HBoxContainer *menu_hb = nullptr; - Control *menu_spacer = nullptr; ItemList *shader_list = nullptr; TabContainer *shader_tabs = nullptr; @@ -150,4 +148,5 @@ public: virtual void apply_changes() override; ShaderEditorPlugin(); + ~ShaderEditorPlugin(); }; diff --git a/editor/shader/text_shader_editor.cpp b/editor/shader/text_shader_editor.cpp index f67c53acdb..99327da800 100644 --- a/editor/shader/text_shader_editor.cpp +++ b/editor/shader/text_shader_editor.cpp @@ -979,6 +979,13 @@ void TextShaderEditor::edit_shader_include(const Ref &p_shader_in code_editor->set_edited_shader_include(p_shader_inc); } +void TextShaderEditor::use_menu_bar_items(MenuButton *p_file_menu, Button *p_make_floating) { + p_file_menu->set_switch_on_hover(true); + menu_bar_hbox->add_child(p_file_menu); + menu_bar_hbox->move_child(p_file_menu, 0); + menu_bar_hbox->add_child(p_make_floating); +} + void TextShaderEditor::save_external_data(const String &p_str) { if (shader.is_null() && shader_inc.is_null()) { disk_changed->hide(); @@ -1027,10 +1034,6 @@ void TextShaderEditor::validate_script() { code_editor->_validate_script(); } -Control *TextShaderEditor::get_top_bar() { - return hbc; -} - bool TextShaderEditor::is_unsaved() const { return code_editor->get_text_editor()->get_saved_version() != code_editor->get_text_editor()->get_version(); } @@ -1204,7 +1207,7 @@ TextShaderEditor::TextShaderEditor() { VBoxContainer *main_container = memnew(VBoxContainer); main_container->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); - hbc = memnew(HBoxContainer); + menu_bar_hbox = memnew(HBoxContainer); edit_menu = memnew(MenuButton); edit_menu->set_flat(false); @@ -1267,20 +1270,21 @@ TextShaderEditor::TextShaderEditor() { bookmarks_menu->connect("index_pressed", callable_mp(this, &TextShaderEditor::_bookmark_item_pressed)); add_child(main_container); - hbc->add_child(edit_menu); - hbc->add_child(search_menu); - hbc->add_child(goto_menu); - hbc->add_spacer(); + main_container->add_child(menu_bar_hbox); + menu_bar_hbox->add_child(edit_menu); + menu_bar_hbox->add_child(search_menu); + menu_bar_hbox->add_child(goto_menu); + menu_bar_hbox->add_spacer(); site_search = memnew(Button); site_search->set_theme_type_variation(SceneStringName(FlatButton)); site_search->connect(SceneStringName(pressed), callable_mp(this, &TextShaderEditor::_menu_option).bind(HELP_DOCS)); site_search->set_text(TTR("Online Docs")); site_search->set_tooltip_text(TTR("Open Godot online documentation.")); - hbc->add_child(site_search); - hbc->add_child(memnew(VSeparator)); + menu_bar_hbox->add_child(site_search); + menu_bar_hbox->add_child(memnew(VSeparator)); - hbc->add_theme_style_override(SceneStringName(panel), EditorNode::get_singleton()->get_editor_theme()->get_stylebox(SNAME("ScriptEditorPanel"), EditorStringName(EditorStyles))); + menu_bar_hbox->add_theme_style_override(SceneStringName(panel), EditorNode::get_singleton()->get_editor_theme()->get_stylebox(SNAME("ScriptEditorPanel"), EditorStringName(EditorStyles))); VSplitContainer *editor_box = memnew(VSplitContainer); main_container->add_child(editor_box); diff --git a/editor/shader/text_shader_editor.h b/editor/shader/text_shader_editor.h index c1f1436193..42a6b60cd7 100644 --- a/editor/shader/text_shader_editor.h +++ b/editor/shader/text_shader_editor.h @@ -136,7 +136,7 @@ class TextShaderEditor : public ShaderEditor { EDIT_EMOJI_AND_SYMBOL, }; - HBoxContainer *hbc = nullptr; + HBoxContainer *menu_bar_hbox = nullptr; MenuButton *edit_menu = nullptr; MenuButton *search_menu = nullptr; PopupMenu *bookmarks_menu = nullptr; @@ -191,12 +191,12 @@ protected: public: virtual void edit_shader(const Ref &p_shader) override; virtual void edit_shader_include(const Ref &p_shader_inc) override; + virtual void use_menu_bar_items(MenuButton *p_file_menu, Button *p_make_floating) override; virtual void apply_shaders() override; virtual bool is_unsaved() const override; virtual void save_external_data(const String &p_str = "") override; virtual void validate_script() override; - virtual Control *get_top_bar() override; bool was_compilation_successful() const { return compilation_success; } bool get_trim_trailing_whitespace_on_save() const { return trim_trailing_whitespace_on_save; } diff --git a/editor/shader/visual_shader_editor_plugin.cpp b/editor/shader/visual_shader_editor_plugin.cpp index c470427419..33b6088a11 100644 --- a/editor/shader/visual_shader_editor_plugin.cpp +++ b/editor/shader/visual_shader_editor_plugin.cpp @@ -1560,6 +1560,13 @@ void VisualShaderEditor::edit_shader(const Ref &p_shader) { } } +void VisualShaderEditor::use_menu_bar_items(MenuButton *p_file_menu, Button *p_make_floating) { + p_file_menu->set_switch_on_hover(false); + toolbar_hflow->add_child(p_file_menu); + toolbar_hflow->move_child(p_file_menu, 2); // Toggle Files Panel button + separator. + toolbar_hflow->add_child(p_make_floating); +} + void VisualShaderEditor::apply_shaders() { // Stub. TODO: Implement apply_shaders in visual shaders for parity with text shaders. } @@ -1610,10 +1617,6 @@ VisualShader::Type VisualShaderEditor::get_current_shader_type() const { return current_type; } -Control *VisualShaderEditor::get_top_bar() { - return toolbar; -} - void VisualShaderEditor::add_plugin(const Ref &p_plugin) { if (plugins.has(p_plugin)) { return; @@ -6607,7 +6610,7 @@ VisualShaderEditor::VisualShaderEditor() { toolbar_panel->set_anchors_and_offsets_preset(Control::PRESET_TOP_WIDE, PRESET_MODE_MINSIZE, 10); toolbar_panel->set_mouse_filter(Control::MOUSE_FILTER_IGNORE); - toolbar = memnew(HFlowContainer); + toolbar_hflow = memnew(HFlowContainer); { LocalVector nodes; for (int i = 0; i < graph->get_menu_hbox()->get_child_count(); i++) { @@ -6617,16 +6620,16 @@ VisualShaderEditor::VisualShaderEditor() { for (Node *node : nodes) { graph->get_menu_hbox()->remove_child(node); - toolbar->add_child(node); + toolbar_hflow->add_child(node); } graph->get_menu_hbox()->hide(); - toolbar_panel->add_child(toolbar); + toolbar_panel->add_child(toolbar_hflow); } VSeparator *vs = memnew(VSeparator); - toolbar->add_child(vs); - toolbar->move_child(vs, 0); + toolbar_hflow->add_child(vs); + toolbar_hflow->move_child(vs, 0); custom_mode_box = memnew(CheckBox); custom_mode_box->set_text(TTR("Custom")); @@ -6660,22 +6663,22 @@ VisualShaderEditor::VisualShaderEditor() { edit_type = edit_type_standard; - toolbar->add_child(custom_mode_box); - toolbar->move_child(custom_mode_box, 0); - toolbar->add_child(edit_type_standard); - toolbar->move_child(edit_type_standard, 0); - toolbar->add_child(edit_type_particles); - toolbar->move_child(edit_type_particles, 0); - toolbar->add_child(edit_type_sky); - toolbar->move_child(edit_type_sky, 0); - toolbar->add_child(edit_type_fog); - toolbar->move_child(edit_type_fog, 0); + toolbar_hflow->add_child(custom_mode_box); + toolbar_hflow->move_child(custom_mode_box, 0); + toolbar_hflow->add_child(edit_type_standard); + toolbar_hflow->move_child(edit_type_standard, 0); + toolbar_hflow->add_child(edit_type_particles); + toolbar_hflow->move_child(edit_type_particles, 0); + toolbar_hflow->add_child(edit_type_sky); + toolbar_hflow->move_child(edit_type_sky, 0); + toolbar_hflow->add_child(edit_type_fog); + toolbar_hflow->move_child(edit_type_fog, 0); add_node = memnew(Button); add_node->set_theme_type_variation(SceneStringName(FlatButton)); add_node->set_text(TTR("Add Node...")); - toolbar->add_child(add_node); - toolbar->move_child(add_node, 0); + toolbar_hflow->add_child(add_node); + toolbar_hflow->move_child(add_node, 0); add_node->connect(SceneStringName(pressed), callable_mp(this, &VisualShaderEditor::_show_members_dialog).bind(false, VisualShaderNode::PORT_TYPE_MAX, VisualShaderNode::PORT_TYPE_MAX)); graph->connect("graph_elements_linked_to_frame_request", callable_mp(this, &VisualShaderEditor::_nodes_linked_to_frame_request)); @@ -6686,7 +6689,7 @@ VisualShaderEditor::VisualShaderEditor() { varying_button->set_theme_type_variation("FlatMenuButton"); varying_button->set_text(TTR("Manage Varyings")); varying_button->set_switch_on_hover(true); - toolbar->add_child(varying_button); + toolbar_hflow->add_child(varying_button); PopupMenu *varying_menu = varying_button->get_popup(); varying_menu->add_item(TTR("Add Varying"), int(VaryingMenuOptions::ADD)); @@ -6697,7 +6700,7 @@ VisualShaderEditor::VisualShaderEditor() { code_preview_button->set_theme_type_variation(SceneStringName(FlatButton)); code_preview_button->set_toggle_mode(true); code_preview_button->set_tooltip_text(TTR("Show generated shader code.")); - toolbar->add_child(code_preview_button); + toolbar_hflow->add_child(code_preview_button); code_preview_button->connect(SceneStringName(pressed), callable_mp(this, &VisualShaderEditor::_show_preview_text)); shader_preview_button = memnew(Button); @@ -6705,34 +6708,34 @@ VisualShaderEditor::VisualShaderEditor() { shader_preview_button->set_toggle_mode(true); shader_preview_button->set_tooltip_text(TTR("Toggle shader preview.")); shader_preview_button->set_pressed(true); - toolbar->add_child(shader_preview_button); + toolbar_hflow->add_child(shader_preview_button); shader_preview_button->connect(SceneStringName(pressed), callable_mp(this, &VisualShaderEditor::_show_shader_preview)); Control *spacer = memnew(Control); spacer->set_h_size_flags(Control::SIZE_EXPAND); - toolbar->add_child(spacer); + toolbar_hflow->add_child(spacer); site_search = memnew(Button); site_search->set_theme_type_variation(SceneStringName(FlatButton)); site_search->connect(SceneStringName(pressed), callable_mp(this, &VisualShaderEditor::_help_open)); site_search->set_text(TTR("Online Docs")); site_search->set_tooltip_text(TTR("Open Godot online documentation.")); - toolbar->add_child(site_search); - toolbar->add_child(memnew(VSeparator)); + toolbar_hflow->add_child(site_search); + toolbar_hflow->add_child(memnew(VSeparator)); VSeparator *separator = memnew(VSeparator); - toolbar->add_child(separator); - toolbar->move_child(separator, 0); + toolbar_hflow->add_child(separator); + toolbar_hflow->move_child(separator, 0); separator = memnew(VSeparator); - toolbar->add_child(separator); - toolbar->move_child(separator, 0); + toolbar_hflow->add_child(separator); + toolbar_hflow->move_child(separator, 0); toggle_files_button = memnew(Button); toggle_files_button->set_theme_type_variation(SceneStringName(FlatButton)); toggle_files_button->connect(SceneStringName(pressed), callable_mp(this, &VisualShaderEditor::_toggle_files_pressed)); - toolbar->add_child(toggle_files_button); - toolbar->move_child(toggle_files_button, 0); + toolbar_hflow->add_child(toggle_files_button); + toolbar_hflow->move_child(toggle_files_button, 0); /////////////////////////////////////// // CODE PREVIEW @@ -7761,6 +7764,10 @@ VisualShaderEditor::VisualShaderEditor() { add_child(panning_debounce_timer); } +VisualShaderEditor::~VisualShaderEditor() { + save_editor_layout(); +} + class VisualShaderNodePluginInputEditor : public OptionButton { GDCLASS(VisualShaderNodePluginInputEditor, OptionButton); diff --git a/editor/shader/visual_shader_editor_plugin.h b/editor/shader/visual_shader_editor_plugin.h index 87b69e29f7..dc3dad38b6 100644 --- a/editor/shader/visual_shader_editor_plugin.h +++ b/editor/shader/visual_shader_editor_plugin.h @@ -43,6 +43,7 @@ class ColorPicker; class CurveEditor; class GraphElement; class GraphFrame; +class HFlowContainer; class MenuButton; class PopupPanel; class RichTextLabel; @@ -220,7 +221,7 @@ class VisualShaderEditor : public ShaderEditor { MenuButton *varying_button = nullptr; Button *code_preview_button = nullptr; Button *shader_preview_button = nullptr; - Control *toolbar = nullptr; + HFlowContainer *toolbar_hflow = nullptr; int last_to_node = -1; int last_to_port = -1; @@ -650,6 +651,7 @@ protected: public: virtual void edit_shader(const Ref &p_shader) override; + virtual void use_menu_bar_items(MenuButton *p_file_menu, Button *p_make_floating) override; virtual void apply_shaders() override; virtual bool is_unsaved() const override; virtual void save_external_data(const String &p_str = "") override; @@ -660,8 +662,6 @@ public: void set_current_shader_type(VisualShader::Type p_type); VisualShader::Type get_current_shader_type() const; - virtual Control *get_top_bar() override; - void add_plugin(const Ref &p_plugin); void remove_plugin(const Ref &p_plugin); @@ -680,6 +680,7 @@ public: Ref get_visual_shader() const { return visual_shader; } VisualShaderEditor(); + ~VisualShaderEditor(); }; class VisualShaderNodePluginDefault : public VisualShaderNodePlugin {