diff options
Diffstat (limited to 'scene/main/canvas_item.cpp')
-rw-r--r-- | scene/main/canvas_item.cpp | 119 |
1 files changed, 89 insertions, 30 deletions
diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp index 2d0da075ba..7ed1f130c8 100644 --- a/scene/main/canvas_item.cpp +++ b/scene/main/canvas_item.cpp @@ -29,6 +29,7 @@ /**************************************************************************/ #include "canvas_item.h" +#include "canvas_item.compat.inc" #include "scene/2d/canvas_group.h" #include "scene/main/canvas_layer.h" @@ -38,7 +39,6 @@ #include "scene/resources/multimesh.h" #include "scene/resources/style_box.h" #include "scene/resources/world_2d.h" -#include "scene/scene_string_names.h" #define ERR_DRAW_GUARD \ ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside this node's `_draw()`, functions connected to its `draw` signal, or when it receives NOTIFICATION_DRAW.") @@ -94,7 +94,7 @@ void CanvasItem::_handle_visibility_change(bool p_visible) { if (p_visible) { queue_redraw(); } else { - emit_signal(SceneStringNames::get_singleton()->hidden); + emit_signal(SceneStringName(hidden)); } _block(); @@ -140,7 +140,7 @@ void CanvasItem::_redraw_callback() { drawing = true; current_item_drawn = this; notification(NOTIFICATION_DRAW); - emit_signal(SceneStringNames::get_singleton()->draw); + emit_signal(SceneStringName(draw)); GDVIRTUAL_CALL(_draw); current_item_drawn = nullptr; drawing = false; @@ -308,7 +308,7 @@ void CanvasItem::_notification(int p_what) { window = Object::cast_to<Window>(viewport); if (window) { - window->connect(SceneStringNames::get_singleton()->visibility_changed, callable_mp(this, &CanvasItem::_window_visibility_changed)); + window->connect(SceneStringName(visibility_changed), callable_mp(this, &CanvasItem::_window_visibility_changed)); parent_visible_in_tree = window->is_visible(); } else { parent_visible_in_tree = true; @@ -336,6 +336,19 @@ void CanvasItem::_notification(int p_what) { get_parent()->connect(SNAME("child_order_changed"), callable_mp(get_viewport(), &Viewport::canvas_parent_mark_dirty).bind(get_parent()), CONNECT_REFERENCE_COUNTED); } + // If using physics interpolation, reset for this node only, + // as a helper, as in most cases, users will want items reset when + // adding to the tree. + // In cases where they move immediately after adding, + // there will be little cost in having two resets as these are cheap, + // and it is worth it for convenience. + // Do not propagate to children, as each child of an added branch + // receives its own NOTIFICATION_ENTER_TREE, and this would + // cause unnecessary duplicate resets. + if (is_physics_interpolated_and_enabled()) { + notification(NOTIFICATION_RESET_PHYSICS_INTERPOLATION); + } + } break; case NOTIFICATION_EXIT_TREE: { ERR_MAIN_THREAD_GUARD; @@ -349,7 +362,7 @@ void CanvasItem::_notification(int p_what) { C = nullptr; } if (window) { - window->disconnect(SceneStringNames::get_singleton()->visibility_changed, callable_mp(this, &CanvasItem::_window_visibility_changed)); + window->disconnect(SceneStringName(visibility_changed), callable_mp(this, &CanvasItem::_window_visibility_changed)); window = nullptr; } _set_global_invalid(true); @@ -360,10 +373,16 @@ void CanvasItem::_notification(int p_what) { } } break; + case NOTIFICATION_RESET_PHYSICS_INTERPOLATION: { + if (is_visible_in_tree() && is_physics_interpolated()) { + RenderingServer::get_singleton()->canvas_item_reset_physics_interpolation(canvas_item); + } + } break; + case NOTIFICATION_VISIBILITY_CHANGED: { ERR_MAIN_THREAD_GUARD; - emit_signal(SceneStringNames::get_singleton()->visibility_changed); + emit_signal(SceneStringName(visibility_changed)); } break; case NOTIFICATION_WORLD_2D_CHANGED: { ERR_MAIN_THREAD_GUARD; @@ -535,7 +554,7 @@ void CanvasItem::item_rect_changed(bool p_size_changed) { if (p_size_changed) { queue_redraw(); } - emit_signal(SceneStringNames::get_singleton()->item_rect_changed); + emit_signal(SceneStringName(item_rect_changed)); } void CanvasItem::set_z_index(int p_z) { @@ -589,7 +608,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); @@ -598,7 +617,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; } @@ -622,7 +641,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) { @@ -663,22 +682,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; @@ -689,9 +708,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); @@ -703,15 +722,44 @@ 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); } } -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, bool p_antialiased) { ERR_THREAD_GUARD; ERR_DRAW_GUARD; - 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_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, 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, 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; + + Vector<Vector2> points; + points.resize(circle_segments + 1); + + Vector2 *points_ptr = points.ptrw(); + const real_t circle_point_step = Math_TAU / circle_segments; + + for (int i = 0; i < circle_segments; 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; + } + points_ptr[circle_segments] = points_ptr[0]; + + Vector<Color> colors = { p_color }; + + RenderingServer::get_singleton()->canvas_item_add_polyline(canvas_item, points, colors, p_width, p_antialiased); + } } void CanvasItem::draw_texture(const Ref<Texture2D> &p_texture, const Point2 &p_pos, const Color &p_modulate) { @@ -921,6 +969,10 @@ void CanvasItem::_notify_transform(CanvasItem *p_node) { } } +void CanvasItem::_physics_interpolated_changed() { + RenderingServer::get_singleton()->canvas_item_set_interpolated(canvas_item, is_physics_interpolated()); +} + Rect2 CanvasItem::get_viewport_rect() const { ERR_READ_THREAD_GUARD_V(Rect2()); ERR_FAIL_COND_V(!is_inside_tree(), Rect2()); @@ -1133,14 +1185,14 @@ 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_circle", "position", "radius", "color"), &CanvasItem::draw_circle); + 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)); 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)); @@ -1378,14 +1430,17 @@ void CanvasItem::_refresh_texture_filter_cache() const { } } +void CanvasItem::_update_self_texture_filter(RS::CanvasItemTextureFilter p_texture_filter) { + RS::get_singleton()->canvas_item_set_default_texture_filter(get_canvas_item(), p_texture_filter); + queue_redraw(); +} + void CanvasItem::_update_texture_filter_changed(bool p_propagate) { if (!is_inside_tree()) { return; } _refresh_texture_filter_cache(); - - RS::get_singleton()->canvas_item_set_default_texture_filter(get_canvas_item(), texture_filter_cache); - queue_redraw(); + _update_self_texture_filter(texture_filter_cache); if (p_propagate) { for (CanvasItem *E : children_items) { @@ -1429,14 +1484,18 @@ void CanvasItem::_refresh_texture_repeat_cache() const { } } +void CanvasItem::_update_self_texture_repeat(RS::CanvasItemTextureRepeat p_texture_repeat) { + RS::get_singleton()->canvas_item_set_default_texture_repeat(get_canvas_item(), p_texture_repeat); + queue_redraw(); +} + void CanvasItem::_update_texture_repeat_changed(bool p_propagate) { if (!is_inside_tree()) { return; } _refresh_texture_repeat_cache(); + _update_self_texture_repeat(texture_repeat_cache); - RS::get_singleton()->canvas_item_set_default_texture_repeat(get_canvas_item(), texture_repeat_cache); - queue_redraw(); if (p_propagate) { for (CanvasItem *E : children_items) { if (!E->top_level && E->texture_repeat == TEXTURE_REPEAT_PARENT_NODE) { |