Browse Source

Revamp the brush animators to handle future IBrush types.

pull/5886/head
Jumar Macato 5 years ago
parent
commit
80c276f31e
No known key found for this signature in database GPG Key ID: B19884DAC3A5BF3F
  1. 11
      src/Avalonia.Animation/Animation.cs
  2. 68
      src/Avalonia.Visuals/Animation/Animators/BaseBrushAnimator.cs
  3. 12
      src/Avalonia.Visuals/Animation/Animators/SolidColorBrushAnimator.cs
  4. 2
      src/Avalonia.Visuals/Media/Brush.cs
  5. 5
      src/Avalonia.Visuals/Media/SolidColorBrush.cs

11
src/Avalonia.Animation/Animation.cs

@ -209,6 +209,17 @@ namespace Avalonia.Animation
( prop => typeof(decimal).IsAssignableFrom(prop.PropertyType), typeof(DecimalAnimator) ),
};
/// <summary>
/// Registers a <see cref="Animator{T}"/> that can handle
/// a value type that matches the specified condition.
/// </summary>
/// <param name="condition">
/// The condition to which the <see cref="Animator{T}"/>
/// is to be activated and used.
/// </param>
/// <typeparam name="TAnimator">
/// The type of the animator to instantiate.
/// </typeparam>
public static void RegisterAnimator<TAnimator>(Func<AvaloniaProperty, bool> condition)
where TAnimator : IAnimator
{

68
src/Avalonia.Visuals/Animation/Animators/BaseBrushAnimator.cs

@ -0,0 +1,68 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Disposables;
using Avalonia.Logging;
using Avalonia.Media;
namespace Avalonia.Animation.Animators
{
/// <summary>
/// Animator that handles all animations on properties
/// with <see cref="IBrush"/> as their type and
/// redirect them to the properly registered
/// animators in this class.
/// </summary>
public class BaseBrushAnimator : Animator<IBrush>
{
private IAnimator _targetAnimator;
private static readonly List<(Func<Type, bool> Match, Type AnimatorType)> _brushAnimators = new();
/// <summary>
/// Register an <see cref="Animator{T}"/> that handles a specific
/// <see cref="IBrush"/>'s descendant value type.
/// </summary>
/// <param name="condition">
/// The condition to which the <see cref="Animator{T}"/>
/// is to be activated and used.
/// </param>
/// <typeparam name="TAnimator">
/// The type of the animator to instantiate.
/// </typeparam>
public static void RegisterBrushAnimator<TAnimator>(Func<Type, bool> condition)
where TAnimator : IAnimator
{
_brushAnimators.Insert(0, (condition, typeof(TAnimator)));
}
/// <inheritdoc/>
public override IDisposable Apply(Animation animation, Animatable control, IClock clock,
IObservable<bool> match, Action onComplete)
{
foreach (var valueType in _brushAnimators
.Where(valueType => valueType.Match(this[0].Value.GetType())))
{
_targetAnimator = (IAnimator)Activator.CreateInstance(valueType.AnimatorType);
foreach (var keyframe in this)
{
_targetAnimator.Add(keyframe);
}
_targetAnimator.Property = this.Property;
_targetAnimator.Apply(animation, control, clock, match, onComplete);
}
Logger.TryGet(LogEventLevel.Error, LogArea.Animations)?.Log(
this,
"The animation's keyframe values didn't match any brush animators registered in BaseBrushAnimator.");
return Disposable.Empty;
}
/// <inheritdoc/>
public override IBrush Interpolate(double progress, IBrush oldValue, IBrush newValue) => null;
}
}

12
src/Avalonia.Visuals/Animation/Animators/SolidColorBrushAnimator.cs

@ -1,21 +1,19 @@
using System;
using System.Reactive.Disposables;
using Avalonia.Media;
using Avalonia.Media;
using Avalonia.Media.Immutable;
namespace Avalonia.Animation.Animators
{
/// <summary>
/// Animator that handles <see cref="SolidColorBrush"/>.
/// Animator that handles <see cref="SolidColorBrush"/> values.
/// </summary>
public class SolidColorBrushAnimator : Animator<IBrush>
{
public override IBrush Interpolate(double progress, IBrush oldValue, IBrush newValue)
{
if (!(oldValue is ISolidColorBrush oldValS) || !(newValue is ISolidColorBrush newValS))
if (!(oldValue is ISolidColorBrush oldSCB) || !(newValue is ISolidColorBrush newSCB))
return Brushes.Transparent;
return new ImmutableSolidColorBrush(ColorAnimator.InterpolateCore(progress, oldValS.Color, newValS.Color));
return new ImmutableSolidColorBrush(ColorAnimator.InterpolateCore(progress, oldSCB.Color, newSCB.Color));
}
}
}

2
src/Avalonia.Visuals/Media/Brush.cs

@ -1,6 +1,7 @@
using System;
using System.ComponentModel;
using Avalonia.Animation;
using Avalonia.Animation.Animators;
namespace Avalonia.Media
{
@ -21,6 +22,7 @@ namespace Avalonia.Media
static Brush()
{
Animation.Animation.RegisterAnimator<BaseBrushAnimator>(prop => typeof(IBrush).IsAssignableFrom(prop.PropertyType));
AffectsRender<Brush>(OpacityProperty);
}

5
src/Avalonia.Visuals/Media/SolidColorBrush.cs

@ -1,4 +1,3 @@
using Avalonia.Animation;
using Avalonia.Animation.Animators;
using Avalonia.Media.Immutable;
@ -17,8 +16,8 @@ namespace Avalonia.Media
static SolidColorBrush()
{
Animation.Animation.RegisterAnimator<SolidColorBrushAnimator>(prop => typeof(ISolidColorBrush).IsAssignableFrom(prop.PropertyType));
AffectsRender<SolidColorBrush>(ColorProperty);
BaseBrushAnimator.RegisterBrushAnimator<SolidColorBrushAnimator>(match => typeof(ISolidColorBrush).IsAssignableFrom(match));
AffectsRender<SolidColorBrush>(ColorProperty);
}
/// <summary>

Loading…
Cancel
Save