Commit 040be7b9 authored by Petr Mikheev's avatar Petr Mikheev

Improved preview mode

parent c25d9575
......@@ -422,6 +422,8 @@ namespace MWBase
virtual void changeVanityModeScale(float factor) = 0;
virtual bool vanityRotateCamera(float * rot) = 0;
virtual void setCameraDistance(float dist, bool adjust = false, bool override = true)=0;
virtual void applyDeferredPreviewRotationToPlayer(float dt) = 0;
virtual void disableDeferredPreviewRotation() = 0;
virtual void setupPlayer() = 0;
virtual void renderPlayer() = 0;
......
......@@ -110,23 +110,31 @@ namespace MWInput
if (MWBase::Environment::get().getInputManager()->getControlSwitch("playerviewswitch"))
{
static const bool separatePreviewCamera = Settings::Manager::getBool("separate preview camera", "Camera");
if (mBindingsManager->actionIsActive(A_TogglePOV))
{
if (mPreviewPOVDelay <= 0.5 &&
(mPreviewPOVDelay += dt) > 0.5)
if (separatePreviewCamera)
{
mPreviewPOVDelay = 1.f;
MWBase::Environment::get().getWorld()->togglePreviewMode(true);
if (mPreviewPOVDelay <= 0.5 && (mPreviewPOVDelay += dt) > 0.5)
{
mPreviewPOVDelay = 1.f;
MWBase::Environment::get().getWorld()->togglePreviewMode(true);
}
}
else
{
if (mPreviewPOVDelay == 0)
MWBase::Environment::get().getWorld()->togglePreviewMode(true);
mPreviewPOVDelay += dt;
}
}
else
{
//disable preview mode
MWBase::Environment::get().getWorld()->togglePreviewMode(false);
if (mPreviewPOVDelay > 0.f && mPreviewPOVDelay <= 0.5)
{
if (mPreviewPOVDelay > 0 || separatePreviewCamera)
MWBase::Environment::get().getWorld()->togglePreviewMode(false);
if (mPreviewPOVDelay > 0.f && mPreviewPOVDelay <= (separatePreviewCamera ? 0.5 : 0.25))
MWBase::Environment::get().getWorld()->togglePOV();
}
mPreviewPOVDelay = 0.f;
}
}
......
......@@ -9,6 +9,7 @@
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
#include "../mwworld/esmstore.hpp"
......@@ -101,6 +102,8 @@ namespace MWInput
mMouseManager->update(dt);
mSensorManager->update(dt);
mActionManager->update(dt, controllerMove);
MWBase::Environment::get().getWorld()->applyDeferredPreviewRotationToPlayer(dt);
}
void InputManager::setDragDrop(bool dragDrop)
......
......@@ -108,6 +108,8 @@ namespace MWInput
player.yaw(x);
player.pitch(y);
}
else if (!input->getControlSwitch("playerlooking"))
MWBase::Environment::get().getWorld()->disableDeferredPreviewRotation();
if (arg.zrel && input->getControlSwitch("playerviewswitch") && input->getControlSwitch("playercontrols")) //Check to make sure you are allowed to zoomout and there is a change
{
......@@ -212,12 +214,15 @@ namespace MWInput
rot[2] = xAxis * dt * 1000.0f * mCameraSensitivity * (mInvertX ? -1 : 1) / 256.f;
// Only actually turn player when we're not in vanity mode
if (!MWBase::Environment::get().getWorld()->vanityRotateCamera(rot) && MWBase::Environment::get().getInputManager()->getControlSwitch("playercontrols"))
bool controls = MWBase::Environment::get().getInputManager()->getControlSwitch("playercontrols");
if (!MWBase::Environment::get().getWorld()->vanityRotateCamera(rot) && controls)
{
MWWorld::Player& player = MWBase::Environment::get().getWorld()->getPlayer();
player.yaw(rot[2]);
player.pitch(rot[0]);
}
else if (!controls)
MWBase::Environment::get().getWorld()->disableDeferredPreviewRotation();
MWBase::Environment::get().getInputManager()->resetIdleTime();
}
......
......@@ -254,12 +254,15 @@ namespace MWInput
rot[2] = mGyroXSpeed * dt * mGyroHSensitivity * 4 * (mInvertX ? -1 : 1);
// Only actually turn player when we're not in vanity mode
if (!MWBase::Environment::get().getWorld()->vanityRotateCamera(rot) && MWBase::Environment::get().getInputManager()->getControlSwitch("playerlooking"))
bool playerLooking = MWBase::Environment::get().getInputManager()->getControlSwitch("playerlooking");
if (!MWBase::Environment::get().getWorld()->vanityRotateCamera(rot) && playerLooking)
{
MWWorld::Player& player = MWBase::Environment::get().getWorld()->getPlayer();
player.yaw(rot[2]);
player.pitch(rot[0]);
}
else if (!playerLooking)
MWBase::Environment::get().getWorld()->disableDeferredPreviewRotation();
MWBase::Environment::get().getInputManager()->resetIdleTime();
}
......
......@@ -58,6 +58,7 @@ namespace MWRender
mIsNearest(false),
mHeight(124.f),
mBaseCameraDistance(192.f),
mUseSeparatePreviewCam(false),
mVanityToggleQueued(false),
mVanityToggleQueuedValue(false),
mViewModeToggleQueued(false),
......@@ -123,7 +124,8 @@ namespace MWRender
osg::Vec3d Camera::getFocalPointOffset() const
{
osg::Vec3d offset(0, 0, 10.f);
if (mThirdPersonMode == ThirdPersonViewMode::OverShoulder && !mPreviewMode && !mVanity.enabled)
bool separatePreviewCam = mUseSeparatePreviewCam && (mPreviewMode || mVanity.enabled);
if (mThirdPersonMode == ThirdPersonViewMode::OverShoulder && !separatePreviewCam)
{
offset.x() += mFocalPointCurrentOffset.x() * cos(getYaw());
offset.y() += mFocalPointCurrentOffset.x() * sin(getYaw());
......@@ -251,8 +253,9 @@ namespace MWRender
if (mThirdPersonMode == ThirdPersonViewMode::Standard)
return; // In Standard mode there is no focal point offset.
bool combat = mTrackingPtr.getClass().isActor() && mTrackingPtr.getClass().getCreatureStats(mTrackingPtr).getDrawState() != MWMechanics::DrawState_Nothing;
ThirdPersonOffsetType newOffsetType = mThirdPersionOffsetType;
if (mTrackingPtr.getClass().isActor() && mTrackingPtr.getClass().getCreatureStats(mTrackingPtr).getDrawState() != MWMechanics::DrawState_Nothing)
if (combat && !isVanityOrPreviewModeEnabled())
newOffsetType = ThirdPersonOffsetType::Combat;
else if (MWBase::Environment::get().getWorld()->isSwimming(mTrackingPtr))
newOffsetType = ThirdPersonOffsetType::Swimming;
......@@ -260,7 +263,9 @@ namespace MWRender
newOffsetType = mDefaultShoulderIsRight ? ThirdPersonOffsetType::RightShoulder : ThirdPersonOffsetType::LeftShoulder;
if (newOffsetType != mThirdPersionOffsetType)
{
if (newOffsetType == ThirdPersonOffsetType::Combat || mThirdPersionOffsetType == ThirdPersonOffsetType::Combat)
if (isVanityOrPreviewModeEnabled())
mFocalPointTransitionSpeed = mVanity.enabled ? 0.2 : 1;
else if (newOffsetType == ThirdPersonOffsetType::Combat || mThirdPersionOffsetType == ThirdPersonOffsetType::Combat)
mFocalPointTransitionSpeed = 5;
else
mFocalPointTransitionSpeed = 1;
......@@ -339,17 +344,19 @@ namespace MWRender
processViewChange();
float offset = mPreviewCam.offset;
if (mVanity.enabled) {
setPitch(osg::DegreesToRadians(-30.f));
mMainCam.offset = mCameraDistance;
} else {
offset = mMainCam.offset;
if (mUseSeparatePreviewCam)
{
float offset = mPreviewCam.offset;
if (mVanity.enabled)
{
setPitch(osg::DegreesToRadians(-30.f));
mMainCam.offset = mCameraDistance;
}
else
offset = mMainCam.offset;
mCameraDistance = offset;
}
mCameraDistance = offset;
return true;
}
......@@ -364,16 +371,18 @@ namespace MWRender
mPreviewMode = enable;
processViewChange();
float offset = mCameraDistance;
if (mPreviewMode) {
mMainCam.offset = offset;
offset = mPreviewCam.offset;
} else {
mPreviewCam.offset = offset;
offset = mMainCam.offset;
if (mUseSeparatePreviewCam)
{
float offset = mCameraDistance;
if (mPreviewMode) {
mMainCam.offset = offset;
offset = mPreviewCam.offset;
} else {
mPreviewCam.offset = offset;
offset = mMainCam.offset;
}
mCameraDistance = offset;
}
mCameraDistance = offset;
}
void Camera::setSneakOffset(float offset)
......@@ -383,7 +392,7 @@ namespace MWRender
float Camera::getYaw() const
{
if(mVanity.enabled || mPreviewMode)
if (mUseSeparatePreviewCam && (mVanity.enabled || mPreviewMode))
return mPreviewCam.yaw;
return mMainCam.yaw;
}
......@@ -395,18 +404,16 @@ namespace MWRender
} else if (angle < -osg::PI) {
angle += osg::PI*2;
}
if (mVanity.enabled || mPreviewMode) {
if (mUseSeparatePreviewCam && (mVanity.enabled || mPreviewMode))
mPreviewCam.yaw = angle;
} else {
else
mMainCam.yaw = angle;
}
}
float Camera::getPitch() const
{
if (mVanity.enabled || mPreviewMode) {
if (mUseSeparatePreviewCam && (mVanity.enabled || mPreviewMode))
return mPreviewCam.pitch;
}
return mMainCam.pitch;
}
......@@ -414,7 +421,7 @@ namespace MWRender
{
const float epsilon = 0.000001f;
float limit = osg::PI_2 - epsilon;
if(mPreviewMode)
if(mUseSeparatePreviewCam && mPreviewMode)
limit /= 2;
if(angle > limit)
......@@ -422,11 +429,10 @@ namespace MWRender
else if(angle < -limit)
angle = -limit;
if (mVanity.enabled || mPreviewMode) {
if (mUseSeparatePreviewCam && (mVanity.enabled || mPreviewMode))
mPreviewCam.pitch = angle;
} else {
else
mMainCam.pitch = angle;
}
}
float Camera::getCameraDistance() const
......@@ -445,7 +451,7 @@ namespace MWRender
if (adjust)
{
if (mVanity.enabled || mPreviewMode)
if (mUseSeparatePreviewCam && (mVanity.enabled || mPreviewMode))
dist += mCameraDistance;
else
dist += std::min(mCameraDistance - getCameraDistanceCorrection(), mBaseCameraDistance);
......@@ -460,7 +466,7 @@ namespace MWRender
mIsNearest = true;
}
if (mVanity.enabled || mPreviewMode)
if (mUseSeparatePreviewCam && (mVanity.enabled || mPreviewMode))
mPreviewCam.offset = dist;
else if (!mFirstPersonView)
mBaseCameraDistance = dist;
......@@ -498,7 +504,7 @@ namespace MWRender
void Camera::setCameraDistance()
{
if (mVanity.enabled || mPreviewMode)
if (mUseSeparatePreviewCam && (mVanity.enabled || mPreviewMode))
mCameraDistance = mPreviewCam.offset;
else if (!mFirstPersonView)
mCameraDistance = mBaseCameraDistance + getCameraDistanceCorrection();
......
......@@ -53,6 +53,7 @@ namespace MWRender
float mHeight, mBaseCameraDistance;
CamData mMainCam, mPreviewCam;
bool mUseSeparatePreviewCam;
bool mVanityToggleQueued;
bool mVanityToggleQueuedValue;
......@@ -116,6 +117,9 @@ namespace MWRender
bool toggleVanityMode(bool enable);
void allowVanityMode(bool allow);
void useSeparatePreviewCamera(bool v) { mUseSeparatePreviewCam = v; }
bool isUsingSeparatePreviewCamera() const { return mUseSeparatePreviewCam; }
/// @note this may be ignored if an important animation is currently playing
void togglePreviewMode(bool enable);
......
......@@ -56,6 +56,7 @@
#include "../mwgui/loadingscreen.hpp"
#include "../mwbase/environment.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwmechanics/movement.hpp"
#include "sky.hpp"
#include "effectmanager.hpp"
......@@ -200,6 +201,8 @@ namespace MWRender
, mNightEyeFactor(0.f)
, mFieldOfViewOverridden(false)
, mFieldOfViewOverride(0.f)
, mDeferredRotation(osg::Vec3f())
, mDeferredRotationDisabled(false)
{
resourceSystem->getSceneManager()->setParticleSystemMask(MWRender::Mask_ParticleSystem);
resourceSystem->getSceneManager()->setShaderPath(resourcePath + "/shaders");
......@@ -391,6 +394,8 @@ namespace MWRender
float horizontal = 30.f, vertical = -10.f;
offset >> horizontal >> vertical;
mCamera->setOverShoulderOffset(horizontal, vertical);
mCamera->useSeparatePreviewCamera(Settings::Manager::getBool("separate preview camera", "Camera"));
}
osgUtil::IncrementalCompileOperation* RenderingManager::getIncrementalCompileOperation()
......@@ -660,7 +665,8 @@ namespace MWRender
if(ptr == mCamera->getTrackingPtr() &&
!mCamera->isVanityOrPreviewModeEnabled())
{
mCamera->rotateCamera(-ptr.getRefData().getPosition().rot[0], -ptr.getRefData().getPosition().rot[2], false);
mCamera->rotateCamera(-ptr.getRefData().getPosition().rot[0] - mDeferredRotation.x(),
-ptr.getRefData().getPosition().rot[2] - mDeferredRotation.z(), false);
}
ptr.getRefData().getBaseNode()->setAttitude(rot);
......@@ -1328,9 +1334,54 @@ namespace MWRender
return false;
mCamera->rotateCamera(rot[0], rot[2], true);
return true;
}
void RenderingManager::applyDeferredPreviewRotationToPlayer(float dt)
{
MWWorld::Ptr ptr = mCamera->getTrackingPtr();
if (mCamera->isVanityOrPreviewModeEnabled() || ptr.isEmpty())
return;
osg::Vec3f rot = mDeferredRotation;
float delta = rot.normalize();
delta = std::min(delta, (delta + 1.f) * 3 * dt);
rot *= delta;
mDeferredRotation -= rot;
auto& movement = ptr.getClass().getMovementSettings(ptr);
movement.mRotation[0] += rot.x();
movement.mRotation[1] += rot.y();
movement.mRotation[2] += rot.z();
}
void RenderingManager::calculateDeferredRotation()
{
MWWorld::Ptr ptr = mCamera->getTrackingPtr();
if (mCamera->isVanityOrPreviewModeEnabled() || mCamera->isUsingSeparatePreviewCamera() || ptr.isEmpty())
return;
if (mCamera->isFirstPerson() || mDeferredRotationDisabled)
{
mDeferredRotationDisabled = false;
mDeferredRotation = osg::Vec3f();
mCamera->rotateCamera(-ptr.getRefData().getPosition().rot[0],
-ptr.getRefData().getPosition().rot[2], false);
return;
}
mDeferredRotation.x() = -ptr.getRefData().getPosition().rot[0] - mCamera->getPitch();
mDeferredRotation.z() = -ptr.getRefData().getPosition().rot[2] - mCamera->getYaw();
if (mDeferredRotation.x() > M_PI)
mDeferredRotation.x() -= 2 * M_PI;
if (mDeferredRotation.x() < -M_PI)
mDeferredRotation.x() += 2 * M_PI;
if (mDeferredRotation.z() > M_PI)
mDeferredRotation.z() -= 2 * M_PI;
if (mDeferredRotation.z() < -M_PI)
mDeferredRotation.z() += 2 * M_PI;
}
void RenderingManager::setCameraDistance(float dist, bool adjust, bool override)
{
if(!mCamera->isVanityOrPreviewModeEnabled() && !mCamera->isFirstPerson())
......@@ -1380,11 +1431,14 @@ namespace MWRender
void RenderingManager::togglePreviewMode(bool enable)
{
mCamera->togglePreviewMode(enable);
calculateDeferredRotation();
}
bool RenderingManager::toggleVanityMode(bool enable)
{
return mCamera->toggleVanityMode(enable);
bool res = mCamera->toggleVanityMode(enable);
calculateDeferredRotation();
return res;
}
void RenderingManager::allowVanityMode(bool allow)
......
......@@ -220,6 +220,9 @@ namespace MWRender
void allowVanityMode(bool allow);
void changeVanityModeScale(float factor);
void applyDeferredPreviewRotationToPlayer(float dt);
void disableDeferredPreviewRotation() { mDeferredRotationDisabled = true; }
/// temporarily override the field of view with given value.
void overrideFieldOfView(float val);
/// reset a previous overrideFieldOfView() call, i.e. revert to field of view specified in the settings file.
......@@ -308,6 +311,11 @@ namespace MWRender
float mFieldOfView;
float mFirstPersonFieldOfView;
// Used to rotate player to the direction of view after exiting preview or vanity mode.
osg::Vec3f mDeferredRotation;
bool mDeferredRotationDisabled;
void calculateDeferredRotation();
void operator = (const RenderingManager&);
RenderingManager(const RenderingManager&);
};
......
......@@ -2429,6 +2429,16 @@ namespace MWWorld
return mRendering->toggleVanityMode(enable);
}
void World::disableDeferredPreviewRotation()
{
mRendering->disableDeferredPreviewRotation();
}
void World::applyDeferredPreviewRotationToPlayer(float dt)
{
mRendering->applyDeferredPreviewRotationToPlayer(dt);
}
void World::allowVanityMode(bool allow)
{
mRendering->allowVanityMode(allow);
......
......@@ -536,6 +536,9 @@ namespace MWWorld
bool vanityRotateCamera(float * rot) override;
void setCameraDistance(float dist, bool adjust = false, bool override = true) override;
void applyDeferredPreviewRotationToPlayer(float dt) override;
void disableDeferredPreviewRotation() override;
void setupPlayer() override;
void renderPlayer() override;
......
......@@ -42,6 +42,10 @@ view over shoulder offset = 30 -10
# Switch shoulder automatically when player is close to an obstacle.
auto switch shoulder = true
# true - standard bahaviour of preview and vanity camera
# false - smooth preview mode
separate preview camera = true
[Cells]
# Preload cells in a background thread. All settings starting with 'preload' have no effect unless this is enabled.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment