Treat activators as actors for rendering and mechanics

Kinda hacky, but it's the only way to get animated activators (flags, silt
striders, etc) to work properly.
This commit is contained in:
Chris Robinson 2013-01-16 14:37:32 -08:00
parent d2fc3c7b33
commit 94b93227d3
9 changed files with 120 additions and 9 deletions

View file

@ -14,8 +14,8 @@ set(GAME_HEADER
source_group(game FILES ${GAME} ${GAME_HEADER}) source_group(game FILES ${GAME} ${GAME_HEADER})
add_openmw_dir (mwrender add_openmw_dir (mwrender
renderingmanager debugging sky player animation npcanimation creatureanimation actors objects renderingmanager debugging sky player animation npcanimation creatureanimation activatoranimation
renderinginterface localmap occlusionquery terrain terrainmaterial water shadows actors objects renderinginterface localmap occlusionquery terrain terrainmaterial water shadows
compositors characterpreview externalrendering globalmap videoplayer compositors characterpreview externalrendering globalmap videoplayer
) )

View file

@ -5,12 +5,13 @@
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/windowmanager.hpp" #include "../mwbase/windowmanager.hpp"
#include "../mwbase/mechanicsmanager.hpp"
#include "../mwworld//cellstore.hpp" #include "../mwworld//cellstore.hpp"
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "../mwworld/physicssystem.hpp" #include "../mwworld/physicssystem.hpp"
#include "../mwrender/objects.hpp" #include "../mwrender/actors.hpp"
#include "../mwrender/renderinginterface.hpp" #include "../mwrender/renderinginterface.hpp"
#include "../mwgui/tooltips.hpp" #include "../mwgui/tooltips.hpp"
@ -21,9 +22,8 @@ namespace MWClass
{ {
const std::string model = getModel(ptr); const std::string model = getModel(ptr);
if (!model.empty()) { if (!model.empty()) {
MWRender::Objects& objects = renderingInterface.getObjects(); MWRender::Actors& actors = renderingInterface.getActors();
objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false); actors.insertActivator(ptr);
objects.insertMesh(ptr, model);
} }
} }
@ -32,6 +32,7 @@ namespace MWClass
const std::string model = getModel(ptr); const std::string model = getModel(ptr);
if(!model.empty()) if(!model.empty())
physics.addObject(ptr); physics.addObject(ptr);
MWBase::Environment::get().getMechanicsManager()->addActor(ptr);
} }
std::string Activator::getModel(const MWWorld::Ptr &ptr) const std::string Activator::getModel(const MWWorld::Ptr &ptr) const

View file

