> Cinder 0.1.0 documentation: cinder.tools API
> Canonical page: https://cinder.ash10.dev/docs/api/tools/ · Source: `docs/api/tools.md` in the engine repository (engine commit 47c9352, imported 2026-11-09)
> Index of every page for agents: https://cinder.ash10.dev/llms.txt

# `cinder.tools`


## `cinder.tools`

Source: `cinder/tools/__init__.mojo`

Developer tools: the ImGui debug overlay (frame graph, inspector, assets, render graph, log).


## `cinder.tools.cstrings`

Source: `cinder/tools/cstrings.mojo`

Frame-scoped C strings for immediate-mode UI calls. ImGui keeps label pointers only until the frame is rendered, and Mojo `String`s move when a list grows (inline small-string storage), so labels are copied into `List[UInt8]` buffers whose heap data stays put. Call `clear` once per frame after rendering.

### struct `CStrings`

```mojo
struct CStrings(Movable)
```

Owns NUL-terminated byte copies of strings handed to C; pointers from `c` stay valid until `clear`.

Fields:


- **`__init__`** `__init__(out self)`
- **`clear`** `clear(mut self)`  
  Frees every buffer; pointers returned by `c` become dangling.
- **`__len__`** `__len__(self) -> Int`
- **`c`** `c( mut self, text: String ) -> Optional[Pointer[c_char, MutUntrackedOrigin]]`  
  A NUL-terminated copy of `text`, valid until `clear`.


## `cinder.tools.debug_ui`

Source: `cinder/tools/debug_ui.mojo`

The ImGui debug overlay: frame-time graph and render stats, entity inspector (view and edit components through the scene registry), asset browser, render graph view and log console. ImGui runs through the shim's SDL3 + WebGPU backends (`cn_imgui_*`); widgets are the generated dcimgui bindings. The overlay draws into the frame's final render pass after the scene.

- `comptime HISTORY = 240` — Frames kept in the frame-time graph.
### struct `DebugUi`

```mojo
struct DebugUi(Movable)
```

The ImGui debug overlay. Construction initialises the shim's ImGui backend for the window and device (raising when that fails); destruction shuts it down. `App` creates it for windowed apps with `debug_ui` set and declares it first, so it is destroyed before the window and GPU device. Per frame: `begin_frame`, `draw`, then `render` into the final pass.

Fields:

- `lib`: NativePtr
- `frame_ms`: List[Float32] — Ring of the last `HISTORY` frame times in milliseconds.
- `frame_cursor`: Int
- `frames`: Int
- `selected`: Int — Index into the last entity snapshot (-1 = none).
- `entities`: List[Entity]
- `edits_applied`: Int
- `visible`: Bool
- `requested_tab`: Int — Tab to force-select on the next frame (-1 = none): 0 Frame, 1 Entities, 2 Assets, 3 Render graph, 4 Log.

- **`__init__`** `__init__( out self, lib: NativePtr, window: Optional[Pointer[SDL_Window, MutUntrackedOrigin]], device: WGPUDevice, format: WGPUTextureFormat, ) raises`
- **`begin_frame`** `begin_frame(mut self, dt_seconds: Float64)`  
  Records `dt_seconds` in the frame-time ring, frees the previous frame's labels and starts a new ImGui frame.
- **`render`** `render(self, pass_: RenderPass)`  
  Draws the accumulated ImGui data into an open render pass.
- **`wants_mouse`** `wants_mouse(self) -> Bool`  
  True when ImGui wants the mouse (`App` then keeps mouse events from the input map); False when ImGui has no IO.
- **`wants_keyboard`** `wants_keyboard(self) -> Bool`  
  True when ImGui wants the keyboard (`App` then keeps key events from the input map); False when ImGui has no IO.
- **`average_frame_ms`** `average_frame_ms(self) -> Float32`  
  Mean frame time in ms over the recorded frames (at most `HISTORY`); 0 before the first frame.
- **`draw`** `draw( mut self, mut world: World, registry: SceneRegistry, renderer: Renderer, assets: Optional[Pointer[AssetServer, MutUntrackedOrigin]], logs: List[LogRecord], physics_live: Int, audio_live: Int, ) raises`  
  Builds the overlay for this frame (between `begin_frame` and `render`).
- **`select_tab`** `select_tab(mut self, index: Int)`  
  Makes tab `index` the active one on the next `draw`.
