void OnMouseDown() { MouseDown = true; _rb.Dragging = true; FPCam.transform.parent.GetComponent <BuilderCamController>().FreezeTilt = true; _startAngle = Bez.CtrlPts[Mrkr.Index].BankAngle * Mathf.Deg2Rad; Vector3 _bankDirection = AttachedTransform.forward * _startAngle; _untiltedPos = VectGeom.RotatePointAroundPivot(transform.position, OtherHandGizmo.position, -_bankDirection); Debug.Log("Start angle = " + Bez.CtrlPts[Mrkr.Index].BankAngle); Debug.Log("UntiltedPos = " + _untiltedPos); //Decide where to move the camera to... This is the nearest point perpendicular to the road and 30m from it Vector2 Perp2d = XSecCalculator.Perpndclr((AttachedTransform.GetComponent <RoadMarker>().Index - 1) * 20); Vector3 Perp = new Vector3(Perp2d.x, 0, Perp2d.y); Vector3 Dest1 = AttachedTransform.position + Perp * 30; Vector3 Dest2 = AttachedTransform.position - Perp * 30; if (Vector3.Distance(FPCam.transform.position, Dest1) < Vector3.Distance(FPCam.transform.position, Dest2)) { LerpEndPt = Dest1; } else { LerpEndPt = Dest2; } LerpStartRot = FPCam.transform.rotation; LerpStartPt = FPCam.transform.position; LerpStartTime = Time.time; Lerping = true; //Debug.Log("Lerp to " + LerpEndPt); }
public void DropMarker(RoadMarker Mrkr) { //Recalc the XSecs XSecCalculator.CalcXSecs(Mrkr.Index - 1, RoadWidth); //two before the marker XSecCalculator.CalcXSecs(Mrkr.Index, RoadWidth); //before the marker XSecCalculator.CalcXSecs(Mrkr.Index + 1, RoadWidth); //after the marker XSecCalculator.CalcXSecs(Mrkr.Index + 2, RoadWidth); //two after the marker //Add to the build queue if ((Mrkr.Index - 2 < Bez.CtrlPts.Count - 4) || (Rd.IsCircular)) { Rd.Sectns[Mrkr.Index - 2].CalcVisibleFenceVerts(); BuildQueue.Enqueue(Mrkr.Index - 2); } if ((Mrkr.Index - 1 < Bez.CtrlPts.Count - 4) || (Rd.IsCircular)) { Rd.Sectns[Mrkr.Index - 1].CalcVisibleFenceVerts(); BuildQueue.Enqueue(Mrkr.Index - 1); } if ((Mrkr.Index < Bez.CtrlPts.Count - 4) || (Rd.IsCircular)) { Rd.Sectns[Mrkr.Index].CalcVisibleFenceVerts(); BuildQueue.Enqueue(Mrkr.Index); } if ((Mrkr.Index + 1 < Bez.CtrlPts.Count - 4) || (Mrkr.Index + 1 <= Bez.CtrlPts.Count - 3 && Rd.IsCircular)) { Rd.Sectns[Mrkr.Index + 1].CalcVisibleFenceVerts(); BuildQueue.Enqueue(Mrkr.Index + 1); } //circular road penultimate CtrlPt needs to rebuild Section 1 if (Mrkr.Index + 1 == Bez.CtrlPts.Count - 3 && Rd.IsCircular) //doesnt work todo - needs fixing { Rd.Sectns[1].CalcVisibleFenceVerts(); BuildQueue.Enqueue(1); } Mrkr.DroppedPosition = Mrkr.transform.position; //Charge for this if they moved the marker more than 1 metre if (GameData.current.BezS.CtrlPts == null) { Rd.Sectns[Mrkr.Index].Chargeable = true; } else { if (GameData.current.BezS.CtrlPts[Mrkr.Index] == null) { Rd.Sectns[Mrkr.Index].Chargeable = true; } else { BezCtrlPtSerial bcps = GameData.current.BezS.CtrlPts[Mrkr.Index]; Vector3 _oldMarkerPos = bcps.Pos.V3; if (Vector3.Distance(Bez.CtrlPts[Mrkr.Index].Pos, _oldMarkerPos) > 1 || Mathf.Abs(bcps.BankAngle - Bez.CtrlPts[Mrkr.Index].BankAngle) > 10) { Rd.Sectns[Mrkr.Index].Chargeable = true; } } } }
public void DropLoopMarker(RoadMarker Mrkr) { //Now we look backwards then forwards til we find a non-hairpin and adjust all these int PrevNoHPin = Bez.CtrlPts.Count - 3; int NxtNoHPin = Mrkr.Index + 1; //Find the previous non-hairpin do { float A = Bez.Angle(PrevNoHPin); //Debug.Log("CtrlPt" + PrevNoHPin.ToString() + " Angle = " + A); if (Mathf.Abs(Bez.Angle(PrevNoHPin)) > 80) { PrevNoHPin++; break; } PrevNoHPin--; } while (true); //Find the next non-hairpin do { float A = Bez.Angle(NxtNoHPin); if (Mathf.Abs(Bez.Angle(NxtNoHPin)) > 80) { break; } NxtNoHPin++; } while (true); //Recalc the XSecs for (int CtrlPtId = 1; CtrlPtId <= NxtNoHPin; CtrlPtId++) //Between the non-hairpin markers { XSecCalculator.CalcXSecs(CtrlPtId, RoadWidth); } for (int CtrlPtId = PrevNoHPin + 1; CtrlPtId < Bez.CtrlPts.Count - 1; CtrlPtId++) //Between the non-hairpin markers { XSecCalculator.CalcXSecs(CtrlPtId, RoadWidth); } //Add to the build queue Rd.Sectns[Bez.CtrlPts.Count - 3].CalcVisibleFenceVerts(); BuildQueue.Enqueue(Bez.CtrlPts.Count - 3); Rd.Sectns[Mrkr.Index].CalcVisibleFenceVerts(); BuildQueue.Enqueue(Mrkr.Index); Rd.Sectns[Mrkr.Index + 1].CalcVisibleFenceVerts(); BuildQueue.Enqueue(Mrkr.Index + 1); Mrkr.DroppedPosition = Mrkr.transform.position; }
IEnumerator BuildSegments() { do { if (BuildIdx > 0) { for (Int32 P = Bez.CtrlPts[BuildIdx].SegStartIdx; P < Bez.CtrlPts[BuildIdx].SegStartIdx + Bez.CtrlPts[BuildIdx].SegCount; P++) { if (P < Bez.Path.Count - 1 || (Rd.IsCircular && P == Bez.Path.Count - 1)) { try { SegVerts Verts = XSecCalculator.SegmentVertices(P); RoadSegment seg = Road.Instance.Segments[P]; seg.BuildMeshes(Verts); seg.GetTerrainHeights(); seg.AdjustTerrain(); seg.AddMeshes(); seg.SetMaterial(); if (P == Rd.StartingLineSegIdx) { PlaceStartingLine(P); } if (P == Bez.CtrlPts[BuildIdx].SegStartIdx + Bez.CtrlPts[BuildIdx].SegCount - 1) { Road.Instance.Sectns[BuildIdx].DeleteFence(); Road.Instance.Sectns[BuildIdx].CreateFence(); } } catch (Exception e) { Debug.Log("BuildSegments Error BuildIndex = " + BuildIdx.ToString() + " P = " + P + " TotSegs = " + Road.Instance.Segments.Count + " Source = " + e.ToString()); } yield return(0); //TerrCtl.SetHeight(Bez.Path[P], Bez.Path[P - 1]); } } } if (BuildQueue.Count == 0) { BuildIdx = 0; } else { BuildIdx = BuildQueue.Dequeue(); } yield return(0); } while (true); }
public static void AdjustHairpin(BezierLine Bez, int CtlPtIdx) { return; if (CtlPtIdx < 2) { return; } //Adjusts the Road.Instance.XSecs around the controlpoint string Hand; Road Rd = Road.Instance; //SegAdj=new List<SegVerts>(); Vector2 PivotStart2d = Vector2.zero; Vector2 PivotEnd2d = Vector2.zero; int PrevCtrlPtSegId = Bez.CtrlPts[CtlPtIdx - 1].SegStartIdx; int PivotStartIdx = Bez.CtrlPts[CtlPtIdx].SegStartIdx; int PivotEndIdx = Bez.CtrlPts[CtlPtIdx].SegStartIdx; int NxtCtrlPtSegId = Bez.CtrlPts[CtlPtIdx + 1].SegStartIdx; if (CtlPtIdx < 2) { return; } //See if its a right or a left hand curve Vector2 Path2d = Convert2d(Rd.XSecs[PivotStartIdx].MidPt); Vector2 PrvPath2d = Convert2d(Rd.XSecs[PivotStartIdx - 1].MidPt); Vector2 NxtPath2d = Convert2d(Rd.XSecs[PivotStartIdx + 1].MidPt); Vector3 cross = Vector3.Cross(PrvPath2d - Path2d, NxtPath2d - Path2d); if (cross.z > 0) { Hand = "R"; } else { Hand = "L"; } //Right Edge if (Hand == "R") { //Catmull Rom up to the control pt int NumXSecsToAdjust = Bez.CtrlPts[CtlPtIdx - 1].SegCount / 2; int AdjustStartIdx = (PrevCtrlPtSegId + PivotStartIdx) / 2; Vector3 a = Rd.XSecs[PrevCtrlPtSegId].KerbR; Vector3 b = Rd.XSecs[(PrevCtrlPtSegId + PivotStartIdx) / 2].KerbR; Vector3 c = Rd.XSecs[PivotStartIdx].KerbR; Vector3 d = Rd.XSecs[(PivotStartIdx + NxtCtrlPtSegId) / 2].KerbR; c = new Vector3(c.x, (b.y + d.y) / 2, c.z); float t = 0.5f; //if (Vector3.Angle(c - b, d - c) > 135 || Vector3.Angle(b - a, c - b) > 135) t = 2.5f; for (int p = 0; p < NumXSecsToAdjust; p++) { float u = (float)p / NumXSecsToAdjust; //Coeffs for the catmullrom equation Vector3 c0 = b; Vector3 c1 = -t * a + t * c; Vector3 c2 = 2f * t * a + (t - 3f) * b + (3f - 2f * t) * c - t * d; Vector3 c3 = -t * a + (2f - t) * b + (t - 2f) * c + t * d; Vector3 temp = c0 + c1 * u + c2 * u * u + c3 * u * u * u; //Vector3 temp = .5f * ((-a + 3f * b - 3f * c + d) * (u * u * u) + (2f * a - 5f * b + 4f * c - d) * (u * u) + (-a + c) * u + 2f * b); Vector3 newKerb = temp; XSec X = new XSec((CtlPtIdx - 1) * 20 - 10 + p); X.KerbR = temp - Rd.XSecs[AdjustStartIdx + p].KerbR; Road.Instance.XSecs[AdjustStartIdx + p].Adjust(X); } //Catmull ROm after the control point NumXSecsToAdjust = Bez.CtrlPts[CtlPtIdx].SegCount / 2; AdjustStartIdx = (PivotStartIdx) / 2; a = b; b = c; c = d; d = Rd.XSecs[NxtCtrlPtSegId].KerbR; //if (Vector3.Angle(c - b, d - c) > 135 || Vector3.Angle(b - a, c - b) > 135) t = 2.5f; for (int p = 0; p < NumXSecsToAdjust; p++) { float u = (float)p / NumXSecsToAdjust; //Coeffs for the catmullrom equation Vector3 c0 = b; Vector3 c1 = -t * a + t * c; Vector3 c2 = 2f * t * a + (t - 3f) * b + (3f - 2f * t) * c - t * d; Vector3 c3 = -t * a + (2f - t) * b + (t - 2f) * c + t * d; Vector3 temp = c0 + c1 * u + c2 * u * u + c3 * u * u * u; //Vector3 temp = .5f * ((-a + 3f * b - 3f * c + d) * (u * u * u) + (2f * a - 5f * b + 4f * c - d) * (u * u) + (-a + c) * u + 2f * b); Vector3 newKerb = temp; XSec X = new XSec((CtlPtIdx - 1) * 20 + p); X.KerbR = temp - Rd.XSecs[AdjustStartIdx + p].KerbR; Road.Instance.XSecs[AdjustStartIdx + p].Adjust(X); } } if (Hand == "L") { for (int Idx1 = (CtlPtIdx - 2) * 20 + 1; Idx1 < (CtlPtIdx - 1) * 20 - 1; Idx1++) { for (int Idx2 = (CtlPtIdx) * 20 - 1; Idx2 > (CtlPtIdx - 1) * 20; Idx2--) { Vector2 PrevKerb12d = Convert2d(XSecCalculator.CalcXSecPerp(Idx1 - 1, 8).KerbL); Vector2 PrevKerb22d = Convert2d(XSecCalculator.CalcXSecPerp(Idx2 - 1, 8).KerbL); Vector2 Kerb12d = Convert2d(XSecCalculator.CalcXSecPerp(Idx1, 8).KerbL); Vector2 Kerb22d = Convert2d(XSecCalculator.CalcXSecPerp(Idx2, 8).KerbL); if (VectGeom.LinesIntersect2d(PrevKerb12d, Kerb12d, PrevKerb22d, Kerb22d)) { //We've found the crossing point // where Hand = "L"; //Take 2 steps back cos the curve would be too tight PivotStartIdx = Idx1 - 2; PivotEndIdx = Idx2 + 1; PivotStart2d = Convert2d(Road.Instance.XSecs[PivotStartIdx].KerbL); PivotEnd2d = Convert2d(Road.Instance.XSecs[PivotEndIdx].KerbL); //Now move the closest pivot back so its the same distance from the control point //Which is the closest? Vector2 CtrlPt2d = Convert2d(Bez.CtrlPts[CtlPtIdx].Pos); float DistS = Vector2.Distance(PivotStart2d, CtrlPt2d); float DistE = Vector2.Distance(PivotEnd2d, CtrlPt2d); PlaceMarker(CtrlPt2d); if (DistS > DistE) { //Debug.Log("ClosestPivotIdx = PivotEndIdx"); PivotEnd2d = Vector2.Lerp(CtrlPt2d, PivotEnd2d, DistS / DistE); Rd.XSecs[PivotEndIdx].KerbL = new Vector3(PivotEnd2d.x, 0, PivotEnd2d.y); //Todo1 } else { //Debug.Log("ClosestPivotIdx = PivotStartIdx"); PivotStart2d = CtrlPt2d + (PivotStart2d - CtrlPt2d) * DistE / DistS; Rd.XSecs[PivotStartIdx].KerbL = new Vector3(PivotStart2d.x, 0, PivotStart2d.y); //Todo1 } PlaceMarker(PivotStart2d); PlaceMarker(PivotEnd2d); } } } } if (PivotStartIdx != PivotEndIdx) { //Adjust all the right kerbs around the pivot //lets just lerp the kerb from pivotstart to pivotend //Todo: would be nice to do a catmul-rom curve around the pivot float TotLerp = (float)(PivotEndIdx - PivotStartIdx); for (int Idx = PivotStartIdx + 1; Idx < PivotEndIdx; Idx++) { float LerpFrac = (float)(Idx - PivotStartIdx) / TotLerp; Vector2 Kerb2d; if (Hand == "R") { //Todo1 Kerb2d = Vector2.Lerp(Convert2d(Road.Instance.XSecs[PivotStartIdx].KerbR), (Convert2d(Road.Instance.XSecs[PivotEndIdx].KerbR)), LerpFrac); Rd.XSecs[Idx].KerbR = new Vector3(Kerb2d.x, Bez.Path[Idx].y, Kerb2d.y); //Todo1 } else { //Todo1 Kerb2d = Vector2.Lerp(Convert2d(Road.Instance.XSecs[PivotStartIdx].KerbL), (Convert2d(Road.Instance.XSecs[PivotEndIdx].KerbL)), LerpFrac); Rd.XSecs[Idx].KerbL = new Vector3(Kerb2d.x, Bez.Path[Idx].y, Kerb2d.y); //Todo1 } } } //Even if there is no hairpin we still might have a steep inner slope //So find where the steepness starts and finishes if (PivotStartIdx == PivotEndIdx) { Vector3 K1; Vector3 K2; bool PivotStarted = false; for (int i = (CtlPtIdx - 1) * 20 - 5; i < (CtlPtIdx - 1) * 20 + 5; i++) { if (Hand == "L") { K1 = Road.Instance.XSecs[i].KerbL; K2 = Road.Instance.XSecs[i + 1].KerbL; } else { K1 = Road.Instance.XSecs[i].KerbR; K2 = Road.Instance.XSecs[i + 1].KerbR; } if ((K2.y - K1.y) / Vector2.Distance(Convert2d(K2), Convert2d(K1)) > 0.4f) { if (PivotStarted == false) { PivotStartIdx = i; PivotStarted = true; } if (PivotStarted == true) { PivotEndIdx = i; } } else { if (PivotStarted == true) { break; } } } } //Adjust the heights so we don't get steps in the road //we adjust the inner slope before and after the pivot uaing a smoothstep function int NoOfSegmentsToAdjust = Mathf.CeilToInt(Mathf.Abs((Bez.Path[PivotEndIdx].y - Bez.Path[PivotStartIdx].y) / 2)); int AdjStartIdx = PivotStartIdx - NoOfSegmentsToAdjust; if (AdjStartIdx < 0) { AdjStartIdx = 0; } int AdjEndIdx = PivotEndIdx + NoOfSegmentsToAdjust; float AdjStarty; float AdjEndy; float TotAdjDist = 0; if (Hand == "L") { AdjStarty = Road.Instance.XSecs[AdjStartIdx].KerbL.y; AdjEndy = Road.Instance.XSecs[AdjEndIdx].KerbL.y; for (int i = AdjStartIdx + 1; i <= AdjEndIdx; i++) { TotAdjDist += Vector2.Distance(Convert2d(Road.Instance.XSecs[i].KerbL), Convert2d(Road.Instance.XSecs[i - 1].KerbL)); } float delta = 0; for (int i = AdjStartIdx + 1; i <= AdjEndIdx; i++) { delta += Vector2.Distance(Convert2d(Road.Instance.XSecs[i].KerbL), Convert2d(Road.Instance.XSecs[i - 1].KerbL)); float NewY = Mathf.SmoothStep(AdjStarty, AdjEndy, delta / TotAdjDist); float AdjY = NewY - Road.Instance.XSecs[i].KerbL.y; XSec X = new XSec(i); X.KerbL = new Vector3(0, AdjY, 0); Road.Instance.XSecs[i].Adjust(X); } } if (Hand == "R") { AdjStarty = Road.Instance.XSecs[AdjStartIdx].KerbR.y; AdjEndy = Road.Instance.XSecs[AdjEndIdx].KerbR.y; for (int i = AdjStartIdx + 1; i <= AdjEndIdx; i++) { TotAdjDist += Vector2.Distance(Convert2d(Road.Instance.XSecs[i].KerbR), Convert2d(Road.Instance.XSecs[i - 1].KerbR)); } float delta = 0; for (int i = AdjStartIdx + 1; i <= AdjEndIdx; i++) { delta += Vector2.Distance(Convert2d(Road.Instance.XSecs[i].KerbR), Convert2d(Road.Instance.XSecs[i - 1].KerbR)); float NewY = Mathf.SmoothStep(AdjStarty, AdjEndy, delta / TotAdjDist); float AdjY = NewY - Road.Instance.XSecs[i].KerbR.y; XSec X = new XSec(i); X.KerbR = new Vector3(0, AdjY, 0); Road.Instance.XSecs[i].Adjust(X); } } }
/// <summary> /// When you drop the marker onto the start marker /// It creates a smooth(ish) overlap by adding two extra control points /// and aligning them with points 2 and 3 /// </summary> /// <param name="Point"></param> public void JoinSection(Vector3 Point) { if (Rd.Sectns.Count < 4) { return; } int SegCount = Mathf.CeilToInt(Vector3.Distance(Point, Bez.CtrlPts[Bez.CtrlPts.Count - 2].Pos) / 0.84f); Road.Instance.IsCircular = true; RoadSectn Sectn = new RoadSectn(); int NewIdx = Road.Instance.Sectns.Count; Sectn.Idx = NewIdx; Sectn.name = "RoadSection" + (NewIdx); Rd.Sectns[NewIdx - 1].AddXSecs(SegCount); //Add XSecs to the PREVIOUS Section Sectn.CreateGameObjects(); Road.Instance.Sectns.Add(Sectn); //Move the hidden control point to the penultimate position: Bez.CtrlPts[0].Pos = Bez.CtrlPts[Bez.CtrlPts.Count - 2].Pos; //this doesnt work any more - had to fix it in CalcXSecs //Add a control point at the join Bez.AddControlPoint(Point, 0, SegCount); //We add a couple more control points so we can recalculate the curve after the join //We will remove one of these two in a sec RoadSectn OverlapSectn = new RoadSectn(); //OverlapSectn.AddXSecs(Rd.Sectns[1].Segments.Count); Bez.AddControlPoint(Bez.CtrlPts[2].Pos, Bez.CtrlPts[2].BankAngle, 20); Bez.AddControlPoint(Bez.CtrlPts[3].Pos, Bez.CtrlPts[3].BankAngle, 20); //Recalculate Section 1 that goes from CtrlPt1 to CtrlPt2 Bez.Interp(1); //It doesn't interp the Section before CtrlPt1 //Interp the path two before the end Bez.Interp(NewIdx - 1); //Interp the path just before the end Bez.Interp(NewIdx); Bez.AlignAllRoadMarkers(); XSecCalculator.CalcXSecs(2, RoadWidth); //Bez.RemoveLastControlPoint(); //Bez.CtrlPts[Bez.CtrlPts.Count - 1] = Bez.CtrlPts[Bez.CtrlPts.Count - 2]; XSecCalculator.CalcXSecs(NewIdx - 1, RoadWidth); XSecCalculator.CalcXSecs(NewIdx, RoadWidth); //NOt sure we need this next bit - We only need to calculate the XSec for one path point. // Commented out because it crashed - XSecCalculator.CalcXSecs(NewIdx + 1, RoadWidth); //Remove the 2 extra control points and their paths Bez.RemoveLastControlPoint(); Bez.RemoveLastControlPoint(); Bez.CtrlPts[Bez.CtrlPts.Count - 1].Pos = Bez.CtrlPts[2].Pos; //new bit for (int Idx = Bez.CtrlPts[NewIdx - 1].SegStartIdx; Idx < Bez.CtrlPts[NewIdx].SegStartIdx; Idx++) //create the segs ahead of the marker but don't mesh them { RoadSegment seg = new RoadSegment(); seg.Idx = Idx; seg.SectnIdx = NewIdx - 1; Rd.Sectns[NewIdx - 1].Segments.Add(seg); seg.CreateGameObjects(); seg.goSeg.name = "RoadSeg" + Idx; Rd.Segments.Add(seg); seg.SetMaterial(RoadMat); seg.LFenceType = LFenceType; seg.RFenceType = RFenceType; seg.goSeg.transform.SetParent(Rd.Sectns[NewIdx - 1].goSectn.transform); } Rd.Sectns[NewIdx - 1].SetMaterial(RoadMat); //bugfix 6/2/18 cos we now store RdMat in the section not the segment Rd.Sectns[NewIdx - 1].LFenceType = LFenceType; //Longstanding bug fixed Rd.Sectns[NewIdx - 1].RFenceType = RFenceType; //Longstanding bug fixed XSecCalculator.AdjustHairpin(Bez, NewIdx - 2); XSecCalculator.AdjustHairpin(Bez, NewIdx - 1); XSecCalculator.AdjustHairpin(Bez, 2); Road.Instance.Sectns[NewIdx - 3].CalcVisibleFenceVerts(); BuildQueue.Enqueue(NewIdx - 3); Road.Instance.Sectns[NewIdx - 2].CalcVisibleFenceVerts(); BuildQueue.Enqueue(NewIdx - 2); Road.Instance.Sectns[NewIdx - 1].CalcVisibleFenceVerts(); BuildQueue.Enqueue(NewIdx - 1); Road.Instance.Sectns[NewIdx].CalcVisibleFenceVerts(); //Join the beginning of the first Segment to the end of the last //Road.Instance.XSecs[0].KerbL = Road.Instance.XSecs[(Road.Instance.Sectns.Count - 2) * 20].KerbL; //Road.Instance.XSecs[0].KerbR = Road.Instance.XSecs[(Road.Instance.Sectns.Count - 2) * 20].KerbR; Road.Instance.Sectns[1].CalcVisibleFenceVerts(); BuildQueue.Enqueue(1); //Remove the Path points that were created when we added the second extra control point (The first one is needed because the SegVerts calculation needs it) //Bez.Path.RemoveRange(Bez.Path.Count - 20, 20); //This line commentd out now because RemoveCtrlPt also removes the Path Points Bez.DrawLine(); }
public void AddSection(Vector3 Point) //We add the section but we can't say how many segments it has //So we add the Xsecs and Segs for the previous section { if (Road.Instance.IsCircular) { return; } if (Bez.CtrlPts.Count > 3 && Vector3.Distance(Point, Bez.CtrlPts[Bez.CtrlPts.Count - 2].Pos) > 80) { Tut.gameObject.SetActive(true); Tut.ShowSpeech("This cone is too far from the last", 5); return; } int NewIdx = Road.Instance.Sectns.Count; int SegCount; Point = Bez.LimitSlope(Point, 0.33f); if (Bez.CtrlPts.Count == 2) { SegCount = 0; } else { SegCount = Mathf.CeilToInt(Vector3.Distance(Point, Bez.CtrlPts[Bez.CtrlPts.Count - 2].Pos) / 0.84f); } Bez.AddControlPoint(Point, 0, SegCount); Bez.Interp(NewIdx - 1); Bez.DrawLine(); RoadSectn Sectn = new RoadSectn(); Sectn.Idx = NewIdx; Sectn.name = "RoadSection" + (NewIdx); Rd.Sectns[NewIdx - 1].Chargeable = true; Rd.Sectns[NewIdx - 1].AddXSecs(SegCount); //Add XSecs to the PREVIOUS Section Sectn.CreateGameObjects(); Road.Instance.Sectns.Add(Sectn); // Section1 comes after RoadMarker1 Bez.CtrlPts[NewIdx].CreateRoadMarker(); Bez.AlignAllRoadMarkers(); XSecCalculator.CalcXSecs(NewIdx - 1, RoadWidth); //calculates for the section up to the previous marker for (int Idx = Bez.CtrlPts[NewIdx - 1].SegStartIdx; Idx < Bez.CtrlPts[NewIdx].SegStartIdx; Idx++) //create the segs ahead of the marker but don't mesh them { RoadSegment seg = new RoadSegment(); seg.Idx = Idx; seg.SectnIdx = NewIdx - 1; Rd.Sectns[NewIdx - 1].Segments.Add(seg); seg.CreateGameObjects(); seg.goSeg.name = "RoadSeg" + Idx; Rd.Segments.Add(seg); seg.SetMaterial(RoadMat); seg.LFenceType = LFenceType; seg.RFenceType = RFenceType; seg.goSeg.transform.SetParent(Rd.Sectns[NewIdx - 1].goSectn.transform); } Rd.Sectns[NewIdx].SetMaterial(RoadMat); Rd.Sectns[NewIdx - 1].LFenceType = LFenceType; Rd.Sectns[NewIdx - 1].RFenceType = RFenceType; Rd.Sectns[NewIdx - 1].SetMaterial(RoadMat); XSecCalculator.AdjustHairpin(Bez, NewIdx - 2); if (NewIdx > 3) { Road.Instance.Sectns[NewIdx - 3].CalcVisibleFenceVerts(); } BuildQueue.Enqueue(NewIdx - 3); Bez.CtrlPts[NewIdx].goRdMkr.GetComponent <RoadMarker>().Select(); //Update the tutorial if (SaveLoadModel.savedGames.Count < 3) { Tutorial Tut = _canvas.transform.Find("pnlTutorialBuild2(Clone)").GetComponent <Tutorial>(); int _roadCost = BillOfRoadMaterials.Items.Sum(i => i.Cost); int _sceneryCost = BillOfSceneryMaterials.Items.Sum(i => i.Opt.Cost); int conesLeft = (UserDataManager.Instance.Data.Coins - _roadCost - _sceneryCost) / 5; Tut.ShowSpeech(string.Format("You have money for {0:0.} more cones\n\nThe track must be a loop", conesLeft), 3); } }
public void Decode() { Road Rd = Road.Instance; Rd.Segments.Clear(); Rd.XSecs.Clear(); Rd.Sectns.Clear(); if (XSecs == null) { //in case we are loading a blank track Rd.Init(); } else { Rd.StartingLineSegIdx = StartingLineSegIdx; if (BuilderPos != null) { Rd.BuilderPos = BuilderPos.V3; } else { Rd.BuilderPos = new Vector3(0, 50f, 0); } if (BuilderRot != null) { Rd.BuilderRot = BuilderRot.Decode; } Rd.IsCircular = IsCircular; foreach (XSecSerial XS in XSecs) { XSec X = XS.Decode(); Rd.XSecs.Add(X); } foreach (RoadSectionSerial RSS in Sectns) { RoadSectn RS = RSS.Decode(); Rd.Sectns.Add(RS); } foreach (RoadSegmentSerial SegS in Segs) { RoadSegment Seg = SegS.Decode(); Rd.Segments.Add(Seg); } //Build the meshes for all the segments for (int Idx = 0; Idx < Segs.Length; Idx++) { RoadSegment seg = Road.Instance.Segments[Idx]; if (seg.HasMesh) { SegVerts Verts = XSecCalculator.SegmentVertices(Idx); seg.BuildMeshes(Verts); } //seg.GetTerrainHeights(); //seg.AdjustTerrain(); //seg.SetMaterial(); //seg.DeleteFence(); //seg.CreateFence(); } Rd.CalculateBends(); } }