From db191e96bdeb79724ba4fe2b5043e11ee37848fe Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Sat, 3 Oct 2015 10:55:25 -0700 Subject: [PATCH] Switch scheduler over to Duration This patch prepares us to switch to using integers when handing off the animation time from the engine to the framework. --- examples/rendering/spinning_flex.dart | 6 +++--- examples/widgets/spinning_mixed.dart | 6 +++--- .../lib/src/animation/animated_simulation.dart | 14 ++++++-------- packages/flutter/lib/src/animation/scheduler.dart | 8 +++++--- packages/flutter/lib/src/rendering/binding.dart | 2 +- packages/flutter/lib/src/widgets/binding.dart | 2 +- packages/flutter_sprites/lib/sprite_box.dart | 9 +++++---- packages/unit/test/animation/scheduler_test.dart | 8 ++++---- 8 files changed, 28 insertions(+), 27 deletions(-) diff --git a/examples/rendering/spinning_flex.dart b/examples/rendering/spinning_flex.dart index db2055ca236..1e72aac95a6 100644 --- a/examples/rendering/spinning_flex.dart +++ b/examples/rendering/spinning_flex.dart @@ -9,7 +9,7 @@ import 'package:sky/rendering.dart'; import 'solid_color_box.dart'; -double timeBase; +Duration timeBase; RenderTransform transformBox; void main() { @@ -34,10 +34,10 @@ void main() { scheduler.addPersistentFrameCallback(rotate); } -void rotate(double timeStamp) { +void rotate(Duration timeStamp) { if (timeBase == null) timeBase = timeStamp; - double delta = (timeStamp - timeBase) / 1000; // radians + double delta = (timeStamp - timeBase).inMicroseconds.toDouble() / Duration.MICROSECONDS_PER_SECOND; // radians transformBox.setIdentity(); transformBox.translate(transformBox.size.width / 2.0, transformBox.size.height / 2.0); diff --git a/examples/widgets/spinning_mixed.dart b/examples/widgets/spinning_mixed.dart index 9317390a996..f44b0e0acde 100644 --- a/examples/widgets/spinning_mixed.dart +++ b/examples/widgets/spinning_mixed.dart @@ -54,13 +54,13 @@ Widget builder() { ); } -double timeBase; +Duration timeBase; RenderTransform transformBox; -void rotate(double timeStamp) { +void rotate(Duration timeStamp) { if (timeBase == null) timeBase = timeStamp; - double delta = (timeStamp - timeBase) / 1000; // radians + double delta = (timeStamp - timeBase).inMicroseconds.toDouble() / Duration.MICROSECONDS_PER_SECOND; // radians transformBox.setIdentity(); transformBox.translate(transformBox.size.width / 2.0, transformBox.size.height / 2.0); diff --git a/packages/flutter/lib/src/animation/animated_simulation.dart b/packages/flutter/lib/src/animation/animated_simulation.dart index 0710dfc6d25..6c2f8afb227 100644 --- a/packages/flutter/lib/src/animation/animated_simulation.dart +++ b/packages/flutter/lib/src/animation/animated_simulation.dart @@ -7,10 +7,7 @@ import 'dart:async'; import 'package:newton/newton.dart'; import 'package:sky/src/animation/scheduler.dart'; -const double _kSecondsPerMillisecond = 1000.0; - -// TODO(abarth): Change from double to Duration. -typedef _TickerCallback(double timeStamp); +typedef _TickerCallback(Duration timeStamp); /// Calls its callback once per animation frame class Ticker { @@ -56,7 +53,7 @@ class Ticker { /// Whether this ticker has scheduled a call to onTick bool get isTicking => _completer != null; - void _tick(double timeStamp) { + void _tick(Duration timeStamp) { assert(isTicking); assert(_animationId != null); _animationId = null; @@ -86,7 +83,7 @@ class AnimatedSimulation { Ticker _ticker; Simulation _simulation; - double _startTime; + Duration _startTime; double _value = 0.0; /// The current value of the simulation @@ -119,11 +116,12 @@ class AnimatedSimulation { /// Whether this object is currently ticking a simulation bool get isAnimating => _ticker.isTicking; - void _tick(double timeStamp) { + void _tick(Duration timeStamp) { if (_startTime == null) _startTime = timeStamp; - double timeInSeconds = (timeStamp - _startTime) / _kSecondsPerMillisecond; + double timeInMicroseconds = (timeStamp - _startTime).inMicroseconds.toDouble(); + double timeInSeconds = timeInMicroseconds / Duration.MICROSECONDS_PER_SECOND; _value = _simulation.x(timeInSeconds); final bool isLastTick = _simulation.isDone(timeInSeconds); diff --git a/packages/flutter/lib/src/animation/scheduler.dart b/packages/flutter/lib/src/animation/scheduler.dart index 999ba890082..bfa585e0f3a 100644 --- a/packages/flutter/lib/src/animation/scheduler.dart +++ b/packages/flutter/lib/src/animation/scheduler.dart @@ -14,7 +14,7 @@ double timeDilation = 1.0; /// scheduler's epoch. Use timeStamp to determine how far to advance animation /// timelines so that all the animations in the system are synchronized to a /// common time base. -typedef void SchedulerCallback(double timeStamp); +typedef void SchedulerCallback(Duration timeStamp); /// Schedules callbacks to run in concert with the engine's animation system class Scheduler { @@ -35,8 +35,10 @@ class Scheduler { /// This function first calls all the callbacks registered by /// [requestAnimationFrame] and then calls all the callbacks registered by /// [addPersistentFrameCallback], which typically drive the rendering pipeline. - void beginFrame(double timeStamp) { - timeStamp /= timeDilation; + void beginFrame(double timeStampMS) { + timeStampMS /= timeDilation; + + Duration timeStamp = new Duration(microseconds: (timeStampMS * Duration.MICROSECONDS_PER_MILLISECOND).round()); _haveScheduledVisualUpdate = false; diff --git a/packages/flutter/lib/src/rendering/binding.dart b/packages/flutter/lib/src/rendering/binding.dart index 59bf21b5c8a..bf9e31ad12f 100644 --- a/packages/flutter/lib/src/rendering/binding.dart +++ b/packages/flutter/lib/src/rendering/binding.dart @@ -78,7 +78,7 @@ class FlutterBinding extends HitTestTarget { } /// Pump the rendering pipeline to generate a frame for the given time stamp - void beginFrame(double timeStamp) { + void beginFrame(Duration timeStamp) { RenderObject.flushLayout(); _renderView.updateCompositingBits(); RenderObject.flushPaint(); diff --git a/packages/flutter/lib/src/widgets/binding.dart b/packages/flutter/lib/src/widgets/binding.dart index 792c6a161a0..59056dfd4f8 100644 --- a/packages/flutter/lib/src/widgets/binding.dart +++ b/packages/flutter/lib/src/widgets/binding.dart @@ -35,7 +35,7 @@ class WidgetFlutterBinding extends FlutterBinding { ); } - void beginFrame(double timeStamp) { + void beginFrame(Duration timeStamp) { buildDirtyElements(); super.beginFrame(timeStamp); Element.finalizeTree(); diff --git a/packages/flutter_sprites/lib/sprite_box.dart b/packages/flutter_sprites/lib/sprite_box.dart index 07e6d317d0a..3abf3be04c7 100644 --- a/packages/flutter_sprites/lib/sprite_box.dart +++ b/packages/flutter_sprites/lib/sprite_box.dart @@ -47,7 +47,7 @@ class SpriteBox extends RenderBox { } // Tracking of frame rate and updates - double _lastTimeStamp; + Duration _lastTimeStamp; double _frameRate = 0.0; double get frameRate => _frameRate; @@ -349,13 +349,14 @@ class SpriteBox extends RenderBox { scheduler.requestAnimationFrame(_tick); } - void _tick(double timeStamp) { + void _tick(Duration timeStamp) { if (!attached) return; // Calculate delta and frame rate - if (_lastTimeStamp == null) _lastTimeStamp = timeStamp; - double delta = (timeStamp - _lastTimeStamp) / 1000; + if (_lastTimeStamp == null) + _lastTimeStamp = timeStamp; + double delta = (timeStamp - _lastTimeStamp).inMicroseconds.toDouble() / Duration.MICROSECONDS_PER_SECOND; _lastTimeStamp = timeStamp; _frameRate = 1.0/delta; diff --git a/packages/unit/test/animation/scheduler_test.dart b/packages/unit/test/animation/scheduler_test.dart index 380de02bb3e..62f9379c3da 100644 --- a/packages/unit/test/animation/scheduler_test.dart +++ b/packages/unit/test/animation/scheduler_test.dart @@ -8,18 +8,18 @@ void main() { bool firstCallbackRan = false; bool secondCallbackRan = false; - void firstCallback(double timeStamp) { + void firstCallback(Duration timeStamp) { expect(firstCallbackRan, isFalse); expect(secondCallbackRan, isFalse); - expect(timeStamp, equals(16.0)); + expect(timeStamp.inMilliseconds, equals(16)); firstCallbackRan = true; scheduler.cancelAnimationFrame(secondId); } - void secondCallback(double timeStamp) { + void secondCallback(Duration timeStamp) { expect(firstCallbackRan, isTrue); expect(secondCallbackRan, isFalse); - expect(timeStamp, equals(16.0)); + expect(timeStamp.inMilliseconds, equals(16)); secondCallbackRan = true; }