Initial window + settings for categories

This commit is contained in:
Zeffuro
2025-12-25 10:06:20 +01:00
parent adfe3dc961
commit c3e3f8b2bf
12 changed files with 274 additions and 17 deletions
@@ -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<CategoryWrapper>? _selectionListNode;
private VerticalLineNode? _separatorLine;
private CategoryConfigurationNode? _configNode;
private TextNode? _nothingSelectedTextNode;
protected override unsafe void OnSetup(AtkUnitBase* addon)
{
List<CategoryWrapper> categoryDefinitionsWrappers = System.Config.Categories.UserCategories
.Select(categoryDefinition => new CategoryWrapper(categoryDefinition))
.ToList();
_selectionListNode = new ModifyListNode<CategoryWrapper> {
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;
}
}
@@ -1,6 +1,9 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using AetherBags.Nodes.Configuration; 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 FFXIVClientStructs.FFXIV.Component.GUI;
using KamiToolKit; using KamiToolKit;
using KamiToolKit.Nodes; using KamiToolKit.Nodes;
+33
View File
@@ -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);
}
}
@@ -16,6 +16,7 @@ public class CategorySettings
public class UserCategoryDefinition public class UserCategoryDefinition
{ {
public bool Enabled { get; set; } = true;
public string Id { get; set; } = Guid.NewGuid().ToString("N"); public string Id { get; set; } = Guid.NewGuid().ToString("N");
public string Name { get; set; } = "New Category"; public string Name { get; set; } = "New Category";
public string Description { get; set; } = string.Empty; public string Description { get; set; } = string.Empty;
+1 -1
View File
@@ -38,7 +38,7 @@ public static unsafe class InventoryState
InventoryStackMode stackMode = config.General.StackMode; InventoryStackMode stackMode = config.General.StackMode;
bool userCategoriesEnabled = config.Categories.UserCategoriesEnabled; bool userCategoriesEnabled = config.Categories.UserCategoriesEnabled;
bool gameCategoriesEnabled = config.Categories.GameCategoriesEnabled; bool gameCategoriesEnabled = config.Categories.GameCategoriesEnabled;
List<UserCategoryDefinition> userCategories = config.Categories.UserCategories; List<UserCategoryDefinition> userCategories = config.Categories.UserCategories.Where(category => category.Enabled).ToList();
Services.Logger.DebugOnly($"RefreshFromGame StackMode={stackMode}"); Services.Logger.DebugOnly($"RefreshFromGame StackMode={stackMode}");
@@ -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<CategoryWrapper> {
private readonly ScrollingAreaNode<VerticalListNode> _categoryList;
private CategoryDefinitionConfigurationNode? _activeNode;
public CategoryConfigurationNode() {
_categoryList = new ScrollingAreaNode<VerticalListNode> {
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<CategoryDefinitionConfigurationNode>()) {
node.Width = Width;
}
}
}
@@ -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;
}
}
@@ -0,0 +1,34 @@
using System.Numerics;
using AetherBags.Addons;
using KamiToolKit.Nodes;
namespace AetherBags.Nodes.Configuration.Category;
public class CategoryScrollingAreaNode : ScrollingAreaNode<VerticalListNode>
{
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",
};
}
}
@@ -1,7 +0,0 @@
using KamiToolKit.Nodes;
namespace AetherBags.Nodes.Configuration;
public class CategoryScrollingAreaNode : ScrollingAreaNode<VerticalListNode>
{
}
@@ -6,9 +6,9 @@ using KamiToolKit.Nodes;
namespace AetherBags.Nodes.Configuration.Currency; namespace AetherBags.Nodes.Configuration.Currency;
public sealed class CurrencyConfigurationNode : TabbedVerticalListNode public sealed class CurrencyGeneralConfigurationNode : TabbedVerticalListNode
{ {
public CurrencyConfigurationNode() public CurrencyGeneralConfigurationNode()
{ {
CurrencySettings config = System.Config.Currency; CurrencySettings config = System.Config.Currency;
@@ -1,13 +1,12 @@
using AetherBags.Nodes.Configuration.Currency;
using KamiToolKit.Nodes; using KamiToolKit.Nodes;
namespace AetherBags.Nodes.Configuration; namespace AetherBags.Nodes.Configuration.Currency;
public sealed class CurrencyScrollingAreaNode : ScrollingAreaNode<VerticalListNode> public sealed class CurrencyScrollingAreaNode : ScrollingAreaNode<VerticalListNode>
{ {
public CurrencyScrollingAreaNode() public CurrencyScrollingAreaNode()
{ {
ContentNode.AddNode(new CurrencyConfigurationNode ContentNode.AddNode(new CurrencyGeneralConfigurationNode
{ {
Size = Size Size = Size
}); });
@@ -1,11 +1,11 @@
using AetherBags.Configuration;
using AetherBags.Nodes.Configuration.Layout;
using KamiToolKit.Nodes;
using System; using System;
using System.Linq; using System.Linq;
using System.Numerics; 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<VerticalListNode> public sealed class GeneralScrollingAreaNode : ScrollingAreaNode<VerticalListNode>
{ {