Skip to content
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
6bf0b7d
Boosted lane connector hovering raycast.
kianzarrin Jan 26, 2020
546941f
minor fix.
kianzarrin Jan 26, 2020
8c27932
kianzarrin Jan 26, 2020
625d805
merged with master
kianzarrin Jan 26, 2020
7fd4eda
fixed merge
kianzarrin Jan 26, 2020
c0e2652
use hit pos instead of mouse pos
kianzarrin Jan 29, 2020
3f67fe3
fixed bridge issue
kianzarrin Jan 29, 2020
db22f6f
reverted changes in subtool.cs and trafficmanagertool.cs
kianzarrin Jan 31, 2020
1961a84
polished a bit more.
kianzarrin Jan 31, 2020
e71b59c
removed debug code
kianzarrin Jan 31, 2020
175cecd
polished
kianzarrin Jan 31, 2020
17e8bb8
use inaccurate hitpos only in case of overpassing road planes.
kianzarrin Jan 31, 2020
7416c50
polished and fine tuened. fixed height calculation bug.
kianzarrin Jan 31, 2020
17b8ccd
fixed hitH satisfactorily.
kianzarrin Jan 31, 2020
c66fa13
cache hover results
kianzarrin Jan 31, 2020
cd2940b
fixed caching issue.
kianzarrin Jan 31, 2020
da2fdc3
fixed spacing.
kianzarrin Feb 2, 2020
eabc5b9
spelling error
kianzarrin Feb 2, 2020
f9d3a18
merged with master
kianzarrin Feb 3, 2020
ab56adc
addded check to avoid selecting multiple lanes.
kianzarrin Feb 3, 2020
4272865
fixed and improved cache.
kianzarrin Feb 3, 2020
0378c50
encapsulated node lane marker rendering and raycasting
kianzarrin Feb 5, 2020
3dfd9ce
lane curve follows mouse position.
kianzarrin Feb 5, 2020
18da5f9
fixed drawlane for underground.
kianzarrin Feb 5, 2020
dce99b7
extended render bezier to create sheath overlay.
kianzarrin Feb 6, 2020
88ae11c
lane curve snaps to hovered maker.
kianzarrin Feb 6, 2020
23076c4
removed redundant anti flickering code.
kianzarrin Feb 8, 2020
5dc89b6
fixed train station source/target colors.
kianzarrin Feb 8, 2020
b1773e5
lane cureves from selected markers are on top:
kianzarrin Feb 8, 2020
f926fb8
Merge remote-tracking branch 'main/master' into 625-boost-lane-hover-…
kianzarrin Feb 8, 2020
6cbad0a
Polish
kianzarrin Feb 8, 2020
eebbb65
fixed problem with for loop level causing multiple lane curves to be …
kianzarrin Feb 9, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion TLM/TLM/UI/SubTool.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
namespace TrafficManager.UI {
using ColossalFramework.UI;
using JetBrains.Annotations;
using TrafficManager.UI.Textures;
using Textures;
using UnityEngine;

public abstract class SubTool {
Expand Down
1 change: 0 additions & 1 deletion TLM/TLM/UI/SubTools/LaneArrowTool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,6 @@ protected override ushort HoveredNodeId {
}
return base.HoveredNodeId;
}
set => base.HoveredNodeId = value;
}

