60 changed files with 565 additions and 417 deletions
@ -0,0 +1,29 @@ |
|||
using System; |
|||
using Avalonia.Rendering.Composition; |
|||
using Avalonia.Rendering.Composition.Utils; |
|||
|
|||
namespace Avalonia.Animation.Easings; |
|||
|
|||
public class CubicBezierEasing : IEasing |
|||
{ |
|||
private CubicBezier _bezier; |
|||
//cubic-bezier(0.25, 0.1, 0.25, 1.0)
|
|||
internal CubicBezierEasing(Point controlPoint1, Point controlPoint2) |
|||
{ |
|||
ControlPoint1 = controlPoint1; |
|||
ControlPoint2 = controlPoint2; |
|||
if (controlPoint1.X < 0 || controlPoint1.X > 1 || controlPoint2.X < 0 || controlPoint2.X > 1) |
|||
throw new ArgumentException(); |
|||
_bezier = new CubicBezier(controlPoint1.X, controlPoint1.Y, controlPoint2.X, controlPoint2.Y); |
|||
} |
|||
|
|||
public Point ControlPoint2 { get; set; } |
|||
public Point ControlPoint1 { get; set; } |
|||
|
|||
internal static IEasing Ease { get; } = new CubicBezierEasing(new Point(0.25, 0.1), new Point(0.25, 1)); |
|||
|
|||
double IEasing.Ease(double progress) |
|||
{ |
|||
return _bezier.Solve(progress); |
|||
} |
|||
} |
|||
@ -1,53 +1,134 @@ |
|||
using System; |
|||
using Avalonia.Animation; |
|||
using Avalonia.Animation.Easings; |
|||
|
|||
namespace Avalonia.Rendering.Composition.Animations |
|||
{ |
|||
|
|||
/// <summary>
|
|||
/// A time-based animation with one or more key frames.
|
|||
/// These frames are markers, allowing developers to specify values at specific times for the animating property.
|
|||
/// KeyFrame animations can be further customized by specifying how the animation interpolates between keyframes.
|
|||
/// </summary>
|
|||
public abstract class KeyFrameAnimation : CompositionAnimation |
|||
{ |
|||
private TimeSpan _duration = TimeSpan.FromMilliseconds(1); |
|||
|
|||
internal KeyFrameAnimation(Compositor compositor) : base(compositor) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// The delay behavior of the key frame animation.
|
|||
/// </summary>
|
|||
public AnimationDelayBehavior DelayBehavior { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Delay before the animation starts after <see cref="CompositionObject.StartAnimation"/> is called.
|
|||
/// </summary>
|
|||
public System.TimeSpan DelayTime { get; set; } |
|||
public AnimationDirection Direction { get; set; } |
|||
public System.TimeSpan Duration { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// The direction the animation is playing.
|
|||
/// The Direction property allows you to drive your animation from start to end or end to start or alternate
|
|||
/// between start and end or end to start if animation has an <see cref="IterationCount"/> greater than one.
|
|||
/// This gives an easy way for customizing animation definitions.
|
|||
/// </summary>
|
|||
public PlaybackDirection Direction { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// The duration of the animation.
|
|||
/// Minimum allowed value is 1ms and maximum allowed value is 24 days.
|
|||
/// </summary>
|
|||
public TimeSpan Duration |
|||
{ |
|||
get => _duration; |
|||
set |
|||
{ |
|||
if (_duration < TimeSpan.FromMilliseconds(1) || _duration > TimeSpan.FromDays(1)) |
|||
throw new ArgumentException("Minimum allowed value is 1ms and maximum allowed value is 24 days."); |
|||
_duration = value; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// The iteration behavior for the key frame animation.
|
|||
/// </summary>
|
|||
public AnimationIterationBehavior IterationBehavior { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// The number of times to repeat the key frame animation.
|
|||
/// </summary>
|
|||
public int IterationCount { get; set; } = 1; |
|||
|
|||
/// <summary>
|
|||
/// Specifies how to set the property value when animation is stopped
|
|||
/// </summary>
|
|||
public AnimationStopBehavior StopBehavior { get; set; } |
|||
|
|||
private protected abstract IKeyFrames KeyFrames { get; } |
|||
|
|||
/// <summary>
|
|||
/// Inserts an expression keyframe.
|
|||
/// </summary>
|
|||
/// <param name="normalizedProgressKey">
|
|||
/// The time the key frame should occur at, expressed as a percentage of the animation Duration. Allowed value is from 0.0 to 1.0.
|
|||
/// </param>
|
|||
/// <param name="value">The expression used to calculate the value of the key frame.</param>
|
|||
/// <param name="easingFunction">The easing function to use when interpolating between frames.</param>
|
|||
public void InsertExpressionKeyFrame(float normalizedProgressKey, string value, |
|||
CompositionEasingFunction easingFunction) => |
|||
KeyFrames.InsertExpressionKeyFrame(normalizedProgressKey, value, easingFunction); |
|||
|
|||
public void InsertExpressionKeyFrame(float normalizedProgressKey, string value) |
|||
=> KeyFrames.InsertExpressionKeyFrame(normalizedProgressKey, value, new LinearEasingFunction(Compositor)); |
|||
Easing? easingFunction = null) => |
|||
KeyFrames.InsertExpressionKeyFrame(normalizedProgressKey, value, easingFunction ?? Compositor.DefaultEasing); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Specifies the animation delay behavior.
|
|||
/// </summary>
|
|||
public enum AnimationDelayBehavior |
|||
{ |
|||
/// <summary>
|
|||
/// If a DelayTime is specified, it delays starting the animation according to delay time and after delay
|
|||
/// has expired it applies animation to the object property.
|
|||
/// </summary>
|
|||
SetInitialValueAfterDelay, |
|||
/// <summary>
|
|||
/// Applies the initial value of the animation (i.e. the value at Keyframe 0) to the object before the delay time
|
|||
/// is elapsed (when there is a DelayTime specified), it then delays starting the animation according to the DelayTime.
|
|||
/// </summary>
|
|||
SetInitialValueBeforeDelay |
|||
} |
|||
|
|||
public enum AnimationDirection |
|||
{ |
|||
Normal, |
|||
Reverse, |
|||
Alternate, |
|||
AlternateReverse |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Specifies if the animation should loop.
|
|||
/// </summary>
|
|||
public enum AnimationIterationBehavior |
|||
{ |
|||
/// <summary>
|
|||
/// The animation should loop the specified number of times.
|
|||
/// </summary>
|
|||
Count, |
|||
/// <summary>
|
|||
/// The animation should loop forever.
|
|||
/// </summary>
|
|||
Forever |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Specifies the behavior of an animation when it stops.
|
|||
/// </summary>
|
|||
public enum AnimationStopBehavior |
|||
{ |
|||
/// <summary>
|
|||
/// Leave the animation at its current value.
|
|||
/// </summary>
|
|||
LeaveCurrentValue, |
|||
/// <summary>
|
|||
/// Reset the animation to its initial value.
|
|||
/// </summary>
|
|||
SetToInitialValue, |
|||
/// <summary>
|
|||
/// Set the animation to its final value.
|
|||
/// </summary>
|
|||
SetToFinalValue |
|||
} |
|||
} |
|||
@ -1,95 +0,0 @@ |
|||
using System; |
|||
using System.Numerics; |
|||
using Avalonia.Rendering.Composition.Transport; |
|||
using Avalonia.Rendering.Composition.Utils; |
|||
|
|||
namespace Avalonia.Rendering.Composition |
|||
{ |
|||
public abstract class CompositionEasingFunction : CompositionObject |
|||
{ |
|||
internal CompositionEasingFunction(Compositor compositor) : base(compositor, null!) |
|||
{ |
|||
} |
|||
|
|||
internal abstract IEasingFunction Snapshot(); |
|||
} |
|||
|
|||
internal interface IEasingFunction |
|||
{ |
|||
float Ease(float progress); |
|||
} |
|||
|
|||
public sealed class DelegateCompositionEasingFunction : CompositionEasingFunction |
|||
{ |
|||
private readonly Easing _func; |
|||
|
|||
public delegate float EasingDelegate(float progress); |
|||
|
|||
internal DelegateCompositionEasingFunction(Compositor compositor, EasingDelegate func) : base(compositor) |
|||
{ |
|||
_func = new Easing(func); |
|||
} |
|||
|
|||
class Easing : IEasingFunction |
|||
{ |
|||
private readonly EasingDelegate _func; |
|||
|
|||
public Easing(EasingDelegate func) |
|||
{ |
|||
_func = func; |
|||
} |
|||
|
|||
public float Ease(float progress) => _func(progress); |
|||
} |
|||
|
|||
internal override IEasingFunction Snapshot() => _func; |
|||
} |
|||
|
|||
public class LinearEasingFunction : CompositionEasingFunction |
|||
{ |
|||
public LinearEasingFunction(Compositor compositor) : base(compositor) |
|||
{ |
|||
} |
|||
|
|||
class Linear : IEasingFunction |
|||
{ |
|||
public float Ease(float progress) => progress; |
|||
} |
|||
|
|||
private static readonly Linear Instance = new Linear(); |
|||
internal override IEasingFunction Snapshot() => Instance; |
|||
} |
|||
|
|||
public class CubicBezierEasingFunction : CompositionEasingFunction |
|||
{ |
|||
private CubicBezier _bezier; |
|||
public Vector2 ControlPoint1 { get; } |
|||
public Vector2 ControlPoint2 { get; } |
|||
//cubic-bezier(0.25, 0.1, 0.25, 1.0)
|
|||
internal CubicBezierEasingFunction(Compositor compositor, Vector2 controlPoint1, Vector2 controlPoint2) : base(compositor) |
|||
{ |
|||
ControlPoint1 = controlPoint1; |
|||
ControlPoint2 = controlPoint2; |
|||
if (controlPoint1.X < 0 || controlPoint1.X > 1 || controlPoint2.X < 0 || controlPoint2.X > 1) |
|||
throw new ArgumentException(); |
|||
_bezier = new CubicBezier(controlPoint1.X, controlPoint1.Y, controlPoint2.X, controlPoint2.Y); |
|||
} |
|||
|
|||
class EasingFunction : IEasingFunction |
|||
{ |
|||
private readonly CubicBezier _bezier; |
|||
|
|||
public EasingFunction(CubicBezier bezier) |
|||
{ |
|||
_bezier = bezier; |
|||
} |
|||
|
|||
public float Ease(float progress) => (float)_bezier.Solve(progress); |
|||
} |
|||
|
|||
internal static IEasingFunction Ease { get; } = new EasingFunction(new CubicBezier(0.25, 0.1, 0.25, 1)); |
|||
|
|||
internal override IEasingFunction Snapshot() => new EasingFunction(_bezier); |
|||
} |
|||
|
|||
} |
|||
@ -1,16 +0,0 @@ |
|||
using Avalonia.Rendering.Composition.Server; |
|||
|
|||
namespace Avalonia.Rendering.Composition |
|||
{ |
|||
public partial class CompositionGradientBrush : CompositionBrush |
|||
{ |
|||
internal CompositionGradientBrush(Compositor compositor, ServerCompositionGradientBrush server) : base(compositor, server) |
|||
{ |
|||
ColorStops = new CompositionGradientStopCollection(compositor, server.Stops); |
|||
} |
|||
|
|||
public CompositionGradientStopCollection ColorStops { get; } |
|||
} |
|||
|
|||
|
|||
} |
|||
@ -1,20 +0,0 @@ |
|||
using System; |
|||
|
|||
namespace Avalonia.Rendering.Composition; |
|||
|
|||
partial class Compositor |
|||
{ |
|||
class CompositorRenderLoopTask : IRenderLoopTask |
|||
{ |
|||
public bool NeedsUpdate { get; } |
|||
public void Update(TimeSpan time) |
|||
{ |
|||
throw new NotImplementedException(); |
|||
} |
|||
|
|||
public void Render() |
|||
{ |
|||
throw new NotImplementedException(); |
|||
} |
|||
} |
|||
} |
|||
@ -1,6 +1,14 @@ |
|||
namespace Avalonia.Rendering.Composition; |
|||
|
|||
public static class ElementCompositionPreview |
|||
/// <summary>
|
|||
/// Enables access to composition visual objects that back XAML elements in the XAML composition tree.
|
|||
/// </summary>
|
|||
public static class ElementComposition |
|||
{ |
|||
/// <summary>
|
|||
/// Gets CompositionVisual that backs a Visual
|
|||
/// </summary>
|
|||
/// <param name="visual"></param>
|
|||
/// <returns></returns>
|
|||
public static CompositionVisual? GetElementVisual(Visual visual) => visual.CompositionVisual; |
|||
} |
|||
@ -1,9 +0,0 @@ |
|||
using Avalonia.Rendering.Composition.Server; |
|||
|
|||
namespace Avalonia.Rendering.Composition |
|||
{ |
|||
public interface ICompositionSurface |
|||
{ |
|||
internal ServerCompositionSurface Server { get; } |
|||
} |
|||
} |
|||
@ -1,7 +0,0 @@ |
|||
namespace Avalonia.Rendering.Composition.Server |
|||
{ |
|||
internal abstract partial class ServerCompositionBrush : ServerObject |
|||
{ |
|||
|
|||
} |
|||
} |
|||
@ -1,15 +0,0 @@ |
|||
using System; |
|||
|
|||
namespace Avalonia.Rendering.Composition.Server |
|||
{ |
|||
internal abstract partial class ServerCompositionGradientBrush : ServerCompositionBrush |
|||
{ |
|||
public ServerCompositionGradientStopCollection Stops { get; } |
|||
public ServerCompositionGradientBrush(ServerCompositor compositor) : base(compositor) |
|||
{ |
|||
Stops = new ServerCompositionGradientStopCollection(compositor); |
|||
} |
|||
|
|||
public override long LastChangedBy => Math.Max(base.LastChangedBy, (long)Stops.LastChangedBy); |
|||
} |
|||
} |
|||
@ -1,15 +0,0 @@ |
|||
using System.Numerics; |
|||
using Avalonia.Media.Immutable; |
|||
using Avalonia.Platform; |
|||
|
|||
namespace Avalonia.Rendering.Composition.Server |
|||
{ |
|||
internal partial class ServerCompositionSolidColorVisual |
|||
{ |
|||
protected override void RenderCore(CompositorDrawingContextProxy canvas) |
|||
{ |
|||
canvas.DrawRectangle(new ImmutableSolidColorBrush(Color), null, new RoundedRect(new Rect(new Size(Size)))); |
|||
base.RenderCore(canvas); |
|||
} |
|||
} |
|||
} |
|||
@ -1,20 +0,0 @@ |
|||
using System.Numerics; |
|||
using Avalonia.Platform; |
|||
|
|||
namespace Avalonia.Rendering.Composition.Server |
|||
{ |
|||
internal partial class ServerCompositionSpriteVisual |
|||
{ |
|||
|
|||
protected override void RenderCore(CompositorDrawingContextProxy canvas) |
|||
{ |
|||
if (Brush != null) |
|||
{ |
|||
//SetTransform(canvas, transform);
|
|||
//canvas.FillRect((Vector2)Size, (ICbBrush)Brush.Brush!);
|
|||
} |
|||
|
|||
base.RenderCore(canvas); |
|||
} |
|||
} |
|||
} |
|||
@ -1,23 +0,0 @@ |
|||
using System; |
|||
|
|||
namespace Avalonia.Rendering.Composition.Utils |
|||
{ |
|||
static class MathExt |
|||
{ |
|||
public static float Clamp(float value, float min, float max) |
|||
{ |
|||
var amax = Math.Max(min, max); |
|||
var amin = Math.Min(min, max); |
|||
return Math.Min(Math.Max(value, amin), amax); |
|||
} |
|||
|
|||
public static double Clamp(double value, double min, double max) |
|||
{ |
|||
var amax = Math.Max(min, max); |
|||
var amin = Math.Min(min, max); |
|||
return Math.Min(Math.Max(value, amin), amax); |
|||
} |
|||
|
|||
|
|||
} |
|||
} |
|||
Loading…
Reference in new issue