Browse Source

Fix fetching neutral value in animations.

Animators fetched the neutral value when the animation is instantiated but did not update the neutral value if it's updated after that.

#6063 was caused by the fact that the neutral value does not take effect until the batch update due to styling has finished on the control, which is _after_ the animation has been instantiated.

Listen for changes on the property and if the change is not an animated value change, update the neutral value.

This isn't perfect because it won't react to changes to the neutral value while the animation is actually running and producing values because `PropertyChanged` events don't get fired for non-active values: for that we'd need to hook into `OnPropertyChangedCore`. But this at least fixes the simple case of the initial neutral value.
Steven Kirk 4 years ago
parent
commit
d6d87b1a32
1 changed files with 20 additions and 1 deletions
  1. 20 1
      src/Avalonia.Animation/AnimationInstance`1.cs

+ 20 - 1
src/Avalonia.Animation/AnimationInstance`1.cs

@@ -5,6 +5,7 @@ using Avalonia.Animation.Animators;
 using Avalonia.Animation.Utils;
 using Avalonia.Data;
 using Avalonia.Reactive;
+using JetBrains.Annotations;
 
 namespace Avalonia.Animation
 {
@@ -45,8 +46,9 @@ namespace Avalonia.Animation
             _onCompleteAction = OnComplete;
             _interpolator = Interpolator;
             _baseClock = baseClock;
-            _neutralValue = (T)_targetControl.GetValue(_animator.Property);
+            control.PropertyChanged += ControlPropertyChanged;
 
+            UpdateNeutralValue();
             FetchProperties();
         }
 
@@ -216,5 +218,22 @@ namespace Avalonia.Animation
                 }
             }
         }
+
+        private void UpdateNeutralValue()
+        {
+            var property = _animator.Property;
+            var baseValue = _targetControl.GetBaseValue(property, BindingPriority.LocalValue);
+
+            _neutralValue = baseValue != AvaloniaProperty.UnsetValue ?
+                (T)baseValue : (T)_targetControl.GetValue(property);
+        }
+
+        private void ControlPropertyChanged(object sender, AvaloniaPropertyChangedEventArgs e)
+        {
+            if (e.Property == _animator.Property && e.Priority > BindingPriority.Animation)
+            {
+                UpdateNeutralValue();
+            }
+        }
     }
 }