private void _guiSpeedLimitsWindow(int num) { GUILayout.BeginHorizontal(); Color oldColor = GUI.color; for (int i = 0; i < SpeedLimitManager.Instance().AvailableSpeedLimits.Count; ++i) { if (curSpeedLimitIndex != i) { GUI.color = Color.gray; } float signSize = TrafficManagerTool.AdaptWidth(guiSpeedSignSize); if (GUILayout.Button(TrafficLightToolTextureResources.SpeedLimitTextures[SpeedLimitManager.Instance().AvailableSpeedLimits[i]], GUILayout.Width(signSize), GUILayout.Height(signSize))) { curSpeedLimitIndex = i; } GUI.color = oldColor; if (i == 6) { GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); } } GUILayout.EndHorizontal(); GUI.DragWindow(); }
protected virtual void CalculateSegPos(ushort vehicleID, ref Vehicle vehicleData, PathUnit.Position position, uint laneID, byte offset, out Vector3 pos, out Vector3 dir, out float maxSpeed) { NetManager instance = Singleton <NetManager> .instance; instance.m_lanes.m_buffer[(int)((UIntPtr)laneID)].CalculatePositionAndDirection((float)offset * 0.003921569f, out pos, out dir); NetInfo info = instance.m_segments.m_buffer[(int)position.m_segment].Info; if (info.m_lanes != null && info.m_lanes.Length > (int)position.m_lane) { var laneSpeedLimit = SpeedLimitManager.GetLockFreeGameSpeedLimit(position.m_segment, position.m_lane, laneID, info.m_lanes[position.m_lane]); maxSpeed = this.CalculateTargetSpeed(vehicleID, ref vehicleData, laneSpeedLimit, instance.m_lanes.m_buffer[(int)((UIntPtr)laneID)].m_curve); } else { maxSpeed = this.CalculateTargetSpeed(vehicleID, ref vehicleData, 1f, 0f); } }
public void CustomCalculateSegmentPositionPathFinder(ushort vehicleID, ref Vehicle vehicleData, PathUnit.Position position, uint laneID, byte offset, out Vector3 pos, out Vector3 dir, out float maxSpeed) { NetManager instance = Singleton <NetManager> .instance; instance.m_lanes.m_buffer[(int)((UIntPtr)laneID)].CalculatePositionAndDirection((float)offset * 0.003921569f, out pos, out dir); NetInfo info = instance.m_segments.m_buffer[(int)position.m_segment].Info; if (info.m_lanes != null && info.m_lanes.Length > (int)position.m_lane) { float speedLimit = Options.customSpeedLimitsEnabled ? SpeedLimitManager.Instance().GetLockFreeGameSpeedLimit(position.m_segment, position.m_lane, laneID, info.m_lanes[position.m_lane]) : info.m_lanes[position.m_lane].m_speedLimit; maxSpeed = this.CalculateTargetSpeed(vehicleID, ref vehicleData, speedLimit, instance.m_lanes.m_buffer[laneID].m_curve); } else { maxSpeed = this.CalculateTargetSpeed(vehicleID, ref vehicleData, 1f, 0f); } }
public void CustomCalculateSegmentPositionPathFinder(ushort vehicleId, ref Vehicle vehicleData, PathUnit.Position position, uint laneId, byte offset, out Vector3 pos, out Vector3 dir, out float maxSpeed) { var netManager = Singleton <NetManager> .instance; netManager.m_lanes.m_buffer[(int)((UIntPtr)laneId)].CalculatePositionAndDirection(offset * 0.003921569f, out pos, out dir); var info = netManager.m_segments.m_buffer[position.m_segment].Info; if (info.m_lanes != null && info.m_lanes.Length > position.m_lane) { var laneSpeedLimit = SpeedLimitManager.GetLockFreeGameSpeedLimit(position.m_segment, position.m_lane, laneId, info.m_lanes[position.m_lane]); //info.m_lanes[position.m_lane].m_speedLimit; maxSpeed = CalculateTargetSpeed(vehicleId, ref vehicleData, laneSpeedLimit, netManager.m_lanes.m_buffer[(int)((UIntPtr)laneId)].m_curve); } else { maxSpeed = CalculateTargetSpeed(vehicleId, ref vehicleData, 1f, 0f); } maxSpeed = CalcMaxSpeed(vehicleId, ref vehicleData, position, pos, maxSpeed, IsRecklessDriver(vehicleId, ref vehicleData)); }
public override void OnSaveData() { bool success = true; // try { // Log.Info("Recalculating segment geometries"); // SegmentGeometry.OnBeforeSaveData(); // } // catch (Exception e) { // Log.Error( // $"OnSaveData: Exception occurred while calling SegmentGeometry.OnBeforeSaveData: {e.ToString()}"); // error = true; // } foreach (ICustomManager manager in LoadingExtension.RegisteredManagers) { try { Log.Info($"OnBeforeSaveData: {manager.GetType().Name}"); manager.OnBeforeSaveData(); } catch (Exception e) { Log.Error($"OnSaveData: Error while notifying {manager.GetType().Name}.OnBeforeSaveData: {e}"); success = false; } } try { Log.Info("Saving Mod Data."); var configuration = new Configuration(); //------------------ // Citizens //------------------ configuration.ExtCitizens = ExtCitizenManager.Instance.SaveData(ref success); configuration.ExtCitizenInstances = ExtCitizenInstanceManager.Instance.SaveData(ref success); //------------------ // Traffic Priorities //------------------ configuration.PrioritySegments = TrafficPriorityManager.AsPrioritySegmentsDM() .SaveData(ref success); configuration.CustomPrioritySegments = TrafficPriorityManager.AsCustomPrioritySegmentsDM() .SaveData(ref success); //------------------ // Junction Restrictions //------------------ configuration.SegmentNodeConfs = JunctionRestrictionsManager.Instance.SaveData(ref success); //------------------ // Traffic Lights //------------------ configuration.TimedLights = TrafficLightSimulationManager.Instance.SaveData(ref success); // configuration.NodeTrafficLights = ((ICustomDataManager<string>)TrafficLightManager.Instance) // .SaveData(ref success); // configuration.ToggledTrafficLights = // ((ICustomDataManager<List<Configuration.NodeTrafficLight>>)TrafficLightManager.Instance) // .SaveData(ref success); //------------------ // Lane Arrows and Connections //------------------ configuration.LaneFlags = LaneArrowManager.AsLaneFlagsDM().SaveData(ref success); configuration.LaneArrows = LaneArrowManager.AsLaneArrowsDM().SaveData(ref success); configuration.LaneConnections = LaneConnectionManager.Instance.SaveData(ref success); //------------------ // Speed Limits //------------------ configuration.LaneSpeedLimits = SpeedLimitManager.AsLaneSpeedLimitsDM().SaveData(ref success); configuration.CustomDefaultSpeedLimits = SpeedLimitManager.AsCustomDefaultSpeedLimitsDM() .SaveData(ref success); //------------------ // Vehicle and Parking Restrictions //------------------ configuration.LaneAllowedVehicleTypes = VehicleRestrictionsManager.Instance.SaveData(ref success); configuration.ParkingRestrictions = ParkingRestrictionsManager.Instance.SaveData(ref success); try { // save options _serializableData.SaveData("TMPE_Options", OptionsManager.Instance.SaveData(ref success)); } catch (Exception ex) { Log.Error("Unexpected error while saving options: " + ex.Message); success = false; } var binaryFormatter = new BinaryFormatter(); var memoryStream = new MemoryStream(); try { binaryFormatter.Serialize(memoryStream, configuration); memoryStream.Position = 0; Log.Info($"Save data byte length {memoryStream.Length}"); _serializableData.SaveData(DATA_ID, memoryStream.ToArray()); } catch (Exception ex) { Log.Error("Unexpected error while saving data: " + ex); success = false; } finally { memoryStream.Close(); } var reverseManagers = new List <ICustomManager>(LoadingExtension.RegisteredManagers); reverseManagers.Reverse(); foreach (ICustomManager manager in reverseManagers) { try { Log.Info($"OnAfterSaveData: {manager.GetType().Name}"); manager.OnAfterSaveData(); } catch (Exception e) { Log.Error( $"OnSaveData: Error while notifying {manager.GetType().Name}.OnAfterSaveData: {e}"); success = false; } } } catch (Exception e) { success = false; Log.Error($"Error occurred while saving data: {e}"); // UIView.library.ShowModal<ExceptionPanel>("ExceptionPanel") // .SetMessage("An error occurred while saving", "Traffic Manager: President Edition // detected an error while saving. To help preventing future errors, please navigate // to http://steamcommunity.com/sharedfiles/filedetails/?id=583429740 and follow // the steps under 'In case problems arise'.", true); } }
public void CustomCalculateSegmentPosition(ushort vehicleId, ref Vehicle vehicleData, PathUnit.Position nextPosition, PathUnit.Position position, uint laneID, byte offset, PathUnit.Position prevPos, uint prevLaneID, byte prevOffset, int index, out Vector3 pos, out Vector3 dir, out float maxSpeed) { var netManager = Singleton <NetManager> .instance; //var vehicleManager = Singleton<VehicleManager>.instance; netManager.m_lanes.m_buffer[(int)((UIntPtr)laneID)].CalculatePositionAndDirection(offset * 0.003921569f, out pos, out dir); bool isRecklessDriver = IsRecklessDriver(vehicleId, ref vehicleData); var lastFrameData = vehicleData.GetLastFrameData(); var lastFrameVehiclePos = lastFrameData.m_position; var camPos = Camera.main.transform.position; bool simulatePrioritySigns = (lastFrameVehiclePos - camPos).sqrMagnitude < FarLod && !isRecklessDriver; if (Options.simAccuracy <= 0) { if (vehicleData.Info.m_vehicleType == VehicleInfo.VehicleType.Car) { VehiclePosition vehiclePos = TrafficPriority.GetVehiclePosition(vehicleId); if (vehiclePos.Valid && simulatePrioritySigns) // TODO check if this should be !vehiclePos.Valid { try { CustomVehicleAI.HandleVehicle(vehicleId, ref Singleton <VehicleManager> .instance.m_vehicles.m_buffer[vehicleId], false, false); } catch (Exception e) { Log.Error("CarAI TmCalculateSegmentPosition Error: " + e.ToString()); } } } else { //Log._Debug($"TmCalculateSegmentPosition does not handle vehicles of type {vehicleData.Info.m_vehicleType}"); } } // I think this is supposed to be the lane position? // [VN, 12/23/2015] It's the 3D car position on the Bezier curve of the lane. // This crazy 0.003921569f equals to 1f/255 and prevOffset is the byte value (0..255) of the car position. var vehiclePosOnBezier = netManager.m_lanes.m_buffer[(int)((UIntPtr)prevLaneID)].CalculatePosition(prevOffset * 0.003921569f); //ushort currentSegmentId = netManager.m_lanes.m_buffer[(int)((UIntPtr)prevLaneID)].m_segment; ushort destinationNodeId; ushort sourceNodeId; if (offset < position.m_offset) { destinationNodeId = netManager.m_segments.m_buffer[position.m_segment].m_startNode; sourceNodeId = netManager.m_segments.m_buffer[position.m_segment].m_endNode; } else { destinationNodeId = netManager.m_segments.m_buffer[position.m_segment].m_endNode; sourceNodeId = netManager.m_segments.m_buffer[position.m_segment].m_startNode; } var previousDestinationNode = prevOffset == 0 ? netManager.m_segments.m_buffer[prevPos.m_segment].m_startNode : netManager.m_segments.m_buffer[prevPos.m_segment].m_endNode; // this seems to be like the required braking force in order to stop the vehicle within its half length. var crazyValue = 0.5f * lastFrameData.m_velocity.sqrMagnitude / m_info.m_braking + m_info.m_generatedInfo.m_size.z * 0.5f; // Essentially, this is true if the car has enough time and space to brake (e.g. for a red traffic light) if (destinationNodeId == previousDestinationNode) { if (Vector3.Distance(lastFrameVehiclePos, vehiclePosOnBezier) >= crazyValue - 1f) { var currentFrameIndex = Singleton <SimulationManager> .instance.m_currentFrameIndex; var num5 = (uint)((previousDestinationNode << 8) / 32768); var num6 = currentFrameIndex - num5 & 255u; var nodeFlags = netManager.m_nodes.m_buffer[destinationNodeId].m_flags; var prevLaneFlags = (NetLane.Flags)netManager.m_lanes.m_buffer[(int)((UIntPtr)prevLaneID)].m_flags; var hasTrafficLight = (nodeFlags & NetNode.Flags.TrafficLights) != NetNode.Flags.None; var hasCrossing = (nodeFlags & NetNode.Flags.LevelCrossing) != NetNode.Flags.None; var isJoinedJunction = (prevLaneFlags & NetLane.Flags.JoinedJunction) != NetLane.Flags.None; bool checkSpace = !Flags.getEnterWhenBlockedAllowed(prevPos.m_segment, netManager.m_segments.m_buffer[prevPos.m_segment].m_startNode == destinationNodeId) && !isRecklessDriver; //TrafficLightSimulation nodeSim = TrafficLightSimulation.GetNodeSimulation(destinationNodeId); /*if (timedNode != null && timedNode.vehiclesMayEnterBlockedJunctions) { * checkSpace = false; * }*/ if (checkSpace) { // check if there is enough space if ((nodeFlags & (NetNode.Flags.Junction | NetNode.Flags.OneWayOut | NetNode.Flags.OneWayIn)) == NetNode.Flags.Junction && netManager.m_nodes.m_buffer[destinationNodeId].CountSegments() != 2) { var len = vehicleData.CalculateTotalLength(vehicleId) + 2f; if (!netManager.m_lanes.m_buffer[(int)((UIntPtr)laneID)].CheckSpace(len)) { var sufficientSpace = false; if (nextPosition.m_segment != 0 && netManager.m_lanes.m_buffer[(int)((UIntPtr)laneID)].m_length < 30f) { var flags3 = netManager.m_nodes.m_buffer[sourceNodeId].m_flags; if ((flags3 & (NetNode.Flags.Junction | NetNode.Flags.OneWayOut | NetNode.Flags.OneWayIn)) != NetNode.Flags.Junction || netManager.m_nodes.m_buffer[sourceNodeId].CountSegments() == 2) { var laneId2 = PathManager.GetLaneID(nextPosition); if (laneId2 != 0u) { sufficientSpace = netManager.m_lanes.m_buffer[(int)((UIntPtr)laneId2)].CheckSpace(len); } } } if (!sufficientSpace) { maxSpeed = 0f; return; } } } } try { VehiclePosition globalTargetPos = TrafficPriority.GetVehiclePosition(vehicleId); if ((vehicleData.m_flags & Vehicle.Flags.Emergency2) == 0) { if (vehicleData.Info.m_vehicleType == VehicleInfo.VehicleType.Car) { if (hasTrafficLight && (!isJoinedJunction || hasCrossing)) { var destinationInfo = netManager.m_nodes.m_buffer[destinationNodeId].Info; if (globalTargetPos.CarState == VehicleJunctionTransitState.None) { globalTargetPos.CarState = VehicleJunctionTransitState.Enter; } RoadBaseAI.TrafficLightState vehicleLightState; RoadBaseAI.TrafficLightState pedestrianLightState; bool vehicles; bool pedestrians; CustomRoadAI.GetTrafficLightState(vehicleId, ref vehicleData, destinationNodeId, prevPos.m_segment, position.m_segment, ref netManager.m_segments.m_buffer[prevPos.m_segment], currentFrameIndex - num5, out vehicleLightState, out pedestrianLightState, out vehicles, out pedestrians); if (isRecklessDriver && (destinationInfo.GetConnectionClass().m_service & ItemClass.Service.PublicTransport) == ItemClass.Service.None) // no reckless driving at railroad crossings { vehicleLightState = RoadBaseAI.TrafficLightState.Green; } if (!vehicles && num6 >= 196u) { vehicles = true; RoadBaseAI.SetTrafficLightState(destinationNodeId, ref netManager.m_segments.m_buffer[prevPos.m_segment], currentFrameIndex - num5, vehicleLightState, pedestrianLightState, vehicles, pedestrians); } var stopCar = false; switch (vehicleLightState) { case RoadBaseAI.TrafficLightState.RedToGreen: if (num6 < 60u) { stopCar = true; } else { globalTargetPos.CarState = VehicleJunctionTransitState.Leave; } break; case RoadBaseAI.TrafficLightState.Red: stopCar = true; break; case RoadBaseAI.TrafficLightState.GreenToRed: if (num6 >= 30u) { stopCar = true; } else { globalTargetPos.CarState = VehicleJunctionTransitState.Leave; } break; } if ((vehicleLightState == RoadBaseAI.TrafficLightState.Green || vehicleLightState == RoadBaseAI.TrafficLightState.RedToGreen) && !Flags.getEnterWhenBlockedAllowed(prevPos.m_segment, netManager.m_segments.m_buffer[prevPos.m_segment].m_startNode == destinationNodeId)) { var hasIncomingCars = TrafficPriority.HasIncomingVehiclesWithHigherPriority(vehicleId, destinationNodeId); if (hasIncomingCars) { // green light but other cars are incoming and they have priority: stop stopCar = true; } } if (stopCar) { globalTargetPos.CarState = VehicleJunctionTransitState.Stop; maxSpeed = 0f; return; } } else if (simulatePrioritySigns) { #if DEBUG //bool debug = destinationNodeId == 10864; //bool debug = destinationNodeId == 13531; bool debug = false; #endif //bool debug = false; #if DEBUG if (debug) { Log._Debug($"Vehicle {vehicleId} is arriving @ seg. {prevPos.m_segment} ({position.m_segment}, {nextPosition.m_segment}), node {destinationNodeId} which is not a traffic light."); } #endif var prioritySegment = TrafficPriority.GetPrioritySegment(destinationNodeId, prevPos.m_segment); if (prioritySegment != null) { #if DEBUG if (debug) { Log._Debug($"Vehicle {vehicleId} is arriving @ seg. {prevPos.m_segment} ({position.m_segment}, {nextPosition.m_segment}), node {destinationNodeId} which is not a traffic light and is a priority segment."); } #endif if (prioritySegment.HasVehicle(vehicleId)) { #if DEBUG if (debug) { Log._Debug($"Vehicle {vehicleId}: segment target position found"); } #endif if (globalTargetPos.Valid) { #if DEBUG if (debug) { Log._Debug($"Vehicle {vehicleId}: global target position found. carState = {globalTargetPos.CarState.ToString()}"); } #endif var currentFrameIndex2 = Singleton <SimulationManager> .instance.m_currentFrameIndex; var frame = currentFrameIndex2 >> 4; if (globalTargetPos.CarState == VehicleJunctionTransitState.None) { globalTargetPos.CarState = VehicleJunctionTransitState.Enter; } if (globalTargetPos.CarState != VehicleJunctionTransitState.Leave) { bool hasIncomingCars; switch (prioritySegment.Type) { case SegmentEnd.PriorityType.Stop: #if DEBUG if (debug) { Log._Debug($"Vehicle {vehicleId}: STOP sign. waittime={globalTargetPos.WaitTime}, vel={lastFrameData.m_velocity.magnitude}"); } #endif if (globalTargetPos.WaitTime < MaxPriorityWaitTime) { globalTargetPos.CarState = VehicleJunctionTransitState.Stop; if (lastFrameData.m_velocity.magnitude < 0.5f || globalTargetPos.Stopped) { globalTargetPos.Stopped = true; globalTargetPos.WaitTime++; float minStopWaitTime = Random.Range(0f, 3f); if (globalTargetPos.WaitTime >= minStopWaitTime) { hasIncomingCars = TrafficPriority.HasIncomingVehiclesWithHigherPriority(vehicleId, destinationNodeId); #if DEBUG if (debug) { Log._Debug($"hasIncomingCars: {hasIncomingCars}"); } #endif if (hasIncomingCars) { maxSpeed = 0f; return; } globalTargetPos.CarState = VehicleJunctionTransitState.Leave; } else { maxSpeed = 0; return; } } else { maxSpeed = 0f; return; } } else { globalTargetPos.CarState = VehicleJunctionTransitState.Leave; } break; case SegmentEnd.PriorityType.Yield: #if DEBUG if (debug) { Log._Debug($"Vehicle {vehicleId}: YIELD sign. waittime={globalTargetPos.WaitTime}"); } #endif if (globalTargetPos.WaitTime < MaxPriorityWaitTime) { globalTargetPos.WaitTime++; globalTargetPos.CarState = VehicleJunctionTransitState.Stop; hasIncomingCars = TrafficPriority.HasIncomingVehiclesWithHigherPriority(vehicleId, destinationNodeId); #if DEBUG if (debug) { Log._Debug($"hasIncomingCars: {hasIncomingCars}"); } #endif if (hasIncomingCars) { if (lastFrameData.m_velocity.magnitude > 0) { maxSpeed = Math.Max(0f, lastFrameData.m_velocity.magnitude - globalTargetPos.ReduceSpeedByValueToYield); } else { maxSpeed = 0; } #if DEBUG /*if (TrafficPriority.Vehicles[vehicleId].ToNode == 8621) * Log.Message($"Vehicle {vehicleId} is yielding at node {destinationNodeId}. Speed: {maxSpeed}, Waiting time: {TrafficPriority.Vehicles[vehicleId].WaitTime}");*/ #endif return; } else { #if DEBUG /*if (TrafficPriority.Vehicles[vehicleId].ToNode == 8621) * Log.Message($"Vehicle {vehicleId} is NOT yielding at node {destinationNodeId}.");*/ #endif if (lastFrameData.m_velocity.magnitude > 0) { maxSpeed = Math.Max(1f, lastFrameData.m_velocity.magnitude - globalTargetPos.ReduceSpeedByValueToYield * 0.5f); } } globalTargetPos.CarState = VehicleJunctionTransitState.Leave; } else { globalTargetPos.CarState = VehicleJunctionTransitState.Leave; } break; case SegmentEnd.PriorityType.Main: #if DEBUG if (debug) { Log._Debug($"Vehicle {vehicleId}: MAIN sign. waittime={globalTargetPos.WaitTime}"); } #endif if (globalTargetPos.WaitTime < MaxPriorityWaitTime) { globalTargetPos.WaitTime++; globalTargetPos.CarState = VehicleJunctionTransitState.Stop; maxSpeed = 0f; hasIncomingCars = TrafficPriority.HasIncomingVehiclesWithHigherPriority(vehicleId, destinationNodeId); #if DEBUG if (debug) { Log._Debug($"hasIncomingCars: {hasIncomingCars}"); } #endif if (hasIncomingCars) { globalTargetPos.Stopped = true; return; } globalTargetPos.CarState = VehicleJunctionTransitState.Leave; globalTargetPos.Stopped = false; } var info3 = netManager.m_segments.m_buffer[position.m_segment].Info; if (info3.m_lanes != null && info3.m_lanes.Length > position.m_lane) { //maxSpeed = CalculateTargetSpeed(vehicleId, ref vehicleData, info3.m_lanes[position.m_lane].m_speedLimit, netManager.m_lanes.m_buffer[(int)((UIntPtr)laneID)].m_curve) * 0.8f; maxSpeed = CalculateTargetSpeed(vehicleId, ref vehicleData, SpeedLimitManager.GetLockFreeGameSpeedLimit(position.m_segment, position.m_lane, laneID, info3.m_lanes[position.m_lane]), netManager.m_lanes.m_buffer[(int)((UIntPtr)laneID)].m_curve); } else { maxSpeed = CalculateTargetSpeed(vehicleId, ref vehicleData, 1f, 0f); } return; } } else { globalTargetPos.CarState = VehicleJunctionTransitState.Leave; } } else { #if DEBUG if (debug) { Log._Debug($"globalTargetPos is null! {vehicleId} @ seg. {prevPos.m_segment} @ node {destinationNodeId}"); } #endif } } else { #if DEBUG if (debug) { Log._Debug($"targetPos is null! {vehicleId} @ seg. {prevPos.m_segment} @ node {destinationNodeId}"); } #endif } } } } } } catch (Exception e) { Log.Error($"Error occured in TmCalculateSegmentPosition: {e.ToString()}"); } } } var info2 = netManager.m_segments.m_buffer[position.m_segment].Info; if (info2.m_lanes != null && info2.m_lanes.Length > position.m_lane) { var laneSpeedLimit = SpeedLimitManager.GetLockFreeGameSpeedLimit(position.m_segment, position.m_lane, laneID, info2.m_lanes[position.m_lane]); // info2.m_lanes[position.m_lane].m_speedLimit; #if DEBUG /*if (position.m_segment == 275) { * Log._Debug($"Applying lane speed limit of {laneSpeedLimit} to lane {laneID} @ seg. {position.m_segment}"); * }*/ #endif /*if (TrafficRoadRestrictions.IsSegment(position.m_segment)) { * var restrictionSegment = TrafficRoadRestrictions.GetSegment(position.m_segment); * * if (restrictionSegment.SpeedLimits[position.m_lane] > 0.1f) { * laneSpeedLimit = restrictionSegment.SpeedLimits[position.m_lane]; * } * }*/ maxSpeed = CalculateTargetSpeed(vehicleId, ref vehicleData, laneSpeedLimit, netManager.m_lanes.m_buffer[(int)((UIntPtr)laneID)].m_curve); } else { maxSpeed = CalculateTargetSpeed(vehicleId, ref vehicleData, 1f, 0f); } maxSpeed = CalcMaxSpeed(vehicleId, ref vehicleData, position, pos, maxSpeed, isRecklessDriver); }
public void CustomCalculateSegmentPosition(ushort vehicleId, ref Vehicle vehicleData, PathUnit.Position nextPosition, PathUnit.Position position, uint laneID, byte offset, PathUnit.Position prevPos, uint prevLaneID, byte prevOffset, int index, out Vector3 pos, out Vector3 dir, out float maxSpeed) { if ((Options.prioritySignsEnabled || Options.timedLightsEnabled) && Options.simAccuracy <= 1) { try { VehicleStateManager.Instance().UpdateVehiclePos(vehicleId, ref vehicleData, ref prevPos, ref position); } catch (Exception e) { Log.Error("TramAI CustomCalculateSegmentPosition Error: " + e.ToString()); } } NetManager netManager = Singleton <NetManager> .instance; netManager.m_lanes.m_buffer[(int)((UIntPtr)laneID)].CalculatePositionAndDirection((float)offset * 0.003921569f, out pos, out dir); Vector3 b = netManager.m_lanes.m_buffer[(int)((UIntPtr)prevLaneID)].CalculatePosition((float)prevOffset * 0.003921569f); Vehicle.Frame lastFrameData = vehicleData.GetLastFrameData(); Vector3 a = lastFrameData.m_position; Vector3 a2 = lastFrameData.m_position; Vector3 b2 = lastFrameData.m_rotation * new Vector3(0f, 0f, this.m_info.m_generatedInfo.m_wheelBase * 0.5f); a += b2; a2 -= b2; float crazyValue = 0.5f * lastFrameData.m_velocity.sqrMagnitude / this.m_info.m_braking; float a3 = Vector3.Distance(a, b); float b3 = Vector3.Distance(a2, b); if (Mathf.Min(a3, b3) >= crazyValue - 1f) { Segment3 segment; segment.a = pos; ushort targetNodeId; ushort nextTargetNodeId; if (offset < position.m_offset) { segment.b = pos + dir.normalized * this.m_info.m_generatedInfo.m_size.z; targetNodeId = netManager.m_segments.m_buffer[(int)position.m_segment].m_startNode; nextTargetNodeId = netManager.m_segments.m_buffer[(int)position.m_segment].m_endNode; } else { segment.b = pos - dir.normalized * this.m_info.m_generatedInfo.m_size.z; targetNodeId = netManager.m_segments.m_buffer[(int)position.m_segment].m_endNode; nextTargetNodeId = netManager.m_segments.m_buffer[(int)position.m_segment].m_startNode; } ushort prevTargetNodeId; if (prevOffset == 0) { prevTargetNodeId = netManager.m_segments.m_buffer[(int)prevPos.m_segment].m_startNode; } else { prevTargetNodeId = netManager.m_segments.m_buffer[(int)prevPos.m_segment].m_endNode; } if (targetNodeId == prevTargetNodeId) { if (!CustomVehicleAI.MayChangeSegment(vehicleId, ref vehicleData, ref lastFrameData, false, ref prevPos, prevTargetNodeId, prevLaneID, ref position, targetNodeId, laneID, ref nextPosition, nextTargetNodeId, out maxSpeed)) { return; } } } NetInfo info = netManager.m_segments.m_buffer[(int)position.m_segment].Info; if (info.m_lanes != null && info.m_lanes.Length > (int)position.m_lane) { float speedLimit = Options.customSpeedLimitsEnabled ? SpeedLimitManager.Instance().GetLockFreeGameSpeedLimit(position.m_segment, position.m_lane, laneID, info.m_lanes[position.m_lane]) : info.m_lanes[position.m_lane].m_speedLimit; maxSpeed = CalculateTargetSpeed(vehicleId, ref vehicleData, speedLimit, netManager.m_lanes.m_buffer[laneID].m_curve); } else { maxSpeed = this.CalculateTargetSpeed(vehicleId, ref vehicleData, 1f, 0f); } }
private bool drawSpeedLimitHandles(ushort segmentId, bool viewOnly) { if (!LoadingExtension.IsPathManagerCompatible) { return(false); } if (viewOnly && !Options.speedLimitsOverlay) { return(false); } // draw speedlimits over mean middle points of lane beziers if (!segmentCenterByDir.ContainsKey(segmentId)) { segmentCenterByDir.Add(segmentId, new Dictionary <NetInfo.Direction, Vector3>()); TrafficManagerTool.CalculateSegmentCenterByDir(segmentId, segmentCenterByDir[segmentId]); } bool hovered = false; foreach (KeyValuePair <NetInfo.Direction, Vector3> e in segmentCenterByDir[segmentId]) { Vector3 signPos = e.Value; var screenPos = Camera.main.WorldToScreenPoint(signPos); screenPos.y = Screen.height - screenPos.y; if (screenPos.z < 0) { return(false); } var camPos = Singleton <SimulationManager> .instance.m_simulationView.m_position; var diff = signPos - camPos; if (diff.magnitude > TrafficManagerTool.PriorityCloseLod) { return(false); // do not draw if too distant } ItemClass connectionClass = Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].Info.GetConnectionClass(); if (!(connectionClass.m_service == ItemClass.Service.Road || (connectionClass.m_service == ItemClass.Service.PublicTransport && connectionClass.m_subService == ItemClass.SubService.PublicTransportTrain))) { return(false); } var zoom = 1.0f / diff.magnitude * 100f * MainTool.GetBaseZoom(); var size = speedLimitSignSize * zoom; var guiColor = GUI.color; var boundingBox = new Rect(screenPos.x - size / 2, screenPos.y - size / 2, size, size); bool hoveredHandle = !viewOnly && TrafficManagerTool.IsMouseOver(boundingBox); if (hoveredHandle) { // mouse hovering over sign hovered = true; guiColor.a = 0.8f; } else { guiColor.a = 0.5f; } GUI.color = guiColor; try { GUI.DrawTexture(boundingBox, TrafficLightToolTextureResources.SpeedLimitTextures[SpeedLimitManager.GetCustomSpeedLimit(segmentId, e.Key)]); } catch (Exception ex) { Log.Error("segment " + segmentId + " limit: " + SpeedLimitManager.GetCustomSpeedLimit(segmentId, e.Key) + ", ex: " + ex.ToString()); } if (hoveredHandle && Input.GetMouseButton(0)) { // change the speed limit to the selected one ushort speedLimitToSet = SpeedLimitManager.AvailableSpeedLimits[curSpeedLimitIndex]; //Log._Debug($"Setting speed limit of segment {segmentId}, dir {e.Key.ToString()} to {speedLimitToSet}"); SpeedLimitManager.SetSpeedLimit(segmentId, e.Key, speedLimitToSet); //mouseClickProcessed = true; } guiColor.a = 1f; GUI.color = guiColor; } return(hovered); }
static TrafficLightToolTextureResources() { // simple RedLightTexture2D = LoadDllResource("light_1_1.png", 103, 243); YellowRedLightTexture2D = LoadDllResource("light_1_2.png", 103, 243); GreenLightTexture2D = LoadDllResource("light_1_3.png", 103, 243); // forward RedLightStraightTexture2D = LoadDllResource("light_2_1.png", 103, 243); YellowLightStraightTexture2D = LoadDllResource("light_2_2.png", 103, 243); GreenLightStraightTexture2D = LoadDllResource("light_2_3.png", 103, 243); // right RedLightRightTexture2D = LoadDllResource("light_3_1.png", 103, 243); YellowLightRightTexture2D = LoadDllResource("light_3_2.png", 103, 243); GreenLightRightTexture2D = LoadDllResource("light_3_3.png", 103, 243); // left RedLightLeftTexture2D = LoadDllResource("light_4_1.png", 103, 243); YellowLightLeftTexture2D = LoadDllResource("light_4_2.png", 103, 243); GreenLightLeftTexture2D = LoadDllResource("light_4_3.png", 103, 243); // forwardright RedLightForwardRightTexture2D = LoadDllResource("light_5_1.png", 103, 243); YellowLightForwardRightTexture2D = LoadDllResource("light_5_2.png", 103, 243); GreenLightForwardRightTexture2D = LoadDllResource("light_5_3.png", 103, 243); // forwardleft RedLightForwardLeftTexture2D = LoadDllResource("light_6_1.png", 103, 243); YellowLightForwardLeftTexture2D = LoadDllResource("light_6_2.png", 103, 243); GreenLightForwardLeftTexture2D = LoadDllResource("light_6_3.png", 103, 243); // yellow YellowLightTexture2D = LoadDllResource("light_yellow.png", 103, 243); // pedestrian PedestrianRedLightTexture2D = LoadDllResource("pedestrian_light_1.png", 73, 123); PedestrianGreenLightTexture2D = LoadDllResource("pedestrian_light_2.png", 73, 123); // light mode LightModeTexture2D = LoadDllResource(Translation.GetTranslatedFileName("light_mode.png"), 103, 95); LightCounterTexture2D = LoadDllResource(Translation.GetTranslatedFileName("light_counter.png"), 103, 95); // pedestrian mode PedestrianModeAutomaticTexture2D = LoadDllResource("pedestrian_mode_1.png", 73, 70); PedestrianModeManualTexture2D = LoadDllResource("pedestrian_mode_2.png", 73, 73); // priority signs SignStopTexture2D = LoadDllResource("sign_stop.png", 200, 200); SignYieldTexture2D = LoadDllResource("sign_yield.png", 200, 200); SignPriorityTexture2D = LoadDllResource("sign_priority.png", 200, 200); SignNoneTexture2D = LoadDllResource("sign_none.png", 200, 200); // delete priority sign SignRemoveTexture2D = LoadDllResource("remove_signs.png", 256, 256); // timer ClockPlayTexture2D = LoadDllResource("clock_play.png", 512, 512); ClockPauseTexture2D = LoadDllResource("clock_pause.png", 512, 512); ClockTestTexture2D = LoadDllResource("clock_test.png", 512, 512); SpeedLimitTextures = new Dictionary <ushort, Texture2D>(); foreach (ushort speedLimit in SpeedLimitManager.Instance().AvailableSpeedLimits) { SpeedLimitTextures.Add(speedLimit, LoadDllResource(speedLimit.ToString() + ".png", 200, 200)); } VehicleRestrictionTextures = new Dictionary <ExtVehicleType, Dictionary <bool, Texture2D> >(); VehicleRestrictionTextures[ExtVehicleType.Bus] = new Dictionary <bool, Texture2D>(); VehicleRestrictionTextures[ExtVehicleType.CargoTrain] = new Dictionary <bool, Texture2D>(); VehicleRestrictionTextures[ExtVehicleType.CargoTruck] = new Dictionary <bool, Texture2D>(); VehicleRestrictionTextures[ExtVehicleType.Emergency] = new Dictionary <bool, Texture2D>(); VehicleRestrictionTextures[ExtVehicleType.PassengerCar] = new Dictionary <bool, Texture2D>(); VehicleRestrictionTextures[ExtVehicleType.PassengerTrain] = new Dictionary <bool, Texture2D>(); VehicleRestrictionTextures[ExtVehicleType.Service] = new Dictionary <bool, Texture2D>(); VehicleRestrictionTextures[ExtVehicleType.Taxi] = new Dictionary <bool, Texture2D>(); foreach (KeyValuePair <ExtVehicleType, Dictionary <bool, Texture2D> > e in VehicleRestrictionTextures) { foreach (bool b in new bool[] { false, true }) { string suffix = b ? "allowed" : "forbidden"; e.Value[b] = LoadDllResource(e.Key.ToString().ToLower() + "_" + suffix + ".png", 200, 200); } } LaneChangeAllowedTexture2D = LoadDllResource("lanechange_allowed.png", 200, 200); LaneChangeForbiddenTexture2D = LoadDllResource("lanechange_forbidden.png", 200, 200); UturnAllowedTexture2D = LoadDllResource("uturn_allowed.png", 200, 200); UturnForbiddenTexture2D = LoadDllResource("uturn_forbidden.png", 200, 200); EnterBlockedJunctionAllowedTexture2D = LoadDllResource("enterblocked_allowed.png", 200, 200); EnterBlockedJunctionForbiddenTexture2D = LoadDllResource("enterblocked_forbidden.png", 200, 200); PedestrianCrossingAllowedTexture2D = LoadDllResource("crossing_allowed.png", 200, 200); PedestrianCrossingForbiddenTexture2D = LoadDllResource("crossing_forbidden.png", 200, 200); VehicleInfoSignTextures = new Dictionary <ExtVehicleType, Texture2D>(); VehicleInfoSignTextures[ExtVehicleType.Bicycle] = LoadDllResource("bicycle_infosign.png", 449, 411); VehicleInfoSignTextures[ExtVehicleType.Bus] = LoadDllResource("bus_infosign.png", 449, 411); VehicleInfoSignTextures[ExtVehicleType.CargoTrain] = LoadDllResource("cargotrain_infosign.png", 449, 411); VehicleInfoSignTextures[ExtVehicleType.CargoTruck] = LoadDllResource("cargotruck_infosign.png", 449, 411); VehicleInfoSignTextures[ExtVehicleType.Emergency] = LoadDllResource("emergency_infosign.png", 449, 411); VehicleInfoSignTextures[ExtVehicleType.PassengerCar] = LoadDllResource("passengercar_infosign.png", 449, 411); VehicleInfoSignTextures[ExtVehicleType.PassengerTrain] = LoadDllResource("passengertrain_infosign.png", 449, 411); VehicleInfoSignTextures[ExtVehicleType.Service] = LoadDllResource("service_infosign.png", 449, 411); VehicleInfoSignTextures[ExtVehicleType.Taxi] = LoadDllResource("taxi_infosign.png", 449, 411); VehicleInfoSignTextures[ExtVehicleType.Tram] = LoadDllResource("tram_infosign.png", 449, 411); }
private void ShowSigns(bool viewOnly) { Quaternion camRot = Camera.main.transform.rotation; Vector3 camPos = Camera.main.transform.position; NetManager netManager = Singleton <NetManager> .instance; SpeedLimitManager speedLimitManager = SpeedLimitManager.Instance; if (lastCamPos == null || lastCamRot == null || !lastCamRot.Equals(camRot) || !lastCamPos.Equals(camPos)) { // cache visible segments currentlyVisibleSegmentIds.Clear(); for (uint segmentId = 1; segmentId < NetManager.MAX_SEGMENT_COUNT; ++segmentId) { if (!Constants.ServiceFactory.NetService.IsSegmentValid((ushort)segmentId)) { continue; } /*if ((netManager.m_segments.m_buffer[segmentId].m_flags & NetSegment.Flags.Untouchable) != NetSegment.Flags.None) * continue;*/ if ((netManager.m_segments.m_buffer[segmentId].m_bounds.center - camPos).magnitude > TrafficManagerTool.MaxOverlayDistance) { continue; // do not draw if too distant } Vector3 screenPos; bool visible = MainTool.WorldToScreenPoint(netManager.m_segments.m_buffer[segmentId].m_bounds.center, out screenPos); if (!visible) { continue; } if (!speedLimitManager.MayHaveCustomSpeedLimits((ushort)segmentId, ref netManager.m_segments.m_buffer[segmentId])) { continue; } currentlyVisibleSegmentIds.Add((ushort)segmentId); } lastCamPos = camPos; lastCamRot = camRot; } bool handleHovered = false; foreach (ushort segmentId in currentlyVisibleSegmentIds) { Vector3 screenPos; bool visible = MainTool.WorldToScreenPoint(netManager.m_segments.m_buffer[segmentId].m_bounds.center, out screenPos); if (!visible) { continue; } NetInfo segmentInfo = netManager.m_segments.m_buffer[segmentId].Info; // draw speed limits if (MainTool.GetToolMode() != ToolMode.VehicleRestrictions || segmentId != SelectedSegmentId) // no speed limit overlay on selected segment when in vehicle restrictions mode { if (drawSpeedLimitHandles((ushort)segmentId, ref netManager.m_segments.m_buffer[segmentId], viewOnly, ref camPos)) { handleHovered = true; } } } overlayHandleHovered = handleHovered; }
public void CustomSegmentSimulationStep(ushort segmentID, ref NetSegment data) { if (initDone) { try { TrafficPriority.segmentHousekeeping(segmentID); } catch (Exception e) { Log.Error($"Error occured while housekeeping segment {segmentID}: " + e.ToString()); } if (!Options.isStockLaneChangerUsed()) { try { InStartupPhase = simStartFrame == 0 || simStartFrame >> 14 >= Singleton <SimulationManager> .instance.m_currentFrameIndex >> 14; // approx. 3 minutes // calculate traffic density uint curLaneId = data.m_lanes; int nextNumLanes = data.Info.m_lanes.Length; uint laneIndex = 0; bool firstWithTraffic = true; bool resetDensity = false; while (laneIndex < nextNumLanes && curLaneId != 0u) { uint buf = currentLaneTrafficBuffer[curLaneId]; uint currentDensities = currentLaneDensities[curLaneId]; //currentMeanDensity = (byte)Math.Min(100u, (uint)((currentDensities * 100u) / Math.Max(1u, maxDens))); // 0 .. 100 byte currentMeanSpeed = 25; // we use integer division here because it's faster if (buf > 0) { uint currentSpeeds = currentLaneSpeeds[curLaneId]; if (!InStartupPhase) { currentMeanSpeed = (byte)Math.Min(100u, ((currentSpeeds * 100u) / buf) / ((uint)(Math.Max(SpeedLimitManager.GetLockFreeGameSpeedLimit(segmentID, laneIndex, curLaneId, data.Info.m_lanes[laneIndex]) * 8f, 1f)))); // 0 .. 100, m_speedLimit of highway is 2, actual max. vehicle speed on highway is 16, that's why we use x*8 == x<<3 (don't ask why CO uses different units for velocity) } } else { if (!InStartupPhase) { currentMeanSpeed = 100; } } /*if (segmentID == 22980) { * Log._Debug($"Lane {curLaneId}: currentMeanSpeed={currentMeanSpeed} currentMeanDensity={currentMeanDensity}"); * }*/ if (currentMeanSpeed >= laneMeanSpeeds[curLaneId]) { laneMeanSpeeds[curLaneId] = (byte)Math.Min((int)laneMeanSpeeds[curLaneId] + 5, currentMeanSpeed); } else { laneMeanSpeeds[curLaneId] = (byte)Math.Max((int)laneMeanSpeeds[curLaneId] - 5, 0); } //laneMeanDensities[curLaneId] = currentMeanDensity; currentLaneTrafficBuffer[curLaneId] = 0; currentLaneSpeeds[curLaneId] = 0; if (currentLaneDensities[curLaneId] > 0 && firstWithTraffic) { resetDensity = (currentLaneDensities[curLaneId] > 1000000); firstWithTraffic = false; } if (resetDensity) { currentLaneDensities[curLaneId] /= 2u; } laneIndex++; curLaneId = Singleton <NetManager> .instance.m_lanes.m_buffer[curLaneId].m_nextLane; } } catch (Exception e) { Log.Error("Error occured while calculating lane traffic density: " + e.ToString()); } } } try { OriginalSimulationStep(segmentID, ref data); } catch (Exception ex) { Log.Error("Error in CustomRoadAI.SimulationStep: " + ex.ToString()); } }
public void CustomCalculateSegmentPosition(ushort vehicleId, ref Vehicle vehicleData, PathUnit.Position nextPosition, PathUnit.Position position, uint laneID, byte offset, PathUnit.Position prevPos, uint prevLaneID, byte prevOffset, int index, out Vector3 pos, out Vector3 dir, out float maxSpeed) { if ((Options.prioritySignsEnabled || Options.timedLightsEnabled) && Options.simAccuracy <= 1) { try { VehicleStateManager.Instance().UpdateVehiclePos(vehicleId, ref vehicleData, ref prevPos, ref position); } catch (Exception e) { Log.Error("CarAI CustomCalculateSegmentPosition Error: " + e.ToString()); } } var netManager = Singleton <NetManager> .instance; //var vehicleManager = Singleton<VehicleManager>.instance; netManager.m_lanes.m_buffer[(int)((UIntPtr)laneID)].CalculatePositionAndDirection(offset * 0.003921569f, out pos, out dir); Vehicle.Frame lastFrameData = vehicleData.GetLastFrameData(); Vector3 lastFrameVehiclePos = lastFrameData.m_position; var camPos = Camera.main.transform.position; #if DEBUG //bool isEmergency = VehicleStateManager._GetVehicleState(vehicleId).VehicleType == ExtVehicleType.Emergency; #endif // I think this is supposed to be the lane position? // [VN, 12/23/2015] It's the 3D car position on the Bezier curve of the lane. // This crazy 0.003921569f equals to 1f/255 and prevOffset is the byte value (0..255) of the car position. var vehiclePosOnBezier = netManager.m_lanes.m_buffer[(int)((UIntPtr)prevLaneID)].CalculatePosition(prevOffset * 0.003921569f); //ushort currentSegmentId = netManager.m_lanes.m_buffer[(int)((UIntPtr)prevLaneID)].m_segment; ushort targetNodeId; ushort nextTargetNodeId; if (offset < position.m_offset) { targetNodeId = netManager.m_segments.m_buffer[position.m_segment].m_startNode; nextTargetNodeId = netManager.m_segments.m_buffer[position.m_segment].m_endNode; } else { targetNodeId = netManager.m_segments.m_buffer[position.m_segment].m_endNode; nextTargetNodeId = netManager.m_segments.m_buffer[position.m_segment].m_startNode; } var prevTargetNodeId = prevOffset == 0 ? netManager.m_segments.m_buffer[prevPos.m_segment].m_startNode : netManager.m_segments.m_buffer[prevPos.m_segment].m_endNode; // this seems to be like the required braking force in order to stop the vehicle within its half length. var crazyValue = 0.5f * lastFrameData.m_velocity.sqrMagnitude / m_info.m_braking + m_info.m_generatedInfo.m_size.z * 0.5f; /*try { * VehicleStateManager.UpdateVehiclePos(vehicleId, ref vehicleData); * } catch (Exception e) { * Log.Error("CarAI TmCalculateSegmentPosition Error: " + e.ToString()); * }*/ bool isRecklessDriver = IsRecklessDriver(vehicleId, ref vehicleData); if (targetNodeId == prevTargetNodeId) { if (Vector3.Distance(lastFrameVehiclePos, vehiclePosOnBezier) >= crazyValue - 1f) { if (!CustomVehicleAI.MayChangeSegment(vehicleId, ref vehicleData, ref lastFrameData, isRecklessDriver, ref prevPos, prevTargetNodeId, prevLaneID, ref position, targetNodeId, laneID, ref nextPosition, nextTargetNodeId, out maxSpeed)) { return; } } } var info2 = netManager.m_segments.m_buffer[position.m_segment].Info; if (info2.m_lanes != null && info2.m_lanes.Length > position.m_lane) { var laneSpeedLimit = Options.customSpeedLimitsEnabled ? SpeedLimitManager.Instance().GetLockFreeGameSpeedLimit(position.m_segment, position.m_lane, laneID, info2.m_lanes[position.m_lane]) : info2.m_lanes[position.m_lane].m_speedLimit; // info2.m_lanes[position.m_lane].m_speedLimit; #if DEBUG /*if (position.m_segment == 275) { * Log._Debug($"Applying lane speed limit of {laneSpeedLimit} to lane {laneID} @ seg. {position.m_segment}"); * }*/ #endif maxSpeed = CalculateTargetSpeed(vehicleId, ref vehicleData, laneSpeedLimit, netManager.m_lanes.m_buffer[(int)((UIntPtr)laneID)].m_curve); } else { maxSpeed = CalculateTargetSpeed(vehicleId, ref vehicleData, 1f, 0f); } maxSpeed = CalcMaxSpeed(vehicleId, ref vehicleData, position, pos, maxSpeed, isRecklessDriver); }
private bool drawSpeedLimitHandles(ushort segmentId, bool viewOnly) { if (!LoadingExtension.IsPathManagerCompatible) { return(false); } if (viewOnly && !Options.speedLimitsOverlay) { return(false); } // draw speedlimits over mean middle points of lane beziers if (!segmentCenterByDir.ContainsKey(segmentId)) { segmentCenterByDir.Add(segmentId, new Dictionary <NetInfo.Direction, Vector3>()); TrafficManagerTool.CalculateSegmentCenterByDir(segmentId, segmentCenterByDir[segmentId]); } bool hovered = false; foreach (KeyValuePair <NetInfo.Direction, Vector3> e in segmentCenterByDir[segmentId]) { Vector3 signPos = e.Value; var screenPos = Camera.main.WorldToScreenPoint(signPos); screenPos.y = Screen.height - screenPos.y; if (screenPos.z < 0) { return(false); } var camPos = Singleton <SimulationManager> .instance.m_simulationView.m_position; var diff = signPos - camPos; if (diff.magnitude > TrafficManagerTool.PriorityCloseLod) { return(false); // do not draw if too distant } ItemClass connectionClass = Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].Info.GetConnectionClass(); if (!(connectionClass.m_service == ItemClass.Service.Road || (connectionClass.m_service == ItemClass.Service.PublicTransport && connectionClass.m_subService == ItemClass.SubService.PublicTransportTrain))) { return(false); } var zoom = 1.0f / diff.magnitude * 100f * MainTool.GetBaseZoom(); var size = speedLimitSignSize * zoom; var guiColor = GUI.color; var boundingBox = new Rect(screenPos.x - size / 2, screenPos.y - size / 2, size, size); bool hoveredHandle = !viewOnly && TrafficManagerTool.IsMouseOver(boundingBox); if (hoveredHandle) { // mouse hovering over sign hovered = true; guiColor.a = 0.8f; } else { guiColor.a = 0.5f; } GUI.color = guiColor; try { GUI.DrawTexture(boundingBox, TrafficLightToolTextureResources.SpeedLimitTextures[SpeedLimitManager.GetCustomSpeedLimit(segmentId, e.Key)]); } catch (Exception ex) { Log.Error("segment " + segmentId + " limit: " + SpeedLimitManager.GetCustomSpeedLimit(segmentId, e.Key) + ", ex: " + ex.ToString()); } if (hoveredHandle && Input.GetMouseButton(0)) { // change the speed limit to the selected one ushort speedLimitToSet = SpeedLimitManager.AvailableSpeedLimits[curSpeedLimitIndex]; //Log._Debug($"Setting speed limit of segment {segmentId}, dir {e.Key.ToString()} to {speedLimitToSet}"); SpeedLimitManager.SetSpeedLimit(segmentId, e.Key, speedLimitToSet); // TODO use SegmentTraverser if (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift)) { NetInfo selectedSegmentInfo = Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].Info; List <object[]> selectedSortedLanes = TrafficManagerTool.GetSortedVehicleLanes(segmentId, selectedSegmentInfo, null); LinkedList <ushort> nodesToProcess = new LinkedList <ushort>(); HashSet <ushort> processedNodes = new HashSet <ushort>(); HashSet <ushort> processedSegments = new HashSet <ushort>(); processedSegments.Add(SelectedSegmentId); ushort selectedStartNodeId = Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].m_startNode; ushort selectedEndNodeId = Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].m_endNode; if (selectedStartNodeId != 0) { nodesToProcess.AddFirst(selectedStartNodeId); } if (selectedEndNodeId != 0) { nodesToProcess.AddFirst(selectedEndNodeId); } while (nodesToProcess.First != null) { ushort nodeId = nodesToProcess.First.Value; nodesToProcess.RemoveFirst(); processedNodes.Add(nodeId); if (Singleton <NetManager> .instance.m_nodes.m_buffer[nodeId].CountSegments() > 2) { continue; // junction. stop. } // explore segments at node for (var s = 0; s < 8; s++) { var otherSegmentId = Singleton <NetManager> .instance.m_nodes.m_buffer[nodeId].GetSegment(s); if (otherSegmentId <= 0 || processedSegments.Contains(otherSegmentId)) { continue; } processedSegments.Add(otherSegmentId); NetInfo segmentInfo = Singleton <NetManager> .instance.m_segments.m_buffer[otherSegmentId].Info; List <object[]> sortedLanes = TrafficManagerTool.GetSortedVehicleLanes(otherSegmentId, segmentInfo, null); if (sortedLanes.Count == selectedSortedLanes.Count) { // number of lanes matches selected segment for (int i = 0; i < sortedLanes.Count; ++i) { object[] selectedLaneData = selectedSortedLanes[i]; object[] laneData = sortedLanes[i]; uint selectedLaneId = (uint)selectedLaneData[0]; uint selectedLaneIndex = (uint)selectedLaneData[2]; NetInfo.Lane selectedLaneInfo = segmentInfo.m_lanes[selectedLaneIndex]; uint laneId = (uint)laneData[0]; uint laneIndex = (uint)laneData[2]; NetInfo.Lane laneInfo = segmentInfo.m_lanes[laneIndex]; if (laneInfo.m_finalDirection == e.Key) { SpeedLimitManager.SetSpeedLimit(otherSegmentId, laneInfo.m_finalDirection, speedLimitToSet); } // apply restrictions of selected segment & lane //VehicleRestrictionsManager.SetAllowedVehicleTypes(otherSegmentId, segmentInfo, laneIndex, laneInfo, laneId, VehicleRestrictionsManager.GetAllowedVehicleTypes(SelectedSegmentId, selectedSegmentInfo, selectedLaneIndex, selectedLaneInfo)); } // add nodes to explore ushort startNodeId = Singleton <NetManager> .instance.m_segments.m_buffer[otherSegmentId].m_startNode; ushort endNodeId = Singleton <NetManager> .instance.m_segments.m_buffer[otherSegmentId].m_endNode; if (startNodeId != 0 && !processedNodes.Contains(startNodeId)) { nodesToProcess.AddFirst(startNodeId); } if (endNodeId != 0 && !processedNodes.Contains(endNodeId)) { nodesToProcess.AddFirst(endNodeId); } } } } } //mouseClickProcessed = true; } guiColor.a = 1f; GUI.color = guiColor; } return(hovered); }
public void CustomCalculateSegmentPosition(ushort vehicleID, ref Vehicle vehicleData, PathUnit.Position nextPosition, PathUnit.Position position, uint laneID, byte offset, PathUnit.Position prevPos, uint prevLaneID, byte prevOffset, int index, out Vector3 pos, out Vector3 dir, out float maxSpeed) { NetManager instance = Singleton <NetManager> .instance; instance.m_lanes.m_buffer[(int)((UIntPtr)laneID)].CalculatePositionAndDirection((float)offset * 0.003921569f, out pos, out dir); Vector3 b = instance.m_lanes.m_buffer[(int)((UIntPtr)prevLaneID)].CalculatePosition((float)prevOffset * 0.003921569f); Vehicle.Frame lastFrameData = vehicleData.GetLastFrameData(); Vector3 a = lastFrameData.m_position; Vector3 a2 = lastFrameData.m_position; Vector3 b2 = lastFrameData.m_rotation * new Vector3(0f, 0f, this.m_info.m_generatedInfo.m_wheelBase * 0.5f); a += b2; a2 -= b2; float num = 0.5f * lastFrameData.m_velocity.sqrMagnitude / this.m_info.m_braking; float a3 = Vector3.Distance(a, b); float b3 = Vector3.Distance(a2, b); if (Mathf.Min(a3, b3) >= num - 1f) { Segment3 segment; segment.a = pos; ushort num2; ushort num3; if (offset < position.m_offset) { segment.b = pos + dir.normalized * this.m_info.m_generatedInfo.m_size.z; num2 = instance.m_segments.m_buffer[(int)position.m_segment].m_startNode; num3 = instance.m_segments.m_buffer[(int)position.m_segment].m_endNode; } else { segment.b = pos - dir.normalized * this.m_info.m_generatedInfo.m_size.z; num2 = instance.m_segments.m_buffer[(int)position.m_segment].m_endNode; num3 = instance.m_segments.m_buffer[(int)position.m_segment].m_startNode; } ushort num4; if (prevOffset == 0) { num4 = instance.m_segments.m_buffer[(int)prevPos.m_segment].m_startNode; } else { num4 = instance.m_segments.m_buffer[(int)prevPos.m_segment].m_endNode; } if (num2 == num4) { NetNode.Flags flags = instance.m_nodes.m_buffer[(int)num2].m_flags; NetLane.Flags flags2 = (NetLane.Flags)instance.m_lanes.m_buffer[(int)((UIntPtr)prevLaneID)].m_flags; bool flag = (flags & NetNode.Flags.TrafficLights) != NetNode.Flags.None; bool flag2 = (flags & NetNode.Flags.LevelCrossing) != NetNode.Flags.None; bool flag3 = (flags2 & NetLane.Flags.JoinedJunction) != NetLane.Flags.None; bool checkSpace = !Options.allowEnterBlockedJunctions; // NON-STOCK CODE if (checkSpace && (flags & (NetNode.Flags.Junction | NetNode.Flags.OneWayOut | NetNode.Flags.OneWayIn)) == NetNode.Flags.Junction && instance.m_nodes.m_buffer[(int)num2].CountSegments() != 2) { float len = vehicleData.CalculateTotalLength(vehicleID) + 2f; if (!instance.m_lanes.m_buffer[(int)((UIntPtr)laneID)].CheckSpace(len)) { bool flag4 = false; if (nextPosition.m_segment != 0 && instance.m_lanes.m_buffer[(int)((UIntPtr)laneID)].m_length < 30f) { NetNode.Flags flags3 = instance.m_nodes.m_buffer[(int)num3].m_flags; if ((flags3 & (NetNode.Flags.Junction | NetNode.Flags.OneWayOut | NetNode.Flags.OneWayIn)) != NetNode.Flags.Junction || instance.m_nodes.m_buffer[(int)num3].CountSegments() == 2) { uint laneID2 = PathManager.GetLaneID(nextPosition); if (laneID2 != 0u) { flag4 = instance.m_lanes.m_buffer[(int)((UIntPtr)laneID2)].CheckSpace(len); } } } if (!flag4) { maxSpeed = 0f; return; } } } if (flag && (!flag3 || flag2)) { uint currentFrameIndex = Singleton <SimulationManager> .instance.m_currentFrameIndex; uint num5 = (uint)(((int)num4 << 8) / 32768); uint num6 = currentFrameIndex - num5 & 255u; RoadBaseAI.TrafficLightState vehicleLightState; RoadBaseAI.TrafficLightState pedestrianLightState; bool flag5; bool pedestrians; /// NON-STOCK CODE START /// CustomRoadAI.GetTrafficLightState(vehicleID, ref vehicleData, num4, prevPos.m_segment, position.m_segment, ref instance.m_segments.m_buffer[(int)prevPos.m_segment], currentFrameIndex - num5, out vehicleLightState, out pedestrianLightState, out flag5, out pedestrians); /// NON-STOCK CODE END /// //RoadBaseAI.GetTrafficLightState(num4, ref instance.m_segments.m_buffer[(int)prevPos.m_segment], currentFrameIndex - num5, out vehicleLightState, out pedestrianLightState, out flag5, out pedestrians); if (!flag5 && num6 >= 196u) { flag5 = true; RoadBaseAI.SetTrafficLightState(num4, ref instance.m_segments.m_buffer[(int)prevPos.m_segment], currentFrameIndex - num5, vehicleLightState, pedestrianLightState, flag5, pedestrians); } switch (vehicleLightState) { case RoadBaseAI.TrafficLightState.RedToGreen: if (num6 < 60u) { maxSpeed = 0f; return; } break; case RoadBaseAI.TrafficLightState.Red: maxSpeed = 0f; return; case RoadBaseAI.TrafficLightState.GreenToRed: if (num6 >= 30u) { maxSpeed = 0f; return; } break; } } } } NetInfo info = instance.m_segments.m_buffer[(int)position.m_segment].Info; if (info.m_lanes != null && info.m_lanes.Length > (int)position.m_lane) { //maxSpeed = this.CalculateTargetSpeed(vehicleID, ref vehicleData, info.m_lanes[(int)position.m_lane].m_speedLimit, instance.m_lanes.m_buffer[(int)((UIntPtr)laneID)].m_curve); maxSpeed = CalculateTargetSpeed(vehicleID, ref vehicleData, SpeedLimitManager.GetLockFreeGameSpeedLimit(position.m_segment, position.m_lane, laneID, info.m_lanes[position.m_lane]), instance.m_lanes.m_buffer[laneID].m_curve); } else { maxSpeed = this.CalculateTargetSpeed(vehicleID, ref vehicleData, 1f, 0f); } }
/// <summary> /// Displays lane ids over lanes /// </summary> private void _guiLanes(ushort segmentId, ref NetSegment segment, ref NetInfo segmentInfo) { GUIStyle _counterStyle = new GUIStyle(); Vector3 centerPos = segment.m_bounds.center; var screenPos = Camera.main.WorldToScreenPoint(centerPos); screenPos.y = Screen.height - screenPos.y - 200; if (screenPos.z < 0) { return; } var camPos = Singleton <SimulationManager> .instance.m_simulationView.m_position; var diff = centerPos - camPos; if (diff.magnitude > DebugCloseLod) { return; // do not draw if too distant } var zoom = 1.0f / diff.magnitude * 150f; _counterStyle.fontSize = (int)(11f * zoom); _counterStyle.normal.textColor = new Color(1f, 1f, 0f); uint totalDensity = 0u; uint curLaneId = segment.m_lanes; for (int i = 0; i < segmentInfo.m_lanes.Length; ++i) { if (curLaneId == 0) { break; } if (CustomRoadAI.currentLaneDensities[segmentId] != null && i < CustomRoadAI.currentLaneDensities[segmentId].Length) { totalDensity += CustomRoadAI.currentLaneDensities[segmentId][i]; } curLaneId = Singleton <NetManager> .instance.m_lanes.m_buffer[curLaneId].m_nextLane; } curLaneId = segment.m_lanes; String labelStr = ""; for (int i = 0; i < segmentInfo.m_lanes.Length; ++i) { if (curLaneId == 0) { break; } NetInfo.Lane laneInfo = segmentInfo.m_lanes[i]; labelStr += "Lane idx " + i + ", id " + curLaneId; #if DEBUG labelStr += ", flags: " + ((NetLane.Flags)Singleton <NetManager> .instance.m_lanes.m_buffer[curLaneId].m_flags).ToString() + ", limit: " + SpeedLimitManager.GetCustomSpeedLimit(curLaneId) + " km/h, dir: " + laneInfo.m_direction + ", final: " + laneInfo.m_finalDirection + ", pos: " + String.Format("{0:0.##}", laneInfo.m_position) + ", sim. idx: " + laneInfo.m_similarLaneIndex + " for " + laneInfo.m_vehicleType + "/" + laneInfo.m_laneType; #endif /*if (CustomRoadAI.InStartupPhase) * labelStr += ", in start-up phase"; * else*/ labelStr += ", avg. speed: " + (CustomRoadAI.laneMeanSpeeds[segmentId] != null && i < CustomRoadAI.laneMeanSpeeds[segmentId].Length ? "" + CustomRoadAI.laneMeanSpeeds[segmentId][i] : "?") + " %"; labelStr += ", rel. density: " + (CustomRoadAI.laneMeanRelDensities[segmentId] != null && i < CustomRoadAI.laneMeanRelDensities[segmentId].Length ? "" + CustomRoadAI.laneMeanRelDensities[segmentId][i] : "?") + " %"; #if ABSDENSITY labelStr += ", abs. density: " + (CustomRoadAI.laneMeanAbsDensities[segmentId] != null && i < CustomRoadAI.laneMeanAbsDensities[segmentId].Length ? "" + CustomRoadAI.laneMeanAbsDensities[segmentId][i] : "?") + " %"; #endif #if DEBUG labelStr += " (" + (CustomRoadAI.currentLaneDensities[segmentId] != null && i < CustomRoadAI.currentLaneDensities[segmentId].Length ? "" + CustomRoadAI.currentLaneDensities[segmentId][i] : "?") + "/" + totalDensity + ")"; #endif labelStr += "\n"; curLaneId = Singleton <NetManager> .instance.m_lanes.m_buffer[curLaneId].m_nextLane; } Vector2 dim = _counterStyle.CalcSize(new GUIContent(labelStr)); Rect labelRect = new Rect(screenPos.x - dim.x / 2f, screenPos.y, dim.x, dim.y); GUI.Label(labelRect, labelStr, _counterStyle); }
private void ShowSigns(bool viewOnly) { NetManager netManager = Singleton <NetManager> .instance; SpeedLimitManager speedLimitManager = SpeedLimitManager.Instance; var currentCamera = new CameraTransformValue(Camera.main); Transform currentCameraTransform = Camera.main.transform; Vector3 camPos = currentCameraTransform.position; if (!LastCachedCamera.Equals(currentCamera)) { // cache visible segments LastCachedCamera = currentCamera; CachedVisibleSegmentIds.Clear(); const float MAX_DIST = TrafficManagerTool.MAX_OVERLAY_DISTANCE * TrafficManagerTool.MAX_OVERLAY_DISTANCE; for (uint segmentId = 1; segmentId < NetManager.MAX_SEGMENT_COUNT; ++segmentId) { if (!Constants.ServiceFactory.NetService.IsSegmentValid((ushort)segmentId)) { continue; } // if ((netManager.m_segments.m_buffer[segmentId].m_flags & // NetSegment.Flags.Untouchable) != NetSegment.Flags.None) continue; Vector3 distToCamera = netManager.m_segments.m_buffer[segmentId].m_bounds.center - camPos; if (distToCamera.sqrMagnitude > MAX_DIST) { continue; // do not draw if too distant } bool visible = MainTool.WorldToScreenPoint( netManager.m_segments.m_buffer[segmentId].m_bounds.center, out Vector3 _); if (!visible) { continue; } if (!speedLimitManager.MayHaveCustomSpeedLimits( (ushort)segmentId, ref netManager.m_segments.m_buffer[segmentId])) { continue; } CachedVisibleSegmentIds.Add((ushort)segmentId); } // end for all segments } for (int segmentIdIndex = CachedVisibleSegmentIds.Size - 1; segmentIdIndex >= 0; segmentIdIndex--) { ushort segmentId = CachedVisibleSegmentIds.Values[segmentIdIndex]; // draw speed limits if ((MainTool.GetToolMode() == ToolMode.VehicleRestrictions) && (segmentId == SelectedSegmentId)) { continue; } // no speed limit overlay on selected segment when in vehicle restrictions mode DrawSpeedLimitHandles( segmentId, ref netManager.m_segments.m_buffer[segmentId], viewOnly, ref camPos); } }
/// <summary> /// Displays vehicle ids over vehicles /// </summary> private void _guiVehicles() { GUIStyle _counterStyle = new GUIStyle(); Array16 <Vehicle> vehicles = Singleton <VehicleManager> .instance.m_vehicles; LaneConnectionManager connManager = LaneConnectionManager.Instance(); SimulationManager simManager = Singleton <SimulationManager> .instance; NetManager netManager = Singleton <NetManager> .instance; VehicleStateManager vehStateManager = VehicleStateManager.Instance(); for (int i = 1; i < vehicles.m_size; ++i) { Vehicle vehicle = vehicles.m_buffer[i]; if (vehicle.m_flags == 0) // node is unused { continue; } Vector3 vehPos = vehicle.GetLastFramePosition(); var screenPos = Camera.main.WorldToScreenPoint(vehPos); screenPos.y = Screen.height - screenPos.y; if (screenPos.z < 0) { continue; } var camPos = simManager.m_simulationView.m_position; var diff = vehPos - camPos; if (diff.magnitude > DebugCloseLod) { continue; // do not draw if too distant } var zoom = 1.0f / diff.magnitude * 150f; _counterStyle.fontSize = (int)(10f * zoom); _counterStyle.normal.textColor = new Color(1f, 1f, 1f); //_counterStyle.normal.background = MakeTex(1, 1, new Color(0f, 0f, 0f, 0.4f)); VehicleState vState = vehStateManager._GetVehicleState((ushort)i); PathUnit.Position?curPos = vState?.GetCurrentPathPosition(ref vehicle); PathUnit.Position?nextPos = vState?.GetNextPathPosition(ref vehicle); bool? startNode = vState?.CurrentSegmentEnd?.StartNode; ushort?segmentId = vState?.CurrentSegmentEnd?.SegmentId; ushort?transitNodeId = vState?.CurrentSegmentEnd?.NodeId; /*float distanceToTransitNode = Single.NaN; * float timeToTransitNode = Single.NaN;*/ ushort vehSpeed = SpeedLimitManager.Instance().VehicleToCustomSpeed(vehicle.GetLastFrameVelocity().magnitude); Vector3?targetPos = null; if (transitNodeId != null) { targetPos = netManager.m_nodes.m_buffer[(ushort)transitNodeId].m_position; } /*if (transitNodeId != null && segmentId != null && startNode != null && curPos != null) { * bool outgoing = false; * connManager.GetLaneEndPoint((ushort)segmentId, (bool)startNode, ((PathUnit.Position)curPos).m_lane, null, null, out outgoing, out targetPos); * }*/ float distanceToTransitNode = Single.NaN; if (targetPos != null) { distanceToTransitNode = ((Vector3)targetPos - vehPos).magnitude; /*if (vehSpeed > 0) * timeToTransitNode = distanceToTransitNode / vehSpeed; * else * timeToTransitNode = Single.PositiveInfinity;*/ } String labelStr = "V #" + i + " is a " + (vState.Valid ? "valid" : "invalid") + " " + vState.VehicleType + " @ ~" + vehSpeed + " km/h (" + vState.JunctionTransitState + ") dist: " + distanceToTransitNode; #if USEPATHWAITCOUNTER labelStr += ", pwc: " + vState.PathWaitCounter + ", seg. " + vState.CurrentSegmentEnd?.SegmentId; #endif //String labelStr = "Veh. " + i + " @ " + String.Format("{0:0.##}", vehSpeed) + "/" + (vState != null ? vState.CurrentMaxSpeed.ToString() : "-") + " (" + (vState != null ? vState.VehicleType.ToString() : "-") + ", valid? " + (vState != null ? vState.Valid.ToString() : "-") + ")" + ", len: " + (vState != null ? vState.TotalLength.ToString() : "-") + ", state: " + (vState != null ? vState.JunctionTransitState.ToString() : "-"); #if PATHRECALC labelStr += ", recalc: " + (vState != null ? vState.LastPathRecalculation.ToString() : "-"); #endif //labelStr += "\npos: " + curPos?.m_segment + "(" + curPos?.m_lane + ")->" + nextPos?.m_segment + "(" + nextPos?.m_lane + ")" /* + ", dist: " + distanceToTransitNode + ", time: " + timeToTransitNode*/ + ", last update: " + vState?.LastPositionUpdate; Vector2 dim = _counterStyle.CalcSize(new GUIContent(labelStr)); Rect labelRect = new Rect(screenPos.x - dim.x / 2f, screenPos.y - dim.y - 50f, dim.x, dim.y); GUI.Box(labelRect, labelStr, _counterStyle); //_counterStyle.normal.background = null; } }