| 1 | /**************************************************************************/ | 
| 2 | /*  skeleton_3d.cpp                                                       */ | 
| 3 | /**************************************************************************/ | 
| 4 | /*                         This file is part of:                          */ | 
| 5 | /*                             GODOT ENGINE                               */ | 
| 6 | /*                        https://godotengine.org                         */ | 
| 7 | /**************************************************************************/ | 
| 8 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ | 
| 9 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur.                  */ | 
| 10 | /*                                                                        */ | 
| 11 | /* Permission is hereby granted, free of charge, to any person obtaining  */ | 
| 12 | /* a copy of this software and associated documentation files (the        */ | 
| 13 | /* "Software"), to deal in the Software without restriction, including    */ | 
| 14 | /* without limitation the rights to use, copy, modify, merge, publish,    */ | 
| 15 | /* distribute, sublicense, and/or sell copies of the Software, and to     */ | 
| 16 | /* permit persons to whom the Software is furnished to do so, subject to  */ | 
| 17 | /* the following conditions:                                              */ | 
| 18 | /*                                                                        */ | 
| 19 | /* The above copyright notice and this permission notice shall be         */ | 
| 20 | /* included in all copies or substantial portions of the Software.        */ | 
| 21 | /*                                                                        */ | 
| 22 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,        */ | 
| 23 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF     */ | 
| 24 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ | 
| 25 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY   */ | 
| 26 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,   */ | 
| 27 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE      */ | 
| 28 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                 */ | 
| 29 | /**************************************************************************/ | 
| 30 |  | 
| 31 | #include "skeleton_3d.h" | 
| 32 |  | 
| 33 | #include "core/object/message_queue.h" | 
| 34 | #include "core/variant/type_info.h" | 
| 35 | #include "scene/3d/physics_body_3d.h" | 
| 36 | #include "scene/resources/surface_tool.h" | 
| 37 | #include "scene/scene_string_names.h" | 
| 38 |  | 
| 39 | void SkinReference::_skin_changed() { | 
| 40 | 	if (skeleton_node) { | 
| 41 | 		skeleton_node->_make_dirty(); | 
| 42 | 	} | 
| 43 | 	skeleton_version = 0; | 
| 44 | } | 
| 45 |  | 
| 46 | void SkinReference::_bind_methods() { | 
| 47 | 	ClassDB::bind_method(D_METHOD("get_skeleton" ), &SkinReference::get_skeleton); | 
| 48 | 	ClassDB::bind_method(D_METHOD("get_skin" ), &SkinReference::get_skin); | 
| 49 | } | 
| 50 |  | 
| 51 | RID SkinReference::get_skeleton() const { | 
| 52 | 	return skeleton; | 
| 53 | } | 
| 54 |  | 
| 55 | Ref<Skin> SkinReference::get_skin() const { | 
| 56 | 	return skin; | 
| 57 | } | 
| 58 |  | 
| 59 | SkinReference::~SkinReference() { | 
| 60 | 	ERR_FAIL_NULL(RenderingServer::get_singleton()); | 
| 61 | 	if (skeleton_node) { | 
| 62 | 		skeleton_node->skin_bindings.erase(this); | 
| 63 | 	} | 
| 64 | 	RS::get_singleton()->free(skeleton); | 
| 65 | } | 
| 66 |  | 
| 67 | /////////////////////////////////////// | 
| 68 |  | 
| 69 | bool Skeleton3D::_set(const StringName &p_path, const Variant &p_value) { | 
| 70 | 	String path = p_path; | 
| 71 |  | 
| 72 | 	if (!path.begins_with("bones/" )) { | 
| 73 | 		return false; | 
| 74 | 	} | 
| 75 |  | 
| 76 | 	int which = path.get_slicec('/', 1).to_int(); | 
| 77 | 	String what = path.get_slicec('/', 2); | 
| 78 |  | 
| 79 | 	if (which == bones.size() && what == "name" ) { | 
| 80 | 		add_bone(p_value); | 
| 81 | 		return true; | 
| 82 | 	} | 
| 83 |  | 
| 84 | 	ERR_FAIL_INDEX_V(which, bones.size(), false); | 
| 85 |  | 
| 86 | 	if (what == "parent" ) { | 
| 87 | 		set_bone_parent(which, p_value); | 
| 88 | 	} else if (what == "rest" ) { | 
| 89 | 		set_bone_rest(which, p_value); | 
| 90 | 	} else if (what == "enabled" ) { | 
| 91 | 		set_bone_enabled(which, p_value); | 
| 92 | 	} else if (what == "position" ) { | 
| 93 | 		set_bone_pose_position(which, p_value); | 
| 94 | 	} else if (what == "rotation" ) { | 
| 95 | 		set_bone_pose_rotation(which, p_value); | 
| 96 | 	} else if (what == "scale" ) { | 
| 97 | 		set_bone_pose_scale(which, p_value); | 
| 98 | 	} else { | 
| 99 | 		return false; | 
| 100 | 	} | 
| 101 |  | 
| 102 | 	return true; | 
| 103 | } | 
| 104 |  | 
| 105 | bool Skeleton3D::_get(const StringName &p_path, Variant &r_ret) const { | 
| 106 | 	String path = p_path; | 
| 107 |  | 
| 108 | 	if (!path.begins_with("bones/" )) { | 
| 109 | 		return false; | 
| 110 | 	} | 
| 111 |  | 
| 112 | 	int which = path.get_slicec('/', 1).to_int(); | 
| 113 | 	String what = path.get_slicec('/', 2); | 
| 114 |  | 
| 115 | 	ERR_FAIL_INDEX_V(which, bones.size(), false); | 
| 116 |  | 
| 117 | 	if (what == "name" ) { | 
| 118 | 		r_ret = get_bone_name(which); | 
| 119 | 	} else if (what == "parent" ) { | 
| 120 | 		r_ret = get_bone_parent(which); | 
| 121 | 	} else if (what == "rest" ) { | 
| 122 | 		r_ret = get_bone_rest(which); | 
| 123 | 	} else if (what == "enabled" ) { | 
| 124 | 		r_ret = is_bone_enabled(which); | 
| 125 | 	} else if (what == "position" ) { | 
| 126 | 		r_ret = get_bone_pose_position(which); | 
| 127 | 	} else if (what == "rotation" ) { | 
| 128 | 		r_ret = get_bone_pose_rotation(which); | 
| 129 | 	} else if (what == "scale" ) { | 
| 130 | 		r_ret = get_bone_pose_scale(which); | 
| 131 | 	} else { | 
| 132 | 		return false; | 
| 133 | 	} | 
| 134 |  | 
| 135 | 	return true; | 
| 136 | } | 
| 137 |  | 
| 138 | void Skeleton3D::_get_property_list(List<PropertyInfo> *p_list) const { | 
| 139 | 	for (int i = 0; i < bones.size(); i++) { | 
| 140 | 		const String prep = vformat("%s/%d/" , PNAME("bones" ), i); | 
| 141 | 		p_list->push_back(PropertyInfo(Variant::STRING, prep + PNAME("name" ), PROPERTY_HINT_NONE, "" , PROPERTY_USAGE_NO_EDITOR)); | 
| 142 | 		p_list->push_back(PropertyInfo(Variant::INT, prep + PNAME("parent" ), PROPERTY_HINT_RANGE, "-1,"  + itos(bones.size() - 1) + ",1" , PROPERTY_USAGE_NO_EDITOR)); | 
| 143 | 		p_list->push_back(PropertyInfo(Variant::TRANSFORM3D, prep + PNAME("rest" ), PROPERTY_HINT_NONE, "" , PROPERTY_USAGE_NO_EDITOR)); | 
| 144 | 		p_list->push_back(PropertyInfo(Variant::BOOL, prep + PNAME("enabled" ), PROPERTY_HINT_NONE, "" , PROPERTY_USAGE_NO_EDITOR)); | 
| 145 | 		p_list->push_back(PropertyInfo(Variant::VECTOR3, prep + PNAME("position" ), PROPERTY_HINT_NONE, "" , PROPERTY_USAGE_NO_EDITOR)); | 
| 146 | 		p_list->push_back(PropertyInfo(Variant::QUATERNION, prep + PNAME("rotation" ), PROPERTY_HINT_NONE, "" , PROPERTY_USAGE_NO_EDITOR)); | 
| 147 | 		p_list->push_back(PropertyInfo(Variant::VECTOR3, prep + PNAME("scale" ), PROPERTY_HINT_NONE, "" , PROPERTY_USAGE_NO_EDITOR)); | 
| 148 | 	} | 
| 149 |  | 
| 150 | 	for (PropertyInfo &E : *p_list) { | 
| 151 | 		_validate_property(E); | 
| 152 | 	} | 
| 153 | } | 
| 154 |  | 
| 155 | void Skeleton3D::_validate_property(PropertyInfo &p_property) const { | 
| 156 | 	PackedStringArray split = p_property.name.split("/" ); | 
| 157 | 	if (split.size() == 3 && split[0] == "bones" ) { | 
| 158 | 		if (split[2] == "rest" ) { | 
| 159 | 			p_property.usage |= PROPERTY_USAGE_READ_ONLY; | 
| 160 | 		} | 
| 161 | 		if (is_show_rest_only()) { | 
| 162 | 			if (split[2] == "enabled" ) { | 
| 163 | 				p_property.usage |= PROPERTY_USAGE_READ_ONLY; | 
| 164 | 			} | 
| 165 | 			if (split[2] == "position" ) { | 
| 166 | 				p_property.usage |= PROPERTY_USAGE_READ_ONLY; | 
| 167 | 			} | 
| 168 | 			if (split[2] == "rotation" ) { | 
| 169 | 				p_property.usage |= PROPERTY_USAGE_READ_ONLY; | 
| 170 | 			} | 
| 171 | 			if (split[2] == "scale" ) { | 
| 172 | 				p_property.usage |= PROPERTY_USAGE_READ_ONLY; | 
| 173 | 			} | 
| 174 | 		} else if (!is_bone_enabled(split[1].to_int())) { | 
| 175 | 			if (split[2] == "position" ) { | 
| 176 | 				p_property.usage |= PROPERTY_USAGE_READ_ONLY; | 
| 177 | 			} | 
| 178 | 			if (split[2] == "rotation" ) { | 
| 179 | 				p_property.usage |= PROPERTY_USAGE_READ_ONLY; | 
| 180 | 			} | 
| 181 | 			if (split[2] == "scale" ) { | 
| 182 | 				p_property.usage |= PROPERTY_USAGE_READ_ONLY; | 
| 183 | 			} | 
| 184 | 		} | 
| 185 | 	} | 
| 186 | } | 
| 187 |  | 
| 188 | void Skeleton3D::_update_process_order() { | 
| 189 | 	if (!process_order_dirty) { | 
| 190 | 		return; | 
| 191 | 	} | 
| 192 |  | 
| 193 | 	Bone *bonesptr = bones.ptrw(); | 
| 194 | 	int len = bones.size(); | 
| 195 |  | 
| 196 | 	parentless_bones.clear(); | 
| 197 |  | 
| 198 | 	for (int i = 0; i < len; i++) { | 
| 199 | 		bonesptr[i].child_bones.clear(); | 
| 200 | 	} | 
| 201 |  | 
| 202 | 	for (int i = 0; i < len; i++) { | 
| 203 | 		if (bonesptr[i].parent >= len) { | 
| 204 | 			// Validate this just in case. | 
| 205 | 			ERR_PRINT("Bone "  + itos(i) + " has invalid parent: "  + itos(bonesptr[i].parent)); | 
| 206 | 			bonesptr[i].parent = -1; | 
| 207 | 		} | 
| 208 |  | 
| 209 | 		if (bonesptr[i].parent != -1) { | 
| 210 | 			int parent_bone_idx = bonesptr[i].parent; | 
| 211 |  | 
| 212 | 			// Check to see if this node is already added to the parent. | 
| 213 | 			if (bonesptr[parent_bone_idx].child_bones.find(i) < 0) { | 
| 214 | 				// Add the child node. | 
| 215 | 				bonesptr[parent_bone_idx].child_bones.push_back(i); | 
| 216 | 			} else { | 
| 217 | 				ERR_PRINT("Skeleton3D parenthood graph is cyclic" ); | 
| 218 | 			} | 
| 219 | 		} else { | 
| 220 | 			parentless_bones.push_back(i); | 
| 221 | 		} | 
| 222 | 	} | 
| 223 |  | 
| 224 | 	process_order_dirty = false; | 
| 225 | } | 
| 226 |  | 
| 227 | void Skeleton3D::_notification(int p_what) { | 
| 228 | 	switch (p_what) { | 
| 229 | 		case NOTIFICATION_ENTER_TREE: { | 
| 230 | 			if (dirty) { | 
| 231 | 				notification(NOTIFICATION_UPDATE_SKELETON); | 
| 232 | 			} | 
| 233 | 		} break; | 
| 234 | 		case NOTIFICATION_UPDATE_SKELETON: { | 
| 235 | 			RenderingServer *rs = RenderingServer::get_singleton(); | 
| 236 | 			Bone *bonesptr = bones.ptrw(); | 
| 237 |  | 
| 238 | 			int len = bones.size(); | 
| 239 | 			dirty = false; | 
| 240 |  | 
| 241 | 			// Update bone transforms. | 
| 242 | 			force_update_all_bone_transforms(); | 
| 243 |  | 
| 244 | 			// Update skins. | 
| 245 | 			for (SkinReference *E : skin_bindings) { | 
| 246 | 				const Skin *skin = E->skin.operator->(); | 
| 247 | 				RID skeleton = E->skeleton; | 
| 248 | 				uint32_t bind_count = skin->get_bind_count(); | 
| 249 |  | 
| 250 | 				if (E->bind_count != bind_count) { | 
| 251 | 					RS::get_singleton()->skeleton_allocate_data(skeleton, bind_count); | 
| 252 | 					E->bind_count = bind_count; | 
| 253 | 					E->skin_bone_indices.resize(bind_count); | 
| 254 | 					E->skin_bone_indices_ptrs = E->skin_bone_indices.ptrw(); | 
| 255 | 				} | 
| 256 |  | 
| 257 | 				if (E->skeleton_version != version) { | 
| 258 | 					for (uint32_t i = 0; i < bind_count; i++) { | 
| 259 | 						StringName bind_name = skin->get_bind_name(i); | 
| 260 |  | 
| 261 | 						if (bind_name != StringName()) { | 
| 262 | 							// Bind name used, use this. | 
| 263 | 							bool found = false; | 
| 264 | 							for (int j = 0; j < len; j++) { | 
| 265 | 								if (bonesptr[j].name == bind_name) { | 
| 266 | 									E->skin_bone_indices_ptrs[i] = j; | 
| 267 | 									found = true; | 
| 268 | 									break; | 
| 269 | 								} | 
| 270 | 							} | 
| 271 |  | 
| 272 | 							if (!found) { | 
| 273 | 								ERR_PRINT("Skin bind #"  + itos(i) + " contains named bind '"  + String(bind_name) + "' but Skeleton3D has no bone by that name." ); | 
| 274 | 								E->skin_bone_indices_ptrs[i] = 0; | 
| 275 | 							} | 
| 276 | 						} else if (skin->get_bind_bone(i) >= 0) { | 
| 277 | 							int bind_index = skin->get_bind_bone(i); | 
| 278 | 							if (bind_index >= len) { | 
| 279 | 								ERR_PRINT("Skin bind #"  + itos(i) + " contains bone index bind: "  + itos(bind_index) + " , which is greater than the skeleton bone count: "  + itos(len) + "." ); | 
| 280 | 								E->skin_bone_indices_ptrs[i] = 0; | 
| 281 | 							} else { | 
| 282 | 								E->skin_bone_indices_ptrs[i] = bind_index; | 
| 283 | 							} | 
| 284 | 						} else { | 
| 285 | 							ERR_PRINT("Skin bind #"  + itos(i) + " does not contain a name nor a bone index." ); | 
| 286 | 							E->skin_bone_indices_ptrs[i] = 0; | 
| 287 | 						} | 
| 288 | 					} | 
| 289 |  | 
| 290 | 					E->skeleton_version = version; | 
| 291 | 				} | 
| 292 |  | 
| 293 | 				for (uint32_t i = 0; i < bind_count; i++) { | 
| 294 | 					uint32_t bone_index = E->skin_bone_indices_ptrs[i]; | 
| 295 | 					ERR_CONTINUE(bone_index >= (uint32_t)len); | 
| 296 | 					rs->skeleton_bone_set_transform(skeleton, i, bonesptr[bone_index].pose_global * skin->get_bind_pose(i)); | 
| 297 | 				} | 
| 298 | 			} | 
| 299 | 			emit_signal(SceneStringNames::get_singleton()->pose_updated); | 
| 300 | 		} break; | 
| 301 |  | 
| 302 | #ifndef _3D_DISABLED | 
| 303 | 		case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { | 
| 304 | 			// This is active only if the skeleton animates the physical bones | 
| 305 | 			// and the state of the bone is not active. | 
| 306 | 			if (animate_physical_bones) { | 
| 307 | 				for (int i = 0; i < bones.size(); i += 1) { | 
| 308 | 					if (bones[i].physical_bone) { | 
| 309 | 						if (bones[i].physical_bone->is_simulating_physics() == false) { | 
| 310 | 							bones[i].physical_bone->reset_to_rest_position(); | 
| 311 | 						} | 
| 312 | 					} | 
| 313 | 				} | 
| 314 | 			} | 
| 315 | 		} break; | 
| 316 | 		case NOTIFICATION_READY: { | 
| 317 | 			if (Engine::get_singleton()->is_editor_hint()) { | 
| 318 | 				set_physics_process_internal(true); | 
| 319 | 			} | 
| 320 | 		} break; | 
| 321 | #endif // _3D_DISABLED | 
| 322 | 	} | 
| 323 | } | 
| 324 |  | 
| 325 | void Skeleton3D::clear_bones_global_pose_override() { | 
| 326 | 	for (int i = 0; i < bones.size(); i += 1) { | 
| 327 | 		bones.write[i].global_pose_override_amount = 0; | 
| 328 | 		bones.write[i].global_pose_override_reset = true; | 
| 329 | 	} | 
| 330 | 	_make_dirty(); | 
| 331 | } | 
| 332 |  | 
| 333 | void Skeleton3D::set_bone_global_pose_override(int p_bone, const Transform3D &p_pose, real_t p_amount, bool p_persistent) { | 
| 334 | 	const int bone_size = bones.size(); | 
| 335 | 	ERR_FAIL_INDEX(p_bone, bone_size); | 
| 336 | 	bones.write[p_bone].global_pose_override_amount = p_amount; | 
| 337 | 	bones.write[p_bone].global_pose_override = p_pose; | 
| 338 | 	bones.write[p_bone].global_pose_override_reset = !p_persistent; | 
| 339 | 	_make_dirty(); | 
| 340 | } | 
| 341 |  | 
| 342 | Transform3D Skeleton3D::get_bone_global_pose_override(int p_bone) const { | 
| 343 | 	const int bone_size = bones.size(); | 
| 344 | 	ERR_FAIL_INDEX_V(p_bone, bone_size, Transform3D()); | 
| 345 | 	return bones[p_bone].global_pose_override; | 
| 346 | } | 
| 347 |  | 
| 348 | Transform3D Skeleton3D::get_bone_global_pose(int p_bone) const { | 
| 349 | 	const int bone_size = bones.size(); | 
| 350 | 	ERR_FAIL_INDEX_V(p_bone, bone_size, Transform3D()); | 
| 351 | 	if (dirty) { | 
| 352 | 		const_cast<Skeleton3D *>(this)->notification(NOTIFICATION_UPDATE_SKELETON); | 
| 353 | 	} | 
| 354 | 	return bones[p_bone].pose_global; | 
| 355 | } | 
| 356 |  | 
| 357 | Transform3D Skeleton3D::get_bone_global_pose_no_override(int p_bone) const { | 
| 358 | 	const int bone_size = bones.size(); | 
| 359 | 	ERR_FAIL_INDEX_V(p_bone, bone_size, Transform3D()); | 
| 360 | 	if (dirty) { | 
| 361 | 		const_cast<Skeleton3D *>(this)->notification(NOTIFICATION_UPDATE_SKELETON); | 
| 362 | 	} | 
| 363 | 	return bones[p_bone].pose_global_no_override; | 
| 364 | } | 
| 365 |  | 
| 366 | void Skeleton3D::set_motion_scale(float p_motion_scale) { | 
| 367 | 	if (p_motion_scale <= 0) { | 
| 368 | 		motion_scale = 1; | 
| 369 | 		ERR_FAIL_MSG("Motion scale must be larger than 0." ); | 
| 370 | 	} | 
| 371 | 	motion_scale = p_motion_scale; | 
| 372 | } | 
| 373 |  | 
| 374 | float Skeleton3D::get_motion_scale() const { | 
| 375 | 	ERR_FAIL_COND_V(motion_scale <= 0, 1); | 
| 376 | 	return motion_scale; | 
| 377 | } | 
| 378 |  | 
| 379 | // Skeleton creation api | 
| 380 |  | 
| 381 | uint64_t Skeleton3D::get_version() const { | 
| 382 | 	return version; | 
| 383 | } | 
| 384 |  | 
| 385 | void Skeleton3D::add_bone(const String &p_name) { | 
| 386 | 	ERR_FAIL_COND(p_name.is_empty() || p_name.contains(":" ) || p_name.contains("/" ) || name_to_bone_index.has(p_name)); | 
| 387 |  | 
| 388 | 	Bone b; | 
| 389 | 	b.name = p_name; | 
| 390 | 	bones.push_back(b); | 
| 391 | 	name_to_bone_index.insert(p_name, bones.size() - 1); | 
| 392 | 	process_order_dirty = true; | 
| 393 | 	version++; | 
| 394 | 	rest_dirty = true; | 
| 395 | 	_make_dirty(); | 
| 396 | 	update_gizmos(); | 
| 397 | } | 
| 398 |  | 
| 399 | int Skeleton3D::find_bone(const String &p_name) const { | 
| 400 | 	const int *bone_index_ptr = name_to_bone_index.getptr(p_name); | 
| 401 | 	return bone_index_ptr != nullptr ? *bone_index_ptr : -1; | 
| 402 | } | 
| 403 |  | 
| 404 | String Skeleton3D::get_bone_name(int p_bone) const { | 
| 405 | 	const int bone_size = bones.size(); | 
| 406 | 	ERR_FAIL_INDEX_V(p_bone, bone_size, "" ); | 
| 407 | 	return bones[p_bone].name; | 
| 408 | } | 
| 409 |  | 
| 410 | void Skeleton3D::set_bone_name(int p_bone, const String &p_name) { | 
| 411 | 	const int bone_size = bones.size(); | 
| 412 | 	ERR_FAIL_INDEX(p_bone, bone_size); | 
| 413 |  | 
| 414 | 	const int *bone_index_ptr = name_to_bone_index.getptr(p_name); | 
| 415 | 	if (bone_index_ptr != nullptr) { | 
| 416 | 		ERR_FAIL_COND_MSG(*bone_index_ptr != p_bone, "Skeleton3D: '"  + get_name() + "', bone name:  '"  + p_name + "' already exists." ); | 
| 417 | 		return; // No need to rename, the bone already has the given name. | 
| 418 | 	} | 
| 419 |  | 
| 420 | 	name_to_bone_index.erase(bones[p_bone].name); | 
| 421 | 	bones.write[p_bone].name = p_name; | 
| 422 | 	name_to_bone_index.insert(p_name, p_bone); | 
| 423 |  | 
| 424 | 	version++; | 
| 425 | } | 
| 426 |  | 
| 427 | bool Skeleton3D::is_bone_parent_of(int p_bone, int p_parent_bone_id) const { | 
| 428 | 	int parent_of_bone = get_bone_parent(p_bone); | 
| 429 |  | 
| 430 | 	if (-1 == parent_of_bone) { | 
| 431 | 		return false; | 
| 432 | 	} | 
| 433 |  | 
| 434 | 	if (parent_of_bone == p_parent_bone_id) { | 
| 435 | 		return true; | 
| 436 | 	} | 
| 437 |  | 
| 438 | 	return is_bone_parent_of(parent_of_bone, p_parent_bone_id); | 
| 439 | } | 
| 440 |  | 
| 441 | int Skeleton3D::get_bone_count() const { | 
| 442 | 	return bones.size(); | 
| 443 | } | 
| 444 |  | 
| 445 | void Skeleton3D::set_bone_parent(int p_bone, int p_parent) { | 
| 446 | 	const int bone_size = bones.size(); | 
| 447 | 	ERR_FAIL_INDEX(p_bone, bone_size); | 
| 448 | 	ERR_FAIL_COND(p_parent != -1 && (p_parent < 0)); | 
| 449 | 	ERR_FAIL_COND(p_bone == p_parent); | 
| 450 |  | 
| 451 | 	bones.write[p_bone].parent = p_parent; | 
| 452 | 	process_order_dirty = true; | 
| 453 | 	rest_dirty = true; | 
| 454 | 	_make_dirty(); | 
| 455 | } | 
| 456 |  | 
| 457 | void Skeleton3D::unparent_bone_and_rest(int p_bone) { | 
| 458 | 	const int bone_size = bones.size(); | 
| 459 | 	ERR_FAIL_INDEX(p_bone, bone_size); | 
| 460 |  | 
| 461 | 	_update_process_order(); | 
| 462 |  | 
| 463 | 	int parent = bones[p_bone].parent; | 
| 464 | 	while (parent >= 0) { | 
| 465 | 		bones.write[p_bone].rest = bones[parent].rest * bones[p_bone].rest; | 
| 466 | 		parent = bones[parent].parent; | 
| 467 | 	} | 
| 468 |  | 
| 469 | 	bones.write[p_bone].parent = -1; | 
| 470 | 	process_order_dirty = true; | 
| 471 |  | 
| 472 | 	rest_dirty = true; | 
| 473 | 	_make_dirty(); | 
| 474 | } | 
| 475 |  | 
| 476 | int Skeleton3D::get_bone_parent(int p_bone) const { | 
| 477 | 	const int bone_size = bones.size(); | 
| 478 | 	ERR_FAIL_INDEX_V(p_bone, bone_size, -1); | 
| 479 | 	if (process_order_dirty) { | 
| 480 | 		const_cast<Skeleton3D *>(this)->_update_process_order(); | 
| 481 | 	} | 
| 482 | 	return bones[p_bone].parent; | 
| 483 | } | 
| 484 |  | 
| 485 | Vector<int> Skeleton3D::get_bone_children(int p_bone) const { | 
| 486 | 	const int bone_size = bones.size(); | 
| 487 | 	ERR_FAIL_INDEX_V(p_bone, bone_size, Vector<int>()); | 
| 488 | 	if (process_order_dirty) { | 
| 489 | 		const_cast<Skeleton3D *>(this)->_update_process_order(); | 
| 490 | 	} | 
| 491 | 	return bones[p_bone].child_bones; | 
| 492 | } | 
| 493 |  | 
| 494 | Vector<int> Skeleton3D::get_parentless_bones() const { | 
| 495 | 	if (process_order_dirty) { | 
| 496 | 		const_cast<Skeleton3D *>(this)->_update_process_order(); | 
| 497 | 	} | 
| 498 | 	return parentless_bones; | 
| 499 | } | 
| 500 |  | 
| 501 | void Skeleton3D::set_bone_rest(int p_bone, const Transform3D &p_rest) { | 
| 502 | 	const int bone_size = bones.size(); | 
| 503 | 	ERR_FAIL_INDEX(p_bone, bone_size); | 
| 504 |  | 
| 505 | 	bones.write[p_bone].rest = p_rest; | 
| 506 | 	rest_dirty = true; | 
| 507 | 	_make_dirty(); | 
| 508 | } | 
| 509 | Transform3D Skeleton3D::get_bone_rest(int p_bone) const { | 
| 510 | 	const int bone_size = bones.size(); | 
| 511 | 	ERR_FAIL_INDEX_V(p_bone, bone_size, Transform3D()); | 
| 512 |  | 
| 513 | 	return bones[p_bone].rest; | 
| 514 | } | 
| 515 | Transform3D Skeleton3D::get_bone_global_rest(int p_bone) const { | 
| 516 | 	const int bone_size = bones.size(); | 
| 517 | 	ERR_FAIL_INDEX_V(p_bone, bone_size, Transform3D()); | 
| 518 | 	if (rest_dirty) { | 
| 519 | 		const_cast<Skeleton3D *>(this)->notification(NOTIFICATION_UPDATE_SKELETON); | 
| 520 | 	} | 
| 521 | 	return bones[p_bone].global_rest; | 
| 522 | } | 
| 523 |  | 
| 524 | void Skeleton3D::set_bone_enabled(int p_bone, bool p_enabled) { | 
| 525 | 	const int bone_size = bones.size(); | 
| 526 | 	ERR_FAIL_INDEX(p_bone, bone_size); | 
| 527 |  | 
| 528 | 	bones.write[p_bone].enabled = p_enabled; | 
| 529 | 	emit_signal(SceneStringNames::get_singleton()->bone_enabled_changed, p_bone); | 
| 530 | 	_make_dirty(); | 
| 531 | } | 
| 532 |  | 
| 533 | bool Skeleton3D::is_bone_enabled(int p_bone) const { | 
| 534 | 	const int bone_size = bones.size(); | 
| 535 | 	ERR_FAIL_INDEX_V(p_bone, bone_size, false); | 
| 536 | 	return bones[p_bone].enabled; | 
| 537 | } | 
| 538 |  | 
| 539 | void Skeleton3D::set_show_rest_only(bool p_enabled) { | 
| 540 | 	show_rest_only = p_enabled; | 
| 541 | 	emit_signal(SceneStringNames::get_singleton()->show_rest_only_changed); | 
| 542 | 	_make_dirty(); | 
| 543 | } | 
| 544 |  | 
| 545 | bool Skeleton3D::is_show_rest_only() const { | 
| 546 | 	return show_rest_only; | 
| 547 | } | 
| 548 |  | 
| 549 | void Skeleton3D::clear_bones() { | 
| 550 | 	bones.clear(); | 
| 551 | 	name_to_bone_index.clear(); | 
| 552 | 	process_order_dirty = true; | 
| 553 | 	version++; | 
| 554 | 	_make_dirty(); | 
| 555 | } | 
| 556 |  | 
| 557 | // Posing api | 
| 558 |  | 
| 559 | void Skeleton3D::set_bone_pose_position(int p_bone, const Vector3 &p_position) { | 
| 560 | 	const int bone_size = bones.size(); | 
| 561 | 	ERR_FAIL_INDEX(p_bone, bone_size); | 
| 562 |  | 
| 563 | 	bones.write[p_bone].pose_position = p_position; | 
| 564 | 	bones.write[p_bone].pose_cache_dirty = true; | 
| 565 | 	if (is_inside_tree()) { | 
| 566 | 		_make_dirty(); | 
| 567 | 	} | 
| 568 | } | 
| 569 | void Skeleton3D::set_bone_pose_rotation(int p_bone, const Quaternion &p_rotation) { | 
| 570 | 	const int bone_size = bones.size(); | 
| 571 | 	ERR_FAIL_INDEX(p_bone, bone_size); | 
| 572 |  | 
| 573 | 	bones.write[p_bone].pose_rotation = p_rotation; | 
| 574 | 	bones.write[p_bone].pose_cache_dirty = true; | 
| 575 | 	if (is_inside_tree()) { | 
| 576 | 		_make_dirty(); | 
| 577 | 	} | 
| 578 | } | 
| 579 | void Skeleton3D::set_bone_pose_scale(int p_bone, const Vector3 &p_scale) { | 
| 580 | 	const int bone_size = bones.size(); | 
| 581 | 	ERR_FAIL_INDEX(p_bone, bone_size); | 
| 582 |  | 
| 583 | 	bones.write[p_bone].pose_scale = p_scale; | 
| 584 | 	bones.write[p_bone].pose_cache_dirty = true; | 
| 585 | 	if (is_inside_tree()) { | 
| 586 | 		_make_dirty(); | 
| 587 | 	} | 
| 588 | } | 
| 589 |  | 
| 590 | Vector3 Skeleton3D::get_bone_pose_position(int p_bone) const { | 
| 591 | 	const int bone_size = bones.size(); | 
| 592 | 	ERR_FAIL_INDEX_V(p_bone, bone_size, Vector3()); | 
| 593 | 	return bones[p_bone].pose_position; | 
| 594 | } | 
| 595 |  | 
| 596 | Quaternion Skeleton3D::get_bone_pose_rotation(int p_bone) const { | 
| 597 | 	const int bone_size = bones.size(); | 
| 598 | 	ERR_FAIL_INDEX_V(p_bone, bone_size, Quaternion()); | 
| 599 | 	return bones[p_bone].pose_rotation; | 
| 600 | } | 
| 601 |  | 
| 602 | Vector3 Skeleton3D::get_bone_pose_scale(int p_bone) const { | 
| 603 | 	const int bone_size = bones.size(); | 
| 604 | 	ERR_FAIL_INDEX_V(p_bone, bone_size, Vector3()); | 
| 605 | 	return bones[p_bone].pose_scale; | 
| 606 | } | 
| 607 |  | 
| 608 | void Skeleton3D::reset_bone_pose(int p_bone) { | 
| 609 | 	const int bone_size = bones.size(); | 
| 610 | 	ERR_FAIL_INDEX(p_bone, bone_size); | 
| 611 | 	set_bone_pose_position(p_bone, bones[p_bone].rest.origin); | 
| 612 | 	set_bone_pose_rotation(p_bone, bones[p_bone].rest.basis.get_rotation_quaternion()); | 
| 613 | 	set_bone_pose_scale(p_bone, bones[p_bone].rest.basis.get_scale()); | 
| 614 | } | 
| 615 |  | 
| 616 | void Skeleton3D::reset_bone_poses() { | 
| 617 | 	for (int i = 0; i < bones.size(); i++) { | 
| 618 | 		reset_bone_pose(i); | 
| 619 | 	} | 
| 620 | } | 
| 621 |  | 
| 622 | Transform3D Skeleton3D::get_bone_pose(int p_bone) const { | 
| 623 | 	const int bone_size = bones.size(); | 
| 624 | 	ERR_FAIL_INDEX_V(p_bone, bone_size, Transform3D()); | 
| 625 | 	((Skeleton3D *)this)->bones.write[p_bone].update_pose_cache(); | 
| 626 | 	return bones[p_bone].pose_cache; | 
| 627 | } | 
| 628 |  | 
| 629 | void Skeleton3D::_make_dirty() { | 
| 630 | 	if (dirty) { | 
| 631 | 		return; | 
| 632 | 	} | 
| 633 |  | 
| 634 | 	if (is_inside_tree()) { | 
| 635 | 		notify_deferred_thread_group(NOTIFICATION_UPDATE_SKELETON); | 
| 636 | 	} | 
| 637 | 	dirty = true; | 
| 638 | } | 
| 639 |  | 
| 640 | void Skeleton3D::localize_rests() { | 
| 641 | 	Vector<int> bones_to_process = get_parentless_bones(); | 
| 642 | 	while (bones_to_process.size() > 0) { | 
| 643 | 		int current_bone_idx = bones_to_process[0]; | 
| 644 | 		bones_to_process.erase(current_bone_idx); | 
| 645 |  | 
| 646 | 		if (bones[current_bone_idx].parent >= 0) { | 
| 647 | 			set_bone_rest(current_bone_idx, bones[bones[current_bone_idx].parent].rest.affine_inverse() * bones[current_bone_idx].rest); | 
| 648 | 		} | 
| 649 |  | 
| 650 | 		// Add the bone's children to the list of bones to be processed. | 
| 651 | 		int child_bone_size = bones[current_bone_idx].child_bones.size(); | 
| 652 | 		for (int i = 0; i < child_bone_size; i++) { | 
| 653 | 			bones_to_process.push_back(bones[current_bone_idx].child_bones[i]); | 
| 654 | 		} | 
| 655 | 	} | 
| 656 | } | 
| 657 |  | 
| 658 | void Skeleton3D::set_animate_physical_bones(bool p_enabled) { | 
| 659 | 	animate_physical_bones = p_enabled; | 
| 660 |  | 
| 661 | 	if (Engine::get_singleton()->is_editor_hint() == false) { | 
| 662 | 		bool sim = false; | 
| 663 | 		for (int i = 0; i < bones.size(); i += 1) { | 
| 664 | 			if (bones[i].physical_bone) { | 
| 665 | 				bones[i].physical_bone->reset_physics_simulation_state(); | 
| 666 | 				if (bones[i].physical_bone->is_simulating_physics()) { | 
| 667 | 					sim = true; | 
| 668 | 				} | 
| 669 | 			} | 
| 670 | 		} | 
| 671 | 		set_physics_process_internal(sim == false && p_enabled); | 
| 672 | 	} | 
| 673 | } | 
| 674 |  | 
| 675 | bool Skeleton3D::get_animate_physical_bones() const { | 
| 676 | 	return animate_physical_bones; | 
| 677 | } | 
| 678 |  | 
| 679 | void Skeleton3D::bind_physical_bone_to_bone(int p_bone, PhysicalBone3D *p_physical_bone) { | 
| 680 | 	const int bone_size = bones.size(); | 
| 681 | 	ERR_FAIL_INDEX(p_bone, bone_size); | 
| 682 | 	ERR_FAIL_COND(bones[p_bone].physical_bone); | 
| 683 | 	ERR_FAIL_NULL(p_physical_bone); | 
| 684 | 	bones.write[p_bone].physical_bone = p_physical_bone; | 
| 685 |  | 
| 686 | 	_rebuild_physical_bones_cache(); | 
| 687 | } | 
| 688 |  | 
| 689 | void Skeleton3D::unbind_physical_bone_from_bone(int p_bone) { | 
| 690 | 	const int bone_size = bones.size(); | 
| 691 | 	ERR_FAIL_INDEX(p_bone, bone_size); | 
| 692 | 	bones.write[p_bone].physical_bone = nullptr; | 
| 693 |  | 
| 694 | 	_rebuild_physical_bones_cache(); | 
| 695 | } | 
| 696 |  | 
| 697 | PhysicalBone3D *Skeleton3D::get_physical_bone(int p_bone) { | 
| 698 | 	const int bone_size = bones.size(); | 
| 699 | 	ERR_FAIL_INDEX_V(p_bone, bone_size, nullptr); | 
| 700 |  | 
| 701 | 	return bones[p_bone].physical_bone; | 
| 702 | } | 
| 703 |  | 
| 704 | PhysicalBone3D *Skeleton3D::get_physical_bone_parent(int p_bone) { | 
| 705 | 	const int bone_size = bones.size(); | 
| 706 | 	ERR_FAIL_INDEX_V(p_bone, bone_size, nullptr); | 
| 707 |  | 
| 708 | 	if (bones[p_bone].cache_parent_physical_bone) { | 
| 709 | 		return bones[p_bone].cache_parent_physical_bone; | 
| 710 | 	} | 
| 711 |  | 
| 712 | 	return _get_physical_bone_parent(p_bone); | 
| 713 | } | 
| 714 |  | 
| 715 | PhysicalBone3D *Skeleton3D::_get_physical_bone_parent(int p_bone) { | 
| 716 | 	const int bone_size = bones.size(); | 
| 717 | 	ERR_FAIL_INDEX_V(p_bone, bone_size, nullptr); | 
| 718 |  | 
| 719 | 	const int parent_bone = bones[p_bone].parent; | 
| 720 | 	if (0 > parent_bone) { | 
| 721 | 		return nullptr; | 
| 722 | 	} | 
| 723 |  | 
| 724 | 	PhysicalBone3D *pb = bones[parent_bone].physical_bone; | 
| 725 | 	if (pb) { | 
| 726 | 		return pb; | 
| 727 | 	} else { | 
| 728 | 		return get_physical_bone_parent(parent_bone); | 
| 729 | 	} | 
| 730 | } | 
| 731 |  | 
| 732 | void Skeleton3D::_rebuild_physical_bones_cache() { | 
| 733 | 	const int b_size = bones.size(); | 
| 734 | 	for (int i = 0; i < b_size; ++i) { | 
| 735 | 		PhysicalBone3D *parent_pb = _get_physical_bone_parent(i); | 
| 736 | 		if (parent_pb != bones[i].cache_parent_physical_bone) { | 
| 737 | 			bones.write[i].cache_parent_physical_bone = parent_pb; | 
| 738 | 			if (bones[i].physical_bone) { | 
| 739 | 				bones[i].physical_bone->_on_bone_parent_changed(); | 
| 740 | 			} | 
| 741 | 		} | 
| 742 | 	} | 
| 743 | } | 
| 744 |  | 
| 745 | void _pb_stop_simulation(Node *p_node) { | 
| 746 | 	for (int i = p_node->get_child_count() - 1; 0 <= i; --i) { | 
| 747 | 		_pb_stop_simulation(p_node->get_child(i)); | 
| 748 | 	} | 
| 749 |  | 
| 750 | 	PhysicalBone3D *pb = Object::cast_to<PhysicalBone3D>(p_node); | 
| 751 | 	if (pb) { | 
| 752 | 		pb->set_simulate_physics(false); | 
| 753 | 	} | 
| 754 | } | 
| 755 |  | 
| 756 | void Skeleton3D::physical_bones_stop_simulation() { | 
| 757 | 	_pb_stop_simulation(this); | 
| 758 | 	if (Engine::get_singleton()->is_editor_hint() == false && animate_physical_bones) { | 
| 759 | 		set_physics_process_internal(true); | 
| 760 | 	} | 
| 761 | } | 
| 762 |  | 
| 763 | void _pb_start_simulation(const Skeleton3D *p_skeleton, Node *p_node, const Vector<int> &p_sim_bones) { | 
| 764 | 	for (int i = p_node->get_child_count() - 1; 0 <= i; --i) { | 
| 765 | 		_pb_start_simulation(p_skeleton, p_node->get_child(i), p_sim_bones); | 
| 766 | 	} | 
| 767 |  | 
| 768 | 	PhysicalBone3D *pb = Object::cast_to<PhysicalBone3D>(p_node); | 
| 769 | 	if (pb) { | 
| 770 | 		if (p_sim_bones.is_empty()) { // If no bones is specified, activate ragdoll on full body. | 
| 771 | 			pb->set_simulate_physics(true); | 
| 772 | 		} else { | 
| 773 | 			for (int i = p_sim_bones.size() - 1; 0 <= i; --i) { | 
| 774 | 				if (p_sim_bones[i] == pb->get_bone_id() || p_skeleton->is_bone_parent_of(pb->get_bone_id(), p_sim_bones[i])) { | 
| 775 | 					pb->set_simulate_physics(true); | 
| 776 | 					break; | 
| 777 | 				} | 
| 778 | 			} | 
| 779 | 		} | 
| 780 | 	} | 
| 781 | } | 
| 782 |  | 
| 783 | void Skeleton3D::physical_bones_start_simulation_on(const TypedArray<StringName> &p_bones) { | 
| 784 | 	set_physics_process_internal(false); | 
| 785 |  | 
| 786 | 	Vector<int> sim_bones; | 
| 787 | 	if (p_bones.size() > 0) { | 
| 788 | 		sim_bones.resize(p_bones.size()); | 
| 789 | 		int c = 0; | 
| 790 | 		for (int i = sim_bones.size() - 1; 0 <= i; --i) { | 
| 791 | 			int bone_id = find_bone(p_bones[i]); | 
| 792 | 			if (bone_id != -1) { | 
| 793 | 				sim_bones.write[c++] = bone_id; | 
| 794 | 			} | 
| 795 | 		} | 
| 796 | 		sim_bones.resize(c); | 
| 797 | 	} | 
| 798 |  | 
| 799 | 	_pb_start_simulation(this, this, sim_bones); | 
| 800 | } | 
| 801 |  | 
| 802 | void _physical_bones_add_remove_collision_exception(bool p_add, Node *p_node, RID p_exception) { | 
| 803 | 	for (int i = p_node->get_child_count() - 1; 0 <= i; --i) { | 
| 804 | 		_physical_bones_add_remove_collision_exception(p_add, p_node->get_child(i), p_exception); | 
| 805 | 	} | 
| 806 |  | 
| 807 | 	CollisionObject3D *co = Object::cast_to<CollisionObject3D>(p_node); | 
| 808 | 	if (co) { | 
| 809 | 		if (p_add) { | 
| 810 | 			PhysicsServer3D::get_singleton()->body_add_collision_exception(co->get_rid(), p_exception); | 
| 811 | 		} else { | 
| 812 | 			PhysicsServer3D::get_singleton()->body_remove_collision_exception(co->get_rid(), p_exception); | 
| 813 | 		} | 
| 814 | 	} | 
| 815 | } | 
| 816 |  | 
| 817 | void Skeleton3D::physical_bones_add_collision_exception(RID p_exception) { | 
| 818 | 	_physical_bones_add_remove_collision_exception(true, this, p_exception); | 
| 819 | } | 
| 820 |  | 
| 821 | void Skeleton3D::physical_bones_remove_collision_exception(RID p_exception) { | 
| 822 | 	_physical_bones_add_remove_collision_exception(false, this, p_exception); | 
| 823 | } | 
| 824 |  | 
| 825 | void Skeleton3D::_skin_changed() { | 
| 826 | 	_make_dirty(); | 
| 827 | } | 
| 828 |  | 
| 829 | Ref<Skin> Skeleton3D::create_skin_from_rest_transforms() { | 
| 830 | 	Ref<Skin> skin; | 
| 831 |  | 
| 832 | 	skin.instantiate(); | 
| 833 | 	skin->set_bind_count(bones.size()); | 
| 834 |  | 
| 835 | 	// Pose changed, rebuild cache of inverses. | 
| 836 | 	const Bone *bonesptr = bones.ptr(); | 
| 837 | 	int len = bones.size(); | 
| 838 |  | 
| 839 | 	// Calculate global rests and invert them. | 
| 840 | 	LocalVector<int> bones_to_process; | 
| 841 | 	bones_to_process = get_parentless_bones(); | 
| 842 | 	while (bones_to_process.size() > 0) { | 
| 843 | 		int current_bone_idx = bones_to_process[0]; | 
| 844 | 		const Bone &b = bonesptr[current_bone_idx]; | 
| 845 | 		bones_to_process.erase(current_bone_idx); | 
| 846 | 		LocalVector<int> child_bones_vector; | 
| 847 | 		child_bones_vector = get_bone_children(current_bone_idx); | 
| 848 | 		int child_bones_size = child_bones_vector.size(); | 
| 849 | 		if (b.parent < 0) { | 
| 850 | 			skin->set_bind_pose(current_bone_idx, b.rest); | 
| 851 | 		} | 
| 852 | 		for (int i = 0; i < child_bones_size; i++) { | 
| 853 | 			int child_bone_idx = child_bones_vector[i]; | 
| 854 | 			const Bone &cb = bonesptr[child_bone_idx]; | 
| 855 | 			skin->set_bind_pose(child_bone_idx, skin->get_bind_pose(current_bone_idx) * cb.rest); | 
| 856 | 			// Add the bone's children to the list of bones to be processed. | 
| 857 | 			bones_to_process.push_back(child_bones_vector[i]); | 
| 858 | 		} | 
| 859 | 	} | 
| 860 |  | 
| 861 | 	for (int i = 0; i < len; i++) { | 
| 862 | 		// The inverse is what is actually required. | 
| 863 | 		skin->set_bind_bone(i, i); | 
| 864 | 		skin->set_bind_pose(i, skin->get_bind_pose(i).affine_inverse()); | 
| 865 | 	} | 
| 866 |  | 
| 867 | 	return skin; | 
| 868 | } | 
| 869 |  | 
| 870 | Ref<SkinReference> Skeleton3D::register_skin(const Ref<Skin> &p_skin) { | 
| 871 | 	ERR_FAIL_COND_V(p_skin.is_null(), Ref<SkinReference>()); | 
| 872 |  | 
| 873 | 	for (const SkinReference *E : skin_bindings) { | 
| 874 | 		if (E->skin == p_skin) { | 
| 875 | 			return Ref<SkinReference>(E); | 
| 876 | 		} | 
| 877 | 	} | 
| 878 |  | 
| 879 | 	Ref<SkinReference> skin_ref; | 
| 880 | 	skin_ref.instantiate(); | 
| 881 |  | 
| 882 | 	skin_ref->skeleton_node = this; | 
| 883 | 	skin_ref->bind_count = 0; | 
| 884 | 	skin_ref->skeleton = RenderingServer::get_singleton()->skeleton_create(); | 
| 885 | 	skin_ref->skeleton_node = this; | 
| 886 | 	skin_ref->skin = p_skin; | 
| 887 |  | 
| 888 | 	skin_bindings.insert(skin_ref.operator->()); | 
| 889 |  | 
| 890 | 	skin_ref->skin->connect_changed(callable_mp(skin_ref.operator->(), &SkinReference::_skin_changed)); | 
| 891 |  | 
| 892 | 	_make_dirty(); // Skin needs to be updated, so update skeleton. | 
| 893 |  | 
| 894 | 	return skin_ref; | 
| 895 | } | 
| 896 |  | 
| 897 | void Skeleton3D::force_update_all_dirty_bones() { | 
| 898 | 	if (dirty) { | 
| 899 | 		const_cast<Skeleton3D *>(this)->notification(NOTIFICATION_UPDATE_SKELETON); | 
| 900 | 	} | 
| 901 | } | 
| 902 |  | 
| 903 | void Skeleton3D::force_update_all_bone_transforms() { | 
| 904 | 	_update_process_order(); | 
| 905 |  | 
| 906 | 	for (int i = 0; i < parentless_bones.size(); i++) { | 
| 907 | 		force_update_bone_children_transforms(parentless_bones[i]); | 
| 908 | 	} | 
| 909 | 	rest_dirty = false; | 
| 910 | } | 
| 911 |  | 
| 912 | void Skeleton3D::force_update_bone_children_transforms(int p_bone_idx) { | 
| 913 | 	const int bone_size = bones.size(); | 
| 914 | 	ERR_FAIL_INDEX(p_bone_idx, bone_size); | 
| 915 |  | 
| 916 | 	Bone *bonesptr = bones.ptrw(); | 
| 917 | 	List<int> bones_to_process = List<int>(); | 
| 918 | 	bones_to_process.push_back(p_bone_idx); | 
| 919 |  | 
| 920 | 	while (bones_to_process.size() > 0) { | 
| 921 | 		int current_bone_idx = bones_to_process[0]; | 
| 922 | 		bones_to_process.erase(current_bone_idx); | 
| 923 |  | 
| 924 | 		Bone &b = bonesptr[current_bone_idx]; | 
| 925 | 		bool bone_enabled = b.enabled && !show_rest_only; | 
| 926 |  | 
| 927 | 		if (bone_enabled) { | 
| 928 | 			b.update_pose_cache(); | 
| 929 | 			Transform3D pose = b.pose_cache; | 
| 930 |  | 
| 931 | 			if (b.parent >= 0) { | 
| 932 | 				b.pose_global = bonesptr[b.parent].pose_global * pose; | 
| 933 | 				b.pose_global_no_override = bonesptr[b.parent].pose_global_no_override * pose; | 
| 934 | 			} else { | 
| 935 | 				b.pose_global = pose; | 
| 936 | 				b.pose_global_no_override = pose; | 
| 937 | 			} | 
| 938 | 		} else { | 
| 939 | 			if (b.parent >= 0) { | 
| 940 | 				b.pose_global = bonesptr[b.parent].pose_global * b.rest; | 
| 941 | 				b.pose_global_no_override = bonesptr[b.parent].pose_global_no_override * b.rest; | 
| 942 | 			} else { | 
| 943 | 				b.pose_global = b.rest; | 
| 944 | 				b.pose_global_no_override = b.rest; | 
| 945 | 			} | 
| 946 | 		} | 
| 947 | 		if (rest_dirty) { | 
| 948 | 			b.global_rest = b.parent >= 0 ? bonesptr[b.parent].global_rest * b.rest : b.rest; | 
| 949 | 		} | 
| 950 |  | 
| 951 | 		if (b.global_pose_override_amount >= CMP_EPSILON) { | 
| 952 | 			b.pose_global = b.pose_global.interpolate_with(b.global_pose_override, b.global_pose_override_amount); | 
| 953 | 		} | 
| 954 |  | 
| 955 | 		if (b.global_pose_override_reset) { | 
| 956 | 			b.global_pose_override_amount = 0.0; | 
| 957 | 		} | 
| 958 |  | 
| 959 | 		// Add the bone's children to the list of bones to be processed. | 
| 960 | 		int child_bone_size = b.child_bones.size(); | 
| 961 | 		for (int i = 0; i < child_bone_size; i++) { | 
| 962 | 			bones_to_process.push_back(b.child_bones[i]); | 
| 963 | 		} | 
| 964 |  | 
| 965 | 		emit_signal(SceneStringNames::get_singleton()->bone_pose_changed, current_bone_idx); | 
| 966 | 	} | 
| 967 | } | 
| 968 |  | 
| 969 | void Skeleton3D::_bind_methods() { | 
| 970 | 	ClassDB::bind_method(D_METHOD("add_bone" , "name" ), &Skeleton3D::add_bone); | 
| 971 | 	ClassDB::bind_method(D_METHOD("find_bone" , "name" ), &Skeleton3D::find_bone); | 
| 972 | 	ClassDB::bind_method(D_METHOD("get_bone_name" , "bone_idx" ), &Skeleton3D::get_bone_name); | 
| 973 | 	ClassDB::bind_method(D_METHOD("set_bone_name" , "bone_idx" , "name" ), &Skeleton3D::set_bone_name); | 
| 974 |  | 
| 975 | 	ClassDB::bind_method(D_METHOD("get_bone_parent" , "bone_idx" ), &Skeleton3D::get_bone_parent); | 
| 976 | 	ClassDB::bind_method(D_METHOD("set_bone_parent" , "bone_idx" , "parent_idx" ), &Skeleton3D::set_bone_parent); | 
| 977 |  | 
| 978 | 	ClassDB::bind_method(D_METHOD("get_bone_count" ), &Skeleton3D::get_bone_count); | 
| 979 | 	ClassDB::bind_method(D_METHOD("get_version" ), &Skeleton3D::get_version); | 
| 980 |  | 
| 981 | 	ClassDB::bind_method(D_METHOD("unparent_bone_and_rest" , "bone_idx" ), &Skeleton3D::unparent_bone_and_rest); | 
| 982 |  | 
| 983 | 	ClassDB::bind_method(D_METHOD("get_bone_children" , "bone_idx" ), &Skeleton3D::get_bone_children); | 
| 984 |  | 
| 985 | 	ClassDB::bind_method(D_METHOD("get_parentless_bones" ), &Skeleton3D::get_parentless_bones); | 
| 986 |  | 
| 987 | 	ClassDB::bind_method(D_METHOD("get_bone_rest" , "bone_idx" ), &Skeleton3D::get_bone_rest); | 
| 988 | 	ClassDB::bind_method(D_METHOD("set_bone_rest" , "bone_idx" , "rest" ), &Skeleton3D::set_bone_rest); | 
| 989 | 	ClassDB::bind_method(D_METHOD("get_bone_global_rest" , "bone_idx" ), &Skeleton3D::get_bone_global_rest); | 
| 990 |  | 
| 991 | 	ClassDB::bind_method(D_METHOD("create_skin_from_rest_transforms" ), &Skeleton3D::create_skin_from_rest_transforms); | 
| 992 | 	ClassDB::bind_method(D_METHOD("register_skin" , "skin" ), &Skeleton3D::register_skin); | 
| 993 |  | 
| 994 | 	ClassDB::bind_method(D_METHOD("localize_rests" ), &Skeleton3D::localize_rests); | 
| 995 |  | 
| 996 | 	ClassDB::bind_method(D_METHOD("clear_bones" ), &Skeleton3D::clear_bones); | 
| 997 |  | 
| 998 | 	ClassDB::bind_method(D_METHOD("get_bone_pose" , "bone_idx" ), &Skeleton3D::get_bone_pose); | 
| 999 | 	ClassDB::bind_method(D_METHOD("set_bone_pose_position" , "bone_idx" , "position" ), &Skeleton3D::set_bone_pose_position); | 
| 1000 | 	ClassDB::bind_method(D_METHOD("set_bone_pose_rotation" , "bone_idx" , "rotation" ), &Skeleton3D::set_bone_pose_rotation); | 
| 1001 | 	ClassDB::bind_method(D_METHOD("set_bone_pose_scale" , "bone_idx" , "scale" ), &Skeleton3D::set_bone_pose_scale); | 
| 1002 |  | 
| 1003 | 	ClassDB::bind_method(D_METHOD("get_bone_pose_position" , "bone_idx" ), &Skeleton3D::get_bone_pose_position); | 
| 1004 | 	ClassDB::bind_method(D_METHOD("get_bone_pose_rotation" , "bone_idx" ), &Skeleton3D::get_bone_pose_rotation); | 
| 1005 | 	ClassDB::bind_method(D_METHOD("get_bone_pose_scale" , "bone_idx" ), &Skeleton3D::get_bone_pose_scale); | 
| 1006 |  | 
| 1007 | 	ClassDB::bind_method(D_METHOD("reset_bone_pose" , "bone_idx" ), &Skeleton3D::reset_bone_pose); | 
| 1008 | 	ClassDB::bind_method(D_METHOD("reset_bone_poses" ), &Skeleton3D::reset_bone_poses); | 
| 1009 |  | 
| 1010 | 	ClassDB::bind_method(D_METHOD("is_bone_enabled" , "bone_idx" ), &Skeleton3D::is_bone_enabled); | 
| 1011 | 	ClassDB::bind_method(D_METHOD("set_bone_enabled" , "bone_idx" , "enabled" ), &Skeleton3D::set_bone_enabled, DEFVAL(true)); | 
| 1012 |  | 
| 1013 | 	ClassDB::bind_method(D_METHOD("clear_bones_global_pose_override" ), &Skeleton3D::clear_bones_global_pose_override); | 
| 1014 | 	ClassDB::bind_method(D_METHOD("set_bone_global_pose_override" , "bone_idx" , "pose" , "amount" , "persistent" ), &Skeleton3D::set_bone_global_pose_override, DEFVAL(false)); | 
| 1015 | 	ClassDB::bind_method(D_METHOD("get_bone_global_pose_override" , "bone_idx" ), &Skeleton3D::get_bone_global_pose_override); | 
| 1016 | 	ClassDB::bind_method(D_METHOD("get_bone_global_pose" , "bone_idx" ), &Skeleton3D::get_bone_global_pose); | 
| 1017 | 	ClassDB::bind_method(D_METHOD("get_bone_global_pose_no_override" , "bone_idx" ), &Skeleton3D::get_bone_global_pose_no_override); | 
| 1018 |  | 
| 1019 | 	ClassDB::bind_method(D_METHOD("force_update_all_bone_transforms" ), &Skeleton3D::force_update_all_bone_transforms); | 
| 1020 | 	ClassDB::bind_method(D_METHOD("force_update_bone_child_transform" , "bone_idx" ), &Skeleton3D::force_update_bone_children_transforms); | 
| 1021 |  | 
| 1022 | 	ClassDB::bind_method(D_METHOD("set_motion_scale" , "motion_scale" ), &Skeleton3D::set_motion_scale); | 
| 1023 | 	ClassDB::bind_method(D_METHOD("get_motion_scale" ), &Skeleton3D::get_motion_scale); | 
| 1024 |  | 
| 1025 | 	ClassDB::bind_method(D_METHOD("set_show_rest_only" , "enabled" ), &Skeleton3D::set_show_rest_only); | 
| 1026 | 	ClassDB::bind_method(D_METHOD("is_show_rest_only" ), &Skeleton3D::is_show_rest_only); | 
| 1027 |  | 
| 1028 | 	ClassDB::bind_method(D_METHOD("set_animate_physical_bones" , "enabled" ), &Skeleton3D::set_animate_physical_bones); | 
| 1029 | 	ClassDB::bind_method(D_METHOD("get_animate_physical_bones" ), &Skeleton3D::get_animate_physical_bones); | 
| 1030 |  | 
| 1031 | 	ClassDB::bind_method(D_METHOD("physical_bones_stop_simulation" ), &Skeleton3D::physical_bones_stop_simulation); | 
| 1032 | 	ClassDB::bind_method(D_METHOD("physical_bones_start_simulation" , "bones" ), &Skeleton3D::physical_bones_start_simulation_on, DEFVAL(Array())); | 
| 1033 | 	ClassDB::bind_method(D_METHOD("physical_bones_add_collision_exception" , "exception" ), &Skeleton3D::physical_bones_add_collision_exception); | 
| 1034 | 	ClassDB::bind_method(D_METHOD("physical_bones_remove_collision_exception" , "exception" ), &Skeleton3D::physical_bones_remove_collision_exception); | 
| 1035 |  | 
| 1036 | 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "motion_scale" , PROPERTY_HINT_RANGE, "0.001,10,0.001,or_greater" ), "set_motion_scale" , "get_motion_scale" ); | 
| 1037 | 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_rest_only" ), "set_show_rest_only" , "is_show_rest_only" ); | 
| 1038 | #ifndef _3D_DISABLED | 
| 1039 | 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "animate_physical_bones" ), "set_animate_physical_bones" , "get_animate_physical_bones" ); | 
| 1040 | #endif // _3D_DISABLED | 
| 1041 |  | 
| 1042 | 	ADD_SIGNAL(MethodInfo("pose_updated" )); | 
| 1043 | 	ADD_SIGNAL(MethodInfo("bone_pose_changed" , PropertyInfo(Variant::INT, "bone_idx" ))); | 
| 1044 | 	ADD_SIGNAL(MethodInfo("bone_enabled_changed" , PropertyInfo(Variant::INT, "bone_idx" ))); | 
| 1045 | 	ADD_SIGNAL(MethodInfo("show_rest_only_changed" )); | 
| 1046 |  | 
| 1047 | 	BIND_CONSTANT(NOTIFICATION_UPDATE_SKELETON); | 
| 1048 | } | 
| 1049 |  | 
| 1050 | Skeleton3D::Skeleton3D() { | 
| 1051 | } | 
| 1052 |  | 
| 1053 | Skeleton3D::~Skeleton3D() { | 
| 1054 | 	// Some skins may remain bound. | 
| 1055 | 	for (SkinReference *E : skin_bindings) { | 
| 1056 | 		E->skeleton_node = nullptr; | 
| 1057 | 	} | 
| 1058 | } | 
| 1059 |  |