Skip to content

Commit

Permalink
Merge pull request #84523 from xiongyaohua/canvasitem_antialiased_for…
Browse files Browse the repository at this point in the history
…_filled

CanvasItem draw implement antialiasing for `circle`, `rect`, `multiline`, and `dashedline`
  • Loading branch information
akien-mga committed May 13, 2024
2 parents c6f1f61 + ed3d311 commit 45ee0fd
Show file tree
Hide file tree
Showing 12 changed files with 353 additions and 76 deletions.
10 changes: 10 additions & 0 deletions doc/classes/CanvasItem.xml
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@
Draws a circle. See also [method draw_arc], [method draw_polyline], and [method draw_polygon].
If [param filled] is [code]true[/code], the circle will be filled with the [param color] specified. If [param filled] is [code]false[/code], the circle will be drawn as a stroke with the [param color] and [param width] specified.
If [param width] is negative, then two-point primitives will be drawn instead of a four-point ones. This means that when the CanvasItem is scaled, the lines will remain thin. If this behavior is not desired, then pass a positive [param width] like [code]1.0[/code].
If [param antialiased] is [code]true[/code], half transparent "feathers" will be attached to the boundary, making outlines smooth.
[b]Note:[/b] [param width] is only effective if [param filled] is [code]false[/code].
</description>
</method>
Expand All @@ -105,9 +106,12 @@
<param index="3" name="width" type="float" default="-1.0" />
<param index="4" name="dash" type="float" default="2.0" />
<param index="5" name="aligned" type="bool" default="true" />
<param index="6" name="antialiased" type="bool" default="false" />
<description>
Draws a dashed line from a 2D point to another, with a given color and width. See also [method draw_multiline] and [method draw_polyline].
If [param width] is negative, then a two-point primitives will be drawn instead of a four-point ones. This means that when the CanvasItem is scaled, the line parts will remain thin. If this behavior is not desired, then pass a positive [param width] like [code]1.0[/code].
If [param antialiased] is [code]true[/code], half transparent "feathers" will be attached to the boundary, making outlines smooth.
[b]Note:[/b] [param antialiased] is only effective if [param width] is greater than [code]0.0[/code].
</description>
</method>
<method name="draw_end_animation">
Expand Down Expand Up @@ -175,19 +179,23 @@
<param index="0" name="points" type="PackedVector2Array" />
<param index="1" name="color" type="Color" />
<param index="2" name="width" type="float" default="-1.0" />
<param index="3" name="antialiased" type="bool" default="false" />
<description>
Draws multiple disconnected lines with a uniform [param width] and [param color]. Each line is defined by two consecutive points from [param points] array, i.e. i-th segment consists of [code]points[2 * i][/code], [code]points[2 * i + 1][/code] endpoints. When drawing large amounts of lines, this is faster than using individual [method draw_line] calls. To draw interconnected lines, use [method draw_polyline] instead.
If [param width] is negative, then two-point primitives will be drawn instead of a four-point ones. This means that when the CanvasItem is scaled, the lines will remain thin. If this behavior is not desired, then pass a positive [param width] like [code]1.0[/code].
[b]Note:[/b] [param antialiased] is only effective if [param width] is greater than [code]0.0[/code].
</description>
</method>
<method name="draw_multiline_colors">
<return type="void" />
<param index="0" name="points" type="PackedVector2Array" />
<param index="1" name="colors" type="PackedColorArray" />
<param index="2" name="width" type="float" default="-1.0" />
<param index="3" name="antialiased" type="bool" default="false" />
<description>
Draws multiple disconnected lines with a uniform [param width] and segment-by-segment coloring. Each segment is defined by two consecutive points from [param points] array and a corresponding color from [param colors] array, i.e. i-th segment consists of [code]points[2 * i][/code], [code]points[2 * i + 1][/code] endpoints and has [code]colors[i][/code] color. When drawing large amounts of lines, this is faster than using individual [method draw_line] calls. To draw interconnected lines, use [method draw_polyline_colors] instead.
If [param width] is negative, then two-point primitives will be drawn instead of a four-point ones. This means that when the CanvasItem is scaled, the lines will remain thin. If this behavior is not desired, then pass a positive [param width] like [code]1.0[/code].
[b]Note:[/b] [param antialiased] is only effective if [param width] is greater than [code]0.0[/code].
</description>
</method>
<method name="draw_multiline_string" qualifiers="const">
Expand Down Expand Up @@ -283,9 +291,11 @@
<param index="1" name="color" type="Color" />
<param index="2" name="filled" type="bool" default="true" />
<param index="3" name="width" type="float" default="-1.0" />
<param index="4" name="antialiased" type="bool" default="false" />
<description>
Draws a rectangle. If [param filled] is [code]true[/code], the rectangle will be filled with the [param color] specified. If [param filled] is [code]false[/code], the rectangle will be drawn as a stroke with the [param color] and [param width] specified. See also [method draw_texture_rect].
If [param width] is negative, then two-point primitives will be drawn instead of a four-point ones. This means that when the CanvasItem is scaled, the lines will remain thin. If this behavior is not desired, then pass a positive [param width] like [code]1.0[/code].
If [param antialiased] is [code]true[/code], half transparent "feathers" will be attached to the boundary, making outlines smooth.
[b]Note:[/b] [param width] is only effective if [param filled] is [code]false[/code].
[b]Note:[/b] Unfilled rectangles drawn with a negative [param width] may not display perfectly. For example, corners may be missing or brighter due to overlapping lines (for a translucent [param color]).
</description>
Expand Down
3 changes: 3 additions & 0 deletions doc/classes/RenderingServer.xml
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@
<param index="1" name="pos" type="Vector2" />
<param index="2" name="radius" type="float" />
<param index="3" name="color" type="Color" />
<param index="4" name="antialiased" type="bool" default="false" />
<description>
Draws a circle on the [CanvasItem] pointed to by the [param item] [RID]. See also [method CanvasItem.draw_circle].
</description>
Expand Down Expand Up @@ -280,6 +281,7 @@
<param index="1" name="points" type="PackedVector2Array" />
<param index="2" name="colors" type="PackedColorArray" />
<param index="3" name="width" type="float" default="-1.0" />
<param index="4" name="antialiased" type="bool" default="false" />
<description>
Draws a 2D multiline on the [CanvasItem] pointed to by the [param item] [RID]. See also [method CanvasItem.draw_multiline] and [method CanvasItem.draw_multiline_colors].
</description>
Expand Down Expand Up @@ -356,6 +358,7 @@
<param index="0" name="item" type="RID" />
<param index="1" name="rect" type="Rect2" />
<param index="2" name="color" type="Color" />
<param index="3" name="antialiased" type="bool" default="false" />
<description>
Draws a rectangle on the [CanvasItem] pointed to by the [param item] [RID]. See also [method CanvasItem.draw_rect].
</description>
Expand Down
13 changes: 13 additions & 0 deletions misc/extension_api_validation/4.2-stable.expected
Original file line number Diff line number Diff line change
Expand Up @@ -344,3 +344,16 @@ GH-91143
Validate extension JSON: Error: Field 'classes/Input/methods/vibrate_handheld/arguments': size changed value in new API, from 1 to 2.

