8.19.40. Slider widgets

The slider family is bounded numeric editing along a fixed track: click the track to jump, drag the handle to scrub. Same call shape spans scalar / vector / vertical and float / int — ten widgets, one mental model.

slider_float(IDENT, (text = "..", format = "%.3f",
                     flags = ImGuiSliderFlags....))
slider_int(IDENT, (text = "..", format = "%d"))
slider_float2 / slider_float3 / slider_float4   // vector forms
slider_int2   / slider_int3   / slider_int4
vslider_float(IDENT, (text, size = float2(w, h), format = "%.3f"))
vslider_int(IDENT, (text, size, format))

Bounds are required — slider has a fixed-width track between (state.bounds.min, state.bounds.max). Unlike drag, zero-init bounds (0, 0) collapses the track to a single point.

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

8.19.40.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: slider widgets — bounded numeric editing along a fixed track.
 22//
 23//   slider_float(IDENT, (text = "..", format = "%.3f",
 24//                        flags = ImGuiSliderFlags....))
 25//   slider_int / slider_float2/3/4 / slider_int2/3/4 / vslider_float /
 26//   vslider_int — same shape; scalar / vector / vertical variants.
 27//
 28// Bounds REQUIRED — slider has a fixed-width track between
 29// (state.bounds.min, state.bounds.max). Unlike drag, zero-init bounds
 30// = (0, 0) collapses the track to a single value.
 31//
 32// vslider takes a `size : float2` arg (width, height) and renders the
 33// track top-to-bottom; otherwise identical to slider_float.
 34//
 35// STANDALONE: daslang.exe modules/dasImgui/examples/tutorial/slider.das
 36// LIVE:       daslang-live modules/dasImgui/examples/tutorial/slider.das
 37//
 38// DRIVE (when running live):
 39//   curl -X POST -d '{"name":"imgui_force_set","args":{"target":"SLIDER_WIN/S_FLOAT","value":0.8}}' \
 40//        localhost:9090/command
 41//   curl -X POST -d '{"name":"imgui_force_set","args":{"target":"SLIDER_WIN/S_VEC3","value":[1.0,2.0,3.0]}}' \
 42//        localhost:9090/command
 43// =============================================================================
 44
 45[export]
 46def init() {
 47    live_create_window("dasImgui slider tutorial", 760, 520)
 48    live_imgui_init(live_window)
 49    let io & = unsafe(GetIO())
 50    GetStyle().FontScaleMain = 1.4
 51}
 52
 53[export]
 54def update() {
 55    if (!live_begin_frame()) return
 56    begin_frame()
 57
 58    ImGui_ImplGlfw_NewFrame()
 59    apply_synth_io_override()
 60    NewFrame()
 61
 62    SetNextWindowPos(ImVec2(20.0f, 20.0f), ImGuiCond.Always)
 63    SetNextWindowSize(ImVec2(720.0f, 480.0f), ImGuiCond.Always)
 64    window(SLIDER_WIN, (text = "slider tutorial", closable = false,
 65                        flags = ImGuiWindowFlags.None)) {
 66
 67        text("Click anywhere on the track to jump; drag the handle to scrub.")
 68        text(S_HINT, (text = "Bounds REQUIRED - track spans (lo, hi) literally."))
 69        separator()
 70
 71        // ---- Stage 1: scalar float, 0..1 ----
 72        S_FLOAT.bounds = (0.0f, 1.0f)
 73        slider_float(S_FLOAT, (text = "volume", format = "%.2f"))
 74        text("S_FLOAT.value = {S_FLOAT.value}")
 75        spacing()
 76
 77        // ---- Stage 2: scalar int, 0..100 ----
 78        S_INT.bounds = (0, 100)
 79        slider_int(S_INT, (text = "percent", format = "%d%%"))
 80        text("S_INT.value = {S_INT.value}")
 81        spacing()
 82
 83        // ---- Stage 3: vector — three handles on one row ----
 84        S_VEC3.bounds = (-1.0f, 1.0f)
 85        slider_float3(S_VEC3, (text = "rotation", format = "%.2f"))
 86        text("S_VEC3.value = ({S_VEC3.value.x}, {S_VEC3.value.y}, {S_VEC3.value.z})")
 87        spacing()
 88
 89        // ---- Stage 4: vertical orientation — same state, different layout ----
 90        text("Vertical sliders (vslider_float) share SliderStateFloat:")
 91        V_LO.bounds = (0.0f, 1.0f)
 92        V_MID.bounds = (0.0f, 1.0f)
 93        V_HI.bounds = (0.0f, 1.0f)
 94        vslider_float(V_LO, (text = "##lo",
 95                             size = float2(36.0f, 140.0f), format = "%.2f"))
 96        same_line(SLINE_1)
 97        vslider_float(V_MID, (text = "##mid",
 98                              size = float2(36.0f, 140.0f), format = "%.2f"))
 99        same_line(SLINE_2)
100        vslider_float(V_HI, (text = "##hi",
101                             size = float2(36.0f, 140.0f), format = "%.2f"))
102    }
103
104    end_of_frame()
105    Render()
106    var w, h : int
107    live_get_framebuffer_size(w, h)
108    glViewport(0, 0, w, h)
109    glClearColor(0.10f, 0.10f, 0.12f, 1.0f)
110    glClear(GL_COLOR_BUFFER_BIT)
111    live_imgui_render()
112
113    live_end_frame()
114}
115
116[export]
117def shutdown() {
118    live_imgui_shutdown()
119    live_destroy_window()
120}
121
122[export]
123def main() {
124    init()
125    while (!exit_requested()) {
126        update()
127        maybe_collect_gc()
128    }
129    shutdown()
130}

