Refactor: moved bits into Initialization section.

This commit is contained in:
ocornut 2022-12-06 11:54:15 +01:00
parent 713e034d95
commit b5883c1cfb

415
imgui.cpp
View File

@ -69,6 +69,7 @@ CODE
// [SECTION] ImGuiListClipper
// [SECTION] STYLING
// [SECTION] RENDER HELPERS
// [SECTION] INITIALIZATION, SHUTDOWN
// [SECTION] MAIN CODE (most of the code! lots of stuff, needs tidying up!)
// [SECTION] INPUTS
// [SECTION] ERROR CHECKING
@ -3396,6 +3397,215 @@ void ImGui::RenderMouseCursor(ImVec2 base_pos, float base_scale, ImGuiMouseCurso
}
}
//-----------------------------------------------------------------------------
// [SECTION] INITIALIZATION, SHUTDOWN
//-----------------------------------------------------------------------------
// Internal state access - if you want to share Dear ImGui state between modules (e.g. DLL) or allocate it yourself
// Note that we still point to some static data and members (such as GFontAtlas), so the state instance you end up using will point to the static data within its module
ImGuiContext* ImGui::GetCurrentContext()
{
return GImGui;
}
void ImGui::SetCurrentContext(ImGuiContext* ctx)
{
#ifdef IMGUI_SET_CURRENT_CONTEXT_FUNC
IMGUI_SET_CURRENT_CONTEXT_FUNC(ctx); // For custom thread-based hackery you may want to have control over this.
#else
GImGui = ctx;
#endif
}
void ImGui::SetAllocatorFunctions(ImGuiMemAllocFunc alloc_func, ImGuiMemFreeFunc free_func, void* user_data)
{
GImAllocatorAllocFunc = alloc_func;
GImAllocatorFreeFunc = free_func;
GImAllocatorUserData = user_data;
}
// This is provided to facilitate copying allocators from one static/DLL boundary to another (e.g. retrieve default allocator of your executable address space)
void ImGui::GetAllocatorFunctions(ImGuiMemAllocFunc* p_alloc_func, ImGuiMemFreeFunc* p_free_func, void** p_user_data)
{
*p_alloc_func = GImAllocatorAllocFunc;
*p_free_func = GImAllocatorFreeFunc;
*p_user_data = GImAllocatorUserData;
}
ImGuiContext* ImGui::CreateContext(ImFontAtlas* shared_font_atlas)
{
ImGuiContext* prev_ctx = GetCurrentContext();
ImGuiContext* ctx = IM_NEW(ImGuiContext)(shared_font_atlas);
SetCurrentContext(ctx);
Initialize();
if (prev_ctx != NULL)
SetCurrentContext(prev_ctx); // Restore previous context if any, else keep new one.
return ctx;
}
void ImGui::DestroyContext(ImGuiContext* ctx)
{
ImGuiContext* prev_ctx = GetCurrentContext();
if (ctx == NULL) //-V1051
ctx = prev_ctx;
SetCurrentContext(ctx);
Shutdown();
SetCurrentContext((prev_ctx != ctx) ? prev_ctx : NULL);
IM_DELETE(ctx);
}
// IMPORTANT: ###xxx suffixes must be same in ALL languages
static const ImGuiLocEntry GLocalizationEntriesEnUS[] =
{
{ ImGuiLocKey_TableSizeOne, "Size column to fit###SizeOne" },
{ ImGuiLocKey_TableSizeAllFit, "Size all columns to fit###SizeAll" },
{ ImGuiLocKey_TableSizeAllDefault, "Size all columns to default###SizeAll" },
{ ImGuiLocKey_TableResetOrder, "Reset order###ResetOrder" },
{ ImGuiLocKey_WindowingMainMenuBar, "(Main menu bar)" },
{ ImGuiLocKey_WindowingPopup, "(Popup)" },
{ ImGuiLocKey_WindowingUntitled, "(Untitled)" },
};
void ImGui::Initialize()
{
ImGuiContext& g = *GImGui;
IM_ASSERT(!g.Initialized && !g.SettingsLoaded);
// Add .ini handle for ImGuiWindow and ImGuiTable types
{
ImGuiSettingsHandler ini_handler;
ini_handler.TypeName = "Window";
ini_handler.TypeHash = ImHashStr("Window");
ini_handler.ClearAllFn = WindowSettingsHandler_ClearAll;
ini_handler.ReadOpenFn = WindowSettingsHandler_ReadOpen;
ini_handler.ReadLineFn = WindowSettingsHandler_ReadLine;
ini_handler.ApplyAllFn = WindowSettingsHandler_ApplyAll;
ini_handler.WriteAllFn = WindowSettingsHandler_WriteAll;
AddSettingsHandler(&ini_handler);
}
TableSettingsAddSettingsHandler();
// Setup default localization table
LocalizeRegisterEntries(GLocalizationEntriesEnUS, IM_ARRAYSIZE(GLocalizationEntriesEnUS));
// Create default viewport
ImGuiViewportP* viewport = IM_NEW(ImGuiViewportP)();
g.Viewports.push_back(viewport);
g.TempBuffer.resize(1024 * 3 + 1, 0);
#ifdef IMGUI_HAS_DOCK
#endif
g.Initialized = true;
}
// This function is merely here to free heap allocations.
void ImGui::Shutdown()
{
// The fonts atlas can be used prior to calling NewFrame(), so we clear it even if g.Initialized is FALSE (which would happen if we never called NewFrame)
ImGuiContext& g = *GImGui;
if (g.IO.Fonts && g.FontAtlasOwnedByContext)
{
g.IO.Fonts->Locked = false;
IM_DELETE(g.IO.Fonts);
}
g.IO.Fonts = NULL;
g.DrawListSharedData.TempBuffer.clear();
// Cleanup of other data are conditional on actually having initialized Dear ImGui.
if (!g.Initialized)
return;
// Save settings (unless we haven't attempted to load them: CreateContext/DestroyContext without a call to NewFrame shouldn't save an empty file)
if (g.SettingsLoaded && g.IO.IniFilename != NULL)
SaveIniSettingsToDisk(g.IO.IniFilename);
CallContextHooks(&g, ImGuiContextHookType_Shutdown);
// Clear everything else
g.Windows.clear_delete();
g.WindowsFocusOrder.clear();
g.WindowsTempSortBuffer.clear();
g.CurrentWindow = NULL;
g.CurrentWindowStack.clear();
g.WindowsById.Clear();
g.NavWindow = NULL;
g.HoveredWindow = g.HoveredWindowUnderMovingWindow = NULL;
g.ActiveIdWindow = g.ActiveIdPreviousFrameWindow = NULL;
g.MovingWindow = NULL;
g.KeysRoutingTable.Clear();
g.ColorStack.clear();
g.StyleVarStack.clear();
g.FontStack.clear();
g.OpenPopupStack.clear();
g.BeginPopupStack.clear();
g.Viewports.clear_delete();
g.TabBars.Clear();
g.CurrentTabBarStack.clear();
g.ShrinkWidthBuffer.clear();
g.ClipperTempData.clear_destruct();
g.Tables.Clear();
g.TablesTempData.clear_destruct();
g.DrawChannelsTempMergeBuffer.clear();
g.ClipboardHandlerData.clear();
g.MenusIdSubmittedThisFrame.clear();
g.InputTextState.ClearFreeMemory();
g.SettingsWindows.clear();
g.SettingsHandlers.clear();
if (g.LogFile)
{
#ifndef IMGUI_DISABLE_TTY_FUNCTIONS
if (g.LogFile != stdout)
#endif
ImFileClose(g.LogFile);
g.LogFile = NULL;
}
g.LogBuffer.clear();
g.DebugLogBuf.clear();
g.DebugLogIndex.clear();
g.Initialized = false;
}
// No specific ordering/dependency support, will see as needed
ImGuiID ImGui::AddContextHook(ImGuiContext* ctx, const ImGuiContextHook* hook)
{
ImGuiContext& g = *ctx;
IM_ASSERT(hook->Callback != NULL && hook->HookId == 0 && hook->Type != ImGuiContextHookType_PendingRemoval_);
g.Hooks.push_back(*hook);
g.Hooks.back().HookId = ++g.HookIdNext;
return g.HookIdNext;
}
// Deferred removal, avoiding issue with changing vector while iterating it
void ImGui::RemoveContextHook(ImGuiContext* ctx, ImGuiID hook_id)
{
ImGuiContext& g = *ctx;
IM_ASSERT(hook_id != 0);
for (int n = 0; n < g.Hooks.Size; n++)
if (g.Hooks[n].HookId == hook_id)
g.Hooks[n].Type = ImGuiContextHookType_PendingRemoval_;
}
// Call context hooks (used by e.g. test engine)
// We assume a small number of hooks so all stored in same array
void ImGui::CallContextHooks(ImGuiContext* ctx, ImGuiContextHookType hook_type)
{
ImGuiContext& g = *ctx;
for (int n = 0; n < g.Hooks.Size; n++)
if (g.Hooks[n].Type == hook_type)
g.Hooks[n].Callback(&g, &g.Hooks[n]);
}
//-----------------------------------------------------------------------------
// [SECTION] MAIN CODE (most of the code! lots of stuff, needs tidying up!)
@ -3842,89 +4052,6 @@ const char* ImGui::GetVersion()
return IMGUI_VERSION;
}
// Internal state access - if you want to share Dear ImGui state between modules (e.g. DLL) or allocate it yourself
// Note that we still point to some static data and members (such as GFontAtlas), so the state instance you end up using will point to the static data within its module
ImGuiContext* ImGui::GetCurrentContext()
{
return GImGui;
}
void ImGui::SetCurrentContext(ImGuiContext* ctx)
{
#ifdef IMGUI_SET_CURRENT_CONTEXT_FUNC
IMGUI_SET_CURRENT_CONTEXT_FUNC(ctx); // For custom thread-based hackery you may want to have control over this.
#else
GImGui = ctx;
#endif
}
void ImGui::SetAllocatorFunctions(ImGuiMemAllocFunc alloc_func, ImGuiMemFreeFunc free_func, void* user_data)
{
GImAllocatorAllocFunc = alloc_func;
GImAllocatorFreeFunc = free_func;
GImAllocatorUserData = user_data;
}
// This is provided to facilitate copying allocators from one static/DLL boundary to another (e.g. retrieve default allocator of your executable address space)
void ImGui::GetAllocatorFunctions(ImGuiMemAllocFunc* p_alloc_func, ImGuiMemFreeFunc* p_free_func, void** p_user_data)
{
*p_alloc_func = GImAllocatorAllocFunc;
*p_free_func = GImAllocatorFreeFunc;
*p_user_data = GImAllocatorUserData;
}
ImGuiContext* ImGui::CreateContext(ImFontAtlas* shared_font_atlas)
{
ImGuiContext* prev_ctx = GetCurrentContext();
ImGuiContext* ctx = IM_NEW(ImGuiContext)(shared_font_atlas);
SetCurrentContext(ctx);
Initialize();
if (prev_ctx != NULL)
SetCurrentContext(prev_ctx); // Restore previous context if any, else keep new one.
return ctx;
}
void ImGui::DestroyContext(ImGuiContext* ctx)
{
ImGuiContext* prev_ctx = GetCurrentContext();
if (ctx == NULL) //-V1051
ctx = prev_ctx;
SetCurrentContext(ctx);
Shutdown();
SetCurrentContext((prev_ctx != ctx) ? prev_ctx : NULL);
IM_DELETE(ctx);
}
// No specific ordering/dependency support, will see as needed
ImGuiID ImGui::AddContextHook(ImGuiContext* ctx, const ImGuiContextHook* hook)
{
ImGuiContext& g = *ctx;
IM_ASSERT(hook->Callback != NULL && hook->HookId == 0 && hook->Type != ImGuiContextHookType_PendingRemoval_);
g.Hooks.push_back(*hook);
g.Hooks.back().HookId = ++g.HookIdNext;
return g.HookIdNext;
}
// Deferred removal, avoiding issue with changing vector while iterating it
void ImGui::RemoveContextHook(ImGuiContext* ctx, ImGuiID hook_id)
{
ImGuiContext& g = *ctx;
IM_ASSERT(hook_id != 0);
for (int n = 0; n < g.Hooks.Size; n++)
if (g.Hooks[n].HookId == hook_id)
g.Hooks[n].Type = ImGuiContextHookType_PendingRemoval_;
}
// Call context hooks (used by e.g. test engine)
// We assume a small number of hooks so all stored in same array
void ImGui::CallContextHooks(ImGuiContext* ctx, ImGuiContextHookType hook_type)
{
ImGuiContext& g = *ctx;
for (int n = 0; n < g.Hooks.Size; n++)
if (g.Hooks[n].Type == hook_type)
g.Hooks[n].Callback(&g, &g.Hooks[n]);
}
ImGuiIO& ImGui::GetIO()
{
IM_ASSERT(GImGui != NULL && "No current context. Did you call ImGui::CreateContext() and ImGui::SetCurrentContext() ?");
@ -4834,128 +4961,6 @@ void ImGui::NewFrame()
CallContextHooks(&g, ImGuiContextHookType_NewFramePost);
}
// IMPORTANT: ###xxx suffixes must be same in ALL languages
static const ImGuiLocEntry GLocalizationEntriesEnUS[] =
{
{ ImGuiLocKey_TableSizeOne, "Size column to fit###SizeOne" },
{ ImGuiLocKey_TableSizeAllFit, "Size all columns to fit###SizeAll" },
{ ImGuiLocKey_TableSizeAllDefault, "Size all columns to default###SizeAll" },
{ ImGuiLocKey_TableResetOrder, "Reset order###ResetOrder" },
{ ImGuiLocKey_WindowingMainMenuBar, "(Main menu bar)" },
{ ImGuiLocKey_WindowingPopup, "(Popup)" },
{ ImGuiLocKey_WindowingUntitled, "(Untitled)" },
};
void ImGui::Initialize()
{
ImGuiContext& g = *GImGui;
IM_ASSERT(!g.Initialized && !g.SettingsLoaded);
// Add .ini handle for ImGuiWindow and ImGuiTable types
{
ImGuiSettingsHandler ini_handler;
ini_handler.TypeName = "Window";
ini_handler.TypeHash = ImHashStr("Window");
ini_handler.ClearAllFn = WindowSettingsHandler_ClearAll;
ini_handler.ReadOpenFn = WindowSettingsHandler_ReadOpen;
ini_handler.ReadLineFn = WindowSettingsHandler_ReadLine;
ini_handler.ApplyAllFn = WindowSettingsHandler_ApplyAll;
ini_handler.WriteAllFn = WindowSettingsHandler_WriteAll;
AddSettingsHandler(&ini_handler);
}
TableSettingsAddSettingsHandler();
// Setup default localization table
LocalizeRegisterEntries(GLocalizationEntriesEnUS, IM_ARRAYSIZE(GLocalizationEntriesEnUS));
// Create default viewport
ImGuiViewportP* viewport = IM_NEW(ImGuiViewportP)();
g.Viewports.push_back(viewport);
g.TempBuffer.resize(1024 * 3 + 1, 0);
#ifdef IMGUI_HAS_DOCK
#endif
g.Initialized = true;
}
// This function is merely here to free heap allocations.
void ImGui::Shutdown()
{
// The fonts atlas can be used prior to calling NewFrame(), so we clear it even if g.Initialized is FALSE (which would happen if we never called NewFrame)
ImGuiContext& g = *GImGui;
if (g.IO.Fonts && g.FontAtlasOwnedByContext)
{
g.IO.Fonts->Locked = false;
IM_DELETE(g.IO.Fonts);
}
g.IO.Fonts = NULL;
g.DrawListSharedData.TempBuffer.clear();
// Cleanup of other data are conditional on actually having initialized Dear ImGui.
if (!g.Initialized)
return;
// Save settings (unless we haven't attempted to load them: CreateContext/DestroyContext without a call to NewFrame shouldn't save an empty file)
if (g.SettingsLoaded && g.IO.IniFilename != NULL)
SaveIniSettingsToDisk(g.IO.IniFilename);
CallContextHooks(&g, ImGuiContextHookType_Shutdown);
// Clear everything else
g.Windows.clear_delete();
g.WindowsFocusOrder.clear();
g.WindowsTempSortBuffer.clear();
g.CurrentWindow = NULL;
g.CurrentWindowStack.clear();
g.WindowsById.Clear();
g.NavWindow = NULL;
g.HoveredWindow = g.HoveredWindowUnderMovingWindow = NULL;
g.ActiveIdWindow = g.ActiveIdPreviousFrameWindow = NULL;
g.MovingWindow = NULL;
g.KeysRoutingTable.Clear();
g.ColorStack.clear();
g.StyleVarStack.clear();
g.FontStack.clear();
g.OpenPopupStack.clear();
g.BeginPopupStack.clear();
g.Viewports.clear_delete();
g.TabBars.Clear();
g.CurrentTabBarStack.clear();
g.ShrinkWidthBuffer.clear();
g.ClipperTempData.clear_destruct();
g.Tables.Clear();
g.TablesTempData.clear_destruct();
g.DrawChannelsTempMergeBuffer.clear();
g.ClipboardHandlerData.clear();
g.MenusIdSubmittedThisFrame.clear();
g.InputTextState.ClearFreeMemory();
g.SettingsWindows.clear();
g.SettingsHandlers.clear();
if (g.LogFile)
{
#ifndef IMGUI_DISABLE_TTY_FUNCTIONS
if (g.LogFile != stdout)
#endif
ImFileClose(g.LogFile);
g.LogFile = NULL;
}
g.LogBuffer.clear();
g.DebugLogBuf.clear();
g.DebugLogIndex.clear();
g.Initialized = false;
}
// FIXME: Add a more explicit sort order in the window structure.
static int IMGUI_CDECL ChildWindowComparer(const void* lhs, const void* rhs)
{