Port loading screen

This commit is contained in:
scrawl 2015-05-03 16:58:05 +02:00
parent 92cbc13964
commit 351fd842fd
3 changed files with 77 additions and 96 deletions

View file

@ -1,14 +1,6 @@
#include "loadingscreen.hpp" #include "loadingscreen.hpp"
#include <OgreRenderWindow.h> #include <osgViewer/Viewer>
#include <OgreMaterialManager.h>
#include <OgreTechnique.h>
#include <OgreRectangle2D.h>
#include <OgreSceneNode.h>
#include <OgreTextureManager.h>
#include <OgreViewport.h>
#include <OgreHardwarePixelBuffer.h>
#include <OgreSceneManager.h>
#include <MyGUI_RenderManager.h> #include <MyGUI_RenderManager.h>
#include <MyGUI_ScrollBar.h> #include <MyGUI_ScrollBar.h>
@ -18,6 +10,7 @@
#include <components/misc/rng.hpp> #include <components/misc/rng.hpp>
#include <components/settings/settings.hpp> #include <components/settings/settings.hpp>
#include <components/vfs/manager.hpp>
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp" #include "../mwbase/world.hpp"
@ -26,15 +19,17 @@
#include "../mwbase/windowmanager.hpp" #include "../mwbase/windowmanager.hpp"
#include "../mwbase/inputmanager.hpp" #include "../mwbase/inputmanager.hpp"
#include "../mwrender/vismask.hpp"
#include "backgroundimage.hpp" #include "backgroundimage.hpp"
namespace MWGui namespace MWGui
{ {
LoadingScreen::LoadingScreen(Ogre::SceneManager* sceneMgr, Ogre::RenderWindow* rw) LoadingScreen::LoadingScreen(const VFS::Manager* vfs, osgViewer::Viewer* viewer)
: mSceneMgr(sceneMgr) : WindowBase("openmw_loading_screen.layout")
, mWindow(rw) , mVFS(vfs)
, WindowBase("openmw_loading_screen.layout") , mViewer(viewer)
, mLastRenderTime(0) , mLastRenderTime(0)
, mLastWallpaperChangeTime(0) , mLastWallpaperChangeTime(0)
, mProgress(0) , mProgress(0)
@ -52,6 +47,32 @@ namespace MWGui
MyGUI::Align::Stretch, "Menu"); MyGUI::Align::Stretch, "Menu");
setVisible(false); setVisible(false);
findSplashScreens();
}
void LoadingScreen::findSplashScreens()
{
const std::map<std::string, VFS::File*>& index = mVFS->getIndex();
std::string pattern = "Splash/";
mVFS->normalizeFilename(pattern);
std::map<std::string, VFS::File*>::const_iterator found = index.lower_bound(pattern);
while (found != index.end())
{
const std::string& name = found->first;
if (name.size() >= pattern.size() && name.substr(0, pattern.size()) == pattern)
{
size_t pos = name.find_last_of('.');
if (pos != std::string::npos && name.compare(pos, name.size()-pos, ".tga") == 0)
mSplashScreens.push_back(found->first);
}
else
break;
++found;
}
if (mSplashScreens.empty())
std::cerr << "No splash screens found!" << std::endl;
} }
void LoadingScreen::setLabel(const std::string &label) void LoadingScreen::setLabel(const std::string &label)
@ -80,17 +101,13 @@ namespace MWGui
if (mMainWidget->getVisible()) if (mMainWidget->getVisible())
return; return;
// Temporarily turn off VSync, we want to do actual loading rather than waiting for the screen to sync.
// Threaded loading would be even better, of course - especially because some drivers force VSync to on and we can't change it.
mVSyncWasEnabled = mWindow->isVSyncEnabled();
mWindow->setVSyncEnabled(false);
bool showWallpaper = (MWBase::Environment::get().getStateManager()->getState() bool showWallpaper = (MWBase::Environment::get().getStateManager()->getState()
== MWBase::StateManager::State_NoGame); == MWBase::StateManager::State_NoGame);
if (!showWallpaper) if (!showWallpaper)
{ {
// TODO
/*
mBackgroundImage->setImageTexture(""); mBackgroundImage->setImageTexture("");
int width = mWindow->getWidth(); int width = mWindow->getWidth();
int height = mWindow->getHeight(); int height = mWindow->getHeight();
@ -111,6 +128,7 @@ namespace MWGui
mWindow->copyContentsToMemory(texture->getBuffer()->lock(Ogre::Image::Box(0,0,width,height), Ogre::HardwareBuffer::HBL_DISCARD)); mWindow->copyContentsToMemory(texture->getBuffer()->lock(Ogre::Image::Box(0,0,width,height), Ogre::HardwareBuffer::HBL_DISCARD));
texture->getBuffer()->unlock(); texture->getBuffer()->unlock();
mBackgroundImage->setBackgroundImage(texture->getName(), false, false); mBackgroundImage->setBackgroundImage(texture->getName(), false, false);
*/
} }
setVisible(true); setVisible(true);
@ -125,9 +143,6 @@ namespace MWGui
void LoadingScreen::loadingOff() void LoadingScreen::loadingOff()
{ {
// Re-enable vsync now.
mWindow->setVSyncEnabled(mVSyncWasEnabled);
setVisible(false); setVisible(false);
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Loading); MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Loading);
@ -136,29 +151,15 @@ namespace MWGui
void LoadingScreen::changeWallpaper () void LoadingScreen::changeWallpaper ()
{ {
if (mResources.empty()) if (!mSplashScreens.empty())
{ {
Ogre::StringVector groups = Ogre::ResourceGroupManager::getSingleton().getResourceGroups (); std::string const & randomSplash = mSplashScreens.at(Misc::Rng::rollDice(mSplashScreens.size()));
for (Ogre::StringVector::iterator it = groups.begin(); it != groups.end(); ++it)
{
Ogre::StringVectorPtr resourcesInThisGroup = Ogre::ResourceGroupManager::getSingleton ().findResourceNames (*it, "Splash/*.tga");
mResources.insert(mResources.end(), resourcesInThisGroup->begin(), resourcesInThisGroup->end());
}
}
if (!mResources.empty())
{
std::string const & randomSplash = mResources.at(Misc::Rng::rollDice(mResources.size()));
Ogre::TextureManager::getSingleton ().load (randomSplash, Ogre::ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME);
// TODO: add option (filename pattern?) to use image aspect ratio instead of 4:3 // TODO: add option (filename pattern?) to use image aspect ratio instead of 4:3
// we can't do this by default, because the Morrowind splash screens are 1024x1024, but should be displayed as 4:3 // we can't do this by default, because the Morrowind splash screens are 1024x1024, but should be displayed as 4:3
bool stretch = Settings::Manager::getBool("stretch menu background", "GUI"); bool stretch = Settings::Manager::getBool("stretch menu background", "GUI");
mBackgroundImage->setBackgroundImage(randomSplash, true, stretch); mBackgroundImage->setBackgroundImage(randomSplash, true, stretch);
} }
else
std::cerr << "No loading screens found!" << std::endl;
} }
void LoadingScreen::setProgressRange (size_t range) void LoadingScreen::setProgressRange (size_t range)
@ -190,7 +191,7 @@ namespace MWGui
void LoadingScreen::indicateProgress() void LoadingScreen::indicateProgress()
{ {
float time = (mTimer.getMilliseconds() % 2001) / 1000.f; float time = (static_cast<int>(mTimer.time_m()) % 2001) / 1000.f;
if (time > 1) if (time > 1)
time = (time-2)*-1; time = (time-2)*-1;
@ -203,43 +204,32 @@ namespace MWGui
{ {
const float loadingScreenFps = 20.f; const float loadingScreenFps = 20.f;
if (mTimer.getMilliseconds () > mLastRenderTime + (1.f/loadingScreenFps) * 1000.f) if (mTimer.time_m() > mLastRenderTime + (1.f/loadingScreenFps) * 1000.f)
{ {
mLastRenderTime = mTimer.getMilliseconds (); mLastRenderTime = mTimer.time_m();
bool showWallpaper = (MWBase::Environment::get().getStateManager()->getState() bool showWallpaper = (MWBase::Environment::get().getStateManager()->getState()
== MWBase::StateManager::State_NoGame); == MWBase::StateManager::State_NoGame);
if (showWallpaper && mTimer.getMilliseconds () > mLastWallpaperChangeTime + 5000*1) if (showWallpaper && mTimer.time_m() > mLastWallpaperChangeTime + 5000*1)
{ {
mLastWallpaperChangeTime = mTimer.getMilliseconds (); mLastWallpaperChangeTime = mTimer.time_m();
changeWallpaper(); changeWallpaper();
} }
// Turn off rendering except the GUI // Turn off rendering except the GUI
mSceneMgr->clearSpecialCaseRenderQueues(); int oldUpdateMask = mViewer->getUpdateVisitor()->getTraversalMask();
// SCRQM_INCLUDE with RENDER_QUEUE_OVERLAY does not work. int oldCullMask = mViewer->getCamera()->getCullMask();
for (int i = 0; i < Ogre::RENDER_QUEUE_MAX; ++i) mViewer->getUpdateVisitor()->setTraversalMask(MWRender::Mask_GUI);
{ mViewer->getCamera()->setCullMask(MWRender::Mask_GUI);
if (i > 0 && i < 96)
mSceneMgr->addSpecialCaseRenderQueue(i);
}
mSceneMgr->setSpecialCaseRenderQueueMode(Ogre::SceneManager::SCRQM_EXCLUDE);
MWBase::Environment::get().getInputManager()->update(0, true, true); //MWBase::Environment::get().getInputManager()->update(0, true, true);
// First, swap buffers from last draw, then, queue an update of the mViewer->frame();
// window contents, but don't swap buffers (which would have
// caused a sync / flush and would be expensive).
// We're doing this so we can do some actual loading while the GPU is busy with the render.
// This means the render is lagging a frame behind, but this is hardly noticable.
mWindow->swapBuffers();
mWindow->update(false);
// resume 3d rendering // resume 3d rendering
mSceneMgr->clearSpecialCaseRenderQueues(); mViewer->getUpdateVisitor()->setTraversalMask(oldUpdateMask);
mSceneMgr->setSpecialCaseRenderQueueMode(Ogre::SceneManager::SCRQM_EXCLUDE); mViewer->getCamera()->setCullMask(oldCullMask);
} }
} }
} }

