Files
AetherBags/AetherBags/Inventory/Context/HighlightState.cs
T
2026-01-11 11:56:08 -05:00

171 lines
4.8 KiB
C#

using System.Collections.Generic;
using System.Numerics;
namespace AetherBags.Inventory.Context;
public enum HighlightSource
{
Search,
AllaganTools,
BiSBuddy,
}
public record HighlightEntry(uint ItemId, Vector3 Color);
public static class HighlightState
{
private static readonly Dictionary<HighlightSource, HashSet<uint>> Filters = new();
private static readonly Dictionary<HighlightSource, (HashSet<uint> ids, Vector3 color)> Labels = new();
private static readonly Dictionary<HighlightSource, Dictionary<uint, HighlightEntry>> PerItemLabels = new();
// Flat cache for O(1) lookups
private static readonly Dictionary<uint, HighlightEntry> CachedEntries = new(capacity: 512);
private static bool _cacheValid;
private static int _version;
/// <summary>
/// Version counter that increments when highlight state changes.
/// Used by ItemInfo to detect when cached visual state is stale.
/// </summary>
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<uint> ids)
{
Filters[source] = new HashSet<uint>(ids);
_version++;
}
public static bool IsInActiveFilters(uint itemId)
{
if (Filters.Count == 0) return true;
foreach (var filter in Filters.Values)
if (filter.Contains(itemId)) return true;
return false;
}
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)
{
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)
{
var color = label.color;
foreach (var id in label.ids)
{
CachedEntries.TryAdd(id, new HighlightEntry(id, color));
}
}
_cacheValid = true;
}
private static void InvalidateCache()
{
_cacheValid = false;
_version++;
}
public static Vector3? GetLabelColor(uint itemId)
=> GetHighlightEntry(itemId)?.Color;
public static void SetLabel(HighlightSource source, IEnumerable<uint> ids, Vector3 color)
{
PerItemLabels.Remove(source);
Labels[source] = (new HashSet<uint>(ids), color);
InvalidateCache();
}
public static void SetLabelWithColors(HighlightSource source, Dictionary<uint, Vector4> itemColors)
{
Labels.Remove(source);
var entries = new Dictionary<uint, HighlightEntry>(itemColors.Count);
foreach (var (itemId, color) in itemColors)
{
var rgb = new Vector3(
color.X * color.W,
color.Y * color.W,
color.Z * color.W
);
entries[itemId] = new HighlightEntry(itemId, rgb);
}
PerItemLabels[source] = entries;
InvalidateCache();
}
public static void SetLabelWithColors(HighlightSource source, IEnumerable<HighlightEntry> entries)
{
Labels.Remove(source);
var dict = new Dictionary<uint, HighlightEntry>();
foreach (var entry in entries)
{
dict[entry.ItemId] = entry;
}
PerItemLabels[source] = dict;
InvalidateCache();
}
public static void SetLabelWithColors(HighlightSource source, Dictionary<uint, Vector3> itemColors)
{
Labels.Remove(source);
var entries = new Dictionary<uint, HighlightEntry>(itemColors.Count);
foreach (var (itemId, color) in itemColors)
{
entries[itemId] = new HighlightEntry(itemId, color);
}
PerItemLabels[source] = entries;
InvalidateCache();
}
public static void ClearAll()
{
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);
_version++;
}
public static void ClearLabel(HighlightSource source)
{
Labels.Remove(source);
PerItemLabels.Remove(source);
InvalidateCache();
}
}