mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-30 15:15:31 +00:00
Separate rendering of window menus. It's still awkward. Needs polishing.
This commit is contained in:
parent
7eaf015b87
commit
57e48cfc03
55 changed files with 1674 additions and 631 deletions
|
@ -122,14 +122,14 @@ if(BUILD_VR_OPENXR)
|
|||
mwvr/openxrmanager.cpp
|
||||
mwvr/openxrmanagerimpl.hpp
|
||||
mwvr/openxrmanagerimpl.cpp
|
||||
mwvr/openxrmenu.hpp
|
||||
mwvr/openxrmenu.cpp
|
||||
mwvr/vrgui.hpp
|
||||
mwvr/vrgui.cpp
|
||||
mwvr/openxrsession.hpp
|
||||
mwvr/openxrsession.cpp
|
||||
mwvr/openxrswapchain.hpp
|
||||
mwvr/openxrswapchain.cpp
|
||||
mwvr/openxrtexture.hpp
|
||||
mwvr/openxrtexture.cpp
|
||||
mwvr/vrtexture.hpp
|
||||
mwvr/vrtexture.cpp
|
||||
mwvr/openxrview.hpp
|
||||
mwvr/openxrview.cpp
|
||||
mwvr/openxrviewer.hpp
|
||||
|
|
|
@ -562,18 +562,16 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
|
|||
MWGui::WindowManager* window = new MWGui::WindowManager(mViewer, guiRoot, mResourceSystem.get(), mWorkQueue.get(),
|
||||
mCfgMgr.getLogPath().string() + std::string("/"), myguiResources,
|
||||
mScriptConsoleMode, mTranslationDataStorage, mEncoding, mExportFonts,
|
||||
Version::getOpenmwVersionDescription(mResDir.string()), mCfgMgr.getUserConfigPath().string(),
|
||||
#ifdef USE_OPENXR
|
||||
true
|
||||
#else
|
||||
false
|
||||
#endif
|
||||
);
|
||||
Version::getOpenmwVersionDescription(mResDir.string()), mCfgMgr.getUserConfigPath().string());
|
||||
mEnvironment.setWindowManager (window);
|
||||
|
||||
// Create sound system
|
||||
mEnvironment.setSoundManager (new MWSound::SoundManager(mVFS.get(), mUseSound));
|
||||
|
||||
#ifdef USE_OPENXR
|
||||
mXrEnvironment.setGUIManager(new MWVR::VRGUIManager(mViewer));
|
||||
#endif
|
||||
|
||||
if (!mSkipMenu)
|
||||
{
|
||||
const std::string& logo = Fallback::Map::getString("Movies_Company_Logo");
|
||||
|
@ -745,7 +743,7 @@ void OMW::Engine::go()
|
|||
auto* xrViewer = MWVR::Environment::get().getViewer();
|
||||
xrViewer->addChild(root);
|
||||
mViewer->setSceneData(xrViewer);
|
||||
mXrEnvironment.setMenuManager(new MWVR::OpenXRMenuManager(mViewer));
|
||||
mXrEnvironment.setGUIManager(new MWVR::VRGUIManager(mViewer));
|
||||
#endif
|
||||
|
||||
// Start the game
|
||||
|
|
|
@ -66,7 +66,11 @@ namespace MWGui
|
|||
|
||||
|
||||
HUD::HUD(CustomMarkerCollection &customMarkers, DragAndDrop* dragAndDrop, MWRender::LocalMap* localMapRender)
|
||||
#ifdef USE_OPENXR
|
||||
: WindowBase("openmw_hud_vr.layout")
|
||||
#else
|
||||
: WindowBase("openmw_hud.layout")
|
||||
#endif
|
||||
, LocalMapBase(customMarkers, localMapRender, Settings::Manager::getBool("local map hud fog of war", "Map"))
|
||||
, mHealth(nullptr)
|
||||
, mMagicka(nullptr)
|
||||
|
@ -99,7 +103,10 @@ namespace MWGui
|
|||
, mIsDrowning(false)
|
||||
, mDrowningFlashTheta(0.f)
|
||||
{
|
||||
#ifndef USE_OPENXR
|
||||
mMainWidget->setSize(MyGUI::RenderManager::getInstance().getViewSize());
|
||||
#endif
|
||||
mMainWidgetBaseSize = mMainWidget->getSize();
|
||||
|
||||
// Energy bars
|
||||
getWidget(mHealthFrame, "HealthFrame");
|
||||
|
@ -374,6 +381,9 @@ namespace MWGui
|
|||
mDrowningFlashTheta += dt * osg::PI*2;
|
||||
|
||||
mSpellIcons->updateWidgets(mEffectBox, true);
|
||||
Log(Debug::Verbose) << "Size: " << mMainWidget->getSize();
|
||||
Log(Debug::Verbose) << "width: " << mMainWidget->getWidth();
|
||||
Log(Debug::Verbose) << "height: " << mMainWidget->getHeight();
|
||||
|
||||
if (mEnemyActorId != -1 && mEnemyHealth->getVisible())
|
||||
{
|
||||
|
@ -587,6 +597,7 @@ namespace MWGui
|
|||
|
||||
const MyGUI::IntSize& viewSize = MyGUI::RenderManager::getInstance().getViewSize();
|
||||
|
||||
#ifndef USE_OPENXR
|
||||
// effect box can have variable width -> variable left coordinate
|
||||
int effectsDx = 0;
|
||||
if (!mMinimapBox->getVisible ())
|
||||
|
@ -597,6 +608,11 @@ namespace MWGui
|
|||
mCellNameBox->setVisible(false);
|
||||
|
||||
mEffectBox->setPosition((viewSize.width - mEffectBoxBaseRight) - mEffectBox->getWidth() + effectsDx, mEffectBox->getTop());
|
||||
#else
|
||||
// in VR mode, the effect box grows to the right and does not need repositioning
|
||||
int width = std::max(mMainWidgetBaseSize.width, mEffectBox->getSize().width);
|
||||
mMainWidget->setSize(width, mMainWidget->getHeight());
|
||||
#endif
|
||||
}
|
||||
|
||||
void HUD::updateEnemyHealthBar()
|
||||
|
|
|
@ -80,6 +80,8 @@ namespace MWGui
|
|||
int mHealthManaStaminaBaseLeft, mWeapBoxBaseLeft, mSpellBoxBaseLeft, mSneakBoxBaseLeft;
|
||||
// bottom right elements
|
||||
int mMinimapBoxBaseRight, mEffectBoxBaseRight;
|
||||
// initial size
|
||||
MyGUI::IntSize mMainWidgetBaseSize;
|
||||
|
||||
DragAndDrop* mDragAndDrop;
|
||||
|
||||
|
|
|
@ -56,7 +56,11 @@ namespace MWGui
|
|||
{
|
||||
|
||||
InventoryWindow::InventoryWindow(DragAndDrop* dragAndDrop, osg::Group* parent, Resource::ResourceSystem* resourceSystem)
|
||||
#ifdef USE_OPENXR
|
||||
: WindowPinnableBase("openmw_inventory_window_vr.layout")
|
||||
#else
|
||||
: WindowPinnableBase("openmw_inventory_window.layout")
|
||||
#endif
|
||||
, mDragAndDrop(dragAndDrop)
|
||||
, mSelectedItem(-1)
|
||||
, mSortModel(nullptr)
|
||||
|
|
|
@ -119,7 +119,7 @@ namespace MWGui
|
|||
void sellItem(MyGUI::Widget* sender, int count);
|
||||
void dragItem(MyGUI::Widget* sender, int count);
|
||||
|
||||
void onWindowResize(MyGUI::Window* _sender);
|
||||
void onWindowResize(MyGUI::Window* _sender) override;
|
||||
void onFilterChanged(MyGUI::Widget* _sender);
|
||||
void onNameFilterChanged(MyGUI::EditBox* _sender);
|
||||
void onAvatarClicked(MyGUI::Widget* _sender);
|
||||
|
|
|
@ -5,6 +5,13 @@
|
|||
#include <MyGUI_Gui.h>
|
||||
#include <MyGUI_TextBox.h>
|
||||
#include <MyGUI_Window.h>
|
||||
#include <MyGUI_OverlappedLayer.h>
|
||||
#include <MyGUI_SharedLayer.h>
|
||||
|
||||
#ifdef USE_OPENXR
|
||||
#include "../mwvr/vrgui.hpp"
|
||||
#include "../mwvr/vrenvironment.hpp"
|
||||
#endif
|
||||
|
||||
namespace MWGui
|
||||
{
|
||||
|
@ -44,9 +51,21 @@ namespace MWGui
|
|||
mMainWidget->setCoord(x,y,w,h);
|
||||
}
|
||||
|
||||
void Layout::setCoordf(float x, float y, float w, float h)
|
||||
{
|
||||
mMainWidget->setRealCoord(x, y, w, h);
|
||||
}
|
||||
|
||||
void Layout::setVisible(bool b)
|
||||
{
|
||||
mMainWidget->setVisible(b);
|
||||
#ifdef USE_OPENXR
|
||||
auto* vrGUIManager = MWVR::Environment::get().getGUIManager();
|
||||
if (!vrGUIManager)
|
||||
// May end up here before before rendering has been fully set up
|
||||
return;
|
||||
vrGUIManager->setVisible(this, b);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Layout::setText(const std::string &name, const std::string &caption)
|
||||
|
@ -64,6 +83,18 @@ namespace MWGui
|
|||
window->setCaptionWithReplacing(title);
|
||||
}
|
||||
|
||||
void Layout::setLayerPick(bool pick)
|
||||
{
|
||||
MyGUI::ILayer* layer = mMainWidget->getLayer();
|
||||
// MyGUI exposes pick on the implementations of ILayer only, but not ILayer itself.
|
||||
auto* oLayer = layer->castType<MyGUI::OverlappedLayer>(false);
|
||||
auto* sLayer = layer->castType<MyGUI::SharedLayer>(false);
|
||||
if (oLayer)
|
||||
oLayer->setPick(pick);
|
||||
if (sLayer)
|
||||
sLayer->setPick(pick);
|
||||
}
|
||||
|
||||
MyGUI::Widget* Layout::getWidget(const std::string &_name)
|
||||
{
|
||||
for (MyGUI::Widget* widget : mListWindowRoot)
|
||||
|
|
|
@ -55,6 +55,7 @@ namespace MWGui
|
|||
|
||||
public:
|
||||
void setCoord(int x, int y, int w, int h);
|
||||
void setCoordf(float x, float y, float w, float h);
|
||||
|
||||
virtual void setVisible(bool b);
|
||||
|
||||
|
@ -63,6 +64,9 @@ namespace MWGui
|
|||
// NOTE: this assume that mMainWidget is of type Window.
|
||||
void setTitle(const std::string& title);
|
||||
|
||||
/// \note Affects the layer, not just the widget.
|
||||
void setLayerPick(bool pick);
|
||||
|
||||
MyGUI::Widget* mMainWidget;
|
||||
|
||||
protected:
|
||||
|
|
|
@ -640,7 +640,11 @@ namespace MWGui
|
|||
// ------------------------------------------------------------------------------------------
|
||||
|
||||
MapWindow::MapWindow(CustomMarkerCollection &customMarkers, DragAndDrop* drag, MWRender::LocalMap* localMapRender, SceneUtil::WorkQueue* workQueue)
|
||||
#ifdef USE_OPENXR
|
||||
: WindowPinnableBase("openmw_map_window_vr.layout")
|
||||
#else
|
||||
: WindowPinnableBase("openmw_map_window.layout")
|
||||
#endif
|
||||
, LocalMapBase(customMarkers, localMapRender)
|
||||
, NoDrop(drag, mMainWidget)
|
||||
, mGlobalMap(0)
|
||||
|
|
|
@ -65,8 +65,14 @@ namespace MWGui
|
|||
|
||||
int w=2;
|
||||
|
||||
for(auto rit = effects.rbegin(); rit != effects.rend(); rit++)
|
||||
{
|
||||
auto& effectInfoPair = *rit;
|
||||
#if 0
|
||||
// in VR mode, the effect box grows to the right so we want to invert the order to avoid reordering effects.
|
||||
for (auto& effectInfoPair : effects)
|
||||
{
|
||||
#endif
|
||||
const int effectId = effectInfoPair.first;
|
||||
const ESM::MagicEffect* effect =
|
||||
MWBase::Environment::get().getWorld ()->getStore ().get<ESM::MagicEffect>().find(effectId);
|
||||
|
@ -192,7 +198,10 @@ namespace MWGui
|
|||
s = 0;
|
||||
int diff = parent->getWidth() - s;
|
||||
parent->setSize(s, parent->getHeight());
|
||||
#ifndef USE_OPENXR
|
||||
// in VR mode, the effect box grows to the right and does not need repositioning
|
||||
parent->setPosition(parent->getLeft()+diff, parent->getTop());
|
||||
#endif
|
||||
}
|
||||
|
||||
// hide inactive effects
|
||||
|
|
|
@ -31,7 +31,11 @@ namespace MWGui
|
|||
{
|
||||
|
||||
SpellWindow::SpellWindow(DragAndDrop* drag)
|
||||
#ifdef USE_OPENXR
|
||||
: WindowPinnableBase("openmw_spell_window_vr.layout")
|
||||
#else
|
||||
: WindowPinnableBase("openmw_spell_window.layout")
|
||||
#endif
|
||||
, NoDrop(drag, mMainWidget)
|
||||
, mSpellView(nullptr)
|
||||
, mUpdateTimer(0.0f)
|
||||
|
|
|
@ -25,7 +25,11 @@
|
|||
namespace MWGui
|
||||
{
|
||||
StatsWindow::StatsWindow (DragAndDrop* drag)
|
||||
#ifdef USE_OPENXR
|
||||
: WindowPinnableBase("openmw_stats_window_vr.layout")
|
||||
#else
|
||||
: WindowPinnableBase("openmw_stats_window.layout")
|
||||
#endif
|
||||
, NoDrop(drag, mMainWidget)
|
||||
, mSkillView(nullptr)
|
||||
, mMajorSkills()
|
||||
|
|
|
@ -50,7 +50,7 @@ namespace MWGui
|
|||
void setExpelled (const std::set<std::string>& expelled);
|
||||
void setBirthSign (const std::string &signId);
|
||||
|
||||
void onWindowResize(MyGUI::Window* window);
|
||||
void onWindowResize(MyGUI::Window* window) override;
|
||||
void onMouseWheel(MyGUI::Widget* _sender, int _rel);
|
||||
|
||||
MyGUI::Widget* mLeftPane;
|
||||
|
|
|
@ -12,6 +12,11 @@
|
|||
#include "draganddrop.hpp"
|
||||
#include "exposedwindow.hpp"
|
||||
|
||||
#ifdef USE_OPENXR
|
||||
#include "../mwvr/vrgui.hpp"
|
||||
#include "../mwvr/vrenvironment.hpp"
|
||||
#endif
|
||||
|
||||
using namespace MWGui;
|
||||
|
||||
WindowBase::WindowBase(const std::string& parLayout)
|
||||
|
@ -48,6 +53,7 @@ void WindowBase::onDoubleClick(MyGUI::Widget *_sender)
|
|||
|
||||
void WindowBase::setVisible(bool visible)
|
||||
{
|
||||
Log(Debug::Verbose) << mLayoutName << ".setVisible: " << visible;
|
||||
bool wasVisible = mMainWidget->getVisible();
|
||||
mMainWidget->setVisible(visible);
|
||||
|
||||
|
@ -55,6 +61,14 @@ void WindowBase::setVisible(bool visible)
|
|||
onOpen();
|
||||
else if (wasVisible)
|
||||
onClose();
|
||||
|
||||
#ifdef USE_OPENXR
|
||||
auto* vrGUIManager = MWVR::Environment::get().getGUIManager();
|
||||
if (!vrGUIManager)
|
||||
// May end up here before before rendering has been fully set up
|
||||
return;
|
||||
vrGUIManager->setVisible(this, visible);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool WindowBase::isVisible()
|
||||
|
|
|
@ -53,6 +53,9 @@ namespace MWGui
|
|||
/// Called when GUI viewport changes size
|
||||
virtual void onResChange(int width, int height) {}
|
||||
|
||||
/// Called when Window widget changes in size
|
||||
virtual void onWindowResize(MyGUI::Window* window) {}
|
||||
|
||||
protected:
|
||||
virtual void onTitleDoubleClicked();
|
||||
|
||||
|
|
|
@ -114,7 +114,7 @@
|
|||
|
||||
#ifdef USE_OPENXR
|
||||
#include "../mwvr/vrenvironment.hpp"
|
||||
#include "../mwvr/openxrmenu.hpp"
|
||||
#include "../mwvr/vrgui.hpp"
|
||||
#endif
|
||||
|
||||
namespace
|
||||
|
@ -133,9 +133,8 @@ namespace MWGui
|
|||
WindowManager::WindowManager(
|
||||
osgViewer::Viewer* viewer, osg::Group* guiRoot, Resource::ResourceSystem* resourceSystem, SceneUtil::WorkQueue* workQueue,
|
||||
const std::string& logpath, const std::string& resourcePath, bool consoleOnlyScripts, Translation::Storage& translationDataStorage,
|
||||
ToUTF8::FromType encoding, bool exportFonts, const std::string& versionDescription, const std::string& userDataPath, bool VRMode)
|
||||
ToUTF8::FromType encoding, bool exportFonts, const std::string& versionDescription, const std::string& userDataPath)
|
||||
: mStore(nullptr)
|
||||
, mVRMode(VRMode)
|
||||
, mResourceSystem(resourceSystem)
|
||||
, mWorkQueue(workQueue)
|
||||
, mViewer(viewer)
|
||||
|
@ -202,7 +201,7 @@ namespace MWGui
|
|||
, mVersionDescription(versionDescription)
|
||||
{
|
||||
float uiScale = Settings::Manager::getFloat("scaling factor", "GUI");
|
||||
mGuiPlatform = new osgMyGUI::Platform(viewer, guiRoot, resourceSystem->getImageManager(), uiScale, mVRMode);
|
||||
mGuiPlatform = new osgMyGUI::Platform(viewer, guiRoot, resourceSystem->getImageManager(), uiScale);
|
||||
mGuiPlatform->initialise(resourcePath, logpath);
|
||||
|
||||
mGui = new MyGUI::Gui;
|
||||
|
@ -246,7 +245,11 @@ namespace MWGui
|
|||
|
||||
MyGUI::FactoryManager::getInstance().registerFactory<ResourceImageSetPointerFix>("Resource", "ResourceImageSetPointer");
|
||||
MyGUI::FactoryManager::getInstance().registerFactory<AutoSizedResourceSkin>("Resource", "AutoSizedResourceSkin");
|
||||
#ifdef USE_OPENXR
|
||||
MyGUI::ResourceManager::getInstance().load("core_vr.xml");
|
||||
#else
|
||||
MyGUI::ResourceManager::getInstance().load("core.xml");
|
||||
#endif
|
||||
WindowManager::loadUserFonts();
|
||||
|
||||
bool keyboardNav = Settings::Manager::getBool("keyboard navigation", "GUI");
|
||||
|
@ -1890,7 +1893,7 @@ namespace MWGui
|
|||
#ifdef USE_OPENXR
|
||||
// Temporary hack to force update of menu placement
|
||||
// (Menu gets recreated next tick)
|
||||
auto* xrMenuManager = MWVR::Environment::get().getMenuManager();
|
||||
auto* xrMenuManager = MWVR::Environment::get().getGUIManager();
|
||||
#endif
|
||||
|
||||
mVideoWidget->eventKeyButtonPressed.clear();
|
||||
|
@ -1935,7 +1938,7 @@ namespace MWGui
|
|||
// (Menu gets recreated next tick)
|
||||
if (xrMenuManager)
|
||||
{
|
||||
xrMenuManager->showMenus(false);
|
||||
xrMenuManager->showGUIs(false);
|
||||
xrMenuManager = nullptr;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -132,7 +132,7 @@ namespace MWGui
|
|||
|
||||
WindowManager(osgViewer::Viewer* viewer, osg::Group* guiRoot, Resource::ResourceSystem* resourceSystem, SceneUtil::WorkQueue* workQueue,
|
||||
const std::string& logpath, const std::string& cacheDir, bool consoleOnlyScripts, Translation::Storage& translationDataStorage,
|
||||
ToUTF8::FromType encoding, bool exportFonts, const std::string& versionDescription, const std::string& localPath, bool VRMode);
|
||||
ToUTF8::FromType encoding, bool exportFonts, const std::string& versionDescription, const std::string& localPath);
|
||||
virtual ~WindowManager();
|
||||
|
||||
/// Set the ESMStore to use for retrieving of GUI-related strings.
|
||||
|
|
|
@ -112,6 +112,11 @@ namespace MWRender
|
|||
return position;
|
||||
}
|
||||
|
||||
osg::Camera* Camera::getOsgCamera()
|
||||
{
|
||||
return mCamera;
|
||||
}
|
||||
|
||||
void Camera::updateCamera()
|
||||
{
|
||||
updateCamera(mCamera);
|
||||
|
|
|
@ -121,6 +121,8 @@ namespace MWRender
|
|||
|
||||
osg::Vec3d getFocalPoint();
|
||||
|
||||
osg::Camera* getOsgCamera();
|
||||
|
||||
/// Stores focal and camera world positions in passed arguments
|
||||
void getPosition(osg::Vec3f &focal, osg::Vec3f &camera);
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include <osg/Node>
|
||||
#include <osg/ValueObject>
|
||||
#include <osg/RenderInfo>
|
||||
|
||||
#include <components/resource/resourcesystem.hpp>
|
||||
#include <components/resource/imagemanager.hpp>
|
||||
|
@ -64,4 +65,21 @@ void overrideTexture(const std::string &texture, Resource::ResourceSystem *resou
|
|||
node->setStateSet(stateset);
|
||||
}
|
||||
|
||||
MipmapCallback::~MipmapCallback()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
void MipmapCallback::operator()(osg::RenderInfo& renderInfo) const
|
||||
{
|
||||
auto* gl = renderInfo.getState()->get<osg::GLExtensions>();
|
||||
auto* tex = mTexture->getTextureObject(renderInfo.getContextID());
|
||||
if (tex)
|
||||
{
|
||||
tex->bind();
|
||||
gl->glGenerateMipmap(tex->target());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,12 +2,14 @@
|
|||
#define OPENMW_MWRENDER_UTIL_H
|
||||
|
||||
#include <osg/NodeCallback>
|
||||
#include <osg/Camera>
|
||||
#include <osg/ref_ptr>
|
||||
#include <string>
|
||||
|
||||
namespace osg
|
||||
{
|
||||
class Node;
|
||||
class Texture2D;
|
||||
}
|
||||
|
||||
namespace Resource
|
||||
|
@ -32,6 +34,24 @@ namespace MWRender
|
|||
// no traverse()
|
||||
}
|
||||
};
|
||||
|
||||
/// Draw callback for RTT that can be used to regenerate mipmaps
|
||||
/// either as a predraw before use or a postdraw after RTT.
|
||||
class MipmapCallback : public osg::Camera::DrawCallback
|
||||
{
|
||||
public:
|
||||
MipmapCallback(osg::Texture2D* texture)
|
||||
: mTexture(texture)
|
||||
{}
|
||||
|
||||
~MipmapCallback();
|
||||
|
||||
void operator()(osg::RenderInfo& info) const override;
|
||||
|
||||
private:
|
||||
|
||||
osg::ref_ptr<osg::Texture2D> mTexture;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -732,6 +732,10 @@ OpenXRInput::getHandPoses(
|
|||
XrSpaceVelocity velocity{ XR_TYPE_SPACE_VELOCITY };
|
||||
location.next = &velocity;
|
||||
CHECK_XRCMD(xrLocateSpace(mHandSpace[(int)Side::LEFT_HAND], referenceSpace, time, &location));
|
||||
if (!location.locationFlags & XR_SPACE_LOCATION_ORIENTATION_VALID_BIT)
|
||||
// Quat must have a magnitude of 1 but openxr sets it to 0 when tracking is unavailable.
|
||||
// I want a no-track pose to still be valid
|
||||
location.pose.orientation.w = 1;
|
||||
|
||||
handPoses[(int)Side::LEFT_HAND] = MWVR::Pose{
|
||||
osg::fromXR(location.pose.position),
|
||||
|
@ -740,6 +744,11 @@ OpenXRInput::getHandPoses(
|
|||
};
|
||||
|
||||
CHECK_XRCMD(xrLocateSpace(mHandSpace[(int)Side::RIGHT_HAND], referenceSpace, time, &location));
|
||||
if (!location.locationFlags & XR_SPACE_LOCATION_ORIENTATION_VALID_BIT)
|
||||
// Quat must have a magnitude of 1 but openxr sets it to 0 when tracking is unavailable.
|
||||
// I want a no-track pose to still be valid
|
||||
location.pose.orientation.w = 1;
|
||||
|
||||
handPoses[(int)Side::RIGHT_HAND] = MWVR::Pose{
|
||||
osg::fromXR(location.pose.position),
|
||||
osg::fromXR(location.pose.orientation),
|
||||
|
@ -817,15 +826,18 @@ private:
|
|||
MWWorld::Ptr ptr = anim->mPointerTarget.mHitObject;
|
||||
auto& dnd = MWBase::Environment::get().getWindowManager()->getDragAndDrop();
|
||||
|
||||
if (node && node->getName() == "XR Menu Geometry")
|
||||
if (node && node->getName() == "VRGUILayer")
|
||||
{
|
||||
// Interseceted with the menu
|
||||
// Inject mouse buttons
|
||||
SDL_MouseButtonEvent arg;
|
||||
if (onPress)
|
||||
mousePressed(arg, SDL_BUTTON_LEFT);
|
||||
else
|
||||
mouseReleased(arg, SDL_BUTTON_LEFT);
|
||||
// Intersected with a GUI layer
|
||||
// Inject mouse press
|
||||
//VRGUILayerUserData* userData = static_cast<VRGUILayerUserData*>(node->getUserData());
|
||||
//userData->mLayer->injectMouseClick(SDL_BUTTON_LEFT, onPress);
|
||||
injectMousePress(SDL_BUTTON_LEFT, onPress);
|
||||
//SDL_MouseButtonEvent arg;
|
||||
//if (onPress)
|
||||
// mousePressed(arg, SDL_BUTTON_LEFT);
|
||||
//else
|
||||
// mouseReleased(arg, SDL_BUTTON_LEFT);
|
||||
}
|
||||
else if (onPress)
|
||||
{
|
||||
|
@ -851,6 +863,15 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
void OpenXRInputManager::injectMousePress(int sdlButton, bool onPress)
|
||||
{
|
||||
SDL_MouseButtonEvent arg;
|
||||
if (onPress)
|
||||
mousePressed(arg, sdlButton);
|
||||
else
|
||||
mouseReleased(arg, sdlButton);
|
||||
}
|
||||
|
||||
OpenXRInputManager::OpenXRInputManager(
|
||||
SDL_Window* window,
|
||||
osg::ref_ptr<osgViewer::Viewer> viewer,
|
||||
|
@ -903,19 +924,26 @@ private:
|
|||
if (world && anim && anim->mPointerTarget.mHit)
|
||||
{
|
||||
auto* node = anim->mPointerTarget.mHitNode;
|
||||
if (node)
|
||||
auto* vrGuiManager = Environment::get().getGUIManager();
|
||||
if (node && node->getName() == "VRGUILayer")
|
||||
{
|
||||
int w, h;
|
||||
SDL_GetWindowSize(mWindow, &w, &h);
|
||||
|
||||
osg::Vec3 local = anim->mPointerTarget.mHitPointLocal;
|
||||
local.x() = (local.x() + 1.f) / 2.f;
|
||||
local.y() = 1.f - (local.y() + 1.f) / 2.f;
|
||||
local.z() = 1.f - (local.z() + 1.f) / 2.f;
|
||||
|
||||
mGuiCursorX = mInvUiScalingFactor * (local.x() * w);
|
||||
mGuiCursorY = mInvUiScalingFactor * (local.y() * h);
|
||||
mGuiCursorY = mInvUiScalingFactor * (local.z() * h);
|
||||
|
||||
MyGUI::InputManager::getInstance().injectMouseMove(int(mGuiCursorX), int(mGuiCursorY), 0);
|
||||
VRGUILayerUserData* userData = static_cast<VRGUILayerUserData*>(node->getUserData());
|
||||
vrGuiManager->setFocusLayer(userData->mLayer);
|
||||
MyGUI::InputManager::getInstance().injectMouseMove((int)mGuiCursorX, (int)mGuiCursorY, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
vrGuiManager->setFocusLayer(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -932,9 +960,9 @@ private:
|
|||
MWInput::InputManager::update(dt, disableControls, disableEvents);
|
||||
|
||||
bool guiMode = MWBase::Environment::get().getWindowManager()->isGuiMode();
|
||||
auto* xrMenuManager = Environment::get().getMenuManager();
|
||||
if(xrMenuManager)
|
||||
xrMenuManager->showMenus(guiMode);
|
||||
auto* xrGUIManager = Environment::get().getGUIManager();
|
||||
if(xrGUIManager)
|
||||
xrGUIManager->showGUIs(guiMode);
|
||||
|
||||
setPlayerControlsEnabled(!guiMode);
|
||||
|
||||
|
@ -953,14 +981,14 @@ private:
|
|||
void OpenXRInputManager::processEvent(const OpenXRActionEvent& event)
|
||||
{
|
||||
//auto* session = Environment::get().getSession();
|
||||
auto* xrMenuManager = Environment::get().getMenuManager();
|
||||
auto* xrGUIManager = Environment::get().getGUIManager();
|
||||
switch (event.action)
|
||||
{
|
||||
case A_GameMenu:
|
||||
toggleMainMenu();
|
||||
// Explicitly request position update here so that the player can move the menu
|
||||
// using the menu key when the menu can't be toggled.
|
||||
xrMenuManager->updatePose();
|
||||
xrGUIManager->updatePose();
|
||||
break;
|
||||
case A_Screenshot:
|
||||
screenshot();
|
||||
|
|
|
@ -47,6 +47,8 @@ namespace MWVR
|
|||
void updateActivationIndication(void);
|
||||
void pointActivation(bool onPress);
|
||||
|
||||
void injectMousePress(int sdlButton, bool onPress);
|
||||
|
||||
std::unique_ptr<OpenXRInput> mXRInput;
|
||||
std::unique_ptr<RealisticCombat::StateMachine> mRealisticCombat;
|
||||
Pose mPreviousHeadPose{};
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include <array>
|
||||
#include "openxrmanager.hpp"
|
||||
#include "openxrtexture.hpp"
|
||||
#include "vrtexture.hpp"
|
||||
|
||||
struct XrCompositionLayerBaseHeader;
|
||||
|
||||
|
|
|
@ -222,6 +222,18 @@ namespace MWVR
|
|||
if (mPrivate)
|
||||
mPrivate->playerScale(stagePose);
|
||||
}
|
||||
Pose Pose::operator+(const Pose& rhs)
|
||||
{
|
||||
Pose pose = *this;
|
||||
pose.position += this->orientation * rhs.position;
|
||||
pose.orientation = rhs.orientation * this->orientation;
|
||||
return pose;
|
||||
}
|
||||
const Pose& Pose::operator+=(const Pose& rhs)
|
||||
{
|
||||
*this = *this + rhs;
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
|
||||
std::ostream& operator <<(
|
||||
|
|
|
@ -44,6 +44,9 @@ namespace MWVR
|
|||
osg::Quat orientation{ 0,0,0,1 };
|
||||
//! Speed of movement in VR space, expressed in meters per second
|
||||
osg::Vec3 velocity{ 0,0,0 };
|
||||
|
||||
Pose operator+(const Pose& rhs);
|
||||
const Pose& operator+=(const Pose& rhs);
|
||||
};
|
||||
|
||||
using PoseSet = std::array<Pose, 2>;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#include "openxrmanagerimpl.hpp"
|
||||
#include "openxrtexture.hpp"
|
||||
#include "vrtexture.hpp"
|
||||
|
||||
#include <components/debug/debuglog.hpp>
|
||||
#include <components/sdlutil/sdlgraphicswindow.hpp>
|
||||
|
@ -385,6 +385,12 @@ namespace MWVR
|
|||
CHECK_XRCMD(xrLocateSpace(limbSpace, referenceSpace, predictedDisplayTime, &location));
|
||||
//if (!(velocity.velocityFlags & XR_SPACE_VELOCITY_LINEAR_VALID_BIT))
|
||||
// Log(Debug::Warning) << "Unable to acquire linear velocity";
|
||||
if (!location.locationFlags & XR_SPACE_LOCATION_ORIENTATION_VALID_BIT)
|
||||
{
|
||||
// Quat must have a magnitude of 1 but openxr sets it to 0 when tracking is unavailable.
|
||||
// I want a no-track pose to still be valid
|
||||
location.pose.orientation.w = 1;
|
||||
}
|
||||
return MWVR::Pose{
|
||||
osg::fromXR(location.pose.position),
|
||||
osg::fromXR(location.pose.orientation),
|
||||
|
|
|
@ -1,308 +0,0 @@
|
|||
#include "openxrmenu.hpp"
|
||||
#include "vrenvironment.hpp"
|
||||
#include "openxrsession.hpp"
|
||||
#include "openxrmanagerimpl.hpp"
|
||||
#include "vranimation.hpp"
|
||||
#include <openxr/openxr.h>
|
||||
#include <osg/Texture2D>
|
||||
#include <osg/ClipNode>
|
||||
#include <osg/FrontFace>
|
||||
#include <osg/BlendFunc>
|
||||
#include <osg/Depth>
|
||||
#include <components/sceneutil/visitor.hpp>
|
||||
#include <components/sceneutil/shadow.hpp>
|
||||
#include <osgViewer/Renderer>
|
||||
#include "../mwrender/util.hpp"
|
||||
#include "../mwrender/renderbin.hpp"
|
||||
|
||||
namespace MWVR
|
||||
{
|
||||
|
||||
/// Draw callback for RTT that can be used to regenerate mipmaps
|
||||
/// either as a predraw before use or a postdraw after RTT.
|
||||
class MipmapCallback : public osg::Camera::DrawCallback
|
||||
{
|
||||
public:
|
||||
MipmapCallback(osg::Texture2D* texture)
|
||||
: mTexture(texture)
|
||||
{}
|
||||
|
||||
void operator()(osg::RenderInfo& info) const override;
|
||||
|
||||
private:
|
||||
|
||||
osg::ref_ptr<osg::Texture2D> mTexture;
|
||||
};
|
||||
|
||||
/// RTT camera used to draw the osg GUI to a texture
|
||||
class GUICamera : public osg::Camera
|
||||
{
|
||||
public:
|
||||
GUICamera()
|
||||
{
|
||||
setRenderOrder(osg::Camera::PRE_RENDER);
|
||||
setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
// Make the texture just a little transparent to feel more natural in the game world.
|
||||
setClearColor(osg::Vec4(0.f,0.f,0.f,.75f));
|
||||
|
||||
setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
|
||||
setReferenceFrame(osg::Camera::ABSOLUTE_RF);
|
||||
setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
|
||||
setName("MenuCamera");
|
||||
|
||||
setCullMask(SceneUtil::Mask_GUI);
|
||||
setNodeMask(SceneUtil::Mask_RenderToTexture);
|
||||
|
||||
unsigned int rttSize = 4000;
|
||||
setViewport(0, 0, rttSize, rttSize);
|
||||
|
||||
// No need for Update traversal since the mSceneRoot is already updated as part of the main scene graph
|
||||
// A double update would mess with the light collection (in addition to being plain redundant)
|
||||
setUpdateCallback(new MWRender::NoTraverseCallback);
|
||||
|
||||
// Create the texture
|
||||
mTexture = new osg::Texture2D;
|
||||
mTexture->setTextureSize(rttSize, rttSize);
|
||||
mTexture->setInternalFormat(GL_RGBA);
|
||||
mTexture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_LINEAR);
|
||||
mTexture->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);
|
||||
mTexture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
|
||||
mTexture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
|
||||
attach(osg::Camera::COLOR_BUFFER, mTexture);
|
||||
// Need to regenerate mipmaps every frame
|
||||
setPostDrawCallback(new MipmapCallback(mTexture));
|
||||
|
||||
// Do not want to waste time on shadows when generating the GUI texture
|
||||
SceneUtil::ShadowManager::disableShadowsForStateSet(getOrCreateStateSet());
|
||||
|
||||
// Put rendering as early as possible
|
||||
getOrCreateStateSet()->setRenderBinDetails(-1, "RenderBin");
|
||||
|
||||
}
|
||||
|
||||
void setScene(osg::Node* scene)
|
||||
{
|
||||
if (mScene)
|
||||
removeChild(mScene);
|
||||
mScene = scene;
|
||||
addChild(scene);
|
||||
Log(Debug::Verbose) << "Set new scene: " << mScene->getName();
|
||||
}
|
||||
|
||||
osg::Texture2D* getTexture() const
|
||||
{
|
||||
return mTexture.get();
|
||||
}
|
||||
|
||||
private:
|
||||
osg::ref_ptr<osg::Texture2D> mTexture;
|
||||
osg::ref_ptr<osg::Node> mScene;
|
||||
};
|
||||
|
||||
|
||||
OpenXRMenu::OpenXRMenu(
|
||||
osg::ref_ptr<osg::Group> geometryRoot,
|
||||
osg::ref_ptr<osg::Group> cameraRoot,
|
||||
osg::ref_ptr<osg::Node> menuSubgraph,
|
||||
const std::string& title,
|
||||
osg::Vec2 extent_meters,
|
||||
Pose pose,
|
||||
int width,
|
||||
int height,
|
||||
const osg::Vec4& clearColor,
|
||||
osgViewer::Viewer* viewer)
|
||||
: mTitle(title)
|
||||
, mGeometryRoot(geometryRoot)
|
||||
, mCameraRoot(cameraRoot)
|
||||
, mMenuSubgraph(menuSubgraph)
|
||||
{
|
||||
osg::ref_ptr<osg::Vec3Array> vertices{ new osg::Vec3Array(4) };
|
||||
osg::ref_ptr<osg::Vec2Array> texCoords{ new osg::Vec2Array(4) };
|
||||
osg::ref_ptr<osg::Vec3Array> normals{ new osg::Vec3Array(1) };
|
||||
|
||||
// Units are divided by 2 because geometry has an extent of 2 (-1 to 1)
|
||||
auto extent_units = extent_meters * Environment::get().unitsPerMeter() / 2.f;
|
||||
|
||||
// Define the menu quad
|
||||
osg::Vec3 top_left (-1, 1, 1);
|
||||
osg::Vec3 bottom_left(-1, -1, 1);
|
||||
osg::Vec3 bottom_right(1, -1, 1);
|
||||
osg::Vec3 top_right (1, 1, 1);
|
||||
(*vertices)[0] = top_left;
|
||||
(*vertices)[1] = bottom_left;
|
||||
(*vertices)[2] = bottom_right;
|
||||
(*vertices)[3] = top_right;
|
||||
mGeometry->setVertexArray(vertices);
|
||||
(*texCoords)[0].set(0.0f, 1.0f);
|
||||
(*texCoords)[1].set(0.0f, 0.0f);
|
||||
(*texCoords)[2].set(1.0f, 0.0f);
|
||||
(*texCoords)[3].set(1.0f, 1.0f);
|
||||
mGeometry->setTexCoordArray(0, texCoords);
|
||||
(*normals)[0].set(0.0f, -1.0f, 0.0f);
|
||||
mGeometry->setNormalArray(normals, osg::Array::BIND_OVERALL);
|
||||
mGeometry->addPrimitiveSet(new osg::DrawArrays(GL_QUADS, 0, 4));
|
||||
mGeometry->setDataVariance(osg::Object::DYNAMIC);
|
||||
mGeometry->setSupportsDisplayList(false);
|
||||
mGeometry->setName("XR Menu Geometry");
|
||||
//mGeode->addDrawable(mGeometry);
|
||||
|
||||
// Define the camera that will render the menu texture
|
||||
mGUICamera = new GUICamera();
|
||||
mGUICamera->setScene(menuSubgraph);
|
||||
|
||||
// Define state set that allows rendering with transparency
|
||||
mStateSet->setTextureAttributeAndModes(0, menuTexture(), osg::StateAttribute::ON);
|
||||
mStateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
|
||||
mStateSet->setMode(GL_BLEND, osg::StateAttribute::ON);
|
||||
mStateSet->setAttributeAndModes(new osg::BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
|
||||
mStateSet->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
|
||||
mGeometry->setStateSet(mStateSet);
|
||||
|
||||
// Position in the game world
|
||||
mTransform->setScale(osg::Vec3(extent_units.x(), extent_units.y(), 1.f));
|
||||
mTransform->setAttitude(pose.orientation);
|
||||
mTransform->setPosition(pose.position);
|
||||
mTransform->addChild(mGeometry);
|
||||
//mTransform->addChild(VRAnimation::createPointerGeometry());
|
||||
|
||||
// Add to scene graph
|
||||
mGeometryRoot->addChild(mTransform);
|
||||
mCameraRoot->addChild(mGUICamera);
|
||||
}
|
||||
|
||||
OpenXRMenu::~OpenXRMenu()
|
||||
{
|
||||
mGeometryRoot->removeChild(mTransform);
|
||||
mCameraRoot->removeChild(mGUICamera);
|
||||
}
|
||||
|
||||
void OpenXRMenu::updateCallback()
|
||||
{
|
||||
}
|
||||
|
||||
void MipmapCallback::operator()(osg::RenderInfo& renderInfo) const
|
||||
{
|
||||
auto* gl = renderInfo.getState()->get<osg::GLExtensions>();
|
||||
auto* tex = mTexture->getTextureObject(renderInfo.getContextID());
|
||||
if (tex)
|
||||
{
|
||||
tex->bind();
|
||||
gl->glGenerateMipmap(tex->target());
|
||||
}
|
||||
}
|
||||
|
||||
osg::Camera* OpenXRMenu::camera()
|
||||
{
|
||||
return mGUICamera.get();
|
||||
}
|
||||
|
||||
osg::ref_ptr<osg::Texture2D> OpenXRMenu::menuTexture()
|
||||
{
|
||||
if (mGUICamera)
|
||||
return mGUICamera->getTexture();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void OpenXRMenu::updatePose(Pose pose)
|
||||
{
|
||||
mTransform->setAttitude(pose.orientation);
|
||||
mTransform->setPosition(pose.position);
|
||||
}
|
||||
|
||||
|
||||
OpenXRMenuManager::OpenXRMenuManager(
|
||||
osg::ref_ptr<osgViewer::Viewer> viewer)
|
||||
: mOsgViewer(viewer)
|
||||
{
|
||||
mGUIGeometriesRoot->setName("XR GUI Geometry Root");
|
||||
mGUICamerasRoot->setName("XR GUI Cameras Root");
|
||||
auto* root = viewer->getSceneData();
|
||||
|
||||
SceneUtil::FindByNameVisitor findGUIVisitor("GUI Root");
|
||||
root->accept(findGUIVisitor);
|
||||
mGuiRoot = findGUIVisitor.mFoundNode;
|
||||
if (!mGuiRoot)
|
||||
{
|
||||
Log(Debug::Error) << "GUI Root doesn't exist";
|
||||
return;
|
||||
}
|
||||
|
||||
SceneUtil::FindByNameVisitor findSceneVisitor("Scene Root");
|
||||
root->accept(findSceneVisitor);
|
||||
if(!findSceneVisitor.mFoundNode)
|
||||
{
|
||||
Log(Debug::Error) << "Scene Root doesn't exist";
|
||||
return;
|
||||
}
|
||||
|
||||
Log(Debug::Verbose) << "Root note: " << root->getName();
|
||||
|
||||
findSceneVisitor.mFoundNode->addChild(mGUIGeometriesRoot);
|
||||
root->asGroup()->addChild(mGUICamerasRoot);
|
||||
|
||||
}
|
||||
|
||||
OpenXRMenuManager::~OpenXRMenuManager(void)
|
||||
{
|
||||
}
|
||||
|
||||
void OpenXRMenuManager::showMenus(bool show)
|
||||
{
|
||||
// TODO: Configurable menu dimensions
|
||||
int width = 1000;
|
||||
int height = 1000;
|
||||
|
||||
if (show && !mMenu)
|
||||
{
|
||||
updatePose();
|
||||
mMenu.reset(new OpenXRMenu(
|
||||
mGUIGeometriesRoot,
|
||||
mGUICamerasRoot,
|
||||
mGuiRoot,
|
||||
"Main Menu",
|
||||
osg::Vec2(1.5f, 1.5f),
|
||||
mPose,
|
||||
width,
|
||||
height,
|
||||
mOsgViewer->getCamera()->getClearColor(),
|
||||
mOsgViewer
|
||||
));
|
||||
Log(Debug::Error) << "Created menu";
|
||||
}
|
||||
else if (!show && mMenu)
|
||||
{
|
||||
mMenu = nullptr;
|
||||
Log(Debug::Error) << "Destroyed menu";
|
||||
}
|
||||
}
|
||||
|
||||
void OpenXRMenuManager::updatePose(void)
|
||||
{
|
||||
osg::Vec3 eye{};
|
||||
osg::Vec3 center{};
|
||||
osg::Vec3 up{};
|
||||
|
||||
auto* camera = mOsgViewer->getCamera();
|
||||
if (!camera)
|
||||
{
|
||||
Log(Debug::Error) << "osg viewer has no camera";
|
||||
return;
|
||||
}
|
||||
|
||||
camera->getViewMatrixAsLookAt(eye, center, up);
|
||||
|
||||
// Position the menu about two thirds of a meter in front of the player
|
||||
osg::Vec3 dir = center - eye;
|
||||
dir.normalize();
|
||||
mPose.position = eye + dir * Environment::get().unitsPerMeter() * 2.f / 3.f;
|
||||
|
||||
|
||||
mPose.orientation = camera->getViewMatrix().getRotate().inverse();
|
||||
|
||||
if (mMenu)
|
||||
mMenu->updatePose(mPose);
|
||||
|
||||
Log(Debug::Error) << "New menu pose: " << mPose;
|
||||
}
|
||||
}
|
|
@ -1,83 +0,0 @@
|
|||
#ifndef OPENXR_MENU_HPP
|
||||
#define OPENXR_MENU_HPP
|
||||
|
||||
#include <osg/Geometry>
|
||||
#include <osg/TexMat>
|
||||
#include <osg/Texture2D>
|
||||
#include <osg/Camera>
|
||||
#include <osg/PositionAttitudeTransform>
|
||||
|
||||
#include "openxrview.hpp"
|
||||
#include "openxrlayer.hpp"
|
||||
|
||||
struct XrCompositionLayerQuad;
|
||||
namespace MWVR
|
||||
{
|
||||
class GUICamera;
|
||||
|
||||
class OpenXRMenu
|
||||
{
|
||||
public:
|
||||
OpenXRMenu(
|
||||
osg::ref_ptr<osg::Group> geometryRoot,
|
||||
osg::ref_ptr<osg::Group> cameraRoot,
|
||||
osg::ref_ptr<osg::Node> menuSubgraph,
|
||||
const std::string& title,
|
||||
osg::Vec2 extent_meters,
|
||||
Pose pose,
|
||||
int width,
|
||||
int height,
|
||||
const osg::Vec4& clearColor,
|
||||
osgViewer::Viewer* viewer);
|
||||
~OpenXRMenu();
|
||||
const std::string& title() const { return mTitle; }
|
||||
void updateCallback();
|
||||
|
||||
void preRenderCallback(osg::RenderInfo& renderInfo);
|
||||
void postRenderCallback(osg::RenderInfo& renderInfo);
|
||||
osg::Camera* camera();
|
||||
|
||||
osg::ref_ptr<osg::Texture2D> menuTexture();
|
||||
|
||||
void updatePose(Pose pose);
|
||||
|
||||
public:
|
||||
std::string mTitle;
|
||||
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<osg::Node> mMenuSubgraph;
|
||||
osg::ref_ptr<osg::StateSet> mStateSet{ new osg::StateSet };
|
||||
osg::ref_ptr<GUICamera> mGUICamera;
|
||||
};
|
||||
|
||||
class OpenXRMenuManager
|
||||
{
|
||||
public:
|
||||
OpenXRMenuManager(
|
||||
osg::ref_ptr<osgViewer::Viewer> viewer);
|
||||
|
||||
~OpenXRMenuManager(void);
|
||||
|
||||
void showMenus(bool show);
|
||||
|
||||
void updatePose(void);
|
||||
|
||||
OpenXRMenu* getMenu(void) const { return mMenu.get(); }
|
||||
|
||||
private:
|
||||
Pose mPose{};
|
||||
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 };
|
||||
|
||||
osg::ref_ptr<osg::Node> mGuiRoot{ nullptr };
|
||||
|
||||
std::unique_ptr<OpenXRMenu> mMenu{ nullptr };
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -22,7 +22,7 @@
|
|||
#include <array>
|
||||
#include <iostream>
|
||||
#include "openxrsession.hpp"
|
||||
#include "openxrmenu.hpp"
|
||||
#include "vrgui.hpp"
|
||||
#include <time.h>
|
||||
|
||||
namespace MWVR
|
||||
|
|
|
@ -32,14 +32,14 @@ namespace MWVR {
|
|||
osg::ref_ptr<OpenXRManager> mXR;
|
||||
XrSwapchain mSwapchain = XR_NULL_HANDLE;
|
||||
std::vector<XrSwapchainImageOpenGLKHR> mSwapchainImageBuffers{};
|
||||
//std::vector<osg::ref_ptr<OpenXRTextureBuffer> > mTextureBuffers{};
|
||||
//std::vector<osg::ref_ptr<VRTexture> > mTextureBuffers{};
|
||||
XrSwapchainSubImage mSubImage{};
|
||||
int32_t mWidth = -1;
|
||||
int32_t mHeight = -1;
|
||||
int32_t mSamples = -1;
|
||||
int64_t mSwapchainColorFormat = -1;
|
||||
uint32_t mFBO = 0;
|
||||
OpenXRTextureBuffer* mRenderBuffer = nullptr;
|
||||
VRTexture* mRenderBuffer = nullptr;
|
||||
};
|
||||
|
||||
OpenXRSwapchainImpl::OpenXRSwapchainImpl(
|
||||
|
@ -99,8 +99,8 @@ namespace MWVR {
|
|||
mSwapchainImageBuffers.resize(imageCount, { XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_KHR });
|
||||
CHECK_XRCMD(xrEnumerateSwapchainImages(mSwapchain, imageCount, &imageCount, reinterpret_cast<XrSwapchainImageBaseHeader*>(mSwapchainImageBuffers.data())));
|
||||
//for (const auto& swapchainImage : mSwapchainImageBuffers)
|
||||
// mTextureBuffers.push_back(new OpenXRTextureBuffer(state, swapchainImage.image, mWidth, mHeight, 0));
|
||||
mRenderBuffer = new OpenXRTextureBuffer(state, mWidth, mHeight, 0);
|
||||
// mTextureBuffers.push_back(new VRTexture(state, swapchainImage.image, mWidth, mHeight, 0));
|
||||
mRenderBuffer = new VRTexture(state, mWidth, mHeight, 0);
|
||||
|
||||
mSubImage.swapchain = mSwapchain;
|
||||
mSubImage.imageRect.offset = { 0, 0 };
|
||||
|
@ -181,7 +181,7 @@ namespace MWVR {
|
|||
return impl().mSamples;
|
||||
}
|
||||
|
||||
OpenXRTextureBuffer* OpenXRSwapchain::renderBuffer()
|
||||
VRTexture* OpenXRSwapchain::renderBuffer()
|
||||
{
|
||||
return impl().mRenderBuffer;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#define OPENXR_SWAPCHAIN_HPP
|
||||
|
||||
#include "openxrmanager.hpp"
|
||||
#include "openxrtexture.hpp"
|
||||
#include "vrtexture.hpp"
|
||||
|
||||
struct XrSwapchainSubImage;
|
||||
|
||||
|
@ -38,7 +38,7 @@ namespace MWVR
|
|||
//! Samples of the view surface
|
||||
int samples();
|
||||
//! Get the current texture
|
||||
OpenXRTextureBuffer* renderBuffer();
|
||||
VRTexture* renderBuffer();
|
||||
//! Get the private implementation
|
||||
OpenXRSwapchainImpl& impl() { return *mPrivate; }
|
||||
//! Get the private implementation
|
||||
|
|
|
@ -154,16 +154,12 @@ namespace MWVR
|
|||
|
||||
}
|
||||
|
||||
void OpenXRViewer::blitEyesToMirrorTexture(osg::GraphicsContext* gc, bool includeMenu)
|
||||
void OpenXRViewer::blitEyesToMirrorTexture(osg::GraphicsContext* gc)
|
||||
{
|
||||
//includeMenu = false;
|
||||
mMirrorTextureSwapchain->beginFrame(gc);
|
||||
|
||||
int mirror_width = 0;
|
||||
if(includeMenu)
|
||||
mirror_width = mMirrorTextureSwapchain->width() / 3;
|
||||
else
|
||||
mirror_width = mMirrorTextureSwapchain->width() / 2;
|
||||
int mirror_width = mMirrorTextureSwapchain->width() / 2;
|
||||
|
||||
|
||||
mViews["RightEye"]->swapchain().renderBuffer()->blit(gc, 0, 0, mirror_width, mMirrorTextureSwapchain->height());
|
||||
|
@ -172,44 +168,6 @@ namespace MWVR
|
|||
auto* state = gc->getState();
|
||||
auto* gl = osg::GLExtensions::Get(state->getContextID(), false);
|
||||
|
||||
if (includeMenu)
|
||||
{
|
||||
auto menuManager = Environment::get().getMenuManager();
|
||||
if (menuManager)
|
||||
{
|
||||
auto menu = menuManager->getMenu();
|
||||
if (menu)
|
||||
{
|
||||
auto texture = menu->menuTexture();
|
||||
if (texture)
|
||||
{
|
||||
auto textureObject = texture->getTextureObject(state->getContextID());
|
||||
if (textureObject)
|
||||
{
|
||||
auto textureId = textureObject->id();
|
||||
|
||||
Log(Debug::Verbose) << "texture id: " << textureId;
|
||||
|
||||
GLuint fbo = 0;
|
||||
gl->glGenFramebuffers(1, &fbo);
|
||||
|
||||
gl->glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, fbo);
|
||||
gl->glFramebufferTexture2D(GL_READ_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, textureId, 0);
|
||||
gl->glBlitFramebuffer(0, 0, texture->getTextureWidth(), texture->getTextureHeight(), 2 * mirror_width, 0, 3 * mirror_width, mMirrorTextureSwapchain->height(), GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
gl->glFramebufferTexture2D(GL_READ_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, 0, 0);
|
||||
gl->glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, 0);
|
||||
|
||||
gl->glDeleteFramebuffers(1, &fbo);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log(Debug::Warning) << "Texture object was null";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mMirrorTextureSwapchain->endFrame(gc);
|
||||
|
||||
|
||||
|
@ -267,7 +225,7 @@ namespace MWVR
|
|||
mLayer->views = mCompositionLayerProjectionViews.data();
|
||||
}
|
||||
|
||||
blitEyesToMirrorTexture(gc, false);
|
||||
blitEyesToMirrorTexture(gc);
|
||||
|
||||
gc->swapBuffersImplementation();
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#include "openxrsession.hpp"
|
||||
#include "openxrlayer.hpp"
|
||||
#include "openxrworldview.hpp"
|
||||
#include "openxrmenu.hpp"
|
||||
#include "vrgui.hpp"
|
||||
#include <components/sceneutil/positionattitudetransform.hpp>
|
||||
|
||||
struct XrCompositionLayerProjection;
|
||||
|
@ -83,7 +83,7 @@ namespace MWVR
|
|||
void traversals();
|
||||
void preDrawCallback(osg::RenderInfo& info);
|
||||
void postDrawCallback(osg::RenderInfo& info);
|
||||
void blitEyesToMirrorTexture(osg::GraphicsContext* gc, bool includeMenu = true);
|
||||
void blitEyesToMirrorTexture(osg::GraphicsContext* gc);
|
||||
void swapBuffers(osg::GraphicsContext* gc) override;
|
||||
void realize(osg::GraphicsContext* gc);
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#include "vranimation.hpp"
|
||||
#include "openxrinputmanager.hpp"
|
||||
#include "openxrsession.hpp"
|
||||
#include "openxrmenu.hpp"
|
||||
#include "vrgui.hpp"
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
|
||||
|
@ -29,9 +29,9 @@ void MWVR::Environment::cleanup()
|
|||
if (mSession)
|
||||
delete mSession;
|
||||
mSession = nullptr;
|
||||
if (mMenuManager)
|
||||
delete mMenuManager;
|
||||
mMenuManager = nullptr;
|
||||
if (mGUIManager)
|
||||
delete mGUIManager;
|
||||
mGUIManager = nullptr;
|
||||
if (mViewer)
|
||||
delete mViewer;
|
||||
mViewer = nullptr;
|
||||
|
@ -65,14 +65,14 @@ void MWVR::Environment::setSession(MWVR::OpenXRSession* xrSession)
|
|||
mSession = xrSession;
|
||||
}
|
||||
|
||||
MWVR::OpenXRMenuManager* MWVR::Environment::getMenuManager() const
|
||||
MWVR::VRGUIManager* MWVR::Environment::getGUIManager() const
|
||||
{
|
||||
return mMenuManager;
|
||||
return mGUIManager;
|
||||
}
|
||||
|
||||
void MWVR::Environment::setMenuManager(MWVR::OpenXRMenuManager* menuManager)
|
||||
void MWVR::Environment::setGUIManager(MWVR::VRGUIManager* GUIManager)
|
||||
{
|
||||
mMenuManager = menuManager;
|
||||
mGUIManager = GUIManager;
|
||||
}
|
||||
|
||||
MWVR::VRAnimation* MWVR::Environment::getPlayerAnimation() const
|
||||
|
|
|
@ -6,7 +6,7 @@ namespace MWVR
|
|||
class VRAnimation;
|
||||
class OpenXRInputManager;
|
||||
class OpenXRSession;
|
||||
class OpenXRMenuManager;
|
||||
class VRGUIManager;
|
||||
class OpenXRViewer;
|
||||
class OpenXRManager;
|
||||
|
||||
|
@ -45,8 +45,8 @@ namespace MWVR
|
|||
// which is stored in MWBase::Environment
|
||||
// void setInputManager(MWVR::OpenXRInputManager*);
|
||||
|
||||
MWVR::OpenXRMenuManager* getMenuManager() const;
|
||||
void setMenuManager(MWVR::OpenXRMenuManager* xrMenuManager);
|
||||
MWVR::VRGUIManager* getGUIManager() const;
|
||||
void setGUIManager(MWVR::VRGUIManager* xrGUIManager);
|
||||
|
||||
MWVR::VRAnimation* getPlayerAnimation() const;
|
||||
void setPlayerAnimation(MWVR::VRAnimation* xrAnimation);
|
||||
|
@ -65,7 +65,7 @@ namespace MWVR
|
|||
|
||||
private:
|
||||
MWVR::OpenXRSession* mSession{ nullptr };
|
||||
MWVR::OpenXRMenuManager* mMenuManager{ nullptr };
|
||||
MWVR::VRGUIManager* mGUIManager{ nullptr };
|
||||
MWVR::VRAnimation* mPlayerAnimation{ nullptr };
|
||||
MWVR::OpenXRViewer* mViewer{ nullptr };
|
||||
MWVR::OpenXRManager* mOpenXRManager{ nullptr };
|
||||
|
|
512
apps/openmw/mwvr/vrgui.cpp
Normal file
512
apps/openmw/mwvr/vrgui.cpp
Normal file
|
@ -0,0 +1,512 @@
|
|||
#include "vrgui.hpp"
|
||||
#include "vrenvironment.hpp"
|
||||
#include "openxrsession.hpp"
|
||||
#include "openxrmanagerimpl.hpp"
|
||||
#include "openxrinputmanager.hpp"
|
||||
#include "vranimation.hpp"
|
||||
#include <openxr/openxr.h>
|
||||
#include <osg/Texture2D>
|
||||
#include <osg/ClipNode>
|
||||
#include <osg/FrontFace>
|
||||
#include <osg/BlendFunc>
|
||||
#include <osg/Depth>
|
||||
#include <components/sceneutil/visitor.hpp>
|
||||
#include <components/sceneutil/shadow.hpp>
|
||||
#include <components/myguiplatform/myguirendermanager.hpp>
|
||||
#include <osgViewer/Renderer>
|
||||
#include "../mwrender/util.hpp"
|
||||
#include "../mwrender/renderbin.hpp"
|
||||
#include "../mwrender/renderingmanager.hpp"
|
||||
#include "../mwrender/camera.hpp"
|
||||
#include "../mwbase/world.hpp"
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwgui/windowbase.hpp"
|
||||
|
||||
#include <MyGUI_Widget.h>
|
||||
#include <MyGUI_ILayer.h>
|
||||
#include <MyGUI_InputManager.h>
|
||||
#include <MyGUI_WidgetManager.h>
|
||||
#include <MyGUI_Window.h>
|
||||
|
||||
namespace MWVR
|
||||
{
|
||||
|
||||
/// RTT camera used to draw the osg GUI to a texture
|
||||
class GUICamera : public osg::Camera
|
||||
{
|
||||
public:
|
||||
GUICamera(int width, int height, osg::Vec4 clearColor)
|
||||
{
|
||||
setRenderOrder(osg::Camera::PRE_RENDER);
|
||||
setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
setCullingActive(false);
|
||||
|
||||
// Make the texture just a little transparent to feel more natural in the game world.
|
||||
setClearColor(clearColor);
|
||||
|
||||
setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
|
||||
setReferenceFrame(osg::Camera::ABSOLUTE_RF);
|
||||
setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
|
||||
setName("GUICamera");
|
||||
|
||||
setCullMask(SceneUtil::Mask_GUI);
|
||||
setNodeMask(SceneUtil::Mask_RenderToTexture);
|
||||
|
||||
setViewport(0, 0, width, height);
|
||||
|
||||
// No need for Update traversal since the mSceneRoot is already updated as part of the main scene graph
|
||||
// A double update would mess with the light collection (in addition to being plain redundant)
|
||||
setUpdateCallback(new MWRender::NoTraverseCallback);
|
||||
|
||||
// Create the texture
|
||||
mTexture = new osg::Texture2D;
|
||||
mTexture->setTextureSize(width, height);
|
||||
mTexture->setInternalFormat(GL_RGBA);
|
||||
mTexture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_LINEAR);
|
||||
mTexture->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);
|
||||
mTexture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
|
||||
mTexture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
|
||||
attach(osg::Camera::COLOR_BUFFER, mTexture);
|
||||
// Need to regenerate mipmaps every frame
|
||||
setPostDrawCallback(new MWRender::MipmapCallback(mTexture));
|
||||
|
||||
// Do not want to waste time on shadows when generating the GUI texture
|
||||
SceneUtil::ShadowManager::disableShadowsForStateSet(getOrCreateStateSet());
|
||||
|
||||
// Put rendering as early as possible
|
||||
getOrCreateStateSet()->setRenderBinDetails(-1, "RenderBin");
|
||||
|
||||
}
|
||||
|
||||
void setScene(osg::Node* scene)
|
||||
{
|
||||
if (mScene)
|
||||
removeChild(mScene);
|
||||
mScene = scene;
|
||||
addChild(scene);
|
||||
Log(Debug::Verbose) << "Set new scene: " << mScene->getName();
|
||||
}
|
||||
|
||||
osg::Texture2D* getTexture() const
|
||||
{
|
||||
return mTexture.get();
|
||||
}
|
||||
|
||||
private:
|
||||
osg::ref_ptr<osg::Texture2D> mTexture;
|
||||
osg::ref_ptr<osg::Node> mScene;
|
||||
};
|
||||
|
||||
|
||||
class LayerUpdateCallback : public osg::Callback
|
||||
{
|
||||
public:
|
||||
LayerUpdateCallback(VRGUILayer* layer)
|
||||
: mLayer(layer)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool run(osg::Object* object, osg::Object* data)
|
||||
{
|
||||
mLayer->update();
|
||||
return traverse(object, data);
|
||||
}
|
||||
|
||||
private:
|
||||
VRGUILayer* mLayer;
|
||||
};
|
||||
|
||||
VRGUILayer::VRGUILayer(
|
||||
osg::ref_ptr<osg::Group> geometryRoot,
|
||||
osg::ref_ptr<osg::Group> cameraRoot,
|
||||
int width,
|
||||
int height,
|
||||
std::string filter,
|
||||
LayerConfig config,
|
||||
MWGui::Layout* widget,
|
||||
VRGUIManager* parent)
|
||||
: mConfig(config)
|
||||
, mFilter(filter)
|
||||
, mWidget(widget)
|
||||
, mWindow(dynamic_cast<MWGui::WindowBase*>(mWidget))
|
||||
, mMyGUIWindow(dynamic_cast<MyGUI::Window*>(mWidget->mMainWidget))
|
||||
, mParent(parent)
|
||||
, mGeometryRoot(geometryRoot)
|
||||
, mCameraRoot(cameraRoot)
|
||||
{
|
||||
osg::ref_ptr<osg::Vec3Array> vertices{ new osg::Vec3Array(4) };
|
||||
osg::ref_ptr<osg::Vec2Array> texCoords{ new osg::Vec2Array(4) };
|
||||
osg::ref_ptr<osg::Vec3Array> normals{ new osg::Vec3Array(1) };
|
||||
|
||||
// Units are divided by 2 because geometry has an extent of 2 (-1 to 1)
|
||||
auto extent_units = config.extent * Environment::get().unitsPerMeter() / 2.f;
|
||||
|
||||
// Define the menu quad
|
||||
osg::Vec3 top_left (-1, 1, 1);
|
||||
osg::Vec3 bottom_left(-1, 1, -1);
|
||||
osg::Vec3 bottom_right(1, 1, -1);
|
||||
osg::Vec3 top_right (1, 1, 1);
|
||||
(*vertices)[0] = top_left;
|
||||
(*vertices)[1] = bottom_left;
|
||||
(*vertices)[2] = bottom_right;
|
||||
(*vertices)[3] = top_right;
|
||||
mGeometry->setVertexArray(vertices);
|
||||
(*texCoords)[0].set(0.0f, 1.0f);
|
||||
(*texCoords)[1].set(0.0f, 0.0f);
|
||||
(*texCoords)[2].set(1.0f, 0.0f);
|
||||
(*texCoords)[3].set(1.0f, 1.0f);
|
||||
mGeometry->setTexCoordArray(0, texCoords);
|
||||
(*normals)[0].set(0.0f, -1.0f, 0.0f);
|
||||
mGeometry->setNormalArray(normals, osg::Array::BIND_OVERALL);
|
||||
mGeometry->addPrimitiveSet(new osg::DrawArrays(GL_QUADS, 0, 4));
|
||||
mGeometry->setDataVariance(osg::Object::DYNAMIC);
|
||||
mGeometry->setSupportsDisplayList(false);
|
||||
mGeometry->setName("VRGUILayer");
|
||||
mGeometry->setUserData(new VRGUILayerUserData(this));
|
||||
|
||||
// Create the camera that will render the menu texture
|
||||
mGUICamera = new GUICamera(width, height, config.backgroundColor);
|
||||
osgMyGUI::RenderManager& renderManager = static_cast<osgMyGUI::RenderManager&>(MyGUI::RenderManager::getInstance());
|
||||
mGUICamera->setScene(renderManager.createGUICamera(osg::Camera::NESTED_RENDER, filter));
|
||||
|
||||
// Define state set that allows rendering with transparency
|
||||
mStateSet->setTextureAttributeAndModes(0, menuTexture(), osg::StateAttribute::ON);
|
||||
mStateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
|
||||
mStateSet->setMode(GL_BLEND, osg::StateAttribute::ON);
|
||||
mStateSet->setAttributeAndModes(new osg::BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
|
||||
mStateSet->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
|
||||
mGeometry->setStateSet(mStateSet);
|
||||
|
||||
// Position in the game world
|
||||
mTransform->setScale(osg::Vec3(extent_units.x(), 1.f, extent_units.y()));
|
||||
mTransform->addChild(mGeometry);
|
||||
|
||||
// Add to scene graph
|
||||
mGeometryRoot->addChild(mTransform);
|
||||
mCameraRoot->addChild(mGUICamera);
|
||||
|
||||
mTransform->addUpdateCallback(new LayerUpdateCallback(this));
|
||||
}
|
||||
|
||||
VRGUILayer::~VRGUILayer()
|
||||
{
|
||||
mGeometryRoot->removeChild(mTransform);
|
||||
mCameraRoot->removeChild(mGUICamera);
|
||||
}
|
||||
osg::Camera* VRGUILayer::camera()
|
||||
{
|
||||
return mGUICamera.get();
|
||||
}
|
||||
|
||||
osg::ref_ptr<osg::Texture2D> VRGUILayer::menuTexture()
|
||||
{
|
||||
if (mGUICamera)
|
||||
return mGUICamera->getTexture();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void VRGUILayer::updatePose()
|
||||
{
|
||||
osg::Vec3 eye{};
|
||||
osg::Vec3 center{};
|
||||
osg::Vec3 up{};
|
||||
|
||||
// Get head pose by reading the camera view matrix to place the GUI in the world.
|
||||
Pose headPose{};
|
||||
auto* world = MWBase::Environment::get().getWorld();
|
||||
if (!world)
|
||||
return;
|
||||
auto* camera = world->getRenderingManager().getCamera()->getOsgCamera();
|
||||
if (!camera)
|
||||
return;
|
||||
camera->getViewMatrixAsLookAt(eye, center, up);
|
||||
headPose.position = eye;
|
||||
headPose.orientation = camera->getViewMatrix().getRotate();
|
||||
|
||||
if (mConfig.trackedLimb == TrackedLimb::HEAD)
|
||||
{
|
||||
mTrackedPose = headPose;
|
||||
mTrackedPose.orientation = mTrackedPose.orientation.inverse();
|
||||
}
|
||||
else
|
||||
{
|
||||
// If it's not head, it's one of the hands, so i don't bother checking
|
||||
auto* session = MWVR::Environment::get().getSession();
|
||||
auto& poses = session->predictedPoses(OpenXRSession::PredictionSlice::Predraw);
|
||||
mTrackedPose = poses.hands[(int)TrackedSpace::STAGE][(int)mConfig.trackedLimb];
|
||||
// World position is the head, so must add difference between head and hand in tracking space to world pose
|
||||
mTrackedPose.position = mTrackedPose.position * MWVR::Environment::get().unitsPerMeter() - poses.head[(int)TrackedSpace::STAGE].position * MWVR::Environment::get().unitsPerMeter() + headPose.position;
|
||||
}
|
||||
|
||||
mLayerPose.orientation = mConfig.rotation * mTrackedPose.orientation;
|
||||
|
||||
if (mConfig.vertical)
|
||||
{
|
||||
// Force layer to be vertical
|
||||
auto axis = osg::Z_AXIS;
|
||||
osg::Quat vertical;
|
||||
auto local = mLayerPose.orientation * axis;
|
||||
vertical.makeRotate(local, axis);
|
||||
mLayerPose.orientation = mLayerPose.orientation * vertical;
|
||||
}
|
||||
// Orient the offset and move the layer
|
||||
mLayerPose.position = mTrackedPose.position + mLayerPose.orientation * mConfig.offset * MWVR::Environment::get().unitsPerMeter();
|
||||
|
||||
mTransform->setAttitude(mLayerPose.orientation);
|
||||
mTransform->setPosition(mLayerPose.position);
|
||||
}
|
||||
|
||||
void VRGUILayer::update()
|
||||
{
|
||||
if (mConfig.trackingMode == TrackingMode::Auto)
|
||||
updatePose();
|
||||
|
||||
if (mConfig.stretch)
|
||||
{
|
||||
if (mWindow && mMyGUIWindow)
|
||||
{
|
||||
mWindow->setCoordf(0.f, 0.f, 1.f, 1.f);
|
||||
mWindow->onWindowResize(mMyGUIWindow);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VRGUIManager::VRGUIManager(
|
||||
osg::ref_ptr<osgViewer::Viewer> viewer)
|
||||
: mOsgViewer(viewer)
|
||||
{
|
||||
mGUIGeometriesRoot->setName("XR GUI Geometry Root");
|
||||
mGUICamerasRoot->setName("XR GUI Cameras Root");
|
||||
auto* root = viewer->getSceneData();
|
||||
|
||||
SceneUtil::FindByNameVisitor findSceneVisitor("Scene Root");
|
||||
root->accept(findSceneVisitor);
|
||||
if(!findSceneVisitor.mFoundNode)
|
||||
{
|
||||
Log(Debug::Error) << "Scene Root doesn't exist";
|
||||
return;
|
||||
}
|
||||
|
||||
findSceneVisitor.mFoundNode->addChild(mGUIGeometriesRoot);
|
||||
root->asGroup()->addChild(mGUICamerasRoot);
|
||||
|
||||
}
|
||||
|
||||
VRGUIManager::~VRGUIManager(void)
|
||||
{
|
||||
}
|
||||
|
||||
void VRGUIManager::showGUIs(bool show)
|
||||
{
|
||||
}
|
||||
|
||||
LayerConfig gDefaultConfig = LayerConfig
|
||||
{
|
||||
true, // stretch
|
||||
osg::Vec4{0.f,0.f,0.f,.75f}, // background
|
||||
osg::Quat{}, // rotation
|
||||
osg::Vec3(0.f,1.f,0.f), // offset
|
||||
osg::Vec2(1.f, 1.f), // extent (meters)
|
||||
osg::Vec2i(2024,2024), // resolution (pixels)
|
||||
TrackedLimb::HEAD,
|
||||
TrackingMode::Manual,
|
||||
true // vertical
|
||||
};
|
||||
|
||||
LayerConfig gStatusHUDConfig = LayerConfig
|
||||
{
|
||||
false, // stretch
|
||||
osg::Vec4{0.f,0.f,0.f,0.f}, // background
|
||||
osg::Quat{}, // rotation
|
||||
osg::Vec3(0.f,.0f,.2f), // offset (meters)
|
||||
osg::Vec2(.2f, .2f), // extent (meters)
|
||||
osg::Vec2i(1024,512), // resolution (pixels)
|
||||
TrackedLimb::RIGHT_HAND,
|
||||
TrackingMode::Auto,
|
||||
false // vertical
|
||||
};
|
||||
|
||||
LayerConfig gMinimapHUDConfig = LayerConfig
|
||||
{
|
||||
false, // stretch
|
||||
osg::Vec4{0.f,0.f,0.f,0.f}, // background
|
||||
osg::Quat{}, // rotation
|
||||
osg::Vec3(0.f,.0f,.2f), // offset (meters)
|
||||
osg::Vec2(.2f, .2f), // extent (meters)
|
||||
osg::Vec2i(1024,512), // resolution (pixels)
|
||||
TrackedLimb::RIGHT_HAND,
|
||||
TrackingMode::Auto,
|
||||
false // vertical
|
||||
};
|
||||
|
||||
LayerConfig gPopupConfig = LayerConfig
|
||||
{
|
||||
false, // stretch
|
||||
osg::Vec4{0.f,0.f,0.f,0.f}, // background
|
||||
osg::Quat{}, // rotation
|
||||
osg::Vec3(0.f,0.f,.2f), // offset
|
||||
osg::Vec2(.2f, .2f), // extent (meters)
|
||||
osg::Vec2i(1024,1024),
|
||||
TrackedLimb::RIGHT_HAND,
|
||||
TrackingMode::Auto,
|
||||
false // vertical
|
||||
};
|
||||
|
||||
LayerConfig gWindowsConfig = gDefaultConfig;
|
||||
LayerConfig gJournalBooksConfig = LayerConfig
|
||||
{
|
||||
true, // stretch
|
||||
gDefaultConfig.backgroundColor,
|
||||
osg::Quat{}, // rotation
|
||||
gDefaultConfig.offset,
|
||||
gDefaultConfig.extent,
|
||||
gDefaultConfig.resolution,
|
||||
TrackedLimb::HEAD,
|
||||
TrackingMode::Manual,
|
||||
true // vertical
|
||||
};
|
||||
LayerConfig gSpellWindowConfig = LayerConfig
|
||||
{
|
||||
true, // stretch
|
||||
gDefaultConfig.backgroundColor,
|
||||
osg::Quat{-osg::PI_2, osg::Z_AXIS}, // rotation
|
||||
gDefaultConfig.offset,
|
||||
gDefaultConfig.extent,
|
||||
gDefaultConfig.resolution,
|
||||
TrackedLimb::HEAD,
|
||||
TrackingMode::Manual,
|
||||
true // vertical
|
||||
};
|
||||
LayerConfig gInventoryWindowConfig = LayerConfig
|
||||
{
|
||||
true, // stretch
|
||||
gDefaultConfig.backgroundColor,
|
||||
osg::Quat{}, // rotation
|
||||
gDefaultConfig.offset,
|
||||
gDefaultConfig.extent,
|
||||
gDefaultConfig.resolution,
|
||||
TrackedLimb::HEAD,
|
||||
TrackingMode::Manual,
|
||||
true // vertical
|
||||
};
|
||||
LayerConfig gMapWindowConfig = LayerConfig
|
||||
{
|
||||
true, // stretch
|
||||
gDefaultConfig.backgroundColor,
|
||||
osg::Quat{osg::PI, osg::Z_AXIS}, // rotation
|
||||
gDefaultConfig.offset,
|
||||
gDefaultConfig.extent,
|
||||
gDefaultConfig.resolution,
|
||||
TrackedLimb::HEAD,
|
||||
TrackingMode::Manual,
|
||||
true // vertical
|
||||
};
|
||||
LayerConfig gStatsWindowConfig = LayerConfig
|
||||
{
|
||||
true, // stretch
|
||||
gDefaultConfig.backgroundColor,
|
||||
osg::Quat{osg::PI_2, osg::Z_AXIS}, // rotation
|
||||
gDefaultConfig.offset,
|
||||
gDefaultConfig.extent,
|
||||
gDefaultConfig.resolution,
|
||||
TrackedLimb::HEAD,
|
||||
TrackingMode::Manual,
|
||||
true // vertical
|
||||
};
|
||||
|
||||
|
||||
static std::map<std::string, LayerConfig&> gLayerConfigs =
|
||||
{
|
||||
{"StatusHUD", gStatusHUDConfig},
|
||||
{"MinimapHUD", gMinimapHUDConfig},
|
||||
{"Popup", gPopupConfig},
|
||||
{"Windows", gWindowsConfig},
|
||||
{"JournalBooks", gJournalBooksConfig},
|
||||
{"SpellWindow", gSpellWindowConfig},
|
||||
{"InventoryWindow", gInventoryWindowConfig},
|
||||
{"MapWindow", gMapWindowConfig},
|
||||
{"StatsWindow", gStatsWindowConfig},
|
||||
{"Default", gDefaultConfig},
|
||||
};
|
||||
|
||||
static std::set<std::string> layerBlacklist =
|
||||
{
|
||||
"Overlay"
|
||||
};
|
||||
|
||||
void VRGUIManager::setVisible(MWGui::Layout* widget, bool visible)
|
||||
{
|
||||
auto* layer = widget->mMainWidget->getLayer();
|
||||
//if (!layer)
|
||||
//{
|
||||
// Log(Debug::Warning) << "Hark! MyGUI has betrayed us. The widget " << widget->mMainWidget->getName() << " has no layer";
|
||||
// return;
|
||||
//}
|
||||
auto name = layer->getName();
|
||||
|
||||
Log(Debug::Verbose) << "setVisible (" << name << "): " << visible;
|
||||
if (layerBlacklist.find(name) != layerBlacklist.end())
|
||||
{
|
||||
Log(Debug::Verbose) << "Blacklisted";
|
||||
// Never pick an invisible layer
|
||||
widget->setLayerPick(false);
|
||||
return;
|
||||
}
|
||||
if (visible)
|
||||
{
|
||||
if (mLayers.find(name) == mLayers.end())
|
||||
{
|
||||
LayerConfig config = gDefaultConfig;
|
||||
auto configIt = gLayerConfigs.find(name);
|
||||
if (configIt != gLayerConfigs.end())
|
||||
config = configIt->second;
|
||||
|
||||
mLayers[name] = std::unique_ptr<VRGUILayer>(new VRGUILayer(
|
||||
mGUIGeometriesRoot,
|
||||
mGUICamerasRoot,
|
||||
2048,
|
||||
2048,
|
||||
name,
|
||||
config,
|
||||
widget,
|
||||
this
|
||||
));
|
||||
|
||||
// Default new layer's pick to false
|
||||
widget->setLayerPick(false);
|
||||
|
||||
Log(Debug::Verbose) << "Created GUI layer " << name;
|
||||
}
|
||||
updatePose();
|
||||
}
|
||||
else
|
||||
{
|
||||
auto it = mLayers.find(name);
|
||||
if (it != mLayers.end())
|
||||
{
|
||||
if (it->second.get() == mFocusLayer)
|
||||
setFocusLayer(nullptr);
|
||||
mLayers.erase(it);
|
||||
Log(Debug::Verbose) << "Erased GUI layer " << name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VRGUIManager::updatePose(void)
|
||||
{
|
||||
for (auto& layer : mLayers)
|
||||
layer.second->updatePose();
|
||||
}
|
||||
|
||||
void VRGUIManager::setFocusLayer(VRGUILayer* layer)
|
||||
{
|
||||
if (mFocusLayer)
|
||||
mFocusLayer->mWidget->setLayerPick(false);
|
||||
mFocusLayer = layer;
|
||||
if (mFocusLayer)
|
||||
mFocusLayer->mWidget->setLayerPick(true);
|
||||
|
||||
}
|
||||
|
||||
}
|
129
apps/openmw/mwvr/vrgui.hpp
Normal file
129
apps/openmw/mwvr/vrgui.hpp
Normal file
|
@ -0,0 +1,129 @@
|
|||
#ifndef OPENXR_MENU_HPP
|
||||
#define OPENXR_MENU_HPP
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <regex>
|
||||
|
||||
#include <osg/Geometry>
|
||||
#include <osg/TexMat>
|
||||
#include <osg/Texture2D>
|
||||
#include <osg/Camera>
|
||||
#include <osg/PositionAttitudeTransform>
|
||||
|
||||
#include "openxrview.hpp"
|
||||
#include "openxrlayer.hpp"
|
||||
|
||||
namespace MyGUI
|
||||
{
|
||||
class Widget;
|
||||
class Window;
|
||||
}
|
||||
|
||||
namespace MWGui
|
||||
{
|
||||
class Layout;
|
||||
class WindowBase;
|
||||
}
|
||||
|
||||
struct XrCompositionLayerQuad;
|
||||
namespace MWVR
|
||||
{
|
||||
class GUICamera;
|
||||
class VRGUIManager;
|
||||
|
||||
enum class TrackingMode
|
||||
{
|
||||
Auto, //!< Update tracking every frame
|
||||
Manual //!< Update tracking only on user request or when GUI visibility changes.
|
||||
};
|
||||
|
||||
struct LayerConfig
|
||||
{
|
||||
bool stretch; //!< Resize layer window to occupy full quad
|
||||
osg::Vec4 backgroundColor; //!< Background color of layer
|
||||
osg::Quat rotation; //!< Rotation relative to the tracking node
|
||||
osg::Vec3 offset; //!< Offset from tracked node in meters
|
||||
osg::Vec2 extent; //!< Spatial extent of the layer in meters
|
||||
osg::Vec2i resolution; //!< Pixel resolution of the texture
|
||||
TrackedLimb trackedLimb; //!< Which limb to track
|
||||
TrackingMode trackingMode; //!< Tracking mode
|
||||
bool vertical; //!< Make layer vertical regardless of tracking orientation
|
||||
};
|
||||
|
||||
class VRGUILayer
|
||||
{
|
||||
public:
|
||||
VRGUILayer(
|
||||
osg::ref_ptr<osg::Group> geometryRoot,
|
||||
osg::ref_ptr<osg::Group> cameraRoot,
|
||||
int width,
|
||||
int height,
|
||||
std::string filter,
|
||||
LayerConfig config,
|
||||
MWGui::Layout* widget,
|
||||
VRGUIManager* parent);
|
||||
~VRGUILayer();
|
||||
|
||||
osg::Camera* camera();
|
||||
|
||||
osg::ref_ptr<osg::Texture2D> menuTexture();
|
||||
|
||||
void updatePose();
|
||||
void update();
|
||||
|
||||
public:
|
||||
Pose mTrackedPose{};
|
||||
Pose mLayerPose{};
|
||||
LayerConfig mConfig;
|
||||
std::string mFilter;
|
||||
MWGui::Layout* mWidget;
|
||||
MWGui::WindowBase* mWindow;
|
||||
MyGUI::Window* mMyGUIWindow;
|
||||
VRGUIManager* mParent;
|
||||
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<osg::StateSet> mStateSet{ new osg::StateSet };
|
||||
osg::ref_ptr<GUICamera> mGUICamera;
|
||||
};
|
||||
|
||||
class VRGUILayerUserData : public osg::Referenced
|
||||
{
|
||||
public:
|
||||
VRGUILayerUserData(VRGUILayer* layer) : mLayer(layer) {};
|
||||
|
||||
VRGUILayer* mLayer;
|
||||
};
|
||||
|
||||
class VRGUIManager
|
||||
{
|
||||
public:
|
||||
VRGUIManager(
|
||||
osg::ref_ptr<osgViewer::Viewer> viewer);
|
||||
|
||||
~VRGUIManager(void);
|
||||
|
||||
void showGUIs(bool show);
|
||||
|
||||
void setVisible(MWGui::Layout*, bool visible);
|
||||
|
||||
void updatePose(void);
|
||||
|
||||
void setFocusLayer(VRGUILayer* layer);
|
||||
|
||||
private:
|
||||
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 };
|
||||
|
||||
std::map<std::string, std::unique_ptr<VRGUILayer>> mLayers;
|
||||
|
||||
VRGUILayer* mFocusLayer{ nullptr };
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,5 +1,5 @@
|
|||
#include "openxrviewer.hpp"
|
||||
#include "openxrtexture.hpp"
|
||||
#include "vrtexture.hpp"
|
||||
#include <osg/Texture2D>
|
||||
#include <osgViewer/Renderer>
|
||||
#include <components/debug/debuglog.hpp>
|
||||
|
@ -13,7 +13,7 @@
|
|||
|
||||
namespace MWVR
|
||||
{
|
||||
OpenXRTextureBuffer::OpenXRTextureBuffer(
|
||||
VRTexture::VRTexture(
|
||||
osg::ref_ptr<osg::State> state,
|
||||
std::size_t width,
|
||||
std::size_t height,
|
||||
|
@ -71,12 +71,12 @@ namespace MWVR
|
|||
gl->glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
|
||||
}
|
||||
|
||||
OpenXRTextureBuffer::~OpenXRTextureBuffer()
|
||||
VRTexture::~VRTexture()
|
||||
{
|
||||
destroy(nullptr);
|
||||
}
|
||||
|
||||
void OpenXRTextureBuffer::destroy(osg::State* state)
|
||||
void VRTexture::destroy(osg::State* state)
|
||||
{
|
||||
if (!state)
|
||||
{
|
||||
|
@ -102,14 +102,14 @@ namespace MWVR
|
|||
mFBO = mDepthBuffer = mColorBuffer;
|
||||
}
|
||||
|
||||
void OpenXRTextureBuffer::beginFrame(osg::GraphicsContext* gc)
|
||||
void VRTexture::beginFrame(osg::GraphicsContext* gc)
|
||||
{
|
||||
auto state = gc->getState();
|
||||
auto* gl = osg::GLExtensions::Get(state->getContextID(), false);
|
||||
gl->glBindFramebuffer(GL_FRAMEBUFFER_EXT, mFBO);
|
||||
}
|
||||
|
||||
void OpenXRTextureBuffer::endFrame(osg::GraphicsContext* gc, uint32_t blitTarget)
|
||||
void VRTexture::endFrame(osg::GraphicsContext* gc, uint32_t blitTarget)
|
||||
{
|
||||
auto* state = gc->getState();
|
||||
auto* gl = osg::GLExtensions::Get(state->getContextID(), false);
|
||||
|
@ -122,7 +122,7 @@ namespace MWVR
|
|||
gl->glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, 0);
|
||||
}
|
||||
|
||||
void OpenXRTextureBuffer::blit(osg::GraphicsContext* gc, int x, int y, int w, int h)
|
||||
void VRTexture::blit(osg::GraphicsContext* gc, int x, int y, int w, int h)
|
||||
{
|
||||
auto* state = gc->getState();
|
||||
auto* gl = osg::GLExtensions::Get(state->getContextID(), false);
|
||||
|
@ -131,7 +131,7 @@ namespace MWVR
|
|||
gl->glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, 0);
|
||||
}
|
||||
|
||||
void OpenXRTextureBuffer::blit(osg::GraphicsContext* gc, int x, int y, int w, int h, int blitTarget)
|
||||
void VRTexture::blit(osg::GraphicsContext* gc, int x, int y, int w, int h, int blitTarget)
|
||||
{
|
||||
auto* state = gc->getState();
|
||||
auto* gl = osg::GLExtensions::Get(state->getContextID(), false);
|
|
@ -10,11 +10,11 @@
|
|||
|
||||
namespace MWVR
|
||||
{
|
||||
class OpenXRTextureBuffer : public osg::Referenced
|
||||
class VRTexture : public osg::Referenced
|
||||
{
|
||||
public:
|
||||
OpenXRTextureBuffer(osg::ref_ptr<osg::State> state, std::size_t width, std::size_t height, uint32_t msaaSamples);
|
||||
~OpenXRTextureBuffer();
|
||||
VRTexture(osg::ref_ptr<osg::State> state, std::size_t width, std::size_t height, uint32_t msaaSamples);
|
||||
~VRTexture();
|
||||
|
||||
void destroy(osg::State* state);
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
#include "mwvr/openxrmanager.hpp"
|
||||
#include "mwvr/openxrsession.hpp"
|
||||
#include "mwvr/openxrviewer.hpp"
|
||||
#include "mwvr/openxrmenu.hpp"
|
||||
#include "mwvr/vrgui.hpp"
|
||||
|
||||
#ifndef USE_OPENXR
|
||||
#error "USE_OPENXR not defined"
|
||||
|
|
|
@ -21,13 +21,13 @@ namespace osgMyGUI
|
|||
|
||||
void AdditiveLayer::renderToTarget(MyGUI::IRenderTarget *_target, bool _update)
|
||||
{
|
||||
RenderManager& renderManager = static_cast<RenderManager&>(MyGUI::RenderManager::getInstance());
|
||||
StateInjectableRenderTarget* injectableTarget = static_cast<StateInjectableRenderTarget*>(_target);
|
||||
|
||||
renderManager.setInjectState(mStateSet.get());
|
||||
injectableTarget->setInjectState(mStateSet.get());
|
||||
|
||||
MyGUI::OverlappedLayer::renderToTarget(_target, _update);
|
||||
|
||||
renderManager.setInjectState(nullptr);
|
||||
injectableTarget->setInjectState(nullptr);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,15 +7,14 @@
|
|||
namespace osgMyGUI
|
||||
{
|
||||
|
||||
Platform::Platform(osgViewer::Viewer *viewer, osg::Group *guiRoot, Resource::ImageManager *imageManager, float uiScalingFactor, bool VRMode)
|
||||
Platform::Platform(osgViewer::Viewer *viewer, osg::Group *guiRoot, Resource::ImageManager *imageManager, float uiScalingFactor)
|
||||
: mRenderManager(nullptr)
|
||||
, mDataManager(nullptr)
|
||||
, mLogManager(nullptr)
|
||||
, mLogFacility(nullptr)
|
||||
, mVRMode(VRMode)
|
||||
{
|
||||
mLogManager = new MyGUI::LogManager();
|
||||
mRenderManager = new RenderManager(viewer, guiRoot, imageManager, uiScalingFactor, VRMode);
|
||||
mRenderManager = new RenderManager(viewer, guiRoot, imageManager, uiScalingFactor);
|
||||
mDataManager = new DataManager();
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ namespace osgMyGUI
|
|||
class Platform
|
||||
{
|
||||
public:
|
||||
Platform(osgViewer::Viewer* viewer, osg::Group* guiRoot, Resource::ImageManager* imageManager, float uiScalingFactor, bool VRMode);
|
||||
Platform(osgViewer::Viewer* viewer, osg::Group* guiRoot, Resource::ImageManager* imageManager, float uiScalingFactor);
|
||||
|
||||
~Platform();
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#include "myguirendermanager.hpp"
|
||||
|
||||
#include <regex>
|
||||
|
||||
#include <MyGUI_Gui.h>
|
||||
#include <MyGUI_Timer.h>
|
||||
#include <MyGUI_LayerManager.h>
|
||||
|
@ -42,8 +44,10 @@
|
|||
namespace osgMyGUI
|
||||
{
|
||||
|
||||
class GUICamera;
|
||||
|
||||
class Drawable : public osg::Drawable {
|
||||
osgMyGUI::RenderManager *mParent;
|
||||
osgMyGUI::RenderManager *mManager;
|
||||
osg::ref_ptr<osg::StateSet> mStateSet;
|
||||
|
||||
public:
|
||||
|
@ -77,26 +81,26 @@ public:
|
|||
{
|
||||
public:
|
||||
CollectDrawCalls()
|
||||
: mRenderManager(nullptr)
|
||||
: mCamera(nullptr)
|
||||
, mFilter("")
|
||||
{
|
||||
}
|
||||
|
||||
void setRenderManager(osgMyGUI::RenderManager* renderManager)
|
||||
void setCamera(osgMyGUI::GUICamera* camera)
|
||||
{
|
||||
mRenderManager = renderManager;
|
||||
mCamera = camera;
|
||||
}
|
||||
|
||||
virtual bool cull(osg::NodeVisitor*, osg::Drawable*, osg::State*) const
|
||||
void setFilter(std::string filter)
|
||||
{
|
||||
if (!mRenderManager)
|
||||
return false;
|
||||
|
||||
mRenderManager->collectDrawCalls();
|
||||
return false;
|
||||
mFilter = filter;
|
||||
}
|
||||
|
||||
virtual bool cull(osg::NodeVisitor*, osg::Drawable*, osg::State*) const;
|
||||
|
||||
private:
|
||||
osgMyGUI::RenderManager* mRenderManager;
|
||||
GUICamera* mCamera;
|
||||
std::string mFilter;
|
||||
};
|
||||
|
||||
// Stage 2: execute the draw calls. Run during the Draw traversal. May run in parallel with the update traversal of the next frame.
|
||||
|
@ -167,20 +171,24 @@ public:
|
|||
}
|
||||
|
||||
public:
|
||||
Drawable(osgMyGUI::RenderManager *parent = nullptr)
|
||||
: mParent(parent)
|
||||
Drawable(std::string filter = "", osgMyGUI::RenderManager *manager = nullptr, osgMyGUI::GUICamera* camera = nullptr)
|
||||
: mManager(manager)
|
||||
, mWriteTo(0)
|
||||
, mReadFrom(0)
|
||||
{
|
||||
setSupportsDisplayList(false);
|
||||
|
||||
osg::ref_ptr<CollectDrawCalls> collectDrawCalls = new CollectDrawCalls;
|
||||
collectDrawCalls->setRenderManager(mParent);
|
||||
collectDrawCalls->setCamera(camera);
|
||||
collectDrawCalls->setFilter(filter);
|
||||
setCullCallback(collectDrawCalls);
|
||||
|
||||
osg::ref_ptr<FrameUpdate> frameUpdate = new FrameUpdate;
|
||||
frameUpdate->setRenderManager(mParent);
|
||||
setUpdateCallback(frameUpdate);
|
||||
if (mManager)
|
||||
{
|
||||
osg::ref_ptr<FrameUpdate> frameUpdate = new FrameUpdate;
|
||||
frameUpdate->setRenderManager(mManager);
|
||||
setUpdateCallback(frameUpdate);
|
||||
}
|
||||
|
||||
mStateSet = new osg::StateSet;
|
||||
mStateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
|
||||
|
@ -196,7 +204,7 @@ public:
|
|||
}
|
||||
Drawable(const Drawable ©, const osg::CopyOp ©op=osg::CopyOp::SHALLOW_COPY)
|
||||
: osg::Drawable(copy, copyop)
|
||||
, mParent(copy.mParent)
|
||||
, mManager(copy.mManager)
|
||||
, mStateSet(copy.mStateSet)
|
||||
, mWriteTo(0)
|
||||
, mReadFrom(0)
|
||||
|
@ -349,15 +357,82 @@ osg::VertexBufferObject* OSGVertexBuffer::getVertexBuffer()
|
|||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
RenderManager::RenderManager(osgViewer::Viewer *viewer, osg::Group *sceneroot, Resource::ImageManager* imageManager, float scalingFactor, bool VRMode)
|
||||
/// Camera used to draw a MyGUI layer
|
||||
class GUICamera : public osg::Camera, public StateInjectableRenderTarget
|
||||
{
|
||||
public:
|
||||
GUICamera(osg::Camera::RenderOrder order, RenderManager* parent, std::string filter)
|
||||
: mParent(parent)
|
||||
, mUpdate(false)
|
||||
{
|
||||
setReferenceFrame(osg::Transform::ABSOLUTE_RF);
|
||||
setProjectionResizePolicy(osg::Camera::FIXED);
|
||||
setProjectionMatrix(osg::Matrix::identity());
|
||||
setViewMatrix(osg::Matrix::identity());
|
||||
setRenderOrder(order);
|
||||
setClearMask(GL_NONE);
|
||||
setName("GUI Camera");
|
||||
mDrawable = new Drawable(filter, parent, this);
|
||||
mDrawable->setName("GUI Drawable");
|
||||
addChild(mDrawable.get());
|
||||
mDrawable->setCullingActive(false);
|
||||
}
|
||||
|
||||
~GUICamera()
|
||||
{
|
||||
mParent->deleteGUICamera(this);
|
||||
}
|
||||
|
||||
|
||||
// Called by the cull traversal
|
||||
/** @see IRenderTarget::begin */
|
||||
void begin() override;
|
||||
void end() override;
|
||||
|
||||
/** @see IRenderTarget::doRender */
|
||||
void doRender(MyGUI::IVertexBuffer* buffer, MyGUI::ITexture* texture, size_t count) override;
|
||||
|
||||
|
||||
void collectDrawCalls();
|
||||
void collectDrawCalls(std::string filter);
|
||||
|
||||
void setViewSize(MyGUI::IntSize viewSize);
|
||||
|
||||
/** @see IRenderTarget::getInfo */
|
||||
const MyGUI::RenderTargetInfo& getInfo() override { return mInfo; }
|
||||
|
||||
RenderManager* mParent;
|
||||
osg::ref_ptr<Drawable> mDrawable;
|
||||
MyGUI::RenderTargetInfo mInfo;
|
||||
bool mUpdate;
|
||||
};
|
||||
|
||||
|
||||
void GUICamera::begin()
|
||||
{
|
||||
mDrawable->clear();
|
||||
// variance will be recomputed based on textures being rendered in this frame
|
||||
mDrawable->setDataVariance(osg::Object::STATIC);
|
||||
}
|
||||
|
||||
bool Drawable::CollectDrawCalls::cull(osg::NodeVisitor*, osg::Drawable*, osg::State*) const
|
||||
{
|
||||
if (!mCamera)
|
||||
return false;
|
||||
|
||||
if (mFilter.empty())
|
||||
mCamera->collectDrawCalls();
|
||||
else
|
||||
mCamera->collectDrawCalls(mFilter);
|
||||
return false;
|
||||
}
|
||||
|
||||
RenderManager::RenderManager(osgViewer::Viewer *viewer, osg::Group *sceneroot, Resource::ImageManager* imageManager, float scalingFactor)
|
||||
: mViewer(viewer)
|
||||
, mSceneRoot(sceneroot)
|
||||
, mImageManager(imageManager)
|
||||
, mUpdate(false)
|
||||
, mIsInitialise(false)
|
||||
, mInvScalingFactor(1.f)
|
||||
, mInjectState(nullptr)
|
||||
, mVRMode(VRMode)
|
||||
{
|
||||
if (scalingFactor != 0.f)
|
||||
mInvScalingFactor = 1.f / scalingFactor;
|
||||
|
@ -367,9 +442,9 @@ RenderManager::~RenderManager()
|
|||
{
|
||||
MYGUI_PLATFORM_LOG(Info, "* Shutdown: "<<getClassTypeName());
|
||||
|
||||
if(mGuiRoot.valid())
|
||||
mSceneRoot->removeChild(mGuiRoot.get());
|
||||
mGuiRoot = nullptr;
|
||||
for (auto guiCamera : mGuiCameras)
|
||||
mSceneRoot->removeChild(guiCamera);
|
||||
mGuiCameras.clear();
|
||||
mSceneRoot = nullptr;
|
||||
mViewer = nullptr;
|
||||
|
||||
|
@ -387,27 +462,7 @@ void RenderManager::initialise()
|
|||
|
||||
mVertexFormat = MyGUI::VertexColourType::ColourABGR;
|
||||
|
||||
mUpdate = false;
|
||||
|
||||
mDrawable = new Drawable(this);
|
||||
mDrawable->setName("GUI Drawable");
|
||||
|
||||
osg::ref_ptr<osg::Camera> camera = new osg::Camera();
|
||||
camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
|
||||
camera->setProjectionResizePolicy(osg::Camera::FIXED);
|
||||
camera->setProjectionMatrix(osg::Matrix::identity());
|
||||
camera->setViewMatrix(osg::Matrix::identity());
|
||||
camera->setRenderOrder(mVRMode ? osg::Camera::NESTED_RENDER : osg::Camera::POST_RENDER);
|
||||
camera->setClearMask(GL_NONE);
|
||||
mDrawable->setCullingActive(false);
|
||||
camera->addChild(mDrawable.get());
|
||||
camera->setName("GUI Camera");
|
||||
|
||||
mGuiRoot = camera;
|
||||
mSceneRoot->addChild(mGuiRoot.get());
|
||||
|
||||
osg::ref_ptr<osg::Viewport> vp = mViewer->getCamera()->getViewport();
|
||||
setViewSize(vp->width(), vp->height());
|
||||
mSceneRoot->addChild(createGUICamera(osg::Camera::POST_RENDER, ""));
|
||||
|
||||
MYGUI_PLATFORM_LOG(Info, getClassTypeName()<<" successfully initialized");
|
||||
mIsInitialise = true;
|
||||
|
@ -415,8 +470,12 @@ void RenderManager::initialise()
|
|||
|
||||
void RenderManager::shutdown()
|
||||
{
|
||||
mGuiRoot->removeChildren(0, mGuiRoot->getNumChildren());
|
||||
mSceneRoot->removeChild(mGuiRoot);
|
||||
// TODO: Is this method meaningful? Why not just let the destructor handle everything?
|
||||
for (auto guiCamera : mGuiCameras)
|
||||
{
|
||||
guiCamera->removeChildren(0, guiCamera->getNumChildren());
|
||||
mSceneRoot->removeChild(guiCamera);
|
||||
}
|
||||
}
|
||||
|
||||
MyGUI::IVertexBuffer* RenderManager::createVertexBuffer()
|
||||
|
@ -429,15 +488,7 @@ void RenderManager::destroyVertexBuffer(MyGUI::IVertexBuffer *buffer)
|
|||
delete buffer;
|
||||
}
|
||||
|
||||
|
||||
void RenderManager::begin()
|
||||
{
|
||||
mDrawable->clear();
|
||||
// variance will be recomputed based on textures being rendered in this frame
|
||||
mDrawable->setDataVariance(osg::Object::STATIC);
|
||||
}
|
||||
|
||||
void RenderManager::doRender(MyGUI::IVertexBuffer *buffer, MyGUI::ITexture *texture, size_t count)
|
||||
void GUICamera::doRender(MyGUI::IVertexBuffer *buffer, MyGUI::ITexture *texture, size_t count)
|
||||
{
|
||||
Drawable::Batch batch;
|
||||
batch.mVertexCount = count;
|
||||
|
@ -450,31 +501,19 @@ void RenderManager::doRender(MyGUI::IVertexBuffer *buffer, MyGUI::ITexture *text
|
|||
if (batch.mTexture->getDataVariance() == osg::Object::DYNAMIC)
|
||||
mDrawable->setDataVariance(osg::Object::DYNAMIC); // only for this frame, reset in begin()
|
||||
}
|
||||
|
||||
if (mInjectState)
|
||||
batch.mStateSet = mInjectState;
|
||||
|
||||
mDrawable->addBatch(batch);
|
||||
}
|
||||
|
||||
void RenderManager::onRenderToTarget(IRenderTarget* _target, bool _update)
|
||||
{
|
||||
MyGUI::LayerManager* layers = MyGUI::LayerManager::getInstancePtr();
|
||||
if (layers != nullptr)
|
||||
{
|
||||
for (unsigned i = 0; i < layers->getLayerCount(); i++)
|
||||
{
|
||||
auto layer = layers->getLayer(i);
|
||||
layer->renderToTarget(_target, _update);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RenderManager::setInjectState(osg::StateSet* stateSet)
|
||||
void StateInjectableRenderTarget::setInjectState(osg::StateSet* stateSet)
|
||||
{
|
||||
mInjectState = stateSet;
|
||||
}
|
||||
|
||||
void RenderManager::end()
|
||||
void GUICamera::end()
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -490,33 +529,90 @@ void RenderManager::update()
|
|||
last_time = now_time;
|
||||
}
|
||||
|
||||
void RenderManager::collectDrawCalls()
|
||||
void GUICamera::collectDrawCalls()
|
||||
{
|
||||
begin();
|
||||
onRenderToTarget(this, mUpdate);
|
||||
MyGUI::LayerManager* myGUILayers = MyGUI::LayerManager::getInstancePtr();
|
||||
if (myGUILayers != nullptr)
|
||||
{
|
||||
for (unsigned i = 0; i < myGUILayers->getLayerCount(); i++)
|
||||
{
|
||||
auto layer = myGUILayers->getLayer(i);
|
||||
layer->renderToTarget(this, mUpdate);
|
||||
}
|
||||
}
|
||||
end();
|
||||
|
||||
mUpdate = false;
|
||||
}
|
||||
|
||||
void GUICamera::collectDrawCalls(std::string filter)
|
||||
{
|
||||
begin();
|
||||
MyGUI::LayerManager* myGUILayers = MyGUI::LayerManager::getInstancePtr();
|
||||
if (myGUILayers != nullptr)
|
||||
{
|
||||
std::regex layerRegex{ filter, std::regex_constants::icase };
|
||||
for (unsigned i = 0; i < myGUILayers->getLayerCount(); i++)
|
||||
{
|
||||
auto layer = myGUILayers->getLayer(i);
|
||||
|
||||
auto name = layer->getName();
|
||||
|
||||
if (std::regex_search(name, layerRegex))
|
||||
{
|
||||
//std::cout << "Including Layer: " << layer->getName() << std::endl;
|
||||
layer->renderToTarget(this, mUpdate);
|
||||
}
|
||||
else {
|
||||
//std::cout << "Excluding Layer: " << layer->getName() << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
end();
|
||||
|
||||
mUpdate = false;
|
||||
}
|
||||
|
||||
void GUICamera::setViewSize(MyGUI::IntSize viewSize)
|
||||
{
|
||||
mInfo.maximumDepth = 1;
|
||||
mInfo.hOffset = 0;
|
||||
mInfo.vOffset = 0;
|
||||
mInfo.aspectCoef = float(viewSize.height) / float(viewSize.width);
|
||||
mInfo.pixScaleX = 1.0f / float(viewSize.width);
|
||||
mInfo.pixScaleY = 1.0f / float(viewSize.height);
|
||||
mUpdate = true;
|
||||
}
|
||||
|
||||
void RenderManager::setViewSize(int width, int height)
|
||||
{
|
||||
if(width < 1) width = 1;
|
||||
if(height < 1) height = 1;
|
||||
|
||||
mGuiRoot->setViewport(0, 0, width, height);
|
||||
|
||||
mViewSize.set(width * mInvScalingFactor, height * mInvScalingFactor);
|
||||
|
||||
mInfo.maximumDepth = 1;
|
||||
mInfo.hOffset = 0;
|
||||
mInfo.vOffset = 0;
|
||||
mInfo.aspectCoef = float(mViewSize.height) / float(mViewSize.width);
|
||||
mInfo.pixScaleX = 1.0f / float(mViewSize.width);
|
||||
mInfo.pixScaleY = 1.0f / float(mViewSize.height);
|
||||
|
||||
for (auto* camera : mGuiCameras)
|
||||
{
|
||||
GUICamera* guiCamera = static_cast<GUICamera*>(camera);
|
||||
guiCamera->setViewport(0, 0, width, height);
|
||||
guiCamera->setViewSize(mViewSize);
|
||||
}
|
||||
onResizeView(mViewSize);
|
||||
mUpdate = true;
|
||||
}
|
||||
|
||||
osg::ref_ptr<osg::Camera> RenderManager::createGUICamera(int order, std::string layerFilter)
|
||||
{
|
||||
osg::ref_ptr<GUICamera> camera = new GUICamera(static_cast<osg::Camera::RenderOrder>(order), this, layerFilter);
|
||||
mGuiCameras.insert(camera);
|
||||
osg::ref_ptr<osg::Viewport> vp = mViewer->getCamera()->getViewport();
|
||||
setViewSize(vp->width(), vp->height());
|
||||
return camera;
|
||||
}
|
||||
|
||||
void RenderManager::deleteGUICamera(GUICamera* camera)
|
||||
{
|
||||
mGuiCameras.erase(camera);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <MyGUI_RenderManager.h>
|
||||
|
||||
#include <osg/ref_ptr>
|
||||
#include <set>
|
||||
|
||||
namespace Resource
|
||||
{
|
||||
|
@ -27,36 +28,46 @@ namespace osgMyGUI
|
|||
{
|
||||
|
||||
class Drawable;
|
||||
class GUICamera;
|
||||
|
||||
class RenderManager : public MyGUI::RenderManager, public MyGUI::IRenderTarget
|
||||
class StateInjectableRenderTarget : public MyGUI::IRenderTarget
|
||||
{
|
||||
public:
|
||||
StateInjectableRenderTarget() = default;
|
||||
~StateInjectableRenderTarget() = default;
|
||||
|
||||
/** specify a StateSet to inject for rendering. The StateSet will be used by future doRender calls until you reset it to nullptr again. */
|
||||
void setInjectState(osg::StateSet* stateSet);
|
||||
|
||||
protected:
|
||||
osg::StateSet* mInjectState{ nullptr };
|
||||
};
|
||||
|
||||
class RenderManager : public MyGUI::RenderManager
|
||||
{
|
||||
osg::ref_ptr<osgViewer::Viewer> mViewer;
|
||||
osg::ref_ptr<osg::Group> mSceneRoot;
|
||||
osg::ref_ptr<Drawable> mDrawable;
|
||||
osg::ref_ptr<GUICamera> mGuiCamera;
|
||||
std::set<GUICamera*> mGuiCameras;
|
||||
Resource::ImageManager* mImageManager;
|
||||
|
||||
MyGUI::IntSize mViewSize;
|
||||
bool mUpdate;
|
||||
|
||||
MyGUI::VertexColourType mVertexFormat;
|
||||
MyGUI::RenderTargetInfo mInfo;
|
||||
|
||||
typedef std::map<std::string, MyGUI::ITexture*> MapTexture;
|
||||
MapTexture mTextures;
|
||||
|
||||
bool mIsInitialise;
|
||||
|
||||
osg::ref_ptr<osg::Camera> mGuiRoot;
|
||||
|
||||
float mInvScalingFactor;
|
||||
|
||||
osg::StateSet* mInjectState;
|
||||
|
||||
bool mVRMode;
|
||||
|
||||
void destroyAllResources();
|
||||
|
||||
public:
|
||||
RenderManager(osgViewer::Viewer *viewer, osg::Group *sceneroot, Resource::ImageManager* imageManager, float scalingFactor, bool VRMode);
|
||||
RenderManager(osgViewer::Viewer *viewer, osg::Group *sceneroot, Resource::ImageManager* imageManager, float scalingFactor);
|
||||
virtual ~RenderManager();
|
||||
|
||||
void initialise();
|
||||
|
@ -92,29 +103,12 @@ public:
|
|||
// Called by the update traversal
|
||||
void update();
|
||||
|
||||
// Called by the cull traversal
|
||||
/** @see IRenderTarget::begin */
|
||||
virtual void begin();
|
||||
/** @see IRenderTarget::end */
|
||||
virtual void end();
|
||||
/** @see IRenderTarget::doRender */
|
||||
void doRender(MyGUI::IVertexBuffer *buffer, MyGUI::ITexture *texture, size_t count) override;
|
||||
|
||||
/** @see IRenderTarget::onRenderToTarget */
|
||||
void onRenderToTarget(IRenderTarget* _target, bool _update) override;
|
||||
|
||||
/** specify a StateSet to inject for rendering. The StateSet will be used by future doRender calls until you reset it to nullptr again. */
|
||||
void setInjectState(osg::StateSet* stateSet);
|
||||
|
||||
/** @see IRenderTarget::getInfo */
|
||||
virtual const MyGUI::RenderTargetInfo& getInfo() { return mInfo; }
|
||||
|
||||
bool checkTexture(MyGUI::ITexture* _texture);
|
||||
|
||||
/*internal:*/
|
||||
|
||||
void collectDrawCalls();
|
||||
void setViewSize(int width, int height);
|
||||
|
||||
osg::ref_ptr<osg::Camera> createGUICamera(int order, std::string layerFilter);
|
||||
void deleteGUICamera(GUICamera* camera);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -87,7 +87,8 @@ namespace SceneUtil
|
|||
}
|
||||
}
|
||||
|
||||
ShadowManager::ShadowManager(osg::ref_ptr<osg::Group> sceneRoot, osg::ref_ptr<osg::Group> rootNode, unsigned int outdoorShadowCastingMask, unsigned int indoorShadowCastingMask, Shader::ShaderManager &shaderManager) : mShadowedScene(new osgShadow::ShadowedScene),
|
||||
ShadowManager::ShadowManager(osg::ref_ptr<osg::Group> sceneRoot, osg::ref_ptr<osg::Group> rootNode, unsigned int outdoorShadowCastingMask, unsigned int indoorShadowCastingMask, Shader::ShaderManager &shaderManager)
|
||||
: mShadowedScene(new osgShadow::ShadowedScene),
|
||||
mShadowTechnique(new MWShadowTechnique),
|
||||
mOutdoorShadowCastingMask(outdoorShadowCastingMask),
|
||||
mIndoorShadowCastingMask(indoorShadowCastingMask)
|
||||
|
|
|
@ -9,6 +9,7 @@ set(DDIRRELATIVE resources/mygui)
|
|||
set(MYGUI_FILES
|
||||
core.skin
|
||||
core.xml
|
||||
core_vr.xml
|
||||
core_layouteditor.xml
|
||||
openmw_alchemy_window.layout
|
||||
openmw_book.layout
|
||||
|
@ -36,17 +37,21 @@ set(MYGUI_FILES
|
|||
openmw_hud_box.skin.xml
|
||||
openmw_hud_energybar.skin.xml
|
||||
openmw_hud.layout
|
||||
openmw_hud_vr.layout
|
||||
openmw_infobox.layout
|
||||
openmw_interactive_messagebox.layout
|
||||
openmw_interactive_messagebox_notransp.layout
|
||||
openmw_inventory_window.layout
|
||||
openmw_inventory_window_vr.layout
|
||||
openmw_journal.layout
|
||||
openmw_journal.skin.xml
|
||||
openmw_layers.xml
|
||||
openmw_layers_vr.xml
|
||||
openmw_list.skin.xml
|
||||
openmw_mainmenu.layout
|
||||
openmw_mainmenu.skin.xml
|
||||
openmw_map_window.layout
|
||||
openmw_map_window_vr.layout
|
||||
openmw_map_window.skin.xml
|
||||
openmw_messagebox.layout
|
||||
openmw_pointer.xml
|
||||
|
@ -57,7 +62,9 @@ set(MYGUI_FILES
|
|||
openmw_settings_window.layout
|
||||
openmw_settings.xml
|
||||
openmw_spell_window.layout
|
||||
openmw_spell_window_vr.layout
|
||||
openmw_stats_window.layout
|
||||
openmw_stats_window_vr.layout
|
||||
openmw_text_input.layout
|
||||
openmw_text.skin.xml
|
||||
openmw_tooltips.layout
|
||||
|
|
10
files/mygui/core_vr.xml
Normal file
10
files/mygui/core_vr.xml
Normal file
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<MyGUI>
|
||||
<MyGUI type="List">
|
||||
<List file="skins.xml" />
|
||||
<List file="openmw_layers_vr.xml" />
|
||||
<List file="openmw_pointer.xml" />
|
||||
<List file="openmw_settings.xml" />
|
||||
</MyGUI>
|
||||
</MyGUI>
|
||||
|
132
files/mygui/openmw_hud_vr.layout
Normal file
132
files/mygui/openmw_hud_vr.layout
Normal file
|
@ -0,0 +1,132 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<MyGUI type="Layout">
|
||||
<Widget type="Widget" layer="StatusHUD" position="0 0 185 80" name="_Main" align="Default">
|
||||
<!-- Spell effects box -->
|
||||
<Widget type="Widget" skin="HUD_Box_Transparent" position="0 15 20 20" align="Left Bottom" name="EffectBox">
|
||||
</Widget>
|
||||
<!-- Energy bars -->
|
||||
<Widget type="ProgressBar" skin="MW_EnergyBar_Yellow" position="0 0 65 12" align="Left Bottom" name="EnemyHealth">
|
||||
<Property key="Visible" value="false"/>
|
||||
</Widget>
|
||||
<Widget type="Button" skin="" position="0 38 65 12" align="Left Bottom" name="HealthFrame">
|
||||
<UserString key="ToolTipType" value="Layout"/>
|
||||
<UserString key="ToolTipLayout" value="HealthToolTip"/>
|
||||
<UserString key="ImageTexture_HealthImage" value="icons\k\health.dds"/>
|
||||
<Widget type="ProgressBar" skin="MW_EnergyBar_Red" position="0 0 65 12" align="Left Bottom" name="Health">
|
||||
<Property key="NeedMouse" value="false"/>
|
||||
</Widget>
|
||||
</Widget>
|
||||
<Widget type="Button" skin="" position="0 53 65 12" align="Left Bottom" name="MagickaFrame">
|
||||
<UserString key="ToolTipType" value="Layout"/>
|
||||
<UserString key="ToolTipLayout" value="HealthToolTip"/>
|
||||
<UserString key="ImageTexture_HealthImage" value="icons\k\magicka.dds"/>
|
||||
<Widget type="ProgressBar" skin="MW_EnergyBar_Blue" position="0 0 65 12" align="Left Bottom" name="Magicka">
|
||||
<Property key="NeedMouse" value="false"/>
|
||||
</Widget>
|
||||
</Widget>
|
||||
<Widget type="Button" skin="" position="0 68 65 12" align="Left Bottom" name="FatigueFrame">
|
||||
<UserString key="ToolTipType" value="Layout"/>
|
||||
<UserString key="ToolTipLayout" value="HealthToolTip"/>
|
||||
<UserString key="ImageTexture_HealthImage" value="icons\k\fatigue.dds"/>
|
||||
<Widget type="ProgressBar" skin="MW_EnergyBar_Green" position="0 0 65 12" align="Left Bottom" name="Stamina">
|
||||
<Property key="NeedMouse" value="false"/>
|
||||
</Widget>
|
||||
</Widget>
|
||||
|
||||
<!-- Equipped weapon box -->
|
||||
<Widget type="Button" skin="" position="69 38 36 41" align="Left Bottom" name="WeapBox">
|
||||
<Widget type="Widget" skin="HUD_Box" position="0 0 36 36">
|
||||
<Property key="NeedMouse" value="false"/>
|
||||
<Widget type="ItemWidget" skin="MW_ItemIconNoShadow" position="-3 -3 42 42" align="Left Top" name="WeapImage">
|
||||
<Property key="NeedMouse" value="false"/>
|
||||
</Widget>
|
||||
</Widget>
|
||||
<Widget type="ProgressBar" skin="MW_EnergyBar_Weapon" position="0 36 36 6" align="Left Bottom" name="WeapStatus">
|
||||
<Property key="NeedMouse" value="false"/>
|
||||
</Widget>
|
||||
</Widget>
|
||||
|
||||
<!-- Selected spell box -->
|
||||
<Widget type="Button" position="109 38 36 41" align="Left Bottom" name="SpellBox">
|
||||
<Widget type="Widget" skin="HUD_Box" position="0 0 36 36">
|
||||
<Widget type="SpellWidget" skin="MW_ItemIconNoShadow" position="-3 -3 42 42" align="Left Top" name="SpellImage"/>
|
||||
<Property key="NeedMouse" value="false"/>
|
||||
</Widget>
|
||||
<Widget type="ProgressBar" skin="MW_EnergyBar_Magic" position="0 36 36 6" align="Left Bottom" name="SpellStatus">
|
||||
<Property key="NeedMouse" value="false"/>
|
||||
</Widget>
|
||||
</Widget>
|
||||
|
||||
<!-- Sneak indicator box -->
|
||||
<Widget type="Button" skin="" position="149 38 36 36" align="Left Bottom" name="SneakBox">
|
||||
<Property key="Visible" value="false"/>
|
||||
<Widget type="Widget" skin="HUD_Box" position="0 0 36 36">
|
||||
<Property key="NeedMouse" value="false"/>
|
||||
<Widget type="ImageBox" skin="ImageBox" position="2 2 32 32" align="Left Top" name="SneakImage">
|
||||
<Property key="NeedMouse" value="false"/>
|
||||
<Property key="ImageTexture" value="icons\k\stealth_sneak.dds"/>
|
||||
</Widget>
|
||||
</Widget>
|
||||
</Widget>
|
||||
|
||||
</Widget>
|
||||
<Widget type="Widget" layer="MiniMapHUD" position="0 0 300 92" name="_Main2" align="Stretch">
|
||||
<!-- Drowning bar -->
|
||||
<Widget type="Window" skin="MW_Dialog" position="0 36 230 58" align="Center Top" name="DrowningFrame">
|
||||
<Property key="Visible" value="false"/>
|
||||
<Widget type="TextBox" skin="SandText" position="0 3 222 24" name="DrowningTitle" align="Center Top HStretch">
|
||||
<Property key="Caption" value="#{sBreath}"/>
|
||||
<Property key="TextAlign" value="Center"/>
|
||||
<Property key="TextShadow" value="true"/>
|
||||
<Property key="TextShadowColour" value="0 0 0"/>
|
||||
</Widget>
|
||||
<Widget type="Widget" skin="MW_Box" position="11 29 200 10" align="Stretch" name="BoundingBox"/>
|
||||
<Widget type="ProgressBar" skin="MW_Progress_Drowning_Full" position="13 31 196 6" align="Center Top" name="Drowning">
|
||||
<Property key="NeedMouse" value="false"/>
|
||||
</Widget>
|
||||
<Widget type="Widget" skin="MW_Progress_Drowning_Small" position="15 33 192 2" align="Center Top" name="Flash"/>
|
||||
</Widget>
|
||||
|
||||
<!-- Equipped weapon/selected spell name display for a few seconds after it changes -->
|
||||
<Widget type="TextBox" skin="SandText" position="13 118 270 24" name="WeaponSpellName" align="Left Bottom HStretch">
|
||||
<Property key="Visible" value="false"/>
|
||||
<Property key="TextAlign" value="Left"/>
|
||||
<Property key="TextShadow" value="true"/>
|
||||
<Property key="TextShadowColour" value="0 0 0"/>
|
||||
<Property key="NeedMouse" value="false"/>
|
||||
</Widget>
|
||||
|
||||
<!-- Cell name display when cell changes -->
|
||||
<Widget type="TextBox" skin="SandText" position="0 89 288 24" name="CellName" align="Left Bottom HStretch">
|
||||
<Property key="Visible" value="false"/>
|
||||
<Property key="TextAlign" value="Right"/>
|
||||
<Property key="TextShadow" value="true"/>
|
||||
<Property key="TextShadowColour" value="0 0 0"/>
|
||||
<Property key="NeedMouse" value="false"/>
|
||||
</Widget>
|
||||
|
||||
<!-- Map box -->
|
||||
<Widget type="Widget" skin="" position="223 15 65 65" name="MiniMapBox" align="Right Bottom">
|
||||
<Widget type="Widget" skin="HUD_Box" position="0 0 65 65" align="Center">
|
||||
|
||||
<Widget type="ScrollView" skin="MW_MapView" position="2 2 61 61" align="Left Bottom" name="MiniMap">
|
||||
<Widget type="ImageBox" skin="RotatingSkin" position="0 0 32 32" align="Bottom Left" name="Compass">
|
||||
<Property key="ImageTexture" value="textures\compass.dds"/>
|
||||
</Widget>
|
||||
|
||||
<Widget type="Button" skin="" position_real="0 0 1 1" name="MiniMapButton" align="Stretch">
|
||||
<Property key="Depth" value="10"/>
|
||||
</Widget>
|
||||
|
||||
</Widget>
|
||||
|
||||
</Widget>
|
||||
</Widget>
|
||||
|
||||
<!-- Crosshair -->
|
||||
<Widget type="ImageBox" skin="HUD_Crosshair" position="0 0 32 32" align="Center Center" name="Crosshair">
|
||||
</Widget>
|
||||
|
||||
</Widget>
|
||||
</MyGUI>
|
63
files/mygui/openmw_inventory_window_vr.layout
Normal file
63
files/mygui/openmw_inventory_window_vr.layout
Normal file
|
@ -0,0 +1,63 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<MyGUI type="Layout">
|
||||
<Widget type="Window" skin="MW_Window_Pinnable" layer="InventoryWindow" position="0 0 600 300" name="_Main">
|
||||
<Property key="MinSize" value="40 40"/>
|
||||
|
||||
<Widget type="Widget" skin="" position="0 0 224 223" align="Left Top" name="LeftPane">
|
||||
|
||||
<!-- Player encumbrance -->
|
||||
<Widget type="MWDynamicStat" skin="MW_ChargeBar_Blue" position="8 8 212 24" name="EncumbranceBar" align="Left Top HStretch">
|
||||
</Widget>
|
||||
|
||||
<!-- Avatar -->
|
||||
<Widget type="Widget" skin="MW_Box" position="8 38 212 185" name="Avatar" align="Left Top Stretch">
|
||||
<Widget type="ImageBox" skin="ImageBox" position="3 3 206 158" align="Stretch" name="AvatarImage">
|
||||
<UserString key="ToolTipType" value="AvatarItemSelection"/>
|
||||
</Widget>
|
||||
<Widget type="TextBox" skin="ProgressText" position="0 161 212 24" align="HStretch Bottom" name="ArmorRating">
|
||||
<Property key="NeedMouse" value="false"/>
|
||||
</Widget>
|
||||
</Widget>
|
||||
|
||||
</Widget>
|
||||
|
||||
<Widget type="Widget" skin="" position="228 0 350 223" align="Left Top" name="RightPane">
|
||||
|
||||
<!-- Items in inventory -->
|
||||
<Widget type="ItemView" skin="MW_ItemView" position="0 38 350 185" name="ItemView" align="Left Top Stretch">
|
||||
</Widget>
|
||||
|
||||
<!-- Categories -->
|
||||
<Widget type="HBox" position="0 6 350 28" align="Left Top HStretch" name="Categories">
|
||||
<Widget type="AutoSizedButton" skin="MW_Button" position="0 0 60 24" name="AllButton">
|
||||
<Property key="Caption" value="#{sAllTab}"/>
|
||||
<Property key="NeedKey" value="false"/>
|
||||
</Widget>
|
||||
<Widget type="AutoSizedButton" skin="MW_Button" position="0 0 60 24" name="WeaponButton">
|
||||
<Property key="Caption" value="#{sWeaponTab}"/>
|
||||
<Property key="NeedKey" value="false"/>
|
||||
</Widget>
|
||||
<Widget type="AutoSizedButton" skin="MW_Button" position="0 0 60 24" name="ApparelButton">
|
||||
<Property key="Caption" value="#{sApparelTab}"/>
|
||||
<Property key="NeedKey" value="false"/>
|
||||
</Widget>
|
||||
<Widget type="AutoSizedButton" skin="MW_Button" position="0 0 60 24" name="MagicButton">
|
||||
<Property key="Caption" value="#{sMagicTab}"/>
|
||||
<Property key="NeedKey" value="false"/>
|
||||
</Widget>
|
||||
<Widget type="AutoSizedButton" skin="MW_Button" position="0 0 60 24" name="MiscButton">
|
||||
<Property key="Caption" value="#{sMiscTab}"/>
|
||||
<Property key="NeedKey" value="false"/>
|
||||
</Widget>
|
||||
<!-- Search box-->
|
||||
<Widget type="EditBox" skin="MW_TextBoxEditWithBorder" position="0 0 0 23" name="FilterEdit">
|
||||
<UserString key="HStretch" value="true"/>
|
||||
<UserString key="AcceptTab" value="true"/>
|
||||
</Widget>
|
||||
</Widget>
|
||||
|
||||
</Widget>
|
||||
|
||||
</Widget>
|
||||
</MyGUI>
|
26
files/mygui/openmw_layers_vr.xml
Normal file
26
files/mygui/openmw_layers_vr.xml
Normal file
|
@ -0,0 +1,26 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<MyGUI type="Layer" version="1.0">
|
||||
<Layer name="Scene" overlapped="false" pick="false"/>
|
||||
<Layer name="Overlay" overlapped="false" pick="false"/>
|
||||
<Layer name="AdditiveOverlay" type="AdditiveLayer" pick="false"/>
|
||||
<Layer name="StatusHUD" overlapped="false" pick="true"/>
|
||||
<Layer name="MiniMapHUD" overlapped="false" pick="true"/>
|
||||
<Layer name="Menu" overlapped="false" pick="true"/>
|
||||
<Layer name="InventoryWindow" overlapped="true" pick="true"/>
|
||||
<Layer name="SpellWindow" overlapped="true" pick="true"/>
|
||||
<Layer name="MapWindow" overlapped="true" pick="true"/>
|
||||
<Layer name="StatsWindow" overlapped="true" pick="true"/>
|
||||
<Layer name="Windows" overlapped="true" pick="true"/>
|
||||
<Layer name="JournalBooks" type="ScalingLayer" pick="true">
|
||||
<Property key="Size" value="600 520"/>
|
||||
</Layer>
|
||||
<Layer name="Debug" overlapped="true" pick="true"/>
|
||||
<Layer name="Notification" overlapped="false" pick="false"/>
|
||||
<Layer name="Popup" overlapped="true" pick="true"/>
|
||||
<Layer name="DragAndDrop" overlapped="false" pick="false"/>
|
||||
<Layer name="LoadingScreen" overlapped="false" pick="true"/>
|
||||
<Layer name="MessageBox" overlapped="false" pick="true"/>
|
||||
<Layer name="InputBlocker" overlapped="false" pick="true"/>
|
||||
<Layer name="Pointer" overlapped="false" pick="false"/>
|
||||
</MyGUI>
|
38
files/mygui/openmw_map_window_vr.layout
Normal file
38
files/mygui/openmw_map_window_vr.layout
Normal file
|
@ -0,0 +1,38 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<MyGUI type="Layout">
|
||||
<Widget type="Window" skin="MW_Window_Pinnable" layer="MapWindow" position="0 0 300 300" name="_Main">
|
||||
<Property key="MinSize" value="40 40"/>
|
||||
|
||||
<!-- Local map -->
|
||||
<Widget type="ScrollView" skin="MW_MapView" position="0 0 284 264" align="Stretch" name="LocalMap">
|
||||
<Widget type="ImageBox" skin="RotatingSkin" position="0 0 32 32" align="Top Left" name="CompassLocal">
|
||||
<Property key="ImageTexture" value="textures\compass.dds"/>
|
||||
</Widget>
|
||||
|
||||
<Widget type="Button" skin="" position_real="0 0 1 1" name="EventBoxLocal" align="Stretch">
|
||||
<Property key="Depth" value="10"/>
|
||||
</Widget>
|
||||
</Widget>
|
||||
|
||||
<!-- Global map -->
|
||||
<Widget type="ScrollView" skin="MW_MapView" position="0 0 284 264" align="Stretch" name="GlobalMap">
|
||||
<Widget type="ImageBox" skin="ImageBox" position_real="0 0 1 1" align="Stretch" name="GlobalMapImage">
|
||||
<Widget type="ImageBox" skin="ImageBox" position_real="0 0 1 1" align="Stretch" name="GlobalMapOverlay"/>
|
||||
</Widget>
|
||||
|
||||
<Widget type="ImageBox" skin="RotatingSkin" position="0 0 32 32" align="Top Left" name="CompassGlobal">
|
||||
<Property key="ImageTexture" value="textures\compass.dds"/>
|
||||
</Widget>
|
||||
|
||||
<Widget type="Button" skin="" position_real="0 0 1 1" name="EventBoxGlobal" align="Stretch"/>
|
||||
</Widget>
|
||||
|
||||
<!-- World button -->
|
||||
<Widget type="AutoSizedButton" skin="MW_Button" position="213 233 61 22" align="Bottom Right" name="WorldButton">
|
||||
<Property key="ExpandDirection" value="Left"/>
|
||||
<Property key="NeedKey" value="false"/>
|
||||
</Widget>
|
||||
|
||||
</Widget>
|
||||
</MyGUI>
|
31
files/mygui/openmw_spell_window_vr.layout
Normal file
31
files/mygui/openmw_spell_window_vr.layout
Normal file
|
@ -0,0 +1,31 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<MyGUI type="Layout">
|
||||
<Widget type="Window" skin="MW_Window_Pinnable" layer="SpellWindow" position="0 0 300 600" name="_Main">
|
||||
<Property key="MinSize" value="40 40"/>
|
||||
|
||||
<!-- Effect box-->
|
||||
<Widget type="Widget" skin="MW_Box" position="8 8 268 23" align="Left Top HStretch">
|
||||
<Widget type="Widget" skin="" position="2 1 264 20" align="Left Top Stretch" name="EffectsBox"/>
|
||||
</Widget>
|
||||
|
||||
<!-- Spell list -->
|
||||
<Widget type="SpellView" skin="MW_SpellView" position="8 38 268 490" align="Left Top Stretch" name="SpellView">
|
||||
</Widget>
|
||||
|
||||
<Widget type="HBox" position="8 535 268 23" align="Right Bottom HStretch">
|
||||
<Widget type="Spacer"/>
|
||||
<!-- Spell deletion button -->
|
||||
<Widget type="AutoSizedButton" skin="MW_Button" align="Right Bottom" position="8 535 0 23" name="DeleteSpellButton">
|
||||
<Property key="Caption" value="#{sDelete}"/>
|
||||
<Property key="NeedKey" value="false"/>
|
||||
</Widget>
|
||||
</Widget>
|
||||
|
||||
<!-- Search box-->
|
||||
<Widget type="EditBox" skin="MW_TextBoxEditWithBorder" position="8 535 268 23" align="Left Bottom HStretch" name="FilterEdit">
|
||||
<UserString key="AcceptTab" value="true"/>
|
||||
</Widget>
|
||||
|
||||
</Widget>
|
||||
</MyGUI>
|
246
files/mygui/openmw_stats_window_vr.layout
Normal file
246
files/mygui/openmw_stats_window_vr.layout
Normal file
|
@ -0,0 +1,246 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<MyGUI type="Layout">
|
||||
<Widget type="Window" skin="MW_Window_Pinnable" layer="StatsWindow" position="0 0 500 342" name="_Main">
|
||||
<Property key="MinSize" value="244 114"/>
|
||||
<Widget type="Widget" skin="" name="LeftPane" position="0 0 220 342">
|
||||
<UserString key="LeftOffsetWidth" value="24"/>
|
||||
<UserString key="LeftPaneRatio" value="0.44"/>
|
||||
|
||||
<!-- Player health stats -->
|
||||
<Widget type="Widget" skin="MW_Box" position="8 8 212 62" align="Left Top HStretch">
|
||||
<!-- Health -->
|
||||
<Widget type="Widget" skin="" position="4 4 204 18" name="Health" align="Left Top HStretch">
|
||||
<Property key="NeedMouse" value="true"/>
|
||||
<UserString key="ToolTipType" value="Layout"/>
|
||||
<UserString key="ToolTipLayout" value="HealthToolTip"/>
|
||||
<UserString key="ImageTexture_HealthImage" value="icons\k\health.dds"/>
|
||||
<Widget type="TextBox" skin="NormalText" position="0 0 70 18" name="Health_str" align="Left Top HStretch">
|
||||
<Property key="NeedMouse" value="false"/>
|
||||
<Property key="Caption" value="#{sHealth}"/>
|
||||
</Widget>
|
||||
<Widget type="ProgressBar" skin="MW_Progress_Red" position="74 0 130 18" name="HBar" align="Right Top">
|
||||
<Property key="NeedMouse" value="false"/>
|
||||
<Widget type="TextBox" skin="ProgressText" position="0 0 130 14" name="HBarT" align="Right VCenter">
|
||||
<Property key="NeedMouse" value="false"/>
|
||||
</Widget>
|
||||
</Widget>
|
||||
</Widget>
|
||||
|
||||
<!-- Magicka -->
|
||||
<Widget type="Widget" skin="" position="4 22 204 18" name="Magicka" align="Left Top HStretch">
|
||||
<Property key="NeedMouse" value="true"/>
|
||||
<UserString key="ToolTipType" value="Layout"/>
|
||||
<UserString key="ToolTipLayout" value="HealthToolTip"/>
|
||||
<UserString key="ImageTexture_HealthImage" value="icons\k\magicka.dds"/>
|
||||
|
||||
<Widget type="TextBox" skin="NormalText" position="0 0 70 18" name="Magicka_str" align="Left Top HStretch">
|
||||
<Property key="Caption" value="#{sMagic}"/>
|
||||
<Property key="NeedMouse" value="false"/>
|
||||
</Widget>
|
||||
|
||||
<Widget type="ProgressBar" skin="MW_Progress_Blue" position="74 0 130 18" name="MBar" align="Right Top">
|
||||
<Property key="NeedMouse" value="false"/>
|
||||
<Widget type="TextBox" skin="ProgressText" position="0 0 130 14" name="MBarT" align="Right VCenter">
|
||||
<Property key="NeedMouse" value="false"/>
|
||||
</Widget>
|
||||
</Widget>
|
||||
</Widget>
|
||||
|
||||
<!-- Fatigue -->
|
||||
<Widget type="Widget" skin="" position="4 40 204 18" name="Fatigue" align="Left Top HStretch">
|
||||
<Property key="NeedMouse" value="true"/>
|
||||
<UserString key="ToolTipType" value="Layout"/>
|
||||
<UserString key="ToolTipLayout" value="HealthToolTip"/>
|
||||
<UserString key="ImageTexture_HealthImage" value="icons\k\fatigue.dds"/>
|
||||
|
||||
<Widget type="TextBox" skin="NormalText" position="0 0 70 18" name="Fatigue_str" align="Left Top HStretch">
|
||||
<Property key="Caption" value="#{sFatigue}"/>
|
||||
<Property key="NeedMouse" value="false"/>
|
||||
</Widget>
|
||||
|
||||
<Widget type="ProgressBar" skin="MW_Progress_Green" position="74 0 130 18" name="FBar" align="Right Top">
|
||||
<Property key="NeedMouse" value="false"/>
|
||||
<Widget type="TextBox" skin="ProgressText" position="0 0 130 14" name="FBarT" align="Right VCenter">
|
||||
<Property key="NeedMouse" value="false"/>
|
||||
</Widget>
|
||||
</Widget>
|
||||
</Widget>
|
||||
</Widget>
|
||||
|
||||
<!-- Player level, race and class -->
|
||||
<Widget type="Widget" skin="MW_Box" position="8 78 212 62" align="Top HStretch">
|
||||
<Widget type="HBox" position="4 4 204 18" align="Top HStretch">
|
||||
<Widget type="AutoSizedTextBox" skin="NormalText" position="0 0 200 18" name="Level_str" align="Left Top">
|
||||
<Property key="Caption" value="#{sLevel}"/>
|
||||
<UserString key="ToolTipType" value="Layout"/>
|
||||
<UserString key="ToolTipLayout" value="LevelToolTip"/>
|
||||
</Widget>
|
||||
<Widget type="TextBox" skin="SandTextRight" position="200 0 40 18" name="LevelText" align="Right Top">
|
||||
<Property key="TextAlign" value="Right Top"/>
|
||||
<UserString key="ToolTipType" value="Layout"/>
|
||||
<UserString key="ToolTipLayout" value="LevelToolTip"/>
|
||||
<UserString key="HStretch" value="true"/>
|
||||
</Widget>
|
||||
|
||||
</Widget>
|
||||
<Widget type="HBox" position="4 24 204 18" align="Top HStretch">
|
||||
<Widget type="AutoSizedTextBox" skin="NormalText" position="0 0 95 18" name="Race_str" align="Left Top">
|
||||
<Property key="Caption" value="#{sRace}"/>
|
||||
<UserString key="ToolTipType" value="Layout"/>
|
||||
<UserString key="ToolTipLayout" value="RaceToolTip"/>
|
||||
</Widget>
|
||||
<Widget type="TextBox" skin="SandTextRight" position="104 0 200 18" name="RaceText" align="Left Top">
|
||||
<Property key="TextAlign" value="Right Top"/>
|
||||
<UserString key="ToolTipType" value="Layout"/>
|
||||
<UserString key="ToolTipLayout" value="RaceToolTip"/>
|
||||
<UserString key="HStretch" value="true"/>
|
||||
</Widget>
|
||||
</Widget>
|
||||
<Widget type="HBox" position="4 42 204 18" align="Top HStretch">
|
||||
<Widget type="AutoSizedTextBox" skin="NormalText" position="0 0 95 18" name="Class_str" align="Left Top">
|
||||
<Property key="Caption" value="#{sClass}"/>
|
||||
<UserString key="ToolTipType" value="Layout"/>
|
||||
<UserString key="ToolTipLayout" value="ClassToolTip"/>
|
||||
</Widget>
|
||||
<Widget type="TextBox" skin="SandTextRight" position="104 0 200 18" name="ClassText" align="Left Top">
|
||||
<Property key="TextAlign" value="Right Top"/>
|
||||
<UserString key="ToolTipType" value="Layout"/>
|
||||
<UserString key="ToolTipLayout" value="ClassToolTip"/>
|
||||
<UserString key="HStretch" value="true"/>
|
||||
</Widget>
|
||||
</Widget>
|
||||
</Widget>
|
||||
|
||||
<Widget type="Widget" skin="MW_Box" position="8 148 212 152" align="Left Top Stretch">
|
||||
<!-- TODO: this should be a scroll view -->
|
||||
<Widget type="Widget" skin="" position="4 4 204 144" align="Left Top Stretch">
|
||||
<Widget type="Button" skin="" position="0 0 204 18" name="Attrib1Box" align="Left Top HStretch">
|
||||
<UserString key="ToolTipType" value="Layout"/>
|
||||
<UserString key="ToolTipLayout" value="AttributeToolTip"/>
|
||||
<UserString key="Caption_AttributeName" value="#{sAttributeStrength}"/>
|
||||
<UserString key="Caption_AttributeDescription" value="#{sStrDesc}"/>
|
||||
<UserString key="ImageTexture_AttributeImage" value="icons\k\attribute_strength.dds"/>
|
||||
<Widget type="TextBox" skin="SandText" position="0 0 160 18" name="Attrib1" align="Left Top HStretch">
|
||||
<Property key="NeedMouse" value="false"/>
|
||||
</Widget>
|
||||
<Widget type="TextBox" skin="SandTextRight" position="160 0 44 18" name="AttribVal1" align="Right Top">
|
||||
<Property key="NeedMouse" value="false"/>
|
||||
</Widget>
|
||||
</Widget>
|
||||
|
||||
<Widget type="Button" skin="" position="0 18 204 18" name="Attrib2Box" align="Left Top HStretch">
|
||||
<UserString key="ToolTipType" value="Layout"/>
|
||||
<UserString key="ToolTipLayout" value="AttributeToolTip"/>
|
||||
<UserString key="Caption_AttributeName" value="#{sAttributeIntelligence}"/>
|
||||
<UserString key="Caption_AttributeDescription" value="#{sIntDesc}"/>
|
||||
<UserString key="ImageTexture_AttributeImage" value="icons\k\attribute_int.dds"/>
|
||||
<Widget type="TextBox" skin="SandText" position="0 0 160 18" name="Attrib2" align="Left Top HStretch">
|
||||
<Property key="NeedMouse" value="false"/>
|
||||
</Widget>
|
||||
<Widget type="TextBox" skin="SandTextRight" position="160 0 44 18" name="AttribVal2" align="Right Top">
|
||||
<Property key="NeedMouse" value="false"/>
|
||||
</Widget>
|
||||
</Widget>
|
||||
|
||||
<Widget type="Button" skin="" position="0 36 204 18" name="Attrib3Box" align="Left Top HStretch">
|
||||
<UserString key="ToolTipType" value="Layout"/>
|
||||
<UserString key="ToolTipLayout" value="AttributeToolTip"/>
|
||||
<UserString key="Caption_AttributeName" value="#{sAttributeWillpower}"/>
|
||||
<UserString key="Caption_AttributeDescription" value="#{sWilDesc}"/>
|
||||
<UserString key="ImageTexture_AttributeImage" value="icons\k\attribute_wilpower.dds"/>
|
||||
<Widget type="TextBox" skin="SandText" position="0 0 160 18" name="Attrib3" align="Left Top HStretch">
|
||||
<Property key="NeedMouse" value="false"/>
|
||||
</Widget>
|
||||
<Widget type="TextBox" skin="SandTextRight" position="160 0 44 18" name="AttribVal3" align="Right Top">
|
||||
<Property key="NeedMouse" value="false"/>
|
||||
</Widget>
|
||||
</Widget>
|
||||
|
||||
<Widget type="Button" skin="" position="0 54 204 18" name="Attrib4Box" align="Left Top HStretch">
|
||||
<UserString key="ToolTipType" value="Layout"/>
|
||||
<UserString key="ToolTipLayout" value="AttributeToolTip"/>
|
||||
<UserString key="Caption_AttributeName" value="#{sAttributeAgility}"/>
|
||||
<UserString key="Caption_AttributeDescription" value="#{sAgiDesc}"/>
|
||||
<UserString key="ImageTexture_AttributeImage" value="icons\k\attribute_agility.dds"/>
|
||||
<Widget type="TextBox" skin="SandText" position="0 0 160 18" name="Attrib4" align="Left Top HStretch">
|
||||
<Property key="NeedMouse" value="false"/>
|
||||
</Widget>
|
||||
<Widget type="TextBox" skin="SandTextRight" position="160 0 44 18" name="AttribVal4" align="Right Top">
|
||||
<Property key="NeedMouse" value="false"/>
|
||||
</Widget>
|
||||
</Widget>
|
||||
|
||||
<Widget type="Button" skin="" position="0 72 204 18" name="Attrib5Box" align="Left Top HStretch">
|
||||
<UserString key="ToolTipType" value="Layout"/>
|
||||
<UserString key="ToolTipLayout" value="AttributeToolTip"/>
|
||||
<UserString key="Caption_AttributeName" value="#{sAttributeSpeed}"/>
|
||||
<UserString key="Caption_AttributeDescription" value="#{sSpdDesc}"/>
|
||||
<UserString key="ImageTexture_AttributeImage" value="icons\k\attribute_speed.dds"/>
|
||||
<Widget type="TextBox" skin="SandText" position="0 0 160 18" name="Attrib5" align="Left Top HStretch">
|
||||
<Property key="NeedMouse" value="false"/>
|
||||
</Widget>
|
||||
<Widget type="TextBox" skin="SandTextRight" position="160 0 44 18" name="AttribVal5" align="Right Top">
|
||||
<Property key="NeedMouse" value="false"/>
|
||||
</Widget>
|
||||
</Widget>
|
||||
|
||||
<Widget type="Button" skin="" position="0 90 204 18" name="Attrib6Box" align="Left Top HStretch">
|
||||
<UserString key="ToolTipType" value="Layout"/>
|
||||
<UserString key="ToolTipLayout" value="AttributeToolTip"/>
|
||||
<UserString key="Caption_AttributeName" value="#{sAttributeEndurance}"/>
|
||||
<UserString key="Caption_AttributeDescription" value="#{sEndDesc}"/>
|
||||
<UserString key="ImageTexture_AttributeImage" value="icons\k\attribute_endurance.dds"/>
|
||||
<Widget type="TextBox" skin="SandText" position="0 0 160 18" name="Attrib6" align="Left Top HStretch">
|
||||
<Property key="NeedMouse" value="false"/>
|
||||
</Widget>
|
||||
<Widget type="TextBox" skin="SandTextRight" position="160 0 44 18" name="AttribVal6" align="Right Top">
|
||||
<Property key="NeedMouse" value="false"/>
|
||||
</Widget>
|
||||
</Widget>
|
||||
|
||||
<Widget type="Button" skin="" position="0 108 204 18" name="Attrib7Box" align="Left Top HStretch">
|
||||
<UserString key="ToolTipType" value="Layout"/>
|
||||
<UserString key="ToolTipLayout" value="AttributeToolTip"/>
|
||||
<UserString key="Caption_AttributeName" value="#{sAttributePersonality}"/>
|
||||
<UserString key="Caption_AttributeDescription" value="#{sPerDesc}"/>
|
||||
<UserString key="ImageTexture_AttributeImage" value="icons\k\attribute_personality.dds"/>
|
||||
<Widget type="TextBox" skin="SandText" position="0 0 160 18" name="Attrib7" align="Left Top HStretch">
|
||||
<Property key="NeedMouse" value="false"/>
|
||||
</Widget>
|
||||
<Widget type="TextBox" skin="SandTextRight" position="160 0 44 18" name="AttribVal7" align="Right Top">
|
||||
<Property key="NeedMouse" value="false"/>
|
||||
</Widget>
|
||||
</Widget>
|
||||
|
||||
<Widget type="Button" skin="" position="0 126 204 18" name="Attrib8Box" align="Left Top HStretch">
|
||||
<UserString key="ToolTipType" value="Layout"/>
|
||||
<UserString key="ToolTipLayout" value="AttributeToolTip"/>
|
||||
<UserString key="Caption_AttributeName" value="#{sAttributeLuck}"/>
|
||||
<UserString key="Caption_AttributeDescription" value="#{sLucDesc}"/>
|
||||
<UserString key="ImageTexture_AttributeImage" value="icons\k\attribute_luck.dds"/>
|
||||
<Widget type="TextBox" skin="SandText" position="0 0 160 18" name="Attrib8" align="Left Top HStretch">
|
||||
<Property key="NeedMouse" value="false"/>
|
||||
</Widget>
|
||||
<Widget type="TextBox" skin="SandTextRight" position="160 0 44 18" name="AttribVal8" align="Right Top">
|
||||
<Property key="NeedMouse" value="false"/>
|
||||
</Widget>
|
||||
</Widget>
|
||||
</Widget>
|
||||
</Widget>
|
||||
|
||||
</Widget>
|
||||
|
||||
<Widget type="Widget" skin="" name="RightPane" position="220 0 280 342">
|
||||
|
||||
<!-- Player skills, factions, birthsign and reputation -->
|
||||
<Widget type="Widget" skin="MW_Box" position="8 8 248 292" align="Left Stretch" name="Skills">
|
||||
<Widget type="ScrollView" skin="MW_ScrollView" position="4 4 240 284" align="Left Top Stretch" name="SkillView">
|
||||
<Property key="CanvasAlign" value="Left Top"/>
|
||||
</Widget>
|
||||
</Widget>
|
||||
|
||||
</Widget>
|
||||
|
||||
</Widget>
|
||||
</MyGUI>
|
Loading…
Reference in a new issue