1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-02-20 23:39:40 +00:00

Rudimentary menu interactions

This commit is contained in:
Mads Buvik Sandvei 2020-03-08 14:14:24 +01:00
parent 2ae7255fac
commit e573a260cb
12 changed files with 114 additions and 44 deletions

View file

@ -7,7 +7,7 @@
#include <map> #include <map>
#include <set> #include <set>
#include <deque> #include <deque>
#include <osg/node> #include <tuple>
#include <components/esm/cellid.hpp> #include <components/esm/cellid.hpp>
@ -22,6 +22,7 @@ namespace osg
class Matrixf; class Matrixf;
class Quat; class Quat;
class Image; class Image;
class Node;
} }
namespace Loading namespace Loading
@ -97,6 +98,12 @@ namespace MWBase
ESM::CellId dest; ESM::CellId dest;
}; };
using IntersectedObject = std::tuple<
MWWorld::Ptr,
osg::Node*,
osg::Vec3f
>;
World() {} World() {}
virtual ~World() {} virtual ~World() {}
@ -261,7 +268,7 @@ namespace MWBase
virtual MWWorld::Ptr getFacedObject() = 0; virtual MWWorld::Ptr getFacedObject() = 0;
///< Return pointer to the object the player is looking at, if it is within activation range ///< Return pointer to the object the player is looking at, if it is within activation range
virtual std::pair<MWWorld::Ptr, osg::Node*> getPointedAtObject() = 0; virtual IntersectedObject getPointedAtObject() = 0;
///< Return pointer to the object and/or node the player is currently pointing at ///< Return pointer to the object and/or node the player is currently pointing at
virtual float getDistanceToFacedObject() = 0; virtual float getDistanceToFacedObject() = 0;

View file

@ -1881,18 +1881,6 @@ bool CharacterController::updateWeaponState(CharacterState& idle)
mAnimation->setAccurateAiming(mUpperBodyState > UpperCharState_WeapEquiped); mAnimation->setAccurateAiming(mUpperBodyState > UpperCharState_WeapEquiped);
#ifdef USE_OPENXR
if (mPtr == getPlayer())
{
auto xrAnimation = dynamic_cast<MWVR::OpenXRAnimation*>(mAnimation);
if (xrAnimation)
{
bool pointing = MWBase::Environment::get().getWorld()->getPlayer().getPointing();
xrAnimation->setPointForward(pointing);
}
}
#endif
return forcestateupdate; return forcestateupdate;
} }

View file

@ -69,6 +69,7 @@
#ifdef USE_OPENXR #ifdef USE_OPENXR
#include "../mwvr/openxranimation.hpp" #include "../mwvr/openxranimation.hpp"
#include "../mwvr/openxrenvironment.hpp"
#endif #endif
namespace namespace
@ -1025,6 +1026,7 @@ namespace MWRender
result.mHit = true; result.mHit = true;
osgUtil::LineSegmentIntersector::Intersection intersection = intersector->getFirstIntersection(); osgUtil::LineSegmentIntersector::Intersection intersection = intersector->getFirstIntersection();
result.mHitPointLocal = intersection.getLocalIntersectPoint();
result.mHitPointWorld = intersection.getWorldIntersectPoint(); result.mHitPointWorld = intersection.getWorldIntersectPoint();
result.mHitNormalWorld = intersection.getWorldIntersectNormal(); result.mHitNormalWorld = intersection.getWorldIntersectNormal();
result.mRatio = intersection.ratio; result.mRatio = intersection.ratio;
@ -1163,7 +1165,8 @@ namespace MWRender
void RenderingManager::renderPlayer(const MWWorld::Ptr &player) void RenderingManager::renderPlayer(const MWWorld::Ptr &player)
{ {
#ifdef USE_OPENXR #ifdef USE_OPENXR
mPlayerAnimation = new MWVR::OpenXRAnimation(player, player.getRefData().getBaseNode(), mResourceSystem, false, nullptr); MWVR::OpenXREnvironment::get().setPlayerAnimation(new MWVR::OpenXRAnimation(player, player.getRefData().getBaseNode(), mResourceSystem, false, nullptr));
mPlayerAnimation = MWVR::OpenXREnvironment::get().getPlayerAnimation();
#else #else
mPlayerAnimation = new NpcAnimation(player, player.getRefData().getBaseNode(), mResourceSystem, 0, NpcAnimation::VM_Normal, mPlayerAnimation = new NpcAnimation(player, player.getRefData().getBaseNode(), mResourceSystem, 0, NpcAnimation::VM_Normal,
mFirstPersonFieldOfView); mFirstPersonFieldOfView);

View file

@ -151,6 +151,7 @@ namespace MWRender
bool mHit; bool mHit;
osg::Vec3f mHitNormalWorld; osg::Vec3f mHitNormalWorld;
osg::Vec3f mHitPointWorld; osg::Vec3f mHitPointWorld;
osg::Vec3f mHitPointLocal;
MWWorld::Ptr mHitObject; MWWorld::Ptr mHitObject;
osg::Node* mHitNode; osg::Node* mHitNode;
float mRatio; float mRatio;

View file

@ -184,11 +184,17 @@ void FingerController::operator()(osg::Node* node, osg::NodeVisitor* nv)
{ {
// Get distance to pointer intersection // Get distance to pointer intersection
auto pat = pointerTransform->asTransform()->asPositionAttitudeTransform(); auto pat = pointerTransform->asTransform()->asPositionAttitudeTransform();
auto* world = MWBase::Environment::get().getWorld();
if (world)
{
// TODO: Using the cached value from the input manager makes this off by one frame // TODO: Using the cached value from the input manager makes this off by one frame
float intersected_distance = MWBase::Environment::get().getWorld()->getDistanceToPointedAtObject(); // So do one otherwise redundant intersection here.
world->getPointedAtObject();
float intersected_distance = world->getDistanceToPointedAtObject();
// Stretch beam to point of intersection. // Stretch beam to point of intersection.
pat->setScale(osg::Vec3(1.f, 1.f, intersected_distance)); pat->setScale(osg::Vec3(.25f, .25f, intersected_distance));
}
} }
} }

