mirror of
https://github.com/kevinporetti/UnrealImGui.git
synced 2025-01-18 08:20:32 +00:00
Merge branch 'master' into master
This commit is contained in:
commit
ca4001343e
107
CHANGES.md
Normal file
107
CHANGES.md
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
This is only a summary provided to give a quick overview of changes. It does not list details which can be found in commit messages. If you think that more detailed changelog would be beneficiary, please raise it as an issue.
|
||||||
|
|
||||||
|
Versions marked as 'unofficial' are labelled only for the needs of this changelog. Officially I maintain version numbers since 2019/04, starting from version 1.14. If you have any of the earlier commits then you will see plugin signed as a version 1.0.
|
||||||
|
|
||||||
|
Change History
|
||||||
|
--------------
|
||||||
|
|
||||||
|
Version: 1.15 (2019/04)
|
||||||
|
- Added new FImGuiDelegates interface for ImGui debug delegates.
|
||||||
|
- Added code preserving delegates during hot-reloading and moving them to a new module.
|
||||||
|
- DEPRECIATED old FImGuiModule delegates interface and FImGuiDelegateHandle.
|
||||||
|
- Delegates registered with depreciated interface are redirected and get benefit of being preserved during hot-reloading. This can be controlled with IMGUI_REDIRECT_OBSOLETE_DELEGATES.
|
||||||
|
- Added IMGUI_WITH_OBSOLETE_DELEGATES allowing to strip depreciated interface from builds (that interface will be officially removed in one of later releases).
|
||||||
|
- Added new ImGui early debug delegates called during world tick start.
|
||||||
|
- Delegates are called in fixed order: multi-context early debug, world early debug (called during world tick start), world debug, multi-context debug (called during world post actor tick or if not available, during world tick start).
|
||||||
|
- Removed from build script configuration of debug delegates.
|
||||||
|
|
||||||
|
Version: 1.14 (2019/03)
|
||||||
|
- Added SImGuiLayout to resets layout for SImGuiWidget.
|
||||||
|
- Refactored rendering in SImGuiWidget to take advantage of layout reset.
|
||||||
|
- Reworked ImGui canvas dragging and scaling and moved it to SImGuiCanvasControl.
|
||||||
|
- Removed dependency on ImGui internal cursor data.
|
||||||
|
|
||||||
|
Version: 1.13 (unofficial) (2019/03)
|
||||||
|
- Fixed mapping from FKey to ImGui key index to gracefully handle unsupported keys and work on platforms that do not support all the keys defined in ImGui key map.
|
||||||
|
- Fixed non-unity compile warnings and errors.
|
||||||
|
|
||||||
|
Version: 1.12 (unofficial) (2018/12)
|
||||||
|
- Added support for sharing with game keyboard and gamepad input.
|
||||||
|
- Added FImGuiModuleSettings to handle delayed loading of UImGuiSettings and serve as settings proxy for other classes.
|
||||||
|
|
||||||
|
Version: 1.11 (unofficial) (2018/10-11)
|
||||||
|
- Moved ImGui Draw events to be called at the end of the world update during post actor tick event. Only available in UE 4.18 or later, with old behaviour available as an option.
|
||||||
|
- Replaced console variable based configuration of ImGui Draw events with macros.
|
||||||
|
- Replaced console variable based configuration of software cursor with a setting.
|
||||||
|
- Console variables and logging that are primarily focused on module development are hidden by default and can be enabled by setting IMGUI_MODULE_DEVELOPER to 1.
|
||||||
|
- Replaced console variables with module properties and settings.
|
||||||
|
- Added console commands to control module properties.
|
||||||
|
- Added support to preserve and move module properties to hot-reloaded module.
|
||||||
|
- Moved properties to public interface.
|
||||||
|
- Added FImGuiModule interface to access properties instance.
|
||||||
|
- DEPRECIATED FImGuiModule functions to modify single properties.
|
||||||
|
|
||||||
|
Version: 1.10 (unofficial) (2018/10)
|
||||||
|
- Changed module type to 'Developer' to make it easier strip it from shipping or other builds.
|
||||||
|
- Added runtime loader to allow automatically load developer module in runtime builds.
|
||||||
|
|
||||||
|
Version: 1.09 (unofficial) (2018/08-09)
|
||||||
|
- Added interface to register user textures for use in ImGui.
|
||||||
|
- Fixed bad deallocation in Texture Manager.
|
||||||
|
- Updated to ImGui 1.61.
|
||||||
|
- Updated to UE 4.20.
|
||||||
|
|
||||||
|
Version: 1.08 (unofficial) (2018/07-08)
|
||||||
|
- Added ImGui Input Handler to allow to customization of input handling.
|
||||||
|
- Added ImGui settings with editor page in project properties.
|
||||||
|
- Added command to switch input mode with configurable key binding.
|
||||||
|
- Added backward compatibility macros.
|
||||||
|
- Fixed hot-reloading issues with using ImGui implementation.
|
||||||
|
|
||||||
|
Version: 1.07 (unofficial) (2018/05)
|
||||||
|
- Improved initialization to allow loading module in any loading phase.
|
||||||
|
|
||||||
|
Version: 1.06 (unofficial) (2018/05)
|
||||||
|
- Updated to ImGui 1.61
|
||||||
|
- Added support for gamepad and keyboard navigation.
|
||||||
|
|
||||||
|
Version: 1.05 (unofficial) (2018/04)
|
||||||
|
- Added mode to scale and drag ImGui canvas.
|
||||||
|
- Using ImGui internal cursor data to draw drag icon.
|
||||||
|
|
||||||
|
Version: 1.04 (unofficial) (2018/03)
|
||||||
|
- Minimised lag between ending ImGui frame and rendering draw data in Slate.
|
||||||
|
- Moved ImGui Draw event to be called during world tick start with configuration to use old behaviour.
|
||||||
|
|
||||||
|
Version: 1.03 (unofficial) (2018/01-03)
|
||||||
|
- Fixed warnings and errors found in non-unity, Linux, PS4 or XBox builds.
|
||||||
|
- Added configuration to choose between hardware and software cursor with hardware cursor used by default.
|
||||||
|
|
||||||
|
Version: 1.02 (unofficial) (2018/01)
|
||||||
|
- Updated to ImGui 1.53.
|
||||||
|
- Fixed problems with ImGui Demo working in multi-context environment.
|
||||||
|
- Added FImGuiModule interface to change input mode and demo visibility.
|
||||||
|
- Fixed input state issues after application loses focus.
|
||||||
|
- Added input state debugging and `ImGui.Debug.Input` console variable to switch it.
|
||||||
|
|
||||||
|
Version: 1.01 (unofficial) (2017/10)
|
||||||
|
- Added `ImGui.ShowDemo` console variable to show/hide ImGui demo.
|
||||||
|
- Added automatic switching to right ImGui context at the beginning of the world tick.
|
||||||
|
- Updated to UE 4.18
|
||||||
|
|
||||||
|
Version: <=1.00 (unofficial) (2017/04-10)
|
||||||
|
- Added ImGui source code as an external module to expose it in IDE.
|
||||||
|
- Integrated ImGui source code to build as part of the ImGui module.
|
||||||
|
- Added FImGuiModule to implement ImGui module interface.
|
||||||
|
- Added FImGuiModuleManager to control other module components.
|
||||||
|
- Added FTextureManager to manage texture resources and map them to ImTextureID.
|
||||||
|
- Added SImGuiWidget to handle Slate input and render in Slate ImGui draw data.
|
||||||
|
- Added FImGuiInputState to collect and store input before it can be copied to ImGui IO.
|
||||||
|
- Added FContextProxy to represent a single ImGui context.
|
||||||
|
- Added FImGuiContextManager to create and manage ImGui context proxies.
|
||||||
|
- Added Multi-PIE support with each PIE instance getting a dedicated ImGui context proxy, input state and widget.
|
||||||
|
- Added `ImGui.InputEnabled` console variable to control whether input mode is enabled.
|
||||||
|
- Added widget debugging and `ImGui.Debug.Widget` console variable to switch it.
|
||||||
|
- Added ImGui software cursor.
|
||||||
|
- Added support for session reloading with ini file names based on world type and PIE index.
|
||||||
|
- Added FImGuiModule interface to register ImGui delegates called to draw ImGui controls.
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"FileVersion": 3,
|
"FileVersion": 3,
|
||||||
"Version": 1,
|
"Version": 1,
|
||||||
"VersionName": "1.0",
|
"VersionName": "1.15",
|
||||||
"FriendlyName": "ImGui",
|
"FriendlyName": "ImGui",
|
||||||
"Description": "",
|
"Description": "",
|
||||||
"Category": "Debug",
|
"Category": "Debug",
|
||||||
|
@ -1,45 +1,11 @@
|
|||||||
// Distributed under the MIT License (MIT) (see accompanying LICENSE file)
|
// 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.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using UnrealBuildTool;
|
using UnrealBuildTool;
|
||||||
|
|
||||||
public class ImGui : ModuleRules
|
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
|
#if WITH_FORWARDED_MODULE_RULES_CTOR
|
||||||
public ImGui(ReadOnlyTargetRules Target) : base(Target)
|
public ImGui(ReadOnlyTargetRules Target) : base(Target)
|
||||||
#else
|
#else
|
||||||
@ -128,17 +94,5 @@ public class ImGui : ModuleRules
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
PrivateDefinitions.Add(string.Format("RUNTIME_LOADER_ENABLED={0}", bEnableRuntimeLoader ? 1 : 0));
|
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));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include "ImGuiContextManager.h"
|
#include "ImGuiContextManager.h"
|
||||||
|
|
||||||
|
#include "ImGuiDelegatesContainer.h"
|
||||||
#include "ImGuiImplementation.h"
|
#include "ImGuiImplementation.h"
|
||||||
#include "Utilities/ScopeGuards.h"
|
#include "Utilities/ScopeGuards.h"
|
||||||
#include "Utilities/WorldContext.h"
|
#include "Utilities/WorldContext.h"
|
||||||
@ -63,7 +64,7 @@ FImGuiContextManager::FImGuiContextManager()
|
|||||||
FontAtlas.GetTexDataAsRGBA32(&Pixels, &Width, &Height, &Bpp);
|
FontAtlas.GetTexDataAsRGBA32(&Pixels, &Width, &Height, &Bpp);
|
||||||
|
|
||||||
FWorldDelegates::OnWorldTickStart.AddRaw(this, &FImGuiContextManager::OnWorldTickStart);
|
FWorldDelegates::OnWorldTickStart.AddRaw(this, &FImGuiContextManager::OnWorldTickStart);
|
||||||
#if DRAW_EVENTS_ON_POST_ACTOR_TICK
|
#if ENGINE_COMPATIBILITY_WITH_WORLD_POST_ACTOR_TICK
|
||||||
FWorldDelegates::OnWorldPostActorTick.AddRaw(this, &FImGuiContextManager::OnWorldPostActorTick);
|
FWorldDelegates::OnWorldPostActorTick.AddRaw(this, &FImGuiContextManager::OnWorldPostActorTick);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -72,7 +73,7 @@ FImGuiContextManager::~FImGuiContextManager()
|
|||||||
{
|
{
|
||||||
// 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);
|
||||||
#if DRAW_EVENTS_ON_POST_ACTOR_TICK
|
#if ENGINE_COMPATIBILITY_WITH_WORLD_POST_ACTOR_TICK
|
||||||
FWorldDelegates::OnWorldPostActorTick.RemoveAll(this);
|
FWorldDelegates::OnWorldPostActorTick.RemoveAll(this);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -89,6 +90,11 @@ void FImGuiContextManager::Tick(float DeltaSeconds)
|
|||||||
{
|
{
|
||||||
ContextData.ContextProxy.Tick(DeltaSeconds);
|
ContextData.ContextProxy.Tick(DeltaSeconds);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Clear to make sure that we don't store objects registered for world that is no longer valid.
|
||||||
|
FImGuiDelegatesContainer::Get().OnWorldDebug(Pair.Key).Clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,22 +103,23 @@ void FImGuiContextManager::OnWorldTickStart(ELevelTick TickType, float DeltaSeco
|
|||||||
if (GWorld)
|
if (GWorld)
|
||||||
{
|
{
|
||||||
FImGuiContextProxy& ContextProxy = GetWorldContextProxy(*GWorld);
|
FImGuiContextProxy& ContextProxy = GetWorldContextProxy(*GWorld);
|
||||||
|
|
||||||
|
// Set as current, so we have right context ready when updating world objects.
|
||||||
ContextProxy.SetAsCurrent();
|
ContextProxy.SetAsCurrent();
|
||||||
|
|
||||||
#if DRAW_EVENTS_ON_WORLD_TICK_START
|
ContextProxy.DrawEarlyDebug();
|
||||||
ContextProxy.Draw();
|
#if !ENGINE_COMPATIBILITY_WITH_WORLD_POST_ACTOR_TICK
|
||||||
|
ContextProxy.DrawDebug();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DRAW_EVENTS_ON_POST_ACTOR_TICK
|
#if ENGINE_COMPATIBILITY_WITH_WORLD_POST_ACTOR_TICK
|
||||||
void FImGuiContextManager::OnWorldPostActorTick(UWorld* World, ELevelTick TickType, float DeltaSeconds)
|
void FImGuiContextManager::OnWorldPostActorTick(UWorld* World, ELevelTick TickType, float DeltaSeconds)
|
||||||
{
|
{
|
||||||
FImGuiContextProxy& ContextProxy = GetWorldContextProxy(*GWorld);
|
GetWorldContextProxy(*GWorld).DrawDebug();
|
||||||
ContextProxy.SetAsCurrent();
|
|
||||||
ContextProxy.Draw();
|
|
||||||
}
|
}
|
||||||
#endif // DRAW_EVENTS_ON_POST_ACTOR_TICK
|
#endif // ENGINE_COMPATIBILITY_WITH_WORLD_POST_ACTOR_TICK
|
||||||
|
|
||||||
#if WITH_EDITOR
|
#if WITH_EDITOR
|
||||||
FImGuiContextManager::FContextData& FImGuiContextManager::GetEditorContextData()
|
FImGuiContextManager::FContextData& FImGuiContextManager::GetEditorContextData()
|
||||||
|
@ -72,7 +72,7 @@ private:
|
|||||||
{
|
{
|
||||||
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, &SharedDrawEvent, &FontAtlas)
|
, ContextProxy(ContextName, ContextIndex, &SharedDrawEvent, &FontAtlas)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,7 +87,7 @@ private:
|
|||||||
struct FContextData
|
struct FContextData
|
||||||
{
|
{
|
||||||
FContextData(const FString& ContextName, int32 ContextIndex, FSimpleMulticastDelegate& SharedDrawEvent, ImFontAtlas& FontAtlas)
|
FContextData(const FString& ContextName, int32 ContextIndex, FSimpleMulticastDelegate& SharedDrawEvent, ImFontAtlas& FontAtlas)
|
||||||
: ContextProxy(ContextName, &SharedDrawEvent, &FontAtlas)
|
: ContextProxy(ContextName, ContextIndex, &SharedDrawEvent, &FontAtlas)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,7 +100,7 @@ private:
|
|||||||
|
|
||||||
void OnWorldTickStart(ELevelTick TickType, float DeltaSeconds);
|
void OnWorldTickStart(ELevelTick TickType, float DeltaSeconds);
|
||||||
|
|
||||||
#if DRAW_EVENTS_ON_POST_ACTOR_TICK
|
#if ENGINE_COMPATIBILITY_WITH_WORLD_POST_ACTOR_TICK
|
||||||
void OnWorldPostActorTick(UWorld* World, ELevelTick TickType, float DeltaSeconds);
|
void OnWorldPostActorTick(UWorld* World, ELevelTick TickType, float DeltaSeconds);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include "ImGuiContextProxy.h"
|
#include "ImGuiContextProxy.h"
|
||||||
|
|
||||||
|
#include "ImGuiDelegatesContainer.h"
|
||||||
#include "ImGuiImplementation.h"
|
#include "ImGuiImplementation.h"
|
||||||
#include "ImGuiInteroperability.h"
|
#include "ImGuiInteroperability.h"
|
||||||
|
|
||||||
@ -52,8 +53,9 @@ FImGuiContextProxy::FImGuiContextPtr::~FImGuiContextPtr()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FImGuiContextProxy::FImGuiContextProxy(const FString& InName, FSimpleMulticastDelegate* InSharedDrawEvent, ImFontAtlas* InFontAtlas)
|
FImGuiContextProxy::FImGuiContextProxy(const FString& InName, int32 InContextIndex, FSimpleMulticastDelegate* InSharedDrawEvent, ImFontAtlas* InFontAtlas)
|
||||||
: Name(InName)
|
: Name(InName)
|
||||||
|
, ContextIndex(InContextIndex)
|
||||||
, SharedDrawEvent(InSharedDrawEvent)
|
, SharedDrawEvent(InSharedDrawEvent)
|
||||||
, IniFilename(TCHAR_TO_ANSI(*GetIniFile(InName)))
|
, IniFilename(TCHAR_TO_ANSI(*GetIniFile(InName)))
|
||||||
{
|
{
|
||||||
@ -81,33 +83,34 @@ FImGuiContextProxy::FImGuiContextProxy(const FString& InName, FSimpleMulticastDe
|
|||||||
BeginFrame();
|
BeginFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FImGuiContextProxy::Draw()
|
void FImGuiContextProxy::DrawEarlyDebug()
|
||||||
{
|
{
|
||||||
if (bIsFrameStarted && !bIsDrawCalled)
|
if (bIsFrameStarted && !bIsDrawEarlyDebugCalled)
|
||||||
{
|
{
|
||||||
bIsDrawCalled = true;
|
bIsDrawEarlyDebugCalled = true;
|
||||||
|
|
||||||
SetAsCurrent();
|
SetAsCurrent();
|
||||||
|
|
||||||
// Broadcast draw event to allow listeners to draw their controls to this context.
|
// Delegates called in order specified in FImGuiDelegates.
|
||||||
#if DRAW_EVENTS_ORDER_WORLD_BEFORE_MULTI_CONTEXT
|
BroadcastMultiContextEarlyDebug();
|
||||||
if (DrawEvent.IsBound())
|
BroadcastWorldEarlyDebug();
|
||||||
{
|
|
||||||
DrawEvent.Broadcast();
|
|
||||||
}
|
}
|
||||||
#endif // DRAW_EVENTS_ORDER_WORLD_BEFORE_MULTI_CONTEXT
|
}
|
||||||
|
|
||||||
if (SharedDrawEvent && SharedDrawEvent->IsBound())
|
void FImGuiContextProxy::DrawDebug()
|
||||||
|
{
|
||||||
|
if (bIsFrameStarted && !bIsDrawDebugCalled)
|
||||||
{
|
{
|
||||||
SharedDrawEvent->Broadcast();
|
bIsDrawDebugCalled = true;
|
||||||
}
|
|
||||||
|
|
||||||
#if !DRAW_EVENTS_ORDER_WORLD_BEFORE_MULTI_CONTEXT
|
// Make sure that early debug is always called first to guarantee order specified in FImGuiDelegates.
|
||||||
if (DrawEvent.IsBound())
|
DrawEarlyDebug();
|
||||||
{
|
|
||||||
DrawEvent.Broadcast();
|
SetAsCurrent();
|
||||||
}
|
|
||||||
#endif // !DRAW_EVENTS_ORDER_WORLD_BEFORE_MULTI_CONTEXT
|
// Delegates called in order specified in FImGuiDelegates.
|
||||||
|
BroadcastWorldDebug();
|
||||||
|
BroadcastMultiContextDebug();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,7 +126,7 @@ void FImGuiContextProxy::Tick(float DeltaSeconds)
|
|||||||
if (bIsFrameStarted)
|
if (bIsFrameStarted)
|
||||||
{
|
{
|
||||||
// Make sure that draw events are called before the end of the frame.
|
// Make sure that draw events are called before the end of the frame.
|
||||||
Draw();
|
DrawDebug();
|
||||||
|
|
||||||
// Ending frame will produce render output that we capture and store for later use. This also puts context to
|
// 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.
|
// state in which it does not allow to draw controls, so we want to immediately start a new frame.
|
||||||
@ -156,7 +159,8 @@ void FImGuiContextProxy::BeginFrame(float DeltaTime)
|
|||||||
ImGui::NewFrame();
|
ImGui::NewFrame();
|
||||||
|
|
||||||
bIsFrameStarted = true;
|
bIsFrameStarted = true;
|
||||||
bIsDrawCalled = false;
|
bIsDrawEarlyDebugCalled = false;
|
||||||
|
bIsDrawDebugCalled = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,3 +196,55 @@ void FImGuiContextProxy::UpdateDrawData(ImDrawData* DrawData)
|
|||||||
DrawLists.Empty();
|
DrawLists.Empty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FImGuiContextProxy::BroadcastWorldEarlyDebug()
|
||||||
|
{
|
||||||
|
if (ContextIndex != Utilities::INVALID_CONTEXT_INDEX)
|
||||||
|
{
|
||||||
|
FSimpleMulticastDelegate& WorldEarlyDebugEvent = FImGuiDelegatesContainer::Get().OnWorldEarlyDebug(ContextIndex);
|
||||||
|
if (WorldEarlyDebugEvent.IsBound())
|
||||||
|
{
|
||||||
|
WorldEarlyDebugEvent.Broadcast();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FImGuiContextProxy::BroadcastMultiContextEarlyDebug()
|
||||||
|
{
|
||||||
|
FSimpleMulticastDelegate& MultiContextEarlyDebugEvent = FImGuiDelegatesContainer::Get().OnMultiContextEarlyDebug();
|
||||||
|
if (MultiContextEarlyDebugEvent.IsBound())
|
||||||
|
{
|
||||||
|
MultiContextEarlyDebugEvent.Broadcast();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FImGuiContextProxy::BroadcastWorldDebug()
|
||||||
|
{
|
||||||
|
if (DrawEvent.IsBound())
|
||||||
|
{
|
||||||
|
DrawEvent.Broadcast();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ContextIndex != Utilities::INVALID_CONTEXT_INDEX)
|
||||||
|
{
|
||||||
|
FSimpleMulticastDelegate& WorldDebugEvent = FImGuiDelegatesContainer::Get().OnWorldDebug(ContextIndex);
|
||||||
|
if (WorldDebugEvent.IsBound())
|
||||||
|
{
|
||||||
|
WorldDebugEvent.Broadcast();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FImGuiContextProxy::BroadcastMultiContextDebug()
|
||||||
|
{
|
||||||
|
if (SharedDrawEvent && SharedDrawEvent->IsBound())
|
||||||
|
{
|
||||||
|
SharedDrawEvent->Broadcast();
|
||||||
|
}
|
||||||
|
|
||||||
|
FSimpleMulticastDelegate& MultiContextDebugEvent = FImGuiDelegatesContainer::Get().OnMultiContextDebug();
|
||||||
|
if (MultiContextDebugEvent.IsBound())
|
||||||
|
{
|
||||||
|
MultiContextDebugEvent.Broadcast();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
#include "ImGuiDrawData.h"
|
#include "ImGuiDrawData.h"
|
||||||
|
|
||||||
|
#include "Utilities/WorldContextIndex.h"
|
||||||
|
|
||||||
#include <ICursor.h>
|
#include <ICursor.h>
|
||||||
|
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
@ -41,7 +43,7 @@ class FImGuiContextProxy
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
FImGuiContextProxy(const FString& Name, FSimpleMulticastDelegate* InSharedDrawEvent, ImFontAtlas* InFontAtlas);
|
FImGuiContextProxy(const FString& Name, int32 InContextIndex, FSimpleMulticastDelegate* InSharedDrawEvent, ImFontAtlas* InFontAtlas);
|
||||||
|
|
||||||
FImGuiContextProxy(const FImGuiContextProxy&) = delete;
|
FImGuiContextProxy(const FImGuiContextProxy&) = delete;
|
||||||
FImGuiContextProxy& operator=(const FImGuiContextProxy&) = delete;
|
FImGuiContextProxy& operator=(const FImGuiContextProxy&) = delete;
|
||||||
@ -82,9 +84,11 @@ public:
|
|||||||
// Delegate called right before ending the frame to allows listeners draw their controls.
|
// Delegate called right before ending the frame to allows listeners draw their controls.
|
||||||
FSimpleMulticastDelegate& OnDraw() { return DrawEvent; }
|
FSimpleMulticastDelegate& OnDraw() { return DrawEvent; }
|
||||||
|
|
||||||
// Call draw events to allow listeners draw their widgets. Only one call per frame is processed. If it is not
|
// Call early debug events to allow listeners draw their debug widgets.
|
||||||
// called manually before, then it will be called from the Tick function.
|
void DrawEarlyDebug();
|
||||||
void Draw();
|
|
||||||
|
// Call debug events to allow listeners draw their debug widgets.
|
||||||
|
void DrawDebug();
|
||||||
|
|
||||||
// Tick to advance context to the next frame. Only one call per frame will be processed.
|
// Tick to advance context to the next frame. Only one call per frame will be processed.
|
||||||
void Tick(float DeltaSeconds);
|
void Tick(float DeltaSeconds);
|
||||||
@ -96,6 +100,12 @@ private:
|
|||||||
|
|
||||||
void UpdateDrawData(ImDrawData* DrawData);
|
void UpdateDrawData(ImDrawData* DrawData);
|
||||||
|
|
||||||
|
void BroadcastWorldEarlyDebug();
|
||||||
|
void BroadcastMultiContextEarlyDebug();
|
||||||
|
|
||||||
|
void BroadcastWorldDebug();
|
||||||
|
void BroadcastMultiContextDebug();
|
||||||
|
|
||||||
FImGuiContextPtr Context;
|
FImGuiContextPtr Context;
|
||||||
|
|
||||||
FVector2D DisplaySize = FVector2D::ZeroVector;
|
FVector2D DisplaySize = FVector2D::ZeroVector;
|
||||||
@ -104,17 +114,20 @@ private:
|
|||||||
bool bHasActiveItem = false;
|
bool bHasActiveItem = false;
|
||||||
|
|
||||||
bool bIsFrameStarted = false;
|
bool bIsFrameStarted = false;
|
||||||
bool bIsDrawCalled = false;
|
bool bIsDrawEarlyDebugCalled = false;
|
||||||
|
bool bIsDrawDebugCalled = false;
|
||||||
uint32 LastFrameNumber = 0;
|
|
||||||
FString Name;
|
|
||||||
FSimpleMulticastDelegate DrawEvent;
|
|
||||||
FSimpleMulticastDelegate* SharedDrawEvent = nullptr;
|
|
||||||
|
|
||||||
const FImGuiInputState* InputState = nullptr;
|
const FImGuiInputState* InputState = nullptr;
|
||||||
|
|
||||||
TArray<FImGuiDrawList> DrawLists;
|
TArray<FImGuiDrawList> DrawLists;
|
||||||
|
|
||||||
|
FString Name;
|
||||||
|
int32 ContextIndex = Utilities::INVALID_CONTEXT_INDEX;
|
||||||
|
|
||||||
|
uint32 LastFrameNumber = 0;
|
||||||
|
|
||||||
|
FSimpleMulticastDelegate DrawEvent;
|
||||||
|
FSimpleMulticastDelegate* SharedDrawEvent = nullptr;
|
||||||
|
|
||||||
std::string IniFilename;
|
std::string IniFilename;
|
||||||
};
|
};
|
||||||
|
37
Source/ImGui/Private/ImGuiDelegates.cpp
Normal file
37
Source/ImGui/Private/ImGuiDelegates.cpp
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
// Distributed under the MIT License (MIT) (see accompanying LICENSE file)
|
||||||
|
|
||||||
|
#include "ImGuiPrivatePCH.h"
|
||||||
|
|
||||||
|
#include "ImGuiDelegates.h"
|
||||||
|
#include "ImGuiDelegatesContainer.h"
|
||||||
|
|
||||||
|
|
||||||
|
FSimpleMulticastDelegate& FImGuiDelegates::OnWorldEarlyDebug()
|
||||||
|
{
|
||||||
|
return OnWorldEarlyDebug(GWorld);
|
||||||
|
}
|
||||||
|
|
||||||
|
FSimpleMulticastDelegate& FImGuiDelegates::OnWorldEarlyDebug(UWorld* World)
|
||||||
|
{
|
||||||
|
return FImGuiDelegatesContainer::Get().OnWorldEarlyDebug(World);
|
||||||
|
}
|
||||||
|
|
||||||
|
FSimpleMulticastDelegate& FImGuiDelegates::OnMultiContextEarlyDebug()
|
||||||
|
{
|
||||||
|
return FImGuiDelegatesContainer::Get().OnMultiContextEarlyDebug();
|
||||||
|
}
|
||||||
|
|
||||||
|
FSimpleMulticastDelegate& FImGuiDelegates::OnWorldDebug()
|
||||||
|
{
|
||||||
|
return OnWorldDebug(GWorld);
|
||||||
|
}
|
||||||
|
|
||||||
|
FSimpleMulticastDelegate& FImGuiDelegates::OnWorldDebug(UWorld* World)
|
||||||
|
{
|
||||||
|
return FImGuiDelegatesContainer::Get().OnWorldDebug(World);
|
||||||
|
}
|
||||||
|
|
||||||
|
FSimpleMulticastDelegate& FImGuiDelegates::OnMultiContextDebug()
|
||||||
|
{
|
||||||
|
return FImGuiDelegatesContainer::Get().OnMultiContextDebug();
|
||||||
|
}
|
39
Source/ImGui/Private/ImGuiDelegatesContainer.cpp
Normal file
39
Source/ImGui/Private/ImGuiDelegatesContainer.cpp
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
// Distributed under the MIT License (MIT) (see accompanying LICENSE file)
|
||||||
|
|
||||||
|
#include "ImGuiPrivatePCH.h"
|
||||||
|
|
||||||
|
#include "ImGuiDelegatesContainer.h"
|
||||||
|
|
||||||
|
#include "Utilities/WorldContextIndex.h"
|
||||||
|
|
||||||
|
|
||||||
|
FImGuiDelegatesContainer FImGuiDelegatesContainer::DefaultInstance;
|
||||||
|
|
||||||
|
FImGuiDelegatesContainer* FImGuiDelegatesContainer::InstancePtr = &FImGuiDelegatesContainer::DefaultInstance;
|
||||||
|
|
||||||
|
void FImGuiDelegatesContainer::MoveContainer(FImGuiDelegatesContainer& Dst)
|
||||||
|
{
|
||||||
|
// Only move data if pointer points to default instance, otherwise our data has already been moved and we only
|
||||||
|
// keep pointer to a more recent version.
|
||||||
|
if (InstancePtr == &DefaultInstance)
|
||||||
|
{
|
||||||
|
Dst = MoveTemp(DefaultInstance);
|
||||||
|
DefaultInstance.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update pointer to the most recent version.
|
||||||
|
InstancePtr = &Dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 FImGuiDelegatesContainer::GetContextIndex(UWorld* World)
|
||||||
|
{
|
||||||
|
return Utilities::GetWorldContextIndex(*World);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FImGuiDelegatesContainer::Clear()
|
||||||
|
{
|
||||||
|
WorldEarlyDebugDelegates.Empty();
|
||||||
|
WorldDebugDelegates.Empty();
|
||||||
|
MultiContextEarlyDebugDelegate.Clear();
|
||||||
|
MultiContextDebugDelegate.Clear();
|
||||||
|
}
|
53
Source/ImGui/Private/ImGuiDelegatesContainer.h
Normal file
53
Source/ImGui/Private/ImGuiDelegatesContainer.h
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
// Distributed under the MIT License (MIT) (see accompanying LICENSE file)
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Containers/Map.h>
|
||||||
|
#include <Delegates/Delegate.h>
|
||||||
|
|
||||||
|
|
||||||
|
struct FImGuiDelegatesContainer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Get the current instance (can change during hot-reloading).
|
||||||
|
static FImGuiDelegatesContainer& Get() { return *InstancePtr; }
|
||||||
|
|
||||||
|
// If this is an active container move its data to a destination and redirect all future calls to that instance.
|
||||||
|
static void MoveContainer(FImGuiDelegatesContainer& Dst);
|
||||||
|
|
||||||
|
// Get delegate to ImGui world early debug event from known world instance.
|
||||||
|
FSimpleMulticastDelegate& OnWorldEarlyDebug(UWorld* World) { return OnWorldEarlyDebug(GetContextIndex(World)); }
|
||||||
|
|
||||||
|
// Get delegate to ImGui world early debug event from known context index.
|
||||||
|
FSimpleMulticastDelegate& OnWorldEarlyDebug(int32 ContextIndex) { return WorldEarlyDebugDelegates.FindOrAdd(ContextIndex); }
|
||||||
|
|
||||||
|
// Get delegate to ImGui multi-context early debug event.
|
||||||
|
FSimpleMulticastDelegate& OnMultiContextEarlyDebug() { return MultiContextEarlyDebugDelegate; }
|
||||||
|
|
||||||
|
// Get delegate to ImGui world debug event from known world instance.
|
||||||
|
FSimpleMulticastDelegate& OnWorldDebug(UWorld* World) { return OnWorldDebug(GetContextIndex(World)); }
|
||||||
|
|
||||||
|
// Get delegate to ImGui world debug event from known context index.
|
||||||
|
FSimpleMulticastDelegate& OnWorldDebug(int32 ContextIndex) { return WorldDebugDelegates.FindOrAdd(ContextIndex); }
|
||||||
|
|
||||||
|
// Get delegate to ImGui multi-context debug event.
|
||||||
|
FSimpleMulticastDelegate& OnMultiContextDebug() { return MultiContextDebugDelegate; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
int32 GetContextIndex(UWorld* World);
|
||||||
|
|
||||||
|
void Clear();
|
||||||
|
|
||||||
|
TMap<int32, FSimpleMulticastDelegate> WorldEarlyDebugDelegates;
|
||||||
|
TMap<int32, FSimpleMulticastDelegate> WorldDebugDelegates;
|
||||||
|
FSimpleMulticastDelegate MultiContextEarlyDebugDelegate;
|
||||||
|
FSimpleMulticastDelegate MultiContextDebugDelegate;
|
||||||
|
|
||||||
|
// Default container instance.
|
||||||
|
static FImGuiDelegatesContainer DefaultInstance;
|
||||||
|
|
||||||
|
// Pointer to the container instance that can be overwritten during hot-reloading.
|
||||||
|
static FImGuiDelegatesContainer* InstancePtr;
|
||||||
|
};
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include "ImGuiModuleManager.h"
|
#include "ImGuiModuleManager.h"
|
||||||
|
|
||||||
|
#include "ImGuiDelegatesContainer.h"
|
||||||
#include "ImGuiTextureHandle.h"
|
#include "ImGuiTextureHandle.h"
|
||||||
#include "TextureManager.h"
|
#include "TextureManager.h"
|
||||||
#include "Utilities/WorldContext.h"
|
#include "Utilities/WorldContext.h"
|
||||||
@ -16,6 +17,8 @@
|
|||||||
|
|
||||||
#include <IPluginManager.h>
|
#include <IPluginManager.h>
|
||||||
|
|
||||||
|
#define IMGUI_REDIRECT_OBSOLETE_DELEGATES 1
|
||||||
|
|
||||||
|
|
||||||
#define LOCTEXT_NAMESPACE "FImGuiModule"
|
#define LOCTEXT_NAMESPACE "FImGuiModule"
|
||||||
|
|
||||||
@ -38,18 +41,29 @@ static FImGuiModuleManager* ImGuiModuleManager = nullptr;
|
|||||||
static FImGuiEditor* ImGuiEditor = nullptr;
|
static FImGuiEditor* ImGuiEditor = nullptr;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if IMGUI_WITH_OBSOLETE_DELEGATES
|
||||||
|
|
||||||
#if WITH_EDITOR
|
#if WITH_EDITOR
|
||||||
FImGuiDelegateHandle FImGuiModule::AddEditorImGuiDelegate(const FImGuiDelegate& Delegate)
|
FImGuiDelegateHandle FImGuiModule::AddEditorImGuiDelegate(const FImGuiDelegate& Delegate)
|
||||||
{
|
{
|
||||||
|
#if IMGUI_REDIRECT_OBSOLETE_DELEGATES
|
||||||
|
return { FImGuiDelegatesContainer::Get().OnWorldDebug(Utilities::EDITOR_CONTEXT_INDEX).Add(Delegate),
|
||||||
|
EDelegateCategory::Default, Utilities::EDITOR_CONTEXT_INDEX };
|
||||||
|
#else
|
||||||
checkf(ImGuiModuleManager, TEXT("Null pointer to internal module implementation. Is module available?"));
|
checkf(ImGuiModuleManager, TEXT("Null pointer to internal module implementation. Is module available?"));
|
||||||
|
|
||||||
return { ImGuiModuleManager->GetContextManager().GetEditorContextProxy().OnDraw().Add(Delegate),
|
return { ImGuiModuleManager->GetContextManager().GetEditorContextProxy().OnDraw().Add(Delegate),
|
||||||
EDelegateCategory::Default, Utilities::EDITOR_CONTEXT_INDEX };
|
EDelegateCategory::Default, Utilities::EDITOR_CONTEXT_INDEX };
|
||||||
|
#endif // IMGUI_REDIRECT_OBSOLETE_DELEGATES
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
FImGuiDelegateHandle FImGuiModule::AddWorldImGuiDelegate(const FImGuiDelegate& Delegate)
|
FImGuiDelegateHandle FImGuiModule::AddWorldImGuiDelegate(const FImGuiDelegate& Delegate)
|
||||||
{
|
{
|
||||||
|
#if IMGUI_REDIRECT_OBSOLETE_DELEGATES
|
||||||
|
const int32 ContextIndex = Utilities::GetWorldContextIndex((UWorld*)GWorld);
|
||||||
|
return { FImGuiDelegatesContainer::Get().OnWorldDebug(ContextIndex).Add(Delegate), EDelegateCategory::Default, ContextIndex };
|
||||||
|
#else
|
||||||
checkf(ImGuiModuleManager, TEXT("Null pointer to internal module implementation. Is module available?"));
|
checkf(ImGuiModuleManager, TEXT("Null pointer to internal module implementation. Is module available?"));
|
||||||
|
|
||||||
#if WITH_EDITOR
|
#if WITH_EDITOR
|
||||||
@ -71,17 +85,32 @@ FImGuiDelegateHandle FImGuiModule::AddWorldImGuiDelegate(const FImGuiDelegate& D
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
return{ Proxy.OnDraw().Add(Delegate), EDelegateCategory::Default, Index };
|
return{ Proxy.OnDraw().Add(Delegate), EDelegateCategory::Default, Index };
|
||||||
|
#endif // IMGUI_REDIRECT_OBSOLETE_DELEGATES
|
||||||
}
|
}
|
||||||
|
|
||||||
FImGuiDelegateHandle FImGuiModule::AddMultiContextImGuiDelegate(const FImGuiDelegate& Delegate)
|
FImGuiDelegateHandle FImGuiModule::AddMultiContextImGuiDelegate(const FImGuiDelegate& Delegate)
|
||||||
{
|
{
|
||||||
|
#if IMGUI_REDIRECT_OBSOLETE_DELEGATES
|
||||||
|
return { FImGuiDelegatesContainer::Get().OnMultiContextDebug().Add(Delegate), EDelegateCategory::MultiContext };
|
||||||
|
#else
|
||||||
checkf(ImGuiModuleManager, TEXT("Null pointer to internal module implementation. Is module available?"));
|
checkf(ImGuiModuleManager, TEXT("Null pointer to internal module implementation. Is module available?"));
|
||||||
|
|
||||||
return { ImGuiModuleManager->GetContextManager().OnDrawMultiContext().Add(Delegate), EDelegateCategory::MultiContext };
|
return { ImGuiModuleManager->GetContextManager().OnDrawMultiContext().Add(Delegate), EDelegateCategory::MultiContext };
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void FImGuiModule::RemoveImGuiDelegate(const FImGuiDelegateHandle& Handle)
|
void FImGuiModule::RemoveImGuiDelegate(const FImGuiDelegateHandle& Handle)
|
||||||
{
|
{
|
||||||
|
#if IMGUI_REDIRECT_OBSOLETE_DELEGATES
|
||||||
|
if (Handle.Category == EDelegateCategory::MultiContext)
|
||||||
|
{
|
||||||
|
FImGuiDelegatesContainer::Get().OnMultiContextDebug().Remove(Handle.Handle);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FImGuiDelegatesContainer::Get().OnWorldDebug(Handle.Index).Remove(Handle.Handle);
|
||||||
|
}
|
||||||
|
#else
|
||||||
if (ImGuiModuleManager)
|
if (ImGuiModuleManager)
|
||||||
{
|
{
|
||||||
if (Handle.Category == EDelegateCategory::MultiContext)
|
if (Handle.Category == EDelegateCategory::MultiContext)
|
||||||
@ -93,8 +122,11 @@ void FImGuiModule::RemoveImGuiDelegate(const FImGuiDelegateHandle& Handle)
|
|||||||
Proxy->OnDraw().Remove(Handle.Handle);
|
Proxy->OnDraw().Remove(Handle.Handle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // IMGUI_WITH_OBSOLETE_DELEGATES
|
||||||
|
|
||||||
FImGuiTextureHandle FImGuiModule::FindTextureHandle(const FName& Name)
|
FImGuiTextureHandle FImGuiModule::FindTextureHandle(const FName& Name)
|
||||||
{
|
{
|
||||||
const TextureIndex Index = ImGuiModuleManager->GetTextureManager().FindTextureIndex(Name);
|
const TextureIndex Index = ImGuiModuleManager->GetTextureManager().FindTextureIndex(Name);
|
||||||
@ -154,6 +186,10 @@ void FImGuiModule::ShutdownModule()
|
|||||||
// deleted. This can cause troubles after hot-reload when code in other modules calls ImGui interface functions
|
// deleted. This can cause troubles after hot-reload when code in other modules calls ImGui interface functions
|
||||||
// which are statically bound to the obsolete module. To keep ImGui code functional we can redirect context handle
|
// which are statically bound to the obsolete module. To keep ImGui code functional we can redirect context handle
|
||||||
// to point to the new module.
|
// to point to the new module.
|
||||||
|
|
||||||
|
// When shutting down during hot-reloading, we might want to rewire handles used in statically bound functions
|
||||||
|
// or move data to a new module.
|
||||||
|
|
||||||
FModuleManager::Get().OnModulesChanged().AddLambda([this] (FName Name, EModuleChangeReason Reason)
|
FModuleManager::Get().OnModulesChanged().AddLambda([this] (FName Name, EModuleChangeReason Reason)
|
||||||
{
|
{
|
||||||
if (Reason == EModuleChangeReason::ModuleLoaded && Name == "ImGui")
|
if (Reason == EModuleChangeReason::ModuleLoaded && Name == "ImGui")
|
||||||
@ -161,8 +197,11 @@ void FImGuiModule::ShutdownModule()
|
|||||||
FImGuiModule& LoadedModule = FImGuiModule::Get();
|
FImGuiModule& LoadedModule = FImGuiModule::Get();
|
||||||
if (&LoadedModule != this)
|
if (&LoadedModule != this)
|
||||||
{
|
{
|
||||||
|
// Statically bound functions will be still made to the obsolete module so we need to
|
||||||
ImGuiImplementation::SetImGuiContextHandle(LoadedModule.GetImGuiContextHandle());
|
ImGuiImplementation::SetImGuiContextHandle(LoadedModule.GetImGuiContextHandle());
|
||||||
|
|
||||||
|
FImGuiDelegatesContainer::MoveContainer(LoadedModule.GetDelegatesContainer());
|
||||||
|
|
||||||
if (bMoveProperties)
|
if (bMoveProperties)
|
||||||
{
|
{
|
||||||
bMoveProperties = false;
|
bMoveProperties = false;
|
||||||
@ -184,6 +223,11 @@ ImGuiContext** FImGuiModule::GetImGuiContextHandle()
|
|||||||
{
|
{
|
||||||
return ImGuiImplementation::GetImGuiContextHandle();
|
return ImGuiImplementation::GetImGuiContextHandle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FImGuiDelegatesContainer& FImGuiModule::GetDelegatesContainer()
|
||||||
|
{
|
||||||
|
return FImGuiDelegatesContainer::Get();
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
FImGuiModuleProperties& FImGuiModule::GetProperties()
|
FImGuiModuleProperties& FImGuiModule::GetProperties()
|
||||||
|
@ -56,6 +56,11 @@ namespace Utilities
|
|||||||
return (World.WorldType == EWorldType::Editor) ? EDITOR_CONTEXT_INDEX : GetWorldContextIndex(World.GetGameInstance());
|
return (World.WorldType == EWorldType::Editor) ? EDITOR_CONTEXT_INDEX : GetWorldContextIndex(World.GetGameInstance());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FORCEINLINE int32 GetWorldContextIndex(const UWorld* World)
|
||||||
|
{
|
||||||
|
return World ? GetWorldContextIndex(*World) : INVALID_CONTEXT_INDEX;
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
@ -23,3 +23,8 @@
|
|||||||
// that renames FStringClassReference to FSoftClassPath, so it is still possible tu use the old type name in code.
|
// that renames FStringClassReference to FSoftClassPath, so it is still possible tu use the old type name in code.
|
||||||
// The old header forwards to the new one but if used it outputs a warning, so we want to avoid it.
|
// The old header forwards to the new one but if used it outputs a warning, so we want to avoid it.
|
||||||
#define ENGINE_COMPATIBILITY_LEGACY_STRING_CLASS_REF BELOW_ENGINE_VERSION(4, 18)
|
#define ENGINE_COMPATIBILITY_LEGACY_STRING_CLASS_REF BELOW_ENGINE_VERSION(4, 18)
|
||||||
|
|
||||||
|
// Starting from version 4.18 engine has a world post actor tick event which if available, provides a good opportunity
|
||||||
|
// to call debug delegates after world actors are already updated.
|
||||||
|
#define ENGINE_COMPATIBILITY_WITH_WORLD_POST_ACTOR_TICK FROM_ENGINE_VERSION(4, 18)
|
||||||
|
|
||||||
|
@ -5,6 +5,64 @@
|
|||||||
#include <Core.h>
|
#include <Core.h>
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delegates to ImGui debug events. World delegates are called once per frame during world updates and have invocation
|
||||||
|
* lists cleared after their worlds become invalid. Multi-context delegates are called once for every updated world.
|
||||||
|
* Early debug delegates are called during world tick start and debug delegates are called during world post actor tick
|
||||||
|
* or in engine versions below 4.18 during world tick start.
|
||||||
|
*
|
||||||
|
* Order of events is defined in a way that multi-context delegates can be used to draw headers and/or footers:
|
||||||
|
* multi-context early debug, world early debug, world debug, multi-context debug.
|
||||||
|
*/
|
||||||
|
class IMGUI_API FImGuiDelegates
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a delegate to ImGui world early debug event for current world (GWorld).
|
||||||
|
* @returns Simple multicast delegate to debug events called once per frame to debug current world
|
||||||
|
*/
|
||||||
|
static FSimpleMulticastDelegate& OnWorldEarlyDebug();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a delegate to ImGui world early debug event for given world.
|
||||||
|
* @param World - World for which we need a delegate
|
||||||
|
* @returns Simple multicast delegate to debug events called once per frame to debug given world
|
||||||
|
*/
|
||||||
|
static FSimpleMulticastDelegate& OnWorldEarlyDebug(UWorld* World);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a delegate to ImGui multi-context early debug event.
|
||||||
|
* @returns Simple multicast delegate to debug events called once per frame for every world to debug
|
||||||
|
*/
|
||||||
|
static FSimpleMulticastDelegate& OnMultiContextEarlyDebug();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a delegate to ImGui world debug event for current world (GWorld).
|
||||||
|
* @returns Simple multicast delegate to debug events called once per frame to debug current world
|
||||||
|
*/
|
||||||
|
static FSimpleMulticastDelegate& OnWorldDebug();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a delegate to ImGui world debug event for given world.
|
||||||
|
* @param World - World for which we need a delegate
|
||||||
|
* @returns Simple multicast delegate to debug events called once per frame to debug given world
|
||||||
|
*/
|
||||||
|
static FSimpleMulticastDelegate& OnWorldDebug(UWorld* World);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a delegate to ImGui multi-context debug event.
|
||||||
|
* @returns Simple multicast delegate to debug events called once per frame for every world to debug
|
||||||
|
*/
|
||||||
|
static FSimpleMulticastDelegate& OnMultiContextDebug();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/** Enable to support legacy ImGui delegates API. */
|
||||||
|
#define IMGUI_WITH_OBSOLETE_DELEGATES 1
|
||||||
|
|
||||||
|
#if IMGUI_WITH_OBSOLETE_DELEGATES
|
||||||
|
|
||||||
/** Delegate that allows to subscribe for ImGui events. */
|
/** Delegate that allows to subscribe for ImGui events. */
|
||||||
typedef FSimpleMulticastDelegate::FDelegate FImGuiDelegate;
|
typedef FSimpleMulticastDelegate::FDelegate FImGuiDelegate;
|
||||||
|
|
||||||
@ -53,3 +111,5 @@ private:
|
|||||||
|
|
||||||
friend class FImGuiModule;
|
friend class FImGuiModule;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif // IMGUI_WITH_OBSOLETE_DELEGATES
|
||||||
|
@ -34,6 +34,8 @@ public:
|
|||||||
return FModuleManager::Get().IsModuleLoaded("ImGui");
|
return FModuleManager::Get().IsModuleLoaded("ImGui");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if IMGUI_WITH_OBSOLETE_DELEGATES
|
||||||
|
|
||||||
#if WITH_EDITOR
|
#if WITH_EDITOR
|
||||||
/**
|
/**
|
||||||
* Add a delegate called at the end of editor debug frame to draw debug controls in its ImGui context, creating
|
* Add a delegate called at the end of editor debug frame to draw debug controls in its ImGui context, creating
|
||||||
@ -71,6 +73,8 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual void RemoveImGuiDelegate(const FImGuiDelegateHandle& Handle);
|
virtual void RemoveImGuiDelegate(const FImGuiDelegateHandle& Handle);
|
||||||
|
|
||||||
|
#endif // #if IMGUI_WITH_OBSOLETE_DELEGATES
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If it exists, get a handle to the texture with given resource name.
|
* If it exists, get a handle to the texture with given resource name.
|
||||||
*
|
*
|
||||||
@ -165,5 +169,6 @@ public:
|
|||||||
#if WITH_EDITOR
|
#if WITH_EDITOR
|
||||||
virtual void SetProperties(const FImGuiModuleProperties& Properties);
|
virtual void SetProperties(const FImGuiModuleProperties& Properties);
|
||||||
virtual struct ImGuiContext** GetImGuiContextHandle();
|
virtual struct ImGuiContext** GetImGuiContextHandle();
|
||||||
|
virtual struct FImGuiDelegatesContainer& GetDelegatesContainer();
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user