@ -166,7 +166,9 @@ namespace MWMechanics
void Actors::addActor (const MWWorld::Ptr& ptr) void Actors::addActor (const MWWorld::Ptr& ptr)
{ {
MWRender::Animation *anim = MWBase::Environment::get().getWorld()->getAnimation(ptr); MWRender::Animation *anim = MWBase::Environment::get().getWorld()->getAnimation(ptr);
if(!MWWorld::Class::get(ptr).getCreatureStats(ptr).isDead()) /* Kind of a hack. Activators need a character controller to manage an idle state. */
if(ptr.getTypeName() == typeid(ESM::Activator).name() ||
!MWWorld::Class::get(ptr).getCreatureStats(ptr).isDead())
mActors.insert(std::make_pair(ptr, CharacterController(ptr, anim, CharState_Idle))); mActors.insert(std::make_pair(ptr, CharacterController(ptr, anim, CharState_Idle)));
else else
mActors.insert(std::make_pair(ptr, CharacterController(ptr, anim, CharState_Dead))); mActors.insert(std::make_pair(ptr, CharacterController(ptr, anim, CharState_Dead)));
@ -203,6 +205,11 @@ namespace MWMechanics
PtrControllerMap::iterator iter(mActors.begin()); PtrControllerMap::iterator iter(mActors.begin());
while(iter != mActors.end()) while(iter != mActors.end())
{ {
if(iter->first.getTypeName() == typeid(ESM::Activator).name())
{
iter++;
continue;
}
if(!MWWorld::Class::get(iter->first).getCreatureStats(iter->first).isDead()) if(!MWWorld::Class::get(iter->first).getCreatureStats(iter->first).isDead())
{ {
if(iter->second.getState() == CharState_Dead) if(iter->second.getState() == CharState_Dead)
@ -267,7 +274,10 @@ namespace MWMechanics
void Actors::restoreDynamicStats() void Actors::restoreDynamicStats()
{ {
for(PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();++iter) for(PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();++iter)
calculateRestoration(iter->first, 3600); {
if(iter->first.getTypeName() != typeid(ESM::Activator).name())
calculateRestoration(iter->first, 3600);
}
} }
int Actors::countDeaths (const std::string& id) const int Actors::countDeaths (const std::string& id) const

View file

@ -21,6 +21,7 @@
#include "../mwrender/animation.hpp" #include "../mwrender/animation.hpp"
#include "../mwworld/class.hpp"
namespace MWMechanics namespace MWMechanics
{ {

View file

@ -0,0 +1,64 @@
#include "activatoranimation.hpp"
#include <OgreEntity.h>
#include <OgreSceneManager.h>
#include <OgreSubEntity.h>
#include "renderconst.hpp"
#include "../mwbase/world.hpp"
namespace MWRender
{
ActivatorAnimation::~ActivatorAnimation()
{
}
ActivatorAnimation::ActivatorAnimation(const MWWorld::Ptr &ptr)
: Animation(ptr)
{
MWWorld::LiveCellRef<ESM::Activator> *ref = mPtr.get<ESM::Activator>();
assert (ref->mBase != NULL);
if(!ref->mBase->mModel.empty())
{
std::string mesh = "meshes\\" + ref->mBase->mModel;
createEntityList(mPtr.getRefData().getBaseNode(), mesh);
for(size_t i = 0;i < mEntityList.mEntities.size();i++)
{
Ogre::Entity *ent = mEntityList.mEntities[i];
bool transparent = false;
for (unsigned int j=0;j < ent->getNumSubEntities() && !transparent; ++j)
{
Ogre::MaterialPtr mat = ent->getSubEntity(j)->getMaterial();
Ogre::Material::TechniqueIterator techIt = mat->getTechniqueIterator();
while (techIt.hasMoreElements() && !transparent)
{
Ogre::Technique* tech = techIt.getNext();
Ogre::Technique::PassIterator passIt = tech->getPassIterator();
while (passIt.hasMoreElements() && !transparent)
{
Ogre::Pass* pass = passIt.getNext();
if (pass->getDepthWriteEnabled() == false)
transparent = true;
}
}
}
ent->setVisibilityFlags(RV_Misc);
ent->setRenderQueueGroup(transparent ? RQG_Alpha : RQG_Main);
}
}
}
void ActivatorAnimation::runAnimation(float timepassed)
{
// Placeholder
Animation::runAnimation(timepassed);
}
}

View file

@ -0,0 +1,23 @@
#ifndef _GAME_RENDER_ACTIVATORANIMATION_H
#define _GAME_RENDER_ACTIVATORANIMATION_H
#include "animation.hpp"
namespace MWWorld
{
class Ptr;
}
namespace MWRender
{
class ActivatorAnimation : public Animation
{
public:
ActivatorAnimation(const MWWorld::Ptr& ptr);
virtual ~ActivatorAnimation();
virtual void runAnimation(float timepassed);
};
}
#endif

View file

@ -6,6 +6,7 @@
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "animation.hpp" #include "animation.hpp"
#include "activatoranimation.hpp"
#include "creatureanimation.hpp" #include "creatureanimation.hpp"
#include "npcanimation.hpp" #include "npcanimation.hpp"
@ -78,6 +79,13 @@ void Actors::insertCreature (const MWWorld::Ptr& ptr)
delete mAllActors[ptr]; delete mAllActors[ptr];
mAllActors[ptr] = anim; mAllActors[ptr] = anim;
} }
void Actors::insertActivator (const MWWorld::Ptr& ptr)
{
insertBegin(ptr);
ActivatorAnimation* anim = new ActivatorAnimation(ptr);
delete mAllActors[ptr];
mAllActors[ptr] = anim;
}
bool Actors::deleteObject (const MWWorld::Ptr& ptr) bool Actors::deleteObject (const MWWorld::Ptr& ptr)
{ {

View file

@ -31,8 +31,9 @@ namespace MWRender
void setMwRoot(Ogre::SceneNode* root); void setMwRoot(Ogre::SceneNode* root);
void insertBegin (const MWWorld::Ptr& ptr); void insertBegin (const MWWorld::Ptr& ptr);
void insertCreature (const MWWorld::Ptr& ptr);
void insertNPC(const MWWorld::Ptr& ptr, MWWorld::InventoryStore& inv); void insertNPC(const MWWorld::Ptr& ptr, MWWorld::InventoryStore& inv);
void insertCreature (const MWWorld::Ptr& ptr);
void insertActivator (const MWWorld::Ptr& ptr);
bool deleteObject (const MWWorld::Ptr& ptr); bool deleteObject (const MWWorld::Ptr& ptr);
///< \return found? ///< \return found?

View file

@ -200,6 +200,9 @@ void Animation::playGroup(std::string groupname, int mode, int loops)
GroupTimes times; GroupTimes times;
try { try {
if(!mEntityList.mSkelBase)
throw std::runtime_error("Attempting to animate an inanimate object");
std::transform(groupname.begin(), groupname.end(), groupname.begin(), ::tolower); std::transform(groupname.begin(), groupname.end(), groupname.begin(), ::tolower);
times.mAnimState = mEntityList.mSkelBase->getAnimationState(groupname); times.mAnimState = mEntityList.mSkelBase->getAnimationState(groupname);
times.mLoops = loops; times.mLoops = loops;