Separate logical ownership, render publication, and GPU retirement across live entities, landblocks, particles, textures, mesh arenas, portal/UI teardown, and per-frame scratch storage. Add bounded DAT/texture caches, upload budgets, three-frame fence retirement, exact-incarnation appearance reconciliation, frame pacing, and extensive lifetime conformance coverage.\n\nThe seven-destination connected route now cuts peak working/private memory roughly in half, returns Caul to 125-153 FPS locally, and produces no WER or AMD reset.\n\nCo-authored-by: OpenAI Codex <codex@openai.com>
73 lines
2.4 KiB
C#
73 lines
2.4 KiB
C#
using System.Numerics;
|
|
using AcDream.Content;
|
|
using DatReaderWriter;
|
|
|
|
namespace AcDream.App.UI.Layout;
|
|
|
|
/// <summary>
|
|
/// Resolved presentation of retail's spell-shortcut row prototype. The spellbook
|
|
/// list points at this prototype through ItemList attribute <c>0x1000000E</c>;
|
|
/// retail clones it for every learned spell.
|
|
/// </summary>
|
|
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;
|
|
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
public static SpellbookRowStyle? TryLoad(IDatReaderWriter 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;
|
|
}
|
|
}
|