This commit is contained in:
Wiesław Šoltés 2023-06-05 21:48:38 +02:00
Родитель fd4c6ff283
Коммит 3b2b6e22ef
4 изменённых файлов: 142 добавлений и 99 удалений

Просмотреть файл

@ -108,6 +108,70 @@ public class Lottie : Control
_baseUri = serviceProvider.GetContextBaseUri();
}
/// <inheritdoc/>
protected override void OnLoaded()
{
base.OnLoaded();
var elemVisual = ElementComposition.GetElementVisual(this);
var compositor = elemVisual?.Compositor;
if (compositor is null)
{
return;
}
_customVisual = compositor.CreateCustomVisual(new LottieCompositionCustomVisualHandler());
ElementComposition.SetElementChildVisual(this, _customVisual);
LayoutUpdated += OnLayoutUpdated;
if (_preloadPath is null)
{
return;
}
DisposeImpl();
Load(_preloadPath);
_customVisual.Size = new Vector2((float)Bounds.Size.Width, (float)Bounds.Size.Height);
_customVisual.SendHandlerMessage(
new LottiePayload(
LottieCommand.Update,
_animation,
Stretch,
StretchDirection));
Start();
_preloadPath = null;
}
protected override void OnUnloaded()
{
base.OnUnloaded();
LayoutUpdated -= OnLayoutUpdated;
Stop();
DisposeImpl();
}
private void OnLayoutUpdated(object? sender, EventArgs e)
{
if (_customVisual == null)
{
return;
}
_customVisual.Size = new Vector2((float)Bounds.Size.Width, (float)Bounds.Size.Height);
_customVisual.SendHandlerMessage(
new LottiePayload(
LottieCommand.Update,
_animation,
Stretch,
StretchDirection));
}
/// <inheritdoc/>
protected override Size MeasureOverride(Size availableSize)
{
if (_animation == null)
@ -122,52 +186,6 @@ public class Lottie : Control
return Stretch.CalculateSize(availableSize, sourceSize, StretchDirection);
}
protected override void OnLoaded()
{
var elemVisual = ElementComposition.GetElementVisual(this);
var compositor = elemVisual?.Compositor;
if (compositor is null)
{
return;
}
_customVisual = compositor.CreateCustomVisual(new LottieCustomVisualHandler());
ElementComposition.SetElementChildVisual(this, _customVisual);
LayoutUpdated += OnLayoutUpdated;
base.OnLoaded();
if (_preloadPath is null)
{
return;
}
DisposeImpl();
Load(_preloadPath);
_customVisual.Size = new Vector2((float)Bounds.Size.Width, (float)Bounds.Size.Height);
_customVisual.SendHandlerMessage(new LottieCustomVisualHandler.Payload(
LottieCustomVisualHandler.Command.Update,
_animation,
Stretch,
StretchDirection));
Start();
_preloadPath = null;
}
private void OnLayoutUpdated(object sender, EventArgs e)
{
if (_customVisual == null) return;
_customVisual.Size = new Vector2((float)Bounds.Size.Width, (float)Bounds.Size.Height);
_customVisual.SendHandlerMessage(
new LottieCustomVisualHandler.Payload(
LottieCustomVisualHandler.Command.Update,
_animation,
Stretch,
StretchDirection));
}
protected override Size ArrangeOverride(Size finalSize)
{
if (_animation == null)
@ -212,12 +230,6 @@ public class Lottie : Control
}
}
private void Stop()
{
_customVisual?.SendHandlerMessage(
new LottieCustomVisualHandler.Payload(LottieCustomVisualHandler.Command.Stop));
}
private SkiaSharp.Skottie.Animation? Load(Stream stream)
{
using var managedStream = new SKManagedStream(stream);
@ -227,12 +239,13 @@ public class Lottie : Control
Logger
.TryGet(LogEventLevel.Information, LogArea.Control)?
.Log(this,
$"Version: {animation.Version} Duration: {animation.Duration} Fps:{animation.Fps} InPoint: {animation.InPoint} OutPoint: {animation.OutPoint}");
.Log(this, $"Version: {animation.Version} Duration: {animation.Duration} Fps:{animation.Fps} InPoint: {animation.InPoint} OutPoint: {animation.OutPoint}");
}
else
{
Logger.TryGet(LogEventLevel.Warning, LogArea.Control)?.Log(this, "Failed to load animation.");
Logger
.TryGet(LogEventLevel.Warning, LogArea.Control)?
.Log(this, "Failed to load animation.");
}
return animation;
@ -240,7 +253,9 @@ public class Lottie : Control
private SkiaSharp.Skottie.Animation? Load(string path, Uri? baseUri)
{
var uri = path.StartsWith("/") ? new Uri(path, UriKind.Relative) : new Uri(path, UriKind.RelativeOrAbsolute);
var uri = path.StartsWith("/")
? new Uri(path, UriKind.Relative)
: new Uri(path, UriKind.RelativeOrAbsolute);
if (uri.IsAbsoluteUri && uri.IsFile)
{
using var fileStream = File.OpenRead(uri.LocalPath);
@ -264,7 +279,6 @@ public class Lottie : Control
if (path is null)
{
DisposeImpl();
return;
}
@ -274,6 +288,7 @@ public class Lottie : Control
{
_repeatCount = RepeatCount;
_animation = Load(path, _baseUri);
if (_animation is null)
{
return;
@ -286,21 +301,31 @@ public class Lottie : Control
}
catch (Exception e)
{
Logger.TryGet(LogEventLevel.Warning, LogArea.Control)?.Log(this, "Failed to load animation: " + e);
Logger
.TryGet(LogEventLevel.Warning, LogArea.Control)?
.Log(this, "Failed to load animation: " + e);
_animation = null;
}
}
private void DisposeImpl()
{
_customVisual?.SendHandlerMessage(
new LottieCustomVisualHandler.Payload(LottieCustomVisualHandler.Command.Dispose));
}
private void Start()
{
_customVisual?.SendHandlerMessage(new LottieCustomVisualHandler.Payload(LottieCustomVisualHandler.Command.Start,
_animation,
Stretch, StretchDirection, _repeatCount));
_customVisual?.SendHandlerMessage(
new LottiePayload(
LottieCommand.Start,
_animation,
Stretch,
StretchDirection,
_repeatCount));
}
private void Stop()
{
_customVisual?.SendHandlerMessage(new LottiePayload(LottieCommand.Stop));
}
private void DisposeImpl()
{
_customVisual?.SendHandlerMessage(new LottiePayload(LottieCommand.Dispose));
}
}

Просмотреть файл

@ -0,0 +1,9 @@
namespace Avalonia.Skia.Lottie;
internal enum LottieCommand
{
Start,
Stop,
Update,
Dispose
}

Просмотреть файл

@ -6,7 +6,7 @@ using SkiaSharp;
namespace Avalonia.Skia.Lottie;
internal class LottieCustomVisualHandler : CompositionCustomVisualHandler
internal class LottieCompositionCustomVisualHandler : CompositionCustomVisualHandler
{
private TimeSpan _primaryTimeElapsed, _animationElapsed;
private TimeSpan? _lastServerTime;
@ -19,35 +19,24 @@ internal class LottieCustomVisualHandler : CompositionCustomVisualHandler
private int _repeatCount;
private int _count;
public enum Command
{
Start,
Stop,
Update,
Dispose
}
public record struct Payload(
Command Command,
SkiaSharp.Skottie.Animation? Animation = null,
Stretch? Stretch = null,
StretchDirection? StretchDirection = null,
int? RepeatCount = null);
public override void OnMessage(object message)
{
if (message is not Payload msg) return;
if (message is not LottiePayload msg)
{
return;
}
switch (msg)
{
case
{
Command: Command.Start,
LottieCommand: LottieCommand.Start,
Animation: { } an,
Stretch: { } st,
StretchDirection: { } sd,
RepeatCount: { } rp
}:
{
_running = true;
_lastServerTime = null;
_stretch = st;
@ -58,24 +47,37 @@ internal class LottieCustomVisualHandler : CompositionCustomVisualHandler
_animationElapsed = TimeSpan.Zero;
RegisterForNextAnimationFrameUpdate();
break;
}
case
{
Command: Command.Update,
LottieCommand: LottieCommand.Update,
Stretch: { } st,
StretchDirection: { } sd
}:
{
_stretch = st;
_stretchDirection = sd;
RegisterForNextAnimationFrameUpdate();
break;
case {Command: Command.Stop}:
}
case
{
LottieCommand: LottieCommand.Stop
}:
{
_running = false;
_animationElapsed = TimeSpan.Zero;
_count = 0;
break;
case {Command: Command.Dispose}:
}
case
{
LottieCommand: LottieCommand.Dispose
}:
{
DisposeImpl();
break;
}
}
}
@ -95,7 +97,6 @@ internal class LottieCustomVisualHandler : CompositionCustomVisualHandler
RegisterForNextAnimationFrameUpdate();
}
private void DisposeImpl()
{
lock (_sync)
@ -128,7 +129,7 @@ internal class LottieCustomVisualHandler : CompositionCustomVisualHandler
return frameTime;
}
private void SkottieDraw(SKCanvas canvas)
private void Draw(SKCanvas canvas)
{
var animation = _animation;
if (animation is null)
@ -158,14 +159,8 @@ internal class LottieCustomVisualHandler : CompositionCustomVisualHandler
var dst = new SKRect(0, 0, animation.Size.Width, animation.Size.Height);
animation.SeekFrameTime(t, ic);
// Debug.WriteLine($"dst: {dst}, ic.Bounds: {ic.Bounds}");
canvas.Save();
animation.Render(canvas, dst);
// canvas.DrawRect(ic.Bounds, new SKPaint { Color = SKColors.Magenta, Style = SKPaintStyle.Stroke, StrokeWidth = 1 });
canvas.Restore();
ic.Reset();
@ -187,8 +182,12 @@ internal class LottieCustomVisualHandler : CompositionCustomVisualHandler
_lastServerTime = CompositionNow;
}
if (_animation is not { } an || _stretch is not { } st || _stretchDirection is not { } sd) return;
if (_animation is not { } an
|| _stretch is not { } st
|| _stretchDirection is not { } sd)
{
return;
}
var leaseFeature = context.TryGetFeature<ISkiaSharpApiLeaseFeature>();
@ -231,7 +230,7 @@ internal class LottieCustomVisualHandler : CompositionCustomVisualHandler
{
return;
}
SkottieDraw(canvas);
Draw(canvas);
}
}
}

Просмотреть файл

@ -0,0 +1,10 @@
using Avalonia.Media;
namespace Avalonia.Skia.Lottie;
internal record struct LottiePayload(
LottieCommand LottieCommand,
SkiaSharp.Skottie.Animation? Animation = null,
Stretch? Stretch = null,
StretchDirection? StretchDirection = null,
int? RepeatCount = null);