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
39void SkinReference::_skin_changed() {
40 if (skeleton_node) {
41 skeleton_node->_make_dirty();
42 }
43 skeleton_version = 0;
44}
45
46void 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
51RID SkinReference::get_skeleton() const {
52 return skeleton;
53}
54
55Ref<Skin> SkinReference::get_skin() const {
56 return skin;
57}
58
59SkinReference::~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
69bool 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
105bool 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
138void 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
155void 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
188void 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
227void 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
325void 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
333void 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
342Transform3D 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
348Transform3D 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
357Transform3D 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
366void 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
374float 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
381uint64_t Skeleton3D::get_version() const {
382 return version;
383}
384
385void 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
399int 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
404String 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
410void 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
427bool 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
441int Skeleton3D::get_bone_count() const {
442 return bones.size();
443}
444
445void 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
457void 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
476int 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
485Vector<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
494Vector<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
501void 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}
509Transform3D 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}
515Transform3D 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
524void 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
533bool 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
539void 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
545bool Skeleton3D::is_show_rest_only() const {
546 return show_rest_only;
547}
548
549void 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
559void 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}
569void 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}
579void 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
590Vector3 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
596Quaternion 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
602Vector3 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
608void 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
616void Skeleton3D::reset_bone_poses() {
617 for (int i = 0; i < bones.size(); i++) {
618 reset_bone_pose(i);
619 }
620}
621
622Transform3D 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
629void 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
640void 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
658void 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
675bool Skeleton3D::get_animate_physical_bones() const {
676 return animate_physical_bones;
677}
678
679void 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
689void 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
697PhysicalBone3D *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
704PhysicalBone3D *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
715PhysicalBone3D *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
732void 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
745void _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
756void 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
763void _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
783void 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
802void _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
817void Skeleton3D::physical_bones_add_collision_exception(RID p_exception) {
818 _physical_bones_add_remove_collision_exception(true, this, p_exception);
819}
820
821void Skeleton3D::physical_bones_remove_collision_exception(RID p_exception) {
822 _physical_bones_add_remove_collision_exception(false, this, p_exception);
823}
824
825void Skeleton3D::_skin_changed() {
826 _make_dirty();
827}
828
829Ref<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
870Ref<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
897void Skeleton3D::force_update_all_dirty_bones() {
898 if (dirty) {
899 const_cast<Skeleton3D *>(this)->notification(NOTIFICATION_UPDATE_SKELETON);
900 }
901}
902
903void 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
912void 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
969void 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
1050Skeleton3D::Skeleton3D() {
1051}
1052
1053Skeleton3D::~Skeleton3D() {
1054 // Some skins may remain bound.
1055 for (SkinReference *E : skin_bindings) {
1056 E->skeleton_node = nullptr;
1057 }
1058}
1059