AnimationClip.cpp 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  1. #include "Base.h"
  2. #include "AnimationClip.h"
  3. #include "Animation.h"
  4. #include "AnimationTarget.h"
  5. #include "Game.h"
  6. #include "Quaternion.h"
  7. namespace gameplay
  8. {
  9. AnimationClip::AnimationClip(const char* id, Animation* animation, unsigned long startTime, unsigned long endTime)
  10. : _id(id), _animation(animation), _startTime(startTime), _endTime(endTime), _duration(_endTime - _startTime), _repeatCount(1.0f),
  11. _activeDuration(_duration * _repeatCount), _speed(1.0f), _isPlaying(false), _timeStarted(0), _elapsedTime(0), _runningTime(0),
  12. _crossFadeToClip(NULL), _crossFadeStart(0), _crossFadeOutElapsed(0), _crossFadeOutDuration(0), _blendWeight(1.0f),
  13. _isFadingOutStarted(false), _isFadingOut(false), _isFadingIn(false), _beginListeners(NULL), _endListeners(NULL)
  14. {
  15. assert(0 <= startTime && startTime <= animation->_duration && 0 <= endTime && endTime <= animation->_duration);
  16. unsigned int channelCount = _animation->_channels.size();
  17. for (unsigned int i = 0; i < channelCount; i++)
  18. {
  19. _values.push_back(new AnimationValue(_animation->_channels[i]->_curve->getComponentCount()));
  20. }
  21. }
  22. AnimationClip::~AnimationClip()
  23. {
  24. std::vector<AnimationValue*>::iterator valueIter = _values.begin();
  25. while (valueIter != _values.end())
  26. {
  27. SAFE_DELETE(*valueIter);
  28. valueIter++;
  29. }
  30. _values.clear();
  31. SAFE_RELEASE(_crossFadeToClip);
  32. SAFE_DELETE(_beginListeners);
  33. SAFE_DELETE(_endListeners);
  34. }
  35. const char* AnimationClip::getID() const
  36. {
  37. return _id.c_str();
  38. }
  39. Animation* AnimationClip::getAnimation() const
  40. {
  41. return _animation;
  42. }
  43. unsigned long AnimationClip::getStartTime() const
  44. {
  45. return _startTime;
  46. }
  47. unsigned long AnimationClip::getEndTime() const
  48. {
  49. return _endTime;
  50. }
  51. unsigned long AnimationClip::getElaspedTime() const
  52. {
  53. return _elapsedTime;
  54. }
  55. void AnimationClip::setRepeatCount(float repeatCount)
  56. {
  57. assert(repeatCount == REPEAT_INDEFINITE || repeatCount > 0.0f);
  58. _repeatCount = repeatCount;
  59. if (repeatCount == REPEAT_INDEFINITE)
  60. {
  61. _activeDuration = _duration;
  62. }
  63. else
  64. {
  65. _activeDuration = _repeatCount * _duration;
  66. }
  67. }
  68. float AnimationClip::getRepeatCount() const
  69. {
  70. return _repeatCount;
  71. }
  72. void AnimationClip::setActiveDuration(unsigned long duration)
  73. {
  74. if (duration == REPEAT_INDEFINITE)
  75. {
  76. _repeatCount = REPEAT_INDEFINITE;
  77. _activeDuration = _duration;
  78. }
  79. else
  80. {
  81. _activeDuration = _duration;
  82. _repeatCount = (float) _activeDuration / (float) _duration;
  83. }
  84. }
  85. unsigned long AnimationClip::getActiveDuration() const
  86. {
  87. if (_repeatCount == REPEAT_INDEFINITE)
  88. return REPEAT_INDEFINITE;
  89. return _activeDuration;
  90. }
  91. void AnimationClip::setSpeed(float speed)
  92. {
  93. _speed = speed;
  94. }
  95. float AnimationClip::getSpeed() const
  96. {
  97. return _speed;
  98. }
  99. void AnimationClip::setBlendWeight(float blendWeight)
  100. {
  101. _blendWeight = blendWeight;
  102. }
  103. float AnimationClip::getBlendWeight() const
  104. {
  105. return _blendWeight;
  106. }
  107. bool AnimationClip::isPlaying() const
  108. {
  109. return _isPlaying;
  110. }
  111. void AnimationClip::play()
  112. {
  113. _animation->_controller->schedule(this);
  114. _timeStarted = Game::getGameTime();
  115. }
  116. void AnimationClip::stop()
  117. {
  118. _animation->_controller->unschedule(this);
  119. if (_isPlaying)
  120. {
  121. _isPlaying = false;
  122. onEnd();
  123. }
  124. }
  125. void AnimationClip::crossFade(AnimationClip* clip, unsigned long duration)
  126. {
  127. assert(clip);
  128. if (clip->_isPlaying && clip->_isFadingOut)
  129. {
  130. clip->_isFadingOut = false;
  131. clip->_crossFadeToClip->_isFadingIn = false;
  132. SAFE_RELEASE(clip->_crossFadeToClip);
  133. }
  134. // If I already have a clip I'm fading too.. release it.
  135. if (_crossFadeToClip)
  136. SAFE_RELEASE(_crossFadeToClip);
  137. // Assign the clip we're fading to, and increase its ref count.
  138. _crossFadeToClip = clip;
  139. _crossFadeToClip->addRef();
  140. // Set the fade in clip to fading in, and set the duration of the fade in.
  141. _crossFadeToClip->_isFadingIn = true;
  142. // Set this clip to fade out, and reset the elapsed time for the fade out.
  143. _isFadingOut = true;
  144. _crossFadeOutElapsed = 0;
  145. _crossFadeOutDuration = duration;
  146. _crossFadeStart = (Game::getGameTime() - _timeStarted);
  147. _isFadingOutStarted = true;
  148. if (!_isPlaying)
  149. play();
  150. _crossFadeToClip->play();
  151. }
  152. void AnimationClip::addBeginListener(AnimationClip::Listener* listener)
  153. {
  154. if (!_beginListeners)
  155. _beginListeners = new std::vector<Listener*>;
  156. _beginListeners->push_back(listener);
  157. }
  158. void AnimationClip::addEndListener(AnimationClip::Listener* listener)
  159. {
  160. if (!_endListeners)
  161. _endListeners = new std::vector<Listener*>;
  162. _endListeners->push_back(listener);
  163. }
  164. bool AnimationClip::update(unsigned long elapsedTime, std::list<AnimationTarget*>* activeTargets)
  165. {
  166. float speed = _speed;
  167. if (!_isPlaying)
  168. {
  169. onBegin();
  170. _elapsedTime = Game::getGameTime() - _timeStarted;
  171. _runningTime = _elapsedTime * speed;
  172. }
  173. else
  174. {
  175. // Update elapsed time.
  176. _elapsedTime += elapsedTime;
  177. _runningTime += elapsedTime * speed;
  178. }
  179. float percentComplete = 0.0f;
  180. // Check to see if clip is complete.
  181. if (_repeatCount != REPEAT_INDEFINITE && ((_speed >= 0 && _runningTime >= (long) _activeDuration) || (_speed < 0 && _runningTime <= 0)))
  182. {
  183. _isPlaying = false;
  184. if (_speed >= 0)
  185. {
  186. percentComplete = _activeDuration % _duration; // Get's the fractional part of the final repeat.
  187. if (percentComplete == 0.0f)
  188. percentComplete = _duration;
  189. }
  190. else
  191. {
  192. percentComplete = 0.0f; // If we are negative speed, the end value should be 0.
  193. }
  194. }
  195. else
  196. {
  197. // Gets portion/fraction of the repeat.
  198. percentComplete = (float) (_runningTime % _duration);
  199. }
  200. // Add back in start time, and divide by the total animation's duration to get the actual percentage complete
  201. percentComplete = (float)(_startTime + percentComplete) / (float) _animation->_duration;
  202. if (_isFadingOut)
  203. {
  204. if (_isFadingOutStarted) // Calculate elapsed time since the fade out begin.
  205. {
  206. _crossFadeOutElapsed = (_elapsedTime - _crossFadeStart) * speed;
  207. _isFadingOutStarted = false;
  208. }
  209. else
  210. {
  211. // continue tracking elapsed time.
  212. _crossFadeOutElapsed += elapsedTime * speed;
  213. }
  214. if (_crossFadeOutElapsed < _crossFadeOutDuration)
  215. {
  216. float tempBlendWeight = (float) (_crossFadeOutDuration - _crossFadeOutElapsed) / (float) _crossFadeOutDuration;
  217. _crossFadeToClip->_blendWeight = (1.0f - tempBlendWeight);
  218. // adjust the clip your blending to's weight to be a percentage of your current blend weight
  219. if (_isFadingIn)
  220. {
  221. _crossFadeToClip->_blendWeight *= _blendWeight;
  222. _blendWeight -= _crossFadeToClip->_blendWeight;
  223. }
  224. else
  225. {
  226. _blendWeight = tempBlendWeight;
  227. }
  228. }
  229. else
  230. { // Fade done.
  231. _crossFadeToClip->_blendWeight = 1.0f;
  232. if (_isFadingIn)
  233. _crossFadeToClip->_blendWeight *= _blendWeight;
  234. _crossFadeToClip->_isFadingIn = false;
  235. SAFE_RELEASE(_crossFadeToClip);
  236. _blendWeight = 0.0f;
  237. _isFadingOut = false;
  238. _isPlaying = false;
  239. }
  240. }
  241. // Evaluate this clip.
  242. Animation::Channel* channel = NULL;
  243. AnimationValue* value = NULL;
  244. AnimationTarget* target = NULL;
  245. unsigned int channelCount = _animation->_channels.size();
  246. for (unsigned int i = 0; i < channelCount; i++)
  247. {
  248. channel = _animation->_channels[i];
  249. target = channel->_target;
  250. value = _values[i];
  251. // If the target's _animationPropertyBitFlag is clear, we can assume that this is the first
  252. // animation channel to act on the target and we can add the target to the list of
  253. // active targets stored by the AnimationController.
  254. if (target->_animationPropertyBitFlag == 0x00)
  255. activeTargets->push_front(target);
  256. // Evaluate the point on Curve
  257. channel->_curve->evaluate(percentComplete, value->_value);
  258. // Set the animation value on the target property.
  259. target->setAnimationPropertyValue(channel->_propertyId, value, _blendWeight);
  260. }
  261. // When ended. Probably should move to it's own method so we can call it when the clip is ended early.
  262. if (!_isPlaying)
  263. {
  264. onEnd();
  265. // Notify end listeners if any.
  266. if (_endListeners)
  267. {
  268. std::vector<Listener*>::iterator listener = _endListeners->begin();
  269. while (listener != _endListeners->end())
  270. {
  271. (*listener)->animationEvent(this, Listener::END);
  272. listener++;
  273. }
  274. }
  275. }
  276. return !_isPlaying;
  277. }
  278. void AnimationClip::onBegin()
  279. {
  280. // Initialize animation to play.
  281. _isPlaying = true;
  282. _elapsedTime = 0;
  283. if (_speed > 0)
  284. {
  285. _runningTime = 0;
  286. }
  287. else
  288. {
  289. _runningTime = _activeDuration;
  290. }
  291. // Notify begin listeners.. if any.
  292. if (_beginListeners)
  293. {
  294. std::vector<Listener*>::iterator listener = _beginListeners->begin();
  295. while (listener != _beginListeners->end())
  296. {
  297. (*listener)->animationEvent(this, Listener::BEGIN);
  298. listener++;
  299. }
  300. }
  301. }
  302. void AnimationClip::onEnd()
  303. {
  304. _blendWeight = 1.0f;
  305. _timeStarted = 0;
  306. }
  307. }