diff --git a/CHANGES.md b/CHANGES.md index 3b70610..5f2d6ec 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -5,6 +5,10 @@ Versions marked as 'unofficial' are labelled only for the needs of this changelo Change History -------------- +Version: 1.22 (2021/04) +- Fixed potential for initialization fiasco when using delegates container. +- Fixed bug in code protecting redirecting handles from self-referencing. + Version: 1.21 (2020/07-09) Improving stability - Fixed a crash in the input handler caused by invalidated by hot-reload instance trying to unregister a delegate. diff --git a/ImGui.uplugin b/ImGui.uplugin index 8237120..f5776ac 100644 --- a/ImGui.uplugin +++ b/ImGui.uplugin @@ -1,7 +1,7 @@ { "FileVersion": 3, "Version": 1, - "VersionName": "1.21", + "VersionName": "1.22", "FriendlyName": "ImGui", "Description": "", "Category": "Debug", diff --git a/README.md b/README.md index e83ff91..7e2f7b0 100644 --- a/README.md +++ b/README.md @@ -9,14 +9,24 @@ Dear ImGui is an immediate-mode graphical user interface library that is very li Status ------ -Version: 1.21 +Version: 1.22 ImGui version: 1.74 -Supported engine version: 4.25* +Supported engine version: 4.26* \* *Plugin has been tested and if necessary updated to compile and work with this engine version. As long as possible I will try to maintain backward compatibility of existing features and possibly but not necessarily when adding new features. When it comes to bare-bone ImGui version it should be at least backward compatible with the engine version 4.15. For NetImgui it needs to be determined.* +Current work +------------ + +Currently, I'm a little busy outside of this project so changes come slowly. But here is what to expect in the reasonably near future: +- Stability first, so fixes for more critical issues like an invalidation of handles after reloading texture resources will be pushed first. The same goes for merges. +- There are a few smaller issues that I'm aware of and that might be not reported but which I want to fix. +- ImGui needs to be updated. +- Smaller features might be slowly pushed but bigger ones will need to wait. The same goes for merges. +- There is a branch with NetImgui which is really good, and which will be eventually merged to master, but first I want to fix a few issues that I know about (some are discussed in thread #28). In the meantime, the NetImgui branch is pretty much ready to use. + About ----- diff --git a/Source/ImGui/Private/ImGuiDelegatesContainer.cpp b/Source/ImGui/Private/ImGuiDelegatesContainer.cpp index b750b0a..8fc7965 100644 --- a/Source/ImGui/Private/ImGuiDelegatesContainer.cpp +++ b/Source/ImGui/Private/ImGuiDelegatesContainer.cpp @@ -11,11 +11,10 @@ // Non-editor version without container redirection // -static FImGuiDelegatesContainer DelegatesContainer; - FImGuiDelegatesContainer& FImGuiDelegatesContainer::Get() { - return DelegatesContainer; + static FImGuiDelegatesContainer* Container = new FImGuiDelegatesContainer(); + return *Container; } #endif // !WITH_EDITOR @@ -36,14 +35,11 @@ struct FImGuiDelegatesContainerHandle : Utilities::TRedirectingHandle("ImGui")) { - SetParent(&Module->GetDelegatesContainerHandle()); + SetParent(Module->DelegatesContainerHandle); } } }; -static FImGuiDelegatesContainer DelegatesContainer; -static FImGuiDelegatesContainerHandle DelegatesHandle(DelegatesContainer); - FImGuiDelegatesContainer& FImGuiDelegatesContainer::Get() { return GetHandle().Get(); @@ -51,7 +47,14 @@ FImGuiDelegatesContainer& FImGuiDelegatesContainer::Get() FImGuiDelegatesContainerHandle& FImGuiDelegatesContainer::GetHandle() { - return DelegatesHandle; + struct FContainerInstance + { + FContainerInstance() : Container(), Handle(Container) {} + FImGuiDelegatesContainer Container; + FImGuiDelegatesContainerHandle Handle; + }; + static FContainerInstance* Instance = new FContainerInstance(); + return Instance->Handle; } void FImGuiDelegatesContainer::MoveContainer(FImGuiDelegatesContainerHandle& OtherContainerHandle) diff --git a/Source/ImGui/Private/ImGuiImplementation.cpp b/Source/ImGui/Private/ImGuiImplementation.cpp index f66deca..98d034e 100644 --- a/Source/ImGui/Private/ImGuiImplementation.cpp +++ b/Source/ImGui/Private/ImGuiImplementation.cpp @@ -30,7 +30,7 @@ struct FImGuiContextHandle : public Utilities::TRedirectingHandle { if (FImGuiModule* Module = FModuleManager::GetModulePtr("ImGui")) { - SetParent(&Module->GetImGuiContextHandle()); + SetParent(Module->ImGuiContextHandle); } } }; diff --git a/Source/ImGui/Private/ImGuiModule.cpp b/Source/ImGui/Private/ImGuiModule.cpp index 2b58d9a..ea12089 100644 --- a/Source/ImGui/Private/ImGuiModule.cpp +++ b/Source/ImGui/Private/ImGuiModule.cpp @@ -100,6 +100,18 @@ void FImGuiModule::ReleaseTexture(const FImGuiTextureHandle& Handle) void FImGuiModule::StartupModule() { + // Initialize handles to allow cross-module redirections. Other handles will always look for parents in the active + // module, which means that we can only redirect to started modules. We don't have to worry about self-referencing + // as local handles are guaranteed to be constructed before initializing pointers. + // This supports in-editor recompilation and hot-reloading after compiling from the command line. The latter method + // theoretically doesn't support plug-ins and will not load re-compiled module, but its handles will still redirect + // to the active one. + +#if WITH_EDITOR + ImGuiContextHandle = &ImGuiImplementation::GetContextHandle(); + DelegatesContainerHandle = &FImGuiDelegatesContainer::GetHandle(); +#endif + // Create managers that implements module logic. checkf(!ImGuiModuleManager, TEXT("Instance of the ImGui Module Manager already exists. Instance should be created only during module startup.")); @@ -148,10 +160,17 @@ void FImGuiModule::ShutdownModule() FImGuiModule& LoadedModule = FImGuiModule::Get(); if (&LoadedModule != this) { - // Statically bound functions will be still made to the obsolete module so we need to - ImGuiImplementation::SetParentContextHandle(LoadedModule.GetImGuiContextHandle()); + // Statically bound functions can be bound to the obsolete module, so we need to manually redirect. - FImGuiDelegatesContainer::MoveContainer(LoadedModule.GetDelegatesContainerHandle()); + if (LoadedModule.ImGuiContextHandle) + { + ImGuiImplementation::SetParentContextHandle(*LoadedModule.ImGuiContextHandle); + } + + if (LoadedModule.DelegatesContainerHandle) + { + FImGuiDelegatesContainer::MoveContainer(*LoadedModule.DelegatesContainerHandle); + } if (bMoveProperties) { @@ -169,16 +188,6 @@ void FImGuiModule::SetProperties(const FImGuiModuleProperties& Properties) { ImGuiModuleManager->GetProperties() = Properties; } - -FImGuiContextHandle& FImGuiModule::GetImGuiContextHandle() -{ - return ImGuiImplementation::GetContextHandle(); -} - -FImGuiDelegatesContainerHandle& FImGuiModule::GetDelegatesContainerHandle() -{ - return FImGuiDelegatesContainer::GetHandle(); -} #endif FImGuiModuleProperties& FImGuiModule::GetProperties() diff --git a/Source/ImGui/Private/Utilities/RedirectingHandle.h b/Source/ImGui/Private/Utilities/RedirectingHandle.h index abec0d1..d0c3dd6 100644 --- a/Source/ImGui/Private/Utilities/RedirectingHandle.h +++ b/Source/ImGui/Private/Utilities/RedirectingHandle.h @@ -8,8 +8,8 @@ namespace Utilities { - // Handle initialized as a pointer to a default value, but once attached it will follow the parent handle. - // When detached it will revert back to the default value. Intended for cross-module redirections. + // Handle initialized as a pointer to a default value, but can be redirected to follow other handles. + // When detached, it will revert to the default value. Intended for cross-module redirections. template struct TRedirectingHandle { @@ -49,7 +49,7 @@ namespace Utilities } // Protecting from setting itself as a parent. - Parent = (Parent != this) ? InParent : nullptr; + Parent = (InParent != this) ? InParent : nullptr; if (Parent) { diff --git a/Source/ImGui/Public/ImGuiModule.h b/Source/ImGui/Public/ImGuiModule.h index f63a480..ec2ac4a 100644 --- a/Source/ImGui/Public/ImGuiModule.h +++ b/Source/ImGui/Public/ImGuiModule.h @@ -168,8 +168,8 @@ private: #if WITH_EDITOR virtual void SetProperties(const FImGuiModuleProperties& Properties); - virtual struct FImGuiContextHandle& GetImGuiContextHandle(); - virtual struct FImGuiDelegatesContainerHandle& GetDelegatesContainerHandle(); + struct FImGuiContextHandle* ImGuiContextHandle = nullptr; + struct FImGuiDelegatesContainerHandle* DelegatesContainerHandle = nullptr; friend struct FImGuiContextHandle; friend struct FImGuiDelegatesContainerHandle; #endif