mirror of
				https://github.com/kevinporetti/UnrealImGui.git
				synced 2025-11-03 23:33:16 +00:00 
			
		
		
		
	Added interface to register ImGui debug delegates.
This commit is contained in:
		
							parent
							
								
									1a6aa98f51
								
							
						
					
					
						commit
						00ad746267
					
				@ -72,7 +72,7 @@ void FImGuiContextManager::Tick(float DeltaSeconds)
 | 
				
			|||||||
		if (ContextData.CanTick())
 | 
							if (ContextData.CanTick())
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			ContextData.ContextProxy.SetAsCurrent();
 | 
								ContextData.ContextProxy.SetAsCurrent();
 | 
				
			||||||
			ContextData.ContextProxy.Tick(DeltaSeconds);
 | 
								ContextData.ContextProxy.Tick(DeltaSeconds, &DrawMultiContextEvent);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -105,7 +105,7 @@ FImGuiContextManager::FContextData& FImGuiContextManager::GetStandaloneWorldCont
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
#endif // !WITH_EDITOR
 | 
					#endif // !WITH_EDITOR
 | 
				
			||||||
 | 
					
 | 
				
			||||||
FImGuiContextManager::FContextData& FImGuiContextManager::GetWorldContextData(const UWorld& World)
 | 
					FImGuiContextManager::FContextData& FImGuiContextManager::GetWorldContextData(const UWorld& World, int32* OutIndex)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	using namespace Utilities;
 | 
						using namespace Utilities;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -140,5 +140,9 @@ FImGuiContextManager::FContextData& FImGuiContextManager::GetWorldContextData(co
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (OutIndex)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							*OutIndex = Index;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	return *Data;
 | 
						return *Data;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -34,6 +34,9 @@ public:
 | 
				
			|||||||
	// Get or create ImGui context proxy for given world.
 | 
						// Get or create ImGui context proxy for given world.
 | 
				
			||||||
	FORCEINLINE FImGuiContextProxy& GetWorldContextProxy(const UWorld& World) { return GetWorldContextData(World).ContextProxy; }
 | 
						FORCEINLINE FImGuiContextProxy& GetWorldContextProxy(const UWorld& World) { return GetWorldContextData(World).ContextProxy; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Get or create ImGui context proxy for given world. Additionally get context index for that proxy.
 | 
				
			||||||
 | 
						FORCEINLINE FImGuiContextProxy& GetWorldContextProxy(const UWorld& World, int32& OutContextIndex) { return GetWorldContextData(World, &OutContextIndex).ContextProxy; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Get context proxy by index, or null if context with that index doesn't exist.
 | 
						// Get context proxy by index, or null if context with that index doesn't exist.
 | 
				
			||||||
	FORCEINLINE FImGuiContextProxy* GetContextProxy(int32 ContextIndex)
 | 
						FORCEINLINE FImGuiContextProxy* GetContextProxy(int32 ContextIndex)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
@ -41,6 +44,10 @@ public:
 | 
				
			|||||||
		return Data ? &(Data->ContextProxy) : nullptr;
 | 
							return Data ? &(Data->ContextProxy) : nullptr;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Delegate called for all contexts in manager, right after calling context specific draw event. Allows listeners
 | 
				
			||||||
 | 
						// draw the same content to multiple contexts.
 | 
				
			||||||
 | 
						FSimpleMulticastDelegate& OnDrawMultiContext() { return DrawMultiContextEvent; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void Tick(float DeltaSeconds);
 | 
						void Tick(float DeltaSeconds);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
@ -87,9 +94,11 @@ private:
 | 
				
			|||||||
	FContextData& GetStandaloneWorldContextData();
 | 
						FContextData& GetStandaloneWorldContextData();
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	FContextData& GetWorldContextData(const UWorld& World);
 | 
						FContextData& GetWorldContextData(const UWorld& World, int32* OutContextIndex = nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	TMap<int32, FContextData> Contexts;
 | 
						TMap<int32, FContextData> Contexts;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	FImGuiDemo ImGuiDemo;
 | 
						FImGuiDemo ImGuiDemo;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						FSimpleMulticastDelegate DrawMultiContextEvent;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
@ -117,7 +117,7 @@ FImGuiContextProxy::~FImGuiContextProxy()
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void FImGuiContextProxy::Tick(float DeltaSeconds)
 | 
					void FImGuiContextProxy::Tick(float DeltaSeconds, FSimpleMulticastDelegate* SharedDrawEvent)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (bIsFrameStarted)
 | 
						if (bIsFrameStarted)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
@ -126,6 +126,10 @@ void FImGuiContextProxy::Tick(float DeltaSeconds)
 | 
				
			|||||||
		{
 | 
							{
 | 
				
			||||||
			DrawEvent.Broadcast();
 | 
								DrawEvent.Broadcast();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							if (SharedDrawEvent && SharedDrawEvent->IsBound())
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								SharedDrawEvent->Broadcast();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Ending frame will produce render output that we capture and store for later use. This also puts context to
 | 
							// Ending frame will produce render output that we capture and store for later use. This also puts context to
 | 
				
			||||||
		// state in which it does not allow to draw controls, so we want to immediately start a new frame.
 | 
							// state in which it does not allow to draw controls, so we want to immediately start a new frame.
 | 
				
			||||||
 | 
				
			|||||||
@ -53,7 +53,8 @@ public:
 | 
				
			|||||||
	FSimpleMulticastDelegate& OnDraw() { return DrawEvent; }
 | 
						FSimpleMulticastDelegate& OnDraw() { return DrawEvent; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Tick to advance context to the next frame.
 | 
						// Tick to advance context to the next frame.
 | 
				
			||||||
	void Tick(float DeltaSeconds);
 | 
						// @param SharedDrawEvent - Shared draw event provided from outside to be called right after context own event 
 | 
				
			||||||
 | 
						void Tick(float DeltaSeconds, FSimpleMulticastDelegate* SharedDrawEvent = nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -3,6 +3,8 @@
 | 
				
			|||||||
#include "ImGuiPrivatePCH.h"
 | 
					#include "ImGuiPrivatePCH.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "ImGuiModuleManager.h"
 | 
					#include "ImGuiModuleManager.h"
 | 
				
			||||||
 | 
					#include "Utilities/WorldContext.h"
 | 
				
			||||||
 | 
					#include "Utilities/WorldContextIndex.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <IPluginManager.h>
 | 
					#include <IPluginManager.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -10,8 +12,77 @@
 | 
				
			|||||||
#define LOCTEXT_NAMESPACE "FImGuiModule"
 | 
					#define LOCTEXT_NAMESPACE "FImGuiModule"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct EDelegateCategory
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						enum
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							// Default per-context draw events.
 | 
				
			||||||
 | 
							Default,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Multi-context draw event defined in context manager.
 | 
				
			||||||
 | 
							MultiContext
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static FImGuiModuleManager* ModuleManager = nullptr;
 | 
					static FImGuiModuleManager* ModuleManager = nullptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if WITH_EDITOR
 | 
				
			||||||
 | 
					FImGuiDelegateHandle FImGuiModule::AddEditorImGuiDelegate(const FImGuiDelegate& Delegate)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						checkf(ModuleManager, TEXT("Null pointer to internal module implementation. Is module available?"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return { ModuleManager->GetContextManager().GetEditorContextProxy().OnDraw().Add(Delegate),
 | 
				
			||||||
 | 
							EDelegateCategory::Default, Utilities::EDITOR_CONTEXT_INDEX };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FImGuiDelegateHandle FImGuiModule::AddWorldImGuiDelegate(const FImGuiDelegate& Delegate)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						checkf(ModuleManager, TEXT("Null pointer to internal module implementation. Is module available?"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if WITH_EDITOR
 | 
				
			||||||
 | 
						checkf(GEngine, TEXT("Null GEngine. AddWorldImGuiDelegate should be only called with GEngine initialized."));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const FWorldContext* WorldContext = Utilities::GetWorldContext(GEngine->GameViewport);
 | 
				
			||||||
 | 
						if (!WorldContext)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							WorldContext = Utilities::GetWorldContextFromNetMode(ENetMode::NM_DedicatedServer);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						checkf(WorldContext, TEXT("Couldn't find current world. AddWorldImGuiDelegate should be only called from a valid world."));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int32 Index;
 | 
				
			||||||
 | 
						FImGuiContextProxy& Proxy = ModuleManager->GetContextManager().GetWorldContextProxy(*WorldContext->World(), Index);
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
						const int32 Index = Utilities::STANDALONE_GAME_CONTEXT_INDEX;
 | 
				
			||||||
 | 
						FImGuiContextProxy& Proxy = ModuleManager->GetContextManager().GetWorldContextProxy();
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return{ Proxy.OnDraw().Add(Delegate), EDelegateCategory::Default, Index };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FImGuiDelegateHandle FImGuiModule::AddMultiContextImGuiDelegate(const FImGuiDelegate& Delegate)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						checkf(ModuleManager, TEXT("Null pointer to internal module implementation. Is module available?"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return { ModuleManager->GetContextManager().OnDrawMultiContext().Add(Delegate), EDelegateCategory::MultiContext };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void FImGuiModule::RemoveImGuiDelegate(const FImGuiDelegateHandle& Handle)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (ModuleManager)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							if (Handle.Category == EDelegateCategory::MultiContext)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								ModuleManager->GetContextManager().OnDrawMultiContext().Remove(Handle.Handle);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else if (auto* Proxy = ModuleManager->GetContextManager().GetContextProxy(Handle.Index))
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								Proxy->OnDraw().Remove(Handle.Handle);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void FImGuiModule::StartupModule()
 | 
					void FImGuiModule::StartupModule()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	checkf(!ModuleManager, TEXT("Instance of Module Manager already exists. Instance should be created only during module startup."));
 | 
						checkf(!ModuleManager, TEXT("Instance of Module Manager already exists. Instance should be created only during module startup."));
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										55
									
								
								Source/ImGui/Public/ImGuiDelegates.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								Source/ImGui/Public/ImGuiDelegates.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,55 @@
 | 
				
			|||||||
 | 
					// Distributed under the MIT License (MIT) (see accompanying LICENSE file)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <Core.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** Delegate that allows to subscribe for ImGui events.  */
 | 
				
			||||||
 | 
					typedef FSimpleMulticastDelegate::FDelegate FImGuiDelegate;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Handle to ImGui delegate. Contains additional information locating delegates in different contexts.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					class FImGuiDelegateHandle
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						FImGuiDelegateHandle() = default;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool IsValid() const
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							return Handle.IsValid();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void Reset()
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							Handle.Reset();
 | 
				
			||||||
 | 
							Index = 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						FImGuiDelegateHandle(const FDelegateHandle& InHandle, int32 InCategory, int32 InIndex = 0)
 | 
				
			||||||
 | 
							: Handle(InHandle)
 | 
				
			||||||
 | 
							, Category(InCategory)
 | 
				
			||||||
 | 
							, Index(InIndex)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						friend bool operator==(const FImGuiDelegateHandle& Lhs, const FImGuiDelegateHandle& Rhs)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							return Lhs.Handle == Rhs.Handle && Lhs.Category == Rhs.Category && Lhs.Index == Rhs.Index;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						friend bool operator!=(const FImGuiDelegateHandle& Lhs, const FImGuiDelegateHandle& Rhs)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							return !(Lhs == Rhs);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						FDelegateHandle Handle;
 | 
				
			||||||
 | 
						int32 Category = 0;
 | 
				
			||||||
 | 
						int32 Index = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						friend class FImGuiModule;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
@ -2,6 +2,8 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "ImGuiDelegates.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <ModuleManager.h>
 | 
					#include <ModuleManager.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -9,6 +11,64 @@ class FImGuiModule : public IModuleInterface
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Singleton-like access to this module's interface. This is just for convenience!
 | 
				
			||||||
 | 
						 * Beware of calling this during the shutdown phase, though. Your module might have been unloaded already.
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @return Returns singleton instance, loading the module on demand if needed
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						static inline FImGuiModule& Get()
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							return FModuleManager::LoadModuleChecked<FImGuiModule>("ImGui");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Checks to see if this module is loaded and ready. It is only valid to call Get() if IsAvailable() returns true.
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @return True if the module is loaded and ready to use
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						static inline bool IsAvailable()
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							return FModuleManager::Get().IsModuleLoaded("ImGui");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if WITH_EDITOR
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Add a delegate called at the end of editor debug frame to draw debug controls in its ImGui context, creating
 | 
				
			||||||
 | 
						 * that context on demand.
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @param Delegate - Delegate that we want to add (@see FImGuiDelegate::Create...)
 | 
				
			||||||
 | 
						 * @returns Returns handle that can be used to remove delegate (@see RemoveImGuiDelegate)
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						virtual FImGuiDelegateHandle AddEditorImGuiDelegate(const FImGuiDelegate& Delegate);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Add a delegate called at the end of current world debug frame to draw debug controls in its ImGui context,
 | 
				
			||||||
 | 
						 * creating that context on demand.
 | 
				
			||||||
 | 
						 * This function will throw if called outside of a world context (i.e. current world cannot be found).
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @param Delegate - Delegate that we want to add (@see FImGuiDelegate::Create...)
 | 
				
			||||||
 | 
						 * @returns Returns handle that can be used to remove delegate (@see RemoveImGuiDelegate)
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						virtual FImGuiDelegateHandle AddWorldImGuiDelegate(const FImGuiDelegate& Delegate);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Add shared delegate called for each ImGui context at the end of debug frame, after calling context specific
 | 
				
			||||||
 | 
						 * delegate. This delegate will be used for any ImGui context, created before or after it is registered.
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @param Delegate - Delegate that we want to add (@see FImGuiDelegate::Create...)
 | 
				
			||||||
 | 
						 * @returns Returns handle that can be used to remove delegate (@see RemoveImGuiDelegate)
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						virtual FImGuiDelegateHandle AddMultiContextImGuiDelegate(const FImGuiDelegate& Delegate);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Remove delegate added with any version of Add...ImGuiDelegate
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @param Handle - Delegate handle that was returned by adding function
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						virtual void RemoveImGuiDelegate(const FImGuiDelegateHandle& Handle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/** IModuleInterface implementation */
 | 
						/** IModuleInterface implementation */
 | 
				
			||||||
	virtual void StartupModule() override;
 | 
						virtual void StartupModule() override;
 | 
				
			||||||
	virtual void ShutdownModule() override;
 | 
						virtual void ShutdownModule() override;
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user