committed by
GitHub
108 changed files with 1651 additions and 640 deletions
@ -1,3 +1,6 @@ |
|||
[submodule "src/Markup/Avalonia.Markup.Xaml/PortableXaml/portable.xaml.github"] |
|||
path = src/Markup/Avalonia.Markup.Xaml/PortableXaml/portable.xaml.github |
|||
url = https://github.com/AvaloniaUI/Portable.Xaml.git |
|||
[submodule "nukebuild/Numerge"] |
|||
path = nukebuild/Numerge |
|||
url = https://github.com/kekekeks/Numerge.git |
|||
|
|||
@ -1,5 +1,5 @@ |
|||
<Project> |
|||
<PropertyGroup> |
|||
<PackageOutputPath Condition="'$(PackageOutputPath)' == ''">$(MSBuildThisFileDirectory)artifacts/nuget</PackageOutputPath> |
|||
<PackageOutputPath Condition="'$(PackageOutputPath)' == ''">$(MSBuildThisFileDirectory)build-intermediate/nuget</PackageOutputPath> |
|||
</PropertyGroup> |
|||
</Project> |
|||
|
|||
@ -1,5 +1,5 @@ |
|||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
|||
<ItemGroup> |
|||
<PackageReference Include="Magick.NET-Q16-AnyCPU" Version="7.0.6.102" /> |
|||
<PackageReference Include="Magick.NET-Q16-AnyCPU" Version="7.9.0.2" /> |
|||
</ItemGroup> |
|||
</Project> |
|||
|
|||
@ -1,6 +1,6 @@ |
|||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
|||
<ItemGroup> |
|||
<PackageReference Include="SkiaSharp" Version="1.60.0" /> |
|||
<PackageReference Condition="'$(IncludeLinuxSkia)' == 'true'" Include="Avalonia.Skia.Linux.Natives" Version="1.60.0.1" /> |
|||
<PackageReference Include="SkiaSharp" Version="1.68.0" /> |
|||
<PackageReference Condition="'$(IncludeLinuxSkia)' == 'true'" Include="SkiaSharp.NativeAssets.Linux" Version="1.68.0" /> |
|||
</ItemGroup> |
|||
</Project> |
|||
|
|||
@ -0,0 +1,8 @@ |
|||
# editorconfig.org |
|||
|
|||
# top-most EditorConfig file |
|||
root = false |
|||
|
|||
# C# files |
|||
[*.cs] |
|||
dotnet_style_require_accessibility_modifiers = never |
|||
@ -0,0 +1,23 @@ |
|||
{ |
|||
"Packages": |
|||
[ |
|||
{ |
|||
"Id": "Avalonia", |
|||
"MergeAll": true, |
|||
"Exclude": ["Avalonia.Remote.Protocol"], |
|||
"IncomingIncludeAssetsOverride": "", |
|||
"Merge": [ |
|||
{ |
|||
"Id": "Avalonia.Build.Tasks", |
|||
"IgnoreMissingFrameworkBinaries": true, |
|||
"DoNotMergeDependencies": true |
|||
}, |
|||
{ |
|||
"Id": "Avalonia.DesktopRuntime", |
|||
"IgnoreMissingFrameworkBinaries": true, |
|||
"IgnoreMissingFrameworkDependencies": true |
|||
} |
|||
] |
|||
} |
|||
] |
|||
} |
|||
@ -0,0 +1,21 @@ |
|||
// 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.
|
|||
|
|||
namespace Avalonia.Animation.Animators |
|||
{ |
|||
/// <summary>
|
|||
/// Animator that handles <see cref="bool"/> properties.
|
|||
/// </summary>
|
|||
public class BoolAnimator : Animator<bool> |
|||
{ |
|||
/// <inheritdocs/>
|
|||
public override bool Interpolate(double progress, bool oldValue, bool newValue) |
|||
{ |
|||
if(progress >= 1d) |
|||
return newValue; |
|||
if(progress >= 0) |
|||
return oldValue; |
|||
return oldValue; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,24 @@ |
|||
// 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 System; |
|||
|
|||
namespace Avalonia.Animation.Animators |
|||
{ |
|||
/// <summary>
|
|||
/// Animator that handles <see cref="byte"/> properties.
|
|||
/// </summary>
|
|||
public class ByteAnimator : Animator<byte> |
|||
{ |
|||
const double maxVal = (double)byte.MaxValue; |
|||
|
|||
/// <inheritdocs/>
|
|||
public override byte Interpolate(double progress, byte oldValue, byte newValue) |
|||
{ |
|||
var normOV = oldValue / maxVal; |
|||
var normNV = newValue / maxVal; |
|||
var deltaV = normNV - normOV; |
|||
return (byte)Math.Round(maxVal * ((deltaV * progress) + normOV)); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,17 @@ |
|||
// 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.
|
|||
|
|||
namespace Avalonia.Animation.Animators |
|||
{ |
|||
/// <summary>
|
|||
/// Animator that handles <see cref="decimal"/> properties.
|
|||
/// </summary>
|
|||
public class DecimalAnimator : Animator<decimal> |
|||
{ |
|||
/// <inheritdocs/>
|
|||
public override decimal Interpolate(double progress, decimal oldValue, decimal newValue) |
|||
{ |
|||
return ((newValue - oldValue) * (decimal)progress) + oldValue; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,17 @@ |
|||
// 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.
|
|||
|
|||
namespace Avalonia.Animation.Animators |
|||
{ |
|||
/// <summary>
|
|||
/// Animator that handles <see cref="double"/> properties.
|
|||
/// </summary>
|
|||
public class DoubleAnimator : Animator<double> |
|||
{ |
|||
/// <inheritdocs/>
|
|||
public override double Interpolate(double progress, double oldValue, double newValue) |
|||
{ |
|||
return ((newValue - oldValue) * progress) + oldValue; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,17 @@ |
|||
// 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.
|
|||
|
|||
namespace Avalonia.Animation.Animators |
|||
{ |
|||
/// <summary>
|
|||
/// Animator that handles <see cref="float"/> properties.
|
|||
/// </summary>
|
|||
public class FloatAnimator : Animator<float> |
|||
{ |
|||
/// <inheritdocs/>
|
|||
public override float Interpolate(double progress, float oldValue, float newValue) |
|||
{ |
|||
return (float)(((newValue - oldValue) * progress) + oldValue); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,24 @@ |
|||
// 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 System; |
|||
|
|||
namespace Avalonia.Animation.Animators |
|||
{ |
|||
/// <summary>
|
|||
/// Animator that handles <see cref="Int16"/> properties.
|
|||
/// </summary>
|
|||
public class Int16Animator : Animator<Int16> |
|||
{ |
|||
const double maxVal = (double)Int16.MaxValue; |
|||
|
|||
/// <inheritdocs/>
|
|||
public override Int16 Interpolate(double progress, Int16 oldValue, Int16 newValue) |
|||
{ |
|||
var normOV = oldValue / maxVal; |
|||
var normNV = newValue / maxVal; |
|||
var deltaV = normNV - normOV; |
|||
return (Int16)Math.Round(maxVal * ((deltaV * progress) + normOV)); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,24 @@ |
|||
// 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 System; |
|||
|
|||
namespace Avalonia.Animation.Animators |
|||
{ |
|||
/// <summary>
|
|||
/// Animator that handles <see cref="Int32"/> properties.
|
|||
/// </summary>
|
|||
public class Int32Animator : Animator<Int32> |
|||
{ |
|||
const double maxVal = (double)Int32.MaxValue; |
|||
|
|||
/// <inheritdocs/>
|
|||
public override Int32 Interpolate(double progress, Int32 oldValue, Int32 newValue) |
|||
{ |
|||
var normOV = oldValue / maxVal; |
|||
var normNV = newValue / maxVal; |
|||
var deltaV = normNV - normOV; |
|||
return (Int32)Math.Round(maxVal * ((deltaV * progress) + normOV)); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,24 @@ |
|||
// 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 System; |
|||
|
|||
namespace Avalonia.Animation.Animators |
|||
{ |
|||
/// <summary>
|
|||
/// Animator that handles <see cref="Int64"/> properties.
|
|||
/// </summary>
|
|||
public class Int64Animator : Animator<Int64> |
|||
{ |
|||
const double maxVal = (double)Int64.MaxValue; |
|||
|
|||
/// <inheritdocs/>
|
|||
public override Int64 Interpolate(double progress, Int64 oldValue, Int64 newValue) |
|||
{ |
|||
var normOV = oldValue / maxVal; |
|||
var normNV = newValue / maxVal; |
|||
var deltaV = normNV - normOV; |
|||
return (Int64)Math.Round(maxVal * ((deltaV * progress) + normOV)); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,24 @@ |
|||
// 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 System; |
|||
|
|||
namespace Avalonia.Animation.Animators |
|||
{ |
|||
/// <summary>
|
|||
/// Animator that handles <see cref="UInt16"/> properties.
|
|||
/// </summary>
|
|||
public class UInt16Animator : Animator<UInt16> |
|||
{ |
|||
const double maxVal = (double)UInt16.MaxValue; |
|||
|
|||
/// <inheritdocs/>
|
|||
public override UInt16 Interpolate(double progress, UInt16 oldValue, UInt16 newValue) |
|||
{ |
|||
var normOV = oldValue / maxVal; |
|||
var normNV = newValue / maxVal; |
|||
var deltaV = normNV - normOV; |
|||
return (UInt16)Math.Round(maxVal * ((deltaV * progress) + normOV)); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,24 @@ |
|||
// 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 System; |
|||
|
|||
namespace Avalonia.Animation.Animators |
|||
{ |
|||
/// <summary>
|
|||
/// Animator that handles <see cref="UInt32"/> properties.
|
|||
/// </summary>
|
|||
public class UInt32Animator : Animator<UInt32> |
|||
{ |
|||
const double maxVal = (double)UInt32.MaxValue; |
|||
|
|||
/// <inheritdocs/>
|
|||
public override UInt32 Interpolate(double progress, UInt32 oldValue, UInt32 newValue) |
|||
{ |
|||
var normOV = oldValue / maxVal; |
|||
var normNV = newValue / maxVal; |
|||
var deltaV = normNV - normOV; |
|||
return (UInt32)Math.Round(maxVal * ((deltaV * progress) + normOV)); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,24 @@ |
|||
// 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 System; |
|||
|
|||
namespace Avalonia.Animation.Animators |
|||
{ |
|||
/// <summary>
|
|||
/// Animator that handles <see cref="UInt64"/> properties.
|
|||
/// </summary>
|
|||
public class UInt64Animator : Animator<UInt64> |
|||
{ |
|||
const double maxVal = (double)UInt64.MaxValue; |
|||
|
|||
/// <inheritdocs/>
|
|||
public override UInt64 Interpolate(double progress, UInt64 oldValue, UInt64 newValue) |
|||
{ |
|||
var normOV = oldValue / maxVal; |
|||
var normNV = newValue / maxVal; |
|||
var deltaV = normNV - normOV; |
|||
return (UInt64)Math.Round(maxVal * ((deltaV * progress) + normOV)); |
|||
} |
|||
} |
|||
} |
|||
@ -1,35 +0,0 @@ |
|||
// 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.
|
|||
|
|||
namespace Avalonia.Animation |
|||
{ |
|||
/// <summary>
|
|||
/// Animator that handles <see cref="double"/> properties.
|
|||
/// </summary>
|
|||
public class DoubleAnimator : Animator<double> |
|||
{ |
|||
|
|||
/// <inheritdocs/>
|
|||
protected override double DoInterpolation(double t, double neutralValue) |
|||
{ |
|||
var pair = GetKFPairAndIntraKFTime(t); |
|||
double y0, y1; |
|||
|
|||
var firstKF = pair.KFPair.FirstKeyFrame; |
|||
var secondKF = pair.KFPair.SecondKeyFrame; |
|||
|
|||
if (firstKF.isNeutral) |
|||
y0 = neutralValue; |
|||
else |
|||
y0 = firstKF.TargetValue; |
|||
|
|||
if (secondKF.isNeutral) |
|||
y1 = neutralValue; |
|||
else |
|||
y1 = secondKF.TargetValue; |
|||
|
|||
// Do linear parametric interpolation
|
|||
return y0 + (pair.IntraKFTime) * (y1 - y0); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,176 @@ |
|||
// 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 System; |
|||
using System.ComponentModel; |
|||
using System.Globalization; |
|||
|
|||
namespace Avalonia.Animation |
|||
{ |
|||
/// <summary>
|
|||
/// Defines the valid modes for a <see cref="IterationCount"/>.
|
|||
/// </summary>
|
|||
public enum IterationType |
|||
{ |
|||
Many, |
|||
Infinite |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Determines the number of iterations of an animation.
|
|||
/// Also defines its repeat behavior.
|
|||
/// </summary>
|
|||
[TypeConverter(typeof(IterationCountTypeConverter))] |
|||
public struct IterationCount : IEquatable<IterationCount> |
|||
{ |
|||
private readonly IterationType _type; |
|||
private readonly ulong _value; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="IterationCount"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="value">The number of iterations of an animation.</param>
|
|||
public IterationCount(ulong value) |
|||
: this(value, IterationType.Many) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="IterationCount"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="value">The size of the IterationCount.</param>
|
|||
/// <param name="type">The unit of the IterationCount.</param>
|
|||
public IterationCount(ulong value, IterationType type) |
|||
{ |
|||
if (type > IterationType.Infinite) |
|||
{ |
|||
throw new ArgumentException("Invalid value", "type"); |
|||
} |
|||
|
|||
_type = type; |
|||
_value = value; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets an instance of <see cref="IterationCount"/> that indicates that an animation
|
|||
/// should repeat forever.
|
|||
/// </summary>
|
|||
public static IterationCount Infinite => new IterationCount(0, IterationType.Infinite); |
|||
|
|||
/// <summary>
|
|||
/// Gets the unit of the <see cref="IterationCount"/>.
|
|||
/// </summary>
|
|||
public IterationType RepeatType => _type; |
|||
|
|||
/// <summary>
|
|||
/// Gets a value that indicates whether the <see cref="IterationCount"/> is set to loop.
|
|||
/// </summary>
|
|||
public bool IsInfinite => _type == IterationType.Infinite; |
|||
|
|||
/// <summary>
|
|||
/// Gets the number of repeat iterations.
|
|||
/// </summary>
|
|||
public ulong Value => _value; |
|||
|
|||
/// <summary>
|
|||
/// Compares two IterationCount structures for equality.
|
|||
/// </summary>
|
|||
/// <param name="a">The first IterationCount.</param>
|
|||
/// <param name="b">The second IterationCount.</param>
|
|||
/// <returns>True if the structures are equal, otherwise false.</returns>
|
|||
public static bool operator ==(IterationCount a, IterationCount b) |
|||
{ |
|||
return (a.IsInfinite && b.IsInfinite) |
|||
|| (a._value == b._value && a._type == b._type); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Compares two IterationCount structures for inequality.
|
|||
/// </summary>
|
|||
/// <param name="rc1">The first IterationCount.</param>
|
|||
/// <param name="rc2">The first IterationCount.</param>
|
|||
/// <returns>True if the structures are unequal, otherwise false.</returns>
|
|||
public static bool operator !=(IterationCount rc1, IterationCount rc2) |
|||
{ |
|||
return !(rc1 == rc2); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Determines whether the <see cref="IterationCount"/> 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 IterationCount)) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
return this == (IterationCount)o; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Compares two IterationCount structures for equality.
|
|||
/// </summary>
|
|||
/// <param name="IterationCount">The structure with which to test equality.</param>
|
|||
/// <returns>True if the structures are equal, otherwise false.</returns>
|
|||
public bool Equals(IterationCount IterationCount) |
|||
{ |
|||
return this == IterationCount; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets a hash code for the IterationCount.
|
|||
/// </summary>
|
|||
/// <returns>The hash code.</returns>
|
|||
public override int GetHashCode() |
|||
{ |
|||
return _value.GetHashCode() ^ _type.GetHashCode(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets a string representation of the <see cref="IterationCount"/>.
|
|||
/// </summary>
|
|||
/// <returns>The string representation.</returns>
|
|||
public override string ToString() |
|||
{ |
|||
if (IsInfinite) |
|||
{ |
|||
return "Infinite"; |
|||
} |
|||
|
|||
string s = _value.ToString(); |
|||
return s; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Parses a string to return a <see cref="IterationCount"/>.
|
|||
/// </summary>
|
|||
/// <param name="s">The string.</param>
|
|||
/// <returns>The <see cref="IterationCount"/>.</returns>
|
|||
public static IterationCount Parse(string s) |
|||
{ |
|||
s = s.ToUpperInvariant().Trim(); |
|||
|
|||
if (s.EndsWith("INFINITE")) |
|||
{ |
|||
return Infinite; |
|||
} |
|||
else |
|||
{ |
|||
if (s.StartsWith("-")) |
|||
throw new InvalidCastException("IterationCount can't be a negative number."); |
|||
|
|||
var value = ulong.Parse(s, CultureInfo.InvariantCulture); |
|||
|
|||
return new IterationCount(value); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -1,33 +0,0 @@ |
|||
// 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.
|
|||
|
|||
namespace Avalonia.Animation |
|||
{ |
|||
/// <summary>
|
|||
/// Represents a pair of keyframe, usually the
|
|||
/// Start and End keyframes of a <see cref="Animator{T}"/> object.
|
|||
/// </summary>
|
|||
public struct KeyFramePair<T> |
|||
{ |
|||
/// <summary>
|
|||
/// Initializes this <see cref="KeyFramePair{T}"/>
|
|||
/// </summary>
|
|||
/// <param name="FirstKeyFrame"></param>
|
|||
/// <param name="LastKeyFrame"></param>
|
|||
public KeyFramePair((T TargetValue, bool isNeutral) FirstKeyFrame, (T TargetValue, bool isNeutral) LastKeyFrame) : this() |
|||
{ |
|||
this.FirstKeyFrame = FirstKeyFrame; |
|||
this.SecondKeyFrame = LastKeyFrame; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// First <see cref="KeyFrame"/> object.
|
|||
/// </summary>
|
|||
public (T TargetValue, bool isNeutral) FirstKeyFrame { get; } |
|||
|
|||
/// <summary>
|
|||
/// Second <see cref="KeyFrame"/> object.
|
|||
/// </summary>
|
|||
public (T TargetValue, bool isNeutral) SecondKeyFrame { get; } |
|||
} |
|||
} |
|||
@ -0,0 +1,33 @@ |
|||
// 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 System; |
|||
using System.Collections.Generic; |
|||
using Avalonia.Collections; |
|||
|
|||
namespace Avalonia.Animation |
|||
{ |
|||
/// <summary>
|
|||
/// A collection of <see cref="KeyFrame"/>s.
|
|||
/// </summary>
|
|||
public class KeyFrames : AvaloniaList<KeyFrame> |
|||
{ |
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="KeyFrames"/> class.
|
|||
/// </summary>
|
|||
public KeyFrames() |
|||
{ |
|||
ResetBehavior = ResetBehavior.Remove; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="KeyFrames"/> class.
|
|||
/// </summary>
|
|||
/// <param name="items">The initial items in the collection.</param>
|
|||
public KeyFrames(IEnumerable<KeyFrame> items) |
|||
: base(items) |
|||
{ |
|||
ResetBehavior = ResetBehavior.Remove; |
|||
} |
|||
} |
|||
} |
|||
@ -1,199 +0,0 @@ |
|||
// 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 System; |
|||
using System.ComponentModel; |
|||
using System.Globalization; |
|||
|
|||
namespace Avalonia.Animation |
|||
{ |
|||
/// <summary>
|
|||
/// Defines the valid modes for a <see cref="RepeatCount"/>.
|
|||
/// </summary>
|
|||
public enum RepeatType |
|||
{ |
|||
None, |
|||
Repeat, |
|||
Loop |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Determines the number of iterations of an animation.
|
|||
/// Also defines its repeat behavior.
|
|||
/// </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 can't be a negative number."); |
|||
|
|||
var value = ulong.Parse(s, CultureInfo.InvariantCulture); |
|||
|
|||
if (value == 1) |
|||
return None; |
|||
|
|||
return new RepeatCount(value); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,70 @@ |
|||
// Original color interpolation code was written by Romain Guy and Francois Blavoet
|
|||
// and adopted from LottieSharp Project (https://github.com/ascora/LottieSharp).
|
|||
|
|||
using System; |
|||
using System.Reactive.Disposables; |
|||
using Avalonia.Logging; |
|||
using Avalonia.Media; |
|||
|
|||
namespace Avalonia.Animation.Animators |
|||
{ |
|||
/// <summary>
|
|||
/// Animator that interpolates <see cref="Color"/> through
|
|||
/// gamma sRGB color space for better visual result.
|
|||
/// </summary>
|
|||
public class ColorAnimator : Animator<Color> |
|||
{ |
|||
// Opto-electronic conversion function for the sRGB color space
|
|||
// Takes a gamma-encoded sRGB value and converts it to a linear sRGB value
|
|||
private static double OECF_sRGB(double linear) |
|||
{ |
|||
// IEC 61966-2-1:1999
|
|||
return linear <= 0.0031308d ? linear * 12.92d : (double)(Math.Pow(linear, 1.0d / 2.4d) * 1.055d - 0.055d); |
|||
} |
|||
|
|||
// Electro-optical conversion function for the sRGB color space
|
|||
// Takes a linear sRGB value and converts it to a gamma-encoded sRGB value
|
|||
private static double EOCF_sRGB(double srgb) |
|||
{ |
|||
// IEC 61966-2-1:1999
|
|||
return srgb <= 0.04045d ? srgb / 12.92d : (double)Math.Pow((srgb + 0.055d) / 1.055d, 2.4d); |
|||
} |
|||
|
|||
public override Color Interpolate(double progress, Color oldValue, Color newValue) |
|||
{ |
|||
// normalize sRGB values.
|
|||
var oldA = oldValue.A / 255d; |
|||
var oldR = oldValue.R / 255d; |
|||
var oldG = oldValue.G / 255d; |
|||
var oldB = oldValue.B / 255d; |
|||
|
|||
var newA = newValue.A / 255d; |
|||
var newR = newValue.R / 255d; |
|||
var newG = newValue.G / 255d; |
|||
var newB = newValue.B / 255d; |
|||
|
|||
// convert from sRGB to linear
|
|||
oldR = EOCF_sRGB(oldR); |
|||
oldG = EOCF_sRGB(oldG); |
|||
oldB = EOCF_sRGB(oldB); |
|||
|
|||
newR = EOCF_sRGB(newR); |
|||
newG = EOCF_sRGB(newG); |
|||
newB = EOCF_sRGB(newB); |
|||
|
|||
// compute the interpolated color in linear space
|
|||
var a = oldA + progress * (newA - oldA); |
|||
var r = oldR + progress * (newR - oldR); |
|||
var g = oldG + progress * (newG - oldG); |
|||
var b = oldB + progress * (newB - oldB); |
|||
|
|||
// convert back to sRGB in the [0..255] range
|
|||
a = a * 255d; |
|||
r = OECF_sRGB(r) * 255d; |
|||
g = OECF_sRGB(g) * 255d; |
|||
b = OECF_sRGB(b) * 255d; |
|||
|
|||
return new Color((byte)Math.Round(a), (byte)Math.Round(r), (byte)Math.Round(g), (byte)Math.Round(b)); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,27 @@ |
|||
using System; |
|||
using Avalonia.Logging; |
|||
using Avalonia.Media; |
|||
|
|||
namespace Avalonia.Animation.Animators |
|||
{ |
|||
/// <summary>
|
|||
/// Animator that handles <see cref="CornerRadius"/> properties.
|
|||
/// </summary>
|
|||
public class CornerRadiusAnimator : Animator<CornerRadius> |
|||
{ |
|||
public override CornerRadius Interpolate(double progress, CornerRadius oldValue, CornerRadius newValue) |
|||
{ |
|||
var deltaTL = newValue.TopLeft - oldValue.TopLeft; |
|||
var deltaTR = newValue.TopRight - oldValue.TopRight; |
|||
var deltaBR = newValue.BottomRight - oldValue.BottomRight; |
|||
var deltaBL = newValue.BottomLeft - oldValue.BottomLeft; |
|||
|
|||
var nTL = progress * deltaTL + oldValue.TopLeft; |
|||
var nTR = progress * deltaTR + oldValue.TopRight; |
|||
var nBR = progress * deltaBR + oldValue.BottomRight; |
|||
var nBL = progress * deltaBL + oldValue.BottomLeft; |
|||
|
|||
return new CornerRadius(nTL, nTR, nBR, nBL); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,17 @@ |
|||
using System; |
|||
using Avalonia.Logging; |
|||
using Avalonia.Media; |
|||
|
|||
namespace Avalonia.Animation.Animators |
|||
{ |
|||
/// <summary>
|
|||
/// Animator that handles <see cref="Point"/> properties.
|
|||
/// </summary>
|
|||
public class PointAnimator : Animator<Point> |
|||
{ |
|||
public override Point Interpolate(double progress, Point oldValue, Point newValue) |
|||
{ |
|||
return ((newValue - oldValue) * progress) + oldValue; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,23 @@ |
|||
using System; |
|||
using Avalonia.Logging; |
|||
using Avalonia.Media; |
|||
|
|||
namespace Avalonia.Animation.Animators |
|||
{ |
|||
/// <summary>
|
|||
/// Animator that handles <see cref="Rect"/> properties.
|
|||
/// </summary>
|
|||
public class RectAnimator : Animator<Rect> |
|||
{ |
|||
public override Rect Interpolate(double progress, Rect oldValue, Rect newValue) |
|||
{ |
|||
var deltaPos = newValue.Position - oldValue.Position; |
|||
var deltaSize = newValue.Size - oldValue.Size; |
|||
|
|||
var newPos = (deltaPos * progress) + oldValue.Position; |
|||
var newSize = (deltaSize * progress) + oldValue.Size; |
|||
|
|||
return new Rect(newPos, newSize); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,17 @@ |
|||
using System; |
|||
using Avalonia.Logging; |
|||
using Avalonia.Media; |
|||
|
|||
namespace Avalonia.Animation.Animators |
|||
{ |
|||
/// <summary>
|
|||
/// Animator that handles <see cref="Size"/> properties.
|
|||
/// </summary>
|
|||
public class SizeAnimator : Animator<Size> |
|||
{ |
|||
public override Size Interpolate(double progress, Size oldValue, Size newValue) |
|||
{ |
|||
return ((newValue - oldValue) * progress) + oldValue; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,74 @@ |
|||
using System; |
|||
using System.Reactive.Disposables; |
|||
using Avalonia.Logging; |
|||
using Avalonia.Media; |
|||
using Avalonia.Media.Immutable; |
|||
|
|||
namespace Avalonia.Animation.Animators |
|||
{ |
|||
/// <summary>
|
|||
/// Animator that handles <see cref="SolidColorBrush"/>.
|
|||
/// </summary>
|
|||
public class SolidColorBrushAnimator : Animator<SolidColorBrush> |
|||
{ |
|||
ColorAnimator _colorAnimator; |
|||
|
|||
void InitializeColorAnimator() |
|||
{ |
|||
_colorAnimator = new ColorAnimator(); |
|||
|
|||
foreach (AnimatorKeyFrame keyframe in this) |
|||
{ |
|||
_colorAnimator.Add(keyframe); |
|||
} |
|||
|
|||
_colorAnimator.Property = SolidColorBrush.ColorProperty; |
|||
} |
|||
|
|||
public override IDisposable Apply(Animation animation, Animatable control, IClock clock, IObservable<bool> match, Action onComplete) |
|||
{ |
|||
foreach (var keyframe in this) |
|||
{ |
|||
if (keyframe.Value as ISolidColorBrush == null) |
|||
return Disposable.Empty; |
|||
|
|||
// Preprocess keyframe values to Color if the xaml parser converts them to ISCB.
|
|||
if (keyframe.Value.GetType() == typeof(ImmutableSolidColorBrush)) |
|||
{ |
|||
keyframe.Value = ((ImmutableSolidColorBrush)keyframe.Value).Color; |
|||
} |
|||
} |
|||
|
|||
// Add SCB if the target prop is empty.
|
|||
if (control.GetValue(Property) == null) |
|||
control.SetValue(Property, new SolidColorBrush(Colors.Transparent)); |
|||
|
|||
var targetVal = control.GetValue(Property); |
|||
|
|||
// Continue if target prop is not empty & is a SolidColorBrush derivative.
|
|||
if (typeof(ISolidColorBrush).IsAssignableFrom(targetVal.GetType())) |
|||
{ |
|||
if (_colorAnimator == null) |
|||
InitializeColorAnimator(); |
|||
|
|||
SolidColorBrush finalTarget; |
|||
|
|||
// If it's ISCB, change it back to SCB.
|
|||
if (targetVal.GetType() == typeof(ImmutableSolidColorBrush)) |
|||
{ |
|||
var col = (ImmutableSolidColorBrush)targetVal; |
|||
targetVal = new SolidColorBrush(col.Color); |
|||
control.SetValue(Property, targetVal); |
|||
} |
|||
|
|||
finalTarget = targetVal as SolidColorBrush; |
|||
|
|||
return _colorAnimator.Apply(animation, finalTarget, clock ?? control.Clock, match, onComplete); |
|||
} |
|||
|
|||
return Disposable.Empty; |
|||
} |
|||
|
|||
public override SolidColorBrush Interpolate(double p, SolidColorBrush o, SolidColorBrush n) => null; |
|||
} |
|||
} |
|||
@ -0,0 +1,17 @@ |
|||
using System; |
|||
using Avalonia.Logging; |
|||
using Avalonia.Media; |
|||
|
|||
namespace Avalonia.Animation.Animators |
|||
{ |
|||
/// <summary>
|
|||
/// Animator that handles <see cref="Thickness"/> properties.
|
|||
/// </summary>
|
|||
public class ThicknessAnimator : Animator<Thickness> |
|||
{ |
|||
public override Thickness Interpolate(double progress, Thickness oldValue, Thickness newValue) |
|||
{ |
|||
return ((newValue - oldValue) * progress) + oldValue; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,17 @@ |
|||
using System; |
|||
using Avalonia.Logging; |
|||
using Avalonia.Media; |
|||
|
|||
namespace Avalonia.Animation.Animators |
|||
{ |
|||
/// <summary>
|
|||
/// Animator that handles <see cref="Vector"/> properties.
|
|||
/// </summary>
|
|||
public class VectorAnimator : Animator<Vector> |
|||
{ |
|||
public override Vector Interpolate(double progress, Vector oldValue, Vector newValue) |
|||
{ |
|||
return ((newValue - oldValue) * progress) + oldValue; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,36 @@ |
|||
// 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 System; |
|||
using System.Reactive.Linq; |
|||
|
|||
namespace Avalonia.Animation |
|||
{ |
|||
/// <summary>
|
|||
/// Transition class that handles <see cref="AvaloniaProperty"/> with <see cref="CornerRadius"/> type.
|
|||
/// </summary>
|
|||
public class CornerRadiusTransition : Transition<CornerRadius> |
|||
{ |
|||
/// <inheritdocs/>
|
|||
public override IObservable<CornerRadius> DoTransition(IObservable<double> progress, CornerRadius oldValue, CornerRadius newValue) |
|||
{ |
|||
return progress |
|||
.Select(p => |
|||
{ |
|||
var f = Easing.Ease(p); |
|||
|
|||
var deltaTL = newValue.TopLeft - oldValue.TopLeft; |
|||
var deltaTR = newValue.TopRight - oldValue.TopRight; |
|||
var deltaBR = newValue.BottomRight - oldValue.BottomRight; |
|||
var deltaBL = newValue.BottomLeft - oldValue.BottomLeft; |
|||
|
|||
var nTL = f * deltaTL + oldValue.TopLeft; |
|||
var nTR = f * deltaTR + oldValue.TopRight; |
|||
var nBR = f * deltaBR + oldValue.BottomRight; |
|||
var nBL = f * deltaBL + oldValue.BottomLeft; |
|||
|
|||
return new CornerRadius(nTL, nTR, nBR, nBL); |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,25 @@ |
|||
// 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 System; |
|||
using System.Reactive.Linq; |
|||
|
|||
namespace Avalonia.Animation |
|||
{ |
|||
/// <summary>
|
|||
/// Transition class that handles <see cref="AvaloniaProperty"/> with <see cref="Size"/> type.
|
|||
/// </summary>
|
|||
public class SizeTransition : Transition<Size> |
|||
{ |
|||
/// <inheritdocs/>
|
|||
public override IObservable<Size> DoTransition(IObservable<double> progress, Size oldValue, Size newValue) |
|||
{ |
|||
return progress |
|||
.Select(p => |
|||
{ |
|||
var f = Easing.Ease(p); |
|||
return ((newValue - oldValue) * f) + oldValue; |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,25 @@ |
|||
// 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 System; |
|||
using System.Reactive.Linq; |
|||
|
|||
namespace Avalonia.Animation |
|||
{ |
|||
/// <summary>
|
|||
/// Transition class that handles <see cref="AvaloniaProperty"/> with <see cref="Vector"/> type.
|
|||
/// </summary>
|
|||
public class VectorTransition : Transition<Vector> |
|||
{ |
|||
/// <inheritdocs/>
|
|||
public override IObservable<Vector> DoTransition(IObservable<double> progress, Vector oldValue, Vector newValue) |
|||
{ |
|||
return progress |
|||
.Select(p => |
|||
{ |
|||
var f = Easing.Ease(p); |
|||
return ((newValue - oldValue) * f) + oldValue; |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue