mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-22 19:09:42 +00:00
Separate some Animation fields into a separate AnimLayer class
This commit is contained in:
parent
c3ce49798a
commit
8782ae6976
3 changed files with 130 additions and 105 deletions
|
@ -304,11 +304,7 @@ void CharacterController::skipAnim()
|
|||
void CharacterController::setState(CharacterState state, bool loop)
|
||||
{
|
||||
if(mState == state)
|
||||
{
|
||||
if(mAnimation)
|
||||
mAnimation->setLooping(loop);
|
||||
return;
|
||||
}
|
||||
mState = state;
|
||||
|
||||
if(!mAnimation)
|
||||
|
|
|
@ -18,6 +18,32 @@
|
|||
namespace MWRender
|
||||
{
|
||||
|
||||
Animation::AnimLayer::AnimLayer()
|
||||
: mControllers(NULL)
|
||||
, mTextKeys(NULL)
|
||||
, mTime(0.0f)
|
||||
, mPlaying(false)
|
||||
, mLooping(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Ogre::Real Animation::AnimationValue::getValue() const
|
||||
{
|
||||
size_t idx = mIndex;
|
||||
while(idx > 0 && mAnimation->mLayer[idx].mGroupName.empty())
|
||||
idx--;
|
||||
if(!mAnimation->mLayer[idx].mGroupName.empty())
|
||||
return mAnimation->mLayer[idx].mTime;
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
void Animation::AnimationValue::setValue(Ogre::Real value)
|
||||
{
|
||||
mAnimation->mLayer[mIndex].mTime = value;
|
||||
}
|
||||
|
||||
|
||||
void Animation::destroyObjectList(Ogre::SceneManager *sceneMgr, NifOgre::ObjectList &objects)
|
||||
{
|
||||
for(size_t i = 0;i < objects.mParticles.size();i++)
|
||||
|
@ -32,7 +58,7 @@ void Animation::destroyObjectList(Ogre::SceneManager *sceneMgr, NifOgre::ObjectL
|
|||
}
|
||||
|
||||
Animation::Animation(const MWWorld::Ptr &ptr)
|
||||
: mAnimationBaseValuePtr(OGRE_NEW AnimationValue(this))
|
||||
: mAnimationBaseValuePtr(OGRE_NEW AnimationValue(this, 0))
|
||||
, mPtr(ptr)
|
||||
, mController(NULL)
|
||||
, mInsert(NULL)
|
||||
|
@ -41,11 +67,6 @@ Animation::Animation(const MWWorld::Ptr &ptr)
|
|||
, mNonAccumRoot(NULL)
|
||||
, mAccumulate(0.0f)
|
||||
, mLastPosition(0.0f)
|
||||
, mCurrentControllers(NULL)
|
||||
, mCurrentKeys(NULL)
|
||||
, mCurrentTime(0.0f)
|
||||
, mPlaying(false)
|
||||
, mLooping(false)
|
||||
, mNonAccumCtrl(NULL)
|
||||
, mAnimVelocity(0.0f)
|
||||
, mAnimSpeedMult(1.0f)
|
||||
|
@ -127,9 +148,6 @@ void Animation::addObjectList(Ogre::SceneNode *node, const std::string &model, b
|
|||
if(objlist.mControllers[i].getSource().isNull())
|
||||
objlist.mControllers[i].setSource(mAnimationBaseValuePtr);
|
||||
}
|
||||
|
||||
if(!mCurrentControllers || (*mCurrentControllers).size() == 0)
|
||||
mCurrentControllers = &objlist.mControllers;
|
||||
}
|
||||
|
||||
void Animation::setRenderProperties(const NifOgre::ObjectList &objlist, Ogre::uint32 visflags, Ogre::uint8 solidqueue, Ogre::uint8 transqueue)
|
||||
|
@ -215,10 +233,6 @@ void Animation::setSpeed(float speed)
|
|||
mAnimSpeedMult = speed / mAnimVelocity;
|
||||
}
|
||||
|
||||
void Animation::setLooping(bool loop)
|
||||
{
|
||||
mLooping = loop;
|
||||
}
|
||||
|
||||
void Animation::updatePtr(const MWWorld::Ptr &ptr)
|
||||
{
|
||||
|
@ -301,7 +315,7 @@ Ogre::Vector3 Animation::updatePosition()
|
|||
Ogre::Vector3 posdiff;
|
||||
|
||||
/* Get the non-accumulation root's difference from the last update. */
|
||||
posdiff = (mNonAccumCtrl->getTranslation(mCurrentTime) - mLastPosition) * mAccumulate;
|
||||
posdiff = (mNonAccumCtrl->getTranslation(mLayer[0].mTime) - mLastPosition) * mAccumulate;
|
||||
|
||||
/* Translate the accumulation root back to compensate for the move. */
|
||||
mLastPosition += posdiff;
|
||||
|
@ -310,7 +324,7 @@ Ogre::Vector3 Animation::updatePosition()
|
|||
return posdiff;
|
||||
}
|
||||
|
||||
bool Animation::reset(const NifOgre::TextKeyMap &keys, NifOgre::NodeTargetValue<Ogre::Real> *nonaccumctrl, const std::string &groupname, const std::string &start, const std::string &stop)
|
||||
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)
|
||||
{
|
||||
std::string tag = groupname+": "+start;
|
||||
NifOgre::TextKeyMap::const_iterator startkey(keys.begin());
|
||||
|
@ -336,31 +350,31 @@ bool Animation::reset(const NifOgre::TextKeyMap &keys, NifOgre::NodeTargetValue<
|
|||
if(startkey == stopkey)
|
||||
return false;
|
||||
|
||||
mStartKey = startkey;
|
||||
mLoopStartKey = mStartKey;
|
||||
mStopKey = stopkey;
|
||||
mNextKey = mStartKey;
|
||||
++mNextKey;
|
||||
mLayer[layeridx].mStartKey = startkey;
|
||||
mLayer[layeridx].mLoopStartKey = startkey;
|
||||
mLayer[layeridx].mStopKey = stopkey;
|
||||
mLayer[layeridx].mNextKey = startkey;
|
||||
mLayer[layeridx].mNextKey++;
|
||||
|
||||
mCurrentTime = mStartKey->first;
|
||||
mLayer[layeridx].mTime = mLayer[layeridx].mStartKey->first;
|
||||
|
||||
if(nonaccumctrl)
|
||||
mLastPosition = nonaccumctrl->getTranslation(mCurrentTime) * mAccumulate;
|
||||
if(layeridx == 0 && nonaccumctrl)
|
||||
mLastPosition = nonaccumctrl->getTranslation(mLayer[layeridx].mTime) * mAccumulate;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Animation::doLoop()
|
||||
void Animation::doLoop(size_t layeridx)
|
||||
{
|
||||
mCurrentTime = mLoopStartKey->first;
|
||||
mNextKey = mLoopStartKey;
|
||||
++mNextKey;
|
||||
if(mNonAccumCtrl)
|
||||
mLastPosition = mNonAccumCtrl->getTranslation(mCurrentTime) * mAccumulate;
|
||||
mLayer[layeridx].mTime = mLayer[layeridx].mLoopStartKey->first;
|
||||
mLayer[layeridx].mNextKey = mLayer[layeridx].mLoopStartKey;
|
||||
mLayer[layeridx].mNextKey++;
|
||||
if(layeridx == 0 && mNonAccumCtrl)
|
||||
mLastPosition = mNonAccumCtrl->getTranslation(mLayer[layeridx].mTime) * mAccumulate;
|
||||
}
|
||||
|
||||
|
||||
bool Animation::handleTextKey(const NifOgre::TextKeyMap::const_iterator &key)
|
||||
bool Animation::handleTextKey(size_t layeridx, const NifOgre::TextKeyMap::const_iterator &key)
|
||||
{
|
||||
float time = key->first;
|
||||
const std::string &evt = key->second;
|
||||
|
@ -378,27 +392,27 @@ bool Animation::handleTextKey(const NifOgre::TextKeyMap::const_iterator &key)
|
|||
return true;
|
||||
}
|
||||
|
||||
if(evt.compare(0, mCurrentGroup.size(), mCurrentGroup) != 0 ||
|
||||
evt.compare(mCurrentGroup.size(), 2, ": ") != 0)
|
||||
if(evt.compare(0, mLayer[layeridx].mGroupName.size(), mLayer[layeridx].mGroupName) != 0 ||
|
||||
evt.compare(mLayer[layeridx].mGroupName.size(), 2, ": ") != 0)
|
||||
{
|
||||
// Not ours
|
||||
// Not ours, skip it
|
||||
return true;
|
||||
}
|
||||
size_t off = mCurrentGroup.size()+2;
|
||||
size_t off = mLayer[layeridx].mGroupName.size()+2;
|
||||
size_t len = evt.size() - off;
|
||||
|
||||
if(evt.compare(off, len, "start") == 0 || evt.compare(off, len, "loop start") == 0)
|
||||
{
|
||||
mLoopStartKey = key;
|
||||
mLayer[layeridx].mLoopStartKey = key;
|
||||
return true;
|
||||
}
|
||||
|
||||
if(evt.compare(off, len, "loop stop") == 0 || evt.compare(off, len, "stop") == 0)
|
||||
{
|
||||
if(mLooping)
|
||||
if(mLayer[layeridx].mLooping)
|
||||
{
|
||||
doLoop();
|
||||
if(mCurrentTime >= time)
|
||||
doLoop(layeridx);
|
||||
if(mLayer[layeridx].mTime >= time)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
@ -412,6 +426,9 @@ bool Animation::handleTextKey(const NifOgre::TextKeyMap::const_iterator &key)
|
|||
|
||||
void Animation::play(const std::string &groupname, const std::string &start, const std::string &stop, bool loop)
|
||||
{
|
||||
// TODO: parameterize this
|
||||
size_t layeridx = 0;
|
||||
|
||||
try {
|
||||
bool foundanim = false;
|
||||
/* Look in reverse; last-inserted source has priority. */
|
||||
|
@ -422,34 +439,40 @@ void Animation::play(const std::string &groupname, const std::string &start, con
|
|||
|
||||
const NifOgre::TextKeyMap &keys = iter->mTextKeys.begin()->second;
|
||||
NifOgre::NodeTargetValue<Ogre::Real> *nonaccumctrl = NULL;
|
||||
for(size_t i = 0;i < iter->mControllers.size();i++)
|
||||
if(layeridx == 0)
|
||||
{
|
||||
NifOgre::NodeTargetValue<Ogre::Real> *dstval;
|
||||
dstval = dynamic_cast<NifOgre::NodeTargetValue<Ogre::Real>*>(iter->mControllers[i].getDestination().getPointer());
|
||||
if(dstval && dstval->getNode() == mNonAccumRoot)
|
||||
for(size_t i = 0;i < iter->mControllers.size();i++)
|
||||
{
|
||||
nonaccumctrl = dstval;
|
||||
break;
|
||||
NifOgre::NodeTargetValue<Ogre::Real> *dstval;
|
||||
dstval = dynamic_cast<NifOgre::NodeTargetValue<Ogre::Real>*>(iter->mControllers[i].getDestination().getPointer());
|
||||
if(dstval && dstval->getNode() == mNonAccumRoot)
|
||||
{
|
||||
nonaccumctrl = dstval;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!foundanim)
|
||||
{
|
||||
if(!reset(keys, nonaccumctrl, groupname, start, stop))
|
||||
if(!reset(layeridx, keys, nonaccumctrl, groupname, start, stop))
|
||||
continue;
|
||||
mCurrentKeys = &keys;
|
||||
mCurrentGroup = groupname;
|
||||
mCurrentControllers = &iter->mControllers;
|
||||
mNonAccumCtrl = nonaccumctrl;
|
||||
mAnimVelocity = 0.0f;
|
||||
mLayer[layeridx].mGroupName = groupname;
|
||||
mLayer[layeridx].mTextKeys = &keys;
|
||||
mLayer[layeridx].mControllers = &iter->mControllers;
|
||||
mLayer[layeridx].mLooping = loop;
|
||||
mLayer[layeridx].mPlaying = true;
|
||||
|
||||
setLooping(loop);
|
||||
mPlaying = true;
|
||||
if(layeridx == 0)
|
||||
{
|
||||
mNonAccumCtrl = nonaccumctrl;
|
||||
mAnimVelocity = 0.0f;
|
||||
}
|
||||
|
||||
foundanim = true;
|
||||
}
|
||||
|
||||
if(!mNonAccumRoot)
|
||||
if(!nonaccumctrl)
|
||||
break;
|
||||
|
||||
mAnimVelocity = calcAnimVelocity(keys, nonaccumctrl, groupname);
|
||||
|
@ -463,37 +486,43 @@ void Animation::play(const std::string &groupname, const std::string &start, con
|
|||
}
|
||||
}
|
||||
|
||||
Ogre::Vector3 Animation::runAnimation(float timepassed)
|
||||
Ogre::Vector3 Animation::runAnimation(float duration)
|
||||
{
|
||||
Ogre::Vector3 movement(0.0f);
|
||||
|
||||
timepassed *= mAnimSpeedMult;
|
||||
while(!mCurrentGroup.empty() && mPlaying)
|
||||
duration *= mAnimSpeedMult;
|
||||
for(size_t layeridx = 0;layeridx < sMaxLayers;layeridx++)
|
||||
{
|
||||
float targetTime = mCurrentTime + timepassed;
|
||||
if(mNextKey->first > targetTime)
|
||||
if(mLayer[layeridx].mGroupName.empty())
|
||||
continue;
|
||||
|
||||
float timepassed = duration;
|
||||
while(mLayer[layeridx].mPlaying)
|
||||
{
|
||||
mCurrentTime = targetTime;
|
||||
if(mNonAccumRoot)
|
||||
float targetTime = mLayer[layeridx].mTime + timepassed;
|
||||
if(mLayer[layeridx].mNextKey->first > targetTime)
|
||||
{
|
||||
mLayer[layeridx].mTime = targetTime;
|
||||
if(layeridx == 0 && mNonAccumRoot)
|
||||
movement += updatePosition();
|
||||
break;
|
||||
}
|
||||
|
||||
NifOgre::TextKeyMap::const_iterator key(mLayer[layeridx].mNextKey++);
|
||||
mLayer[layeridx].mTime = key->first;
|
||||
if(layeridx == 0 && mNonAccumRoot)
|
||||
movement += updatePosition();
|
||||
break;
|
||||
|
||||
mLayer[layeridx].mPlaying = (mLayer[layeridx].mLooping || mLayer[layeridx].mStopKey->first > mLayer[layeridx].mTime);
|
||||
timepassed = targetTime - mLayer[layeridx].mTime;
|
||||
|
||||
if(!handleTextKey(layeridx, key))
|
||||
break;
|
||||
}
|
||||
|
||||
NifOgre::TextKeyMap::const_iterator key(mNextKey++);
|
||||
mCurrentTime = key->first;
|
||||
if(mNonAccumRoot)
|
||||
movement += updatePosition();
|
||||
|
||||
mPlaying = (mLooping || mStopKey->first > mCurrentTime);
|
||||
timepassed = targetTime - mCurrentTime;
|
||||
|
||||
if(!handleTextKey(key))
|
||||
break;
|
||||
for(size_t i = 0;i < (*(mLayer[layeridx].mControllers)).size();i++)
|
||||
(*(mLayer[layeridx].mControllers))[i].update();
|
||||
}
|
||||
|
||||
for(size_t i = 0;i < (*mCurrentControllers).size();i++)
|
||||
(*mCurrentControllers)[i].update();
|
||||
|
||||
if(mSkelBase)
|
||||
{
|
||||
const Ogre::SkeletonInstance *baseinst = mSkelBase->getSkeleton();
|
||||
|
|
|
@ -23,20 +23,15 @@ protected:
|
|||
{
|
||||
private:
|
||||
Animation *mAnimation;
|
||||
size_t mIndex;
|
||||
|
||||
public:
|
||||
AnimationValue(Animation *anim) : mAnimation(anim)
|
||||
AnimationValue(Animation *anim, size_t layeridx)
|
||||
: mAnimation(anim), mIndex(layeridx)
|
||||
{ }
|
||||
|
||||
virtual Ogre::Real getValue() const
|
||||
{
|
||||
return mAnimation->mCurrentTime;
|
||||
}
|
||||
|
||||
virtual void setValue(Ogre::Real value)
|
||||
{
|
||||
mAnimation->mCurrentTime = value;
|
||||
}
|
||||
virtual Ogre::Real getValue() const;
|
||||
virtual void setValue(Ogre::Real value);
|
||||
};
|
||||
Ogre::SharedPtr<Ogre::ControllerValue<Ogre::Real> > mAnimationBaseValuePtr;
|
||||
|
||||
|
@ -51,21 +46,28 @@ protected:
|
|||
Ogre::Vector3 mAccumulate;
|
||||
Ogre::Vector3 mLastPosition;
|
||||
|
||||
std::string mCurrentGroup;
|
||||
std::vector<Ogre::Controller<Ogre::Real> > *mCurrentControllers;
|
||||
const NifOgre::TextKeyMap *mCurrentKeys;
|
||||
NifOgre::TextKeyMap::const_iterator mStartKey;
|
||||
NifOgre::TextKeyMap::const_iterator mLoopStartKey;
|
||||
NifOgre::TextKeyMap::const_iterator mStopKey;
|
||||
NifOgre::TextKeyMap::const_iterator mNextKey;
|
||||
float mCurrentTime;
|
||||
bool mPlaying;
|
||||
bool mLooping;
|
||||
|
||||
NifOgre::NodeTargetValue<Ogre::Real> *mNonAccumCtrl;
|
||||
float mAnimVelocity;
|
||||
float mAnimSpeedMult;
|
||||
|
||||
static const size_t sMaxLayers = 1;
|
||||
struct AnimLayer {
|
||||
std::string mGroupName;
|
||||
std::vector<Ogre::Controller<Ogre::Real> > *mControllers;
|
||||
const NifOgre::TextKeyMap *mTextKeys;
|
||||
NifOgre::TextKeyMap::const_iterator mStartKey;
|
||||
NifOgre::TextKeyMap::const_iterator mLoopStartKey;
|
||||
NifOgre::TextKeyMap::const_iterator mStopKey;
|
||||
NifOgre::TextKeyMap::const_iterator mNextKey;
|
||||
|
||||
float mTime;
|
||||
|
||||
bool mPlaying;
|
||||
bool mLooping;
|
||||
|
||||
AnimLayer();
|
||||
} mLayer[sMaxLayers];
|
||||
|
||||
static float calcAnimVelocity(const NifOgre::TextKeyMap &keys,
|
||||
NifOgre::NodeTargetValue<Ogre::Real> *nonaccumctrl,
|
||||
const std::string &groupname);
|
||||
|
@ -85,11 +87,11 @@ protected:
|
|||
* the marker is not found, or if the markers are the same, it returns
|
||||
* false.
|
||||
*/
|
||||
bool reset(const NifOgre::TextKeyMap &keys, NifOgre::NodeTargetValue<Ogre::Real> *nonaccumctrl, const std::string &groupname, const std::string &start, const std::string &stop);
|
||||
bool 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);
|
||||
|
||||
void doLoop();
|
||||
void doLoop(size_t layeridx);
|
||||
|
||||
bool handleTextKey(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);
|
||||
static void destroyObjectList(Ogre::SceneManager *sceneMgr, NifOgre::ObjectList &objects);
|
||||
|
@ -113,8 +115,6 @@ public:
|
|||
|
||||
void setSpeed(float speed);
|
||||
|
||||
void setLooping(bool loop);
|
||||
|
||||
void play(const std::string &groupname, const std::string &start, const std::string &stop, bool loop);
|
||||
virtual Ogre::Vector3 runAnimation(float timepassed);
|
||||
|
||||
|
|
Loading…
Reference in a new issue