mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-02-19 03:39:58 +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
@ -27,9 +27,9 @@ ActivatorAnimation::ActivatorAnimation(const MWWorld::Ptr &ptr)
|
|||||||
std::string mesh = "meshes\\" + ref->mBase->mModel;
|
std::string mesh = "meshes\\" + ref->mBase->mModel;
|
||||||
|
|
||||||
createObjectList(mPtr.getRefData().getBaseNode(), mesh);
|
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);
|
ent->setVisibilityFlags(RV_Misc);
|
||||||
|
|
||||||
for(unsigned int j=0; j < ent->getNumSubEntities(); ++j)
|
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);
|
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->setVisibilityFlags(RV_Misc);
|
||||||
|
|
||||||
part->setRenderQueueGroup(RQG_Alpha);
|
part->setRenderQueueGroup(RQG_Alpha);
|
||||||
}
|
}
|
||||||
setAnimationSource(mesh);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,68 +55,45 @@ Animation::~Animation()
|
|||||||
if(mInsert)
|
if(mInsert)
|
||||||
{
|
{
|
||||||
Ogre::SceneManager *sceneMgr = mInsert->getCreator();
|
Ogre::SceneManager *sceneMgr = mInsert->getCreator();
|
||||||
destroyObjectList(sceneMgr, mObjectList);
|
for(size_t i = 0;i < mObjectLists.size();i++)
|
||||||
|
destroyObjectList(sceneMgr, mObjectLists[i]);
|
||||||
for(size_t i = 0;i < mAnimationSources.size();i++)
|
mObjectLists.clear();
|
||||||
destroyObjectList(sceneMgr, mAnimationSources[i]);
|
|
||||||
mAnimationSources.clear();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Animation::setAnimationSources(const std::vector<std::string> &names)
|
void Animation::createObjectList(Ogre::SceneNode *node, const std::string &model)
|
||||||
{
|
{
|
||||||
if(!mSkelBase)
|
assert(!mInsert);
|
||||||
return;
|
mInsert = node->createChildSceneNode();
|
||||||
Ogre::SceneManager *sceneMgr = mInsert->getCreator();
|
assert(mInsert);
|
||||||
|
|
||||||
mCurrentControllers = &mObjectList.mControllers;
|
mObjectLists.resize(1);
|
||||||
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();
|
|
||||||
|
|
||||||
Ogre::SharedPtr<Ogre::ControllerValue<Ogre::Real> > ctrlval(OGRE_NEW AnimationValue(this));
|
mObjectLists[0] = NifOgre::Loader::createObjects(mInsert, model);
|
||||||
Ogre::SkeletonInstance *skelinst = mSkelBase->getSkeleton();
|
if(mObjectLists[0].mSkelBase)
|
||||||
std::vector<std::string>::const_iterator nameiter;
|
|
||||||
for(nameiter = names.begin();nameiter != names.end();nameiter++)
|
|
||||||
{
|
{
|
||||||
mAnimationSources.push_back(NifOgre::Loader::createObjectBase(sceneMgr, *nameiter));
|
mSkelBase = mObjectLists[0].mSkelBase;
|
||||||
if(!mAnimationSources.back().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;
|
Ogre::AnimationState *state = asiter.getNext();
|
||||||
destroyObjectList(sceneMgr, mAnimationSources.back());
|
state->setEnabled(false);
|
||||||
mAnimationSources.pop_back();
|
state->setLoop(false);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for(size_t i = 0;i < objects.mControllers.size();i++)
|
// Set the bones as manually controlled since we're applying the
|
||||||
{
|
// transformations manually (needed if we want to apply an animation
|
||||||
if(objects.mControllers[i].getSource().isNull())
|
// from one skeleton onto another).
|
||||||
objects.mControllers[i].setSource(ctrlval);
|
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(skelinst->getName());
|
||||||
Ogre::SkeletonPtr skel = Ogre::SkeletonManager::getSingleton().getByName(ent->getSkeleton()->getName());
|
boneiter = skel->getBoneIterator();
|
||||||
Ogre::Skeleton::BoneIterator boneiter = skel->getBoneIterator();
|
|
||||||
while(boneiter.hasMoreElements())
|
while(boneiter.hasMoreElements())
|
||||||
{
|
{
|
||||||
Ogre::Bone *bone = boneiter.getNext();
|
Ogre::Bone *bone = boneiter.getNext();
|
||||||
@ -143,43 +120,14 @@ void Animation::setAnimationSources(const std::vector<std::string> &names)
|
|||||||
break;
|
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));
|
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())
|
if(mObjectLists[0].mControllers[i].getSource().isNull())
|
||||||
mObjectList.mControllers[i].setSource(ctrlval);
|
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)
|
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 true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -449,7 +397,7 @@ void Animation::play(const std::string &groupname, const std::string &start, con
|
|||||||
try {
|
try {
|
||||||
bool found = false;
|
bool found = false;
|
||||||
/* Look in reverse; last-inserted source has priority. */
|
/* 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))
|
if(iter->mSkelBase->hasAnimationState(groupname))
|
||||||
{
|
{
|
||||||
@ -513,9 +461,19 @@ Ogre::Vector3 Animation::runAnimation(float timepassed)
|
|||||||
|
|
||||||
if(mSkelBase)
|
if(mSkelBase)
|
||||||
{
|
{
|
||||||
|
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
|
// HACK: Dirty the animation state set so that Ogre will apply the
|
||||||
// transformations to entities this skeleton instance is shared with.
|
// transformations to entities this skeleton instance is shared with.
|
||||||
mSkelBase->getAllAnimationStates()->_notifyDirty();
|
ent->getAllAnimationStates()->_notifyDirty();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return movement;
|
return movement;
|
||||||
|
@ -44,15 +44,13 @@ protected:
|
|||||||
|
|
||||||
Ogre::SceneNode *mInsert;
|
Ogre::SceneNode *mInsert;
|
||||||
Ogre::Entity *mSkelBase;
|
Ogre::Entity *mSkelBase;
|
||||||
NifOgre::ObjectList mObjectList;
|
std::vector<NifOgre::ObjectList> mObjectLists;
|
||||||
std::map<std::string,NifOgre::TextKeyMap> mTextKeys;
|
std::map<std::string,NifOgre::TextKeyMap> mTextKeys;
|
||||||
Ogre::Node *mAccumRoot;
|
Ogre::Node *mAccumRoot;
|
||||||
Ogre::Bone *mNonAccumRoot;
|
Ogre::Bone *mNonAccumRoot;
|
||||||
Ogre::Vector3 mAccumulate;
|
Ogre::Vector3 mAccumulate;
|
||||||
Ogre::Vector3 mLastPosition;
|
Ogre::Vector3 mLastPosition;
|
||||||
|
|
||||||
std::vector<NifOgre::ObjectList> mAnimationSources;
|
|
||||||
|
|
||||||
std::vector<Ogre::Controller<Ogre::Real> > *mCurrentControllers;
|
std::vector<Ogre::Controller<Ogre::Real> > *mCurrentControllers;
|
||||||
NifOgre::TextKeyMap *mCurrentKeys;
|
NifOgre::TextKeyMap *mCurrentKeys;
|
||||||
NifOgre::TextKeyMap::const_iterator mNextKey;
|
NifOgre::TextKeyMap::const_iterator mNextKey;
|
||||||
@ -83,16 +81,6 @@ protected:
|
|||||||
|
|
||||||
bool handleEvent(float time, const std::string &evt);
|
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);
|
void createObjectList(Ogre::SceneNode *node, const std::string &model);
|
||||||
static void destroyObjectList(Ogre::SceneManager *sceneMgr, NifOgre::ObjectList &objects);
|
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;
|
std::string model = "meshes\\"+ref->mBase->mModel;
|
||||||
|
|
||||||
createObjectList(mPtr.getRefData().getBaseNode(), model);
|
std::vector<std::string> names;
|
||||||
for(size_t i = 0;i < mObjectList.mEntities.size();i++)
|
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);
|
ent->setVisibilityFlags(RV_Actors);
|
||||||
|
|
||||||
for(unsigned int j=0; j < ent->getNumSubEntities(); ++j)
|
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);
|
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->setVisibilityFlags(RV_Actors);
|
||||||
|
|
||||||
part->setRenderQueueGroup(RQG_Alpha);
|
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;
|
bool isBeast = (race->mData.mFlags & ESM::Race::Beast) != 0;
|
||||||
std::string smodel = (!isBeast ? "meshes\\base_anim.nif" : "meshes\\base_animkna.nif");
|
std::string smodel = (!isBeast ? "meshes\\base_anim.nif" : "meshes\\base_animkna.nif");
|
||||||
|
|
||||||
createObjectList(node, smodel);
|
std::vector<std::string> skelnames(1, smodel);
|
||||||
for(size_t i = 0;i < mObjectList.mEntities.size();i++)
|
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));
|
base->getUserObjectBindings().setUserAny(Ogre::Any(-1));
|
||||||
if (mVisibilityFlags != 0)
|
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);
|
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));
|
part->getUserObjectBindings().setUserAny(Ogre::Any(-1));
|
||||||
if(mVisibilityFlags != 0)
|
if(mVisibilityFlags != 0)
|
||||||
@ -121,15 +129,6 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, MWWor
|
|||||||
part->setRenderQueueGroup(RQG_Alpha);
|
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();
|
forceUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user