Files
UnrealEngineUWP/Engine/Source/Developer/GameplayDebugger/Private/GameplayDebugger.cpp
Ben Zeigler 02a9e1dd4e Merging Dev -> Main using UE4-Fortnite-To-UE4 from CL 2340802
Includes following engine changes:

Getting display metrics only once at construct time when using SSafeZone. GetDisplayMetrics is expensive in Windows so it is impractical to call it every frame.
- Some AI API improvements, mostly switchig pointer function parameters to references.
- minor refactor of UCrowdFollowingComponent's queryinf functions:
    - IsCrowd*Enabled functions refactored to  IsCrowd*Active
    - implemented IsCrowd*Enabled that return acrual values of relevant properties
- Added a function to CrowdManager to query for location of agents neighbouring given agent
Added support for PS4 touchpad-based cursor
You can now choose to skip synchronously scanning for asset data in object libraries and just use the data that is currently in the asset registry. The data will be refereshed automatically later once the global scan completes. The only applies to non-commandlet editor instances.
Crash fixes for trying to access NULL Metal surfaces on IOS
Slate: Cleaned up some atlas code related to padding and corrected some comments

[CL 2347323 by Ben Zeigler in Main branch]
2014-11-03 15:47:28 -05:00

393 lines
10 KiB
C++

// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.
#include "GameplayDebuggerPrivate.h"
#include "Misc/CoreMisc.h"
#include "GameplayDebuggingComponent.h"
#include "GameplayDebuggingHUDComponent.h"
#include "GameplayDebuggingReplicator.h"
#include "GameplayDebuggingControllerComponent.h"
#include "AISystem.h"
#if WITH_EDITOR
#include "Editor/EditorEngine.h"
#endif // WITH_EDITOR
uint32 FGameplayDebuggerSettings::ShowFlagIndex = 0;
FGameplayDebuggerSettings GameplayDebuggerSettings(class AGameplayDebuggingReplicator* Replicator)
{
static uint32 Settings = (1 << EAIDebugDrawDataView::Basic) | (1 << EAIDebugDrawDataView::OverHead);
return FGameplayDebuggerSettings(Replicator == NULL ? Settings : Replicator->DebuggerShowFlags);
}
class FGameplayDebugger : public FSelfRegisteringExec, public IGameplayDebugger
{
public:
// Begin IModuleInterface
virtual void StartupModule() override;
virtual void ShutdownModule() override;
// End IModuleInterface
void WorldAdded(UWorld* InWorld);
void WorldDestroyed(UWorld* InWorld);
#if WITH_EDITOR
void OnLevelActorAdded(AActor* InActor);
void OnLevelActorDeleted(AActor* InActor);
#endif
TArray<TWeakObjectPtr<AGameplayDebuggingReplicator> >& GetAllReplicators(UWorld* InWorld);
void AddReplicator(UWorld* InWorld, AGameplayDebuggingReplicator* InReplicator);
void RemoveReplicator(UWorld* InWorld, AGameplayDebuggingReplicator* InReplicator);
// Begin FExec Interface
virtual bool Exec(UWorld* Inworld, const TCHAR* Cmd, FOutputDevice& Ar) override;
// End FExec Interface
private:
virtual bool CreateGameplayDebuggerForPlayerController(APlayerController* PlayerController) override;
bool DoesGameplayDebuggingReplicatorExistForPlayerController(APlayerController* PlayerController);
TMap<TWeakObjectPtr<UWorld>, TArray<TWeakObjectPtr<AGameplayDebuggingReplicator> > > AllReplilcatorsPerWorlds;
};
IMPLEMENT_MODULE(FGameplayDebugger, GameplayDebugger)
// This code will execute after your module is loaded into memory (but after global variables are initialized, of course.)
void FGameplayDebugger::StartupModule()
{
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
if (GEngine)
{
GEngine->OnWorldAdded().AddRaw(this, &FGameplayDebugger::WorldAdded);
GEngine->OnWorldDestroyed().AddRaw(this, &FGameplayDebugger::WorldDestroyed);
#if WITH_EDITOR
GEngine->OnLevelActorAdded().AddRaw(this, &FGameplayDebugger::OnLevelActorAdded);
GEngine->OnLevelActorDeleted().AddRaw(this, &FGameplayDebugger::OnLevelActorDeleted);
#endif
}
#endif
}
// This function may be called during shutdown to clean up your module. For modules that support dynamic reloading,
// we call this function before unloading the module.
void FGameplayDebugger::ShutdownModule()
{
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
if (GEngine)
{
GEngine->OnWorldAdded().RemoveAll(this);
GEngine->OnWorldDestroyed().RemoveAll(this);
#if WITH_EDITOR
GEngine->OnLevelActorAdded().RemoveAll(this);
GEngine->OnLevelActorDeleted().RemoveAll(this);
#endif
}
#endif
}
bool FGameplayDebugger::DoesGameplayDebuggingReplicatorExistForPlayerController(APlayerController* PlayerController)
{
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
if (PlayerController == NULL)
{
return false;
}
UWorld* World = PlayerController->GetWorld();
if (World == NULL)
{
return false;
}
for (auto It = GetAllReplicators(World).CreateConstIterator(); It; ++It)
{
TWeakObjectPtr<AGameplayDebuggingReplicator> Replicator = *It;
if (Replicator.IsValid())
{
if (Replicator->GetLocalPlayerOwner() == PlayerController)
{
return true;
}
}
}
#endif
return false;
}
bool FGameplayDebugger::CreateGameplayDebuggerForPlayerController(APlayerController* PlayerController)
{
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
if (PlayerController == NULL)
{
return false;
}
bool bIsServer = PlayerController->GetNetMode() < ENetMode::NM_Client; // (Only create on some sort of server)
if (!bIsServer)
{
return false;
}
UWorld* World = PlayerController->GetWorld();
if (World == NULL)
{
return false;
}
if (DoesGameplayDebuggingReplicatorExistForPlayerController(PlayerController))
{
// No need to create one if we already have one.
return false;
}
FActorSpawnParameters SpawnInfo;
SpawnInfo.bNoCollisionFail = true;
SpawnInfo.Name = *FString::Printf(TEXT("GameplayDebuggingReplicator_%s"), *PlayerController->GetName());
AGameplayDebuggingReplicator* DestActor = World->SpawnActor<AGameplayDebuggingReplicator>(SpawnInfo);
if (DestActor != NULL)
{
DestActor->SetLocalPlayerOwner(PlayerController);
DestActor->SetReplicates(true);
DestActor->SetAsGlobalInWorld(false);
#if WITH_EDITOR
UEditorEngine* EEngine = Cast<UEditorEngine>(GEngine);
if (EEngine && EEngine->bIsSimulatingInEditor)
{
DestActor->CreateTool();
DestActor->EnableTool();
}
#endif
AddReplicator(World, DestActor);
return true;
}
#endif
return false;
}
TArray<TWeakObjectPtr<AGameplayDebuggingReplicator> >& FGameplayDebugger::GetAllReplicators(UWorld* InWorld)
{
return AllReplilcatorsPerWorlds.FindOrAdd(InWorld);
}
void FGameplayDebugger::AddReplicator(UWorld* InWorld, AGameplayDebuggingReplicator* InReplicator)
{
GetAllReplicators(InWorld).Add(InReplicator);
}
void FGameplayDebugger::RemoveReplicator(UWorld* InWorld, AGameplayDebuggingReplicator* InReplicator)
{
GetAllReplicators(InWorld).RemoveSwap(InReplicator);
}
void FGameplayDebugger::WorldAdded(UWorld* InWorld)
{
bool bIsServer = InWorld && InWorld->GetNetMode() < ENetMode::NM_Client; // (Only server code)
if (!bIsServer)
{
return;
}
for (auto It = GetAllReplicators(InWorld).CreateConstIterator(); It; ++It)
{
TWeakObjectPtr<AGameplayDebuggingReplicator> Replicator = *It;
if (Replicator.IsValid() && Replicator->IsGlobalInWorld())
{
// Ok, we have global replicator on level
return;
}
}
// create global replicator on level
FActorSpawnParameters SpawnInfo;
SpawnInfo.bNoCollisionFail = true;
SpawnInfo.Name = *FString::Printf(TEXT("GameplayDebuggingReplicator_Global"));
AGameplayDebuggingReplicator* DestActor = InWorld->SpawnActor<AGameplayDebuggingReplicator>(SpawnInfo);
if (DestActor != NULL)
{
DestActor->SetLocalPlayerOwner(NULL);
DestActor->SetReplicates(false);
DestActor->SetActorTickEnabled(true);
DestActor->SetAsGlobalInWorld(true);
AddReplicator(InWorld, DestActor);
}
}
void FGameplayDebugger::WorldDestroyed(UWorld* InWorld)
{
bool bIsServer = InWorld && InWorld->GetNetMode() < ENetMode::NM_Client; // (Only work on server)
if (!bIsServer)
{
return;
}
// remove global replicator from level
AllReplilcatorsPerWorlds.Remove(InWorld);
}
#if WITH_EDITOR
void FGameplayDebugger::OnLevelActorAdded(AActor* InActor)
{
// This function doesn't help much, because it's only called in EDITOR!
// We need a function that is called in the game! So instead of creating it automatically, I'm leaving it
// to be created explicitly by any player controller that needs to create it.
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
APlayerController* PC = Cast<APlayerController>(InActor);
if (PC && PC->GetNetMode() < ENetMode::NM_Client)
{
CreateGameplayDebuggerForPlayerController(PC);
}
#endif
}
void FGameplayDebugger::OnLevelActorDeleted(AActor* InActor)
{
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
APlayerController* PC = Cast<APlayerController>(InActor);
if (!PC)
{
return;
}
UWorld* World = PC->GetWorld();
if (!World)
{
return;
}
for (auto It = GetAllReplicators(World).CreateConstIterator(); It; ++It)
{
TWeakObjectPtr<AGameplayDebuggingReplicator> Replicator = *It;
if (Replicator != NULL)
{
if (Replicator->GetLocalPlayerOwner() == PC)
{
RemoveReplicator(World, Replicator.Get());
World->DestroyActor(Replicator.Get());
}
}
}
#endif
}
#endif //WITH_EDITOR
bool FGameplayDebugger::Exec(UWorld* Inworld, const TCHAR* Cmd, FOutputDevice& Ar)
{
bool bHandled = false;
APlayerController* PC = Inworld ? Inworld->GetFirstPlayerController() : NULL;
if (!Inworld || !PC)
{
return bHandled;
}
if (FParse::Command(&Cmd, TEXT("EnableGDT")))
{
AGameplayDebuggingReplicator* Replicator = NULL;
for (TActorIterator<AGameplayDebuggingReplicator> It(Inworld); It; ++It)
{
Replicator = *It;
if (Replicator && !Replicator->IsPendingKill())
{
APlayerController* LocalPC = Replicator->GetLocalPlayerOwner();
if (LocalPC == PC)
{
break;
}
}
Replicator = NULL;
}
if (Inworld->GetNetMode() == NM_Client)
{
if (!Replicator)
{
PC->ConsoleCommand("cheat EnableGDT");
bHandled = true;
}
else if (!Replicator->IsToolCreated())
{
Replicator->CreateTool();
Replicator->EnableTool();
bHandled = true;
}
}
else if (Inworld->GetNetMode() < NM_Client)
{
if (!Replicator)
{
CreateGameplayDebuggerForPlayerController(PC);
for (TActorIterator<AGameplayDebuggingReplicator> It(Inworld); It; ++It)
{
Replicator = *It;
if (Replicator && !Replicator->IsPendingKill())
{
APlayerController* LocalPC = Replicator->GetLocalPlayerOwner();
if (LocalPC == PC)
{
break;
}
}
Replicator = NULL;
}
}
if (Inworld->GetNetMode() != NM_DedicatedServer)
{
if (Replicator && !Replicator->IsToolCreated())
{
Replicator->CreateTool();
Replicator->EnableTool();
bHandled = true;
}
}
else
{
if (Replicator)
{
Replicator->bAutoActivate = true;;
bHandled = true;
}
}
}
}
else if (FParse::Command(&Cmd, TEXT("RunEQS")))
{
bHandled = true;
APlayerController* MyPC = Inworld->GetFirstPlayerController();
UAISystem* AISys = UAISystem::GetCurrent(*Inworld);
UEnvQueryManager* EQS = AISys ? AISys->GetEnvironmentQueryManager() : NULL;
if (MyPC && EQS)
{
AGameplayDebuggingReplicator* DebuggingReplicator = NULL;
for (TActorIterator<AGameplayDebuggingReplicator> It(Inworld); It; ++It)
{
AGameplayDebuggingReplicator* A = *It;
if (!A->IsPendingKill())
{
DebuggingReplicator = A;
if (!DebuggingReplicator->IsGlobalInWorld() && DebuggingReplicator->GetLocalPlayerOwner() == MyPC)
{
break;
}
}
}
UObject* Target = DebuggingReplicator != NULL ? DebuggingReplicator->GetSelectedActorToDebug() : NULL;
FString QueryName = FParse::Token(Cmd, 0);
if (Target)
{
AISys->RunEQS(QueryName, Target);
}
else
{
MyPC->ClientMessage(TEXT("No debugging target to run EQS"));
}
}
}
return bHandled;
}