[LottieGen] Added new AnimationController API support for LottieGen (#488)
This commit is contained in:
Родитель
a3ee250679
Коммит
56f986c233
|
@ -242,6 +242,11 @@ if ($InstallWindowsSDK)
|
|||
# Note: there is a delay from Windows SDK announcements to availability via the static link
|
||||
$uri = "https://go.microsoft.com/fwlink/?prd=11966&pver=1.0&plcid=0x409&clcid=0x409&ar=Flight&sar=Sdsurl&o1=$buildNumber"
|
||||
|
||||
if ($buildNumber -eq "22621")
|
||||
{
|
||||
$uri = "https://go.microsoft.com/fwlink/p/?linkid=2196240"
|
||||
}
|
||||
|
||||
if ($env:TEMP -eq $null)
|
||||
{
|
||||
$env:TEMP = Join-Path $env:SystemDrive 'temp'
|
||||
|
|
|
@ -33,6 +33,7 @@ namespace CommunityToolkit.WinUI.Lottie
|
|||
Loader? _loader;
|
||||
WinCompData.Visual? _wincompDataRootVisual;
|
||||
WinCompData.CompositionPropertySet? _wincompDataThemingPropertySet;
|
||||
IEnumerable<WinCompData.AnimationController>? _wincompDataAnimationControllers;
|
||||
CompositionPropertySet? _themingPropertySet;
|
||||
double _width;
|
||||
double _height;
|
||||
|
@ -62,6 +63,7 @@ namespace CommunityToolkit.WinUI.Lottie
|
|||
CompositionObjectNodes.
|
||||
Where(n => n.Object is WinCompData.CompositionPropertySet cps && cps.Owner is null).
|
||||
Select(n => (WinCompData.CompositionPropertySet)n.Object).FirstOrDefault();
|
||||
_wincompDataAnimationControllers = graph.CompositionObjectNodes.Where(n => (n.Object is WinCompData.AnimationController) && ((WinCompData.AnimationController)n.Object).IsCustom).Select(n => (WinCompData.AnimationController)n.Object);
|
||||
}
|
||||
|
||||
internal bool CanInstantiate => _wincompDataRootVisual is not null;
|
||||
|
@ -84,7 +86,10 @@ namespace CommunityToolkit.WinUI.Lottie
|
|||
var instantiator = new Instantiator(compositor, surfaceResolver: LoadImageFromUri);
|
||||
|
||||
// _wincompDataRootVisual is not null is implied by CanInstantiate.
|
||||
var result = new DisposableAnimatedVisual((Visual)instantiator.GetInstance(_wincompDataRootVisual!))
|
||||
Visual rootVisual = (Visual)instantiator.GetInstance(_wincompDataRootVisual!);
|
||||
IEnumerable<AnimationController> animationControllers = _wincompDataAnimationControllers!.Select(o => (AnimationController)instantiator.GetInstance(o));
|
||||
|
||||
var result = new DisposableAnimatedVisual(rootVisual, animationControllers)
|
||||
{
|
||||
Size = new System.Numerics.Vector2((float)_width, (float)_height),
|
||||
Duration = _duration,
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#nullable enable
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
|
||||
|
@ -18,13 +19,20 @@ namespace CommunityToolkit.WinUI.Lottie
|
|||
{
|
||||
sealed class DisposableAnimatedVisual : IAnimatedVisual, IDisposable
|
||||
{
|
||||
internal DisposableAnimatedVisual(Visual rootVisual)
|
||||
internal DisposableAnimatedVisual(Visual rootVisual, IEnumerable<AnimationController> customAnimationControllers)
|
||||
{
|
||||
RootVisual = rootVisual;
|
||||
CustomAnimationControllers = customAnimationControllers;
|
||||
}
|
||||
|
||||
public Visual RootVisual { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Keeps references to all custom AnimationController objects.
|
||||
/// We need references because otherwise they will be destroyed from dwm.
|
||||
/// </summary>
|
||||
public IEnumerable<AnimationController> CustomAnimationControllers { get; }
|
||||
|
||||
public TimeSpan Duration { get; set; }
|
||||
|
||||
public Vector2 Size { get; set; }
|
||||
|
|
|
@ -402,6 +402,8 @@ namespace CommunityToolkit.WinUI.Lottie
|
|||
foreach (var animator in source.Animators)
|
||||
{
|
||||
var animation = GetCompositionAnimation(animator.Animation);
|
||||
if (animator.Controller is null || !animator.Controller.IsCustom)
|
||||
{
|
||||
target.StartAnimation(animator.AnimatedProperty, animation);
|
||||
var controller = animator.Controller;
|
||||
if (controller is not null)
|
||||
|
@ -413,6 +415,15 @@ namespace CommunityToolkit.WinUI.Lottie
|
|||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException("LottieViewer and Instantiator does not support custom AnimationControllers yet");
|
||||
/*
|
||||
We should retarget to SDK 22621 to support this
|
||||
target.StartAnimation(animator.AnimatedProperty, animation, GetAnimationController(animator.Controller));
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Wc.AnimationController GetAnimationController(Wd.AnimationController obj)
|
||||
|
@ -422,9 +433,25 @@ namespace CommunityToolkit.WinUI.Lottie
|
|||
return result;
|
||||
}
|
||||
|
||||
var targetObject = GetCompositionObject(obj.TargetObject);
|
||||
if (obj.IsCustom)
|
||||
{
|
||||
throw new InvalidOperationException("LottieViewer and Instantiator does not support custom AnimationControllers yet");
|
||||
/*
|
||||
We should retarget to SDK 22621 to support this
|
||||
result = CacheAndInitializeCompositionObject(obj, _c.CreateAnimationController());
|
||||
|
||||
if (obj.IsPaused)
|
||||
{
|
||||
result.Pause();
|
||||
}
|
||||
*/
|
||||
}
|
||||
else
|
||||
{
|
||||
var targetObject = GetCompositionObject(obj.TargetObject!);
|
||||
result = CacheAndInitializeCompositionObject(obj, targetObject.TryGetAnimationController(obj.TargetProperty));
|
||||
}
|
||||
|
||||
StartAnimations(obj, result);
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -219,17 +219,20 @@ namespace CommunityToolkit.WinUI.Lottie
|
|||
{
|
||||
// Start testing on version 2. We know that at least version 1 is supported because
|
||||
// we are running in UAP code.
|
||||
var versionToTest = 2u;
|
||||
var versionToTest = 1u;
|
||||
|
||||
// Keep querying until IsApiContractPresent fails to find the version.
|
||||
while (ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", (ushort)versionToTest))
|
||||
while (ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", (ushort)(versionToTest + 1)))
|
||||
{
|
||||
// Keep looking ...
|
||||
versionToTest++;
|
||||
}
|
||||
|
||||
// TODO: we do not support UAP above 14 in Lottie-Windows yet, only in LottieGen.
|
||||
versionToTest = Math.Min(versionToTest, 14);
|
||||
|
||||
// Query failed on versionToTest. Return the previous version.
|
||||
return versionToTest - 1;
|
||||
return versionToTest;
|
||||
}
|
||||
|
||||
// Specializes the Stopwatch to do just the one thing we need of it - get the time
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices.WindowsRuntime;
|
||||
using System.Threading.Tasks;
|
||||
using CommunityToolkit.WinUI.Lottie;
|
||||
|
|
|
@ -43,6 +43,13 @@ namespace CommunityToolkit.WinUI.Lottie.LottieToWinComp
|
|||
Debug.Assert(scale <= 1, "Precondition");
|
||||
Debug.Assert(animation.KeyFrameCount > 0, "Precondition");
|
||||
|
||||
if (scale == 1.0 && offset == 0.0 && context.ObjectFactory.IsUapApiAvailable(nameof(AnimationController)) && context.RootProgressController is not null)
|
||||
{
|
||||
// Special case when we can use root AnimationController (no time stretch, no time offset)
|
||||
compObject.StartAnimation(target, animation, context.RootProgressController!);
|
||||
return;
|
||||
}
|
||||
|
||||
var state = context.GetStateCache<StateCache>();
|
||||
|
||||
// Start the animation ...
|
||||
|
|
|
@ -86,6 +86,12 @@ namespace CommunityToolkit.WinUI.Lottie.LottieToWinComp
|
|||
case nameof(PathKeyFrameAnimation):
|
||||
return 11;
|
||||
|
||||
// AnimationController class was introduced in version 6, but
|
||||
// it became possible to create it explicitly only after verstion 15
|
||||
// with compositor.CreateAnimationController() method
|
||||
case nameof(AnimationController):
|
||||
return 15;
|
||||
|
||||
default:
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
@ -304,5 +310,11 @@ namespace CommunityToolkit.WinUI.Lottie.LottieToWinComp
|
|||
|
||||
HighestUapVersionUsed = Math.Max(HighestUapVersionUsed, uapVersion);
|
||||
}
|
||||
|
||||
internal AnimationController CreateAnimationControllerList()
|
||||
{
|
||||
ConsumeVersionFeature(GetUapVersionForApi(nameof(AnimationController)));
|
||||
return _compositor.CreateAnimationController();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -150,6 +150,11 @@ namespace CommunityToolkit.WinUI.Lottie.LottieToWinComp
|
|||
/// </summary>
|
||||
public ContainerVisual? RootVisual { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// AnimationController that has Progress property bound to RootVisual.Progress property.
|
||||
/// </summary>
|
||||
public AnimationController? RootProgressController { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// True iff theme property bindings are enabled.
|
||||
/// </summary>
|
||||
|
@ -223,6 +228,16 @@ namespace CommunityToolkit.WinUI.Lottie.LottieToWinComp
|
|||
// Add the master progress property to the visual.
|
||||
RootVisual.Properties.InsertScalar(ProgressPropertyName, 0);
|
||||
|
||||
// AnimationController that has Progress value bound to RootVisual.Progress
|
||||
if (ObjectFactory.IsUapApiAvailable(nameof(AnimationController)))
|
||||
{
|
||||
RootProgressController = ObjectFactory.CreateAnimationControllerList();
|
||||
var rootProgressAnimation = context.ObjectFactory.CreateExpressionAnimation(ExpressionFactory.RootProgress);
|
||||
rootProgressAnimation.SetReferenceParameter(ExpressionFactory.RootName, RootVisual);
|
||||
RootProgressController.Pause();
|
||||
RootProgressController.StartAnimation("Progress", rootProgressAnimation);
|
||||
}
|
||||
|
||||
// Add the translations of each layer to the root visual. This will recursively
|
||||
// add the tranlation of the layers in precomps.
|
||||
var contentsChildren = RootVisual.Children;
|
||||
|
|
|
@ -700,16 +700,20 @@ namespace CommunityToolkit.WinUI.Lottie.UIData.Tools
|
|||
if (visibilityController is not null)
|
||||
{
|
||||
var animator = TryGetAnimatorByPropertyName(visibilityController, "Progress");
|
||||
if (animator is null)
|
||||
|
||||
if (visibilityController.IsCustom)
|
||||
{
|
||||
ApplyVisibility(parent, GetVisiblityAnimationDescription(visual), null, visibilityController);
|
||||
}
|
||||
else if (animator is not null)
|
||||
{
|
||||
ApplyVisibility(parent, GetVisiblityAnimationDescription(visual), animator.Animation, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
ApplyVisibility(
|
||||
parent,
|
||||
GetVisiblityAnimationDescription(visual),
|
||||
animator.Animation);
|
||||
|
||||
// Clear out the visibility property and animation from the visual.
|
||||
visual.IsVisible = null;
|
||||
visual.StopAnimation("IsVisible");
|
||||
|
@ -790,13 +794,20 @@ namespace CommunityToolkit.WinUI.Lottie.UIData.Tools
|
|||
if (visibilityController is not null)
|
||||
{
|
||||
var animator = TryGetAnimatorByPropertyName(visibilityController, "Progress");
|
||||
if (animator is null)
|
||||
|
||||
if (visibilityController.IsCustom)
|
||||
{
|
||||
ApplyVisibility(visual, GetVisiblityAnimationDescription(shape), null, visibilityController);
|
||||
}
|
||||
else if (animator is not null)
|
||||
{
|
||||
ApplyVisibility(visual, GetVisiblityAnimationDescription(shape), animator.Animation, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
ApplyVisibility(visual, GetVisiblityAnimationDescription(shape), animator.Animation);
|
||||
|
||||
// Clear out the Scale properties and animations from the shape.
|
||||
shape.Scale = null;
|
||||
shape.StopAnimation("Scale");
|
||||
|
@ -806,8 +817,10 @@ namespace CommunityToolkit.WinUI.Lottie.UIData.Tools
|
|||
|
||||
// Applies the given visibility to the given Visual, combining it with the
|
||||
// visibility it already has.
|
||||
void ApplyVisibility(Visual to, VisibilityDescription fromVisibility, CompositionAnimation progressAnimation)
|
||||
void ApplyVisibility(Visual to, VisibilityDescription fromVisibility, CompositionAnimation? progressAnimation, AnimationController? customController)
|
||||
{
|
||||
Debug.Assert(progressAnimation is not null || customController is not null, "Precondition");
|
||||
|
||||
var toVisibility = GetVisiblityAnimationDescription(to);
|
||||
|
||||
var compositeVisibility = VisibilityDescription.Compose(fromVisibility, toVisibility);
|
||||
|
@ -829,12 +842,18 @@ namespace CommunityToolkit.WinUI.Lottie.UIData.Tools
|
|||
animation.InsertKeyFrame(progress, isVisible);
|
||||
}
|
||||
|
||||
if (progressAnimation is not null)
|
||||
{
|
||||
to.StartAnimation("IsVisible", animation);
|
||||
|
||||
var controller = to.TryGetAnimationController("IsVisible")!;
|
||||
controller.Pause();
|
||||
controller.StartAnimation("Progress", progressAnimation);
|
||||
}
|
||||
else
|
||||
{
|
||||
to.StartAnimation("IsVisible", animation, customController);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Returns a description of the visibility over time of the given visual.
|
||||
|
@ -1325,9 +1344,16 @@ namespace CommunityToolkit.WinUI.Lottie.UIData.Tools
|
|||
|
||||
// Start the from's animations on the to.
|
||||
foreach (var anim in from.Animators)
|
||||
{
|
||||
if (anim.Controller is null || !anim.Controller.IsCustom)
|
||||
{
|
||||
to.StartAnimation(anim.AnimatedProperty, anim.Animation);
|
||||
if (anim.Controller is not null && (anim.Controller.IsPaused || anim.Controller.Animators.Count > 0))
|
||||
} else
|
||||
{
|
||||
to.StartAnimation(anim.AnimatedProperty, anim.Animation, anim.Controller);
|
||||
}
|
||||
|
||||
if (anim.Controller is not null && !anim.Controller.IsCustom && (anim.Controller.IsPaused || anim.Controller.Animators.Count > 0))
|
||||
{
|
||||
var controller = to.TryGetAnimationController(anim.AnimatedProperty)!;
|
||||
if (anim.Controller.IsPaused)
|
||||
|
@ -1336,9 +1362,16 @@ namespace CommunityToolkit.WinUI.Lottie.UIData.Tools
|
|||
}
|
||||
|
||||
foreach (var controllerAnim in anim.Controller.Animators)
|
||||
{
|
||||
if (controllerAnim.Controller is null || !controllerAnim.Controller.IsCustom)
|
||||
{
|
||||
controller.StartAnimation(controllerAnim.AnimatedProperty, controllerAnim.Animation);
|
||||
}
|
||||
else
|
||||
{
|
||||
controller.StartAnimation(controllerAnim.AnimatedProperty, controllerAnim.Animation, controllerAnim.Controller);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1382,9 +1415,17 @@ namespace CommunityToolkit.WinUI.Lottie.UIData.Tools
|
|||
|
||||
// Start the from's animations on the to.
|
||||
foreach (var anim in from.Animators)
|
||||
{
|
||||
if (anim.Controller is null || !anim.Controller.IsCustom)
|
||||
{
|
||||
to.StartAnimation(anim.AnimatedProperty, anim.Animation);
|
||||
if (anim.Controller is not null && (anim.Controller.IsPaused || anim.Controller.Animators.Count > 0))
|
||||
}
|
||||
else
|
||||
{
|
||||
to.StartAnimation(anim.AnimatedProperty, anim.Animation, anim.Controller);
|
||||
}
|
||||
|
||||
if (anim.Controller is not null && !anim.Controller.IsCustom && (anim.Controller.IsPaused || anim.Controller.Animators.Count > 0))
|
||||
{
|
||||
var controller = to.TryGetAnimationController(anim.AnimatedProperty)!;
|
||||
if (anim.Controller.IsPaused)
|
||||
|
@ -1393,9 +1434,16 @@ namespace CommunityToolkit.WinUI.Lottie.UIData.Tools
|
|||
}
|
||||
|
||||
foreach (var controllerAnim in anim.Controller.Animators)
|
||||
{
|
||||
if (controllerAnim.Controller is null || !controllerAnim.Controller.IsCustom)
|
||||
{
|
||||
controller.StartAnimation(controllerAnim.AnimatedProperty, controllerAnim.Animation);
|
||||
}
|
||||
else
|
||||
{
|
||||
controller.StartAnimation(controllerAnim.AnimatedProperty, controllerAnim.Animation, controllerAnim.Controller);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -363,6 +363,12 @@ namespace CommunityToolkit.WinUI.Lottie.UIData.Tools
|
|||
return true;
|
||||
}
|
||||
|
||||
bool VisitAnimationControllerList(AnimationController obj, T node)
|
||||
{
|
||||
VisitCompositionObject(obj, node);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitCanvasGeometry(CanvasGeometry obj, T node)
|
||||
{
|
||||
return true;
|
||||
|
|
|
@ -440,13 +440,21 @@ namespace CommunityToolkit.WinUI.Lottie.UIData.Tools
|
|||
foreach (var animator in source.Animators)
|
||||
{
|
||||
var animation = GetCompositionAnimation(animator.Animation);
|
||||
var controller = animator.Controller;
|
||||
|
||||
// Freeze the animation to indicate that it will not be mutated further. This
|
||||
// will ensure that it does not need to be copied when target.StartAnimation is called.
|
||||
animation.Freeze();
|
||||
if (controller is null || !controller.IsCustom)
|
||||
{
|
||||
target.StartAnimation(animator.AnimatedProperty, animation);
|
||||
var controller = animator.Controller;
|
||||
if (controller is not null)
|
||||
}
|
||||
else
|
||||
{
|
||||
target.StartAnimation(animator.AnimatedProperty, animation, GetAnimationController(controller));
|
||||
}
|
||||
|
||||
if (controller is not null && !controller.IsCustom)
|
||||
{
|
||||
var animationController = GetAnimationController(controller);
|
||||
if (controller.IsPaused)
|
||||
|
@ -464,9 +472,22 @@ namespace CommunityToolkit.WinUI.Lottie.UIData.Tools
|
|||
return result;
|
||||
}
|
||||
|
||||
var targetObject = GetCompositionObject(obj.TargetObject);
|
||||
if (obj.IsCustom)
|
||||
{
|
||||
result = CacheAndInitializeCompositionObject(obj, _c.CreateAnimationController());
|
||||
|
||||
if (obj.IsPaused)
|
||||
{
|
||||
result.Pause();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var targetObject = GetCompositionObject(obj.TargetObject!);
|
||||
|
||||
result = CacheAndInitializeCompositionObject(obj, targetObject.TryGetAnimationController(obj.TargetProperty!)!);
|
||||
}
|
||||
|
||||
result = CacheAndInitializeCompositionObject(obj, targetObject.TryGetAnimationController(obj.TargetProperty)!);
|
||||
StartAnimationsAndFreeze(obj, result);
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -160,6 +160,8 @@ namespace CommunityToolkit.WinUI.Lottie.UIData.Tools
|
|||
}
|
||||
}
|
||||
|
||||
public int AnimationControllerListCount { get; }
|
||||
|
||||
public int AnimationControllerCount { get; }
|
||||
|
||||
public int AnimatorCount { get; }
|
||||
|
|
|
@ -1092,7 +1092,10 @@ namespace CommunityToolkit.WinUI.Lottie.UIData.CodeGen.Cppwinrt
|
|||
builder.WriteBreakableLine($"auto result = winrt::make<{info.ClassName}>(", CommaSeparate(GetConstructorArguments(info)), ");");
|
||||
if (info.ImplementCreateAndDestroyMethods)
|
||||
{
|
||||
builder.WriteLine($"result.{CreateAnimationsMethod}();");
|
||||
builder.WriteLine($"if (auto result2 = result.try_as<{_animatedVisualTypeName2}>())");
|
||||
builder.OpenScope();
|
||||
builder.WriteLine($"result2.{CreateAnimationsMethod}();");
|
||||
builder.CloseScope();
|
||||
}
|
||||
|
||||
builder.WriteLine("return result;");
|
||||
|
|
|
@ -1134,7 +1134,7 @@ namespace CommunityToolkit.WinUI.Lottie.UIData.CodeGen
|
|||
node.RequiresStorage = true;
|
||||
}
|
||||
}
|
||||
else if (configuration.ImplementCreateAndDestroyMethods && node.Object is CompositionObject obj && obj.Animators.Count > 0)
|
||||
else if ((configuration.ImplementCreateAndDestroyMethods && node.Object is CompositionObject obj && obj.Animators.Count > 0) || (node.Object is AnimationController c && c.IsCustom))
|
||||
{
|
||||
// If we are implementing IAnimatedVisual2 interface we need to store all the composition objects that have animators.
|
||||
node.RequiresStorage = true;
|
||||
|
@ -1718,7 +1718,7 @@ namespace CommunityToolkit.WinUI.Lottie.UIData.CodeGen
|
|||
return obj.Type switch
|
||||
{
|
||||
// Do not generate code for animation controllers. It is done inline in the CompositionObject initialization.
|
||||
CompositionObjectType.AnimationController => throw new InvalidOperationException(),
|
||||
CompositionObjectType.AnimationController => GenerateCustomAnimationController(builder, (AnimationController)obj, node),
|
||||
CompositionObjectType.BooleanKeyFrameAnimation => GenerateBooleanKeyFrameAnimationFactory(builder, (BooleanKeyFrameAnimation)obj, node),
|
||||
CompositionObjectType.ColorKeyFrameAnimation => GenerateColorKeyFrameAnimationFactory(builder, (ColorKeyFrameAnimation)obj, node),
|
||||
CompositionObjectType.CompositionColorBrush => GenerateCompositionColorBrushFactory(builder, (CompositionColorBrush)obj, node),
|
||||
|
@ -2001,23 +2001,37 @@ namespace CommunityToolkit.WinUI.Lottie.UIData.CodeGen
|
|||
}
|
||||
|
||||
if (_configuration.ImplementCreateAndDestroyMethods)
|
||||
{
|
||||
if (animator.Controller is not null && animator.Controller.IsCustom)
|
||||
{
|
||||
_createAnimationsCodeBuilder
|
||||
.WriteLine($"{localName}{Deref}StartAnimation({String(animator.AnimatedProperty)}, {animationFactoryCall}, {CallFactoryFromFor(node, NodeFor(animator.Controller))});");
|
||||
}
|
||||
else
|
||||
{
|
||||
_createAnimationsCodeBuilder
|
||||
.WriteLine($"{localName}{Deref}StartAnimation({String(animator.AnimatedProperty)}, {animationFactoryCall});");
|
||||
|
||||
ConfigureAnimationController(_createAnimationsCodeBuilder, localName, ref controllerVariableAdded, animator);
|
||||
}
|
||||
|
||||
// If we are implementing IAnimatedVisual2 we should also write a destruction call.
|
||||
_destroyAnimationsCodeBuilder
|
||||
.WriteLine($"{localName}{Deref}StopAnimation({String(animator.AnimatedProperty)});");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (animator.Controller is not null && animator.Controller.IsCustom)
|
||||
{
|
||||
builder.WriteLine($"{localName}{Deref}StartAnimation({String(animator.AnimatedProperty)}, {animationFactoryCall}, {CallFactoryFromFor(node, NodeFor(animator.Controller))});");
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.WriteLine($"{localName}{Deref}StartAnimation({String(animator.AnimatedProperty)}, {animationFactoryCall});");
|
||||
ConfigureAnimationController(builder, localName, ref controllerVariableAdded, animator);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigureAnimationController(CodeBuilder builder, string localName, ref bool controllerVariableAdded, CompositionObject.Animator animator)
|
||||
{
|
||||
|
@ -2528,6 +2542,27 @@ namespace CommunityToolkit.WinUI.Lottie.UIData.CodeGen
|
|||
InitializeCompositionAnimation(builder, animation, node);
|
||||
}
|
||||
|
||||
bool GenerateCustomAnimationController(CodeBuilder builder, AnimationController obj, ObjectData node)
|
||||
{
|
||||
if (!obj.IsCustom)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
WriteObjectFactoryStart(builder, node);
|
||||
|
||||
WriteCreateAssignment(builder, node, $"_c{Deref}Create{obj.Type}()");
|
||||
|
||||
if (obj.IsPaused)
|
||||
{
|
||||
builder.WriteLine($"result{Deref}Pause();");
|
||||
}
|
||||
|
||||
WriteCompositionObjectFactoryEnd(builder, obj, node);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GenerateBooleanKeyFrameAnimationFactory(CodeBuilder builder, BooleanKeyFrameAnimation obj, ObjectData node)
|
||||
{
|
||||
WriteObjectFactoryStart(builder, node);
|
||||
|
@ -3442,7 +3477,7 @@ namespace CommunityToolkit.WinUI.Lottie.UIData.CodeGen
|
|||
{
|
||||
// AnimationController is never created explicitly - they result from
|
||||
// calling TryGetAnimationController(...).
|
||||
CompositionObjectType.AnimationController => false,
|
||||
CompositionObjectType.AnimationController => ((AnimationController)obj).IsCustom,
|
||||
|
||||
// CompositionPropertySet is never created explicitly - they just exist
|
||||
// on the Properties property of every CompositionObject.
|
||||
|
|
|
@ -16,9 +16,18 @@ namespace CommunityToolkit.WinUI.Lottie.WinCompData
|
|||
TargetProperty = targetProperty;
|
||||
}
|
||||
|
||||
public CompositionObject TargetObject { get; }
|
||||
internal AnimationController()
|
||||
{
|
||||
}
|
||||
|
||||
public string TargetProperty { get; }
|
||||
// AnimationController can be created separately from an composition animation,
|
||||
// in this case it will be marked as "Custom", it does not have TargetObject and TargetProperty.
|
||||
// Custom controller should be configured only once and then can be used for many animations.
|
||||
public bool IsCustom => TargetObject is null;
|
||||
|
||||
public CompositionObject? TargetObject { get; }
|
||||
|
||||
public string? TargetProperty { get; }
|
||||
|
||||
public bool IsPaused { get; private set; }
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
|
||||
namespace CommunityToolkit.WinUI.Lottie.WinCompData
|
||||
|
@ -116,11 +117,13 @@ namespace CommunityToolkit.WinUI.Lottie.WinCompData
|
|||
public CompositionPropertySet Properties { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Binds an animation to a property.
|
||||
/// Binds an animation to a property with a given custom controller.
|
||||
/// </summary>
|
||||
/// <param name="target">The name of the property.</param>
|
||||
/// <param name="animation">The animation.</param>
|
||||
public void StartAnimation(string target, CompositionAnimation animation)
|
||||
/// <param name="customController">Custom controller.</param>
|
||||
/// <returns>New animator.</returns>
|
||||
public Animator StartAnimation(string target, CompositionAnimation animation, AnimationController? customController)
|
||||
{
|
||||
// Remove any existing animation.
|
||||
StopAnimation(target);
|
||||
|
@ -133,6 +136,13 @@ namespace CommunityToolkit.WinUI.Lottie.WinCompData
|
|||
? null
|
||||
: new AnimationController(this, target);
|
||||
|
||||
if (customController is not null)
|
||||
{
|
||||
Debug.Assert(customController.IsCustom, "Should be custom!");
|
||||
Debug.Assert(animation is not ExpressionAnimation, "Should not be ExpressionAnimation!");
|
||||
controller = customController;
|
||||
}
|
||||
|
||||
var animator = new Animator(
|
||||
animatedProperty: target,
|
||||
animatedObject: this,
|
||||
|
@ -140,8 +150,17 @@ namespace CommunityToolkit.WinUI.Lottie.WinCompData
|
|||
controller: controller);
|
||||
|
||||
_animators.Add(animator);
|
||||
return animator;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Binds an animation to a property.
|
||||
/// </summary>
|
||||
/// <param name="target">The name of the property.</param>
|
||||
/// <param name="animation">The animation.</param>
|
||||
/// <returns>New animator.</returns>
|
||||
public Animator StartAnimation(string target, CompositionAnimation animation) => StartAnimation(target, animation, null);
|
||||
|
||||
/// <summary>
|
||||
/// Stops an animation that was previously started.
|
||||
/// </summary>
|
||||
|
@ -230,7 +249,7 @@ namespace CommunityToolkit.WinUI.Lottie.WinCompData
|
|||
/// The controller for this <see cref="Animator"/> or null
|
||||
/// if the animation is an <see cref="ExpressionAnimation"/>.
|
||||
/// </summary>
|
||||
public AnimationController? Controller { get; }
|
||||
public AnimationController? Controller { get; private set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string ToString() => AnimatedProperty;
|
||||
|
|
|
@ -13,6 +13,8 @@ namespace CommunityToolkit.WinUI.Lottie.WinCompData
|
|||
#endif
|
||||
sealed class Compositor
|
||||
{
|
||||
public AnimationController CreateAnimationController() => new AnimationController();
|
||||
|
||||
public BooleanKeyFrameAnimation CreateBooleanKeyFrameAnimation() => new BooleanKeyFrameAnimation();
|
||||
|
||||
public CompositionColorBrush CreateColorBrush() => new CompositionColorBrush();
|
||||
|
|
Загрузка…
Ссылка в новой задаче