Selaa lähdekoodia

Fix console errors and crash in cleanup code for PhysicalBoneSimulator3D

Mike Estee 6 kuukautta sitten
vanhempi
commit
d39003c0bf

+ 8 - 3
scene/3d/physical_bone_simulator_3d.cpp

@@ -73,9 +73,14 @@ void PhysicalBoneSimulator3D::_pose_updated() {
 	if (!skeleton || simulating) {
 		return;
 	}
-	ERR_FAIL_COND(skeleton->get_bone_count() != bones.size());
-	for (int i = 0; i < skeleton->get_bone_count(); i++) {
-		_bone_pose_updated(skeleton, i);
+	// If this triggers that means that we likely haven't rebuilt the bone list yet.
+	if (skeleton->get_bone_count() != bones.size()) {
+		// NOTE: this is re-entrant and will call _pose_updated again.
+		_bone_list_changed();
+	} else {
+		for (int i = 0; i < skeleton->get_bone_count(); i++) {
+			_bone_pose_updated(skeleton, i);
+		}
 	}
 }
 

+ 6 - 2
scene/3d/physics/physical_bone_3d.cpp

@@ -752,8 +752,9 @@ void PhysicalBone3D::_get_property_list(List<PropertyInfo> *p_list) const {
 
 void PhysicalBone3D::_notification(int p_what) {
 	switch (p_what) {
-		case NOTIFICATION_ENTER_TREE:
-		case NOTIFICATION_PARENTED:
+		// We need to wait until the bone has finished being added to the tree
+		// or none of the global transform calls will work correctly.
+		case NOTIFICATION_POST_ENTER_TREE:
 			_update_simulator_path();
 			update_bone_id();
 			reset_to_rest_position();
@@ -763,6 +764,9 @@ void PhysicalBone3D::_notification(int p_what) {
 			}
 			break;
 
+		// If we're detached from the skeleton we need to
+		// clear our references to it.
+		case NOTIFICATION_UNPARENTED:
 		case NOTIFICATION_EXIT_TREE: {
 			PhysicalBoneSimulator3D *simulator = get_simulator();
 			if (simulator) {

+ 9 - 0
scene/3d/skeleton_3d.cpp

@@ -838,6 +838,13 @@ bool Skeleton3D::is_show_rest_only() const {
 void Skeleton3D::clear_bones() {
 	bones.clear();
 	name_to_bone_index.clear();
+
+	// All these structures contain references to now invalid bone indices.
+	skin_bindings.clear();
+	bone_global_pose_dirty.clear();
+	parentless_bones.clear();
+	nested_set_offset_to_bone_index.clear();
+
 	process_order_dirty = true;
 	version++;
 	_make_dirty();
@@ -1091,6 +1098,8 @@ void Skeleton3D::_force_update_bone_children_transforms(int p_bone_idx) const {
 	const int bone_size = bones.size();
 	ERR_FAIL_INDEX(p_bone_idx, bone_size);
 
+	_update_process_order();
+
 	Bone *bonesptr = bones.ptr();
 
 	// Loop through nested set.