1 /* 2 * Copyright 2015 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "include/core/SkScalar.h" 9 #include "include/core/SkTime.h" 10 11 #ifndef AnimTimer_DEFINED 12 #define AnimTimer_DEFINED 13 14 /** 15 * Class to track a "timer". It supports 3 states: stopped, paused, and running. 16 * Playback speed is variable. 17 * 18 * The caller must call updateTime() to resync with the clock (typically just before 19 * using the timer). Forcing the caller to do this ensures that the timer's return values 20 * are consistent if called repeatedly, as they only reflect the time since the last 21 * calle to updateTimer(). 22 */ 23 class AnimTimer { 24 public: 25 /** 26 * Class begins in the "stopped" state. 27 */ AnimTimer()28 AnimTimer() {} 29 30 enum State { kStopped_State, kPaused_State, kRunning_State }; 31 state()32 State state() const { return fState; } 33 nanos()34 double nanos() const { return fElapsedNanos; } 35 36 /** 37 * Control the rate at which time advances. 38 */ getSpeed()39 float getSpeed() const { return fSpeed; } setSpeed(float speed)40 void setSpeed(float speed) { fSpeed = speed; } 41 42 /** 43 * If the timer is paused or stopped, it will resume (or start if it was stopped). 44 */ run()45 void run() { 46 switch (this->state()) { 47 case kStopped_State: 48 fPreviousNanos = SkTime::GetNSecs(); 49 fElapsedNanos = 0; 50 break; 51 case kPaused_State: // they want "resume" 52 fPreviousNanos = SkTime::GetNSecs(); 53 break; 54 case kRunning_State: break; 55 } 56 fState = kRunning_State; 57 } 58 pause()59 void pause() { 60 if (kRunning_State == this->state()) { 61 fState = kPaused_State; 62 } // else stay stopped or paused 63 } 64 65 /** 66 * If the timer is stopped, start running, else it toggles between paused and running. 67 */ togglePauseResume()68 void togglePauseResume() { 69 if (kRunning_State == this->state()) { 70 this->pause(); 71 } else { 72 this->run(); 73 } 74 } 75 76 /** 77 * Call this each time you want to sample the clock for the timer. This is NOT done 78 * automatically, so that repeated calls to msec() or secs() will always return the 79 * same value. 80 * 81 * This may safely be called with the timer in any state. 82 */ updateTime()83 void updateTime() { 84 if (kRunning_State == this->state()) { 85 double now = SkTime::GetNSecs(); 86 fElapsedNanos += (now - fPreviousNanos) * fSpeed; 87 fPreviousNanos = now; 88 } 89 } 90 91 private: 92 double fPreviousNanos = 0; 93 double fElapsedNanos = 0; 94 float fSpeed = 1; 95 State fState = kStopped_State; 96 }; 97 98 #endif 99