int x, int y , ESM::RefId worldspace => ESM::ExteriorCellIndex

also removed the changeToExteriorCell that only took a position as input, didn't work with esm4.
simplify_debugging
florent.teppe 2 years ago
parent 43e247d458
commit 141878f30d

@ -250,10 +250,6 @@ namespace MWBase
///< Move to interior cell. ///< Move to interior cell.
///< @param changeEvent If false, do not trigger cell change flag or detect worldspace changes ///< @param changeEvent If false, do not trigger cell change flag or detect worldspace changes
virtual void changeToExteriorCell(const ESM::Position& position, bool adjustPlayerPos, bool changeEvent = true)
= 0;
///< Move to exterior cell.
///< @param changeEvent If false, do not trigger cell change flag or detect worldspace changes
virtual void changeToCell( virtual void changeToCell(
const ESM::RefId& cellId, const ESM::Position& position, bool adjustPlayerPos, bool changeEvent = true) const ESM::RefId& cellId, const ESM::Position& position, bool adjustPlayerPos, bool changeEvent = true)
= 0; = 0;

@ -584,7 +584,7 @@ namespace MWGui
{ {
if (!mInterior) if (!mInterior)
requestMapRender(&MWBase::Environment::get().getWorldModel()->getExterior( requestMapRender(&MWBase::Environment::get().getWorldModel()->getExterior(
entry.mCellX, entry.mCellY, ESM::Cell::sDefaultWorldspaceId)); ESM::ExteriorCellIndex(entry.mCellX, entry.mCellY, ESM::Cell::sDefaultWorldspaceId)));
osg::ref_ptr<osg::Texture2D> texture = mLocalMapRender->getMapTexture(entry.mCellX, entry.mCellY); osg::ref_ptr<osg::Texture2D> texture = mLocalMapRender->getMapTexture(entry.mCellX, entry.mCellY);
if (texture) if (texture)
@ -641,8 +641,9 @@ namespace MWGui
for (MapEntry& entry : mMaps) for (MapEntry& entry : mMaps)
{ {
if (!entry.mMapTexture && !widgetCropped(entry.mMapWidget, mLocalMap)) if (!entry.mMapTexture && !widgetCropped(entry.mMapWidget, mLocalMap))
world->getDoorMarkers( world->getDoorMarkers(worldModel->getExterior(ESM::ExteriorCellIndex(
worldModel->getExterior(entry.mCellX, entry.mCellY, ESM::Cell::sDefaultWorldspaceId), doors); entry.mCellX, entry.mCellY, ESM::Cell::sDefaultWorldspaceId)),
doors);
} }
if (doors.empty()) if (doors.empty())
return; return;

@ -131,7 +131,7 @@ namespace MWGui
if (cellname.empty()) if (cellname.empty())
{ {
MWWorld::CellStore& cell = MWBase::Environment::get().getWorldModel()->getExterior( MWWorld::CellStore& cell = MWBase::Environment::get().getWorldModel()->getExterior(
cellIndex.x(), cellIndex.y(), ESM::Cell::sDefaultWorldspaceId); ESM::ExteriorCellIndex(cellIndex.x(), cellIndex.y(), ESM::Cell::sDefaultWorldspaceId));
cellname = MWBase::Environment::get().getWorld()->getCellName(&cell); cellname = MWBase::Environment::get().getWorld()->getCellName(&cell);
interior = false; interior = false;
} }

@ -115,7 +115,7 @@ namespace MWLua
= [](std::string_view name) { return GCell{ &MWBase::Environment::get().getWorldModel()->getCell(name) }; }; = [](std::string_view name) { return GCell{ &MWBase::Environment::get().getWorldModel()->getCell(name) }; };
api["getExteriorCell"] = [](int x, int y) { api["getExteriorCell"] = [](int x, int y) {
return GCell{ &MWBase::Environment::get().getWorldModel()->getExterior( return GCell{ &MWBase::Environment::get().getWorldModel()->getExterior(
x, y, ESM::Cell::sDefaultWorldspaceId) }; ESM::ExteriorCellIndex(x, y, ESM::Cell::sDefaultWorldspaceId)) };
}; };
api["activeActors"] = GObjectList{ worldView->getActorsInScene() }; api["activeActors"] = GObjectList{ worldView->getActorsInScene() };
api["createObject"] = [](std::string_view recordId, sol::optional<int> count) -> GObject { api["createObject"] = [](std::string_view recordId, sol::optional<int> count) -> GObject {

@ -483,11 +483,11 @@ namespace MWPhysics
mHeightFields.erase(heightfield); mHeightFields.erase(heightfield);
} }
const HeightField* PhysicsSystem::getHeightField(int x, int y, ESM::RefId worldspace) const const HeightField* PhysicsSystem::getHeightField(ESM::ExteriorCellIndex cellIndex) const
{ {
if (worldspace != ESM::Cell::sDefaultWorldspaceId) if (cellIndex.mWorldspace != ESM::Cell::sDefaultWorldspaceId)
return nullptr; return nullptr;
const auto heightField = mHeightFields.find(std::make_pair(x, y)); const auto heightField = mHeightFields.find(std::make_pair(cellIndex.mX, cellIndex.mY));
if (heightField == mHeightFields.end()) if (heightField == mHeightFields.end())
return nullptr; return nullptr;
return heightField->second.get(); return heightField->second.get();

@ -17,6 +17,7 @@
#include <osg/ref_ptr> #include <osg/ref_ptr>
#include <components/detournavigator/collisionshapetype.hpp> #include <components/detournavigator/collisionshapetype.hpp>
#include <components/esm/util.hpp>
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
@ -189,7 +190,7 @@ namespace MWPhysics
void removeHeightField(int x, int y); void removeHeightField(int x, int y);
const HeightField* getHeightField(int x, int y, ESM::RefId worldspace) const; const HeightField* getHeightField(ESM::ExteriorCellIndex cellIndex) const;
bool toggleCollisionMode(); bool toggleCollisionMode();

@ -18,11 +18,12 @@ namespace MWRender
mCache = new CacheType; mCache = new CacheType;
} }
osg::ref_ptr<ESMTerrain::LandObject> LandManager::getLand(int x, int y, ESM::RefId worldspace) osg::ref_ptr<ESMTerrain::LandObject> LandManager::getLand(ESM::ExteriorCellIndex cellIndex)
{ {
if (worldspace != ESM::Cell::sDefaultWorldspaceId) if (cellIndex.mWorldspace != ESM::Cell::sDefaultWorldspaceId)
return osg::ref_ptr<ESMTerrain::LandObject>(nullptr); return osg::ref_ptr<ESMTerrain::LandObject>(nullptr);
int x = cellIndex.mX;
int y = cellIndex.mY;
osg::ref_ptr<osg::Object> obj = mCache->getRefFromObjectCache(std::make_pair(x, y)); osg::ref_ptr<osg::Object> obj = mCache->getRefFromObjectCache(std::make_pair(x, y));
if (obj) if (obj)
return static_cast<ESMTerrain::LandObject*>(obj.get()); return static_cast<ESMTerrain::LandObject*>(obj.get());

@ -3,6 +3,7 @@
#include <osg/Object> #include <osg/Object>
#include <components/esm/util.hpp>
#include <components/esm3terrain/storage.hpp> #include <components/esm3terrain/storage.hpp>
#include <components/resource/resourcemanager.hpp> #include <components/resource/resourcemanager.hpp>
@ -20,7 +21,7 @@ namespace MWRender
LandManager(int loadFlags); LandManager(int loadFlags);
/// @note Will return nullptr if not found. /// @note Will return nullptr if not found.
osg::ref_ptr<ESMTerrain::LandObject> getLand(int x, int y, ESM::RefId worldspace); osg::ref_ptr<ESMTerrain::LandObject> getLand(ESM::ExteriorCellIndex cellIndex);
void reportStats(unsigned int frameNumber, osg::Stats* stats) const override; void reportStats(unsigned int frameNumber, osg::Stats* stats) const override;

@ -68,7 +68,7 @@ namespace MWRender
osg::ref_ptr<const ESMTerrain::LandObject> TerrainStorage::getLand(int cellX, int cellY) osg::ref_ptr<const ESMTerrain::LandObject> TerrainStorage::getLand(int cellX, int cellY)
{ {
return mLandManager->getLand(cellX, cellY, ESM::Cell::sDefaultWorldspaceId); return mLandManager->getLand(ESM::ExteriorCellIndex(cellX, cellY, ESM::Cell::sDefaultWorldspaceId));
} }
const ESM::LandTexture* TerrainStorage::getLandTexture(int index, short plugin) const ESM::LandTexture* TerrainStorage::getLandTexture(int index, short plugin)

@ -402,8 +402,8 @@ namespace MWScript
if (store->isExterior()) if (store->isExterior())
{ {
const osg::Vec2i cellIndex = MWWorld::positionToCellIndex(x, y); const osg::Vec2i cellIndex = MWWorld::positionToCellIndex(x, y);
store store = &worldModel->getExterior(
= &worldModel->getExterior(cellIndex.x(), cellIndex.y(), store->getCell()->getWorldSpace()); ESM::ExteriorCellIndex(cellIndex.x(), cellIndex.y(), store->getCell()->getWorldSpace()));
} }
} }
catch (std::exception&) catch (std::exception&)
@ -418,7 +418,8 @@ namespace MWScript
if (!isPlayer) if (!isPlayer)
return; return;
const osg::Vec2i cellIndex = MWWorld::positionToCellIndex(x, y); const osg::Vec2i cellIndex = MWWorld::positionToCellIndex(x, y);
store = &worldModel->getExterior(cellIndex.x(), cellIndex.y(), store->getCell()->getWorldSpace()); store = &worldModel->getExterior(
ESM::ExteriorCellIndex(cellIndex.x(), cellIndex.y(), store->getCell()->getWorldSpace()));
} }
if (store) if (store)
{ {
@ -475,7 +476,7 @@ namespace MWScript
if (isPlayer) if (isPlayer)
{ {
MWWorld::CellStore* cell = &MWBase::Environment::get().getWorldModel()->getExterior( MWWorld::CellStore* cell = &MWBase::Environment::get().getWorldModel()->getExterior(
cellIndex.x(), cellIndex.y(), ESM::Cell::sDefaultWorldspaceId); ESM::ExteriorCellIndex(cellIndex.x(), cellIndex.y(), ESM::Cell::sDefaultWorldspaceId));
ptr = world->moveObject(ptr, cell, osg::Vec3(x, y, z)); ptr = world->moveObject(ptr, cell, osg::Vec3(x, y, z));
} }
else else
@ -569,8 +570,8 @@ namespace MWScript
if (player.getCell()->isExterior()) if (player.getCell()->isExterior())
{ {
const osg::Vec2i cellIndex = MWWorld::positionToCellIndex(x, y); const osg::Vec2i cellIndex = MWWorld::positionToCellIndex(x, y);
store = &MWBase::Environment::get().getWorldModel()->getExterior( store = &MWBase::Environment::get().getWorldModel()->getExterior(ESM::ExteriorCellIndex(
cellIndex.x(), cellIndex.y(), player.getCell()->getCell()->getWorldSpace()); cellIndex.x(), cellIndex.y(), player.getCell()->getCell()->getWorldSpace()));
} }
else else
store = player.getCell(); store = player.getCell();

@ -563,8 +563,8 @@ void MWState::StateManager::loadGame(const Character* character, const std::file
{ {
// Cell no longer exists (i.e. changed game files), choose a default cell // Cell no longer exists (i.e. changed game files), choose a default cell
Log(Debug::Warning) << "Warning: Player character's cell no longer exists, changing to the default cell"; Log(Debug::Warning) << "Warning: Player character's cell no longer exists, changing to the default cell";
MWWorld::CellStore& cell MWWorld::CellStore& cell = MWBase::Environment::get().getWorldModel()->getExterior(
= MWBase::Environment::get().getWorldModel()->getExterior(0, 0, ESM::Cell::sDefaultWorldspaceId); ESM::ExteriorCellIndex(0, 0, ESM::Cell::sDefaultWorldspaceId));
float x, y; float x, y;
MWBase::Environment::get().getWorld()->indexToPosition(0, 0, x, y, false); MWBase::Environment::get().getWorld()->indexToPosition(0, 0, x, y, false);
ESM::Position pos; ESM::Position pos;

@ -102,7 +102,8 @@ namespace MWWorld
try try
{ {
mTerrain->cacheCell(mTerrainView.get(), mX, mY); mTerrain->cacheCell(mTerrainView.get(), mX, mY);
mPreloadedObjects.insert(mLandManager->getLand(mX, mY, ESM::Cell::sDefaultWorldspaceId)); mPreloadedObjects.insert(
mLandManager->getLand(ESM::ExteriorCellIndex(mX, mY, ESM::Cell::sDefaultWorldspaceId)));
} }
catch (std::exception&) catch (std::exception&)
{ {

@ -248,13 +248,13 @@ namespace
return std::abs(cellPosition.first) + std::abs(cellPosition.second); return std::abs(cellPosition.first) + std::abs(cellPosition.second);
} }
bool isCellInCollection(int x, int y, ESM::RefId worldspace, MWWorld::Scene::CellStoreCollection& collection) bool isCellInCollection(ESM::ExteriorCellIndex cellIndex, MWWorld::Scene::CellStoreCollection& collection)
{ {
for (auto* cell : collection) for (auto* cell : collection)
{ {
assert(cell->getCell()->isExterior()); assert(cell->getCell()->isExterior());
if (x == cell->getCell()->getGridX() && y == cell->getCell()->getGridY() if (cellIndex.mX == cell->getCell()->getGridX() && cellIndex.mY == cell->getCell()->getGridY()
&& cell->getCell()->getWorldSpace() == worldspace) && cell->getCell()->getWorldSpace() == cellIndex.mWorldspace)
return true; return true;
} }
return false; return false;
@ -306,8 +306,7 @@ namespace MWWorld
{ {
if (mChangeCellGridRequest.has_value()) if (mChangeCellGridRequest.has_value())
{ {
changeCellGrid(mChangeCellGridRequest->mPosition, mChangeCellGridRequest->mCell.x(), changeCellGrid(mChangeCellGridRequest->mPosition, mChangeCellGridRequest->mCellIndex,
mChangeCellGridRequest->mCell.y(), mChangeCellGridRequest->exteriorWorldspace,
mChangeCellGridRequest->mChangeEvent); mChangeCellGridRequest->mChangeEvent);
mChangeCellGridRequest.reset(); mChangeCellGridRequest.reset();
} }
@ -348,7 +347,8 @@ namespace MWWorld
if (cell->getCell()->isExterior()) if (cell->getCell()->isExterior())
{ {
if (mPhysics->getHeightField(cellX, cellY, cell->getCell()->getWorldSpace()) != nullptr) if (mPhysics->getHeightField(ESM::ExteriorCellIndex(cellX, cellY, cell->getCell()->getWorldSpace()))
!= nullptr)
mNavigator.removeHeightfield(osg::Vec2i(cellX, cellY), navigatorUpdateGuard); mNavigator.removeHeightfield(osg::Vec2i(cellX, cellY), navigatorUpdateGuard);
mPhysics->removeHeightField(cellX, cellY); mPhysics->removeHeightField(cellX, cellY);
@ -394,11 +394,11 @@ namespace MWWorld
const int cellY = cell.getCell()->getGridY(); const int cellY = cell.getCell()->getGridY();
const MWWorld::Cell& cellVariant = *cell.getCell(); const MWWorld::Cell& cellVariant = *cell.getCell();
ESM::RefId worldspace = cellVariant.getWorldSpace(); ESM::RefId worldspace = cellVariant.getWorldSpace();
ESM::ExteriorCellIndex cellIndex(cellX, cellY, worldspace);
if (cellVariant.isExterior()) if (cellVariant.isExterior())
{ {
osg::ref_ptr<const ESMTerrain::LandObject> land osg::ref_ptr<const ESMTerrain::LandObject> land = mRendering.getLandManager()->getLand(cellIndex);
= mRendering.getLandManager()->getLand(cellX, cellY, worldspace);
const ESM::Land::LandData* data = land ? land->getData(ESM::Land::DATA_VHGT) : nullptr; const ESM::Land::LandData* data = land ? land->getData(ESM::Land::DATA_VHGT) : nullptr;
const int verts = ESM::Land::LAND_SIZE; const int verts = ESM::Land::LAND_SIZE;
const int worldsize = ESM::Land::REAL_SIZE; const int worldsize = ESM::Land::REAL_SIZE;
@ -414,7 +414,7 @@ namespace MWWorld
mPhysics->addHeightField(defaultHeight.data(), cellX, cellY, worldsize, verts, mPhysics->addHeightField(defaultHeight.data(), cellX, cellY, worldsize, verts,
ESM::Land::DEFAULT_HEIGHT, ESM::Land::DEFAULT_HEIGHT, land.get()); ESM::Land::DEFAULT_HEIGHT, ESM::Land::DEFAULT_HEIGHT, land.get());
} }
if (const auto heightField = mPhysics->getHeightField(cellX, cellY, worldspace)) if (const auto heightField = mPhysics->getHeightField(cellIndex))
{ {
const osg::Vec2i cellPosition(cellX, cellY); const osg::Vec2i cellPosition(cellX, cellY);
const btVector3& origin = heightField->getCollisionObject()->getWorldTransform().getOrigin(); const btVector3& origin = heightField->getCollisionObject()->getWorldTransform().getOrigin();
@ -469,7 +469,7 @@ namespace MWWorld
if (cellVariant.isExterior()) if (cellVariant.isExterior())
{ {
if (const auto heightField = mPhysics->getHeightField(cellX, cellY, worldspace)) if (const auto heightField = mPhysics->getHeightField(cellIndex))
mNavigator.addWater( mNavigator.addWater(
osg::Vec2i(cellX, cellY), ESM::Land::REAL_SIZE, waterLevel, navigatorUpdateGuard); osg::Vec2i(cellX, cellY), ESM::Land::REAL_SIZE, waterLevel, navigatorUpdateGuard);
} }
@ -537,14 +537,16 @@ namespace MWWorld
void Scene::requestChangeCellGrid(const osg::Vec3f& position, const osg::Vec2i& cell, bool changeEvent) void Scene::requestChangeCellGrid(const osg::Vec3f& position, const osg::Vec2i& cell, bool changeEvent)
{ {
mChangeCellGridRequest mChangeCellGridRequest = ChangeCellGridRequest{ position,
= ChangeCellGridRequest{ position, cell, mCurrentCell->getCell()->getWorldSpace(), changeEvent }; ESM::ExteriorCellIndex(cell.x(), cell.y(), mCurrentCell->getCell()->getWorldSpace()), changeEvent };
} }
void Scene::changeCellGrid( void Scene::changeCellGrid(const osg::Vec3f& pos, ESM::ExteriorCellIndex playerCellIndex, bool changeEvent)
const osg::Vec3f& pos, int playerCellX, int playerCellY, ESM::RefId exteriorWorldspace, bool changeEvent)
{ {
auto navigatorUpdateGuard = mNavigator.makeUpdateGuard(); auto navigatorUpdateGuard = mNavigator.makeUpdateGuard();
int playerCellX = playerCellIndex.mX;
int playerCellY = playerCellIndex.mY;
ESM::RefId exteriorWorldspace = playerCellIndex.mWorldspace;
for (auto iter = mActiveCells.begin(); iter != mActiveCells.end();) for (auto iter = mActiveCells.begin(); iter != mActiveCells.end();)
{ {
@ -560,11 +562,8 @@ namespace MWWorld
unloadCell(cell, navigatorUpdateGuard.get()); unloadCell(cell, navigatorUpdateGuard.get());
} }
mNavigator.setWorldspace( mNavigator.setWorldspace(
Misc::StringUtils::lowerCase(mWorld.getWorldModel() Misc::StringUtils::lowerCase(
.getExterior(playerCellX, playerCellY, exteriorWorldspace) mWorld.getWorldModel().getExterior(playerCellIndex).getCell()->getWorldSpace().serializeText()),
.getCell()
->getWorldSpace()
.serializeText()),
navigatorUpdateGuard.get()); navigatorUpdateGuard.get());
mNavigator.updateBounds(pos, navigatorUpdateGuard.get()); mNavigator.updateBounds(pos, navigatorUpdateGuard.get());
@ -586,9 +585,9 @@ namespace MWWorld
{ {
for (int y = playerCellY - range; y <= playerCellY + range; ++y) for (int y = playerCellY - range; y <= playerCellY + range; ++y)
{ {
if (!isCellInCollection(x, y, exteriorWorldspace, collection)) if (!isCellInCollection(playerCellIndex, collection))
{ {
refsToLoad += mWorld.getWorldModel().getExterior(x, y, exteriorWorldspace).count(); refsToLoad += mWorld.getWorldModel().getExterior(playerCellIndex).count();
cellsPositionsToLoad.emplace_back(x, y); cellsPositionsToLoad.emplace_back(x, y);
} }
} }
@ -620,9 +619,10 @@ namespace MWWorld
for (const auto& [x, y] : cellsPositionsToLoad) for (const auto& [x, y] : cellsPositionsToLoad)
{ {
if (!isCellInCollection(x, y, exteriorWorldspace, mActiveCells)) ESM::ExteriorCellIndex indexToLoad = { x, y, exteriorWorldspace };
if (!isCellInCollection(indexToLoad, mActiveCells))
{ {
CellStore& cell = mWorld.getWorldModel().getExterior(x, y, exteriorWorldspace); CellStore& cell = mWorld.getWorldModel().getExterior(indexToLoad);
loadCell(cell, loadingListener, changeEvent, pos, navigatorUpdateGuard.get()); loadCell(cell, loadingListener, changeEvent, pos, navigatorUpdateGuard.get());
} }
} }
@ -631,7 +631,7 @@ namespace MWWorld
navigatorUpdateGuard.reset(); navigatorUpdateGuard.reset();
CellStore& current = mWorld.getWorldModel().getExterior(playerCellX, playerCellY, exteriorWorldspace); CellStore& current = mWorld.getWorldModel().getExterior(playerCellIndex);
MWBase::Environment::get().getWindowManager()->changeCell(&current); MWBase::Environment::get().getWindowManager()->changeCell(&current);
if (changeEvent) if (changeEvent)
@ -684,8 +684,8 @@ namespace MWWorld
loadingListener->setLabel("#{OMWEngine:TestingExteriorCells} (" + std::to_string(i) + "/" loadingListener->setLabel("#{OMWEngine:TestingExteriorCells} (" + std::to_string(i) + "/"
+ std::to_string(cells.getExtSize()) + ")..."); + std::to_string(cells.getExtSize()) + ")...");
CellStore& cell CellStore& cell = mWorld.getWorldModel().getExterior(
= mWorld.getWorldModel().getExterior(it->mData.mX, it->mData.mY, ESM::Cell::sDefaultWorldspaceId); ESM::ExteriorCellIndex(it->mData.mX, it->mData.mY, ESM::Cell::sDefaultWorldspaceId));
mNavigator.setWorldspace(Misc::StringUtils::lowerCase(cell.getCell()->getWorldSpace().serializeText()), mNavigator.setWorldspace(Misc::StringUtils::lowerCase(cell.getCell()->getWorldSpace().serializeText()),
navigatorUpdateGuard.get()); navigatorUpdateGuard.get());
const osg::Vec3f position const osg::Vec3f position
@ -941,8 +941,8 @@ namespace MWWorld
const osg::Vec2i cellIndex(current.getCell()->getGridX(), current.getCell()->getGridY()); const osg::Vec2i cellIndex(current.getCell()->getGridX(), current.getCell()->getGridY());
changeCellGrid( changeCellGrid(position.asVec3(),
position.asVec3(), cellIndex.x(), cellIndex.y(), current.getCell()->getWorldSpace(), changeEvent); ESM::ExteriorCellIndex(cellIndex.x(), cellIndex.y(), current.getCell()->getWorldSpace()), changeEvent);
changePlayerCell(current, position, adjustPlayerPos); changePlayerCell(current, position, adjustPlayerPos);
@ -1187,8 +1187,8 @@ namespace MWWorld
+ mPreloadDistance; + mPreloadDistance;
if (dist < loadDist) if (dist < loadDist)
preloadCell( preloadCell(mWorld.getWorldModel().getExterior(
mWorld.getWorldModel().getExterior(cellX + dx, cellY + dy, ESM::Cell::sDefaultWorldspaceId)); ESM::ExteriorCellIndex(cellX + dx, cellY + dy, ESM::Cell::sDefaultWorldspaceId)));
} }
} }
} }
@ -1204,8 +1204,8 @@ namespace MWWorld
{ {
for (int dy = -mHalfGridSize; dy <= mHalfGridSize; ++dy) for (int dy = -mHalfGridSize; dy <= mHalfGridSize; ++dy)
{ {
mPreloader->preload( mPreloader->preload(mWorld.getWorldModel().getExterior(
mWorld.getWorldModel().getExterior(x + dx, y + dy, cell.getCell()->getWorldSpace()), ESM::ExteriorCellIndex(x + dx, y + dy, cell.getCell()->getWorldSpace())),
mRendering.getReferenceTime()); mRendering.getReferenceTime());
if (++numpreloaded >= mPreloader->getMaxCacheSize()) if (++numpreloaded >= mPreloader->getMaxCacheSize())
break; break;
@ -1269,8 +1269,8 @@ namespace MWWorld
}; };
void Scene::preloadFastTravelDestinations(const osg::Vec3f& playerPos, const osg::Vec3f& /*predictedPos*/, void Scene::preloadFastTravelDestinations(const osg::Vec3f& playerPos, const osg::Vec3f& /*predictedPos*/,
std::vector<PositionCellGrid>& std::vector<PositionCellGrid>& exteriorPositions) // ignore predictedPos here since opening dialogue with
exteriorPositions) // ignore predictedPos here since opening dialogue with travel service takes extra time // travel service takes extra time
{ {
const MWWorld::ConstPtr player = mWorld.getPlayerPtr(); const MWWorld::ConstPtr player = mWorld.getPlayerPtr();
ListFastTravelDestinationsVisitor listVisitor(mPreloadDistance, player.getRefData().getPosition().asVec3()); ListFastTravelDestinationsVisitor listVisitor(mPreloadDistance, player.getRefData().getPosition().asVec3());
@ -1289,8 +1289,8 @@ namespace MWWorld
{ {
osg::Vec3f pos = dest.mPos.asVec3(); osg::Vec3f pos = dest.mPos.asVec3();
const osg::Vec2i cellIndex = positionToCellIndex(pos.x(), pos.y()); const osg::Vec2i cellIndex = positionToCellIndex(pos.x(), pos.y());
preloadCell( preloadCell(mWorld.getWorldModel().getExterior(
mWorld.getWorldModel().getExterior(cellIndex.x(), cellIndex.y(), ESM::Cell::sDefaultWorldspaceId), ESM::ExteriorCellIndex(cellIndex.x(), cellIndex.y(), ESM::Cell::sDefaultWorldspaceId)),
true); true);
exteriorPositions.emplace_back(pos, gridCenterToBounds(getNewGridCenter(pos))); exteriorPositions.emplace_back(pos, gridCenterToBounds(getNewGridCenter(pos)));
} }

@ -13,6 +13,7 @@
#include <unordered_map> #include <unordered_map>
#include <vector> #include <vector>
#include <components/esm/util.hpp>
#include <components/misc/constants.hpp> #include <components/misc/constants.hpp>
namespace osg namespace osg
@ -79,8 +80,7 @@ namespace MWWorld
struct ChangeCellGridRequest struct ChangeCellGridRequest
{ {
osg::Vec3f mPosition; osg::Vec3f mPosition;
osg::Vec2i mCell; ESM::ExteriorCellIndex mCellIndex;
ESM::RefId exteriorWorldspace;
bool mChangeEvent; bool mChangeEvent;
}; };
@ -118,8 +118,7 @@ namespace MWWorld
osg::Vec2i mCurrentGridCenter; osg::Vec2i mCurrentGridCenter;
// Load and unload cells as necessary to create a cell grid with "X" and "Y" in the center // Load and unload cells as necessary to create a cell grid with "X" and "Y" in the center
void changeCellGrid(const osg::Vec3f& pos, int playerCellX, int playerCellY, ESM::RefId exteriorWorldspace, void changeCellGrid(const osg::Vec3f& pos, ESM::ExteriorCellIndex playerCellIndex, bool changeEvent = true);
bool changeEvent = true);
void requestChangeCellGrid(const osg::Vec3f& position, const osg::Vec2i& cell, bool changeEvent = true); void requestChangeCellGrid(const osg::Vec3f& position, const osg::Vec2i& cell, bool changeEvent = true);

@ -1105,9 +1105,9 @@ namespace MWWorld
return foundCell->second; return foundCell->second;
} }
const ESM4::Cell* Store<ESM4::Cell>::searchExterior(int x, int y, ESM::RefId worldSpace) const const ESM4::Cell* Store<ESM4::Cell>::searchExterior(ESM::ExteriorCellIndex cellIndex) const
{ {
const auto foundCell = mExteriors.find({ x, y, worldSpace }); const auto foundCell = mExteriors.find(cellIndex);
if (foundCell == mExteriors.end()) if (foundCell == mExteriors.end())
return nullptr; return nullptr;
return foundCell->second; return foundCell->second;

@ -289,7 +289,7 @@ namespace MWWorld
public: public:
const ESM4::Cell* searchCellName(std::string_view) const; const ESM4::Cell* searchCellName(std::string_view) const;
const ESM4::Cell* searchExterior(int x, int y, ESM::RefId worldSpace) const; const ESM4::Cell* searchExterior(ESM::ExteriorCellIndex cellIndex) const;
ESM4::Cell* insert(const ESM4::Cell& item, bool overrideOnly = false); ESM4::Cell* insert(const ESM4::Cell& item, bool overrideOnly = false);
ESM4::Cell* insertStatic(const ESM4::Cell& item); ESM4::Cell* insertStatic(const ESM4::Cell& item);
void clearDynamic() override; void clearDynamic() override;

@ -353,9 +353,10 @@ namespace MWWorld
if (bypass && !mStartCell.empty()) if (bypass && !mStartCell.empty())
{ {
ESM::Position pos; ESM::Position pos;
if (!findExteriorPosition(mStartCell, pos).empty()) ESM::RefId cellId = findExteriorPosition(mStartCell, pos);
if (!cellId.empty())
{ {
changeToExteriorCell(pos, true); changeToCell(cellId, pos, true);
adjustPosition(getPlayerPtr(), false); adjustPosition(getPlayerPtr(), false);
} }
else else
@ -967,25 +968,6 @@ namespace MWWorld
mRendering->getCamera()->instantTransition(); mRendering->getCamera()->instantTransition();
} }
void World::changeToExteriorCell(const ESM::Position& position, bool adjustPlayerPos, bool changeEvent)
{
mPhysics->clearQueuedMovement();
mDiscardMovements = true;
if (changeEvent && mCurrentWorldSpace != ESM::Cell::sDefaultWorldspace)
{
// changed worldspace
mProjectileManager->clear();
mRendering->notifyWorldSpaceChanged();
}
removeContainerScripts(getPlayerPtr());
osg::Vec2i exteriorCellPos = positionToCellIndex(position.pos[0], position.pos[1]);
ESM::RefId cellId = ESM::RefId::esm3ExteriorCell(exteriorCellPos.x(), exteriorCellPos.y());
mWorldScene->changeToExteriorCell(cellId, position, adjustPlayerPos, changeEvent);
addContainerScripts(getPlayerPtr(), getPlayerPtr().getCell());
mRendering->getCamera()->instantTransition();
}
void World::changeToCell( void World::changeToCell(
const ESM::RefId& cellId, const ESM::Position& position, bool adjustPlayerPos, bool changeEvent) const ESM::RefId& cellId, const ESM::Position& position, bool adjustPlayerPos, bool changeEvent)
{ {
@ -1268,8 +1250,9 @@ namespace MWWorld
CellStore* cell = ptr.getCell(); CellStore* cell = ptr.getCell();
ESM::RefId worldspaceId ESM::RefId worldspaceId
= cell->isExterior() ? cell->getCell()->getWorldSpace() : ESM::Cell::sDefaultWorldspaceId; = cell->isExterior() ? cell->getCell()->getWorldSpace() : ESM::Cell::sDefaultWorldspaceId;
CellStore* newCell CellStore* newCell = cell->isExterior()
= cell->isExterior() ? &mWorldModel.getExterior(index.x(), index.y(), worldspaceId) : nullptr; ? &mWorldModel.getExterior(ESM::ExteriorCellIndex(index.x(), index.y(), worldspaceId))
: nullptr;
bool isCellActive = getPlayerPtr().isInCell() && getPlayerPtr().getCell()->isExterior() bool isCellActive = getPlayerPtr().isInCell() && getPlayerPtr().getCell()->isExterior()
&& (newCell && mWorldScene->isCellActive(*newCell)); && (newCell && mWorldScene->isCellActive(*newCell));
@ -2072,7 +2055,8 @@ namespace MWWorld
if (cell->isExterior()) if (cell->isExterior())
{ {
const osg::Vec2i index = positionToCellIndex(pos.pos[0], pos.pos[1]); const osg::Vec2i index = positionToCellIndex(pos.pos[0], pos.pos[1]);
cell = &mWorldModel.getExterior(index.x(), index.y(), cell->getCell()->getWorldSpace()); cell = &mWorldModel.getExterior(
ESM::ExteriorCellIndex(index.x(), index.y(), cell->getCell()->getWorldSpace()));
} }
MWWorld::Ptr dropped = object.getClass().copyToCell(object, *cell, pos, count); MWWorld::Ptr dropped = object.getClass().copyToCell(object, *cell, pos, count);
@ -2756,7 +2740,8 @@ namespace MWWorld
if (xResult.ec == std::errc::result_out_of_range || yResult.ec == std::errc::result_out_of_range) if (xResult.ec == std::errc::result_out_of_range || yResult.ec == std::errc::result_out_of_range)
throw std::runtime_error("Cell coordinates out of range."); throw std::runtime_error("Cell coordinates out of range.");
else if (xResult.ec == std::errc{} && yResult.ec == std::errc{}) else if (xResult.ec == std::errc{} && yResult.ec == std::errc{})
ext = mWorldModel.getExterior(x, y, ESM::Cell::sDefaultWorldspaceId).getCell(); ext = mWorldModel.getExterior(ESM::ExteriorCellIndex(x, y, ESM::Cell::sDefaultWorldspaceId))
.getCell();
// ignore std::errc::invalid_argument, as this means that name probably refers to a interior cell // ignore std::errc::invalid_argument, as this means that name probably refers to a interior cell
// instead of comma separated coordinates // instead of comma separated coordinates
} }

@ -345,11 +345,6 @@ namespace MWWorld
///< Move to interior cell. ///< Move to interior cell.
///< @param changeEvent If false, do not trigger cell change flag or detect worldspace changes ///< @param changeEvent If false, do not trigger cell change flag or detect worldspace changes
void changeToExteriorCell(
const ESM::Position& position, bool adjustPlayerPos, bool changeEvent = true) override;
///< Move to exterior cell.
///< @param changeEvent If false, do not trigger cell change flag or detect worldspace changes
void changeToCell(const ESM::RefId& cellId, const ESM::Position& position, bool adjustPlayerPos, void changeToCell(const ESM::RefId& cellId, const ESM::Position& position, bool adjustPlayerPos,
bool changeEvent = true) override; bool changeEvent = true) override;
///< @param changeEvent If false, do not trigger cell change flag or detect worldspace changes ///< @param changeEvent If false, do not trigger cell change flag or detect worldspace changes

@ -161,26 +161,25 @@ MWWorld::WorldModel::WorldModel(const MWWorld::ESMStore& store, ESM::ReadersCach
{ {
} }
MWWorld::CellStore& MWWorld::WorldModel::getExterior(int x, int y, ESM::RefId exteriorWorldspace) MWWorld::CellStore& MWWorld::WorldModel::getExterior(ESM::ExteriorCellIndex cellIndex)
{ {
std::map<ESM::ExteriorCellIndex, CellStore*>::iterator result; std::map<ESM::ExteriorCellIndex, CellStore*>::iterator result;
ESM::ExteriorCellIndex extIndex = { x, y, exteriorWorldspace };
result = mExteriors.find({ x, y, exteriorWorldspace }); result = mExteriors.find(cellIndex);
if (result == mExteriors.end()) if (result == mExteriors.end())
{ {
if (exteriorWorldspace == ESM::Cell::sDefaultWorldspaceId) if (cellIndex.mWorldspace == ESM::Cell::sDefaultWorldspaceId)
{ {
const ESM::Cell* cell = mStore.get<ESM::Cell>().search(x, y); const ESM::Cell* cell = mStore.get<ESM::Cell>().search(cellIndex.mX, cellIndex.mY);
if (!cell) if (!cell)
{ {
// Cell isn't predefined. Make one on the fly. // Cell isn't predefined. Make one on the fly.
ESM::Cell record; ESM::Cell record;
record.mData.mFlags = ESM::Cell::HasWater; record.mData.mFlags = ESM::Cell::HasWater;
record.mData.mX = x; record.mData.mX = cellIndex.mX;
record.mData.mY = y; record.mData.mY = cellIndex.mY;
record.mWater = 0; record.mWater = 0;
record.mMapColor = 0; record.mMapColor = 0;
record.updateId(); record.updateId();
@ -190,31 +189,31 @@ MWWorld::CellStore& MWWorld::WorldModel::getExterior(int x, int y, ESM::RefId ex
CellStore* cellStore CellStore* cellStore
= &mCells.emplace(cell->mId, CellStore(MWWorld::Cell(*cell), mStore, mReaders)).first->second; = &mCells.emplace(cell->mId, CellStore(MWWorld::Cell(*cell), mStore, mReaders)).first->second;
result = mExteriors.emplace(extIndex, cellStore).first; result = mExteriors.emplace(cellIndex, cellStore).first;
} }
else else
{ {
const Store<ESM4::Cell>& cell4Store = mStore.get<ESM4::Cell>(); const Store<ESM4::Cell>& cell4Store = mStore.get<ESM4::Cell>();
bool exteriorExists = mStore.get<ESM4::World>().search(exteriorWorldspace); bool exteriorExists = mStore.get<ESM4::World>().search(cellIndex.mWorldspace);
const ESM4::Cell* cell = cell4Store.searchExterior(x, y, exteriorWorldspace); const ESM4::Cell* cell = cell4Store.searchExterior(cellIndex);
if (exteriorExists) if (exteriorExists)
{ {
if (!cell) if (!cell)
{ {
ESM4::Cell record; ESM4::Cell record;
record.mParent = exteriorWorldspace; record.mParent = cellIndex.mWorldspace;
record.mX = x; record.mX = cellIndex.mX;
record.mY = y; record.mY = cellIndex.mY;
record.mCellFlags = !ESM4::CELL_Interior; record.mCellFlags = !ESM4::CELL_Interior;
cell = MWBase::Environment::get().getESMStore()->insert(record); cell = MWBase::Environment::get().getESMStore()->insert(record);
} }
CellStore* cellStore CellStore* cellStore
= &mCells.emplace(cell->mId, CellStore(MWWorld::Cell(*cell), mStore, mReaders)).first->second; = &mCells.emplace(cell->mId, CellStore(MWWorld::Cell(*cell), mStore, mReaders)).first->second;
result = mExteriors.emplace(extIndex, cellStore).first; result = mExteriors.emplace(cellIndex, cellStore).first;
} }
else else
{ {
throw std::runtime_error("exterior not found: '" + exteriorWorldspace.toDebugString() + "'"); throw std::runtime_error("exterior not found: '" + cellIndex.mWorldspace.toDebugString() + "'");
} }
} }
} }
@ -263,7 +262,8 @@ MWWorld::CellStore& MWWorld::WorldModel::getCell(const ESM::RefId& id)
return result->second; return result->second;
if (const auto* exteriorId = id.getIf<ESM::ESM3ExteriorCellRefId>()) if (const auto* exteriorId = id.getIf<ESM::ESM3ExteriorCellRefId>())
return getExterior(exteriorId->getX(), exteriorId->getY(), ESM::Cell::sDefaultWorldspaceId); return getExterior(
ESM::ExteriorCellIndex(exteriorId->getX(), exteriorId->getY(), ESM::Cell::sDefaultWorldspaceId));
const ESM4::Cell* cell4 = mStore.get<ESM4::Cell>().search(id); const ESM4::Cell* cell4 = mStore.get<ESM4::Cell>().search(id);
CellStore* newCellStore = nullptr; CellStore* newCellStore = nullptr;
@ -325,7 +325,7 @@ MWWorld::CellStore& MWWorld::WorldModel::getCell(std::string_view name)
if (!cell) if (!cell)
throw std::runtime_error(std::string("Can't find cell with name ") + std::string(name)); throw std::runtime_error(std::string("Can't find cell with name ") + std::string(name));
return getExterior(cell->getGridX(), cell->getGridY(), ESM::Cell::sDefaultWorldspaceId); return getExterior(ESM::ExteriorCellIndex(cell->getGridX(), cell->getGridY(), ESM::Cell::sDefaultWorldspaceId));
} }
MWWorld::CellStore& MWWorld::WorldModel::getCellByPosition( MWWorld::CellStore& MWWorld::WorldModel::getCellByPosition(
@ -336,7 +336,7 @@ MWWorld::CellStore& MWWorld::WorldModel::getCellByPosition(
const osg::Vec2i cellIndex = positionToCellIndex(pos.x(), pos.y()); const osg::Vec2i cellIndex = positionToCellIndex(pos.x(), pos.y());
ESM::RefId exteriorWorldspace ESM::RefId exteriorWorldspace
= cellInSameWorldSpace ? cellInSameWorldSpace->getCell()->getWorldSpace() : ESM::Cell::sDefaultWorldspaceId; = cellInSameWorldSpace ? cellInSameWorldSpace->getCell()->getWorldSpace() : ESM::Cell::sDefaultWorldspaceId;
return getExterior(cellIndex.x(), cellIndex.y(), exteriorWorldspace); return getExterior(ESM::ExteriorCellIndex(cellIndex.x(), cellIndex.y(), exteriorWorldspace));
} }
MWWorld::Ptr MWWorld::WorldModel::getPtr(const ESM::RefId& name, CellStore& cell) MWWorld::Ptr MWWorld::WorldModel::getPtr(const ESM::RefId& name, CellStore& cell)

@ -65,7 +65,7 @@ namespace MWWorld
void clear(); void clear();
CellStore& getExterior(int x, int y, ESM::RefId exteriorWorldSpace); CellStore& getExterior(ESM::ExteriorCellIndex cellIndex);
CellStore& getInterior(std::string_view name); CellStore& getInterior(std::string_view name);
CellStore& getCell(std::string_view name); // interior or named exterior CellStore& getCell(std::string_view name); // interior or named exterior
CellStore& getCell(const ESM::RefId& Id); CellStore& getCell(const ESM::RefId& Id);

@ -49,6 +49,13 @@ namespace ESM
int mX, mY; int mX, mY;
ESM::RefId mWorldspace; ESM::RefId mWorldspace;
ExteriorCellIndex(int x, int y, ESM::RefId worldspace)
: mX(x)
, mY(y)
, mWorldspace(worldspace)
{
}
bool operator==(const ExteriorCellIndex& other) const bool operator==(const ExteriorCellIndex& other) const
{ {
return mX == other.mX && mY == other.mY && mWorldspace == other.mWorldspace; return mX == other.mX && mY == other.mY && mWorldspace == other.mWorldspace;

Loading…
Cancel
Save