handle physics during player changing cells

actorid
Marc Zinnschlag 14 years ago
parent 5486c70edf
commit 6a14ea8ec3

@ -145,6 +145,7 @@ set(GAMEWORLD_HEADER
mwworld/containerutil.hpp
mwworld/player.hpp
mwworld/doingphysics.hpp
mwworld/cellfunctors.hpp
)
source_group(apps\\openmw\\mwworld FILES ${GAMEWORLD} ${GAMEWORLD_HEADER})

@ -0,0 +1,31 @@
#ifndef GAME_MWWORLD_CELLFUNCTORS_H
#define GAME_MWWORLD_CELLFUNCTORS_H
#include <vector>
#include <string>
#include "refdata.hpp"
namespace ESM
{
class CellRef;
}
namespace MWWorld
{
/// List all (Ogre-)handles.
struct ListHandles
{
std::vector<std::string> mHandles;
bool operator() (ESM::CellRef& ref, RefData& data)
{
std::string handle = data.getHandle();
if (!handle.empty())
mHandles.push_back (handle);
return true;
}
};
}
#endif

@ -4,6 +4,7 @@
namespace MWWorld
{
int DoingPhysics::sCounter = 0;
int DoingPhysics::sSuppress = 0;
DoingPhysics::DoingPhysics()
{
@ -17,6 +18,16 @@ namespace MWWorld
bool DoingPhysics::isDoingPhysics()
{
return sCounter>0;
return sCounter>0 || sSuppress>0;
}
SuppressDoingPhysics::SuppressDoingPhysics()
{
++DoingPhysics::sSuppress;
}
SuppressDoingPhysics::~SuppressDoingPhysics()
{
--DoingPhysics::sSuppress;
}
}

@ -3,10 +3,13 @@
namespace MWWorld
{
///< Scope guard for blocking physics updates during physics simulation.
class SuppressDoingPhysics;
/// Scope guard for blocking physics updates during physics simulation.
class DoingPhysics
{
static int sCounter;
static int sSuppress;
private:
@ -20,6 +23,23 @@ namespace MWWorld
~DoingPhysics();
static bool isDoingPhysics();
friend class SuppressDoingPhysics;
};
/// Scope guard for temporarily lifting the block issues by DoingPhysics
class SuppressDoingPhysics
{
private:
SuppressDoingPhysics (const SuppressDoingPhysics&);
SuppressDoingPhysics& operator= (const SuppressDoingPhysics&);
public:
SuppressDoingPhysics();
~SuppressDoingPhysics();
};
}

@ -22,6 +22,7 @@
#include "refdata.hpp"
#include "globals.hpp"
#include "doingphysics.hpp"
#include "cellfunctors.hpp"
namespace
{
@ -271,6 +272,15 @@ namespace MWWorld
void World::unloadCell (CellRenderCollection::iterator iter)
{
ListHandles functor;
iter->first->forEach (functor);
{ // silence annoying g++ warning
for (std::vector<std::string>::const_iterator iter (functor.mHandles.begin());
iter!=functor.mHandles.end(); ++iter)
mScene.removeObject (*iter);
}
removeScripts (iter->first);
mEnvironment.mMechanicsManager->dropActors (iter->first);
iter->second->destroy();
@ -616,6 +626,8 @@ namespace MWWorld
void World::changeCell (int X, int Y, const ESM::Position& position)
{
SuppressDoingPhysics scopeGuard;
// remove active
CellRenderCollection::iterator active = mActiveCells.begin();
@ -782,10 +794,10 @@ namespace MWWorld
if (mCurrentCell->cell->data.gridX!=cellX || mCurrentCell->cell->data.gridY!=cellY)
{
changeCell (cellX, cellY, mPlayer->getPlayer().getCellRef().pos);
if (!DoingPhysics::isDoingPhysics())
mScene.moveObject (ptr.getRefData().getHandle(), Ogre::Vector3 (x, y, z));
}
if (!DoingPhysics::isDoingPhysics())
mScene.moveObject (ptr.getRefData().getHandle(), Ogre::Vector3 (x, y, z));
}
}
}

@ -133,7 +133,48 @@ namespace ESMS
loadRefs(store, esm);
}
/// Call functor (ref) for each reference. functor must return a bool. Returning
/// false will abort the iteration.
/// \return Iteration completed?
template<class Functor>
bool forEach (Functor& functor)
{
return
forEachImp (functor, activators) &&
forEachImp (functor, potions) &&
forEachImp (functor, appas) &&
forEachImp (functor, armors) &&
forEachImp (functor, books) &&
forEachImp (functor, clothes) &&
forEachImp (functor, containers) &&
forEachImp (functor, creatures) &&
forEachImp (functor, doors) &&
forEachImp (functor, ingreds) &&
forEachImp (functor, creatureLists) &&
forEachImp (functor, itemLists) &&
forEachImp (functor, lights) &&
forEachImp (functor, lockpicks) &&
forEachImp (functor, miscItems) &&
forEachImp (functor, npcs) &&
forEachImp (functor, probes) &&
forEachImp (functor, repairs) &&
forEachImp (functor, statics) &&
forEachImp (functor, weapons);
}
private:
template<class Functor, class List>
bool forEachImp (Functor& functor, List& list)
{
for (typename List::List::iterator iter (list.list.begin()); iter!=list.list.end();
++iter)
if (!functor (iter->ref, iter->mData))
return false;
return true;
}
void loadRefs(const ESMStore &store, ESMReader &esm)
{
assert (cell);

Loading…
Cancel
Save