soui 5.0.0.1
Soui5 Doc
 
Loading...
Searching...
No Matches
SValueAnimator.cpp
1#include <souistd.h>
3#include <animation/SInterpolatorImpl.h>
4#include <helper/STime.h>
5
6SNSBEGIN
7
9 : mContainer(NULL)
10{
11 sDurationScale = 1.0f;
12 mStartTime = -1;
13
15
16 mSeekFraction = -1;
17
19 mOverallFraction = 0.f;
20
21 mCurrentFraction = 0.f;
22
23 mLastFrameTime = -1;
24
25 mFirstFrameTime = -1;
26
27 mRunning = false;
28
29 mStarted = false;
30
32
33 mInitialized = false;
34
36
37 mDuration = 300;
38
39 mStartDelay = 0;
40
41 mRepeatCount = 0;
42
43 mRepeatMode = RESTART;
45}
46
48{
49 removeAnimationCallback();
50}
51
52void SValueAnimator::addAnimationCallback()
53{
54 SASSERT(mContainer);
55 mContainer->RegisterTimelineHandler(this);
56}
57
58void SValueAnimator::copy(const IValueAnimator *pSrc)
59{
60 SValueAnimator *pSrc2 = sobj_cast<SValueAnimator>(pSrc);
61 mDuration = pSrc2->mDuration;
62 mStartDelay = pSrc2->mStartDelay;
64 mRepeatMode = pSrc2->mRepeatMode;
66 m_strName = pSrc2->m_strName;
67 m_nID = pSrc2->m_nID;
68}
69
70void SValueAnimator::removeAnimationCallback()
71{
72 if (mContainer)
73 {
74 mContainer->UnregisterTimelineHandler(this);
75 mContainer = NULL;
76 }
77}
78
80{
81 doAnimationFrame(STime::GetCurrentTimeMs());
82}
83
84void SValueAnimator::animateValue(float fraction)
85{
86 fraction = mInterpolator->getInterpolation(fraction);
87 mCurrentFraction = fraction;
88 onEvaluateValue(fraction);
89 size_t numListeners = mUpdateListeners.GetCount();
90 for (size_t i = 0; i < numListeners; ++i)
91 {
92 mUpdateListeners[i]->onAnimationUpdate(this);
93 }
94}
95
100
101bool SValueAnimator::doAnimationFrame(uint64_t frameTime)
102{
103 if (mStartTime < 0)
104 {
105 // First frame. If there is start delay, start delay count down will happen *after* this
106 // frame.
107 mStartTime = mReversing ? frameTime : frameTime + (long)(mStartDelay * sDurationScale);
108 }
109
110 if (!mRunning)
111 {
112 // If not running, that means the animation is in the start delay phase of a forward
113 // running animation. In the case of reversing, we want to run start delay in the end.
114 if (mStartTime > frameTime && mSeekFraction == -1)
115 {
116 // This is when no seek fraction is set during start delay. If developers change the
117 // seek fraction during the delay, animation will start from the seeked position
118 // right away.
119 return false;
120 }
121 else
122 {
123 // If mRunning is not set by now, that means non-zero start delay,
124 // no seeking, not reversing. At this point, start delay has passed.
125 mRunning = true;
126 startAnimation();
127 }
128 }
129
130 if (mLastFrameTime < 0)
131 {
132 if (mSeekFraction >= 0)
133 {
134 long seekTime = (long)(getScaledDuration() * mSeekFraction);
135 mStartTime = frameTime - seekTime;
136 mSeekFraction = -1;
137 }
138 mStartTimeCommitted = false; // allow start time to be compensated for jank
139 }
140 mLastFrameTime = frameTime;
141 // The frame time might be before the start time during the first frame of
142 // an animation. The "current time" must always be on or after the start
143 // time to avoid animating frames at negative time intervals. In practice, this
144 // is very rare and only happens when seeking backwards.
145 uint64_t currentTime = smax(frameTime, mStartTime);
146 bool finished = animateBasedOnTime(currentTime);
147
148 if (finished)
149 {
150 endAnimation();
151 }
152 return finished;
153}
154
155bool SValueAnimator::isInitialized()
156{
157 return mInitialized;
158}
159
160void SValueAnimator::skipToEndValue(bool inReverse)
161{
162 float endFraction = inReverse ? 0.f : 1.f;
163 if (mRepeatCount % 2 == 1 && mRepeatMode == REVERSE)
164 {
165 // This would end on fraction = 0
166 endFraction = 0.f;
167 }
168 animateValue(endFraction);
169}
170
171void SValueAnimator::animateBasedOnPlayTime(long currentPlayTime, long lastPlayTime, bool inReverse)
172{
173 if (currentPlayTime < 0 || lastPlayTime < 0)
174 {
175 return; // error
176 }
177 // Check whether repeat callback is needed only when repeat count is non-zero
178 if (mRepeatCount > 0)
179 {
180 int iteration = (int)(currentPlayTime / mDuration);
181 int lastIteration = (int)(lastPlayTime / mDuration);
182
183 // Clamp iteration to [0, mRepeatCount]
184 iteration = smin(iteration, mRepeatCount);
185 lastIteration = smin(lastIteration, mRepeatCount);
186
187 if (iteration != lastIteration)
188 {
189 size_t numListeners = mListeners.GetCount();
190 for (size_t i = 0; i < numListeners; ++i)
191 {
192 mListeners[i]->onAnimationRepeat(this);
193 }
194 }
195 }
196
197 if (mRepeatCount != INFINITE && currentPlayTime >= (mRepeatCount + 1) * mDuration)
198 {
199 skipToEndValue(inReverse);
200 }
201 else
202 {
203 // Find the current fraction:
204 float fraction = currentPlayTime / (float)mDuration;
205 fraction = getCurrentIterationFraction(fraction, inReverse);
206 animateValue(fraction);
207 }
208}
209
210bool SValueAnimator::animateBasedOnTime(uint64_t currentTime)
211{
212 bool done = false;
213 if (mRunning)
214 {
215 long scaledDuration = getScaledDuration();
216 float fraction = scaledDuration > 0 ? (float)(currentTime - mStartTime) / scaledDuration : 1.f;
217 float lastFraction = mOverallFraction;
218 bool newIteration = (int)fraction > (int)lastFraction;
219 bool lastIterationFinished = (fraction >= mRepeatCount + 1) && (mRepeatCount != INFINITE);
220 if (scaledDuration == 0)
221 {
222 // 0 duration animator, ignore the repeat count and skip to the end
223 done = true;
224 }
225 else if (newIteration && !lastIterationFinished)
226 {
227 // Time to repeat
228 SArray<IAnimatorListener *> tmpListeners = mListeners;
229 for (UINT i = 0; i < tmpListeners.GetCount(); i++)
230 {
231 tmpListeners[i]->onAnimationRepeat(this);
232 }
233 }
234 else if (lastIterationFinished)
235 {
236 done = true;
237 }
238 mOverallFraction = clampFraction(fraction);
239 float currentIterationFraction = getCurrentIterationFraction(mOverallFraction, mReversing);
240 animateValue(currentIterationFraction);
241 }
242 return done;
243}
244
246{
248 {
249 mStartTimeCommitted = true;
250 uint64_t adjustment = frameTime - mLastFrameTime;
251 if (adjustment > 0)
252 {
253 mStartTime += adjustment;
254 }
255 }
256}
257
258bool SValueAnimator::isPulsingInternal()
259{
260 return mLastFrameTime >= 0;
261}
262
263void SValueAnimator::startAnimation()
264{
266 mRunning = true;
267 if (mSeekFraction >= 0)
268 {
270 }
271 else
272 {
273 mOverallFraction = 0.f;
274 }
275 notifyStartListeners();
276}
277
278void SValueAnimator::endAnimation()
279{
281 {
282 return;
283 }
284 removeAnimationCallback();
285
287 bool notify = (mStarted || mRunning);
288 if (notify && !mRunning)
289 {
290 // If it's not yet running, then start listeners weren't called. Call them now.
291 notifyStartListeners();
292 }
293 mRunning = false;
294 mStarted = false;
295 mStartListenersCalled = false;
296 mLastFrameTime = -1;
297 mFirstFrameTime = -1;
298 mStartTime = -1;
299 AddRef();
300 if (notify)
301 {
302 SArray<IAnimatorListener *> tmpListeners = mListeners;
303 size_t numListeners = tmpListeners.GetCount();
304 for (size_t i = 0; i < numListeners; ++i)
305 {
306 tmpListeners[i]->onAnimationEnd(this);
307 }
308 }
309 mReversing = false;
310 Release();
311}
312
313bool SValueAnimator::canReverse()
314{
315 return true;
316}
317
319{
320 if (isPulsingInternal())
321 {
322 uint64_t currentTime = STime::GetCurrentTimeMs();
323 uint64_t currentPlayTime = currentTime - mStartTime;
324 uint64_t timeLeft = getScaledDuration() - currentPlayTime;
325 mStartTime = currentTime - timeLeft;
326 mStartTimeCommitted = true; // do not allow start time to be compensated for jank
328 }
329 else if (mStarted)
330 {
332 end();
333 }
334 else
335 {
336 start(true);
337 }
338}
339
341{
342 return mStarted;
343}
344
346{
347 return mRunning;
348}
349
351{
352 if (!mStarted)
353 return;
354 if (!mRunning)
355 {
356 // Special case if the animation has not yet started; get it ready for ending
357 startAnimation();
358 }
359 animateValue(shouldPlayBackward(mRepeatCount, mReversing) ? 0.f : 1.f);
360 endAnimation();
361}
362
363void SValueAnimator::start(ITimelineHandlersMgr *pContainer)
364{
365 mContainer = pContainer;
366 start(false);
367}
368
369void SValueAnimator::start(bool playBackwards)
370{
371 SASSERT(mInterpolator);
372 mReversing = playBackwards;
373 // Special case: reversing from seek-to-0 should act as if not seeked at all.
374 if (playBackwards && mSeekFraction != -1 && mSeekFraction != 0)
375 {
376 if (mRepeatCount == INFINITE)
377 {
378 // Calculate the fraction of the current iteration.
379 float fraction = (float)(mSeekFraction - floor(mSeekFraction));
380 mSeekFraction = 1 - fraction;
381 }
382 else
383 {
385 }
386 }
387 mStarted = true;
388 mRunning = false;
390 // Resets mLastFrameTime when start() is called, so that if the animation was running,
391 // calling start() would put the animation in the
392 // started-but-not-yet-reached-the-first-frame phase.
393 mLastFrameTime = -1;
394 mFirstFrameTime = -1;
395 mStartTime = -1;
396 addAnimationCallback();
397
398 if (mStartDelay == 0 || mSeekFraction >= 0 || mReversing)
399 {
400 // If there's no start delay, init the animation and notify start listeners right away
401 // to be consistent with the previous behavior. Otherwise, postpone this until the first
402 // frame after the start delay.
403 startAnimation();
404 if (mSeekFraction == -1)
405 {
406 // No seek, start at play time 0. Note that the reason we are not using fraction 0
407 // is because for animations with 0 duration, we want to be consistent with pre-N
408 // behavior: skip to the value immediately.
410 }
411 else
412 {
414 }
415 }
416}
417
418void SValueAnimator::notifyStartListeners()
419{
420 AddRef();
421 SArray<IAnimatorListener *> tmpListeners = mListeners;
422 size_t numListeners = tmpListeners.GetCount();
423 for (size_t i = 0; i < numListeners; ++i)
424 {
425 tmpListeners[i]->onAnimationStart(this);
426 }
428 Release();
429}
430
431void SValueAnimator::removeListener(IAnimatorListener *p)
432{
433 int iFind = mListeners.Find(p);
434 if (iFind != -1)
435 {
436 mListeners.RemoveAt(iFind);
437 }
438}
439
440void SValueAnimator::addListener(IAnimatorListener *p)
441{
442 mListeners.Add(p);
443}
444
446{
447 return mInterpolator;
448}
449
450void SValueAnimator::setInterpolator(IInterpolator *value)
451{
452 mInterpolator = value;
453}
454
455void SValueAnimator::removeUpdateListener(IAnimatorUpdateListener *listener)
456{
457 int iFind = mUpdateListeners.Find(listener);
458 if (iFind != -1)
459 mUpdateListeners.RemoveAt(iFind);
460}
461
466
467void SValueAnimator::addUpdateListener(IAnimatorUpdateListener *listener)
468{
469 mUpdateListeners.Add(listener);
470}
471
473{
474 return mRepeatMode;
475}
476
477void SValueAnimator::setRepeatMode(RepeatMode value)
478{
479 mRepeatMode = value;
480}
481
483{
484 return mRepeatCount;
485}
486
488{
489 mRepeatCount = value;
490}
491
492void SValueAnimator::setStartDelay(long startDelay)
493{
494 // Clamp start delay to non-negative range.
495 if (startDelay < 0)
496 {
497 startDelay = 0;
498 }
499 mStartDelay = startDelay;
500}
501
503{
504 return mStartDelay;
505}
506
508{
509 if (!mInitialized || (!mStarted && mSeekFraction < 0))
510 {
511 return 0;
512 }
513 if (mSeekFraction >= 0)
514 {
515 return (long)(mDuration * mSeekFraction);
516 }
518}
519
520bool SValueAnimator::shouldPlayBackward(int iteration, bool inReverse)
521{
522 if (iteration > 0 && mRepeatMode == REVERSE && (iteration < (mRepeatCount + 1) || mRepeatCount == -1))
523 {
524 // if we were seeked to some other iteration in a reversing animator,
525 // figure out the correct direction to start playing based on the iteration
526 if (inReverse)
527 {
528 return (iteration % 2) == 0;
529 }
530 else
531 {
532 return (iteration % 2) != 0;
533 }
534 }
535 else
536 {
537 return inReverse;
538 }
539}
540
541float SValueAnimator::clampFraction(float fraction)
542{
543 if (fraction < 0)
544 {
545 fraction = 0;
546 }
547 else if (mRepeatCount != INFINITE)
548 {
549 fraction = smin(fraction, mRepeatCount + 1);
550 }
551 return fraction;
552}
553
554float SValueAnimator::getCurrentIterationFraction(float fraction, bool inReverse)
555{
556 fraction = clampFraction(fraction);
557 int iteration = getCurrentIteration(fraction);
558 float currentFraction = fraction - iteration;
559 return shouldPlayBackward(iteration, inReverse) ? 1.f - currentFraction : currentFraction;
560}
561
562int SValueAnimator::getCurrentIteration(float fraction)
563{
564 fraction = clampFraction(fraction);
565 // If the overall fraction is a positive integer, we consider the current iteration to be
566 // complete. In other words, the fraction for the current iteration would be 1, and the
567 // current iteration would be overall fraction - 1.
568 double iteration = floor(fraction);
569 if (fraction == iteration && fraction > 0)
570 {
571 iteration--;
572 }
573 return (int)iteration;
574}
575
577{
578 fraction = clampFraction(fraction);
579 mStartTimeCommitted = true; // do not allow start time to be compensated for jank
580 if (isPulsingInternal())
581 {
582 long seekTime = (long)(getScaledDuration() * fraction);
583 uint64_t currentTime = STime::GetCurrentTimeMs();
584 // Only modify the start time when the animation is running. Seek fraction will ensure
585 // non-running animations skip to the correct start time.
586 mStartTime = currentTime - seekTime;
587 }
588 else
589 {
590 // If the animation loop hasn't started, or during start delay, the startTime will be
591 // adjusted once the delay has passed based on seek fraction.
592 mSeekFraction = fraction;
593 }
594 mOverallFraction = fraction;
595 float currentIterationFraction = getCurrentIterationFraction(fraction, mReversing);
596 animateValue(currentIterationFraction);
597}
598
600{
601 float fraction = mDuration > 0 ? (float)playTime / mDuration : 1;
602 setCurrentFraction(fraction);
603}
604
606{
607 if (mRepeatCount == -1)
608 {
609 return 100000; // todo: DURATION_INFINITE;
610 }
611 else
612 {
613 return mStartDelay + (mDuration * (mRepeatCount + 1));
614 }
615}
616
618{
619 return mDuration;
620}
621
622long SValueAnimator::getScaledDuration()
623{
624 return (long)(mDuration * sDurationScale);
625}
626
628{
629 if (duration >= 0)
630 {
631 mDuration = duration;
632 }
633}
634
635IValueAnimator *SValueAnimator::clone(THIS) const
636{
638 pRet->copy(this);
639 return pRet;
640}
641
642//////////////////////////////////////////////////////////////////////////
643
644HRESULT SColorAnimator::OnAttrFrom(const SStringW &strValue, BOOL bLoading)
645{
646 COLORREF crStart = GETCOLOR(strValue);
647 mValueEvaluator.setStart(crStart);
648 return S_FALSE;
649}
650HRESULT SColorAnimator::OnAttrTo(const SStringW &strValue, BOOL bLoading)
651{
652 COLORREF crEnd = GETCOLOR(strValue);
653 mValueEvaluator.setEnd(crEnd);
654 return S_FALSE;
655}
656
657//////////////////////////////////////////////////////////////////////////
662
664{
665 SPOSITION pos = m_lstAnimator.GetStartPosition();
666 while (pos)
667 {
668 IValueAnimator *ani = m_lstAnimator.GetNextKey(pos);
669 ani->removeListener(this);
670 ani->Release();
671 }
672 m_lstAnimator.RemoveAll();
673}
674
675BOOL SAnimatorGroup::AddAnimator(IValueAnimator *ani)
676{
677 AnimatorStateMap::CPair *it = m_lstAnimator.Lookup(ani);
678 if (it)
679 return FALSE;
680
681 AniState state = idle;
682 if (ani->isRunning())
683 state = running;
684 else if (ani->isStarted())
685 state = started;
686 else
687 state = idle;
688 m_lstAnimator[ani] = state;
689 ani->addListener(this);
690 ani->AddRef();
691 return TRUE;
692}
693
694BOOL SAnimatorGroup::RemoveAnimator(IValueAnimator *ani)
695{
696 if (!m_lstAnimator.RemoveKey(ani))
697 return FALSE;
698 ani->removeListener(this);
699 ani->Release();
700 return TRUE;
701}
702
703void SAnimatorGroup::onAnimationStart(THIS_ IValueAnimator *pAnimator)
704{
705 AnimatorStateMap::CPair *it = m_lstAnimator.Lookup(pAnimator);
706 if (!it)
707 {
708 SSLOGW() << "onAnimationStart error, animator is not found!";
709 return;
710 }
711 it->m_value = running;
712}
713
714void SAnimatorGroup::onAnimationEnd(THIS_ IValueAnimator *pAnimator)
715{
716 AnimatorStateMap::CPair *it = m_lstAnimator.Lookup(pAnimator);
717 if (!it)
718 {
719 SSLOGW() << "onAnimationStart error, animator is not found!";
720 return;
721 }
722 it->m_value = idle;
723 bool bAllStop = true;
724 SPOSITION pos = m_lstAnimator.GetStartPosition();
725 while (pos)
726 {
727 AniState state = m_lstAnimator.GetNextValue(pos);
728 if (state != idle)
729 {
730 bAllStop = false;
731 break;
732 }
733 }
734
735 if (bAllStop && m_listener)
736 {
737 m_listener->OnAnimatorGroupEnd(this);
738 }
739}
740
741void SAnimatorGroup::SetListener(THIS_ IAnimatorGroupListerer *listener)
742{
743 m_listener = listener;
744}
745
746SNSEND
Provides a simple timing engine for running animations which calculate animated values and set them o...
void onAnimationStart(IValueAnimator *pAnimator)
Called when an animation starts.
AniState
Enumeration of animation states.
AnimatorStateMap m_lstAnimator
Map of animators and their states.
SAnimatorGroup()
Constructor.
void onAnimationEnd(IValueAnimator *pAnimator)
Called when an animation ends.
IAnimatorGroupListerer * m_listener
Listener for the animator group.
void SetListener(IAnimatorGroupListerer *listener) OVERRIDE
Sets the listener for the animator group.
BOOL AddAnimator(IValueAnimator *ani) OVERRIDE
Adds an animator to the group.
BOOL RemoveAnimator(IValueAnimator *ani) OVERRIDE
Removes an animator from the group.
~SAnimatorGroup()
Destructor.
virtual IValueAnimator * CreateValueAnimatorByName(LPCWSTR pszName) const
Create a value animator by name.
Definition SApp.cpp:659
HRESULT OnAttrTo(const SStringW &strValue, BOOL bLoading)
Handles the "valueTo" attribute.
HRESULT OnAttrFrom(const SStringW &strValue, BOOL bLoading)
Handles the "valueFrom" attribute.
An interpolator where the rate of change is constant.
LPCWSTR GetObjectClass() SCONST OVERRIDE
Definition Sobject.hpp:211
static SApplication * getSingletonPtr(void)
Definition SSingleton.h:73
A class representing an ASCII string.
Definition sstringw.h:96
static uint64_t GetCurrentTimeMs()
获取当前时间的毫秒数
Definition stime.cpp:189
int getRepeatCount() SCONST OVERRIDE
Defines how many times the animation should repeat.
SAutoRefPtr< IInterpolator > mInterpolator
The time interpolator to be used.
ITimelineHandlersMgr * mContainer
The container managing the timeline handlers.
void setRepeatCount(int value) OVERRIDE
Sets how many times the animation should be repeated.
void addUpdateListener(IAnimatorUpdateListener *listener) OVERRIDE
Adds a listener to the set of listeners that are sent update events through the life of an animation.
float mCurrentFraction
Tracks current elapsed/eased fraction, for querying in getAnimatedFraction().
void commitAnimationFrame(long frameTime) OVERRIDE
Applies an adjustment to the animation to compensate for jank between when the animation first ran an...
BOOL isStarted() SCONST OVERRIDE
Checks if the animation has been started.
bool mStarted
Additional playing state to indicate whether an animator has been start()'d, whether or not there is ...
void setInterpolator(IInterpolator *value) OVERRIDE
Sets the time interpolator used in calculating the elapsed fraction of this animation.
void setStartDelay(long startDelay) OVERRIDE
Sets the amount of time, in milliseconds, to delay starting the animation after start() is called.
void setRepeatMode(RepeatMode value) OVERRIDE
Defines what this animation should do when it reaches the end.
bool mStartListenersCalled
Tracks whether we've notified listeners of the onAnimationStart() event.
uint64_t mLastFrameTime
Tracks the time (in milliseconds) when the last frame arrived.
long getTotalDuration() SCONST OVERRIDE
Gets the total duration of the animation, including any repetitions.
bool mAnimationEndRequested
Flag that tracks whether animation has been requested to end.
float mSeekFraction
Set when setCurrentPlayTime() is called.
void setDuration(long duration) OVERRIDE
Sets the length of the animation.
void setCurrentPlayTime(long playTime) OVERRIDE
Sets the position of the animation to the specified point in time.
void reverse() OVERRIDE
Plays the SValueAnimator in reverse.
void setCurrentFraction(float fraction) OVERRIDE
Sets the position of the animation to the specified fraction.
bool mReversing
Flag to indicate whether this animator is playing in reverse mode.
IInterpolator * getInterpolator() SCONST OVERRIDE
Returns the timing interpolator that this SValueAnimator uses.
float getAnimatedFraction() SCONST OVERRIDE
Returns the current animation fraction.
uint64_t mStartTime
The first time that the animation's animateFrame() method is called.
void end() OVERRIDE
Ends the animation.
uint64_t mFirstFrameTime
Tracks the time (in milliseconds) when the first frame arrived.
BOOL isRunning() SCONST OVERRIDE
Checks if the animation is running.
bool mRunning
Additional playing state to indicate whether an animator has been start()'d.
~SValueAnimator()
Destructor.
long mStartDelay
The amount of time in milliseconds to delay starting the animation after start() is called.
RepeatMode getRepeatMode() SCONST OVERRIDE
Defines what this animation should do when it reaches the end.
SValueAnimator()
Creates a new SValueAnimator object.
IValueAnimator * clone() SCONST OVERRIDE
Creates a clone of the current animation.
void addListener(IAnimatorListener *p) OVERRIDE
Adds an animator listener.
void copy(const IValueAnimator *pSrc) OVERRIDE
Copies the properties of another animation to this animation.
SArray< IAnimatorUpdateListener * > mUpdateListeners
The set of listeners to be sent update events through the life of an animation.
float mOverallFraction
Tracks the overall fraction of the animation, ranging from 0 to mRepeatCount + 1.
void removeListener(IAnimatorListener *p) OVERRIDE
Removes an animator listener.
long getStartDelay() SCONST OVERRIDE
Gets the amount of time, in milliseconds, to delay starting the animation after start() is called.
float sDurationScale
Scaling factor for the duration.
long getCurrentPlayTime() OVERRIDE
Gets the current position of the animation in time.
int mRepeatCount
The number of times the animation will repeat.
RepeatMode mRepeatMode
The type of repetition that will occur when repeatMode is nonzero.
long mDuration
How long the animation should last in milliseconds.
void removeUpdateListener(IAnimatorUpdateListener *listener) OVERRIDE
Removes a listener from the set listening to frame updates for this animation.
void removeAllUpdateListeners() OVERRIDE
Removes all listeners from the set listening to frame updates for this animation.
void OnNextFrame() OVERRIDE
Handles the next frame of the animation.
bool mInitialized
Flag that denotes whether the animation is set up and ready to go.
long getDuration() SCONST OVERRIDE
Gets the length of the animation.
bool mStartTimeCommitted
Flag indicating whether the start time has been firmly committed.
TypeEvaluator< COLORREF > mValueEvaluator