forked from teamnwah/openmw-tes3coop
Allow multiple ObjectLists to be created for Animations.
addObjectList may not currently be called outside of the related constructor.
This commit is contained in:
parent
69084139aa
commit
1b1f9f7921
7 changed files with 82 additions and 78 deletions
|
@ -24,12 +24,13 @@ ActivatorAnimation::ActivatorAnimation(const MWWorld::Ptr &ptr)
|
||||||
assert (ref->mBase != NULL);
|
assert (ref->mBase != NULL);
|
||||||
if(!ref->mBase->mModel.empty())
|
if(!ref->mBase->mModel.empty())
|
||||||
{
|
{
|
||||||
std::string mesh = "meshes\\" + ref->mBase->mModel;
|
const std::string name = "meshes\\"+ref->mBase->mModel;
|
||||||
|
|
||||||
createObjectList(mPtr.getRefData().getBaseNode(), mesh);
|
addObjectList(mPtr.getRefData().getBaseNode(), name, false);
|
||||||
for(size_t i = 0;i < mObjectLists[0].mEntities.size();i++)
|
const NifOgre::ObjectList &objlist = mObjectLists.back();
|
||||||
|
for(size_t i = 0;i < objlist.mEntities.size();i++)
|
||||||
{
|
{
|
||||||
Ogre::Entity *ent = mObjectLists[0].mEntities[i];
|
Ogre::Entity *ent = objlist.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,9 +39,9 @@ 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 < mObjectLists[0].mParticles.size();i++)
|
for(size_t i = 0;i < objlist.mParticles.size();i++)
|
||||||
{
|
{
|
||||||
Ogre::ParticleSystem *part = mObjectLists[0].mParticles[i];
|
Ogre::ParticleSystem *part = objlist.mParticles[i];
|
||||||
part->setVisibilityFlags(RV_Misc);
|
part->setVisibilityFlags(RV_Misc);
|
||||||
part->setRenderQueueGroup(RQG_Alpha);
|
part->setRenderQueueGroup(RQG_Alpha);
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ Animation::Animation(const MWWorld::Ptr &ptr)
|
||||||
, mSkelBase(NULL)
|
, mSkelBase(NULL)
|
||||||
, mAccumRoot(NULL)
|
, mAccumRoot(NULL)
|
||||||
, mNonAccumRoot(NULL)
|
, mNonAccumRoot(NULL)
|
||||||
, mAccumulate(Ogre::Vector3::ZERO)
|
, mAccumulate(0.0f)
|
||||||
, mLastPosition(0.0f)
|
, mLastPosition(0.0f)
|
||||||
, mCurrentControllers(NULL)
|
, mCurrentControllers(NULL)
|
||||||
, mCurrentKeys(NULL)
|
, mCurrentKeys(NULL)
|
||||||
|
@ -62,20 +62,24 @@ Animation::~Animation()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Animation::createObjectList(Ogre::SceneNode *node, const std::string &model)
|
void Animation::addObjectList(Ogre::SceneNode *node, const std::string &model, bool baseonly)
|
||||||
|
{
|
||||||
|
if(!mInsert)
|
||||||
{
|
{
|
||||||
assert(!mInsert);
|
|
||||||
mInsert = node->createChildSceneNode();
|
mInsert = node->createChildSceneNode();
|
||||||
assert(mInsert);
|
assert(mInsert);
|
||||||
|
}
|
||||||
|
Ogre::SharedPtr<Ogre::ControllerValue<Ogre::Real> > ctrlval(OGRE_NEW AnimationValue(this));
|
||||||
|
|
||||||
mObjectLists.resize(1);
|
mObjectLists.push_back(!baseonly ? NifOgre::Loader::createObjects(mInsert, model) :
|
||||||
|
NifOgre::Loader::createObjectBase(mInsert, model));
|
||||||
mObjectLists[0] = NifOgre::Loader::createObjects(mInsert, model);
|
NifOgre::ObjectList &objlist = mObjectLists.back();
|
||||||
if(mObjectLists[0].mSkelBase)
|
if(objlist.mSkelBase)
|
||||||
{
|
{
|
||||||
mSkelBase = mObjectLists[0].mSkelBase;
|
if(!mSkelBase)
|
||||||
|
mSkelBase = objlist.mSkelBase;
|
||||||
|
|
||||||
Ogre::AnimationStateSet *aset = mObjectLists[0].mSkelBase->getAllAnimationStates();
|
Ogre::AnimationStateSet *aset = objlist.mSkelBase->getAllAnimationStates();
|
||||||
Ogre::AnimationStateIterator asiter = aset->getAnimationStateIterator();
|
Ogre::AnimationStateIterator asiter = aset->getAnimationStateIterator();
|
||||||
while(asiter.hasMoreElements())
|
while(asiter.hasMoreElements())
|
||||||
{
|
{
|
||||||
|
@ -87,11 +91,28 @@ void Animation::createObjectList(Ogre::SceneNode *node, const std::string &model
|
||||||
// Set the bones as manually controlled since we're applying the
|
// Set the bones as manually controlled since we're applying the
|
||||||
// transformations manually (needed if we want to apply an animation
|
// transformations manually (needed if we want to apply an animation
|
||||||
// from one skeleton onto another).
|
// from one skeleton onto another).
|
||||||
Ogre::SkeletonInstance *skelinst = mObjectLists[0].mSkelBase->getSkeleton();
|
Ogre::SkeletonInstance *skelinst = objlist.mSkelBase->getSkeleton();
|
||||||
Ogre::Skeleton::BoneIterator boneiter = skelinst->getBoneIterator();
|
Ogre::Skeleton::BoneIterator boneiter = skelinst->getBoneIterator();
|
||||||
while(boneiter.hasMoreElements())
|
while(boneiter.hasMoreElements())
|
||||||
boneiter.getNext()->setManuallyControlled(true);
|
boneiter.getNext()->setManuallyControlled(true);
|
||||||
|
|
||||||
|
if(mSkelBase != objlist.mSkelBase)
|
||||||
|
{
|
||||||
|
Ogre::SkeletonInstance *baseinst = mSkelBase->getSkeleton();
|
||||||
|
for(size_t i = 0;i < objlist.mControllers.size();i++)
|
||||||
|
{
|
||||||
|
NifOgre::NodeTargetValue<Ogre::Real> *dstval;
|
||||||
|
dstval = dynamic_cast<NifOgre::NodeTargetValue<Ogre::Real>*>(objlist.mControllers[i].getDestination().getPointer());
|
||||||
|
if(!dstval) continue;
|
||||||
|
|
||||||
|
const Ogre::String &trgtname = dstval->getNode()->getName();
|
||||||
|
if(!baseinst->hasBone(trgtname)) continue;
|
||||||
|
|
||||||
|
Ogre::Bone *bone = baseinst->getBone(trgtname);
|
||||||
|
dstval->setNode(bone);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ogre::SkeletonPtr skel = Ogre::SkeletonManager::getSingleton().getByName(skelinst->getName());
|
Ogre::SkeletonPtr skel = Ogre::SkeletonManager::getSingleton().getByName(skelinst->getName());
|
||||||
boneiter = skel->getBoneIterator();
|
boneiter = skel->getBoneIterator();
|
||||||
while(boneiter.hasMoreElements())
|
while(boneiter.hasMoreElements())
|
||||||
|
@ -120,14 +141,14 @@ void Animation::createObjectList(Ogre::SceneNode *node, const std::string &model
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for(size_t i = 0;i < objlist.mControllers.size();i++)
|
||||||
Ogre::SharedPtr<Ogre::ControllerValue<Ogre::Real> > ctrlval(OGRE_NEW AnimationValue(this));
|
|
||||||
for(size_t i = 0;i < mObjectLists[0].mControllers.size();i++)
|
|
||||||
{
|
{
|
||||||
if(mObjectLists[0].mControllers[i].getSource().isNull())
|
if(objlist.mControllers[i].getSource().isNull())
|
||||||
mObjectLists[0].mControllers[i].setSource(ctrlval);
|
objlist.mControllers[i].setSource(ctrlval);
|
||||||
}
|
}
|
||||||
mCurrentControllers = &mObjectLists[0].mControllers;
|
|
||||||
|
if(!mCurrentControllers || (*mCurrentControllers).size() == 0)
|
||||||
|
mCurrentControllers = &objlist.mControllers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -399,9 +420,10 @@ void Animation::play(const std::string &groupname, const std::string &start, con
|
||||||
/* Look in reverse; last-inserted source has priority. */
|
/* Look in reverse; last-inserted source has priority. */
|
||||||
for(std::vector<NifOgre::ObjectList>::reverse_iterator iter(mObjectLists.rbegin());iter != mObjectLists.rend();iter++)
|
for(std::vector<NifOgre::ObjectList>::reverse_iterator iter(mObjectLists.rbegin());iter != mObjectLists.rend();iter++)
|
||||||
{
|
{
|
||||||
if(iter->mSkelBase->hasAnimationState(groupname))
|
if(iter->mSkelBase && iter->mSkelBase->hasAnimationState(groupname))
|
||||||
{
|
{
|
||||||
mCurrentAnim = iter->mSkelBase->getSkeleton()->getAnimation(groupname);
|
Ogre::SkeletonInstance *skel = iter->mSkelBase->getSkeleton();
|
||||||
|
mCurrentAnim = skel->getAnimation(groupname);
|
||||||
mCurrentKeys = &mTextKeys[groupname];
|
mCurrentKeys = &mTextKeys[groupname];
|
||||||
mCurrentControllers = &iter->mControllers;
|
mCurrentControllers = &iter->mControllers;
|
||||||
mAnimVelocity = 0.0f;
|
mAnimVelocity = 0.0f;
|
||||||
|
@ -456,20 +478,22 @@ Ogre::Vector3 Animation::runAnimation(float timepassed)
|
||||||
if(!handleEvent(time, evt))
|
if(!handleEvent(time, evt))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
for(size_t i = 0;i < mCurrentControllers->size();i++)
|
|
||||||
|
for(size_t i = 0;i < (*mCurrentControllers).size();i++)
|
||||||
(*mCurrentControllers)[i].update();
|
(*mCurrentControllers)[i].update();
|
||||||
|
|
||||||
if(mSkelBase)
|
if(mSkelBase)
|
||||||
{
|
{
|
||||||
const Ogre::SkeletonInstance *skelsrc = mSkelBase->getSkeleton();
|
const Ogre::SkeletonInstance *baseinst = mSkelBase->getSkeleton();
|
||||||
for(size_t i = 0;i < mObjectLists.size();i++)
|
for(std::vector<NifOgre::ObjectList>::iterator iter(mObjectLists.begin());iter != mObjectLists.end();iter++)
|
||||||
{
|
{
|
||||||
Ogre::Entity *ent = mObjectLists[i].mSkelBase;
|
Ogre::Entity *ent = iter->mSkelBase;
|
||||||
if(!ent) continue;
|
if(!ent) continue;
|
||||||
|
|
||||||
Ogre::SkeletonInstance *skeldst = ent->getSkeleton();
|
Ogre::SkeletonInstance *inst = ent->getSkeleton();
|
||||||
if(skelsrc != skeldst)
|
if(baseinst != inst)
|
||||||
updateSkeletonInstance(skelsrc, skeldst);
|
updateSkeletonInstance(baseinst, inst);
|
||||||
|
|
||||||
// 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.
|
||||||
ent->getAllAnimationStates()->_notifyDirty();
|
ent->getAllAnimationStates()->_notifyDirty();
|
||||||
|
|
|
@ -81,7 +81,7 @@ protected:
|
||||||
|
|
||||||
bool handleEvent(float time, const std::string &evt);
|
bool handleEvent(float time, const std::string &evt);
|
||||||
|
|
||||||
void createObjectList(Ogre::SceneNode *node, const std::string &model);
|
void addObjectList(Ogre::SceneNode *node, const std::string &model, bool baseonly);
|
||||||
static void destroyObjectList(Ogre::SceneManager *sceneMgr, NifOgre::ObjectList &objects);
|
static void destroyObjectList(Ogre::SceneManager *sceneMgr, NifOgre::ObjectList &objects);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -26,15 +26,15 @@ CreatureAnimation::CreatureAnimation(const MWWorld::Ptr &ptr)
|
||||||
{
|
{
|
||||||
std::string model = "meshes\\"+ref->mBase->mModel;
|
std::string model = "meshes\\"+ref->mBase->mModel;
|
||||||
|
|
||||||
std::vector<std::string> names;
|
|
||||||
if((ref->mBase->mFlags&ESM::Creature::Biped))
|
if((ref->mBase->mFlags&ESM::Creature::Biped))
|
||||||
names.push_back("meshes\\base_anim.nif");
|
addObjectList(mPtr.getRefData().getBaseNode(), "meshes\\base_anim.nif", true);
|
||||||
names.push_back(model);
|
|
||||||
|
|
||||||
createObjectList(mPtr.getRefData().getBaseNode(), model/*names*/);
|
addObjectList(mPtr.getRefData().getBaseNode(), model, false);
|
||||||
for(size_t i = 0;i < mObjectLists[0].mEntities.size();i++)
|
|
||||||
|
const NifOgre::ObjectList &objlist = mObjectLists.back();
|
||||||
|
for(size_t i = 0;i < objlist.mEntities.size();i++)
|
||||||
{
|
{
|
||||||
Ogre::Entity *ent = mObjectLists[0].mEntities[i];
|
Ogre::Entity *ent = objlist.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)
|
||||||
|
@ -43,11 +43,10 @@ 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 < mObjectLists[0].mParticles.size();i++)
|
for(size_t i = 0;i < objlist.mParticles.size();i++)
|
||||||
{
|
{
|
||||||
Ogre::ParticleSystem *part = mObjectLists[0].mParticles[i];
|
Ogre::ParticleSystem *part = objlist.mParticles[i];
|
||||||
part->setVisibilityFlags(RV_Actors);
|
part->setVisibilityFlags(RV_Actors);
|
||||||
|
|
||||||
part->setRenderQueueGroup(RQG_Alpha);
|
part->setRenderQueueGroup(RQG_Alpha);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,38 +96,13 @@ 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");
|
||||||
|
|
||||||
std::vector<std::string> skelnames(1, smodel);
|
addObjectList(node, smodel, true);
|
||||||
if(!mNpc->isMale() && !isBeast)
|
if(!mNpc->isMale() && !isBeast)
|
||||||
skelnames.push_back("meshes\\base_anim_female.nif");
|
addObjectList(node, "meshes\\base_anim_female.nif", true);
|
||||||
else if(mBodyPrefix.find("argonian") != std::string::npos)
|
else if(mBodyPrefix.find("argonian") != std::string::npos)
|
||||||
skelnames.push_back("meshes\\argonian_swimkna.nif");
|
addObjectList(node, "meshes\\argonian_swimkna.nif", true);
|
||||||
if(mNpc->mModel.length() > 0)
|
if(mNpc->mModel.length() > 0)
|
||||||
skelnames.push_back("meshes\\"+Misc::StringUtils::lowerCase(mNpc->mModel));
|
addObjectList(node, "meshes\\"+mNpc->mModel, true);
|
||||||
|
|
||||||
createObjectList(node, smodel/*skelnames*/);
|
|
||||||
for(size_t i = 0;i < mObjectLists[0].mEntities.size();i++)
|
|
||||||
{
|
|
||||||
Ogre::Entity *base = mObjectLists[0].mEntities[i];
|
|
||||||
|
|
||||||
base->getUserObjectBindings().setUserAny(Ogre::Any(-1));
|
|
||||||
if (mVisibilityFlags != 0)
|
|
||||||
base->setVisibilityFlags(mVisibilityFlags);
|
|
||||||
|
|
||||||
for(unsigned int j=0; j < base->getNumSubEntities(); ++j)
|
|
||||||
{
|
|
||||||
Ogre::SubEntity* subEnt = base->getSubEntity(j);
|
|
||||||
subEnt->setRenderQueueGroup(subEnt->getMaterial()->isTransparent() ? RQG_Alpha : RQG_Main);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for(size_t i = 0;i < mObjectLists[0].mParticles.size();i++)
|
|
||||||
{
|
|
||||||
Ogre::ParticleSystem *part = mObjectLists[0].mParticles[i];
|
|
||||||
|
|
||||||
part->getUserObjectBindings().setUserAny(Ogre::Any(-1));
|
|
||||||
if(mVisibilityFlags != 0)
|
|
||||||
part->setVisibilityFlags(mVisibilityFlags);
|
|
||||||
part->setRenderQueueGroup(RQG_Alpha);
|
|
||||||
}
|
|
||||||
|
|
||||||
forceUpdate();
|
forceUpdate();
|
||||||
}
|
}
|
||||||
|
@ -406,14 +381,16 @@ Ogre::Vector3 NpcAnimation::runAnimation(float timepassed)
|
||||||
mTimeToChange -= timepassed;
|
mTimeToChange -= timepassed;
|
||||||
|
|
||||||
Ogre::Vector3 ret = Animation::runAnimation(timepassed);
|
Ogre::Vector3 ret = Animation::runAnimation(timepassed);
|
||||||
const Ogre::SkeletonInstance *skelsrc = mSkelBase->getSkeleton();
|
|
||||||
|
Ogre::SkeletonInstance *baseinst = mSkelBase->getSkeleton();
|
||||||
for(size_t i = 0;i < sPartListSize;i++)
|
for(size_t i = 0;i < sPartListSize;i++)
|
||||||
{
|
{
|
||||||
Ogre::Entity *ent = mObjectParts[i].mSkelBase;
|
Ogre::Entity *ent = mObjectParts[i].mSkelBase;
|
||||||
if(!ent) continue;
|
if(!ent) continue;
|
||||||
updateSkeletonInstance(skelsrc, ent->getSkeleton());
|
updateSkeletonInstance(baseinst, ent->getSkeleton());
|
||||||
ent->getAllAnimationStates()->_notifyDirty();
|
ent->getAllAnimationStates()->_notifyDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -800,12 +800,15 @@ ObjectList Loader::createObjects(Ogre::Entity *parent, const std::string &bonena
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ObjectList Loader::createObjectBase(Ogre::SceneManager *sceneMgr, std::string name, const std::string &group)
|
ObjectList Loader::createObjectBase(Ogre::SceneNode *parentNode, std::string name, const std::string &group)
|
||||||
{
|
{
|
||||||
ObjectList objectlist;
|
ObjectList objectlist;
|
||||||
|
|
||||||
Misc::StringUtils::toLower(name);
|
Misc::StringUtils::toLower(name);
|
||||||
NIFObjectLoader::load(sceneMgr, objectlist, name, group, 0xC0000000);
|
NIFObjectLoader::load(parentNode->getCreator(), objectlist, name, group, 0xC0000000);
|
||||||
|
|
||||||
|
if(objectlist.mSkelBase)
|
||||||
|
parentNode->attachObject(objectlist.mSkelBase);
|
||||||
|
|
||||||
return objectlist;
|
return objectlist;
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,7 +69,7 @@ public:
|
||||||
std::string name,
|
std::string name,
|
||||||
const std::string &group="General");
|
const std::string &group="General");
|
||||||
|
|
||||||
static ObjectList createObjectBase(Ogre::SceneManager *sceneMgr,
|
static ObjectList createObjectBase(Ogre::SceneNode *parentNode,
|
||||||
std::string name,
|
std::string name,
|
||||||
const std::string &group="General");
|
const std::string &group="General");
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue