Skip to content

Editor API

Namespace GodotECS.Editor, plus the plugin entry point (global class). Editor tooling: debugger dock, entity inspector backend, AABB gizmos, and the bake button. See Editor tools for workflows.

plugin

csharp
[Tool]
public partial class plugin : EditorPlugin
{
    public override void _EnterTree();
    public override void _ExitTree();
}

Compiled only with TOOLS. _EnterTree() adds an EntityDebuggerDock { Name = "ECS Debugger" } to DockSlot.LeftUr; _ExitTree() removes and frees it. Registered via addons/godotecs/plugin.cfg (name="GodotECS", version="0.1.0", script="plugin.cs").

EntityDebuggerDock

csharp
public partial class EntityDebuggerDock : Control
{
    public const int TimingCapacity = 120;

    public bool Paused { get; private set; }
    public bool StepPending { get; }
    public World CurrentWorld { get; private set; }
    public int TimingCount { get; }

    public EntityDebuggerDock();

    public void RegisterTiming(float ms);
    public void ClearTimings();
    public float AverageMs();
    public float[] GetTimingsOrdered();
    public void SetPaused(bool paused);
    public void TogglePause();
    public void RequestStep();
    public bool ConsumeStep();
    public World[] GetWorlds();
    public void SelectWorld(int index);
    public static ulong ComputeHash(World w);
    public void RefreshNow();
    public override void _Ready();
    public override void _Process(double delta);
}
  • TimingCapacity — ring-buffer size (120 samples).
  • Constructor sets CurrentWorld = World.Default.
  • RegisterTiming(float ms) — pushes a sample; negative/NaN/infinite values are stored as 0. Redraws the graph when in the tree.
  • ClearTimings() — empties the buffer.
  • AverageMs() — mean over stored samples (0 when empty).
  • GetTimingsOrdered() — oldest-first copy of the stored samples.
  • SetPaused(bool) — sets Paused and updates the pause button label ("Riprendi" / "Pausa"). TogglePause() flips it.
  • RequestStep() — arms the one-shot step flag (StepPending); ConsumeStep() returns false when disarmed, else disarms and returns true.
  • GetWorlds(){ World.Default, World.Preview }. SelectWorld(int index) — switches CurrentWorld (out-of-range ignored, keeps selection) and refreshes.
  • ComputeHash(World w)Snapshot.Hash(w).
  • RefreshNow() — no-op until _Ready() built the UI or when CurrentWorld is null. Otherwise updates the info label (World / Tick / Live / Query(All) count, -1 on query failure), the hash label (Snapshot.Save + HashBytes, err <Exception> on failure), the timing label, and the graph.
  • _Ready() — builds the UI (world selector, labels, graph, pause/step/refresh buttons) and refreshes. _Process(double delta) — records delta * 1000 ms when unpaused and refreshes every 0.5 s.

TimingGraph

Nested inside EntityDebuggerDock (sealed partial class TimingGraph : Control, constructed with its owning dock). Custom _Draw(): dark background rect, one green bar per stored sample scaled to 1.2 × max, and a yellow horizontal line at the average. No public members beyond the constructor.

EntityInspector

csharp
public partial class EntityInspector : Node
{
    public void RegisterMapping(int multimeshInstanceId, int instanceIndex, Entity entity);
    public bool TryGetEntity(int multimeshInstanceId, int instanceIndex, out Entity entity);
    public bool UnregisterMapping(int multimeshInstanceId, int instanceIndex);
    public void ClearMappings();
    public int MappingCount { get; }
    public Godot.Collections.Dictionary Inspect(World world, Entity entity);
    public Godot.Collections.Dictionary InspectWith<T>(World world, Entity entity)
        where T : struct, IComponentData;
}
  • Mapping key packs both ids: (long)(uint)multimeshInstanceId << 32 | (uint)instanceIndex. TryGetEntity returns false on miss; UnregisterMapping returns whether an entry was removed.
  • Inspect(World world, Entity entity)Dictionary with world (name), tick (int), index, version, alive, liveCount. Null world → World.Default.
  • InspectWith<T>(World world, Entity entity)Inspect plus has_<TypeName> (bool) and, when present, data_<TypeName> (ToString() of the component or err:<Exception>).

EcsGizmos

csharp
public partial class EcsGizmos : Node3D
{
    public bool ShowGizmos { get; set; }
    public int BoxCount { get; }
    public override void _Ready();
    public void AddBox(in GodotECS.Math.Aabb box);
    public void SetBoxes(IEnumerable<GodotECS.Math.Aabb> boxes);
    public void ClearBoxes();
    public override void _Process(double delta);
    public void Rebuild();
}
  • ShowGizmos — master toggle, default true. BoxCount — queued box count.
  • AddBox appends, SetBoxes replaces (null → empty), ClearBoxes empties; all mark the mesh dirty.
  • Rebuild() — recreates the internal ImmediateMesh/MeshInstance3D nodes if missing, clears surfaces, and emits 12 line edges per box (unshaded green, shadow-casting off). No-op other than clearing the dirty flag when empty or hidden.
  • _Process(double) — hides the mesh node when ShowGizmos is false or the node is off-tree; otherwise shows it and rebuilds only when dirty.

BakeTool

csharp
public partial class BakeTool : VBoxContainer
{
    public string LastStatus { get; private set; }
    public override void _Ready();
    public bool TryBake();
    public bool TryBake(Node root);
}
  • LastStatus — starts "idle"; mirrored to the status label.
  • TryBake() — reflects over GodotECS.Authoring.Baker for a zero-parameter static BakeAll / Bake / BakeWorld / BakeActiveScene; invokes the first found, status baked:<name> (or bake-failed:<name> + warning when it returns false).
  • TryBake(Node root) — with non-null root prefers static BakeSubtreeInto(World.Preview, root) → status baked-subtree:<n>, else BakeSubtree(root)baked-subtree; with null root falls back to TryBake().
  • Failure modes (all return false, warn, leave scenes untouched): Baker type absent → baker-missing; no known entry point → baker-no-entrypoint; exception → bake-error.

GodotECS docs — version 0.1.0. All rights reserved until a license is added.