Table of Contents

Dear ImGui

The engine runs Dear ImGui through ImGui.NET, with docking enabled and the dark style. It is for debug panels, tools and developer views. Player-facing screens belong in BSGameLib.UI.

The engine starts a frame before your drawing and ends it after. Your code only adds windows and widgets, so use the ImGuiNET namespace as you would in any ImGui.NET program:

using ImGuiNET;

protected override void EndFrame(IGameTime gameTime)
{
  ImGui.Begin("Debug");
  ImGui.Text($"Frame: {gameTime.DeltaSeconds * 1000f:F1} ms");

  if (ImGui.Button("Pause"))
    _paused = true;

  ImGui.End();

  base.EndFrame(gameTime);
}

Where to call ImGui

Call ImGui while a frame is open. That is from EndFrame, which is the usual place for windows, and also from Draw and ConfigureRenderGraph. Outside a frame an ImGui call is invalid, so do not make them from Update or Initialize. Put a window in EndFrame and it is drawn in that same frame, on top of the game.

The engine finishes the frame and draws it after EndFrame returns. Do not call ImGui.NewFrame, ImGui.EndFrame or ImGui.Render yourself.

Fonts

ImGui's built-in font has Latin letters only. Text in another script comes out blank unless a font with those glyphs is merged in. IImGuiFonts chooses that font:

using BSGameLib.Game;
using BSGameLib.Game.Localization;

var fonts = GetService<IImGuiFonts>();
fonts.UseFont(
  Path.Combine(AppContext.BaseDirectory, "Fonts", "NotoSansJP-Regular.ttf"),
  LanguageScripts.Japanese);

UseFont merges the font's glyphs for one script into the built-in font. English draws as before, and the script draws in the font. Pass null to go back to the built-in font alone.

  • The script is one of the constants in LanguageScripts: Latin (the default), Cyrillic, Greek, Vietnamese, Thai, Japanese, Korean, ChineseSimplified and ChineseFull. An unknown name is treated as Latin.
  • A file that does not exist is logged, and the built-in font is kept.
  • The change takes effect at the start of the next frame, when the font texture is rebuilt.
  • ChineseFull covers every Chinese character, which makes a large texture. Prefer ChineseSimplified unless the game needs more.

FontPath and Script on the same interface report what is in use. A localized game can pass the font and script a language file names (LanguageInfo.FontFile and Script) when the language changes. See Localization.

ImGui and the game's own text are separate. This font is used only by ImGui windows.

Input and ImGui

When one of its windows wants the keyboard or the mouse, ImGui has first claim on that input. The game's input follows from that:

  • While ImGui wants the keyboard, the game receives no keys. The bindings and IKeyboardManager see nothing, and the key events are not raised. Typing into an ImGui text field does not also reach a game action. A key released while ImGui has the keyboard is still released for the game, so no key is left held down. See Input.
  • While ImGui wants the mouse, the scroll wheel is withheld from the game. Clicks and movement still reach it, so a game that should ignore clicks over an ImGui window must check for itself.

ImGui's text fields receive typed text for as long as the renderer runs. It holds text input through the same count as the game's text handlers, so a game text box losing focus does not switch it off.

To ask ImGui, read ImGui.GetIO().WantCaptureMouse or WantCaptureKeyboard. ImGui sets these during its own frame, so in Update they describe the frame before.

protected override void Update(IGameTime gameTime)
{
  if (!ImGui.GetIO().WantCaptureMouse && _mouse.IsClicked)
    SelectTile();

  base.Update(gameTime);
}

Clipboard

ImGui's clipboard reads and writes the same system clipboard as SdlClipboard, so text copied in an ImGui field can be pasted into a game control, and the reverse.