From dfa75a6d4f5623d82bf3babe485e04a22d3425b9 Mon Sep 17 00:00:00 2001 From: Jumar Macato Date: Fri, 7 May 2021 23:21:00 +0800 Subject: [PATCH 01/12] fix bug on instances where SCB animation applies a localvalue wrongly. --- .../Animators/SolidColorBrushAnimator.cs | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/Avalonia.Visuals/Animation/Animators/SolidColorBrushAnimator.cs b/src/Avalonia.Visuals/Animation/Animators/SolidColorBrushAnimator.cs index a8e618af27..42962e219e 100644 --- a/src/Avalonia.Visuals/Animation/Animators/SolidColorBrushAnimator.cs +++ b/src/Avalonia.Visuals/Animation/Animators/SolidColorBrushAnimator.cs @@ -41,23 +41,23 @@ namespace Avalonia.Animation.Animators SolidColorBrush finalTarget; var targetVal = control.GetValue(Property); - if (targetVal is null) + + switch (targetVal) { - finalTarget = new SolidColorBrush(Colors.Transparent); - control.SetValue(Property, finalTarget); - } - else if (targetVal is ImmutableSolidColorBrush immutableSolidColorBrush) - { - finalTarget = new SolidColorBrush(immutableSolidColorBrush.Color); - control.SetValue(Property, finalTarget); - } - else if (targetVal is ISolidColorBrush) - { - finalTarget = targetVal as SolidColorBrush; - } - else - { - return Disposable.Empty; + case null: + finalTarget = new SolidColorBrush(Colors.Transparent); + break; + case ImmutableSolidColorBrush immutableSolidColorBrush: + finalTarget = new SolidColorBrush(immutableSolidColorBrush.Color); + break; + case SolidColorBrush target: + finalTarget = target; + break; + case ISolidColorBrush target: + finalTarget = target as SolidColorBrush; + break; + default: + return Disposable.Empty; } if (_colorAnimator == null) From f80709287715d96cf9e3c85493d168b228aec05a Mon Sep 17 00:00:00 2001 From: Jumar Macato Date: Sat, 8 May 2021 19:58:57 +0800 Subject: [PATCH 02/12] Heavily simplify SCB animator --- .../Animation/Animators/ColorAnimator.cs | 7 ++- .../Animators/SolidColorBrushAnimator.cs | 60 ++----------------- 2 files changed, 11 insertions(+), 56 deletions(-) diff --git a/src/Avalonia.Visuals/Animation/Animators/ColorAnimator.cs b/src/Avalonia.Visuals/Animation/Animators/ColorAnimator.cs index 6d1f6c39bd..1686cafeb9 100644 --- a/src/Avalonia.Visuals/Animation/Animators/ColorAnimator.cs +++ b/src/Avalonia.Visuals/Animation/Animators/ColorAnimator.cs @@ -31,6 +31,11 @@ namespace Avalonia.Animation.Animators } public override Color Interpolate(double progress, Color oldValue, Color newValue) + { + return InterpolateCore(progress, oldValue, newValue); + } + + internal static Color InterpolateCore(double progress, Color oldValue, Color newValue) { // normalize sRGB values. var oldA = oldValue.A / 255d; @@ -59,7 +64,7 @@ namespace Avalonia.Animation.Animators var b = oldB + progress * (newB - oldB); // convert back to sRGB in the [0..255] range - a = a * 255d; + a *= 255d; r = OECF_sRGB(r) * 255d; g = OECF_sRGB(g) * 255d; b = OECF_sRGB(b) * 255d; diff --git a/src/Avalonia.Visuals/Animation/Animators/SolidColorBrushAnimator.cs b/src/Avalonia.Visuals/Animation/Animators/SolidColorBrushAnimator.cs index 42962e219e..80eb13d2c4 100644 --- a/src/Avalonia.Visuals/Animation/Animators/SolidColorBrushAnimator.cs +++ b/src/Avalonia.Visuals/Animation/Animators/SolidColorBrushAnimator.cs @@ -8,64 +8,14 @@ namespace Avalonia.Animation.Animators /// /// Animator that handles . /// - public class SolidColorBrushAnimator : Animator + public class SolidColorBrushAnimator : Animator { - private ColorAnimator _colorAnimator; - - private 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 match, Action onComplete) + public override IBrush Interpolate(double progress, IBrush oldValue, IBrush newValue) { - // Preprocess keyframe values to Color if the xaml parser converts them to ISCB. - foreach (var keyframe in this) - { - if (keyframe.Value is ISolidColorBrush colorBrush) - { - keyframe.Value = colorBrush.Color; - } - else - { - return Disposable.Empty; - } - } - - SolidColorBrush finalTarget; - var targetVal = control.GetValue(Property); + if (oldValue is not ISolidColorBrush oldValS || newValue is not ISolidColorBrush newValS) + return Brushes.Transparent; - switch (targetVal) - { - case null: - finalTarget = new SolidColorBrush(Colors.Transparent); - break; - case ImmutableSolidColorBrush immutableSolidColorBrush: - finalTarget = new SolidColorBrush(immutableSolidColorBrush.Color); - break; - case SolidColorBrush target: - finalTarget = target; - break; - case ISolidColorBrush target: - finalTarget = target as SolidColorBrush; - break; - default: - return Disposable.Empty; - } - - if (_colorAnimator == null) - InitializeColorAnimator(); - - return _colorAnimator.Apply(animation, finalTarget, clock ?? control.Clock, match, onComplete); + return new ImmutableSolidColorBrush(ColorAnimator.InterpolateCore(progress, oldValS.Color, newValS.Color)); } - - public override SolidColorBrush Interpolate(double p, SolidColorBrush o, SolidColorBrush n) => null; } } From 8df4a59cbe9c133860a2197f4896c8122c9cf638 Mon Sep 17 00:00:00 2001 From: Jumar Macato Date: Sat, 8 May 2021 21:15:01 +0800 Subject: [PATCH 03/12] dont use "not" c# preview feature --- .../Animation/Animators/SolidColorBrushAnimator.cs | 2 +- src/Avalonia.Visuals/ApiCompatBaseline.txt | 4 +++- src/Avalonia.Visuals/Media/SolidColorBrush.cs | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Avalonia.Visuals/Animation/Animators/SolidColorBrushAnimator.cs b/src/Avalonia.Visuals/Animation/Animators/SolidColorBrushAnimator.cs index 80eb13d2c4..3ae9b3be5f 100644 --- a/src/Avalonia.Visuals/Animation/Animators/SolidColorBrushAnimator.cs +++ b/src/Avalonia.Visuals/Animation/Animators/SolidColorBrushAnimator.cs @@ -12,7 +12,7 @@ namespace Avalonia.Animation.Animators { public override IBrush Interpolate(double progress, IBrush oldValue, IBrush newValue) { - if (oldValue is not ISolidColorBrush oldValS || newValue is not ISolidColorBrush newValS) + if (!(oldValue is ISolidColorBrush oldValS) || !(newValue is ISolidColorBrush newValS)) return Brushes.Transparent; return new ImmutableSolidColorBrush(ColorAnimator.InterpolateCore(progress, oldValS.Color, newValS.Color)); diff --git a/src/Avalonia.Visuals/ApiCompatBaseline.txt b/src/Avalonia.Visuals/ApiCompatBaseline.txt index 35ba8f2b19..69a0ea30fa 100644 --- a/src/Avalonia.Visuals/ApiCompatBaseline.txt +++ b/src/Avalonia.Visuals/ApiCompatBaseline.txt @@ -1,4 +1,6 @@ Compat issues with assembly Avalonia.Visuals: +CannotRemoveBaseTypeOrInterface : Type 'Avalonia.Animation.Animators.SolidColorBrushAnimator' does not inherit from base type 'Avalonia.Animation.Animators.Animator' in the implementation but it does in the contract. +MembersMustExist : Member 'public Avalonia.Media.SolidColorBrush Avalonia.Animation.Animators.SolidColorBrushAnimator.Interpolate(System.Double, Avalonia.Media.SolidColorBrush, Avalonia.Media.SolidColorBrush)' does not exist in the implementation but it does exist in the contract. MembersMustExist : Member 'public void Avalonia.Media.TextFormatting.DrawableTextRun.Draw(Avalonia.Media.DrawingContext)' does not exist in the implementation but it does exist in the contract. CannotAddAbstractMembers : Member 'public void Avalonia.Media.TextFormatting.DrawableTextRun.Draw(Avalonia.Media.DrawingContext, Avalonia.Point)' is abstract in the implementation but is missing in the contract. CannotSealType : Type 'Avalonia.Media.TextFormatting.GenericTextParagraphProperties' is actually (has the sealed modifier) sealed in the implementation but not sealed in the contract. @@ -63,4 +65,4 @@ InterfacesShouldHaveSameMembers : Interface member 'public System.Boolean Avalon InterfacesShouldHaveSameMembers : Interface member 'public Avalonia.Platform.IGlyphRunImpl Avalonia.Platform.IPlatformRenderInterface.CreateGlyphRun(Avalonia.Media.GlyphRun)' is present in the implementation but not in the contract. InterfacesShouldHaveSameMembers : Interface member 'public Avalonia.Platform.IGlyphRunImpl Avalonia.Platform.IPlatformRenderInterface.CreateGlyphRun(Avalonia.Media.GlyphRun, System.Double)' is present in the contract but not in the implementation. MembersMustExist : Member 'public Avalonia.Platform.IGlyphRunImpl Avalonia.Platform.IPlatformRenderInterface.CreateGlyphRun(Avalonia.Media.GlyphRun, System.Double)' does not exist in the implementation but it does exist in the contract. -Total Issues: 64 +Total Issues: 66 diff --git a/src/Avalonia.Visuals/Media/SolidColorBrush.cs b/src/Avalonia.Visuals/Media/SolidColorBrush.cs index 8e30880489..f390489ed5 100644 --- a/src/Avalonia.Visuals/Media/SolidColorBrush.cs +++ b/src/Avalonia.Visuals/Media/SolidColorBrush.cs @@ -17,8 +17,8 @@ namespace Avalonia.Media static SolidColorBrush() { - Animation.Animation.RegisterAnimator(prop => typeof(IBrush).IsAssignableFrom(prop.PropertyType)); - AffectsRender(ColorProperty); + Animation.Animation.RegisterAnimator(prop => typeof(ISolidColorBrush).IsAssignableFrom(prop.PropertyType)); + AffectsRender(ColorProperty); } /// From 80c276f31e7e1c0ca5fa5eb60a44396f6f1cfe45 Mon Sep 17 00:00:00 2001 From: Jumar Macato Date: Sun, 9 May 2021 00:15:56 +0800 Subject: [PATCH 04/12] Revamp the brush animators to handle future IBrush types. --- src/Avalonia.Animation/Animation.cs | 11 +++ .../Animation/Animators/BaseBrushAnimator.cs | 68 +++++++++++++++++++ .../Animators/SolidColorBrushAnimator.cs | 12 ++-- src/Avalonia.Visuals/Media/Brush.cs | 2 + src/Avalonia.Visuals/Media/SolidColorBrush.cs | 5 +- 5 files changed, 88 insertions(+), 10 deletions(-) create mode 100644 src/Avalonia.Visuals/Animation/Animators/BaseBrushAnimator.cs diff --git a/src/Avalonia.Animation/Animation.cs b/src/Avalonia.Animation/Animation.cs index 05142532e9..c42153ec4f 100644 --- a/src/Avalonia.Animation/Animation.cs +++ b/src/Avalonia.Animation/Animation.cs @@ -209,6 +209,17 @@ namespace Avalonia.Animation ( prop => typeof(decimal).IsAssignableFrom(prop.PropertyType), typeof(DecimalAnimator) ), }; + /// + /// Registers a that can handle + /// a value type that matches the specified condition. + /// + /// + /// The condition to which the + /// is to be activated and used. + /// + /// + /// The type of the animator to instantiate. + /// public static void RegisterAnimator(Func condition) where TAnimator : IAnimator { diff --git a/src/Avalonia.Visuals/Animation/Animators/BaseBrushAnimator.cs b/src/Avalonia.Visuals/Animation/Animators/BaseBrushAnimator.cs new file mode 100644 index 0000000000..9576803692 --- /dev/null +++ b/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 +{ + /// + /// Animator that handles all animations on properties + /// with as their type and + /// redirect them to the properly registered + /// animators in this class. + /// + public class BaseBrushAnimator : Animator + { + private IAnimator _targetAnimator; + + private static readonly List<(Func Match, Type AnimatorType)> _brushAnimators = new(); + + /// + /// Register an that handles a specific + /// 's descendant value type. + /// + /// + /// The condition to which the + /// is to be activated and used. + /// + /// + /// The type of the animator to instantiate. + /// + public static void RegisterBrushAnimator(Func condition) + where TAnimator : IAnimator + { + _brushAnimators.Insert(0, (condition, typeof(TAnimator))); + } + + /// + public override IDisposable Apply(Animation animation, Animatable control, IClock clock, + IObservable 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; + } + + /// + public override IBrush Interpolate(double progress, IBrush oldValue, IBrush newValue) => null; + } +} diff --git a/src/Avalonia.Visuals/Animation/Animators/SolidColorBrushAnimator.cs b/src/Avalonia.Visuals/Animation/Animators/SolidColorBrushAnimator.cs index 3ae9b3be5f..9077ef2e6c 100644 --- a/src/Avalonia.Visuals/Animation/Animators/SolidColorBrushAnimator.cs +++ b/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 { /// - /// Animator that handles . + /// Animator that handles values. /// public class SolidColorBrushAnimator : Animator { 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)); } } } diff --git a/src/Avalonia.Visuals/Media/Brush.cs b/src/Avalonia.Visuals/Media/Brush.cs index a19d5af8b7..fb03d19a4e 100644 --- a/src/Avalonia.Visuals/Media/Brush.cs +++ b/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(prop => typeof(IBrush).IsAssignableFrom(prop.PropertyType)); AffectsRender(OpacityProperty); } diff --git a/src/Avalonia.Visuals/Media/SolidColorBrush.cs b/src/Avalonia.Visuals/Media/SolidColorBrush.cs index f390489ed5..32663bb8eb 100644 --- a/src/Avalonia.Visuals/Media/SolidColorBrush.cs +++ b/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(prop => typeof(ISolidColorBrush).IsAssignableFrom(prop.PropertyType)); - AffectsRender(ColorProperty); + BaseBrushAnimator.RegisterBrushAnimator(match => typeof(ISolidColorBrush).IsAssignableFrom(match)); + AffectsRender(ColorProperty); } /// From 72ae35c9ea61745e238e7aa770bc59e5d337ea61 Mon Sep 17 00:00:00 2001 From: Jumar Macato Date: Sun, 9 May 2021 00:16:49 +0800 Subject: [PATCH 05/12] return after applying the target animator in BaseBrushAnimator.cs --- src/Avalonia.Visuals/Animation/Animators/BaseBrushAnimator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Avalonia.Visuals/Animation/Animators/BaseBrushAnimator.cs b/src/Avalonia.Visuals/Animation/Animators/BaseBrushAnimator.cs index 9576803692..30162999b5 100644 --- a/src/Avalonia.Visuals/Animation/Animators/BaseBrushAnimator.cs +++ b/src/Avalonia.Visuals/Animation/Animators/BaseBrushAnimator.cs @@ -52,7 +52,7 @@ namespace Avalonia.Animation.Animators _targetAnimator.Property = this.Property; - _targetAnimator.Apply(animation, control, clock, match, onComplete); + return _targetAnimator.Apply(animation, control, clock, match, onComplete); } Logger.TryGet(LogEventLevel.Error, LogArea.Animations)?.Log( From da907379054ab2d6170f8cfcc5905e7026131fe4 Mon Sep 17 00:00:00 2001 From: Jumar Macato Date: Sun, 9 May 2021 00:22:25 +0800 Subject: [PATCH 06/12] revert to non preview feature again --- src/Avalonia.Visuals/Animation/Animators/BaseBrushAnimator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Avalonia.Visuals/Animation/Animators/BaseBrushAnimator.cs b/src/Avalonia.Visuals/Animation/Animators/BaseBrushAnimator.cs index 30162999b5..c9a7ad9cba 100644 --- a/src/Avalonia.Visuals/Animation/Animators/BaseBrushAnimator.cs +++ b/src/Avalonia.Visuals/Animation/Animators/BaseBrushAnimator.cs @@ -17,7 +17,7 @@ namespace Avalonia.Animation.Animators { private IAnimator _targetAnimator; - private static readonly List<(Func Match, Type AnimatorType)> _brushAnimators = new(); + private static readonly List<(Func Match, Type AnimatorType)> _brushAnimators = new List<(Func Match, Type AnimatorType)>(); /// /// Register an that handles a specific From bd9892b9a47a55d613f09006f01d9c29de3de321 Mon Sep 17 00:00:00 2001 From: robloo Date: Sun, 18 Apr 2021 22:12:09 -0400 Subject: [PATCH 07/12] Update windows build instructions --- Documentation/build.md | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/Documentation/build.md b/Documentation/build.md index 5f75290424..a7d68eb599 100644 --- a/Documentation/build.md +++ b/Documentation/build.md @@ -9,10 +9,24 @@ git clone https://github.com/AvaloniaUI/Avalonia.git git submodule update --init ``` +### Install the required version of the .NET Core SDK + +Go to https://dotnet.microsoft.com/download/visual-studio-sdks and install the latest version of the .NET Core SDK compatible with Avalonia UI. Make sure to download the SDK (not just the "runtime") package. The version compatible is indicated within the [global.json](https://github.com/AvaloniaUI/Avalonia/blob/master/global.json) file. Note that Avalonia UI does not always use the latest version and is hardcoded to use the last version known to be compatible (SDK releases may break the builds from time-to-time). + ### Open in Visual Studio -Open the `Avalonia.sln` solution in Visual Studio 2019 or newer. The free Visual Studio Community -edition works fine. Run the `Samples\ControlCatalog.Desktop` project to see the sample application. +Open the `Avalonia.sln` solution in Visual Studio 2019 or newer. The free Visual Studio Community edition works fine. Build and run the `Samples\ControlCatalog.Desktop` or `ControlCatalog.NetCore` project to see the sample application. + +### Troubleshooting + + * **Error CS0006: Avalonia.DesktopRuntime.dll could not be found** + + It is common for the first build to fail with the errors below (also discussed in [#4257](https://github.com/AvaloniaUI/Avalonia/issues/4257)). + ``` + >CSC : error CS0006: Metadata file 'C:\...\Avalonia\src\Avalonia.DesktopRuntime\bin\Debug\netcoreapp2.0\Avalonia.DesktopRuntime.dll' could not be found + >CSC : error CS0006: Metadata file 'C:\...\Avalonia\packages\Avalonia\bin\Debug\netcoreapp2.0\Avalonia.dll' could not be found + ``` + To correct this, right click on the `Avalonia.DesktopRuntime` project then press `Build` to build the project manually. Afterwards the solution should build normally and the ControlCatalog can be run. # Linux/macOS @@ -20,9 +34,9 @@ It's *not* possible to build the *whole* project on Linux/macOS. You can only bu MonoDevelop, Xamarin Studio and Visual Studio for Mac aren't capable of properly opening our solution. You can use Rider (at least 2017.2 EAP) or VSCode instead. They will fail to load most of platform specific projects, but you don't need them to run on .NET Core. -### Install the latest version of .NET Core +### Install the latest version of the .NET Core SDK -Go to https://www.microsoft.com/net/core and follow instructions for your OS. You need SDK (not just "runtime") package. +Go to https://www.microsoft.com/net/core and follow the instructions for your OS. Make sure to download the SDK (not just the "runtime") package. ### Additional requirements for macOS From d084cf8fc7d2bf35fcf387eac3bf4b9f17cdbc9a Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Mon, 10 May 2021 14:49:54 +0100 Subject: [PATCH 08/12] dont break api. --- src/Avalonia.Animation/AnimationInstance`1.cs | 2 +- .../Animators/Animator`1.cs | 2 +- .../Animators/SolidColorBrushAnimator.cs | 21 ++++++++++++------- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/Avalonia.Animation/AnimationInstance`1.cs b/src/Avalonia.Animation/AnimationInstance`1.cs index 6f601a3e13..77547451bb 100644 --- a/src/Avalonia.Animation/AnimationInstance`1.cs +++ b/src/Avalonia.Animation/AnimationInstance`1.cs @@ -12,7 +12,7 @@ namespace Avalonia.Animation /// Handles interpolation and time-related functions /// for keyframe animations. /// - internal class AnimationInstance : SingleSubscriberObservableBase + internal class AnimationInstance : SingleSubscriberObservableBase { private T _lastInterpValue; private T _firstKFValue; diff --git a/src/Avalonia.Animation/Animators/Animator`1.cs b/src/Avalonia.Animation/Animators/Animator`1.cs index 0660440e30..679c879935 100644 --- a/src/Avalonia.Animation/Animators/Animator`1.cs +++ b/src/Avalonia.Animation/Animators/Animator`1.cs @@ -116,7 +116,7 @@ namespace Avalonia.Animation.Animators clock ?? control.Clock ?? Clock.GlobalClock, onComplete, InterpolationHandler); - return control.Bind((AvaloniaProperty)Property, instance, BindingPriority.Animation); + return control.Bind(Property, instance, BindingPriority.Animation); } /// diff --git a/src/Avalonia.Visuals/Animation/Animators/SolidColorBrushAnimator.cs b/src/Avalonia.Visuals/Animation/Animators/SolidColorBrushAnimator.cs index 9077ef2e6c..dd1580e3b3 100644 --- a/src/Avalonia.Visuals/Animation/Animators/SolidColorBrushAnimator.cs +++ b/src/Avalonia.Visuals/Animation/Animators/SolidColorBrushAnimator.cs @@ -1,4 +1,5 @@ -using Avalonia.Media; +using System; +using Avalonia.Media; using Avalonia.Media.Immutable; namespace Avalonia.Animation.Animators @@ -6,14 +7,20 @@ namespace Avalonia.Animation.Animators /// /// Animator that handles values. /// - public class SolidColorBrushAnimator : Animator + public class ISolidColorBrushAnimator : Animator { - public override IBrush Interpolate(double progress, IBrush oldValue, IBrush newValue) + public override ISolidColorBrush Interpolate(double progress, ISolidColorBrush oldValue, ISolidColorBrush newValue) { - if (!(oldValue is ISolidColorBrush oldSCB) || !(newValue is ISolidColorBrush newSCB)) - return Brushes.Transparent; - - return new ImmutableSolidColorBrush(ColorAnimator.InterpolateCore(progress, oldSCB.Color, newSCB.Color)); + return new ImmutableSolidColorBrush(ColorAnimator.InterpolateCore(progress, oldValue.Color, newValue.Color)); + } + } + + [Obsolete] + public class SolidColorBrushAnimator : Animator + { + public override SolidColorBrush Interpolate(double progress, SolidColorBrush oldValue, SolidColorBrush newValue) + { + return new SolidColorBrush(ColorAnimator.InterpolateCore(progress, oldValue.Color, newValue.Color)); } } } From 545253290ed35aa05b858e99a98c466bf5585f92 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Mon, 10 May 2021 14:52:46 +0100 Subject: [PATCH 09/12] register new brush animator. --- src/Avalonia.Visuals/Media/SolidColorBrush.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Avalonia.Visuals/Media/SolidColorBrush.cs b/src/Avalonia.Visuals/Media/SolidColorBrush.cs index 32663bb8eb..fd94cbd214 100644 --- a/src/Avalonia.Visuals/Media/SolidColorBrush.cs +++ b/src/Avalonia.Visuals/Media/SolidColorBrush.cs @@ -16,7 +16,7 @@ namespace Avalonia.Media static SolidColorBrush() { - BaseBrushAnimator.RegisterBrushAnimator(match => typeof(ISolidColorBrush).IsAssignableFrom(match)); + BaseBrushAnimator.RegisterBrushAnimator(match => typeof(ISolidColorBrush).IsAssignableFrom(match)); AffectsRender(ColorProperty); } From c6f248a1e5ade8744440aa4acbc2094afbdad9f7 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Mon, 10 May 2021 14:55:16 +0100 Subject: [PATCH 10/12] fix api compat --- src/Avalonia.Visuals/ApiCompatBaseline.txt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Avalonia.Visuals/ApiCompatBaseline.txt b/src/Avalonia.Visuals/ApiCompatBaseline.txt index 69a0ea30fa..35ba8f2b19 100644 --- a/src/Avalonia.Visuals/ApiCompatBaseline.txt +++ b/src/Avalonia.Visuals/ApiCompatBaseline.txt @@ -1,6 +1,4 @@ Compat issues with assembly Avalonia.Visuals: -CannotRemoveBaseTypeOrInterface : Type 'Avalonia.Animation.Animators.SolidColorBrushAnimator' does not inherit from base type 'Avalonia.Animation.Animators.Animator' in the implementation but it does in the contract. -MembersMustExist : Member 'public Avalonia.Media.SolidColorBrush Avalonia.Animation.Animators.SolidColorBrushAnimator.Interpolate(System.Double, Avalonia.Media.SolidColorBrush, Avalonia.Media.SolidColorBrush)' does not exist in the implementation but it does exist in the contract. MembersMustExist : Member 'public void Avalonia.Media.TextFormatting.DrawableTextRun.Draw(Avalonia.Media.DrawingContext)' does not exist in the implementation but it does exist in the contract. CannotAddAbstractMembers : Member 'public void Avalonia.Media.TextFormatting.DrawableTextRun.Draw(Avalonia.Media.DrawingContext, Avalonia.Point)' is abstract in the implementation but is missing in the contract. CannotSealType : Type 'Avalonia.Media.TextFormatting.GenericTextParagraphProperties' is actually (has the sealed modifier) sealed in the implementation but not sealed in the contract. @@ -65,4 +63,4 @@ InterfacesShouldHaveSameMembers : Interface member 'public System.Boolean Avalon InterfacesShouldHaveSameMembers : Interface member 'public Avalonia.Platform.IGlyphRunImpl Avalonia.Platform.IPlatformRenderInterface.CreateGlyphRun(Avalonia.Media.GlyphRun)' is present in the implementation but not in the contract. InterfacesShouldHaveSameMembers : Interface member 'public Avalonia.Platform.IGlyphRunImpl Avalonia.Platform.IPlatformRenderInterface.CreateGlyphRun(Avalonia.Media.GlyphRun, System.Double)' is present in the contract but not in the implementation. MembersMustExist : Member 'public Avalonia.Platform.IGlyphRunImpl Avalonia.Platform.IPlatformRenderInterface.CreateGlyphRun(Avalonia.Media.GlyphRun, System.Double)' does not exist in the implementation but it does exist in the contract. -Total Issues: 66 +Total Issues: 64 From e63e00f7dde218280785c61689cabb83a27d606a Mon Sep 17 00:00:00 2001 From: Jumar Macato Date: Mon, 10 May 2021 22:06:07 +0800 Subject: [PATCH 11/12] remove linq --- .../Animation/Animators/BaseBrushAnimator.cs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/Avalonia.Visuals/Animation/Animators/BaseBrushAnimator.cs b/src/Avalonia.Visuals/Animation/Animators/BaseBrushAnimator.cs index c9a7ad9cba..508891fd72 100644 --- a/src/Avalonia.Visuals/Animation/Animators/BaseBrushAnimator.cs +++ b/src/Avalonia.Visuals/Animation/Animators/BaseBrushAnimator.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Reactive.Disposables; using Avalonia.Logging; using Avalonia.Media; @@ -17,7 +16,8 @@ namespace Avalonia.Animation.Animators { private IAnimator _targetAnimator; - private static readonly List<(Func Match, Type AnimatorType)> _brushAnimators = new List<(Func Match, Type AnimatorType)>(); + private static readonly List<(Func Match, Type AnimatorType)> _brushAnimators = + new List<(Func Match, Type AnimatorType)>(); /// /// Register an that handles a specific @@ -35,14 +35,15 @@ namespace Avalonia.Animation.Animators { _brushAnimators.Insert(0, (condition, typeof(TAnimator))); } - + /// public override IDisposable Apply(Animation animation, Animatable control, IClock clock, IObservable match, Action onComplete) { - foreach (var valueType in _brushAnimators - .Where(valueType => valueType.Match(this[0].Value.GetType()))) + foreach (var valueType in _brushAnimators) { + if (!valueType.Match(this[0].Value.GetType())) continue; + _targetAnimator = (IAnimator)Activator.CreateInstance(valueType.AnimatorType); foreach (var keyframe in this) From 472e179e41e7f108baa398fec043d516a0e0a743 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Mon, 10 May 2021 16:22:54 +0100 Subject: [PATCH 12/12] no boxing required. --- src/Avalonia.Animation/AnimationInstance`1.cs | 2 +- src/Avalonia.Animation/Animators/Animator`1.cs | 8 +++++++- .../Animation/Animators/SolidColorBrushAnimator.cs | 6 ++++++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.Animation/AnimationInstance`1.cs b/src/Avalonia.Animation/AnimationInstance`1.cs index 77547451bb..6f601a3e13 100644 --- a/src/Avalonia.Animation/AnimationInstance`1.cs +++ b/src/Avalonia.Animation/AnimationInstance`1.cs @@ -12,7 +12,7 @@ namespace Avalonia.Animation /// Handles interpolation and time-related functions /// for keyframe animations. /// - internal class AnimationInstance : SingleSubscriberObservableBase + internal class AnimationInstance : SingleSubscriberObservableBase { private T _lastInterpValue; private T _firstKFValue; diff --git a/src/Avalonia.Animation/Animators/Animator`1.cs b/src/Avalonia.Animation/Animators/Animator`1.cs index 679c879935..d784227620 100644 --- a/src/Avalonia.Animation/Animators/Animator`1.cs +++ b/src/Avalonia.Animation/Animators/Animator`1.cs @@ -104,6 +104,11 @@ namespace Avalonia.Animation.Animators throw new Exception("Index time is out of keyframe time range."); } + public virtual IDisposable BindAnimation(Animatable control, IObservable instance) + { + return control.Bind((AvaloniaProperty)Property, instance, BindingPriority.Animation); + } + /// /// Runs the KeyFrames Animation. /// @@ -116,7 +121,8 @@ namespace Avalonia.Animation.Animators clock ?? control.Clock ?? Clock.GlobalClock, onComplete, InterpolationHandler); - return control.Bind(Property, instance, BindingPriority.Animation); + + return BindAnimation(control, instance); } /// diff --git a/src/Avalonia.Visuals/Animation/Animators/SolidColorBrushAnimator.cs b/src/Avalonia.Visuals/Animation/Animators/SolidColorBrushAnimator.cs index dd1580e3b3..cec96fecf8 100644 --- a/src/Avalonia.Visuals/Animation/Animators/SolidColorBrushAnimator.cs +++ b/src/Avalonia.Visuals/Animation/Animators/SolidColorBrushAnimator.cs @@ -1,4 +1,5 @@ using System; +using Avalonia.Data; using Avalonia.Media; using Avalonia.Media.Immutable; @@ -13,6 +14,11 @@ namespace Avalonia.Animation.Animators { return new ImmutableSolidColorBrush(ColorAnimator.InterpolateCore(progress, oldValue.Color, newValue.Color)); } + + public override IDisposable BindAnimation(Animatable control, IObservable instance) + { + return control.Bind((AvaloniaProperty)Property, instance, BindingPriority.Animation); + } } [Obsolete]