summaryrefslogtreecommitdiff
path: root/scene/gui/graph_edit.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'scene/gui/graph_edit.cpp')
-rw-r--r--scene/gui/graph_edit.cpp115
1 files changed, 43 insertions, 72 deletions
diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp
index fcecbb5fca..0281bc7efb 100644
--- a/scene/gui/graph_edit.cpp
+++ b/scene/gui/graph_edit.cpp
@@ -51,10 +51,6 @@ GraphEditFilter::GraphEditFilter(GraphEdit *p_edit) {
ge = p_edit;
}
-void GraphEditMinimap::_bind_methods() {
- ClassDB::bind_method(D_METHOD("_gui_input"), &GraphEditMinimap::_gui_input);
-}
-
GraphEditMinimap::GraphEditMinimap(GraphEdit *p_edit) {
ge = p_edit;
@@ -148,7 +144,7 @@ Vector2 GraphEditMinimap::_convert_to_graph_position(const Vector2 &p_position)
return graph_position;
}
-void GraphEditMinimap::_gui_input(const Ref<InputEvent> &p_ev) {
+void GraphEditMinimap::gui_input(const Ref<InputEvent> &p_ev) {
ERR_FAIL_COND(p_ev.is_null());
if (!ge->is_minimap_enabled()) {
@@ -805,68 +801,36 @@ bool GraphEdit::is_in_hot_zone(const Vector2 &pos, const Vector2 &p_mouse_pos, c
return true;
}
-template <class Vector2>
-static _FORCE_INLINE_ Vector2 _bezier_interp(real_t t, Vector2 start, Vector2 control_1, Vector2 control_2, Vector2 end) {
- /* Formula from Wikipedia article on Bezier curves. */
- real_t omt = (1.0 - t);
- real_t omt2 = omt * omt;
- real_t omt3 = omt2 * omt;
- real_t t2 = t * t;
- real_t t3 = t2 * t;
-
- return start * omt3 + control_1 * omt2 * t * 3.0 + control_2 * omt * t2 * 3.0 + end * t3;
-}
-
-void GraphEdit::_bake_segment2d(Vector<Vector2> &points, Vector<Color> &colors, float p_begin, float p_end, const Vector2 &p_a, const Vector2 &p_out, const Vector2 &p_b, const Vector2 &p_in, int p_depth, int p_min_depth, int p_max_depth, float p_tol, const Color &p_color, const Color &p_to_color, int &lines) const {
- float mp = p_begin + (p_end - p_begin) * 0.5;
- Vector2 beg = _bezier_interp(p_begin, p_a, p_a + p_out, p_b + p_in, p_b);
- Vector2 mid = _bezier_interp(mp, p_a, p_a + p_out, p_b + p_in, p_b);
- Vector2 end = _bezier_interp(p_end, p_a, p_a + p_out, p_b + p_in, p_b);
-
- Vector2 na = (mid - beg).normalized();
- Vector2 nb = (end - mid).normalized();
- float dp = Math::rad2deg(Math::acos(na.dot(nb)));
-
- if (p_depth >= p_min_depth && (dp < p_tol || p_depth >= p_max_depth)) {
- points.push_back((beg + end) * 0.5);
- colors.push_back(p_color.lerp(p_to_color, mp));
- lines++;
- } else {
- _bake_segment2d(points, colors, p_begin, mp, p_a, p_out, p_b, p_in, p_depth + 1, p_min_depth, p_max_depth, p_tol, p_color, p_to_color, lines);
- _bake_segment2d(points, colors, mp, p_end, p_a, p_out, p_b, p_in, p_depth + 1, p_min_depth, p_max_depth, p_tol, p_color, p_to_color, lines);
+PackedVector2Array GraphEdit::get_connection_line(const Vector2 &p_from, const Vector2 &p_to) {
+ Vector<Vector2> ret;
+ if (GDVIRTUAL_CALL(_get_connection_line, p_from, p_to, ret)) {
+ return ret;
}
-}
-void GraphEdit::_draw_cos_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_bezier_ratio) {
- //cubic bezier code
- float diff = p_to.x - p_from.x;
- float cp_offset;
- int cp_len = get_theme_constant(SNAME("bezier_len_pos")) * p_bezier_ratio;
- int cp_neg_len = get_theme_constant(SNAME("bezier_len_neg")) * p_bezier_ratio;
-
- if (diff > 0) {
- cp_offset = MIN(cp_len, diff * 0.5);
- } else {
- cp_offset = MAX(MIN(cp_len - diff, cp_neg_len), -diff * 0.5);
- }
-
- Vector2 c1 = Vector2(cp_offset * zoom, 0);
- Vector2 c2 = Vector2(-cp_offset * zoom, 0);
-
- int lines = 0;
+ Curve2D curve;
+ Vector<Color> colors;
+ curve.add_point(p_from);
+ curve.set_point_out(0, Vector2(60, 0));
+ curve.add_point(p_to);
+ curve.set_point_in(1, Vector2(-60, 0));
+ return curve.tessellate();
+}
- Vector<Point2> points;
+void GraphEdit::_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) {
+ Vector<Vector2> points = get_connection_line(p_from / p_zoom, p_to / p_zoom);
+ Vector<Vector2> scaled_points;
Vector<Color> colors;
- points.push_back(p_from);
- colors.push_back(p_color);
- _bake_segment2d(points, colors, 0, 1, p_from, c1, p_to, c2, 0, 3, 9, 3, p_color, p_to_color, lines);
- points.push_back(p_to);
- colors.push_back(p_to_color);
+ float length = (p_from / p_zoom).distance_to(p_to / p_zoom);
+ for (int i = 0; i < points.size(); i++) {
+ float d = (p_from / p_zoom).distance_to(points[i]) / length;
+ colors.push_back(p_color.lerp(p_to_color, d));
+ scaled_points.push_back(points[i] * p_zoom);
+ }
#ifdef TOOLS_ENABLED
- p_where->draw_polyline_colors(points, colors, Math::floor(p_width * EDSCALE), lines_antialiased);
+ p_where->draw_polyline_colors(scaled_points, colors, Math::floor(p_width * EDSCALE), lines_antialiased);
#else
- p_where->draw_polyline_colors(points, colors, p_width, lines_antialiased);
+ p_where->draw_polyline_colors(scaled_points, colors, p_width, lines_antialiased);
#endif
}
@@ -913,7 +877,7 @@ void GraphEdit::_connections_layer_draw() {
color = color.lerp(activity_color, E->get().activity);
tocolor = tocolor.lerp(activity_color, E->get().activity);
}
- _draw_cos_line(connections_layer, frompos, topos, color, tocolor, lines_thickness);
+ _draw_connection_line(connections_layer, frompos, topos, color, tocolor, lines_thickness, zoom);
}
while (to_erase.size()) {
@@ -952,7 +916,7 @@ void GraphEdit::_top_layer_draw() {
if (!connecting_out) {
SWAP(pos, topos);
}
- _draw_cos_line(top_layer, pos, topos, col, col, lines_thickness);
+ _draw_connection_line(top_layer, pos, topos, col, col, lines_thickness, zoom);
}
if (box_selecting) {
@@ -1056,7 +1020,7 @@ void GraphEdit::_minimap_draw() {
from_color = from_color.lerp(activity_color, E.activity);
to_color = to_color.lerp(activity_color, E.activity);
}
- _draw_cos_line(minimap, from_position, to_position, from_color, to_color, 1.0, 0.5);
+ _draw_connection_line(minimap, from_position, to_position, from_color, to_color, 0.1, minimap->_convert_from_graph_position(Vector2(zoom, zoom)).length());
}
// Draw the "camera" viewport.
@@ -1080,7 +1044,7 @@ void GraphEdit::set_selected(Node *p_child) {
}
}
-void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) {
+void GraphEdit::gui_input(const Ref<InputEvent> &p_ev) {
ERR_FAIL_COND(p_ev.is_null());
Ref<InputEventMouseMotion> mm = p_ev;
@@ -2048,7 +2012,6 @@ void GraphEdit::arrange_nodes() {
if (gn->is_selected()) {
selected_nodes.insert(gn->get_name());
- origin = origin < gn->get_position_offset() ? origin : gn->get_position_offset();
Set<StringName> s;
for (List<Connection>::Element *E = connections.front(); E; E = E->next()) {
GraphNode *p_from = Object::cast_to<GraphNode>(node_names[E->get().from]);
@@ -2072,6 +2035,11 @@ void GraphEdit::arrange_nodes() {
}
}
+ if (!selected_nodes.size()) {
+ arranging_graph = false;
+ return;
+ }
+
HashMap<int, Vector<StringName>> layers = _layering(selected_nodes, upper_neighbours);
_crossing_minimisation(layers, upper_neighbours);
@@ -2098,16 +2066,16 @@ void GraphEdit::arrange_nodes() {
for (const Set<StringName>::Element *E = block_heads.front(); E; E = E->next()) {
_place_block(E->get(), gap_v, layers, root, align, node_names, inner_shift, sink, shift, new_positions);
}
+ origin.y = Object::cast_to<GraphNode>(node_names[layers[0][0]])->get_position_offset().y - (new_positions[layers[0][0]].y + (float)inner_shift[layers[0][0]]);
+ origin.x = Object::cast_to<GraphNode>(node_names[layers[0][0]])->get_position_offset().x;
for (const Set<StringName>::Element *E = block_heads.front(); E; E = E->next()) {
StringName u = E->get();
- StringName prev = u;
float start_from = origin.y + new_positions[E->get()].y;
do {
Vector2 cal_pos;
cal_pos.y = start_from + (real_t)inner_shift[u];
new_positions.set(u, cal_pos);
- prev = u;
u = align[u];
} while (u != E->get());
}
@@ -2130,10 +2098,11 @@ void GraphEdit::arrange_nodes() {
if (current_node_size == largest_node_size) {
cal_pos.x = start_from;
} else {
- float current_node_start_pos;
- if (current_node_size >= largest_node_size / 2) {
- current_node_start_pos = start_from;
- } else {
+ float current_node_start_pos = start_from;
+ if (current_node_size < largest_node_size / 2) {
+ if (!(i || j)) {
+ start_from -= (largest_node_size - current_node_size);
+ }
current_node_start_pos = start_from + largest_node_size - current_node_size;
}
cal_pos.x = current_node_start_pos;
@@ -2179,6 +2148,7 @@ void GraphEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("add_valid_connection_type", "from_type", "to_type"), &GraphEdit::add_valid_connection_type);
ClassDB::bind_method(D_METHOD("remove_valid_connection_type", "from_type", "to_type"), &GraphEdit::remove_valid_connection_type);
ClassDB::bind_method(D_METHOD("is_valid_connection_type", "from_type", "to_type"), &GraphEdit::is_valid_connection_type);
+ ClassDB::bind_method(D_METHOD("get_connection_line", "from", "to"), &GraphEdit::get_connection_line);
ClassDB::bind_method(D_METHOD("set_zoom", "zoom"), &GraphEdit::set_zoom);
ClassDB::bind_method(D_METHOD("get_zoom"), &GraphEdit::get_zoom);
@@ -2218,7 +2188,6 @@ void GraphEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_right_disconnects", "enable"), &GraphEdit::set_right_disconnects);
ClassDB::bind_method(D_METHOD("is_right_disconnects_enabled"), &GraphEdit::is_right_disconnects_enabled);
- ClassDB::bind_method(D_METHOD("_gui_input"), &GraphEdit::_gui_input);
ClassDB::bind_method(D_METHOD("_update_scroll_offset"), &GraphEdit::_update_scroll_offset);
ClassDB::bind_method(D_METHOD("get_zoom_hbox"), &GraphEdit::get_zoom_hbox);
@@ -2227,6 +2196,8 @@ void GraphEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_selected", "node"), &GraphEdit::set_selected);
+ GDVIRTUAL_BIND(_get_connection_line, "from", "to")
+
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "right_disconnects"), "set_right_disconnects", "is_right_disconnects_enabled");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "scroll_offset"), "set_scroll_ofs", "get_scroll_ofs");
ADD_PROPERTY(PropertyInfo(Variant::INT, "snap_distance"), "set_snap", "get_snap");