Refactored loading screen

- Add loading progress for data files, global map, terrain
 - Refactored and improved cell loading progress
This commit is contained in:
scrawl 2013-08-27 15:48:13 +02:00
parent fb7273e14a
commit d3d6dfbde8
31 changed files with 551 additions and 387 deletions

View file

@ -123,6 +123,7 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt)
MWBase::Environment::get().getWindowManager()->wmUpdateFps(window->getLastFPS(), tri, batch); MWBase::Environment::get().getWindowManager()->wmUpdateFps(window->getLastFPS(), tri, batch);
MWBase::Environment::get().getWindowManager()->onFrame(frametime); MWBase::Environment::get().getWindowManager()->onFrame(frametime);
MWBase::Environment::get().getWindowManager()->update();
} }
catch (const std::exception& e) catch (const std::exception& e)
{ {
@ -385,26 +386,39 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
loadBSA(); loadBSA();
// Create input and UI first to set up a bootstrapping environment for
// showing a loading screen and keeping the window responsive while doing so
std::string keybinderUser = (mCfgMgr.getUserPath() / "input.xml").string();
bool keybinderUserExists = boost::filesystem::exists(keybinderUser);
MWInput::InputManager* input = new MWInput::InputManager (*mOgre, *this, keybinderUser, keybinderUserExists);
mEnvironment.setInputManager (input);
MWGui::WindowManager* window = new MWGui::WindowManager(
mExtensions, mFpsLevel, mOgre, mCfgMgr.getLogPath().string() + std::string("/"),
mCfgMgr.getCachePath ().string(), mScriptConsoleMode, mTranslationDataStorage, mEncoding);
mEnvironment.setWindowManager (window);
if (mNewGame)
mEnvironment.getWindowManager()->setNewGame(true);
// Create the world // Create the world
mEnvironment.setWorld( new MWWorld::World (*mOgre, mFileCollections, mMaster, mPlugins, mEnvironment.setWorld( new MWWorld::World (*mOgre, mFileCollections, mMaster, mPlugins,
mResDir, mCfgMgr.getCachePath(), mEncoder, mFallbackMap, mResDir, mCfgMgr.getCachePath(), mEncoder, mFallbackMap,
mActivationDistanceOverride)); mActivationDistanceOverride));
MWBase::Environment::get().getWorld()->setupPlayer(); MWBase::Environment::get().getWorld()->setupPlayer();
input->setPlayer(&mEnvironment.getWorld()->getPlayer());
window->initUI();
window->renderWorldMap();
//Load translation data //Load translation data
mTranslationDataStorage.setEncoder(mEncoder); mTranslationDataStorage.setEncoder(mEncoder);
for (size_t i = 0; i < mMaster.size(); i++) for (size_t i = 0; i < mMaster.size(); i++)
mTranslationDataStorage.loadTranslationData(mFileCollections, mMaster[i]); mTranslationDataStorage.loadTranslationData(mFileCollections, mMaster[i]);
// Create window manager - this manages all the MW-specific GUI windows
Compiler::registerExtensions (mExtensions); Compiler::registerExtensions (mExtensions);
mEnvironment.setWindowManager (new MWGui::WindowManager(
mExtensions, mFpsLevel, mOgre, mCfgMgr.getLogPath().string() + std::string("/"),
mCfgMgr.getCachePath ().string(), mScriptConsoleMode, mTranslationDataStorage, mEncoding));
if (mNewGame)
mEnvironment.getWindowManager()->setNewGame(true);
// Create sound system // Create sound system
mEnvironment.setSoundManager (new MWSound::SoundManager(mUseSound)); mEnvironment.setSoundManager (new MWSound::SoundManager(mUseSound));
@ -422,16 +436,6 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
mEnvironment.setJournal (new MWDialogue::Journal); mEnvironment.setJournal (new MWDialogue::Journal);
mEnvironment.setDialogueManager (new MWDialogue::DialogueManager (mExtensions, mVerboseScripts, mTranslationDataStorage)); mEnvironment.setDialogueManager (new MWDialogue::DialogueManager (mExtensions, mVerboseScripts, mTranslationDataStorage));
// Sets up the input system
// Get the path for the keybinder xml file
std::string keybinderUser = (mCfgMgr.getUserPath() / "input.xml").string();
bool keybinderUserExists = boost::filesystem::exists(keybinderUser);
mEnvironment.setInputManager (new MWInput::InputManager (*mOgre,
MWBase::Environment::get().getWorld()->getPlayer(),
*MWBase::Environment::get().getWindowManager(), *this, keybinderUser, keybinderUserExists));
mEnvironment.getWorld()->renderPlayer(); mEnvironment.getWorld()->renderPlayer();
if (!mNewGame) if (!mNewGame)

View file

@ -9,6 +9,8 @@
#include <components/translation/translation.hpp> #include <components/translation/translation.hpp>
#include <components/loadinglistener/loadinglistener.hpp>
#include "../mwmechanics/stat.hpp" #include "../mwmechanics/stat.hpp"
#include "../mwgui/mode.hpp" #include "../mwgui/mode.hpp"
@ -253,9 +255,6 @@ namespace MWBase
virtual void executeInConsole (const std::string& path) = 0; virtual void executeInConsole (const std::string& path) = 0;
virtual void setLoadingProgress (const std::string& stage, int depth, int current, int total) = 0;
virtual void loadingDone() = 0;
virtual void enableRest() = 0; virtual void enableRest() = 0;
virtual bool getRestEnabled() = 0; virtual bool getRestEnabled() = 0;
virtual bool getJournalAllowed() = 0; virtual bool getJournalAllowed() = 0;
@ -282,6 +281,8 @@ namespace MWBase
virtual const Translation::Storage& getTranslationDataStorage() const = 0; virtual const Translation::Storage& getTranslationDataStorage() const = 0;
virtual void setKeyFocusWidget (MyGUI::Widget* widget) = 0; virtual void setKeyFocusWidget (MyGUI::Widget* widget) = 0;
virtual Loading::Listener* getLoadingScreen() = 0;
}; };
} }

View file

@ -19,20 +19,16 @@ namespace MWGui
: mSceneMgr(sceneMgr) : mSceneMgr(sceneMgr)
, mWindow(rw) , mWindow(rw)
, WindowBase("openmw_loading_screen.layout") , WindowBase("openmw_loading_screen.layout")
, mLoadingOn(false)
, mLastRenderTime(0.f) , mLastRenderTime(0.f)
, mLastWallpaperChangeTime(0.f) , mLastWallpaperChangeTime(0.f)
, mFirstLoad(true) , mFirstLoad(true)
, mTotalRefsLoading(0) , mProgress(0)
, mCurrentCellLoading(0)
, mTotalCellsLoading(0)
, mCurrentRefLoading(0)
, mCurrentRefList(0)
{ {
getWidget(mLoadingText, "LoadingText"); getWidget(mLoadingText, "LoadingText");
getWidget(mProgressBar, "ProgressBar"); getWidget(mProgressBar, "ProgressBar");
getWidget(mBackgroundImage, "BackgroundImage"); getWidget(mBackgroundImage, "BackgroundImage");
mProgressBar->setScrollViewPage(1);
mBackgroundMaterial = Ogre::MaterialManager::getSingleton().create("BackgroundMaterial", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); mBackgroundMaterial = Ogre::MaterialManager::getSingleton().create("BackgroundMaterial", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
mBackgroundMaterial->getTechnique(0)->getPass(0)->setLightingEnabled(false); mBackgroundMaterial->getTechnique(0)->getPass(0)->setLightingEnabled(false);
@ -54,6 +50,11 @@ namespace MWGui
mRectangle->setVisible(false); mRectangle->setVisible(false);
} }
void LoadingScreen::setLabel(const std::string &label)
{
mLoadingText->setCaptionWithReplacing(label);
}
LoadingScreen::~LoadingScreen() LoadingScreen::~LoadingScreen()
{ {
delete mRectangle; delete mRectangle;
@ -64,149 +65,25 @@ namespace MWGui
setCoord(0,0,w,h); setCoord(0,0,w,h);
} }
void LoadingScreen::setLoadingProgress (const std::string& stage, int depth, int current, int total)
{
if (!mLoadingOn)
loadingOn();
const int numRefLists = 20;
if (depth == 0)
{
mCurrentCellLoading = current;
mTotalCellsLoading = total;
mCurrentRefLoading = 0;
mCurrentRefList = 0;
}
else if (depth == 1)
{
mCurrentRefLoading = current;
mTotalRefsLoading = total;
}
assert (mTotalCellsLoading != 0);
float refProgress;
if (mTotalRefsLoading <= 1)
refProgress = 1;
else
refProgress = float(mCurrentRefLoading) / float(mTotalRefsLoading-1);
refProgress += mCurrentRefList;
refProgress /= numRefLists;
assert(refProgress <= 1 && refProgress >= 0);
if (depth == 1 && mCurrentRefLoading == mTotalRefsLoading-1)
++mCurrentRefList;
float progress = (float(mCurrentCellLoading)+refProgress) / float(mTotalCellsLoading);
assert(progress <= 1 && progress >= 0);
mLoadingText->setCaption(stage);
mProgressBar->setProgressPosition (static_cast<size_t>(progress * 1000));
static float loadingScreenFps = 30.f;
if (mTimer.getMilliseconds () > mLastRenderTime + (1.f/loadingScreenFps) * 1000.f)
{
float dt = mTimer.getMilliseconds () - mLastRenderTime;
mLastRenderTime = mTimer.getMilliseconds ();
if (mFirstLoad && mTimer.getMilliseconds () > mLastWallpaperChangeTime + 3000*1)
{
mLastWallpaperChangeTime = mTimer.getMilliseconds ();
changeWallpaper();
}
// Turn off rendering except the GUI
mSceneMgr->clearSpecialCaseRenderQueues();
// SCRQM_INCLUDE with RENDER_QUEUE_OVERLAY does not work.
for (int i = 0; i < Ogre::RENDER_QUEUE_MAX; ++i)
{
if (i > 0 && i < 96)
mSceneMgr->addSpecialCaseRenderQueue(i);
}
mSceneMgr->setSpecialCaseRenderQueueMode(Ogre::SceneManager::SCRQM_EXCLUDE);
// always update input before rendering something, otherwise mygui goes crazy when something was entered in the frame before
// (e.g. when using "coc" console command, it would enter an infinite loop and crash due to overflow)
MWBase::Environment::get().getInputManager()->update(0, true);
Ogre::CompositorChain* chain = Ogre::CompositorManager::getSingleton().getCompositorChain(mWindow->getViewport(0));
bool hasCompositor = chain->getCompositor ("gbufferFinalizer");
if (!hasCompositor)
{
mWindow->getViewport(0)->setClearEveryFrame(false);
}
else
{
if (!mFirstLoad)
{
mBackgroundMaterial->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureName(chain->getCompositor ("gbufferFinalizer")->getTextureInstance ("no_mrt_output", 0)->getName());
mRectangle->setVisible(true);
}
for (unsigned int i = 0; i<chain->getNumCompositors(); ++i)
{
Ogre::CompositorManager::getSingleton().setCompositorEnabled(mWindow->getViewport(0), chain->getCompositor(i)->getCompositor()->getName(), false);
}
}
MWBase::Environment::get().getWorld ()->getFader ()->update (dt);
mWindow->update();
if (!hasCompositor)
mWindow->getViewport(0)->setClearEveryFrame(true);
else
{
for (unsigned int i = 0; i<chain->getNumCompositors(); ++i)
{
Ogre::CompositorManager::getSingleton().setCompositorEnabled(mWindow->getViewport(0), chain->getCompositor(i)->getCompositor()->getName(), true);
}
}
mRectangle->setVisible(false);
// resume 3d rendering
mSceneMgr->clearSpecialCaseRenderQueues();
mSceneMgr->setSpecialCaseRenderQueueMode(Ogre::SceneManager::SCRQM_EXCLUDE);
}
}
void LoadingScreen::loadingDone()
{
loadingOff();
}
void LoadingScreen::loadingOn() void LoadingScreen::loadingOn()
{ {
setVisible(true); setVisible(true);
mLoadingOn = true;
if (mFirstLoad) if (mFirstLoad)
{ {
changeWallpaper(); changeWallpaper();
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_LoadingWallpaper);
} }
else else
{ {
mBackgroundImage->setImageTexture(""); mBackgroundImage->setImageTexture("");
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Loading);
} }
}
MWBase::Environment::get().getWindowManager()->pushGuiMode(mFirstLoad ? GM_LoadingWallpaper : GM_Loading);
}
void LoadingScreen::loadingOff() void LoadingScreen::loadingOff()
{ {
setVisible(false); setVisible(false);
mLoadingOn = false;
mFirstLoad = false;
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Loading); MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Loading);
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_LoadingWallpaper); MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_LoadingWallpaper);
@ -235,4 +112,124 @@ namespace MWGui
else else
std::cerr << "No loading screens found!" << std::endl; std::cerr << "No loading screens found!" << std::endl;
} }
void LoadingScreen::setProgressRange (size_t range)
{
mProgressBar->setScrollRange(range+1);
mProgressBar->setScrollPosition(0);
mProgressBar->setTrackSize(0);
mProgress = 0;
}
void LoadingScreen::setProgress (size_t value)
{
assert(value < mProgressBar->getScrollRange());
if (value - mProgress < mProgressBar->getScrollRange()/100.f)
return;
mProgress = value;
mProgressBar->setScrollPosition(0);
mProgressBar->setTrackSize(value / (float)(mProgressBar->getScrollRange()) * mProgressBar->getLineSize());
draw();
}
void LoadingScreen::increaseProgress (size_t increase)
{
mProgressBar->setScrollPosition(0);
size_t value = mProgress + increase;
mProgress = value;
assert(mProgress < mProgressBar->getScrollRange());
mProgressBar->setTrackSize(value / (float)(mProgressBar->getScrollRange()) * mProgressBar->getLineSize());
draw();
}
void LoadingScreen::indicateProgress()
{
float time = (mTimer.getMilliseconds() % 2001) / 1000.f;
if (time > 1)
time = (time-2)*-1;
mProgressBar->setTrackSize(50);
mProgressBar->setScrollPosition(time * (mProgressBar->getScrollRange()-1));
draw();
}
void LoadingScreen::removeWallpaper()
{
mFirstLoad = false;
}
void LoadingScreen::draw()
{
const float loadingScreenFps = 20.f;
if (mTimer.getMilliseconds () > mLastRenderTime + (1.f/loadingScreenFps) * 1000.f)
{
mLastRenderTime = mTimer.getMilliseconds ();
if (mFirstLoad && mTimer.getMilliseconds () > mLastWallpaperChangeTime + 5000*1)
{
mLastWallpaperChangeTime = mTimer.getMilliseconds ();
changeWallpaper();
}
// Turn off rendering except the GUI
mSceneMgr->clearSpecialCaseRenderQueues();
// SCRQM_INCLUDE with RENDER_QUEUE_OVERLAY does not work.
for (int i = 0; i < Ogre::RENDER_QUEUE_MAX; ++i)
{
if (i > 0 && i < 96)
mSceneMgr->addSpecialCaseRenderQueue(i);
}
mSceneMgr->setSpecialCaseRenderQueueMode(Ogre::SceneManager::SCRQM_EXCLUDE);
MWBase::Environment::get().getInputManager()->update(0, true);
Ogre::CompositorChain* chain = Ogre::CompositorManager::getSingleton().getCompositorChain(mWindow->getViewport(0));
bool hasCompositor = chain->getCompositor ("gbufferFinalizer");
if (!hasCompositor)
{
mWindow->getViewport(0)->setClearEveryFrame(false);
}
else
{
if (!mFirstLoad)
{
mBackgroundMaterial->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureName(chain->getCompositor ("gbufferFinalizer")->getTextureInstance ("no_mrt_output", 0)->getName());
mRectangle->setVisible(true);
}
for (unsigned int i = 0; i<chain->getNumCompositors(); ++i)
{
Ogre::CompositorManager::getSingleton().setCompositorEnabled(mWindow->getViewport(0), chain->getCompositor(i)->getCompositor()->getName(), false);
}
}
// First, swap buffers from last draw, then, queue an update of the
// 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(false); // never Vsync, makes no sense here
mWindow->update(false);
if (!hasCompositor)
mWindow->getViewport(0)->setClearEveryFrame(true);
else
{
for (unsigned int i = 0; i<chain->getNumCompositors(); ++i)
{
Ogre::CompositorManager::getSingleton().setCompositorEnabled(mWindow->getViewport(0), chain->getCompositor(i)->getCompositor()->getName(), true);
}
}
mRectangle->setVisible(false);
// resume 3d rendering
mSceneMgr->clearSpecialCaseRenderQueues();
mSceneMgr->setSpecialCaseRenderQueueMode(Ogre::SceneManager::SCRQM_EXCLUDE);
}
}
} }

