// 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)); } } }