Option to replicate client selection to server.

This commit is contained in:
Arnaud Jamin
2025-01-06 13:41:46 -05:00
parent c58126d244
commit 9a1cd48434
9 changed files with 82 additions and 28 deletions
@@ -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);
}
//--------------------------------------------------------------------------------------------------------------------------
@@ -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
}
@@ -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<AActor> Selection[MaxPie];
};
@@ -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; }
@@ -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();
}
@@ -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)
{
@@ -75,7 +75,7 @@ protected:
bool bSelectionModeActive = false;
bool bIsInputEnabledBeforeEnteringSelectionMode;
bool bIsInputEnabledBeforeEnteringSelectionMode = false;
int32 WaitInputReleased = 0;
@@ -734,7 +734,7 @@ bool FCogWindowWidgets::CollisionProfileChannels(int32& Channels)
}
//--------------------------------------------------------------------------------------------------------------------------
bool FCogWindowWidgets::ActorsListWithFilters(const UWorld& World, const TArray<TSubclassOf<AActor>>& ActorClasses, int32& SelectedActorClassIndex, ImGuiTextFilter* Filter, const APawn* LocalPlayerPawn, const FCogWindowActorContextMenuFunction& ContextMenuFunction)
bool FCogWindowWidgets::ActorsListWithFilters(AActor*& NewSelection, const UWorld& World, const TArray<TSubclassOf<AActor>>& ActorClasses, int32& SelectedActorClassIndex, ImGuiTextFilter* Filter, const APawn* LocalPlayerPawn, const FCogWindowActorContextMenuFunction& ContextMenuFunction)
{
TSubclassOf<AActor> 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<AActor> ActorClass, const ImGuiTextFilter* Filter, const APawn* LocalPlayerPawn, const FCogWindowActorContextMenuFunction& ContextMenuFunction)
bool FCogWindowWidgets::ActorsList(AActor*& NewSelection, const UWorld& World, const TSubclassOf<AActor> ActorClass, const ImGuiTextFilter* Filter, const APawn* LocalPlayerPawn, const FCogWindowActorContextMenuFunction& ContextMenuFunction)
{
TArray<AActor*> Actors;
for (TActorIterator It(&World, ActorClass); It; ++It)
@@ -813,8 +813,8 @@ bool FCogWindowWidgets::ActorsList(const UWorld& World, const TSubclassOf<AActor
}
}
const AActor* OldSelection = FCogDebug::GetSelection();
const AActor* NewSelection = OldSelection;
AActor* OldSelection = FCogDebug::GetSelection();
NewSelection = OldSelection;
ImGuiListClipper Clipper;
Clipper.Begin(Actors.Num());
@@ -833,7 +833,7 @@ bool FCogWindowWidgets::ActorsList(const UWorld& World, const TSubclassOf<AActor
const bool bIsSelected = Actor == FCogDebug::GetSelection();
if (ImGui::Selectable(TCHAR_TO_ANSI(*FCogWindowHelper::GetActorName(*Actor)), bIsSelected))
{
FCogDebug::SetSelection(&World, Actor);
//FCogDebug::SetSelection(&World, Actor);
NewSelection = Actor;
}
@@ -862,17 +862,17 @@ bool FCogWindowWidgets::ActorsList(const UWorld& World, const TSubclassOf<AActor
}
//--------------------------------------------------------------------------------------------------------------------------
bool FCogWindowWidgets::MenuActorsCombo(const char* StrID, const UWorld& World, TSubclassOf<AActor> ActorClass, const FCogWindowActorContextMenuFunction& ContextMenuFunction)
bool FCogWindowWidgets::MenuActorsCombo(const char* StrID, AActor*& NewSelection, const UWorld& World, TSubclassOf<AActor> 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<TSubclassOf<AActor>>& ActorClasses, int32& SelectedActorClassIndex, ImGuiTextFilter* Filter, const APawn* LocalPlayerPawn, const FCogWindowActorContextMenuFunction& ContextMenuFunction)
bool FCogWindowWidgets::MenuActorsCombo(const char* StrID, AActor*& NewSelection, const UWorld& World, const TArray<TSubclassOf<AActor>>& 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();
@@ -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<AActor> ActorClass, const FCogWindowActorContextMenuFunction& ContextMenuFunction = nullptr);
static bool MenuActorsCombo(const char* StrID, AActor*& NewSelection, const UWorld& World, TSubclassOf<AActor> ActorClass, const FCogWindowActorContextMenuFunction& ContextMenuFunction = nullptr);
static bool MenuActorsCombo(const char* StrID, const UWorld& World, const TArray<TSubclassOf<AActor>>& 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<TSubclassOf<AActor>>& ActorClasses, int32& SelectedActorClassIndex, ImGuiTextFilter* Filter, const APawn* LocalPlayerPawn, const FCogWindowActorContextMenuFunction& ContextMenuFunction = nullptr);
static bool ActorsListWithFilters(const UWorld& World, const TArray<TSubclassOf<AActor>>& ActorClasses, int32& SelectedActorClassIndex, ImGuiTextFilter* Filter, const APawn* LocalPlayerPawn, const FCogWindowActorContextMenuFunction& ContextMenuFunction = nullptr);
static bool ActorsListWithFilters(AActor*& NewSelection, const UWorld& World, const TArray<TSubclassOf<AActor>>& ActorClasses, int32& SelectedActorClassIndex, ImGuiTextFilter* Filter, const APawn* LocalPlayerPawn, const FCogWindowActorContextMenuFunction& ContextMenuFunction = nullptr);
static bool ActorsList(const UWorld& World, const TSubclassOf<AActor> ActorClass, const ImGuiTextFilter* Filter = nullptr, const APawn* LocalPlayerPawn = nullptr, const FCogWindowActorContextMenuFunction& ContextMenuFunction = nullptr);
static bool ActorsList(AActor*& NewSelection, const UWorld& World, const TSubclassOf<AActor> ActorClass, const ImGuiTextFilter* Filter = nullptr, const APawn* LocalPlayerPawn = nullptr, const FCogWindowActorContextMenuFunction& ContextMenuFunction = nullptr);
static void ActorContextMenu(AActor& Selection, const FCogWindowActorContextMenuFunction& ContextMenuFunction);