Merge pull request #86158 from Geometror/ge-connection-rework
Rework `GraphEdit` connections (drawing, API, optimizations)
This commit is contained in:
commit
66b0bd9203
10 changed files with 700 additions and 259 deletions
|
@ -119,6 +119,10 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static real_t get_distance_to_segment(const Vector2 &p_point, const Vector2 *p_segment) {
|
||||||
|
return p_point.distance_to(get_closest_point_to_segment(p_point, p_segment));
|
||||||
|
}
|
||||||
|
|
||||||
static bool is_point_in_triangle(const Vector2 &s, const Vector2 &a, const Vector2 &b, const Vector2 &c) {
|
static bool is_point_in_triangle(const Vector2 &s, const Vector2 &a, const Vector2 &b, const Vector2 &c) {
|
||||||
Vector2 an = a - s;
|
Vector2 an = a - s;
|
||||||
Vector2 bn = b - s;
|
Vector2 bn = b - s;
|
||||||
|
@ -249,6 +253,28 @@ public:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool segment_intersects_rect(const Vector2 &p_from, const Vector2 &p_to, const Rect2 &p_rect) {
|
||||||
|
if (p_rect.has_point(p_from) || p_rect.has_point(p_to)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Vector2 rect_points[4] = {
|
||||||
|
p_rect.position,
|
||||||
|
p_rect.position + Vector2(p_rect.size.x, 0),
|
||||||
|
p_rect.position + p_rect.size,
|
||||||
|
p_rect.position + Vector2(0, p_rect.size.y)
|
||||||
|
};
|
||||||
|
|
||||||
|
// Check if any of the rect's edges intersect the segment.
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
if (segment_intersects_segment(p_from, p_to, rect_points[i], rect_points[(i + 1) % 4], nullptr)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
enum PolyBooleanOperation {
|
enum PolyBooleanOperation {
|
||||||
OPERATION_UNION,
|
OPERATION_UNION,
|
||||||
OPERATION_DIFFERENCE,
|
OPERATION_DIFFERENCE,
|
||||||
|
|
|
@ -143,7 +143,22 @@
|
||||||
[b]Note:[/b] This method suppresses any other connection request signals apart from [signal connection_drag_ended].
|
[b]Note:[/b] This method suppresses any other connection request signals apart from [signal connection_drag_ended].
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
<method name="get_connection_line">
|
<method name="get_closest_connection_at_point" qualifiers="const">
|
||||||
|
<return type="Dictionary" />
|
||||||
|
<param index="0" name="point" type="Vector2" />
|
||||||
|
<param index="1" name="max_distance" type="float" default="4.0" />
|
||||||
|
<description>
|
||||||
|
Returns the closest connection to the given point in screen space. If no connection is found within [param max_distance] pixels, an empty [Dictionary] is returned.
|
||||||
|
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].
|
||||||
|
For example, getting a connection at a given mouse position can be achieved like this:
|
||||||
|
[codeblocks]
|
||||||
|
[gdscript]
|
||||||
|
var connection = get_closest_connection_at_point(mouse_event.get_position())
|
||||||
|
[/gdscript]
|
||||||
|
[/codeblocks]
|
||||||
|
</description>
|
||||||
|
</method>
|
||||||
|
<method name="get_connection_line" qualifiers="const">
|
||||||
<return type="PackedVector2Array" />
|
<return type="PackedVector2Array" />
|
||||||
<param index="0" name="from_node" type="Vector2" />
|
<param index="0" name="from_node" type="Vector2" />
|
||||||
<param index="1" name="to_node" type="Vector2" />
|
<param index="1" name="to_node" type="Vector2" />
|
||||||
|
@ -154,7 +169,14 @@
|
||||||
<method name="get_connection_list" qualifiers="const">
|
<method name="get_connection_list" qualifiers="const">
|
||||||
<return type="Dictionary[]" />
|
<return type="Dictionary[]" />
|
||||||
<description>
|
<description>
|
||||||
Returns an Array containing the list of connections. 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 an [Array] containing the list of connections. 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].
|
||||||
|
</description>
|
||||||
|
</method>
|
||||||
|
<method name="get_connections_intersecting_with_rect" qualifiers="const">
|
||||||
|
<return type="Dictionary[]" />
|
||||||
|
<param index="0" name="rect" type="Rect2" />
|
||||||
|
<description>
|
||||||
|
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].
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
<method name="get_menu_hbox">
|
<method name="get_menu_hbox">
|
||||||
|
@ -233,7 +255,7 @@
|
||||||
<member name="connection_lines_curvature" type="float" setter="set_connection_lines_curvature" getter="get_connection_lines_curvature" default="0.5">
|
<member name="connection_lines_curvature" type="float" setter="set_connection_lines_curvature" getter="get_connection_lines_curvature" default="0.5">
|
||||||
The curvature of the lines between the nodes. 0 results in straight lines.
|
The curvature of the lines between the nodes. 0 results in straight lines.
|
||||||
</member>
|
</member>
|
||||||
<member name="connection_lines_thickness" type="float" setter="set_connection_lines_thickness" getter="get_connection_lines_thickness" default="2.0">
|
<member name="connection_lines_thickness" type="float" setter="set_connection_lines_thickness" getter="get_connection_lines_thickness" default="4.0">
|
||||||
The thickness of the lines between the nodes.
|
The thickness of the lines between the nodes.
|
||||||
</member>
|
</member>
|
||||||
<member name="focus_mode" type="int" setter="set_focus_mode" getter="get_focus_mode" overrides="Control" enum="Control.FocusMode" default="2" />
|
<member name="focus_mode" type="int" setter="set_focus_mode" getter="get_focus_mode" overrides="Control" enum="Control.FocusMode" default="2" />
|
||||||
|
@ -417,7 +439,16 @@
|
||||||
</constants>
|
</constants>
|
||||||
<theme_items>
|
<theme_items>
|
||||||
<theme_item name="activity" data_type="color" type="Color" default="Color(1, 1, 1, 1)">
|
<theme_item name="activity" data_type="color" type="Color" default="Color(1, 1, 1, 1)">
|
||||||
Color of the connection's activity (see [method set_connection_activity]).
|
Color the connection line is interpolated to based on the activity value of a connection (see [method set_connection_activity]).
|
||||||
|
</theme_item>
|
||||||
|
<theme_item name="connection_hover_tint_color" data_type="color" type="Color" default="Color(0, 0, 0, 0.3)">
|
||||||
|
Color which is blended with the connection line when the mouse is hovering over it.
|
||||||
|
</theme_item>
|
||||||
|
<theme_item name="connection_rim_color" data_type="color" type="Color" default="Color(0.1, 0.1, 0.1, 0.6)">
|
||||||
|
Color of the rim around each connection line used for making intersecting lines more distinguishable.
|
||||||
|
</theme_item>
|
||||||
|
<theme_item name="connection_valid_target_tint_color" data_type="color" type="Color" default="Color(1, 1, 1, 0.4)">
|
||||||
|
Color which is blended with the connection line when the currently dragged connection is hovering over a valid target port.
|
||||||
</theme_item>
|
</theme_item>
|
||||||
<theme_item name="grid_major" data_type="color" type="Color" default="Color(1, 1, 1, 0.2)">
|
<theme_item name="grid_major" data_type="color" type="Color" default="Color(1, 1, 1, 0.2)">
|
||||||
Color of major grid lines/dots.
|
Color of major grid lines/dots.
|
||||||
|
|
|
@ -1442,6 +1442,10 @@ void EditorThemeManager::_populate_standard_styles(const Ref<EditorTheme> &p_the
|
||||||
p_theme->set_color("selection_stroke", "GraphEdit", p_theme->get_color(SNAME("box_selection_stroke_color"), EditorStringName(Editor)));
|
p_theme->set_color("selection_stroke", "GraphEdit", p_theme->get_color(SNAME("box_selection_stroke_color"), EditorStringName(Editor)));
|
||||||
p_theme->set_color("activity", "GraphEdit", p_config.accent_color);
|
p_theme->set_color("activity", "GraphEdit", p_config.accent_color);
|
||||||
|
|
||||||
|
p_theme->set_color("connection_hover_tint_color", "GraphEdit", p_config.dark_theme ? Color(0, 0, 0, 0.3) : Color(1, 1, 1, 0.3));
|
||||||
|
p_theme->set_color("connection_valid_target_tint_color", "GraphEdit", p_config.dark_theme ? Color(1, 1, 1, 0.4) : Color(0, 0, 0, 0.4));
|
||||||
|
p_theme->set_color("connection_rim_color", "GraphEdit", p_config.tree_panel_style->get_bg_color());
|
||||||
|
|
||||||
p_theme->set_icon("zoom_out", "GraphEdit", p_theme->get_icon(SNAME("ZoomLess"), EditorStringName(EditorIcons)));
|
p_theme->set_icon("zoom_out", "GraphEdit", p_theme->get_icon(SNAME("ZoomLess"), EditorStringName(EditorIcons)));
|
||||||
p_theme->set_icon("zoom_in", "GraphEdit", p_theme->get_icon(SNAME("ZoomMore"), EditorStringName(EditorIcons)));
|
p_theme->set_icon("zoom_in", "GraphEdit", p_theme->get_icon(SNAME("ZoomMore"), EditorStringName(EditorIcons)));
|
||||||
p_theme->set_icon("zoom_reset", "GraphEdit", p_theme->get_icon(SNAME("ZoomReset"), EditorStringName(EditorIcons)));
|
p_theme->set_icon("zoom_reset", "GraphEdit", p_theme->get_icon(SNAME("ZoomReset"), EditorStringName(EditorIcons)));
|
||||||
|
|
|
@ -59,3 +59,10 @@ Validate extension JSON: Error: Field 'classes/TileMap/methods/get_collision_vis
|
||||||
Validate extension JSON: Error: Field 'classes/TileMap/methods/get_navigation_visibility_mode': is_const changed value in new API, from false to true.
|
Validate extension JSON: Error: Field 'classes/TileMap/methods/get_navigation_visibility_mode': is_const changed value in new API, from false to true.
|
||||||
|
|
||||||
Two TileMap getters were made const. No adjustments should be necessary.
|
Two TileMap getters were made const. No adjustments should be necessary.
|
||||||
|
|
||||||
|
|
||||||
|
GH-86158
|
||||||
|
--------
|
||||||
|
Validate extension JSON: Error: Field 'classes/GraphEdit/methods/get_connection_line': is_const changed value in new API, from false to true.
|
||||||
|
|
||||||
|
get_connection_line was made const.
|
||||||
|
|
|
@ -38,9 +38,14 @@ void GraphEdit::_set_arrange_nodes_button_hidden_bind_compat_81582(bool p_enable
|
||||||
set_show_arrange_button(!p_enable);
|
set_show_arrange_button(!p_enable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PackedVector2Array GraphEdit::_get_connection_line_bind_compat_86158(const Vector2 &p_from, const Vector2 &p_to) {
|
||||||
|
return get_connection_line(p_from, p_to);
|
||||||
|
}
|
||||||
|
|
||||||
void GraphEdit::_bind_compatibility_methods() {
|
void GraphEdit::_bind_compatibility_methods() {
|
||||||
ClassDB::bind_compatibility_method(D_METHOD("is_arrange_nodes_button_hidden"), &GraphEdit::_is_arrange_nodes_button_hidden_bind_compat_81582);
|
ClassDB::bind_compatibility_method(D_METHOD("is_arrange_nodes_button_hidden"), &GraphEdit::_is_arrange_nodes_button_hidden_bind_compat_81582);
|
||||||
ClassDB::bind_compatibility_method(D_METHOD("set_arrange_nodes_button_hidden", "enable"), &GraphEdit::_set_arrange_nodes_button_hidden_bind_compat_81582);
|
ClassDB::bind_compatibility_method(D_METHOD("set_arrange_nodes_button_hidden", "enable"), &GraphEdit::_set_arrange_nodes_button_hidden_bind_compat_81582);
|
||||||
|
ClassDB::bind_compatibility_method(D_METHOD("get_connection_line", "from_node", "to_node"), &GraphEdit::_get_connection_line_bind_compat_86158);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -39,6 +39,7 @@ class GraphEdit;
|
||||||
class GraphEditArranger;
|
class GraphEditArranger;
|
||||||
class HScrollBar;
|
class HScrollBar;
|
||||||
class Label;
|
class Label;
|
||||||
|
class Line2D;
|
||||||
class PanelContainer;
|
class PanelContainer;
|
||||||
class SpinBox;
|
class SpinBox;
|
||||||
class ViewPanner;
|
class ViewPanner;
|
||||||
|
@ -112,12 +113,25 @@ class GraphEdit : public Control {
|
||||||
GDCLASS(GraphEdit, Control);
|
GDCLASS(GraphEdit, Control);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
struct Connection {
|
struct Connection : RefCounted {
|
||||||
StringName from_node;
|
StringName from_node;
|
||||||
StringName to_node;
|
StringName to_node;
|
||||||
int from_port = 0;
|
int from_port = 0;
|
||||||
int to_port = 0;
|
int to_port = 0;
|
||||||
float activity = 0.0;
|
float activity = 0.0;
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct Cache {
|
||||||
|
bool dirty = true;
|
||||||
|
Vector2 from_pos; // In graph space.
|
||||||
|
Vector2 to_pos; // In graph space.
|
||||||
|
Color from_color;
|
||||||
|
Color to_color;
|
||||||
|
Rect2 aabb; // In local screen space.
|
||||||
|
Line2D *line = nullptr; // In local screen space.
|
||||||
|
} _cache;
|
||||||
|
|
||||||
|
friend class GraphEdit;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Should be in sync with ControlScheme in ViewPanner.
|
// Should be in sync with ControlScheme in ViewPanner.
|
||||||
|
@ -184,15 +198,15 @@ private:
|
||||||
GridPattern grid_pattern = GRID_PATTERN_LINES;
|
GridPattern grid_pattern = GRID_PATTERN_LINES;
|
||||||
|
|
||||||
bool connecting = false;
|
bool connecting = false;
|
||||||
String connecting_from;
|
StringName connecting_from_node;
|
||||||
bool connecting_out = false;
|
bool connecting_from_output = false;
|
||||||
int connecting_index = 0;
|
|
||||||
int connecting_type = 0;
|
int connecting_type = 0;
|
||||||
Color connecting_color;
|
Color connecting_color;
|
||||||
bool connecting_target = false;
|
Vector2 connecting_to_point; // In local screen space.
|
||||||
Vector2 connecting_to;
|
bool connecting_target_valid = false;
|
||||||
StringName connecting_target_to;
|
StringName connecting_target_node;
|
||||||
int connecting_target_index = 0;
|
int connecting_from_port_index = 0;
|
||||||
|
int connecting_target_port_index = 0;
|
||||||
|
|
||||||
bool just_disconnected = false;
|
bool just_disconnected = false;
|
||||||
bool connecting_valid = false;
|
bool connecting_valid = false;
|
||||||
|
@ -222,18 +236,28 @@ private:
|
||||||
bool right_disconnects = false;
|
bool right_disconnects = false;
|
||||||
bool updating = false;
|
bool updating = false;
|
||||||
bool awaiting_scroll_offset_update = false;
|
bool awaiting_scroll_offset_update = false;
|
||||||
List<Connection> connections;
|
|
||||||
|
|
||||||
float lines_thickness = 2.0f;
|
List<Ref<Connection>> connections;
|
||||||
|
HashMap<StringName, List<Ref<Connection>>> connection_map;
|
||||||
|
Ref<Connection> hovered_connection;
|
||||||
|
|
||||||
|
float lines_thickness = 4.0f;
|
||||||
float lines_curvature = 0.5f;
|
float lines_curvature = 0.5f;
|
||||||
bool lines_antialiased = true;
|
bool lines_antialiased = true;
|
||||||
|
|
||||||
PanelContainer *menu_panel = nullptr;
|
PanelContainer *menu_panel = nullptr;
|
||||||
HBoxContainer *menu_hbox = nullptr;
|
HBoxContainer *menu_hbox = nullptr;
|
||||||
Control *connections_layer = nullptr;
|
Control *connections_layer = nullptr;
|
||||||
GraphEditFilter *top_layer = nullptr;
|
|
||||||
|
GraphEditFilter *top_connection_layer = nullptr; // Draws a dragged connection. Necessary since the connection line shader can't be applied to the whole top layer.
|
||||||
|
Line2D *dragged_connection_line = nullptr;
|
||||||
|
Control *top_layer = nullptr; // Used for drawing the box selection rect. Contains the minimap, menu panel and the scrollbars.
|
||||||
|
|
||||||
GraphEditMinimap *minimap = nullptr;
|
GraphEditMinimap *minimap = nullptr;
|
||||||
|
|
||||||
|
static Ref<Shader> default_connections_shader;
|
||||||
|
Ref<Shader> connections_shader;
|
||||||
|
|
||||||
Ref<GraphEditArranger> arranger;
|
Ref<GraphEditArranger> arranger;
|
||||||
|
|
||||||
HashSet<ConnectionType, ConnectionType> valid_connection_types;
|
HashSet<ConnectionType, ConnectionType> valid_connection_types;
|
||||||
|
@ -248,6 +272,10 @@ private:
|
||||||
Color grid_minor;
|
Color grid_minor;
|
||||||
|
|
||||||
Color activity_color;
|
Color activity_color;
|
||||||
|
Color connection_hover_tint_color;
|
||||||
|
Color connection_valid_target_tint_color;
|
||||||
|
Color connection_rim_color;
|
||||||
|
|
||||||
Color selection_fill;
|
Color selection_fill;
|
||||||
Color selection_stroke;
|
Color selection_stroke;
|
||||||
|
|
||||||
|
@ -274,30 +302,35 @@ private:
|
||||||
void _zoom_plus();
|
void _zoom_plus();
|
||||||
void _update_zoom_label();
|
void _update_zoom_label();
|
||||||
|
|
||||||
void _draw_connection_line(CanvasItem *p_where, const Vector2 &p_from, const Vector2 &p_to, const Color &p_color, const Color &p_to_color, float p_width, float p_zoom);
|
|
||||||
|
|
||||||
void _graph_element_selected(Node *p_node);
|
void _graph_element_selected(Node *p_node);
|
||||||
void _graph_element_deselected(Node *p_node);
|
void _graph_element_deselected(Node *p_node);
|
||||||
void _graph_element_moved_to_front(Node *p_node);
|
void _graph_element_moved_to_front(Node *p_node);
|
||||||
void _graph_element_resized(Vector2 p_new_minsize, Node *p_node);
|
void _graph_element_resized(Vector2 p_new_minsize, Node *p_node);
|
||||||
void _graph_element_moved(Node *p_node);
|
void _graph_element_moved(Node *p_node);
|
||||||
void _graph_node_slot_updated(int p_index, Node *p_node);
|
void _graph_node_slot_updated(int p_index, Node *p_node);
|
||||||
|
void _graph_node_rect_changed(GraphNode *p_node);
|
||||||
|
|
||||||
void _update_scroll();
|
void _update_scroll();
|
||||||
void _update_scroll_offset();
|
void _update_scroll_offset();
|
||||||
void _scroll_moved(double);
|
void _scroll_moved(double);
|
||||||
virtual void gui_input(const Ref<InputEvent> &p_ev) override;
|
virtual void gui_input(const Ref<InputEvent> &p_ev) override;
|
||||||
void _top_layer_input(const Ref<InputEvent> &p_ev);
|
void _top_connection_layer_input(const Ref<InputEvent> &p_ev);
|
||||||
|
|
||||||
|
float _get_shader_line_width();
|
||||||
|
void _draw_minimap_connection_line(CanvasItem *p_where, const Vector2 &p_from, const Vector2 &p_to, const Color &p_color, const Color &p_to_color);
|
||||||
|
void _invalidate_connection_line_cache();
|
||||||
|
void _update_top_connection_layer();
|
||||||
|
void _update_connections();
|
||||||
|
|
||||||
|
void _top_layer_draw();
|
||||||
|
void _minimap_draw();
|
||||||
|
void _draw_grid();
|
||||||
|
|
||||||
bool is_in_port_hotzone(const Vector2 &p_pos, const Vector2 &p_mouse_pos, const Vector2i &p_port_size, bool p_left);
|
bool is_in_port_hotzone(const Vector2 &p_pos, const Vector2 &p_mouse_pos, const Vector2i &p_port_size, bool p_left);
|
||||||
|
|
||||||
void _top_layer_draw();
|
|
||||||
void _connections_layer_draw();
|
|
||||||
void _minimap_draw();
|
|
||||||
|
|
||||||
void _draw_grid();
|
|
||||||
|
|
||||||
TypedArray<Dictionary> _get_connection_list() const;
|
TypedArray<Dictionary> _get_connection_list() const;
|
||||||
|
Dictionary _get_closest_connection_at_point(const Vector2 &p_point, float p_max_distance = 4.0) const;
|
||||||
|
TypedArray<Dictionary> _get_connections_intersecting_with_rect(const Rect2 &p_rect) const;
|
||||||
|
|
||||||
friend class GraphEditFilter;
|
friend class GraphEditFilter;
|
||||||
bool _filter_input(const Point2 &p_point);
|
bool _filter_input(const Point2 &p_point);
|
||||||
|
@ -313,6 +346,7 @@ private:
|
||||||
#ifndef DISABLE_DEPRECATED
|
#ifndef DISABLE_DEPRECATED
|
||||||
bool _is_arrange_nodes_button_hidden_bind_compat_81582() const;
|
bool _is_arrange_nodes_button_hidden_bind_compat_81582() const;
|
||||||
void _set_arrange_nodes_button_hidden_bind_compat_81582(bool p_enable);
|
void _set_arrange_nodes_button_hidden_bind_compat_81582(bool p_enable);
|
||||||
|
PackedVector2Array _get_connection_line_bind_compat_86158(const Vector2 &p_from, const Vector2 &p_to);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -336,6 +370,9 @@ protected:
|
||||||
GDVIRTUAL4R(bool, _is_node_hover_valid, StringName, int, StringName, int);
|
GDVIRTUAL4R(bool, _is_node_hover_valid, StringName, int, StringName, int);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
static void init_shaders();
|
||||||
|
static void finish_shaders();
|
||||||
|
|
||||||
virtual CursorShape get_cursor_shape(const Point2 &p_pos = Point2i()) const override;
|
virtual CursorShape get_cursor_shape(const Point2 &p_pos = Point2i()) const override;
|
||||||
|
|
||||||
PackedStringArray get_configuration_warnings() const override;
|
PackedStringArray get_configuration_warnings() const override;
|
||||||
|
@ -344,12 +381,17 @@ public:
|
||||||
bool is_node_connected(const StringName &p_from, int p_from_port, const StringName &p_to, int p_to_port);
|
bool is_node_connected(const StringName &p_from, int p_from_port, const StringName &p_to, int p_to_port);
|
||||||
void disconnect_node(const StringName &p_from, int p_from_port, const StringName &p_to, int p_to_port);
|
void disconnect_node(const StringName &p_from, int p_from_port, const StringName &p_to, int p_to_port);
|
||||||
void clear_connections();
|
void clear_connections();
|
||||||
void force_connection_drag_end();
|
|
||||||
|
|
||||||
virtual PackedVector2Array get_connection_line(const Vector2 &p_from, const Vector2 &p_to);
|
void force_connection_drag_end();
|
||||||
|
const List<Ref<Connection>> &get_connection_list() const;
|
||||||
|
virtual PackedVector2Array get_connection_line(const Vector2 &p_from, const Vector2 &p_to) const;
|
||||||
|
Ref<Connection> get_closest_connection_at_point(const Vector2 &p_point, float p_max_distance = 4.0) const;
|
||||||
|
List<Ref<Connection>> get_connections_intersecting_with_rect(const Rect2 &p_rect) const;
|
||||||
|
|
||||||
virtual bool is_node_hover_valid(const StringName &p_from, int p_from_port, const StringName &p_to, int p_to_port);
|
virtual bool is_node_hover_valid(const StringName &p_from, int p_from_port, const StringName &p_to, int p_to_port);
|
||||||
|
|
||||||
void set_connection_activity(const StringName &p_from, int p_from_port, const StringName &p_to, int p_to_port, float p_activity);
|
void set_connection_activity(const StringName &p_from, int p_from_port, const StringName &p_to, int p_to_port, float p_activity);
|
||||||
|
void reset_all_connection_activity();
|
||||||
|
|
||||||
void add_valid_connection_type(int p_type, int p_with_type);
|
void add_valid_connection_type(int p_type, int p_with_type);
|
||||||
void remove_valid_connection_type(int p_type, int p_with_type);
|
void remove_valid_connection_type(int p_type, int p_with_type);
|
||||||
|
@ -392,10 +434,10 @@ public:
|
||||||
void set_show_arrange_button(bool p_hidden);
|
void set_show_arrange_button(bool p_hidden);
|
||||||
bool is_showing_arrange_button() const;
|
bool is_showing_arrange_button() const;
|
||||||
|
|
||||||
GraphEditFilter *get_top_layer() const { return top_layer; }
|
Control *get_top_layer() const { return top_layer; }
|
||||||
GraphEditMinimap *get_minimap() const { return minimap; }
|
GraphEditMinimap *get_minimap() const { return minimap; }
|
||||||
|
|
||||||
void get_connection_list(List<Connection> *r_connections) const;
|
void override_connections_shader(const Ref<Shader> &p_shader);
|
||||||
|
|
||||||
void set_right_disconnects(bool p_enable);
|
void set_right_disconnects(bool p_enable);
|
||||||
bool is_right_disconnects_enabled() const;
|
bool is_right_disconnects_enabled() const;
|
||||||
|
|
|
@ -65,8 +65,7 @@ void GraphEditArranger::arrange_nodes() {
|
||||||
float gap_v = 100.0f;
|
float gap_v = 100.0f;
|
||||||
float gap_h = 100.0f;
|
float gap_h = 100.0f;
|
||||||
|
|
||||||
List<GraphEdit::Connection> connection_list;
|
List<Ref<GraphEdit::Connection>> connection_list = graph_edit->get_connection_list();
|
||||||
graph_edit->get_connection_list(&connection_list);
|
|
||||||
|
|
||||||
for (int i = graph_edit->get_child_count() - 1; i >= 0; i--) {
|
for (int i = graph_edit->get_child_count() - 1; i >= 0; i--) {
|
||||||
GraphNode *graph_element = Object::cast_to<GraphNode>(graph_edit->get_child(i));
|
GraphNode *graph_element = Object::cast_to<GraphNode>(graph_edit->get_child(i));
|
||||||
|
@ -77,15 +76,16 @@ void GraphEditArranger::arrange_nodes() {
|
||||||
if (graph_element->is_selected() || arrange_entire_graph) {
|
if (graph_element->is_selected() || arrange_entire_graph) {
|
||||||
selected_nodes.insert(graph_element->get_name());
|
selected_nodes.insert(graph_element->get_name());
|
||||||
HashSet<StringName> s;
|
HashSet<StringName> s;
|
||||||
for (List<GraphEdit::Connection>::Element *E = connection_list.front(); E; E = E->next()) {
|
|
||||||
GraphNode *p_from = Object::cast_to<GraphNode>(node_names[E->get().from_node]);
|
for (const Ref<GraphEdit::Connection> &connection : connection_list) {
|
||||||
if (E->get().to_node == graph_element->get_name() && (p_from->is_selected() || arrange_entire_graph) && E->get().to_node != E->get().from_node) {
|
GraphNode *p_from = Object::cast_to<GraphNode>(node_names[connection->from_node]);
|
||||||
|
if (connection->to_node == graph_element->get_name() && (p_from->is_selected() || arrange_entire_graph) && connection->to_node != connection->from_node) {
|
||||||
if (!s.has(p_from->get_name())) {
|
if (!s.has(p_from->get_name())) {
|
||||||
s.insert(p_from->get_name());
|
s.insert(p_from->get_name());
|
||||||
}
|
}
|
||||||
String s_connection = String(p_from->get_name()) + " " + String(E->get().to_node);
|
String s_connection = String(p_from->get_name()) + " " + String(connection->to_node);
|
||||||
StringName _connection(s_connection);
|
StringName _connection(s_connection);
|
||||||
Pair<int, int> ports(E->get().from_port, E->get().to_port);
|
Pair<int, int> ports(connection->from_port, connection->to_port);
|
||||||
port_info.insert(_connection, ports);
|
port_info.insert(_connection, ports);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -437,31 +437,30 @@ float GraphEditArranger::_calculate_threshold(const StringName &p_v, const Strin
|
||||||
float threshold = p_current_threshold;
|
float threshold = p_current_threshold;
|
||||||
if (p_v == p_w) {
|
if (p_v == p_w) {
|
||||||
int min_order = MAX_ORDER;
|
int min_order = MAX_ORDER;
|
||||||
GraphEdit::Connection incoming;
|
Ref<GraphEdit::Connection> incoming;
|
||||||
List<GraphEdit::Connection> connection_list;
|
List<Ref<GraphEdit::Connection>> connection_list = graph_edit->get_connection_list();
|
||||||
graph_edit->get_connection_list(&connection_list);
|
for (const Ref<GraphEdit::Connection> &connection : connection_list) {
|
||||||
for (List<GraphEdit::Connection>::Element *E = connection_list.front(); E; E = E->next()) {
|
if (connection->to_node == p_w) {
|
||||||
if (E->get().to_node == p_w) {
|
ORDER(connection->from_node, r_layers);
|
||||||
ORDER(E->get().from_node, r_layers);
|
|
||||||
if (min_order > order) {
|
if (min_order > order) {
|
||||||
min_order = order;
|
min_order = order;
|
||||||
incoming = E->get();
|
incoming = connection;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (incoming.from_node != StringName()) {
|
if (incoming.is_valid()) {
|
||||||
GraphNode *gnode_from = Object::cast_to<GraphNode>(r_node_names[incoming.from_node]);
|
GraphNode *gnode_from = Object::cast_to<GraphNode>(r_node_names[incoming->from_node]);
|
||||||
GraphNode *gnode_to = Object::cast_to<GraphNode>(r_node_names[p_w]);
|
GraphNode *gnode_to = Object::cast_to<GraphNode>(r_node_names[p_w]);
|
||||||
Vector2 pos_from = gnode_from->get_output_port_position(incoming.from_port) * graph_edit->get_zoom();
|
Vector2 pos_from = gnode_from->get_output_port_position(incoming->from_port) * graph_edit->get_zoom();
|
||||||
Vector2 pos_to = gnode_to->get_input_port_position(incoming.to_port) * graph_edit->get_zoom();
|
Vector2 pos_to = gnode_to->get_input_port_position(incoming->to_port) * graph_edit->get_zoom();
|
||||||
|
|
||||||
// If connected block node is selected, calculate thershold or add current block to list.
|
// If connected block node is selected, calculate thershold or add current block to list.
|
||||||
if (gnode_from->is_selected()) {
|
if (gnode_from->is_selected()) {
|
||||||
Vector2 connected_block_pos = r_node_positions[r_root[incoming.from_node]];
|
Vector2 connected_block_pos = r_node_positions[r_root[incoming->from_node]];
|
||||||
if (connected_block_pos.y != FLT_MAX) {
|
if (connected_block_pos.y != FLT_MAX) {
|
||||||
//Connected block is placed, calculate threshold.
|
//Connected block is placed, calculate threshold.
|
||||||
threshold = connected_block_pos.y + (real_t)r_inner_shift[incoming.from_node] - (real_t)r_inner_shift[p_w] + pos_from.y - pos_to.y;
|
threshold = connected_block_pos.y + (real_t)r_inner_shift[incoming->from_node] - (real_t)r_inner_shift[p_w] + pos_from.y - pos_to.y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -469,31 +468,30 @@ float GraphEditArranger::_calculate_threshold(const StringName &p_v, const Strin
|
||||||
if (threshold == FLT_MIN && (StringName)r_align[p_w] == p_v) {
|
if (threshold == FLT_MIN && (StringName)r_align[p_w] == p_v) {
|
||||||
// This time, pick an outgoing edge and repeat as above!
|
// This time, pick an outgoing edge and repeat as above!
|
||||||
int min_order = MAX_ORDER;
|
int min_order = MAX_ORDER;
|
||||||
GraphEdit::Connection outgoing;
|
Ref<GraphEdit::Connection> outgoing;
|
||||||
List<GraphEdit::Connection> connection_list;
|
List<Ref<GraphEdit::Connection>> connection_list = graph_edit->get_connection_list();
|
||||||
graph_edit->get_connection_list(&connection_list);
|
for (const Ref<GraphEdit::Connection> &connection : connection_list) {
|
||||||
for (List<GraphEdit::Connection>::Element *E = connection_list.front(); E; E = E->next()) {
|
if (connection->from_node == p_w) {
|
||||||
if (E->get().from_node == p_w) {
|
ORDER(connection->to_node, r_layers);
|
||||||
ORDER(E->get().to_node, r_layers);
|
|
||||||
if (min_order > order) {
|
if (min_order > order) {
|
||||||
min_order = order;
|
min_order = order;
|
||||||
outgoing = E->get();
|
outgoing = connection;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (outgoing.to_node != StringName()) {
|
if (outgoing.is_valid()) {
|
||||||
GraphNode *gnode_from = Object::cast_to<GraphNode>(r_node_names[p_w]);
|
GraphNode *gnode_from = Object::cast_to<GraphNode>(r_node_names[p_w]);
|
||||||
GraphNode *gnode_to = Object::cast_to<GraphNode>(r_node_names[outgoing.to_node]);
|
GraphNode *gnode_to = Object::cast_to<GraphNode>(r_node_names[outgoing->to_node]);
|
||||||
Vector2 pos_from = gnode_from->get_output_port_position(outgoing.from_port) * graph_edit->get_zoom();
|
Vector2 pos_from = gnode_from->get_output_port_position(outgoing->from_port) * graph_edit->get_zoom();
|
||||||
Vector2 pos_to = gnode_to->get_input_port_position(outgoing.to_port) * graph_edit->get_zoom();
|
Vector2 pos_to = gnode_to->get_input_port_position(outgoing->to_port) * graph_edit->get_zoom();
|
||||||
|
|
||||||
// If connected block node is selected, calculate thershold or add current block to list.
|
// If connected block node is selected, calculate thershold or add current block to list.
|
||||||
if (gnode_to->is_selected()) {
|
if (gnode_to->is_selected()) {
|
||||||
Vector2 connected_block_pos = r_node_positions[r_root[outgoing.to_node]];
|
Vector2 connected_block_pos = r_node_positions[r_root[outgoing->to_node]];
|
||||||
if (connected_block_pos.y != FLT_MAX) {
|
if (connected_block_pos.y != FLT_MAX) {
|
||||||
//Connected block is placed. Calculate threshold
|
//Connected block is placed. Calculate threshold
|
||||||
threshold = connected_block_pos.y + (real_t)r_inner_shift[outgoing.to_node] - (real_t)r_inner_shift[p_w] + pos_from.y - pos_to.y;
|
threshold = connected_block_pos.y + (real_t)r_inner_shift[outgoing->to_node] - (real_t)r_inner_shift[p_w] + pos_from.y - pos_to.y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1184,7 +1184,9 @@ void register_scene_types() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (RenderingServer::get_singleton()) {
|
if (RenderingServer::get_singleton()) {
|
||||||
ColorPicker::init_shaders(); // RenderingServer needs to exist for this to succeed.
|
// RenderingServer needs to exist for this to succeed.
|
||||||
|
ColorPicker::init_shaders();
|
||||||
|
GraphEdit::init_shaders();
|
||||||
}
|
}
|
||||||
|
|
||||||
SceneDebugger::initialize();
|
SceneDebugger::initialize();
|
||||||
|
@ -1236,6 +1238,7 @@ void unregister_scene_types() {
|
||||||
ParticleProcessMaterial::finish_shaders();
|
ParticleProcessMaterial::finish_shaders();
|
||||||
CanvasItemMaterial::finish_shaders();
|
CanvasItemMaterial::finish_shaders();
|
||||||
ColorPicker::finish_shaders();
|
ColorPicker::finish_shaders();
|
||||||
|
GraphEdit::finish_shaders();
|
||||||
SceneStringNames::free();
|
SceneStringNames::free();
|
||||||
|
|
||||||
OS::get_singleton()->benchmark_end_measure("Scene", "Unregister Types");
|
OS::get_singleton()->benchmark_end_measure("Scene", "Unregister Types");
|
||||||
|
|
|
@ -1161,6 +1161,9 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
|
||||||
theme->set_color("selection_fill", "GraphEdit", Color(1, 1, 1, 0.3));
|
theme->set_color("selection_fill", "GraphEdit", Color(1, 1, 1, 0.3));
|
||||||
theme->set_color("selection_stroke", "GraphEdit", Color(1, 1, 1, 0.8));
|
theme->set_color("selection_stroke", "GraphEdit", Color(1, 1, 1, 0.8));
|
||||||
theme->set_color("activity", "GraphEdit", Color(1, 1, 1));
|
theme->set_color("activity", "GraphEdit", Color(1, 1, 1));
|
||||||
|
theme->set_color("connection_hover_tint_color", "GraphEdit", Color(0, 0, 0, 0.3));
|
||||||
|
theme->set_color("connection_valid_target_tint_color", "GraphEdit", Color(1, 1, 1, 0.4));
|
||||||
|
theme->set_color("connection_rim_color", "GraphEdit", style_normal_color);
|
||||||
|
|
||||||
// Visual Node Ports
|
// Visual Node Ports
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue