summaryrefslogtreecommitdiff
path: root/scene/3d/skeleton.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'scene/3d/skeleton.cpp')
-rw-r--r--scene/3d/skeleton.cpp67
1 files changed, 56 insertions, 11 deletions
diff --git a/scene/3d/skeleton.cpp b/scene/3d/skeleton.cpp
index 4089e0c23b..3ef502cfd3 100644
--- a/scene/3d/skeleton.cpp
+++ b/scene/3d/skeleton.cpp
@@ -41,6 +41,7 @@ void SkinReference::_skin_changed() {
if (skeleton_node) {
skeleton_node->_make_dirty();
}
+ skeleton_version = 0;
}
void SkinReference::_bind_methods() {
@@ -138,7 +139,7 @@ bool Skeleton::_get(const StringName &p_path, Variant &r_ret) const {
else if (what == "bound_children") {
Array children;
- for (const List<uint32_t>::Element *E = bones[which].nodes_bound.front(); E; E = E->next()) {
+ for (const List<ObjectID>::Element *E = bones[which].nodes_bound.front(); E; E = E->next()) {
Object *obj = ObjectDB::get_instance(E->get());
ERR_CONTINUE(!obj);
@@ -302,7 +303,7 @@ void Skeleton::_notification(int p_what) {
b.global_pose_override_amount = 0.0;
}
- for (List<uint32_t>::Element *E = b.nodes_bound.front(); E; E = E->next()) {
+ for (List<ObjectID>::Element *E = b.nodes_bound.front(); E; E = E->next()) {
Object *obj = ObjectDB::get_instance(E->get());
ERR_CONTINUE(!obj);
@@ -322,10 +323,49 @@ void Skeleton::_notification(int p_what) {
if (E->get()->bind_count != bind_count) {
VS::get_singleton()->skeleton_allocate(skeleton, bind_count);
E->get()->bind_count = bind_count;
+ E->get()->skin_bone_indices.resize(bind_count);
+ E->get()->skin_bone_indices_ptrs = E->get()->skin_bone_indices.ptrw();
+ }
+
+ if (E->get()->skeleton_version != version) {
+
+ for (uint32_t i = 0; i < bind_count; i++) {
+ StringName bind_name = skin->get_bind_name(i);
+
+ if (bind_name != StringName()) {
+ //bind name used, use this
+ bool found = false;
+ for (int j = 0; j < len; j++) {
+ if (bonesptr[j].name == bind_name) {
+ E->get()->skin_bone_indices_ptrs[i] = j;
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ ERR_PRINT("Skin bind #" + itos(i) + " contains named bind '" + String(bind_name) + "' but Skeleton has no bone by that name.");
+ E->get()->skin_bone_indices_ptrs[i] = 0;
+ }
+ } else if (skin->get_bind_bone(i) >= 0) {
+ int bind_index = skin->get_bind_bone(i);
+ if (bind_index >= len) {
+ ERR_PRINT("Skin bind #" + itos(i) + " contains bone index bind: " + itos(bind_index) + " , which is greater than the skeleton bone count: " + itos(len) + ".");
+ E->get()->skin_bone_indices_ptrs[i] = 0;
+ } else {
+ E->get()->skin_bone_indices_ptrs[i] = bind_index;
+ }
+ } else {
+ ERR_PRINT("Skin bind #" + itos(i) + " does not contain a name nor a bone index.");
+ E->get()->skin_bone_indices_ptrs[i] = 0;
+ }
+ }
+
+ E->get()->skeleton_version = version;
}
for (uint32_t i = 0; i < bind_count; i++) {
- uint32_t bone_index = skin->get_bind_bone(i);
+ uint32_t bone_index = E->get()->skin_bone_indices_ptrs[i];
ERR_CONTINUE(bone_index >= (uint32_t)len);
vs->skeleton_bone_set_transform(skeleton, i, bonesptr[bone_index].pose_global * skin->get_bind_pose(i));
}
@@ -388,6 +428,7 @@ void Skeleton::add_bone(const String &p_name) {
b.name = p_name;
bones.push_back(b);
process_order_dirty = true;
+ version++;
_make_dirty();
update_gizmo();
}
@@ -505,9 +546,9 @@ void Skeleton::bind_child_node_to_bone(int p_bone, Node *p_node) {
ERR_FAIL_NULL(p_node);
ERR_FAIL_INDEX(p_bone, bones.size());
- uint32_t id = p_node->get_instance_id();
+ ObjectID id = p_node->get_instance_id();
- for (const List<uint32_t>::Element *E = bones[p_bone].nodes_bound.front(); E; E = E->next()) {
+ for (const List<ObjectID>::Element *E = bones[p_bone].nodes_bound.front(); E; E = E->next()) {
if (E->get() == id)
return; // already here
@@ -520,14 +561,14 @@ void Skeleton::unbind_child_node_from_bone(int p_bone, Node *p_node) {
ERR_FAIL_NULL(p_node);
ERR_FAIL_INDEX(p_bone, bones.size());
- uint32_t id = p_node->get_instance_id();
+ ObjectID id = p_node->get_instance_id();
bones.write[p_bone].nodes_bound.erase(id);
}
void Skeleton::get_bound_child_nodes_to_bone(int p_bone, List<Node *> *p_bound) const {
ERR_FAIL_INDEX(p_bone, bones.size());
- for (const List<uint32_t>::Element *E = bones[p_bone].nodes_bound.front(); E; E = E->next()) {
+ for (const List<ObjectID>::Element *E = bones[p_bone].nodes_bound.front(); E; E = E->next()) {
Object *obj = ObjectDB::get_instance(E->get());
ERR_CONTINUE(!obj);
@@ -539,7 +580,7 @@ void Skeleton::clear_bones() {
bones.clear();
process_order_dirty = true;
-
+ version++;
_make_dirty();
}
@@ -733,7 +774,8 @@ void Skeleton::physical_bones_start_simulation_on(const Array &p_bones) {
sim_bones.resize(p_bones.size());
int c = 0;
for (int i = sim_bones.size() - 1; 0 <= i; --i) {
- if (Variant::STRING == p_bones.get(i).get_type()) {
+ Variant::Type type = p_bones.get(i).get_type();
+ if (Variant::STRING == type || Variant::STRING_NAME == type) {
int bone_id = find_bone(p_bones.get(i));
if (bone_id != -1)
sim_bones.write[c++] = bone_id;
@@ -829,8 +871,10 @@ Ref<SkinReference> Skeleton::register_skin(const Ref<Skin> &p_skin) {
skin_bindings.insert(skin_ref.operator->());
- skin->connect("changed", skin_ref.operator->(), "_skin_changed");
- _make_dirty();
+ skin->connect_compat("changed", skin_ref.operator->(), "_skin_changed");
+
+ _make_dirty(); //skin needs to be updated, so update skeleton
+
return skin_ref;
}
@@ -892,6 +936,7 @@ Skeleton::Skeleton() {
animate_physical_bones = true;
dirty = false;
+ version = 1;
process_order_dirty = true;
}