From a69e47e08da755e8fe8ef148344cea1b4416db40 Mon Sep 17 00:00:00 2001 From: Arcadio Garcia Salvadores Date: Mon, 16 May 2022 14:44:48 -0700 Subject: [PATCH 1/3] Evaluate expression nodes --- .../Expressions/CompositionExtensions.cs | 41 +++++++ .../ExpressionNodes/BooleanNode.cs | 65 +++++++++++ .../Expressions/ExpressionNodes/ColorNode.cs | 38 +++++++ .../ExpressionNodes/Matrix3x2Node.cs | 54 +++++++++ .../ExpressionNodes/Matrix4x4Node.cs | 75 +++++++++++++ .../ExpressionNodes/QuaternionNode.cs | 65 +++++++++++ .../Expressions/ExpressionNodes/ScalarNode.cs | 104 ++++++++++++++++++ .../ExpressionNodes/Vector2Node.cs | 66 +++++++++++ .../ExpressionNodes/Vector3Node.cs | 70 ++++++++++++ .../ExpressionNodes/Vector4Node.cs | 68 ++++++++++++ .../UI/Animations/Test_ExpressionNode.cs | 63 +++++++++++ UnitTests/UnitTests.UWP/UnitTests.UWP.csproj | 1 + 12 files changed, 710 insertions(+) create mode 100644 UnitTests/UnitTests.UWP/UI/Animations/Test_ExpressionNode.cs diff --git a/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/CompositionExtensions.cs b/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/CompositionExtensions.cs index 521d69ea2a9..3dea1f5c27c 100644 --- a/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/CompositionExtensions.cs +++ b/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/CompositionExtensions.cs @@ -263,5 +263,46 @@ private static ExpressionAnimation CreateExpressionAnimationFromNode(Compositor return expressionNode.ExpressionAnimation; } + + internal static float EvaluateSubchannel(this ExpressionNode node, string subchannel) => (node, subchannel) switch + { + (Vector2Node n, "X") => n.Evaluate().X, + (Vector2Node n, "Y") => n.Evaluate().Y, + + (Vector3Node n, "X") => n.Evaluate().X, + (Vector3Node n, "Y") => n.Evaluate().Y, + (Vector3Node n, "Z") => n.Evaluate().Z, + + (Vector4Node n, "X") => n.Evaluate().X, + (Vector4Node n, "Y") => n.Evaluate().Y, + (Vector4Node n, "Z") => n.Evaluate().Z, + (Vector4Node n, "W") => n.Evaluate().W, + + (Matrix3x2Node n, "Channel11") => n.Evaluate().M11, + (Matrix3x2Node n, "Channel12") => n.Evaluate().M12, + (Matrix3x2Node n, "Channel21") => n.Evaluate().M21, + (Matrix3x2Node n, "Channel22") => n.Evaluate().M22, + (Matrix3x2Node n, "Channel31") => n.Evaluate().M31, + (Matrix3x2Node n, "Channel32") => n.Evaluate().M32, + + (Matrix4x4Node n, "Channel11") => n.Evaluate().M11, + (Matrix4x4Node n, "Channel12") => n.Evaluate().M12, + (Matrix4x4Node n, "Channel13") => n.Evaluate().M13, + (Matrix4x4Node n, "Channel14") => n.Evaluate().M14, + (Matrix4x4Node n, "Channel21") => n.Evaluate().M21, + (Matrix4x4Node n, "Channel22") => n.Evaluate().M22, + (Matrix4x4Node n, "Channel23") => n.Evaluate().M23, + (Matrix4x4Node n, "Channel24") => n.Evaluate().M24, + (Matrix4x4Node n, "Channel31") => n.Evaluate().M31, + (Matrix4x4Node n, "Channel32") => n.Evaluate().M32, + (Matrix4x4Node n, "Channel33") => n.Evaluate().M33, + (Matrix4x4Node n, "Channel34") => n.Evaluate().M34, + (Matrix4x4Node n, "Channel41") => n.Evaluate().M41, + (Matrix4x4Node n, "Channel42") => n.Evaluate().M42, + (Matrix4x4Node n, "Channel43") => n.Evaluate().M43, + (Matrix4x4Node n, "Channel44") => n.Evaluate().M44, + + _ => 0 + }; } } \ No newline at end of file diff --git a/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/BooleanNode.cs b/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/BooleanNode.cs index 6e49f5e9417..e6d206432cc 100644 --- a/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/BooleanNode.cs +++ b/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/BooleanNode.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System; + namespace Microsoft.Toolkit.Uwp.UI.Animations.Expressions { // Ignore warning: 'BooleanNode' defines operator == or operator != but does not override Object.Equals(object o) && Object.GetHashCode() @@ -127,6 +129,69 @@ protected internal override string GetValue() } private bool _value; + + /// + /// Evaluates the current value of the expression + /// + /// The current value of the expression + public bool Evaluate() + { + switch (NodeType) + { + case ExpressionNodeType.ConstantValue: + return _value; + case ExpressionNodeType.ConstantParameter: + throw new NotImplementedException(); + case ExpressionNodeType.Equals: + return Equals(Children[0], Children[1]); + case ExpressionNodeType.NotEquals: + return !Equals(Children[0], Children[1]); + case ExpressionNodeType.And: + return (Children[0] as BooleanNode).Evaluate() && (Children[1] as BooleanNode).Evaluate(); + case ExpressionNodeType.Or: + return (Children[0] as BooleanNode).Evaluate() || (Children[1] as BooleanNode).Evaluate(); + case ExpressionNodeType.LessThan: + return (Children[0] as ScalarNode).Evaluate() < (Children[1] as ScalarNode).Evaluate(); + case ExpressionNodeType.LessThanEquals: + return (Children[0] as ScalarNode).Evaluate() <= (Children[1] as ScalarNode).Evaluate(); + case ExpressionNodeType.GreaterThan: + return (Children[0] as ScalarNode).Evaluate() > (Children[1] as ScalarNode).Evaluate(); + case ExpressionNodeType.GreaterThanEquals: + return (Children[0] as ScalarNode).Evaluate() >= (Children[1] as ScalarNode).Evaluate(); + case ExpressionNodeType.Not: + return !(Children[0] as BooleanNode).Evaluate(); + case ExpressionNodeType.ReferenceProperty: + var reference = (Children[0] as ReferenceNode).Reference; + switch (PropertyName) + { + default: + reference.Properties.TryGetBoolean(PropertyName, out var referencedProperty); + return referencedProperty; + } + + case ExpressionNodeType.Conditional: + return + (Children[0] as BooleanNode).Evaluate() ? + (Children[1] as BooleanNode).Evaluate() : + (Children[2] as BooleanNode).Evaluate(); + default: + throw new NotImplementedException(); + } + + bool Equals(ExpressionNode e1, ExpressionNode e2) => (e1, e2) switch + { + (BooleanNode n1, BooleanNode n2) => n1.Evaluate() == n2.Evaluate(), + (ScalarNode n1, ScalarNode n2) => n1.Evaluate() == n2.Evaluate(), + (Vector2Node n1, Vector2Node n2) => n1.Evaluate() == n2.Evaluate(), + (Vector3Node n1, Vector3Node n2) => n1.Evaluate() == n2.Evaluate(), + (Vector4Node n1, Vector4Node n2) => n1.Evaluate() == n2.Evaluate(), + (ColorNode n1, ColorNode n2) => n1.Evaluate() == n2.Evaluate(), + (QuaternionNode n1, QuaternionNode n2) => n1.Evaluate() == n2.Evaluate(), + (Matrix3x2Node n1, Matrix3x2Node n2) => n1.Evaluate() == n2.Evaluate(), + (Matrix4x4Node n1, Matrix4x4Node n2) => n1.Evaluate() == n2.Evaluate(), + _ => false + }; + } } #pragma warning restore CS0660, CS0661 } \ No newline at end of file diff --git a/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/ColorNode.cs b/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/ColorNode.cs index 553beee5005..5e85bc7ff1e 100644 --- a/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/ColorNode.cs +++ b/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/ColorNode.cs @@ -2,7 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System; using Windows.UI; +using Windows.UI.Composition; namespace Microsoft.Toolkit.Uwp.UI.Animations.Expressions { @@ -97,6 +99,42 @@ protected internal override string GetValue() } private Color _value; + + /// + /// Evaluates the current value of the expression + /// + /// The current value of the expression + public Color Evaluate() + { + switch (NodeType) + { + case ExpressionNodeType.ConstantValue: + return _value; + case ExpressionNodeType.ConstantParameter: + throw new NotImplementedException(); + case ExpressionNodeType.ReferenceProperty: + var reference = (Children[0] as ReferenceNode).Reference; + return PropertyName switch + { + nameof(CompositionColorBrush.Color) => (reference as CompositionColorBrush).Color, + _ => GetProperty() + }; + + Color GetProperty() + { + reference.Properties.TryGetColor(PropertyName, out var value); + return value; + } + + case ExpressionNodeType.Conditional: + return + (Children[0] as BooleanNode).Evaluate() ? + (Children[1] as ColorNode).Evaluate() : + (Children[2] as ColorNode).Evaluate(); + default: + throw new NotImplementedException(); + } + } } #pragma warning restore CS0660, CS0661 } \ No newline at end of file diff --git a/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/Matrix3x2Node.cs b/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/Matrix3x2Node.cs index 4fe297e34f8..2d12adffc99 100644 --- a/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/Matrix3x2Node.cs +++ b/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/Matrix3x2Node.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System; using System.Numerics; namespace Microsoft.Toolkit.Uwp.UI.Animations.Expressions @@ -336,6 +337,59 @@ protected internal override string GetValue() } private Matrix3x2 _value; + + /// + /// Evaluates the current value of the expression + /// + /// The current value of the expression + public Matrix3x2 Evaluate() + { + switch (NodeType) + { + case ExpressionNodeType.ConstantValue: + return _value; + case ExpressionNodeType.ConstantParameter: + throw new NotImplementedException(); + case ExpressionNodeType.ReferenceProperty: + var reference = (Children[0] as ReferenceNode).Reference; + reference.Properties.TryGetMatrix3x2(PropertyName, out var referencedProperty); + return referencedProperty; + case ExpressionNodeType.Add: + return + (Children[0] as Matrix3x2Node).Evaluate() + + (Children[1] as Matrix3x2Node).Evaluate(); + case ExpressionNodeType.Subtract: + return + (Children[0] as Matrix3x2Node).Evaluate() - + (Children[1] as Matrix3x2Node).Evaluate(); + case ExpressionNodeType.Negate: + return + -(Children[0] as Matrix3x2Node).Evaluate(); + case ExpressionNodeType.Multiply: + return (Children[0], Children[1]) switch + { + (Matrix3x2Node v1, Matrix3x2Node v2) => v1.Evaluate() * v2.Evaluate(), + (Matrix3x2Node v1, ScalarNode s2) => v1.Evaluate() * s2.Evaluate(), + (ScalarNode s1, Matrix3x2Node v2) => v2.Evaluate() * s1.Evaluate(), + _ => throw new NotImplementedException() + }; + case ExpressionNodeType.Conditional: + return + (Children[0] as BooleanNode).Evaluate() ? + (Children[1] as Matrix3x2Node).Evaluate() : + (Children[2] as Matrix3x2Node).Evaluate(); + case ExpressionNodeType.Swizzle: + return new Matrix3x2( + Children[0].EvaluateSubchannel(Subchannels[0]), + Children[0].EvaluateSubchannel(Subchannels[1]), + Children[0].EvaluateSubchannel(Subchannels[2]), + Children[0].EvaluateSubchannel(Subchannels[3]), + Children[0].EvaluateSubchannel(Subchannels[4]), + Children[0].EvaluateSubchannel(Subchannels[5])); + default: + throw new NotImplementedException(); + } + } } #pragma warning restore CS0660, CS0661 } \ No newline at end of file diff --git a/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/Matrix4x4Node.cs b/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/Matrix4x4Node.cs index b75ec095e87..97e2d79665b 100644 --- a/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/Matrix4x4Node.cs +++ b/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/Matrix4x4Node.cs @@ -2,7 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System; using System.Numerics; +using Windows.UI.Composition; namespace Microsoft.Toolkit.Uwp.UI.Animations.Expressions { @@ -410,6 +412,79 @@ protected internal override string GetValue() } private Matrix4x4 _value; + + /// + /// Evaluates the current value of the expression + /// + /// The current value of the expression + public Matrix4x4 Evaluate() + { + switch (NodeType) + { + case ExpressionNodeType.ConstantValue: + return _value; + case ExpressionNodeType.ConstantParameter: + throw new NotImplementedException(); + case ExpressionNodeType.ReferenceProperty: + var reference = (Children[0] as ReferenceNode).Reference; + return PropertyName switch + { + nameof(Visual.TransformMatrix) => (reference as Visual).TransformMatrix, + _ => GetProperty() + }; + + Matrix4x4 GetProperty() + { + reference.Properties.TryGetMatrix4x4(PropertyName, out var value); + return value; + } + + case ExpressionNodeType.Add: + return + (Children[0] as Matrix4x4Node).Evaluate() + + (Children[1] as Matrix4x4Node).Evaluate(); + case ExpressionNodeType.Subtract: + return + (Children[0] as Matrix4x4Node).Evaluate() - + (Children[1] as Matrix4x4Node).Evaluate(); + case ExpressionNodeType.Negate: + return + -(Children[0] as Matrix4x4Node).Evaluate(); + case ExpressionNodeType.Multiply: + return (Children[0], Children[1]) switch + { + (Matrix4x4Node v1, Matrix4x4Node v2) => v1.Evaluate() * v2.Evaluate(), + (Matrix4x4Node v1, ScalarNode s2) => v1.Evaluate() * s2.Evaluate(), + (ScalarNode s1, Matrix4x4Node v2) => v2.Evaluate() * s1.Evaluate(), + _ => throw new NotImplementedException() + }; + case ExpressionNodeType.Conditional: + return + (Children[0] as BooleanNode).Evaluate() ? + (Children[1] as Matrix4x4Node).Evaluate() : + (Children[2] as Matrix4x4Node).Evaluate(); + case ExpressionNodeType.Swizzle: + return new Matrix4x4( + Children[0].EvaluateSubchannel(Subchannels[0]), + Children[0].EvaluateSubchannel(Subchannels[1]), + Children[0].EvaluateSubchannel(Subchannels[2]), + Children[0].EvaluateSubchannel(Subchannels[3]), + Children[0].EvaluateSubchannel(Subchannels[4]), + Children[0].EvaluateSubchannel(Subchannels[5]), + Children[0].EvaluateSubchannel(Subchannels[6]), + Children[0].EvaluateSubchannel(Subchannels[7]), + Children[0].EvaluateSubchannel(Subchannels[8]), + Children[0].EvaluateSubchannel(Subchannels[9]), + Children[0].EvaluateSubchannel(Subchannels[10]), + Children[0].EvaluateSubchannel(Subchannels[11]), + Children[0].EvaluateSubchannel(Subchannels[12]), + Children[0].EvaluateSubchannel(Subchannels[13]), + Children[0].EvaluateSubchannel(Subchannels[14]), + Children[0].EvaluateSubchannel(Subchannels[15])); + default: + throw new NotImplementedException(); + } + } } #pragma warning restore CS0660, CS0661 } \ No newline at end of file diff --git a/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/QuaternionNode.cs b/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/QuaternionNode.cs index 54b09e738ca..cd69fa34253 100644 --- a/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/QuaternionNode.cs +++ b/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/QuaternionNode.cs @@ -2,7 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System; using System.Numerics; +using Windows.UI.Composition; namespace Microsoft.Toolkit.Uwp.UI.Animations.Expressions { @@ -130,6 +132,69 @@ protected internal override string GetValue() } private Quaternion _value; + + /// + /// Evaluates the current value of the expression + /// + /// The current value of the expression + public Quaternion Evaluate() + { + switch (NodeType) + { + case ExpressionNodeType.ConstantValue: + return _value; + case ExpressionNodeType.ConstantParameter: + throw new NotImplementedException(); + case ExpressionNodeType.ReferenceProperty: + var reference = (Children[0] as ReferenceNode).Reference; + return PropertyName switch + { + nameof(Visual.Orientation) => (reference as Visual).Orientation, + _ => GetProperty() + }; + + Quaternion GetProperty() + { + reference.Properties.TryGetQuaternion(PropertyName, out var value); + return value; + } + + case ExpressionNodeType.Add: + return + (Children[0] as QuaternionNode).Evaluate() + + (Children[1] as QuaternionNode).Evaluate(); + case ExpressionNodeType.Subtract: + return + (Children[0] as QuaternionNode).Evaluate() - + (Children[1] as QuaternionNode).Evaluate(); + case ExpressionNodeType.Negate: + return + -(Children[0] as QuaternionNode).Evaluate(); + case ExpressionNodeType.Multiply: + return (Children[0], Children[1]) switch + { + (QuaternionNode v1, QuaternionNode v2) => v1.Evaluate() * v2.Evaluate(), + (QuaternionNode v1, ScalarNode s2) => v1.Evaluate() * s2.Evaluate(), + (ScalarNode s1, QuaternionNode v2) => v2.Evaluate() * s1.Evaluate(), + _ => throw new NotImplementedException() + }; + case ExpressionNodeType.Divide: + return + (Children[0] as QuaternionNode).Evaluate() / + (Children[1] as QuaternionNode).Evaluate(); + case ExpressionNodeType.QuaternionFromAxisAngle: + return Quaternion.CreateFromAxisAngle((Children[0] as Vector3Node).Evaluate(), (Children[1] as ScalarNode).Evaluate()); + case ExpressionNodeType.Conditional: + return + (Children[0] as BooleanNode).Evaluate() ? + (Children[1] as QuaternionNode).Evaluate() : + (Children[2] as QuaternionNode).Evaluate(); + case ExpressionNodeType.Swizzle: + return new Quaternion(this.EvaluateSubchannel(Subchannels[0]), this.EvaluateSubchannel(Subchannels[1]), this.EvaluateSubchannel(Subchannels[2]), this.EvaluateSubchannel(Subchannels[4])); + default: + throw new NotImplementedException(); + } + } } #pragma warning restore CS0660, CS0661 } \ No newline at end of file diff --git a/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/ScalarNode.cs b/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/ScalarNode.cs index fe3b7408b91..3f9ef5cc4d7 100644 --- a/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/ScalarNode.cs +++ b/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/ScalarNode.cs @@ -2,6 +2,10 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System; +using System.Numerics; +using Windows.UI.Composition; + namespace Microsoft.Toolkit.Uwp.UI.Animations.Expressions { // Ignore warning: 'ScalarNode' defines operator == or operator != but does not override Object.Equals(object o) && Object.GetHashCode() @@ -258,6 +262,106 @@ protected internal override string GetValue() } private float _value; + + /// + /// Evaluates the current value of the expression + /// + /// The current value of the expression + public float Evaluate() + { + switch (NodeType) + { + case ExpressionNodeType.ConstantValue: + return _value; + case ExpressionNodeType.ConstantParameter: + throw new NotImplementedException(); + case ExpressionNodeType.ReferenceProperty: + var reference = (Children[0] as ReferenceNode).Reference; + return PropertyName switch + { + nameof(Visual.Opacity) => (reference as Visual).Opacity, + nameof(Visual.RotationAngle) => (reference as Visual).RotationAngle, + nameof(InsetClip.BottomInset) => (reference as InsetClip).BottomInset, + nameof(InsetClip.LeftInset) => (reference as InsetClip).LeftInset, + nameof(InsetClip.RightInset) => (reference as InsetClip).RightInset, + nameof(InsetClip.TopInset) => (reference as InsetClip).TopInset, + _ => GetProperty() + }; + + float GetProperty() + { + reference.Properties.TryGetScalar(PropertyName, out var value); + return value; + } + + case ExpressionNodeType.Negate: + return -(Children[0] as ScalarNode).Evaluate(); + case ExpressionNodeType.Add: + return (Children[0] as ScalarNode).Evaluate() + (Children[1] as ScalarNode).Evaluate(); + case ExpressionNodeType.Subtract: + return (Children[0] as ScalarNode).Evaluate() - (Children[1] as ScalarNode).Evaluate(); + case ExpressionNodeType.Multiply: + return (Children[0] as ScalarNode).Evaluate() * (Children[1] as ScalarNode).Evaluate(); + case ExpressionNodeType.Divide: + return (Children[0] as ScalarNode).Evaluate() / (Children[1] as ScalarNode).Evaluate(); + case ExpressionNodeType.Min: + return MathF.Min((Children[0] as ScalarNode).Evaluate(), (Children[1] as ScalarNode).Evaluate()); + case ExpressionNodeType.Max: + return MathF.Max((Children[0] as ScalarNode).Evaluate(), (Children[1] as ScalarNode).Evaluate()); + case ExpressionNodeType.Absolute: + return MathF.Abs((Children[0] as ScalarNode).Evaluate()); + case ExpressionNodeType.Sin: + return MathF.Sin((Children[0] as ScalarNode).Evaluate()); + case ExpressionNodeType.Cos: + return MathF.Cos((Children[0] as ScalarNode).Evaluate()); + case ExpressionNodeType.Asin: + return MathF.Asin((Children[0] as ScalarNode).Evaluate()); + case ExpressionNodeType.Acos: + return MathF.Acos((Children[0] as ScalarNode).Evaluate()); + case ExpressionNodeType.Atan: + return MathF.Atan((Children[0] as ScalarNode).Evaluate()); + case ExpressionNodeType.Log10: + return MathF.Log10((Children[0] as ScalarNode).Evaluate()); + case ExpressionNodeType.Conditional: + return (Children[0] as BooleanNode).Evaluate() ? (Children[1] as ScalarNode).Evaluate() : (Children[2] as ScalarNode).Evaluate(); + case ExpressionNodeType.Distance: + return Vector2.Distance((Children[0] as Vector2Node).Evaluate(), (Children[1] as Vector2Node).Evaluate()); + case ExpressionNodeType.Lerp: + { + var start = (Children[0] as ScalarNode).Evaluate(); + var end = (Children[1] as ScalarNode).Evaluate(); + var progress = (Children[2] as ScalarNode).Evaluate(); + return start + (progress * (end - start)); + } + + case ExpressionNodeType.Swizzle: + return Children[0] switch + { + ScalarNode n => n.Evaluate(), + Vector2Node n => Subchannels[0] switch + { + "X" => n.Evaluate().X, + _ => n.Evaluate().Y, + }, + Vector3Node n => Subchannels[0] switch + { + "X" => n.Evaluate().X, + "Y" => n.Evaluate().Y, + _ => n.Evaluate().Z, + }, + Vector4Node n => Subchannels[0] switch + { + "X" => n.Evaluate().X, + "Y" => n.Evaluate().Y, + "Z" => n.Evaluate().Z, + _ => n.Evaluate().W, + }, + _ => throw new NotImplementedException() + }; + default: + throw new NotImplementedException(); + } + } } #pragma warning restore CS0660, CS0661 } \ No newline at end of file diff --git a/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/Vector2Node.cs b/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/Vector2Node.cs index 31c9885e70e..100eba0970d 100644 --- a/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/Vector2Node.cs +++ b/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/Vector2Node.cs @@ -2,7 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System; using System.Numerics; +using Windows.UI.Composition; namespace Microsoft.Toolkit.Uwp.UI.Animations.Expressions { @@ -301,6 +303,70 @@ protected internal override string GetValue() } private Vector2 _value; + + /// + /// Evaluates the current value of the expression + /// + /// The current value of the expression + public Vector2 Evaluate() + { + switch (NodeType) + { + case ExpressionNodeType.ConstantValue: + return _value; + case ExpressionNodeType.ConstantParameter: + throw new NotImplementedException(); + case ExpressionNodeType.ReferenceProperty: + var reference = (Children[0] as ReferenceNode).Reference; + return PropertyName switch + { + nameof(Visual.Size) => (reference as Visual).Size, + nameof(Visual.AnchorPoint) => (reference as Visual).AnchorPoint, + _ => GetProperty() + }; + + Vector2 GetProperty() + { + reference.Properties.TryGetVector2(PropertyName, out var value); + return value; + } + + case ExpressionNodeType.Conditional: + return + (Children[0] as BooleanNode).Evaluate() ? + (Children[1] as Vector2Node).Evaluate() : + (Children[2] as Vector2Node).Evaluate(); + case ExpressionNodeType.Add: + return + (Children[0] as Vector2Node).Evaluate() + + (Children[1] as Vector2Node).Evaluate(); + case ExpressionNodeType.Subtract: + return + (Children[0] as Vector2Node).Evaluate() - + (Children[1] as Vector2Node).Evaluate(); + case ExpressionNodeType.Negate: + return + -(Children[0] as Vector2Node).Evaluate(); + case ExpressionNodeType.Multiply: + return (Children[0], Children[1]) switch + { + (Vector2Node v1, Vector2Node v2) => v1.Evaluate() * v2.Evaluate(), + (Vector2Node v1, ScalarNode s2) => v1.Evaluate() * s2.Evaluate(), + (ScalarNode s1, Vector2Node v2) => s1.Evaluate() * v2.Evaluate(), + _ => throw new NotImplementedException() + }; + case ExpressionNodeType.Divide: + return + (Children[0] as Vector2Node).Evaluate() / + (Children[1] as Vector2Node).Evaluate(); + case ExpressionNodeType.Vector2: + return new Vector2((Children[0] as ScalarNode).Evaluate(), (Children[1] as ScalarNode).Evaluate()); + case ExpressionNodeType.Swizzle: + return new Vector2(Children[0].EvaluateSubchannel(Subchannels[0]), Children[0].EvaluateSubchannel(Subchannels[1])); + default: + throw new NotImplementedException(); + } + } } #pragma warning restore CS0660, CS0661 } \ No newline at end of file diff --git a/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/Vector3Node.cs b/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/Vector3Node.cs index 7493428608a..238f0468ede 100644 --- a/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/Vector3Node.cs +++ b/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/Vector3Node.cs @@ -2,7 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System; using System.Numerics; +using Windows.UI.Composition; namespace Microsoft.Toolkit.Uwp.UI.Animations.Expressions { @@ -324,6 +326,74 @@ protected internal override string GetValue() } private Vector3 _value; + + /// + /// Evaluates the current value of the expression + /// + /// The current value of the expression + public Vector3 Evaluate() + { + switch (NodeType) + { + case ExpressionNodeType.ConstantValue: + return _value; + case ExpressionNodeType.ConstantParameter: + throw new NotImplementedException(); + case ExpressionNodeType.ReferenceProperty: + var reference = (Children[0] as ReferenceNode).Reference; + return PropertyName switch + { + nameof(Visual.Offset) => (reference as Visual).Offset, + nameof(Visual.RotationAxis) => (reference as Visual).RotationAxis, + nameof(Visual.CenterPoint) => (reference as Visual).CenterPoint, + _ => GetProperty() + }; + + Vector3 GetProperty() + { + reference.Properties.TryGetVector3(PropertyName, out var value); + return value; + } + + case ExpressionNodeType.Conditional: + return + (Children[0] as BooleanNode).Evaluate() ? + (Children[1] as Vector3Node).Evaluate() : + (Children[2] as Vector3Node).Evaluate(); + case ExpressionNodeType.Add: + return + (Children[0] as Vector3Node).Evaluate() + + (Children[1] as Vector3Node).Evaluate(); + case ExpressionNodeType.Subtract: + return + (Children[0] as Vector3Node).Evaluate() - + (Children[1] as Vector3Node).Evaluate(); + case ExpressionNodeType.Negate: + return + -(Children[0] as Vector3Node).Evaluate(); + case ExpressionNodeType.Multiply: + return (Children[0], Children[1]) switch + { + (Vector3Node v1, Vector3Node v2) => v1.Evaluate() * v2.Evaluate(), + (Vector3Node v1, ScalarNode s2) => v1.Evaluate() * s2.Evaluate(), + (ScalarNode s1, Vector3Node v2) => s1.Evaluate() * v2.Evaluate(), + _ => throw new NotImplementedException() + }; + case ExpressionNodeType.Divide: + return + (Children[0] as Vector3Node).Evaluate() / + (Children[1] as Vector3Node).Evaluate(); + case ExpressionNodeType.Vector3: + return new Vector3( + (Children[0] as ScalarNode).Evaluate(), + (Children[1] as ScalarNode).Evaluate(), + (Children[2] as ScalarNode).Evaluate()); + case ExpressionNodeType.Swizzle: + return new Vector3(Children[0].EvaluateSubchannel(Subchannels[0]), Children[0].EvaluateSubchannel(Subchannels[1]), Children[0].EvaluateSubchannel(Subchannels[2])); + default: + throw new NotImplementedException(); + } + } } #pragma warning restore CS0660, CS0661 } \ No newline at end of file diff --git a/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/Vector4Node.cs b/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/Vector4Node.cs index 83b85093088..fd43d02b5f0 100644 --- a/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/Vector4Node.cs +++ b/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/Vector4Node.cs @@ -2,7 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System; using System.Numerics; +using Windows.UI.Composition; namespace Microsoft.Toolkit.Uwp.UI.Animations.Expressions { @@ -347,6 +349,72 @@ protected internal override string GetValue() } private Vector4 _value; + + /// + /// Evaluates the current value of the expression + /// + /// The current value of the expression + public Vector4 Evaluate() + { + switch (NodeType) + { + case ExpressionNodeType.ConstantValue: + return _value; + case ExpressionNodeType.ConstantParameter: + throw new NotImplementedException(); + case ExpressionNodeType.ReferenceProperty: + var reference = (Children[0] as ReferenceNode).Reference; + return PropertyName switch + { + _ => GetProperty() + }; + + Vector4 GetProperty() + { + reference.Properties.TryGetVector4(PropertyName, out var value); + return value; + } + + case ExpressionNodeType.Conditional: + return + (Children[0] as BooleanNode).Evaluate() ? + (Children[1] as Vector4Node).Evaluate() : + (Children[2] as Vector4Node).Evaluate(); + case ExpressionNodeType.Add: + return + (Children[0] as Vector4Node).Evaluate() + + (Children[1] as Vector4Node).Evaluate(); + case ExpressionNodeType.Subtract: + return + (Children[0] as Vector4Node).Evaluate() - + (Children[1] as Vector4Node).Evaluate(); + case ExpressionNodeType.Negate: + return + -(Children[0] as Vector4Node).Evaluate(); + case ExpressionNodeType.Multiply: + return (Children[0], Children[1]) switch + { + (Vector4Node v1, Vector4Node v2) => v1.Evaluate() * v2.Evaluate(), + (Vector4Node v1, ScalarNode s2) => v1.Evaluate() * s2.Evaluate(), + (ScalarNode s1, Vector4Node v2) => s1.Evaluate() * v2.Evaluate(), + _ => throw new NotImplementedException() + }; + case ExpressionNodeType.Divide: + return + (Children[0] as Vector4Node).Evaluate() / + (Children[1] as Vector4Node).Evaluate(); + case ExpressionNodeType.Vector3: + return new Vector4( + (Children[0] as ScalarNode).Evaluate(), + (Children[1] as ScalarNode).Evaluate(), + (Children[2] as ScalarNode).Evaluate(), + (Children[2] as ScalarNode).Evaluate()); + case ExpressionNodeType.Swizzle: + return new Vector4(Children[0].EvaluateSubchannel(Subchannels[0]), Children[0].EvaluateSubchannel(Subchannels[1]), Children[0].EvaluateSubchannel(Subchannels[2]), Children[0].EvaluateSubchannel(Subchannels[3])); + default: + throw new NotImplementedException(); + } + } } #pragma warning restore CS0660, CS0661 } \ No newline at end of file diff --git a/UnitTests/UnitTests.UWP/UI/Animations/Test_ExpressionNode.cs b/UnitTests/UnitTests.UWP/UI/Animations/Test_ExpressionNode.cs new file mode 100644 index 00000000000..c61d8bafc99 --- /dev/null +++ b/UnitTests/UnitTests.UWP/UI/Animations/Test_ExpressionNode.cs @@ -0,0 +1,63 @@ +// 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. + +using System.Threading.Tasks; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Microsoft.Toolkit.Uwp; +using Windows.UI.Xaml.Controls; +using Microsoft.Toolkit.Uwp.UI.Animations; +using System.Numerics; +using Microsoft.Toolkit.Uwp.UI; +using System; +using Windows.UI.Xaml.Media; +using Windows.UI.Xaml.Hosting; +using Microsoft.Toolkit.Uwp.UI.Animations.Expressions; + +namespace UnitTests.UWP.UI.Animations +{ + [TestClass] + [TestCategory("Test_ExpressionNode")] + public class Test_ExpressionNode : VisualUITestBase + { + [TestMethod] + public async Task EvaluateExpressionNode() + { + await App.DispatcherQueue.EnqueueAsync(async () => + { + Grid grid = new(); + await SetTestContentAsync(grid); + + var visual = ElementCompositionPreview.GetElementVisual(grid); + + // Test basic vector algebra + visual.Offset = Vector3.UnitX; + var vector3AlgebraNode = (-visual.GetReference().Offset + + Vector3.UnitY + - Vector3.UnitZ) * 5; + + Assert.AreEqual(new Vector3(-5, 5, -5), vector3AlgebraNode.Evaluate()); + + // Test swizzle operation + visual.CenterPoint = Vector3.UnitY; + var swizzleNode = visual.GetReference().CenterPoint.GetSubchannels( + Vector3Node.Subchannel.Y, + Vector3Node.Subchannel.X, + Vector3Node.Subchannel.Y); + + Assert.AreEqual(new Vector3(1, 0, 1), swizzleNode.Evaluate()); + + // Test retrieving properties from set + var propertySet = visual.Compositor.CreatePropertySet(); + var propertyName = "test"; + var propertyNode = propertySet.GetReference().GetVector4Property(propertyName); + + propertySet.InsertVector4(propertyName, Vector4.UnitW); + Assert.AreEqual(Vector4.UnitW, propertyNode.Evaluate()); + + propertySet.InsertVector4(propertyName, Vector4.UnitX); + Assert.AreEqual(Vector4.UnitX, propertyNode.Evaluate()); + }); + } + } +} \ No newline at end of file diff --git a/UnitTests/UnitTests.UWP/UnitTests.UWP.csproj b/UnitTests/UnitTests.UWP/UnitTests.UWP.csproj index d50b438032e..29f55845ee9 100644 --- a/UnitTests/UnitTests.UWP/UnitTests.UWP.csproj +++ b/UnitTests/UnitTests.UWP/UnitTests.UWP.csproj @@ -231,6 +231,7 @@ + From f109535049d3224bea49fd1e49dd74dd76f9a080 Mon Sep 17 00:00:00 2001 From: Arcadio Garcia Salvadores Date: Mon, 16 May 2022 15:32:36 -0700 Subject: [PATCH 2/3] Remove explicit ConstantParameter --- .../Expressions/ExpressionNodes/BooleanNode.cs | 2 -- .../Expressions/ExpressionNodes/ColorNode.cs | 2 -- .../Expressions/ExpressionNodes/Matrix3x2Node.cs | 2 -- .../Expressions/ExpressionNodes/Matrix4x4Node.cs | 2 -- .../Expressions/ExpressionNodes/QuaternionNode.cs | 2 -- .../Expressions/ExpressionNodes/ScalarNode.cs | 2 -- .../Expressions/ExpressionNodes/Vector2Node.cs | 2 -- .../Expressions/ExpressionNodes/Vector3Node.cs | 2 -- .../Expressions/ExpressionNodes/Vector4Node.cs | 2 -- 9 files changed, 18 deletions(-) diff --git a/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/BooleanNode.cs b/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/BooleanNode.cs index e6d206432cc..625cf7dbbae 100644 --- a/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/BooleanNode.cs +++ b/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/BooleanNode.cs @@ -140,8 +140,6 @@ public bool Evaluate() { case ExpressionNodeType.ConstantValue: return _value; - case ExpressionNodeType.ConstantParameter: - throw new NotImplementedException(); case ExpressionNodeType.Equals: return Equals(Children[0], Children[1]); case ExpressionNodeType.NotEquals: diff --git a/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/ColorNode.cs b/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/ColorNode.cs index 5e85bc7ff1e..c442df610fd 100644 --- a/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/ColorNode.cs +++ b/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/ColorNode.cs @@ -110,8 +110,6 @@ public Color Evaluate() { case ExpressionNodeType.ConstantValue: return _value; - case ExpressionNodeType.ConstantParameter: - throw new NotImplementedException(); case ExpressionNodeType.ReferenceProperty: var reference = (Children[0] as ReferenceNode).Reference; return PropertyName switch diff --git a/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/Matrix3x2Node.cs b/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/Matrix3x2Node.cs index 2d12adffc99..87155ba3073 100644 --- a/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/Matrix3x2Node.cs +++ b/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/Matrix3x2Node.cs @@ -348,8 +348,6 @@ public Matrix3x2 Evaluate() { case ExpressionNodeType.ConstantValue: return _value; - case ExpressionNodeType.ConstantParameter: - throw new NotImplementedException(); case ExpressionNodeType.ReferenceProperty: var reference = (Children[0] as ReferenceNode).Reference; reference.Properties.TryGetMatrix3x2(PropertyName, out var referencedProperty); diff --git a/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/Matrix4x4Node.cs b/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/Matrix4x4Node.cs index 97e2d79665b..33bd6650465 100644 --- a/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/Matrix4x4Node.cs +++ b/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/Matrix4x4Node.cs @@ -423,8 +423,6 @@ public Matrix4x4 Evaluate() { case ExpressionNodeType.ConstantValue: return _value; - case ExpressionNodeType.ConstantParameter: - throw new NotImplementedException(); case ExpressionNodeType.ReferenceProperty: var reference = (Children[0] as ReferenceNode).Reference; return PropertyName switch diff --git a/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/QuaternionNode.cs b/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/QuaternionNode.cs index cd69fa34253..26b29041cc0 100644 --- a/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/QuaternionNode.cs +++ b/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/QuaternionNode.cs @@ -143,8 +143,6 @@ public Quaternion Evaluate() { case ExpressionNodeType.ConstantValue: return _value; - case ExpressionNodeType.ConstantParameter: - throw new NotImplementedException(); case ExpressionNodeType.ReferenceProperty: var reference = (Children[0] as ReferenceNode).Reference; return PropertyName switch diff --git a/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/ScalarNode.cs b/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/ScalarNode.cs index 3f9ef5cc4d7..32dbfee2061 100644 --- a/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/ScalarNode.cs +++ b/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/ScalarNode.cs @@ -273,8 +273,6 @@ public float Evaluate() { case ExpressionNodeType.ConstantValue: return _value; - case ExpressionNodeType.ConstantParameter: - throw new NotImplementedException(); case ExpressionNodeType.ReferenceProperty: var reference = (Children[0] as ReferenceNode).Reference; return PropertyName switch diff --git a/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/Vector2Node.cs b/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/Vector2Node.cs index 100eba0970d..91c7513c980 100644 --- a/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/Vector2Node.cs +++ b/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/Vector2Node.cs @@ -314,8 +314,6 @@ public Vector2 Evaluate() { case ExpressionNodeType.ConstantValue: return _value; - case ExpressionNodeType.ConstantParameter: - throw new NotImplementedException(); case ExpressionNodeType.ReferenceProperty: var reference = (Children[0] as ReferenceNode).Reference; return PropertyName switch diff --git a/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/Vector3Node.cs b/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/Vector3Node.cs index 238f0468ede..833dfe450c5 100644 --- a/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/Vector3Node.cs +++ b/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/Vector3Node.cs @@ -337,8 +337,6 @@ public Vector3 Evaluate() { case ExpressionNodeType.ConstantValue: return _value; - case ExpressionNodeType.ConstantParameter: - throw new NotImplementedException(); case ExpressionNodeType.ReferenceProperty: var reference = (Children[0] as ReferenceNode).Reference; return PropertyName switch diff --git a/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/Vector4Node.cs b/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/Vector4Node.cs index fd43d02b5f0..dadc67f5489 100644 --- a/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/Vector4Node.cs +++ b/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/Vector4Node.cs @@ -358,8 +358,6 @@ public Vector4 Evaluate() { switch (NodeType) { - case ExpressionNodeType.ConstantValue: - return _value; case ExpressionNodeType.ConstantParameter: throw new NotImplementedException(); case ExpressionNodeType.ReferenceProperty: From 9b6230cc52bb99ebabf774135a3b548ad91f61d3 Mon Sep 17 00:00:00 2001 From: Arcadio Garcia Salvadores Date: Mon, 4 Jul 2022 16:16:46 -0700 Subject: [PATCH 3/3] Add missing methods --- .../Expressions/ExpressionNodes/ScalarNode.cs | 20 +++++++++++++++++++ .../ExpressionNodes/Vector3Node.cs | 7 +++++++ 2 files changed, 27 insertions(+) diff --git a/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/ScalarNode.cs b/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/ScalarNode.cs index 32dbfee2061..34f07643a56 100644 --- a/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/ScalarNode.cs +++ b/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/ScalarNode.cs @@ -318,8 +318,28 @@ float GetProperty() return MathF.Acos((Children[0] as ScalarNode).Evaluate()); case ExpressionNodeType.Atan: return MathF.Atan((Children[0] as ScalarNode).Evaluate()); + case ExpressionNodeType.Ceil: + return MathF.Ceiling((Children[0] as ScalarNode).Evaluate()); + case ExpressionNodeType.Floor: + return MathF.Floor((Children[0] as ScalarNode).Evaluate()); + case ExpressionNodeType.Ln: + return MathF.Log((Children[0] as ScalarNode).Evaluate()); case ExpressionNodeType.Log10: return MathF.Log10((Children[0] as ScalarNode).Evaluate()); + case ExpressionNodeType.Pow: + return MathF.Pow((Children[0] as ScalarNode).Evaluate(), (Children[1] as ScalarNode).Evaluate()); + case ExpressionNodeType.Round: + return MathF.Round((Children[0] as ScalarNode).Evaluate()); + case ExpressionNodeType.Square: + return MathF.Pow((Children[0] as ScalarNode).Evaluate(), 2); + case ExpressionNodeType.Sqrt: + return MathF.Sqrt((Children[0] as ScalarNode).Evaluate()); + case ExpressionNodeType.ToDegrees: + return 180 * (Children[0] as ScalarNode).Evaluate() / MathF.PI; + case ExpressionNodeType.ToRadians: + return MathF.PI * (Children[0] as ScalarNode).Evaluate() / 180; + case ExpressionNodeType.Modulus: + return (Children[0] as ScalarNode).Evaluate() % (Children[1] as ScalarNode).Evaluate(); case ExpressionNodeType.Conditional: return (Children[0] as BooleanNode).Evaluate() ? (Children[1] as ScalarNode).Evaluate() : (Children[2] as ScalarNode).Evaluate(); case ExpressionNodeType.Distance: diff --git a/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/Vector3Node.cs b/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/Vector3Node.cs index 833dfe450c5..4a89f50991d 100644 --- a/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/Vector3Node.cs +++ b/Microsoft.Toolkit.Uwp.UI.Animations/Expressions/ExpressionNodes/Vector3Node.cs @@ -366,6 +366,13 @@ Vector3 GetProperty() return (Children[0] as Vector3Node).Evaluate() - (Children[1] as Vector3Node).Evaluate(); + case ExpressionNodeType.Lerp: + { + var t = (Children[2] as ScalarNode).Evaluate(); + return + (Children[0] as Vector3Node).Evaluate() * t - + (Children[1] as Vector3Node).Evaluate() * (1 - t); + } case ExpressionNodeType.Negate: return -(Children[0] as Vector3Node).Evaluate();