xref: /third_party/skia/tools/viewer/AnimTimer.h (revision cb93a386)
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