Added optional argument. Compatibility method registered.


GH-84523
--------
Validate extension JSON: Error: Field 'classes/CanvasItem/methods/draw_dashed_line/arguments': size changed value in new API, from 6 to 7.
Validate extension JSON: Error: Field 'classes/CanvasItem/methods/draw_multiline/arguments': size changed value in new API, from 3 to 4.
Validate extension JSON: Error: Field 'classes/CanvasItem/methods/draw_multiline_colors/arguments': size changed value in new API, from 3 to 4.
Validate extension JSON: Error: Field 'classes/CanvasItem/methods/draw_rect/arguments': size changed value in new API, from 4 to 5.
Validate extension JSON: Error: Field 'classes/RenderingServer/methods/canvas_item_add_circle/arguments': size changed value in new API, from 4 to 5.
Validate extension JSON: Error: Field 'classes/RenderingServer/methods/canvas_item_add_multiline/arguments': size changed value in new API, from 4 to 5.
Validate extension JSON: Error: Field 'classes/RenderingServer/methods/canvas_item_add_rect/arguments': size changed value in new API, from 3 to 4.

Optional arguments added. Compatibility methods registered.
24 changes: 22 additions & 2 deletions scene/main/canvas_item.compat.inc
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,32 @@

#ifndef DISABLE_DEPRECATED

