diff options
29 files changed, 414 insertions, 276 deletions
diff --git a/drivers/gles2/rasterizer_scene_gles2.cpp b/drivers/gles2/rasterizer_scene_gles2.cpp index cc414c26af..7e52b41ca2 100644 --- a/drivers/gles2/rasterizer_scene_gles2.cpp +++ b/drivers/gles2/rasterizer_scene_gles2.cpp @@ -2570,12 +2570,6 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements, state.scene_shader.set_uniform(SceneShaderGLES2::WORLD_TRANSFORM, e->instance->transform); - if (skeleton) { - state.scene_shader.set_uniform(SceneShaderGLES2::SKELETON_IN_WORLD_COORDS, skeleton->use_world_transform); - state.scene_shader.set_uniform(SceneShaderGLES2::SKELETON_TRANSFORM, skeleton->world_transform); - state.scene_shader.set_uniform(SceneShaderGLES2::SKELETON_TRANSFORM_INVERSE, skeleton->world_transform_inverse); - } - if (use_lightmap_capture) { //this is per instance, must be set always if present glUniform4fv(state.scene_shader.get_uniform_location(SceneShaderGLES2::LIGHTMAP_CAPTURES), 12, (const GLfloat *)e->instance->lightmap_capture_data.ptr()); state.scene_shader.set_uniform(SceneShaderGLES2::LIGHTMAP_CAPTURE_SKY, false); diff --git a/drivers/gles2/rasterizer_storage_gles2.cpp b/drivers/gles2/rasterizer_storage_gles2.cpp index 5c02d8096d..4734e2a063 100644 --- a/drivers/gles2/rasterizer_storage_gles2.cpp +++ b/drivers/gles2/rasterizer_storage_gles2.cpp @@ -3663,23 +3663,6 @@ void RasterizerStorageGLES2::skeleton_set_base_transform_2d(RID p_skeleton, cons skeleton->base_transform_2d = p_base_transform; } -void RasterizerStorageGLES2::skeleton_set_world_transform(RID p_skeleton, bool p_enable, const Transform &p_world_transform) { - - Skeleton *skeleton = skeleton_owner.getornull(p_skeleton); - - ERR_FAIL_COND(skeleton->use_2d); - - skeleton->world_transform = p_world_transform; - skeleton->use_world_transform = p_enable; - if (p_enable) { - skeleton->world_transform_inverse = skeleton->world_transform.affine_inverse(); - } - - if (!skeleton->update_list.in_list()) { - skeleton_update_list.add(&skeleton->update_list); - } -} - void RasterizerStorageGLES2::_update_skeleton_transform_buffer(const PoolVector<float> &p_data, size_t p_size) { glBindBuffer(GL_ARRAY_BUFFER, resources.skeleton_transform_buffer); diff --git a/drivers/gles2/rasterizer_storage_gles2.h b/drivers/gles2/rasterizer_storage_gles2.h index d139697b86..492e149eaf 100644 --- a/drivers/gles2/rasterizer_storage_gles2.h +++ b/drivers/gles2/rasterizer_storage_gles2.h @@ -868,16 +868,12 @@ public: Set<RasterizerScene::InstanceBase *> instances; Transform2D base_transform_2d; - Transform world_transform; - Transform world_transform_inverse; - bool use_world_transform; Skeleton() : use_2d(false), size(0), tex_id(0), - update_list(this), - use_world_transform(false) { + update_list(this) { } }; @@ -895,7 +891,6 @@ public: virtual void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform); virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const; virtual void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform); - virtual void skeleton_set_world_transform(RID p_skeleton, bool p_enable, const Transform &p_world_transform); void _update_skeleton_transform_buffer(const PoolVector<float> &p_data, size_t p_size); diff --git a/drivers/gles2/shaders/scene.glsl b/drivers/gles2/shaders/scene.glsl index 8a9387f0b3..51447dc00f 100644 --- a/drivers/gles2/shaders/scene.glsl +++ b/drivers/gles2/shaders/scene.glsl @@ -61,9 +61,6 @@ uniform ivec2 skeleton_texture_size; #endif -uniform highp mat4 skeleton_transform; -uniform highp mat4 skeleton_transform_inverse; -uniform bool skeleton_in_world_coords; #endif @@ -410,12 +407,9 @@ void main() { #endif - if (skeleton_in_world_coords) { - bone_transform = skeleton_transform * (bone_transform * skeleton_transform_inverse); - world_matrix = bone_transform * world_matrix; - } else { - world_matrix = world_matrix * bone_transform; - } + + world_matrix = world_matrix * bone_transform; + #endif diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 1472954ebc..1cab3d89aa 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -2260,11 +2260,6 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_ _set_cull(e->sort_key & RenderList::SORT_KEY_MIRROR_FLAG, e->sort_key & RenderList::SORT_KEY_CULL_DISABLED_FLAG, p_reverse_cull); - if (skeleton) { - state.scene_shader.set_uniform(SceneShaderGLES3::SKELETON_TRANSFORM, skeleton->world_transform); - state.scene_shader.set_uniform(SceneShaderGLES3::SKELETON_IN_WORLD_COORDS, skeleton->use_world_transform); - } - state.scene_shader.set_uniform(SceneShaderGLES3::WORLD_TRANSFORM, e->instance->transform); _render_geometry(e); diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index 5f4acbc2de..d2a799f93c 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -5160,20 +5160,6 @@ void RasterizerStorageGLES3::skeleton_set_base_transform_2d(RID p_skeleton, cons skeleton->base_transform_2d = p_base_transform; } -void RasterizerStorageGLES3::skeleton_set_world_transform(RID p_skeleton, bool p_enable, const Transform &p_world_transform) { - - Skeleton *skeleton = skeleton_owner.getornull(p_skeleton); - - ERR_FAIL_COND(skeleton->use_2d); - - skeleton->world_transform = p_world_transform; - skeleton->use_world_transform = p_enable; - - if (!skeleton->update_list.in_list()) { - skeleton_update_list.add(&skeleton->update_list); - } -} - void RasterizerStorageGLES3::update_dirty_skeletons() { glActiveTexture(GL_TEXTURE0); diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index 0a7e47e304..84632308b4 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -892,15 +892,12 @@ public: SelfList<Skeleton> update_list; Set<RasterizerScene::InstanceBase *> instances; //instances using skeleton Transform2D base_transform_2d; - bool use_world_transform; - Transform world_transform; Skeleton() : use_2d(false), size(0), texture(0), - update_list(this), - use_world_transform(false) { + update_list(this) { } }; @@ -918,7 +915,6 @@ public: virtual void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform); virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const; virtual void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform); - virtual void skeleton_set_world_transform(RID p_skeleton, bool p_enable, const Transform &p_world_transform); /* Light API */ diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index f08d3f4d23..20e0c282e3 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -302,8 +302,6 @@ out highp float dp_clip; #ifdef USE_SKELETON uniform highp sampler2D skeleton_texture; // texunit:-1 -uniform highp mat4 skeleton_transform; -uniform bool skeleton_in_world_coords; #endif out highp vec4 position_interp; @@ -432,14 +430,8 @@ void main() { vec4(0.0, 0.0, 0.0, 1.0)) * bone_weights.w; - if (skeleton_in_world_coords) { - highp mat4 bone_matrix = skeleton_transform * (transpose(m) * inverse(skeleton_transform)); - world_matrix = bone_matrix * world_matrix; - - } else { + world_matrix = world_matrix * transpose(m); - world_matrix = world_matrix * transpose(m); - } } #endif diff --git a/editor/import/editor_import_collada.cpp b/editor/import/editor_import_collada.cpp index 449124acec..adfdfee603 100644 --- a/editor/import/editor_import_collada.cpp +++ b/editor/import/editor_import_collada.cpp @@ -176,7 +176,6 @@ Error ColladaImport::_create_scene_skeletons(Collada::Node *p_node) { Skeleton *sk = memnew(Skeleton); int bone = 0; - sk->set_use_bones_in_world_transform(true); // This improves compatibility in Collada for (int i = 0; i < p_node->children.size(); i++) { _populate_skeleton(sk, p_node->children[i], bone, -1); diff --git a/editor/import/editor_scene_importer_gltf.cpp b/editor/import/editor_scene_importer_gltf.cpp index 9ea7c86e0c..f6c72722db 100644 --- a/editor/import/editor_scene_importer_gltf.cpp +++ b/editor/import/editor_scene_importer_gltf.cpp @@ -2133,7 +2133,7 @@ Spatial *EditorSceneImporterGLTF::_generate_scene(GLTFState &state, int p_bake_f Vector<Skeleton *> skeletons; for (int i = 0; i < state.skins.size(); i++) { Skeleton *s = memnew(Skeleton); - s->set_use_bones_in_world_transform(false); //GLTF does not need this since meshes are always local + String name = state.skins[i].name; if (name == "") { name = _gen_unique_name(state, "Skeleton"); diff --git a/editor/plugins/spatial_editor_plugin.h b/editor/plugins/spatial_editor_plugin.h index 728b67f6fa..aa61f4bae1 100644 --- a/editor/plugins/spatial_editor_plugin.h +++ b/editor/plugins/spatial_editor_plugin.h @@ -58,6 +58,7 @@ public: RID instance; Ref<ArrayMesh> mesh; Ref<Material> material; + Ref<SkinReference> skin_reference; RID skeleton; bool billboard; bool unscaled; @@ -101,7 +102,7 @@ protected: public: void add_lines(const Vector<Vector3> &p_lines, const Ref<Material> &p_material, bool p_billboard = false); - void add_mesh(const Ref<ArrayMesh> &p_mesh, bool p_billboard = false, const RID &p_skeleton = RID(), const Ref<Material> &p_material = Ref<Material>()); + void add_mesh(const Ref<ArrayMesh> &p_mesh, bool p_billboard = false, const Ref<SkinReference> &p_skin_reference = Ref<SkinReference>(), const Ref<Material> &p_material = Ref<Material>()); void add_collision_segments(const Vector<Vector3> &p_lines); void add_collision_triangles(const Ref<TriangleMesh> &p_tmesh); void add_unscaled_billboard(const Ref<Material> &p_material, float p_scale = 1); diff --git a/editor/spatial_editor_gizmos.cpp b/editor/spatial_editor_gizmos.cpp index 4c5371769f..663ce3ba8a 100644 --- a/editor/spatial_editor_gizmos.cpp +++ b/editor/spatial_editor_gizmos.cpp @@ -172,8 +172,8 @@ void EditorSpatialGizmo::Instance::create_instance(Spatial *p_base, bool p_hidde instance = VS::get_singleton()->instance_create2(mesh->get_rid(), p_base->get_world()->get_scenario()); VS::get_singleton()->instance_attach_object_instance_id(instance, p_base->get_instance_id()); - if (skeleton.is_valid()) - VS::get_singleton()->instance_attach_skeleton(instance, skeleton); + if (skin_reference.is_valid()) + VS::get_singleton()->instance_attach_skeleton(instance, skin_reference->get_skeleton()); if (extra_margin) VS::get_singleton()->instance_set_extra_visibility_margin(instance, 1); VS::get_singleton()->instance_geometry_set_cast_shadows_setting(instance, VS::SHADOW_CASTING_SETTING_OFF); @@ -181,14 +181,14 @@ void EditorSpatialGizmo::Instance::create_instance(Spatial *p_base, bool p_hidde VS::get_singleton()->instance_set_layer_mask(instance, layer); //gizmos are 26 } -void EditorSpatialGizmo::add_mesh(const Ref<ArrayMesh> &p_mesh, bool p_billboard, const RID &p_skeleton, const Ref<Material> &p_material) { +void EditorSpatialGizmo::add_mesh(const Ref<ArrayMesh> &p_mesh, bool p_billboard, const Ref<SkinReference> &p_skin_reference, const Ref<Material> &p_material) { ERR_FAIL_COND(!spatial_node); Instance ins; ins.billboard = p_billboard; ins.mesh = p_mesh; - ins.skeleton = p_skeleton; + ins.skin_reference = p_skin_reference; ins.material = p_material; if (valid) { ins.create_instance(spatial_node, hidden); @@ -1789,7 +1789,7 @@ void SkeletonSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { } Ref<ArrayMesh> m = surface_tool->commit(); - p_gizmo->add_mesh(m, false, skel->get_skeleton()); + p_gizmo->add_mesh(m, false, skel->register_skin(Ref<Skin>())); } //// @@ -3712,7 +3712,7 @@ void CollisionShapeSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { Ref<ConcavePolygonShape> cs2 = s; Ref<ArrayMesh> mesh = cs2->get_debug_mesh(); - p_gizmo->add_mesh(mesh, false, RID(), material); + p_gizmo->add_mesh(mesh, false, Ref<SkinReference>(), material); } if (Object::cast_to<RayShape>(*s)) { @@ -3734,7 +3734,7 @@ void CollisionShapeSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { Ref<HeightMapShape> hms = s; Ref<ArrayMesh> mesh = hms->get_debug_mesh(); - p_gizmo->add_mesh(mesh, false, RID(), material); + p_gizmo->add_mesh(mesh, false, Ref<SkinReference>(), material); } } diff --git a/modules/csg/csg_gizmos.cpp b/modules/csg/csg_gizmos.cpp index e6bfa5525d..0d26943af6 100644 --- a/modules/csg/csg_gizmos.cpp +++ b/modules/csg/csg_gizmos.cpp @@ -377,7 +377,7 @@ void CSGShapeSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { break; } - p_gizmo->add_mesh(mesh, false, RID(), solid_material); + p_gizmo->add_mesh(mesh, false, Ref<SkinReference>(), solid_material); } if (Object::cast_to<CSGSphere>(cs)) { diff --git a/scene/3d/mesh_instance.cpp b/scene/3d/mesh_instance.cpp index 89072519d5..50ca466df3 100644 --- a/scene/3d/mesh_instance.cpp +++ b/scene/3d/mesh_instance.cpp @@ -149,12 +149,38 @@ Ref<Mesh> MeshInstance::get_mesh() const { void MeshInstance::_resolve_skeleton_path() { - if (skeleton_path.is_empty()) + Ref<SkinReference> new_skin_reference; + + if (!skeleton_path.is_empty()) { + Skeleton *skeleton = Object::cast_to<Skeleton>(get_node(skeleton_path)); + if (skeleton) { + new_skin_reference = skeleton->register_skin(skin); + if (skin.is_null()) { + //a skin was created for us + skin = new_skin_reference->get_skin(); + _change_notify(); + } + } + } + + skin_ref = new_skin_reference; + + if (skin_ref.is_valid()) { + VisualServer::get_singleton()->instance_attach_skeleton(get_instance(), skin_ref->get_skeleton()); + } else { + VisualServer::get_singleton()->instance_attach_skeleton(get_instance(), RID()); + } +} + +void MeshInstance::set_skin(const Ref<Skin> &p_skin) { + skin = p_skin; + if (!is_inside_tree()) return; + _resolve_skeleton_path(); +} - Skeleton *skeleton = Object::cast_to<Skeleton>(get_node(skeleton_path)); - if (skeleton) - VisualServer::get_singleton()->instance_attach_skeleton(get_instance(), skeleton->get_skeleton()); +Ref<Skin> MeshInstance::get_skin() const { + return skin; } void MeshInstance::set_skeleton_path(const NodePath &p_skeleton) { @@ -365,6 +391,8 @@ void MeshInstance::_bind_methods() { ClassDB::bind_method(D_METHOD("get_mesh"), &MeshInstance::get_mesh); ClassDB::bind_method(D_METHOD("set_skeleton_path", "skeleton_path"), &MeshInstance::set_skeleton_path); ClassDB::bind_method(D_METHOD("get_skeleton_path"), &MeshInstance::get_skeleton_path); + ClassDB::bind_method(D_METHOD("set_skin", "skin"), &MeshInstance::set_skin); + ClassDB::bind_method(D_METHOD("get_skin"), &MeshInstance::get_skin); ClassDB::bind_method(D_METHOD("get_surface_material_count"), &MeshInstance::get_surface_material_count); ClassDB::bind_method(D_METHOD("set_surface_material", "surface", "material"), &MeshInstance::set_surface_material); @@ -380,6 +408,7 @@ void MeshInstance::_bind_methods() { ClassDB::set_method_flags("MeshInstance", "create_debug_tangents", METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "mesh", PROPERTY_HINT_RESOURCE_TYPE, "Mesh"), "set_mesh", "get_mesh"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "skin", PROPERTY_HINT_RESOURCE_TYPE, "Skin"), "set_skin", "get_skin"); ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "skeleton", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Skeleton"), "set_skeleton_path", "get_skeleton_path"); } diff --git a/scene/3d/mesh_instance.h b/scene/3d/mesh_instance.h index 8b690b0c21..77ead75dd3 100644 --- a/scene/3d/mesh_instance.h +++ b/scene/3d/mesh_instance.h @@ -31,8 +31,10 @@ #ifndef MESH_INSTANCE_H #define MESH_INSTANCE_H +#include "scene/3d/skeleton.h" #include "scene/3d/visual_instance.h" #include "scene/resources/mesh.h" +#include "scene/resources/skin.h" class MeshInstance : public GeometryInstance { @@ -40,6 +42,8 @@ class MeshInstance : public GeometryInstance { protected: Ref<Mesh> mesh; + Ref<Skin> skin; + Ref<SkinReference> skin_ref; NodePath skeleton_path; struct BlendShapeTrack { @@ -70,6 +74,9 @@ public: void set_mesh(const Ref<Mesh> &p_mesh); Ref<Mesh> get_mesh() const; + void set_skin(const Ref<Skin> &p_skin); + Ref<Skin> get_skin() const; + void set_skeleton_path(const NodePath &p_skeleton); NodePath get_skeleton_path(); diff --git a/scene/3d/physics_body.cpp b/scene/3d/physics_body.cpp index 0756be5fc8..5cc4f739ca 100644 --- a/scene/3d/physics_body.cpp +++ b/scene/3d/physics_body.cpp @@ -2182,7 +2182,7 @@ void PhysicalBone::_notification(int p_what) { void PhysicalBone::_direct_state_changed(Object *p_state) { - if (!simulate_physics) { + if (!simulate_physics || !_internal_simulate_physics) { return; } @@ -2205,7 +2205,7 @@ void PhysicalBone::_direct_state_changed(Object *p_state) { // Update skeleton if (parent_skeleton) { if (-1 != bone_id) { - parent_skeleton->set_bone_global_pose(bone_id, parent_skeleton->get_global_transform().affine_inverse() * (global_transform * body_offset_inverse)); + parent_skeleton->set_bone_global_pose_override(bone_id, parent_skeleton->get_global_transform().affine_inverse() * (global_transform * body_offset_inverse), 1.0, true); } } } @@ -2716,7 +2716,6 @@ void PhysicalBone::_start_physics_simulation() { PhysicsServer::get_singleton()->body_set_collision_layer(get_rid(), get_collision_layer()); PhysicsServer::get_singleton()->body_set_collision_mask(get_rid(), get_collision_mask()); PhysicsServer::get_singleton()->body_set_force_integration_callback(get_rid(), this, "_direct_state_changed"); - parent_skeleton->set_bone_ignore_animation(bone_id, true); _internal_simulate_physics = true; } @@ -2728,6 +2727,6 @@ void PhysicalBone::_stop_physics_simulation() { PhysicsServer::get_singleton()->body_set_collision_layer(get_rid(), 0); PhysicsServer::get_singleton()->body_set_collision_mask(get_rid(), 0); PhysicsServer::get_singleton()->body_set_force_integration_callback(get_rid(), NULL, ""); - parent_skeleton->set_bone_ignore_animation(bone_id, false); + parent_skeleton->set_bone_global_pose_override(bone_id, Transform(), 0.0, false); _internal_simulate_physics = false; } diff --git a/scene/3d/skeleton.cpp b/scene/3d/skeleton.cpp index e192e040f2..ead1e69f90 100644 --- a/scene/3d/skeleton.cpp +++ b/scene/3d/skeleton.cpp @@ -36,6 +36,34 @@ #include "scene/3d/physics_body.h" #include "scene/resources/surface_tool.h" +void SkinReference::_skin_changed() { + if (skeleton_node) { + skeleton_node->_make_dirty(); + } +} + +void SkinReference::_bind_methods() { + ClassDB::bind_method(D_METHOD("_skin_changed"), &SkinReference::_skin_changed); + ClassDB::bind_method(D_METHOD("get_skeleton"), &SkinReference::get_skeleton); + ClassDB::bind_method(D_METHOD("get_skin"), &SkinReference::get_skin); +} + +RID SkinReference::get_skeleton() const { + return skeleton; +} + +Ref<Skin> SkinReference::get_skin() const { + return skin; +} + +SkinReference::~SkinReference() { + if (skeleton_node) { + skeleton_node->skin_bindings.erase(this); + } + + VS::get_singleton()->free(skeleton); +} + bool Skeleton::_set(const StringName &p_path, const Variant &p_value) { String path = p_path; @@ -196,110 +224,77 @@ void Skeleton::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_WORLD: { - - VS::get_singleton()->skeleton_set_world_transform(skeleton, use_bones_in_world_transform, get_global_transform()); - - } break; - case NOTIFICATION_EXIT_WORLD: { - - } break; - case NOTIFICATION_TRANSFORM_CHANGED: { - - VS::get_singleton()->skeleton_set_world_transform(skeleton, use_bones_in_world_transform, get_global_transform()); - } break; case NOTIFICATION_UPDATE_SKELETON: { VisualServer *vs = VisualServer::get_singleton(); Bone *bonesptr = bones.ptrw(); int len = bones.size(); - vs->skeleton_allocate(skeleton, len); // if same size, nothing really happens - _update_process_order(); const int *order = process_order.ptr(); - // 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[order[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[order[i]]; - b.rest_global_inverse.affine_invert(); - } - - rest_global_inverse_dirty = false; - } - for (int i = 0; i < len; i++) { Bone &b = bonesptr[order[i]]; - if (b.disable_rest) { - if (b.enabled) { + if (b.global_pose_override_amount >= 0.999) { + b.pose_global = b.global_pose_override; + } else { + if (b.disable_rest) { + if (b.enabled) { - Transform pose = b.pose; - if (b.custom_pose_enable) { + Transform pose = b.pose; + if (b.parent >= 0) { - pose = b.custom_pose * pose; - } + b.pose_global = bonesptr[b.parent].pose_global * pose; + } else { - if (b.parent >= 0) { - - b.pose_global = bonesptr[b.parent].pose_global * pose; + b.pose_global = pose; + } } else { - b.pose_global = pose; - } - } else { - - if (b.parent >= 0) { + if (b.parent >= 0) { - b.pose_global = bonesptr[b.parent].pose_global; - } else { + b.pose_global = bonesptr[b.parent].pose_global; + } else { - b.pose_global = Transform(); + b.pose_global = Transform(); + } } - } - } else { - if (b.enabled) { + } else { + if (b.enabled) { - Transform pose = b.pose; - if (b.custom_pose_enable) { + Transform pose = b.pose; - pose = b.custom_pose * pose; - } + if (b.parent >= 0) { - if (b.parent >= 0) { + b.pose_global = bonesptr[b.parent].pose_global * (b.rest * pose); + } else { - b.pose_global = bonesptr[b.parent].pose_global * (b.rest * pose); + b.pose_global = b.rest * pose; + } } else { - b.pose_global = b.rest * pose; - } - } else { + if (b.parent >= 0) { - if (b.parent >= 0) { + b.pose_global = bonesptr[b.parent].pose_global * b.rest; + } else { - b.pose_global = bonesptr[b.parent].pose_global * b.rest; - } else { - - b.pose_global = b.rest; + b.pose_global = b.rest; + } } } + + if (b.global_pose_override_amount >= CMP_EPSILON) { + b.pose_global = b.pose_global.interpolate_with(b.global_pose_override, b.global_pose_override_amount); + } } - b.transform_final = b.pose_global * b.rest_global_inverse; - vs->skeleton_bone_set_transform(skeleton, order[i], b.transform_final); + if (b.global_pose_override_reset) { + b.global_pose_override_amount = 0.0; + } for (List<uint32_t>::Element *E = b.nodes_bound.front(); E; E = E->next()) { @@ -311,28 +306,37 @@ void Skeleton::_notification(int p_what) { } } + //update skins + for (Set<SkinReference *>::Element *E = skin_bindings.front(); E; E = E->next()) { + + const Skin *skin = E->get()->skin.operator->(); + RID skeleton = E->get()->skeleton; + uint32_t bind_count = skin->get_bind_count(); + + if (E->get()->bind_count != bind_count) { + VS::get_singleton()->skeleton_allocate(skeleton, bind_count); + E->get()->bind_count = bind_count; + } + + for (uint32_t i = 0; i < bind_count; i++) { + uint32_t bone_index = skin->get_bind_bone(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)); + } + } + dirty = false; } break; } } -Transform Skeleton::get_bone_transform(int p_bone) const { - ERR_FAIL_INDEX_V(p_bone, bones.size(), Transform()); - if (dirty) - const_cast<Skeleton *>(this)->notification(NOTIFICATION_UPDATE_SKELETON); - return bones[p_bone].pose_global * bones[p_bone].rest_global_inverse; -} - -void Skeleton::set_bone_global_pose(int p_bone, const Transform &p_pose) { +void Skeleton::set_bone_global_pose_override(int p_bone, const Transform &p_pose, float p_amount, bool p_persistent) { ERR_FAIL_INDEX(p_bone, bones.size()); - if (bones[p_bone].parent == -1) { - - set_bone_pose(p_bone, bones[p_bone].rest_global_inverse * p_pose); //fast - } else { - - set_bone_pose(p_bone, bones[p_bone].rest.affine_inverse() * (get_bone_global_pose(bones[p_bone].parent).affine_inverse() * p_pose)); //slow - } + bones.write[p_bone].global_pose_override_amount = p_amount; + bones.write[p_bone].global_pose_override = p_pose; + bones.write[p_bone].global_pose_override_reset = !p_persistent; + _make_dirty(); } Transform Skeleton::get_bone_global_pose(int p_bone) const { @@ -343,11 +347,6 @@ Transform Skeleton::get_bone_global_pose(int p_bone) const { return bones[p_bone].pose_global; } -RID Skeleton::get_skeleton() const { - - return skeleton; -} - // skeleton creation api void Skeleton::add_bone(const String &p_name) { @@ -362,8 +361,6 @@ void Skeleton::add_bone(const String &p_name) { b.name = p_name; bones.push_back(b); process_order_dirty = true; - - rest_global_inverse_dirty = true; _make_dirty(); update_gizmo(); } @@ -408,7 +405,6 @@ void Skeleton::set_bone_parent(int p_bone, int p_parent) { 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(); } @@ -426,23 +422,11 @@ void Skeleton::unparent_bone_and_rest(int p_bone) { } bones.write[p_bone].parent = -1; - bones.write[p_bone].rest_global_inverse = bones[p_bone].rest.affine_inverse(); //same thing process_order_dirty = true; _make_dirty(); } -void Skeleton::set_bone_ignore_animation(int p_bone, bool p_ignore) { - ERR_FAIL_INDEX(p_bone, bones.size()); - bones.write[p_bone].ignore_animation = p_ignore; -} - -bool Skeleton::is_bone_ignore_animation(int p_bone) const { - - ERR_FAIL_INDEX_V(p_bone, bones.size(), false); - return bones[p_bone].ignore_animation; -} - void Skeleton::set_bone_disable_rest(int p_bone, bool p_disable) { ERR_FAIL_INDEX(p_bone, bones.size()); @@ -467,7 +451,6 @@ 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(); } Transform Skeleton::get_bone_rest(int p_bone) const { @@ -482,7 +465,6 @@ void Skeleton::set_bone_enabled(int p_bone, bool p_enabled) { ERR_FAIL_INDEX(p_bone, bones.size()); bones.write[p_bone].enabled = p_enabled; - rest_global_inverse_dirty = true; _make_dirty(); } bool Skeleton::is_bone_enabled(int p_bone) const { @@ -529,7 +511,6 @@ void Skeleton::get_bound_child_nodes_to_bone(int p_bone, List<Node *> *p_bound) void Skeleton::clear_bones() { bones.clear(); - rest_global_inverse_dirty = true; process_order_dirty = true; _make_dirty(); @@ -552,23 +533,6 @@ Transform Skeleton::get_bone_pose(int p_bone) const { return bones[p_bone].pose; } -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(); -} - -Transform Skeleton::get_bone_custom_pose(int p_bone) const { - - ERR_FAIL_INDEX_V(p_bone, bones.size(), Transform()); - return bones[p_bone].custom_pose; -} - void Skeleton::_make_dirty() { if (dirty) @@ -747,14 +711,66 @@ void Skeleton::physical_bones_remove_collision_exception(RID p_exception) { #endif // _3D_DISABLED -void Skeleton::set_use_bones_in_world_transform(bool p_enable) { - use_bones_in_world_transform = p_enable; - if (is_inside_tree()) { - VS::get_singleton()->skeleton_set_world_transform(skeleton, use_bones_in_world_transform, get_global_transform()); - } +void Skeleton::_skin_changed() { + _make_dirty(); } -bool Skeleton::is_using_bones_in_world_transform() const { - return use_bones_in_world_transform; + +Ref<SkinReference> Skeleton::register_skin(const Ref<Skin> &p_skin) { + + for (Set<SkinReference *>::Element *E = skin_bindings.front(); E; E = E->next()) { + if (E->get()->skin == p_skin) { + return Ref<SkinReference>(E->get()); + } + } + + Ref<Skin> skin = p_skin; + + if (skin.is_null()) { + //need to create one from existing code, this is for compatibility only + //when skeletons did not support skins. It is also used by gizmo + //to display the skeleton. + + skin.instance(); + skin->set_bind_count(bones.size()); + _update_process_order(); //just in case + + // pose changed, rebuild cache of inverses + const Bone *bonesptr = bones.ptr(); + int len = bones.size(); + const int *order = process_order.ptr(); + + // calculate global rests and invert them + for (int i = 0; i < len; i++) { + const Bone &b = bonesptr[order[i]]; + if (b.parent >= 0) { + skin->set_bind_pose(order[i], skin->get_bind_pose(b.parent) * b.rest); + } else { + skin->set_bind_pose(order[i], b.rest); + } + } + + for (int i = 0; i < len; i++) { + //the inverse is what is actually required + skin->set_bind_bone(i, i); + skin->set_bind_pose(i, skin->get_bind_pose(i).affine_inverse()); + } + } + + ERR_FAIL_COND_V(skin.is_null(), Ref<SkinReference>()); + + Ref<SkinReference> skin_ref; + skin_ref.instance(); + + skin_ref->skeleton_node = this; + skin_ref->bind_count = 0; + skin_ref->skeleton = VisualServer::get_singleton()->skeleton_create(); + skin_ref->skeleton_node = this; + skin_ref->skin = skin; + + skin_bindings.insert(skin_ref.operator->()); + + skin->connect("changed", skin_ref.operator->(), "_skin_changed"); + return skin_ref; } void Skeleton::_bind_methods() { @@ -773,6 +789,8 @@ void Skeleton::_bind_methods() { ClassDB::bind_method(D_METHOD("get_bone_rest", "bone_idx"), &Skeleton::get_bone_rest); ClassDB::bind_method(D_METHOD("set_bone_rest", "bone_idx", "rest"), &Skeleton::set_bone_rest); + ClassDB::bind_method(D_METHOD("register_skin", "skin"), &Skeleton::register_skin); + ClassDB::bind_method(D_METHOD("localize_rests"), &Skeleton::localize_rests); ClassDB::bind_method(D_METHOD("set_bone_disable_rest", "bone_idx", "disable"), &Skeleton::set_bone_disable_rest); @@ -787,17 +805,9 @@ void Skeleton::_bind_methods() { ClassDB::bind_method(D_METHOD("get_bone_pose", "bone_idx"), &Skeleton::get_bone_pose); ClassDB::bind_method(D_METHOD("set_bone_pose", "bone_idx", "pose"), &Skeleton::set_bone_pose); - ClassDB::bind_method(D_METHOD("set_bone_global_pose", "bone_idx", "pose"), &Skeleton::set_bone_global_pose); + ClassDB::bind_method(D_METHOD("set_bone_global_pose_override", "bone_idx", "pose", "amount", "persistent"), &Skeleton::set_bone_global_pose_override, DEFVAL(false)); ClassDB::bind_method(D_METHOD("get_bone_global_pose", "bone_idx"), &Skeleton::get_bone_global_pose); - ClassDB::bind_method(D_METHOD("get_bone_custom_pose", "bone_idx"), &Skeleton::get_bone_custom_pose); - ClassDB::bind_method(D_METHOD("set_bone_custom_pose", "bone_idx", "custom_pose"), &Skeleton::set_bone_custom_pose); - - ClassDB::bind_method(D_METHOD("get_bone_transform", "bone_idx"), &Skeleton::get_bone_transform); - - ClassDB::bind_method(D_METHOD("set_use_bones_in_world_transform", "enable"), &Skeleton::set_use_bones_in_world_transform); - ClassDB::bind_method(D_METHOD("is_using_bones_in_world_transform"), &Skeleton::is_using_bones_in_world_transform); - #ifndef _3D_DISABLED ClassDB::bind_method(D_METHOD("physical_bones_stop_simulation"), &Skeleton::physical_bones_stop_simulation); @@ -807,22 +817,19 @@ void Skeleton::_bind_methods() { #endif // _3D_DISABLED - ClassDB::bind_method(D_METHOD("set_bone_ignore_animation", "bone", "ignore"), &Skeleton::set_bone_ignore_animation); - - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "bones_in_world_transform"), "set_use_bones_in_world_transform", "is_using_bones_in_world_transform"); BIND_CONSTANT(NOTIFICATION_UPDATE_SKELETON); } Skeleton::Skeleton() { - rest_global_inverse_dirty = true; dirty = false; process_order_dirty = true; - skeleton = VisualServer::get_singleton()->skeleton_create(); - set_notify_transform(true); - use_bones_in_world_transform = false; } Skeleton::~Skeleton() { - VisualServer::get_singleton()->free(skeleton); + + //some skins may remain bound + for (Set<SkinReference *>::Element *E = skin_bindings.front(); E; E = E->next()) { + E->get()->skeleton_node = nullptr; + } } diff --git a/scene/3d/skeleton.h b/scene/3d/skeleton.h index 5b55dffbc8..f20c550055 100644 --- a/scene/3d/skeleton.h +++ b/scene/3d/skeleton.h @@ -33,6 +33,7 @@ #include "core/rid.h" #include "scene/3d/spatial.h" +#include "scene/resources/skin.h" #ifndef _3D_DISABLED typedef int BoneId; @@ -40,10 +41,38 @@ typedef int BoneId; class PhysicalBone; #endif // _3D_DISABLED +class Skeleton; + +class SkinReference : public Reference { + GDCLASS(SkinReference, Reference) + friend class Skeleton; + + Skeleton *skeleton_node; + RID skeleton; + Ref<Skin> skin; + uint32_t bind_count = 0; + void _skin_changed(); + +protected: + static void _bind_methods(); + +public: + RID get_skeleton() const; + Ref<Skin> get_skin() const; + ~SkinReference(); +}; + class Skeleton : public Spatial { GDCLASS(Skeleton, Spatial); +private: + friend class SkinReference; + + Set<SkinReference *> skin_bindings; + + void _skin_changed(); + struct Bone { String name; @@ -52,19 +81,15 @@ class Skeleton : public Spatial { int parent; int sort_index; //used for re-sorting process order - bool ignore_animation; - bool disable_rest; Transform rest; - Transform rest_global_inverse; Transform pose; Transform pose_global; - bool custom_pose_enable; - Transform custom_pose; - - Transform transform_final; + float global_pose_override_amount; + bool global_pose_override_reset; + Transform global_pose_override; #ifndef _3D_DISABLED PhysicalBone *physical_bone; @@ -76,9 +101,9 @@ class Skeleton : public Spatial { Bone() { parent = -1; enabled = true; - ignore_animation = false; - custom_pose_enable = false; disable_rest = false; + global_pose_override_amount = 0; + global_pose_override_reset = false; #ifndef _3D_DISABLED physical_bone = NULL; cache_parent_physical_bone = NULL; @@ -86,17 +111,12 @@ class Skeleton : public Spatial { } }; - bool rest_global_inverse_dirty; - Vector<Bone> bones; Vector<int> process_order; bool process_order_dirty; - RID skeleton; - void _make_dirty(); bool dirty; - bool use_bones_in_world_transform; // bind helpers Array _get_bound_child_nodes_to_bone(int p_bone) const { @@ -127,8 +147,6 @@ public: NOTIFICATION_UPDATE_SKELETON = 50 }; - RID get_skeleton() const; - // skeleton creation api void add_bone(const String &p_name); int find_bone(const String &p_name) const; @@ -141,9 +159,6 @@ public: void unparent_bone_and_rest(int p_bone); - void set_bone_ignore_animation(int p_bone, bool p_ignore); - bool is_bone_ignore_animation(int p_bone) const; - void set_bone_disable_rest(int p_bone, bool p_disable); bool is_bone_rest_disabled(int p_bone) const; @@ -151,10 +166,9 @@ public: void set_bone_rest(int p_bone, const Transform &p_rest); Transform get_bone_rest(int p_bone) const; - Transform get_bone_transform(int p_bone) const; Transform get_bone_global_pose(int p_bone) const; - void set_bone_global_pose(int p_bone, const Transform &p_pose); + void set_bone_global_pose_override(int p_bone, const Transform &p_pose, float p_amount, bool p_persistent = false); void set_bone_enabled(int p_bone, bool p_enabled); bool is_bone_enabled(int p_bone) const; @@ -170,14 +184,10 @@ public: void set_bone_pose(int p_bone, const Transform &p_pose); Transform get_bone_pose(int p_bone) const; - void set_bone_custom_pose(int p_bone, const Transform &p_custom_pose); - Transform get_bone_custom_pose(int p_bone) const; - void localize_rests(); // used for loaders and tools int get_process_order(int p_idx); - void set_use_bones_in_world_transform(bool p_enable); - bool is_using_bones_in_world_transform() const; + Ref<SkinReference> register_skin(const Ref<Skin> &p_skin); #ifndef _3D_DISABLED // Physical bone API diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp index 051f832882..728c23fbaa 100644 --- a/scene/animation/animation_player.cpp +++ b/scene/animation/animation_player.cpp @@ -256,7 +256,7 @@ void AnimationPlayer::_ensure_node_caches(AnimationData *p_anim) { Skeleton *sk = Object::cast_to<Skeleton>(child); bone_idx = sk->find_bone(a->track_get_path(i).get_subname(0)); - if (bone_idx == -1 || sk->is_bone_ignore_animation(bone_idx)) { + if (bone_idx == -1) { continue; } diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp index bb7c400cfe..eb152bc41e 100644 --- a/scene/animation/animation_tree.cpp +++ b/scene/animation/animation_tree.cpp @@ -622,7 +622,7 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) { Skeleton *sk = Object::cast_to<Skeleton>(spatial); int bone_idx = sk->find_bone(path.get_subname(0)); - if (bone_idx != -1 && !sk->is_bone_ignore_animation(bone_idx)) { + if (bone_idx != -1) { track_xform->skeleton = sk; track_xform->bone_idx = bone_idx; diff --git a/scene/animation/animation_tree_player.cpp b/scene/animation/animation_tree_player.cpp index 8f6d53c21c..ba5936562a 100644 --- a/scene/animation/animation_tree_player.cpp +++ b/scene/animation/animation_tree_player.cpp @@ -820,11 +820,7 @@ void AnimationTreePlayer::_process_animation(float p_delta) { t.value = t.object->get_indexed(t.subpath); t.value.zero(); - if (t.skeleton) { - t.skip = t.skeleton->is_bone_ignore_animation(t.bone_idx); - } else { - t.skip = false; - } + t.skip = false; } /* STEP 2 PROCESS ANIMATIONS */ diff --git a/scene/animation/skeleton_ik.cpp b/scene/animation/skeleton_ik.cpp index 7a1b10792b..4ec22cf3df 100644 --- a/scene/animation/skeleton_ik.cpp +++ b/scene/animation/skeleton_ik.cpp @@ -320,7 +320,7 @@ void FabrikInverseKinematic::solve(Task *p_task, real_t blending_delta, bool ove new_bone_pose.basis = new_bone_pose.basis * p_task->chain.tips[0].end_effector->goal_transform.basis; } - p_task->skeleton->set_bone_global_pose(ci->bone, new_bone_pose); + p_task->skeleton->set_bone_global_pose_override(ci->bone, new_bone_pose, 1.0); if (!ci->children.empty()) ci = &ci->children.write[0]; diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index e3af521e8c..418ee6af0e 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -364,6 +364,9 @@ void register_scene_types() { /* REGISTER 3D */ + ClassDB::register_class<Skin>(); + ClassDB::register_virtual_class<SkinReference>(); + ClassDB::register_class<Spatial>(); ClassDB::register_virtual_class<SpatialGizmo>(); ClassDB::register_class<Skeleton>(); diff --git a/scene/resources/skin.cpp b/scene/resources/skin.cpp new file mode 100644 index 0000000000..8446e2f249 --- /dev/null +++ b/scene/resources/skin.cpp @@ -0,0 +1,102 @@ +#include "skin.h" + +void Skin::set_bind_count(int p_size) { + ERR_FAIL_COND(p_size < 0); + binds.resize(p_size); + binds_ptr = binds.ptrw(); + bind_count = p_size; + emit_changed(); +} + +void Skin::add_bind(int p_bone, const Transform &p_pose) { + uint32_t index = bind_count; + set_bind_count(bind_count + 1); + set_bind_bone(index, p_bone); + set_bind_pose(index, p_pose); +} + +void Skin::set_bind_bone(int p_index, int p_bone) { + ERR_FAIL_INDEX(p_index, bind_count); + binds_ptr[p_index].bone = p_bone; + emit_changed(); +} + +void Skin::set_bind_pose(int p_index, const Transform &p_pose) { + ERR_FAIL_INDEX(p_index, bind_count); + binds_ptr[p_index].pose = p_pose; + emit_changed(); +} + +void Skin::clear_binds() { + binds.clear(); + binds_ptr = nullptr; + bind_count = 0; + emit_changed(); +} + +bool Skin::_set(const StringName &p_name, const Variant &p_value) { + String name = p_name; + if (name == "bind_count") { + set_bind_count(p_value); + return true; + } else if (name.begins_with("bind/")) { + int index = name.get_slicec('/', 1).to_int(); + String what = name.get_slicec('/', 2); + if (what == "bone") { + set_bind_bone(index, p_value); + return true; + } else if (what == "pose") { + set_bind_pose(index, p_value); + return true; + } + } + return false; +} + +bool Skin::_get(const StringName &p_name, Variant &r_ret) const { + + String name = p_name; + if (name == "bind_count") { + r_ret = get_bind_count(); + return true; + } else if (name.begins_with("bind/")) { + int index = name.get_slicec('/', 1).to_int(); + String what = name.get_slicec('/', 2); + if (what == "bone") { + r_ret = get_bind_bone(index); + return true; + } else if (what == "pose") { + r_ret = get_bind_pose(index); + return true; + } + } + return false; +} +void Skin::_get_property_list(List<PropertyInfo> *p_list) const { + p_list->push_back(PropertyInfo(Variant::INT, "bind_count", PROPERTY_HINT_RANGE, "0,16384,1,or_greater")); + for (int i = 0; i < get_bind_count(); i++) { + p_list->push_back(PropertyInfo(Variant::INT, "bind/" + itos(i) + "/bone", PROPERTY_HINT_RANGE, "0,16384,1,or_greater")); + p_list->push_back(PropertyInfo(Variant::TRANSFORM, "bind/" + itos(i) + "/pose")); + } +} + +void Skin::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_bind_count", "bind_count"), &Skin::set_bind_count); + ClassDB::bind_method(D_METHOD("get_bind_count"), &Skin::get_bind_count); + + ClassDB::bind_method(D_METHOD("add_bind", "bone", "pose"), &Skin::add_bind); + + ClassDB::bind_method(D_METHOD("set_bind_pose", "bind_index", "pose"), &Skin::set_bind_pose); + ClassDB::bind_method(D_METHOD("get_bind_pose", "bind_index"), &Skin::get_bind_pose); + + ClassDB::bind_method(D_METHOD("set_bind_bone", "bind_index", "bone"), &Skin::set_bind_bone); + ClassDB::bind_method(D_METHOD("get_bind_bone", "bind_index"), &Skin::get_bind_bone); + + ClassDB::bind_method(D_METHOD("clear_binds"), &Skin::clear_binds); +} + +Skin::Skin() { + bind_count = 0; + binds_ptr = nullptr; +} diff --git a/scene/resources/skin.h b/scene/resources/skin.h new file mode 100644 index 0000000000..a7e55bfa89 --- /dev/null +++ b/scene/resources/skin.h @@ -0,0 +1,54 @@ +#ifndef SKIN_H +#define SKIN_H + +#include "core/resource.h" + +class Skin : public Resource { + GDCLASS(Skin, Resource) + + struct Bind { + int bone; + Transform pose; + }; + + Vector<Bind> binds; + + Bind *binds_ptr; + int bind_count; + +protected: + bool _set(const StringName &p_name, const Variant &p_value); + bool _get(const StringName &p_name, Variant &r_ret) const; + void _get_property_list(List<PropertyInfo> *p_list) const; + + static void _bind_methods(); + +public: + void set_bind_count(int p_size); + inline int get_bind_count() const { return bind_count; } + + void add_bind(int p_bone, const Transform &p_pose); + + void set_bind_bone(int p_index, int p_bone); + void set_bind_pose(int p_index, const Transform &p_pose); + + inline int get_bind_bone(int p_index) const { +#ifdef DEBUG_ENABLED + ERR_FAIL_INDEX_V(p_index, bind_count, -1); +#endif + return binds_ptr[p_index].bone; + } + + inline Transform get_bind_pose(int p_index) const { +#ifdef DEBUG_ENABLED + ERR_FAIL_INDEX_V(p_index, bind_count, Transform()); +#endif + return binds_ptr[p_index].pose; + } + + void clear_binds(); + + Skin(); +}; + +#endif // SKIN_H diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h index 31b468b50b..9aaebefd80 100644 --- a/servers/visual/rasterizer.h +++ b/servers/visual/rasterizer.h @@ -357,7 +357,6 @@ public: virtual void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) = 0; virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const = 0; virtual void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) = 0; - virtual void skeleton_set_world_transform(RID p_skeleton, bool p_enable, const Transform &p_world_transform) = 0; /* Light API */ diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h index dcfbd28dd6..0df228457e 100644 --- a/servers/visual/visual_server_raster.h +++ b/servers/visual/visual_server_raster.h @@ -294,7 +294,6 @@ public: BIND3(skeleton_bone_set_transform_2d, RID, int, const Transform2D &) BIND2RC(Transform2D, skeleton_bone_get_transform_2d, RID, int) BIND2(skeleton_set_base_transform_2d, RID, const Transform2D &) - BIND3(skeleton_set_world_transform, RID, bool, const Transform &) /* Light API */ diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h index 41993d7c88..273cf728c1 100644 --- a/servers/visual/visual_server_wrap_mt.h +++ b/servers/visual/visual_server_wrap_mt.h @@ -230,7 +230,6 @@ public: FUNC3(skeleton_bone_set_transform_2d, RID, int, const Transform2D &) FUNC2RC(Transform2D, skeleton_bone_get_transform_2d, RID, int) FUNC2(skeleton_set_base_transform_2d, RID, const Transform2D &) - FUNC3(skeleton_set_world_transform, RID, bool, const Transform &) /* Light API */ diff --git a/servers/visual_server.h b/servers/visual_server.h index 1b0164e5ca..5e6c4d9b1e 100644 --- a/servers/visual_server.h +++ b/servers/visual_server.h @@ -391,7 +391,6 @@ public: virtual void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) = 0; virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const = 0; virtual void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) = 0; - virtual void skeleton_set_world_transform(RID p_skeleton, bool p_enable, const Transform &p_base_transform) = 0; /* Light API */ |