diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index f490baefe5..27e54b2284 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" @@ -310,6 +311,18 @@ namespace MWRender } } + void Animation::clearAnimSources() + { + mStates.clear(); + + for(size_t i = 0;i < sNumGroups;i++) + mAnimationTimePtr[i]->setAnimName(std::string()); + + mAccumCtrl = NULL; + + mAnimSources.clear(); + } + bool Animation::hasAnimation(const std::string &anim) { AnimSourceList::const_iterator iter(mAnimSources.begin()); @@ -668,13 +681,14 @@ namespace MWRender float Animation::getVelocity(const std::string &groupname) const { - return 0.f; - /* + if (!mAccumRoot) + return 0.0f; + // Look in reverse; last-inserted source has priority. AnimSourceList::const_reverse_iterator animsrc(mAnimSources.rbegin()); for(;animsrc != mAnimSources.rend();++animsrc) { - const NifOsg::TextKeyMap &keys = (*animsrc)->mTextKeys; + const NifOsg::TextKeyMap &keys = (*animsrc)->getTextKeys(); if(findGroupStart(keys, groupname) != keys.end()) break; } @@ -682,15 +696,14 @@ namespace MWRender return 0.0f; float velocity = 0.0f; - const NifOsg::TextKeyMap &keys = (*animsrc)->mTextKeys; - const std::vector >&ctrls = (*animsrc)->mControllers[0]; - for(size_t i = 0;i < ctrls.size();i++) + const NifOsg::TextKeyMap &keys = (*animsrc)->getTextKeys(); + + const AnimSource::ControllerMap& ctrls = (*animsrc)->mControllerMap[0]; + for (AnimSource::ControllerMap::const_iterator it = ctrls.begin(); it != ctrls.end(); ++it) { - NifOsg::NodeTargetValue *dstval; - dstval = static_cast*>(ctrls[i].getDestination().getPointer()); - if(dstval->getNode() == mNonAccumRoot) + if (Misc::StringUtils::ciEqual(it->first, mAccumRoot->getName())) { - velocity = calcAnimVelocity(keys, dstval, mAccumulate, groupname); + velocity = calcAnimVelocity(keys, it->second, mAccumulate, groupname); break; } } @@ -704,15 +717,14 @@ namespace MWRender while(!(velocity > 1.0f) && ++animiter != mAnimSources.rend()) { - const NifOgre::TextKeyMap &keys = (*animiter)->mTextKeys; - const std::vector >&ctrls = (*animiter)->mControllers[0]; - for(size_t i = 0;i < ctrls.size();i++) + const NifOsg::TextKeyMap &keys = (*animiter)->getTextKeys(); + + const AnimSource::ControllerMap& ctrls = (*animiter)->mControllerMap[0]; + for (AnimSource::ControllerMap::const_iterator it = ctrls.begin(); it != ctrls.end(); ++it) { - NifOgre::NodeTargetValue *dstval; - dstval = static_cast*>(ctrls[i].getDestination().getPointer()); - if(dstval->getNode() == mNonAccumRoot) + if (Misc::StringUtils::ciEqual(it->first, mAccumRoot->getName())) { - velocity = calcAnimVelocity(keys, dstval, mAccumulate, groupname); + velocity = calcAnimVelocity(keys, it->second, mAccumulate, groupname); break; } } @@ -720,7 +732,6 @@ namespace MWRender } return velocity; - */ } void Animation::updatePosition(float oldtime, float newtime, osg::Vec3f& position) @@ -808,7 +819,7 @@ namespace MWRender return movement; } - void Animation::setObjectRoot(const std::string &model) + void Animation::setObjectRoot(const std::string &model, bool forceskeleton) { if (mObjectRoot) { @@ -821,7 +832,20 @@ namespace MWRender mAccumRoot = NULL; mAccumCtrl = NULL; - mObjectRoot = mResourceSystem->getSceneManager()->createInstance(model, mInsert); + if (!forceskeleton) + mObjectRoot = mResourceSystem->getSceneManager()->createInstance(model, mInsert); + else + { + osg::ref_ptr newObjectRoot = mResourceSystem->getSceneManager()->createInstance(model); + if (!dynamic_cast(newObjectRoot.get())) + { + osg::ref_ptr skel = new SceneUtil::Skeleton; + skel->addChild(newObjectRoot); + newObjectRoot = skel; + } + mInsert->addChild(newObjectRoot); + mObjectRoot = newObjectRoot; + } NodeMapVisitor visitor; mObjectRoot->accept(visitor); @@ -1062,7 +1086,7 @@ namespace MWRender { if (!model.empty()) { - setObjectRoot(model); + setObjectRoot(model, false); if (!ptr.getClass().getEnchantment(ptr).empty()) addGlow(mObjectRoot, getEnchantmentColor(ptr)); diff --git a/apps/openmw/mwrender/animation.hpp b/apps/openmw/mwrender/animation.hpp index 083213c85b..d5b2de81b5 100644 --- a/apps/openmw/mwrender/animation.hpp +++ b/apps/openmw/mwrender/animation.hpp @@ -215,12 +215,13 @@ protected: void handleTextKey(AnimState &state, const std::string &groupname, const std::multimap::const_iterator &key, const std::multimap& map); - /* Sets the root model of the object. + /** Sets the root model of the object. * * Note that you must make sure all animation sources are cleared before reseting the object * root. All nodes previously retrieved with getNode will also become invalidated. + * @param forceskeleton Wrap the object root in a Skeleton, even if it contains no skinned parts. Use this if you intend to add skinned parts manually. */ - void setObjectRoot(const std::string &model); + void setObjectRoot(const std::string &model, bool forceskeleton); /* Adds the keyframe controllers in the specified model as a new animation source. Note that * the filename portion of the provided model name will be prepended with 'x', and the .nif @@ -230,7 +231,7 @@ protected: /** Adds an additional light to the given node using the specified ESM record. */ void addExtraLight(osg::ref_ptr parent, const ESM::Light *light); - //void clearAnimSources(); + void clearAnimSources(); osg::Vec4f getEnchantmentColor(MWWorld::Ptr item); diff --git a/apps/openmw/mwrender/creatureanimation.cpp b/apps/openmw/mwrender/creatureanimation.cpp index 721215749a..d2abf14135 100644 --- a/apps/openmw/mwrender/creatureanimation.cpp +++ b/apps/openmw/mwrender/creatureanimation.cpp @@ -26,7 +26,7 @@ CreatureAnimation::CreatureAnimation(const MWWorld::Ptr &ptr, if(!model.empty()) { - setObjectRoot(model /* , baseonly = false */); + setObjectRoot(model, false /* , baseonly = false */); //setRenderProperties(mObjectRoot, RV_Actors, RQG_Main, RQG_Alpha); if((ref->mBase->mFlags&ESM::Creature::Bipedal)) @@ -45,7 +45,7 @@ CreatureWeaponAnimation::CreatureWeaponAnimation(const MWWorld::Ptr &ptr, const if(!model.empty()) { - setObjectRoot(model /* , baseonly = false*/); + setObjectRoot(model, true /* , baseonly = false*/); //setRenderProperties(mObjectRoot, RV_Actors, RQG_Main, RQG_Alpha); if((ref->mBase->mFlags&ESM::Creature::Bipedal)) diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index ab32864bd3..80dbf3c7f6 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -233,7 +233,7 @@ void NpcAnimation::rebuild() void NpcAnimation::updateNpcBase() { - //clearAnimSources(); + clearAnimSources(); const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); const ESM::Race *race = store.get().find(mNpc->mRace); @@ -279,7 +279,8 @@ void NpcAnimation::updateNpcBase() : "meshes\\base_animkna.1st.nif" : "meshes\\wolf\\skin.1st.nif"); smodel = Misc::ResourceHelpers::correctActorModelPath(smodel, mResourceSystem->getVFS()); - setObjectRoot(smodel /*, baseonly = true*/); + + setObjectRoot(smodel, true /*, baseonly = true*/); if(mViewMode != VM_FirstPerson) {