Mutiple fixes

Fix shipping build by reworking Cog integration (now use a subsystem)
Fix crash when stopping and restarting in the editor
This commit is contained in:
Arnaud Jamin
2025-05-13 13:30:21 -04:00
parent ac000a37c6
commit 4c615ae10d
32 changed files with 248 additions and 194 deletions
+40 -43
View File
@@ -25,9 +25,22 @@ FString UCogSubsystem::SaveLayoutCommand = TEXT("Cog.SaveLayout");
FString UCogSubsystem::ResetLayoutCommand = TEXT("Cog.ResetLayout");
//--------------------------------------------------------------------------------------------------------------------------
void UCogSubsystem::Initialize(FSubsystemCollectionBase& Collection)
bool UCogSubsystem::ShouldCreateSubsystem(UObject* Outer) const
{
Super::Initialize(Collection);
if (Super::ShouldCreateSubsystem(Outer) == false)
{ return false; }
#if ENABLE_COG
return true;
#else
return false;
#endif
}
//--------------------------------------------------------------------------------------------------------------------------
TStatId UCogSubsystem::GetStatId() const
{
RETURN_QUICK_DECLARE_CYCLE_STAT(UCogSubsystemBase, STATGROUP_Tickables);
}
//--------------------------------------------------------------------------------------------------------------------------
@@ -38,12 +51,6 @@ void UCogSubsystem::Deinitialize()
Super::Deinitialize();
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogSubsystem::Activate()
{
FWorldDelegates::OnWorldTickStart.AddUObject(this, &ThisClass::Tick);
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogSubsystem::TryInitialize(UWorld& World)
{
@@ -60,7 +67,7 @@ void UCogSubsystem::TryInitialize(UWorld& World)
Context.Initialize(WorldContext->GameViewport.Get());
FCogImGuiContextScope ImGuiContextScope(Context);
ImGuiSettingsHandler IniHandler;
IniHandler.TypeName = "Cog";
IniHandler.TypeHash = ImHashStr("Cog");
@@ -71,14 +78,14 @@ void UCogSubsystem::TryInitialize(UWorld& World)
IniHandler.WriteAllFn = SettingsHandler_WriteAll;
IniHandler.UserData = this;
ImGui::AddSettingsHandler(&IniHandler);
SpaceWindows.Add(AddWindow<FCogWindow_Spacing>("Spacing 1"));
SpaceWindows.Add(AddWindow<FCogWindow_Spacing>("Spacing 2"));
SpaceWindows.Add(AddWindow<FCogWindow_Spacing>("Spacing 3"));
SpaceWindows.Add(AddWindow<FCogWindow_Spacing>("Spacing 4"));
Settings = GetConfig<UCogWindowConfig_Settings>();
Settings = GetConfig<UCogWindowConfig_Settings>();
UCogWindowConfig_Settings* SettingsPtr = Settings.Get();
AddShortcut(SettingsPtr, &UCogWindowConfig_Settings::Shortcut_ToggleImguiInput).BindLambda([this] () { ToggleInputMode(); });
AddShortcut(SettingsPtr, &UCogWindowConfig_Settings::Shortcut_LoadLayout1).BindLambda([this] (){ LoadLayout(1); });
@@ -91,14 +98,14 @@ void UCogSubsystem::TryInitialize(UWorld& World)
AddShortcut(SettingsPtr, &UCogWindowConfig_Settings::Shortcut_SaveLayout4).BindLambda([this] (){ SaveLayout(4); });
AddShortcut(SettingsPtr, &UCogWindowConfig_Settings::Shortcut_ResetLayout).BindLambda([this] (){ ResetLayout(); });
LayoutsWindow = AddWindow<FCogWindow_Layouts>("Window.Layouts");
SettingsWindow = AddWindow<FCogWindow_Settings>("Window.Settings");
LayoutsWindow = AddWindow<FCogWindow_Layouts>("Window.Layouts");
SettingsWindow = AddWindow<FCogWindow_Settings>("Window.Settings");
for (FCogWindow* Window : Windows)
{
InitializeWindow(Window);
}
FCogConsoleCommandManager::RegisterWorldConsoleCommand(
*ToggleInputCommand,
TEXT("Toggle the input focus between the Game and ImGui"),
@@ -107,7 +114,7 @@ void UCogSubsystem::TryInitialize(UWorld& World)
{
ToggleInputMode();
}));
FCogConsoleCommandManager::RegisterWorldConsoleCommand(
*DisableInputCommand,
TEXT("Disable ImGui input"),
@@ -116,7 +123,7 @@ void UCogSubsystem::TryInitialize(UWorld& World)
{
DisableInputMode();
}));
FCogConsoleCommandManager::RegisterWorldConsoleCommand(
*ResetLayoutCommand,
TEXT("Reset the layout."),
@@ -128,7 +135,7 @@ void UCogSubsystem::TryInitialize(UWorld& World)
ResetLayout();
}
}));
FCogConsoleCommandManager::RegisterWorldConsoleCommand(
*LoadLayoutCommand,
TEXT("Load the layout. Cog.LoadLayout <Index>"),
@@ -140,7 +147,7 @@ void UCogSubsystem::TryInitialize(UWorld& World)
LoadLayout(FCString::Atoi(*InArgs[0]));
}
}));
FCogConsoleCommandManager::RegisterWorldConsoleCommand(
*SaveLayoutCommand,
TEXT("Save the layout. Cog.SaveLayout <Index>"),
@@ -167,10 +174,6 @@ void UCogSubsystem::Shutdown()
// imgui serialize their visibility state in imgui.ini
// It also save the Cog Settings, so they are saved regularly.
//------------------------------------------------------------------
if (IsInitialized)
{
Context.Shutdown();
}
for (FCogWindow* Window : Windows)
{
@@ -179,9 +182,12 @@ void UCogSubsystem::Shutdown()
}
Windows.Empty();
if (IsInitialized)
{
Context.Shutdown();
}
FCogConsoleCommandManager::UnregisterAllWorldConsoleCommands(GetWorld());
FWorldDelegates::OnWorldTickStart.RemoveAll(this);
}
//--------------------------------------------------------------------------------------------------------------------------
@@ -212,18 +218,10 @@ void UCogSubsystem::ReloadAllSettings()
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogSubsystem::Tick(UWorld* InTickedWorld, ELevelTick InTickType, float InDeltaTime)
void UCogSubsystem::Tick(float InDeltaTime)
{
UWorld* World = GetWorld();
//----------------------------------------------------------------------------------------------
// The tick currently gets called from a static tick function, which tick for all PIEInstance worlds.
// We must not tick for a different world than ours.
// TODO: Find a better way to tick the subsystem only for our world.
//----------------------------------------------------------------------------------------------
if (World != InTickedWorld)
{ return; }
//----------------------------------------------------------------------------------------------
// When changing world the DebugExecBindings can change.
//----------------------------------------------------------------------------------------------
@@ -315,11 +313,6 @@ void UCogSubsystem::SetLocalPlayerController(APlayerController& PlayerController
//--------------------------------------------------------------------------------------------------------------------------
void UCogSubsystem::UpdatePlayerControllers(UWorld& World)
{
if (APlayerController* PlayerController = GetGameInstance()->GetFirstLocalPlayerController())
{
SetLocalPlayerController(*PlayerController);
}
TArray<UCogDebugPluginSubsystem*> PluginSubsystems;
ServerPlayerControllers.RemoveAll([] (TWeakObjectPtr<APlayerController> PlayerController)
@@ -330,9 +323,14 @@ void UCogSubsystem::UpdatePlayerControllers(UWorld& World)
for (FConstPlayerControllerIterator It = World.GetPlayerControllerIterator(); It; ++It)
{
APlayerController* PlayerController = It->Get();
if (PlayerController == nullptr)
if (IsValid(PlayerController) == false)
{ continue; }
if (PlayerController->IsLocalController())
{
SetLocalPlayerController(*PlayerController);
}
if (World.GetNetMode() != NM_Client)
{
if (ServerPlayerControllers.Contains(PlayerController))
@@ -342,7 +340,7 @@ void UCogSubsystem::UpdatePlayerControllers(UWorld& World)
if (PluginSubsystems.IsEmpty())
{
PluginSubsystems = GetOuterUGameInstance()->GetSubsystemArrayCopy<UCogDebugPluginSubsystem>();
PluginSubsystems = World.GetGameInstance()->GetSubsystemArrayCopy<UCogDebugPluginSubsystem>();
}
for (UCogDebugPluginSubsystem* PluginSubsystem : PluginSubsystems)
@@ -874,7 +872,6 @@ void UCogSubsystem::SettingsHandler_WriteAll(ImGuiContext* Context, ImGuiSetting
{
UCogSubsystem* CogSubsystem = static_cast<UCogSubsystem*>(Handler->UserData);
CogSubsystem->SaveAllSettings();
//-----------------------------------------------------------------------------------
+9 -9
View File
@@ -5,7 +5,8 @@
#include "CogImguiContext.h"
#include "CogWindow_Settings.h"
#include "imgui.h"
#include "Engine/GameInstance.h"
#include "Subsystems/WorldSubsystem.h"
#include "CogSubsystem.generated.h"
class UCogCommonConfig;
@@ -22,25 +23,26 @@ struct FKey;
//--------------------------------------------------------------------------------------------------------------------------
UCLASS()
class COG_API UCogSubsystem : public UGameInstanceSubsystem
class COG_API UCogSubsystem : public UTickableWorldSubsystem
{
GENERATED_BODY()
public:
virtual bool ShouldCreateSubsystem(UObject* Outer) const override;
virtual void Initialize(FSubsystemCollectionBase& Collection) override;
virtual TStatId GetStatId() const override;
virtual void Deinitialize() override;
void Activate();
virtual void SortMainMenu();
virtual void Tick(float DeltaTime) override;
virtual void AddWindow(FCogWindow* Window, const FString& Name);
template<class T>
T* AddWindow(const FString& Name);
virtual void SortMainMenu();
virtual FCogWindow* FindWindowByID(ImGuiID ID);
virtual void CloseAllWindows();
@@ -113,8 +115,6 @@ protected:
virtual void Render(float DeltaTime);
virtual void Tick(UWorld* InTickedWorld, ELevelTick InTickType, float InDeltaTime);
virtual void TryInitialize(UWorld& World);
virtual void UpdatePlayerControllers(UWorld& World);
@@ -60,6 +60,13 @@ void FCogImguiContext::Initialize(UGameViewportClient* InGameViewport)
GameViewport = InGameViewport;
// ImGui Context must be created before creating widgets as widgets can receive events that uses the ImGui context right away.
Context = ImGui::CreateContext();
PlotContext = ImPlot::CreateContext();
ImGui::SetCurrentContext(Context);
ImPlot::SetImGuiContext(Context);
ImPlot::SetCurrentContext(PlotContext);
if (GameViewport != nullptr)
{
SAssignNew(MainWidget, SCogImguiWidget).Context(this);
@@ -69,12 +76,6 @@ void FCogImguiContext::Initialize(UGameViewportClient* InGameViewport)
GameViewport->AddViewportWidgetContent(InputCatcherWidget.ToSharedRef(), -TNumericLimits<int32>::Max());
}
Context = ImGui::CreateContext();
PlotContext = ImPlot::CreateContext();
ImGui::SetCurrentContext(Context);
ImPlot::SetImGuiContext(Context);
ImPlot::SetCurrentContext(PlotContext);
ImGuiIO& IO = ImGui::GetIO();
IO.UserData = this;
@@ -209,12 +210,20 @@ void FCogImguiContext::Shutdown()
//--------------------------------------------------------------------------------------------------------------------------
void FCogImguiContext::OnImGuiWidgetFocusLost()
{
FCogImGuiContextScope ImGuiContextScope(Context, PlotContext);
if (bEnableInput == false)
{ return; }
if (GameViewport == nullptr)
{ return; }
if (bEnableInput && GameViewport->GetGameViewportWidget()->HasUserFocus(0))
{
bRetakeFocus = true;
}
const SViewport* ViewportWidget = GameViewport->GetGameViewportWidget().Get();
if (ViewportWidget == nullptr)
{ return; }
if (!ViewportWidget->HasUserFocus(0))
{ return; }
bRetakeFocus = true;
}
//--------------------------------------------------------------------------------------------------------------------------
+38 -38
View File
@@ -42,26 +42,26 @@
#include "GameFramework/GameUserSettings.h"
//--------------------------------------------------------------------------------------------------------------------------
void Cog::AddAllWindows(UCogSubsystem& CogWindowManager)
void Cog::AddAllWindows(UCogSubsystem& CogSubsystem)
{
//---------------------------------------
// Engine
//---------------------------------------
CogWindowManager.AddWindow<FCogEngineWindow_BuildInfo>("Engine.Build Info");
CogSubsystem.AddWindow<FCogEngineWindow_BuildInfo>("Engine.Build Info");
CogWindowManager.AddWindow<FCogEngineWindow_CollisionTester>("Engine.Collision Tester");
CogSubsystem.AddWindow<FCogEngineWindow_CollisionTester>("Engine.Collision Tester");
CogWindowManager.AddWindow<FCogEngineWindow_CollisionViewer>("Engine.Collision Viewer");
CogSubsystem.AddWindow<FCogEngineWindow_CollisionViewer>("Engine.Collision Viewer");
CogWindowManager.AddWindow<FCogEngineWindow_CommandBindings>("Engine.Command Bindings");
CogSubsystem.AddWindow<FCogEngineWindow_CommandBindings>("Engine.Command Bindings");
CogWindowManager.AddWindow<FCogEngineWindow_Console>("Engine.Console");
CogSubsystem.AddWindow<FCogEngineWindow_Console>("Engine.Console");
CogWindowManager.AddWindow<FCogEngineWindow_DebugSettings>("Engine.Debug Settings");
CogSubsystem.AddWindow<FCogEngineWindow_DebugSettings>("Engine.Debug Settings");
CogWindowManager.AddWindow<FCogEngineWindow_ImGui>("Engine.ImGui");
CogSubsystem.AddWindow<FCogEngineWindow_ImGui>("Engine.ImGui");
FCogEngineWindow_Inspector* Inspector = CogWindowManager.AddWindow<FCogEngineWindow_Inspector>("Engine.Inspector");
FCogEngineWindow_Inspector* Inspector = CogSubsystem.AddWindow<FCogEngineWindow_Inspector>("Engine.Inspector");
Inspector->AddFavorite(GEngine->GetGameUserSettings(), [](UObject* Object)
{
if (UGameUserSettings* UserSettings = Cast<UGameUserSettings>(Object))
@@ -70,70 +70,70 @@ void Cog::AddAllWindows(UCogSubsystem& CogWindowManager)
}
});
CogWindowManager.AddWindow<FCogEngineWindow_Levels>("Engine.Levels");
CogSubsystem.AddWindow<FCogEngineWindow_Levels>("Engine.Levels");
CogWindowManager.AddWindow<FCogEngineWindow_LogCategories>("Engine.Log Categories");
CogSubsystem.AddWindow<FCogEngineWindow_LogCategories>("Engine.Log Categories");
CogWindowManager.AddWindow<FCogEngineWindow_Metrics>("Engine.Metrics");
CogSubsystem.AddWindow<FCogEngineWindow_Metrics>("Engine.Metrics");
CogWindowManager.AddWindow<FCogEngineWindow_NetEmulation>("Engine.Net Emulation");
CogSubsystem.AddWindow<FCogEngineWindow_NetEmulation>("Engine.Net Emulation");
CogWindowManager.AddWindow<FCogEngineWindow_NetImgui>("Engine.Net ImGui");
CogSubsystem.AddWindow<FCogEngineWindow_NetImgui>("Engine.Net ImGui");
CogWindowManager.AddWindow<FCogEngineWindow_Notifications>("Engine.Notifications");
CogSubsystem.AddWindow<FCogEngineWindow_Notifications>("Engine.Notifications");
CogWindowManager.AddWindow<FCogEngineWindow_OutputLog>("Engine.Output Log");
CogSubsystem.AddWindow<FCogEngineWindow_OutputLog>("Engine.Output Log");
CogWindowManager.AddWindow<FCogEngineWindow_Plots>("Engine.Plots");
CogSubsystem.AddWindow<FCogEngineWindow_Plots>("Engine.Plots");
CogWindowManager.AddWindow<FCogEngineWindow_Selection>("Engine.Selection");
CogSubsystem.AddWindow<FCogEngineWindow_Selection>("Engine.Selection");
CogWindowManager.AddWindow<FCogEngineWindow_Scalability>("Engine.Scalability");
CogSubsystem.AddWindow<FCogEngineWindow_Scalability>("Engine.Scalability");
CogWindowManager.AddWindow<FCogEngineWindow_Skeleton>("Engine.Skeleton");
CogSubsystem.AddWindow<FCogEngineWindow_Skeleton>("Engine.Skeleton");
CogWindowManager.AddWindow<FCogEngineWindow_Slate>("Engine.Slate");
CogSubsystem.AddWindow<FCogEngineWindow_Slate>("Engine.Slate");
CogWindowManager.AddWindow<FCogEngineWindow_Spawns>("Engine.Spawns");
CogSubsystem.AddWindow<FCogEngineWindow_Spawns>("Engine.Spawns");
CogWindowManager.AddWindow<FCogEngineWindow_Stats>("Engine.Stats");
CogSubsystem.AddWindow<FCogEngineWindow_Stats>("Engine.Stats");
CogWindowManager.AddWindow<FCogEngineWindow_TimeScale>("Engine.Time Scale");
CogSubsystem.AddWindow<FCogEngineWindow_TimeScale>("Engine.Time Scale");
CogWindowManager.AddWindow<FCogEngineWindow_Transform>("Engine.Transform");
CogSubsystem.AddWindow<FCogEngineWindow_Transform>("Engine.Transform");
//---------------------------------------
// Abilities
//---------------------------------------
CogWindowManager.AddWindow<FCogAbilityWindow_Abilities>("Gameplay.Abilities");
CogSubsystem.AddWindow<FCogAbilityWindow_Abilities>("Gameplay.Abilities");
CogWindowManager.AddWindow<FCogAbilityWindow_Attributes>("Gameplay.Attributes");
CogSubsystem.AddWindow<FCogAbilityWindow_Attributes>("Gameplay.Attributes");
CogWindowManager.AddWindow<FCogAbilityWindow_BlockedTags>("Gameplay.Blocking Tags");
CogSubsystem.AddWindow<FCogAbilityWindow_BlockedTags>("Gameplay.Blocking Tags");
CogWindowManager.AddWindow<FCogEngineWindow_Cheats>("Gameplay.Cheats");
CogSubsystem.AddWindow<FCogEngineWindow_Cheats>("Gameplay.Cheats");
CogWindowManager.AddWindow<FCogAbilityWindow_Effects>("Gameplay.Effects");
CogSubsystem.AddWindow<FCogAbilityWindow_Effects>("Gameplay.Effects");
CogWindowManager.AddWindow<FCogAbilityWindow_Pools>("Gameplay.Pools");
CogSubsystem.AddWindow<FCogAbilityWindow_Pools>("Gameplay.Pools");
CogWindowManager.AddWindow<FCogAbilityWindow_OwnedTags>("Gameplay.Owned Tags");
CogSubsystem.AddWindow<FCogAbilityWindow_OwnedTags>("Gameplay.Owned Tags");
CogWindowManager.AddWindow<FCogAbilityWindow_Tasks>("Gameplay.Tasks");
CogSubsystem.AddWindow<FCogAbilityWindow_Tasks>("Gameplay.Tasks");
CogWindowManager.AddWindow<FCogAbilityWindow_Tweaks>("Gameplay.Tweaks");
CogSubsystem.AddWindow<FCogAbilityWindow_Tweaks>("Gameplay.Tweaks");
//---------------------------------------
// AI
//---------------------------------------
CogWindowManager.AddWindow<FCogAIWindow_BehaviorTree>("AI.Behavior Tree");
CogSubsystem.AddWindow<FCogAIWindow_BehaviorTree>("AI.Behavior Tree");
CogWindowManager.AddWindow<FCogAIWindow_Blackboard>("AI.Blackboard");
CogSubsystem.AddWindow<FCogAIWindow_Blackboard>("AI.Blackboard");
//---------------------------------------
// Input
//---------------------------------------
CogWindowManager.AddWindow<FCogInputWindow_Actions>("Input.Actions");
CogSubsystem.AddWindow<FCogInputWindow_Actions>("Input.Actions");
CogWindowManager.AddWindow<FCogInputWindow_Gamepad>("Input.Gamepad");
CogSubsystem.AddWindow<FCogInputWindow_Gamepad>("Input.Gamepad");
}
+1 -1
View File
@@ -6,5 +6,5 @@ class UCogSubsystem;
namespace Cog
{
void COGALL_API AddAllWindows(UCogSubsystem& CogWindowManager);
void COGALL_API AddAllWindows(UCogSubsystem& CogSubsystem);
}