fix(studio): Character window — selected-row highlight uses retail bar sprite

Replaces the translucent-gold BackgroundColor tint with sprite 0x06001397
(Button state 6 — the retail dark horizontal bars) for the selected-row
background. When spriteResolve is provided to Bind(), clicking a row now
applies BackgroundSprite=0x06001397 + SpriteResolve on that row and clears
it on all others. Falls back to HighlightBg tint when no resolver is passed
(tests, or contexts without GL).

UiPanel.BackgroundSprite / SpriteResolve added so any panel can host a
sprite background in place of the solid BackgroundColor rect. HandleRowClick
updated to accept spriteResolve and apply the sprite or tint branch
depending on availability. Two new tests verify the sprite / deselect paths.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-06-26 02:26:46 +02:00
parent a236dc33ac
commit dfb4c81133
3 changed files with 89 additions and 4 deletions

View file

@ -410,7 +410,7 @@ public static class CharacterStatController
return v.ToString();
});
row.OnClick = () => HandleRowClick(rowIndex, sel, rows, data, allRaise1, allRaise10);
row.OnClick = () => HandleRowClick(rowIndex, sel, rows, spriteResolve, data, allRaise1, allRaise10);
rows.Add(row);
y += RowHeight;
}
@ -437,7 +437,7 @@ public static class CharacterStatController
};
});
row.OnClick = () => HandleRowClick(absIndex, sel, rows, data, allRaise1, allRaise10);
row.OnClick = () => HandleRowClick(absIndex, sel, rows, spriteResolve, data, allRaise1, allRaise10);
rows.Add(row);
y += RowHeight;
}
@ -453,6 +453,7 @@ public static class CharacterStatController
int clickedIndex,
int[] sel,
List<UiClickablePanel> rows,
Func<uint, (uint handle, int w, int h)>? spriteResolve,
Func<CharacterSheet> data,
List<UiButton> allRaise1,
List<UiButton> allRaise10)
@ -465,8 +466,35 @@ public static class CharacterStatController
Console.WriteLine($"[CharacterStat] Row click: index={clickedIndex} → selected={newSel} ({rowName})");
// Update highlight on all rows.
// Retail uses sprite 0x06001397 (Button state 6 — the dark horizontal bars)
// for the selected row background. When spriteResolve is available, apply the
// sprite; otherwise fall back to the translucent gold tint.
const uint HighlightSprite = 0x06001397u;
for (int i = 0; i < rows.Count; i++)
rows[i].BackgroundColor = (i == newSel) ? HighlightBg : Vector4.Zero;
{
var row = rows[i];
if (i == newSel)
{
if (spriteResolve is not null)
{
row.BackgroundColor = Vector4.Zero;
row.BackgroundSprite = HighlightSprite;
row.SpriteResolve = spriteResolve;
}
else
{
row.BackgroundColor = HighlightBg;
row.BackgroundSprite = 0u;
row.SpriteResolve = null;
}
}
else
{
row.BackgroundColor = Vector4.Zero;
row.BackgroundSprite = 0u;
row.SpriteResolve = null;
}
}
// Update raise buttons.
RefreshRaiseButtons(newSel, data, allRaise1, allRaise10);

View file

@ -24,10 +24,28 @@ public class UiPanel : UiElement
public float BorderThickness { get; set; } = 1f;
/// <summary>Optional dat RenderSurface id for the panel background sprite, drawn
/// in place of (or alongside) <see cref="BackgroundColor"/>. 0 = none.
/// When set, the sprite is stretched to fill the panel rect.
/// Used by the attribute-list selected-row highlight (sprite 0x06001397 = Button state 6).</summary>
public uint BackgroundSprite { get; set; }
/// <summary>Resolves a dat RenderSurface id to (GL tex handle, pixel width, pixel height).
/// Required when <see cref="BackgroundSprite"/> is non-zero.</summary>
public Func<uint, (uint tex, int w, int h)>? SpriteResolve { get; set; }
protected override void OnDraw(UiRenderContext ctx)
{
if (BackgroundColor.W > 0f)
if (BackgroundSprite != 0 && SpriteResolve is { } sr)
{
var (tex, tw, th) = sr(BackgroundSprite);
if (tex != 0 && tw != 0 && th != 0)
ctx.DrawSprite(tex, 0, 0, Width, Height, 0, 0, Width / tw, Height / th, Vector4.One);
}
else if (BackgroundColor.W > 0f)
{
ctx.DrawRect(0, 0, Width, Height, BackgroundColor);
}
if (BorderColor.W > 0f && BorderThickness > 0f)
ctx.DrawRectOutline(0, 0, Width, Height, BorderColor, BorderThickness);