|
|
|
@ -12,6 +12,7 @@
|
|
|
|
|
#include <components/resource/resourcesystem.hpp>
|
|
|
|
|
#include <components/resource/scenemanager.hpp>
|
|
|
|
|
#include <components/resource/bulletshape.hpp>
|
|
|
|
|
#include <components/sceneutil/unrefqueue.hpp>
|
|
|
|
|
#include <components/detournavigator/navigator.hpp>
|
|
|
|
|
#include <components/detournavigator/debug.hpp>
|
|
|
|
|
#include <components/misc/convert.hpp>
|
|
|
|
@ -22,6 +23,8 @@
|
|
|
|
|
#include "../mwbase/mechanicsmanager.hpp"
|
|
|
|
|
#include "../mwbase/windowmanager.hpp"
|
|
|
|
|
|
|
|
|
|
#include "../mwmechanics/actorutil.hpp"
|
|
|
|
|
|
|
|
|
|
#include "../mwrender/renderingmanager.hpp"
|
|
|
|
|
#include "../mwrender/landmanager.hpp"
|
|
|
|
|
|
|
|
|
@ -205,10 +208,11 @@ namespace
|
|
|
|
|
{
|
|
|
|
|
MWWorld::CellStore& mCell;
|
|
|
|
|
Loading::Listener& mLoadingListener;
|
|
|
|
|
bool mTest;
|
|
|
|
|
|
|
|
|
|
std::vector<MWWorld::Ptr> mToInsert;
|
|
|
|
|
|
|
|
|
|
InsertVisitor (MWWorld::CellStore& cell, Loading::Listener& loadingListener);
|
|
|
|
|
InsertVisitor (MWWorld::CellStore& cell, Loading::Listener& loadingListener, bool test);
|
|
|
|
|
|
|
|
|
|
bool operator() (const MWWorld::Ptr& ptr);
|
|
|
|
|
|
|
|
|
@ -216,8 +220,8 @@ namespace
|
|
|
|
|
void insert(AddObject&& addObject);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
InsertVisitor::InsertVisitor (MWWorld::CellStore& cell, Loading::Listener& loadingListener)
|
|
|
|
|
: mCell (cell), mLoadingListener (loadingListener)
|
|
|
|
|
InsertVisitor::InsertVisitor (MWWorld::CellStore& cell, Loading::Listener& loadingListener, bool test)
|
|
|
|
|
: mCell (cell), mLoadingListener (loadingListener), mTest(test)
|
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
bool InsertVisitor::operator() (const MWWorld::Ptr& ptr)
|
|
|
|
@ -246,7 +250,8 @@ namespace
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mLoadingListener.increaseProgress (1);
|
|
|
|
|
if (!mTest)
|
|
|
|
|
mLoadingListener.increaseProgress (1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -317,9 +322,10 @@ namespace MWWorld
|
|
|
|
|
mPreloader->updateCache(mRendering.getReferenceTime());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Scene::unloadCell (CellStoreCollection::iterator iter)
|
|
|
|
|
void Scene::unloadCell (CellStoreCollection::iterator iter, bool test)
|
|
|
|
|
{
|
|
|
|
|
Log(Debug::Info) << "Unloading cell " << (*iter)->getCell()->getDescription();
|
|
|
|
|
if (!test)
|
|
|
|
|
Log(Debug::Info) << "Unloading cell " << (*iter)->getCell()->getDescription();
|
|
|
|
|
|
|
|
|
|
const auto navigator = MWBase::Environment::get().getWorld()->getNavigator();
|
|
|
|
|
ListAndResetObjectsVisitor visitor;
|
|
|
|
@ -373,13 +379,16 @@ namespace MWWorld
|
|
|
|
|
mActiveCells.erase(*iter);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Scene::loadCell (CellStore *cell, Loading::Listener* loadingListener, bool respawn)
|
|
|
|
|
void Scene::loadCell (CellStore *cell, Loading::Listener* loadingListener, bool respawn, bool test)
|
|
|
|
|
{
|
|
|
|
|
std::pair<CellStoreCollection::iterator, bool> result = mActiveCells.insert(cell);
|
|
|
|
|
|
|
|
|
|
if(result.second)
|
|
|
|
|
{
|
|
|
|
|
Log(Debug::Info) << "Loading cell " << cell->getCell()->getDescription();
|
|
|
|
|
if (test)
|
|
|
|
|
Log(Debug::Info) << "Testing cell " << cell->getCell()->getDescription();
|
|
|
|
|
else
|
|
|
|
|
Log(Debug::Info) << "Loading cell " << cell->getCell()->getDescription();
|
|
|
|
|
|
|
|
|
|
float verts = ESM::Land::LAND_SIZE;
|
|
|
|
|
float worldsize = ESM::Land::REAL_SIZE;
|
|
|
|
@ -390,7 +399,7 @@ namespace MWWorld
|
|
|
|
|
const int cellY = cell->getCell()->getGridY();
|
|
|
|
|
|
|
|
|
|
// Load terrain physics first...
|
|
|
|
|
if (cell->getCell()->isExterior())
|
|
|
|
|
if (!test && cell->getCell()->isExterior())
|
|
|
|
|
{
|
|
|
|
|
osg::ref_ptr<const ESMTerrain::LandObject> land = mRendering.getLandManager()->getLand(cellX, cellY);
|
|
|
|
|
const ESM::Land::LandData* data = land ? land->getData(ESM::Land::DATA_VHGT) : 0;
|
|
|
|
@ -418,38 +427,44 @@ namespace MWWorld
|
|
|
|
|
cell->respawn();
|
|
|
|
|
|
|
|
|
|
// ... then references. This is important for adjustPosition to work correctly.
|
|
|
|
|
insertCell (*cell, loadingListener);
|
|
|
|
|
insertCell (*cell, loadingListener, test);
|
|
|
|
|
|
|
|
|
|
mRendering.addCell(cell);
|
|
|
|
|
MWBase::Environment::get().getWindowManager()->addCell(cell);
|
|
|
|
|
bool waterEnabled = cell->getCell()->hasWater() || cell->isExterior();
|
|
|
|
|
float waterLevel = cell->getWaterLevel();
|
|
|
|
|
mRendering.setWaterEnabled(waterEnabled);
|
|
|
|
|
if (waterEnabled)
|
|
|
|
|
if (!test)
|
|
|
|
|
{
|
|
|
|
|
mPhysics->enableWater(waterLevel);
|
|
|
|
|
mRendering.setWaterHeight(waterLevel);
|
|
|
|
|
|
|
|
|
|
if (cell->getCell()->isExterior())
|
|
|
|
|
MWBase::Environment::get().getWindowManager()->addCell(cell);
|
|
|
|
|
bool waterEnabled = cell->getCell()->hasWater() || cell->isExterior();
|
|
|
|
|
float waterLevel = cell->getWaterLevel();
|
|
|
|
|
mRendering.setWaterEnabled(waterEnabled);
|
|
|
|
|
if (waterEnabled)
|
|
|
|
|
{
|
|
|
|
|
if (const auto heightField = mPhysics->getHeightField(cellX, cellY))
|
|
|
|
|
navigator->addWater(osg::Vec2i(cellX, cellY), ESM::Land::REAL_SIZE,
|
|
|
|
|
cell->getWaterLevel(), heightField->getCollisionObject()->getWorldTransform());
|
|
|
|
|
mPhysics->enableWater(waterLevel);
|
|
|
|
|
mRendering.setWaterHeight(waterLevel);
|
|
|
|
|
|
|
|
|
|
if (cell->getCell()->isExterior())
|
|
|
|
|
{
|
|
|
|
|
if (const auto heightField = mPhysics->getHeightField(cellX, cellY))
|
|
|
|
|
navigator->addWater(osg::Vec2i(cellX, cellY), ESM::Land::REAL_SIZE,
|
|
|
|
|
cell->getWaterLevel(), heightField->getCollisionObject()->getWorldTransform());
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
navigator->addWater(osg::Vec2i(cellX, cellY), std::numeric_limits<int>::max(),
|
|
|
|
|
cell->getWaterLevel(), btTransform::getIdentity());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
mPhysics->disableWater();
|
|
|
|
|
|
|
|
|
|
const auto player = MWBase::Environment::get().getWorld()->getPlayerPtr();
|
|
|
|
|
navigator->update(player.getRefData().getPosition().asVec3());
|
|
|
|
|
|
|
|
|
|
if (!cell->isExterior() && !(cell->getCell()->mData.mFlags & ESM::Cell::QuasiEx))
|
|
|
|
|
{
|
|
|
|
|
navigator->addWater(osg::Vec2i(cellX, cellY), std::numeric_limits<int>::max(),
|
|
|
|
|
cell->getWaterLevel(), btTransform::getIdentity());
|
|
|
|
|
|
|
|
|
|
mRendering.configureAmbient(cell->getCell());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
mPhysics->disableWater();
|
|
|
|
|
|
|
|
|
|
const auto player = MWBase::Environment::get().getWorld()->getPlayerPtr();
|
|
|
|
|
navigator->update(player.getRefData().getPosition().asVec3());
|
|
|
|
|
|
|
|
|
|
if (!cell->isExterior() && !(cell->getCell()->mData.mFlags & ESM::Cell::QuasiEx))
|
|
|
|
|
mRendering.configureAmbient(cell->getCell());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mPreloader->notifyLoaded(cell);
|
|
|
|
@ -594,6 +609,101 @@ namespace MWWorld
|
|
|
|
|
mCellChanged = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Scene::testExteriorCells()
|
|
|
|
|
{
|
|
|
|
|
// Note: temporary disable ICO to decrease memory usage
|
|
|
|
|
mRendering.getResourceSystem()->getSceneManager()->setIncrementalCompileOperation(nullptr);
|
|
|
|
|
|
|
|
|
|
mRendering.getResourceSystem()->setExpiryDelay(1.f);
|
|
|
|
|
|
|
|
|
|
const MWWorld::Store<ESM::Cell> &cells = MWBase::Environment::get().getWorld()->getStore().get<ESM::Cell>();
|
|
|
|
|
|
|
|
|
|
Loading::Listener* loadingListener = MWBase::Environment::get().getWindowManager()->getLoadingScreen();
|
|
|
|
|
Loading::ScopedLoad load(loadingListener);
|
|
|
|
|
loadingListener->setProgressRange(cells.getExtSize());
|
|
|
|
|
|
|
|
|
|
MWWorld::Store<ESM::Cell>::iterator it = cells.extBegin();
|
|
|
|
|
int i = 1;
|
|
|
|
|
for (; it != cells.extEnd(); ++it)
|
|
|
|
|
{
|
|
|
|
|
loadingListener->setLabel("Testing exterior cells ("+std::to_string(i)+"/"+std::to_string(cells.getExtSize())+")...");
|
|
|
|
|
|
|
|
|
|
CellStoreCollection::iterator iter = mActiveCells.begin();
|
|
|
|
|
|
|
|
|
|
CellStore *cell = MWBase::Environment::get().getWorld()->getExterior(it->mData.mX, it->mData.mY);
|
|
|
|
|
loadCell (cell, loadingListener, false, true);
|
|
|
|
|
|
|
|
|
|
iter = mActiveCells.begin();
|
|
|
|
|
while (iter != mActiveCells.end())
|
|
|
|
|
{
|
|
|
|
|
if (it->isExterior() && it->mData.mX == (*iter)->getCell()->getGridX() &&
|
|
|
|
|
it->mData.mY == (*iter)->getCell()->getGridY())
|
|
|
|
|
{
|
|
|
|
|
unloadCell(iter, true);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
++iter;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mRendering.getResourceSystem()->updateCache(mRendering.getReferenceTime());
|
|
|
|
|
mRendering.getUnrefQueue()->flush(mRendering.getWorkQueue());
|
|
|
|
|
|
|
|
|
|
loadingListener->increaseProgress (1);
|
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mRendering.getResourceSystem()->getSceneManager()->setIncrementalCompileOperation(mRendering.getIncrementalCompileOperation());
|
|
|
|
|
mRendering.getResourceSystem()->setExpiryDelay(Settings::Manager::getFloat("cache expiry delay", "Cells"));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Scene::testInteriorCells()
|
|
|
|
|
{
|
|
|
|
|
// Note: temporary disable ICO to decrease memory usage
|
|
|
|
|
mRendering.getResourceSystem()->getSceneManager()->setIncrementalCompileOperation(nullptr);
|
|
|
|
|
|
|
|
|
|
mRendering.getResourceSystem()->setExpiryDelay(1.f);
|
|
|
|
|
|
|
|
|
|
const MWWorld::Store<ESM::Cell> &cells = MWBase::Environment::get().getWorld()->getStore().get<ESM::Cell>();
|
|
|
|
|
|
|
|
|
|
Loading::Listener* loadingListener = MWBase::Environment::get().getWindowManager()->getLoadingScreen();
|
|
|
|
|
Loading::ScopedLoad load(loadingListener);
|
|
|
|
|
loadingListener->setProgressRange(cells.getIntSize());
|
|
|
|
|
|
|
|
|
|
int i = 1;
|
|
|
|
|
MWWorld::Store<ESM::Cell>::iterator it = cells.intBegin();
|
|
|
|
|
for (; it != cells.intEnd(); ++it)
|
|
|
|
|
{
|
|
|
|
|
loadingListener->setLabel("Testing interior cells ("+std::to_string(i)+"/"+std::to_string(cells.getIntSize())+")...");
|
|
|
|
|
|
|
|
|
|
CellStore *cell = MWBase::Environment::get().getWorld()->getInterior(it->mName);
|
|
|
|
|
loadCell (cell, loadingListener, false, true);
|
|
|
|
|
|
|
|
|
|
CellStoreCollection::iterator iter = mActiveCells.begin();
|
|
|
|
|
while (iter != mActiveCells.end())
|
|
|
|
|
{
|
|
|
|
|
assert (!(*iter)->getCell()->isExterior());
|
|
|
|
|
|
|
|
|
|
if (it->mName == (*iter)->getCell()->mName)
|
|
|
|
|
{
|
|
|
|
|
unloadCell(iter, true);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
++iter;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mRendering.getResourceSystem()->updateCache(mRendering.getReferenceTime());
|
|
|
|
|
mRendering.getUnrefQueue()->flush(mRendering.getWorkQueue());
|
|
|
|
|
|
|
|
|
|
loadingListener->increaseProgress (1);
|
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mRendering.getResourceSystem()->getSceneManager()->setIncrementalCompileOperation(mRendering.getIncrementalCompileOperation());
|
|
|
|
|
mRendering.getResourceSystem()->setExpiryDelay(Settings::Manager::getFloat("cache expiry delay", "Cells"));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Scene::changePlayerCell(CellStore *cell, const ESM::Position &pos, bool adjustPlayerPos)
|
|
|
|
|
{
|
|
|
|
|
mCurrentCell = cell;
|
|
|
|
@ -759,9 +869,9 @@ namespace MWWorld
|
|
|
|
|
mCellChanged = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Scene::insertCell (CellStore &cell, Loading::Listener* loadingListener)
|
|
|
|
|
void Scene::insertCell (CellStore &cell, Loading::Listener* loadingListener, bool test)
|
|
|
|
|
{
|
|
|
|
|
InsertVisitor insertVisitor (cell, *loadingListener);
|
|
|
|
|
InsertVisitor insertVisitor (cell, *loadingListener, test);
|
|
|
|
|
cell.forEach (insertVisitor);
|
|
|
|
|
insertVisitor.insert([&] (const MWWorld::Ptr& ptr) { addObject(ptr, *mPhysics, mRendering); });
|
|
|
|
|
insertVisitor.insert([&] (const MWWorld::Ptr& ptr) { addObject(ptr, *mPhysics, mNavigator); });
|
|
|
|
|