/// <summary>
Expand Down
149 changes: 114 additions & 35 deletions TLM/TLM/UI/SubTools/LaneConnectorTool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ namespace TrafficManager.UI.SubTools {
using TrafficManager.State;
using TrafficManager.Util.Caching;
using UnityEngine;
using static Util.Shortcuts;

public class LaneConnectorTool : SubTool {
private enum MarkerSelectionMode {
Expand Down Expand Up @@ -54,19 +55,94 @@ private class NodeLaneMarker {
internal ushort SegmentId;
internal ushort NodeId;
internal bool StartNode;
internal Vector3 Position;
internal Vector3 SecondaryPosition;
internal Vector3 Position; /// projected on train
internal Vector3 SecondaryPosition; /// original height.
internal bool IsSource;
internal bool IsTarget;
internal uint LaneId;
internal int InnerSimilarLaneIndex;
internal int SegmentIndex;
internal float Radius = 1f;
internal readonly float Radius = 1f;
internal Color Color;
internal readonly List<NodeLaneMarker> ConnectedMarkers = new List<NodeLaneMarker>();
internal SegmentLaneMarker segmentLaneMarker;
[UsedImplicitly]
internal NetInfo.LaneType LaneType;
internal VehicleInfo.VehicleType VehicleType;

}

// code revived from the old Traffic++ mod : https://github.com/joaofarias/csl-traffic/blob/a4c5609e030c5bde91811796b9836aad60ddde20/CSL-Traffic/Tools/RoadCustomizerTool.cs
private class SegmentLaneMarker {
internal uint laneID;
internal int laneIndex;
internal Bezier3 bezier;

private Bounds[] bounds;
private float prev_H;
internal bool IntersectRay(Ray ray, float hitH) {
if (hitH != prev_H || bounds == null)
CalculateBounds(hitH);
prev_H = hitH;
foreach (Bounds bounds in bounds) {
if (bounds.IntersectRay(ray))
return true;
}

return false;
}

void CalculateBounds(float hitH) {
// if marker is projected on another road plane then modify its height
Bezier3 bezier0 = bezier;
//float minH = Mathf.Min(bezier0.a.y, bezier0.d.y);
float maxH = Mathf.Max(bezier0.a.y, bezier0.d.y);
if (hitH > maxH + 2.5f) {
bezier0.a.y = bezier0.b.y = bezier0.c.y = bezier0.d.y = hitH;
}

float angle = Vector3.Angle(bezier0.a, bezier0.b);
if (Mathf.Approximately(angle, 0f) || Mathf.Approximately(angle, 180f)) {
angle = Vector3.Angle(bezier0.b, bezier0.c);
if (Mathf.Approximately(angle, 0f) || Mathf.Approximately(angle, 180f)) {
angle = Vector3.Angle(bezier0.c, bezier0.d);
if (Mathf.Approximately(angle, 0f) || Mathf.Approximately(angle, 180f)) {
// linear bezier
Bounds bounds = bezier0.GetBounds();
bounds.Expand(0.25f);
this.bounds = new Bounds[] { bounds };
return;
}
}
}

// split bezier in 10 parts to correctly raycast curves
int n = 10;
bounds = new Bounds[n];
float size = 1f / n;
for (int i = 0; i < n; i++) {
Bezier3 bezier = bezier0.Cut(i * size, (i + 1) * size);
Bounds bounds = bezier.GetBounds();
bounds.Expand(0.9f);
this.bounds[i] = bounds;
}
}

internal void RenderOverlay(RenderManager.CameraInfo cameraInfo, Color color, bool enlarge=false) {
float minH = Mathf.Min(bezier.a.y, bezier.d.y);
float maxH = Mathf.Max(bezier.a.y, bezier.d.y);
RenderManager.instance.OverlayEffect.DrawBezier(
cameraInfo,
color,
bezier,
enlarge ? 1.5f : 1f,
0,
0,
minH - 100f,
maxH+ 100f,
true,
false);
}
}

public LaneConnectorTool(TrafficManagerTool mainTool)
Expand Down Expand Up @@ -199,10 +275,6 @@ private void ShowOverlay(bool viewOnly, RenderManager.CameraInfo cameraInfo) {
continue;
}

// bounds.center = laneMarker.position;
// bounds.IntersectRay(mouseRay);
bool markerIsHovered = IsLaneMarkerHovered(laneMarker, ref mouseRay);

// draw source marker in source selection mode,
// draw target marker (if segment turning angles are within bounds) and
// selected source marker in target selection mode
Expand All @@ -223,27 +295,29 @@ bool drawMarker
|| (laneMarker == selectedMarker)));

// highlight hovered marker and selected marker
bool highlightMarker =
drawMarker && ((laneMarker == selectedMarker) || markerIsHovered);

if (drawMarker) {
laneMarker.Radius = highlightMarker ? 2f : 1f;
} else {
markerIsHovered = false;
}

if (markerIsHovered) {
hoveredMarker = laneMarker;
}

var circleColor = laneMarker.IsTarget ? Color.white : laneMarker.Color;
float hitH = TrafficManagerTool.GetAccurateHitHeight();
bool markerIsHovered = IsLaneMarkerHovered(laneMarker, ref mouseRay, hitH);

if (!markerIsHovered &&
laneMarker.segmentLaneMarker.IntersectRay(mouseRay, hitH)) {
//only draw lane when segmentLaneMarker is hovered but laneMarker is not hovered.
laneMarker.segmentLaneMarker.RenderOverlay(cameraInfo, Color.white);
markerIsHovered = true;
}

if (markerIsHovered) {
hoveredMarker = laneMarker;
}

if (drawMarker) {
bool highlightMarker = laneMarker == selectedMarker || markerIsHovered;
float magnify = highlightMarker ? 2f : 1f;
var circleColor = laneMarker.IsTarget ? Color.white : laneMarker.Color;
RenderManager.instance.OverlayEffect.DrawCircle(
cameraInfo,
circleColor,
laneMarker.Position,
laneMarker.Radius,
laneMarker.Radius * magnify,
laneMarker.Position.y - 100f, // through all the geometry -100..100
laneMarker.Position.y + 100f,
false,
Expand All @@ -252,7 +326,7 @@ bool drawMarker
cameraInfo,
Color.black,
laneMarker.Position,
laneMarker.Radius * 0.75f, // inner black
laneMarker.Radius * 0.75f * magnify, // inner black
laneMarker.Position.y - 100f, // through all the geometry -100..100
laneMarker.Position.y + 100f,
false,
Expand All @@ -262,17 +336,14 @@ bool drawMarker
} // end for node in all nodes
}

private bool IsLaneMarkerHovered(NodeLaneMarker laneMarker, ref Ray mouseRay) {
Bounds bounds = new Bounds(Vector3.zero, Vector3.one) {
center = laneMarker.Position
};

if (bounds.IntersectRay(mouseRay)) {
return true;
private bool IsLaneMarkerHovered(NodeLaneMarker laneMarker, ref Ray mouseRay, float hitH) {
Vector3 pos = laneMarker.SecondaryPosition;
if (hitH - pos.y > 2.5f) {
// if marker is projected on road plane above then modify its height
pos.y = hitH;
}

bounds = new Bounds(Vector3.zero, Vector3.one) {
center = laneMarker.SecondaryPosition
Bounds bounds = new Bounds(Vector3.zero, Vector3.one * laneMarker.Radius) {
center = pos,
};
return bounds.IntersectRay(mouseRay);
}
Expand Down Expand Up @@ -711,6 +782,13 @@ Color32 nodeMarkerColor
? COLOR_CHOICES[nodeMarkerColorIndex % COLOR_CHOICES.Length]
: default; // or black (not used while rendering)

NetLane lane = NetManager.instance.m_lanes.m_buffer[laneId];
SegmentLaneMarker segmentLaneMarker = new SegmentLaneMarker {
bezier = lane.m_bezier,
laneID = laneId,
laneIndex = laneIndex,
};

nodeMarkers.Add(
new NodeLaneMarker {
SegmentId = segmentId,
Expand All @@ -729,7 +807,8 @@ Color32 nodeMarkerColor
? laneInfo.m_similarLaneIndex
: laneInfo.m_similarLaneCount -
laneInfo.m_similarLaneIndex - 1,
SegmentIndex = i
SegmentIndex = i,
segmentLaneMarker = segmentLaneMarker,
});

if (isSource) {
Expand Down Expand Up @@ -923,4 +1002,4 @@ private static readonly Color32[] COLOR_CHOICES
new Color32(99, 75, 85, 255)
};
}
}
}
66 changes: 49 additions & 17 deletions TLM/TLM/UI/TrafficManagerTool.cs
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
namespace TrafficManager.UI {
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using API.Manager;
using API.Traffic.Data;
using API.Traffic.Enums;
using API.Util;
using ColossalFramework;
using ColossalFramework.Math;
using ColossalFramework.UI;
using ColossalFramework;
using CSUtil.Commons;
using JetBrains.Annotations;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System;
using TrafficManager.API.Manager;
using TrafficManager.API.Traffic.Data;
using TrafficManager.API.Traffic.Enums;
using TrafficManager.API.Util;
using TrafficManager.Manager.Impl;
using TrafficManager.State.ConfigData;
using TrafficManager.State;
using TrafficManager.UI.MainMenu;
using TrafficManager.UI.SubTools.SpeedLimits;
using TrafficManager.UI.SubTools;
using TrafficManager.Util;
using Manager.Impl;
using State;
using State.ConfigData;
using MainMenu;
using SubTools;
using SubTools.SpeedLimits;
using Util;
using UnityEngine;

[UsedImplicitly]
Expand All @@ -31,6 +31,7 @@ public class TrafficManagerTool

internal static ushort HoveredNodeId;
internal static ushort HoveredSegmentId;
internal static Vector3 HitPos;

private static bool _mouseClickProcessed;

Expand Down Expand Up @@ -822,9 +823,18 @@ public bool DoRayCast(RaycastInput input, out RaycastOutput output) {
return RayCast(input, out output);
}

private bool DetermineHoveredElements() {
private static Vector3 prev_mousePosition;
private bool DetermineHoveredElements() {
if(prev_mousePosition == m_mousePosition) {
// if mouse ray is not changing use cached results.
// the assumption is that its practically impossible to change mouse ray
// without changing m_mousePosition.
return HoveredNodeId != 0 || HoveredSegmentId != 0;
}

HoveredSegmentId = 0;
HoveredNodeId = 0;
HitPos = Vector3.zero;

bool mouseRayValid = !UIView.IsInsideUI() && Cursor.visible &&
(_activeSubTool == null || !_activeSubTool.IsCursorInPanel());
Expand Down Expand Up @@ -918,6 +928,10 @@ private bool DetermineHoveredElements() {
}
}
}

if(HoveredSegmentId != 0) {
HitPos = segmentOutput.m_hitPos;
}

if (HoveredNodeId <= 0 && HoveredSegmentId > 0) {
// alternative way to get a node hit: check distance to start and end nodes
Expand Down Expand Up @@ -988,6 +1002,24 @@ private static float GetAngle(Vector3 v1, Vector3 v2) {
return ret;
}

private static float prev_H = 0f;
private static float prev_H_Fixed;
internal static float GetAccurateHitHeight() {
// cache result.
if (HitPos.y == prev_H) {
return prev_H_Fixed;
}
prev_H = HitPos.y;

if (Shortcuts.GetSeg(HoveredSegmentId).GetClosestLanePosition(
HitPos, NetInfo.LaneType.All, VehicleInfo.VehicleType.All,
out Vector3 pos, out uint laneID, out int laneIndex, out float laneOffset)) {

return prev_H_Fixed = pos.y;
}
return prev_H_Fixed = HitPos.y + 0.5f;
}


/// <summary>
/// Displays lane ids over lanes
Expand Down