diff --git a/Microsoft.Toolkit.Uwp.UI.Controls/TileControl/TileControl.cs b/Microsoft.Toolkit.Uwp.UI.Controls/TileControl/TileControl.cs index dea441e074f..b537ffebf6c 100644 --- a/Microsoft.Toolkit.Uwp.UI.Controls/TileControl/TileControl.cs +++ b/Microsoft.Toolkit.Uwp.UI.Controls/TileControl/TileControl.cs @@ -8,7 +8,6 @@ using System.Numerics; using System.Threading; using System.Threading.Tasks; -using Microsoft.Toolkit.Uwp.UI.Animations.Expressions; using Microsoft.Toolkit.Uwp.UI.Extensions; using Windows.Foundation; using Windows.UI.Composition; @@ -439,11 +438,16 @@ private async Task CreateModuloExpression(ScrollViewer scrollViewer = null) /// The ScrollOrientation private void CreateModuloExpression(ScrollViewer scrollViewer, double imageWidth, double imageHeight, ScrollOrientation scrollOrientation) { - const string offsetXParam = "offsetX"; - const string offsetYParam = "offsetY"; - const string imageWidthParam = "imageWidth"; - const string imageHeightParam = "imageHeight"; - const string speedParam = "speed"; + const string propSetParam = "p"; + const string offsetXParam = nameof(OffsetX); + const string qualifiedOffsetXParam = propSetParam + "." + offsetXParam; + const string offsetYParam = nameof(OffsetY); + const string qualifiedOffsetYParam = propSetParam + "." + offsetYParam; + const string imageWidthParam = nameof(imageWidth); + const string qualifiedImageWidthParam = propSetParam + "." + imageWidthParam; + const string imageHeightParam = nameof(imageHeight); + const string qualifiedImageHeightParam = propSetParam + "." + imageHeightParam; + const string speedParam = nameof(ParallaxSpeedRatio); if (_containerVisual == null) { @@ -453,10 +457,8 @@ private void CreateModuloExpression(ScrollViewer scrollViewer, double imageWidth var compositor = _containerVisual.Compositor; // Setup the expression - ExpressionNode expressionX = null; - ExpressionNode expressionY = null; - ExpressionNode expressionXVal; - ExpressionNode expressionYVal; + var expressionX = compositor.CreateExpressionAnimation(); + var expressionY = compositor.CreateExpressionAnimation(); var propertySetModulo = compositor.CreatePropertySet(); propertySetModulo.InsertScalar(imageWidthParam, (float)imageWidth); @@ -465,78 +467,67 @@ private void CreateModuloExpression(ScrollViewer scrollViewer, double imageWidth propertySetModulo.InsertScalar(offsetYParam, (float)OffsetY); propertySetModulo.InsertScalar(speedParam, (float)ParallaxSpeedRatio); - var propertySetNodeModulo = propertySetModulo.GetReference(); - - var imageHeightNode = propertySetNodeModulo.GetScalarProperty(imageHeightParam); - var imageWidthNode = propertySetNodeModulo.GetScalarProperty(imageWidthParam); + expressionX.SetReferenceParameter(propSetParam, propertySetModulo); + expressionY.SetReferenceParameter(propSetParam, propertySetModulo); + + string GenerateFormula(string common, string dimension) + => string.Format( + "{0} == 0 " + + "? 0 " + + ": {0} < 0 " + + "? -(Abs({0} - (Ceil({0} / {1}) * {1})) % {1}) " + + ": -({1} - ({0} % {1}))", + common, + dimension); + + string expressionXVal; + string expressionYVal; if (scrollViewer == null) { - var offsetXNode = ExpressionFunctions.Ceil(propertySetNodeModulo.GetScalarProperty(offsetXParam)); - var offsetYNode = ExpressionFunctions.Ceil(propertySetNodeModulo.GetScalarProperty(offsetYParam)); - // expressions are created to simulate a positive and negative modulo with the size of the image and the offset - expressionXVal = ExpressionFunctions.Conditional( - offsetXNode == 0, - 0, - ExpressionFunctions.Conditional( - offsetXNode < 0, - -(ExpressionFunctions.Abs(offsetXNode - (ExpressionFunctions.Ceil(offsetXNode / imageWidthNode) * imageWidthNode)) % imageWidthNode), - -(imageWidthNode - (offsetXNode % imageWidthNode)))); - - expressionYVal = ExpressionFunctions.Conditional( - offsetYNode == 0, - 0, - ExpressionFunctions.Conditional( - offsetYNode < 0, - -(ExpressionFunctions.Abs(offsetYNode - (ExpressionFunctions.Ceil(offsetYNode / imageHeightNode) * imageHeightNode)) % imageHeightNode), - -(imageHeightNode - (offsetYNode % imageHeightNode)))); + expressionXVal = GenerateFormula("Ceil(" + qualifiedOffsetXParam + ")", qualifiedImageHeightParam); + + expressionYVal = GenerateFormula("Ceil(" + qualifiedOffsetYParam + ")", qualifiedImageWidthParam); } else { // expressions are created to simulate a positive and negative modulo with the size of the image and the offset and the ScrollViewer offset (Translation) var scrollProperties = ElementCompositionPreview.GetScrollViewerManipulationPropertySet(scrollViewer); - var scrollPropSet = scrollProperties.GetSpecializedReference(); - - var speed = propertySetNodeModulo.GetScalarProperty(speedParam); - var xCommon = ExpressionFunctions.Ceil((scrollPropSet.Translation.X * speed) + propertySetNodeModulo.GetScalarProperty(offsetXParam)); - expressionXVal = ExpressionFunctions.Conditional( - xCommon == 0, - 0, - ExpressionFunctions.Conditional( - xCommon < 0, - -(ExpressionFunctions.Abs(xCommon - (ExpressionFunctions.Ceil(xCommon / imageWidthNode) * imageWidthNode)) % imageWidthNode), - -(imageWidthNode - (xCommon % imageWidthNode)))); - - var yCommon = ExpressionFunctions.Ceil((scrollPropSet.Translation.Y * speed) + propertySetNodeModulo.GetScalarProperty(offsetYParam)); - expressionYVal = ExpressionFunctions.Conditional( - yCommon == 0, - 0, - ExpressionFunctions.Conditional( - yCommon < 0, - -(ExpressionFunctions.Abs(yCommon - (ExpressionFunctions.Ceil(yCommon / imageHeightNode) * imageHeightNode)) % imageHeightNode), - -(imageHeightNode - (yCommon % imageHeightNode)))); + const string scrollParam = "s"; + const string translationParam = scrollParam + "." + nameof(scrollViewer.Translation); + const string qualifiedSpeedParam = propSetParam + "." + speedParam; + + expressionX.SetReferenceParameter(scrollParam, scrollProperties); + expressionY.SetReferenceParameter(scrollParam, scrollProperties); + + string GenerateParallaxFormula(string scrollTranslation, string speed, string offset, string dimension) + => GenerateFormula(string.Format("Ceil(({0} * {1}) + {2})", scrollTranslation, speed, offset), dimension); + + expressionXVal = GenerateParallaxFormula(translationParam + "." + nameof(scrollViewer.Translation.X), qualifiedSpeedParam, qualifiedOffsetXParam, qualifiedImageWidthParam); + + expressionYVal = GenerateParallaxFormula(translationParam + "." + nameof(scrollViewer.Translation.Y), qualifiedSpeedParam, qualifiedOffsetYParam, qualifiedImageHeightParam); } if (scrollOrientation == ScrollOrientation.Horizontal || scrollOrientation == ScrollOrientation.Both) { - expressionX = expressionXVal; + expressionX.Expression = expressionXVal; if (scrollOrientation == ScrollOrientation.Horizontal) { // In horizontal mode we never move the offset y - expressionY = (ScalarNode)0.0f; + expressionY.Expression = "0"; _containerVisual.Offset = new Vector3((float)OffsetY, 0, 0); } } if (scrollOrientation == ScrollOrientation.Vertical || scrollOrientation == ScrollOrientation.Both) { - expressionY = expressionYVal; + expressionY.Expression = expressionYVal; if (scrollOrientation == ScrollOrientation.Vertical) { // In vertical mode we never move the offset x - expressionX = (ScalarNode)0.0f; + expressionX.Expression = "0"; _containerVisual.Offset = new Vector3(0, (float)OffsetX, 0); } }