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 0000000..c239751
Binary files /dev/null and b/AetherBags/Media/Textures/alpha_background.png differ
diff --git a/AetherBags/Nodes/Color/ColorInputRow.cs b/AetherBags/Nodes/Color/ColorInputRow.cs
new file mode 100644
index 0000000..5263b08
--- /dev/null
+++ b/AetherBags/Nodes/Color/ColorInputRow.cs
@@ -0,0 +1,92 @@
+using System;
+using System.Numerics;
+using KamiToolKit.Nodes;
+using KamiToolKit.Premade.Addons;
+
+namespace AetherBags.Nodes.Color;
+
+public class ColorInputRow : HorizontalListNode
+{
+ private readonly GridNode _gridNode;
+ private ColorPickerAddon? _colorPickerAddon;
+ private readonly LabelTextNode _labelTextNode;
+ private ColorPreviewButtonNode _colorPreview;
+ private Vector4 _initialColor;
+
+ public ColorInputRow()
+ {
+ InitializeColorPicker();
+
+ _initialColor = CurrentColor;
+
+ _colorPreview = new ColorPreviewButtonNode
+ {
+ Size = new Vector2(28),
+ Color = CurrentColor,
+ OnClick = () =>
+ {
+ _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;
}