Browse Source

Delegated the animation clock to the Animatable objects so that we can control their Play State individually.

pull/1461/head
Jumar Macato 9 years ago
parent
commit
99e9f9eed5
  1. 8
      samples/RenderTest/ViewModels/AnimationsPageViewModel.cs
  2. 64
      src/Avalonia.Animation/Animatable.cs
  3. 2
      src/Avalonia.Animation/Animation.cs
  4. 1
      src/Avalonia.Animation/Keyframes/KeyFrame.cs
  5. 4
      src/Avalonia.Animation/Keyframes/KeyFrames.cs
  6. 4
      src/Avalonia.Animation/PlayState.cs
  7. 28
      src/Avalonia.Animation/Timing.cs

8
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;
}
}

64
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();
}
/// <summary>
/// Defines the <see cref="AnimationPlayState"/> property.
/// The specific animations timer for this control.
/// </summary>
public static readonly DirectProperty<Animatable, PlayState> AnimationPlayStateProperty =
/// <returns></returns>
public IObservable<ulong> AnimatableTimer;
internal void PrepareAnimatableForAnimation()
{
if (!_animationsInitialized)
{
_animationsInitialized = true;
}
}
bool _animationsInitialized = false;
// internal ConcurrentDictionary<int, (int repeatCount, int direction)> _animationStates;
internal ulong _animationTime;
// internal int _iterationTokenCounter;
// internal uint GetIterationToken()
// {
// return (uint)Interlocked.Increment(ref _iterationTokenCounter);
// }
/// <summary>
/// Defines the <see cref="PlayState"/> property.
/// </summary>
public static readonly DirectProperty<Animatable, PlayState> PlayStateProperty =
AvaloniaProperty.RegisterDirect<Animatable, PlayState>(
nameof(AnimationPlayState),
o => o.AnimationPlayState,
(o, v) => o.AnimationPlayState = v);
nameof(PlayState),
o => o.PlayState,
(o, v) => o.PlayState = v);
/// <summary>
/// Gets or sets the state of the animation for this
/// control.
/// </summary>
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;
/// <summary>
/// Defines the <see cref="Transitions"/> property.

2
src/Avalonia.Animation/Animation.cs

@ -64,6 +64,8 @@ namespace Avalonia.Animation
/// <inheritdocs/>
public IDisposable Apply(Animatable control, IObservable<bool> matchObs)
{
control.PrepareAnimatableForAnimation();
foreach (IKeyFrames keyframes in Children)
{
_subscription.Add(keyframes.Apply(this, control, matchObs));

1
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;

4
src/Avalonia.Animation/Keyframes/KeyFrames.cs

@ -29,6 +29,7 @@ namespace Avalonia.Animation.Keyframes
private bool IsVerfifiedAndConverted;
/// <inheritdoc/>
public virtual IDisposable Apply(Animation animation, Animatable control, IObservable<bool> 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);
});
}

4
src/Avalonia.Animation/PlayState.cs

@ -6,7 +6,7 @@ namespace Avalonia.Animation
{
public enum PlayState
{
Running,
Paused
Run,
Pause
}
}

28
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;
/// <summary>
/// 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.
/// </remarks>
/// <value>
/// The animation timer.
/// </value>
public static IObservable<ulong> AnimationTimer
internal static IObservable<PlayState> 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.
/// </remarks>
/// <value>
/// The animation timer.
/// </value>
public static IObservable<ulong> TransitionsTimer
{
get;
@ -124,10 +110,10 @@ namespace Avalonia.Animation
/// </remarks>
public static IObservable<double> 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)

Loading…
Cancel
Save