View file

@ -5,11 +5,27 @@
#include "windowbase.hpp" #include "windowbase.hpp"
#include <components/loadinglistener/loadinglistener.hpp>
namespace MWGui namespace MWGui
{ {
class LoadingScreen : public WindowBase class LoadingScreen : public WindowBase, public Loading::Listener
{ {
public: public:
virtual void setLabel (const std::string& label);
/// Indicate that some progress has been made, without specifying how much
virtual void indicateProgress ();
virtual void loadingOn();
virtual void loadingOff();
virtual void setProgressRange (size_t range);
virtual void setProgress (size_t value);
virtual void increaseProgress (size_t increase);
virtual void removeWallpaper();
LoadingScreen(Ogre::SceneManager* sceneMgr, Ogre::RenderWindow* rw); LoadingScreen(Ogre::SceneManager* sceneMgr, Ogre::RenderWindow* rw);
virtual ~LoadingScreen(); virtual ~LoadingScreen();
@ -30,27 +46,20 @@ namespace MWGui
unsigned long mLastRenderTime; unsigned long mLastRenderTime;
Ogre::Timer mTimer; Ogre::Timer mTimer;
MyGUI::TextBox* mLoadingText; size_t mProgress;
MyGUI::ProgressBar* mProgressBar;
MyGUI::ImageBox* mBackgroundImage;
int mCurrentCellLoading; MyGUI::TextBox* mLoadingText;
int mTotalCellsLoading; MyGUI::ScrollBar* mProgressBar;
int mCurrentRefLoading; MyGUI::ImageBox* mBackgroundImage;
int mTotalRefsLoading;
int mCurrentRefList;
Ogre::Rectangle2D* mRectangle; Ogre::Rectangle2D* mRectangle;
Ogre::MaterialPtr mBackgroundMaterial; Ogre::MaterialPtr mBackgroundMaterial;
Ogre::StringVector mResources; Ogre::StringVector mResources;
bool mLoadingOn;
void loadingOn();
void loadingOff();
void changeWallpaper(); void changeWallpaper();
void draw();
}; };
} }

View file

