Skip to content

Commit

Permalink
Optimize Visual size sync through RelativeSizeAdjustment over express…
Browse files Browse the repository at this point in the history
…ion animations (#4397)

## PR Type

What kind of change does this PR introduce?

<!-- Please uncomment one or more options below that apply to this PR. -->

- Optimization
<!-- - Bugfix -->
<!-- - Feature -->
<!-- - Code style update (formatting) -->
<!-- - Refactoring (no functional changes, no api changes) -->
<!-- - Build or CI related changes -->
<!-- - Documentation content changes -->
<!-- - Sample app changes -->
<!-- - Other... Please describe: -->

## What is the current behavior?
All `Visual` objects created through our pipeline system are kept in sync with target objects through an expression animation.
<!-- Please describe the current behavior that you are modifying, or link to a relevant issue. -->

## What is the new behavior?
We're now just using [Visual.RelativeSizeAdjustment](https://docs.microsoft.com/en-us/uwp/api/windows.ui.composition.visual.relativesizeadjustment) to achieve the same without the animation overhead.

I did test this in the sample app, but still adding the testing required tag as I'd like more validation on this.

## Open questions

I'm wondering whether there's a way to also optimize this bit here by removing the animation:

https://github.com/CommunityToolkit/WindowsCommunityToolkit/blob/4a09bf04531fb24e20dd8f42b18c0460f22d3ef3/Microsoft.Toolkit.Uwp.UI/Extensions/VisualExtensions.cs#L502-L511

Haven't yet figured out a solution though 🤔

**EDIT:** spoke with Chris, yeah there isn't a way to do this, nevermind 🤣

## PR Checklist

Please check if your PR fulfills the following requirements: <!-- and remove the ones that are not applicable to the current PR -->

- [X] Tested code with current [supported SDKs](../#supported)
- [ ] New component
  - [ ] Pull Request has been submitted to the documentation repository [instructions](../blob/main/Contributing.md#docs). Link: <!-- docs PR link -->
  - [ ] Added description of major feature to project description for NuGet package (4000 total character limit, so don't push entire description over that)
  - [ ] If control, added to Visual Studio Design project
- [ ] Sample in sample app has been added / updated (for bug fixes / features)
  - [ ] Icon has been created (if new sample) following the [Thumbnail Style Guide and templates](https://github.com/CommunityToolkit/WindowsCommunityToolkit-design-assets)
- [ ] New major technical changes in the toolkit have or will be added to the [Wiki](https://github.com/CommunityToolkit/WindowsCommunityToolkit/wiki) e.g. build changes, source generators, testing infrastructure, sample creation changes, etc...
- [ ] Tests for the changes have been added (for bug fixes / features) (if applicable)
- [X] Header has been added to all new source files (run _build/UpdateHeaders.bat_)
- [X] Contains **NO** breaking changes
  • Loading branch information
msftbot[bot] authored Jan 4, 2022
2 parents a629604 + c991429 commit c1cdfee
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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.Numerics;
using Windows.UI.Composition;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Hosting;

Expand Down Expand Up @@ -48,10 +50,10 @@ public static void SetVisualFactory(UIElement element, AttachedVisualFactoryBase
/// <param name="e">The <see cref="DependencyPropertyChangedEventArgs"/> instance for the current event.</param>
private static async void OnVisualFactoryPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var element = (UIElement)d;
var attachedVisual = await ((AttachedVisualFactoryBase)e.NewValue).GetAttachedVisualAsync(element);
UIElement element = (UIElement)d;
Visual attachedVisual = await ((AttachedVisualFactoryBase)e.NewValue).GetAttachedVisualAsync(element);

attachedVisual.BindSize(element);
attachedVisual.RelativeSizeAdjustment = Vector2.One;

ElementCompositionPreview.SetElementChildVisual(element, attachedVisual);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ namespace Microsoft.Toolkit.Uwp.UI.Media
internal static class CompositionObjectExtensions
{
/// <summary>
/// Starts an <see cref="ExpressionAnimation"/> to keep the size of the source <see cref="CompositionObject"/> in sync with the target <see cref="UIElement"/>
/// Starts an <see cref="ExpressionAnimation"/> to keep the size of the source <see cref="Visual"/> in sync with the target <see cref="UIElement"/>
/// </summary>
/// <param name="source">The <see cref="CompositionObject"/> to start the animation on</param>
/// <param name="source">The <see cref="Visual"/> to start the animation on</param>
/// <param name="target">The target <see cref="UIElement"/> to read the size updates from</param>
public static void BindSize(this CompositionObject source, UIElement target)
public static void BindSize(this Visual source, UIElement target)
{
var visual = ElementCompositionPreview.GetElementVisual(target);
var bindSizeAnimation = source.Compositor.CreateExpressionAnimation($"{nameof(visual)}.Size");
Expand Down
12 changes: 10 additions & 2 deletions Microsoft.Toolkit.Uwp.UI.Media/Pipelines/PipelineBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Numerics;
using System.Threading.Tasks;
using Microsoft.Toolkit.Uwp.UI.Animations;
using Windows.Graphics.Effects;
Expand Down Expand Up @@ -188,15 +189,22 @@ public async Task<CompositionBrush> BuildAsync()
/// <returns>A <see cref="Task{T}"/> that returns the final <see cref="SpriteVisual"/> instance to use</returns>
public async Task<SpriteVisual> AttachAsync(UIElement target, UIElement reference = null)
{
var visual = Window.Current.Compositor.CreateSpriteVisual();
SpriteVisual visual = Window.Current.Compositor.CreateSpriteVisual();

visual.Brush = await BuildAsync();

ElementCompositionPreview.SetElementChildVisual(target, visual);

if (reference != null)
{
visual.BindSize(reference);
if (reference == target)
{
visual.RelativeSizeAdjustment = Vector2.One;
}
else
{
visual.BindSize(reference);
}
}

return visual;
Expand Down

0 comments on commit c1cdfee

Please sign in to comment.