Reorganized context handling to be more explicit,

- YOU NOW NEED TO CALL ImGui::CreateContext() AT THE BEGINNING OF YOUR APP, AND CALL ImGui::DestroyContext() AT THE END.
- removed Shutdown() function, as DestroyContext() serve this purpose.
- you may pass a ImFontAtlas* pointer to CreateContext() to share a font atlas between contexts. Otherwhise CreateContext() will create its own font atlas instance.
- removed allocator parameters from CreateContext(), they are now setup with SetAllocatorFunctions(), and shared by all contexts.
- removed the default global context and font atlas instance, which were confusing for users of DLL reloading and users of multiple contexts
(#1565, #586, #992, #1007, #1558)
This commit is contained in:
omar 2018-01-21 19:58:32 +01:00
parent 7e4d28a49d
commit 5e2aa6185c
3 changed files with 49 additions and 34 deletions

View File

@ -125,6 +125,7 @@
- A minimal application skeleton may be: - A minimal application skeleton may be:
// Application init // Application init
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
io.DisplaySize.x = 1920.0f; io.DisplaySize.x = 1920.0f;
io.DisplaySize.y = 1280.0f; io.DisplaySize.y = 1280.0f;
@ -162,6 +163,10 @@
SwapBuffers(); SwapBuffers();
} }
// Shutdown
ImGui::DestroyContext();
- A minimal render function skeleton may be: - A minimal render function skeleton may be:
void void MyRenderFunction(ImDrawData* draw_data)(ImDrawData* draw_data) void void MyRenderFunction(ImDrawData* draw_data)(ImDrawData* draw_data)
@ -213,7 +218,12 @@
Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code. Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code.
Also read releases logs https://github.com/ocornut/imgui/releases for more details. Also read releases logs https://github.com/ocornut/imgui/releases for more details.
- 2018/01/20 (1.XX) - removed allocator parameters from CreateContext(), they are now setup with SetAllocatorFunctions() and shared by all contexts. - 2018/01/21 (1.XX) - reorganized context handling to be more explicit,
- YOU NOW NEED TO CALL ImGui::CreateContext() AT THE BEGINNING OF YOUR APP, AND CALL ImGui::DestroyContext() AT THE END.
- removed Shutdown() function, as DestroyContext() serve this purpose.
- you may pass a ImFontAtlas* pointer to CreateContext() to share a font atlas between contexts. Otherwhise CreateContext() will create its own font atlas instance.
- removed allocator parameters from CreateContext(), they are now setup with SetAllocatorFunctions(), and shared by all contexts.
- removed the default global context and font atlas instance, which were confusing for users of DLL reloading and users of multiple contexts.
- 2018/01/11 (1.54) - obsoleted IsAnyWindowHovered() in favor of IsWindowHovered(ImGuiHoveredFlags_AnyWindow). Kept redirection function (will obsolete). - 2018/01/11 (1.54) - obsoleted IsAnyWindowHovered() in favor of IsWindowHovered(ImGuiHoveredFlags_AnyWindow). Kept redirection function (will obsolete).
- 2018/01/11 (1.54) - obsoleted IsAnyWindowFocused() in favor of IsWindowFocused(ImGuiFocusedFlags_AnyWindow). Kept redirection function (will obsolete). - 2018/01/11 (1.54) - obsoleted IsAnyWindowFocused() in favor of IsWindowFocused(ImGuiFocusedFlags_AnyWindow). Kept redirection function (will obsolete).
- 2018/01/03 (1.54) - renamed ImGuiSizeConstraintCallback to ImGuiSizeCallback, ImGuiSizeConstraintCallbackData to ImGuiSizeCallbackData. - 2018/01/03 (1.54) - renamed ImGuiSizeConstraintCallback to ImGuiSizeCallback, ImGuiSizeConstraintCallbackData to ImGuiSizeCallbackData.
@ -695,19 +705,14 @@ static void ImeSetInputScreenPosFn_DefaultImpl(int x, int y);
// Context // Context
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Default font atlas storage. // Current context pointer. Implicitely used by all ImGui functions. Always assumed to be != NULL.
// New contexts always point by default to this font atlas. It can be changed by reassigning the GetIO().Fonts variable. // CreateContext() will automatically set this pointer if it is NULL. Change to a different context by calling ImGui::SetCurrentContext().
static ImFontAtlas GImDefaultFontAtlas; // If you use DLL hotreloading you might need to call SetCurrentContext() after reloading code from this file.
// ImGui functions are not thread-safe because of this pointer. If you want thread-safety to allow N threads to access N different contexts, you can:
// Default context storage + current context pointer. // - Change this variable to use thread local storage. You may #define GImGui in imconfig.h for that purpose. Future development aim to make this context pointer explicit to all calls. Also read https://github.com/ocornut/imgui/issues/586
// Implicitely used by all ImGui functions. Always assumed to be != NULL. Change to a different context by calling ImGui::SetCurrentContext()
// If you are hot-reloading this code in a DLL you will lose the static/global variables. Create your own context+font atlas instead of relying on those default (see FAQ entry "How can I preserve my ImGui context across reloading a DLL?").
// ImGui is currently not thread-safe because of this variable. If you want thread-safety to allow N threads to access N different contexts, you might work around it by:
// - Having multiple instances of the ImGui code compiled inside different namespace (easiest/safest, if you have a finite number of contexts) // - Having multiple instances of the ImGui code compiled inside different namespace (easiest/safest, if you have a finite number of contexts)
// - or: Changing this variable to be TLS. You may #define GImGui in imconfig.h for further custom hackery. Future development aim to make this context pointer explicit to all calls. Also read https://github.com/ocornut/imgui/issues/586
#ifndef GImGui #ifndef GImGui
static ImGuiContext GImDefaultContext; ImGuiContext* GImGui = NULL;
ImGuiContext* GImGui = &GImDefaultContext;
#endif #endif
// Memory Allocator functions. Use SetAllocatorFunctions() to change them. // Memory Allocator functions. Use SetAllocatorFunctions() to change them.
@ -807,7 +812,7 @@ ImGuiIO::ImGuiIO()
KeyRepeatRate = 0.050f; KeyRepeatRate = 0.050f;
UserData = NULL; UserData = NULL;
Fonts = &GImDefaultFontAtlas; Fonts = NULL;
FontGlobalScale = 1.0f; FontGlobalScale = 1.0f;
FontDefault = NULL; FontDefault = NULL;
FontAllowUserScaling = false; FontAllowUserScaling = false;
@ -2237,14 +2242,19 @@ void ImGui::SetAllocatorFunctions(void* (*alloc_func)(size_t sz, void* user_data
GImAllocatorUserData = user_data; GImAllocatorUserData = user_data;
} }
ImGuiContext* ImGui::CreateContext() ImGuiContext* ImGui::CreateContext(ImFontAtlas* shared_font_atlas)
{ {
ImGuiContext* ctx = IM_NEW(ImGuiContext)(); ImGuiContext* ctx = IM_NEW(ImGuiContext)(shared_font_atlas);
if (GImGui == NULL)
SetCurrentContext(ctx);
return ctx; return ctx;
} }
void ImGui::DestroyContext(ImGuiContext* ctx) void ImGui::DestroyContext(ImGuiContext* ctx)
{ {
if (ctx == NULL)
ctx = GImGui;
Shutdown(ctx);
if (GImGui == ctx) if (GImGui == ctx)
SetCurrentContext(NULL); SetCurrentContext(NULL);
IM_DELETE(ctx); IM_DELETE(ctx);
@ -2252,11 +2262,13 @@ void ImGui::DestroyContext(ImGuiContext* ctx)
ImGuiIO& ImGui::GetIO() ImGuiIO& ImGui::GetIO()
{ {
IM_ASSERT(GImGui != NULL && "No current context. Did you call ImGui::CreateContext() or ImGui::SetCurrentContext()?");
return GImGui->IO; return GImGui->IO;
} }
ImGuiStyle& ImGui::GetStyle() ImGuiStyle& ImGui::GetStyle()
{ {
IM_ASSERT(GImGui != NULL && "No current context. Did you call ImGui::CreateContext() or ImGui::SetCurrentContext()?");
return GImGui->Style; return GImGui->Style;
} }
@ -2304,7 +2316,7 @@ void ImGui::NewFrame()
// Initialize on first frame // Initialize on first frame
if (!g.Initialized) if (!g.Initialized)
Initialize(); Initialize(&g);
g.Time += g.IO.DeltaTime; g.Time += g.IO.DeltaTime;
g.FrameCount += 1; g.FrameCount += 1;
@ -2624,9 +2636,9 @@ static void SettingsHandlerWindow_WriteAll(ImGuiContext* imgui_ctx, ImGuiSetting
} }
} }
void ImGui::Initialize() void ImGui::Initialize(ImGuiContext* context)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *context;
g.LogClipboard = IM_NEW(ImGuiTextBuffer)(); g.LogClipboard = IM_NEW(ImGuiTextBuffer)();
// Add .ini handle for ImGuiWindow type // Add .ini handle for ImGuiWindow type
@ -2645,13 +2657,13 @@ void ImGui::Initialize()
} }
// This function is merely here to free heap allocations. // This function is merely here to free heap allocations.
void ImGui::Shutdown() void ImGui::Shutdown(ImGuiContext* context)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *context;
// 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) // 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)
if (g.IO.Fonts) // Testing for NULL to allow user to NULLify in case of running Shutdown() on multiple contexts. Bit hacky. if (g.IO.Fonts && g.FontAtlasOwnedByContext)
g.IO.Fonts->Clear(); IM_DELETE(g.IO.Fonts);
// Cleanup of other data are conditional on actually having initialize ImGui. // Cleanup of other data are conditional on actually having initialize ImGui.
if (!g.Initialized) if (!g.Initialized)

