Skip to main content

modelio/
submesh.rs

1use crate::error::Result;
2use crate::ffi;
3use crate::handle::ObjectHandle;
4use crate::material::Material;
5use crate::mesh::MeshBuffer;
6use crate::protocols::Named;
7use crate::types::{GeometryType, IndexBitDepth};
8use crate::util::{c_string, take_string};
9
10#[derive(Debug, Clone)]
11/// Wraps the corresponding Model I/O submesh counterpart.
12pub struct Submesh {
13    handle: ObjectHandle,
14}
15
16impl Named for Submesh {
17    fn name(&self) -> Option<String> {
18        self.name()
19    }
20
21    fn set_name(&self, name: &str) -> Result<()> {
22        self.set_name(name)
23    }
24}
25
26impl Submesh {
27    /// Builds this wrapper from the retained handle of the wrapped Model I/O submesh counterpart.
28    pub(crate) fn from_handle(handle: ObjectHandle) -> Self {
29        Self { handle }
30    }
31
32    /// Returns the opaque pointer used to call the wrapped Model I/O submesh counterpart.
33    pub(crate) fn as_ptr(&self) -> *mut core::ffi::c_void {
34        self.handle.as_ptr()
35    }
36
37    #[must_use]
38    /// Calls the corresponding Model I/O method on the wrapped Model I/O submesh counterpart.
39    pub fn name(&self) -> Option<String> {
40        // SAFETY: ObjectHandle wraps a valid opaque pointer from Swift; FFI function accepts it safely.
41        take_string(unsafe { ffi::mdl_submesh_name_string(self.handle.as_ptr()) })
42    }
43
44    /// Calls the corresponding Model I/O method on the wrapped Model I/O submesh counterpart.
45    pub fn set_name(&self, name: &str) -> Result<()> {
46        let name = c_string(name)?;
47        // SAFETY: ObjectHandle wraps a valid opaque pointer from Swift; FFI function accepts it safely.
48        unsafe { ffi::mdl_submesh_set_name(self.handle.as_ptr(), name.as_ptr()) };
49        Ok(())
50    }
51
52    #[must_use]
53    /// Calls the corresponding Model I/O method on the wrapped Model I/O submesh counterpart.
54    pub fn index_count(&self) -> usize {
55        // SAFETY: ObjectHandle wraps a valid opaque pointer from Swift; FFI function accepts it safely.
56        unsafe { ffi::mdl_submesh_index_count(self.handle.as_ptr()) as usize }
57    }
58
59    #[must_use]
60    /// Calls the corresponding Model I/O method on the wrapped Model I/O submesh counterpart.
61    pub fn index_type(&self) -> Option<IndexBitDepth> {
62        // SAFETY: ObjectHandle wraps a valid opaque pointer from Swift; FFI function accepts it safely.
63        IndexBitDepth::from_raw(unsafe { ffi::mdl_submesh_index_type(self.handle.as_ptr()) })
64    }
65
66    #[must_use]
67    /// Calls the corresponding Model I/O method on the wrapped Model I/O submesh counterpart.
68    pub fn geometry_type(&self) -> Option<GeometryType> {
69        // SAFETY: ObjectHandle wraps a valid opaque pointer from Swift; FFI function accepts it safely.
70        GeometryType::from_raw(unsafe { ffi::mdl_submesh_geometry_type(self.handle.as_ptr()) })
71    }
72
73    #[must_use]
74    /// Calls the corresponding Model I/O method on the wrapped Model I/O submesh counterpart.
75    pub fn index_buffer(&self) -> Option<MeshBuffer> {
76        // SAFETY: ObjectHandle wraps a valid opaque pointer from Swift; FFI function accepts it safely.
77        let ptr = unsafe { ffi::mdl_submesh_index_buffer(self.handle.as_ptr()) };
78        // SAFETY: The unsafe operation is valid in this context.
79        unsafe { ObjectHandle::from_retained_ptr(ptr) }.map(MeshBuffer::from_handle)
80    }
81
82    #[must_use]
83    /// Calls the corresponding Model I/O method on the wrapped Model I/O submesh counterpart.
84    pub fn index_buffer_as_type(&self, index_type: IndexBitDepth) -> Option<MeshBuffer> {
85        // SAFETY: The unsafe operation is valid in this context.
86        let ptr = unsafe {
87            ffi::mdl_submesh_index_buffer_as_type(self.handle.as_ptr(), index_type.as_raw())
88        };
89        // SAFETY: The unsafe operation is valid in this context.
90        unsafe { ObjectHandle::from_retained_ptr(ptr) }.map(MeshBuffer::from_handle)
91    }
92
93    #[must_use]
94    /// Calls the corresponding Model I/O method on the wrapped Model I/O submesh counterpart.
95    pub fn material(&self) -> Option<Material> {
96        // SAFETY: ObjectHandle wraps a valid opaque pointer from Swift; FFI function accepts it safely.
97        let ptr = unsafe { ffi::mdl_submesh_material(self.handle.as_ptr()) };
98        // SAFETY: The unsafe operation is valid in this context.
99        unsafe { ObjectHandle::from_retained_ptr(ptr) }.map(Material::from_handle)
100    }
101
102    #[must_use]
103    /// Calls the corresponding Model I/O method on the wrapped Model I/O submesh counterpart.
104    pub fn topology(&self) -> Option<SubmeshTopology> {
105        // SAFETY: ObjectHandle wraps a valid opaque pointer from Swift; FFI function accepts it safely.
106        let ptr = unsafe { ffi::mdl_submesh_topology(self.handle.as_ptr()) };
107        // SAFETY: The unsafe operation is valid in this context.
108        unsafe { ObjectHandle::from_retained_ptr(ptr) }.map(SubmeshTopology::from_handle)
109    }
110
111    /// Calls the corresponding Model I/O method on the wrapped Model I/O submesh counterpart.
112    pub fn set_topology(&self, topology: Option<&SubmeshTopology>) {
113        // SAFETY: The unsafe operation is valid in this context.
114        unsafe {
115            ffi::mdl_submesh_set_topology(
116                self.handle.as_ptr(),
117                topology.map_or(std::ptr::null_mut(), SubmeshTopology::as_ptr),
118            );
119        };
120    }
121
122    /// Calls the corresponding Model I/O method on the wrapped Model I/O submesh counterpart.
123    pub fn set_material(&self, material: Option<&Material>) {
124        // SAFETY: The unsafe operation is valid in this context.
125        unsafe {
126            ffi::mdl_submesh_set_material(
127                self.handle.as_ptr(),
128                material.map_or(std::ptr::null_mut(), Material::as_ptr),
129            );
130        };
131    }
132}
133
134#[derive(Debug, Clone)]
135/// Wraps the corresponding Model I/O submesh topology counterpart.
136pub struct SubmeshTopology {
137    handle: ObjectHandle,
138}
139
140impl SubmeshTopology {
141    /// Builds this wrapper from the retained handle of the wrapped Model I/O submesh topology counterpart.
142    pub(crate) fn from_handle(handle: ObjectHandle) -> Self {
143        Self { handle }
144    }
145
146    /// Returns the opaque pointer used to call the wrapped Model I/O submesh topology counterpart.
147    pub(crate) fn as_ptr(&self) -> *mut core::ffi::c_void {
148        self.handle.as_ptr()
149    }
150
151    /// Wraps the corresponding Model I/O initializer for the wrapped Model I/O submesh topology counterpart.
152    pub fn new(submesh: &Submesh) -> Result<Self> {
153        let mut out_topology = std::ptr::null_mut();
154        let mut out_error = std::ptr::null_mut();
155        // SAFETY: The unsafe operation is valid in this context.
156        let status = unsafe {
157            ffi::mdl_submesh_topology_new(submesh.as_ptr(), &mut out_topology, &mut out_error)
158        };
159        crate::util::status_result(status, out_error)?;
160        Ok(Self::from_handle(crate::util::required_handle(
161            out_topology,
162            "MDLSubmeshTopology",
163        )?))
164    }
165
166    #[must_use]
167    /// Calls the corresponding Model I/O method on the wrapped Model I/O submesh topology counterpart.
168    pub fn face_topology(&self) -> Option<MeshBuffer> {
169        // SAFETY: ObjectHandle wraps a valid opaque pointer from Swift; FFI function accepts it safely.
170        let ptr = unsafe { ffi::mdl_submesh_topology_face_topology(self.handle.as_ptr()) };
171        // SAFETY: The unsafe operation is valid in this context.
172        unsafe { ObjectHandle::from_retained_ptr(ptr) }.map(MeshBuffer::from_handle)
173    }
174
175    /// Calls the corresponding Model I/O method on the wrapped Model I/O submesh topology counterpart.
176    pub fn set_face_topology(&self, buffer: Option<&MeshBuffer>) {
177        // SAFETY: The unsafe operation is valid in this context.
178        unsafe {
179            ffi::mdl_submesh_topology_set_face_topology(
180                self.handle.as_ptr(),
181                buffer.map_or(std::ptr::null_mut(), MeshBuffer::as_ptr),
182            );
183        };
184    }
185
186    #[must_use]
187    /// Calls the corresponding Model I/O method on the wrapped Model I/O submesh topology counterpart.
188    pub fn face_count(&self) -> usize {
189        // SAFETY: ObjectHandle wraps a valid opaque pointer from Swift; FFI function accepts it safely.
190        unsafe { ffi::mdl_submesh_topology_face_count(self.handle.as_ptr()) as usize }
191    }
192
193    /// Calls the corresponding Model I/O method on the wrapped Model I/O submesh topology counterpart.
194    pub fn set_face_count(&self, count: usize) {
195        // SAFETY: ObjectHandle wraps a valid opaque pointer from Swift; FFI function accepts it safely.
196        unsafe { ffi::mdl_submesh_topology_set_face_count(self.handle.as_ptr(), count as u64) };
197    }
198
199    #[must_use]
200    /// Calls the corresponding Model I/O method on the wrapped Model I/O submesh topology counterpart.
201    pub fn vertex_crease_indices(&self) -> Option<MeshBuffer> {
202        // SAFETY: ObjectHandle wraps a valid opaque pointer from Swift; FFI function accepts it safely.
203        let ptr = unsafe { ffi::mdl_submesh_topology_vertex_crease_indices(self.handle.as_ptr()) };
204        // SAFETY: The unsafe operation is valid in this context.
205        unsafe { ObjectHandle::from_retained_ptr(ptr) }.map(MeshBuffer::from_handle)
206    }
207
208    /// Calls the corresponding Model I/O method on the wrapped Model I/O submesh topology counterpart.
209    pub fn set_vertex_crease_indices(&self, buffer: Option<&MeshBuffer>) {
210        // SAFETY: The unsafe operation is valid in this context.
211        unsafe {
212            ffi::mdl_submesh_topology_set_vertex_crease_indices(
213                self.handle.as_ptr(),
214                buffer.map_or(std::ptr::null_mut(), MeshBuffer::as_ptr),
215            );
216        };
217    }
218
219    #[must_use]
220    /// Calls the corresponding Model I/O method on the wrapped Model I/O submesh topology counterpart.
221    pub fn vertex_creases(&self) -> Option<MeshBuffer> {
222        // SAFETY: ObjectHandle wraps a valid opaque pointer from Swift; FFI function accepts it safely.
223        let ptr = unsafe { ffi::mdl_submesh_topology_vertex_creases(self.handle.as_ptr()) };
224        // SAFETY: The unsafe operation is valid in this context.
225        unsafe { ObjectHandle::from_retained_ptr(ptr) }.map(MeshBuffer::from_handle)
226    }
227
228    /// Calls the corresponding Model I/O method on the wrapped Model I/O submesh topology counterpart.
229    pub fn set_vertex_creases(&self, buffer: Option<&MeshBuffer>) {
230        // SAFETY: The unsafe operation is valid in this context.
231        unsafe {
232            ffi::mdl_submesh_topology_set_vertex_creases(
233                self.handle.as_ptr(),
234                buffer.map_or(std::ptr::null_mut(), MeshBuffer::as_ptr),
235            );
236        };
237    }
238
239    #[must_use]
240    /// Calls the corresponding Model I/O method on the wrapped Model I/O submesh topology counterpart.
241    pub fn vertex_crease_count(&self) -> usize {
242        // SAFETY: ObjectHandle wraps a valid opaque pointer from Swift; FFI function accepts it safely.
243        unsafe { ffi::mdl_submesh_topology_vertex_crease_count(self.handle.as_ptr()) as usize }
244    }
245
246    /// Calls the corresponding Model I/O method on the wrapped Model I/O submesh topology counterpart.
247    pub fn set_vertex_crease_count(&self, count: usize) {
248        // SAFETY: The unsafe operation is valid in this context.
249        unsafe {
250            ffi::mdl_submesh_topology_set_vertex_crease_count(self.handle.as_ptr(), count as u64);
251        };
252    }
253
254    #[must_use]
255    /// Calls the corresponding Model I/O method on the wrapped Model I/O submesh topology counterpart.
256    pub fn edge_crease_indices(&self) -> Option<MeshBuffer> {
257        // SAFETY: ObjectHandle wraps a valid opaque pointer from Swift; FFI function accepts it safely.
258        let ptr = unsafe { ffi::mdl_submesh_topology_edge_crease_indices(self.handle.as_ptr()) };
259        // SAFETY: The unsafe operation is valid in this context.
260        unsafe { ObjectHandle::from_retained_ptr(ptr) }.map(MeshBuffer::from_handle)
261    }
262
263    /// Calls the corresponding Model I/O method on the wrapped Model I/O submesh topology counterpart.
264    pub fn set_edge_crease_indices(&self, buffer: Option<&MeshBuffer>) {
265        // SAFETY: The unsafe operation is valid in this context.
266        unsafe {
267            ffi::mdl_submesh_topology_set_edge_crease_indices(
268                self.handle.as_ptr(),
269                buffer.map_or(std::ptr::null_mut(), MeshBuffer::as_ptr),
270            );
271        };
272    }
273
274    #[must_use]
275    /// Calls the corresponding Model I/O method on the wrapped Model I/O submesh topology counterpart.
276    pub fn edge_creases(&self) -> Option<MeshBuffer> {
277        // SAFETY: ObjectHandle wraps a valid opaque pointer from Swift; FFI function accepts it safely.
278        let ptr = unsafe { ffi::mdl_submesh_topology_edge_creases(self.handle.as_ptr()) };
279        // SAFETY: The unsafe operation is valid in this context.
280        unsafe { ObjectHandle::from_retained_ptr(ptr) }.map(MeshBuffer::from_handle)
281    }
282
283    /// Calls the corresponding Model I/O method on the wrapped Model I/O submesh topology counterpart.
284    pub fn set_edge_creases(&self, buffer: Option<&MeshBuffer>) {
285        // SAFETY: The unsafe operation is valid in this context.
286        unsafe {
287            ffi::mdl_submesh_topology_set_edge_creases(
288                self.handle.as_ptr(),
289                buffer.map_or(std::ptr::null_mut(), MeshBuffer::as_ptr),
290            );
291        };
292    }
293
294    #[must_use]
295    /// Calls the corresponding Model I/O method on the wrapped Model I/O submesh topology counterpart.
296    pub fn edge_crease_count(&self) -> usize {
297        // SAFETY: ObjectHandle wraps a valid opaque pointer from Swift; FFI function accepts it safely.
298        unsafe { ffi::mdl_submesh_topology_edge_crease_count(self.handle.as_ptr()) as usize }
299    }
300
301    /// Calls the corresponding Model I/O method on the wrapped Model I/O submesh topology counterpart.
302    pub fn set_edge_crease_count(&self, count: usize) {
303        // SAFETY: The unsafe operation is valid in this context.
304        unsafe {
305            ffi::mdl_submesh_topology_set_edge_crease_count(self.handle.as_ptr(), count as u64);
306        };
307    }
308}