Adds the backend-agnostic UI contract layer called for by the 2026-04-24
staged UI strategy (docs/plans/2026-04-24-ui-framework.md). This is the
stable layer both the Phase D.2a Hexa.NET.ImGui backend and the later
D.2b custom retail-look backend implement.
New module `src/AcDream.UI.Abstractions/`:
* IPanel — a drawable panel (id/title/visible/Render)
* IPanelHost — owns the panel list, drives per-frame dispatch
* IPanelRenderer — drawing primitives (Begin/End/Text/SameLine/
Separator/ProgressBar). Kept small + retail-friendly
on purpose — if a widget can't be expressed with
dat-sourced sprites+fonts later, don't add it here.
* ICommandBus — user-intent publisher; NullCommandBus is D.2a default
* PanelContext — per-frame record struct (DeltaSeconds + Commands)
* Panels/Vitals/
VitalsVM — reads CombatState.GetHealthPercent for the local
player. Stamina/Mana return null in D.2a; they await
a LocalPlayerState cache of PlayerDescription (0x0013)
which is filed as a follow-up issue.
VitalsPanel — first real panel. HP bar always drawn; Stam/Mana
appear automatically when the VM returns non-null.
Invariant documented in IPanel's XML doc: no `using Hexa.NET.ImGui` in
panel files, ever. If a widget needs something IPanelRenderer can't
express, the interface grows; panels never reach through.
References AcDream.Core for CombatState. Zero runtime/UI dependencies
— this project compiles headless, perfect for unit testing the
ViewModels.
No visible change yet. Next commits: (2) tests, (3) ImGui backend,
(4) GameWindow hookup + visible panel behind ACDREAM_DEVTOOLS=1.
37 lines
1.6 KiB
C#
37 lines
1.6 KiB
C#
namespace AcDream.UI.Abstractions;
|
|
|
|
/// <summary>
|
|
/// A UI panel — chat window, inventory, vitals HUD, character sheet, etc.
|
|
/// Panels are backend-agnostic: they only call into <see cref="IPanelRenderer"/>
|
|
/// primitives, never reach through to a specific UI library (Hexa.NET.ImGui
|
|
/// in Phase D.2a, a custom retail-look toolkit in Phase D.2b).
|
|
///
|
|
/// <para>
|
|
/// Hard rule: <b>no <c>using Hexa.NET.ImGui</c> inside a panel file</b>. If a
|
|
/// widget needs a feature the abstraction doesn't expose, extend
|
|
/// <see cref="IPanelRenderer"/>; do not import the backend. See
|
|
/// <c>docs/plans/2026-04-24-ui-framework.md</c>.
|
|
/// </para>
|
|
/// </summary>
|
|
public interface IPanel
|
|
{
|
|
/// <summary>Stable, globally-unique identifier. Convention: <c>acdream.{name}</c>.</summary>
|
|
string Id { get; }
|
|
|
|
/// <summary>Human-readable window title shown in the chrome of the panel.</summary>
|
|
string Title { get; }
|
|
|
|
/// <summary>
|
|
/// Whether the panel is currently visible. Backends read this per frame;
|
|
/// panels may mutate it in response to their own close-button handling.
|
|
/// </summary>
|
|
bool IsVisible { get; set; }
|
|
|
|
/// <summary>
|
|
/// Draw the panel for one frame. Called by <see cref="IPanelHost.RenderAll"/>
|
|
/// on the render thread once ImGui's (or the future custom backend's)
|
|
/// frame has begun. Panels issue drawing calls through <paramref name="renderer"/>
|
|
/// and publish user-intent actions through <paramref name="ctx"/>.<see cref="PanelContext.Commands"/>.
|
|
/// </summary>
|
|
void Render(PanelContext ctx, IPanelRenderer renderer);
|
|
}
|