private RaycastHit[] FindNearbyRoads(RoadBase currentRoad)
 {
     RaycastHit[] objectHits = new RaycastHit[RoadBase.directions.Length];
     for (int i = 0; i < RoadBase.directions.Length; i++)
     {
         string dir = RoadBase.directions[i];
         // If can connect towards dir
         if (currentRoad.GetComponent <IRoadInterface>().IsDirectionConnectable(dir))
         {
             RaycastHit[] hits = Physics.RaycastAll(currentRoad.transform.position, RoadBase.DirToVec(dir), rayLength, roadLayerMask);
             if (hits.Length > 0)
             {
                 if (hits[0].collider.gameObject != currentRoad.gameObject)
                 {
                     objectHits[i] = hits[0];
                 }
                 else if (hits.Length > 1)
                 {
                     if (hits[1].collider.gameObject != currentRoad.gameObject)
                     {
                         objectHits[i] = hits[1];
                     }
                 }
             }
         }
     }
     return(objectHits);
 }
    private RoadBase GetPrevRoad()
    {
        RoadBase prevRoad = null;

        if (GetCurrentComponent <RoadBase>() != null)
        {
            prevRoad = GetCurrentComponent <RoadBase>();
        }
        else if (roadRoot.childCount > 1)
        {
            prevRoad = roadRoot.GetChild(roadRoot.childCount - 2).gameObject.GetComponent <RoadBase>();
        }
        return(prevRoad);
    }
    private void DrawRoadSelectionButtons()
    {
        if (GUILayout.Button(Utilities.RotateTextureClockwise(roadButtonTexture, RoadBase.DirToInd(currentOrientation))))
        {
            currentRoadPrefab = roadPrefab;
            if (selectAndBuild)
            {
                NewRoadButtonCallback(currentRoadPrefab, null, null, null);
            }
        }

        if (GUILayout.Button(Utilities.RotateTextureClockwise(roadButtonRTexture, RoadBase.DirToInd(currentOrientation))))
        {
            currentRoadPrefab = roadPrefabCorner_R;
            if (selectAndBuild)
            {
                NewRoadButtonCallback(currentRoadPrefab, null, null, null);
            }
        }

        if (GUILayout.Button(Utilities.RotateTextureClockwise(roadButtonLTexture, RoadBase.DirToInd(currentOrientation))))
        {
            currentRoadPrefab = roadPrefabCorner_L;
            if (selectAndBuild)
            {
                NewRoadButtonCallback(currentRoadPrefab, null, null, null);
            }
        }

        if (GUILayout.Button(Utilities.RotateTextureClockwise(roadButtonTTexture, RoadBase.DirToInd(currentOrientation))))
        {
            currentRoadPrefab = roadPrefab_T;
            if (selectAndBuild)
            {
                NewRoadButtonCallback(currentRoadPrefab, null, null, null);
            }
        }

        if (GUILayout.Button(Utilities.RotateTextureClockwise(roadButtonXTexture, RoadBase.DirToInd(currentOrientation))))
        {
            currentRoadPrefab = roadPrefab_X;
            if (selectAndBuild)
            {
                NewRoadButtonCallback(currentRoadPrefab, null, null, null);
            }
        }
    }
    // Using Vector3[] array since Vector3 is not nullable
    private void NewRoadButtonCallback(GameObject currentRoadPrefab, string newOrientation, Vector3[] newPosVec, string newName)
    {
        RoadBase currentRoad = NewRoad(currentRoadPrefab, newOrientation, newPosVec, newName);

        RaycastHit[] nearbyRoadHits = FindNearbyRoads(currentRoad);
        for (int i = 0; i < nearbyRoadHits.Length; i++)
        {
            if (nearbyRoadHits[i].collider?.GetComponent <RoadBase>() != null)
            {
                Waypoint[]   thisObjectWaypoint   = FindWaypointsInRoadClosestToPoint(currentRoad, nearbyRoadHits[i].point);
                Waypoint[]   otherObjectWaypoints = FindWaypointsInRoadClosestToPoint(nearbyRoadHits[i].collider.GetComponent <RoadBase>(), nearbyRoadHits[i].point);
                Waypoint[][] orderedForConnection = OrderWaypointsForConnection(thisObjectWaypoint, otherObjectWaypoints);
                RoadBase.ConnectRoads(orderedForConnection);
            }
        }
        currentOrientation = currentRoad.createDirection;
    }
    private RoadBase NewRoad(GameObject roadPrefab, string newOrientation, Vector3[] newPositionTransform, string newName)
    {
        GameObject roadObject = Instantiate(roadPrefab, roadRoot);

        if (newName == null)
        {
            roadObject.name = "Road " + roadRoot.childCount;
        }
        else
        {
            roadObject.name = newName;
        }
        RoadBase prevRoad = GetPrevRoad();

        if (prevRoad != null)
        {
            roadObject.GetComponent <IRoadInterface>().CreateRoad(prevRoad, gridSize, newOrientation, newPositionTransform);
        }
        Selection.activeGameObject = roadObject;
        return(roadObject.GetComponent <RoadBase>());
    }
 private Waypoint[] FindWaypointsInRoadClosestToPoint(RoadBase road, Vector3 pointHit)
 {
     float[]      closestDistances       = { Mathf.Infinity, Mathf.Infinity };
     GameObject[] closestWaypointObjects = { null, null };
     foreach (GameObject laneObject in road.lanes)
     {
         float distanceToPoint = (laneObject.transform.position - pointHit).magnitude;
         if (distanceToPoint < closestDistances[0] && laneObject != closestWaypointObjects[1])
         {
             closestWaypointObjects[1] = closestWaypointObjects[0];
             closestWaypointObjects[0] = laneObject;
             closestDistances[1]       = closestDistances[0];
             closestDistances[0]       = distanceToPoint;
         }
         else if (distanceToPoint < closestDistances[1] && laneObject != closestWaypointObjects[0])
         {
             closestWaypointObjects[1] = laneObject;
             closestDistances[1]       = distanceToPoint;
         }
     }
     Waypoint[] closestWaypoints = { closestWaypointObjects[0].GetComponent <Waypoint>(),
                                     closestWaypointObjects[1].GetComponent <Waypoint>() };
     return(closestWaypoints);
 }
    private void DrawRotationButtons()
    {
        EditorGUI.BeginDisabledGroup(!GetCurrentComponent <RoadT>());
        if (GUILayout.Button(counterClockwiseText))
        {
            RoadBase  currentlySelectedRoad = GetCurrentComponent <RoadBase>();
            string    newRotation           = RoadBase.RotateClockwise(currentlySelectedRoad.orientation, 3);
            Vector3[] currentPos            = { currentlySelectedRoad.transform.position };
            string    currentName           = currentlySelectedRoad.name;
            DestroyImmediate(currentlySelectedRoad.gameObject);
            NewRoadButtonCallback(roadPrefab_T, newRotation, currentPos, currentName);
        }

        if (GUILayout.Button(clockwiseText))
        {
            RoadBase  currentlySelectedRoad = GetCurrentComponent <RoadBase>();
            string    newRotation           = RoadBase.RotateClockwise(currentlySelectedRoad.orientation, 1);
            Vector3[] currentPos            = { currentlySelectedRoad.transform.position };
            string    currentName           = currentlySelectedRoad.name;
            DestroyImmediate(currentlySelectedRoad.gameObject);
            NewRoadButtonCallback(roadPrefab_T, newRotation, currentPos, currentName);
        }
        EditorGUI.EndDisabledGroup();
    }
    private void DrawRoadContinueButtons()
    {
        Texture2D upButton    = arrowUpTexture;
        Texture2D rightButton = arrowRightTexture;
        Texture2D downButton  = arrowDownTexture;
        Texture2D leftButton  = arrowLeftTexture;

        if (SelectedHasComponent <IRoadInterface>() || ParentHasComponent <IRoadInterface>())
        {
            IRoadInterface currentRoadInterface = GetCurrentComponent <IRoadInterface>();
            RoadBase       currentRoad          = GetCurrentComponent <RoadBase>();

            string dir;
            bool   isDisabled = false;

            GUILayout.BeginHorizontal();
            dir        = "forward";
            isDisabled = IsDirectionButtonDisabled(currentRoadInterface, dir);
            EditorGUI.BeginDisabledGroup(isDisabled);
            if (currentRoad != null)
            {
                if (currentRoad.createDirection == dir)
                {
                    upButton = arrowUpTexture_G;
                }
            }
            else
            {
                upButton = arrowUpTexture;
            }
            if (GUILayout.Button(upButton))
            {
                currentRoadInterface.SetCreateDirection(dir);
                currentOrientation = dir;
            }
            EditorGUI.EndDisabledGroup();
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal();
            dir        = "left";
            isDisabled = IsDirectionButtonDisabled(currentRoadInterface, dir);
            EditorGUI.BeginDisabledGroup(isDisabled);
            if (currentRoad != null)
            {
                if (currentRoad.createDirection == dir)
                {
                    leftButton = arrowLeftTexture_G;
                }
            }
            else
            {
                leftButton = arrowLeftTexture;
            }
            if (GUILayout.Button(leftButton))
            {
                currentRoadInterface.SetCreateDirection(dir);
                currentOrientation = dir;
            }
            EditorGUI.EndDisabledGroup();

            dir        = "right";
            isDisabled = IsDirectionButtonDisabled(currentRoadInterface, dir);
            EditorGUI.BeginDisabledGroup(isDisabled);
            if (currentRoad != null)
            {
                if (currentRoad.createDirection == dir)
                {
                    rightButton = arrowRightTexture_G;
                }
            }
            else
            {
                rightButton = arrowRightTexture;
            }
            if (GUILayout.Button(rightButton))
            {
                currentRoadInterface.SetCreateDirection(dir);
                currentOrientation = dir;
            }
            EditorGUI.EndDisabledGroup();
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal();
            dir        = "backward";
            isDisabled = IsDirectionButtonDisabled(currentRoadInterface, dir);
            EditorGUI.BeginDisabledGroup(isDisabled);
            if (currentRoad != null)
            {
                if (currentRoad.createDirection == dir)
                {
                    downButton = arrowDownTexture_G;
                }
            }
            else
            {
                downButton = arrowDownTexture;
            }
            if (GUILayout.Button(downButton))
            {
                currentRoadInterface.SetCreateDirection(dir);
                currentOrientation = dir;
            }
            EditorGUI.EndDisabledGroup();
            GUILayout.EndHorizontal();
        }
        else
        {
            if (GUILayout.Button("Reset Direction"))
            {
                currentOrientation = "forward";
            }
        }
    }