Skip to content

Feature Proposal: Add a Flag to Toggle Rendering Behavior (RenderInCurrentWindow = false by default) #70

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
SPyofgame200 opened this issue Mar 4, 2025 · 0 comments

Comments

@SPyofgame200
Copy link

Summary

Introduce a configurable flag, RenderInCurrentWindow, to control whether the test engine renders within the existing UI instead of creating a separate floating window. By default, this flag will be set to false, maintaining the current behavior.

Context

This proposal aims to introduce a configurable flag to allow developers to toggle whether the test engine renders inside the existing UI rather than opening a new window. This provides greater flexibility while maintaining backward compatibility by keeping the current behavior as the default.

Tag

Test Engine UI Configurable Flag Render In Current Window Not spawn new window for test engine

Motivation

In certain projects, developers may already have custom inspector tools integrated into their UI. For these cases, automatically spawning a new floating window for testing can be redundant or disruptive. Allowing the option to render within an existing window would provide better flexibility and a more seamless user experience.

Steps to reproduce

  1. Include the required libraries
#include "imgui_test_engine/imgui_te_ui.h"
#include "imgui_test_engine/imgui_te_engine.h"
#include "imgui_test_engine/imgui_te_context.h"
#include "imgui_test_engine/imgui_te_internal.h"
#include "imgui_test_engine/imgui_te_perftool.h"
  1. Create the current context
ImGuiTestEngine *e = HelloImGui::GetImGuiTestEngine();
bool *p_open = nullptr;
  1. Call the only known public function that display the test engine
ImGuiTestEngine_ShowTestEngineWindows(e, p_open);
  1. During the GUI rendering, you may add some tests to check the behaviour
        if (ImGui::Button("Add new runtime test")) {
            static int counter = 0;
            ++counter;

            ImGuiTestEngine *engine = HelloImGui::GetImGuiTestEngine();
            const std::string testname = ("test" + std::to_string(counter));
            testSimple = IM_REGISTER_TEST(engine, "Runtime Tests", testname.c_str());
            testSimple->GuiFunc = [](ImGuiTestContext *ctx) // Optionally provide a GUI function in addition to your application GUI
            {
                ImGui::Begin("Test Window", NULL, ImGuiWindowFlags_NoSavedSettings);
                ImGui::Text("Hello, automation world");
                ImGui::Button("Click Me");
                if (ImGui::TreeNode("Node")) {
                    static bool b = false;
                    ImGui::Checkbox("Checkbox", &b);
                    ImGui::TreePop();
                }
                ImGui::End();
            };
            testSimple->TestFunc = [](ImGuiTestContext *ctx) // Generally provide a Test function which will drive the test.
            {
                ctx->SetRef("Test Window");
                ctx->ItemClick("Click Me");
                ctx->ItemOpen("Node"); // Optional as ItemCheck("Node/Checkbox") can do it automatically
                ctx->ItemCheck("Node/Checkbox");
                ctx->ItemUncheck("Node/Checkbox");
            };
        }
  1. You may also use RegisterTests from hello_imgui, like this
    auto TestCase() -> void
    {
		static ImGuiTest *testFirstScreenShot;
		ImGuiTestEngine *engine = HelloImGui::GetImGuiTestEngine();
		testFirstScreenShot = IM_REGISTER_TEST(engine, "Backend Tests", "First_Screenshot");
		auto testFirstScreenShotFunc = [](ImGuiTestContext *ctx) {
			ctx->CaptureScreenshot();
		};
		testFirstScreenShot->TestFunc = testFirstScreenShotFunc;
     }
     runner.callbacks.RegisterTests = TestCase();

Tradeoff

I think it has many applicable pros

  • Improves workflow efficiency to people who prefer one-window workspace and let user combine with their own private inspector tools.
  • Provides developers with greater control over UI integration and makes the test engine more adaptable to various UI structures.
  • Reduces UI clutter for those who prefer an embedded approach and reduces window management overhead.
  • Maintains backward compatibility by keeping false as the default behavior.

compare to its cons

  • Add one more flag value (either 8 bit or 1 bit) auxiliary memory consumption
  • May introduce new edge cases or require additional testing to ensure smooth integration.
  • Ensuring that all related UI elements behave correctly in both modes (new window vs. current window) may require extra adjustments.
  • While default value preserve common behaviours, certain projects relying on assumptions about window creation might need minor refactoring.

Proposal Solution

In imgui_te_internal.h

