Skip to content

Commit

Permalink
feat: Support nested properties in ExpressionAnimation
Browse files Browse the repository at this point in the history
  • Loading branch information
Youssef1313 committed Feb 26, 2024
1 parent 59890bc commit cec4076
Show file tree
Hide file tree
Showing 6 changed files with 237 additions and 27 deletions.
26 changes: 23 additions & 3 deletions src/Uno.UI.Composition/Composition/CompositionColorBrush.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,37 @@ public Color Color
set { SetProperty(ref _color, value); }
}

private protected override bool IsAnimatableProperty(string propertyName)
private protected override bool IsAnimatableProperty(ReadOnlySpan<char> propertyName)
{
return propertyName is nameof(Color);
}

private protected override void SetAnimatableProperty(string propertyName, object? propertyValue)
private protected override void SetAnimatableProperty(ReadOnlySpan<char> propertyName, ReadOnlySpan<char> subPropertyName, object? propertyValue)
{
if (propertyName is nameof(Color))
if (propertyName is nameof(Color) && subPropertyName.Length == 0)
{
Color = ValidateValue<Color>(propertyValue);
}
else if (propertyName is nameof(Color) && subPropertyName == "A")
{
var a = ValidateValue<byte>(propertyValue);
Color = new Color(a, Color.R, Color.G, Color.B);
}
else if (propertyName is nameof(Color) && subPropertyName == "R")
{
var r = ValidateValue<byte>(propertyValue);
Color = new Color(Color.A, r, Color.G, Color.B);
}
else if (propertyName is nameof(Color) && subPropertyName == "G")
{
var g = ValidateValue<byte>(propertyValue);
Color = new Color(Color.A, Color.R, g, Color.B);
}
else if (propertyName is nameof(Color) && subPropertyName == "B")
{
var b = ValidateValue<byte>(propertyValue);
Color = new Color(Color.A, Color.R, Color.G, b);
}
else
{
throw new Exception($"Unable to set property '{propertyName}' on {this}");
Expand Down
41 changes: 35 additions & 6 deletions src/Uno.UI.Composition/Composition/CompositionObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,28 @@ private protected T ValidateValue<T>(object? value)

// Overrides are based on:
// https://learn.microsoft.com/en-us/uwp/api/windows.ui.composition.compositionobject.startanimation?view=winrt-22621
private protected virtual bool IsAnimatableProperty(string propertyName) => false;
private protected virtual void SetAnimatableProperty(string propertyName, object? propertyValue) { }
private protected virtual bool IsAnimatableProperty(ReadOnlySpan<char> propertyName) => false;
private protected virtual void SetAnimatableProperty(ReadOnlySpan<char> propertyName, ReadOnlySpan<char> subPropertyName, object? propertyValue) { }

public void StartAnimation(string propertyName, CompositionAnimation animation)
{
if (!IsAnimatableProperty(propertyName))
ReadOnlySpan<char> firstPropertyName;
ReadOnlySpan<char> subPropertyName;
var firstDotIndex = propertyName.IndexOf('.');
if (firstDotIndex > -1)
{
throw new ArgumentException($"Property '{propertyName}' is not animatable.");
firstPropertyName = propertyName.AsSpan().Slice(0, firstDotIndex);
subPropertyName = propertyName.AsSpan().Slice(firstDotIndex + 1);
}
else
{
firstPropertyName = propertyName;
subPropertyName = default;
}

if (!IsAnimatableProperty(firstPropertyName))
{
throw new ArgumentException($"Property '{firstPropertyName}' is not animatable.");
}

if (_animations?.ContainsKey(propertyName) == true)
Expand All @@ -87,7 +101,7 @@ public void StartAnimation(string propertyName, CompositionAnimation animation)

try
{
this.SetAnimatableProperty(propertyName, animationValue);
this.SetAnimatableProperty(firstPropertyName, subPropertyName, animationValue);
}
catch (Exception ex)
{
Expand All @@ -111,7 +125,22 @@ private void ReEvaluateAnimation(CompositionAnimation animation)
{
if (value == animation)
{
this.SetAnimatableProperty(key, animation.Evaluate());
var propertyName = key;
ReadOnlySpan<char> firstPropertyName;
ReadOnlySpan<char> subPropertyName;
var firstDotIndex = propertyName.IndexOf('.');
if (firstDotIndex > -1)
{
firstPropertyName = propertyName.AsSpan().Slice(0, firstDotIndex);
subPropertyName = propertyName.AsSpan().Slice(firstDotIndex + 1);
}
else
{
firstPropertyName = propertyName;
subPropertyName = default;
}

this.SetAnimatableProperty(firstPropertyName, subPropertyName, animation.Evaluate());
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/Uno.UI.Composition/Composition/CompositionPropertySet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,11 @@ private void SetValue<T>(string propertyName, T value)
}

// TODO
private protected override bool IsAnimatableProperty(string propertyName)
private protected override bool IsAnimatableProperty(ReadOnlySpan<char> propertyName)
=> false;

// TODO
private protected override void SetAnimatableProperty(string propertyName, object? propertyValue)
private protected override void SetAnimatableProperty(ReadOnlySpan<char> propertyName, ReadOnlySpan<char> subPropertyName, object? propertyValue)
{
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/Uno.UI.Composition/Composition/InsetClip.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public float BottomInset
set => SetProperty(ref _bottomInset, value);
}

private protected override bool IsAnimatableProperty(string propertyName)
private protected override bool IsAnimatableProperty(ReadOnlySpan<char> propertyName)
{
return propertyName is
nameof(BottomInset) or
Expand All @@ -49,7 +49,7 @@ private protected override bool IsAnimatableProperty(string propertyName)
nameof(TopInset);
}

private protected override void SetAnimatableProperty(string propertyName, object? propertyValue)
private protected override void SetAnimatableProperty(ReadOnlySpan<char> propertyName, ReadOnlySpan<char> subPropertyName, object? propertyValue)
{
if (propertyName is nameof(BottomInset))
{
Expand Down
65 changes: 59 additions & 6 deletions src/Uno.UI.Composition/Composition/Visual.cs
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ private protected override void OnPropertyChangedCore(string? propertyName, bool
Compositor.InvalidateRender(this);
}

private protected override bool IsAnimatableProperty(string propertyName)
private protected override bool IsAnimatableProperty(ReadOnlySpan<char> propertyName)
{
return propertyName is
nameof(AnchorPoint) or
Expand All @@ -149,26 +149,67 @@ private protected override bool IsAnimatableProperty(string propertyName)
nameof(TransformMatrix);
}

private protected override void SetAnimatableProperty(string propertyName, object? propertyValue)
private protected override void SetAnimatableProperty(ReadOnlySpan<char> propertyName, ReadOnlySpan<char> subPropertyName, object? propertyValue)
{
if (propertyName is nameof(AnchorPoint))
if (propertyName is nameof(AnchorPoint) && subPropertyName.Length == 0)
{
AnchorPoint = ValidateValue<Vector2>(propertyValue);
}
else if (propertyName is nameof(CenterPoint))
else if (propertyName is nameof(AnchorPoint) && subPropertyName.Equals("X", StringComparison.Ordinal))
{
var x = ValidateValue<float>(propertyValue);
AnchorPoint = new Vector2(x, AnchorPoint.Y);
}
else if (propertyName is nameof(AnchorPoint) && subPropertyName.Equals("Y", StringComparison.Ordinal))
{
var y = ValidateValue<float>(propertyValue);
AnchorPoint = new Vector2(AnchorPoint.X, y);
}
else if (propertyName is nameof(CenterPoint) && subPropertyName.Length == 0)
{
CenterPoint = ValidateValue<Vector3>(propertyValue);
}
else if (propertyName is nameof(Offset))
else if (propertyName is nameof(CenterPoint) && subPropertyName.Equals("X", StringComparison.Ordinal))
{
var x = ValidateValue<float>(propertyValue);
CenterPoint = new Vector3(x, CenterPoint.Y, CenterPoint.Z);
}
else if (propertyName is nameof(CenterPoint) && subPropertyName.Equals("Y", StringComparison.Ordinal))
{
var y = ValidateValue<float>(propertyValue);
CenterPoint = new Vector3(CenterPoint.X, y, CenterPoint.Z);
}
else if (propertyName is nameof(CenterPoint) && subPropertyName.Equals("Z", StringComparison.Ordinal))
{
var z = ValidateValue<float>(propertyValue);
CenterPoint = new Vector3(CenterPoint.X, CenterPoint.Y, z);
}
else if (propertyName is nameof(Offset) && subPropertyName.Length == 0)
{
Offset = ValidateValue<Vector3>(propertyValue);
}
else if (propertyName is nameof(Offset) && subPropertyName.Equals("X", StringComparison.Ordinal))
{
var x = ValidateValue<float>(propertyValue);
Offset = new Vector3(x, Offset.Y, Offset.Z);
}
else if (propertyName is nameof(Offset) && subPropertyName.Equals("Y", StringComparison.Ordinal))
{
var y = ValidateValue<float>(propertyValue);
Offset = new Vector3(Offset.X, y, Offset.Z);
}
else if (propertyName is nameof(Offset) && subPropertyName.Equals("Z", StringComparison.Ordinal))
{
var z = ValidateValue<float>(propertyValue);
Offset = new Vector3(Offset.X, Offset.Y, z);
}
else if (propertyName is nameof(Opacity))
{
Opacity = ValidateValue<float>(propertyValue);
}
else if (propertyName is nameof(Orientation))
{
// TODO: Support X, Y, Z, and W
Orientation = ValidateValue<Quaternion>(propertyValue);
}
else if (propertyName is nameof(RotationAngle))
Expand All @@ -177,14 +218,26 @@ private protected override void SetAnimatableProperty(string propertyName, objec
}
else if (propertyName is nameof(RotationAxis))
{
// TODO: Support X, Y, and Z
RotationAxis = ValidateValue<Vector3>(propertyValue);
}
else if (propertyName is nameof(Size))
else if (propertyName is nameof(Size) && subPropertyName.Length == 0)
{
Size = ValidateValue<Vector2>(propertyValue);
}
else if (propertyName is nameof(Size) && subPropertyName.Equals("X", StringComparison.Ordinal))
{
var x = ValidateValue<float>(propertyValue);
Size = new Vector2(x, Size.Y);
}
else if (propertyName is nameof(Size) && subPropertyName.Equals("Y", StringComparison.Ordinal))
{
var y = ValidateValue<float>(propertyValue);
Size = new Vector2(Size.X, y);
}
else if (propertyName is nameof(TransformMatrix))
{
// TODO: Support sub properties.
TransformMatrix = ValidateValue<Matrix4x4>(propertyValue);
}
else
Expand Down
Loading

0 comments on commit cec4076

Please sign in to comment.