Here, we will document important internal classes.

Core/Defines.hpp

The Defines.hpp header contains the following definitions:

  1. Defines the std_filesystem macro, to make working with older compilers that support std::filesystem as part of std::experimental::filesystem possible
  2. Defines the IMGUI_START macro that is called as the first thing in the entry point.
  3. Defines the CAST macro that does a static_cast to go around some linter warnings.
  4. Defines the FCAST macro that does a C-style cast to go around some linter and compiler warning. The F stands for "force".
  5. Creates C++ type definitions for ComponentType and ComponentState.

The C alternative, CDefines.h, defines the following:

  1. Defines __declspec(dllimport)/__declspec(dllexport) when compiling for Windows
  2. The UNUSED macro that can be used to remove UNUSED warnings for functions whose return types are marked as [[nodiscard]]
  3. The CARRAY_SIZE macro that returns the size of a static C-style array
  4. The C implementation of UImGui_ComponentType and UImGui_ComponentState.

It also defines the following strings that can be used to set the semantic type of window in X11(more info on the Window Interface page). They look like this:

#define X11_WINDOW_TYPE_DESKTOP "_NET_WM_WINDOW_TYPE_DESKTOP"
#define X11_WINDOW_TYPE_DOCK "_NET_WM_WINDOW_TYPE_DOCK"
#define X11_WINDOW_TYPE_TOOLBAR "_NET_WM_WINDOW_TYPE_TOOLBAR"
#define X11_WINDOW_TYPE_MENU "_NET_WM_WINDOW_TYPE_MENU"
#define X11_WINDOW_TYPE_UTILITY "_NET_WM_WINDOW_TYPE_UTILITY"
#define X11_WINDOW_TYPE_SPLASH "_NET_WM_WINDOW_TYPE_SPLASH"
#define X11_WINDOW_TYPE_DIALOG "_NET_WM_WINDOW_TYPE_DIALOG"
#define X11_WINDOW_TYPE_NORMAL "_NET_WM_WINDOW_TYPE_NORMAL"

Core/Global

This class defines the Global class, which stores global data used internally. It has the following members:

  1. Pointer to the current Instance
  2. Pointer to the current RendererInternal class, which represents the renderer
  3. A single instance of WindowInternal
  4. A single instance of ModulesManager
  5. A single instance of the CDeallocationStruct - More information here

Core/FrameworkMain

This class defines the FrameworkMain class that serves as a bridge between the entry point application and the framework and/or project library. Functions in this class deal with tasks such as collecting CLI arguments, sharing instances between libraries and more.

Core/Types.hpp

It defines the following types:

// Redefine for C++
typedef UImGui_FVector2 FVector2;
typedef UImGui_FVector FVector;
typedef UImGui_FVector4 FVector4;
typedef UImGui_String String;
typedef std::string FString;

YAML::Emitter& operator<<(YAML::Emitter& out, const FVector4& vect) noexcept;
YAML::Emitter& operator<<(YAML::Emitter& out, const FVector& vect) noexcept;
YAML::Emitter& operator<<(YAML::Emitter& out, const FVector2& vect) noexcept;

and also calls using namespace UVKLog; to remove the UVKLog namespace when logging.

The above type definitions are imported from the C API at CTypes.h, which looks like this:

struct UIMGUI_PUBLIC_API UImGui_FVector2_I
{
    float x;
    float y;
};

struct UIMGUI_PUBLIC_API UImGui_FVector_I
{
    float x;
    float y;
    float z;
};

struct UIMGUI_PUBLIC_API UImGui_FVector4_I
{
    float x;
    float y;
    float z;
    float w;
};

typedef const char* UImGui_String;

typedef struct UImGui_FVector2_I UImGui_FVector2;
typedef struct UImGui_FVector_I UImGui_FVector;
typedef struct UImGui_FVector4_I UImGui_FVector4;

The 3 operator<< overrides allow our vector types to easily be output to YAML. Additionally, the following class definitions allow us to easily load YAML into those types:

namespace YAML
{
    template<>
    struct convert<UImGui::FVector4>
    {
        static Node encode(const UImGui::FVector4& rhs) noexcept
        {
            Node node;
            node.push_back(rhs.x);
            node.push_back(rhs.y);
            node.push_back(rhs.z);
            node.push_back(rhs.w);
            node.SetStyle(EmitterStyle::Flow);
            return node;
        }

        static bool decode(const Node& node, UImGui::FVector4& rhs) noexcept
        {
            if (!node.IsSequence() || node.size() != 4)
                return false;

            rhs.x = node[0].as<float>();
            rhs.y = node[1].as<float>();
            rhs.z = node[2].as<float>();
            rhs.w = node[3].as<float>();
            return true;
        }
    };

    template<>
    struct convert<UImGui::FVector>
    {
        static Node encode(const UImGui::FVector& rhs) noexcept
        {
            Node node;
            node.push_back(rhs.x);
            node.push_back(rhs.y);
            node.push_back(rhs.z);
            node.SetStyle(EmitterStyle::Flow);
            return node;
        }

        static bool decode(const Node& node, UImGui::FVector& rhs) noexcept
        {
            if (!node.IsSequence() || node.size() != 3)
                return false;

            rhs.x = node[0].as<float>();
            rhs.y = node[1].as<float>();
            rhs.z = node[2].as<float>();
            return true;
        }
    };

