fix(D.2b): arrow swap, centered menu text, scrollbar-to-top, Send caption

- scroll arrows: native sprites are opposite (0x06004C6C up / 0x06004C69 down) per live
  visual — swap the assignment, drop the V-flip.
- menu labels centered vertically in each 17px row (was top-aligned, looked corrupt).
- scrollbar pulled up to the panel top so the top arrow meets the window border and the
  max/min button lines up with it (the 6px dat offset left a gap after the resize-bar reclaim).
- Send button: the dat sprite 0x06001915 is a blank gold frame (export-confirmed), so add a
  generic optional Label/LabelFont to UiDatElement and draw "Send" centered on it.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@
This commit is contained in:
Erik 2026-06-16 11:56:07 +02:00
parent bb983ae850
commit 621a4ab468
4 changed files with 43 additions and 21 deletions

View file

@ -87,21 +87,36 @@ public sealed class UiDatElement : UiElement
return false;
}
/// <summary>Optional centered text label drawn over the sprite (e.g. the "Send"
/// button face whose dat sprite is a blank frame). Null = sprite only.</summary>
public string? Label { get; set; }
/// <summary>Dat font for <see cref="Label"/>. Required for the label to draw.</summary>
public UiDatFont? LabelFont { get; set; }
/// <summary>Label color (default white).</summary>
public Vector4 LabelColor { get; set; } = Vector4.One;
protected override void OnDraw(UiRenderContext ctx)
{
var (file, _) = ActiveMedia();
if (file == 0) return;
if (file != 0)
{
var (tex, tw, th) = _resolve(file);
if (tex != 0 && tw != 0 && th != 0)
{
// Normal → TILE at native size on both axes (UV-repeat; GL_REPEAT-wrapped UI
// texture), matching ImgTex::TileCSI. Overlay/Alphablend use the same blit (the
// sprite shader already alpha-blends). No Stretch mode exists in DrawModeType.
ctx.DrawSprite(tex, 0, 0, Width, Height, 0, 0, Width / tw, Height / th, Vector4.One);
}
}
var (tex, tw, th) = _resolve(file);
if (tex == 0 || tw == 0 || th == 0) return;
// Normal → TILE at native size on both axes (UV-repeat; GL_REPEAT-wrapped UI texture),
// matching ImgTex::TileCSI. Overlay/Alphablend are the same blit with a blend state; the
// sprite shader already alpha-blends, so the quad is identical for all draw modes in Plan 1.
// (No Stretch mode exists in DatReaderWriter.Enums.DrawModeType.)
// DrawMode is not yet branched here — Plan 2 can add per-mode behavior if needed.
float u1 = Width / tw;
float v1 = Height / th;
ctx.DrawSprite(tex, 0, 0, Width, Height, 0, 0, u1, v1, Vector4.One);
// Centered text label over the sprite (retail draws button captions as text;
// their dat sprites are blank frames).
if (Label is { Length: > 0 } label && LabelFont is { } lf)
{
float tx = (Width - lf.MeasureWidth(label)) * 0.5f;
float ty = (Height - lf.LineHeight) * 0.5f;
ctx.DrawStringDat(lf, label, tx, ty, LabelColor);
}
}
}