They were causing certification issues because they had some color in them. But we don't need them because they're only for lock screen notifications, which we don't use.
* Add a new build configuration for a Beta version of LottieViewer.
The "BETA" build configuration will build LottieViewer with a different name and identity so that it can be released to beta testers and exist side-by-side with the non-beta version.
Add visual assets stamped with "BETA" to make it obvious that it's a BETA.
* Fix crash on some cases of path groups.
As a result of looking again at the algorithm that we use to combine animated paths I decided it needed a lot more documentation and to be rewritten to make sure that we handle all cases.
* Cleanup: remove redundant type tags.
These type tags evolved a little unevenly. The goal is that the tags represent each of the direct subclasses, but some of the tags were referring to subclasses of subclasses.
* Parse layer effects.
Enable parsing of layer effects. This only fully supports drop shadow effects, however the data model is set up so that other effects can be supported in the future.
Because Lotties can render differently on different UAP versions, it's important that users know what version of UAP they're using. That way, when they say "this doesn't look right", and I say "looks fine to me", we can check the UAP version easily to determine whether that accounts for the difference.
* Allow external images to be loaded by LottieVisualSource, and add .lottie file support.
External images (i.e. images that are not embedded in the .JSON file) are a problem for LottieVisualSource because it doesn't know how to get them. For securit reasons, we don't want LottieVisualSource to have the ability to read files that are referenced from a Lottie .json file, and in many cases LottieVisualSource wouldn't be able to resolve the file because it doesn't have permissions.
This change adds an ImageAssetDelegate that the user can set on the AnimatedVisualSource in order to handle reading of external images.
This change also adds support for the .lottie format (see https://dotlottie.io). There is a parser for .lottie files, and support in LottieViewer for displaying Lotties from a .lottie file. Because .lottie files package images together with the .json Lottie file, it enables LottieViewer to display Lotties that have external images.
* Fix some bugs that were obvious when I started to CR.
* CR feedback.
* CR feedback.
* CR feedback.
* Fix typo in header.
Replace Asserts that are now handled by nullable analysis.
Add some more "#nullable enable" to quieten code analysis in VS.
Rename a method in CodeBuilder because it referred to Cpp but is now used by C# as well.
We always had this overload, however due to a misunderstanding about the rules around overload attributes for WinRT, it was never visible in the WinMD.
This should address #366.
* Generate a way to convert between marker names and progress values, and set bound colors.
To use this without having to cast to a particular class type, use the -AdditionalInterface command line option in LottieGen.
Cppwinrt example:
LottieGen.exe -inp MyLottieFile -AdditionalInterface MyNamespace.IMyInterface -l cppwinrt
...then in your cppwinrt project, add an IDL file that defines MyNamespace.IMyInterface and declares the methods you want to access, e.g.:
namespace MyNamespace
{
interface IMyInterface
{
Windows.Foundation.Collections.IMapView<String, Double> Markers { get; };
void SetColorProperty(String propertyName, Windows.UI.Color value);
};
}
...and finally, reference the interface from your code with an include of "MyNamespace.IMyInterface.h".
* Add ability to specify additional interfaces for the generated code.
This adds a feature to LottieGen to specify interfaces that LottieGen will then claim that the generated class implements.
This feature allows you to access methods that we generated on the class that are not members of IAnimatedVisualSource. This provides a way for us to add new features to the generated code, that can be accessed without knowing the exact type of the generated class, and without us having to update the IAnimatedVisualSource interface.
For example, I am about to add some metadata methods:
double GetMarkerAsProgress(string markerName);
void SetColorBinding(string bindingName, Color color);
Cool, but how do you access those methods? If you know the type of the generated class (e.g. "MyCoolLottie") then you can just call the methods on a variable of that type. But what if you want to call one of these methods without knowing the type? Or maybe you want to treat all your generated code in the same way, so the types get in the way.
The solution is to tell LottieGen that the generated code supports an additional interface that you will define to contain the new methods. LottieGen will then say "sure, the generated code implements "MyCoolAdditionalInterface". As long as your interface's methods are the same as the ones that we generate, you'll now be able to use MyCoolAdditionalInterface to call those methods.
* Enable nullable reference types where possible.
This enables C# 8 nullable reference types. Many files have nullables disabled so I don't have to fix everything at once. I'll get them all enabled bit by bit. All new files default to nullable now.
* Fixes a hole in the GraphCompactor optimizer wrt visiblity and masks.
We use CompositionVisualSurface to implement masks. CompositionVisualSurface allows a Visual tree to be used as a brush, however it ignores many of the properties on the root of the Visual tree it hosts.
The GraphCompactor attempts to push IsVisible animations higher up the tree, however before this fix it could push IsVisible into a Visual that was the root of a CompositionVisualSurface's tree, with the result that the IsVisible property would get ignored.
The fix disallows pushing of IsVisible into a Visual that is at the root of a CompositionVisualSurface's tree.
* cppwinrt codegen refinements.
This is in response to user suggestions:
1. Use non-namespace-qualified names for the names of the *.idl, *.h, *.cpp files. Previously we were qualifying them with namespaces as cppwinrt does, but user preferred non-qualified.
2. Add a -RootNamespace option to LottieGen that corresponds to the same option in cppwinrt.exe. When cppwinrt.exe is given a root namespace, the names of the files it generates has that namespace stripped from them. This option in LottieGen affects the names used in the #includes that include the cppwinrt.exe-generated code.
* Fix 2 bugs - path translation optimizer, cppwinrt codegen.
The path translation optimizer didn't handle the case of paths that consist of single beziers. As a result, some animations were being incorrectly optimized into offset animations.
CppWinrt codegen was instantiating the implementation of CompositeEffect on the stack when it should have been on the heap.
* Get image layer working with cppwinrt.
Has some issues if the images are not found, but it works otherwise.
Includes some untested cleaning up of the CX code.
This is not complete (IDynamicAnimatedVisualSource code will not compile). However it fixes a number of IDynamicAnimatedVisualSource issues.
Also gives unique names to the AnimatedVisual classes. This should make callstacks clearer in C++.
This only affects Lotties with non-embedded images. When IsAnimatedVisualSourceDynamic is true the load of the Lottie is not considered complete until all the images have loaded. This guarantees that you never see a Lottie that is missing its images.
When IsAnimatedVisualSourceDynamic is false, the Lottie will load synchronously and the image will pop in when they are finally loaded.
Lotties with non-embedded images are quite rare, and one dev that tried to use them found them to be difficult because they had to wait for the Lottie to be loaded before playing. But they really didn't care about the images taking too long (they were on disk so they should show up really quickly). If we had made IsAnimatedVisualSourceDynamic default to false they wouldn't have had to deal with waiting for the loading and would never have noticed any issue.
So, assuming that most use case are similar (i.e. the images are on disk and there is no need to wait for the images to load), I'm changing the default value false. You can always turn on IsAnimatedVisualSourceDynamic if you need it, but I'm pretty sure hardly anyone ever will.
* LottieViewer: allow palette colors to be changed, and markers in the info panel.
This change required more space for the color picker, and that it didn't cover up the playing Lottie, so the info and play speed and color picker are all now implemented as panels that slide out from the right.
We were showing the number of animation objects previously, but that doesn't really tell you how expensive animations are in DWM because the one animation might be started multiple times. Animator counts are a better representation of cost.
Here's an example of the extra info. Note the animators, and parameters counts.
```// | Object stats | UAP v12 count | UAP v8 count |
// |__________________________|_______________|______________|
// | All CompositionObjects | 567 | 567 |
// |--------------------------+---------------+--------------|
// | Expression animators | 51 | 51 |
// | KeyFrame animators | 50 | 50 |
// | Reference parameters | 51 | 51 |
// |--------------------------+---------------+--------------|
// | Animated brushes | 1 | 1 |
```
LP0002 is always populated from an exception message, which are supposed to have periods on the end. So most of the time we were getting double periods, which looks bad.
* Addressed #333. Allow JSON to be loaded from any stream, including memory.
There was a request (#333) to be able to load Lottie files from memory. This change allows that by enabling any IInputStream to be used.
As part of this change, I found some cruft that I could clean up, and I pulled out the classes for the Loader and ContentFactory and did some other straightforward refactoring.
The code generated for loading an IDynamicAnimatedVisualSource previously only invalidated when all of the images loaded successfully. This means that any failure to load an image would result in the IAnimatedVisual never loading.
With this change, completion of all image loads, even if one of them fails, will invalidate the IDynamicAnimatedVisualSource.
This will allow a Lottie to show up even if one of its images can't load.
* Refactor to allow better modularization of the translator.
Previously most of the translation code had to be in the LottieToWinCompTranslator class and that was making it difficult to maintain.
The goal with this refactor is to allow translation code to be implemented in static methods grouped for convenience into static classes, and to avoid having to pass more than one context to a translation method.
The state that is needed for translation is now in various "contexts". The LottieToWinCompTranslator is now just a static class that creates the top-level context and tells it to translate.
Previously we had a "TranslationContext" that was the context for translating a layer, and a "ShapeContext" that was the context for translating a shape withing a shape layer.
Now we have:
TranslationContext - context for stuff that is global to a particular Lottie file's translation.
CompositionContext - context for a list of layers. There is a CompositionContext for the root of the Lottie as well as one for each PreComp layer.
LayerContext - context for stuff that is layer dependent. There are strongly-typed subclasses of this for each layer type.
ShapeContext - as before - context for translating a shape.
These contexts form a hierarchy: ShapeContext contains a LayerContext which contains a CompositionContext which contains a TranslationContext.
Contexts inherit state from their containing context.
Through the magic of implicit conversions, a context can always be passed to a method requiring a context type higher in the hierarchy, e.g. a LayerContext can be passed to a method that requires a TranslationContext.
This switch is intended to exist only until we fork LottieGen to be WinUI3 only. Until then it is a convenient way to have the code generator output code that needs little hand tweaking to work with WinUI3.
We were not handling the distinction between RoundCorners.Radius and Rectangle.Roundness. This change does a much better job.
Note that it gets the Trimming wrong for RoundCorners - that will come in a later fix. I'm getting this in now because it has so much refactoring that it will be hard to focus on the trimming algorithm alongside this.
These are the After Effects rules for how RoundCorners.Radius and Rectangle.Roundness interact:
RoundCorners.Radius is ignored if Rectangle.Roundness != 0.
RoundCorners.Radius is able to produce an ellipse if the radius is large enough.
Rectangle.Roundness creates round corners with equal X and Y radii, so it can never create an ellipse.
* Adding markers to the scrubber.
This is a rewrite of the Scrubber to support markers. It also is a much nicer implementation of the
scrubber that reuses more of the XAML Slider functionality, and reduces the amount of copied XAML from
the default Slider style (from generic.xaml).
As I was adding this change, it became apparent that the way the XAML slider draws its track would
not work well with markers at 0.0 or 1.0 because the track ends up extending before and after the
0.0 and 1.0 positions which would make the markers look like they were incorrectly placed. So now
we do all of the drawing (track, decrease rectangle, and thumb) using Composition.
We also now mimic the mouse-over behavior of Slider so that the control feels a little more engaging.
This required hooking Composition into the VisualStateManager, which is achieved by replacing the
default VisualStateManager with our own implementation.