Added a new canvas_item_add_texture_rect_animation() method to the RenderingServer.

This commit is contained in:
Relintai 2024-03-11 18:21:05 +01:00
parent d38e9256b6
commit 2934369381
10 changed files with 450 additions and 6 deletions

View File

@ -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<Item::CommandRect *>(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<RasterizerCanvas::Item::CommandRectAnimation *>(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<real_t>(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<RasterizerCanvas::Item::CommandRectAnimation *>(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<real_t>(storage->frame.delta));
// If we are rendering an animation, send redraw request
RenderingServerRaster::redraw_request(false);
}

View File

@ -69,6 +69,9 @@ private:
public:
void initialize();
RasterizerCanvasGLES2();
protected:
virtual void _update_texture_rect_animation(RasterizerCanvas::Item::CommandRectAnimation *p_item);
};
#endif // RASTERIZERCANVASGLES2_H

View File

@ -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<RasterizerCanvas::Item::CommandRectAnimation *>(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<true>(rect, r_fill_state, r_command_start, command_num, command_count, commands, p_item, multiply_final_modulate);
} else {
buffer_full = _prefill_rect<false>(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

View File

@ -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<CommandRect *> rects;
Vector<real_t> 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<const Item::CommandRectAnimation *>(c);
r = crectanim->get_command_rect()->rect;
} break;
}
if (found_xform) {

View File

@ -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);

View File

@ -247,6 +247,8 @@ public:
void canvas_item_add_triangle_array(RID p_item, const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), const Vector<int> &p_bones = Vector<int>(), const Vector<float> &p_weights = Vector<float>(), 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);

View File

@ -612,6 +612,8 @@ public:
BIND12(canvas_item_add_triangle_array, RID, const Vector<int> &, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, const Vector<int> &, const Vector<float> &, 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)

View File

@ -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<Rect2> &, RID, const Vector<Rect2> &, 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<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, float, RID)
FUNC7(canvas_item_add_polygon, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, RID, bool)

View File

@ -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<Point2>()), DEFVAL(Vector<int>()), DEFVAL(Vector<float>()), 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);

View File

@ -943,6 +943,8 @@ public:
virtual void canvas_item_add_triangle_array(RID p_item, const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), const Vector<int> &p_bones = Vector<int>(), const Vector<float> &p_weights = Vector<float>(), 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;