From d55fe43fc95bfaec681c65b57aff378e6703f894 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 22 Dec 2014 18:50:24 +0100 Subject: [PATCH] Support animation groups for Light and Door objects (Fixes #2039) --- apps/openmw/mwclass/door.cpp | 8 +++++-- apps/openmw/mwclass/light.cpp | 9 +++++--- apps/openmw/mwrender/activatoranimation.cpp | 25 +++++++++++++++++++++ apps/openmw/mwrender/activatoranimation.hpp | 3 +++ apps/openmw/mwrender/actors.cpp | 11 ++++++++- apps/openmw/mwrender/actors.hpp | 2 +- apps/openmw/mwrender/animation.cpp | 17 -------------- apps/openmw/mwrender/animation.hpp | 3 --- apps/openmw/mwrender/objects.cpp | 10 +-------- apps/openmw/mwrender/objects.hpp | 2 +- 10 files changed, 53 insertions(+), 37 deletions(-) diff --git a/apps/openmw/mwclass/door.cpp b/apps/openmw/mwclass/door.cpp index fa9db9e16..41f9f3686 100644 --- a/apps/openmw/mwclass/door.cpp +++ b/apps/openmw/mwclass/door.cpp @@ -8,6 +8,7 @@ #include "../mwbase/world.hpp" #include "../mwbase/windowmanager.hpp" #include "../mwbase/soundmanager.hpp" +#include "../mwbase/mechanicsmanager.hpp" #include "../mwworld/ptr.hpp" #include "../mwworld/nullaction.hpp" @@ -22,7 +23,7 @@ #include "../mwgui/tooltips.hpp" -#include "../mwrender/objects.hpp" +#include "../mwrender/actors.hpp" #include "../mwrender/renderinginterface.hpp" namespace @@ -51,7 +52,8 @@ namespace MWClass { const std::string model = getModel(ptr); if (!model.empty()) { - renderingInterface.getObjects().insertModel(ptr, model); + MWRender::Actors& actors = renderingInterface.getActors(); + actors.insertActivator(ptr); } } @@ -70,6 +72,8 @@ namespace MWClass MWBase::Environment::get().getWorld()->activateDoor(ptr, customData.mDoorState); } } + + MWBase::Environment::get().getMechanicsManager()->add(ptr); } std::string Door::getModel(const MWWorld::Ptr &ptr) const diff --git a/apps/openmw/mwclass/light.cpp b/apps/openmw/mwclass/light.cpp index e6d266de2..7ad81232d 100644 --- a/apps/openmw/mwclass/light.cpp +++ b/apps/openmw/mwclass/light.cpp @@ -8,6 +8,7 @@ #include "../mwbase/world.hpp" #include "../mwbase/soundmanager.hpp" #include "../mwbase/windowmanager.hpp" +#include "../mwbase/mechanicsmanager.hpp" #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" @@ -22,6 +23,7 @@ #include "../mwgui/tooltips.hpp" #include "../mwrender/objects.hpp" +#include "../mwrender/actors.hpp" #include "../mwrender/renderinginterface.hpp" namespace @@ -54,13 +56,12 @@ namespace MWClass void Light::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const { - const std::string model = getModel(ptr); - MWWorld::LiveCellRef *ref = ptr.get(); // Insert even if model is empty, so that the light is added - renderingInterface.getObjects().insertModel(ptr, model, false, !(ref->mBase->mData.mFlags & ESM::Light::OffDefault)); + MWRender::Actors& actors = renderingInterface.getActors(); + actors.insertActivator(ptr, !(ref->mBase->mData.mFlags & ESM::Light::OffDefault)); } void Light::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const @@ -78,6 +79,8 @@ namespace MWClass MWBase::Environment::get().getSoundManager()->playSound3D(ptr, ref->mBase->mSound, 1.0, 1.0, MWBase::SoundManager::Play_TypeSfx, MWBase::SoundManager::Play_Loop); + + MWBase::Environment::get().getMechanicsManager()->add(ptr); } std::string Light::getModel(const MWWorld::Ptr &ptr) const diff --git a/apps/openmw/mwrender/activatoranimation.cpp b/apps/openmw/mwrender/activatoranimation.cpp index 540876a3e..4c63e2cf2 100644 --- a/apps/openmw/mwrender/activatoranimation.cpp +++ b/apps/openmw/mwrender/activatoranimation.cpp @@ -1,5 +1,8 @@ #include "activatoranimation.hpp" +#include +#include + #include #include "../mwbase/world.hpp" @@ -27,6 +30,28 @@ ActivatorAnimation::ActivatorAnimation(const MWWorld::Ptr &ptr) addAnimSource(model); } + else + { + // No model given. Create an object root anyway, so that lights can be added to it if needed. + mObjectRoot = NifOgre::ObjectScenePtr (new NifOgre::ObjectScene(mInsert->getCreator())); + } +} + +void ActivatorAnimation::addLight(const ESM::Light *light) +{ + addExtraLight(mInsert->getCreator(), mObjectRoot, light); +} + +void ActivatorAnimation::removeParticles() +{ + for (unsigned int i=0; imParticles.size(); ++i) + { + // Don't destroyParticleSystem, the ParticleSystemController is still holding a pointer to it. + // Don't setVisible, this could conflict with a VisController. + // The following will remove all spawned particles, then set the speed factor to zero so that no new ones will be spawned. + mObjectRoot->mParticles[i]->setSpeedFactor(0.f); + mObjectRoot->mParticles[i]->clear(); + } } } diff --git a/apps/openmw/mwrender/activatoranimation.hpp b/apps/openmw/mwrender/activatoranimation.hpp index eb3e5815e..ec0114ccd 100644 --- a/apps/openmw/mwrender/activatoranimation.hpp +++ b/apps/openmw/mwrender/activatoranimation.hpp @@ -15,6 +15,9 @@ namespace MWRender public: ActivatorAnimation(const MWWorld::Ptr& ptr); virtual ~ActivatorAnimation(); + + void addLight(const ESM::Light *light); + void removeParticles(); }; } diff --git a/apps/openmw/mwrender/actors.cpp b/apps/openmw/mwrender/actors.cpp index b7e9f5730..06acf4b3c 100644 --- a/apps/openmw/mwrender/actors.cpp +++ b/apps/openmw/mwrender/actors.cpp @@ -83,10 +83,19 @@ void Actors::insertCreature (const MWWorld::Ptr& ptr, bool weaponsShields) mAllActors[ptr] = anim; mRendering->addWaterRippleEmitter (ptr); } -void Actors::insertActivator (const MWWorld::Ptr& ptr) +void Actors::insertActivator (const MWWorld::Ptr& ptr, bool addLight) { insertBegin(ptr); ActivatorAnimation* anim = new ActivatorAnimation(ptr); + + if(ptr.getTypeName() == typeid(ESM::Light).name()) + { + if (addLight) + anim->addLight(ptr.get()->mBase); + else + anim->removeParticles(); + } + delete mAllActors[ptr]; mAllActors[ptr] = anim; } diff --git a/apps/openmw/mwrender/actors.hpp b/apps/openmw/mwrender/actors.hpp index d5d6c52bb..177c8a732 100644 --- a/apps/openmw/mwrender/actors.hpp +++ b/apps/openmw/mwrender/actors.hpp @@ -41,7 +41,7 @@ namespace MWRender void insertNPC(const MWWorld::Ptr& ptr); void insertCreature (const MWWorld::Ptr& ptr, bool weaponsShields); - void insertActivator (const MWWorld::Ptr& ptr); + void insertActivator (const MWWorld::Ptr& ptr, bool addLight=false); bool deleteObject (const MWWorld::Ptr& ptr); ///< \return found? diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index 4894378c7..af9fdf853 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -1507,23 +1507,6 @@ ObjectAnimation::ObjectAnimation(const MWWorld::Ptr& ptr, const std::string &mod } } -void ObjectAnimation::addLight(const ESM::Light *light) -{ - addExtraLight(mInsert->getCreator(), mObjectRoot, light); -} - -void ObjectAnimation::removeParticles() -{ - for (unsigned int i=0; imParticles.size(); ++i) - { - // Don't destroyParticleSystem, the ParticleSystemController is still holding a pointer to it. - // Don't setVisible, this could conflict with a VisController. - // The following will remove all spawned particles, then set the speed factor to zero so that no new ones will be spawned. - mObjectRoot->mParticles[i]->setSpeedFactor(0.f); - mObjectRoot->mParticles[i]->clear(); - } -} - class FindEntityTransparency { public: diff --git a/apps/openmw/mwrender/animation.hpp b/apps/openmw/mwrender/animation.hpp index 712069036..73d10fd06 100644 --- a/apps/openmw/mwrender/animation.hpp +++ b/apps/openmw/mwrender/animation.hpp @@ -346,9 +346,6 @@ class ObjectAnimation : public Animation { public: ObjectAnimation(const MWWorld::Ptr& ptr, const std::string &model); - void addLight(const ESM::Light *light); - void removeParticles(); - bool canBatch() const; void fillBatch(Ogre::StaticGeometry *sg); }; diff --git a/apps/openmw/mwrender/objects.cpp b/apps/openmw/mwrender/objects.cpp index 96decbb36..96cce178e 100644 --- a/apps/openmw/mwrender/objects.cpp +++ b/apps/openmw/mwrender/objects.cpp @@ -73,20 +73,12 @@ void Objects::insertBegin(const MWWorld::Ptr& ptr) ptr.getRefData().setBaseNode(insert); } -void Objects::insertModel(const MWWorld::Ptr &ptr, const std::string &mesh, bool batch, bool addLight) +void Objects::insertModel(const MWWorld::Ptr &ptr, const std::string &mesh, bool batch) { insertBegin(ptr); std::auto_ptr anim(new ObjectAnimation(ptr, mesh)); - if(ptr.getTypeName() == typeid(ESM::Light).name()) - { - if (addLight) - anim->addLight(ptr.get()->mBase); - else - anim->removeParticles(); - } - if (!mesh.empty()) { Ogre::AxisAlignedBox bounds = anim->getWorldBounds(); diff --git a/apps/openmw/mwrender/objects.hpp b/apps/openmw/mwrender/objects.hpp index 7f740dbab..02e974e2d 100644 --- a/apps/openmw/mwrender/objects.hpp +++ b/apps/openmw/mwrender/objects.hpp @@ -41,7 +41,7 @@ public: , mRootNode(NULL) {} ~Objects(){} - void insertModel(const MWWorld::Ptr& ptr, const std::string &model, bool batch=false, bool addLight=false); + void insertModel(const MWWorld::Ptr& ptr, const std::string &model, bool batch=false); ObjectAnimation* getAnimation(const MWWorld::Ptr &ptr);