class mrpt::imgui::CImGuiAppShell

Overview

Window and main loop of a Dear ImGui application with docking panels.

Owns the GLFW window, its OpenGL 3.3 core context, and the ImGui and ImPlot contexts. Every frame it sets up a full-window dockspace whose central node is transparent (“passthrough”), so the application can draw a 3D scene behind all panels (see CImGuiBackgroundScene) and the user can dock panels anywhere. The docking layout is saved to imgui.ini in the per-user config directory of the application (see userConfigDirectory()), and restored on the next run.

It also loads the Material Symbols icon font (mrpt/imgui/icons.h), merged into the default font, and scales the UI with the monitor content scale (HiDPI).

A minimal application:

mrpt::imgui::CImGuiAppShell app;
if (!app.init("My app")) { return 1; }
app.mainMenuBar = [&]() {
  if (ImGui::BeginMenu("File")) {
    if (ImGui::MenuItem("Quit")) { app.requestClose(); }
    ImGui::EndMenu();
  }
};
app.run([&]() {
  ImGui::Begin("Panel");
  ImGui::Text("Hello");
  ImGui::End();
});

For automated (headless) tests, two environment variables are honored:

  • MRPT_IMGUI_MAX_FRAMES=N : run() returns after N frames.

  • MRPT_IMGUI_SCREENSHOT=file.png : the last frame is saved to that file.

#include <mrpt/imgui/CImGuiAppShell.h>

class CImGuiAppShell
{
public:
    // structs

    struct Options;

    // fields

    std::function<void()> mainMenuBar;
    std::function<void()> beforeDockspace;
    std::function<void(unsigned int dockspaceId)> setupDefaultLayout;
    std::function<bool()> onCloseRequest;
    std::function<void(const std::vector<std::string>&files)> onFilesDropped;
    float clearColor[4] = {0.10f, 0.10f, 0.11f, 1.0f};
    uint64_t maxFrames = 0;

    // construction

    CImGuiAppShell();
    CImGuiAppShell(const CImGuiAppShell&);

    // methods

    CImGuiAppShell& operator = (const CImGuiAppShell&);
    bool init(const std::string& windowTitle, const Options& options);
    bool init(const std::string& windowTitle);
    void run(const std::function<void()>& renderFrame);
    void shutdown();
    void requestClose();
    bool isInitialized() const;
    GLFWwindow* windowHandle() const;
    void setWindowTitle(const std::string& title);
    uint64_t frameCount() const;
    float dpiScale() const;
    const std::string& iniFilePath() const;
    unsigned int dockspaceId() const;
    std::array<float, 4> centralNodeRect() const;
    void requestScreenshot(const std::string& file);
    void requestFrameGrab(std::function<void(const mrpt::img::CImage&)> callback);
    std::array<float, 2> framebufferScale() const;
    std::optional<mrpt::img::CImage> grabFramebuffer() const;
};

Fields

std::function<void()> mainMenuBar

Called each frame inside ImGui::BeginMainMenuBar() / EndMainMenuBar(), so the application menus go in the main menu bar.

std::function<void()> beforeDockspace

Called each frame before the dockspace is created.

Windows that must reduce the area of the dockspace go here, e.g. a toolbar or a timeline pinned to an edge with ImGui::BeginViewportSideBar().

std::function<void(unsigned int dockspaceId)> setupDefaultLayout

Called once, with the dockspace ID, the first time the application runs with no saved layout, to dock its panels by default with ImGui::DockBuilderSplitNode() and ImGui::DockBuilderDockWindow().

std::function<bool()> onCloseRequest

Called when the user tries to close the window.

Return false to keep it open (e.g. to ask about unsaved changes first).

std::function<void(const std::vector<std::string>&files)> onFilesDropped

Files dropped onto the window.

float clearColor[4] = {0.10f, 0.10f, 0.11f, 1.0f}

Background (clear) color of the window, behind everything.

uint64_t maxFrames = 0

Maximum frames to render before run() returns (0 = unlimited).

Initialized from the MRPT_IMGUI_MAX_FRAMES environment variable.

Methods

bool init(const std::string& windowTitle, const Options& options)

Creates the window, the GL context, and the ImGui/ImPlot contexts.

Returns:

false on failure (e.g. no display); details are printed to stderr.

void run(const std::function<void()>& renderFrame)

Runs the main loop until the window is closed or requestClose() is called.

renderFrame is called once per frame, after the dockspace has been set up, to submit the application windows.

void shutdown()

Destroys the contexts and the window.

Safe to call more than once; also called by the destructor.

void requestClose()

run() returns after the current frame.

uint64_t frameCount() const

Number of frames rendered so far by run().

float dpiScale() const

UI scale factor from the monitor content scale (1.0 on normal DPI).

const std::string& iniFilePath() const

Path of the imgui.ini file with the saved layout (empty if layout persistence is disabled or no config directory is available).

unsigned int dockspaceId() const

ImGui ID of the main dockspace, valid after the first frame.

std::array<float, 4> centralNodeRect() const

Rectangle (x, y, width, height), in ImGui coordinates, of the central node of the dockspace in the last frame: the area not covered by docked panels, where a background scene is visible.

void requestScreenshot(const std::string& file)

Saves the current window contents to an image file at the end of this frame (or the next one, if called outside of a frame).

void requestFrameGrab(std::function<void(const mrpt::img::CImage&)> callback)

Calls callback with the window contents at the end of this frame (after all ImGui windows are drawn), e.g.

to crop and save part of it. Coordinates of the image are framebuffer pixels: multiply ImGui coordinates by framebufferScale().

std::array<float, 2> framebufferScale() const

Framebuffer pixels per ImGui unit (2 on most HiDPI displays).

std::optional<mrpt::img::CImage> grabFramebuffer() const

Reads the window framebuffer contents now.

Must be called from the GL thread, between frames or from a renderFrame callback (in which case the previous frame contents are read).