@
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:
parent
bb983ae850
commit
621a4ab468
4 changed files with 43 additions and 21 deletions
|
|
@ -46,8 +46,8 @@ public sealed class ChatWindowController
|
|||
private const uint ThumbSprite = 0x06004C63u; // 3-slice middle tile
|
||||
private const uint ThumbTopSprite = 0x06004C60u; // 3-slice top cap
|
||||
private const uint ThumbBotSprite = 0x06004C66u; // 3-slice bottom cap
|
||||
private const uint UpSprite = 0x06004C69u;
|
||||
private const uint DownSprite = 0x06004C6Cu;
|
||||
private const uint UpSprite = 0x06004C6Cu; // up arrow (top button)
|
||||
private const uint DownSprite = 0x06004C69u; // down arrow (bottom button)
|
||||
|
||||
// Channel menu sprite ids (confirmed in chat element dump).
|
||||
private const uint MenuNormal = 0x06004D65u; // button face
|
||||
|
|
@ -199,10 +199,13 @@ public sealed class ChatWindowController
|
|||
{
|
||||
c.Scrollbar = new UiChatScrollbar
|
||||
{
|
||||
// Pull the bar up to the panel top so the top arrow meets the window
|
||||
// border (and lines up with the max/min button at root y=0); the dat
|
||||
// track sits 6px down, which left a gap after the resize-bar reclaim.
|
||||
Left = track.Left,
|
||||
Top = track.Top,
|
||||
Top = 0f,
|
||||
Width = track.Width,
|
||||
Height = track.Height,
|
||||
Height = track.Height + track.Top,
|
||||
Anchors = track.Anchors,
|
||||
Model = c.Transcript.Scroll,
|
||||
SpriteResolve = resolve,
|
||||
|
|
@ -248,6 +251,10 @@ public sealed class ChatWindowController
|
|||
{
|
||||
sendEl.ClickThrough = false;
|
||||
sendEl.OnClick = () => c.Input.Submit();
|
||||
// The Send sprite is a blank gold button — retail draws the caption as text.
|
||||
sendEl.Label = "Send";
|
||||
sendEl.LabelFont = datFont;
|
||||
sendEl.LabelColor = new Vector4(1f, 0.92f, 0.72f, 1f);
|
||||
}
|
||||
|
||||
// ── Max/min toggle — simplified gmMainChatUI::HandleMaximizeButton ──
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -134,11 +134,12 @@ public sealed class UiChannelMenu : UiElement
|
|||
bool selected = Items[i].Channel is { } c && c == Selected;
|
||||
DrawSprite(ctx, resolve, selected ? ItemHighlightSprite : ItemNormalSprite, x, y, ColW, ItemH);
|
||||
}
|
||||
float textY = (ItemH - LineH()) * 0.5f; // center the label in its row
|
||||
for (int i = 0; i < Items.Length; i++)
|
||||
{
|
||||
int col = i / Rows, row = i % Rows;
|
||||
bool avail = Items[i].Channel is { } c && IsAvailable(c);
|
||||
DrawLabel(ctx, Items[i].Label, 4f + col * ColW, top + row * ItemH,
|
||||
DrawLabel(ctx, Items[i].Label, 4f + col * ColW, top + row * ItemH + textY,
|
||||
avail ? TextColorAvailable : TextColorGhosted);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -89,11 +89,10 @@ public sealed class UiChatScrollbar : UiElement
|
|||
// sprite (~16×32) repeats to fill the element height instead of stretch-distorting.
|
||||
DrawTiled(ctx, resolve, TrackSprite, 0f, 0f, Width, Height);
|
||||
|
||||
// Up button — top ButtonH rows. The dat up/down arrow sprites both point DOWN
|
||||
// (confirmed by sprite export), so the TOP button is drawn V-FLIPPED to point UP.
|
||||
DrawSpriteFlipV(ctx, resolve, UpSprite, 0f, 0f, Width, ButtonH);
|
||||
// Up button — top ButtonH rows. UpSprite (0x06004C6C) is the up-arrow art, drawn 1:1.
|
||||
DrawSprite(ctx, resolve, UpSprite, 0f, 0f, Width, ButtonH);
|
||||
|
||||
// Down button — bottom ButtonH rows (down arrow as-is).
|
||||
// Down button — bottom ButtonH rows. DownSprite (0x06004C69) is the down-arrow art.
|
||||
DrawSprite(ctx, resolve, DownSprite, 0f, Height - ButtonH, Width, ButtonH);
|
||||
|
||||
// Thumb — only when content overflows the view. Retail 3-slice: top cap +
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue