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 |
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 |
public abstract class KeyFrameAnimation : CompositionAnimation |
||||
{ |
{ |
||||
|
private TimeSpan _duration = TimeSpan.FromMilliseconds(1); |
||||
|
|
||||
internal KeyFrameAnimation(Compositor compositor) : base(compositor) |
internal KeyFrameAnimation(Compositor compositor) : base(compositor) |
||||
{ |
{ |
||||
} |
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// The delay behavior of the key frame animation.
|
||||
|
/// </summary>
|
||||
public AnimationDelayBehavior DelayBehavior { get; set; } |
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 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; } |
public AnimationIterationBehavior IterationBehavior { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// The number of times to repeat the key frame animation.
|
||||
|
/// </summary>
|
||||
public int IterationCount { get; set; } = 1; |
public int IterationCount { get; set; } = 1; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Specifies how to set the property value when animation is stopped
|
||||
|
/// </summary>
|
||||
public AnimationStopBehavior StopBehavior { get; set; } |
public AnimationStopBehavior StopBehavior { get; set; } |
||||
|
|
||||
private protected abstract IKeyFrames KeyFrames { get; } |
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, |
public void InsertExpressionKeyFrame(float normalizedProgressKey, string value, |
||||
CompositionEasingFunction easingFunction) => |
Easing? easingFunction = null) => |
||||
KeyFrames.InsertExpressionKeyFrame(normalizedProgressKey, value, easingFunction); |
KeyFrames.InsertExpressionKeyFrame(normalizedProgressKey, value, easingFunction ?? Compositor.DefaultEasing); |
||||
|
|
||||
public void InsertExpressionKeyFrame(float normalizedProgressKey, string value) |
|
||||
=> KeyFrames.InsertExpressionKeyFrame(normalizedProgressKey, value, new LinearEasingFunction(Compositor)); |
|
||||
} |
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Specifies the animation delay behavior.
|
||||
|
/// </summary>
|
||||
public enum AnimationDelayBehavior |
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, |
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 |
SetInitialValueBeforeDelay |
||||
} |
} |
||||
|
|
||||
public enum AnimationDirection |
/// <summary>
|
||||
{ |
/// Specifies if the animation should loop.
|
||||
Normal, |
/// </summary>
|
||||
Reverse, |
|
||||
Alternate, |
|
||||
AlternateReverse |
|
||||
} |
|
||||
|
|
||||
public enum AnimationIterationBehavior |
public enum AnimationIterationBehavior |
||||
{ |
{ |
||||
|
/// <summary>
|
||||
|
/// The animation should loop the specified number of times.
|
||||
|
/// </summary>
|
||||
Count, |
Count, |
||||
|
/// <summary>
|
||||
|
/// The animation should loop forever.
|
||||
|
/// </summary>
|
||||
Forever |
Forever |
||||
} |
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Specifies the behavior of an animation when it stops.
|
||||
|
/// </summary>
|
||||
public enum AnimationStopBehavior |
public enum AnimationStopBehavior |
||||
{ |
{ |
||||
|
/// <summary>
|
||||
|
/// Leave the animation at its current value.
|
||||
|
/// </summary>
|
||||
LeaveCurrentValue, |
LeaveCurrentValue, |
||||
|
/// <summary>
|
||||
|
/// Reset the animation to its initial value.
|
||||
|
/// </summary>
|
||||
SetToInitialValue, |
SetToInitialValue, |
||||
|
/// <summary>
|
||||
|
/// Set the animation to its final value.
|
||||
|
/// </summary>
|
||||
SetToFinalValue |
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; |
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; |
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