Skip to main content

modelio/
value_types.rs

1use std::ptr;
2
3use crate::error::Result;
4use crate::ffi;
5use crate::handle::ObjectHandle;
6use crate::types::Matrix4x4ArrayInfo;
7use crate::util::{parse_json, required_handle};
8
9#[derive(Debug, Clone)]
10/// Wraps the corresponding Model I/O matrix4x4array counterpart.
11pub struct Matrix4x4Array {
12    handle: ObjectHandle,
13}
14
15impl Matrix4x4Array {
16    /// Builds this wrapper from the retained handle of the wrapped Model I/O matrix4x4array counterpart.
17    pub(crate) fn from_handle(handle: ObjectHandle) -> Self {
18        Self { handle }
19    }
20
21    #[allow(dead_code)]
22    /// Returns the opaque pointer used to call the wrapped Model I/O matrix4x4array counterpart.
23    pub(crate) fn as_ptr(&self) -> *mut core::ffi::c_void {
24        self.handle.as_ptr()
25    }
26
27    /// Wraps the corresponding Model I/O initializer for the wrapped Model I/O matrix4x4array counterpart.
28    pub fn new(element_count: usize) -> Result<Self> {
29        let mut out_array = ptr::null_mut();
30        let mut out_error = ptr::null_mut();
31        // SAFETY: The unsafe operation is valid in this context.
32        let status = unsafe {
33            ffi::mdl_matrix4x4_array_new(element_count as u64, &mut out_array, &mut out_error)
34        };
35        crate::util::status_result(status, out_error)?;
36        Ok(Self::from_handle(required_handle(
37            out_array,
38            "MDLMatrix4x4Array",
39        )?))
40    }
41
42    /// Calls the corresponding Model I/O method on the wrapped Model I/O matrix4x4array counterpart.
43    pub fn info(&self) -> Result<Matrix4x4ArrayInfo> {
44        parse_json(
45            // SAFETY: ObjectHandle wraps a valid opaque pointer from Swift; FFI function accepts it safely.
46            unsafe { ffi::mdl_matrix4x4_array_info_json(self.handle.as_ptr()) },
47            "MDLMatrix4x4Array",
48        )
49    }
50
51    /// Calls the corresponding Model I/O method on the wrapped Model I/O matrix4x4array counterpart.
52    pub fn clear(&self) {
53        // SAFETY: ObjectHandle wraps a valid opaque pointer from Swift; FFI function accepts it safely.
54        unsafe { ffi::mdl_matrix4x4_array_clear(self.handle.as_ptr()) };
55    }
56
57    /// Calls the corresponding Model I/O method on the wrapped Model I/O matrix4x4array counterpart.
58    pub fn set_float_matrices(&self, values: &[[f32; 16]]) {
59        let flattened = values
60            .iter()
61            .flat_map(|value| value.iter().copied())
62            .collect::<Vec<_>>();
63        // SAFETY: The unsafe operation is valid in this context.
64        unsafe {
65            ffi::mdl_matrix4x4_array_set_float_matrices(
66                self.handle.as_ptr(),
67                flattened.as_ptr(),
68                values.len() as u64,
69            );
70        };
71    }
72
73    /// Calls the corresponding Model I/O method on the wrapped Model I/O matrix4x4array counterpart.
74    pub fn float_matrices(&self) -> Result<Vec<[f32; 16]>> {
75        let count = self.info()?.element_count;
76        if count == 0 {
77            return Ok(Vec::new());
78        }
79        let mut flattened = vec![0.0_f32; count * 16];
80        // SAFETY: The unsafe operation is valid in this context.
81        let written = unsafe {
82            ffi::mdl_matrix4x4_array_copy_float_matrices(
83                self.handle.as_ptr(),
84                flattened.as_mut_ptr(),
85                count as u64,
86            )
87        } as usize;
88        flattened.truncate(written * 16);
89        Ok(flattened
90            .chunks_exact(16)
91            .map(|chunk| {
92                let mut matrix = [0.0_f32; 16];
93                matrix.copy_from_slice(chunk);
94                matrix
95            })
96            .collect())
97    }
98}