Skip to content

Commit

Permalink
Extend CanvasItem::draw_circle()
Browse files Browse the repository at this point in the history
Make it possible to draw unfilled circle, like draw_rect().
  • Loading branch information
xiongyaohua committed Nov 5, 2023
1 parent 5ee9831 commit 18493f3
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 5 deletions.
7 changes: 6 additions & 1 deletion doc/classes/CanvasItem.xml
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,13 @@
<param index="0" name="position" type="Vector2" />
<param index="1" name="radius" type="float" />
<param index="2" name="color" type="Color" />
<param index="3" name="filled" type="bool" default="true" />
<param index="4" name="width" type="float" default="-1.0" />
<description>
Draws a colored, filled circle. See also [method draw_arc], [method draw_polyline] and [method draw_polygon].
Draws a circle. See also [method draw_arc], [method draw_polyline] and [method draw_polygon].
If [param filled] is [code]true[/code], the cricle 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].
[b]Note:[/b] [param width] is only effective if [param filled] is [code]false[/code].
</description>
</method>
<method name="draw_colored_polygon">
Expand Down
34 changes: 31 additions & 3 deletions scene/main/canvas_item.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -700,11 +700,39 @@ void CanvasItem::draw_rect(const Rect2 &p_rect, const Color &p_color, bool p_fil
}
}

void CanvasItem::draw_circle(const Point2 &p_pos, real_t p_radius, const Color &p_color) {
void CanvasItem::draw_circle(const Point2 &p_pos, real_t p_radius, const Color &p_color, bool p_filled, real_t p_width) {
ERR_THREAD_GUARD;
ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");

RenderingServer::get_singleton()->canvas_item_add_circle(canvas_item, p_pos, p_radius, p_color);
if (p_filled) {
if (p_width != -1.0) {
WARN_PRINT("The draw_rect() \"width\" argument has no effect when \"filled\" is \"true\".");
}

RenderingServer::get_singleton()->canvas_item_add_circle(canvas_item, p_pos, p_radius, p_color);
} 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);
} else {
// Tessellation count hardcoded. Keep in sync with the same variable in 'RendererCanvasCull::canvas_item_add_circle()'
const int circle_points = 64;

Vector<Vector2> points;
points.resize(circle_points + 1);

Vector2 *points_ptr = points.ptrw();
const real_t circle_point_step = Math_TAU / circle_points;

for (int i = 0; i < circle_points + 1; i++) {
float angle = i * circle_point_step;
points_ptr[i].x = Math::cos(angle) * p_radius;
points_ptr[i].y = Math::sin(angle) * p_radius;
points_ptr[i] += p_pos;
}

Vector<Color> colors = { p_color };

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

void CanvasItem::draw_texture(const Ref<Texture2D> &p_texture, const Point2 &p_pos, const Color &p_modulate) {
Expand Down Expand Up @@ -1133,7 +1161,7 @@ void CanvasItem::_bind_methods() {
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_circle", "position", "radius", "color"), &CanvasItem::draw_circle);
ClassDB::bind_method(D_METHOD("draw_circle", "position", "radius", "color", "filled", "width"), &CanvasItem::draw_circle, DEFVAL(true), DEFVAL(-1.0));
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));
ClassDB::bind_method(D_METHOD("draw_texture_rect_region", "texture", "rect", "src_rect", "modulate", "transpose", "clip_uv"), &CanvasItem::draw_texture_rect_region, DEFVAL(Color(1, 1, 1, 1)), DEFVAL(false), DEFVAL(true));
Expand Down
2 changes: 1 addition & 1 deletion scene/main/canvas_item.h
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ class CanvasItem : public Node {
void draw_multiline(const Vector<Point2> &p_points, const Color &p_color, real_t p_width = -1.0);
void draw_multiline_colors(const Vector<Point2> &p_points, const Vector<Color> &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);
void draw_circle(const Point2 &p_pos, real_t p_radius, const Color &p_color);
void draw_circle(const Point2 &p_pos, real_t p_radius, const Color &p_color, bool p_filled = true, real_t p_width = -1.0);
void draw_texture(const Ref<Texture2D> &p_texture, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1, 1));
void draw_texture_rect(const Ref<Texture2D> &p_texture, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false);
void draw_texture_rect_region(const Ref<Texture2D> &p_texture, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, bool p_clip_uv = false);
Expand Down

0 comments on commit 18493f3

Please sign in to comment.