diff --git a/src/Snap.Hutao/Snap.Hutao/Control/AutoSuggestBox/AutoSuggestTokenBox.cs b/src/Snap.Hutao/Snap.Hutao/Control/AutoSuggestBox/AutoSuggestTokenBox.cs index 05f62895..43d2e518 100644 --- a/src/Snap.Hutao/Snap.Hutao/Control/AutoSuggestBox/AutoSuggestTokenBox.cs +++ b/src/Snap.Hutao/Snap.Hutao/Control/AutoSuggestBox/AutoSuggestTokenBox.cs @@ -59,7 +59,7 @@ internal sealed partial class AutoSuggestTokenBox : TokenizingTextBox return; } - CommandExtension.TryExecute(FilterCommand, FilterCommandParameter); + CommandInvocation.TryExecute(FilterCommand, FilterCommandParameter); } private void OnTokenItemAdding(TokenizingTextBox sender, TokenItemAddingEventArgs args) @@ -74,6 +74,6 @@ internal sealed partial class AutoSuggestTokenBox : TokenizingTextBox private void OnTokenItemModified(TokenizingTextBox sender, object args) { - CommandExtension.TryExecute(FilterCommand, FilterCommandParameter); + CommandInvocation.TryExecute(FilterCommand, FilterCommandParameter); } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Control/Extension/CommandExtension.cs b/src/Snap.Hutao/Snap.Hutao/Control/Extension/CommandInvocation.cs similarity index 90% rename from src/Snap.Hutao/Snap.Hutao/Control/Extension/CommandExtension.cs rename to src/Snap.Hutao/Snap.Hutao/Control/Extension/CommandInvocation.cs index e616d989..41f83527 100644 --- a/src/Snap.Hutao/Snap.Hutao/Control/Extension/CommandExtension.cs +++ b/src/Snap.Hutao/Snap.Hutao/Control/Extension/CommandInvocation.cs @@ -3,7 +3,7 @@ namespace Snap.Hutao.Control.Extension; -internal static class CommandExtension +internal static class CommandInvocation { public static bool TryExecute(this ICommand? command, object? parameter = null) { diff --git a/src/Snap.Hutao/Snap.Hutao/Control/Extension/DependencyObjectExtension.cs b/src/Snap.Hutao/Snap.Hutao/Control/Extension/DependencyObjectExtension.cs index 87e29747..61e5dddc 100644 --- a/src/Snap.Hutao/Snap.Hutao/Control/Extension/DependencyObjectExtension.cs +++ b/src/Snap.Hutao/Snap.Hutao/Control/Extension/DependencyObjectExtension.cs @@ -2,11 +2,13 @@ // Licensed under the MIT license. using Microsoft.UI.Xaml; +using System.Runtime.CompilerServices; namespace Snap.Hutao.Control.Extension; internal static class DependencyObjectExtension { + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static IServiceProvider ServiceProvider(this DependencyObject obj) { return Ioc.Default; diff --git a/src/Snap.Hutao/Snap.Hutao/Control/Image/CachedImage.cs b/src/Snap.Hutao/Snap.Hutao/Control/Image/CachedImage.cs index b8a4deb0..caebb559 100644 --- a/src/Snap.Hutao/Snap.Hutao/Control/Image/CachedImage.cs +++ b/src/Snap.Hutao/Snap.Hutao/Control/Image/CachedImage.cs @@ -3,7 +3,9 @@ using Microsoft.UI.Xaml.Media; using Microsoft.UI.Xaml.Media.Imaging; +using Snap.Hutao.Control.Extension; using Snap.Hutao.Core.Caching; +using Snap.Hutao.Core.ExceptionService; using System.Runtime.InteropServices; namespace Snap.Hutao.Control.Image; @@ -26,12 +28,11 @@ internal sealed class CachedImage : Implementation.ImageEx /// protected override async Task ProvideCachedResourceAsync(Uri imageUri, CancellationToken token) { - // We can only use Ioc to retrieve IImageCache, no IServiceProvider is available. - IImageCache imageCache = Ioc.Default.GetRequiredService(); + IImageCache imageCache = this.ServiceProvider().GetRequiredService(); try { - Verify.Operation(!string.IsNullOrEmpty(imageUri.Host), SH.ControlImageCachedImageInvalidResourceUri); + HutaoException.ThrowIf(string.IsNullOrEmpty(imageUri.Host), HutaoExceptionKind.ImageCacheInvalidUri, SH.ControlImageCachedImageInvalidResourceUri); string file = await imageCache.GetFileFromCacheAsync(imageUri).ConfigureAwait(true); // BitmapImage need to be created by main thread. token.ThrowIfCancellationRequested(); // check token state to determine whether the operation should be canceled. return new BitmapImage(file.ToUri()); // BitmapImage initialize with a uri will increase image quality and loading speed. diff --git a/src/Snap.Hutao/Snap.Hutao/Control/Image/Implementation/ImageEx.cs b/src/Snap.Hutao/Snap.Hutao/Control/Image/Implementation/ImageEx.cs index 18121e3e..f1e3accd 100644 --- a/src/Snap.Hutao/Snap.Hutao/Control/Image/Implementation/ImageEx.cs +++ b/src/Snap.Hutao/Snap.Hutao/Control/Image/Implementation/ImageEx.cs @@ -7,21 +7,14 @@ using Windows.Media.Casting; namespace Snap.Hutao.Control.Image.Implementation; -internal class ImageEx : ImageExBase +[DependencyProperty("NineGrid", typeof(Thickness))] +internal partial class ImageEx : ImageExBase { - private static readonly DependencyProperty NineGridProperty = DependencyProperty.Register(nameof(NineGrid), typeof(Thickness), typeof(ImageEx), new PropertyMetadata(default(Thickness))); - public ImageEx() : base() { } - public Thickness NineGrid - { - get => (Thickness)GetValue(NineGridProperty); - set => SetValue(NineGridProperty, value); - } - public override CompositionBrush GetAlphaMask() { if (IsInitialized && Image is Microsoft.UI.Xaml.Controls.Image image) diff --git a/src/Snap.Hutao/Snap.Hutao/Control/Image/Implementation/ImageExBase.cs b/src/Snap.Hutao/Snap.Hutao/Control/Image/Implementation/ImageExBase.cs index ecc33dde..ee41e58f 100644 --- a/src/Snap.Hutao/Snap.Hutao/Control/Image/Implementation/ImageExBase.cs +++ b/src/Snap.Hutao/Snap.Hutao/Control/Image/Implementation/ImageExBase.cs @@ -6,6 +6,7 @@ using Microsoft.UI.Composition; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Media; using Microsoft.UI.Xaml.Media.Imaging; +using Snap.Hutao.Win32; using System.IO; using Windows.Foundation; @@ -158,7 +159,6 @@ internal abstract partial class ImageExBase : Microsoft.UI.Xaml.Controls.Control if (value) { control.LayoutUpdated += control.OnImageExBaseLayoutUpdated; - control.InvalidateLazyLoading(); } else @@ -169,7 +169,7 @@ internal abstract partial class ImageExBase : Microsoft.UI.Xaml.Controls.Control private static void LazyLoadingThresholdChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { - if (d is ImageExBase control && control.EnableLazyLoading) + if (d is ImageExBase { EnableLazyLoading: true } control) { control.InvalidateLazyLoading(); } @@ -229,9 +229,6 @@ internal abstract partial class ImageExBase : Microsoft.UI.Xaml.Controls.Control private void AttachPlaceholderSource(ImageSource? source) { - // Setting the source at this point should call ImageExOpened/VisualStateManager.GoToState - // as we register to both the ImageOpened/ImageFailed events of the underlying control. - // We only need to call those methods if we fail in other cases before we get here. if (PlaceholderImage is Microsoft.UI.Xaml.Controls.Image image) { image.Source = source; @@ -240,6 +237,15 @@ internal abstract partial class ImageExBase : Microsoft.UI.Xaml.Controls.Control { brush.ImageSource = source; } + + if (source is null) + { + VisualStateManager.GoToState(this, UnloadedState, true); + } + else if (source is BitmapSource { PixelHeight: > 0, PixelWidth: > 0 }) + { + VisualStateManager.GoToState(this, LoadedState, true); + } } private async void SetSource(object? source) @@ -311,8 +317,7 @@ internal abstract partial class ImageExBase : Microsoft.UI.Xaml.Controls.Control } tokenSource?.Cancel(); - - tokenSource = new CancellationTokenSource(); + tokenSource = new(); AttachPlaceholderSource(null); @@ -443,9 +448,10 @@ internal abstract partial class ImageExBase : Microsoft.UI.Xaml.Controls.Control return; } - Rect controlRect = TransformToVisual(hostElement) - .TransformBounds(new Rect(0, 0, ActualWidth, ActualHeight)); + Rect controlRect = TransformToVisual(hostElement).TransformBounds(StructMarshal.Rect(ActualSize)); double lazyLoadingThreshold = LazyLoadingThreshold; + + // Left/Top 1 Threshold, Right/Bottom 2 Threshold Rect hostRect = new( 0 - lazyLoadingThreshold, 0 - lazyLoadingThreshold, diff --git a/src/Snap.Hutao/Snap.Hutao/Control/Layout/DefaultItemCollectionTransitionProvider.cs b/src/Snap.Hutao/Snap.Hutao/Control/Layout/DefaultItemCollectionTransitionProvider.cs deleted file mode 100644 index 1426af0e..00000000 --- a/src/Snap.Hutao/Snap.Hutao/Control/Layout/DefaultItemCollectionTransitionProvider.cs +++ /dev/null @@ -1,151 +0,0 @@ -// Copyright (c) DGP Studio. All rights reserved. -// Licensed under the MIT license. - -using Microsoft.UI.Composition; -using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Hosting; -using System.Numerics; -using Windows.Foundation; - -namespace Snap.Hutao.Control.Layout; - -internal sealed class DefaultItemCollectionTransitionProvider : ItemCollectionTransitionProvider -{ - private const double DefaultAnimationDurationInMs = 300.0; - - static DefaultItemCollectionTransitionProvider() - { - AnimationSlowdownFactor = 1.0; - } - - public static double AnimationSlowdownFactor { get; set; } - - protected override bool ShouldAnimateCore(ItemCollectionTransition transition) - { - return true; - } - - protected override void StartTransitions(IList transitions) - { - List addTransitions = []; - List removeTransitions = []; - List moveTransitions = []; - - foreach (ItemCollectionTransition transition in addTransitions) - { - switch (transition.Operation) - { - case ItemCollectionTransitionOperation.Add: - addTransitions.Add(transition); - break; - case ItemCollectionTransitionOperation.Remove: - removeTransitions.Add(transition); - break; - case ItemCollectionTransitionOperation.Move: - moveTransitions.Add(transition); - break; - } - } - - StartAddTransitions(addTransitions, removeTransitions.Count > 0, moveTransitions.Count > 0); - StartRemoveTransitions(removeTransitions); - StartMoveTransitions(moveTransitions, removeTransitions.Count > 0); - } - - private static void StartAddTransitions(IList transitions, bool hasRemoveTransitions, bool hasMoveTransitions) - { - foreach (ItemCollectionTransition transition in transitions) - { - ItemCollectionTransitionProgress progress = transition.Start(); - Visual visual = ElementCompositionPreview.GetElementVisual(progress.Element); - Compositor compositor = visual.Compositor; - - ScalarKeyFrameAnimation fadeInAnimation = compositor.CreateScalarKeyFrameAnimation(); - fadeInAnimation.InsertKeyFrame(0.0f, 0.0f); - - if (hasMoveTransitions && hasRemoveTransitions) - { - fadeInAnimation.InsertKeyFrame(0.66f, 0.0f); - } - else if (hasMoveTransitions || hasRemoveTransitions) - { - fadeInAnimation.InsertKeyFrame(0.5f, 0.0f); - } - - fadeInAnimation.InsertKeyFrame(1.0f, 1.0f); - fadeInAnimation.Duration = TimeSpan.FromMilliseconds( - DefaultAnimationDurationInMs * ((hasRemoveTransitions ? 1 : 0) + (hasMoveTransitions ? 1 : 0) + 1) * AnimationSlowdownFactor); - - CompositionScopedBatch batch = compositor.CreateScopedBatch(CompositionBatchTypes.Animation); - visual.StartAnimation("Opacity", fadeInAnimation); - batch.End(); - batch.Completed += (_, _) => progress.Complete(); - } - } - - private static void StartRemoveTransitions(IList transitions) - { - foreach (ItemCollectionTransition transition in transitions) - { - ItemCollectionTransitionProgress progress = transition.Start(); - Visual visual = ElementCompositionPreview.GetElementVisual(progress.Element); - Compositor compositor = visual.Compositor; - - ScalarKeyFrameAnimation fadeOutAnimation = compositor.CreateScalarKeyFrameAnimation(); - fadeOutAnimation.InsertExpressionKeyFrame(0.0f, "this.CurrentValue"); - fadeOutAnimation.InsertKeyFrame(1.0f, 0.0f); - fadeOutAnimation.Duration = TimeSpan.FromMilliseconds(DefaultAnimationDurationInMs * AnimationSlowdownFactor); - - CompositionScopedBatch batch = compositor.CreateScopedBatch(CompositionBatchTypes.Animation); - visual.StartAnimation(nameof(Visual.Opacity), fadeOutAnimation); - batch.End(); - batch.Completed += (_, _) => - { - visual.Opacity = 1.0f; - progress.Complete(); - }; - } - } - - private static void StartMoveTransitions(IList transitions, bool hasRemoveAnimations) - { - foreach (ItemCollectionTransition transition in transitions) - { - ItemCollectionTransitionProgress progress = transition.Start(); - Visual visual = ElementCompositionPreview.GetElementVisual(progress.Element); - Compositor compositor = visual.Compositor; - CompositionScopedBatch batch = compositor.CreateScopedBatch(CompositionBatchTypes.Animation); - - // Animate offset. - if (transition.OldBounds.X != transition.NewBounds.X || - transition.OldBounds.Y != transition.NewBounds.Y) - { - AnimateOffset(visual, compositor, transition.OldBounds, transition.NewBounds, hasRemoveAnimations); - } - - batch.End(); - batch.Completed += (_, _) => progress.Complete(); - } - } - - private static void AnimateOffset(Visual visual, Compositor compositor, Rect oldBounds, Rect newBounds, bool hasRemoveAnimations) - { - Vector2KeyFrameAnimation offsetAnimation = compositor.CreateVector2KeyFrameAnimation(); - - offsetAnimation.SetVector2Parameter("delta", new Vector2( - (float)(oldBounds.X - newBounds.X), - (float)(oldBounds.Y - newBounds.Y))); - offsetAnimation.SetVector2Parameter("final", default); - offsetAnimation.InsertExpressionKeyFrame(0.0f, "this.CurrentValue + delta"); - if (hasRemoveAnimations) - { - offsetAnimation.InsertExpressionKeyFrame(0.5f, "delta"); - } - - offsetAnimation.InsertExpressionKeyFrame(1.0f, "final"); - offsetAnimation.Duration = TimeSpan.FromMilliseconds( - DefaultAnimationDurationInMs * ((hasRemoveAnimations ? 1 : 0) + 1) * AnimationSlowdownFactor); - - visual.StartAnimation("TransformMatrix._41_42", offsetAnimation); - } -} \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Control/Layout/UniformStaggeredLayout.cs b/src/Snap.Hutao/Snap.Hutao/Control/Layout/UniformStaggeredLayout.cs index 96f69e44..8edbf364 100644 --- a/src/Snap.Hutao/Snap.Hutao/Control/Layout/UniformStaggeredLayout.cs +++ b/src/Snap.Hutao/Snap.Hutao/Control/Layout/UniformStaggeredLayout.cs @@ -4,6 +4,7 @@ using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using System.Collections.Specialized; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using Windows.Foundation; @@ -18,14 +19,12 @@ internal sealed partial class UniformStaggeredLayout : VirtualizingLayout protected override void InitializeForContextCore(VirtualizingLayoutContext context) { context.LayoutState = new UniformStaggeredLayoutState(context); - base.InitializeForContextCore(context); } /// protected override void UninitializeForContextCore(VirtualizingLayoutContext context) { context.LayoutState = null; - base.UninitializeForContextCore(context); } /// @@ -84,14 +83,15 @@ internal sealed partial class UniformStaggeredLayout : VirtualizingLayout if (columnWidth != state.ColumnWidth) { - // The items will need to be remeasured + // Remeasure items later + // Rearrange items later state.Clear(); } state.ColumnWidth = columnWidth; - // adjust for column spacing on all columns expect the first - double totalWidth = state.ColumnWidth + ((numberOfColumns - 1) * (state.ColumnWidth + MinColumnSpacing)); + double totalWidth = ((state.ColumnWidth + MinColumnSpacing) * numberOfColumns) - MinColumnSpacing; + if (totalWidth > availableWidth) { numberOfColumns--; @@ -103,12 +103,15 @@ internal sealed partial class UniformStaggeredLayout : VirtualizingLayout if (numberOfColumns != state.NumberOfColumns) { - // The items will not need to be remeasured, but they will need to go into new columns - state.ClearColumns(); + // Remeasure items later + // Rearrange items later + state.Clear(); } if (MinRowSpacing != state.RowSpacing) { + // Rearrange items later + // If the RowSpacing changes the height of the rows will be different. // The columns stores the height so we'll want to clear them out to // get the proper height @@ -170,7 +173,7 @@ internal sealed partial class UniformStaggeredLayout : VirtualizingLayout item.Element.Measure(new Size(state.ColumnWidth, availableHeight)); if (item.Height != item.Element.DesiredSize.Height) { - // this item changed size; we need to recalculate layout for everything after this + // this item changed size; we need to recalculate layout for everything after this item state.RemoveFromIndex(i + 1); item.Height = item.Element.DesiredSize.Height; columnHeights[columnIndex] = item.Top + item.Height; @@ -201,8 +204,7 @@ internal sealed partial class UniformStaggeredLayout : VirtualizingLayout // Cycle through each column and arrange the items that are within the realization bounds for (int columnIndex = 0; columnIndex < state.NumberOfColumns; columnIndex++) { - UniformStaggeredColumnLayout layout = state.GetColumnLayout(columnIndex); - foreach (ref readonly UniformStaggeredItem item in CollectionsMarshal.AsSpan(layout)) + foreach (ref readonly UniformStaggeredItem item in CollectionsMarshal.AsSpan(state.GetColumnLayout(columnIndex))) { double bottom = item.Top + item.Height; if (bottom < context.RealizationRect.Top) @@ -211,6 +213,7 @@ internal sealed partial class UniformStaggeredLayout : VirtualizingLayout continue; } + // Partial or fully in the view if (item.Top <= context.RealizationRect.Bottom) { double itemHorizontalOffset = (state.ColumnWidth * columnIndex) + (MinColumnSpacing * columnIndex); @@ -229,21 +232,22 @@ internal sealed partial class UniformStaggeredLayout : VirtualizingLayout return finalSize; } - private static (int NumberOfColumns, double ColumnWidth) GetNumberOfColumnsAndWidth(double availableWidth, double minItemWidth, double minColumnSpacing) + private static (int NumberOfColumns, double ColumnWidth) GetNumberOfColumnsAndWidth(double availableWidth, double minItemWidth, double columnSpacing) { // test if the width can fit in 2 items - if ((2 * minItemWidth) + minColumnSpacing > availableWidth) + if ((2 * minItemWidth) + columnSpacing > availableWidth) { return (1, availableWidth); } - int columnCount = Math.Max(1, (int)((availableWidth + minColumnSpacing) / (minItemWidth + minColumnSpacing))); - double columnWidthAddSpacing = (availableWidth + minColumnSpacing) / columnCount; - return (columnCount, columnWidthAddSpacing - minColumnSpacing); + int columnCount = Math.Max(1, (int)((availableWidth + columnSpacing) / (minItemWidth + columnSpacing))); + double columnWidthWithSpacing = (availableWidth + columnSpacing) / columnCount; + return (columnCount, columnWidthWithSpacing - columnSpacing); } private static int GetLowestColumnIndex(in ReadOnlySpan columnHeights) { + // We want to find the leftest column with the lowest height int columnIndex = 0; double height = columnHeights[0]; for (int j = 1; j < columnHeights.Length; j++) @@ -260,13 +264,11 @@ internal sealed partial class UniformStaggeredLayout : VirtualizingLayout private static void OnMinItemWidthChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { - UniformStaggeredLayout panel = (UniformStaggeredLayout)d; - panel.InvalidateMeasure(); + ((UniformStaggeredLayout)d).InvalidateMeasure(); } private static void OnSpacingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { - UniformStaggeredLayout panel = (UniformStaggeredLayout)d; - panel.InvalidateMeasure(); + ((UniformStaggeredLayout)d).InvalidateMeasure(); } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Control/Layout/UniformStaggeredLayoutState.cs b/src/Snap.Hutao/Snap.Hutao/Control/Layout/UniformStaggeredLayoutState.cs index 31f8a0ab..205de7d9 100644 --- a/src/Snap.Hutao/Snap.Hutao/Control/Layout/UniformStaggeredLayoutState.cs +++ b/src/Snap.Hutao/Snap.Hutao/Control/Layout/UniformStaggeredLayoutState.cs @@ -67,46 +67,6 @@ internal sealed class UniformStaggeredLayoutState return columnLayout[columnIndex]; } - /// - /// Clear everything that has been calculated. - /// - internal void Clear() - { - // https://github.com/DGP-Studio/Snap.Hutao/issues/1079 - // The first element must be force refreshed otherwise - // it will use the old one realized - // https://github.com/DGP-Studio/Snap.Hutao/issues/1099 - // Now we need to refresh the first element of each column - // https://github.com/DGP-Studio/Snap.Hutao/issues/1099 - // Finally we need to refresh the whole layout when we reset - if (context.ItemCount > 0) - { - for (int i = 0; i < context.ItemCount; i++) - { - RecycleElementAt(i); - } - } - - columnLayout.Clear(); - items.Clear(); - } - - /// - /// Clear the layout columns so they will be recalculated. - /// - internal void ClearColumns() - { - columnLayout.Clear(); - } - - /// - /// Gets the estimated height of the layout. - /// - /// The estimated height of the layout. - /// - /// If all of the items have been calculated then the actual height will be returned. - /// If all of the items have not been calculated then an estimated height will be calculated based on the average height of the items. - /// internal double GetHeight() { double desiredHeight = columnLayout.Values.Max(c => c.Height); @@ -139,10 +99,37 @@ internal sealed class UniformStaggeredLayoutState return desiredHeight; } + internal void Clear() + { + RecycleElements(); + ClearColumns(); + ClearItems(); + } + + internal void ClearColumns() + { + columnLayout.Clear(); + } + + internal void ClearItems() + { + items.Clear(); + } + + internal void RecycleElements() + { + if (context.ItemCount > 0) + { + for (int i = 0; i < items.Count; i++) + { + RecycleElementAt(i); + } + } + } + internal void RecycleElementAt(int index) { - UIElement element = context.GetOrCreateElementAt(index); - context.RecycleElement(element); + context.RecycleElement(context.GetOrCreateElementAt(index)); } internal void RemoveFromIndex(int index) @@ -175,7 +162,7 @@ internal sealed class UniformStaggeredLayoutState { for (int i = startIndex; i <= endIndex; i++) { - if (i > items.Count) + if (i >= items.Count) { break; } @@ -184,7 +171,7 @@ internal sealed class UniformStaggeredLayoutState item.Height = 0; item.Top = 0; - // We must recycle all elements to ensure that it gets the correct context + // We must recycle all removed elements to ensure that it gets the correct context RecycleElementAt(i); } diff --git a/src/Snap.Hutao/Snap.Hutao/Core/ExceptionService/HutaoExceptionKind.cs b/src/Snap.Hutao/Snap.Hutao/Core/ExceptionService/HutaoExceptionKind.cs index 07fb80d5..80333902 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/ExceptionService/HutaoExceptionKind.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/ExceptionService/HutaoExceptionKind.cs @@ -9,6 +9,7 @@ internal enum HutaoExceptionKind // Foundation ServiceTypeCastFailed, + ImageCacheInvalidUri, // IO FileSystemCreateFileInsufficientPermissions, diff --git a/src/Snap.Hutao/Snap.Hutao/Win32/StructMarshal.cs b/src/Snap.Hutao/Snap.Hutao/Win32/StructMarshal.cs index afa83041..9cdb3ec2 100644 --- a/src/Snap.Hutao/Snap.Hutao/Win32/StructMarshal.cs +++ b/src/Snap.Hutao/Snap.Hutao/Win32/StructMarshal.cs @@ -4,6 +4,7 @@ using System.Buffers.Binary; using System.Numerics; using System.Runtime.CompilerServices; +using Windows.Foundation; using Windows.Graphics; namespace Snap.Hutao.Win32; @@ -26,45 +27,26 @@ internal static class StructMarshal return color; } - /// - /// 从 0,0 点构造一个新的 - /// - /// 尺寸 - /// 新的实例 + public static Rect Rect(Vector2 size) + { + return new(0, 0, size.X, size.Y); + } + public static RectInt32 RectInt32(SizeInt32 size) { return new(0, 0, size.Width, size.Height); } - /// - /// 构造一个新的 - /// - /// 左上角位置 - /// 尺寸 - /// 新的实例 public static RectInt32 RectInt32(PointInt32 point, Vector2 size) { return RectInt32(point.X, point.Y, size); } - /// - /// 构造一个新的 - /// - /// X - /// Y - /// 尺寸 - /// 新的实例 public static RectInt32 RectInt32(int x, int y, Vector2 size) { return new(x, y, (int)size.X, (int)size.Y); } - /// - /// 构造一个新的 - /// - /// 左上角位置 - /// 尺寸 - /// 新的实例 public static RectInt32 RectInt32(PointInt32 point, SizeInt32 size) { return new(point.X, point.Y, size.Width, size.Height);