Use a separate list of controllers to update

This should make it easier to figure out what controllers need to be updated
for various animation sources and layers.
actorid
Chris Robinson 12 years ago
parent e4c5aac966
commit c4806f01f8

@ -71,6 +71,9 @@ Animation::Animation(const MWWorld::Ptr &ptr)
, mAnimVelocity(0.0f)
, mAnimSpeedMult(1.0f)
{
/* As long as we remain under 128 active controllers, we can avoid
* reallocations. */
mActiveCtrls.reserve(128);
}
Animation::~Animation()
@ -179,6 +182,79 @@ void Animation::setRenderProperties(const NifOgre::ObjectList &objlist, Ogre::ui
}
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;
}
}
/* 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<<layer)))
break;
}
}
assert(ctrls != NULL);
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)
{
if(mSkelBase)
@ -433,86 +509,76 @@ void Animation::play(const std::string &groupname, const std::string &start, con
// TODO: parameterize this
size_t layeridx = 0;
try {
for(std::vector<ObjectInfo>::iterator iter(mObjects.begin());iter != mObjects.end();iter++)
iter->mActiveLayers &= ~(1<<layeridx);
for(std::vector<ObjectInfo>::iterator iter(mObjects.begin());iter != mObjects.end();iter++)
iter->mActiveLayers &= ~(1<<layeridx);
if(groupname.empty())
{
// Do not allow layer 0 to be disabled
assert(layeridx != 0);
bool foundanim = false;
if(groupname.empty())
{
// Do not allow layer 0 to be disabled
assert(layeridx != 0);
mLayer[layeridx].mGroupName.clear();
mLayer[layeridx].mTextKeys = NULL;
mLayer[layeridx].mControllers = NULL;
mLayer[layeridx].mLooping = false;
mLayer[layeridx].mPlaying = false;
mLayer[layeridx].mGroupName.clear();
mLayer[layeridx].mTextKeys = NULL;
mLayer[layeridx].mControllers = NULL;
mLayer[layeridx].mLooping = false;
mLayer[layeridx].mPlaying = false;
if(layeridx == 0)
foundanim = true;
}
/* Look in reverse; last-inserted source has priority. */
else for(std::vector<ObjectInfo>::reverse_iterator iter(mObjects.rbegin());iter != mObjects.rend();iter++)
{
NifOgre::ObjectList &objlist = iter->mObjectList;
if(objlist.mTextKeys.size() == 0)
continue;
const NifOgre::TextKeyMap &keys = objlist.mTextKeys.begin()->second;
NifOgre::NodeTargetValue<Ogre::Real> *nonaccumctrl = NULL;
if(layeridx == 0)
{
for(size_t i = 0;i < objlist.mControllers.size();i++)
{
mNonAccumCtrl = NULL;
mAnimVelocity = 0.0f;
NifOgre::NodeTargetValue<Ogre::Real> *dstval;
dstval = dynamic_cast<NifOgre::NodeTargetValue<Ogre::Real>*>(objlist.mControllers[i].getDestination().getPointer());
if(dstval && dstval->getNode() == mNonAccumRoot)
{
nonaccumctrl = dstval;
break;
}
}
return;
}
bool foundanim = false;
/* Look in reverse; last-inserted source has priority. */
for(std::vector<ObjectInfo>::reverse_iterator iter(mObjects.rbegin());iter != mObjects.rend();iter++)
if(!foundanim)
{
NifOgre::ObjectList &objlist = iter->mObjectList;
if(objlist.mTextKeys.size() == 0)
if(!reset(layeridx, keys, nonaccumctrl, groupname, start, stop))
continue;
mLayer[layeridx].mGroupName = groupname;
mLayer[layeridx].mTextKeys = &keys;
mLayer[layeridx].mControllers = &objlist.mControllers;
mLayer[layeridx].mLooping = loop;
mLayer[layeridx].mPlaying = true;
const NifOgre::TextKeyMap &keys = objlist.mTextKeys.begin()->second;
NifOgre::NodeTargetValue<Ogre::Real> *nonaccumctrl = NULL;
if(layeridx == 0)
{
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 && dstval->getNode() == mNonAccumRoot)
{
nonaccumctrl = dstval;
break;
}
}
mNonAccumCtrl = nonaccumctrl;
mAnimVelocity = 0.0f;
}
if(!foundanim)
{
if(!reset(layeridx, keys, nonaccumctrl, groupname, start, stop))
continue;
mLayer[layeridx].mGroupName = groupname;
mLayer[layeridx].mTextKeys = &keys;
mLayer[layeridx].mControllers = &objlist.mControllers;
mLayer[layeridx].mLooping = loop;
mLayer[layeridx].mPlaying = true;
if(layeridx == 0)
{
mNonAccumCtrl = nonaccumctrl;
mAnimVelocity = 0.0f;
}
iter->mActiveLayers |= (1<<layeridx);
foundanim = true;
}
iter->mActiveLayers |= (1<<layeridx);
foundanim = true;
}
if(!nonaccumctrl)
break;
if(!nonaccumctrl)
break;
mAnimVelocity = calcAnimVelocity(keys, nonaccumctrl, groupname);
if(mAnimVelocity > 0.0f) break;
}
if(!foundanim)
throw std::runtime_error("Failed to find animation "+groupname);
}
catch(std::exception &e) {
std::cerr<< e.what() <<std::endl;
mAnimVelocity = calcAnimVelocity(keys, nonaccumctrl, groupname);
if(mAnimVelocity > 0.0f) break;
}
if(!foundanim)
std::cerr<< "Failed to find animation "<<groupname <<std::endl;
updateActiveControllers();
}
Ogre::Vector3 Animation::runAnimation(float duration)
@ -548,25 +614,11 @@ Ogre::Vector3 Animation::runAnimation(float duration)
if(!handleTextKey(layeridx, key))
break;
}
bool updatectrls = true;
for(size_t i = layeridx-1;i < layeridx;i--)
{
if(mLayer[i].mGroupName.empty())
continue;
if(mLayer[i].mControllers == mLayer[layeridx].mControllers)
{
updatectrls = false;
break;
}
}
if(updatectrls)
{
for(size_t i = 0;i < (*(mLayer[layeridx].mControllers)).size();i++)
(*(mLayer[layeridx].mControllers))[i].update();
}
}
for(size_t i = 0;i < mActiveCtrls.size();i++)
mActiveCtrls[i].update();
if(mSkelBase)
{
const Ogre::SkeletonInstance *baseinst = mSkelBase->getSkeleton();

@ -58,6 +58,7 @@ protected:
NifOgre::NodeTargetValue<Ogre::Real> *mNonAccumCtrl;
float mAnimVelocity;
float mAnimSpeedMult;
std::vector<Ogre::Controller<Ogre::Real> > mActiveCtrls;
static const size_t sMaxLayers = 1;
struct AnimLayer {
@ -107,6 +108,8 @@ protected:
static void setRenderProperties(const NifOgre::ObjectList &objlist, Ogre::uint32 visflags, Ogre::uint8 solidqueue, Ogre::uint8 transqueue);
void updateActiveControllers();
public:
Animation(const MWWorld::Ptr &ptr);
virtual ~Animation();

Loading…
Cancel
Save