fix(D.2b): channel menu popup opaque + button label tracks selected target

- the popup inherited the chat window 0.75 opacity so the transcript bled through;
  add UiRenderContext.PushAlphaAbsolute and draw the popup at absolute opacity.
- the "Chat" button was hardcoded; it now shows the active talk target (retail
  updates it on selection). Exact textured menu-panel sprite is a follow-up (the
  popup is a keystone UIElement_Menu construct, not in the chat LayoutDesc).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@
This commit is contained in:
Erik 2026-06-16 10:38:56 +02:00
parent ccaf188e41
commit 7094a1c847
2 changed files with 37 additions and 8 deletions

View file

@ -53,7 +53,7 @@ public sealed class UiChannelMenu : UiElement
public uint PressedSprite { get; set; }
public Vector4 TextColor { get; set; } = new(1f, 0.92f, 0.72f, 1f);
/// <summary>Popup panel fill — the retail talk-focus menu is a warm tan/orange.</summary>
public Vector4 PopupColor { get; set; } = new(0.56f, 0.40f, 0.18f, 0.97f);
public Vector4 PopupColor { get; set; } = new(0.56f, 0.40f, 0.18f, 1f);
private bool _open;
private static float PopupW => 2 * ColW;
@ -61,26 +61,51 @@ public sealed class UiChannelMenu : UiElement
public UiChannelMenu() { CapturesPointerDrag = true; }
/// <summary>The button face label = the active talk target (retail updates the
/// "Chat" button to whichever target you pick). "Chat" = Chat-to-All (Say).</summary>
private string ButtonText => Selected switch
{
ChatChannelKind.Say => "Chat",
ChatChannelKind.General => "General",
ChatChannelKind.Trade => "Trade",
ChatChannelKind.Lfg => "LFG",
ChatChannelKind.Fellowship => "Fellow",
ChatChannelKind.Allegiance => "Alleg",
ChatChannelKind.Patron => "Patron",
ChatChannelKind.Vassals => "Vassals",
ChatChannelKind.Monarch => "Monarch",
ChatChannelKind.Roleplay => "Roleplay",
ChatChannelKind.Society => "Society",
ChatChannelKind.Olthoi => "Olthoi",
_ => "Chat",
};
protected override void OnDraw(UiRenderContext ctx)
{
// Button face + the "Chat" label (retail labels the talk-focus button "Chat").
// Button face + the active-target label (retail updates this to the chosen target).
if (SpriteResolve is { } resolve)
{
var (tex, _, _) = resolve(_open ? PressedSprite : NormalSprite);
if (tex != 0) ctx.DrawSprite(tex, 0, 0, Width, Height, 0f, 0f, 1f, 1f, Vector4.One);
}
DrawLabel(ctx, "Chat", 4f, (Height - LineH()) * 0.5f);
DrawLabel(ctx, ButtonText, 4f, (Height - LineH()) * 0.5f);
if (!_open) return;
// Two-column popup opening UPWARD from the button (chat sits at screen bottom).
float top = -PopupH;
ctx.DrawRect(0, top, PopupW, PopupH, PopupColor);
for (int i = 0; i < Items.Length; i++)
// Force OPAQUE: the menu must read solid even though the chat window is translucent.
ctx.PushAlphaAbsolute(1f);
try
{
int col = i / Rows, row = i % Rows;
DrawLabel(ctx, Items[i].Label, 4f + col * ColW, top + row * ItemH);
float top = -PopupH;
ctx.DrawRect(0, top, PopupW, PopupH, PopupColor);
for (int i = 0; i < Items.Length; i++)
{
int col = i / Rows, row = i % Rows;
DrawLabel(ctx, Items[i].Label, 4f + col * ColW, top + row * ItemH);
}
}
finally { ctx.PopAlpha(); }
}
private float LineH() => DatFont?.LineHeight ?? Font?.LineHeight ?? 14f;

View file

@ -34,6 +34,10 @@ public sealed class UiRenderContext
/// <summary>Multiply <paramref name="a"/> into the running opacity. Pair with <see cref="PopAlpha"/>.</summary>
public void PushAlpha(float a) { _alphaStack.Add(_alpha); _alpha *= a; }
/// <summary>Push an ABSOLUTE opacity (replaces, not multiplies) — for popups/overlays
/// that must stay opaque even inside a translucent window. Pair with <see cref="PopAlpha"/>.</summary>
public void PushAlphaAbsolute(float a) { _alphaStack.Add(_alpha); _alpha = a; }
public void PopAlpha()
{
if (_alphaStack.Count == 0) return;