diff --git a/Source/ImGui/Private/ImGuiImplementation.cpp b/Source/ImGui/Private/ImGuiImplementation.cpp index 062d467..71bcad2 100644 --- a/Source/ImGui/Private/ImGuiImplementation.cpp +++ b/Source/ImGui/Private/ImGuiImplementation.cpp @@ -15,6 +15,15 @@ #define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS #endif // PLATFORM_XBOXONE +#if WITH_EDITOR +// Global ImGui context pointer. +ImGuiContext* GImGuiContextPtr = nullptr; +// Handle to the global ImGui context pointer. +ImGuiContext** GImGuiContextPtrHandle = &GImGuiContextPtr; +// Get the global ImGui context pointer (GImGui) indirectly to allow redirections in obsolete modules. +#define GImGui (*GImGuiContextPtrHandle) +#endif // WITH_EDITOR + #if PLATFORM_WINDOWS #include #endif // PLATFORM_WINDOWS @@ -51,4 +60,16 @@ namespace ImGuiImplementation return false; } } + +#if WITH_EDITOR + ImGuiContext** GetImGuiContextHandle() + { + return GImGuiContextPtrHandle; + } + + void SetImGuiContextHandle(ImGuiContext** Handle) + { + GImGuiContextPtrHandle = Handle; + } +#endif // WITH_EDITOR } \ No newline at end of file diff --git a/Source/ImGui/Private/ImGuiImplementation.h b/Source/ImGui/Private/ImGuiImplementation.h index 925659b..f2228ae 100644 --- a/Source/ImGui/Private/ImGuiImplementation.h +++ b/Source/ImGui/Private/ImGuiImplementation.h @@ -10,4 +10,12 @@ namespace ImGuiImplementation { // Get specific cursor data. bool GetCursorData(ImGuiMouseCursor CursorType, FVector2D& OutSize, FVector2D& OutUVMin, FVector2D& OutUVMax, FVector2D& OutOutlineUVMin, FVector2D& OutOutlineUVMax); + +#if WITH_EDITOR + // Get the handle to the ImGui Context pointer. + ImGuiContext** GetImGuiContextHandle(); + + // Set the ImGui Context pointer handle. + void SetImGuiContextHandle(ImGuiContext** Handle); +#endif // WITH_EDITOR } diff --git a/Source/ImGui/Private/ImGuiModule.cpp b/Source/ImGui/Private/ImGuiModule.cpp index 83f20fb..e33dc3b 100644 --- a/Source/ImGui/Private/ImGuiModule.cpp +++ b/Source/ImGui/Private/ImGuiModule.cpp @@ -7,6 +7,7 @@ #include "Utilities/WorldContextIndex.h" #if WITH_EDITOR +#include "ImGuiImplementation.h" #include "Editor/ImGuiEditor.h" #endif @@ -138,8 +139,33 @@ void FImGuiModule::ShutdownModule() checkf(ImGuiModuleManager, TEXT("Null ImGui Module Manager. Module manager instance should be deleted during module shutdown.")); delete ImGuiModuleManager; ImGuiModuleManager = nullptr; + +#if WITH_EDITOR + // When shutting down we leave the global ImGui context pointer and handle pointing to resources that are already + // deleted. This can cause troubles after hot-reload when code in other modules calls ImGui interface functions + // which are statically bound to the obsolete module. To keep ImGui code functional we can redirect context handle + // to point to the new module. + FModuleManager::Get().OnModulesChanged().AddLambda([this](FName Name, EModuleChangeReason Reason) + { + if (Reason == EModuleChangeReason::ModuleLoaded && Name == "ImGui") + { + FImGuiModule& LoadedModule = FImGuiModule::Get(); + if (&LoadedModule != this) + { + ImGuiImplementation::SetImGuiContextHandle(LoadedModule.GetImGuiContextHandle()); + } + } + }); +#endif // WITH_EDITOR } +#if WITH_EDITOR +ImGuiContext** FImGuiModule::GetImGuiContextHandle() +{ + return ImGuiImplementation::GetImGuiContextHandle(); +} +#endif + bool FImGuiModule::IsInputMode() const { return CVars::InputEnabled.GetValueOnAnyThread() > 0; diff --git a/Source/ImGui/Public/ImGuiModule.h b/Source/ImGui/Public/ImGuiModule.h index eb23285..0fd4a4d 100644 --- a/Source/ImGui/Public/ImGuiModule.h +++ b/Source/ImGui/Public/ImGuiModule.h @@ -110,4 +110,10 @@ public: /** IModuleInterface implementation */ virtual void StartupModule() override; virtual void ShutdownModule() override; + + private: + +#if WITH_EDITOR + virtual struct ImGuiContext** GetImGuiContextHandle(); +#endif };