diff --git a/CollapseLauncher/App.xaml b/CollapseLauncher/App.xaml index 066e3cad2..ec8e4a46e 100644 --- a/CollapseLauncher/App.xaml +++ b/CollapseLauncher/App.xaml @@ -31,6 +31,15 @@ + + + + + + + + + @@ -69,11 +78,6 @@ Color="#000000" /> - - - - - #ffd52a - - - - - - #693758 - (Brush)GetValue(ForegroundProperty); + set => SetValue(ForegroundProperty, value); + } + + /// + /// Dependency property for Foreground. + /// + public static readonly DependencyProperty ForegroundProperty = + DependencyProperty.Register(nameof(Foreground), typeof(Brush), typeof(BindableThemeChangeAnimation), + new PropertyMetadata(null!, OnForegroundChanged)); + + protected static void OnForegroundChanged(DependencyObject d, DependencyPropertyChangedEventArgs args) + => ((BindableThemeChangeAnimation)d).OnForegroundChanged(args.NewValue as Brush); + + protected abstract void OnForegroundChanged(Brush? brush); +} diff --git a/CollapseLauncher/Classes/AnimatedVisuals/Lottie/DownloadIcon.cs b/CollapseLauncher/Classes/AnimatedVisuals/Lottie/DownloadIcon.cs index 59d0c86ba..67b789ebb 100644 --- a/CollapseLauncher/Classes/AnimatedVisuals/Lottie/DownloadIcon.cs +++ b/CollapseLauncher/Classes/AnimatedVisuals/Lottie/DownloadIcon.cs @@ -3,13 +3,13 @@ // This code was generated by a tool. // // LottieGen version: -// 8.0.280225.1+7cd366a738 +// 8.2.250604.1+b02a3ee244 // // Command: -// LottieGen -Language CSharp -Namespace CollapseLauncher.AnimatedVisuals.Lottie -Public -WinUIVersion 3.0 -InputFile DownloadIcon.lottie +// LottieGen -GenerateColorBindings -GenerateDependencyObject -Language CSharp -Namespace CollapseLauncher.AnimatedVisuals.Lottie -Public -WinUIVersion 3.0 -InputFile DownloadIcon.json // // Input file: -// DownloadIcon.lottie (1623 bytes created 23:20+07:00 Jun 1 2024) +// DownloadIcon.json (7800 bytes created 16:59+07:00 Jan 4 2026) // // LottieGen source: // http://aka.ms/Lottie @@ -21,16 +21,16 @@ // ____________________________________ // | Object stats | Count | // |__________________________|_______| -// | All CompositionObjects | 118 | +// | All CompositionObjects | 121 | // |--------------------------+-------| -// | Expression animators | 8 | +// | Expression animators | 9 | // | KeyFrame animators | 15 | -// | Reference parameters | 8 | -// | Expression operations | 6 | +// | Reference parameters | 9 | +// | Expression operations | 10 | // |--------------------------+-------| -// | Animated brushes | - | +// | Animated brushes | 1 | // | Animated gradient stops | - | -// | ExpressionAnimations | 8 | +// | ExpressionAnimations | 9 | // | PathKeyFrameAnimations | 1 | // |--------------------------+-------| // | ContainerVisuals | 5 | @@ -48,6 +48,8 @@ using Microsoft.Graphics.Canvas.Effects; using Microsoft.Graphics.Canvas.Geometry; using Microsoft.UI.Composition; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Media; using System; using System.Collections.Generic; using System.Numerics; @@ -59,13 +61,67 @@ namespace CollapseLauncher.AnimatedVisuals.Lottie // Frame rate: 60 fps // Frame count: 300 // Duration: 5000.0 mS - sealed partial class DownloadIcon - : Microsoft.UI.Xaml.Controls.IAnimatedVisualSource + public sealed partial class DownloadIcon + : BindableThemeChangeAnimation + , Microsoft.UI.Xaml.Controls.IAnimatedVisualSource , Microsoft.UI.Xaml.Controls.IAnimatedVisualSource2 { + protected override void OnForegroundChanged(Brush brush) + { + if (brush is SolidColorBrush colorBrush) + { + Color_FFFFFF = colorBrush.Color; + return; + } + + if (brush is AcrylicBrush acrylicBrush) + { + Color_FFFFFF = acrylicBrush.TintColor; + return; + } + } + + private static Color GetForegroundColor(bool isLightTheme) => + isLightTheme + ? Color.FromArgb(0xFF, 0x00, 0x00, 0x00) + : Color.FromArgb(0xFF, 0xFF, 0xFF, 0xFF); + // Animation duration: 5.000 seconds. internal const long c_durationTicks = 50000000; + CompositionPropertySet _themeProperties; + + /// + /// Dependency property for Color_FFFFFF. + /// + public static readonly DependencyProperty Color_FFFFFFProperty = + DependencyProperty.Register("Color_FFFFFF", typeof(Color), typeof(DownloadIcon), + new PropertyMetadata(GetForegroundColor(InnerLauncherConfig.IsAppThemeLight), OnColor_FFFFFFChanged)); + + // Theme properties. + public Color Color_FFFFFF + { + get => (Color)GetValue(Color_FFFFFFProperty); + set => SetValue(Color_FFFFFFProperty, value); + } + + static Vector4 ColorAsVector4(Color color) => new Vector4(color.R, color.G, color.B, color.A); + + static void OnColor_FFFFFFChanged(DependencyObject d, DependencyPropertyChangedEventArgs args) + { + ((DownloadIcon)d)._themeProperties?.InsertVector4("Color_FFFFFF", ColorAsVector4((Color)(Color)args.NewValue)); + } + + CompositionPropertySet EnsureThemeProperties(Compositor compositor) + { + if (_themeProperties == null) + { + _themeProperties = compositor.CreatePropertySet(); + _themeProperties.InsertVector4("Color_FFFFFF", ColorAsVector4((Color)Color_FFFFFF)); + } + return _themeProperties; + } + public Microsoft.UI.Xaml.Controls.IAnimatedVisual TryCreateAnimatedVisual(Compositor compositor) { object ignored = null; @@ -75,10 +131,12 @@ public Microsoft.UI.Xaml.Controls.IAnimatedVisual TryCreateAnimatedVisual(Compos public Microsoft.UI.Xaml.Controls.IAnimatedVisual TryCreateAnimatedVisual(Compositor compositor, out object diagnostics) { diagnostics = null; + EnsureThemeProperties(compositor); var res = new DownloadIcon_AnimatedVisual( - compositor + compositor, + _themeProperties ); res.CreateAnimations(); return res; @@ -122,6 +180,19 @@ public double FrameToProgress(double frameNumber) /// public void SetColorProperty(string propertyName, Color value) { + if (propertyName == "Color_FFFFFF") + { + Color_FFFFFF = value; + } + else + { + return; + } + + if (_themeProperties != null) + { + _themeProperties.InsertVector4(propertyName, ColorAsVector4(value)); + } } /// @@ -139,8 +210,9 @@ sealed partial class DownloadIcon_AnimatedVisual const long c_durationTicks = 50000000; readonly Compositor _c; readonly ExpressionAnimation _reusableExpressionAnimation; + readonly CompositionPropertySet _themeProperties; AnimationController _animationController_0; - CompositionColorBrush _colorBrush_White; + CompositionColorBrush _themeColor_Color_FFFFFF; CompositionContainerShape _containerShape_0; CompositionContainerShape _containerShape_1; CompositionContainerShape _containerShape_2; @@ -155,7 +227,7 @@ sealed partial class DownloadIcon_AnimatedVisual CubicBezierEasingFunction _cubicBezierEasingFunction_0; CubicBezierEasingFunction _cubicBezierEasingFunction_1; ScalarKeyFrameAnimation _opacityScalarAnimation_1_to_0; - ScalarKeyFrameAnimation _positionYScalarAnimation_1025_to_2350; + ScalarKeyFrameAnimation _positionYScalarAnimation_128p125_to_293p75; ScalarKeyFrameAnimation _rotationAngleInDegreesScalarAnimation_0_to_0_0; ShapeVisual _shapeVisual_2; StepEasingFunction _holdThenStepEasingFunction; @@ -245,11 +317,11 @@ CanvasGeometry Geometry_2() CanvasGeometry result; using (var builder = new CanvasPathBuilder(null)) { - builder.BeginFigure(new Vector2(2316F, -196F)); - builder.AddCubicBezier(new Vector2(2316F, -196F), new Vector2(-336F, -196F), new Vector2(-336F, -196F)); - builder.AddCubicBezier(new Vector2(-336F, -196F), new Vector2(-336F, 2132F), new Vector2(-336F, 2132F)); - builder.AddCubicBezier(new Vector2(-336F, 2132F), new Vector2(2316F, 2132F), new Vector2(2316F, 2132F)); - builder.AddCubicBezier(new Vector2(2316F, 2132F), new Vector2(2316F, -196F), new Vector2(2316F, -196F)); + builder.BeginFigure(new Vector2(289.5F, -24.5F)); + builder.AddCubicBezier(new Vector2(289.5F, -24.5F), new Vector2(-42F, -24.5F), new Vector2(-42F, -24.5F)); + builder.AddCubicBezier(new Vector2(-42F, -24.5F), new Vector2(-42F, 266.5F), new Vector2(-42F, 266.5F)); + builder.AddCubicBezier(new Vector2(-42F, 266.5F), new Vector2(289.5F, 266.5F), new Vector2(289.5F, 266.5F)); + builder.AddCubicBezier(new Vector2(289.5F, 266.5F), new Vector2(289.5F, -24.5F), new Vector2(289.5F, -24.5F)); builder.EndFigure(CanvasFigureLoop.Closed); result = CanvasGeometry.CreatePath(builder); } @@ -264,11 +336,11 @@ CanvasGeometry Geometry_3() CanvasGeometry result; using (var builder = new CanvasPathBuilder(null)) { - builder.BeginFigure(new Vector2(2316F, -196F)); - builder.AddCubicBezier(new Vector2(2316F, -196F), new Vector2(-336F, -196F), new Vector2(-336F, -196F)); - builder.AddCubicBezier(new Vector2(-336F, -196F), new Vector2(-336F, 1532F), new Vector2(-336F, 1532F)); - builder.AddCubicBezier(new Vector2(-336F, 1532F), new Vector2(2316F, 1532F), new Vector2(2316F, 1532F)); - builder.AddCubicBezier(new Vector2(2316F, 1532F), new Vector2(2316F, -196F), new Vector2(2316F, -196F)); + builder.BeginFigure(new Vector2(289.5F, -24.5F)); + builder.AddCubicBezier(new Vector2(289.5F, -24.5F), new Vector2(-42F, -24.5F), new Vector2(-42F, -24.5F)); + builder.AddCubicBezier(new Vector2(-42F, -24.5F), new Vector2(-42F, 191.5F), new Vector2(-42F, 191.5F)); + builder.AddCubicBezier(new Vector2(-42F, 191.5F), new Vector2(289.5F, 191.5F), new Vector2(289.5F, 191.5F)); + builder.AddCubicBezier(new Vector2(289.5F, 191.5F), new Vector2(289.5F, -24.5F), new Vector2(289.5F, -24.5F)); builder.EndFigure(CanvasFigureLoop.Closed); result = CanvasGeometry.CreatePath(builder); } @@ -283,11 +355,11 @@ CanvasGeometry Geometry_4() CanvasGeometry result; using (var builder = new CanvasPathBuilder(null)) { - builder.BeginFigure(new Vector2(2316F, -196F)); - builder.AddCubicBezier(new Vector2(2316F, -196F), new Vector2(-336F, -196F), new Vector2(-336F, -196F)); - builder.AddCubicBezier(new Vector2(-336F, -196F), new Vector2(-336F, 1432F), new Vector2(-336F, 1432F)); - builder.AddCubicBezier(new Vector2(-336F, 1432F), new Vector2(2316F, 1432F), new Vector2(2316F, 1432F)); - builder.AddCubicBezier(new Vector2(2316F, 1432F), new Vector2(2316F, -196F), new Vector2(2316F, -196F)); + builder.BeginFigure(new Vector2(289.5F, -24.5F)); + builder.AddCubicBezier(new Vector2(289.5F, -24.5F), new Vector2(-42F, -24.5F), new Vector2(-42F, -24.5F)); + builder.AddCubicBezier(new Vector2(-42F, -24.5F), new Vector2(-42F, 179F), new Vector2(-42F, 179F)); + builder.AddCubicBezier(new Vector2(-42F, 179F), new Vector2(289.5F, 179F), new Vector2(289.5F, 179F)); + builder.AddCubicBezier(new Vector2(289.5F, 179F), new Vector2(289.5F, -24.5F), new Vector2(289.5F, -24.5F)); builder.EndFigure(CanvasFigureLoop.Closed); result = CanvasGeometry.CreatePath(builder); } @@ -314,11 +386,13 @@ CompositionColorBrush ColorBrush_Black() return _c.CreateColorBrush(Color.FromArgb(0xFF, 0x00, 0x00, 0x00)); } - CompositionColorBrush ColorBrush_White() + // Color bound to theme property value: Color_FFFFFF + CompositionColorBrush ThemeColor_Color_FFFFFF() { - return (_colorBrush_White == null) - ? _colorBrush_White = _c.CreateColorBrush(InnerLauncherConfig.IsAppThemeLight ? Color.FromArgb(0xFF, 0xFF, 0xFF, 0xFF) : Color.FromArgb(0xFF, 0x00, 0x00, 0x00)) - : _colorBrush_White; + if (_themeColor_Color_FFFFFF != null) { return _themeColor_Color_FFFFFF; } + var result = _themeColor_Color_FFFFFF = _c.CreateColorBrush(); + BindProperty(_themeColor_Color_FFFFFF, "Color", "ColorRGB(_theme.Color_FFFFFF.W,_theme.Color_FFFFFF.X,_theme.Color_FFFFFF.Y,_theme.Color_FFFFFF.Z)", "_theme", _themeProperties); + return result; } CompositionContainerShape ContainerShape_0() @@ -326,7 +400,9 @@ CompositionContainerShape ContainerShape_0() if (_containerShape_0 != null) { return _containerShape_0; } var result = _containerShape_0 = _c.CreateContainerShape(); var propertySet = result.Properties; - propertySet.InsertVector2("Position", new Vector2(1024F, 1025F)); + propertySet.InsertVector2("Position", new Vector2(128F, 128.125F)); + result.CenterPoint = new Vector2(50F, 50F); + result.Scale = new Vector2(0.125F, 0.125F); // Transforms: Shape Layer 1 Offset:<50, 50> result.Shapes.Add(SpriteShape_0()); BindProperty(_containerShape_0, "Offset", "Vector2(my.Position.X-50,my.Position.Y-50)", "my", _containerShape_0); @@ -338,7 +414,9 @@ CompositionContainerShape ContainerShape_1() if (_containerShape_1 != null) { return _containerShape_1; } var result = _containerShape_1 = _c.CreateContainerShape(); var propertySet = result.Properties; - propertySet.InsertVector2("Position", new Vector2(1024F, 1025F)); + propertySet.InsertVector2("Position", new Vector2(128F, 128.125F)); + result.CenterPoint = new Vector2(50F, 50F); + result.Scale = new Vector2(0.125F, 0.125F); // Transforms: Shape Layer 2 Offset:<50, 50> result.Shapes.Add(SpriteShape_1()); BindProperty(_containerShape_1, "Offset", "Vector2(my.Position.X-50,my.Position.Y-50)", "my", _containerShape_1); @@ -350,8 +428,9 @@ CompositionContainerShape ContainerShape_2() if (_containerShape_2 != null) { return _containerShape_2; } var result = _containerShape_2 = _c.CreateContainerShape(); var propertySet = result.Properties; - propertySet.InsertVector2("Position", new Vector2(1024F, 1264F)); + propertySet.InsertVector2("Position", new Vector2(128F, 179.125F)); result.CenterPoint = new Vector2(4F, 344F); + result.Scale = new Vector2(0.125F, 0.125F); // ShapeGroup: Shape 1 result.Shapes.Add(SpriteShape_3()); BindProperty(_containerShape_2, "Offset", "Vector2(my.Position.X-4,my.Position.Y-344)", "my", _containerShape_2); @@ -433,7 +512,7 @@ CompositionSpriteShape SpriteShape_0() { // Offset:<50, 50> var result = CreateSpriteShape(PathGeometry_0(), new Matrix3x2(1F, 0F, 0F, 1F, 50F, 50F));; - result.StrokeBrush = ColorBrush_White(); + result.StrokeBrush = ThemeColor_Color_FFFFFF(); result.StrokeDashCap = CompositionStrokeCap.Round; result.StrokeStartCap = CompositionStrokeCap.Round; result.StrokeEndCap = CompositionStrokeCap.Round; @@ -448,7 +527,7 @@ CompositionSpriteShape SpriteShape_1() { // Offset:<50, 50> var result = CreateSpriteShape(PathGeometry_1(), new Matrix3x2(1F, 0F, 0F, 1F, 50F, 50F));; - result.StrokeBrush = ColorBrush_White(); + result.StrokeBrush = ThemeColor_Color_FFFFFF(); result.StrokeDashCap = CompositionStrokeCap.Round; result.StrokeStartCap = CompositionStrokeCap.Round; result.StrokeEndCap = CompositionStrokeCap.Round; @@ -464,7 +543,7 @@ CompositionSpriteShape SpriteShape_2() { if (_spriteShape_2 != null) { return _spriteShape_2; } var result = _spriteShape_2 = _c.CreateSpriteShape(PathGeometry_2()); - result.CenterPoint = new Vector2(1024F, 1024F); + result.CenterPoint = new Vector2(128F, 128F); result.FillBrush = ColorBrush_Black(); return result; } @@ -473,7 +552,7 @@ CompositionSpriteShape SpriteShape_2() CompositionSpriteShape SpriteShape_3() { var result = _c.CreateSpriteShape(PathGeometry_3()); - result.StrokeBrush = ColorBrush_White(); + result.StrokeBrush = ThemeColor_Color_FFFFFF(); result.StrokeDashCap = CompositionStrokeCap.Round; result.StrokeStartCap = CompositionStrokeCap.Round; result.StrokeEndCap = CompositionStrokeCap.Round; @@ -500,7 +579,7 @@ CompositionVisualSurface VisualSurface_0() { var result = _c.CreateVisualSurface(); result.SourceVisual = ContainerVisual_0(); - result.SourceSize = new Vector2(2048F, 2048F); + result.SourceSize = new Vector2(256F, 256F); return result; } @@ -509,7 +588,7 @@ CompositionVisualSurface VisualSurface_1() { var result = _c.CreateVisualSurface(); result.SourceVisual = ContainerVisual_3(); - result.SourceSize = new Vector2(2048F, 2048F); + result.SourceSize = new Vector2(256F, 256F); return result; } @@ -529,7 +608,7 @@ ContainerVisual ContainerVisual_1() { if (_containerVisual_1 != null) { return _containerVisual_1; } var result = _containerVisual_1 = _c.CreateContainerVisual(); - result.CenterPoint = new Vector3(1024F, 1024F, 0F); + result.CenterPoint = new Vector3(128F, 128F, 0F); result.Scale = new Vector3(1F, 1F, 0F); // Transforms for DownloadIcon result.Children.InsertAtTop(ContainerVisual_2()); @@ -543,7 +622,7 @@ ContainerVisual ContainerVisual_2() { var result = _c.CreateContainerVisual(); result.Clip = InsetClip_0(); - result.Size = new Vector2(2048F, 2048F); + result.Size = new Vector2(256F, 256F); // Layer aggregator result.Children.InsertAtTop(ShapeVisual_0()); return result; @@ -627,43 +706,43 @@ ScalarKeyFrameAnimation OpacityScalarAnimation_1_to_0() } // Position.Y - ScalarKeyFrameAnimation PositionYScalarAnimation_1025_to_2350() + ScalarKeyFrameAnimation PositionYScalarAnimation_128p125_to_293p75() { // Frame 0. - if (_positionYScalarAnimation_1025_to_2350 != null) { return _positionYScalarAnimation_1025_to_2350; } - var result = _positionYScalarAnimation_1025_to_2350 = CreateScalarKeyFrameAnimation(0F, 1025F, StepThenHoldEasingFunction()); + if (_positionYScalarAnimation_128p125_to_293p75 != null) { return _positionYScalarAnimation_128p125_to_293p75; } + var result = _positionYScalarAnimation_128p125_to_293p75 = CreateScalarKeyFrameAnimation(0F, 128.125F, StepThenHoldEasingFunction()); // Frame 50. - result.InsertKeyFrame(0.166666672F, 1025F, HoldThenStepEasingFunction()); + result.InsertKeyFrame(0.166666672F, 128.125F, HoldThenStepEasingFunction()); // Frame 90. - result.InsertKeyFrame(0.300000012F, 1009F, CubicBezierEasingFunction_0()); + result.InsertKeyFrame(0.300000012F, 126.125F, CubicBezierEasingFunction_0()); // Frame 165. - result.InsertKeyFrame(0.550000012F, 1009F, CubicBezierEasingFunction_0()); + result.InsertKeyFrame(0.550000012F, 126.125F, CubicBezierEasingFunction_0()); // Frame 200. - result.InsertKeyFrame(0.666666687F, 876F, CubicBezierEasingFunction_0()); + result.InsertKeyFrame(0.666666687F, 109.5F, CubicBezierEasingFunction_0()); // Frame 210. - result.InsertKeyFrame(0.699999988F, 876F, _c.CreateCubicBezierEasingFunction(new Vector2(0.333000004F, 0F), new Vector2(0.167999998F, 1F))); + result.InsertKeyFrame(0.699999988F, 109.5F, _c.CreateCubicBezierEasingFunction(new Vector2(0.333000004F, 0F), new Vector2(0.167999998F, 1F))); // Frame 255. - result.InsertKeyFrame(0.850000024F, 2350F, CubicBezierEasingFunction_0()); + result.InsertKeyFrame(0.850000024F, 293.75F, CubicBezierEasingFunction_0()); return result; } // Position.Y - ScalarKeyFrameAnimation PositionYScalarAnimation_1264_to_1433() + ScalarKeyFrameAnimation PositionYScalarAnimation_179p125_to_179p125() { // Frame 0. - var result = CreateScalarKeyFrameAnimation(0F, 1264F, StepThenHoldEasingFunction()); + var result = CreateScalarKeyFrameAnimation(0F, 179.125F, StepThenHoldEasingFunction()); // Frame 30. - result.InsertKeyFrame(0.100000001F, 1264F, HoldThenStepEasingFunction()); + result.InsertKeyFrame(0.100000001F, 179.125F, HoldThenStepEasingFunction()); // Frame 70. - result.InsertKeyFrame(0.233333334F, 1433F, CubicBezierEasingFunction_0()); + result.InsertKeyFrame(0.233333334F, 179.125F, CubicBezierEasingFunction_0()); // Frame 167. - result.InsertKeyFrame(0.556666672F, 1433F, _c.CreateCubicBezierEasingFunction(new Vector2(0.157000005F, 0F), new Vector2(0.0299999993F, 1F))); + result.InsertKeyFrame(0.556666672F, 179.125F, _c.CreateCubicBezierEasingFunction(new Vector2(0.157000005F, 0F), new Vector2(0.0299999993F, 1F))); // Frame 188. - result.InsertKeyFrame(0.626666665F, 1577F, CubicBezierEasingFunction_0()); + result.InsertKeyFrame(0.626666665F, 197.125F, CubicBezierEasingFunction_0()); // Frame 210. - result.InsertKeyFrame(0.699999988F, 1577F, CubicBezierEasingFunction_0()); + result.InsertKeyFrame(0.699999988F, 197.125F, CubicBezierEasingFunction_0()); // Frame 240. - result.InsertKeyFrame(0.800000012F, 1433F, CubicBezierEasingFunction_0()); + result.InsertKeyFrame(0.800000012F, 179.125F, CubicBezierEasingFunction_0()); return result; } @@ -785,7 +864,7 @@ ScalarKeyFrameAnimation TStartScalarAnimation_0p855_to_0() ShapeVisual ShapeVisual_0() { var result = _c.CreateShapeVisual(); - result.Size = new Vector2(2048F, 2048F); + result.Size = new Vector2(256F, 256F); var shapes = result.Shapes; shapes.Add(ContainerShape_0()); shapes.Add(ContainerShape_1()); @@ -797,7 +876,7 @@ ShapeVisual ShapeVisual_0() ShapeVisual ShapeVisual_1() { var result = _c.CreateShapeVisual(); - result.Size = new Vector2(2048F, 2048F); + result.Size = new Vector2(256F, 256F); result.Shapes.Add(SpriteShape_2()); return result; } @@ -807,7 +886,7 @@ ShapeVisual ShapeVisual_2() { if (_shapeVisual_2 != null) { return _shapeVisual_2; } var result = _shapeVisual_2 = _c.CreateShapeVisual(); - result.Size = new Vector2(2048F, 2048F); + result.Size = new Vector2(256F, 256F); result.Shapes.Add(ContainerShape_2()); return result; } @@ -816,7 +895,7 @@ ShapeVisual ShapeVisual_2() SpriteVisual SpriteVisual_0() { var result = _c.CreateSpriteVisual(); - result.Size = new Vector2(2048F, 2048F); + result.Size = new Vector2(256F, 256F); result.Brush = EffectBrush(); return result; } @@ -838,25 +917,27 @@ StepEasingFunction StepThenHoldEasingFunction() } internal DownloadIcon_AnimatedVisual( - Compositor compositor + Compositor compositor, + CompositionPropertySet themeProperties ) { _c = compositor; + _themeProperties = themeProperties; _reusableExpressionAnimation = compositor.CreateExpressionAnimation(); Root(); } public Visual RootVisual => _root; public TimeSpan Duration => TimeSpan.FromTicks(c_durationTicks); - public Vector2 Size => new Vector2(2048F, 2048F); + public Vector2 Size => new Vector2(256F, 256F); void IDisposable.Dispose() => _root?.Dispose(); public void CreateAnimations() { - _containerShape_0.Properties.StartAnimation("Position.Y", PositionYScalarAnimation_1025_to_2350(), AnimationController_0()); - _containerShape_1.Properties.StartAnimation("Position.Y", PositionYScalarAnimation_1025_to_2350(), AnimationController_0()); + _containerShape_0.Properties.StartAnimation("Position.Y", PositionYScalarAnimation_128p125_to_293p75(), AnimationController_0()); + _containerShape_1.Properties.StartAnimation("Position.Y", PositionYScalarAnimation_128p125_to_293p75(), AnimationController_0()); _containerShape_2.StartAnimation("RotationAngleInDegrees", RotationAngleInDegreesScalarAnimation_0_to_0_1(), AnimationController_0()); - _containerShape_2.Properties.StartAnimation("Position.Y", PositionYScalarAnimation_1264_to_1433(), AnimationController_0()); + _containerShape_2.Properties.StartAnimation("Position.Y", PositionYScalarAnimation_179p125_to_179p125(), AnimationController_0()); _pathGeometry_0.StartAnimation("TStart", TStartScalarAnimation_0p855_to_0(), AnimationController_0()); _pathGeometry_0.StartAnimation("TEnd", TEndScalarAnimation_0p855_to_0p1(), AnimationController_0()); _pathGeometry_1.StartAnimation("TrimStart", TrimStartScalarAnimation_0p585_to_0(), AnimationController_0()); diff --git a/CollapseLauncher/Classes/AnimatedVisuals/Lottie/DownloadIcon.json b/CollapseLauncher/Classes/AnimatedVisuals/Lottie/DownloadIcon.json new file mode 100644 index 000000000..2810c9899 --- /dev/null +++ b/CollapseLauncher/Classes/AnimatedVisuals/Lottie/DownloadIcon.json @@ -0,0 +1 @@ +{"v":"5.12.2","fr":60,"ip":0,"op":300,"w":256,"h":256,"nm":"DownloadIconMasterComp","ddd":0,"assets":[{"id":"comp_0","nm":"DownloadIcon","fr":60,"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 2","parent":3,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[50,50,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[360.517,-180.5],[0,180.017],[-360.517,-180.5]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":128,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":53,"s":[58.5]},{"t":83,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":53,"s":[58.5]},{"t":83,"s":[58.5]}],"ix":2},"o":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":53,"s":[-101.6]},{"t":83,"s":[0]}],"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":300,"st":-7,"ct":1,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Shape Layer 1","parent":3,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[50,50,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,-459.501],[-459.501,0],[0,459.501],[0,0]],"o":[[0,0],[-459.501,0],[0,459.501],[459.501,0],[0,-459.501],[0,0]],"v":[[0,116],[0,-832],[-832,0],[0,832],[832,0],[515,-688]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":128,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[85.5]},{"t":60,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[85.5]},{"t":80,"s":[10]}],"ix":2},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":30,"s":[0]},{"t":60,"s":[0]}],"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":300,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":3,"nm":"Null 1","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"s":true,"x":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":50,"s":[128]},{"t":90,"s":[128]}],"ix":3},"y":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":50,"s":[128.125]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":90,"s":[126.125]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":165,"s":[126.125]},{"i":{"x":[0.168],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":200,"s":[109.5]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":210,"s":[109.5]},{"t":255,"s":[293.75]}],"ix":4}},"a":{"a":0,"k":[50,50,0],"ix":1,"l":2},"s":{"a":0,"k":[12.5,12.5,100],"ix":6,"l":2}},"ao":0,"ip":0,"op":300,"st":-10,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 3","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":260,"s":[100]},{"t":280,"s":[0]}],"ix":11},"r":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":140,"s":[0]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":150,"s":[8]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":167,"s":[-8]},{"t":184,"s":[0]}],"ix":10},"p":{"s":true,"x":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":30,"s":[128]},{"t":70,"s":[128]}],"ix":3},"y":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":30,"s":[179.125]},{"i":{"x":[0.03],"y":[1]},"o":{"x":[0.157],"y":[0]},"t":70,"s":[179.125]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":167,"s":[179.125]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":188,"s":[197.125]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":210,"s":[197.125]},{"t":240,"s":[179.125]}],"ix":4}},"a":{"a":0,"k":[4,344,0],"ix":1,"l":2},"s":{"a":0,"k":[12.5,12.5,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-460,344],[468,344]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":128,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":30,"s":[0]},{"i":{"x":[0.586],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":70,"s":[0]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":260,"s":[0]},{"t":280,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":30,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":70,"s":[100]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":260,"s":[100]},{"t":280,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":2,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":300,"st":-15,"ct":1,"bm":0},{"ddd":0,"ind":2,"ty":0,"nm":"DownloadIcon","refId":"comp_0","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":260,"s":[100]},{"t":280,"s":[0]}],"ix":11},"r":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":140,"s":[0]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":150,"s":[-9]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":160,"s":[11]},{"t":179,"s":[0]}],"ix":10},"p":{"s":true,"x":{"a":0,"k":128,"ix":3},"y":{"a":0,"k":128,"ix":4}},"a":{"a":0,"k":[128,128,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"hasMask":true,"masksProperties":[{"inv":false,"mode":"a","pt":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":150,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[289.5,-24.5],[-42,-24.5],[-42,266.5],[289.5,266.5]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":189,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[289.5,-24.5],[-42,-24.5],[-42,191.5],[289.5,191.5]],"c":true}]},{"t":230,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[289.5,-24.5],[-42,-24.5],[-42,179],[289.5,179]],"c":true}]}],"ix":1},"o":{"a":0,"k":100,"ix":3},"x":{"a":0,"k":0,"ix":4},"nm":"Mask 1"}],"w":256,"h":256,"ip":0,"op":300,"st":0,"bm":0}],"markers":[],"props":{}} \ No newline at end of file diff --git a/CollapseLauncher/Classes/AnimatedVisuals/Lottie/DownloadIcon.lottie b/CollapseLauncher/Classes/AnimatedVisuals/Lottie/DownloadIcon.lottie deleted file mode 100644 index d40ef8c19..000000000 Binary files a/CollapseLauncher/Classes/AnimatedVisuals/Lottie/DownloadIcon.lottie and /dev/null differ diff --git a/CollapseLauncher/Classes/AnimatedVisuals/Lottie/LoadingSprite.cs b/CollapseLauncher/Classes/AnimatedVisuals/Lottie/LoadingSprite.cs index 3d1e74178..45c1ba614 100644 --- a/CollapseLauncher/Classes/AnimatedVisuals/Lottie/LoadingSprite.cs +++ b/CollapseLauncher/Classes/AnimatedVisuals/Lottie/LoadingSprite.cs @@ -3,13 +3,13 @@ // This code was generated by a tool. // // LottieGen version: -// 8.0.280225.1+7cd366a738 +// 8.2.250604.1+b02a3ee244 // // Command: -// LottieGen -Language CSharp -Namespace CollapseLauncher.AnimatedVisuals.Lottie -Public -WinUIVersion 3.0 -InputFile LoadingSprite.lottie +// LottieGen -GenerateColorBindings -GenerateDependencyObject -Language CSharp -Namespace CollapseLauncher.AnimatedVisuals.Lottie -Public -WinUIVersion 3.0 -InputFile LoadingSprite.json // // Input file: -// LoadingSprite.lottie (1342 bytes created 20:17+07:00 May 23 2024) +// LoadingSprite.json (5570 bytes created 16:59+07:00 Jan 4 2026) // // LottieGen source: // http://aka.ms/Lottie @@ -21,16 +21,16 @@ // ____________________________________ // | Object stats | Count | // |__________________________|_______| -// | All CompositionObjects | 92 | +// | All CompositionObjects | 97 | // |--------------------------+-------| -// | Expression animators | 6 | +// | Expression animators | 8 | // | KeyFrame animators | 17 | -// | Reference parameters | 6 | -// | Expression operations | 0 | +// | Reference parameters | 8 | +// | Expression operations | 8 | // |--------------------------+-------| -// | Animated brushes | - | +// | Animated brushes | 2 | // | Animated gradient stops | - | -// | ExpressionAnimations | 6 | +// | ExpressionAnimations | 8 | // | PathKeyFrameAnimations | - | // |--------------------------+-------| // | ContainerVisuals | 1 | @@ -44,6 +44,7 @@ // | CompositionVisualSurface | - | // ------------------------------------ using Microsoft.UI.Composition; +using Microsoft.UI.Xaml; using System; using System.Collections.Generic; using System.Numerics; @@ -55,13 +56,72 @@ namespace CollapseLauncher.AnimatedVisuals.Lottie // Frame rate: 60 fps // Frame count: 180 // Duration: 3000.0 mS - sealed partial class LoadingSprite - : Microsoft.UI.Xaml.Controls.IAnimatedVisualSource + public sealed partial class LoadingSprite : + DependencyObject + , Microsoft.UI.Xaml.Controls.IAnimatedVisualSource , Microsoft.UI.Xaml.Controls.IAnimatedVisualSource2 { // Animation duration: 3.000 seconds. internal const long c_durationTicks = 30000000; + // Theme property: Color_000000. + internal static readonly Color c_themeColor_000000 = Color.FromArgb(0xFF, 0x00, 0x00, 0x00); + + // Theme property: Color_FFFFFF. + internal static readonly Color c_themeColor_FFFFFF = Color.FromArgb(0xFF, 0xFF, 0xFF, 0xFF); + + CompositionPropertySet _themeProperties; + + /// + /// Dependency property for Color_000000. + /// + public static readonly DependencyProperty Color_000000Property = + DependencyProperty.Register("Color_000000", typeof(Color), typeof(LoadingSprite), + new PropertyMetadata(Color.FromArgb(0xFF, 0x00, 0x00, 0x00), OnColor_000000Changed)); + + /// + /// Dependency property for Color_FFFFFF. + /// + public static readonly DependencyProperty Color_FFFFFFProperty = + DependencyProperty.Register("Color_FFFFFF", typeof(Color), typeof(LoadingSprite), + new PropertyMetadata(Color.FromArgb(0xFF, 0xFF, 0xFF, 0xFF), OnColor_FFFFFFChanged)); + + // Theme properties. + public Color Color_000000 + { + get => (Color)GetValue(Color_000000Property); + set => SetValue(Color_000000Property, value); + } + + public Color Color_FFFFFF + { + get => (Color)GetValue(Color_FFFFFFProperty); + set => SetValue(Color_FFFFFFProperty, value); + } + + static Vector4 ColorAsVector4(Color color) => new Vector4(color.R, color.G, color.B, color.A); + + static void OnColor_000000Changed(DependencyObject d, DependencyPropertyChangedEventArgs args) + { + ((LoadingSprite)d)._themeProperties?.InsertVector4("Color_000000", ColorAsVector4((Color)(Color)args.NewValue)); + } + + static void OnColor_FFFFFFChanged(DependencyObject d, DependencyPropertyChangedEventArgs args) + { + ((LoadingSprite)d)._themeProperties?.InsertVector4("Color_FFFFFF", ColorAsVector4((Color)(Color)args.NewValue)); + } + + CompositionPropertySet EnsureThemeProperties(Compositor compositor) + { + if (_themeProperties == null) + { + _themeProperties = compositor.CreatePropertySet(); + _themeProperties.InsertVector4("Color_000000", ColorAsVector4((Color)Color_000000)); + _themeProperties.InsertVector4("Color_FFFFFF", ColorAsVector4((Color)Color_FFFFFF)); + } + return _themeProperties; + } + public Microsoft.UI.Xaml.Controls.IAnimatedVisual TryCreateAnimatedVisual(Compositor compositor) { object ignored = null; @@ -71,10 +131,12 @@ public Microsoft.UI.Xaml.Controls.IAnimatedVisual TryCreateAnimatedVisual(Compos public Microsoft.UI.Xaml.Controls.IAnimatedVisual TryCreateAnimatedVisual(Compositor compositor, out object diagnostics) { diagnostics = null; + EnsureThemeProperties(compositor); var res = new LoadingSprite_AnimatedVisual( - compositor + compositor, + _themeProperties ); res.CreateAnimations(); return res; @@ -118,6 +180,23 @@ public double FrameToProgress(double frameNumber) /// public void SetColorProperty(string propertyName, Color value) { + if (propertyName == "Color_000000") + { + Color_000000 = value; + } + else if (propertyName == "Color_FFFFFF") + { + Color_FFFFFF = value; + } + else + { + return; + } + + if (_themeProperties != null) + { + _themeProperties.InsertVector4(propertyName, ColorAsVector4(value)); + } } /// @@ -135,8 +214,10 @@ sealed partial class LoadingSprite_AnimatedVisual const long c_durationTicks = 30000000; readonly Compositor _c; readonly ExpressionAnimation _reusableExpressionAnimation; + readonly CompositionPropertySet _themeProperties; AnimationController _animationController_0; - CompositionColorBrush _colorBrush_White; + CompositionColorBrush _themeColor_Color_000000; + CompositionColorBrush _themeColor_Color_FFFFFF; CompositionContainerShape _containerShape_0; CompositionContainerShape _containerShape_1; CompositionContainerShape _containerShape_2; @@ -150,9 +231,9 @@ sealed partial class LoadingSprite_AnimatedVisual CubicBezierEasingFunction _cubicBezierEasingFunction_2; CubicBezierEasingFunction _cubicBezierEasingFunction_3; CubicBezierEasingFunction _cubicBezierEasingFunction_4; - ScalarKeyFrameAnimation _scalarAnimation_0p85_to_1; - ScalarKeyFrameAnimation _scalarAnimation_1_to_1_0; - ScalarKeyFrameAnimation _scalarAnimation_1_to_1_1; + ScalarKeyFrameAnimation _scalarAnimation_0p2_to_0p2_0; + ScalarKeyFrameAnimation _scalarAnimation_0p2_to_0p2_1; + ScalarKeyFrameAnimation _scalarAnimation_0p17_to_0p2; StepEasingFunction _holdThenStepEasingFunction; StepEasingFunction _stepThenHoldEasingFunction; @@ -211,16 +292,22 @@ AnimationController AnimationController_0() // - - Layer aggregator // ShapeGroup: Rectangle 1 Offset:<-2.5, -4> - CompositionColorBrush ColorBrush_SemiTransparentBlack() + // Color bound to theme property value: Color_000000 + CompositionColorBrush ThemeColor_Color_000000() { - return _c.CreateColorBrush(Color.FromArgb(0x4C, 0x00, 0x00, 0x00)); + if (_themeColor_Color_000000 != null) { return _themeColor_Color_000000; } + var result = _themeColor_Color_000000 = _c.CreateColorBrush(); + BindProperty(_themeColor_Color_000000, "Color", "ColorRGB(_theme.Color_000000.W*0.3,_theme.Color_000000.X,_theme.Color_000000.Y,_theme.Color_000000.Z)", "_theme", _themeProperties); + return result; } - CompositionColorBrush ColorBrush_White() + // Color bound to theme property value: Color_FFFFFF + CompositionColorBrush ThemeColor_Color_FFFFFF() { - return (_colorBrush_White == null) - ? _colorBrush_White = _c.CreateColorBrush(Color.FromArgb(0xFF, 0xFF, 0xFF, 0xFF)) - : _colorBrush_White; + if (_themeColor_Color_FFFFFF != null) { return _themeColor_Color_FFFFFF; } + var result = _themeColor_Color_FFFFFF = _c.CreateColorBrush(); + BindProperty(_themeColor_Color_FFFFFF, "Color", "ColorRGB(_theme.Color_FFFFFF.W,_theme.Color_FFFFFF.X,_theme.Color_FFFFFF.Y,_theme.Color_FFFFFF.Z)", "_theme", _themeProperties); + return result; } // Layer aggregator @@ -229,7 +316,7 @@ CompositionContainerShape ContainerShape_0() if (_containerShape_0 != null) { return _containerShape_0; } var result = _containerShape_0 = _c.CreateContainerShape(); result.CenterPoint = new Vector2(-2.5F, -4F); - result.Offset = new Vector2(322.5F, 324F); + result.Offset = new Vector2(66.5F, 68F); // ShapeGroup: Rectangle 1 Offset:<-2.5, -4> result.Shapes.Add(SpriteShape_0()); return result; @@ -241,7 +328,7 @@ CompositionContainerShape ContainerShape_1() if (_containerShape_1 != null) { return _containerShape_1; } var result = _containerShape_1 = _c.CreateContainerShape(); result.CenterPoint = new Vector2(15.75F, 4.75F); - result.Offset = new Vector2(304.25F, 315.25F); + result.Offset = new Vector2(48.25F, 59.25F); // ShapeGroup: Ellipse 1 Offset:<15.75, 4.75> result.Shapes.Add(SpriteShape_1()); return result; @@ -265,7 +352,7 @@ CompositionContainerShape ContainerShape_3() if (_containerShape_3 != null) { return _containerShape_3; } var result = _containerShape_3 = _c.CreateContainerShape(); result.CenterPoint = new Vector2(15.75F, 4.75F); - result.Offset = new Vector2(304.25F, 315.25F); + result.Offset = new Vector2(48.25F, 59.25F); // ShapeGroup: Ellipse 1 Offset:<15.75, 4.75> result.Shapes.Add(SpriteShape_2()); return result; @@ -319,7 +406,7 @@ CompositionSpriteShape SpriteShape_0() { // Offset:<-2.5, -4> var geometry = RoundedRectangle_291(); - var result = CreateSpriteShape(geometry, new Matrix3x2(1F, 0F, 0F, 1F, -2.5F, -4F), ColorBrush_SemiTransparentBlack());; + var result = CreateSpriteShape(geometry, new Matrix3x2(1F, 0F, 0F, 1F, -2.5F, -4F), ThemeColor_Color_000000());; return result; } @@ -329,7 +416,7 @@ CompositionSpriteShape SpriteShape_1() { // Offset:<15.75, 4.75> var result = CreateSpriteShape(Ellipse_84p25_0(), new Matrix3x2(1F, 0F, 0F, 1F, 15.75F, 4.75F));; - result.StrokeBrush = ColorBrush_White(); + result.StrokeBrush = ThemeColor_Color_FFFFFF(); result.StrokeDashCap = CompositionStrokeCap.Round; result.StrokeStartCap = CompositionStrokeCap.Round; result.StrokeEndCap = CompositionStrokeCap.Round; @@ -344,7 +431,7 @@ CompositionSpriteShape SpriteShape_2() { // Offset:<15.75, 4.75> var result = CreateSpriteShape(Ellipse_84p25_1(), new Matrix3x2(1F, 0F, 0F, 1F, 15.75F, 4.75F));; - result.StrokeBrush = ColorBrush_White(); + result.StrokeBrush = ThemeColor_Color_FFFFFF(); result.StrokeDashCap = CompositionStrokeCap.Round; result.StrokeStartCap = CompositionStrokeCap.Round; result.StrokeEndCap = CompositionStrokeCap.Round; @@ -455,47 +542,47 @@ ScalarKeyFrameAnimation RoundnessScalarAnimation_25_to_25() } // Scale - ScalarKeyFrameAnimation ScalarAnimation_0p85_to_1() + ScalarKeyFrameAnimation ScalarAnimation_0p2_to_0p2_0() { // Frame 0. - if (_scalarAnimation_0p85_to_1 != null) { return _scalarAnimation_0p85_to_1; } - var result = _scalarAnimation_0p85_to_1 = CreateScalarKeyFrameAnimation(0F, 0.850000024F, StepThenHoldEasingFunction()); - // Frame 100. - result.InsertKeyFrame(0.555555582F, 0.850000024F, HoldThenStepEasingFunction()); - // Frame 120. - result.InsertKeyFrame(0.666666687F, 1F, CubicBezierEasingFunction_0()); + if (_scalarAnimation_0p2_to_0p2_0 != null) { return _scalarAnimation_0p2_to_0p2_0; } + var result = _scalarAnimation_0p2_to_0p2_0 = CreateScalarKeyFrameAnimation(0F, 0.200000003F, StepThenHoldEasingFunction()); + // Frame 10. + result.InsertKeyFrame(0.055555556F, 0.200000003F, HoldThenStepEasingFunction()); + // Frame 30. + result.InsertKeyFrame(0.166666672F, 0.150000006F, CubicBezierEasingFunction_0()); + // Frame 90. + result.InsertKeyFrame(0.5F, 0.150000006F, _c.CreateCubicBezierEasingFunction(new Vector2(0.166999996F, 0F), new Vector2(0.666999996F, 1F))); + // Frame 110. + result.InsertKeyFrame(0.611111104F, 0.200000003F, _c.CreateCubicBezierEasingFunction(new Vector2(0.333000004F, 0F), new Vector2(0.666999996F, 1F))); return result; } // Scale - ScalarKeyFrameAnimation ScalarAnimation_1_to_1_0() + ScalarKeyFrameAnimation ScalarAnimation_0p2_to_0p2_1() { // Frame 0. - if (_scalarAnimation_1_to_1_0 != null) { return _scalarAnimation_1_to_1_0; } - var result = _scalarAnimation_1_to_1_0 = CreateScalarKeyFrameAnimation(0F, 1F, StepThenHoldEasingFunction()); - // Frame 10. - result.InsertKeyFrame(0.055555556F, 1F, HoldThenStepEasingFunction()); - // Frame 30. - result.InsertKeyFrame(0.166666672F, 0.75F, CubicBezierEasingFunction_0()); + if (_scalarAnimation_0p2_to_0p2_1 != null) { return _scalarAnimation_0p2_to_0p2_1; } + var result = _scalarAnimation_0p2_to_0p2_1 = CreateScalarKeyFrameAnimation(0F, 0.200000003F, HoldThenStepEasingFunction()); + // Frame 20. + result.InsertKeyFrame(0.111111112F, 0.170000002F, _c.CreateCubicBezierEasingFunction(new Vector2(0.333000004F, 0F), new Vector2(0.833000004F, 0.833000004F))); // Frame 90. - result.InsertKeyFrame(0.5F, 0.75F, _c.CreateCubicBezierEasingFunction(new Vector2(0.166999996F, 0F), new Vector2(0.666999996F, 1F))); + result.InsertKeyFrame(0.5F, 0.170000002F, _c.CreateCubicBezierEasingFunction(new Vector2(0.166999996F, 0F), new Vector2(0.460000008F, 1F))); // Frame 110. - result.InsertKeyFrame(0.611111104F, 1F, _c.CreateCubicBezierEasingFunction(new Vector2(0.333000004F, 0F), new Vector2(0.666999996F, 1F))); + result.InsertKeyFrame(0.611111104F, 0.200000003F, CubicBezierEasingFunction_0()); return result; } // Scale - ScalarKeyFrameAnimation ScalarAnimation_1_to_1_1() + ScalarKeyFrameAnimation ScalarAnimation_0p17_to_0p2() { // Frame 0. - if (_scalarAnimation_1_to_1_1 != null) { return _scalarAnimation_1_to_1_1; } - var result = _scalarAnimation_1_to_1_1 = CreateScalarKeyFrameAnimation(0F, 1F, HoldThenStepEasingFunction()); - // Frame 20. - result.InsertKeyFrame(0.111111112F, 0.850000024F, _c.CreateCubicBezierEasingFunction(new Vector2(0.333000004F, 0F), new Vector2(0.833000004F, 0.833000004F))); - // Frame 90. - result.InsertKeyFrame(0.5F, 0.850000024F, _c.CreateCubicBezierEasingFunction(new Vector2(0.166999996F, 0F), new Vector2(0.460000008F, 1F))); - // Frame 110. - result.InsertKeyFrame(0.611111104F, 1F, CubicBezierEasingFunction_0()); + if (_scalarAnimation_0p17_to_0p2 != null) { return _scalarAnimation_0p17_to_0p2; } + var result = _scalarAnimation_0p17_to_0p2 = CreateScalarKeyFrameAnimation(0F, 0.170000002F, StepThenHoldEasingFunction()); + // Frame 100. + result.InsertKeyFrame(0.555555582F, 0.170000002F, HoldThenStepEasingFunction()); + // Frame 120. + result.InsertKeyFrame(0.666666687F, 0.200000003F, CubicBezierEasingFunction_0()); return result; } @@ -587,7 +674,7 @@ ScalarKeyFrameAnimation TStartScalarAnimation_0_to_0p5_1() ShapeVisual ShapeVisual_0() { var result = _c.CreateShapeVisual(); - result.Size = new Vector2(640F, 640F); + result.Size = new Vector2(128F, 128F); var shapes = result.Shapes; shapes.Add(ContainerShape_0()); shapes.Add(ContainerShape_1()); @@ -624,31 +711,33 @@ Vector2KeyFrameAnimation ShapeVisibilityAnimation() } internal LoadingSprite_AnimatedVisual( - Compositor compositor + Compositor compositor, + CompositionPropertySet themeProperties ) { _c = compositor; + _themeProperties = themeProperties; _reusableExpressionAnimation = compositor.CreateExpressionAnimation(); Root(); } public Visual RootVisual => _root; public TimeSpan Duration => TimeSpan.FromTicks(c_durationTicks); - public Vector2 Size => new Vector2(640F, 640F); + public Vector2 Size => new Vector2(128F, 128F); void IDisposable.Dispose() => _root?.Dispose(); public void CreateAnimations() { _containerShape_0.StartAnimation("RotationAngleInDegrees", RotationAngleInDegreesScalarAnimation_45_to_135(), AnimationController_0()); - _containerShape_0.StartAnimation("Scale.X", ScalarAnimation_1_to_1_0(), AnimationController_0()); - _containerShape_0.StartAnimation("Scale.Y", ScalarAnimation_1_to_1_0(), AnimationController_0()); + _containerShape_0.StartAnimation("Scale.X", ScalarAnimation_0p2_to_0p2_0(), AnimationController_0()); + _containerShape_0.StartAnimation("Scale.Y", ScalarAnimation_0p2_to_0p2_0(), AnimationController_0()); _containerShape_1.StartAnimation("RotationAngleInDegrees", RotationAngleInDegreesScalarAnimation_180_to_900_0(), AnimationController_0()); - _containerShape_1.StartAnimation("Scale.X", ScalarAnimation_1_to_1_1(), AnimationController_0()); - _containerShape_1.StartAnimation("Scale.Y", ScalarAnimation_1_to_1_1(), AnimationController_0()); + _containerShape_1.StartAnimation("Scale.X", ScalarAnimation_0p2_to_0p2_1(), AnimationController_0()); + _containerShape_1.StartAnimation("Scale.Y", ScalarAnimation_0p2_to_0p2_1(), AnimationController_0()); _containerShape_2.StartAnimation("Scale", ShapeVisibilityAnimation(), AnimationController_0()); _containerShape_3.StartAnimation("RotationAngleInDegrees", RotationAngleInDegreesScalarAnimation_180_to_900_1(), AnimationController_0()); - _containerShape_3.StartAnimation("Scale.X", ScalarAnimation_0p85_to_1(), AnimationController_0()); - _containerShape_3.StartAnimation("Scale.Y", ScalarAnimation_0p85_to_1(), AnimationController_0()); + _containerShape_3.StartAnimation("Scale.X", ScalarAnimation_0p17_to_0p2(), AnimationController_0()); + _containerShape_3.StartAnimation("Scale.Y", ScalarAnimation_0p17_to_0p2(), AnimationController_0()); _ellipse_84p25_0.StartAnimation("TStart", TStartScalarAnimation_0_to_0p5_0(), AnimationController_0()); _ellipse_84p25_0.StartAnimation("TEnd", TEndScalarAnimation_0_to_0p5_0(), AnimationController_0()); _ellipse_84p25_0.StartAnimation("TrimOffset", TrimOffsetScalarAnimation_0_to_0p5_0(), AnimationController_0()); diff --git a/CollapseLauncher/Classes/AnimatedVisuals/Lottie/LoadingSprite.json b/CollapseLauncher/Classes/AnimatedVisuals/Lottie/LoadingSprite.json new file mode 100644 index 000000000..066b5ce05 --- /dev/null +++ b/CollapseLauncher/Classes/AnimatedVisuals/Lottie/LoadingSprite.json @@ -0,0 +1 @@ +{"v":"5.12.2","fr":60,"ip":0,"op":180,"w":128,"h":128,"nm":"LoadingSprite","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 4","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":90,"s":[180]},{"t":180,"s":[900]}],"ix":10},"p":{"a":0,"k":[64,64,0],"ix":2,"l":2},"a":{"a":0,"k":[15.75,4.75,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0,0,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":100,"s":[17,17,100]},{"t":120,"s":[20,20,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[168.5,168.5],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":26,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[15.75,4.75],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":90,"s":[0]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":120,"s":[50]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":150,"s":[50]},{"t":180,"s":[50]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":150,"s":[0]},{"t":180,"s":[50]}],"ix":2},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":120,"s":[0]},{"t":150,"s":[180]}],"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":90,"op":271,"st":90,"ct":1,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Shape Layer 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[180]},{"t":90,"s":[900]}],"ix":10},"p":{"a":0,"k":[64,64,0],"ix":2,"l":2},"a":{"a":0,"k":[15.75,4.75,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":0,"s":[20,20,100]},{"i":{"x":[0.46,0.46,0.667],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":20,"s":[17,17,100]},{"i":{"x":[0,0,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":90,"s":[17,17,100]},{"t":110,"s":[20,20,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[168.5,168.5],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":26,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[15.75,4.75],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[0]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":30,"s":[50]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":60,"s":[50]},{"t":90,"s":[50]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":60,"s":[0]},{"t":90,"s":[50]}],"ix":2},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":30,"s":[0]},{"t":60,"s":[180]}],"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":181,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Shape Layer 3","sr":1,"ks":{"o":{"a":0,"k":30,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[45]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":60,"s":[90]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":90,"s":[90]},{"t":150,"s":[135]}],"ix":10},"p":{"a":0,"k":[64,64,0],"ix":2,"l":2},"a":{"a":0,"k":[-2.5,-4,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0,0,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":10,"s":[20,20,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":30,"s":[15,15,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":90,"s":[15,15,100]},{"t":110,"s":[20,20,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[291,291],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[25]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":60,"s":[125]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":90,"s":[125]},{"t":150,"s":[25]}],"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-2.5,-4],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":182,"st":0,"ct":1,"bm":0}],"markers":[],"props":{}} \ No newline at end of file diff --git a/CollapseLauncher/Classes/AnimatedVisuals/Lottie/LoadingSprite.lottie b/CollapseLauncher/Classes/AnimatedVisuals/Lottie/LoadingSprite.lottie deleted file mode 100644 index 357515fa6..000000000 Binary files a/CollapseLauncher/Classes/AnimatedVisuals/Lottie/LoadingSprite.lottie and /dev/null differ diff --git a/CollapseLauncher/Classes/AnimatedVisuals/Lottie/StartGameIcon.cs b/CollapseLauncher/Classes/AnimatedVisuals/Lottie/StartGameIcon.cs index 8478138ac..fdbcf99b2 100644 --- a/CollapseLauncher/Classes/AnimatedVisuals/Lottie/StartGameIcon.cs +++ b/CollapseLauncher/Classes/AnimatedVisuals/Lottie/StartGameIcon.cs @@ -3,13 +3,13 @@ // This code was generated by a tool. // // LottieGen version: -// 8.0.280225.1+7cd366a738 +// 8.2.250604.1+b02a3ee244 // // Command: -// LottieGen -Language CSharp -Namespace CollapseLauncher.AnimatedVisuals.Lottie -Public -WinUIVersion 3.0 -InputFile StartGameIcon.lottie +// LottieGen -GenerateColorBindings -GenerateDependencyObject -Language CSharp -Namespace CollapseLauncher.AnimatedVisuals.Lottie -Public -WinUIVersion 3.0 -InputFile StartGameIcon.json // // Input file: -// StartGameIcon.lottie (1259 bytes created 0:25+07:00 Jun 2 2024) +// StartGameIcon.json (8234 bytes created 16:59+07:00 Jan 4 2026) // // LottieGen source: // http://aka.ms/Lottie @@ -21,16 +21,16 @@ // ____________________________________ // | Object stats | Count | // |__________________________|_______| -// | All CompositionObjects | 70 | +// | All CompositionObjects | 77 | // |--------------------------+-------| -// | Expression animators | 9 | +// | Expression animators | 12 | // | KeyFrame animators | 6 | -// | Reference parameters | 9 | -// | Expression operations | 6 | +// | Reference parameters | 15 | +// | Expression operations | 18 | // |--------------------------+-------| // | Animated brushes | 3 | // | Animated gradient stops | - | -// | ExpressionAnimations | 9 | +// | ExpressionAnimations | 12 | // | PathKeyFrameAnimations | - | // |--------------------------+-------| // | ContainerVisuals | 1 | @@ -44,6 +44,8 @@ // | CompositionVisualSurface | - | // ------------------------------------ using Microsoft.UI.Composition; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Media; using System; using System.Collections.Generic; using System.Numerics; @@ -55,13 +57,67 @@ namespace CollapseLauncher.AnimatedVisuals.Lottie // Frame rate: 60 fps // Frame count: 40 // Duration: 666.7 mS - sealed partial class StartGameIcon - : Microsoft.UI.Xaml.Controls.IAnimatedVisualSource + public sealed partial class StartGameIcon + : BindableThemeChangeAnimation + , Microsoft.UI.Xaml.Controls.IAnimatedVisualSource , Microsoft.UI.Xaml.Controls.IAnimatedVisualSource2 { + protected override void OnForegroundChanged(Brush brush) + { + if (brush is SolidColorBrush colorBrush) + { + Color_FFFFFF = colorBrush.Color; + return; + } + + if (brush is AcrylicBrush acrylicBrush) + { + Color_FFFFFF = acrylicBrush.TintColor; + return; + } + } + + private static Color GetForegroundColor(bool isLightTheme) => + isLightTheme + ? Color.FromArgb(0xFF, 0x00, 0x00, 0x00) + : Color.FromArgb(0xFF, 0xFF, 0xFF, 0xFF); + // Animation duration: 0.667 seconds. internal const long c_durationTicks = 6666666; + CompositionPropertySet _themeProperties; + + /// + /// Dependency property for Color_FFFFFF. + /// + public static readonly DependencyProperty Color_FFFFFFProperty = + DependencyProperty.Register("Color_FFFFFF", typeof(Color), typeof(StartGameIcon), + new PropertyMetadata(GetForegroundColor(InnerLauncherConfig.IsAppThemeLight), OnColor_FFFFFFChanged)); + + // Theme properties. + public Color Color_FFFFFF + { + get => (Color)GetValue(Color_FFFFFFProperty); + set => SetValue(Color_FFFFFFProperty, value); + } + + static Vector4 ColorAsVector4(Color color) => new Vector4(color.R, color.G, color.B, color.A); + + static void OnColor_FFFFFFChanged(DependencyObject d, DependencyPropertyChangedEventArgs args) + { + ((StartGameIcon)d)._themeProperties?.InsertVector4("Color_FFFFFF", ColorAsVector4((Color)(Color)args.NewValue)); + } + + CompositionPropertySet EnsureThemeProperties(Compositor compositor) + { + if (_themeProperties == null) + { + _themeProperties = compositor.CreatePropertySet(); + _themeProperties.InsertVector4("Color_FFFFFF", ColorAsVector4((Color)Color_FFFFFF)); + } + return _themeProperties; + } + public Microsoft.UI.Xaml.Controls.IAnimatedVisual TryCreateAnimatedVisual(Compositor compositor) { object ignored = null; @@ -71,10 +127,12 @@ public Microsoft.UI.Xaml.Controls.IAnimatedVisual TryCreateAnimatedVisual(Compos public Microsoft.UI.Xaml.Controls.IAnimatedVisual TryCreateAnimatedVisual(Compositor compositor, out object diagnostics) { diagnostics = null; + EnsureThemeProperties(compositor); var res = new StartGameIcon_AnimatedVisual( - compositor + compositor, + _themeProperties ); res.CreateAnimations(); return res; @@ -118,6 +176,19 @@ public double FrameToProgress(double frameNumber) /// public void SetColorProperty(string propertyName, Color value) { + if (propertyName == "Color_FFFFFF") + { + Color_FFFFFF = value; + } + else + { + return; + } + + if (_themeProperties != null) + { + _themeProperties.InsertVector4(propertyName, ColorAsVector4(value)); + } } /// @@ -133,19 +204,18 @@ sealed partial class StartGameIcon_AnimatedVisual , Microsoft.UI.Xaml.Controls.IAnimatedVisual2 { const long c_durationTicks = 6666666; - readonly Color _color = InnerLauncherConfig.IsAppThemeLight ? Color.FromArgb(0xFF, 0xFF, 0xFF, 0xFF) : Color.FromArgb(0xFF, 0x00, 0x00, 0x00); - readonly Color _colorTransparent = InnerLauncherConfig.IsAppThemeLight ? Color.FromArgb(0x00, 0xFF, 0xFF, 0xFF) : Color.FromArgb(0x00, 0x00, 0x00, 0x00); readonly Compositor _c; readonly ExpressionAnimation _reusableExpressionAnimation; + readonly CompositionPropertySet _themeProperties; AnimationController _animationController_0; AnimationController _animationController_1; AnimationController _animationController_2; AnimationController _animationController_3; AnimationController _animationController_4; AnimationController _animationController_5; - CompositionColorBrush _animatedColorBrush_TransparentWhite_to_White; - CompositionColorBrush _animatedColorBrush_White_to_TransparentWhite; - CompositionColorBrush _animatedColorBrush_White_to_White; + CompositionColorBrush _themeColor_Color_FFFFFF_0; + CompositionColorBrush _themeColor_Color_FFFFFF_1; + CompositionColorBrush _themeColor_Color_FFFFFF_2; CompositionContainerShape _containerShape_0; CompositionContainerShape _containerShape_1; CompositionContainerShape _containerShape_2; @@ -153,7 +223,7 @@ sealed partial class StartGameIcon_AnimatedVisual ContainerVisual _root; CubicBezierEasingFunction _cubicBezierEasingFunction_0; CubicBezierEasingFunction _cubicBezierEasingFunction_1; - ScalarKeyFrameAnimation _positionXScalarAnimation_m92_to_993; + ScalarKeyFrameAnimation _positionXScalarAnimation_m11p5_to_124p125; StepEasingFunction _holdThenStepEasingFunction; void BindProperty( @@ -169,13 +239,20 @@ void BindProperty( target.StartAnimation(animatedPropertyName, _reusableExpressionAnimation); } - ColorKeyFrameAnimation CreateColorKeyFrameAnimation(float initialProgress, Color initialValue, CompositionEasingFunction initialEasingFunction) + void BindProperty2( + CompositionObject target, + string animatedPropertyName, + string expression, + string referenceParameterName0, + CompositionObject referencedObject0, + string referenceParameterName1, + CompositionObject referencedObject1) { - var result = _c.CreateColorKeyFrameAnimation(); - result.Duration = TimeSpan.FromTicks(c_durationTicks); - result.InterpolationColorSpace = CompositionColorSpace.Rgb; - result.InsertKeyFrame(initialProgress, initialValue, initialEasingFunction); - return result; + _reusableExpressionAnimation.ClearAllParameters(); + _reusableExpressionAnimation.Expression = expression; + _reusableExpressionAnimation.SetReferenceParameter(referenceParameterName0, referencedObject0); + _reusableExpressionAnimation.SetReferenceParameter(referenceParameterName1, referencedObject1); + target.StartAnimation(animatedPropertyName, _reusableExpressionAnimation); } ScalarKeyFrameAnimation CreateScalarKeyFrameAnimation(float initialProgress, float initialValue, CompositionEasingFunction initialEasingFunction) @@ -193,7 +270,6 @@ CompositionSpriteShape CreateSpriteShape(CompositionGeometry geometry, Matrix3x2 return result; } - // - ShapeGroup: Rectangle 1 Offset:<30, 198> AnimationController AnimationController_0() { if (_animationController_0 != null) { return _animationController_0; } @@ -212,7 +288,6 @@ AnimationController AnimationController_1() return result; } - // - ShapeGroup: Rectangle 1 Offset:<30, 198> AnimationController AnimationController_2() { if (_animationController_2 != null) { return _animationController_2; } @@ -231,7 +306,6 @@ AnimationController AnimationController_3() return result; } - // - ShapeGroup: Rectangle 1 Offset:<30, 198> AnimationController AnimationController_4() { if (_animationController_4 != null) { return _animationController_4; } @@ -250,69 +324,39 @@ AnimationController AnimationController_5() return result; } - // - ShapeGroup: Rectangle 1 Offset:<30, 198> - // Color - ColorKeyFrameAnimation ColorAnimation_TransparentWhite_to_White() - { - // Frame 0. - var result = CreateColorKeyFrameAnimation(0F, _colorTransparent, HoldThenStepEasingFunction()); - // Frame 8.91. - // White - result.InsertKeyFrame(0.222662598F, _color, CubicBezierEasingFunction_0()); - // Frame 40. - // White - result.InsertKeyFrame(1F, _color, CubicBezierEasingFunction_1()); - return result; - } - - // - ShapeGroup: Rectangle 1 Offset:<30, 198> - // Color - ColorKeyFrameAnimation ColorAnimation_White_to_TransparentWhite() - { - // Frame 0. - var result = CreateColorKeyFrameAnimation(0F, _color, CubicBezierEasingFunction_0()); - // Frame 27.93. - // White - result.InsertKeyFrame(0.698220015F, _color, CubicBezierEasingFunction_1()); - // Frame 40. - // TransparentWhite - result.InsertKeyFrame(0.99998045F, _colorTransparent, CubicBezierEasingFunction_0()); - return result; - } - - // - ShapeGroup: Rectangle 1 Offset:<30, 198> - // Color - ColorKeyFrameAnimation ColorAnimation_White_to_White() - { - // Frame 0. - var result = CreateColorKeyFrameAnimation(0F, _color, CubicBezierEasingFunction_0()); - // Frame 40. - // White - result.InsertKeyFrame(1F, _color, CubicBezierEasingFunction_1()); - return result; - } - // ShapeGroup: Rectangle 1 Offset:<30, 198> - CompositionColorBrush AnimatedColorBrush_TransparentWhite_to_White() + // Color bound to theme property value: Color_FFFFFF + CompositionColorBrush ThemeColor_Color_FFFFFF_0() { - if (_animatedColorBrush_TransparentWhite_to_White != null) { return _animatedColorBrush_TransparentWhite_to_White; } - var result = _animatedColorBrush_TransparentWhite_to_White = _c.CreateColorBrush(); + if (_themeColor_Color_FFFFFF_0 != null) { return _themeColor_Color_FFFFFF_0; } + var result = _themeColor_Color_FFFFFF_0 = _c.CreateColorBrush(); + var propertySet = result.Properties; + propertySet.InsertScalar("Opacity0", 1F); + BindProperty2(_themeColor_Color_FFFFFF_0, "Color", "ColorRGB(_theme.Color_FFFFFF.W*my.Opacity0,_theme.Color_FFFFFF.X,_theme.Color_FFFFFF.Y,_theme.Color_FFFFFF.Z)", "_theme", _themeProperties, "my", propertySet); return result; } // ShapeGroup: Rectangle 1 Offset:<30, 198> - CompositionColorBrush AnimatedColorBrush_White_to_TransparentWhite() + // Color bound to theme property value: Color_FFFFFF + CompositionColorBrush ThemeColor_Color_FFFFFF_1() { - if (_animatedColorBrush_White_to_TransparentWhite != null) { return _animatedColorBrush_White_to_TransparentWhite; } - var result = _animatedColorBrush_White_to_TransparentWhite = _c.CreateColorBrush(); + if (_themeColor_Color_FFFFFF_1 != null) { return _themeColor_Color_FFFFFF_1; } + var result = _themeColor_Color_FFFFFF_1 = _c.CreateColorBrush(); + var propertySet = result.Properties; + propertySet.InsertScalar("Opacity0", 1F); + BindProperty2(_themeColor_Color_FFFFFF_1, "Color", "ColorRGB(_theme.Color_FFFFFF.W*my.Opacity0,_theme.Color_FFFFFF.X,_theme.Color_FFFFFF.Y,_theme.Color_FFFFFF.Z)", "_theme", _themeProperties, "my", propertySet); return result; } // ShapeGroup: Rectangle 1 Offset:<30, 198> - CompositionColorBrush AnimatedColorBrush_White_to_White() + // Color bound to theme property value: Color_FFFFFF + CompositionColorBrush ThemeColor_Color_FFFFFF_2() { - if (_animatedColorBrush_White_to_White != null) { return _animatedColorBrush_White_to_White; } - var result = _animatedColorBrush_White_to_White = _c.CreateColorBrush(); + if (_themeColor_Color_FFFFFF_2 != null) { return _themeColor_Color_FFFFFF_2; } + var result = _themeColor_Color_FFFFFF_2 = _c.CreateColorBrush(); + var propertySet = result.Properties; + propertySet.InsertScalar("Opacity0", 0F); + BindProperty2(_themeColor_Color_FFFFFF_2, "Color", "ColorRGB(_theme.Color_FFFFFF.W*my.Opacity0,_theme.Color_FFFFFF.X,_theme.Color_FFFFFF.Y,_theme.Color_FFFFFF.Z)", "_theme", _themeProperties, "my", propertySet); return result; } @@ -321,9 +365,10 @@ CompositionContainerShape ContainerShape_0() if (_containerShape_0 != null) { return _containerShape_0; } var result = _containerShape_0 = _c.CreateContainerShape(); var propertySet = result.Properties; - propertySet.InsertVector2("Position", new Vector2(-92F, 1024F)); + propertySet.InsertVector2("Position", new Vector2(-11.5F, 128F)); result.CenterPoint = new Vector2(30F, 198F); result.RotationAngleInDegrees = 45F; + result.Scale = new Vector2(0.125F, 0.125F); // ShapeGroup: Rectangle 1 Offset:<30, 198> result.Shapes.Add(SpriteShape_0()); BindProperty(_containerShape_0, "Offset", "Vector2(my.Position.X-30,my.Position.Y-198)", "my", _containerShape_0); @@ -335,9 +380,10 @@ CompositionContainerShape ContainerShape_1() if (_containerShape_1 != null) { return _containerShape_1; } var result = _containerShape_1 = _c.CreateContainerShape(); var propertySet = result.Properties; - propertySet.InsertVector2("Position", new Vector2(-92F, 1024F)); + propertySet.InsertVector2("Position", new Vector2(-11.5F, 128F)); result.CenterPoint = new Vector2(30F, 198F); result.RotationAngleInDegrees = 45F; + result.Scale = new Vector2(0.125F, 0.125F); // ShapeGroup: Rectangle 1 Offset:<30, 198> result.Shapes.Add(SpriteShape_1()); BindProperty(_containerShape_1, "Offset", "Vector2(my.Position.X-30,my.Position.Y-198)", "my", _containerShape_1); @@ -349,9 +395,10 @@ CompositionContainerShape ContainerShape_2() if (_containerShape_2 != null) { return _containerShape_2; } var result = _containerShape_2 = _c.CreateContainerShape(); var propertySet = result.Properties; - propertySet.InsertVector2("Position", new Vector2(-92F, 1024F)); + propertySet.InsertVector2("Position", new Vector2(-11.5F, 128F)); result.CenterPoint = new Vector2(30F, 198F); result.RotationAngleInDegrees = 45F; + result.Scale = new Vector2(0.125F, 0.125F); // ShapeGroup: Rectangle 1 Offset:<30, 198> result.Shapes.Add(SpriteShape_2()); BindProperty(_containerShape_2, "Offset", "Vector2(my.Position.X-30,my.Position.Y-198)", "my", _containerShape_2); @@ -376,7 +423,7 @@ CompositionSpriteShape SpriteShape_0() { // Offset:<30, 198> var result = CreateSpriteShape(Rectangle_1036(), new Matrix3x2(1F, 0F, 0F, 1F, 30F, 198F));; - result.StrokeBrush = AnimatedColorBrush_White_to_TransparentWhite(); + result.StrokeBrush = ThemeColor_Color_FFFFFF_0(); result.StrokeDashCap = CompositionStrokeCap.Round; result.StrokeStartCap = CompositionStrokeCap.Round; result.StrokeEndCap = CompositionStrokeCap.Round; @@ -390,7 +437,7 @@ CompositionSpriteShape SpriteShape_1() { // Offset:<30, 198> var result = CreateSpriteShape(Rectangle_1036(), new Matrix3x2(1F, 0F, 0F, 1F, 30F, 198F));; - result.StrokeBrush = AnimatedColorBrush_White_to_White(); + result.StrokeBrush = ThemeColor_Color_FFFFFF_1(); result.StrokeDashCap = CompositionStrokeCap.Round; result.StrokeStartCap = CompositionStrokeCap.Round; result.StrokeEndCap = CompositionStrokeCap.Round; @@ -404,7 +451,7 @@ CompositionSpriteShape SpriteShape_2() { // Offset:<30, 198> var result = CreateSpriteShape(Rectangle_1036(), new Matrix3x2(1F, 0F, 0F, 1F, 30F, 198F));; - result.StrokeBrush = AnimatedColorBrush_TransparentWhite_to_White(); + result.StrokeBrush = ThemeColor_Color_FFFFFF_2(); result.StrokeDashCap = CompositionStrokeCap.Round; result.StrokeStartCap = CompositionStrokeCap.Round; result.StrokeEndCap = CompositionStrokeCap.Round; @@ -439,14 +486,48 @@ CubicBezierEasingFunction CubicBezierEasingFunction_1() : _cubicBezierEasingFunction_1; } + // Opacity0 + ScalarKeyFrameAnimation Opacity0ScalarAnimation_0_to_1() + { + // Frame 0. + var result = CreateScalarKeyFrameAnimation(0F, 0F, HoldThenStepEasingFunction()); + // Frame 8.91. + result.InsertKeyFrame(0.222662598F, 1F, CubicBezierEasingFunction_0()); + // Frame 40. + result.InsertKeyFrame(1F, 1F, CubicBezierEasingFunction_1()); + return result; + } + + // Opacity0 + ScalarKeyFrameAnimation Opacity0ScalarAnimation_1_to_0() + { + // Frame 0. + var result = CreateScalarKeyFrameAnimation(0F, 1F, CubicBezierEasingFunction_0()); + // Frame 27.93. + result.InsertKeyFrame(0.698220015F, 1F, CubicBezierEasingFunction_1()); + // Frame 40. + result.InsertKeyFrame(0.99998045F, 0F, CubicBezierEasingFunction_0()); + return result; + } + + // Opacity0 + ScalarKeyFrameAnimation Opacity0ScalarAnimation_1_to_1() + { + // Frame 0. + var result = CreateScalarKeyFrameAnimation(0F, 1F, CubicBezierEasingFunction_0()); + // Frame 40. + result.InsertKeyFrame(1F, 1F, CubicBezierEasingFunction_1()); + return result; + } + // Position.X - ScalarKeyFrameAnimation PositionXScalarAnimation_m92_to_993() + ScalarKeyFrameAnimation PositionXScalarAnimation_m11p5_to_124p125() { // Frame 0. - if (_positionXScalarAnimation_m92_to_993 != null) { return _positionXScalarAnimation_m92_to_993; } - var result = _positionXScalarAnimation_m92_to_993 = CreateScalarKeyFrameAnimation(0F, -92F, HoldThenStepEasingFunction()); + if (_positionXScalarAnimation_m11p5_to_124p125 != null) { return _positionXScalarAnimation_m11p5_to_124p125; } + var result = _positionXScalarAnimation_m11p5_to_124p125 = CreateScalarKeyFrameAnimation(0F, -11.5F, HoldThenStepEasingFunction()); // Frame 40. - result.InsertKeyFrame(1F, 993F, _c.CreateCubicBezierEasingFunction(new Vector2(0.47299999F, 0.0659999996F), new Vector2(0.521000028F, 1F))); + result.InsertKeyFrame(1F, 124.125F, _c.CreateCubicBezierEasingFunction(new Vector2(0.47299999F, 0.523999989F), new Vector2(0.521000028F, 1F))); return result; } @@ -454,7 +535,7 @@ ScalarKeyFrameAnimation PositionXScalarAnimation_m92_to_993() ShapeVisual ShapeVisual_0() { var result = _c.CreateShapeVisual(); - result.Size = new Vector2(2048F, 2048F); + result.Size = new Vector2(256F, 256F); var shapes = result.Shapes; shapes.Add(ContainerShape_0()); shapes.Add(ContainerShape_1()); @@ -471,34 +552,36 @@ StepEasingFunction HoldThenStepEasingFunction() } internal StartGameIcon_AnimatedVisual( - Compositor compositor + Compositor compositor, + CompositionPropertySet themeProperties ) { _c = compositor; + _themeProperties = themeProperties; _reusableExpressionAnimation = compositor.CreateExpressionAnimation(); Root(); } public Visual RootVisual => _root; public TimeSpan Duration => TimeSpan.FromTicks(c_durationTicks); - public Vector2 Size => new Vector2(2048F, 2048F); + public Vector2 Size => new Vector2(256F, 256F); void IDisposable.Dispose() => _root?.Dispose(); public void CreateAnimations() { - _animatedColorBrush_TransparentWhite_to_White.StartAnimation("Color", ColorAnimation_TransparentWhite_to_White(), AnimationController_4()); - _animatedColorBrush_White_to_TransparentWhite.StartAnimation("Color", ColorAnimation_White_to_TransparentWhite(), AnimationController_0()); - _animatedColorBrush_White_to_White.StartAnimation("Color", ColorAnimation_White_to_White(), AnimationController_2()); - _containerShape_0.Properties.StartAnimation("Position.X", PositionXScalarAnimation_m92_to_993(), AnimationController_1()); - _containerShape_1.Properties.StartAnimation("Position.X", PositionXScalarAnimation_m92_to_993(), AnimationController_3()); - _containerShape_2.Properties.StartAnimation("Position.X", PositionXScalarAnimation_m92_to_993(), AnimationController_5()); + _themeColor_Color_FFFFFF_0.Properties.StartAnimation("Opacity0", Opacity0ScalarAnimation_1_to_0(), AnimationController_0()); + _themeColor_Color_FFFFFF_1.Properties.StartAnimation("Opacity0", Opacity0ScalarAnimation_1_to_1(), AnimationController_2()); + _themeColor_Color_FFFFFF_2.Properties.StartAnimation("Opacity0", Opacity0ScalarAnimation_0_to_1(), AnimationController_4()); + _containerShape_0.Properties.StartAnimation("Position.X", PositionXScalarAnimation_m11p5_to_124p125(), AnimationController_1()); + _containerShape_1.Properties.StartAnimation("Position.X", PositionXScalarAnimation_m11p5_to_124p125(), AnimationController_3()); + _containerShape_2.Properties.StartAnimation("Position.X", PositionXScalarAnimation_m11p5_to_124p125(), AnimationController_5()); } public void DestroyAnimations() { - _animatedColorBrush_TransparentWhite_to_White.StopAnimation("Color"); - _animatedColorBrush_White_to_TransparentWhite.StopAnimation("Color"); - _animatedColorBrush_White_to_White.StopAnimation("Color"); + _themeColor_Color_FFFFFF_0.Properties.StopAnimation("Opacity0"); + _themeColor_Color_FFFFFF_1.Properties.StopAnimation("Opacity0"); + _themeColor_Color_FFFFFF_2.Properties.StopAnimation("Opacity0"); _containerShape_0.Properties.StopAnimation("Position.X"); _containerShape_1.Properties.StopAnimation("Position.X"); _containerShape_2.Properties.StopAnimation("Position.X"); diff --git a/CollapseLauncher/Classes/AnimatedVisuals/Lottie/StartGameIcon.json b/CollapseLauncher/Classes/AnimatedVisuals/Lottie/StartGameIcon.json new file mode 100644 index 000000000..90563bd90 --- /dev/null +++ b/CollapseLauncher/Classes/AnimatedVisuals/Lottie/StartGameIcon.json @@ -0,0 +1 @@ +{"v":"5.12.2","fr":60,"ip":0,"op":40,"w":256,"h":256,"nm":"StartGameIcon","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 5","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":79,"s":[0]},{"i":{"x":[0.413],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":99,"s":[100]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":168.822,"s":[100]},{"t":198.998046875,"s":[0]}],"ix":11},"r":{"a":0,"k":45,"ix":10},"p":{"s":true,"x":{"a":1,"k":[{"i":{"x":[0.521],"y":[1]},"o":{"x":[0.473],"y":[0.524]},"t":79,"s":[-11.5]},{"t":199,"s":[124.125]}],"ix":3},"y":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":79,"s":[128]},{"t":99,"s":[128]}],"ix":4}},"a":{"a":0,"k":[30,198,0],"ix":1,"l":2},"s":{"a":0,"k":[12.5,12.5,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[1036,1036],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"tm","s":{"a":0,"k":37,"ix":1},"e":{"a":0,"k":63,"ix":2},"o":{"a":0,"k":180,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":128,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[30,198],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":79,"op":79.6060606060606,"st":79,"ct":1,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Shape Layer 4","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":40,"s":[0]},{"i":{"x":[0.413],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":60,"s":[100]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":129.822,"s":[100]},{"t":159.998046875,"s":[0]}],"ix":11},"r":{"a":0,"k":45,"ix":10},"p":{"s":true,"x":{"a":1,"k":[{"i":{"x":[0.521],"y":[1]},"o":{"x":[0.473],"y":[0.524]},"t":40,"s":[-11.5]},{"t":160,"s":[124.125]}],"ix":3},"y":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":40,"s":[128]},{"t":60,"s":[128]}],"ix":4}},"a":{"a":0,"k":[30,198,0],"ix":1,"l":2},"s":{"a":0,"k":[12.5,12.5,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[1036,1036],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"tm","s":{"a":0,"k":37,"ix":1},"e":{"a":0,"k":63,"ix":2},"o":{"a":0,"k":180,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":128,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[30,198],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":40,"op":40.6060606060606,"st":40,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Shape Layer 3","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[0]},{"i":{"x":[0.413],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":20,"s":[100]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":89.822,"s":[100]},{"t":119.998046875,"s":[0]}],"ix":11},"r":{"a":0,"k":45,"ix":10},"p":{"s":true,"x":{"a":1,"k":[{"i":{"x":[0.521],"y":[1]},"o":{"x":[0.473],"y":[0.524]},"t":0,"s":[-11.5]},{"t":120,"s":[124.125]}],"ix":3},"y":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[128]},{"t":20,"s":[128]}],"ix":4}},"a":{"a":0,"k":[30,198,0],"ix":1,"l":2},"s":{"a":0,"k":[12.5,12.5,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[1036,1036],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"tm","s":{"a":0,"k":37,"ix":1},"e":{"a":0,"k":63,"ix":2},"o":{"a":0,"k":180,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":128,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[30,198],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":40,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Shape Layer 2","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":-40,"s":[0]},{"i":{"x":[0.413],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":-20,"s":[100]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":49.822,"s":[100]},{"t":79.998046875,"s":[0]}],"ix":11},"r":{"a":0,"k":45,"ix":10},"p":{"s":true,"x":{"a":1,"k":[{"i":{"x":[0.521],"y":[1]},"o":{"x":[0.473],"y":[0.524]},"t":-40,"s":[-11.5]},{"t":80,"s":[124.125]}],"ix":3},"y":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":-40,"s":[128]},{"t":-20,"s":[128]}],"ix":4}},"a":{"a":0,"k":[30,198,0],"ix":1,"l":2},"s":{"a":0,"k":[12.5,12.5,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[1036,1036],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"tm","s":{"a":0,"k":37,"ix":1},"e":{"a":0,"k":63,"ix":2},"o":{"a":0,"k":180,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":128,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[30,198],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":40,"st":-40,"ct":1,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":-80,"s":[0]},{"i":{"x":[0.413],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":-60,"s":[100]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":9.822,"s":[100]},{"t":39.998046875,"s":[0]}],"ix":11},"r":{"a":0,"k":45,"ix":10},"p":{"s":true,"x":{"a":1,"k":[{"i":{"x":[0.521],"y":[1]},"o":{"x":[0.473],"y":[0.524]},"t":-80,"s":[-11.5]},{"t":40,"s":[124.125]}],"ix":3},"y":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":-80,"s":[128]},{"t":-60,"s":[128]}],"ix":4}},"a":{"a":0,"k":[30,198,0],"ix":1,"l":2},"s":{"a":0,"k":[12.5,12.5,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[1036,1036],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"tm","s":{"a":0,"k":37,"ix":1},"e":{"a":0,"k":63,"ix":2},"o":{"a":0,"k":180,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":128,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[30,198],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":40,"st":-80,"ct":1,"bm":0}],"markers":[],"props":{}} \ No newline at end of file diff --git a/CollapseLauncher/Classes/AnimatedVisuals/Lottie/StartGameIcon.lottie b/CollapseLauncher/Classes/AnimatedVisuals/Lottie/StartGameIcon.lottie deleted file mode 100644 index 22323e1b1..000000000 Binary files a/CollapseLauncher/Classes/AnimatedVisuals/Lottie/StartGameIcon.lottie and /dev/null differ diff --git a/CollapseLauncher/Classes/AnimatedVisuals/Lottie/UpdateIcon.cs b/CollapseLauncher/Classes/AnimatedVisuals/Lottie/UpdateIcon.cs index f41006052..13ecb8fde 100644 --- a/CollapseLauncher/Classes/AnimatedVisuals/Lottie/UpdateIcon.cs +++ b/CollapseLauncher/Classes/AnimatedVisuals/Lottie/UpdateIcon.cs @@ -3,13 +3,13 @@ // This code was generated by a tool. // // LottieGen version: -// 8.0.280225.1+7cd366a738 +// 8.2.250604.1+b02a3ee244 // // Command: -// LottieGen -Language CSharp -Namespace CollapseLauncher.AnimatedVisuals.Lottie -Public -WinUIVersion 3.0 -InputFile UpdateIcon.lottie +// LottieGen -GenerateColorBindings -GenerateDependencyObject -Language CSharp -Namespace CollapseLauncher.AnimatedVisuals.Lottie -Public -WinUIVersion 3.0 -InputFile UpdateIcon.json // // Input file: -// UpdateIcon.lottie (1532 bytes created 20:12+07:00 Jun 2 2024) +// UpdateIcon.json (5270 bytes created 16:59+07:00 Jan 4 2026) // // LottieGen source: // http://aka.ms/Lottie @@ -21,16 +21,16 @@ // ____________________________________ // | Object stats | Count | // |__________________________|_______| -// | All CompositionObjects | 42 | +// | All CompositionObjects | 45 | // |--------------------------+-------| -// | Expression animators | 1 | +// | Expression animators | 2 | // | KeyFrame animators | 3 | -// | Reference parameters | 1 | -// | Expression operations | 0 | +// | Reference parameters | 2 | +// | Expression operations | 4 | // |--------------------------+-------| -// | Animated brushes | - | +// | Animated brushes | 1 | // | Animated gradient stops | - | -// | ExpressionAnimations | 1 | +// | ExpressionAnimations | 2 | // | PathKeyFrameAnimations | - | // |--------------------------+-------| // | ContainerVisuals | 3 | @@ -43,8 +43,11 @@ // | Gradient stops | - | // | CompositionVisualSurface | - | // ------------------------------------ +using Microsoft.Graphics; using Microsoft.Graphics.Canvas.Geometry; using Microsoft.UI.Composition; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Media; using System; using System.Collections.Generic; using System.Numerics; @@ -56,13 +59,67 @@ namespace CollapseLauncher.AnimatedVisuals.Lottie // Frame rate: 60 fps // Frame count: 240 // Duration: 4000.0 mS - sealed partial class UpdateIcon - : Microsoft.UI.Xaml.Controls.IAnimatedVisualSource + public sealed partial class UpdateIcon + : BindableThemeChangeAnimation + , Microsoft.UI.Xaml.Controls.IAnimatedVisualSource , Microsoft.UI.Xaml.Controls.IAnimatedVisualSource2 { + protected override void OnForegroundChanged(Brush brush) + { + if (brush is SolidColorBrush colorBrush) + { + Color_FFFFFF = colorBrush.Color; + return; + } + + if (brush is AcrylicBrush acrylicBrush) + { + Color_FFFFFF = acrylicBrush.TintColor; + return; + } + } + + private static Color GetForegroundColor(bool isLightTheme) => + isLightTheme + ? Color.FromArgb(0xFF, 0x00, 0x00, 0x00) + : Color.FromArgb(0xFF, 0xFF, 0xFF, 0xFF); + // Animation duration: 4.000 seconds. internal const long c_durationTicks = 40000000; + CompositionPropertySet _themeProperties; + + /// + /// Dependency property for Color_FFFFFF. + /// + public static readonly DependencyProperty Color_FFFFFFProperty = + DependencyProperty.Register("Color_FFFFFF", typeof(Color), typeof(UpdateIcon), + new PropertyMetadata(GetForegroundColor(InnerLauncherConfig.IsAppThemeLight), OnColor_FFFFFFChanged)); + + // Theme properties. + public Color Color_FFFFFF + { + get => (Color)GetValue(Color_FFFFFFProperty); + set => SetValue(Color_FFFFFFProperty, value); + } + + static Vector4 ColorAsVector4(Color color) => new Vector4(color.R, color.G, color.B, color.A); + + static void OnColor_FFFFFFChanged(DependencyObject d, DependencyPropertyChangedEventArgs args) + { + ((UpdateIcon)d)._themeProperties?.InsertVector4("Color_FFFFFF", ColorAsVector4((Color)(Color)args.NewValue)); + } + + CompositionPropertySet EnsureThemeProperties(Compositor compositor) + { + if (_themeProperties == null) + { + _themeProperties = compositor.CreatePropertySet(); + _themeProperties.InsertVector4("Color_FFFFFF", ColorAsVector4((Color)Color_FFFFFF)); + } + return _themeProperties; + } + public Microsoft.UI.Xaml.Controls.IAnimatedVisual TryCreateAnimatedVisual(Compositor compositor) { object ignored = null; @@ -72,10 +129,12 @@ public Microsoft.UI.Xaml.Controls.IAnimatedVisual TryCreateAnimatedVisual(Compos public Microsoft.UI.Xaml.Controls.IAnimatedVisual TryCreateAnimatedVisual(Compositor compositor, out object diagnostics) { diagnostics = null; + EnsureThemeProperties(compositor); var res = new UpdateIcon_AnimatedVisual( - compositor + compositor, + _themeProperties ); res.CreateAnimations(); return res; @@ -119,6 +178,19 @@ public double FrameToProgress(double frameNumber) /// public void SetColorProperty(string propertyName, Color value) { + if (propertyName == "Color_FFFFFF") + { + Color_FFFFFF = value; + } + else + { + return; + } + + if (_themeProperties != null) + { + _themeProperties.InsertVector4(propertyName, ColorAsVector4(value)); + } } /// @@ -134,11 +206,11 @@ sealed partial class UpdateIcon_AnimatedVisual , Microsoft.UI.Xaml.Controls.IAnimatedVisual2 { const long c_durationTicks = 40000000; - readonly Color _color = InnerLauncherConfig.IsAppThemeLight ? Color.FromArgb(0xFF, 0xFF, 0xFF, 0xFF) : Color.FromArgb(0xFF, 0x00, 0x00, 0x00); readonly Compositor _c; readonly ExpressionAnimation _reusableExpressionAnimation; + readonly CompositionPropertySet _themeProperties; AnimationController _animationController_0; - CompositionColorBrush _colorBrush_White; + CompositionColorBrush _themeColor_Color_FFFFFF; CompositionPathGeometry _pathGeometry_2; CompositionPathGeometry _pathGeometry_3; ContainerVisual _containerVisual_0; @@ -186,7 +258,7 @@ AnimationController AnimationController_0() // - - - - - PreComp layer: UpdateIcon // - - - Layer aggregator - // - - Offset:<1543, 561> + // - - Scale:0.125,0.125, Offset:<192.875, 70.125> CanvasGeometry Geometry_0() { CanvasGeometry result; @@ -203,7 +275,7 @@ CanvasGeometry Geometry_0() // - - - - - PreComp layer: UpdateIcon // - - - Layer aggregator - // - - Offset:<505.5, 1488> + // - - Scale:0.125,0.125, Offset:<63.188, 186> CanvasGeometry Geometry_1() { CanvasGeometry result; @@ -220,7 +292,7 @@ CanvasGeometry Geometry_1() // - - - - - PreComp layer: UpdateIcon // - - - Layer aggregator - // - - Offset:<1024, 1024> + // - - Scale:0.125,0.125, Offset:<128, 128> CanvasGeometry Geometry_2() { CanvasGeometry result; @@ -241,7 +313,7 @@ CanvasGeometry Geometry_2() // - - - - - PreComp layer: UpdateIcon // - - - Layer aggregator - // - - Offset:<1024, 1024> + // - - Scale:0.125,0.125, Offset:<128, 128> CanvasGeometry Geometry_3() { CanvasGeometry result; @@ -259,16 +331,18 @@ CanvasGeometry Geometry_3() return result; } - CompositionColorBrush ColorBrush_White() + // Color bound to theme property value: Color_FFFFFF + CompositionColorBrush ThemeColor_Color_FFFFFF() { - return (_colorBrush_White == null) - ? _colorBrush_White = _c.CreateColorBrush(_color) - : _colorBrush_White; + if (_themeColor_Color_FFFFFF != null) { return _themeColor_Color_FFFFFF; } + var result = _themeColor_Color_FFFFFF = _c.CreateColorBrush(); + BindProperty(_themeColor_Color_FFFFFF, "Color", "ColorRGB(_theme.Color_FFFFFF.W,_theme.Color_FFFFFF.X,_theme.Color_FFFFFF.Y,_theme.Color_FFFFFF.Z)", "_theme", _themeProperties); + return result; } // - - - PreComp layer: UpdateIcon // - Layer aggregator - // Offset:<1543, 561> + // Scale:0.125,0.125, Offset:<192.875, 70.125> CompositionPathGeometry PathGeometry_0() { return _c.CreatePathGeometry(new CompositionPath(Geometry_0())); @@ -276,7 +350,7 @@ CompositionPathGeometry PathGeometry_0() // - - - PreComp layer: UpdateIcon // - Layer aggregator - // Offset:<505.5, 1488> + // Scale:0.125,0.125, Offset:<63.188, 186> CompositionPathGeometry PathGeometry_1() { return _c.CreatePathGeometry(new CompositionPath(Geometry_1())); @@ -284,7 +358,7 @@ CompositionPathGeometry PathGeometry_1() // - - - PreComp layer: UpdateIcon // - Layer aggregator - // Offset:<1024, 1024> + // Scale:0.125,0.125, Offset:<128, 128> CompositionPathGeometry PathGeometry_2() { if (_pathGeometry_2 != null) { return _pathGeometry_2; } @@ -294,7 +368,7 @@ CompositionPathGeometry PathGeometry_2() // - - - PreComp layer: UpdateIcon // - Layer aggregator - // Offset:<1024, 1024> + // Scale:0.125,0.125, Offset:<128, 128> CompositionPathGeometry PathGeometry_3() { if (_pathGeometry_3 != null) { return _pathGeometry_3; } @@ -307,9 +381,9 @@ CompositionPathGeometry PathGeometry_3() // Path 1 CompositionSpriteShape SpriteShape_0() { - // Offset:<1543, 561> - var result = CreateSpriteShape(PathGeometry_0(), new Matrix3x2(1F, 0F, 0F, 1F, 1543F, 561F));; - result.StrokeBrush = ColorBrush_White(); + // Offset:<192.875, 70.125>, Scale:<0.125, 0.125> + var result = CreateSpriteShape(PathGeometry_0(), new Matrix3x2(0.125F, 0F, 0F, 0.125F, 192.875F, 70.125F));; + result.StrokeBrush = ThemeColor_Color_FFFFFF(); result.StrokeDashCap = CompositionStrokeCap.Round; result.StrokeStartCap = CompositionStrokeCap.Round; result.StrokeEndCap = CompositionStrokeCap.Round; @@ -323,9 +397,9 @@ CompositionSpriteShape SpriteShape_0() // Path 1 CompositionSpriteShape SpriteShape_1() { - // Offset:<505.5, 1488> - var result = CreateSpriteShape(PathGeometry_1(), new Matrix3x2(1F, 0F, 0F, 1F, 505.5F, 1488F));; - result.StrokeBrush = ColorBrush_White(); + // Offset:<63.188, 186>, Scale:<0.125, 0.125> + var result = CreateSpriteShape(PathGeometry_1(), new Matrix3x2(0.125F, 0F, 0F, 0.125F, 63.1879997F, 186F));; + result.StrokeBrush = ThemeColor_Color_FFFFFF(); result.StrokeDashCap = CompositionStrokeCap.Round; result.StrokeStartCap = CompositionStrokeCap.Round; result.StrokeEndCap = CompositionStrokeCap.Round; @@ -339,9 +413,9 @@ CompositionSpriteShape SpriteShape_1() // Path 1 CompositionSpriteShape SpriteShape_2() { - // Offset:<1024, 1024> - var result = CreateSpriteShape(PathGeometry_2(), new Matrix3x2(1F, 0F, 0F, 1F, 1024F, 1024F));; - result.StrokeBrush = ColorBrush_White(); + // Offset:<128, 128>, Scale:<0.125, 0.125> + var result = CreateSpriteShape(PathGeometry_2(), new Matrix3x2(0.125F, 0F, 0F, 0.125F, 128F, 128F));; + result.StrokeBrush = ThemeColor_Color_FFFFFF(); result.StrokeDashCap = CompositionStrokeCap.Round; result.StrokeStartCap = CompositionStrokeCap.Round; result.StrokeEndCap = CompositionStrokeCap.Round; @@ -356,9 +430,9 @@ CompositionSpriteShape SpriteShape_2() // Path 1 CompositionSpriteShape SpriteShape_3() { - // Offset:<1024, 1024> - var result = CreateSpriteShape(PathGeometry_3(), new Matrix3x2(1F, 0F, 0F, 1F, 1024F, 1024F));; - result.StrokeBrush = ColorBrush_White(); + // Offset:<128, 128>, Scale:<0.125, 0.125> + var result = CreateSpriteShape(PathGeometry_3(), new Matrix3x2(0.125F, 0F, 0F, 0.125F, 128F, 128F));; + result.StrokeBrush = ThemeColor_Color_FFFFFF(); result.StrokeDashCap = CompositionStrokeCap.Round; result.StrokeStartCap = CompositionStrokeCap.Round; result.StrokeEndCap = CompositionStrokeCap.Round; @@ -373,8 +447,7 @@ ContainerVisual ContainerVisual_0() { if (_containerVisual_0 != null) { return _containerVisual_0; } var result = _containerVisual_0 = _c.CreateContainerVisual(); - result.CenterPoint = new Vector3(1024F, 1024F, 0F); - result.Offset = new Vector3(176F, 176F, 0F); + result.CenterPoint = new Vector3(128F, 128F, 0F); result.Scale = new Vector3(1F, 1F, 0F); result.Children.InsertAtTop(ContainerVisual_1()); return result; @@ -385,7 +458,7 @@ ContainerVisual ContainerVisual_1() { var result = _c.CreateContainerVisual(); result.Clip = InsetClip_0(); - result.Size = new Vector2(2048F, 2048F); + result.Size = new Vector2(256F, 256F); // Layer aggregator result.Children.InsertAtTop(ShapeVisual_0()); return result; @@ -448,15 +521,15 @@ ScalarKeyFrameAnimation TrimStartScalarAnimation_0_to_0() ShapeVisual ShapeVisual_0() { var result = _c.CreateShapeVisual(); - result.Size = new Vector2(2048F, 2048F); + result.Size = new Vector2(256F, 256F); var shapes = result.Shapes; - // Offset:<1543, 561> + // Scale:0.125,0.125, Offset:<192.875, 70.125> shapes.Add(SpriteShape_0()); - // Offset:<505.5, 1488> + // Scale:0.125,0.125, Offset:<63.188, 186> shapes.Add(SpriteShape_1()); - // Offset:<1024, 1024> + // Scale:0.125,0.125, Offset:<128, 128> shapes.Add(SpriteShape_2()); - // Offset:<1024, 1024> + // Scale:0.125,0.125, Offset:<128, 128> shapes.Add(SpriteShape_3()); return result; } @@ -470,17 +543,19 @@ StepEasingFunction HoldThenStepEasingFunction() } internal UpdateIcon_AnimatedVisual( - Compositor compositor + Compositor compositor, + CompositionPropertySet themeProperties ) { _c = compositor; + _themeProperties = themeProperties; _reusableExpressionAnimation = compositor.CreateExpressionAnimation(); Root(); } public Visual RootVisual => _root; public TimeSpan Duration => TimeSpan.FromTicks(c_durationTicks); - public Vector2 Size => new Vector2(2400F, 2400F); + public Vector2 Size => new Vector2(256F, 256F); void IDisposable.Dispose() => _root?.Dispose(); public void CreateAnimations() diff --git a/CollapseLauncher/Classes/AnimatedVisuals/Lottie/UpdateIcon.json b/CollapseLauncher/Classes/AnimatedVisuals/Lottie/UpdateIcon.json new file mode 100644 index 000000000..e57b78cd8 --- /dev/null +++ b/CollapseLauncher/Classes/AnimatedVisuals/Lottie/UpdateIcon.json @@ -0,0 +1 @@ +{"v":"5.12.2","fr":60,"ip":0,"op":240,"w":256,"h":256,"nm":"UpdateIconMasterComp","ddd":0,"assets":[{"id":"comp_0","nm":"UpdateIcon","fr":60,"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[128,128,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[12.5,12.5,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-14.666,56.266],[-31.132,53.758],[-105.895,61.521],[-128.947,-0.321],[-103.436,-60.448],[-61.24,-107.197]],"o":[[16.051,-61.58],[61.391,-106.008],[103.968,-60.401],[128.408,0.32],[106.564,62.276],[14.259,24.959]],"v":[[-679.411,-177.885],[-608.024,-351.501],[-352.405,-607.463],[1.406,-702.002],[353.538,-606.465],[610.018,-347.459]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":128,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[0]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":30,"s":[50]},{"t":80,"s":[0]}],"ix":1},"e":{"a":0,"k":100,"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":242,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Shape Layer 3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[128,128,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[12.5,12.5,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[11.129,-42.34],[31.671,-54.12],[104.889,-60.982],[129.029,0.321],[102.932,59.646],[61.568,105.903],[11.121,25.826]],"o":[[-16.328,62.123],[-61.282,104.72],[-104.012,60.472],[-127.485,-0.317],[-106.028,-61.44],[-14.021,-24.117],[-3.58,-8.314]],"v":[[679.076,179.264],[606.447,354.255],[352.629,607.348],[-1.38,702.002],[-351.277,607.765],[-607.341,352.059],[-645.109,277.089]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":128,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[0]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":30,"s":[50]},{"t":80,"s":[0]}],"ix":1},"e":{"a":0,"k":100,"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":242,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Shape Layer 4","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[63.188,186,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[12.5,12.5,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-244.242,122.011],[-123.464,-207.693],[206.416,-86.902]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":128,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false}],"ip":0,"op":242,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[192.875,70.125,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[12.5,12.5,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[244.229,-121.905],[123.49,207.693],[-206.2,86.799]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":128,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false}],"ip":0,"op":242,"st":0,"ct":1,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":0,"nm":"UpdateIcon","refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[0]},{"i":{"x":[0.024],"y":[1]},"o":{"x":[0.158],"y":[0]},"t":30,"s":[-65]},{"t":220,"s":[2160]}],"ix":10},"p":{"a":0,"k":[128,128,0],"ix":2,"l":2},"a":{"a":0,"k":[128,128,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"w":256,"h":256,"ip":0,"op":240,"st":0,"bm":0}],"markers":[],"props":{}} \ No newline at end of file diff --git a/CollapseLauncher/Classes/AnimatedVisuals/Lottie/UpdateIcon.lottie b/CollapseLauncher/Classes/AnimatedVisuals/Lottie/UpdateIcon.lottie deleted file mode 100644 index 23168ac30..000000000 Binary files a/CollapseLauncher/Classes/AnimatedVisuals/Lottie/UpdateIcon.lottie and /dev/null differ diff --git a/CollapseLauncher/Classes/EventsManagement/EventsHandler.cs b/CollapseLauncher/Classes/EventsManagement/EventsHandler.cs index 5f891f117..fcaf47cec 100644 --- a/CollapseLauncher/Classes/EventsManagement/EventsHandler.cs +++ b/CollapseLauncher/Classes/EventsManagement/EventsHandler.cs @@ -304,50 +304,6 @@ public class NotificationInvokerProp } #endregion - #region BackgroundRegion - internal static class BackgroundImgChanger - { - private static readonly BackgroundImgChangerInvoker Invoker = new(); - public static void ChangeBackground(string imgPath, Action actionAfterLoaded, - bool isCustom = true, bool isForceRecreateCache = false, bool isRequestInit = false) - { - Invoker!.ChangeBackground(imgPath, actionAfterLoaded, isCustom, isForceRecreateCache, isRequestInit); - } - public static void ToggleBackground(bool hide) => Invoker!.ToggleBackground(hide); - } - - internal class BackgroundImgChangerInvoker - { - public static event EventHandler ImgEvent; - public static event EventHandler IsImageHide; - - public void ChangeBackground(string imgPath, Action actionAfterLoaded, - bool isCustom, bool isForceRecreateCache = false, bool isRequestInit = false) - { - ImgEvent?.Invoke(this, new BackgroundImgProperty(imgPath, isCustom, isForceRecreateCache, isRequestInit, actionAfterLoaded)); - } - - public void ToggleBackground(bool hide) => IsImageHide?.Invoke(this, hide); - } - - internal class BackgroundImgProperty - { - internal BackgroundImgProperty(string imgPath, bool isCustom, bool isForceRecreateCache, bool isRequestInit, Action actionAfterLoaded) - { - ImgPath = imgPath; - IsCustom = isCustom; - IsForceRecreateCache = isForceRecreateCache; - IsRequestInit = isRequestInit; - ActionAfterLoaded = actionAfterLoaded; - } - - public Action ActionAfterLoaded { get; } - public bool IsRequestInit { get; } - public bool IsForceRecreateCache { get; } - public string ImgPath { get; } - public bool IsCustom { get; } - } - #endregion #region SpawnWebView2Region internal static class SpawnWebView2 { diff --git a/CollapseLauncher/Classes/Extension/DispatcherQueueExtensions.cs b/CollapseLauncher/Classes/Extension/DispatcherQueueExtensions.cs index 19e705f40..d35567fc8 100644 --- a/CollapseLauncher/Classes/Extension/DispatcherQueueExtensions.cs +++ b/CollapseLauncher/Classes/Extension/DispatcherQueueExtensions.cs @@ -1,11 +1,24 @@ using Microsoft.UI.Dispatching; using System; +using System.Threading.Tasks; +#nullable enable namespace CollapseLauncher.Extension { public static class DispatcherQueueExtensions { - public static bool HasThreadAccessSafe(this DispatcherQueue queue) + static DispatcherQueueExtensions() + { + CurrentDispatcherQueue ??= DispatcherQueue.GetForCurrentThread(); + } + + public static DispatcherQueue CurrentDispatcherQueue + { + get; + set; + } + + public static bool HasThreadAccessSafe(this DispatcherQueue? queue) { if (queue == null) return false; @@ -18,5 +31,31 @@ public static bool HasThreadAccessSafe(this DispatcherQueue queue) return false; // Return false if an exception occurs } } + + public static Task CreateObjectFromUIThread() + where T : new() + { + if (CurrentDispatcherQueue.HasThreadAccessSafe()) + { + return Task.FromResult(new T()); + } + + TaskCompletionSource tcs = new(); + Impl(); + + return tcs.Task; + + void Impl() + { + try + { + CurrentDispatcherQueue.TryEnqueue(() => tcs.SetResult(new T())); + } + catch (Exception e) + { + tcs.SetException(e); + } + } + } } } \ No newline at end of file diff --git a/CollapseLauncher/Classes/Extension/UIElementExtensions.SetCursor.cs b/CollapseLauncher/Classes/Extension/UIElementExtensions.SetCursor.cs new file mode 100644 index 000000000..b5acabe70 --- /dev/null +++ b/CollapseLauncher/Classes/Extension/UIElementExtensions.SetCursor.cs @@ -0,0 +1,50 @@ +using Microsoft.UI.Input; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using System; +using System.Runtime.CompilerServices; + +#nullable enable +#pragma warning disable IDE0130 +namespace CollapseLauncher.Extension; + +public static partial class UIElementExtensions +{ + public static readonly DependencyProperty CursorTypeProperty = + DependencyProperty.RegisterAttached("CursorType", typeof(InputSystemCursorShape), + typeof(UIElement), new PropertyMetadata(InputSystemCursorShape.Arrow)); + + public static InputSystemCursorShape GetCursorType(DependencyObject obj) => (InputSystemCursorShape)obj.GetValue(CursorTypeProperty); + + public static void SetCursorType(DependencyObject obj, InputSystemCursorShape value) + { + InputSystemCursor? cursor = InputSystemCursor.Create(value); + if (cursor is null || + obj is not UIElement asElement) + { + return; + } + + asElement.SetCursor(cursor); + asElement.SetValue(CursorTypeProperty, value); + } + + extension(Control source) + { + [UnsafeAccessor(UnsafeAccessorKind.Method, Name = "GetTemplateChild")] + private extern DependencyObject GetTemplateChildAccessor(string name); + + internal T GetTemplateChild(string name) + where T : class + { + DependencyObject obj = source.GetTemplateChildAccessor(name); + if (obj is not T castObj) + { + throw new + InvalidCastException($"Cannot cast type to: {typeof(T).Name} as the object expects type: {obj.GetType().Name}"); + } + + return castObj; + } + } +} diff --git a/CollapseLauncher/Classes/Extension/UIElementExtensions.SetIsTranslationEnabled.cs b/CollapseLauncher/Classes/Extension/UIElementExtensions.SetIsTranslationEnabled.cs new file mode 100644 index 000000000..860ca02da --- /dev/null +++ b/CollapseLauncher/Classes/Extension/UIElementExtensions.SetIsTranslationEnabled.cs @@ -0,0 +1,21 @@ +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Hosting; + +#nullable enable +#pragma warning disable IDE0130 +namespace CollapseLauncher.Extension; + +public static partial class UIElementExtensions +{ + public static readonly DependencyProperty IsTranslationEnabledProperty = + DependencyProperty.RegisterAttached("IsTranslationEnabled", typeof(bool), + typeof(UIElement), new PropertyMetadata(false)); + + public static bool GetIsTranslationEnabled(DependencyObject obj) => (bool)((UIElement)obj).GetValue(IsTranslationEnabledProperty); + + public static void SetIsTranslationEnabled(DependencyObject obj, bool value) + { + ElementCompositionPreview.SetIsTranslationEnabled((UIElement)obj, value); + ((UIElement)obj).SetValue(IsTranslationEnabledProperty, value); + } +} diff --git a/CollapseLauncher/Classes/Extension/UIElementExtensions.ThemeExtensions.cs b/CollapseLauncher/Classes/Extension/UIElementExtensions.ThemeExtensions.cs index bd33a12e3..f045cc4cb 100644 --- a/CollapseLauncher/Classes/Extension/UIElementExtensions.ThemeExtensions.cs +++ b/CollapseLauncher/Classes/Extension/UIElementExtensions.ThemeExtensions.cs @@ -8,7 +8,7 @@ #nullable enable namespace CollapseLauncher.Extension { - internal static partial class UIElementExtensions + public static partial class UIElementExtensions { private static string CurrentReversedThemeKey => InnerLauncherConfig.IsAppThemeLight ? "Dark" : "Light"; diff --git a/CollapseLauncher/Classes/Extension/UIElementExtensions.UnsafeAccessorExtensions.cs b/CollapseLauncher/Classes/Extension/UIElementExtensions.UnsafeAccessorExtensions.cs index 40a9d8432..efbeff7e4 100644 --- a/CollapseLauncher/Classes/Extension/UIElementExtensions.UnsafeAccessorExtensions.cs +++ b/CollapseLauncher/Classes/Extension/UIElementExtensions.UnsafeAccessorExtensions.cs @@ -5,7 +5,7 @@ #nullable enable namespace CollapseLauncher.Extension { - internal static partial class UIElementExtensions + public static partial class UIElementExtensions { /// /// Set the cursor for the element. diff --git a/CollapseLauncher/Classes/Extension/UIElementExtensions.cs b/CollapseLauncher/Classes/Extension/UIElementExtensions.cs index 08b471d43..57787320e 100644 --- a/CollapseLauncher/Classes/Extension/UIElementExtensions.cs +++ b/CollapseLauncher/Classes/Extension/UIElementExtensions.cs @@ -5,6 +5,7 @@ using Hi3Helper.CommunityToolkit.WinUI.Controls; using Hi3Helper.SentryHelper; using Microsoft.UI; +using Microsoft.UI.Dispatching; using Microsoft.UI.Input; using Microsoft.UI.Text; using Microsoft.UI.Xaml; @@ -20,6 +21,8 @@ using System.Linq; using System.Numerics; using System.Runtime.CompilerServices; +using System.Threading.Tasks; +using System.Xml.Linq; using Windows.UI; using Windows.UI.Text; using WinRT; @@ -36,7 +39,7 @@ internal class NavigationViewItemLocaleTextProperty public string LocalePropertyName { get; init; } } - internal static partial class UIElementExtensions + public static partial class UIElementExtensions { #nullable enable /// @@ -188,6 +191,22 @@ internal static void ApplyNavigationViewItemLocaleTextBindings(this NavigationVi navViewControl.UpdateLayout(); } + internal static void BindProperty(this FrameworkElement element, + object? source, + string propertyName, + DependencyProperty dependencyProperty, + BindingMode bindingMode, + IValueConverter? converter = null) + { + element.SetBinding(dependencyProperty, new Binding + { + Mode = bindingMode, + Source = source, + Path = new PropertyPath(propertyName), + Converter = converter + }); + } + internal static void BindProperty( this T element, DependencyProperty dependencyProperty, @@ -237,13 +256,18 @@ internal static TButtonBase CreateButtonWithIcon(string text = null string buttonStyle = "DefaultButtonStyle", double iconSize = 16d, double? textSize = null, CornerRadius? cornerRadius = null, FontWeight? textWeight = null) where TButtonBase : ButtonBase, new() { - Grid contentPanel = CreateIconTextGrid(text, iconGlyph, iconFontFamily, iconSize, textSize, textWeight); - TButtonBase buttonReturn = new TButtonBase(); + return RunFunctionReturnFromUIThread(Impl); - buttonReturn.CornerRadius = cornerRadius ?? AttachRoundedKindCornerRadius(buttonReturn); - buttonReturn.Content = contentPanel; - buttonReturn.Style = GetApplicationResource + \ No newline at end of file diff --git a/CollapseLauncher/XAMLs/Theme/CustomControls/LayeredBackgroundImage/LayeredBackgroundImageExtensions.cs b/CollapseLauncher/XAMLs/Theme/CustomControls/LayeredBackgroundImage/LayeredBackgroundImageExtensions.cs new file mode 100644 index 000000000..d60cce46a --- /dev/null +++ b/CollapseLauncher/XAMLs/Theme/CustomControls/LayeredBackgroundImage/LayeredBackgroundImageExtensions.cs @@ -0,0 +1,390 @@ +using Hi3Helper.Win32.WinRT.WindowsStream; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Media.Imaging; +using PhotoSauce.MagicScaler; +using PhotoSauce.MagicScaler.Transforms; +using PhotoSauce.NativeCodecs.Libheif; +using PhotoSauce.NativeCodecs.Libjxl; +using PhotoSauce.NativeCodecs.Libwebp; +using System; +using System.IO; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; +using Windows.Storage.Streams; + +// ReSharper disable SwitchStatementHandlesSomeKnownEnumValuesWithDefault +// ReSharper disable ConvertIfStatementToSwitchStatement + +#nullable enable +namespace CollapseLauncher.XAMLs.Theme.CustomControls.LayeredBackgroundImage; + +internal static class LayeredBackgroundImageExtensions +{ + private static readonly HttpClient Client; + + static LayeredBackgroundImageExtensions() + { + // Initialize support for MagicScaler's WebP decoding + CodecManager.Configure(InitializeMagicScalerCodecs); + Client = CreateHttpClient(); + } + + private static void InitializeMagicScalerCodecs(CodecCollection codecs) + { + codecs.UseWicCodecs(WicCodecPolicy.All); + codecs.UseLibwebp(); + codecs.UseLibheif(); + codecs.UseLibjxl(); + } + + private static HttpClient CreateHttpClient() + { + SocketsHttpHandler handler = new() + { + AllowAutoRedirect = true, + MaxConnectionsPerServer = Environment.ProcessorCount * 2 + }; + return new HttpClient(handler, false); + } + + internal static async ValueTask LoadImageAsync( + this Image image, + Uri? sourceFromPath, + Stream? sourceFromStream, + LayeredBackgroundImage instance, + DependencyProperty useCacheProperty, + IPixelTransform? pixelTransform = null) + { + IMediaCacheHandler? cacheHandler = instance.MediaCacheHandler; + bool isDisposeStream = sourceFromStream == null; + bool forceUseInternalDecoder = false; + + // Try get cached source from cache handler + if (cacheHandler != null) + { + object? source = sourceFromPath; + source ??= sourceFromStream; + MediaCacheResult cacheResult = await cacheHandler.LoadCachedSource(source); + + forceUseInternalDecoder = cacheResult.ForceUseInternalDecoder; + isDisposeStream = cacheResult.DisposeStream; + + if (cacheResult.CachedSource is Uri sourceAsPath) + { + sourceFromPath = sourceAsPath; + sourceFromStream = null; + } + else if (cacheResult.CachedSource is Stream sourceAsStream) + { + sourceFromPath = null; + sourceFromStream = sourceAsStream; + } + else + { + return false; + } + } + + try + { + if (sourceFromPath != null) + { + return await image.LoadImageFromUriPathSourceAsync(sourceFromPath, + forceUseInternalDecoder, + instance, + useCacheProperty, + pixelTransform); + } + + if (sourceFromStream != null) + { + return await image.LoadImageFromStreamSourceAsync(sourceFromStream, + forceUseInternalDecoder, + instance, + useCacheProperty, + pixelTransform); + } + + return false; + } + finally + { + if (isDisposeStream && sourceFromStream != null) + { + await sourceFromStream.DisposeAsync(); + } + } + } + + private static async ValueTask LoadImageFromUriPathSourceAsync( + this Image image, + Uri sourceFromPath, + bool forceUseInternalDecoder, + LayeredBackgroundImage instance, + DependencyProperty useCacheProperty, + IPixelTransform? pixelTransform = null) + { + string extension = Path.GetExtension(sourceFromPath.ToString()); + bool isInternalFormat = LayeredBackgroundImage + .SupportedImageBitmapExtensionsLookup + .Contains(extension); + bool isSvgFormat = LayeredBackgroundImage + .SupportedImageVectorExtensionsLookup + .Contains(extension); + + if ((forceUseInternalDecoder || + isInternalFormat || + isSvgFormat) && pixelTransform == null) + { + if (isSvgFormat) + { + image.Source = new SvgImageSource(sourceFromPath); + return true; + } + + image.Source = new BitmapImage(sourceFromPath) + { + CreateOptions = (bool)instance.GetValue(useCacheProperty) + ? BitmapCreateOptions.None + : BitmapCreateOptions.IgnoreImageCache + }; + return true; + } + + await using FileStream? fileStream = await TryGetStreamFromPathAsync(sourceFromPath); + if (fileStream == null) + { + return false; + } + + // Borrow loading process from stream source loader. + // We gonna ignore internal decoder enforcement here because, uh... idk. + return await image + .LoadImageFromStreamSourceAsync(fileStream, + false, + instance, + useCacheProperty, + pixelTransform); + } + + private static async ValueTask LoadImageFromStreamSourceAsync( + this Image image, + Stream sourceFromStream, + bool forceUseInternalDecoder, + LayeredBackgroundImage instance, + DependencyProperty useCacheProperty, + IPixelTransform? pixelTransform = null) + { + (Stream? stream, bool isTemporaryStream) = + await sourceFromStream.GetNativeOrCopiedStreamIfNotSeekable(CancellationToken.None); + + if (stream == null) + { + return false; + } + + try + { + // Reset position + stream.Position = 0; + + // Guess codec type + ImageExternalCodecType codecType = await stream.GuessImageFormatFromStreamAsync(); + if (codecType == ImageExternalCodecType.NotSupported) + { + return false; + } + + // Reset position after format guessing + stream.Position = 0; + + if ((forceUseInternalDecoder || + codecType == ImageExternalCodecType.Default) && + pixelTransform != null) + { + using IRandomAccessStream sourceRandomStream = stream.AsRandomAccessStream(true); + BitmapImage bitmapImage = new() + { + CreateOptions = (bool)instance.GetValue(useCacheProperty) + ? BitmapCreateOptions.None + : BitmapCreateOptions.IgnoreImageCache + }; + await bitmapImage.SetSourceAsync(sourceRandomStream); + image.Source = bitmapImage; + return true; + } + + if (codecType == ImageExternalCodecType.Svg) + { + using IRandomAccessStream sourceRandomStream = stream.AsRandomAccessStream(true); + SvgImageSource svgImageSource = new(); + svgImageSource.SetSourceAsync(sourceRandomStream); + image.Source = svgImageSource; + return true; + } + + // Use MagicScaler for external codec types + await using FileStream tempStream = CreateTemporaryStream(); + await Task.Run(() => + { + ProcessImageSettings settings = new(); + settings.TrySetEncoderFormat(ImageMimeTypes.Png); + + using ProcessingPipeline pipeline = MagicImageProcessor.BuildPipeline(stream, settings); + if (pixelTransform != null) + { + pipeline.AddTransform(pixelTransform); + } + + pipeline.WriteOutput(tempStream); + }); + + tempStream.Position = 0; + using IRandomAccessStream tempRandomStream = tempStream.AsRandomAccessStream(true); + BitmapImage tempBitmapImage = new() + { + CreateOptions = (bool)instance.GetValue(useCacheProperty) + ? BitmapCreateOptions.None + : BitmapCreateOptions.IgnoreImageCache + }; + await tempBitmapImage.SetSourceAsync(tempRandomStream); + image.Source = tempBitmapImage; + return true; + } + finally + { + if (isTemporaryStream) + { + await stream.DisposeAsync(); + } + } + } + + private static async Task TryGetStreamFromPathAsync(Uri? url) + { + if (url == null) + { + return null; + } + + if (url.IsFile) + { + return File.Open(url.LocalPath, FileMode.Open, FileAccess.Read, FileShare.Read); + } + + if (await GetFileLengthFromUrl(Client, url) is 0) + { + return null; + } + + HttpRequestMessage requestMessage = new(HttpMethod.Get, url); + HttpResponseMessage responseMessage = + await Client.SendAsync(requestMessage, + HttpCompletionOption.ResponseHeadersRead); + + if (!responseMessage.IsSuccessStatusCode) + { + responseMessage.Dispose(); + requestMessage.Dispose(); + return null; + } + + FileStream tempStream = url.CreateTemporaryStreamFromUrl(); + try + { + await using Stream networkStream = await responseMessage.Content.ReadAsStreamAsync(); + await networkStream.CopyToAsync(tempStream); + return tempStream; + } + catch (Exception e) + { + Console.WriteLine(e); + await tempStream.DisposeAsync(); + } + + return null; + } + + private static async Task GetFileLengthFromUrl(HttpClient client, Uri url) + { + HttpRequestMessage requestMessage = new(HttpMethod.Head, url); + HttpResponseMessage responseMessage = + await client.SendAsync(requestMessage, HttpCompletionOption.ResponseHeadersRead); + + if (responseMessage.IsSuccessStatusCode) + { + return responseMessage.Content.Headers.ContentLength ?? 0; + } + + responseMessage.Dispose(); + requestMessage.Dispose(); + return 0; + } + + internal static double GetClampedVolume(this double thisVolume) + { + if (double.IsNaN(thisVolume) || + double.IsInfinity(thisVolume)) + { + thisVolume = 0; + } + + return Math.Clamp(thisVolume, 0, 100d) / 100d; + } + + private static async ValueTask<(Stream? Stream, bool IsTemporaryStream)> + GetNativeOrCopiedStreamIfNotSeekable( + this T stream, + CancellationToken token) + where T : Stream + { + // If it's seekable, then just return it + if (stream.CanSeek) + { + return (stream, false); + } + + // Copy over + FileStream tempStream = CreateTemporaryStream(); + try + { + await stream.CopyToAsync(tempStream, token); + return (tempStream, true); + } + catch + { + await tempStream.DisposeAsync(); + return (null, false); + } + } + + private static FileStream CreateTemporaryStreamFromUrl(this Uri url) + { + string extension = Path.GetExtension(url.AbsolutePath); + string path = Path.Combine(Path.GetTempPath(), Path.GetTempFileName() + extension); + + return File.Open(path, + new FileStreamOptions + { + Mode = FileMode.Create, + Access = FileAccess.ReadWrite, + Share = FileShare.ReadWrite, + Options = FileOptions.DeleteOnClose + }); + } + + private static FileStream CreateTemporaryStream() + { + string path = Path.Combine(Path.GetTempPath(), Path.GetTempFileName()); + return File.Open(path, + new FileStreamOptions + { + Mode = FileMode.Create, + Access = FileAccess.ReadWrite, + Share = FileShare.ReadWrite, + Options = FileOptions.DeleteOnClose + }); + } +} diff --git a/CollapseLauncher/XAMLs/Theme/CustomControls/LayeredBackgroundImage/LayeredBackgroundImage_themeresources.xaml b/CollapseLauncher/XAMLs/Theme/CustomControls/LayeredBackgroundImage/LayeredBackgroundImage_themeresources.xaml new file mode 100644 index 000000000..e6f44a0db --- /dev/null +++ b/CollapseLauncher/XAMLs/Theme/CustomControls/LayeredBackgroundImage/LayeredBackgroundImage_themeresources.xaml @@ -0,0 +1,21 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/CollapseLauncher/XAMLs/Theme/CustomControls/ManagedUIElementList.cs b/CollapseLauncher/XAMLs/Theme/CustomControls/ManagedUIElementList.cs new file mode 100644 index 000000000..a8dc028e9 --- /dev/null +++ b/CollapseLauncher/XAMLs/Theme/CustomControls/ManagedUIElementList.cs @@ -0,0 +1,225 @@ +using Microsoft.UI.Xaml; +using System.Collections; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.ComponentModel; +using System.Runtime.CompilerServices; +using WinRT; + +// ReSharper disable StaticMemberInGenericType + +#nullable enable +namespace CollapseLauncher.XAMLs.Theme.CustomControls; + +[ProjectedRuntimeClass(typeof(IList))] +[GeneratedBindableCustomProperty] +public partial class ManagedUIElementList : IList, INotifyCollectionChanged, INotifyPropertyChanged +{ + private readonly List _backedList; + + #region Cached Property Changes Arguments + + private static readonly PropertyChangedEventArgs CountPropertyChanged = new(nameof(Count)); + private static readonly PropertyChangedEventArgs IndexerPropertyChanged = new("Item[]"); + + #endregion + + #region Events + + /// + public event NotifyCollectionChangedEventHandler? CollectionChanged; + + /// + public event PropertyChangedEventHandler? PropertyChanged; + + #endregion + + /// + /// Creates a new empty Observable List + /// + public ManagedUIElementList() => _backedList = []; + + /// + /// Creates a new Observable List from the enumerable. + /// + /// + /// Borrow the current instance of instead of allocating new backed list if possible. + public ManagedUIElementList(IEnumerable enumerable, bool useBorrow = false) + { + if (enumerable is List borrowedList && + useBorrow) + { + _backedList = borrowedList; + return; + } + + _backedList = [.. enumerable]; + } + + /// + public IEnumerator GetEnumerator() => _backedList.GetEnumerator(); + + /// + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + /// + public void Add(UIElement item) => Add(item, true); + + /// + /// Adds an item to the backed List and notify the changes. + /// + /// The object to add to the backed List. + /// Whether to notify the changes or not. + public void Add(UIElement item, bool notifyChanges) + { + _backedList.Add(item); + if (!notifyChanges) + { + return; + } + + NotifyCountPropertyChange(); + NotifyIndexerPropertyChange(); + CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item)); + } + + public void AddRange(IEnumerable items) + { + _backedList.AddRange(items); + + NotifyCountPropertyChange(); + NotifyIndexerPropertyChange(); + CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, items)); + } + + /// + public void Clear() => Clear(true); + + /// + /// Removes all items from the backed List and notify the changes. + /// + /// Whether to notify the changes or not. + public void Clear(bool notifyChanges) + { + _backedList.Clear(); + if (!notifyChanges) + { + return; + } + + NotifyCountPropertyChange(); + NotifyIndexerPropertyChange(); + CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); + } + + /// + public bool Contains(UIElement item) => _backedList.Contains(item); + + /// + public void CopyTo(UIElement[] array, int arrayIndex) => _backedList.CopyTo(array, arrayIndex); + + /// + public int Count => _backedList.Count; + + /// + public bool IsReadOnly => false; + + /// + public int IndexOf(UIElement item) => _backedList.IndexOf(item); + + /// + public bool Remove(UIElement item) => Remove(item, true); + + /// + /// Removes the first occurrence of a specific object from the backed List. + /// + /// The object to remove from the backed List. + /// Whether to notify the changes or not. + /// + /// if was successfully removed from the backed List; otherwise, . + /// This method also returns if is not found from the backed List. + /// + public bool Remove(UIElement item, bool notifyChanges) + { + bool isSuccess = _backedList.Remove(item); + + if (!isSuccess) + { + return false; + } + + if (!notifyChanges) + { + return true; + } + + NotifyCountPropertyChange(); + NotifyIndexerPropertyChange(); + CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item)); + return true; + } + + /// + public void Insert(int index, UIElement item) => Insert(index, item, true); + + /// + /// Inserts an item to the backed List at the specified index. + /// + /// The zero-based index at which should be inserted. + /// The object to insert into the backed List. + /// Whether to notify the changes or not. + public void Insert(int index, UIElement item, bool notifyChanges) + { + _backedList.Insert(index, item); + + if (!notifyChanges) + { + return; + } + + NotifyCountPropertyChange(); + NotifyIndexerPropertyChange(); + CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item, index)); + } + + /// + public void RemoveAt(int index) => RemoveAt(index, true); + + /// + /// Removes the backed List item at the specified index. + /// + /// The zero-based index of the item to remove. + /// Whether to notify the changes or not. + public void RemoveAt(int index, bool notifyChanges) + { + UIElement item = _backedList[index]; + _backedList.Remove(item); + + if (!notifyChanges) + { + return; + } + + NotifyCountPropertyChange(); + NotifyIndexerPropertyChange(); + CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item, index)); + } + + /// + [IndexerName("Item")] + public UIElement this[int index] + { + get => _backedList[index]; + set + { + UIElement oldItem = _backedList[index]; + UIElement newItem = _backedList[index] = value; + + NotifyIndexerPropertyChange(); + CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, newItem, oldItem, index)); + } + } + + private void NotifyCountPropertyChange() => PropertyChanged?.Invoke(this, CountPropertyChanged); + private void NotifyIndexerPropertyChange() => PropertyChanged?.Invoke(this, IndexerPropertyChanged); +} diff --git a/CollapseLauncher/XAMLs/Theme/CustomControls/NewPipsPager/NewPipsPager.Converters.cs b/CollapseLauncher/XAMLs/Theme/CustomControls/NewPipsPager/NewPipsPager.Converters.cs new file mode 100644 index 000000000..91ab0c973 --- /dev/null +++ b/CollapseLauncher/XAMLs/Theme/CustomControls/NewPipsPager/NewPipsPager.Converters.cs @@ -0,0 +1,23 @@ +using Microsoft.UI.Xaml.Data; +using System; + +#nullable enable +namespace CollapseLauncher.XAMLs.Theme.CustomControls.NewPipsPager; + +internal partial class IndexAddOneConverter : IValueConverter +{ + public object Convert(object value, Type targetType, object parameter, string language) + { + if (value is int asInt) + { + return asInt + 1; + } + + return value; + } + + public object ConvertBack(object value, Type targetType, object parameter, string language) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/CollapseLauncher/XAMLs/Theme/CustomControls/NewPipsPager/NewPipsPager.Enums.cs b/CollapseLauncher/XAMLs/Theme/CustomControls/NewPipsPager/NewPipsPager.Enums.cs new file mode 100644 index 000000000..22fa67adf --- /dev/null +++ b/CollapseLauncher/XAMLs/Theme/CustomControls/NewPipsPager/NewPipsPager.Enums.cs @@ -0,0 +1,14 @@ +namespace CollapseLauncher.XAMLs.Theme.CustomControls.NewPipsPager; + +public enum NewPipsPagerNavigationMode +{ + Auto, + Hidden, + Visible +} + +public enum NewPipsPagerSelectionMode +{ + Click, + Hover +} \ No newline at end of file diff --git a/CollapseLauncher/XAMLs/Theme/CustomControls/NewPipsPager/NewPipsPager.Events.cs b/CollapseLauncher/XAMLs/Theme/CustomControls/NewPipsPager/NewPipsPager.Events.cs new file mode 100644 index 000000000..6dd8deafd --- /dev/null +++ b/CollapseLauncher/XAMLs/Theme/CustomControls/NewPipsPager/NewPipsPager.Events.cs @@ -0,0 +1,403 @@ +using Microsoft.UI.Input; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Input; +using System; +using System.Linq; +using System.Numerics; +using Windows.Foundation; +using Windows.System; + +#nullable enable +namespace CollapseLauncher.XAMLs.Theme.CustomControls.NewPipsPager; + +public partial class NewPipsPager +{ + #region Size Measure Override + + protected override Size MeasureOverride(Size parentSize) + { + Orientation orientation = Orientation; + double pipsButtonSize = GetButtonSize(orientation); + + Vector2 containerSize = _pipsPagerItemsRepeater.ActualSize; + double containerTotalWidth = containerSize.X; + double containerTotalHeight = containerSize.Y; + + GetNavigationButtonTotalSize(PreviousNavigationButtonMode, + _previousPageButton, + out double buttonPrevSizeTotalWidth, + out double buttonPrevSizeTotalHeight); + + GetNavigationButtonTotalSize(NextNavigationButtonMode, + _nextPageButton, + out double buttonNextSizeTotalWidth, + out double buttonNextSizeTotalHeight); + + Vector2 scrollViewportSize = parentSize.ToVector2(); + double scrollViewportTotalWidth = scrollViewportSize.X; + double scrollViewportTotalHeight = scrollViewportSize.Y; + + Size selfSize = base.MeasureOverride(parentSize); + double totalCalculatedWidth = selfSize.Width; + double totalCalculatedHeight = selfSize.Height; + + if (orientation == Orientation.Horizontal) + { + _pipsPagerScrollViewer.MaxWidth = + GetViewportSize(scrollViewportTotalWidth, + containerTotalWidth, + buttonPrevSizeTotalWidth, + buttonNextSizeTotalWidth, + pipsButtonSize, + out bool isContainerLarger); + + totalCalculatedWidth = 0; + totalCalculatedWidth += !isContainerLarger + ? containerTotalWidth + : _pipsPagerScrollViewer.MaxWidth; + totalCalculatedWidth += buttonPrevSizeTotalWidth + + buttonNextSizeTotalWidth; + } + else + { + _pipsPagerScrollViewer.MaxHeight = + GetViewportSize(scrollViewportTotalHeight, + containerTotalHeight, + buttonPrevSizeTotalHeight, + buttonNextSizeTotalHeight, + pipsButtonSize, + out bool isContainerLarger); + + totalCalculatedHeight = 0; + totalCalculatedHeight += !isContainerLarger + ? containerTotalHeight + : _pipsPagerScrollViewer.MaxHeight; + totalCalculatedHeight += buttonPrevSizeTotalHeight + + buttonNextSizeTotalHeight; + } + + return new Size(totalCalculatedWidth, totalCalculatedHeight); + } + + private static void GetNavigationButtonTotalSize( + NewPipsPagerNavigationMode mode, + Button element, + out double width, + out double height) + { + bool isVisible = mode != NewPipsPagerNavigationMode.Hidden; + Vector2 size = isVisible ? element.ActualSize : Vector2.Zero; + Thickness margin = isVisible ? element.Margin : default; + width = size.X + margin.Left + margin.Right; + height = size.Y + margin.Top + margin.Bottom; + } + + private static double GetViewportSize(double initialViewportSize, + double initialContainerSize, + double previousSideElementSize, + double nextSideElementSize, + double perButtonSize, + out bool isContainerLarger) + { + // Decrease viewport based on total width of navigation buttons + initialViewportSize -= previousSideElementSize + nextSideElementSize; + isContainerLarger = initialContainerSize > initialViewportSize; + + // Clamp to display only viewable pips + if (isContainerLarger) + { + double dividedPerButtonSize = Math.Floor(initialViewportSize / perButtonSize); + initialViewportSize = dividedPerButtonSize * perButtonSize; + int clampedNth = (int)dividedPerButtonSize; + if (clampedNth % 2 == 0) + { + initialViewportSize = (clampedNth - 1) * perButtonSize; + } + + return Math.Max(initialViewportSize, 0); + } + + return double.PositiveInfinity; + } + + #endregion + + #region UI Events - Navigation Buttons + + private void PreviousPageButton_OnClick(object sender, RoutedEventArgs e) => ItemIndex--; + + private void NextPageButton_OnClick(object sender, RoutedEventArgs e) => ItemIndex++; + + private void KeyboardKeys_Pressed(object sender, KeyRoutedEventArgs e) + { + switch (e.Key) + { + case VirtualKey.Left: + case VirtualKey.Up: + PreviousPageButton_OnClick(sender, e); + break; + case VirtualKey.Right: + case VirtualKey.Down: + NextPageButton_OnClick(sender, e); + break; + } + } + + #endregion + + #region UI Events - Orientation + + private static void Orientation_OnChange(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + NewPipsPager pager = (NewPipsPager)d; + Orientation orientation = (Orientation)e.NewValue; + + Orientation_OnChange(pager, orientation); + } + + private static void Orientation_OnChange(NewPipsPager pager, Orientation orientation) + { + string state = orientation == Orientation.Vertical + ? "VerticalOrientationView" + : "HorizontalOrientationView"; + VisualStateManager.GoToState(pager, state, true); + } + + #endregion + + #region Property Changes + + private static void ItemsCount_OnChange(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + if (d is not NewPipsPager pager) + { + return; + } + + object obj = e.NewValue; + int value = 0; + if (obj is int asInt) + { + value = asInt; + } + + pager.ItemsCount_OnChange(value); + } + + private void ItemsCount_OnChange(int value) + { + if (!_isTemplateLoaded) + { + return; + } + + if (value < 0) + { + throw new IndexOutOfRangeException("ItemsCount cannot be negative!"); + } + + int oldItemsCount = _itemsDummy.Length; + + using (_atomicLock.EnterScope()) + { + try + { + + if (value == 0) + { + _itemsDummy = []; + return; + } + + _itemsDummy = Enumerable.Range(0, value).ToArray(); + } + finally + { + // Update ItemsSource if already assigned + _pipsPagerItemsRepeater.ItemsSource = _itemsDummy; + _pipsPagerItemsRepeater.UpdateLayout(); + + // Update index only if the count is invalid + int currentIndex = ItemIndex; + if (currentIndex > value || + (value != 0 && currentIndex < 0)) + { + ItemIndex = 0; + } + + ItemsCountChanged?.Invoke(this, new ChangedStructItemArgs(oldItemsCount, value)); + } + } + } + + private static void ItemIndex_OnChange(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + // Ignore if the old and new index are equal + if (e is not { NewValue: int asNewIndex, OldValue: int asOldIndex } || + asNewIndex == asOldIndex) + { + return; + } + + NewPipsPager pager = (NewPipsPager)d; + if (!pager.IsLoaded) + { + return; + } + + // Update navigation buttons state + UpdatePreviousButtonVisualState(pager); + UpdateNextButtonVisualState(pager); + + // Update pip buttons state + UpdateAndBringSelectedPipToView(pager, asNewIndex, asOldIndex); + + // Update pager layout + pager.UpdateLayout(); + } + + #endregion + + #region ItemsRepeater + + private void ItemsRepeater_ElementPrepared(ItemsRepeater sender, ItemsRepeaterElementPreparedEventArgs args) + { + if (args.Element is not Button asButton) + { + return; + } + + if (asButton.Tag is not int asIndex) + { + return; + } + + AssignPipButtonStyle(asButton, + asIndex != ItemIndex + ? NormalPipButtonStyle + : SelectedPipButtonStyle); + + // Avoid redundant loaded + unloaded events assignment + if (asButton.IsLoaded) + { + return; + } + + asButton.Loaded += ItemsRepeaterPipButton_LoadedEvent; + asButton.Unloaded += ItemsRepeaterPipButton_UnloadedEvent; + } + + private void ItemsRepeater_OnSizeChanged(object sender, SizeChangedEventArgs e) => InvalidateMeasure(); + + private void ItemsRepeaterPipButton_UnloadedEvent(object sender, RoutedEventArgs e) + { + Button button = (Button)sender; + if (SelectionMode == NewPipsPagerSelectionMode.Click) + { + button.Click -= ItemsRepeaterPipButton_OnClick; + } + else + { + button.PointerEntered -= ItemsRepeaterPipButton_OnClick; + } + + button.Loaded -= ItemsRepeaterPipButton_LoadedEvent; + button.Unloaded -= ItemsRepeaterPipButton_UnloadedEvent; + } + + private void ItemsRepeaterPipButton_LoadedEvent(object sender, RoutedEventArgs e) + { + Button button = (Button)sender; + if (SelectionMode == NewPipsPagerSelectionMode.Click) + { + button.Click += ItemsRepeaterPipButton_OnClick; + } + else + { + button.PointerEntered += ItemsRepeaterPipButton_OnClick; + } + } + + private void ItemsRepeaterPipButton_OnClick(object sender, RoutedEventArgs args) + { + ItemIndex = (int)((Button)sender).Tag; + } + + #endregion + + #region ScrollViewer + + private void ScrollViewer_OnPointerWheelChanged(object sender, PointerRoutedEventArgs e) + { + if (!e.Pointer.IsInRange || + sender is not UIElement element) + { + return; + } + + Orientation layoutOrientation = Orientation; + double pipsButtonSize = GetButtonSize(layoutOrientation); + + PointerPoint pointer = e.GetCurrentPoint(element); + int orientation = pointer.Properties.MouseWheelDelta; + bool isHorizontal = layoutOrientation == Orientation.Horizontal; + double delta = pipsButtonSize * (orientation / 120d); + + double toOffset = (isHorizontal + ? _pipsPagerScrollViewer.HorizontalOffset + : _pipsPagerScrollViewer.VerticalOffset) + -delta; + toOffset = Math.Round(toOffset / pipsButtonSize) * pipsButtonSize; + + if (isHorizontal) + { + toOffset = Math.Clamp(toOffset, 0, _pipsPagerScrollViewer.ExtentWidth); + _pipsPagerScrollViewer.ChangeView(toOffset, _pipsPagerScrollViewer.VerticalOffset, _pipsPagerScrollViewer.ZoomFactor); + } + else + { + toOffset = Math.Clamp(toOffset, 0, _pipsPagerScrollViewer.ExtentHeight); + _pipsPagerScrollViewer.ChangeView(_pipsPagerScrollViewer.HorizontalOffset, toOffset, _pipsPagerScrollViewer.ZoomFactor); + } + } + + private double GetButtonSize(Orientation orientation) + { + double pipsButtonSize = 0d; + + if (_pipsPagerItemsRepeater.TryGetElement(0) is UIElement button) + { + var desiredSize = button.ActualSize; + pipsButtonSize = orientation == Orientation.Horizontal + ? desiredSize.X + : desiredSize.Y; + } + + return pipsButtonSize; + } + + #endregion + + #region Loaded and Unloaded + + private void NewPipsPager_Unloaded(object sender, RoutedEventArgs e) + { + UnapplyNavigationButtonEvents(); + UnapplyKeyPressEvents(); + UnapplyItemsRepeaterEvents(); + + _pipsPagerItemsRepeater.ItemsSource = null; + } + + private void NewPipsPager_Loaded(object sender, RoutedEventArgs e) + { + ItemsCount_OnChange(ItemsCount); + UpdateAndBringSelectedPipToView(this, ItemIndex, -1); + + // Update navigation buttons state + UpdatePreviousButtonVisualState(this); + UpdateNextButtonVisualState(this); + } + + #endregion +} diff --git a/CollapseLauncher/XAMLs/Theme/CustomControls/NewPipsPager/NewPipsPager.Properties.cs b/CollapseLauncher/XAMLs/Theme/CustomControls/NewPipsPager/NewPipsPager.Properties.cs new file mode 100644 index 000000000..59c3fdca3 --- /dev/null +++ b/CollapseLauncher/XAMLs/Theme/CustomControls/NewPipsPager/NewPipsPager.Properties.cs @@ -0,0 +1,300 @@ +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using System; +using System.Threading; +using Windows.Foundation; + +#nullable enable +namespace CollapseLauncher.XAMLs.Theme.CustomControls.NewPipsPager; + +public partial class NewPipsPager +{ + #region Events + + public event TypedEventHandler>? ItemsCountChanged; + public event TypedEventHandler>? ItemIndexChanged; + + #endregion + + #region Properties + + public Orientation Orientation + { + get => (Orientation)GetValue(OrientationProperty); + set => SetValue(OrientationProperty, value); + } + + public int ItemsCount + { + get => (int)GetValue(ItemsCountProperty); + set => SetValue(ItemsCountProperty, value); + } + + public int ItemIndex + { + get => (int)GetValue(ItemIndexProperty); + set + { + using (_atomicLock.EnterScope()) + { + int itemsCount = ItemsCount; + if (itemsCount == 0) + { + return; + } + + if (value < 0) + { + value = itemsCount - 1; + } + + if (value >= itemsCount) + { + value = 0; + } + + SetValue(ItemIndexProperty, value); + } + } + } + + public NewPipsPagerSelectionMode SelectionMode + { + get => (NewPipsPagerSelectionMode)GetValue(SelectionModeProperty); + set => SetValue(SelectionModeProperty, value); + } + + public NewPipsPagerNavigationMode PreviousNavigationButtonMode + { + get => (NewPipsPagerNavigationMode)GetValue(PreviousNavigationButtonModeProperty); + set => SetValue(PreviousNavigationButtonModeProperty, value); + } + + public NewPipsPagerNavigationMode NextNavigationButtonMode + { + get => (NewPipsPagerNavigationMode)GetValue(NextNavigationButtonModeProperty); + set => SetValue(NextNavigationButtonModeProperty, value); + } + + public Style PreviousButtonStyle + { + get => (Style)GetValue(PreviousButtonStyleProperty); + set => SetValue(PreviousButtonStyleProperty, value); + } + + public Style NextButtonStyle + { + get => (Style)GetValue(NextButtonStyleProperty); + set => SetValue(NextButtonStyleProperty, value); + } + + public Style NormalPipButtonStyle + { + get => (Style)GetValue(NormalPipButtonStyleProperty); + set => SetValue(NormalPipButtonStyleProperty, value); + } + + public Style SelectedPipButtonStyle + { + get => (Style)GetValue(SelectedPipButtonStyleProperty); + set => SetValue(SelectedPipButtonStyleProperty, value); + } + + #endregion + + #region Fields + + private readonly Lock _atomicLock = new(); + + private int[] _itemsDummy = []; + + #endregion + + #region Dependency Change Methods + + private static void UpdatePreviousButtonVisualState(NewPipsPager pager) + { + UpdateButtonVisualState(pager, + pager._previousPageButton, + pager.ItemIndex > 0, + NavButtonStatePreviousPageButtonCollapsed, + NavButtonStatePreviousPageButtonVisible, + NavButtonStatePreviousPageButtonHidden, + pager.PreviousNavigationButtonMode); + } + + private static void UpdateNextButtonVisualState(NewPipsPager pager) + { + UpdateButtonVisualState(pager, + pager._nextPageButton, + pager.ItemIndex + 1 < pager.ItemsCount, + NavButtonStateNextPageButtonCollapsed, + NavButtonStateNextPageButtonVisible, + NavButtonStateNextPageButtonHidden, + pager.NextNavigationButtonMode); + } + + private static void UpdateButtonVisualState( + NewPipsPager instance, + Button? button, + bool conditionForAutoVisible, + string stateNameForCollapsed, + string stateNameForVisible, + string stateNameForHidden, + NewPipsPagerNavigationMode mode) + { + if (button == null) + { + return; + } + + if (mode == NewPipsPagerNavigationMode.Hidden) + { + VisualStateManager.GoToState(instance, stateNameForCollapsed, true); + return; + } + + VisualStateManager.GoToState(instance, stateNameForVisible, true); + button.IsEnabled = true; + if (mode == NewPipsPagerNavigationMode.Visible) + { + return; + } + + if (conditionForAutoVisible) + { + return; + } + + button.IsEnabled = false; + VisualStateManager.GoToState(instance, stateNameForHidden, true); + } + + private static void UpdateAndBringSelectedPipToView(NewPipsPager pager, int newIndex, int oldIndex) + { + if (pager.UpdateSelectedPipStyle(newIndex, oldIndex) is not { } asButton) + { + return; + } + + BringIntoViewOptions options = new() + { + AnimationDesired = true + }; + if (pager.Orientation == Orientation.Horizontal) + { + options.HorizontalAlignmentRatio = 0.5d; + } + else + { + options.VerticalAlignmentRatio = 0.5d; + } + asButton.StartBringIntoView(options); + } + + private Button? UpdateSelectedPipStyle(int newIndex, int oldIndex) + { + ItemsRepeater? repeater = _pipsPagerItemsRepeater; + + try + { + if (!_isTemplateLoaded || + repeater?.ItemsSourceView == null) + { + return null; + } + + int childCount = repeater.ItemsSourceView.Count; + bool isUpdateNewChild = newIndex >= 0 && newIndex < childCount; + bool isUpdateOldChild = oldIndex >= 0 && oldIndex < childCount; + + if (ItemsCount == 0) + { + return null; + } + + Button? newIndexPipButton = repeater.GetOrCreateElement(newIndex) as Button; + Button? oldIndexPipButton = repeater.TryGetElement(oldIndex) as Button; + + try + { + if (isUpdateOldChild) + { + AssignPipButtonStyle(oldIndexPipButton, NormalPipButtonStyle); + } + + if (isUpdateNewChild) + { + return AssignPipButtonStyle(newIndexPipButton, SelectedPipButtonStyle); + } + + return newIndexPipButton; + } + finally + { + if (newIndex != oldIndex) + { + ItemIndexChanged?.Invoke(this, new ChangedStructItemArgs(oldIndex, newIndex)); + } + } + } + catch + { + // ignored + } + + return null; + } + + private static Button? AssignPipButtonStyle(Button? button, Style? style) + { + if (button is null) + { + return button; + } + + button.Style = style; + button.UpdateLayout(); + VisualStateManager.GoToState(button, PipButtonStateNormal, true); + return button; + } + + private static Style? TryGetStyle(string styleName) + { + if (Application.Current.Resources.TryGetValue(styleName, out object styleObj) && + styleObj is Style asStyle) + { + return asStyle; + } + + return null; + } + + private static void PreviousNavigationButtonMode_OnChange(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + UpdatePreviousButtonVisualState((NewPipsPager)d); + } + + private static void NextNavigationButtonMode_OnChange(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + UpdateNextButtonVisualState((NewPipsPager)d); + } + + #endregion + + #region Dependency Properties + + public static readonly DependencyProperty OrientationProperty = DependencyProperty.Register(nameof(Orientation), typeof(Orientation), typeof(NewPipsPager), new PropertyMetadata(Orientation.Vertical, Orientation_OnChange)); + public static readonly DependencyProperty ItemsCountProperty = DependencyProperty.Register(nameof(ItemsCount), typeof(int), typeof(NewPipsPager), new PropertyMetadata(0, ItemsCount_OnChange)); + public static readonly DependencyProperty ItemIndexProperty = DependencyProperty.Register(nameof(ItemIndex), typeof(int), typeof(NewPipsPager), new PropertyMetadata(-1, ItemIndex_OnChange)); + public static readonly DependencyProperty SelectionModeProperty = DependencyProperty.Register(nameof(SelectionMode), typeof(bool), typeof(NewPipsPager), new PropertyMetadata(NewPipsPagerSelectionMode.Click)); + public static readonly DependencyProperty PreviousNavigationButtonModeProperty = DependencyProperty.Register(nameof(PreviousNavigationButtonMode), typeof(NewPipsPagerNavigationMode), typeof(NewPipsPager), new PropertyMetadata(NewPipsPagerNavigationMode.Auto, PreviousNavigationButtonMode_OnChange)); + public static readonly DependencyProperty NextNavigationButtonModeProperty = DependencyProperty.Register(nameof(NextNavigationButtonMode), typeof(NewPipsPagerNavigationMode), typeof(NewPipsPager), new PropertyMetadata(NewPipsPagerNavigationMode.Auto, NextNavigationButtonMode_OnChange)); + + public static readonly DependencyProperty PreviousButtonStyleProperty = DependencyProperty.Register(nameof(PreviousButtonStyle), typeof(Style), typeof(NewPipsPager), new PropertyMetadata(null!)); + public static readonly DependencyProperty NextButtonStyleProperty = DependencyProperty.Register(nameof(NextButtonStyle), typeof(Style), typeof(NewPipsPager), new PropertyMetadata(null!)); + public static readonly DependencyProperty NormalPipButtonStyleProperty = DependencyProperty.Register(nameof(NormalPipButtonStyle), typeof(Style), typeof(NewPipsPager), new PropertyMetadata(null!)); + public static readonly DependencyProperty SelectedPipButtonStyleProperty = DependencyProperty.Register(nameof(SelectedPipButtonStyle), typeof(Style), typeof(NewPipsPager), new PropertyMetadata(null!)); + + #endregion +} diff --git a/CollapseLauncher/XAMLs/Theme/CustomControls/NewPipsPager/NewPipsPager.Templates.cs b/CollapseLauncher/XAMLs/Theme/CustomControls/NewPipsPager/NewPipsPager.Templates.cs new file mode 100644 index 000000000..c23da0b70 --- /dev/null +++ b/CollapseLauncher/XAMLs/Theme/CustomControls/NewPipsPager/NewPipsPager.Templates.cs @@ -0,0 +1,111 @@ +using CollapseLauncher.Extension; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using System.Threading; + +#nullable enable +namespace CollapseLauncher.XAMLs.Theme.CustomControls.NewPipsPager; + +[TemplatePart(Name = TemplateNamePreviousPageButton, Type = typeof(Button))] +[TemplatePart(Name = TemplateNameNextPageButton, Type = typeof(Button))] +[TemplatePart(Name = TemplateNamePipsPagerScrollViewer, Type = typeof(ScrollViewer))] +[TemplatePart(Name = TemplateNamePipsPagerItemsRepeater, Type = typeof(ItemsRepeater))] +public partial class NewPipsPager +{ + #region Constants + + private const string TemplateNamePreviousPageButton = "PreviousPageButton"; + private const string TemplateNameNextPageButton = "NextPageButton"; + private const string TemplateNamePipsPagerScrollViewer = "PipsPagerScrollViewer"; + private const string TemplateNamePipsPagerItemsRepeater = "PipsPagerItemsRepeater"; + + private const string PipButtonStateNormal = "Normal"; + + private const string NavButtonStatePreviousPageButtonCollapsed = "PreviousPageButtonCollapsed"; + private const string NavButtonStatePreviousPageButtonVisible = "PreviousPageButtonVisible"; + private const string NavButtonStatePreviousPageButtonHidden = "PreviousPageButtonHidden"; + private const string NavButtonStateNextPageButtonCollapsed = "NextPageButtonCollapsed"; + private const string NavButtonStateNextPageButtonVisible = "NextPageButtonVisible"; + private const string NavButtonStateNextPageButtonHidden = "NextPageButtonHidden"; + + #endregion + + #region Fields + + private Button _previousPageButton = null!; + private Button _nextPageButton = null!; + private ScrollViewer _pipsPagerScrollViewer = null!; + private ItemsRepeater _pipsPagerItemsRepeater = null!; + + private bool _isTemplateLoaded; + + #endregion + + #region Apply Template Methods + + protected override void OnApplyTemplate() + { + if (Interlocked.Exchange(ref _isTemplateLoaded, true)) + { + return; + } + + base.OnApplyTemplate(); + + _previousPageButton = this.GetTemplateChild