@ -260,12 +260,10 @@ namespace MWGui
MapWindow::MapWindow(const std::string& cacheDir) MapWindow::MapWindow(const std::string& cacheDir)
: MWGui::WindowPinnableBase("openmw_map_window.layout") : MWGui::WindowPinnableBase("openmw_map_window.layout")
, mGlobal(false) , mGlobal(false)
, mGlobalMap(0)
{ {
setCoord(500,0,320,300); setCoord(500,0,320,300);
mGlobalMapRender = new MWRender::GlobalMap(cacheDir);
mGlobalMapRender->render();
getWidget(mLocalMap, "LocalMap"); getWidget(mLocalMap, "LocalMap");
getWidget(mGlobalMap, "GlobalMap"); getWidget(mGlobalMap, "GlobalMap");
getWidget(mGlobalMapImage, "GlobalMapImage"); getWidget(mGlobalMapImage, "GlobalMapImage");
@ -273,9 +271,6 @@ namespace MWGui
getWidget(mPlayerArrowLocal, "CompassLocal"); getWidget(mPlayerArrowLocal, "CompassLocal");
getWidget(mPlayerArrowGlobal, "CompassGlobal"); getWidget(mPlayerArrowGlobal, "CompassGlobal");
mGlobalMapImage->setImageTexture("GlobalMap.png");
mGlobalMapOverlay->setImageTexture("GlobalMapOverlay");
mGlobalMap->setVisible (false); mGlobalMap->setVisible (false);
getWidget(mButton, "WorldButton"); getWidget(mButton, "WorldButton");
@ -292,6 +287,14 @@ namespace MWGui
LocalMapBase::init(mLocalMap, mPlayerArrowLocal, this); LocalMapBase::init(mLocalMap, mPlayerArrowLocal, this);
} }
void MapWindow::renderGlobalMap(Loading::Listener* loadingListener)
{
mGlobalMapRender = new MWRender::GlobalMap("");
mGlobalMapRender->render(loadingListener);
mGlobalMapImage->setImageTexture("GlobalMap.png");
mGlobalMapOverlay->setImageTexture("GlobalMapOverlay");
}
MapWindow::~MapWindow() MapWindow::~MapWindow()
{ {
delete mGlobalMapRender; delete mGlobalMapRender;

View file

@ -8,6 +8,11 @@ namespace MWRender
class GlobalMap; class GlobalMap;
} }
namespace Loading
{
class Listener;
}
namespace MWGui namespace MWGui
{ {
class LocalMapBase class LocalMapBase
@ -71,6 +76,8 @@ namespace MWGui
void setCellName(const std::string& cellName); void setCellName(const std::string& cellName);
void renderGlobalMap(Loading::Listener* loadingListener);
void addVisitedLocation(const std::string& name, int x, int y); // adds the marker to the global map void addVisitedLocation(const std::string& name, int x, int y); // adds the marker to the global map
void cellExplored(int x, int y); void cellExplored(int x, int y);

View file

@ -62,6 +62,7 @@ namespace MWGui
const std::string& logpath, const std::string& cacheDir, bool consoleOnlyScripts, const std::string& logpath, const std::string& cacheDir, bool consoleOnlyScripts,
Translation::Storage& translationDataStorage, ToUTF8::FromType encoding) Translation::Storage& translationDataStorage, ToUTF8::FromType encoding)
: mGuiManager(NULL) : mGuiManager(NULL)
, mConsoleOnlyScripts(consoleOnlyScripts)
, mRendering(ogre) , mRendering(ogre)
, mHud(NULL) , mHud(NULL)
, mMap(NULL) , mMap(NULL)
@ -156,7 +157,28 @@ namespace MWGui
MyGUI::LanguageManager::getInstance().eventRequestTag = MyGUI::newDelegate(this, &WindowManager::onRetrieveTag); MyGUI::LanguageManager::getInstance().eventRequestTag = MyGUI::newDelegate(this, &WindowManager::onRetrieveTag);
// Get size info from the Gui object // Get size info from the Gui object
assert(mGui); int w = MyGUI::RenderManager::getInstance().getViewSize().width;
int h = MyGUI::RenderManager::getInstance().getViewSize().height;
mLoadingScreen = new LoadingScreen(mRendering->getScene (), mRendering->getWindow ());
mLoadingScreen->onResChange (w,h);
//set up the hardware cursor manager
mSoftwareCursor = new Cursor();
mCursorManager = new SFO::SDLCursorManager();
MyGUI::PointerManager::getInstance().eventChangeMousePointer += MyGUI::newDelegate(this, &WindowManager::onCursorChange);
MyGUI::InputManager::getInstance().eventChangeKeyFocus += MyGUI::newDelegate(this, &WindowManager::onKeyFocusChanged);
setUseHardwareCursors(mUseHardwareCursors);
onCursorChange(MyGUI::PointerManager::getInstance().getDefaultPointer());
mCursorManager->cursorVisibilityChange(false);
}
void WindowManager::initUI()
{
// Get size info from the Gui object
int w = MyGUI::RenderManager::getInstance().getViewSize().width; int w = MyGUI::RenderManager::getInstance().getViewSize().width;
int h = MyGUI::RenderManager::getInstance().getViewSize().height; int h = MyGUI::RenderManager::getInstance().getViewSize().height;
@ -169,9 +191,9 @@ namespace MWGui
mDragAndDrop->mDragAndDropWidget = dragAndDropWidget; mDragAndDrop->mDragAndDropWidget = dragAndDropWidget;
mMenu = new MainMenu(w,h); mMenu = new MainMenu(w,h);
mMap = new MapWindow(cacheDir); mMap = new MapWindow("");
mStatsWindow = new StatsWindow(); mStatsWindow = new StatsWindow();
mConsole = new Console(w,h, consoleOnlyScripts); mConsole = new Console(w,h, mConsoleOnlyScripts);
mJournal = JournalWindow::create(JournalViewModel::create ()); mJournal = JournalWindow::create(JournalViewModel::create ());
mMessageBoxManager = new MessageBoxManager(); mMessageBoxManager = new MessageBoxManager();
mInventoryWindow = new InventoryWindow(mDragAndDrop); mInventoryWindow = new InventoryWindow(mDragAndDrop);
@ -200,13 +222,8 @@ namespace MWGui
mSoulgemDialog = new SoulgemDialog(mMessageBoxManager); mSoulgemDialog = new SoulgemDialog(mMessageBoxManager);
mCompanionWindow = new CompanionWindow(mDragAndDrop, mMessageBoxManager); mCompanionWindow = new CompanionWindow(mDragAndDrop, mMessageBoxManager);
mLoadingScreen = new LoadingScreen(mRendering->getScene (), mRendering->getWindow ());
mLoadingScreen->onResChange (w,h);
mInputBlocker = mGui->createWidget<MyGUI::Widget>("",0,0,w,h,MyGUI::Align::Default,"Windows",""); mInputBlocker = mGui->createWidget<MyGUI::Widget>("",0,0,w,h,MyGUI::Align::Default,"Windows","");
mSoftwareCursor = new Cursor();
mHud->setVisible(mHudEnabled); mHud->setVisible(mHudEnabled);
mCharGen = new CharacterCreation(); mCharGen = new CharacterCreation();
@ -225,19 +242,15 @@ namespace MWGui
unsetSelectedSpell(); unsetSelectedSpell();
unsetSelectedWeapon(); unsetSelectedWeapon();
//set up the hardware cursor manager
mCursorManager = new SFO::SDLCursorManager();
MyGUI::PointerManager::getInstance().eventChangeMousePointer += MyGUI::newDelegate(this, &WindowManager::onCursorChange);
MyGUI::InputManager::getInstance().eventChangeKeyFocus += MyGUI::newDelegate(this, &WindowManager::onKeyFocusChanged);
setUseHardwareCursors(mUseHardwareCursors);
onCursorChange(MyGUI::PointerManager::getInstance().getDefaultPointer());
mCursorManager->cursorVisibilityChange(false);
// Set up visibility // Set up visibility
updateVisible(); updateVisible();
MWBase::Environment::get().getInputManager()->changeInputMode(false);
}
void WindowManager::renderWorldMap()
{
mMap->renderGlobalMap(mLoadingScreen);
} }
void WindowManager::setNewGame(bool newgame) void WindowManager::setNewGame(bool newgame)
@ -329,6 +342,8 @@ namespace MWGui
void WindowManager::updateVisible() void WindowManager::updateVisible()
{ {
if (!mMap)
return; // UI not created yet
// Start out by hiding everything except the HUD // Start out by hiding everything except the HUD
mMap->setVisible(false); mMap->setVisible(false);
mMenu->setVisible(false); mMenu->setVisible(false);
@ -1148,7 +1163,7 @@ namespace MWGui
bool WindowManager::isGuiMode() const bool WindowManager::isGuiMode() const
{ {
return !mGuiModes.empty() || mMessageBoxManager->isInteractiveMessageBox(); return !mGuiModes.empty() || (mMessageBoxManager && mMessageBoxManager->isInteractiveMessageBox());
} }
bool WindowManager::isConsoleMode() const bool WindowManager::isConsoleMode() const
@ -1211,7 +1226,8 @@ namespace MWGui
void WindowManager::showCrosshair (bool show) void WindowManager::showCrosshair (bool show)
{ {
mHud->setCrosshairVisible (show && mCrosshairEnabled); if (mHud)
mHud->setCrosshairVisible (show && mCrosshairEnabled);
} }
void WindowManager::activateQuickKey (int index) void WindowManager::activateQuickKey (int index)
@ -1230,15 +1246,6 @@ namespace MWGui
mHud->setVisible (mHudEnabled); mHud->setVisible (mHudEnabled);
} }
void WindowManager::setLoadingProgress (const std::string& stage, int depth, int current, int total)
{
mLoadingScreen->setLoadingProgress (stage, depth, current, total);
}
void WindowManager::loadingDone ()
{
mLoadingScreen->loadingDone ();
}
bool WindowManager::getRestEnabled() bool WindowManager::getRestEnabled()
{ {
//Enable rest dialogue if character creation finished //Enable rest dialogue if character creation finished
@ -1345,4 +1352,9 @@ namespace MWGui
mHud->setEnemy(enemy); mHud->setEnemy(enemy);
} }
Loading::Listener* WindowManager::getLoadingScreen()
{
return mLoadingScreen;
}
} }

View file

