mirror of
				https://github.com/kevinporetti/UnrealImGui.git
				synced 2025-11-03 23:33:16 +00:00 
			
		
		
		
	Changed interface to register ImGui debug delegates:
- Added new FImGuiDelegates interface for ImGui debug delegates. - Added FImGuiDelegatesContainer for ImGui delegates. - Added code preserving delegates during hot-reloading and moving them to a new module. - Depreciated old FImGuiModule delegates interface and FImGuiDelegateHandle. - Delegates registered with depreciated interface are redirected and get benefit of being preserved during hot-reloading. This can be controlled with IMGUI_REDIRECT_OBSOLETE_DELEGATES. - Added IMGUI_WITH_OBSOLETE_DELEGATES allowing to strip depreciated interface from builds. - Modified context manager and context proxy to work with FImGuiDelegatesContainer.
This commit is contained in:
		
							parent
							
								
									2b5d871609
								
							
						
					
					
						commit
						867a34e640
					
				@ -5,6 +5,13 @@ Versions marked as 'unofficial' are labelled only for the needs of this changelo
 | 
				
			|||||||
Change History
 | 
					Change History
 | 
				
			||||||
--------------
 | 
					--------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Version: 1.15 (2019/04)
 | 
				
			||||||
 | 
					- Added new FImGuiDelegates interface for ImGui debug delegates.
 | 
				
			||||||
 | 
					- Added code preserving delegates during hot-reloading and moving them to a new module.
 | 
				
			||||||
 | 
					- DEPRECIATED old FImGuiModule delegates interface and FImGuiDelegateHandle.
 | 
				
			||||||
 | 
					- Delegates registered with depreciated interface are redirected and get benefit of being preserved during hot-reloading. This can be controlled with IMGUI_REDIRECT_OBSOLETE_DELEGATES.
 | 
				
			||||||
 | 
					- Added IMGUI_WITH_OBSOLETE_DELEGATES allowing to strip depreciated interface from builds (that interface will be officially removed in one of later releases).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Version: 1.14 (2019/03)
 | 
					Version: 1.14 (2019/03)
 | 
				
			||||||
- Added SImGuiLayout to resets layout for SImGuiWidget.
 | 
					- Added SImGuiLayout to resets layout for SImGuiWidget.
 | 
				
			||||||
- Refactored rendering in SImGuiWidget to take advantage of layout reset.
 | 
					- Refactored rendering in SImGuiWidget to take advantage of layout reset.
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,7 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	"FileVersion": 3,
 | 
						"FileVersion": 3,
 | 
				
			||||||
	"Version": 1,
 | 
						"Version": 1,
 | 
				
			||||||
	"VersionName": "1.14",
 | 
						"VersionName": "1.15",
 | 
				
			||||||
	"FriendlyName": "ImGui",
 | 
						"FriendlyName": "ImGui",
 | 
				
			||||||
	"Description": "",
 | 
						"Description": "",
 | 
				
			||||||
	"Category": "Debug",
 | 
						"Category": "Debug",
 | 
				
			||||||
 | 
				
			|||||||
@ -4,6 +4,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "ImGuiContextManager.h"
 | 
					#include "ImGuiContextManager.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "ImGuiDelegatesContainer.h"
 | 
				
			||||||
#include "ImGuiImplementation.h"
 | 
					#include "ImGuiImplementation.h"
 | 
				
			||||||
#include "Utilities/ScopeGuards.h"
 | 
					#include "Utilities/ScopeGuards.h"
 | 
				
			||||||
#include "Utilities/WorldContext.h"
 | 
					#include "Utilities/WorldContext.h"
 | 
				
			||||||
