Support Unreal 5.5. Fix Multi PIE not working when running under one process.

This commit is contained in:
Arnaud Jamin
2024-12-31 01:11:11 -05:00
parent 3539881135
commit 19d88558cb
21 changed files with 339 additions and 77 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"FileVersion": 3, "FileVersion": 3,
"EngineAssociation": "5.3", "EngineAssociation": "5.5",
"Category": "", "Category": "",
"Description": "", "Description": "",
"Modules": [ "Modules": [
@@ -3,13 +3,14 @@
#include "CogCommonDebugFilteredActorInterface.h" #include "CogCommonDebugFilteredActorInterface.h"
#include "CogDebugDrawHelper.h" #include "CogDebugDrawHelper.h"
#include "CogDebugReplicator.h" #include "CogDebugReplicator.h"
#include "imgui.h"
#include "Engine/World.h"
#include "Engine/Engine.h" #include "Engine/Engine.h"
#include "Engine/World.h"
#include "imgui.h"
#include "Kismet/KismetMathLibrary.h" #include "Kismet/KismetMathLibrary.h"
#include "Misc/EngineVersionComparison.h"
//-------------------------------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------------------------------
TWeakObjectPtr<AActor> FCogDebug::Selection; TWeakObjectPtr<AActor> FCogDebug::Selection[] = {};
FCogDebugSettings FCogDebug::Settings = FCogDebugSettings(); FCogDebugSettings FCogDebug::Settings = FCogDebugSettings();
//-------------------------------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------------------------------
@@ -32,7 +33,7 @@ bool FCogDebug::IsDebugActiveForObject(const UObject* WorldContextObject)
return true; return true;
} }
const bool Result = IsDebugActiveForObject_Internal(WorldContextObject, Selection.Get(), Settings.bIsFilteringBySelection); const bool Result = IsDebugActiveForObject_Internal(WorldContextObject, Selection[GetPieSessionId()].Get(), Settings.bIsFilteringBySelection);
return Result; return Result;
} }
@@ -83,20 +84,32 @@ bool FCogDebug::IsDebugActiveForObject_Internal(const UObject* WorldContextObjec
Outer = NewOuter; Outer = NewOuter;
} }
return true;
} }
//-------------------------------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------------------------------
AActor* FCogDebug::GetSelection() AActor* FCogDebug::GetSelection()
{ {
return Selection.Get(); return Selection[GetPieSessionId()].Get();
}
//--------------------------------------------------------------------------------------------------------------------------
int32 FCogDebug::GetPieSessionId()
{
#if UE_EDITOR
#if UE_VERSION_OLDER_THAN(5, 5, 0)
return GPlayInEditorID;
#else
return UE::GetPlayInEditorID();
#endif
#else
return 0;
#endif
} }
//-------------------------------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------------------------------
void FCogDebug::SetSelection(const UWorld* World, AActor* Value) void FCogDebug::SetSelection(const UWorld* World, AActor* Value)
{ {
Selection = Value; Selection[GetPieSessionId()] = Value;
if (World != nullptr && World->GetNetMode() == NM_Client) if (World != nullptr && World->GetNetMode() == NM_Client)
{ {
@@ -2,9 +2,10 @@
#include "CogDebug.h" #include "CogDebug.h"
#include "Components/LineBatchComponent.h" #include "Components/LineBatchComponent.h"
#include "Engine/Engine.h"
#include "DrawDebugHelpers.h"
#include "Components/BoxComponent.h" #include "Components/BoxComponent.h"
#include "DrawDebugHelpers.h"
#include "Engine/Engine.h"
#include "Engine/OverlapResult.h"
namespace namespace
{ {
@@ -130,10 +130,6 @@ FLogCategoryBase* FCogDebugLog::FindLogCategory(const FName CategoryName)
{ {
return LogCategoryInfo->LogCategory; return LogCategoryInfo->LogCategory;
} }
else
{
return nullptr;
}
return nullptr; return nullptr;
} }
@@ -427,7 +427,11 @@ public:
private: private:
static int32 GetPieSessionId();
static constexpr uint32 MaxPie = 16;
static bool IsDebugActiveForObject_Internal(const UObject* WorldContextObject, const AActor* InSelection, bool InIsFilteringBySelection); static bool IsDebugActiveForObject_Internal(const UObject* WorldContextObject, const AActor* InSelection, bool InIsFilteringBySelection);
static TWeakObjectPtr<AActor> Selection; static TWeakObjectPtr<AActor> Selection[MaxPie];
}; };
@@ -5,6 +5,7 @@
#include "Components/PrimitiveComponent.h" #include "Components/PrimitiveComponent.h"
#include "Components/SceneComponent.h" #include "Components/SceneComponent.h"
#include "Engine/World.h" #include "Engine/World.h"
#include "Engine/OverlapResult.h"
//-------------------------------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------------------------------
ACogEngineCollisionTester::ACogEngineCollisionTester(const FObjectInitializer& ObjectInitializer) ACogEngineCollisionTester::ACogEngineCollisionTester(const FObjectInitializer& ObjectInitializer)
@@ -5,6 +5,7 @@
#include "CogEngineWindow_ImGui.h" #include "CogEngineWindow_ImGui.h"
#include "CogImguiHelper.h" #include "CogImguiHelper.h"
#include "CogImguiInputHelper.h" #include "CogImguiInputHelper.h"
#include "CogWindowConsoleCommandManager.h"
#include "CogWindowManager.h" #include "CogWindowManager.h"
#include "CogWindowWidgets.h" #include "CogWindowWidgets.h"
#include "Components/PrimitiveComponent.h" #include "Components/PrimitiveComponent.h"
@@ -27,11 +28,14 @@ void FCogEngineWindow_Selection::Initialize()
Config = GetConfig<UCogEngineConfig_Selection>(); Config = GetConfig<UCogEngineConfig_Selection>();
ConsoleCommands.Add(IConsoleManager::Get().RegisterConsoleCommand( FCogWindowConsoleCommandManager::RegisterWorldConsoleCommand(
*ToggleSelectionModeCommand, *ToggleSelectionModeCommand,
TEXT("Toggle the actor selection mode"), TEXT("Toggle the actor selection mode"),
FConsoleCommandWithArgsDelegate::CreateLambda([this](const TArray<FString>& Args) { ToggleSelectionMode(); }), GetWorld(),
ECVF_Cheat)); FCogWindowConsoleCommandDelegate::CreateLambda([this](const TArray<FString>& InArgs, UWorld* InWorld)
{
ToggleSelectionMode();
}));
TryReapplySelection(); TryReapplySelection();
} }
@@ -50,10 +54,6 @@ void FCogEngineWindow_Selection::RenderHelp()
//-------------------------------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------------------------------
void FCogEngineWindow_Selection::Shutdown() void FCogEngineWindow_Selection::Shutdown()
{ {
for (IConsoleObject* ConsoleCommand : ConsoleCommands)
{
IConsoleManager::Get().UnregisterConsoleObject(ConsoleCommand);
}
} }
//-------------------------------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------------------------------
@@ -83,8 +83,6 @@ protected:
ETraceTypeQuery TraceType = TraceTypeQuery1; ETraceTypeQuery TraceType = TraceTypeQuery1;
TArray<IConsoleObject*> ConsoleCommands;
TObjectPtr<UCogEngineConfig_Selection> Config; TObjectPtr<UCogEngineConfig_Selection> Config;
ImGuiTextFilter Filter; ImGuiTextFilter Filter;
@@ -17,12 +17,41 @@
#include "imgui.h" #include "imgui.h"
#include "imgui_internal.h" #include "imgui_internal.h"
#include "implot.h" #include "implot.h"
#include "Misc/EngineVersionComparison.h"
#include "TextureResource.h" #include "TextureResource.h"
#include "Widgets/SViewport.h" #include "Widgets/SViewport.h"
#include "Widgets/SWindow.h" #include "Widgets/SWindow.h"
static UPlayerInput* GetPlayerInput(const UWorld* World); static UPlayerInput* GetPlayerInput(const UWorld* World);
FCogImGuiContextScope::
FCogImGuiContextScope(FCogImguiContext& CogImguiContext)
{
PrevContext = ImGui::GetCurrentContext();
PrevPlotContext = ImPlot::GetCurrentContext();
ImGui::SetCurrentContext(CogImguiContext.ImGuiContext);
ImPlot::SetCurrentContext(CogImguiContext.PlotContext);
}
FCogImGuiContextScope::
FCogImGuiContextScope(ImGuiContext* GuiCtx, ImPlotContext* PlotCtx)
{
PrevContext = ImGui::GetCurrentContext();
PrevPlotContext = ImPlot::GetCurrentContext();
ImGui::SetCurrentContext(GuiCtx);
ImPlot::SetCurrentContext(PlotCtx);
}
FCogImGuiContextScope::
~FCogImGuiContextScope()
{
ImGui::SetCurrentContext(PrevContext);
ImPlot::SetCurrentContext(PrevPlotContext);
}
//-------------------------------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------------------------------
void FCogImguiContext::Initialize() void FCogImguiContext::Initialize()
{ {
@@ -45,7 +74,9 @@ void FCogImguiContext::Initialize()
ImGuiContext = ImGui::CreateContext(); ImGuiContext = ImGui::CreateContext();
PlotContext = ImPlot::CreateContext(); PlotContext = ImPlot::CreateContext();
ImGui::SetCurrentContext(ImGuiContext);
ImPlot::SetImGuiContext(ImGuiContext); ImPlot::SetImGuiContext(ImGuiContext);
ImPlot::SetCurrentContext(PlotContext);
ImGuiIO& IO = ImGui::GetIO(); ImGuiIO& IO = ImGui::GetIO();
IO.UserData = this; IO.UserData = this;
@@ -105,6 +136,13 @@ void FCogImguiContext::Initialize()
//-------------------------------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------------------------------
void FCogImguiContext::Shutdown() void FCogImguiContext::Shutdown()
{ {
if (FSlateApplication::IsInitialized() == false)
{
return;
}
FCogImGuiContextScope ImGuiContextScope(ImGuiContext, PlotContext);
ImGuiViewport* MainViewport = ImGui::GetMainViewport(); ImGuiViewport* MainViewport = ImGui::GetMainViewport();
if (const FCogImGuiViewportData* ViewportData = static_cast<FCogImGuiViewportData*>(MainViewport->PlatformUserData)) if (const FCogImGuiViewportData* ViewportData = static_cast<FCogImGuiViewportData*>(MainViewport->PlatformUserData))
{ {
@@ -122,6 +160,7 @@ void FCogImguiContext::Shutdown()
} }
GameViewport->RemoveViewportWidgetContent(MainWidget.ToSharedRef()); GameViewport->RemoveViewportWidgetContent(MainWidget.ToSharedRef());
GameViewport->RemoveViewportWidgetContent(InputCatcherWidget.ToSharedRef());
if (PlotContext) if (PlotContext)
{ {
@@ -139,6 +178,8 @@ void FCogImguiContext::Shutdown()
//-------------------------------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------------------------------
void FCogImguiContext::OnDisplayMetricsChanged(const FDisplayMetrics& DisplayMetrics) const void FCogImguiContext::OnDisplayMetricsChanged(const FDisplayMetrics& DisplayMetrics) const
{ {
FCogImGuiContextScope ImGuiContextScope(ImGuiContext, PlotContext);
ImGuiPlatformIO& PlatformIO = ImGui::GetPlatformIO(); ImGuiPlatformIO& PlatformIO = ImGui::GetPlatformIO();
PlatformIO.Monitors.resize(0); PlatformIO.Monitors.resize(0);
@@ -165,6 +206,8 @@ void FCogImguiContext::OnDisplayMetricsChanged(const FDisplayMetrics& DisplayMet
//-------------------------------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------------------------------
bool FCogImguiContext::BeginFrame(float InDeltaTime) bool FCogImguiContext::BeginFrame(float InDeltaTime)
{ {
FCogImGuiContextScope ImGuiContextScope(ImGuiContext, PlotContext);
//------------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------------
// Skip the first frame, to let the main widget update its TickSpaceGeometry which is returned by the // Skip the first frame, to let the main widget update its TickSpaceGeometry which is returned by the
// plateform callback ImGui_GetWindowPos. When using viewports Imgui needs to know the main viewport // plateform callback ImGui_GetWindowPos. When using viewports Imgui needs to know the main viewport
@@ -176,10 +219,6 @@ bool FCogImguiContext::BeginFrame(float InDeltaTime)
return false; return false;
} }
ImGui::SetCurrentContext(ImGuiContext);
ImPlot::SetImGuiContext(ImGuiContext);
ImPlot::SetCurrentContext(PlotContext);
ImGuiIO& IO = ImGui::GetIO(); ImGuiIO& IO = ImGui::GetIO();
IO.DeltaTime = InDeltaTime; IO.DeltaTime = InDeltaTime;
IO.DisplaySize = FCogImguiHelper::ToImVec2(MainWidget->GetTickSpaceGeometry().GetAbsoluteSize()); IO.DisplaySize = FCogImguiHelper::ToImVec2(MainWidget->GetTickSpaceGeometry().GetAbsoluteSize());
@@ -287,6 +326,8 @@ bool FCogImguiContext::BeginFrame(float InDeltaTime)
//-------------------------------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------------------------------
void FCogImguiContext::EndFrame() void FCogImguiContext::EndFrame()
{ {
FCogImGuiContextScope ImGuiContextScope(ImGuiContext, PlotContext);
ImGui::Render(); ImGui::Render();
ImGui_RenderWindow(ImGui::GetMainViewport(), nullptr); ImGui_RenderWindow(ImGui::GetMainViewport(), nullptr);
@@ -686,6 +727,8 @@ void FCogImguiContext::SetDPIScale(float Value)
//-------------------------------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------------------------------
void FCogImguiContext::BuildFont() void FCogImguiContext::BuildFont()
{ {
FCogImGuiContextScope ImGuiContextScope(ImGuiContext, PlotContext);
if (FontAtlasTexture != nullptr) if (FontAtlasTexture != nullptr)
{ {
FontAtlasTexture->RemoveFromRoot(); FontAtlasTexture->RemoveFromRoot();
@@ -703,7 +746,15 @@ void FCogImguiContext::BuildFont()
int32 TextureWidth, TextureHeight, BytesPerPixel; int32 TextureWidth, TextureHeight, BytesPerPixel;
IO.Fonts->GetTexDataAsRGBA32(&TextureDataRaw, &TextureWidth, &TextureHeight, &BytesPerPixel); IO.Fonts->GetTexDataAsRGBA32(&TextureDataRaw, &TextureWidth, &TextureHeight, &BytesPerPixel);
FontAtlasTexture = UTexture2D::CreateTransient(TextureWidth, TextureHeight, PF_R8G8B8A8, TEXT("ImGuiFontAtlas")); #if UE_VERSION_OLDER_THAN(5, 5, 0)
const int32 PieSessionId = GPlayInEditorID;
#else
const int32 PieSessionId = UE::GetPlayInEditorID();
#endif
FString TextureName = FString::Format(TEXT("ImGuiFontAtlas{0}"), { PieSessionId });
FontAtlasTexture = UTexture2D::CreateTransient(TextureWidth, TextureHeight, PF_R8G8B8A8, *TextureName);
FontAtlasTexture->Filter = TF_Bilinear; FontAtlasTexture->Filter = TF_Bilinear;
FontAtlasTexture->AddressX = TA_Wrap; FontAtlasTexture->AddressX = TA_Wrap;
FontAtlasTexture->AddressY = TA_Wrap; FontAtlasTexture->AddressY = TA_Wrap;
@@ -93,6 +93,8 @@ FReply SCogImguiInputCatcherWidget::OnMouseButtonUp(const FGeometry& MyGeometry,
//-------------------------------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------------------------------
FReply SCogImguiInputCatcherWidget::HandleMouseButtonEvent(const FPointerEvent& MouseEvent, bool Down) FReply SCogImguiInputCatcherWidget::HandleMouseButtonEvent(const FPointerEvent& MouseEvent, bool Down)
{ {
FCogImGuiContextScope ImGuiContextScope(*Context);
if (Context->GetEnableInput() == false) if (Context->GetEnableInput() == false)
{ {
UE_LOG(LogCogImGui, VeryVerbose, TEXT("SCogImguiInputCatcherWidget::HandleMouseButtonEvent | Window:%s | Unhandled | EnableInput == false | Down:%d"), Window.IsValid() ? *Window->GetTitle().ToString() : *FString("None"), Down); UE_LOG(LogCogImGui, VeryVerbose, TEXT("SCogImguiInputCatcherWidget::HandleMouseButtonEvent | Window:%s | Unhandled | EnableInput == false | Down:%d"), Window.IsValid() ? *Window->GetTitle().ToString() : *FString("None"), Down);
@@ -110,6 +112,8 @@ FReply SCogImguiInputCatcherWidget::HandleMouseButtonEvent(const FPointerEvent&
//-------------------------------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------------------------------
FReply SCogImguiInputCatcherWidget::OnMouseWheel(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) FReply SCogImguiInputCatcherWidget::OnMouseWheel(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
{ {
FCogImGuiContextScope ImGuiContextScope(*Context);
if (Context->GetEnableInput() == false) if (Context->GetEnableInput() == false)
{ {
return FReply::Unhandled(); return FReply::Unhandled();
@@ -33,4 +33,4 @@ void FCogImguiModule::ShutdownModule()
//-------------------------------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------------------------------
#undef LOCTEXT_NAMESPACE #undef LOCTEXT_NAMESPACE
IMPLEMENT_MODULE(FCogImguiModule, CogImGui) IMPLEMENT_MODULE(FCogImguiModule, CogImgui)
@@ -112,6 +112,8 @@ FVector2D SCogImguiWidget::ComputeDesiredSize(float Scale) const
//-------------------------------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------------------------------
FReply SCogImguiWidget::OnKeyChar(const FGeometry& MyGeometry, const FCharacterEvent& CharacterEvent) FReply SCogImguiWidget::OnKeyChar(const FGeometry& MyGeometry, const FCharacterEvent& CharacterEvent)
{ {
FCogImGuiContextScope ImGuiContextScope(*Context);
ImGuiIO& IO = ImGui::GetIO(); ImGuiIO& IO = ImGui::GetIO();
IO.AddInputCharacter(FCogImguiInputHelper::CastInputChar(CharacterEvent.GetCharacter())); IO.AddInputCharacter(FCogImguiInputHelper::CastInputChar(CharacterEvent.GetCharacter()));
@@ -134,6 +136,8 @@ FReply SCogImguiWidget::OnKeyUp(const FGeometry& MyGeometry, const FKeyEvent& Ke
//-------------------------------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------------------------------
FReply SCogImguiWidget::HandleKeyEvent(const FKeyEvent& KeyEvent, bool Down) FReply SCogImguiWidget::HandleKeyEvent(const FKeyEvent& KeyEvent, bool Down)
{ {
FCogImGuiContextScope ImGuiContextScope(*Context);
if (Context->GetEnableInput() == false) if (Context->GetEnableInput() == false)
{ {
return FReply::Unhandled(); return FReply::Unhandled();
@@ -196,6 +200,8 @@ FReply SCogImguiWidget::OnMouseButtonUp(const FGeometry& MyGeometry, const FPoin
//-------------------------------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------------------------------
FReply SCogImguiWidget::HandleMouseButtonEvent(const FPointerEvent& MouseEvent, bool Down) FReply SCogImguiWidget::HandleMouseButtonEvent(const FPointerEvent& MouseEvent, bool Down)
{ {
FCogImGuiContextScope ImGuiContextScope(*Context);
if (Context->GetEnableInput() == false) if (Context->GetEnableInput() == false)
{ {
UE_LOG(LogCogImGui, VeryVerbose, TEXT("SCogImguiWidget::HandleMouseButtonEvent | %s | Unhandled | EnableInput == false | Down:%d"), Window.IsValid() ? *Window->GetTitle().ToString() : *FString("None"), Down); UE_LOG(LogCogImGui, VeryVerbose, TEXT("SCogImguiWidget::HandleMouseButtonEvent | %s | Unhandled | EnableInput == false | Down:%d"), Window.IsValid() ? *Window->GetTitle().ToString() : *FString("None"), Down);
@@ -212,6 +218,8 @@ FReply SCogImguiWidget::HandleMouseButtonEvent(const FPointerEvent& MouseEvent,
//-------------------------------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------------------------------
FReply SCogImguiWidget::OnMouseWheel(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) FReply SCogImguiWidget::OnMouseWheel(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
{ {
FCogImGuiContextScope ImGuiContextScope(*Context);
if (Context->GetEnableInput() == false) if (Context->GetEnableInput() == false)
{ {
return FReply::Unhandled(); return FReply::Unhandled();
@@ -224,6 +232,8 @@ FReply SCogImguiWidget::OnMouseWheel(const FGeometry& MyGeometry, const FPointer
//-------------------------------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------------------------------
FReply SCogImguiWidget::OnMouseMove(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) FReply SCogImguiWidget::OnMouseMove(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
{ {
FCogImGuiContextScope ImGuiContextScope(*Context);
if (Context->GetEnableInput() == false) if (Context->GetEnableInput() == false)
{ {
//UE_LOG(LogCogImGui, VeryVerbose, TEXT("SCogImguiWidget::OnMouseMove | Window:%s | Unhandled | EnableInput == false"), Window.IsValid() ? *Window->GetTitle().ToString() : *FString("None")); //UE_LOG(LogCogImGui, VeryVerbose, TEXT("SCogImguiWidget::OnMouseMove | Window:%s | Unhandled | EnableInput == false"), Window.IsValid() ? *Window->GetTitle().ToString() : *FString("None"));
@@ -25,6 +25,18 @@ struct COGIMGUI_API FCogImGuiViewportData
TWeakPtr<SCogImguiWidget> Widget = nullptr; TWeakPtr<SCogImguiWidget> Widget = nullptr;
}; };
struct COGIMGUI_API FCogImGuiContextScope
{
UE_NODISCARD_CTOR explicit FCogImGuiContextScope(FCogImguiContext& CogImguiContext);
UE_NODISCARD_CTOR explicit FCogImGuiContextScope(ImGuiContext* GuiCtx, ImPlotContext* PlotCtx);
~FCogImGuiContextScope();
private:
ImGuiContext* PrevContext = nullptr;
ImPlotContext* PrevPlotContext = nullptr;
};
class COGIMGUI_API FCogImguiContext : public TSharedFromThis<FCogImguiContext> class COGIMGUI_API FCogImguiContext : public TSharedFromThis<FCogImguiContext>
{ {
public: public:
@@ -65,6 +77,8 @@ public:
private: private:
friend struct FCogImGuiContextScope;
void OnDisplayMetricsChanged(const FDisplayMetrics& DisplayMetrics) const; void OnDisplayMetricsChanged(const FDisplayMetrics& DisplayMetrics) const;
bool IsConsoleOpened() const; bool IsConsoleOpened() const;
@@ -0,0 +1,66 @@
#include "CogWindowConsoleCommandManager.h"
#include "Engine/World.h"
TMap<FString, FCogCommandInfo> FCogWindowConsoleCommandManager::CommandMap;
//--------------------------------------------------------------------------------------------------------------------------
void FCogWindowConsoleCommandManager::RegisterWorldConsoleCommand(const TCHAR* InName, const TCHAR* InHelp, UWorld* InWorld, const FCogWindowConsoleCommandDelegate& InDelegate)
{
FCogCommandInfo& commandInfo = CommandMap.FindOrAdd(InName);
if (commandInfo.Receivers.Num() == 0)
{
commandInfo.ConsoleObject = IConsoleManager::Get().RegisterConsoleCommand
(
InName,
InHelp,
FConsoleCommandWithWorldAndArgsDelegate::CreateLambda(
[InName](const TArray<FString>& Args, UWorld* InCommandWorld)
{
FCogCommandInfo* commandInfo = CommandMap.Find(InName);
if (commandInfo == nullptr)
{
return;
}
for (auto& receiver : commandInfo->Receivers)
{
if (receiver.World == InCommandWorld)
{
receiver.Delegate.ExecuteIfBound(Args, InCommandWorld);
break;
}
}
}),
ECVF_Cheat
);
}
FCogCommandReceiver& receiver = commandInfo.Receivers.AddDefaulted_GetRef();
receiver.World = InWorld;
receiver.Delegate = InDelegate;
}
//--------------------------------------------------------------------------------------------------------------------------
void FCogWindowConsoleCommandManager::UnregisterAllWorldConsoleCommands(const UWorld* InWorld)
{
for (auto& kv : CommandMap)
{
FCogCommandInfo& commandInfo = kv.Value;
for (int32 i = commandInfo.Receivers.Num() - 1; i >= 0; --i)
{
if (commandInfo.Receivers[i].World == InWorld)
{
commandInfo.Receivers.RemoveAt(i);
}
}
if (commandInfo.Receivers.Num() == 0 && commandInfo.ConsoleObject != nullptr)
{
IConsoleManager::Get().UnregisterConsoleObject(commandInfo.ConsoleObject);
commandInfo.ConsoleObject = nullptr;
}
}
}
@@ -3,6 +3,7 @@
#include "CogDebugDrawImGui.h" #include "CogDebugDrawImGui.h"
#include "CogImguiHelper.h" #include "CogImguiHelper.h"
#include "CogImguiInputHelper.h" #include "CogImguiInputHelper.h"
#include "CogWindowConsoleCommandManager.h"
#include "CogWindow_Layouts.h" #include "CogWindow_Layouts.h"
#include "CogWindow_Settings.h" #include "CogWindow_Settings.h"
#include "CogWindow_Spacing.h" #include "CogWindow_Spacing.h"
@@ -12,8 +13,10 @@
#include "GameFramework/PlayerInput.h" #include "GameFramework/PlayerInput.h"
#include "HAL/IConsoleManager.h" #include "HAL/IConsoleManager.h"
#include "imgui_internal.h" #include "imgui_internal.h"
#include "Misc/EngineVersionComparison.h"
FString UCogWindowManager::ToggleInputCommand = TEXT("Cog.ToggleInput"); FString UCogWindowManager::ToggleInputCommand = TEXT("Cog.ToggleInput");
FString UCogWindowManager::DisableInputCommand = TEXT("Cog.DisableInput");
FString UCogWindowManager::LoadLayoutCommand = TEXT("Cog.LoadLayout"); FString UCogWindowManager::LoadLayoutCommand = TEXT("Cog.LoadLayout");
FString UCogWindowManager::SaveLayoutCommand = TEXT("Cog.SaveLayout"); FString UCogWindowManager::SaveLayoutCommand = TEXT("Cog.SaveLayout");
FString UCogWindowManager::ResetLayoutCommand = TEXT("Cog.ResetLayout"); FString UCogWindowManager::ResetLayoutCommand = TEXT("Cog.ResetLayout");
@@ -28,13 +31,21 @@ void UCogWindowManager::PostInitProperties()
{ {
Super::PostInitProperties(); Super::PostInitProperties();
if (bRegisterDefaultCommands) //if (bRegisterDefaultCommands)
{ //{
if (RegisterDefaultCommandBindings()) // if (RegisterDefaultCommandBindings())
{ // {
bRegisterDefaultCommands = false; // bRegisterDefaultCommands = false;
} // }
} //}
//-------------------------------------------------------------------------------
// Currently always register default commands.
// Since UE5.4, the ini files must have this to be saved:
// [SectionsToSave]
// bCanSaveAllSections = True
//-------------------------------------------------------------------------------
RegisterDefaultCommandBindings();
} }
//-------------------------------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------------------------------
@@ -42,6 +53,8 @@ void UCogWindowManager::InitializeInternal()
{ {
Context.Initialize(); Context.Initialize();
FCogImGuiContextScope ImGuiContextScope(Context);
ImGuiSettingsHandler IniHandler; ImGuiSettingsHandler IniHandler;
IniHandler.TypeName = "Cog"; IniHandler.TypeName = "Cog";
IniHandler.TypeHash = ImHashStr("Cog"); IniHandler.TypeHash = ImHashStr("Cog");
@@ -61,29 +74,59 @@ void UCogWindowManager::InitializeInternal()
LayoutsWindow = AddWindow<FCogWindow_Layouts>("Window.Layouts", false); LayoutsWindow = AddWindow<FCogWindow_Layouts>("Window.Layouts", false);
SettingsWindow = AddWindow<FCogWindow_Settings>("Window.Settings", false); SettingsWindow = AddWindow<FCogWindow_Settings>("Window.Settings", false);
ConsoleCommands.Add(IConsoleManager::Get().RegisterConsoleCommand( FCogWindowConsoleCommandManager::RegisterWorldConsoleCommand(
*ToggleInputCommand, *ToggleInputCommand,
TEXT("Toggle the input focus between the Game and ImGui"), TEXT("Toggle the input focus between the Game and ImGui"),
FConsoleCommandWithArgsDelegate::CreateLambda([this](const TArray<FString>& Args) { ToggleInputMode(); }), GetWorld(),
ECVF_Cheat)); FCogWindowConsoleCommandDelegate::CreateLambda([this](const TArray<FString>& InArgs, UWorld* InWorld)
{
ToggleInputMode();
}));
ConsoleCommands.Add(IConsoleManager::Get().RegisterConsoleCommand( FCogWindowConsoleCommandManager::RegisterWorldConsoleCommand(
*DisableInputCommand,
TEXT("Disable ImGui input"),
GetWorld(),
FCogWindowConsoleCommandDelegate::CreateLambda([this](const TArray<FString>& InArgs, UWorld* InWorld)
{
DisableInputMode();
}));
FCogWindowConsoleCommandManager::RegisterWorldConsoleCommand(
*ResetLayoutCommand, *ResetLayoutCommand,
TEXT("Reset the layout."), TEXT("Reset the layout."),
FConsoleCommandWithArgsDelegate::CreateLambda([this](const TArray<FString>& Args) { if (Args.Num() > 0) { ResetLayout(); }}), GetWorld(),
ECVF_Cheat)); FCogWindowConsoleCommandDelegate::CreateLambda([this](const TArray<FString>& InArgs, UWorld* InWorld)
{
if (InArgs.Num() > 0)
{
ResetLayout();
}
}));
ConsoleCommands.Add(IConsoleManager::Get().RegisterConsoleCommand( FCogWindowConsoleCommandManager::RegisterWorldConsoleCommand(
*LoadLayoutCommand, *LoadLayoutCommand,
TEXT("Load the layout. Cog.LoadLayout <Index>"), TEXT("Load the layout. Cog.LoadLayout <Index>"),
FConsoleCommandWithArgsDelegate::CreateLambda([this](const TArray<FString>& Args) { if (Args.Num() > 0) { LoadLayout(FCString::Atoi(*Args[0])); }}), GetWorld(),
ECVF_Cheat)); FCogWindowConsoleCommandDelegate::CreateLambda([this](const TArray<FString>& InArgs, UWorld* InWorld)
{
if (InArgs.Num() > 0)
{
LoadLayout(FCString::Atoi(*InArgs[0]));
}
}));
ConsoleCommands.Add(IConsoleManager::Get().RegisterConsoleCommand( FCogWindowConsoleCommandManager::RegisterWorldConsoleCommand(
*SaveLayoutCommand, *SaveLayoutCommand,
TEXT("Save the layout. Cog.SaveLayout <Index>"), TEXT("Save the layout. Cog.SaveLayout <Index>"),
FConsoleCommandWithArgsDelegate::CreateLambda([this](const TArray<FString>& Args) { if (Args.Num() > 0) { SaveLayout(FCString::Atoi(*Args[0])); }}), GetWorld(),
ECVF_Cheat)); FCogWindowConsoleCommandDelegate::CreateLambda([this](const TArray<FString>& InArgs, UWorld* InWorld)
{
if (InArgs.Num() > 0)
{
SaveLayout(FCString::Atoi(*InArgs[0]));
}
}));
IsInitialized = true; IsInitialized = true;
} }
@@ -91,6 +134,8 @@ void UCogWindowManager::InitializeInternal()
//-------------------------------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------------------------------
void UCogWindowManager::Shutdown() void UCogWindowManager::Shutdown()
{ {
FCogImGuiContextScope ImGuiContextScope(Context);
//------------------------------------------------------------ //------------------------------------------------------------
// Call PreSaveConfig before destroying imgui context // Call PreSaveConfig before destroying imgui context
// if PreSaveConfig needs to read ImGui IO for example // if PreSaveConfig needs to read ImGui IO for example
@@ -104,7 +149,10 @@ void UCogWindowManager::Shutdown()
// Destroy ImGui before destroying the windows to make sure // Destroy ImGui before destroying the windows to make sure
// imgui serialize their visibility state in imgui.ini // imgui serialize their visibility state in imgui.ini
//------------------------------------------------------------ //------------------------------------------------------------
Context.Shutdown(); if (IsInitialized == true)
{
Context.Shutdown();
}
SaveConfig(); SaveConfig();
@@ -120,15 +168,14 @@ void UCogWindowManager::Shutdown()
Config->SaveConfig(); Config->SaveConfig();
} }
for (IConsoleObject* ConsoleCommand : ConsoleCommands) FCogWindowConsoleCommandManager::UnregisterAllWorldConsoleCommands(GetWorld());
{
IConsoleManager::Get().UnregisterConsoleObject(ConsoleCommand);
}
} }
//-------------------------------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------------------------------
void UCogWindowManager::Tick(float DeltaTime) void UCogWindowManager::Tick(float DeltaTime)
{ {
FCogImGuiContextScope ImGuiContextScope(Context);
if (GEngine->GameViewport == nullptr) if (GEngine->GameViewport == nullptr)
{ {
return; return;
@@ -161,6 +208,8 @@ void UCogWindowManager::Tick(float DeltaTime)
//-------------------------------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------------------------------
void UCogWindowManager::Render(float DeltaTime) void UCogWindowManager::Render(float DeltaTime)
{ {
FCogImGuiContextScope ImGuiContextScope(Context);
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0, 0, 0, 0)); ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0, 0, 0, 0));
ImGui::DockSpaceOverViewport(0, ImGuiDockNodeFlags_PassthruCentralNode | ImGuiDockNodeFlags_NoDockingInCentralNode | ImGuiDockNodeFlags_AutoHideTabBar); ImGui::DockSpaceOverViewport(0, ImGuiDockNodeFlags_PassthruCentralNode | ImGuiDockNodeFlags_NoDockingInCentralNode | ImGuiDockNodeFlags_AutoHideTabBar);
ImGui::PopStyleColor(1); ImGui::PopStyleColor(1);
@@ -249,6 +298,8 @@ void UCogWindowManager::SetHideAllWindows(const bool Value)
//-------------------------------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------------------------------
void UCogWindowManager::ResetLayout() void UCogWindowManager::ResetLayout()
{ {
FCogImGuiContextScope ImGuiContextScope(Context);
for (const FCogWindow* Window : Windows) for (const FCogWindow* Window : Windows)
{ {
ImGui::SetWindowPos(TCHAR_TO_ANSI(*Window->GetName()), ImVec2(10, 10), ImGuiCond_Always); ImGui::SetWindowPos(TCHAR_TO_ANSI(*Window->GetName()), ImVec2(10, 10), ImGuiCond_Always);
@@ -280,6 +331,8 @@ void UCogWindowManager::LoadLayout(const int32 LayoutIndex)
//-------------------------------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------------------------------
void UCogWindowManager::SaveLayout(const int32 LayoutIndex) void UCogWindowManager::SaveLayout(const int32 LayoutIndex)
{ {
FCogImGuiContextScope ImGuiContextScope(Context);
const FString Filename = *FCogImguiHelper::GetIniFilePath(FString::Printf(TEXT("imgui_layout_%d"), LayoutIndex)); const FString Filename = *FCogImguiHelper::GetIniFilePath(FString::Printf(TEXT("imgui_layout_%d"), LayoutIndex));
ImGui::SaveIniSettingsToDisk(TCHAR_TO_ANSI(*Filename)); ImGui::SaveIniSettingsToDisk(TCHAR_TO_ANSI(*Filename));
} }
@@ -681,6 +734,10 @@ bool UCogWindowManager::RegisterDefaultCommandBindings()
} }
UPlayerInput* PlayerInput = FCogImguiInputHelper::GetPlayerInput(*GetWorld()); UPlayerInput* PlayerInput = FCogImguiInputHelper::GetPlayerInput(*GetWorld());
if (PlayerInput == nullptr)
{
return false;
}
AddCommand(PlayerInput, "Cog.ToggleInput", EKeys::F1); AddCommand(PlayerInput, "Cog.ToggleInput", EKeys::F1);
AddCommand(PlayerInput, "Cog.LoadLayout 1", EKeys::F2); AddCommand(PlayerInput, "Cog.LoadLayout 1", EKeys::F2);
@@ -690,13 +747,17 @@ bool UCogWindowManager::RegisterDefaultCommandBindings()
SortCommands(PlayerInput); SortCommands(PlayerInput);
PlayerInput->SaveConfig(); PlayerInput->SaveConfig();
return true; return true;
} }
//-------------------------------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------------------------------
void UCogWindowManager::AddCommand(UPlayerInput* PlayerInput, const FString& Command, const FKey& Key) void UCogWindowManager::AddCommand(UPlayerInput* PlayerInput, const FString& Command, const FKey& Key)
{ {
if (PlayerInput == nullptr)
{
return;
}
//--------------------------------------------------- //---------------------------------------------------
// Reassign conflicting commands // Reassign conflicting commands
//--------------------------------------------------- //---------------------------------------------------
@@ -788,3 +849,10 @@ void UCogWindowManager::ToggleInputMode()
Context.SetEnableInput(!Context.GetEnableInput()); Context.SetEnableInput(!Context.GetEnableInput());
} }
//--------------------------------------------------------------------------------------------------------------------------
void UCogWindowManager::DisableInputMode()
{
UE_LOG(LogCogImGui, Verbose, TEXT("UCogWindowManager::DisableInputMode"));
Context.SetEnableInput(false);
}
@@ -0,0 +1,39 @@
#pragma once
#include "CoreMinimal.h"
#include "HAL/IConsoleManager.h"
#include "Templates/Function.h"
class UWorld;
DECLARE_DELEGATE_TwoParams(FCogWindowConsoleCommandDelegate, const TArray<FString>&, UWorld*);
//--------------------------------------------------------------------------------------------------------------------------
struct FCogCommandReceiver
{
UWorld* World = nullptr;
FCogWindowConsoleCommandDelegate Delegate;
};
//--------------------------------------------------------------------------------------------------------------------------
struct FCogCommandInfo
{
IConsoleObject* ConsoleObject = nullptr;
TArray<FCogCommandReceiver> Receivers;
};
//--------------------------------------------------------------------------------------------------------------------------
struct COGWINDOW_API FCogWindowConsoleCommandManager
{
public:
static void RegisterWorldConsoleCommand(const TCHAR* InName, const TCHAR* InHelp, UWorld* InWorld, const FCogWindowConsoleCommandDelegate& InDelegate);
static void UnregisterAllWorldConsoleCommands(const UWorld* InWorld);
protected:
static TMap<FString, FCogCommandInfo> CommandMap;
};
@@ -101,10 +101,12 @@ protected:
virtual void RenderMenuItem(FCogWindow& Window, const char* MenuItemName); virtual void RenderMenuItem(FCogWindow& Window, const char* MenuItemName);
void RenderMenuItemHelp(FCogWindow& Window); virtual void RenderMenuItemHelp(FCogWindow& Window);
virtual void ToggleInputMode(); virtual void ToggleInputMode();
virtual void DisableInputMode();
static void SettingsHandler_ClearAll(ImGuiContext* ctx, ImGuiSettingsHandler*); static void SettingsHandler_ClearAll(ImGuiContext* ctx, ImGuiSettingsHandler*);
static void SettingsHandler_ApplyAll(ImGuiContext* ctx, ImGuiSettingsHandler*); static void SettingsHandler_ApplyAll(ImGuiContext* ctx, ImGuiSettingsHandler*);
@@ -116,6 +118,8 @@ protected:
static void SettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandler* handler, ImGuiTextBuffer* buf); static void SettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandler* handler, ImGuiTextBuffer* buf);
static FString ToggleInputCommand; static FString ToggleInputCommand;
static FString DisableInputCommand;
static FString LoadLayoutCommand; static FString LoadLayoutCommand;
@@ -155,8 +159,6 @@ protected:
bool bHideAllWindows = false; bool bHideAllWindows = false;
bool IsInitialized = false; bool IsInitialized = false;
TArray<IConsoleObject*> ConsoleCommands;
}; };
//-------------------------------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------------------------------
-5
View File
@@ -446,8 +446,3 @@ class ACogSamplePlayerController
![Data Assets](https://github.com/arnaud-jamin/Cog/assets/13844285/1f4f3255-4104-4dfc-ab9e-fd34335c0289) ![Data Assets](https://github.com/arnaud-jamin/Cog/assets/13844285/1f4f3255-4104-4dfc-ab9e-fd34335c0289)
Currently, Cog does not properly work when running under a single process in multiplayer mode. You might want to disable the setting `Editor Preferences - Run Under One Process`:
![image](https://github.com/arnaud-jamin/Cog/assets/13844285/6079b71c-bd41-4193-b3c6-aa76a70984e5)
+4 -6
View File
@@ -5,11 +5,9 @@ public class CogSampleTarget : TargetRules
{ {
public CogSampleTarget(TargetInfo Target) : base(Target) public CogSampleTarget(TargetInfo Target) : base(Target)
{ {
Type = TargetType.Game; Type = TargetType.Game;
DefaultBuildSettings = BuildSettingsVersion.V2; DefaultBuildSettings = BuildSettingsVersion.V2;
//IncludeOrderVersion = EngineIncludeOrderVersion.Unreal5_2; DefaultBuildSettings = BuildSettingsVersion.Latest;
ExtraModuleNames.Add("CogSample"); IncludeOrderVersion = EngineIncludeOrderVersion.Latest;
//bUseUnityBuild = false;
//bUsePCHFiles = false;
} }
} }
@@ -7,6 +7,7 @@
#include "CogSampleLogCategories.h" #include "CogSampleLogCategories.h"
#include "CogSampleTargetableInterface.h" #include "CogSampleTargetableInterface.h"
#include "Components/CapsuleComponent.h" #include "Components/CapsuleComponent.h"
#include "Engine/OverlapResult.h"
#include "GameFramework/PlayerController.h" #include "GameFramework/PlayerController.h"
#if ENABLE_COG #if ENABLE_COG
+6 -5
View File
@@ -5,9 +5,10 @@ public class CogSampleEditorTarget : TargetRules
{ {
public CogSampleEditorTarget(TargetInfo Target) : base(Target) public CogSampleEditorTarget(TargetInfo Target) : base(Target)
{ {
Type = TargetType.Editor; Type = TargetType.Editor;
DefaultBuildSettings = BuildSettingsVersion.V2; DefaultBuildSettings = BuildSettingsVersion.V2;
//IncludeOrderVersion = EngineIncludeOrderVersion.Unreal5_2; DefaultBuildSettings = BuildSettingsVersion.Latest;
ExtraModuleNames.Add("CogSample"); IncludeOrderVersion = EngineIncludeOrderVersion.Latest;
} ExtraModuleNames.Add("CogSample");
}
} }