diff --git a/samples/RenderTest/ViewModels/AnimationsPageViewModel.cs b/samples/RenderTest/ViewModels/AnimationsPageViewModel.cs index b7f6086d0f..17eee547a1 100644 --- a/samples/RenderTest/ViewModels/AnimationsPageViewModel.cs +++ b/samples/RenderTest/ViewModels/AnimationsPageViewModel.cs @@ -17,14 +17,14 @@ namespace RenderTest.ViewModels { switch (Timing.GetGlobalPlayState()) { - case PlayState.Running: + case PlayState.Run: PlayStateText = "Resume all animations"; - Timing.SetGlobalPlayState(PlayState.Paused); + Timing.SetGlobalPlayState(PlayState.Pause); break; - case PlayState.Paused: + case PlayState.Pause: PlayStateText = "Pause all animations"; - Timing.SetGlobalPlayState(PlayState.Running); + Timing.SetGlobalPlayState(PlayState.Run); break; } } diff --git a/src/Avalonia.Animation/Animatable.cs b/src/Avalonia.Animation/Animatable.cs index 8359d22c51..f88c25fd0e 100644 --- a/src/Avalonia.Animation/Animatable.cs +++ b/src/Avalonia.Animation/Animatable.cs @@ -8,6 +8,8 @@ using System.Reactive.Linq; using Avalonia.Collections; using Avalonia.Animation.Transitions; using System.Collections.Generic; +using System.Threading; +using System.Collections.Concurrent; namespace Avalonia.Animation { @@ -22,29 +24,69 @@ namespace Avalonia.Animation public Animatable() { Transitions = new Transitions.Transitions(); + AnimatableTimer = Timing.AnimationStateTimer + .Select(p => + { + if (p == PlayState.Run + && this._playState == PlayState.Run) + return _animationTime++; + else + return _animationTime; + }) + .Publish() + .RefCount(); } /// - /// Defines the property. + /// The specific animations timer for this control. /// - public static readonly DirectProperty AnimationPlayStateProperty = + /// + public IObservable AnimatableTimer; + + internal void PrepareAnimatableForAnimation() + { + if (!_animationsInitialized) + { + + + _animationsInitialized = true; + } + } + + bool _animationsInitialized = false; + + // internal ConcurrentDictionary _animationStates; + + internal ulong _animationTime; + + // internal int _iterationTokenCounter; + + // internal uint GetIterationToken() + // { + // return (uint)Interlocked.Increment(ref _iterationTokenCounter); + // } + + /// + /// Defines the property. + /// + public static readonly DirectProperty PlayStateProperty = AvaloniaProperty.RegisterDirect( - nameof(AnimationPlayState), - o => o.AnimationPlayState, - (o, v) => o.AnimationPlayState = v); + nameof(PlayState), + o => o.PlayState, + (o, v) => o.PlayState = v); /// /// Gets or sets the state of the animation for this /// control. /// - public PlayState AnimationPlayState - { - get { return _animationPlayState; } - set { SetAndRaise(AnimationPlayStateProperty, ref _animationPlayState, value); } - + public PlayState PlayState + { + get { return _playState; } + set { SetAndRaise(PlayStateProperty, ref _playState, value); } + } - private PlayState _animationPlayState; + private PlayState _playState = PlayState.Run; /// /// Defines the property. diff --git a/src/Avalonia.Animation/Animation.cs b/src/Avalonia.Animation/Animation.cs index eb97093b06..c3a31d05fa 100644 --- a/src/Avalonia.Animation/Animation.cs +++ b/src/Avalonia.Animation/Animation.cs @@ -64,6 +64,8 @@ namespace Avalonia.Animation /// public IDisposable Apply(Animatable control, IObservable matchObs) { + control.PrepareAnimatableForAnimation(); + foreach (IKeyFrames keyframes in Children) { _subscription.Add(keyframes.Apply(this, control, matchObs)); diff --git a/src/Avalonia.Animation/Keyframes/KeyFrame.cs b/src/Avalonia.Animation/Keyframes/KeyFrame.cs index e4a8e59ab1..9a9f9ba940 100644 --- a/src/Avalonia.Animation/Keyframes/KeyFrame.cs +++ b/src/Avalonia.Animation/Keyframes/KeyFrame.cs @@ -13,7 +13,6 @@ namespace Avalonia.Animation.Keyframes public class KeyFrame { internal bool timeSpanSet, cueSet; - private TimeSpan _ktimeSpan; private Cue _kCue; diff --git a/src/Avalonia.Animation/Keyframes/KeyFrames.cs b/src/Avalonia.Animation/Keyframes/KeyFrames.cs index 34576beb7d..a6dee814c1 100644 --- a/src/Avalonia.Animation/Keyframes/KeyFrames.cs +++ b/src/Avalonia.Animation/Keyframes/KeyFrames.cs @@ -29,6 +29,7 @@ namespace Avalonia.Animation.Keyframes private bool IsVerfifiedAndConverted; + /// public virtual IDisposable Apply(Animation animation, Animatable control, IObservable obsMatch) { @@ -38,11 +39,12 @@ namespace Avalonia.Animation.Keyframes return obsMatch .Where(p => p == true) // Ignore triggers when global timers are paused. - .Where(p=> Timing.GetGlobalPlayState() != PlayState.Paused) + .Where(p=> Timing.GetGlobalPlayState() == PlayState.Run) .Subscribe(_ => { var interp = DoInterpolation(animation, control) .Select(p => (object)p); + control.Bind(Property, interp, BindingPriority.Animation); }); } diff --git a/src/Avalonia.Animation/PlayState.cs b/src/Avalonia.Animation/PlayState.cs index ae2890cce1..a76a680eb8 100644 --- a/src/Avalonia.Animation/PlayState.cs +++ b/src/Avalonia.Animation/PlayState.cs @@ -6,7 +6,7 @@ namespace Avalonia.Animation { public enum PlayState { - Running, - Paused + Run, + Pause } } diff --git a/src/Avalonia.Animation/Timing.cs b/src/Avalonia.Animation/Timing.cs index 0714b9e201..95fc0328c2 100644 --- a/src/Avalonia.Animation/Timing.cs +++ b/src/Avalonia.Animation/Timing.cs @@ -16,7 +16,7 @@ namespace Avalonia.Animation public static class Timing { static ulong _animationsFrameCount, _transitionsFrameCount; - static PlayState _globalState = PlayState.Running; + static PlayState _globalState = PlayState.Run; /// /// The number of frames per second. @@ -35,18 +35,10 @@ namespace Avalonia.Animation { var globalTimer = Observable.Interval(Tick, AvaloniaScheduler.Instance); - AnimationTimer = globalTimer + AnimationStateTimer = globalTimer .Select(_ => { - switch (_globalState) - { - case PlayState.Paused: - break; - default: - _animationsFrameCount ++; - break; - } - return _animationsFrameCount; + return _globalState; }) .Publish() .RefCount(); @@ -85,10 +77,7 @@ namespace Avalonia.Animation /// The parameter passed to a subsciber is the number of frames since the animation system was /// initialized. /// - /// - /// The animation timer. - /// - public static IObservable AnimationTimer + internal static IObservable AnimationStateTimer { get; } @@ -102,9 +91,6 @@ namespace Avalonia.Animation /// The parameter passed to a subsciber is the number of frames since the animation system was /// initialized. /// - /// - /// The animation timer. - /// public static IObservable TransitionsTimer { get; @@ -124,10 +110,10 @@ namespace Avalonia.Animation /// public static IObservable GetAnimationsTimer(Animatable control, TimeSpan duration, TimeSpan delay) { - var startTime = _animationsFrameCount; - var _duration = (ulong)(duration.Ticks/Tick.Ticks); + var startTime = control._animationTime; + var _duration = (ulong)(duration.Ticks / Tick.Ticks); var endTime = startTime + _duration; - return AnimationTimer + return control.AnimatableTimer .TakeWhile(x => x < endTime) .Select(x => (double)(x - startTime) / _duration) .StartWith(0.0)