From 2934369381c9a8d6ea51c7b26a5b723546592556 Mon Sep 17 00:00:00 2001 From: Relintai Date: Mon, 11 Mar 2024 18:21:05 +0100 Subject: [PATCH] Added a new canvas_item_add_texture_rect_animation() method to the RenderingServer. --- drivers/gles2/rasterizer_canvas_gles2.cpp | 264 +++++++++++++++++- drivers/gles2/rasterizer_canvas_gles2.h | 3 + .../gles_common/rasterizer_canvas_batcher.h | 44 ++- servers/rendering/rasterizer.h | 52 +++- servers/rendering/rendering_server_canvas.cpp | 85 ++++++ servers/rendering/rendering_server_canvas.h | 2 + servers/rendering/rendering_server_raster.h | 2 + servers/rendering/rendering_server_wrap_mt.h | 1 + servers/rendering_server.cpp | 1 + servers/rendering_server.h | 2 + 10 files changed, 450 insertions(+), 6 deletions(-) diff --git a/drivers/gles2/rasterizer_canvas_gles2.cpp b/drivers/gles2/rasterizer_canvas_gles2.cpp index 7b66771a4..5dabac323 100644 --- a/drivers/gles2/rasterizer_canvas_gles2.cpp +++ b/drivers/gles2/rasterizer_canvas_gles2.cpp @@ -390,6 +390,7 @@ void RasterizerCanvasGLES2::render_batches(Item *p_current_clip, bool &r_reclip, } break; case Item::Command::TYPE_RECT: { + // If anything changes also update Item::Command::TYPE_RECT_ANIMATION Item::CommandRect *r = static_cast(command); glDisableVertexAttribArray(RS::ARRAY_COLOR); @@ -874,7 +875,7 @@ void RasterizerCanvasGLES2::render_batches(Item *p_current_clip, bool &r_reclip, Size2 texpixel_size(1.0 / texture->width, 1.0 / texture->height); state.canvas_shader.set_uniform(CanvasShaderGLES2::COLOR_TEXPIXEL_SIZE, texpixel_size); } - + state.canvas_shader.set_uniform(CanvasShaderGLES2::MODELVIEW_MATRIX, state.uniforms.modelview_matrix * mesh->transform); state.canvas_shader.set_uniform(CanvasShaderGLES2::FINAL_MODULATE, state.uniforms.final_modulate * mesh->modulate); @@ -921,7 +922,7 @@ void RasterizerCanvasGLES2::render_batches(Item *p_current_clip, bool &r_reclip, glDisableVertexAttribArray(j); } } - + state.canvas_shader.set_uniform(CanvasShaderGLES2::MODELVIEW_MATRIX, state.uniforms.modelview_matrix); state.canvas_shader.set_uniform(CanvasShaderGLES2::FINAL_MODULATE, state.uniforms.final_modulate); @@ -1186,6 +1187,253 @@ void RasterizerCanvasGLES2::render_batches(Item *p_current_clip, bool &r_reclip, } break; + case Item::Command::TYPE_RECT_ANIMATION: { + // Should probably move this to a method maybe + RasterizerCanvas::Item::CommandRectAnimation *rectanim = static_cast(command); + RasterizerCanvas::Item::CommandRect *r = rectanim->get_command_rect(); + + // Update here. Even though this way the animation can lag 1 frame behind sometimes, + // but doing it here is the simplest, without heavy changes to batching. + // Since this type of animation is more fitting to just small tilemap + rectanim->update(static_cast(storage->frame.delta)); + + // If we are rendering an animation, send redraw request + RenderingServerRaster::redraw_request(false); + + glDisableVertexAttribArray(RS::ARRAY_COLOR); + glVertexAttrib4fv(RS::ARRAY_COLOR, r->modulate.components); + + bool can_tile = true; + if (r->texture.is_valid() && r->flags & CANVAS_RECT_TILE && !storage->config.support_npot_repeat_mipmap) { + // workaround for when setting tiling does not work due to hardware limitation + + RasterizerStorageGLES2::Texture *texture = storage->texture_owner.getornull(r->texture); + + if (texture) { + texture = texture->get_ptr(); + + if (next_power_of_2(texture->alloc_width) != (unsigned int)texture->alloc_width && next_power_of_2(texture->alloc_height) != (unsigned int)texture->alloc_height) { + state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_FORCE_REPEAT, true); + can_tile = false; + } + } + } + + // On some widespread Nvidia cards, the normal draw method can produce some + // flickering in draw_rect and especially TileMap rendering (tiles randomly flicker). + // See GH-9913. + // To work it around, we use a simpler draw method which does not flicker, but gives + // a non negligible performance hit, so it's opt-in (GH-24466). + if (use_nvidia_rect_workaround) { + // are we using normal maps, if so we want to use light angle + bool send_light_angles = false; + + // only need to use light angles when normal mapping + // otherwise we can use the default shader + if (state.current_normal != RID()) { + send_light_angles = true; + } + + _set_texture_rect_mode(false, send_light_angles); + + if (state.canvas_shader.bind()) { + _set_uniforms(); + state.canvas_shader.use_material((void *)p_material); + } + + Vector2 points[4] = { + r->rect.position, + r->rect.position + Vector2(r->rect.size.x, 0.0), + r->rect.position + r->rect.size, + r->rect.position + Vector2(0.0, r->rect.size.y), + }; + + if (r->rect.size.x < 0) { + SWAP(points[0], points[1]); + SWAP(points[2], points[3]); + } + if (r->rect.size.y < 0) { + SWAP(points[0], points[3]); + SWAP(points[1], points[2]); + } + + RasterizerStorageGLES2::Texture *texture = _bind_canvas_texture(r->texture, r->normal_map); + + if (texture) { + Size2 texpixel_size(1.0 / texture->width, 1.0 / texture->height); + + Rect2 src_rect = (r->flags & CANVAS_RECT_REGION) ? Rect2(r->source.position * texpixel_size, r->source.size * texpixel_size) : Rect2(0, 0, 1, 1); + + Vector2 uvs[4] = { + src_rect.position, + src_rect.position + Vector2(src_rect.size.x, 0.0), + src_rect.position + src_rect.size, + src_rect.position + Vector2(0.0, src_rect.size.y), + }; + + // for encoding in light angle + bool flip_h = false; + bool flip_v = false; + + if (r->flags & CANVAS_RECT_TRANSPOSE) { + SWAP(uvs[1], uvs[3]); + } + + if (r->flags & CANVAS_RECT_FLIP_H) { + SWAP(uvs[0], uvs[1]); + SWAP(uvs[2], uvs[3]); + flip_h = true; + flip_v = !flip_v; + } + if (r->flags & CANVAS_RECT_FLIP_V) { + SWAP(uvs[0], uvs[3]); + SWAP(uvs[1], uvs[2]); + flip_v = !flip_v; + } + + state.canvas_shader.set_uniform(CanvasShaderGLES2::COLOR_TEXPIXEL_SIZE, texpixel_size); + + bool untile = false; + + if (can_tile && r->flags & CANVAS_RECT_TILE && !(texture->flags & RS::TEXTURE_FLAG_REPEAT)) { + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + untile = true; + } + + if (send_light_angles) { + // for single rects, there is no need to fully utilize the light angle, + // we only need it to encode flips (horz and vert). But the shader can be reused with + // batching in which case the angle encodes the transform as well as + // the flips. + // Note transpose is NYI. I don't think it worked either with the non-nvidia method. + + // if horizontal flip, angle is 180 + float angle = 0.0f; + if (flip_h) { + angle = Math_PI; + } + + // add 1 (to take care of zero floating point error with sign) + angle += 1.0f; + + // flip if necessary + if (flip_v) { + angle *= -1.0f; + } + + // light angle must be sent for each vert, instead as a single uniform in the uniform draw method + // this has the benefit of enabling batching with light angles. + float light_angles[4] = { angle, angle, angle, angle }; + + _draw_gui_primitive(4, points, nullptr, uvs, light_angles); + } else { + _draw_gui_primitive(4, points, nullptr, uvs); + } + + if (untile) { + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + } + } else { + static const Vector2 uvs[4] = { + Vector2(0.0, 0.0), + Vector2(0.0, 1.0), + Vector2(1.0, 1.0), + Vector2(1.0, 0.0), + }; + + state.canvas_shader.set_uniform(CanvasShaderGLES2::COLOR_TEXPIXEL_SIZE, Vector2()); + _draw_gui_primitive(4, points, nullptr, uvs); + } + + } else { + // This branch is better for performance, but can produce flicker on Nvidia, see above comment. + _bind_quad_buffer(); + + _set_texture_rect_mode(true); + + if (state.canvas_shader.bind()) { + _set_uniforms(); + state.canvas_shader.use_material((void *)p_material); + } + + RasterizerStorageGLES2::Texture *tex = _bind_canvas_texture(r->texture, r->normal_map); + + if (!tex) { + Rect2 dst_rect = Rect2(r->rect.position, r->rect.size); + + if (dst_rect.size.width < 0) { + dst_rect.position.x += dst_rect.size.width; + dst_rect.size.width *= -1; + } + if (dst_rect.size.height < 0) { + dst_rect.position.y += dst_rect.size.height; + dst_rect.size.height *= -1; + } + + state.canvas_shader.set_uniform(CanvasShaderGLES2::DST_RECT, Color(dst_rect.position.x, dst_rect.position.y, dst_rect.size.x, dst_rect.size.y)); + state.canvas_shader.set_uniform(CanvasShaderGLES2::SRC_RECT, Color(0, 0, 1, 1)); + + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + storage->info.render._2d_draw_call_count++; + } else { + bool untile = false; + + if (can_tile && r->flags & CANVAS_RECT_TILE && !(tex->flags & RS::TEXTURE_FLAG_REPEAT)) { + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + untile = true; + } + + Size2 texpixel_size(1.0 / tex->width, 1.0 / tex->height); + Rect2 src_rect = (r->flags & CANVAS_RECT_REGION) ? Rect2(r->source.position * texpixel_size, r->source.size * texpixel_size) : Rect2(0, 0, 1, 1); + + Rect2 dst_rect = Rect2(r->rect.position, r->rect.size); + + if (dst_rect.size.width < 0) { + dst_rect.position.x += dst_rect.size.width; + dst_rect.size.width *= -1; + } + if (dst_rect.size.height < 0) { + dst_rect.position.y += dst_rect.size.height; + dst_rect.size.height *= -1; + } + + if (r->flags & CANVAS_RECT_FLIP_H) { + src_rect.size.x *= -1; + } + + if (r->flags & CANVAS_RECT_FLIP_V) { + src_rect.size.y *= -1; + } + + if (r->flags & CANVAS_RECT_TRANSPOSE) { + dst_rect.size.x *= -1; // Encoding in the dst_rect.z uniform + } + + state.canvas_shader.set_uniform(CanvasShaderGLES2::COLOR_TEXPIXEL_SIZE, texpixel_size); + + state.canvas_shader.set_uniform(CanvasShaderGLES2::DST_RECT, Color(dst_rect.position.x, dst_rect.position.y, dst_rect.size.x, dst_rect.size.y)); + state.canvas_shader.set_uniform(CanvasShaderGLES2::SRC_RECT, Color(src_rect.position.x, src_rect.position.y, src_rect.size.x, src_rect.size.y)); + + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + storage->info.render._2d_draw_call_count++; + + if (untile) { + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + } + } + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + } + + state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_FORCE_REPEAT, false); + + } break; + default: { // FIXME: Proper error handling if relevant //print_line("other"); @@ -2399,3 +2647,15 @@ void RasterizerCanvasGLES2::initialize() { RasterizerCanvasGLES2::RasterizerCanvasGLES2() { batch_constructor(); } + +void RasterizerCanvasGLES2::_update_texture_rect_animation(RasterizerCanvas::Item::CommandRectAnimation *p_item) { + RasterizerCanvas::Item::CommandRectAnimation *rectanim = static_cast(p_item); + + // Update here. Even though this way the animation can lag 1 frame behind sometimes, + // but doing it here is the simplest, without heavy changes to batching. + // Since this type of animation is more fitting to just small tilemap + rectanim->update(static_cast(storage->frame.delta)); + + // If we are rendering an animation, send redraw request + RenderingServerRaster::redraw_request(false); +} diff --git a/drivers/gles2/rasterizer_canvas_gles2.h b/drivers/gles2/rasterizer_canvas_gles2.h index b9731fcb5..015a6f94c 100644 --- a/drivers/gles2/rasterizer_canvas_gles2.h +++ b/drivers/gles2/rasterizer_canvas_gles2.h @@ -69,6 +69,9 @@ private: public: void initialize(); RasterizerCanvasGLES2(); + +protected: + virtual void _update_texture_rect_animation(RasterizerCanvas::Item::CommandRectAnimation *p_item); }; #endif // RASTERIZERCANVASGLES2_H diff --git a/drivers/gles_common/rasterizer_canvas_batcher.h b/drivers/gles_common/rasterizer_canvas_batcher.h index be563ed6a..6cc2e1d79 100644 --- a/drivers/gles_common/rasterizer_canvas_batcher.h +++ b/drivers/gles_common/rasterizer_canvas_batcher.h @@ -699,6 +699,10 @@ public: return bdata.vertices.request(); } + +protected: + virtual void _update_texture_rect_animation(RasterizerCanvas::Item::CommandRectAnimation *p_item) {} + protected: // no need to compile these in in release, they are unneeded outside the editor and only add to executable size #if defined(TOOLS_ENABLED) && defined(DEBUG_ENABLED) @@ -1959,7 +1963,8 @@ bool C_PREAMBLE::_prefill_rect(RasterizerCanvas::Item::CommandRect *rect, FillSt int command_num_next = command_num + 1; if (command_num_next < command_count) { RasterizerCanvas::Item::Command *command_next = commands[command_num_next]; - if ((command_next->type != RasterizerCanvas::Item::Command::TYPE_RECT) && (command_next->type != RasterizerCanvas::Item::Command::TYPE_TRANSFORM)) { + if ((command_next->type != RasterizerCanvas::Item::Command::TYPE_RECT && command_next->type != RasterizerCanvas::Item::Command::TYPE_RECT_ANIMATION) && + (command_next->type != RasterizerCanvas::Item::Command::TYPE_TRANSFORM)) { is_single_rect = true; } } else { @@ -2874,6 +2879,34 @@ PREAMBLE(bool)::prefill_joined_item(FillState &r_fill_state, int &r_command_star #endif } break; + + case RasterizerCanvas::Item::Command::TYPE_RECT_ANIMATION: { + RasterizerCanvas::Item::CommandRectAnimation *rectanim = static_cast(command); + RasterizerCanvas::Item::CommandRect *rect = rectanim->get_command_rect(); + + // Update here. Even though this way the animation can lag 1 frame behind sometimes, + // but doing it here is the simplest, without heavy changes to batching. + // Since this type of animation is more fitting to just small tilemap + _update_texture_rect_animation(rectanim); + + // unoptimized - could this be done once per batch / batch texture? + bool send_light_angles = rect->normal_map != RID(); + + bool buffer_full = false; + + // the template params must be explicit for compilation, + // this forces building the multiple versions of the function. + if (send_light_angles) { + buffer_full = _prefill_rect(rect, r_fill_state, r_command_start, command_num, command_count, commands, p_item, multiply_final_modulate); + } else { + buffer_full = _prefill_rect(rect, r_fill_state, r_command_start, command_num, command_count, commands, p_item, multiply_final_modulate); + } + + if (buffer_full) { + return true; + } + + } break; } } @@ -3215,7 +3248,7 @@ PREAMBLE(bool)::_sort_items_match(const BSortItem &p_a, const BSortItem &p_b) co // return false; const RasterizerCanvas::Item::Command &cb = *b->commands[0]; - if ((cb.type != RasterizerCanvas::Item::Command::TYPE_RECT) && (cb.type != RasterizerCanvas::Item::Command::TYPE_MULTIRECT)) { + if ((cb.type != RasterizerCanvas::Item::Command::TYPE_RECT) && (cb.type != RasterizerCanvas::Item::Command::TYPE_MULTIRECT) && (cb.type != RasterizerCanvas::Item::Command::TYPE_RECT_ANIMATION)) { return false; } @@ -3278,7 +3311,7 @@ PREAMBLE(bool)::sort_items_from(int p_start) { return false; } const RasterizerCanvas::Item::Command &command_start = *start.item->commands[0]; - if ((command_start.type != RasterizerCanvas::Item::Command::TYPE_RECT) && (command_start.type != RasterizerCanvas::Item::Command::TYPE_MULTIRECT)) { + if ((command_start.type != RasterizerCanvas::Item::Command::TYPE_RECT) && (command_start.type != RasterizerCanvas::Item::Command::TYPE_MULTIRECT) && (command_start.type != RasterizerCanvas::Item::Command::TYPE_RECT_ANIMATION)) { return false; } @@ -3682,6 +3715,11 @@ PREAMBLE(bool)::_detect_item_batch_break(RenderItemState &r_ris, RasterizerCanva case RasterizerCanvas::Item::Command::TYPE_TRANSFORM: { // compatible with all types } break; + case RasterizerCanvas::Item::Command::TYPE_RECT_ANIMATION: { + if (_disallow_item_join_if_batch_types_too_different(r_ris, RasterizerStorageCommon::BTF_RECT)) { + return true; + } + } break; } // switch } // for through commands diff --git a/servers/rendering/rasterizer.h b/servers/rendering/rasterizer.h index f2243fc72..28675a141 100644 --- a/servers/rendering/rasterizer.h +++ b/servers/rendering/rasterizer.h @@ -682,6 +682,7 @@ public: TYPE_TRANSFORM, TYPE_CLIP_IGNORE, TYPE_MULTIRECT, + TYPE_RECT_ANIMATION, }; virtual bool contains_reference(const RID &p_rid) const { return false; } @@ -851,6 +852,52 @@ public: } }; + struct CommandRectAnimation : public Command { + // Make sure to always add 1 allocated element into the Vectors! + Vector rects; + Vector times; + int current; + real_t time_elapsed; + real_t total_time; + + const CommandRect *get_command_rect() const { + CRASH_BAD_INDEX(current, rects.size()); + + return rects[current]; + } + + CommandRect *get_command_rect() { + CRASH_BAD_INDEX(current, rects.size()); + + return rects.write[current]; + } + + void update(real_t p_delta) { + time_elapsed += p_delta; + + while (time_elapsed >= total_time) { + time_elapsed -= total_time; + } + + real_t next_frame_time = 0; + for (int i = 0; i < times.size(); ++i) { + next_frame_time += times[i]; + + if (next_frame_time > time_elapsed) { + current = i; + break; + } + } + } + + CommandRectAnimation() { + current = 0; + time_elapsed = 0; + total_time = 0; + type = TYPE_RECT_ANIMATION; + } + }; + struct ViewportRender { RenderingServer *owner; void *udata; @@ -1047,9 +1094,12 @@ public: found_xform = true; continue; } break; - case Item::Command::TYPE_CLIP_IGNORE: { } break; + case Item::Command::TYPE_RECT_ANIMATION: { + const Item::CommandRectAnimation *crectanim = static_cast(c); + r = crectanim->get_command_rect()->rect; + } break; } if (found_xform) { diff --git a/servers/rendering/rendering_server_canvas.cpp b/servers/rendering/rendering_server_canvas.cpp index 4e7ec61d8..f31a6f2f7 100644 --- a/servers/rendering/rendering_server_canvas.cpp +++ b/servers/rendering/rendering_server_canvas.cpp @@ -1512,6 +1512,91 @@ void RenderingServerCanvas::canvas_item_add_multimesh(RID p_item, RID p_mesh, RI } } +void RenderingServerCanvas::canvas_item_add_texture_rect_animation(RID p_item, const Array &p_animation_data) { + // Important! + if (p_animation_data.size() == 0) { + return; + } + + Item *canvas_item = canvas_item_owner.getornull(p_item); + ERR_FAIL_COND(!canvas_item); + + // Note Item::CommandRectAnimations need at least one item set. The way the logic is set up this will always happen. + Item::CommandRectAnimation *ra = memnew(Item::CommandRectAnimation); + ERR_FAIL_COND(!ra); + + //void canvas_item_add_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, + //const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, RID p_normal_map = RID(), bool p_clip_uv = false); + + real_t total_frame_time = 0; + + for (int i = 0; i < p_animation_data.size(); ++i) { + Array d = p_animation_data[i]; + + if (d.size() < 8) { + bool need_to_set_default_color = d.size() < 5; + + d.resize(8); + + if (need_to_set_default_color) { + d[4] = Color(1, 1, 1); + } + } + + Item::CommandRect *rect = memnew(Item::CommandRect); + ERR_FAIL_COND(!rect); + + real_t frame_time = d[0]; + total_frame_time += frame_time; + Rect2 tex_rect = d[1]; //const Rect2 &p_rect + rect->rect = tex_rect; + rect->texture = d[2]; //RID p_texture + Rect2 tex_src_rect = d[3]; //const Rect2 &p_src_rect + rect->source = tex_src_rect; + rect->modulate = d[4]; //const Color &p_modulate = Color(1, 1, 1) + bool transpose = d[5]; //bool p_transpose = false + rect->normal_map = d[6]; //RID p_normal_map = RID() + bool clip_uv = d[7]; //bool p_clip_uv = false + + rect->flags = RasterizerCanvas::CANVAS_RECT_REGION; + + if (tex_rect.size.x < 0) { + rect->flags |= RasterizerCanvas::CANVAS_RECT_FLIP_H; + rect->rect.size.x = -rect->rect.size.x; + } + if (tex_src_rect.size.x < 0) { + rect->flags ^= RasterizerCanvas::CANVAS_RECT_FLIP_H; + rect->source.size.x = -rect->source.size.x; + } + if (tex_rect.size.y < 0) { + rect->flags |= RasterizerCanvas::CANVAS_RECT_FLIP_V; + rect->rect.size.y = -rect->rect.size.y; + } + if (tex_src_rect.size.y < 0) { + rect->flags ^= RasterizerCanvas::CANVAS_RECT_FLIP_V; + rect->source.size.y = -rect->source.size.y; + } + + if (transpose) { + rect->flags |= RasterizerCanvas::CANVAS_RECT_TRANSPOSE; + SWAP(rect->rect.size.x, rect->rect.size.y); + } + + if (clip_uv) { + rect->flags |= RasterizerCanvas::CANVAS_RECT_CLIP_UV; + } + + ra->rects.push_back(rect); + ra->times.push_back(frame_time); + } + + ra->total_time = total_frame_time; + + canvas_item->rect_dirty = true; + canvas_item->commands.push_back(ra); + _make_bound_dirty(canvas_item); +} + void RenderingServerCanvas::canvas_item_add_clip_ignore(RID p_item, bool p_ignore) { Item *canvas_item = canvas_item_owner.getornull(p_item); ERR_FAIL_COND(!canvas_item); diff --git a/servers/rendering/rendering_server_canvas.h b/servers/rendering/rendering_server_canvas.h index 04573372d..c9dcd8b67 100644 --- a/servers/rendering/rendering_server_canvas.h +++ b/servers/rendering/rendering_server_canvas.h @@ -247,6 +247,8 @@ public: void canvas_item_add_triangle_array(RID p_item, const Vector &p_indices, const Vector &p_points, const Vector &p_colors, const Vector &p_uvs = Vector(), const Vector &p_bones = Vector(), const Vector &p_weights = Vector(), RID p_texture = RID(), int p_count = -1, RID p_normal_map = RID(), bool p_antialiased = false, bool p_antialiasing_use_indices = false); void canvas_item_add_mesh(RID p_item, const RID &p_mesh, const Transform2D &p_transform = Transform2D(), const Color &p_modulate = Color(1, 1, 1), RID p_texture = RID(), RID p_normal_map = RID()); void canvas_item_add_multimesh(RID p_item, RID p_mesh, RID p_texture = RID(), RID p_normal_map = RID()); + void canvas_item_add_texture_rect_animation(RID p_item, const Array &p_animation_data); + 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_set_sort_children_by_y(RID p_item, bool p_enable); diff --git a/servers/rendering/rendering_server_raster.h b/servers/rendering/rendering_server_raster.h index 770c648b4..eac3a363c 100644 --- a/servers/rendering/rendering_server_raster.h +++ b/servers/rendering/rendering_server_raster.h @@ -612,6 +612,8 @@ public: BIND12(canvas_item_add_triangle_array, RID, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, RID, int, RID, bool, bool) BIND6(canvas_item_add_mesh, RID, const RID &, const Transform2D &, const Color &, RID, RID) BIND4(canvas_item_add_multimesh, RID, RID, RID, RID) + BIND2(canvas_item_add_texture_rect_animation, RID, const Array &) + BIND2(canvas_item_add_set_transform, RID, const Transform2D &) BIND2(canvas_item_add_clip_ignore, RID, bool) BIND2(canvas_item_set_sort_children_by_y, RID, bool) diff --git a/servers/rendering/rendering_server_wrap_mt.h b/servers/rendering/rendering_server_wrap_mt.h index 0b05306e4..a7e38b5f3 100644 --- a/servers/rendering/rendering_server_wrap_mt.h +++ b/servers/rendering/rendering_server_wrap_mt.h @@ -514,6 +514,7 @@ public: FUNC7(canvas_item_add_texture_rect, RID, const Rect2 &, RID, bool, const Color &, bool, RID) FUNC8(canvas_item_add_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &, bool, RID, bool) FUNC7(canvas_item_add_texture_multirect_region, RID, const Vector &, RID, const Vector &, const Color &, uint32_t, RID) + FUNC2(canvas_item_add_texture_rect_animation, RID, const Array &) FUNC11(canvas_item_add_nine_patch, RID, const Rect2 &, const Rect2 &, RID, const Vector2 &, const Vector2 &, NinePatchAxisMode, NinePatchAxisMode, bool, const Color &, RID) FUNC7(canvas_item_add_primitive, RID, const Vector &, const Vector &, const Vector &, RID, float, RID) FUNC7(canvas_item_add_polygon, RID, const Vector &, const Vector &, const Vector &, RID, RID, bool) diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index 1234ec4ef..9271e62c3 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -2155,6 +2155,7 @@ void RenderingServer::_bind_methods() { ClassDB::bind_method(D_METHOD("canvas_item_add_triangle_array", "item", "indices", "points", "colors", "uvs", "bones", "weights", "texture", "count", "normal_map", "antialiased", "antialiasing_use_indices"), &RenderingServer::canvas_item_add_triangle_array, DEFVAL(Vector()), DEFVAL(Vector()), DEFVAL(Vector()), DEFVAL(RID()), DEFVAL(-1), DEFVAL(RID()), DEFVAL(false), DEFVAL(false)); ClassDB::bind_method(D_METHOD("canvas_item_add_mesh", "item", "mesh", "transform", "modulate", "texture", "normal_map"), &RenderingServer::canvas_item_add_mesh, DEFVAL(Transform2D()), DEFVAL(Color(1, 1, 1)), DEFVAL(RID()), DEFVAL(RID())); ClassDB::bind_method(D_METHOD("canvas_item_add_multimesh", "item", "mesh", "texture", "normal_map"), &RenderingServer::canvas_item_add_multimesh, DEFVAL(RID())); + ClassDB::bind_method(D_METHOD("canvas_item_add_texture_rect_animation", "item", "animation_data"), &RenderingServer::canvas_item_add_texture_rect_animation); ClassDB::bind_method(D_METHOD("canvas_item_add_set_transform", "item", "transform"), &RenderingServer::canvas_item_add_set_transform); ClassDB::bind_method(D_METHOD("canvas_item_add_clip_ignore", "item", "ignore"), &RenderingServer::canvas_item_add_clip_ignore); ClassDB::bind_method(D_METHOD("canvas_item_set_sort_children_by_y", "item", "enabled"), &RenderingServer::canvas_item_set_sort_children_by_y); diff --git a/servers/rendering_server.h b/servers/rendering_server.h index 6a8d48b1e..861145338 100644 --- a/servers/rendering_server.h +++ b/servers/rendering_server.h @@ -943,6 +943,8 @@ public: virtual void canvas_item_add_triangle_array(RID p_item, const Vector &p_indices, const Vector &p_points, const Vector &p_colors, const Vector &p_uvs = Vector(), const Vector &p_bones = Vector(), const Vector &p_weights = Vector(), RID p_texture = RID(), int p_count = -1, RID p_normal_map = RID(), bool p_antialiased = false, bool p_antialiasing_use_indices = false) = 0; virtual void canvas_item_add_mesh(RID p_item, const RID &p_mesh, const Transform2D &p_transform = Transform2D(), const Color &p_modulate = Color(1, 1, 1), RID p_texture = RID(), RID p_normal_map = RID()) = 0; virtual void canvas_item_add_multimesh(RID p_item, RID p_mesh, RID p_texture = RID(), RID p_normal_map = RID()) = 0; + virtual void canvas_item_add_texture_rect_animation(RID p_item, const Array &p_animation_data) = 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_set_sort_children_by_y(RID p_item, bool p_enable) = 0;