From 99e997ae15dae35de9f8b320d03796b75c852d5f Mon Sep 17 00:00:00 2001 From: Aaron Franke Date: Fri, 12 Jul 2024 11:56:49 -0700 Subject: [PATCH] Make shader language editors inherit the same base class --- editor/plugins/script_editor_plugin.cpp | 5 +- editor/plugins/shader/shader_editor.h | 50 +++++++++++++++++ editor/plugins/shader_editor_plugin.cpp | 54 +++++++------------ editor/plugins/shader_editor_plugin.h | 7 ++- editor/plugins/text_shader_editor.cpp | 5 +- editor/plugins/text_shader_editor.h | 19 ++++--- .../plugins/visual_shader_editor_plugin.cpp | 27 +++++++--- editor/plugins/visual_shader_editor_plugin.h | 14 +++-- 8 files changed, 120 insertions(+), 61 deletions(-) create mode 100644 editor/plugins/shader/shader_editor.h diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index c51eb44aee4..9da66a08626 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -3799,7 +3799,10 @@ void ScriptEditor::_on_find_in_files_result_selected(const String &fpath, int li ShaderEditorPlugin *shader_editor = Object::cast_to(EditorNode::get_editor_data().get_editor_by_name("Shader")); shader_editor->edit(res.ptr()); shader_editor->make_visible(true); - shader_editor->get_shader_editor(res)->goto_line_selection(line_number - 1, begin, end); + TextShaderEditor *text_shader_editor = Object::cast_to(shader_editor->get_shader_editor(res)); + if (text_shader_editor) { + text_shader_editor->goto_line_selection(line_number - 1, begin, end); + } return; } else if (fpath.get_extension() == "tscn") { Ref f = FileAccess::open(fpath, FileAccess::READ); diff --git a/editor/plugins/shader/shader_editor.h b/editor/plugins/shader/shader_editor.h new file mode 100644 index 00000000000..32e690015b9 --- /dev/null +++ b/editor/plugins/shader/shader_editor.h @@ -0,0 +1,50 @@ +/**************************************************************************/ +/* shader_editor.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef SHADER_EDITOR_H +#define SHADER_EDITOR_H + +#include "scene/gui/control.h" +#include "scene/resources/shader.h" + +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 apply_shaders() = 0; + virtual bool is_unsaved() const = 0; + virtual void save_external_data(const String &p_str = "") = 0; + virtual void validate_script() = 0; +}; + +#endif // SHADER_EDITOR_H diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp index 9d1576cdf2b..82c436d3a53 100644 --- a/editor/plugins/shader_editor_plugin.cpp +++ b/editor/plugins/shader_editor_plugin.cpp @@ -142,7 +142,7 @@ void ShaderEditorPlugin::edit(Object *p_object) { } es.shader_inc = Ref(si); es.shader_editor = memnew(TextShaderEditor); - es.shader_editor->edit(si); + es.shader_editor->edit_shader_include(si); shader_tabs->add_child(es.shader_editor); } else { Shader *s = Object::cast_to(p_object); @@ -156,20 +156,18 @@ void ShaderEditorPlugin::edit(Object *p_object) { es.shader = Ref(s); Ref vs = es.shader; if (vs.is_valid()) { - es.visual_shader_editor = memnew(VisualShaderEditor); - shader_tabs->add_child(es.visual_shader_editor); - es.visual_shader_editor->edit(vs.ptr()); + es.shader_editor = memnew(VisualShaderEditor); } else { es.shader_editor = memnew(TextShaderEditor); - shader_tabs->add_child(es.shader_editor); - es.shader_editor->edit(s); } + shader_tabs->add_child(es.shader_editor); + es.shader_editor->edit_shader(es.shader); } - if (es.shader_editor) { - es.shader_editor->connect("validation_changed", callable_mp(this, &ShaderEditorPlugin::_update_shader_list)); - - CodeTextEditor *cte = es.shader_editor->get_code_editor(); + TextShaderEditor *text_shader_editor = Object::cast_to(es.shader_editor); + if (text_shader_editor) { + text_shader_editor->connect("validation_changed", callable_mp(this, &ShaderEditorPlugin::_update_shader_list)); + CodeTextEditor *cte = text_shader_editor->get_code_editor(); if (cte) { cte->set_zoom_factor(text_shader_zoom_factor); cte->connect("zoomed", callable_mp(this, &ShaderEditorPlugin::_set_text_shader_zoom_factor)); @@ -194,7 +192,7 @@ void ShaderEditorPlugin::make_visible(bool p_visible) { void ShaderEditorPlugin::selected_notify() { } -TextShaderEditor *ShaderEditorPlugin::get_shader_editor(const Ref &p_for_shader) { +ShaderEditor *ShaderEditorPlugin::get_shader_editor(const Ref &p_for_shader) { for (EditedShader &edited_shader : edited_shaders) { if (edited_shader.shader == p_for_shader) { return edited_shader.shader_editor; @@ -203,15 +201,6 @@ TextShaderEditor *ShaderEditorPlugin::get_shader_editor(const Ref &p_for return nullptr; } -VisualShaderEditor *ShaderEditorPlugin::get_visual_shader_editor(const Ref &p_for_shader) { - for (EditedShader &edited_shader : edited_shaders) { - if (edited_shader.shader == p_for_shader) { - return edited_shader.visual_shader_editor; - } - } - return nullptr; -} - void ShaderEditorPlugin::set_window_layout(Ref p_layout) { if (EDITOR_GET("interface/multi_window/restore_windows_on_load") && window_wrapper->is_window_available() && p_layout->has_section_key("ShaderEditor", "window_rect")) { window_wrapper->restore_window_from_saved_position( @@ -280,7 +269,7 @@ void ShaderEditorPlugin::get_window_layout(Ref p_layout) { String selected_shader; for (int i = 0; i < shader_tabs->get_tab_count(); i++) { EditedShader edited_shader = edited_shaders[i]; - if (edited_shader.shader_editor || edited_shader.visual_shader_editor) { + if (edited_shader.shader_editor) { String shader_path; if (edited_shader.shader.is_valid()) { shader_path = edited_shader.shader->get_path(); @@ -290,10 +279,9 @@ void ShaderEditorPlugin::get_window_layout(Ref p_layout) { } shaders.push_back(shader_path); - TextShaderEditor *shader_editor = Object::cast_to(shader_tabs->get_current_tab_control()); - VisualShaderEditor *visual_shader_editor = Object::cast_to(shader_tabs->get_current_tab_control()); + ShaderEditor *shader_editor = Object::cast_to(shader_tabs->get_current_tab_control()); - if ((shader_editor && edited_shader.shader_editor == shader_editor) || (visual_shader_editor && edited_shader.visual_shader_editor == visual_shader_editor)) { + if (shader_editor && edited_shader.shader_editor == shader_editor) { selected_shader = shader_path; } } @@ -366,10 +354,6 @@ void ShaderEditorPlugin::_shader_selected(int p_index) { edited_shaders[p_index].shader_editor->validate_script(); } - if (edited_shaders[p_index].visual_shader_editor) { - edited_shaders[p_index].visual_shader_editor->validate_script(); - } - shader_tabs->set_current_tab(p_index); shader_list->select(p_index); } @@ -440,7 +424,7 @@ void ShaderEditorPlugin::_menu_item_pressed(int p_index) { case FILE_SAVE: { int index = shader_tabs->get_current_tab(); ERR_FAIL_INDEX(index, shader_tabs->get_tab_count()); - TextShaderEditor *editor = edited_shaders[index].shader_editor; + TextShaderEditor *editor = Object::cast_to(edited_shaders[index].shader_editor); if (editor) { if (editor->get_trim_trailing_whitespace_on_save()) { editor->trim_trailing_whitespace(); @@ -462,7 +446,7 @@ void ShaderEditorPlugin::_menu_item_pressed(int p_index) { case FILE_SAVE_AS: { int index = shader_tabs->get_current_tab(); ERR_FAIL_INDEX(index, shader_tabs->get_tab_count()); - TextShaderEditor *editor = edited_shaders[index].shader_editor; + TextShaderEditor *editor = Object::cast_to(edited_shaders[index].shader_editor); if (editor) { if (editor->get_trim_trailing_whitespace_on_save()) { editor->trim_trailing_whitespace(); @@ -623,8 +607,9 @@ void ShaderEditorPlugin::_set_text_shader_zoom_factor(float p_zoom_factor) { if (text_shader_zoom_factor != p_zoom_factor) { text_shader_zoom_factor = p_zoom_factor; for (const EditedShader &edited_shader : edited_shaders) { - if (edited_shader.shader_editor) { - CodeTextEditor *cte = edited_shader.shader_editor->get_code_editor(); + TextShaderEditor *text_shader_editor = Object::cast_to(edited_shader.shader_editor); + if (text_shader_editor) { + CodeTextEditor *cte = text_shader_editor->get_code_editor(); if (cte && cte->get_zoom_factor() != text_shader_zoom_factor) { cte->set_zoom_factor(text_shader_zoom_factor); } @@ -655,12 +640,13 @@ void ShaderEditorPlugin::_res_saved_callback(const Ref &p_res) { } ERR_FAIL_COND(shader_res.is_null()); - if (!edited.shader_editor || !shader_res->is_built_in()) { + TextShaderEditor *text_shader_editor = Object::cast_to(edited.shader_editor); + if (!text_shader_editor || !shader_res->is_built_in()) { continue; } if (shader_res->get_path().get_slice("::", 0) == path) { - edited.shader_editor->tag_saved_version(); + text_shader_editor->tag_saved_version(); _update_shader_list(); } } diff --git a/editor/plugins/shader_editor_plugin.h b/editor/plugins/shader_editor_plugin.h index 386261d8442..f9b9405e45c 100644 --- a/editor/plugins/shader_editor_plugin.h +++ b/editor/plugins/shader_editor_plugin.h @@ -37,6 +37,7 @@ class HSplitContainer; class ItemList; class MenuButton; class ShaderCreateDialog; +class ShaderEditor; class TabContainer; class TextShaderEditor; class VisualShaderEditor; @@ -52,8 +53,7 @@ class ShaderEditorPlugin : public EditorPlugin { struct EditedShader { Ref shader; Ref shader_inc; - TextShaderEditor *shader_editor = nullptr; - VisualShaderEditor *visual_shader_editor = nullptr; + ShaderEditor *shader_editor = nullptr; String path; String name; }; @@ -121,8 +121,7 @@ public: virtual void make_visible(bool p_visible) override; virtual void selected_notify() override; - TextShaderEditor *get_shader_editor(const Ref &p_for_shader); - VisualShaderEditor *get_visual_shader_editor(const Ref &p_for_shader); + ShaderEditor *get_shader_editor(const Ref &p_for_shader); virtual void set_window_layout(Ref p_layout) override; virtual void get_window_layout(Ref p_layout) override; diff --git a/editor/plugins/text_shader_editor.cpp b/editor/plugins/text_shader_editor.cpp index 276c57533f7..6cd92bdf57f 100644 --- a/editor/plugins/text_shader_editor.cpp +++ b/editor/plugins/text_shader_editor.cpp @@ -895,7 +895,7 @@ void TextShaderEditor::_reload() { } } -void TextShaderEditor::edit(const Ref &p_shader) { +void TextShaderEditor::edit_shader(const Ref &p_shader) { if (p_shader.is_null() || !p_shader->is_text_shader()) { return; } @@ -910,7 +910,7 @@ void TextShaderEditor::edit(const Ref &p_shader) { code_editor->set_edited_shader(shader); } -void TextShaderEditor::edit(const Ref &p_shader_inc) { +void TextShaderEditor::edit_shader_include(const Ref &p_shader_inc) { if (p_shader_inc.is_null()) { return; } @@ -1141,6 +1141,7 @@ TextShaderEditor::TextShaderEditor() { context_menu->connect(SceneStringName(id_pressed), callable_mp(this, &TextShaderEditor::_menu_option)); VBoxContainer *main_container = memnew(VBoxContainer); + main_container->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); HBoxContainer *hbc = memnew(HBoxContainer); edit_menu = memnew(MenuButton); diff --git a/editor/plugins/text_shader_editor.h b/editor/plugins/text_shader_editor.h index 61066ed7c65..55efb4e30ed 100644 --- a/editor/plugins/text_shader_editor.h +++ b/editor/plugins/text_shader_editor.h @@ -32,6 +32,7 @@ #define TEXT_SHADER_EDITOR_H #include "editor/code_editor.h" +#include "editor/plugins/shader/shader_editor.h" #include "scene/gui/margin_container.h" #include "scene/gui/menu_button.h" #include "scene/gui/rich_text_label.h" @@ -104,8 +105,8 @@ public: ShaderTextEditor(); }; -class TextShaderEditor : public MarginContainer { - GDCLASS(TextShaderEditor, MarginContainer); +class TextShaderEditor : public ShaderEditor { + GDCLASS(TextShaderEditor, ShaderEditor); enum { EDIT_UNDO, @@ -188,19 +189,21 @@ protected: void _bookmark_item_pressed(int p_idx); public: + virtual void edit_shader(const Ref &p_shader) override; + virtual void edit_shader_include(const Ref &p_shader_inc) 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; + bool was_compilation_successful() const { return compilation_success; } bool get_trim_trailing_whitespace_on_save() const { return trim_trailing_whitespace_on_save; } bool get_trim_final_newlines_on_save() const { return trim_final_newlines_on_save; } - void apply_shaders(); void ensure_select_current(); - void edit(const Ref &p_shader); - void edit(const Ref &p_shader_inc); void goto_line_selection(int p_line, int p_begin, int p_end); - void save_external_data(const String &p_str = ""); void trim_trailing_whitespace(); void trim_final_newlines(); - void validate_script(); - bool is_unsaved() const; void tag_saved_version(); ShaderTextEditor *get_code_editor() { return code_editor; } diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index 2da9d66d9a4..cd80273d67e 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -1509,17 +1509,18 @@ Vector2 VisualShaderEditor::selection_center; List VisualShaderEditor::copy_items_buffer; List VisualShaderEditor::copy_connections_buffer; -void VisualShaderEditor::edit(VisualShader *p_visual_shader) { +void VisualShaderEditor::edit_shader(const Ref &p_shader) { bool changed = false; - if (p_visual_shader) { + VisualShader *visual_shader_ptr = Object::cast_to(p_shader.ptr()); + if (visual_shader_ptr) { if (visual_shader.is_null()) { changed = true; } else { - if (visual_shader.ptr() != p_visual_shader) { + if (visual_shader.ptr() != visual_shader_ptr) { changed = true; } } - visual_shader = Ref(p_visual_shader); + visual_shader = p_shader; graph_plugin->register_shader(visual_shader.ptr()); visual_shader->connect_changed(callable_mp(this, &VisualShaderEditor::_update_preview)); @@ -1546,6 +1547,19 @@ void VisualShaderEditor::edit(VisualShader *p_visual_shader) { } } +void VisualShaderEditor::apply_shaders() { + // Stub. TODO: Implement apply_shaders in visual shaders for parity with text shaders. +} + +bool VisualShaderEditor::is_unsaved() const { + // Stub. TODO: Implement is_unsaved in visual shaders for parity with text shaders. + return false; +} + +void VisualShaderEditor::save_external_data(const String &p_str) { + ResourceSaver::save(visual_shader, visual_shader->get_path()); +} + void VisualShaderEditor::validate_script() { if (visual_shader.is_valid()) { _update_nodes(); @@ -6054,8 +6068,7 @@ VisualShaderEditor::VisualShaderEditor() { graph = memnew(GraphEdit); graph->get_menu_hbox()->set_h_size_flags(SIZE_EXPAND_FILL); - graph->set_v_size_flags(SIZE_EXPAND_FILL); - graph->set_h_size_flags(SIZE_EXPAND_FILL); + graph->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); graph->set_grid_pattern(GraphEdit::GridPattern::GRID_PATTERN_DOTS); int grid_pattern = EDITOR_GET("editors/visual_editors/grid_pattern"); graph->set_grid_pattern((GraphEdit::GridPattern)grid_pattern); @@ -7562,7 +7575,7 @@ void EditorPropertyVisualShaderMode::_option_selected(int p_which) { if (!shader_editor) { return; } - VisualShaderEditor *editor = shader_editor->get_visual_shader_editor(visual_shader); + VisualShaderEditor *editor = Object::cast_to(shader_editor->get_shader_editor(visual_shader)); if (!editor) { return; } diff --git a/editor/plugins/visual_shader_editor_plugin.h b/editor/plugins/visual_shader_editor_plugin.h index a9826fd6178..aaeb77ac817 100644 --- a/editor/plugins/visual_shader_editor_plugin.h +++ b/editor/plugins/visual_shader_editor_plugin.h @@ -34,6 +34,7 @@ #include "editor/editor_properties.h" #include "editor/plugins/editor_plugin.h" #include "editor/plugins/editor_resource_conversion_plugin.h" +#include "editor/plugins/shader/shader_editor.h" #include "scene/gui/graph_edit.h" #include "scene/resources/syntax_highlighter.h" #include "scene/resources/visual_shader.h" @@ -195,8 +196,8 @@ public: VisualShaderEditedProperty() {} }; -class VisualShaderEditor : public VBoxContainer { - GDCLASS(VisualShaderEditor, VBoxContainer); +class VisualShaderEditor : public ShaderEditor { + GDCLASS(VisualShaderEditor, ShaderEditor); friend class VisualShaderGraphPlugin; PopupPanel *property_editor_popup = nullptr; @@ -596,6 +597,12 @@ protected: static void _bind_methods(); public: + virtual void edit_shader(const Ref &p_shader) 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; + void add_plugin(const Ref &p_plugin); void remove_plugin(const Ref &p_plugin); @@ -609,11 +616,8 @@ public: virtual Size2 get_minimum_size() const override; - void edit(VisualShader *p_visual_shader); Ref get_visual_shader() const { return visual_shader; } - void validate_script(); - VisualShaderEditor(); };