Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

[DRAFT] Add LottieIsland and LottieWinRT for frameworkless or native applications #557

Open
wants to merge 45 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
03637d8
Moved Lottie Island project files over to this repo
getrou Mar 15, 2024
15673a6
SimpleIslandApp now calls into C# JSON loader and works end to end. H…
getrou Mar 15, 2024
f715f7b
Merge pull request #1 from getrou/getrou/c_sharp_sample_working
getrou Mar 15, 2024
7d583f3
Updated sample app to match FHL sample
getrou Mar 20, 2024
2669684
Changed LottieVisualSource2 to LottieVisualSourceFrameworkless and wr…
getrou Apr 12, 2024
3e107ef
Updated sample and LottieIsland to consume new interfaces
getrou Apr 16, 2024
0329c09
Removed unused projects, moved LottieWinRT over to custom interface
getrou Apr 18, 2024
9cf356a
Reduced CsWinRT issue down to simpler form, added logic to build scri…
getrou Apr 18, 2024
567d126
Changed LottieIsland.IAnimatedVisualSource to LottieIsland.IAnimatedV…
getrou Apr 18, 2024
aef4a7c
Moved LottieWinRT to be based on public Lottie-WinUI nuget package in…
getrou Apr 18, 2024
87525d0
Worked through threading issues from using C# events
getrou Apr 19, 2024
e7a6d2f
Test app working, loading Lottie. Working through small bug around re…
getrou Apr 19, 2024
381c02d
Add nuget restore for LottieIsland.vcxproj
getrou Apr 19, 2024
7263a34
Fix project references so everything builds out of the box with no cu…
getrou Apr 19, 2024
807c32a
Merge branch 'dev/getrou/lottie_island' into dev/getrou/lottie_island…
getrou Apr 19, 2024
8fd5e6b
Add nuget restore for SimpleLottieIslandApp.vcxproj
getrou Apr 19, 2024
b41d8fd
More project reference work
getrou Apr 19, 2024
66b537b
Add C# app and show how to consume nuget packages. (Only working in C…
getrou Apr 20, 2024
457d0b7
Clean up C# app and add comments
getrou Apr 20, 2024
10d8542
Remove C# sample app, change LottieIsland to take an AnimatedVisual
getrou Apr 24, 2024
623d418
Merge branch 'dev/getrou/lottie_island' into dev/getrou/lottie_island…
getrou Apr 24, 2024
ddcc1a6
Fixed LottieWinRT x86 project dependencies
getrou Apr 24, 2024
144a389
Fixed sample app Release configuration
getrou Apr 25, 2024
af22bdc
Can build from command line: msbuild .\Lottie-Windows.sln /p:Platform…
getrou Apr 25, 2024
7201843
Add nuget.config
getrou Apr 25, 2024
95e6616
Fixed up some more project configurations
getrou Apr 25, 2024
544cde6
Remove UWP samples from sln file to allow solution to build
getrou Apr 25, 2024
8d9c060
Fix pack targets
getrou Apr 25, 2024
5896c83
Cleaned up nuget generation
getrou Apr 25, 2024
9e92f8e
Make nuget package for LottieWinRT include projection DLLs for projec…
getrou Apr 25, 2024
1167c74
Remove AnyCPU from LottieWinRT
getrou Apr 25, 2024
b40f53f
Remove build target for LottieWinRT AnyCPU
getrou Apr 25, 2024
9a0ce7c
Removed a few comments
getrou Apr 25, 2024
0840bbb
Add Lottie-Windows-WinUI3-Controls project and package to remove the …
getrou Apr 26, 2024
32e0e81
Fixes to get build to succeed
getrou Apr 26, 2024
a542db3
Fixups for PR feedback
getrou Apr 26, 2024
05d2e1f
Remove outdated tooling, old .NET versions
getrou Apr 26, 2024
267afe5
Removed more unneeded code
getrou Apr 28, 2024
f91bf4d
Resolve merge conflicts with main
getrou Apr 28, 2024
d8752d4
Bump Lottie-Windows TFM to 19041
getrou Apr 29, 2024
845f6f3
Add UIA support
May 7, 2024
750f44c
Update version to 8.1 and start producing Controls package
getrou May 8, 2024
81b8438
Don't take the lock in Add/GetHandler in AutomationBase
getrou May 8, 2024
eac0dc2
Use AppData in LottieIsland
May 8, 2024
0945863
Merge pull request #558 from CommunityToolkit/user/adpa-ms/lottie_isl…
getrou May 9, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,9 @@ FakesAssemblies/
# Visual Studio 6 workspace options file
*.opt

