diff --git a/Plugins/Cog/Source/CogDebug/Private/CogDebug.cpp b/Plugins/Cog/Source/CogDebug/Private/CogDebug.cpp index 97696bf..973ad8a 100644 --- a/Plugins/Cog/Source/CogDebug/Private/CogDebug.cpp +++ b/Plugins/Cog/Source/CogDebug/Private/CogDebug.cpp @@ -106,18 +106,35 @@ int32 FCogDebug::GetPieSessionId() #endif } + //-------------------------------------------------------------------------------------------------------------------------- void FCogDebug::SetSelection(const UWorld* World, AActor* Value) { Selection[GetPieSessionId()] = Value; - if (World != nullptr && World->GetNetMode() == NM_Client) + ReplicateSelection(World, Value); +} + +//-------------------------------------------------------------------------------------------------------------------------- +void FCogDebug::ReplicateSelection(const UWorld* World, AActor* Value) +{ + if (World == nullptr) { - if (ACogDebugReplicator* Replicator = ACogDebugReplicator::GetLocalReplicator(*World)) - { - Replicator->Server_SetSelection(Value); - } + return; } + + ACogDebugReplicator* Replicator = ACogDebugReplicator::GetLocalReplicator(*World); + if (Replicator == nullptr) + { + return; + } + + if (Replicator->HasAuthority()) + { + return; + } + + Replicator->Server_SetSelection(Value, Settings.ReplicateSelection); } //-------------------------------------------------------------------------------------------------------------------------- diff --git a/Plugins/Cog/Source/CogDebug/Private/CogDebugReplicator.cpp b/Plugins/Cog/Source/CogDebug/Private/CogDebugReplicator.cpp index f0ea6a6..a2a95d2 100644 --- a/Plugins/Cog/Source/CogDebug/Private/CogDebugReplicator.cpp +++ b/Plugins/Cog/Source/CogDebug/Private/CogDebugReplicator.cpp @@ -82,7 +82,7 @@ void ACogDebugReplicator::BeginPlay() if (OwnerPlayerController != nullptr && OwnerPlayerController->IsLocalController()) { Server_RequestAllCategoriesVerbosity(); - Server_SetSelection(FCogDebug::GetSelection()); + Server_SetSelection(FCogDebug::GetSelection(), FCogDebug::Settings.ReplicateSelection); Server_SetIsFilteringBySelection(FCogDebug::GetIsFilteringBySelection()); } } @@ -210,12 +210,22 @@ void ACogDebugReplicator::Server_SetIsFilteringBySelection_Implementation(bool V } //-------------------------------------------------------------------------------------------------------------------------- -void ACogDebugReplicator::Server_SetSelection_Implementation(AActor* Value) +void ACogDebugReplicator::Server_SetSelection_Implementation(AActor* Value, bool ForceSelection) { #if !UE_BUILD_SHIPPING ServerSelection = Value; + if (ForceSelection) + { + FCogDebug::SetSelection(GetWorld(), Value); + } + else + { + FCogDebug::SetSelection(GetWorld(), nullptr); + } + + #endif // !UE_BUILD_SHIPPING } diff --git a/Plugins/Cog/Source/CogDebug/Public/CogDebug.h b/Plugins/Cog/Source/CogDebug/Public/CogDebug.h index 3d8d5c8..7a4b517 100644 --- a/Plugins/Cog/Source/CogDebug/Public/CogDebug.h +++ b/Plugins/Cog/Source/CogDebug/Public/CogDebug.h @@ -29,6 +29,9 @@ struct FCogDebugSettings UPROPERTY(Config) bool bIsFilteringBySelection = true; + UPROPERTY(Config) + bool ReplicateSelection = true; + UPROPERTY(Config) bool Persistent = false; @@ -429,9 +432,11 @@ private: static int32 GetPieSessionId(); - static constexpr uint32 MaxPie = 16; + static void ReplicateSelection(const UWorld* World, AActor* Value); static bool IsDebugActiveForObject_Internal(const UObject* WorldContextObject, const AActor* InSelection, bool InIsFilteringBySelection); + static constexpr uint32 MaxPie = 16; + static TWeakObjectPtr Selection[MaxPie]; }; diff --git a/Plugins/Cog/Source/CogDebug/Public/CogDebugReplicator.h b/Plugins/Cog/Source/CogDebug/Public/CogDebugReplicator.h index 0076af6..8ddcc1a 100644 --- a/Plugins/Cog/Source/CogDebug/Public/CogDebugReplicator.h +++ b/Plugins/Cog/Source/CogDebug/Public/CogDebugReplicator.h @@ -88,7 +88,7 @@ public: AActor* GetServerSelection() const { return ServerSelection.Get(); } UFUNCTION(Server, Reliable) - void Server_SetSelection(AActor* Value); + void Server_SetSelection(AActor* Value, bool ForceSelection); bool IsServerFilteringBySelection() const { return bIsServerFilteringBySelection; } diff --git a/Plugins/Cog/Source/CogEngine/Private/CogEngineWindow_CollisionTester.cpp b/Plugins/Cog/Source/CogEngine/Private/CogEngineWindow_CollisionTester.cpp index 497909e..d4abc26 100644 --- a/Plugins/Cog/Source/CogEngine/Private/CogEngineWindow_CollisionTester.cpp +++ b/Plugins/Cog/Source/CogEngine/Private/CogEngineWindow_CollisionTester.cpp @@ -84,7 +84,11 @@ void FCogEngineWindow_CollisionTester::RenderContent() } ImGui::SetNextItemWidth(-1); - FCogWindowWidgets::MenuActorsCombo("CollisionTesters", *GetWorld(), ACogEngineCollisionTester::StaticClass()); + AActor* NewSelection = nullptr; + if (FCogWindowWidgets::MenuActorsCombo("CollisionTesters", NewSelection, *GetWorld(), ACogEngineCollisionTester::StaticClass())) + { + FCogDebug::SetSelection(GetWorld(), NewSelection); + } ImGui::EndMenuBar(); } diff --git a/Plugins/Cog/Source/CogEngine/Private/CogEngineWindow_Selection.cpp b/Plugins/Cog/Source/CogEngine/Private/CogEngineWindow_Selection.cpp index 2a29fa6..e9b00ad 100644 --- a/Plugins/Cog/Source/CogEngine/Private/CogEngineWindow_Selection.cpp +++ b/Plugins/Cog/Source/CogEngine/Private/CogEngineWindow_Selection.cpp @@ -2,6 +2,7 @@ #include "CogDebug.h" #include "CogEngineHelper.h" +#include "CogEngineReplicator.h" #include "CogEngineWindow_ImGui.h" #include "CogImguiHelper.h" #include "CogImguiInputHelper.h" @@ -204,7 +205,14 @@ void FCogEngineWindow_Selection::RenderContent() if (ImGui::BeginMenu("Options")) { ImGui::Checkbox("Save selection", &Config->bReapplySelection); - ImGui::Checkbox("Actor Name Use Label", &FCogDebug::Settings.ActorNameUseLabel); + ImGui::SetItemTooltip("Should the last selection be saved and reapplied on startup."); + + ImGui::Checkbox("Actor Name Use Label", &FCogDebug::Settings.ActorNameUseLabel); + ImGui::SetItemTooltip("Should actor names be displayed using their label. Labels are more readable."); + + ImGui::Checkbox("Replicate Selection", &FCogDebug::Settings.ReplicateSelection); + ImGui::SetItemTooltip("Should the client replicate its actor selection to the server."); + ImGui::EndMenu(); } @@ -219,7 +227,14 @@ void FCogEngineWindow_Selection::RenderContent() //-------------------------------------------------------------------------------------------------------------------------- bool FCogEngineWindow_Selection::DrawSelectionCombo() { - return FCogWindowWidgets::ActorsListWithFilters(*GetWorld(), ActorClasses, Config->SelectedClassIndex, &Filter, GetLocalPlayerPawn()); + AActor* NewSelection = nullptr; + const bool result = FCogWindowWidgets::ActorsListWithFilters(NewSelection, *GetWorld(), ActorClasses, Config->SelectedClassIndex, &Filter, GetLocalPlayerPawn()); + if (result) + { + SetGlobalSelection(NewSelection); + } + + return result; } //-------------------------------------------------------------------------------------------------------------------------- @@ -353,7 +368,8 @@ void FCogEngineWindow_Selection::RenderMainMenuWidget(int32 SubWidgetIndex, floa else if (SubWidgetIndex == 1) { ImGui::SetNextItemWidth(Width); - FCogWindowWidgets::MenuActorsCombo("MenuActorSelection", *GetWorld(), ActorClasses, Config->SelectedClassIndex, &Filter, GetLocalPlayerPawn(), [this](AActor& Actor) { RenderActorContextMenu(Actor); }); + AActor* NewSelection = nullptr; + FCogWindowWidgets::MenuActorsCombo("MenuActorSelection", NewSelection, *GetWorld(), ActorClasses, Config->SelectedClassIndex, &Filter, GetLocalPlayerPawn(), [this](AActor& Actor) { RenderActorContextMenu(Actor); }); } else if (SubWidgetIndex == 2) { diff --git a/Plugins/Cog/Source/CogEngine/Public/CogEngineWindow_Selection.h b/Plugins/Cog/Source/CogEngine/Public/CogEngineWindow_Selection.h index 817efd4..d40fc94 100644 --- a/Plugins/Cog/Source/CogEngine/Public/CogEngineWindow_Selection.h +++ b/Plugins/Cog/Source/CogEngine/Public/CogEngineWindow_Selection.h @@ -75,7 +75,7 @@ protected: bool bSelectionModeActive = false; - bool bIsInputEnabledBeforeEnteringSelectionMode; + bool bIsInputEnabledBeforeEnteringSelectionMode = false; int32 WaitInputReleased = 0; diff --git a/Plugins/Cog/Source/CogWindow/Private/CogWindowWidgets.cpp b/Plugins/Cog/Source/CogWindow/Private/CogWindowWidgets.cpp index 00a52db..21244c5 100644 --- a/Plugins/Cog/Source/CogWindow/Private/CogWindowWidgets.cpp +++ b/Plugins/Cog/Source/CogWindow/Private/CogWindowWidgets.cpp @@ -734,7 +734,7 @@ bool FCogWindowWidgets::CollisionProfileChannels(int32& Channels) } //-------------------------------------------------------------------------------------------------------------------------- -bool FCogWindowWidgets::ActorsListWithFilters(const UWorld& World, const TArray>& ActorClasses, int32& SelectedActorClassIndex, ImGuiTextFilter* Filter, const APawn* LocalPlayerPawn, const FCogWindowActorContextMenuFunction& ContextMenuFunction) +bool FCogWindowWidgets::ActorsListWithFilters(AActor*& NewSelection, const UWorld& World, const TArray>& ActorClasses, int32& SelectedActorClassIndex, ImGuiTextFilter* Filter, const APawn* LocalPlayerPawn, const FCogWindowActorContextMenuFunction& ContextMenuFunction) { TSubclassOf SelectedClass = AActor::StaticClass(); if (ActorClasses.IsValidIndex(SelectedActorClassIndex)) @@ -783,14 +783,14 @@ bool FCogWindowWidgets::ActorsListWithFilters(const UWorld& World, const TArray< // Actor List //------------------------ ImGui::BeginChild("ActorsList", ImVec2(-1, -1), false); - const bool SelectionChanged = ActorsList(World, SelectedClass, Filter, LocalPlayerPawn, ContextMenuFunction); + const bool SelectionChanged = ActorsList(NewSelection, World, SelectedClass, Filter, LocalPlayerPawn, ContextMenuFunction); ImGui::EndChild(); return SelectionChanged; } //-------------------------------------------------------------------------------------------------------------------------- -bool FCogWindowWidgets::ActorsList(const UWorld& World, const TSubclassOf ActorClass, const ImGuiTextFilter* Filter, const APawn* LocalPlayerPawn, const FCogWindowActorContextMenuFunction& ContextMenuFunction) +bool FCogWindowWidgets::ActorsList(AActor*& NewSelection, const UWorld& World, const TSubclassOf ActorClass, const ImGuiTextFilter* Filter, const APawn* LocalPlayerPawn, const FCogWindowActorContextMenuFunction& ContextMenuFunction) { TArray Actors; for (TActorIterator It(&World, ActorClass); It; ++It) @@ -813,8 +813,8 @@ bool FCogWindowWidgets::ActorsList(const UWorld& World, const TSubclassOf ActorClass, const FCogWindowActorContextMenuFunction& ContextMenuFunction) +bool FCogWindowWidgets::MenuActorsCombo(const char* StrID, AActor*& NewSelection, const UWorld& World, TSubclassOf ActorClass, const FCogWindowActorContextMenuFunction& ContextMenuFunction) { int32 SelectedActorClassIndex = 0; const TArray ActorClasses = { ActorClass }; AActor* Actor = nullptr; - return MenuActorsCombo(StrID, World, ActorClasses, SelectedActorClassIndex, nullptr, nullptr, ContextMenuFunction); + return MenuActorsCombo(StrID, NewSelection, World, ActorClasses, SelectedActorClassIndex, nullptr, nullptr, ContextMenuFunction); } //-------------------------------------------------------------------------------------------------------------------------- -bool FCogWindowWidgets::MenuActorsCombo(const char* StrID, const UWorld& World, const TArray>& ActorClasses, int32& SelectedActorClassIndex, ImGuiTextFilter* Filter, const APawn* LocalPlayerPawn, const FCogWindowActorContextMenuFunction& ContextMenuFunction) +bool FCogWindowWidgets::MenuActorsCombo(const char* StrID, AActor*& NewSelection, const UWorld& World, const TArray>& ActorClasses, int32& SelectedActorClassIndex, ImGuiTextFilter* Filter, const APawn* LocalPlayerPawn, const FCogWindowActorContextMenuFunction& ContextMenuFunction) { bool Result = false; ImGui::PushID(StrID); @@ -928,7 +928,7 @@ bool FCogWindowWidgets::MenuActorsCombo(const char* StrID, const UWorld& World, { ImGui::BeginChild("Child", ImVec2(Pos2.x - Pos1.x, GetFontWidth() * 40), false); - Result = ActorsListWithFilters(World, ActorClasses, SelectedActorClassIndex, Filter, LocalPlayerPawn, ContextMenuFunction); + Result = ActorsListWithFilters(NewSelection, World, ActorClasses, SelectedActorClassIndex, Filter, LocalPlayerPawn, ContextMenuFunction); if (Result) { ImGui::CloseCurrentPopup(); diff --git a/Plugins/Cog/Source/CogWindow/Public/CogWindowWidgets.h b/Plugins/Cog/Source/CogWindow/Public/CogWindowWidgets.h index 4bb9b40..344eb13 100644 --- a/Plugins/Cog/Source/CogWindow/Public/CogWindowWidgets.h +++ b/Plugins/Cog/Source/CogWindow/Public/CogWindowWidgets.h @@ -4,6 +4,8 @@ #include "imgui.h" #include "UObject/ReflectedTypeAccessors.h" +class AActor; +class APawn; class FEnumProperty; class UCollisionProfile; class UEnum; @@ -91,13 +93,13 @@ public: static bool CollisionProfileChannels(int32& Channels); - static bool MenuActorsCombo(const char* StrID, const UWorld& World, TSubclassOf ActorClass, const FCogWindowActorContextMenuFunction& ContextMenuFunction = nullptr); + static bool MenuActorsCombo(const char* StrID, AActor*& NewSelection, const UWorld& World, TSubclassOf ActorClass, const FCogWindowActorContextMenuFunction& ContextMenuFunction = nullptr); - static bool MenuActorsCombo(const char* StrID, const UWorld& World, const TArray>& ActorClasses, int32& SelectedActorClassIndex, ImGuiTextFilter* Filter, const APawn* LocalPlayerPawn, const FCogWindowActorContextMenuFunction& ContextMenuFunction = nullptr); + static bool MenuActorsCombo(const char* StrID, AActor*& NewSelection, const UWorld& World, const TArray>& ActorClasses, int32& SelectedActorClassIndex, ImGuiTextFilter* Filter, const APawn* LocalPlayerPawn, const FCogWindowActorContextMenuFunction& ContextMenuFunction = nullptr); - static bool ActorsListWithFilters(const UWorld& World, const TArray>& ActorClasses, int32& SelectedActorClassIndex, ImGuiTextFilter* Filter, const APawn* LocalPlayerPawn, const FCogWindowActorContextMenuFunction& ContextMenuFunction = nullptr); + static bool ActorsListWithFilters(AActor*& NewSelection, const UWorld& World, const TArray>& ActorClasses, int32& SelectedActorClassIndex, ImGuiTextFilter* Filter, const APawn* LocalPlayerPawn, const FCogWindowActorContextMenuFunction& ContextMenuFunction = nullptr); - static bool ActorsList(const UWorld& World, const TSubclassOf ActorClass, const ImGuiTextFilter* Filter = nullptr, const APawn* LocalPlayerPawn = nullptr, const FCogWindowActorContextMenuFunction& ContextMenuFunction = nullptr); + static bool ActorsList(AActor*& NewSelection, const UWorld& World, const TSubclassOf ActorClass, const ImGuiTextFilter* Filter = nullptr, const APawn* LocalPlayerPawn = nullptr, const FCogWindowActorContextMenuFunction& ContextMenuFunction = nullptr); static void ActorContextMenu(AActor& Selection, const FCogWindowActorContextMenuFunction& ContextMenuFunction);