mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-25 15:35:23 +00:00
Use std::list to store mechanics objects
To make the order of elements deterministic. Using memory address based objects as map key makes order of elements there nondeterministic. Later it can be replaced with vector when there are no indirect munipulations with container inside iteration loops. Change map key to const MWWorld::LiveCellRefBase* to avoid erasing and inserting elements on MWWorld::Ptr update. Store CharacterController by value instead of pointer to avoid redundant memory allocation.
This commit is contained in:
parent
b9b4f1c3c2
commit
ce3bba0cdc
@ -241,6 +241,8 @@ public:
|
||||
CharacterController(const MWWorld::Ptr &ptr, MWRender::Animation *anim);
|
||||
virtual ~CharacterController();
|
||||
|
||||
const MWWorld::Ptr& getPtr() const { return mPtr; };
|
||||
|
||||
void handleTextKey(const std::string &groupname, SceneUtil::TextKeyMap::ConstIterator key, const SceneUtil::TextKeyMap& map) override;
|
||||
|
||||
// Be careful when to call this, see comment in Actors
|
||||
|
@ -13,55 +13,43 @@
|
||||
namespace MWMechanics
|
||||
{
|
||||
|
||||
Objects::~Objects()
|
||||
{
|
||||
for(auto& object : mObjects)
|
||||
{
|
||||
delete object.second;
|
||||
object.second = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void Objects::addObject(const MWWorld::Ptr& ptr)
|
||||
{
|
||||
removeObject(ptr);
|
||||
|
||||
MWRender::Animation *anim = MWBase::Environment::get().getWorld()->getAnimation(ptr);
|
||||
if(anim) mObjects.insert(std::make_pair(ptr, new CharacterController(ptr, anim)));
|
||||
if (anim == nullptr)
|
||||
return;
|
||||
|
||||
const auto it = mObjects.emplace(mObjects.end(), ptr, anim);
|
||||
mIndex.emplace(ptr.getBase(), it);
|
||||
}
|
||||
|
||||
void Objects::removeObject(const MWWorld::Ptr& ptr)
|
||||
{
|
||||
PtrControllerMap::iterator iter = mObjects.find(ptr);
|
||||
if(iter != mObjects.end())
|
||||
const auto iter = mIndex.find(ptr.getBase());
|
||||
if (iter != mIndex.end())
|
||||
{
|
||||
delete iter->second;
|
||||
mObjects.erase(iter);
|
||||
mObjects.erase(iter->second);
|
||||
mIndex.erase(iter);
|
||||
}
|
||||
}
|
||||
|
||||
void Objects::updateObject(const MWWorld::Ptr &old, const MWWorld::Ptr &ptr)
|
||||
{
|
||||
PtrControllerMap::iterator iter = mObjects.find(old);
|
||||
if(iter != mObjects.end())
|
||||
{
|
||||
CharacterController *ctrl = iter->second;
|
||||
mObjects.erase(iter);
|
||||
|
||||
ctrl->updatePtr(ptr);
|
||||
mObjects.insert(std::make_pair(ptr, ctrl));
|
||||
}
|
||||
const auto iter = mIndex.find(old.getBase());
|
||||
if (iter != mIndex.end())
|
||||
iter->second->updatePtr(ptr);
|
||||
}
|
||||
|
||||
void Objects::dropObjects (const MWWorld::CellStore *cellStore)
|
||||
{
|
||||
PtrControllerMap::iterator iter = mObjects.begin();
|
||||
while(iter != mObjects.end())
|
||||
for (auto iter = mObjects.begin(); iter != mObjects.end();)
|
||||
{
|
||||
if(iter->first.getCell()==cellStore)
|
||||
if (iter->getPtr().getCell() == cellStore)
|
||||
{
|
||||
delete iter->second;
|
||||
mObjects.erase(iter++);
|
||||
mIndex.erase(iter->getPtr().getBase());
|
||||
iter = mObjects.erase(iter);
|
||||
}
|
||||
else
|
||||
++iter;
|
||||
@ -72,8 +60,8 @@ void Objects::update(float duration, bool paused)
|
||||
{
|
||||
if(!paused)
|
||||
{
|
||||
for(auto& object : mObjects)
|
||||
object.second->update(duration);
|
||||
for (CharacterController& object : mObjects)
|
||||
object.update(duration);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -82,15 +70,15 @@ void Objects::update(float duration, bool paused)
|
||||
if(mode != MWGui::GM_Container)
|
||||
return;
|
||||
|
||||
for(auto& object : mObjects)
|
||||
for (CharacterController& object : mObjects)
|
||||
{
|
||||
if (object.first.getType() != ESM::Container::sRecordId)
|
||||
if (object.getPtr().getType() != ESM::Container::sRecordId)
|
||||
continue;
|
||||
|
||||
if (object.second->isAnimPlaying("containeropen"))
|
||||
if (object.isAnimPlaying("containeropen"))
|
||||
{
|
||||
object.second->update(duration);
|
||||
MWBase::Environment::get().getWorld()->updateAnimatedCollisionShape(object.first);
|
||||
object.update(duration);
|
||||
MWBase::Environment::get().getWorld()->updateAnimatedCollisionShape(object.getPtr());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -98,23 +86,23 @@ void Objects::update(float duration, bool paused)
|
||||
|
||||
bool Objects::onOpen(const MWWorld::Ptr& ptr)
|
||||
{
|
||||
PtrControllerMap::iterator iter = mObjects.find(ptr);
|
||||
if(iter != mObjects.end())
|
||||
const auto iter = mIndex.find(ptr.getBase());
|
||||
if (iter != mIndex.end())
|
||||
return iter->second->onOpen();
|
||||
return true;
|
||||
}
|
||||
|
||||
void Objects::onClose(const MWWorld::Ptr& ptr)
|
||||
{
|
||||
PtrControllerMap::iterator iter = mObjects.find(ptr);
|
||||
if(iter != mObjects.end())
|
||||
const auto iter = mIndex.find(ptr.getBase());
|
||||
if (iter != mIndex.end())
|
||||
iter->second->onClose();
|
||||
}
|
||||
|
||||
bool Objects::playAnimationGroup(const MWWorld::Ptr& ptr, const std::string& groupName, int mode, int number, bool persist)
|
||||
{
|
||||
PtrControllerMap::iterator iter = mObjects.find(ptr);
|
||||
if(iter != mObjects.end())
|
||||
const auto iter = mIndex.find(ptr.getBase());
|
||||
if (iter != mIndex.end())
|
||||
{
|
||||
return iter->second->playGroup(groupName, mode, number, persist);
|
||||
}
|
||||
@ -126,24 +114,22 @@ bool Objects::playAnimationGroup(const MWWorld::Ptr& ptr, const std::string& gro
|
||||
}
|
||||
void Objects::skipAnimation(const MWWorld::Ptr& ptr)
|
||||
{
|
||||
PtrControllerMap::iterator iter = mObjects.find(ptr);
|
||||
if(iter != mObjects.end())
|
||||
const auto iter = mIndex.find(ptr.getBase());
|
||||
if (iter != mIndex.end())
|
||||
iter->second->skipAnim();
|
||||
}
|
||||
|
||||
void Objects::persistAnimationStates()
|
||||
{
|
||||
for (PtrControllerMap::iterator iter = mObjects.begin(); iter != mObjects.end(); ++iter)
|
||||
iter->second->persistAnimationState();
|
||||
for (CharacterController& object : mObjects)
|
||||
object.persistAnimationState();
|
||||
}
|
||||
|
||||
void Objects::getObjectsInRange(const osg::Vec3f& position, float radius, std::vector<MWWorld::Ptr>& out)
|
||||
void Objects::getObjectsInRange(const osg::Vec3f& position, float radius, std::vector<MWWorld::Ptr>& out) const
|
||||
{
|
||||
for (PtrControllerMap::iterator iter = mObjects.begin(); iter != mObjects.end(); ++iter)
|
||||
{
|
||||
if ((position - iter->first.getRefData().getPosition().asVec3()).length2() <= radius*radius)
|
||||
out.push_back(iter->first);
|
||||
}
|
||||
for (const CharacterController& object : mObjects)
|
||||
if ((position - object.getPtr().getRefData().getPosition().asVec3()).length2() <= radius * radius)
|
||||
out.push_back(object.getPtr());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,9 +1,12 @@
|
||||
#ifndef GAME_MWMECHANICS_ACTIVATORS_H
|
||||
#define GAME_MWMECHANICS_ACTIVATORS_H
|
||||
|
||||
#include "character.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
|
||||
namespace osg
|
||||
{
|
||||
@ -18,17 +21,12 @@ namespace MWWorld
|
||||
|
||||
namespace MWMechanics
|
||||
{
|
||||
class CharacterController;
|
||||
|
||||
class Objects
|
||||
{
|
||||
typedef std::map<MWWorld::Ptr,CharacterController*> PtrControllerMap;
|
||||
PtrControllerMap mObjects;
|
||||
std::list<CharacterController> mObjects;
|
||||
std::map<const MWWorld::LiveCellRefBase*, std::list<CharacterController>::iterator> mIndex;
|
||||
|
||||
public:
|
||||
Objects() = default;
|
||||
~Objects();
|
||||
|
||||
void addObject (const MWWorld::Ptr& ptr);
|
||||
///< Register an animated object
|
||||
|
||||
@ -51,7 +49,7 @@ namespace MWMechanics
|
||||
void skipAnimation(const MWWorld::Ptr& ptr);
|
||||
void persistAnimationStates();
|
||||
|
||||
void getObjectsInRange (const osg::Vec3f& position, float radius, std::vector<MWWorld::Ptr>& out);
|
||||
void getObjectsInRange(const osg::Vec3f& position, float radius, std::vector<MWWorld::Ptr>& out) const;
|
||||
|
||||
std::size_t size() const
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user