From 01e6619e86fef7535e4daa2381c4892b3bb4ad98 Mon Sep 17 00:00:00 2001 From: Arnaud Jamin Date: Mon, 6 Jan 2025 00:55:39 -0500 Subject: [PATCH] improve NetImgui integration --- .../Private/CogEngineWindow_NetImGui.cpp | 367 +++++++++++++----- .../Private/CogEngineWindow_Selection.cpp | 14 +- .../Public/CogEngineWindow_NetImGui.h | 52 ++- .../CogImgui/Private/CogImguiContext.cpp | 72 +++- .../CogImgui/Private/CogImguiWidget.cpp | 4 + .../Source/CogImgui/Public/CogImguiContext.h | 12 + .../CogWindow/Private/CogWindowManager.cpp | 56 ++- .../CogWindow/Private/CogWindowWidgets.cpp | 15 + .../CogWindow/Public/CogWindowManager.h | 13 +- .../CogWindow/Public/CogWindowWidgets.h | 3 + .../CogAll/Source/CogAll/Private/CogAll.cpp | 4 +- 11 files changed, 452 insertions(+), 160 deletions(-) diff --git a/Plugins/Cog/Source/CogEngine/Private/CogEngineWindow_NetImGui.cpp b/Plugins/Cog/Source/CogEngine/Private/CogEngineWindow_NetImGui.cpp index a0308fc..ae56af4 100644 --- a/Plugins/Cog/Source/CogEngine/Private/CogEngineWindow_NetImGui.cpp +++ b/Plugins/Cog/Source/CogEngine/Private/CogEngineWindow_NetImGui.cpp @@ -11,14 +11,14 @@ #include "NetImgui_Api.h" //-------------------------------------------------------------------------------------------------------------------------- -void FCogEngineWindow_NetImGui::Initialize() +void FCogEngineWindow_NetImgui::Initialize() { Super::Initialize(); - bHasMenu = true; - Config = GetConfig(); + + Config = GetConfig(); FCogWindowConsoleCommandManager::RegisterWorldConsoleCommand( - TEXT("Cog.NetImgui.ConnectTo"), + TEXT("Cog.NetImgui.Connect"), TEXT("Connect to NetImgui server"), GetWorld(), FCogWindowConsoleCommandDelegate::CreateLambda([this](const TArray& InArgs, UWorld* InWorld) @@ -27,7 +27,7 @@ void FCogEngineWindow_NetImGui::Initialize() })); FCogWindowConsoleCommandManager::RegisterWorldConsoleCommand( - TEXT("Cog.NetImgui.ConnectFrom"), + TEXT("Cog.NetImgui.Listen"), TEXT("Listen for NetImgui server connection"), GetWorld(), FCogWindowConsoleCommandDelegate::CreateLambda([this](const TArray& InArgs, UWorld* InWorld) @@ -43,121 +43,129 @@ void FCogEngineWindow_NetImGui::Initialize() { Disconnect(); })); + + FCogWindowConsoleCommandManager::RegisterWorldConsoleCommand( + TEXT("Cog.NetImgui.RunServer"), + TEXT("Run NetImgui server"), + GetWorld(), + FCogWindowConsoleCommandDelegate::CreateLambda([this](const TArray& InArgs, UWorld* InWorld) + { + RunServer(); + })); + + FCogWindowConsoleCommandManager::RegisterWorldConsoleCommand( + TEXT("Cog.NetImgui.CloseServer"), + TEXT("Close NetImgui server"), + GetWorld(), + FCogWindowConsoleCommandDelegate::CreateLambda([this](const TArray& InArgs, UWorld* InWorld) + { + CloseServer(); + })); } //-------------------------------------------------------------------------------------------------------------------------- -void FCogEngineWindow_NetImGui::Shutdown() +void FCogEngineWindow_NetImgui::Shutdown() { - if (NetImgui::IsConnected()) + if (NetImgui::IsConnected() || NetImgui::IsConnectionPending()) { - ImGui::TextUnformatted("Status: Connected"); - if (ImGui::Button("Disconnect")) - { - NetImgui::Disconnect(); - } - } - else if (NetImgui::IsConnectionPending()) - { - ImGui::TextUnformatted("Status: Waiting Server"); - if (ImGui::Button("Cancel")) - { - NetImgui::Disconnect(); - } + NetImgui::Disconnect(); } + + CloseServer(); } //-------------------------------------------------------------------------------------------------------------------------- -void FCogEngineWindow_NetImGui::ResetConfig() +void FCogEngineWindow_NetImgui::ResetConfig() { Super::ResetConfig(); Config->Reset(); } //-------------------------------------------------------------------------------------------------------------------------- -void FCogEngineWindow_NetImGui::RenderHelp() +void FCogEngineWindow_NetImgui::RenderHelp() { - ImGui::Text(""); + ImGui::Text("This window manage the connection to the NetImgui server." + "See https://github.com/sammyfreg/netImgui for more info."); } //-------------------------------------------------------------------------------------------------------------------------- -void FCogEngineWindow_NetImGui::RenderTick(float DeltaTime) +void FCogEngineWindow_NetImgui::RenderTick(float DeltaTime) { //------------------------------------------------------ // Before auto connecting, wait for NetImgui startup, // which require imgui context to be initialized //------------------------------------------------------ - if (HasAlreadyTriedToConnectOnDedicatedServer == false - && Config->AutoConnectOnDedicatedServer - && UCogWindowManager::GetIsNetImguiInitialized() - && IsRunningDedicatedServer()) + if (HasAlreadyTriedToConnect == false && FCogImguiContext::GetIsNetImguiInitialized()) + { + const ENetMode NetMode = GetWorld()->GetNetMode(); + const bool ShouldConnect = (Config->AutoConnectOnDedicatedServer && NetMode == NM_DedicatedServer) + || (Config->AutoConnectOnListenServer && NetMode == NM_ListenServer) + || (Config->AutoConnectOnClient && NetMode == NM_Client) + || (Config->AutoConnectOnStandalone && NetMode == NM_Standalone); + + if (ShouldConnect) { - ConnectFrom(); - HasAlreadyTriedToConnectOnDedicatedServer = true; + if (Config->AutoRunServer) + { + ConnectTo(); + } + else + { + ConnectFrom(); + } } + + if (Config->AutoRunServer) + { + RunServer(); + } + + HasAlreadyTriedToConnect = true; + } } //-------------------------------------------------------------------------------------------------------------------------- -void FCogEngineWindow_NetImGui::RenderContent() +void FCogEngineWindow_NetImgui::RenderContent() { Super::RenderContent(); #if NETIMGUI_ENABLED - if (ImGui::BeginMenuBar()) - { - if (ImGui::BeginMenu("Settings")) - { - { - static char Buffer[256] = ""; - ImStrncpy(Buffer, TCHAR_TO_ANSI(*Config->ServerName), IM_ARRAYSIZE(Buffer)); - if (ImGui::InputText("Server Name", Buffer, IM_ARRAYSIZE(Buffer))) - { - Config->ServerName = FString(Buffer); - } - } - ImGui::InputInt("Server Port", &Config->ServerPort); - - ImGui::Separator(); - - { - static char Buffer[256] = ""; - ImStrncpy(Buffer, TCHAR_TO_ANSI(*Config->ClientName), IM_ARRAYSIZE(Buffer)); - if (ImGui::InputText("Client Name", Buffer, IM_ARRAYSIZE(Buffer))) - { - Config->ClientName = FString(Buffer); - } - } - ImGui::InputInt("Client Port", &Config->ClientPort); - - ImGui::Separator(); - ImGui::Checkbox("Auto Listen On Dedicated Server", &Config->AutoConnectOnDedicatedServer); - - ImGui::EndMenu(); - } - - ImGui::EndMenuBar(); - } - + //---------------------------------------- + // Status + //---------------------------------------- if (NetImgui::IsConnected()) { ImGui::TextUnformatted("Status: Connected"); - if (ImGui::Button("Disconnect")) + } + else if (NetImgui::IsConnectionPending()) + { + ImGui::TextUnformatted("Status: Waiting Server"); + } + else + { + ImGui::TextUnformatted("Status: Not Connected"); + } + + //---------------------------------------- + // Connection buttons + //---------------------------------------- + if (NetImgui::IsConnected()) + { + if (ImGui::Button("Disconnect", ImVec2(ImGui::GetContentRegionAvail().x, 0))) { NetImgui::Disconnect(); } } else if (NetImgui::IsConnectionPending()) { - ImGui::TextUnformatted("Status: Waiting Server"); - if (ImGui::Button("Cancel")) + if (ImGui::Button("Cancel Connection", ImVec2(ImGui::GetContentRegionAvail().x, 0))) { NetImgui::Disconnect(); } } - else // No connection + else { - ImGui::TextUnformatted("Status: Not Connected"); - if (ImGui::Button("Connect", ImVec2(ImGui::GetContentRegionAvail().x, 0))) { ConnectTo(); @@ -177,55 +185,238 @@ void FCogEngineWindow_NetImGui::RenderContent() } } + //---------------------------------------- + // Run/Close server button + //---------------------------------------- + if (FPlatformProcess::IsProcRunning(ServerProcess)) + { + if (ImGui::Button("Close Server", ImVec2(ImGui::GetContentRegionAvail().x, 0))) + { + CloseServer(); + } + if (ImGui::IsItemHovered()) + { + ImGui::SetTooltip("Close the NetImgui server executable."); + } + } + else + { + if (ImGui::Button("Run Server", ImVec2(ImGui::GetContentRegionAvail().x, 0))) + { + RunServer(); + } + if (ImGui::IsItemHovered()) + { + ImGui::SetTooltip("Run the NetImgui server executable."); + } + } + + //---------------------------------------- + // Settings + //---------------------------------------- + if (ImGui::CollapsingHeader("Settings", ImGuiTreeNodeFlags_DefaultOpen)) + { + FCogWindowWidgets::SetNextItemToShortWidth(); + FCogWindowWidgets::InputText("Server Address", Config->ServerAddress); + if (ImGui::IsItemHovered()) + { + ImGui::SetTooltip("NetImgui server application address."); + } + + FCogWindowWidgets::SetNextItemToShortWidth(); + ImGui::InputInt("Server Port", &Config->ServerPort); + if (ImGui::IsItemHovered()) + { + ImGui::SetTooltip("Port of the NetImgui Server application to connect to."); + } + + FCogWindowWidgets::SetNextItemToShortWidth(); + FCogWindowWidgets::InputText("Client Name", Config->ClientName); + if (ImGui::IsItemHovered()) + { + ImGui::SetTooltip("Client name displayed in the server's clients list."); + } + + FCogWindowWidgets::SetNextItemToShortWidth(); + ImGui::InputInt("Client Port", &Config->ClientPort); + if (ImGui::IsItemHovered()) + { + ImGui::SetTooltip("Port this client should wait for connection from server application."); + } + + ImGui::Checkbox("Auto Connect on Dedicated Server", &Config->AutoConnectOnDedicatedServer); + if (ImGui::IsItemHovered()) + { + ImGui::SetTooltip("Automatically connect to the NetImgui server when launching on dedicated server mode."); + } + + ImGui::Checkbox("Auto Connect on Listen Server", &Config->AutoConnectOnListenServer); + if (ImGui::IsItemHovered()) + { + ImGui::SetTooltip("Automatically connect to the NetImgui server when launching on listen server mode."); + } + + ImGui::Checkbox("Auto Connect on Client", &Config->AutoConnectOnClient); + if (ImGui::IsItemHovered()) + { + ImGui::SetTooltip("Automatically connect to the NetImgui server when launching on client mode."); + } + + ImGui::Checkbox("Auto Connect on Standalone", &Config->AutoConnectOnStandalone); + if (ImGui::IsItemHovered()) + { + ImGui::SetTooltip("Automatically connect to the NetImgui server when launching on standlone mode."); + } + + ImGui::Checkbox("Auto Run Server", &Config->AutoRunServer); + if (ImGui::IsItemHovered()) + { + ImGui::SetTooltip("Automatically run the NetImgui server executable at startup."); + } + + FCogWindowWidgets::SetNextItemToShortWidth(); + FCogWindowWidgets::InputText("Server Exe Path", Config->ServerExePath); + if (ImGui::IsItemHovered()) + { + ImGui::SetTooltip("Path to NetImgui server executable path. Used to automatically run the NetImgui server executable."); + } + + FCogWindowWidgets::SetNextItemToShortWidth(); + FCogWindowWidgets::InputText("Server Exe Args", Config->ServerExeArgs); + if (ImGui::IsItemHovered()) + { + ImGui::SetTooltip("Argument used when launching the NetImgui server executable."); + } + } #endif // #if NETIMGUI_ENABLED } + //-------------------------------------------------------------------------------------------------------------------------- -void FCogEngineWindow_NetImGui::ConnectTo() +FString FCogEngineWindow_NetImgui::GetClientName() +{ + switch (GetWorld()->GetNetMode()) + { + case NM_Standalone: + return FString::Printf(TEXT("%s_%s"), *Config->ClientName, TEXT("Standalone")); + + case NM_DedicatedServer: + return FString::Printf(TEXT("%s_%s"), *Config->ClientName, TEXT("DedicatedServer")); + + case NM_ListenServer: + return FString::Printf(TEXT("%s_%s"), *Config->ClientName, TEXT("ListenServer")); + + case NM_Client: + return FString::Printf(TEXT("%s_%s"), *Config->ClientName, TEXT("Client")); + } + + return Config->ClientName; +} + + +//-------------------------------------------------------------------------------------------------------------------------- +void FCogEngineWindow_NetImgui::ConnectTo() { FCogImGuiContextScope ImGuiContextScope(GetOwner()->GetContext()); - UE_LOG(LogCogImGui, Verbose, TEXT("FCogEngineWindow_NetImGui::ConnectTo | Client:%s | Server:%s | ServerPort:%d"), - *Config->ClientName, - *Config->ServerName, + const FString ClientName = GetClientName(); + + UE_LOG(LogCogImGui, Verbose, TEXT("FCogEngineWindow_NetImgui::ConnectTo | ClientName:%s | ServerAddress:%s | ServerPort:%d"), + *ClientName, + *Config->ServerAddress, Config->ServerPort); - const auto clientName = StringCast(*Config->ClientName); - const auto serverName = StringCast(*Config->ServerName); - NetImgui::ConnectToApp(clientName.Get(), serverName.Get(), Config->ServerPort, nullptr, nullptr); + const auto clientName = StringCast(*ClientName); + const auto serverAddress = StringCast(*Config->ServerAddress); + NetImgui::ConnectToApp(clientName.Get(), serverAddress.Get(), Config->ServerPort, nullptr, nullptr); } //-------------------------------------------------------------------------------------------------------------------------- -void FCogEngineWindow_NetImGui::ConnectFrom() +void FCogEngineWindow_NetImgui::ConnectFrom() { FCogImGuiContextScope ImGuiContextScope(GetOwner()->GetContext()); - UE_LOG(LogCogImGui, Verbose, TEXT("FCogEngineWindow_NetImGui::ConnectFrom | Client:%s | ClientPort:%d"), - *Config->ClientName, + const FString ClientName = GetClientName(); + + UE_LOG(LogCogImGui, Verbose, TEXT("FCogEngineWindow_NetImgui::ConnectFrom | ClientName:%s | ClientPort:%d"), + *ClientName, Config->ClientPort); - const auto clientName = StringCast(*Config->ClientName); + const auto clientName = StringCast(*ClientName); NetImgui::ConnectFromApp(clientName.Get(), Config->ClientPort, nullptr, nullptr); + } //-------------------------------------------------------------------------------------------------------------------------- -void FCogEngineWindow_NetImGui::Disconnect() +void FCogEngineWindow_NetImgui::Disconnect() { FCogImGuiContextScope ImGuiContextScope(GetOwner()->GetContext()); - UE_LOG(LogCogImGui, Verbose, TEXT("FCogEngineWindow_NetImGui::Disconnect")); + UE_LOG(LogCogImGui, Verbose, TEXT("FCogEngineWindow_NetImgui::Disconnect")); NetImgui::Disconnect(); } //-------------------------------------------------------------------------------------------------------------------------- -void UCogEngineConfig_NetImGui::Reset() +void FCogEngineWindow_NetImgui::RunServer() +{ + if (FPlatformProcess::IsProcRunning(ServerProcess)) + { + return; + } + + if (Config->ServerExePath.IsEmpty()) + { + return; + } + + ServerProcess = FPlatformProcess::CreateProc( + *Config->ServerExePath, + *Config->ServerExeArgs, + true, + false, + false, + nullptr, + 0, + nullptr, + nullptr + ); +} + +//-------------------------------------------------------------------------------------------------------------------------- +void FCogEngineWindow_NetImgui::CloseServer() +{ + if (FPlatformProcess::IsProcRunning(ServerProcess) == false) + { + return; + } + + if (Config->ServerExePath.IsEmpty() == false) + { + FPlatformProcess::TerminateProc(ServerProcess); + } +} + +//-------------------------------------------------------------------------------------------------------------------------- +// Config +//-------------------------------------------------------------------------------------------------------------------------- +void UCogEngineWindowConfig_NetImgui::Reset() { Super::Reset(); #if NETIMGUI_ENABLED - ClientName = FString("cog"); - ServerName = FString("localhost"); + + ClientName = FString("Cog"); ClientPort = NetImgui::kDefaultClientPort; + AutoConnectOnDedicatedServer = true; + AutoConnectOnListenServer = false; + AutoConnectOnClient = false; + AutoConnectOnStandalone = false; + + ServerAddress = FString("127.0.0.1"); ServerPort = NetImgui::kDefaultServerPort; + ServerExePath = FString("C:\\NetImgui\\Server_Exe\\NetImguiServer.exe"); + ServerExeArgs = FString(""); + AutoRunServer = false; + #endif } diff --git a/Plugins/Cog/Source/CogEngine/Private/CogEngineWindow_Selection.cpp b/Plugins/Cog/Source/CogEngine/Private/CogEngineWindow_Selection.cpp index 7d70773..2a29fa6 100644 --- a/Plugins/Cog/Source/CogEngine/Private/CogEngineWindow_Selection.cpp +++ b/Plugins/Cog/Source/CogEngine/Private/CogEngineWindow_Selection.cpp @@ -139,7 +139,7 @@ void FCogEngineWindow_Selection::ActivateSelectionMode() bSelectionModeActive = true; bIsInputEnabledBeforeEnteringSelectionMode = GetOwner()->GetContext().GetEnableInput(); GetOwner()->GetContext().SetEnableInput(true); - GetOwner()->SetHideAllWindows(true); + GetOwner()->SetActivateSelectionMode(true); } //-------------------------------------------------------------------------------------------------------------------------- @@ -161,7 +161,7 @@ void FCogEngineWindow_Selection::DeactivateSelectionMode() //-------------------------------------------------------------------------------------------- GetOwner()->GetContext().SetEnableInput(bIsInputEnabledBeforeEnteringSelectionMode); - GetOwner()->SetHideAllWindows(false); + GetOwner()->SetActivateSelectionMode(false); } //-------------------------------------------------------------------------------------------------------------------------- @@ -254,7 +254,15 @@ void FCogEngineWindow_Selection::TickSelectionMode() AActor* HoveredActor = nullptr; FVector WorldOrigin, WorldDirection; - if (UGameplayStatics::DeprojectScreenToWorld(PlayerController, FCogImguiHelper::ToFVector2D(ImGui::GetMousePos() - ViewportPos), WorldOrigin, WorldDirection)) + + //----------------------------------------------------------------------------------------------- + // Do not use imgui mouse pos because when connected to NetImgui, the mouse position is invalid. + // See https://github.com/sammyfreg/netImgui/issues/61 + //----------------------------------------------------------------------------------------------- + //ImVec2 mousePos = ImGui::GetMousePos(); + ImVec2 mousePos = GetOwner()->GetContext().GetImguiMousePos(); + + if (UGameplayStatics::DeprojectScreenToWorld(PlayerController, FCogImguiHelper::ToFVector2D(mousePos - ViewportPos), WorldOrigin, WorldDirection)) { //-------------------------------------------------------------------------------------------------------- // Prioritize another actor than the selected actor unless we only touch the selected actor. diff --git a/Plugins/Cog/Source/CogEngine/Public/CogEngineWindow_NetImGui.h b/Plugins/Cog/Source/CogEngine/Public/CogEngineWindow_NetImGui.h index 8cd31db..9bc57af 100644 --- a/Plugins/Cog/Source/CogEngine/Public/CogEngineWindow_NetImGui.h +++ b/Plugins/Cog/Source/CogEngine/Public/CogEngineWindow_NetImGui.h @@ -3,11 +3,11 @@ #include "CoreMinimal.h" #include "CogCommonConfig.h" #include "CogWindow.h" -#include "CogEngineWindow_NetImGui.generated.h" +#include "CogEngineWindow_NetImgui.generated.h" -class UCogEngineConfig_NetImGui; +class UCogEngineWindowConfig_NetImgui; -class COGENGINE_API FCogEngineWindow_NetImGui : public FCogWindow +class COGENGINE_API FCogEngineWindow_NetImgui : public FCogWindow { typedef FCogWindow Super; @@ -35,16 +35,24 @@ protected: void TryStartup(); + void RunServer(); + + void CloseServer(); + private: - TWeakObjectPtr Config = nullptr; + FString GetClientName(); - bool HasAlreadyTriedToConnectOnDedicatedServer = false; + TObjectPtr Config = nullptr; + + bool HasAlreadyTriedToConnect = false; + + FProcHandle ServerProcess; }; //-------------------------------------------------------------------------------------------------------------------------- UCLASS(Config = Cog) -class UCogEngineConfig_NetImGui : public UCogCommonConfig +class UCogEngineWindowConfig_NetImgui : public UCogCommonConfig { GENERATED_BODY() @@ -53,17 +61,35 @@ public: virtual void Reset() override; UPROPERTY(Config) - FString ClientName = FString("cog"); - - UPROPERTY(Config) - FString ServerName = FString("localhost"); - - UPROPERTY(Config) - int32 ServerPort = 8888; + FString ClientName = FString("Cog"); UPROPERTY(Config) int32 ClientPort = 8889; UPROPERTY(Config) bool AutoConnectOnDedicatedServer = true; + + UPROPERTY(Config) + bool AutoConnectOnListenServer = false; + + UPROPERTY(Config) + bool AutoConnectOnClient = false; + + UPROPERTY(Config) + bool AutoConnectOnStandalone = false; + + UPROPERTY(Config) + FString ServerAddress = FString("127.0.0.1"); + + UPROPERTY(Config) + int32 ServerPort = 8888; + + UPROPERTY(Config) + FString ServerExePath = FString("C:\\NetImgui\\Server_Exe\\NetImguiServer.exe"); + + UPROPERTY(Config) + FString ServerExeArgs = FString(""); + + UPROPERTY(Config) + bool AutoRunServer = false; }; \ No newline at end of file diff --git a/Plugins/Cog/Source/CogImgui/Private/CogImguiContext.cpp b/Plugins/Cog/Source/CogImgui/Private/CogImguiContext.cpp index 2c13401..9c0b5fd 100644 --- a/Plugins/Cog/Source/CogImgui/Private/CogImguiContext.cpp +++ b/Plugins/Cog/Source/CogImgui/Private/CogImguiContext.cpp @@ -18,6 +18,7 @@ #include "imgui_internal.h" #include "implot.h" #include "Misc/EngineVersionComparison.h" +#include "NetImgui_Api.h" #include "TextureResource.h" #include "Widgets/SViewport.h" #include "Widgets/SWindow.h" @@ -51,6 +52,8 @@ FCogImGuiContextScope:: ImPlot::SetCurrentContext(PrevPlotContext); } +//-------------------------------------------------------------------------------------------------------------------------- +bool FCogImguiContext::bIsNetImguiInitialized = false; //-------------------------------------------------------------------------------------------------------------------------- void FCogImguiContext::Initialize() @@ -139,6 +142,14 @@ void FCogImguiContext::Initialize() DisplayMetrics.MonitorInfo.Add(monitorInfo); OnDisplayMetricsChanged(DisplayMetrics); } + +#if NETIMGUI_ENABLED + if (bIsNetImguiInitialized == false) + { + NetImgui::Startup(); + bIsNetImguiInitialized = true; + } +#endif } //-------------------------------------------------------------------------------------------------------------------------- @@ -146,6 +157,17 @@ void FCogImguiContext::Shutdown() { FCogImGuiContextScope ImGuiContextScope(ImGuiContext, PlotContext); + //------------------------------------------------------------------ + // NetImgui must be shutdown before imgui as it uses context hooks + //------------------------------------------------------------------ +#if NETIMGUI_ENABLED + if (bIsNetImguiInitialized) + { + NetImgui::Shutdown(); + bIsNetImguiInitialized = false; + } +#endif + if (ImGuiViewport* MainViewport = ImGui::GetMainViewport()) { if (const FCogImGuiViewportData* ViewportData = static_cast(MainViewport->PlatformUserData)) @@ -287,7 +309,7 @@ bool FCogImguiContext::BeginFrame(float InDeltaTime) //------------------------------------------------------------------------------------------------------- // //------------------------------------------------------------------------------------------------------- - if (bEnableInput) + if (bEnableInput || NetImgui::IsConnected()) { IO.ConfigFlags &= ~ImGuiConfigFlags_NoMouse; } @@ -296,7 +318,7 @@ bool FCogImguiContext::BeginFrame(float InDeltaTime) IO.ConfigFlags |= ImGuiConfigFlags_NoMouse; } - if (MainWidget != nullptr) + if (MainWidget != nullptr && FSlateApplication::IsInitialized()) { const bool bHasMouse = (IO.ConfigFlags & ImGuiConfigFlags_NoMouse) == 0; const bool bUpdateMouseMouseCursor = (IO.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) == 0; @@ -305,18 +327,10 @@ bool FCogImguiContext::BeginFrame(float InDeltaTime) MainWidget->SetCursor(FCogImguiInputHelper::ToSlateMouseCursor(ImGui::GetMouseCursor())); } - if (FSlateApplication::IsInitialized()) + if (bEnableInput) { - const FVector2D& MousePosition = FSlateApplication::Get().GetCursorPos(); - if (IO.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) - { - IO.AddMousePosEvent(MousePosition.X, MousePosition.Y); - } - else - { - const FVector2D TransformedMousePosition = MousePosition - MainWidget->GetTickSpaceGeometry().GetAbsolutePosition(); - IO.AddMousePosEvent(TransformedMousePosition.X, TransformedMousePosition.Y); - } + const ImVec2 mousePos = GetImguiMousePos(); + IO.AddMousePosEvent(mousePos.x, mousePos.y); } } @@ -334,18 +348,37 @@ bool FCogImguiContext::BeginFrame(float InDeltaTime) } ImGui::NewFrame(); + //if (NetImgui::NewFrame(true) == false) + //{ + // return false; + //} //DrawDebug(); return true; } +//-------------------------------------------------------------------------------------------------------------------------- +ImVec2 FCogImguiContext::GetImguiMousePos() +{ + const FVector2D& MousePosition = FSlateApplication::Get().GetCursorPos(); + if (ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_ViewportsEnable) + { + return ImVec2(MousePosition.X, MousePosition.Y); + } + + const FVector2D TransformedMousePosition = MousePosition - MainWidget->GetTickSpaceGeometry().GetAbsolutePosition(); + return ImVec2(TransformedMousePosition.X, TransformedMousePosition.Y); +} + //-------------------------------------------------------------------------------------------------------------------------- void FCogImguiContext::EndFrame() { FCogImGuiContextScope ImGuiContextScope(ImGuiContext, PlotContext); ImGui::Render(); + //NetImgui::EndFrame(); + ImGui_RenderWindow(ImGui::GetMainViewport(), nullptr); ImGui::UpdatePlatformWindows(); @@ -862,3 +895,16 @@ ULocalPlayer* FCogImguiContext::GetLocalPlayer() const ULocalPlayer* LocalPlayer = World->GetFirstLocalPlayerFromController(); return LocalPlayer; } + +//-------------------------------------------------------------------------------------------------------------------------- +bool FCogImguiContext::GetSkipRendering() const +{ + return bSkipRendering; +} + +//-------------------------------------------------------------------------------------------------------------------------- +void FCogImguiContext::SetSkipRendering(bool Value) +{ + bSkipRendering = Value; +} + diff --git a/Plugins/Cog/Source/CogImgui/Private/CogImguiWidget.cpp b/Plugins/Cog/Source/CogImgui/Private/CogImguiWidget.cpp index e1b24ef..13c3474 100644 --- a/Plugins/Cog/Source/CogImgui/Private/CogImguiWidget.cpp +++ b/Plugins/Cog/Source/CogImgui/Private/CogImguiWidget.cpp @@ -45,6 +45,10 @@ int32 SCogImguiWidget::OnPaint( const FWidgetStyle& WidgetStyle, bool bParentEnabled) const { + if (Context == nullptr || Context->GetSkipRendering()) + { + return LayerId; + } const FSlateRenderTransform Transform(FCogImguiHelper::RoundTranslation(AllottedGeometry.GetAccumulatedRenderTransform().GetTranslation() - FVector2d(DrawData.DisplayPos))); diff --git a/Plugins/Cog/Source/CogImgui/Public/CogImguiContext.h b/Plugins/Cog/Source/CogImgui/Public/CogImguiContext.h index a9bef0e..47bddc1 100644 --- a/Plugins/Cog/Source/CogImgui/Public/CogImguiContext.h +++ b/Plugins/Cog/Source/CogImgui/Public/CogImguiContext.h @@ -65,16 +65,26 @@ public: bool BeginFrame(float InDeltaTime); + void GetCursorPos(ImGuiIO& IO); + void EndFrame(); float GetDpiScale() const { return DpiScale; } void SetDPIScale(float Value); + bool GetSkipRendering() const; + + void SetSkipRendering(bool Value); + + ImVec2 GetImguiMousePos(); + TObjectPtr GetGameViewport() const { return GameViewport; } TSharedPtr GetMainWidget() const { return MainWidget; } + static bool GetIsNetImguiInitialized() { return bIsNetImguiInitialized; } + private: friend struct FCogImGuiContextScope; @@ -161,4 +171,6 @@ private: bool bWantCaptureMouse = false; float DpiScale = 1.f; + static bool bIsNetImguiInitialized; + }; diff --git a/Plugins/Cog/Source/CogWindow/Private/CogWindowManager.cpp b/Plugins/Cog/Source/CogWindow/Private/CogWindowManager.cpp index 1db0303..6aa4435 100644 --- a/Plugins/Cog/Source/CogWindow/Private/CogWindowManager.cpp +++ b/Plugins/Cog/Source/CogWindow/Private/CogWindowManager.cpp @@ -23,8 +23,6 @@ FString UCogWindowManager::LoadLayoutCommand = TEXT("Cog.LoadLayout"); FString UCogWindowManager::SaveLayoutCommand = TEXT("Cog.SaveLayout"); FString UCogWindowManager::ResetLayoutCommand = TEXT("Cog.ResetLayout"); -bool UCogWindowManager::IsNetImguiInitialized = false; - //-------------------------------------------------------------------------------------------------------------------------- UCogWindowManager::UCogWindowManager() { @@ -132,15 +130,6 @@ void UCogWindowManager::InitializeInternal() } })); - -#if NETIMGUI_ENABLED - if (IsNetImguiInitialized == false) - { - NetImgui::Startup(); - IsNetImguiInitialized = true; - } -#endif - IsInitialized = true; } @@ -159,17 +148,6 @@ void UCogWindowManager::Shutdown() Window->PreSaveConfig(); } - //------------------------------------------------------------------ - // NetImgui must be shutdown before imgui as it uses context hooks - //------------------------------------------------------------------ -#if NETIMGUI_ENABLED - if (IsNetImguiInitialized) - { - NetImgui::Shutdown(); - IsNetImguiInitialized = false; - } -#endif - //------------------------------------------------------------------ // Destroy ImGui before destroying the windows to make sure // imgui serialize their visibility state in imgui.ini @@ -223,6 +201,9 @@ void UCogWindowManager::Tick(float DeltaTime) Window->GameTick(DeltaTime); } + const bool shouldSkipRendering = NetImgui::IsConnected() && bIsSelectionModeActive == false; + Context.SetSkipRendering(shouldSkipRendering); + if (Context.BeginFrame(DeltaTime)) { Render(DeltaTime); @@ -246,19 +227,25 @@ void UCogWindowManager::Render(float DeltaTime) FCogWindowWidgets::PushStyleCompact(); } - if (bHideAllWindows == false) + //---------------------------------------------------------------------- + // There is no need to have Imgui input enabled if the imgui rendering + // is only done on the NetImgui server. So we disable imgui input. + //---------------------------------------------------------------------- + if (Context.GetEnableInput() && NetImgui::IsConnected() && bIsSelectionModeActive == false) { - if (Context.GetEnableInput()) - { - RenderMainMenu(); - } + Context.SetEnableInput(false); + } + + if ((Context.GetEnableInput() || NetImgui::IsConnected()) && bIsSelectionModeActive == false) + { + RenderMainMenu(); } for (FCogWindow* Window : Windows) { Window->RenderTick(DeltaTime); - if (Window->GetIsVisible() && bHideAllWindows == false) + if (Window->GetIsVisible() && bIsSelectionModeActive == false) { if (SettingsWindow->GetSettingsConfig()->bTransparentMode) { @@ -314,10 +301,15 @@ FCogWindow* UCogWindowManager::FindWindowByID(const ImGuiID ID) } //-------------------------------------------------------------------------------------------------------------------------- -void UCogWindowManager::SetHideAllWindows(const bool Value) +void UCogWindowManager::SetActivateSelectionMode(const bool Value) { - HideAllWindowsCounter = FMath::Max(HideAllWindowsCounter + (Value ? +1 : -1), 0); - bHideAllWindows = HideAllWindowsCounter > 0; + SelectionModeActiveCounter = FMath::Max(SelectionModeActiveCounter + (Value ? 1 : -1), 0); + bIsSelectionModeActive = SelectionModeActiveCounter > 0; + + if (bIsSelectionModeActive) + { + Context.SetEnableInput(true); + } } //-------------------------------------------------------------------------------------------------------------------------- @@ -429,7 +421,6 @@ void UCogWindowManager::RenderMainMenu() ImGui::Separator(); RenderMenuItem(*LayoutsWindow, "Layouts"); - RenderMenuItem(*SettingsWindow, "Settings"); if (ImGui::BeginMenu("Spacing")) @@ -880,4 +871,3 @@ void UCogWindowManager::DisableInputMode() UE_LOG(LogCogImGui, Verbose, TEXT("UCogWindowManager::DisableInputMode")); Context.SetEnableInput(false); } - diff --git a/Plugins/Cog/Source/CogWindow/Private/CogWindowWidgets.cpp b/Plugins/Cog/Source/CogWindow/Private/CogWindowWidgets.cpp index 1fd1d4b..00a52db 100644 --- a/Plugins/Cog/Source/CogWindow/Private/CogWindowWidgets.cpp +++ b/Plugins/Cog/Source/CogWindow/Private/CogWindowWidgets.cpp @@ -1029,4 +1029,19 @@ void FCogWindowWidgets::SmallButton(const char* Text, const ImVec4& Color) ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(Color.x, Color.y, Color.z, Color.w * 1.0f)); ImGui::SmallButton(Text); ImGui::PopStyleColor(3); +} + +//-------------------------------------------------------------------------------------------------------------------------- +bool FCogWindowWidgets::InputText(const char* Text, FString& Value) +{ + static char Buffer[256] = ""; + ImStrncpy(Buffer, TCHAR_TO_ANSI(*Value), IM_ARRAYSIZE(Buffer)); + + bool result = ImGui::InputText(Text, Buffer, IM_ARRAYSIZE(Buffer)); + if (result) + { + Value = FString(Buffer); + } + + return result; } \ No newline at end of file diff --git a/Plugins/Cog/Source/CogWindow/Public/CogWindowManager.h b/Plugins/Cog/Source/CogWindow/Public/CogWindowManager.h index c0a058b..a0695e1 100644 --- a/Plugins/Cog/Source/CogWindow/Public/CogWindowManager.h +++ b/Plugins/Cog/Source/CogWindow/Public/CogWindowManager.h @@ -36,6 +36,7 @@ public: virtual void Tick(float DeltaTime); + virtual void AddWindow(FCogWindow* Window, const FString& Name, bool AddToMainMenu = true); template @@ -51,9 +52,9 @@ public: virtual void SaveLayout(int32 LayoutIndex); - virtual bool GetHideAllWindows() const { return bHideAllWindows; } + virtual bool GetHideAllWindows() const { return bIsSelectionModeActive; } - virtual void SetHideAllWindows(bool Value); + virtual void SetActivateSelectionMode(bool Value); virtual void ResetAllWindowsConfig(); @@ -79,8 +80,6 @@ public: static void SortCommands(UPlayerInput* PlayerInput); - static bool GetIsNetImguiInitialized() { return IsNetImguiInitialized; } - protected: friend class FCogWindow_Layouts; @@ -156,13 +155,11 @@ protected: int32 LayoutToLoad = -1; - int32 HideAllWindowsCounter = 0; + int32 SelectionModeActiveCounter = 0; - bool bHideAllWindows = false; + bool bIsSelectionModeActive = false; bool IsInitialized = false; - - static bool IsNetImguiInitialized; }; //-------------------------------------------------------------------------------------------------------------------------- diff --git a/Plugins/Cog/Source/CogWindow/Public/CogWindowWidgets.h b/Plugins/Cog/Source/CogWindow/Public/CogWindowWidgets.h index e576f0e..4bb9b40 100644 --- a/Plugins/Cog/Source/CogWindow/Public/CogWindowWidgets.h +++ b/Plugins/Cog/Source/CogWindow/Public/CogWindowWidgets.h @@ -104,6 +104,9 @@ public: static void ActorFrame(const AActor& Actor); static void SmallButton(const char* Text, const ImVec4& Color); + + static bool InputText(const char* Text, FString& Value); + }; template diff --git a/Plugins/CogAll/Source/CogAll/Private/CogAll.cpp b/Plugins/CogAll/Source/CogAll/Private/CogAll.cpp index a81a94f..6425a08 100644 --- a/Plugins/CogAll/Source/CogAll/Private/CogAll.cpp +++ b/Plugins/CogAll/Source/CogAll/Private/CogAll.cpp @@ -18,8 +18,8 @@ #include "CogEngineWindow_Inspector.h" #include "CogEngineWindow_LogCategories.h" #include "CogEngineWindow_Metrics.h" +#include "CogEngineWindow_NetImgui.h" #include "CogEngineWindow_NetEmulation.h" -#include "CogEngineWindow_NetImGui.h" #include "CogEngineWindow_OutputLog.h" #include "CogEngineWindow_Plots.h" #include "CogEngineWindow_Scalability.h" @@ -70,7 +70,7 @@ void Cog::AddAllWindows(UCogWindowManager& CogWindowManager) CogWindowManager.AddWindow("Engine.Net Emulation"); - CogWindowManager.AddWindow("Engine.NetImGui"); + CogWindowManager.AddWindow("Engine.Net ImGui"); CogWindowManager.AddWindow("Engine.Output Log");