mirror of
https://github.com/kevinporetti/UnrealImGui.git
synced 2025-01-18 08:20:32 +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())
|
||||
{
|
||||
ContextData.ContextProxy.SetAsCurrent();
|
||||
ContextData.ContextProxy.Tick(DeltaSeconds);
|
||||
ContextData.ContextProxy.Tick(DeltaSeconds, &DrawMultiContextEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -105,7 +105,7 @@ FImGuiContextManager::FContextData& FImGuiContextManager::GetStandaloneWorldCont
|
||||
}
|
||||
#endif // !WITH_EDITOR
|
||||
|
||||
FImGuiContextManager::FContextData& FImGuiContextManager::GetWorldContextData(const UWorld& World)
|
||||
FImGuiContextManager::FContextData& FImGuiContextManager::GetWorldContextData(const UWorld& World, int32* OutIndex)
|
||||
{
|
||||
using namespace Utilities;
|
||||
|
||||
@ -140,5 +140,9 @@ FImGuiContextManager::FContextData& FImGuiContextManager::GetWorldContextData(co
|
||||
}
|
||||
#endif
|
||||
|
||||
if (OutIndex)
|
||||
{
|
||||
*OutIndex = Index;
|
||||
}
|
||||
return *Data;
|
||||
}
|
||||
|
@ -34,6 +34,9 @@ public:
|
||||
// Get or create ImGui context proxy for given world.
|
||||
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.
|
||||
FORCEINLINE FImGuiContextProxy* GetContextProxy(int32 ContextIndex)
|
||||
{
|
||||
@ -41,6 +44,10 @@ public:
|
||||
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);
|
||||
|
||||
private:
|
||||
@ -87,9 +94,11 @@ private:
|
||||
FContextData& GetStandaloneWorldContextData();
|
||||
#endif
|
||||
|
||||
FContextData& GetWorldContextData(const UWorld& World);
|
||||
FContextData& GetWorldContextData(const UWorld& World, int32* OutContextIndex = nullptr);
|
||||
|
||||
TMap<int32, FContextData> Contexts;
|
||||
|
||||
FImGuiDemo ImGuiDemo;
|
||||
|
||||
FSimpleMulticastDelegate DrawMultiContextEvent;
|
||||
};
|
||||
|
@ -117,7 +117,7 @@ FImGuiContextProxy::~FImGuiContextProxy()
|
||||
}
|
||||
}
|
||||
|
||||
void FImGuiContextProxy::Tick(float DeltaSeconds)
|
||||
void FImGuiContextProxy::Tick(float DeltaSeconds, FSimpleMulticastDelegate* SharedDrawEvent)
|
||||
{
|
||||
if (bIsFrameStarted)
|
||||
{
|
||||
@ -126,6 +126,10 @@ void FImGuiContextProxy::Tick(float DeltaSeconds)
|
||||
{
|
||||
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
|
||||
// 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; }
|
||||
|
||||
// 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:
|
||||
|
||||
|
@ -3,6 +3,8 @@
|
||||
#include "ImGuiPrivatePCH.h"
|
||||
|
||||
#include "ImGuiModuleManager.h"
|
||||
#include "Utilities/WorldContext.h"
|
||||
#include "Utilities/WorldContextIndex.h"
|
||||
|
||||
#include <IPluginManager.h>
|
||||
|
||||
@ -10,8 +12,77 @@
|
||||
#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;
|
||||
|
||||
#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()
|
||||
{
|
||||
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
|
||||
|
||||
#include "ImGuiDelegates.h"
|
||||
|
||||
#include <ModuleManager.h>
|
||||
|
||||
|
||||
@ -9,6 +11,64 @@ class FImGuiModule : public IModuleInterface
|
||||
{
|
||||
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 */
|
||||
virtual void StartupModule() override;
|
||||
virtual void ShutdownModule() override;
|
||||
|
Loading…
Reference in New Issue
Block a user