summaryrefslogtreecommitdiff
path: root/scene/3d
diff options
context:
space:
mode:
Diffstat (limited to 'scene/3d')
-rw-r--r--scene/3d/skeleton.cpp46
-rw-r--r--scene/3d/skeleton.h5
2 files changed, 49 insertions, 2 deletions
diff --git a/scene/3d/skeleton.cpp b/scene/3d/skeleton.cpp
index a1d1856001..660b5bc7da 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() {
@@ -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();
}
@@ -539,7 +580,7 @@ void Skeleton::clear_bones() {
bones.clear();
process_order_dirty = true;
-
+ version++;
_make_dirty();
}
@@ -894,6 +935,7 @@ Skeleton::Skeleton() {
animate_physical_bones = true;
dirty = false;
+ version = 1;
process_order_dirty = true;
}
diff --git a/scene/3d/skeleton.h b/scene/3d/skeleton.h
index b42c2112e3..76fd96f30a 100644
--- a/scene/3d/skeleton.h
+++ b/scene/3d/skeleton.h
@@ -51,6 +51,9 @@ class SkinReference : public Reference {
RID skeleton;
Ref<Skin> skin;
uint32_t bind_count = 0;
+ uint64_t skeleton_version = 0;
+ Vector<uint32_t> skin_bone_indices;
+ uint32_t *skin_bone_indices_ptrs;
void _skin_changed();
protected:
@@ -123,6 +126,8 @@ private:
void _make_dirty();
bool dirty;
+ uint64_t version;
+
// bind helpers
Array _get_bound_child_nodes_to_bone(int p_bone) const {