void CanvasItem::_draw_circle_compat_84472(const Point2 &p_pos, real_t p_radius, const Color &p_color) {
void CanvasItem::_draw_circle_bind_compat_84472(const Point2 &p_pos, real_t p_radius, const Color &p_color) {
draw_circle(p_pos, p_radius, p_color, true, -1.0, false);
}

void CanvasItem::_draw_rect_bind_compat_84523(const Rect2 &p_rect, const Color &p_color, bool p_filled, real_t p_width) {
draw_rect(p_rect, p_color, p_filled, p_width, false);
}

void CanvasItem::_draw_dashed_line_bind_compat_84523(const Point2 &p_from, const Point2 &p_to, const Color &p_color, real_t p_width, real_t p_dash, bool p_aligned) {
draw_dashed_line(p_from, p_to, p_color, p_width, p_dash, p_aligned, false);
}

void CanvasItem::_draw_multiline_bind_compat_84523(const Vector<Point2> &p_points, const Color &p_color, real_t p_width) {
draw_multiline(p_points, p_color, p_width, false);
}

void CanvasItem::_draw_multiline_colors_bind_compat_84523(const Vector<Point2> &p_points, const Vector<Color> &p_colors, real_t p_width) {
draw_multiline_colors(p_points, p_colors, p_width, false);
}

void CanvasItem::_bind_compatibility_methods() {
ClassDB::bind_compatibility_method(D_METHOD("draw_circle", "position", "radius", "color"), &CanvasItem::_draw_circle_compat_84472);
ClassDB::bind_compatibility_method(D_METHOD("draw_circle", "position", "radius", "color"), &CanvasItem::_draw_circle_bind_compat_84472);
ClassDB::bind_compatibility_method(D_METHOD("draw_rect", "rect", "color", "filled", "width"), &CanvasItem::_draw_rect_bind_compat_84523, DEFVAL(true), DEFVAL(-1.0));
ClassDB::bind_compatibility_method(D_METHOD("draw_dashed_line", "from", "to", "color", "width", "dash", "aligned"), &CanvasItem::_draw_dashed_line_bind_compat_84523, DEFVAL(-1.0), DEFVAL(2.0), DEFVAL(true));
ClassDB::bind_compatibility_method(D_METHOD("draw_multiline", "points", "color", "width"), &CanvasItem::_draw_multiline_bind_compat_84523, DEFVAL(-1.0));
ClassDB::bind_compatibility_method(D_METHOD("draw_multiline_colors", "points", "colors", "width"), &CanvasItem::_draw_multiline_colors_bind_compat_84523, DEFVAL(-1.0));
}

#endif
34 changes: 17 additions & 17 deletions scene/main/canvas_item.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -609,7 +609,7 @@ bool CanvasItem::is_y_sort_enabled() const {
return y_sort_enabled;
}

void CanvasItem::draw_dashed_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, real_t p_width, real_t p_dash, bool p_aligned) {
void CanvasItem::draw_dashed_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, real_t p_width, real_t p_dash, bool p_aligned, bool p_antialiased) {
ERR_THREAD_GUARD;
ERR_DRAW_GUARD;
ERR_FAIL_COND(p_dash <= 0.0);
Expand All @@ -618,7 +618,7 @@ void CanvasItem::draw_dashed_line(const Point2 &p_from, const Point2 &p_to, cons
Vector2 step = p_dash * (p_to - p_from).normalized();

if (length < p_dash || step == Vector2()) {
RenderingServer::get_singleton()->canvas_item_add_line(canvas_item, p_from, p_to, p_color, p_width);
RenderingServer::get_singleton()->canvas_item_add_line(canvas_item, p_from, p_to, p_color, p_width, p_antialiased);
return;
}

Expand All @@ -642,7 +642,7 @@ void CanvasItem::draw_dashed_line(const Point2 &p_from, const Point2 &p_to, cons

Vector<Color> colors = { p_color };

RenderingServer::get_singleton()->canvas_item_add_multiline(canvas_item, points, colors, p_width);
RenderingServer::get_singleton()->canvas_item_add_multiline(canvas_item, points, colors, p_width, p_antialiased);
}

void CanvasItem::draw_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, real_t p_width, bool p_antialiased) {
Expand Down Expand Up @@ -683,22 +683,22 @@ void CanvasItem::draw_arc(const Vector2 &p_center, real_t p_radius, real_t p_sta
draw_polyline(points, p_color, p_width, p_antialiased);
}

void CanvasItem::draw_multiline(const Vector<Point2> &p_points, const Color &p_color, real_t p_width) {
void CanvasItem::draw_multiline(const Vector<Point2> &p_points, const Color &p_color, real_t p_width, bool p_antialiased) {
ERR_THREAD_GUARD;
ERR_DRAW_GUARD;

Vector<Color> colors = { p_color };
RenderingServer::get_singleton()->canvas_item_add_multiline(canvas_item, p_points, colors, p_width);
RenderingServer::get_singleton()->canvas_item_add_multiline(canvas_item, p_points, colors, p_width, p_antialiased);
}

void CanvasItem::draw_multiline_colors(const Vector<Point2> &p_points, const Vector<Color> &p_colors, real_t p_width) {
void CanvasItem::draw_multiline_colors(const Vector<Point2> &p_points, const Vector<Color> &p_colors, real_t p_width, bool p_antialiased) {
ERR_THREAD_GUARD;
ERR_DRAW_GUARD;

RenderingServer::get_singleton()->canvas_item_add_multiline(canvas_item, p_points, p_colors, p_width);
RenderingServer::get_singleton()->canvas_item_add_multiline(canvas_item, p_points, p_colors, p_width, p_antialiased);
}

void CanvasItem::draw_rect(const Rect2 &p_rect, const Color &p_color, bool p_filled, real_t p_width) {
void CanvasItem::draw_rect(const Rect2 &p_rect, const Color &p_color, bool p_filled, real_t p_width, bool p_antialiased) {
ERR_THREAD_GUARD;
ERR_DRAW_GUARD;

Expand All @@ -709,9 +709,9 @@ void CanvasItem::draw_rect(const Rect2 &p_rect, const Color &p_color, bool p_fil
WARN_PRINT("The draw_rect() \"width\" argument has no effect when \"filled\" is \"true\".");
}

RenderingServer::get_singleton()->canvas_item_add_rect(canvas_item, rect, p_color);
RenderingServer::get_singleton()->canvas_item_add_rect(canvas_item, rect, p_color, p_antialiased);
} else if (p_width >= rect.size.width || p_width >= rect.size.height) {
RenderingServer::get_singleton()->canvas_item_add_rect(canvas_item, rect.grow(0.5f * p_width), p_color);
RenderingServer::get_singleton()->canvas_item_add_rect(canvas_item, rect.grow(0.5f * p_width), p_color, p_antialiased);
} else {
Vector<Vector2> points;
points.resize(5);
Expand All @@ -723,7 +723,7 @@ void CanvasItem::draw_rect(const Rect2 &p_rect, const Color &p_color, bool p_fil

Vector<Color> colors = { p_color };

RenderingServer::get_singleton()->canvas_item_add_polyline(canvas_item, points, colors, p_width);
RenderingServer::get_singleton()->canvas_item_add_polyline(canvas_item, points, colors, p_width, p_antialiased);
}
}

Expand All @@ -736,9 +736,9 @@ void CanvasItem::draw_circle(const Point2 &p_pos, real_t p_radius, const Color &
WARN_PRINT("The draw_circle() \"width\" argument has no effect when \"filled\" is \"true\".");
}

RenderingServer::get_singleton()->canvas_item_add_circle(canvas_item, p_pos, p_radius, p_color);
RenderingServer::get_singleton()->canvas_item_add_circle(canvas_item, p_pos, p_radius, p_color, p_antialiased);
} else if (p_width >= 2.0 * p_radius) {
RenderingServer::get_singleton()->canvas_item_add_circle(canvas_item, p_pos, p_radius + 0.5 * p_width, p_color);
RenderingServer::get_singleton()->canvas_item_add_circle(canvas_item, p_pos, p_radius + 0.5 * p_width, p_color, p_antialiased);
} else {
// Tessellation count is hardcoded. Keep in sync with the same variable in `RendererCanvasCull::canvas_item_add_circle()`.
const int circle_segments = 64;
Expand Down Expand Up @@ -1186,13 +1186,13 @@ void CanvasItem::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_draw_behind_parent_enabled"), &CanvasItem::is_draw_behind_parent_enabled);

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_dashed_line", "from", "to", "color", "width", "dash", "aligned", "antialiased"), &CanvasItem::draw_dashed_line, DEFVAL(-1.0), DEFVAL(2.0), DEFVAL(true), 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));
ClassDB::bind_method(D_METHOD("draw_multiline", "points", "color", "width", "antialiased"), &CanvasItem::draw_multiline, DEFVAL(-1.0), DEFVAL(false));
ClassDB::bind_method(D_METHOD("draw_multiline_colors", "points", "colors", "width", "antialiased"), &CanvasItem::draw_multiline_colors, DEFVAL(-1.0), DEFVAL(false));
ClassDB::bind_method(D_METHOD("draw_rect", "rect", "color", "filled", "width", "antialiased"), &CanvasItem::draw_rect, DEFVAL(true), DEFVAL(-1.0), DEFVAL(false));
ClassDB::bind_method(D_METHOD("draw_circle", "position", "radius", "color", "filled", "width", "antialiased"), &CanvasItem::draw_circle, DEFVAL(true), DEFVAL(-1.0), DEFVAL(false));
ClassDB::bind_method(D_METHOD("draw_texture", "texture", "position", "modulate"), &CanvasItem::draw_texture, DEFVAL(Color(1, 1, 1, 1)));
ClassDB::bind_method(D_METHOD("draw_texture_rect", "texture", "rect", "tile", "modulate", "transpose"), &CanvasItem::draw_texture_rect, DEFVAL(Color(1, 1, 1, 1)), DEFVAL(false));
Expand Down
Loading

0 comments on commit 45ee0fd

Please sign in to comment.