using Gley.UrbanSystem.Internal; using System.Collections.Generic; using System.Linq; using UnityEngine; namespace Gley.TrafficSystem.Internal { /// /// Controls the priority intersection. /// internal class PriorityIntersection : GenericIntersection, IDestroyable { private readonly List _waypointsToCkeck; private readonly List _waypointColor; private readonly float _requiredTime; private List _pedestriansCrossing; private PriorityIntersectionData _priorityIntersectionData; private Vector3 _position; private float _currentTime; private int _currentRoadIndex; private int _tempRoadIndex; private bool _changeRequested; internal PriorityIntersection(PriorityIntersectionData priorityIntersectionData, TrafficWaypointsDataHandler trafficWaypointsDataHandler, IPedestrianWaypointsDataHandler pedestrianWaypointsDataHandler) { _priorityIntersectionData = priorityIntersectionData; for (int i = 0; i < _priorityIntersectionData.ExitWaypoints.Length; i++) { trafficWaypointsDataHandler.SetIntersection(_priorityIntersectionData.ExitWaypoints[i], this, false, false, false, true); } int nr = 0; for (int i = 0; i < _priorityIntersectionData.StopWaypoints.Length; i++) { for (int j = 0; j < _priorityIntersectionData.StopWaypoints[i].roadWaypoints.Length; j++) { trafficWaypointsDataHandler.SetIntersection(_priorityIntersectionData.StopWaypoints[i].roadWaypoints[j], this, true, false, true, false); _position += trafficWaypointsDataHandler.GetPosition(_priorityIntersectionData.StopWaypoints[i].roadWaypoints[j]); nr++; } } _position = _position / nr; InitializePedestrianWaypoints(pedestrianWaypointsDataHandler); _carsInIntersection = new List(); _requiredTime = 3; _waypointsToCkeck = new List(); _waypointColor = new List(); Assign(); } public void Assign() { DestroyableManager.Instance.Register(this); } /// /// Check if the intersection road is free and update intersection priority /// /// /// public override bool IsPathFree(int waypointIndex) { int road = 0; for (int i = 0; i < _priorityIntersectionData.StopWaypoints.Length; i++) { //if the waypoint is in the enter waypoints list needs to be verified if is free if (_priorityIntersectionData.StopWaypoints[i].roadWaypoints.Contains(waypointIndex)) { if (!_waypointsToCkeck.Contains(waypointIndex)) { _waypointsToCkeck.Add(waypointIndex); _waypointColor.Add(Color.green); } road = i; if (IsPedestrianCrossing(road)) { _waypointColor[_waypointsToCkeck.IndexOf(waypointIndex)] = Color.red; return false; } bool stopChange = false; //if vehicle is on current road, wait to pass before changing the road priority if (i == _currentRoadIndex) { _changeRequested = false; stopChange = true; } //construct priority if vehicle is not on the priority road if (stopChange == false) { if (_tempRoadIndex == _currentRoadIndex) { _tempRoadIndex = road; _changeRequested = true; _currentTime = Time.timeSinceLevelLoad; } } break; } } int index = _waypointsToCkeck.IndexOf(waypointIndex); //if a new vehicle is requesting access to intersection but there are vehicles on intersection -> wait if (_changeRequested == true) { if (_carsInIntersection.Count >= 1) { _waypointColor[index] = Color.red; return false; } _changeRequested = false; _currentRoadIndex = _tempRoadIndex; } //if the number of vehicles in intersection is <3 -> permit access if (_carsInIntersection.Count <= 3) { if (_priorityIntersectionData.StopWaypoints[_currentRoadIndex].roadWaypoints.Contains(waypointIndex)) { _waypointColor[index] = Color.green; return true; } } //after some time change the priority road if (Time.timeSinceLevelLoad - _currentTime > _requiredTime) { _tempRoadIndex = road; _changeRequested = true; _currentTime = Time.timeSinceLevelLoad; } _waypointColor[index] = Color.red; return false; } public override void PedestrianPassed(int pedestrianIndex) { PedestrianCrossing ped = _pedestriansCrossing.FirstOrDefault(cond => cond.PedestrianIndex == pedestrianIndex); if (ped != null) { if (ped.Crossing == false) { ped.Crossing = true; } else { _pedestriansCrossing.Remove(ped); } } } internal override string GetName() { return _priorityIntersectionData.Name; } internal override void ResetIntersection() { base.ResetIntersection(); _pedestriansCrossing = new List(); } internal Vector3 GetPosition() { return _position; } internal List GetWaypointsToCkeck() { return _waypointsToCkeck; } internal List GetWaypointColors() { return _waypointColor; } internal override List GetStopWaypoints() { var result = new List(); for (int i = 0; i < _priorityIntersectionData.StopWaypoints.Length; i++) { result.AddRange(_priorityIntersectionData.StopWaypoints[i].roadWaypoints); } return result; } internal override void UpdateIntersection(float realtimeSinceStartup) { } internal int GetCarsInIntersection() { return _carsInIntersection.Count; } internal List GetPedestriansCrossing() { return _pedestriansCrossing; } internal override int[] GetPedStopWaypoint() { return new int[0]; } private void InitializePedestrianWaypoints(IPedestrianWaypointsDataHandler pedestrianWaypointsDataHandler) { _pedestriansCrossing = new List(); #if GLEY_PEDESTRIAN_SYSTEM for(int i=0;i<_priorityIntersectionData.StopWaypoints.Length;i++) { pedestrianWaypointsDataHandler.SetIntersection(_priorityIntersectionData.StopWaypoints[i].pedestrianWaypoints, this); } PedestrianSystem.Events.OnStreetCrossing += PedestrianWantsToCross; #endif } private void PedestrianWantsToCross(int pedestrianIndex, IIntersection intersection, int waypointIndex) { if (intersection == this) { int road = GetRoadToCross(waypointIndex); _pedestriansCrossing.Add(new PedestrianCrossing(pedestrianIndex, road)); } } private int GetRoadToCross(int waypoint) { for (int i = 0; i < _priorityIntersectionData.StopWaypoints.Length; i++) { for (int j = 0; j < _priorityIntersectionData.StopWaypoints[i].pedestrianWaypoints.Length; j++) { if (_priorityIntersectionData.StopWaypoints[i].pedestrianWaypoints[j] == waypoint) { return i; } } } Debug.LogError("Not Good - verify pedestrians assignments in priority intersection"); return -1; } private bool IsPedestrianCrossing(int road) { if (_pedestriansCrossing.Count == 0) { return false; } return _pedestriansCrossing.FirstOrDefault(cond => cond.Road == road) != null; } public void OnDestroy() { #if GLEY_PEDESTRIAN_SYSTEM PedestrianSystem.Events.OnStreetCrossing -= PedestrianWantsToCross; #endif } } }