Fix move item
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AAgentSatisfactionSupply_002Ecs_002Fl_003AC_0021_003FUsers_003FJeffro_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fb2cd0663609440e590f52980cafc1ba3822648_003F28_003Ffa48b62e_003FAgentSatisfactionSupply_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AAgentSatisfactionSupply_002Ecs_002Fl_003AC_0021_003FUsers_003FJeffro_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fb2cd0663609440e590f52980cafc1ba3822648_003F28_003Ffa48b62e_003FAgentSatisfactionSupply_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AAtkValue_002Ecs_002Fl_003AC_0021_003FUsers_003FJeffro_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FSourcesCache_003F1b966bf9f0d5b3eb39a7ee3ff6ab5c83f5bea8a841eafd7c8a1e55532d2d952_003FAtkValue_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ACurrencyManager_002Ecs_002Fl_003AC_0021_003FUsers_003FJeffro_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fe66db7cd515142b9bbfb1b4e18f82ace825448_003Ffc_003F78df30c7_003FCurrencyManager_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ACurrencyManager_002Ecs_002Fl_003AC_0021_003FUsers_003FJeffro_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fe66db7cd515142b9bbfb1b4e18f82ace825448_003Ffc_003F78df30c7_003FCurrencyManager_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AInventoryManager_002Ecs_002Fl_003AC_0021_003FUsers_003FJeffro_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FSourcesCache_003F7d322ffbe41aca452171c1858ac4d72a967922191dfb8ada66667df5fd58b_003FInventoryManager_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AInventoryManager_002Ecs_002Fl_003AC_0021_003FUsers_003FJeffro_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FSourcesCache_003F7d322ffbe41aca452171c1858ac4d72a967922191dfb8ada66667df5fd58b_003FInventoryManager_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AItem_002Eg_002Ecs_002Fl_003AC_0021_003FUsers_003FJeffro_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FSourcesCache_003F8ec7cc8a18dbb6a6f3c21f8adcb4e2661dc7979_003FItem_002Eg_002Ecs/@EntryIndexedValue">ForceIncluded</s:String></wpf:ResourceDictionary>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AItem_002Eg_002Ecs_002Fl_003AC_0021_003FUsers_003FJeffro_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FSourcesCache_003F8ec7cc8a18dbb6a6f3c21f8adcb4e2661dc7979_003FItem_002Eg_002Ecs/@EntryIndexedValue">ForceIncluded</s:String></wpf:ResourceDictionary>
|
||||||
@@ -85,14 +85,88 @@ public static unsafe class InventoryTypeExtensions
|
|||||||
InventoryType.SaddleBag2 => ItemOrderModule.Instance()->SaddleBagSorter,
|
InventoryType.SaddleBag2 => ItemOrderModule.Instance()->SaddleBagSorter,
|
||||||
InventoryType.PremiumSaddleBag1 => ItemOrderModule.Instance()->PremiumSaddleBagSorter,
|
InventoryType.PremiumSaddleBag1 => ItemOrderModule.Instance()->PremiumSaddleBagSorter,
|
||||||
InventoryType.PremiumSaddleBag2 => ItemOrderModule.Instance()->PremiumSaddleBagSorter,
|
InventoryType.PremiumSaddleBag2 => ItemOrderModule.Instance()->PremiumSaddleBagSorter,
|
||||||
_ => throw new Exception($"Type Not Implemented: {inventoryType}"),
|
_ => null,
|
||||||
};
|
};
|
||||||
|
|
||||||
public int GetInventoryStartIndex => inventoryType switch {
|
public int GetInventoryStartIndex => inventoryType switch {
|
||||||
InventoryType.Inventory2 => inventoryType.GetInventorySorter->ItemsPerPage,
|
InventoryType.Inventory2 => inventoryType.GetInventorySorter->ItemsPerPage,
|
||||||
InventoryType.Inventory3 => inventoryType.GetInventorySorter->ItemsPerPage * 2,
|
InventoryType.Inventory3 => inventoryType.GetInventorySorter->ItemsPerPage * 2,
|
||||||
InventoryType.Inventory4 => inventoryType.GetInventorySorter->ItemsPerPage * 3,
|
InventoryType.Inventory4 => inventoryType.GetInventorySorter->ItemsPerPage * 3,
|
||||||
|
InventoryType.SaddleBag2 => inventoryType.GetInventorySorter->ItemsPerPage,
|
||||||
|
InventoryType.PremiumSaddleBag2 => inventoryType.GetInventorySorter->ItemsPerPage,
|
||||||
_ => 0,
|
_ => 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public bool IsMainInventory => inventoryType is
|
||||||
|
InventoryType.Inventory1 or
|
||||||
|
InventoryType.Inventory2 or
|
||||||
|
InventoryType.Inventory3 or
|
||||||
|
InventoryType.Inventory4;
|
||||||
|
|
||||||
|
public bool IsSaddleBag => inventoryType is
|
||||||
|
InventoryType.SaddleBag1 or
|
||||||
|
InventoryType.SaddleBag2 or
|
||||||
|
InventoryType.PremiumSaddleBag1 or
|
||||||
|
InventoryType.PremiumSaddleBag2;
|
||||||
|
|
||||||
|
public bool IsArmory => inventoryType is
|
||||||
|
InventoryType.ArmoryMainHand or
|
||||||
|
InventoryType.ArmoryHead or
|
||||||
|
InventoryType.ArmoryBody or
|
||||||
|
InventoryType.ArmoryHands or
|
||||||
|
InventoryType.ArmoryLegs or
|
||||||
|
InventoryType.ArmoryFeets or
|
||||||
|
InventoryType.ArmoryOffHand or
|
||||||
|
InventoryType.ArmoryEar or
|
||||||
|
InventoryType.ArmoryNeck or
|
||||||
|
InventoryType.ArmoryWrist or
|
||||||
|
InventoryType.ArmoryRings or
|
||||||
|
InventoryType.ArmorySoulCrystal;
|
||||||
|
|
||||||
|
public int ContainerGroup => inventoryType switch
|
||||||
|
{
|
||||||
|
_ when inventoryType.IsMainInventory => 1,
|
||||||
|
_ when inventoryType.IsSaddleBag => 2,
|
||||||
|
_ when inventoryType.IsArmory => 3,
|
||||||
|
_ => 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
public bool IsSameContainerGroup(InventoryType other)
|
||||||
|
=> inventoryType.ContainerGroup == other.ContainerGroup;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Resolves the real container and slot for this inventory type using ItemOrderModule.
|
||||||
|
/// For sorted inventories, the visual slot differs from the actual storage slot.
|
||||||
|
/// </summary>
|
||||||
|
public (InventoryType Container, ushort Slot) GetRealItemLocation(int visualSlot)
|
||||||
|
{
|
||||||
|
var sorter = inventoryType.GetInventorySorter;
|
||||||
|
if (sorter == null)
|
||||||
|
return (inventoryType, (ushort)visualSlot);
|
||||||
|
|
||||||
|
int startIndex = inventoryType.GetInventoryStartIndex;
|
||||||
|
int sorterIndex = startIndex + visualSlot;
|
||||||
|
|
||||||
|
if (sorterIndex < 0 || sorterIndex >= sorter->Items.LongCount)
|
||||||
|
return (inventoryType, (ushort)visualSlot);
|
||||||
|
|
||||||
|
var entry = sorter->Items[sorterIndex].Value;
|
||||||
|
if (entry == null)
|
||||||
|
return (inventoryType, (ushort)visualSlot);
|
||||||
|
|
||||||
|
InventoryType baseType = inventoryType switch
|
||||||
|
{
|
||||||
|
_ when inventoryType.IsMainInventory => InventoryType.Inventory1,
|
||||||
|
_ when inventoryType.IsSaddleBag => inventoryType is InventoryType. SaddleBag1 or InventoryType.SaddleBag2
|
||||||
|
? InventoryType. SaddleBag1
|
||||||
|
: InventoryType.PremiumSaddleBag1,
|
||||||
|
_ => inventoryType,
|
||||||
|
};
|
||||||
|
|
||||||
|
InventoryType realContainer = baseType + entry->Page;
|
||||||
|
ushort realSlot = entry->Slot;
|
||||||
|
|
||||||
|
return (realContainer, realSlot);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
using AetherBags. Extensions;
|
||||||
|
using FFXIVClientStructs.FFXIV.Client.Game;
|
||||||
|
using FFXIVClientStructs.FFXIV.Client.UI;
|
||||||
|
using FFXIVClientStructs.FFXIV.Component. GUI;
|
||||||
|
using ValueType = FFXIVClientStructs. FFXIV. Component.GUI.ValueType;
|
||||||
|
|
||||||
|
namespace AetherBags. Helpers;
|
||||||
|
|
||||||
|
public static unsafe class InventoryMoveHelper
|
||||||
|
{
|
||||||
|
public static void MoveItem(InventoryType sourceContainer, ushort sourceSlot, InventoryType destContainer, ushort destSlot)
|
||||||
|
{
|
||||||
|
bool isCrossContainerMove = ! sourceContainer.IsSameContainerGroup(destContainer);
|
||||||
|
|
||||||
|
if (isCrossContainerMove)
|
||||||
|
{
|
||||||
|
MoveItemViaAgent(sourceContainer, sourceSlot, destContainer, destSlot);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
InventoryManager.Instance()->MoveItemSlot(sourceContainer, sourceSlot, destContainer, destSlot, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void MoveItemViaAgent(InventoryType sourceInventory, ushort sourceSlot, InventoryType destInventory, ushort destSlot)
|
||||||
|
{
|
||||||
|
uint sourceContainerId = sourceInventory.AgentItemContainerId;
|
||||||
|
uint destContainerId = destInventory.AgentItemContainerId;
|
||||||
|
|
||||||
|
if (sourceContainerId == 0 || destContainerId == 0)
|
||||||
|
{
|
||||||
|
Services.Logger.Warning($"[MoveItemViaAgent] Invalid container IDs: src={sourceContainerId}, dst={destContainerId}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Services.Logger.Debug($"[MoveItemViaAgent] {sourceContainerId}:{sourceSlot} -> {destContainerId}:{destSlot}");
|
||||||
|
|
||||||
|
var atkValues = stackalloc AtkValue[4];
|
||||||
|
for (var i = 0; i < 4; i++)
|
||||||
|
atkValues[i]. Type = ValueType.UInt;
|
||||||
|
|
||||||
|
atkValues[0].SetUInt(sourceContainerId);
|
||||||
|
atkValues[1].SetUInt(sourceSlot);
|
||||||
|
atkValues[2].SetUInt(destContainerId);
|
||||||
|
atkValues[3].SetUInt(destSlot);
|
||||||
|
|
||||||
|
var retVal = stackalloc AtkValue[1];
|
||||||
|
|
||||||
|
RaptureAtkModule* atkModule = RaptureAtkModule.Instance();
|
||||||
|
atkModule->HandleItemMove(retVal, atkValues, 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,16 +1,16 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
using AetherBags.Extensions;
|
||||||
|
using AetherBags.Helpers;
|
||||||
using AetherBags.Inventory;
|
using AetherBags.Inventory;
|
||||||
using AetherBags.Nodes.Layout;
|
using AetherBags.Nodes.Layout;
|
||||||
using FFXIVClientStructs.FFXIV.Client.Game;
|
using FFXIVClientStructs.FFXIV.Client.Game;
|
||||||
using FFXIVClientStructs.FFXIV.Client.UI;
|
|
||||||
using FFXIVClientStructs.FFXIV.Client.UI.Misc;
|
|
||||||
using FFXIVClientStructs.FFXIV.Component.GUI;
|
using FFXIVClientStructs.FFXIV.Component.GUI;
|
||||||
using KamiToolKit.Classes;
|
using KamiToolKit.Classes;
|
||||||
using KamiToolKit.Nodes;
|
using KamiToolKit.Nodes;
|
||||||
|
|
||||||
// TODO: Switch back to CS version when Dalamud Updated
|
// TODO: Switch back to CS version when Dalamud Updated
|
||||||
using DragDropFixedNode = AetherBags.Nodes.DragDropNode;
|
using DragDropFixedNode = AetherBags.Nodes.DragDropNode;
|
||||||
using ValueType = FFXIVClientStructs.FFXIV.Component.GUI.ValueType;
|
|
||||||
|
|
||||||
namespace AetherBags.Nodes.Inventory;
|
namespace AetherBags.Nodes.Inventory;
|
||||||
|
|
||||||
@@ -23,14 +23,11 @@ public class InventoryCategoryNode : SimpleComponentNode
|
|||||||
private const float HeaderHeight = 16;
|
private const float HeaderHeight = 16;
|
||||||
private const float MinWidth = 40;
|
private const float MinWidth = 40;
|
||||||
|
|
||||||
private float? _fixedWidth;
|
private float? _fixedWidth;
|
||||||
|
|
||||||
private int _hoverRefs;
|
private int _hoverRefs;
|
||||||
private bool _headerSuppressed;
|
private bool _headerSuppressed;
|
||||||
private bool _headerExpanded;
|
private bool _headerExpanded;
|
||||||
|
|
||||||
private float _baseHeaderWidth = 96f;
|
private float _baseHeaderWidth = 96f;
|
||||||
|
|
||||||
private string _fullHeaderText = string.Empty;
|
private string _fullHeaderText = string.Empty;
|
||||||
|
|
||||||
public event Action<InventoryCategoryNode, bool>? HeaderHoverChanged;
|
public event Action<InventoryCategoryNode, bool>? HeaderHoverChanged;
|
||||||
@@ -77,7 +74,6 @@ public class InventoryCategoryNode : SimpleComponentNode
|
|||||||
|
|
||||||
_categoryNameTextNode.String = _fullHeaderText;
|
_categoryNameTextNode.String = _fullHeaderText;
|
||||||
_categoryNameTextNode.TextColor = value.Category.Color;
|
_categoryNameTextNode.TextColor = value.Category.Color;
|
||||||
|
|
||||||
_categoryNameTextNode.TooltipString = value.Category.Description;
|
_categoryNameTextNode.TooltipString = value.Category.Description;
|
||||||
|
|
||||||
UpdateItemGrid();
|
UpdateItemGrid();
|
||||||
@@ -96,7 +92,7 @@ public class InventoryCategoryNode : SimpleComponentNode
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public float? FixedWidth
|
public float? FixedWidth
|
||||||
{
|
{
|
||||||
get => _fixedWidth;
|
get => _fixedWidth;
|
||||||
set
|
set
|
||||||
@@ -114,7 +110,6 @@ public class InventoryCategoryNode : SimpleComponentNode
|
|||||||
|
|
||||||
_headerExpanded = true;
|
_headerExpanded = true;
|
||||||
ApplyHeaderVisualStateAndSize();
|
ApplyHeaderVisualStateAndSize();
|
||||||
|
|
||||||
HeaderHoverChanged?.Invoke(this, true);
|
HeaderHoverChanged?.Invoke(this, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,7 +122,6 @@ public class InventoryCategoryNode : SimpleComponentNode
|
|||||||
|
|
||||||
_headerExpanded = false;
|
_headerExpanded = false;
|
||||||
ApplyHeaderVisualStateAndSize();
|
ApplyHeaderVisualStateAndSize();
|
||||||
|
|
||||||
HeaderHoverChanged?.Invoke(this, false);
|
HeaderHoverChanged?.Invoke(this, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,12 +134,11 @@ public class InventoryCategoryNode : SimpleComponentNode
|
|||||||
|
|
||||||
private void ApplyHeaderVisualStateAndSize()
|
private void ApplyHeaderVisualStateAndSize()
|
||||||
{
|
{
|
||||||
_categoryNameTextNode.IsVisible = !_headerSuppressed;
|
_categoryNameTextNode.IsVisible = ! _headerSuppressed;
|
||||||
if (_headerSuppressed)
|
if (_headerSuppressed)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var flags = _categoryNameTextNode.TextFlags;
|
var flags = _categoryNameTextNode.TextFlags;
|
||||||
|
|
||||||
flags &= ~(TextFlags.WordWrap | TextFlags.MultiLine);
|
flags &= ~(TextFlags.WordWrap | TextFlags.MultiLine);
|
||||||
|
|
||||||
if (_headerExpanded)
|
if (_headerExpanded)
|
||||||
@@ -153,7 +146,7 @@ public class InventoryCategoryNode : SimpleComponentNode
|
|||||||
flags &= ~(TextFlags.OverflowHidden | TextFlags.Ellipsis);
|
flags &= ~(TextFlags.OverflowHidden | TextFlags.Ellipsis);
|
||||||
_categoryNameTextNode.TextFlags = flags;
|
_categoryNameTextNode.TextFlags = flags;
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(_fullHeaderText))
|
if (! string.IsNullOrEmpty(_fullHeaderText))
|
||||||
_categoryNameTextNode.String = _fullHeaderText;
|
_categoryNameTextNode.String = _fullHeaderText;
|
||||||
|
|
||||||
Vector2 drawSize = _categoryNameTextNode.GetTextDrawSize();
|
Vector2 drawSize = _categoryNameTextNode.GetTextDrawSize();
|
||||||
@@ -167,7 +160,7 @@ public class InventoryCategoryNode : SimpleComponentNode
|
|||||||
if (!string.IsNullOrEmpty(_fullHeaderText))
|
if (!string.IsNullOrEmpty(_fullHeaderText))
|
||||||
_categoryNameTextNode.String = _fullHeaderText;
|
_categoryNameTextNode.String = _fullHeaderText;
|
||||||
|
|
||||||
flags |= (TextFlags.OverflowHidden | TextFlags.Ellipsis);
|
flags |= TextFlags.OverflowHidden | TextFlags.Ellipsis;
|
||||||
_categoryNameTextNode.TextFlags = flags;
|
_categoryNameTextNode.TextFlags = flags;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -179,58 +172,30 @@ public class InventoryCategoryNode : SimpleComponentNode
|
|||||||
if (itemCount == 0)
|
if (itemCount == 0)
|
||||||
{
|
{
|
||||||
float width = _fixedWidth ?? MinWidth;
|
float width = _fixedWidth ?? MinWidth;
|
||||||
|
|
||||||
Size = new Vector2(width, HeaderHeight);
|
Size = new Vector2(width, HeaderHeight);
|
||||||
|
|
||||||
_baseHeaderWidth = width;
|
_baseHeaderWidth = width;
|
||||||
|
|
||||||
_itemGridNode.Position = new Vector2(0, HeaderHeight);
|
_itemGridNode.Position = new Vector2(0, HeaderHeight);
|
||||||
_itemGridNode.Size = new Vector2(width, 0);
|
_itemGridNode.Size = new Vector2(width, 0);
|
||||||
|
|
||||||
ApplyHeaderVisualStateAndSize();
|
ApplyHeaderVisualStateAndSize();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int itemsPerLine = _itemGridNode.ItemsPerLine;
|
int itemsPerLine = Math.Max(1, _itemGridNode.ItemsPerLine);
|
||||||
if (itemsPerLine < 1) itemsPerLine = 1;
|
|
||||||
|
|
||||||
int rows = (itemCount + itemsPerLine - 1) / itemsPerLine;
|
int rows = (itemCount + itemsPerLine - 1) / itemsPerLine;
|
||||||
int actualColumns = Math.Min(itemCount, itemsPerLine);
|
int actualColumns = Math.Min(itemCount, itemsPerLine);
|
||||||
|
|
||||||
float cellW, cellH;
|
float cellW = _itemGridNode.Nodes.Count > 0 ? _itemGridNode.Nodes[0].Width : FallbackItemSize;
|
||||||
if (_itemGridNode.Nodes.Count > 0)
|
float cellH = _itemGridNode.Nodes.Count > 0 ? _itemGridNode.Nodes[0].Height : FallbackItemSize;
|
||||||
{
|
|
||||||
var firstChild = _itemGridNode.Nodes[0];
|
|
||||||
cellW = firstChild.Width;
|
|
||||||
cellH = firstChild.Height;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cellW = FallbackItemSize;
|
|
||||||
cellH = FallbackItemSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
float hPad = _itemGridNode.HorizontalPadding;
|
float hPad = _itemGridNode.HorizontalPadding;
|
||||||
float vPad = _itemGridNode.VerticalPadding;
|
float vPad = _itemGridNode.VerticalPadding;
|
||||||
|
|
||||||
float calculatedWidth;
|
float calculatedWidth = _fixedWidth ?? Math.Max(MinWidth, actualColumns * cellW + (actualColumns - 1) * hPad);
|
||||||
if (_fixedWidth.HasValue)
|
|
||||||
{
|
|
||||||
calculatedWidth = _fixedWidth.Value;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
calculatedWidth = actualColumns * cellW + (actualColumns - 1) * hPad;
|
|
||||||
if (calculatedWidth < MinWidth) calculatedWidth = MinWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
float height = HeaderHeight + rows * cellH + (rows - 1) * vPad;
|
float height = HeaderHeight + rows * cellH + (rows - 1) * vPad;
|
||||||
|
|
||||||
Size = new Vector2(calculatedWidth, height);
|
Size = new Vector2(calculatedWidth, height);
|
||||||
|
|
||||||
_itemGridNode.Position = new Vector2(0, HeaderHeight);
|
_itemGridNode.Position = new Vector2(0, HeaderHeight);
|
||||||
_itemGridNode.Size = new Vector2(calculatedWidth, height - HeaderHeight);
|
_itemGridNode.Size = new Vector2(calculatedWidth, height - HeaderHeight);
|
||||||
|
|
||||||
_baseHeaderWidth = calculatedWidth;
|
_baseHeaderWidth = calculatedWidth;
|
||||||
|
|
||||||
ApplyHeaderVisualStateAndSize();
|
ApplyHeaderVisualStateAndSize();
|
||||||
@@ -248,7 +213,7 @@ public class InventoryCategoryNode : SimpleComponentNode
|
|||||||
{
|
{
|
||||||
InventoryItem item = data.Item;
|
InventoryItem item = data.Item;
|
||||||
|
|
||||||
var node = new InventoryDragDropNode
|
return new InventoryDragDropNode
|
||||||
{
|
{
|
||||||
Size = new Vector2(42, 46),
|
Size = new Vector2(42, 46),
|
||||||
IsVisible = true,
|
IsVisible = true,
|
||||||
@@ -258,14 +223,11 @@ public class InventoryCategoryNode : SimpleComponentNode
|
|||||||
Payload = new DragDropPayload
|
Payload = new DragDropPayload
|
||||||
{
|
{
|
||||||
Type = DragDropType.Inventory_Item,
|
Type = DragDropType.Inventory_Item,
|
||||||
Int1 = (int)item.GetInventoryType(),
|
Int1 = (int)item.Container,
|
||||||
Int2 = item.Slot,
|
Int2 = item.Slot,
|
||||||
},
|
},
|
||||||
IsClickable = true,
|
IsClickable = true,
|
||||||
OnEnd = _ =>
|
OnEnd = _ => System.AddonInventoryWindow.ManualInventoryRefresh(),
|
||||||
{
|
|
||||||
System.AddonInventoryWindow.ManualInventoryRefresh();
|
|
||||||
},
|
|
||||||
OnPayloadAccepted = (n, p) => OnPayloadAccepted(n, p, data),
|
OnPayloadAccepted = (n, p) => OnPayloadAccepted(n, p, data),
|
||||||
OnRollOver = n =>
|
OnRollOver = n =>
|
||||||
{
|
{
|
||||||
@@ -277,54 +239,54 @@ public class InventoryCategoryNode : SimpleComponentNode
|
|||||||
EndHeaderHover();
|
EndHeaderHover();
|
||||||
n.HideTooltip();
|
n.HideTooltip();
|
||||||
},
|
},
|
||||||
|
|
||||||
ItemInfo = data
|
ItemInfo = data
|
||||||
};
|
};
|
||||||
|
|
||||||
return node;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private unsafe void OnPayloadAccepted(DragDropNode node, DragDropPayload payload, ItemInfo itemInfo)
|
private void OnPayloadAccepted(DragDropNode node, DragDropPayload payload, ItemInfo targetItemInfo)
|
||||||
{
|
{
|
||||||
if (payload.Type != DragDropType.Item) return;
|
if (payload.Type != DragDropType.Item && payload.Type != DragDropType.Inventory_Item)
|
||||||
InventoryItem item = itemInfo.Item;
|
return;
|
||||||
Services.Logger.Debug($"Inventory DragDropNode Payload Accepted: {payload.Type} Int1: {payload.Int1} Int2: {payload.Int2} ReferenceIndex: {payload.ReferenceIndex}");
|
|
||||||
InventoryType inventoryType = InventoryType.GetInventoryTypeFromContainerId(payload.Int1);
|
|
||||||
ushort sourceSlot = (ushort)payload.Int2;
|
|
||||||
ItemOrderModuleSorterItemEntry* itemEntry = item.GetItemOrderData();
|
|
||||||
Services.Logger.Debug($"{item.Slot} vs {item.GetSlot()}: entry: {itemEntry->Slot}");
|
|
||||||
Services.Logger.Info($"[OnPayload] Moving {inventoryType}@{sourceSlot} -> {item.Container}@{item.Slot} -> {item.Name.ExtractText()}");
|
|
||||||
InventoryManager.Instance()->MoveItemSlot(inventoryType, sourceSlot, item.Container, item.GetSlot(), true);
|
|
||||||
|
|
||||||
|
var (sourceContainer, sourceSlot) = ResolveSourceFromPayload(payload);
|
||||||
|
|
||||||
// System.AddonInventoryWindow.ManualInventoryRefresh();
|
if (sourceContainer == 0)
|
||||||
|
{
|
||||||
// Should work for swapping item but need a fake empty slot to put new items in probably.
|
Services.Logger.Warning($"[OnPayload] Could not resolve source from payload");
|
||||||
// Services.Logger.Debug($"Moving Item from {inventoryType} Slot {sourceSlot} to {itemInfo.Item.Container} Slot {itemInfo.Item.GetSlot()}");
|
return;
|
||||||
//MoveItem(inventoryType, sourceSlot, itemInfo.Item.Container, itemInfo.Item.GetSlot());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Possibly still use this
|
|
||||||
private unsafe void MoveItem(InventoryType sourceInventory, uint sourceSlot, InventoryType destinationInventory, uint destinationSlot)
|
|
||||||
{
|
|
||||||
var sourceContainerId = sourceInventory.AgentItemContainerId;
|
|
||||||
var destinationContainerId = destinationInventory.AgentItemContainerId;
|
|
||||||
|
|
||||||
if (sourceContainerId != 0 && destinationContainerId != 0) {
|
|
||||||
var atkValues = stackalloc AtkValue[4];
|
|
||||||
for (var i = 0; i < 4; i++) atkValues[i].Type = ValueType.UInt;
|
|
||||||
|
|
||||||
atkValues[0].UInt = sourceContainerId;
|
|
||||||
atkValues[1].UInt = sourceSlot;
|
|
||||||
atkValues[2].UInt = destinationContainerId;
|
|
||||||
atkValues[3].UInt = destinationSlot;
|
|
||||||
|
|
||||||
var retVal = stackalloc AtkValue[1];
|
|
||||||
|
|
||||||
RaptureAtkModule* atkModule = RaptureAtkModule.Instance();
|
|
||||||
// (RaptureAtkModule* a1, void* outValue, AtkValue* atkValues);
|
|
||||||
// (AtkValue* returnValue, AtkValue* values, uint valueCount)
|
|
||||||
atkModule->HandleItemMove(retVal, atkValues, 4);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
InventoryType targetContainer = targetItemInfo.Item.Container;
|
||||||
|
ushort targetSlot = (ushort)targetItemInfo.Item.Slot;
|
||||||
|
|
||||||
|
Services.Logger.Info($"[OnPayload] Moving {sourceContainer}@{sourceSlot} -> {targetContainer}@{targetSlot}");
|
||||||
|
|
||||||
|
InventoryMoveHelper.MoveItem(sourceContainer, sourceSlot, targetContainer, targetSlot);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
private static (InventoryType Container, ushort Slot) ResolveSourceFromPayload(DragDropPayload payload)
|
||||||
|
{
|
||||||
|
if (payload.Type == DragDropType.Inventory_Item)
|
||||||
|
{
|
||||||
|
return ((InventoryType)payload.Int1, (ushort)payload.Int2);
|
||||||
|
}
|
||||||
|
|
||||||
|
int containerId = payload.Int1;
|
||||||
|
int slotIndex = payload.Int2;
|
||||||
|
|
||||||
|
InventoryType sourceContainer = InventoryType.GetInventoryTypeFromContainerId(containerId);
|
||||||
|
|
||||||
|
if (sourceContainer == 0)
|
||||||
|
return (0, 0);
|
||||||
|
|
||||||
|
// For main inventory, resolve the real slot via ItemOrderModule
|
||||||
|
if (sourceContainer.IsMainInventory)
|
||||||
|
{
|
||||||
|
var (realContainer, realSlot) = sourceContainer.GetRealItemLocation(slotIndex);
|
||||||
|
return (realContainer, realSlot);
|
||||||
|
}
|
||||||
|
|
||||||
|
// For other containers (saddlebags, armory, etc.), use the slot directly
|
||||||
|
return (sourceContainer, (ushort)slotIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user