aboutsummaryrefslogtreecommitdiffhomepage
path: root/gm
diff options
context:
space:
mode:
authorGravatar reed <reed@google.com>2015-02-02 12:55:02 -0800
committerGravatar Commit bot <commit-bot@chromium.org>2015-02-02 12:55:02 -0800
commit76113a9b7716748c70ea0ecf7aacbabe4cce5009 (patch)
tree57d91f56a717a0ffcb829b00c71e17195491753c /gm
parenta669bc7a7ae7580c5cd92067aeb95d09e64ea720 (diff)
add SkAnimTimer, SPACE = pause/resume, ESP = stop
Diffstat (limited to 'gm')
-rw-r--r--gm/SkAnimTimer.h139
-rw-r--r--gm/addarc.cpp5
-rw-r--r--gm/gm.cpp4
-rw-r--r--gm/gm.h6
4 files changed, 148 insertions, 6 deletions
diff --git a/gm/SkAnimTimer.h b/gm/SkAnimTimer.h
new file mode 100644
index 0000000000..725171a8fe
--- /dev/null
+++ b/gm/SkAnimTimer.h
@@ -0,0 +1,139 @@
+/*
+ * 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 "SkTime.h"
+
+#ifndef SkAnimTimer_DEFINED
+#define SkAnimTimer_DEFINED
+
+/**
+ * Class to track a "timer". It supports 3 states: stopped, paused, running.
+ *
+ * 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 SkAnimTimer {
+public:
+ enum State {
+ kStopped_State,
+ kPaused_State,
+ kRunning_State
+ };
+
+ /**
+ * Class begins in the "stopped" state.
+ */
+ SkAnimTimer() : fBaseTime(0), fCurrTime(0), fState(kStopped_State) {}
+
+ bool isStopped() const { return kStopped_State == fState; }
+ bool isRunning() const { return kRunning_State == fState; }
+ bool isPaused() const { return kPaused_State == fState; }
+
+ /**
+ * Stops the timer, and resets it, such that the next call to run or togglePauseResume
+ * will begin at time 0.
+ */
+ void stop() {
+ this->setState(kStopped_State);
+ }
+
+ /**
+ * If the timer is paused or stopped, it will resume (or start if it was stopped).
+ */
+ void run() {
+ this->setState(kRunning_State);
+ }
+
+ /**
+ * If the timer is stopped, this has no effect, else it toggles between paused and running.
+ */
+ void togglePauseResume() {
+ if (kRunning_State == fState) {
+ this->setState(kPaused_State);
+ } else {
+ this->setState(kRunning_State);
+ }
+ }
+
+ /**
+ * 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 == fState) {
+ fCurrTime = SkTime::GetMSecs();
+ }
+ }
+
+ /**
+ * Return the time in milliseconds the timer has been in the running state.
+ * Returns 0 if the timer is stopped.
+ */
+ SkMSec msec() const { return fCurrTime - fBaseTime; }
+
+ /**
+ * Return the time in seconds the timer has been in the running state.
+ * Returns 0 if the timer is stopped.
+ */
+ double secs() const {
+ return this->msec() * 0.001;
+ }
+
+ /**
+ * Return the time in seconds the timer has been in the running state,
+ * scaled by "speed" and (if not zero) mod by period.
+ * Returns 0 if the timer is stopped.
+ */
+ SkScalar scaled(SkScalar speed, SkScalar period = 0) const {
+ double value = this->secs() * speed;
+ if (period) {
+ value = ::fmod(value, SkScalarToDouble(period));
+ }
+ return SkDoubleToScalar(value);
+ }
+
+private:
+ SkMSec fBaseTime;
+ SkMSec fCurrTime;
+ State fState;
+
+ void setState(State newState) {
+ switch (newState) {
+ case kStopped_State:
+ fBaseTime = fCurrTime = 0;
+ fState = kStopped_State;
+ break;
+ case kPaused_State:
+ if (kRunning_State == fState) {
+ fState = kPaused_State;
+ } // else stay stopped or paused
+ break;
+ case kRunning_State:
+ switch (fState) {
+ case kStopped_State:
+ fBaseTime = fCurrTime = SkTime::GetMSecs();
+ break;
+ case kPaused_State: {// they want "resume"
+ SkMSec now = SkTime::GetMSecs();
+ fBaseTime += now - fCurrTime;
+ fCurrTime = now;
+ } break;
+ case kRunning_State:
+ break;
+ }
+ fState = kRunning_State;
+ break;
+ }
+ }
+};
+
+#endif
diff --git a/gm/addarc.cpp b/gm/addarc.cpp
index 1386cdd0e7..e6fad25772 100644
--- a/gm/addarc.cpp
+++ b/gm/addarc.cpp
@@ -6,6 +6,7 @@
*/
#include "gm.h"
+#include "SkAnimTimer.h"
#include "SkCanvas.h"
#include "SkRandom.h"
@@ -49,8 +50,8 @@ protected:
}
}
- bool onAnimatePulse(SkMSec curr, SkMSec prev) SK_OVERRIDE {
- fRotate = SkDoubleToScalar(fmod(curr * 0.001, 360));
+ bool onAnimate(const SkAnimTimer& timer) SK_OVERRIDE {
+ fRotate = timer.scaled(1, 360);
return true;
}
diff --git a/gm/gm.cpp b/gm/gm.cpp
index c8109a7e26..8d269d977d 100644
--- a/gm/gm.cpp
+++ b/gm/gm.cpp
@@ -51,8 +51,8 @@ void GM::setBGColor(SkColor color) {
fBGColor = color;
}
-bool GM::animatePulse(SkMSec curr, SkMSec prev) {
- return this->onAnimatePulse(curr, prev);
+bool GM::animate(const SkAnimTimer& timer) {
+ return this->onAnimate(timer);
}
/////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/gm/gm.h b/gm/gm.h
index c7dca6d276..e263528f90 100644
--- a/gm/gm.h
+++ b/gm/gm.h
@@ -16,6 +16,8 @@
#include "SkTRegistry.h"
#include "sk_tool_utils.h"
+class SkAnimTimer;
+
#if SK_SUPPORT_GPU
#include "GrContext.h"
#endif
@@ -92,7 +94,7 @@ namespace skiagm {
fStarterMatrix = matrix;
}
- bool animatePulse(SkMSec curr, SkMSec prev);
+ bool animate(const SkAnimTimer&);
protected:
/** draws a standard message that the GM is only intended to be used with the GPU.*/
@@ -103,7 +105,7 @@ namespace skiagm {
virtual SkISize onISize() = 0;
virtual SkString onShortName() = 0;
- virtual bool onAnimatePulse(SkMSec curr, SkMSec prev) { return false; }
+ virtual bool onAnimate(const SkAnimTimer&) { return false; }
virtual SkMatrix onGetInitialTransform() const { return SkMatrix::I(); }
private: