Dalamud/Dalamud/Interface/Internal/Windows/Data/Widgets/InventoryWidget.cs
Haselnussbomber c93f04f0e4
Code cleanup (#2439)
* Use new Lock objects

* Fix CA1513: Use ObjectDisposedException.ThrowIf

* Fix CA1860: Avoid using 'Enumerable.Any()' extension method

* Fix IDE0028: Use collection initializers or expressions

* Fix CA2263: Prefer generic overload when type is known

* Fix CA1862: Use the 'StringComparison' method overloads to perform case-insensitive string comparisons

* Fix IDE0270: Null check can be simplified

* Fix IDE0280: Use 'nameof'

* Fix IDE0009: Add '.this'

* Fix IDE0007: Use 'var' instead of explicit type

* Fix IDE0062: Make local function static

* Fix CA1859: Use concrete types when possible for improved performance

* Fix IDE0066: Use switch expression

Only applied to where it doesn't look horrendous.

* Use is over switch

* Fix CA1847: Use String.Contains(char) instead of String.Contains(string) with single characters

* Fix SYSLIB1045: Use 'GeneratedRegexAttribute' to generate the regular expression implementation at compile-time.

* Fix CA1866: Use 'string.EndsWith(char)' instead of 'string.EndsWith(string)' when you have a string with a single char

* Fix IDE0057: Substring can be simplified

* Fix IDE0059: Remove unnecessary value assignment

* Fix CA1510: Use ArgumentNullException throw helper

* Fix IDE0300: Use collection expression for array

* Fix IDE0250: Struct can be made 'readonly'

* Fix IDE0018: Inline variable declaration

* Fix CA1850: Prefer static HashData method over ComputeHash

* Fi CA1872: Prefer 'Convert.ToHexString' and 'Convert.ToHexStringLower' over call chains based on 'BitConverter.ToString'

* Update ModuleLog instantiations

* Organize usings
2026-01-06 08:36:55 -08:00

344 lines
13 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System.Buffers.Binary;
using System.Numerics;
using System.Text;
using Dalamud.Bindings.ImGui;
using Dalamud.Data;
using Dalamud.Game.Inventory;
using Dalamud.Interface.Textures;
using Dalamud.Interface.Textures.Internal;
using Dalamud.Interface.Utility;
using Dalamud.Interface.Utility.Raii;
using Dalamud.Utility;
using FFXIVClientStructs.FFXIV.Client.Game;
using Lumina.Excel.Sheets;
namespace Dalamud.Interface.Internal.Windows.Data.Widgets;
/// <summary>
/// Widget for displaying inventory data.
/// </summary>
internal class InventoryWidget : IDataWindowWidget
{
private DataManager dataManager;
private TextureManager textureManager;
private GameInventoryType? selectedInventoryType = GameInventoryType.Inventory1;
/// <inheritdoc/>
public string[]? CommandShortcuts { get; init; } = ["inv", "inventory"];
/// <inheritdoc/>
public string DisplayName { get; init; } = "Inventory";
/// <inheritdoc/>
public bool Ready { get; set; }
/// <inheritdoc/>
public void Load()
{
this.Ready = true;
}
/// <inheritdoc/>
public void Draw()
{
this.dataManager ??= Service<DataManager>.Get();
this.textureManager ??= Service<TextureManager>.Get();
this.DrawInventoryTypeList();
if (this.selectedInventoryType == null)
return;
ImGui.SameLine(0, ImGui.GetStyle().ItemInnerSpacing.X);
this.DrawInventoryType(this.selectedInventoryType.Value);
}
private static string StripSoftHypen(string input)
{
return input.Replace("\u00AD", string.Empty);
}
private unsafe void DrawInventoryTypeList()
{
using var table = ImRaii.Table("InventoryTypeTable"u8, 2, ImGuiTableFlags.RowBg | ImGuiTableFlags.Borders | ImGuiTableFlags.ScrollY | ImGuiTableFlags.NoSavedSettings, new Vector2(300, -1));
if (!table) return;
ImGui.TableSetupColumn("Type"u8);
ImGui.TableSetupColumn("Size"u8, ImGuiTableColumnFlags.WidthFixed, 40);
ImGui.TableSetupScrollFreeze(2, 1);
ImGui.TableHeadersRow();
foreach (var inventoryType in Enum.GetValues<GameInventoryType>())
{
var items = GameInventoryItem.GetReadOnlySpanOfInventory(inventoryType);
using var itemDisabled = ImRaii.Disabled(items.IsEmpty);
ImGui.TableNextRow();
ImGui.TableNextColumn(); // Type
if (ImGui.Selectable(inventoryType.ToString(), this.selectedInventoryType == inventoryType, ImGuiSelectableFlags.SpanAllColumns))
{
this.selectedInventoryType = inventoryType;
}
using (var contextMenu = ImRaii.ContextPopupItem($"##InventoryContext{inventoryType}"))
{
if (contextMenu)
{
if (ImGui.MenuItem("Copy Name"u8))
{
ImGui.SetClipboardText(inventoryType.ToString());
}
if (ImGui.MenuItem("Copy Address"u8))
{
var container = InventoryManager.Instance()->GetInventoryContainer((InventoryType)inventoryType);
ImGui.SetClipboardText($"0x{(nint)container:X}");
}
}
}
ImGui.TableNextColumn(); // Size
ImGui.Text(items.Length.ToString());
}
}
private unsafe void DrawInventoryType(GameInventoryType inventoryType)
{
var items = GameInventoryItem.GetReadOnlySpanOfInventory(inventoryType);
if (items.IsEmpty)
{
ImGui.Text($"{inventoryType} is empty.");
return;
}
using var itemTable = ImRaii.Table("InventoryItemTable"u8, 4, ImGuiTableFlags.RowBg | ImGuiTableFlags.Borders | ImGuiTableFlags.ScrollY | ImGuiTableFlags.NoSavedSettings);
if (!itemTable) return;
ImGui.TableSetupColumn("Slot"u8, ImGuiTableColumnFlags.WidthFixed, 40);
ImGui.TableSetupColumn("ItemId"u8, ImGuiTableColumnFlags.WidthFixed, 70);
ImGui.TableSetupColumn("Quantity"u8, ImGuiTableColumnFlags.WidthFixed, 70);
ImGui.TableSetupColumn("Item"u8);
ImGui.TableSetupScrollFreeze(0, 1);
ImGui.TableHeadersRow();
for (var slotIndex = 0; slotIndex < items.Length; slotIndex++)
{
var item = items[slotIndex];
using var disableditem = ImRaii.Disabled(item.ItemId == 0);
ImGui.TableNextRow();
ImGui.TableNextColumn(); // Slot
ImGui.Text(slotIndex.ToString());
ImGui.TableNextColumn(); // ItemId
ImGuiHelpers.ClickToCopyText(item.ItemId.ToString());
ImGui.TableNextColumn(); // Quantity
ImGuiHelpers.ClickToCopyText(item.Quantity.ToString());
ImGui.TableNextColumn(); // Item
if (item.ItemId != 0 && item.Quantity != 0)
{
var itemName = ItemUtil.GetItemName(item.ItemId).ExtractText();
var iconId = this.GetItemIconId(item.ItemId);
if (this.textureManager.Shared.TryGetFromGameIcon(new GameIconLookup(iconId, item.IsHq), out var tex) && tex.TryGetWrap(out var texture, out _))
{
ImGui.Image(texture.Handle, new Vector2(ImGui.GetTextLineHeight()));
if (ImGui.IsItemHovered())
{
ImGui.SetMouseCursor(ImGuiMouseCursor.Hand);
ImGui.BeginTooltip();
ImGui.Text("Click to copy IconId"u8);
ImGui.Text($"ID: {iconId} Size: {texture.Width}x{texture.Height}");
ImGui.Image(texture.Handle, new(texture.Width, texture.Height));
ImGui.EndTooltip();
}
if (ImGui.IsItemClicked())
ImGui.SetClipboardText(iconId.ToString());
}
ImGui.SameLine();
using var itemNameColor = ImRaii.PushColor(ImGuiCol.Text, this.GetItemRarityColor(item.ItemId));
using var node = ImRaii.TreeNode($"{itemName}###{inventoryType}_{slotIndex}", ImGuiTreeNodeFlags.SpanAvailWidth);
itemNameColor.Dispose();
using (var contextMenu = ImRaii.ContextPopupItem($"{inventoryType}_{slotIndex}_ContextMenu"))
{
if (contextMenu)
{
if (ImGui.MenuItem("Copy Name"u8))
{
ImGui.SetClipboardText(itemName);
}
}
}
if (!node) continue;
using var itemInfoTable = ImRaii.Table($"{inventoryType}_{slotIndex}_Table", 2, ImGuiTableFlags.BordersInner | ImGuiTableFlags.NoSavedSettings);
if (!itemInfoTable) continue;
ImGui.TableSetupColumn("Name"u8, ImGuiTableColumnFlags.WidthFixed, 150);
ImGui.TableSetupColumn("Value"u8);
// ImGui.TableHeadersRow();
static void AddKeyValueRow(string fieldName, string value)
{
ImGui.TableNextRow();
ImGui.TableNextColumn();
ImGui.Text(fieldName);
ImGui.TableNextColumn();
ImGuiHelpers.ClickToCopyText(value);
}
static void AddValueValueRow(string value1, string value2)
{
ImGui.TableNextRow();
ImGui.TableNextColumn();
ImGuiHelpers.ClickToCopyText(value1);
ImGui.TableNextColumn();
ImGuiHelpers.ClickToCopyText(value2);
}
AddKeyValueRow("ItemId", item.ItemId.ToString());
AddKeyValueRow("Quantity", item.Quantity.ToString());
AddKeyValueRow("GlamourId", item.GlamourId.ToString());
if (!ItemUtil.IsEventItem(item.ItemId))
{
AddKeyValueRow(item.IsCollectable ? "Collectability" : "Spiritbond", item.SpiritbondOrCollectability.ToString());
if (item.CrafterContentId != 0)
AddKeyValueRow("CrafterContentId", item.CrafterContentId.ToString());
}
var flagsBuilder = new StringBuilder();
if (item.IsHq)
{
flagsBuilder.Append("IsHq");
}
if (item.IsCompanyCrestApplied)
{
if (flagsBuilder.Length != 0)
flagsBuilder.Append(", ");
flagsBuilder.Append("IsCompanyCrestApplied");
}
if (item.IsRelic)
{
if (flagsBuilder.Length != 0)
flagsBuilder.Append(", ");
flagsBuilder.Append("IsRelic");
}
if (item.IsCollectable)
{
if (flagsBuilder.Length != 0)
flagsBuilder.Append(", ");
flagsBuilder.Append("IsCollectable");
}
if (flagsBuilder.Length == 0)
flagsBuilder.Append("None");
AddKeyValueRow("Flags", flagsBuilder.ToString());
if (ItemUtil.IsNormalItem(item.ItemId) && this.dataManager.Excel.GetSheet<Item>().TryGetRow(item.ItemId, out var itemRow))
{
if (itemRow.DyeCount > 0 && item.Stains.Length > 0)
{
ImGui.TableNextRow();
ImGui.TableNextColumn();
ImGui.Text("Stains"u8);
ImGui.TableNextColumn();
using var stainTable = ImRaii.Table($"{inventoryType}_{slotIndex}_StainTable", 2, ImGuiTableFlags.BordersInner | ImGuiTableFlags.NoSavedSettings);
if (!stainTable) continue;
ImGui.TableSetupColumn("Stain Id"u8, ImGuiTableColumnFlags.WidthFixed, 80);
ImGui.TableSetupColumn("Name"u8);
ImGui.TableHeadersRow();
for (var i = 0; i < itemRow.DyeCount; i++)
{
var stainId = item.Stains[i];
AddValueValueRow(stainId.ToString(), this.GetStainName(stainId));
}
}
if (itemRow.MateriaSlotCount > 0 && item.Materia.Length > 0)
{
ImGui.TableNextRow();
ImGui.TableNextColumn();
ImGui.Text("Materia"u8);
ImGui.TableNextColumn();
using var materiaTable = ImRaii.Table($"{inventoryType}_{slotIndex}_MateriaTable", 2, ImGuiTableFlags.BordersInner | ImGuiTableFlags.NoSavedSettings);
if (!materiaTable) continue;
ImGui.TableSetupColumn("Materia Id"u8, ImGuiTableColumnFlags.WidthFixed, 80);
ImGui.TableSetupColumn("MateriaGrade Id"u8);
ImGui.TableHeadersRow();
for (var i = 0; i < Math.Min(itemRow.MateriaSlotCount, item.Materia.Length); i++)
{
AddValueValueRow(item.Materia[i].ToString(), item.MateriaGrade[i].ToString());
}
}
}
}
}
}
private string GetStainName(uint stainId)
{
return this.dataManager.Excel.GetSheet<Stain>().TryGetRow(stainId, out var stainRow)
? StripSoftHypen(stainRow.Name.ExtractText())
: $"Stain#{stainId}";
}
private uint GetItemRarityColor(uint itemId, bool isEdgeColor = false)
{
if (ItemUtil.IsEventItem(itemId))
return isEdgeColor ? 0xFF000000 : 0xFFFFFFFF;
if (!this.dataManager.Excel.GetSheet<Item>().TryGetRow(ItemUtil.GetBaseId(itemId).ItemId, out var item))
return isEdgeColor ? 0xFF000000 : 0xFFFFFFFF;
var rowId = ItemUtil.GetItemRarityColorType(item.RowId, isEdgeColor);
return this.dataManager.Excel.GetSheet<UIColor>().TryGetRow(rowId, out var color)
? BinaryPrimitives.ReverseEndianness(color.Dark) | 0xFF000000
: 0xFFFFFFFF;
}
private uint GetItemIconId(uint itemId)
{
// EventItem
if (ItemUtil.IsEventItem(itemId))
return this.dataManager.Excel.GetSheet<EventItem>().TryGetRow(itemId, out var eventItem) ? eventItem.Icon : 0u;
// HighQuality
if (ItemUtil.IsHighQuality(itemId))
itemId -= 1_000_000;
// Collectible
if (ItemUtil.IsCollectible(itemId))
itemId -= 500_000;
return this.dataManager.Excel.GetSheet<Item>().TryGetRow(itemId, out var item) ? item.Icon : 0u;
}
}