Improve category matching
This commit is contained in:
@@ -119,6 +119,7 @@ public class AddonCategoryConfigurationWindow : NativeAddon
|
|||||||
listNode.AddOption(newWrapper);
|
listNode.AddOption(newWrapper);
|
||||||
|
|
||||||
RefreshSelectionList();
|
RefreshSelectionList();
|
||||||
|
System.AddonInventoryWindow.ManualInventoryRefresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnRemoveCategory(CategoryWrapper categoryWrapper)
|
private void OnRemoveCategory(CategoryWrapper categoryWrapper)
|
||||||
@@ -134,6 +135,7 @@ public class AddonCategoryConfigurationWindow : NativeAddon
|
|||||||
{
|
{
|
||||||
OnOptionChanged(null);
|
OnOptionChanged(null);
|
||||||
}
|
}
|
||||||
|
System.AddonInventoryWindow.ManualInventoryRefresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RefreshSelectionList()
|
private void RefreshSelectionList()
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
using AetherBags.Configuration;
|
using AetherBags.Configuration;
|
||||||
|
using AetherBags.Inventory;
|
||||||
|
using Dalamud.Game.Text.SeStringHandling;
|
||||||
using KamiToolKit.Premade;
|
using KamiToolKit.Premade;
|
||||||
|
using SeStringBuilder = Lumina.Text.SeStringBuilder;
|
||||||
|
|
||||||
namespace AetherBags.Addons;
|
namespace AetherBags.Addons;
|
||||||
|
|
||||||
@@ -13,7 +16,8 @@ public class CategoryWrapper(UserCategoryDefinition categoryDefinition) : IInfoN
|
|||||||
}
|
}
|
||||||
|
|
||||||
public string GetSubLabel() {
|
public string GetSubLabel() {
|
||||||
return CategoryDefinition!.Enabled ? "Enabled" : "Disabled";
|
if(UserCategoryMatcher.IsCatchAll(CategoryDefinition!)) return " No valid rules!";
|
||||||
|
return CategoryDefinition!.Enabled ? "✓ Enabled" : " Disabled";
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint? GetId() => null;
|
public uint? GetId() => null;
|
||||||
|
|||||||
@@ -54,6 +54,13 @@ public static class CategoryBucketManager
|
|||||||
for (int i = 0; i < sortedScratch.Count; i++)
|
for (int i = 0; i < sortedScratch.Count; i++)
|
||||||
{
|
{
|
||||||
UserCategoryDefinition category = sortedScratch[i];
|
UserCategoryDefinition category = sortedScratch[i];
|
||||||
|
|
||||||
|
if (!category.Enabled)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (UserCategoryMatcher.IsCatchAll(category))
|
||||||
|
continue;
|
||||||
|
|
||||||
uint bucketKey = MakeUserCategoryKey(category.Order);
|
uint bucketKey = MakeUserCategoryKey(category.Order);
|
||||||
|
|
||||||
if (!bucketsByKey.TryGetValue(bucketKey, out CategoryBucket? bucket))
|
if (!bucketsByKey.TryGetValue(bucketKey, out CategoryBucket? bucket))
|
||||||
|
|||||||
@@ -11,6 +11,44 @@ internal static class UserCategoryMatcher
|
|||||||
{
|
{
|
||||||
var rules = userCategory.Rules;
|
var rules = userCategory.Rules;
|
||||||
|
|
||||||
|
bool hasIdentificationFilters = rules.AllowedItemIds.Count > 0 || rules.AllowedItemNamePatterns.Count > 0;
|
||||||
|
|
||||||
|
if (hasIdentificationFilters)
|
||||||
|
{
|
||||||
|
bool matchesAnyIdentification = false;
|
||||||
|
|
||||||
|
if (rules.AllowedItemIds.Count > 0 && rules.AllowedItemIds.Contains(item.Item.ItemId))
|
||||||
|
{
|
||||||
|
matchesAnyIdentification = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!matchesAnyIdentification && rules.AllowedItemNamePatterns.Count > 0)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < rules.AllowedItemNamePatterns.Count; i++)
|
||||||
|
{
|
||||||
|
string pattern = rules.AllowedItemNamePatterns[i];
|
||||||
|
if (string.IsNullOrWhiteSpace(pattern))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (Regex.IsMatch(item.Name, pattern, RegexOptions.CultureInvariant | RegexOptions.IgnoreCase))
|
||||||
|
{
|
||||||
|
matchesAnyIdentification = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// Invalid regex: ignore it.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!matchesAnyIdentification)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (rules.AllowedUiCategoryIds.Count > 0)
|
if (rules.AllowedUiCategoryIds.Count > 0)
|
||||||
{
|
{
|
||||||
uint uiCategoryId = item.UiCategory.RowId;
|
uint uiCategoryId = item.UiCategory.RowId;
|
||||||
@@ -18,9 +56,6 @@ internal static class UserCategoryMatcher
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rules.AllowedItemIds.Count > 0 && !rules.AllowedItemIds.Contains(item.Item.ItemId))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (rules.AllowedRarities.Count > 0 && !rules.AllowedRarities.Contains(item.Rarity))
|
if (rules.AllowedRarities.Count > 0 && !rules.AllowedRarities.Contains(item.Rarity))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -39,40 +74,46 @@ internal static class UserCategoryMatcher
|
|||||||
if (!MatchesToggle(rules.Dyeable, item.IsDyeable)) return false;
|
if (!MatchesToggle(rules.Dyeable, item.IsDyeable)) return false;
|
||||||
if (!MatchesToggle(rules.Repairable, item.IsRepairable)) return false;
|
if (!MatchesToggle(rules.Repairable, item.IsRepairable)) return false;
|
||||||
|
|
||||||
if (rules.AllowedItemNamePatterns.Count > 0)
|
|
||||||
{
|
|
||||||
bool any = false;
|
|
||||||
for (int i = 0; i < rules.AllowedItemNamePatterns.Count; i++)
|
|
||||||
{
|
|
||||||
string pattern = rules.AllowedItemNamePatterns[i];
|
|
||||||
if (string.IsNullOrWhiteSpace(pattern))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Treat patterns as regex for now.
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (Regex.IsMatch(item.Name, pattern, RegexOptions.CultureInvariant | RegexOptions.IgnoreCase))
|
|
||||||
{
|
|
||||||
any = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
// Invalid regex: ignore it.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!any)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool InRange<T>(T value, T min, T max) where T : struct, IComparable<T>
|
private static bool InRange<T>(T value, T min, T max) where T : struct, IComparable<T>
|
||||||
=> value.CompareTo(min) >= 0 && value.CompareTo(max) <= 0;
|
=> value.CompareTo(min) >= 0 && value.CompareTo(max) <= 0;
|
||||||
|
|
||||||
|
public static bool IsCatchAll(UserCategoryDefinition userCategory)
|
||||||
|
{
|
||||||
|
var rules = userCategory.Rules;
|
||||||
|
|
||||||
|
if (rules.AllowedItemIds.Count > 0)
|
||||||
|
return false;
|
||||||
|
if (rules.AllowedItemNamePatterns.Count > 0)
|
||||||
|
return false;
|
||||||
|
if (rules.AllowedUiCategoryIds.Count > 0)
|
||||||
|
return false;
|
||||||
|
if (rules.AllowedRarities.Count > 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (rules.Level.Enabled)
|
||||||
|
return false;
|
||||||
|
if (rules.ItemLevel.Enabled)
|
||||||
|
return false;
|
||||||
|
if (rules.VendorPrice.Enabled)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (rules.Untradable.ToggleState != ToggleFilterState.Ignored)
|
||||||
|
return false;
|
||||||
|
if (rules.Unique.ToggleState != ToggleFilterState.Ignored)
|
||||||
|
return false;
|
||||||
|
if (rules.Collectable.ToggleState != ToggleFilterState.Ignored)
|
||||||
|
return false;
|
||||||
|
if (rules.Dyeable.ToggleState != ToggleFilterState.Ignored)
|
||||||
|
return false;
|
||||||
|
if (rules.Repairable.ToggleState != ToggleFilterState.Ignored)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private static bool MatchesToggle(StateFilter filter, bool itemHasProperty)
|
private static bool MatchesToggle(StateFilter filter, bool itemHasProperty)
|
||||||
=> filter.ToggleState switch
|
=> filter.ToggleState switch
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using AetherBags.Configuration;
|
using AetherBags.Configuration;
|
||||||
|
using AetherBags.Inventory;
|
||||||
using AetherBags.Nodes.Color;
|
using AetherBags.Nodes.Color;
|
||||||
using Dalamud.Utility;
|
using Dalamud.Utility;
|
||||||
using FFXIVClientStructs.FFXIV.Component.GUI;
|
using FFXIVClientStructs.FFXIV.Component.GUI;
|
||||||
@@ -8,6 +9,7 @@ using KamiToolKit.Classes;
|
|||||||
using KamiToolKit.Nodes;
|
using KamiToolKit.Nodes;
|
||||||
using Lumina.Excel;
|
using Lumina.Excel;
|
||||||
using Lumina.Excel.Sheets;
|
using Lumina.Excel.Sheets;
|
||||||
|
using Lumina.Text;
|
||||||
using Action = System.Action;
|
using Action = System.Action;
|
||||||
|
|
||||||
namespace AetherBags.Nodes.Configuration.Category;
|
namespace AetherBags.Nodes.Configuration.Category;
|
||||||
@@ -65,6 +67,17 @@ public sealed class CategoryDefinitionConfigurationNode : VerticalListNode
|
|||||||
FitContents = true;
|
FitContents = true;
|
||||||
ItemSpacing = 4.0f;
|
ItemSpacing = 4.0f;
|
||||||
|
|
||||||
|
var catchAllWarningNode = new TextNode
|
||||||
|
{
|
||||||
|
Size = new Vector2(300, 40),
|
||||||
|
TextFlags = TextFlags.MultiLine | TextFlags.AutoAdjustNodeSize,
|
||||||
|
SeString = new SeStringBuilder().Append(" Warning: No rules configured\nThis category won't match anything!").ToReadOnlySeString(),
|
||||||
|
TextColor = ColorHelper.GetColor(17),
|
||||||
|
LineSpacing = 20,
|
||||||
|
IsVisible = UserCategoryMatcher.IsCatchAll(CategoryDefinition),
|
||||||
|
};
|
||||||
|
AddNode(catchAllWarningNode);
|
||||||
|
|
||||||
AddNode(CreateSectionHeader("Basic Settings"));
|
AddNode(CreateSectionHeader("Basic Settings"));
|
||||||
|
|
||||||
_enabledCheckbox = new CheckboxNode
|
_enabledCheckbox = new CheckboxNode
|
||||||
@@ -297,7 +310,7 @@ public sealed class CategoryDefinitionConfigurationNode : VerticalListNode
|
|||||||
|
|
||||||
private static void NotifyChanged()
|
private static void NotifyChanged()
|
||||||
{
|
{
|
||||||
System.AddonInventoryWindow?.ManualInventoryRefresh();
|
System.AddonInventoryWindow.ManualInventoryRefresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void NotifyCategoryPropertyChanged()
|
private void NotifyCategoryPropertyChanged()
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ public sealed class InventoryNotificationNode : SimpleComponentNode
|
|||||||
|
|
||||||
Timeline?.PlayAnimation(101);
|
Timeline?.PlayAnimation(101);
|
||||||
}
|
}
|
||||||
} = new("sdsdsd", "sdsd");
|
}
|
||||||
|
|
||||||
// Future Zeff, this always goes on a parent
|
// Future Zeff, this always goes on a parent
|
||||||
private Timeline ParentLabels => new TimelineBuilder()
|
private Timeline ParentLabels => new TimelineBuilder()
|
||||||
|
|||||||
Reference in New Issue
Block a user