Skip to content

Feature/animation apis revamp #3639

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conversation

Sergio0694
Copy link
Member

@Sergio0694 Sergio0694 commented Dec 18, 2020

Closes #3638

PR Type

What kind of change does this PR introduce?

  • Feature

Overview

This PR introduces an oberhaul of the animation package, by adding new APIs, doing a refactoring of the existing animation APIs, and also introducing extension points for both the behaviors and media packages. For more info, see linked issue.

APIs breakdown

AnimationBuilder (click to expand):
namespace Microsoft.Toolkit.Uwp.UI.Animations
{
    public sealed partial class AnimationBuilder
    {
        // Constructors

        public static AnimationBuilder Create();
        public void Start(UIElement element);
        public void Start(UIElement element, CancellationToken token);
        public Task StartAsync(UIElement element);
        public Task StartAsync(UIElement element, CancellationToken token);

        // Default animations

        public AnimationBuilder AnchorPoint(
            Axis axis,
            double to,
            double? from = null,
            TimeSpan? delay = null,
            TimeSpan? duration = null,
            EasingType easingType = DefaultEasingType,
            EasingMode easingMode = DefaultEasingMode);
        public AnimationBuilder AnchorPoint(
            Vector2 to,
            Vector2? from = null,
            TimeSpan? delay = null,
            TimeSpan? duration = null,
            EasingType easingType = DefaultEasingType,
            EasingMode easingMode = DefaultEasingMode);
        public AnimationBuilder Opacity(
            double to,
            double? from = null,
            TimeSpan? delay = null,
            TimeSpan? duration = null,
            EasingType easingType = DefaultEasingType,
            EasingMode easingMode = DefaultEasingMode,
            FrameworkLayer layer = FrameworkLayer.Composition);
        public AnimationBuilder Translation(
            Axis axis,
            double to,
            double? from = null,
            TimeSpan? delay = null,
            TimeSpan? duration = null,
            EasingType easingType = DefaultEasingType,
            EasingMode easingMode = DefaultEasingMode,
            FrameworkLayer layer = FrameworkLayer.Composition);
        public AnimationBuilder Translation(
            Vector2 to,
            Vector2? from = null,
            TimeSpan? delay = null,
            TimeSpan? duration = null,
            EasingType easingType = DefaultEasingType,
            EasingMode easingMode = DefaultEasingMode,
            FrameworkLayer layer = FrameworkLayer.Composition);
        public AnimationBuilder Translation(
            Vector3 to,
            Vector3? from = null,
            TimeSpan? delay = null,
            TimeSpan? duration = null,
            EasingType easingType = DefaultEasingType,
            EasingMode easingMode = DefaultEasingMode);
        public AnimationBuilder Offset(
            Axis axis,
            double to,
            double? from = null,
            TimeSpan? delay = null,
            TimeSpan? duration = null,
            EasingType easingType = DefaultEasingType,
            EasingMode easingMode = DefaultEasingMode);
        public AnimationBuilder Offset(
            Vector2 to,
            Vector2? from = null,
            TimeSpan? delay = null,
            TimeSpan? duration = null,
            EasingType easingType = DefaultEasingType,
            EasingMode easingMode = DefaultEasingMode);
        public AnimationBuilder Offset(
            Vector3 to,
            Vector3? from = null,
            TimeSpan? delay = null,
            TimeSpan? duration = null,
            EasingType easingType = DefaultEasingType,
            EasingMode easingMode = DefaultEasingMode);
        public AnimationBuilder Scale(
            double to,
            double? from = null,
            TimeSpan? delay = null,
            TimeSpan? duration = null,
            EasingType easingType = DefaultEasingType,
            EasingMode easingMode = DefaultEasingMode,
            FrameworkLayer layer = FrameworkLayer.Composition);
        public AnimationBuilder Scale(
            Axis axis,
            double to,
            double? from = null,
            TimeSpan? delay = null,
            TimeSpan? duration = null,
            EasingType easingType = DefaultEasingType,
            EasingMode easingMode = DefaultEasingMode,
            FrameworkLayer layer = FrameworkLayer.Composition);
        public AnimationBuilder Scale(
            Vector2 to,
            Vector2? from = null,
            TimeSpan? delay = null,
            TimeSpan? duration = null,
            EasingType easingType = DefaultEasingType,
            EasingMode easingMode = DefaultEasingMode,
            FrameworkLayer layer = FrameworkLayer.Composition);
        public AnimationBuilder Scale(
            Vector3 to,
            Vector3? from = null,
            TimeSpan? delay = null,
            TimeSpan? duration = null,
            EasingType easingType = DefaultEasingType,
            EasingMode easingMode = DefaultEasingMode);
        public AnimationBuilder CenterPoint(
            Axis axis,
            double to,
            double? from = null,
            TimeSpan? delay = null,
            TimeSpan? duration = null,
            EasingType easingType = DefaultEasingType,
            EasingMode easingMode = DefaultEasingMode,
            FrameworkLayer layer = FrameworkLayer.Composition);
        public AnimationBuilder CenterPoint(
            Vector2 to,
            Vector2? from = null,
            TimeSpan? delay = null,
            TimeSpan? duration = null,
            EasingType easingType = DefaultEasingType,
            EasingMode easingMode = DefaultEasingMode,
            FrameworkLayer layer = FrameworkLayer.Composition);
        public AnimationBuilder CenterPoint(
            Vector3 to,
            Vector3? from = null,
            TimeSpan? delay = null,
            TimeSpan? duration = null,
            EasingType easingType = DefaultEasingType,
            EasingMode easingMode = DefaultEasingMode);
        public AnimationBuilder Rotation(
            double to,
            double? from = null,
            TimeSpan? delay = null,
            TimeSpan? duration = null,
            EasingType easingType = DefaultEasingType,
            EasingMode easingMode = DefaultEasingMode,
            FrameworkLayer layer = FrameworkLayer.Composition);
        public AnimationBuilder RotationInDegrees(
            double to,
            double? from = null,
            TimeSpan? delay = null,
            TimeSpan? duration = null,
            EasingType easingType = DefaultEasingType,
            EasingMode easingMode = DefaultEasingMode,
            FrameworkLayer layer = FrameworkLayer.Composition);
        public AnimationBuilder RotationAxis(
            Vector3 to,
            Vector3? from = null,
            TimeSpan? delay = null,
            TimeSpan? duration = null,
            EasingType easingType = DefaultEasingType,
            EasingMode easingMode = DefaultEasingMode);
        public AnimationBuilder Orientation(
            Quaternion to,
            Quaternion? from = null,
            TimeSpan? delay = null,
            TimeSpan? duration = null,
            EasingType easingType = DefaultEasingType,
            EasingMode easingMode = DefaultEasingMode);
        public AnimationBuilder Transform(
            Matrix4x4 to,
            Matrix4x4? from = null,
            TimeSpan? delay = null,
            TimeSpan? duration = null,
            EasingType easingType = DefaultEasingType,
            EasingMode easingMode = DefaultEasingMode);
        public AnimationBuilder Clip(
            Side side,
            double to,
            double? from = null,
            TimeSpan? delay = null,
            TimeSpan? duration = null,
            EasingType easingType = DefaultEasingType,
            EasingMode easingMode = DefaultEasingMode);
        public AnimationBuilder Clip(
            Thickness to,
            Thickness? from = null,
            TimeSpan? delay = null,
            TimeSpan? duration = null,
            EasingType easingType = DefaultEasingType,
            EasingMode easingMode = DefaultEasingMode);
        public AnimationBuilder Size(
            Axis axis,
            double to,
            double? from = null,
            TimeSpan? delay = null,
            TimeSpan? duration = null,
            EasingType easingType = DefaultEasingType,
            EasingMode easingMode = DefaultEasingMode,
            FrameworkLayer layer = FrameworkLayer.Composition);
        public AnimationBuilder Size(
            Vector2 to,
            Vector2? from = null,
            TimeSpan? delay = null,
            TimeSpan? duration = null,
            EasingType easingType = DefaultEasingType,
            EasingMode easingMode = DefaultEasingMode,
            FrameworkLayer layer = FrameworkLayer.Composition);

