mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-19 20:53:50 +00:00
Use an array of objectlists, instead of one base objectlist and an array of 'animation sources'
This commit is contained in:
parent
f9dee25fd1
commit
69084139aa
5 changed files with 75 additions and 133 deletions
|
@ -27,9 +27,9 @@ ActivatorAnimation::ActivatorAnimation(const MWWorld::Ptr &ptr)
|
|||
std::string mesh = "meshes\\" + ref->mBase->mModel;
|
||||
|
||||
createObjectList(mPtr.getRefData().getBaseNode(), mesh);
|
||||
for(size_t i = 0;i < mObjectList.mEntities.size();i++)
|
||||
for(size_t i = 0;i < mObjectLists[0].mEntities.size();i++)
|
||||
{
|
||||
Ogre::Entity *ent = mObjectList.mEntities[i];
|
||||
Ogre::Entity *ent = mObjectLists[0].mEntities[i];
|
||||
ent->setVisibilityFlags(RV_Misc);
|
||||
|
||||
for(unsigned int j=0; j < ent->getNumSubEntities(); ++j)
|
||||
|
@ -38,14 +38,12 @@ ActivatorAnimation::ActivatorAnimation(const MWWorld::Ptr &ptr)
|
|||
subEnt->setRenderQueueGroup(subEnt->getMaterial()->isTransparent() ? RQG_Alpha : RQG_Main);
|
||||
}
|
||||
}
|
||||
for(size_t i = 0;i < mObjectList.mParticles.size();i++)
|
||||
for(size_t i = 0;i < mObjectLists[0].mParticles.size();i++)
|
||||
{
|
||||
Ogre::ParticleSystem *part = mObjectList.mParticles[i];
|
||||
Ogre::ParticleSystem *part = mObjectLists[0].mParticles[i];
|
||||
part->setVisibilityFlags(RV_Misc);
|
||||
|
||||
part->setRenderQueueGroup(RQG_Alpha);
|
||||
}
|
||||
setAnimationSource(mesh);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -55,68 +55,45 @@ Animation::~Animation()
|
|||
if(mInsert)
|
||||
{
|
||||
Ogre::SceneManager *sceneMgr = mInsert->getCreator();
|
||||
destroyObjectList(sceneMgr, mObjectList);
|
||||
|
||||
for(size_t i = 0;i < mAnimationSources.size();i++)
|
||||
destroyObjectList(sceneMgr, mAnimationSources[i]);
|
||||
mAnimationSources.clear();
|
||||
for(size_t i = 0;i < mObjectLists.size();i++)
|
||||
destroyObjectList(sceneMgr, mObjectLists[i]);
|
||||
mObjectLists.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Animation::setAnimationSources(const std::vector<std::string> &names)
|
||||
void Animation::createObjectList(Ogre::SceneNode *node, const std::string &model)
|
||||
{
|
||||
if(!mSkelBase)
|
||||
return;
|
||||
Ogre::SceneManager *sceneMgr = mInsert->getCreator();
|
||||
assert(!mInsert);
|
||||
mInsert = node->createChildSceneNode();
|
||||
assert(mInsert);
|
||||
|
||||
mCurrentControllers = &mObjectList.mControllers;
|
||||
mCurrentAnim = NULL;
|
||||
mCurrentKeys = NULL;
|
||||
mAnimVelocity = 0.0f;
|
||||
mAccumRoot = NULL;
|
||||
mNonAccumRoot = NULL;
|
||||
mTextKeys.clear();
|
||||
for(size_t i = 0;i < mAnimationSources.size();i++)
|
||||
destroyObjectList(sceneMgr, mAnimationSources[i]);
|
||||
mAnimationSources.clear();
|
||||
mObjectLists.resize(1);
|
||||
|
||||
Ogre::SharedPtr<Ogre::ControllerValue<Ogre::Real> > ctrlval(OGRE_NEW AnimationValue(this));
|
||||
Ogre::SkeletonInstance *skelinst = mSkelBase->getSkeleton();
|
||||
std::vector<std::string>::const_iterator nameiter;
|
||||
for(nameiter = names.begin();nameiter != names.end();nameiter++)
|
||||
mObjectLists[0] = NifOgre::Loader::createObjects(mInsert, model);
|
||||
if(mObjectLists[0].mSkelBase)
|
||||
{
|
||||
mAnimationSources.push_back(NifOgre::Loader::createObjectBase(sceneMgr, *nameiter));
|
||||
if(!mAnimationSources.back().mSkelBase)
|
||||
mSkelBase = mObjectLists[0].mSkelBase;
|
||||
|
||||
Ogre::AnimationStateSet *aset = mObjectLists[0].mSkelBase->getAllAnimationStates();
|
||||
Ogre::AnimationStateIterator asiter = aset->getAnimationStateIterator();
|
||||
while(asiter.hasMoreElements())
|
||||
{
|
||||
std::cerr<< "Failed to get skeleton source "<<*nameiter <<std::endl;
|
||||
destroyObjectList(sceneMgr, mAnimationSources.back());
|
||||
mAnimationSources.pop_back();
|
||||
continue;
|
||||
}
|
||||
NifOgre::ObjectList &objects = mAnimationSources.back();
|
||||
|
||||
for(size_t i = 0;i < objects.mControllers.size();i++)
|
||||
{
|
||||
NifOgre::NodeTargetValue<Ogre::Real> *dstval = dynamic_cast<NifOgre::NodeTargetValue<Ogre::Real>*>(objects.mControllers[i].getDestination().getPointer());
|
||||
if(!dstval) continue;
|
||||
|
||||
const Ogre::String &trgtname = dstval->getNode()->getName();
|
||||
if(!skelinst->hasBone(trgtname)) continue;
|
||||
|
||||
Ogre::Bone *bone = skelinst->getBone(trgtname);
|
||||
dstval->setNode(bone);
|
||||
Ogre::AnimationState *state = asiter.getNext();
|
||||
state->setEnabled(false);
|
||||
state->setLoop(false);
|
||||
}
|
||||
|
||||
for(size_t i = 0;i < objects.mControllers.size();i++)
|
||||
{
|
||||
if(objects.mControllers[i].getSource().isNull())
|
||||
objects.mControllers[i].setSource(ctrlval);
|
||||
}
|
||||
// Set the bones as manually controlled since we're applying the
|
||||
// transformations manually (needed if we want to apply an animation
|
||||
// from one skeleton onto another).
|
||||
Ogre::SkeletonInstance *skelinst = mObjectLists[0].mSkelBase->getSkeleton();
|
||||
Ogre::Skeleton::BoneIterator boneiter = skelinst->getBoneIterator();
|
||||
while(boneiter.hasMoreElements())
|
||||
boneiter.getNext()->setManuallyControlled(true);
|
||||
|
||||
Ogre::Entity *ent = objects.mSkelBase;
|
||||
Ogre::SkeletonPtr skel = Ogre::SkeletonManager::getSingleton().getByName(ent->getSkeleton()->getName());
|
||||
Ogre::Skeleton::BoneIterator boneiter = skel->getBoneIterator();
|
||||
Ogre::SkeletonPtr skel = Ogre::SkeletonManager::getSingleton().getByName(skelinst->getName());
|
||||
boneiter = skel->getBoneIterator();
|
||||
while(boneiter.hasMoreElements())
|
||||
{
|
||||
Ogre::Bone *bone = boneiter.getNext();
|
||||
|
@ -143,43 +120,14 @@ void Animation::setAnimationSources(const std::vector<std::string> &names)
|
|||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Animation::createObjectList(Ogre::SceneNode *node, const std::string &model)
|
||||
{
|
||||
mInsert = node->createChildSceneNode();
|
||||
assert(mInsert);
|
||||
|
||||
mObjectList = NifOgre::Loader::createObjects(mInsert, model);
|
||||
if(mObjectList.mSkelBase)
|
||||
{
|
||||
mSkelBase = mObjectList.mSkelBase;
|
||||
|
||||
Ogre::AnimationStateSet *aset = mSkelBase->getAllAnimationStates();
|
||||
Ogre::AnimationStateIterator asiter = aset->getAnimationStateIterator();
|
||||
while(asiter.hasMoreElements())
|
||||
{
|
||||
Ogre::AnimationState *state = asiter.getNext();
|
||||
state->setEnabled(false);
|
||||
state->setLoop(false);
|
||||
}
|
||||
|
||||
// Set the bones as manually controlled since we're applying the
|
||||
// transformations manually (needed if we want to apply an animation
|
||||
// from one skeleton onto another).
|
||||
Ogre::SkeletonInstance *skelinst = mSkelBase->getSkeleton();
|
||||
Ogre::Skeleton::BoneIterator boneiter = skelinst->getBoneIterator();
|
||||
while(boneiter.hasMoreElements())
|
||||
boneiter.getNext()->setManuallyControlled(true);
|
||||
}
|
||||
|
||||
Ogre::SharedPtr<Ogre::ControllerValue<Ogre::Real> > ctrlval(OGRE_NEW AnimationValue(this));
|
||||
for(size_t i = 0;i < mObjectList.mControllers.size();i++)
|
||||
for(size_t i = 0;i < mObjectLists[0].mControllers.size();i++)
|
||||
{
|
||||
if(mObjectList.mControllers[i].getSource().isNull())
|
||||
mObjectList.mControllers[i].setSource(ctrlval);
|
||||
if(mObjectLists[0].mControllers[i].getSource().isNull())
|
||||
mObjectLists[0].mControllers[i].setSource(ctrlval);
|
||||
}
|
||||
mCurrentControllers = &mObjectList.mControllers;
|
||||
mCurrentControllers = &mObjectLists[0].mControllers;
|
||||
}
|
||||
|
||||
|
||||
|
@ -197,9 +145,9 @@ Ogre::Node *Animation::getNode(const std::string &name)
|
|||
|
||||
bool Animation::hasAnimation(const std::string &anim)
|
||||
{
|
||||
for(std::vector<NifOgre::ObjectList>::const_iterator iter(mAnimationSources.begin());iter != mAnimationSources.end();iter++)
|
||||
for(std::vector<NifOgre::ObjectList>::const_iterator iter(mObjectLists.begin());iter != mObjectLists.end();iter++)
|
||||
{
|
||||
if(iter->mSkelBase->hasAnimationState(anim))
|
||||
if(iter->mSkelBase && iter->mSkelBase->hasAnimationState(anim))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -449,7 +397,7 @@ void Animation::play(const std::string &groupname, const std::string &start, con
|
|||
try {
|
||||
bool found = false;
|
||||
/* Look in reverse; last-inserted source has priority. */
|
||||
for(std::vector<NifOgre::ObjectList>::reverse_iterator iter(mAnimationSources.rbegin());iter != mAnimationSources.rend();iter++)
|
||||
for(std::vector<NifOgre::ObjectList>::reverse_iterator iter(mObjectLists.rbegin());iter != mObjectLists.rend();iter++)
|
||||
{
|
||||
if(iter->mSkelBase->hasAnimationState(groupname))
|
||||
{
|
||||
|
@ -513,9 +461,19 @@ Ogre::Vector3 Animation::runAnimation(float timepassed)
|
|||
|
||||
if(mSkelBase)
|
||||
{
|
||||
// HACK: Dirty the animation state set so that Ogre will apply the
|
||||
// transformations to entities this skeleton instance is shared with.
|
||||
mSkelBase->getAllAnimationStates()->_notifyDirty();
|
||||
const Ogre::SkeletonInstance *skelsrc = mSkelBase->getSkeleton();
|
||||
for(size_t i = 0;i < mObjectLists.size();i++)
|
||||
{
|
||||
Ogre::Entity *ent = mObjectLists[i].mSkelBase;
|
||||
if(!ent) continue;
|
||||
|
||||
Ogre::SkeletonInstance *skeldst = ent->getSkeleton();
|
||||
if(skelsrc != skeldst)
|
||||
updateSkeletonInstance(skelsrc, skeldst);
|
||||
// HACK: Dirty the animation state set so that Ogre will apply the
|
||||
// transformations to entities this skeleton instance is shared with.
|
||||
ent->getAllAnimationStates()->_notifyDirty();
|
||||
}
|
||||
}
|
||||
|
||||
return movement;
|
||||
|
|
|
@ -44,15 +44,13 @@ protected:
|
|||
|
||||
Ogre::SceneNode *mInsert;
|
||||
Ogre::Entity *mSkelBase;
|
||||
NifOgre::ObjectList mObjectList;
|
||||
std::vector<NifOgre::ObjectList> mObjectLists;
|
||||
std::map<std::string,NifOgre::TextKeyMap> mTextKeys;
|
||||
Ogre::Node *mAccumRoot;
|
||||
Ogre::Bone *mNonAccumRoot;
|
||||
Ogre::Vector3 mAccumulate;
|
||||
Ogre::Vector3 mLastPosition;
|
||||
|
||||
std::vector<NifOgre::ObjectList> mAnimationSources;
|
||||
|
||||
std::vector<Ogre::Controller<Ogre::Real> > *mCurrentControllers;
|
||||
NifOgre::TextKeyMap *mCurrentKeys;
|
||||
NifOgre::TextKeyMap::const_iterator mNextKey;
|
||||
|
@ -83,16 +81,6 @@ protected:
|
|||
|
||||
bool handleEvent(float time, const std::string &evt);
|
||||
|
||||
/* Specifies a list of skeleton names to use as animation sources. */
|
||||
void setAnimationSources(const std::vector<std::string> &names);
|
||||
|
||||
/* Specifies a single skeleton name to use as an animation source. */
|
||||
void setAnimationSource(const std::string &name)
|
||||
{
|
||||
std::vector<std::string> names(1, name);
|
||||
setAnimationSources(names);
|
||||
}
|
||||
|
||||
void createObjectList(Ogre::SceneNode *node, const std::string &model);
|
||||
static void destroyObjectList(Ogre::SceneManager *sceneMgr, NifOgre::ObjectList &objects);
|
||||
|
||||
|
|
|
@ -26,10 +26,15 @@ CreatureAnimation::CreatureAnimation(const MWWorld::Ptr &ptr)
|
|||
{
|
||||
std::string model = "meshes\\"+ref->mBase->mModel;
|
||||
|
||||
createObjectList(mPtr.getRefData().getBaseNode(), model);
|
||||
for(size_t i = 0;i < mObjectList.mEntities.size();i++)
|
||||
std::vector<std::string> names;
|
||||
if((ref->mBase->mFlags&ESM::Creature::Biped))
|
||||
names.push_back("meshes\\base_anim.nif");
|
||||
names.push_back(model);
|
||||
|
||||
createObjectList(mPtr.getRefData().getBaseNode(), model/*names*/);
|
||||
for(size_t i = 0;i < mObjectLists[0].mEntities.size();i++)
|
||||
{
|
||||
Ogre::Entity *ent = mObjectList.mEntities[i];
|
||||
Ogre::Entity *ent = mObjectLists[0].mEntities[i];
|
||||
ent->setVisibilityFlags(RV_Actors);
|
||||
|
||||
for(unsigned int j=0; j < ent->getNumSubEntities(); ++j)
|
||||
|
@ -38,19 +43,13 @@ CreatureAnimation::CreatureAnimation(const MWWorld::Ptr &ptr)
|
|||
subEnt->setRenderQueueGroup(subEnt->getMaterial()->isTransparent() ? RQG_Alpha : RQG_Main);
|
||||
}
|
||||
}
|
||||
for(size_t i = 0;i < mObjectList.mParticles.size();i++)
|
||||
for(size_t i = 0;i < mObjectLists[0].mParticles.size();i++)
|
||||
{
|
||||
Ogre::ParticleSystem *part = mObjectList.mParticles[i];
|
||||
Ogre::ParticleSystem *part = mObjectLists[0].mParticles[i];
|
||||
part->setVisibilityFlags(RV_Actors);
|
||||
|
||||
part->setRenderQueueGroup(RQG_Alpha);
|
||||
}
|
||||
|
||||
std::vector<std::string> names;
|
||||
if((ref->mBase->mFlags&ESM::Creature::Biped))
|
||||
names.push_back("meshes\\base_anim.nif");
|
||||
names.push_back(model);
|
||||
setAnimationSources(names);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -96,10 +96,18 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, MWWor
|
|||
bool isBeast = (race->mData.mFlags & ESM::Race::Beast) != 0;
|
||||
std::string smodel = (!isBeast ? "meshes\\base_anim.nif" : "meshes\\base_animkna.nif");
|
||||
|
||||
createObjectList(node, smodel);
|
||||
for(size_t i = 0;i < mObjectList.mEntities.size();i++)
|
||||
std::vector<std::string> skelnames(1, smodel);
|
||||
if(!mNpc->isMale() && !isBeast)
|
||||
skelnames.push_back("meshes\\base_anim_female.nif");
|
||||
else if(mBodyPrefix.find("argonian") != std::string::npos)
|
||||
skelnames.push_back("meshes\\argonian_swimkna.nif");
|
||||
if(mNpc->mModel.length() > 0)
|
||||
skelnames.push_back("meshes\\"+Misc::StringUtils::lowerCase(mNpc->mModel));
|
||||
|
||||
createObjectList(node, smodel/*skelnames*/);
|
||||
for(size_t i = 0;i < mObjectLists[0].mEntities.size();i++)
|
||||
{
|
||||
Ogre::Entity *base = mObjectList.mEntities[i];
|
||||
Ogre::Entity *base = mObjectLists[0].mEntities[i];
|
||||
|
||||
base->getUserObjectBindings().setUserAny(Ogre::Any(-1));
|
||||
if (mVisibilityFlags != 0)
|
||||
|
@ -111,9 +119,9 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, MWWor
|
|||
subEnt->setRenderQueueGroup(subEnt->getMaterial()->isTransparent() ? RQG_Alpha : RQG_Main);
|
||||
}
|
||||
}
|
||||
for(size_t i = 0;i < mObjectList.mParticles.size();i++)
|
||||
for(size_t i = 0;i < mObjectLists[0].mParticles.size();i++)
|
||||
{
|
||||
Ogre::ParticleSystem *part = mObjectList.mParticles[i];
|
||||
Ogre::ParticleSystem *part = mObjectLists[0].mParticles[i];
|
||||
|
||||
part->getUserObjectBindings().setUserAny(Ogre::Any(-1));
|
||||
if(mVisibilityFlags != 0)
|
||||
|
@ -121,15 +129,6 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, MWWor
|
|||
part->setRenderQueueGroup(RQG_Alpha);
|
||||
}
|
||||
|
||||
std::vector<std::string> skelnames(1, smodel);
|
||||
if(!mNpc->isMale() && !isBeast)
|
||||
skelnames.push_back("meshes\\base_anim_female.nif");
|
||||
else if(mBodyPrefix.find("argonian") != std::string::npos)
|
||||
skelnames.push_back("meshes\\argonian_swimkna.nif");
|
||||
if(mNpc->mModel.length() > 0)
|
||||
skelnames.push_back("meshes\\"+Misc::StringUtils::lowerCase(mNpc->mModel));
|
||||
setAnimationSources(skelnames);
|
||||
|
||||
forceUpdate();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue