diff --git a/doc/classes/GraphEdit.xml b/doc/classes/GraphEdit.xml
index 18469b00a84..001839d7452 100644
--- a/doc/classes/GraphEdit.xml
+++ b/doc/classes/GraphEdit.xml
@@ -109,6 +109,14 @@
Rearranges selected nodes in a layout with minimum crossings between connections and uniform horizontal and vertical gap between nodes.
+
+
+
+
+
+ Attaches the [param element] [GraphElement] to the [param frame] [GraphFrame].
+
+
@@ -125,6 +133,13 @@
Create a connection between the [param from_port] of the [param from_node] [GraphNode] and the [param to_port] of the [param to_node] [GraphNode]. If the connection already exists, no connection is created.
+
+
+
+
+ Detaches the [param element] [GraphElement] from the [GraphFrame] it is currently attached to.
+
+
@@ -143,6 +158,13 @@
[b]Note:[/b] This method suppresses any other connection request signals apart from [signal connection_drag_ended].
+
+
+
+
+ Returns an array of node names that are attached to the [GraphFrame] with the given name.
+
+
@@ -179,6 +201,13 @@
Returns an [Array] containing the list of connections that intersect with the given [Rect2]. A connection consists in a structure of the form [code]{ from_port: 0, from_node: "GraphNode name 0", to_port: 1, to_node: "GraphNode name 1" }[/code].
+
+
+
+
+ Returns the [GraphFrame] that contains the [GraphElement] with the given name.
+
+
@@ -395,6 +424,21 @@
Emitted at the end of a [GraphElement]'s movement.
+
+
+
+
+ Emitted when the [GraphFrame] [param frame] is resized to [param new_rect].
+
+
+
+
+
+
+ Emitted when one or more [GraphElement]s are dropped onto the [GraphFrame] named [param frame], when they were not previously attached to any other one.
+ [param elements] is an array of [GraphElement]s to be attached.
+
+
diff --git a/doc/classes/GraphElement.xml b/doc/classes/GraphElement.xml
index 17c4184a20b..7cd6496773f 100644
--- a/doc/classes/GraphElement.xml
+++ b/doc/classes/GraphElement.xml
@@ -17,7 +17,7 @@
If [code]true[/code], the user can resize the GraphElement.
- [b]Note:[/b] Dragging the handle will only emit the [signal resize_request] signal, the GraphElement needs to be resized manually.
+ [b]Note:[/b] Dragging the handle will only emit the [signal resize_request] and [signal resize_end] signals, the GraphElement needs to be resized manually.
If [code]true[/code], the user can select the GraphElement.
@@ -59,8 +59,14 @@
Emitted when displaying the GraphElement over other ones is requested. Happens on focusing (clicking into) the GraphElement.
+
+
+
+ Emitted when releasing the mouse button after dragging the resizer handle (see [member resizable]).
+
+
-
+
Emitted when resizing the GraphElement is requested. Happens on dragging the resizer handle (see [member resizable]).
diff --git a/doc/classes/GraphFrame.xml b/doc/classes/GraphFrame.xml
new file mode 100644
index 00000000000..52bb451d957
--- /dev/null
+++ b/doc/classes/GraphFrame.xml
@@ -0,0 +1,66 @@
+
+
+
+ GraphFrame is a special [GraphElement] that can be used to organize other [GraphElement]s inside a [GraphEdit].
+
+
+ GraphFrame is a special [GraphElement] to which other [GraphElement]s can be attached. It can be configured to automatically resize to enclose all attached [GraphElement]s. If the frame is moved, all the attached [GraphElement]s inside it will be moved as well.
+ A GraphFrame is always kept behind the connection layer and other [GraphElement]s inside a [GraphEdit].
+
+
+
+
+
+
+
+ Returns the [HBoxContainer] used for the title bar, only containing a [Label] for displaying the title by default.
+ This can be used to add custom controls to the title bar such as option or close buttons.
+
+
+
+
+
+ If [code]true[/code], the frame's rect will be adjusted automatically to enclose all attached [GraphElement]s.
+
+
+ The margin around the attached nodes that is used to calculate the size of the frame when [member autoshrink_enabled] is [code]true[/code].
+
+
+ The margin inside the frame that can be used to drag the frame.
+
+
+
+ The color of the frame when [member tint_color_enabled] is [code]true[/code].
+
+
+ If [code]true[/code], the tint color will be used to tint the frame.
+
+
+ Title of the frame.
+
+
+
+
+
+ Emitted when [member autoshrink_enabled] or [member autoshrink_margin] changes.
+
+
+
+
+
+ The color modulation applied to the resizer icon.
+
+
+ The default [StyleBox] used for the background of the [GraphFrame].
+
+
+ The [StyleBox] used for the background of the [GraphFrame] when it is selected.
+
+
+ The [StyleBox] used for the title bar of the [GraphFrame].
+
+
+ The [StyleBox] used for the title bar of the [GraphFrame] when it is selected.
+
+
+
diff --git a/doc/classes/VisualShader.xml b/doc/classes/VisualShader.xml
index 0b416214b53..c8230d94e4a 100644
--- a/doc/classes/VisualShader.xml
+++ b/doc/classes/VisualShader.xml
@@ -29,6 +29,15 @@
Adds a new varying value node to the shader.
+
+
+
+
+
+
+ Attaches the given node to the given frame.
+
+
@@ -62,6 +71,14 @@
Connects the specified nodes and ports, even if they can't be connected. Such connection is invalid and will not function properly.
+
+
+
+
+
+ Detaches the given node from the frame it is attached to.
+
+
diff --git a/doc/classes/VisualShaderNode.xml b/doc/classes/VisualShaderNode.xml
index cc6394e2da7..5b82d202462 100644
--- a/doc/classes/VisualShaderNode.xml
+++ b/doc/classes/VisualShaderNode.xml
@@ -61,6 +61,9 @@
+
+ Represents the index of the frame this node is linked to. If set to [code]-1[/code] the node is not linked to any frame.
+
Sets the output port index which will be showed for preview. If set to [code]-1[/code] no port will be open for preview.
diff --git a/doc/classes/VisualShaderNodeComment.xml b/doc/classes/VisualShaderNodeComment.xml
deleted file mode 100644
index b4063409b91..00000000000
--- a/doc/classes/VisualShaderNodeComment.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
-
- A comment node to be placed on visual shader graph.
-
-
- A resizable rectangular area with changeable [member title] and [member description] used for better organizing of other visual shader nodes.
-
-
-
-
-
- An additional description which placed below the title.
-
-
- A title of the node.
-
-
-
diff --git a/doc/classes/VisualShaderNodeFrame.xml b/doc/classes/VisualShaderNodeFrame.xml
new file mode 100644
index 00000000000..3126a56abe1
--- /dev/null
+++ b/doc/classes/VisualShaderNodeFrame.xml
@@ -0,0 +1,46 @@
+
+
+
+ A frame other visual shader nodes can be attached to for better organization.
+
+
+ A rectangular frame that can be used to group visual shader nodes together to improve organization.
+ Nodes attached to the frame will move with it when it is dragged and it can automatically resize to enclose all attached nodes.
+ Its title, description and color can be customized.
+
+
+
+
+
+
+
+
+ Adds a node to the list of nodes attached to the frame. Should not be called directly, use the [method VisualShader.attach_node_to_frame] method instead.
+
+
+
+
+
+
+ Removes a node from the list of nodes attached to the frame. Should not be called directly, use the [method VisualShader.detach_node_from_frame] method instead.
+
+
+
+
+
+ The list of nodes attached to the frame.
+
+
+ If [code]true[/code], the frame will automatically resize to enclose all attached nodes.
+
+
+ The color of the frame when [member tint_color_enabled] is [code]true[/code].
+
+
+ If [code]true[/code], the frame will be tinted with the color specified in [member tint_color].
+
+
+ The title of the node.
+
+
+
diff --git a/editor/icons/GraphFrame.svg b/editor/icons/GraphFrame.svg
new file mode 100644
index 00000000000..cd25c847561
--- /dev/null
+++ b/editor/icons/GraphFrame.svg
@@ -0,0 +1 @@
+
diff --git a/editor/plugins/animation_blend_tree_editor_plugin.cpp b/editor/plugins/animation_blend_tree_editor_plugin.cpp
index e75bb454aea..a7c64b79db1 100644
--- a/editor/plugins/animation_blend_tree_editor_plugin.cpp
+++ b/editor/plugins/animation_blend_tree_editor_plugin.cpp
@@ -170,7 +170,7 @@ void AnimationNodeBlendTreeEditor::update_graph() {
name->connect("focus_exited", callable_mp(this, &AnimationNodeBlendTreeEditor::_node_renamed_focus_out).bind(agnode), CONNECT_DEFERRED);
name->connect("text_changed", callable_mp(this, &AnimationNodeBlendTreeEditor::_node_rename_lineedit_changed), CONNECT_DEFERRED);
base = 1;
- agnode->set_closable(true);
+ agnode->set_deletable(true);
if (!read_only) {
Button *delete_button = memnew(Button);
@@ -541,7 +541,7 @@ void AnimationNodeBlendTreeEditor::_delete_nodes_request(const TypedArray(graph->get_child(i));
if (gn && gn->is_selected()) {
Ref anode = blend_tree->get_node(gn->get_name());
- if (anode->is_closable()) {
+ if (anode->is_deletable()) {
to_erase.push_back(gn->get_name());
}
}
@@ -549,7 +549,7 @@ void AnimationNodeBlendTreeEditor::_delete_nodes_request(const TypedArray anode = blend_tree->get_node(p_nodes[i]);
- if (anode->is_closable()) {
+ if (anode->is_deletable()) {
to_erase.push_back(p_nodes[i]);
}
}
diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp
index c83c47577d3..71af1dadd9e 100644
--- a/editor/plugins/visual_shader_editor_plugin.cpp
+++ b/editor/plugins/visual_shader_editor_plugin.cpp
@@ -48,6 +48,7 @@
#include "scene/gui/button.h"
#include "scene/gui/check_box.h"
#include "scene/gui/code_edit.h"
+#include "scene/gui/color_picker.h"
#include "scene/gui/graph_edit.h"
#include "scene/gui/menu_button.h"
#include "scene/gui/option_button.h"
@@ -120,6 +121,11 @@ void VisualShaderGraphPlugin::_bind_methods() {
ClassDB::bind_method("set_expression", &VisualShaderGraphPlugin::set_expression);
ClassDB::bind_method("update_curve", &VisualShaderGraphPlugin::update_curve);
ClassDB::bind_method("update_curve_xyz", &VisualShaderGraphPlugin::update_curve_xyz);
+ ClassDB::bind_method(D_METHOD("attach_node_to_frame", "type", "id", "frame"), &VisualShaderGraphPlugin::attach_node_to_frame);
+ ClassDB::bind_method(D_METHOD("detach_node_from_frame", "type", "id"), &VisualShaderGraphPlugin::detach_node_from_frame);
+ ClassDB::bind_method(D_METHOD("set_frame_color_enabled", "type", "id", "enabled"), &VisualShaderGraphPlugin::set_frame_color_enabled);
+ ClassDB::bind_method(D_METHOD("set_frame_color", "type", "id", "color"), &VisualShaderGraphPlugin::set_frame_color);
+ ClassDB::bind_method(D_METHOD("set_frame_autoshrink_enabled", "type", "id", "enabled"), &VisualShaderGraphPlugin::set_frame_autoshrink_enabled);
}
void VisualShaderGraphPlugin::set_editor(VisualShaderEditor *p_editor) {
@@ -191,7 +197,9 @@ void VisualShaderGraphPlugin::update_node(VisualShader::Type p_type, int p_node_
return;
}
remove_node(p_type, p_node_id, true);
- add_node(p_type, p_node_id, true);
+ add_node(p_type, p_node_id, true, true);
+
+ // TODO: Restore focus here?
}
void VisualShaderGraphPlugin::set_input_port_default_value(VisualShader::Type p_type, int p_node_id, int p_port_id, const Variant &p_value) {
@@ -282,6 +290,92 @@ void VisualShaderGraphPlugin::set_expression(VisualShader::Type p_type, int p_no
links[p_node_id].expression_edit->set_text(p_expression);
}
+void VisualShaderGraphPlugin::attach_node_to_frame(VisualShader::Type p_type, int p_node_id, int p_frame_id) {
+ if (p_type != visual_shader->get_shader_type() || !links.has(p_node_id) || !links.has(p_frame_id)) {
+ return;
+ }
+
+ GraphEdit *graph = editor->graph;
+ if (!graph) {
+ return;
+ }
+
+ // Get the hint label and hide it before attaching the node to prevent resizing issues with the frame.
+ GraphFrame *frame = Object::cast_to(links[p_frame_id].graph_element);
+ ERR_FAIL_COND_MSG(!frame, "VisualShader node to attach to is not a frame node.");
+
+ Label *frame_hint_label = Object::cast_to