mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-19 21:23:52 +00:00
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);
|
||||
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);
|
||||
for(size_t i = 0;i < mObjectLists[0].mEntities.size();i++)
|
||||
addObjectList(mPtr.getRefData().getBaseNode(), name, false);
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
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->setRenderQueueGroup(RQG_Alpha);
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ Animation::Animation(const MWWorld::Ptr &ptr)
|
|||
, mSkelBase(NULL)
|
||||
, mAccumRoot(NULL)
|
||||
, mNonAccumRoot(NULL)
|
||||
, mAccumulate(Ogre::Vector3::ZERO)
|
||||
, mAccumulate(0.0f)
|
||||
, mLastPosition(0.0f)
|
||||
, mCurrentControllers(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();
|
||||
assert(mInsert);
|
||||
}
|
||||
Ogre::SharedPtr<Ogre::ControllerValue<Ogre::Real> > ctrlval(OGRE_NEW AnimationValue(this));
|
||||
|
||||
mObjectLists.resize(1);
|
||||
|
||||
mObjectLists[0] = NifOgre::Loader::createObjects(mInsert, model);
|
||||
if(mObjectLists[0].mSkelBase)
|
||||
mObjectLists.push_back(!baseonly ? NifOgre::Loader::createObjects(mInsert, model) :
|
||||
NifOgre::Loader::createObjectBase(mInsert, model));
|
||||
NifOgre::ObjectList &objlist = mObjectLists.back();
|
||||
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();
|
||||
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
|
||||
// transformations manually (needed if we want to apply an animation
|
||||
// from one skeleton onto another).
|
||||
Ogre::SkeletonInstance *skelinst = mObjectLists[0].mSkelBase->getSkeleton();
|
||||
Ogre::SkeletonInstance *skelinst = objlist.mSkelBase->getSkeleton();
|
||||
Ogre::Skeleton::BoneIterator boneiter = skelinst->getBoneIterator();
|
||||
while(boneiter.hasMoreElements())
|
||||
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());
|
||||
boneiter = skel->getBoneIterator();
|
||||
while(boneiter.hasMoreElements())
|
||||
|
@ -120,14 +141,14 @@ void Animation::createObjectList(Ogre::SceneNode *node, const std::string &model
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Ogre::SharedPtr<Ogre::ControllerValue<Ogre::Real> > ctrlval(OGRE_NEW AnimationValue(this));
|
||||
for(size_t i = 0;i < mObjectLists[0].mControllers.size();i++)
|
||||
for(size_t i = 0;i < objlist.mControllers.size();i++)
|
||||
{
|
||||
if(mObjectLists[0].mControllers[i].getSource().isNull())
|
||||
mObjectLists[0].mControllers[i].setSource(ctrlval);
|
||||
if(objlist.mControllers[i].getSource().isNull())
|
||||
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. */
|
||||
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];
|
||||
mCurrentControllers = &iter->mControllers;
|
||||
mAnimVelocity = 0.0f;
|
||||
|
@ -456,20 +478,22 @@ Ogre::Vector3 Animation::runAnimation(float timepassed)
|
|||
if(!handleEvent(time, evt))
|
||||
break;
|
||||
}
|
||||
for(size_t i = 0;i < mCurrentControllers->size();i++)
|
||||
|
||||
for(size_t i = 0;i < (*mCurrentControllers).size();i++)
|
||||
(*mCurrentControllers)[i].update();
|
||||
|
||||
if(mSkelBase)
|
||||
{
|
||||
const Ogre::SkeletonInstance *skelsrc = mSkelBase->getSkeleton();
|
||||
for(size_t i = 0;i < mObjectLists.size();i++)
|
||||
const Ogre::SkeletonInstance *baseinst = mSkelBase->getSkeleton();
|
||||
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;
|
||||
|
||||
Ogre::SkeletonInstance *skeldst = ent->getSkeleton();
|
||||
if(skelsrc != skeldst)
|
||||
updateSkeletonInstance(skelsrc, skeldst);
|
||||
Ogre::SkeletonInstance *inst = ent->getSkeleton();
|
||||
if(baseinst != inst)
|
||||
updateSkeletonInstance(baseinst, inst);
|
||||
|
||||
// HACK: Dirty the animation state set so that Ogre will apply the
|
||||
// transformations to entities this skeleton instance is shared with.
|
||||
ent->getAllAnimationStates()->_notifyDirty();
|
||||
|
|
|
@ -81,7 +81,7 @@ protected:
|
|||
|
||||
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);
|
||||
|
||||
public:
|
||||
|
|
|
@ -26,15 +26,15 @@ CreatureAnimation::CreatureAnimation(const MWWorld::Ptr &ptr)
|
|||
{
|
||||
std::string model = "meshes\\"+ref->mBase->mModel;
|
||||
|
||||
std::vector<std::string> names;
|
||||
if((ref->mBase->mFlags&ESM::Creature::Biped))
|
||||
names.push_back("meshes\\base_anim.nif");
|
||||
names.push_back(model);
|
||||
addObjectList(mPtr.getRefData().getBaseNode(), "meshes\\base_anim.nif", true);
|
||||
|
||||
createObjectList(mPtr.getRefData().getBaseNode(), model/*names*/);
|
||||
for(size_t i = 0;i < mObjectLists[0].mEntities.size();i++)
|
||||
addObjectList(mPtr.getRefData().getBaseNode(), model, false);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
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->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;
|
||||
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)
|
||||
skelnames.push_back("meshes\\base_anim_female.nif");
|
||||
addObjectList(node, "meshes\\base_anim_female.nif", true);
|
||||
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)
|
||||
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 = 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);
|
||||
}
|
||||
addObjectList(node, "meshes\\"+mNpc->mModel, true);
|
||||
|
||||
forceUpdate();
|
||||
}
|
||||
|
@ -406,14 +381,16 @@ Ogre::Vector3 NpcAnimation::runAnimation(float timepassed)
|
|||
mTimeToChange -= 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++)
|
||||
{
|
||||
Ogre::Entity *ent = mObjectParts[i].mSkelBase;
|
||||
if(!ent) continue;
|
||||
updateSkeletonInstance(skelsrc, ent->getSkeleton());
|
||||
updateSkeletonInstance(baseinst, ent->getSkeleton());
|
||||
ent->getAllAnimationStates()->_notifyDirty();
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -69,7 +69,7 @@ public:
|
|||
std::string name,
|
||||
const std::string &group="General");
|
||||
|
||||
static ObjectList createObjectBase(Ogre::SceneManager *sceneMgr,
|
||||
static ObjectList createObjectBase(Ogre::SceneNode *parentNode,
|
||||
std::string name,
|
||||
const std::string &group="General");
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue