diff --git a/AetherBags/Addons/InventoryAddonBase.cs b/AetherBags/Addons/InventoryAddonBase.cs index 444e92d..eff8a21 100644 --- a/AetherBags/Addons/InventoryAddonBase.cs +++ b/AetherBags/Addons/InventoryAddonBase.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Numerics; -using AetherBags.AddonLifecycles; using AetherBags.Configuration; using AetherBags.Helpers; using AetherBags.Inventory; @@ -43,8 +42,8 @@ public abstract unsafe class InventoryAddonBase : NativeAddon, IInventoryWindow protected virtual float MaxWindowHeight => 1000; protected const float CategorySpacing = 12; - protected const float ItemSize = 40; - protected const float ItemPadding = 4; + protected const float ItemSize = 42; + protected const float ItemPadding = 5; protected const float FooterHeight = 28f; protected const float FooterTopSpacing = 4f; protected const float SettingsButtonOffset = 48f; @@ -172,7 +171,7 @@ public abstract unsafe class InventoryAddonBase : NativeAddon, IInventoryWindow string dataFilter = config.SearchMode == SearchMode.Filter ? searchText : string.Empty; var categories = InventoryState.GetCategories(dataFilter); - float maxContentWidth = MaxWindowWidth - (ContentStartPosition.X * 2); + float maxContentWidth = CategoriesNode.Width > 0 ? CategoriesNode.Width : ContentSize.X; int maxItemsPerLine = CalculateOptimalItemsPerLine(maxContentWidth); CategoriesNode.SyncWithListDataByKey( @@ -181,10 +180,11 @@ public abstract unsafe class InventoryAddonBase : NativeAddon, IInventoryWindow getKeyFromNode: node => node.CategorizedInventory.Key, updateNode: (node, data) => { + node.MaxWidth = maxContentWidth; node.SetCategoryData(data, Math.Min(data.Items.Count, maxItemsPerLine)); node.RefreshNodeVisuals(); }, - createNodeMethod: _ => CreateCategoryNode()); + createNodeMethod: _ => CreateCategoryNode(maxContentWidth)); if (HasPinning) { @@ -254,11 +254,12 @@ public abstract unsafe class InventoryAddonBase : NativeAddon, IInventoryWindow BackgroundDropTarget.AttachNode(this); } - protected virtual InventoryCategoryNode CreateCategoryNode() + protected virtual InventoryCategoryNode CreateCategoryNode(float? maxWidth = null) { return new InventoryCategoryNode { Size = ContentSize with { Y = 120 }, + MaxWidth = maxWidth, OnRefreshRequested = ManualRefresh, OnDragEnd = () => InventoryOrchestrator.RefreshAll(updateMaps: true), }; @@ -340,6 +341,20 @@ public abstract unsafe class InventoryAddonBase : NativeAddon, IInventoryWindow CategoriesNode.Position = contentPos; CategoriesNode.Size = new Vector2(contentSize.X, gridH); + + UpdateCategoryMaxWidths(contentSize.X); + } + + private void UpdateCategoryMaxWidths(float maxWidth) + { + foreach (var node in CategoriesNode.Nodes) + { + if (node is InventoryCategoryNode categoryNode && categoryNode.MaxWidth != maxWidth) + { + categoryNode.MaxWidth = maxWidth; + categoryNode.RecalculateSize(); + } + } } protected virtual void AutoSizeWindow() @@ -376,6 +391,8 @@ public abstract unsafe class InventoryAddonBase : NativeAddon, IInventoryWindow CategoriesNode.Position = ContentStartPosition; CategoriesNode.Size = new Vector2(contentWidth, gridBudget); + UpdateCategoryMaxWidths(contentWidth); + CategoriesNode.RecalculateLayout(); float requiredGridHeight = CategoriesNode.GetRequiredHeight(); diff --git a/AetherBags/Helpers/RegexCache.cs b/AetherBags/Helpers/RegexCache.cs new file mode 100644 index 0000000..b6ee376 --- /dev/null +++ b/AetherBags/Helpers/RegexCache.cs @@ -0,0 +1,47 @@ +using System.Collections.Concurrent; +using System.Text.RegularExpressions; + +namespace AetherBags.Helpers; + +/// +/// Thread-safe cache for compiled Regex objects to avoid repeated compilation overhead. +/// +internal static class RegexCache +{ + private const int MaxCacheSize = 128; + private static readonly ConcurrentDictionary Cache = new(); + + /// + /// Gets or creates a compiled Regex for the given pattern with case-insensitive matching. + /// Returns null if the pattern is invalid. + /// + public static Regex? GetOrCreate(string pattern) + { + if (string.IsNullOrEmpty(pattern)) + return null; + + if (Cache.TryGetValue(pattern, out var cached)) + return cached; + + try + { + var regex = new Regex(pattern, RegexOptions.CultureInvariant | RegexOptions.IgnoreCase | RegexOptions.Compiled); + + if (Cache.Count < MaxCacheSize) + { + Cache.TryAdd(pattern, regex); + } + + return regex; + } + catch + { + return null; + } + } + + /// + /// Clears the regex cache. Call when configuration changes significantly. + /// + public static void Clear() => Cache.Clear(); +} diff --git a/AetherBags/Inventory/Categories/CategoryBucket.cs b/AetherBags/Inventory/Categories/CategoryBucket.cs index 3dda341..b1b9695 100644 --- a/AetherBags/Inventory/Categories/CategoryBucket.cs +++ b/AetherBags/Inventory/Categories/CategoryBucket.cs @@ -10,6 +10,7 @@ public sealed class CategoryBucket public List Items = null!; public List FilteredItems = null!; public bool Used; + public bool NeedsSorting = true; } public sealed class ItemCountDescComparer : IComparer diff --git a/AetherBags/Inventory/Categories/CategoryBucketManager.cs b/AetherBags/Inventory/Categories/CategoryBucketManager.cs index b24db77..227593b 100644 --- a/AetherBags/Inventory/Categories/CategoryBucketManager.cs +++ b/AetherBags/Inventory/Categories/CategoryBucketManager.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using AetherBags.Configuration; using AetherBags.Inventory.Items; using KamiToolKit.Classes; @@ -49,6 +48,7 @@ public static class CategoryBucketManager bucket.Used = false; bucket.Items.Clear(); bucket.FilteredItems.Clear(); + bucket.NeedsSorting = true; } } @@ -302,8 +302,9 @@ public static class CategoryBucketManager CategoryInfo miscInfo; if (itemInfoByKey.Count > 0) { - var sample = itemInfoByKey.Values.First(); - miscInfo = GetCategoryInfoCached(0u, sample); + using var enumerator = itemInfoByKey.Values.GetEnumerator(); + enumerator.MoveNext(); + miscInfo = GetCategoryInfoCached(0u, enumerator.Current); } else { @@ -353,7 +354,12 @@ public static class CategoryBucketManager continue; // TODO: Make configurable - bucket.Items.Sort(ItemCountDescComparer.Instance); + // Only sort if items changed + if (bucket.NeedsSorting) + { + bucket.Items.Sort(ItemCountDescComparer.Instance); + bucket.NeedsSorting = false; + } sortedCategoryKeys.Add(bucket.Key); } diff --git a/AetherBags/Inventory/Categories/InventoryFilter.cs b/AetherBags/Inventory/Categories/InventoryFilter.cs index 42d91ca..a35f7f6 100644 --- a/AetherBags/Inventory/Categories/InventoryFilter.cs +++ b/AetherBags/Inventory/Categories/InventoryFilter.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Text.RegularExpressions; +using AetherBags.Helpers; using AetherBags.Inventory.Items; namespace AetherBags.Inventory.Categories; @@ -17,17 +18,8 @@ public static class InventoryFilter if (string.IsNullOrEmpty(filterString)) return allCategories; - Regex? re = null; - bool regexValid = true; - - try - { - re = new Regex(filterString, RegexOptions.CultureInvariant | RegexOptions.IgnoreCase); - } - catch - { - regexValid = false; - } + Regex? re = RegexCache.GetOrCreate(filterString); + bool regexValid = re != null; filteredCategories.Clear(); diff --git a/AetherBags/Inventory/Categories/UserCategoryMatcher.cs b/AetherBags/Inventory/Categories/UserCategoryMatcher.cs index 32edcdb..ea33e63 100644 --- a/AetherBags/Inventory/Categories/UserCategoryMatcher.cs +++ b/AetherBags/Inventory/Categories/UserCategoryMatcher.cs @@ -1,6 +1,6 @@ using System; -using System.Text.RegularExpressions; using AetherBags.Configuration; +using AetherBags.Helpers; using AetherBags.Inventory.Items; namespace AetherBags.Inventory.Categories; @@ -30,17 +30,11 @@ internal static class UserCategoryMatcher if (string.IsNullOrWhiteSpace(pattern)) continue; - try + var regex = RegexCache.GetOrCreate(pattern); + if (regex != null && regex.IsMatch(item.Name)) { - if (Regex.IsMatch(item.Name, pattern, RegexOptions.CultureInvariant | RegexOptions.IgnoreCase)) - { - matchesAnyIdentification = true; - break; - } - } - catch - { - // Invalid regex: ignore it. + matchesAnyIdentification = true; + break; } } } diff --git a/AetherBags/Inventory/Context/HighlightState.cs b/AetherBags/Inventory/Context/HighlightState.cs index a763d49..00dd134 100644 --- a/AetherBags/Inventory/Context/HighlightState.cs +++ b/AetherBags/Inventory/Context/HighlightState.cs @@ -18,13 +18,27 @@ public static class HighlightState private static readonly Dictionary ids, Vector3 color)> Labels = new(); private static readonly Dictionary> PerItemLabels = new(); + // Flat cache for O(1) lookups + private static readonly Dictionary CachedEntries = new(capacity: 512); + private static bool _cacheValid; + private static int _version; + + /// + /// Version counter that increments when highlight state changes. + /// Used by ItemInfo to detect when cached visual state is stale. + /// + public static int Version => _version; + public static string? SelectedAllaganToolsFilterKey { get; set; } = string.Empty; public static string? SelectedBisBuddyFilterKey { get; set; } = string.Empty; public static bool IsFilterActive => Filters.Count > 0; public static void SetFilter(HighlightSource source, IEnumerable ids) - => Filters[source] = new HashSet(ids); + { + Filters[source] = new HashSet(ids); + _version++; + } public static bool IsInActiveFilters(uint itemId) { @@ -36,19 +50,42 @@ public static class HighlightState public static HighlightEntry? GetHighlightEntry(uint itemId) { + EnsureCacheValid(); + return CachedEntries.TryGetValue(itemId, out var entry) ? entry : null; + } + + private static void EnsureCacheValid() + { + if (_cacheValid) return; + + CachedEntries.Clear(); + + // PerItemLabels have priority - add them first foreach (var perItemLabel in PerItemLabels.Values) { - if (perItemLabel.TryGetValue(itemId, out var entry)) - return entry; + foreach (var (id, entry) in perItemLabel) + { + CachedEntries.TryAdd(id, entry); + } } + // Labels are fallback - only add if not already present foreach (var label in Labels.Values) { - if (label.ids.Contains(itemId)) - return new HighlightEntry(itemId, label.color); + var color = label.color; + foreach (var id in label.ids) + { + CachedEntries.TryAdd(id, new HighlightEntry(id, color)); + } } - return null; + _cacheValid = true; + } + + private static void InvalidateCache() + { + _cacheValid = false; + _version++; } public static Vector3? GetLabelColor(uint itemId) @@ -58,6 +95,7 @@ public static class HighlightState { PerItemLabels.Remove(source); Labels[source] = (new HashSet(ids), color); + InvalidateCache(); } public static void SetLabelWithColors(HighlightSource source, Dictionary itemColors) @@ -76,6 +114,7 @@ public static class HighlightState } PerItemLabels[source] = entries; + InvalidateCache(); } public static void SetLabelWithColors(HighlightSource source, IEnumerable entries) @@ -89,6 +128,7 @@ public static class HighlightState } PerItemLabels[source] = dict; + InvalidateCache(); } public static void SetLabelWithColors(HighlightSource source, Dictionary itemColors) @@ -102,6 +142,7 @@ public static class HighlightState } PerItemLabels[source] = entries; + InvalidateCache(); } public static void ClearAll() @@ -109,14 +150,22 @@ public static class HighlightState Filters.Clear(); Labels.Clear(); PerItemLabels.Clear(); + CachedEntries.Clear(); + _cacheValid = true; // Empty cache is valid + _version++; SelectedAllaganToolsFilterKey = string.Empty; } - public static void ClearFilter(HighlightSource source) => Filters.Remove(source); + public static void ClearFilter(HighlightSource source) + { + Filters.Remove(source); + _version++; + } public static void ClearLabel(HighlightSource source) { Labels.Remove(source); PerItemLabels.Remove(source); + InvalidateCache(); } } \ No newline at end of file diff --git a/AetherBags/Inventory/Items/ItemInfo.cs b/AetherBags/Inventory/Items/ItemInfo.cs index b4a59fd..1a7d822 100644 --- a/AetherBags/Inventory/Items/ItemInfo.cs +++ b/AetherBags/Inventory/Items/ItemInfo.cs @@ -1,6 +1,7 @@ using System; using System.Numerics; using System.Text.RegularExpressions; +using AetherBags.Helpers; using AetherBags.Inventory.Context; using FFXIVClientStructs.FFXIV.Client.Game; using Lumina.Excel; @@ -23,6 +24,12 @@ public sealed class ItemInfo : IEquatable private string? _name; private string? _description; + private string? _levelString; + private string? _itemLevelString; + + private int _cachedHighlightVersion = -1; + private float _cachedVisualAlpha; + private Vector3 _cachedHighlightColor; private ref readonly Item Row { @@ -44,6 +51,8 @@ public sealed class ItemInfo : IEquatable public int Level => Row.LevelEquip; public int ItemLevel => (int)Row.LevelItem.RowId; + private string LevelString => _levelString ??= Level.ToString(); + private string ItemLevelString => _itemLevelString ??= ItemLevel.ToString(); public int Rarity => Row.Rarity; public uint VendorPrice => Row.PriceLow; public uint StackSize => Row.StackSize; @@ -90,19 +99,37 @@ public sealed class ItemInfo : IEquatable } } - public float VisualAlpha => IsEligibleForContext ? 1.0f : 0.4f; + public float VisualAlpha + { + get + { + EnsureVisualStateCached(); + return _cachedVisualAlpha; + } + } public Vector3 HighlightOverlayColor { get { - if (!System.Config.Categories.BisBuddyEnabled) - return Vector3.Zero; - - return HighlightState.GetLabelColor(Item.ItemId) ?? Vector3.Zero; + EnsureVisualStateCached(); + return _cachedHighlightColor; } } + private void EnsureVisualStateCached() + { + int currentVersion = HighlightState.Version; + if (_cachedHighlightVersion == currentVersion) + return; + + _cachedVisualAlpha = IsEligibleForContext ? 1.0f : 0.4f; + _cachedHighlightColor = System.Config.Categories.BisBuddyEnabled + ? HighlightState.GetLabelColor(Item.ItemId) ?? Vector3.Zero + : Vector3.Zero; + _cachedHighlightVersion = currentVersion; + } + private bool CheckNativeContextEligibility() { uint contextId = InventoryContextState.ActiveContextId; @@ -138,14 +165,16 @@ public sealed class ItemInfo : IEquatable if (string.IsNullOrEmpty(searchTerms)) return true; - var re = new Regex(searchTerms, RegexOptions.CultureInvariant | RegexOptions.IgnoreCase); + var re = RegexCache.GetOrCreate(searchTerms); + if (re == null) + return false; if (re.IsMatch(Name)) return true; if (re.IsMatch(Description)) return true; - if (re.IsMatch(Level.ToString())) return true; - if (re.IsMatch(ItemLevel.ToString())) return true; + if (re.IsMatch(LevelString)) return true; + if (re.IsMatch(ItemLevelString)) return true; return false; } @@ -155,8 +184,8 @@ public sealed class ItemInfo : IEquatable if (re.IsMatch(Name)) return true; if (re.IsMatch(Description)) return true; - if (re.IsMatch(Level.ToString())) return true; - if (re.IsMatch(ItemLevel.ToString())) return true; + if (re.IsMatch(LevelString)) return true; + if (re.IsMatch(ItemLevelString)) return true; return false; } diff --git a/AetherBags/Inventory/State/InventoryStateBase.cs b/AetherBags/Inventory/State/InventoryStateBase.cs index c4d9cc1..9f0ed23 100644 --- a/AetherBags/Inventory/State/InventoryStateBase.cs +++ b/AetherBags/Inventory/State/InventoryStateBase.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using System.Linq; using AetherBags.Configuration; using AetherBags.Currency; using AetherBags.Inventory.Categories; @@ -109,7 +108,7 @@ public abstract class InventoryStateBase } else { - UpdateAllaganHighlight(HighlightState.SelectedBisBuddyFilterKey); + UpdateBisBuddyHighlight(HighlightState.SelectedBisBuddyFilterKey); } } else @@ -156,10 +155,10 @@ public abstract class InventoryStateBase return; } - var filterItems = System.IPC.AllaganTools.GetFilterItems(filterKey); - if (filterItems != null) + var bisItems = System.IPC.BisBuddy.ItemLookup; + if (bisItems.Count > 0) { - HighlightState.SetFilter(HighlightSource.BiSBuddy, filterItems.Keys); + HighlightState.SetFilter(HighlightSource.BiSBuddy, bisItems.Keys); } else { diff --git a/AetherBags/Nodes/Inventory/InventoryCategoryNode.cs b/AetherBags/Nodes/Inventory/InventoryCategoryNode.cs index afff5fd..e1af79d 100644 --- a/AetherBags/Nodes/Inventory/InventoryCategoryNode.cs +++ b/AetherBags/Nodes/Inventory/InventoryCategoryNode.cs @@ -30,6 +30,7 @@ public class InventoryCategoryNode : InventoryCategoryNodeBase private const float MinWidth = 40; private float? _fixedWidth; + private float? _maxWidth; private int _hoverRefs; private bool _headerSuppressed; private bool _headerExpanded; @@ -40,6 +41,7 @@ public class InventoryCategoryNode : InventoryCategoryNodeBase private int _lastItemCount; private ulong _lastItemsHash; private int _lastItemsPerLine; + private float? _lastMaxWidth; public event Action? HeaderHoverChanged; public Action? OnRefreshRequested { get; set; } @@ -88,6 +90,7 @@ public class InventoryCategoryNode : InventoryCategoryNodeBase { bool categoryChanged = data.Key != _lastCategoryKey; bool itemsPerLineChanged = itemsPerLine != _lastItemsPerLine; + bool maxWidthChanged = _maxWidth != _lastMaxWidth; ulong itemsHash = ComputeItemsHash(CollectionsMarshal.AsSpan(data.Items)); bool itemsChanged = data.Items.Count != _lastItemCount || itemsHash != _lastItemsHash; @@ -96,6 +99,7 @@ public class InventoryCategoryNode : InventoryCategoryNodeBase _lastItemCount = data.Items.Count; _lastItemsHash = itemsHash; _lastItemsPerLine = itemsPerLine; + _lastMaxWidth = _maxWidth; _categorizedInventory = data; @@ -120,7 +124,7 @@ public class InventoryCategoryNode : InventoryCategoryNodeBase _itemGridNode.ItemsPerLine = itemsPerLine; } - if (categoryChanged || itemsChanged || itemsPerLineChanged) + if (categoryChanged || itemsChanged || itemsPerLineChanged || maxWidthChanged) { RecalculateSize(); } @@ -160,6 +164,12 @@ public class InventoryCategoryNode : InventoryCategoryNodeBase } } + public float? MaxWidth + { + get => _maxWidth; + set => _maxWidth = value; + } + public override bool IsPinnedInConfig => CategorizedInventory.Category?.IsPinned ?? false; public void BeginHeaderHover() @@ -224,13 +234,19 @@ public class InventoryCategoryNode : InventoryCategoryNodeBase } } - private void RecalculateSize() + public void RecalculateSize() { int itemCount = CategorizedInventory.Items.Count; + float cellW = _itemGridNode.Nodes.Count > 0 ? _itemGridNode.Nodes[0].Width : FallbackItemSize; + float cellH = _itemGridNode.Nodes.Count > 0 ? _itemGridNode.Nodes[0].Height : FallbackItemSize; + float hPad = _itemGridNode.HorizontalPadding; + float vPad = _itemGridNode.VerticalPadding; + if (itemCount == 0) { float width = _fixedWidth ?? MinWidth; + if (_maxWidth.HasValue) width = Math.Min(width, _maxWidth.Value); Size = new Vector2(width, HeaderHeight); _baseHeaderWidth = width; _itemGridNode.Position = new Vector2(0, HeaderHeight); @@ -240,21 +256,36 @@ public class InventoryCategoryNode : InventoryCategoryNodeBase } int itemsPerLine = Math.Max(1, _itemGridNode.ItemsPerLine); + + float minUsableWidth = cellW; + if (_maxWidth.HasValue && _fixedWidth is null && _maxWidth.Value >= minUsableWidth) + { + int maxColumns = (int)MathF.Floor((_maxWidth.Value + hPad) / (cellW + hPad)); + maxColumns = Math.Max(1, maxColumns); + + float widthNeeded = maxColumns * cellW + (maxColumns - 1) * hPad; + if (widthNeeded > _maxWidth.Value && maxColumns > 1) + maxColumns--; + + itemsPerLine = Math.Min(itemsPerLine, maxColumns); + } + int rows = (itemCount + itemsPerLine - 1) / itemsPerLine; int actualColumns = Math.Min(itemCount, itemsPerLine); - float cellW = _itemGridNode.Nodes.Count > 0 ? _itemGridNode.Nodes[0].Width : FallbackItemSize; - float cellH = _itemGridNode.Nodes.Count > 0 ? _itemGridNode.Nodes[0].Height : FallbackItemSize; - - float hPad = _itemGridNode.HorizontalPadding; - float vPad = _itemGridNode.VerticalPadding; - float calculatedWidth = _fixedWidth ?? Math.Max(MinWidth, actualColumns * cellW + (actualColumns - 1) * hPad); + + if (_maxWidth.HasValue && _fixedWidth is null && _maxWidth.Value >= minUsableWidth) + calculatedWidth = Math.Min(calculatedWidth, _maxWidth.Value); + float height = HeaderHeight + rows * cellH + (rows - 1) * vPad; Size = new Vector2(calculatedWidth, height); _itemGridNode.Position = new Vector2(0, HeaderHeight); _itemGridNode.Size = new Vector2(calculatedWidth, height - HeaderHeight); + + if (_itemGridNode.ItemsPerLine != itemsPerLine) + _itemGridNode.ItemsPerLine = itemsPerLine; _baseHeaderWidth = calculatedWidth; ApplyHeaderVisualStateAndSize(); diff --git a/AetherBags/Nodes/Layout/DeferrableLayoutListNode.cs b/AetherBags/Nodes/Layout/DeferrableLayoutListNode.cs index e9632e7..3c5f43d 100644 --- a/AetherBags/Nodes/Layout/DeferrableLayoutListNode.cs +++ b/AetherBags/Nodes/Layout/DeferrableLayoutListNode.cs @@ -78,7 +78,6 @@ public abstract class DeferrableLayoutListNode : SimpleComponentNode } } - [Obsolete] protected virtual void AdjustNode(NodeBase node) { } protected abstract void InternalRecalculateLayout(); diff --git a/AetherBags/Nodes/Layout/WrappingGridNode.cs b/AetherBags/Nodes/Layout/WrappingGridNode.cs index d116f21..83a11fd 100644 --- a/AetherBags/Nodes/Layout/WrappingGridNode.cs +++ b/AetherBags/Nodes/Layout/WrappingGridNode.cs @@ -30,9 +30,9 @@ public sealed class WrappingGridNode : DeferrableLayoutListNode where T : Nod private float _lastVSpace = float.NaN; private float _lastTopPadding = float.NaN; private float _lastBottomPadding = float.NaN; - private bool _lastuseCompactPacking; - private bool _lastpreferLargestFit; - private bool _lastuseStableInsert; + private bool _lastUseCompactPacking; + private bool _lastPreferLargestFit; + private bool _lastUseStableInsert; private int _lastCompactLookahead; private int[] _orderScratch = Array.Empty(); @@ -977,9 +977,9 @@ public sealed class WrappingGridNode : DeferrableLayoutListNode where T : Nod NearlyEqual(_lastVSpace, VerticalSpacing) && NearlyEqual(_lastTopPadding, TopPadding) && NearlyEqual(_lastBottomPadding, BottomPadding) && - _lastuseCompactPacking == System.Config.General.CompactPackingEnabled && - _lastpreferLargestFit == System.Config.General.CompactPreferLargestFit && - _lastuseStableInsert == System.Config.General.CompactStableInsert && + _lastUseCompactPacking == System.Config.General.CompactPackingEnabled && + _lastPreferLargestFit == System.Config.General.CompactPreferLargestFit && + _lastUseStableInsert == System.Config.General.CompactStableInsert && _lastCompactLookahead == System.Config.General.CompactLookahead; } @@ -992,9 +992,9 @@ public sealed class WrappingGridNode : DeferrableLayoutListNode where T : Nod _lastTopPadding = TopPadding; _lastBottomPadding = BottomPadding; - _lastuseCompactPacking = System.Config.General.CompactPackingEnabled; - _lastpreferLargestFit = System.Config.General.CompactPreferLargestFit; - _lastuseStableInsert = System.Config.General.CompactStableInsert; + _lastUseCompactPacking = System.Config.General.CompactPackingEnabled; + _lastPreferLargestFit = System.Config.General.CompactPreferLargestFit; + _lastUseStableInsert = System.Config.General.CompactStableInsert; _lastCompactLookahead = System.Config.General.CompactLookahead; }