Browse Source

Simplify RepeatBehavior into a RepeatCount with Loop option.

pull/1461/head
Jumar Macato 8 years ago
parent
commit
287588c300
  1. 5
      samples/RenderTest/Pages/AnimationsPage.xaml
  2. 2
      samples/RenderTest/Pages/ClippingPage.xaml
  3. 25
      src/Avalonia.Animation/Animation.cs
  4. 25
      src/Avalonia.Animation/AnimatorStateMachine`1.cs
  5. 13
      src/Avalonia.Animation/RepeatBehavior.cs
  6. 203
      src/Avalonia.Animation/RepeatCount.cs
  7. 23
      src/Avalonia.Animation/RepeatCountTypeConverter.cs

5
samples/RenderTest/Pages/AnimationsPage.xaml

@ -43,7 +43,6 @@
<Style Selector="Border.Rect1:pointerover">
<Style.Animations>
<Animation Duration="0:0:2.5"
RepeatBehavior="Repeat"
RepeatCount="4"
FillMode="None"
PlaybackDirection="AlternateReverse"
@ -73,7 +72,9 @@
<Style Selector="Border.Rect3">
<Setter Property="Child" Value="{StaticResource Heart}"/>
<Style.Animations>
<Animation Duration="0:0:0.5" Easing="QuadraticEaseInOut" RepeatBehavior="Loop">
<Animation Duration="0:0:0.5"
Easing="QuadraticEaseInOut"
RepeatCount="Loop">
<KeyFrame Cue="50%">
<TransformSetter Property="ScaleTransform.ScaleX" Value="0.8"/>
<TransformSetter Property="ScaleTransform.ScaleY" Value="0.8"/>

2
samples/RenderTest/Pages/ClippingPage.xaml

@ -8,7 +8,7 @@
</Style>
<Style Selector="Border#clipChild">
<Style.Animations>
<Animation Duration="0:0:2" RepeatBehavior="Loop">
<Animation Duration="0:0:2" RepeatCount="Loop">
<KeyFrame Cue="100%">
<TransformSetter Property="RotateTransform.Angle" Value="360"/>
</KeyFrame>

25
src/Avalonia.Animation/Animation.cs

@ -34,9 +34,9 @@ namespace Avalonia.Animation
public TimeSpan Delay { get; set; }
/// <summary>
/// The repeat behavor for this animation.
/// The repeat count for this animation.
/// </summary>
public RepeatBehavior RepeatBehavior { get; set; }
public RepeatCount RepeatCount { get; set; }
/// <summary>
/// The playback direction for this animation.
@ -46,35 +46,18 @@ namespace Avalonia.Animation
/// <summary>
/// The value fill mode for this animation.
/// </summary>
public FillMode FillMode { get; set; }
/// <summary>
/// Number of repeat iteration for this animation.
/// </summary>
public ulong? RepeatCount { get; set; }
public FillMode FillMode { get; set; }
/// <summary>
/// Easing function to be used.
/// </summary>
public Easing Easing { get; set; } = new LinearEasing();
public Animation()
{
this.CollectionChanged += delegate { _isChildrenChanged = true; };
}
public Animation(IEnumerable<KeyFrame> items) : base(items)
{
this.CollectionChanged += delegate { _isChildrenChanged = true; };
}
public Animation(params KeyFrame[] items) : base(items)
{
this.CollectionChanged += delegate { _isChildrenChanged = true; };
}
private void InterpretKeyframes()
{
var handlerList = new List<(Type, AvaloniaProperty)>();

25
src/Avalonia.Animation/AnimatorStateMachine`1.cs

@ -61,29 +61,16 @@ namespace Avalonia.Animation
_delayTotalFrameCount = (ulong)(animation.Delay.Ticks / Timing.FrameTick.Ticks);
_durationTotalFrameCount = (ulong)(animation.Duration.Ticks / Timing.FrameTick.Ticks);
switch (animation.RepeatBehavior)
switch (animation.RepeatCount.RepeatType)
{
case RepeatBehavior.Loop:
case RepeatType.Loop:
_isLooping = true;
_checkLoopAndRepeat = true;
break;
case RepeatBehavior.Repeat:
if (animation.RepeatCount != null)
{
if (animation.RepeatCount == 0)
{
throw new InvalidOperationException
($"RepeatCount should be greater than zero when RepeatBehavior is set to Repeat.");
}
_isRepeating = true;
_checkLoopAndRepeat = true;
_repeatCount = (ulong)animation.RepeatCount;
}
else
{
throw new InvalidOperationException
($"RepeatCount should be defined when RepeatBehavior is set to Repeat.");
}
case RepeatType.Repeat:
_isRepeating = true;
_checkLoopAndRepeat = true;
_repeatCount = animation.RepeatCount.Value;
break;
}

13
src/Avalonia.Animation/RepeatBehavior.cs

@ -1,13 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Avalonia.Animation
{
public enum RepeatBehavior
{
None,
Repeat,
Loop
}
}

203
src/Avalonia.Animation/RepeatCount.cs