        // Keyframe animations

        public IPropertyAnimationBuilder<double> AnchorPoint(Axis axis);
        public IPropertyAnimationBuilder<Vector2> AnchorPoint();
        public IPropertyAnimationBuilder<double> Opacity(FrameworkLayer layer = FrameworkLayer.Composition);
        public IPropertyAnimationBuilder<double> Translation(Axis axis, FrameworkLayer layer = FrameworkLayer.Composition);
        public IPropertyAnimationBuilder<Vector3> Translation();
        public IPropertyAnimationBuilder<double> Offset(Axis axis);
        public IPropertyAnimationBuilder<Vector3> Offset();
        public IPropertyAnimationBuilder<double> Scale(Axis axis, FrameworkLayer layer = FrameworkLayer.Composition);
        public IPropertyAnimationBuilder<Vector3> Scale();
        public IPropertyAnimationBuilder<double> CenterPoint(Axis axis, FrameworkLayer layer = FrameworkLayer.Composition);
        public IPropertyAnimationBuilder<Vector3> CenterPoint();
        public IPropertyAnimationBuilder<double> Rotation();
        public IPropertyAnimationBuilder<double> RotationInDegrees(FrameworkLayer layer = FrameworkLayer.Composition);
        public IPropertyAnimationBuilder<Vector3> RotationAxis();
        public IPropertyAnimationBuilder<Quaternion> Orientation();
        public IPropertyAnimationBuilder<double> Clip(Side side);
        public IPropertyAnimationBuilder<double> Size(Axis axis, FrameworkLayer layer = FrameworkLayer.Composition);
        public IPropertyAnimationBuilder<Vector2> Size();

