class mrpt::imgui::CImGuiTimeline

Overview

A global time slider for log players: play/pause, step, speed, a current-time readout, per-sensor tick marks along the axis, click-to-seek, and keyboard shortcuts.

The timeline covers [minTime(), maxTime()], in seconds or any other unit (for logs without timestamps, use entry indices as times). If key times are set (e.g. the timestamps of the log entries), stepping jumps between them and currentKeyIndex() tells the entry at the current time.

The model (time, stepping, playback) has no ImGui dependency and can be driven programmatically; render() draws the widgets in the current window, and renderAsBottomBar() pins them to the bottom of the main window.

Keyboard shortcuts (if keyboardShortcuts is true, and no text is being typed): Space play/pause; Left/Right step; PageUp/PageDown step 10; Home/End jump to start/end.

#include <mrpt/imgui/CImGuiTimeline.h>

class CImGuiTimeline
{
public:
    // structs

    struct Track;

    // fields

    double speed = 1.0;
    bool loop = false;
    double stepSize = 0.1;
    std::function<void(double t)> onTimeChanged;
    std::function<std::string(double t)> timeFormatter;
    bool keyboardShortcuts = true;

    // construction

    CImGuiTimeline();

    // methods

    void setRange(double tMin, double tMax);
    double minTime() const;
    double maxTime() const;
    double duration() const;
    void setKeyTimes(std::vector<double> times);
    const std::vector<double>& keyTimes() const;
    std::optional<size_t> currentKeyIndex() const;
    void seekToKey(size_t index);
    void setTime(double t);
    double time() const;
    void play();
    void pause();
    void togglePlay();
    bool isPlaying() const;
    void step(int n);
    void jumpToStart();
    void jumpToEnd();
    bool update(double wallDt);
    std::string timeLabel() const;
    bool render();
    bool renderAsBottomBar(const char* name = "##Timeline");
    float barHeight() const;
    void clearTracks();
    void addTrack(Track track);
    std::vector<Track>& tracks();
    const std::vector<Track>& tracks() const;

    static std::vector<int> tickColumns(
        const std::vector<double>& times,
        double tMin,
        double tMax,
        int widthPx
        );
};

Fields

double speed = 1.0

Playback speed, as a multiple of real time.

bool loop = false

Restart from the beginning when the end is reached while playing.

double stepSize = 0.1

Step size (in time units) when there are no key times.

std::function<void(double t)> onTimeChanged

Called whenever the current time changes.

std::function<std::string(double t)> timeFormatter

Formats a time for the readout.

Default: seconds since minTime().

Methods

void setRange(double tMin, double tMax)

Sets the time range.

The current time is clamped into it.

void setKeyTimes(std::vector<double> times)

Sets the discrete times stepping moves between (sorted on input).

If the range was empty, it is set to span them.

std::optional<size_t> currentKeyIndex() const

Index of the last key time not after the current time (or the first one, if the current time is before all of them); nullopt if there are no key times.

If several keys have the current time, the one reached with seekToKey() or step(), if any.

void seekToKey(size_t index)

Moves to the given key time (index clamped).

Calls onTimeChanged if the time or the key changed (keys may share the same time).

void setTime(double t)

Sets the current time, clamped to the range.

Calls onTimeChanged if it changed.

void step(int n)

Moves n key times forward (or backward, if negative); without key times, n * stepSize units.

Pauses playback.

bool update(double wallDt)

Advances the time by wallDt * speed if playing, and returns true if the time changed.

At the end of the range playback stops, or restarts from the beginning if loop.

std::string timeLabel() const

The readout text of the current time, using timeFormatter.

bool render()

Draws the timeline in the current ImGui window, handles its input, and advances playback with the frame time.

Returns true if the time changed in this frame.

bool renderAsBottomBar(const char* name = "##Timeline")

Draws the timeline in a bar pinned to the bottom of the main window.

Call it from CImGuiAppShell::beforeDockspace, so the dockspace does not cover it.

float barHeight() const

Height of the bar drawn by renderAsBottomBar() (ImGui units).

static std::vector<int> tickColumns(
    const std::vector<double>& times,
    double tMin,
    double tMax,
    int widthPx
    )

Pixel columns, in [0, widthPx), with at least one of times within [tMin, tMax] (sorted, unique), so dense tracks are drawn with at most one tick per column.