Files
UnrealEngineUWP/Engine/Source/Developer/GameplayDebugger/Private/GameplayDebuggingReplicator.cpp
Marc Audy 4c41590c3d Copying //UE4/Dev-Framework to Dev-Main (//UE4/Dev-Main) @ 2879625
#lockdown Nick.Penwarden

==========================
MAJOR FEATURES + CHANGES
==========================
Change 2821607 on 2016/01/08 by Mieszko.Zielinski

	Added a way to limit amount of information logged by vlog by discarding logs from classes from outside of class whitelist #UE4

	This feature was followed by refactoring of functions taking FVisualLogEntry pointers to use references instead.

	#rb Lukasz.Furman

Change 2828384 on 2016/01/14 by Mieszko.Zielinski

	Back out of visual log refactor done as part of CL#2821607 #UE4

Change 2869215 on 2016/02/16 by Marc.Audy

	Store a WorldSettings pointer on ULevel instead of requiring it be index 0 in the Actors array. However, we will still generally attempt to keep it at index 0 for consistency with previous behavior
	#rb Bruce.Nesbit
	#jira UE-26417

Change 2869404 on 2016/02/16 by Ori.Cohen

	Improve UI for default collision. It now uses a single drop down and sets the appropriate flags under the hood.

	#rb Lina.Halper

Change 2870062 on 2016/02/17 by Jurre.deBaare

	Name parameter driven by bone controller
	#JIRA UE-25997
	#rb Thomas.Sarkanen

Change 2870280 on 2016/02/17 by Mieszko.Zielinski

	Vis log category handling fixes #UE4

	Also, a minor cleanup

	#rb Lukasz.Furman

Change 2871729 on 2016/02/18 by James.Golding

	UE-26663 Fix 'LOD For Collision' display name
	#rb thomas.sarkanen

Change 2871730 on 2016/02/18 by James.Golding

	UE-26580 Make ECollisionEnabled a BlueprintType
	UE-25373 Add a MakeHitResult node
	#rb thomas.sarkanen

Change 2871732 on 2016/02/18 by James.Golding

	UE-24397 Add 'test' option to async query API, and use it in places that made sense. Also removed deprecated (4.8) functions from API.
	#rb ori.cohen

Change 2872022 on 2016/02/18 by Lukasz.Furman

	gameplay debugger refactor
	#ue4

Change 2872082 on 2016/02/18 by Lukasz.Furman

	enabled old gameplay debugger as default one for now
	it will be deprecated with next version after testing in game projects
	#ue4

Change 2872390 on 2016/02/18 by Aaron.McLeran

	OR-15041 (CPU) Hitches due to audio decompression on Windows

	1) Moving ogg-vorbis file info parsing into a worker thread
	 - stat dumphitches now shows the vorbis stuff totally gone

	2) Moving async decoding tasks to be retrieved and started from OnBufferEnd callback

	#rb marc.audy

Change 2872418 on 2016/02/18 by Mieszko.Zielinski

	Fixed EQS debugger not storing data properly when subsequent Option is the one that produces result #UE4

	#rb Lukasz.Furman

Change 2872446 on 2016/02/18 by Aaron.McLeran

	Using cached value of ActualVolume in GetVolumeWeightedPriority

Change 2872770 on 2016/02/18 by Aaron.McLeran

	QAGame testing content for audio testing.

	Going to create a folder with specific sub-system testing maps for audio

Change 2873733 on 2016/02/19 by Jurre.deBaare

	- HLOD generated assets are now saved into a separate package instead of inside of the level asset
	#rb Ori.Cohen

Change 2873828 on 2016/02/19 by Ori.Cohen

	Distributions that bake out no longer load in cooked build.

	#JIRA UE-27126
	#rb Olaf.Piesche, Nick.Penwarden

Change 2874623 on 2016/02/19 by Aaron.McLeran

	UE-27131 Support for changing sound class volumes dynamically

	- new BP function to override a sound mix sound class adjuster
	- cleanup of AudioDevice.h and AudioDevice.cpp
	   - removing unnecessarily forward declares on various types
	   - removing unnecessary spaces and (void) params, etc

Change 2874922 on 2016/02/20 by Mieszko.Zielinski

	Fixed EQS tests being compiled out from Shipping and Test with WITH_DEV_AUTOMATION_TESTS macro #UE4

	#jira OR-15292
	#rb none

Change 2875838 on 2016/02/22 by Benn.Gallagher