        // Custom keyframe animations

        public AnimationBuilder NormalizedKeyFrames<T>(
            string property,
            Action<INormalizedKeyFrameAnimationBuilder<T>> build,
            TimeSpan? delay = null,
            TimeSpan? duration = null,
            FrameworkLayer layer = FrameworkLayer.Composition)
            where T : unmanaged;
        public AnimationBuilder NormalizedKeyFrames<T, TState>(
            string property,
            TState state,
            Action<INormalizedKeyFrameAnimationBuilder<T>, TState> build,
            TimeSpan? delay = null,
            TimeSpan? duration = null,
            FrameworkLayer layer = FrameworkLayer.Composition)
            where T : unmanaged;
        public AnimationBuilder TimedKeyFrames<T>(
            string property,
            Action<ITimedKeyFrameAnimationBuilder<T>> build,
            TimeSpan? delay = null,
            FrameworkLayer layer = FrameworkLayer.Composition)
            where T : unmanaged;
        public AnimationBuilder TimedKeyFrames<T, TState>(
            string property,
            TState state,
            Action<ITimedKeyFrameAnimationBuilder<T>, TState> build,
            TimeSpan? delay = null,
            FrameworkLayer layer = FrameworkLayer.Composition)
            where T : unmanaged;

        // External animations

        public AnimationBuilder ExternalAnimation(CompositionAnimation animation);
        public AnimationBuilder ExternalAnimation(CompositionObject target, CompositionAnimation animation);
        public AnimationBuilder ExternalAnimation(Timeline animation);
    }
}
Keyframe animation builders (click to expand):
namespace Microsoft.Toolkit.Uwp.UI.Animations
{
    public interface INormalizedKeyFrameAnimationBuilder<in T>
    {
        INormalizedKeyFrameAnimationBuilder<T> KeyFrame(
            double progress,
            T value,
            EasingType easingType = DefaultEasingType,
            EasingMode easingMode = DefaultEasingMode);
        INormalizedKeyFrameAnimationBuilder<T> ExpressionKeyFrame(
            double progress,
            string expression,
            EasingType easingType = DefaultEasingType,
            EasingMode easingMode = DefaultEasingMode);
    }

    public interface ITimedKeyFrameAnimationBuilder<in T>
    {
        ITimedKeyFrameAnimationBuilder<T> KeyFrame(
            TimeSpan progress,
            T value,
            EasingType easingType = DefaultEasingType,
            EasingMode easingMode = DefaultEasingMode);
        ITimedKeyFrameAnimationBuilder<T> ExpressionKeyFrame(
            TimeSpan progress,
            string expression,
            EasingType easingType = DefaultEasingType,
            EasingMode easingMode = DefaultEasingMode);
    }

    public interface IPropertyAnimationBuilder<in T>
    {
        AnimationBuilder NormalizedKeyFrames(
            Action<INormalizedKeyFrameAnimationBuilder<T>> build,
            TimeSpan? delay = null,
            TimeSpan? duration = null);
        AnimationBuilder NormalizedKeyFrames<TState>(
            TState state,
            Action<INormalizedKeyFrameAnimationBuilder<T>, TState> build,
            TimeSpan? delay = null,
            TimeSpan? duration = null);
        AnimationBuilder TimedKeyFrames(
            Action<ITimedKeyFrameAnimationBuilder<T>> build,
            TimeSpan? delay = null);
        AnimationBuilder TimedKeyFrames<TState>(
            TState state,
            Action<ITimedKeyFrameAnimationBuilder<T>, TState> build,
            TimeSpan? delay = null);
    }
}
Extensions (click to expand):
namespace Microsoft.Toolkit.Uwp.UI.Animations.Extensions
{
    public static class AnimationExtensions
    {
        public static TimeSpan DefaultDelay { get; }
        public static TimeSpan DefaultDuration { get ;}
        public const EasingType DefaultEasingType;
        public const EasingMode DefaultEasingMode;
    }

    public static class CompositionObjectExtensions
    {
        public static void StartAnimation(this CompositionObject compositionObject, CompositionAnimation animation);
    }

