diff --git a/Source/ImGui/Private/ImGuiContextManager.cpp b/Source/ImGui/Private/ImGuiContextManager.cpp index 21df97f..b0b8803 100644 --- a/Source/ImGui/Private/ImGuiContextManager.cpp +++ b/Source/ImGui/Private/ImGuiContextManager.cpp @@ -12,6 +12,20 @@ #include +namespace CVars +{ + TAutoConsoleVariable DebugDrawOnWorldTick(TEXT("ImGui.DebugDrawOnWorldTick"), 1, + TEXT("If this is enabled then all the ImGui debug draw events will be called during World Tick Start.\n") + TEXT("This has an advantage that all the global variables like GWorld are set to correct values.\n") + TEXT("A disadvantage is that objects are not yet updated. That can be changed by disabling this feature,") + TEXT("but preferable solution is to call debug code from object's own Tick function.\n") + TEXT("NOTE: Order of multi-context and world draw events depends on this value and is arranged in a way ") + TEXT("that world draw events and objects updates are closer together.\n") + TEXT("0: disabled, ImGui Debug Draw is called during Post-Tick\n") + TEXT("1: enabled (default), ImGui Debug Draw is called during World Tick Start"), + ECVF_Default); +} + namespace { #if WITH_EDITOR @@ -58,17 +72,13 @@ namespace FImGuiContextManager::FImGuiContextManager() { -#if WITH_EDITOR FWorldDelegates::OnWorldTickStart.AddRaw(this, &FImGuiContextManager::OnWorldTickStart); -#endif } FImGuiContextManager::~FImGuiContextManager() { -#if WITH_EDITOR // Order matters because contexts can be created during World Tick Start events. FWorldDelegates::OnWorldTickStart.RemoveAll(this); -#endif Contexts.Empty(); ImGui::Shutdown(); } @@ -88,15 +98,18 @@ void FImGuiContextManager::Tick(float DeltaSeconds) } } -#if WITH_EDITOR void FImGuiContextManager::OnWorldTickStart(ELevelTick TickType, float DeltaSeconds) { if (GWorld) { - GetWorldContextProxy(*GWorld).SetAsCurrent(); + FImGuiContextProxy& ContextProxy = GetWorldContextProxy(*GWorld); + ContextProxy.SetAsCurrent(); + if (CVars::DebugDrawOnWorldTick.GetValueOnGameThread() > 0) + { + ContextProxy.Draw(); + } } } -#endif // WITH_EDITOR #if WITH_EDITOR FImGuiContextManager::FContextData& FImGuiContextManager::GetEditorContextData() diff --git a/Source/ImGui/Private/ImGuiContextManager.h b/Source/ImGui/Private/ImGuiContextManager.h index 6664eee..bf31eca 100644 --- a/Source/ImGui/Private/ImGuiContextManager.h +++ b/Source/ImGui/Private/ImGuiContextManager.h @@ -86,9 +86,7 @@ private: #endif // WITH_EDITOR -#if WITH_EDITOR void OnWorldTickStart(ELevelTick TickType, float DeltaSeconds); -#endif #if WITH_EDITOR FContextData& GetEditorContextData(); diff --git a/Source/ImGui/Private/ImGuiContextProxy.cpp b/Source/ImGui/Private/ImGuiContextProxy.cpp index 8804860..af74a46 100644 --- a/Source/ImGui/Private/ImGuiContextProxy.cpp +++ b/Source/ImGui/Private/ImGuiContextProxy.cpp @@ -14,6 +14,11 @@ static constexpr float DEFAULT_CANVAS_WIDTH = 3840.f; static constexpr float DEFAULT_CANVAS_HEIGHT = 2160.f; +namespace CVars +{ + extern TAutoConsoleVariable DebugDrawOnWorldTick; +} + namespace { FString GetSaveDirectory() @@ -99,24 +104,26 @@ FImGuiContextProxy::~FImGuiContextProxy() void FImGuiContextProxy::Draw() { - // Comparing to LastTickFrameNumber rather than GFrameNumber to make sure that this is driven by our own update cycle. - if (LastDrawFrameNumber < LastTickFrameNumber) + if (bIsFrameStarted && !bIsDrawCalled) { - LastDrawFrameNumber = LastTickFrameNumber; + bIsDrawCalled = true; - if (bIsFrameStarted) + SetAsCurrent(); + + const bool bSharedFirst = (CVars::DebugDrawOnWorldTick.GetValueOnGameThread() > 0); + + // Broadcast draw event to allow listeners to draw their controls to this context. + if (bSharedFirst && SharedDrawEvent && SharedDrawEvent->IsBound()) { - SetAsCurrent(); - - // Broadcast draw event to allow listeners to draw their controls to this context. - if (DrawEvent.IsBound()) - { - DrawEvent.Broadcast(); - } - if (SharedDrawEvent && SharedDrawEvent->IsBound()) - { - SharedDrawEvent->Broadcast(); - } + SharedDrawEvent->Broadcast(); + } + if (DrawEvent.IsBound()) + { + DrawEvent.Broadcast(); + } + if (!bSharedFirst && SharedDrawEvent && SharedDrawEvent->IsBound()) + { + SharedDrawEvent->Broadcast(); } } } @@ -124,9 +131,9 @@ void FImGuiContextProxy::Draw() void FImGuiContextProxy::Tick(float DeltaSeconds) { // Making sure that we tick only once per frame. - if (LastTickFrameNumber < GFrameNumber) + if (LastFrameNumber < GFrameNumber) { - LastTickFrameNumber = GFrameNumber; + LastFrameNumber = GFrameNumber; SetAsCurrent(); @@ -165,6 +172,7 @@ void FImGuiContextProxy::BeginFrame(float DeltaTime) ImGui::NewFrame(); bIsFrameStarted = true; + bIsDrawCalled = false; } } diff --git a/Source/ImGui/Private/ImGuiContextProxy.h b/Source/ImGui/Private/ImGuiContextProxy.h index 817f9ea..ea8c530 100644 --- a/Source/ImGui/Private/ImGuiContextProxy.h +++ b/Source/ImGui/Private/ImGuiContextProxy.h @@ -76,12 +76,13 @@ private: bool bHasActiveItem = false; bool bIsFrameStarted = false; + bool bIsDrawCalled = false; + + uint32 LastFrameNumber = 0; + FSimpleMulticastDelegate DrawEvent; FSimpleMulticastDelegate* SharedDrawEvent = nullptr; - uint32 LastTickFrameNumber = 0; - uint32 LastDrawFrameNumber = 0; - const FImGuiInputState* InputState = nullptr; TArray DrawLists;