mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-30 16:15:31 +00:00
Improved preview mode
This commit is contained in:
parent
c3b581131d
commit
4d206d2c67
13 changed files with 157 additions and 48 deletions
|
@ -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(Settings::Manager::getFloat("third person camera distance", "Camera")),
|
||||
mUseSeparatePreviewCam(Settings::Manager::getBool("separate preview camera", "Camera")),
|
||||
mVanityToggleQueued(false),
|
||||
mVanityToggleQueuedValue(false),
|
||||
mViewModeToggleQueued(false),
|
||||
|
@ -126,7 +127,7 @@ namespace MWRender
|
|||
osg::Vec3d Camera::getFocalPointOffset() const
|
||||
{
|
||||
osg::Vec3d offset(0, 0, 10.f);
|
||||
if (!mPreviewMode && !mVanity.enabled)
|
||||
if (!mUseSeparatePreviewCam || (!mPreviewMode && !mVanity.enabled))
|
||||
{
|
||||
offset.x() += mFocalPointCurrentOffset.x() * cos(getYaw());
|
||||
offset.y() += mFocalPointCurrentOffset.x() * sin(getYaw());
|
||||
|
@ -322,17 +323,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;
|
||||
}
|
||||
|
||||
|
@ -347,16 +350,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)
|
||||
|
@ -366,7 +371,7 @@ namespace MWRender
|
|||
|
||||
float Camera::getYaw() const
|
||||
{
|
||||
if(mVanity.enabled || mPreviewMode)
|
||||
if (mUseSeparatePreviewCam && (mVanity.enabled || mPreviewMode))
|
||||
return mPreviewCam.yaw;
|
||||
return mMainCam.yaw;
|
||||
}
|
||||
|
@ -378,18 +383,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;
|
||||
}
|
||||
|
||||
|
@ -397,7 +400,7 @@ namespace MWRender
|
|||
{
|
||||
const float epsilon = 0.000001f;
|
||||
float limit = osg::PI_2 - epsilon;
|
||||
if(mPreviewMode)
|
||||
if(mUseSeparatePreviewCam && mPreviewMode)
|
||||
limit /= 2;
|
||||
|
||||
if(angle > limit)
|
||||
|
@ -405,11 +408,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
|
||||
|
@ -428,7 +430,7 @@ namespace MWRender
|
|||
|
||||
if (adjust)
|
||||
{
|
||||
if (mVanity.enabled || mPreviewMode)
|
||||
if (mUseSeparatePreviewCam && (mVanity.enabled || mPreviewMode))
|
||||
dist += mCameraDistance;
|
||||
else
|
||||
dist += std::min(mCameraDistance - getCameraDistanceCorrection(), mBaseCameraDistance);
|
||||
|
@ -443,7 +445,7 @@ namespace MWRender
|
|||
mIsNearest = true;
|
||||
}
|
||||
|
||||
if (mVanity.enabled || mPreviewMode)
|
||||
if (mUseSeparatePreviewCam && (mVanity.enabled || mPreviewMode))
|
||||
mPreviewCam.offset = dist;
|
||||
else if (!mFirstPersonView)
|
||||
{
|
||||
|
@ -482,7 +484,7 @@ namespace MWRender
|
|||
|
||||
void Camera::setCameraDistance()
|
||||
{
|
||||
if (mVanity.enabled || mPreviewMode)
|
||||
if (mUseSeparatePreviewCam && (mVanity.enabled || mPreviewMode))
|
||||
mCameraDistance = mPreviewCam.offset;
|
||||
else if (!mFirstPersonView)
|
||||
{
|
||||
|
|
|
@ -48,6 +48,7 @@ namespace MWRender
|
|||
|
||||
float mHeight, mBaseCameraDistance;
|
||||
CamData mMainCam, mPreviewCam;
|
||||
bool mUseSeparatePreviewCam;
|
||||
|
||||
bool mVanityToggleQueued;
|
||||
bool mVanityToggleQueuedValue;
|
||||
|
@ -115,6 +116,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);
|
||||
|
||||
|
@ -152,6 +156,7 @@ namespace MWRender
|
|||
void getPosition(osg::Vec3d &focal, osg::Vec3d &camera) const;
|
||||
|
||||
bool isVanityOrPreviewModeEnabled() const;
|
||||
bool isVanityModeEnabled() const { return mVanity.enabled; }
|
||||
|
||||
bool isNearest() const;
|
||||
};
|
||||
|
|
|
@ -58,6 +58,7 @@
|
|||
#include "../mwgui/loadingscreen.hpp"
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/windowmanager.hpp"
|
||||
#include "../mwmechanics/movement.hpp"
|
||||
|
||||
#include "sky.hpp"
|
||||
#include "effectmanager.hpp"
|
||||
|
@ -203,6 +204,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");
|
||||
|
@ -653,7 +656,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);
|
||||
|
@ -1324,6 +1328,50 @@ namespace MWRender
|
|||
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() > 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;
|
||||
}
|
||||
|
||||
void RenderingManager::setCameraDistance(float dist, bool adjust, bool override)
|
||||
{
|
||||
if(!mCamera->isVanityOrPreviewModeEnabled() && !mCamera->isFirstPerson())
|
||||
|
@ -1373,11 +1421,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)
|
||||
|
|
|
@ -221,6 +221,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.
|
||||
|
@ -310,6 +313,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&);
|
||||
};
|
||||
|
|
|
@ -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,9 +47,13 @@ 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->isVanityOrPreviewModeEnabled())
|
||||
mCamera->setFocalPointTransitionSpeed(mCamera->isVanityModeEnabled() ? 0.2 : 1);
|
||||
else if (oldMode == Mode::Combat || mMode == Mode::Combat)
|
||||
mCamera->setFocalPointTransitionSpeed(5.f);
|
||||
else
|
||||
mCamera->setFocalPointTransitionSpeed(1.f);
|
||||
|
|
|
@ -2405,6 +2405,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;
|
||||
|
||||
|
|
|
@ -33,6 +33,10 @@ field of view = 60.0
|
|||
# Best to leave this at the default since vanilla assets are not complete enough to adapt to high FoV's. Too low FoV would clip the hands off screen.
|
||||
first person field of view = 60.0
|
||||
|
||||
# true - standard bahaviour of preview and vanity camera
|
||||
# false - smooth preview mode
|
||||
separate preview camera = true
|
||||
|
||||
# Distance from the camera to the character in third person mode.
|
||||
third person camera distance = 192
|
||||
|
||||
|
|
Loading…
Reference in a new issue