Replaced 'ImGui.DebugDrawOnWorldTick' console variable with conditional compilation switches and extended support to post actor tick event:

- Replaced 'ImGui.DebugDrawOnWorldTick' with DRAW_EVENTS_ON_WORLD_TICK_START switch to enforce consistency in project setup.
- Added DRAW_EVENTS_ON_POST_ACTOR_TICK to support post actor tick events (only for UE 4.18 or later).
- Added DRAW_EVENTS_ORDER_WORLD_BEFORE_MULTI_CONTEXT to allow explicitly define order between multi-context and world-context draw events.
- Rules can be configured in ImGui.Build.cs file.
This commit is contained in:
Sebastian 2018-10-28 19:54:18 +00:00
parent b4e959ccd3
commit b492932055
4 changed files with 81 additions and 30 deletions

View File

@ -1,11 +1,45 @@
// Distributed under the MIT License (MIT) (see accompanying LICENSE file)
#if UE_4_18_OR_LATER
#define WITH_POST_ACTOR_TICK
#endif
using System.Collections.Generic;
using System.IO;
using UnrealBuildTool;
public class ImGui : ModuleRules
{
// Defines when events should be broadcast. Note that at the end of the ImGui frame some global variables might be
// not set and so it seems preferable to use post actor tick (not available in older engine versions) or world tick
// start events. If more control is required Late mode with manually calling events may be used (as in practice
// events are guaranteed to be raised only once per frame).
enum EEventsBroadcastMode
{
OnWorldTickStart, // Broadcast during world tick start event.
#if WITH_POST_ACTOR_TICK
OnPostActorTick, // Broadcast during post actor tick event.
#endif
Late, // Broadcast at the end of the ImGui frame.
}
// Defines order in which multi-context and world-context events are called.
enum EEventsOrder
{
MultiBeforeWorldContext,
WorldBeforeMultiContext,
}
#if WITH_POST_ACTOR_TICK
EEventsBroadcastMode DrawEventsBroadcastMode = EEventsBroadcastMode.OnPostActorTick;
EEventsOrder DrawEventsOrder = EEventsOrder.WorldBeforeMultiContext;
#else
EEventsBroadcastMode DrawEventsBroadcastMode = EEventsBroadcastMode.OnWorldTickStart;
EEventsOrder DrawEventsOrder = EEventsOrder.MultiBeforeWorldContext;
#endif // WITH_POST_ACTOR_TICK
#if WITH_FORWARDED_MODULE_RULES_CTOR
public ImGui(ReadOnlyTargetRules Target) : base(Target)
#else
@ -89,6 +123,19 @@ public class ImGui : ModuleRules
#if !UE_4_19_OR_LATER
List<string> PrivateDefinitions = Definitions;
#endif
PrivateDefinitions.Add(string.Format("RUNTIME_LOADER_ENABLED = {0}", bEnableRuntimeLoader ? 1 : 0));
bool bDrawOnWorldTickStart = (DrawEventsBroadcastMode == EEventsBroadcastMode.OnWorldTickStart);
#if WITH_POST_ACTOR_TICK
bool bDrawOnPostActorTick = (DrawEventsBroadcastMode == EEventsBroadcastMode.OnPostActorTick);
#else
bool bDrawOnPostActorTick = false;
#endif
PrivateDefinitions.Add(string.Format("DRAW_EVENTS_ON_WORLD_TICK_START = {0}", bDrawOnWorldTickStart ? 1 : 0));
PrivateDefinitions.Add(string.Format("DRAW_EVENTS_ON_POST_ACTOR_TICK = {0}", bDrawOnPostActorTick ? 1 : 0));
PrivateDefinitions.Add(string.Format("DRAW_EVENTS_ORDER_WORLD_BEFORE_MULTI_CONTEXT = {0}",
(DrawEventsOrder == EEventsOrder.WorldBeforeMultiContext) ? 1 : 0));
}
}

