1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-01-16 12:49:56 +00:00
openmw-tes3mp/apps/openmw/mwvr/vrgui.hpp

211 lines
7.4 KiB
C++
Raw Normal View History

#ifndef VRGUI_HPP
#define VRGUI_HPP
#include <map>
#include <set>
#include <regex>
2020-05-12 20:13:01 +00:00
#include <MyGUI_Widget.h>
#include <osg/Geometry>
#include <osg/TexMat>
#include <osg/Texture2D>
#include <osg/Camera>
#include <osg/PositionAttitudeTransform>
#include "vrview.hpp"
#include "openxrmanager.hpp"
namespace MyGUI
{
class Widget;
class Window;
}
namespace MWGui
{
class Layout;
class WindowBase;
class ILayer;
}
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-06-28 09:33:01 +00:00
/// Configuration of a VRGUILayer
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.
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
TrackingMode trackingMode; //!< Tracking mode
std::string extraLayers; //!< Additional layers to draw (list separated by any non-alphabetic)
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-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.
class VRGUILayer
{
public:
VRGUILayer(
osg::ref_ptr<osg::Group> geometryRoot,
osg::ref_ptr<osg::Group> cameraRoot,
MyGUI::ILayer* layer,
LayerConfig config,
VRGUIManager* parent);
~VRGUILayer();
2020-06-28 09:33:01 +00:00
void update();
2020-06-28 09:33:01 +00:00
protected:
friend class VRGUIManager;
osg::Camera* camera();
osg::ref_ptr<osg::Texture2D> menuTexture();
2020-05-12 20:13:01 +00:00
void setAngle(float angle);
void updateTracking(const Pose& headPose = {});
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; }
public:
Pose mTrackedPose{};
LayerConfig mConfig;
std::string mLayerName;
MyGUI::ILayer* mMyGUILayer;
2020-05-12 20:13:01 +00:00
std::vector<MWGui::Layout*> mWidgets;
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-06-28 09:33:01 +00:00
/// \brief osg user data used to refer back to VRGUILayer objects when intersecting with the scene graph.
class VRGUILayerUserData : public osg::Referenced
{
public:
2020-05-12 20:13:01 +00:00
VRGUILayerUserData(std::shared_ptr<VRGUILayer> layer) : mLayer(layer) {};
2020-05-12 20:13:01 +00:00
std::weak_ptr<VRGUILayer> mLayer;
};
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.
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
void setVisible(MWGui::Layout*, bool visible);
2020-06-28 09:33:01 +00:00
/// Insert the given layer quad if it isn't already
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
void removeLayer(MyGUI::ILayer* layer);
2020-05-12 20:13:01 +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
/// 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
bool updateFocus();
/// 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; };
/// Inject mouse click if applicable
bool injectMouseClick(bool onPress);
/// 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-11-29 12:14:00 +00:00
void processChangedSettings(const std::set< std::pair<std::string, std::string> >& changed);
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);
void setFocusWidget(MyGUI::Widget* widget);
bool validateFocusWidget();
bool focusIsModalWindow();
MyGUI::Widget* widgetFromGuiCursor(int x, int y);
void updateGuiCursor(int x, int y);
2020-11-29 12:14:00 +00:00
void configUpdated(const std::string& layer);
2020-05-12 20:13: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;
bool mShouldUpdatePoses{ true };
2020-05-12 20:13:01 +00:00
Pose mHeadPose{};
osg::Vec2i mGuiCursor{};
VRGUILayer* mFocusLayer{ nullptr };
MyGUI::Widget* mFocusWidget{ nullptr };
MyGUI::Widget* mModalWindow{ nullptr };
osg::observer_ptr<osg::Camera> mCamera{ nullptr };
2020-11-28 18:41:09 +00:00
std::map<std::string, LayerConfig> mLayerConfigs{};
};
}
#endif