Merge remote-tracking branch 'remotes/origin/master' into openxr_vr

pull/615/head
Mads Buvik Sandvei 5 years ago
commit 1023ef6e49

@ -435,6 +435,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,21 @@ namespace MWInput
if (MWBase::Environment::get().getInputManager()->getControlSwitch("playerviewswitch"))
{
const float switchLimit = 0.25;
MWBase::World* world = MWBase::Environment::get().getWorld();
if (mBindingsManager->actionIsActive(A_TogglePOV))
{
if (mPreviewPOVDelay <= 0.5 &&
(mPreviewPOVDelay += dt) > 0.5)
{
mPreviewPOVDelay = 1.f;
MWBase::Environment::get().getWorld()->togglePreviewMode(true);
}
if (world->isFirstPerson() ? mPreviewPOVDelay > switchLimit : mPreviewPOVDelay == 0)
world->togglePreviewMode(true);
mPreviewPOVDelay += dt;
}
else
{
//disable preview mode
MWBase::Environment::get().getWorld()->togglePreviewMode(false);
if (mPreviewPOVDelay > 0.f && mPreviewPOVDelay <= 0.5)
{
MWBase::Environment::get().getWorld()->togglePOV();
}
if (mPreviewPOVDelay > 0)
world->togglePreviewMode(false);
if (mPreviewPOVDelay > 0.f && mPreviewPOVDelay <= switchLimit)
world->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
{
@ -207,17 +209,20 @@ namespace MWInput
return;
float rot[3];
rot[0] = yAxis * dt * 1000.0f * mCameraSensitivity * (mInvertY ? -1 : 1) * mCameraYMultiplier / 256.f;
rot[0] = -yAxis * dt * 1000.0f * mCameraSensitivity * (mInvertY ? -1 : 1) * mCameraYMultiplier / 256.f;
rot[1] = 0.0f;
rot[2] = xAxis * dt * 1000.0f * mCameraSensitivity * (mInvertX ? -1 : 1) / 256.f;
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]);
player.yaw(-rot[2]);
player.pitch(-rot[0]);
}
else if (!controls)
MWBase::Environment::get().getWorld()->disableDeferredPreviewRotation();
MWBase::Environment::get().getInputManager()->resetIdleTime();
}

@ -249,17 +249,20 @@ namespace MWInput
if (!mGuiCursorEnabled)
{
float rot[3];
rot[0] = mGyroYSpeed * dt * mGyroVSensitivity * 4 * (mInvertY ? -1 : 1);
rot[0] = -mGyroYSpeed * dt * mGyroVSensitivity * 4 * (mInvertY ? -1 : 1);
rot[1] = 0.0f;
rot[2] = mGyroXSpeed * dt * mGyroHSensitivity * 4 * (mInvertX ? -1 : 1);
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]);
player.yaw(-rot[2]);
player.pitch(-rot[0]);
}
else if (!playerLooking)
MWBase::Environment::get().getWorld()->disableDeferredPreviewRotation();
MWBase::Environment::get().getInputManager()->resetIdleTime();
}