19
imgui.h
View File

@ -127,6 +127,14 @@ struct ImVec4
// In a namespace so that user can add extra functions in a separate file (e.g. Value() helpers for your vector or common types) // In a namespace so that user can add extra functions in a separate file (e.g. Value() helpers for your vector or common types)
namespace ImGui namespace ImGui
{ {
// Context creation and access, if you want to use multiple context, share context between modules (e.g. DLL).
// All contexts share a same ImFontAtlas by default. If you want different font atlas, you can new() them and overwrite the GetIO().Fonts variable of an ImGui context.
// All those functions are not reliant on the current context.
IMGUI_API ImGuiContext* CreateContext(ImFontAtlas* shared_font_atlas = NULL);
IMGUI_API void DestroyContext(ImGuiContext* ctx = NULL); // NULL = Destroy current context
IMGUI_API ImGuiContext* GetCurrentContext();
IMGUI_API void SetCurrentContext(ImGuiContext* ctx);
// Main // Main
IMGUI_API ImGuiIO& GetIO(); IMGUI_API ImGuiIO& GetIO();
IMGUI_API ImGuiStyle& GetStyle(); IMGUI_API ImGuiStyle& GetStyle();
@ -134,7 +142,6 @@ namespace ImGui
IMGUI_API void NewFrame(); // start a new ImGui frame, you can submit any command from this point until Render()/EndFrame(). IMGUI_API void NewFrame(); // start a new ImGui frame, you can submit any command from this point until Render()/EndFrame().
IMGUI_API void Render(); // ends the ImGui frame, finalize the draw data, then call your io.RenderDrawListsFn() function if set. IMGUI_API void Render(); // ends the ImGui frame, finalize the draw data, then call your io.RenderDrawListsFn() function if set.
IMGUI_API void EndFrame(); // ends the ImGui frame. automatically called by Render(), so most likely don't need to ever call that yourself directly. If you don't need to render you may call EndFrame() but you'll have wasted CPU already. If you don't need to render, better to not create any imgui windows instead! IMGUI_API void EndFrame(); // ends the ImGui frame. automatically called by Render(), so most likely don't need to ever call that yourself directly. If you don't need to render you may call EndFrame() but you'll have wasted CPU already. If you don't need to render, better to not create any imgui windows instead!
IMGUI_API void Shutdown();
// Demo, Debug, Informations // Demo, Debug, Informations
IMGUI_API void ShowDemoWindow(bool* p_open = NULL); // create demo/test window (previously called ShowTestWindow). demonstrate most ImGui features. call this to learn about the library! try to make it always available in your application! IMGUI_API void ShowDemoWindow(bool* p_open = NULL); // create demo/test window (previously called ShowTestWindow). demonstrate most ImGui features. call this to learn about the library! try to make it always available in your application!
@ -143,6 +150,7 @@ namespace ImGui
IMGUI_API bool ShowStyleSelector(const char* label); IMGUI_API bool ShowStyleSelector(const char* label);
IMGUI_API void ShowFontSelector(const char* label); IMGUI_API void ShowFontSelector(const char* label);
IMGUI_API void ShowUserGuide(); // add basic help/info block (not a window): how to manipulate ImGui as a end-user (mouse/keyboard controls). IMGUI_API void ShowUserGuide(); // add basic help/info block (not a window): how to manipulate ImGui as a end-user (mouse/keyboard controls).
IMGUI_API const char* GetVersion();
// Window // Window
IMGUI_API bool Begin(const char* name, bool* p_open = NULL, ImGuiWindowFlags flags = 0); // push window to the stack and start appending to it. see .cpp for details. return false when window is collapsed (so you can early out in your code) but you always need to call End() regardless. 'bool* p_open' creates a widget on the upper-right to close the window (which sets your bool to false). IMGUI_API bool Begin(const char* name, bool* p_open = NULL, ImGuiWindowFlags flags = 0); // push window to the stack and start appending to it. see .cpp for details. return false when window is collapsed (so you can early out in your code) but you always need to call End() regardless. 'bool* p_open' creates a widget on the upper-right to close the window (which sets your bool to false).
@ -510,15 +518,6 @@ namespace ImGui
IMGUI_API const char* GetClipboardText(); IMGUI_API const char* GetClipboardText();
IMGUI_API void SetClipboardText(const char* text); IMGUI_API void SetClipboardText(const char* text);
// Context creation and access, if you want to use multiple context, share context between modules (e.g. DLL). There is a default context created and active by default.
// All contexts share a same ImFontAtlas by default. If you want different font atlas, you can new() them and overwrite the GetIO().Fonts variable of an ImGui context.
// All those functions are not reliant on the current context.
IMGUI_API const char* GetVersion();
IMGUI_API ImGuiContext* CreateContext();
IMGUI_API void DestroyContext(ImGuiContext* ctx);
IMGUI_API ImGuiContext* GetCurrentContext();
IMGUI_API void SetCurrentContext(ImGuiContext* ctx);
} // namespace ImGui } // namespace ImGui
// Flags for ImGui::Begin() // Flags for ImGui::Begin()

View File

@ -497,6 +497,7 @@ struct ImGuiNextWindowData
struct ImGuiContext struct ImGuiContext
{ {
bool Initialized; bool Initialized;
bool FontAtlasOwnedByContext; // Io.Fonts-> is owned by the ImGuiContext and will be destructed along with it.
ImGuiIO IO; ImGuiIO IO;
ImGuiStyle Style; ImGuiStyle Style;
ImFont* Font; // (Shortcut) == FontStack.empty() ? IO.Font : FontStack.back() ImFont* Font; // (Shortcut) == FontStack.empty() ? IO.Font : FontStack.back()
@ -598,11 +599,13 @@ struct ImGuiContext
int WantTextInputNextFrame; int WantTextInputNextFrame;
char TempBuffer[1024*3+1]; // temporary text buffer char TempBuffer[1024*3+1]; // temporary text buffer
ImGuiContext() : OverlayDrawList(NULL) ImGuiContext(ImFontAtlas* shared_font_atlas) : OverlayDrawList(NULL)
{ {
Initialized = false; Initialized = false;
Font = NULL; Font = NULL;
FontSize = FontBaseSize = 0.0f; FontSize = FontBaseSize = 0.0f;
FontAtlasOwnedByContext = shared_font_atlas ? false : true;
IO.Fonts = shared_font_atlas ? shared_font_atlas : IM_NEW(ImFontAtlas)();
Time = 0.0f; Time = 0.0f;
FrameCount = 0; FrameCount = 0;
@ -864,7 +867,8 @@ namespace ImGui
IMGUI_API void BringWindowToBack(ImGuiWindow* window); IMGUI_API void BringWindowToBack(ImGuiWindow* window);
IMGUI_API bool IsWindowChildOf(ImGuiWindow* window, ImGuiWindow* potential_parent); IMGUI_API bool IsWindowChildOf(ImGuiWindow* window, ImGuiWindow* potential_parent);
IMGUI_API void Initialize(); IMGUI_API void Initialize(ImGuiContext* context);
IMGUI_API void Shutdown(ImGuiContext* context); // Since 1.54 this is a _private_ function. You can call DestroyContext() to destroy the context created by CreateContext().
IMGUI_API void MarkIniSettingsDirty(); IMGUI_API void MarkIniSettingsDirty();
IMGUI_API ImGuiSettingsHandler* FindSettingsHandler(const char* type_name); IMGUI_API ImGuiSettingsHandler* FindSettingsHandler(const char* type_name);