@ -0,0 +1,203 @@
// 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.Utilities;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
namespace Avalonia.Animation
{
/// <summary>
/// Defines the valid modes for a <see cref="RepeatCount"/>.
/// </summary>
public enum RepeatType
{
None,
Repeat,
Loop
}
/// <summary>
/// Determines the repeat behavior of an animation.
/// </summary>
[TypeConverter(typeof(RepeatCountTypeConverter))]
public struct RepeatCount : IEquatable<RepeatCount>
{
private readonly RepeatType _type;
private readonly ulong _value;
/// <summary>
/// Initializes a new instance of the <see cref="RepeatCount"/> struct.
/// </summary>
/// <param name="value">The number of iterations of an animation.</param>
public RepeatCount(ulong value)
: this(value, RepeatType.Repeat)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="RepeatCount"/> struct.
/// </summary>
/// <param name="value">The size of the RepeatCount.</param>
/// <param name="type">The unit of the RepeatCount.</param>
public RepeatCount(ulong value, RepeatType type)
{
if (type < RepeatType.None || type > RepeatType.Loop)
{
throw new ArgumentException("Invalid value", "type");
}
_type = type;
_value = value;
}
/// <summary>
/// Gets an instance of <see cref="RepeatCount"/> that indicates that an animation
/// should repeat forever.
/// </summary>
public static RepeatCount Loop => new RepeatCount(0, RepeatType.Loop);
/// <summary>
/// Gets an instance of <see cref="RepeatCount"/> that indicates that an animation
/// should not repeat.
/// </summary>
public static RepeatCount None => new RepeatCount(0, RepeatType.None);
/// <summary>
/// Gets the unit of the <see cref="RepeatCount"/>.
/// </summary>
public RepeatType RepeatType => _type;
/// <summary>
/// Gets a value that indicates whether the <see cref="RepeatCount"/> is set to loop.
/// </summary>
public bool IsLoop => _type == RepeatType.Loop;
/// <summary>
/// Gets a value that indicates whether the <see cref="RepeatCount"/> is set to not repeat.
/// </summary>
public bool IsNone => _type == RepeatType.None;
/// <summary>
/// Gets the number of repeat iterations.
/// </summary>
public ulong Value => _value;
/// <summary>
/// Compares two RepeatCount structures for equality.
/// </summary>
/// <param name="a">The first RepeatCount.</param>
/// <param name="b">The second RepeatCount.</param>
/// <returns>True if the structures are equal, otherwise false.</returns>
public static bool operator ==(RepeatCount a, RepeatCount b)
{
return (a.IsNone && b.IsNone) && (a.IsLoop && b.IsLoop)
|| (a._value == b._value && a._type == b._type);
}
/// <summary>
/// Compares two RepeatCount structures for inequality.
/// </summary>
/// <param name="rc1">The first RepeatCount.</param>
/// <param name="rc2">The first RepeatCount.</param>
/// <returns>True if the structures are unequal, otherwise false.</returns>
public static bool operator !=(RepeatCount rc1, RepeatCount rc2)
{
return !(rc1 == rc2);
}
/// <summary>
/// Determines whether the <see cref="RepeatCount"/> is equal to the specified object.
/// </summary>
/// <param name="o">The object with which to test equality.</param>
/// <returns>True if the objects are equal, otherwise false.</returns>
public override bool Equals(object o)
{
if (o == null)
{
return false;
}
if (!(o is RepeatCount))
{
return false;
}
return this == (RepeatCount)o;
}
/// <summary>
/// Compares two RepeatCount structures for equality.
/// </summary>
/// <param name="RepeatCount">The structure with which to test equality.</param>
/// <returns>True if the structures are equal, otherwise false.</returns>
public bool Equals(RepeatCount RepeatCount)
{
return this == RepeatCount;
}
/// <summary>
/// Gets a hash code for the RepeatCount.
/// </summary>
/// <returns>The hash code.</returns>
public override int GetHashCode()
{
return _value.GetHashCode() ^ _type.GetHashCode();
}
/// <summary>
/// Gets a string representation of the <see cref="RepeatCount"/>.
/// </summary>
/// <returns>The string representation.</returns>
public override string ToString()
{
if (IsLoop)
{
return "Auto";
}
else if (IsNone)
{
return "None";
}
string s = _value.ToString();
return s;
}
/// <summary>
/// Parses a string to return a <see cref="RepeatCount"/>.
/// </summary>
/// <param name="s">The string.</param>
/// <returns>The <see cref="RepeatCount"/>.</returns>
public static RepeatCount Parse(string s)
{
s = s.ToUpperInvariant().Trim();
if (s == "NONE")
{
return None;
}
else if (s.EndsWith("LOOP"))
{
return Loop;
}
else
{
if(s.StartsWith("-"))
throw new InvalidCastException("RepeatCount iterations can't be a negative number.");
var value = ulong.Parse(s, CultureInfo.InvariantCulture);
if (value == 1)
return None;
return new RepeatCount(value);
}
}
}
}

23
src/Avalonia.Animation/RepeatCountTypeConverter.cs

@ -0,0 +1,23 @@
// 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.Animation.Easings;
using System;
using System.ComponentModel;
using System.Globalization;
namespace Avalonia.Animation
{
public class RepeatCountTypeConverter : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return sourceType == typeof(string);
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
return RepeatCount.Parse((string)value);
}
}
}
Loading…
Cancel
Save