8.19.40.1.1. Requires

Already in the baseline boost layer:

  • imgui/imgui_widgets_builtin — every slider_* / vslider_* rail.

  • imgui/imgui_boost_runtimeSliderStateFloat / SliderStateInt / vector state structs.

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

8.19.40.1.2. Bounds

Bounds are a property of the state, not the call. Set them every frame (idempotent assignment, no branching):

S_FLOAT.bounds = (0.0f, 1.0f)
slider_float(S_FLOAT, (text = "volume", format = "%.2f"))

The wrapper passes (min, max) to ImGui’s SliderFloat which constrains the handle. Unlike Drag widgets, zero bounds are not unclamped — the track has nowhere to render.

8.19.40.1.3. Format

format is the printf-style label format. Default "%.3f" / "%d"; customize for units:

slider_int(S_INT, (text = "percent", format = "%d%%"))    // 42%
slider_float(S_TEMP, (text = "temp", format = "%.1f °C")) // 23.5 °C

8.19.40.1.4. Vector forms

The 2 / 3 / 4 suffix puts that many handles on one row. state.value becomes float2 / float3 / float4 (or int2 / int3 / int4):

S_VEC3.bounds = (-1.0f, 1.0f)        // applies to every component
slider_float3(S_VEC3, (text = "rotation", format = "%.2f"))
// S_VEC3.value.x, S_VEC3.value.y, S_VEC3.value.z

8.19.40.1.5. Vertical orientation

vslider_float / vslider_int share the same state struct as the horizontal form, but render the track top-to-bottom. The distinguishing arg is size : float2 (width, height):

V_MID.bounds = (0.0f, 1.0f)
vslider_float(V_MID, (text = "##mid",
                      size = float2(36.0f, 140.0f), format = "%.2f"))

Common pattern: three vslider_floats with same_line between them form a mixer-channel strip. The "##mid" text prefix hides the label (everything after ## is ID-only); use "label" instead to display it above the slider.

8.19.40.1.6. Driving from outside

Every slider exposes the same telemetry channel — imgui_force_set writes state.pending_value which the next frame consumes:

# Scalar:
curl -X POST -d '{"name":"imgui_force_set","args":{"target":"SLIDER_WIN/S_FLOAT","value":0.8}}' \
     localhost:9090/command
# Vector — one number per component:
curl -X POST -d '{"name":"imgui_force_set","args":{"target":"SLIDER_WIN/S_VEC3","value":[1.0,2.0,3.0]}}' \
     localhost:9090/command

The dispatcher ([widget_dispatch] on SliderStateFloat and friends) accepts the right JSON shape per state type — scalar number or array of numbers.

8.19.40.1.7. Slider vs drag vs input

The three numeric-edit families differ in interaction shape:

  • slider — click and drag along a fixed-width track between v_min / v_max. Best for bounded percentages, settings sliders.

  • drag — click and scrub, no fixed track. Best for “tweak this value” where the range is large or open-ended.

  • input — type the number, optionally with + / - step buttons. Best for precise values where the user knows the number.

All three families share the same vector / scalar / format conventions. See Drag widgets.

8.19.40.1.8. Caller-owned variant

For sites where the value lives on an external scalar (not a widget state struct), use the edit_slider_* rail instead — it takes a T? pointer via safe_addr and skips the state-struct allocation:

var g_volume : float = 0.5f
edit_slider_float(safe_addr(g_volume), (id = "VOLUME",
                                        text = "volume",
                                        v_min = 0.0f, v_max = 1.0f))

See External-pointer editing rail.

See also

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

Features-side demo: modules/dasImgui/examples/features/inputs_slider.das / modules/dasImgui/examples/features/edit_vsliders.das — every slider in one window, useful for imgui_force_set smoke testing.

Sibling tutorial: Drag widgets.

Boost macros — the macro layer.