Commit 5cb00100 authored by Adam Barth's avatar Adam Barth

Remove AnimatedSimulation

This patch folds the functionality from AnimatedSimulation into Timeline.
parent 49aba0cc
...@@ -7,7 +7,6 @@ ...@@ -7,7 +7,6 @@
/// This library depends only on core Dart libraries and the `newton` package. /// This library depends only on core Dart libraries and the `newton` package.
library animation; library animation;
export 'src/animation/animated_simulation.dart';
export 'src/animation/animated_value.dart'; export 'src/animation/animated_value.dart';
export 'src/animation/animation_performance.dart'; export 'src/animation/animation_performance.dart';
export 'src/animation/clamped_simulation.dart'; export 'src/animation/clamped_simulation.dart';
...@@ -15,4 +14,5 @@ export 'src/animation/curves.dart'; ...@@ -15,4 +14,5 @@ export 'src/animation/curves.dart';
export 'src/animation/forces.dart'; export 'src/animation/forces.dart';
export 'src/animation/scheduler.dart'; export 'src/animation/scheduler.dart';
export 'src/animation/scroll_behavior.dart'; export 'src/animation/scroll_behavior.dart';
export 'src/animation/timeline.dart'; export 'src/animation/simulation_stepper.dart';
export 'src/animation/ticker.dart';
...@@ -6,7 +6,7 @@ import 'dart:async'; ...@@ -6,7 +6,7 @@ import 'dart:async';
import 'package:sky/src/animation/animated_value.dart'; import 'package:sky/src/animation/animated_value.dart';
import 'package:sky/src/animation/forces.dart'; import 'package:sky/src/animation/forces.dart';
import 'package:sky/src/animation/timeline.dart'; import 'package:sky/src/animation/simulation_stepper.dart';
/// The status of an animation /// The status of an animation
enum AnimationStatus { enum AnimationStatus {
...@@ -53,7 +53,7 @@ abstract class WatchableAnimationPerformance { ...@@ -53,7 +53,7 @@ abstract class WatchableAnimationPerformance {
/// progression. /// progression.
class AnimationPerformance implements WatchableAnimationPerformance { class AnimationPerformance implements WatchableAnimationPerformance {
AnimationPerformance({ this.duration, double progress }) { AnimationPerformance({ this.duration, double progress }) {
_timeline = new Timeline(_tick); _timeline = new SimulationStepper(_tick);
if (progress != null) if (progress != null)
_timeline.value = progress.clamp(0.0, 1.0); _timeline.value = progress.clamp(0.0, 1.0);
} }
...@@ -66,7 +66,7 @@ class AnimationPerformance implements WatchableAnimationPerformance { ...@@ -66,7 +66,7 @@ class AnimationPerformance implements WatchableAnimationPerformance {
/// The length of time this performance should last /// The length of time this performance should last
Duration duration; Duration duration;
Timeline _timeline; SimulationStepper _timeline;
Direction _direction; Direction _direction;
/// The direction used to select the current curve /// The direction used to select the current curve
...@@ -159,7 +159,7 @@ class AnimationPerformance implements WatchableAnimationPerformance { ...@@ -159,7 +159,7 @@ class AnimationPerformance implements WatchableAnimationPerformance {
if (force == null) if (force == null)
force = kDefaultSpringForce; force = kDefaultSpringForce;
_direction = velocity < 0.0 ? Direction.reverse : Direction.forward; _direction = velocity < 0.0 ? Direction.reverse : Direction.forward;
return _timeline.fling(force.release(progress, velocity)); return _timeline.animateWith(force.release(progress, velocity));
} }
final List<AnimationPerformanceListener> _listeners = new List<AnimationPerformanceListener>(); final List<AnimationPerformanceListener> _listeners = new List<AnimationPerformanceListener>();
......
...@@ -5,23 +5,26 @@ ...@@ -5,23 +5,26 @@
import 'dart:async'; import 'dart:async';
import 'package:newton/newton.dart'; import 'package:newton/newton.dart';
import 'package:sky/src/animation/curves.dart';
import 'package:sky/src/animation/animated_value.dart'; import 'package:sky/src/animation/animated_value.dart';
import 'package:sky/src/animation/animated_simulation.dart'; import 'package:sky/src/animation/curves.dart';
import 'package:sky/src/animation/ticker.dart';
/// A simulation that linearly varies from [begin] to [end] over [duration] /// A simulation that varies from [begin] to [end] over [duration] using [curve]
///
/// This class is an adaptor between the Simulation interface and the
/// AnimatedValue interface.
class _TweenSimulation extends Simulation { class _TweenSimulation extends Simulation {
final double _durationInSeconds;
final AnimatedValue<double> _tween;
_TweenSimulation(double begin, double end, Duration duration, Curve curve) _TweenSimulation(double begin, double end, Duration duration, Curve curve)
: _durationInSeconds = duration.inMicroseconds / Duration.MICROSECONDS_PER_SECOND, : _durationInSeconds = duration.inMicroseconds.toDouble() / Duration.MICROSECONDS_PER_SECOND,
_tween = new AnimatedValue<double>(begin, end: end, curve: curve) { _tween = new AnimatedValue<double>(begin, end: end, curve: curve) {
assert(_durationInSeconds > 0.0); assert(_durationInSeconds > 0.0);
assert(begin != null); assert(begin != null);
assert(end != null); assert(end != null);
} }
final double _durationInSeconds;
final AnimatedValue<double> _tween;
double x(double timeInSeconds) { double x(double timeInSeconds) {
assert(timeInSeconds >= 0.0); assert(timeInSeconds >= 0.0);
final double t = (timeInSeconds / _durationInSeconds).clamp(0.0, 1.0); final double t = (timeInSeconds / _durationInSeconds).clamp(0.0, 1.0);
...@@ -34,24 +37,30 @@ class _TweenSimulation extends Simulation { ...@@ -34,24 +37,30 @@ class _TweenSimulation extends Simulation {
bool isDone(double timeInSeconds) => timeInSeconds > _durationInSeconds; bool isDone(double timeInSeconds) => timeInSeconds > _durationInSeconds;
} }
/// A timeline for an animation typedef TimelineCallback(double value);
class Timeline {
Timeline(Function onTick) { /// Steps a simulation one per frame
_animation = new AnimatedSimulation(onTick); class SimulationStepper {
SimulationStepper(TimelineCallback onTick) : _onTick = onTick {
_ticker = new Ticker(_tick);
} }
AnimatedSimulation _animation; final TimelineCallback _onTick;
Ticker _ticker;
Simulation _simulation;
/// The current value of the timeline /// The current value of the timeline
double get value => _animation.value; double get value => _value;
double _value = 0.0;
void set value(double newValue) { void set value(double newValue) {
assert(newValue != null); assert(newValue != null);
assert(!isAnimating); assert(!isAnimating);
_animation.value = newValue; _value = newValue;
_onTick(_value);
} }
/// Whether the timeline is currently animating /// Whether the timeline is currently animating
bool get isAnimating => _animation.isAnimating; bool get isAnimating => _ticker.isTicking;
/// Animate value of the timeline to the given target over the given duration /// Animate value of the timeline to the given target over the given duration
/// ///
...@@ -59,18 +68,38 @@ class Timeline { ...@@ -59,18 +68,38 @@ class Timeline {
/// typically when the timeline arives at the target value. /// typically when the timeline arives at the target value.
Future animateTo(double target, { Duration duration, Curve curve: linear }) { Future animateTo(double target, { Duration duration, Curve curve: linear }) {
assert(duration > Duration.ZERO); assert(duration > Duration.ZERO);
assert(!_animation.isAnimating); assert(!isAnimating);
return _animation.start(new _TweenSimulation(value, target, duration, curve)); return _start(new _TweenSimulation(value, target, duration, curve));
}
/// Gives the given simulation control over the timeline
Future animateWith(Simulation simulation) {
stop();
return _start(simulation);
}
/// Start ticking the given simulation once per frame
///
/// Returns a future that resolves when the simulation stops ticking.
Future _start(Simulation simulation) {
assert(simulation != null);
assert(!isAnimating);
_simulation = simulation;
_value = simulation.x(0.0);
return _ticker.start();
} }
/// Stop animating the timeline /// Stop animating the timeline
void stop() { void stop() {
_animation.stop(); _simulation = null;
_ticker.stop();
} }
/// Gives the given simulation control over the timeline void _tick(Duration elapsed) {
Future fling(Simulation simulation) { double elapsedInSeconds = elapsed.inMicroseconds.toDouble() / Duration.MICROSECONDS_PER_SECOND;
stop(); _value = _simulation.x(elapsedInSeconds);
return _animation.start(simulation); if (_simulation.isDone(elapsedInSeconds))
stop();
_onTick(_value);
} }
} }
...@@ -4,17 +4,16 @@ ...@@ -4,17 +4,16 @@
import 'dart:async'; import 'dart:async';
import 'package:newton/newton.dart';
import 'package:sky/src/animation/scheduler.dart'; import 'package:sky/src/animation/scheduler.dart';
typedef _TickerCallback(Duration elapsed); typedef TickerCallback(Duration elapsed);
/// Calls its callback once per animation frame /// Calls its callback once per animation frame
class Ticker { class Ticker {
/// Constructs a ticker that will call onTick once per frame while running /// Constructs a ticker that will call onTick once per frame while running
Ticker(_TickerCallback onTick) : _onTick = onTick; Ticker(TickerCallback onTick) : _onTick = onTick;
final _TickerCallback _onTick; final TickerCallback _onTick;
Completer _completer; Completer _completer;
int _animationId; int _animationId;
...@@ -45,7 +44,7 @@ class Ticker { ...@@ -45,7 +44,7 @@ class Ticker {
_animationId = null; _animationId = null;
} }
// We take the _completer into a local variable so that !isTicking // We take the _completer into a local variable so that isTicking is false
// when we actually complete the future (isTicking uses _completer // when we actually complete the future (isTicking uses _completer
// to determine its state). // to determine its state).
Completer localCompleter = _completer; Completer localCompleter = _completer;
...@@ -78,57 +77,3 @@ class Ticker { ...@@ -78,57 +77,3 @@ class Ticker {
_animationId = scheduler.requestAnimationFrame(_tick); _animationId = scheduler.requestAnimationFrame(_tick);
} }
} }
/// Ticks a simulation once per frame
class AnimatedSimulation {
AnimatedSimulation(Function onTick) : _onTick = onTick {
_ticker = new Ticker(_tick);
}
final Function _onTick;
Ticker _ticker;
Simulation _simulation;
double _value = 0.0;
/// The current value of the simulation
double get value => _value;
void set value(double newValue) {
assert(!_ticker.isTicking);
_value = newValue;
_onTick(_value);
}
/// Start ticking the given simulation once per frame
///
/// Returns a future that resolves when the simulation stops ticking.
Future start(Simulation simulation) {
assert(simulation != null);
assert(!_ticker.isTicking);
_simulation = simulation;
_value = simulation.x(0.0);
return _ticker.start();
}
/// Stop ticking the current simulation
void stop() {
_simulation = null;
_ticker.stop();
}
/// Whether this object is currently ticking a simulation
bool get isAnimating => _ticker.isTicking;
void _tick(Duration elapsed) {
double elapsedInSeconds = elapsed.inMicroseconds.toDouble() / Duration.MICROSECONDS_PER_SECOND;
_value = _simulation.x(elapsedInSeconds);
if (_simulation.isDone(elapsedInSeconds))
stop();
_onTick(_value);
}
}
...@@ -51,10 +51,10 @@ abstract class ScrollableState<T extends Scrollable> extends State<T> { ...@@ -51,10 +51,10 @@ abstract class ScrollableState<T extends Scrollable> extends State<T> {
super.initState(); super.initState();
if (config.initialScrollOffset is double) if (config.initialScrollOffset is double)
_scrollOffset = config.initialScrollOffset; _scrollOffset = config.initialScrollOffset;
_animation = new Timeline(_setScrollOffset); _animation = new SimulationStepper(_setScrollOffset);
} }
Timeline _animation; SimulationStepper _animation;
double _scrollOffset = 0.0; double _scrollOffset = 0.0;
double get scrollOffset => _scrollOffset; double get scrollOffset => _scrollOffset;
...@@ -151,7 +151,7 @@ abstract class ScrollableState<T extends Scrollable> extends State<T> { ...@@ -151,7 +151,7 @@ abstract class ScrollableState<T extends Scrollable> extends State<T> {
_createSnapSimulation(velocity) ?? _createFlingSimulation(velocity ?? 0.0); _createSnapSimulation(velocity) ?? _createFlingSimulation(velocity ?? 0.0);
if (simulation == null) if (simulation == null)
return new Future.value(); return new Future.value();
return _animation.fling(simulation); return _animation.animateWith(simulation);
} }
void dispose() { void dispose() {
......
...@@ -13,7 +13,6 @@ import 'package:sky/painting.dart'; ...@@ -13,7 +13,6 @@ import 'package:sky/painting.dart';
import 'package:sky/rendering.dart'; import 'package:sky/rendering.dart';
import 'package:sky/src/widgets/basic.dart'; import 'package:sky/src/widgets/basic.dart';
import 'package:sky/src/widgets/framework.dart'; import 'package:sky/src/widgets/framework.dart';
import 'package:sky/src/widgets/gesture_detector.dart';
import 'package:sky/src/widgets/icon.dart'; import 'package:sky/src/widgets/icon.dart';
import 'package:sky/src/widgets/ink_well.dart'; import 'package:sky/src/widgets/ink_well.dart';
import 'package:sky/src/widgets/scrollable.dart'; import 'package:sky/src/widgets/scrollable.dart';
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment