Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified doc/source/_static/tutorials/bar_groups_and_pie.mp4
Binary file not shown.
Binary file modified doc/source/_static/tutorials/colormaps_and_style.mp4
Binary file not shown.
Binary file modified doc/source/_static/tutorials/drag_tools.mp4
Binary file not shown.
Binary file modified doc/source/_static/tutorials/heatmap_histogram.mp4
Binary file not shown.
Binary file modified doc/source/_static/tutorials/line_plot.mp4
Binary file not shown.
Binary file modified doc/source/_static/tutorials/multi_axes.mp4
Binary file not shown.
Binary file modified doc/source/_static/tutorials/multi_series.mp4
Binary file not shown.
Binary file modified doc/source/_static/tutorials/query_and_hover.mp4
Binary file not shown.
Binary file modified doc/source/_static/tutorials/realtime_scroll.mp4
Binary file not shown.
Binary file modified doc/source/_static/tutorials/shaded_and_stairs.mp4
Binary file not shown.
Binary file modified doc/source/_static/tutorials/subplots.mp4
Binary file not shown.
21 changes: 6 additions & 15 deletions tests/integration/record_bar_groups_and_pie.das
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,6 @@ let PIE = "PLOT_WIN/PIE"
let SERIES = "industrial"
let LEAD_MS = 800u

// Hold a beat's caption for the remainder of its voice dwell, measuring real elapsed
// work (gesture + verify) so the next say_begin can't fire early and overlap the voice.
def hold_remainder(dwell : uint; t0 : int64) {
let elapsed = uint(get_time_usec(t0) / 1000)
if (dwell > elapsed) {
sleep(dwell - elapsed)
}
}

[export]
def main {
with_implot_recording_app("examples/tutorial/bar_groups_and_pie.das", "bar_groups_and_pie.apng", 45) $(app) {
Expand All @@ -52,25 +43,25 @@ def main {
// ---- Beat 2: legend toggle on the grouped bars (hide across all groups, then restore) ----
let d_leg = say_begin(app, "toggle a series in the legend", BARS,
[voice = "Each cluster shares one legend. Click a series to hide it across every group at once, then click again to bring it back."])
let t_leg = ref_time_ticks()
sleep(LEAD_MS)
let t_leg = record_frame_count(app)
hold_content(app, LEAD_MS)
legend_toggle(bars, SERIES)
record_check(app, "{SERIES} hidden across all groups after the legend click",
wait_for_series_shown(bars, SERIES, false) != null)
sleep(900u) // dwell so the whole-series-gone state reads before restoring
hold_content(app, 900u) // dwell so the whole-series-gone state reads before restoring
legend_toggle(bars, SERIES)
record_check(app, "{SERIES} restored after the second click",
wait_for_series_shown(bars, SERIES, true) != null)
hold_remainder(d_leg, t_leg)
hold_remainder_content(app, d_leg, t_leg)

// ---- Beat 3: the pie chart ----
let d_pie = say_begin(app, "a pie splits the whole", PIE,
[voice = "The pie chart splits a single whole into slices, each labelled with its share as a percentage. A different shape from the same simple call."])
let t_pie = ref_time_ticks()
let t_pie = record_frame_count(app)
var psnap = snapshot(app)
move_to(app, plot_center(psnap, pie), 900)
wait_for_mouse_idle(app)
record_check_rendered(app, PIE, true)
hold_remainder(d_pie, t_pie)
hold_remainder_content(app, d_pie, t_pie)
}
}
17 changes: 4 additions & 13 deletions tests/integration/record_colormaps_and_style.das
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,6 @@ require daslib/json_boost public
let HEAT = "PLOT_WIN/HEAT"
let LINES = "PLOT_WIN/LINES"

// Hold a beat's caption for the remainder of its voice dwell, measuring real elapsed
// work (glide + verify) so the next say_begin can't fire early and overlap the voice.
def hold_remainder(dwell : uint; t0 : int64) {
let elapsed = uint(get_time_usec(t0) / 1000)
if (dwell > elapsed) {
sleep(dwell - elapsed)
}
}

[export]
def main {
with_implot_recording_app("examples/tutorial/colormaps_and_style.das", "colormaps_and_style.apng", 45) $(app) {
Expand Down Expand Up @@ -58,21 +49,21 @@ def main {
// ---- Beat 2: the colorbar reads as a smooth ramp (the sequential map) ----
let d_heat = say_begin(app, "a sequential map reads as a ramp", HEAT,
[voice = "Viridis is a sequential colormap, so the colorbar beside the heatmap reads as a smooth ramp from low to high. That is the natural fit for a heatmap."])
let t_heat = ref_time_ticks()
let t_heat = record_frame_count(app)
// Drift toward the colorbar on the heatmap's right edge.
move_to(app, (hx + hw * 0.96f, hy + hh * 0.5f), 900)
wait_for_mouse_idle(app)
record_check_rendered(app, HEAT, true)
hold_remainder(d_heat, t_heat)
hold_remainder_content(app, d_heat, t_heat)

// ---- Beat 3: auto-colored series ----
let d_lines = say_begin(app, "series auto-color from the map", LINES,
[voice = "On the right, six series in one colormap scope. Each line takes the next color from the map, so a family of related series stays consistent with no per-series color set."])
let t_lines = ref_time_ticks()
let t_lines = record_frame_count(app)
var lsnap = snapshot(app)
move_to(app, plot_center(lsnap, lines), 900)
wait_for_mouse_idle(app)
record_check_rendered(app, LINES, true)
hold_remainder(d_lines, t_lines)
hold_remainder_content(app, d_lines, t_lines)
}
}
17 changes: 4 additions & 13 deletions tests/integration/record_heatmap_histogram.das
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,6 @@ require daslib/json_boost public
let HEAT = "PLOT_WIN/HEAT"
let HIST = "PLOT_WIN/HIST"

// Hold a beat's caption for the remainder of its voice dwell, measuring real elapsed
// work (glide + verify) so the next say_begin can't fire early and overlap the voice.
def hold_remainder(dwell : uint; t0 : int64) {
let elapsed = uint(get_time_usec(t0) / 1000)
if (dwell > elapsed) {
sleep(dwell - elapsed)
}
}

[export]
def main {
with_implot_recording_app("examples/tutorial/heatmap_histogram.das", "heatmap_histogram.apng", 45) $(app) {
Expand Down Expand Up @@ -57,7 +48,7 @@ def main {
// ---- Beat 2: trace the heatmap grid ----
let d_heat = say_begin(app, "a heatmap colors a grid by value", HEAT,
[voice = "The heatmap draws a rows by columns grid, and each cell takes its color from its value through the active colormap, so the structure in the data shows up as a pattern of colors."])
let t_heat = ref_time_ticks()
let t_heat = record_frame_count(app)
// Glide diagonally across the grid so the cursor sweeps the gradient.
move_to(app, (hx + hw * 0.1f, hy + hh * 0.15f), 300)
wait_for_mouse_idle(app)
Expand All @@ -66,16 +57,16 @@ def main {
record_check(app, "the cursor lands hovered over the heatmap grid",
wait_for_hovered(heat, true) != null)
record_check_rendered(app, HEAT, true)
hold_remainder(d_heat, t_heat)
hold_remainder_content(app, d_heat, t_heat)

// ---- Beat 3: the histogram ----
let d_hist = say_begin(app, "a histogram bins a sample set", HIST,
[voice = "The histogram bins a flat array of samples into bars, showing the shape of the distribution. Here, a count per bin, with the bin count picked automatically from the sample size."])
let t_hist = ref_time_ticks()
let t_hist = record_frame_count(app)
var gsnap = snapshot(app)
move_to(app, plot_center(gsnap, hist), 900)
wait_for_mouse_idle(app)
record_check_rendered(app, HIST, true)
hold_remainder(d_hist, t_hist)
hold_remainder_content(app, d_hist, t_hist)
}
}
29 changes: 10 additions & 19 deletions tests/integration/record_line_plot.das
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,6 @@ def double_click(app : ImguiApp; pt : tuple<float; float>) {
wait_for_mouse_idle(app)
}

// Hold a beat's caption for the remainder of its voice dwell, measuring real elapsed
// work (gesture + verify) so the next say_begin can't fire early and overlap the voice.
def hold_remainder(dwell : uint; t0 : int64) {
let elapsed = uint(get_time_usec(t0) / 1000)
if (dwell > elapsed) {
sleep(dwell - elapsed)
}
}

[export]
def main {
with_implot_recording_app("examples/tutorial/line_plot.das", "line_plot.apng", 50) $(app) {
Expand All @@ -93,35 +84,35 @@ def main {
let before_pan = field_json(snapshot(app), PLOT, "x_max")
let d_pan = say_begin(app, "drag to pan", PLOT,
[voice = "Hold the left button inside the plot and drag to pan. The whole view slides with the cursor."])
let t_pan = ref_time_ticks()
sleep(LEAD_MS)
let t_pan = record_frame_count(app)
hold_content(app, LEAD_MS)
pan_drag(app, center, left)
record_check_changed(app, PLOT, "x_max", before_pan)
hold_remainder(d_pan, t_pan)
hold_remainder_content(app, d_pan, t_pan)

// ---- Beat 3: zoom (scroll wheel) ----
let before_zoom = field_json(snapshot(app), PLOT, "x_max")
let d_zoom = say_begin(app, "scroll to zoom", PLOT,
[voice = "Scroll the wheel over the plot to zoom. It zooms in around the cursor, toward the data under it."])
let t_zoom = ref_time_ticks()
sleep(LEAD_MS)
let t_zoom = record_frame_count(app)
hold_content(app, LEAD_MS)
move_to(app, center, 300)
wait_for_mouse_idle(app)
for (_b in range(3)) {
scroll_zoom(app, 2)
sleep(260u)
hold_content(app, 260u)
}
record_check_changed(app, PLOT, "x_max", before_zoom)
hold_remainder(d_zoom, t_zoom)
hold_remainder_content(app, d_zoom, t_zoom)

// ---- Beat 4: fit (double click) ----
let before_fit = field_json(snapshot(app), PLOT, "x_max")
let d_fit = say_begin(app, "double click to fit", PLOT,
[voice = "Double click anywhere in the plot to fit the axes back to the data. One gesture resets the view."])
let t_fit = ref_time_ticks()
sleep(LEAD_MS)
let t_fit = record_frame_count(app)
hold_content(app, LEAD_MS)
double_click(app, center)
record_check_changed(app, PLOT, "x_max", before_fit)
hold_remainder(d_fit, t_fit)
hold_remainder_content(app, d_fit, t_fit)
}
}
21 changes: 6 additions & 15 deletions tests/integration/record_multi_axes.das
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,6 @@ let PLOT = "PLOT_WIN/CHART"
let LEAD_MS = 800u
let HOLD_TOL = 1.0lf // an untouched axis' range must not drift more than this (data units)

// Hold a beat's caption for the remainder of its voice dwell, measuring real elapsed
// work (gesture + verify) so the next say_begin can't fire early and overlap the voice.
def hold_remainder(dwell : uint; t0 : int64) {
let elapsed = uint(get_time_usec(t0) / 1000)
if (dwell > elapsed) {
sleep(dwell - elapsed)
}
}

[export]
def main {
with_implot_recording_app("examples/tutorial/multi_axes.das", "multi_axes.apng", 45) $(app) {
Expand All @@ -56,29 +47,29 @@ def main {
let b2_y2 = plot_axis_limit(b2, s, "y2_max")
let d_left = say_begin(app, "drag the left axis to pan temperature alone", PLOT,
[voice = "Grab the left temperature axis and drag it. Only temperature pans. Pressure on the right does not move."])
let t_left = ref_time_ticks()
sleep(LEAD_MS)
let t_left = record_frame_count(app)
hold_content(app, LEAD_MS)
drag_axis(s, ImAxis.Y1, -110.0f)
var dleft = wait_for_axis_limit_changed(s, "y_max", b2_y1)
record_check(app, "temperature (Y1) panned by the left-axis drag", dleft != null)
// Held-steady check on the SAME frame the pan was detected (dleft), not a later snapshot.
record_check(app, "pressure (Y2) held steady while Y1 dragged",
abs(plot_axis_limit(dleft, s, "y2_max") - b2_y2) < HOLD_TOL)
hold_remainder(d_left, t_left)
hold_remainder_content(app, d_left, t_left)

// ---- Beat 3: drag the RIGHT axis (pressure / Y2) ----
var b3 = snapshot(app)
let b3_y1 = plot_axis_limit(b3, s, "y_max")
let b3_y2 = plot_axis_limit(b3, s, "y2_max")
let d_right = say_begin(app, "drag the right axis to pan pressure alone", PLOT,
[voice = "Now the right pressure axis. Drag it, and only pressure pans. Temperature on the left stays put. Each axis moves on its own."])
let t_right = ref_time_ticks()
sleep(LEAD_MS)
let t_right = record_frame_count(app)
hold_content(app, LEAD_MS)
drag_axis(s, ImAxis.Y2, 120.0f)
var dright = wait_for_axis_limit_changed(s, "y2_max", b3_y2)
record_check(app, "pressure (Y2) panned by the right-axis drag", dright != null)
record_check(app, "temperature (Y1) held steady while Y2 dragged",
abs(plot_axis_limit(dright, s, "y_max") - b3_y1) < HOLD_TOL)
hold_remainder(d_right, t_right)
hold_remainder_content(app, d_right, t_right)
}
}
21 changes: 6 additions & 15 deletions tests/integration/record_multi_series.das
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,6 @@ let BARS = "PLOT_WIN/BARS"
let SERIES = "cos"
let LEAD_MS = 800u

// Hold a beat's caption for the remainder of its voice dwell, measuring real elapsed
// work (gesture + verify) so the next say_begin can't fire early and overlap the voice.
def hold_remainder(dwell : uint; t0 : int64) {
let elapsed = uint(get_time_usec(t0) / 1000)
if (dwell > elapsed) {
sleep(dwell - elapsed)
}
}

[export]
def main {
with_implot_recording_app("examples/tutorial/multi_series.das", "multi_series.apng", 45) $(app) {
Expand All @@ -50,19 +41,19 @@ def main {
// ---- Beat 2: legend toggle - hide ----
let d_hide = say_begin(app, "click a legend entry to hide", PLOT,
[voice = "Every series has a legend entry. Click one to hide that series. Here the co-sine curve disappears."])
let t_hide = ref_time_ticks()
sleep(LEAD_MS)
let t_hide = record_frame_count(app)
hold_content(app, LEAD_MS)
legend_toggle(s, SERIES)
record_check(app, "{SERIES} hidden after legend click", wait_for_series_shown(s, SERIES, false) != null)
hold_remainder(d_hide, t_hide)
hold_remainder_content(app, d_hide, t_hide)

// ---- Beat 3: legend toggle - show ----
let d_show = say_begin(app, "click again to show", PLOT,
[voice = "Click the same entry again and the series comes right back."])
let t_show = ref_time_ticks()
sleep(LEAD_MS)
let t_show = record_frame_count(app)
hold_content(app, LEAD_MS)
legend_toggle(s, SERIES)
record_check(app, "{SERIES} shown after second legend click", wait_for_series_shown(s, SERIES, true) != null)
hold_remainder(d_show, t_show)
hold_remainder_content(app, d_show, t_show)
}
}
18 changes: 4 additions & 14 deletions tests/integration/record_query_and_hover.das
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ options no_unused_function_arguments = false

require imgui/imgui_implot_app public
require imgui/imgui_implot_playwright public
require implot
require daslib/json public
require daslib/json_boost public

Expand All @@ -20,15 +19,6 @@ require daslib/json_boost public

let CHART = "PLOT_WIN/CHART"

// Hold a beat's caption for the remainder of its voice dwell, measuring real elapsed work
// (glide + verify) so the next say_begin can't fire early and overlap the voice.
def hold_remainder(dwell : uint; t0 : int64) {
let elapsed = uint(get_time_usec(t0) / 1000)
if (dwell > elapsed) {
sleep(dwell - elapsed)
}
}

[export]
def main {
with_implot_recording_app("examples/tutorial/query_and_hover.das", "query_and_hover.apng", 45) $(app) {
Expand All @@ -54,19 +44,19 @@ def main {
// ---- Beat 2: the readout follows the cursor (glide to the left third) ----
let d_l = say_begin(app, "the readout follows the cursor", CHART,
[voice = "Move the cursor and the readout follows. Here, near the left, the label shows the x and y under the pointer, updated every frame."])
let t_l = ref_time_ticks()
let t_l = record_frame_count(app)
move_to(app, (px + pw * 0.22f, py + ph * 0.42f), 900)
wait_for_mouse_idle(app)
var hl = wait_for_hovered(s, true)
let mx_l = mouse_x(hl, s)
record_check(app, "readout tracks the cursor near the left (x in [8,40], got {mx_l})",
mx_l >= 8.0lf && mx_l <= 40.0lf)
hold_remainder(d_l, t_l)
hold_remainder_content(app, d_l, t_l)

// ---- Beat 3: read any point (glide across to the right third) ----
let d_r = say_begin(app, "read any point", CHART,
[voice = "Glide across to the right and the crosshair and the label track right along with it. You can read off the value at any point on the plot."])
let t_r = ref_time_ticks()
let t_r = record_frame_count(app)
move_to(app, (px + pw * 0.74f, py + ph * 0.58f), 1100)
wait_for_mouse_idle(app)
var hr = wait_for_hovered(s, true)
Expand All @@ -75,7 +65,7 @@ def main {
mx_r >= 60.0lf && mx_r <= 92.0lf)
record_check(app, "the readout moved right with the cursor (left {mx_l} < right {mx_r})",
mx_r > mx_l + 20.0lf)
hold_remainder(d_r, t_r)
hold_remainder_content(app, d_r, t_r)
}
}

Expand Down
15 changes: 2 additions & 13 deletions tests/integration/record_realtime_scroll.das
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ options no_unused_function_arguments = false

require imgui/imgui_implot_app public
require imgui/imgui_implot_playwright public
require implot
require daslib/json public
require daslib/json_boost public

Expand All @@ -19,16 +18,6 @@ require daslib/json_boost public
let SCROLL = "PLOT_WIN/SCROLL"
let SCROLL_MARGIN = 2.0lf // x_min must advance at least this far over the narration (data units)

// Hold a beat's caption for the remainder of its voice dwell, measuring real elapsed
// work so the next say_begin can't fire early and overlap the voice. For this tutorial the
// hold doubles as the observation window: the plot keeps streaming while the caption holds.
def hold_remainder(dwell : uint; t0 : int64) {
let elapsed = uint(get_time_usec(t0) / 1000)
if (dwell > elapsed) {
sleep(dwell - elapsed)
}
}

[export]
def main {
with_implot_recording_app("examples/tutorial/realtime_scroll.das", "realtime_scroll.apng", 45) $(app) {
Expand All @@ -52,8 +41,8 @@ def main {
let x0 = plot_axis_limits(snapshot(app), s).x_min
let d_scroll = say_begin(app, "the window scrolls with time", SCROLL,
[voice = "Watch it scroll. As time advances the window slides to the right. New samples push in on the right while the oldest ones drop off the left."])
let t_scroll = ref_time_ticks()
hold_remainder(d_scroll, t_scroll)
let t_scroll = record_frame_count(app)
hold_remainder_content(app, d_scroll, t_scroll)
let x1 = plot_axis_limits(snapshot(app), s).x_min
record_check(app, "x window scrolled forward (x_min advanced over the narration)",
x1 > x0 + SCROLL_MARGIN)
Expand Down
Loading
Loading