struct ImGuiTestEngine
{
    // Others
    ...
    // Inputs
    ...
    // UI support
    ...
    // Performance Monitor
    ...
    // Screen/Video Capturing
    ...
    // Tools
    ...
    bool                        BackupConfigNoThrottle = false;
    bool                        RenderInCurrentWindow = false; // add this line <------------------------
    // Functions
    ...
}

Then in imgui_te_ui.cpp

    ImGui::SetNextWindowSize(ImVec2(ImGui::GetFontSize() * 50, ImGui::GetFontSize() * 40), ImGuiCond_FirstUseEver);
    if (!ImGui::Begin("Dear ImGui Test Engine", p_open, ImGuiWindowFlags_MenuBar))
    {
        ImGui::End();
        return;
    }
    ...
    ImGui::End();

we change to become

    if (!engine->RenderInCurrentWindow) {
        ImGui::SetNextWindowSize(ImVec2(ImGui::GetFontSize() * 50, ImGui::GetFontSize() * 40), ImGuiCond_FirstUseEver);
        if (!ImGui::Begin("Dear ImGui Test Engine", p_open, ImGuiWindowFlags_MenuBar))
        {
            ImGui::End();
            return;
        }
    }
    ...
    if (!engine->RenderInCurrentWindow) {
        ImGui::End();
    }

Alternative solutions

We can also use ImGui::BeginChild() instead of ignoring it completely

if (RenderInCurrentWindow)
{
    ImGui::BeginChild("TestToolEmbedded");
}
else
{
    if (!ImGui::Begin("Dear ImGui Test Engine", p_open, ImGuiWindowFlags_MenuBar))
    {
        ImGui::End();
        return;
    }
}

Instead of using a boolean, you may

  • treat it as a string for Window name, with empty means no window, by default it is
  • treat it as an enum of options
bool RenderInCurrentWindow = false;
ImGuiTestEngineName WindowName = "Dear ImGui Test Engine";
ImGuiTestEngineRenderOptions RenderOptions = ImGuiTestEngineRenderOptions::NewWindow;

the other options can be

enum class ImGuiTestEngineRenderOptions {
    CurrentWindow,                  // everything rendered in current window, separated by separator
    CurrentWindowTabbed,      // same things, but tabbed for each of its tool
    NewWindow,                      // everything rendered in a new window, separated by docks
    NewWindowWithTabbed,  // everything rendered in a new window, but separated by tabs
    Custom,                             // define a custom VoidFunction to change the order of how it should be rendered
};

Futher Improvements

If it is appropriate, we can make it configurable at runtime via UI settings

  • Adding an option in the settings menu so users can toggle RenderInCurrentWindow without modifying code.
if (ImGui::Checkbox("Render in Current Window", &engine->RenderInCurrentWindow))
{
    // Apply changes dynamically
}
  • As mentioned ealier, use callback for custom rendering so the user can define the order of imgui_te combined with their own inspector tools.
using RenderFunction = std::function<void()>;
RenderFunction DefaultRenderFunction = []() { ... };
RenderFunction CustomRenderCallback = DefaultRenderFunction; // User-defined callback

Benchmarked Testing

With my System and Environment like this

  • OS: Windows 11 Home Single Language 64bit (10.0, Build 22631)
  • MSVC: C/C++ Optimizing Compiler Version 19.42.34436 for x86
  • vscode: 1.96.4 (cd4ee3b1c348a13bafd8f9ad8060705f6d4b9cba x64)
  • Git: git version 2.47.0.windows.2
  • Github CLI: gh version 2.27.0 (2023-04-07)

I successfully tested imgui_te with bool RenderInCurrentWindow = false;

Image

  • Performance impact: None (too small to bring any undesirable effects)
  • Memory impact: None (only consume one more byte of memory for the flags)
  • Compatibility impact: None (things work just fine as before the changes, dependencies remained the same)

Before posting the issues, I have...

  • Searched for similar feature requests regarding configurable rendering options.
  • Explored alternative libraries such as hello_imgui and imm_app to determine if they support rendering within an existing window.
  • Tested possible workarounds but found that they either required modifying core behavior or lacked flexibility.
  • Exploit some APIs to see if I can enforce the behaviour to be inside current window.
  • Asking chatgpt o1 pro, deepseek r1, perplexity, claude, github copilot, gemini, meta bot, grek, ... given certain knowledge about imgui_te and its implementations
  • Literally devour (or to says, intergrate, mix, alternate, modify, ...) certain parts of original functions just to mimic the needed behaviours.
  • Tested the solution and benchmark for performance to verified the impact of the change on UI performance and usability.
  • Checked for related issues like https://github.com/ocornut/imgui_test_engine/issues?q=current%20window
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant