void AGameplayDebuggingReplicator::EnableTool()
{
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
	if (GetWorld() && GetNetMode() != ENetMode::NM_DedicatedServer)
	{
		UGameplayDebuggingControllerComponent*  GDC = FindComponentByClass<UGameplayDebuggingControllerComponent>();
		if (GDC)
		{
			// simulate key press
			GDC->OnActivationKeyPressed();
			GDC->OnActivationKeyReleased();
		}
	}
#endif
}
void AGameplayDebuggingHUDComponent::DrawNavMeshSnapshot(APlayerController* PC, class UGameplayDebuggingComponent *DebugComponent)
{
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
	if (DebugComponent && DebugComponent->NavmeshRepData.Num())
	{
		UGameplayDebuggingControllerComponent*  GDC = PC ? PC->FindComponentByClass<UGameplayDebuggingControllerComponent>() : NULL;
		FString NextUpdateDesc;
		if (GDC)
		{
			const float TimeLeft = GDC->GetUpdateNavMeshTimeRemaining();
			NextUpdateDesc = FString::Printf(TEXT(", next update: {yellow}%.1fs"), TimeLeft);
		}

		PrintString(DefaultContext, FString::Printf(TEXT("\n\n{green}Showing NavMesh (%.1fkB)%s\n"),
			DebugComponent->NavmeshRepData.Num() / 1024.0f, *NextUpdateDesc));
	}
#endif //!(UE_BUILD_SHIPPING || UE_BUILD_TEST)
}
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 = GDC && GDC->GetDebugCameraController().IsValid() && 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::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 AGameplayDebuggingHUDComponent::DrawMenu(const float X, const float Y, class UGameplayDebuggingComponent* DebugComponent)
{
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
	const float OldX = DefaultContext.CursorX;
	const float OldY = DefaultContext.CursorY;

	UGameplayDebuggingControllerComponent*  GDC = GetDebuggingReplicator()->FindComponentByClass<UGameplayDebuggingControllerComponent>();
	if (DefaultContext.Canvas != NULL)
	{
		TArray<FDebugCategoryView> Categories;
		GetKeyboardDesc(Categories);

		UFont* OldFont = DefaultContext.Font;
		DefaultContext.Font = GEngine->GetMediumFont();

		TArray<float> CategoriesWidth;
		CategoriesWidth.AddZeroed(Categories.Num());
		float TotalWidth = 0.0f, MaxHeight = 0.0f;

		FString ActivationKeyDisplayName = TEXT("'");
		FString ActivationKeyName = TEXT("Apostrophe");

		APlayerController* const MyPC = Cast<APlayerController>(PlayerOwner);
		if (GDC)
		{
			ActivationKeyDisplayName = GDC->GetActivationKey().Key.GetDisplayName().ToString();
			ActivationKeyName = GDC->GetActivationKey().Key.GetFName().ToString();
		}

		const FString KeyDesc = ActivationKeyName != ActivationKeyDisplayName ? FString::Printf(TEXT("(%s key)"), *ActivationKeyName) : TEXT("");
		FString HeaderDesc = FString::Printf(TEXT("Tap %s %s to close, use Numpad numbers to toggle categories"), *ActivationKeyDisplayName, *KeyDesc);

		float HeaderWidth = 0.0f;
		CalulateStringSize(DefaultContext, DefaultContext.Font, HeaderDesc, HeaderWidth, MaxHeight);

		for (int32 i = 0; i < Categories.Num(); i++)
		{
			Categories[i].Desc = FString::Printf(TEXT("%d:%s "), i, *Categories[i].Desc);

			float StrHeight = 0.0f;
			CalulateStringSize(DefaultContext, DefaultContext.Font, Categories[i].Desc, CategoriesWidth[i], StrHeight);
			TotalWidth += CategoriesWidth[i];
			MaxHeight = FMath::Max(MaxHeight, StrHeight);
		}

		{
			static FString KeyShortcut = GDC->DebugCameraBind.GetInputText().ToString();
			const int32 DebugCameraIndex = Categories.Add(FDebugCategoryView());
			CategoriesWidth.AddZeroed(1);
			Categories[DebugCameraIndex].Desc = FString::Printf(TEXT(" %s[%s]: %s  "), GDC && GDC->GetDebugCameraController().IsValid() ? TEXT("{Green}") : TEXT("{White}"), *KeyShortcut, TEXT("Debug Camera"));
			float StrHeight = 0.0f;
			CalulateStringSize(DefaultContext, DefaultContext.Font, Categories[DebugCameraIndex].Desc, CategoriesWidth[DebugCameraIndex], StrHeight);
			TotalWidth += CategoriesWidth[DebugCameraIndex];
			MaxHeight = FMath::Max(MaxHeight, StrHeight);
		}
		{
			static FString KeyShortcut = GDC->OnScreenDebugMessagesBind.GetInputText().ToString();
			const int32 DebugCameraIndex = Categories.Add(FDebugCategoryView());
			CategoriesWidth.AddZeroed(1);
			Categories[DebugCameraIndex].Desc = FString::Printf(TEXT(" %s[%s]: %s  "), GEngine && GEngine->bEnableOnScreenDebugMessages ? TEXT("{Green}") : TEXT("{White}"), *KeyShortcut, TEXT("DebugMessages"));
			float StrHeight = 0.0f;
			CalulateStringSize(DefaultContext, DefaultContext.Font, Categories[DebugCameraIndex].Desc, CategoriesWidth[DebugCameraIndex], StrHeight);
			TotalWidth += CategoriesWidth[DebugCameraIndex];
			MaxHeight = FMath::Max(MaxHeight, StrHeight);
		}
		{
			static FString KeyShortcut = GDC->GameHUDBind.GetInputText().ToString();
			const AHUD* GameHUD = MyPC ? MyPC->GetHUD() : NULL;
			const int32 DebugCameraIndex = Categories.Add(FDebugCategoryView());
			CategoriesWidth.AddZeroed(1);
			Categories[DebugCameraIndex].Desc = FString::Printf(TEXT(" %s[%s]: %s  "), GameHUD && GameHUD->bShowHUD ? TEXT("{Green}") : TEXT("{White}"), *KeyShortcut, TEXT("GameHUD"));
			float StrHeight = 0.0f;
			CalulateStringSize(DefaultContext, DefaultContext.Font, Categories[DebugCameraIndex].Desc, CategoriesWidth[DebugCameraIndex], StrHeight);
			TotalWidth += CategoriesWidth[DebugCameraIndex];
			MaxHeight = FMath::Max(MaxHeight, StrHeight);
		}


		TotalWidth = FMath::Max(TotalWidth, HeaderWidth);

		FCanvasTileItem TileItem(FVector2D(10, 10), GWhiteTexture, FVector2D(TotalWidth + 20, MaxHeight + 20), FColor(0, 0, 0, 20));
		TileItem.BlendMode = SE_BLEND_Translucent;
		DrawItem(DefaultContext, TileItem, MenuStartX, MenuStartY);

		PrintString(DefaultContext, FColorList::LightBlue, HeaderDesc, MenuStartX + 2.f, MenuStartY + 2.f);

		float XPos = MenuStartX + 20.f;
		for (int32 i = 0; i < Categories.Num(); i++)
		{
			const bool bIsActive = GameplayDebuggerSettings(GetDebuggingReplicator()).CheckFlag(Categories[i].View) ? true : false;
			const bool bIsDisabled = Categories[i].View == EAIDebugDrawDataView::NavMesh ? false : (DebugComponent && DebugComponent->GetSelectedActor() ? false: true);

			PrintString(DefaultContext, bIsDisabled ? (bIsActive ? FColorList::DarkGreen  : FColorList::LightGrey) : (bIsActive ? FColorList::Green : FColorList::White), Categories[i].Desc, XPos, MenuStartY + MaxHeight + 2.f);
			XPos += CategoriesWidth[i];
		}
		DefaultContext.Font = OldFont;
	}

	if ((!DebugComponent || !DebugComponent->GetSelectedActor()) && GetWorld()->GetNetMode() == NM_Client)
	{
		PrintString(DefaultContext, "\n{red}No Pawn selected - waiting for data to replicate from server. {green}Press and hold ' to select Pawn \n");
	}

	if (GDC && GDC->GetDebugCameraController().IsValid())
	{
		ADebugCameraController* DebugCamController = GDC->GetDebugCameraController().Get();
		if (DebugCamController != NULL)
		{
			FVector const CamLoc = DebugCamController->PlayerCameraManager->GetCameraLocation();
			FRotator const CamRot = DebugCamController->PlayerCameraManager->GetCameraRotation();

			FString HitString;
			FCollisionQueryParams TraceParams(NAME_None, true, this);
			FHitResult Hit;
			bool bHit = GetWorld()->LineTraceSingleByChannel(Hit, CamLoc, CamRot.Vector() * 100000.f + CamLoc, ECC_Pawn, TraceParams);
			if (bHit && Hit.GetActor() != nullptr)
			{
				HitString = FString::Printf(TEXT("{white}Under cursor: {yellow}'%s'"), *Hit.GetActor()->GetName());
				DrawDebugLine(GetWorld(), Hit.Location, Hit.Location + Hit.Normal*30.f, FColor::White);
			}
			else
			{
				HitString = FString::Printf(TEXT("Not actor under cursor"));
			}

			PrintString(DefaultContext, FColor::White, HitString, MenuStartX, MenuStartY + 40);
		}
	}


	DefaultContext.CursorX = OldX;
	DefaultContext.CursorY = OldY;
#endif //!(UE_BUILD_SHIPPING || UE_BUILD_TEST)
}