acdream/tests/AcDream.App.Tests/UI/MossTankIconInstalledDatTests.cs
Erik e61edd946b fix(plugin-ui): plugin did icons use retail's keyed-white recolor, not a raw blit
Owner report 2026-09-06: MossTank's shelf icon (0x06002C41) drew with a white
ring. DAT icon art reserves pure-white-opaque pixels as the recolor key that
retail IconData::RenderIcons (0x0058d180) replaces per pixel through
SurfaceWindow::ReplaceColor (0x004415b0) from the effect tile — the solid-black
0x21 tile when there are no effects. The inventory already does this through
IconComposer; the plugin did sink (markup <icon did>, <button icon>, <list icons>
and the shelf button) blitted the art raw.

RetailMarkupIconResolver.ResolveDid now hands out IconComposer.GetKeyedIcon —
the drag-icon composite (base art + effects==0 recolor, no overlay, no
underlay), sharing that cache — so did icons look like a mundane inventory item
does. The resolver no longer needs a TextureCache. KeyedIconInstalledDatTests
pins both halves against the real DAT: the raw art carries the key, the
composite carries none, and ResolveDid returns exactly the keyed composite.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-06 17:40:39 +02:00

65 lines
2.6 KiB
C#

using AcDream.App.Rendering;
using AcDream.App.Tests.Rendering;
using AcDream.App.Tests.Rendering.Gpu;
using AcDream.App.UI;
using AcDream.Content;
using AcDream.Core.Items;
using DatReaderWriter;
using DatReaderWriter.DBObjs;
using DatReaderWriter.Options;
using Xunit;
namespace AcDream.App.Tests.UI;
/// <summary>
/// Owner direction 2026-09-06 (Smoke-plugin removal +
/// <c>docs/plans/2026-09-06-plugin-shelf-and-dat-icons.md</c> follow-up):
/// <c>MossTankPlugin</c>'s shelf descriptor now sets a real
/// <c>IconSurfaceId</c> instead of relying solely on the <c>"MT"</c> text
/// fallback. Mirrors the
/// <see cref="AcDream.App.Tests.UI.RetailMarkupIconResolverInstalledDatTests"/>
/// installed-DAT gate convention: <see cref="InstalledDatTestPath"/> +
/// <c>[Trait("Lane", "InstalledDat")]</c>, <c>Assert.Fail</c> with the
/// standard message when no DAT is configured (see docs/release-gate.md).
/// </summary>
[Trait("Lane", "InstalledDat")]
public sealed class MossTankIconInstalledDatTests
{
/// <summary>The id <c>MossTankPlugin.cs</c> sets as its shelf descriptor's
/// <c>IconSurfaceId</c>.</summary>
private const uint MossTankShelfIconId = 0x06002C41u;
[Fact]
public void MossTankShelfIconId_IsARealInstalledRenderSurface()
{
string? datDir = InstalledDatTestPath.Resolve();
if (datDir is null)
{
Assert.Fail(
"Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md.");
return;
}
using var dats = new DatCollection(datDir, DatAccessType.Read);
using var adapter = new DatCollectionAdapter(dats);
// The RenderSurface must exist in Portal or HighRes — the same two
// databases RetailMarkupIconResolver.ResolveDid probes before ever
// touching TextureCache.
bool existsInPortal = adapter.Portal.TryGet<RenderSurface>(MossTankShelfIconId, out _);
bool existsInHighRes = adapter.HighRes.TryGet<RenderSurface>(MossTankShelfIconId, out _);
Assert.True(
existsInPortal || existsInHighRes,
$"expected 0x{MossTankShelfIconId:X8} to be a real installed RenderSurface (Portal or HighRes)");
var device = new RecordingGpuDevice();
using var cache = new TextureCache(device, adapter);
var icons = new IconComposer(adapter, cache);
var objects = new ClientObjectTable();
var resolver = new RetailMarkupIconResolver(adapter, icons, objects);
(uint tex, int w, int h) = resolver.ResolveDid(MossTankShelfIconId);
Assert.NotEqual(0u, tex);
Assert.True(w > 0 && h > 0);
}
}