View file

@ -2,6 +2,7 @@
#include <cassert> #include <cassert>
#include "openxranimation.hpp"
#include "openxrinputmanager.hpp" #include "openxrinputmanager.hpp"
#include "openxrsession.hpp" #include "openxrsession.hpp"
#include "openxrmenu.hpp" #include "openxrmenu.hpp"
@ -31,6 +32,9 @@ void MWVR::OpenXREnvironment::cleanup()
if (mMenuManager) if (mMenuManager)
delete mMenuManager; delete mMenuManager;
mMenuManager = nullptr; mMenuManager = nullptr;
if (mPlayerAnimation)
delete mPlayerAnimation;
mPlayerAnimation = nullptr;
if (mViewer) if (mViewer)
delete mViewer; delete mViewer;
mViewer = nullptr; mViewer = nullptr;
@ -39,7 +43,7 @@ void MWVR::OpenXREnvironment::cleanup()
mOpenXRManager = nullptr; mOpenXRManager = nullptr;
} }
const MWVR::OpenXREnvironment& MWVR::OpenXREnvironment::get() MWVR::OpenXREnvironment& MWVR::OpenXREnvironment::get()
{ {
assert (sThis); assert (sThis);
return *sThis; return *sThis;
@ -74,6 +78,16 @@ void MWVR::OpenXREnvironment::setMenuManager(MWVR::OpenXRMenuManager* menuManage
mMenuManager = menuManager; mMenuManager = menuManager;
} }
MWVR::OpenXRAnimation* MWVR::OpenXREnvironment::getPlayerAnimation() const
{
return mPlayerAnimation;
}
void MWVR::OpenXREnvironment::setPlayerAnimation(MWVR::OpenXRAnimation* xrAnimation)
{
mPlayerAnimation = xrAnimation;
}
MWVR::OpenXRViewer* MWVR::OpenXREnvironment::getViewer() const MWVR::OpenXRViewer* MWVR::OpenXREnvironment::getViewer() const
{ {

View file

@ -3,6 +3,7 @@
namespace MWVR namespace MWVR
{ {
class OpenXRAnimation;
class OpenXRInputManager; class OpenXRInputManager;
class OpenXRSession; class OpenXRSession;
class OpenXRMenuManager; class OpenXRMenuManager;
@ -35,7 +36,7 @@ namespace MWVR
void cleanup(); void cleanup();
///< Delete all mwvr-subsystems. ///< Delete all mwvr-subsystems.
static const OpenXREnvironment& get(); static OpenXREnvironment& get();
///< Return instance of this class. ///< Return instance of this class.
MWVR::OpenXRInputManager* getInputManager() const; MWVR::OpenXRInputManager* getInputManager() const;
@ -47,6 +48,9 @@ namespace MWVR
MWVR::OpenXRMenuManager* getMenuManager() const; MWVR::OpenXRMenuManager* getMenuManager() const;
void setMenuManager(MWVR::OpenXRMenuManager* xrMenuManager); void setMenuManager(MWVR::OpenXRMenuManager* xrMenuManager);
MWVR::OpenXRAnimation* getPlayerAnimation() const;
void setPlayerAnimation(MWVR::OpenXRAnimation* xrAnimation);
MWVR::OpenXRSession* getSession() const; MWVR::OpenXRSession* getSession() const;
void setSession(MWVR::OpenXRSession* xrSession); void setSession(MWVR::OpenXRSession* xrSession);
@ -62,6 +66,7 @@ namespace MWVR
private: private:
MWVR::OpenXRSession* mSession{ nullptr }; MWVR::OpenXRSession* mSession{ nullptr };
MWVR::OpenXRMenuManager* mMenuManager{ nullptr }; MWVR::OpenXRMenuManager* mMenuManager{ nullptr };
MWVR::OpenXRAnimation* mPlayerAnimation{ nullptr };
MWVR::OpenXRViewer* mViewer{ nullptr }; MWVR::OpenXRViewer* mViewer{ nullptr };
MWVR::OpenXRManager* mOpenXRManager{ nullptr }; MWVR::OpenXRManager* mOpenXRManager{ nullptr };
float mUnitsPerMeter{ 1.f }; float mUnitsPerMeter{ 1.f };

View file

@ -1,3 +1,4 @@
#include "openxranimation.hpp"
#include "openxrinputmanager.hpp" #include "openxrinputmanager.hpp"
#include "openxrenvironment.hpp" #include "openxrenvironment.hpp"
#include "openxrmanager.hpp" #include "openxrmanager.hpp"
@ -625,10 +626,6 @@ namespace MWVR
{ {
mActionEvents.emplace_back(OpenXRActionEvent{ MWInput::InputManager::A_Inventory, true }); mActionEvents.emplace_back(OpenXRActionEvent{ MWInput::InputManager::A_Inventory, true });
} }
if (mActivate.actionOnPress())
{
mActionEvents.emplace_back(OpenXRActionEvent{ MWInput::InputManager::A_Activate, true });
}
if (mJump.actionOnPress()) if (mJump.actionOnPress())
{ {
mActionEvents.emplace_back(OpenXRActionEvent{ MWInput::InputManager::A_Jump, true }); mActionEvents.emplace_back(OpenXRActionEvent{ MWInput::InputManager::A_Jump, true });
@ -638,6 +635,12 @@ namespace MWVR
mActionEvents.emplace_back(OpenXRActionEvent{ MWInput::InputManager::A_QuickMenu, true }); mActionEvents.emplace_back(OpenXRActionEvent{ MWInput::InputManager::A_QuickMenu, true });
} }
// Actions that activate on release
if (mActivate.actionChanged())
{
mActionEvents.emplace_back(OpenXRActionEvent{ MWInput::InputManager::A_Activate, mActivate.actionOnPress() });
}
// Actions that hold with the button // Actions that hold with the button
if (mUse.actionChanged()) if (mUse.actionChanged())
{ {
@ -749,9 +752,16 @@ namespace MWVR
return mXRInput->getHandPoses(time, space); return mXRInput->getHandPoses(time, space);
} }
void OpenXRInputManager::showActivationIndication(bool show) void OpenXRInputManager::updateActivationIndication(void)
{ {
bool guiMode = MWBase::Environment::get().getWindowManager()->isGuiMode();
bool show = guiMode | mActivationIndication;
if (mPlayer)
mPlayer->setPointing(show); mPlayer->setPointing(show);
auto* playerAnimation = OpenXREnvironment::get().getPlayerAnimation();
if (playerAnimation)
playerAnimation->setPointForward(show);
} }
OpenXRInputManager::OpenXRInputManager( OpenXRInputManager::OpenXRInputManager(
@ -801,11 +811,30 @@ namespace MWVR
{ {
mXRInput->updateControls(); mXRInput->updateControls();
auto* world = MWBase::Environment::get().getWorld(); auto* world = MWBase::Environment::get().getWorld();
if (world) if (world)
{ {
auto pointedAt = world->getPointedAtObject(); auto pointedAt = world->getPointedAtObject();
// TODO: Left off here // TODO: Left off here
auto* node = std::get<1>(pointedAt);
if (node)
{
int w, h;
SDL_GetWindowSize(mWindow, &w, &h);
osg::Vec3 local = std::get<2>(pointedAt);
local.x() = (local.x() + 1.f) / 2.f;
local.y() = 1.f - (local.y() + 1.f) / 2.f;
mGuiCursorX = mInvUiScalingFactor * (local.x() * w);
mGuiCursorY = mInvUiScalingFactor * (local.y() * h);
MyGUI::InputManager::getInstance().injectMouseMove(int(mGuiCursorX), int(mGuiCursorY), 0);
}
} }
OpenXRActionEvent event{}; OpenXRActionEvent event{};
@ -814,6 +843,8 @@ namespace MWVR
processEvent(event); processEvent(event);
} }
updateActivationIndication();
MWInput::InputManager::update(dt, disableControls, disableEvents); MWInput::InputManager::update(dt, disableControls, disableEvents);
bool guiMode = MWBase::Environment::get().getWindowManager()->isGuiMode(); bool guiMode = MWBase::Environment::get().getWindowManager()->isGuiMode();
@ -831,7 +862,6 @@ namespace MWVR
switch (event.action) switch (event.action)
{ {
case A_GameMenu: case A_GameMenu:
Log(Debug::Verbose) << "A_GameMenu";
toggleMainMenu(); toggleMainMenu();
// Explicitly request position update here so that the player can move the menu // Explicitly request position update here so that the player can move the menu
// using the menu key when the menu can't be toggled. // using the menu key when the menu can't be toggled.
@ -848,7 +878,14 @@ namespace MWVR
break; break;
case A_Activate: case A_Activate:
resetIdleTime(); resetIdleTime();
{
if (MWBase::Environment::get().getWindowManager()->isGuiMode())
{
// Do nothing
}
else if(!event.onPress)
activate(); activate();
}
break; break;
// TODO: Movement // TODO: Movement
//case A_MoveLeft: //case A_MoveLeft:
@ -964,10 +1001,19 @@ namespace MWVR
mAttemptJump = true; mAttemptJump = true;
break; break;
case A_Use: case A_Use:
if (MWBase::Environment::get().getWindowManager()->isGuiMode())
{
SDL_MouseButtonEvent arg;
if (event.onPress)
mousePressed(arg, SDL_BUTTON_LEFT);
else
mouseReleased(arg, SDL_BUTTON_LEFT);
}
else
mInputBinder->getChannel(A_Use)->setValue(event.onPress); mInputBinder->getChannel(A_Use)->setValue(event.onPress);
break; break;
case OpenXRInput::A_ActivateTouch: case OpenXRInput::A_ActivateTouch:
showActivationIndication(event.onPress); mActivationIndication = event.onPress;
break; break;
default: default:
Log(Debug::Warning) << "Unhandled XR action " << event.action; Log(Debug::Warning) << "Unhandled XR action " << event.action;

View file

@ -43,12 +43,13 @@ namespace MWVR
PoseSet getHandPoses(int64_t time, TrackedSpace space); PoseSet getHandPoses(int64_t time, TrackedSpace space);
void showActivationIndication(bool show); void updateActivationIndication(void);
std::unique_ptr<OpenXRInput> mXRInput; std::unique_ptr<OpenXRInput> mXRInput;
Pose mPreviousHeadPose{}; Pose mPreviousHeadPose{};
osg::Vec3 mHeadOffset{ 0,0,0 }; osg::Vec3 mHeadOffset{ 0,0,0 };
bool mRecenter{ true }; bool mRecenter{ true };
bool mActivationIndication{ false };
float mYaw{ 0.f }; float mYaw{ 0.f };
float mVrAngles[3]{ 0.f,0.f,0.f }; float mVrAngles[3]{ 0.f,0.f,0.f };

View file

@ -58,7 +58,7 @@ namespace MWVR
createInfo.enabledExtensionCount = extensions.size(); createInfo.enabledExtensionCount = extensions.size();
createInfo.enabledExtensionNames = extensions.data(); createInfo.enabledExtensionNames = extensions.data();
strcpy(createInfo.applicationInfo.applicationName, "Boo"); strcpy(createInfo.applicationInfo.applicationName, "openmw_vr");
createInfo.applicationInfo.apiVersion = XR_CURRENT_API_VERSION; createInfo.applicationInfo.apiVersion = XR_CURRENT_API_VERSION;
CHECK_XRCMD(xrCreateInstance(&createInfo, &mInstance)); CHECK_XRCMD(xrCreateInstance(&createInfo, &mInstance));
assert(mInstance); assert(mInstance);
@ -504,7 +504,7 @@ namespace MWVR
MWBase::Environment::get().getWorld()->getStore().get<ESM::Race>().find(ref->mBase->mRace); MWBase::Environment::get().getWorld()->getStore().get<ESM::Race>().find(ref->mBase->mRace);
bool isMale = ref->mBase->isMale(); bool isMale = ref->mBase->isMale();
float charHeightFactor = isMale ? race->mData.mHeight.mMale : race->mData.mHeight.mFemale; float charHeightFactor = isMale ? race->mData.mHeight.mMale : race->mData.mHeight.mFemale;
float charHeightBase = 2.f; float charHeightBase = 1.8f;
float charHeight = charHeightBase * charHeightFactor; float charHeight = charHeightBase * charHeightFactor;
// TODO: Player height should be configurable // TODO: Player height should be configurable
// For now i'm just using my own // For now i'm just using my own

View file

@ -1113,7 +1113,7 @@ namespace MWWorld
return facedObject; return facedObject;
} }
std::pair<MWWorld::Ptr, osg::Node*> World::getPointedAtObject() World::IntersectedObject World::getPointedAtObject()
{ {
if (MWBase::Environment::get().getWindowManager()->isGuiMode() && if (MWBase::Environment::get().getWindowManager()->isGuiMode() &&
MWBase::Environment::get().getWindowManager()->isConsoleMode()) MWBase::Environment::get().getWindowManager()->isConsoleMode())
@ -1123,10 +1123,10 @@ namespace MWWorld
else else
{ {
auto pointedAtObject = getPointedAtObject(getActivationDistancePlusTelekinesis(), true); auto pointedAtObject = getPointedAtObject(getActivationDistancePlusTelekinesis(), true);
auto ptr = std::get<0>(pointedAtObject);
if (!pointedAtObject.first.isEmpty() && !pointedAtObject.first.getClass().allowTelekinesis(pointedAtObject.first) if (!ptr.isEmpty() && !ptr.getClass().allowTelekinesis(ptr)
&& mDistanceToFacedObject > getMaxActivationDistance() && !MWBase::Environment::get().getWindowManager()->isGuiMode()) && mDistanceToFacedObject > getMaxActivationDistance() && !MWBase::Environment::get().getWindowManager()->isGuiMode())
return std::pair<MWWorld::Ptr, osg::Node*>(); return IntersectedObject();
return pointedAtObject; return pointedAtObject;
} }
} }
@ -2070,7 +2070,7 @@ namespace MWWorld
return facedObject; return facedObject;
} }
std::pair<MWWorld::Ptr, osg::Node*> World::getPointedAtObject(float maxDistance, bool ignorePlayer) World::IntersectedObject World::getPointedAtObject(float maxDistance, bool ignorePlayer)
{ {
auto sceneRoot = mRendering->getLightRoot(); auto sceneRoot = mRendering->getLightRoot();
@ -2103,11 +2103,10 @@ namespace MWWorld
else else
// Leave a very large but not too large number to permit visualizing a beam going into "infinity" // Leave a very large but not too large number to permit visualizing a beam going into "infinity"
mDistanceToPointedAtObject = 10000.f; mDistanceToPointedAtObject = 10000.f;
return { rayToObject.mHitObject, rayToObject.mHitNode, rayToObject.mHitPointLocal };
return { rayToObject.mHitObject, rayToObject.mHitNode };
} }
return std::pair<MWWorld::Ptr, osg::Node*>(); return IntersectedObject();
} }
bool World::isCellExterior() const bool World::isCellExterior() const

View file

@ -140,7 +140,7 @@ namespace MWWorld
MWWorld::Ptr getFacedObject(float maxDistance, bool ignorePlayer=true); MWWorld::Ptr getFacedObject(float maxDistance, bool ignorePlayer=true);
std::pair<MWWorld::Ptr, osg::Node*> getPointedAtObject(float maxDistance, bool ignorePlayer=true); IntersectedObject getPointedAtObject(float maxDistance, bool ignorePlayer=true);
public: // FIXME public: // FIXME
void addContainerScripts(const Ptr& reference, CellStore* cell) override; void addContainerScripts(const Ptr& reference, CellStore* cell) override;
@ -377,7 +377,7 @@ namespace MWWorld
MWWorld::Ptr getFacedObject() override; MWWorld::Ptr getFacedObject() override;
///< Return pointer to the object the player is looking at, if it is within activation range ///< Return pointer to the object the player is looking at, if it is within activation range
std::pair<MWWorld::Ptr, osg::Node*> getPointedAtObject() override; IntersectedObject getPointedAtObject() override;
///< Return pointer to the object and/or node the player is currently pointing at ///< Return pointer to the object and/or node the player is currently pointing at
float getDistanceToFacedObject() override; float getDistanceToFacedObject() override;