    public static class CompositorExtensions
    {
        public static CompositionEasingFunction? TryCreateEasingFunction(this Compositor compositor, EasingType easingType = DefaultEasingType, EasingMode easingMode = DefaultEasingMode);
        public static CubicBezierEasingFunction CreateCubicBezierEasingFunction(this Compositor compositor, float x1, float y1, float x2, float y2);
        public static BooleanKeyFrameAnimation CreateBooleanKeyFrameAnimation(
            this Compositor compositor,
            string? target,
            bool to,
            bool? from = null,
            TimeSpan? delay = null,
            TimeSpan? duration = null,
            AnimationDelayBehavior delayBehavior = AnimationDelayBehavior.SetInitialValueBeforeDelay,
            AnimationDirection direction = AnimationDirection.Normal,
            AnimationIterationBehavior iterationBehavior = AnimationIterationBehavior.Count,
            int iterationCount = 1);
        public static ScalarKeyFrameAnimation CreateScalarKeyFrameAnimation(
            this Compositor compositor,
            string? target,
            float to,
            float? from = null,
            TimeSpan? delay = null,
            TimeSpan? duration = null,
            CompositionEasingFunction? easing = null,
            AnimationDelayBehavior delayBehavior = AnimationDelayBehavior.SetInitialValueBeforeDelay,
            AnimationDirection direction = AnimationDirection.Normal,
            AnimationIterationBehavior iterationBehavior = AnimationIterationBehavior.Count,
            int iterationCount = 1);
        public static Vector2KeyFrameAnimation CreateVector2KeyFrameAnimation(
            this Compositor compositor,
            string? target,
            Vector2 to,
            Vector2? from = null,
            TimeSpan? delay = null,
            TimeSpan? duration = null,
            CompositionEasingFunction? easing = null,
            AnimationDelayBehavior delayBehavior = AnimationDelayBehavior.SetInitialValueBeforeDelay,
            AnimationDirection direction = AnimationDirection.Normal,
            AnimationIterationBehavior iterationBehavior = AnimationIterationBehavior.Count,
            int iterationCount = 1);
        public static Vector3KeyFrameAnimation CreateVector3KeyFrameAnimation(
            this Compositor compositor,
            string? target,
            Vector3 to,
            Vector3? from = null,
            TimeSpan? delay = null,
            TimeSpan? duration = null,
            CompositionEasingFunction? easing = null,
            AnimationDelayBehavior delayBehavior = AnimationDelayBehavior.SetInitialValueBeforeDelay,
            AnimationDirection direction = AnimationDirection.Normal,
            AnimationIterationBehavior iterationBehavior = AnimationIterationBehavior.Count,
            int iterationCount = 1);
        public static Vector4KeyFrameAnimation CreateVector4KeyFrameAnimation(
            this Compositor compositor,
            string? target,
            Vector4 to,
            Vector4? from = null,
            TimeSpan? delay = null,
            TimeSpan? duration = null,
            CompositionEasingFunction? easing = null,
            AnimationDelayBehavior delayBehavior = AnimationDelayBehavior.SetInitialValueBeforeDelay,
            AnimationDirection direction = AnimationDirection.Normal,
            AnimationIterationBehavior iterationBehavior = AnimationIterationBehavior.Count,
            int iterationCount = 1);
        public static ColorKeyFrameAnimation CreateColorKeyFrameAnimation(
            this Compositor compositor,
            string? target,
            Color to,
            Color? from = null,
            TimeSpan? delay = null,
            TimeSpan? duration = null,
            CompositionEasingFunction? easing = null,
            AnimationDelayBehavior delayBehavior = AnimationDelayBehavior.SetInitialValueBeforeDelay,
            AnimationDirection direction = AnimationDirection.Normal,
            AnimationIterationBehavior iterationBehavior = AnimationIterationBehavior.Count,
            int iterationCount = 1);
        public static QuaternionKeyFrameAnimation CreateQuaternionKeyFrameAnimation(
            this Compositor compositor,
            string? target,
            Quaternion to,
            Quaternion? from = null,
            TimeSpan? delay = null,
            TimeSpan? duration = null,
            CompositionEasingFunction? easing = null,
            AnimationDelayBehavior delayBehavior = AnimationDelayBehavior.SetInitialValueBeforeDelay,
            AnimationDirection direction = AnimationDirection.Normal,
            AnimationIterationBehavior iterationBehavior = AnimationIterationBehavior.Count,
            int iterationCount = 1);
    }

    public static class DependencyObjectExtensions
    {
        public static DoubleAnimation CreateDoubleAnimation(
            this DependencyObject target,
            string property,
            double to,
            double? from,
            TimeSpan? delay,
            TimeSpan duration,
            EasingFunctionBase? easing = null,
            bool enableDependecyAnimations = false);
        public static PointAnimation CreatePointAnimation(
            this DependencyObject target,
            string property,
            Point to,
            Point? from,
            TimeSpan? delay,
            TimeSpan duration,
            EasingFunctionBase? easing = null,
            bool enableDependecyAnimations = false);
        public static XamlColorAnimation CreateColorAnimation(
            this DependencyObject target,
            string property,
            Color to,
            Color? from,
            TimeSpan? delay,
            TimeSpan duration,
            EasingFunctionBase? easing = null);
    }

    public static class EasingTypeExtensions
    {
        public static EasingFunctionBase? ToEasingFunction(this EasingType easingType, EasingMode easingMode = DefaultEasingMode);
    }

