Browse Source

Merge branch 'master' into CleanFluent

pull/5863/head
Dan Walmsley 5 years ago
committed by GitHub
parent
commit
4076ecb0dc
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 22
      Documentation/build.md
  2. 11
      src/Avalonia.Animation/Animation.cs
  3. 8
      src/Avalonia.Animation/Animators/Animator`1.cs
  4. 69
      src/Avalonia.Visuals/Animation/Animators/BaseBrushAnimator.cs
  5. 7
      src/Avalonia.Visuals/Animation/Animators/ColorAnimator.cs
  6. 71
      src/Avalonia.Visuals/Animation/Animators/SolidColorBrushAnimator.cs
  7. 2
      src/Avalonia.Visuals/Media/Brush.cs
  8. 3
      src/Avalonia.Visuals/Media/SolidColorBrush.cs

22
Documentation/build.md

@ -9,10 +9,24 @@ git clone https://github.com/AvaloniaUI/Avalonia.git
git submodule update --init 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 in Visual Studio
Open the `Avalonia.sln` solution in Visual Studio 2019 or newer. The free Visual Studio Community 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.
edition works fine. Run the `Samples\ControlCatalog.Desktop` 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 # 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. 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 ### Additional requirements for macOS

11
src/Avalonia.Animation/Animation.cs

@ -209,6 +209,17 @@ namespace Avalonia.Animation
( prop => typeof(decimal).IsAssignableFrom(prop.PropertyType), typeof(DecimalAnimator) ), ( 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) public static void RegisterAnimator<TAnimator>(Func<AvaloniaProperty, bool> condition)
where TAnimator : IAnimator where TAnimator : IAnimator
{ {

8
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."); throw new Exception("Index time is out of keyframe time range.");
} }
public virtual IDisposable BindAnimation(Animatable control, IObservable<T> instance)
{
return control.Bind((AvaloniaProperty<T>)Property, instance, BindingPriority.Animation);
}
/// <summary> /// <summary>
/// Runs the KeyFrames Animation. /// Runs the KeyFrames Animation.
/// </summary> /// </summary>
@ -116,7 +121,8 @@ namespace Avalonia.Animation.Animators
clock ?? control.Clock ?? Clock.GlobalClock, clock ?? control.Clock ?? Clock.GlobalClock,
onComplete, onComplete,
InterpolationHandler); InterpolationHandler);
return control.Bind<T>((AvaloniaProperty<T>)Property, instance, BindingPriority.Animation);
return BindAnimation(control, instance);
} }
/// <summary> /// <summary>

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

@ -0,0 +1,69 @@
using System;
using System.Collections.Generic;
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 List<(Func<Type, bool> Match, Type AnimatorType)>();
/// <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)
{
if (!valueType.Match(this[0].Value.GetType())) continue;
_targetAnimator = (IAnimator)Activator.CreateInstance(valueType.AnimatorType);
foreach (var keyframe in this)
{
_targetAnimator.Add(keyframe);
}
_targetAnimator.Property = this.Property;
return _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;
}
}

7
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) 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. // normalize sRGB values.
var oldA = oldValue.A / 255d; var oldA = oldValue.A / 255d;
@ -59,7 +64,7 @@ namespace Avalonia.Animation.Animators
var b = oldB + progress * (newB - oldB); var b = oldB + progress * (newB - oldB);
// convert back to sRGB in the [0..255] range // convert back to sRGB in the [0..255] range
a = a * 255d; a *= 255d;
r = OECF_sRGB(r) * 255d; r = OECF_sRGB(r) * 255d;
g = OECF_sRGB(g) * 255d; g = OECF_sRGB(g) * 255d;
b = OECF_sRGB(b) * 255d; b = OECF_sRGB(b) * 255d;

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

@ -1,71 +1,32 @@
using System; using System;
using System.Reactive.Disposables; using Avalonia.Data;
using Avalonia.Media; using Avalonia.Media;
using Avalonia.Media.Immutable; using Avalonia.Media.Immutable;
namespace Avalonia.Animation.Animators namespace Avalonia.Animation.Animators
{ {
/// <summary> /// <summary>
/// Animator that handles <see cref="SolidColorBrush"/>. /// Animator that handles <see cref="SolidColorBrush"/> values.
/// </summary> /// </summary>
public class SolidColorBrushAnimator : Animator<SolidColorBrush> public class ISolidColorBrushAnimator : Animator<ISolidColorBrush>
{ {
private ColorAnimator _colorAnimator; public override ISolidColorBrush Interpolate(double progress, ISolidColorBrush oldValue, ISolidColorBrush newValue)
private void InitializeColorAnimator()
{ {
_colorAnimator = new ColorAnimator(); return new ImmutableSolidColorBrush(ColorAnimator.InterpolateCore(progress, oldValue.Color, newValue.Color));
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) public override IDisposable BindAnimation(Animatable control, IObservable<ISolidColorBrush> instance)
{ {
// Preprocess keyframe values to Color if the xaml parser converts them to ISCB. return control.Bind((AvaloniaProperty<IBrush>)Property, instance, BindingPriority.Animation);
foreach (var keyframe in this) }
{ }
if (keyframe.Value is ISolidColorBrush colorBrush)
{ [Obsolete]
keyframe.Value = colorBrush.Color; public class SolidColorBrushAnimator : Animator<SolidColorBrush>
} {
else public override SolidColorBrush Interpolate(double progress, SolidColorBrush oldValue, SolidColorBrush newValue)
{ {
return Disposable.Empty; return new SolidColorBrush(ColorAnimator.InterpolateCore(progress, oldValue.Color, newValue.Color));
}
}
SolidColorBrush finalTarget;
var targetVal = control.GetValue(Property);
if (targetVal is null)
{
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;
}
if (_colorAnimator == null)
InitializeColorAnimator();
return _colorAnimator.Apply(animation, finalTarget, clock ?? control.Clock, match, onComplete);
} }
public override SolidColorBrush Interpolate(double p, SolidColorBrush o, SolidColorBrush n) => null;
} }
} }

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

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

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

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

Loading…
Cancel
Save