using System.Numerics;
using DatReaderWriter;
namespace AcDream.App.UI.Layout;
///
/// Resolved presentation of retail's spell-shortcut row prototype. The spellbook
/// list points at this prototype through ItemList attribute 0x1000000E;
/// retail clones it for every learned spell.
///
public readonly record struct SpellbookRowStyle(
float Width,
float Height,
float IconLeft,
float IconTop,
float IconWidth,
float IconHeight,
float LabelLeft,
float LabelWidth,
uint FontDid,
Vector4 LabelColor,
uint BackgroundSprite,
uint SelectedSprite)
{
public const uint CatalogLayoutId = 0x21000037u;
public const uint PrototypeId = 0x10000343u;
public const uint SelectedOverlayId = 0x10000342u;
public const uint LabelId = 0x10000344u;
public const uint IconId = 0x1000033Bu;
///
/// Resolve the complete row geometry and media from the installed retail DAT.
/// Returns null if the authored prototype is incomplete; callers then leave the
/// panel unbound rather than inventing replacement art.
///
public static SpellbookRowStyle? TryLoad(DatCollection dats)
{
ArgumentNullException.ThrowIfNull(dats);
ElementInfo? prototype = LayoutImporter.ImportInfos(dats, CatalogLayoutId, PrototypeId);
if (prototype is null
|| Find(prototype, SelectedOverlayId) is not { } selected
|| Find(prototype, LabelId) is not { } label
|| Find(prototype, IconId) is not { } icon
|| !prototype.StateMedia.TryGetValue("", out var background)
|| !selected.StateMedia.TryGetValue("", out var selection)
|| prototype.Width <= 0f
|| prototype.Height <= 0f)
return null;
return new SpellbookRowStyle(
prototype.Width,
prototype.Height,
icon.X,
icon.Y,
icon.Width,
icon.Height,
label.X,
label.Width,
label.FontDid,
label.FontColor ?? Vector4.One,
background.File,
selection.File);
}
private static ElementInfo? Find(ElementInfo root, uint id)
{
if (root.Id == id) return root;
foreach (ElementInfo child in root.Children)
if (Find(child, id) is { } found) return found;
return null;
}
}