Skip to content

Commit

Permalink
Apply Shift+Click speed limit to entire roundabout (#920)
Browse files Browse the repository at this point in the history
#869: Apply Shift+Click speed limit to entire roundabout

(cherry picked from commit ec3227d)
  • Loading branch information
krzychu124 committed Nov 14, 2020
1 parent eb34bdd commit 37c5d02
Show file tree
Hide file tree
Showing 2 changed files with 130 additions and 50 deletions.
58 changes: 34 additions & 24 deletions TLM/TLM/Manager/Impl/ExtSegmentEndManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,10 @@ public class ExtSegmentEndManager
: AbstractCustomManager,
IExtSegmentEndManager
{
public static ExtSegmentEndManager Instance { get; }

static ExtSegmentEndManager() {
Instance = new ExtSegmentEndManager();
}

/// <summary>
/// All additional data for segment ends
/// </summary>
public ExtSegmentEnd[] ExtSegmentEnds { get; }

private ExtSegmentEndManager() {
ExtSegmentEnds = new ExtSegmentEnd[NetManager.MAX_SEGMENT_COUNT * 2];
for (uint i = 0; i < NetManager.MAX_SEGMENT_COUNT; ++i) {
Expand All @@ -31,6 +24,13 @@ private ExtSegmentEndManager() {
}
}

public static ExtSegmentEndManager Instance { get; }

/// <summary>
/// All additional data for segment ends
/// </summary>
public ExtSegmentEnd[] ExtSegmentEnds { get; }

#if DEBUG
public string GenerateVehicleChainDebugInfo(ushort segmentId, bool startNode) {
int index = GetIndex(segmentId, startNode);
Expand Down Expand Up @@ -298,23 +298,33 @@ private void Recalculate(ref ExtSegmentEnd segEnd) {
public void CalculateCorners(ushort segmentId, bool startNode) {
if (!Shortcuts.netService.IsSegmentValid(segmentId))
return;
ref ExtSegmentEnd segEnd = ref ExtSegmentEnds[GetIndex(segmentId, startNode)];
segmentId.ToSegment().CalculateCorner(
segmentID: segmentId,
heightOffset: true,
start: startNode,
leftSide: false,
cornerPos: out segEnd.RightCorner,
cornerDirection: out segEnd.RightCornerDir,
smooth: out _);
segmentId.ToSegment().CalculateCorner(
segmentID: segmentId,
heightOffset: true,
start: startNode,
leftSide: true,
cornerPos: out segEnd.LeftCorner,
cornerDirection: out segEnd.LeftCornerDir,
smooth: out _);
if (!segmentId.ToSegment().Info) {
Log.Warning($"segment {segmentId} has null info");
return;
}

try {
ref ExtSegmentEnd segEnd = ref ExtSegmentEnds[GetIndex(segmentId, startNode)];
segmentId.ToSegment().CalculateCorner(
segmentID: segmentId,
heightOffset: true,
start: startNode,
leftSide: false,
cornerPos: out segEnd.RightCorner,
cornerDirection: out segEnd.RightCornerDir,
smooth: out _);
segmentId.ToSegment().CalculateCorner(
segmentID: segmentId,
heightOffset: true,
start: startNode,
leftSide: true,
cornerPos: out segEnd.LeftCorner,
cornerDirection: out segEnd.LeftCornerDir,
smooth: out _);
} catch (Exception e) {
Log.Error($"failed calculating corner for segment:{segmentId}, info={segmentId.ToSegment().Info}\n"
+ e.Message);
}
}

private void CalculateIncomingOutgoing(ushort segmentId,
Expand Down
122 changes: 96 additions & 26 deletions TLM/TLM/UI/SubTools/SpeedLimits/SpeedLimitsTool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public const int
/// 0 = no limit
/// null = default
/// </summary>
private SpeedValue ?currentPaletteSpeedLimit = new SpeedValue(-1f);
private SpeedValue? currentPaletteSpeedLimit = new SpeedValue(-1f);

private readonly Dictionary<ushort, Dictionary<NetInfo.Direction, Vector3>> segmentCenterByDir =
new Dictionary<ushort, Dictionary<NetInfo.Direction, Vector3>>();
Expand Down Expand Up @@ -96,12 +96,21 @@ private struct RenderData {
private RenderData renderData_;

public SpeedLimitsTool(TrafficManagerTool mainTool)
: base(mainTool)
{
: base(mainTool) {
CachedVisibleSegmentIds = new GenericArrayCache<ushort>(NetManager.MAX_SEGMENT_COUNT);
LastCachedCamera = new CameraTransformValue();
}

internal static void SetSpeedLimit(LanePos lane, SpeedValue? speed) {
ushort segmentId = lane.laneId.ToLane().m_segment;
SpeedLimitManager.Instance.SetSpeedLimit(
segmentId: segmentId,
laneIndex: lane.laneIndex,
laneInfo: segmentId.ToSegment().Info.m_lanes[lane.laneIndex],
laneId: lane.laneId,
speedLimit: speed?.GameUnits);
}

public override bool IsCursorInPanel() {
return base.IsCursorInPanel() || cursorInSecondaryPanel;
}
Expand Down Expand Up @@ -156,17 +165,21 @@ public override void OnToolGUI(Event e) {
private void RenderLaneOverlay(RenderManager.CameraInfo cameraInfo, uint laneId) {
var marker = new SegmentLaneMarker(laneBuffer[laneId].m_bezier);
bool pressed = Input.GetMouseButton(0);
Color color = MainTool.GetToolColor(pressed,false);
Color color = MainTool.GetToolColor(pressed, false);
if (!ShowLimitsPerLane) {
marker.Size = 3f; // lump the lanes together.
}
marker.RenderOverlay(cameraInfo, color, pressed);
}

/// <summary>
/// Renders all lanes with the given <paramref name="finalDirection"/>
/// if NetInfo.Direction.None, all lanes are rendered.
/// </summary>
private int RenderSegmentSideOverlay(
RenderManager.CameraInfo cameraInfo,
ushort segmentId,
NetInfo.Direction finalDirection) {
NetInfo.Direction finalDirection = NetInfo.Direction.None) {
int count = 0;
bool pressed = Input.GetMouseButton(0);
Color color = MainTool.GetToolColor(pressed, false);
Expand All @@ -180,7 +193,7 @@ private int RenderSegmentSideOverlay(
byte laneIndex) => {
bool render = (laneInfo.m_laneType & SpeedLimitManager.LANE_TYPES) != 0;
render &= (laneInfo.m_vehicleType & SpeedLimitManager.VEHICLE_TYPES) != 0;
render &= laneInfo.m_finalDirection == finalDirection;
render &= laneInfo.m_finalDirection == finalDirection || finalDirection == NetInfo.Direction.None;
if (render) {
RenderLaneOverlay(cameraInfo, laneId);
count++;
Expand All @@ -193,13 +206,18 @@ private int RenderSegmentSideOverlay(
private void RenderLanes(RenderManager.CameraInfo cameraInfo) {
if (!MultiSegmentMode) {
RenderLaneOverlay(cameraInfo, renderData_.LaneId);
} else if (RoundaboutMassEdit.Instance.TraverseLoop(renderData_.SegmentId, out var segmentList)) {
var lanes = FollowRoundaboutLane(segmentList, renderData_.SegmentId, renderData_.SortedLaneIndex);
foreach (var lane in lanes)
RenderLaneOverlay(cameraInfo, lane.laneId);
} else {
bool LaneVisitorFun(SegmentLaneTraverser.SegmentLaneVisitData data) {
if (data.SortedLaneIndex == renderData_.SortedLaneIndex) {
RenderLaneOverlay(cameraInfo, data.CurLanePos.laneId);
}
return true;
}
{
SegmentLaneTraverser.Traverse(
renderData_.SegmentId,
SegmentTraverser.TraverseDirection.AnyDirection,
Expand All @@ -211,10 +229,53 @@ bool LaneVisitorFun(SegmentLaneTraverser.SegmentLaneVisitData data) {
LaneVisitorFun);
}
}
}

/// <summary>
/// iterates through the given roundabout <paramref name="segmentList"/> returning an enumeration
/// of all lanes with a matching <paramref name="sortedLaneIndex"/> based on <paramref name="segmentId0"/>
/// </summary>
/// <param name="segmentList">input list of roundabout segments (must be oneway, and in the same direction).</param>
/// <param name="segmentId0">The segment to match lane agaisnt</param>
/// <param name="sortedLaneIndex"></param>
private IEnumerable<LanePos> FollowRoundaboutLane(List<ushort> segmentList, ushort segmentId0, int sortedLaneIndex) {
bool invert0 = segmentId0.ToSegment().m_flags.IsFlagSet(NetSegment.Flags.Invert);
int count0 = netService.GetSortedLanes(
segmentId: segmentId0,
segment: ref segmentId0.ToSegment(),
startNode: null,
laneTypeFilter: SpeedLimitManager.LANE_TYPES,
vehicleTypeFilter: SpeedLimitManager.VEHICLE_TYPES,
sort: false).Count;
foreach (ushort segmentId in segmentList) {
bool invert = segmentId.ToSegment().m_flags.IsFlagSet(NetSegment.Flags.Invert);
var lanes = netService.GetSortedLanes(
segmentId: segmentId,
segment: ref segmentId.ToSegment(),
startNode: null,
laneTypeFilter: SpeedLimitManager.LANE_TYPES,
vehicleTypeFilter: SpeedLimitManager.VEHICLE_TYPES,
reverse: invert != invert0,
sort: true);
int index = sortedLaneIndex;

// if lane count does not match, assume segments are connected from outer side of the roundabout.
if (invert0) {
int diff = lanes.Count - count0;
index += diff;
}
if (0 <= index && index < lanes.Count) {
yield return lanes[index];
}
} // foreach
}

private void RenderSegmentsSide(RenderManager.CameraInfo cameraInfo) {
if (!MultiSegmentMode) {
RenderSegmentSideOverlay(cameraInfo, renderData_.SegmentId, renderData_.FinalDirection);
} else if (RoundaboutMassEdit.Instance.TraverseLoop(renderData_.SegmentId, out var segmentList)) {
foreach (ushort segmentId in segmentList)
RenderSegmentSideOverlay(cameraInfo, segmentId);
} else {
SegmentTraverser.Traverse(
renderData_.SegmentId,
Expand Down Expand Up @@ -305,8 +366,7 @@ private void ShowSigns(bool viewOnly) {
bool hover = false;
for (int segmentIdIndex = CachedVisibleSegmentIds.Size - 1;
segmentIdIndex >= 0;
segmentIdIndex--)
{
segmentIdIndex--) {
ushort segmentId = CachedVisibleSegmentIds.Values[segmentIdIndex];
// draw speed limits
if ((MainTool.GetToolMode() == ToolMode.VehicleRestrictions) &&
Expand All @@ -315,7 +375,7 @@ private void ShowSigns(bool viewOnly) {
}

// no speed limit overlay on selected segment when in vehicle restrictions mode
hover|= DrawSpeedLimitHandles(
hover |= DrawSpeedLimitHandles(
segmentId,
ref netManager.m_segments.m_buffer[segmentId],
viewOnly,
Expand Down Expand Up @@ -485,8 +545,7 @@ private void GuiDefaultsWindow(int num) {
GUILayout.FlexibleSpace();

if (GUILayout.Button(Translation.SpeedLimits.Get("Button:Save"),
GUILayout.Width(70)))
{
GUILayout.Width(70))) {
SpeedLimitManager.Instance.FixCurrentSpeedLimits(info);
SpeedLimitManager.Instance.SetCustomNetInfoSpeedLimit(info, currentSpeedLimit.GameUnits);
}
Expand All @@ -512,8 +571,7 @@ private void UpdateRoadTex(NetInfo info) {
if (info != null) {
if ((info.m_Atlas != null) && (info.m_Atlas.material != null) &&
(info.m_Atlas.material.mainTexture != null) &&
info.m_Atlas.material.mainTexture is Texture2D mainTex)
{
info.m_Atlas.material.mainTexture is Texture2D mainTex) {
UITextureAtlas.SpriteInfo spriteInfo = info.m_Atlas[info.m_Thumbnail];

if ((spriteInfo != null) && (spriteInfo.texture != null) &&
Expand Down Expand Up @@ -569,7 +627,7 @@ private void GuiSpeedLimitsWindow(int num) {

foreach (SpeedValue speedLimit in allSpeedLimits) {
// Highlight palette item if it is very close to its float speed
if (currentPaletteSpeedLimit !=null &&
if (currentPaletteSpeedLimit != null &&
FloatUtil.NearlyEqual(
(float)currentPaletteSpeedLimit?.GameUnits,
speedLimit.GameUnits)) {
Expand All @@ -589,7 +647,7 @@ private void GuiSpeedLimitsWindow(int num) {
}
}
{
if (currentPaletteSpeedLimit == null ) {
if (currentPaletteSpeedLimit == null) {
GUI.color = Color.gray;
}
GuiSpeedLimitsWindow_AddClearButton();
Expand All @@ -606,7 +664,7 @@ private void GuiSpeedLimitsWindow(int num) {

if (GUILayout.Button(Translation.SpeedLimits.Get("Window.Title:Default speed limits"),
GUILayout.Width(200))) {
TrafficManagerTool.ShowAdvisor(this.GetType().Name + "_Defaults");
TrafficManagerTool.ShowAdvisor(GetType().Name + "_Defaults");
defaultsWindowVisible = true;
}

Expand Down Expand Up @@ -728,7 +786,7 @@ private bool DrawSpeedLimitHandles(ushort segmentId,

Vector3 center = segment.m_bounds.center;
NetManager netManager = Singleton<NetManager>.instance;
SpeedValue ?speedLimitToSet = viewOnly
SpeedValue? speedLimitToSet = viewOnly
? new SpeedValue(-1f)
: currentPaletteSpeedLimit;

Expand Down Expand Up @@ -812,8 +870,7 @@ private bool DrawSpeedLimitHandles(ushort segmentId,
if (!viewOnly
&& !onlyMonorailLanes
&& ((laneInfo.m_vehicleType & VehicleInfo.VehicleType.Monorail) !=
VehicleInfo.VehicleType.None))
{
VehicleInfo.VehicleType.None)) {
Texture2D tex1 = RoadUI.VehicleInfoSignTextures[
LegacyExtVehicleType.ToNew(ExtVehicleType.PassengerTrain)];
MainTool.DrawStaticSquareOverlayGridTexture(
Expand Down Expand Up @@ -845,8 +902,15 @@ private bool DrawSpeedLimitHandles(ushort segmentId,
speedLimitToSet?.GameUnits);

if (MultiSegmentMode) {
if (new RoundaboutMassEdit().TraverseLoop(segmentId, out var segmentList)) {
var lanes = FollowRoundaboutLane(segmentList, segmentId, sortedLaneIndex);
foreach (var lane in lanes) {
if (lane.laneId == laneId) // the speed limit for this lane has already been set.
continue;
SetSpeedLimit(lane, speedLimitToSet);
}
} else {
int slIndexCopy = sortedLaneIndex;

SegmentLaneTraverser.Traverse(
segmentId,
SegmentTraverser.TraverseDirection.AnyDirection,
Expand Down Expand Up @@ -883,6 +947,7 @@ private bool DrawSpeedLimitHandles(ushort segmentId,
});
}
}
}

++x;
}
Expand All @@ -897,7 +962,7 @@ private bool DrawSpeedLimitHandles(ushort segmentId,
GeometryUtil.CalculateSegmentCenterByDir(
segmentId,
segCenter,
speedLimitSignSize*TrafficManagerTool.MAX_ZOOM);
speedLimitSignSize * TrafficManagerTool.MAX_ZOOM);
}

foreach (KeyValuePair<NetInfo.Direction, Vector3> e in segCenter) {
Expand Down Expand Up @@ -941,6 +1006,13 @@ private bool DrawSpeedLimitHandles(ushort segmentId,
currentPaletteSpeedLimit?.GameUnits);

if (MultiSegmentMode) {
if (new RoundaboutMassEdit().TraverseLoop(segmentId, out var segmentList)) {
foreach (ushort segId in segmentList) {
SpeedLimitManager.Instance.SetSpeedLimit(
segId,
currentPaletteSpeedLimit?.GameUnits);
}
} else {
NetInfo.Direction normDir = e.Key;
if ((netManager.m_segments.m_buffer[segmentId].m_flags & NetSegment.Flags.Invert) != NetSegment.Flags.None) {
normDir = NetInfo.InvertDirection(normDir);
Expand All @@ -954,8 +1026,7 @@ private bool DrawSpeedLimitHandles(ushort segmentId,
SegmentTraverser.SegmentStopCriterion.Junction,
SpeedLimitManager.LANE_TYPES,
SpeedLimitManager.VEHICLE_TYPES,
data =>
{
data => {
if (data.SegVisitData.Initial) {
return true;
}
Expand All @@ -974,8 +1045,7 @@ private bool DrawSpeedLimitHandles(ushort segmentId,

if (((netManager.m_segments.m_buffer[otherSegmentId].m_flags
& NetSegment.Flags.Invert)
!= NetSegment.Flags.None) ^ reverse)
{
!= NetSegment.Flags.None) ^ reverse) {
otherNormDir = NetInfo.InvertDirection(otherNormDir);
}

Expand All @@ -988,6 +1058,7 @@ private bool DrawSpeedLimitHandles(ushort segmentId,

return true;
});
}
}
}

Expand Down Expand Up @@ -1124,6 +1195,5 @@ public static float GetVerticalTextureScale() {
? 1.25f
: 1.0f;
}

} // end class
}

0 comments on commit 37c5d02

Please sign in to comment.