    public static class ITimedKeyFrameAnimationBuilderExtensions
    {
        public static ITimedKeyFrameAnimationBuilder<T> KeyFrame<T>(
            this ITimedKeyFrameAnimationBuilder<T> builder,
            int progress,
            T value,
            EasingType easingType = DefaultEasingType,
            EasingMode easingMode = DefaultEasingMode)
            where T : unmanaged;
    }

    public static partial class ScrollViewerExtensions
    {
        public static ExpressionAnimation StartExpressionAnimation(
            this ScrollViewer scroller,
            UIElement target,
            Axis axis,
            VisualProperty property = VisualProperty.Translation);
        public static ExpressionAnimation StartExpressionAnimation(
            this ScrollViewer scroller,
            UIElement target,
            Axis sourceAxis,
            Axis targetAxis,
            VisualProperty property = VisualProperty.Translation);
    }

    public static class StoryboardAnimations
    {
        public static Task BeginAsync(this Storyboard storyboard);
    }
}
XAML animation types (click to expand):
namespace Microsoft.Toolkit.Uwp.UI.Animations
{
    // Animation set types

    public sealed class AnimationDictionary : DependencyObject, IList<AnimationSet>
    {
    }

    public sealed class AnimationSet : DependencyObjectCollection
    {
        public event EventHandler? Started;
        public event EventHandler? Ended;
        public bool IsSequential { get; set; }
        public async void Start();
        public async void Start(UIElement element);
        public async void Start(CancellationToken token);
        public Task StartAsync();
        public Task StartAsync(UIElement element);
        public Task StartAsync(CancellationToken token);
        public async Task StartAsync(UIElement element, CancellationToken token);
        public void Stop();
        public void Stop(UIElement element);

        public interface INode
        {
        }
    }

    public sealed class ImplicitAnimationSet : DependencyObjectCollection
    {
    }

    public sealed class AnimationScope : Animation
    {
        public IList<Animation> Animations { get; set; }
        public static readonly DependencyProperty AnimationsProperty;
        public override AnimationBuilder AppendToBuilder(AnimationBuilder builder, TimeSpan? delayHint, TimeSpan? durationHint, EasingType? easingTypeHint, EasingMode? easingModeHint);
    }

    // Interfaces

    public interface IActivity : AnimationSet.INode
    {
        Task InvokeAsync(UIElement element, CancellationToken token);
    }

    public interface IImplicitTimeline
    {
        CompositionAnimation GetAnimation(UIElement element, out string? target);
    }

    public interface IKeyFrame<T>
    {
        INormalizedKeyFrameAnimationBuilder<T> AppendToBuilder(INormalizedKeyFrameAnimationBuilder<T> builder);
    }

    public interface ITimeline : AnimationSet.INode
    {
        AnimationBuilder AppendToBuilder(
            AnimationBuilder builder,
            TimeSpan? delayHint = null,
            TimeSpan? durationHint = null,
            EasingType? easingTypeHint = null,
            EasingMode? easingModeHint = null);
    }

    // Abstract animation and activity types

    public abstract class Animation : DependencyObject, ITimeline
    {
        public TimeSpan? Delay { get; set; }
        public TimeSpan? Duration { get; set; }
        public EasingType? EasingType { get; set; }
        public EasingMode? EasingMode { get; set; }
        public static readonly DependencyProperty DelayProperty;
        public static readonly DependencyProperty DurationProperty;
        public static readonly DependencyProperty EasingTypeProperty;
        public static readonly DependencyProperty EasingModeProperty;
        public abstract AnimationBuilder AppendToBuilder(AnimationBuilder builder, TimeSpan? delayHint, TimeSpan? durationHint, EasingType? easingTypeHint, EasingMode? easingModeHint);
    }

    public abstract class Animation<TValue, TKeyFrame> : Animation
        where TKeyFrame : unmanaged
    {
        public TValue? To { get; set; }
        public TValue? From { get; set; }
        public IList<IKeyFrame<TKeyFrame>> KeyFrames { get; set; }
        public static readonly DependencyProperty KeyFramesProperty;
        public static readonly DependencyProperty FromProperty;
        public static readonly DependencyProperty ToProperty;
        public override AnimationBuilder AppendToBuilder(AnimationBuilder builder, TimeSpan? delayHint, TimeSpan? durationHint, EasingType? easingTypeHint, EasingMode? easingModeHint);
        protected abstract (TKeyFrame? To, TKeyFrame? From) GetParsedValues();
    }

    public abstract class CustomAnimation<TValue, TKeyFrame> : ImplicitAnimation<TValue, TKeyFrame>
        where TKeyFrame : unmanaged
    {
        public string? Target { get; set; }
        public FrameworkLayer Layer { get; set; }
        public override AnimationBuilder AppendToBuilder(AnimationBuilder builder, TimeSpan? delayHint, TimeSpan? durationHint, EasingType? easingTypeHint, EasingMode? easingModeHint);
    }

