diff --git a/src/SamplesApp/UITests.Shared/Microsoft_UI_Xaml_Controls/AnimatedVisualPlayer/Checkmark.cs b/src/SamplesApp/UITests.Shared/Microsoft_UI_Xaml_Controls/AnimatedVisualPlayer/Checkmark.cs
new file mode 100644
index 000000000000..babd4beae2db
--- /dev/null
+++ b/src/SamplesApp/UITests.Shared/Microsoft_UI_Xaml_Controls/AnimatedVisualPlayer/Checkmark.cs
@@ -0,0 +1,1324 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+//
+// LottieGen version:
+// 8.1.240821.1+077322fa26
+//
+// Command:
+// LottieGen -Language CSharp -Public -WinUIVersion 3.0 -InputFile Checkmark.lottie
+//
+// Input file:
+// Checkmark.lottie (2345 bytes created 13:06+01:00 Jan 23 2025)
+//
+// LottieGen source:
+// http://aka.ms/Lottie
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+// ____________________________________
+// | Object stats | Count |
+// |__________________________|_______|
+// | All CompositionObjects | 202 |
+// |--------------------------+-------|
+// | Expression animators | 17 |
+// | KeyFrame animators | 33 |
+// | Reference parameters | 17 |
+// | Expression operations | 0 |
+// |--------------------------+-------|
+// | Animated brushes | 1 |
+// | Animated gradient stops | - |
+// | ExpressionAnimations | 17 |
+// | PathKeyFrameAnimations | - |
+// |--------------------------+-------|
+// | ContainerVisuals | 12 |
+// | ShapeVisuals | 12 |
+// |--------------------------+-------|
+// | ContainerShapes | - |
+// | CompositionSpriteShapes | 13 |
+// |--------------------------+-------|
+// | Brushes | 3 |
+// | Gradient stops | - |
+// | CompositionVisualSurface | - |
+// ------------------------------------
+using Microsoft.Graphics;
+using Microsoft.Graphics.Canvas.Geometry;
+using Microsoft.UI.Composition;
+using Microsoft.UI.Xaml.Controls;
+using System;
+using System.Collections.Generic;
+using System.Numerics;
+using Windows.Foundation;
+using Windows.UI;
+
+namespace AnimatedVisuals
+{
+ // Name: Comp 1
+ // Frame rate: 29.9700012207031 fps
+ // Frame count: 45.0000018328876
+ // Duration: 1501.5 mS
+ sealed class Checkmark
+ : Microsoft.UI.Xaml.Controls.IAnimatedVisualSource
+ , Microsoft.UI.Xaml.Controls.IAnimatedVisualSource2
+ {
+ // Animation duration: 1.502 seconds.
+ internal const long c_durationTicks = 15015015;
+
+ public Microsoft.UI.Xaml.Controls.IAnimatedVisual TryCreateAnimatedVisual(Compositor compositor)
+ {
+ object ignored = null;
+ return TryCreateAnimatedVisual(compositor, out ignored);
+ }
+
+ public Microsoft.UI.Xaml.Controls.IAnimatedVisual TryCreateAnimatedVisual(Compositor compositor, out object diagnostics)
+ {
+ diagnostics = null;
+
+ var res =
+ new Checkmark_AnimatedVisual(
+ compositor
+ );
+ res.CreateAnimations();
+ return res;
+ }
+
+ ///
+ /// Gets the number of frames in the animation.
+ ///
+ public double FrameCount => 45.0000018328876;
+
+ ///
+ /// Gets the frame rate of the animation.
+ ///
+ public double Framerate => 29.9700012207031;
+
+ ///
+ /// Gets the duration of the animation.
+ ///
+ public TimeSpan Duration => TimeSpan.FromTicks(15015015);
+
+ ///
+ /// Converts a zero-based frame number to the corresponding progress value denoting the
+ /// start of the frame.
+ ///
+ public double FrameToProgress(double frameNumber)
+ {
+ return frameNumber / 45.0000018328876;
+ }
+
+ ///
+ /// Returns a map from marker names to corresponding progress values.
+ ///
+ public IReadOnlyDictionary Markers =>
+ new Dictionary
+ {
+ };
+
+ ///
+ /// Sets the color property with the given name, or does nothing if no such property
+ /// exists.
+ ///
+ public void SetColorProperty(string propertyName, Color value)
+ {
+ }
+
+ ///
+ /// Sets the scalar property with the given name, or does nothing if no such property
+ /// exists.
+ ///
+ public void SetScalarProperty(string propertyName, double value)
+ {
+ }
+
+ public void Update(AnimatedVisualPlayer player) => throw new NotImplementedException();
+ public void Load() => throw new NotImplementedException();
+ public void Unload() => throw new NotImplementedException();
+ public void Play(double fromProgress, double toProgress, bool looped) => throw new NotImplementedException();
+ public void Stop() => throw new NotImplementedException();
+ public void Pause() => throw new NotImplementedException();
+ public void Resume() => throw new NotImplementedException();
+ public void SetProgress(double progress) => throw new NotImplementedException();
+ public Size Measure(Size availableSize) => throw new NotImplementedException();
+
+ sealed class Checkmark_AnimatedVisual
+ : Microsoft.UI.Xaml.Controls.IAnimatedVisual
+ , Microsoft.UI.Xaml.Controls.IAnimatedVisual2
+ {
+ const long c_durationTicks = 15015015;
+ readonly Compositor _c;
+ readonly ExpressionAnimation _reusableExpressionAnimation;
+ AnimationController _animationController_0;
+ CompositionColorBrush _animatedColorBrush_TransparentWhite_to_TransparentWhite;
+ CompositionColorBrush _colorBrush_AlmostDodgerBlue_FF149BD6;
+ CompositionEllipseGeometry _ellipse_0_0;
+ CompositionEllipseGeometry _ellipse_0_1;
+ CompositionEllipseGeometry _ellipse_0_2;
+ CompositionEllipseGeometry _ellipse_0_3;
+ CompositionPath _path;
+ CompositionPathGeometry _pathGeometry_0;
+ CompositionPathGeometry _pathGeometry_1;
+ CompositionPathGeometry _pathGeometry_2;
+ CompositionPathGeometry _pathGeometry_3;
+ CompositionPathGeometry _pathGeometry_4;
+ CompositionPathGeometry _pathGeometry_5;
+ CompositionPathGeometry _pathGeometry_6;
+ CompositionPathGeometry _pathGeometry_7;
+ CompositionPathGeometry _pathGeometry_8;
+ CompositionSpriteShape _spriteShape_06;
+ CompositionSpriteShape _spriteShape_07;
+ CompositionSpriteShape _spriteShape_08;
+ ContainerVisual _root;
+ CubicBezierEasingFunction _cubicBezierEasingFunction_0;
+ CubicBezierEasingFunction _cubicBezierEasingFunction_1;
+ CubicBezierEasingFunction _cubicBezierEasingFunction_2;
+ CubicBezierEasingFunction _cubicBezierEasingFunction_3;
+ CubicBezierEasingFunction _cubicBezierEasingFunction_4;
+ CubicBezierEasingFunction _cubicBezierEasingFunction_5;
+ InsetClip _insetClip_0;
+ ScalarKeyFrameAnimation _opacityScalarAnimation_1_to_0p3_0;
+ ScalarKeyFrameAnimation _opacityScalarAnimation_1_to_0p3_1;
+ ScalarKeyFrameAnimation _tEndScalarAnimation_0_to_1_0;
+ ScalarKeyFrameAnimation _tEndScalarAnimation_0_to_1_1;
+ ScalarKeyFrameAnimation _tStartScalarAnimation_0_to_1_0;
+ ScalarKeyFrameAnimation _tStartScalarAnimation_0_to_1_1;
+ ShapeVisual _shapeVisual_01;
+ ShapeVisual _shapeVisual_02;
+ ShapeVisual _shapeVisual_03;
+ ShapeVisual _shapeVisual_04;
+ ShapeVisual _shapeVisual_08;
+ ShapeVisual _shapeVisual_09;
+ ShapeVisual _shapeVisual_10;
+ ShapeVisual _shapeVisual_11;
+ StepEasingFunction _holdThenStepEasingFunction;
+ StepEasingFunction _stepThenHoldEasingFunction;
+ Vector2KeyFrameAnimation _offsetVector2Animation;
+ Vector2KeyFrameAnimation _radiusVector2Animation_1;
+
+ void BindProperty(
+ CompositionObject target,
+ string animatedPropertyName,
+ string expression,
+ string referenceParameterName,
+ CompositionObject referencedObject)
+ {
+ _reusableExpressionAnimation.ClearAllParameters();
+ _reusableExpressionAnimation.Expression = expression;
+ _reusableExpressionAnimation.SetReferenceParameter(referenceParameterName, referencedObject);
+ target.StartAnimation(animatedPropertyName, _reusableExpressionAnimation);
+ }
+
+ ColorKeyFrameAnimation CreateColorKeyFrameAnimation(float initialProgress, Color initialValue, CompositionEasingFunction initialEasingFunction)
+ {
+ var result = _c.CreateColorKeyFrameAnimation();
+ result.Duration = TimeSpan.FromTicks(c_durationTicks);
+ result.InterpolationColorSpace = CompositionColorSpace.Rgb;
+ result.InsertKeyFrame(initialProgress, initialValue, initialEasingFunction);
+ return result;
+ }
+
+ ScalarKeyFrameAnimation CreateScalarKeyFrameAnimation(float initialProgress, float initialValue, CompositionEasingFunction initialEasingFunction)
+ {
+ var result = _c.CreateScalarKeyFrameAnimation();
+ result.Duration = TimeSpan.FromTicks(c_durationTicks);
+ result.InsertKeyFrame(initialProgress, initialValue, initialEasingFunction);
+ return result;
+ }
+
+ Vector2KeyFrameAnimation CreateVector2KeyFrameAnimation(float initialProgress, Vector2 initialValue, CompositionEasingFunction initialEasingFunction)
+ {
+ var result = _c.CreateVector2KeyFrameAnimation();
+ result.Duration = TimeSpan.FromTicks(c_durationTicks);
+ result.InsertKeyFrame(initialProgress, initialValue, initialEasingFunction);
+ return result;
+ }
+
+ CompositionSpriteShape CreateSpriteShape(CompositionGeometry geometry, Matrix3x2 transformMatrix)
+ {
+ var result = _c.CreateSpriteShape(geometry);
+ result.TransformMatrix = transformMatrix;
+ return result;
+ }
+
+ CompositionSpriteShape CreateSpriteShape(CompositionGeometry geometry, Matrix3x2 transformMatrix, CompositionBrush fillBrush)
+ {
+ var result = _c.CreateSpriteShape(geometry);
+ result.TransformMatrix = transformMatrix;
+ result.FillBrush = fillBrush;
+ return result;
+ }
+
+ AnimationController AnimationController_0()
+ {
+ if (_animationController_0 != null) { return _animationController_0; }
+ var result = _animationController_0 = _c.CreateAnimationController();
+ result.Pause();
+ BindProperty(_animationController_0, "Progress", "_.Progress", "_", _root);
+ return result;
+ }
+
+ // - - - Layer aggregator
+ // - - Scale:0.6959,0.6959, Offset:<236.888, 240.258>
+ CanvasGeometry Geometry_0()
+ {
+ CanvasGeometry result;
+ using (var builder = new CanvasPathBuilder(null))
+ {
+ builder.BeginFigure(new Vector2(-76.4260025F, 37.9990005F));
+ builder.AddLine(new Vector2(12.0559998F, 114.073997F));
+ builder.AddLine(new Vector2(169.990997F, -68.6350021F));
+ builder.EndFigure(CanvasFigureLoop.Open);
+ result = CanvasGeometry.CreatePath(builder);
+ }
+ return result;
+ }
+
+ CanvasGeometry Geometry_1()
+ {
+ CanvasGeometry result;
+ using (var builder = new CanvasPathBuilder(null))
+ {
+ builder.BeginFigure(new Vector2(-230F, 4F));
+ builder.AddLine(new Vector2(214F, 4F));
+ builder.EndFigure(CanvasFigureLoop.Open);
+ result = CanvasGeometry.CreatePath(builder);
+ }
+ return result;
+ }
+
+ // Color
+ ColorKeyFrameAnimation ColorAnimation_TransparentWhite_to_TransparentWhite()
+ {
+ // Frame 0.
+ var result = CreateColorKeyFrameAnimation(0F, Color.FromArgb(0x00, 0xFF, 0xFF, 0xFF), StepThenHoldEasingFunction());
+ // Frame 24.
+ // TransparentWhite
+ result.InsertKeyFrame(0.533333302F, Color.FromArgb(0x00, 0xFF, 0xFF, 0xFF), HoldThenStepEasingFunction());
+ // Frame 25.
+ // White
+ result.InsertKeyFrame(0.555555522F, Color.FromArgb(0xFF, 0xFF, 0xFF, 0xFF), CubicBezierEasingFunction_5());
+ // Frame 29.
+ // White
+ result.InsertKeyFrame(0.644444406F, Color.FromArgb(0xFF, 0xFF, 0xFF, 0xFF), CubicBezierEasingFunction_5());
+ // Frame 38.
+ // TransparentWhite
+ result.InsertKeyFrame(0.844444454F, Color.FromArgb(0x00, 0xFF, 0xFF, 0xFF), CubicBezierEasingFunction_5());
+ return result;
+ }
+
+ CompositionColorBrush AnimatedColorBrush_TransparentWhite_to_TransparentWhite()
+ {
+ if (_animatedColorBrush_TransparentWhite_to_TransparentWhite != null) { return _animatedColorBrush_TransparentWhite_to_TransparentWhite; }
+ var result = _animatedColorBrush_TransparentWhite_to_TransparentWhite = _c.CreateColorBrush();
+ return result;
+ }
+
+ CompositionColorBrush ColorBrush_AlmostDodgerBlue_FF149BD6()
+ {
+ return (_colorBrush_AlmostDodgerBlue_FF149BD6 == null)
+ ? _colorBrush_AlmostDodgerBlue_FF149BD6 = _c.CreateColorBrush(Color.FromArgb(0xFF, 0x14, 0x9B, 0xD6))
+ : _colorBrush_AlmostDodgerBlue_FF149BD6;
+ }
+
+ // - Layer aggregator
+ // Scale:0.6959,0.6959, Offset:<236.888, 240.258>
+ CompositionColorBrush ColorBrush_White()
+ {
+ return _c.CreateColorBrush(Color.FromArgb(0xFF, 0xFF, 0xFF, 0xFF));
+ }
+
+ // - Layer aggregator
+ // Scale:0.8,0.8, Offset:<256, 256>
+ // Ellipse Path 1.EllipseGeometry
+ CompositionEllipseGeometry Ellipse_0_0()
+ {
+ if (_ellipse_0_0 != null) { return _ellipse_0_0; }
+ var result = _ellipse_0_0 = _c.CreateEllipseGeometry();
+ result.Radius = new Vector2(0F, 0F);
+ return result;
+ }
+
+ // - - PreComp layer: firefly
+ // - Shape tree root for layer: Shape Layer 1
+ // Offset:<256, 256>
+ // Ellipse Path 1.EllipseGeometry
+ CompositionEllipseGeometry Ellipse_0_1()
+ {
+ if (_ellipse_0_1 != null) { return _ellipse_0_1; }
+ var result = _ellipse_0_1 = _c.CreateEllipseGeometry();
+ result.Radius = new Vector2(0F, 0F);
+ return result;
+ }
+
+ // - - PreComp layer: firefly
+ // - Shape tree root for layer: Shape Layer 1
+ // Offset:<256, 256>
+ // Ellipse Path 1.EllipseGeometry
+ CompositionEllipseGeometry Ellipse_0_2()
+ {
+ if (_ellipse_0_2 != null) { return _ellipse_0_2; }
+ var result = _ellipse_0_2 = _c.CreateEllipseGeometry();
+ result.Radius = new Vector2(0F, 0F);
+ return result;
+ }
+
+ // - - PreComp layer: firefly
+ // - Shape tree root for layer: Shape Layer 1
+ // Offset:<256, 256>
+ // Ellipse Path 1.EllipseGeometry
+ CompositionEllipseGeometry Ellipse_0_3()
+ {
+ if (_ellipse_0_3 != null) { return _ellipse_0_3; }
+ var result = _ellipse_0_3 = _c.CreateEllipseGeometry();
+ result.Radius = new Vector2(0F, 0F);
+ return result;
+ }
+
+ CompositionPath Path()
+ {
+ if (_path != null) { return _path; }
+ var result = _path = new CompositionPath(Geometry_1());
+ return result;
+ }
+
+ // - Layer aggregator
+ // Scale:0.6959,0.6959, Offset:<236.888, 240.258>
+ CompositionPathGeometry PathGeometry_0()
+ {
+ if (_pathGeometry_0 != null) { return _pathGeometry_0; }
+ var result = _pathGeometry_0 = _c.CreatePathGeometry(new CompositionPath(Geometry_0()));
+ return result;
+ }
+
+ CompositionPathGeometry PathGeometry_1()
+ {
+ if (_pathGeometry_1 != null) { return _pathGeometry_1; }
+ var result = _pathGeometry_1 = _c.CreatePathGeometry(Path());
+ var propertySet = result.Properties;
+ propertySet.InsertScalar("TEnd", 0F);
+ propertySet.InsertScalar("TStart", 0F);
+ BindProperty(_pathGeometry_1, "TrimStart", "Min(my.TStart,my.TEnd)", "my", _pathGeometry_1);
+ BindProperty(_pathGeometry_1, "TrimEnd", "Max(my.TStart,my.TEnd)", "my", _pathGeometry_1);
+ return result;
+ }
+
+ CompositionPathGeometry PathGeometry_2()
+ {
+ if (_pathGeometry_2 != null) { return _pathGeometry_2; }
+ var result = _pathGeometry_2 = _c.CreatePathGeometry(Path());
+ var propertySet = result.Properties;
+ propertySet.InsertScalar("TEnd", 0F);
+ propertySet.InsertScalar("TStart", 0F);
+ BindProperty(_pathGeometry_2, "TrimStart", "Min(my.TStart,my.TEnd)", "my", _pathGeometry_2);
+ BindProperty(_pathGeometry_2, "TrimEnd", "Max(my.TStart,my.TEnd)", "my", _pathGeometry_2);
+ return result;
+ }
+
+ CompositionPathGeometry PathGeometry_3()
+ {
+ if (_pathGeometry_3 != null) { return _pathGeometry_3; }
+ var result = _pathGeometry_3 = _c.CreatePathGeometry(Path());
+ var propertySet = result.Properties;
+ propertySet.InsertScalar("TEnd", 0F);
+ propertySet.InsertScalar("TStart", 0F);
+ BindProperty(_pathGeometry_3, "TrimStart", "Min(my.TStart,my.TEnd)", "my", _pathGeometry_3);
+ BindProperty(_pathGeometry_3, "TrimEnd", "Max(my.TStart,my.TEnd)", "my", _pathGeometry_3);
+ return result;
+ }
+
+ CompositionPathGeometry PathGeometry_4()
+ {
+ if (_pathGeometry_4 != null) { return _pathGeometry_4; }
+ var result = _pathGeometry_4 = _c.CreatePathGeometry(Path());
+ var propertySet = result.Properties;
+ propertySet.InsertScalar("TEnd", 0F);
+ propertySet.InsertScalar("TStart", 0F);
+ BindProperty(_pathGeometry_4, "TrimStart", "Min(my.TStart,my.TEnd)", "my", _pathGeometry_4);
+ BindProperty(_pathGeometry_4, "TrimEnd", "Max(my.TStart,my.TEnd)", "my", _pathGeometry_4);
+ return result;
+ }
+
+ CompositionPathGeometry PathGeometry_5()
+ {
+ if (_pathGeometry_5 != null) { return _pathGeometry_5; }
+ var result = _pathGeometry_5 = _c.CreatePathGeometry(Path());
+ var propertySet = result.Properties;
+ propertySet.InsertScalar("TEnd", 0F);
+ propertySet.InsertScalar("TStart", 0F);
+ BindProperty(_pathGeometry_5, "TrimStart", "Min(my.TStart,my.TEnd)", "my", _pathGeometry_5);
+ BindProperty(_pathGeometry_5, "TrimEnd", "Max(my.TStart,my.TEnd)", "my", _pathGeometry_5);
+ return result;
+ }
+
+ CompositionPathGeometry PathGeometry_6()
+ {
+ if (_pathGeometry_6 != null) { return _pathGeometry_6; }
+ var result = _pathGeometry_6 = _c.CreatePathGeometry(Path());
+ var propertySet = result.Properties;
+ propertySet.InsertScalar("TEnd", 0F);
+ propertySet.InsertScalar("TStart", 0F);
+ BindProperty(_pathGeometry_6, "TrimStart", "Min(my.TStart,my.TEnd)", "my", _pathGeometry_6);
+ BindProperty(_pathGeometry_6, "TrimEnd", "Max(my.TStart,my.TEnd)", "my", _pathGeometry_6);
+ return result;
+ }
+
+ CompositionPathGeometry PathGeometry_7()
+ {
+ if (_pathGeometry_7 != null) { return _pathGeometry_7; }
+ var result = _pathGeometry_7 = _c.CreatePathGeometry(Path());
+ var propertySet = result.Properties;
+ propertySet.InsertScalar("TEnd", 0F);
+ propertySet.InsertScalar("TStart", 0F);
+ BindProperty(_pathGeometry_7, "TrimStart", "Min(my.TStart,my.TEnd)", "my", _pathGeometry_7);
+ BindProperty(_pathGeometry_7, "TrimEnd", "Max(my.TStart,my.TEnd)", "my", _pathGeometry_7);
+ return result;
+ }
+
+ CompositionPathGeometry PathGeometry_8()
+ {
+ if (_pathGeometry_8 != null) { return _pathGeometry_8; }
+ var result = _pathGeometry_8 = _c.CreatePathGeometry(Path());
+ var propertySet = result.Properties;
+ propertySet.InsertScalar("TEnd", 0F);
+ propertySet.InsertScalar("TStart", 0F);
+ BindProperty(_pathGeometry_8, "TrimStart", "Min(my.TStart,my.TEnd)", "my", _pathGeometry_8);
+ BindProperty(_pathGeometry_8, "TrimEnd", "Max(my.TStart,my.TEnd)", "my", _pathGeometry_8);
+ return result;
+ }
+
+ // Layer aggregator
+ // Ellipse Path 1
+ CompositionSpriteShape SpriteShape_00()
+ {
+ // Offset:<260.7936, 258.792>, Rotation:-0.011598425070025746 degrees,
+ // Scale:<0.8, 0.8>
+ var geometry = Ellipse_0_0();
+ var result = CreateSpriteShape(geometry, new Matrix3x2(0.800000012F, 0F, 0F, 0.800000012F, 260.79361F, 258.791992F), ColorBrush_AlmostDodgerBlue_FF149BD6());;
+ return result;
+ }
+
+ // Layer aggregator
+ // Path 1
+ CompositionSpriteShape SpriteShape_01()
+ {
+ // Offset:<232.0167, 247.9129>, Scale:<0.6959, 0.6959>
+ var result = CreateSpriteShape(PathGeometry_0(), new Matrix3x2(0.695900023F, 0F, 0F, 0.695900023F, 232.016693F, 247.912903F));;
+ result.StrokeBrush = ColorBrush_White();
+ result.StrokeDashCap = CompositionStrokeCap.Round;
+ result.StrokeStartCap = CompositionStrokeCap.Round;
+ result.StrokeEndCap = CompositionStrokeCap.Round;
+ result.StrokeMiterLimit = 2F;
+ result.StrokeThickness = 35F;
+ return result;
+ }
+
+ // - PreComp layer: trait 2
+ // Opacity for layer: Shape Layer 1
+ // Path 1
+ CompositionSpriteShape SpriteShape_02()
+ {
+ // Offset:<256, 256>
+ var result = CreateSpriteShape(PathGeometry_1(), new Matrix3x2(1F, 0F, 0F, 1F, 256F, 256F));;
+ result.StrokeBrush = ColorBrush_AlmostDodgerBlue_FF149BD6();
+ result.StrokeDashCap = CompositionStrokeCap.Round;
+ result.StrokeStartCap = CompositionStrokeCap.Round;
+ result.StrokeEndCap = CompositionStrokeCap.Round;
+ result.StrokeMiterLimit = 2F;
+ result.StrokeThickness = 70F;
+ return result;
+ }
+
+ // - PreComp layer: trait 2
+ // Opacity for layer: Shape Layer 1
+ // Path 1
+ CompositionSpriteShape SpriteShape_03()
+ {
+ // Offset:<256, 256>
+ var result = CreateSpriteShape(PathGeometry_2(), new Matrix3x2(1F, 0F, 0F, 1F, 256F, 256F));;
+ result.StrokeBrush = ColorBrush_AlmostDodgerBlue_FF149BD6();
+ result.StrokeDashCap = CompositionStrokeCap.Round;
+ result.StrokeStartCap = CompositionStrokeCap.Round;
+ result.StrokeEndCap = CompositionStrokeCap.Round;
+ result.StrokeMiterLimit = 2F;
+ result.StrokeThickness = 70F;
+ return result;
+ }
+
+ // - PreComp layer: trait 2
+ // Opacity for layer: Shape Layer 1
+ // Path 1
+ CompositionSpriteShape SpriteShape_04()
+ {
+ // Offset:<256, 256>
+ var result = CreateSpriteShape(PathGeometry_3(), new Matrix3x2(1F, 0F, 0F, 1F, 256F, 256F));;
+ result.StrokeBrush = ColorBrush_AlmostDodgerBlue_FF149BD6();
+ result.StrokeDashCap = CompositionStrokeCap.Round;
+ result.StrokeStartCap = CompositionStrokeCap.Round;
+ result.StrokeEndCap = CompositionStrokeCap.Round;
+ result.StrokeMiterLimit = 2F;
+ result.StrokeThickness = 70F;
+ return result;
+ }
+
+ // - PreComp layer: trait 2
+ // Opacity for layer: Shape Layer 1
+ // Path 1
+ CompositionSpriteShape SpriteShape_05()
+ {
+ // Offset:<256, 256>
+ var result = CreateSpriteShape(PathGeometry_4(), new Matrix3x2(1F, 0F, 0F, 1F, 256F, 256F));;
+ result.StrokeBrush = ColorBrush_AlmostDodgerBlue_FF149BD6();
+ result.StrokeDashCap = CompositionStrokeCap.Round;
+ result.StrokeStartCap = CompositionStrokeCap.Round;
+ result.StrokeEndCap = CompositionStrokeCap.Round;
+ result.StrokeMiterLimit = 2F;
+ result.StrokeThickness = 70F;
+ return result;
+ }
+
+ // - PreComp layer: firefly
+ // Shape tree root for layer: Shape Layer 1
+ // Ellipse Path 1
+ CompositionSpriteShape SpriteShape_06()
+ {
+ // Offset:<256, 256>
+ var geometry = Ellipse_0_1();
+ if (_spriteShape_06 != null) { return _spriteShape_06; }
+ var result = _spriteShape_06 = CreateSpriteShape(geometry, new Matrix3x2(1F, 0F, 0F, 1F, 256F, 256F), AnimatedColorBrush_TransparentWhite_to_TransparentWhite());;
+ return result;
+ }
+
+ // - PreComp layer: firefly
+ // Shape tree root for layer: Shape Layer 1
+ // Ellipse Path 1
+ CompositionSpriteShape SpriteShape_07()
+ {
+ // Offset:<256, 256>
+ var geometry = Ellipse_0_2();
+ if (_spriteShape_07 != null) { return _spriteShape_07; }
+ var result = _spriteShape_07 = CreateSpriteShape(geometry, new Matrix3x2(1F, 0F, 0F, 1F, 256F, 256F), AnimatedColorBrush_TransparentWhite_to_TransparentWhite());;
+ return result;
+ }
+
+ // - PreComp layer: firefly
+ // Shape tree root for layer: Shape Layer 1
+ // Ellipse Path 1
+ CompositionSpriteShape SpriteShape_08()
+ {
+ // Offset:<256, 256>
+ var geometry = Ellipse_0_3();
+ if (_spriteShape_08 != null) { return _spriteShape_08; }
+ var result = _spriteShape_08 = CreateSpriteShape(geometry, new Matrix3x2(1F, 0F, 0F, 1F, 256F, 256F), AnimatedColorBrush_TransparentWhite_to_TransparentWhite());;
+ return result;
+ }
+
+ // - PreComp layer: trait
+ // Opacity for layer: Shape Layer 1
+ // Path 1
+ CompositionSpriteShape SpriteShape_09()
+ {
+ // Offset:<256, 256>
+ var result = CreateSpriteShape(PathGeometry_5(), new Matrix3x2(1F, 0F, 0F, 1F, 256F, 256F));;
+ result.StrokeBrush = ColorBrush_AlmostDodgerBlue_FF149BD6();
+ result.StrokeDashCap = CompositionStrokeCap.Round;
+ result.StrokeStartCap = CompositionStrokeCap.Round;
+ result.StrokeEndCap = CompositionStrokeCap.Round;
+ result.StrokeMiterLimit = 2F;
+ result.StrokeThickness = 70F;
+ return result;
+ }
+
+ // - PreComp layer: trait
+ // Opacity for layer: Shape Layer 1
+ // Path 1
+ CompositionSpriteShape SpriteShape_10()
+ {
+ // Offset:<256, 256>
+ var result = CreateSpriteShape(PathGeometry_6(), new Matrix3x2(1F, 0F, 0F, 1F, 256F, 256F));;
+ result.StrokeBrush = ColorBrush_AlmostDodgerBlue_FF149BD6();
+ result.StrokeDashCap = CompositionStrokeCap.Round;
+ result.StrokeStartCap = CompositionStrokeCap.Round;
+ result.StrokeEndCap = CompositionStrokeCap.Round;
+ result.StrokeMiterLimit = 2F;
+ result.StrokeThickness = 70F;
+ return result;
+ }
+
+ // - PreComp layer: trait
+ // Opacity for layer: Shape Layer 1
+ // Path 1
+ CompositionSpriteShape SpriteShape_11()
+ {
+ // Offset:<256, 256>
+ var result = CreateSpriteShape(PathGeometry_7(), new Matrix3x2(1F, 0F, 0F, 1F, 256F, 256F));;
+ result.StrokeBrush = ColorBrush_AlmostDodgerBlue_FF149BD6();
+ result.StrokeDashCap = CompositionStrokeCap.Round;
+ result.StrokeStartCap = CompositionStrokeCap.Round;
+ result.StrokeEndCap = CompositionStrokeCap.Round;
+ result.StrokeMiterLimit = 2F;
+ result.StrokeThickness = 70F;
+ return result;
+ }
+
+ // - PreComp layer: trait
+ // Opacity for layer: Shape Layer 1
+ // Path 1
+ CompositionSpriteShape SpriteShape_12()
+ {
+ // Offset:<256, 256>
+ var result = CreateSpriteShape(PathGeometry_8(), new Matrix3x2(1F, 0F, 0F, 1F, 256F, 256F));;
+ result.StrokeBrush = ColorBrush_AlmostDodgerBlue_FF149BD6();
+ result.StrokeDashCap = CompositionStrokeCap.Round;
+ result.StrokeStartCap = CompositionStrokeCap.Round;
+ result.StrokeEndCap = CompositionStrokeCap.Round;
+ result.StrokeMiterLimit = 2F;
+ result.StrokeThickness = 70F;
+ return result;
+ }
+
+ // Transforms for trait 2 Scale(0.19512,0.19512,0),
+ // RotationDegrees(-45.60599899291992), Offset(160.72198,-142.794,0)
+ ContainerVisual ContainerVisual_00()
+ {
+ var result = _c.CreateContainerVisual();
+ result.Clip = InsetClip_0();
+ result.Size = new Vector2(512F, 512F);
+ // Offset:<346.08496, 113.953125>, Rotation:{X:0 Y:-0 Z:-0.38756385 W:0.9218429},
+ // Scale:<0.19512, 0.19512>
+ result.TransformMatrix = new Matrix4x4(0.136503726F, -0.139422208F, 0F, 0F, 0.139422208F, 0.136503726F, 0F, 0F, 0F, 0F, 0F, 0F, 346.084961F, 113.953125F, 0F, 1F);
+ // Opacity for layer: Shape Layer 1
+ result.Children.InsertAtTop(ShapeVisual_01());
+ return result;
+ }
+
+ // Transforms for trait 2 Scale(0.19512,0.19512,0),
+ // RotationDegrees(-135.2050018310547), Offset(-151.136,-144.29001,0)
+ ContainerVisual ContainerVisual_01()
+ {
+ var result = _c.CreateContainerVisual();
+ result.Clip = InsetClip_0();
+ result.Size = new Vector2(512F, 512F);
+ // Offset:<105.116745, 182.3505>, Rotation:{X:0 Y:0 Z:0.92456263 W:-0.38103005},
+ // Scale:<0.19511999, 0.19511999>
+ result.TransformMatrix = new Matrix4x4(-0.138463438F, -0.137476146F, 0F, 0F, 0.137476146F, -0.138463438F, 0F, 0F, 0F, 0F, 0F, 0F, 105.116745F, 182.350494F, 0F, 1F);
+ // Opacity for layer: Shape Layer 1
+ result.Children.InsertAtTop(ShapeVisual_02());
+ return result;
+ }
+
+ // Transforms for trait 2 Scale(-0.19512,0.19512,0),
+ // RotationDegrees(-45.60599899291992), Offset(-150.465,146.59799,0)
+ ContainerVisual ContainerVisual_02()
+ {
+ var result = _c.CreateContainerVisual();
+ result.Clip = InsetClip_0();
+ result.Size = new Vector2(512F, 512F);
+ // Offset:<104.78787, 331.96097>, Rotation:{X:0.38756385 Y:0.9218429 Z:0 W:0},
+ // Scale:<0.19512, 0.19512>
+ result.TransformMatrix = new Matrix4x4(-0.136503726F, 0.139422208F, 0F, 0F, 0.139422208F, 0.136503726F, 0F, 0F, 0F, 0F, 0F, 0F, 104.787872F, 331.960968F, 0F, 1F);
+ // Opacity for layer: Shape Layer 1
+ result.Children.InsertAtTop(ShapeVisual_03());
+ return result;
+ }
+
+ // Transforms for trait 2 Scale(-0.19512,0.19512,0),
+ // RotationDegrees(-135.2050018310547), Offset(154.86499,150.53,0)
+ ContainerVisual ContainerVisual_03()
+ {
+ var result = _c.CreateContainerVisual();
+ result.Clip = InsetClip_0();
+ result.Size = new Vector2(512F, 512F);
+ // Offset:<340.22446, 406.7827>, Rotation:{X:0.92456263 Y:0.38103005 Z:0 W:0},
+ // Scale:<0.19511999, 0.19511999>
+ result.TransformMatrix = new Matrix4x4(0.138463438F, 0.137476146F, 0F, 0F, 0.137476146F, -0.138463438F, 0F, 0F, 0F, 0F, 0F, 0F, 340.224457F, 406.782715F, 0F, 1F);
+ // Opacity for layer: Shape Layer 1
+ result.Children.InsertAtTop(ShapeVisual_04());
+ return result;
+ }
+
+ // Transforms for firefly Scale(0.3,0.3,0), RotationDegrees(-45.707000732421875),
+ // Offset(140.89401,-105.039,0)
+ ContainerVisual ContainerVisual_04()
+ {
+ var result = _c.CreateContainerVisual();
+ result.Clip = InsetClip_0();
+ result.Size = new Vector2(512F, 512F);
+ // Offset:<288.29068, 152.30118>, Rotation:{X:0 Y:-0 Z:-0.3883762 W:0.92150086},
+ // Scale:<0.3, 0.3>
+ result.TransformMatrix = new Matrix4x4(0.209498361F, -0.214733422F, 0F, 0F, 0.214733422F, 0.209498361F, 0F, 0F, 0F, 0F, 0F, 0F, 288.29068F, 152.301178F, 0F, 1F);
+ // Shape tree root for layer: Shape Layer 1
+ result.Children.InsertAtTop(ShapeVisual_05());
+ return result;
+ }
+
+ // Transforms for firefly Scale(0.2,0.2,0), RotationDegrees(-72.47100067138672),
+ // Offset(103.412994,-105.088,0)
+ ContainerVisual ContainerVisual_05()
+ {
+ var result = _c.CreateContainerVisual();
+ result.Clip = InsetClip_0();
+ result.Size = new Vector2(512F, 512F);
+ // Offset:<295.16965, 184.31367>, Rotation:{X:0 Y:-0 Z:-0.5911056 W:0.8065942},
+ // Scale:<0.2, 0.2>
+ result.TransformMatrix = new Matrix4x4(0.060237702F, -0.190712929F, 0F, 0F, 0.190712929F, 0.060237702F, 0F, 0F, 0F, 0F, 0F, 0F, 295.169647F, 184.313675F, 0F, 1F);
+ // Shape tree root for layer: Shape Layer 1
+ result.Children.InsertAtTop(ShapeVisual_06());
+ return result;
+ }
+
+ // Transforms for firefly Scale(0.2,0.2,0), RotationDegrees(-18.097000122070312),
+ // Offset(144.63501,-66.29201,0)
+ ContainerVisual ContainerVisual_06()
+ {
+ var result = _c.CreateContainerVisual();
+ result.Clip = InsetClip_0();
+ result.Size = new Vector2(512F, 512F);
+ // Offset:<336.0637, 156.94484>, Rotation:{X:0 Y:-0 Z:-0.15727048 W:0.98755556},
+ // Scale:<0.2, 0.2>
+ result.TransformMatrix = new Matrix4x4(0.190106407F, -0.0621253327F, 0F, 0F, 0.0621253327F, 0.190106407F, 0F, 0F, 0F, 0F, 0F, 0F, 336.06369F, 156.944839F, 0F, 1F);
+ // Shape tree root for layer: Shape Layer 1
+ result.Children.InsertAtTop(ShapeVisual_07());
+ return result;
+ }
+
+ // Transforms for trait Scale(0.15,0.15,0), Offset(213.91,2.7919922,0)
+ ContainerVisual ContainerVisual_07()
+ {
+ var result = _c.CreateContainerVisual();
+ result.Clip = InsetClip_0();
+ result.Size = new Vector2(512F, 512F);
+ // Offset:<431.51, 220.392>, Scale:<0.15, 0.15>
+ result.TransformMatrix = new Matrix4x4(0.150000006F, 0F, 0F, 0F, 0F, 0.150000006F, 0F, 0F, 0F, 0F, 0F, 0F, 431.51001F, 220.391998F, 0F, 1F);
+ // Opacity for layer: Shape Layer 1
+ result.Children.InsertAtTop(ShapeVisual_08());
+ return result;
+ }
+
+ // Transforms for trait Scale(0.15,0.15,0), RotationDegrees(-90),
+ // Offset(10.321991,-211.685,0)
+ ContainerVisual ContainerVisual_08()
+ {
+ var result = _c.CreateContainerVisual();
+ result.Clip = InsetClip_0();
+ result.Size = new Vector2(512F, 512F);
+ // Offset:<227.92198, 82.714966>, Rotation:{X:0 Y:0 Z:-0.70710677 W:0.70710677},
+ // Scale:<0.15, 0.15>
+ result.TransformMatrix = new Matrix4x4(-6.55670851E-09F, -0.150000006F, 0F, 0F, 0.150000006F, -6.55670851E-09F, 0F, 0F, 0F, 0F, 0F, 0F, 227.921982F, 82.7149658F, 0F, 1F);
+ // Opacity for layer: Shape Layer 1
+ result.Children.InsertAtTop(ShapeVisual_09());
+ return result;
+ }
+
+ // Transforms for trait Scale(0.15,0.15,0), RotationDegrees(-180),
+ // Offset(-204.35901,-2.725006,0)
+ ContainerVisual ContainerVisual_09()
+ {
+ var result = _c.CreateContainerVisual();
+ result.Clip = InsetClip_0();
+ result.Size = new Vector2(512F, 512F);
+ // Offset:<90.040955, 291.67496>, Rotation:{X:0 Y:0 Z:1 W:4.371139E-08},
+ // Scale:<0.15, 0.15>
+ result.TransformMatrix = new Matrix4x4(-0.150000006F, 1.3113417E-08F, 0F, 0F, -1.3113417E-08F, -0.150000006F, 0F, 0F, 0F, 0F, 0F, 0F, 90.0409546F, 291.674957F, 0F, 1F);
+ // Opacity for layer: Shape Layer 1
+ result.Children.InsertAtTop(ShapeVisual_10());
+ return result;
+ }
+
+ // Transforms for trait Scale(0.15,0.15,0), RotationDegrees(90),
+ // Offset(7.334015,215.10901,0)
+ ContainerVisual ContainerVisual_10()
+ {
+ var result = _c.CreateContainerVisual();
+ result.Clip = InsetClip_0();
+ result.Size = new Vector2(512F, 512F);
+ // Offset:<301.73398, 432.70898>, Rotation:{X:0 Y:0 Z:0.70710677 W:0.70710677},
+ // Scale:<0.15, 0.15>
+ result.TransformMatrix = new Matrix4x4(-6.55670851E-09F, 0.150000006F, 0F, 0F, -0.150000006F, -6.55670851E-09F, 0F, 0F, 0F, 0F, 0F, 0F, 301.733978F, 432.708984F, 0F, 1F);
+ // Opacity for layer: Shape Layer 1
+ result.Children.InsertAtTop(ShapeVisual_11());
+ return result;
+ }
+
+ // The root of the composition.
+ ContainerVisual Root()
+ {
+ if (_root != null) { return _root; }
+ var result = _root = _c.CreateContainerVisual();
+ var propertySet = result.Properties;
+ propertySet.InsertScalar("Progress", 0F);
+ var children = result.Children;
+ // Layer aggregator
+ children.InsertAtTop(ShapeVisual_00());
+ // PreComp layer: trait 2
+ children.InsertAtTop(ContainerVisual_00());
+ // PreComp layer: trait 2
+ children.InsertAtTop(ContainerVisual_01());
+ // PreComp layer: trait 2
+ children.InsertAtTop(ContainerVisual_02());
+ // PreComp layer: trait 2
+ children.InsertAtTop(ContainerVisual_03());
+ // PreComp layer: firefly
+ children.InsertAtTop(ContainerVisual_04());
+ // PreComp layer: firefly
+ children.InsertAtTop(ContainerVisual_05());
+ // PreComp layer: firefly
+ children.InsertAtTop(ContainerVisual_06());
+ // PreComp layer: trait
+ children.InsertAtTop(ContainerVisual_07());
+ // PreComp layer: trait
+ children.InsertAtTop(ContainerVisual_08());
+ // PreComp layer: trait
+ children.InsertAtTop(ContainerVisual_09());
+ // PreComp layer: trait
+ children.InsertAtTop(ContainerVisual_10());
+ return result;
+ }
+
+ CubicBezierEasingFunction CubicBezierEasingFunction_0()
+ {
+ return (_cubicBezierEasingFunction_0 == null)
+ ? _cubicBezierEasingFunction_0 = _c.CreateCubicBezierEasingFunction(new Vector2(0.166999996F, 0.166999996F), new Vector2(0.588F, 0F))
+ : _cubicBezierEasingFunction_0;
+ }
+
+ CubicBezierEasingFunction CubicBezierEasingFunction_1()
+ {
+ return (_cubicBezierEasingFunction_1 == null)
+ ? _cubicBezierEasingFunction_1 = _c.CreateCubicBezierEasingFunction(new Vector2(0.509000003F, 0.00300000003F), new Vector2(0.69599998F, 0.999000013F))
+ : _cubicBezierEasingFunction_1;
+ }
+
+ CubicBezierEasingFunction CubicBezierEasingFunction_2()
+ {
+ return (_cubicBezierEasingFunction_2 == null)
+ ? _cubicBezierEasingFunction_2 = _c.CreateCubicBezierEasingFunction(new Vector2(0.456999987F, 0.063000001F), new Vector2(0.565999985F, 0.999000013F))
+ : _cubicBezierEasingFunction_2;
+ }
+
+ CubicBezierEasingFunction CubicBezierEasingFunction_3()
+ {
+ return (_cubicBezierEasingFunction_3 == null)
+ ? _cubicBezierEasingFunction_3 = _c.CreateCubicBezierEasingFunction(new Vector2(0.166999996F, 0.166999996F), new Vector2(0.572000027F, 0.555999994F))
+ : _cubicBezierEasingFunction_3;
+ }
+
+ CubicBezierEasingFunction CubicBezierEasingFunction_4()
+ {
+ return (_cubicBezierEasingFunction_4 == null)
+ ? _cubicBezierEasingFunction_4 = _c.CreateCubicBezierEasingFunction(new Vector2(0.640999973F, 0.0560000017F), new Vector2(0.833000004F, 0.833000004F))
+ : _cubicBezierEasingFunction_4;
+ }
+
+ CubicBezierEasingFunction CubicBezierEasingFunction_5()
+ {
+ return (_cubicBezierEasingFunction_5 == null)
+ ? _cubicBezierEasingFunction_5 = _c.CreateCubicBezierEasingFunction(new Vector2(0.166999996F, 0.166999996F), new Vector2(0.833000004F, 0.833000004F))
+ : _cubicBezierEasingFunction_5;
+ }
+
+ InsetClip InsetClip_0()
+ {
+ if (_insetClip_0 != null) { return _insetClip_0; }
+ var result = _insetClip_0 = _c.CreateInsetClip();
+ return result;
+ }
+
+ // Layer opacity animation
+ ScalarKeyFrameAnimation OpacityScalarAnimation_1_to_0p3_0()
+ {
+ // Frame 0.
+ if (_opacityScalarAnimation_1_to_0p3_0 != null) { return _opacityScalarAnimation_1_to_0p3_0; }
+ var result = _opacityScalarAnimation_1_to_0p3_0 = CreateScalarKeyFrameAnimation(0F, 1F, StepThenHoldEasingFunction());
+ // Frame 10.
+ result.InsertKeyFrame(0.222222209F, 1F, HoldThenStepEasingFunction());
+ // Frame 16.
+ result.InsertKeyFrame(0.355555534F, 0.921540022F, CubicBezierEasingFunction_3());
+ // Frame 20.
+ result.InsertKeyFrame(0.444444448F, 0.300000012F, CubicBezierEasingFunction_4());
+ return result;
+ }
+
+ // Layer opacity animation
+ ScalarKeyFrameAnimation OpacityScalarAnimation_1_to_0p3_1()
+ {
+ // Frame 0.
+ if (_opacityScalarAnimation_1_to_0p3_1 != null) { return _opacityScalarAnimation_1_to_0p3_1; }
+ var result = _opacityScalarAnimation_1_to_0p3_1 = CreateScalarKeyFrameAnimation(0F, 1F, StepThenHoldEasingFunction());
+ // Frame 7.
+ result.InsertKeyFrame(0.155555546F, 1F, HoldThenStepEasingFunction());
+ // Frame 13.
+ result.InsertKeyFrame(0.288888872F, 0.921540022F, CubicBezierEasingFunction_3());
+ // Frame 17.
+ result.InsertKeyFrame(0.377777785F, 0.300000012F, CubicBezierEasingFunction_4());
+ return result;
+ }
+
+ // TEnd
+ ScalarKeyFrameAnimation TEndScalarAnimation_0_to_1_0()
+ {
+ // Frame 0.
+ if (_tEndScalarAnimation_0_to_1_0 != null) { return _tEndScalarAnimation_0_to_1_0; }
+ var result = _tEndScalarAnimation_0_to_1_0 = CreateScalarKeyFrameAnimation(0F, 0F, StepThenHoldEasingFunction());
+ // Frame 10.
+ result.InsertKeyFrame(0.222222209F, 0F, HoldThenStepEasingFunction());
+ // Frame 19.
+ result.InsertKeyFrame(0.422222227F, 1F, CubicBezierEasingFunction_2());
+ return result;
+ }
+
+ // TEnd
+ ScalarKeyFrameAnimation TEndScalarAnimation_0_to_1_1()
+ {
+ // Frame 0.
+ if (_tEndScalarAnimation_0_to_1_1 != null) { return _tEndScalarAnimation_0_to_1_1; }
+ var result = _tEndScalarAnimation_0_to_1_1 = CreateScalarKeyFrameAnimation(0F, 0F, StepThenHoldEasingFunction());
+ // Frame 7.
+ result.InsertKeyFrame(0.155555546F, 0F, HoldThenStepEasingFunction());
+ // Frame 16.
+ result.InsertKeyFrame(0.355555564F, 1F, CubicBezierEasingFunction_2());
+ return result;
+ }
+
+ // - - Layer aggregator
+ // - Scale:0.6959,0.6959, Offset:<236.888, 240.258>
+ // TrimEnd
+ ScalarKeyFrameAnimation TrimEndScalarAnimation_0_to_1()
+ {
+ // Frame 0.
+ var result = CreateScalarKeyFrameAnimation(0F, 0F, HoldThenStepEasingFunction());
+ // Frame 14.79.
+ result.InsertKeyFrame(0.32868889F, 0F, _c.CreateCubicBezierEasingFunction(new Vector2(0.166999996F, 0F), new Vector2(0.833000004F, 0F)));
+ // Frame 19.79.
+ result.InsertKeyFrame(0.439799994F, 0.319999993F, _c.CreateCubicBezierEasingFunction(new Vector2(0.166999996F, 0.0419999994F), new Vector2(0F, 0.97299999F)));
+ // Frame 24.79.
+ result.InsertKeyFrame(0.550916672F, 1F, _c.CreateCubicBezierEasingFunction(new Vector2(0.828000009F, 0.0109999999F), new Vector2(0.833000004F, 0.833000004F)));
+ return result;
+ }
+
+ // TStart
+ ScalarKeyFrameAnimation TStartScalarAnimation_0_to_1_0()
+ {
+ // Frame 0.
+ if (_tStartScalarAnimation_0_to_1_0 != null) { return _tStartScalarAnimation_0_to_1_0; }
+ var result = _tStartScalarAnimation_0_to_1_0 = CreateScalarKeyFrameAnimation(0F, 0F, StepThenHoldEasingFunction());
+ // Frame 10.
+ result.InsertKeyFrame(0.222222209F, 0F, HoldThenStepEasingFunction());
+ // Frame 13.
+ result.InsertKeyFrame(0.288888872F, 0F, CubicBezierEasingFunction_0());
+ // Frame 19.
+ result.InsertKeyFrame(0.422222227F, 1F, CubicBezierEasingFunction_1());
+ return result;
+ }
+
+ // TStart
+ ScalarKeyFrameAnimation TStartScalarAnimation_0_to_1_1()
+ {
+ // Frame 0.
+ if (_tStartScalarAnimation_0_to_1_1 != null) { return _tStartScalarAnimation_0_to_1_1; }
+ var result = _tStartScalarAnimation_0_to_1_1 = CreateScalarKeyFrameAnimation(0F, 0F, StepThenHoldEasingFunction());
+ // Frame 7.
+ result.InsertKeyFrame(0.155555546F, 0F, HoldThenStepEasingFunction());
+ // Frame 10.
+ result.InsertKeyFrame(0.222222209F, 0F, CubicBezierEasingFunction_0());
+ // Frame 16.
+ result.InsertKeyFrame(0.355555564F, 1F, CubicBezierEasingFunction_1());
+ return result;
+ }
+
+ // Layer aggregator
+ ShapeVisual ShapeVisual_00()
+ {
+ var result = _c.CreateShapeVisual();
+ result.Size = new Vector2(512F, 512F);
+ var shapes = result.Shapes;
+ // Scale:0.8,0.8, Offset:<256, 256>
+ shapes.Add(SpriteShape_00());
+ // Scale:0.6959,0.6959, Offset:<236.888, 240.258>
+ shapes.Add(SpriteShape_01());
+ return result;
+ }
+
+ // PreComp layer: trait 2
+ // Shape tree root for layer: Shape Layer 1
+ ShapeVisual ShapeVisual_01()
+ {
+ if (_shapeVisual_01 != null) { return _shapeVisual_01; }
+ var result = _shapeVisual_01 = _c.CreateShapeVisual();
+ result.Size = new Vector2(512F, 512F);
+ // Offset:<256, 256>
+ result.Shapes.Add(SpriteShape_02());
+ return result;
+ }
+
+ // PreComp layer: trait 2
+ // Shape tree root for layer: Shape Layer 1
+ ShapeVisual ShapeVisual_02()
+ {
+ if (_shapeVisual_02 != null) { return _shapeVisual_02; }
+ var result = _shapeVisual_02 = _c.CreateShapeVisual();
+ result.Size = new Vector2(512F, 512F);
+ // Offset:<256, 256>
+ result.Shapes.Add(SpriteShape_03());
+ return result;
+ }
+
+ // PreComp layer: trait 2
+ // Shape tree root for layer: Shape Layer 1
+ ShapeVisual ShapeVisual_03()
+ {
+ if (_shapeVisual_03 != null) { return _shapeVisual_03; }
+ var result = _shapeVisual_03 = _c.CreateShapeVisual();
+ result.Size = new Vector2(512F, 512F);
+ // Offset:<256, 256>
+ result.Shapes.Add(SpriteShape_04());
+ return result;
+ }
+
+ // PreComp layer: trait 2
+ // Shape tree root for layer: Shape Layer 1
+ ShapeVisual ShapeVisual_04()
+ {
+ if (_shapeVisual_04 != null) { return _shapeVisual_04; }
+ var result = _shapeVisual_04 = _c.CreateShapeVisual();
+ result.Size = new Vector2(512F, 512F);
+ // Offset:<256, 256>
+ result.Shapes.Add(SpriteShape_05());
+ return result;
+ }
+
+ // PreComp layer: firefly
+ // Shape tree root for layer: Shape Layer 1
+ ShapeVisual ShapeVisual_05()
+ {
+ var result = _c.CreateShapeVisual();
+ result.Size = new Vector2(512F, 512F);
+ // Offset:<256, 256>
+ result.Shapes.Add(SpriteShape_06());
+ return result;
+ }
+
+ // PreComp layer: firefly
+ // Shape tree root for layer: Shape Layer 1
+ ShapeVisual ShapeVisual_06()
+ {
+ var result = _c.CreateShapeVisual();
+ result.Size = new Vector2(512F, 512F);
+ // Offset:<256, 256>
+ result.Shapes.Add(SpriteShape_07());
+ return result;
+ }
+
+ // PreComp layer: firefly
+ // Shape tree root for layer: Shape Layer 1
+ ShapeVisual ShapeVisual_07()
+ {
+ var result = _c.CreateShapeVisual();
+ result.Size = new Vector2(512F, 512F);
+ // Offset:<256, 256>
+ result.Shapes.Add(SpriteShape_08());
+ return result;
+ }
+
+ // PreComp layer: trait
+ // Shape tree root for layer: Shape Layer 1
+ ShapeVisual ShapeVisual_08()
+ {
+ if (_shapeVisual_08 != null) { return _shapeVisual_08; }
+ var result = _shapeVisual_08 = _c.CreateShapeVisual();
+ result.Size = new Vector2(512F, 512F);
+ // Offset:<256, 256>
+ result.Shapes.Add(SpriteShape_09());
+ return result;
+ }
+
+ // PreComp layer: trait
+ // Shape tree root for layer: Shape Layer 1
+ ShapeVisual ShapeVisual_09()
+ {
+ if (_shapeVisual_09 != null) { return _shapeVisual_09; }
+ var result = _shapeVisual_09 = _c.CreateShapeVisual();
+ result.Size = new Vector2(512F, 512F);
+ // Offset:<256, 256>
+ result.Shapes.Add(SpriteShape_10());
+ return result;
+ }
+
+ // PreComp layer: trait
+ // Shape tree root for layer: Shape Layer 1
+ ShapeVisual ShapeVisual_10()
+ {
+ if (_shapeVisual_10 != null) { return _shapeVisual_10; }
+ var result = _shapeVisual_10 = _c.CreateShapeVisual();
+ result.Size = new Vector2(512F, 512F);
+ // Offset:<256, 256>
+ result.Shapes.Add(SpriteShape_11());
+ return result;
+ }
+
+ // PreComp layer: trait
+ // Shape tree root for layer: Shape Layer 1
+ ShapeVisual ShapeVisual_11()
+ {
+ if (_shapeVisual_11 != null) { return _shapeVisual_11; }
+ var result = _shapeVisual_11 = _c.CreateShapeVisual();
+ result.Size = new Vector2(512F, 512F);
+ // Offset:<256, 256>
+ result.Shapes.Add(SpriteShape_12());
+ return result;
+ }
+
+ StepEasingFunction HoldThenStepEasingFunction()
+ {
+ if (_holdThenStepEasingFunction != null) { return _holdThenStepEasingFunction; }
+ var result = _holdThenStepEasingFunction = _c.CreateStepEasingFunction();
+ result.IsFinalStepSingleFrame = true;
+ return result;
+ }
+
+ StepEasingFunction StepThenHoldEasingFunction()
+ {
+ if (_stepThenHoldEasingFunction != null) { return _stepThenHoldEasingFunction; }
+ var result = _stepThenHoldEasingFunction = _c.CreateStepEasingFunction();
+ result.IsInitialStepSingleFrame = true;
+ return result;
+ }
+
+ // Offset
+ Vector2KeyFrameAnimation OffsetVector2Animation()
+ {
+ // Frame 0.
+ if (_offsetVector2Animation != null) { return _offsetVector2Animation; }
+ var result = _offsetVector2Animation = CreateVector2KeyFrameAnimation(0F, new Vector2(-181.074005F, -5.41400003F), StepThenHoldEasingFunction());
+ // Frame 24.
+ result.InsertKeyFrame(0.533333302F, new Vector2(-181.074005F, -5.41400003F), HoldThenStepEasingFunction());
+ // Frame 38.
+ result.InsertKeyFrame(0.844444454F, new Vector2(200F, -5.41400003F), _c.CreateCubicBezierEasingFunction(new Vector2(0.166999996F, 0.166999996F), new Vector2(0.666999996F, 1F)));
+ return result;
+ }
+
+ // - - Layer aggregator
+ // - Scale:0.8,0.8, Offset:<256, 256>
+ // Ellipse Path 1.EllipseGeometry
+ // Radius
+ Vector2KeyFrameAnimation RadiusVector2Animation_0()
+ {
+ // Frame 0.
+ var result = CreateVector2KeyFrameAnimation(0F, new Vector2(0F, 0F), HoldThenStepEasingFunction());
+ // Frame 7.
+ result.InsertKeyFrame(0.155555546F, new Vector2(200.512497F, 200.512497F), _c.CreateCubicBezierEasingFunction(new Vector2(0.653999984F, 0.00700000022F), new Vector2(0.976000011F, 0.967999995F)));
+ // Frame 12.
+ result.InsertKeyFrame(0.266666651F, new Vector2(186.350006F, 186.350006F), _c.CreateCubicBezierEasingFunction(new Vector2(0.345999986F, 0F), new Vector2(0.467999995F, 1F)));
+ // Frame 16.
+ result.InsertKeyFrame(0.355555534F, new Vector2(200.512497F, 200.512497F), _c.CreateCubicBezierEasingFunction(new Vector2(0.363999993F, 0.0309999995F), new Vector2(0.375F, 1F)));
+ // Frame 20.
+ result.InsertKeyFrame(0.444444448F, new Vector2(200.512497F, 200.512497F), _c.CreateCubicBezierEasingFunction(new Vector2(0.326999992F, 0F), new Vector2(0.833000004F, 1F)));
+ return result;
+ }
+
+ // Radius
+ Vector2KeyFrameAnimation RadiusVector2Animation_1()
+ {
+ // Frame 0.
+ if (_radiusVector2Animation_1 != null) { return _radiusVector2Animation_1; }
+ var result = _radiusVector2Animation_1 = CreateVector2KeyFrameAnimation(0F, new Vector2(20F, 20F), StepThenHoldEasingFunction());
+ // Frame 24.
+ result.InsertKeyFrame(0.533333302F, new Vector2(20F, 20F), HoldThenStepEasingFunction());
+ // Frame 27.
+ result.InsertKeyFrame(0.599999964F, new Vector2(45F, 45F), _c.CreateCubicBezierEasingFunction(new Vector2(0.166999996F, 0.166999996F), new Vector2(0F, 0.996999979F)));
+ // Frame 38.
+ result.InsertKeyFrame(0.844444454F, new Vector2(9.19699955F, 9.19699955F), _c.CreateCubicBezierEasingFunction(new Vector2(0.574000001F, 0F), new Vector2(0.833000004F, 0.833000004F)));
+ return result;
+ }
+
+ internal Checkmark_AnimatedVisual(
+ Compositor compositor
+ )
+ {
+ _c = compositor;
+ _reusableExpressionAnimation = compositor.CreateExpressionAnimation();
+ Root();
+ }
+
+ public Visual RootVisual => _root;
+ public TimeSpan Duration => TimeSpan.FromTicks(c_durationTicks);
+ public Vector2 Size => new Vector2(512F, 512F);
+ void IDisposable.Dispose() => _root?.Dispose();
+
+ public void CreateAnimations()
+ {
+ _animatedColorBrush_TransparentWhite_to_TransparentWhite.StartAnimation("Color", ColorAnimation_TransparentWhite_to_TransparentWhite(), AnimationController_0());
+ _ellipse_0_0.StartAnimation("Radius", RadiusVector2Animation_0(), AnimationController_0());
+ _ellipse_0_1.StartAnimation("Radius", RadiusVector2Animation_1(), AnimationController_0());
+ _ellipse_0_2.StartAnimation("Radius", RadiusVector2Animation_1(), AnimationController_0());
+ _ellipse_0_3.StartAnimation("Radius", RadiusVector2Animation_1(), AnimationController_0());
+ _pathGeometry_0.StartAnimation("TrimEnd", TrimEndScalarAnimation_0_to_1(), AnimationController_0());
+ _pathGeometry_1.StartAnimation("TStart", TStartScalarAnimation_0_to_1_0(), AnimationController_0());
+ _pathGeometry_1.StartAnimation("TEnd", TEndScalarAnimation_0_to_1_0(), AnimationController_0());
+ _pathGeometry_2.StartAnimation("TStart", TStartScalarAnimation_0_to_1_0(), AnimationController_0());
+ _pathGeometry_2.StartAnimation("TEnd", TEndScalarAnimation_0_to_1_0(), AnimationController_0());
+ _pathGeometry_3.StartAnimation("TStart", TStartScalarAnimation_0_to_1_0(), AnimationController_0());
+ _pathGeometry_3.StartAnimation("TEnd", TEndScalarAnimation_0_to_1_0(), AnimationController_0());
+ _pathGeometry_4.StartAnimation("TStart", TStartScalarAnimation_0_to_1_0(), AnimationController_0());
+ _pathGeometry_4.StartAnimation("TEnd", TEndScalarAnimation_0_to_1_0(), AnimationController_0());
+ _pathGeometry_5.StartAnimation("TStart", TStartScalarAnimation_0_to_1_1(), AnimationController_0());
+ _pathGeometry_5.StartAnimation("TEnd", TEndScalarAnimation_0_to_1_1(), AnimationController_0());
+ _pathGeometry_6.StartAnimation("TStart", TStartScalarAnimation_0_to_1_1(), AnimationController_0());
+ _pathGeometry_6.StartAnimation("TEnd", TEndScalarAnimation_0_to_1_1(), AnimationController_0());
+ _pathGeometry_7.StartAnimation("TStart", TStartScalarAnimation_0_to_1_1(), AnimationController_0());
+ _pathGeometry_7.StartAnimation("TEnd", TEndScalarAnimation_0_to_1_1(), AnimationController_0());
+ _pathGeometry_8.StartAnimation("TStart", TStartScalarAnimation_0_to_1_1(), AnimationController_0());
+ _pathGeometry_8.StartAnimation("TEnd", TEndScalarAnimation_0_to_1_1(), AnimationController_0());
+ _spriteShape_06.StartAnimation("Offset", OffsetVector2Animation(), AnimationController_0());
+ _spriteShape_07.StartAnimation("Offset", OffsetVector2Animation(), AnimationController_0());
+ _spriteShape_08.StartAnimation("Offset", OffsetVector2Animation(), AnimationController_0());
+ _shapeVisual_01.StartAnimation("Opacity", OpacityScalarAnimation_1_to_0p3_0(), AnimationController_0());
+ _shapeVisual_02.StartAnimation("Opacity", OpacityScalarAnimation_1_to_0p3_0(), AnimationController_0());
+ _shapeVisual_03.StartAnimation("Opacity", OpacityScalarAnimation_1_to_0p3_0(), AnimationController_0());
+ _shapeVisual_04.StartAnimation("Opacity", OpacityScalarAnimation_1_to_0p3_0(), AnimationController_0());
+ _shapeVisual_08.StartAnimation("Opacity", OpacityScalarAnimation_1_to_0p3_1(), AnimationController_0());
+ _shapeVisual_09.StartAnimation("Opacity", OpacityScalarAnimation_1_to_0p3_1(), AnimationController_0());
+ _shapeVisual_10.StartAnimation("Opacity", OpacityScalarAnimation_1_to_0p3_1(), AnimationController_0());
+ _shapeVisual_11.StartAnimation("Opacity", OpacityScalarAnimation_1_to_0p3_1(), AnimationController_0());
+ }
+
+ public void DestroyAnimations()
+ {
+ _animatedColorBrush_TransparentWhite_to_TransparentWhite.StopAnimation("Color");
+ _ellipse_0_0.StopAnimation("Radius");
+ _ellipse_0_1.StopAnimation("Radius");
+ _ellipse_0_2.StopAnimation("Radius");
+ _ellipse_0_3.StopAnimation("Radius");
+ _pathGeometry_0.StopAnimation("TrimEnd");
+ _pathGeometry_1.StopAnimation("TStart");
+ _pathGeometry_1.StopAnimation("TEnd");
+ _pathGeometry_2.StopAnimation("TStart");
+ _pathGeometry_2.StopAnimation("TEnd");
+ _pathGeometry_3.StopAnimation("TStart");
+ _pathGeometry_3.StopAnimation("TEnd");
+ _pathGeometry_4.StopAnimation("TStart");
+ _pathGeometry_4.StopAnimation("TEnd");
+ _pathGeometry_5.StopAnimation("TStart");
+ _pathGeometry_5.StopAnimation("TEnd");
+ _pathGeometry_6.StopAnimation("TStart");
+ _pathGeometry_6.StopAnimation("TEnd");
+ _pathGeometry_7.StopAnimation("TStart");
+ _pathGeometry_7.StopAnimation("TEnd");
+ _pathGeometry_8.StopAnimation("TStart");
+ _pathGeometry_8.StopAnimation("TEnd");
+ _spriteShape_06.StopAnimation("Offset");
+ _spriteShape_07.StopAnimation("Offset");
+ _spriteShape_08.StopAnimation("Offset");
+ _shapeVisual_01.StopAnimation("Opacity");
+ _shapeVisual_02.StopAnimation("Opacity");
+ _shapeVisual_03.StopAnimation("Opacity");
+ _shapeVisual_04.StopAnimation("Opacity");
+ _shapeVisual_08.StopAnimation("Opacity");
+ _shapeVisual_09.StopAnimation("Opacity");
+ _shapeVisual_10.StopAnimation("Opacity");
+ _shapeVisual_11.StopAnimation("Opacity");
+ }
+
+ }
+ }
+}
diff --git a/src/SamplesApp/UITests.Shared/UITests.Shared.projitems b/src/SamplesApp/UITests.Shared/UITests.Shared.projitems
index 35fc576c69e2..6dfad9978920 100644
--- a/src/SamplesApp/UITests.Shared/UITests.Shared.projitems
+++ b/src/SamplesApp/UITests.Shared/UITests.Shared.projitems
@@ -5553,6 +5553,7 @@
AnimatedIconPage.xaml
+
BreadcrumbBarPage.xaml
diff --git a/src/Uno.UI.Composition/Composition/Compositor.cs b/src/Uno.UI.Composition/Composition/Compositor.cs
index cfeefd2cc726..64138daab4fe 100644
--- a/src/Uno.UI.Composition/Composition/Compositor.cs
+++ b/src/Uno.UI.Composition/Composition/Compositor.cs
@@ -28,25 +28,41 @@ public Compositor()
// See https://github.com/dotnet/runtime/blob/c52fd37cc835a13bcfa9a64fdfe7520809a75345/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Stopwatch.cs#L157
public long TimestampInTicks => unchecked((long)(Stopwatch.GetTimestamp() * s_tickFrequency));
+ ///
+ /// Creates an instance of AnimationController.
+ ///
+ /// The created AnimationController object.
+ public AnimationController CreateAnimationController() => new(this);
+
+ ///
+ /// Creates an instance of CompositionColorBrush.
+ ///
+ /// Returns the created CompositionColorBrush object.
+ public CompositionColorBrush CreateColorBrush() => new(this);
+
+ ///
+ /// Creates an instance of CompositionColorBrush using the specified color.
+ ///
+ /// The color for the brush to use.
+ /// Returns the created CompositionColorBrush object.
+ public CompositionColorBrush CreateColorBrush(Color color) => new(this)
+ {
+ Color = color
+ };
+
internal static Compositor GetSharedCompositor() => _sharedCompositorLazy.Value;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static CompositionEasingFunction GetDefaultEasingFunction() => _defaultEasingFunction.Value;
- public ContainerVisual CreateContainerVisual()
- => new ContainerVisual(this);
+
+ public ContainerVisual CreateContainerVisual() => new(this);
public SpriteVisual CreateSpriteVisual()
=> new SpriteVisual(this);
- public CompositionColorBrush CreateColorBrush()
- => new CompositionColorBrush(this);
- public CompositionColorBrush CreateColorBrush(Color color)
- => new CompositionColorBrush(this)
- {
- Color = color
- };
+
public ScalarKeyFrameAnimation CreateScalarKeyFrameAnimation()
=> new ScalarKeyFrameAnimation(this);
diff --git a/src/Uno.UI.Composition/Generated/3.0.0.0/Microsoft.UI.Composition/Compositor.cs b/src/Uno.UI.Composition/Generated/3.0.0.0/Microsoft.UI.Composition/Compositor.cs
index 8afa2035912b..eba2e36ab688 100644
--- a/src/Uno.UI.Composition/Generated/3.0.0.0/Microsoft.UI.Composition/Compositor.cs
+++ b/src/Uno.UI.Composition/Generated/3.0.0.0/Microsoft.UI.Composition/Compositor.cs
@@ -173,7 +173,7 @@ public static float MinGlobalPlaybackRate
#endif
// Skipping already declared method Microsoft.UI.Composition.Compositor.CreateRadialGradientBrush()
// Skipping already declared method Microsoft.UI.Composition.Compositor.CreateVisualSurface()
-#if __ANDROID__ || __IOS__ || IS_UNIT_TESTS || __WASM__ || __SKIA__ || __NETSTD_REFERENCE__ || __MACOS__
+#if false
[global::Uno.NotImplemented("__ANDROID__", "__IOS__", "IS_UNIT_TESTS", "__WASM__", "__SKIA__", "__NETSTD_REFERENCE__", "__MACOS__")]
public global::Microsoft.UI.Composition.AnimationController CreateAnimationController()
{
diff --git a/src/Uno.UI/Generated/3.0.0.0/Microsoft.UI.Xaml.Automation.Peers/AnimatedVisualPlayerAutomationPeer.cs b/src/Uno.UI/Generated/3.0.0.0/Microsoft.UI.Xaml.Automation.Peers/AnimatedVisualPlayerAutomationPeer.cs
index 85585e0f9e75..c6556afa7da3 100644
--- a/src/Uno.UI/Generated/3.0.0.0/Microsoft.UI.Xaml.Automation.Peers/AnimatedVisualPlayerAutomationPeer.cs
+++ b/src/Uno.UI/Generated/3.0.0.0/Microsoft.UI.Xaml.Automation.Peers/AnimatedVisualPlayerAutomationPeer.cs
@@ -3,12 +3,12 @@
#pragma warning disable 114 // new keyword hiding
namespace Microsoft.UI.Xaml.Automation.Peers
{
-#if __ANDROID__ || __IOS__ || IS_UNIT_TESTS || __WASM__ || __SKIA__ || __NETSTD_REFERENCE__ || __MACOS__
+#if false
[global::Uno.NotImplemented]
#endif
public partial class AnimatedVisualPlayerAutomationPeer : global::Microsoft.UI.Xaml.Automation.Peers.FrameworkElementAutomationPeer
{
-#if __ANDROID__ || __IOS__ || IS_UNIT_TESTS || __WASM__ || __SKIA__ || __NETSTD_REFERENCE__ || __MACOS__
+#if false
[global::Uno.NotImplemented("__ANDROID__", "__IOS__", "IS_UNIT_TESTS", "__WASM__", "__SKIA__", "__NETSTD_REFERENCE__", "__MACOS__")]
public AnimatedVisualPlayerAutomationPeer(global::Microsoft.UI.Xaml.Controls.AnimatedVisualPlayer owner) : base(owner)
{
diff --git a/src/Uno.UI/Generated/3.0.0.0/Microsoft.UI.Xaml.Controls/AnimatedVisualPlayer.cs b/src/Uno.UI/Generated/3.0.0.0/Microsoft.UI.Xaml.Controls/AnimatedVisualPlayer.cs
index f039a6b3ff28..5aedee6cd138 100644
--- a/src/Uno.UI/Generated/3.0.0.0/Microsoft.UI.Xaml.Controls/AnimatedVisualPlayer.cs
+++ b/src/Uno.UI/Generated/3.0.0.0/Microsoft.UI.Xaml.Controls/AnimatedVisualPlayer.cs
@@ -13,7 +13,7 @@ public partial class AnimatedVisualPlayer : global::Microsoft.UI.Xaml.FrameworkE
// Skipping already declared property PlaybackRate
// Skipping already declared property FallbackContent
// Skipping already declared property AutoPlay
-#if __ANDROID__ || __IOS__ || IS_UNIT_TESTS || __WASM__ || __SKIA__ || __NETSTD_REFERENCE__ || __MACOS__
+#if false
[global::Uno.NotImplemented("__ANDROID__", "__IOS__", "IS_UNIT_TESTS", "__WASM__", "__SKIA__", "__NETSTD_REFERENCE__", "__MACOS__")]
public object Diagnostics
{
@@ -26,7 +26,7 @@ public object Diagnostics
// Skipping already declared property Duration
// Skipping already declared property IsAnimatedVisualLoaded
// Skipping already declared property IsPlaying
-#if __ANDROID__ || __IOS__ || IS_UNIT_TESTS || __WASM__ || __SKIA__ || __NETSTD_REFERENCE__ || __MACOS__
+#if false
[global::Uno.NotImplemented("__ANDROID__", "__IOS__", "IS_UNIT_TESTS", "__WASM__", "__SKIA__", "__NETSTD_REFERENCE__", "__MACOS__")]
public global::Microsoft.UI.Composition.CompositionObject ProgressObject
{
@@ -36,7 +36,7 @@ public object Diagnostics
}
}
#endif
-#if __ANDROID__ || __IOS__ || IS_UNIT_TESTS || __WASM__ || __SKIA__ || __NETSTD_REFERENCE__ || __MACOS__
+#if false
[global::Uno.NotImplemented("__ANDROID__", "__IOS__", "IS_UNIT_TESTS", "__WASM__", "__SKIA__", "__NETSTD_REFERENCE__", "__MACOS__")]
public global::Microsoft.UI.Xaml.Controls.PlayerAnimationOptimization AnimationOptimization
{
@@ -51,7 +51,7 @@ public object Diagnostics
}
#endif
// Skipping already declared property AutoPlayProperty
-#if __ANDROID__ || __IOS__ || IS_UNIT_TESTS || __WASM__ || __SKIA__ || __NETSTD_REFERENCE__ || __MACOS__
+#if false
[global::Uno.NotImplemented("__ANDROID__", "__IOS__", "IS_UNIT_TESTS", "__WASM__", "__SKIA__", "__NETSTD_REFERENCE__", "__MACOS__")]
public static global::Microsoft.UI.Xaml.DependencyProperty DiagnosticsProperty { get; } =
Microsoft.UI.Xaml.DependencyProperty.Register(
@@ -66,7 +66,7 @@ public object Diagnostics
// Skipping already declared property PlaybackRateProperty
// Skipping already declared property SourceProperty
// Skipping already declared property StretchProperty
-#if __ANDROID__ || __IOS__ || IS_UNIT_TESTS || __WASM__ || __SKIA__ || __NETSTD_REFERENCE__ || __MACOS__
+#if false
[global::Uno.NotImplemented("__ANDROID__", "__IOS__", "IS_UNIT_TESTS", "__WASM__", "__SKIA__", "__NETSTD_REFERENCE__", "__MACOS__")]
public static global::Microsoft.UI.Xaml.DependencyProperty AnimationOptimizationProperty { get; } =
Microsoft.UI.Xaml.DependencyProperty.Register(
diff --git a/src/Uno.UI/Generated/3.0.0.0/Microsoft.UI.Xaml.Controls/IAnimatedVisual2.cs b/src/Uno.UI/Generated/3.0.0.0/Microsoft.UI.Xaml.Controls/IAnimatedVisual2.cs
index 20bd9d66a240..4239f050fae1 100644
--- a/src/Uno.UI/Generated/3.0.0.0/Microsoft.UI.Xaml.Controls/IAnimatedVisual2.cs
+++ b/src/Uno.UI/Generated/3.0.0.0/Microsoft.UI.Xaml.Controls/IAnimatedVisual2.cs
@@ -3,15 +3,15 @@
#pragma warning disable 114 // new keyword hiding
namespace Microsoft.UI.Xaml.Controls
{
-#if __ANDROID__ || __IOS__ || IS_UNIT_TESTS || __WASM__ || __SKIA__ || __NETSTD_REFERENCE__ || __MACOS__
+#if false
[global::Uno.NotImplemented]
#endif
public partial interface IAnimatedVisual2 : global::Microsoft.UI.Xaml.Controls.IAnimatedVisual, global::System.IDisposable
{
-#if __ANDROID__ || __IOS__ || IS_UNIT_TESTS || __WASM__ || __SKIA__ || __NETSTD_REFERENCE__ || __MACOS__
+#if false
void CreateAnimations();
#endif
-#if __ANDROID__ || __IOS__ || IS_UNIT_TESTS || __WASM__ || __SKIA__ || __NETSTD_REFERENCE__ || __MACOS__
+#if false
void DestroyAnimations();
#endif
}
diff --git a/src/Uno.UI/Generated/3.0.0.0/Microsoft.UI.Xaml.Controls/IAnimatedVisualSource.cs b/src/Uno.UI/Generated/3.0.0.0/Microsoft.UI.Xaml.Controls/IAnimatedVisualSource.cs
index f4ed6e4e8950..569bc1167611 100644
--- a/src/Uno.UI/Generated/3.0.0.0/Microsoft.UI.Xaml.Controls/IAnimatedVisualSource.cs
+++ b/src/Uno.UI/Generated/3.0.0.0/Microsoft.UI.Xaml.Controls/IAnimatedVisualSource.cs
@@ -8,7 +8,7 @@ namespace Microsoft.UI.Xaml.Controls
#endif
public partial interface IAnimatedVisualSource
{
-#if __ANDROID__ || __IOS__ || IS_UNIT_TESTS || __WASM__ || __SKIA__ || __NETSTD_REFERENCE__ || __MACOS__
+#if false
global::Microsoft.UI.Xaml.Controls.IAnimatedVisual TryCreateAnimatedVisual(global::Microsoft.UI.Composition.Compositor compositor, out object diagnostics);
#endif
}
diff --git a/src/Uno.UI/Generated/3.0.0.0/Microsoft.UI.Xaml.Controls/IAnimatedVisualSource3.cs b/src/Uno.UI/Generated/3.0.0.0/Microsoft.UI.Xaml.Controls/IAnimatedVisualSource3.cs
index 70fe8e842a29..37b022fe537c 100644
--- a/src/Uno.UI/Generated/3.0.0.0/Microsoft.UI.Xaml.Controls/IAnimatedVisualSource3.cs
+++ b/src/Uno.UI/Generated/3.0.0.0/Microsoft.UI.Xaml.Controls/IAnimatedVisualSource3.cs
@@ -3,12 +3,12 @@
#pragma warning disable 114 // new keyword hiding
namespace Microsoft.UI.Xaml.Controls
{
-#if __ANDROID__ || __IOS__ || IS_UNIT_TESTS || __WASM__ || __SKIA__ || __NETSTD_REFERENCE__ || __MACOS__
+#if false
[global::Uno.NotImplemented]
#endif
public partial interface IAnimatedVisualSource3
{
-#if __ANDROID__ || __IOS__ || IS_UNIT_TESTS || __WASM__ || __SKIA__ || __NETSTD_REFERENCE__ || __MACOS__
+#if false
global::Microsoft.UI.Xaml.Controls.IAnimatedVisual2 TryCreateAnimatedVisual(global::Microsoft.UI.Composition.Compositor compositor, out object diagnostics, bool createAnimations);
#endif
}
diff --git a/src/Uno.UI/Generated/3.0.0.0/Microsoft.UI.Xaml.Controls/PlayerAnimationOptimization.cs b/src/Uno.UI/Generated/3.0.0.0/Microsoft.UI.Xaml.Controls/PlayerAnimationOptimization.cs
index 01f972ddd670..85209bb2a1de 100644
--- a/src/Uno.UI/Generated/3.0.0.0/Microsoft.UI.Xaml.Controls/PlayerAnimationOptimization.cs
+++ b/src/Uno.UI/Generated/3.0.0.0/Microsoft.UI.Xaml.Controls/PlayerAnimationOptimization.cs
@@ -3,13 +3,13 @@
#pragma warning disable 114 // new keyword hiding
namespace Microsoft.UI.Xaml.Controls
{
-#if __ANDROID__ || __IOS__ || IS_UNIT_TESTS || __WASM__ || __SKIA__ || __NETSTD_REFERENCE__ || __MACOS__
+#if false
public enum PlayerAnimationOptimization
{
-#if __ANDROID__ || __IOS__ || IS_UNIT_TESTS || __WASM__ || __SKIA__ || __NETSTD_REFERENCE__ || __MACOS__
+#if false
Latency = 0,
#endif
-#if __ANDROID__ || __IOS__ || IS_UNIT_TESTS || __WASM__ || __SKIA__ || __NETSTD_REFERENCE__ || __MACOS__
+#if false
Resources = 1,
#endif
}
diff --git a/src/Uno.UI/Microsoft/UI/Xaml/Controls/AnimatedVisualPlayer/AnimatedVisualPlayer.Properties.cs b/src/Uno.UI/Microsoft/UI/Xaml/Controls/AnimatedVisualPlayer/AnimatedVisualPlayer.Properties.cs
new file mode 100644
index 000000000000..abfd06358c33
--- /dev/null
+++ b/src/Uno.UI/Microsoft/UI/Xaml/Controls/AnimatedVisualPlayer/AnimatedVisualPlayer.Properties.cs
@@ -0,0 +1,205 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See LICENSE in the project root for license information.
+// MUX Reference src\controls\dev\Generated\AnimatedVisualPlayer.properties.cpp, tag winui3/release/1.6.3, commit 66d24dfff
+
+using System;
+using Microsoft.UI.Xaml.Media;
+
+namespace Microsoft/* UWP don't rename */.UI.Xaml.Controls;
+
+partial class AnimatedVisualPlayer
+{
+ ///
+ /// Gets or sets a value that specifies how animations are cached when the AnimatedVisualPlayer is idle (when PlayAsync is not active).
+ ///
+ public PlayerAnimationOptimization AnimationOptimization
+ {
+ get => (PlayerAnimationOptimization)GetValue(AnimationOptimizationProperty);
+ set => SetValue(AnimationOptimizationProperty, value);
+ }
+
+ ///
+ /// Identifies the AnimationOptimization dependency property.
+ ///
+ public static DependencyProperty AnimationOptimizationProperty { get; } =
+ DependencyProperty.Register(
+ nameof(AnimationOptimization),
+ typeof(PlayerAnimationOptimization),
+ typeof(AnimatedVisualPlayer),
+ new FrameworkPropertyMetadata(
+ PlayerAnimationOptimization.Latency,
+ (sender, args) => ((AnimatedVisualPlayer)sender).OnAnimationOptimizationPropertyChanged(args));
+
+ ///
+ /// Gets or sets a value that indicates whether an animated visual plays immediately when it is loaded.
+ ///
+ public bool AutoPlay
+ {
+ get => (bool)GetValue(AutoPlayProperty);
+ set => SetValue(AutoPlayProperty, value);
+ }
+
+ ///
+ /// Identifies the AutoPlay dependency property.
+ ///
+ public static DependencyProperty AutoPlayProperty { get; } =
+ DependencyProperty.Register(
+ nameof(AutoPlay),
+ typeof(bool),
+ typeof(AnimatedVisualPlayer),
+ new FrameworkPropertyMetadata(
+ true,
+ (sender, args) => ((AnimatedVisualPlayer)sender).OnAutoPlayPropertyChanged(args)));
+
+ ///
+ /// Gets optional diagnostics information about the last attempt to load an animated visual.
+ ///
+ public object Diagnostics
+ {
+ get => GetValue(DiagnosticsProperty);
+ private set => SetValue(DiagnosticsProperty, value);
+ }
+
+ ///
+ /// Identifies the Diagnostics dependency property.
+ ///
+ public static DependencyProperty DiagnosticsProperty { get; } =
+ DependencyProperty.Register(
+ nameof(Diagnostics),
+ typeof(object),
+ typeof(AnimatedVisualPlayer),
+ new FrameworkPropertyMetadata(null));
+
+ ///
+ /// Gets the duration of the the currently loaded animated visual, or TimeSpan.Zero if no animated visual is loaded.
+ ///
+ public TimeSpan Duration
+ {
+ get => (TimeSpan)GetValue(DurationProperty);
+ private set => SetValue(DurationProperty, value);
+ }
+
+ ///
+ /// Identifies the Duration dependency property.
+ ///
+ public static DependencyProperty DurationProperty { get; } =
+ DependencyProperty.Register(
+ nameof(Duration),
+ typeof(TimeSpan),
+ typeof(AnimatedVisualPlayer),
+ new FrameworkPropertyMetadata(default(TimeSpan)));
+
+ ///
+ /// Gets or sets content to display if an animated visual fails to load.
+ ///
+ public DataTemplate FallbackContent
+ {
+ get => (DataTemplate)GetValue(FallbackContentProperty);
+ set => SetValue(FallbackContentProperty, value);
+ }
+
+ ///
+ /// Identifies the FallbackContent dependency property.
+ ///
+ public static DependencyProperty FallbackContentProperty { get; } =
+ DependencyProperty.Register(
+ nameof(FallbackContent),
+ typeof(DataTemplate),
+ typeof(AnimatedVisualPlayer),
+ new FrameworkPropertyMetadata(
+ null,
+ (sender, args) => ((AnimatedVisualPlayer)sender).OnFallbackContentPropertyChanged(args)));
+
+ ///
+ /// Gets a value that indicates whether an animated visual is loaded.
+ ///
+ public bool IsAnimatedVisualLoaded
+ {
+ get => (bool)GetValue(IsAnimatedVisualLoadedProperty);
+ private set => SetValue(IsAnimatedVisualLoadedProperty, value);
+ }
+
+ ///
+ /// Identifies the IsAnimatedVisualLoaded dependency property.
+ ///
+ public static DependencyProperty IsAnimatedVisualLoadedProperty { get; } =
+ DependencyProperty.Register(nameof(IsAnimatedVisualLoaded), typeof(bool), typeof(AnimatedVisualPlayer), new FrameworkPropertyMetadata(false));
+
+ ///
+ /// Gets a value that indicates whether an animated visual is loaded and a play is underway.
+ ///
+ public bool IsPlaying => (bool)GetValue(IsPlayingProperty);
+
+ ///
+ /// Identifies the IsPlaying dependency property.
+ ///
+ public static DependencyProperty IsPlayingProperty { get; } =
+ DependencyProperty.Register(
+ nameof(IsPlaying),
+ typeof(bool),
+ typeof(AnimatedVisualPlayer),
+ new FrameworkPropertyMetadata(false));
+
+ ///
+ /// Gets or sets the rate at which the animation plays.
+ ///
+ public double PlaybackRate
+ {
+ get => (double)GetValue(PlaybackRateProperty);
+ set => SetValue(PlaybackRateProperty, value);
+ }
+
+ ///
+ /// Identifies the PlaybackRate dependency property.
+ ///
+ public static DependencyProperty PlaybackRateProperty { get; } =
+ DependencyProperty.Register(
+ nameof(PlaybackRate),
+ typeof(double),
+ typeof(AnimatedVisualPlayer),
+ new FrameworkPropertyMetadata(
+ 1.0,
+ (sender, args) => ((AnimatedVisualPlayer)sender).OnPlaybackRatePropertyChanged(args)));
+
+ ///
+ /// Gets or sets the provider of the animated visual for the player.
+ ///
+ public IAnimatedVisualSource Source
+ {
+ get => (IAnimatedVisualSource)GetValue(SourceProperty);
+ set => SetValue(SourceProperty, value);
+ }
+
+ ///
+ /// Identifies the Source dependency property.
+ ///
+ public static DependencyProperty SourceProperty { get; } =
+ DependencyProperty.Register(
+ nameof(Source),
+ typeof(IAnimatedVisualSource),
+ typeof(AnimatedVisualPlayer),
+ new FrameworkPropertyMetadata(
+ null,
+ (sender, args) => ((AnimatedVisualPlayer)sender).OnSourcePropertyChanged(args)));
+
+ ///
+ /// Gets or sets a value that describes how an animated visual should be stretched to fill the destination rectangle.
+ ///
+ public Stretch Stretch
+ {
+ get => (Stretch)GetValue(StretchProperty);
+ set => SetValue(StretchProperty, value);
+ }
+
+ ///
+ /// Identifies the Stretch dependency property.
+ ///
+ public static DependencyProperty StretchProperty { get; } =
+ DependencyProperty.Register(
+ nameof(Stretch),
+ typeof(Stretch),
+ typeof(AnimatedVisualPlayer),
+ new FrameworkPropertyMetadata(
+ Stretch.Uniform,
+ (sender, args) => ((AnimatedVisualPlayer)sender).OnStretchPropertyChanged(args)));
+}
diff --git a/src/Uno.UI/Microsoft/UI/Xaml/Controls/AnimatedVisualPlayer/AnimatedVisualPlayer.cs b/src/Uno.UI/Microsoft/UI/Xaml/Controls/AnimatedVisualPlayer/AnimatedVisualPlayer.cs
new file mode 100644
index 000000000000..cc36d59149c0
--- /dev/null
+++ b/src/Uno.UI/Microsoft/UI/Xaml/Controls/AnimatedVisualPlayer/AnimatedVisualPlayer.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Microsoft/* UWP don't rename */.UI.Xaml.Controls;
+
+///
+/// An element that displays and controls an IAnimatedVisual.
+///
+public partial class AnimatedVisualPlayer : FrameworkElement
+{
+}
diff --git a/src/Uno.UI/Microsoft/UI/Xaml/Controls/AnimatedVisualPlayer/AnimatedVisualPlayer.h.mux.cs b/src/Uno.UI/Microsoft/UI/Xaml/Controls/AnimatedVisualPlayer/AnimatedVisualPlayer.h.mux.cs
new file mode 100644
index 000000000000..0215f3cdfe4f
--- /dev/null
+++ b/src/Uno.UI/Microsoft/UI/Xaml/Controls/AnimatedVisualPlayer/AnimatedVisualPlayer.h.mux.cs
@@ -0,0 +1,68 @@
+using System;
+using System.Numerics;
+using System.Threading.Tasks;
+using Microsoft.UI.Composition;
+using Uno.Disposables;
+
+namespace Microsoft/* UWP don't rename */.UI.Xaml.Controls;
+
+partial class AnimatedVisualPlayer
+{
+ internal partial class AnimationPlay : TaskCompletionSource
+ {
+ private AnimatedVisualPlayer m_owner;
+ private readonly float m_fromProgress;
+ private readonly float m_toProgress;
+ private readonly bool m_looped;
+ private TimeSpan m_playDuration;
+
+ private AnimationController m_controller;
+ private bool m_isPaused;
+ private bool m_isPausedBecauseHidden;
+ private long m_batchCompletedToken;
+ CompositionScopedBatch m_batch;
+ }
+
+ //
+ // Initialized by the constructor.
+ //
+ // A Visual used for clipping and for parenting of m_animatedVisualRoot.
+ private SpriteVisual m_rootVisual;
+ // The property set that contains the Progress property that will be used to
+ // set the progress of the animated visual.
+ private CompositionPropertySet m_progressPropertySet;
+ // Revokers for events that we are subscribed to.
+ private SerialDisposable m_suspendingRevoker = new();
+ private SerialDisposable m_resumingRevoker = new();
+ private SerialDisposable m_xamlRootChangedRevoker = new();
+ private SerialDisposable m_loadedRevoker = new();
+ private SerialDisposable m_unloadedRevoker = new();
+
+ //
+ // Player mutable state state.
+ //
+ private IAnimatedVisual m_animatedVisual;
+ // The native size of the current animated visual. Only valid if m_animatedVisual is not nullptr.
+ private Vector2 m_animatedVisualSize;
+ private Visual m_animatedVisualRoot;
+ private int m_playAsyncVersion;
+ private double m_currentPlayFromProgress;
+ // The play that will be stopped when Stop() is called.
+ private AnimationPlay m_nowPlaying;
+ private SerialDisposable m_dynamicAnimatedVisualInvalidatedRevoker;
+
+ // Set true if an animated visual has failed to load and set false the next time an animated
+ // visual loads with non-null content. When this is true the fallback content (if any) will
+ // be displayed.
+ private bool m_isFallenBack;
+
+ // Set true when FrameworkElement::Unloaded is fired, then set false when FrameworkElement::Loaded is fired.
+ // This is used to differentiate the first Loaded event (when the element has never been
+ // unloaded) from later Loaded events.
+ private bool m_isUnloaded;
+
+ private bool m_isAnimationsCreated;
+ private uint m_createAnimationsCounter = 0;
+
+ private bool m_isHostVisible;
+}
diff --git a/src/Uno.UI/Microsoft/UI/Xaml/Controls/AnimatedVisualPlayer/AnimatedVisualPlayer.mux.cs b/src/Uno.UI/Microsoft/UI/Xaml/Controls/AnimatedVisualPlayer/AnimatedVisualPlayer.mux.cs
new file mode 100644
index 000000000000..4522ba73876e
--- /dev/null
+++ b/src/Uno.UI/Microsoft/UI/Xaml/Controls/AnimatedVisualPlayer/AnimatedVisualPlayer.mux.cs
@@ -0,0 +1,1154 @@
+using System;
+using System.Numerics;
+using Microsoft.UI.Composition;
+using Microsoft.UI.Xaml.Automation.Peers;
+using Microsoft.UI.Xaml.Hosting;
+using Microsoft.UI.Xaml.Media;
+using Uno.Disposables;
+using Uno.UI.DataBinding;
+using Windows.Foundation;
+using static Microsoft/* UWP don't rename */.UI.Xaml.Controls._Tracing;
+
+namespace Microsoft/* UWP don't rename */.UI.Xaml.Controls;
+
+partial class AnimatedVisualPlayer
+{
+ partial class AnimationPlay
+ {
+ private AnimationPlay(
+ AnimatedVisualPlayer owner,
+ float fromProgress,
+ float toProgress,
+ bool looped)
+ {
+ // Save the play duration as time.
+ m_owner = owner;
+ m_fromProgress = fromProgress;
+
+ m_toProgress = toProgress;
+
+ m_looped = looped;
+ // Save the play duration as time.
+ // If toProgress is less than fromProgress the animation will wrap around,
+ // so the time is calculated as fromProgress..end + start..toProgress.
+ var durationAsProgress = fromProgress > toProgress ? ((1 - fromProgress) + toProgress) : (toProgress - fromProgress);
+ // NOTE: this relies on the Duration() being set on the owner.
+ m_playDuration = std.chrono.duration_cast(m_owner.Duration() * durationAsProgress);
+ }
+
+ internal internalfloat FromProgress()
+ {
+ return m_fromProgress;
+ }
+
+ // REENTRANCE SIDE EFFECT: IsPlaying DP.
+ internal void Start()
+ {
+ //// m_owner should be alive since we are calling Start() from owner only
+ //MUX_ASSERT(m_owner);
+ //MUX_ASSERT(IsCurrentPlay());
+ //MUX_ASSERT(!m_controller);
+
+ //// If the duration is really short (< 20ms) don't bother trying to animate.
+ //if (m_playDuration < TimeSpan{ 20ms })
+ // {
+ // // Nothing to play. Jump to the from position.
+ // // This will have the side effect of completing this play immediately.
+ // m_owner.SetProgress(m_fromProgress);
+ // // Do not do anything after calling SetProgress()... the AnimationPlay is destructed already.
+ // return;
+ //}
+
+ // else
+ //{
+ // // Create an animation to drive the Progress property.
+ // var compositor = m_owner.m_progressPropertySet.Compositor();
+ // var animation = compositor.CreateScalarKeyFrameAnimation();
+ // animation.Duration(m_playDuration);
+ // var linearEasing = compositor.CreateLinearEasingFunction();
+
+ // // Play from fromProgress.
+ // animation.InsertKeyFrame(0, m_fromProgress);
+
+ // // from > to is treated as playing from fromProgress to the end, then playing from
+ // // the beginning to toProgress. Insert extra keyframes to do that.
+ // if (m_fromProgress > m_toProgress)
+ // {
+ // // Play to the end.
+ // var timeToEnd = (1 - m_fromProgress) / ((1 - m_fromProgress) + m_toProgress);
+ // animation.InsertKeyFrame(timeToEnd, 1, linearEasing);
+ // // Jump to the beginning.
+ // animation.InsertKeyFrame(.nextafterf(timeToEnd, 1), 0, linearEasing);
+ // }
+
+ // // Play to toProgress
+ // animation.InsertKeyFrame(1, m_toProgress, linearEasing);
+
+ // if (m_looped)
+ // {
+ // animation.IterationBehavior(AnimationIterationBehavior.Forever);
+ // }
+ // else
+ // {
+ // animation.IterationBehavior(AnimationIterationBehavior.Count);
+ // animation.IterationCount(1);
+ // }
+
+ // // Create a batch so that we can know when the animation finishes. This only
+ // // works for non-looping animations (the batch completes immediately
+ // // for looping animations).
+ // m_batch = m_looped
+ // ? null
+ // : compositor.CreateScopedBatch(CompositionBatchTypes.Animation);
+
+ // // Start the animation and get the controller.
+ // m_owner.m_progressPropertySet.StartAnimation("Progress", animation);
+
+ // m_controller = m_owner.m_progressPropertySet.TryGetAnimationController("Progress");
+
+ // if (m_isPaused || m_isPausedBecauseHidden)
+ // {
+ // // The play was paused before it was started.
+ // m_controller.Pause();
+ // }
+
+ // // Set the playback rate.
+ // var playbackRate = (float)(m_owner.PlaybackRate());
+ // m_controller.PlaybackRate(playbackRate);
+
+ // if (playbackRate < 0)
+ // {
+ // // Play from end to beginning if playing in reverse.
+ // m_controller.Progress(1);
+ // }
+
+ // if (m_batch)
+ // {
+ // std.weak_ptr me_weak = m_owner.m_nowPlaying;
+ // // Subscribe to the batch completed event.
+ // m_batchCompletedToken = m_batch.Completed([me_weak](object &, CompositionBatchCompletedEventArgs &)
+
+ // {
+ // var me = me_weak.lock () ;
+
+ // if (!me)
+ // {
+ // return;
+ // }
+
+ // if (me.m_owner)
+ // {
+ // // If optimization is set to Resources - destroy animations immediately after player stops.
+ // if (me.m_owner.AnimationOptimization() == PlayerAnimationOptimization.Resources)
+ // {
+ // me.m_owner.DestroyAnimations();
+ // }
+ // }
+
+ // // Complete the play when the batch completes.
+ // //
+ // // The "this" pointer is guaranteed to be valid because:
+ // // 1) The AnimationPlay (this) is kept alive by a reference from m_owner.m_nowPlaying that
+ // // is only reset by a call to the AnimationPlay.Complete() method.
+ // // 2) Before m_owner.m_nowPlaying is reset in AnimationPlay.Complete(),
+ // // the m_batch.Completed event is unsubscribed, guaranteeing that this lambda
+ // // will not run after AnimationPlay.Complete() has been called.
+ // // 3) To handle AnimatedVisualPlayer shutdown, AnimationPlay.Complete() is called when
+ // // the AnimatedVisualPlayer is unloaded, so that the AnimationPlay cannot outlive
+ // // the AnimatedVisualPlayer.
+ // //
+ // // Do not do anything after calling Complete()... the object is destructed already.
+ // me.Complete();
+ // });
+ // // Indicate that nothing else is going into the batch.
+ // m_batch.End();
+ // }
+
+ // // WARNING - this may cause reentrance.
+ // m_owner.IsPlaying(true);
+ //}
+ }
+
+ internal bool IsCurrentPlay()
+ {
+ return m_owner is not null && m_owner.m_nowPlaying == this;
+ }
+
+ internal void SetPlaybackRate(float value)
+ {
+ if (m_controller is not null)
+ {
+ m_controller.PlaybackRate = value;
+ }
+ }
+
+ // Called when the animation is becoming hidden.
+ internal void OnHiding()
+ {
+ if (!m_isPausedBecauseHidden)
+ {
+ m_isPausedBecauseHidden = true;
+
+ // Pause the animation if it's not already paused.
+ // This is necessary to ensure that the animation doesn't
+ // keep running and causing DWM to wake up when the animation
+ // cannot be seen.
+ if (m_controller is not null)
+ {
+ if (!m_isPaused)
+ {
+ m_controller.Pause();
+ }
+ }
+ }
+ }
+
+ // Called when the animation was hidden but is now becoming visible.
+ internal void OnUnhiding()
+ {
+ if (m_isPausedBecauseHidden)
+ {
+ m_isPausedBecauseHidden = false;
+
+ // Resume the animation that was paused due to the app being suspended.
+ if (m_controller is not null)
+ {
+ if (!m_isPaused)
+ {
+ m_controller.Resume();
+ }
+ }
+ }
+ }
+
+ internal void Pause()
+ {
+ m_isPaused = true;
+
+ if (m_controller is not null)
+ {
+ if (!m_isPausedBecauseHidden)
+ {
+ m_controller.Pause();
+ }
+ }
+ }
+
+ internal void Resume()
+ {
+ m_isPaused = false;
+
+ if (m_controller is not null)
+ {
+ if (!m_isPausedBecauseHidden)
+ {
+ m_controller.Resume();
+ }
+ }
+ }
+
+ // Completes the play, and unregisters it from the player.
+ // Called on the UI thread from:
+ // * SetProgress
+ // - when any property is set that invalidates the current play, such as starting a new play or setting progress.
+ // * CompositionScopedBatch.BatchCompleted event
+ // - when a non-looping animation gets to it final keyframe.
+ // * ~AnimatedVisualPlayer - in owner's destructor
+ // Do not do anything with this object after calling here... the object is destructed already.
+ // REENTRANCE SIDE EFFECT: IsPlaying DP.
+ internal void Complete()
+ {
+ //
+ // NOTEs about lifetime (i.e. why we can trust that m_owner is still valid)
+ // The AnimatedVisualPlayer will be alive as the time when Complete() is called. This
+ // is because:
+ // 1. There is only ever one un-completed AnimationPlay. When a new play
+ // is started the current play is completed.
+ // 2. An uncompleted AnimationPlay will be completed when the AnimatedVisualPlayer
+ // is unloaded or the AnimatedVisualPlayer destructor is run.
+ // 3. If the call to here is from SetProgress
+ // then the AnimatedVisualPlayer is obviously still alive.
+ // 4. If the batch completion event fires the AnimatedVisualPlayer must still be
+ // alive because if it had been unloaded or destroyedComplete() would have been
+ // called during the unload or from the destructor which would have unsubscribed
+ // from the batch completion event.
+ //
+
+ // Grab a copy of the pointer so the object stays alive until the method returns.
+ // We need to copy pointer only in case if owner is alive,
+ // because we are resetting only owner's pointer in this method
+ std.AnimationPlay me;
+ if (m_owner)
+ {
+ me = m_owner.m_nowPlaying;
+ }
+
+ // Unsubscribe from batch.Completed.
+ if (m_batch)
+ {
+ m_batch.Completed(m_batchCompletedToken);
+ m_batchCompletedToken = { 0 };
+ }
+
+ // If this play is the one that is currently associated with the player,
+ // disassociate it from the player and update the player's IsPlaying property.
+ if (m_owner && IsCurrentPlay())
+ {
+ // Disconnect this AnimationPlay from the player.
+ m_owner.m_nowPlaying.reset();
+
+ // Update the IsPlaying state. Note that this is done
+ // after being disconnected so that this AnimationPlay won't be
+ // reentered, however the AnimatedVisualPlayer may be reentered.
+ // WARNING - this may cause reentrance.
+ m_owner.IsPlaying(false);
+ }
+
+ // Allow anything waiting on this awaitable to complete.
+ // This will not cause reentrance because this signals an event and does not call out.
+ CompleteAwaits();
+ }
+
+ // This is called in AnimatedVisualPlayer destructor to prevent
+ // AnimationPlay accessing owner in case if it lives longer
+ internal void ResetOwner()
+ {
+ m_owner = null;
+ }
+ }
+
+
+ public AnimatedVisualPlayer()
+ {
+ //__RP_Marker_ClassById(RuntimeProfiler.ProfId_AnimatedVisualPlayer);
+
+ // EnsureProperties();
+
+ var compositor = ElementCompositionPreview.GetElementVisual(this).Compositor;
+ m_rootVisual = compositor.CreateSpriteVisual();
+ m_progressPropertySet = m_rootVisual.Properties;
+
+ // Set an initial value for the Progress property.
+ m_progressPropertySet.InsertScalar("Progress", 0);
+
+ // Ensure the content can't render outside the bounds of the element.
+ m_rootVisual.Clip = compositor.CreateInsetClip();
+
+ // Subscribe to suspending, resuming, and visibility events so we can pause the animation if it's
+ // definitely not visible.
+ m_suspendingRevoker = Application.Current.Suspending(auto_revoke, [weakThis{ get_weak() }](
+ var /*sender*/,
+ var /*e*/)
+
+ {
+ if (var strongThis = weakThis)
+ {
+ strongThis.OnHiding();
+ }
+ });
+
+ m_resumingRevoker = Application.Current.Resuming(auto_revoke, [weakThis{ get_weak() }](
+ var /*sender*/,
+ var /*e*/)
+
+ {
+ if (var strongThis = weakThis)
+ {
+ if (CoreWindow.GetForCurrentThread().Visible())
+ {
+ strongThis.OnUnhiding();
+ }
+ }
+ });
+
+ // Subscribe to the Loaded/Unloaded events to ensure we unload the animated visual then reload
+ // when it is next loaded.
+ Loaded += OnLoaded;
+ m_loadedRevoker.Disposable = Disposable.Create(() => Loaded -= OnLoaded);
+ Unloaded += OnUnloaded;
+ m_unloadedRevoker.Disposable = Disposable.Create(() => Unloaded -= OnUnloaded);
+ }
+
+ ~AnimatedVisualPlayer()
+ {
+ // TODO:MZ: Move to unloaded
+ // Ensure any outstanding play is stopped.
+ if (m_nowPlaying)
+ {
+ // To stop and destroy m_nowPlaying we need to call Complete()
+ // But we need to detach us (m_owner) from m_nowPlaying first so that AnimationPlay
+ // will not try to call us (m_owner), since we are already in the destructor
+ m_nowPlaying.ResetOwner();
+ m_nowPlaying.Complete();
+ }
+ }
+
+ private void OnLoaded(object sender, RoutedEventArgs args)
+ {
+ //
+ // Do initialization here rather than in the ructor because when the
+ // ructor is called the outer object is not fully initialized.
+ //
+ // Any initialization that can call back into the outer object MUST be
+ // done here rather than the ructor.
+ //
+ // Other initialization can be done here too, so rather than having to
+ // guess whether an initialization call calls back into the outer, just
+ // put most of the initialization here.
+ //
+
+ // Calls back into the outer - must be done OnLoaded rather than in the ructor.
+ ElementCompositionPreview.SetElementChildVisual(this, m_rootVisual);
+
+ // Set the background for AnimatedVisualPlayer to ensure it will be visible to
+ // hit-testing. XAML does not hit test anything that has a null background.
+ // Set here rather than in the ructor so we don't have to worry about it
+ // calling back into the outer.
+ Background = new SolidColorBrush(Colors.Transparent);
+
+ if (m_isUnloaded)
+ {
+ // Reload the content.
+ // Only do this if the element had been previously unloaded so that the
+ // first Loaded event doesn't overwrite any state that was set before
+ // the event was fired.
+ UpdateContent();
+ m_isUnloaded = false;
+ }
+
+ // TODO:MZ: Avoid leaking (XamlRoot.Changed should be a weak event!)
+ var weakThis = WeakReferencePool.RentSelfWeakReference(this);
+ void OnXamlRootChanged(object sender, object args)
+ {
+ if (weakThis.IsAlive && weakThis.Target is AnimatedVisualPlayer strongThis)
+ {
+ var xamlRoot = strongThis.XamlRoot;
+ bool hostVisibility = xamlRoot.IsHostVisible;
+ if (hostVisibility != strongThis.m_isHostVisible)
+ {
+ strongThis.m_isHostVisible = hostVisibility;
+ if (hostVisibility)
+ {
+ // Transition from invisible to visible.
+ strongThis.OnUnhiding();
+ }
+ else
+ {
+ // Transition from visible to invisible.
+ strongThis.OnHiding();
+ }
+
+ }
+ }
+ }
+
+ XamlRoot.Changed += OnXamlRootChanged;
+ m_xamlRootChangedRevoker.Disposable = Disposable.Create(() => XamlRoot.Changed -= OnXamlRootChanged);
+ }
+
+ private void OnUnloaded(object sender, RoutedEventArgs args)
+ {
+ // There is an anomaly in the Loading/Loaded/Unloaded events that can cause an Unloaded event to
+ // fire when the element is in the tree. When this happens, we end up unlaoding our content
+ // and not displaying it. Unfortunately, we can't fix this until at least version 2.0 so for
+ // for now we will work around it (as we have suggested to customers to do), by checking to see
+ // if we are actually unloaded before removing our content.
+ if (!IsLoaded)
+ {
+ m_isUnloaded = true;
+ // Remove any content. If we get reloaded the content will get reloaded.
+ UnloadContent();
+ }
+ }
+
+ private void OnHiding()
+ {
+ if (m_nowPlaying)
+ {
+ m_nowPlaying.OnHiding();
+ }
+ }
+
+ private void OnUnhiding()
+ {
+ if (m_nowPlaying)
+ {
+ m_nowPlaying.OnUnhiding();
+ }
+ }
+
+ // Public API.
+ protected override AutomationPeer OnCreateAutomationPeer() => new AnimatedVisualPlayerAutomationPeer(this);
+
+ // Public API.
+ // Overrides FrameworkElement.MeasureOverride. Returns the size that is needed to display the
+ // animated visual within the available size and respecting the Stretch property.
+ protected override Size MeasureOverride(Size availableSize)
+ {
+ if (m_isFallenBack && Children.Size > 0)
+ {
+ // We are showing the fallback content due to a failure to load an animated visual.
+ // Tell the content to measure itself.
+ Children[0].Measure(availableSize);
+ // Our size is whatever the fallback content desires.
+ return Children[0].DesiredSize;
+ }
+
+ if ((!m_animatedVisualRoot) || (m_animatedVisualSize == float2.zero()))
+ {
+ return { 0, 0 };
+ }
+
+ switch (Stretch)
+ {
+ case Stretch.None:
+ // No scaling will be done. Measured size is the smallest of each dimension.
+ return { std.min(m_animatedVisualSize.x, availableSize.Width), std.min(m_animatedVisualSize.y, availableSize.Height) };
+ case Stretch.Fill:
+ // Both height and width will be scaled to fill the available space.
+ if (availableSize.Width != std.numeric_limits.infinity() && availableSize.Height != std.numeric_limits.infinity())
+ {
+ // We will scale both dimensions to fill all available space.
+ return availableSize;
+ }
+ // One of the dimensions is infinite and we can't fill infinite dimensions, so
+ // fall back to Uniform so at least the non-infinite dimension will be filled.
+ break;
+ case Stretch.UniformToFill:
+ // Height and width will be scaled by the same amount such that there is no space
+ // around the edges.
+ if (availableSize.Width != std.numeric_limits.infinity() && availableSize.Height != std.numeric_limits.infinity())
+ {
+ // Scale so there is no space around the edge.
+ var widthScale = availableSize.Width / m_animatedVisualSize.x;
+ var heightScale = availableSize.Height / m_animatedVisualSize.y;
+ var measuredSize = (heightScale < widthScale)
+ ? Size{ availableSize.Width, m_animatedVisualSize.y* widthScale }
+ : Size{ m_animatedVisualSize.x* heightScale, availableSize.Height };
+
+ // Clip the size to the available size.
+ measuredSize = Size{
+ std.min(measuredSize.Width, availableSize.Width),
+ std.min(measuredSize.Height, availableSize.Height)
+
+ };
+
+ return measuredSize;
+ }
+ // One of the dimensions is infinite and we can't fill infinite dimensions, so
+ // fall back to Uniform so at least the non-infinite dimension will be filled.
+ break;
+ } // end switch
+
+ // Uniform scaling.
+ // Scale so that one dimension fits exactly and no dimension exceeds the boundary.
+ var widthScale = ((availableSize.Width == std.numeric_limits.infinity()) ? FLT_MAX : availableSize.Width) / m_animatedVisualSize.x;
+ var heightScale = ((availableSize.Height == std.numeric_limits.infinity()) ? FLT_MAX : availableSize.Height) / m_animatedVisualSize.y;
+ return (heightScale > widthScale)
+ ? Size{ availableSize.Width, m_animatedVisualSize.y* widthScale }
+ : Size{ m_animatedVisualSize.x* heightScale, availableSize.Height };
+ }
+
+ // Public API.
+ // Overrides FrameworkElement.ArrangeOverride. Scales to fit the animated visual into finalSize
+ // respecting the current Stretch and returns the size actually used.
+ protected override Size ArrangeOverride(Size finalSize)
+ {
+ // if (m_isFallenBack && Children.Size > 0)
+ // {
+ // // We are showing the fallback content due to a failure to load an animated visual.
+ // // Tell the content to arrange itself.
+ // Children[0].Arrange(Rect{ Point{ 0,0}, finalSize });
+ // return finalSize;
+ // }
+
+ // float2 scale;
+ // float2 arrangedSize;
+
+ // if (!m_animatedVisualRoot)
+ // {
+ // // No content. 0 size.
+ // scale = { 1, 1 };
+ // arrangedSize = { 0,0 };
+ // }
+ // else
+ // {
+ // var stretch = Stretch;
+ // if (stretch == Stretch.None)
+ // {
+ // // Do not scale, do not center.
+ // scale = { 1, 1 };
+ // arrangedSize = {
+ // std.min(finalSize.Width, m_animatedVisualSize.x),
+ // std.min(finalSize.Height, m_animatedVisualSize.y)
+
+ // };
+ // }
+ // else
+ // {
+ // scale = (float2)(finalSize) / m_animatedVisualSize;
+
+ // switch (stretch)
+ // {
+ // case Stretch.Uniform:
+ // // Scale both dimensions by the same amount.
+ // if (scale.x < scale.y)
+ // {
+ // scale.y = scale.x;
+ // }
+ // else
+ // {
+ // scale.x = scale.y;
+ // }
+ // break;
+ // case Stretch.UniformToFill:
+ // // Scale both dimensions by the same amount and leave no gaps around the edges.
+ // if (scale.x > scale.y)
+ // {
+ // scale.y = scale.x;
+ // }
+ // else
+ // {
+ // scale.x = scale.y;
+ // }
+ // break;
+ // }
+
+ // // A size needs to be set because there's an InsetClip applied, and without a
+ // // size the clip will prevent anything from being visible.
+ // arrangedSize = {
+ // std.min(finalSize.Width / scale.x, m_animatedVisualSize.x),
+ // std.min(finalSize.Height / scale.y, m_animatedVisualSize.y)
+
+ // };
+
+ // // Center the animation within the available space.
+ // var offset = (finalSize - (m_animatedVisualSize * scale)) / 2;
+ // var z = 0.0F;
+ // m_rootVisual.Offset({ offset, z });
+
+ // // Adjust the position of the clip.
+ // m_rootVisual.Clip().Offset(
+ // (stretch == Stretch.UniformToFill)
+ // ? -(offset / scale)
+ // : float2.zero()
+ // );
+ // }
+ // }
+
+ // m_rootVisual.Size(arrangedSize);
+ // var z = 1.0F;
+ // m_rootVisual.Scale({ scale, z });
+
+ // return finalSize;
+ }
+
+ // Public API.
+ // Accessor for ProgressObject property.
+ // NOTE: This is not a dependency property because it never changes and is not useful for binding.
+ ///
+ /// Gets a CompositionObject that is animated along with the progress of the AnimatedVisualPlayer.
+ ///
+ public CompositionObject ProgressObject => m_progressPropertySet;
+
+ // Public API.
+ ///
+ /// Pauses the currently playing animated visual, or does nothing if no play is underway.
+ ///
+ public void Pause()
+ {
+ if (m_nowPlaying)
+ {
+ m_nowPlaying.Pause();
+ }
+ }
+
+ // Public API.
+
+ ///
+ /// Starts playing the loaded animated visual, or does nothing if no animated visual is loaded.
+ ///
+ /// The point from which to start the animation, as a value from 0 to 1.
+ /// The point at which to finish the animation, as a value from 0 to 1.
+ /// If true, the animation loops continuously between fromProgress and toProgress. If false, the animation plays once then stops.
+ /// An async action that is completed when the play is stopped or, if looped is not set, when the play reaches toProgress.
+ public IAsyncAction PlayAsync(double fromProgress, double toProgress, bool looped)
+ {
+ // Make sure that animations are created.
+ CreateAnimations();
+
+ // Used to detect reentrance.
+ var version = ++m_playAsyncVersion;
+
+ // Complete m_nowPlaying if it is still running.
+ // Identical to Stop() call but without destroying the animations.
+ // WARNING - this call may cause reentrance via the IsPlaying DP.
+ if (m_nowPlaying)
+ {
+ m_progressPropertySet.InsertScalar("Progress", (float)(m_currentPlayFromProgress));
+ m_nowPlaying.Complete();
+ }
+
+ if (version != m_playAsyncVersion)
+ {
+ // The call was overtaken by another call due to reentrance.
+ co_return;
+ }
+
+ MUX_ASSERT(!m_nowPlaying);
+
+ // Adjust for the case where there is a segment that
+ // goes from [fromProgress..0] where m_fromProgress > 0.
+ // This is equivalent to [fromProgress..1], and by setting
+ // toProgress to 1 it saves us from generating extra key frames.
+ if (toProgress == 0 && fromProgress > 0)
+ {
+ toProgress = 1;
+ }
+
+ // Adjust for the case where there is a segment that
+ // goes from [1..toProgress] where toProgress > 0.
+ // This is equivalent to [0..toProgress], and by setting
+ // fromProgress to 0 it saves us from generating extra key frames.
+ if (toProgress > 0 && fromProgress == 1)
+ {
+ fromProgress = 0;
+ }
+
+ // Create an AnimationPlay to hold the play information.
+ // Keep a copy of the pointer because reentrance may cause the m_nowPlaying
+ // value to change.
+ var thisPlay = m_nowPlaying = std.new AnimationPlay(
+ this,
+ std.clamp((float)(fromProgress), 0.0F, 1.0F),
+ std.clamp((float)(toProgress), 0.0F, 1.0F),
+ looped);
+
+ if (IsAnimatedVisualLoaded())
+ {
+ // There is an animated visual loaded, so start it playing.
+ // WARNING - this may cause reentrance via IsPlaying DP.
+ thisPlay.Start();
+ }
+
+ // Capture the context so we can finish in the calling thread.
+ apartment_context calling_thread;
+
+ // Await the current play. The await will complete when the animation completes
+ // or Stop() is called. It can complete on any thread.
+ co_await thisPlay;
+
+ // Get back to the calling thread.
+ // This is necessary to destruct the AnimationPlay, and because callers
+ // from the dispatcher thread will expect to continue on the dispatcher thread.
+ co_await calling_thread;
+ }
+
+ // Public API.
+ ///
+ /// Resumes the currently paused animated visual, or does nothing if there is no animated visual loaded or the animated visual is not paused.
+ ///
+ public void Resume()
+ {
+ if (m_nowPlaying)
+ {
+ m_nowPlaying.Resume();
+ }
+ }
+
+ // Public API.
+ // REENTRANCE SIDE EFFECT: IsPlaying DP via m_nowPlaying.Complete() or InsertScalar iff m_nowPlaying.
+ ///
+ /// Moves the progress of the animated visual to the given value, or does nothing if no animated visual is loaded.
+ ///
+ /// A value from 0 to 1 that represents the progress of the animated visual.
+ public void SetProgress(double progress)
+ {
+ // Make sure that animations are created.
+ CreateAnimations();
+
+ var clampedProgress = Math.Clamp((float)(progress), 0.0F, 1.0F);
+
+ // WARNING: Reentrance via IsPlaying DP may occur from this point down to the end of the method
+ // iff m_nowPlaying.
+
+ // Setting the Progress value will stop the current play.
+ m_progressPropertySet.InsertScalar("Progress", (float)(clampedProgress));
+
+ // Ensure the current PlayAsync task is completed.
+ // Note that this explicit call is necessary, even though InsertScalar
+ // will stop the current animation, because the BatchCompleted event for
+ // the animation only gets hooked up if the animation is not looped.
+ // If there was a BatchCompleted event and it already fired from setting the Progress
+ // value then Complete() is a no-op.
+ if (m_nowPlaying)
+ {
+ m_nowPlaying.Complete();
+ }
+
+ // If optimization is set to Resources - destroy annimations immediately.
+ if (AnimationOptimization == PlayerAnimationOptimization.Resources)
+ {
+ DestroyAnimations();
+ }
+ }
+
+ // Public API.
+ // REENTRANCE SIDE EFFECT: IsPlaying DP via SetProgress or InsertScalar iff m_nowPlaying.
+ ///
+ /// Stops the current play, or does nothing if no play is underway.
+ ///
+ public void Stop()
+ {
+ if (m_nowPlaying)
+ {
+ // Stop the animation by setting the Progress value to the fromProgress of the
+ // most recent play.
+ // This may cause reentrance via the IsPlaying DP.
+ SetProgress(m_currentPlayFromProgress);
+ }
+ }
+
+ private void OnAutoPlayPropertyChanged(DependencyPropertyChangedEventArgs args)
+ {
+ var newValue = (bool)args.NewValue;
+
+ if (newValue && IsAnimatedVisualLoaded && !m_nowPlaying)
+ {
+ // Start playing immediately.
+ var from = 0;
+ var to = 1;
+ var looped = true;
+ var ignore = PlayAsync(from, to, looped);
+ }
+ }
+
+ private void OnAnimationOptimizationPropertyChanged(DependencyPropertyChangedEventArgs args)
+ {
+ var optimization = (PlayerAnimationOptimization)args.NewValue;
+
+ if (m_nowPlaying)
+ {
+ // If there is something in play right now we should not create/destroy animations.
+ return;
+ }
+
+ if (optimization == PlayerAnimationOptimization.Resources)
+ {
+ DestroyAnimations();
+ }
+ else if (optimization == PlayerAnimationOptimization.Latency)
+ {
+ CreateAnimations();
+ }
+ }
+
+ private void CreateAnimations()
+ {
+ m_createAnimationsCounter++;
+
+ if (m_isAnimationsCreated || m_animatedVisual == null)
+ {
+ return;
+ }
+
+ // Check if current animated visual supports creating animations and create them.
+ if (m_animatedVisual is { } animatedVisual)
+ {
+ if (animatedVisual is IAnimatedVisual2 animatedVisual2)
+ {
+ animatedVisual2.CreateAnimations();
+ m_isAnimationsCreated = true;
+ }
+ }
+ }
+
+ private void DestroyAnimations()
+ {
+ if (!m_isAnimationsCreated || m_animatedVisual == null)
+ {
+ return;
+ }
+
+ // Call RequestCommit to make sure that previous compositor calls complete before destroying animations.
+ // RequestCommitAsync is available only for RS4+
+ m_rootVisual.Compositor.RequestCommitAsync().Completed(
+ [me_weak = get_weak(), createAnimationsCounter = m_createAnimationsCounter](auto, auto) {
+ var me = me_weak;
+
+ if (!me)
+ {
+ return;
+ }
+
+ // Check if there was any CreateAnimations call after DestroyAnimations.
+ // We should not destroy animations in this case,
+ // they will be destroyed by the following DestroyAnimations call.
+ if (createAnimationsCounter != me.m_createAnimationsCounter)
+ {
+ return;
+ }
+
+ // Check if current animated visual supports destroyig animations.
+ if (var animatedVisual = me.m_animatedVisual)
+ {
+ if (var animatedVisual2 = animatedVisual as IAnimatedVisual2())
+ {
+ animatedVisual2.DestroyAnimations();
+ me.m_isAnimationsCreated = false;
+ }
+ }
+ }
+ );
+ }
+
+ private void OnFallbackContentPropertyChanged(DependencyPropertyChangedEventArgs args)
+ {
+ if (m_isFallenBack)
+ {
+ LoadFallbackContent();
+ }
+ }
+
+ private void OnSourcePropertyChanged(DependencyPropertyChangedEventArgs args)
+ {
+ var newSource = args.NewValue as IAnimatedVisualSource;
+
+ // WARNING - this may cause reentrance via the IsPlaying DP iff m_nowPlaying.
+ Stop();
+
+ // Disconnect from the update notifications of the old source.
+ m_dynamicAnimatedVisualInvalidatedRevoker.revoke();
+
+ if (newSource is IDynamicAnimatedVisualSource newDynamicSource)
+ {
+ // Connect to the update notifications of the new source.
+ m_dynamicAnimatedVisualInvalidatedRevoker
+ = newDynamicSource.AnimatedVisualInvalidated(auto_revoke, [weakThis{ get_weak() }](
+ var /*sender*/,
+ var /*e*/)
+
+ {
+ if (var strongThis = weakThis)
+ {
+ strongThis.UpdateContent();
+ }
+ });
+ }
+
+ UpdateContent();
+ }
+
+ // Unload the current animated visual (if any).
+ private void UnloadContent()
+ {
+ if (m_animatedVisualRoot is not null)
+ {
+ // This will complete any current play.
+ // WARNING - this may cause reentrance via IsPlaying DP iff m_nowPlaying.
+ Stop();
+
+ // Remove the old animated visual (if any).
+ var animatedVisual = m_animatedVisual;
+ if (animatedVisual is not null)
+ {
+ m_rootVisual.Children.RemoveAll();
+ m_animatedVisualRoot = null;
+ // Notify the animated visual that it will no longer be used.
+ (animatedVisual as IDisposable)?.Dispose();
+ m_animatedVisual = null;
+ }
+
+ // Size has changed. Tell XAML to re-measure.
+ InvalidateMeasure();
+
+ // WARNING - these may cause reentrance.
+ Duration = TimeSpan.Zero;
+ Diagnostics = null;
+ // Set IsAnimatedVisualLoaded last as it is the property that is most likely
+ // to have user code react to its state change.
+ IsAnimatedVisualLoaded = false;
+ }
+ }
+
+ private void UpdateContent()
+ {
+ // Unload the existing content, if any.
+ UnloadContent();
+
+ // Try to create a new animated visual.
+ var source = Source;
+ if (source is null)
+ {
+ // No source set. Nothing to do.
+ return;
+ }
+
+ object diagnostics;
+ IAnimatedVisual animatedVisual;
+
+ bool createAnimations = AnimationOptimization == PlayerAnimationOptimization.Latency;
+
+ if (source is IAnimatedVisualSource3 source3)
+ {
+ animatedVisual = source3.TryCreateAnimatedVisual(m_rootVisual.Compositor, out diagnostics, createAnimations);
+ m_isAnimationsCreated = createAnimations;
+ m_animatedVisual = animatedVisual;
+ }
+
+ else
+ {
+ animatedVisual = source.TryCreateAnimatedVisual(m_rootVisual.Compositor, out diagnostics);
+ m_isAnimationsCreated = true;
+
+ // m_animatedVisual should be updated before DestroyAnimations call
+ m_animatedVisual = animatedVisual;
+
+ // Destroy animations if we don't need them.
+ // Old IAnimatedVisualSource interface always creates them.
+ if (!createAnimations)
+ {
+ DestroyAnimations();
+ }
+ }
+
+ if (animatedVisual is null)
+ {
+ // Create failed.
+
+ if (!m_isFallenBack)
+ {
+ // Show the fallback content, if any.
+ m_isFallenBack = true;
+ LoadFallbackContent();
+ }
+
+ // Complete any play that was started during loading.
+ // WARNING - this may cause reentrance via IsPlaying DP iff m_nowPlaying.
+ Stop();
+
+ // WARNING - this may cause reentrance.
+ Diagnostics = diagnostics;
+
+ return;
+ }
+
+ // If the content is empty, do nothing. If we are in fallback from a previous
+ // failure to load, stay fallen back.
+ // Empty content means the source has nothing to show yet.
+ if (animatedVisual?.RootVisual is null || animatedVisual.Size == default(Vector2))
+ {
+ // WARNING - this may cause reentrance.
+ Diagnostics = diagnostics;
+
+ return;
+ }
+
+ // We have non-empty content to show.
+ // If we were in fallback, clear that fallback content.
+ if (m_isFallenBack)
+ {
+ // Get out of the fallback state.
+ m_isFallenBack = false;
+ UnloadFallbackContent();
+ }
+
+ // Hook up the new animated visual.
+ m_animatedVisualRoot = animatedVisual.RootVisual;
+ m_animatedVisualSize = animatedVisual.Size;
+ m_rootVisual.Children.InsertAtTop(m_animatedVisualRoot);
+
+ // Size has changed. Tell XAML to re-measure.
+ InvalidateMeasure();
+
+ // Ensure the animated visual has a Progress property. This guarantees that a composition without
+ // a Progress property won't blow up when we create an expression that references it below.
+ // Normally the animated visual would have a Progress property that all its expressions reference,
+ // but just in case, insert it here.
+ m_animatedVisualRoot.Properties.InsertScalar("Progress", 0.0F);
+
+ // Tie the animated visual's Progress property to the player Progress with an ExpressionAnimation.
+ var compositor = m_rootVisual.Compositor;
+ var progressAnimation = compositor.CreateExpressionAnimation("_.Progress");
+ progressAnimation.SetReferenceParameter("_", m_progressPropertySet);
+ m_animatedVisualRoot.Properties.StartAnimation("Progress", progressAnimation);
+
+ // WARNING - these may cause reentrance.
+ // Set these properties before the if (AutoPlay()) branch calls PlayAsync
+ // so that the properties are updated before playing starts.
+ Duration = animatedVisual.Duration;
+ Diagnostics = diagnostics;
+ // Set IsAnimatedVisualLoaded last as it is the property that is most likely
+ // to have user code react to its state change.
+ IsAnimatedVisualLoaded = true;
+
+ // Check whether playing has been started already via reentrance from a DP handler.
+ if (m_nowPlaying)
+ {
+ m_nowPlaying.Start();
+ }
+ else if (AutoPlay)
+ {
+ // Start playing immediately.
+ var from = 0;
+ var to = 1;
+ var looped = true;
+ // NOTE: If !IsAnimatedVisualLoaded() then this is a no-op.
+ var ignore = PlayAsync(from, to, looped);
+ }
+ }
+
+ private void LoadFallbackContent()
+ {
+ MUX_ASSERT(m_isFallenBack);
+
+ UIElement fallbackContentElement = null;
+ var fallbackContentTemplate = FallbackContent;
+ if (fallbackContentTemplate is not null)
+ {
+ // Load the content from the DataTemplate. It should be a UIElement tree root.
+ DependencyObject fallbackContentObject = fallbackContentTemplate.LoadContent();
+ // Get the content.
+ fallbackContentElement = fallbackContentObject as UIElement;
+ }
+
+ // Set the (possibly null) content. We allow null content so as to handle the
+ // case where the fallback content got removed - in which case we want to
+ // clear out the existing content if any.
+ SetFallbackContent(fallbackContentElement);
+ }
+
+ private void UnloadFallbackContent()
+ {
+ MUX_ASSERT(!m_isFallenBack);
+ SetFallbackContent(null);
+ }
+
+ private void SetFallbackContent(UIElement uiElement)
+ {
+ // Clear out the existing content.
+ ClearChildren();
+
+ // Place the content in the tree.
+ if (uiElement is not null)
+ {
+ AddChild(uiElement);
+ }
+
+ // Size has probably changed. Tell XAML to re-measure.
+ InvalidateMeasure();
+ }
+
+ private void OnPlaybackRatePropertyChanged(DependencyPropertyChangedEventArgs args)
+ {
+ if (m_nowPlaying is not null)
+ {
+ m_nowPlaying.SetPlaybackRate((float)(double)args.NewValue);
+ }
+ }
+
+ private void OnStretchPropertyChanged(DependencyPropertyChangedEventArgs args)
+ {
+ InvalidateMeasure();
+ }
+}
diff --git a/src/Uno.UI/Microsoft/UI/Xaml/Controls/AnimatedVisualPlayer/AnimatedVisualPlayerAutomationPeer.mux.cs b/src/Uno.UI/Microsoft/UI/Xaml/Controls/AnimatedVisualPlayer/AnimatedVisualPlayerAutomationPeer.mux.cs
new file mode 100644
index 000000000000..42efe756e2a1
--- /dev/null
+++ b/src/Uno.UI/Microsoft/UI/Xaml/Controls/AnimatedVisualPlayer/AnimatedVisualPlayerAutomationPeer.mux.cs
@@ -0,0 +1,30 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See LICENSE in the project root for license information.
+// MUX Reference src\controls\dev\AnimatedVisualPlayer\AnimatedVisualPlayerAutomationPeer.cpp, tag winui3/release/1.6.3, commit 66d24dfff
+
+using System.Text;
+using System.Threading.Tasks;
+using Microsoft.UI.Xaml.Controls;
+
+namespace Microsoft/* UWP don't rename */.UI.Xaml.Automation.Peers;
+
+///
+/// Exposes AnimatedVisualPlayer types to Microsoft UI Automation.
+///
+public partial class AnimatedVisualPlayerAutomationPeer : FrameworkElementAutomationPeer
+{
+ ///
+ /// Initializes a new instance of the AnimatedVisualPlayerAutomationPeer class.
+ ///
+ ///
+ public AnimatedVisualPlayerAutomationPeer(AnimatedVisualPlayer owner) : base(owner)
+ {
+ }
+
+ protected override string GetClassNameCore() => nameof(AnimatedVisualPlayer);
+
+ protected override AutomationControlType GetAutomationControlTypeCore() => AutomationControlType.Image;
+}
diff --git a/src/Uno.UI/Microsoft/UI/Xaml/Controls/AnimatedVisualPlayer/IAnimatedVisual.cs b/src/Uno.UI/Microsoft/UI/Xaml/Controls/AnimatedVisualPlayer/IAnimatedVisual.cs
index 13a44ad4d47d..223c09b732bf 100644
--- a/src/Uno.UI/Microsoft/UI/Xaml/Controls/AnimatedVisualPlayer/IAnimatedVisual.cs
+++ b/src/Uno.UI/Microsoft/UI/Xaml/Controls/AnimatedVisualPlayer/IAnimatedVisual.cs
@@ -6,26 +6,25 @@
using System.Numerics;
using Microsoft.UI.Composition;
-namespace Microsoft/* UWP don't rename */.UI.Xaml.Controls
+namespace Microsoft/* UWP don't rename */.UI.Xaml.Controls;
+
+///
+/// An animated Composition.Visual that can be used by other objects, such as an AnimatedVisualPlayer or AnimatedIcon.
+///
+public partial interface IAnimatedVisual : IDisposable
{
///
- /// An animated Composition.Visual that can be used by other objects, such as an AnimatedVisualPlayer or AnimatedIcon.
+ /// Gets the root Visual of the animated visual.
///
- public partial interface IAnimatedVisual : IDisposable
- {
- ///
- /// Gets the root Visual of the animated visual.
- ///
- Visual RootVisual { get; }
+ Visual RootVisual { get; }
- ///
- /// Gets the size of the animated visual.
- ///
- Vector2 Size { get; }
+ ///
+ /// Gets the size of the animated visual.
+ ///
+ Vector2 Size { get; }
- ///
- /// Gets the duration of the animated visual.
- ///
- TimeSpan Duration { get; }
- }
+ ///
+ /// Gets the duration of the animated visual.
+ ///
+ TimeSpan Duration { get; }
}
diff --git a/src/Uno.UI/Microsoft/UI/Xaml/Controls/AnimatedVisualPlayer/IAnimatedVisual2.cs b/src/Uno.UI/Microsoft/UI/Xaml/Controls/AnimatedVisualPlayer/IAnimatedVisual2.cs
new file mode 100644
index 000000000000..18c4a2d0781e
--- /dev/null
+++ b/src/Uno.UI/Microsoft/UI/Xaml/Controls/AnimatedVisualPlayer/IAnimatedVisual2.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace Microsoft/* UWP don't rename */.UI.Xaml.Controls;
+
+///
+/// An animated Composition.Visual that can be used by other objects, such as an AnimatedVisualPlayer or AnimatedIcon.
+/// Extends IAnimatedVisual with methods to create and destroy animations.
+///
+public partial interface IAnimatedVisual2 : IAnimatedVisual, IDisposable
+{
+ void CreateAnimations();
+
+ void DestroyAnimations();
+}
diff --git a/src/Uno.UI/Microsoft/UI/Xaml/Controls/AnimatedVisualPlayer/IAnimatedVisualSource.cs b/src/Uno.UI/Microsoft/UI/Xaml/Controls/AnimatedVisualPlayer/IAnimatedVisualSource.cs
new file mode 100644
index 000000000000..3308b37a4f12
--- /dev/null
+++ b/src/Uno.UI/Microsoft/UI/Xaml/Controls/AnimatedVisualPlayer/IAnimatedVisualSource.cs
@@ -0,0 +1,17 @@
+using Microsoft.UI.Composition;
+
+namespace Microsoft/* UWP don't rename */.UI.Xaml.Controls;
+
+///
+/// An animated Visual that can be used by other objects, such as an AnimatedVisualPlayer.
+///
+public partial interface IAnimatedVisualSource
+{
+ ///
+ /// Attempts to create an animated visual.
+ ///
+ /// The compositor for the animated visual.
+ /// The diagnostics information about the attempt to create an animated visual.
+ /// An animated visual that can be used by other objects.
+ IAnimatedVisual TryCreateAnimatedVisual(Compositor compositor, out object diagnostics);
+}
diff --git a/src/Uno.UI/Microsoft/UI/Xaml/Controls/AnimatedVisualPlayer/IAnimatedVisualSource2.cs b/src/Uno.UI/Microsoft/UI/Xaml/Controls/AnimatedVisualPlayer/IAnimatedVisualSource2.cs
new file mode 100644
index 000000000000..f4acc857fb2c
--- /dev/null
+++ b/src/Uno.UI/Microsoft/UI/Xaml/Controls/AnimatedVisualPlayer/IAnimatedVisualSource2.cs
@@ -0,0 +1,22 @@
+using System.Collections.Generic;
+using Windows.UI;
+
+namespace Microsoft/* UWP don't rename */.UI.Xaml.Controls;
+
+///
+/// An animated Visual that can be used by other objects, such as an AnimatedIcon. Extends IAnimatedVisualSource.
+///
+public partial interface IAnimatedVisualSource2 : IAnimatedVisualSource
+{
+ ///
+ /// Gets a collection that provides a mapping of marker names to playback positions in the animation.
+ ///
+ public IReadOnlyDictionary Markers { get; }
+
+ ///
+ /// Sets a color for the animated visual.
+ ///
+ /// The property name of the color as defined in the JSON file for the animated icon.
+ /// The color value for the propertyName.
+ void SetColorProperty(string propertyName, Color value);
+}
diff --git a/src/Uno.UI/Microsoft/UI/Xaml/Controls/AnimatedVisualPlayer/IAnimatedVisualSource3.cs b/src/Uno.UI/Microsoft/UI/Xaml/Controls/AnimatedVisualPlayer/IAnimatedVisualSource3.cs
new file mode 100644
index 000000000000..1916dd56231a
--- /dev/null
+++ b/src/Uno.UI/Microsoft/UI/Xaml/Controls/AnimatedVisualPlayer/IAnimatedVisualSource3.cs
@@ -0,0 +1,18 @@
+using Microsoft.UI.Composition;
+
+namespace Microsoft/* UWP don't rename */.UI.Xaml.Controls;
+
+///
+/// An animated Composition.Visual that can be used by other objects, such as an AnimatedVisualPlayer or AnimatedIcon.
+///
+public partial interface IAnimatedVisualSource3
+{
+ ///
+ /// Attempts to create an animated visual.
+ ///
+ /// The compositor for the animated visual.
+ /// The diagnostics information about the attempt to create an animated visual.
+ /// True to create the animations; otherwise, false.
+ /// An animated visual that can be used by other objects.
+ IAnimatedVisual2 TryCreateAnimatedVisual(Compositor compositor, out object diagnostics, bool createAnimations);
+}
diff --git a/src/Uno.UI/UI/Xaml/Controls/AnimatedVisualPlayer/AnimatedVisualPlayer.cs b/src/Uno.UI/Microsoft/UI/Xaml/Controls/AnimatedVisualPlayer/Legacy/AnimatedVisualPlayer.legacy.cs
similarity index 99%
rename from src/Uno.UI/UI/Xaml/Controls/AnimatedVisualPlayer/AnimatedVisualPlayer.cs
rename to src/Uno.UI/Microsoft/UI/Xaml/Controls/AnimatedVisualPlayer/Legacy/AnimatedVisualPlayer.legacy.cs
index 0f9e303b41dc..9d35908137c2 100644
--- a/src/Uno.UI/UI/Xaml/Controls/AnimatedVisualPlayer/AnimatedVisualPlayer.cs
+++ b/src/Uno.UI/Microsoft/UI/Xaml/Controls/AnimatedVisualPlayer/Legacy/AnimatedVisualPlayer.legacy.cs
@@ -1,4 +1,5 @@
-using System;
+#if false
+using System;
using System.Threading.Tasks;
using Uno;
using Windows.Foundation;
@@ -139,3 +140,4 @@ protected override Size MeasureOverride(Size availableSize)
protected override Size ArrangeOverride(Size finalSize) => ArrangeFirstChild(finalSize);
}
}
+#endif
diff --git a/src/Uno.UI/UI/Xaml/Controls/AnimatedVisualPlayer/IAnimatedVisualSource.cs b/src/Uno.UI/Microsoft/UI/Xaml/Controls/AnimatedVisualPlayer/Legacy/IAnimatedVisualSource.legacy.cs
similarity index 94%
rename from src/Uno.UI/UI/Xaml/Controls/AnimatedVisualPlayer/IAnimatedVisualSource.cs
rename to src/Uno.UI/Microsoft/UI/Xaml/Controls/AnimatedVisualPlayer/Legacy/IAnimatedVisualSource.legacy.cs
index e321eb286427..c4b85de1fead 100644
--- a/src/Uno.UI/UI/Xaml/Controls/AnimatedVisualPlayer/IAnimatedVisualSource.cs
+++ b/src/Uno.UI/Microsoft/UI/Xaml/Controls/AnimatedVisualPlayer/Legacy/IAnimatedVisualSource.legacy.cs
@@ -1,4 +1,5 @@
-using System;
+#if false
+using System;
using Microsoft/* UWP don't rename */.UI.Xaml.Controls;
using Windows.Foundation;
@@ -24,3 +25,4 @@ internal partial interface IAnimatedVisualSourceWithUri
Uri UriSource { get; set; }
}
}
+#endif
diff --git a/src/Uno.UI/UI/Xaml/Controls/AnimatedVisualPlayer/IAnimatedVisualSource2.cs b/src/Uno.UI/Microsoft/UI/Xaml/Controls/AnimatedVisualPlayer/Legacy/IAnimatedVisualSource2.legacy.cs
similarity index 85%
rename from src/Uno.UI/UI/Xaml/Controls/AnimatedVisualPlayer/IAnimatedVisualSource2.cs
rename to src/Uno.UI/Microsoft/UI/Xaml/Controls/AnimatedVisualPlayer/Legacy/IAnimatedVisualSource2.legacy.cs
index c839ad5ca75c..3b07ac0e98ec 100644
--- a/src/Uno.UI/UI/Xaml/Controls/AnimatedVisualPlayer/IAnimatedVisualSource2.cs
+++ b/src/Uno.UI/Microsoft/UI/Xaml/Controls/AnimatedVisualPlayer/Legacy/IAnimatedVisualSource2.legacy.cs
@@ -1,4 +1,5 @@
-using System.Collections.Generic;
+#if false
+using System.Collections.Generic;
using Windows.UI;
using Microsoft.UI.Xaml.Controls;
@@ -11,3 +12,4 @@ public partial interface IAnimatedVisualSource2 : IAnimatedVisualSource
void SetColorProperty(string propertyName, Color value);
}
}
+#endif
diff --git a/src/Uno.UI/Microsoft/UI/Xaml/Controls/AnimatedVisualPlayer/ILottieVisualSourceProvider.cs b/src/Uno.UI/Microsoft/UI/Xaml/Controls/AnimatedVisualPlayer/Legacy/ILottieVisualSourceProvider.cs
similarity index 100%
rename from src/Uno.UI/Microsoft/UI/Xaml/Controls/AnimatedVisualPlayer/ILottieVisualSourceProvider.cs
rename to src/Uno.UI/Microsoft/UI/Xaml/Controls/AnimatedVisualPlayer/Legacy/ILottieVisualSourceProvider.cs
diff --git a/src/Uno.UI/UI/Xaml/Controls/AnimatedVisualPlayer/IThemableAnimatedVisualSource.cs b/src/Uno.UI/Microsoft/UI/Xaml/Controls/AnimatedVisualPlayer/Legacy/IThemableAnimatedVisualSource.cs
similarity index 100%
rename from src/Uno.UI/UI/Xaml/Controls/AnimatedVisualPlayer/IThemableAnimatedVisualSource.cs
rename to src/Uno.UI/Microsoft/UI/Xaml/Controls/AnimatedVisualPlayer/Legacy/IThemableAnimatedVisualSource.cs
diff --git a/src/Uno.UI/Microsoft/UI/Xaml/Controls/AnimatedVisualPlayer/PlayerAnimationOptimization.cs b/src/Uno.UI/Microsoft/UI/Xaml/Controls/AnimatedVisualPlayer/PlayerAnimationOptimization.cs
new file mode 100644
index 000000000000..ce951290dcbd
--- /dev/null
+++ b/src/Uno.UI/Microsoft/UI/Xaml/Controls/AnimatedVisualPlayer/PlayerAnimationOptimization.cs
@@ -0,0 +1,17 @@
+namespace Microsoft/* UWP don't rename */.UI.Xaml.Controls;
+
+///
+/// Defines constants that specify how an AnimatedVisualPlayer caches animations when the player is idle.
+///
+public enum PlayerAnimationOptimization
+{
+ ///
+ /// The player optimizes animation caching for lower latency.
+ ///
+ Latency = 0,
+
+ ///
+ /// The player optimizes animation caching for lower resource usage.
+ ///
+ Resources = 1,
+}