void Skeleton::set_bone_enabled(int p_bone, bool p_enabled) { ERR_FAIL_INDEX( p_bone, bones.size() ); bones[p_bone].enabled=p_enabled; rest_global_inverse_dirty=true; _make_dirty(); }
void Skeleton::set_bone_pose(int p_bone, const Transform &p_pose) { ERR_FAIL_INDEX(p_bone, bones.size()); ERR_FAIL_COND(!is_inside_tree()); bones.write[p_bone].pose = p_pose; _make_dirty(); }
void Skeleton::set_bone_rest(int p_bone, const Transform &p_rest) { ERR_FAIL_INDEX(p_bone, bones.size()); bones.write[p_bone].rest = p_rest; rest_global_inverse_dirty = true; _make_dirty(); }
void Skeleton::clear_bones() { bones.clear(); rest_global_inverse_dirty = true; process_order_dirty = true; _make_dirty(); }
void Skeleton::set_bone_parent(int p_bone, int p_parent) { ERR_FAIL_INDEX( p_bone, bones.size() ); ERR_FAIL_COND( p_parent!=-1 && (p_parent<0 || p_parent>=p_bone)); bones[p_bone].parent=p_parent; rest_global_inverse_dirty=true; _make_dirty(); }
void Skeleton::set_bone_custom_pose(int p_bone, const Transform &p_custom_pose) { ERR_FAIL_INDEX(p_bone, bones.size()); //ERR_FAIL_COND( !is_inside_scene() ); bones.write[p_bone].custom_pose_enable = (p_custom_pose != Transform()); bones.write[p_bone].custom_pose = p_custom_pose; _make_dirty(); }
void Skeleton::set_bone_parent(int p_bone, int p_parent) { ERR_FAIL_INDEX(p_bone, bones.size()); ERR_FAIL_COND(p_parent != -1 && (p_parent < 0)); bones.write[p_bone].parent = p_parent; rest_global_inverse_dirty = true; process_order_dirty = true; _make_dirty(); }
void Skeleton::unparent_bone_and_rest(int p_bone) { ERR_FAIL_INDEX(p_bone, bones.size()); int parent = bones[p_bone].parent; while (parent >= 0) { bones.write[p_bone].rest = bones[parent].rest * bones[p_bone].rest; parent = bones[parent].parent; } bones.write[p_bone].parent = -1; bones.write[p_bone].rest_global_inverse = bones[p_bone].rest.affine_inverse(); //same thing _make_dirty(); }
// skeleton creation api void Skeleton::add_bone(const String& p_name) { ERR_FAIL_COND( p_name=="" || p_name.find(":")!=-1 || p_name.find("/")!=-1 ); for (int i=0;i<bones.size();i++) { ERR_FAIL_COND( bones[i].name=="p_name"); } Bone b; b.name=p_name; bones.push_back(b); rest_global_inverse_dirty=true; _make_dirty(); update_gizmo(); }
void Skeleton::_notification(int p_what) { switch(p_what) { case NOTIFICATION_ENTER_WORLD: { if (dirty) { dirty=false; _make_dirty(); // property make it dirty } } break; case NOTIFICATION_EXIT_WORLD: { } break; case NOTIFICATION_UPDATE_SKELETON: { VisualServer *vs=VisualServer::get_singleton(); Bone *bonesptr=&bones[0]; int len=bones.size(); vs->skeleton_resize( skeleton, len ); // if same size, nothin really happens // pose changed, rebuild cache of inverses if (rest_global_inverse_dirty) { // calculate global rests and invert them for (int i=0;i<len;i++) { Bone &b=bonesptr[i]; if (b.parent>=0) b.rest_global_inverse=bonesptr[b.parent].rest_global_inverse * b.rest; else b.rest_global_inverse=b.rest; } for (int i=0;i<len;i++) { Bone &b=bonesptr[i]; b.rest_global_inverse.affine_invert(); } rest_global_inverse_dirty=false; } for (int i=0;i<len;i++) { Bone &b=bonesptr[i]; if (b.disable_rest) { if (b.enabled) { Transform pose=b.pose; if (b.custom_pose_enable) { pose = b.custom_pose * pose; } if (b.parent>=0) { b.pose_global=bonesptr[b.parent].pose_global * pose; } else { b.pose_global=pose; } } else { if (b.parent>=0) { b.pose_global=bonesptr[b.parent].pose_global; } else { b.pose_global=Transform(); } } } else { if (b.enabled) { Transform pose=b.pose; if (b.custom_pose_enable) { pose = b.custom_pose * pose; } if (b.parent>=0) { b.pose_global=bonesptr[b.parent].pose_global * (b.rest * pose); } else { b.pose_global=b.rest * pose; } } else { if (b.parent>=0) { b.pose_global=bonesptr[b.parent].pose_global * b.rest; } else { b.pose_global=b.rest; } } } vs->skeleton_bone_set_transform( skeleton, i, b.pose_global * b.rest_global_inverse ); for(List<uint32_t>::Element *E=b.nodes_bound.front();E;E=E->next()) { Object *obj=ObjectDB::get_instance(E->get()); ERR_CONTINUE(!obj); Spatial *sp = obj->cast_to<Spatial>(); ERR_CONTINUE(!sp); sp->set_transform(b.pose_global); } } dirty=false; } break; } }