o
odinpkg.dev
packages / library / Odin-ImReflect

Odin-ImReflect

33410a1library

A package for producing ImGui UI elements for data using Odin type reflection.

MIT · updated 4 months ago

ImReflect

An Odin package built on top of Dear ImGui that uses Odin's runtime type reflection to automatically generate editable inspector UI for any value at runtime.


Overview

ImReflect walks the Odin type system at runtime and renders an appropriate ImGui widget for every field it encounters. Pass any value to draw_value and get a full recursive inspector tree.

This makes it ideal for:

  • Game/engine tooling — inspect entity components, settings structs, or world state while the program is running.
  • Debugging — see and edit live data without recompiling or adding print statements.
  • Rapid prototyping — expose tunable parameters instantly without writing any UI code.

Usage

The entire public API is a single procedure:

draw_value :: proc(name: string, value: any, flags: Draw_Flags = nil)

Call it inside your ImGui frame, inside any window:

imgui.Gui_Begin("Inspector", nil, nil)

imrefl.draw_value("my_struct", my_struct)

imgui.Gui_End()

That's it. ImReflect will recursively build the entire UI for you.

Tags

ImReflect parses struct tags using the key imrefl to get extra formatting information.

My_Struct :: struct {
    editable_field:  int,
    _:           [4]byte `imrefl:"padding"`,
    read_only_field: int `imrefl:"read-only"`,
}
Tag Flag Description
read-only Read_Only Disables all editable widgets, rendering the value for inspection only.
padding Padding Used to stop a struct field from being drawn.
callable Callable Used to add a button to call a proc type with. The function should only accept one paramater, a pointer to the struct containing the function. Any return values are ignored.

You can also pass flags directly to draw_value.

Quick Start with the Bootstrap Package

If you just want to get something on screen as fast as possible, the bootstrap sub-package wraps all of the GLFW + OpenGL3 + ImGui initialisation boilerplate into four calls:

import imrefl      "path/to/imreflect"
import bootstrap   "path/to/imreflect/bootstrap"

main :: proc() {
    if !bootstrap.init() {
        return
    }
    defer bootstrap.shutdown()

    my_data: My_Struct
    // ... populate my_data ...

    for bootstrap.start_frame("Inspector") {
        imrefl.draw_value("my_data", my_data)
        bootstrap.end_frame() // Calls free_all(context.temp_allocator)
    }
}

Note: The bootstrap package is intentionally minimal — it is designed for quick inspection and demos. For production use you will want to manage your own window, context, and render loop.

Full Example

The demo package exercises nearly every supported type using the bootstrap package. See demo/demo.odin for the full source.

To run the demo yourself:

odin run demo

Known Limitations & TODOs

  • String editing — string types are read-only.
  • 128-bit types — not yet supported due to ImGui having no native 128-bit scalar type.
  • Multi-pointers ([^]T) — length information is not available via reflection, so only the raw address is shown. A future struct tag may be able to annotate a length.
  • Enumerated arrays — tree node is rendered but element iteration is not yet implemented.
  • SOA pointers — tree node renders but no data is displayed.
  • Struct tags — plans to add more tags to allow for more control over field formatting.

License

MIT License — see LICENSE for details.

Copyright (c) 2026 Alex Davis