refactor: Split item grid out of ItemBrowser

This commit is contained in:
VAC committed 2026-10-16 00:38:45 -03:00
1 parent 3195e7ba92
commit 6b3dcccc7c
2 files changed
+99 -85

No files matched your search

+2 -85
View File
@@ -1,89 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using Terraria; using Terraria;
using Terraria.GameContent.Creative;
using Terraria.ID;
using Terraria.Localization;
using Terraria.UI;
#if TMODLOADER
using Terraria.ModLoader;
#endif
namespace TerraSharp.UI; namespace TerraSharp.UI;
public sealed class ItemBrowser() : GridBrowser("items", "Item Browser", new Vector2(660, 120), 532, 520, "Search items by name or ID", "items", new IdIndex(() => ItemCount, Lang.GetItemNameValue), Categories()) public sealed class ItemBrowser() : ItemGrid("items", "Item Browser", new Vector2(660, 120), 534, 520, [])
{ {
const int InventorySlots = 50; const int InventorySlots = 50;
#if TMODLOADER
static int ItemCount => ItemLoader.ItemCount;
#else
static int ItemCount => ItemID.Count;
#endif
enum WeaponClass { Melee, Ranged, Magic, Summon, Other }
static readonly IItemEntryFilter Weapon = new ItemFilters.Weapon();
// Journey duplication filters paired with Infinite_Icons frame indices.
static readonly (IItemEntryFilter Filter, int Icon)[] Filters = [(new ItemFilters.Tools(), 6), (new ItemFilters.Armor(), 2), (new ItemFilters.Vanity(), 8), (new ItemFilters.Accessories(), 1), (new ItemFilters.MiscAccessories(), 9), (new ItemFilters.Consumables(), 3), (new ItemFilters.BuildingBlock(), 4), (new ItemFilters.Furniture(), 7), (new ItemFilters.Materials(), 10)];
static BrowserCategory[] Categories() =>
[
new("All", _ => true),
new(Language.GetTextValue(Weapon.GetDisplayNameKey()), type => Fits(Weapon, type), 0, [.. Enum.GetValues(typeof(WeaponClass)).Cast<WeaponClass>().Select(weaponClass => new BrowserCategory(weaponClass.ToString(), type => ContentSample(type) is { } item && ClassOf(item) == weaponClass)), new("Ammo", type => ContentSample(type) is { ammo: > 0 })]),
.. Filters.Select(entry => new BrowserCategory(Language.GetTextValue(entry.Filter.GetDisplayNameKey()), type => Fits(entry.Filter, type), entry.Icon)),
new(Language.GetTextValue("CreativePowers.TabMisc"), type => !Fits(Weapon, type) && !Filters.Any(entry => Fits(entry.Filter, type)), 5),
];
static Item? ContentSample(int type) => ContentSamples.ItemsByType.TryGetValue(type, out Item? item) ? item : null;
// Whips must be classified as summon weapons before checking melee.
static WeaponClass? ClassOf(Item item)
{
if (!Weapon.FitsFilter(item) || item.pick > 0 || item.axe > 0 || item.hammer > 0 || item.ammo > 0)
return null;
#if TMODLOADER
if (item.CountsAsClass(DamageClass.Summon))
return WeaponClass.Summon;
if (item.CountsAsClass(DamageClass.Magic))
return WeaponClass.Magic;
if (item.CountsAsClass(DamageClass.Ranged))
return WeaponClass.Ranged;
if (item.CountsAsClass(DamageClass.Melee))
return WeaponClass.Melee;
#else
if (item.summon)
return WeaponClass.Summon;
if (item.magic)
return WeaponClass.Magic;
if (item.ranged)
return WeaponClass.Ranged;
if (item.melee)
return WeaponClass.Melee;
#endif
return WeaponClass.Other;
}
static bool Fits(IItemEntryFilter filter, int type) => ContentSample(type) is { } item && filter.FitsFilter(item);
readonly Dictionary<int, Item> _samples = [];
public override void OnOpen() => Main.playerInventory = true; public override void OnOpen() => Main.playerInventory = true;
Item Sample(int type)
{
if (!_samples.TryGetValue(type, out Item? item))
{
item = new Item();
item.SetDefaults(type);
_samples[type] = item;
}
return item;
}
protected override void DrawContent(Rectangle body) protected override void DrawContent(Rectangle body)
{ {
DrawSearchGrid(body, body.Y, body.Bottom - 30); DrawSearchGrid(body, body.Y, body.Bottom - 30);
@@ -92,18 +17,10 @@ public sealed class ItemBrowser() : GridBrowser("items", "Item Browser", new Vec
protected override void DrawSlot(int type, Rectangle bounds, bool hot) protected override void DrawSlot(int type, Rectangle bounds, bool hot)
{ {
Widgets.Slot(bounds, hot); DrawItem(type, bounds, hot);
Render.Item(Widgets.SpriteBatch, type, new Rectangle(bounds.X + 6, bounds.Y + 6, bounds.Width - 12, bounds.Height - 12));
if (!hot) if (!hot)
return; return;
#if TMODLOADER
Item sample = Sample(type);
ItemSlot.MouseHover(ref sample, ItemSlot.Context.CreativeInfinite);
#else
ItemSlot.MouseHover(Sample(type), ItemSlot.Context.CreativeInfinite);
#endif
if (Widgets.Click) if (Widgets.Click)
Give(type, Widgets.Shift); Give(type, Widgets.Shift);
else if (Widgets.RightClick) else if (Widgets.RightClick)
+97
View File
@@ -0,0 +1,97 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Terraria;
using Terraria.GameContent.Creative;
using Terraria.ID;
using Terraria.Localization;
using Terraria.UI;
#if TMODLOADER
using Terraria.ModLoader;
#endif
namespace TerraSharp.UI;
public abstract class ItemGrid(string id, string title, Vector2 position, int width, int height, BrowserCategory[] extra) : GridBrowser(id, title, position, width, height, "Search items by name or ID", "items", new IdIndex(() => ItemCount, Lang.GetItemNameValue), [.. Categories(), .. extra])
{
#if TMODLOADER
static int ItemCount => ItemLoader.ItemCount;
#else
static int ItemCount => ItemID.Count;
#endif
enum WeaponClass { Melee, Ranged, Magic, Summon, Other }
static readonly IItemEntryFilter Weapon = new ItemFilters.Weapon();
// Journey duplication filters paired with Infinite_Icons frame indices.
static readonly (IItemEntryFilter Filter, int Icon)[] Filters = [(new ItemFilters.Tools(), 6), (new ItemFilters.Armor(), 2), (new ItemFilters.Vanity(), 8), (new ItemFilters.Accessories(), 1), (new ItemFilters.MiscAccessories(), 9), (new ItemFilters.Consumables(), 3), (new ItemFilters.BuildingBlock(), 4), (new ItemFilters.Furniture(), 7), (new ItemFilters.Materials(), 10)];
static BrowserCategory[] Categories() =>
[
new("All", _ => true),
new(Language.GetTextValue(Weapon.GetDisplayNameKey()), type => Fits(Weapon, type), 0, [.. Enum.GetValues(typeof(WeaponClass)).Cast<WeaponClass>().Select(weaponClass => new BrowserCategory(weaponClass.ToString(), type => ContentSample(type) is { } item && ClassOf(item) == weaponClass)), new("Ammo", type => ContentSample(type) is { ammo: > 0 })]),
.. Filters.Select(entry => new BrowserCategory(Language.GetTextValue(entry.Filter.GetDisplayNameKey()), type => Fits(entry.Filter, type), entry.Icon)),
new(Language.GetTextValue("CreativePowers.TabMisc"), type => !Fits(Weapon, type) && !Filters.Any(entry => Fits(entry.Filter, type)), 5),
];
static Item? ContentSample(int type) => ContentSamples.ItemsByType.TryGetValue(type, out Item? item) ? item : null;
// Whips must be classified as summon weapons before checking melee.
static WeaponClass? ClassOf(Item item)
{
if (!Weapon.FitsFilter(item) || item.pick > 0 || item.axe > 0 || item.hammer > 0 || item.ammo > 0)
return null;
#if TMODLOADER
if (item.CountsAsClass(DamageClass.Summon))
return WeaponClass.Summon;
if (item.CountsAsClass(DamageClass.Magic))
return WeaponClass.Magic;
if (item.CountsAsClass(DamageClass.Ranged))
return WeaponClass.Ranged;
if (item.CountsAsClass(DamageClass.Melee))
return WeaponClass.Melee;
#else
if (item.summon)
return WeaponClass.Summon;
if (item.magic)
return WeaponClass.Magic;
if (item.ranged)
return WeaponClass.Ranged;
if (item.melee)
return WeaponClass.Melee;
#endif
return WeaponClass.Other;
}
static bool Fits(IItemEntryFilter filter, int type) => ContentSample(type) is { } item && filter.FitsFilter(item);
readonly Dictionary<int, Item> _samples = [];
Item Sample(int type)
{
if (!_samples.TryGetValue(type, out Item? item))
{
item = new Item();
item.SetDefaults(type);
_samples[type] = item;
}
return item;
}
protected void DrawItem(int type, Rectangle bounds, bool hot, bool selected = false)
{
Widgets.Slot(bounds, hot, selected);
Render.Item(Widgets.SpriteBatch, type, new Rectangle(bounds.X + 6, bounds.Y + 6, bounds.Width - 12, bounds.Height - 12));
if (!hot)
return;
#if TMODLOADER
Item sample = Sample(type);
ItemSlot.MouseHover(ref sample, ItemSlot.Context.CreativeInfinite);
#else
ItemSlot.MouseHover(Sample(type), ItemSlot.Context.CreativeInfinite);
#endif
}
}