Skip to main content

modelio/
animation.rs

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::skeleton::Skeleton;
10use crate::types::{AnimationBindComponentInfo, PackedJointAnimationInfo};
11use crate::util::{c_string, parse_json, required_handle};
12
13fn c_string_vec(values: &[&str]) -> Result<(Vec<CString>, Vec<*const i8>)> {
14    let c_strings = values
15        .iter()
16        .map(|value| c_string(value))
17        .collect::<Result<Vec<_>>>()?;
18    let raw = c_strings.iter().map(|value| value.as_ptr()).collect();
19    Ok((c_strings, raw))
20}
21
22#[derive(Debug, Clone)]
23pub struct PackedJointAnimation {
24    handle: ObjectHandle,
25}
26
27impl PackedJointAnimation {
28    pub(crate) fn from_handle(handle: ObjectHandle) -> Self {
29        Self { handle }
30    }
31
32    pub fn new(name: &str, joint_paths: &[&str]) -> Result<Self> {
33        let name = c_string(name)?;
34        let (_joint_paths, raw_joint_paths) = c_string_vec(joint_paths)?;
35        let mut out_animation = ptr::null_mut();
36        let mut out_error = ptr::null_mut();
37        let status = unsafe {
38            ffi::mdl_packed_joint_animation_new(
39                name.as_ptr(),
40                raw_joint_paths.as_ptr(),
41                raw_joint_paths.len() as u64,
42                &mut out_animation,
43                &mut out_error,
44            )
45        };
46        crate::util::status_result(status, out_error)?;
47        Ok(Self::from_handle(required_handle(
48            out_animation,
49            "MDLPackedJointAnimation",
50        )?))
51    }
52
53    pub fn info(&self) -> Result<PackedJointAnimationInfo> {
54        parse_json(
55            unsafe { ffi::mdl_packed_joint_animation_info_json(self.handle.as_ptr()) },
56            "MDLPackedJointAnimation",
57        )
58    }
59
60    pub fn translations(&self) -> Result<AnimatedVector3Array> {
61        let ptr = unsafe { ffi::mdl_packed_joint_animation_translations(self.handle.as_ptr()) };
62        Ok(AnimatedVector3Array::from_handle(required_handle(
63            ptr,
64            "MDLPackedJointAnimation translations",
65        )?))
66    }
67
68    pub fn rotations(&self) -> Result<AnimatedQuaternionArray> {
69        let ptr = unsafe { ffi::mdl_packed_joint_animation_rotations(self.handle.as_ptr()) };
70        Ok(AnimatedQuaternionArray::from_handle(required_handle(
71            ptr,
72            "MDLPackedJointAnimation rotations",
73        )?))
74    }
75
76    pub fn scales(&self) -> Result<AnimatedVector3Array> {
77        let ptr = unsafe { ffi::mdl_packed_joint_animation_scales(self.handle.as_ptr()) };
78        Ok(AnimatedVector3Array::from_handle(required_handle(
79            ptr,
80            "MDLPackedJointAnimation scales",
81        )?))
82    }
83
84    #[must_use]
85    pub fn as_object(&self) -> Object {
86        Object::from_handle(self.handle.clone())
87    }
88}
89
90#[derive(Debug, Clone)]
91pub struct AnimationBindComponent {
92    handle: ObjectHandle,
93}
94
95impl AnimationBindComponent {
96    pub(crate) fn from_handle(handle: ObjectHandle) -> Self {
97        Self { handle }
98    }
99
100    pub fn new() -> Result<Self> {
101        let mut out_component = ptr::null_mut();
102        let mut out_error = ptr::null_mut();
103        let status =
104            unsafe { ffi::mdl_animation_bind_component_new(&mut out_component, &mut out_error) };
105        crate::util::status_result(status, out_error)?;
106        Ok(Self::from_handle(required_handle(
107            out_component,
108            "MDLAnimationBindComponent",
109        )?))
110    }
111
112    pub fn info(&self) -> Result<AnimationBindComponentInfo> {
113        parse_json(
114            unsafe { ffi::mdl_animation_bind_component_info_json(self.handle.as_ptr()) },
115            "MDLAnimationBindComponent",
116        )
117    }
118
119    pub fn set_skeleton(&self, skeleton: &Skeleton) {
120        unsafe {
121            ffi::mdl_animation_bind_component_set_skeleton(
122                self.handle.as_ptr(),
123                skeleton.handle.as_ptr(),
124            );
125        };
126    }
127
128    #[must_use]
129    pub fn skeleton(&self) -> Option<Skeleton> {
130        let ptr = unsafe { ffi::mdl_animation_bind_component_skeleton(self.handle.as_ptr()) };
131        unsafe { ObjectHandle::from_retained_ptr(ptr) }.map(Skeleton::from_handle)
132    }
133
134    pub fn set_packed_joint_animation(&self, animation: &PackedJointAnimation) {
135        unsafe {
136            ffi::mdl_animation_bind_component_set_packed_joint_animation(
137                self.handle.as_ptr(),
138                animation.handle.as_ptr(),
139            );
140        };
141    }
142
143    #[must_use]
144    pub fn packed_joint_animation(&self) -> Option<PackedJointAnimation> {
145        let ptr = unsafe {
146            ffi::mdl_animation_bind_component_packed_joint_animation(self.handle.as_ptr())
147        };
148        unsafe { ObjectHandle::from_retained_ptr(ptr) }.map(PackedJointAnimation::from_handle)
149    }
150
151    pub fn set_joint_paths(&self, joint_paths: &[&str]) -> Result<()> {
152        let (_joint_paths, raw_joint_paths) = c_string_vec(joint_paths)?;
153        unsafe {
154            ffi::mdl_animation_bind_component_set_joint_paths(
155                self.handle.as_ptr(),
156                raw_joint_paths.as_ptr(),
157                raw_joint_paths.len() as u64,
158            );
159        };
160        Ok(())
161    }
162
163    pub fn set_geometry_bind_transform(&self, matrix: [f32; 16]) {
164        unsafe {
165            ffi::mdl_animation_bind_component_set_geometry_bind_transform(
166                self.handle.as_ptr(),
167                matrix.as_ptr(),
168            );
169        };
170    }
171}