diff --git a/src/AtomUI/Interceptors/TransitionInterceptors.cs b/src/AtomUI/Interceptors/TransitionInterceptors.cs index e42023dc6..c9470c39d 100644 --- a/src/AtomUI/Interceptors/TransitionInterceptors.cs +++ b/src/AtomUI/Interceptors/TransitionInterceptors.cs @@ -15,17 +15,12 @@ internal static class TransitionInterceptor { _disposables = new Dictionary(); } - + public static bool DoTransitionPrefix(TTransition __instance, IObservable progress) { if (!_disposables.ContainsKey(__instance) && __instance is INotifyTransitionCompleted notifier) { - var disposable = progress.Subscribe(onNext: d => {}, onCompleted: () => - { - HandleCompleted(notifier, true); - }, onError:exception => - { - HandleCompleted(notifier, false); - }); + var disposable = progress.Subscribe(onNext: d => { }, onCompleted: () => { HandleCompleted(notifier, true); }, + onError: exception => { HandleCompleted(notifier, false); }); _disposables.Add(notifier, disposable); } @@ -37,6 +32,7 @@ internal static class TransitionInterceptor if (succeed) { notifier.NotifyTransitionCompleted(); } + _disposables[notifier].Dispose(); _disposables.Remove(notifier); } @@ -44,30 +40,29 @@ internal static class TransitionInterceptor internal static class TransitionInterceptorsRegister { - private static readonly MethodInfo? DoTransitionMethodInfo; - - static TransitionInterceptorsRegister() - { - DoTransitionMethodInfo = typeof(TransitionInterceptor<,>) - .GetMethod("DoTransitionPrefix", BindingFlags.Static | BindingFlags.Public); - } - public static void Register(Harmony harmony) { RegisterTransformOperationsTransition(harmony); + RegisterDoubleTransition(harmony); } private static void RegisterTransformOperationsTransition(Harmony harmony) { - var origin = typeof(TransformOperationsTransition).GetMethod("DoTransition", BindingFlags.Instance | BindingFlags.NonPublic); - var prefixInterceptor = DoTransitionMethodInfo?.MakeGenericMethod(typeof(TransformOperationsTransition), typeof(ITransform)); + var origin = + typeof(TransformOperationsTransition).GetMethod("DoTransition", + BindingFlags.Instance | BindingFlags.NonPublic); + var prefixInterceptor = typeof(TransitionInterceptor<,>) + .MakeGenericType(typeof(TransformOperationsTransition), typeof(ITransform)) + .GetMethod("DoTransitionPrefix", BindingFlags.Static | BindingFlags.Public); harmony.Patch(origin, prefix: new HarmonyMethod(prefixInterceptor)); } private static void RegisterDoubleTransition(Harmony harmony) { var origin = typeof(DoubleTransition).GetMethod("DoTransition", BindingFlags.Instance | BindingFlags.NonPublic); - var prefixInterceptor = DoTransitionMethodInfo?.MakeGenericMethod(typeof(DoubleTransition), typeof(double)); + var prefixInterceptor = typeof(TransitionInterceptor<,>) + .MakeGenericType(typeof(DoubleTransition), typeof(double)) + .GetMethod("DoTransitionPrefix", BindingFlags.Static | BindingFlags.Public); harmony.Patch(origin, prefix: new HarmonyMethod(prefixInterceptor)); } } \ No newline at end of file diff --git a/src/AtomUI/MotionScene/AbstractMotion.cs b/src/AtomUI/MotionScene/AbstractMotion.cs index ec84ac601..d85ea0647 100644 --- a/src/AtomUI/MotionScene/AbstractMotion.cs +++ b/src/AtomUI/MotionScene/AbstractMotion.cs @@ -1,32 +1,17 @@ using System.Diagnostics; -using AtomUI.Media; using Avalonia; using Avalonia.Animation; using Avalonia.Animation.Easings; using Avalonia.Controls; -using Avalonia.Layout; using Avalonia.Media; using Microsoft.CSharp.RuntimeBinder; -using ColorTransition = Avalonia.Animation.ColorTransition; namespace AtomUI.MotionScene; public enum TransitionKind { - BoxShadows, - Brush, - Color, - CornerRadius, Double, - Float, - Integer, - Point, - PixelPoint, - RelativePoint, - Size, - Thickness, TransformOperations, - Vector, } public record class MotionConfig @@ -58,27 +43,27 @@ public abstract class AbstractMotion : AvaloniaObject, IMotion private List _transitions; // 定义我们目前支持的动效属性 - protected static readonly StyledProperty MotionWidthProperty = - Layoutable.WidthProperty.AddOwner(); - - protected static readonly StyledProperty MotionHeightProperty = - Layoutable.HeightProperty.AddOwner(); - - protected static readonly StyledProperty MotionWindowPositionProperty = - AvaloniaProperty.Register(nameof(MotionWindowPosition)); - protected static readonly StyledProperty MotionOpacityProperty = Visual.OpacityProperty.AddOwner(); + + protected static readonly StyledProperty MotionWidthProperty = + Visual.OpacityProperty.AddOwner(); + + protected static readonly StyledProperty MotionHeightProperty = + Visual.OpacityProperty.AddOwner(); - protected static readonly StyledProperty MotionRenderOffsetProperty = - AvaloniaProperty.Register(nameof(MotionRenderOffset)); - - protected static readonly StyledProperty MotionRenderBoundsProperty = - AvaloniaProperty.Register(nameof(MotionRenderBounds)); + protected static readonly StyledProperty MotionRenderTransformOriginProperty = + AvaloniaProperty.Register(nameof(MotionRenderTransformOrigin)); protected static readonly StyledProperty MotionRenderTransformProperty = AvaloniaProperty.Register(nameof(MotionRenderTransform)); + protected double MotionOpacity + { + get => GetValue(MotionOpacityProperty); + set => SetValue(MotionOpacityProperty, value); + } + protected double MotionWidth { get => GetValue(MotionWidthProperty); @@ -91,28 +76,10 @@ public abstract class AbstractMotion : AvaloniaObject, IMotion set => SetValue(MotionHeightProperty, value); } - protected PixelPoint MotionWindowPosition + protected RelativePoint MotionRenderTransformOrigin { - get => GetValue(MotionWindowPositionProperty); - set => SetValue(MotionWindowPositionProperty, value); - } - - protected double MotionOpacity - { - get => GetValue(MotionOpacityProperty); - set => SetValue(MotionOpacityProperty, value); - } - - protected Point MotionRenderOffset - { - get => GetValue(MotionRenderOffsetProperty); - set => SetValue(MotionRenderOffsetProperty, value); - } - - protected Rect MotionRenderBounds - { - get => GetValue(MotionRenderBoundsProperty); - set => SetValue(MotionRenderBoundsProperty, value); + get => GetValue(MotionRenderTransformOriginProperty); + set => SetValue(MotionRenderTransformOriginProperty, value); } protected ITransform MotionRenderTransform @@ -168,32 +135,8 @@ public abstract class AbstractMotion : AvaloniaObject, IMotion protected virtual ITransition NotifyBuildTransition(MotionConfig config) { TransitionBase transition = default!; - if (config.TransitionKind == TransitionKind.Brush) { - transition = new SolidColorBrushTransition(); - } else if (config.TransitionKind == TransitionKind.Color) { - transition = new ColorTransition(); - } else if (config.TransitionKind == TransitionKind.Double) { + if (config.TransitionKind == TransitionKind.Double) { transition = new DoubleTransition(); - } else if (config.TransitionKind == TransitionKind.Float) { - transition = new FloatTransition(); - } else if (config.TransitionKind == TransitionKind.Integer) { - transition = new IntegerTransition(); - } else if (config.TransitionKind == TransitionKind.Point) { - transition = new PointTransition(); - } else if (config.TransitionKind == TransitionKind.PixelPoint) { - transition = new PixelPointTransition(); - } else if (config.TransitionKind == TransitionKind.Size) { - transition = new SizeTransition(); - } else if (config.TransitionKind == TransitionKind.Thickness) { - transition = new ThicknessTransition(); - } else if (config.TransitionKind == TransitionKind.Vector) { - transition = new VectorTransition(); - } else if (config.TransitionKind == TransitionKind.BoxShadows) { - transition = new BoxShadowsTransition(); - } else if (config.TransitionKind == TransitionKind.CornerRadius) { - transition = new CornerRadiusTransition(); - } else if (config.TransitionKind == TransitionKind.RelativePoint) { - transition = new RelativePointTransition(); } else if (config.TransitionKind == TransitionKind.TransformOperations) { transition = new TransformOperationsTransition(); } diff --git a/src/AtomUI/MotionScene/CollapseMotion.cs b/src/AtomUI/MotionScene/CollapseMotion.cs index 782b86d25..cbe73b946 100644 --- a/src/AtomUI/MotionScene/CollapseMotion.cs +++ b/src/AtomUI/MotionScene/CollapseMotion.cs @@ -10,17 +10,57 @@ public class CollapseMotion : AbstractMotion : base(actor) {} + public MotionConfig? OpacityConfig => GetMotionConfig(MotionOpacityProperty); + public MotionConfig? HeightConfig => GetMotionConfig(MotionHeightProperty); + + public void ConfigureHeight(TimeSpan duration, Easing? easing = null) + { + easing ??= new CubicEaseInOut(); + var motionEntity = GetMotionEntity(); + var config = new MotionConfig(MotionHeightProperty) + { + TransitionKind = TransitionKind.Double, + StartValue = motionEntity.Bounds.Height, + EndValue = 0, + MotionDuration = duration, + MotionEasing = easing + }; + AddMotionConfig(config); + } + + public void ConfigureOpacity(TimeSpan duration, Easing? easing = null) + { + easing ??= new CubicEaseInOut(); + var config = new MotionConfig(MotionOpacityProperty) + { + TransitionKind = TransitionKind.Double, + StartValue = 1d, + EndValue = 0d, + MotionDuration = duration, + MotionEasing = easing + }; + AddMotionConfig(config); + } +} + +public class ExpandMotion : AbstractMotion +{ + public ExpandMotion(MotionActor actor) + : base(actor) + {} + + public MotionConfig? OpacityConfig => GetMotionConfig(MotionOpacityProperty); public MotionConfig? HeightConfig => GetMotionConfig(MotionHeightProperty); - public MotionConfig? WidthConfig => GetMotionConfig(MotionWidthProperty); public void ConfigureHeight(double originHeight, TimeSpan duration, Easing? easing = null) { easing ??= new CubicEaseInOut(); + var motionEntity = GetMotionEntity(); var config = new MotionConfig(MotionHeightProperty) { TransitionKind = TransitionKind.Double, - StartValue = originHeight, - EndValue = 0, + StartValue = 0, + EndValue = motionEntity.Bounds.Height, MotionDuration = duration, MotionEasing = easing }; @@ -30,12 +70,11 @@ public class CollapseMotion : AbstractMotion public void ConfigureOpacity(double originOpacity, TimeSpan duration, Easing? easing = null) { easing ??= new CubicEaseInOut(); - originOpacity = Math.Clamp(originOpacity, 0, 1); var config = new MotionConfig(MotionOpacityProperty) { TransitionKind = TransitionKind.Double, - StartValue = originOpacity, - EndValue = 0, + StartValue = 0d, + EndValue = 1d, MotionDuration = duration, MotionEasing = easing }; diff --git a/src/AtomUI/MotionScene/MoveMotion.cs b/src/AtomUI/MotionScene/MoveMotion.cs index 05ba46877..0c049b798 100644 --- a/src/AtomUI/MotionScene/MoveMotion.cs +++ b/src/AtomUI/MotionScene/MoveMotion.cs @@ -1,12 +1,13 @@ using Avalonia; using Avalonia.Animation.Easings; +using Avalonia.Media; namespace AtomUI.MotionScene; public class MoveDownInMotion : AbstractMotion { public MotionConfig? OpacityConfig => GetMotionConfig(MotionOpacityProperty); - public MotionConfig? OffsetConfig => GetMotionConfig(MotionRenderOffsetProperty); + public MotionConfig? RenderTransformConfig => GetMotionConfig(MotionRenderTransformProperty); public MoveDownInMotion(MotionActor actor) : base(actor) @@ -26,18 +27,19 @@ public class MoveDownInMotion : AbstractMotion AddMotionConfig(config); } - public void ConfigureOffset(TimeSpan duration, Easing? easing = null) + public void ConfigureTransform(TimeSpan duration, Easing? easing = null) { easing ??= new CircularEaseOut(); - var target = GetMotionActor()?.Entity!; - var config = new MotionConfig(MotionRenderOffsetProperty) + var motionEntity = GetMotionActor().Entity; + var config = new MotionConfig(MotionRenderTransformProperty) { - TransitionKind = TransitionKind.Point, - StartValue = new Point(target.Bounds.X, target.Bounds.Bottom), - EndValue = new Point(target.Bounds.X, 0), + TransitionKind = TransitionKind.TransformOperations, + StartValue = new TranslateTransform(0, motionEntity.Bounds.Bottom), + EndValue = new TranslateTransform(0, 0), MotionDuration = duration, MotionEasing = easing }; + AddMotionConfig(config); } } @@ -45,7 +47,7 @@ public class MoveDownInMotion : AbstractMotion public class MoveDownOutMotion : AbstractMotion { public MotionConfig? OpacityConfig => GetMotionConfig(MotionOpacityProperty); - public MotionConfig? OffsetConfig => GetMotionConfig(MotionRenderOffsetProperty); + public MotionConfig? RenderTransformConfig => GetMotionConfig(MotionRenderTransformProperty); public MoveDownOutMotion(MotionActor actor) : base(actor) @@ -65,15 +67,16 @@ public class MoveDownOutMotion : AbstractMotion AddMotionConfig(config); } - public void ConfigureOffset(TimeSpan duration, Easing? easing = null) + public void ConfigureTransform(TimeSpan duration, Easing? easing = null) { easing ??= new CircularEaseInOut(); var motionEntity = GetMotionEntity(); - var config = new MotionConfig(MotionRenderOffsetProperty) + + var config = new MotionConfig(MotionRenderTransformProperty) { - TransitionKind = TransitionKind.Point, - StartValue = new Point(motionEntity.Bounds.X, 0), - EndValue = new Point(motionEntity.Bounds.X, motionEntity.Bounds.Bottom), + TransitionKind = TransitionKind.TransformOperations, + StartValue = new TranslateTransform(0, 0), + EndValue = new TranslateTransform(0, motionEntity.Bounds.Bottom), MotionDuration = duration, MotionEasing = easing }; @@ -84,7 +87,7 @@ public class MoveDownOutMotion : AbstractMotion public class MoveLeftInMotion : AbstractMotion { public MotionConfig? OpacityConfig => GetMotionConfig(MotionOpacityProperty); - public MotionConfig? OffsetConfig => GetMotionConfig(MotionRenderOffsetProperty); + public MotionConfig? RenderTransformConfig => GetMotionConfig(MotionRenderTransformProperty); public MoveLeftInMotion(MotionActor actor) : base(actor) @@ -104,15 +107,15 @@ public class MoveLeftInMotion : AbstractMotion AddMotionConfig(config); } - public void ConfigureOffset(TimeSpan duration, Easing? easing = null) + public void ConfigureTransform(TimeSpan duration, Easing? easing = null) { easing ??= new CircularEaseOut(); var motionEntity = GetMotionEntity(); - var config = new MotionConfig(MotionRenderOffsetProperty) + var config = new MotionConfig(MotionRenderTransformProperty) { - TransitionKind = TransitionKind.Point, - StartValue = new Point(motionEntity.Bounds.X - motionEntity.Bounds.Width, motionEntity.Bounds.Y), - EndValue = new Point(motionEntity.Bounds.X, motionEntity.Bounds.Y), + TransitionKind = TransitionKind.TransformOperations, + StartValue = new TranslateTransform(- motionEntity.Bounds.Width, 0), + EndValue = new TranslateTransform(0, 0), MotionDuration = duration, MotionEasing = easing }; @@ -123,7 +126,7 @@ public class MoveLeftInMotion : AbstractMotion public class MoveLeftOutMotion : AbstractMotion { public MotionConfig? OpacityConfig => GetMotionConfig(MotionOpacityProperty); - public MotionConfig? OffsetConfig => GetMotionConfig(MotionRenderOffsetProperty); + public MotionConfig? RenderTransformConfig => GetMotionConfig(MotionRenderTransformProperty); public MoveLeftOutMotion(MotionActor actor) : base(actor) @@ -143,18 +146,20 @@ public class MoveLeftOutMotion : AbstractMotion AddMotionConfig(config); } - public void ConfigureOffset(TimeSpan duration, Easing? easing = null) + public void ConfigureTransform(TimeSpan duration, Easing? easing = null) { easing ??= new CircularEaseInOut(); var motionEntity = GetMotionEntity(); - var config = new MotionConfig(MotionRenderOffsetProperty) + + var config = new MotionConfig(MotionRenderTransformProperty) { - TransitionKind = TransitionKind.Point, - StartValue = new Point(motionEntity.Bounds.X, motionEntity.Bounds.Y), - EndValue = new Point(motionEntity.Bounds.X - motionEntity.Bounds.Width, motionEntity.Bounds.Y), + TransitionKind = TransitionKind.TransformOperations, + StartValue = new TranslateTransform(0, 0), + EndValue = new TranslateTransform( - motionEntity.Bounds.Width, 0), MotionDuration = duration, MotionEasing = easing }; + AddMotionConfig(config); } } @@ -162,7 +167,7 @@ public class MoveLeftOutMotion : AbstractMotion public class MoveRightInMotion : AbstractMotion { public MotionConfig? OpacityConfig => GetMotionConfig(MotionOpacityProperty); - public MotionConfig? OffsetConfig => GetMotionConfig(MotionRenderOffsetProperty); + public MotionConfig? RenderTransformConfig => GetMotionConfig(MotionRenderTransformProperty); public MoveRightInMotion(MotionActor actor) : base(actor) @@ -182,15 +187,15 @@ public class MoveRightInMotion : AbstractMotion AddMotionConfig(config); } - public void ConfigureOffset(TimeSpan duration, Easing? easing = null) + public void ConfigureTransform(TimeSpan duration, Easing? easing = null) { easing ??= new CircularEaseOut(); var motionEntity = GetMotionEntity(); - var config = new MotionConfig(MotionRenderOffsetProperty) + var config = new MotionConfig(MotionRenderTransformProperty) { - TransitionKind = TransitionKind.Point, - StartValue = new Point(motionEntity.Bounds.Right, motionEntity.Bounds.Y), - EndValue = new Point(motionEntity.Bounds.X, motionEntity.Bounds.Y), + TransitionKind = TransitionKind.TransformOperations, + StartValue = new TranslateTransform(motionEntity.Bounds.Right, 0), + EndValue = new TranslateTransform(0, 0), MotionDuration = duration, MotionEasing = easing }; @@ -201,7 +206,7 @@ public class MoveRightInMotion : AbstractMotion public class MoveRightOutMotion : AbstractMotion { public MotionConfig? OpacityConfig => GetMotionConfig(MotionOpacityProperty); - public MotionConfig? OffsetConfig => GetMotionConfig(MotionRenderOffsetProperty); + public MotionConfig? RenderTransformConfig => GetMotionConfig(MotionRenderTransformProperty); public MoveRightOutMotion(MotionActor actor) : base(actor) @@ -221,15 +226,15 @@ public class MoveRightOutMotion : AbstractMotion AddMotionConfig(config); } - public void ConfigureOffset(TimeSpan duration, Easing? easing = null) + public void ConfigureTransform(TimeSpan duration, Easing? easing = null) { easing ??= new CircularEaseInOut(); var motionEntity = GetMotionEntity(); - var config = new MotionConfig(MotionRenderOffsetProperty) + var config = new MotionConfig(MotionRenderTransformProperty) { - TransitionKind = TransitionKind.Point, - StartValue = new Point(motionEntity.Bounds.X, motionEntity.Bounds.Y), - EndValue = new Point(motionEntity.Bounds.Right, motionEntity.Bounds.Y), + TransitionKind = TransitionKind.TransformOperations, + StartValue = new TranslateTransform(0, 0), + EndValue = new TranslateTransform(motionEntity.Bounds.Right, 0), MotionDuration = duration, MotionEasing = easing };