forked from mirror/openmw-tes3mp
Respect the framelimit in all cases (Fixes #3531)
Affects loading screen, videos & modal dialogs. Also skips rendering if window is minimized.
This commit is contained in:
parent
dc53573de4
commit
8c6a8ca48d
6 changed files with 81 additions and 25 deletions
|
@ -84,7 +84,6 @@ void OMW::Engine::frame(float frametime)
|
|||
try
|
||||
{
|
||||
mStartTick = mViewer->getStartTick();
|
||||
mEnvironment.setFrameDuration (frametime);
|
||||
|
||||
// update input
|
||||
mEnvironment.getInputManager()->update(frametime, false);
|
||||
|
@ -651,6 +650,8 @@ void OMW::Engine::go()
|
|||
Settings::Manager::getString("screenshot format", "General")));
|
||||
mViewer->addEventHandler(mScreenCaptureHandler);
|
||||
|
||||
mEnvironment.setFrameRateLimit(Settings::Manager::getFloat("framerate limit", "Video"));
|
||||
|
||||
// Create encoder
|
||||
ToUTF8::Utf8Encoder encoder (mEncoding);
|
||||
mEncoder = &encoder;
|
||||
|
@ -684,7 +685,6 @@ void OMW::Engine::go()
|
|||
// Start the main rendering loop
|
||||
osg::Timer frameTimer;
|
||||
double simulationTime = 0.0;
|
||||
float framerateLimit = Settings::Manager::getFloat("framerate limit", "Video");
|
||||
while (!mViewer->done() && !mEnvironment.getStateManager()->hasQuitRequest())
|
||||
{
|
||||
double dt = frameTimer.time_s();
|
||||
|
@ -697,6 +697,8 @@ void OMW::Engine::go()
|
|||
|
||||
mViewer->advance(simulationTime);
|
||||
|
||||
mEnvironment.setFrameDuration(dt);
|
||||
|
||||
frame(dt);
|
||||
|
||||
if (!mEnvironment.getInputManager()->isWindowVisible())
|
||||
|
@ -714,15 +716,7 @@ void OMW::Engine::go()
|
|||
mViewer->renderingTraversals();
|
||||
}
|
||||
|
||||
if (framerateLimit > 0.f)
|
||||
{
|
||||
double thisFrameTime = frameTimer.time_s();
|
||||
double minFrameTime = 1.0 / framerateLimit;
|
||||
if (thisFrameTime < minFrameTime)
|
||||
{
|
||||
OpenThreads::Thread::microSleep(1000*1000*(minFrameTime-thisFrameTime));
|
||||
}
|
||||
}
|
||||
mEnvironment.limitFrameRate(frameTimer.time_s());
|
||||
}
|
||||
|
||||
// Save user settings
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
#include <cassert>
|
||||
|
||||
#include <OpenThreads/Thread>
|
||||
|
||||
#include "world.hpp"
|
||||
#include "scriptmanager.hpp"
|
||||
#include "dialoguemanager.hpp"
|
||||
|
@ -17,7 +19,7 @@ MWBase::Environment *MWBase::Environment::sThis = 0;
|
|||
MWBase::Environment::Environment()
|
||||
: mWorld (0), mSoundManager (0), mScriptManager (0), mWindowManager (0),
|
||||
mMechanicsManager (0), mDialogueManager (0), mJournal (0), mInputManager (0), mStateManager (0),
|
||||
mFrameDuration (0)
|
||||
mFrameDuration (0), mFrameRateLimit(0.f)
|
||||
{
|
||||
assert (!sThis);
|
||||
sThis = this;
|
||||
|
@ -79,6 +81,29 @@ void MWBase::Environment::setFrameDuration (float duration)
|
|||
mFrameDuration = duration;
|
||||
}
|
||||
|
||||
void MWBase::Environment::setFrameRateLimit(float limit)
|
||||
{
|
||||
mFrameRateLimit = limit;
|
||||
}
|
||||
|
||||
float MWBase::Environment::getFrameRateLimit() const
|
||||
{
|
||||
return mFrameRateLimit;
|
||||
}
|
||||
|
||||
void MWBase::Environment::limitFrameRate(double dt) const
|
||||
{
|
||||
if (mFrameRateLimit > 0.f)
|
||||
{
|
||||
double thisFrameTime = dt;
|
||||
double minFrameTime = 1.0 / static_cast<double>(mFrameRateLimit);
|
||||
if (thisFrameTime < minFrameTime)
|
||||
{
|
||||
OpenThreads::Thread::microSleep(1000*1000*(minFrameTime-thisFrameTime));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MWBase::World *MWBase::Environment::getWorld() const
|
||||
{
|
||||
assert (mWorld);
|
||||
|
|
|
@ -33,6 +33,7 @@ namespace MWBase
|
|||
InputManager *mInputManager;
|
||||
StateManager *mStateManager;
|
||||
float mFrameDuration;
|
||||
float mFrameRateLimit;
|
||||
|
||||
Environment (const Environment&);
|
||||
///< not implemented
|
||||
|
@ -67,6 +68,10 @@ namespace MWBase
|
|||
void setFrameDuration (float duration);
|
||||
///< Set length of current frame in seconds.
|
||||
|
||||
void setFrameRateLimit(float frameRateLimit);
|
||||
float getFrameRateLimit() const;
|
||||
void limitFrameRate(double dt) const;
|
||||
|
||||
World *getWorld() const;
|
||||
|
||||
SoundManager *getSoundManager() const;
|
||||
|
|
|
@ -102,6 +102,15 @@ namespace MWGui
|
|||
mBackgroundImage->setVisible(visible);
|
||||
}
|
||||
|
||||
double LoadingScreen::getTargetFrameRate() const
|
||||
{
|
||||
double frameRateLimit = MWBase::Environment::get().getFrameRateLimit();
|
||||
if (frameRateLimit > 0)
|
||||
return std::min(frameRateLimit, mTargetFrameRate);
|
||||
else
|
||||
return mTargetFrameRate;
|
||||
}
|
||||
|
||||
class CopyFramebufferToTextureCallback : public osg::Camera::DrawCallback
|
||||
{
|
||||
public:
|
||||
|
@ -141,7 +150,7 @@ namespace MWGui
|
|||
if (mViewer->getIncrementalCompileOperation())
|
||||
{
|
||||
mViewer->getIncrementalCompileOperation()->setMaximumNumOfObjectsToCompilePerFrame(100);
|
||||
mViewer->getIncrementalCompileOperation()->setTargetFrameRate(mTargetFrameRate);
|
||||
mViewer->getIncrementalCompileOperation()->setTargetFrameRate(getTargetFrameRate());
|
||||
}
|
||||
|
||||
// Assign dummy bounding sphere callback to avoid the bounding sphere of the entire scene being recomputed after each frame of loading
|
||||
|
@ -210,7 +219,7 @@ namespace MWGui
|
|||
void LoadingScreen::setProgress (size_t value)
|
||||
{
|
||||
// skip expensive update if there isn't enough visible progress
|
||||
if (value - mProgress < mProgressBar->getScrollRange()/200.f)
|
||||
if (mProgressBar->getWidth() <= 0 || value - mProgress < mProgressBar->getScrollRange()/mProgressBar->getWidth())
|
||||
return;
|
||||
value = std::min(value, mProgressBar->getScrollRange()-1);
|
||||
mProgress = value;
|
||||
|
@ -231,7 +240,7 @@ namespace MWGui
|
|||
|
||||
bool LoadingScreen::needToDrawLoadingScreen()
|
||||
{
|
||||
if ( mTimer.time_m() <= mLastRenderTime + (1.0/mTargetFrameRate) * 1000.0)
|
||||
if ( mTimer.time_m() <= mLastRenderTime + (1.0/getTargetFrameRate()) * 1000.0)
|
||||
return false;
|
||||
|
||||
// the minimal delay before a loading screen shows
|
||||
|
|
|
@ -43,6 +43,8 @@ namespace MWGui
|
|||
|
||||
virtual void setVisible(bool visible);
|
||||
|
||||
double getTargetFrameRate() const;
|
||||
|
||||
private:
|
||||
void findSplashScreens();
|
||||
bool needToDrawLoadingScreen();
|
||||
|
|
|
@ -906,19 +906,30 @@ namespace MWGui
|
|||
|
||||
if (block)
|
||||
{
|
||||
osg::Timer frameTimer;
|
||||
while (mMessageBoxManager->readPressedButton(false) == -1
|
||||
&& !MWBase::Environment::get().getStateManager()->hasQuitRequest())
|
||||
{
|
||||
mMessageBoxManager->onFrame(0.f);
|
||||
MWBase::Environment::get().getInputManager()->update(0, true, false);
|
||||
double dt = frameTimer.time_s();
|
||||
frameTimer.setStartTick();
|
||||
|
||||
mMessageBoxManager->onFrame(dt);
|
||||
MWBase::Environment::get().getInputManager()->update(dt, true, false);
|
||||
|
||||
if (!MWBase::Environment::get().getInputManager()->isWindowVisible())
|
||||
OpenThreads::Thread::microSleep(5000);
|
||||
else
|
||||
{
|
||||
mViewer->eventTraversal();
|
||||
mViewer->updateTraversal();
|
||||
mViewer->renderingTraversals();
|
||||
}
|
||||
// at the time this function is called we are in the middle of a frame,
|
||||
// so out of order calls are necessary to get a correct frameNumber for the next frame.
|
||||
// refer to the advance() and frame() order in Engine::go()
|
||||
mViewer->eventTraversal();
|
||||
mViewer->updateTraversal();
|
||||
mViewer->renderingTraversals();
|
||||
mViewer->advance(mViewer->getFrameStamp()->getSimulationTime());
|
||||
|
||||
MWBase::Environment::get().limitFrameRate(frameTimer.time_s());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1838,18 +1849,28 @@ namespace MWGui
|
|||
if (mVideoWidget->hasAudioStream())
|
||||
MWBase::Environment::get().getSoundManager()->pauseSounds(
|
||||
MWBase::SoundManager::Play_TypeMask&(~MWBase::SoundManager::Play_TypeMovie));
|
||||
|
||||
osg::Timer frameTimer;
|
||||
while (mVideoWidget->update() && !MWBase::Environment::get().getStateManager()->hasQuitRequest())
|
||||
{
|
||||
MWBase::Environment::get().getInputManager()->update(0, true, false);
|
||||
double dt = frameTimer.time_s();
|
||||
frameTimer.setStartTick();
|
||||
|
||||
MWBase::Environment::get().getInputManager()->update(dt, true, false);
|
||||
|
||||
if (!MWBase::Environment::get().getInputManager()->isWindowVisible())
|
||||
OpenThreads::Thread::microSleep(5000);
|
||||
else
|
||||
{
|
||||
mViewer->eventTraversal();
|
||||
mViewer->updateTraversal();
|
||||
mViewer->renderingTraversals();
|
||||
}
|
||||
// at the time this function is called we are in the middle of a frame,
|
||||
// so out of order calls are necessary to get a correct frameNumber for the next frame.
|
||||
// refer to the advance() and frame() order in Engine::go()
|
||||
mViewer->eventTraversal();
|
||||
mViewer->updateTraversal();
|
||||
mViewer->renderingTraversals();
|
||||
mViewer->advance(mViewer->getFrameStamp()->getSimulationTime());
|
||||
|
||||
MWBase::Environment::get().limitFrameRate(frameTimer.time_s());
|
||||
}
|
||||
mVideoWidget->stop();
|
||||
|
||||
|
|
Loading…
Reference in a new issue