Skip to content

Gizmos

The @shell/gizmos package provides 2D debug and editor visualization for the ECS world. It supports both immediate-mode (one-frame) drawing and retained-mode (persistent) components, all rendered via PixiJS on top of the scene.


Add GizmoPlugin to the world after PixiPlugin:

import { GizmoPlugin } from '@shell/gizmos';
world.addPlugin(GizmoPlugin);

This registers the Gizmos resource (IoC key: 'gizmos'), five gizmo components, and two systems:

  • GizmoClearSystem at Schedule.PreUpdate — clears immediate-mode draw buffers
  • GizmoRenderSystem at Schedule.PreRender — renders everything via PixiJS Graphics

Both systems run only when gizmos.enabled is true and both run in edit mode.


Draw one-frame shapes inside a system update. Commands are cleared automatically at PreUpdate.

.update(({ resources }) => {
const gizmos = resources.get('gizmos');
gizmos.line({ x: 0, y: 0 }, { x: 100, y: 0 }, { color: 0xff0000 });
gizmos.circle({ x: 200, y: 200 }, 50, { color: 0x00ff00, layer: 'physics' });
})

Attach gizmo components to entities for persistent visuals. Each component requires the canonical Transform component from @shell/transform.

import { GizmoCircle } from '@shell/gizmos';
import { Transform } from '@shell/transform';
commands.spawn(
Define.prefab()
.with(Transform, { x: 100, y: 100 })
.with(GizmoCircle, { radius: 50, color: 0xff0000 }),
);

Gizmos are organized into named layers with independent visibility and depth sorting.

const gizmos = resources.get('gizmos');
gizmos.setLayer('physics', { zIndex: 10 });
gizmos.setLayer('ai', { zIndex: 5, enabled: false });
gizmos.enableLayer('physics');
gizmos.disableLayer('ai');
gizmos.isLayerEnabled('physics'); // true

The 'default' layer exists at zIndex: 0 automatically. Draw calls to a disabled layer are discarded. Component gizmos on a disabled layer are skipped during rendering.