Creating GUI tabs with a C++ mod

UE4SS already includes the ImGui library to render its console GUI, built from the UE4SS-RE/imgui repo. Refer to ImGui documentation in that repo on how to use ImGui-specific classes and methods for rendering actual buttons and textboxes and other window objects.

This guide will show how you create custom tabs for the GUI with a C++ mod, and the guide will take the form of comments in the code example below:

#include <Mod/CppUserModBase.hpp>
#include <UE4SSProgram.hpp>

class MyAwesomeMod : public RC::CppUserModBase
    int m_private_number{33};
    std::shared_ptr<GUI::GUITab> m_less_safe_tab{};

    MyAwesomeMod() : CppUserModBase()
        ModName = STR("MyAwesomeMod");
        ModVersion = STR("1.0");
        ModDescription = STR("This is my awesome mod");
        ModAuthors = STR("UE4SS Team");
        // It's critical that you enable ImGui before you create your tab.
        // If you don't do this, a crash will occur as soon as ImGui tries to render anything in your tab.
        // The 'register_tab' function will tell UE4SS to render a tab.
        // Tabs registered this way will be automatically cleaned up when this C++ mod is destructed.
        // The first param is the display name of your tab.
        // The second param is a callback that UE4SS will use to render the contents of the tab.
        // The param to the callback is a pointer to your mod.
        register_tab(STR("My Test Tab"), [](CppUserModBase* instance) {
            // In this callback, you can start rendering the contents of your tab with ImGui. 
            ImGui::Text("This is the contents of the tab");
            // You can access members of your mod class with the 'instance' param.
            auto mod = dynamic_cast<MyAwesomeMod*>(instance);
            if (!mod)
                // Something went wrong that caused the 'instance' to not be correctly set.
                // Let's abort the rest of the function so that you don't access an invalid pointer.
            // You can access both public and private members.
        // The 'UE4SSProgram::add_gui_tab' function is another way to tell UE4SS to render a tab.
        // This way of registering a tab will make you responsible for cleaning up the tab when your mod destructs.
        // Failure to clean up the tab on mod destruction will result in a crash.
        // It's recommended that you use 'register_tab' instead of this function.
        m_less_safe_tab = std::make_shared<GUI::GUITab>(STR("My Less Safe Tab"), [](CppUserModBase* instance) {
            // This callback is identical to the one used with 'register_tab' except 'instance' is always nullptr.
            ImGui::Text("This is the contents of the less safe tab");

    ~MyAwesomeMod() override
        // Because you created a tab with 'UE4SSProgram::add_gui_tab', you must manually remove it.
        // Failure to remove the tab will result in a crash.
    auto render_some_stuff(int Number) -> void
        auto calculated_value = Number + 1;
        ImGui::Text(std::format("calculated_value: {}", calculated_value).c_str());

#define MY_AWESOME_MOD_API __declspec(dllexport)
extern "C"
    MY_AWESOME_MOD_API RC::CppUserModBase* start_mod()
        return new MyAwesomeMod();

    MY_AWESOME_MOD_API void uninstall_mod(RC::CppUserModBase* mod)
        delete mod;