// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
using System.Diagnostics;
using System.Linq;
using System.Reactive.Linq;
using Avalonia.Data;
using Avalonia.Threading;
namespace Avalonia.Animation
{
///
/// Provides global timing functions for animations.
///
public static class Timing
{
static ulong _transitionsFrameCount;
static PlayState _globalState = PlayState.Run;
///
/// The number of frames per second.
///
public const int FramesPerSecond = 60;
///
/// The time span of each frame.
///
internal static readonly TimeSpan FrameTick = TimeSpan.FromSeconds(1.0 / FramesPerSecond);
///
/// Initializes static members of the class.
///
static Timing()
{
var globalTimer = Observable.Interval(FrameTick, AvaloniaScheduler.Instance);
AnimationStateTimer = globalTimer
.Select(_ =>
{
return _globalState;
})
.Publish()
.RefCount();
TransitionsTimer = globalTimer
.Select(p => _transitionsFrameCount++)
.Publish()
.RefCount();
}
///
/// Sets the animation play state for all animations
///
public static void SetGlobalPlayState(PlayState playState)
{
Dispatcher.UIThread.VerifyAccess();
_globalState = playState;
}
///
/// Gets the animation play state for all animations
///
public static PlayState GetGlobalPlayState()
{
Dispatcher.UIThread.VerifyAccess();
return _globalState;
}
///
/// Gets the animation timer.
///
///
/// The animation timer triggers usually at 60 times per second or as
/// defined in .
/// The parameter passed to a subsciber is the current playstate of the animation.
///
internal static IObservable AnimationStateTimer
{
get;
}
///
/// Gets the transitions timer.
///
///
/// The transitions timer increments usually 60 times per second as
/// defined in .
/// The parameter passed to a subsciber is the number of frames since the animation system was
/// initialized.
///
public static IObservable TransitionsTimer
{
get;
}
///
/// Gets a timer that fires every frame for the specified duration with delay.
///
///
/// An observable that notifies the subscriber of the progress along the transition.
///
///
/// The parameter passed to the subscriber is the progress along the transition, with
/// 0 being the start and 1 being the end. The observable is guaranteed to fire 0
/// immediately on subscribe and 1 at the end of the duration.
///
public static IObservable GetTransitionsTimer(Animatable control, TimeSpan duration, TimeSpan delay = default(TimeSpan))
{
var startTime = _transitionsFrameCount;
var _duration = (ulong)(duration.Ticks / FrameTick.Ticks);
var endTime = startTime + _duration;
return TransitionsTimer
.TakeWhile(x => x < endTime)
.Select(x => (double)(x - startTime) / _duration)
.StartWith(0.0)
.Concat(Observable.Return(1.0));
}
}
}