@ -19,6 +19,7 @@
#endif
#include "../mwmechanics/drawstate.hpp"
#include "../mwmechanics/movement.hpp"
#include "../mwmechanics/npcstats.hpp"
#include "npcanimation.hpp"
@ -59,7 +60,10 @@ namespace MWRender
mCamera(camera),
mAnimation(nullptr),
mFirstPersonView(true),
mPreviewMode(false),
mMode(Mode::Normal),
mVanityAllowed(true),
mStandingPreviewAllowed(Settings::Manager::getBool("preview if stand still", "Camera")),
mDeferredRotationAllowed(Settings::Manager::getBool("deferred preview rotation", "Camera")),
mNearest(30.f),
mFurthest(800.f),
mIsNearest(false),
@ -78,20 +82,10 @@ namespace MWRender
mSmoothedSpeed(0.f),
mZoomOutWhenMoveCoef(Settings::Manager::getFloat("zoom out when move coef", "Camera")),
mDynamicCameraDistanceEnabled(false),
mShowCrosshairInThirdPersonMode(false)
mShowCrosshairInThirdPersonMode(false),
mDeferredRotation(osg::Vec3f()),
mDeferredRotationDisabled(false)
{
mVanity.enabled = false;
mVanity.allowed = true;
mPreviewCam.roll = 0.f;
mPreviewCam.pitch = 0.f;
mPreviewCam.yaw = 0.f;
mPreviewCam.offset = 400.f;
mMainCam.roll = 0.f;
mMainCam.pitch = 0.f;
mMainCam.yaw = 0.f;
mMainCam.offset = 400.f;
mCameraDistance = mBaseCameraDistance;
mUpdateCallback = new UpdateRenderCameraCallback(this);
@ -103,19 +97,14 @@ namespace MWRender
mCamera->removeUpdateCallback(mUpdateCallback);
}
MWWorld::Ptr Camera::getTrackingPtr() const
{
return mTrackingPtr;
}
osg::Vec3d Camera::getFocalPoint() const
{
const osg::Node* trackNode = mTrackingNode;
if (!trackNode)
if (!mTrackingNode)
{
return osg::Vec3d();
}
osg::NodePathList nodepaths = trackNode->getParentalNodePaths();
osg::NodePathList nodepaths = mTrackingNode->getParentalNodePaths();
if (nodepaths.empty())
return osg::Vec3d();
osg::Matrix worldMat = osg::computeLocalToWorld(nodepaths[0]);
@ -147,12 +136,9 @@ namespace MWRender
osg::Vec3d Camera::getFocalPointOffset() const
{
osg::Vec3d offset(0, 0, 10.f);
if (!mPreviewMode && !mVanity.enabled)
{
offset.x() += mFocalPointCurrentOffset.x() * cos(getYaw());
offset.y() += mFocalPointCurrentOffset.x() * sin(getYaw());
offset.z() += mFocalPointCurrentOffset.y();
}
offset.x() += mFocalPointCurrentOffset.x() * cos(getYaw());
offset.y() += mFocalPointCurrentOffset.x() * sin(getYaw());
offset.z() += mFocalPointCurrentOffset.y();
return offset;
}
@ -170,9 +156,6 @@ namespace MWRender
void Camera::updateCamera(osg::Camera *cam)
{
if (mTrackingPtr.isEmpty())
return;
osg::Quat orient = osg::Quat(getPitch(), osg::Vec3d(1,0,0)) * osg::Quat(getRoll(), osg::Vec3d(0, 1, 0)) * osg::Quat(getYaw(), osg::Vec3d(0,0,1));
osg::Vec3d focal, position;
getPosition(focal, position);
@ -183,7 +166,6 @@ namespace MWRender
{
position += inputManager->headOffset();
}
#else
#endif
osg::Vec3d forward = orient * osg::Vec3d(0,1,0);
@ -213,11 +195,6 @@ namespace MWRender
setRoll(roll);
}
void Camera::attachTo(const MWWorld::Ptr &ptr)
{
mTrackingPtr = ptr;
}
void Camera::update(float duration, bool paused)
{
if (mAnimation->upperBodyReady())
@ -230,7 +207,6 @@ namespace MWRender
}
if (mViewModeToggleQueued)
{
togglePreviewMode(false);
toggleViewMode();
mViewModeToggleQueued = false;
@ -242,13 +218,11 @@ namespace MWRender
// only show the crosshair in game mode
MWBase::WindowManager *wm = MWBase::Environment::get().getWindowManager();
wm->showCrosshair(!wm->isGuiMode() && !mVanity.enabled && !mPreviewMode
wm->showCrosshair(!wm->isGuiMode() && mMode != Mode::Preview && mMode != Mode::Vanity
&& (mFirstPersonView || mShowCrosshairInThirdPersonMode));
if(mVanity.enabled)
{
if(mMode == Mode::Vanity)
rotateCamera(0.f, 0.f, osg::DegreesToRadians(3.f * duration), true);
}
updateFocalPointOffset(duration);
@ -258,6 +232,24 @@ namespace MWRender
mSmoothedSpeed += osg::clampBetween(speed - mSmoothedSpeed, -maxDelta, maxDelta);
mMaxNextCameraDistance = mCameraDistance + duration * (100.f + mBaseCameraDistance);
updateStandingPreviewMode();
}
void Camera::updateStandingPreviewMode()
{
if (!mStandingPreviewAllowed)
return;
float speed = mTrackingPtr.getClass().getSpeed(mTrackingPtr);
bool combat = mTrackingPtr.getClass().isActor() &&
mTrackingPtr.getClass().getCreatureStats(mTrackingPtr).getDrawState() != MWMechanics::DrawState_Nothing;
bool standingStill = speed == 0 && !combat && !mFirstPersonView;
if (!standingStill && mMode == Mode::StandingPreview)
{
mMode = Mode::Normal;
calculateDeferredRotation();
}
else if (standingStill && mMode == Mode::Normal)
mMode = Mode::StandingPreview;
}
void Camera::setFocalPointTargetOffset(osg::Vec2d v)
@ -324,14 +316,19 @@ namespace MWRender
mTrackingPtr.getClass().getCreatureStats(mTrackingPtr).setSideMovementAngle(0);
mFirstPersonView = !mFirstPersonView;
updateStandingPreviewMode();
instantTransition();
processViewChange();
}
void Camera::allowVanityMode(bool allow)
{
if (!allow && mVanity.enabled)
if (!allow && mMode == Mode::Vanity)
{
disableDeferredPreviewRotation();
toggleVanityMode(false);
mVanity.allowed = allow;
}
mVanityAllowed = allow;
}
bool Camera::toggleVanityMode(bool enable)
@ -349,26 +346,18 @@ namespace MWRender
return false;
}
if(!mVanity.allowed && enable)
if (!mVanityAllowed && enable)
return false;
if(mVanity.enabled == enable)
if ((mMode == Mode::Vanity) == enable)
return true;
mVanity.enabled = enable;
mMode = enable ? Mode::Vanity : Mode::Normal;
if (!mDeferredRotationAllowed)
disableDeferredPreviewRotation();
if (!enable)
calculateDeferredRotation();
processViewChange();
float offset = mPreviewCam.offset;
if (mVanity.enabled) {
setPitch(osg::DegreesToRadians(-30.f));
mMainCam.offset = mCameraDistance;
} else {
offset = mMainCam.offset;
}
mCameraDistance = offset;
return true;
}
@ -377,22 +366,21 @@ namespace MWRender
if (mFirstPersonView && !mAnimation->upperBodyReady())
return;
if(mPreviewMode == enable)
if((mMode == Mode::Preview) == enable)
return;
mPreviewMode = enable;
processViewChange();
float offset = mCameraDistance;
if (mPreviewMode) {
mMainCam.offset = offset;
offset = mPreviewCam.offset;
} else {
mPreviewCam.offset = offset;
offset = mMainCam.offset;
mMode = enable ? Mode::Preview : Mode::Normal;
if (mMode == Mode::Normal)
updateStandingPreviewMode();
else if (mFirstPersonView)
instantTransition();
if (mMode == Mode::Normal)
{
if (!mDeferredRotationAllowed)
disableDeferredPreviewRotation();
calculateDeferredRotation();
}
mCameraDistance = offset;
processViewChange();
}
void Camera::setSneakOffset(float offset)
@ -400,13 +388,6 @@ namespace MWRender
mAnimation->setFirstPersonOffset(osg::Vec3f(0,0,-offset));
}
float Camera::getYaw() const
{
if(mVanity.enabled || mPreviewMode)
return mPreviewCam.yaw;
return mMainCam.yaw;
}
void Camera::setYaw(float angle)
{
if (angle > osg::PI) {
@ -414,18 +395,7 @@ namespace MWRender
} else if (angle < -osg::PI) {
angle += osg::PI*2;
}
if (mVanity.enabled || mPreviewMode) {
mPreviewCam.yaw = angle;
} else {
mMainCam.yaw = angle;
}
}
float Camera::getRoll()
{
if (mVanity.enabled || mPreviewMode)
return mPreviewCam.roll;
return mMainCam.roll;
mYaw = angle;
}
void Camera::setRoll(float angle)
@ -437,46 +407,19 @@ namespace MWRender
else if (angle < -osg::PI) {
angle += osg::PI * 2;
}
if (mVanity.enabled || mPreviewMode) {
mPreviewCam.roll = angle;
}
else {
mMainCam.roll = angle;
}
mRoll = angle;
#else
// It seems OpenMW saves roll data, causing the camera to get tilted
// when loading a VR save in non-VR.
mMainCam.roll = mPreviewCam.roll = 0.f;
mRoll = 0.f;
#endif
}
float Camera::getPitch() const
{
if (mVanity.enabled || mPreviewMode) {
return mPreviewCam.pitch;
}
return mMainCam.pitch;
}
void Camera::setPitch(float angle)
{
const float epsilon = 0.000001f;
float limit = osg::PI_2 - epsilon;
if(mPreviewMode)
limit /= 2;
#ifndef USE_OPENXR
if(angle > limit)
angle = limit;
else if(angle < -limit)
angle = -limit;
#endif
if (mVanity.enabled || mPreviewMode) {
mPreviewCam.pitch = angle;
} else {
mMainCam.pitch = angle;
}
mPitch = osg::clampBetween(angle, -limit, limit);
}
float Camera::getCameraDistance() const
@ -488,50 +431,25 @@ namespace MWRender
void Camera::updateBaseCameraDistance(float dist, bool adjust)
{
if(mFirstPersonView && !mPreviewMode && !mVanity.enabled)
if (isFirstPerson())
return;
mIsNearest = false;
if (adjust)
{
if (mVanity.enabled || mPreviewMode)
dist += mCameraDistance;
else
dist += std::min(mCameraDistance - getCameraDistanceCorrection(), mBaseCameraDistance);
}
dist += std::min(mCameraDistance - getCameraDistanceCorrection(), mBaseCameraDistance);
if (dist >= mFurthest)
dist = mFurthest;
else if (dist <= mNearest)
{
dist = mNearest;
mIsNearest = true;
}
if (mVanity.enabled || mPreviewMode)
mPreviewCam.offset = dist;
else if (!mFirstPersonView)
{
mBaseCameraDistance = dist;
Settings::Manager::setFloat("third person camera distance", "Camera", dist);
}
mIsNearest = dist <= mNearest;
mBaseCameraDistance = osg::clampBetween(dist, mNearest, mFurthest);
Settings::Manager::setFloat("third person camera distance", "Camera", mBaseCameraDistance);
setCameraDistance();
}
void Camera::setCameraDistance(float dist, bool adjust)
{
if(mFirstPersonView && !mPreviewMode && !mVanity.enabled)
if (isFirstPerson())
return;
if (adjust) dist += mCameraDistance;
if (dist >= mFurthest)
dist = mFurthest;
else if (dist < 10.f)
dist = 10.f;
mCameraDistance = dist;
if (adjust)
dist += mCameraDistance;
mCameraDistance = osg::clampBetween(dist, 10.f, mFurthest);
}
float Camera::getCameraDistanceCorrection() const
@ -549,21 +467,17 @@ namespace MWRender
void Camera::setCameraDistance()
{
if (mVanity.enabled || mPreviewMode)
mCameraDistance = mPreviewCam.offset;
else if (!mFirstPersonView)
{
mCameraDistance = mBaseCameraDistance + getCameraDistanceCorrection();
if (mDynamicCameraDistanceEnabled)
mCameraDistance = std::min(mCameraDistance, mMaxNextCameraDistance);
}
mFocalPointAdjustment = osg::Vec3d();
if (isFirstPerson())
return;
mCameraDistance = mBaseCameraDistance + getCameraDistanceCorrection();
if (mDynamicCameraDistanceEnabled)
mCameraDistance = std::min(mCameraDistance, mMaxNextCameraDistance);
}
void Camera::setAnimation(NpcAnimation *anim)
{
mAnimation = anim;
processViewChange();
}
@ -602,13 +516,74 @@ namespace MWRender
#endif
}
bool Camera::isVanityOrPreviewModeEnabled() const
void Camera::applyDeferredPreviewRotationToPlayer(float dt)
{
if (isVanityOrPreviewModeEnabled() || mTrackingPtr.isEmpty())
return;
osg::Vec3f rot = mDeferredRotation;
float delta = rot.normalize();
delta = std::min(delta, (delta + 1.f) * 3 * dt);
rot *= delta;
mDeferredRotation -= rot;
if (mDeferredRotationDisabled)
{
mDeferredRotationDisabled = delta > 0.0001;
rotateCameraToTrackingPtr();
return;
}
auto& movement = mTrackingPtr.getClass().getMovementSettings(mTrackingPtr);
movement.mRotation[0] += rot.x();
movement.mRotation[1] += rot.y();
movement.mRotation[2] += rot.z();
if (std::abs(mDeferredRotation.z()) > 0.0001)
{
float s = std::sin(mDeferredRotation.z());
float c = std::cos(mDeferredRotation.z());
float x = movement.mPosition[0];
float y = movement.mPosition[1];
movement.mPosition[0] = x * c + y * s;
movement.mPosition[1] = x * -s + y * c;
}
}
void Camera::rotateCameraToTrackingPtr()
{
setPitch(-mTrackingPtr.getRefData().getPosition().rot[0] - mDeferredRotation.x());
setYaw(-mTrackingPtr.getRefData().getPosition().rot[2] - mDeferredRotation.z());
}
void Camera::instantTransition()
{
return mPreviewMode || mVanity.enabled;
mSkipFocalPointTransition = true;
mDeferredRotationDisabled = false;
mDeferredRotation = osg::Vec3f();
rotateCameraToTrackingPtr();
}
bool Camera::isNearest() const
void Camera::calculateDeferredRotation()
{
return mIsNearest;
MWWorld::Ptr ptr = mTrackingPtr;
if (isVanityOrPreviewModeEnabled() || ptr.isEmpty())
return;
if (mFirstPersonView)
{
instantTransition();
return;
}
mDeferredRotation.x() = -ptr.getRefData().getPosition().rot[0] - mPitch;
mDeferredRotation.z() = -ptr.getRefData().getPosition().rot[2] - mYaw;
if (mDeferredRotation.x() > osg::PI)
mDeferredRotation.x() -= 2 * osg::PI;
if (mDeferredRotation.x() < -osg::PI)
mDeferredRotation.x() += 2 * osg::PI;
if (mDeferredRotation.z() > osg::PI)
mDeferredRotation.z() -= 2 * osg::PI;
if (mDeferredRotation.z() < -osg::PI)
mDeferredRotation.z() += 2 * osg::PI;
}
}

