#ifndef OPENXR_MENU_HPP #define OPENXR_MENU_HPP #include #include #include #include #include #include #include #include #include #include "vrview.hpp" #include "openxrmanager.hpp" namespace MyGUI { class Widget; class Window; } namespace MWGui { class Layout; class WindowBase; } struct XrCompositionLayerQuad; namespace MWVR { class GUICamera; class VRGUIManager; enum class TrackingMode { 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 }; struct LayerConfig { int priority; //!< Higher priority shows over lower priority windows. bool sideBySide; //!< Resize layer window to occupy full quad osg::Vec4 backgroundColor; //!< Background color of layer osg::Vec3 offset; //!< Offset from tracked node in meters 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 TrackingMode trackingMode; //!< Tracking mode std::string extraLayers; //!< Additional layers to draw (list separated by any non-alphabetic) bool operator<(const LayerConfig& rhs) const { return priority < rhs.priority; } }; class VRGUILayer { public: VRGUILayer( osg::ref_ptr geometryRoot, osg::ref_ptr cameraRoot, std::string layerName, LayerConfig config, VRGUIManager* parent); ~VRGUILayer(); osg::Camera* camera(); osg::ref_ptr menuTexture(); void setAngle(float angle); void updateTracking(const Pose& headPose = {}); void updatePose(); void updateRect(); void update(); 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; } public: Pose mTrackedPose{}; LayerConfig mConfig; std::string mLayerName; std::vector mWidgets; osg::ref_ptr mGeometryRoot; osg::ref_ptr mGeometry{ new osg::Geometry }; osg::ref_ptr mTransform{ new osg::PositionAttitudeTransform }; osg::ref_ptr mCameraRoot; osg::ref_ptr mGUICamera; osg::ref_ptr mMyGUICamera{ nullptr }; MyGUI::FloatRect mRealRect{}; osg::Quat mRotation{ 0,0,0,1 }; }; class VRGUILayerUserData : public osg::Referenced { public: VRGUILayerUserData(std::shared_ptr layer) : mLayer(layer) {}; std::weak_ptr mLayer; }; class VRGUIManager { public: VRGUIManager( osg::ref_ptr viewer); ~VRGUIManager(void); void setVisible(MWGui::Layout*, bool visible); void updateSideBySideLayers(); void insertLayer(const std::string& name); void insertWidget(MWGui::Layout* widget); void removeLayer(const std::string& name); void removeWidget(MWGui::Layout* widget); void updateTracking(void); bool updateFocus(); void setFocusLayer(VRGUILayer* layer); osg::Vec2i guiCursor() { return mGuiCursor; }; private: void computeGuiCursor(osg::Vec3 hitPoint); osg::ref_ptr mOsgViewer{ nullptr }; osg::ref_ptr mGUIGeometriesRoot{ new osg::Group }; osg::ref_ptr mGUICamerasRoot{ new osg::Group }; std::map> mLayers; std::vector > mSideBySideLayers; Pose mHeadPose{}; osg::Vec2i mGuiCursor{}; VRGUILayer* mFocusLayer{ nullptr }; }; } #endif