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