@ -23,11 +23,10 @@ namespace MWRender
/// \brief Camera control
class Camera
{
private:
struct CamData {
float roll, pitch, yaw, offset;
};
public:
enum class Mode { Normal, Vanity, Preview, StandingPreview };
private:
MWWorld::Ptr mTrackingPtr;
osg::ref_ptr<const osg::Node> mTrackingNode;
float mHeightScale;
@ -37,17 +36,17 @@ namespace MWRender
NpcAnimation *mAnimation;
bool mFirstPersonView;
bool mPreviewMode;
Mode mMode;
bool mVanityAllowed;
bool mStandingPreviewAllowed;
bool mDeferredRotationAllowed;
float mNearest;
float mFurthest;
bool mIsNearest;
struct {
bool enabled, allowed;
} mVanity;
float mHeight, mBaseCameraDistance;
CamData mMainCam, mPreviewCam;
float mPitch, mYaw, mRoll;
bool mVanityToggleQueued;
bool mVanityToggleQueuedValue;
@ -78,15 +77,23 @@ namespace MWRender
osg::ref_ptr<osg::NodeCallback> mUpdateCallback;
// Used to rotate player to the direction of view after exiting preview or vanity mode.
osg::Vec3f mDeferredRotation;
bool mDeferredRotationDisabled;
void calculateDeferredRotation();
void updateStandingPreviewMode();
public:
Camera(osg::Camera* camera);
~Camera();
MWWorld::Ptr getTrackingPtr() const;
/// Attach camera to object
void attachTo(const MWWorld::Ptr &ptr) { mTrackingPtr = ptr; }
MWWorld::Ptr getTrackingPtr() const { return mTrackingPtr; }
void setFocalPointTransitionSpeed(float v) { mFocalPointTransitionSpeedCoef = v; }
void setFocalPointTargetOffset(osg::Vec2d v);
void skipFocalPointTransition() { mSkipFocalPointTransition = true; }
void instantTransition();
void enableDynamicCameraDistance(bool v) { mDynamicCameraDistanceEnabled = v; }
void enableCrosshairInThirdPersonMode(bool v) { mShowCrosshairInThirdPersonMode = v; }
@ -102,18 +109,16 @@ namespace MWRender
/// Set where the camera is looking at. Uses Morrowind (euler) angles
/// \param rot Rotation angles in radians
void rotateCamera(float pitch, float roll, float yaw, bool adjust);
void rotateCameraToTrackingPtr();
float getYaw() const;
float getYaw() const { return mYaw; }
void setYaw(float angle);
float getRoll();
void setRoll(float angle);
float getPitch() const;
float getPitch() const { return mPitch; }
void setPitch(float angle);
/// Attach camera to object
void attachTo(const MWWorld::Ptr &);
float getRoll() { return mRoll; }
void setRoll(float angle);
/// @param Force view mode switch, even if currently not allowed by the animation.
void toggleViewMode(bool force=false);
@ -124,11 +129,13 @@ namespace MWRender
/// @note this may be ignored if an important animation is currently playing
void togglePreviewMode(bool enable);
void applyDeferredPreviewRotationToPlayer(float dt);
void disableDeferredPreviewRotation() { mDeferredRotationDisabled = true; }
/// \brief Lowers the camera for sneak.
void setSneakOffset(float offset);
bool isFirstPerson() const
{ return !(mVanity.enabled || mPreviewMode || !mFirstPersonView); }
bool isFirstPerson() const { return mFirstPersonView && mMode == Mode::Normal; }
void processViewChange();
@ -159,9 +166,10 @@ namespace MWRender
/// Stores focal and camera world positions in passed arguments
void getPosition(osg::Vec3d &focal, osg::Vec3d &camera) const;
bool isVanityOrPreviewModeEnabled() const;
bool isVanityOrPreviewModeEnabled() const { return mMode != Mode::Normal; }
Mode getMode() const { return mMode; }
bool isNearest() const;
bool isNearest() const { return mIsNearest; }
};
}