View File

@ -12,20 +12,6 @@
#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
{
#if WITH_EDITOR
@ -77,12 +63,18 @@ FImGuiContextManager::FImGuiContextManager()
FontAtlas.GetTexDataAsRGBA32(&Pixels, &Width, &Height, &Bpp);
FWorldDelegates::OnWorldTickStart.AddRaw(this, &FImGuiContextManager::OnWorldTickStart);
#if DRAW_EVENTS_ON_POST_ACTOR_TICK
FWorldDelegates::OnWorldPostActorTick.AddRaw(this, &FImGuiContextManager::OnWorldPostActorTick);
#endif
}
FImGuiContextManager::~FImGuiContextManager()
{
// Order matters because contexts can be created during World Tick Start events.
FWorldDelegates::OnWorldTickStart.RemoveAll(this);
#if DRAW_EVENTS_ON_POST_ACTOR_TICK
FWorldDelegates::OnWorldPostActorTick.RemoveAll(this);
#endif
}
void FImGuiContextManager::Tick(float DeltaSeconds)
@ -106,12 +98,21 @@ void FImGuiContextManager::OnWorldTickStart(ELevelTick TickType, float DeltaSeco
{
FImGuiContextProxy& ContextProxy = GetWorldContextProxy(*GWorld);
ContextProxy.SetAsCurrent();
if (CVars::DebugDrawOnWorldTick.GetValueOnGameThread() > 0)
#if DRAW_EVENTS_ON_WORLD_TICK_START
ContextProxy.Draw();
#endif
}
}
#if DRAW_EVENTS_ON_POST_ACTOR_TICK
void FImGuiContextManager::OnWorldPostActorTick(UWorld* World, ELevelTick TickType, float DeltaSeconds)
{
FImGuiContextProxy& ContextProxy = GetWorldContextProxy(*GWorld);
ContextProxy.SetAsCurrent();
ContextProxy.Draw();
}
}
}
#endif // DRAW_EVENTS_ON_POST_ACTOR_TICK
#if WITH_EDITOR
FImGuiContextManager::FContextData& FImGuiContextManager::GetEditorContextData()

View File

@ -92,6 +92,10 @@ private:
void OnWorldTickStart(ELevelTick TickType, float DeltaSeconds);
#if DRAW_EVENTS_ON_POST_ACTOR_TICK
void OnWorldPostActorTick(UWorld* World, ELevelTick TickType, float DeltaSeconds);
#endif
#if WITH_EDITOR
FContextData& GetEditorContextData();
#endif

View File

@ -14,11 +14,6 @@ static constexpr float DEFAULT_CANVAS_WIDTH = 3840.f;
static constexpr float DEFAULT_CANVAS_HEIGHT = 2160.f;
namespace CVars
{
extern TAutoConsoleVariable<int> DebugDrawOnWorldTick;
}
namespace
{
FString GetSaveDirectory()
@ -94,21 +89,25 @@ void FImGuiContextProxy::Draw()
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())
{
SharedDrawEvent->Broadcast();
}
#if DRAW_EVENTS_ORDER_WORLD_BEFORE_MULTI_CONTEXT
if (DrawEvent.IsBound())
{
DrawEvent.Broadcast();
}
if (!bSharedFirst && SharedDrawEvent && SharedDrawEvent->IsBound())
#endif // DRAW_EVENTS_ORDER_WORLD_BEFORE_MULTI_CONTEXT
if (SharedDrawEvent && SharedDrawEvent->IsBound())
{
SharedDrawEvent->Broadcast();
}
#if !DRAW_EVENTS_ORDER_WORLD_BEFORE_MULTI_CONTEXT
if (DrawEvent.IsBound())
{
DrawEvent.Broadcast();
}
#endif // !DRAW_EVENTS_ORDER_WORLD_BEFORE_MULTI_CONTEXT
}
}