fmod/core/geometry/
general.rs

1// Copyright (c) 2024 Lily Lyons
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at https://mozilla.org/MPL/2.0/.
6
7use fmod_sys::*;
8use std::ffi::{c_float, c_int, c_void};
9
10use crate::{Geometry, Vector};
11
12impl Geometry {
13    /// Adds a polygon.
14    ///
15    /// All vertices must lay in the same plane otherwise behavior may be unpredictable.
16    /// The polygon is assumed to be convex. A non convex polygon will produce unpredictable behavior.
17    /// Polygons with zero area will be ignored.
18    ///
19    /// Polygons cannot be added if already at the maximum number of polygons or if the addition of their verticies would result in exceeding the maximum number of vertices.
20    ///
21    /// Vertices of an object are in object space, not world space, and so are relative to the position, or center of the object.
22    /// See [`Geometry::setP_psition`].
23    pub fn add_polygon(
24        &self,
25        direct_occlusion: c_float,
26        reverb_occlusion: c_float,
27        double_sided: bool,
28        vertices: &[Vector],
29    ) -> Result<c_int> {
30        let mut index = 0;
31        unsafe {
32            FMOD_Geometry_AddPolygon(
33                self.inner,
34                direct_occlusion,
35                reverb_occlusion,
36                double_sided.into(),
37                vertices.len() as c_int,
38                vertices.as_ptr().cast(),
39                &mut index,
40            )
41            .to_result()?;
42        }
43        Ok(index)
44    }
45
46    /// Sets whether an object is processed by the geometry engine.
47    pub fn set_active(&self, active: bool) -> Result<()> {
48        unsafe { FMOD_Geometry_SetActive(self.inner, active.into()).to_result() }
49    }
50
51    /// Retrieves whether an object is processed by the geometry engine.
52    pub fn get_active(&self) -> Result<bool> {
53        let mut active = FMOD_BOOL::FALSE;
54        unsafe {
55            FMOD_Geometry_GetActive(self.inner, &mut active).to_result()?;
56        }
57        Ok(active.into())
58    }
59
60    /// Retrieves the maximum number of polygons and vertices allocatable for this object.
61    ///
62    /// The maximum number was set with [`crate::System::create_geometry`].
63    pub fn get_max_polygons(&self) -> Result<(c_int, c_int)> {
64        let mut max_polygons = 0;
65        let mut max_vertices = 0;
66        unsafe {
67            FMOD_Geometry_GetMaxPolygons(self.inner, &mut max_polygons, &mut max_vertices)
68                .to_result()?;
69        }
70        Ok((max_polygons, max_vertices))
71    }
72
73    /// Retrieves the number of polygons in this object.
74    pub fn get_polygon_count(&self) -> Result<c_int> {
75        let mut count = 0;
76        unsafe {
77            FMOD_Geometry_GetNumPolygons(self.inner, &mut count).to_result()?;
78        }
79        Ok(count)
80    }
81
82    #[allow(clippy::not_unsafe_ptr_arg_deref)] // fmod doesn't dereference the passed in pointer, and the user dereferencing it is unsafe anyway
83    pub fn set_raw_userdata(&self, userdata: *mut c_void) -> Result<()> {
84        unsafe { FMOD_Geometry_SetUserData(self.inner, userdata).to_result() }
85    }
86
87    pub fn get_raw_userdata(&self) -> Result<*mut c_void> {
88        let mut userdata = std::ptr::null_mut();
89        unsafe {
90            FMOD_Geometry_GetUserData(self.inner, &mut userdata).to_result()?;
91        }
92        Ok(userdata)
93    }
94
95    /// Frees a geometry object and releases its memory.
96    pub fn release(&self) -> Result<()> {
97        // release userdata
98        #[cfg(feature = "userdata-abstraction")]
99        let userdata = self.get_raw_userdata()?;
100
101        unsafe {
102            FMOD_Geometry_Release(self.inner).to_result()?;
103        }
104
105        // release/remove userdata if it is not null
106        #[cfg(feature = "userdata-abstraction")]
107        if !userdata.is_null() {
108            crate::userdata::remove_userdata(userdata.into());
109            self.set_raw_userdata(std::ptr::null_mut())?;
110        }
111
112        Ok(())
113    }
114
115    /// Saves the geometry object as a serialized binary block to a [`Vec`].
116    ///
117    /// The data can be saved to a file if required and loaded later with [`crate::System::load_geometry`].
118    pub fn save(&self) -> Result<Vec<u8>> {
119        let mut data_size = 0;
120        unsafe {
121            FMOD_Geometry_Save(self.inner, std::ptr::null_mut(), &mut data_size).to_result()?;
122        }
123
124        let mut data = vec![0; data_size as usize];
125        unsafe {
126            FMOD_Geometry_Save(self.inner, data.as_mut_ptr().cast(), &mut data_size).to_result()?;
127        }
128
129        Ok(data)
130    }
131}
132
133#[cfg(feature = "userdata-abstraction")]
134impl Geometry {
135    pub fn set_userdata(&self, userdata: crate::userdata::Userdata) -> Result<()> {
136        use crate::userdata::{insert_userdata, set_userdata};
137
138        let pointer = self.get_raw_userdata()?;
139        if pointer.is_null() {
140            let key = insert_userdata(userdata, *self);
141            self.set_raw_userdata(key.into())?;
142        } else {
143            set_userdata(pointer.into(), userdata);
144        }
145
146        Ok(())
147    }
148
149    pub fn get_userdata(&self) -> Result<Option<crate::userdata::Userdata>> {
150        use crate::userdata::get_userdata;
151
152        let pointer = self.get_raw_userdata()?;
153        Ok(get_userdata(pointer.into()))
154    }
155}