[CL 2880055 by Marc Audy in Main branch]
2016-02-24 14:23:53 -05:00

829 lines
26 KiB
C++

// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved.
//////////////////////////////////////////////////////////////////////////
// THIS CLASS IS NOW DEPRECATED AND WILL BE REMOVED IN NEXT VERSION
// Please check GameplayDebugger.h for details.
#include "GameplayDebuggerPrivatePCH.h"
#include "Engine/GameInstance.h"
#include "Engine/Canvas.h"
#include "Debug/DebugDrawService.h"
#include "GameFramework/HUD.h"
#include "GameFramework/Pawn.h"
#include "GameplayDebugger.h"
#include "GameplayDebuggingComponent.h"
#include "GameplayDebuggingHUDComponent.h"
#include "GameplayDebuggingReplicator.h"
#include "GameplayDebuggingControllerComponent.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 FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
, MaxEQSQueries(5)
, bIsGlobalInWorld(true)
, LastDrawAtFrame(0)
, PlayerControllersUpdateDelay(0)
{
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
// Structure to hold one-time initialization
struct FConstructorStatics
{
ConstructorHelpers::FObjectFinderOptional<UTexture2D> RedIcon;
ConstructorHelpers::FObjectFinderOptional<UTexture2D> GreenIcon;
// both icons are needed to debug AI
FConstructorStatics()
: RedIcon(TEXT("/Engine/EngineResources/AICON-Red.AICON-Red"))
, GreenIcon(TEXT("/Engine/EngineResources/AICON-Green.AICON-Green"))
{
}
};
static FConstructorStatics ConstructorStatics;
DefaultTexture_Red = ConstructorStatics.RedIcon.Get();
DefaultTexture_Green = ConstructorStatics.GreenIcon.Get();
PrimaryActorTick.bCanEverTick = true;
PrimaryActorTick.bStartWithTickEnabled = false;
USceneComponent* SceneComponent = CreateDefaultSubobject<USceneComponent>(TEXT("SceneComponent"));
RootComponent = SceneComponent;
#if WITH_EDITOR
SetIsTemporarilyHiddenInEditor(true);
#endif
#if WITH_EDITORONLY_DATA
SetTickableWhenPaused(true);
SetActorHiddenInGame(false);
bHiddenEdLevel = true;
bHiddenEdLayer = true;
bHiddenEd = true;
bEditable = false;
#endif
DebuggerShowFlags = GameplayDebuggerSettings().DebuggerShowFlags;
FGameplayDebuggerSettings Settings = GameplayDebuggerSettings(this);
#define UPDATE_VIEW_PROPS(__FlagName__) __FlagName__ = Settings.CheckFlag(EAIDebugDrawDataView::__FlagName__);
UPDATE_VIEW_PROPS(OverHead);
UPDATE_VIEW_PROPS(Basic);
UPDATE_VIEW_PROPS(BehaviorTree);
UPDATE_VIEW_PROPS(EQS);
UPDATE_VIEW_PROPS(Perception);
UPDATE_VIEW_PROPS(GameView1);
UPDATE_VIEW_PROPS(GameView2);
UPDATE_VIEW_PROPS(GameView3);
UPDATE_VIEW_PROPS(GameView4);
UPDATE_VIEW_PROPS(GameView5);
#undef UPDATE_VIEW_PROPS
EnableEQSOnHUD = true;
if (!HasAnyFlags(RF_ClassDefaultObject))
{
SetActorTickEnabled(true);
bReplicates = false;
SetRemoteRoleForBackwardsCompat(ROLE_SimulatedProxy);
SetReplicates(true);
AGameplayDebuggingReplicator::OnSelectionChangedDelegate.AddUObject(this, &AGameplayDebuggingReplicator::ServerSetActorToDebug);
}
#endif //!(UE_BUILD_SHIPPING || UE_BUILD_TEST)
}
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);
DOREPLIFETIME_CONDITION(AGameplayDebuggingReplicator, LastSelectedActorToDebug, COND_OwnerOnly);
#endif
}
bool AGameplayDebuggingReplicator::IsNetRelevantFor(const AActor* RealViewer, const AActor* ViewTarget, const FVector& SrcLocation) const
{
return LocalPlayerOwner == RealViewer;
}
void AGameplayDebuggingReplicator::PostInitializeComponents()
{
Super::PostInitializeComponents();
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
SetActorTickEnabled(true);
#endif
}
#if WITH_EDITOR
void AGameplayDebuggingReplicator::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
{
Super::PostEditChangeProperty(PropertyChangedEvent);
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
// @note patching up OR-9814
UGameplayDebuggingComponent* DummyPointer = GetDebugComponent();
if (!PropertyChangedEvent.Property)
{
return;
}
FGameplayDebuggerSettings Settings = GameplayDebuggerSettings(this);
#define CHECK_AND_UPDATE_FLAGS(__FlagName_) \
if (PropertyChangedEvent.Property->GetFName() == GET_MEMBER_NAME_CHECKED(AGameplayDebuggingReplicator, __FlagName_)) \
{ \
__FlagName_ ? Settings.SetFlag(EAIDebugDrawDataView::__FlagName_) : Settings.ClearFlag(EAIDebugDrawDataView::__FlagName_); \
DebugComponent->ServerReplicateData(Settings.CheckFlag(EAIDebugDrawDataView::__FlagName_) ? EDebugComponentMessage::ActivateDataView : EDebugComponentMessage::DeactivateDataView, EAIDebugDrawDataView::__FlagName_); \
}else
CHECK_AND_UPDATE_FLAGS(OverHead)
CHECK_AND_UPDATE_FLAGS(Basic)
CHECK_AND_UPDATE_FLAGS(BehaviorTree)
CHECK_AND_UPDATE_FLAGS(EQS)
CHECK_AND_UPDATE_FLAGS(Perception)
CHECK_AND_UPDATE_FLAGS(GameView1)
CHECK_AND_UPDATE_FLAGS(GameView2)
CHECK_AND_UPDATE_FLAGS(GameView3)
CHECK_AND_UPDATE_FLAGS(GameView4)
CHECK_AND_UPDATE_FLAGS(GameView5) {}
#if WITH_EQS
if (PropertyChangedEvent.Property->GetFName() == GET_MEMBER_NAME_CHECKED(AGameplayDebuggingReplicator, EQS))
{
DebugComponent->EnableClientEQSSceneProxy(EQS);
DebugComponent->SetEQSIndex(ActiveEQSIndex);
DebugComponent->MarkRenderStateDirty();
}
if (PropertyChangedEvent.Property->GetFName() == GET_MEMBER_NAME_CHECKED(AGameplayDebuggingReplicator, ActiveEQSIndex))
{
DebugComponent->SetEQSIndex(ActiveEQSIndex);
}
#endif // WITH_EQS
#undef CHECK_AND_UPDATE_FLAGS
#endif //!(UE_BUILD_SHIPPING || UE_BUILD_TEST)
}
#endif //WITH_EDITOR
void AGameplayDebuggingReplicator::BeginPlay()
{
Super::BeginPlay();
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
if (Role == ROLE_Authority)
{
bReplicates = false;
SetRemoteRoleForBackwardsCompat(ROLE_SimulatedProxy);
SetReplicates(true);
if (!DebugComponentClass.IsValid() && GetWorld() && GetNetMode() < ENetMode::NM_Client)
{
DebugComponentClass = StaticLoadClass(UGameplayDebuggingComponent::StaticClass(), NULL, *DebugComponentClassName, NULL, LOAD_None, NULL);
if (!DebugComponentClass.IsValid())
{
DebugComponentClass = UGameplayDebuggingComponent::StaticClass();
}
}
// @note patching up OR-9814
const UGameplayDebuggingComponent* DummyPointer = GetDebugComponent();
if (DummyPointer == nullptr)
{
UE_LOG(LogGameplayDebugger, Error, TEXT("Unable to create UGameplayDebuggingComponent instance!"));
}
}
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 WITH_EDITOR
const UEditorEngine* EEngine = Cast<UEditorEngine>(GEngine);
if (EEngine && (EEngine->bIsSimulatingInEditor || EEngine->EditorWorld) && GetWorld() != EEngine->EditorWorld && !IsGlobalInWorld() && GCurrentLevelEditingViewportClient && GCurrentLevelEditingViewportClient->EngineShowFlags.DebugAI)
{
SetIsTemporarilyHiddenInEditor(false);
SetActorHiddenInGame(false);
bHiddenEdLevel = false;
bHiddenEdLayer = false;
bHiddenEd = false;
bEditable = true;
if (DebugComponent)
{
DebugComponent->ServerReplicateData(EDebugComponentMessage::ActivateReplication, EAIDebugDrawDataView::Empty);
FGameplayDebuggerSettings Settings = GameplayDebuggerSettings(this);
DebugComponent->ServerReplicateData(Settings.CheckFlag(EAIDebugDrawDataView::OverHead) ? EDebugComponentMessage::ActivateDataView : EDebugComponentMessage::DeactivateDataView, EAIDebugDrawDataView::OverHead);
DebugComponent->ServerReplicateData(Settings.CheckFlag(EAIDebugDrawDataView::Basic) ? EDebugComponentMessage::ActivateDataView : EDebugComponentMessage::DeactivateDataView, EAIDebugDrawDataView::Basic);
DebugComponent->ServerReplicateData(Settings.CheckFlag(EAIDebugDrawDataView::BehaviorTree) ? EDebugComponentMessage::ActivateDataView : EDebugComponentMessage::DeactivateDataView, EAIDebugDrawDataView::BehaviorTree);
DebugComponent->ServerReplicateData(Settings.CheckFlag(EAIDebugDrawDataView::EQS) ? EDebugComponentMessage::ActivateDataView : EDebugComponentMessage::DeactivateDataView, EAIDebugDrawDataView::EQS);
DebugComponent->ServerReplicateData(Settings.CheckFlag(EAIDebugDrawDataView::Perception) ? EDebugComponentMessage::ActivateDataView : EDebugComponentMessage::DeactivateDataView, EAIDebugDrawDataView::Perception);
DebugComponent->ServerReplicateData(Settings.CheckFlag(EAIDebugDrawDataView::GameView1) ? EDebugComponentMessage::ActivateDataView : EDebugComponentMessage::DeactivateDataView, EAIDebugDrawDataView::GameView1);
DebugComponent->ServerReplicateData(Settings.CheckFlag(EAIDebugDrawDataView::GameView2) ? EDebugComponentMessage::ActivateDataView : EDebugComponentMessage::DeactivateDataView, EAIDebugDrawDataView::GameView2);
DebugComponent->ServerReplicateData(Settings.CheckFlag(EAIDebugDrawDataView::GameView3) ? EDebugComponentMessage::ActivateDataView : EDebugComponentMessage::DeactivateDataView, EAIDebugDrawDataView::GameView3);
DebugComponent->ServerReplicateData(Settings.CheckFlag(EAIDebugDrawDataView::GameView4) ? EDebugComponentMessage::ActivateDataView : EDebugComponentMessage::DeactivateDataView, EAIDebugDrawDataView::GameView4);
DebugComponent->ServerReplicateData(Settings.CheckFlag(EAIDebugDrawDataView::GameView5) ? EDebugComponentMessage::ActivateDataView : EDebugComponentMessage::DeactivateDataView, EAIDebugDrawDataView::GameView5);
}
}
else
{
SetTickableWhenPaused(true);
SetIsTemporarilyHiddenInEditor(true);
SetActorHiddenInGame(false);
bHiddenEdLevel = true;
bHiddenEdLayer = true;
bHiddenEd = true;
bEditable = false;
if (DebugComponent)
{
DebugComponent->ServerReplicateData(EDebugComponentMessage::DeactivateDataView, EAIDebugDrawDataView::Empty);
}
}
#endif
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 (bAutoActivate)
{
OnRep_AutoActivate();
}
#endif //!(UE_BUILD_SHIPPING || UE_BUILD_TEST)
}
void AGameplayDebuggingReplicator::BeginDestroy()
{
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
if (GEngine)
{
GEngine->bEnableOnScreenDebugMessages = true;
}
if (IsDrawEnabled())
{
EnableDraw(false);
}
#endif
Super::BeginDestroy();
}
void AGameplayDebuggingReplicator::PostNetInit()
{
Super::PostNetInit();
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
if (bAutoActivate)
{
OnRep_AutoActivate();
}
#endif
}
void AGameplayDebuggingReplicator::ClientAutoActivate_Implementation()
{
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
// we are already replicated so let's activate tool
if (GetWorld() && GetNetMode() == ENetMode::NM_Client && !IsToolCreated() && !IsGlobalInWorld())
{
if (IsToolCreated())
{
EnableDraw(!IsDrawEnabled());
}
else
{
CreateTool();
EnableTool();
}
}
#endif
}
void AGameplayDebuggingReplicator::OnRep_AutoActivate()
{
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
// we are already replicated so let's activate tool
if (GetWorld() && GetNetMode() == ENetMode::NM_Client && !IsToolCreated() && !IsGlobalInWorld())
{
if (IsToolCreated())
{
EnableDraw(!IsDrawEnabled());
}
else
{
CreateTool();
EnableTool();
}
}
#endif
}
UGameplayDebuggingComponent* AGameplayDebuggingReplicator::GetDebugComponent()
{
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
if (IsPendingKill() == false && !DebugComponent && DebugComponentClass.IsValid() && GetNetMode() < ENetMode::NM_Client)
{
DebugComponent = NewObject<UGameplayDebuggingComponent>(this, DebugComponentClass.Get(), TEXT("DebugComponent"), RF_Transient);
DebugComponent->SetIsReplicated(true);
DebugComponent->RegisterComponent();
DebugComponent->Activate();
}
#endif
return DebugComponent;
}
class UNetConnection* AGameplayDebuggingReplicator::GetNetConnection() const
{
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
if (LocalPlayerOwner && LocalPlayerOwner->IsPendingKill() == false && IsPendingKill() == false)
{
return LocalPlayerOwner->GetNetConnection();
}
#endif
return NULL;
}
bool AGameplayDebuggingReplicator::ClientEnableTargetSelection_Validate(bool, APlayerController* )
{
return true;
}
void AGameplayDebuggingReplicator::ClientEnableTargetSelection_Implementation(bool bEnable, APlayerController* Context)
{
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
// @note patching up OR-9814
const UGameplayDebuggingComponent* DummyPointer = GetDebugComponent();
if (DebugComponent)
{
DebugComponent->ClientEnableTargetSelection(bEnable);
}
#endif
}
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 ((EDebugComponentMessage::Type)InMessage == EDebugComponentMessage::DeactivateReplilcation)
{
ServerSetActorToDebug(NULL);
MarkComponentsRenderStateDirty();
}
// @note patching up OR-9814
const UGameplayDebuggingComponent* DummyPointer = GetDebugComponent();
if (DebugComponent)
{
DebugComponent->ServerReplicateData((EDebugComponentMessage::Type)InMessage, (EAIDebugDrawDataView::Type)DataView);
}
#endif //!(UE_BUILD_SHIPPING || UE_BUILD_TEST)
}
bool AGameplayDebuggingReplicator::IsDrawEnabled()
{
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
return bEnabledDraw && GetWorld() && GetNetMode() != ENetMode::NM_DedicatedServer;
#else
return false;
#endif
}
void AGameplayDebuggingReplicator::EnableDraw(bool bEnable)
{
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
bEnabledDraw = bEnable;
if (AHUD* const GameHUD = LocalPlayerOwner ? LocalPlayerOwner->GetHUD() : NULL)
{
GameHUD->bShowHUD = bEnable ? false : true;
}
GEngine->bEnableOnScreenDebugMessages = bEnable ? false : true;
if (DebugComponent)
{
const bool bEnabledEQSView = GameplayDebuggerSettings(this).CheckFlag(EAIDebugDrawDataView::EQS);
DebugComponent->EnableClientEQSSceneProxy(bEnable && bEnabledEQSView ? true : false);
DebugComponent->MarkRenderStateDirty();
}
#endif
}
bool AGameplayDebuggingReplicator::IsToolCreated()
{
UGameplayDebuggingControllerComponent* GDC = FindComponentByClass<UGameplayDebuggingControllerComponent>();
return LocalPlayerOwner && GDC;
}
void AGameplayDebuggingReplicator::CreateTool()
{
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
if (GetWorld() && GetNetMode() != ENetMode::NM_DedicatedServer)
{
UGameplayDebuggingControllerComponent* GDC = FindComponentByClass<UGameplayDebuggingControllerComponent>();
if (!GDC)
{
DebugComponentControllerClass = StaticLoadClass(UGameplayDebuggingControllerComponent::StaticClass(), NULL, *DebugComponentControllerClassName, NULL, LOAD_None, NULL);
if (!DebugComponentControllerClass.IsValid())
{
DebugComponentControllerClass = AGameplayDebuggingHUDComponent::StaticClass();
}
GDC = NewObject<UGameplayDebuggingControllerComponent>(this, DebugComponentControllerClass.Get());
GDC->SetPlayerOwner(LocalPlayerOwner);
GDC->RegisterComponent();
}
}
#endif
}
void AGameplayDebuggingReplicator::EnableTool()
{
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
// @note patching up OR-9814
if (GetWorld() && GetNetMode() != ENetMode::NM_DedicatedServer && DebugComponent != nullptr)
{
UGameplayDebuggingControllerComponent* GDC = FindComponentByClass<UGameplayDebuggingControllerComponent>();
if (GDC)
{
// simulate key press
GDC->OnActivationKeyPressed();
ClientEnableTargetSelection(true, LocalPlayerOwner);
// @note patching up OR-9814
DebugComponent->SelectTargetToDebug();
GDC->OnActivationKeyReleased();
}
}
#endif
}
void AGameplayDebuggingReplicator::TickActor(float DeltaTime, enum ELevelTick TickType, FActorTickFunction& ThisTickFunction)
{
Super::TickActor(DeltaTime, TickType, ThisTickFunction);
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
UWorld* World = GetWorld();
if (!IsGlobalInWorld() || !World || GetNetMode() == ENetMode::NM_Client || !GameplayDebugger::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)
{
GameplayDebugger& Debugger = GameplayDebugger::Get();
Debugger.CreateGameplayDebuggerForPlayerController(PC);
}
}
PlayerControllersUpdateDelay = 5;
}
#endif
}
bool AGameplayDebuggingReplicator::ServerSetActorToDebug_Validate(AActor* InActor)
{
return true;
}
void AGameplayDebuggingReplicator::ServerSetActorToDebug_Implementation(AActor* InActor)
{
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
if (LastSelectedActorToDebug != InActor)
{
LastSelectedActorToDebug = InActor;
UGameplayDebuggingComponent::OnDebuggingTargetChangedDelegate.Broadcast(InActor, InActor ? InActor->IsSelected() : false);
APawn* TargetPawn = Cast<APawn>(InActor);
if (TargetPawn)
{
FBehaviorTreeDelegates::OnDebugSelected.Broadcast(TargetPawn);
}
}
// @note patching up OR-9814
const UGameplayDebuggingComponent* DummyPointer = GetDebugComponent();
if (DebugComponent)
{
DebugComponent->SetActorToDebug(InActor);
}
#endif
}
void AGameplayDebuggingReplicator::OnDebugAIDelegate(class UCanvas* Canvas, class APlayerController* PC)
{
#if WITH_EDITOR && !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
if (!GIsEditor)
{
return;
}
if (!LocalPlayerOwner || IsGlobalInWorld())
{
return;
}
UEditorEngine* EEngine = Cast<UEditorEngine>(GEngine);
if (GFrameNumber == LastDrawAtFrame || !EEngine || !EEngine->bIsSimulatingInEditor)
{
return;
}
if (!Canvas || !Canvas->SceneView || Canvas->SceneView->bIsGameView == false)
{
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;
}
EnableDraw(true);
UWorld* World = GetWorld();
UGameplayDebuggingComponent* DebuggingComponent = GetDebugComponent();
if (World && DebuggingComponent && DebuggingComponent->GetOwnerRole() == ROLE_Authority)
{
UGameplayDebuggingControllerComponent* GDC = FindComponentByClass<UGameplayDebuggingControllerComponent>();
TArray<int32> OryginalReplicateViewDataCounters;
OryginalReplicateViewDataCounters = DebuggingComponent->ReplicateViewDataCounters;
for (uint32 Index = 0; Index < EAIDebugDrawDataView::MAX; ++Index)
{
DebuggingComponent->ReplicateViewDataCounters[Index] = GameplayDebuggerSettings(this).CheckFlag((EAIDebugDrawDataView::Type)Index) ? 1 : 0;
}
// looks like Simulate in UE4 Editor - let's find selected Pawn to debug
AActor* FullSelectedTarget = NULL;
for (FConstPawnIterator Iterator = World->GetPawnIterator(); Iterator; ++Iterator)
{
AActor* NewTarget = Cast<AActor>(*Iterator);
if (NewTarget->IsSelected() && !FullSelectedTarget)
{
FullSelectedTarget = NewTarget;
continue;
}
//We needs to collect data manually in Simulate
DebuggingComponent->SetActorToDebug(NewTarget);
DebuggingComponent->CollectDataToReplicate(NewTarget->IsSelected());
DrawDebugData(Canvas, PC);
}
const AActor* OldActor = LastSelectedActorToDebug;
ServerSetActorToDebug(FullSelectedTarget);
if (FullSelectedTarget)
{
DebuggingComponent->CollectDataToReplicate(true);
DebuggingComponent->SetEQSIndex(ActiveEQSIndex);
DrawDebugData(Canvas, PC);
}
if (GetSelectedActorToDebug() != OldActor)
{
DebuggingComponent->MarkRenderStateDirty();
}
DebuggingComponent->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() || !IsDrawEnabled())
{
return;
}
if (Canvas->SceneView != NULL && !Canvas->SceneView->bIsGameView)
{
return;
}
if (GFrameNumber == LastDrawAtFrame)
{
return;
}
LastDrawAtFrame = GFrameNumber;
const UGameplayDebuggingControllerComponent* GDC = FindComponentByClass<UGameplayDebuggingControllerComponent>();
if (!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)
{
ServerSetActorToDebug(NewTarget);
}
// @note patching up OR-9814
const UGameplayDebuggingComponent* DummyPointer = GetDebugComponent();
if (DebugComponent)
{
DebugComponent->SetActorToDebug(NewTarget);
DebugComponent->CollectDataToReplicate(true);
}
}
}
DrawDebugData(Canvas, PC);
#endif
}
void AGameplayDebuggingReplicator::DrawDebugData(class UCanvas* Canvas, class APlayerController* PC)
{
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
if (!LocalPlayerOwner)
{
return;
}
bool bAllowToDraw = Canvas && Canvas->SceneView && (Canvas->SceneView->ViewActor == LocalPlayerOwner->AcknowledgedPawn || Canvas->SceneView->ViewActor == LocalPlayerOwner->GetPawnOrSpectator());
if (!bAllowToDraw)
{
// check for spectator debug camera
UGameplayDebuggingControllerComponent* GDC = FindComponentByClass<UGameplayDebuggingControllerComponent>();
// bAllowToDraw here used to check GDC->GetDebugCameraController().IsValid(), but it doesn't seem to be necessary, and it was preventing display in some desired cases.
bAllowToDraw = GDC && (Canvas->SceneView->ViewActor->GetInstigatorController() == GDC->GetDebugCameraController().Get());
if (!bAllowToDraw)
{
return;
}
}
if (!DebugRenderer.IsValid() && DebugComponentHUDClass.IsValid())
{
FActorSpawnParameters SpawnInfo;
SpawnInfo.Owner = NULL;
SpawnInfo.Instigator = NULL;
SpawnInfo.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
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
}
void AGameplayDebuggingReplicator::DebugNextPawn(UClass* CompareClass, APawn* CurrentPawn)
{
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
APawn* LastSeen = nullptr;
APawn* FirstSeen = nullptr;
// Search through the list looking for the next one of this type
for (FConstPawnIterator It = GetWorld()->GetPawnIterator(); It; It++)
{
APawn* IterPawn = *It;
if (IterPawn->IsA(CompareClass))
{
if (LastSeen == CurrentPawn)
{
ServerSetActorToDebug(IterPawn);
return;
}
LastSeen = IterPawn;
if (FirstSeen == nullptr)
{
FirstSeen = IterPawn;
}
}
}
// See if we need to wrap around the list
if (FirstSeen != nullptr)
{
ServerSetActorToDebug(FirstSeen);
}
#endif
}
void AGameplayDebuggingReplicator::DebugPrevPawn(UClass* CompareClass, APawn* CurrentPawn)
{
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
APawn* LastSeen = nullptr;
APawn* PrevSeen = nullptr;
APawn* FirstSeen = nullptr;
// Search through the list looking for the prev one of this type
for (FConstPawnIterator It = GetWorld()->GetPawnIterator(); It; It++)
{
APawn* IterPawn = *It;
if (IterPawn->IsA(CompareClass))
{
if (LastSeen == CurrentPawn && FirstSeen != CurrentPawn)
{
ServerSetActorToDebug(PrevSeen);
return;
}
PrevSeen = LastSeen;
LastSeen = IterPawn;
if (FirstSeen == nullptr)
{
FirstSeen = IterPawn;
if (CurrentPawn == nullptr)
{
ServerSetActorToDebug(FirstSeen);
return;
}
}
}
}
// Wrap from the beginning to the end
if (FirstSeen == CurrentPawn)
{
ServerSetActorToDebug(LastSeen);
}
// Handle getting the previous to the end
else if (LastSeen == CurrentPawn)
{
ServerSetActorToDebug(PrevSeen);
}
#endif
}