1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-02-02 05:45:33 +00:00

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})
add_openmw_dir (mwrender
renderingmanager debugging sky player animation npcanimation creatureanimation actors objects
renderinginterface localmap occlusionquery terrain terrainmaterial water shadows
renderingmanager debugging sky player animation npcanimation creatureanimation activatoranimation
actors objects renderinginterface localmap occlusionquery terrain terrainmaterial water shadows
compositors characterpreview externalrendering globalmap videoplayer
)

View file

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

View file

@ -166,7 +166,9 @@ namespace MWMechanics
void Actors::addActor (const MWWorld::Ptr& 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)));
else
mActors.insert(std::make_pair(ptr, CharacterController(ptr, anim, CharState_Dead)));
@ -203,6 +205,11 @@ namespace MWMechanics
PtrControllerMap::iterator iter(mActors.begin());
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(iter->second.getState() == CharState_Dead)
@ -267,7 +274,10 @@ namespace MWMechanics
void Actors::restoreDynamicStats()
{
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

View file

@ -21,6 +21,7 @@
#include "../mwrender/animation.hpp"
#include "../mwworld/class.hpp"
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 "animation.hpp"
#include "activatoranimation.hpp"
#include "creatureanimation.hpp"
#include "npcanimation.hpp"
@ -78,6 +79,13 @@ void Actors::insertCreature (const MWWorld::Ptr& ptr)
delete mAllActors[ptr];
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)
{

View file

@ -31,8 +31,9 @@ namespace MWRender
void setMwRoot(Ogre::SceneNode* root);
void insertBegin (const MWWorld::Ptr& ptr);
void insertCreature (const MWWorld::Ptr& ptr);
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);
///< \return found?

View file

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