terminalCode Example

Custom editor tools — EditorTool, Gizmo drawing, scene tracing, and overlay UI

calendar_today May 5, 2026 schedule ~1 min read person patrickjr verified 50

Custom Editor Tools

Editor tools appear in the s&box toolbar and let you build scene editing workflows — painting, placement, custom gizmos. They must live in an editor project.

Minimal Tool

CSHARP
[EditorTool]
[Title( "Sprinkle Tool" )]
[Icon( "scatter_plot" )]           // Material Symbols icon name
[Shortcut( "editortool.sprinkle", "u" )]
public class SprinkleTool : EditorTool
{
    public override void OnEnabled()
    {
        AllowGameObjectSelection = false;  // prevent accidental selection
    }

    public override void OnUpdate()
    {
        // Trace against render meshes to find placement point
        var tr = Scene.Trace
            .Ray( Gizmo.CurrentRay, 5000f )
            .UseRenderMeshes( true )
            .UsePhysicsWorld( false )
            .Run();

        if ( !tr.Hit ) return;

        // Draw a preview gizmo at the hit point
        using ( Gizmo.Scope( "preview" ) )
        {
            Gizmo.Transform = new Transform( tr.HitPosition, Rotation.LookAt( tr.Normal ) );
            Gizmo.Draw.LineCircle( Vector3.Zero, 50f );
            Gizmo.Draw.Arrow( Vector3.Zero, Vector3.Up * 30f );
        }

        // Place on click
        if ( Gizmo.WasLeftMousePressed )
            PlaceObject( tr.HitPosition, tr.Normal );
    }

    void PlaceObject( Vector3 pos, Vector3 normal )
    {
        var go = Scene.CreateObject();
        go.Name = "Sprinkled";
        go.WorldPosition = pos;
        go.WorldRotation = Rotation.LookAt( normal );
        go.Tags.Add( "sprinkled" );
    }
}

Overlay UI

Add a floating widget panel to the scene viewport:

CSHARP
public override void OnEnabled()
{
    var window = new WidgetWindow( SceneOverlay );
    window.Layout = Layout.Column();
    window.Layout.Margin = 16;

    var slider = new Slider();
    slider.Minimum = 1f;
    slider.Maximum = 200f;
    slider.Value   = 50f;
    window.Layout.Add( new Label( "Radius" ) );
    window.Layout.Add( slider );

    // AddOverlay ensures the window is destroyed when the tool is deactivated
    AddOverlay( window, TextFlag.LeftTop, 10 );
}

Gizmo Drawing Reference

CSHARP
using ( Gizmo.Scope( "my_gizmo" ) )
{
    Gizmo.Transform = someTransform;

    Gizmo.Draw.Color = Color.Green;
    Gizmo.Draw.LineSphere( Vector3.Zero, 32f );
    Gizmo.Draw.LineCircle( Vector3.Zero, 64f );
    Gizmo.Draw.Arrow( Vector3.Zero, Vector3.Up * 50f );
    Gizmo.Draw.ScreenText( Vector3.Zero, "Label", size: 14 );
}
Was this helpful?