Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TileControl: Remove Animations.Expressions usage #3633

Merged
12 commits merged into from
Dec 17, 2020
107 changes: 49 additions & 58 deletions Microsoft.Toolkit.Uwp.UI.Controls/TileControl/TileControl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -439,11 +438,16 @@ private async Task CreateModuloExpression(ScrollViewer scrollViewer = null)
/// <param name="scrollOrientation">The ScrollOrientation</param>
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)
{
Expand All @@ -453,90 +457,77 @@ 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);
propertySetModulo.InsertScalar(imageHeightParam, (float)imageWidth);
michael-hawker marked this conversation as resolved.
Show resolved Hide resolved
propertySetModulo.InsertScalar(offsetXParam, (float)OffsetX);
propertySetModulo.InsertScalar(imageHeightParam, (float)imageHeight);
propertySetModulo.InsertScalar(imageWidthParam, (float)imageHeight);
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<ManipulationPropertySetReferenceNode>();

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 GenerateParalaxFormula(string scrollTranslation, string speed, string offset, string dimension)
=> GenerateFormula(string.Format("Ceil(({0} * {1}) + {2})", scrollTranslation, speed, offset), dimension);

expressionXVal = GenerateParalaxFormula(translationParam + "." + nameof(scrollViewer.Translation.X), qualifiedSpeedParam, qualifiedOffsetXParam, qualifiedImageWidthParam);

expressionYVal = GenerateParalaxFormula(translationParam + "." + nameof(scrollViewer.Translation.Y), qualifiedSpeedParam, qualifiedOffsetYParam, qualifiedImageHeightParam);
Rosuavio marked this conversation as resolved.
Show resolved Hide resolved
}

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);
}
}
Expand Down