AEyeXActorBase* AEyeXPlayerController::FindBySweep(FHitResult& OutHit, const FSceneView* const View, const FVector2D& GazePoint,
	const FCollisionObjectQueryParams& ObjectParams, const FCollisionQueryParams& TraceParams)
{
	if (SweepIntervals <= 1)
	{
		UE_LOG(LogEyeX, Warning, TEXT("Invalid value for SweepIntervals: %i. Must be greater than 0."), SweepIntervals);
		return nullptr;
	}

	UWorld* World = GetWorld();
	if (!World) return nullptr;

	FVector Start, Direction;
	View->DeprojectFVector2D(GazePoint, Start, Direction);

	const float TanFOVScaled = GetTanOfFOVAngleScaled();

	// Perform sweeps
	const float DeltaDistance = MaxDistance / SweepIntervals;
	const FVector DeltaDirection = DeltaDistance * Direction;
	float CurrentDistance = DeltaDistance / 2;
	FCollisionShape Shape;
	AEyeXActorBase* EyeXActor = nullptr;
	for (int i = 0; i < SweepIntervals; ++i)	
	{
		const FVector End = Start + DeltaDirection;
		const float Radius = (i == 0) ? 0.0f : TanFOVScaled * CurrentDistance; // Depends on the view frustrum, size of the screen and the distance.
		Shape.SetSphere(Radius);

		if (World->SweepSingleByObjectType(OutHit, Start, End, FQuat::Identity, ObjectParams, Shape, TraceParams))
		{
			EyeXActor = Cast<AEyeXActorBase>(OutHit.GetActor());
			break;
		}

		Start = End;
		CurrentDistance += DeltaDistance;
	}
	
	VisualizeHit(bVisualizeDetection, World, OutHit, Shape.GetSphereRadius());
	VisualizeGazePoint(bVisualizeDetection, World, Start);

	return EyeXActor;
}
UCollision2PGeom::UCollision2PGeom(const FCollisionShape& CollisionShape)
{
	switch (CollisionShape.ShapeType)
	{
		case ECollisionShape::Box:
		{
			new (Storage)PxBoxGeometry(U2PVector(CollisionShape.GetBox()));
			break;
		}
		case ECollisionShape::Sphere:
		{
			new (Storage)PxSphereGeometry(CollisionShape.GetSphereRadius());
			break;
		}
		case ECollisionShape::Capsule:
		{
			new (Storage)PxCapsuleGeometry(CollisionShape.GetCapsuleRadius(), CollisionShape.GetCapsuleAxisHalfLength());
			break;
		}
		default:
			// invalid point
			ensure(false);
	}
}
float UAISense_Aquaphobia::Update()
{
	AIPerception::FListenerMap& ListenersMap = *GetListeners();

	//For each listener who has this sense we're going to perform a sweep to determine nearby aqua actors
	for (auto& Elem : ListenersMap)
	{
		//Get the listener
		FPerceptionListener Listener = Elem.Value;
		const AActor* ListenerBodyActor = Listener.GetBodyActor();

		for (int32 DigestedPropertyIndex = 0; DigestedPropertyIndex < DigestedProperties.Num(); DigestedPropertyIndex++)
		{
			//Create the sphere for this sense and perform the sweep to determine nearby actors
			FCollisionShape CollisionSphere = FCollisionShape::MakeSphere(DigestedProperties[DigestedPropertyIndex].PhobiaRadius);
			TArray<FHitResult> HitResults;
			GetWorld()->SweepMultiByChannel(HitResults, ListenerBodyActor->GetActorLocation(), ListenerBodyActor->GetActorLocation() + FVector::UpVector*CollisionSphere.GetSphereRadius(), FQuat(), ECollisionChannel::ECC_WorldDynamic, CollisionSphere);

			//Draw debug sphere if we have activated it via the config
			if (DigestedProperties[DigestedPropertyIndex].bDisplayDebugSphere)
			{
				DrawDebugSphere(GetWorld(), ListenerBodyActor->GetActorLocation(), DigestedProperties[DigestedPropertyIndex].PhobiaRadius, 8, FColor::Blue, false, 30.f, 1, 2.f);
			}
			

			//Check hit results for aqua actors
			for (int32 i = 0; i < HitResults.Num(); i++)
			{
				FHitResult hit = HitResults[i];
				//To simplify things, we're going to assume that "water resources" for this post are actors that have the following game tag
				if (hit.GetActor()->ActorHasTag(FName("AquaActor")))
				{
					if ((hit.GetActor()->GetActorLocation() - ListenerBodyActor->GetActorLocation()).Size() <= DigestedProperties[DigestedPropertyIndex].PhobiaRadius)
					{
						Elem.Value.RegisterStimulus(hit.GetActor(), FAIStimulus(*this, 5.f, hit.GetActor()->GetActorLocation(), ListenerBodyActor->GetActorLocation()));
						GLog->Log("registered stimulus!");
					}

				}

			}
		}
		
		
	}
	//Time until next update; in this case we're forcing the update to happen in each frame
	return 0.f;
}