diff --git a/apps/openmw/mwrender/activatoranimation.cpp b/apps/openmw/mwrender/activatoranimation.cpp index f951307b6..7bc89b917 100644 --- a/apps/openmw/mwrender/activatoranimation.cpp +++ b/apps/openmw/mwrender/activatoranimation.cpp @@ -51,6 +51,7 @@ ActivatorAnimation::ActivatorAnimation(const MWWorld::Ptr &ptr) ent->setVisibilityFlags(RV_Misc); ent->setRenderQueueGroup(transparent ? RQG_Alpha : RQG_Main); } + setAnimationSource(mesh); } } diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index 707aedcd9..160641eb0 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -46,45 +46,64 @@ Animation::~Animation() } -Ogre::Bone *Animation::insertSkeletonSource(const std::string &name) +void Animation::setAnimationSources(const std::vector &names) { Ogre::SkeletonManager &skelMgr = Ogre::SkeletonManager::getSingleton(); - Ogre::SkeletonPtr skel = skelMgr.getByName(name); - if(skel.isNull()) + + mCurrentAnim = NULL; + mCurrentKeys = NULL; + mAnimVelocity = 0.0f; + mAccumRoot = NULL; + mNonAccumRoot = NULL; + mSkeletonSources.clear(); + + std::vector::const_iterator nameiter = names.begin(); + while(nameiter != names.end()) { - NifOgre::Loader::createSkeleton(name); - skel = skelMgr.getByName(name); + Ogre::SkeletonPtr skel = skelMgr.getByName(*nameiter); if(skel.isNull()) { - std::cerr<< "Failed to get skeleton source "<touch(); - mSkeletonSources.push_back(skel); + skel->touch(); - Ogre::Skeleton::BoneIterator boneiter = skel->getBoneIterator(); - while(boneiter.hasMoreElements()) - { - Ogre::Bone *bone = boneiter.getNext(); - Ogre::UserObjectBindings &bindings = bone->getUserObjectBindings(); - const Ogre::Any &data = bindings.getUserAny(NifOgre::sTextKeyExtraDataID); - if(data.isEmpty() || !Ogre::any_cast(data)) - continue; - - for(int i = 0;i < skel->getNumAnimations();i++) + Ogre::Skeleton::BoneIterator boneiter = skel->getBoneIterator(); + while(boneiter.hasMoreElements()) { - Ogre::Animation *anim = skel->getAnimation(i); - const Ogre::Any &groupdata = bindings.getUserAny(std::string(NifOgre::sTextKeyExtraDataID)+ - "@"+anim->getName()); - if(!groupdata.isEmpty()) - mTextKeys[anim->getName()] = Ogre::any_cast(groupdata); + Ogre::Bone *bone = boneiter.getNext(); + Ogre::UserObjectBindings &bindings = bone->getUserObjectBindings(); + const Ogre::Any &data = bindings.getUserAny(NifOgre::sTextKeyExtraDataID); + if(data.isEmpty() || !Ogre::any_cast(data)) + continue; + + if(!mNonAccumRoot && mEntityList.mSkelBase) + { + mAccumRoot = mInsert; + mNonAccumRoot = mEntityList.mSkelBase->getSkeleton()->getBone(bone->getName()); + } + + mSkeletonSources.push_back(skel); + for(int i = 0;i < skel->getNumAnimations();i++) + { + Ogre::Animation *anim = skel->getAnimation(i); + const Ogre::Any &groupdata = bindings.getUserAny(std::string(NifOgre::sTextKeyExtraDataID)+ + "@"+anim->getName()); + if(!groupdata.isEmpty()) + mTextKeys[anim->getName()] = Ogre::any_cast(groupdata); + } + + break; } - return bone; + nameiter++; } - - return NULL; } void Animation::createEntityList(Ogre::SceneNode *node, const std::string &model) @@ -111,31 +130,6 @@ void Animation::createEntityList(Ogre::SceneNode *node, const std::string &model Ogre::Skeleton::BoneIterator boneiter = skelinst->getBoneIterator(); while(boneiter.hasMoreElements()) boneiter.getNext()->setManuallyControlled(true); - - Ogre::Bone *bone = insertSkeletonSource(skelinst->getName()); - if(!bone) - { - for(std::vector::const_iterator iter(mSkeletonSources.begin()); - !bone && iter != mSkeletonSources.end();iter++) - { - Ogre::Skeleton::BoneIterator boneiter = (*iter)->getBoneIterator(); - while(boneiter.hasMoreElements()) - { - bone = boneiter.getNext(); - Ogre::UserObjectBindings &bindings = bone->getUserObjectBindings(); - const Ogre::Any &data = bindings.getUserAny(NifOgre::sTextKeyExtraDataID); - if(!data.isEmpty() && Ogre::any_cast(data)) - break; - - bone = NULL; - } - } - } - if(bone) - { - mAccumRoot = mInsert; - mNonAccumRoot = skelinst->getBone(bone->getName()); - } } } diff --git a/apps/openmw/mwrender/animation.hpp b/apps/openmw/mwrender/animation.hpp index c6e230670..130805a50 100644 --- a/apps/openmw/mwrender/animation.hpp +++ b/apps/openmw/mwrender/animation.hpp @@ -57,9 +57,15 @@ protected: * anything. If the marker is not found, it resets to the beginning. */ void reset(const std::string &marker); - /* Inserts an additional skeleton into the animation source chain. Returns - * the bone representing the non-accum root from the base skeleton. */ - Ogre::Bone *insertSkeletonSource(const std::string &name); + /* Specifies a list of skeleton names to use as animation sources. */ + void setAnimationSources(const std::vector &names); + + /* Specifies a single skeleton name to use as an animation source. */ + void setAnimationSource(const std::string &name) + { + std::vector names(1, name); + setAnimationSources(names); + } void createEntityList(Ogre::SceneNode *node, const std::string &model); diff --git a/apps/openmw/mwrender/creatureanimation.cpp b/apps/openmw/mwrender/creatureanimation.cpp index 094281c46..b85c4dbbd 100644 --- a/apps/openmw/mwrender/creatureanimation.cpp +++ b/apps/openmw/mwrender/creatureanimation.cpp @@ -23,10 +23,9 @@ CreatureAnimation::CreatureAnimation(const MWWorld::Ptr &ptr) assert (ref->mBase != NULL); if(!ref->mBase->mModel.empty()) { - if((ref->mBase->mFlags&ESM::Creature::Biped)) - insertSkeletonSource("meshes\\base_anim.nif"); + std::string model = "meshes\\"+ref->mBase->mModel; - createEntityList(mPtr.getRefData().getBaseNode(), "meshes\\"+ref->mBase->mModel); + createEntityList(mPtr.getRefData().getBaseNode(), model); for(size_t i = 0;i < mEntityList.mEntities.size();i++) { Ogre::Entity *ent = mEntityList.mEntities[i]; @@ -52,6 +51,12 @@ CreatureAnimation::CreatureAnimation(const MWWorld::Ptr &ptr) } ent->setRenderQueueGroup(transparent ? RQG_Alpha : RQG_Main); } + + std::vector names; + if((ref->mBase->mFlags&ESM::Creature::Biped)) + names.push_back("meshes\\base_anim.nif"); + names.push_back(model); + setAnimationSources(names); } } diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index 4d8119c72..3f135b7f6 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -125,13 +125,14 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, MWWor base->setRenderQueueGroup(transparent ? RQG_Alpha : RQG_Main); } + std::vector skelnames(1, smodel); if(!mNpc->isMale() && !isBeast) - insertSkeletonSource("meshes\\base_anim_female.nif"); + skelnames.push_back("meshes\\base_anim_female.nif"); else if(mBodyPrefix.find("argonian") != std::string::npos) - insertSkeletonSource("meshes\\argonian_swimkna.nif"); - + skelnames.push_back("meshes\\argonian_swimkna.nif"); if(mNpc->mModel.length() > 0) - insertSkeletonSource("meshes\\"+Misc::StringUtils::lowerCase(mNpc->mModel)); + skelnames.push_back("meshes\\"+Misc::StringUtils::lowerCase(mNpc->mModel)); + setAnimationSources(skelnames); updateParts(true); }