# Visual Studio editor config file
.editorconfig

# LightSwitch generated files
GeneratedArtifacts/
_Pvt_Extensions/
Expand Down Expand Up @@ -234,4 +237,6 @@ msbuild.binlog
LottieGenOutput-*/

# Visual Studio debugging configuration file.
launchSettings.json
launchSettings.json

Generated Files/
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0-windows10.0.19041.0</TargetFramework>
<OutputType>Library</OutputType>
<IsPackable>true</IsPackable>
<PackageId>CommunityToolkit.WinUI.Lottie.Controls</PackageId>
<PackageTags>WinUI3 Toolkit Windows Animations Lottie XAML</PackageTags>

<Nullable>enable</Nullable>
<Platforms>x64;x86;ARM64</Platforms>
<CsWinRTIncludes>Microsoft</CsWinRTIncludes>
<SignAssembly>True</SignAssembly>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Graphics.Win2D" Version="1.0.4" />
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.5.240428000" />
<PackageReference Include="Microsoft.Windows.CsWinRT" Version="2.0.7" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Lottie-Windows\Lottie-Windows-WinUI3\Lottie-Windows-WinUI3.csproj" />
</ItemGroup>
</Project>
219 changes: 219 additions & 0 deletions Lottie-Windows-WinUI3-Controls/LottieVisualSourceWinUI.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#nullable enable

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading.Tasks;
using CommunityToolkit.WinAppSDK.LottieIsland;
using CommunityToolkit.WinUI.Lottie;
using Microsoft.UI.Composition;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Windows.Foundation;
using Windows.Foundation.Metadata;
using Windows.Storage;
using Windows.Storage.Streams;

namespace CommunityToolkit.WinUI.Lottie.Controls
Copy link
Member

Choose a reason for hiding this comment

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

Since we're adding new code, would be good to start switching to file-scoped namespaces and reduce indentation.

