diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 563c9e422..ec7700bee 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -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 ) diff --git a/apps/openmw/mwclass/activator.cpp b/apps/openmw/mwclass/activator.cpp index 26d286aa1..292627286 100644 --- a/apps/openmw/mwclass/activator.cpp +++ b/apps/openmw/mwclass/activator.cpp @@ -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 diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index d9a3b6878..23272e674 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -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 diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 6496ba9f2..5bf468ffb 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -21,6 +21,7 @@ #include "../mwrender/animation.hpp" +#include "../mwworld/class.hpp" namespace MWMechanics { diff --git a/apps/openmw/mwrender/activatoranimation.cpp b/apps/openmw/mwrender/activatoranimation.cpp new file mode 100644 index 000000000..18ae31865 --- /dev/null +++ b/apps/openmw/mwrender/activatoranimation.cpp @@ -0,0 +1,64 @@ +#include "activatoranimation.hpp" + +#include +#include +#include + +#include "renderconst.hpp" + +#include "../mwbase/world.hpp" + +namespace MWRender +{ + +ActivatorAnimation::~ActivatorAnimation() +{ +} + +ActivatorAnimation::ActivatorAnimation(const MWWorld::Ptr &ptr) + : Animation(ptr) +{ + MWWorld::LiveCellRef *ref = mPtr.get(); + + 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); +} + +} diff --git a/apps/openmw/mwrender/activatoranimation.hpp b/apps/openmw/mwrender/activatoranimation.hpp new file mode 100644 index 000000000..f3d8d86c8 --- /dev/null +++ b/apps/openmw/mwrender/activatoranimation.hpp @@ -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 diff --git a/apps/openmw/mwrender/actors.cpp b/apps/openmw/mwrender/actors.cpp index 10b654834..d62e16fa2 100644 --- a/apps/openmw/mwrender/actors.cpp +++ b/apps/openmw/mwrender/actors.cpp @@ -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) { diff --git a/apps/openmw/mwrender/actors.hpp b/apps/openmw/mwrender/actors.hpp index 92965a059..4ef78c577 100644 --- a/apps/openmw/mwrender/actors.hpp +++ b/apps/openmw/mwrender/actors.hpp @@ -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? diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index 5341ffd7a..978419845 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -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;