void FGameplayDebuggerCategory_AI::DrawPawnIcons(UWorld* World, AActor* DebugActor, APawn* SkipPawn, FGameplayDebuggerCanvasContext& CanvasContext) { FString FailsafeIcon = TEXT("/Engine/EngineResources/AICON-Green.AICON-Green"); for (FConstPawnIterator It = World->GetPawnIterator(); It; ++It) { const APawn* ItPawn = *It; if (IsValid(ItPawn) && SkipPawn != ItPawn) { const FVector IconLocation = ItPawn->GetActorLocation() + FVector(0, 0, ItPawn->GetSimpleCollisionHalfHeight()); const AAIController* ItAI = Cast<const AAIController>(ItPawn->GetController()); FString DebugIconPath = IsValid(ItAI) ? ItAI->GetDebugIcon() : FailsafeIcon; if (CanvasContext.IsLocationVisible(IconLocation) && DebugIconPath.Len()) { UTexture2D* IconTexture = (UTexture2D*)StaticLoadObject(UTexture2D::StaticClass(), NULL, *DebugIconPath, NULL, LOAD_NoWarn | LOAD_Quiet, NULL); FCanvasIcon CanvasIcon = UCanvas::MakeIcon(IconTexture); if (CanvasIcon.Texture) { const FVector2D ScreenLoc = CanvasContext.ProjectLocation(IconLocation); const float IconSize = (DebugActor == ItPawn) ? 32.0f : 16.0f; CanvasContext.DrawIcon(FColor::White, CanvasIcon, ScreenLoc.X, ScreenLoc.Y - IconSize, IconSize / CanvasIcon.Texture->GetSurfaceWidth()); } } } } }
void FGameplayDebuggerCategory_AI::DrawData(APlayerController* OwnerPC, FGameplayDebuggerCanvasContext& CanvasContext) { const bool bReducedMode = IsSimulateInEditor(); bShowCategoryName = !bReducedMode; UWorld* MyWorld = OwnerPC->GetWorld(); AActor* SelectedActor = FindLocalDebugActor(); DrawPawnIcons(MyWorld, SelectedActor, OwnerPC ? OwnerPC->GetPawn() : nullptr, CanvasContext); if (bReducedMode) { if (DataPack.bHasController) { DrawPath(MyWorld); } } else { if (SelectedActor) { DrawOverheadInfo(*SelectedActor, CanvasContext); } DrawPath(MyWorld); } const bool bShowClassNames = !bReducedMode || DataPack.bHasController; if (bShowClassNames) { CanvasContext.Printf(TEXT("Controller Name: {yellow}%s"), *DataPack.ControllerName); CanvasContext.Printf(TEXT("Pawn Name: {yellow}%s"), *DataPack.PawnName); } if (DataPack.bIsUsingCharacter) { CanvasContext.Printf(TEXT("Movement Mode: {yellow}%s{white}, Base: {yellow}%s"), *DataPack.MovementModeInfo, *DataPack.MovementBaseInfo); CanvasContext.Printf(TEXT("NavData: {yellow}%s{white}, Path following: {yellow}%s"), *DataPack.NavDataInfo, *DataPack.PathFollowingInfo); } if (DataPack.bIsUsingBehaviorTree) { CanvasContext.Printf(TEXT("Behavior: {yellow}%s{white}, Tree: {yellow}%s"), *DataPack.CurrentAIState, *DataPack.CurrentAIAssets); CanvasContext.Printf(TEXT("Active task: {yellow}%s"), *DataPack.CurrentAITask); } if (DataPack.bIsUsingGameplayTasks) { if (DataPack.NumTickingTasks > 0) { CanvasContext.Printf(TEXT("Ticking tasks: {yellow}%d%s"), DataPack.NumTickingTasks, *DataPack.TickingTaskInfo); } CanvasContext.Printf(TEXT("Gameplay tasks: {yellow}%d%s"), DataPack.NumTasksInQueue, *DataPack.TaskQueueInfo); } if (DataPack.bIsUsingCharacter) { CanvasContext.Printf(TEXT("Montage: {yellow}%s"), *DataPack.MontageInfo); } }
void FGameplayDebuggerCategory_AI::DrawOverheadInfo(AActor& DebugActor, FGameplayDebuggerCanvasContext& CanvasContext) { const FVector OverheadLocation = DebugActor.GetActorLocation() + FVector(0, 0, DebugActor.GetSimpleCollisionHalfHeight()); if (CanvasContext.IsLocationVisible(OverheadLocation)) { FGameplayDebuggerCanvasContext OverheadContext(CanvasContext); OverheadContext.Font = GEngine->GetSmallFont(); OverheadContext.FontRenderInfo.bEnableShadow = true; const FVector2D ScreenLoc = OverheadContext.ProjectLocation(OverheadLocation); FString ActorDesc = FString::Printf(TEXT("{yellow}%s {white}%s"), *DataPack.ControllerName, *DataPack.PawnName); float SizeX = 0.0f, SizeY = 0.0f; OverheadContext.MeasureString(ActorDesc, SizeX, SizeY); OverheadContext.PrintAt(ScreenLoc.X - (SizeX * 0.5f), ScreenLoc.Y - (SizeY * 1.2f), ActorDesc); } }
void FGameplayDebuggerShape::Draw(UWorld* World, FGameplayDebuggerCanvasContext& Context) { FVector DescLocation; switch (Type) { case EGameplayDebuggerShape::Point: if (ShapeData.Num() == 2 && ShapeData[1].X > 0) { DrawDebugSphere(World, ShapeData[0], ShapeData[1].X, 16, Color); DescLocation = ShapeData[0]; } break; case EGameplayDebuggerShape::Segment: if (ShapeData.Num() == 3 && ShapeData[2].X > 0) { DrawDebugLine(World, ShapeData[0], ShapeData[1], Color, false, -1.0f, 0, ShapeData[2].X); DescLocation = (ShapeData[0] + ShapeData[1]) * 0.5f; } break; case EGameplayDebuggerShape::Box: if (ShapeData.Num() == 2) { DrawDebugBox(World, ShapeData[0], ShapeData[1], Color); DescLocation = ShapeData[0]; } break; case EGameplayDebuggerShape::Cone: if (ShapeData.Num() == 3 && ShapeData[2].X > 0) { DrawDebugCone(World, ShapeData[0], ShapeData[1], ShapeData[2].X, PI * 0.5f, PI * 0.5f, 16, Color); DescLocation = ShapeData[0]; } break; case EGameplayDebuggerShape::Cylinder: if (ShapeData.Num() == 2) { DrawDebugCylinder(World, ShapeData[0] - FVector(0, 0, ShapeData[1].Z), ShapeData[0] + FVector(0, 0, ShapeData[1].Z), ShapeData[1].X, 16, Color); DescLocation = ShapeData[0]; } break; case EGameplayDebuggerShape::Capsule: if (ShapeData.Num() == 2) { DrawDebugCapsule(World, ShapeData[0], ShapeData[1].Z, ShapeData[1].X, FQuat::Identity, Color); DescLocation = ShapeData[0]; } break; case EGameplayDebuggerShape::Polygon: if (ShapeData.Num() > 0) { FVector MidPoint = FVector::ZeroVector; TArray<int32> Indices; for (int32 Idx = 0; Idx < ShapeData.Num(); Idx++) { Indices.Add(Idx); MidPoint += ShapeData[Idx]; } DrawDebugMesh(World, ShapeData, Indices, Color); DescLocation = MidPoint / ShapeData.Num(); } break; default: break; } if (Description.Len() && Context.IsLocationVisible(DescLocation)) { const FVector2D ScreenLoc = Context.ProjectLocation(DescLocation); Context.PrintAt(ScreenLoc.X, ScreenLoc.Y, Color, Description); } }