private static void FixSegmentRoundabout(ushort segmentId, ushort nextSegmentId) { if (OptionsMassEditTab.RoundAboutQuickFix_ParkingBanMainR) { ParkingRestrictionsManager.Instance.SetParkingAllowed(segmentId, false); } if (OptionsMassEditTab.RoundAboutQuickFix_RealisticSpeedLimits) { float? targetSpeed = CalculatePreferedSpeed(segmentId)?.GameUnits; float defaultSpeed = SpeedLimitManager.Instance.GetCustomNetInfoSpeedLimit(segmentId.ToSegment().Info); if (targetSpeed != null && targetSpeed < defaultSpeed) { SpeedLimitManager.Instance.SetSpeedLimit(segmentId, NetInfo.Direction.Forward, targetSpeed); SpeedLimitManager.Instance.SetSpeedLimit(segmentId, NetInfo.Direction.Backward, targetSpeed); } } ushort nodeId = netService.GetHeadNode(segmentId); if (OptionsMassEditTab.RoundAboutQuickFix_StayInLaneMainR && !HasJunctionFlag(nodeId)) { StayInLane(nodeId, StayInLaneMode.Both); } // allocation of dedicated exit lanes is supported only when the roundabout is round // in which case the next segment should be straigh ahead. bool isStraight = segEndMan.GetDirection(segmentId, nextSegmentId, nodeId) == ArrowDirection.Forward; if (OptionsMassEditTab.RoundAboutQuickFix_DedicatedExitLanes && HasJunctionFlag(nodeId) && SeparateTurningLanesUtil.CanChangeLanes( segmentId, nodeId) == SetLaneArrow_Result.Success && isStraight) { bool startNode = (bool)netService.IsStartNode(segmentId, nodeId); IList<LanePos> laneList = netService.GetSortedLanes( segmentId, ref GetSeg(segmentId), startNode, LaneArrowManager.LANE_TYPES, LaneArrowManager.VEHICLE_TYPES, true); int nSrc = laneList.Count; // check for exits. segEndMan.CalculateOutgoingLeftStraightRightSegments( ref GetSegEnd(segmentId, nodeId), ref GetNode(nodeId), out bool bLeft, out bool bForward, out bool bRight); //Set one dedicated exit lane per exit - if there are enough lanes that is. switch (nSrc) { case 0: Debug.LogAssertion("The road is the wrong way around."); break; case 1: break;// not enough lanes Use default settings. case 2: if (bRight && bLeft) { // not enough lanes, use default settings } else if (bRight) { LaneArrowManager.Instance.SetLaneArrows(laneList[0].laneId, LaneArrows.Forward); LaneArrowManager.Instance.SetLaneArrows(laneList[1].laneId, LaneArrows.Right); } else if (bLeft) { LaneArrowManager.Instance.SetLaneArrows(laneList[0].laneId, LaneArrows.Left); LaneArrowManager.Instance.SetLaneArrows(laneList[1].laneId, LaneArrows.Forward); } else { LaneArrowManager.Instance.SetLaneArrows(laneList[0].laneId, LaneArrows.Forward); LaneArrowManager.Instance.SetLaneArrows(laneList[1].laneId, LaneArrows.Forward); } break; default: for (int i = 0; i < laneList.Count; ++i) { LaneArrowManager.Instance.SetLaneArrows(laneList[i].laneId, LaneArrows.Forward); } if (bRight) { LaneArrowManager.Instance.SetLaneArrows(laneList[nSrc - 1].laneId, LaneArrows.Right); } if (bLeft) { LaneArrowManager.Instance.SetLaneArrows(laneList[0].laneId, LaneArrows.Left); } break; } // end switch } // end if }
/// <summary> /// Creates and configures default traffic the input junction /// </summary> /// <param name="nodeId">input junction</param> /// <returns>true if successful</returns> public static ErrorResult Setup(ushort nodeId) { if (tlsMan.HasTimedSimulation(nodeId)) { return(ErrorResult.TTLExists); } // issue #575: Support level crossings. NetNode.Flags flags = Singleton <NetManager> .instance.m_nodes.m_buffer[nodeId].m_flags; if ((flags & NetNode.Flags.LevelCrossing) != 0) { return(ErrorResult.NotSupported); } var segList = ArrangedSegments(nodeId); int n = segList.Count; if (n < 3) { return(ErrorResult.NotSupported); } if (!Add(nodeId)) { return(ErrorResult.Other); } if (SeparateLanes) { SeparateTurningLanesUtil.SeparateNode(nodeId, out _); } //Is it special case: { var segList2Way = TwoWayRoads(segList, out int n2); if (n2 < 2) { return(ErrorResult.NotSupported); } bool b = HasIncommingOneWaySegment(nodeId); if (n2 == 2 && !b) { return(SetupSpecial(nodeId, segList2Way)); } } for (int i = 0; i < n; ++i) { ITimedTrafficLightsStep step = TimedLight(nodeId).AddStep( minTime: 3, maxTime: 8, changeMetric: StepChangeMetric.Default, waitFlowBalance: 0.3f, makeRed: true); SetupHelper(step, nodeId, segList[i], GreenDir.AllGreen); ushort nextSegmentId = segList[(i + 1) % n]; if (NeedsShortOnly(nextSegmentId, nodeId)) { SetupHelper(step, nodeId, nextSegmentId, GreenDir.ShortOnly); } else { SetupHelper(step, nodeId, nextSegmentId, GreenDir.AllRed); } for (int j = 2; j < n; ++j) { SetupHelper(step, nodeId, segList[(i + j) % n], GreenDir.AllRed); } } Sim(nodeId).Housekeeping(); TimedLight(nodeId).Start(); return(ErrorResult.Success); }