From 728c51e3627a0f6d6ff60314b47b636221ffa4f2 Mon Sep 17 00:00:00 2001 From: kleonc <9283098+kleonc@users.noreply.github.com> Date: Thu, 19 Jan 2023 13:38:15 +0100 Subject: [PATCH] CanvasItem::draw_polyline Support thin polylines drawn using line strip --- doc/classes/CanvasItem.xml | 15 ++++++---- doc/classes/RenderingServer.xml | 2 +- scene/main/canvas_item.cpp | 6 ++-- scene/main/canvas_item.h | 6 ++-- servers/rendering/renderer_canvas_cull.cpp | 35 ++++++++++++++++++++-- servers/rendering/renderer_canvas_cull.h | 2 +- servers/rendering_server.cpp | 2 +- servers/rendering_server.h | 2 +- 8 files changed, 51 insertions(+), 19 deletions(-) diff --git a/doc/classes/CanvasItem.xml b/doc/classes/CanvasItem.xml index 5279574d5a17..c3c768c12dbb 100644 --- a/doc/classes/CanvasItem.xml +++ b/doc/classes/CanvasItem.xml @@ -42,10 +42,11 @@ - + - Draws an unfilled arc between the given angles. The larger the value of [param point_count], the smoother the curve. See also [method draw_circle]. + Draws an unfilled arc between the given angles with a uniform [param color] and [param width] and optional antialiasing (supported only for positive [param width]). The larger the value of [param point_count], the smoother the curve. See also [method draw_circle]. + If [param width] is negative, then the arc is drawn using [constant RenderingServer.PRIMITIVE_LINE_STRIP]. This means that when the CanvasItem is scaled, the arc will remain thin. If this behavior is not desired, then pass a positive [param width] like [code]1.0[/code]. The arc is drawn from [param start_angle] towards the value of [param end_angle] so in clockwise direction if [code]start_angle < end_angle[/code] and counter-clockwise otherwise. Passing the same angles but in reversed order will produce the same arc. If absolute difference of [param start_angle] and [param end_angle] is greater than [constant @GDScript.TAU] radians, then a full circle arc is drawn (i.e. arc will not overlap itself). @@ -243,20 +244,22 @@ - + - Draws interconnected line segments with a uniform [param color] and [param width] and optional antialiasing. When drawing large amounts of lines, this is faster than using individual [method draw_line] calls. To draw disconnected lines, use [method draw_multiline] instead. See also [method draw_polygon]. + Draws interconnected line segments with a uniform [param color] and [param width] and optional antialiasing (supported only for positive [param width]). When drawing large amounts of lines, this is faster than using individual [method draw_line] calls. To draw disconnected lines, use [method draw_multiline] instead. See also [method draw_polygon]. + If [param width] is negative, the polyline is drawn using [constant RenderingServer.PRIMITIVE_LINE_STRIP]. This means that when the CanvasItem is scaled, the polyline will remain thin. If this behavior is not desired, then pass a positive [param width] like [code]1.0[/code]. - + - Draws interconnected line segments with a uniform [param width] and segment-by-segment coloring, and optional antialiasing. Colors assigned to line segments match by index between [param points] and [param colors]. When drawing large amounts of lines, this is faster than using individual [method draw_line] calls. To draw disconnected lines, use [method draw_multiline_colors] instead. See also [method draw_polygon]. + Draws interconnected line segments with a uniform [param width] and segment-by-segment coloring, and optional antialiasing (supported only for positive [param width]). Colors assigned to line segments match by index between [param points] and [param colors]. When drawing large amounts of lines, this is faster than using individual [method draw_line] calls. To draw disconnected lines, use [method draw_multiline_colors] instead. See also [method draw_polygon]. + If [param width] is negative, then the polyline is drawn using [constant RenderingServer.PRIMITIVE_LINE_STRIP]. This means that when the CanvasItem is scaled, the polyline will remain thin. If this behavior is not desired, then pass a positive [param width] like [code]1.0[/code]. diff --git a/doc/classes/RenderingServer.xml b/doc/classes/RenderingServer.xml index 33170e6606f9..272bddfe2e45 100644 --- a/doc/classes/RenderingServer.xml +++ b/doc/classes/RenderingServer.xml @@ -291,7 +291,7 @@ - + diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp index a4af7988c675..ed5be67abc3d 100644 --- a/scene/main/canvas_item.cpp +++ b/scene/main/canvas_item.cpp @@ -973,9 +973,9 @@ void CanvasItem::_bind_methods() { ClassDB::bind_method(D_METHOD("draw_line", "from", "to", "color", "width", "antialiased"), &CanvasItem::draw_line, DEFVAL(-1.0), DEFVAL(false)); ClassDB::bind_method(D_METHOD("draw_dashed_line", "from", "to", "color", "width", "dash", "aligned"), &CanvasItem::draw_dashed_line, DEFVAL(-1.0), DEFVAL(2.0), DEFVAL(true)); - ClassDB::bind_method(D_METHOD("draw_polyline", "points", "color", "width", "antialiased"), &CanvasItem::draw_polyline, DEFVAL(1.0), DEFVAL(false)); - ClassDB::bind_method(D_METHOD("draw_polyline_colors", "points", "colors", "width", "antialiased"), &CanvasItem::draw_polyline_colors, DEFVAL(1.0), DEFVAL(false)); - ClassDB::bind_method(D_METHOD("draw_arc", "center", "radius", "start_angle", "end_angle", "point_count", "color", "width", "antialiased"), &CanvasItem::draw_arc, DEFVAL(1.0), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("draw_polyline", "points", "color", "width", "antialiased"), &CanvasItem::draw_polyline, DEFVAL(-1.0), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("draw_polyline_colors", "points", "colors", "width", "antialiased"), &CanvasItem::draw_polyline_colors, DEFVAL(-1.0), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("draw_arc", "center", "radius", "start_angle", "end_angle", "point_count", "color", "width", "antialiased"), &CanvasItem::draw_arc, DEFVAL(-1.0), DEFVAL(false)); ClassDB::bind_method(D_METHOD("draw_multiline", "points", "color", "width"), &CanvasItem::draw_multiline, DEFVAL(-1.0)); ClassDB::bind_method(D_METHOD("draw_multiline_colors", "points", "colors", "width"), &CanvasItem::draw_multiline_colors, DEFVAL(-1.0)); ClassDB::bind_method(D_METHOD("draw_rect", "rect", "color", "filled", "width"), &CanvasItem::draw_rect, DEFVAL(true), DEFVAL(-1.0)); diff --git a/scene/main/canvas_item.h b/scene/main/canvas_item.h index b2c12b2ea2a8..a7e9fc3c79a4 100644 --- a/scene/main/canvas_item.h +++ b/scene/main/canvas_item.h @@ -249,9 +249,9 @@ public: void draw_dashed_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, real_t p_width = -1.0, real_t p_dash = 2.0, bool p_aligned = true); void draw_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, real_t p_width = -1.0, bool p_antialiased = false); - void draw_polyline(const Vector &p_points, const Color &p_color, real_t p_width = 1.0, bool p_antialiased = false); - void draw_polyline_colors(const Vector &p_points, const Vector &p_colors, real_t p_width = 1.0, bool p_antialiased = false); - void draw_arc(const Vector2 &p_center, real_t p_radius, real_t p_start_angle, real_t p_end_angle, int p_point_count, const Color &p_color, real_t p_width = 1.0, bool p_antialiased = false); + void draw_polyline(const Vector &p_points, const Color &p_color, real_t p_width = -1.0, bool p_antialiased = false); + void draw_polyline_colors(const Vector &p_points, const Vector &p_colors, real_t p_width = -1.0, bool p_antialiased = false); + void draw_arc(const Vector2 &p_center, real_t p_radius, real_t p_start_angle, real_t p_end_angle, int p_point_count, const Color &p_color, real_t p_width = -1.0, bool p_antialiased = false); void draw_multiline(const Vector &p_points, const Color &p_color, real_t p_width = -1.0); void draw_multiline_colors(const Vector &p_points, const Vector &p_colors, real_t p_width = -1.0); void draw_rect(const Rect2 &p_rect, const Color &p_color, bool p_filled = true, real_t p_width = -1.0); diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp index 4265ee5518f3..b9e3c4f303ec 100644 --- a/servers/rendering/renderer_canvas_cull.cpp +++ b/servers/rendering/renderer_canvas_cull.cpp @@ -821,6 +821,38 @@ void RendererCanvasCull::canvas_item_add_polyline(RID p_item, const Vector indices; int point_count = p_points.size(); + + Item::CommandPolygon *pline = canvas_item->alloc_command(); + ERR_FAIL_COND(!pline); + + if (p_width < 0) { + if (p_antialiased) { + WARN_PRINT("Antialiasing is not supported for thin polylines drawn using line strips (`p_width < 0`)."); + } + + pline->primitive = RS::PRIMITIVE_LINE_STRIP; + + if (p_colors.size() == 1 || p_colors.size() == point_count) { + pline->polygon.create(indices, p_points, p_colors); + } else { + Vector colors; + if (p_colors.is_empty()) { + colors.push_back(color); + } else { + colors.resize(point_count); + Color *colors_ptr = colors.ptrw(); + for (int i = 0; i < point_count; i++) { + if (i < p_colors.size()) { + color = p_colors[i]; + } + colors_ptr[i] = color; + } + } + pline->polygon.create(indices, p_points, colors); + } + return; + } + int polyline_point_count = point_count * 2; bool loop = p_points[0].is_equal_approx(p_points[point_count - 1]); @@ -845,9 +877,6 @@ void RendererCanvasCull::canvas_item_add_polyline(RID p_item, const Vectoralloc_command(); - ERR_FAIL_COND(!pline); - PackedColorArray colors; PackedVector2Array points; diff --git a/servers/rendering/renderer_canvas_cull.h b/servers/rendering/renderer_canvas_cull.h index 2494ddf63197..1106fc4f1ed5 100644 --- a/servers/rendering/renderer_canvas_cull.h +++ b/servers/rendering/renderer_canvas_cull.h @@ -222,7 +222,7 @@ public: void canvas_item_set_update_when_visible(RID p_item, bool p_update); void canvas_item_add_line(RID p_item, const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width = -1.0, bool p_antialiased = false); - void canvas_item_add_polyline(RID p_item, const Vector &p_points, const Vector &p_colors, float p_width = 1.0, bool p_antialiased = false); + void canvas_item_add_polyline(RID p_item, const Vector &p_points, const Vector &p_colors, float p_width = -1.0, bool p_antialiased = false); void canvas_item_add_multiline(RID p_item, const Vector &p_points, const Vector &p_colors, float p_width = -1.0); void canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color); void canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color); diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index e24b2af976b6..485cfae4b426 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -2593,7 +2593,7 @@ void RenderingServer::_bind_methods() { /* Primitives */ ClassDB::bind_method(D_METHOD("canvas_item_add_line", "item", "from", "to", "color", "width", "antialiased"), &RenderingServer::canvas_item_add_line, DEFVAL(-1.0), DEFVAL(false)); - ClassDB::bind_method(D_METHOD("canvas_item_add_polyline", "item", "points", "colors", "width", "antialiased"), &RenderingServer::canvas_item_add_polyline, DEFVAL(1.0), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("canvas_item_add_polyline", "item", "points", "colors", "width", "antialiased"), &RenderingServer::canvas_item_add_polyline, DEFVAL(-1.0), DEFVAL(false)); ClassDB::bind_method(D_METHOD("canvas_item_add_rect", "item", "rect", "color"), &RenderingServer::canvas_item_add_rect); ClassDB::bind_method(D_METHOD("canvas_item_add_circle", "item", "pos", "radius", "color"), &RenderingServer::canvas_item_add_circle); ClassDB::bind_method(D_METHOD("canvas_item_add_texture_rect", "item", "rect", "texture", "tile", "modulate", "transpose"), &RenderingServer::canvas_item_add_texture_rect, DEFVAL(false), DEFVAL(Color(1, 1, 1)), DEFVAL(false)); diff --git a/servers/rendering_server.h b/servers/rendering_server.h index 4b51099ef0ab..231139e9df1a 100644 --- a/servers/rendering_server.h +++ b/servers/rendering_server.h @@ -1335,7 +1335,7 @@ public: }; virtual void canvas_item_add_line(RID p_item, const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width = -1.0, bool p_antialiased = false) = 0; - virtual void canvas_item_add_polyline(RID p_item, const Vector &p_points, const Vector &p_colors, float p_width = 1.0, bool p_antialiased = false) = 0; + virtual void canvas_item_add_polyline(RID p_item, const Vector &p_points, const Vector &p_colors, float p_width = -1.0, bool p_antialiased = false) = 0; virtual void canvas_item_add_multiline(RID p_item, const Vector &p_points, const Vector &p_colors, float p_width = -1.0) = 0; virtual void canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color) = 0; virtual void canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color) = 0;