Commit 3b62185f authored by Hixie's avatar Hixie

Simplify AnimationPerformance

AnimationPerformance had some logic for supporting multiple variables
that was hardly ever used. ValueAnimation, a subclass, has logic for
handling a single variable. I've removed the logic for handling
variables from AnimationPerformance in favour of most call sites instead
using ValueAnimation.
parent 347bd25c
...@@ -43,7 +43,7 @@ abstract class WatchableAnimationPerformance { ...@@ -43,7 +43,7 @@ abstract class WatchableAnimationPerformance {
void removeStatusListener(AnimationPerformanceStatusListener listener); void removeStatusListener(AnimationPerformanceStatusListener listener);
} }
/// A collection of values that animated based on a timeline /// A timeline that can be reversed and used to update [AnimatedVariable]s.
/// ///
/// For example, a performance may handle an animation of a menu opening by /// For example, a performance may handle an animation of a menu opening by
/// sliding and fading in (changing Y value and opacity) over .5 seconds. The /// sliding and fading in (changing Y value and opacity) over .5 seconds. The
...@@ -52,9 +52,10 @@ abstract class WatchableAnimationPerformance { ...@@ -52,9 +52,10 @@ abstract class WatchableAnimationPerformance {
/// [fling] the timeline causing a physics-based simulation to take over the /// [fling] the timeline causing a physics-based simulation to take over the
/// progression. /// progression.
class AnimationPerformance implements WatchableAnimationPerformance { class AnimationPerformance implements WatchableAnimationPerformance {
AnimationPerformance({ AnimatedVariable variable, this.duration }) : AnimationPerformance({ this.duration, double progress }) {
_variable = variable {
_timeline = new Timeline(_tick); _timeline = new Timeline(_tick);
if (progress != null)
_timeline.value = progress.clamp(0.0, 1.0);
} }
/// Returns a [WatchableAnimationPerformance] for this performance, /// Returns a [WatchableAnimationPerformance] for this performance,
...@@ -65,18 +66,14 @@ class AnimationPerformance implements WatchableAnimationPerformance { ...@@ -65,18 +66,14 @@ class AnimationPerformance implements WatchableAnimationPerformance {
/// The length of time this performance should last /// The length of time this performance should last
Duration duration; Duration duration;
/// The variable being updated by this performance
AnimatedVariable get variable => _variable;
void set variable(AnimatedVariable variable) { _variable = variable; }
AnimatedVariable _variable;
Timeline _timeline; Timeline _timeline;
Direction _direction; Direction _direction;
/// The direction used to select the current curve /// The direction used to select the current curve
/// ///
/// Curve direction is only reset when we hit the beginning or the end of the /// Curve direction is only reset when we hit the beginning or the end of the
/// timeline to avoid discontinuities in the value of the variable. /// timeline to avoid discontinuities in the value of any variables this
/// performance is used to animate.
Direction _curveDirection; Direction _curveDirection;
/// If non-null, animate with this timing instead of a linear timing /// If non-null, animate with this timing instead of a linear timing
...@@ -85,21 +82,6 @@ class AnimationPerformance implements WatchableAnimationPerformance { ...@@ -85,21 +82,6 @@ class AnimationPerformance implements WatchableAnimationPerformance {
/// If non-null, animate with this force instead of a zero-to-one timeline. /// If non-null, animate with this force instead of a zero-to-one timeline.
Force attachedForce; Force attachedForce;
/// Add a variable to this animation
///
/// If there are no attached variables, this variable becomes the value of
/// [variable]. Otherwise, all the variables are stored in an [AnimatedList].
void addVariable(AnimatedVariable newVariable) {
if (variable == null) {
variable = newVariable;
} else if (variable is AnimatedList) {
final AnimatedList variable = this.variable; // TODO(ianh): Remove this line when the analyzer is cleverer
variable.variables.add(newVariable);
} else {
variable = new AnimatedList([variable, newVariable]);
}
}
/// The progress of this performance along the timeline /// The progress of this performance along the timeline
/// ///
/// Note: Setting this value stops the current animation. /// Note: Setting this value stops the current animation.
...@@ -238,8 +220,10 @@ class AnimationPerformance implements WatchableAnimationPerformance { ...@@ -238,8 +220,10 @@ class AnimationPerformance implements WatchableAnimationPerformance {
void _tick(double t) { void _tick(double t) {
_updateCurveDirection(); _updateCurveDirection();
if (variable != null) didTick(t);
variable.setProgress(_curvedProgress, _curveDirection); }
void didTick(double t) {
_notifyListeners(); _notifyListeners();
_checkStatusChanged(); _checkStatusChanged();
} }
...@@ -247,11 +231,15 @@ class AnimationPerformance implements WatchableAnimationPerformance { ...@@ -247,11 +231,15 @@ class AnimationPerformance implements WatchableAnimationPerformance {
/// An animation performance with an animated variable with a concrete type /// An animation performance with an animated variable with a concrete type
class ValueAnimation<T> extends AnimationPerformance { class ValueAnimation<T> extends AnimationPerformance {
ValueAnimation({ AnimatedValue<T> variable, Duration duration }) : ValueAnimation({ this.variable, Duration duration, double progress }) :
super(variable: variable, duration: duration); super(duration: duration, progress: progress);
AnimatedValue<T> get variable => _variable as AnimatedValue<T>;
void set variable(AnimatedValue<T> v) { _variable = v; }
AnimatedValue<T> variable;
T get value => variable.value; T get value => variable.value;
void didTick(double t) {
if (variable != null)
variable.setProgress(_curvedProgress, _curveDirection);
super.didTick(t);
}
} }
...@@ -131,7 +131,7 @@ class _RenderCheckbox extends RenderToggleable { ...@@ -131,7 +131,7 @@ class _RenderCheckbox extends RenderToggleable {
..color = uncheckedColor; ..color = uncheckedColor;
// The rrect contracts slightly during the animation // The rrect contracts slightly during the animation
double inset = 2.0 - (position.value - _kMidpoint).abs() * 2.0; double inset = 2.0 - (position - _kMidpoint).abs() * 2.0;
sky.Rect rect = new sky.Rect.fromLTWH(offset.dx + inset, offset.dy + inset, sky.Rect rect = new sky.Rect.fromLTWH(offset.dx + inset, offset.dy + inset,
_kEdgeSize - inset, _kEdgeSize - inset); _kEdgeSize - inset, _kEdgeSize - inset);
sky.RRect rrect = new sky.RRect() sky.RRect rrect = new sky.RRect()
...@@ -142,19 +142,19 @@ class _RenderCheckbox extends RenderToggleable { ...@@ -142,19 +142,19 @@ class _RenderCheckbox extends RenderToggleable {
canvas.drawRRect(rrect, paint); canvas.drawRRect(rrect, paint);
// Radial gradient that changes size // Radial gradient that changes size
if (position.value > 0) { if (position > 0) {
paint.setStyle(sky.PaintingStyle.fill); paint.setStyle(sky.PaintingStyle.fill);
paint.setShader(new sky.Gradient.radial( paint.setShader(new sky.Gradient.radial(
new Point(_kEdgeSize / 2.0, _kEdgeSize / 2.0), new Point(_kEdgeSize / 2.0, _kEdgeSize / 2.0),
_kEdgeSize * (_kMidpoint - position.value) * 8.0, [ _kEdgeSize * (_kMidpoint - position) * 8.0, [
const sky.Color(0x00000000), const sky.Color(0x00000000),
uncheckedColor uncheckedColor
])); ]));
canvas.drawRRect(rrect, paint); canvas.drawRRect(rrect, paint);
} }
if (position.value > _kMidpoint) { if (position > _kMidpoint) {
double t = (position.value - _kMidpoint) / (1.0 - _kMidpoint); double t = (position - _kMidpoint) / (1.0 - _kMidpoint);
// Solid filled rrect // Solid filled rrect
paint.setStyle(sky.PaintingStyle.strokeAndFill); paint.setStyle(sky.PaintingStyle.strokeAndFill);
......
...@@ -30,11 +30,11 @@ class InkSplash { ...@@ -30,11 +30,11 @@ class InkSplash {
_radius = new AnimatedValue<double>( _radius = new AnimatedValue<double>(
_kSplashInitialSize, end: _targetRadius, curve: easeOut); _kSplashInitialSize, end: _targetRadius, curve: easeOut);
_performance = new AnimationPerformance() _performance = new ValueAnimation<double>(
..variable = _radius variable: _radius,
..duration = new Duration(milliseconds: (_targetRadius / _kSplashUnconfirmedVelocity).floor()) duration: new Duration(milliseconds: (_targetRadius / _kSplashUnconfirmedVelocity).floor())
..addListener(_handleRadiusChange) )..addListener(_handleRadiusChange)
..play(); ..play();
} }
final int pointer; final int pointer;
......
...@@ -35,11 +35,15 @@ abstract class ProgressIndicator extends StatefulComponent { ...@@ -35,11 +35,15 @@ abstract class ProgressIndicator extends StatefulComponent {
} }
class ProgressIndicatorState extends State<ProgressIndicator> { class ProgressIndicatorState extends State<ProgressIndicator> {
ValueAnimation<double> _performance;
void initState() { void initState() {
super.initState(); super.initState();
_performance = new AnimationPerformance() _performance = new ValueAnimation<double>(
..duration = const Duration(milliseconds: 1500) variable: new AnimatedValue<double>(0.0, end: 1.0, curve: ease),
..variable = new AnimatedValue<double>(0.0, end: 1.0, curve: ease); duration: const Duration(milliseconds: 1500)
);
_performance.addStatusListener((AnimationStatus status) { _performance.addStatusListener((AnimationStatus status) {
if (status == AnimationStatus.completed) if (status == AnimationStatus.completed)
_restartAnimation(); _restartAnimation();
...@@ -47,9 +51,6 @@ class ProgressIndicatorState extends State<ProgressIndicator> { ...@@ -47,9 +51,6 @@ class ProgressIndicatorState extends State<ProgressIndicator> {
_performance.play(); _performance.play();
} }
AnimationPerformance _performance;
double get _performanceValue => (_performance.variable as AnimatedValue<double>).value;
void _restartAnimation() { void _restartAnimation() {
_performance.progress = 0.0; _performance.progress = 0.0;
_performance.play(); _performance.play();
...@@ -57,13 +58,13 @@ class ProgressIndicatorState extends State<ProgressIndicator> { ...@@ -57,13 +58,13 @@ class ProgressIndicatorState extends State<ProgressIndicator> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
if (config.value != null) if (config.value != null)
return config._buildIndicator(context, _performanceValue); return config._buildIndicator(context, _performance.value);
return new BuilderTransition( return new BuilderTransition(
variables: [_performance.variable], variables: [_performance.variable],
performance: _performance.view, performance: _performance.view,
builder: (BuildContext context) { builder: (BuildContext context) {
return config._buildIndicator(context, _performanceValue); return config._buildIndicator(context, _performance.value);
} }
); );
} }
......
...@@ -97,9 +97,9 @@ class _RenderSwitch extends RenderToggleable { ...@@ -97,9 +97,9 @@ class _RenderSwitch extends RenderToggleable {
_radialReaction = new RadialReaction( _radialReaction = new RadialReaction(
center: new Point(_kSwitchSize.width / 2.0, _kSwitchSize.height / 2.0), center: new Point(_kSwitchSize.width / 2.0, _kSwitchSize.height / 2.0),
radius: _kReactionRadius, radius: _kReactionRadius,
startPosition: startLocation) startPosition: startLocation
..addListener(markNeedsPaint) )..addListener(markNeedsPaint)
..show(); ..show();
} }
Future _hideRadialReaction() async { Future _hideRadialReaction() async {
...@@ -140,10 +140,10 @@ class _RenderSwitch extends RenderToggleable { ...@@ -140,10 +140,10 @@ class _RenderSwitch extends RenderToggleable {
paint.drawLooper = builder.build(); paint.drawLooper = builder.build();
// The thumb contracts slightly during the animation // The thumb contracts slightly during the animation
double inset = 2.0 - (position.value - 0.5).abs() * 2.0; double inset = 2.0 - (position - 0.5).abs() * 2.0;
Point thumbPos = new Point(offset.dx + Point thumbPos = new Point(offset.dx +
_kTrackRadius + _kTrackRadius +
position.value * (_kTrackWidth - _kTrackRadius * 2), position * (_kTrackWidth - _kTrackRadius * 2),
offset.dy + _kSwitchHeight / 2.0); offset.dy + _kSwitchHeight / 2.0);
canvas.drawCircle(thumbPos, _kThumbRadius - inset, paint); canvas.drawCircle(thumbPos, _kThumbRadius - inset, paint);
} }
......
...@@ -30,16 +30,16 @@ class RadialReaction { ...@@ -30,16 +30,16 @@ class RadialReaction {
_outerOpacity = new AnimatedValue<double>(0.0, end: _kMaxOpacity, curve: easeOut); _outerOpacity = new AnimatedValue<double>(0.0, end: _kMaxOpacity, curve: easeOut);
_innerCenter = new AnimatedValue<Point>(startPosition, end: center, curve: easeOut); _innerCenter = new AnimatedValue<Point>(startPosition, end: center, curve: easeOut);
_innerRadius = new AnimatedValue<double>(0.0, end: radius, curve: easeOut); _innerRadius = new AnimatedValue<double>(0.0, end: radius, curve: easeOut);
_showPerformance = new AnimationPerformance() _showPerformance = new AnimationPerformance(duration: _kShowDuration)
..addVariable(_outerOpacity) ..addListener(() {
..addVariable(_innerCenter) _showPerformance.updateVariable(_outerOpacity);
..addVariable(_innerRadius) _showPerformance.updateVariable(_innerCenter);
..duration = _kShowDuration; _showPerformance.updateVariable(_innerRadius);
});
_fade = new AnimatedValue(1.0, end: 0.0, curve: easeIn); _fade = new ValueAnimation<double>(
_hidePerformance = new AnimationPerformance() variable: new AnimatedValue(1.0, end: 0.0, curve: easeIn),
..addVariable(_fade) duration: _kHideDuration
..duration =_kHideDuration; );
} }
/// The center of the circle in which the reaction occurs /// The center of the circle in which the reaction occurs
...@@ -55,8 +55,7 @@ class RadialReaction { ...@@ -55,8 +55,7 @@ class RadialReaction {
Future _showComplete; Future _showComplete;
AnimationPerformance _hidePerformance; ValueAnimation<double> _fade;
AnimatedValue<double> _fade;
/// Show the reaction /// Show the reaction
/// ///
...@@ -70,13 +69,13 @@ class RadialReaction { ...@@ -70,13 +69,13 @@ class RadialReaction {
/// Returns a future that resolves when the reaction is completely hidden. /// Returns a future that resolves when the reaction is completely hidden.
Future hide() async { Future hide() async {
await _showComplete; await _showComplete;
await _hidePerformance.forward(); await _fade.forward();
} }
/// Call listener whenever the visual appearance of the reaction changes /// Call listener whenever the visual appearance of the reaction changes
void addListener(Function listener) { void addListener(Function listener) {
_showPerformance.addListener(listener); _showPerformance.addListener(listener);
_hidePerformance.addListener(listener); _fade.addListener(listener);
} }
final Paint _outerPaint = new Paint(); final Paint _outerPaint = new Paint();
......
...@@ -24,13 +24,18 @@ abstract class RenderToggleable extends RenderConstrainedBox { ...@@ -24,13 +24,18 @@ abstract class RenderToggleable extends RenderConstrainedBox {
: _value = value, : _value = value,
_onChanged = onChanged, _onChanged = onChanged,
super(additionalConstraints: new BoxConstraints.tight(size)) { super(additionalConstraints: new BoxConstraints.tight(size)) {
_performance = new AnimationPerformance() _performance = new ValueAnimation<double>(
..variable = _position variable: new AnimatedValue<double>(0.0, end: 1.0, curve: easeIn, reverseCurve: easeOut),
..duration = _kToggleDuration duration: _kToggleDuration,
..progress = _value ? 1.0 : 0.0 progress: _value ? 1.0 : 0.0
..addListener(markNeedsPaint); )..addListener(markNeedsPaint);
} }
ValueAnimation<double> get performance => _performance;
ValueAnimation<double> _performance;
double get position => _performance.value;
void handleEvent(sky.Event event, BoxHitTestEntry entry) { void handleEvent(sky.Event event, BoxHitTestEntry entry) {
if (event.type == 'pointerdown') if (event.type == 'pointerdown')
_tap.addPointer(event); _tap.addPointer(event);
...@@ -68,15 +73,7 @@ abstract class RenderToggleable extends RenderConstrainedBox { ...@@ -68,15 +73,7 @@ abstract class RenderToggleable extends RenderConstrainedBox {
ValueChanged get onChanged => _onChanged; ValueChanged get onChanged => _onChanged;
ValueChanged _onChanged; ValueChanged _onChanged;
void set onChanged(ValueChanged onChanged) { void set onChanged(ValueChanged onChanged) {
_onChanged = onChanged; _onChanged = onChanged;
} }
AnimatedValue<double> get position => _position;
final AnimatedValue<double> _position =
new AnimatedValue<double>(0.0, end: 1.0, curve: easeIn, reverseCurve: easeOut);
AnimationPerformance get performance => _performance;
AnimationPerformance _performance;
} }
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