8.19.45. Color

Five shapes for picking a color: two inline editors, two pop-out pickers, and one caller-owned swatch:

color_edit3(IDENT, (text = ".."))           // inline RGB row
color_edit4(IDENT, (text = ".."))           // inline RGBA row (+ alpha)
color_picker3(IDENT, (text = ".."))         // full picker wheel, RGB
color_picker4(IDENT, (text = "..",          // same, optional ref swatch
                      flags = ...,
                      ref_col = float4(...),
                      has_ref_col = true))
color_button(IDENT, "##desc", col)          // click-trigger swatch;
                                            //   caller owns `col`

State types:

  • color_edit3 / color_picker3ColorState3 (value : float3)

  • color_edit4 / color_picker4ColorState4 (value : float4 incl. alpha)

  • color_buttonClickState (color is caller-owned)

Source: modules/dasImgui/examples/tutorial/color.das.

8.19.45.1. Walkthrough

  1options gen2
  2options _comment_hygiene = true
  3options gc
  4
  5require imgui
  6require imgui_app
  7require opengl/opengl_boost
  8require live/glfw_live
  9require live/live_api
 10require live/live_commands
 11require live/live_vars
 12require live_host
 13require imgui/imgui_live
 14require imgui/imgui_boost_runtime
 15require imgui/imgui_boost_v2
 16require imgui/imgui_widgets_builtin
 17require imgui/imgui_containers_builtin
 18require imgui/imgui_visual_aids
 19
 20// =============================================================================
 21// TUTORIAL: color — four shapes of color editing + one click trigger.
 22//
 23//   color_edit3(IDENT, (text = ".."))         — inline RGB editor.
 24//   color_edit4(IDENT, (text = ".."))         — inline RGBA (adds alpha row).
 25//   color_picker3(IDENT, (text = ".."))       — popout wheel + RGB sliders.
 26//   color_picker4(IDENT, (text = "..",        — same, plus optional ref swatch.
 27//                         has_ref_col = true,
 28//                         ref_col = float4(...)))
 29//   color_button(IDENT, "##desc", col)        — click-trigger swatch; caller
 30//                                                owns `col`. Use to surface a
 31//                                                style-palette row or to open
 32//                                                a custom picker popup.
 33//
 34// State types:
 35//   - color_edit3 / color_picker3 → ColorState3 (value : float3)
 36//   - color_edit4 / color_picker4 → ColorState4 (value : float4 incl. alpha)
 37//   - color_button                → ClickState  (color is caller-owned)
 38//
 39// STANDALONE: daslang.exe modules/dasImgui/examples/tutorial/color.das
 40// LIVE:       daslang-live modules/dasImgui/examples/tutorial/color.das
 41//
 42// DRIVE (when running live):
 43//   curl -X POST -d '{"name":"imgui_force_set","args":{"target":"CO_WIN/CO_EDIT3","value":[1.0,0.5,0.0]}}' \
 44//        localhost:9090/command
 45//   curl -X POST -d '{"name":"imgui_force_set","args":{"target":"CO_WIN/CO_EDIT4","value":[0.2,0.4,0.9,0.6]}}' \
 46//        localhost:9090/command
 47//   curl -X POST -d '{"name":"imgui_click","args":{"target":"CO_WIN/CO_SWATCH"}}' \
 48//        localhost:9090/command
 49// =============================================================================
 50
 51let SWATCH_COLOR : float4 = float4(0.85f, 0.20f, 0.20f, 1.0f)
 52let REF_COLOR    : float4 = float4(0.10f, 0.55f, 0.95f, 1.0f)
 53
 54[export]
 55def init() {
 56    live_create_window("dasImgui color tutorial", 800, 700)
 57    live_imgui_init(live_window)
 58    let io & = unsafe(GetIO())
 59    GetStyle().FontScaleMain = 1.4
 60}
 61
 62[export]
 63def update() {
 64    if (!live_begin_frame()) return
 65    begin_frame()
 66
 67    ImGui_ImplGlfw_NewFrame()
 68    apply_synth_io_override()
 69    NewFrame()
 70
 71    SetNextWindowPos(ImVec2(20.0f, 20.0f), ImGuiCond.Always)
 72    SetNextWindowSize(ImVec2(760.0f, 660.0f), ImGuiCond.Always)
 73    window(CO_WIN, (text = "color tutorial", closable = false,
 74                    flags = ImGuiWindowFlags.None)) {
 75
 76        text("Four edit shapes + one click trigger.")
 77        text(CO_HINT, (text = "edit_* is inline; picker_* is the open square + hue bar; color_button is a swatch."))
 78        separator()
 79
 80        // ---- Stage 1: color_edit3 — inline RGB ----
 81        color_edit3(CO_EDIT3, (text = "tint (RGB)"))
 82        text("CO_EDIT3.value = ({CO_EDIT3.value.x:.2f}, {CO_EDIT3.value.y:.2f}, {CO_EDIT3.value.z:.2f})")
 83        spacing()
 84
 85        // ---- Stage 2: color_edit4 — inline RGBA ----
 86        color_edit4(CO_EDIT4, (text = "tint (RGBA)"))
 87        text("CO_EDIT4.value.a = {CO_EDIT4.value.w:.2f}  // 4-form adds alpha")
 88        spacing()
 89
 90        // ---- Stage 3: color_picker4 — popout wheel + ref swatch ----
 91        color_picker4(CO_PICKER, (text = "picker",
 92                                  flags = ImGuiColorEditFlags.None,
 93                                  ref_col = REF_COLOR,
 94                                  has_ref_col = true))
 95        text("CO_PICKER.value = ({CO_PICKER.value.x:.2f}, {CO_PICKER.value.y:.2f}, {CO_PICKER.value.z:.2f}, {CO_PICKER.value.w:.2f})")
 96        spacing()
 97
 98        // ---- Stage 4: color_button — caller-owned color, click trigger ----
 99        text("Swatch (click triggers - value is caller-owned, not widget state):")
100        if (color_button(CO_SWATCH, (desc_id = "##swatch", col = SWATCH_COLOR,
101                                     size = float2(96.0f, 48.0f)))) {
102            // Hook: open a custom picker popup, copy to clipboard, etc.
103        }
104        text("CO_SWATCH clicks = {CO_SWATCH.click_count}")
105    }
106
107    end_of_frame()
108    Render()
109    var w, h : int
110    live_get_framebuffer_size(w, h)
111    glViewport(0, 0, w, h)
112    glClearColor(0.10f, 0.10f, 0.12f, 1.0f)
113    glClear(GL_COLOR_BUFFER_BIT)
114    live_imgui_render()
115
116    live_end_frame()
117}
118
119[export]
120def shutdown() {
121    live_imgui_shutdown()
122    live_destroy_window()
123}
124
125[export]
126def main() {
127    init()
128    while (!exit_requested()) {
129        update()
130        maybe_collect_gc()
131    }
132    shutdown()
133}

