Skip to main content

openvr/
overlay.rs

1
2pub use crate::errors::VROverlayError;
3use crate::pose::Matrix3x4;
4use crate::Overlay;
5use crate::TextureBounds;
6use crate::TrackingUniverseOrigin;
7use crate::{sys, ColorTint, TrackedDeviceIndex};
8
9
10
11impl Overlay {
12
13    pub fn create_overlay(
14        &mut self,
15        key: &str,
16        friendly_name: &str,
17    ) -> Result<OverlayHandle, VROverlayError> {
18        let mut handle = sys::VROverlayHandle_t::default();
19        let err = unsafe {
20            self.0.CreateOverlay.unwrap()(key.as_ptr().cast_mut().cast(),friendly_name.as_ptr().cast_mut().cast(),&mut handle)
21        };
22
23        VROverlayError::new(err)?;
24        Ok(OverlayHandle(handle))
25    }
26
27    pub fn set_visibility(
28        &mut self,
29        overlay: OverlayHandle,
30        is_visible: bool,
31    ) -> Result<(), VROverlayError> {
32        let err = if is_visible {
33            unsafe { self.0.ShowOverlay.unwrap()(overlay.0) }
34        } else {
35            unsafe { self.0.HideOverlay.unwrap()(overlay.0) }
36        };
37        VROverlayError::new(err)
38    }
39
40    pub fn is_visible(&mut self, overlay: OverlayHandle) -> bool {
41        unsafe { self.0.IsOverlayVisible.unwrap()(overlay.0) }
42    }
43
44    /// Set the curvature of the overlay, with 0 being a quad and 1 being a cylinder.
45    /// # Panics
46    /// Panics if `curvature` is not in `[0,1]`
47    pub fn set_curvature(
48        &mut self,
49        overlay: OverlayHandle,
50        curvature: f32,
51    ) -> Result<(), VROverlayError> {
52        // if !(0.0..=1.0).contains(&curvature) {
53        //     panic!("`curvature` must lie in range [0,1]")
54        // }
55        let err = unsafe {
56            self.0
57                .SetOverlayCurvature.unwrap()(overlay.0, curvature)
58        };
59        VROverlayError::new(err)
60    }
61
62    pub fn curvature(&mut self, overlay: OverlayHandle) -> Result<f32, VROverlayError> {
63        let mut curvature = 0.0;
64        let err = unsafe {
65            self.0
66                .GetOverlayCurvature.unwrap()(overlay.0, &mut curvature)
67        };
68        VROverlayError::new(err)?;
69        Ok(curvature)
70    }
71
72    /// Sets the opacity of the overlay. `alpha` ranges from 0.0 (transparent) to 1.0 (opaque).
73    /// # Panics
74    /// Panics if `alpha` is not in `[0,1]`
75    pub fn set_opacity(
76        &mut self,
77        overlay: OverlayHandle,
78        alpha: f32,
79    ) -> Result<(), VROverlayError> {
80        if !(0.0..=1.0).contains(&alpha) {
81            panic!("`alpha` must be in range [0,1]");
82        }
83        let err = unsafe { self.0.SetOverlayAlpha.unwrap()(overlay.0, alpha) };
84        VROverlayError::new(err)
85    }
86
87    pub fn opacity(&mut self, overlay: OverlayHandle) -> Result<f32, VROverlayError> {
88        let mut alpha = 0.0;
89        let err = unsafe { self.0.GetOverlayAlpha.unwrap()(overlay.0, &mut alpha) };
90        VROverlayError::new(err)?;
91        Ok(alpha)
92    }
93
94    pub fn width(&mut self, overlay: OverlayHandle) -> Result<f32, VROverlayError> {
95        let mut width = 0.0;
96        let err = unsafe {
97            self.0
98                .GetOverlayWidthInMeters.unwrap()(overlay.0, &mut width)
99        };
100        VROverlayError::new(err)?;
101        Ok(width)
102    }
103
104    pub fn set_width(
105        &mut self,
106        overlay: OverlayHandle,
107        width_in_meters: f32,
108    ) -> Result<(), VROverlayError> {
109        let err = unsafe {
110            self.0
111                .SetOverlayWidthInMeters.unwrap()(overlay.0, width_in_meters)
112        };
113        VROverlayError::new(err)
114    }
115
116    pub fn sort_order(&mut self, overlay: OverlayHandle) -> Result<u32, VROverlayError> {
117        let mut sort_order: u32 = 0;
118        let err = unsafe {
119            self.0
120                .GetOverlaySortOrder.unwrap()(overlay.0, &mut sort_order)
121        };
122        VROverlayError::new(err)?;
123        Ok(sort_order)
124    }
125
126    pub fn set_sort_order(
127        &mut self,
128        overlay: OverlayHandle,
129        sort_order: u32,
130    ) -> Result<(), VROverlayError> {
131        let err = unsafe {
132            self.0
133                .SetOverlaySortOrder.unwrap()(overlay.0, sort_order)
134        };
135        VROverlayError::new(err)
136    }
137
138    pub fn tint(&mut self, overlay: OverlayHandle) -> Result<ColorTint, VROverlayError> {
139        let mut tint = ColorTint::default();
140        unsafe {
141            let err = self.0.GetOverlayColor.unwrap()(
142                overlay.0,
143                &mut tint.r,
144                &mut tint.g,
145                &mut tint.b,
146            );
147            VROverlayError::new(err)?;
148            let err = self.0.GetOverlayAlpha.unwrap()(overlay.0, &mut tint.a);
149            VROverlayError::new(err)?
150        };
151        Ok(tint)
152    }
153
154    pub fn set_tint(
155        &mut self,
156        overlay: OverlayHandle,
157        tint: ColorTint,
158    ) -> Result<(), VROverlayError> {
159        unsafe {
160            let err = self.0
161                .SetOverlayColor.unwrap()(overlay.0, tint.r, tint.g, tint.b);
162            VROverlayError::new(err)?;
163            let err = self.0.SetOverlayAlpha.unwrap()(overlay.0, tint.a);
164            VROverlayError::new(err)?;
165        }
166        Ok(())
167    }
168
169    pub fn set_image(
170        &mut self,
171        overlay: OverlayHandle,
172        img_path: &std::ffi::CStr,
173    ) -> Result<(), VROverlayError> {
174        let err = unsafe {
175            self.0
176                .SetOverlayFromFile.unwrap()(overlay.0, img_path.as_ptr().cast_mut())
177        };
178        VROverlayError::new(err)
179    }
180
181    pub fn set_raw_data(
182        &mut self,
183        overlay: OverlayHandle,
184        data: &[u8],
185        width: usize,
186        height: usize,
187        bytes_per_pixel: usize,
188    ) -> Result<(), VROverlayError> {
189        let err = unsafe {
190            let ptr: *const std::ffi::c_void = data.as_ptr().cast();
191            // I think there is a typo in the API, and it actually needs a const
192            // ptr. *IF* this is true, the following line is safe.
193            let ptr = ptr as *mut std::ffi::c_void;
194
195            self.0.SetOverlayRaw.unwrap()(
196                overlay.0,
197                ptr.cast(),
198                width as u32,
199                height as u32,
200                bytes_per_pixel as u32,
201            )
202        };
203        VROverlayError::new(err)
204    }
205
206    /// Get aspect ratio, with aspect expressed as width / height.
207    pub fn texel_aspect(&mut self, overlay: OverlayHandle) -> Result<f32, VROverlayError> {
208        let mut aspect = 0.0;
209        let err = unsafe {
210            self.0
211                .GetOverlayTexelAspect.unwrap()(overlay.0, &mut aspect)
212        };
213        VROverlayError::new(err)?;
214        Ok(aspect)
215    }
216
217    /// Set aspect ratio, with aspect expressed as width / height.
218    ///
219    /// Note that too extreme of an aspect ratio will cause an error to be returned.
220    pub fn set_texel_aspect(
221        &mut self,
222        overlay: OverlayHandle,
223        aspect: f32,
224    ) -> Result<(), VROverlayError> {
225        let err = unsafe { self.0.SetOverlayTexelAspect.unwrap()(overlay.0, aspect) };
226        VROverlayError::new(err)
227    }
228
229    /// Sets an absolute transform for this overlay.
230    ///
231    /// Wraps c++ `SetOverlayTransformAbsolute`.
232    pub fn set_transform_absolute(
233        &mut self,
234        overlay: OverlayHandle,
235        origin: TrackingUniverseOrigin,
236        origin_to_overlay: &Matrix3x4,
237    ) -> Result<(), VROverlayError> {
238        let origin_to_overlay: &sys::HmdMatrix34_t = origin_to_overlay.into();
239        
240        let err = unsafe {
241            self.0
242                .SetOverlayTransformAbsolute.unwrap()(overlay.0, origin.into(), (&raw const *origin_to_overlay).cast_mut()) 
243        };
244        VROverlayError::new(err)
245    }
246
247    /// Gets the absolute transform for this overlay.
248    ///
249    /// Wraps c++ `GetOverlayTransformAbsolute`.
250    pub fn get_transform_absolute(
251        &mut self,
252        overlay: OverlayHandle,
253        origin_to_overlay: &mut Matrix3x4,
254    ) -> Result<TrackingUniverseOrigin, VROverlayError> {
255        // Some random value just to initialize the data
256        let mut origin = TrackingUniverseOrigin::Standing;
257        let origin_to_overlay: &mut sys::HmdMatrix34_t = origin_to_overlay.into();
258        let err = unsafe {
259            self.0.GetOverlayTransformAbsolute.unwrap()(
260                overlay.0,
261                (&raw mut origin).cast(),
262                origin_to_overlay,
263            )
264        };
265        VROverlayError::new(err).map(|_| origin)
266    }
267
268    /// Sets the transform for this overlay, relative to a tracked device.
269    ///
270    /// Wraps c++ `SetOverlayTransformTrackedDeviceRelative`.
271    pub fn set_transform_tracked_device_relative(
272        &mut self,
273        overlay: OverlayHandle,
274        index: TrackedDeviceIndex,
275        device_to_overlay: &Matrix3x4,
276    ) -> Result<(), VROverlayError> {
277        let device_to_overlay: &sys::HmdMatrix34_t = device_to_overlay.into();
278        let err = unsafe {
279            self.0
280                .SetOverlayTransformTrackedDeviceRelative.unwrap()(overlay.0, index.0, (&raw const *device_to_overlay).cast_mut())
281        };
282        VROverlayError::new(err)
283    }
284
285    /// Gets the transform for this overlay, relative to a tracked device.
286    ///
287    /// Wraps c++ `GetOverlayTransformTrackedDeviceRelative`.
288    pub fn get_transform_tracked_device_relative(
289        &mut self,
290        overlay: OverlayHandle,
291        device_to_overlay: &mut Matrix3x4,
292    ) -> Result<TrackedDeviceIndex, VROverlayError> {
293        let mut index = sys::TrackedDeviceIndex_t::default();
294        let device_to_overlay: &mut sys::HmdMatrix34_t = device_to_overlay.into();
295        let err = unsafe {
296            self.0
297                .GetOverlayTransformTrackedDeviceRelative.unwrap()(overlay.0, &mut index, device_to_overlay)
298        };
299        VROverlayError::new(err)?;
300        // TODO: is the error ever really going to be delayed to here? (Can we successfully return an invalid handle?)
301        if index==sys::k_unTrackedDeviceIndexInvalid as u32{
302            return Err(VROverlayError::RequestFailed);
303        }
304        Ok(crate::tracking::TrackedDeviceIndex(index))
305    }
306
307    pub fn set_texture_bounds(
308        &mut self,
309        overlay: OverlayHandle,
310        bounds: &TextureBounds,
311    ) -> Result<(), VROverlayError> {
312        let err = unsafe {
313            self.0
314                .SetOverlayTextureBounds.unwrap()(overlay.0, (&raw const bounds.0).cast_mut())
315        };
316        VROverlayError::new(err)
317    }
318
319    pub fn is_dashboard_visible(&mut self) -> bool {
320        unsafe { self.0.IsDashboardVisible.unwrap()() }
321    }
322}
323unsafe impl Send for Overlay {}
324unsafe impl Sync for Overlay {}
325
326#[derive(Debug, PartialEq, Eq, Clone, Copy)]
327pub struct OverlayHandle(pub sys::VROverlayHandle_t);