From aedcc7953c5fe7fa889d619a3b7e634074664496 Mon Sep 17 00:00:00 2001 From: Zeffuro Date: Tue, 23 Dec 2025 07:40:53 +0100 Subject: [PATCH] Add Color options --- AetherBags/Addons/AddonInventoryWindow.cs | 7 +- AetherBags/AetherBags.csproj | 1 + AetherBags/Configuration/CurrencySettings.cs | 4 + .../Media/Textures/alpha_background.png | Bin 0 -> 406 bytes AetherBags/Nodes/Color/ColorInputRow.cs | 92 +++++++++++++ .../Nodes/Color/ColorPreviewButtonNode.cs | 43 ++++++ AetherBags/Nodes/Color/ColorPreviewNode.cs | 112 ++++++++++++++++ .../Currency/CurrencyConfigurationNode.cs | 126 ++++++++++++++++++ .../CurrencyScrollingAreaNode.cs | 11 +- .../Configuration/GeneralScrollingAreaNode.cs | 2 +- .../Layout/CompactLookaheadNode.cs | 2 +- .../Layout/LayoutConfigurationNode.cs | 6 +- AetherBags/Nodes/InventoryFooterNode.cs | 3 + AetherBags/Nodes/LabeledDropdownNode.cs | 11 +- AetherBags/Plugin.cs | 2 +- 15 files changed, 404 insertions(+), 18 deletions(-) create mode 100644 AetherBags/Media/Textures/alpha_background.png create mode 100644 AetherBags/Nodes/Color/ColorInputRow.cs create mode 100644 AetherBags/Nodes/Color/ColorPreviewButtonNode.cs create mode 100644 AetherBags/Nodes/Color/ColorPreviewNode.cs create mode 100644 AetherBags/Nodes/Configuration/Currency/CurrencyConfigurationNode.cs diff --git a/AetherBags/Addons/AddonInventoryWindow.cs b/AetherBags/Addons/AddonInventoryWindow.cs index 692207c..76cad89 100644 --- a/AetherBags/Addons/AddonInventoryWindow.cs +++ b/AetherBags/Addons/AddonInventoryWindow.cs @@ -117,12 +117,17 @@ public class AddonInventoryWindow : NativeAddon base.OnUpdate(addon); } - public void ManualRefresh() + public void ManualInventoryRefresh() { InventoryState.RefreshFromGame(); RefreshCategoriesCore(true); } + public void ManualCurrencyRefresh() + { + _footerNode.RefreshCurrencies(); + } + private void OnInventoryUpdate(AddonEvent type, AddonArgs args) { InventoryState.RefreshFromGame(); diff --git a/AetherBags/AetherBags.csproj b/AetherBags/AetherBags.csproj index 394cab3..9215a23 100644 --- a/AetherBags/AetherBags.csproj +++ b/AetherBags/AetherBags.csproj @@ -28,5 +28,6 @@ PreserveNewest false + diff --git a/AetherBags/Configuration/CurrencySettings.cs b/AetherBags/Configuration/CurrencySettings.cs index e5d2091..0b5ad3f 100644 --- a/AetherBags/Configuration/CurrencySettings.cs +++ b/AetherBags/Configuration/CurrencySettings.cs @@ -1,10 +1,14 @@ using System.Numerics; using KamiToolKit.Classes; +using SixLabors.ImageSharp.PixelFormats; namespace AetherBags.Configuration; public class CurrencySettings { + public bool Enabled { get; set; } = true; + public bool ColorWhenCapped { get; set; } = true; + public bool ColorWhenLimited { get; set; } = true; public Vector4 DefaultColor { get; set; } = ColorHelper.GetColor(8); public Vector4 CappedColor { get; set; } = ColorHelper.GetColor(43); public Vector4 LimitColor { get; set; } = ColorHelper.GetColor(17); diff --git a/AetherBags/Media/Textures/alpha_background.png b/AetherBags/Media/Textures/alpha_background.png new file mode 100644 index 0000000000000000000000000000000000000000..c239751af15397e1c89e94ce9da0f98266da74d9 GIT binary patch literal 406 zcmV;H0crk;P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0V_#FK~y+Tl~UWT zL{JRf|NmJS*AbqGCzqKRPk6#y=*enM1&5K-WTjQ@>TRpr?M7LaG4ed0bx{;--|u%q z46tV_+qOy9b-G+GD;S1BmSxfN`J`{6JkKMLIF7RdeE8RO9Zl0j<2cS*fNv&1B_wR& zy6!mvg7ygD69UK{0pxUqzVA5^fQT(n*Xxz59TCU~pU-Em3|qbxf;CO!tuKMgn5Id? zFmUA~QMh@UriUoYlB%kr$K&w_@T*^ + { + _colorPickerAddon?.InitialColor = CurrentColor; + _colorPickerAddon?.DefaultColor = DefaultColor; + _colorPickerAddon?.Toggle(); + _colorPickerAddon?.OnColorConfirmed = color => + { + CurrentColor = color; + _colorPreview?.Color = color; + _initialColor = color; + OnColorConfirmed?.Invoke(color); + }; + _colorPickerAddon?.OnColorCancelled = () => OnColorCanceled?.Invoke(_initialColor); + } + }; + _colorPreview.AttachNode(this); + + _labelTextNode = new LabelTextNode + { + Position = new Vector2(28, 0), + Size = Size with { Y = 24 }, + String = Label ?? string.Empty, + }; + _labelTextNode.AttachNode(this); + } + + private void InitializeColorPicker() { + if (_colorPickerAddon is not null) return; + + _colorPickerAddon = new ColorPickerAddon { + InternalName = "ColorPicker", + Title = "ColorPicker_AetherBags", + }; + } + + protected override void Dispose(bool disposing, bool isNativeDestructor) { + base.Dispose(); + + _colorPickerAddon?.Dispose(); + _colorPickerAddon = null; + } + + public required string Label + { + get; + set + { + field = value; + _labelTextNode.String = value; + } + } + + public required Vector4 CurrentColor + { + get; + set + { + field = value; + _colorPreview.Color = value; + } + } + + public required Vector4 DefaultColor { get; set; } + public Action? OnColorConfirmed { get; set; } + public Action? OnColorCanceled { get; set; } + public Action? OnColorChange { get; set; } +} \ No newline at end of file diff --git a/AetherBags/Nodes/Color/ColorPreviewButtonNode.cs b/AetherBags/Nodes/Color/ColorPreviewButtonNode.cs new file mode 100644 index 0000000..3c48edb --- /dev/null +++ b/AetherBags/Nodes/Color/ColorPreviewButtonNode.cs @@ -0,0 +1,43 @@ +using System.Numerics; +using Dalamud.Game.Addon.Events.EventDataTypes; +using KamiToolKit.Nodes; +using ColorPreviewNode = AetherBags.Nodes.Color.ColorPreviewNode; + +namespace AetherBags.Nodes.Color; + +public class ColorPreviewButtonNode : ButtonBase { + private readonly ColorPreviewNode _colorPreview; + + public ColorPreviewButtonNode() { + _colorPreview = new ColorPreviewNode { + IsVisible = true, + Position = Vector2.Zero, + Size = base.Size, + }; + + _colorPreview.AttachNode(this); + + LoadTimelines(); + + InitializeComponentEvents(); + } + + public override Vector4 Color + { + get => _colorPreview.Color; + set => _colorPreview.Color = value; + } + + public override Vector2 Size + { + get => base.Size; + set + { + base.Size = value; + _colorPreview.Size = value; + } + } + + private void LoadTimelines() + => LoadTwoPartTimelines(this, _colorPreview); +} diff --git a/AetherBags/Nodes/Color/ColorPreviewNode.cs b/AetherBags/Nodes/Color/ColorPreviewNode.cs new file mode 100644 index 0000000..848e6af --- /dev/null +++ b/AetherBags/Nodes/Color/ColorPreviewNode.cs @@ -0,0 +1,112 @@ +using System.Drawing; +using System.IO; +using System.Numerics; +using Dalamud.Interface; +using KamiToolKit.Classes; +using KamiToolKit.Nodes; + +namespace AetherBags.Nodes.Color; + +public class ColorPreviewNode : ResNode +{ + private readonly BackgroundImageNode _colorBackground; + private readonly ImGuiImageNode _alphaLayer; + private readonly BackgroundImageNode _colorForeground; + + private bool _isDisposed; + + public ColorPreviewNode() + { + base.Size = new Vector2(64, 64); + + _colorBackground = new BackgroundImageNode + { + IsVisible = true, + Color = KnownColor.Black.Vector(), + FitTexture = true, + }; + _colorBackground.AttachNode(this); + + _alphaLayer = new ImGuiImageNode + { + IsVisible = true, + TexturePath = GetAlphaTexturePath(), + WrapMode = WrapMode.Tile, + }; + _alphaLayer.AttachNode(this); + + _colorForeground = new BackgroundImageNode + { + IsVisible = true, + Color = KnownColor.White.Vector(), + FitTexture = true, + }; + _colorForeground.AttachNode(this); + + UpdateLayout(); + } + + public override Vector4 Color + { + get => _colorForeground.Color; + set => _colorForeground.Color = value; + } + + public override Vector2 Size + { + get => base.Size; + set + { + base.Size = value; + UpdateLayout(); + } + } + + public BackgroundImageNode BackgroundNode => _colorBackground; + public BackgroundImageNode ForegroundNode => _colorForeground; + + private void UpdateLayout() + { + const float backgroundPadding = 6f; + const float alphaPadding = 8f; + const float foregroundPadding = 8f; + + var bgSize = base.Size - new Vector2(backgroundPadding * 2f); + var alphaSize = base.Size - new Vector2(alphaPadding * 2f); + var fgSize = base.Size - new Vector2(foregroundPadding * 2f); + + _colorBackground.Size = bgSize; + _colorBackground.Position = new Vector2(backgroundPadding, backgroundPadding); + + _alphaLayer.Size = alphaSize; + _alphaLayer.Position = new Vector2(alphaPadding, alphaPadding); + + _colorForeground.Size = fgSize; + _colorForeground.Position = new Vector2(foregroundPadding, foregroundPadding); + } + + private static string GetAlphaTexturePath() + { + var baseDir = Services.PluginInterface.AssemblyLocation.Directory!.FullName; + return Path.Combine(baseDir, "Media", "Textures", "alpha_background.png"); + } + + protected override void Dispose(bool disposing, bool isNativeDestructor) + { + if (_isDisposed) + { + base.Dispose(disposing, isNativeDestructor); + return; + } + + _isDisposed = true; + if (disposing) + { + _colorBackground.Dispose(); + _alphaLayer.Dispose(); + _colorForeground.Dispose(); + } + + base.Dispose(disposing, isNativeDestructor); + } +} diff --git a/AetherBags/Nodes/Configuration/Currency/CurrencyConfigurationNode.cs b/AetherBags/Nodes/Configuration/Currency/CurrencyConfigurationNode.cs new file mode 100644 index 0000000..d3c4816 --- /dev/null +++ b/AetherBags/Nodes/Configuration/Currency/CurrencyConfigurationNode.cs @@ -0,0 +1,126 @@ +using System.Drawing; +using System.Numerics; +using AetherBags.Configuration; +using AetherBags.Nodes.Color; +using Dalamud.Interface; +using KamiToolKit.Classes; +using KamiToolKit.Nodes; +using KamiToolKit.Premade.Addons; +using KamiToolKit.Premade.Nodes; + +namespace AetherBags.Nodes.Configuration.Currency; + +public sealed class CurrencyConfigurationNode : TabbedVerticalListNode +{ + public CurrencyConfigurationNode() + { + CurrencySettings config = System.Config.Currency; + + LabelTextNode titleNode = new LabelTextNode + { + Size = Size with { Y = 18 }, + String = "Currency Configuration", + TextColor = ColorHelper.GetColor(2), + TextOutlineColor = ColorHelper.GetColor(0), + }; + AddNode(titleNode); + + AddTab(1); + + CheckboxNode currencyEnabledCheckbox = new CheckboxNode + { + Size = Size with { Y = 18 }, + IsVisible = true, + String = "Show Currency", + IsChecked = config.Enabled, + OnClick = isChecked => + { + config.Enabled = isChecked; + RefreshCurrency(); + } + }; + AddNode(currencyEnabledCheckbox); + + AddTab(1); + + ColorInputRow defaultCurrencyColorNode = new ColorInputRow + { + Label = "Default Currency Color", + Size = new Vector2(300, 24), + CurrentColor = config.DefaultColor, + DefaultColor = new CurrencySettings().DefaultColor, + OnColorConfirmed = color => + { + config.DefaultColor = color; + RefreshCurrency(); + }, + }; + AddNode(defaultCurrencyColorNode); + + AddNode(); + + CheckboxNode cappedEnabledCheckbox = new CheckboxNode + { + Size = Size with { Y = 18 }, + IsVisible = true, + String = "Color When Capped", + IsChecked = config.ColorWhenCapped, + OnClick = isChecked => + { + config.ColorWhenCapped = isChecked; + RefreshCurrency(); + } + }; + AddNode(cappedEnabledCheckbox); + + AddTab(1); + + ColorInputRow cappedCurrencyColorNode = new ColorInputRow + { + Label = "Capped Currency Color", + Size = new Vector2(300, 24), + CurrentColor = config.CappedColor, + DefaultColor = new CurrencySettings().CappedColor, + OnColorConfirmed = color => + { + config.CappedColor = color; + RefreshCurrency(); + }, + }; + AddNode(cappedCurrencyColorNode); + + SubtractTab(1); + + CheckboxNode limitedEnabledCheckbox = new CheckboxNode + { + Size = Size with { Y = 18 }, + IsVisible = true, + String = "Color Weekly Limit", + IsChecked = config.ColorWhenLimited, + OnClick = isChecked => + { + config.ColorWhenLimited = isChecked; + RefreshCurrency(); + } + }; + AddNode(limitedEnabledCheckbox); + + AddTab(1); + + ColorInputRow limitCurrencyColorNode = new ColorInputRow + { + Label = "Limit Currency Color", + Size = new Vector2(300, 24), + CurrentColor = config.LimitColor, + DefaultColor = new CurrencySettings().LimitColor, + OnColorConfirmed = color => + { + config.LimitColor = color; + RefreshCurrency(); + }, + }; + AddNode(limitCurrencyColorNode); + } + + private void RefreshCurrency() => System.AddonInventoryWindow.ManualCurrencyRefresh(); +} \ No newline at end of file diff --git a/AetherBags/Nodes/Configuration/CurrencyScrollingAreaNode.cs b/AetherBags/Nodes/Configuration/CurrencyScrollingAreaNode.cs index c15980a..70847d4 100644 --- a/AetherBags/Nodes/Configuration/CurrencyScrollingAreaNode.cs +++ b/AetherBags/Nodes/Configuration/CurrencyScrollingAreaNode.cs @@ -1,8 +1,15 @@ +using AetherBags.Nodes.Configuration.Currency; using KamiToolKit.Nodes; namespace AetherBags.Nodes.Configuration; -public class CurrencyScrollingAreaNode : ScrollingAreaNode +public sealed class CurrencyScrollingAreaNode : ScrollingAreaNode { - + public CurrencyScrollingAreaNode() + { + ContentNode.AddNode(new CurrencyConfigurationNode + { + Size = Size + }); + } } \ No newline at end of file diff --git a/AetherBags/Nodes/Configuration/GeneralScrollingAreaNode.cs b/AetherBags/Nodes/Configuration/GeneralScrollingAreaNode.cs index 6de7fa8..6436640 100644 --- a/AetherBags/Nodes/Configuration/GeneralScrollingAreaNode.cs +++ b/AetherBags/Nodes/Configuration/GeneralScrollingAreaNode.cs @@ -46,5 +46,5 @@ public sealed class GeneralScrollingAreaNode : ScrollingAreaNode System.AddonInventoryWindow.ManualRefresh(); + private void RefreshInventory() => System.AddonInventoryWindow.ManualInventoryRefresh(); } \ No newline at end of file diff --git a/AetherBags/Nodes/Configuration/Layout/CompactLookaheadNode.cs b/AetherBags/Nodes/Configuration/Layout/CompactLookaheadNode.cs index 51689a8..638ba6f 100644 --- a/AetherBags/Nodes/Configuration/Layout/CompactLookaheadNode.cs +++ b/AetherBags/Nodes/Configuration/Layout/CompactLookaheadNode.cs @@ -32,7 +32,7 @@ internal sealed class CompactLookaheadNode : SimpleComponentNode OnValueUpdate = value => { config.CompactLookahead = value; - System.AddonInventoryWindow.ManualRefresh(); + System.AddonInventoryWindow.ManualInventoryRefresh(); } }; CompactLookahead.ComponentBase->SetEnabledState(config.CompactPackingEnabled); diff --git a/AetherBags/Nodes/Configuration/Layout/LayoutConfigurationNode.cs b/AetherBags/Nodes/Configuration/Layout/LayoutConfigurationNode.cs index 121762b..87e9650 100644 --- a/AetherBags/Nodes/Configuration/Layout/LayoutConfigurationNode.cs +++ b/AetherBags/Nodes/Configuration/Layout/LayoutConfigurationNode.cs @@ -38,7 +38,7 @@ internal class LayoutConfigurationNode : TabbedVerticalListNode _preferLargestFitCheckboxNode.IsEnabled = isChecked; _useStableInsertCheckboxNode.IsEnabled = isChecked; _compactLookaheadNode.CompactLookahead.ComponentBase->SetEnabledState(isChecked); - System.AddonInventoryWindow.ManualRefresh(); + System.AddonInventoryWindow.ManualInventoryRefresh(); } }; AddNode(compactPackingCheckboxNode); @@ -54,7 +54,7 @@ internal class LayoutConfigurationNode : TabbedVerticalListNode OnClick = isChecked => { config.CompactPreferLargestFit = isChecked; - System.AddonInventoryWindow.ManualRefresh(); + System.AddonInventoryWindow.ManualInventoryRefresh(); } }; AddNode(_preferLargestFitCheckboxNode); @@ -69,7 +69,7 @@ internal class LayoutConfigurationNode : TabbedVerticalListNode OnClick = isChecked => { config.CompactStableInsert = isChecked; - System.AddonInventoryWindow.ManualRefresh(); + System.AddonInventoryWindow.ManualInventoryRefresh(); } }; AddNode(_useStableInsertCheckboxNode); diff --git a/AetherBags/Nodes/InventoryFooterNode.cs b/AetherBags/Nodes/InventoryFooterNode.cs index 3f936a3..11a4095 100644 --- a/AetherBags/Nodes/InventoryFooterNode.cs +++ b/AetherBags/Nodes/InventoryFooterNode.cs @@ -34,6 +34,7 @@ public sealed class InventoryFooterNode : SimpleComponentNode { Position = new Vector2(0, 0), Size = new Vector2(120, 28), + IsVisible = System.Config.Currency.Enabled }; _currencyListNode.AttachNode(this); @@ -42,6 +43,8 @@ public sealed class InventoryFooterNode : SimpleComponentNode public void RefreshCurrencies() { + _currencyListNode.IsVisible = System.Config.Currency.Enabled; + IReadOnlyList currencyInfoList = InventoryState.GetCurrencyInfoList([1, 28, 0xFFFF_FFFE, 0xFFFF_FFFD]); _currencyListNode.SyncWithListDataByKey( dataList: currencyInfoList, diff --git a/AetherBags/Nodes/LabeledDropdownNode.cs b/AetherBags/Nodes/LabeledDropdownNode.cs index 9f285fa..c3e98e9 100644 --- a/AetherBags/Nodes/LabeledDropdownNode.cs +++ b/AetherBags/Nodes/LabeledDropdownNode.cs @@ -17,15 +17,8 @@ public class LabeledDropdownNode : SimpleComponentNode { }; _gridNode.AttachNode(this); - _labelNode = new TextNode { - AlignmentType = AlignmentType.Bottom, - FontType = FontType.Axis, - FontSize = 14, - LineSpacing = 14, - TextColor = ColorHelper.GetColor(8), - TextOutlineColor = ColorHelper.GetColor(7), - TextFlags = TextFlags.Edge | TextFlags.AutoAdjustNodeSize, - String = string.Empty, + _labelNode = new LabelTextNode { + String = String.Empty, }; _labelNode.AttachNode(_gridNode[0, 0]); diff --git a/AetherBags/Plugin.cs b/AetherBags/Plugin.cs index dbc9310..258fa71 100644 --- a/AetherBags/Plugin.cs +++ b/AetherBags/Plugin.cs @@ -88,7 +88,7 @@ public class Plugin : IDalamudPlugin { // Manually import from SortaKinda for testing until we have a proper config window ImportExportResetHelper.TryImportSortaKindaFromClipboard(true); - System.AddonInventoryWindow.ManualRefresh(); + System.AddonInventoryWindow.ManualInventoryRefresh(); } break; }