Fix skeleton 2D stale bounding rect

Adds special logic for handling skeleton bounding rect updates. Previously these were never being updated because the canvas item is never set to "rect_dirty".
This commit is contained in:
lawnjelly 2022-07-16 13:27:48 +01:00
parent c55e8dd516
commit 18bb668a2e
6 changed files with 54 additions and 11 deletions

View File

@ -483,6 +483,7 @@ public:
Transform skeleton_bone_get_transform(RID p_skeleton, int p_bone) const { return Transform(); }
void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) {}
Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const { return Transform2D(); }
uint32_t skeleton_get_revision(RID p_skeleton) const { return 0; }
/* Light API */

View File

@ -3731,6 +3731,7 @@ void RasterizerStorageGLES2::skeleton_bone_set_transform_2d(RID p_skeleton, int
if (!skeleton->update_list.in_list()) {
skeleton_update_list.add(&skeleton->update_list);
}
skeleton->revision++;
}
Transform2D RasterizerStorageGLES2::skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const {
@ -3763,6 +3764,12 @@ void RasterizerStorageGLES2::skeleton_set_base_transform_2d(RID p_skeleton, cons
skeleton->base_transform_2d = p_base_transform;
}
uint32_t RasterizerStorageGLES2::skeleton_get_revision(RID p_skeleton) const {
const Skeleton *skeleton = skeleton_owner.getornull(p_skeleton);
ERR_FAIL_COND_V(!skeleton, 0);
return skeleton->revision;
}
void RasterizerStorageGLES2::update_dirty_blend_shapes() {
while (blend_shapes_update_list.first()) {
Mesh *mesh = blend_shapes_update_list.first()->self();

View File

@ -890,6 +890,7 @@ public:
bool use_2d;
int size;
uint32_t revision;
// TODO use float textures for storage
@ -905,6 +906,7 @@ public:
Skeleton() :
use_2d(false),
size(0),
revision(1),
tex_id(0),
update_list(this) {
}
@ -924,6 +926,7 @@ public:
virtual void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform);
virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const;
virtual void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform);
virtual uint32_t skeleton_get_revision(RID p_skeleton) const;
void _update_skeleton_transform_buffer(const PoolVector<float> &p_data, size_t p_size);

View File

@ -5277,6 +5277,8 @@ void RasterizerStorageGLES3::skeleton_bone_set_transform_2d(RID p_skeleton, int
if (!skeleton->update_list.in_list()) {
skeleton_update_list.add(&skeleton->update_list);
}
skeleton->revision++;
}
Transform2D RasterizerStorageGLES3::skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const {
Skeleton *skeleton = skeleton_owner.getornull(p_skeleton);
@ -5310,6 +5312,12 @@ void RasterizerStorageGLES3::skeleton_set_base_transform_2d(RID p_skeleton, cons
skeleton->base_transform_2d = p_base_transform;
}
uint32_t RasterizerStorageGLES3::skeleton_get_revision(RID p_skeleton) const {
const Skeleton *skeleton = skeleton_owner.getornull(p_skeleton);
ERR_FAIL_COND_V(!skeleton, 0);
return skeleton->revision;
}
void RasterizerStorageGLES3::update_dirty_skeletons() {
glActiveTexture(GL_TEXTURE0);

View File

@ -920,6 +920,7 @@ public:
struct Skeleton : RID_Data {
bool use_2d;
int size;
uint32_t revision;
Vector<float> skel_texture;
GLuint texture;
SelfList<Skeleton> update_list;
@ -929,6 +930,7 @@ public:
Skeleton() :
use_2d(false),
size(0),
revision(1),
texture(0),
update_list(this) {
}
@ -948,6 +950,7 @@ public:
virtual void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform);
virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const;
virtual void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform);
virtual uint32_t skeleton_get_revision(RID p_skeleton) const;
/* Light API */

View File

@ -448,6 +448,7 @@ public:
virtual void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) = 0;
virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const = 0;
virtual void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) = 0;
virtual uint32_t skeleton_get_revision(RID p_skeleton) const = 0;
/* Light API */
@ -947,19 +948,24 @@ public:
};
Transform2D xform;
bool clip;
bool visible;
bool behind;
bool update_when_visible;
//VS::MaterialBlendMode blend_mode;
int light_mask;
bool clip : 1;
bool visible : 1;
bool behind : 1;
bool update_when_visible : 1;
bool distance_field : 1;
bool light_masked : 1;
mutable bool custom_rect : 1;
mutable bool rect_dirty : 1;
Vector<Command *> commands;
mutable bool custom_rect;
mutable bool rect_dirty;
mutable Rect2 rect;
RID material;
RID skeleton;
//VS::MaterialBlendMode blend_mode;
int32_t light_mask;
mutable uint32_t skeleton_revision;
Item *next;
struct CopyBackBuffer {
@ -975,15 +981,29 @@ public:
Item *final_clip_owner;
Item *material_owner;
ViewportRender *vp_render;
bool distance_field;
bool light_masked;
Rect2 global_rect_cache;
const Rect2 &get_rect() const {
if (custom_rect || (!rect_dirty && !update_when_visible)) {
if (custom_rect) {
return rect;
}
if (!rect_dirty && !update_when_visible) {
if (skeleton == RID()) {
return rect;
} else {
// special case for skeletons
uint32_t rev = RasterizerStorage::base_singleton->skeleton_get_revision(skeleton);
if (rev == skeleton_revision) {
// no change to the skeleton since we last calculated the bounding rect
return rect;
} else {
// We need to recalculate.
// Mark as done for next time.
skeleton_revision = rev;
}
}
}
//must update rect
int s = commands.size();
@ -1171,6 +1191,7 @@ public:
}
Item() {
light_mask = 1;
skeleton_revision = 0;
vp_render = nullptr;
next = nullptr;
final_clip_owner = nullptr;