    template<>
    struct convert<UImGui::FVector2>
    {
        static Node encode(const UImGui::FVector2& rhs) noexcept
        {
            Node node;
            node.push_back(rhs.x);
            node.push_back(rhs.y);
            node.SetStyle(EmitterStyle::Flow);
            return node;
        }

        static bool decode(const Node& node, UImGui::FVector2& rhs) noexcept
        {
            if (!node.IsSequence() || node.size() != 2)
                return false;

            rhs.x = node[0].as<float>();
            rhs.y = node[1].as<float>();
            return true;
        }
    };
}

Core/CDeallocation.hpp

This file contains a struct that stores some intermediate data for the C API. The max memory complexity is estimated at somewhere below 100% more memory. THe struct currently looks like this:

struct UIMGUI_PUBLIC_API CDeallocationStruct
{
    std::vector<FString> keyStrings; // Stores temporary strings
    std::vector<UImGui_CMonitorData> monitors; // Stores temporary C monitor structs
};

Modules/Manager/ModulesManager

This file defines the internal ModulesManager class, the Modules interface and the ModuleSettings struct.

The ModulesManager class manages module settings, which module is enabled at runtime and at compile time, and managing the modules' lifetime.

It looks like this:

class ModulesManager
{
private:
    ModuleSettings settings;
#ifdef UIMGUI_LOCALE_MODULE_ENABLED
    LocaleManager localeManager{};
#endif

#ifdef UIMGUI_UNDO_MODULE_ENABLED
    StateTracker stateTracker{};
#endif

    void init(const FString& configDir);
    void initModules(const FString& projectDir);
    void save(const FString& configDir) const noexcept;
};

Reference:

  1. init - Loads module settings
  2. initModules - Initializes modules with the settings
  3. save - saves settings to Modules.yaml

Renderer/Renderer

The internal Renderer class looks like this:

class RendererInternal
{
public:
    void start();
    void stop() const noexcept;

    RendererInternalMetadata metadata;
private:
    static void tick(void* rendererInstance) noexcept;

    void loadConfig() noexcept;
    void saveConfig() const noexcept;

    OpenGLRenderer opengl{};
ef __EMSCRIPTEN__
    WebGPURenderer wgpu{};
e
    VulkanRenderer vulkan{};
if
    GenericRenderer* custom = nullptr;
    GenericRenderer* renderers[UIMGUI_RENDERER_TYPE_COUNT] =
    {
        &opengl,
ef __EMSCRIPTEN__
        &wgpu,
e
        &vulkan,
if
        custom
    };
    GenericRenderer* renderer = nullptr;
    RendererData data =
    {
        .rendererType = UIMGUI_RENDERER_TYPE_OPENGL,
        .textureRendererType = UIMGUI_RENDERER_TYPE_OPENGL,
        .bUsingVSync = true,
        .msaaSamples = 1,
        .bEnablePowerSavingMode = false,
        .idleFrameRate = 9.0f
    };
    YAML::Node customConfig;
    double lastTime = 0.0f;
    bool bIdling = false;
};

Reference:

  1. start - Initializes and starts the renderer
  2. stop - Destroys the renderer and deallocates all renderer data
  3. loadConfig - Loads the renderer config file, Renderer.yaml
  4. saveConfig - Saves the renderer data stored in the data field to Renderer.yaml
  5. metadata - The internal renderer metadata struct
  6. opengl, webgpu, vulkan and custom - Instances of the OpenGL, Vulkan, WebGPU and an optional custom renderer respectively
  7. renderers and renderer - An array of all renderers mapped to the RendererType enum and a pointer to the current active renderer
  8. data - The internal renderer data struct
  9. customConfig - The internal custom renderer configuration native C++ YAML object
  10. lastTime - The frame render time for rendering the last frame
  11. bIdling - An internal boolean that tracks whether the user is idling. Used when power-saving is enabled

ImGui/ImGui

The GUIRenderer class contains internal functions that set up dear imgui through the different stages of the render loop. It looks like this:

class GUIRenderer
{
private:
    static void init(GenericRenderer* renderer) noexcept;
    static void beginUI(float deltaTime, GenericRenderer* renderer) noexcept;
    static void beginFrame() noexcept;
    static void shutdown(GenericRenderer* renderer) noexcept;
};

Reference:

  1. init - Creates an imgui context, sets up themes and style, calls the begin events of the components and the instance
  2. beginUI - Called at the beginning of every render loop iteration
  3. beginFrame - Starts a new imgui frame
  4. shutdown - Cleans up imgui resources

Window

Internal monitor C and C++ API bridge

The Monitor class contains the CInternalGetMonitorClassDoNotTouch member class, which looks like this:

class CInternalGetMonitorClassDoNotTouch
{
public:
    static UImGui_CMonitorData UImGui_Window_getWindowMonitor();
    static void pushGlobalMonitorCallbackFun(UImGui::Monitor& monitor, UImGui::MonitorState state,
                                             UImGui_Window_pushGlobalMonitorCallbackFun f);
    static void UImGui_Monitor_pushEvent(UImGui_CMonitorData* data, UImGui_Monitor_EventsFun f);
    static void UImGui_Monitor_setWindowMonitor(UImGui_CMonitorData* monitor);
    static UImGui_CMonitorData* UImGui_Window_getMonitors(size_t* size);
};

It is here, mostly because of our header file design, which prevents us from using friend functions for accessing the private GLFWmonitor*. This class exists to store these functions, which will have access to the private GLFWmonitor*. These will then be called from the implementation of the C API functions.