{
/// <summary>
/// An <see cref="IAnimatedVisualSource"/> for a Lottie composition. This allows
/// a Lottie to be specified as the source for a <see cref="AnimatedVisualPlayer"/>.
/// </summary>
public sealed class LottieVisualSourceWinUI : DependencyObject, IDynamicAnimatedVisualSource
Copy link
Member

Choose a reason for hiding this comment

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

Having WinUI in the class name seems really odd here as it's already part of the namespace. Do we need an alternate as LottieVisualSource is already used in the base library?

Will they ever both need to be used together though (if they're in different namespaces)?

I'm not completely looped into how this all works, but just trying to provide some general guidance when I saw the namespace/class names come up in the discussion.

{
LottieVisualSource _lottieVisualSource;

HashSet<TypedEventHandler<IDynamicAnimatedVisualSource?, object?>> _compositionInvalidatedEventTokenTable = new HashSet<TypedEventHandler<IDynamicAnimatedVisualSource?, object?>>();

/// <summary>
/// Gets the options for the <see cref="LottieVisualSourceWinUI"/>.
/// </summary>
// Optimize Lotties by default. Optimization takes a little longer but usually produces much
// more efficient translations. The only reason someone would turn optimization off is if
// the time to translate is too high, but in that case the Lottie is probably going to perform
// so badly on the machine that it won't really be usable with our without optimization.
public static DependencyProperty OptionsProperty { get; } =
RegisterDp(nameof(Options), LottieVisualOptions.Optimize);

/// <summary>
/// Gets the URI from which to load a JSON Lottie file.
/// </summary>
public static DependencyProperty UriSourceProperty { get; } =
RegisterDp<Uri>(nameof(UriSource), null,
(owner, oldValue, newValue) => owner._lottieVisualSource.UriSource = newValue);

static DependencyProperty RegisterDp<T>(string propertyName, T defaultValue) =>
DependencyProperty.Register(propertyName, typeof(T), typeof(LottieVisualSourceWinUI), new PropertyMetadata(defaultValue));

static DependencyProperty RegisterDp<T>(string propertyName, T? defaultValue, Action<LottieVisualSourceWinUI, T, T> callback)
where T : class
=>
DependencyProperty.Register(propertyName, typeof(T), typeof(LottieVisualSourceWinUI),
new PropertyMetadata(defaultValue, (d, e) => callback((LottieVisualSourceWinUI)d, (T)e.OldValue, (T)e.NewValue)));

/// <summary>
/// Initializes a new instance of the <see cref="LottieVisualSourceWinUI"/> class.
/// </summary>
public LottieVisualSourceWinUI()
{
_lottieVisualSource = new LottieVisualSource();
_lottieVisualSource.AnimatedVisualInvalidated += OnAnimatedVisualInvalidated;
}

public LottieVisualSourceWinUI(LottieVisualSource lottieVisualSource)
{
_lottieVisualSource = lottieVisualSource;
_lottieVisualSource.AnimatedVisualInvalidated += OnAnimatedVisualInvalidated;
}

/// <summary>
/// Gets or sets options for how the Lottie is loaded.
/// </summary>
public LottieVisualOptions Options
{
get => (LottieVisualOptions)GetValue(OptionsProperty);
set => SetValue(OptionsProperty, value);
}

/// <summary>
/// Gets or sets the Uniform Resource Identifier (URI) of the JSON source file for this <see cref="LottieVisualSourceWinUI"/>.
/// </summary>
public Uri UriSource
{
get => (Uri)GetValue(UriSourceProperty);
set => SetValue(UriSourceProperty, value);
}

/// <summary>
/// Called by XAML to convert a string to an <see cref="IAnimatedVisualSource"/>.
/// </summary>
/// <returns>The <see cref="LottieVisualSourceWinUI"/> for the given url.</returns>
public static LottieVisualSourceWinUI? CreateFromString(string uri)
{
LottieVisualSource? lottieVisualSource = LottieVisualSource.CreateFromString(uri);
if (lottieVisualSource != null)
{
return new LottieVisualSourceWinUI(lottieVisualSource);
}
else
{
return new LottieVisualSourceWinUI();
}
}

/// <summary>
/// Sets the source for the <see cref="LottieVisualSourceWinUI"/>.
/// </summary>
/// <param name="stream">A stream containing the text of a JSON Lottie file encoded as UTF-8.</param>
/// <returns>An <see cref="IAsyncAction"/> that completes when the load completes or fails.</returns>
[Overload("SetSourceStreamAsync")]
public IAsyncAction SetSourceAsync(IInputStream stream)
{
return _lottieVisualSource.SetSourceAsync(stream);
}

/// <summary>
/// Sets the source for the <see cref="LottieVisualSourceWinUI"/>.
/// </summary>
/// <param name="file">A file that is a JSON Lottie file.</param>
/// <returns>An <see cref="IAsyncAction"/> that completes when the load completes or fails.</returns>
[Overload("SetSourceFileAsync")]
public IAsyncAction SetSourceAsync(StorageFile file)
{
return _lottieVisualSource.SetSourceAsync(file);
}

/// <summary>
/// Sets the source for the <see cref="LottieVisualSourceWinUI"/>.
/// </summary>
/// <param name="sourceUri">A URI that refers to a JSON Lottie file.</param>
/// <returns>An <see cref="IAsyncAction"/> that completes when the load completes or fails.</returns>
[DefaultOverload]
[Overload("SetSourceUriAsync")]
public IAsyncAction SetSourceAsync(Uri sourceUri)
{
return _lottieVisualSource.SetSourceAsync(sourceUri);
}

/// <summary>
/// Implements <see cref="IDynamicAnimatedVisualSource"/>.
/// </summary>
// TODO: currently explicitly implemented interfaces are causing a problem with .NET Native. Make them implicit for now.
public event TypedEventHandler<IDynamicAnimatedVisualSource?, object?> AnimatedVisualInvalidated
{
add
{
_compositionInvalidatedEventTokenTable.Add(value);
}

remove
{
_compositionInvalidatedEventTokenTable.Remove(value);
}
}

/// <summary>
/// Sets a delegate that returns an <see cref="ICompositionSurface"/> for the given image uri.
/// If this is null, no images will be loaded from references to external images.
/// </summary>
/// <remarks>Most Lottie files do not reference external images, but those that do
/// will refer to the files via a uri. It is up to the user of <see cref="LottieVisualSourceWinUI"/>
/// to manage the loading of the image, and return an <see cref="ICompositionSurface"/> for
/// that image. Alternatively the delegate may return null, and the image will not be
/// displayed.</remarks>
public void SetImageAssetHandler(ImageAssetHandler? imageAssetHandler)
{
_lottieVisualSource.SetImageAssetHandler(imageAssetHandler);
}

/// <summary>
/// Implements <see cref="IAnimatedVisualSource"/>.
/// </summary>
/// <param name="compositor">The <see cref="Compositor"/> that can be used as a factory for the resulting <see cref="IAnimatedVisual"/>.</param>
/// <param name="diagnostics">An optional object that may provide extra information about the result.</param>
/// <returns>An <see cref="IAnimatedVisual"/>.</returns>
// TODO: currently explicitly implemented interfaces are causing a problem with .NET Native. Make them implicit for now.
//bool IAnimatedVisualSource.TryCreateAnimatedVisual(
public IAnimatedVisual? TryCreateAnimatedVisual(
Compositor compositor,
out object? diagnostics)
{
if (_lottieVisualSource is null)
{
// No content has been loaded yet.
// Return an IAnimatedVisual that produces nothing.
diagnostics = null;
return null;
}
else
{
// Some content was loaded. Ask the factory to produce an
// IAnimatedVisual. If it returns null, the player will treat it
// as an error.
IAnimatedVisualFrameworkless? animatedVisual = _lottieVisualSource.TryCreateAnimatedVisual(compositor, out diagnostics);
if (animatedVisual != null)
{
return new LottieVisualWinUI(animatedVisual);
}
else
{
return null;
}
}
}

private void OnAnimatedVisualInvalidated(LottieVisualSource? sender, object? args)
{
foreach (var v in _compositionInvalidatedEventTokenTable)
{
v.Invoke(this, null);
}
}
}
}
41 changes: 41 additions & 0 deletions Lottie-Windows-WinUI3-Controls/LottieVisualWinUI.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#nullable enable

using System;
using System.Numerics;
using CommunityToolkit.WinAppSDK.LottieIsland;
using Microsoft.UI.Composition;
using Microsoft.UI.Xaml.Controls;
using WinRT;

namespace CommunityToolkit.WinUI.Lottie.Controls
{
/// <summary>
/// Simple wrapper to convert an <see cref="IAnimatedVisualFrameworkless"/> to an
/// <see cref="IAnimatedVisual"/> for a Lottie composition. This allows
/// a Lottie to be specified as the source for a <see cref="AnimatedVisualPlayer"/>.
/// </summary>
internal class LottieVisualWinUI : IAnimatedVisual
{
IAnimatedVisualFrameworkless _animatedVisual;

internal LottieVisualWinUI(IAnimatedVisualFrameworkless animatedVisual)
{
_animatedVisual = animatedVisual;
}

public TimeSpan Duration => _animatedVisual.Duration;

public Visual RootVisual => _animatedVisual.RootVisual;

public Vector2 Size => _animatedVisual.Size;

public void Dispose()
{
_animatedVisual.As<IDisposable>().Dispose();
}
}
}
Loading