Browse Source

Fix skinning initialization in MeshInstance when loaded from thread

Fix for a regression from software skinning support:
instance_attach_skeleton wasn't called in set_mesh before, and it's
causing issues when the mesh instance is loaded from a thread.
1. Call from a thread queues instance_attach_skeleton with RID() in the
visual server.
2. Call from the main thread when entering tree calls
instance_attach_skeleton immediately with a valid skeleton
3. Queued instance_attach_skeleton resets the attached skeleton

This change prevents that to happen by making sure
instance_attach_skeleton is not called on set_mesh as it was doing
before, but there might be a more general problem to solve in how
visual server commands are executed when resources are loaded from
a different thread.

(cherry picked from commit feee9f9695e988c0e7192f9c3cc452349e400e4d)
PouleyKetchoupp 4 years ago
parent
commit
703c290b71
2 changed files with 12 additions and 6 deletions
  1. 11 5
      scene/3d/mesh_instance.cpp
  2. 1 1
      scene/3d/mesh_instance.h

+ 11 - 5
scene/3d/mesh_instance.cpp

@@ -143,7 +143,7 @@ void MeshInstance::set_mesh(const Ref<Mesh> &p_mesh) {
 		mesh->connect(CoreStringNames::get_singleton()->changed, this, SceneStringNames::get_singleton()->_mesh_changed);
 		materials.resize(mesh->get_surface_count());
 
-		_initialize_skinning();
+		_initialize_skinning(false, false);
 	} else {
 
 		set_base(RID());
@@ -208,7 +208,7 @@ bool MeshInstance::_is_software_skinning_enabled() const {
 	return global_software_skinning;
 }
 
-void MeshInstance::_initialize_skinning(bool p_force_reset) {
+void MeshInstance::_initialize_skinning(bool p_force_reset, bool p_call_attach_skeleton) {
 	if (mesh.is_null()) {
 		return;
 	}
@@ -324,7 +324,9 @@ void MeshInstance::_initialize_skinning(bool p_force_reset) {
 				update_mesh = true;
 			}
 
-			visual_server->instance_attach_skeleton(get_instance(), RID());
+			if (p_call_attach_skeleton) {
+				visual_server->instance_attach_skeleton(get_instance(), RID());
+			}
 
 			if (is_visible_in_tree() && (software_skinning_flags & SoftwareSkinning::FLAG_BONES_READY)) {
 				// Intialize from current skeleton pose.
@@ -336,7 +338,9 @@ void MeshInstance::_initialize_skinning(bool p_force_reset) {
 				skin_ref->get_skeleton_node()->disconnect("skeleton_updated", this, "_update_skinning");
 			}
 
-			visual_server->instance_attach_skeleton(get_instance(), skin_ref->get_skeleton());
+			if (p_call_attach_skeleton) {
+				visual_server->instance_attach_skeleton(get_instance(), skin_ref->get_skeleton());
+			}
 
 			if (software_skinning) {
 				memdelete(software_skinning);
@@ -345,7 +349,9 @@ void MeshInstance::_initialize_skinning(bool p_force_reset) {
 			}
 		}
 	} else {
-		visual_server->instance_attach_skeleton(get_instance(), RID());
+		if (p_call_attach_skeleton) {
+			visual_server->instance_attach_skeleton(get_instance(), RID());
+		}
 		if (software_skinning) {
 			memdelete(software_skinning);
 			software_skinning = nullptr;

+ 1 - 1
scene/3d/mesh_instance.h

@@ -93,7 +93,7 @@ protected:
 	bool _is_software_skinning_enabled() const;
 	static bool _is_global_software_skinning_enabled();
 
-	void _initialize_skinning(bool p_force_reset = false);
+	void _initialize_skinning(bool p_force_reset = false, bool p_call_attach_skeleton = true);
 	void _update_skinning();
 
 protected: