diff options
-rw-r--r-- | doc/classes/CanvasItem.xml | 22 | ||||
-rw-r--r-- | scene/main/canvas_item.cpp | 13 | ||||
-rw-r--r-- | scene/main/canvas_item.h | 2 | ||||
-rw-r--r-- | servers/rendering/renderer_canvas_cull.cpp | 12 | ||||
-rw-r--r-- | servers/rendering/renderer_canvas_cull.h | 2 | ||||
-rw-r--r-- | servers/rendering/renderer_canvas_render.h | 12 | ||||
-rw-r--r-- | servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp | 15 | ||||
-rw-r--r-- | servers/rendering/rendering_server_default.h | 2 | ||||
-rw-r--r-- | servers/rendering_server.h | 1 |
9 files changed, 81 insertions, 0 deletions
diff --git a/doc/classes/CanvasItem.xml b/doc/classes/CanvasItem.xml index 87b157db4e..f15bc14be3 100644 --- a/doc/classes/CanvasItem.xml +++ b/doc/classes/CanvasItem.xml @@ -24,6 +24,21 @@ Overridable function called by the engine (if defined) to draw the canvas item. </description> </method> + <method name="draw_animation_slice"> + <return type="void"> + </return> + <argument index="0" name="animation_length" type="float"> + </argument> + <argument index="1" name="slice_begin" type="float"> + </argument> + <argument index="2" name="slice_end" type="float"> + </argument> + <argument index="3" name="offset" type="float" default="0.0"> + </argument> + <description> + Subsequent drawing commands will be ignored unless they fall within the specified animation slice. This is a faster way to implement animations that loop on background rather than redrawing constantly. + </description> + </method> <method name="draw_arc"> <return type="void"> </return> @@ -98,6 +113,13 @@ Draws a colored polygon of any amount of points, convex or concave. </description> </method> + <method name="draw_end_animation"> + <return type="void"> + </return> + <description> + After submitting all animations slices via [method draw_animation_slice], this function can be used to revert drawing to its default state (all subsequent drawing commands will be visible). If you don't care about this particular use case, usage of this function after submitting the slices is not required. + </description> + </method> <method name="draw_line"> <return type="void"> </return> diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp index 181fe606c8..a4393d682f 100644 --- a/scene/main/canvas_item.cpp +++ b/scene/main/canvas_item.cpp @@ -876,6 +876,17 @@ void CanvasItem::draw_set_transform_matrix(const Transform2D &p_matrix) { RenderingServer::get_singleton()->canvas_item_add_set_transform(canvas_item, p_matrix); } +void CanvasItem::draw_animation_slice(double p_animation_length, double p_slice_begin, double p_slice_end, double p_offset) { + ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); + + RenderingServer::get_singleton()->canvas_item_add_animation_slice(canvas_item, p_animation_length, p_slice_begin, p_slice_end, p_offset); +} + +void CanvasItem::draw_end_animation() { + ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); + + RenderingServer::get_singleton()->canvas_item_add_animation_slice(canvas_item, 1, 0, 2, 0); +} void CanvasItem::draw_polygon(const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, Ref<Texture2D> p_texture) { ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); @@ -1159,6 +1170,8 @@ void CanvasItem::_bind_methods() { ClassDB::bind_method(D_METHOD("draw_multimesh", "multimesh", "texture"), &CanvasItem::draw_multimesh); ClassDB::bind_method(D_METHOD("draw_set_transform", "position", "rotation", "scale"), &CanvasItem::draw_set_transform, DEFVAL(0.0), DEFVAL(Size2(1.0, 1.0))); ClassDB::bind_method(D_METHOD("draw_set_transform_matrix", "xform"), &CanvasItem::draw_set_transform_matrix); + ClassDB::bind_method(D_METHOD("draw_animation_slice", "animation_length", "slice_begin", "slice_end", "offset"), &CanvasItem::draw_animation_slice, DEFVAL(0.0)); + ClassDB::bind_method(D_METHOD("draw_end_animation"), &CanvasItem::draw_end_animation); ClassDB::bind_method(D_METHOD("get_transform"), &CanvasItem::get_transform); ClassDB::bind_method(D_METHOD("get_global_transform"), &CanvasItem::get_global_transform); ClassDB::bind_method(D_METHOD("get_global_transform_with_canvas"), &CanvasItem::get_global_transform_with_canvas); diff --git a/scene/main/canvas_item.h b/scene/main/canvas_item.h index 1c64cafab8..afdd18d76b 100644 --- a/scene/main/canvas_item.h +++ b/scene/main/canvas_item.h @@ -356,6 +356,8 @@ public: void draw_set_transform(const Point2 &p_offset, real_t p_rot = 0.0, const Size2 &p_scale = Size2(1.0, 1.0)); void draw_set_transform_matrix(const Transform2D &p_matrix); + void draw_animation_slice(double p_animation_length, double p_slice_begin, double p_slice_end, double p_offset = 0); + void draw_end_animation(); static CanvasItem *get_current_item_drawn(); diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp index 5703737252..016a172f25 100644 --- a/servers/rendering/renderer_canvas_cull.cpp +++ b/servers/rendering/renderer_canvas_cull.cpp @@ -1003,6 +1003,18 @@ void RendererCanvasCull::canvas_item_add_clip_ignore(RID p_item, bool p_ignore) ci->ignore = p_ignore; } +void RendererCanvasCull::canvas_item_add_animation_slice(RID p_item, double p_animation_length, double p_slice_begin, double p_slice_end, double p_offset) { + Item *canvas_item = canvas_item_owner.getornull(p_item); + ERR_FAIL_COND(!canvas_item); + + Item::CommandAnimationSlice *as = canvas_item->alloc_command<Item::CommandAnimationSlice>(); + ERR_FAIL_COND(!as); + as->animation_length = p_animation_length; + as->slice_begin = p_slice_begin; + as->slice_end = p_slice_end; + as->offset = p_offset; +} + void RendererCanvasCull::canvas_item_set_sort_children_by_y(RID p_item, bool p_enable) { Item *canvas_item = canvas_item_owner.getornull(p_item); ERR_FAIL_COND(!canvas_item); diff --git a/servers/rendering/renderer_canvas_cull.h b/servers/rendering/renderer_canvas_cull.h index 661216cad3..a51b419613 100644 --- a/servers/rendering/renderer_canvas_cull.h +++ b/servers/rendering/renderer_canvas_cull.h @@ -231,6 +231,8 @@ public: void canvas_item_add_particles(RID p_item, RID p_particles, RID p_texture); void canvas_item_add_set_transform(RID p_item, const Transform2D &p_transform); void canvas_item_add_clip_ignore(RID p_item, bool p_ignore); + void canvas_item_add_animation_slice(RID p_item, double p_animation_length, double p_slice_begin, double p_slice_end, double p_offset); + void canvas_item_set_sort_children_by_y(RID p_item, bool p_enable); void canvas_item_set_z_index(RID p_item, int p_z); void canvas_item_set_z_as_relative_to_parent(RID p_item, bool p_enable); diff --git a/servers/rendering/renderer_canvas_render.h b/servers/rendering/renderer_canvas_render.h index 0266e137c0..c10b9db035 100644 --- a/servers/rendering/renderer_canvas_render.h +++ b/servers/rendering/renderer_canvas_render.h @@ -180,6 +180,7 @@ public: TYPE_PARTICLES, TYPE_TRANSFORM, TYPE_CLIP_IGNORE, + TYPE_ANIMATION_SLICE, }; Command *next; @@ -286,6 +287,17 @@ public: } }; + struct CommandAnimationSlice : public Command { + double animation_length = 0; + double slice_begin = 0; + double slice_end = 0; + double offset = 0; + + CommandAnimationSlice() { + type = TYPE_ANIMATION_SLICE; + } + }; + struct ViewportRender { RenderingServer *owner; void *udata; diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp index 9d325fe69b..fe6d3be82e 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp @@ -464,8 +464,15 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend RID last_texture; Size2 texpixel_size; + bool skipping = false; + const Item::Command *c = p_item->commands; while (c) { + if (skipping && c->type != Item::Command::TYPE_ANIMATION_SLICE) { + c = c->next; + continue; + } + push_constant.flags = base_flags | (push_constant.flags & (FLAGS_DEFAULT_NORMAL_MAP_USED | FLAGS_DEFAULT_SPECULAR_MAP_USED)); //reset on each command for sanity, keep canvastexture binding config switch (c->type) { @@ -879,6 +886,14 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend } } break; + case Item::Command::TYPE_ANIMATION_SLICE: { + const Item::CommandAnimationSlice *as = static_cast<const Item::CommandAnimationSlice *>(c); + double current_time = RendererCompositorRD::singleton->get_total_time(); + double local_time = Math::fposmod(current_time - as->offset, as->animation_length); + skipping = !(local_time >= as->slice_begin && local_time < as->slice_end); + + RenderingServerDefault::redraw_request(); // animation visible means redraw request + } break; } c = c->next; diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h index 9404374287..16e9f1fc77 100644 --- a/servers/rendering/rendering_server_default.h +++ b/servers/rendering/rendering_server_default.h @@ -813,6 +813,8 @@ public: FUNC3(canvas_item_add_particles, RID, RID, RID) FUNC2(canvas_item_add_set_transform, RID, const Transform2D &) FUNC2(canvas_item_add_clip_ignore, RID, bool) + FUNC5(canvas_item_add_animation_slice, RID, double, double, double, double) + FUNC2(canvas_item_set_sort_children_by_y, RID, bool) FUNC2(canvas_item_set_z_index, RID, int) FUNC2(canvas_item_set_z_as_relative_to_parent, RID, bool) diff --git a/servers/rendering_server.h b/servers/rendering_server.h index ac6b0a4d1a..594e2d885c 100644 --- a/servers/rendering_server.h +++ b/servers/rendering_server.h @@ -1294,6 +1294,7 @@ public: virtual void canvas_item_add_particles(RID p_item, RID p_particles, RID p_texture) = 0; virtual void canvas_item_add_set_transform(RID p_item, const Transform2D &p_transform) = 0; virtual void canvas_item_add_clip_ignore(RID p_item, bool p_ignore) = 0; + virtual void canvas_item_add_animation_slice(RID p_item, double p_animation_length, double p_slice_begin, double p_slice_end, double p_offset) = 0; virtual void canvas_item_set_sort_children_by_y(RID p_item, bool p_enable) = 0; virtual void canvas_item_set_z_index(RID p_item, int p_z) = 0; virtual void canvas_item_set_z_as_relative_to_parent(RID p_item, bool p_enable) = 0; |