using System.Numerics; namespace AcDream.App.UI; /// /// Rectangular container with an optional translucent background and /// border. Used as the base of every retail panel (attributes, chat, /// inventory, login, etc.). /// /// Retail has panel background art stored as 9-slice sprite assets in /// the 0x06xxxxxx RenderSurface range, and composed via /// LayoutDesc (0x21xxxxxx) trees. Until our /// AcFont/UiSpriteBatch consumes those directly, we draw a /// simple translucent rectangle so panels are visible during development. /// public class UiPanel : UiElement { /// Background fill color. Set to skip. public Vector4 BackgroundColor { get; set; } = new(0f, 0f, 0f, 0.55f); /// Border color. Set to skip. public Vector4 BorderColor { get; set; } = new(0.15f, 0.15f, 0.2f, 0.8f); public float BorderThickness { get; set; } = 1f; protected override void OnDraw(UiRenderContext ctx) { 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); } } /// /// Static text label. Draws a single line of text using the context's /// default font (or an override). Does not consume input. /// /// Equivalent retail primitive: wide-string appended to a CString via /// FUN_0040b8f0 then drawn by the widget's draw method through /// FUN_00698330. /// public class UiLabel : UiElement { public string Text { get; set; } = string.Empty; public Vector4 TextColor { get; set; } = new(1f, 1f, 1f, 1f); public UiLabel() { ClickThrough = true; } protected override void OnDraw(UiRenderContext ctx) => ctx.DrawString(Text, 0, 0, TextColor); } /// /// Simple clickable button: panel background + centered label + click /// callback. Retail equivalent is Keystone's button widget, driven by /// a StateDesc per UIStateId (normal / hot / pressed / /// disabled) from the panel layout. /// public class UiButton : UiPanel { public string Text { get; set; } = string.Empty; public Vector4 TextColor { get; set; } = new(1f, 1f, 1f, 1f); public event System.Action? Click; public UiButton() { BackgroundColor = new Vector4(0.1f, 0.1f, 0.15f, 0.8f); BorderColor = new Vector4(0.45f, 0.45f, 0.55f, 1f); } public override bool OnEvent(in UiEvent e) { if (e.Type == UiEventType.Click && Enabled) { Click?.Invoke(); return true; } return false; } protected override void OnDraw(UiRenderContext ctx) { base.OnDraw(ctx); if (Text.Length == 0 || ctx.DefaultFont is null) return; float textW = ctx.DefaultFont.MeasureWidth(Text); float tx = (Width - textW) * 0.5f; float ty = (Height - ctx.DefaultFont.LineHeight) * 0.5f; ctx.DrawString(Text, tx, ty, TextColor); } }