/// <summary> /// Returns a position on the spline at the given percentage. /// </summary> public Vector3 GetPosition(float percentage, bool evenDistribution = true, int distributionSteps = 100) { //evaluate curve: CurveDetail curveDetail = GetCurve(percentage); //avoid an error in editor usage where this index can be -1: if (curveDetail.currentCurve < 0) { return(Vector3.zero); } SplineAnchor startAnchor = Anchors[curveDetail.currentCurve]; SplineAnchor endAnchor = Anchors[curveDetail.currentCurve + 1]; return(BezierCurves.GetPoint(startAnchor.Anchor.position, endAnchor.Anchor.position, startAnchor.OutTangent.position, endAnchor.InTangent.position, curveDetail.currentCurvePercentage, evenDistribution, distributionSteps)); }
/// <summary> /// Returns a facing vector at the given percentage along the spline to allow content to properly orient along the spline. /// </summary> public Vector3 GetDirection(float percentage) { //get direction: CurveDetail curveDetail = GetCurve(percentage); //avoid an error in editor usage where this index can be -1: if (curveDetail.currentCurve < 0) { return(Vector3.zero); } SplineAnchor startAnchor = Anchors[curveDetail.currentCurve]; SplineAnchor endAnchor = Anchors[curveDetail.currentCurve + 1]; return(BezierCurves.GetFirstDerivative(startAnchor.Anchor.position, endAnchor.Anchor.position, startAnchor.OutTangent.position, endAnchor.InTangent.position, curveDetail.currentCurvePercentage).normalized); }
static void DrawTools(Transform target) { Spline spline = target.GetComponent <Spline> (); if (spline == null) { return; } if (target.transform.childCount == 0) { return; } //set primary draw color: Handles.color = spline.SecondaryColor; for (int i = 0; i < spline.Anchors.Length; i++) { //refs: Quaternion lookRotation = Quaternion.identity; SplineAnchor currentAnchor = spline.Anchors[i]; //scale geometry: currentAnchor.InTangent.localScale = Vector3.one * (spline.toolScale * 1.3f); currentAnchor.OutTangent.localScale = Vector3.one * (spline.toolScale * 1.3f); currentAnchor.Anchor.localScale = Vector3.one * (spline.toolScale * 2.1f); if (spline.toolScale > 0) { //draw persistent identifiers that face the scene view camera and only draw if the corrosponding tangent is active: if (currentAnchor.OutTangent.gameObject.activeSelf) { //connection: Handles.DrawDottedLine(currentAnchor.Anchor.position, currentAnchor.OutTangent.position, 3); //indicators: if (SceneView.currentDrawingSceneView != null) { lookRotation = Quaternion.LookRotation((SceneView.currentDrawingSceneView.camera.transform.position - currentAnchor.OutTangent.position).normalized); Handles.CircleHandleCap(0, currentAnchor.OutTangent.position, lookRotation, spline.toolScale * .65f, EventType.Repaint); Handles.CircleHandleCap(0, currentAnchor.OutTangent.position, lookRotation, spline.toolScale * .25f, EventType.Repaint); } } if (currentAnchor.InTangent.gameObject.activeSelf) { //connection: Handles.DrawDottedLine(currentAnchor.Anchor.position, currentAnchor.InTangent.position, 3); //indicators: if (SceneView.currentDrawingSceneView != null) { lookRotation = Quaternion.LookRotation((SceneView.currentDrawingSceneView.camera.transform.position - currentAnchor.InTangent.position).normalized); Handles.CircleHandleCap(0, currentAnchor.InTangent.position, lookRotation, spline.toolScale * .65f, EventType.Repaint); Handles.CircleHandleCap(0, currentAnchor.InTangent.position, lookRotation, spline.toolScale * .25f, EventType.Repaint); } } //anchor tools: if (SceneView.currentDrawingSceneView != null) { lookRotation = Quaternion.LookRotation((SceneView.currentDrawingSceneView.camera.transform.position - currentAnchor.Anchor.position).normalized); Handles.CircleHandleCap(0, currentAnchor.Anchor.position, lookRotation, spline.toolScale, EventType.Repaint); } //identify path origin: if (spline.direction == SplineDirection.Forward && i == 0 || spline.direction == SplineDirection.Backwards && i == spline.Anchors.Length - 1) { Handles.CircleHandleCap(0, currentAnchor.Anchor.position, lookRotation, spline.toolScale * .8f, EventType.Repaint); Handles.CircleHandleCap(0, currentAnchor.Anchor.position, lookRotation, spline.toolScale * .75f, EventType.Repaint); Handles.CircleHandleCap(0, currentAnchor.Anchor.position, lookRotation, spline.toolScale * .5f, EventType.Repaint); Handles.CircleHandleCap(0, currentAnchor.Anchor.position, lookRotation, spline.toolScale * .45f, EventType.Repaint); Handles.CircleHandleCap(0, currentAnchor.Anchor.position, lookRotation, spline.toolScale * .25f, EventType.Repaint); } } } //draw spline: for (int i = 0; i < spline.Anchors.Length - 1; i++) { SplineAnchor startAnchor = spline.Anchors[i]; SplineAnchor endAnchor = spline.Anchors[i + 1]; Handles.DrawBezier(startAnchor.Anchor.position, endAnchor.Anchor.position, startAnchor.OutTangent.position, endAnchor.InTangent.position, spline.color, null, 2); } }
/// <summary> /// Makes a spline longer. /// </summary> public GameObject[] AddAnchors(int count) { //refs: GameObject anchorTemplate = Resources.Load("Anchor") as GameObject; //if we have no anchors let's make sure we create a spline segment and not just a single anchor: if (Anchors.Length == 0) { count = 2; } //create return array: GameObject[] returnObjects = new GameObject[count]; for (int i = 0; i < count; i++) { //previous anchor refs: Transform previousPreviousAnchor = null; Transform previousAnchor = null; if (Anchors.Length == 1) { previousPreviousAnchor = transform; previousAnchor = Anchors[0].transform; } else if (Anchors.Length > 1) { previousPreviousAnchor = Anchors[Anchors.Length - 2].transform; previousAnchor = Anchors[Anchors.Length - 1].transform; } //create a new anchor: GameObject newAnchor = Instantiate <GameObject>(anchorTemplate); newAnchor.name = newAnchor.name.Replace("(Clone)", ""); SplineAnchor anchor = newAnchor.GetComponent <SplineAnchor>(); anchor.tangentMode = defaultTangentMode; newAnchor.transform.parent = transform; newAnchor.transform.rotation = Quaternion.LookRotation(transform.forward); //tilt tangents for variety as we add new anchors: //anchor.Tilt (new Vector3 (0, 0, 0)); anchor.InTangent.Translate(Vector3.up * .5f); anchor.OutTangent.Translate(Vector3.up * -.5f); //position new anchor: if (previousPreviousAnchor != null && previousAnchor != null) { //determine direction for next placement: Vector3 direction = (previousAnchor.position - previousPreviousAnchor.position).normalized; if (direction == Vector3.zero) { direction = transform.forward; } //place from the previous anchor in the correct direction: newAnchor.transform.position = previousAnchor.transform.position + (direction * 1.5f); } else { newAnchor.transform.localPosition = Vector3.zero; } //catalog this new anchor for return: returnObjects[i] = newAnchor; } return(returnObjects); }