mirror of
https://github.com/kevinporetti/UnrealImGui.git
synced 2025-01-18 16:30:32 +00:00
Changed FImGuiContextManager to prevent moving created context proxies and to allow other objects with the same or shorter lifespan safely use cached pointers to those resources.
- Disabled move semantics in FImGuiContextProxy and removed code related to moving ImGui context. - Changed FImGuiContextManager to store proxies as unique pointers.
This commit is contained in:
parent
5f1dc964cf
commit
71dd082f69
@ -88,7 +88,7 @@ void FImGuiContextManager::Tick(float DeltaSeconds)
|
|||||||
auto& ContextData = Pair.Value;
|
auto& ContextData = Pair.Value;
|
||||||
if (ContextData.CanTick())
|
if (ContextData.CanTick())
|
||||||
{
|
{
|
||||||
ContextData.ContextProxy.Tick(DeltaSeconds);
|
ContextData.ContextProxy->Tick(DeltaSeconds);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -129,7 +129,7 @@ FImGuiContextManager::FContextData& FImGuiContextManager::GetEditorContextData()
|
|||||||
if (UNLIKELY(!Data))
|
if (UNLIKELY(!Data))
|
||||||
{
|
{
|
||||||
Data = &Contexts.Emplace(Utilities::EDITOR_CONTEXT_INDEX, FContextData{ GetEditorContextName(), Utilities::EDITOR_CONTEXT_INDEX, DrawMultiContextEvent, FontAtlas, -1 });
|
Data = &Contexts.Emplace(Utilities::EDITOR_CONTEXT_INDEX, FContextData{ GetEditorContextName(), Utilities::EDITOR_CONTEXT_INDEX, DrawMultiContextEvent, FontAtlas, -1 });
|
||||||
ContextProxyCreatedEvent.Broadcast(Utilities::EDITOR_CONTEXT_INDEX, Data->ContextProxy);
|
ContextProxyCreatedEvent.Broadcast(Utilities::EDITOR_CONTEXT_INDEX, *Data->ContextProxy);
|
||||||
}
|
}
|
||||||
|
|
||||||
return *Data;
|
return *Data;
|
||||||
@ -144,7 +144,7 @@ FImGuiContextManager::FContextData& FImGuiContextManager::GetStandaloneWorldCont
|
|||||||
if (UNLIKELY(!Data))
|
if (UNLIKELY(!Data))
|
||||||
{
|
{
|
||||||
Data = &Contexts.Emplace(Utilities::STANDALONE_GAME_CONTEXT_INDEX, FContextData{ GetWorldContextName(), Utilities::STANDALONE_GAME_CONTEXT_INDEX, DrawMultiContextEvent, FontAtlas });
|
Data = &Contexts.Emplace(Utilities::STANDALONE_GAME_CONTEXT_INDEX, FContextData{ GetWorldContextName(), Utilities::STANDALONE_GAME_CONTEXT_INDEX, DrawMultiContextEvent, FontAtlas });
|
||||||
ContextProxyCreatedEvent.Broadcast(Utilities::STANDALONE_GAME_CONTEXT_INDEX, Data->ContextProxy);
|
ContextProxyCreatedEvent.Broadcast(Utilities::STANDALONE_GAME_CONTEXT_INDEX, *Data->ContextProxy);
|
||||||
}
|
}
|
||||||
|
|
||||||
return *Data;
|
return *Data;
|
||||||
@ -185,7 +185,7 @@ FImGuiContextManager::FContextData& FImGuiContextManager::GetWorldContextData(co
|
|||||||
if (UNLIKELY(!Data))
|
if (UNLIKELY(!Data))
|
||||||
{
|
{
|
||||||
Data = &Contexts.Emplace(Index, FContextData{ GetWorldContextName(World), Index, DrawMultiContextEvent, FontAtlas, WorldContext->PIEInstance });
|
Data = &Contexts.Emplace(Index, FContextData{ GetWorldContextName(World), Index, DrawMultiContextEvent, FontAtlas, WorldContext->PIEInstance });
|
||||||
ContextProxyCreatedEvent.Broadcast(Index, Data->ContextProxy);
|
ContextProxyCreatedEvent.Broadcast(Index, *Data->ContextProxy);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -196,7 +196,7 @@ FImGuiContextManager::FContextData& FImGuiContextManager::GetWorldContextData(co
|
|||||||
if (UNLIKELY(!Data))
|
if (UNLIKELY(!Data))
|
||||||
{
|
{
|
||||||
Data = &Contexts.Emplace(Index, FContextData{ GetWorldContextName(World), Index, DrawMultiContextEvent, FontAtlas });
|
Data = &Contexts.Emplace(Index, FContextData{ GetWorldContextName(World), Index, DrawMultiContextEvent, FontAtlas });
|
||||||
ContextProxyCreatedEvent.Broadcast(Index, Data->ContextProxy);
|
ContextProxyCreatedEvent.Broadcast(Index, *Data->ContextProxy);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -34,25 +34,25 @@ public:
|
|||||||
|
|
||||||
#if WITH_EDITOR
|
#if WITH_EDITOR
|
||||||
// Get or create editor ImGui context proxy.
|
// Get or create editor ImGui context proxy.
|
||||||
FORCEINLINE FImGuiContextProxy& GetEditorContextProxy() { return GetEditorContextData().ContextProxy; }
|
FORCEINLINE FImGuiContextProxy& GetEditorContextProxy() { return *GetEditorContextData().ContextProxy; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !WITH_EDITOR
|
#if !WITH_EDITOR
|
||||||
// Get or create standalone game ImGui context proxy.
|
// Get or create standalone game ImGui context proxy.
|
||||||
FORCEINLINE FImGuiContextProxy& GetWorldContextProxy() { return GetStandaloneWorldContextData().ContextProxy; }
|
FORCEINLINE FImGuiContextProxy& GetWorldContextProxy() { return *GetStandaloneWorldContextData().ContextProxy; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// 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.
|
// 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; }
|
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)
|
||||||
{
|
{
|
||||||
FContextData* Data = Contexts.Find(ContextIndex);
|
FContextData* Data = Contexts.Find(ContextIndex);
|
||||||
return Data ? &(Data->ContextProxy) : nullptr;
|
return Data ? Data->ContextProxy.Get() : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delegate called for all contexts in manager, right after calling context specific draw event. Allows listeners
|
// Delegate called for all contexts in manager, right after calling context specific draw event. Allows listeners
|
||||||
@ -66,38 +66,20 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
#if WITH_EDITOR
|
|
||||||
|
|
||||||
struct FContextData
|
struct FContextData
|
||||||
{
|
{
|
||||||
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, ContextIndex, &SharedDrawEvent, &FontAtlas)
|
, ContextProxy(new FImGuiContextProxy(ContextName, ContextIndex, &SharedDrawEvent, &FontAtlas))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCEINLINE bool CanTick() const { return PIEInstance < 0 || GEngine->GetWorldContextFromPIEInstance(PIEInstance); }
|
FORCEINLINE bool CanTick() const { return PIEInstance < 0 || GEngine->GetWorldContextFromPIEInstance(PIEInstance); }
|
||||||
|
|
||||||
int32 PIEInstance = -1;
|
int32 PIEInstance = -1;
|
||||||
FImGuiContextProxy ContextProxy;
|
TUniquePtr<FImGuiContextProxy> ContextProxy;
|
||||||
};
|
};
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
struct FContextData
|
|
||||||
{
|
|
||||||
FContextData(const FString& ContextName, int32 ContextIndex, FSimpleMulticastDelegate& SharedDrawEvent, ImFontAtlas& FontAtlas)
|
|
||||||
: ContextProxy(ContextName, ContextIndex, &SharedDrawEvent, &FontAtlas)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
FORCEINLINE bool CanTick() const { return true; }
|
|
||||||
|
|
||||||
FImGuiContextProxy ContextProxy;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // WITH_EDITOR
|
|
||||||
|
|
||||||
void OnWorldTickStart(ELevelTick TickType, float DeltaSeconds);
|
void OnWorldTickStart(ELevelTick TickType, float DeltaSeconds);
|
||||||
|
|
||||||
#if ENGINE_COMPATIBILITY_WITH_WORLD_POST_ACTOR_TICK
|
#if ENGINE_COMPATIBILITY_WITH_WORLD_POST_ACTOR_TICK
|
||||||
|
@ -41,19 +41,6 @@ namespace
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FImGuiContextProxy::FImGuiContextPtr::~FImGuiContextPtr()
|
|
||||||
{
|
|
||||||
if (Context)
|
|
||||||
{
|
|
||||||
// Setting this as a current context. is still required in the current framework version to properly shutdown
|
|
||||||
// and save data.
|
|
||||||
ImGui::SetCurrentContext(Context);
|
|
||||||
|
|
||||||
// Save context data and destroy.
|
|
||||||
ImGui::DestroyContext(Context);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
FImGuiContextProxy::FImGuiContextProxy(const FString& InName, int32 InContextIndex, FSimpleMulticastDelegate* InSharedDrawEvent, ImFontAtlas* InFontAtlas)
|
FImGuiContextProxy::FImGuiContextProxy(const FString& InName, int32 InContextIndex, FSimpleMulticastDelegate* InSharedDrawEvent, ImFontAtlas* InFontAtlas)
|
||||||
: Name(InName)
|
: Name(InName)
|
||||||
, ContextIndex(InContextIndex)
|
, ContextIndex(InContextIndex)
|
||||||
@ -61,7 +48,7 @@ FImGuiContextProxy::FImGuiContextProxy(const FString& InName, int32 InContextInd
|
|||||||
, IniFilename(TCHAR_TO_ANSI(*GetIniFile(InName)))
|
, IniFilename(TCHAR_TO_ANSI(*GetIniFile(InName)))
|
||||||
{
|
{
|
||||||
// Create context.
|
// Create context.
|
||||||
Context = FImGuiContextPtr(ImGui::CreateContext(InFontAtlas));
|
Context = ImGui::CreateContext(InFontAtlas);
|
||||||
|
|
||||||
// Set this context in ImGui for initialization (any allocations will be tracked in this context).
|
// Set this context in ImGui for initialization (any allocations will be tracked in this context).
|
||||||
SetAsCurrent();
|
SetAsCurrent();
|
||||||
@ -84,6 +71,19 @@ FImGuiContextProxy::FImGuiContextProxy(const FString& InName, int32 InContextInd
|
|||||||
BeginFrame();
|
BeginFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FImGuiContextProxy::~FImGuiContextProxy()
|
||||||
|
{
|
||||||
|
if (Context)
|
||||||
|
{
|
||||||
|
// It seems that to properly shutdown context we need to set it as the current one (at least in this framework
|
||||||
|
// version), even though we can pass it to the destroy function.
|
||||||
|
SetAsCurrent();
|
||||||
|
|
||||||
|
// Save context data and destroy.
|
||||||
|
ImGui::DestroyContext(Context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void FImGuiContextProxy::DrawEarlyDebug()
|
void FImGuiContextProxy::DrawEarlyDebug()
|
||||||
{
|
{
|
||||||
if (bIsFrameStarted && !bIsDrawEarlyDebugCalled)
|
if (bIsFrameStarted && !bIsDrawEarlyDebugCalled)
|
||||||
|
@ -17,37 +17,16 @@
|
|||||||
// broadcasts draw events to allow listeners draw their controls. After update it stores draw data.
|
// broadcasts draw events to allow listeners draw their controls. After update it stores draw data.
|
||||||
class FImGuiContextProxy
|
class FImGuiContextProxy
|
||||||
{
|
{
|
||||||
class FImGuiContextPtr
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
FImGuiContextPtr() = default;
|
|
||||||
FImGuiContextPtr(ImGuiContext* InContext) : Context(InContext) {}
|
|
||||||
|
|
||||||
FImGuiContextPtr(const FImGuiContextPtr&) = delete;
|
|
||||||
FImGuiContextPtr& operator=(const FImGuiContextPtr&) = delete;
|
|
||||||
|
|
||||||
FImGuiContextPtr(FImGuiContextPtr&& Other) : Context(Other.Context) { Other.Context = nullptr; }
|
|
||||||
FImGuiContextPtr& operator=(FImGuiContextPtr&& Other) { std::swap(Context, Other.Context); return *this; }
|
|
||||||
|
|
||||||
~FImGuiContextPtr();
|
|
||||||
|
|
||||||
ImGuiContext* Get() const { return Context; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
ImGuiContext* Context = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
FImGuiContextProxy(const FString& Name, int32 InContextIndex, FSimpleMulticastDelegate* InSharedDrawEvent, ImFontAtlas* InFontAtlas);
|
FImGuiContextProxy(const FString& Name, int32 InContextIndex, FSimpleMulticastDelegate* InSharedDrawEvent, ImFontAtlas* InFontAtlas);
|
||||||
|
~FImGuiContextProxy();
|
||||||
|
|
||||||
FImGuiContextProxy(const FImGuiContextProxy&) = delete;
|
FImGuiContextProxy(const FImGuiContextProxy&) = delete;
|
||||||
FImGuiContextProxy& operator=(const FImGuiContextProxy&) = delete;
|
FImGuiContextProxy& operator=(const FImGuiContextProxy&) = delete;
|
||||||
|
|
||||||
FImGuiContextProxy(FImGuiContextProxy&&) = default;
|
FImGuiContextProxy(FImGuiContextProxy&&) = delete;
|
||||||
FImGuiContextProxy& operator=(FImGuiContextProxy&&) = default;
|
FImGuiContextProxy& operator=(FImGuiContextProxy&&) = delete;
|
||||||
|
|
||||||
// Get the name of this context.
|
// Get the name of this context.
|
||||||
const FString& GetName() const { return Name; }
|
const FString& GetName() const { return Name; }
|
||||||
@ -60,10 +39,10 @@ public:
|
|||||||
const FImGuiInputState& GetInputState() const { return InputState; }
|
const FImGuiInputState& GetInputState() const { return InputState; }
|
||||||
|
|
||||||
// Is this context the current ImGui context.
|
// Is this context the current ImGui context.
|
||||||
bool IsCurrentContext() const { return ImGui::GetCurrentContext() == Context.Get(); }
|
bool IsCurrentContext() const { return ImGui::GetCurrentContext() == Context; }
|
||||||
|
|
||||||
// Set this context as current ImGui context.
|
// Set this context as current ImGui context.
|
||||||
void SetAsCurrent() { ImGui::SetCurrentContext(Context.Get()); }
|
void SetAsCurrent() { ImGui::SetCurrentContext(Context); }
|
||||||
|
|
||||||
// Context display size (read once per frame during context update).
|
// Context display size (read once per frame during context update).
|
||||||
const FVector2D& GetDisplaySize() const { return DisplaySize; }
|
const FVector2D& GetDisplaySize() const { return DisplaySize; }
|
||||||
@ -102,7 +81,7 @@ private:
|
|||||||
void BroadcastWorldDebug();
|
void BroadcastWorldDebug();
|
||||||
void BroadcastMultiContextDebug();
|
void BroadcastMultiContextDebug();
|
||||||
|
|
||||||
FImGuiContextPtr Context;
|
ImGuiContext* Context;
|
||||||
|
|
||||||
FVector2D DisplaySize = FVector2D::ZeroVector;
|
FVector2D DisplaySize = FVector2D::ZeroVector;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user