Made some changes + comments cleanup as discussed

This commit is contained in:
aborziak-ms 2021-06-14 10:56:34 -07:00
Родитель e27c69f60f
Коммит 04cd5fe11a
4 изменённых файлов: 79 добавлений и 68 удалений

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

@ -168,7 +168,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.LottieToWinComp
ApplyCommonStrokeProperties(
context,
shapeStroke,
TranslateLinearGradient(context, shapeStroke, contextOpacity, null),
TranslateLinearGradient(context, shapeStroke, contextOpacity),
sprite);
}
@ -181,7 +181,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.LottieToWinComp
ApplyCommonStrokeProperties(
context,
shapeStroke,
TranslateRadialGradient(context, shapeStroke, contextOpacity, null),
TranslateRadialGradient(context, shapeStroke, contextOpacity),
sprite);
}
@ -258,7 +258,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.LottieToWinComp
LayerContext context,
ShapeFill? shapeFill,
CompositeOpacity opacity,
Rectangles.InternalOffset? internalOffset)
Rectangles.OriginOffset? originOffset)
{
if (shapeFill is null)
{
@ -267,9 +267,12 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.LottieToWinComp
return shapeFill.FillKind switch
{
ShapeFill.ShapeFillKind.SolidColor => TranslateSolidColorFill(context, (SolidColorFill)shapeFill, opacity),
ShapeFill.ShapeFillKind.LinearGradient => TranslateLinearGradient(context, (LinearGradientFill)shapeFill, opacity, internalOffset),
ShapeFill.ShapeFillKind.RadialGradient => TranslateRadialGradient(context, (RadialGradientFill)shapeFill, opacity, internalOffset),
ShapeFill.ShapeFillKind.SolidColor =>
TranslateSolidColorFill(context, (SolidColorFill)shapeFill, opacity),
ShapeFill.ShapeFillKind.LinearGradient =>
TranslateLinearGradient(context, (LinearGradientFill)shapeFill, opacity, originOffset),
ShapeFill.ShapeFillKind.RadialGradient =>
TranslateRadialGradient(context, (RadialGradientFill)shapeFill, opacity, originOffset),
_ => throw new InvalidOperationException(),
};
}
@ -410,40 +413,64 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.LottieToWinComp
return result;
}
static void TranslateVector2AnimatableWithInternalOffset(
// Animate Vector2 property of object with TrimmedAnimatable while applying OriginOffset to it.
// Returns non-null Sn.Vector2 value if no animation is needed (and no animation was applied).
static Sn.Vector2? AnimateVector2WithOriginOffsetOrGetValue(
LayerContext context,
CompositionObject obj,
string propertyName,
TrimmedAnimatable<Vector2> value,
Rectangles.InternalOffset offset)
Rectangles.OriginOffset? offset)
{
// anomate source property first
if (offset is null)
{
if (value.IsAnimated)
{
Animate.Vector2(context, value, obj, propertyName);
return null;
}
else
{
return ConvertTo.Vector2(value.InitialValue);
}
}
if (!offset.IsAnimated && !value.IsAnimated)
{
return ConvertTo.Vector2(value.InitialValue) + offset.OffsetValue!;
}
// Animate source property first.
// We are using this auxiliary property to store original animation,
// so that its value can be used in expression animation of property itself.
string sourcePropertyName = propertyName + "Source";
obj.Properties.InsertVector2(sourcePropertyName, ConvertTo.Vector2(value.InitialValue));
Animate.Vector2(context, value, obj, sourcePropertyName);
// create expression that offsets source property by internal offset
// Create expression that offsets source property by origin offset.
WinCompData.Expressions.Vector2 expression = offset.IsAnimated ?
ExpressionFactory.InternalOffsetExressionAdded(sourcePropertyName, offset.OffsetExpression!) :
ExpressionFactory.InternalOffsetValueAdded(sourcePropertyName, (Sn.Vector2)offset.OffsetValue!);
ExpressionFactory.OriginOffsetExressionAdded(sourcePropertyName, offset.OffsetExpression!) :
ExpressionFactory.OriginOffsetValueAdded(sourcePropertyName, (Sn.Vector2)offset.OffsetValue!);
var expressionAnimation = context.ObjectFactory.CreateExpressionAnimation(expression);
expressionAnimation.SetReferenceParameter("my", obj);
if (offset.IsAnimated)
{
// expression can use geometry
// Expression can use geometry.
expressionAnimation.SetReferenceParameter("geometry", offset.Geometry);
}
// animate original property with expression that applies internal offset to it
// Animate original property with expression that applies origin offset to it.
Animate.WithExpression(obj, expressionAnimation, propertyName);
return null;
}
static CompositionLinearGradientBrush? TranslateLinearGradient(
LayerContext context,
IGradient linearGradient,
CompositeOpacity opacity,
Rectangles.InternalOffset? internalOffset)
Rectangles.OriginOffset? originOffset = null)
{
var result = context.ObjectFactory.CreateLinearGradientBrush();
@ -453,30 +480,16 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.LottieToWinComp
var startPoint = Optimizer.TrimAnimatable(context, linearGradient.StartPoint);
var endPoint = Optimizer.TrimAnimatable(context, linearGradient.EndPoint);
if (internalOffset is not null)
var startPointValue = AnimateVector2WithOriginOffsetOrGetValue(context, result, nameof(result.StartPoint), startPoint, originOffset);
if (startPointValue is not null)
{
TranslateVector2AnimatableWithInternalOffset(context, result, nameof(result.StartPoint), startPoint, internalOffset);
}
else if (startPoint.IsAnimated)
{
Animate.Vector2(context, startPoint, result, nameof(result.StartPoint));
}
else
{
result.StartPoint = ConvertTo.Vector2(startPoint.InitialValue);
result.StartPoint = startPointValue!;
}
if (internalOffset is not null)
var endPointValue = AnimateVector2WithOriginOffsetOrGetValue(context, result, nameof(result.EndPoint), endPoint, originOffset);
if (endPointValue is not null)
{
TranslateVector2AnimatableWithInternalOffset(context, result, nameof(result.EndPoint), endPoint, internalOffset);
}
else if (endPoint.IsAnimated)
{
Animate.Vector2(context, endPoint, result, nameof(result.EndPoint));
}
else
{
result.EndPoint = ConvertTo.Vector2(endPoint.InitialValue);
result.EndPoint = endPointValue!;
}
var gradientStops = Optimizer.TrimAnimatable(context, linearGradient.GradientStops);
@ -496,13 +509,13 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.LottieToWinComp
LayerContext context,
IRadialGradient gradient,
CompositeOpacity opacity,
Rectangles.InternalOffset? internalOffset)
Rectangles.OriginOffset? originOffset = null)
{
if (!context.ObjectFactory.IsUapApiAvailable(nameof(CompositionRadialGradientBrush), versionDependentFeatureDescription: "Radial gradient fill"))
{
// CompositionRadialGradientBrush didn't exist until UAP v8. If the target OS doesn't support
// UAP v8 then fall back to linear gradients as a compromise.
return TranslateLinearGradient(context, gradient, opacity, internalOffset);
return TranslateLinearGradient(context, gradient, opacity, originOffset);
}
var result = context.ObjectFactory.CreateRadialGradientBrush();
@ -513,17 +526,10 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.LottieToWinComp
var startPoint = Optimizer.TrimAnimatable(context, gradient.StartPoint);
var endPoint = Optimizer.TrimAnimatable(context, gradient.EndPoint);
if (internalOffset is not null)
var startPointValue = AnimateVector2WithOriginOffsetOrGetValue(context, result, nameof(result.EllipseCenter), startPoint, originOffset);
if (startPointValue is not null)
{
TranslateVector2AnimatableWithInternalOffset(context, result, nameof(result.EllipseCenter), startPoint, internalOffset);
}
else if (startPoint.IsAnimated)
{
Animate.Vector2(context, startPoint, result, nameof(result.EllipseCenter));
}
else
{
result.EllipseCenter = ConvertTo.Vector2(startPoint.InitialValue);
result.EllipseCenter = startPointValue!;
}
if (endPoint.IsAnimated)

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

@ -47,9 +47,9 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.LottieToWinComp
MyPosition.Y - MyAnchor.Y,
0);
internal static Vector2 InternalOffsetExressionAdded(string property, Vector2 offsetExpression) => MyVector2(property) + offsetExpression;
internal static Vector2 OriginOffsetExressionAdded(string property, Vector2 offsetExpression) => MyVector2(property) + offsetExpression;
internal static Vector2 InternalOffsetValueAdded(string property, Sn.Vector2 offsetValue) => MyVector2(property) + Vector2(offsetValue);
internal static Vector2 OriginOffsetValueAdded(string property, Sn.Vector2 offsetValue) => MyVector2(property) + Vector2(offsetValue);
internal static Color ThemedColorMultipliedByOpacity(string bindingName, Animatables.Opacity opacity)
=> ColorAsVector4MultipliedByOpacity(ThemedColor4Property(bindingName), opacity.Value);

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

