1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-02-25 12:41:01 +00:00

Merge branch 'cellstore_optimize' into 'master'

Optimize CellStore modifications

See merge request OpenMW/openmw!3013
This commit is contained in:
psi29a 2023-05-11 07:09:52 +00:00
commit 42bf639916
3 changed files with 30 additions and 47 deletions

View File

@ -430,7 +430,7 @@ namespace MWWorld
{ {
mMovedHere.insert(std::make_pair(object.getBase(), from)); mMovedHere.insert(std::make_pair(object.getBase(), from));
} }
updateMergedRefs(); requestMergedRefsUpdate();
} }
MWWorld::Ptr CellStore::moveTo(const Ptr& object, CellStore* cellToMoveTo) MWWorld::Ptr CellStore::moveTo(const Ptr& object, CellStore* cellToMoveTo)
@ -443,10 +443,6 @@ namespace MWWorld
throw std::runtime_error( throw std::runtime_error(
"moveTo: can't move object from a non-loaded cell (how did you get this object anyway?)"); "moveTo: can't move object from a non-loaded cell (how did you get this object anyway?)");
// Ensure that the object actually exists in the cell
if (searchViaRefNum(object.getCellRef().getRefNum()).isEmpty())
throw std::runtime_error("moveTo: object is not in this cell");
MWBase::Environment::get().getWorldModel()->registerPtr(MWWorld::Ptr(object.getBase(), cellToMoveTo)); MWBase::Environment::get().getWorldModel()->registerPtr(MWWorld::Ptr(object.getBase(), cellToMoveTo));
MovedRefTracker::iterator found = mMovedHere.find(object.getBase()); MovedRefTracker::iterator found = mMovedHere.find(object.getBase());
@ -466,14 +462,14 @@ namespace MWWorld
originalCell->moveTo(object, cellToMoveTo); originalCell->moveTo(object, cellToMoveTo);
} }
updateMergedRefs(); requestMergedRefsUpdate();
return MWWorld::Ptr(object.getBase(), cellToMoveTo); return MWWorld::Ptr(object.getBase(), cellToMoveTo);
} }
cellToMoveTo->moveFrom(object, this); cellToMoveTo->moveFrom(object, this);
mMovedToAnotherCell.insert(std::make_pair(object.getBase(), cellToMoveTo)); mMovedToAnotherCell.insert(std::make_pair(object.getBase(), cellToMoveTo));
updateMergedRefs(); requestMergedRefsUpdate();
MWWorld::Ptr ptr(object.getBase(), cellToMoveTo); MWWorld::Ptr ptr(object.getBase(), cellToMoveTo);
const Class& cls = ptr.getClass(); const Class& cls = ptr.getClass();
if (cls.hasInventoryStore(ptr)) if (cls.hasInventoryStore(ptr))
@ -513,13 +509,19 @@ namespace MWWorld
const std::map<LiveCellRefBase*, MWWorld::CellStore*>& mMovedToAnotherCell; const std::map<LiveCellRefBase*, MWWorld::CellStore*>& mMovedToAnotherCell;
}; };
void CellStore::updateMergedRefs() void CellStore::requestMergedRefsUpdate()
{
mRechargingItemsUpToDate = false;
mMergedRefsNeedsUpdate = true;
}
void CellStore::updateMergedRefs() const
{ {
mMergedRefs.clear(); mMergedRefs.clear();
mRechargingItemsUpToDate = false;
MergeVisitor visitor(mMergedRefs, mMovedHere, mMovedToAnotherCell); MergeVisitor visitor(mMergedRefs, mMovedHere, mMovedToAnotherCell);
CellStoreImp::forEachInternal(visitor, *this); CellStoreImp::forEachInternal(visitor, const_cast<CellStore&>(*this));
visitor.merge(); visitor.merge();
mMergedRefsNeedsUpdate = false;
} }
bool CellStore::movedHere(const MWWorld::Ptr& ptr) const bool CellStore::movedHere(const MWWorld::Ptr& ptr) const
@ -659,13 +661,6 @@ namespace MWWorld
} }
}; };
Ptr CellStore::searchViaRefNum(const ESM::RefNum& refNum)
{
RefNumSearchVisitor searchVisitor(refNum);
forEach(searchVisitor);
return searchVisitor.mFound;
}
float CellStore::getWaterLevel() const float CellStore::getWaterLevel() const
{ {
if (isExterior()) if (isExterior())
@ -681,6 +676,8 @@ namespace MWWorld
std::size_t CellStore::count() const std::size_t CellStore::count() const
{ {
if (mMergedRefsNeedsUpdate)
updateMergedRefs();
return mMergedRefs.size(); return mMergedRefs.size();
} }
@ -847,7 +844,7 @@ namespace MWWorld
ESM::visit([&](auto&& cell) { loadRefs(cell, refNumToID); }, mCellVariant); ESM::visit([&](auto&& cell) { loadRefs(cell, refNumToID); }, mCellVariant);
updateMergedRefs(); requestMergedRefsUpdate();
} }
bool CellStore::isExterior() const bool CellStore::isExterior() const
@ -1033,10 +1030,6 @@ namespace MWWorld
} }
} }
// Do another update here to make sure objects referred to by MVRF tags can be found
// This update is only needed for old saves that used the old copy&delete way of moving objects
updateMergedRefs();
while (reader.isNextSub("MVRF")) while (reader.isNextSub("MVRF"))
{ {
reader.cacheSubName(); reader.cacheSubName();
@ -1050,7 +1043,7 @@ namespace MWWorld
} }
// Search for the reference. It might no longer exist if its content file was removed. // Search for the reference. It might no longer exist if its content file was removed.
Ptr movedRef = searchViaRefNum(refnum); Ptr movedRef = MWBase::Environment::get().getWorldModel()->getPtr(refnum);
if (movedRef.isEmpty()) if (movedRef.isEmpty())
{ {
Log(Debug::Warning) << "Warning: Dropping moved ref tag for " << refnum.mIndex Log(Debug::Warning) << "Warning: Dropping moved ref tag for " << refnum.mIndex

View File

@ -128,7 +128,7 @@ namespace MWWorld
mHasState = true; mHasState = true;
CellRefList<T>& list = get<T>(); CellRefList<T>& list = get<T>();
LiveCellRefBase* ret = &list.insert(*ref); LiveCellRefBase* ret = &list.insert(*ref);
updateMergedRefs(); requestMergedRefsUpdate();
return ret; return ret;
} }
@ -166,11 +166,6 @@ namespace MWWorld
Ptr searchViaActorId(int id); Ptr searchViaActorId(int id);
///< Will return an empty Ptr if cell is not loaded. ///< Will return an empty Ptr if cell is not loaded.
Ptr searchViaRefNum(const ESM::RefNum& refNum);
///< Will return an empty Ptr if cell is not loaded. Does not check references in
/// containers.
/// @note Triggers CellStore hasState flag.
float getWaterLevel() const; float getWaterLevel() const;
bool movedHere(const MWWorld::Ptr& ptr) const; bool movedHere(const MWWorld::Ptr& ptr) const;
@ -203,6 +198,8 @@ namespace MWWorld
if (mState != State_Loaded) if (mState != State_Loaded)
return false; return false;
if (mMergedRefsNeedsUpdate)
updateMergedRefs();
if (mMergedRefs.empty()) if (mMergedRefs.empty())
return true; return true;
@ -230,6 +227,9 @@ namespace MWWorld
if (mState != State_Loaded) if (mState != State_Loaded)
return false; return false;
if (mMergedRefsNeedsUpdate)
updateMergedRefs();
for (unsigned int i = 0; i < mMergedRefs.size(); ++i) for (unsigned int i = 0; i < mMergedRefs.size(); ++i)
{ {
if (!isAccessible(mMergedRefs[i]->mData, mMergedRefs[i]->mRef)) if (!isAccessible(mMergedRefs[i]->mData, mMergedRefs[i]->mRef))
@ -252,6 +252,8 @@ namespace MWWorld
if (mState != State_Loaded) if (mState != State_Loaded)
return false; return false;
if (mMergedRefsNeedsUpdate)
updateMergedRefs();
if (mMergedRefs.empty()) if (mMergedRefs.empty())
return true; return true;
@ -373,7 +375,8 @@ namespace MWWorld
// Merged list of ref's currently in this cell - i.e. with added refs from mMovedHere, removed refs from // Merged list of ref's currently in this cell - i.e. with added refs from mMovedHere, removed refs from
// mMovedToAnotherCell // mMovedToAnotherCell
std::vector<LiveCellRefBase*> mMergedRefs; mutable std::vector<LiveCellRefBase*> mMergedRefs;
mutable bool mMergedRefsNeedsUpdate = false;
// Get the Ptr for the given ref which originated from this cell (possibly moved to another cell at this point). // Get the Ptr for the given ref which originated from this cell (possibly moved to another cell at this point).
Ptr getCurrentPtr(MWWorld::LiveCellRefBase* ref); Ptr getCurrentPtr(MWWorld::LiveCellRefBase* ref);
@ -382,7 +385,8 @@ namespace MWWorld
void moveFrom(const MWWorld::Ptr& object, MWWorld::CellStore* from); void moveFrom(const MWWorld::Ptr& object, MWWorld::CellStore* from);
/// Repopulate mMergedRefs. /// Repopulate mMergedRefs.
void updateMergedRefs(); void requestMergedRefsUpdate();
void updateMergedRefs() const;
// (item, max charge) // (item, max charge)
typedef std::vector<std::pair<LiveCellRefBase*, float>> TRechargingItems; typedef std::vector<std::pair<LiveCellRefBase*, float>> TRechargingItems;

View File

@ -1880,14 +1880,7 @@ namespace MWWorld
facedObject = rayToObject.mHitObject; facedObject = rayToObject.mHitObject;
if (facedObject.isEmpty() && rayToObject.mHitRefnum.isSet()) if (facedObject.isEmpty() && rayToObject.mHitRefnum.isSet())
{ facedObject = MWBase::Environment::get().getWorldModel()->getPtr(rayToObject.mHitRefnum);
for (CellStore* cellstore : mWorldScene->getActiveCells())
{
facedObject = cellstore->searchViaRefNum(rayToObject.mHitRefnum);
if (!facedObject.isEmpty())
break;
}
}
if (rayToObject.mHit) if (rayToObject.mHit)
mDistanceToFacedObject = (rayToObject.mRatio * maxDistance) - camDist; mDistanceToFacedObject = (rayToObject.mRatio * maxDistance) - camDist;
else else
@ -1904,14 +1897,7 @@ namespace MWWorld
res.mHitNormal = rayRes.mHitNormalWorld; res.mHitNormal = rayRes.mHitNormalWorld;
res.mHitObject = rayRes.mHitObject; res.mHitObject = rayRes.mHitObject;
if (res.mHitObject.isEmpty() && rayRes.mHitRefnum.isSet()) if (res.mHitObject.isEmpty() && rayRes.mHitRefnum.isSet())
{ res.mHitObject = MWBase::Environment::get().getWorldModel()->getPtr(rayRes.mHitRefnum);
for (CellStore* cellstore : mWorldScene->getActiveCells())
{
res.mHitObject = cellstore->searchViaRefNum(rayRes.mHitRefnum);
if (!res.mHitObject.isEmpty())
break;
}
}
return res.mHit; return res.mHit;
} }