mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-19 22:53:50 +00:00
Use a map of active layers instead of an array
A bit of an upheaval. Each animation is now a "layer", instead of each layer having an animation. Incidentally, this is much closer to how Ogre handles animation states. In the future, each layer will have a priority, which will be used to determine which one affects a given bone group (which we currently only have one of).
This commit is contained in:
parent
d5490b0f8f
commit
ccff364b52
3 changed files with 113 additions and 153 deletions
|
@ -339,7 +339,7 @@ void CharacterController::update(float duration, Movement &movement)
|
||||||
else if(rot.z < 0.0f)
|
else if(rot.z < 0.0f)
|
||||||
setState(CharState_TurnLeft, true);
|
setState(CharState_TurnLeft, true);
|
||||||
}
|
}
|
||||||
else if(getState() != CharState_SpecialIdle || !mAnimation->isPlaying(0))
|
else if(getState() != CharState_SpecialIdle)
|
||||||
{
|
{
|
||||||
if(mAnimQueue.size() == 0)
|
if(mAnimQueue.size() == 0)
|
||||||
setState((inwater ? CharState_IdleSwim : (sneak ? CharState_IdleSneak : CharState_Idle)), true);
|
setState((inwater ? CharState_IdleSwim : (sneak ? CharState_IdleSneak : CharState_Idle)), true);
|
||||||
|
|
|
@ -18,28 +18,19 @@
|
||||||
namespace MWRender
|
namespace MWRender
|
||||||
{
|
{
|
||||||
|
|
||||||
Animation::AnimLayer::AnimLayer()
|
|
||||||
: mSource(NULL)
|
|
||||||
, mTime(0.0f)
|
|
||||||
, mPlaying(false)
|
|
||||||
, mLoopCount(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Ogre::Real Animation::AnimationValue::getValue() const
|
Ogre::Real Animation::AnimationValue::getValue() const
|
||||||
{
|
{
|
||||||
size_t idx = mIndex;
|
AnimLayerMap::const_iterator iter = mAnimation->mLayers.find(mAnimation->mAnimationName);
|
||||||
while(idx > 0 && mAnimation->mLayer[idx].mGroupName.empty())
|
if(iter != mAnimation->mLayers.end())
|
||||||
idx--;
|
return iter->second.mTime;
|
||||||
if(!mAnimation->mLayer[idx].mGroupName.empty())
|
|
||||||
return mAnimation->mLayer[idx].mTime;
|
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Animation::AnimationValue::setValue(Ogre::Real value)
|
void Animation::AnimationValue::setValue(Ogre::Real value)
|
||||||
{
|
{
|
||||||
mAnimation->mLayer[mIndex].mTime = value;
|
AnimLayerMap::iterator iter = mAnimation->mLayers.find(mAnimation->mAnimationName);
|
||||||
|
if(iter != mAnimation->mLayers.end())
|
||||||
|
iter->second.mTime = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -67,8 +58,8 @@ Animation::Animation(const MWWorld::Ptr &ptr)
|
||||||
, mAnimVelocity(0.0f)
|
, mAnimVelocity(0.0f)
|
||||||
, mAnimSpeedMult(1.0f)
|
, mAnimSpeedMult(1.0f)
|
||||||
{
|
{
|
||||||
for(size_t i = 0;i < sMaxLayers;i++)
|
mSource = NULL;
|
||||||
mAnimationValuePtr[i].bind(OGRE_NEW AnimationValue(this, i));
|
mAnimationValuePtr.bind(OGRE_NEW AnimationValue(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
Animation::~Animation()
|
Animation::~Animation()
|
||||||
|
@ -127,7 +118,7 @@ void Animation::setObjectRoot(Ogre::SceneNode *node, const std::string &model, b
|
||||||
for(size_t i = 0;i < mObjectRoot.mControllers.size();i++)
|
for(size_t i = 0;i < mObjectRoot.mControllers.size();i++)
|
||||||
{
|
{
|
||||||
if(mObjectRoot.mControllers[i].getSource().isNull())
|
if(mObjectRoot.mControllers[i].getSource().isNull())
|
||||||
mObjectRoot.mControllers[i].setSource(mAnimationValuePtr[0]);
|
mObjectRoot.mControllers[i].setSource(mAnimationValuePtr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,20 +191,17 @@ void Animation::addAnimSource(const std::string &model)
|
||||||
mNonAccumRoot = dstval->getNode();
|
mNonAccumRoot = dstval->getNode();
|
||||||
}
|
}
|
||||||
|
|
||||||
ctrls[i].setSource(mAnimationValuePtr[0]);
|
ctrls[i].setSource(mAnimationValuePtr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Animation::clearAnimSources()
|
void Animation::clearAnimSources()
|
||||||
{
|
{
|
||||||
for(size_t layer = 0;layer < sMaxLayers;layer++)
|
mLayers.clear();
|
||||||
{
|
|
||||||
mLayer[layer].mGroupName.clear();
|
mSource = NULL;
|
||||||
mLayer[layer].mSource = NULL;
|
mAnimationName.empty();
|
||||||
mLayer[layer].mTime = 0.0f;
|
|
||||||
mLayer[layer].mLoopCount = 0;
|
|
||||||
mLayer[layer].mPlaying = false;
|
|
||||||
}
|
|
||||||
mNonAccumCtrl = NULL;
|
mNonAccumCtrl = NULL;
|
||||||
mAnimVelocity = 0.0f;
|
mAnimVelocity = 0.0f;
|
||||||
|
|
||||||
|
@ -353,14 +341,14 @@ void Animation::updateSkeletonInstance(const Ogre::SkeletonInstance *skelsrc, Og
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Animation::updatePosition(Ogre::Vector3 &position)
|
void Animation::updatePosition(float time, Ogre::Vector3 &position)
|
||||||
{
|
{
|
||||||
Ogre::Vector3 posdiff;
|
Ogre::Vector3 posdiff;
|
||||||
|
|
||||||
/* Get the non-accumulation root's difference from the last update, and move the position
|
/* Get the non-accumulation root's difference from the last update, and move the position
|
||||||
* accordingly.
|
* accordingly.
|
||||||
*/
|
*/
|
||||||
posdiff = (mNonAccumCtrl->getTranslation(mLayer[0].mTime) - mLastPosition) * mAccumulate;
|
posdiff = (mNonAccumCtrl->getTranslation(time) - mLastPosition) * mAccumulate;
|
||||||
position += posdiff;
|
position += posdiff;
|
||||||
|
|
||||||
/* Translate the accumulation root back to compensate for the move. */
|
/* Translate the accumulation root back to compensate for the move. */
|
||||||
|
@ -368,7 +356,7 @@ void Animation::updatePosition(Ogre::Vector3 &position)
|
||||||
mAccumRoot->setPosition(-mLastPosition);
|
mAccumRoot->setPosition(-mLastPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Animation::reset(size_t layeridx, const NifOgre::TextKeyMap &keys, NifOgre::NodeTargetValue<Ogre::Real> *nonaccumctrl, const std::string &groupname, const std::string &start, const std::string &stop, float startpoint)
|
bool Animation::reset(AnimLayer &layer, const NifOgre::TextKeyMap &keys, NifOgre::NodeTargetValue<Ogre::Real> *nonaccumctrl, const std::string &groupname, const std::string &start, const std::string &stop, float startpoint)
|
||||||
{
|
{
|
||||||
std::string tag = groupname+": "+start;
|
std::string tag = groupname+": "+start;
|
||||||
NifOgre::TextKeyMap::const_iterator startkey(keys.begin());
|
NifOgre::TextKeyMap::const_iterator startkey(keys.begin());
|
||||||
|
@ -394,46 +382,45 @@ bool Animation::reset(size_t layeridx, const NifOgre::TextKeyMap &keys, NifOgre:
|
||||||
if(startkey == stopkey)
|
if(startkey == stopkey)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
mLayer[layeridx].mStartKey = startkey;
|
layer.mStartKey = startkey;
|
||||||
mLayer[layeridx].mLoopStartKey = startkey;
|
layer.mLoopStartKey = startkey;
|
||||||
mLayer[layeridx].mStopKey = stopkey;
|
layer.mStopKey = stopkey;
|
||||||
mLayer[layeridx].mNextKey = startkey;
|
layer.mNextKey = startkey;
|
||||||
|
|
||||||
mLayer[layeridx].mTime = mLayer[layeridx].mStartKey->first + ((mLayer[layeridx].mStopKey->first-
|
layer.mTime = layer.mStartKey->first + ((layer.mStopKey->first - layer.mStartKey->first) * startpoint);
|
||||||
mLayer[layeridx].mStartKey->first) * startpoint);
|
|
||||||
|
|
||||||
tag = groupname+": loop start";
|
tag = groupname+": loop start";
|
||||||
while(mLayer[layeridx].mNextKey->first <= mLayer[layeridx].mTime && mLayer[layeridx].mNextKey != mLayer[layeridx].mStopKey)
|
while(layer.mNextKey->first <= layer.mTime && layer.mNextKey != layer.mStopKey)
|
||||||
{
|
{
|
||||||
if(mLayer[layeridx].mNextKey->second == tag)
|
if(layer.mNextKey->second == tag)
|
||||||
mLayer[layeridx].mLoopStartKey = mLayer[layeridx].mNextKey;
|
layer.mLoopStartKey = layer.mNextKey;
|
||||||
mLayer[layeridx].mNextKey++;
|
layer.mNextKey++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(layeridx == 0 && nonaccumctrl)
|
if(nonaccumctrl)
|
||||||
mLastPosition = nonaccumctrl->getTranslation(mLayer[layeridx].mTime) * mAccumulate;
|
mLastPosition = nonaccumctrl->getTranslation(layer.mTime) * mAccumulate;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Animation::doLoop(size_t layeridx)
|
bool Animation::doLoop(AnimLayer &layer)
|
||||||
{
|
{
|
||||||
if(mLayer[layeridx].mLoopCount == 0)
|
if(layer.mLoopCount == 0)
|
||||||
return false;
|
return false;
|
||||||
mLayer[layeridx].mLoopCount--;
|
layer.mLoopCount--;
|
||||||
|
|
||||||
mLayer[layeridx].mTime = mLayer[layeridx].mLoopStartKey->first;
|
layer.mTime = layer.mLoopStartKey->first;
|
||||||
mLayer[layeridx].mNextKey = mLayer[layeridx].mLoopStartKey;
|
layer.mNextKey = layer.mLoopStartKey;
|
||||||
mLayer[layeridx].mNextKey++;
|
layer.mNextKey++;
|
||||||
mLayer[layeridx].mPlaying = true;
|
layer.mPlaying = true;
|
||||||
if(layeridx == 0 && mNonAccumCtrl)
|
if(mNonAccumCtrl)
|
||||||
mLastPosition = mNonAccumCtrl->getTranslation(mLayer[layeridx].mTime) * mAccumulate;
|
mLastPosition = mNonAccumCtrl->getTranslation(layer.mTime) * mAccumulate;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Animation::handleTextKey(size_t layeridx, const NifOgre::TextKeyMap::const_iterator &key)
|
bool Animation::handleTextKey(AnimLayer &layer, const std::string &groupname, const NifOgre::TextKeyMap::const_iterator &key)
|
||||||
{
|
{
|
||||||
float time = key->first;
|
float time = key->first;
|
||||||
const std::string &evt = key->second;
|
const std::string &evt = key->second;
|
||||||
|
@ -451,26 +438,26 @@ bool Animation::handleTextKey(size_t layeridx, const NifOgre::TextKeyMap::const_
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(evt.compare(0, mLayer[layeridx].mGroupName.size(), mLayer[layeridx].mGroupName) != 0 ||
|
if(evt.compare(0, groupname.size(), groupname) != 0 ||
|
||||||
evt.compare(mLayer[layeridx].mGroupName.size(), 2, ": ") != 0)
|
evt.compare(groupname.size(), 2, ": ") != 0)
|
||||||
{
|
{
|
||||||
// Not ours, skip it
|
// Not ours, skip it
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
size_t off = mLayer[layeridx].mGroupName.size()+2;
|
size_t off = groupname.size()+2;
|
||||||
size_t len = evt.size() - off;
|
size_t len = evt.size() - off;
|
||||||
|
|
||||||
if(evt.compare(off, len, "start") == 0 || evt.compare(off, len, "loop start") == 0)
|
if(evt.compare(off, len, "start") == 0 || evt.compare(off, len, "loop start") == 0)
|
||||||
{
|
{
|
||||||
mLayer[layeridx].mLoopStartKey = key;
|
layer.mLoopStartKey = key;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(evt.compare(off, len, "loop stop") == 0 || evt.compare(off, len, "stop") == 0)
|
if(evt.compare(off, len, "loop stop") == 0 || evt.compare(off, len, "stop") == 0)
|
||||||
{
|
{
|
||||||
if(doLoop(layeridx))
|
if(doLoop(layer))
|
||||||
{
|
{
|
||||||
if(mLayer[layeridx].mTime >= time)
|
if(layer.mTime >= time)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -483,20 +470,14 @@ bool Animation::handleTextKey(size_t layeridx, const NifOgre::TextKeyMap::const_
|
||||||
|
|
||||||
bool Animation::play(const std::string &groupname, const std::string &start, const std::string &stop, float startpoint, size_t loops)
|
bool Animation::play(const std::string &groupname, const std::string &start, const std::string &stop, float startpoint, size_t loops)
|
||||||
{
|
{
|
||||||
// TODO: parameterize this
|
if(!mSkelBase || groupname.empty())
|
||||||
size_t layeridx = 0;
|
|
||||||
|
|
||||||
if(!mSkelBase)
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
mLayer[layeridx].mGroupName.clear();
|
AnimLayerMap::iterator layeriter = mLayers.find(groupname);
|
||||||
mLayer[layeridx].mSource = NULL;
|
if(layeriter != mLayers.end())
|
||||||
mLayer[layeridx].mTime = 0.0f;
|
mLayers.erase(layeriter);
|
||||||
mLayer[layeridx].mLoopCount = 0;
|
// HACK: Don't clear all active animations
|
||||||
mLayer[layeridx].mPlaying = false;
|
mLayers.clear();
|
||||||
|
|
||||||
if(groupname.empty())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
bool movinganim = false;
|
bool movinganim = false;
|
||||||
bool foundanim = false;
|
bool foundanim = false;
|
||||||
|
@ -507,7 +488,7 @@ bool Animation::play(const std::string &groupname, const std::string &start, con
|
||||||
{
|
{
|
||||||
const NifOgre::TextKeyMap &keys = iter->mTextKeys;
|
const NifOgre::TextKeyMap &keys = iter->mTextKeys;
|
||||||
NifOgre::NodeTargetValue<Ogre::Real> *nonaccumctrl = NULL;
|
NifOgre::NodeTargetValue<Ogre::Real> *nonaccumctrl = NULL;
|
||||||
if(layeridx == 0 && mNonAccumRoot)
|
if(mNonAccumRoot)
|
||||||
{
|
{
|
||||||
for(size_t i = 0;i < iter->mControllers.size();i++)
|
for(size_t i = 0;i < iter->mControllers.size();i++)
|
||||||
{
|
{
|
||||||
|
@ -523,22 +504,22 @@ bool Animation::play(const std::string &groupname, const std::string &start, con
|
||||||
|
|
||||||
if(!foundanim)
|
if(!foundanim)
|
||||||
{
|
{
|
||||||
if(!reset(layeridx, keys, nonaccumctrl, groupname, start, stop, startpoint))
|
AnimLayer layer;
|
||||||
|
if(!reset(layer, keys, nonaccumctrl, groupname, start, stop, startpoint))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
mLayer[layeridx].mGroupName = groupname;
|
|
||||||
mLayer[layeridx].mSource = &*iter;
|
|
||||||
mLayer[layeridx].mLoopCount = loops;
|
|
||||||
mLayer[layeridx].mPlaying = true;
|
|
||||||
|
|
||||||
if(layeridx == 0)
|
|
||||||
{
|
|
||||||
mNonAccumCtrl = nonaccumctrl;
|
|
||||||
mAnimVelocity = 0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
foundanim = true;
|
foundanim = true;
|
||||||
|
|
||||||
|
layer.mLoopCount = loops;
|
||||||
|
layer.mPlaying = true;
|
||||||
|
mLayers[groupname] = layer;
|
||||||
|
|
||||||
|
// FIXME
|
||||||
|
mSource = &*iter;
|
||||||
|
mAnimationName = groupname;
|
||||||
|
|
||||||
|
mNonAccumCtrl = nonaccumctrl;
|
||||||
|
mAnimVelocity = 0.0f;
|
||||||
|
|
||||||
if(mAccumulate == Ogre::Vector3(0.0f))
|
if(mAccumulate == Ogre::Vector3(0.0f))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -559,34 +540,21 @@ bool Animation::play(const std::string &groupname, const std::string &start, con
|
||||||
return movinganim;
|
return movinganim;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Animation::disable(size_t layeridx)
|
bool Animation::getInfo(const std::string &groupname, float *complete, std::string *start, std::string *stop) const
|
||||||
{
|
{
|
||||||
if(mLayer[layeridx].mGroupName.empty())
|
AnimLayerMap::const_iterator iter = mLayers.find(groupname);
|
||||||
return;
|
if(iter == mLayers.end())
|
||||||
|
|
||||||
mLayer[layeridx].mGroupName.clear();
|
|
||||||
mLayer[layeridx].mSource = NULL;
|
|
||||||
mLayer[layeridx].mTime = 0.0f;
|
|
||||||
mLayer[layeridx].mLoopCount = 0;
|
|
||||||
mLayer[layeridx].mPlaying = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Animation::getInfo(size_t layeridx, float *complete, std::string *groupname, std::string *start, std::string *stop) const
|
|
||||||
{
|
|
||||||
if(mLayer[layeridx].mGroupName.empty())
|
|
||||||
{
|
{
|
||||||
if(complete) *complete = 0.0f;
|
if(complete) *complete = 0.0f;
|
||||||
if(groupname) *groupname = "";
|
|
||||||
if(start) *start = "";
|
if(start) *start = "";
|
||||||
if(stop) *stop = "";
|
if(stop) *stop = "";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(complete) *complete = (mLayer[layeridx].mTime - mLayer[layeridx].mStartKey->first) /
|
if(complete) *complete = (iter->second.mTime - iter->second.mStartKey->first) /
|
||||||
(mLayer[layeridx].mStopKey->first - mLayer[layeridx].mStartKey->first);
|
(iter->second.mStopKey->first - iter->second.mStartKey->first);
|
||||||
if(groupname) *groupname = mLayer[layeridx].mGroupName;
|
if(start) *start = iter->second.mStartKey->second.substr(groupname.size()+2);
|
||||||
if(start) *start = mLayer[layeridx].mStartKey->second.substr(mLayer[layeridx].mGroupName.size()+2);
|
if(stop) *stop = iter->second.mStopKey->second.substr(groupname.size()+2);
|
||||||
if(stop) *stop = mLayer[layeridx].mStopKey->second.substr(mLayer[layeridx].mGroupName.size()+2);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -596,45 +564,41 @@ Ogre::Vector3 Animation::runAnimation(float duration)
|
||||||
Ogre::Vector3 movement(0.0f);
|
Ogre::Vector3 movement(0.0f);
|
||||||
|
|
||||||
duration *= mAnimSpeedMult;
|
duration *= mAnimSpeedMult;
|
||||||
for(size_t layeridx = 0;layeridx < sMaxLayers;layeridx++)
|
AnimLayerMap::iterator layeriter = mLayers.begin();
|
||||||
|
for(;layeriter != mLayers.end();layeriter++)
|
||||||
{
|
{
|
||||||
if(mLayer[layeridx].mGroupName.empty())
|
AnimLayer &layer = layeriter->second;
|
||||||
continue;
|
|
||||||
|
|
||||||
float timepassed = duration;
|
float timepassed = duration;
|
||||||
while(mLayer[layeridx].mPlaying)
|
while(layer.mPlaying)
|
||||||
{
|
{
|
||||||
float targetTime = mLayer[layeridx].mTime + timepassed;
|
float targetTime = layer.mTime + timepassed;
|
||||||
if(mLayer[layeridx].mNextKey->first > targetTime)
|
if(layer.mNextKey->first > targetTime)
|
||||||
{
|
{
|
||||||
mLayer[layeridx].mTime = targetTime;
|
layer.mTime = targetTime;
|
||||||
if(layeridx == 0 && mNonAccumCtrl)
|
if(mNonAccumCtrl)
|
||||||
updatePosition(movement);
|
updatePosition(layer.mTime, movement);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
NifOgre::TextKeyMap::const_iterator key(mLayer[layeridx].mNextKey++);
|
NifOgre::TextKeyMap::const_iterator key(layer.mNextKey++);
|
||||||
mLayer[layeridx].mTime = key->first;
|
layer.mTime = key->first;
|
||||||
if(layeridx == 0 && mNonAccumCtrl)
|
if(mNonAccumCtrl)
|
||||||
updatePosition(movement);
|
updatePosition(layer.mTime, movement);
|
||||||
|
|
||||||
mLayer[layeridx].mPlaying = (key != mLayer[layeridx].mStopKey);
|
layer.mPlaying = (key != layer.mStopKey);
|
||||||
timepassed = targetTime - mLayer[layeridx].mTime;
|
timepassed = targetTime - layer.mTime;
|
||||||
|
|
||||||
if(!handleTextKey(layeridx, key))
|
if(!handleTextKey(layer, layeriter->first, key))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(size_t i = 0;i < mObjectRoot.mControllers.size();i++)
|
for(size_t i = 0;i < mObjectRoot.mControllers.size();i++)
|
||||||
mObjectRoot.mControllers[i].update();
|
mObjectRoot.mControllers[i].update();
|
||||||
for(size_t layeridx = 0;layeridx < sMaxLayers;layeridx++)
|
if(mSource)
|
||||||
{
|
{
|
||||||
if(mLayer[layeridx].mGroupName.empty())
|
for(size_t i = 0;i < mSource->mControllers.size();i++)
|
||||||
continue;
|
mSource->mControllers[i].update();
|
||||||
|
|
||||||
for(size_t i = 0;i < mLayer[layeridx].mSource->mControllers.size();i++)
|
|
||||||
mLayer[layeridx].mSource->mControllers[i].update();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mSkelBase)
|
if(mSkelBase)
|
||||||
|
|
|
@ -19,11 +19,10 @@ protected:
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
Animation *mAnimation;
|
Animation *mAnimation;
|
||||||
size_t mIndex;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AnimationValue(Animation *anim, size_t layeridx)
|
AnimationValue(Animation *anim)
|
||||||
: mAnimation(anim), mIndex(layeridx)
|
: mAnimation(anim)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
virtual Ogre::Real getValue() const;
|
virtual Ogre::Real getValue() const;
|
||||||
|
@ -37,8 +36,6 @@ protected:
|
||||||
typedef std::vector<AnimSource> AnimSourceList;
|
typedef std::vector<AnimSource> AnimSourceList;
|
||||||
|
|
||||||
struct AnimLayer {
|
struct AnimLayer {
|
||||||
std::string mGroupName;
|
|
||||||
AnimSource *mSource;
|
|
||||||
NifOgre::TextKeyMap::const_iterator mStartKey;
|
NifOgre::TextKeyMap::const_iterator mStartKey;
|
||||||
NifOgre::TextKeyMap::const_iterator mLoopStartKey;
|
NifOgre::TextKeyMap::const_iterator mLoopStartKey;
|
||||||
NifOgre::TextKeyMap::const_iterator mStopKey;
|
NifOgre::TextKeyMap::const_iterator mStopKey;
|
||||||
|
@ -49,8 +46,10 @@ protected:
|
||||||
bool mPlaying;
|
bool mPlaying;
|
||||||
size_t mLoopCount;
|
size_t mLoopCount;
|
||||||
|
|
||||||
AnimLayer();
|
AnimLayer() : mTime(0.0f), mPlaying(false), mLoopCount(0)
|
||||||
|
{ }
|
||||||
};
|
};
|
||||||
|
typedef std::map<std::string,AnimLayer> AnimLayerMap;
|
||||||
|
|
||||||
MWWorld::Ptr mPtr;
|
MWWorld::Ptr mPtr;
|
||||||
|
|
||||||
|
@ -67,9 +66,12 @@ protected:
|
||||||
float mAnimVelocity;
|
float mAnimVelocity;
|
||||||
float mAnimSpeedMult;
|
float mAnimSpeedMult;
|
||||||
|
|
||||||
static const size_t sMaxLayers = 1;
|
AnimLayerMap mLayers;
|
||||||
AnimLayer mLayer[sMaxLayers];
|
|
||||||
Ogre::SharedPtr<AnimationValue> mAnimationValuePtr[sMaxLayers];
|
// Note: One per animation group (lower body, upper body, left arm, etc).
|
||||||
|
AnimSource *mSource;
|
||||||
|
std::string mAnimationName;
|
||||||
|
Ogre::SharedPtr<AnimationValue> mAnimationValuePtr;
|
||||||
|
|
||||||
static float calcAnimVelocity(const NifOgre::TextKeyMap &keys,
|
static float calcAnimVelocity(const NifOgre::TextKeyMap &keys,
|
||||||
NifOgre::NodeTargetValue<Ogre::Real> *nonaccumctrl,
|
NifOgre::NodeTargetValue<Ogre::Real> *nonaccumctrl,
|
||||||
|
@ -80,9 +82,9 @@ protected:
|
||||||
* bone names) are positioned identically. */
|
* bone names) are positioned identically. */
|
||||||
void updateSkeletonInstance(const Ogre::SkeletonInstance *skelsrc, Ogre::SkeletonInstance *skel);
|
void updateSkeletonInstance(const Ogre::SkeletonInstance *skelsrc, Ogre::SkeletonInstance *skel);
|
||||||
|
|
||||||
/* Updates the position of the accum root node for the current time, and
|
/* Updates the position of the accum root node for the given time, and
|
||||||
* returns the wanted movement vector from the previous update. */
|
* returns the wanted movement vector from the previous update. */
|
||||||
void updatePosition(Ogre::Vector3 &position);
|
void updatePosition(float time, Ogre::Vector3 &position);
|
||||||
|
|
||||||
static NifOgre::TextKeyMap::const_iterator findGroupStart(const NifOgre::TextKeyMap &keys, const std::string &groupname);
|
static NifOgre::TextKeyMap::const_iterator findGroupStart(const NifOgre::TextKeyMap &keys, const std::string &groupname);
|
||||||
|
|
||||||
|
@ -91,14 +93,14 @@ protected:
|
||||||
* the marker is not found, or if the markers are the same, it returns
|
* the marker is not found, or if the markers are the same, it returns
|
||||||
* false.
|
* false.
|
||||||
*/
|
*/
|
||||||
bool reset(size_t layeridx, const NifOgre::TextKeyMap &keys,
|
bool reset(AnimLayer &layer, const NifOgre::TextKeyMap &keys,
|
||||||
NifOgre::NodeTargetValue<Ogre::Real> *nonaccumctrl,
|
NifOgre::NodeTargetValue<Ogre::Real> *nonaccumctrl,
|
||||||
const std::string &groupname, const std::string &start, const std::string &stop,
|
const std::string &groupname, const std::string &start, const std::string &stop,
|
||||||
float startpoint);
|
float startpoint);
|
||||||
|
|
||||||
bool doLoop(size_t layeridx);
|
bool doLoop(AnimLayer &layer);
|
||||||
|
|
||||||
bool handleTextKey(size_t layeridx, const NifOgre::TextKeyMap::const_iterator &key);
|
bool handleTextKey(AnimLayer &layer, const std::string &groupname, const NifOgre::TextKeyMap::const_iterator &key);
|
||||||
|
|
||||||
void setObjectRoot(Ogre::SceneNode *node, const std::string &model, bool baseonly);
|
void setObjectRoot(Ogre::SceneNode *node, const std::string &model, bool baseonly);
|
||||||
void addAnimSource(const std::string &model);
|
void addAnimSource(const std::string &model);
|
||||||
|
@ -138,27 +140,21 @@ public:
|
||||||
*/
|
*/
|
||||||
bool play(const std::string &groupname, const std::string &start, const std::string &stop, float startpoint, size_t loops);
|
bool play(const std::string &groupname, const std::string &start, const std::string &stop, float startpoint, size_t loops);
|
||||||
|
|
||||||
/** Stops and removes the animation from the given layer. */
|
void disable(const std::string &groupname);
|
||||||
void disable(size_t layeridx);
|
|
||||||
|
|
||||||
/** Gets info about the given animation layer.
|
/** Gets info about the given animation group.
|
||||||
* \param layeridx Layer index to get info about.
|
* \param groupname Animation group to check.
|
||||||
* \param complete Stores completion amount (0 = at start key, 0.5 = half way between start and stop keys), etc.
|
* \param complete Stores completion amount (0 = at start key, 0.5 = half way between start and stop keys), etc.
|
||||||
* \param groupname Stores animation group being played.
|
|
||||||
* \param start Stores the start key
|
* \param start Stores the start key
|
||||||
* \param stop Stores the stop key
|
* \param stop Stores the stop key
|
||||||
* \return True if an animation is active on the layer, false otherwise.
|
* \return True if the animation is active, false otherwise.
|
||||||
*/
|
*/
|
||||||
bool getInfo(size_t layeridx, float *complete=NULL, std::string *groupname=NULL, std::string *start=NULL, std::string *stop=NULL) const;
|
bool getInfo(const std::string &groupname, float *complete=NULL, std::string *start=NULL, std::string *stop=NULL) const;
|
||||||
|
|
||||||
virtual Ogre::Vector3 runAnimation(float duration);
|
virtual Ogre::Vector3 runAnimation(float duration);
|
||||||
|
|
||||||
virtual void showWeapons(bool showWeapon);
|
virtual void showWeapons(bool showWeapon);
|
||||||
|
|
||||||
/* Returns if there's an animation playing on the given layer. */
|
|
||||||
bool isPlaying(size_t layeridx) const
|
|
||||||
{ return mLayer[layeridx].mPlaying; }
|
|
||||||
|
|
||||||
Ogre::Node *getNode(const std::string &name);
|
Ogre::Node *getNode(const std::string &name);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue