AEyeXActorBase* AEyeXPlayerController::FindBySweep(FHitResult& OutHit, const FSceneView* const View, const FVector2D& GazePoint,
	const FCollisionQueryParams& TraceParams, const FCollisionObjectQueryParams& ObjectParams)
{
	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->SweepSingle(OutHit, Start, End, FQuat::Identity, Shape, TraceParams, ObjectParams))
		{
			EyeXActor = Cast<AEyeXActorBase>(OutHit.GetActor());
			break;
		}

		Start = End;
		CurrentDistance += DeltaDistance;
	}

	VisualizeHit(bVisualizeDetection, World, OutHit, Shape.GetSphereRadius());
	VisualizeGazePoint(bVisualizeDetection, World, Start);

	return EyeXActor;
}
bool AGameplayAbilityTargetActor_GroundTrace::AdjustCollisionResultForShape(const FVector OriginalStartPoint, const FVector OriginalEndPoint, const FCollisionQueryParams Params, FHitResult& OutHitResult) const
{
	UWorld *ThisWorld = GetWorld();
	//Pull back toward player to find a better spot, accounting for the width of our object
	FVector Movement = (OriginalEndPoint - OriginalStartPoint);
	FVector MovementDirection = Movement.SafeNormal();
	float MovementMagnitude2D = Movement.Size2D();

	if (bDebug)
	{
		if (CollisionHeight > 0.0f)
		{
			DrawDebugCapsule(ThisWorld, OriginalEndPoint, CollisionHeight * 0.5f, CollisionRadius, FQuat::Identity, FColor::Black);
		}
		else
		{
			DrawDebugSphere(ThisWorld, OriginalEndPoint, CollisionRadius, 8, FColor::Black);
		}
	}

	if ((MovementMagnitude2D < (CollisionRadius * 2.0f)) || (CollisionRadius <= 1.0f))
	{
		return false;		//Bad case!
	}

	float IncrementSize = FMath::Clamp<float>(CollisionRadius * 0.5f, 25.0f, 250.0f);
	float LerpIncrement = IncrementSize / MovementMagnitude2D;
	FHitResult LocalResult;
	FVector TraceStart;
	FVector TraceEnd;
	//This needs to ramp up - the first few increments should be small, then we should start moving in larger steps.
	for (float LerpValue = CollisionRadius / MovementMagnitude2D; LerpValue < 1.0f; LerpValue += LerpIncrement)
	{
		TraceEnd = TraceStart = OriginalEndPoint - (LerpValue * Movement);
		TraceEnd.Z -= 99999.0f;
		ThisWorld->SweepSingle(LocalResult, TraceStart, TraceEnd, FQuat::Identity, TraceChannel, CollisionShape, Params);
		if (!LocalResult.bStartPenetrating)
		{
			if (!LocalResult.bBlockingHit)
			{
				//This is probably off the map and should not be considered valid. This should not happen in a non-debug map.
				if (bDebug)
				{
					if (CollisionHeight > 0.0f)
					{
						DrawDebugCapsule(ThisWorld, LocalResult.Location, CollisionHeight * 0.5f, CollisionRadius, FQuat::Identity, FColor::Yellow);
					}
					else
					{
						DrawDebugSphere(ThisWorld, LocalResult.Location, CollisionRadius, 8, FColor::Yellow);
					}
				}
				continue;
				//LocalResult.Location = TraceStart;
			}
			if (bDebug)
			{
				if (CollisionHeight > 0.0f)
				{
					DrawDebugCapsule(ThisWorld, LocalResult.Location, CollisionHeight * 0.5f, CollisionRadius, FQuat::Identity, FColor::Green);
				}
				else
				{
					DrawDebugSphere(ThisWorld, LocalResult.Location, CollisionRadius, 8, FColor::Green);
				}
			}
			OutHitResult = LocalResult;
			return true;
		}
		if (bDebug)
		{
			if (CollisionHeight > 0.0f)
			{
				DrawDebugCapsule(ThisWorld, TraceStart, CollisionHeight * 0.5f, CollisionRadius, FQuat::Identity, FColor::Red);
			}
			else
			{
				DrawDebugSphere(ThisWorld, TraceStart, CollisionRadius, 8, FColor::Red);
			}
		}
	}
	return false;
}
	FORCEINLINE_DEBUGGABLE FVector RunBoxTrace(const FVector& StartPos, const FVector& EndPos)
	{
		FHitResult OutHit;
		const bool bHit = World->SweepSingle(OutHit, StartPos, EndPos, FQuat((EndPos - StartPos).Rotation()), Channel, FCollisionShape::MakeBox(Extent), Params);
		return bHit ? OutHit.ImpactPoint : EndPos;
	}
	FORCEINLINE_DEBUGGABLE FVector RunCapsuleTrace(const FVector& StartPos, const FVector& EndPos)
	{
		FHitResult OutHit;
		const bool bHit = World->SweepSingle(OutHit, StartPos, EndPos, FQuat::Identity, Channel, FCollisionShape::MakeCapsule(Extent.X, Extent.Z), Params);
		return bHit ? OutHit.ImpactPoint : EndPos;
	}