Add nullable attributes, TimeSpan and overloads to Skottie (#2119)
* Add nullable attibutes and overloads to Skottie * Changed Duration to TimeSpan * Update xample to use new APIs
This commit is contained in:
Родитель
917a4b58f8
Коммит
297d6bfc5b
|
@ -1,7 +1,6 @@
|
|||
using System;
|
||||
using System.ComponentModel;
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using SkiaSharp.SceneGraph;
|
||||
|
||||
namespace SkiaSharp.Skottie
|
||||
|
@ -22,27 +21,54 @@ namespace SkiaSharp.Skottie
|
|||
protected override void DisposeNative ()
|
||||
=> SkottieApi.skottie_animation_delete (Handle);
|
||||
|
||||
public static bool TryParse (string data, out Animation animation)
|
||||
public static Animation? Parse (string json) =>
|
||||
TryParse (json, out var animation)
|
||||
? animation
|
||||
: null;
|
||||
|
||||
public static bool TryParse (string json, [System.Diagnostics.CodeAnalysis.NotNullWhen (true)] out Animation? animation)
|
||||
{
|
||||
animation = GetObject (SkottieApi.skottie_animation_make_from_string (data, data.Length));
|
||||
_ = json ?? throw new ArgumentNullException (nameof (json));
|
||||
|
||||
animation = GetObject (SkottieApi.skottie_animation_make_from_string (json, json.Length));
|
||||
return animation != null;
|
||||
}
|
||||
|
||||
public static bool TryCreate (Stream stream, out Animation animation)
|
||||
public static Animation? Create (Stream stream) =>
|
||||
TryCreate (stream, out var animation)
|
||||
? animation
|
||||
: null;
|
||||
|
||||
public static bool TryCreate (Stream stream, [System.Diagnostics.CodeAnalysis.NotNullWhen (true)] out Animation? animation)
|
||||
{
|
||||
using (var managed = new SKManagedStream (stream)) {
|
||||
return TryCreate (managed, out animation);
|
||||
}
|
||||
_ = stream ?? throw new ArgumentNullException (nameof (stream));
|
||||
|
||||
using var managed = new SKManagedStream (stream);
|
||||
return TryCreate (managed, out animation);
|
||||
}
|
||||
|
||||
public static bool TryCreate (SKStream stream, out Animation animation)
|
||||
public static Animation? Create (SKStream stream) =>
|
||||
TryCreate (stream, out var animation)
|
||||
? animation
|
||||
: null;
|
||||
|
||||
public static bool TryCreate (SKStream stream, [System.Diagnostics.CodeAnalysis.NotNullWhen (true)] out Animation? animation)
|
||||
{
|
||||
_ = stream ?? throw new ArgumentNullException (nameof (stream));
|
||||
|
||||
animation = GetObject (SkottieApi.skottie_animation_make_from_stream (stream.Handle));
|
||||
return animation != null;
|
||||
}
|
||||
|
||||
public static bool TryCreate (string path, out Animation animation)
|
||||
public static Animation? Create (string path) =>
|
||||
TryCreate (path, out var animation)
|
||||
? animation
|
||||
: null;
|
||||
|
||||
public static bool TryCreate (string path, [System.Diagnostics.CodeAnalysis.NotNullWhen (true)] out Animation? animation)
|
||||
{
|
||||
_ = path ?? throw new ArgumentNullException (nameof (path));
|
||||
|
||||
animation = GetObject (SkottieApi.skottie_animation_make_from_file (path));
|
||||
return animation != null;
|
||||
}
|
||||
|
@ -53,17 +79,20 @@ namespace SkiaSharp.Skottie
|
|||
public void Render (SKCanvas canvas, SKRect dst, AnimationRenderFlags flags)
|
||||
=> SkottieApi.skottie_animation_render_with_flags (Handle, canvas.Handle, &dst, flags);
|
||||
|
||||
public void Seek (double t, InvalidationController ic = null)
|
||||
=> SkottieApi.skottie_animation_seek (Handle, (float)t, ic?.Handle ?? IntPtr.Zero);
|
||||
public void Seek (double percent, InvalidationController? ic = null)
|
||||
=> SkottieApi.skottie_animation_seek (Handle, (float)percent, ic?.Handle ?? IntPtr.Zero);
|
||||
|
||||
public void SeekFrame (double t, InvalidationController ic = null)
|
||||
=> SkottieApi.skottie_animation_seek_frame (Handle, (float)t, ic?.Handle ?? IntPtr.Zero);
|
||||
public void SeekFrame (double frame, InvalidationController? ic = null)
|
||||
=> SkottieApi.skottie_animation_seek_frame (Handle, (float)frame, ic?.Handle ?? IntPtr.Zero);
|
||||
|
||||
public void SeekFrameTime (double t, InvalidationController ic = null)
|
||||
=> SkottieApi.skottie_animation_seek_frame_time (Handle, (float)t, ic?.Handle ?? IntPtr.Zero);
|
||||
public void SeekFrameTime (double seconds, InvalidationController? ic = null)
|
||||
=> SkottieApi.skottie_animation_seek_frame_time (Handle, (float)seconds, ic?.Handle ?? IntPtr.Zero);
|
||||
|
||||
public double Duration
|
||||
=> SkottieApi.skottie_animation_get_duration (Handle);
|
||||
public void SeekFrameTime (TimeSpan time, InvalidationController? ic = null)
|
||||
=> SeekFrameTime (time.TotalSeconds, ic);
|
||||
|
||||
public TimeSpan Duration
|
||||
=> TimeSpan.FromSeconds(SkottieApi.skottie_animation_get_duration (Handle));
|
||||
|
||||
public double Fps
|
||||
=> SkottieApi.skottie_animation_get_fps (Handle);
|
||||
|
@ -77,9 +106,7 @@ namespace SkiaSharp.Skottie
|
|||
public string Version {
|
||||
get {
|
||||
using var str = new SKString ();
|
||||
|
||||
SkottieApi.skottie_animation_get_version (Handle, str.Handle);
|
||||
|
||||
return str.ToString ();
|
||||
}
|
||||
}
|
||||
|
@ -92,7 +119,7 @@ namespace SkiaSharp.Skottie
|
|||
}
|
||||
}
|
||||
|
||||
internal static Animation GetObject (IntPtr handle) =>
|
||||
internal static Animation? GetObject (IntPtr handle) =>
|
||||
handle == IntPtr.Zero ? null : new Animation (handle, true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using SkiaSharp;
|
||||
|
@ -12,24 +9,12 @@ namespace SkiaSharpSample.Samples
|
|||
[Preserve(AllMembers = true)]
|
||||
public class SkottieSample : AnimatedSampleBase
|
||||
{
|
||||
private readonly Animation _animation;
|
||||
private Animation _animation;
|
||||
private Stopwatch _watch = new Stopwatch();
|
||||
|
||||
[Preserve]
|
||||
public SkottieSample()
|
||||
{
|
||||
using var fileStream = new SKManagedStream(SampleMedia.Images.LottieLogo);
|
||||
|
||||
if (SkiaSharp.Skottie.Animation.TryCreate(fileStream, out _animation))
|
||||
{
|
||||
_animation.Seek(0, null);
|
||||
|
||||
Console.WriteLine($"SkottieSample(): Version:{_animation.Version} Duration:{_animation.Duration} Fps:{_animation.Fps} InPoint:{_animation.InPoint} OutPoint:{_animation.OutPoint}");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"SkottieSample(): failed to load animation");
|
||||
}
|
||||
}
|
||||
|
||||
public override string Title => "Skottie";
|
||||
|
@ -38,47 +23,35 @@ namespace SkiaSharpSample.Samples
|
|||
|
||||
protected override async Task OnInit()
|
||||
{
|
||||
try
|
||||
{
|
||||
await base.OnInit();
|
||||
|
||||
_watch.Start();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e);
|
||||
}
|
||||
_animation = Animation.Create(SampleMedia.Images.LottieLogo);
|
||||
_animation.Seek(0, null);
|
||||
|
||||
_watch.Start();
|
||||
|
||||
await base.OnInit();
|
||||
}
|
||||
|
||||
protected override async Task OnUpdate(CancellationToken token)
|
||||
{
|
||||
try
|
||||
{
|
||||
await Task.Delay(25, token);
|
||||
if (_animation == null)
|
||||
return;
|
||||
|
||||
_animation.SeekFrameTime((float)_watch.Elapsed.TotalSeconds, null);
|
||||
await Task.Delay(25, token);
|
||||
|
||||
if(_watch.Elapsed.TotalSeconds > _animation.Duration)
|
||||
{
|
||||
_watch.Restart();
|
||||
}
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
Console.WriteLine(e);
|
||||
}
|
||||
_animation.SeekFrameTime(_watch.Elapsed);
|
||||
|
||||
if (_watch.Elapsed > _animation.Duration)
|
||||
_watch.Restart();
|
||||
}
|
||||
|
||||
protected override void OnDrawSample(SKCanvas canvas, int width, int height)
|
||||
{
|
||||
try
|
||||
{
|
||||
_animation.Render(canvas, new SKRect(0, 0, width, height));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e);
|
||||
}
|
||||
if (_animation == null)
|
||||
return;
|
||||
|
||||
canvas.Clear(SKColors.White);
|
||||
|
||||
_animation.Render(canvas, new SKRect(0, 0, width, height));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,93 +1,130 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Xunit;
|
||||
using System.IO;
|
||||
using SkiaSharp.SceneGraph;
|
||||
using SkiaSharp.Skottie;
|
||||
using Xunit;
|
||||
|
||||
namespace SkiaSharp.Tests
|
||||
{
|
||||
public class AnimationTest : SKTest
|
||||
{
|
||||
[Trait(CategoryKey, ApiCategory)]
|
||||
[SkippableFact]
|
||||
public void When_Default_Make()
|
||||
public void When_Default_TryParse()
|
||||
{
|
||||
var path = Path.Combine(PathToImages, "LottieLogo1.json");
|
||||
var result = Animation.TryParse(File.ReadAllText(path), out var animation);
|
||||
|
||||
var result = SkiaSharp.Skottie.Animation.TryParse(File.ReadAllText(path), out var animation);
|
||||
Assert.True(result);
|
||||
Assert.NotEqual(IntPtr.Zero, animation?.Handle);
|
||||
Assert.NotNull(animation);
|
||||
Assert.NotEqual(IntPtr.Zero, animation.Handle);
|
||||
}
|
||||
|
||||
[Trait(CategoryKey, ApiCategory)]
|
||||
[SkippableFact]
|
||||
public void When_Default_Make_From_SKStream()
|
||||
public void When_Default_Parse()
|
||||
{
|
||||
var path = Path.Combine(PathToImages, "LottieLogo1.json");
|
||||
var animation = Animation.Parse(File.ReadAllText(path));
|
||||
|
||||
Assert.NotNull(animation);
|
||||
Assert.NotEqual(IntPtr.Zero, animation.Handle);
|
||||
}
|
||||
|
||||
[SkippableFact]
|
||||
public void When_Default_TryCreate_From_SKStream()
|
||||
{
|
||||
var path = Path.Combine(PathToImages, "LottieLogo1.json");
|
||||
using var fileStream = File.OpenRead(path);
|
||||
using var managedStream = new SKManagedStream(fileStream);
|
||||
var result = SkiaSharp.Skottie.Animation.TryCreate(managedStream, out var animation);
|
||||
var result = Animation.TryCreate(managedStream, out var animation);
|
||||
|
||||
Assert.True(result);
|
||||
Assert.NotNull(animation);
|
||||
Assert.NotEqual(IntPtr.Zero, animation.Handle);
|
||||
}
|
||||
|
||||
[SkippableFact]
|
||||
public void When_Default_Create_From_SKStream()
|
||||
{
|
||||
var path = Path.Combine(PathToImages, "LottieLogo1.json");
|
||||
using var fileStream = File.OpenRead(path);
|
||||
using var managedStream = new SKManagedStream(fileStream);
|
||||
var animation = Animation.Create(managedStream);
|
||||
|
||||
Assert.NotNull(animation);
|
||||
Assert.NotEqual(IntPtr.Zero, animation.Handle);
|
||||
}
|
||||
|
||||
[SkippableFact]
|
||||
public void When_Default_TryCreate_From_Stream()
|
||||
{
|
||||
var path = Path.Combine(PathToImages, "LottieLogo1.json");
|
||||
using var fileStream = File.OpenRead(path);
|
||||
var result = Animation.TryCreate(fileStream, out var animation);
|
||||
|
||||
Assert.True(result);
|
||||
Assert.NotEqual(IntPtr.Zero, animation?.Handle);
|
||||
}
|
||||
|
||||
[Trait(CategoryKey, ApiCategory)]
|
||||
[SkippableFact]
|
||||
public void When_Default_Make_From_Stream()
|
||||
public void When_Default_Create_From_Stream()
|
||||
{
|
||||
var path = Path.Combine(PathToImages, "LottieLogo1.json");
|
||||
|
||||
using var fileStream = File.OpenRead(path);
|
||||
var result = SkiaSharp.Skottie.Animation.TryCreate(fileStream, out var animation);
|
||||
var animation = Animation.Create(fileStream);
|
||||
|
||||
Assert.NotNull(animation);
|
||||
Assert.NotEqual(IntPtr.Zero, animation.Handle);
|
||||
}
|
||||
|
||||
[SkippableFact]
|
||||
public void When_Default_TryCreate_From_File()
|
||||
{
|
||||
var path = Path.Combine(PathToImages, "LottieLogo1.json");
|
||||
var result = Animation.TryCreate(path, out var animation);
|
||||
|
||||
Assert.True(result);
|
||||
Assert.NotEqual(IntPtr.Zero, animation?.Handle);
|
||||
}
|
||||
|
||||
[Trait(CategoryKey, ApiCategory)]
|
||||
[SkippableFact]
|
||||
public void When_Seek_Without_Controller()
|
||||
public void When_Default_Create_From_File()
|
||||
{
|
||||
var path = Path.Combine(PathToImages, "LottieLogo1.json");
|
||||
var animation = Animation.Create(path);
|
||||
|
||||
using var fileStream = File.OpenRead(path);
|
||||
var result = SkiaSharp.Skottie.Animation.TryCreate(fileStream, out var animation);
|
||||
Assert.True(result);
|
||||
Assert.NotEqual(IntPtr.Zero, animation?.Handle);
|
||||
|
||||
animation.Seek(.1);
|
||||
}
|
||||
|
||||
[Trait(CategoryKey, ApiCategory)]
|
||||
[SkippableFact]
|
||||
public void When_Seek_With_Controller()
|
||||
{
|
||||
var path = Path.Combine(PathToImages, "LottieLogo1.json");
|
||||
|
||||
using var fileStream = File.OpenRead(path);
|
||||
var result = SkiaSharp.Skottie.Animation.TryCreate(fileStream, out var animation);
|
||||
Assert.True(result);
|
||||
Assert.NotEqual(IntPtr.Zero, animation?.Handle);
|
||||
|
||||
var controller = new InvalidationController();
|
||||
|
||||
animation.Seek(.1, controller);
|
||||
Assert.NotNull(animation);
|
||||
Assert.NotEqual(IntPtr.Zero, animation.Handle);
|
||||
}
|
||||
|
||||
private Animation BuildDefaultAnimation()
|
||||
{
|
||||
var path = Path.Combine(PathToImages, "LottieLogo1.json");
|
||||
var result = Animation.TryCreate(path, out var animation);
|
||||
|
||||
using var fileStream = File.OpenRead(path);
|
||||
var result = SkiaSharp.Skottie.Animation.TryCreate(fileStream, out var animation);
|
||||
Assert.True(result);
|
||||
Assert.NotEqual(IntPtr.Zero, animation?.Handle);
|
||||
|
||||
return animation;
|
||||
}
|
||||
|
||||
[Trait(CategoryKey, ApiCategory)]
|
||||
[SkippableFact]
|
||||
public void When_Seek_Without_Controller()
|
||||
{
|
||||
var animation = BuildDefaultAnimation();
|
||||
|
||||
animation.Seek(.1);
|
||||
}
|
||||
|
||||
[SkippableFact]
|
||||
public void When_Seek_With_Controller()
|
||||
{
|
||||
var animation = BuildDefaultAnimation();
|
||||
|
||||
var controller = new InvalidationController();
|
||||
|
||||
animation.Seek(.1, controller);
|
||||
}
|
||||
|
||||
[SkippableFact]
|
||||
public void When_SeekFrame_Without_Controller()
|
||||
{
|
||||
|
@ -96,7 +133,6 @@ namespace SkiaSharp.Tests
|
|||
animation.SeekFrame(.1);
|
||||
}
|
||||
|
||||
[Trait(CategoryKey, ApiCategory)]
|
||||
[SkippableFact]
|
||||
public void When_SeekFrame_With_Controller()
|
||||
{
|
||||
|
@ -107,7 +143,6 @@ namespace SkiaSharp.Tests
|
|||
animation.SeekFrame(.1, controller);
|
||||
}
|
||||
|
||||
[Trait(CategoryKey, ApiCategory)]
|
||||
[SkippableFact]
|
||||
public void When_SeekFrameTime_Without_Controller()
|
||||
{
|
||||
|
@ -116,7 +151,6 @@ namespace SkiaSharp.Tests
|
|||
animation.SeekFrameTime(.1);
|
||||
}
|
||||
|
||||
[Trait(CategoryKey, ApiCategory)]
|
||||
[SkippableFact]
|
||||
public void When_SeekFrameTime_With_Controller()
|
||||
{
|
||||
|
@ -127,58 +161,70 @@ namespace SkiaSharp.Tests
|
|||
animation.SeekFrameTime(.1, controller);
|
||||
}
|
||||
|
||||
[Trait(CategoryKey, ApiCategory)]
|
||||
[SkippableFact]
|
||||
public void When_SeekFrameTimeSpan_Without_Controller()
|
||||
{
|
||||
var animation = BuildDefaultAnimation();
|
||||
|
||||
animation.SeekFrameTime(TimeSpan.FromSeconds(.1));
|
||||
}
|
||||
|
||||
[SkippableFact]
|
||||
public void When_SeekFrameTimeSpan_With_Controller()
|
||||
{
|
||||
var animation = BuildDefaultAnimation();
|
||||
|
||||
var controller = new InvalidationController();
|
||||
|
||||
animation.SeekFrameTime(TimeSpan.FromSeconds(.1), controller);
|
||||
}
|
||||
|
||||
[SkippableFact]
|
||||
public void When_Duration()
|
||||
{
|
||||
var animation = BuildDefaultAnimation();
|
||||
|
||||
Assert.True(animation.Duration > 0);
|
||||
Assert.Equal(TimeSpan.FromSeconds(5.9666666), animation.Duration);
|
||||
}
|
||||
|
||||
[Trait(CategoryKey, ApiCategory)]
|
||||
[SkippableFact]
|
||||
public void When_Fps()
|
||||
{
|
||||
var animation = BuildDefaultAnimation();
|
||||
|
||||
Assert.True(animation.Fps == 30);
|
||||
Assert.Equal(30, animation.Fps);
|
||||
}
|
||||
|
||||
[Trait(CategoryKey, ApiCategory)]
|
||||
[SkippableFact]
|
||||
public void When_InPoint()
|
||||
{
|
||||
var animation = BuildDefaultAnimation();
|
||||
|
||||
Assert.True(animation.InPoint == 0);
|
||||
Assert.Equal(0, animation.InPoint);
|
||||
}
|
||||
|
||||
[Trait(CategoryKey, ApiCategory)]
|
||||
[SkippableFact]
|
||||
public void When_OutPoint()
|
||||
{
|
||||
var animation = BuildDefaultAnimation();
|
||||
|
||||
Assert.True(animation.OutPoint > 0);
|
||||
Assert.Equal(179, animation.OutPoint);
|
||||
}
|
||||
|
||||
[Trait(CategoryKey, ApiCategory)]
|
||||
[SkippableFact]
|
||||
public void When_Version()
|
||||
{
|
||||
var animation = BuildDefaultAnimation();
|
||||
|
||||
Assert.True(animation.Version.Length > 0);
|
||||
Assert.Equal("4.4.26", animation.Version);
|
||||
}
|
||||
|
||||
[Trait(CategoryKey, ApiCategory)]
|
||||
[SkippableFact]
|
||||
public void When_Size()
|
||||
{
|
||||
var animation = BuildDefaultAnimation();
|
||||
|
||||
Assert.True(animation.Size.Height > 0);
|
||||
Assert.Equal(new SKSize(375, 667), animation.Size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче