KROYSDOCS
HomeWhat's newv0.1.0
MANUAL / Extend the editor / Your first C# plugin

Your first C# plugin

Build a small panel for the editor in C#, change it while the editor runs, and give it a command you can undo. About ten minutes.

You needA project open in the editor
LanguageC# · .NET 10
Code editorAny; VS Code is set up for you

Editor plugins add panels, commands, settings pages, importers, asset types and viewport tools. You write them in C#, save, and the running editor rebuilds and reloads them. You do not install .NET: the editor builds plugins with the engine's own pinned SDK.

01

Create the plugin

  1. Tools › Plugins › New Editor Plugin (C#)..., or New C# Plugin... in the Plugin Manager.
  2. Type a name, for example Level Tools.
  3. Keep In project (the plugin lives in <project>/Plugins/LevelTools/ and travels with the project) and Start from: Blank.
  4. Press Create.

The editor writes the plugin folder, enables the plugin for the project, builds it (a Build C# plugin task in the Tasks panel) and loads it. No restart: its panel, Level Tools, opens, and the folder opens in your code editor.

LevelTools/
LevelTools/
  LevelTools.kplugin     the manifest: id, version, what the plugin may use
  LevelTools.csproj      the C# project (references KroysPlugins.Sdk.dll)
  Plugin.cs              your code
  .vscode/               attach-debugger and build settings for VS Code
Build C# plugin · LevelTools succeeded
Plugin loaded · panel Level Tools opened
02

Draw a panel

A plugin is one class derived from EditorPlugin. In OnLoad it registers what it adds through Host; here a panel with a button and a counter.

The panel is drawn every frame it is visible (immediate mode): each ui.* call draws one control and returns true when the user clicked or changed it. Panels use the editor's own controls and theme, so a plugin looks like part of the editor.

Plugin.cs
public sealed class LevelToolsPlugin : EditorPlugin
{
    private int clicks;

    public override void OnLoad()
    {
        Host.AddPanel(new PanelOptions("Main", "Level Tools") { Icon = "plug" }, DrawPanel);
    }

    private void DrawPanel(Ui ui)
    {
        ui.Heading("Level Tools");
        if (ui.Button("Count", ButtonStyle.Primary)) clicks++;
        ui.SameLine();
        ui.Text($"Clicks: {clicks}");
    }
}
03

Change it while it runs

Add a line to DrawPanel and save. The editor notices within half a second, builds the plugin in the background and hot-reloads it: the panel shows your change and keeps its place in the layout.

A reload removes every registration of the old build, calls OnUnload, unloads the old assembly and calls OnLoad on a new instance. Fields start fresh; values saved with Host.SetSetting stay.

If it does not compileThe previous build keeps running. The error appears in the Console as Plugin.cs(14,9): error CS1002: ; expected; click it to jump to the line.
If it throwsAn exception in your code is caught and shown in the Console with its stack. The plugin pauses (Faulted) until you save a fix; the editor keeps running.
Plugin.cs, edited
ui.Heading("Level Tools");
if (ui.Button("Count clicks", ButtonStyle.Primary)) clicks += 1;
ui.SameLine();
ui.Text($"Clicks: {clicks}");
ui.Text("Hello from my first plugin!");   // saved: the editor rebuilds and reloads
Saved Plugin.cs
Build C# plugin · LevelTools succeeded
Reloaded · panel kept its place
04

Make a change you can undo

Commands appear in Tools › Plugins, in the command palette (Ctrl+Shift+P) and, with Toolbar = true, on the viewport's plugin toolbar. This one lifts the selected entities by one metre. Everything inside Host.Transaction is one undo step, named after the transaction, so Ctrl+Z reverts the whole command.

What a plugin may use is declared in its manifest. The blank template declares capability commands panels settings services tasks automation and permission scene.read scene.write; a call outside them fails with a message naming the line to add. See Manifest and permissions.

Plugin.cs
public override void OnLoad()
{
    Host.AddPanel(new PanelOptions("Main", "Level Tools") { Icon = "plug" }, DrawPanel);
    Host.AddCommand(new CommandOptions("Lift", "Lift Selection") { Toolbar = true, Icon = "arrow-up", Shortcut = "Ctrl+Shift+L" }, Lift);
}

private void Lift()
{
    World scene = Host.Document ?? throw new InvalidOperationException("Open a scene first.");
    using (Host.Transaction("Lift Selection"))        // one undo step for the whole edit
    {
        foreach (Entity entity in Host.Selection)
        {
            Transform transform = scene.GetTransform(entity);
            transform.Position += new Vector3(0.0f, 1.0f, 0.0f);
            scene.SetTransform(entity, transform);
        }
    }
}
05

Debug it

In VS Code, run Attach to Kroys Editor (.vscode/launch.json), set a breakpoint and use the plugin. Builds include symbols. After a reload, attach again if the debugger lost the old module.

Next: Panels and controls.

KroysEngine 0.1.0 documentation, built from the engine repository by Tools/BuildDocsSite.py.