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}