|
@@ -9,10 +9,10 @@ namespace gameplay
|
|
|
{
|
|
{
|
|
|
|
|
|
|
|
AnimationClip::AnimationClip(const char* id, Animation* animation, unsigned long startTime, unsigned long endTime)
|
|
AnimationClip::AnimationClip(const char* id, Animation* animation, unsigned long startTime, unsigned long endTime)
|
|
|
- : _id(id), _animation(animation), _startTime(startTime), _endTime(endTime), _duration(_endTime - _startTime), _repeatCount(1.0f),
|
|
|
|
|
- _activeDuration(_duration * _repeatCount), _speed(1.0f), _isPlaying(false), _timeStarted(0), _elapsedTime(0),
|
|
|
|
|
- _crossFadeToClip(NULL), _crossFadeOutElapsed(0), _crossFadeOutDuration(0), _blendWeight(1.0f), _isFadingOutStarted(false),
|
|
|
|
|
- _isFadingOut(false), _isFadingIn(false), _beginListeners(NULL), _endListeners(NULL), _listeners(NULL), _listenerItr(NULL)
|
|
|
|
|
|
|
+ : _id(id), _animation(animation), _startTime(startTime), _endTime(endTime), _duration(_endTime - _startTime),
|
|
|
|
|
+ _stateBits(0x00), _repeatCount(1.0f), _activeDuration(_duration * _repeatCount), _speed(1.0f), _timeStarted(0),
|
|
|
|
|
+ _elapsedTime(0), _crossFadeToClip(NULL), _crossFadeOutElapsed(0), _crossFadeOutDuration(0), _blendWeight(1.0f),
|
|
|
|
|
+ _beginListeners(NULL), _endListeners(NULL), _listeners(NULL), _listenerItr(NULL)
|
|
|
{
|
|
{
|
|
|
assert(0 <= startTime && startTime <= animation->_duration && 0 <= endTime && endTime <= animation->_duration);
|
|
assert(0 <= startTime && startTime <= animation->_duration && 0 <= endTime && endTime <= animation->_duration);
|
|
|
|
|
|
|
@@ -130,21 +130,30 @@ float AnimationClip::getBlendWeight() const
|
|
|
|
|
|
|
|
bool AnimationClip::isPlaying() const
|
|
bool AnimationClip::isPlaying() const
|
|
|
{
|
|
{
|
|
|
- return _isPlaying;
|
|
|
|
|
|
|
+ return isClipStateBitSet(CLIP_IS_PLAYING_BIT);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void AnimationClip::play()
|
|
void AnimationClip::play()
|
|
|
{
|
|
{
|
|
|
|
|
+ if (isClipStateBitSet(CLIP_IS_PLAYING_BIT))
|
|
|
|
|
+ {
|
|
|
|
|
+ _animation->_controller->unschedule(this);
|
|
|
|
|
+ resetClipStateBit(CLIP_IS_STARTED_BIT);
|
|
|
|
|
+ onEnd();
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ setClipStateBit(CLIP_IS_PLAYING_BIT);
|
|
|
|
|
+
|
|
|
_animation->_controller->schedule(this);
|
|
_animation->_controller->schedule(this);
|
|
|
_timeStarted = Game::getGameTime();
|
|
_timeStarted = Game::getGameTime();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void AnimationClip::stop()
|
|
void AnimationClip::stop()
|
|
|
{
|
|
{
|
|
|
- _animation->_controller->unschedule(this);
|
|
|
|
|
- if (_isPlaying)
|
|
|
|
|
|
|
+ if (isClipStateBitSet(CLIP_IS_PLAYING_BIT))
|
|
|
{
|
|
{
|
|
|
- _isPlaying = false;
|
|
|
|
|
|
|
+ _animation->_controller->unschedule(this);
|
|
|
|
|
+ resetClipStateBit(CLIP_IS_PLAYING_BIT | CLIP_IS_STARTED_BIT);
|
|
|
onEnd();
|
|
onEnd();
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -155,25 +164,28 @@ void AnimationClip::crossFade(AnimationClip* clip, unsigned long duration)
|
|
|
|
|
|
|
|
// If I already have a clip I'm fading to and it's not the same as the given clip release it.
|
|
// If I already have a clip I'm fading to and it's not the same as the given clip release it.
|
|
|
// Assign the new clip and increase it's ref count.
|
|
// Assign the new clip and increase it's ref count.
|
|
|
- // TODO: Do I need to anything else to the crossFade clip here before releasing?
|
|
|
|
|
if (_crossFadeToClip)
|
|
if (_crossFadeToClip)
|
|
|
|
|
+ {
|
|
|
|
|
+ _crossFadeToClip->stop();
|
|
|
|
|
+ _crossFadeToClip->resetClipStateBit(CLIP_IS_FADING_IN_BIT);
|
|
|
SAFE_RELEASE(_crossFadeToClip);
|
|
SAFE_RELEASE(_crossFadeToClip);
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
_crossFadeToClip = clip;
|
|
_crossFadeToClip = clip;
|
|
|
_crossFadeToClip->addRef();
|
|
_crossFadeToClip->addRef();
|
|
|
|
|
|
|
|
// Set the crossfade clip to fading in, and initialize it's blend weight to zero.
|
|
// Set the crossfade clip to fading in, and initialize it's blend weight to zero.
|
|
|
- _crossFadeToClip->_isFadingIn = true;
|
|
|
|
|
|
|
+ _crossFadeToClip->setClipStateBit(CLIP_IS_FADING_IN_BIT);
|
|
|
_crossFadeToClip->_blendWeight = 0.0f;
|
|
_crossFadeToClip->_blendWeight = 0.0f;
|
|
|
|
|
|
|
|
// Set this clip to fade out, set the fade duration and reset the fade elapsed time.
|
|
// Set this clip to fade out, set the fade duration and reset the fade elapsed time.
|
|
|
- _isFadingOut = true;
|
|
|
|
|
|
|
+ setClipStateBit(CLIP_IS_FADING_OUT_STARTED_BIT);
|
|
|
|
|
+ setClipStateBit(CLIP_IS_FADING_OUT_BIT);
|
|
|
_crossFadeOutElapsed = 0;
|
|
_crossFadeOutElapsed = 0;
|
|
|
_crossFadeOutDuration = duration;
|
|
_crossFadeOutDuration = duration;
|
|
|
- _isFadingOutStarted = true;
|
|
|
|
|
|
|
|
|
|
// If this clip is currently not playing, we should start playing it.
|
|
// If this clip is currently not playing, we should start playing it.
|
|
|
- if (!_isPlaying)
|
|
|
|
|
|
|
+ if (!isClipStateBitSet(CLIP_IS_PLAYING_BIT))
|
|
|
play();
|
|
play();
|
|
|
|
|
|
|
|
// Start playing the cross fade clip.
|
|
// Start playing the cross fade clip.
|
|
@@ -193,7 +205,7 @@ void AnimationClip::addListener(AnimationClip::Listener* listener, unsigned long
|
|
|
_listeners->push_front(listener);
|
|
_listeners->push_front(listener);
|
|
|
|
|
|
|
|
_listenerItr = new std::list<Listener*>::iterator;
|
|
_listenerItr = new std::list<Listener*>::iterator;
|
|
|
- if (_isPlaying)
|
|
|
|
|
|
|
+ if (isClipStateBitSet(CLIP_IS_PLAYING_BIT))
|
|
|
*_listenerItr = _listeners->begin();
|
|
*_listenerItr = _listeners->begin();
|
|
|
}
|
|
}
|
|
|
else
|
|
else
|
|
@@ -206,7 +218,7 @@ void AnimationClip::addListener(AnimationClip::Listener* listener, unsigned long
|
|
|
|
|
|
|
|
// If playing, update the iterator if we need to.
|
|
// If playing, update the iterator if we need to.
|
|
|
// otherwise, it will just be set the next time the clip gets played.
|
|
// otherwise, it will just be set the next time the clip gets played.
|
|
|
- if (_isPlaying)
|
|
|
|
|
|
|
+ if (isClipStateBitSet(CLIP_IS_PLAYING_BIT))
|
|
|
{
|
|
{
|
|
|
unsigned long currentTime = _elapsedTime % _duration;
|
|
unsigned long currentTime = _elapsedTime % _duration;
|
|
|
if ((_speed >= 0.0f && currentTime < eventTime && (*_listenerItr == _listeners->end() || eventTime < (**_listenerItr)->_listenerTime)) ||
|
|
if ((_speed >= 0.0f && currentTime < eventTime && (*_listenerItr == _listeners->end() || eventTime < (**_listenerItr)->_listenerTime)) ||
|
|
@@ -237,7 +249,7 @@ void AnimationClip::addEndListener(AnimationClip::Listener* listener)
|
|
|
|
|
|
|
|
bool AnimationClip::update(unsigned long elapsedTime, std::list<AnimationTarget*>* activeTargets)
|
|
bool AnimationClip::update(unsigned long elapsedTime, std::list<AnimationTarget*>* activeTargets)
|
|
|
{
|
|
{
|
|
|
- if (!_isPlaying)
|
|
|
|
|
|
|
+ if (!isClipStateBitSet(CLIP_IS_STARTED_BIT))
|
|
|
onBegin();
|
|
onBegin();
|
|
|
else
|
|
else
|
|
|
_elapsedTime += elapsedTime * _speed;
|
|
_elapsedTime += elapsedTime * _speed;
|
|
@@ -246,7 +258,7 @@ bool AnimationClip::update(unsigned long elapsedTime, std::list<AnimationTarget*
|
|
|
// Check to see if clip is complete.
|
|
// Check to see if clip is complete.
|
|
|
if (_repeatCount != REPEAT_INDEFINITE && ((_speed >= 0.0f && _elapsedTime >= (long) _activeDuration) || (_speed <= 0.0f && _elapsedTime <= 0L)))
|
|
if (_repeatCount != REPEAT_INDEFINITE && ((_speed >= 0.0f && _elapsedTime >= (long) _activeDuration) || (_speed <= 0.0f && _elapsedTime <= 0L)))
|
|
|
{
|
|
{
|
|
|
- _isPlaying = false;
|
|
|
|
|
|
|
+ resetClipStateBit(CLIP_IS_STARTED_BIT);
|
|
|
if (_speed >= 0.0f)
|
|
if (_speed >= 0.0f)
|
|
|
{
|
|
{
|
|
|
currentTime = _activeDuration % _duration; // Get's the fractional part of the final repeat.
|
|
currentTime = _activeDuration % _duration; // Get's the fractional part of the final repeat.
|
|
@@ -288,12 +300,12 @@ bool AnimationClip::update(unsigned long elapsedTime, std::list<AnimationTarget*
|
|
|
// Add back in start time, and divide by the total animation's duration to get the actual percentage complete
|
|
// Add back in start time, and divide by the total animation's duration to get the actual percentage complete
|
|
|
float percentComplete = (float)(_startTime + currentTime) / (float) _animation->_duration;
|
|
float percentComplete = (float)(_startTime + currentTime) / (float) _animation->_duration;
|
|
|
|
|
|
|
|
- if (_isFadingOut)
|
|
|
|
|
|
|
+ if (isClipStateBitSet(CLIP_IS_FADING_OUT_BIT))
|
|
|
{
|
|
{
|
|
|
- if (_isFadingOutStarted) // Calculate elapsed time since the fade out begin.
|
|
|
|
|
|
|
+ if (isClipStateBitSet(CLIP_IS_FADING_OUT_STARTED_BIT)) // Calculate elapsed time since the fade out begin.
|
|
|
{
|
|
{
|
|
|
- _crossFadeOutElapsed = (Game::getGameTime() - _crossFadeToClip->_timeStarted) * _speed;
|
|
|
|
|
- _isFadingOutStarted = false;
|
|
|
|
|
|
|
+ _crossFadeOutElapsed = (Game::getGameTime() - _crossFadeToClip->_timeStarted) * abs(_speed);
|
|
|
|
|
+ resetClipStateBit(CLIP_IS_FADING_OUT_STARTED_BIT);
|
|
|
}
|
|
}
|
|
|
else
|
|
else
|
|
|
{
|
|
{
|
|
@@ -307,7 +319,7 @@ bool AnimationClip::update(unsigned long elapsedTime, std::list<AnimationTarget*
|
|
|
float tempBlendWeight = (float) (_crossFadeOutDuration - _crossFadeOutElapsed) / (float) _crossFadeOutDuration;
|
|
float tempBlendWeight = (float) (_crossFadeOutDuration - _crossFadeOutElapsed) / (float) _crossFadeOutDuration;
|
|
|
|
|
|
|
|
// If this clip is fading in, adjust the crossfade clip's weight to be a percentage of your current blend weight
|
|
// If this clip is fading in, adjust the crossfade clip's weight to be a percentage of your current blend weight
|
|
|
- if (_isFadingIn)
|
|
|
|
|
|
|
+ if (isClipStateBitSet(CLIP_IS_FADING_IN_BIT))
|
|
|
{
|
|
{
|
|
|
_crossFadeToClip->_blendWeight = (1.0f - tempBlendWeight) * _blendWeight;
|
|
_crossFadeToClip->_blendWeight = (1.0f - tempBlendWeight) * _blendWeight;
|
|
|
_blendWeight -= _crossFadeToClip->_blendWeight;
|
|
_blendWeight -= _crossFadeToClip->_blendWeight;
|
|
@@ -321,21 +333,21 @@ bool AnimationClip::update(unsigned long elapsedTime, std::list<AnimationTarget*
|
|
|
}
|
|
}
|
|
|
else
|
|
else
|
|
|
{ // Fade is done.
|
|
{ // Fade is done.
|
|
|
- // Set the crossFadeToClip's blend weight to 1
|
|
|
|
|
|
|
+ // Set blendweights
|
|
|
_crossFadeToClip->_blendWeight = 1.0f;
|
|
_crossFadeToClip->_blendWeight = 1.0f;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// Adjust the crossfade clip's blend weight if this clip is also fading in.
|
|
// Adjust the crossfade clip's blend weight if this clip is also fading in.
|
|
|
- if (_isFadingIn)
|
|
|
|
|
|
|
+ if (isClipStateBitSet(CLIP_IS_FADING_IN_BIT))
|
|
|
_crossFadeToClip->_blendWeight *= _blendWeight;
|
|
_crossFadeToClip->_blendWeight *= _blendWeight;
|
|
|
|
|
|
|
|
- // The crossfade clip is no longer fading in
|
|
|
|
|
- _crossFadeToClip->_isFadingIn = false;
|
|
|
|
|
|
|
+ _blendWeight = 0.0f;
|
|
|
|
|
+
|
|
|
|
|
+ // reset the states of our clips to turn off the cross fade.
|
|
|
|
|
+ _crossFadeToClip->resetClipStateBit(CLIP_IS_FADING_IN_BIT);
|
|
|
|
|
+ resetClipStateBit(CLIP_IS_FADING_OUT_BIT | CLIP_IS_STARTED_BIT);
|
|
|
|
|
|
|
|
// Release the crossfade clip, mark ourselves as done and set our blend weight to 0.
|
|
// Release the crossfade clip, mark ourselves as done and set our blend weight to 0.
|
|
|
SAFE_RELEASE(_crossFadeToClip);
|
|
SAFE_RELEASE(_crossFadeToClip);
|
|
|
- _blendWeight = 0.0f;
|
|
|
|
|
- _isFadingOut = false;
|
|
|
|
|
- _isPlaying = false;
|
|
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -363,7 +375,7 @@ bool AnimationClip::update(unsigned long elapsedTime, std::list<AnimationTarget*
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// When ended. Probably should move to it's own method so we can call it when the clip is ended early.
|
|
// When ended. Probably should move to it's own method so we can call it when the clip is ended early.
|
|
|
- if (!_isPlaying)
|
|
|
|
|
|
|
+ if (!isClipStateBitSet(CLIP_IS_STARTED_BIT))
|
|
|
{
|
|
{
|
|
|
onEnd();
|
|
onEnd();
|
|
|
// Notify end listeners if any.
|
|
// Notify end listeners if any.
|
|
@@ -376,16 +388,17 @@ bool AnimationClip::update(unsigned long elapsedTime, std::list<AnimationTarget*
|
|
|
listener++;
|
|
listener++;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ return true;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- return !_isPlaying;
|
|
|
|
|
|
|
+ return false;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void AnimationClip::onBegin()
|
|
void AnimationClip::onBegin()
|
|
|
{
|
|
{
|
|
|
// Initialize animation to play.
|
|
// Initialize animation to play.
|
|
|
- _isPlaying = true;
|
|
|
|
|
-
|
|
|
|
|
|
|
+ setClipStateBit(CLIP_IS_STARTED_BIT);
|
|
|
if (_speed >= 0)
|
|
if (_speed >= 0)
|
|
|
{
|
|
{
|
|
|
_elapsedTime = 0;
|
|
_elapsedTime = 0;
|
|
@@ -419,6 +432,22 @@ void AnimationClip::onEnd()
|
|
|
{
|
|
{
|
|
|
_blendWeight = 1.0f;
|
|
_blendWeight = 1.0f;
|
|
|
_timeStarted = 0;
|
|
_timeStarted = 0;
|
|
|
|
|
+ resetClipStateBit(CLIP_IS_PLAYING_BIT);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+bool AnimationClip::isClipStateBitSet(char bit) const
|
|
|
|
|
+{
|
|
|
|
|
+ return (_stateBits & bit) == bit;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void AnimationClip::setClipStateBit(char bit)
|
|
|
|
|
+{
|
|
|
|
|
+ _stateBits |= bit;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void AnimationClip::resetClipStateBit(char bit)
|
|
|
|
|
+{
|
|
|
|
|
+ _stateBits &= ~bit;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
}
|
|
}
|