diff --git a/doc/classes/CanvasItem.xml b/doc/classes/CanvasItem.xml index 8efa1adae8c..2dc86f2a3f1 100644 --- a/doc/classes/CanvasItem.xml +++ b/doc/classes/CanvasItem.xml @@ -41,6 +41,8 @@ + + Draws an arc between the given angles. The larger the value of [code]point_count[/code], the smoother the curve. @@ -181,6 +183,8 @@ + + Draws interconnected line segments with a uniform [code]color[/code] and [code]width[/code]. @@ -194,6 +198,8 @@ + + Draws interconnected line segments with a uniform [code]width[/code] and segment-by-segment coloring. Colors assigned to line segments match by index between [code]points[/code] and [code]colors[/code]. diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp index ad02aaade5a..96810e87079 100644 --- a/scene/gui/graph_edit.cpp +++ b/scene/gui/graph_edit.cpp @@ -659,9 +659,9 @@ void GraphEdit::_draw_cos_line(CanvasItem *p_where, const Vector2 &p_from, const colors.push_back(p_to_color); #ifdef TOOLS_ENABLED - p_where->draw_polyline_colors(points, colors, Math::floor(2 * EDSCALE)); + p_where->draw_polyline_colors(points, colors, Math::floor(2 * EDSCALE), true); #else - p_where->draw_polyline_colors(points, colors, 2); + p_where->draw_polyline_colors(points, colors, 2, true); #endif } diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp index e6c35352f56..a982e6a42b3 100644 --- a/scene/main/canvas_item.cpp +++ b/scene/main/canvas_item.cpp @@ -742,21 +742,21 @@ void CanvasItem::draw_line(const Point2 &p_from, const Point2 &p_to, const Color RenderingServer::get_singleton()->canvas_item_add_line(canvas_item, p_from, p_to, p_color, p_width); } -void CanvasItem::draw_polyline(const Vector &p_points, const Color &p_color, float p_width) { +void CanvasItem::draw_polyline(const Vector &p_points, const Color &p_color, float p_width, bool p_antialiased) { ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); Vector colors; colors.push_back(p_color); - RenderingServer::get_singleton()->canvas_item_add_polyline(canvas_item, p_points, colors, p_width); + RenderingServer::get_singleton()->canvas_item_add_polyline(canvas_item, p_points, colors, p_width, p_antialiased); } -void CanvasItem::draw_polyline_colors(const Vector &p_points, const Vector &p_colors, float p_width) { +void CanvasItem::draw_polyline_colors(const Vector &p_points, const Vector &p_colors, float p_width, bool p_antialiased) { ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); - RenderingServer::get_singleton()->canvas_item_add_polyline(canvas_item, p_points, p_colors, p_width); + RenderingServer::get_singleton()->canvas_item_add_polyline(canvas_item, p_points, p_colors, p_width, p_antialiased); } -void CanvasItem::draw_arc(const Vector2 &p_center, float p_radius, float p_start_angle, float p_end_angle, int p_point_count, const Color &p_color, float p_width) { +void CanvasItem::draw_arc(const Vector2 &p_center, float p_radius, float p_start_angle, float p_end_angle, int p_point_count, const Color &p_color, float p_width, bool p_antialiased) { Vector points; points.resize(p_point_count); const float delta_angle = p_end_angle - p_start_angle; @@ -765,7 +765,7 @@ void CanvasItem::draw_arc(const Vector2 &p_center, float p_radius, float p_start points.set(i, p_center + Vector2(Math::cos(theta), Math::sin(theta)) * p_radius); } - draw_polyline(points, p_color, p_width); + draw_polyline(points, p_color, p_width, p_antialiased); } void CanvasItem::draw_multiline(const Vector &p_points, const Color &p_color, float p_width) { @@ -1144,9 +1144,9 @@ void CanvasItem::_bind_methods() { //ClassDB::bind_method(D_METHOD("get_transform"),&CanvasItem::get_transform); ClassDB::bind_method(D_METHOD("draw_line", "from", "to", "color", "width"), &CanvasItem::draw_line, DEFVAL(1.0)); - ClassDB::bind_method(D_METHOD("draw_polyline", "points", "color", "width"), &CanvasItem::draw_polyline, DEFVAL(1.0)); - ClassDB::bind_method(D_METHOD("draw_polyline_colors", "points", "colors", "width"), &CanvasItem::draw_polyline_colors, DEFVAL(1.0)); - ClassDB::bind_method(D_METHOD("draw_arc", "center", "radius", "start_angle", "end_angle", "point_count", "color", "width"), &CanvasItem::draw_arc, DEFVAL(1.0)); + 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 412ef8079b4..74353cd4b56 100644 --- a/scene/main/canvas_item.h +++ b/scene/main/canvas_item.h @@ -331,9 +331,9 @@ public: /* DRAWING API */ void draw_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width = 1.0); - void draw_polyline(const Vector &p_points, const Color &p_color, float p_width = 1.0); - void draw_polyline_colors(const Vector &p_points, const Vector &p_colors, float p_width = 1.0); - void draw_arc(const Vector2 &p_center, float p_radius, float p_start_angle, float p_end_angle, int p_point_count, const Color &p_color, float p_width = 1.0); + void draw_polyline(const Vector &p_points, const Color &p_color, float p_width = 1.0, bool p_antialiased = false); + void draw_polyline_colors(const Vector &p_points, const Vector &p_colors, float p_width = 1.0, bool p_antialiased = false); + void draw_arc(const Vector2 &p_center, float p_radius, float p_start_angle, float p_end_angle, int p_point_count, const Color &p_color, float p_width = 1.0, bool p_antialiased = false); void draw_multiline(const Vector &p_points, const Color &p_color, float p_width = 1.0); void draw_multiline_colors(const Vector &p_points, const Vector &p_colors, float p_width = 1.0); void draw_rect(const Rect2 &p_rect, const Color &p_color, bool p_filled = true, float p_width = 1.0); diff --git a/servers/rendering/rendering_server_canvas.cpp b/servers/rendering/rendering_server_canvas.cpp index ffc1ec391d6..d518d709c50 100644 --- a/servers/rendering/rendering_server_canvas.cpp +++ b/servers/rendering/rendering_server_canvas.cpp @@ -540,59 +540,60 @@ void RenderingServerCanvas::canvas_item_add_line(RID p_item, const Point2 &p_fro } } -void RenderingServerCanvas::canvas_item_add_polyline(RID p_item, const Vector &p_points, const Vector &p_colors, float p_width) { +void RenderingServerCanvas::canvas_item_add_polyline(RID p_item, const Vector &p_points, const Vector &p_colors, float p_width, bool p_antialiased) { ERR_FAIL_COND(p_points.size() < 2); Item *canvas_item = canvas_item_owner.getornull(p_item); ERR_FAIL_COND(!canvas_item); + Vector indices; + int pc = p_points.size(); + int pc2 = pc * 2; + + Vector2 prev_t; + int j2; + Item::CommandPolygon *pline = canvas_item->alloc_command(); ERR_FAIL_COND(!pline); - if (true || p_width <= 1) { -#define TODO make thick lines possible - Vector indices; - int pc = p_points.size(); - indices.resize((pc - 1) * 2); - { - int *iptr = indices.ptrw(); - for (int i = 0; i < (pc - 1); i++) { - iptr[i * 2 + 0] = i; - iptr[i * 2 + 1] = i + 1; - } - } + PackedColorArray colors; + PackedVector2Array points; - pline->primitive = RS::PRIMITIVE_LINES; - pline->polygon.create(indices, p_points, p_colors); - } else { -#if 0 - //make a trianglestrip for drawing the line... - Vector2 prev_t; - pline->triangles.resize(p_points.size() * 2); - if (p_antialiased) { - pline->lines.resize(p_points.size() * 2); - } + colors.resize(pc2); + points.resize(pc2); - if (p_colors.size() == 0) { - pline->triangle_colors.push_back(Color(1, 1, 1, 1)); - if (p_antialiased) { - pline->line_colors.push_back(Color(1, 1, 1, 1)); - } - } else if (p_colors.size() == 1) { - pline->triangle_colors = p_colors; - pline->line_colors = p_colors; - } else { - if (p_colors.size() != p_points.size()) { - pline->triangle_colors.push_back(p_colors[0]); - pline->line_colors.push_back(p_colors[0]); - } else { - pline->triangle_colors.resize(pline->triangles.size()); - pline->line_colors.resize(pline->lines.size()); - } - } + Vector2 *points_ptr = points.ptrw(); + Color *colors_ptr = colors.ptrw(); - for (int i = 0; i < p_points.size(); i++) { + if (p_antialiased) { + PackedColorArray colors_top; + PackedVector2Array points_top; + + colors_top.resize(pc2); + points_top.resize(pc2); + + PackedColorArray colors_bottom; + PackedVector2Array points_bottom; + + colors_bottom.resize(pc2); + points_bottom.resize(pc2); + + Item::CommandPolygon *pline_top = canvas_item->alloc_command(); + ERR_FAIL_COND(!pline_top); + + Item::CommandPolygon *pline_bottom = canvas_item->alloc_command(); + ERR_FAIL_COND(!pline_bottom); + + //make three trianglestrip's for drawing the antialiased line... + + Vector2 *points_top_ptr = points_top.ptrw(); + Vector2 *points_bottom_ptr = points_bottom.ptrw(); + + Color *colors_top_ptr = colors_top.ptrw(); + Color *colors_bottom_ptr = colors_bottom.ptrw(); + + for (int i = 0, j = 0; i < pc; i++, j += 2) { Vector2 t; - if (i == p_points.size() - 1) { + if (i == pc - 1) { t = prev_t; } else { t = (p_points[i + 1] - p_points[i]).normalized().tangent(); @@ -601,29 +602,73 @@ void RenderingServerCanvas::canvas_item_add_polyline(RID p_item, const Vectorlines.write[i] = p_points[i] + tangent; - pline->lines.write[p_points.size() * 2 - i - 1] = p_points[i] - tangent; - if (pline->line_colors.size() > 1) { - pline->line_colors.write[i] = p_colors[i]; - pline->line_colors.write[p_points.size() * 2 - i - 1] = p_colors[i]; - } - } + points_ptr[j] = pos + tangent; + points_ptr[j2] = pos - tangent; - pline->triangles.write[i * 2 + 0] = p_points[i] + tangent; - pline->triangles.write[i * 2 + 1] = p_points[i] - tangent; + points_top_ptr[j] = pos + tangent + tangent; + points_top_ptr[j2] = pos + tangent; - if (pline->triangle_colors.size() > 1) { - pline->triangle_colors.write[i * 2 + 0] = p_colors[i]; - pline->triangle_colors.write[i * 2 + 1] = p_colors[i]; - } + points_bottom_ptr[j] = pos - tangent; + points_bottom_ptr[j2] = pos - tangent - tangent; + + Color color = p_colors[i]; + Color color2 = Color(color.r, color.g, color.b, 0); + + colors_ptr[j] = color; + colors_ptr[j2] = color; + + colors_top_ptr[j] = color2; + colors_top_ptr[j2] = color; + + colors_bottom_ptr[j] = color; + colors_bottom_ptr[j2] = color2; + + prev_t = t; + } + + pline_top->primitive = RS::PRIMITIVE_TRIANGLE_STRIP; + pline_top->polygon.create(indices, points_top, colors_top); + + pline_bottom->primitive = RS::PRIMITIVE_TRIANGLE_STRIP; + pline_bottom->polygon.create(indices, points_bottom, colors_bottom); + } else { + //make a trianglestrip for drawing the line... + + for (int i = 0, j = 0; i < pc; i++, j += 2) { + Vector2 t; + if (i == pc - 1) { + t = prev_t; + } else { + t = (p_points[i + 1] - p_points[i]).normalized().tangent(); + if (i == 0) { + prev_t = t; + } + } + + j2 = j + 1; + + Vector2 tangent = ((t + prev_t).normalized()) * p_width * 0.5; + + Vector2 pos = p_points[j]; + Color color = p_colors[j2]; + + points_ptr[j] = pos + tangent; + points_ptr[j2] = pos - tangent; + + colors_ptr[j] = color; + colors_ptr[j2] = color; prev_t = t; } -#endif } + + pline->primitive = RS::PRIMITIVE_TRIANGLE_STRIP; + pline->polygon.create(indices, points, colors); } void RenderingServerCanvas::canvas_item_add_multiline(RID p_item, const Vector &p_points, const Vector &p_colors, float p_width) { diff --git a/servers/rendering/rendering_server_canvas.h b/servers/rendering/rendering_server_canvas.h index 83b76539c40..89f511a8fbd 100644 --- a/servers/rendering/rendering_server_canvas.h +++ b/servers/rendering/rendering_server_canvas.h @@ -192,7 +192,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); - void canvas_item_add_polyline(RID p_item, const Vector &p_points, const Vector &p_colors, float p_width = 1.0); + 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/rendering_server_raster.h b/servers/rendering/rendering_server_raster.h index 413fcda5817..67666cee9f7 100644 --- a/servers/rendering/rendering_server_raster.h +++ b/servers/rendering/rendering_server_raster.h @@ -717,7 +717,7 @@ public: BIND2(canvas_item_set_draw_behind_parent, RID, bool) BIND5(canvas_item_add_line, RID, const Point2 &, const Point2 &, const Color &, float) - BIND4(canvas_item_add_polyline, RID, const Vector &, const Vector &, float) + BIND5(canvas_item_add_polyline, RID, const Vector &, const Vector &, float, bool) BIND4(canvas_item_add_multiline, RID, const Vector &, const Vector &, float) BIND3(canvas_item_add_rect, RID, const Rect2 &, const Color &) BIND4(canvas_item_add_circle, RID, const Point2 &, float, const Color &) diff --git a/servers/rendering/rendering_server_wrap_mt.h b/servers/rendering/rendering_server_wrap_mt.h index d33bdb043a0..320c0a8f203 100644 --- a/servers/rendering/rendering_server_wrap_mt.h +++ b/servers/rendering/rendering_server_wrap_mt.h @@ -618,7 +618,7 @@ public: FUNC2(canvas_item_set_draw_behind_parent, RID, bool) FUNC5(canvas_item_add_line, RID, const Point2 &, const Point2 &, const Color &, float) - FUNC4(canvas_item_add_polyline, RID, const Vector &, const Vector &, float) + FUNC5(canvas_item_add_polyline, RID, const Vector &, const Vector &, float, bool) FUNC4(canvas_item_add_multiline, RID, const Vector &, const Vector &, float) FUNC3(canvas_item_add_rect, RID, const Rect2 &, const Color &) FUNC4(canvas_item_add_circle, RID, const Point2 &, float, const Color &) diff --git a/servers/rendering_server.h b/servers/rendering_server.h index 236112c3fb6..f21d876bf00 100644 --- a/servers/rendering_server.h +++ b/servers/rendering_server.h @@ -1175,7 +1175,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) = 0; - virtual void canvas_item_add_polyline(RID p_item, const Vector &p_points, const Vector &p_colors, float p_width = 1.0) = 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;