@ -660,7 +660,7 @@ namespace MWRender
if(ptr == mCamera->getTrackingPtr() &&
!mCamera->isVanityOrPreviewModeEnabled())
{
mCamera->rotateCamera(-ptr.getRefData().getPosition().rot[0], -ptr.getRefData().getPosition().rot[1], -ptr.getRefData().getPosition().rot[2], false);
mCamera->rotateCameraToTrackingPtr();
}
ptr.getRefData().getBaseNode()->setAttitude(rot);

@ -33,12 +33,13 @@ namespace MWRender
void ViewOverShoulderController::update()
{
if (mCamera->isVanityOrPreviewModeEnabled() || mCamera->isFirstPerson())
if (mCamera->isFirstPerson())
return;
Mode oldMode = mMode;
auto ptr = mCamera->getTrackingPtr();
if (ptr.getClass().isActor() && ptr.getClass().getCreatureStats(ptr).getDrawState() != MWMechanics::DrawState_Nothing)
bool combat = ptr.getClass().isActor() && ptr.getClass().getCreatureStats(ptr).getDrawState() != MWMechanics::DrawState_Nothing;
if (combat && !mCamera->isVanityOrPreviewModeEnabled())
mMode = Mode::Combat;
else if (MWBase::Environment::get().getWorld()->isSwimming(ptr))
mMode = Mode::Swimming;
@ -46,12 +47,18 @@ namespace MWRender
mMode = mDefaultShoulderIsRight ? Mode::RightShoulder : Mode::LeftShoulder;
if (mAutoSwitchShoulder && (mMode == Mode::LeftShoulder || mMode == Mode::RightShoulder))
trySwitchShoulder();
if (oldMode == mMode) return;
if (oldMode == Mode::Combat || mMode == Mode::Combat)
if (oldMode == mMode)
return;
if (mCamera->getMode() == Camera::Mode::Vanity)
// Player doesn't touch controls for a long time. Transition should be very slow.
mCamera->setFocalPointTransitionSpeed(0.2f);
else if ((oldMode == Mode::Combat || mMode == Mode::Combat) && mCamera->getMode() == Camera::Mode::Normal)
// Transition to/from combat mode and we are not it preview mode. Should be fast.
mCamera->setFocalPointTransitionSpeed(5.f);
else
mCamera->setFocalPointTransitionSpeed(1.f);
mCamera->setFocalPointTransitionSpeed(1.f); // Default transition speed.
switch (mMode)
{
@ -70,6 +77,9 @@ namespace MWRender
void ViewOverShoulderController::trySwitchShoulder()
{
if (mCamera->getMode() != Camera::Mode::Normal)
return;
const float limitToSwitch = 120; // switch to other shoulder if wall is closer than this limit
const float limitToSwitchBack = 300; // switch back to default shoulder if there is no walls at this distance
@ -93,4 +103,4 @@ namespace MWRender
mMode = mDefaultShoulderIsRight ? Mode::RightShoulder : Mode::LeftShoulder;
}
}
}

