diff --git a/AetherBags/Addons/AddonCategoryConfigurationWindow.cs b/AetherBags/Addons/AddonCategoryConfigurationWindow.cs new file mode 100644 index 0000000..916b39c --- /dev/null +++ b/AetherBags/Addons/AddonCategoryConfigurationWindow.cs @@ -0,0 +1,70 @@ +using System.Collections.Generic; +using System.Linq; +using System.Numerics; +using AetherBags.Nodes.Configuration.Category; +using FFXIVClientStructs.FFXIV.Component.GUI; +using KamiToolKit; +using KamiToolKit.Classes; +using KamiToolKit.Nodes; +using KamiToolKit.Premade.Nodes; + +namespace AetherBags.Addons; + +public class AddonCategoryConfigurationWindow : NativeAddon +{ + private ModifyListNode? _selectionListNode; + private VerticalLineNode? _separatorLine; + private CategoryConfigurationNode? _configNode; + private TextNode? _nothingSelectedTextNode; + + protected override unsafe void OnSetup(AtkUnitBase* addon) + { + List categoryDefinitionsWrappers = System.Config.Categories.UserCategories + .Select(categoryDefinition => new CategoryWrapper(categoryDefinition)) + .ToList(); + + _selectionListNode = new ModifyListNode { + Position = ContentStartPosition, + Size = new Vector2(250.0f, ContentSize.Y), + SelectionOptions = categoryDefinitionsWrappers, + OnOptionChanged = OnOptionChanged, + }; + _selectionListNode.AttachNode(this); + + _separatorLine = new VerticalLineNode { + Position = ContentStartPosition + new Vector2(250.0f + 8.0f, 0.0f), + Size = new Vector2(4.0f, ContentSize.Y), + }; + _separatorLine.AttachNode(this); + + _nothingSelectedTextNode = new TextNode { + Position = ContentStartPosition + new Vector2(250.0f + 16.0f, 0.0f), + Size = ContentSize - new Vector2(250.0f + 16.0f, 0.0f), + AlignmentType = AlignmentType.Center, + TextFlags = TextFlags.WordWrap | TextFlags.MultiLine, + FontSize = 14, + LineSpacing = 22, + FontType = FontType.Axis, + String = "Please select a category on the left or add one.", + TextColor = ColorHelper.GetColor(1), + }; + _nothingSelectedTextNode.AttachNode(this); + + _configNode = new CategoryConfigurationNode { + Position = ContentStartPosition + new Vector2(250.0f + 16.0f, 0.0f), + Size = ContentSize - new Vector2(250.0f + 16.0f, 0.0f), + IsVisible = false, + }; + + _configNode.AttachNode(this); + } + + private void OnOptionChanged(CategoryWrapper? newOption) { + if (_configNode is null) return; + + _configNode.IsVisible = newOption is not null; + _nothingSelectedTextNode?.IsVisible = newOption is null; + + _configNode.ConfigurationOption = newOption; + } +} \ No newline at end of file diff --git a/AetherBags/Addons/AddonConfigurationWindow.cs b/AetherBags/Addons/AddonConfigurationWindow.cs index 981d0d4..228b4ed 100644 --- a/AetherBags/Addons/AddonConfigurationWindow.cs +++ b/AetherBags/Addons/AddonConfigurationWindow.cs @@ -1,6 +1,9 @@ using System; using System.Collections.Generic; using AetherBags.Nodes.Configuration; +using AetherBags.Nodes.Configuration.Category; +using AetherBags.Nodes.Configuration.Currency; +using AetherBags.Nodes.Configuration.General; using FFXIVClientStructs.FFXIV.Component.GUI; using KamiToolKit; using KamiToolKit.Nodes; diff --git a/AetherBags/Addons/CategoryWrapper.cs b/AetherBags/Addons/CategoryWrapper.cs new file mode 100644 index 0000000..68b7f85 --- /dev/null +++ b/AetherBags/Addons/CategoryWrapper.cs @@ -0,0 +1,33 @@ +using AetherBags.Configuration; +using KamiToolKit.Premade; + +namespace AetherBags.Addons; + +public class CategoryWrapper(UserCategoryDefinition categoryDefinition) : IInfoNodeData +{ + public UserCategoryDefinition? CategoryDefinition { get; } = categoryDefinition; + + public string GetLabel() { + + return CategoryDefinition!.Name; + } + + public string GetSubLabel() { + return CategoryDefinition!.Enabled ? "Enabled" : "Disabled"; + } + + public uint? GetId() => null; + + public uint? GetIconId() { + return 0; + } + + public string? GetTexturePath() + => null; + + public int Compare(IInfoNodeData other, string sortingMode) { + if (other is not CategoryWrapper otherWrapper) return 0; + + return CategoryDefinition!.Order.CompareTo(otherWrapper.CategoryDefinition!.Order); + } +} \ No newline at end of file diff --git a/AetherBags/Configuration/CategorySettings.cs b/AetherBags/Configuration/CategorySettings.cs index 3aa5d18..1ab344b 100644 --- a/AetherBags/Configuration/CategorySettings.cs +++ b/AetherBags/Configuration/CategorySettings.cs @@ -16,6 +16,7 @@ public class CategorySettings public class UserCategoryDefinition { + public bool Enabled { get; set; } = true; public string Id { get; set; } = Guid.NewGuid().ToString("N"); public string Name { get; set; } = "New Category"; public string Description { get; set; } = string.Empty; diff --git a/AetherBags/Inventory/InventoryState.cs b/AetherBags/Inventory/InventoryState.cs index b5599fa..d4e279a 100644 --- a/AetherBags/Inventory/InventoryState.cs +++ b/AetherBags/Inventory/InventoryState.cs @@ -38,7 +38,7 @@ public static unsafe class InventoryState InventoryStackMode stackMode = config.General.StackMode; bool userCategoriesEnabled = config.Categories.UserCategoriesEnabled; bool gameCategoriesEnabled = config.Categories.GameCategoriesEnabled; - List userCategories = config.Categories.UserCategories; + List userCategories = config.Categories.UserCategories.Where(category => category.Enabled).ToList(); Services.Logger.DebugOnly($"RefreshFromGame StackMode={stackMode}"); diff --git a/AetherBags/Nodes/Configuration/Category/CategoryConfigurationNode.cs b/AetherBags/Nodes/Configuration/Category/CategoryConfigurationNode.cs new file mode 100644 index 0000000..e69e209 --- /dev/null +++ b/AetherBags/Nodes/Configuration/Category/CategoryConfigurationNode.cs @@ -0,0 +1,55 @@ +using System.Collections.Generic; +using System.Numerics; +using AetherBags.Addons; +using AetherBags.Configuration; +using KamiToolKit.Nodes; +using KamiToolKit.Premade.Nodes; +using Lumina.Excel.Sheets; + +namespace AetherBags.Nodes.Configuration.Category; + +public class CategoryConfigurationNode : ConfigNode { + private readonly ScrollingAreaNode _categoryList; + private CategoryDefinitionConfigurationNode? _activeNode; + + public CategoryConfigurationNode() { + _categoryList = new ScrollingAreaNode { + ContentHeight = 100.0f, + AutoHideScrollBar = true, + }; + _categoryList.ContentNode.FitContents = true; + _categoryList.AttachNode(this); + } + + + protected override void OptionChanged(CategoryWrapper? option) { + if (option?.CategoryDefinition is null) { + _categoryList.IsVisible = false; + return; + } + + _categoryList.IsVisible = true; + + if (_activeNode is null) { + _activeNode = new CategoryDefinitionConfigurationNode(option.CategoryDefinition) { + Size = new Vector2(_categoryList.ContentNode.Width, 0f), + }; + _categoryList.ContentNode.AddNode(_activeNode); + } else { + _activeNode.SetCategory(option.CategoryDefinition); + } + + _categoryList.ContentNode.RecalculateLayout(); + _categoryList.ContentHeight = _categoryList.ContentNode.Height; + } + + protected override void OnSizeChanged() { + base.OnSizeChanged(); + _categoryList.Size = Size; + _categoryList.ContentNode.Width = Width; + + foreach (var node in _categoryList.ContentNode.GetNodes()) { + node.Width = Width; + } + } +} diff --git a/AetherBags/Nodes/Configuration/Category/CategoryDefinitionConfigurationNode.cs b/AetherBags/Nodes/Configuration/Category/CategoryDefinitionConfigurationNode.cs new file mode 100644 index 0000000..af525f9 --- /dev/null +++ b/AetherBags/Nodes/Configuration/Category/CategoryDefinitionConfigurationNode.cs @@ -0,0 +1,69 @@ +using System.Numerics; +using AetherBags.Configuration; +using AetherBags.Nodes.Color; +using FFXIVClientStructs.FFXIV.Component.GUI; +using KamiToolKit.Nodes; +using Action = Lumina.Excel.Sheets.Action; + +namespace AetherBags.Nodes.Configuration.Category; + +public sealed class CategoryDefinitionConfigurationNode : VerticalListNode { + private readonly CheckboxNode enabledCheckbox; + private readonly TextInputNode nameInputNode; + private readonly TextInputNode descriptionInputNode; + private readonly ColorInputRow colorInputNode; + + public UserCategoryDefinition CategoryDefinition { get; private set; } + + public CategoryDefinitionConfigurationNode(UserCategoryDefinition categoryDefinition) { + CategoryDefinition = categoryDefinition; + + FirstItemSpacing = 35.0f; + ItemSpacing = 5.0f; + + enabledCheckbox = new CheckboxNode { + IsChecked = CategoryDefinition.Enabled, + OnClick = isChecked => CategoryDefinition.Enabled = isChecked, + }; + AddNode(enabledCheckbox); + + colorInputNode = new ColorInputRow + { + Label = "Color", + CurrentColor = CategoryDefinition.Color, + DefaultColor = new UserCategoryDefinition().Color, + OnColorConfirmed = color => CategoryDefinition.Color = color, + // OnColorChange = color => CategoryDefinition.Color = color, + OnColorCanceled = color => CategoryDefinition.Color = color, + }; + AddNode(colorInputNode); + + nameInputNode = new TextInputNode + { + String = CategoryDefinition.Name, + OnInputComplete = name => CategoryDefinition.Name = name.ExtractText() + }; + AddNode(nameInputNode); + + descriptionInputNode = new TextInputNode + { + String = CategoryDefinition.Description, + OnInputComplete = name => CategoryDefinition.Description = name.ExtractText() + }; + AddNode(descriptionInputNode); + + // TODO: Add Rules + } + + public void SetCategory(UserCategoryDefinition newCategory) { + CategoryDefinition = newCategory; + RefreshValues(); + } + + private void RefreshValues() + { + enabledCheckbox.IsChecked = CategoryDefinition.Enabled; + colorInputNode.CurrentColor = CategoryDefinition.Color; + nameInputNode.String = CategoryDefinition.Name; + } +} diff --git a/AetherBags/Nodes/Configuration/Category/CategoryScrollingAreaNode.cs b/AetherBags/Nodes/Configuration/Category/CategoryScrollingAreaNode.cs new file mode 100644 index 0000000..7d489c9 --- /dev/null +++ b/AetherBags/Nodes/Configuration/Category/CategoryScrollingAreaNode.cs @@ -0,0 +1,34 @@ +using System.Numerics; +using AetherBags.Addons; +using KamiToolKit.Nodes; + +namespace AetherBags.Nodes.Configuration.Category; + +public class CategoryScrollingAreaNode : ScrollingAreaNode +{ + private AddonCategoryConfigurationWindow? _categoryConfigurationAddon; + private readonly TextButtonNode _categoryConfigurationButtonNode; + + public CategoryScrollingAreaNode() + { + InitializeCategoryAddon(); + + _categoryConfigurationButtonNode = new TextButtonNode + { + Size = new Vector2(300, 28), + String = "Configure Categories", + OnClick = () => _categoryConfigurationAddon?.Toggle(), + }; + _categoryConfigurationButtonNode.AttachNode(this); + } + + private void InitializeCategoryAddon() { + if (_categoryConfigurationAddon is not null) return; + + _categoryConfigurationAddon = new AddonCategoryConfigurationWindow { + Size = new Vector2(700.0f, 500.0f), + InternalName = "AetherBags_CategoryConfig", + Title = "Category Configuration Window", + }; + } +} \ No newline at end of file diff --git a/AetherBags/Nodes/Configuration/CategoryScrollingAreaNode.cs b/AetherBags/Nodes/Configuration/CategoryScrollingAreaNode.cs deleted file mode 100644 index fd33e4c..0000000 --- a/AetherBags/Nodes/Configuration/CategoryScrollingAreaNode.cs +++ /dev/null @@ -1,7 +0,0 @@ -using KamiToolKit.Nodes; - -namespace AetherBags.Nodes.Configuration; - -public class CategoryScrollingAreaNode : ScrollingAreaNode -{ -} \ No newline at end of file diff --git a/AetherBags/Nodes/Configuration/Currency/CurrencyConfigurationNode.cs b/AetherBags/Nodes/Configuration/Currency/CurrencyGeneralConfigurationNode.cs similarity index 96% rename from AetherBags/Nodes/Configuration/Currency/CurrencyConfigurationNode.cs rename to AetherBags/Nodes/Configuration/Currency/CurrencyGeneralConfigurationNode.cs index 0d2814b..f8c1006 100644 --- a/AetherBags/Nodes/Configuration/Currency/CurrencyConfigurationNode.cs +++ b/AetherBags/Nodes/Configuration/Currency/CurrencyGeneralConfigurationNode.cs @@ -6,9 +6,9 @@ using KamiToolKit.Nodes; namespace AetherBags.Nodes.Configuration.Currency; -public sealed class CurrencyConfigurationNode : TabbedVerticalListNode +public sealed class CurrencyGeneralConfigurationNode : TabbedVerticalListNode { - public CurrencyConfigurationNode() + public CurrencyGeneralConfigurationNode() { CurrencySettings config = System.Config.Currency; diff --git a/AetherBags/Nodes/Configuration/CurrencyScrollingAreaNode.cs b/AetherBags/Nodes/Configuration/Currency/CurrencyScrollingAreaNode.cs similarity index 58% rename from AetherBags/Nodes/Configuration/CurrencyScrollingAreaNode.cs rename to AetherBags/Nodes/Configuration/Currency/CurrencyScrollingAreaNode.cs index 70847d4..f0e074f 100644 --- a/AetherBags/Nodes/Configuration/CurrencyScrollingAreaNode.cs +++ b/AetherBags/Nodes/Configuration/Currency/CurrencyScrollingAreaNode.cs @@ -1,13 +1,12 @@ -using AetherBags.Nodes.Configuration.Currency; using KamiToolKit.Nodes; -namespace AetherBags.Nodes.Configuration; +namespace AetherBags.Nodes.Configuration.Currency; public sealed class CurrencyScrollingAreaNode : ScrollingAreaNode { public CurrencyScrollingAreaNode() { - ContentNode.AddNode(new CurrencyConfigurationNode + ContentNode.AddNode(new CurrencyGeneralConfigurationNode { Size = Size }); diff --git a/AetherBags/Nodes/Configuration/GeneralScrollingAreaNode.cs b/AetherBags/Nodes/Configuration/General/GeneralScrollingAreaNode.cs similarity index 96% rename from AetherBags/Nodes/Configuration/GeneralScrollingAreaNode.cs rename to AetherBags/Nodes/Configuration/General/GeneralScrollingAreaNode.cs index 1d2544c..3098e00 100644 --- a/AetherBags/Nodes/Configuration/GeneralScrollingAreaNode.cs +++ b/AetherBags/Nodes/Configuration/General/GeneralScrollingAreaNode.cs @@ -1,11 +1,11 @@ -using AetherBags.Configuration; -using AetherBags.Nodes.Configuration.Layout; -using KamiToolKit.Nodes; using System; using System.Linq; using System.Numerics; +using AetherBags.Configuration; +using AetherBags.Nodes.Configuration.Layout; +using KamiToolKit.Nodes; -namespace AetherBags.Nodes.Configuration; +namespace AetherBags.Nodes.Configuration.General; public sealed class GeneralScrollingAreaNode : ScrollingAreaNode {