[Unity] Dynamically changing Animation Values with Bindings
Hey all, hopefully this is something simple that I have just overlooked. I'm trying to animate the ViewBox property of an ImageBrush through an animation. The catch is that I need to specify the value to animate to at runtime so I figured this would be a perfect time to take a stab at adding properties to the user control and use bindings for this.
Below is the code I current have set up and I am calling AnimateToView with a new Rect(50, 20, 348, 236) so the image being displayed should zoom in. However, nothing happens. when I update the animation storyboard to just use a hard coded value of To="50, 20, 348, 236" it works as expected. So I'm not sure what it is that I am missing. Any thoughts?
Below is the code I current have set up and I am calling AnimateToView with a new Rect(50, 20, 348, 236) so the image being displayed should zoom in. However, nothing happens. when I update the animation storyboard to just use a hard coded value of To="50, 20, 348, 236" it works as expected. So I'm not sure what it is that I am missing. Any thoughts?
Code: Select all
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:noesis="clr-namespace:NoesisGUIExtensions" xmlns:five="clr-namespace:FiveGui"
mc:Ignorable="d" x:Class="FiveGui.UIImageViewer" x:Name="_UIImageViewerControl" d:DesignWidth="1920" d:DesignHeight="1080">
<UserControl.Resources>
<ResourceDictionary>
<Storyboard x:Key="NextFrame">
<RectAnimation To="{Binding Frame}" Duration="0:0:1" Storyboard.TargetName="_Image" Storyboard.TargetProperty="Viewbox"/>
</Storyboard>
</ResourceDictionary>
</UserControl.Resources>
<Grid x:Name="LayoutRoot">
<Rectangle>
<Rectangle.Fill>
<ImageBrush x:Name="_Image" ImageSource="../GUIResources/DefaultImage.png" Viewbox="0,0,448,276" ViewboxUnits="Absolute"/>
</Rectangle.Fill>
</Rectangle>
</Grid>
</UserControl>
Code: Select all
using Noesis;
namespace FiveGui
{
[Noesis.Extended]
[Noesis.UserControlSource("Assets/GUI/GUIControls/UIImageViewer.xaml")]
public class UIImageViewer : Noesis.UserControl
{
public static DependencyProperty FrameProperty = DependencyProperty.Register("Frame", typeof(Rect), typeof(UIImageViewer), new PropertyMetadata(null));
public Rect Frame
{
get { return GetValue<Rect>(FrameProperty); }
set { SetValue<Rect>(FrameProperty, value); }
}
private Storyboard _nextFrame;
public void OnPostInit()
{
_nextFrame = FindStringResource<Storyboard>("NextFrame");
Frame = new Rect(0, 0, 448, 276);
}
private void AnimateToView(Rect rect)
{
Frame = rect;
_nextFrame.Begin(this);
}
}
}
-
sfernandez
Site Admin
- Posts: 3184
- Joined:
Re: [Unity] Dynamically changing Animation Values with Bindi
Hi,
The Binding you are using in the RectAnimation expects a DataContext to search for the Frame property. You have to set it when your UserControl is initialized:
The Binding you are using in the RectAnimation expects a DataContext to search for the Frame property. You have to set it when your UserControl is initialized:
Code: Select all
public class UIImageViewer : Noesis.UserControl
{
// ...
public void OnPostInit()
{
SetDataContext(this);
_nextFrame = FindStringResource<Storyboard>("NextFrame");
Frame = new Rect(0, 0, 448, 276);
}
// ...
}
Re: [Unity] Dynamically changing Animation Values with Bindi
Added that in and still got nothing.
-
sfernandez
Site Admin
- Posts: 3184
- Joined:
Re: [Unity] Dynamically changing Animation Values with Bindi
I tried the attached scene in 1.1.11 version and worked correctly.
Maybe you have a more complex scenario, could you please attach your complete scene here (or send it to me privately)?
Maybe you have a more complex scenario, could you please attach your complete scene here (or send it to me privately)?
- Attachments
-
- AnimationBinding.unitypackage
- (516.04 KiB) Downloaded 361 times
Re: [Unity] Dynamically changing Animation Values with Bindi
Using the Image viewer by itself directly in the Noesis GUIPanel, the Frame property works as expected and shown in your text example. However, as soon as I add the user control to another xaml file, the Frame property stops working.
Example:
Should I submit a bug for this, or am I doing something wrong?
Example:
Code: Select all
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:noesis="clr-namespace:NoesisGUIExtensions" xmlns:five="clr-namespace:FiveGui"
mc:Ignorable="d" x:Name="_PageRoot" d:DesignWidth="1440" d:DesignHeight="810" RenderTransformOrigin="0.5,0.5">
<Viewbox x:Name="_ControllerRoot" Stretch="UniformToFill" HorizontalAlignment="Center" VerticalAlignment="Center">
<Grid x:Name="_ContentRoot" Width="1920" Height="1080">
<five:UIImageViewerx:Name="_ImageViewer"/>
</Grid>
</Viewbox>
</Page>
-
sfernandez
Site Admin
- Posts: 3184
- Joined:
Re: [Unity] Dynamically changing Animation Values with Bindi
Ok, I was able to reproduce the error. We will fix it in a future release.
Meanwhile I found a workaround. Instead of defining the storyboard in the UserControl.Resources, do it in the inner Grid panel:
And set the DataContext in that Grid:
This should work
Meanwhile I found a workaround. Instead of defining the storyboard in the UserControl.Resources, do it in the inner Grid panel:
Code: Select all
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:noesis="clr-namespace:NoesisGUIExtensions" xmlns:five="clr-namespace:FiveGui"
mc:Ignorable="d" x:Class="FiveGui.UIImageViewer" x:Name="_UIImageViewerControl" d:DesignWidth="1920" d:DesignHeight="1080">
<Grid x:Name="LayoutRoot">
<Grid.Resources>
<Storyboard x:Key="NextFrame">
<RectAnimation To="{Binding Frame}" Duration="0:0:1" Storyboard.TargetName="_Image" Storyboard.TargetProperty="Viewbox"/>
</Storyboard>
</Grid.Resources>
<Rectangle>
<Rectangle.Fill>
<ImageBrush x:Name="_Image" ImageSource="../GUIResources/DefaultImage.png" Viewbox="0,0,448,276" ViewboxUnits="Absolute"/>
</Rectangle.Fill>
</Rectangle>
</Grid>
</UserControl>
Code: Select all
public class UIImageViewer : Noesis.UserControl
{
// ...
public void OnPostInit()
{
var layout = FindName<Grid>("LayoutRoot");
layout.SetDataContext(this);
_nextFrame = layout.FindStringResource<Storyboard>("NextFrame");
Frame = new Noesis.Rect(0, 0, 640, 480);
}
// ...
}
Re: [Unity] Dynamically changing Animation Values with Bindi
Found another fun issue related to all this. Apparently once a property is animated, it can no longer be changed directly via Set, in the case of this code, after animating the ImageBox's Viewbox property I can no longer set that property directly using SetViewbox. No error is thrown, no indication as to what is wrong. I've tried calling Stop and Remove on the Storyboard with no luck. Know of any workarounds? So far the only one I've been able to think of is just having a "Reset" storyboard with a 0 duration that resets the values back to what I want them to be.
Also I'm not sure if this is a bug with just ImageBrushes or animating any property in general. Haven't tested all cases yet.
Also I'm not sure if this is a bug with just ImageBrushes or animating any property in general. Haven't tested all cases yet.
-
sfernandez
Site Admin
- Posts: 3184
- Joined:
Re: [Unity] Dynamically changing Animation Values with Bindi
DependencyProperty follows a value precedence scheme to determine how to obtain the effective value of the property. As you can see in the previous link, an animated value has precedence over a local value (when you do a SetValue).
So when a property is animated, and you want to set a new value in code, you need to clear the property first:
I have to check again the behavior of WPF, but I think it should be done the same way.
Anyway I'm seeing we have a different API compared to WPF, we will change it to make code compatible between WPF and Noesis.
So when a property is animated, and you want to set a new value in code, you need to clear the property first:
Code: Select all
rectangle.ClearAnimation(Shape.StrokeThicknessProperty);
rectangle.SetStrokeThickness(2.0f);
Anyway I'm seeing we have a different API compared to WPF, we will change it to make code compatible between WPF and Noesis.
Re: [Unity] Dynamically changing Animation Values with Bindi
I'm trying to set the value after the animation has been complete, not during the animation. I would have thought that once an animation has been complete the precedence would have been cleared automatically.
Thanks for the info, I'll give this a shot.
Edit: Thanks again for the Binding work around. Works great, simplifies my code a lot as I can use the same binding in several areas instead of needing direct references to all of those pieces.
Thanks for the info, I'll give this a shot.
Edit: Thanks again for the Binding work around. Works great, simplifies my code a lot as I can use the same binding in several areas instead of needing direct references to all of those pieces.
-
sfernandez
Site Admin
- Posts: 3184
- Joined:
Re: [Unity] Dynamically changing Animation Values with Bindi
The animation value is just another value source, in fact the animation value is not modifying the local value (that remains the same during all the animation duration). You can specify how your storyboard behaves when the animation completes by setting the FillBehavior property:I'm trying to set the value after the animation has been complete, not during the animation. I would have thought that once an animation has been complete the precedence would have been cleared automatically.
Thanks for the info, I'll give this a shot.
- <Storyboard x:Key="anim"> or <Storyboard x:Key="anim" FillBehavior="HoldEnd"> is the default behavior, that will maintain the last animated value after animation ends.
- <Storyboard x:Key="anim" FillBehavior="Stop"> will remove last animated value after animation ends, so the local (or any other value with less precedence) will be recovered.
You're welcomeEdit: Thanks again for the Binding work around. Works great, simplifies my code a lot as I can use the same binding in several areas instead of needing direct references to all of those pieces.
Who is online
Users browsing this forum: No registered users and 8 guests