From 2e628b7fa8b76b3bf102bdf3bd25f6c2bcc948de Mon Sep 17 00:00:00 2001 From: Relintai Date: Sun, 7 Aug 2022 16:01:27 +0200 Subject: [PATCH] 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 https://github.com/godotengine/godot/commit/18bb668a2ec4207828a52928760c7e8445740a96 --- drivers/dummy/rasterizer_dummy.h | 1 + drivers/gles2/rasterizer_storage_gles2.cpp | 8 ++++ drivers/gles2/rasterizer_storage_gles2.h | 3 ++ servers/visual/rasterizer.h | 44 ++++++++++++++++------ 4 files changed, 45 insertions(+), 11 deletions(-) diff --git a/drivers/dummy/rasterizer_dummy.h b/drivers/dummy/rasterizer_dummy.h index 701d2ff0b..49efec3e5 100644 --- a/drivers/dummy/rasterizer_dummy.h +++ b/drivers/dummy/rasterizer_dummy.h @@ -476,6 +476,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 */ diff --git a/drivers/gles2/rasterizer_storage_gles2.cpp b/drivers/gles2/rasterizer_storage_gles2.cpp index ca67648b2..0cb20e7b4 100644 --- a/drivers/gles2/rasterizer_storage_gles2.cpp +++ b/drivers/gles2/rasterizer_storage_gles2.cpp @@ -3731,6 +3731,8 @@ 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 +3765,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(); diff --git a/drivers/gles2/rasterizer_storage_gles2.h b/drivers/gles2/rasterizer_storage_gles2.h index bb5e0d969..7d6085f0e 100644 --- a/drivers/gles2/rasterizer_storage_gles2.h +++ b/drivers/gles2/rasterizer_storage_gles2.h @@ -888,6 +888,7 @@ public: bool use_2d; int size; + uint32_t revision; // TODO use float textures for storage @@ -903,6 +904,7 @@ public: Skeleton() : use_2d(false), size(0), + revision(1), tex_id(0), 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 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 &p_data, size_t p_size); diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h index e7e0592cc..234e8a891 100644 --- a/servers/visual/rasterizer.h +++ b/servers/visual/rasterizer.h @@ -429,6 +429,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 */ @@ -804,19 +805,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 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 { @@ -832,16 +838,31 @@ 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(); if (s == 0) { @@ -1020,6 +1041,7 @@ public: } Item() { light_mask = 1; + skeleton_revision = 0; vp_render = nullptr; next = nullptr; final_clip_owner = nullptr;