WindowSpec record
Immutable declaration of a plugin window’s identity, initial geometry, and chrome options. Passed to Register to create the window.
public record WindowSpec : IRenderGatedPublic Members
Section titled “Public Members”| name | description |
|---|---|
| Anchor { get; set; } | Anchor for the initial placement of DefaultRect on the (possibly scaled) window canvas. Defaults to TopLeft = legacy absolute top-left. Use Center etc. to center/corner-anchor without computing the UI scale yourself; DefaultRect.X/Y then act as a canvas-unit offset from the anchor. A user’s saved drag still overrides this. |
| AutoSizeWidth { get; set; } | Content-size the window WIDTH to its body instead of fixing it to DefaultRect.Width. Only safe for windows without wrapping text (e.g. the launcher’s fixed-width icon tiles) — the in-world clip bug that forced fixed width was a wrapping-text problem the launcher does not have. Defaults false. |
| BackgroundOpacity { get; set; } | Borderless windows only: poll-diffed black background opacity (0 = transparent, 1 = fully black). Applied to the root’s existing click-blocker Image so the background fills the entire window rect and expands when the user resizes height — no separate child GO needed. Null = no background (default). |
| Category { get; set; } | Logical category that determines which group this window appears in within the layout editor. |
| Closable { get; set; } | When true the chrome draws a ✕ close glyph that hides the window. Defaults false (plugin windows manage their own visibility). Independent of Draggable so a window can be draggable without a close button (e.g. the Settings hub). |
| DefaultRect { get; set; } | Initial position and size applied on first run (before user adjustments are persisted). |
| DismissOnOutsideClick { get; set; } | When true the framework auto-hides this window on Escape or a mouse press outside its rect — the click-away dismiss a cursor popup / context menu wants. The dismiss invokes the registration’s OnClose (wire it to SetVisible(false)); with no OnClose the flag is inert. Handled on the per-render-frame interaction ticker, NOT the throttled framework tick, so it never misses a one-frame click/key edge (a press lasting one rendered frame would be missed by a plugin polling input from its throttled OnUpdate). |
| Draggable { get; set; } | When true the window is a movable dialog: drag-by-title-bar (the post-drag rect is committed + persisted) and excluded from the Shift+` Layout editor (it owns its own position). When false the window is positioned via the Layout editor and any title-bar drag is discarded. Defaults false. Settings windows + opt-in plugin panels (e.g. StatInspector settings) set this true. |
| EditModeDragOnly { get; set; } | When true the chrome draws a bottom-right ↘ resize grip; dragging it changes the window size (clamped to MinWidth/MinHeight .. MaxWidth/MaxHeight), and the new size persists alongside the position. The window’s vertical content-fit is disabled (fixed height); a ScrollElement in the body fills the freed space. Defaults false. The CombatMeter list uses this. |
| Id { get; set; } | Stable string id, unique per plugin. Used to persist position and hotkey binding. |
| MaxHeight { get; set; } | Maximum allowed window height in pixels when Resizable is true. |
| MaxWidth { get; set; } | Maximum allowed window width in pixels when Resizable is true. |
| MinHeight { get; set; } | Minimum allowed window height in pixels when Resizable is true. |
| MinWidth { get; set; } | Minimum allowed window width in pixels when Resizable is true. |
| Resizable { get; set; } | When true the chrome draws a resize grip; dragging it changes the window size (clamped to Min/Max bounds). |
| ShouldRender { get; set; } | The single source of visibility truth (hide = !ShouldRender(), evaluated each apply ~10 Hz). Compiler-required: every WindowSpec MUST set it or the build fails. Read whatever you want — Phase, UiState, your own state — via the plugin’s captured services. Use () => true for always-on chrome, () => _services.ClientState.Phase == GamePhase.World for a gameplay window. |
| ShowTitleBar { get; set; } | GlassMenu only: draw the top title bar. Defaults true. Set false for windows that self-compose their own header inside the body (the launcher, whose header is top in Full/vertical but a LEFT strip in horizontal — a single fixed top bar can’t express both). With no title bar the whole frame becomes the drag handle (if Draggable), and the body must supply its own close affordance. |
| StartVisible { get; set; } | Whether the window is visible on first run (before user toggles via hotkey). |
| Style { get; set; } | Visual chrome style applied to the window frame. |
| Surface { get; set; } | Which render surface the window’s Text / Bar (Default style) / Pill leaves use. Defaults to Menu = the window theme chrome (unchanged — every existing window keeps rendering exactly as before). Set HudOverlay to reproduce the borderless HUD look for those leaves: shadowed text over the world, rounded HP-bar chrome, and a transparent pill chip — byte-identical to the native HUD renderer, so a HUD-path plugin can migrate onto the window path with pixel-exact fidelity. Only those three leaf types are affected; all other widgets render identically either way. The positional constructor is unchanged, so this is non-breaking. |
| Title { get; set; } | Display title shown in the title bar and Settings layout editor. |
| ZOrder { get; set; } | Explicit draw-order among Stellar windows: HIGHER draws on top. Default 0. The framework stacks windows by (ZOrder, then Category as a tiebreak — HUD<Tools<Debug — then Id), so a plugin that sets this fully controls where its window sits relative to others regardless of load/mount order; one that leaves it 0 falls back to the category default. Click-away (DismissOnOutsideClick) popups always render above all of these. |
See Also
Section titled “See Also”- interface IRenderGated
- namespace Stellar.Abstractions.Domain