8.19.45.1.1. Requires

Already in the baseline boost layer:

  • imgui/imgui_widgets_builtincolor_edit3/4 / color_picker3/4 / color_button rails.

  • imgui/imgui_boost_runtimeColorState3 / ColorState4 / ClickState structs.

The caller-owned form at the end of this page also needs daslib/safe_addr for safe_addr.

8.19.45.1.2. edit vs picker

The two families differ in shape, not in semantics:

  • color_edit* — inline row: small swatch + numeric fields. Clicking the swatch pops up ImGui’s stock picker. Best for “tweak a value beside other inputs.”

  • color_picker* — always-visible wheel + RGB sliders. Heavier on screen; best for “this dialog is for picking a color.”

Both write to state.value (float3 / float4). state.changed mirrors ImGui’s per-frame “did it change” return — same in both families.

The 3 vs 4 suffix is alpha:

  • 3float3, no alpha row.

  • 4float4 (.a is the alpha row), and the picker variant takes optional ref_col + has_ref_col = true to surface a comparison swatch alongside the new color.

8.19.45.1.3. color_button — click trigger, caller-owned color

The asymmetry: color_button does NOT have a ColorState — it takes the color inline as col : float4 and stores only click bookkeeping. Use it for cells in a palette grid or as the trigger for a custom picker popup:

let RED : float4 = float4(0.85f, 0.20f, 0.20f, 1.0f)
if (color_button(SWATCH, (desc_id = "##red", col = RED,
                           size = float2(96.0f, 48.0f)))) {
    // open a custom popup, set the active palette index, etc.
}

desc_id is the ImGui label (typically "##name" to suppress visible text). size = (0, 0) lets ImGui pick a default square.

For a swatch that reports hover without click bookkeeping, see Color button hover.

8.19.45.1.4. Flags

flags : ImGuiColorEditFlags carries the standard edit-mode toggles — NoAlpha, NoPicker, NoOptions, NoSmallPreview, NoInputs, NoTooltip, NoLabel, NoSidePreview, NoDragDrop, NoBorder, NoColorMarkers, AlphaBar, AlphaOpaque, AlphaNoBg, AlphaPreviewHalf, HDR, plus display-mode bits (DisplayRGB / DisplayHSV / DisplayHex), data-type bits (Uint8 / Float), picker-shape bits (PickerHueBar / PickerHueWheel) and input-mode bits (InputRGB / InputHSV). Composable via |:

color_edit4(TINT, (text = "tint",
                   flags = ImGuiColorEditFlags.NoInputs |
                           ImGuiColorEditFlags.AlphaBar))

8.19.45.1.5. Driving from outside

# RGB editor / picker — 3-element value
curl -X POST -d '{"name":"imgui_force_set","args":{"target":"CO_WIN/CO_EDIT3","value":[1.0,0.5,0.0]}}' \
     localhost:9090/command
# RGBA editor / picker — 4-element value
curl -X POST -d '{"name":"imgui_force_set","args":{"target":"CO_WIN/CO_EDIT4","value":[0.2,0.4,0.9,0.6]}}' \
     localhost:9090/command
# color_button — click trigger
curl -X POST -d '{"name":"imgui_click","args":{"target":"CO_WIN/CO_SWATCH"}}' \
     localhost:9090/command

8.19.45.1.6. Caller-owned variants

For sites where the value lives on an external float3 / float4, use the edit_* rails — they take a T? pointer via safe_addr and skip the state-struct allocation:

var g_tint : float4 = float4(1.0f, 1.0f, 1.0f, 1.0f)
edit_color_edit4(safe_addr(g_tint), (id = "TINT", text = "tint"))

See External-pointer editing rail.

See also

Full source: modules/dasImgui/examples/tutorial/color.das

Hover variant: Color button hover — swatch as a per-frame hover surface, no click bookkeeping.

Sibling tutorial: Buttons (the broader click-trigger family).

Boost macros — the macro layer.