    public abstract class ImplicitAnimation<TValue, TKeyFrame> : Animation<TValue, TKeyFrame>, IImplicitTimeline
        where TKeyFrame : unmanaged
    {
        public string? ImplicitTarget { get; set; }
        public CompositionAnimation GetAnimation(UIElement element, out string? target);
    }

    public abstract class KeyFrame<TValue, TKeyFrame> : DependencyObject, IKeyFrame<TKeyFrame>
    {
        public double Key { get; set; }
        public TValue? Value { get; set; }
        public string? Expression { get; set; }
        public EasingType? EasingType { get; set; }
        public EasingMode? EasingMode { get; set; }
        public static readonly DependencyProperty KeyProperty;
        public static readonly DependencyProperty ValueProperty;
        public static readonly DependencyProperty ExpressionProperty;
        public static readonly DependencyProperty EasingTypeProperty;
        public static readonly DependencyProperty EasingModeProperty;
        public INormalizedKeyFrameAnimationBuilder<TKeyFrame> AppendToBuilder(INormalizedKeyFrameAnimationBuilder<TKeyFrame> builder);
        protected abstract TKeyFrame? GetParsedValue();
    }

    public abstract class Activity : DependencyObject, IActivity
    {
        public TimeSpan? Delay { get; set; }
        public static readonly DependencyProperty DelayProperty;
        public virtual Task InvokeAsync(UIElement element, CancellationToken token);
    }

    // Default animations

    public sealed class AnchorPointAnimation : ImplicitAnimation<string, Vector2>
    {
    }

    public sealed class CenterPointAnimation : ImplicitAnimation<string, Vector3>
    {
    }

    public sealed class ClipAnimation : Animation<Thickness?, Thickness>
    {
    }

    public sealed class OffsetAnimation : ImplicitAnimation<string, Vector3>
    {
    }

    public sealed class OpacityAnimation : ImplicitAnimation<double?, double>
    {
    }

    public sealed class OrientationAnimation : ImplicitAnimation<string, Quaternion>
    {
    }

    public sealed class RotationAnimation : ImplicitAnimation<double?, double>
    {
    }

    public sealed class RotationAxisAnimation : ImplicitAnimation<string, Vector3>
    {
    }

    public sealed class RotationInDegreesAnimation : ImplicitAnimation<double?, double>
    {
    }

    public sealed class ScaleAnimation : ImplicitAnimation<string, Vector3>
    {
    }

    public sealed class SizeAnimation : ImplicitAnimation<string, Vector2>
    {
    }

    public sealed class TranslationAnimation : ImplicitAnimation<string, Vector3>
    {
    }

    // Custom animations

    public sealed class ColorAnimation : CustomAnimation<Color?, Color>
    {
    }

    public sealed class QuaternionAnimation : CustomAnimation<string, Quaternion>
    {
    }

    public sealed class ScalarAnimation : CustomAnimation<double?, double>
    {
    }

    public sealed class Vector2Animation : CustomAnimation<string, Vector2>
    {
    }

    public sealed class Vector3Animation : CustomAnimation<string, Vector3>
    {
    }

    public sealed class Vector4Animation : CustomAnimation<string, Vector4>
    {
    }

    // Keyframes

    public sealed class ColorKeyFrame : KeyFrame<Color?, Color>
    {
    }

    public sealed class QuaternionKeyFrame : KeyFrame<string, Quaternion>
    {
    }

    public sealed class ScalarKeyFrame : KeyFrame<double?, double>
    {
    }

    public sealed class Vector2KeyFrame : KeyFrame<string, Vector2>
    {
    }

    public sealed class Vector3KeyFrame : KeyFrame<string, Vector3>
    {
    }

    public sealed class Vector4KeyFrame : KeyFrame<string, Vector4>
    {
    }

    // Activities

    public class StartAnimationActivity : Activity
    {
        public AnimationSet Animation { get; set; }
        public UIElement TargetObject { get; set; }
        public static readonly DependencyProperty AnimationProperty;
        public static readonly DependencyProperty TargetObjectProperty;
    }

    public class StopAnimationActivity : Activity
    {
        public AnimationSet Animation { get; set; }
        public UIElement TargetObject { get; set; }
        public static readonly DependencyProperty AnimationProperty;
        public static readonly DependencyProperty TargetObjectProperty;
    }
}
Attached properties (click to expand):
namespace Microsoft.Toolkit.Uwp.UI.Animations
{
    public static class Explicit
    {
        public static readonly DependencyProperty AnimationsProperty;
        public static AnimationDictionary GetAnimations(UIElement element);
        public static void SetAnimations(UIElement element, AnimationDictionary value);
    }

