using UnityEngine;
namespace Gley.TrafficSystem.Internal
{
///
/// Used to check if a vehicle can be instantiated in a given position
///
internal class PositionValidator
{
private readonly float _minDistanceToAdd;
private readonly bool _debugDensity;
private Collider[] _results;
private Transform[] _activeCameras;
private LayerMask _trafficLayer;
private LayerMask _playerLayer;
private LayerMask _buildingsLayers;
///
/// Setup dependencies
///
///
///
///
///
///
///
internal PositionValidator(Transform[] activeCameras, LayerMask trafficLayer, LayerMask playerLayer, LayerMask buildingsLayers, float minDistanceToAdd, bool debugDensity)
{
UpdateCamera(activeCameras);
_trafficLayer = trafficLayer;
_playerLayer = playerLayer;
_minDistanceToAdd = minDistanceToAdd * minDistanceToAdd;
_buildingsLayers = buildingsLayers;
_debugDensity = debugDensity;
_results = new Collider[1];
}
///
/// Checks if a vehicle can be instantiated in a given position
///
/// position to check
///
///
/// validate position eve if it is in view
///
internal bool IsValid(Vector3 position, float vehicleLength, float vehicleHeight, float vehicleWidth, bool ignoreLineOfSight, float frontWheelOffset, Quaternion rotation)
{
position -= rotation * new Vector3(0, 0, frontWheelOffset);
for (int i = 0; i < _activeCameras.Length; i++)
{
if (!ignoreLineOfSight)
{
//if position if far enough from the player
if (Vector3.SqrMagnitude(_activeCameras[i].position - position) < _minDistanceToAdd)
{
if (!Physics.Linecast(position, _activeCameras[i].position, _buildingsLayers))
{
#if UNITY_EDITOR
if (_debugDensity)
{
Debug.Log("Density: Direct view of the camera");
Debug.DrawLine(_activeCameras[i].position, position, Color.red, 0.1f);
}
#endif
return false;
}
else
{
#if UNITY_EDITOR
if (_debugDensity)
{
Debug.DrawLine(_activeCameras[i].position, position, Color.green, 0.1f);
}
#endif
}
}
}
}
//check if the final position is free
return IsPositionFree(position, vehicleLength, vehicleHeight, vehicleWidth, rotation);
}
///
/// Check if a given position if free
///
///
///
///
///
///
///
internal bool IsPositionFree(Vector3 position, float length, float height, float width, Quaternion rotation)
{
if (Physics.OverlapBoxNonAlloc(position, new Vector3(width / 2, height / 2, length / 2), _results, rotation, _trafficLayer | _playerLayer) > 0)
{
#if UNITY_EDITOR
if (_debugDensity)
{
Debug.Log("Density: Other obstacle is blocking the waypoint");
}
#endif
return false;
}
return true;
}
internal bool CheckTrailerPosition(Vector3 position, Quaternion vehicleRotation, Quaternion trailerRotation, VehicleComponent vehicle)
{
Vector3 translatedPosition = position - vehicleRotation * Vector3.forward * (vehicle.frontTrigger.transform.localPosition.z + vehicle.carHolder.transform.localPosition.z);
translatedPosition = translatedPosition - trailerRotation * Vector3.forward * vehicle.trailer.length / 2;
return IsPositionFree(translatedPosition, vehicle.trailer.length, vehicle.trailer.height, vehicle.trailer.width, trailerRotation);
}
///
/// Update player camera transform
///
///
internal void UpdateCamera(Transform[] activeCameras)
{
_activeCameras = activeCameras;
}
}
}