1use std::ffi::CString;
2use std::ptr;
3
4use crate::animated_value_types::{AnimatedQuaternionArray, AnimatedVector3Array};
5use crate::error::Result;
6use crate::ffi;
7use crate::handle::ObjectHandle;
8use crate::object::Object;
9use crate::protocols::{Component, JointAnimation};
10use crate::skeleton::Skeleton;
11use crate::types::{AnimationBindComponentInfo, PackedJointAnimationInfo};
12use crate::util::{c_string, parse_json, required_handle};
13
14fn c_string_vec(values: &[&str]) -> Result<(Vec<CString>, Vec<*const i8>)> {
15 let c_strings = values
16 .iter()
17 .map(|value| c_string(value))
18 .collect::<Result<Vec<_>>>()?;
19 let raw = c_strings.iter().map(|value| value.as_ptr()).collect();
20 Ok((c_strings, raw))
21}
22
23#[derive(Debug, Clone)]
24pub struct PackedJointAnimation {
26 handle: ObjectHandle,
27}
28
29impl JointAnimation for PackedJointAnimation {}
30
31impl PackedJointAnimation {
32 pub(crate) fn from_handle(handle: ObjectHandle) -> Self {
34 Self { handle }
35 }
36
37 pub fn new(name: &str, joint_paths: &[&str]) -> Result<Self> {
39 let name = c_string(name)?;
40 let (_joint_paths, raw_joint_paths) = c_string_vec(joint_paths)?;
41 let mut out_animation = ptr::null_mut();
42 let mut out_error = ptr::null_mut();
43 let status = unsafe {
45 ffi::mdl_packed_joint_animation_new(
46 name.as_ptr(),
47 raw_joint_paths.as_ptr(),
48 raw_joint_paths.len() as u64,
49 &mut out_animation,
50 &mut out_error,
51 )
52 };
53 crate::util::status_result(status, out_error)?;
54 Ok(Self::from_handle(required_handle(
55 out_animation,
56 "MDLPackedJointAnimation",
57 )?))
58 }
59
60 pub fn info(&self) -> Result<PackedJointAnimationInfo> {
62 parse_json(
63 unsafe { ffi::mdl_packed_joint_animation_info_json(self.handle.as_ptr()) },
65 "MDLPackedJointAnimation",
66 )
67 }
68
69 pub fn translations(&self) -> Result<AnimatedVector3Array> {
71 let ptr = unsafe { ffi::mdl_packed_joint_animation_translations(self.handle.as_ptr()) };
73 Ok(AnimatedVector3Array::from_handle(required_handle(
74 ptr,
75 "MDLPackedJointAnimation translations",
76 )?))
77 }
78
79 pub fn rotations(&self) -> Result<AnimatedQuaternionArray> {
81 let ptr = unsafe { ffi::mdl_packed_joint_animation_rotations(self.handle.as_ptr()) };
83 Ok(AnimatedQuaternionArray::from_handle(required_handle(
84 ptr,
85 "MDLPackedJointAnimation rotations",
86 )?))
87 }
88
89 pub fn scales(&self) -> Result<AnimatedVector3Array> {
91 let ptr = unsafe { ffi::mdl_packed_joint_animation_scales(self.handle.as_ptr()) };
93 Ok(AnimatedVector3Array::from_handle(required_handle(
94 ptr,
95 "MDLPackedJointAnimation scales",
96 )?))
97 }
98
99 #[must_use]
100 pub fn as_object(&self) -> Object {
102 Object::from_handle(self.handle.clone())
103 }
104}
105
106#[derive(Debug, Clone)]
107pub struct AnimationBindComponent {
109 handle: ObjectHandle,
110}
111
112impl Component for AnimationBindComponent {}
113
114impl AnimationBindComponent {
115 pub(crate) fn from_handle(handle: ObjectHandle) -> Self {
117 Self { handle }
118 }
119
120 pub fn new() -> Result<Self> {
122 let mut out_component = ptr::null_mut();
123 let mut out_error = ptr::null_mut();
124 let status =
125 unsafe { ffi::mdl_animation_bind_component_new(&mut out_component, &mut out_error) };
127 crate::util::status_result(status, out_error)?;
128 Ok(Self::from_handle(required_handle(
129 out_component,
130 "MDLAnimationBindComponent",
131 )?))
132 }
133
134 pub fn info(&self) -> Result<AnimationBindComponentInfo> {
136 parse_json(
137 unsafe { ffi::mdl_animation_bind_component_info_json(self.handle.as_ptr()) },
139 "MDLAnimationBindComponent",
140 )
141 }
142
143 pub fn set_skeleton(&self, skeleton: &Skeleton) {
145 unsafe {
147 ffi::mdl_animation_bind_component_set_skeleton(
148 self.handle.as_ptr(),
149 skeleton.handle.as_ptr(),
150 );
151 };
152 }
153
154 #[must_use]
155 pub fn skeleton(&self) -> Option<Skeleton> {
157 let ptr = unsafe { ffi::mdl_animation_bind_component_skeleton(self.handle.as_ptr()) };
159 unsafe { ObjectHandle::from_retained_ptr(ptr) }.map(Skeleton::from_handle)
161 }
162
163 pub fn set_packed_joint_animation(&self, animation: &PackedJointAnimation) {
165 unsafe {
167 ffi::mdl_animation_bind_component_set_packed_joint_animation(
168 self.handle.as_ptr(),
169 animation.handle.as_ptr(),
170 );
171 };
172 }
173
174 #[must_use]
175 pub fn packed_joint_animation(&self) -> Option<PackedJointAnimation> {
177 let ptr = unsafe {
179 ffi::mdl_animation_bind_component_packed_joint_animation(self.handle.as_ptr())
180 };
181 unsafe { ObjectHandle::from_retained_ptr(ptr) }.map(PackedJointAnimation::from_handle)
183 }
184
185 pub fn set_joint_paths(&self, joint_paths: &[&str]) -> Result<()> {
187 let (_joint_paths, raw_joint_paths) = c_string_vec(joint_paths)?;
188 unsafe {
190 ffi::mdl_animation_bind_component_set_joint_paths(
191 self.handle.as_ptr(),
192 raw_joint_paths.as_ptr(),
193 raw_joint_paths.len() as u64,
194 );
195 };
196 Ok(())
197 }
198
199 pub fn set_geometry_bind_transform(&self, matrix: [f32; 16]) {
201 unsafe {
203 ffi::mdl_animation_bind_component_set_geometry_bind_transform(
204 self.handle.as_ptr(),
205 matrix.as_ptr(),
206 );
207 };
208 }
209}