    public static class Implicit
    {
        public static readonly DependencyProperty ShowAnimationsProperty;
        public static readonly DependencyProperty HideAnimationsProperty;
        public static readonly DependencyProperty AnimationsProperty;
        public static ImplicitAnimationSet GetShowAnimations(UIElement element);
        public static void SetShowAnimations(UIElement element, ImplicitAnimationSet value);
        public static ImplicitAnimationSet GetHideAnimations(UIElement element);
        public static void SetHideAnimations(UIElement element, ImplicitAnimationSet value);
        public static ImplicitAnimationSet GetAnimations(UIElement element);
        public static void SetAnimations(UIElement element, ImplicitAnimationSet value);
    }

    public static class ItemsReorderAnimation
    {
        public static readonly DependencyProperty DurationProperty;
        private static readonly DependencyProperty ReorderAnimationProperty;
        public static TimeSpan GetDuration(ListViewBase listView);
        public static void SetDuration(ListViewBase listView, TimeSpan value);
    }
}
Animation behaviors (click to expand):
namespace Microsoft.Toolkit.Uwp.UI.Behaviors.Animations
{
    public sealed class AnimationEndBehavior : Trigger<AnimationSet>
    {
    }

    public sealed class AnimationStartBehavior : Trigger<AnimationSet>
    {
    }

    public class InvokeActionsActivity : Activity
    {
        public ActionCollection Actions { get; }
        public static readonly DependencyProperty ActionsProperty;
        public override async Task InvokeAsync(UIElement element, CancellationToken token);
    }

    public sealed class StartAnimationAction : DependencyObject, IAction
    {
        public AnimationSet Animation { get; set; }
        public UIElement TargetObject { get; set; }
        public static readonly DependencyProperty AnimationProperty;
        public static readonly DependencyProperty TargetObjectProperty;
        public object Execute(object sender, object parameter);
    }
}
Effect animations (click to expand):
namespace Microsoft.Toolkit.Uwp.UI.Animations
{
    // Abstract types

    public abstract class EffectAnimation<TEffect, TValue, TKeyFrame> : Animation<TValue, TKeyFrame>
        where TEffect : class, IPipelineEffect
        where TKeyFrame : unmanaged
    {
        public TEffect? Target { get; set; }
        public static readonly DependencyProperty TargetProperty;
        public override AnimationBuilder AppendToBuilder(AnimationBuilder builder, TimeSpan? delayHint, TimeSpan? durationHint, EasingType? easingTypeHint, EasingMode? easingModeHint);
    }

    // Effect animations

    public sealed class BlurEffectAnimation : EffectAnimation<BlurEffect, double?, double>
    {
    }

    public sealed class ColorEffectAnimation : EffectAnimation<TintEffect, Color?, Color>
    {
    }

    public sealed class CrossFadeEffectAnimation : EffectAnimation<CrossFadeEffect, double?, double>
    {
    }

    public sealed class ExposureEffectAnimation : EffectAnimation<ExposureEffect, double?, double>
    {
    }

    public sealed class HueRotationEffectAnimation : EffectAnimation<HueRotationEffect, double?, double>
    {
    }

    public sealed class OpacityEffectAnimation : EffectAnimation<OpacityEffect, double?, double>
    {
    }

    public sealed class SaturationEffectAnimation : EffectAnimation<SaturationEffect, double?, double>
    {
    }

    public sealed class SepiaEffectAnimation : EffectAnimation<SepiaEffect, double?, double>
    {
    }
}
Pipeline effects factory (click to expand):
namespace Microsoft.Toolkit.Uwp.UI.Media
{
    public abstract class AttachedVisualFactoryBase : DependencyObject
    {
        public abstract ValueTask<Visual> GetAttachedVisualAsync(UIElement element);
    }

    public sealed class PipelineVisualFactory : PipelineVisualFactoryBase
    {
        public PipelineBuilder Source { get; set; }
        public IList<PipelineEffect> Effects { get; set; }
        public static readonly DependencyProperty EffectsProperty;
        public override async ValueTask<Visual> GetAttachedVisualAsync(UIElement element);
        protected override PipelineBuilder OnPipelineRequested();
    }

    public abstract class PipelineVisualFactoryBase : AttachedVisualFactoryBase
    {
        public override async ValueTask<Visual> GetAttachedVisualAsync(UIElement element);
        protected abstract PipelineBuilder OnPipelineRequested();
    }
}

NOTE: work is still ongoing, will keep updating this post to keep the APIs in sync with the PR.

PR Checklist

Please check if your PR fulfills the following requirements:

  • Tested code with current supported SDKs
  • Pull Request has been submitted to the documentation repository instructions. Link:
  • Sample in sample app has been added / updated (for bug fixes / features)
  • New major technical changes in the toolkit have or will be added to the Wiki e.g. build changes, source generators, testing infrastructure, sample creation changes, etc...
  • Tests for the changes have been added (for bug fixes / features) (if applicable)
  • Header has been added to all new source files (run build/UpdateHeaders.bat)
  • Contains NO breaking changes

