Ported: 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".
-lawnjelly
18bb668a2e
This commit is contained in:
Relintai 2022-08-07 16:01:27 +02:00
parent eed219ada1
commit 2e628b7fa8
4 changed files with 45 additions and 11 deletions

View File

@ -476,6 +476,7 @@ public:
Transform skeleton_bone_get_transform(RID p_skeleton, int p_bone) const { return Transform(); } 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) {} 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(); } 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 */ /* Light API */

View File

@ -3731,6 +3731,8 @@ void RasterizerStorageGLES2::skeleton_bone_set_transform_2d(RID p_skeleton, int
if (!skeleton->update_list.in_list()) { if (!skeleton->update_list.in_list()) {
skeleton_update_list.add(&skeleton->update_list); skeleton_update_list.add(&skeleton->update_list);
} }
skeleton->revision++;
} }
Transform2D RasterizerStorageGLES2::skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const { Transform2D RasterizerStorageGLES2::skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const {
@ -3763,6 +3765,12 @@ void RasterizerStorageGLES2::skeleton_set_base_transform_2d(RID p_skeleton, cons
skeleton->base_transform_2d = p_base_transform; 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() { void RasterizerStorageGLES2::update_dirty_blend_shapes() {
while (blend_shapes_update_list.first()) { while (blend_shapes_update_list.first()) {
Mesh *mesh = blend_shapes_update_list.first()->self(); Mesh *mesh = blend_shapes_update_list.first()->self();

View File

@ -888,6 +888,7 @@ public:
bool use_2d; bool use_2d;
int size; int size;
uint32_t revision;
// TODO use float textures for storage // TODO use float textures for storage
@ -903,6 +904,7 @@ public:
Skeleton() : Skeleton() :
use_2d(false), use_2d(false),
size(0), size(0),
revision(1),
tex_id(0), tex_id(0),
update_list(this) { update_list(this) {
} }
@ -922,6 +924,7 @@ public:
virtual void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform); 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 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 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); void _update_skeleton_transform_buffer(const PoolVector<float> &p_data, size_t p_size);

View File

@ -429,6 +429,7 @@ public:
virtual void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) = 0; 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 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 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 */ /* Light API */
@ -804,19 +805,24 @@ public:
}; };
Transform2D xform; Transform2D xform;
bool clip; bool clip : 1;
bool visible; bool visible : 1;
bool behind; bool behind : 1;
bool update_when_visible; bool update_when_visible : 1;
//VS::MaterialBlendMode blend_mode; bool distance_field : 1;
int light_mask; bool light_masked : 1;
mutable bool custom_rect : 1;
mutable bool rect_dirty : 1;
Vector<Command *> commands; Vector<Command *> commands;
mutable bool custom_rect;
mutable bool rect_dirty;
mutable Rect2 rect; mutable Rect2 rect;
RID material; RID material;
RID skeleton; RID skeleton;
//VS::MaterialBlendMode blend_mode;
int32_t light_mask;
mutable uint32_t skeleton_revision;
Item *next; Item *next;
struct CopyBackBuffer { struct CopyBackBuffer {
@ -832,16 +838,31 @@ public:
Item *final_clip_owner; Item *final_clip_owner;
Item *material_owner; Item *material_owner;
ViewportRender *vp_render; ViewportRender *vp_render;
bool distance_field;
bool light_masked;
Rect2 global_rect_cache; Rect2 global_rect_cache;
const Rect2 &get_rect() const { const Rect2 &get_rect() const {
if (custom_rect || (!rect_dirty && !update_when_visible)) { if (custom_rect) {
return 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 //must update rect
int s = commands.size(); int s = commands.size();
if (s == 0) { if (s == 0) {
@ -1020,6 +1041,7 @@ public:
} }
Item() { Item() {
light_mask = 1; light_mask = 1;
skeleton_revision = 0;
vp_render = nullptr; vp_render = nullptr;
next = nullptr; next = nullptr;
final_clip_owner = nullptr; final_clip_owner = nullptr;