mirror of
https://github.com/Relintai/pandemonium_engine.git
synced 2024-12-22 11:56:49 +01:00
Added a new canvas_item_add_texture_rect_animation() method to the RenderingServer.
This commit is contained in:
parent
d38e9256b6
commit
2934369381
@ -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);
|
||||
}
|
||||
|
@ -69,6 +69,9 @@ private:
|
||||
public:
|
||||
void initialize();
|
||||
RasterizerCanvasGLES2();
|
||||
|
||||
protected:
|
||||
virtual void _update_texture_rect_animation(RasterizerCanvas::Item::CommandRectAnimation *p_item);
|
||||
};
|
||||
|
||||
#endif // RASTERIZERCANVASGLES2_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<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
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user