Line plot

The simplest ImPlot chart. A plot is an RAII scope — the plot container guarantees the matching EndPlot — and inside it each plot_line draws one y-series. ImPlot shares dasImgui’s ImGui context, so there is nothing to wire up beyond creating an ImPlotContext once. The plot container also serializes the plot’s per-frame state (geometry, axis limits, hovered, mouse position) into the snapshot, which is what lets a test or recording read and drive it.

g_ctx = implot::CreateContext()          // once, after the ImGui context
plot(WAVES, (title = "waves", size = float2(-1.0f, 620.0f), flags = ImPlotFlags.None)) {
    setup_axes("sample", "value")
    setup_axes_limits(0.0lf, 200.0lf, -1.5lf, 1.5lf)   // initial range, cond=Once
    plot_line("sin", g_sin)              // x = sample index
    plot_line("cos", g_cos)
}

Source: examples/tutorial/line_plot.das.

 1options gen2
 2
 3require imgui/imgui_harness
 4require imgui/imgui_containers_builtin
 5require imgui/imgui_widgets_builtin
 6require imgui/imgui_implot_boost_v2
 7require implot
 8require math
 9
10// =============================================================================
11// TUTORIAL: line_plot — the simplest ImPlot chart (v2 DSL).
12//
13//   plot(IDENT, (title, size, flags)) { ... }  — RAII plot scope; EndPlot can't be
14//       skipped, AND the scope serializes the plot's per-frame state (geometry,
15//       axis limits, hovered, mouse-plot-pos) into the snapshot, so a test/recording
16//       can read and drive it.
17//   setup_axes(x, y)                 — label the axes.
18//   setup_axes_limits(...)           — fix the INITIAL visible range (cond=Once by
19//       default, so the user can still pan/zoom afterward).
20//   plot_line(LABEL, ys)             — draw a y-series (x = sample index).
21//   plot_line(LABEL, xs, ys)         — or an explicit x/y series.
22//
23// ImPlot views are interactive out of the box: left-drag pans, the scroll wheel
24// zooms, and a double-click fits the axes back to the data.
25//
26// The ImPlot context is created once after the ImGui context (init) and destroyed
27// at shutdown. ImPlot shares dasImgui's ImGui context — nothing else to wire up.
28// Built on the dasImgui harness: runs standalone (windowed), headless, and live.
29//
30// STANDALONE: daslang.exe modules/dasImguiImplot/examples/tutorial/line_plot.das
31// LIVE:       daslang-live modules/dasImguiImplot/examples/tutorial/line_plot.das
32// =============================================================================
33
34var g_ctx : ImPlotContext?
35var g_sin : array<double>
36var g_cos : array<double>
37
38[export]
39def init() {
40    harness_init("dasImguiImplot — line_plot", 1100, 760)
41    g_ctx = implot::CreateContext()
42    g_sin <- [for (i in range(200)); double(sin(float(i) * 0.05f))]
43    g_cos <- [for (i in range(200)); double(cos(float(i) * 0.05f))]
44}
45
46[export]
47def update() {
48    if (!harness_begin_frame()) return
49    harness_new_frame()
50
51    SetNextWindowPos(float2(20.0, 20.0), ImGuiCond.Always)
52    SetNextWindowSize(float2(1060.0, 720.0), ImGuiCond.Always)
53    window(PLOT_WIN, (text = "line plot", closable = false,
54                      flags = ImGuiWindowFlags.None)) {
55        text("plot scopes the chart; each plot_line draws one series. Drag to pan, scroll to zoom.")
56        plot(WAVES, (title = "waves", size = float2(-1.0f, 620.0f), flags = ImPlotFlags.None)) {
57            setup_axes("sample", "value")
58            setup_axes_limits(0.0lf, 200.0lf, -1.5lf, 1.5lf)
59            plot_line("sin", g_sin)
60            plot_line("cos", g_cos)
61        }
62    }
63
64    harness_end_frame()
65}
66
67[export]
68def shutdown() {
69    if (g_ctx != null) {
70        DestroyContext(g_ctx)
71    }
72    harness_shutdown()
73}
74
75[export]
76def main() {
77    init()
78    while (!exit_requested()) {
79        update()
80    }
81    shutdown()
82}

Walkthrough

The ImPlot context

implot::CreateContext() returns an ImPlotContext? that holds ImPlot’s per-frame state. Create it once in init (after harness_init has made the ImGui context) and DestroyContext it at shutdown. The name is qualified implot:: because dasImgui also exports a CreateContext.

The plot scope

plot(IDENT, (title, size, flags)) { ... } opens a plot and closes it for you. A size of float2(-1.0f, 620.0f) means fill the available width, 620 px tall — the -1 sentinel is ImPlot’s “use the remaining space on that axis”. setup_axes labels the axes and setup_axes_limits fixes the initial visible range; both must run before any item is drawn in the scope. The limits default to ImPlotCond.Once, so they seed the first frame and then leave the user free to pan and zoom.

The IDENT (WAVES) is a bareword the container uses to register the plot in the snapshot — that is what distinguishes the v2 plot from the v1 imgui_implot_boost with_plot, which is otherwise the same scope but registers nothing.

View navigation

ImPlot views are interactive out of the box, and these gestures work on every plot in the rest of the tutorials:

  • Pan — left-drag inside the plot area; the whole view slides under the cursor.

  • Zoom — scroll the wheel over the plot; it zooms around the point under the cursor.

  • Fit — double-click anywhere in the plot to snap the axes back to the data bounds.

Because the gestures change the axis limits (and the plot scope serializes those), the recording above drives each one for real and asserts the limits actually moved — a no-op would fail the recording.

Items

plot_line(label, ys) draws ys against an implicit x = 0, 1, 2, (the sample index). The two-argument form plot_line(label, xs, ys) takes an explicit x series instead. The next tutorial, Multi series, adds scatter, bars, and per-item styling, and shows how to toggle a series from the legend.