namespace DrawXXL { using UnityEngine; using System.Collections.Generic; public class UtilitiesDXXL_Bezier { public static void BezierSegmentQuadratic(bool is2D, Vector3 startPosition, Vector3 endPosition, Vector3 controlPosInBetween, Color color, string text, float width, int straightSubDivisions, float textSize, bool drawIngameWarningTextForZeroExtent, float durationInSec, bool hiddenByNearerObjects) { if (DXXLWrapperForUntiysBuildInDrawLines.CheckIfDrawingIsCurrentlySkipped()) { return; } if (drawIngameWarningTextForZeroExtent) { if (UtilitiesDXXL_Math.CheckIf_vectorsAreApproximatelyEqual(startPosition, endPosition, controlPosInBetween)) { if (is2D) { UtilitiesDXXL_DrawBasics2D.PointFallback(startPosition, "[ BezierQuadratic2D with extent of 0]
" + text, color, width, durationInSec, hiddenByNearerObjects); } else { UtilitiesDXXL_DrawBasics.PointFallback(startPosition, "[ BezierQuadratic with extent of 0]
" + text, color, width, durationInSec, hiddenByNearerObjects); } return; } } straightSubDivisions = Mathf.Clamp(straightSubDivisions, 4, 1000); InternalDXXL_Plane preferredAmplitudeDir = is2D ? UtilitiesDXXL_DrawBasics2D.xyPlane_throughZero : null; Vector3 prevPointOnBezierCurve = startPosition; float progress0to1_perStraightSubDivision = 1.0f / (float)straightSubDivisions; for (int i = 1; i < straightSubDivisions; i++) { float progress_0to1 = progress0to1_perStraightSubDivision * i; float oneMinusProgress0to1 = 1.0f - progress_0to1; float factor1 = oneMinusProgress0to1 * oneMinusProgress0to1; float factor2 = 2.0f * oneMinusProgress0to1 * progress_0to1; float factor3 = progress_0to1 * progress_0to1; Vector3 currPointOnBezierCurve = factor1 * startPosition + factor2 * controlPosInBetween + factor3 * endPosition; UtilitiesDXXL_DrawBasics.Line(prevPointOnBezierCurve, currPointOnBezierCurve, color, width, null, DrawBasics.LineStyle.solid, 1.0f, 0.0f, null, preferredAmplitudeDir, is2D, 0.0f, 0.0f, durationInSec, hiddenByNearerObjects, false, false, null, false, 0.0f); prevPointOnBezierCurve = currPointOnBezierCurve; } UtilitiesDXXL_DrawBasics.Line(prevPointOnBezierCurve, endPosition, color, width, null, DrawBasics.LineStyle.solid, 1.0f, 0.0f, null, preferredAmplitudeDir, is2D, 0.0f, 0.0f, durationInSec, hiddenByNearerObjects, false, false, null, false, 0.0f); if (text != null && text != "") { if (is2D) { UtilitiesDXXL_Text.Write2DFramed(text, startPosition, color, textSize, default(Vector2), DrawText.TextAnchorDXXL.LowerLeftOfFirstLine, startPosition.z, DrawBasics.LineStyle.invisible, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, true, durationInSec, hiddenByNearerObjects); } else { UtilitiesDXXL_Text.WriteFramed(text, startPosition, color, textSize, default(Vector3), default(Vector3), DrawText.TextAnchorDXXL.LowerLeftOfFirstLine, DrawBasics.LineStyle.invisible, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, true, durationInSec, hiddenByNearerObjects); } } } public static void BezierSegmentCubic(bool is2D, Vector3 startPosition, Vector3 endPosition, Vector3 controlPosOfStartDirection, Vector3 controlPosOfEndDirection, Color color, string text, float width, int straightSubDivisions, float textSize, bool drawIngameWarningTextForZeroExtent, float durationInSec, bool hiddenByNearerObjects) { if (DXXLWrapperForUntiysBuildInDrawLines.CheckIfDrawingIsCurrentlySkipped()) { return; } if (drawIngameWarningTextForZeroExtent) { if (UtilitiesDXXL_Math.CheckIf_vectorsAreApproximatelyEqual(startPosition, endPosition, controlPosOfStartDirection, controlPosOfEndDirection)) { if (is2D) { UtilitiesDXXL_DrawBasics2D.PointFallback(startPosition, "[ BezierCubic2D with extent of 0]
" + text, color, width, durationInSec, hiddenByNearerObjects); } else { UtilitiesDXXL_DrawBasics.PointFallback(startPosition, "[ BezierCubic with extent of 0]
" + text, color, width, durationInSec, hiddenByNearerObjects); } return; } } straightSubDivisions = Mathf.Clamp(straightSubDivisions, 4, 1000); InternalDXXL_Plane preferredAmplitudeDir = is2D ? UtilitiesDXXL_DrawBasics2D.xyPlane_throughZero : null; Vector3 prevPointOnBezierCurve = startPosition; float progress0to1_perStraightSubDivision = 1.0f / (float)straightSubDivisions; for (int i = 1; i < straightSubDivisions; i++) { float progress_0to1 = progress0to1_perStraightSubDivision * i; float progress_0to1_sqr = progress_0to1 * progress_0to1; float oneMinusProgress0to1 = 1.0f - progress_0to1; float oneMinusProgress0to1_sqr = oneMinusProgress0to1 * oneMinusProgress0to1; float factor1 = oneMinusProgress0to1 * oneMinusProgress0to1_sqr; float factor2 = 3.0f * oneMinusProgress0to1_sqr * progress_0to1; float factor3 = 3.0f * oneMinusProgress0to1 * progress_0to1_sqr; float factor4 = progress_0to1 * progress_0to1_sqr; Vector3 currPointOnBezierCurve = factor1 * startPosition + factor2 * controlPosOfStartDirection + factor3 * controlPosOfEndDirection + factor4 * endPosition; UtilitiesDXXL_DrawBasics.Line(prevPointOnBezierCurve, currPointOnBezierCurve, color, width, null, DrawBasics.LineStyle.solid, 1.0f, 0.0f, null, preferredAmplitudeDir, is2D, 0.0f, 0.0f, durationInSec, hiddenByNearerObjects, false, false, null, false, 0.0f); prevPointOnBezierCurve = currPointOnBezierCurve; } UtilitiesDXXL_DrawBasics.Line(prevPointOnBezierCurve, endPosition, color, width, null, DrawBasics.LineStyle.solid, 1.0f, 0.0f, null, preferredAmplitudeDir, is2D, 0.0f, 0.0f, durationInSec, hiddenByNearerObjects, false, false, null, false, 0.0f); if (text != null && text != "") { if (is2D) { UtilitiesDXXL_Text.Write2DFramed(text, startPosition, color, textSize, default(Vector2), DrawText.TextAnchorDXXL.LowerLeftOfFirstLine, startPosition.z, DrawBasics.LineStyle.invisible, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, true, durationInSec, hiddenByNearerObjects); } else { UtilitiesDXXL_Text.WriteFramed(text, startPosition, color, textSize, default(Vector3), default(Vector3), DrawText.TextAnchorDXXL.LowerLeftOfFirstLine, DrawBasics.LineStyle.invisible, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, true, durationInSec, hiddenByNearerObjects); } } } public delegate Vector3 FlexibleGetPosAtIndex(T collection, int i_whereToObtain, out bool itemIsNull); public delegate Vector3 FlexibleGetDirectionControlPosOfTransform(T collection, int i_transformWhereToObtain); public static Vector3 GetPositionsFromGameObjectsArray(GameObject[] points, int i_whereToObtain, out bool itemIsNull) { if (points[i_whereToObtain] == null) { itemIsNull = true; return Vector3.zero; } else { itemIsNull = false; return points[i_whereToObtain].transform.position; } } public static Vector3 GetPositionsFromGameObjectsList(List points, int i_whereToObtain, out bool itemIsNull) { if (points[i_whereToObtain] == null) { itemIsNull = true; return Vector3.zero; } else { itemIsNull = false; return points[i_whereToObtain].transform.position; } } public static Vector3 GetPositionsFromTransformsArray(Transform[] points, int i_whereToObtain, out bool itemIsNull) { if (points[i_whereToObtain] == null) { itemIsNull = true; return Vector3.zero; } else { itemIsNull = false; return points[i_whereToObtain].position; } } public static Vector3 GetPositionsFromTransformsList(List points, int i_whereToObtain, out bool itemIsNull) { if (points[i_whereToObtain] == null) { itemIsNull = true; return Vector3.zero; } else { itemIsNull = false; return points[i_whereToObtain].position; } } public static Vector3 GetPositionsFromVector3Array(Vector3[] points, int i_whereToObtain, out bool itemIsNull) { Vector3 vectorAtRequestedPos = points[i_whereToObtain]; if (UtilitiesDXXL_Math.FloatIsInvalid(vectorAtRequestedPos.x) || UtilitiesDXXL_Math.FloatIsInvalid(vectorAtRequestedPos.y) || UtilitiesDXXL_Math.FloatIsInvalid(vectorAtRequestedPos.z)) { itemIsNull = true; return Vector3.zero; } else { itemIsNull = false; return points[i_whereToObtain]; } } public static Vector3 GetPositionsFromVector3List(List points, int i_whereToObtain, out bool itemIsNull) { Vector3 vectorAtRequestedPos = points[i_whereToObtain]; if (UtilitiesDXXL_Math.FloatIsInvalid(vectorAtRequestedPos.x) || UtilitiesDXXL_Math.FloatIsInvalid(vectorAtRequestedPos.y) || UtilitiesDXXL_Math.FloatIsInvalid(vectorAtRequestedPos.z)) { itemIsNull = true; return Vector3.zero; } else { itemIsNull = false; return points[i_whereToObtain]; } } public static Vector3 GetForwardControlPosFromGameObjectsArray(GameObject[] points, int i_whereToObtain) { return (points[i_whereToObtain].transform.position + points[i_whereToObtain].transform.forward * points[i_whereToObtain].transform.localScale.z); } public static Vector3 GetForwardControlPosFromGameObjectsList(List points, int i_whereToObtain) { return (points[i_whereToObtain].transform.position + points[i_whereToObtain].transform.forward * points[i_whereToObtain].transform.localScale.z); } public static Vector3 GetForwardControlPosFromTransformsArray(Transform[] points, int i_whereToObtain) { return (points[i_whereToObtain].position + points[i_whereToObtain].forward * points[i_whereToObtain].localScale.z); } public static Vector3 GetForwardControlPosFromTransformsList(List points, int i_whereToObtain) { return (points[i_whereToObtain].position + points[i_whereToObtain].forward * points[i_whereToObtain].localScale.z); } public static Vector3 GetBackwardControlPosFromGameObjectsArray(GameObject[] points, int i_whereToObtain) { return (points[i_whereToObtain].transform.position - points[i_whereToObtain].transform.forward * points[i_whereToObtain].transform.localScale.y); } public static Vector3 GetBackwardControlPosFromGameObjectsList(List points, int i_whereToObtain) { return (points[i_whereToObtain].transform.position - points[i_whereToObtain].transform.forward * points[i_whereToObtain].transform.localScale.y); } public static Vector3 GetBackwardControlPosFromTransformsArray(Transform[] points, int i_whereToObtain) { return (points[i_whereToObtain].position - points[i_whereToObtain].forward * points[i_whereToObtain].localScale.y); } public static Vector3 GetBackwardControlPosFromTransformsList(List points, int i_whereToObtain) { return (points[i_whereToObtain].position - points[i_whereToObtain].forward * points[i_whereToObtain].localScale.y); } public static Vector3 GetPositions3DFromGameObjectsArray_2D(GameObject[] points, int i_whereToObtain, out bool itemIsNull) { if (points[i_whereToObtain] == null) { itemIsNull = true; return new Vector3(0.0f, 0.0f, currentZPos); } else { itemIsNull = false; return new Vector3(points[i_whereToObtain].transform.position.x, points[i_whereToObtain].transform.position.y, currentZPos); } } public static Vector3 GetPositions3DFromGameObjectsList_2D(List points, int i_whereToObtain, out bool itemIsNull) { if (points[i_whereToObtain] == null) { itemIsNull = true; return new Vector3(0.0f, 0.0f, currentZPos); } else { itemIsNull = false; return new Vector3(points[i_whereToObtain].transform.position.x, points[i_whereToObtain].transform.position.y, currentZPos); } } public static Vector3 GetPositions3DFromTransformsArray_2D(Transform[] points, int i_whereToObtain, out bool itemIsNull) { if (points[i_whereToObtain] == null) { itemIsNull = true; return new Vector3(0.0f, 0.0f, currentZPos); } else { itemIsNull = false; return new Vector3(points[i_whereToObtain].position.x, points[i_whereToObtain].position.y, currentZPos); } } public static Vector3 GetPositions3DFromTransformsList_2D(List points, int i_whereToObtain, out bool itemIsNull) { if (points[i_whereToObtain] == null) { itemIsNull = true; return new Vector3(0.0f, 0.0f, currentZPos); } else { itemIsNull = false; return new Vector3(points[i_whereToObtain].position.x, points[i_whereToObtain].position.y, currentZPos); } } public static Vector3 GetPositions3DFromVector2Array_2D(Vector2[] points, int i_whereToObtain, out bool itemIsNull) { Vector2 vectorAtRequestedPos = points[i_whereToObtain]; if (UtilitiesDXXL_Math.FloatIsInvalid(vectorAtRequestedPos.x) || UtilitiesDXXL_Math.FloatIsInvalid(vectorAtRequestedPos.y)) { itemIsNull = true; return Vector2.zero; } else { itemIsNull = false; return new Vector3(points[i_whereToObtain].x, points[i_whereToObtain].y, currentZPos); } } public static Vector3 GetPositions3DFromVector2List_2D(List points, int i_whereToObtain, out bool itemIsNull) { Vector2 vectorAtRequestedPos = points[i_whereToObtain]; if (UtilitiesDXXL_Math.FloatIsInvalid(vectorAtRequestedPos.x) || UtilitiesDXXL_Math.FloatIsInvalid(vectorAtRequestedPos.y)) { itemIsNull = true; return Vector2.zero; } else { itemIsNull = false; return new Vector3(points[i_whereToObtain].x, points[i_whereToObtain].y, currentZPos); } } public static Vector3 GetForwardControlPos3DFromGameObjectsArray_2D(GameObject[] points, int i_whereToObtain) { Vector3 pos3D_notYetForcedToDrawZPos = (points[i_whereToObtain].transform.position + points[i_whereToObtain].transform.right * points[i_whereToObtain].transform.localScale.x); return new Vector3(pos3D_notYetForcedToDrawZPos.x, pos3D_notYetForcedToDrawZPos.y, currentZPos); } public static Vector3 GetForwardControlPos3DFromGameObjectsList_2D(List points, int i_whereToObtain) { Vector3 pos3D_notYetForcedToDrawZPos = (points[i_whereToObtain].transform.position + points[i_whereToObtain].transform.right * points[i_whereToObtain].transform.localScale.x); return new Vector3(pos3D_notYetForcedToDrawZPos.x, pos3D_notYetForcedToDrawZPos.y, currentZPos); } public static Vector3 GetForwardControlPos3DFromTransformsArray_2D(Transform[] points, int i_whereToObtain) { Vector3 pos3D_notYetForcedToDrawZPos = (points[i_whereToObtain].position + points[i_whereToObtain].right * points[i_whereToObtain].localScale.x); return new Vector3(pos3D_notYetForcedToDrawZPos.x, pos3D_notYetForcedToDrawZPos.y, currentZPos); } public static Vector3 GetForwardControlPos3DFromTransformsList_2D(List points, int i_whereToObtain) { Vector3 pos3D_notYetForcedToDrawZPos = (points[i_whereToObtain].position + points[i_whereToObtain].right * points[i_whereToObtain].localScale.x); return new Vector3(pos3D_notYetForcedToDrawZPos.x, pos3D_notYetForcedToDrawZPos.y, currentZPos); } public static Vector3 GetBackwardControlPos3DFromGameObjectsArray_2D(GameObject[] points, int i_whereToObtain) { Vector3 pos3D_notYetForcedToDrawZPos = (points[i_whereToObtain].transform.position - points[i_whereToObtain].transform.right * points[i_whereToObtain].transform.localScale.y); return new Vector3(pos3D_notYetForcedToDrawZPos.x, pos3D_notYetForcedToDrawZPos.y, currentZPos); } public static Vector3 GetBackwardControlPos3DFromGameObjectsList_2D(List points, int i_whereToObtain) { Vector3 pos3D_notYetForcedToDrawZPos = (points[i_whereToObtain].transform.position - points[i_whereToObtain].transform.right * points[i_whereToObtain].transform.localScale.y); return new Vector3(pos3D_notYetForcedToDrawZPos.x, pos3D_notYetForcedToDrawZPos.y, currentZPos); } public static Vector3 GetBackwardControlPos3DFromTransformsArray_2D(Transform[] points, int i_whereToObtain) { Vector3 pos3D_notYetForcedToDrawZPos = (points[i_whereToObtain].position - points[i_whereToObtain].right * points[i_whereToObtain].localScale.y); return new Vector3(pos3D_notYetForcedToDrawZPos.x, pos3D_notYetForcedToDrawZPos.y, currentZPos); } public static Vector3 GetBackwardControlPos3DFromTransformsList_2D(List points, int i_whereToObtain) { Vector3 pos3D_notYetForcedToDrawZPos = (points[i_whereToObtain].position - points[i_whereToObtain].right * points[i_whereToObtain].localScale.y); return new Vector3(pos3D_notYetForcedToDrawZPos.x, pos3D_notYetForcedToDrawZPos.y, currentZPos); } static float currentZPos; public static void BezierSpline(bool is2D, float customZPos_for2D, BezierPointCollection bezierPointCollection, FlexibleGetPosAtIndex GetPos, FlexibleGetDirectionControlPosOfTransform GetForwardControlPos, FlexibleGetDirectionControlPosOfTransform GetBackwardControlPos, int lengthOfCollection, Color color, DrawBasics.BezierPosInterpretation interpretationOfPointsCollection, string text, float width, bool closeGapFromEndToStart, int straightSubDivisionsPerSegment, float textSize, float durationInSec, bool hiddenByNearerObjects) { if (DXXLWrapperForUntiysBuildInDrawLines.CheckIfDrawingIsCurrentlySkipped()) { return; } Vector3 textPosition; bool textPosition_hasBeenAssigned; currentZPos = UtilitiesDXXL_DrawBasics2D.TryFallbackToDefaultZ(customZPos_for2D); switch (interpretationOfPointsCollection) { case DrawBasics.BezierPosInterpretation.start_control1_control2_endIsNextStart: textPosition = DrawSpline_case_start_control1_control2_endIsNextStart(is2D, out textPosition_hasBeenAssigned, ref text, bezierPointCollection, GetPos, lengthOfCollection, color, interpretationOfPointsCollection, width, closeGapFromEndToStart, straightSubDivisionsPerSegment, textSize, durationInSec, hiddenByNearerObjects); break; case DrawBasics.BezierPosInterpretation.start_control1_endIsNextStart: textPosition = DrawSpline_case_start_control1_endIsNextStart(is2D, out textPosition_hasBeenAssigned, ref text, bezierPointCollection, GetPos, lengthOfCollection, color, interpretationOfPointsCollection, width, closeGapFromEndToStart, straightSubDivisionsPerSegment, textSize, durationInSec, hiddenByNearerObjects); break; case DrawBasics.BezierPosInterpretation.onlySegmentStartPoints_backwardForwardIsAligned: textPosition = DrawSpline_case_onlySegmentStartPoints_backwardForwardIsAligned(is2D, out textPosition_hasBeenAssigned, bezierPointCollection, GetPos, GetForwardControlPos, GetBackwardControlPos, lengthOfCollection, color, interpretationOfPointsCollection, width, closeGapFromEndToStart, straightSubDivisionsPerSegment, textSize, durationInSec, hiddenByNearerObjects); break; case DrawBasics.BezierPosInterpretation.onlySegmentStartPoints_backwardForwardIsMirrored: textPosition = DrawSpline_case_onlySegmentStartPoints_backwardForwardIsMirrored(is2D, out textPosition_hasBeenAssigned, bezierPointCollection, GetPos, GetForwardControlPos, lengthOfCollection, color, interpretationOfPointsCollection, width, closeGapFromEndToStart, straightSubDivisionsPerSegment, textSize, durationInSec, hiddenByNearerObjects); break; case DrawBasics.BezierPosInterpretation.onlySegmentStartPoints_backwardForwardIsKinked: textPosition = DrawSpline_case_onlySegmentStartPoints_backwardForwardIsKinked(is2D, out textPosition_hasBeenAssigned, bezierPointCollection, GetPos, GetForwardControlPos, lengthOfCollection, color, interpretationOfPointsCollection, width, closeGapFromEndToStart, straightSubDivisionsPerSegment, textSize, durationInSec, hiddenByNearerObjects); break; default: textPosition = Vector3.zero; textPosition_hasBeenAssigned = false; Debug.LogError("BezierPosInterpretation of '" + interpretationOfPointsCollection + "' not implemented -> DrawBezierSpline not executed."); break; } if (text != null && text != "") { if (textPosition_hasBeenAssigned) { UtilitiesDXXL_Text.WriteFramed(text, textPosition, color, textSize, default(Vector3), default(Vector3), DrawText.TextAnchorDXXL.LowerLeftOfFirstLine, DrawBasics.LineStyle.invisible, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, true, durationInSec, hiddenByNearerObjects); } else { Debug.Log("No ingame position for the text of the BezierSpline could be appointed -> Fallback to log console. The text is: " + text); } } } static Vector3 DrawSpline_case_start_control1_control2_endIsNextStart(bool is2D, out bool textPosition_hasAlreadyBeenAssigned, ref string text, BezierPointCollection bezierPointCollection, FlexibleGetPosAtIndex GetPos, int lengthOfCollection, Color color, DrawBasics.BezierPosInterpretation interpretationOfPointsCollection, float width, bool closeGapFromEndToStart, int straightSubDivisionsPerSegment, float textSize, float durationInSec, bool hiddenByNearerObjects) { textPosition_hasAlreadyBeenAssigned = false; Vector3 textPosition = Vector3.zero; if (lengthOfCollection < 3) { Debug.LogError("Bezier spline with BezierPosInterpretation of '" + interpretationOfPointsCollection + "' needs at least 3 control points, but the specified collection has only " + lengthOfCollection + " -> drawing skipped."); } else { bool splineHasAlreadyCommunicatedANullItem = false; //preventing log spam and many drawn lines (for multiple fallback texts) int i_startOfCurrSegment = 0; int i_endOfCurrSegment = i_startOfCurrSegment + 3; int maxNumberOfWhileLoops = 10000; //prevent freeze/endless loops int i_whileLoop = 0; while (i_endOfCurrSegment < lengthOfCollection) { TryDrawCubicSegment_ofSplineCase_start_control1_control2_endIsNextStart(is2D, i_startOfCurrSegment, i_endOfCurrSegment, bezierPointCollection, GetPos, i_whileLoop, ref textPosition_hasAlreadyBeenAssigned, ref textPosition, ref splineHasAlreadyCommunicatedANullItem, color, width, straightSubDivisionsPerSegment, textSize, durationInSec, hiddenByNearerObjects); i_startOfCurrSegment = i_endOfCurrSegment; i_endOfCurrSegment = i_startOfCurrSegment + 3; i_whileLoop++; if (i_whileLoop > maxNumberOfWhileLoops) { Debug.LogError("Too many Bezier Segments (more than " + maxNumberOfWhileLoops + "). Drawing aborted."); break; } } if ((i_startOfCurrSegment + 2) < lengthOfCollection) { //two splineDefiningCollectionPoints more than '3 points per segment (+1 final)' scheme: //->one to little for another segment if (closeGapFromEndToStart) { TryDrawCubicSegment_ofSplineCase_start_control1_control2_endIsNextStart(is2D, i_startOfCurrSegment, 0, bezierPointCollection, GetPos, i_whileLoop, ref textPosition_hasAlreadyBeenAssigned, ref textPosition, ref splineHasAlreadyCommunicatedANullItem, color, width, straightSubDivisionsPerSegment, textSize, durationInSec, hiddenByNearerObjects); } else { //Fallback to quadratic bezier at spline end: TryDrawQuadraticSegment_ofSplineCase_start_control1_end(is2D, i_startOfCurrSegment, i_startOfCurrSegment + 2, bezierPointCollection, GetPos, i_whileLoop, ref textPosition_hasAlreadyBeenAssigned, ref textPosition, ref splineHasAlreadyCommunicatedANullItem, color, width, straightSubDivisionsPerSegment, textSize, durationInSec, hiddenByNearerObjects); if (lengthOfCollection > 3) { text = "[ points collection length is 2 too long for the '3 points per segment (+1 final)' scheme
-> last segment falls back from cubic to quadratic bezier]
" + text; } } if (lengthOfCollection == 3) { text = "[ points collection length is 3 but the first segment needs 4
-> the single segment falls back from cubic to quadratic bezier]
" + text; } } else { if ((i_startOfCurrSegment + 1) < lengthOfCollection) { //one splineDefiningCollectionPoint more than '3 points per segment (+1 final)' scheme: //->two to little for another segment if (closeGapFromEndToStart) { TryDrawQuadraticSegment_ofSplineCase_start_control1_end(is2D, i_startOfCurrSegment, 0, bezierPointCollection, GetPos, i_whileLoop, ref textPosition_hasAlreadyBeenAssigned, ref textPosition, ref splineHasAlreadyCommunicatedANullItem, color, width, straightSubDivisionsPerSegment, textSize, durationInSec, hiddenByNearerObjects); } else { text = "[ points collection length is 1 too long for the '3 points per segment (+1 final)' scheme
-> last point discarded]
" + text; } } else { if (i_startOfCurrSegment < lengthOfCollection) { //bezierPointCollection.length perfectly fits the '3 points per segment (+1 final)' scheme //-> no surplus points available if (closeGapFromEndToStart) { TryDrawCubicSegment_asGapCloserBetweenSplineEndAndStart(is2D, i_startOfCurrSegment, bezierPointCollection, GetPos, i_whileLoop, ref textPosition_hasAlreadyBeenAssigned, ref textPosition, ref splineHasAlreadyCommunicatedANullItem, color, width, straightSubDivisionsPerSegment, textSize, durationInSec, hiddenByNearerObjects); } } } } } return textPosition; } static void TryDrawCubicSegment_ofSplineCase_start_control1_control2_endIsNextStart(bool is2D, int i_ofSegmentStartPos_insideBezierPointsCollection, int i_ofSegmentEndPos_insideBezierPointsCollection, BezierPointCollection bezierPointCollection, FlexibleGetPosAtIndex GetPos, int i_whileLoop, ref bool textPosition_hasAlreadyBeenAssigned, ref Vector3 textPosition, ref bool splineHasAlreadyCommunicatedANullItem, Color color, float width, int straightSubDivisionsPerSegment, float textSize, float durationInSec, bool hiddenByNearerObjects) { Vector3 fallbackPositionOfSegment = Vector3.zero; bool fallbackPositionOfSegment_hasAlreadyBeenAssigned = false; bool oneOfTheSegmentPointsIsUndefined_becauseCollectionItemIsNullOrInvalid = false; Vector3 startPosition = TryGetPosFromBezierPointCollection(out bool startPosItemIsNull, bezierPointCollection, GetPos, i_ofSegmentStartPos_insideBezierPointsCollection, ref oneOfTheSegmentPointsIsUndefined_becauseCollectionItemIsNullOrInvalid); TryAssignFallbackAndTextPositions(startPosItemIsNull, startPosition, ref fallbackPositionOfSegment, ref fallbackPositionOfSegment_hasAlreadyBeenAssigned, ref textPosition, ref textPosition_hasAlreadyBeenAssigned); Vector3 controlPosOfStartDirection = TryGetPosFromBezierPointCollection(bezierPointCollection, GetPos, i_ofSegmentStartPos_insideBezierPointsCollection + 1, ref oneOfTheSegmentPointsIsUndefined_becauseCollectionItemIsNullOrInvalid); Vector3 controlPosOfEndDirection = TryGetPosFromBezierPointCollection(bezierPointCollection, GetPos, i_ofSegmentStartPos_insideBezierPointsCollection + 2, ref oneOfTheSegmentPointsIsUndefined_becauseCollectionItemIsNullOrInvalid); Vector3 endPosition = TryGetPosFromBezierPointCollection(out bool endPosItemIsNull, bezierPointCollection, GetPos, i_ofSegmentEndPos_insideBezierPointsCollection, ref oneOfTheSegmentPointsIsUndefined_becauseCollectionItemIsNullOrInvalid); TryAssignFallbackAndTextPositions(endPosItemIsNull, endPosition, ref fallbackPositionOfSegment, ref fallbackPositionOfSegment_hasAlreadyBeenAssigned, ref textPosition, ref textPosition_hasAlreadyBeenAssigned); TryDrawCubicBezierSegment(is2D, startPosition, endPosition, controlPosOfStartDirection, controlPosOfEndDirection, oneOfTheSegmentPointsIsUndefined_becauseCollectionItemIsNullOrInvalid, ref splineHasAlreadyCommunicatedANullItem, i_whileLoop, fallbackPositionOfSegment_hasAlreadyBeenAssigned, fallbackPositionOfSegment, color, width, straightSubDivisionsPerSegment, textSize, durationInSec, hiddenByNearerObjects); } static void TryDrawQuadraticSegment_ofSplineCase_start_control1_end(bool is2D, int i_ofSegmentStartPos_insideBezierPointsCollection, int i_ofSegmentEndPos_insideBezierPointsCollection, BezierPointCollection bezierPointCollection, FlexibleGetPosAtIndex GetPos, int i_whileLoop, ref bool textPosition_hasAlreadyBeenAssigned, ref Vector3 textPosition, ref bool splineHasAlreadyCommunicatedANullItem, Color color, float width, int straightSubDivisionsPerSegment, float textSize, float durationInSec, bool hiddenByNearerObjects) { Vector3 fallbackPositionOfSegment = Vector3.zero; bool fallbackPositionOfSegment_hasAlreadyBeenAssigned = false; bool oneOfTheSegmentPointsIsUndefined_becauseCollectionItemIsNullOrInvalid = false; Vector3 startPosition = TryGetPosFromBezierPointCollection(out bool startPosItemIsNullOrInvalid, bezierPointCollection, GetPos, i_ofSegmentStartPos_insideBezierPointsCollection, ref oneOfTheSegmentPointsIsUndefined_becauseCollectionItemIsNullOrInvalid); TryAssignFallbackAndTextPositions(startPosItemIsNullOrInvalid, startPosition, ref fallbackPositionOfSegment, ref fallbackPositionOfSegment_hasAlreadyBeenAssigned, ref textPosition, ref textPosition_hasAlreadyBeenAssigned); Vector3 controlPosInBetween = TryGetPosFromBezierPointCollection(bezierPointCollection, GetPos, i_ofSegmentStartPos_insideBezierPointsCollection + 1, ref oneOfTheSegmentPointsIsUndefined_becauseCollectionItemIsNullOrInvalid); Vector3 endPosition = TryGetPosFromBezierPointCollection(out bool endPosItemIsNullOrInvalid, bezierPointCollection, GetPos, i_ofSegmentEndPos_insideBezierPointsCollection, ref oneOfTheSegmentPointsIsUndefined_becauseCollectionItemIsNullOrInvalid); TryAssignFallbackAndTextPositions(endPosItemIsNullOrInvalid, endPosition, ref fallbackPositionOfSegment, ref fallbackPositionOfSegment_hasAlreadyBeenAssigned, ref textPosition, ref textPosition_hasAlreadyBeenAssigned); TryDrawQuadraticBezierSegment(is2D, startPosition, endPosition, controlPosInBetween, oneOfTheSegmentPointsIsUndefined_becauseCollectionItemIsNullOrInvalid, ref splineHasAlreadyCommunicatedANullItem, i_whileLoop, fallbackPositionOfSegment_hasAlreadyBeenAssigned, fallbackPositionOfSegment, color, width, straightSubDivisionsPerSegment, textSize, durationInSec, hiddenByNearerObjects); } static void TryDrawCubicSegment_asGapCloserBetweenSplineEndAndStart(bool is2D, int i_lastSlotOfBezierPointsCollection, BezierPointCollection bezierPointCollection, FlexibleGetPosAtIndex GetPos, int i_whileLoop, ref bool textPosition_hasAlreadyBeenAssigned, ref Vector3 textPosition, ref bool splineHasAlreadyCommunicatedANullItem, Color color, float width, int straightSubDivisionsPerSegment, float textSize, float durationInSec, bool hiddenByNearerObjects) { Vector3 fallbackPositionOfSegment = Vector3.zero; bool fallbackPositionOfSegment_hasAlreadyBeenAssigned = false; bool oneOfTheSegmentPointsIsUndefined_becauseCollectionItemIsNullOrInvalid = false; Vector3 gapClosingSegmentsStartPosition_isSplineEndPos = TryGetPosFromBezierPointCollection(out bool segmentsStartPosItemIsNull, bezierPointCollection, GetPos, i_lastSlotOfBezierPointsCollection, ref oneOfTheSegmentPointsIsUndefined_becauseCollectionItemIsNullOrInvalid); TryAssignFallbackAndTextPositions(segmentsStartPosItemIsNull, gapClosingSegmentsStartPosition_isSplineEndPos, ref fallbackPositionOfSegment, ref fallbackPositionOfSegment_hasAlreadyBeenAssigned, ref textPosition, ref textPosition_hasAlreadyBeenAssigned); Vector3 backwardControlPosOfSplinesEndPos = TryGetPosFromBezierPointCollection(out bool backwardControlPosOfSplinesEndPos_isNull, bezierPointCollection, GetPos, i_lastSlotOfBezierPointsCollection - 1, ref oneOfTheSegmentPointsIsUndefined_becauseCollectionItemIsNullOrInvalid); Vector3 controlPosOfSegmentStartDirection = Vector3.zero; if (backwardControlPosOfSplinesEndPos_isNull == false) { Vector3 splinesEndPos_toHisBackwardControlPos = backwardControlPosOfSplinesEndPos - gapClosingSegmentsStartPosition_isSplineEndPos; controlPosOfSegmentStartDirection = gapClosingSegmentsStartPosition_isSplineEndPos - splinesEndPos_toHisBackwardControlPos; } Vector3 gapClosingSegmentsEndPosition_isSplineStartPos = TryGetPosFromBezierPointCollection(out bool segmentsEndPosItemIsNull, bezierPointCollection, GetPos, 0, ref oneOfTheSegmentPointsIsUndefined_becauseCollectionItemIsNullOrInvalid); TryAssignFallbackAndTextPositions(segmentsEndPosItemIsNull, gapClosingSegmentsEndPosition_isSplineStartPos, ref fallbackPositionOfSegment, ref fallbackPositionOfSegment_hasAlreadyBeenAssigned, ref textPosition, ref textPosition_hasAlreadyBeenAssigned); Vector3 forwardControlPosOfSplinesStartPos = TryGetPosFromBezierPointCollection(out bool forwardControlPosOfSplinesStartPos_isNull, bezierPointCollection, GetPos, 1, ref oneOfTheSegmentPointsIsUndefined_becauseCollectionItemIsNullOrInvalid); Vector3 controlPosOfSegmentEndDirection = Vector3.zero; if (forwardControlPosOfSplinesStartPos_isNull == false) { Vector3 splinesStartPos_toHisForwardControlPos = forwardControlPosOfSplinesStartPos - gapClosingSegmentsEndPosition_isSplineStartPos; controlPosOfSegmentEndDirection = gapClosingSegmentsEndPosition_isSplineStartPos - splinesStartPos_toHisForwardControlPos; } TryDrawCubicBezierSegment(is2D, gapClosingSegmentsStartPosition_isSplineEndPos, gapClosingSegmentsEndPosition_isSplineStartPos, controlPosOfSegmentStartDirection, controlPosOfSegmentEndDirection, oneOfTheSegmentPointsIsUndefined_becauseCollectionItemIsNullOrInvalid, ref splineHasAlreadyCommunicatedANullItem, i_whileLoop, fallbackPositionOfSegment_hasAlreadyBeenAssigned, fallbackPositionOfSegment, color, width, straightSubDivisionsPerSegment, textSize, durationInSec, hiddenByNearerObjects); } static Vector3 DrawSpline_case_start_control1_endIsNextStart(bool is2D, out bool textPosition_hasAlreadyBeenAssigned, ref string text, BezierPointCollection bezierPointCollection, FlexibleGetPosAtIndex GetPos, int lengthOfCollection, Color color, DrawBasics.BezierPosInterpretation interpretationOfPointsCollection, float width, bool closeGapFromEndToStart, int straightSubDivisionsPerSegment, float textSize, float durationInSec, bool hiddenByNearerObjects) { textPosition_hasAlreadyBeenAssigned = false; Vector3 textPosition = Vector3.zero; if (lengthOfCollection < 3) { Debug.LogError("Bezier spline with BezierPosInterpretation of '" + interpretationOfPointsCollection + "' needs at least 3 control points, but the specified collection has only " + lengthOfCollection + " -> drawing skipped."); } else { bool splineHasAlreadyCommunicatedANullItem = false; //preventing log spam and many drawn lines (for multiple fallback texts) int i_startOfCurrSegment = 0; int i_endOfCurrSegment = i_startOfCurrSegment + 2; int maxNumberOfWhileLoops = 10000; //prevent freeze/endless loops int i_whileLoop = 0; while (i_endOfCurrSegment < lengthOfCollection) { TryDrawQuadraticSegment_ofSplineCase_start_control1_end(is2D, i_startOfCurrSegment, i_endOfCurrSegment, bezierPointCollection, GetPos, i_whileLoop, ref textPosition_hasAlreadyBeenAssigned, ref textPosition, ref splineHasAlreadyCommunicatedANullItem, color, width, straightSubDivisionsPerSegment, textSize, durationInSec, hiddenByNearerObjects); i_startOfCurrSegment = i_endOfCurrSegment; i_endOfCurrSegment = i_startOfCurrSegment + 2; i_whileLoop++; if (i_whileLoop > maxNumberOfWhileLoops) { Debug.LogError("Too many Bezier Segments (more than " + maxNumberOfWhileLoops + "). Drawing aborted."); break; } } if ((i_startOfCurrSegment + 1) < lengthOfCollection) { //one splineDefiningCollectionPoint more than '2 points per segment (+1 final)' scheme: //->one to little for another segment if (closeGapFromEndToStart) { TryDrawQuadraticSegment_ofSplineCase_start_control1_end(is2D, i_startOfCurrSegment, 0, bezierPointCollection, GetPos, i_whileLoop, ref textPosition_hasAlreadyBeenAssigned, ref textPosition, ref splineHasAlreadyCommunicatedANullItem, color, width, straightSubDivisionsPerSegment, textSize, durationInSec, hiddenByNearerObjects); } else { text = "[ points collection length is 1 too long for the '2 points per segment (+1 final)' scheme
-> last point discarded]
" + text; } } else { if (i_startOfCurrSegment < lengthOfCollection) { //bezierPointCollection.length perfectly fits the '3 points per segment (+1 final)' scheme //-> no surplus points available if (closeGapFromEndToStart) { TryDrawQuadraticSegment_asGapCloserBetweenSplineEndAndStart(is2D, i_startOfCurrSegment, bezierPointCollection, GetPos, i_whileLoop, ref textPosition_hasAlreadyBeenAssigned, ref textPosition, ref splineHasAlreadyCommunicatedANullItem, color, width, straightSubDivisionsPerSegment, textSize, durationInSec, hiddenByNearerObjects); } } } } return textPosition; } static void TryDrawQuadraticSegment_asGapCloserBetweenSplineEndAndStart(bool is2D, int i_lastSlotOfBezierPointsCollection, BezierPointCollection bezierPointCollection, FlexibleGetPosAtIndex GetPos, int i_whileLoop, ref bool textPosition_hasAlreadyBeenAssigned, ref Vector3 textPosition, ref bool splineHasAlreadyCommunicatedANullItem, Color color, float width, int straightSubDivisionsPerSegment, float textSize, float durationInSec, bool hiddenByNearerObjects) { Vector3 fallbackPositionOfSegment = Vector3.zero; bool fallbackPositionOfSegment_hasAlreadyBeenAssigned = false; bool oneOfTheSegmentPointsIsUndefined_becauseCollectionItemIsNullOrInvalid = false; Vector3 gapClosingSegmentsStartPosition_isSplineEndPos = TryGetPosFromBezierPointCollection(out bool segmentsStartPosItemIsNull, bezierPointCollection, GetPos, i_lastSlotOfBezierPointsCollection, ref oneOfTheSegmentPointsIsUndefined_becauseCollectionItemIsNullOrInvalid); TryAssignFallbackAndTextPositions(segmentsStartPosItemIsNull, gapClosingSegmentsStartPosition_isSplineEndPos, ref fallbackPositionOfSegment, ref fallbackPositionOfSegment_hasAlreadyBeenAssigned, ref textPosition, ref textPosition_hasAlreadyBeenAssigned); Vector3 backwardControlPosOfSplinesEndPos = TryGetPosFromBezierPointCollection(out bool backwardControlPosOfSplinesEndPos_isNull, bezierPointCollection, GetPos, i_lastSlotOfBezierPointsCollection - 1, ref oneOfTheSegmentPointsIsUndefined_becauseCollectionItemIsNullOrInvalid); Vector3 controlPosOfSegmentStartDirection = Vector3.zero; if (backwardControlPosOfSplinesEndPos_isNull == false) { Vector3 splinesEndPos_toHisBackwardControlPos = backwardControlPosOfSplinesEndPos - gapClosingSegmentsStartPosition_isSplineEndPos; controlPosOfSegmentStartDirection = gapClosingSegmentsStartPosition_isSplineEndPos - splinesEndPos_toHisBackwardControlPos; } Vector3 gapClosingSegmentsEndPosition_isSplineStartPos = TryGetPosFromBezierPointCollection(out bool segmentsEndPosItemIsNull, bezierPointCollection, GetPos, 0, ref oneOfTheSegmentPointsIsUndefined_becauseCollectionItemIsNullOrInvalid); TryAssignFallbackAndTextPositions(segmentsEndPosItemIsNull, gapClosingSegmentsEndPosition_isSplineStartPos, ref fallbackPositionOfSegment, ref fallbackPositionOfSegment_hasAlreadyBeenAssigned, ref textPosition, ref textPosition_hasAlreadyBeenAssigned); Vector3 forwardControlPosOfSplinesStartPos = TryGetPosFromBezierPointCollection(bezierPointCollection, GetPos, 1, ref oneOfTheSegmentPointsIsUndefined_becauseCollectionItemIsNullOrInvalid); TryDrawQuadraticBezierSegment(is2D, gapClosingSegmentsStartPosition_isSplineEndPos, gapClosingSegmentsEndPosition_isSplineStartPos, controlPosOfSegmentStartDirection, oneOfTheSegmentPointsIsUndefined_becauseCollectionItemIsNullOrInvalid, ref splineHasAlreadyCommunicatedANullItem, i_whileLoop, fallbackPositionOfSegment_hasAlreadyBeenAssigned, fallbackPositionOfSegment, color, width, straightSubDivisionsPerSegment, textSize, durationInSec, hiddenByNearerObjects); } static Vector3 DrawSpline_case_onlySegmentStartPoints_backwardForwardIsAligned(bool is2D, out bool textPosition_hasAlreadyBeenAssigned, BezierPointCollection bezierPointCollection, FlexibleGetPosAtIndex GetPos, FlexibleGetDirectionControlPosOfTransform GetForwardControlPos, FlexibleGetDirectionControlPosOfTransform GetBackwardControlPos, int lengthOfCollection, Color color, DrawBasics.BezierPosInterpretation interpretationOfPointsCollection, float width, bool closeGapFromEndToStart, int straightSubDivisionsPerSegment, float textSize, float durationInSec, bool hiddenByNearerObjects) { textPosition_hasAlreadyBeenAssigned = false; Vector3 textPosition = Vector3.zero; if (lengthOfCollection < 2) { Debug.LogError("Bezier spline with BezierPosInterpretation of '" + interpretationOfPointsCollection + "' needs at least 2 control points, but the specified collection has only " + lengthOfCollection + " -> drawing skipped."); } else { bool splineHasAlreadyCommunicatedANullItem = false; //preventing log spam and many drawn lines (for multiple fallback texts) for (int i_segmentEndPos = 1; i_segmentEndPos < lengthOfCollection; i_segmentEndPos++) { int i_segmentStartPos = i_segmentEndPos - 1; TryDrawSegment_ofSplineCase_onlySegmentStartPoints_backwardForwardIsAligned(is2D, i_segmentStartPos, i_segmentEndPos, bezierPointCollection, GetPos, GetForwardControlPos, GetBackwardControlPos, ref textPosition_hasAlreadyBeenAssigned, ref textPosition, ref splineHasAlreadyCommunicatedANullItem, color, width, straightSubDivisionsPerSegment, textSize, durationInSec, hiddenByNearerObjects); } if (closeGapFromEndToStart) { TryDrawSegment_ofSplineCase_onlySegmentStartPoints_backwardForwardIsAligned(is2D, lengthOfCollection - 1, 0, bezierPointCollection, GetPos, GetForwardControlPos, GetBackwardControlPos, ref textPosition_hasAlreadyBeenAssigned, ref textPosition, ref splineHasAlreadyCommunicatedANullItem, color, width, straightSubDivisionsPerSegment, textSize, durationInSec, hiddenByNearerObjects); } } return textPosition; } static void TryDrawSegment_ofSplineCase_onlySegmentStartPoints_backwardForwardIsAligned(bool is2D, int i_segmentStartPos, int i_segmentEndPos, BezierPointCollection bezierPointCollection, FlexibleGetPosAtIndex GetPos, FlexibleGetDirectionControlPosOfTransform GetForwardControlPos, FlexibleGetDirectionControlPosOfTransform GetBackwardControlPos, ref bool textPosition_hasAlreadyBeenAssigned, ref Vector3 textPosition, ref bool splineHasAlreadyCommunicatedANullItem, Color color, float width, int straightSubDivisionsPerSegment, float textSize, float durationInSec, bool hiddenByNearerObjects) { Vector3 fallbackPositionOfSegment = Vector3.zero; Vector3 controlPosOfEndDirection = Vector3.zero; Vector3 controlPosOfStartDirection = Vector3.zero; bool fallbackPositionOfSegment_hasAlreadyBeenAssigned = false; bool oneOfTheSegmentPointsIsUndefined_becauseCollectionItemIsNullOrInvalid = false; Vector3 startPosition = TryGetPosFromBezierPointCollection(out bool startPosItemIsNullOrInvalid, bezierPointCollection, GetPos, i_segmentStartPos, ref oneOfTheSegmentPointsIsUndefined_becauseCollectionItemIsNullOrInvalid); TryAssignFallbackAndTextPositions(startPosItemIsNullOrInvalid, startPosition, ref fallbackPositionOfSegment, ref fallbackPositionOfSegment_hasAlreadyBeenAssigned, ref textPosition, ref textPosition_hasAlreadyBeenAssigned); if (startPosItemIsNullOrInvalid == false) { controlPosOfStartDirection = GetForwardControlPos(bezierPointCollection, i_segmentStartPos); } Vector3 endPosition = TryGetPosFromBezierPointCollection(out bool endPosItemIsNullOrInvalid, bezierPointCollection, GetPos, i_segmentEndPos, ref oneOfTheSegmentPointsIsUndefined_becauseCollectionItemIsNullOrInvalid); TryAssignFallbackAndTextPositions(endPosItemIsNullOrInvalid, endPosition, ref fallbackPositionOfSegment, ref fallbackPositionOfSegment_hasAlreadyBeenAssigned, ref textPosition, ref textPosition_hasAlreadyBeenAssigned); if (endPosItemIsNullOrInvalid == false) { controlPosOfEndDirection = GetBackwardControlPos(bezierPointCollection, i_segmentEndPos); } TryDrawCubicBezierSegment(is2D, startPosition, endPosition, controlPosOfStartDirection, controlPosOfEndDirection, oneOfTheSegmentPointsIsUndefined_becauseCollectionItemIsNullOrInvalid, ref splineHasAlreadyCommunicatedANullItem, i_segmentStartPos, fallbackPositionOfSegment_hasAlreadyBeenAssigned, fallbackPositionOfSegment, color, width, straightSubDivisionsPerSegment, textSize, durationInSec, hiddenByNearerObjects); } static Vector3 DrawSpline_case_onlySegmentStartPoints_backwardForwardIsMirrored(bool is2D, out bool textPosition_hasAlreadyBeenAssigned, BezierPointCollection bezierPointCollection, FlexibleGetPosAtIndex GetPos, FlexibleGetDirectionControlPosOfTransform GetForwardControlPos, int lengthOfCollection, Color color, DrawBasics.BezierPosInterpretation interpretationOfPointsCollection, float width, bool closeGapFromEndToStart, int straightSubDivisionsPerSegment, float textSize, float durationInSec, bool hiddenByNearerObjects) { textPosition_hasAlreadyBeenAssigned = false; Vector3 textPosition = Vector3.zero; if (lengthOfCollection < 2) { Debug.LogError("Bezier spline with BezierPosInterpretation of '" + interpretationOfPointsCollection + "' needs at least 2 control points, but the specified collection has only " + lengthOfCollection + " -> drawing skipped."); } else { bool splineHasAlreadyCommunicatedANullItem = false; //preventing log spam and many drawn lines (for multiple fallback texts) for (int i_segmentEndPos = 1; i_segmentEndPos < lengthOfCollection; i_segmentEndPos++) { int i_segmentStartPos = i_segmentEndPos - 1; TryDrawSegment_ofSplineCase_onlySegmentStartPoints_backwardForwardIsMirrored(is2D, i_segmentStartPos, i_segmentEndPos, bezierPointCollection, GetPos, GetForwardControlPos, ref textPosition_hasAlreadyBeenAssigned, ref textPosition, ref splineHasAlreadyCommunicatedANullItem, color, width, straightSubDivisionsPerSegment, textSize, durationInSec, hiddenByNearerObjects); } if (closeGapFromEndToStart) { TryDrawSegment_ofSplineCase_onlySegmentStartPoints_backwardForwardIsMirrored(is2D, lengthOfCollection - 1, 0, bezierPointCollection, GetPos, GetForwardControlPos, ref textPosition_hasAlreadyBeenAssigned, ref textPosition, ref splineHasAlreadyCommunicatedANullItem, color, width, straightSubDivisionsPerSegment, textSize, durationInSec, hiddenByNearerObjects); } } return textPosition; } static void TryDrawSegment_ofSplineCase_onlySegmentStartPoints_backwardForwardIsMirrored(bool is2D, int i_segmentStartPos, int i_segmentEndPos, BezierPointCollection bezierPointCollection, FlexibleGetPosAtIndex GetPos, FlexibleGetDirectionControlPosOfTransform GetForwardControlPos, ref bool textPosition_hasAlreadyBeenAssigned, ref Vector3 textPosition, ref bool splineHasAlreadyCommunicatedANullItem, Color color, float width, int straightSubDivisionsPerSegment, float textSize, float durationInSec, bool hiddenByNearerObjects) { Vector3 fallbackPositionOfSegment = Vector3.zero; Vector3 controlPosOfEndDirection = Vector3.zero; Vector3 controlPosOfStartDirection = Vector3.zero; bool fallbackPositionOfSegment_hasAlreadyBeenAssigned = false; bool oneOfTheSegmentPointsIsUndefined_becauseCollectionItemIsNullOrInvalid = false; Vector3 startPosition = TryGetPosFromBezierPointCollection(out bool startPosItemIsNullOrInvalid, bezierPointCollection, GetPos, i_segmentStartPos, ref oneOfTheSegmentPointsIsUndefined_becauseCollectionItemIsNullOrInvalid); TryAssignFallbackAndTextPositions(startPosItemIsNullOrInvalid, startPosition, ref fallbackPositionOfSegment, ref fallbackPositionOfSegment_hasAlreadyBeenAssigned, ref textPosition, ref textPosition_hasAlreadyBeenAssigned); if (startPosItemIsNullOrInvalid == false) { controlPosOfStartDirection = GetForwardControlPos(bezierPointCollection, i_segmentStartPos); } Vector3 endPosition = TryGetPosFromBezierPointCollection(out bool endPosItemIsNullOrInvalid, bezierPointCollection, GetPos, i_segmentEndPos, ref oneOfTheSegmentPointsIsUndefined_becauseCollectionItemIsNullOrInvalid); TryAssignFallbackAndTextPositions(endPosItemIsNullOrInvalid, endPosition, ref fallbackPositionOfSegment, ref fallbackPositionOfSegment_hasAlreadyBeenAssigned, ref textPosition, ref textPosition_hasAlreadyBeenAssigned); if (endPosItemIsNullOrInvalid == false) { Vector3 controlPosOfEndDirection_forward = GetForwardControlPos(bezierPointCollection, i_segmentEndPos); Vector3 endPos_to_endPosForwardControlPos = controlPosOfEndDirection_forward - endPosition; controlPosOfEndDirection = endPosition - endPos_to_endPosForwardControlPos; } TryDrawCubicBezierSegment(is2D, startPosition, endPosition, controlPosOfStartDirection, controlPosOfEndDirection, oneOfTheSegmentPointsIsUndefined_becauseCollectionItemIsNullOrInvalid, ref splineHasAlreadyCommunicatedANullItem, i_segmentStartPos, fallbackPositionOfSegment_hasAlreadyBeenAssigned, fallbackPositionOfSegment, color, width, straightSubDivisionsPerSegment, textSize, durationInSec, hiddenByNearerObjects); } static Vector3 DrawSpline_case_onlySegmentStartPoints_backwardForwardIsKinked(bool is2D, out bool textPosition_hasAlreadyBeenAssigned, BezierPointCollection bezierPointCollection, FlexibleGetPosAtIndex GetPos, FlexibleGetDirectionControlPosOfTransform GetForwardControlPos, int lengthOfCollection, Color color, DrawBasics.BezierPosInterpretation interpretationOfPointsCollection, float width, bool closeGapFromEndToStart, int straightSubDivisionsPerSegment, float textSize, float durationInSec, bool hiddenByNearerObjects) { textPosition_hasAlreadyBeenAssigned = false; Vector3 textPosition = Vector3.zero; if (lengthOfCollection < 2) { Debug.LogError("Bezier spline with BezierPosInterpretation of '" + interpretationOfPointsCollection + "' needs at least 2 control points, but the specified collection has only " + lengthOfCollection + " -> drawing skipped."); } else { bool splineHasAlreadyCommunicatedANullItem = false; //preventing log spam and many drawn lines (for multiple fallback texts) for (int i_segmentEndPos = 1; i_segmentEndPos < lengthOfCollection; i_segmentEndPos++) { int i_segmentStartPos = i_segmentEndPos - 1; TryDrawSegment_ofSplineCase_onlySegmentStartPoints_backwardForwardIsKinked(is2D, i_segmentStartPos, i_segmentEndPos, bezierPointCollection, GetPos, GetForwardControlPos, ref textPosition_hasAlreadyBeenAssigned, ref textPosition, ref splineHasAlreadyCommunicatedANullItem, color, width, straightSubDivisionsPerSegment, textSize, durationInSec, hiddenByNearerObjects); } if (closeGapFromEndToStart) { TryDrawSegment_ofSplineCase_onlySegmentStartPoints_backwardForwardIsKinked(is2D, lengthOfCollection - 1, 0, bezierPointCollection, GetPos, GetForwardControlPos, ref textPosition_hasAlreadyBeenAssigned, ref textPosition, ref splineHasAlreadyCommunicatedANullItem, color, width, straightSubDivisionsPerSegment, textSize, durationInSec, hiddenByNearerObjects); } } return textPosition; } static void TryDrawSegment_ofSplineCase_onlySegmentStartPoints_backwardForwardIsKinked(bool is2D, int i_segmentStartPos, int i_segmentEndPos, BezierPointCollection bezierPointCollection, FlexibleGetPosAtIndex GetPos, FlexibleGetDirectionControlPosOfTransform GetForwardControlPos, ref bool textPosition_hasAlreadyBeenAssigned, ref Vector3 textPosition, ref bool splineHasAlreadyCommunicatedANullItem, Color color, float width, int straightSubDivisionsPerSegment, float textSize, float durationInSec, bool hiddenByNearerObjects) { Vector3 fallbackPositionOfSegment = Vector3.zero; Vector3 controlPosInBetween = Vector3.zero; bool fallbackPositionOfSegment_hasAlreadyBeenAssigned = false; bool oneOfTheSegmentPointsIsUndefined_becauseCollectionItemIsNullOrInvalid = false; Vector3 startPosition = TryGetPosFromBezierPointCollection(out bool startPosItemIsNullOrInvalid, bezierPointCollection, GetPos, i_segmentStartPos, ref oneOfTheSegmentPointsIsUndefined_becauseCollectionItemIsNullOrInvalid); TryAssignFallbackAndTextPositions(startPosItemIsNullOrInvalid, startPosition, ref fallbackPositionOfSegment, ref fallbackPositionOfSegment_hasAlreadyBeenAssigned, ref textPosition, ref textPosition_hasAlreadyBeenAssigned); if (startPosItemIsNullOrInvalid == false) { controlPosInBetween = GetForwardControlPos(bezierPointCollection, i_segmentStartPos); } Vector3 endPosition = TryGetPosFromBezierPointCollection(out bool endPosItemIsNullOrInvalid, bezierPointCollection, GetPos, i_segmentEndPos, ref oneOfTheSegmentPointsIsUndefined_becauseCollectionItemIsNullOrInvalid); TryAssignFallbackAndTextPositions(endPosItemIsNullOrInvalid, endPosition, ref fallbackPositionOfSegment, ref fallbackPositionOfSegment_hasAlreadyBeenAssigned, ref textPosition, ref textPosition_hasAlreadyBeenAssigned); TryDrawQuadraticBezierSegment(is2D, startPosition, endPosition, controlPosInBetween, oneOfTheSegmentPointsIsUndefined_becauseCollectionItemIsNullOrInvalid, ref splineHasAlreadyCommunicatedANullItem, i_segmentStartPos, fallbackPositionOfSegment_hasAlreadyBeenAssigned, fallbackPositionOfSegment, color, width, straightSubDivisionsPerSegment, textSize, durationInSec, hiddenByNearerObjects); } static Vector3 TryGetPosFromBezierPointCollection(BezierPointCollection bezierPointCollection, FlexibleGetPosAtIndex GetPos, int i_insideBezierPointCollection_whereToTryObtain, ref bool oneOfTheSegmentPointsIsUndefined_becauseCollectionItemIsNullOrInvalid) { return TryGetPosFromBezierPointCollection(out bool unused, bezierPointCollection, GetPos, i_insideBezierPointCollection_whereToTryObtain, ref oneOfTheSegmentPointsIsUndefined_becauseCollectionItemIsNullOrInvalid); } static Vector3 TryGetPosFromBezierPointCollection(out bool collectionItemIsNullOrInvalid, BezierPointCollection bezierPointCollection, FlexibleGetPosAtIndex GetPos, int i_insideBezierPointCollection_whereToTryObtain, ref bool oneOfTheSegmentPointsIsUndefined_becauseCollectionItemIsNullOrInvalid) { Vector3 obtainedPos = GetPos(bezierPointCollection, i_insideBezierPointCollection_whereToTryObtain, out collectionItemIsNullOrInvalid); if (collectionItemIsNullOrInvalid) { oneOfTheSegmentPointsIsUndefined_becauseCollectionItemIsNullOrInvalid = true; } return obtainedPos; } static void TryAssignFallbackAndTextPositions(bool collectionItemIsNullOrInvalid, Vector3 position, ref Vector3 fallbackPositionOfSegment, ref bool fallbackPositionOfSegment_hasAlreadyBeenAssigned, ref Vector3 textPosition, ref bool textPosition_hasAlreadyBeenAssigned) { if (collectionItemIsNullOrInvalid == false) { AssignFallbackPositionOfSegment(ref fallbackPositionOfSegment, ref fallbackPositionOfSegment_hasAlreadyBeenAssigned, position); AssignTextPosition(ref textPosition, ref textPosition_hasAlreadyBeenAssigned, position); } } static void AssignFallbackPositionOfSegment(ref Vector3 fallbackPositionOfSegment, ref bool fallbackPositionOfSegment_hasAlreadyBeenAssigned, Vector3 fallbackPositionOfSegmentCandidate) { if (fallbackPositionOfSegment_hasAlreadyBeenAssigned == false) { fallbackPositionOfSegment = fallbackPositionOfSegmentCandidate; fallbackPositionOfSegment_hasAlreadyBeenAssigned = true; } } static void AssignTextPosition(ref Vector3 textPosition, ref bool textPosition_hasAlreadyBeenAssigned, Vector3 textPositionCandidate) { if (textPosition_hasAlreadyBeenAssigned == false) { textPosition = textPositionCandidate; textPosition_hasAlreadyBeenAssigned = true; } } static void TryDrawCubicBezierSegment(bool is2D, Vector3 startPosition, Vector3 endPosition, Vector3 controlPosOfStartDirection, Vector3 controlPosOfEndDirection, bool oneOfTheSegmentPointsIsUndefined_becauseCollectionItemIsNullOrInvalid, ref bool splineHasAlreadyCommunicatedANullItem, int i_segment_usedForErrorText, bool fallbackPositionOfSegment_hasAlreadyBeenAssigned, Vector3 fallbackPositionOfSegment, Color color, float width, int straightSubDivisionsPerSegment, float textSize, float durationInSec, bool hiddenByNearerObjects) { if (oneOfTheSegmentPointsIsUndefined_becauseCollectionItemIsNullOrInvalid) { CommunicateMissingArrayItem(ref splineHasAlreadyCommunicatedANullItem, i_segment_usedForErrorText, fallbackPositionOfSegment_hasAlreadyBeenAssigned, fallbackPositionOfSegment, color, textSize, durationInSec, hiddenByNearerObjects); } else { BezierSegmentCubic(is2D, startPosition, endPosition, controlPosOfStartDirection, controlPosOfEndDirection, color, null, width, straightSubDivisionsPerSegment, 0.1f, false, durationInSec, hiddenByNearerObjects); } } static void TryDrawQuadraticBezierSegment(bool is2D, Vector3 startPosition, Vector3 endPosition, Vector3 controlPosInBetween, bool oneOfTheSegmentPointsIsUndefined_becauseCollectionItemIsNullOrInvalid, ref bool splineHasAlreadyCommunicatedANullItem, int i_segment_usedForErrorText, bool fallbackPositionOfSegment_hasAlreadyBeenAssigned, Vector3 fallbackPositionOfSegment, Color color, float width, int straightSubDivisionsPerSegment, float textSize, float durationInSec, bool hiddenByNearerObjects) { if (oneOfTheSegmentPointsIsUndefined_becauseCollectionItemIsNullOrInvalid) { CommunicateMissingArrayItem(ref splineHasAlreadyCommunicatedANullItem, i_segment_usedForErrorText, fallbackPositionOfSegment_hasAlreadyBeenAssigned, fallbackPositionOfSegment, color, textSize, durationInSec, hiddenByNearerObjects); } else { BezierSegmentQuadratic(is2D, startPosition, endPosition, controlPosInBetween, color, null, width, straightSubDivisionsPerSegment, 0.1f, false, durationInSec, hiddenByNearerObjects); } } static void CommunicateMissingArrayItem(ref bool splineHasAlreadyCommunicatedANullItem, int i_segment_usedForErrorText, bool hasfallbackPositionOfSegment, Vector3 fallbackPositionOfSegment, Color color, float textSize, float durationInSec, bool hiddenByNearerObjects) { if (splineHasAlreadyCommunicatedANullItem == false) { if (hasfallbackPositionOfSegment) { UtilitiesDXXL_Text.WriteFramed("[ An item in points collection is null/invalid
-> skip drawing of bezier segment (i=" + i_segment_usedForErrorText + ")]", fallbackPositionOfSegment, color, textSize, default(Vector3), default(Vector3), DrawText.TextAnchorDXXL.UpperRight, DrawBasics.LineStyle.invisible, 0.0f, 0.0f, 0.02f, 0.0f, 0.0f, true, durationInSec, hiddenByNearerObjects); } else { Debug.LogError("An item in points collection is null/invalid -> skip drawing of bezier spline segment (i=" + i_segment_usedForErrorText + ")"); } } splineHasAlreadyCommunicatedANullItem = true; } } }