Browse Source

- Initial implementation of ColorTransition.cs

- Added System.Numerics.Vectors in Avalonia.Base.
- Replaced AnimationPlayState in Animatable.cs with a DirectProperty.
pull/1461/head
Jumar Macato 9 years ago
parent
commit
456c7c10c2
  1. 16
      src/Avalonia.Animation/Animatable.cs
  2. 34
      src/Avalonia.Animation/ColorInterpolationMode.cs
  3. 1
      src/Avalonia.Animation/Keyframes/KeyFrames.cs
  4. 2
      src/Avalonia.Animation/Timing.cs
  5. 4
      src/Avalonia.Animation/Transitions/Transition.cs
  6. 81
      src/Avalonia.Visuals/Animation/Transitions/ColorTransition.cs
  7. 27
      src/Avalonia.Visuals/Media/Color.cs

16
src/Avalonia.Animation/Animatable.cs

@ -27,19 +27,25 @@ namespace Avalonia.Animation
/// <summary>
/// Defines the <see cref="AnimationPlayState"/> property.
/// </summary>
public static readonly StyledProperty<AnimationPlayState> AnimationPlayStateProperty =
AvaloniaProperty.Register<Animatable, AnimationPlayState>(nameof(AnimationPlayState));
public static readonly DirectProperty<Animatable, AnimationPlayState> AnimationPlayStateProperty =
AvaloniaProperty.RegisterDirect<Animatable, AnimationPlayState>(
nameof(AnimationPlayState),
o => o.AnimationPlayState,
(o, v) => o.AnimationPlayState = v);
/// <summary>
/// Gets or sets the state of the animation for this
/// control.
/// </summary>
public AnimationPlayState AnimationPlayState
{
get { return GetValue(AnimationPlayStateProperty); }
set { SetValue(AnimationPlayStateProperty, value); }
{
get { return _animationPlayState; }
set { SetAndRaise(AnimationPlayStateProperty, ref _animationPlayState, value); }
}
private AnimationPlayState _animationPlayState;
/// <summary>
/// Defines the <see cref="Transitions"/> property.
/// </summary>

34
src/Avalonia.Animation/ColorInterpolationMode.cs

@ -0,0 +1,34 @@
namespace Avalonia.Animation
{
/// <summary>
/// Defines the intermediate color space
/// in which the color interpolation will be done.
/// </summary>
public enum ColorInterpolationMode
{
/// <summary>
/// Premultiply the alpha component and interpolate from RGB color space.
/// Fast but relatively accurate, perception-wise.
/// </summary>
PremultipliedRGB,
/// <summary>
/// Directly interpolate from RGB color space.
/// Fastest but the least accurate, perception-wise.
/// </summary>
RGB,
/// <summary>
/// Converts RGB into HSV color space and interpolates.
/// Slow but accurate, perception-wise.
/// </summary>
HSV,
/// <summary>
/// Converts RGB into HSV color space and interpolates.
/// Slowest but the most accurate, perception-wise.
/// </summary>
LAB,
}
}

1
src/Avalonia.Animation/Keyframes/KeyFrames.cs

@ -37,6 +37,7 @@ namespace Avalonia.Animation.Keyframes
return obsMatch
.Where(p => p == true)
// Ignore triggers when global timers are paused.
.Where(p=> Timing.GetGlobalPlayState() != AnimationPlayState.Paused)
.Subscribe(_ =>
{

2
src/Avalonia.Animation/Timing.cs

@ -143,7 +143,7 @@ namespace Avalonia.Animation
/// 0 being the start and 1 being the end. The observable is guaranteed to fire 0
/// immediately on subscribe and 1 at the end of the duration.
/// </remarks>
public static IObservable<double> GetTransitionsTimer(Animatable control, TimeSpan duration, TimeSpan delay)
public static IObservable<double> GetTransitionsTimer(Animatable control, TimeSpan duration, TimeSpan delay = default(TimeSpan))
{
var startTime = _transitionsFrameCount;
var _duration = (ulong)(duration.Ticks / Tick.Ticks);

4
src/Avalonia.Animation/Transitions/Transition.cs

@ -11,7 +11,7 @@ namespace Avalonia.Animation.Transitions
/// <summary>
/// Defines how a property should be animated using a transition.
/// </summary>
public abstract class Transition<T> : ITransition
public abstract class Transition<T> : AvaloniaObject, ITransition
{
private AvaloniaProperty _prop;
private Easing _easing;
@ -59,7 +59,7 @@ namespace Avalonia.Animation.Transitions
public abstract IObservable<T> DoTransition(IObservable<double> progress, T oldValue, T newValue);
/// <inheritdocs/>
public IDisposable Apply(Animatable control, object oldValue, object newValue)
public virtual IDisposable Apply(Animatable control, object oldValue, object newValue)
{
var transition = DoTransition(Timing.GetTransitionsTimer(control, Duration, TimeSpan.Zero), (T)oldValue, (T)newValue).Select(p => (object)p);
return control.Bind(Property, transition, Data.BindingPriority.Animation);

81
src/Avalonia.Visuals/Animation/Transitions/ColorTransition.cs

@ -0,0 +1,81 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using Avalonia.Metadata;
using System;
using System.Reactive.Linq;
using Avalonia.Media;
using System.Numerics;
namespace Avalonia.Animation.Transitions
{
/// <summary>
/// Transition class that handles <see cref="AvaloniaProperty"/> with <see cref="SolidColorBrush"/> types.
/// TODO: Must be refactored to handle object creation.
/// </summary>
public class ColorTransition : Transition<SolidColorBrush>
{
/// <summary>
/// Defines the <see cref="AnimationPlayState"/> property.
/// </summary>
public static readonly DirectProperty<ColorTransition, ColorInterpolationMode> InterpolationModeProperty =
AvaloniaProperty.RegisterDirect<ColorTransition, ColorInterpolationMode>(
nameof(InterpolationMode),
o => o.InterpolationMode,
(o, v) => o.InterpolationMode = v);
/// <summary>
/// Gets or sets the state of the animation for this
/// control.
/// </summary>
public ColorInterpolationMode InterpolationMode
{
get { return _interpolationMode; }
set { SetAndRaise(InterpolationModeProperty, ref _interpolationMode, value); }
}
private ColorInterpolationMode _interpolationMode;
public override IObservable<SolidColorBrush> DoTransition(IObservable<double> progress, SolidColorBrush oldValue, SolidColorBrush newValue)
{
var oldColor = new Vector4(oldValue.Color.A, oldValue.Color.R, oldValue.Color.G, oldValue.Color.B);
var newColor = new Vector4(newValue.Color.A, newValue.Color.R, newValue.Color.G, newValue.Color.B);
oldColor = oldColor / 255f;
newColor = newColor / 255f;
var deltaColor = newColor - oldColor;
switch (InterpolationMode)
{
case ColorInterpolationMode.PremultipliedRGB:
var premultOV = new Vector4(1, oldColor.W, oldColor.W, oldColor.W);
var premultNV = new Vector4(1, newColor.W, newColor.W, newColor.W);
oldColor *= premultOV;
newColor *= premultNV;
return progress
.Select(p =>
{
var time = (float)Easing.Ease(p);
var interpolatedColor = (deltaColor * time) + oldColor;
return new SolidColorBrush(Color.FromVector4(interpolatedColor, true));
});
case ColorInterpolationMode.RGB:
return progress
.Select(p =>
{
var time = (float)Easing.Ease(p);
var interpolatedColor = (deltaColor * time) + oldColor;
return new SolidColorBrush(Color.FromVector4(interpolatedColor, true));
});
default:
throw new NotImplementedException($"{Enum.GetName(typeof(ColorInterpolationMode), InterpolationMode)} color interpolation is not supported.");
}
}
}
}

27
src/Avalonia.Visuals/Media/Color.cs

@ -4,6 +4,7 @@
using System;
using System.Globalization;
using System.Linq;
using System.Numerics;
using System.Reflection;
namespace Avalonia.Media
@ -81,6 +82,32 @@ namespace Avalonia.Media
);
}
/// <summary>
/// Creates a <see cref="Color"/> from a <see cref="Vector4"/>.
/// </summary>
/// <param name="value">The <see cref="Vector4"/> value.</param>
/// <param name="normalized">True if the color vector is normalized floats, false if it's bytes (0-255)</param>
/// <returns>The color.</returns>
public static Color FromVector4(Vector4 value, bool normalized)
{
if (normalized)
{
return new Color(
(byte)(value.W * 255),
(byte)(value.X * 255),
(byte)(value.Y * 255),
(byte)(value.Z * 255)
);
} else {
return new Color(
(byte)(value.W),
(byte)(value.X),
(byte)(value.Y),
(byte)(value.Z)
);
}
}
/// <summary>
/// Parses a color string.
/// </summary>

Loading…
Cancel
Save