Unreal ImGui

repository·master·Indexed 20 days ago

https://github.com/segross/unrealimgui

An Unreal Engine 4 plugin that integrates the Dear ImGui library to provide a lightweight immediate-mode GUI for creating debugging tools and developer interfaces. It includes features for Unreal texture registration, ImGui Delegates for safe rendering, and an experimental NetImgui branch for remote connections to the Unreal editor or application.

Tokens
5.6K
Snippets
14
Records
25
Agent score
23%

What's inside unrealimgui

  1. Handle input dispatching between ImGui and your application

    master

    To prevent input conflicts (e.g., clicking a button in ImGui also triggering a game action), use the flags provided in the ImGuiIO structure.

    • io.WantCaptureMouse: Set when ImGui wants to consume mouse input. You should discard/hide mouse inputs from your application when this is true.
    • io.WantCaptureKeyboard: Set when ImGui wants to consume keyboard input. You should discard/hide keyboard inputs from your application when this is true.
    • io.WantTextInput: Set when ImGui needs text input (e.g., an active text box). You may want to trigger an OS on-screen keyboard.

    Important Implementation Details:

    1. Always pass inputs to ImGui: Even if the WantCapture flags are false, you must still pass mouse/keyboard events to ImGui so it can detect clicks in empty space to unfocus windows.
    2. Timing: These flags are updated by ImGui::NewFrame(). For best results, read them after calling NewFrame().
    3. Accuracy: Do not manually check if the mouse is hovering an ImGui window; io.WantCaptureMouse is the authoritative source and correctly handles dragging and modal windows.
    4. Keyboard Edge Case: Text input widgets release focus on "Return KeyDown". This means the subsequent "Return KeyUp" event might arrive when io.WantCaptureKeyboard is already false. You may need to track key-down states to filter these out.
    if (ImGui::GetIO().WantCaptureMouse) {
        // Discard mouse input for the rest of the application
    }
  2. Use ImGui Delegates for safe rendering

    master

    ImGui can be called directly in game code, but using ImGui Delegates is safer, especially if your code runs outside the game thread or outside the world update scope. Delegates also continue to work when the game is paused.

    Include ImGuiDelegates.h to access two types of delegates:

    1. World Delegates: Created for every world and cleared when the world becomes invalid. Best for world objects.
    2. Multi-context Delegates: Called for every updated world. These can be called multiple times per frame in different contexts.

    Delegates are called in a specific order to allow content to be added before or after world objects:

    • multi-context early debug
    • world early debug
    • world update
    • world debug
    • multi-context debug.
  3. How the ImGui ID Stack and Labels work

    master

    Dear ImGui uses a unique ID system to track interactive widgets and their state. IDs are implicitly built by hashing the 'path' of elements (like windows and tree nodes) and their labels.

    ID Collisions: If two widgets in the same scope have the same label, they will share an ID, causing interaction with one to trigger the other.

    Solving ID Conflicts:

    1. Inline ID modification: Use ## to add a hidden suffix to a label that contributes to the ID but is not visible. Use ### to provide a visible label that is not part of the ID (useful for animating titles while keeping a constant ID).
    2. Manual Scoping: Use PushID() and PopID() to create unique ID scopes. You can push integers, strings, or pointers.
    3. Implicit Scoping: Functions like TreeNode() automatically push an ID to the stack for their children.
    // Using ## for hidden ID suffixes
    Button("Play##foo1"); 
    Button("Play##foo2"); // Different ID, same visible label "Play"
    
    // Using ### for visible labels with constant IDs
    Button("Hello###ID"); 
    Button("World###ID"); // Same ID, different visible labels
    
    // Using PushID/PopID for programmatic loops
    for (int i = 0; i < 100; i++) {
      PushID(i);
      Button("Click");
      PopID();
    }
  4. How to display images using ImTextureID

    master

    To display images, use ImGui::Image() or ImGui::ImageButton().

    The ImTextureID Concept: ImGui is renderer-agnostic. It does not load images; it only manages draw commands. It uses an ImTextureID (which is a void*) to pass a handle to your underlying graphics API.

    • User Code: You must cast your engine's texture pointer or API handle (like a GLuint or ID3D11ShaderResourceView*) to ImTextureID (void*) when calling ImGui::Image().
    • Renderer Code: Your rendering backend receives this void* and casts it back to the appropriate type to bind the texture before drawing.

    Common API Mappings:

    • OpenGL: ImTextureID = GLuint (cast via (void*)(intptr_t)my_tex)
    • DirectX 11: ImTextureID = ID3D11ShaderResourceView*
    • DirectX 12: ImTextureID = D3D12_GPU_DESCRIPTOR_HANDLE
    // User side: Casting a texture to ImTextureID
    MyTexture* texture = g_CoffeeTableTexture;
    ImGui::Image((void*)texture, ImVec2(texture->Width, texture->Height));
    
    // Renderer side: Casting back from ImTextureID
    MyTexture* texture = (MyTexture*)pcmd->TextureId;
    MyEngineBindTexture2D(texture);
  5. Merge icon fonts into a main font

    master

    The most efficient way to use icons is to merge an icon font (like FontAwesome) into your existing main font using ImFontConfig::MergeMode. This allows you to include icon glyphs directly within your text strings.

    static ImWchar ranges[] = { 0xf000, 0xf3ff, 0 };
    ImFontConfig config;
    config.MergeMode = true;
    
    ImGuiIO& io = ImGui::GetIO();
    // Load the base font first
    io.Fonts->AddFontDefault();
    // Merge the icon font into the default font
    io.Fonts->AddFontFromFileTTF("fontawesome-webfont.ttf", 16.0f, &config, ranges);
  6. Manage ImGui Input Mode and Sharing

    master

    By default, ImGui starts in render-only mode. To interact with the UI, you must enable input mode via code, console commands, or keyboard shortcuts.

    Input Sharing

    You can enable features to pass keyboard, gamepad, or mouse events back to the game.

    • Keyboard/Gamepad: Straightforward event passing.
    • Mouse: Since ImGui overlays the viewport, mouse sharing requires the widget to switch hit visibility and update position in the background.
  7. Understand the Dear ImGui C++ API design

    master

    Dear ImGui is written in C++ to leverage features that make the API more terse and convenient, specifically:

    • Function Overloading
    • Default Parameters
    • Namespaces
    • Constructors
    • Templates (e.g., ImVector<>)

    Note on Compatibility and Bindings:

    • The library does not require C++11, making it compatible with older C++ compilers.
    • It does not use any external C++ header files.
    • If you are working in a language other than C++, you can use the auto-generated C API cimgui or look for existing third-party bindings. When creating your own bindings, it is recommended to replicate function overloading and default parameters to maintain ease of use.
  8. Install Unreal ImGui

    master

    To install Unreal ImGui, place the contents of the repository into your project's Plugins directory at [Project Root]/Plugins/ImGui/. After compiling and running your project, the ImGui module will be available for use.

    Note: While plugins can also be placed in the engine directory ([UE4 Root]/Engine/Plugins/), it is recommended to use the project-specific directory.

  9. Choose the correct Dear ImGui version

    master

    When selecting a version of Dear ImGui:

    • Standard Usage: It is generally recommended to sync to the master branch or the latest release. The library is stable, and regressions are typically fixed quickly.
    • Advanced Features: If you require Docking/Merging features or Multi-viewport support, use the docking branch. This branch is kept in sync with master regularly and is widely used by many projects.
  10. Interact with standard C++ types (std::string, std::vector)

    master

    ImGui uses raw C-style types (like char*) for maximum portability and performance. To use standard C++ containers:

    • std::string: Use the helper provided in misc/cpp/imgui_stdlib.h to enable ImGui::InputText() to work with std::string.
    • std::vector / Containers: Use the BeginCombo() / EndCombo() API (or ListBoxHeader/Footer) to manually iterate through your container and submit items one by one. Avoid the older Combo() or ListBox() APIs for complex data structures.
  11. Explore Dear ImGui documentation and examples

    master

    Dear ImGui is designed to be explored through its source and examples rather than extensive written documentation. To learn how to use the library, follow these methods:

    • Explore Examples: Check the examples/ folder in the repository for standalone applications (using OpenGL, DirectX, etc.) that demonstrate integration with different engines.
    • Use the Demo Window: Call ImGui::ShowDemoWindow() in your code. This opens a comprehensive UI within your application that showcases almost all available features. You can inspect the imgui_demo.cpp file to see how specific widgets are implemented.
    • Inspect Source Code: Refer to the comments in imgui.cpp and imgui.h for API details. Your IDE's ability to jump to declarations is highly recommended for discovering function signatures and associated comments.
  12. Set up NetImgui (Experimental)

    master

    NetImgui allows for remote connection to the Unreal editor or application.

    1. Branch: Use the net_imgui branch instead of master.
    2. Server: You must run a netImguiServer (see the NetImgui repository for instructions).
    3. Configuration: After launching the server, add client configurations for ports 8889 and 8890.
    4. Connection: Set the server to autoconnection mode or initialize manually. Once connected, use the top bar in the NetImgui client to switch between contexts (Editor, PIE instances, etc.).