@ -91,6 +91,11 @@ namespace MWGui
Translation::Storage& translationDataStorage, ToUTF8::FromType encoding); Translation::Storage& translationDataStorage, ToUTF8::FromType encoding);
virtual ~WindowManager(); virtual ~WindowManager();
void initUI();
void renderWorldMap();
virtual Loading::Listener* getLoadingScreen();
/** /**
* Should be called each frame to update windows/gui elements. * Should be called each frame to update windows/gui elements.
* This could mean updating sizes of gui elements or opening * This could mean updating sizes of gui elements or opening
@ -241,9 +246,6 @@ namespace MWGui
virtual void executeInConsole (const std::string& path); virtual void executeInConsole (const std::string& path);
virtual void setLoadingProgress (const std::string& stage, int depth, int current, int total);
virtual void loadingDone();
virtual void enableRest() { mRestAllowed = true; } virtual void enableRest() { mRestAllowed = true; }
virtual bool getRestEnabled(); virtual bool getRestEnabled();
@ -275,6 +277,8 @@ namespace MWGui
void onSoulgemDialogButtonPressed (int button); void onSoulgemDialogButtonPressed (int button);
private: private:
bool mConsoleOnlyScripts;
OEngine::GUI::MyGUIManager *mGuiManager; OEngine::GUI::MyGUIManager *mGuiManager;
OEngine::Render::OgreRenderer *mRendering; OEngine::Render::OgreRenderer *mRendering;
HUD *mHud; HUD *mHud;

View file

@ -86,13 +86,10 @@ namespace
namespace MWInput namespace MWInput
{ {
InputManager::InputManager(OEngine::Render::OgreRenderer &ogre, InputManager::InputManager(OEngine::Render::OgreRenderer &ogre,
MWWorld::Player& player,
MWBase::WindowManager &windows,
OMW::Engine& engine, OMW::Engine& engine,
const std::string& userFile, bool userFileExists) const std::string& userFile, bool userFileExists)
: mOgre(ogre) : mOgre(ogre)
, mPlayer(player) , mPlayer(NULL)
, mWindows(windows)
, mEngine(engine) , mEngine(engine)
, mMouseLookEnabled(true) , mMouseLookEnabled(true)
, mMouseX(ogre.getWindow()->getWidth ()/2.f) , mMouseX(ogre.getWindow()->getWidth ()/2.f)
@ -124,8 +121,6 @@ namespace MWInput
adjustMouseRegion (window->getWidth(), window->getHeight()); adjustMouseRegion (window->getWidth(), window->getHeight());
MyGUI::InputManager::getInstance().injectMouseMove(mMouseX, mMouseY, 0);
loadKeyDefaults(); loadKeyDefaults();
for (int i = 0; i < A_Last; ++i) for (int i = 0; i < A_Last; ++i)
@ -140,8 +135,6 @@ namespace MWInput
mControlSwitch["playermagic"] = true; mControlSwitch["playermagic"] = true;
mControlSwitch["playerviewswitch"] = true; mControlSwitch["playerviewswitch"] = true;
mControlSwitch["vanitymode"] = true; mControlSwitch["vanitymode"] = true;
changeInputMode(false);
} }
InputManager::~InputManager() InputManager::~InputManager()
@ -164,7 +157,7 @@ namespace MWInput
if (action == A_Use) if (action == A_Use)
{ {
MWWorld::Class::get(mPlayer.getPlayer()).getCreatureStats(mPlayer.getPlayer()).setAttackingOrSpell(currentValue); MWWorld::Class::get(mPlayer->getPlayer()).getCreatureStats(mPlayer->getPlayer()).setAttackingOrSpell(currentValue);
if (currentValue == 1) if (currentValue == 1)
{ {
int type = MWMechanics::CreatureStats::AT_Chop; int type = MWMechanics::CreatureStats::AT_Chop;
@ -177,7 +170,7 @@ namespace MWInput
if (forward && !side) if (forward && !side)
type = MWMechanics::CreatureStats::AT_Thrust; type = MWMechanics::CreatureStats::AT_Thrust;
MWWorld::Class::get(mPlayer.getPlayer()).getCreatureStats(mPlayer.getPlayer()).setAttackType(type); MWWorld::Class::get(mPlayer->getPlayer()).getCreatureStats(mPlayer->getPlayer()).setAttackType(type);
} }
} }
@ -204,9 +197,9 @@ namespace MWInput
case A_Activate: case A_Activate:
resetIdleTime(); resetIdleTime();
if (mWindows.isGuiMode()) if (MWBase::Environment::get().getWindowManager()->isGuiMode())
{ {
if (mWindows.getMode() == MWGui::GM_Container) if (MWBase::Environment::get().getWindowManager()->getMode() == MWGui::GM_Container)
toggleContainer (); toggleContainer ();
else else
MWBase::Environment::get().getWindowManager()->activateKeyPressed(); MWBase::Environment::get().getWindowManager()->activateKeyPressed();
@ -266,7 +259,7 @@ namespace MWInput
showQuickKeysMenu(); showQuickKeysMenu();
break; break;
case A_ToggleHUD: case A_ToggleHUD:
mWindows.toggleHud(); MWBase::Environment::get().getWindowManager()->toggleHud();
break; break;
} }
} }
@ -274,8 +267,7 @@ namespace MWInput
void InputManager::update(float dt, bool loading) void InputManager::update(float dt, bool loading)
{ {
// Tell OIS to handle all input events mInputManager->capture(loading);
mInputManager->capture();
// inject some fake mouse movement to force updating MyGUI's widget states // inject some fake mouse movement to force updating MyGUI's widget states
// this shouldn't do any harm since we're moving back to the original position afterwards // this shouldn't do any harm since we're moving back to the original position afterwards
MyGUI::InputManager::getInstance().injectMouseMove( int(mMouseX+1), int(mMouseY+1), mMouseWheel); MyGUI::InputManager::getInstance().injectMouseMove( int(mMouseX+1), int(mMouseY+1), mMouseWheel);
@ -285,18 +277,10 @@ namespace MWInput
if (!loading) if (!loading)
mInputBinder->update(dt); mInputBinder->update(dt);
// Update windows/gui as a result of input events bool main_menu = MWBase::Environment::get().getWindowManager()->containsMode(MWGui::GM_MainMenu);
// For instance this could mean opening a new window/dialog,
// by doing this after the input events are handled we
// ensure that window/gui changes appear quickly while
// avoiding that window/gui changes does not happen in
// event callbacks (which may crash)
mWindows.update();
bool main_menu = mWindows.containsMode(MWGui::GM_MainMenu);
bool was_relative = mInputManager->getMouseRelative(); bool was_relative = mInputManager->getMouseRelative();
bool is_relative = !mWindows.isGuiMode(); bool is_relative = !MWBase::Environment::get().getWindowManager()->isGuiMode();
// don't keep the pointer away from the window edge in gui mode // don't keep the pointer away from the window edge in gui mode
// stop using raw mouse motions and switch to system cursor movements // stop using raw mouse motions and switch to system cursor movements
@ -312,8 +296,11 @@ namespace MWInput
mInputManager->warpMouse(mMouseX, mMouseY); mInputManager->warpMouse(mMouseX, mMouseY);
} }
if (loading)
return;
// Disable movement in Gui mode // Disable movement in Gui mode
if (mWindows.isGuiMode()) return; if (MWBase::Environment::get().getWindowManager()->isGuiMode()) return;
// Configure player movement according to keyboard input. Actual movement will // Configure player movement according to keyboard input. Actual movement will
@ -324,45 +311,45 @@ namespace MWInput
if (actionIsActive(A_MoveLeft)) if (actionIsActive(A_MoveLeft))
{ {
triedToMove = true; triedToMove = true;
mPlayer.setLeftRight (-1); mPlayer->setLeftRight (-1);
} }
else if (actionIsActive(A_MoveRight)) else if (actionIsActive(A_MoveRight))
{ {
triedToMove = true; triedToMove = true;
mPlayer.setLeftRight (1); mPlayer->setLeftRight (1);
} }
if (actionIsActive(A_MoveForward)) if (actionIsActive(A_MoveForward))
{ {
triedToMove = true; triedToMove = true;
mPlayer.setAutoMove (false); mPlayer->setAutoMove (false);
mPlayer.setForwardBackward (1); mPlayer->setForwardBackward (1);
} }
else if (actionIsActive(A_MoveBackward)) else if (actionIsActive(A_MoveBackward))
{ {
triedToMove = true; triedToMove = true;
mPlayer.setAutoMove (false); mPlayer->setAutoMove (false);
mPlayer.setForwardBackward (-1); mPlayer->setForwardBackward (-1);
} }
else if(mPlayer.getAutoMove()) else if(mPlayer->getAutoMove())
{ {
triedToMove = true; triedToMove = true;
mPlayer.setForwardBackward (1); mPlayer->setForwardBackward (1);
} }
mPlayer.setSneak(actionIsActive(A_Sneak)); mPlayer->setSneak(actionIsActive(A_Sneak));
if (actionIsActive(A_Jump) && mControlSwitch["playerjumping"]) if (actionIsActive(A_Jump) && mControlSwitch["playerjumping"])
{ {
mPlayer.setUpDown (1); mPlayer->setUpDown (1);
triedToMove = true; triedToMove = true;
} }
if (mAlwaysRunActive) if (mAlwaysRunActive)
mPlayer.setRunState(!actionIsActive(A_Run)); mPlayer->setRunState(!actionIsActive(A_Run));
else else
mPlayer.setRunState(actionIsActive(A_Run)); mPlayer->setRunState(actionIsActive(A_Run));
// if player tried to start moving, but can't (due to being overencumbered), display a notification. // if player tried to start moving, but can't (due to being overencumbered), display a notification.
if (triedToMove) if (triedToMove)
@ -371,7 +358,7 @@ namespace MWInput
mOverencumberedMessageDelay -= dt; mOverencumberedMessageDelay -= dt;
if (MWWorld::Class::get(player).getEncumbrance(player) >= MWWorld::Class::get(player).getCapacity(player)) if (MWWorld::Class::get(player).getEncumbrance(player) >= MWWorld::Class::get(player).getCapacity(player))
{ {
mPlayer.setAutoMove (false); mPlayer->setAutoMove (false);
if (mOverencumberedMessageDelay <= 0) if (mOverencumberedMessageDelay <= 0)
{ {
MWBase::Environment::get().getWindowManager ()->messageBox("#{sNotifyMessage59}"); MWBase::Environment::get().getWindowManager ()->messageBox("#{sNotifyMessage59}");
@ -425,8 +412,8 @@ namespace MWInput
mGuiCursorEnabled = guiMode; mGuiCursorEnabled = guiMode;
mMouseLookEnabled = !guiMode; mMouseLookEnabled = !guiMode;
if (guiMode) if (guiMode)
mWindows.showCrosshair(false); MWBase::Environment::get().getWindowManager()->showCrosshair(false);
mWindows.setCursorVisible(guiMode); MWBase::Environment::get().getWindowManager()->setCursorVisible(guiMode);
// if not in gui mode, the camera decides whether to show crosshair or not. // if not in gui mode, the camera decides whether to show crosshair or not.
} }
@ -459,13 +446,13 @@ namespace MWInput
} }
/// \note 7 switches at all, if-else is relevant /// \note 7 switches at all, if-else is relevant
if (sw == "playercontrols" && !value) { if (sw == "playercontrols" && !value) {
mPlayer.setLeftRight(0); mPlayer->setLeftRight(0);
mPlayer.setForwardBackward(0); mPlayer->setForwardBackward(0);
mPlayer.setAutoMove(false); mPlayer->setAutoMove(false);
mPlayer.setUpDown(0); mPlayer->setUpDown(0);
} else if (sw == "playerjumping" && !value) { } else if (sw == "playerjumping" && !value) {
/// \fixme maybe crouching at this time /// \fixme maybe crouching at this time
mPlayer.setUpDown(0); mPlayer->setUpDown(0);
} else if (sw == "vanitymode") { } else if (sw == "vanitymode") {
MWBase::Environment::get().getWorld()->allowVanityMode(value); MWBase::Environment::get().getWorld()->allowVanityMode(value);
} else if (sw == "playerlooking") { } else if (sw == "playerlooking") {
@ -594,8 +581,8 @@ namespace MWInput
// Only actually turn player when we're not in vanity mode // Only actually turn player when we're not in vanity mode
if(!MWBase::Environment::get().getWorld()->vanityRotateCamera(rot)) if(!MWBase::Environment::get().getWorld()->vanityRotateCamera(rot))
{ {
mPlayer.yaw(x/scale); mPlayer->yaw(x/scale);
mPlayer.pitch(-y/scale); mPlayer->pitch(-y/scale);
} }
if (arg.zrel) if (arg.zrel)
@ -627,51 +614,51 @@ namespace MWInput
if (MyGUI::InputManager::getInstance ().isModalAny()) if (MyGUI::InputManager::getInstance ().isModalAny())
return; return;
if (mWindows.isGuiMode () && mWindows.getMode () == MWGui::GM_Video) if (MWBase::Environment::get().getWindowManager()->isGuiMode () && MWBase::Environment::get().getWindowManager()->getMode () == MWGui::GM_Video)
MWBase::Environment::get().getWorld ()->stopVideo (); MWBase::Environment::get().getWorld ()->stopVideo ();
else if (mWindows.containsMode(MWGui::GM_MainMenu)) else if (MWBase::Environment::get().getWindowManager()->containsMode(MWGui::GM_MainMenu))
mWindows.popGuiMode(); MWBase::Environment::get().getWindowManager()->popGuiMode();
else else
mWindows.pushGuiMode (MWGui::GM_MainMenu); MWBase::Environment::get().getWindowManager()->pushGuiMode (MWGui::GM_MainMenu);
} }
void InputManager::toggleSpell() void InputManager::toggleSpell()
{ {
if (mWindows.isGuiMode()) return; if (MWBase::Environment::get().getWindowManager()->isGuiMode()) return;
// Not allowed before the magic window is accessible // Not allowed before the magic window is accessible
if (!mWindows.isAllowed(MWGui::GW_Magic)) if (!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Magic))
return; return;
MWMechanics::DrawState_ state = mPlayer.getDrawState(); MWMechanics::DrawState_ state = mPlayer->getDrawState();
if (state == MWMechanics::DrawState_Weapon || state == MWMechanics::DrawState_Nothing) if (state == MWMechanics::DrawState_Weapon || state == MWMechanics::DrawState_Nothing)
mPlayer.setDrawState(MWMechanics::DrawState_Spell); mPlayer->setDrawState(MWMechanics::DrawState_Spell);
else else
mPlayer.setDrawState(MWMechanics::DrawState_Nothing); mPlayer->setDrawState(MWMechanics::DrawState_Nothing);
} }
void InputManager::toggleWeapon() void InputManager::toggleWeapon()
{ {
if (mWindows.isGuiMode()) return; if (MWBase::Environment::get().getWindowManager()->isGuiMode()) return;
// Not allowed before the inventory window is accessible // Not allowed before the inventory window is accessible
if (!mWindows.isAllowed(MWGui::GW_Inventory)) if (!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory))
return; return;
MWMechanics::DrawState_ state = mPlayer.getDrawState(); MWMechanics::DrawState_ state = mPlayer->getDrawState();
if (state == MWMechanics::DrawState_Spell || state == MWMechanics::DrawState_Nothing) if (state == MWMechanics::DrawState_Spell || state == MWMechanics::DrawState_Nothing)
mPlayer.setDrawState(MWMechanics::DrawState_Weapon); mPlayer->setDrawState(MWMechanics::DrawState_Weapon);
else else
mPlayer.setDrawState(MWMechanics::DrawState_Nothing); mPlayer->setDrawState(MWMechanics::DrawState_Nothing);
} }
void InputManager::rest() void InputManager::rest()
{ {
if (!mWindows.getRestEnabled () || mWindows.isGuiMode ()) if (!MWBase::Environment::get().getWindowManager()->getRestEnabled () || MWBase::Environment::get().getWindowManager()->isGuiMode ())
return; return;
/// \todo check if resting is currently allowed (enemies nearby?) /// \todo check if resting is currently allowed (enemies nearby?)
mWindows.pushGuiMode (MWGui::GM_Rest); MWBase::Environment::get().getWindowManager()->pushGuiMode (MWGui::GM_Rest);
} }
void InputManager::screenshot() void InputManager::screenshot()
@ -679,7 +666,7 @@ namespace MWInput
mEngine.screenshot(); mEngine.screenshot();
std::vector<std::string> empty; std::vector<std::string> empty;
mWindows.messageBox ("Screenshot saved", empty); MWBase::Environment::get().getWindowManager()->messageBox ("Screenshot saved", empty);
} }
void InputManager::toggleInventory() void InputManager::toggleInventory()
@ -688,13 +675,13 @@ namespace MWInput
return; return;
// Toggle between game mode and inventory mode // Toggle between game mode and inventory mode
if(!mWindows.isGuiMode()) if(!MWBase::Environment::get().getWindowManager()->isGuiMode())
mWindows.pushGuiMode(MWGui::GM_Inventory); MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Inventory);
else else
{ {
MWGui::GuiMode mode = mWindows.getMode(); MWGui::GuiMode mode = MWBase::Environment::get().getWindowManager()->getMode();
if(mode == MWGui::GM_Inventory || mode == MWGui::GM_Container) if(mode == MWGui::GM_Inventory || mode == MWGui::GM_Container)
mWindows.popGuiMode(); MWBase::Environment::get().getWindowManager()->popGuiMode();
} }
// .. but don't touch any other mode, except container. // .. but don't touch any other mode, except container.
@ -705,12 +692,12 @@ namespace MWInput
if (MyGUI::InputManager::getInstance ().isModalAny()) if (MyGUI::InputManager::getInstance ().isModalAny())
return; return;
if(mWindows.isGuiMode()) if(MWBase::Environment::get().getWindowManager()->isGuiMode())
{ {
if (mWindows.getMode() == MWGui::GM_Container) if (MWBase::Environment::get().getWindowManager()->getMode() == MWGui::GM_Container)
mWindows.popGuiMode(); MWBase::Environment::get().getWindowManager()->popGuiMode();
else else
mWindows.pushGuiMode(MWGui::GM_Container); MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Container);
} }
} }
@ -722,15 +709,15 @@ namespace MWInput
// Switch to console mode no matter what mode we are currently // Switch to console mode no matter what mode we are currently
// in, except of course if we are already in console mode // in, except of course if we are already in console mode
if (mWindows.isGuiMode()) if (MWBase::Environment::get().getWindowManager()->isGuiMode())
{ {
if (mWindows.getMode() == MWGui::GM_Console) if (MWBase::Environment::get().getWindowManager()->getMode() == MWGui::GM_Console)
mWindows.popGuiMode(); MWBase::Environment::get().getWindowManager()->popGuiMode();
else else
mWindows.pushGuiMode(MWGui::GM_Console); MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Console);
} }
else else
mWindows.pushGuiMode(MWGui::GM_Console); MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Console);
} }
void InputManager::toggleJournal() void InputManager::toggleJournal()
@ -739,31 +726,31 @@ namespace MWInput
return; return;
// Toggle between game mode and journal mode // Toggle between game mode and journal mode
if(!mWindows.isGuiMode() && MWBase::Environment::get().getWindowManager ()->getJournalAllowed()) if(!MWBase::Environment::get().getWindowManager()->isGuiMode() && MWBase::Environment::get().getWindowManager ()->getJournalAllowed())
{ {
MWBase::Environment::get().getSoundManager()->playSound ("book open", 1.0, 1.0); MWBase::Environment::get().getSoundManager()->playSound ("book open", 1.0, 1.0);
mWindows.pushGuiMode(MWGui::GM_Journal); MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Journal);
} }
else if(mWindows.getMode() == MWGui::GM_Journal) else if(MWBase::Environment::get().getWindowManager()->getMode() == MWGui::GM_Journal)
{ {
MWBase::Environment::get().getSoundManager()->playSound ("book close", 1.0, 1.0); MWBase::Environment::get().getSoundManager()->playSound ("book close", 1.0, 1.0);
mWindows.popGuiMode(); MWBase::Environment::get().getWindowManager()->popGuiMode();
} }
// .. but don't touch any other mode. // .. but don't touch any other mode.
} }
void InputManager::quickKey (int index) void InputManager::quickKey (int index)
{ {
if (!mWindows.isGuiMode()) if (!MWBase::Environment::get().getWindowManager()->isGuiMode())
mWindows.activateQuickKey (index); MWBase::Environment::get().getWindowManager()->activateQuickKey (index);
} }
void InputManager::showQuickKeysMenu() void InputManager::showQuickKeysMenu()
{ {
if (!mWindows.isGuiMode ()) if (!MWBase::Environment::get().getWindowManager()->isGuiMode ())
mWindows.pushGuiMode (MWGui::GM_QuickKeysMenu); MWBase::Environment::get().getWindowManager()->pushGuiMode (MWGui::GM_QuickKeysMenu);
else if (mWindows.getMode () == MWGui::GM_QuickKeysMenu) else if (MWBase::Environment::get().getWindowManager()->getMode () == MWGui::GM_QuickKeysMenu)
mWindows.removeGuiMode (MWGui::GM_QuickKeysMenu); MWBase::Environment::get().getWindowManager()->removeGuiMode (MWGui::GM_QuickKeysMenu);
} }
void InputManager::activate() void InputManager::activate()
@ -774,22 +761,22 @@ namespace MWInput
void InputManager::toggleAutoMove() void InputManager::toggleAutoMove()
{ {
if (mWindows.isGuiMode()) return; if (MWBase::Environment::get().getWindowManager()->isGuiMode()) return;
if (mControlSwitch["playercontrols"]) if (mControlSwitch["playercontrols"])
mPlayer.setAutoMove (!mPlayer.getAutoMove()); mPlayer->setAutoMove (!mPlayer->getAutoMove());
} }
void InputManager::toggleWalking() void InputManager::toggleWalking()
{ {
if (mWindows.isGuiMode()) return; if (MWBase::Environment::get().getWindowManager()->isGuiMode()) return;
mAlwaysRunActive = !mAlwaysRunActive; mAlwaysRunActive = !mAlwaysRunActive;
} }
// Exit program now button (which is disabled in GUI mode) // Exit program now button (which is disabled in GUI mode)
void InputManager::exitNow() void InputManager::exitNow()
{ {
if(!mWindows.isGuiMode()) if(!MWBase::Environment::get().getWindowManager()->isGuiMode())
Ogre::Root::getSingleton().queueEndRendering (); Ogre::Root::getSingleton().queueEndRendering ();
} }

View file

@ -60,8 +60,6 @@ namespace MWInput
{ {
public: public:
InputManager(OEngine::Render::OgreRenderer &_ogre, InputManager(OEngine::Render::OgreRenderer &_ogre,
MWWorld::Player&_player,
MWBase::WindowManager &_windows,
OMW::Engine& engine, OMW::Engine& engine,
const std::string& userFile, bool userFileExists); const std::string& userFile, bool userFileExists);
@ -69,6 +67,8 @@ namespace MWInput
virtual void update(float dt, bool loading); virtual void update(float dt, bool loading);
void setPlayer (MWWorld::Player* player) { mPlayer = player; }
virtual void changeInputMode(bool guiMode); virtual void changeInputMode(bool guiMode);
virtual void processChangedSettings(const Settings::CategorySettingVector& changed); virtual void processChangedSettings(const Settings::CategorySettingVector& changed);
@ -125,8 +125,7 @@ namespace MWInput
private: private:
OEngine::Render::OgreRenderer &mOgre; OEngine::Render::OgreRenderer &mOgre;
MWWorld::Player& mPlayer; MWWorld::Player* mPlayer;
MWBase::WindowManager &mWindows;
OMW::Engine& mEngine; OMW::Engine& mEngine;
ICS::InputControlSystem* mInputBinder; ICS::InputControlSystem* mInputBinder;

View file

@ -10,6 +10,8 @@
#include <OgreRoot.h> #include <OgreRoot.h>
#include <OgreHardwarePixelBuffer.h> #include <OgreHardwarePixelBuffer.h>
#include <components/loadinglistener/loadinglistener.hpp>
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp" #include "../mwbase/world.hpp"
@ -28,7 +30,7 @@ namespace MWRender
} }
void GlobalMap::render () void GlobalMap::render (Loading::Listener* loadingListener)
{ {
Ogre::TexturePtr tex; Ogre::TexturePtr tex;
@ -53,6 +55,11 @@ namespace MWRender
mWidth = cellSize*(mMaxX-mMinX+1); mWidth = cellSize*(mMaxX-mMinX+1);
mHeight = cellSize*(mMaxY-mMinY+1); mHeight = cellSize*(mMaxY-mMinY+1);
loadingListener->loadingOn();
loadingListener->setLabel("Creating map");
loadingListener->setProgressRange((mMaxX-mMinX+1) * (mMaxY-mMinY+1));
loadingListener->setProgress(0);
mExploredBuffer.resize((mMaxX-mMinX+1) * (mMaxY-mMinY+1) * 4); mExploredBuffer.resize((mMaxX-mMinX+1) * (mMaxY-mMinY+1) * 4);
//if (!boost::filesystem::exists(mCacheDir + "/GlobalMap.png")) //if (!boost::filesystem::exists(mCacheDir + "/GlobalMap.png"))
@ -147,6 +154,7 @@ namespace MWRender
data[texelY * mWidth * 3 + texelX * 3+2] = b; data[texelY * mWidth * 3 + texelX * 3+2] = b;
} }
} }
loadingListener->increaseProgress(1);
} }
} }
@ -177,6 +185,8 @@ namespace MWRender
memcpy(mOverlayTexture->getBuffer()->lock(Ogre::HardwareBuffer::HBL_DISCARD), &buffer[0], mWidth*mHeight*4); memcpy(mOverlayTexture->getBuffer()->lock(Ogre::HardwareBuffer::HBL_DISCARD), &buffer[0], mWidth*mHeight*4);
mOverlayTexture->getBuffer()->unlock(); mOverlayTexture->getBuffer()->unlock();
loadingListener->loadingOff();
} }
void GlobalMap::worldPosToImageSpace(float x, float z, float& imageX, float& imageY) void GlobalMap::worldPosToImageSpace(float x, float z, float& imageX, float& imageY)

View file

@ -5,6 +5,11 @@
#include <OgreTexture.h> #include <OgreTexture.h>
namespace Loading
{
class Listener;
}
namespace MWRender namespace MWRender
{ {
@ -13,7 +18,7 @@ namespace MWRender
public: public:
GlobalMap(const std::string& cacheDir); GlobalMap(const std::string& cacheDir);
void render(); void render(Loading::Listener* loadingListener);
int getWidth() { return mWidth; } int getWidth() { return mWidth; }
int getHeight() { return mHeight; } int getHeight() { return mHeight; }

View file

@ -82,7 +82,7 @@ RenderingManager::RenderingManager(OEngine::Render::OgreRenderer& _rend, const b
Settings::Manager::setString("shader mode", "General", openGL ? (glES ? "glsles" : "glsl") : "hlsl"); Settings::Manager::setString("shader mode", "General", openGL ? (glES ? "glsles" : "glsl") : "hlsl");
} }
mRendering.createScene("PlayerCam", Settings::Manager::getFloat("field of view", "General"), 5); mRendering.adjustCamera(Settings::Manager::getFloat("field of view", "General"), 5);
mRendering.getWindow()->addListener(this); mRendering.getWindow()->addListener(this);
mRendering.setWindowListener(this); mRendering.setWindowListener(this);
@ -1018,12 +1018,15 @@ void RenderingManager::enableTerrain(bool enable)
{ {
if (!mTerrain) if (!mTerrain)
{ {
mTerrain = new Terrain::Terrain(mRendering.getScene(), new MWRender::TerrainStorage(), RV_Terrain, Loading::Listener* listener = MWBase::Environment::get().getWindowManager()->getLoadingScreen();
Loading::ScopedLoad load(listener);
mTerrain = new Terrain::Terrain(listener, mRendering.getScene(), new MWRender::TerrainStorage(), RV_Terrain,
Settings::Manager::getBool("distant land", "Terrain"), Settings::Manager::getBool("distant land", "Terrain"),
Settings::Manager::getBool("shader", "Terrain")); Settings::Manager::getBool("shader", "Terrain"));
mTerrain->applyMaterials(Settings::Manager::getBool("enabled", "Shadows"), mTerrain->applyMaterials(Settings::Manager::getBool("enabled", "Shadows"),
Settings::Manager::getBool("split", "Shadows")); Settings::Manager::getBool("split", "Shadows"));
mTerrain->update(mRendering.getCamera()->getRealPosition()); mTerrain->update(mRendering.getCamera()->getRealPosition());
mTerrain->setLoadingListener(NULL);
} }
mTerrain->setVisible(true); mTerrain->setVisible(true);
} }

View file

@ -5,6 +5,8 @@
#include <boost/filesystem/operations.hpp> #include <boost/filesystem/operations.hpp>
#include <components/loadinglistener/loadinglistener.hpp>
namespace MWWorld namespace MWWorld
{ {
@ -21,8 +23,10 @@ static bool isCacheableRecord(int id)
return false; return false;
} }
void ESMStore::load(ESM::ESMReader &esm) void ESMStore::load(ESM::ESMReader &esm, Loading::Listener* listener)
{ {
listener->setProgressRange(1000);
std::set<std::string> missing; std::set<std::string> missing;
ESM::Dialogue *dialogue = 0; ESM::Dialogue *dialogue = 0;
@ -109,6 +113,7 @@ void ESMStore::load(ESM::ESMReader &esm)
mIds[id] = n.val; mIds[id] = n.val;
} }
} }
listener->setProgress(esm.getFileOffset() / (float)esm.getFileSize() * 1000);
} }
/* This information isn't needed on screen. But keep the code around /* This information isn't needed on screen. But keep the code around

View file

@ -6,6 +6,11 @@
#include <components/esm/records.hpp> #include <components/esm/records.hpp>
#include "store.hpp" #include "store.hpp"
namespace Loading
{
class Listener;
}
namespace MWWorld namespace MWWorld
{ {
class ESMStore class ESMStore
@ -158,7 +163,7 @@ namespace MWWorld
mNpcs.insert(mPlayerTemplate); mNpcs.insert(mPlayerTemplate);
} }
void load(ESM::ESMReader &esm); void load(ESM::ESMReader &esm, Loading::Listener* listener);
template <class T> template <class T>
const Store<T> &get() const { const Store<T> &get() const {

View file

@ -25,13 +25,12 @@ namespace
template<typename T> template<typename T>
void insertCellRefList(MWRender::RenderingManager& rendering, void insertCellRefList(MWRender::RenderingManager& rendering,
T& cellRefList, MWWorld::CellStore &cell, MWWorld::PhysicsSystem& physics, bool rescale) T& cellRefList, MWWorld::CellStore &cell, MWWorld::PhysicsSystem& physics, bool rescale, Loading::Listener* loadingListener)
{ {
if (!cellRefList.mList.empty()) if (!cellRefList.mList.empty())
{ {
const MWWorld::Class& class_ = const MWWorld::Class& class_ =
MWWorld::Class::get (MWWorld::Ptr (&*cellRefList.mList.begin(), &cell)); MWWorld::Class::get (MWWorld::Ptr (&*cellRefList.mList.begin(), &cell));
int current = 0;
for (typename T::List::iterator it = cellRefList.mList.begin(); for (typename T::List::iterator it = cellRefList.mList.begin();
it != cellRefList.mList.end(); it++) it != cellRefList.mList.end(); it++)
{ {
@ -43,8 +42,6 @@ namespace
it->mRef.mScale = 2; it->mRef.mScale = 2;
} }
++current;
if (it->mData.getCount() && it->mData.isEnabled()) if (it->mData.getCount() && it->mData.isEnabled())
{ {
MWWorld::Ptr ptr (&*it, &cell); MWWorld::Ptr ptr (&*it, &cell);
@ -68,6 +65,8 @@ namespace
std::cerr << error + e.what() << std::endl; std::cerr << error + e.what() << std::endl;
} }
} }
loadingListener->increaseProgress(1);
} }
} }
} }
@ -117,7 +116,7 @@ namespace MWWorld
mActiveCells.erase(*iter); mActiveCells.erase(*iter);
} }
void Scene::loadCell (Ptr::CellStore *cell) void Scene::loadCell (Ptr::CellStore *cell, Loading::Listener* loadingListener)
{ {
// register local scripts // register local scripts
MWBase::Environment::get().getWorld()->getLocalScripts().addCell (cell); MWBase::Environment::get().getWorld()->getLocalScripts().addCell (cell);
@ -150,7 +149,7 @@ namespace MWWorld
// ... then references. This is important for adjustPosition to work correctly. // ... then references. This is important for adjustPosition to work correctly.
/// \todo rescale depending on the state of a new GMST /// \todo rescale depending on the state of a new GMST
insertCell (*cell, true); insertCell (*cell, true, loadingListener);
mRendering.cellAdded (cell); mRendering.cellAdded (cell);
@ -200,17 +199,15 @@ namespace MWWorld
void Scene::changeCell (int X, int Y, const ESM::Position& position, bool adjustPlayerPos) void Scene::changeCell (int X, int Y, const ESM::Position& position, bool adjustPlayerPos)
{ {
Nif::NIFFile::CacheLock cachelock; Nif::NIFFile::CacheLock cachelock;
const MWWorld::Store<ESM::GameSetting> &gmst =
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
mRendering.preCellChange(mCurrentCell); Loading::Listener* loadingListener = MWBase::Environment::get().getWindowManager()->getLoadingScreen();
Loading::ScopedLoad load(loadingListener);
// remove active // remove active
MWBase::Environment::get().getMechanicsManager()->remove(MWBase::Environment::get().getWorld()->getPlayer().getPlayer()); MWBase::Environment::get().getMechanicsManager()->remove(MWBase::Environment::get().getWorld()->getPlayer().getPlayer());
std::string loadingExteriorText; std::string loadingExteriorText = "#{sLoadingMessage3}";
loadingListener->setLabel(loadingExteriorText);
loadingExteriorText = gmst.find ("sLoadingMessage3")->getString();
CellStoreCollection::iterator active = mActiveCells.begin(); CellStoreCollection::iterator active = mActiveCells.begin();
@ -232,7 +229,6 @@ namespace MWWorld
++numUnload; ++numUnload;
} }
int current = 0;
active = mActiveCells.begin(); active = mActiveCells.begin();
while (active!=mActiveCells.end()) while (active!=mActiveCells.end())
{ {
@ -247,11 +243,10 @@ namespace MWWorld
} }
} }
unloadCell (active++); unloadCell (active++);
++current;
} }
int numLoad = 0; int refsToLoad = 0;
// get the number of cells to load // get the number of refs to load
for (int x=X-1; x<=X+1; ++x) for (int x=X-1; x<=X+1; ++x)
for (int y=Y-1; y<=Y+1; ++y) for (int y=Y-1; y<=Y+1; ++y)
{ {
@ -269,11 +264,12 @@ namespace MWWorld
} }
if (iter==mActiveCells.end()) if (iter==mActiveCells.end())
++numLoad; refsToLoad += countRefs(*MWBase::Environment::get().getWorld()->getExterior(x, y));
} }
loadingListener->setProgressRange(refsToLoad);
// Load cells // Load cells
current = 0;
for (int x=X-1; x<=X+1; ++x) for (int x=X-1; x<=X+1; ++x)
for (int y=Y-1; y<=Y+1; ++y) for (int y=Y-1; y<=Y+1; ++y)
{ {
@ -294,11 +290,7 @@ namespace MWWorld
{ {
CellStore *cell = MWBase::Environment::get().getWorld()->getExterior(x, y); CellStore *cell = MWBase::Environment::get().getWorld()->getExterior(x, y);
//Loading Exterior loading text loadCell (cell, loadingListener);
MWBase::Environment::get().getWindowManager ()->setLoadingProgress (loadingExteriorText, 0, current, numLoad);
loadCell (cell);
++current;
} }
} }
@ -330,7 +322,7 @@ namespace MWWorld
mCellChanged = true; mCellChanged = true;
MWBase::Environment::get().getWindowManager ()->loadingDone (); loadingListener->removeWallpaper();
} }
//We need the ogre renderer and a scene node. //We need the ogre renderer and a scene node.
@ -356,13 +348,14 @@ namespace MWWorld
void Scene::changeToInteriorCell (const std::string& cellName, const ESM::Position& position) void Scene::changeToInteriorCell (const std::string& cellName, const ESM::Position& position)
{ {
MWBase::Environment::get().getWorld ()->getFader ()->fadeOut(0.5); MWBase::Environment::get().getWorld ()->getFader ()->fadeOut(0.5);
const MWWorld::Store<ESM::GameSetting> &gmst =
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
mRendering.enableTerrain(false); mRendering.enableTerrain(false);
std::string loadingInteriorText; Loading::Listener* loadingListener = MWBase::Environment::get().getWindowManager()->getLoadingScreen();
loadingInteriorText = gmst.find ("sLoadingMessage2")->getString(); Loading::ScopedLoad load(loadingListener);
std::string loadingInteriorText = "#{sLoadingMessage2}";
loadingListener->setLabel(loadingInteriorText);
CellStore *cell = MWBase::Environment::get().getWorld()->getInterior(cellName); CellStore *cell = MWBase::Environment::get().getWorld()->getInterior(cellName);
bool loadcell = (mCurrentCell == NULL); bool loadcell = (mCurrentCell == NULL);
@ -406,13 +399,15 @@ namespace MWWorld
++current; ++current;
} }
int refsToLoad = countRefs(*cell);
loadingListener->setProgressRange(refsToLoad);
// Load cell. // Load cell.
std::cout << "cellName: " << cell->mCell->mName << std::endl; std::cout << "cellName: " << cell->mCell->mName << std::endl;
//Loading Interior loading text //Loading Interior loading text
MWBase::Environment::get().getWindowManager ()->setLoadingProgress (loadingInteriorText, 0, 0, 1);
loadCell (cell); loadCell (cell, loadingListener);
mCurrentCell = cell; mCurrentCell = cell;
@ -429,7 +424,7 @@ namespace MWWorld
mCellChanged = true; mCellChanged = true;
MWBase::Environment::get().getWorld ()->getFader ()->fadeIn(0.5); MWBase::Environment::get().getWorld ()->getFader ()->fadeIn(0.5);
MWBase::Environment::get().getWindowManager ()->loadingDone (); loadingListener->removeWallpaper();
} }
void Scene::changeToExteriorCell (const ESM::Position& position) void Scene::changeToExteriorCell (const ESM::Position& position)
@ -454,30 +449,54 @@ namespace MWWorld
mCellChanged = false; mCellChanged = false;
} }
void Scene::insertCell (Ptr::CellStore &cell, bool rescale) int Scene::countRefs (const Ptr::CellStore& cell)
{
return cell.mActivators.mList.size()
+ cell.mPotions.mList.size()
+ cell.mAppas.mList.size()
+ cell.mArmors.mList.size()
+ cell.mBooks.mList.size()
+ cell.mClothes.mList.size()
+ cell.mContainers.mList.size()
+ cell.mDoors.mList.size()
+ cell.mIngreds.mList.size()
+ cell.mCreatureLists.mList.size()
+ cell.mItemLists.mList.size()
+ cell.mLights.mList.size()
+ cell.mLockpicks.mList.size()
+ cell.mMiscItems.mList.size()
+ cell.mProbes.mList.size()
+ cell.mRepairs.mList.size()
+ cell.mStatics.mList.size()
+ cell.mWeapons.mList.size()
+ cell.mCreatures.mList.size()
+ cell.mNpcs.mList.size();
}
void Scene::insertCell (Ptr::CellStore &cell, bool rescale, Loading::Listener* loadingListener)
{ {
// Loop through all references in the cell // Loop through all references in the cell
insertCellRefList(mRendering, cell.mActivators, cell, *mPhysics, rescale); insertCellRefList(mRendering, cell.mActivators, cell, *mPhysics, rescale, loadingListener);
insertCellRefList(mRendering, cell.mPotions, cell, *mPhysics, rescale); insertCellRefList(mRendering, cell.mPotions, cell, *mPhysics, rescale, loadingListener);
insertCellRefList(mRendering, cell.mAppas, cell, *mPhysics, rescale); insertCellRefList(mRendering, cell.mAppas, cell, *mPhysics, rescale, loadingListener);
insertCellRefList(mRendering, cell.mArmors, cell, *mPhysics, rescale); insertCellRefList(mRendering, cell.mArmors, cell, *mPhysics, rescale, loadingListener);
insertCellRefList(mRendering, cell.mBooks, cell, *mPhysics, rescale); insertCellRefList(mRendering, cell.mBooks, cell, *mPhysics, rescale, loadingListener);
insertCellRefList(mRendering, cell.mClothes, cell, *mPhysics, rescale); insertCellRefList(mRendering, cell.mClothes, cell, *mPhysics, rescale, loadingListener);
insertCellRefList(mRendering, cell.mContainers, cell, *mPhysics, rescale); insertCellRefList(mRendering, cell.mContainers, cell, *mPhysics, rescale, loadingListener);
insertCellRefList(mRendering, cell.mDoors, cell, *mPhysics, rescale); insertCellRefList(mRendering, cell.mDoors, cell, *mPhysics, rescale, loadingListener);
insertCellRefList(mRendering, cell.mIngreds, cell, *mPhysics, rescale); insertCellRefList(mRendering, cell.mIngreds, cell, *mPhysics, rescale, loadingListener);
insertCellRefList(mRendering, cell.mCreatureLists, cell, *mPhysics, rescale); insertCellRefList(mRendering, cell.mCreatureLists, cell, *mPhysics, rescale, loadingListener);
insertCellRefList(mRendering, cell.mItemLists, cell, *mPhysics, rescale); insertCellRefList(mRendering, cell.mItemLists, cell, *mPhysics, rescale, loadingListener);
insertCellRefList(mRendering, cell.mLights, cell, *mPhysics, rescale); insertCellRefList(mRendering, cell.mLights, cell, *mPhysics, rescale, loadingListener);
insertCellRefList(mRendering, cell.mLockpicks, cell, *mPhysics, rescale); insertCellRefList(mRendering, cell.mLockpicks, cell, *mPhysics, rescale, loadingListener);
insertCellRefList(mRendering, cell.mMiscItems, cell, *mPhysics, rescale); insertCellRefList(mRendering, cell.mMiscItems, cell, *mPhysics, rescale, loadingListener);
insertCellRefList(mRendering, cell.mProbes, cell, *mPhysics, rescale); insertCellRefList(mRendering, cell.mProbes, cell, *mPhysics, rescale, loadingListener);
insertCellRefList(mRendering, cell.mRepairs, cell, *mPhysics, rescale); insertCellRefList(mRendering, cell.mRepairs, cell, *mPhysics, rescale, loadingListener);
insertCellRefList(mRendering, cell.mStatics, cell, *mPhysics, rescale); insertCellRefList(mRendering, cell.mStatics, cell, *mPhysics, rescale, loadingListener);
insertCellRefList(mRendering, cell.mWeapons, cell, *mPhysics, rescale); insertCellRefList(mRendering, cell.mWeapons, cell, *mPhysics, rescale, loadingListener);
// Load NPCs and creatures _after_ everything else (important for adjustPosition to work correctly) // Load NPCs and creatures _after_ everything else (important for adjustPosition to work correctly)
insertCellRefList(mRendering, cell.mCreatures, cell, *mPhysics, rescale); insertCellRefList(mRendering, cell.mCreatures, cell, *mPhysics, rescale, loadingListener);
insertCellRefList(mRendering, cell.mNpcs, cell, *mPhysics, rescale); insertCellRefList(mRendering, cell.mNpcs, cell, *mPhysics, rescale, loadingListener);
} }
void Scene::addObjectToScene (const Ptr& ptr) void Scene::addObjectToScene (const Ptr& ptr)

View file

@ -56,7 +56,9 @@ namespace MWWorld
void playerCellChange (CellStore *cell, const ESM::Position& position, void playerCellChange (CellStore *cell, const ESM::Position& position,
bool adjustPlayerPos = true); bool adjustPlayerPos = true);
void insertCell (Ptr::CellStore &cell, bool rescale); void insertCell (Ptr::CellStore &cell, bool rescale, Loading::Listener* loadingListener);
int countRefs (const Ptr::CellStore& cell);
public: public:
@ -66,7 +68,7 @@ namespace MWWorld
void unloadCell (CellStoreCollection::iterator iter); void unloadCell (CellStoreCollection::iterator iter);
void loadCell (CellStore *cell); void loadCell (CellStore *cell, Loading::Listener* loadingListener);
void changeCell (int X, int Y, const ESM::Position& position, bool adjustPlayerPos); void changeCell (int X, int Y, const ESM::Position& position, bool adjustPlayerPos);
///< Move from exterior to interior or from interior cell to a different ///< Move from exterior to interior or from interior cell to a different

View file

@ -184,11 +184,14 @@ namespace MWWorld
int idx = 0; int idx = 0;
// NOTE: We might need to reserve one more for the running game / save. // NOTE: We might need to reserve one more for the running game / save.
mEsm.resize(master.size() + plugins.size()); mEsm.resize(master.size() + plugins.size());
Loading::Listener* listener = MWBase::Environment::get().getWindowManager()->getLoadingScreen();
listener->loadingOn();
for (std::vector<std::string>::size_type i = 0; i < master.size(); i++, idx++) for (std::vector<std::string>::size_type i = 0; i < master.size(); i++, idx++)
{ {
boost::filesystem::path masterPath (fileCollections.getCollection (".esm").getPath (master[i])); boost::filesystem::path masterPath (fileCollections.getCollection (".esm").getPath (master[i]));
std::cout << "Loading ESM " << masterPath.string() << "\n"; std::cout << "Loading ESM " << masterPath.string() << "\n";
listener->setLabel(masterPath.filename().string());
// This parses the ESM file // This parses the ESM file
ESM::ESMReader lEsm; ESM::ESMReader lEsm;
@ -197,7 +200,7 @@ namespace MWWorld
lEsm.setGlobalReaderList(&mEsm); lEsm.setGlobalReaderList(&mEsm);
lEsm.open (masterPath.string()); lEsm.open (masterPath.string());
mEsm[idx] = lEsm; mEsm[idx] = lEsm;
mStore.load (mEsm[idx]); mStore.load (mEsm[idx], listener);
} }
for (std::vector<std::string>::size_type i = 0; i < plugins.size(); i++, idx++) for (std::vector<std::string>::size_type i = 0; i < plugins.size(); i++, idx++)
@ -205,6 +208,7 @@ namespace MWWorld
boost::filesystem::path pluginPath (fileCollections.getCollection (".esp").getPath (plugins[i])); boost::filesystem::path pluginPath (fileCollections.getCollection (".esp").getPath (plugins[i]));
std::cout << "Loading ESP " << pluginPath.string() << "\n"; std::cout << "Loading ESP " << pluginPath.string() << "\n";
listener->setLabel(pluginPath.filename().string());
// This parses the ESP file // This parses the ESP file
ESM::ESMReader lEsm; ESM::ESMReader lEsm;
@ -213,8 +217,9 @@ namespace MWWorld
lEsm.setGlobalReaderList(&mEsm); lEsm.setGlobalReaderList(&mEsm);
lEsm.open (pluginPath.string()); lEsm.open (pluginPath.string());
mEsm[idx] = lEsm; mEsm[idx] = lEsm;
mStore.load (mEsm[idx]); mStore.load (mEsm[idx], listener);
} }
listener->loadingOff();
// insert records that may not be present in all versions of MW // insert records that may not be present in all versions of MW
if (mEsm[0].getFormat() == 0) if (mEsm[0].getFormat() == 0)

View file

@ -70,6 +70,10 @@ add_component_dir (terrain
quadtreenode chunk terrain storage material quadtreenode chunk terrain storage material
) )
add_component_dir (loadinglistener
loadinglistener
)
find_package(Qt4 COMPONENTS QtCore QtGui) find_package(Qt4 COMPONENTS QtCore QtGui)
if(QT_QTGUI_LIBRARY AND QT_QTCORE_LIBRARY) if(QT_QTGUI_LIBRARY AND QT_QTCORE_LIBRARY)

View file

@ -70,6 +70,11 @@ public:
void openRaw(const std::string &file); void openRaw(const std::string &file);
/// Get the file size. Make sure that the file has been opened!
size_t getFileSize() { return mEsm->size(); }
/// Get the current position in the file. Make sure that the file has been opened!
size_t getFileOffset() { return mEsm->tell(); }
// This is a quick hack for multiple esm/esp files. Each plugin introduces its own // This is a quick hack for multiple esm/esp files. Each plugin introduces its own
// terrain palette, but ESMReader does not pass a reference to the correct plugin // terrain palette, but ESMReader does not pass a reference to the correct plugin
// to the individual load() methods. This hack allows to pass this reference // to the individual load() methods. This hack allows to pass this reference

View file

@ -0,0 +1,35 @@
#ifndef COMPONENTS_LOADINGLISTENER_H
#define COMPONENTS_LOADINGLISTENER_H
namespace Loading
{
class Listener
{
public:
virtual void setLabel (const std::string& label) = 0;
// Use ScopedLoad instead of using these directly
virtual void loadingOn() = 0;
virtual void loadingOff() = 0;
/// Indicate that some progress has been made, without specifying how much
virtual void indicateProgress () = 0;
virtual void setProgressRange (size_t range) = 0;
virtual void setProgress (size_t value) = 0;
virtual void increaseProgress (size_t increase) = 0;
/// Indicate the scene is now ready to be shown
virtual void removeWallpaper() = 0;
};
// Used for stopping a loading sequence when the object goes out of scope
struct ScopedLoad
{
ScopedLoad(Listener* l) : mListener(l) { mListener->loadingOn(); }
~ScopedLoad() { mListener->loadingOff(); }
Listener* mListener;
};
}
#endif

View file

@ -220,7 +220,7 @@ const Ogre::AxisAlignedBox& QuadTreeNode::getBoundingBox()
return mBounds; return mBounds;
} }
void QuadTreeNode::update(const Ogre::Vector3 &cameraPos) void QuadTreeNode::update(const Ogre::Vector3 &cameraPos, Loading::Listener* loadingListener)
{ {
const Ogre::AxisAlignedBox& bounds = getBoundingBox(); const Ogre::AxisAlignedBox& bounds = getBoundingBox();
if (bounds.isNull()) if (bounds.isNull())
@ -254,6 +254,9 @@ void QuadTreeNode::update(const Ogre::Vector3 &cameraPos)
bool hadChunk = hasChunk(); bool hadChunk = hasChunk();
if (loadingListener)
loadingListener->indicateProgress();
if (!distantLand && dist > 8192*2) if (!distantLand && dist > 8192*2)
{ {
if (mIsActive) if (mIsActive)
@ -341,7 +344,7 @@ void QuadTreeNode::update(const Ogre::Vector3 &cameraPos)
} }
assert(hasChildren() && "Leaf node's LOD needs to be 0"); assert(hasChildren() && "Leaf node's LOD needs to be 0");
for (int i=0; i<4; ++i) for (int i=0; i<4; ++i)
mChildren[i]->update(cameraPos); mChildren[i]->update(cameraPos, loadingListener);
} }
} }

View file

@ -5,6 +5,8 @@
#include <OgreVector2.h> #include <OgreVector2.h>
#include <OgreTexture.h> #include <OgreTexture.h>
#include <components/loadinglistener/loadinglistener.hpp>
namespace Ogre namespace Ogre
{ {
class Rectangle2D; class Rectangle2D;
@ -96,7 +98,7 @@ namespace Terrain
Terrain* getTerrain() { return mTerrain; } Terrain* getTerrain() { return mTerrain; }
/// Adjust LODs for the given camera position, possibly splitting up chunks or merging them. /// Adjust LODs for the given camera position, possibly splitting up chunks or merging them.
void update (const Ogre::Vector3& cameraPos); void update (const Ogre::Vector3& cameraPos, Loading::Listener* loadingListener);
/// Adjust index buffers of chunks to stitch together chunks of different LOD, so that cracks are avoided. /// Adjust index buffers of chunks to stitch together chunks of different LOD, so that cracks are avoided.
/// Call after QuadTreeNode::update! /// Call after QuadTreeNode::update!

View file

@ -7,6 +7,7 @@
#include <OgreRoot.h> #include <OgreRoot.h>
#include <components/esm/loadland.hpp> #include <components/esm/loadland.hpp>
#include <components/loadinglistener/loadinglistener.hpp>
#include "storage.hpp" #include "storage.hpp"
#include "quadtreenode.hpp" #include "quadtreenode.hpp"
@ -51,7 +52,8 @@ namespace
namespace Terrain namespace Terrain
{ {
Terrain::Terrain(Ogre::SceneManager* sceneMgr, Storage* storage, int visibilityFlags, bool distantLand, bool shaders) Terrain::Terrain(Loading::Listener* loadingListener, Ogre::SceneManager* sceneMgr,
Storage* storage, int visibilityFlags, bool distantLand, bool shaders)
: mStorage(storage) : mStorage(storage)
, mMinBatchSize(1) , mMinBatchSize(1)
, mMaxBatchSize(64) , mMaxBatchSize(64)
@ -60,7 +62,10 @@ namespace Terrain
, mDistantLand(distantLand) , mDistantLand(distantLand)
, mShaders(shaders) , mShaders(shaders)
, mVisible(true) , mVisible(true)
, mLoadingListener(loadingListener)
{ {
loadingListener->setLabel("Creating terrain");
mCompositeMapSceneMgr = Ogre::Root::getSingleton().createSceneManager(Ogre::ST_GENERIC); mCompositeMapSceneMgr = Ogre::Root::getSingleton().createSceneManager(Ogre::ST_GENERIC);
Ogre::Camera* compositeMapCam = mCompositeMapSceneMgr->createCamera("a"); Ogre::Camera* compositeMapCam = mCompositeMapSceneMgr->createCamera("a");
@ -86,8 +91,11 @@ namespace Terrain
mRootNode = new QuadTreeNode(this, Root, size, Ogre::Vector2(center.x, center.y), NULL); mRootNode = new QuadTreeNode(this, Root, size, Ogre::Vector2(center.x, center.y), NULL);
buildQuadTree(mRootNode); buildQuadTree(mRootNode);
loadingListener->indicateProgress();
mRootNode->initAabb(); mRootNode->initAabb();
loadingListener->indicateProgress();
mRootNode->initNeighbours(); mRootNode->initNeighbours();
loadingListener->indicateProgress();
} }
Terrain::~Terrain() Terrain::~Terrain()
@ -147,7 +155,7 @@ namespace Terrain
{ {
if (!mVisible) if (!mVisible)
return; return;
mRootNode->update(cameraPos); mRootNode->update(cameraPos, mLoadingListener);
mRootNode->updateIndexBuffers(); mRootNode->updateIndexBuffers();
} }

View file

@ -6,6 +6,11 @@
#include <OgreAxisAlignedBox.h> #include <OgreAxisAlignedBox.h>
#include <OgreTexture.h> #include <OgreTexture.h>
namespace Loading
{
class Listener;
}
namespace Ogre namespace Ogre
{ {
class Camera; class Camera;
@ -28,6 +33,7 @@ namespace Terrain
{ {
public: public:
/// @note takes ownership of \a storage /// @note takes ownership of \a storage
/// @param loadingListener Listener to update with progress
/// @param sceneMgr scene manager to use /// @param sceneMgr scene manager to use
/// @param storage Storage instance to get terrain data from (heights, normals, colors, textures..) /// @param storage Storage instance to get terrain data from (heights, normals, colors, textures..)
/// @param visbilityFlags visibility flags for the created meshes /// @param visbilityFlags visibility flags for the created meshes
@ -35,9 +41,12 @@ namespace Terrain
/// This is a temporary option until it can be streamlined. /// This is a temporary option until it can be streamlined.
/// @param shaders Whether to use splatting shader, or multi-pass fixed function splatting. Shader is usually /// @param shaders Whether to use splatting shader, or multi-pass fixed function splatting. Shader is usually
/// faster so this is just here for compatibility. /// faster so this is just here for compatibility.
Terrain(Ogre::SceneManager* sceneMgr, Storage* storage, int visiblityFlags, bool distantLand, bool shaders); Terrain(Loading::Listener* loadingListener, Ogre::SceneManager* sceneMgr,
Storage* storage, int visiblityFlags, bool distantLand, bool shaders);
~Terrain(); ~Terrain();
void setLoadingListener(Loading::Listener* loadingListener) { mLoadingListener = loadingListener; }
bool getDistantLandEnabled() { return mDistantLand; } bool getDistantLandEnabled() { return mDistantLand; }
bool getShadersEnabled() { return mShaders; } bool getShadersEnabled() { return mShaders; }
bool getShadowsEnabled() { return mShadows; } bool getShadowsEnabled() { return mShadows; }
@ -84,6 +93,8 @@ namespace Terrain
bool mSplitShadows; bool mSplitShadows;
bool mVisible; bool mVisible;
Loading::Listener* mLoadingListener;
QuadTreeNode* mRootNode; QuadTreeNode* mRootNode;
Ogre::SceneNode* mRootSceneNode; Ogre::SceneNode* mRootSceneNode;
Storage* mStorage; Storage* mStorage;

View file

@ -35,9 +35,20 @@ namespace SFO
mSDLWindow = NULL; mSDLWindow = NULL;
} }
void InputWrapper::capture() void InputWrapper::capture(bool windowEventsOnly)
{ {
SDL_PumpEvents();
SDL_Event evt; SDL_Event evt;
if (windowEventsOnly)
{
// During loading, just handle window events, and keep others for later
while (SDL_PeepEvents(&evt, 1, SDL_GETEVENT, SDL_WINDOWEVENT, SDL_WINDOWEVENT))
handleWindowEvent(evt);
return;
}
while(SDL_PollEvent(&evt)) while(SDL_PollEvent(&evt))
{ {
switch(evt.type) switch(evt.type)

View file

@ -24,7 +24,7 @@ namespace SFO
void setWindowEventCallback(WindowListener* listen) { mWindowListener = listen; } void setWindowEventCallback(WindowListener* listen) { mWindowListener = listen; }
void setJoyEventCallback(JoyListener* listen) { mJoyListener = listen; } void setJoyEventCallback(JoyListener* listen) { mJoyListener = listen; }
void capture(); void capture(bool windowEventsOnly);
bool isModifierHeld(SDL_Keymod mod); bool isModifierHeld(SDL_Keymod mod);
bool isKeyDown(SDL_Scancode key); bool isKeyDown(SDL_Scancode key);

View file

@ -12,8 +12,7 @@
<Property key="TextAlign" value="Center"/> <Property key="TextAlign" value="Center"/>
</Widget> </Widget>
<Widget type="ProgressBar" skin="MW_Progress_Loading" position="20 36 260 8" name="ProgressBar"> <Widget type="ScrollBar" skin="MW_ProgressScroll_Loading" position="20 36 260 8" name="ProgressBar">
<Property key="Range" value="1000"/>
</Widget> </Widget>
</Widget> </Widget>

View file

@ -58,10 +58,23 @@
</Skin> </Skin>
<Skin name="MW_Progress_Loading" size="64 6"> <Skin name="MW_Progress_Loading" size="64 6">
<Property key="TrackSkin" value="MW_BigTrack_Progress_Blue_Small"/> <Property key="TrackSkin" value="MW_BigTrack_Progress_Blue_Small"/>
<Property key="TrackWidth" value="1"/> <Property key="TrackWidth" value="1"/>
<Child type="Widget" skin="MW_Box" offset="0 0 64 6" align="Stretch"/> <Child type="Widget" skin="MW_Box" offset="0 0 64 6" align="Stretch"/>
<Child type="Widget" skin="BlackBG" offset="2 2 60 2" align="Stretch" name="Client"/> <Child type="Widget" skin="BlackBG" offset="2 2 60 2" align="Stretch" name="Client"/>
</Skin> </Skin>
<Skin name="MW_ProgressScroll_Loading" size="64 6">
<Property key="TrackWidth" value="1"/>
<Property key="TrackRangeMargins" value="0 0"/>
<Property key="MinTrackSize" value="1"/>
<Property key="VerticalAlignment" value="false"/>
<Property key="MoveToClick" value="false"/>
<Child type="Widget" skin="BlackBG" offset="2 2 60 2" align="Stretch" name="Client"/>
<Child type="Button" skin="MW_BigTrack_Progress_Blue_Small" offset="0 0 1 6" align="Left VStretch" name="Track"/>
<Child type="Widget" skin="MW_Box" offset="0 0 64 6" align="Stretch"/>
</Skin>
</MyGUI> </MyGUI>

View file

@ -279,27 +279,23 @@ void OgreRenderer::createWindow(const std::string &title, const WindowSettings&
0, 0,
Ogre::PF_A8R8G8B8, Ogre::PF_A8R8G8B8,
Ogre::TU_WRITE_ONLY); Ogre::TU_WRITE_ONLY);
}
void OgreRenderer::createScene(const std::string& camName, float fov, float nearClip)
{
assert(mRoot);
assert(mWindow);
// Get the SceneManager, in this case a generic one
mScene = mRoot->createSceneManager(ST_GENERIC); mScene = mRoot->createSceneManager(ST_GENERIC);
// Create the camera mFader = new Fader(mScene);
mCamera = mScene->createCamera(camName);
mCamera->setNearClipDistance(nearClip); mCamera = mScene->createCamera("cam");
mCamera->setFOVy(Degree(fov));
// Create one viewport, entire window // Create one viewport, entire window
mView = mWindow->addViewport(mCamera); mView = mWindow->addViewport(mCamera);
// Alter the camera aspect ratio to match the viewport // Alter the camera aspect ratio to match the viewport
mCamera->setAspectRatio(Real(mView->getActualWidth()) / Real(mView->getActualHeight())); mCamera->setAspectRatio(Real(mView->getActualWidth()) / Real(mView->getActualHeight()));
}
mFader = new Fader(mScene); void OgreRenderer::adjustCamera(float fov, float nearClip)
{
mCamera->setNearClipDistance(nearClip);
mCamera->setFOVy(Degree(fov));
} }
void OgreRenderer::adjustViewport() void OgreRenderer::adjustViewport()

View file

@ -157,7 +157,7 @@ namespace OEngine
void createWindow(const std::string &title, const WindowSettings& settings); void createWindow(const std::string &title, const WindowSettings& settings);
/// Set up the scene manager, camera and viewport /// Set up the scene manager, camera and viewport
void createScene(const std::string& camName="Camera",// Camera name void adjustCamera(
float fov=55, // Field of view angle float fov=55, // Field of view angle
float nearClip=5 // Near clip distance float nearClip=5 // Near clip distance
); );