Merge pull request #51952 from Jummit/refactor-graphedit-connections
Refactor GraphEdit connections
This commit is contained in:
commit
8cae1294b8
3 changed files with 43 additions and 60 deletions
|
@ -10,6 +10,14 @@
|
||||||
<tutorials>
|
<tutorials>
|
||||||
</tutorials>
|
</tutorials>
|
||||||
<methods>
|
<methods>
|
||||||
|
<method name="_get_connection_line" qualifiers="virtual">
|
||||||
|
<return type="PackedVector2Array" />
|
||||||
|
<argument index="0" name="from" type="Vector2" />
|
||||||
|
<argument index="1" name="to" type="Vector2" />
|
||||||
|
<description>
|
||||||
|
Virtual method which can be overridden to customize how connections are drawn.
|
||||||
|
</description>
|
||||||
|
</method>
|
||||||
<method name="add_valid_connection_type">
|
<method name="add_valid_connection_type">
|
||||||
<return type="void" />
|
<return type="void" />
|
||||||
<argument index="0" name="from_type" type="int" />
|
<argument index="0" name="from_type" type="int" />
|
||||||
|
@ -64,6 +72,14 @@
|
||||||
Removes the connection between the [code]from_port[/code] slot of the [code]from[/code] GraphNode and the [code]to_port[/code] slot of the [code]to[/code] GraphNode. If the connection does not exist, no connection is removed.
|
Removes the connection between the [code]from_port[/code] slot of the [code]from[/code] GraphNode and the [code]to_port[/code] slot of the [code]to[/code] GraphNode. If the connection does not exist, no connection is removed.
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
|
<method name="get_connection_line">
|
||||||
|
<return type="PackedVector2Array" />
|
||||||
|
<argument index="0" name="from" type="Vector2" />
|
||||||
|
<argument index="1" name="to" type="Vector2" />
|
||||||
|
<description>
|
||||||
|
Returns the points which would make up a connection between [code]from[/code] and [code]to[/code].
|
||||||
|
</description>
|
||||||
|
</method>
|
||||||
<method name="get_connection_list" qualifiers="const">
|
<method name="get_connection_list" qualifiers="const">
|
||||||
<return type="Array" />
|
<return type="Array" />
|
||||||
<description>
|
<description>
|
||||||
|
|
|
@ -805,63 +805,28 @@ bool GraphEdit::is_in_hot_zone(const Vector2 &pos, const Vector2 &p_mouse_pos, c
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Vector2>
|
PackedVector2Array GraphEdit::get_connection_line(const Vector2 &p_from, const Vector2 &p_to) {
|
||||||
static _FORCE_INLINE_ Vector2 _bezier_interp(real_t t, Vector2 start, Vector2 control_1, Vector2 control_2, Vector2 end) {
|
if (get_script_instance() && get_script_instance()->get_script().is_valid() && get_script_instance()->has_method("_get_connection_line")) {
|
||||||
/* Formula from Wikipedia article on Bezier curves. */
|
return get_script_instance()->call("_get_connection_line", p_from, p_to);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector2 c1 = Vector2(cp_offset * zoom, 0);
|
Curve2D curve;
|
||||||
Vector2 c2 = Vector2(-cp_offset * zoom, 0);
|
|
||||||
|
|
||||||
int lines = 0;
|
|
||||||
|
|
||||||
Vector<Point2> points;
|
|
||||||
Vector<Color> colors;
|
Vector<Color> colors;
|
||||||
points.push_back(p_from);
|
curve.add_point(p_from);
|
||||||
colors.push_back(p_color);
|
curve.set_point_out(0, Vector2(60, 0));
|
||||||
_bake_segment2d(points, colors, 0, 1, p_from, c1, p_to, c2, 0, 3, 9, 3, p_color, p_to_color, lines);
|
curve.add_point(p_to);
|
||||||
points.push_back(p_to);
|
curve.set_point_in(1, Vector2(-60, 0));
|
||||||
colors.push_back(p_to_color);
|
return curve.tessellate();
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
Vector<Vector2> points = get_connection_line(p_from, p_to);
|
||||||
|
Vector<Color> colors;
|
||||||
|
float length = p_from.distance_to(p_to);
|
||||||
|
for (int i = 0; i < points.size(); i++) {
|
||||||
|
float d = p_from.distance_to(points[i]) / length;
|
||||||
|
colors.push_back(p_color.lerp(p_to_color, d));
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef TOOLS_ENABLED
|
#ifdef TOOLS_ENABLED
|
||||||
p_where->draw_polyline_colors(points, colors, Math::floor(p_width * EDSCALE), lines_antialiased);
|
p_where->draw_polyline_colors(points, colors, Math::floor(p_width * EDSCALE), lines_antialiased);
|
||||||
|
@ -913,7 +878,7 @@ void GraphEdit::_connections_layer_draw() {
|
||||||
color = color.lerp(activity_color, E->get().activity);
|
color = color.lerp(activity_color, E->get().activity);
|
||||||
tocolor = tocolor.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);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (to_erase.size()) {
|
while (to_erase.size()) {
|
||||||
|
@ -952,7 +917,7 @@ void GraphEdit::_top_layer_draw() {
|
||||||
if (!connecting_out) {
|
if (!connecting_out) {
|
||||||
SWAP(pos, topos);
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (box_selecting) {
|
if (box_selecting) {
|
||||||
|
@ -1056,7 +1021,7 @@ void GraphEdit::_minimap_draw() {
|
||||||
from_color = from_color.lerp(activity_color, E.activity);
|
from_color = from_color.lerp(activity_color, E.activity);
|
||||||
to_color = to_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, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw the "camera" viewport.
|
// Draw the "camera" viewport.
|
||||||
|
@ -2179,6 +2144,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("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("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("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("set_zoom", "zoom"), &GraphEdit::set_zoom);
|
||||||
ClassDB::bind_method(D_METHOD("get_zoom"), &GraphEdit::get_zoom);
|
ClassDB::bind_method(D_METHOD("get_zoom"), &GraphEdit::get_zoom);
|
||||||
|
@ -2227,6 +2193,8 @@ void GraphEdit::_bind_methods() {
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("set_selected", "node"), &GraphEdit::set_selected);
|
ClassDB::bind_method(D_METHOD("set_selected", "node"), &GraphEdit::set_selected);
|
||||||
|
|
||||||
|
BIND_VMETHOD(MethodInfo(Variant::PACKED_VECTOR2_ARRAY, "_get_connection_line", PropertyInfo(Variant::VECTOR2, "from"), PropertyInfo(Variant::VECTOR2, "to")));
|
||||||
|
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "right_disconnects"), "set_right_disconnects", "is_right_disconnects_enabled");
|
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::VECTOR2, "scroll_offset"), "set_scroll_ofs", "get_scroll_ofs");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "snap_distance"), "set_snap", "get_snap");
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "snap_distance"), "set_snap", "get_snap");
|
||||||
|
|
|
@ -169,9 +169,8 @@ private:
|
||||||
float lines_thickness = 2.0f;
|
float lines_thickness = 2.0f;
|
||||||
bool lines_antialiased = true;
|
bool lines_antialiased = true;
|
||||||
|
|
||||||
void _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;
|
PackedVector2Array get_connection_line(const Vector2 &p_from, const Vector2 &p_to);
|
||||||
|
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);
|
||||||
void _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 = 1.0);
|
|
||||||
|
|
||||||
void _graph_node_raised(Node *p_gn);
|
void _graph_node_raised(Node *p_gn);
|
||||||
void _graph_node_moved(Node *p_gn);
|
void _graph_node_moved(Node *p_gn);
|
||||||
|
|
Loading…
Reference in a new issue