public SerializedCurvySpline(CurvySpline spline, CurvySerializationSpace space = CurvySerializationSpace.WorldSpline) { if (spline) { Name = spline.name; P = (space == CurvySerializationSpace.Self) ? spline.transform.localPosition : spline.transform.position; R = (space == CurvySerializationSpace.Self) ? spline.transform.localRotation.eulerAngles : spline.transform.rotation.eulerAngles; Interpolation = spline.Interpolation; Keep2D = spline.RestrictTo2D; Closed = spline.Closed; AutoEndTangents = spline.AutoEndTangents; Orientation = spline.Orientation; BzAutoDist = spline.AutoHandleDistance; CacheDensity = spline.CacheDensity; Pooling = spline.UsePooling; Threading = spline.UseThreading; CheckTForm = spline.CheckTransform; UpdateIn = spline.UpdateIn; ControlPoints = new SerializedCurvySplineSegment[spline.ControlPointCount]; for (int i = 0; i < spline.ControlPointCount; i++) { ControlPoints[i] = new SerializedCurvySplineSegment(spline.ControlPoints[i]); } } }
/// <summary> /// Sets Bezier Handles by interpolating between Control Points /// </summary> /// <param name="interpolation">the interpolation to use</param> /// <param name="offset">the offset in F (0..1)</param> /// <param name="freeMoveHandles">whether Handles should be moved individually</param> /// <param name="controlPoints">the Control Points to set the Handles for</param> public static void InterpolateBezierHandles(CurvyInterpolation interpolation, float offset, bool freeMoveHandles, params CurvySplineSegment[] controlPoints) { if (controlPoints.Length == 0) { return; } offset = UnityEngine.Mathf.Clamp01(offset); foreach (CurvySplineSegment cp in controlPoints) { cp.FreeHandles = freeMoveHandles; CurvySplineSegment other = cp.PreviousSegment; if (other) { cp.HandleInPosition = other.Interpolate(1 - offset, interpolation); } else { cp.HandleInPosition = cp.Interpolate(0, interpolation); } if (freeMoveHandles) { if (cp.IsValidSegment) { cp.HandleOutPosition = cp.Interpolate(offset, interpolation); } else { cp.HandleInPosition = UnityEngine.Vector3.zero; } } } controlPoints[0].Spline.Refresh(); }
/// <summary> /// Interpolates position for a local F /// </summary> /// <param name="localF">a local F in the range 0..1</param> /// <param name="interpolation">the interpolation to use</param> /// <returns>the interpolated position</returns> public Vector3 Interpolate(float localF, CurvyInterpolation interpolation) { localF = Mathf.Clamp01(localF); switch (interpolation) { case CurvyInterpolation.Bezier: return(CurvySpline.Bezier(HandleOutScaled, Transform.position, NextTransform.position, NextControlPoint.HandleInScaled, localF)); case CurvyInterpolation.CatmulRom: //return CurvySpline.CatmulRom(PreviousTransform.position, Transform.position, NextTransform.position, NextControlPoint.NextTransform.position, localF); return(CurvySpline.CatmulRom(GetPrevPosition(), Transform.position, GetNextPosition(), GetNextNextPosition(), localF)); case CurvyInterpolation.TCB: float t0 = StartTension; float t1 = EndTension; float c0 = StartContinuity; float c1 = EndContinuity; float b0 = StartBias; float b1 = EndBias; if (!OverrideGlobalTension) { t0 = t1 = Spline.Tension; } if (!OverrideGlobalContinuity) { c0 = c1 = Spline.Continuity; } if (!OverrideGlobalBias) { b0 = b1 = Spline.Bias; } return(CurvySpline.TCB(PreviousTransform.position, Transform.position, NextTransform.position, NextControlPoint.NextTransform.position, localF, t0, c0, b0, t1, c1, b1)); default: // LINEAR return(Vector3.Lerp(Transform.position, NextTransform.position, localF)); } }
/// <summary> /// Sets basic spline parameters /// </summary> protected void PrepareSpline(CurvyInterpolation interpolation, CurvyOrientation orientation = CurvyOrientation.Dynamic, int cachedensity = 50, bool closed = true) { #if UNITY_EDITOR if (!Application.isPlaying) { Undo.RecordObject(Spline, "Apply Shape"); } #endif Spline.Interpolation = interpolation; Spline.Orientation = orientation; Spline.CacheDensity = cachedensity; Spline.Closed = closed; Spline.RestrictTo2D = this is CurvyShape2D; }
CurvySpline CreateSpline(CurvyInterpolation type, int points, int granularity) { CurvySpline spl = CurvySpline.Create(); spl.Interpolation = type; spl.Granularity = granularity; spl.Closed = false; spl.ShowGizmos = false; spl.AutoEndTangents = true; for (int i = 0; i < points; i++) { spl.Add(null, false).Position = Random.insideUnitCircle * 10; } spl.RefreshImmediately(); return(spl); }
static void LoadRuntimeSettings() { if (!PlayerPrefs.HasKey("Curvy_MaxCachePPU")) { SaveRuntimeSettings(); } MaxCachePPU = DTUtility.GetPlayerPrefs <int>("Curvy_MaxCachePPU", MaxCachePPU); SceneViewResolution = DTUtility.GetPlayerPrefs <float>("Curvy_SceneViewResolution", SceneViewResolution); DefaultGizmoColor = DTUtility.GetPlayerPrefs <Color>("Curvy_DefaultGizmoColor", DefaultGizmoColor); DefaultGizmoSelectionColor = DTUtility.GetPlayerPrefs <Color>("Curvy_DefaultGizmoSelectionColor", DefaultGizmoColor); DefaultInterpolation = DTUtility.GetPlayerPrefs <CurvyInterpolation>("Curvy_DefaultInterpolation", DefaultInterpolation); GizmoControlPointSize = DTUtility.GetPlayerPrefs <float>("Curvy_ControlPointSize", GizmoControlPointSize); GizmoOrientationLength = DTUtility.GetPlayerPrefs <float>("Curvy_OrientationLength", GizmoOrientationLength); GizmoOrientationColor = DTUtility.GetPlayerPrefs <Color>("Curvy_OrientationColor", GizmoOrientationColor); Gizmos = DTUtility.GetPlayerPrefs <CurvySplineGizmos>("Curvy_Gizmos", Gizmos); SplineLayer = DTUtility.GetPlayerPrefs <int>("Curvy_SplineLayer", SplineLayer); }
public static void InterpolateBezierHandles(CurvyInterpolation interpolation, float offset, bool?freeMoveHandles, params CurvySplineSegment[] controlPoints) { if (controlPoints.Length == 0) { return; } offset = Mathf.Clamp01(offset); foreach (CurvySplineSegment cp in controlPoints) { bool movestate = freeMoveHandles.HasValue ? freeMoveHandles.Value : cp.FreeHandles; cp.FreeHandles = movestate; CurvySplineSegment other = cp.PreviousSegment; if (other) { cp.HandleIn = other.Interpolate(1 - offset, interpolation) - cp.transform.localPosition; } else { cp.HandleIn = cp.Interpolate(0, interpolation); } if (cp.FreeHandles) { if (cp.IsValidSegment) { cp.HandleOut = cp.Interpolate(offset, interpolation) - cp.transform.localPosition; } else { cp.HandleIn = Vector3.zero; } } } controlPoints[0].Spline.Refresh(); }
/// <summary> /// Interpolates position for a local F /// </summary> /// <param name="localF">a local F in the range 0..1</param> /// <param name="interpolation">the interpolation to use</param> /// <returns>the interpolated position</returns> public Vector3 Interpolate(float localF, CurvyInterpolation interpolation) { localF = Mathf.Clamp01(localF); switch (interpolation) { case CurvyInterpolation.Bezier: return CurvySpline.Bezier(HandleOutScaled,Transform.position, NextTransform.position, NextControlPoint.HandleInScaled, localF); case CurvyInterpolation.CatmulRom: //return CurvySpline.CatmulRom(PreviousTransform.position, Transform.position, NextTransform.position, NextControlPoint.NextTransform.position, localF); return CurvySpline.CatmulRom(GetPrevPosition(), Transform.position, GetNextPosition(), GetNextNextPosition(), localF); case CurvyInterpolation.TCB: float t0=StartTension;float t1=EndTension; float c0=StartContinuity;float c1=EndContinuity; float b0=StartBias;float b1=EndBias; if (!OverrideGlobalTension) t0 = t1 = Spline.Tension; if (!OverrideGlobalContinuity) c0 = c1 = Spline.Continuity; if (!OverrideGlobalBias) b0 = b1 = Spline.Bias; return CurvySpline.TCB(PreviousTransform.position, Transform.position, NextTransform.position, NextControlPoint.NextTransform.position, localF, t0, c0, b0, t1, c1, b1); default: // LINEAR return Vector3.Lerp(Transform.position, NextTransform.position, localF); } }
void OnGUI() { GUILayout.BeginVertical(GUI.skin.box); GUILayout.Label("Curvy offers various options to fine-tune performance vs. precision balance:"); // Interpolation GUILayout.BeginHorizontal(); GUILayout.Label("Interpolation: "); if (GUILayout.Toggle(mInterpolation == CurvyInterpolation.Linear, "Linear", GUI.skin.button)) { mInterpolation = CurvyInterpolation.Linear; } if (GUILayout.Toggle(mInterpolation == CurvyInterpolation.Bezier, "Bezier", GUI.skin.button)) { mInterpolation = CurvyInterpolation.Bezier; } if (GUILayout.Toggle(mInterpolation == CurvyInterpolation.CatmullRom, "CatmullRom", GUI.skin.button)) { mInterpolation = CurvyInterpolation.CatmullRom; } if (GUILayout.Toggle(mInterpolation == CurvyInterpolation.TCB, "TCB", GUI.skin.button)) { mInterpolation = CurvyInterpolation.TCB; } GUILayout.EndHorizontal(); // Orientation GUILayout.BeginHorizontal(); GUILayout.Label("Orientation: "); if (GUILayout.Toggle(mOrientation == CurvyOrientation.None, "None", GUI.skin.button)) { mOrientation = CurvyOrientation.None; } if (GUILayout.Toggle(mOrientation == CurvyOrientation.Static, "Static", GUI.skin.button)) { mOrientation = CurvyOrientation.Static; } if (GUILayout.Toggle(mOrientation == CurvyOrientation.Dynamic, "Dynamic", GUI.skin.button)) { mOrientation = CurvyOrientation.Dynamic; } GUILayout.EndHorizontal(); // CP-Count GUILayout.BeginHorizontal(); GUILayout.Label("Control Points (max): " + mControlPointCount.ToString()); mControlPointCount = (int)GUILayout.HorizontalSlider(mControlPointCount, 2, 1000); GUILayout.EndHorizontal(); // Length GUILayout.BeginHorizontal(); GUILayout.Label("Total spline length: " + mTotalSplineLength.ToString()); mTotalSplineLength = (int)GUILayout.HorizontalSlider(mTotalSplineLength, 5, 10000); GUILayout.EndHorizontal(); // Cache GUILayout.BeginHorizontal(); GUILayout.Label("Cache Density: " + mCacheSize.ToString()); mCacheSize = (int)GUILayout.HorizontalSlider(mCacheSize, 1, 100); GUILayout.EndHorizontal(); mUseCache = GUILayout.Toggle(mUseCache, "Use Cache (where applicable)"); mUseMultiThreads = GUILayout.Toggle(mUseMultiThreads, "Use Multiple Threads (where applicable)"); GUILayout.Label("Select Test:"); int sel = GUILayout.SelectionGrid(Mathf.Max(0, mCurrentTest), mTests.ToArray(), 4); if (sel != mCurrentTest) { mCurrentTest = sel; Timer.Clear(); mTestResults.Clear(); mGUIMethod = GetType().GetMethod("GUI_" + mTests[mCurrentTest], BindingFlags.NonPublic | BindingFlags.Instance); mRunMethod = GetType().GetMethod("Test_" + mTests[mCurrentTest], BindingFlags.NonPublic | BindingFlags.Instance); } GUILayout.Space(5); if (mGUIMethod != null) { mGUIMethod.Invoke(this, null); } GUI.enabled = !mExecuting && mRunMethod != null; string label = (mExecuting) ? "Please wait..." : "Run (" + LOOPS + " times)"; if (GUILayout.Button(label)) { mExecuting = true; Timer.Clear(); mTestResults.Clear(); Invoke("runTest", .5f); } GUI.enabled = true; if (Timer.Count > 0) { foreach (var s in mTestResults) { GUILayout.Label(s); } GUILayout.Label(string.Format("Average (ms): {0:0.0000}", Timer.AverageMS)); GUILayout.Label(string.Format("Minimum (ms): {0:0.0000}", Timer.MinimumMS)); GUILayout.Label(string.Format("Maximum (ms): {0:0.0000}", Timer.MaximumMS)); } GUILayout.EndVertical(); }
/// <summary> /// Gets the interpolated position for a certain TF /// </summary> /// <remarks>TF (Total Fragment) relates to the total length of the spline</remarks> /// <param name="tf">TF value identifying position on spline (0..1)</param> /// <param name="interpolation">the interpolation to use</param> /// <returns>the interpolated position</returns> public override Vector3 Interpolate(float tf, CurvyInterpolation interpolation) { float localF; CurvySplineSegment seg = TFToSegment(tf, out localF); return seg.Interpolate(localF, interpolation); }
/// <summary> /// Sets Bezier Handles by interpolating between Control Points /// </summary> /// <param name="interpolation">the interpolation to use</param> /// <param name="offset">the offset in F (0..1)</param> /// <param name="freeMoveHandles">whether Handles should be moved individually</param> /// <param name="controlPoints">the Control Points to set the Handles for</param> public static void InterpolateBezierHandles(CurvyInterpolation interpolation, float offset, bool freeMoveHandles, params CurvySplineSegment[] controlPoints) { if (controlPoints.Length == 0) return; offset = Mathf.Clamp01(offset); foreach (CurvySplineSegment cp in controlPoints) { cp.FreeHandles = freeMoveHandles; CurvySplineSegment other = cp.PreviousSegment; if (other) cp.HandleInPosition = other.Interpolate(1 - offset, interpolation); else cp.HandleInPosition = cp.Interpolate(0, interpolation); if (freeMoveHandles) { if (cp.IsValidSegment) cp.HandleOutPosition = cp.Interpolate(offset, interpolation); else cp.HandleInPosition = Vector3.zero; } } controlPoints[0].Spline.Refresh(); }
/// <summary> /// Sets basic spline parameters /// </summary> protected void PrepareSpline(CurvyInterpolation interpolation, CurvyOrientation orientation = CurvyOrientation.Dynamic, int cachedensity = 50, bool closed = true) { #if UNITY_EDITOR if (!Application.isPlaying) Undo.RecordObject(Spline, "Apply Shape"); #endif Spline.Interpolation = interpolation; Spline.Orientation = orientation; Spline.CacheDensity = cachedensity; Spline.Closed = closed; Spline.RestrictTo2D = this is CurvyShape2D; }
CurvySpline CreateSpline(CurvyInterpolation type, int points, int granularity) { CurvySpline spl = CurvySpline.Create(); spl.Interpolation = type; spl.Granularity = granularity; spl.Closed = false; spl.ShowGizmos = false; spl.AutoEndTangents = true; for (int i = 0; i < points; i++) spl.Add(null, false).Position = Random.insideUnitCircle * 10; spl.RefreshImmediately(); return spl; }
void OnGUI() { GUILayout.BeginVertical(GUI.skin.box); GUILayout.Label("Curvy offers various options to fine-tune performance vs. precision balance:"); // Interpolation GUILayout.BeginHorizontal(); GUILayout.Label("Interpolation: "); if (GUILayout.Toggle(mInterpolation == CurvyInterpolation.Linear, "Linear", GUI.skin.button)) mInterpolation=CurvyInterpolation.Linear; if (GUILayout.Toggle(mInterpolation == CurvyInterpolation.Bezier, "Bezier", GUI.skin.button)) mInterpolation=CurvyInterpolation.Bezier; if (GUILayout.Toggle(mInterpolation == CurvyInterpolation.CatmullRom, "CatmullRom", GUI.skin.button)) mInterpolation = CurvyInterpolation.CatmullRom; if (GUILayout.Toggle(mInterpolation == CurvyInterpolation.TCB, "TCB", GUI.skin.button)) mInterpolation = CurvyInterpolation.TCB; GUILayout.EndHorizontal(); // Orientation GUILayout.BeginHorizontal(); GUILayout.Label("Orientation: "); if (GUILayout.Toggle(mOrientation == CurvyOrientation.None, "None", GUI.skin.button)) mOrientation = CurvyOrientation.None; if (GUILayout.Toggle(mOrientation == CurvyOrientation.Static, "Static", GUI.skin.button)) mOrientation = CurvyOrientation.Static; if (GUILayout.Toggle(mOrientation == CurvyOrientation.Dynamic, "Dynamic", GUI.skin.button)) mOrientation = CurvyOrientation.Dynamic; GUILayout.EndHorizontal(); // CP-Count GUILayout.BeginHorizontal(); GUILayout.Label("Control Points (max): " + mControlPointCount.ToString()); mControlPointCount = (int)GUILayout.HorizontalSlider(mControlPointCount, 2, 1000); GUILayout.EndHorizontal(); // Length GUILayout.BeginHorizontal(); GUILayout.Label("Total spline length: " + mTotalSplineLength.ToString()); mTotalSplineLength = (int)GUILayout.HorizontalSlider(mTotalSplineLength, 5, 10000); GUILayout.EndHorizontal(); // Cache GUILayout.BeginHorizontal(); GUILayout.Label("Cache Density: "+mCacheSize.ToString()); mCacheSize=(int)GUILayout.HorizontalSlider(mCacheSize, 1, 100); GUILayout.EndHorizontal(); mUseCache=GUILayout.Toggle(mUseCache, "Use Cache (where applicable)"); mUseMultiThreads = GUILayout.Toggle(mUseMultiThreads, "Use Multiple Threads (where applicable)"); GUILayout.Label("Select Test:"); int sel=GUILayout.SelectionGrid(Mathf.Max(0,mCurrentTest), mTests.ToArray(),4); if (sel != mCurrentTest) { mCurrentTest = sel; Timer.Clear(); mTestResults.Clear(); mGUIMethod = GetType().GetMethod("GUI_"+mTests[mCurrentTest], BindingFlags.NonPublic | BindingFlags.Instance); mRunMethod = GetType().GetMethod("Test_"+mTests[mCurrentTest], BindingFlags.NonPublic | BindingFlags.Instance); } GUILayout.Space(5); if (mGUIMethod != null) mGUIMethod.Invoke(this, null); GUI.enabled = !mExecuting && mRunMethod!=null; string label = (mExecuting) ? "Please wait..." : "Run (" + LOOPS + " times)"; if (GUILayout.Button(label)) { mExecuting = true; Timer.Clear(); mTestResults.Clear(); Invoke("runTest", .5f); } GUI.enabled = true; if (Timer.Count > 0) { foreach (var s in mTestResults) GUILayout.Label(s); GUILayout.Label(string.Format("Average (ms): {0:0.0000}", Timer.AverageMS)); GUILayout.Label(string.Format("Minimum (ms): {0:0.0000}", Timer.MinimumMS)); GUILayout.Label(string.Format("Maximum (ms): {0:0.0000}", Timer.MaximumMS)); } GUILayout.EndVertical(); }
/// <summary> /// Gets the interpolated position for a certain TF /// </summary> /// <remarks>TF (Total Fragment) relates to the total length of the spline</remarks> /// <param name="tf">TF value identifying position on spline (0..1)</param> /// <param name="interpolation">the interpolation to use</param> /// <returns>the interpolated position</returns> public virtual UnityEngine.Vector3 Interpolate(float tf, CurvyInterpolation interpolation) { return(UnityEngine.Vector3.zero); }
void OnGUI() { GUILayout.BeginArea(new Rect(10, 10, 1000, 600)); GUILayout.BeginHorizontal(); GUILayout.Label("Spline Type: "); splineSelection = GUILayout.SelectionGrid(splineSelection, new string[] { "Linear", "Catmul-Rom", "TCB", "Bezier" }, 4); GUILayout.EndHorizontal(); switch (splineSelection) { case 0: splineType = CurvyInterpolation.Linear; Prefix = "Linear"; break; case 1: splineType = CurvyInterpolation.CatmulRom; Prefix = "Catmul"; break; case 2: splineType = CurvyInterpolation.TCB; Prefix = "TCB"; break; case 3: splineType = CurvyInterpolation.Bezier; Prefix = "Bezier"; break; } Prefix += " G=" + granularity; GUILayout.BeginHorizontal(); GUILayout.Label("Spline Granularity: " + granularity); int oldGran = granularity; granularity = (int)GUILayout.HorizontalSlider(granularity, 1, 100); GUILayout.EndHorizontal(); if (Splines.Count > 0 && (splineType != Splines[0].Interpolation || granularity != oldGran)) { Clear(); } includeDependent = GUILayout.Toggle(includeDependent, "Run tests that vary by different Spline Types"); includeIndependent = GUILayout.Toggle(includeIndependent, "Run tests that vary by different Granularity"); includeMisc = GUILayout.Toggle(includeMisc, "Run tests for misc. methods (conversions, etc.)"); includeGetNearestPoint = GUILayout.Toggle(includeGetNearestPoint, "Run CurvySpline.GetNearestPointTF() - takes some time"); GUILayout.BeginHorizontal(); if (GUILayout.Button("Clear Result")) { Results.Clear(); } GUI.enabled = !running; if (GUILayout.Button((running) ? "Please wait..." : "Run!")) { StartCoroutine(RunTests()); } if (!Application.isWebPlayer) { GUI.enabled = Results.Count > 0; if (GUILayout.Button("Save as CSV")) { SaveToCSV(); } } GUI.enabled = true; GUILayout.EndHorizontal(); GUILayout.Label("* 'Create & Precalculate' as an exception is a single run only, the other values are calculated by averaging 50k runs (including time needed to get random values)!"); GUILayout.Label("* Times are in Milliseconds"); GUILayout.BeginHorizontal(); GUILayout.Label("Test", GUILayout.Width(400)); GUILayout.Label("2 Segments", GUILayout.Width(120)); GUILayout.Label("10 Segments", GUILayout.Width(120)); GUILayout.Label("50 Segments", GUILayout.Width(120)); GUILayout.Label("100 Segments", GUILayout.Width(120)); GUILayout.EndHorizontal(); scroll = GUILayout.BeginScrollView(scroll); foreach (Result R in Results) { R.OnGUI(); } GUILayout.EndScrollView(); GUILayout.EndArea(); }
/// <summary> /// Gets the interpolated position for a certain TF /// </summary> /// <remarks>TF (Total Fragment) relates to the total length of the spline</remarks> /// <param name="tf">TF value identifying position on spline (0..1)</param> /// <param name="interpolation">the interpolation to use</param> /// <returns>the interpolated position</returns> public virtual Vector3 Interpolate(float tf, CurvyInterpolation interpolation) { return Vector3.zero; }
/// <summary> /// Gets the interpolated position for a certain TF /// </summary> /// <remarks>TF (Total Fragment) relates to the total length of the spline</remarks> /// <param name="tf">TF value identifying position on spline (0..1)</param> /// <param name="interpolation">the interpolation to use</param> /// <returns>the interpolated position</returns> public virtual Vector3 Interpolate(float tf, CurvyInterpolation interpolation) { return(Vector3.zero); }
void OnGUI() { GUILayout.BeginArea(new Rect(10, 10, 1000, 600)); GUILayout.BeginHorizontal(); GUILayout.Label("Spline Type: "); splineSelection = GUILayout.SelectionGrid(splineSelection, new string[] { "Linear", "Catmul-Rom", "TCB" ,"Bezier"}, 4); GUILayout.EndHorizontal(); switch (splineSelection) { case 0: splineType = CurvyInterpolation.Linear; Prefix = "Linear"; break; case 1: splineType = CurvyInterpolation.CatmulRom; Prefix = "Catmul"; break; case 2: splineType = CurvyInterpolation.TCB; Prefix = "TCB"; break; case 3: splineType = CurvyInterpolation.Bezier; Prefix = "Bezier"; break; } Prefix += " G=" + granularity; GUILayout.BeginHorizontal(); GUILayout.Label("Spline Granularity: "+granularity); int oldGran = granularity; granularity=(int)GUILayout.HorizontalSlider(granularity, 1, 100); GUILayout.EndHorizontal(); if (Splines.Count > 0 && (splineType != Splines[0].Interpolation || granularity!=oldGran)) Clear(); includeDependent = GUILayout.Toggle(includeDependent, "Run tests that vary by different Spline Types"); includeIndependent = GUILayout.Toggle(includeIndependent, "Run tests that vary by different Granularity"); includeMisc = GUILayout.Toggle(includeMisc, "Run tests for misc. methods (conversions, etc.)"); includeGetNearestPoint = GUILayout.Toggle(includeGetNearestPoint, "Run CurvySpline.GetNearestPointTF() - takes some time"); GUILayout.BeginHorizontal(); if (GUILayout.Button("Clear Result")) Results.Clear(); GUI.enabled = !running; if (GUILayout.Button((running) ? "Please wait..." : "Run!")) StartCoroutine(RunTests()); if (!Application.isWebPlayer) { GUI.enabled = Results.Count > 0; if (GUILayout.Button("Save as CSV")) SaveToCSV(); } GUI.enabled = true; GUILayout.EndHorizontal(); GUILayout.Label("* 'Create & Precalculate' as an exception is a single run only, the other values are calculated by averaging 50k runs (including time needed to get random values)!"); GUILayout.Label("* Times are in Milliseconds"); GUILayout.BeginHorizontal(); GUILayout.Label("Test", GUILayout.Width(400)); GUILayout.Label("2 Segments", GUILayout.Width(120)); GUILayout.Label("10 Segments", GUILayout.Width(120)); GUILayout.Label("50 Segments", GUILayout.Width(120)); GUILayout.Label("100 Segments", GUILayout.Width(120)); GUILayout.EndHorizontal(); scroll=GUILayout.BeginScrollView(scroll); foreach (Result R in Results) R.OnGUI(); GUILayout.EndScrollView(); GUILayout.EndArea(); }