Use InventoryScrollingNode, fixes #12

This commit is contained in:
Zeffuro
2026-02-20 22:18:15 +01:00
parent 267c811def
commit eb6e534630
5 changed files with 118 additions and 6 deletions
+3 -3
View File
@@ -25,7 +25,7 @@ public unsafe class AddonInventoryWindow : InventoryAddonBase
{ {
InitializeBackgroundDropTarget(); InitializeBackgroundDropTarget();
ScrollableCategories = new ScrollingAreaNode<WrappingGridNode<InventoryCategoryNodeBase>> ScrollableCategories = new InventoryScrollingAreaNode<WrappingGridNode<InventoryCategoryNodeBase>>
{ {
Position = ContentStartPosition, Position = ContentStartPosition,
Size = ContentSize, Size = ContentSize,
@@ -179,6 +179,8 @@ public unsafe class AddonInventoryWindow : InventoryAddonBase
protected override void OnFinalize(AtkUnitBase* addon) protected override void OnFinalize(AtkUnitBase* addon)
{ {
_lootedCategoryNode?.Dispose();
System.LootedItemsTracker.OnLootedItemsChanged -= OnLootedItemsChanged; System.LootedItemsTracker.OnLootedItemsChanged -= OnLootedItemsChanged;
ref var blockingAddonId = ref AgentInventoryContext.Instance()->BlockingAddonId; ref var blockingAddonId = ref AgentInventoryContext.Instance()->BlockingAddonId;
@@ -189,8 +191,6 @@ public unsafe class AddonInventoryWindow : InventoryAddonBase
addon->UnsubscribeAtkArrayData(1, (int)NumberArrayType.Inventory); addon->UnsubscribeAtkArrayData(1, (int)NumberArrayType.Inventory);
_lootedCategoryNode?.Dispose();
IsSetupComplete = false; IsSetupComplete = false;
base.OnFinalize(addon); base.OnFinalize(addon);
} }
+1 -1
View File
@@ -38,7 +38,7 @@ public unsafe class AddonRetainerWindow : InventoryAddonBase
WindowNode?.AddColor = _tintColor; WindowNode?.AddColor = _tintColor;
ScrollableCategories = new ScrollingAreaNode<WrappingGridNode<InventoryCategoryNodeBase>> ScrollableCategories = new InventoryScrollingAreaNode<WrappingGridNode<InventoryCategoryNodeBase>>
{ {
Position = ContentStartPosition, Position = ContentStartPosition,
Size = ContentSize, Size = ContentSize,
+1 -1
View File
@@ -31,7 +31,7 @@ public unsafe class AddonSaddleBagWindow : InventoryAddonBase
WindowNode?.AddColor = _tintColor; WindowNode?.AddColor = _tintColor;
ScrollableCategories = new ScrollingAreaNode<WrappingGridNode<InventoryCategoryNodeBase>> ScrollableCategories = new InventoryScrollingAreaNode<WrappingGridNode<InventoryCategoryNodeBase>>
{ {
Position = ContentStartPosition, Position = ContentStartPosition,
Size = ContentSize, Size = ContentSize,
+1 -1
View File
@@ -29,7 +29,7 @@ public abstract unsafe class InventoryAddonBase : NativeAddon, IInventoryWindow
protected readonly HashSet<InventoryCategoryNode> HoverSubscribed = new(); protected readonly HashSet<InventoryCategoryNode> HoverSubscribed = new();
protected DragDropNode BackgroundDropTarget = null!; protected DragDropNode BackgroundDropTarget = null!;
protected ScrollingAreaNode<WrappingGridNode<InventoryCategoryNodeBase>> ScrollableCategories = null!; protected InventoryScrollingAreaNode<WrappingGridNode<InventoryCategoryNodeBase>> ScrollableCategories = null!;
protected WrappingGridNode<InventoryCategoryNodeBase> CategoriesNode = null!; protected WrappingGridNode<InventoryCategoryNodeBase> CategoriesNode = null!;
protected TextInputWithButtonNode SearchInputNode = null!; protected TextInputWithButtonNode SearchInputNode = null!;
protected InventoryFooterNode FooterNode = null!; protected InventoryFooterNode FooterNode = null!;
@@ -0,0 +1,112 @@
using System.Linq;
using System.Numerics;
using FFXIVClientStructs.FFXIV.Component.GUI;
using KamiToolKit;
using KamiToolKit.Nodes;
namespace AetherBags.Nodes.Layout;
/// <summary>
/// A copy of KamiToolKit's ScrollingAreaNode with ContentAreaClipNode changed from
/// SimpleComponentNode to ResNode, to prevent the native AtkDragDropManager from
/// treating the clip boundary as a component node (which blocks drag-to-hotbar).
/// According to Kami it is possible that this may or may not leak.
/// We will eventually change this later.
/// </summary>
public unsafe class InventoryScrollingAreaNode<T> : SimpleComponentNode where T : NodeBase, new() {
public readonly ResNode ContentAreaClipNode;
public readonly T ContentAreaNode;
public readonly ScrollBarNode ScrollBarNode;
public readonly CollisionNode ScrollingCollisionNode;
public InventoryScrollingAreaNode() {
ScrollingCollisionNode = new CollisionNode();
ScrollingCollisionNode.AttachNode(this);
ContentAreaClipNode = new ResNode {
NodeFlags = NodeFlags.Clip | NodeFlags.EmitsEvents | NodeFlags.Visible,
};
ContentAreaClipNode.AttachNode(this);
ContentAreaNode = new T();
ContentAreaNode.AttachNode(ContentAreaClipNode);
ScrollBarNode = new ScrollBarNode {
ContentNode = ContentAreaNode,
ContentCollisionNode = ScrollingCollisionNode,
HideWhenDisabled = true,
};
ScrollBarNode.AttachNode(this);
AtkResNode* clipNode = ContentAreaClipNode;
AtkResNode* contentNode = ContentAreaNode;
clipNode->AtkEventManager.RegisterEvent(
AtkEventType.MouseWheel,
5,
null,
ScrollingCollisionNode,
ScrollBarNode,
false);
ScrollingCollisionNode.Node->AtkEventManager.RegisterEvent(
AtkEventType.MouseWheel,
5,
null,
ScrollingCollisionNode,
ScrollBarNode,
false);
contentNode->AtkEventManager.RegisterEvent(
AtkEventType.MouseWheel,
5,
null,
ScrollingCollisionNode,
ScrollBarNode,
false);
}
public virtual T ContentNode => ContentAreaNode;
public int ScrollPosition {
get => ScrollBarNode.ScrollPosition;
set => ScrollBarNode.ScrollPosition = value;
}
public int ScrollSpeed {
get => ScrollBarNode.ScrollSpeed;
set => ScrollBarNode.ScrollSpeed = value;
}
public required float ContentHeight {
get => ContentAreaNode.Height;
set {
ContentAreaNode.Height = value;
ScrollBarNode.UpdateScrollParams();
}
}
public bool AutoHideScrollBar {
get => ScrollBarNode.HideWhenDisabled;
set => ScrollBarNode.HideWhenDisabled = value;
}
protected override void OnSizeChanged() {
base.OnSizeChanged();
ContentAreaNode.Width = Width - 16.0f;
ScrollingCollisionNode.Size = new Vector2(Width - 16.0f, Height);
ContentAreaClipNode.Size = new Vector2(Width - 16.0f, Height);
ScrollBarNode.Size = new Vector2(8.0f, Height);
ScrollBarNode.UpdateScrollParams();
ScrollBarNode.X = Width - 8.0f;
}
public void FitToContentHeight() {
if (ContentNode is LayoutListNode layoutNode) {
ContentHeight = layoutNode.Nodes.Sum(node => node.IsVisible ? node.Height + layoutNode.ItemSpacing : 0.0f) + layoutNode.FirstItemSpacing;
}
}
}