skia2/tools/viewer/AnimTimer.h
Hal Canary 41248071ac tools: separate TimeUtils from AnimTimer
gm, slides, and samples no longer need to know about the implementation
details of AnimTimer.

This
    virtual bool onAnimate(const AnimTimer&);
becomes this:
    virtual bool onAnimate(double /*nanoseconds*/);
which is much easier to reason about.

AnimTimer itself is now part of viewer.

Change-Id: Ib70bf7a0798b1991f25204ae84f70463cdbeb358
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/226838
Reviewed-by: Ben Wagner <bungeman@google.com>
Commit-Queue: Hal Canary <halcanary@google.com>
2019-07-12 15:05:01 +00:00

99 lines
2.6 KiB
C++

/*
* Copyright 2015 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "include/core/SkScalar.h"
#include "include/core/SkTime.h"
#ifndef AnimTimer_DEFINED
#define AnimTimer_DEFINED
/**
* Class to track a "timer". It supports 3 states: stopped, paused, and running.
* Playback speed is variable.
*
* The caller must call updateTime() to resync with the clock (typically just before
* using the timer). Forcing the caller to do this ensures that the timer's return values
* are consistent if called repeatedly, as they only reflect the time since the last
* calle to updateTimer().
*/
class AnimTimer {
public:
/**
* Class begins in the "stopped" state.
*/
AnimTimer() {}
enum State { kStopped_State, kPaused_State, kRunning_State };
State state() const { return fState; }
double nanos() const { return fElapsedNanos; }
/**
* Control the rate at which time advances.
*/
float getSpeed() const { return fSpeed; }
void setSpeed(float speed) { fSpeed = speed; }
/**
* If the timer is paused or stopped, it will resume (or start if it was stopped).
*/
void run() {
switch (this->state()) {
case kStopped_State:
fPreviousNanos = SkTime::GetNSecs();
fElapsedNanos = 0;
break;
case kPaused_State: // they want "resume"
fPreviousNanos = SkTime::GetNSecs();
break;
case kRunning_State: break;
}
fState = kRunning_State;
}
void pause() {
if (kRunning_State == this->state()) {
fState = kPaused_State;
} // else stay stopped or paused
}
/**
* If the timer is stopped, start running, else it toggles between paused and running.
*/
void togglePauseResume() {
if (kRunning_State == this->state()) {
this->pause();
} else {
this->run();
}
}
/**
* Call this each time you want to sample the clock for the timer. This is NOT done
* automatically, so that repeated calls to msec() or secs() will always return the
* same value.
*
* This may safely be called with the timer in any state.
*/
void updateTime() {
if (kRunning_State == this->state()) {
double now = SkTime::GetNSecs();
fElapsedNanos += (now - fPreviousNanos) * fSpeed;
fPreviousNanos = now;
}
}
private:
double fPreviousNanos = 0;
double fElapsedNanos = 0;
float fSpeed = 1;
State fState = kStopped_State;
};
#endif