diff options
Diffstat (limited to 'scene/gui/graph_edit.cpp')
-rw-r--r-- | scene/gui/graph_edit.cpp | 153 |
1 files changed, 50 insertions, 103 deletions
diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp index fcecbb5fca..35e31be9af 100644 --- a/scene/gui/graph_edit.cpp +++ b/scene/gui/graph_edit.cpp @@ -36,10 +36,6 @@ #include "scene/gui/box_container.h" #include "scene/gui/button.h" -#ifdef TOOLS_ENABLED -#include "editor/editor_scale.h" -#endif - constexpr int MINIMAP_OFFSET = 12; constexpr int MINIMAP_PADDING = 5; @@ -51,10 +47,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 +140,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()) { @@ -360,17 +352,6 @@ void GraphEdit::_graph_node_raised(Node *p_gn) { } else { gn->raise(); } - int first_not_comment = 0; - for (int i = 0; i < get_child_count(); i++) { - GraphNode *gn2 = Object::cast_to<GraphNode>(get_child(i)); - if (gn2 && !gn2->is_comment()) { - first_not_comment = i; - break; - } - } - - move_child(connections_layer, first_not_comment); - top_layer->raise(); emit_signal(SNAME("node_selected"), p_gn); } @@ -451,6 +432,8 @@ void GraphEdit::_notification(int p_what) { snap_button->set_icon(get_theme_icon(SNAME("snap"))); minimap_button->set_icon(get_theme_icon(SNAME("minimap"))); layout_button->set_icon(get_theme_icon(SNAME("layout"))); + + zoom_label->set_custom_minimum_size(Size2(48, 0) * get_theme_default_base_scale()); } if (p_what == NOTIFICATION_READY) { Size2 hmin = h_scroll->get_combined_minimum_size(); @@ -712,7 +695,7 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) { } else if (!just_disconnected) { String from = connecting_from; int from_slot = connecting_index; - Vector2 ofs = Vector2(mb->get_position().x, mb->get_position().y); + Vector2 ofs = mb->get_position(); if (!connecting_out) { emit_signal(SNAME("connection_from_empty"), from, from_slot, ofs); @@ -805,69 +788,33 @@ 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); - } -} - -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); +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; } - 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); -#else - p_where->draw_polyline_colors(points, colors, p_width, lines_antialiased); -#endif + p_where->draw_polyline_colors(scaled_points, colors, Math::floor(p_width * get_theme_default_base_scale()), lines_antialiased); } void GraphEdit::_connections_layer_draw() { @@ -913,7 +860,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 +899,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 +1003,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 +1027,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; @@ -1118,10 +1065,7 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) { if (mm.is_valid() && box_selecting) { box_selecting_to = mm->get_position(); - box_selecting_rect = Rect2(MIN(box_selecting_from.x, box_selecting_to.x), - MIN(box_selecting_from.y, box_selecting_to.y), - ABS(box_selecting_from.x - box_selecting_to.x), - ABS(box_selecting_from.y - box_selecting_to.y)); + box_selecting_rect = Rect2(box_selecting_from.min(box_selecting_to), (box_selecting_from - box_selecting_to).abs()); for (int i = get_child_count() - 1; i >= 0; i--) { GraphNode *gn = Object::cast_to<GraphNode>(get_child(i)); @@ -2048,7 +1992,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 +2015,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 +2046,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 +2078,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; @@ -2145,7 +2094,7 @@ void GraphEdit::arrange_nodes() { largest_node_size = 0.0f; } - emit_signal("begin_node_move"); + emit_signal(SNAME("begin_node_move")); for (const Set<StringName>::Element *E = selected_nodes.front(); E; E = E->next()) { GraphNode *gn = Object::cast_to<GraphNode>(node_names[E->get()]); gn->set_drag(true); @@ -2158,7 +2107,7 @@ void GraphEdit::arrange_nodes() { gn->set_position_offset(pos); gn->set_drag(false); } - emit_signal("end_node_move"); + emit_signal(SNAME("end_node_move")); arranging_graph = false; } @@ -2179,6 +2128,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 +2168,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 +2176,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"); @@ -2275,14 +2226,14 @@ GraphEdit::GraphEdit() { zoom_max = (1 * Math::pow(zoom_step, 4)); top_layer = memnew(GraphEditFilter(this)); - add_child(top_layer); + add_child(top_layer, false, INTERNAL_MODE_BACK); top_layer->set_mouse_filter(MOUSE_FILTER_PASS); top_layer->set_anchors_and_offsets_preset(Control::PRESET_WIDE); top_layer->connect("draw", callable_mp(this, &GraphEdit::_top_layer_draw)); top_layer->connect("gui_input", callable_mp(this, &GraphEdit::_top_layer_input)); connections_layer = memnew(Control); - add_child(connections_layer); + add_child(connections_layer, false, INTERNAL_MODE_FRONT); connections_layer->connect("draw", callable_mp(this, &GraphEdit::_connections_layer_draw)); connections_layer->set_name("CLAYER"); connections_layer->set_disable_visibility_clip(true); // so it can draw freely and be offset @@ -2315,11 +2266,7 @@ GraphEdit::GraphEdit() { zoom_label->set_visible(false); zoom_label->set_v_size_flags(Control::SIZE_SHRINK_CENTER); zoom_label->set_align(Label::ALIGN_CENTER); -#ifdef TOOLS_ENABLED - zoom_label->set_custom_minimum_size(Size2(48, 0) * EDSCALE); -#else zoom_label->set_custom_minimum_size(Size2(48, 0)); -#endif _update_zoom_label(); zoom_minus = memnew(Button); |