Skip to main content

modelio/
physically_plausible_light.rs

1use std::path::Path;
2use std::ptr;
3
4use crate::error::Result;
5use crate::ffi;
6use crate::handle::ObjectHandle;
7use crate::light::Light;
8use crate::object::Object;
9use crate::texture::Texture;
10use crate::types::{AreaLightInfo, PhotometricLightInfo, PhysicallyPlausibleLightInfo};
11use crate::util::{parse_json, path_to_c_string, required_handle};
12
13#[derive(Debug, Clone)]
14/// Wraps the corresponding Model I/O physically plausible light counterpart.
15pub struct PhysicallyPlausibleLight {
16    handle: ObjectHandle,
17}
18
19impl PhysicallyPlausibleLight {
20    /// Builds this wrapper from the retained handle of the wrapped Model I/O physically plausible light counterpart.
21    pub(crate) fn from_handle(handle: ObjectHandle) -> Self {
22        Self { handle }
23    }
24
25    /// Wraps the corresponding Model I/O initializer for the wrapped Model I/O physically plausible light counterpart.
26    pub fn new() -> Result<Self> {
27        let mut out_light = ptr::null_mut();
28        let mut out_error = ptr::null_mut();
29        let status =
30            // SAFETY: Output pointers are initialized and managed; FFI function is called safely.
31            unsafe { ffi::mdl_physically_plausible_light_new(&mut out_light, &mut out_error) };
32        crate::util::status_result(status, out_error)?;
33        Ok(Self::from_handle(required_handle(
34            out_light,
35            "MDLPhysicallyPlausibleLight",
36        )?))
37    }
38
39    /// Calls the corresponding Model I/O method on the wrapped Model I/O physically plausible light counterpart.
40    pub fn info(&self) -> Result<PhysicallyPlausibleLightInfo> {
41        parse_json(
42            // SAFETY: ObjectHandle wraps a valid opaque pointer from Swift; FFI function accepts it safely.
43            unsafe { ffi::mdl_physically_plausible_light_info_json(self.handle.as_ptr()) },
44            "MDLPhysicallyPlausibleLight",
45        )
46    }
47
48    /// Calls the corresponding Model I/O method on the wrapped Model I/O physically plausible light counterpart.
49    pub fn set_color_temperature(&self, temperature: f32) {
50        // SAFETY: The unsafe operation is valid in this context.
51        unsafe {
52            ffi::mdl_physically_plausible_light_set_color_temperature(
53                self.handle.as_ptr(),
54                temperature,
55            );
56        };
57    }
58
59    /// Calls the corresponding Model I/O method on the wrapped Model I/O physically plausible light counterpart.
60    pub fn set_color(&self, color: [f32; 4]) {
61        // SAFETY: The unsafe operation is valid in this context.
62        unsafe {
63            ffi::mdl_physically_plausible_light_set_color(
64                self.handle.as_ptr(),
65                color[0],
66                color[1],
67                color[2],
68                color[3],
69            );
70        };
71    }
72
73    /// Calls the corresponding Model I/O method on the wrapped Model I/O physically plausible light counterpart.
74    pub fn set_lumens(&self, lumens: f32) {
75        // SAFETY: ObjectHandle wraps a valid opaque pointer from Swift; FFI function accepts it safely.
76        unsafe { ffi::mdl_physically_plausible_light_set_lumens(self.handle.as_ptr(), lumens) };
77    }
78
79    /// Calls the corresponding Model I/O method on the wrapped Model I/O physically plausible light counterpart.
80    pub fn set_inner_cone_angle(&self, angle: f32) {
81        // SAFETY: The unsafe operation is valid in this context.
82        unsafe {
83            ffi::mdl_physically_plausible_light_set_inner_cone_angle(self.handle.as_ptr(), angle);
84        };
85    }
86
87    /// Calls the corresponding Model I/O method on the wrapped Model I/O physically plausible light counterpart.
88    pub fn set_outer_cone_angle(&self, angle: f32) {
89        // SAFETY: The unsafe operation is valid in this context.
90        unsafe {
91            ffi::mdl_physically_plausible_light_set_outer_cone_angle(self.handle.as_ptr(), angle);
92        };
93    }
94
95    /// Calls the corresponding Model I/O method on the wrapped Model I/O physically plausible light counterpart.
96    pub fn set_attenuation_start_distance(&self, distance: f32) {
97        // SAFETY: The unsafe operation is valid in this context.
98        unsafe {
99            ffi::mdl_physically_plausible_light_set_attenuation_start_distance(
100                self.handle.as_ptr(),
101                distance,
102            );
103        };
104    }
105
106    /// Calls the corresponding Model I/O method on the wrapped Model I/O physically plausible light counterpart.
107    pub fn set_attenuation_end_distance(&self, distance: f32) {
108        // SAFETY: The unsafe operation is valid in this context.
109        unsafe {
110            ffi::mdl_physically_plausible_light_set_attenuation_end_distance(
111                self.handle.as_ptr(),
112                distance,
113            );
114        };
115    }
116
117    #[must_use]
118    /// Calls the corresponding Model I/O method on the wrapped Model I/O physically plausible light counterpart.
119    pub fn as_light(&self) -> Light {
120        Light::from_handle(self.handle.clone())
121    }
122
123    #[must_use]
124    /// Calls the corresponding Model I/O method on the wrapped Model I/O physically plausible light counterpart.
125    pub fn as_object(&self) -> Object {
126        Object::from_handle(self.handle.clone())
127    }
128}
129
130#[derive(Debug, Clone)]
131/// Wraps the corresponding Model I/O area light counterpart.
132pub struct AreaLight {
133    handle: ObjectHandle,
134}
135
136impl AreaLight {
137    /// Builds this wrapper from the retained handle of the wrapped Model I/O area light counterpart.
138    pub(crate) fn from_handle(handle: ObjectHandle) -> Self {
139        Self { handle }
140    }
141
142    /// Wraps the corresponding Model I/O initializer for the wrapped Model I/O area light counterpart.
143    pub fn new() -> Result<Self> {
144        let mut out_light = ptr::null_mut();
145        let mut out_error = ptr::null_mut();
146        // SAFETY: Output pointers are initialized and managed; FFI function is called safely.
147        let status = unsafe { ffi::mdl_area_light_new(&mut out_light, &mut out_error) };
148        crate::util::status_result(status, out_error)?;
149        Ok(Self::from_handle(required_handle(
150            out_light,
151            "MDLAreaLight",
152        )?))
153    }
154
155    /// Calls the corresponding Model I/O method on the wrapped Model I/O area light counterpart.
156    pub fn info(&self) -> Result<AreaLightInfo> {
157        parse_json(
158            // SAFETY: ObjectHandle wraps a valid opaque pointer from Swift; FFI function accepts it safely.
159            unsafe { ffi::mdl_area_light_info_json(self.handle.as_ptr()) },
160            "MDLAreaLight",
161        )
162    }
163
164    /// Calls the corresponding Model I/O method on the wrapped Model I/O area light counterpart.
165    pub fn set_area_radius(&self, value: f32) {
166        // SAFETY: ObjectHandle wraps a valid opaque pointer from Swift; FFI function accepts it safely.
167        unsafe { ffi::mdl_area_light_set_area_radius(self.handle.as_ptr(), value) };
168    }
169
170    /// Calls the corresponding Model I/O method on the wrapped Model I/O area light counterpart.
171    pub fn set_super_elliptic_power(&self, value: [f32; 2]) {
172        // SAFETY: The unsafe operation is valid in this context.
173        unsafe {
174            ffi::mdl_area_light_set_super_elliptic_power(self.handle.as_ptr(), value[0], value[1]);
175        };
176    }
177
178    /// Calls the corresponding Model I/O method on the wrapped Model I/O area light counterpart.
179    pub fn set_aspect(&self, value: f32) {
180        // SAFETY: ObjectHandle wraps a valid opaque pointer from Swift; FFI function accepts it safely.
181        unsafe { ffi::mdl_area_light_set_aspect(self.handle.as_ptr(), value) };
182    }
183
184    #[must_use]
185    /// Calls the corresponding Model I/O method on the wrapped Model I/O area light counterpart.
186    pub fn as_physically_plausible_light(&self) -> PhysicallyPlausibleLight {
187        PhysicallyPlausibleLight::from_handle(self.handle.clone())
188    }
189
190    #[must_use]
191    /// Calls the corresponding Model I/O method on the wrapped Model I/O area light counterpart.
192    pub fn as_light(&self) -> Light {
193        Light::from_handle(self.handle.clone())
194    }
195
196    #[must_use]
197    /// Calls the corresponding Model I/O method on the wrapped Model I/O area light counterpart.
198    pub fn as_object(&self) -> Object {
199        Object::from_handle(self.handle.clone())
200    }
201}
202
203#[derive(Debug, Clone)]
204/// Wraps the corresponding Model I/O photometric light counterpart.
205pub struct PhotometricLight {
206    handle: ObjectHandle,
207}
208
209impl PhotometricLight {
210    /// Builds this wrapper from the retained handle of the wrapped Model I/O photometric light counterpart.
211    pub(crate) fn from_handle(handle: ObjectHandle) -> Self {
212        Self { handle }
213    }
214
215    /// Wraps the corresponding Model I/O initializer for the wrapped Model I/O photometric light counterpart.
216    pub fn new() -> Result<Self> {
217        let mut out_light = ptr::null_mut();
218        let mut out_error = ptr::null_mut();
219        // SAFETY: Output pointers are initialized and managed; FFI function is called safely.
220        let status = unsafe { ffi::mdl_photometric_light_new(&mut out_light, &mut out_error) };
221        crate::util::status_result(status, out_error)?;
222        Ok(Self::from_handle(required_handle(
223            out_light,
224            "MDLPhotometricLight",
225        )?))
226    }
227
228    /// Calls the corresponding Model I/O method on the wrapped Model I/O photometric light counterpart.
229    pub fn from_ies_profile(path: impl AsRef<Path>) -> Result<Self> {
230        let path = path_to_c_string(path.as_ref())?;
231        let mut out_light = ptr::null_mut();
232        let mut out_error = ptr::null_mut();
233        // SAFETY: The unsafe operation is valid in this context.
234        let status = unsafe {
235            ffi::mdl_photometric_light_new_with_ies_profile(
236                path.as_ptr(),
237                &mut out_light,
238                &mut out_error,
239            )
240        };
241        crate::util::status_result(status, out_error)?;
242        Ok(Self::from_handle(required_handle(
243            out_light,
244            "MDLPhotometricLight",
245        )?))
246    }
247
248    /// Calls the corresponding Model I/O method on the wrapped Model I/O photometric light counterpart.
249    pub fn info(&self) -> Result<PhotometricLightInfo> {
250        parse_json(
251            // SAFETY: ObjectHandle wraps a valid opaque pointer from Swift; FFI function accepts it safely.
252            unsafe { ffi::mdl_photometric_light_info_json(self.handle.as_ptr()) },
253            "MDLPhotometricLight",
254        )
255    }
256
257    /// Calls the corresponding Model I/O method on the wrapped Model I/O photometric light counterpart.
258    pub fn generate_spherical_harmonics_from_light(&self, level: usize) {
259        // SAFETY: The unsafe operation is valid in this context.
260        unsafe {
261            ffi::mdl_photometric_light_generate_spherical_harmonics_from_light(
262                self.handle.as_ptr(),
263                level as u64,
264            );
265        };
266    }
267
268    /// Calls the corresponding Model I/O method on the wrapped Model I/O photometric light counterpart.
269    pub fn generate_cubemap_from_light(&self, texture_size: usize) {
270        // SAFETY: The unsafe operation is valid in this context.
271        unsafe {
272            ffi::mdl_photometric_light_generate_cubemap_from_light(
273                self.handle.as_ptr(),
274                texture_size as u64,
275            );
276        };
277    }
278
279    #[must_use]
280    /// Calls the corresponding Model I/O method on the wrapped Model I/O photometric light counterpart.
281    pub fn generate_texture(&self, texture_size: usize) -> Option<Texture> {
282        // SAFETY: The unsafe operation is valid in this context.
283        let ptr = unsafe {
284            ffi::mdl_photometric_light_generate_texture(self.handle.as_ptr(), texture_size as u64)
285        };
286        // SAFETY: The unsafe operation is valid in this context.
287        unsafe { ObjectHandle::from_retained_ptr(ptr) }.map(Texture::from_handle)
288    }
289
290    #[must_use]
291    /// Calls the corresponding Model I/O method on the wrapped Model I/O photometric light counterpart.
292    pub fn light_cube_map(&self) -> Option<Texture> {
293        // SAFETY: ObjectHandle wraps a valid opaque pointer from Swift; FFI function accepts it safely.
294        let ptr = unsafe { ffi::mdl_photometric_light_light_cube_map(self.handle.as_ptr()) };
295        // SAFETY: The unsafe operation is valid in this context.
296        unsafe { ObjectHandle::from_retained_ptr(ptr) }.map(Texture::from_handle)
297    }
298
299    #[must_use]
300    /// Calls the corresponding Model I/O method on the wrapped Model I/O photometric light counterpart.
301    pub fn as_physically_plausible_light(&self) -> PhysicallyPlausibleLight {
302        PhysicallyPlausibleLight::from_handle(self.handle.clone())
303    }
304
305    #[must_use]
306    /// Calls the corresponding Model I/O method on the wrapped Model I/O photometric light counterpart.
307    pub fn as_light(&self) -> Light {
308        Light::from_handle(self.handle.clone())
309    }
310
311    #[must_use]
312    /// Calls the corresponding Model I/O method on the wrapped Model I/O photometric light counterpart.
313    pub fn as_object(&self) -> Object {
314        Object::from_handle(self.handle.clone())
315    }
316}