@ -21,31 +21,29 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.LottieToWinComp
// Rectangles are implemented differently in WinComp API
// and Lottie. In WinComp API coordinates inside rectangle start in
// top left corner and in Lottie they start in the middle
// To account for this we need to offset all the internal points
// for (Rectangle.Size / 2)
// To account for this we need to offset all the points inside
// the rectangle for (Rectangle.Size / 2).
// This class represents this offset (static or animated)
public class InternalOffset
public class OriginOffset
{
public RectangleOrRoundedRectangleGeometry Geometry { get; }
// Use expression if size is animated
#nullable enable
public Expressions.Vector2? OffsetExpression { get; }
#nullable disable
// Use constant value if size if static
public Sn.Vector2? OffsetValue { get; }
public bool IsAnimated => OffsetExpression is not null;
public bool IsAnimated => OffsetValue is null;
public InternalOffset(RectangleOrRoundedRectangleGeometry geometry, Expressions.Vector2 expression)
public OriginOffset(RectangleOrRoundedRectangleGeometry geometry, Expressions.Vector2 expression)
{
Geometry = geometry;
OffsetExpression = expression;
OffsetValue = null;
}
public InternalOffset(RectangleOrRoundedRectangleGeometry geometry, Sn.Vector2 value)
public OriginOffset(RectangleOrRoundedRectangleGeometry geometry, Sn.Vector2 value)
{
Geometry = geometry;
OffsetExpression = null;
@ -353,15 +351,16 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.LottieToWinComp
var height = size.InitialValue.Y;
var trimOffsetDegrees = (width / (2 * (width + height))) * 360;
InternalOffset internalOffset = size.IsAnimated ?
new InternalOffset(geometry, ExpressionFactory.GeometryHalfSize) :
new InternalOffset(geometry, ConvertTo.Vector2(size.InitialValue / 2));
// If offset is not animated then other computations for fill brush can be optimized.
OriginOffset originOffset = size.IsAnimated ?
new OriginOffset(geometry, ExpressionFactory.GeometryHalfSize) :
new OriginOffset(geometry, ConvertTo.Vector2(size.InitialValue / 2));
Shapes.TranslateAndApplyShapeContextWithTrimOffset(
context,
compositionRectangle,
rectangle.DrawingDirection == DrawingDirection.Reverse,
internalOffset,
originOffset,
trimOffsetDegrees: trimOffsetDegrees);
compositionRectangle.SetDescription(context, () => rectangle.Name);
@ -448,15 +447,16 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.LottieToWinComp
var initialHeight = height.InitialValue;
var trimOffsetDegrees = (initialWidth / (2 * (initialWidth + initialHeight))) * 360;
InternalOffset internalOffset = width.IsAnimated || height.IsAnimated ?
new InternalOffset(geometry, ExpressionFactory.GeometryHalfSize) :
new InternalOffset(geometry, ConvertTo.Vector2(width.InitialValue / 2, height.InitialValue / 2));
// If offset is not animated then other computations for fill brush can be optimized.
OriginOffset originOffset = width.IsAnimated || height.IsAnimated ?
new OriginOffset(geometry, ExpressionFactory.GeometryHalfSize) :
new OriginOffset(geometry, ConvertTo.Vector2(width.InitialValue / 2, height.InitialValue / 2));
Shapes.TranslateAndApplyShapeContextWithTrimOffset(
context,
compositionRectangle,
rectangle.DrawingDirection == DrawingDirection.Reverse,
internalOffset,
originOffset,
trimOffsetDegrees: trimOffsetDegrees);
compositionRectangle.SetDescription(context, () => rectangle.Name);

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

@ -34,18 +34,23 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.LottieToWinComp
ShapeContext context,
CompositionSpriteShape shape,
bool reverseDirection) =>
TranslateAndApplyShapeContextWithTrimOffset(context, shape, reverseDirection, null, 0);
TranslateAndApplyShapeContextWithTrimOffset(
context,
shape,
reverseDirection,
originOffset: null,
trimOffsetDegrees: 0);
public static void TranslateAndApplyShapeContextWithTrimOffset(
ShapeContext context,
CompositionSpriteShape shape,
bool reverseDirection,
Rectangles.InternalOffset? internalOffset,
Rectangles.OriginOffset? originOffset,
double trimOffsetDegrees)
{
Debug.Assert(shape.Geometry is not null, "Precondition");
shape.FillBrush = Brushes.TranslateShapeFill(context, context.Fill, context.Opacity, internalOffset);
shape.FillBrush = Brushes.TranslateShapeFill(context, context.Fill, context.Opacity, originOffset);
Brushes.TranslateAndApplyStroke(context, context.Stroke, shape, context.Opacity);
TranslateAndApplyTrimPath(