From a8aa937465216ee37ffdd4890b42cb32a289be51 Mon Sep 17 00:00:00 2001 From: WantToBeeMe <93130991+WantToBeeMe@users.noreply.github.com> Date: Fri, 27 Jun 2025 23:22:51 +0200 Subject: [PATCH 01/14] Trails work --- WheelWizard/Views/App.axaml | 1 + .../Components/WhWzLibrary/WheelTrail.axaml | 35 +++++++++++ .../WhWzLibrary/WheelTrail.axaml.cs | 63 +++++++++++++++++++ WheelWizard/Views/Layout.axaml | 8 ++- WheelWizard/Views/Pages/HomePage.axaml | 20 +++++- 5 files changed, 122 insertions(+), 5 deletions(-) create mode 100644 WheelWizard/Views/Components/WhWzLibrary/WheelTrail.axaml create mode 100644 WheelWizard/Views/Components/WhWzLibrary/WheelTrail.axaml.cs diff --git a/WheelWizard/Views/App.axaml b/WheelWizard/Views/App.axaml index 6c44826f..c8b10f02 100644 --- a/WheelWizard/Views/App.axaml +++ b/WheelWizard/Views/App.axaml @@ -68,5 +68,6 @@ + \ No newline at end of file diff --git a/WheelWizard/Views/Components/WhWzLibrary/WheelTrail.axaml b/WheelWizard/Views/Components/WhWzLibrary/WheelTrail.axaml new file mode 100644 index 00000000..00c78d67 --- /dev/null +++ b/WheelWizard/Views/Components/WhWzLibrary/WheelTrail.axaml @@ -0,0 +1,35 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/WheelWizard/Views/Components/WhWzLibrary/WheelTrail.axaml.cs b/WheelWizard/Views/Components/WhWzLibrary/WheelTrail.axaml.cs new file mode 100644 index 00000000..20c70a18 --- /dev/null +++ b/WheelWizard/Views/Components/WhWzLibrary/WheelTrail.axaml.cs @@ -0,0 +1,63 @@ +using Avalonia; +using Avalonia.Controls.Primitives; +using Avalonia.Media; + +namespace WheelWizard.Views.Components +{ + public class WheelTrail : TemplatedControl + { + public static readonly StyledProperty AngleProperty = AvaloniaProperty.Register(nameof(Angle)); + + public double Angle + { + get => GetValue(AngleProperty); + set => SetValue(AngleProperty, value); + } + + public static readonly StyledProperty XProperty = AvaloniaProperty.Register(nameof(X)); + + public double X + { + get => GetValue(XProperty); + set => SetValue(XProperty, value); + } + + public static readonly StyledProperty YProperty = AvaloniaProperty.Register(nameof(Y)); + + public double Y + { + get => GetValue(YProperty); + set => SetValue(YProperty, value); + } + + private readonly RotateTransform _rotateTransform = new RotateTransform { CenterX = 0.5, CenterY = 0.5 }; + private readonly TranslateTransform _translateTransform = new TranslateTransform { X = 0, Y = 0 }; + + public WheelTrail() + { + var group = new TransformGroup(); + group.Children.Add(_rotateTransform); + group.Children.Add(_translateTransform); + this.RenderTransform = group; + } + + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + { + base.OnPropertyChanged(change); + + if (change.Property == AngleProperty) + { + _rotateTransform.Angle = (double)(change.NewValue ?? 0.0); + } + + if (change.Property == XProperty) + { + _translateTransform.X = (double)(change.NewValue ?? 0.0); + } + if (change.Property == YProperty) + { + _translateTransform.Y = (double)(change.NewValue ?? 0.0); + } + } + } +} diff --git a/WheelWizard/Views/Layout.axaml b/WheelWizard/Views/Layout.axaml index 9c331224..db31cd3a 100644 --- a/WheelWizard/Views/Layout.axaml +++ b/WheelWizard/Views/Layout.axaml @@ -56,9 +56,11 @@ - - + + + + - + + + + + - + + + From 16833fc1b62a6575672053ffd76daec1e453f4f3 Mon Sep 17 00:00:00 2001 From: WantToBeeMe <93130991+WantToBeeMe@users.noreply.github.com> Date: Fri, 27 Jun 2025 23:35:29 +0200 Subject: [PATCH 02/14] extended Height property which can be used for animating later --- .../Views/Components/WhWzLibrary/WheelTrail.axaml | 6 ++++-- .../Components/WhWzLibrary/WheelTrail.axaml.cs | 10 ++++++++++ .../Views/Converters/DoubleToThicknessConverters.cs | 13 +++++++++++++ 3 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 WheelWizard/Views/Converters/DoubleToThicknessConverters.cs diff --git a/WheelWizard/Views/Components/WhWzLibrary/WheelTrail.axaml b/WheelWizard/Views/Components/WhWzLibrary/WheelTrail.axaml index 00c78d67..4ecc1824 100644 --- a/WheelWizard/Views/Components/WhWzLibrary/WheelTrail.axaml +++ b/WheelWizard/Views/Components/WhWzLibrary/WheelTrail.axaml @@ -1,12 +1,13 @@ - + @@ -19,7 +20,8 @@ + CornerRadius="100000,100000,0,0" Height="10000" VerticalAlignment="Top" + Margin="{TemplateBinding ExtendedHeight, Converter={x:Static conv:DoubleToThicknessConverters.DoubleToTop}}"> diff --git a/WheelWizard/Views/Components/WhWzLibrary/WheelTrail.axaml.cs b/WheelWizard/Views/Components/WhWzLibrary/WheelTrail.axaml.cs index 20c70a18..917597d7 100644 --- a/WheelWizard/Views/Components/WhWzLibrary/WheelTrail.axaml.cs +++ b/WheelWizard/Views/Components/WhWzLibrary/WheelTrail.axaml.cs @@ -30,6 +30,16 @@ public double Y set => SetValue(YProperty, value); } + public static readonly StyledProperty ExtendedHeightProperty = AvaloniaProperty.Register( + nameof(ExtendedHeight) + ); + + public double ExtendedHeight + { + get => GetValue(ExtendedHeightProperty); + set => SetValue(ExtendedHeightProperty, value); + } + private readonly RotateTransform _rotateTransform = new RotateTransform { CenterX = 0.5, CenterY = 0.5 }; private readonly TranslateTransform _translateTransform = new TranslateTransform { X = 0, Y = 0 }; diff --git a/WheelWizard/Views/Converters/DoubleToThicknessConverters.cs b/WheelWizard/Views/Converters/DoubleToThicknessConverters.cs new file mode 100644 index 00000000..c84853fc --- /dev/null +++ b/WheelWizard/Views/Converters/DoubleToThicknessConverters.cs @@ -0,0 +1,13 @@ +using Avalonia; +using Avalonia.Data.Converters; +using Avalonia.Media; + +namespace WheelWizard.Views.Converters; + +public class DoubleToThicknessConverters +{ + public static readonly IValueConverter DoubleToTop = new FuncValueConverter(x => new Thickness(0, x, 0, 0)); + public static readonly IValueConverter DoubleToBottom = new FuncValueConverter(x => new Thickness(0, 0, 0, x)); + public static readonly IValueConverter DoubleToLeft = new FuncValueConverter(x => new Thickness(x, 0, 0, 0)); + public static readonly IValueConverter DoubleToRight = new FuncValueConverter(x => new Thickness(0, 0, x, 0)); +} From 3f967c115425a7a5c322963ddb97673815021a23 Mon Sep 17 00:00:00 2001 From: WantToBeeMe <93130991+WantToBeeMe@users.noreply.github.com> Date: Fri, 27 Jun 2025 23:53:04 +0200 Subject: [PATCH 03/14] this is so satisfying --- WheelWizard/Views/Pages/HomePage.axaml | 37 ++++++++++++++++++++------ 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/WheelWizard/Views/Pages/HomePage.axaml b/WheelWizard/Views/Pages/HomePage.axaml index c9479bd4..481a934b 100644 --- a/WheelWizard/Views/Pages/HomePage.axaml +++ b/WheelWizard/Views/Pages/HomePage.axaml @@ -8,6 +8,22 @@ mc:Ignorable="d" d:DesignWidth="656" d:DesignHeight="876" ClipToBounds="False" x:Class="WheelWizard.Views.Pages.HomePage"> + + + @@ -35,14 +51,15 @@ + Width="137" Angle="45" Y="-60" X="-20" Classes="EntranceTrail" ExtendedHeight="700" + Background="{StaticResource Primary400}" Foreground="{StaticResource Primary700}"/> + + Width="137" Angle="45" Y="-40" X="170" Classes="EntranceTrail" ExtendedHeight="700" + Background="{StaticResource Primary600}" Foreground="{StaticResource Primary800}"/> + Width="137" Angle="45" Y="150" X="190" Classes="EntranceTrail" ExtendedHeight="700" + Background="{StaticResource Primary200}" Foreground="{StaticResource Primary600}"/> @@ -58,10 +75,10 @@ --> @@ -88,5 +105,9 @@ Click="DolphinButton_OnClick" Width="100" Margin="0,6,0,0" /> + + + + \ No newline at end of file From f7309aeaee7a3efc00918fed0bcf20fbde5471e6 Mon Sep 17 00:00:00 2001 From: WantToBeeMe <93130991+WantToBeeMe@users.noreply.github.com> Date: Sat, 28 Jun 2025 00:17:21 +0200 Subject: [PATCH 04/14] this is soo satisfying --- WheelWizard/Views/Pages/HomePage.axaml | 22 +++++++++++----------- WheelWizard/Views/Pages/HomePage.axaml.cs | 22 ++++++++++++++++++++++ 2 files changed, 33 insertions(+), 11 deletions(-) diff --git a/WheelWizard/Views/Pages/HomePage.axaml b/WheelWizard/Views/Pages/HomePage.axaml index 481a934b..0bca5685 100644 --- a/WheelWizard/Views/Pages/HomePage.axaml +++ b/WheelWizard/Views/Pages/HomePage.axaml @@ -12,7 +12,7 @@ + + + + + + + + + @@ -26,31 +78,54 @@ - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - diff --git a/WheelWizard/Views/Converters/BrushColorConverters.cs b/WheelWizard/Views/Converters/BrushColorConverters.cs new file mode 100644 index 00000000..120ae5f8 --- /dev/null +++ b/WheelWizard/Views/Converters/BrushColorConverters.cs @@ -0,0 +1,28 @@ +using Avalonia.Data.Converters; +using Avalonia.Media; + +namespace WheelWizard.Views.Converters; + +// Note that this is static, which means you dont have to add it as a converter +public static class BrushColorConverters +{ + public static readonly IValueConverter TransparentColor = new FuncValueConverter(x => + { + if (x is ISolidColorBrush brush) + return new Color(0, brush.Color.R, brush.Color.G, brush.Color.B); + if (x is Color c) + return new Color(0, c.R, c.G, c.B); + + return (Colors.Transparent); + }); + + public static readonly IValueConverter BrushToColor = new FuncValueConverter(x => + { + if (x is ISolidColorBrush brush) + return brush.Color; + if (x is IGradientBrush gradientBrush) + return gradientBrush.GradientStops[0].Color; + + return (Colors.Transparent); + }); +} From 0267e0c4d843d47d4b7f9c39a8ed4818bac4ebb8 Mon Sep 17 00:00:00 2001 From: WantToBeeMe <93130991+WantToBeeMe@users.noreply.github.com> Date: Sat, 28 Jun 2025 14:10:04 +0200 Subject: [PATCH 07/14] rotate --- WheelWizard/Views/Pages/HomePage.axaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/WheelWizard/Views/Pages/HomePage.axaml b/WheelWizard/Views/Pages/HomePage.axaml index 0bca5685..0f75c467 100644 --- a/WheelWizard/Views/Pages/HomePage.axaml +++ b/WheelWizard/Views/Pages/HomePage.axaml @@ -16,9 +16,11 @@ FillMode="Forward" Easing="0,0.5,0.1,1"> + + From 1b3bde09b98a7803deab130cd3bffd60c85f0d7c Mon Sep 17 00:00:00 2001 From: WantToBeeMe <93130991+WantToBeeMe@users.noreply.github.com> Date: Sat, 28 Jun 2025 14:34:47 +0200 Subject: [PATCH 08/14] option 1 --- WheelWizard/Views/Pages/HomePage.axaml | 48 +++++++++++++++-------- WheelWizard/Views/Pages/HomePage.axaml.cs | 45 +++++++++++++++++++++ 2 files changed, 77 insertions(+), 16 deletions(-) diff --git a/WheelWizard/Views/Pages/HomePage.axaml b/WheelWizard/Views/Pages/HomePage.axaml index 0f75c467..1ee5be96 100644 --- a/WheelWizard/Views/Pages/HomePage.axaml +++ b/WheelWizard/Views/Pages/HomePage.axaml @@ -5,13 +5,12 @@ xmlns:lang="clr-namespace:WheelWizard.Resources.Languages" xmlns:components="clr-namespace:WheelWizard.Views.Components" xmlns:behaviorComponent="clr-namespace:WheelWizard.Views.BehaviorComponent" - mc:Ignorable="d" d:DesignWidth="656" d:DesignHeight="876" + mc:Ignorable="d" d:DesignWidth="490" d:DesignHeight="830" ClipToBounds="False" x:Class="WheelWizard.Views.Pages.HomePage"> + - + + + + diff --git a/WheelWizard/Views/Pages/HomePage.axaml b/WheelWizard/Views/Pages/HomePage.axaml index 71ba16df..cb20c176 100644 --- a/WheelWizard/Views/Pages/HomePage.axaml +++ b/WheelWizard/Views/Pages/HomePage.axaml @@ -49,31 +49,33 @@ - - - + + @@ -115,7 +119,7 @@ Width="137" Angle="45" Y="-60" X="-20" ExtendedHeight="1000" IsVisible="False" Background="{StaticResource Primary400}" Foreground="{StaticResource Primary700}" /> diff --git a/WheelWizard/Views/Pages/HomePage.axaml.cs b/WheelWizard/Views/Pages/HomePage.axaml.cs index 12862ffa..feda2c6f 100644 --- a/WheelWizard/Views/Pages/HomePage.axaml.cs +++ b/WheelWizard/Views/Pages/HomePage.axaml.cs @@ -20,7 +20,20 @@ public partial class HomePage : UserControlBase { private static ILauncher currentLauncher => _launcherTypes[_launcherIndex]; private static int _launcherIndex = 0; // Make sure this index never goes over the list index - private WheelTrail[] _trails = []; + + private WheelTrail[] _trails; // also used as a lock + + private WheelTrailState _currentTrailState2 = WheelTrailState.Static_None; + + private WheelTrailState _currentTrailState + { + get => _currentTrailState2; + set + { + _currentTrailState2 = value; + Console.WriteLine($"STATUS: {_currentTrailState2}"); + } + } private static List _launcherTypes = [ @@ -95,8 +108,8 @@ private static async void Update() private void PlayButton_Click(object? sender, RoutedEventArgs e) { - currentButtonState?.OnClick?.Invoke(); - + // currentButtonState?.OnClick?.Invoke(); + PlayActivateAnimation(); UpdateActionButton(); DisableAllButtonsTemporarily(); } @@ -155,6 +168,14 @@ private void SetButtonState(MainButtonState state) } #region WheelTrail Animations + // -------------------------- + // IMPORTANT + // -------------------------- + // When you are changing the animation, note that you are working with locks + // Note that the enum _currentTrailState is used to determine the state of the wheel trails, and that should only be read and changed under the influence of lock(_trails) + // Also note that for NO REASON WHATSOEVER you are permitted to put other logic in these animation code other than the animation itself. + // If for whatever reason the lock gets in to a deadlock, only the animation will freeze, the rest will continue to work. + private async void PlayEntranceAnimation() { // If the animations are disabled, it will never play the entrance animation @@ -163,6 +184,15 @@ private async void PlayEntranceAnimation() if (!(bool)SettingsManager.ENABLE_ANIMATIONS.Get()) return; + Console.WriteLine("try to play entrance"); + var allowedToRun = WaitForWheelTrailState( + WheelTrailState.Playing_Entrance, + c => c is WheelTrailState.Static_None + // even if there are 3 waiting, only 1 will go through, since there is an default check that it cant be the same + ); + if (!await allowedToRun) + return; + foreach (var t in _trails) { t.Classes.Add("EntranceTrail"); @@ -173,41 +203,155 @@ private async void PlayEntranceAnimation() foreach (var t in _trails) { t.Classes.Remove("EntranceTrail"); - await Task.Delay(40); + } + + lock (_trails) + { + _currentTrailState = WheelTrailState.Static_Visible; } } - private bool currentlyHovering = false; + private async void PlayActivateAnimation() + { + if (!(bool)SettingsManager.ENABLE_ANIMATIONS.Get()) + return; + + var allowedToRun = WaitForWheelTrailState( + WheelTrailState.Playing_Activate, + c => c is WheelTrailState.Static_Hover or WheelTrailState.Static_Visible, + c => c is WheelTrailState.Static_None or WheelTrailState.Playing_Activate + ); + if (!await allowedToRun) + return; + + foreach (var t in _trails) + { + t.Classes.Clear(); + t.Classes.Add("ActivateTrail"); + await Task.Delay(80); + } + + await Task.Delay(1000); + foreach (var t in _trails) + { + t.Classes.Remove("ActivateTrail"); + await Task.Delay(40); + } + + lock (_trails) + { + _currentTrailState = WheelTrailState.Static_None; + } + } private async void PlayButton_OnPointerEntered(object? sender, PointerEventArgs e) { - currentlyHovering = true; + var allowedToRun = WaitForWheelTrailState( + WheelTrailState.Playing_HoverEnter, + c => c is WheelTrailState.Static_Visible or WheelTrailState.Playing_HoverExit, + c => c is WheelTrailState.Playing_HoverExit + ); + if (!await allowedToRun) + return; + foreach (var t in _trails) { - while (t.Classes.Contains("EntranceTrail")) + // Making sure that if after these seconds the state changed ,that it will not apply the class anymore + lock (_trails) { - await Task.Delay(20); - if (!currentlyHovering) + if (_currentTrailState is not WheelTrailState.Playing_HoverEnter) return; } - if (!currentlyHovering) - return; t.Classes.Remove("HoverExitTrail"); if (!t.Classes.Contains("HoverEnterTrail")) t.Classes.Add("HoverEnterTrail"); await Task.Delay(20); } + + await Task.Delay(300); + lock (_trails) + { + if (_currentTrailState is WheelTrailState.Playing_HoverEnter) + _currentTrailState = WheelTrailState.Static_Hover; + } } - private void PlayButton_OnPointerExit(object? sender, PointerEventArgs e) + private async void PlayButton_OnPointerExit(object? sender, PointerEventArgs e) { - currentlyHovering = false; + var allowedToRun = WaitForWheelTrailState( + WheelTrailState.Playing_HoverExit, + c => c is WheelTrailState.Static_Hover or WheelTrailState.Playing_HoverEnter, + c => c is not WheelTrailState.Static_Hover and not WheelTrailState.Playing_HoverEnter + ); + if (!await allowedToRun) + return; + foreach (var t in _trails) { + lock (_trails) + { + if (_currentTrailState is not WheelTrailState.Playing_HoverExit) + return; + } t.Classes.Remove("HoverEnterTrail"); t.Classes.Add("HoverExitTrail"); } + + await Task.Delay(350); + lock (_trails) + { + if (_currentTrailState is WheelTrailState.Playing_HoverExit) + _currentTrailState = WheelTrailState.Static_Visible; + } + } + + private async Task WaitForWheelTrailState( + WheelTrailState changeStateTo, + Func acceptWhen, + Func? abortWhen = null + ) + { + bool accepted; + lock (_trails) + { + accepted = acceptWhen(_currentTrailState); + if (accepted) + _currentTrailState = changeStateTo; + } + + while (!accepted) + { + await Task.Delay(20); + bool abort; + lock (_trails) + { + abort = (abortWhen?.Invoke(_currentTrailState) ?? false) || _currentTrailState == changeStateTo; + } + if (abort) + return false; + + lock (_trails) + { + accepted = acceptWhen(_currentTrailState); + if (accepted) + _currentTrailState = changeStateTo; + } + } + + return true; + } + + enum WheelTrailState + { + Static_None, // It is not in view + Static_Visible, // It is just doing nothing + Static_Hover, // It is just doing nothing while it is being hovered + + Playing_Entrance, // Animation for entrance is playing NOTHING is allowed to interrupt Playing_Entrance + Playing_Activate, // Animation for activation is playing NOTHING is allowed to interrupt Playing_Entrance + Playing_HoverEnter, // Hover Enter animation is playing can be interrupted + Playing_HoverExit, // Hover Exit animation is exiting can be interrupted } #endregion From 2dcd8940426a1a85bdcc2072e104b25be7750bdc Mon Sep 17 00:00:00 2001 From: WantToBeeMe <93130991+WantToBeeMe@users.noreply.github.com> Date: Sat, 28 Jun 2025 18:52:46 +0200 Subject: [PATCH 13/14] animations are almost perfect imo --- WheelWizard/Views/Pages/HomePage.axaml | 18 ++++++- WheelWizard/Views/Pages/HomePage.axaml.cs | 66 ++++++++++++++--------- 2 files changed, 58 insertions(+), 26 deletions(-) diff --git a/WheelWizard/Views/Pages/HomePage.axaml b/WheelWizard/Views/Pages/HomePage.axaml index cb20c176..479e3e8e 100644 --- a/WheelWizard/Views/Pages/HomePage.axaml +++ b/WheelWizard/Views/Pages/HomePage.axaml @@ -50,7 +50,7 @@ - +