// -*-c++-*- // SPDX-License-Identifier: LGPL-2.1-only // Copyright (C) 2021 James Hogan #ifndef OSGXR_Manager #define OSGXR_Manager 1 #include #include #include #include #include #include #include #include #include #include namespace osgXR { // Internal state class class XRState; /** * Public VR state manager class. * Applications can extend this class to allow tighter integration with osgXR. */ class OSGXR_EXPORT Manager : public osgViewer::ViewConfig { public: Manager(); virtual ~Manager(); /// Use if viewer is a CompositeViewer. void setViewer(osgViewer::ViewerBase *viewer) { _viewer = viewer; } /// Set the NodeMasks to use for visibility masks. void setVisibilityMaskNodeMasks(osg::Node::NodeMask left, osg::Node::NodeMask right) const; void configure(osgViewer::View& view) const override; /** * Perform a regular update. * This will poll for OpenXR events, and handle any pending VR start / * stop operations (possibly invoking the Manager's view callbacks). * Some of these operations require threading on the viewer to be * temporarily stopped, but in all cases it is started again. */ virtual void update(); /// Find whether state has changed since last call, and reset. bool checkAndResetStateChanged(); /// Find whether VR seems to be present. bool getPresent() const; /** * Get whether VR is currently set to be enabled. * When enabled, osgXR will try to keep VR running. * @return Whether VR is enabled */ bool getEnabled() const; /** * Set whether VR is currently set to be enabled. * When enabled, osgXR will try to keep VR running. * @param enabled Whether VR is enabled. */ void setEnabled(bool enabled); /** * Start destroying the VR state and wait for safe shutdown. */ void destroyAndWait(); /** * Find whether this manager is in the process of being destroyed. */ bool isDestroying() const; /** * Get whether a VR session is currently running. * @return Whether a VR session is currently running. */ bool isRunning() const; /// Arrange reinit as needed for new settings. void syncSettings(); /// Arrange reinit as needed of action setup. void syncActionSetup(); /* * OpenXR information. */ /** * Find whether OpenXR's validation layer is supported. * This looks to see whether the OpenXR validation API layer (i.e. * XR_APILAYER_LUNARG_core_validation) is available. */ bool hasValidationLayer() const; /** * Find whether OpenXR supports the submission of depth information. * This looks to see whether the OpenXR instance extension for * submitting depth information to help the runtime perform better * reprojection (i.e. XR_KHR_composition_layer_depth) is available. */ bool hasDepthInfoExtension() const; /** * Find whether OpenXR supports the visibility mask extension. * This looks to see whether the OpenXR instance extension for getting * visibility masks is available, which can be used to reduce fragment * load. */ bool hasVisibilityMaskExtension() const; /// Find the name of the OpenXR runtime. const char *getRuntimeName() const; /// Find the name of the OpenXR system in use. const char *getSystemName() const; /// Get a string describing the state (for user consumption). const char *getStateString() const; /* * For implementation by derived classes. */ /** * Callback telling the app to configure a new view. * This callback allows osgXR to tell the app to configure a new view of * the world. The application should notify osgXR of the addition and * removal of slave cameras which osgXR should hook into using the * osgXR::View parameter. * The implementation may stop threading, and it will be started again * before update() returns. * @param xrView The new osgXR::View with a public API to allow the * application to retrieve what it needs in relation to * the view and to inform osgXR of changes. */ virtual void doCreateView(View *xrView) = 0; /** * Callback telling the app to destroy an existing view. * This callback allows osgXR to tell the app to remove an existing view * of the world that it had requested via doCreateView(). The * application should notify osgXR of the removal of any slave cameras * which it has already informed osgXR about. * The implementation may stop threading, and it will be started again * before update() returns. */ virtual void doDestroyView(View *xrView) = 0; /** * Callback telling the app that the VR session is now running. * This happens after the OpenXR session has started running, and views * have been configured (see doCreateView()). The app should start * rendering the VR views, and may choose to reconfigure the desktop * window to make a VR mirror visible. */ virtual void onRunning(); /** * Callback telling the app that the VR session has now stopped. * This happens after the OpenXR session has stopped, and views have * been removed (see doDestroyView()). The app should stop rendering the * VR views, and may choose to reconfigure the desktop window so as to * no longer show a VR mirror. */ virtual void onStopped(); /** * Callback telling the app that the VR session is in focus. * This happens when the VR session enters focus and can get VR input * from the user. The app may choose to resume the experience if it was * previously paused due to onUnfocus(). */ virtual void onFocus(); /** * Callback telling the app that the VR session is no longer in focus. * This happens when the VR session leaves focus and can no longer get * VR input from the user. The VR runtime may be presenting a modal * pop-up on top of the application's rendered frames. The app may * choose to pause the experience. */ virtual void onUnfocus(); /// Add a custom mirror to the queue of mirrors to configure. void addMirror(Mirror *mirror); /// Set up a camera to render a VR mirror. void setupMirrorCamera(osg::Camera *camera); /* * Internal */ inline Settings *_getSettings() { return _settings.get(); } inline XRState *_getXrState() { return _state; } void _setupMirrors(); protected: osg::ref_ptr _viewer; osg::ref_ptr _settings; bool _destroying; private: std::list > _mirrorQueue; osg::ref_ptr _state; }; } #endif