2
0
Эх сурвалжийг харах

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 3 жил өмнө
parent
commit
18bb668a2e

+ 1 - 0
drivers/dummy/rasterizer_dummy.h

@@ -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 */
 

+ 7 - 0
drivers/gles2/rasterizer_storage_gles2.cpp

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

+ 3 - 0
drivers/gles2/rasterizer_storage_gles2.h

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

+ 8 - 0
drivers/gles3/rasterizer_storage_gles3.cpp

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

+ 3 - 0
drivers/gles3/rasterizer_storage_gles3.h

@@ -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 */
 

+ 32 - 11
servers/visual/rasterizer.h

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