@ghost
Copy link

ghost commented Dec 18, 2020

Thanks Sergio0694 for opening a Pull Request! The reviewers will test the PR and highlight if there is any conflict or changes required. If the PR is approved we will proceed to merge the pull request 🙌

@ghost ghost requested review from michael-hawker and azchohfi December 18, 2020 22:19
@michael-hawker
Copy link
Member

michael-hawker commented Jan 21, 2021

@Sergio0694 I noticed the Offset sample isn't triggering on Loaded for some reason unlike the other ones??? It seems to be the only one that's not playing it's animation on Load?

Also looks like you accidently overwrote the Fade sample with the Blur sample? Pointed out the commit inline below.

@ghost ghost removed the needs attention 👋 label Jan 21, 2021
</media:PipelineVisualFactory>
</media:UIElementExtensions.VisualFactory>
<ani:Explicit.Animations>
<ani:AnimationSet x:Name="BlurAnimation">
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah not sure what happened here, but this used to be the Fade example? Looks like a mistake in e5ee018

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whoops, sorry! 😅
Fixed in 6196cdf, good catch!

Copy link
Member

@michael-hawker michael-hawker left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved with Changes, @RosarioPulella assume you and Sergio will be up before I will, so once the Fade and Offset samples are fixed we should be good to merge this unless you find any other issues. Then feel free to merge the dev/new-animations branch to master and update the dev/split-controls so you can continue on. 🎉

@michael-hawker michael-hawker mentioned this pull request Jan 21, 2021
8 tasks
@hawkerm
Copy link

hawkerm commented Jan 21, 2021

@Sergio0694 you added the StopAnimationActivity but not the corresponding StopAnimationAction in the behaviors, eh?

@Sergio0694
Copy link
Member Author

"I noticed the Offset sample isn't triggering on Loaded for some reason unlike the other ones??? It seems to be the only one that's not playing it's animation on Load?"

Seems like it was caused by the layout pass updating the offset after that and stopping the animation.
Changed how that played in 608b308, it works now 🙂

@Sergio0694
Copy link
Member Author

"you added the StopAnimationActivity but not the corresponding StopAnimationAction in the behaviors, eh?"

Added in 4f35471 😄

@Rosuavio Rosuavio merged commit 6a080a6 into CommunityToolkit:dev/new-animations Jan 21, 2021
@Rosuavio Rosuavio mentioned this pull request Jan 21, 2021
8 tasks
@Sergio0694 Sergio0694 mentioned this pull request Feb 28, 2021
8 tasks
ghost pushed a commit that referenced this pull request Mar 4, 2021
## Follow up for #3639

<!-- Add a brief overview here of the feature/bug & fix. -->

## PR Type
What kind of change does this PR introduce?
<!-- Please uncomment one or more that apply to this PR. -->

- Feature
- Improvements
<!-- - Code style update (formatting) -->
<!-- - Refactoring (no functional changes, no api changes) -->
<!-- - Build or CI related changes -->
<!-- - Documentation content changes -->
<!-- - Sample app changes -->
<!-- - Other... Please describe: -->


## Changelog

This PR tracks new changes and tweaks for the `Microsoft.Toolkit.Uwp.UI.Animations` package before the 7.0 release.
Changes are done according to feedbacks and requests from developers trying out the Preview 5 release.
This PR contains the following changes:

- All `AnimationBuilder` and XAML animation types now use `AnimationDelayBehavior.SetValueBeforeDelay` by default
- New `DelayBehavior` property available for XAML animation types (ignored when an animation is on the XAML layer)
- New `delayBehavior` parameter available for the explicit `AnimationBuilder` keyframe animation APIs (the more advanced ones)
- New `RepeatOption` parameter now available for all `AnimationBuilder` APIs (default, keyframe, etc.)

Opening as a draft PR until we finalize the list of changes to add.

## PR Checklist

Please check if your PR fulfills the following requirements:

- [X] Tested code with current [supported SDKs](../readme.md#supported)
- [ ] Pull Request has been submitted to the documentation repository [instructions](..\contributing.md#docs). Link: <!-- docs PR link -->
- [ ] Sample in sample app has been added / updated (for bug fixes / features)
    - [ ] Icon has been created (if new sample) following the [Thumbnail Style Guide and templates](https://github.com/windows-toolkit/WindowsCommunityToolkit-design-assets)
- [X] New major technical changes in the toolkit have or will be added to the [Wiki](https://github.com/windows-toolkit/WindowsCommunityToolkit/wiki) e.g. build changes, source generators, testing infrastructure, sample creation changes, etc...
- [ ] Tests for the changes have been added (for bug fixes / features) (if applicable)
- [X] Header has been added to all new source files (run *build/UpdateHeaders.bat*)
- [ ] Contains **NO** breaking changes
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Feature] New/Updated XAML/C# Animations Package
5 participants