HOWTO-ImGui

From ScummVM :: Wiki

ImGui is a marvellous library that we use for building interactive UI. It uses the concept of Immediate Mode GUI, which is stateless (but we often keep some state for caching) and is very pleasant to work with and _very_ fast to develop. You may watch this video for understanding the general concept behind the Immediate Mode GUI.

Typically, we use it for various debugging tools. The most advanced usage so far is in the Director engine.

Also, the Event Recorder currently uses it, and you need to enable it at compile-time with the configure script.

We use docking ImGui branch, which allows multiple windows and window docking.

For understanding how to build GUI with ImGui, it has an awesome interactive demo with interactive source code. You click on a widget, you see how to make it.

Plugging it into your engine

First, you need to add it as a component to your `configure.engine` file, like this:

# This file is included from the main "configure" script
# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps] [components]
add_engine twine "Little Big Adventure" yes "" "" "highres" "imgui midi gif"

Since the component is optional, you need to make sure that you wrap all your code in the #if USE_UMGUI preprocessor check and ifdef USE_IMGUI in the module.mk file.

Then, create new files with the ImGui implementation. The current established schema is

   debugtools.cpp -- for the main file
   debugger/  -- if you have more complex multifile logic
   debugger/debugtools.h -- your minimalistic include file
   debugger/dt-internal.h -- your internal structures
   debugtools/dt-xxxxxx.cpp -- individual files

See example in the Director engine

It is recommended to use <sytaxhighlight lang="C++>namespace DT</syntaxhighlight> for your code.

Next, you need to initialize it. in your Engine::run() method, add:

#include "backends/imgui/imgui.h"

#ifdef USE_IMGUI
    ImGuiCallbacks callbacks;
    bool drawImGui = debugChannelSet(-1, kDebugImGui);
    callbacks.init = DT::onImGuiInit;
    callbacks.render = drawImGui ? DT::onImGuiRender : nullptr;
    callbacks.cleanup = DT::onImGuiCleanup;
    _system->setImGuiCallbacks(callbacks);
#endif

Your debugtools.h contains these declariations:

#ifndef DIRECTOR_DEBUGTOOLS_H
#define DIRECTOR_DEBUGTOOLS_H

namespace Director {
namespace DT {
void onImGuiInit();
void onImGuiRender();
void onImGuiCleanup();
} // namespace DT
} // namespace Director

#endif

And implement these methods. The almost-minimal implementation could be found here: WAGE initial ImGui commit.

Please denote the following moving parts of this implementation:

  • We implement MainMenuBar with the ImGui menu
  • We keep the GUI state (open window, caches, etc) in ImGuiState *_state
  • Each window has its own method, and starts with
static void showWorld() {
	if (!_state->_showWorld)
		return;

This allows having multiple windows open.

Using Material icons

For nicer UIs, we added Material Design icons font by Google.

Using it with ImGui is pretty straightforward:

#include "backends/imgui/IconsMaterialSymbols.h"

void onImGuiInit() {
...
    static const ImWchar icons_ranges[] = {ICON_MIN_MS, ICON_MAX_MS, 0};
    io.FontDefault = ImGui::addTTFFontFromArchive("MaterialSymbolsSharp.ttf", 16.f, &icons_config, icons_ranges);
}

// And then use freely in your text fields

if (ImGui::Button(ICON_MS_ALIGN_JUSTIFY_CENTER))

The IconsMaterialSymbols.h contains constants for the currently used font (sev updates it from time to time, when something of interest is added to the font).

And you may use the great search site provided by Google for looking up the icon of your interest. The ICON_MS_XXXX corresponds to the "Icon name". Click on the desired icon; a pane opens on the right side, scroll to the bottom, and you will see the icon name.

Extensions

In case you would like to extend our ImGui with some nice component (there are plenty on the market), please put it into backends/imgui/components/ directory. You can already see the logger and memory viewer. As usual, do not forget to leave the attribution and put repo and commit references in your git log message.


Updates

If updating the ImGui itself, the process is described in the relevant commit log messages.

Materials icon update is three-step. First, add add the TTF, then regenerate fonts.zip, and finally, update IconsMaterialSymbols.h file.