From 9a3158675aacbff494621cac25686778d1be1418 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 10 Feb 2011 10:38:45 +0100 Subject: [PATCH] reworked cell changing mechanism --- apps/openmw/engine.cpp | 2 +- apps/openmw/mwmechanics/mechanicsmanager.cpp | 6 + apps/openmw/mwscript/cellextensions.cpp | 2 +- apps/openmw/mwworld/actionteleport.cpp | 2 +- apps/openmw/mwworld/world.cpp | 176 ++++++++++--------- apps/openmw/mwworld/world.hpp | 16 +- 6 files changed, 111 insertions(+), 93 deletions(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 5c3da5d2b..b78eb1582 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -393,7 +393,7 @@ void OMW::Engine::go() else { pos.pos[0] = pos.pos[1] = 0; - mEnvironment.mWorld->changeCell (mCellName, pos); + mEnvironment.mWorld->changeToInteriorCell (mCellName, pos); } // Sets up the input system diff --git a/apps/openmw/mwmechanics/mechanicsmanager.cpp b/apps/openmw/mwmechanics/mechanicsmanager.cpp index cad257f38..df0b5616c 100644 --- a/apps/openmw/mwmechanics/mechanicsmanager.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanager.cpp @@ -234,11 +234,17 @@ namespace MWMechanics void MechanicsManager::removeActor (const MWWorld::Ptr& ptr) { + if (ptr==mWatched) + mWatched = MWWorld::Ptr(); + mActors.erase (ptr); } void MechanicsManager::dropActors (const MWWorld::Ptr::CellStore *cellStore) { + if (!mWatched.isEmpty() && mWatched.getCell()==cellStore) + mWatched = MWWorld::Ptr(); + std::set::iterator iter = mActors.begin(); while (iter!=mActors.end()) diff --git a/apps/openmw/mwscript/cellextensions.cpp b/apps/openmw/mwscript/cellextensions.cpp index 4d3025469..a84de3edd 100644 --- a/apps/openmw/mwscript/cellextensions.cpp +++ b/apps/openmw/mwscript/cellextensions.cpp @@ -53,7 +53,7 @@ namespace MWScript else { pos.pos[0] = pos.pos[1] = 0; - context.getWorld().changeCell (cell, pos); + context.getWorld().changeToInteriorCell (cell, pos); } } }; diff --git a/apps/openmw/mwworld/actionteleport.cpp b/apps/openmw/mwworld/actionteleport.cpp index 3db294818..207e2c50e 100644 --- a/apps/openmw/mwworld/actionteleport.cpp +++ b/apps/openmw/mwworld/actionteleport.cpp @@ -16,6 +16,6 @@ namespace MWWorld if (mCellName.empty()) environment.mWorld->changeToExteriorCell (mPosition); else - environment.mWorld->changeCell (mCellName, mPosition); + environment.mWorld->changeToInteriorCell (mCellName, mPosition); } } diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index d67cc1459..f071acdd8 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -305,9 +305,12 @@ namespace MWWorld } } - void World::playerCellChange (Ptr::CellStore *cell, const ESM::Position& position) + void World::playerCellChange (Ptr::CellStore *cell, const ESM::Position& position, + bool adjustPlayerPos) { - mPlayer->setPos (position.pos[0], position.pos[1], position.pos[2], true); + if (adjustPlayerPos) + mPlayer->setPos (position.pos[0], position.pos[1], position.pos[2], true); + mPlayer->setCell (cell); // TODO orientation @@ -326,8 +329,87 @@ namespace MWWorld } } + void World::changeCell (int X, int Y, const ESM::Position& position, bool adjustPlayerPos) + { + SuppressDoingPhysics scopeGuard; + + // remove active + mEnvironment.mMechanicsManager->removeActor (mPlayer->getPlayer()); + + CellRenderCollection::iterator active = mActiveCells.begin(); + + while (active!=mActiveCells.end()) + { + if (!(active->first->cell->data.flags & ESM::Cell::Interior)) + { + if (std::abs (X-active->first->cell->data.gridX)<=1 && + std::abs (Y-active->first->cell->data.gridY)<=1) + { + // keep cells within the new 3x3 grid + ++active; + continue; + } + } + + unloadCell (active++); + } + + // Load cells + for (int x=X-1; x<=X+1; ++x) + for (int y=Y-1; y<=Y+1; ++y) + { + CellRenderCollection::iterator iter = mActiveCells.begin(); + + while (iter!=mActiveCells.end()) + { + assert (!(iter->first->cell->data.flags & ESM::Cell::Interior)); + + if (x==iter->first->cell->data.gridX && + y==iter->first->cell->data.gridY) + break; + + ++iter; + } + + if (iter==mActiveCells.end()) + { + mExteriors[std::make_pair (x, y)].loadExt (x, y, mStore, mEsm); + Ptr::CellStore *cell = &mExteriors[std::make_pair (x, y)]; + + loadCell (cell, new MWRender::ExteriorCellRender (*cell, mEnvironment, mScene)); + } + } + + // find current cell + CellRenderCollection::iterator iter = mActiveCells.begin(); + + while (iter!=mActiveCells.end()) + { + assert (!(iter->first->cell->data.flags & ESM::Cell::Interior)); + + if (X==iter->first->cell->data.gridX && + Y==iter->first->cell->data.gridY) + break; + + ++iter; + } + + assert (iter!=mActiveCells.end()); + + mCurrentCell = iter->first; + + // adjust player + playerCellChange (&mExteriors[std::make_pair (X, Y)], position, adjustPlayerPos); + + // Sky system + adjustSky(); + + mCellChanged = true; + } + World::World (OEngine::Render::OgreRenderer& renderer, const boost::filesystem::path& dataDir, - const std::string& master, const boost::filesystem::path& resDir, bool newGame, Environment& environment) + const std::string& master, const boost::filesystem::path& resDir, + bool newGame, Environment& environment) : mSkyManager (0), mScene (renderer), mPlayer (0), mCurrentCell (0), mGlobalVariables (0), mSky (false), mCellChanged (false), mEnvironment (environment) { @@ -597,8 +679,10 @@ namespace MWWorld return mGlobalVariables->getInt ("timescale"); } - void World::changeCell (const std::string& cellName, const ESM::Position& position) + void World::changeToInteriorCell (const std::string& cellName, const ESM::Position& position) { + SuppressDoingPhysics scopeGuard; + // remove active CellRenderCollection::iterator active = mActiveCells.begin(); @@ -624,91 +708,14 @@ namespace MWWorld //currentRegion->name = ""; } - void World::changeCell (int X, int Y, const ESM::Position& position) - { - SuppressDoingPhysics scopeGuard; - - // remove active - CellRenderCollection::iterator active = mActiveCells.begin(); - - while (active!=mActiveCells.end()) - { - if (!(active->first->cell->data.flags & ESM::Cell::Interior)) - { - if (std::abs (X-active->first->cell->data.gridX)<=1 && - std::abs (Y-active->first->cell->data.gridY)<=1) - { - // keep cells within the new 3x3 grid - ++active; - continue; - } - } - - unloadCell (active++); - } - - // Load cells - for (int x=X-1; x<=X+1; ++x) - for (int y=Y-1; y<=Y+1; ++y) - { - CellRenderCollection::iterator iter = mActiveCells.begin(); - - while (iter!=mActiveCells.end()) - { - assert (!(iter->first->cell->data.flags & ESM::Cell::Interior)); - - if (x==iter->first->cell->data.gridX && - y==iter->first->cell->data.gridY) - break; - - ++iter; - } - - if (iter==mActiveCells.end()) - { - mExteriors[std::make_pair (x, y)].loadExt (x, y, mStore, mEsm); - Ptr::CellStore *cell = &mExteriors[std::make_pair (x, y)]; - - loadCell (cell, new MWRender::ExteriorCellRender (*cell, mEnvironment, mScene)); - } - } - - // find current cell - CellRenderCollection::iterator iter = mActiveCells.begin(); - - while (iter!=mActiveCells.end()) - { - assert (!(iter->first->cell->data.flags & ESM::Cell::Interior)); - - if (X==iter->first->cell->data.gridX && - Y==iter->first->cell->data.gridY) - break; - - ++iter; - } - - assert (iter!=mActiveCells.end()); - - mCurrentCell = iter->first; - - // adjust player - playerCellChange (&mExteriors[std::make_pair (X, Y)], position); - - // Sky system - adjustSky(); - - mCellChanged = true; - } - - - void World::changeToExteriorCell (const ESM::Position& position) + void World::changeToExteriorCell (const ESM::Position& position) { int x = 0; int y = 0; positionToIndex (position.pos[0], position.pos[1], x, y); - changeCell (x, y, position); + changeCell (x, y, position, true); } const ESM::Cell *World::getExterior (const std::string& cellName) const @@ -734,6 +741,7 @@ namespace MWWorld return 0; } + void World::markCellAsUnchanged() { mCellChanged = false; @@ -793,7 +801,7 @@ namespace MWWorld if (mCurrentCell->cell->data.gridX!=cellX || mCurrentCell->cell->data.gridY!=cellY) { - changeCell (cellX, cellY, mPlayer->getPlayer().getCellRef().pos); + changeCell (cellX, cellY, mPlayer->getPlayer().getCellRef().pos, false); } if (!DoingPhysics::isDoingPhysics()) diff --git a/apps/openmw/mwworld/world.hpp b/apps/openmw/mwworld/world.hpp index 6930589f4..15b6df233 100644 --- a/apps/openmw/mwworld/world.hpp +++ b/apps/openmw/mwworld/world.hpp @@ -88,14 +88,19 @@ namespace MWWorld void loadCell (Ptr::CellStore *cell, MWRender::CellRender *render); - void playerCellChange (Ptr::CellStore *cell, const ESM::Position& position); + void playerCellChange (Ptr::CellStore *cell, const ESM::Position& position, + bool adjustPlayerPos = true); void adjustSky(); + void changeCell (int X, int Y, const ESM::Position& position, bool adjustPlayerPos); + ///< Move from exterior to interior or from interior cell to a different + /// interior cell. public: World (OEngine::Render::OgreRenderer& renderer, const boost::filesystem::path& dataDir, - const std::string& master, const boost::filesystem::path& resDir, bool newGame, Environment& environment); + const std::string& master, const boost::filesystem::path& resDir, bool newGame, + Environment& environment); ~World(); @@ -143,12 +148,11 @@ namespace MWWorld float getTimeScaleFactor() const; - void changeCell (const std::string& cellName, const ESM::Position& position); - ///< works only for interior cells currently. - - void changeCell (int X, int Y, const ESM::Position& position); + void changeToInteriorCell (const std::string& cellName, const ESM::Position& position); + ///< Move to interior cell. void changeToExteriorCell (const ESM::Position& position); + ///< Move to exterior cell. const ESM::Cell *getExterior (const std::string& cellName) const; ///< Return a cell matching the given name or a 0-pointer, if there is no such cell.