diff options
Diffstat (limited to 'editor/plugins/visual_shader_editor_plugin.cpp')
-rw-r--r-- | editor/plugins/visual_shader_editor_plugin.cpp | 159 |
1 files changed, 139 insertions, 20 deletions
diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index ede8351e41..31e158bba7 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -258,7 +258,7 @@ void VisualShaderGraphPlugin::show_port_preview(VisualShader::Type p_type, int p vbox->add_child(offset); VisualShaderNodePortPreview *port_preview = memnew(VisualShaderNodePortPreview); - port_preview->setup(visual_shader, editor->preview_material, visual_shader->get_shader_type(), p_node_id, p_port_id, p_is_valid); + port_preview->setup(visual_shader, editor->preview_material, visual_shader->get_shader_type(), links[p_node_id].output_ports[p_port_id].type == VisualShaderNode::PORT_TYPE_VECTOR_4D, p_node_id, p_port_id, p_is_valid); port_preview->set_h_size_flags(Control::SIZE_SHRINK_CENTER); vbox->add_child(port_preview); link.preview_visible = true; @@ -554,8 +554,8 @@ void VisualShaderGraphPlugin::register_link(VisualShader::Type p_type, int p_id, links.insert(p_id, { p_type, p_visual_node, p_graph_element, p_visual_node->get_output_port_for_preview() != -1, -1, HashMap<int, InputPort>(), HashMap<int, Port>(), nullptr, nullptr, nullptr, { nullptr, nullptr, nullptr } }); } -void VisualShaderGraphPlugin::register_output_port(int p_node_id, int p_port, TextureButton *p_button) { - links[p_node_id].output_ports.insert(p_port, { p_button }); +void VisualShaderGraphPlugin::register_output_port(int p_node_id, int p_port, VisualShaderNode::PortType p_port_type, TextureButton *p_button) { + links[p_node_id].output_ports.insert(p_port, { p_port_type, p_button }); } void VisualShaderGraphPlugin::register_parameter_name(int p_node_id, LineEdit *p_parameter_name) { @@ -1138,7 +1138,7 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id, bool name_box->connect(SceneStringName(focus_exited), callable_mp(editor, &VisualShaderEditor::_port_name_focus_out).bind(name_box, p_id, j, false), CONNECT_DEFERRED); Button *remove_btn = memnew(Button); - remove_btn->set_icon(EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Remove"), EditorStringName(EditorIcons))); + remove_btn->set_button_icon(EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Remove"), EditorStringName(EditorIcons))); remove_btn->set_tooltip_text(TTR("Remove") + " " + name_left); remove_btn->connect(SceneStringName(pressed), callable_mp(editor, &VisualShaderEditor::_remove_input_port).bind(p_id, j), CONNECT_DEFERRED); hb->add_child(remove_btn); @@ -1166,7 +1166,7 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id, bool if (valid_right) { if (is_group) { Button *remove_btn = memnew(Button); - remove_btn->set_icon(EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Remove"), EditorStringName(EditorIcons))); + remove_btn->set_button_icon(EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Remove"), EditorStringName(EditorIcons))); remove_btn->set_tooltip_text(TTR("Remove") + " " + name_left); remove_btn->connect(SceneStringName(pressed), callable_mp(editor, &VisualShaderEditor::_remove_output_port).bind(p_id, i), CONNECT_DEFERRED); hb->add_child(remove_btn); @@ -1220,7 +1220,7 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id, bool preview->set_texture_pressed(editor->get_editor_theme_icon(SNAME("GuiVisibilityVisible"))); preview->set_v_size_flags(Control::SIZE_SHRINK_CENTER); - register_output_port(p_id, j, preview); + register_output_port(p_id, j, port_right, preview); preview->connect(SceneStringName(pressed), callable_mp(editor, &VisualShaderEditor::_preview_select_port).bind(p_id, j), CONNECT_DEFERRED); hb->add_child(preview); @@ -1472,7 +1472,7 @@ void VisualShaderGraphPlugin::disconnect_nodes(VisualShader::Type p_type, int p_ if (visual_shader.is_valid() && visual_shader->get_shader_type() == p_type) { graph->disconnect_node(itos(p_from_node), p_from_port, itos(p_to_node), p_to_port); - for (const List<VisualShader::Connection>::Element *E = connections.front(); E; E = E->next()) { + for (List<VisualShader::Connection>::Element *E = connections.front(); E; E = E->next()) { if (E->get().from_node == p_from_node && E->get().from_port == p_from_port && E->get().to_node == p_to_node && E->get().to_port == p_to_port) { connections.erase(E); break; @@ -1985,6 +1985,67 @@ bool VisualShaderEditor::_update_preview_parameter_tree() { return found; } +void VisualShaderEditor::_preview_tools_menu_option(int p_idx) { + ShaderMaterial *src_mat = nullptr; + + if (p_idx == COPY_PARAMS_FROM_MATERIAL || p_idx == PASTE_PARAMS_TO_MATERIAL) { + for (int i = EditorNode::get_singleton()->get_editor_selection_history()->get_path_size() - 1; i >= 0; i--) { + Object *object = ObjectDB::get_instance(EditorNode::get_singleton()->get_editor_selection_history()->get_path_object(i)); + ShaderMaterial *src_mat2; + if (!object) { + continue; + } + if (object->has_method("get_material_override")) { // Trying to get material from MeshInstance. + src_mat2 = Object::cast_to<ShaderMaterial>(object->call("get_material_override")); + } else if (object->has_method("get_material")) { // From CanvasItem/Node2D. + src_mat2 = Object::cast_to<ShaderMaterial>(object->call("get_material")); + } else { + src_mat2 = Object::cast_to<ShaderMaterial>(object); + } + + if (src_mat2 && src_mat2->get_shader().is_valid() && src_mat2->get_shader() == visual_shader) { + src_mat = src_mat2; + break; + } + } + } + + switch (p_idx) { + case COPY_PARAMS_FROM_MATERIAL: + if (src_mat) { + EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); + undo_redo->create_action(TTR("Copy Preview Shader Parameters From Material")); + + List<PropertyInfo> params; + preview_material->get_shader()->get_shader_uniform_list(¶ms); + for (const PropertyInfo &E : params) { + undo_redo->add_do_method(visual_shader.ptr(), "_set_preview_shader_parameter", E.name, src_mat->get_shader_parameter(E.name)); + undo_redo->add_undo_method(visual_shader.ptr(), "_set_preview_shader_parameter", E.name, preview_material->get_shader_parameter(E.name)); + } + + undo_redo->commit_action(); + } + break; + case PASTE_PARAMS_TO_MATERIAL: + if (src_mat) { + EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); + undo_redo->create_action(TTR("Paste Preview Shader Parameters To Material")); + + List<PropertyInfo> params; + preview_material->get_shader()->get_shader_uniform_list(¶ms); + for (const PropertyInfo &E : params) { + undo_redo->add_do_method(src_mat, "set_shader_parameter", E.name, preview_material->get_shader_parameter(E.name)); + undo_redo->add_undo_method(src_mat, "set_shader_parameter", E.name, src_mat->get_shader_parameter(E.name)); + } + + undo_redo->commit_action(); + } + break; + default: + break; + } +} + void VisualShaderEditor::_clear_preview_param() { selected_param_id = ""; current_prop = nullptr; @@ -2128,12 +2189,11 @@ void VisualShaderEditor::_update_nodes() { } } - Array keys = added.keys(); - keys.sort(); - - for (int i = 0; i < keys.size(); i++) { - const Variant &key = keys.get(i); + List<Variant> keys; + added.get_key_list(&keys); + keys.sort_custom<StringLikeVariantOrder>(); + for (const Variant &key : keys) { const Dictionary &value = (Dictionary)added[key]; add_custom_type(value["name"], value["type"], value["script"], value["description"], value["return_icon_type"], value["category"], value["highend"]); @@ -4065,6 +4125,7 @@ void VisualShaderEditor::_connection_request(const String &p_from, int p_from_in int from = p_from.to_int(); int to = p_to.to_int(); + bool swap = last_to_node != -1 && Input::get_singleton()->is_key_pressed(Key::CMD_OR_CTRL); if (!visual_shader->can_connect_nodes(type, from, p_from_index, to, p_to_index)) { return; @@ -4082,6 +4143,14 @@ void VisualShaderEditor::_connection_request(const String &p_from, int p_from_in undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port); undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port); undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port); + + if (swap) { + undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes", type, E.from_node, E.from_port, last_to_node, last_to_port); + undo_redo->add_undo_method(visual_shader.ptr(), "disconnect_nodes", type, E.from_node, E.from_port, last_to_node, last_to_port); + undo_redo->add_do_method(graph_plugin.ptr(), "connect_nodes", type, E.from_node, E.from_port, last_to_node, last_to_port); + undo_redo->add_undo_method(graph_plugin.ptr(), "disconnect_nodes", type, E.from_node, E.from_port, last_to_node, last_to_port); + } + break; } } @@ -4095,6 +4164,9 @@ void VisualShaderEditor::_connection_request(const String &p_from, int p_from_in undo_redo->add_do_method(graph_plugin.ptr(), "update_node", (int)type, to); undo_redo->add_undo_method(graph_plugin.ptr(), "update_node", (int)type, to); undo_redo->commit_action(); + + last_to_node = -1; + last_to_port = -1; } void VisualShaderEditor::_disconnection_request(const String &p_from, int p_from_index, const String &p_to, int p_to_index) { @@ -4105,6 +4177,11 @@ void VisualShaderEditor::_disconnection_request(const String &p_from, int p_from int from = p_from.to_int(); int to = p_to.to_int(); + last_to_node = to; + last_to_port = p_to_index; + + info_label->show(); + EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); undo_redo->create_action(TTR("Nodes Disconnected")); undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, from, p_from_index, to, p_to_index); @@ -4116,6 +4193,10 @@ void VisualShaderEditor::_disconnection_request(const String &p_from, int p_from undo_redo->commit_action(); } +void VisualShaderEditor::_connection_drag_ended() { + info_label->hide(); +} + void VisualShaderEditor::_connection_to_empty(const String &p_from, int p_from_slot, const Vector2 &p_release_position) { from_node = p_from.to_int(); from_slot = p_from_slot; @@ -5020,8 +5101,11 @@ void VisualShaderEditor::_param_property_changed(const String &p_property, const void VisualShaderEditor::_update_current_param() { if (current_prop != nullptr) { String name = current_prop->get_meta("id"); - preview_material->set("shader_parameter/" + name, visual_shader->_get_preview_shader_parameter(name)); - + if (visual_shader->_has_preview_shader_parameter(name)) { + preview_material->set("shader_parameter/" + name, visual_shader->_get_preview_shader_parameter(name)); + } else { + preview_material->set("shader_parameter/" + name, Variant()); + } current_prop->update_property(); current_prop->update_editor_property_status(); current_prop->update_cache(); @@ -5107,8 +5191,8 @@ void VisualShaderEditor::_notification(int p_what) { param_filter->set_right_icon(Control::get_editor_theme_icon(SNAME("Search"))); node_filter->set_right_icon(Control::get_editor_theme_icon(SNAME("Search"))); - code_preview_button->set_icon(Control::get_editor_theme_icon(SNAME("Shader"))); - shader_preview_button->set_icon(Control::get_editor_theme_icon(SNAME("SubViewport"))); + code_preview_button->set_button_icon(Control::get_editor_theme_icon(SNAME("Shader"))); + shader_preview_button->set_button_icon(Control::get_editor_theme_icon(SNAME("SubViewport"))); { Color background_color = EDITOR_GET("text_editor/theme/highlighting/background_color"); @@ -5159,7 +5243,8 @@ void VisualShaderEditor::_notification(int p_what) { error_label->end_bulk_theme_override(); } - tools->set_icon(get_editor_theme_icon(SNAME("Tools"))); + tools->set_button_icon(get_editor_theme_icon(SNAME("Tools"))); + preview_tools->set_button_icon(get_editor_theme_icon(SNAME("Tools"))); if (is_visible_in_tree()) { _update_graph(); @@ -6306,6 +6391,7 @@ VisualShaderEditor::VisualShaderEditor() { graph->connect(SceneStringName(gui_input), callable_mp(this, &VisualShaderEditor::_graph_gui_input)); graph->connect("connection_to_empty", callable_mp(this, &VisualShaderEditor::_connection_to_empty)); graph->connect("connection_from_empty", callable_mp(this, &VisualShaderEditor::_connection_from_empty)); + graph->connect("connection_drag_ended", callable_mp(this, &VisualShaderEditor::_connection_drag_ended)); graph->connect(SceneStringName(visibility_changed), callable_mp(this, &VisualShaderEditor::_visibility_changed)); graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR, VisualShaderNode::PORT_TYPE_SCALAR); graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR, VisualShaderNode::PORT_TYPE_SCALAR_INT); @@ -6366,6 +6452,13 @@ VisualShaderEditor::VisualShaderEditor() { graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_TRANSFORM, VisualShaderNode::PORT_TYPE_TRANSFORM); graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SAMPLER, VisualShaderNode::PORT_TYPE_SAMPLER); + info_label = memnew(Label); + info_label->set_text(vformat(TTR("Hold %s Key To Swap Connections"), keycode_get_string((Key)KeyModifierMask::CMD_OR_CTRL))); + info_label->set_anchors_and_offsets_preset(Control::PRESET_BOTTOM_WIDE, PRESET_MODE_MINSIZE, 20); + info_label->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER); + info_label->hide(); + graph->get_top_layer()->add_child(info_label); + PanelContainer *toolbar_panel = static_cast<PanelContainer *>(graph->get_menu_hbox()->get_parent()); toolbar_panel->set_anchors_and_offsets_preset(Control::PRESET_TOP_WIDE, PRESET_MODE_MINSIZE, 10); toolbar_panel->set_mouse_filter(Control::MOUSE_FILTER_IGNORE); @@ -6556,11 +6649,21 @@ VisualShaderEditor::VisualShaderEditor() { VBoxContainer *params_vbox = memnew(VBoxContainer); preview_split->add_child(params_vbox); + HBoxContainer *filter_hbox = memnew(HBoxContainer); + params_vbox->add_child(filter_hbox); + param_filter = memnew(LineEdit); + filter_hbox->add_child(param_filter); param_filter->connect(SceneStringName(text_changed), callable_mp(this, &VisualShaderEditor::_param_filter_changed)); param_filter->set_h_size_flags(SIZE_EXPAND_FILL); param_filter->set_placeholder(TTR("Filter Parameters")); - params_vbox->add_child(param_filter); + + preview_tools = memnew(MenuButton); + filter_hbox->add_child(preview_tools); + preview_tools->set_tooltip_text(TTR("Options")); + preview_tools->get_popup()->connect(SceneStringName(id_pressed), callable_mp(this, &VisualShaderEditor::_preview_tools_menu_option)); + preview_tools->get_popup()->add_item(TTR("Copy Parameters From Material"), COPY_PARAMS_FROM_MATERIAL); + preview_tools->get_popup()->add_item(TTR("Paste Parameters To Material"), PASTE_PARAMS_TO_MATERIAL); ScrollContainer *sc = memnew(ScrollContainer); sc->set_v_size_flags(SIZE_EXPAND_FILL); @@ -6776,8 +6879,10 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("Grayscale", "Color/Functions", "VisualShaderNodeColorFunc", TTR("Grayscale function."), { VisualShaderNodeColorFunc::FUNC_GRAYSCALE }, VisualShaderNode::PORT_TYPE_VECTOR_3D)); add_options.push_back(AddOption("HSV2RGB", "Color/Functions", "VisualShaderNodeColorFunc", TTR("Converts HSV vector to RGB equivalent."), { VisualShaderNodeColorFunc::FUNC_HSV2RGB, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D)); + add_options.push_back(AddOption("LinearToSRGB", "Color/Functions", "VisualShaderNodeColorFunc", TTR("Converts color from linear to sRGB color space."), { VisualShaderNodeColorFunc::FUNC_LINEAR_TO_SRGB }, VisualShaderNode::PORT_TYPE_VECTOR_3D)); add_options.push_back(AddOption("RGB2HSV", "Color/Functions", "VisualShaderNodeColorFunc", TTR("Converts RGB vector to HSV equivalent."), { VisualShaderNodeColorFunc::FUNC_RGB2HSV, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D)); add_options.push_back(AddOption("Sepia", "Color/Functions", "VisualShaderNodeColorFunc", TTR("Sepia function."), { VisualShaderNodeColorFunc::FUNC_SEPIA }, VisualShaderNode::PORT_TYPE_VECTOR_3D)); + add_options.push_back(AddOption("SRGBToLinear", "Color/Functions", "VisualShaderNodeColorFunc", TTR("Converts color from sRGB to linear color space."), { VisualShaderNodeColorFunc::FUNC_SRGB_TO_LINEAR }, VisualShaderNode::PORT_TYPE_VECTOR_3D)); add_options.push_back(AddOption("Burn", "Color/Operators", "VisualShaderNodeColorOp", TTR("Burn operator."), { VisualShaderNodeColorOp::OP_BURN }, VisualShaderNode::PORT_TYPE_VECTOR_3D)); add_options.push_back(AddOption("Darken", "Color/Operators", "VisualShaderNodeColorOp", TTR("Darken operator."), { VisualShaderNodeColorOp::OP_DARKEN }, VisualShaderNode::PORT_TYPE_VECTOR_3D)); @@ -6923,7 +7028,7 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("NodePositionView", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "node_position_view", "NODE_POSITION_VIEW"), { "node_position_view" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("NodePositionWorld", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "node_position_world", "NODE_POSITION_WORLD"), { "node_position_world" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("PointCoord", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "point_coord", "POINT_COORD"), { "point_coord" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); - add_options.push_back(AddOption("ScreenUV", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "screen_uv", "SCREEN_UV"), { "screen_uv" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("ScreenUV", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "screen_uv", "SCREEN_UV"), { "screen_uv" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("Tangent", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "tangent", "TANGENT"), { "tangent" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("Vertex", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "vertex", "VERTEX"), { "vertex" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("View", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "view", "VIEW"), { "view" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); @@ -6941,6 +7046,7 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("LightIsDirectional", "Input/Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "light_is_directional", "LIGHT_IS_DIRECTIONAL"), { "light_is_directional" }, VisualShaderNode::PORT_TYPE_BOOLEAN, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("Metallic", "Input/Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "metallic", "METALLIC"), { "metallic" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("Roughness", "Input/Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "roughness", "ROUGHNESS"), { "roughness" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("ScreenUV", "Input/Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "screen_uv", "SCREEN_UV"), { "screen_uv" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("Specular", "Input/Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "specular", "SPECULAR_LIGHT"), { "specular" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("View", "Input/Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "view", "VIEW"), { "view" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL)); @@ -8032,7 +8138,15 @@ void VisualShaderNodePortPreview::_shader_changed() { set_material(mat); } -void VisualShaderNodePortPreview::setup(const Ref<VisualShader> &p_shader, Ref<ShaderMaterial> &p_preview_material, VisualShader::Type p_type, int p_node, int p_port, bool p_is_valid) { +void VisualShaderNodePortPreview::setup(const Ref<VisualShader> &p_shader, Ref<ShaderMaterial> &p_preview_material, VisualShader::Type p_type, bool p_has_transparency, int p_node, int p_port, bool p_is_valid) { + if (p_has_transparency) { + checkerboard = memnew(TextureRect); + checkerboard->set_stretch_mode(TextureRect::STRETCH_TILE); + checkerboard->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); + checkerboard->set_draw_behind_parent(true); + add_child(checkerboard); + } + shader = p_shader; shader->connect_changed(callable_mp(this, &VisualShaderNodePortPreview::_shader_changed), CONNECT_DEFERRED); preview_mat = p_preview_material; @@ -8051,6 +8165,11 @@ Size2 VisualShaderNodePortPreview::get_minimum_size() const { void VisualShaderNodePortPreview::_notification(int p_what) { switch (p_what) { + case NOTIFICATION_THEME_CHANGED: { + if (checkerboard != nullptr) { + checkerboard->set_texture(get_theme_icon(SNAME("GuiMiniCheckerboard"), EditorStringName(EditorIcons))); + } + } break; case NOTIFICATION_DRAW: { Vector<Vector2> points = { Vector2(), |