Panels and controls
A panel is a draw callback the editor calls every frame. Controls are one call each and report what the user did through their return value.
Add a panel
Host.AddPanel(new PanelOptions(id, title), draw) registers a dockable panel. It is listed under Window, keeps its dock position across reloads, and can be opened or closed from code with Host.SetPanelOpen. PanelOptions also takes an icon (a Lucide icon name), a category, the default dock slot and whether it opens by default.
Controls
Each control draws itself and returns true when it was clicked or changed; the values live in your fields, passed by ref.
| Kind | Calls |
|---|---|
| Text | Text, TextWrapped, TextColored, Heading, SeparatorText |
| Buttons | Button (with a ButtonStyle), icon buttons, Selectable |
| Values | Checkbox, InputText, InputInt, InputFloat, SliderFloat, DragFloat3, Combo, ColorEdit4 |
| Feedback | ProgressBar, Tooltip, IsItemHovered |
| Layout | SameLine, Separator, Indent, SetNextItemWidth, collapsible sections |
| Structure | BeginTable / EndTable, TreeNode / TreePop, PushId / PopId, BeginDisabled / EndDisabled |
SpawnerPanel.cs
public sealed class SpawnerPanel : EditorPlugin { private static readonly string[] Shapes = ["Cube", "Sphere", "Capsule"]; private string prefix = "Crate"; private int count = 4; private float spacing = 2.0f; private int shape; private bool randomRotation; private Vector4 tint = new(0.23f, 0.27f, 1.0f, 1.0f); public override void OnLoad() => Host.AddPanel(new PanelOptions("Spawner", "Spawner") { Icon = "boxes" }, Draw); private void Draw(Ui ui) { ui.Heading("Spawner"); ui.InputText("Name prefix", ref prefix); ui.InputInt("Count", ref count); ui.SliderFloat("Spacing", ref spacing, 0.5f, 10.0f); ui.Combo("Shape", ref shape, Shapes); ui.Checkbox("Random rotation", ref randomRotation); ui.ColorEdit4("Tint", ref tint); ui.Separator(); // Controls return true when the user changed or clicked them. ui.BeginDisabled(count <= 0); if (ui.Button($"Spawn {count} {Shapes[shape]}s", ButtonStyle.Primary)) Host.Log($"spawning {count} x {prefix}"); ui.EndDisabled(); if (ui.IsItemHovered()) ui.Tooltip("Adds the entities to the open scene (one undo step)."); } }
Tables and lists
Tables lay out rows and columns with the editor's styling; trees show hierarchies. Keep long lists cheap: draw only what is visible or cap the rows.
ReportPanel.cs
public sealed class ReportPanel : EditorPlugin { public override void OnLoad() => Host.AddPanel(new PanelOptions("Report", "Scene Report"), Draw); private void Draw(Ui ui) { World? scene = Host.Document; if (scene is null) { ui.TextColored(ThemeColor.TextSecondary, "Open a scene to see its report."); return; } IReadOnlyList<Entity> entities = scene.Entities; ui.Text($"{entities.Count} entities"); if (ui.BeginTable("entities", 2)) { ui.TableSetupColumn("Name"); ui.TableSetupColumn("Position"); ui.TableHeadersRow(); foreach (Entity entity in entities.Take(200)) { ui.TableNextRow(); ui.TableNextColumn(); ui.Text(scene.GetName(entity)); ui.TableNextColumn(); ui.Text(scene.GetTransform(entity).Position.ToString("0.0", CultureInfo.InvariantCulture)); } ui.EndTable(); } } }
Theme
Use ThemeColor and ThemeMetric instead of fixed colours and sizes. Panels then follow the user's theme and UI scale, and look like the editor's own. See Ui for every control.
KroysEngine 0.1.0 documentation, built from the engine repository by Tools/BuildDocsSite.py.