From 6f87c0c36d912de51b943e7989d6c4117d568760 Mon Sep 17 00:00:00 2001 From: greye Date: Tue, 14 Aug 2012 14:37:48 +0400 Subject: [PATCH] preview mode, advanced vanity support --- apps/openmw/mwbase/world.hpp | 3 + apps/openmw/mwinput/inputmanagerimp.cpp | 27 ++-- apps/openmw/mwrender/player.cpp | 145 +++++++++++++++++----- apps/openmw/mwrender/player.hpp | 14 ++- apps/openmw/mwrender/renderingmanager.cpp | 4 +- apps/openmw/mwrender/renderingmanager.hpp | 12 ++ apps/openmw/mwworld/worldimp.hpp | 12 ++ 7 files changed, 169 insertions(+), 48 deletions(-) diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index c2db2acf1..819a242ec 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -250,6 +250,9 @@ namespace MWBase virtual bool isUnderwater(const ESM::Cell &cell, const Ogre::Vector3 &pos) = 0; virtual void togglePOV() = 0; + virtual void togglePreviewMode(bool enable) = 0; + virtual bool toggleVanityMode(bool enable, bool force) = 0; + virtual void allowVanityMode(bool allow) = 0; }; } diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index 6bdd87d2a..f0ca510ea 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -406,19 +406,22 @@ private: else player.setUpDown (0); - if (poller.isDown(A_TogglePOV)) { - if (mPreviewPOVDelay <= 0.5 && - (mPreviewPOVDelay += duration) > 0.5) - { - // enable preview mode + if (mControlSwitch["playerviewswitch"]) { + if (poller.isDown(A_TogglePOV)) { + if (mPreviewPOVDelay <= 0.5 && + (mPreviewPOVDelay += duration) > 0.5) + { + MWBase::Environment::get().getWorld()->togglePreviewMode(true); + } + } else { + if (mPreviewPOVDelay > 0.5) { + //disable preview mode + MWBase::Environment::get().getWorld()->togglePreviewMode(false); + } else if (mPreviewPOVDelay > 0.f) { + togglePOV(); + } + mPreviewPOVDelay = 0.f; } - } else { - if (mPreviewPOVDelay > 0.5) { - //disable preview mode - } else if (mPreviewPOVDelay > 0.f) { - togglePOV(); - } - mPreviewPOVDelay = 0.f; } } } diff --git a/apps/openmw/mwrender/player.cpp b/apps/openmw/mwrender/player.cpp index 5b74b9903..2a1feacad 100644 --- a/apps/openmw/mwrender/player.cpp +++ b/apps/openmw/mwrender/player.cpp @@ -18,28 +18,49 @@ namespace MWRender mCameraNode(mPlayerNode->createChildSceneNode()), mVanityNode(mPlayerNode->createChildSceneNode()), mFirstPersonView(true), - mVanityMode(false), mPreviewMode(false), - mHeight(40.f) + mHeight(40.f), + mCameraDistance(400.f) { + mVanity.enabled = false; + mVanity.allowed = true; + mVanity.forced = false; + mCameraNode->attachObject(mCamera); mCameraNode->setPosition(0.f, 0.f, mHeight); mPreviewCam.yaw = 0.f; + mPreviewCam.offset = 600.f; } bool Player::rotate(const Ogre::Vector3 &rot, bool adjust) { - rotateCamera(rot, adjust); - mUpdates = 0; mTimeIdle = 0.f; - if (mVanityMode) { + if (mVanity.enabled) { toggleVanityMode(false); } - return !mVanityMode && !mPreviewMode; + Ogre::Vector3 trueRot = rot; + + /// \note rotate player on forced vanity + if (mVanity.forced) { + moveCameraNode(mPlayerNode); + mVanity.enabled = false; + + rotateCamera(rot, adjust); + + moveCameraNode(mVanityNode); + mVanity.enabled = true; + + trueRot.z = 0.f; + } + + rotateCamera(trueRot, adjust); + + /// \note if vanity mode is forced by TVM then rotate player + return (!mVanity.enabled && !mPreviewMode) || mVanity.forced; } void Player::rotateCamera(const Ogre::Vector3 &rot, bool adjust) @@ -90,19 +111,19 @@ namespace MWRender void Player::update(float duration) { - if (!mVanityMode) { + if (!mVanity.enabled) { ++mUpdates; mTimeIdle += duration; if (mTimeIdle > 30.f) { toggleVanityMode(true); } } - if (mFirstPersonView && !mVanityMode) { + if (mFirstPersonView && !mVanity.enabled) { return; } - if (mVanityMode) { + if (mVanity.enabled) { Ogre::Vector3 rot(0.f, 0.f, 0.f); - rot.z = Ogre::Degree(3.f * duration).valueRadians(); + rot.z = Ogre::Degree(-3.f * duration).valueRadians(); rotateCamera(rot, true); } } @@ -113,49 +134,75 @@ namespace MWRender if (mFirstPersonView) { mCamera->setPosition(0.f, 0.f, 0.f); } else { - mCamera->setPosition(0.f, 0.f, 400.f); + mCamera->setPosition(0.f, 0.f, mCameraDistance); } } - - void Player::toggleVanityMode(bool enable, bool force) + + void Player::allowVanityMode(bool allow) { - if (mVanityMode == enable) { - return; + if (!allow && mVanity.enabled && !mVanity.forced) { + toggleVanityMode(false); } - mVanityMode = enable; + mVanity.allowed = allow; + } + + bool Player::toggleVanityMode(bool enable, bool force) + { + if ((mVanity.forced && !force) || + (!mVanity.allowed && (force || enable))) + { + return false; + } else if (mVanity.enabled == enable) { + return true; + } + mVanity.enabled = enable; + mVanity.forced = force && enable; float offset = 300.f; Ogre::Vector3 rot(0.f, 0.f, 0.f); - if (mVanityMode) { + if (mVanity.enabled) { rot.x = Ogre::Degree(-30.f).valueRadians(); mMainCam.offset = mCamera->getPosition().z; - mPlayerNode->removeChild(mCameraNode); - mVanityNode->addChild(mCameraNode); + moveCameraNode(mVanityNode); } else { rot.x = getPitch(); offset = mMainCam.offset; - mVanityNode->removeChild(mCameraNode); - mPlayerNode->addChild(mCameraNode); + moveCameraNode(mPlayerNode); } rot.z = getYaw(); mCamera->setPosition(0.f, 0.f, offset); rotateCamera(rot, false); + + return true; } void Player::togglePreviewMode(bool enable) { - /// \todo move camera if (mPreviewMode == enable) { return; } mPreviewMode = enable; + float offset = mCamera->getPosition().z; + if (mPreviewMode) { + mMainCam.offset = offset; + offset = mPreviewCam.offset; + + moveCameraNode(mVanityNode); + } else { + mPreviewCam.offset = offset; + offset = mMainCam.offset; + + moveCameraNode(mPlayerNode); + } + mCamera->setPosition(0.f, 0.f, mPreviewCam.offset); + rotateCamera(Ogre::Vector3(getPitch(), 0.f, getYaw()), false); } float Player::getYaw() { - if (mVanityMode || mPreviewMode) { + if (mVanity.enabled || mPreviewMode) { return mPreviewCam.yaw; } return mMainCam.yaw; @@ -168,7 +215,7 @@ namespace MWRender } else if (angle < -Ogre::Math::PI) { angle += Ogre::Math::TWO_PI; } - if (mVanityMode || mPreviewMode) { + if (mVanity.enabled || mPreviewMode) { mPreviewCam.yaw = angle; } else { mMainCam.yaw = angle; @@ -177,23 +224,59 @@ namespace MWRender float Player::getPitch() { - if (mVanityMode || mPreviewMode) { + if (mVanity.enabled || mPreviewMode) { return mPreviewCam.pitch; } return mMainCam.pitch; } void Player::setPitch(float angle) - { - if (angle > Ogre::Math::HALF_PI) { - angle = Ogre::Math::HALF_PI - 0.01; - } else if (angle < -Ogre::Math::HALF_PI) { - angle = -Ogre::Math::HALF_PI + 0.01; + { + float limit = Ogre::Math::HALF_PI; + if (mVanity.forced || mPreviewMode) { + limit /= 2; } - if (mVanityMode || mPreviewMode) { + if (angle > limit) { + angle = limit - 0.01; + } else if (angle < -limit) { + angle = -limit + 0.01; + } + if (mVanity.enabled || mPreviewMode) { mPreviewCam.pitch = angle; } else { mMainCam.pitch = angle; } } + + void Player::moveCameraNode(Ogre::SceneNode *node) + { + mCameraNode->getParentSceneNode()->removeChild(mCameraNode); + node->addChild(mCameraNode); + } + + void Player::setCameraDistance(float dist, bool adjust) + { + /// \note non-Morrowind feature: allow to change camera distance + /// int 3d-person mode + /// \todo review and simplify condition if possible + if (mPreviewMode || + mVanity.forced || + (!mVanity.enabled && !mFirstPersonView)) + { + Ogre::Vector3 v(0.f, 0.f, dist); + if (adjust) { + v += mCamera->getPosition(); + } + if (v.z > 800.f) { + v.z = 800.f; + } else if (v.z < 100.f) { + v.z = 100.f; + } + mCamera->setPosition(v); + + if (!mVanity.enabled && !mFirstPersonView) { + mCameraDistance = v.z; + } + } + } } diff --git a/apps/openmw/mwrender/player.hpp b/apps/openmw/mwrender/player.hpp index 060d62fa0..1ca9bfc21 100644 --- a/apps/openmw/mwrender/player.hpp +++ b/apps/openmw/mwrender/player.hpp @@ -31,10 +31,13 @@ namespace MWRender Ogre::SceneNode *mVanityNode; bool mFirstPersonView; - bool mVanityMode; bool mPreviewMode; - float mHeight; + struct { + bool enabled, allowed, forced; + } mVanity; + + float mHeight, mCameraDistance; CamData mMainCam, mPreviewCam; float mTimeIdle; @@ -51,6 +54,8 @@ namespace MWRender float getPitch(); void setPitch(float angle); + void moveCameraNode(Ogre::SceneNode *node); + public: Player (Ogre::Camera *camera, Ogre::SceneNode* mNode); @@ -69,11 +74,14 @@ namespace MWRender void toggleViewMode(); - void toggleVanityMode(bool enable, bool force = false); + bool toggleVanityMode(bool enable, bool force = false); + void allowVanityMode(bool allow); void togglePreviewMode(bool enable); void update(float duration); + + void setCameraDistance(float dist, bool adjust = false); }; } diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index cc08eae91..05902d662 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -318,13 +318,13 @@ void RenderingManager::update (float duration){ float *fpos = data.getPosition().pos; /// \note only for LocalMap::updatePlayer() - Ogre::Vector3 pos(fpos[0], -fpos[2], fpos[1]); + Ogre::Vector3 pos(fpos[0], -fpos[2], -fpos[1]); Ogre::SceneNode *node = data.getBaseNode(); Ogre::Quaternion orient = node->convertLocalToWorldOrientation(node->_getDerivedOrientation()); - mLocalMap->updatePlayer(mRendering.getCamera()->getRealPosition(), orient); + mLocalMap->updatePlayer(pos, orient); if (mWater) { Ogre::Vector3 cam = mRendering.getCamera()->getRealPosition(); diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index f100fdd59..741ccc559 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -60,6 +60,18 @@ class RenderingManager: private RenderingInterface, public Ogre::WindowEventList mPlayer->toggleViewMode(); } + void togglePreviewMode(bool enable) { + mPlayer->togglePreviewMode(enable); + } + + virtual bool toggleVanityMode(bool enable, bool force) { + return mPlayer->toggleVanityMode(enable, force); + } + + virtual void allowVanityMode(bool allow) { + mPlayer->allowVanityMode(allow); + } + void attachCameraTo(const MWWorld::Ptr &ptr); SkyManager* getSkyManager(); diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 2e5f73702..26824e763 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -280,6 +280,18 @@ namespace MWWorld virtual void togglePOV() { mRendering->togglePOV(); } + + virtual void togglePreviewMode(bool enable) { + mRendering->togglePreviewMode(enable); + } + + virtual bool toggleVanityMode(bool enable, bool force) { + return mRendering->toggleVanityMode(enable, force); + } + + virtual void allowVanityMode(bool allow) { + mRendering->allowVanityMode(allow); + } }; }