mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-03-29 13:20:35 +00:00
Only load one Nif for Animation objects
This breaks quite a bit, but it's needed for the transition to using the .kf files.
This commit is contained in:
parent
6a3ba41170
commit
e85bc8b2cd
@ -21,8 +21,8 @@ ActivatorAnimation::ActivatorAnimation(const MWWorld::Ptr &ptr)
|
|||||||
{
|
{
|
||||||
const std::string name = "meshes\\"+ref->mBase->mModel;
|
const std::string name = "meshes\\"+ref->mBase->mModel;
|
||||||
|
|
||||||
addObjectList(mPtr.getRefData().getBaseNode(), name, false);
|
setObjectRoot(mPtr.getRefData().getBaseNode(), name, false);
|
||||||
setRenderProperties(mObjects.back().mObjectList, RV_Misc, RQG_Main, RQG_Alpha);
|
setRenderProperties(mObjectRoot, RV_Misc, RQG_Main, RQG_Alpha);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,10 +70,6 @@ Animation::Animation(const MWWorld::Ptr &ptr)
|
|||||||
{
|
{
|
||||||
for(size_t i = 0;i < sMaxLayers;i++)
|
for(size_t i = 0;i < sMaxLayers;i++)
|
||||||
mAnimationValuePtr[i].bind(OGRE_NEW AnimationValue(this, i));
|
mAnimationValuePtr[i].bind(OGRE_NEW AnimationValue(this, i));
|
||||||
|
|
||||||
/* As long as we remain under 128 active controllers, we can avoid
|
|
||||||
* reallocations. */
|
|
||||||
mActiveCtrls.reserve(128);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Animation::~Animation()
|
Animation::~Animation()
|
||||||
@ -81,34 +77,23 @@ Animation::~Animation()
|
|||||||
if(mInsert)
|
if(mInsert)
|
||||||
{
|
{
|
||||||
Ogre::SceneManager *sceneMgr = mInsert->getCreator();
|
Ogre::SceneManager *sceneMgr = mInsert->getCreator();
|
||||||
for(size_t i = 0;i < mObjects.size();i++)
|
destroyObjectList(sceneMgr, mObjectRoot);
|
||||||
destroyObjectList(sceneMgr, mObjects[i].mObjectList);
|
|
||||||
mObjects.clear();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Animation::addObjectList(Ogre::SceneNode *node, const std::string &model, bool baseonly)
|
void Animation::setObjectRoot(Ogre::SceneNode *node, const std::string &model, bool baseonly)
|
||||||
{
|
{
|
||||||
if(!mInsert)
|
OgreAssert(!mInsert, "Object already has a root!");
|
||||||
|
mInsert = node->createChildSceneNode();
|
||||||
|
|
||||||
|
mObjectRoot = (!baseonly ? NifOgre::Loader::createObjects(mInsert, model) :
|
||||||
|
NifOgre::Loader::createObjectBase(mInsert, model));
|
||||||
|
if(mObjectRoot.mSkelBase)
|
||||||
{
|
{
|
||||||
mInsert = node->createChildSceneNode();
|
mSkelBase = mObjectRoot.mSkelBase;
|
||||||
assert(mInsert);
|
|
||||||
}
|
|
||||||
|
|
||||||
mObjects.push_back(ObjectInfo());
|
Ogre::AnimationStateSet *aset = mObjectRoot.mSkelBase->getAllAnimationStates();
|
||||||
ObjectInfo &obj = mObjects.back();
|
|
||||||
obj.mActiveLayers = 0;
|
|
||||||
obj.mObjectList = (!baseonly ? NifOgre::Loader::createObjects(mInsert, model) :
|
|
||||||
NifOgre::Loader::createObjectBase(mInsert, model));
|
|
||||||
|
|
||||||
NifOgre::ObjectList &objlist = obj.mObjectList;
|
|
||||||
if(objlist.mSkelBase)
|
|
||||||
{
|
|
||||||
if(mObjects.size() == 1)
|
|
||||||
mSkelBase = objlist.mSkelBase;
|
|
||||||
|
|
||||||
Ogre::AnimationStateSet *aset = objlist.mSkelBase->getAllAnimationStates();
|
|
||||||
Ogre::AnimationStateIterator asiter = aset->getAnimationStateIterator();
|
Ogre::AnimationStateIterator asiter = aset->getAnimationStateIterator();
|
||||||
while(asiter.hasMoreElements())
|
while(asiter.hasMoreElements())
|
||||||
{
|
{
|
||||||
@ -120,45 +105,22 @@ void Animation::addObjectList(Ogre::SceneNode *node, const std::string &model, b
|
|||||||
// 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 = objlist.mSkelBase->getSkeleton();
|
Ogre::SkeletonInstance *skelinst = mObjectRoot.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(objlist.mSkelBase && mSkelBase)
|
|
||||||
{
|
|
||||||
Ogre::SkeletonInstance *baseinst = mSkelBase->getSkeleton();
|
|
||||||
if(mSkelBase == objlist.mSkelBase)
|
|
||||||
{
|
|
||||||
if(objlist.mTextKeys.size() > 0)
|
|
||||||
{
|
|
||||||
mAccumRoot = mInsert;
|
|
||||||
mNonAccumRoot = baseinst->getBone(objlist.mTextKeys.begin()->first);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
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(mObjectRoot.mTextKeys.size() > 0)
|
||||||
if(!baseinst->hasBone(trgtname)) continue;
|
{
|
||||||
|
mAccumRoot = mInsert;
|
||||||
Ogre::Bone *bone = baseinst->getBone(trgtname);
|
mNonAccumRoot = skelinst->getBone(mObjectRoot.mTextKeys.begin()->first);
|
||||||
dstval->setNode(bone);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for(size_t i = 0;i < objlist.mControllers.size();i++)
|
for(size_t i = 0;i < mObjectRoot.mControllers.size();i++)
|
||||||
{
|
{
|
||||||
if(objlist.mControllers[i].getSource().isNull())
|
if(mObjectRoot.mControllers[i].getSource().isNull())
|
||||||
objlist.mControllers[i].setSource(mAnimationValuePtr[0]);
|
mObjectRoot.mControllers[i].setSource(mAnimationValuePtr[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
mActiveCtrls.insert(mActiveCtrls.end(), objlist.mControllers.begin(), objlist.mControllers.end());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Animation::setRenderProperties(const NifOgre::ObjectList &objlist, Ogre::uint32 visflags, Ogre::uint8 solidqueue, Ogre::uint8 transqueue)
|
void Animation::setRenderProperties(const NifOgre::ObjectList &objlist, Ogre::uint32 visflags, Ogre::uint8 solidqueue, Ogre::uint8 transqueue)
|
||||||
@ -186,113 +148,6 @@ void Animation::setRenderProperties(const NifOgre::ObjectList &objlist, Ogre::ui
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Animation::clearExtraSources()
|
|
||||||
{
|
|
||||||
for(size_t layer = 0;layer < sMaxLayers;layer++)
|
|
||||||
{
|
|
||||||
mLayer[layer].mGroupName.clear();
|
|
||||||
mLayer[layer].mTextKeys = NULL;
|
|
||||||
mLayer[layer].mControllers = NULL;
|
|
||||||
mLayer[layer].mTime = 0.0f;
|
|
||||||
mLayer[layer].mLoopCount = 0;
|
|
||||||
mLayer[layer].mPlaying = false;
|
|
||||||
}
|
|
||||||
mNonAccumCtrl = NULL;
|
|
||||||
mAnimVelocity = 0.0f;
|
|
||||||
|
|
||||||
mLastPosition = Ogre::Vector3(0.0f);
|
|
||||||
if(mAccumRoot)
|
|
||||||
mAccumRoot->setPosition(mLastPosition);
|
|
||||||
|
|
||||||
if(mObjects.size() > 1)
|
|
||||||
{
|
|
||||||
mObjects.resize(1);
|
|
||||||
mObjects[0].mActiveLayers = 0;
|
|
||||||
|
|
||||||
NifOgre::ObjectList &objlist = mObjects[0].mObjectList;
|
|
||||||
mActiveCtrls.clear();
|
|
||||||
mActiveCtrls.insert(mActiveCtrls.end(), objlist.mControllers.begin(), objlist.mControllers.end());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Animation::updateActiveControllers()
|
|
||||||
{
|
|
||||||
mActiveCtrls.clear();
|
|
||||||
|
|
||||||
/* First, get all controllers that don't target a node, or that target
|
|
||||||
* nodes that don't belong to any particular layer.
|
|
||||||
*/
|
|
||||||
std::vector<ObjectInfo>::iterator obj(mObjects.begin());
|
|
||||||
for(;obj != mObjects.end();obj++)
|
|
||||||
{
|
|
||||||
std::vector<Ogre::Controller<Ogre::Real> >::const_iterator ctrl(obj->mObjectList.mControllers.begin());
|
|
||||||
for(;ctrl != obj->mObjectList.mControllers.end();ctrl++)
|
|
||||||
{
|
|
||||||
NifOgre::NodeTargetValue<Ogre::Real> *dstval;
|
|
||||||
dstval = dynamic_cast<NifOgre::NodeTargetValue<Ogre::Real>*>(ctrl->getDestination().getPointer());
|
|
||||||
if(dstval)
|
|
||||||
{
|
|
||||||
/*if(getLayerByName(dstval->getNode()->getName()) >= 0)*/
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
mActiveCtrls.insert(mActiveCtrls.end(), *ctrl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<Ogre::Controller<Ogre::Real> > *ctrls = NULL;
|
|
||||||
size_t layer = 0;
|
|
||||||
while(layer < sMaxLayers)
|
|
||||||
{
|
|
||||||
/* Now get controllers that target nodes that belong to this layer from
|
|
||||||
* whatever objectlist is active on this layer.
|
|
||||||
*/
|
|
||||||
std::vector<ObjectInfo>::iterator obj(mObjects.begin());
|
|
||||||
for(;obj != mObjects.end();obj++)
|
|
||||||
{
|
|
||||||
if((obj->mActiveLayers&(1<<layer)))
|
|
||||||
{
|
|
||||||
ctrls = &obj->mObjectList.mControllers;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(ctrls == NULL)
|
|
||||||
{
|
|
||||||
layer++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check if any objectlists are active on subsequent layers. Include
|
|
||||||
* those layers if not.
|
|
||||||
*/
|
|
||||||
size_t nextlayer = layer+1;
|
|
||||||
for(;nextlayer < sMaxLayers;nextlayer++)
|
|
||||||
{
|
|
||||||
for(obj = mObjects.begin();obj != mObjects.end();obj++)
|
|
||||||
{
|
|
||||||
if((obj->mActiveLayers&(1<<nextlayer)))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<Ogre::Controller<Ogre::Real> >::const_iterator ctrl(ctrls->begin());
|
|
||||||
for(;ctrl != ctrls->end();ctrl++)
|
|
||||||
{
|
|
||||||
NifOgre::NodeTargetValue<Ogre::Real> *dstval;
|
|
||||||
dstval = dynamic_cast<NifOgre::NodeTargetValue<Ogre::Real>*>(ctrl->getDestination().getPointer());
|
|
||||||
if(dstval)
|
|
||||||
{
|
|
||||||
/*ssize_t idx = getLayerByName(dstval->getNode()->getName());
|
|
||||||
if(idx >= (ssize_t)layer && idx < (ssize_t)nextlayer)*/
|
|
||||||
mActiveCtrls.insert(mActiveCtrls.end(), *ctrl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
layer = nextlayer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Ogre::Node *Animation::getNode(const std::string &name)
|
Ogre::Node *Animation::getNode(const std::string &name)
|
||||||
{
|
{
|
||||||
if(mSkelBase)
|
if(mSkelBase)
|
||||||
@ -323,15 +178,13 @@ bool Animation::hasAnimation(const std::string &anim)
|
|||||||
if(!mSkelBase)
|
if(!mSkelBase)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for(std::vector<ObjectInfo>::const_iterator iter(mObjects.begin());iter != mObjects.end();iter++)
|
if(mObjectRoot.mTextKeys.size() > 0)
|
||||||
{
|
{
|
||||||
if(iter->mObjectList.mTextKeys.size() == 0)
|
const NifOgre::TextKeyMap &keys = mObjectRoot.mTextKeys.begin()->second;
|
||||||
continue;
|
|
||||||
|
|
||||||
const NifOgre::TextKeyMap &keys = iter->mObjectList.mTextKeys.begin()->second;
|
|
||||||
if(findGroupStart(keys, anim) != keys.end())
|
if(findGroupStart(keys, anim) != keys.end())
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -561,9 +414,6 @@ bool Animation::play(const std::string &groupname, const std::string &start, con
|
|||||||
if(!mSkelBase)
|
if(!mSkelBase)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for(std::vector<ObjectInfo>::iterator iter(mObjects.begin());iter != mObjects.end();iter++)
|
|
||||||
iter->mActiveLayers &= ~(1<<layeridx);
|
|
||||||
|
|
||||||
mLayer[layeridx].mGroupName.clear();
|
mLayer[layeridx].mGroupName.clear();
|
||||||
mLayer[layeridx].mTextKeys = NULL;
|
mLayer[layeridx].mTextKeys = NULL;
|
||||||
mLayer[layeridx].mControllers = NULL;
|
mLayer[layeridx].mControllers = NULL;
|
||||||
@ -578,9 +428,8 @@ bool Animation::play(const std::string &groupname, const std::string &start, con
|
|||||||
bool foundanim = false;
|
bool foundanim = false;
|
||||||
|
|
||||||
/* Look in reverse; last-inserted source has priority. */
|
/* Look in reverse; last-inserted source has priority. */
|
||||||
for(std::vector<ObjectInfo>::reverse_iterator iter(mObjects.rbegin());iter != mObjects.rend();iter++)
|
do {
|
||||||
{
|
NifOgre::ObjectList &objlist = mObjectRoot;
|
||||||
NifOgre::ObjectList &objlist = iter->mObjectList;
|
|
||||||
if(objlist.mTextKeys.size() == 0)
|
if(objlist.mTextKeys.size() == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -617,7 +466,6 @@ bool Animation::play(const std::string &groupname, const std::string &start, con
|
|||||||
mAnimVelocity = 0.0f;
|
mAnimVelocity = 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
iter->mActiveLayers |= (1<<layeridx);
|
|
||||||
foundanim = true;
|
foundanim = true;
|
||||||
|
|
||||||
if(mAccumulate == Ogre::Vector3(0.0f))
|
if(mAccumulate == Ogre::Vector3(0.0f))
|
||||||
@ -633,12 +481,10 @@ bool Animation::play(const std::string &groupname, const std::string &start, con
|
|||||||
movinganim = (nonaccumctrl==mNonAccumCtrl);
|
movinganim = (nonaccumctrl==mNonAccumCtrl);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
} while(0);
|
||||||
if(!foundanim)
|
if(!foundanim)
|
||||||
std::cerr<< "Failed to find animation "<<groupname <<std::endl;
|
std::cerr<< "Failed to find animation "<<groupname <<std::endl;
|
||||||
|
|
||||||
updateActiveControllers();
|
|
||||||
|
|
||||||
return movinganim;
|
return movinganim;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -647,17 +493,12 @@ void Animation::disable(size_t layeridx)
|
|||||||
if(mLayer[layeridx].mGroupName.empty())
|
if(mLayer[layeridx].mGroupName.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for(std::vector<ObjectInfo>::iterator iter(mObjects.begin());iter != mObjects.end();iter++)
|
|
||||||
iter->mActiveLayers &= ~(1<<layeridx);
|
|
||||||
|
|
||||||
mLayer[layeridx].mGroupName.clear();
|
mLayer[layeridx].mGroupName.clear();
|
||||||
mLayer[layeridx].mTextKeys = NULL;
|
mLayer[layeridx].mTextKeys = NULL;
|
||||||
mLayer[layeridx].mControllers = NULL;
|
mLayer[layeridx].mControllers = NULL;
|
||||||
mLayer[layeridx].mTime = 0.0f;
|
mLayer[layeridx].mTime = 0.0f;
|
||||||
mLayer[layeridx].mLoopCount = 0;
|
mLayer[layeridx].mLoopCount = 0;
|
||||||
mLayer[layeridx].mPlaying = false;
|
mLayer[layeridx].mPlaying = false;
|
||||||
|
|
||||||
updateActiveControllers();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Animation::getInfo(size_t layeridx, float *complete, std::string *groupname, std::string *start, std::string *stop) const
|
bool Animation::getInfo(size_t layeridx, float *complete, std::string *groupname, std::string *start, std::string *stop) const
|
||||||
@ -715,30 +556,21 @@ Ogre::Vector3 Animation::runAnimation(float duration)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(size_t i = 0;i < mActiveCtrls.size();i++)
|
for(size_t i = 0;i < mObjectRoot.mControllers.size();i++)
|
||||||
mActiveCtrls[i].update();
|
mObjectRoot.mControllers[i].update();
|
||||||
|
|
||||||
if(mSkelBase)
|
if(mSkelBase)
|
||||||
{
|
{
|
||||||
const Ogre::SkeletonInstance *baseinst = mSkelBase->getSkeleton();
|
// HACK: Dirty the animation state set so that Ogre will apply the
|
||||||
for(std::vector<ObjectInfo>::iterator iter(mObjects.begin());iter != mObjects.end();iter++)
|
// transformations to entities this skeleton instance is shared with.
|
||||||
{
|
mSkelBase->getAllAnimationStates()->_notifyDirty();
|
||||||
Ogre::Entity *ent = iter->mObjectList.mSkelBase;
|
|
||||||
if(!ent) continue;
|
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return movement;
|
return movement;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Animation::showWeapons(bool showWeapon){}
|
void Animation::showWeapons(bool showWeapon)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -30,15 +30,6 @@ protected:
|
|||||||
virtual void setValue(Ogre::Real value);
|
virtual void setValue(Ogre::Real value);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ObjectInfo {
|
|
||||||
NifOgre::ObjectList mObjectList;
|
|
||||||
/* Bit-field specifying which animation layers this object list is
|
|
||||||
* explicitly animating on (1 = layer 0, 2 = layer 1, 4 = layer 2.
|
|
||||||
* etc).
|
|
||||||
*/
|
|
||||||
int mActiveLayers;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct AnimLayer {
|
struct AnimLayer {
|
||||||
std::string mGroupName;
|
std::string mGroupName;
|
||||||
std::vector<Ogre::Controller<Ogre::Real> > *mControllers;
|
std::vector<Ogre::Controller<Ogre::Real> > *mControllers;
|
||||||
@ -60,21 +51,19 @@ protected:
|
|||||||
|
|
||||||
Ogre::SceneNode *mInsert;
|
Ogre::SceneNode *mInsert;
|
||||||
Ogre::Entity *mSkelBase;
|
Ogre::Entity *mSkelBase;
|
||||||
std::vector<ObjectInfo> mObjects;
|
NifOgre::ObjectList mObjectRoot;
|
||||||
Ogre::Node *mAccumRoot;
|
Ogre::Node *mAccumRoot;
|
||||||
Ogre::Bone *mNonAccumRoot;
|
Ogre::Bone *mNonAccumRoot;
|
||||||
NifOgre::NodeTargetValue<Ogre::Real> *mNonAccumCtrl;
|
NifOgre::NodeTargetValue<Ogre::Real> *mNonAccumCtrl;
|
||||||
Ogre::Vector3 mAccumulate;
|
Ogre::Vector3 mAccumulate;
|
||||||
Ogre::Vector3 mLastPosition;
|
Ogre::Vector3 mLastPosition;
|
||||||
|
|
||||||
std::vector<Ogre::Controller<Ogre::Real> > mActiveCtrls;
|
|
||||||
|
|
||||||
float mAnimVelocity;
|
float mAnimVelocity;
|
||||||
float mAnimSpeedMult;
|
float mAnimSpeedMult;
|
||||||
|
|
||||||
static const size_t sMaxLayers = 1;
|
static const size_t sMaxLayers = 1;
|
||||||
AnimLayer mLayer[sMaxLayers];
|
AnimLayer mLayer[sMaxLayers];
|
||||||
Ogre::SharedPtr<Ogre::ControllerValue<Ogre::Real> > mAnimationValuePtr[sMaxLayers];
|
Ogre::SharedPtr<AnimationValue> mAnimationValuePtr[sMaxLayers];
|
||||||
|
|
||||||
static float calcAnimVelocity(const NifOgre::TextKeyMap &keys,
|
static float calcAnimVelocity(const NifOgre::TextKeyMap &keys,
|
||||||
NifOgre::NodeTargetValue<Ogre::Real> *nonaccumctrl,
|
NifOgre::NodeTargetValue<Ogre::Real> *nonaccumctrl,
|
||||||
@ -105,22 +94,16 @@ protected:
|
|||||||
|
|
||||||
bool handleTextKey(size_t layeridx, const NifOgre::TextKeyMap::const_iterator &key);
|
bool handleTextKey(size_t layeridx, const NifOgre::TextKeyMap::const_iterator &key);
|
||||||
|
|
||||||
void addObjectList(Ogre::SceneNode *node, const std::string &model, bool baseonly);
|
void setObjectRoot(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);
|
||||||
|
|
||||||
static void setRenderProperties(const NifOgre::ObjectList &objlist, Ogre::uint32 visflags, Ogre::uint8 solidqueue, Ogre::uint8 transqueue);
|
static void setRenderProperties(const NifOgre::ObjectList &objlist, Ogre::uint32 visflags, Ogre::uint8 solidqueue, Ogre::uint8 transqueue);
|
||||||
|
|
||||||
void updateActiveControllers();
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Animation(const MWWorld::Ptr &ptr);
|
Animation(const MWWorld::Ptr &ptr);
|
||||||
virtual ~Animation();
|
virtual ~Animation();
|
||||||
|
|
||||||
/** Clears all ObjectLists except the first one. As a consequence, any
|
|
||||||
* playing animations are stopped.
|
|
||||||
*/
|
|
||||||
void clearExtraSources();
|
|
||||||
|
|
||||||
void updatePtr(const MWWorld::Ptr &ptr);
|
void updatePtr(const MWWorld::Ptr &ptr);
|
||||||
|
|
||||||
bool hasAnimation(const std::string &anim);
|
bool hasAnimation(const std::string &anim);
|
||||||
|
@ -21,11 +21,8 @@ CreatureAnimation::CreatureAnimation(const MWWorld::Ptr &ptr)
|
|||||||
{
|
{
|
||||||
std::string model = "meshes\\"+ref->mBase->mModel;
|
std::string model = "meshes\\"+ref->mBase->mModel;
|
||||||
|
|
||||||
if((ref->mBase->mFlags&ESM::Creature::Biped))
|
setObjectRoot(mPtr.getRefData().getBaseNode(), model, false);
|
||||||
addObjectList(mPtr.getRefData().getBaseNode(), "meshes\\base_anim.nif", true);
|
setRenderProperties(mObjectRoot, RV_Actors, RQG_Main, RQG_Alpha);
|
||||||
|
|
||||||
addObjectList(mPtr.getRefData().getBaseNode(), model, false);
|
|
||||||
setRenderProperties(mObjects.back().mObjectList, RV_Actors, RQG_Main, RQG_Alpha);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,26 +99,27 @@ 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");
|
||||||
|
setObjectRoot(node, smodel, true);
|
||||||
addObjectList(node, smodel, true);
|
#if 0
|
||||||
|
addAnimSource(node, smodel);
|
||||||
if(mBodyPrefix.find("argonian") != std::string::npos)
|
if(mBodyPrefix.find("argonian") != std::string::npos)
|
||||||
addObjectList(node, "meshes\\argonian_swimkna.nif", true);
|
addAnimSource(node, "meshes\\argonian_swimkna.nif");
|
||||||
else if(!mNpc->isMale() && !isBeast)
|
else if(!mNpc->isMale() && !isBeast)
|
||||||
addObjectList(node, "meshes\\base_anim_female.nif", true);
|
addAnimSource(node, "meshes\\base_anim_female.nif");
|
||||||
if(mNpc->mModel.length() > 0)
|
if(mNpc->mModel.length() > 0)
|
||||||
addObjectList(node, "meshes\\"+mNpc->mModel, true);
|
addAnimSource(node, "meshes\\"+mNpc->mModel);
|
||||||
if(mViewMode == VM_FirstPerson)
|
if(mViewMode == VM_FirstPerson)
|
||||||
{
|
{
|
||||||
/* A bit counter-intuitive, but unlike third-person anims, it seems
|
/* A bit counter-intuitive, but unlike third-person anims, it seems
|
||||||
* beast races get both base_anim.1st.nif and base_animkna.1st.nif.
|
* beast races get both base_anim.1st.nif and base_animkna.1st.nif.
|
||||||
*/
|
*/
|
||||||
addObjectList(node, "meshes\\base_anim.1st.nif", true);
|
addAnimSource(node, "meshes\\base_anim.1st.nif");
|
||||||
if(isBeast)
|
if(isBeast)
|
||||||
addObjectList(node, "meshes\\base_animkna.1st.nif", true);
|
addAnimSource(node, "meshes\\base_animkna.1st.nif");
|
||||||
if(!mNpc->isMale() && !isBeast)
|
if(!mNpc->isMale() && !isBeast)
|
||||||
addObjectList(node, "meshes\\base_anim_female.1st.nif", true);
|
addAnimSource(node, "meshes\\base_anim_female.1st.nif");
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
forceUpdate();
|
forceUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,27 +133,29 @@ void NpcAnimation::setViewMode(NpcAnimation::ViewMode viewMode)
|
|||||||
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
|
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
|
||||||
const ESM::Race *race = store.get<ESM::Race>().find(mNpc->mRace);
|
const ESM::Race *race = store.get<ESM::Race>().find(mNpc->mRace);
|
||||||
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");
|
||||||
clearExtraSources();
|
#if 0
|
||||||
|
clearAnimSources();
|
||||||
|
addAnimSource(node, smodel);
|
||||||
if(mBodyPrefix.find("argonian") != std::string::npos)
|
if(mBodyPrefix.find("argonian") != std::string::npos)
|
||||||
addObjectList(node, "meshes\\argonian_swimkna.nif", true);
|
addAnimSource(node, "meshes\\argonian_swimkna.nif");
|
||||||
else if(!mNpc->isMale() && !isBeast)
|
else if(!mNpc->isMale() && !isBeast)
|
||||||
addObjectList(node, "meshes\\base_anim_female.nif", true);
|
addAnimSource(node, "meshes\\base_anim_female.nif");
|
||||||
if(mNpc->mModel.length() > 0)
|
if(mNpc->mModel.length() > 0)
|
||||||
addObjectList(node, "meshes\\"+mNpc->mModel, true);
|
addAnimSource(node, "meshes\\"+mNpc->mModel);
|
||||||
if(mViewMode == VM_FirstPerson)
|
if(mViewMode == VM_FirstPerson)
|
||||||
{
|
{
|
||||||
/* A bit counter-intuitive, but unlike third-person anims, it seems
|
/* A bit counter-intuitive, but unlike third-person anims, it seems
|
||||||
* beast races get both base_anim.1st.nif and base_animkna.1st.nif.
|
* beast races get both base_anim.1st.nif and base_animkna.1st.nif.
|
||||||
*/
|
*/
|
||||||
addObjectList(node, "meshes\\base_anim.1st.nif", true);
|
addAnimSource(node, "meshes\\base_anim.1st.nif");
|
||||||
if(isBeast)
|
if(isBeast)
|
||||||
addObjectList(node, "meshes\\base_animkna.1st.nif", true);
|
addAnimSource(node, "meshes\\base_animkna.1st.nif");
|
||||||
if(!mNpc->isMale() && !isBeast)
|
if(!mNpc->isMale() && !isBeast)
|
||||||
addObjectList(node, "meshes\\base_anim_female.1st.nif", true);
|
addAnimSource(node, "meshes\\base_anim_female.1st.nif");
|
||||||
}
|
}
|
||||||
MWBase::Environment::get().getMechanicsManager()->forceStateUpdate(mPtr);
|
MWBase::Environment::get().getMechanicsManager()->forceStateUpdate(mPtr);
|
||||||
|
#endif
|
||||||
for(size_t i = 0;i < sPartListSize;i++)
|
for(size_t i = 0;i < sPartListSize;i++)
|
||||||
removeIndividualPart(i);
|
removeIndividualPart(i);
|
||||||
forceUpdate();
|
forceUpdate();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user