Moved ImGui Draw events, so they are called during World Tick Start. Old behaviour, where those events were called during Post-Tick, can be restored by setting console variable ImGui.DebugDrawOnWorldTick to zero.

This commit is contained in:
Sebastian 2018-03-20 23:24:03 +00:00
parent 052ae0a201
commit 8c1c710646
4 changed files with 49 additions and 29 deletions

View File

@ -12,6 +12,20 @@
#include <imgui.h> #include <imgui.h>
namespace CVars
{
TAutoConsoleVariable<int> 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 namespace
{ {
#if WITH_EDITOR #if WITH_EDITOR
@ -58,17 +72,13 @@ namespace
FImGuiContextManager::FImGuiContextManager() FImGuiContextManager::FImGuiContextManager()
{ {
#if WITH_EDITOR
FWorldDelegates::OnWorldTickStart.AddRaw(this, &FImGuiContextManager::OnWorldTickStart); FWorldDelegates::OnWorldTickStart.AddRaw(this, &FImGuiContextManager::OnWorldTickStart);
#endif
} }
FImGuiContextManager::~FImGuiContextManager() FImGuiContextManager::~FImGuiContextManager()
{ {
#if WITH_EDITOR
// Order matters because contexts can be created during World Tick Start events. // Order matters because contexts can be created during World Tick Start events.
FWorldDelegates::OnWorldTickStart.RemoveAll(this); FWorldDelegates::OnWorldTickStart.RemoveAll(this);
#endif
Contexts.Empty(); Contexts.Empty();
ImGui::Shutdown(); ImGui::Shutdown();
} }
@ -88,15 +98,18 @@ void FImGuiContextManager::Tick(float DeltaSeconds)
} }
} }
#if WITH_EDITOR
void FImGuiContextManager::OnWorldTickStart(ELevelTick TickType, float DeltaSeconds) void FImGuiContextManager::OnWorldTickStart(ELevelTick TickType, float DeltaSeconds)
{ {
if (GWorld) if (GWorld)
{ {
GetWorldContextProxy(*GWorld).SetAsCurrent(); FImGuiContextProxy& ContextProxy = GetWorldContextProxy(*GWorld);
ContextProxy.SetAsCurrent();
if (CVars::DebugDrawOnWorldTick.GetValueOnGameThread() > 0)
{
ContextProxy.Draw();
}
} }
} }
#endif // WITH_EDITOR
#if WITH_EDITOR #if WITH_EDITOR
FImGuiContextManager::FContextData& FImGuiContextManager::GetEditorContextData() FImGuiContextManager::FContextData& FImGuiContextManager::GetEditorContextData()

View File

@ -86,9 +86,7 @@ private:
#endif // WITH_EDITOR #endif // WITH_EDITOR
#if WITH_EDITOR
void OnWorldTickStart(ELevelTick TickType, float DeltaSeconds); void OnWorldTickStart(ELevelTick TickType, float DeltaSeconds);
#endif
#if WITH_EDITOR #if WITH_EDITOR
FContextData& GetEditorContextData(); FContextData& GetEditorContextData();

View File

@ -14,6 +14,11 @@ static constexpr float DEFAULT_CANVAS_WIDTH = 3840.f;
static constexpr float DEFAULT_CANVAS_HEIGHT = 2160.f; static constexpr float DEFAULT_CANVAS_HEIGHT = 2160.f;
namespace CVars
{
extern TAutoConsoleVariable<int> DebugDrawOnWorldTick;
}
namespace namespace
{ {
FString GetSaveDirectory() FString GetSaveDirectory()
@ -99,24 +104,26 @@ FImGuiContextProxy::~FImGuiContextProxy()
void FImGuiContextProxy::Draw() void FImGuiContextProxy::Draw()
{ {
// Comparing to LastTickFrameNumber rather than GFrameNumber to make sure that this is driven by our own update cycle. if (bIsFrameStarted && !bIsDrawCalled)
if (LastDrawFrameNumber < LastTickFrameNumber)
{ {
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(); SharedDrawEvent->Broadcast();
}
// Broadcast draw event to allow listeners to draw their controls to this context. if (DrawEvent.IsBound())
if (DrawEvent.IsBound()) {
{ DrawEvent.Broadcast();
DrawEvent.Broadcast(); }
} if (!bSharedFirst && SharedDrawEvent && SharedDrawEvent->IsBound())
if (SharedDrawEvent && SharedDrawEvent->IsBound()) {
{ SharedDrawEvent->Broadcast();
SharedDrawEvent->Broadcast();
}
} }
} }
} }
@ -124,9 +131,9 @@ void FImGuiContextProxy::Draw()
void FImGuiContextProxy::Tick(float DeltaSeconds) void FImGuiContextProxy::Tick(float DeltaSeconds)
{ {
// Making sure that we tick only once per frame. // Making sure that we tick only once per frame.
if (LastTickFrameNumber < GFrameNumber) if (LastFrameNumber < GFrameNumber)
{ {
LastTickFrameNumber = GFrameNumber; LastFrameNumber = GFrameNumber;
SetAsCurrent(); SetAsCurrent();
@ -165,6 +172,7 @@ void FImGuiContextProxy::BeginFrame(float DeltaTime)
ImGui::NewFrame(); ImGui::NewFrame();
bIsFrameStarted = true; bIsFrameStarted = true;
bIsDrawCalled = false;
} }
} }

View File

@ -76,12 +76,13 @@ private:
bool bHasActiveItem = false; bool bHasActiveItem = false;
bool bIsFrameStarted = false; bool bIsFrameStarted = false;
bool bIsDrawCalled = false;
uint32 LastFrameNumber = 0;
FSimpleMulticastDelegate DrawEvent; FSimpleMulticastDelegate DrawEvent;
FSimpleMulticastDelegate* SharedDrawEvent = nullptr; FSimpleMulticastDelegate* SharedDrawEvent = nullptr;
uint32 LastTickFrameNumber = 0;
uint32 LastDrawFrameNumber = 0;
const FImGuiInputState* InputState = nullptr; const FImGuiInputState* InputState = nullptr;
TArray<FImGuiDrawList> DrawLists; TArray<FImGuiDrawList> DrawLists;