View file

@ -1,16 +1,20 @@
#ifndef MWGUI_LOADINGSCREEN_H #ifndef MWGUI_LOADINGSCREEN_H
#define MWGUI_LOADINGSCREEN_H #define MWGUI_LOADINGSCREEN_H
#include <OgreTimer.h> #include <osg/Timer>
#include <OgreStringVector.h> #include <osg/ref_ptr>
#include "windowbase.hpp" #include "windowbase.hpp"
#include <components/loadinglistener/loadinglistener.hpp> #include <components/loadinglistener/loadinglistener.hpp>
namespace Ogre namespace osgViewer
{ {
class SceneManager; class Viewer;
}
namespace VFS
{
class Manager;
} }
namespace MWGui namespace MWGui
@ -20,6 +24,9 @@ namespace MWGui
class LoadingScreen : public WindowBase, public Loading::Listener class LoadingScreen : public WindowBase, public Loading::Listener
{ {
public: public:
LoadingScreen(const VFS::Manager* vfs, osgViewer::Viewer* viewer);
virtual ~LoadingScreen();
virtual void setLabel (const std::string& label); virtual void setLabel (const std::string& label);
/// Indicate that some progress has been made, without specifying how much /// Indicate that some progress has been made, without specifying how much
@ -34,21 +41,18 @@ namespace MWGui
virtual void setVisible(bool visible); virtual void setVisible(bool visible);
LoadingScreen(Ogre::SceneManager* sceneMgr, Ogre::RenderWindow* rw);
virtual ~LoadingScreen();
void setLoadingProgress (const std::string& stage, int depth, int current, int total); void setLoadingProgress (const std::string& stage, int depth, int current, int total);
void loadingDone(); void loadingDone();
void updateWindow(Ogre::RenderWindow* rw) { mWindow = rw; }
private: private:
Ogre::SceneManager* mSceneMgr; void findSplashScreens();
Ogre::RenderWindow* mWindow;
const VFS::Manager* mVFS;
osg::ref_ptr<osgViewer::Viewer> mViewer;
unsigned long mLastWallpaperChangeTime; unsigned long mLastWallpaperChangeTime;
unsigned long mLastRenderTime; unsigned long mLastRenderTime;
Ogre::Timer mTimer; osg::Timer mTimer;
size_t mProgress; size_t mProgress;
@ -58,7 +62,7 @@ namespace MWGui
MyGUI::ScrollBar* mProgressBar; MyGUI::ScrollBar* mProgressBar;
BackgroundImage* mBackgroundImage; BackgroundImage* mBackgroundImage;
Ogre::StringVector mResources; std::vector<std::string> mSplashScreens;
bool mVSyncWasEnabled; bool mVSyncWasEnabled;

View file

@ -213,9 +213,9 @@ namespace MWGui
MyGUI::FactoryManager::getInstance().registerFactory<ResourceImageSetPointerFix>("Resource", "ResourceImageSetPointer"); MyGUI::FactoryManager::getInstance().registerFactory<ResourceImageSetPointerFix>("Resource", "ResourceImageSetPointer");
MyGUI::ResourceManager::getInstance().load("core.xml"); MyGUI::ResourceManager::getInstance().load("core.xml");
#if 0
mLoadingScreen = new LoadingScreen(mRendering->getScene (), mRendering->getWindow ()); mLoadingScreen = new LoadingScreen(mResourceSystem->getVFS(), mViewer);
#endif
//set up the hardware cursor manager //set up the hardware cursor manager
//mCursorManager = new SFO::SDLCursorManager(); //mCursorManager = new SFO::SDLCursorManager();
@ -1173,8 +1173,8 @@ namespace MWGui
if (!mGuiModes.empty()) if (!mGuiModes.empty())
mGuiModes.pop_back(); mGuiModes.pop_back();
bool gameMode = !isGuiMode(); //bool gameMode = !isGuiMode();
MWBase::Environment::get().getInputManager()->changeInputMode(!gameMode); //MWBase::Environment::get().getInputManager()->changeInputMode(!gameMode);
updateVisible(); updateVisible();
} }
@ -1190,8 +1190,8 @@ namespace MWGui
++it; ++it;
} }
bool gameMode = !isGuiMode(); //bool gameMode = !isGuiMode();
MWBase::Environment::get().getInputManager()->changeInputMode(!gameMode); //MWBase::Environment::get().getInputManager()->changeInputMode(!gameMode);
updateVisible(); updateVisible();
} }
@ -1541,22 +1541,9 @@ namespace MWGui
mHud->setEnemy(enemy); mHud->setEnemy(enemy);
} }
class DummyListener : public Loading::Listener
{
public:
virtual void setLabel (const std::string& label){}
virtual void loadingOn(){}
virtual void loadingOff(){}
virtual void indicateProgress (){}
virtual void setProgressRange (size_t range){}
virtual void setProgress (size_t value){}
virtual void increaseProgress (size_t increase = 1){}
};
Loading::Listener* WindowManager::getLoadingScreen() Loading::Listener* WindowManager::getLoadingScreen()
{ {
static DummyListener listener; return mLoadingScreen;
return &listener;
} }
void WindowManager::startRecharge(MWWorld::Ptr soulgem) void WindowManager::startRecharge(MWWorld::Ptr soulgem)