Fixed potential for initialization fiasco when using delegates container. Fixed bug in code protecting redirecting handles from self-referencing. Updated project version and status.

This commit is contained in:
Sebastian 2021-04-14 23:11:49 -04:00
parent 39c3eced41
commit 9f41d0906e
8 changed files with 56 additions and 30 deletions

View File

@ -5,6 +5,10 @@ Versions marked as 'unofficial' are labelled only for the needs of this changelo
Change History 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) Version: 1.21 (2020/07-09)
Improving stability Improving stability
- Fixed a crash in the input handler caused by invalidated by hot-reload instance trying to unregister a delegate. - Fixed a crash in the input handler caused by invalidated by hot-reload instance trying to unregister a delegate.

View File

@ -1,7 +1,7 @@
{ {
"FileVersion": 3, "FileVersion": 3,
"Version": 1, "Version": 1,
"VersionName": "1.21", "VersionName": "1.22",
"FriendlyName": "ImGui", "FriendlyName": "ImGui",
"Description": "", "Description": "",
"Category": "Debug", "Category": "Debug",

View File

@ -9,14 +9,24 @@ Dear ImGui is an immediate-mode graphical user interface library that is very li
Status Status
------ ------
Version: 1.21 Version: 1.22
ImGui version: 1.74 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.* \* *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 About
----- -----

View File

@ -11,11 +11,10 @@
// Non-editor version without container redirection // Non-editor version without container redirection
// //
static FImGuiDelegatesContainer DelegatesContainer;
FImGuiDelegatesContainer& FImGuiDelegatesContainer::Get() FImGuiDelegatesContainer& FImGuiDelegatesContainer::Get()
{ {
return DelegatesContainer; static FImGuiDelegatesContainer* Container = new FImGuiDelegatesContainer();
return *Container;
} }
#endif // !WITH_EDITOR #endif // !WITH_EDITOR
@ -36,14 +35,11 @@ struct FImGuiDelegatesContainerHandle : Utilities::TRedirectingHandle<FImGuiDele
{ {
if (FImGuiModule* Module = FModuleManager::GetModulePtr<FImGuiModule>("ImGui")) if (FImGuiModule* Module = FModuleManager::GetModulePtr<FImGuiModule>("ImGui"))
{ {
SetParent(&Module->GetDelegatesContainerHandle()); SetParent(Module->DelegatesContainerHandle);
} }
} }
}; };
static FImGuiDelegatesContainer DelegatesContainer;
static FImGuiDelegatesContainerHandle DelegatesHandle(DelegatesContainer);
FImGuiDelegatesContainer& FImGuiDelegatesContainer::Get() FImGuiDelegatesContainer& FImGuiDelegatesContainer::Get()
{ {
return GetHandle().Get(); return GetHandle().Get();
@ -51,7 +47,14 @@ FImGuiDelegatesContainer& FImGuiDelegatesContainer::Get()
FImGuiDelegatesContainerHandle& FImGuiDelegatesContainer::GetHandle() 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) void FImGuiDelegatesContainer::MoveContainer(FImGuiDelegatesContainerHandle& OtherContainerHandle)

View File

@ -30,7 +30,7 @@ struct FImGuiContextHandle : public Utilities::TRedirectingHandle<ImGuiContext*>
{ {
if (FImGuiModule* Module = FModuleManager::GetModulePtr<FImGuiModule>("ImGui")) if (FImGuiModule* Module = FModuleManager::GetModulePtr<FImGuiModule>("ImGui"))
{ {
SetParent(&Module->GetImGuiContextHandle()); SetParent(Module->ImGuiContextHandle);
} }
} }
}; };

View File

@ -100,6 +100,18 @@ void FImGuiModule::ReleaseTexture(const FImGuiTextureHandle& Handle)
void FImGuiModule::StartupModule() 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. // 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.")); 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(); FImGuiModule& LoadedModule = FImGuiModule::Get();
if (&LoadedModule != this) if (&LoadedModule != this)
{ {
// Statically bound functions will be still made to the obsolete module so we need to // Statically bound functions can be bound to the obsolete module, so we need to manually redirect.
ImGuiImplementation::SetParentContextHandle(LoadedModule.GetImGuiContextHandle());
FImGuiDelegatesContainer::MoveContainer(LoadedModule.GetDelegatesContainerHandle()); if (LoadedModule.ImGuiContextHandle)
{
ImGuiImplementation::SetParentContextHandle(*LoadedModule.ImGuiContextHandle);
}
if (LoadedModule.DelegatesContainerHandle)
{
FImGuiDelegatesContainer::MoveContainer(*LoadedModule.DelegatesContainerHandle);
}
if (bMoveProperties) if (bMoveProperties)
{ {
@ -169,16 +188,6 @@ void FImGuiModule::SetProperties(const FImGuiModuleProperties& Properties)
{ {
ImGuiModuleManager->GetProperties() = Properties; ImGuiModuleManager->GetProperties() = Properties;
} }
FImGuiContextHandle& FImGuiModule::GetImGuiContextHandle()
{
return ImGuiImplementation::GetContextHandle();
}
FImGuiDelegatesContainerHandle& FImGuiModule::GetDelegatesContainerHandle()
{
return FImGuiDelegatesContainer::GetHandle();
}
#endif #endif
FImGuiModuleProperties& FImGuiModule::GetProperties() FImGuiModuleProperties& FImGuiModule::GetProperties()

View File

@ -8,8 +8,8 @@
namespace Utilities namespace Utilities
{ {
// Handle initialized as a pointer to a default value, but once attached it will follow the parent handle. // Handle initialized as a pointer to a default value, but can be redirected to follow other handles.
// When detached it will revert back to the default value. Intended for cross-module redirections. // When detached, it will revert to the default value. Intended for cross-module redirections.
template<typename T> template<typename T>
struct TRedirectingHandle struct TRedirectingHandle
{ {
@ -49,7 +49,7 @@ namespace Utilities
} }
// Protecting from setting itself as a parent. // Protecting from setting itself as a parent.
Parent = (Parent != this) ? InParent : nullptr; Parent = (InParent != this) ? InParent : nullptr;
if (Parent) if (Parent)
{ {

View File

@ -168,8 +168,8 @@ private:
#if WITH_EDITOR #if WITH_EDITOR
virtual void SetProperties(const FImGuiModuleProperties& Properties); virtual void SetProperties(const FImGuiModuleProperties& Properties);
virtual struct FImGuiContextHandle& GetImGuiContextHandle(); struct FImGuiContextHandle* ImGuiContextHandle = nullptr;
virtual struct FImGuiDelegatesContainerHandle& GetDelegatesContainerHandle(); struct FImGuiDelegatesContainerHandle* DelegatesContainerHandle = nullptr;
friend struct FImGuiContextHandle; friend struct FImGuiContextHandle;
friend struct FImGuiDelegatesContainerHandle; friend struct FImGuiDelegatesContainerHandle;
#endif #endif