Files
UnrealEngineUWP/Engine/Source/Developer/GameplayDebugger/Private/GameplayDebuggingReplicator.cpp
Billy Bramer 087e56e66a Merging using UE4-Fortnite-To-UE4 from CL 2261973
Includes the following engine-level changes (among others; biggest change is enabling world assets by default):

CL 2252857
added dynamic allocations for path finding, removed hardcoded limit of 128 polys in path corridor

CL 2256142
Added support for native arrays in JSON object converter.

- Permissive in treating arrays of size 1 and scalars as equivalent
- Excess elements in JSON are ignored. Serialization succeeds but a warning is logged

CL 2256073
Fixed a bug in ARecastNavMesh::BatchRaycast resulting in NaN hit locations

CL 2253797
#UE4 More aggressively setting RF_Public and RF_Standalone flags on maps and ensuring world names match package names. This is necessary because umaps are currently being managed outside of the content browser and it is causing a few issues. Also, packages containing maps now synthesize asset data when the package contains absolutely no asset data (probably because the UWorld in it was not RF_Public at the time it was saved due to a previous bug).

CL 2258142
#UE4 Added a GC during map load that reclaims memory allocated during load/init. This is needed to finish the load on low-memory devices in games that allocate more memory after load.

CL 2247003
Added homing to ProjectileMovementComponent

- Homing requires both a bool and a target component to be set, the strength is determined by a customizable variable
- Both homing and gravity are now applied in the new virtual function "CalculateAcceleration"

CL 2247249
Moved the homing modification to acceleration occur in a separate function specifically for homing

CL 2257043
- Guard net dormancy calls against executing on clients, based on thread with DaveR and JohnP; This particular case was the result of an intentionally client-authoritative actor calling the dormancy functions via inheritance

CL 2245629
#UE4 - fixed json TryGetNumber to round negatives appropriately

CL 2255312
#UE4 Enabling World Assets by default.

CL 2260956
Analytics ET now loads HTTP at StartupModule so the module will be available during ShutdownModule to flush events

CL 2245571
GenericTeamAgentInterface can now retrieve attitude of an agent towards a given actor #UE4

- Made PerceptionSystem's sight sense take advantage of that

CL 2246897
Fixed perception listeners not being removed from the PerceptionSystem on Owner's end play #UE4

- addresses TTP#343392

CL 2260634
added more debug data for NaN in crowd simulation

CL 2248387
Added possibility to debug multiple EQS queries with GameplayDebugger. #ue4
Fixed network replication from bandwidth point of view for data in GameplayDebugger. #ue4

CL 2253281
Added additional information to the visual logger for UBTCompositeNode::DoDecoratorsAllowExecution
- We now keep track of whether a decorator allows execution, in addition to the existing log for not allowing execution

CL 2255310
#UE4 The world browser module now listens to WorldAdded/WorldDestroyed events instead of WorldInit/WorldCleanup events. Worlds can be initialized without being the editor world and this handles that case.

CL 2258256
#UE4 Replacing the SOpenLevelDialog with a new generic SAssetDialog. This dialog will be used as a generic Open or Save As dialog for assets.

[CL 2266822 by Billy Bramer in Main branch]
2014-08-21 20:30:51 -04:00

479 lines
14 KiB
C++

// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.
#include "GameplayDebuggerPrivate.h"
#include "Engine/GameInstance.h"
#include "Debug/DebugDrawService.h"
#include "GameFramework/HUD.h"
#include "GameplayDebuggingComponent.h"
#include "GameplayDebuggingHUDComponent.h"
#include "GameplayDebuggingReplicator.h"
#include "BehaviorTreeDelegates.h"
#if WITH_EDITOR
#include "Editor/EditorEngine.h"
#include "LevelEditorViewport.h"
#endif // WITH_EDITOR
#include "UnrealNetwork.h"
FOnSelectionChanged AGameplayDebuggingReplicator::OnSelectionChangedDelegate;
AGameplayDebuggingReplicator::AGameplayDebuggingReplicator(const class FPostConstructInitializeProperties& PCIP)
: Super(PCIP)
, bIsGlobalInWorld(true)
, LastDrawAtFrame(0)
, PlayerControllersUpdateDelay(0)
{
PrimaryActorTick.bCanEverTick = true;
PrimaryActorTick.bStartWithTickEnabled = true;
TSubobjectPtr<USceneComponent> SceneComponent = PCIP.CreateDefaultSubobject<USceneComponent>(this, TEXT("SceneComponent"));
RootComponent = SceneComponent;
#if WITH_EDITOR
SetTickableWhenPaused(true);
SetIsTemporarilyHiddenInEditor(true);
SetActorHiddenInGame(false);
#endif
#if WITH_EDITORONLY_DATA
bHiddenEdLevel = true;
bHiddenEdLayer = true;
bHiddenEd = true;
bEditable = false;
#endif
DebuggerShowFlags = GameplayDebuggerSettings().DebuggerShowFlags;
if (!HasAnyFlags(RF_ClassDefaultObject))
{
SetActorTickEnabled(true);
bReplicates = false;
SetRemoteRoleForBackwardsCompat(ROLE_SimulatedProxy);
SetReplicates(true);
AGameplayDebuggingReplicator::OnSelectionChangedDelegate.AddUObject(this, &AGameplayDebuggingReplicator::SetActorToDebug);
}
}
void AGameplayDebuggingReplicator::GetLifetimeReplicatedProps(TArray< FLifetimeProperty > & OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
DOREPLIFETIME_CONDITION(AGameplayDebuggingReplicator, DebugComponent, COND_OwnerOnly);
DOREPLIFETIME_CONDITION(AGameplayDebuggingReplicator, LocalPlayerOwner, COND_OwnerOnly);
DOREPLIFETIME_CONDITION(AGameplayDebuggingReplicator, bIsGlobalInWorld, COND_OwnerOnly);
#endif
}
bool AGameplayDebuggingReplicator::IsNetRelevantFor(class APlayerController* RealViewer, AActor* Viewer, const FVector& SrcLocation)
{
return LocalPlayerOwner == RealViewer;
}
void AGameplayDebuggingReplicator::PostInitializeComponents()
{
Super::PostInitializeComponents();
SetActorTickEnabled(true);
}
void AGameplayDebuggingReplicator::BeginPlay()
{
Super::BeginPlay();
#if WITH_EDITOR
const UEditorEngine* EEngine = Cast<UEditorEngine>(GEngine);
if (EEngine && (EEngine->bIsSimulatingInEditor || EEngine->EditorWorld) && IsGlobalInWorld() && GCurrentLevelEditingViewportClient->EngineShowFlags.DebugAI)
{
SetIsTemporarilyHiddenInEditor(false);
SetActorHiddenInGame(false);
bHiddenEdLevel = false;
bHiddenEdLayer = false;
bHiddenEd = false;
bEditable = true;
}
else
{
SetTickableWhenPaused(true);
SetIsTemporarilyHiddenInEditor(true);
SetActorHiddenInGame(false);
bHiddenEdLevel = true;
bHiddenEdLayer = true;
bHiddenEd = true;
bEditable = false;
}
#endif
if (Role == ROLE_Authority)
{
bReplicates = false;
SetRemoteRoleForBackwardsCompat(ROLE_SimulatedProxy);
SetReplicates(true);
if (!DebugComponentClass.IsValid())
{
DebugComponentClass = StaticLoadClass(UGameplayDebuggingComponent::StaticClass(), NULL, *DebugComponentClassName, NULL, LOAD_None, NULL);
if (!DebugComponentClass.IsValid())
{
DebugComponentClass = UGameplayDebuggingComponent::StaticClass();
}
}
if (DebugComponent == NULL)
{
DebugComponent = ConstructObject<UGameplayDebuggingComponent>(DebugComponentClass.Get(), this);
DebugComponent->SetIsReplicated(true);
DebugComponent->RegisterComponent();
DebugComponent->Activate();
}
}
if (GetWorld() && GetNetMode() != ENetMode::NM_DedicatedServer)
{
if (GIsEditor)
{
UDebugDrawService::Register(TEXT("DebugAI"), FDebugDrawDelegate::CreateUObject(this, &AGameplayDebuggingReplicator::OnDebugAIDelegate));
}
UDebugDrawService::Register(TEXT("Game"), FDebugDrawDelegate::CreateUObject(this, &AGameplayDebuggingReplicator::DrawDebugDataDelegate));
if (!DebugComponentHUDClass.IsValid())
{
DebugComponentHUDClass = StaticLoadClass(AGameplayDebuggingHUDComponent::StaticClass(), NULL, *DebugComponentHUDClassName, NULL, LOAD_None, NULL);
if (!DebugComponentHUDClass.IsValid())
{
DebugComponentHUDClass = AGameplayDebuggingHUDComponent::StaticClass();
}
}
}
if (!DebugComponentClass.IsValid() && GetWorld() && GetNetMode() < ENetMode::NM_Client)
{
DebugComponentClass = StaticLoadClass(UGameplayDebuggingComponent::StaticClass(), NULL, *DebugComponentClassName, NULL, LOAD_None, NULL);
if (!DebugComponentClass.IsValid())
{
DebugComponentClass = UGameplayDebuggingComponent::StaticClass();
}
}
}
UGameplayDebuggingComponent* AGameplayDebuggingReplicator::GetDebugComponent()
{
if (!DebugComponent && DebugComponentClass.IsValid() && GetNetMode() < ENetMode::NM_Client)
{
DebugComponent = ConstructObject<UGameplayDebuggingComponent>(DebugComponentClass.Get(), this);
DebugComponent->SetIsReplicated(true);
DebugComponent->RegisterComponent();
DebugComponent->Activate();
}
return DebugComponent;
}
class UNetConnection* AGameplayDebuggingReplicator::GetNetConnection()
{
if (LocalPlayerOwner)
{
return LocalPlayerOwner->GetNetConnection();
}
return NULL;
}
bool AGameplayDebuggingReplicator::ServerEnableTargetSelection_Validate(bool, APlayerController* )
{
return true;
}
void AGameplayDebuggingReplicator::ServerEnableTargetSelection_Implementation(bool bEnable, APlayerController* Context)
{
if (GetDebugComponent())
{
GetDebugComponent()->ServerEnableTargetSelection(bEnable);
}
}
bool AGameplayDebuggingReplicator::ClientReplicateMessage_Validate(class AActor* Actor, uint32 InMessage, uint32 DataView)
{
return true;
}
void AGameplayDebuggingReplicator::ClientReplicateMessage_Implementation(class AActor* Actor, uint32 InMessage, uint32 DataView)
{
}
bool AGameplayDebuggingReplicator::ServerReplicateMessage_Validate(class AActor* Actor, uint32 InMessage, uint32 DataView)
{
return true;
}
void AGameplayDebuggingReplicator::ServerReplicateMessage_Implementation(class AActor* Actor, uint32 InMessage, uint32 DataView)
{
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
if (GetDebugComponent())
{
GetDebugComponent()->ServerReplicateData((EDebugComponentMessage::Type)InMessage, (EAIDebugDrawDataView::Type)DataView);
}
#endif //!(UE_BUILD_SHIPPING || UE_BUILD_TEST)
}
bool AGameplayDebuggingReplicator::IsDrawEnabled()
{
return bEnabledDraw && GetWorld() && GetNetMode() != ENetMode::NM_DedicatedServer;
}
void AGameplayDebuggingReplicator::EnableDraw(bool bEnable)
{
bEnabledDraw = bEnable;
if (AHUD* const GameHUD = LocalPlayerOwner ? LocalPlayerOwner->GetHUD() : NULL)
{
GameHUD->bShowHUD = bEnable ? false : true;
}
GEngine->bEnableOnScreenDebugMessages = bEnable ? false : true;
}
bool AGameplayDebuggingReplicator::IsToolCreated()
{
UGameplayDebuggingControllerComponent* GDC = FindComponentByClass<UGameplayDebuggingControllerComponent>();
return LocalPlayerOwner && GDC;
}
void AGameplayDebuggingReplicator::CreateTool()
{
if (GetWorld() && GetNetMode() != ENetMode::NM_DedicatedServer)
{
UGameplayDebuggingControllerComponent* GDC = FindComponentByClass<UGameplayDebuggingControllerComponent>();
if (!GDC)
{
GDC = ConstructObject<UGameplayDebuggingControllerComponent>(UGameplayDebuggingControllerComponent::StaticClass(), this);
GDC->SetPlayerOwner(LocalPlayerOwner);
GDC->RegisterComponent();
}
}
}
void AGameplayDebuggingReplicator::EnableTool()
{
if (GetWorld() && GetNetMode() != ENetMode::NM_DedicatedServer)
{
UGameplayDebuggingControllerComponent* GDC = FindComponentByClass<UGameplayDebuggingControllerComponent>();
if (GDC)
{
// simulate key press
GDC->OnActivationKeyPressed();
GDC->OnActivationKeyReleased();
}
}
}
void AGameplayDebuggingReplicator::TickActor(float DeltaTime, enum ELevelTick TickType, FActorTickFunction& ThisTickFunction)
{
Super::TickActor(DeltaTime, TickType, ThisTickFunction);
UWorld* World = GetWorld();
if (!IsGlobalInWorld() || !World || GetNetMode() == ENetMode::NM_Client || !IGameplayDebugger::IsAvailable())
{
// global level replicator don't have any local player and it's prepared to work only on servers
return;
}
UGameInstance* GameInstance = World->GetGameInstance();
if (!GameInstance || !World->IsGameWorld())
{
return;
}
PlayerControllersUpdateDelay -= DeltaTime;
if (PlayerControllersUpdateDelay <= 0)
{
for (FConstPlayerControllerIterator Iterator = World->GetPlayerControllerIterator(); Iterator; Iterator++)
{
APlayerController* PC = *Iterator;
if (PC)
{
IGameplayDebugger& Debugger = IGameplayDebugger::Get();
Debugger.CreateGameplayDebuggerForPlayerController(PC);
}
}
PlayerControllersUpdateDelay = 5;
}
}
void AGameplayDebuggingReplicator::SetActorToDebug(AActor* InActor)
{
if (LastSelectedActorInSimulation.Get() != InActor)
{
LastSelectedActorInSimulation = InActor;
UGameplayDebuggingComponent::OnDebuggingTargetChangedDelegate.Broadcast(InActor, InActor ? InActor->IsSelected() : false);
APawn* TargetPawn = Cast<APawn>(InActor);
if (TargetPawn)
{
FBehaviorTreeDelegates::OnDebugSelected.Broadcast(TargetPawn);
}
}
if (UGameplayDebuggingComponent* DebugComponent = GetDebugComponent())
{
DebugComponent->SetActorToDebug(InActor);
DebugComponent->SelectForDebugging(InActor ? InActor->IsSelected() : false);
}
}
void AGameplayDebuggingReplicator::OnDebugAIDelegate(class UCanvas* Canvas, class APlayerController* PC)
{
#if WITH_EDITOR
if (!GIsEditor)
{
return;
}
if (!LocalPlayerOwner || IsGlobalInWorld())
{
return;
}
UEditorEngine* EEngine = Cast<UEditorEngine>(GEngine);
if (GFrameNumber == LastDrawAtFrame || !EEngine || !EEngine->bIsSimulatingInEditor)
{
return;
}
LastDrawAtFrame = GFrameNumber;
FEngineShowFlags EngineShowFlags = Canvas && Canvas->SceneView && Canvas->SceneView->Family ? Canvas->SceneView->Family->EngineShowFlags : FEngineShowFlags(GIsEditor ? EShowFlagInitMode::ESFIM_Editor : EShowFlagInitMode::ESFIM_Game);
if (!EngineShowFlags.DebugAI)
{
return;
}
UWorld* World = GetWorld();
if (World && GetDebugComponent() && GetDebugComponent()->GetOwnerRole() == ROLE_Authority)
{
bool bBroadcastedNewSelection = false;
UGameplayDebuggingControllerComponent* GDC = FindComponentByClass<UGameplayDebuggingControllerComponent>();
TArray<int32> OryginalReplicateViewDataCounters;
if (UGameplayDebuggingComponent* DebugComponent = GetDebugComponent())
{
OryginalReplicateViewDataCounters = DebugComponent->ReplicateViewDataCounters;
for (uint32 Index = 0; Index < EAIDebugDrawDataView::MAX; ++Index)
{
DebugComponent->ReplicateViewDataCounters[Index] = GameplayDebuggerSettings(this).CheckFlag((EAIDebugDrawDataView::Type)Index) ? 1 : 0;
}
}
// looks like Simulate in UE4 Editor - let's find selected Pawn to debug
for (FConstPawnIterator Iterator = World->GetPawnIterator(); Iterator; ++Iterator)
{
AActor* NewTarget = Cast<AActor>(*Iterator);
//We needs to collect data manually in Simulate
GetDebugComponent()->SetActorToDebug(NewTarget);
GetDebugComponent()->SelectForDebugging(NewTarget->IsSelected());
GetDebugComponent()->CollectDataToReplicate(NewTarget->IsSelected());
if (NewTarget->IsSelected())
{
SetActorToDebug(NewTarget);
bBroadcastedNewSelection = true;
}
DrawDebugData(Canvas, PC);
}
if (!bBroadcastedNewSelection && GetSelectedActorToDebug() && !GetSelectedActorToDebug()->IsSelected())
{
SetActorToDebug(NULL);
}
if (UGameplayDebuggingComponent* DebugComponent = GetDebugComponent())
{
DebugComponent->ReplicateViewDataCounters = OryginalReplicateViewDataCounters;
}
}
#endif
}
void AGameplayDebuggingReplicator::DrawDebugDataDelegate(class UCanvas* Canvas, class APlayerController* PC)
{
#if !(UE_BUILD_SHIPPING && UE_BUILD_TEST)
if (GetWorld() == NULL || IsPendingKill() || Canvas == NULL || Canvas->IsPendingKill())
{
return;
}
if (!LocalPlayerOwner || IsGlobalInWorld())
{
return;
}
if (Canvas->SceneView != NULL && !Canvas->SceneView->bIsGameView)
{
return;
}
if (GFrameNumber == LastDrawAtFrame)
{
return;
}
LastDrawAtFrame = GFrameNumber;
const UGameplayDebuggingControllerComponent* GDC = FindComponentByClass<UGameplayDebuggingControllerComponent>();
if (!IsDrawEnabled() || !GDC)
{
return;
}
if (GetWorld()->bPlayersOnly && Role == ROLE_Authority)
{
for (FConstPawnIterator Iterator = GetWorld()->GetPawnIterator(); Iterator; ++Iterator)
{
AActor* NewTarget = Cast<AActor>(*Iterator);
if (NewTarget->IsSelected() && GetSelectedActorToDebug() != NewTarget)
{
SetActorToDebug(NewTarget);
}
GetDebugComponent()->SetActorToDebug(NewTarget);
GetDebugComponent()->CollectDataToReplicate(true);
}
}
DrawDebugData(Canvas, PC);
}
void AGameplayDebuggingReplicator::DrawDebugData(class UCanvas* Canvas, class APlayerController* PC)
{
if (!LocalPlayerOwner)
{
return;
}
const bool bAllowToDraw = Canvas && Canvas->SceneView && (Canvas->SceneView->ViewActor == LocalPlayerOwner->AcknowledgedPawn || Canvas->SceneView->ViewActor == LocalPlayerOwner->GetPawnOrSpectator());
if (!bAllowToDraw)
{
return;
}
if (!DebugRenderer.IsValid() && DebugComponentHUDClass.IsValid())
{
FActorSpawnParameters SpawnInfo;
SpawnInfo.Owner = NULL;
SpawnInfo.Instigator = NULL;
SpawnInfo.bNoCollisionFail = true;
DebugRenderer = GetWorld()->SpawnActor<AGameplayDebuggingHUDComponent>(DebugComponentHUDClass.Get(), SpawnInfo);
DebugRenderer->SetCanvas(Canvas);
DebugRenderer->SetPlayerOwner(LocalPlayerOwner);
DebugRenderer->SetWorld(GetWorld());
}
if (DebugRenderer != NULL)
{
DebugRenderer->SetCanvas(Canvas);
DebugRenderer->Render();
}
#endif
}