@ -954,7 +954,7 @@ namespace MWWorld
removeContainerScripts(getPlayerPtr());
mWorldScene->changeToInteriorCell(cellName, position, adjustPlayerPos, changeEvent);
addContainerScripts(getPlayerPtr(), getPlayerPtr().getCell());
mRendering->getCamera()->skipFocalPointTransition();
mRendering->getCamera()->instantTransition();
#ifdef USE_OPENXR
auto* xrInput = MWVR::Environment::get().getInputManager();
@ -976,7 +976,7 @@ namespace MWWorld
removeContainerScripts(getPlayerPtr());
mWorldScene->changeToExteriorCell(position, adjustPlayerPos, changeEvent);
addContainerScripts(getPlayerPtr(), getPlayerPtr().getCell());
mRendering->getCamera()->skipFocalPointTransition();
mRendering->getCamera()->instantTransition();
#ifdef USE_OPENXR
auto* xrInput = MWVR::Environment::get().getInputManager();
@ -2446,6 +2446,16 @@ namespace MWWorld
return mRendering->toggleVanityMode(enable);
}
void World::disableDeferredPreviewRotation()
{
mRendering->getCamera()->disableDeferredPreviewRotation();
}
void World::applyDeferredPreviewRotationToPlayer(float dt)
{
mRendering->getCamera()->applyDeferredPreviewRotationToPlayer(dt);
}
void World::allowVanityMode(bool allow)
{
mRendering->allowVanityMode(allow);

@ -540,6 +540,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;

@ -174,3 +174,27 @@ Slightly pulls camera away (or closer in case of negative value) when the charac
This setting can only be configured by editing the settings configuration file.
preview if stand still
----------------------
:Type: boolean
:Range: True/False
:Default: False
If enabled then the character rotation is not synchonized with the camera rotation while the character doesn't move and not in combat mode.
This setting can only be configured by editing the settings configuration file.
deferred preview rotation
-------------------------
:Type: boolean
:Range: True/False
:Default: True
Makes difference only in third person mode.
If enabled then the character smoothly rotates to the view direction after exiting preview or vanity mode.
If disabled then the camera rotates rather than the character.
This setting can only be configured by editing the settings configuration file.

@ -48,6 +48,12 @@ auto switch shoulder = true
# Slightly pulls camera away when the character moves. Works only in 'view over shoulder' mode. Set to 0 to disable.
zoom out when move coef = 20
# Automatically enable preview mode when player doesn't move.
preview if stand still = false
# Rotate the character to the view direction after exiting preview mode.
deferred preview rotation = true
[Cells]
# Preload cells in a background thread. All settings starting with 'preload' have no effect unless this is enabled.

Loading…
Cancel
Save