@ -89,6 +90,11 @@ void FImGuiContextManager::Tick(float DeltaSeconds)
 | 
				
			|||||||
		{
 | 
							{
 | 
				
			||||||
			ContextData.ContextProxy.Tick(DeltaSeconds);
 | 
								ContextData.ContextProxy.Tick(DeltaSeconds);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								// Clear to make sure that we don't store objects registered for world that is no longer valid.
 | 
				
			||||||
 | 
								FImGuiDelegatesContainer::Get().OnWorldDebug(Pair.Key).Clear();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -72,7 +72,7 @@ private:
 | 
				
			|||||||
	{
 | 
						{
 | 
				
			||||||
		FContextData(const FString& ContextName, int32 ContextIndex, FSimpleMulticastDelegate& SharedDrawEvent, ImFontAtlas& FontAtlas, int32 InPIEInstance = -1)
 | 
							FContextData(const FString& ContextName, int32 ContextIndex, FSimpleMulticastDelegate& SharedDrawEvent, ImFontAtlas& FontAtlas, int32 InPIEInstance = -1)
 | 
				
			||||||
			: PIEInstance(InPIEInstance)
 | 
								: PIEInstance(InPIEInstance)
 | 
				
			||||||
			, ContextProxy(ContextName, &SharedDrawEvent, &FontAtlas)
 | 
								, ContextProxy(ContextName, ContextIndex, &SharedDrawEvent, &FontAtlas)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -87,7 +87,7 @@ private:
 | 
				
			|||||||
	struct FContextData
 | 
						struct FContextData
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		FContextData(const FString& ContextName, int32 ContextIndex, FSimpleMulticastDelegate& SharedDrawEvent, ImFontAtlas& FontAtlas)
 | 
							FContextData(const FString& ContextName, int32 ContextIndex, FSimpleMulticastDelegate& SharedDrawEvent, ImFontAtlas& FontAtlas)
 | 
				
			||||||
			: ContextProxy(ContextName, &SharedDrawEvent, &FontAtlas)
 | 
								: ContextProxy(ContextName, ContextIndex, &SharedDrawEvent, &FontAtlas)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -4,6 +4,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "ImGuiContextProxy.h"
 | 
					#include "ImGuiContextProxy.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "ImGuiDelegatesContainer.h"
 | 
				
			||||||
#include "ImGuiImplementation.h"
 | 
					#include "ImGuiImplementation.h"
 | 
				
			||||||
#include "ImGuiInteroperability.h"
 | 
					#include "ImGuiInteroperability.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -52,8 +53,9 @@ FImGuiContextProxy::FImGuiContextPtr::~FImGuiContextPtr()
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
FImGuiContextProxy::FImGuiContextProxy(const FString& InName, FSimpleMulticastDelegate* InSharedDrawEvent, ImFontAtlas* InFontAtlas)
 | 
					FImGuiContextProxy::FImGuiContextProxy(const FString& InName, int32 InContextIndex, FSimpleMulticastDelegate* InSharedDrawEvent, ImFontAtlas* InFontAtlas)
 | 
				
			||||||
	: Name(InName)
 | 
						: Name(InName)
 | 
				
			||||||
 | 
						, ContextIndex(InContextIndex)
 | 
				
			||||||
	, SharedDrawEvent(InSharedDrawEvent)
 | 
						, SharedDrawEvent(InSharedDrawEvent)
 | 
				
			||||||
	, IniFilename(TCHAR_TO_ANSI(*GetIniFile(InName)))
 | 
						, IniFilename(TCHAR_TO_ANSI(*GetIniFile(InName)))
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -91,22 +93,13 @@ void FImGuiContextProxy::Draw()
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		// Broadcast draw event to allow listeners to draw their controls to this context.
 | 
							// Broadcast draw event to allow listeners to draw their controls to this context.
 | 
				
			||||||
#if DRAW_EVENTS_ORDER_WORLD_BEFORE_MULTI_CONTEXT
 | 
					#if DRAW_EVENTS_ORDER_WORLD_BEFORE_MULTI_CONTEXT
 | 
				
			||||||
		if (DrawEvent.IsBound())
 | 
							BroadcastWorldTick();
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			DrawEvent.Broadcast();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
#endif // DRAW_EVENTS_ORDER_WORLD_BEFORE_MULTI_CONTEXT
 | 
					#endif // DRAW_EVENTS_ORDER_WORLD_BEFORE_MULTI_CONTEXT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (SharedDrawEvent && SharedDrawEvent->IsBound())
 | 
							BroadcastMultiContextTick();
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			SharedDrawEvent->Broadcast();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if !DRAW_EVENTS_ORDER_WORLD_BEFORE_MULTI_CONTEXT
 | 
					#if !DRAW_EVENTS_ORDER_WORLD_BEFORE_MULTI_CONTEXT
 | 
				
			||||||
		if (DrawEvent.IsBound())
 | 
							BroadcastWorldTick();
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			DrawEvent.Broadcast();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
#endif // !DRAW_EVENTS_ORDER_WORLD_BEFORE_MULTI_CONTEXT
 | 
					#endif // !DRAW_EVENTS_ORDER_WORLD_BEFORE_MULTI_CONTEXT
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -192,3 +185,34 @@ void FImGuiContextProxy::UpdateDrawData(ImDrawData* DrawData)
 | 
				
			|||||||
		DrawLists.Empty();
 | 
							DrawLists.Empty();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void FImGuiContextProxy::BroadcastWorldTick()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (DrawEvent.IsBound())
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							DrawEvent.Broadcast();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ContextIndex != Utilities::INVALID_CONTEXT_INDEX)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							FSimpleMulticastDelegate& WorldDebugEvent = FImGuiDelegatesContainer::Get().OnWorldDebug(ContextIndex);
 | 
				
			||||||
 | 
							if (WorldDebugEvent.IsBound())
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								WorldDebugEvent.Broadcast();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void FImGuiContextProxy::BroadcastMultiContextTick()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (SharedDrawEvent && SharedDrawEvent->IsBound())
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							SharedDrawEvent->Broadcast();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						FSimpleMulticastDelegate& MultiContextDebugEvent = FImGuiDelegatesContainer::Get().OnMultiContextDebug();
 | 
				
			||||||
 | 
						if (MultiContextDebugEvent.IsBound())
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							MultiContextDebugEvent.Broadcast();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -4,6 +4,8 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "ImGuiDrawData.h"
 | 
					#include "ImGuiDrawData.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "Utilities/WorldContextIndex.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <ICursor.h>
 | 
					#include <ICursor.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <imgui.h>
 | 
					#include <imgui.h>
 | 
				
			||||||
@ -41,7 +43,7 @@ class FImGuiContextProxy
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	FImGuiContextProxy(const FString& Name, FSimpleMulticastDelegate* InSharedDrawEvent, ImFontAtlas* InFontAtlas);
 | 
						FImGuiContextProxy(const FString& Name, int32 InContextIndex, FSimpleMulticastDelegate* InSharedDrawEvent, ImFontAtlas* InFontAtlas);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	FImGuiContextProxy(const FImGuiContextProxy&) = delete;
 | 
						FImGuiContextProxy(const FImGuiContextProxy&) = delete;
 | 
				
			||||||
	FImGuiContextProxy& operator=(const FImGuiContextProxy&) = delete;
 | 
						FImGuiContextProxy& operator=(const FImGuiContextProxy&) = delete;
 | 
				
			||||||
@ -96,6 +98,9 @@ private:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	void UpdateDrawData(ImDrawData* DrawData);
 | 
						void UpdateDrawData(ImDrawData* DrawData);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void BroadcastWorldTick();
 | 
				
			||||||
 | 
						void BroadcastMultiContextTick();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	FImGuiContextPtr Context;
 | 
						FImGuiContextPtr Context;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	FVector2D DisplaySize = FVector2D::ZeroVector;
 | 
						FVector2D DisplaySize = FVector2D::ZeroVector;
 | 
				
			||||||
@ -115,6 +120,8 @@ private:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	TArray<FImGuiDrawList> DrawLists;
 | 
						TArray<FImGuiDrawList> DrawLists;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int32 ContextIndex = Utilities::INVALID_CONTEXT_INDEX;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	FString Name;
 | 
						FString Name;
 | 
				
			||||||
	std::string IniFilename;
 | 
						std::string IniFilename;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										22
									
								
								Source/ImGui/Private/ImGuiDelegates.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								Source/ImGui/Private/ImGuiDelegates.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,22 @@
 | 
				
			|||||||
 | 
					// Distributed under the MIT License (MIT) (see accompanying LICENSE file)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "ImGuiPrivatePCH.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "ImGuiDelegates.h"
 | 
				
			||||||
 | 
					#include "ImGuiDelegatesContainer.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FSimpleMulticastDelegate& FImGuiDelegates::OnWorldDebug()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return OnWorldDebug(GWorld);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FSimpleMulticastDelegate& FImGuiDelegates::OnWorldDebug(UWorld* World)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return FImGuiDelegatesContainer::Get().OnWorldDebug(World);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FSimpleMulticastDelegate& FImGuiDelegates::OnMultiContextDebug()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return FImGuiDelegatesContainer::Get().OnMultiContextDebug();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										37
									
								
								Source/ImGui/Private/ImGuiDelegatesContainer.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								Source/ImGui/Private/ImGuiDelegatesContainer.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,37 @@
 | 
				
			|||||||
 | 
					// Distributed under the MIT License (MIT) (see accompanying LICENSE file)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "ImGuiPrivatePCH.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "ImGuiDelegatesContainer.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "Utilities/WorldContextIndex.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FImGuiDelegatesContainer FImGuiDelegatesContainer::DefaultInstance;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FImGuiDelegatesContainer* FImGuiDelegatesContainer::InstancePtr = &FImGuiDelegatesContainer::DefaultInstance;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void FImGuiDelegatesContainer::MoveContainer(FImGuiDelegatesContainer& Dst)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						// Only move data if pointer points to default instance, otherwise our data has already been moved and we only
 | 
				
			||||||
 | 
						// keep pointer to a more recent version.
 | 
				
			||||||
 | 
						if (InstancePtr == &DefaultInstance)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							Dst = MoveTemp(DefaultInstance);
 | 
				
			||||||
 | 
							DefaultInstance.Clear();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Update pointer to the most recent version.
 | 
				
			||||||
 | 
						InstancePtr = &Dst;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FSimpleMulticastDelegate& FImGuiDelegatesContainer::OnWorldDebug(UWorld* World)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return OnWorldDebug(Utilities::GetWorldContextIndex(*World));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void FImGuiDelegatesContainer::Clear()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						WorldDelegates.Empty();
 | 
				
			||||||
 | 
						MultiContextDelegate.Clear();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										40
									
								
								Source/ImGui/Private/ImGuiDelegatesContainer.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								Source/ImGui/Private/ImGuiDelegatesContainer.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,40 @@
 | 
				
			|||||||
 | 
					// Distributed under the MIT License (MIT) (see accompanying LICENSE file)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <Containers/Map.h>
 | 
				
			||||||
 | 
					#include <Delegates/Delegate.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct FImGuiDelegatesContainer
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Get the current instance (can change during hot-reloading).
 | 
				
			||||||
 | 
						static FImGuiDelegatesContainer& Get() { return *InstancePtr; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// If this is an active container move its data to a destination and redirect all future calls to that instance.
 | 
				
			||||||
 | 
						static void MoveContainer(FImGuiDelegatesContainer& Dst);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Get delegate to ImGui world debug event from known world instance.
 | 
				
			||||||
 | 
						FSimpleMulticastDelegate& OnWorldDebug(UWorld* World);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Get delegate to ImGui world debug event from known context index.
 | 
				
			||||||
 | 
						FSimpleMulticastDelegate& OnWorldDebug(int32 ContextIndex) { return WorldDelegates.FindOrAdd(ContextIndex); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Get delegate to ImGui multi-context debug event.
 | 
				
			||||||
 | 
						FSimpleMulticastDelegate& OnMultiContextDebug() { return MultiContextDelegate; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void Clear();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						TMap<int32, FSimpleMulticastDelegate> WorldDelegates;
 | 
				
			||||||
 | 
						FSimpleMulticastDelegate MultiContextDelegate;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Default container instance.
 | 
				
			||||||
 | 
						static FImGuiDelegatesContainer DefaultInstance;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Pointer to the container instance that can be overwritten during hot-reloading.
 | 
				
			||||||
 | 
						static FImGuiDelegatesContainer* InstancePtr;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
@ -4,6 +4,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "ImGuiModuleManager.h"
 | 
					#include "ImGuiModuleManager.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "ImGuiDelegatesContainer.h"
 | 
				
			||||||
#include "ImGuiTextureHandle.h"
 | 
					#include "ImGuiTextureHandle.h"
 | 
				
			||||||
#include "TextureManager.h"
 | 
					#include "TextureManager.h"
 | 
				
			||||||
#include "Utilities/WorldContext.h"
 | 
					#include "Utilities/WorldContext.h"
 | 
				
			||||||
@ -16,6 +17,8 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include <IPluginManager.h>
 | 
					#include <IPluginManager.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define IMGUI_REDIRECT_OBSOLETE_DELEGATES 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define LOCTEXT_NAMESPACE "FImGuiModule"
 | 
					#define LOCTEXT_NAMESPACE "FImGuiModule"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -38,18 +41,29 @@ static FImGuiModuleManager* ImGuiModuleManager = nullptr;
 | 
				
			|||||||
static FImGuiEditor* ImGuiEditor = nullptr;
 | 
					static FImGuiEditor* ImGuiEditor = nullptr;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if IMGUI_WITH_OBSOLETE_DELEGATES
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if WITH_EDITOR
 | 
					#if WITH_EDITOR
 | 
				
			||||||
FImGuiDelegateHandle FImGuiModule::AddEditorImGuiDelegate(const FImGuiDelegate& Delegate)
 | 
					FImGuiDelegateHandle FImGuiModule::AddEditorImGuiDelegate(const FImGuiDelegate& Delegate)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					#if IMGUI_REDIRECT_OBSOLETE_DELEGATES
 | 
				
			||||||
 | 
						return { FImGuiDelegatesContainer::Get().OnWorldDebug(Utilities::EDITOR_CONTEXT_INDEX).Add(Delegate),
 | 
				
			||||||
 | 
							EDelegateCategory::Default, Utilities::EDITOR_CONTEXT_INDEX };
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
	checkf(ImGuiModuleManager, TEXT("Null pointer to internal module implementation. Is module available?"));
 | 
						checkf(ImGuiModuleManager, TEXT("Null pointer to internal module implementation. Is module available?"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return { ImGuiModuleManager->GetContextManager().GetEditorContextProxy().OnDraw().Add(Delegate),
 | 
						return { ImGuiModuleManager->GetContextManager().GetEditorContextProxy().OnDraw().Add(Delegate),
 | 
				
			||||||
		EDelegateCategory::Default, Utilities::EDITOR_CONTEXT_INDEX };
 | 
							EDelegateCategory::Default, Utilities::EDITOR_CONTEXT_INDEX };
 | 
				
			||||||
 | 
					#endif // IMGUI_REDIRECT_OBSOLETE_DELEGATES
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
FImGuiDelegateHandle FImGuiModule::AddWorldImGuiDelegate(const FImGuiDelegate& Delegate)
 | 
					FImGuiDelegateHandle FImGuiModule::AddWorldImGuiDelegate(const FImGuiDelegate& Delegate)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					#if IMGUI_REDIRECT_OBSOLETE_DELEGATES
 | 
				
			||||||
 | 
						const int32 ContextIndex = Utilities::GetWorldContextIndex((UWorld*)GWorld);
 | 
				
			||||||
 | 
						return { FImGuiDelegatesContainer::Get().OnWorldDebug(ContextIndex).Add(Delegate), EDelegateCategory::Default, ContextIndex };
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
	checkf(ImGuiModuleManager, TEXT("Null pointer to internal module implementation. Is module available?"));
 | 
						checkf(ImGuiModuleManager, TEXT("Null pointer to internal module implementation. Is module available?"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if WITH_EDITOR
 | 
					#if WITH_EDITOR
 | 
				
			||||||
@ -71,17 +85,32 @@ FImGuiDelegateHandle FImGuiModule::AddWorldImGuiDelegate(const FImGuiDelegate& D
 | 
				
			|||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return{ Proxy.OnDraw().Add(Delegate), EDelegateCategory::Default, Index };
 | 
						return{ Proxy.OnDraw().Add(Delegate), EDelegateCategory::Default, Index };
 | 
				
			||||||
 | 
					#endif // IMGUI_REDIRECT_OBSOLETE_DELEGATES
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
FImGuiDelegateHandle FImGuiModule::AddMultiContextImGuiDelegate(const FImGuiDelegate& Delegate)
 | 
					FImGuiDelegateHandle FImGuiModule::AddMultiContextImGuiDelegate(const FImGuiDelegate& Delegate)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					#if IMGUI_REDIRECT_OBSOLETE_DELEGATES
 | 
				
			||||||
 | 
						return { FImGuiDelegatesContainer::Get().OnMultiContextDebug().Add(Delegate), EDelegateCategory::MultiContext };
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
	checkf(ImGuiModuleManager, TEXT("Null pointer to internal module implementation. Is module available?"));
 | 
						checkf(ImGuiModuleManager, TEXT("Null pointer to internal module implementation. Is module available?"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return { ImGuiModuleManager->GetContextManager().OnDrawMultiContext().Add(Delegate), EDelegateCategory::MultiContext };
 | 
						return { ImGuiModuleManager->GetContextManager().OnDrawMultiContext().Add(Delegate), EDelegateCategory::MultiContext };
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void FImGuiModule::RemoveImGuiDelegate(const FImGuiDelegateHandle& Handle)
 | 
					void FImGuiModule::RemoveImGuiDelegate(const FImGuiDelegateHandle& Handle)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					#if IMGUI_REDIRECT_OBSOLETE_DELEGATES
 | 
				
			||||||
 | 
						if (Handle.Category == EDelegateCategory::MultiContext)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							FImGuiDelegatesContainer::Get().OnMultiContextDebug().Remove(Handle.Handle);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							FImGuiDelegatesContainer::Get().OnWorldDebug(Handle.Index).Remove(Handle.Handle);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
	if (ImGuiModuleManager)
 | 
						if (ImGuiModuleManager)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		if (Handle.Category == EDelegateCategory::MultiContext)
 | 
							if (Handle.Category == EDelegateCategory::MultiContext)
 | 
				
			||||||
@ -93,8 +122,11 @@ void FImGuiModule::RemoveImGuiDelegate(const FImGuiDelegateHandle& Handle)
 | 
				
			|||||||
			Proxy->OnDraw().Remove(Handle.Handle);
 | 
								Proxy->OnDraw().Remove(Handle.Handle);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif // IMGUI_WITH_OBSOLETE_DELEGATES
 | 
				
			||||||
 | 
					
 | 
				
			||||||
FImGuiTextureHandle FImGuiModule::FindTextureHandle(const FName& Name)
 | 
					FImGuiTextureHandle FImGuiModule::FindTextureHandle(const FName& Name)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	const TextureIndex Index = ImGuiModuleManager->GetTextureManager().FindTextureIndex(Name);
 | 
						const TextureIndex Index = ImGuiModuleManager->GetTextureManager().FindTextureIndex(Name);
 | 
				
			||||||
@ -154,6 +186,10 @@ void FImGuiModule::ShutdownModule()
 | 
				
			|||||||
	// deleted. This can cause troubles after hot-reload when code in other modules calls ImGui interface functions
 | 
						// 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
 | 
						// which are statically bound to the obsolete module. To keep ImGui code functional we can redirect context handle
 | 
				
			||||||
	// to point to the new module.
 | 
						// to point to the new module.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// When shutting down during hot-reloading, we might want to rewire handles used in statically bound functions
 | 
				
			||||||
 | 
						// or move data to a new module.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	FModuleManager::Get().OnModulesChanged().AddLambda([this] (FName Name, EModuleChangeReason Reason)
 | 
						FModuleManager::Get().OnModulesChanged().AddLambda([this] (FName Name, EModuleChangeReason Reason)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		if (Reason == EModuleChangeReason::ModuleLoaded && Name == "ImGui")
 | 
							if (Reason == EModuleChangeReason::ModuleLoaded && Name == "ImGui")
 | 
				
			||||||
@ -161,8 +197,11 @@ 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  
 | 
				
			||||||
				ImGuiImplementation::SetImGuiContextHandle(LoadedModule.GetImGuiContextHandle());
 | 
									ImGuiImplementation::SetImGuiContextHandle(LoadedModule.GetImGuiContextHandle());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									FImGuiDelegatesContainer::MoveContainer(LoadedModule.GetDelegatesContainer());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				if (bMoveProperties)
 | 
									if (bMoveProperties)
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					bMoveProperties = false;
 | 
										bMoveProperties = false;
 | 
				
			||||||
@ -184,6 +223,11 @@ ImGuiContext** FImGuiModule::GetImGuiContextHandle()
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	return ImGuiImplementation::GetImGuiContextHandle();
 | 
						return ImGuiImplementation::GetImGuiContextHandle();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FImGuiDelegatesContainer& FImGuiModule::GetDelegatesContainer()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return FImGuiDelegatesContainer::Get();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
FImGuiModuleProperties& FImGuiModule::GetProperties()
 | 
					FImGuiModuleProperties& FImGuiModule::GetProperties()
 | 
				
			||||||
 | 
				
			|||||||
@ -56,6 +56,11 @@ namespace Utilities
 | 
				
			|||||||
		return (World.WorldType == EWorldType::Editor) ? EDITOR_CONTEXT_INDEX : GetWorldContextIndex(World.GetGameInstance());
 | 
							return (World.WorldType == EWorldType::Editor) ? EDITOR_CONTEXT_INDEX : GetWorldContextIndex(World.GetGameInstance());
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						FORCEINLINE int32 GetWorldContextIndex(const UWorld* World)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							return World ? GetWorldContextIndex(*World) : INVALID_CONTEXT_INDEX;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	template<typename T>
 | 
						template<typename T>
 | 
				
			||||||
 | 
				
			|||||||
@ -5,6 +5,43 @@
 | 
				
			|||||||
#include <Core.h>
 | 
					#include <Core.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Delegates to ImGui debug events called. World delegates are called once per frame to draw debug for owning world
 | 
				
			||||||
 | 
					 * and are automatically cleared when that world becomes invalid. Multi-context delegates are called once for every
 | 
				
			||||||
 | 
					 * world that needs to be debugged.
 | 
				
			||||||
 | 
					 * In engine version 4.18 or later delegates are called during OnWorldPostActorTick event while in older versions
 | 
				
			||||||
 | 
					 * 4.18 during OnWorldTickStart event. Calling behaviours can be changed in build configuration.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					class IMGUI_API FImGuiDelegates
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Get a delegate to ImGui world debug event for current world (GWorld).
 | 
				
			||||||
 | 
						 * @returns Simple multicast delegate to debug events called once per frame to debug current world
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						static FSimpleMulticastDelegate& OnWorldDebug();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Get a delegate to ImGui world debug event for given world.
 | 
				
			||||||
 | 
						 * @param World - World for which we need a delegate
 | 
				
			||||||
 | 
						 * @returns Simple multicast delegate to debug events called once per frame to debug given world
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						static FSimpleMulticastDelegate& OnWorldDebug(UWorld* World);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Get a delegate to ImGui multi-context debug event.
 | 
				
			||||||
 | 
						 * @returns Simple multicast delegate to debug events called once per frame for every world to debug
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						static FSimpleMulticastDelegate& OnMultiContextDebug();
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** Enable to support legacy ImGui delegates API. */
 | 
				
			||||||
 | 
					#define IMGUI_WITH_OBSOLETE_DELEGATES 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if IMGUI_WITH_OBSOLETE_DELEGATES
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Delegate that allows to subscribe for ImGui events.  */
 | 
					/** Delegate that allows to subscribe for ImGui events.  */
 | 
				
			||||||
typedef FSimpleMulticastDelegate::FDelegate FImGuiDelegate;
 | 
					typedef FSimpleMulticastDelegate::FDelegate FImGuiDelegate;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -53,3 +90,5 @@ private:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	friend class FImGuiModule;
 | 
						friend class FImGuiModule;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif // IMGUI_WITH_OBSOLETE_DELEGATES
 | 
				
			||||||
 | 
				
			|||||||
@ -34,6 +34,8 @@ public:
 | 
				
			|||||||
		return FModuleManager::Get().IsModuleLoaded("ImGui");
 | 
							return FModuleManager::Get().IsModuleLoaded("ImGui");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if IMGUI_WITH_OBSOLETE_DELEGATES
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if WITH_EDITOR
 | 
					#if WITH_EDITOR
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * Add a delegate called at the end of editor debug frame to draw debug controls in its ImGui context, creating
 | 
						 * Add a delegate called at the end of editor debug frame to draw debug controls in its ImGui context, creating
 | 
				
			||||||
@ -71,6 +73,8 @@ public:
 | 
				
			|||||||
	 */
 | 
						 */
 | 
				
			||||||
	virtual void RemoveImGuiDelegate(const FImGuiDelegateHandle& Handle);
 | 
						virtual void RemoveImGuiDelegate(const FImGuiDelegateHandle& Handle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif // #if IMGUI_WITH_OBSOLETE_DELEGATES
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * If it exists, get a handle to the texture with given resource name.
 | 
						 * If it exists, get a handle to the texture with given resource name.
 | 
				
			||||||
	 *
 | 
						 *
 | 
				
			||||||
@ -165,5 +169,6 @@ public:
 | 
				
			|||||||
#if WITH_EDITOR
 | 
					#if WITH_EDITOR
 | 
				
			||||||
	virtual void SetProperties(const FImGuiModuleProperties& Properties);
 | 
						virtual void SetProperties(const FImGuiModuleProperties& Properties);
 | 
				
			||||||
	virtual struct ImGuiContext** GetImGuiContextHandle();
 | 
						virtual struct ImGuiContext** GetImGuiContextHandle();
 | 
				
			||||||
 | 
						virtual struct FImGuiDelegatesContainer& GetDelegatesContainer();
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user