1 module openvr.helper;
2 
3 import openvr.api;
4 
5 /** Returns true if the tracked controller role is allowed to be a hand */
6 pragma(inline, true) bool IsRoleAllowedAsHand(ETrackedControllerRole eRole)
7 {
8 	switch (eRole) with (ETrackedControllerRole)
9 	{
10 	case Invalid:
11 	case LeftHand:
12 	case RightHand:
13 		return true;
14 	default:
15 		return false;
16 	}
17 }
18 
19 pragma(inline, true) ulong ButtonMaskFromId(EVRButtonId id)
20 {
21 	return 1UL << id;
22 }
23 
24 /** Compositor frame timing reprojection flags. */
25 
26 /// This flag indicates the async reprojection mode is active,
27 /// but does not indicate if reprojection actually happened or not.
28 /// Use the ReprojectionReason flags above to check if reprojection
29 /// was actually applied (i.e. scene texture was reused).
30 /// NumFramePresents > 1 also indicates the scene texture was reused,
31 /// and also the number of times that it was presented in total.
32 enum uint VRCompositor_ReprojectionReason_Cpu = 0x01;
33 enum uint VRCompositor_ReprojectionReason_Gpu = 0x02;
34 enum uint VRCompositor_ReprojectionAsync = 0x04;
35 
36 /// This flag indicates whether or not motion smoothing was triggered for this frame
37 enum uint VRCompositor_ReprojectionMotion = 0x08;
38 
39 /// The runtime may predict more than one frame (up to four) ahead if
40 /// it detects the application is taking too long to render. These two
41 /// bits will contain the count of additional frames (normally zero).
42 /// Use the VR_COMPOSITOR_ADDITIONAL_PREDICTED_FRAMES macro to read from
43 /// the latest frame timing entry.
44 enum uint VRCompositor_PredictionMask = 0x30;
45 
46 /// Number of frames the compositor is throttling the application.
47 /// Use the VR_COMPOSITOR_NUMBER_OF_THROTTLED_FRAMES macro to read from
48 /// the latest frame timing entry.
49 enum uint VRCompositor_ThrottleMask = 0xC0;
50 
51 enum VR_COMPOSITOR_ADDITIONAL_PREDICTED_FRAMES(alias timing) = (((timing)
52 			.m_nReprojectionFlags & vr.VRCompositor_PredictionMask) >> 4);
53 enum VR_COMPOSITOR_NUMBER_OF_THROTTLED_FRAMES(alias timing) = (((timing)
54 			.m_nReprojectionFlags & vr.VRCompositor_ThrottleMask) >> 6);
55 
56 /** These flags will be set on DriverDirectMode_FrameTiming::m_nReprojectionFlags when IVRDriverDirectModeComponent::GetFrameTiming is called for drivers to optionally respond to. */
57 enum uint VRCompositor_ReprojectionMotion_Enabled = 0x100; /// Motion Smoothing is enabled in the UI for the currently running application
58 enum uint VRCompositor_ReprojectionMotion_ForcedOn = 0x200; /// Motion Smoothing is forced on in the UI for the currently running application
59 enum uint VRCompositor_ReprojectionMotion_AppThrottled = 0x400; /// Application is requesting throttling via ForceInterleavedReprojectionOn
60 
61 /** Returns the current IVRHeadsetView pointer or NULL the interface could not be found. */
62 extern (C) IVRHeadsetView VRHeadsetView();
63 
64 /** Returns true if there is an HMD attached. This check is as lightweight as possible and
65 * can be called outside of VR_Init/VR_Shutdown. It should be used when an application wants
66 * to know if initializing VR is a possibility but isn't ready to take that step yet.
67 */
68 extern (C) bool VR_IsHmdPresent();
69 
70 /** Returns true if the OpenVR runtime is installed. */
71 extern (C) bool VR_IsRuntimeInstalled();
72 
73 /** Returns where the OpenVR runtime is installed. */
74 extern (C) bool VR_GetRuntimePath(char* pchPathBuffer, uint unBufferSize,
75 		uint* punRequiredBufferSize);
76 
77 /** Returns the name of the enum value for an EVRInitError. This function may be called outside of VR_Init()/VR_Shutdown(). */
78 extern (C) const(char)* VR_GetVRInitErrorAsSymbol(EVRInitError error);
79 
80 /** Returns an English string for an EVRInitError. Applications should call VR_GetVRInitErrorAsSymbol instead and
81 * use that as a key to look up their own localized error message. This function may be called outside of VR_Init()/VR_Shutdown(). */
82 extern (C) const(char)* VR_GetVRInitErrorAsEnglishDescription(EVRInitError error);
83 
84 /** Returns the interface of the specified version. This method must be called after VR_Init. The
85 * pointer returned is valid until VR_Shutdown is called.
86 */
87 extern (C) void* VR_GetGenericInterface(const(char)* pchInterfaceVersion, EVRInitError* peError);
88 
89 /** Returns whether the interface of the specified version exists.
90 */
91 extern (C) bool VR_IsInterfaceVersionValid(const(char)* pchInterfaceVersion);
92 
93 /** Returns a token that represents whether the VR interface handles need to be reloaded */
94 extern (C) uint VR_GetInitToken();
95 
96 extern (C) uint VR_InitInternal2(EVRInitError* peError,
97 		EVRApplicationType eApplicationType, const(char)* pStartupInfo);
98 extern (C) void VR_ShutdownInternal();
99 
100 extern (C++, vr)
101 {
102 
103 	/** Finds the active installation of the VR API and initializes it. The provided path must be absolute
104 * or relative to the current working directory. These are the local install versions of the equivalent
105 * functions in steamvr.h and will work without a local Steam install.
106 *
107 * This path is to the "root" of the VR API install. That's the directory with
108 * the "drivers" directory and a platform (i.e. "win32") directory in it, not the directory with the DLL itself.
109 *
110 * pStartupInfo is reserved for future use.
111 */
112 	pragma(inline, true) IVRSystem VR_Init(EVRInitError* peError,
113 			EVRApplicationType eApplicationType, const(char)* pStartupInfo = null);
114 
115 	/** unloads vrclient.dll. Any interface pointers from the interface are
116 * invalid after this point */
117 	pragma(inline, true) void VR_Shutdown();
118 
119 	pragma(inline, true) ref uint VRToken()
120 	{
121 		static uint token;
122 		return token;
123 	}
124 
125 	class COpenVRContext
126 	{
127 	public:
128 		this()
129 		{
130 			Clear();
131 		}
132 
133 		pragma(inline, true) void Clear()
134 		{
135 			m_pVRSystem = null;
136 			m_pVRChaperone = null;
137 			m_pVRChaperoneSetup = null;
138 			m_pVRCompositor = null;
139 			m_pVROverlay = null;
140 			m_pVROverlayView = null;
141 			m_pVRHeadsetView = null;
142 			m_pVRRenderModels = null;
143 			m_pVRExtendedDisplay = null;
144 			m_pVRSettings = null;
145 			m_pVRApplications = null;
146 			m_pVRTrackedCamera = null;
147 			m_pVRResources = null;
148 			m_pVRScreenshots = null;
149 			m_pVRDriverManager = null;
150 			m_pVRInput = null;
151 			m_pVRIOBuffer = null;
152 			m_pVRSpatialAnchors = null;
153 			m_pVRNotifications = null;
154 			m_pVRDebug = null;
155 		}
156 
157 		pragma(inline, true) void CheckClear()
158 		{
159 			if (VRToken() != VR_GetInitToken())
160 			{
161 				Clear();
162 				VRToken() = VR_GetInitToken();
163 			}
164 		}
165 
166 		IVRSystem VRSystem()
167 		{
168 			CheckClear();
169 			if (m_pVRSystem is null)
170 			{
171 				EVRInitError eError;
172 				m_pVRSystem = cast(IVRSystem) VR_GetGenericInterface(IVRSystem_Version,
173 						&eError);
174 			}
175 			return m_pVRSystem;
176 		}
177 
178 		IVRChaperone VRChaperone()
179 		{
180 			CheckClear();
181 			if (m_pVRChaperone is null)
182 			{
183 				EVRInitError eError;
184 				m_pVRChaperone = cast(IVRChaperone) VR_GetGenericInterface(
185 						IVRChaperone_Version, &eError);
186 			}
187 			return m_pVRChaperone;
188 		}
189 
190 		IVRChaperoneSetup VRChaperoneSetup()
191 		{
192 			CheckClear();
193 			if (m_pVRChaperoneSetup is null)
194 			{
195 				EVRInitError eError;
196 				m_pVRChaperoneSetup = cast(IVRChaperoneSetup) VR_GetGenericInterface(
197 						IVRChaperoneSetup_Version, &eError);
198 			}
199 			return m_pVRChaperoneSetup;
200 		}
201 
202 		IVRCompositor VRCompositor()
203 		{
204 			CheckClear();
205 			if (m_pVRCompositor is null)
206 			{
207 				EVRInitError eError;
208 				m_pVRCompositor = cast(IVRCompositor) VR_GetGenericInterface(
209 						IVRCompositor_Version, &eError);
210 			}
211 			return m_pVRCompositor;
212 		}
213 
214 		IVROverlay VROverlay()
215 		{
216 			CheckClear();
217 			if (m_pVROverlay is null)
218 			{
219 				EVRInitError eError;
220 				m_pVROverlay = cast(IVROverlay) VR_GetGenericInterface(
221 						IVROverlay_Version, &eError);
222 			}
223 			return m_pVROverlay;
224 		}
225 
226 		IVROverlayView VROverlayView()
227 		{
228 			CheckClear();
229 			if (m_pVROverlayView is null)
230 			{
231 				EVRInitError eError;
232 				m_pVROverlayView = cast(IVROverlayView) VR_GetGenericInterface(
233 						IVROverlayView_Version, &eError);
234 			}
235 			return m_pVROverlayView;
236 		}
237 
238 		IVRHeadsetView VRHeadsetView()
239 		{
240 			CheckClear();
241 			if (m_pVRHeadsetView is null)
242 			{
243 				EVRInitError eError;
244 				m_pVRHeadsetView = cast(IVRHeadsetView) VR_GetGenericInterface(
245 						IVRHeadsetView_Version, &eError);
246 			}
247 			return m_pVRHeadsetView;
248 		}
249 
250 		IVRResources VRResources()
251 		{
252 			CheckClear();
253 			if (m_pVRResources is null)
254 			{
255 				EVRInitError eError;
256 				m_pVRResources = cast(IVRResources) VR_GetGenericInterface(
257 						IVRResources_Version, &eError);
258 			}
259 			return m_pVRResources;
260 		}
261 
262 		IVRScreenshots VRScreenshots()
263 		{
264 			CheckClear();
265 			if (m_pVRScreenshots is null)
266 			{
267 				EVRInitError eError;
268 				m_pVRScreenshots = cast(IVRScreenshots) VR_GetGenericInterface(
269 						IVRScreenshots_Version, &eError);
270 			}
271 			return m_pVRScreenshots;
272 		}
273 
274 		IVRRenderModels VRRenderModels()
275 		{
276 			CheckClear();
277 			if (m_pVRRenderModels is null)
278 			{
279 				EVRInitError eError;
280 				m_pVRRenderModels = cast(IVRRenderModels) VR_GetGenericInterface(
281 						IVRRenderModels_Version, &eError);
282 			}
283 			return m_pVRRenderModels;
284 		}
285 
286 		IVRExtendedDisplay VRExtendedDisplay()
287 		{
288 			CheckClear();
289 			if (m_pVRExtendedDisplay is null)
290 			{
291 				EVRInitError eError;
292 				m_pVRExtendedDisplay = cast(IVRExtendedDisplay) VR_GetGenericInterface(
293 						IVRExtendedDisplay_Version, &eError);
294 			}
295 			return m_pVRExtendedDisplay;
296 		}
297 
298 		IVRSettings VRSettings()
299 		{
300 			CheckClear();
301 			if (m_pVRSettings is null)
302 			{
303 				EVRInitError eError;
304 				m_pVRSettings = cast(IVRSettings) VR_GetGenericInterface(
305 						IVRSettings_Version, &eError);
306 			}
307 			return m_pVRSettings;
308 		}
309 
310 		IVRApplications VRApplications()
311 		{
312 			CheckClear();
313 			if (m_pVRApplications is null)
314 			{
315 				EVRInitError eError;
316 				m_pVRApplications = cast(IVRApplications) VR_GetGenericInterface(
317 						IVRApplications_Version, &eError);
318 			}
319 			return m_pVRApplications;
320 		}
321 
322 		IVRTrackedCamera VRTrackedCamera()
323 		{
324 			CheckClear();
325 			if (m_pVRTrackedCamera is null)
326 			{
327 				EVRInitError eError;
328 				m_pVRTrackedCamera = cast(IVRTrackedCamera) VR_GetGenericInterface(
329 						IVRTrackedCamera_Version, &eError);
330 			}
331 			return m_pVRTrackedCamera;
332 		}
333 
334 		IVRDriverManager VRDriverManager()
335 		{
336 			CheckClear();
337 			if (!m_pVRDriverManager)
338 			{
339 				EVRInitError eError;
340 				m_pVRDriverManager = cast(IVRDriverManager) VR_GetGenericInterface(
341 						IVRDriverManager_Version, &eError);
342 			}
343 			return m_pVRDriverManager;
344 		}
345 
346 		IVRInput VRInput()
347 		{
348 			CheckClear();
349 			if (!m_pVRInput)
350 			{
351 				EVRInitError eError;
352 				m_pVRInput = cast(IVRInput) VR_GetGenericInterface(IVRInput_Version,
353 						&eError);
354 			}
355 			return m_pVRInput;
356 		}
357 
358 		IVRIOBuffer VRIOBuffer()
359 		{
360 			if (!m_pVRIOBuffer)
361 			{
362 				EVRInitError eError;
363 				m_pVRIOBuffer = cast(IVRIOBuffer) VR_GetGenericInterface(
364 						IVRIOBuffer_Version, &eError);
365 			}
366 			return m_pVRIOBuffer;
367 		}
368 
369 		IVRSpatialAnchors VRSpatialAnchors()
370 		{
371 			CheckClear();
372 			if (!m_pVRSpatialAnchors)
373 			{
374 				EVRInitError eError;
375 				m_pVRSpatialAnchors = cast(IVRSpatialAnchors) VR_GetGenericInterface(
376 						IVRSpatialAnchors_Version, &eError);
377 			}
378 			return m_pVRSpatialAnchors;
379 		}
380 
381 		IVRDebug VRDebug()
382 		{
383 			CheckClear();
384 			if (!m_pVRDebug)
385 			{
386 				EVRInitError eError;
387 				m_pVRDebug = cast(IVRDebug) VR_GetGenericInterface(IVRDebug_Version,
388 						&eError);
389 			}
390 			return m_pVRDebug;
391 		}
392 
393 		IVRNotifications VRNotifications()
394 		{
395 			CheckClear();
396 			if (!m_pVRNotifications)
397 			{
398 				EVRInitError eError;
399 				m_pVRNotifications = cast(IVRNotifications) VR_GetGenericInterface(
400 						IVRNotifications_Version, &eError);
401 			}
402 			return m_pVRNotifications;
403 		}
404 
405 	private:
406 		IVRSystem m_pVRSystem;
407 		IVRChaperone m_pVRChaperone;
408 		IVRChaperoneSetup m_pVRChaperoneSetup;
409 		IVRCompositor m_pVRCompositor;
410 		IVRHeadsetView m_pVRHeadsetView;
411 		IVROverlay m_pVROverlay;
412 		IVROverlayView m_pVROverlayView;
413 		IVRResources m_pVRResources;
414 		IVRRenderModels m_pVRRenderModels;
415 		IVRExtendedDisplay m_pVRExtendedDisplay;
416 		IVRSettings m_pVRSettings;
417 		IVRApplications m_pVRApplications;
418 		IVRTrackedCamera m_pVRTrackedCamera;
419 		IVRScreenshots m_pVRScreenshots;
420 		IVRDriverManager m_pVRDriverManager;
421 		IVRInput m_pVRInput;
422 		IVRIOBuffer m_pVRIOBuffer;
423 		IVRSpatialAnchors m_pVRSpatialAnchors;
424 		IVRDebug m_pVRDebug;
425 		IVRNotifications m_pVRNotifications;
426 	}
427 
428 	pragma(inline, true) ref COpenVRContext OpenVRInternal_ModuleContext()
429 	{
430 		static COpenVRContext ctx = null;
431 		if (ctx is null)
432 			ctx = new COpenVRContext();
433 		return ctx;
434 	}
435 
436 	pragma(inline, true) IVRSystem VRSystem()
437 	{
438 		return OpenVRInternal_ModuleContext().VRSystem();
439 	}
440 
441 	pragma(inline, true) IVRChaperone VRChaperone()
442 	{
443 		return OpenVRInternal_ModuleContext().VRChaperone();
444 	}
445 
446 	pragma(inline, true) IVRChaperoneSetup VRChaperoneSetup()
447 	{
448 		return OpenVRInternal_ModuleContext().VRChaperoneSetup();
449 	}
450 
451 	pragma(inline, true) IVRCompositor VRCompositor()
452 	{
453 		return OpenVRInternal_ModuleContext().VRCompositor();
454 	}
455 
456 	pragma(inline, true) IVROverlay VROverlay()
457 	{
458 		return OpenVRInternal_ModuleContext().VROverlay();
459 	}
460 
461 	pragma(inline, true) IVROverlayView VROverlayView()
462 	{
463 		return OpenVRInternal_ModuleContext().VROverlayView();
464 	}
465 
466 	pragma(inline, true) IVRHeadsetView VRHeadsetView()
467 	{
468 		return OpenVRInternal_ModuleContext().VRHeadsetView();
469 	}
470 
471 	pragma(inline, true) IVRScreenshots VRScreenshots()
472 	{
473 		return OpenVRInternal_ModuleContext().VRScreenshots();
474 	}
475 
476 	pragma(inline, true) IVRRenderModels VRRenderModels()
477 	{
478 		return OpenVRInternal_ModuleContext().VRRenderModels();
479 	}
480 
481 	pragma(inline, true) IVRApplications VRApplications()
482 	{
483 		return OpenVRInternal_ModuleContext().VRApplications();
484 	}
485 
486 	pragma(inline, true) IVRSettings VRSettings()
487 	{
488 		return OpenVRInternal_ModuleContext().VRSettings();
489 	}
490 
491 	pragma(inline, true) IVRResources VRResources()
492 	{
493 		return OpenVRInternal_ModuleContext().VRResources();
494 	}
495 
496 	pragma(inline, true) IVRExtendedDisplay VRExtendedDisplay()
497 	{
498 		return OpenVRInternal_ModuleContext().VRExtendedDisplay();
499 	}
500 
501 	pragma(inline, true) IVRTrackedCamera VRTrackedCamera()
502 	{
503 		return OpenVRInternal_ModuleContext().VRTrackedCamera();
504 	}
505 
506 	pragma(inline, true) IVRDriverManager VRDriverManager()
507 	{
508 		return OpenVRInternal_ModuleContext().VRDriverManager();
509 	}
510 
511 	pragma(inline, true) IVRInput VRInput()
512 	{
513 		return OpenVRInternal_ModuleContext().VRInput();
514 	}
515 
516 	pragma(inline, true) IVRIOBuffer VRIOBuffer()
517 	{
518 		return OpenVRInternal_ModuleContext().VRIOBuffer();
519 	}
520 
521 	pragma(inline, true) IVRSpatialAnchors VRSpatialAnchors()
522 	{
523 		return OpenVRInternal_ModuleContext().VRSpatialAnchors();
524 	}
525 
526 	pragma(inline, true) IVRNotifications VRNotifications()
527 	{
528 		return OpenVRInternal_ModuleContext().VRNotifications();
529 	}
530 
531 	pragma(inline, true) IVRDebug VRDebug()
532 	{
533 		return OpenVRInternal_ModuleContext().VRDebug();
534 	}
535 
536 	/** Finds the active installation of vrclient.dll and initializes it */
537 	pragma(inline, true) IVRSystem VR_Init(EVRInitError* peError,
538 			EVRApplicationType eApplicationType, const(char)* pStartupInfo)
539 	{
540 		IVRSystem pVRSystem = null;
541 
542 		EVRInitError eError;
543 		VRToken() = VR_InitInternal2(&eError, eApplicationType, pStartupInfo);
544 		COpenVRContext* ctx = &OpenVRInternal_ModuleContext();
545 		ctx.Clear();
546 
547 		if (eError == EVRInitError.None)
548 		{
549 			if (VR_IsInterfaceVersionValid(IVRSystem_Version))
550 			{
551 				pVRSystem = VRSystem();
552 			}
553 			else
554 			{
555 				VR_ShutdownInternal();
556 				eError = EVRInitError.Init_InterfaceNotFound;
557 			}
558 		}
559 
560 		if (peError)
561 			*peError = eError;
562 		return pVRSystem;
563 	}
564 
565 	/** unloads vrclient.dll. Any interface pointers from the interface are
566 * invalid after this point */
567 	pragma(inline, true) void VR_Shutdown()
568 	{
569 		VR_ShutdownInternal();
570 	}
571 
572 }