2020-11-27 20:47:20 +00:00
# ifndef VRGUI_HPP
# define VRGUI_HPP
2020-05-01 19:37:01 +00:00
# include <map>
# include <set>
# include <regex>
2020-05-12 20:13:01 +00:00
# include <MyGUI_Widget.h>
2020-05-01 19:37:01 +00:00
# include <osg/Geometry>
# include <osg/TexMat>
# include <osg/Texture2D>
# include <osg/Camera>
# include <osg/PositionAttitudeTransform>
2020-05-24 16:00:42 +00:00
# include "vrview.hpp"
# include "openxrmanager.hpp"
2020-05-01 19:37:01 +00:00
namespace MyGUI
{
2020-06-26 21:02:48 +00:00
class Widget ;
class Window ;
2020-05-01 19:37:01 +00:00
}
namespace MWGui
{
2020-06-26 21:02:48 +00:00
class Layout ;
class WindowBase ;
2020-11-27 20:47:20 +00:00
class ILayer ;
2020-05-01 19:37:01 +00:00
}
struct XrCompositionLayerQuad ;
namespace MWVR
{
class GUICamera ;
class VRGUIManager ;
enum class TrackingMode
{
2020-05-12 20:13:01 +00:00
Menu , //!< Menu quads with fixed position based on head tracking.
HudLeftHand , //!< Hud quads tracking the left hand every frame
HudRightHand , //!< Hud quads tracking the right hand every frame
} ;
// Some UI elements should occupy predefined geometries
// Others should grow/shrink freely
enum class SizingMode
{
Auto ,
Fixed
2020-05-01 19:37:01 +00:00
} ;
2020-06-28 09:33:01 +00:00
/// Configuration of a VRGUILayer
2020-05-01 19:37:01 +00:00
struct LayerConfig
{
2020-06-28 09:33:01 +00:00
int priority ; //!< Higher priority shows over lower priority windows by moving higher priority layers slightly closer to the player.
bool sideBySide ; //!< All layers with this config will show up side by side in a partial circle around the player, and will all be resized to a predefined size.
2020-05-01 19:37:01 +00:00
osg : : Vec4 backgroundColor ; //!< Background color of layer
osg : : Vec3 offset ; //!< Offset from tracked node in meters
2020-05-12 20:13:01 +00:00
osg : : Vec2 center ; //!< Model space centerpoint of menu geometry. All menu geometries have model space lengths of 1 in each dimension. Use this to affect how geometries grow with changing size.
osg : : Vec2 extent ; //!< Spatial extent of the layer in meters when using Fixed sizing mode
int spatialResolution ; //!< Pixels when using the Auto sizing mode. \note Meters per pixel of the GUI viewport, not the RTT texture.
osg : : Vec2i pixelResolution ; //!< Pixel resolution of the RTT texture
osg : : Vec2 myGUIViewSize ; //!< Resizable elements are resized to this (fraction of full view)
SizingMode sizingMode ; //!< How to size the layer
2020-05-01 19:37:01 +00:00
TrackingMode trackingMode ; //!< Tracking mode
2020-05-17 14:25:51 +00:00
std : : string extraLayers ; //!< Additional layers to draw (list separated by any non-alphabetic)
2020-11-27 20:47:20 +00:00
bool ignoreModality ; //!< Layer input should be enabled even if another modal window is active
2020-05-12 20:13:01 +00:00
bool operator < ( const LayerConfig & rhs ) const { return priority < rhs . priority ; }
2020-05-01 19:37:01 +00:00
} ;
2020-06-28 09:33:01 +00:00
/// \brief A single VR GUI Quad.
///
/// In VR menus are shown as quads within the game world.
/// The behaviour of that quad is defined by the MWVR::LayerConfig struct
/// Each instance of VRGUILayer is used to show one MYGUI layer.
2020-05-01 19:37:01 +00:00
class VRGUILayer
{
public :
VRGUILayer (
osg : : ref_ptr < osg : : Group > geometryRoot ,
osg : : ref_ptr < osg : : Group > cameraRoot ,
2020-11-27 20:47:20 +00:00
MyGUI : : ILayer * layer ,
2020-05-01 19:37:01 +00:00
LayerConfig config ,
VRGUIManager * parent ) ;
~ VRGUILayer ( ) ;
2020-06-28 09:33:01 +00:00
void update ( ) ;
2020-05-01 19:37:01 +00:00
2020-06-28 09:33:01 +00:00
protected :
friend class VRGUIManager ;
osg : : Camera * camera ( ) ;
2020-05-01 19:37:01 +00:00
osg : : ref_ptr < osg : : Texture2D > menuTexture ( ) ;
2020-05-12 20:13:01 +00:00
void setAngle ( float angle ) ;
void updateTracking ( const Pose & headPose = { } ) ;
2020-05-01 19:37:01 +00:00
void updatePose ( ) ;
2020-05-12 20:13:01 +00:00
void updateRect ( ) ;
void insertWidget ( MWGui : : Layout * widget ) ;
void removeWidget ( MWGui : : Layout * widget ) ;
int widgetCount ( ) { return mWidgets . size ( ) ; }
bool operator < ( const VRGUILayer & rhs ) const { return mConfig . priority < rhs . mConfig . priority ; }
2020-05-01 19:37:01 +00:00
public :
Pose mTrackedPose { } ;
LayerConfig mConfig ;
2020-05-17 14:25:51 +00:00
std : : string mLayerName ;
2020-11-27 20:47:20 +00:00
MyGUI : : ILayer * mMyGUILayer ;
2020-05-12 20:13:01 +00:00
std : : vector < MWGui : : Layout * > mWidgets ;
2020-05-01 19:37:01 +00:00
osg : : ref_ptr < osg : : Group > mGeometryRoot ;
osg : : ref_ptr < osg : : Geometry > mGeometry { new osg : : Geometry } ;
osg : : ref_ptr < osg : : PositionAttitudeTransform > mTransform { new osg : : PositionAttitudeTransform } ;
osg : : ref_ptr < osg : : Group > mCameraRoot ;
osg : : ref_ptr < GUICamera > mGUICamera ;
2020-05-12 20:13:01 +00:00
osg : : ref_ptr < osg : : Camera > mMyGUICamera { nullptr } ;
MyGUI : : FloatRect mRealRect { } ;
osg : : Quat mRotation { 0 , 0 , 0 , 1 } ;
2020-05-01 19:37:01 +00:00
} ;
2020-06-28 09:33:01 +00:00
/// \brief osg user data used to refer back to VRGUILayer objects when intersecting with the scene graph.
2020-05-01 19:37:01 +00:00
class VRGUILayerUserData : public osg : : Referenced
{
public :
2020-05-12 20:13:01 +00:00
VRGUILayerUserData ( std : : shared_ptr < VRGUILayer > layer ) : mLayer ( layer ) { } ;
2020-05-01 19:37:01 +00:00
2020-05-12 20:13:01 +00:00
std : : weak_ptr < VRGUILayer > mLayer ;
2020-05-01 19:37:01 +00:00
} ;
2020-06-28 09:33:01 +00:00
/// \brief Manager of VRGUILayer objects.
///
/// Constructs and destructs VRGUILayer objects in response to MWGui::Layout::setVisible calls.
/// Layers can also be made visible directly by calling insertLayer() directly, e.g. to show
/// the video player.
2020-05-01 19:37:01 +00:00
class VRGUIManager
{
public :
VRGUIManager (
osg : : ref_ptr < osgViewer : : Viewer > viewer ) ;
~ VRGUIManager ( void ) ;
2020-06-28 09:33:01 +00:00
/// Set visibility of the layer this layout is on
2020-05-01 19:37:01 +00:00
void setVisible ( MWGui : : Layout * , bool visible ) ;
2020-06-28 09:33:01 +00:00
/// Insert the given layer quad if it isn't already
2020-11-27 20:47:20 +00:00
void insertLayer ( MyGUI : : ILayer * layer ) ;
2020-05-12 20:13:01 +00:00
2020-06-28 09:33:01 +00:00
/// Remove the given layer quad
2020-11-27 20:47:20 +00:00
void removeLayer ( MyGUI : : ILayer * layer ) ;
2020-05-12 20:13:01 +00:00
2020-10-21 19:22:38 +00:00
/// Update layer quads based on current camera
2020-05-12 20:13:01 +00:00
void updateTracking ( void ) ;
2020-06-28 09:33:01 +00:00
2020-10-21 19:22:38 +00:00
/// Set camera on which to base tracking
void setCamera ( osg : : Camera * camera ) ;
2020-05-12 20:13:01 +00:00
2020-06-28 09:33:01 +00:00
/// Check current pointer target and update focus layer
2020-05-17 14:25:51 +00:00
bool updateFocus ( ) ;
2020-05-01 19:37:01 +00:00
2020-10-21 19:22:38 +00:00
/// Update traversal
void update ( ) ;
2020-06-28 09:33:01 +00:00
/// Gui cursor coordinates to use to simulate a mouse press/move if the player is currently pointing at a vr gui layer
2020-05-12 20:13:01 +00:00
osg : : Vec2i guiCursor ( ) { return mGuiCursor ; } ;
2020-11-14 18:13:16 +00:00
/// Inject mouse click if applicable
bool injectMouseClick ( bool onPress ) ;
2020-11-27 20:47:20 +00:00
/// Notify VRGUIManager that a widget has been unlinked
void notifyWidgetUnlinked ( MyGUI : : Widget * widget ) ;
/// Notify VRGUIManager that a window is modal
void notifyModalWindow ( MyGUI : : Widget * window ) ;
/// Currently focus widget according to VR
MyGUI : : Widget * focusWidget ( ) { return mFocusWidget ; }
2020-05-01 19:37:01 +00:00
private :
2020-05-12 20:13:01 +00:00
void computeGuiCursor ( osg : : Vec3 hitPoint ) ;
2020-06-28 09:33:01 +00:00
void updateSideBySideLayers ( ) ;
void insertWidget ( MWGui : : Layout * widget ) ;
void removeWidget ( MWGui : : Layout * widget ) ;
void setFocusLayer ( VRGUILayer * layer ) ;
2020-11-14 18:13:16 +00:00
void setFocusWidget ( MyGUI : : Widget * widget ) ;
2020-11-27 20:47:20 +00:00
bool validateFocusWidget ( ) ;
bool focusIsModalWindow ( ) ;
MyGUI : : Widget * widgetFromGuiCursor ( int x , int y ) ;
void updateGuiCursor ( int x , int y ) ;
2020-05-12 20:13:01 +00:00
2020-05-01 19:37:01 +00:00
osg : : ref_ptr < osgViewer : : Viewer > mOsgViewer { nullptr } ;
osg : : ref_ptr < osg : : Group > mGUIGeometriesRoot { new osg : : Group } ;
osg : : ref_ptr < osg : : Group > mGUICamerasRoot { new osg : : Group } ;
2020-05-12 20:13:01 +00:00
std : : map < std : : string , std : : shared_ptr < VRGUILayer > > mLayers ;
std : : vector < std : : shared_ptr < VRGUILayer > > mSideBySideLayers ;
2020-05-01 19:37:01 +00:00
2020-10-21 19:22:38 +00:00
bool mShouldUpdatePoses { true } ;
2020-05-12 20:13:01 +00:00
Pose mHeadPose { } ;
osg : : Vec2i mGuiCursor { } ;
2020-05-01 19:37:01 +00:00
VRGUILayer * mFocusLayer { nullptr } ;
2020-11-14 18:13:16 +00:00
MyGUI : : Widget * mFocusWidget { nullptr } ;
2020-11-27 20:47:20 +00:00
MyGUI : : Widget * mModalWindow { nullptr } ;
2020-10-21 19:22:38 +00:00
osg : : observer_ptr < osg : : Camera > mCamera { nullptr } ;
2020-11-28 18:41:09 +00:00
std : : map < std : : string , LayerConfig > mLayerConfigs { } ;
2020-05-01 19:37:01 +00:00
} ;
}
# endif