Skip to main content

modelio/
animated_value_types.rs

1use std::ptr;
2
3use crate::error::Result;
4use crate::ffi;
5use crate::handle::ObjectHandle;
6use crate::types::{AnimatedValueInfo, AnimatedValueInterpolation};
7use crate::util::{parse_json, required_handle};
8
9fn animated_info(handle: &ObjectHandle, context: &'static str) -> Result<AnimatedValueInfo> {
10    parse_json(
11        // SAFETY: ObjectHandle wraps a valid opaque pointer from Swift; FFI function accepts it safely.
12        unsafe { ffi::mdl_animated_value_info_json(handle.as_ptr()) },
13        context,
14    )
15}
16
17fn animated_clear(handle: &ObjectHandle) {
18    // SAFETY: ObjectHandle wraps a valid opaque pointer from Swift; FFI function accepts it safely.
19    unsafe { ffi::mdl_animated_value_clear(handle.as_ptr()) };
20}
21
22fn animated_set_interpolation(handle: &ObjectHandle, interpolation: AnimatedValueInterpolation) {
23    // SAFETY: ObjectHandle wraps a valid opaque pointer from Swift; FFI function accepts it safely.
24    unsafe { ffi::mdl_animated_value_set_interpolation(handle.as_ptr(), interpolation.as_raw()) };
25}
26
27fn convert_vectors<const N: usize>(raw: &[f32]) -> Vec<[f32; N]> {
28    raw.chunks_exact(N)
29        .map(|chunk| {
30            let mut value = [0.0_f32; N];
31            value.copy_from_slice(chunk);
32            value
33        })
34        .collect()
35}
36
37#[derive(Debug, Clone)]
38/// Wraps the corresponding Model I/O animated value counterpart.
39pub struct AnimatedValue {
40    handle: ObjectHandle,
41}
42
43impl AnimatedValue {
44    /// Builds this wrapper from the retained handle of the wrapped Model I/O animated value counterpart.
45    pub(crate) fn from_handle(handle: ObjectHandle) -> Self {
46        Self { handle }
47    }
48
49    /// Calls the corresponding Model I/O method on the wrapped Model I/O animated value counterpart.
50    pub fn info(&self) -> Result<AnimatedValueInfo> {
51        animated_info(&self.handle, "MDLAnimatedValue")
52    }
53
54    /// Calls the corresponding Model I/O method on the wrapped Model I/O animated value counterpart.
55    pub fn clear(&self) {
56        animated_clear(&self.handle);
57    }
58
59    /// Calls the corresponding Model I/O method on the wrapped Model I/O animated value counterpart.
60    pub fn set_interpolation(&self, interpolation: AnimatedValueInterpolation) {
61        animated_set_interpolation(&self.handle, interpolation);
62    }
63}
64
65#[derive(Debug, Clone)]
66/// Wraps the corresponding Model I/O animated scalar counterpart.
67pub struct AnimatedScalar {
68    handle: ObjectHandle,
69}
70
71impl AnimatedScalar {
72    /// Builds this wrapper from the retained handle of the wrapped Model I/O animated scalar counterpart.
73    pub(crate) fn from_handle(handle: ObjectHandle) -> Self {
74        Self { handle }
75    }
76
77    /// Wraps the corresponding Model I/O initializer for the wrapped Model I/O animated scalar counterpart.
78    pub fn new() -> Result<Self> {
79        let mut out_value = ptr::null_mut();
80        let mut out_error = ptr::null_mut();
81        // SAFETY: Output pointers are initialized and managed; FFI function is called safely.
82        let status = unsafe { ffi::mdl_animated_scalar_new(&mut out_value, &mut out_error) };
83        crate::util::status_result(status, out_error)?;
84        Ok(Self::from_handle(required_handle(
85            out_value,
86            "MDLAnimatedScalar",
87        )?))
88    }
89
90    /// Calls the corresponding Model I/O method on the wrapped Model I/O animated scalar counterpart.
91    pub fn info(&self) -> Result<AnimatedValueInfo> {
92        animated_info(&self.handle, "MDLAnimatedScalar")
93    }
94
95    /// Calls the corresponding Model I/O method on the wrapped Model I/O animated scalar counterpart.
96    pub fn clear(&self) {
97        animated_clear(&self.handle);
98    }
99
100    /// Calls the corresponding Model I/O method on the wrapped Model I/O animated scalar counterpart.
101    pub fn set_interpolation(&self, interpolation: AnimatedValueInterpolation) {
102        animated_set_interpolation(&self.handle, interpolation);
103    }
104
105    /// Calls the corresponding Model I/O method on the wrapped Model I/O animated scalar counterpart.
106    pub fn set_float(&self, value: f32, time: f64) {
107        // SAFETY: ObjectHandle wraps a valid opaque pointer from Swift; FFI function accepts it safely.
108        unsafe { ffi::mdl_animated_scalar_set_float(self.handle.as_ptr(), value, time) };
109    }
110
111    #[must_use]
112    /// Calls the corresponding Model I/O method on the wrapped Model I/O animated scalar counterpart.
113    pub fn float_value(&self, time: f64) -> f32 {
114        // SAFETY: ObjectHandle wraps a valid opaque pointer from Swift; FFI function accepts it safely.
115        unsafe { ffi::mdl_animated_scalar_float_value(self.handle.as_ptr(), time) }
116    }
117}
118
119#[derive(Debug, Clone)]
120/// Wraps the corresponding Model I/O animated vector2 counterpart.
121pub struct AnimatedVector2 {
122    handle: ObjectHandle,
123}
124
125impl AnimatedVector2 {
126    /// Builds this wrapper from the retained handle of the wrapped Model I/O animated vector2 counterpart.
127    pub(crate) fn from_handle(handle: ObjectHandle) -> Self {
128        Self { handle }
129    }
130
131    /// Wraps the corresponding Model I/O initializer for the wrapped Model I/O animated vector2 counterpart.
132    pub fn new() -> Result<Self> {
133        let mut out_value = ptr::null_mut();
134        let mut out_error = ptr::null_mut();
135        // SAFETY: Output pointers are initialized and managed; FFI function is called safely.
136        let status = unsafe { ffi::mdl_animated_vector2_new(&mut out_value, &mut out_error) };
137        crate::util::status_result(status, out_error)?;
138        Ok(Self::from_handle(required_handle(
139            out_value,
140            "MDLAnimatedVector2",
141        )?))
142    }
143
144    /// Calls the corresponding Model I/O method on the wrapped Model I/O animated vector2 counterpart.
145    pub fn info(&self) -> Result<AnimatedValueInfo> {
146        animated_info(&self.handle, "MDLAnimatedVector2")
147    }
148
149    /// Calls the corresponding Model I/O method on the wrapped Model I/O animated vector2 counterpart.
150    pub fn clear(&self) {
151        animated_clear(&self.handle);
152    }
153
154    /// Calls the corresponding Model I/O method on the wrapped Model I/O animated vector2 counterpart.
155    pub fn set_interpolation(&self, interpolation: AnimatedValueInterpolation) {
156        animated_set_interpolation(&self.handle, interpolation);
157    }
158
159    /// Calls the corresponding Model I/O method on the wrapped Model I/O animated vector2 counterpart.
160    pub fn set_float2(&self, value: [f32; 2], time: f64) {
161        // SAFETY: The unsafe operation is valid in this context.
162        unsafe {
163            ffi::mdl_animated_vector2_set_float2(self.handle.as_ptr(), value[0], value[1], time);
164        };
165    }
166
167    #[must_use]
168    /// Calls the corresponding Model I/O method on the wrapped Model I/O animated vector2 counterpart.
169    pub fn float2_value(&self, time: f64) -> [f32; 2] {
170        let mut value = [0.0_f32; 2];
171        // SAFETY: The unsafe operation is valid in this context.
172        unsafe {
173            ffi::mdl_animated_vector2_copy_float2_value(
174                self.handle.as_ptr(),
175                time,
176                &mut value[0],
177                &mut value[1],
178            );
179        };
180        value
181    }
182}
183
184#[derive(Debug, Clone)]
185/// Wraps the corresponding Model I/O animated vector3 counterpart.
186pub struct AnimatedVector3 {
187    handle: ObjectHandle,
188}
189
190impl AnimatedVector3 {
191    /// Builds this wrapper from the retained handle of the wrapped Model I/O animated vector3 counterpart.
192    pub(crate) fn from_handle(handle: ObjectHandle) -> Self {
193        Self { handle }
194    }
195
196    /// Wraps the corresponding Model I/O initializer for the wrapped Model I/O animated vector3 counterpart.
197    pub fn new() -> Result<Self> {
198        let mut out_value = ptr::null_mut();
199        let mut out_error = ptr::null_mut();
200        // SAFETY: Output pointers are initialized and managed; FFI function is called safely.
201        let status = unsafe { ffi::mdl_animated_vector3_new(&mut out_value, &mut out_error) };
202        crate::util::status_result(status, out_error)?;
203        Ok(Self::from_handle(required_handle(
204            out_value,
205            "MDLAnimatedVector3",
206        )?))
207    }
208
209    /// Calls the corresponding Model I/O method on the wrapped Model I/O animated vector3 counterpart.
210    pub fn info(&self) -> Result<AnimatedValueInfo> {
211        animated_info(&self.handle, "MDLAnimatedVector3")
212    }
213
214    /// Calls the corresponding Model I/O method on the wrapped Model I/O animated vector3 counterpart.
215    pub fn clear(&self) {
216        animated_clear(&self.handle);
217    }
218
219    /// Calls the corresponding Model I/O method on the wrapped Model I/O animated vector3 counterpart.
220    pub fn set_interpolation(&self, interpolation: AnimatedValueInterpolation) {
221        animated_set_interpolation(&self.handle, interpolation);
222    }
223
224    /// Calls the corresponding Model I/O method on the wrapped Model I/O animated vector3 counterpart.
225    pub fn set_float3(&self, value: [f32; 3], time: f64) {
226        // SAFETY: The unsafe operation is valid in this context.
227        unsafe {
228            ffi::mdl_animated_vector3_set_float3(
229                self.handle.as_ptr(),
230                value[0],
231                value[1],
232                value[2],
233                time,
234            );
235        };
236    }
237
238    #[must_use]
239    /// Calls the corresponding Model I/O method on the wrapped Model I/O animated vector3 counterpart.
240    pub fn float3_value(&self, time: f64) -> [f32; 3] {
241        let mut value = [0.0_f32; 3];
242        // SAFETY: The unsafe operation is valid in this context.
243        unsafe {
244            ffi::mdl_animated_vector3_copy_float3_value(
245                self.handle.as_ptr(),
246                time,
247                &mut value[0],
248                &mut value[1],
249                &mut value[2],
250            );
251        };
252        value
253    }
254}
255
256#[derive(Debug, Clone)]
257/// Wraps the corresponding Model I/O animated vector4 counterpart.
258pub struct AnimatedVector4 {
259    handle: ObjectHandle,
260}
261
262impl AnimatedVector4 {
263    /// Builds this wrapper from the retained handle of the wrapped Model I/O animated vector4 counterpart.
264    pub(crate) fn from_handle(handle: ObjectHandle) -> Self {
265        Self { handle }
266    }
267
268    /// Wraps the corresponding Model I/O initializer for the wrapped Model I/O animated vector4 counterpart.
269    pub fn new() -> Result<Self> {
270        let mut out_value = ptr::null_mut();
271        let mut out_error = ptr::null_mut();
272        // SAFETY: Output pointers are initialized and managed; FFI function is called safely.
273        let status = unsafe { ffi::mdl_animated_vector4_new(&mut out_value, &mut out_error) };
274        crate::util::status_result(status, out_error)?;
275        Ok(Self::from_handle(required_handle(
276            out_value,
277            "MDLAnimatedVector4",
278        )?))
279    }
280
281    /// Calls the corresponding Model I/O method on the wrapped Model I/O animated vector4 counterpart.
282    pub fn info(&self) -> Result<AnimatedValueInfo> {
283        animated_info(&self.handle, "MDLAnimatedVector4")
284    }
285
286    /// Calls the corresponding Model I/O method on the wrapped Model I/O animated vector4 counterpart.
287    pub fn clear(&self) {
288        animated_clear(&self.handle);
289    }
290
291    /// Calls the corresponding Model I/O method on the wrapped Model I/O animated vector4 counterpart.
292    pub fn set_interpolation(&self, interpolation: AnimatedValueInterpolation) {
293        animated_set_interpolation(&self.handle, interpolation);
294    }
295
296    /// Calls the corresponding Model I/O method on the wrapped Model I/O animated vector4 counterpart.
297    pub fn set_float4(&self, value: [f32; 4], time: f64) {
298        // SAFETY: The unsafe operation is valid in this context.
299        unsafe {
300            ffi::mdl_animated_vector4_set_float4(
301                self.handle.as_ptr(),
302                value[0],
303                value[1],
304                value[2],
305                value[3],
306                time,
307            );
308        };
309    }
310
311    #[must_use]
312    /// Calls the corresponding Model I/O method on the wrapped Model I/O animated vector4 counterpart.
313    pub fn float4_value(&self, time: f64) -> [f32; 4] {
314        let mut value = [0.0_f32; 4];
315        // SAFETY: The unsafe operation is valid in this context.
316        unsafe {
317            ffi::mdl_animated_vector4_copy_float4_value(
318                self.handle.as_ptr(),
319                time,
320                &mut value[0],
321                &mut value[1],
322                &mut value[2],
323                &mut value[3],
324            );
325        };
326        value
327    }
328}
329
330#[derive(Debug, Clone)]
331/// Wraps the corresponding Model I/O animated quaternion counterpart.
332pub struct AnimatedQuaternion {
333    handle: ObjectHandle,
334}
335
336impl AnimatedQuaternion {
337    /// Builds this wrapper from the retained handle of the wrapped Model I/O animated quaternion counterpart.
338    pub(crate) fn from_handle(handle: ObjectHandle) -> Self {
339        Self { handle }
340    }
341
342    /// Wraps the corresponding Model I/O initializer for the wrapped Model I/O animated quaternion counterpart.
343    pub fn new() -> Result<Self> {
344        let mut out_value = ptr::null_mut();
345        let mut out_error = ptr::null_mut();
346        // SAFETY: Output pointers are initialized and managed; FFI function is called safely.
347        let status = unsafe { ffi::mdl_animated_quaternion_new(&mut out_value, &mut out_error) };
348        crate::util::status_result(status, out_error)?;
349        Ok(Self::from_handle(required_handle(
350            out_value,
351            "MDLAnimatedQuaternion",
352        )?))
353    }
354
355    /// Calls the corresponding Model I/O method on the wrapped Model I/O animated quaternion counterpart.
356    pub fn info(&self) -> Result<AnimatedValueInfo> {
357        animated_info(&self.handle, "MDLAnimatedQuaternion")
358    }
359
360    /// Calls the corresponding Model I/O method on the wrapped Model I/O animated quaternion counterpart.
361    pub fn clear(&self) {
362        animated_clear(&self.handle);
363    }
364
365    /// Calls the corresponding Model I/O method on the wrapped Model I/O animated quaternion counterpart.
366    pub fn set_interpolation(&self, interpolation: AnimatedValueInterpolation) {
367        animated_set_interpolation(&self.handle, interpolation);
368    }
369
370    /// Calls the corresponding Model I/O method on the wrapped Model I/O animated quaternion counterpart.
371    pub fn set_float_quaternion(&self, value: [f32; 4], time: f64) {
372        // SAFETY: The unsafe operation is valid in this context.
373        unsafe {
374            ffi::mdl_animated_quaternion_set_float(
375                self.handle.as_ptr(),
376                value[0],
377                value[1],
378                value[2],
379                value[3],
380                time,
381            );
382        };
383    }
384
385    #[must_use]
386    /// Calls the corresponding Model I/O method on the wrapped Model I/O animated quaternion counterpart.
387    pub fn float_quaternion_value(&self, time: f64) -> [f32; 4] {
388        let mut raw = [0.0_f32; 4];
389        // SAFETY: The unsafe operation is valid in this context.
390        unsafe {
391            ffi::mdl_animated_quaternion_copy_float_value(
392                self.handle.as_ptr(),
393                time,
394                raw.as_mut_ptr(),
395            );
396        };
397        raw
398    }
399}
400
401#[derive(Debug, Clone)]
402/// Wraps the corresponding Model I/O animated matrix4x4 counterpart.
403pub struct AnimatedMatrix4x4 {
404    handle: ObjectHandle,
405}
406
407impl AnimatedMatrix4x4 {
408    /// Builds this wrapper from the retained handle of the wrapped Model I/O animated matrix4x4 counterpart.
409    pub(crate) fn from_handle(handle: ObjectHandle) -> Self {
410        Self { handle }
411    }
412
413    /// Wraps the corresponding Model I/O initializer for the wrapped Model I/O animated matrix4x4 counterpart.
414    pub fn new() -> Result<Self> {
415        let mut out_value = ptr::null_mut();
416        let mut out_error = ptr::null_mut();
417        // SAFETY: Output pointers are initialized and managed; FFI function is called safely.
418        let status = unsafe { ffi::mdl_animated_matrix4x4_new(&mut out_value, &mut out_error) };
419        crate::util::status_result(status, out_error)?;
420        Ok(Self::from_handle(required_handle(
421            out_value,
422            "MDLAnimatedMatrix4x4",
423        )?))
424    }
425
426    /// Calls the corresponding Model I/O method on the wrapped Model I/O animated matrix4x4 counterpart.
427    pub fn info(&self) -> Result<AnimatedValueInfo> {
428        animated_info(&self.handle, "MDLAnimatedMatrix4x4")
429    }
430
431    /// Calls the corresponding Model I/O method on the wrapped Model I/O animated matrix4x4 counterpart.
432    pub fn clear(&self) {
433        animated_clear(&self.handle);
434    }
435
436    /// Calls the corresponding Model I/O method on the wrapped Model I/O animated matrix4x4 counterpart.
437    pub fn set_interpolation(&self, interpolation: AnimatedValueInterpolation) {
438        animated_set_interpolation(&self.handle, interpolation);
439    }
440
441    /// Calls the corresponding Model I/O method on the wrapped Model I/O animated matrix4x4 counterpart.
442    pub fn set_float4x4(&self, value: [f32; 16], time: f64) {
443        // SAFETY: The unsafe operation is valid in this context.
444        unsafe {
445            ffi::mdl_animated_matrix4x4_set_float(self.handle.as_ptr(), value.as_ptr(), time);
446        };
447    }
448
449    #[must_use]
450    /// Calls the corresponding Model I/O method on the wrapped Model I/O animated matrix4x4 counterpart.
451    pub fn float4x4_value(&self, time: f64) -> [f32; 16] {
452        let mut raw = [0.0_f32; 16];
453        // SAFETY: The unsafe operation is valid in this context.
454        unsafe {
455            ffi::mdl_animated_matrix4x4_copy_float_value(
456                self.handle.as_ptr(),
457                time,
458                raw.as_mut_ptr(),
459            );
460        };
461        raw
462    }
463}
464
465#[derive(Debug, Clone)]
466/// Wraps the corresponding Model I/O animated scalar array counterpart.
467pub struct AnimatedScalarArray {
468    handle: ObjectHandle,
469}
470
471impl AnimatedScalarArray {
472    /// Builds this wrapper from the retained handle of the wrapped Model I/O animated scalar array counterpart.
473    pub(crate) fn from_handle(handle: ObjectHandle) -> Self {
474        Self { handle }
475    }
476
477    /// Wraps the corresponding Model I/O initializer for the wrapped Model I/O animated scalar array counterpart.
478    pub fn new(element_count: usize) -> Result<Self> {
479        let mut out_value = ptr::null_mut();
480        let mut out_error = ptr::null_mut();
481        // SAFETY: The unsafe operation is valid in this context.
482        let status = unsafe {
483            ffi::mdl_animated_scalar_array_new(element_count as u64, &mut out_value, &mut out_error)
484        };
485        crate::util::status_result(status, out_error)?;
486        Ok(Self::from_handle(required_handle(
487            out_value,
488            "MDLAnimatedScalarArray",
489        )?))
490    }
491
492    /// Calls the corresponding Model I/O method on the wrapped Model I/O animated scalar array counterpart.
493    pub fn info(&self) -> Result<AnimatedValueInfo> {
494        animated_info(&self.handle, "MDLAnimatedScalarArray")
495    }
496
497    /// Calls the corresponding Model I/O method on the wrapped Model I/O animated scalar array counterpart.
498    pub fn clear(&self) {
499        animated_clear(&self.handle);
500    }
501
502    /// Calls the corresponding Model I/O method on the wrapped Model I/O animated scalar array counterpart.
503    pub fn set_interpolation(&self, interpolation: AnimatedValueInterpolation) {
504        animated_set_interpolation(&self.handle, interpolation);
505    }
506
507    /// Calls the corresponding Model I/O method on the wrapped Model I/O animated scalar array counterpart.
508    pub fn set_float_array(&self, values: &[f32], time: f64) {
509        // SAFETY: The unsafe operation is valid in this context.
510        unsafe {
511            ffi::mdl_animated_scalar_array_set_float(
512                self.handle.as_ptr(),
513                values.as_ptr(),
514                values.len() as u64,
515                time,
516            );
517        };
518    }
519
520    /// Calls the corresponding Model I/O method on the wrapped Model I/O animated scalar array counterpart.
521    pub fn float_array_at_time(&self, time: f64) -> Result<Vec<f32>> {
522        let element_count = self.info()?.element_count.unwrap_or(0);
523        if element_count == 0 {
524            return Ok(Vec::new());
525        }
526        let mut values = vec![0.0_f32; element_count];
527        // SAFETY: The unsafe operation is valid in this context.
528        let written = unsafe {
529            ffi::mdl_animated_scalar_array_copy_float_at_time(
530                self.handle.as_ptr(),
531                time,
532                values.as_mut_ptr(),
533                element_count as u64,
534            )
535        } as usize;
536        values.truncate(written);
537        Ok(values)
538    }
539}
540
541#[derive(Debug, Clone)]
542/// Wraps the corresponding Model I/O animated vector3array counterpart.
543pub struct AnimatedVector3Array {
544    handle: ObjectHandle,
545}
546
547impl AnimatedVector3Array {
548    /// Builds this wrapper from the retained handle of the wrapped Model I/O animated vector3array counterpart.
549    pub(crate) fn from_handle(handle: ObjectHandle) -> Self {
550        Self { handle }
551    }
552
553    /// Wraps the corresponding Model I/O initializer for the wrapped Model I/O animated vector3array counterpart.
554    pub fn new(element_count: usize) -> Result<Self> {
555        let mut out_value = ptr::null_mut();
556        let mut out_error = ptr::null_mut();
557        // SAFETY: The unsafe operation is valid in this context.
558        let status = unsafe {
559            ffi::mdl_animated_vector3_array_new(
560                element_count as u64,
561                &mut out_value,
562                &mut out_error,
563            )
564        };
565        crate::util::status_result(status, out_error)?;
566        Ok(Self::from_handle(required_handle(
567            out_value,
568            "MDLAnimatedVector3Array",
569        )?))
570    }
571
572    /// Calls the corresponding Model I/O method on the wrapped Model I/O animated vector3array counterpart.
573    pub fn info(&self) -> Result<AnimatedValueInfo> {
574        animated_info(&self.handle, "MDLAnimatedVector3Array")
575    }
576
577    /// Calls the corresponding Model I/O method on the wrapped Model I/O animated vector3array counterpart.
578    pub fn clear(&self) {
579        animated_clear(&self.handle);
580    }
581
582    /// Calls the corresponding Model I/O method on the wrapped Model I/O animated vector3array counterpart.
583    pub fn set_interpolation(&self, interpolation: AnimatedValueInterpolation) {
584        animated_set_interpolation(&self.handle, interpolation);
585    }
586
587    /// Calls the corresponding Model I/O method on the wrapped Model I/O animated vector3array counterpart.
588    pub fn set_float3_array(&self, values: &[[f32; 3]], time: f64) {
589        let flattened = values
590            .iter()
591            .flat_map(|value| value.iter().copied())
592            .collect::<Vec<_>>();
593        // SAFETY: The unsafe operation is valid in this context.
594        unsafe {
595            ffi::mdl_animated_vector3_array_set_float(
596                self.handle.as_ptr(),
597                flattened.as_ptr(),
598                values.len() as u64,
599                time,
600            );
601        };
602    }
603
604    /// Calls the corresponding Model I/O method on the wrapped Model I/O animated vector3array counterpart.
605    pub fn float3_array_at_time(&self, time: f64) -> Result<Vec<[f32; 3]>> {
606        let element_count = self.info()?.element_count.unwrap_or(0);
607        if element_count == 0 {
608            return Ok(Vec::new());
609        }
610        let mut values = vec![0.0_f32; element_count * 3];
611        // SAFETY: The unsafe operation is valid in this context.
612        let written = unsafe {
613            ffi::mdl_animated_vector3_array_copy_float_at_time(
614                self.handle.as_ptr(),
615                time,
616                values.as_mut_ptr(),
617                element_count as u64,
618            )
619        } as usize;
620        values.truncate(written * 3);
621        Ok(convert_vectors::<3>(&values))
622    }
623}
624
625#[derive(Debug, Clone)]
626/// Wraps the corresponding Model I/O animated quaternion array counterpart.
627pub struct AnimatedQuaternionArray {
628    handle: ObjectHandle,
629}
630
631impl AnimatedQuaternionArray {
632    /// Builds this wrapper from the retained handle of the wrapped Model I/O animated quaternion array counterpart.
633    pub(crate) fn from_handle(handle: ObjectHandle) -> Self {
634        Self { handle }
635    }
636
637    /// Wraps the corresponding Model I/O initializer for the wrapped Model I/O animated quaternion array counterpart.
638    pub fn new(element_count: usize) -> Result<Self> {
639        let mut out_value = ptr::null_mut();
640        let mut out_error = ptr::null_mut();
641        // SAFETY: The unsafe operation is valid in this context.
642        let status = unsafe {
643            ffi::mdl_animated_quaternion_array_new(
644                element_count as u64,
645                &mut out_value,
646                &mut out_error,
647            )
648        };
649        crate::util::status_result(status, out_error)?;
650        Ok(Self::from_handle(required_handle(
651            out_value,
652            "MDLAnimatedQuaternionArray",
653        )?))
654    }
655
656    /// Calls the corresponding Model I/O method on the wrapped Model I/O animated quaternion array counterpart.
657    pub fn info(&self) -> Result<AnimatedValueInfo> {
658        animated_info(&self.handle, "MDLAnimatedQuaternionArray")
659    }
660
661    /// Calls the corresponding Model I/O method on the wrapped Model I/O animated quaternion array counterpart.
662    pub fn clear(&self) {
663        animated_clear(&self.handle);
664    }
665
666    /// Calls the corresponding Model I/O method on the wrapped Model I/O animated quaternion array counterpart.
667    pub fn set_interpolation(&self, interpolation: AnimatedValueInterpolation) {
668        animated_set_interpolation(&self.handle, interpolation);
669    }
670
671    /// Calls the corresponding Model I/O method on the wrapped Model I/O animated quaternion array counterpart.
672    pub fn set_float_quaternion_array(&self, values: &[[f32; 4]], time: f64) {
673        let flattened = values
674            .iter()
675            .flat_map(|value| value.iter().copied())
676            .collect::<Vec<_>>();
677        // SAFETY: The unsafe operation is valid in this context.
678        unsafe {
679            ffi::mdl_animated_quaternion_array_set_float(
680                self.handle.as_ptr(),
681                flattened.as_ptr(),
682                values.len() as u64,
683                time,
684            );
685        };
686    }
687
688    /// Calls the corresponding Model I/O method on the wrapped Model I/O animated quaternion array counterpart.
689    pub fn float_quaternion_array_at_time(&self, time: f64) -> Result<Vec<[f32; 4]>> {
690        let element_count = self.info()?.element_count.unwrap_or(0);
691        if element_count == 0 {
692            return Ok(Vec::new());
693        }
694        let mut values = vec![0.0_f32; element_count * 4];
695        // SAFETY: The unsafe operation is valid in this context.
696        let written = unsafe {
697            ffi::mdl_animated_quaternion_array_copy_float_at_time(
698                self.handle.as_ptr(),
699                time,
700                values.as_mut_ptr(),
701                element_count as u64,
702            )
703        } as usize;
704        values.truncate(written * 4);
705        Ok(convert_vectors::<4>(&values))
706    }
707}