From dc0fcbeecb82ed9f07ed17bfba116f6540fea6d3 Mon Sep 17 00:00:00 2001 From: Wiktor Rott Date: Mon, 2 Aug 2021 11:58:43 +0200 Subject: [PATCH] Release v2.2.3 --- CHANGELOG.md | 3 + Runtime/BezierSpline.cs | 47 ++-- Runtime/SplinePath.cs | 55 +++-- .../Runtime/LineRendererSpline.cs | 2 +- .../SplineMeshEditorConfiguration.asset | 1 + .../Editor/SplineMeshEditorState.cs | 2 +- .../Editor/SplineMeshEditor_Base.cs | 2 +- .../Editor/SplineMeshEditor_Inspector_Mesh.cs | 2 +- .../Editor/SplineMeshEditor_SceneGUI.cs | 8 +- .../Editor/SplineMeshSettingsProvider.cs | 2 +- Samples/Mesh Generator/Runtime/Jobs.meta | 8 + .../Runtime/Jobs/GenerateMeshJob.cs | 184 +++++++++++++++ .../Runtime/Jobs/GenerateMeshJob.cs.meta | 11 + .../Runtime/Jobs/IDisposableJobParallelFor.cs | 17 ++ .../Jobs/IDisposableJobParallelFor.cs.meta | 11 + .../Runtime/Jobs/JobsExtensions.cs | 64 +++++ .../Runtime/Jobs/JobsExtensions.cs.meta | 11 + .../Runtime/Jobs/MeshJobExecutor.cs | 192 +++++++++++++++ .../Runtime/Jobs/MeshJobExecutor.cs.meta | 11 + .../SplineEditor.Samples.MeshGenerator.asmdef | 3 +- Samples/Mesh Generator/Runtime/SplineMesh.cs | 222 +++++------------- .../SplineMeshConfiguration.cs} | 26 +- .../SplineMeshConfiguration.cs.meta} | 0 package.json | 10 +- 24 files changed, 677 insertions(+), 217 deletions(-) create mode 100644 Samples/Mesh Generator/Runtime/Jobs.meta create mode 100644 Samples/Mesh Generator/Runtime/Jobs/GenerateMeshJob.cs create mode 100644 Samples/Mesh Generator/Runtime/Jobs/GenerateMeshJob.cs.meta create mode 100644 Samples/Mesh Generator/Runtime/Jobs/IDisposableJobParallelFor.cs create mode 100644 Samples/Mesh Generator/Runtime/Jobs/IDisposableJobParallelFor.cs.meta create mode 100644 Samples/Mesh Generator/Runtime/Jobs/JobsExtensions.cs create mode 100644 Samples/Mesh Generator/Runtime/Jobs/JobsExtensions.cs.meta create mode 100644 Samples/Mesh Generator/Runtime/Jobs/MeshJobExecutor.cs create mode 100644 Samples/Mesh Generator/Runtime/Jobs/MeshJobExecutor.cs.meta rename Samples/Mesh Generator/{Editor/SplineMeshEditorConfiguration.cs => Runtime/SplineMeshConfiguration.cs} (67%) rename Samples/Mesh Generator/{Editor/SplineMeshEditorConfiguration.cs.meta => Runtime/SplineMeshConfiguration.cs.meta} (100%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 337d042..ad6ee00 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +## v2.2.3 [02.08.2021] +- Adding Jobs system for mesh generation. + ## v2.1.3 [26.07.2021] - Fix for index out of bounds error when creating new bezier spline. - Getting rid of EditorUtility.SetDirty invokes which will soon become deprecated. diff --git a/Runtime/BezierSpline.cs b/Runtime/BezierSpline.cs index 63b64a3..a2d855c 100644 --- a/Runtime/BezierSpline.cs +++ b/Runtime/BezierSpline.cs @@ -22,6 +22,9 @@ public class BezierSpline : MonoBehaviour private readonly List normalsOffsetCopyList = new List(); + [SerializeField] + private int curvesCount = 0; + [SerializeField] private bool isLoop = default; @@ -86,7 +89,19 @@ public enum BezierControlPointMode : int /// /// Gets number of curves in the splines. /// - public int CurvesCount => Mathf.Max(0, (PointsCount - 1) / 3); + public int CurvesCount + { + get + { + if (curvesCount == 0) + { + curvesCount = Mathf.Max(0, (PointsCount - 1) / 3); + } + + return curvesCount; + } + private set => curvesCount = value; + } /// /// Gets number of points in the spline. @@ -673,7 +688,7 @@ public void RecalculateNormals() var targetDistance = GetLinearLength(targetT: currentTargetT, precision: 0.00001f, useWorldScale: false); normals[0] = normalsPath.Normals[0]; Tangents[0] = normalsPath.Tangents[0]; - for (var i = 1; i < normalsPath.Points.Length; i++) + for (var i = 1; i < normalsPath.Points.Count; i++) { distance += Vector3.Distance(normalsPath.Points[i - 1], normalsPath.Points[i]); if (distance >= targetDistance) @@ -700,8 +715,8 @@ public void RecalculateNormals() } else { - normals[normals.Count - 1] = normalsPath.Normals[normalsPath.Normals.Length - 1]; - Tangents[Tangents.Count - 1] = normalsPath.Tangents[normalsPath.Tangents.Length - 1]; + normals[normals.Count - 1] = normalsPath.Normals[normalsPath.Normals.Count - 1]; + Tangents[Tangents.Count - 1] = normalsPath.Tangents[normalsPath.Tangents.Count - 1]; } globalNormalsRotation = globalAngleCopy; @@ -721,11 +736,12 @@ public void RecalculateNormals() /// Transform points from local space to world space. public void GetEvenlySpacedPoints(float spacing, SplinePath bezierPath, float precision = 0.001f, bool useWorldSpace = true) { - var scales = new List(); - var normals = new List(); - var tangents = new List(); - var parametersT = new List(); - var spacedPoints = new List(); + bezierPath.Reset(); + var scales = bezierPath.Scales; + var normals = bezierPath.Normals; + var tangents = bezierPath.Tangents; + var parametersT = bezierPath.ParametersT; + var spacedPoints = bezierPath.Points; var splineLength = GetLinearLength(precision: 0.0001f, useWorldScale: false); var segmentsCount = Mathf.RoundToInt(splineLength / spacing) + 1; @@ -783,7 +799,7 @@ public void GetEvenlySpacedPoints(float spacing, SplinePath bezierPath, float pr if (isLoop && normals.Count > 1) { // Get angle between first and last normal (if zero, they're already lined up, otherwise we need to correct) - float normalsAngleErrorAcrossJoin = Vector3.SignedAngle(normals[normals.Count - 1], normals[0], tangents[0]); + var normalsAngleErrorAcrossJoin = Vector3.SignedAngle(normals[normals.Count - 1], normals[0], tangents[0]); // Gradually rotate the normals along the path to ensure start and end normals line up correctly if (Mathf.Abs(normalsAngleErrorAcrossJoin) > MinNormalsAnglesDifference) // don't bother correcting if very nearly correct @@ -799,15 +815,9 @@ public void GetEvenlySpacedPoints(float spacing, SplinePath bezierPath, float pr } } - bezierPath.Scales = scales.ToArray(); - bezierPath.Points = spacedPoints.ToArray(); - bezierPath.Normals = normals.ToArray(); - bezierPath.Tangents = tangents.ToArray(); - bezierPath.ParametersT = parametersT.ToArray(); - if (useWorldSpace) { - for (var i = 0; i < bezierPath.Points.Length; i++) + for (var i = 0; i < bezierPath.Points.Count; i++) { bezierPath.Points[i] = transform.TransformPoint(bezierPath.Points[i]); } @@ -1137,11 +1147,14 @@ private void AddPoint(Vector3 point, int index) { Points.Add(linePoint); } + + CurvesCount = Mathf.Max(0, (PointsCount - 1) / 3); } private void RemovePoint(int pointIndex) { Points.RemoveAt(pointIndex); + CurvesCount = Mathf.Max(0, (PointsCount - 1) / 3); } private void ApplyContraints(int pointIndex) diff --git a/Runtime/SplinePath.cs b/Runtime/SplinePath.cs index 500b42c..ee5611b 100644 --- a/Runtime/SplinePath.cs +++ b/Runtime/SplinePath.cs @@ -4,6 +4,7 @@ // using System; +using System.Collections.Generic; using UnityEngine; namespace SplineEditor @@ -16,37 +17,37 @@ namespace SplineEditor public class SplinePath { [SerializeField] - private Vector3[] scales; + private List scales; [SerializeField] - private Vector3[] points; + private List points; [SerializeField] - private Vector3[] normals; + private List normals; [SerializeField] - private Vector3[] tangents; + private List tangents; [SerializeField] - private float[] parametersT; + private List parametersT; /// /// Initializes a new instance of the class. /// public SplinePath() { - this.Points = new Vector3[0]; - this.Normals = new Vector3[0]; - this.Tangents = new Vector3[0]; - this.Scales = new Vector3[0]; - this.ParametersT = new float[0]; + this.Points = new List(); + this.Normals = new List(); + this.Tangents = new List(); + this.Scales = new List(); + this.ParametersT = new List(); } /// /// Initializes a new instance of the class. /// - /// Array of points positions on path. - /// Array of tangents on path. - /// Array of normal vectors on path. - /// Array of scales on path. - /// Array of t parameters on path. - public SplinePath(Vector3[] points, Vector3[] tangents, Vector3[] normals, Vector3[] scales, float[] parametersT) + /// List of points positions on path. + /// List of tangents on path. + /// List of normal vectors on path. + /// List of scales on path. + /// List of t parameters on path. + public SplinePath(List points, List tangents, List normals, List scales, List parametersT) { this.Points = points; this.Normals = normals; @@ -58,7 +59,7 @@ public SplinePath(Vector3[] points, Vector3[] tangents, Vector3[] normals, Vecto /// /// Gets or sets scales for path points. /// - public Vector3[] Scales + public List Scales { get => scales; set => scales = value; @@ -67,7 +68,7 @@ public Vector3[] Scales /// /// Gets or sets positions for path points. /// - public Vector3[] Points + public List Points { get => points; set => points = value; @@ -76,7 +77,7 @@ public Vector3[] Points /// /// Gets or sets normal vectors for path points. /// - public Vector3[] Normals + public List Normals { get => normals; set => normals = value; @@ -85,7 +86,7 @@ public Vector3[] Normals /// /// Gets or sets tangents for path points. /// - public Vector3[] Tangents + public List Tangents { get => tangents; set => tangents = value; @@ -94,10 +95,22 @@ public Vector3[] Tangents /// /// Gets or sets t parameters of bezier spline for path points. /// - public float[] ParametersT + public List ParametersT { get => parametersT; set => parametersT = value; } + + /// + /// Resets all variables to empty lists. + /// + public void Reset() + { + Scales.Clear(); + Points.Clear(); + Normals.Clear(); + Tangents.Clear(); + ParametersT.Clear(); + } } } \ No newline at end of file diff --git a/Samples/Line Renderer/Runtime/LineRendererSpline.cs b/Samples/Line Renderer/Runtime/LineRendererSpline.cs index 4fc22a3..3bbefb2 100644 --- a/Samples/Line Renderer/Runtime/LineRendererSpline.cs +++ b/Samples/Line Renderer/Runtime/LineRendererSpline.cs @@ -178,7 +178,7 @@ private void UpdateLinePointsWithEvenlySpacedPoints() bezierSpline.GetEvenlySpacedPoints(pointsSpacing, cachedSplinePath, useWorldSpace: false); var generatedPoints = cachedSplinePath.Points; - var generatedPointsLength = generatedPoints.Length; + var generatedPointsLength = generatedPoints.Count; lineRenderer.positionCount = generatedPointsLength; diff --git a/Samples/Mesh Generator/Editor/Resources/SplineMeshEditorConfiguration.asset b/Samples/Mesh Generator/Editor/Resources/SplineMeshEditorConfiguration.asset index 2561511..b973d39 100644 --- a/Samples/Mesh Generator/Editor/Resources/SplineMeshEditorConfiguration.asset +++ b/Samples/Mesh Generator/Editor/Resources/SplineMeshEditorConfiguration.asset @@ -17,3 +17,4 @@ MonoBehaviour: pointsColor: {r: 0, g: 0, b: 1, a: 1} normalsColor: {r: 0, g: 1, b: 0, a: 1} normalVectorLength: 2.5 + useJobsWithCoroutines: 0 diff --git a/Samples/Mesh Generator/Editor/SplineMeshEditorState.cs b/Samples/Mesh Generator/Editor/SplineMeshEditorState.cs index ef20a7e..b2596e8 100644 --- a/Samples/Mesh Generator/Editor/SplineMeshEditorState.cs +++ b/Samples/Mesh Generator/Editor/SplineMeshEditorState.cs @@ -168,7 +168,7 @@ public void SetDebugModeView(SplineMesh splineMesh, bool state) /// SplineMesh component to have UV material set. public void SetDebugModeMaterial(SplineMesh splineMesh) { - var settingsScriptable = SplineMeshEditorConfiguration.Instance; + var settingsScriptable = SplineMeshConfiguration.Instance; var prevMaterial = splineMesh.MeshRenderer.sharedMaterial; var newMaterial = settingsScriptable.UvMaterial; diff --git a/Samples/Mesh Generator/Editor/SplineMeshEditor_Base.cs b/Samples/Mesh Generator/Editor/SplineMeshEditor_Base.cs index 54c7395..9555502 100644 --- a/Samples/Mesh Generator/Editor/SplineMeshEditor_Base.cs +++ b/Samples/Mesh Generator/Editor/SplineMeshEditor_Base.cs @@ -17,7 +17,7 @@ public partial class SplineMeshEditor : UnityEditor.Editor private static SplineMeshEditorState MeshEditorState => SplineMeshEditorState.instance; - private static SplineMeshEditorConfiguration MeshEditorConfiguration => SplineMeshEditorConfiguration.Instance; + private static SplineMeshConfiguration MeshEditorConfiguration => SplineMeshConfiguration.Instance; private void OnEnable() { diff --git a/Samples/Mesh Generator/Editor/SplineMeshEditor_Inspector_Mesh.cs b/Samples/Mesh Generator/Editor/SplineMeshEditor_Inspector_Mesh.cs index edfd0de..6312bb1 100644 --- a/Samples/Mesh Generator/Editor/SplineMeshEditor_Inspector_Mesh.cs +++ b/Samples/Mesh Generator/Editor/SplineMeshEditor_Inspector_Mesh.cs @@ -91,7 +91,7 @@ private void DrawBakeMeshButton() GUILayout.Space(20); if (GUILayout.Button(MeshOptionsBakeMeshButtonContent, buttonStyle, ButtonHeight)) { - splineMesh.ConstructMesh(); + splineMesh.GenerateMesh(); var path = EditorUtility.SaveFilePanel(MeshOptionsBakeMeshWindowTitle, MeshOptionsBakeMeshWindowFolderPath, MeshOptionsBakeMeshWindowFileName, MeshOptionsBakeMeshWindowFileExtension); if (string.IsNullOrEmpty(path)) { diff --git a/Samples/Mesh Generator/Editor/SplineMeshEditor_SceneGUI.cs b/Samples/Mesh Generator/Editor/SplineMeshEditor_SceneGUI.cs index 5bd82bb..0a864c8 100644 --- a/Samples/Mesh Generator/Editor/SplineMeshEditor_SceneGUI.cs +++ b/Samples/Mesh Generator/Editor/SplineMeshEditor_SceneGUI.cs @@ -32,7 +32,7 @@ private void OnSceneGUI() private void DrawPoints() { - for (var i = 0; i < splineMesh.Points.Length; i++) + for (var i = 0; i < splineMesh.Points.Count; i++) { DrawPoint(i); } @@ -46,7 +46,7 @@ private void DrawPoint(int index) if (MeshEditorState.DrawPoints) { var handleSize = 0.025f; - Handles.color = SplineMeshEditorConfiguration.Instance.PointsColor; + Handles.color = SplineMeshConfiguration.Instance.PointsColor; Handles.Button(point, Quaternion.identity, size * handleSize, size * handleSize, Handles.DotHandleCap); } @@ -59,8 +59,8 @@ private void DrawPoint(int index) private void DrawNormal(Vector3 point, int index) { var normal = splineMesh.Normals[index]; - var normalLength = SplineMeshEditorConfiguration.Instance.NormalVectorLength; - Handles.color = SplineMeshEditorConfiguration.Instance.NormalsColor; + var normalLength = SplineMeshConfiguration.Instance.NormalVectorLength; + Handles.color = SplineMeshConfiguration.Instance.NormalsColor; Handles.DrawLine(point, point + splineMesh.transform.TransformDirection(normal * normalLength)); } } diff --git a/Samples/Mesh Generator/Editor/SplineMeshSettingsProvider.cs b/Samples/Mesh Generator/Editor/SplineMeshSettingsProvider.cs index d7a7f37..b7fec57 100644 --- a/Samples/Mesh Generator/Editor/SplineMeshSettingsProvider.cs +++ b/Samples/Mesh Generator/Editor/SplineMeshSettingsProvider.cs @@ -35,7 +35,7 @@ public SplineMeshSettingsProvider(string path, SettingsScope scope) : base(path, [SettingsProvider] public static SettingsProvider CreateMyCustomSettingsProvider() { - var settingsScriptable = SplineMeshEditorConfiguration.Instance; + var settingsScriptable = SplineMeshConfiguration.Instance; if (cachedEditor == null) { diff --git a/Samples/Mesh Generator/Runtime/Jobs.meta b/Samples/Mesh Generator/Runtime/Jobs.meta new file mode 100644 index 0000000..321e63a --- /dev/null +++ b/Samples/Mesh Generator/Runtime/Jobs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3b95bc1922e05824186fdf8abe45758a +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Samples/Mesh Generator/Runtime/Jobs/GenerateMeshJob.cs b/Samples/Mesh Generator/Runtime/Jobs/GenerateMeshJob.cs new file mode 100644 index 0000000..ad7a333 --- /dev/null +++ b/Samples/Mesh Generator/Runtime/Jobs/GenerateMeshJob.cs @@ -0,0 +1,184 @@ +// +// Copyright (c) vvrvvd. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using Unity.Burst; +using Unity.Collections; +using UnityEngine; + +/// +/// Job for generating flat mesh from given spline path settings. +/// +[BurstCompile(CompileSynchronously = true)] +public struct GenerateMeshJob : IDisposableJobParallelFor +{ + /// + /// Width of the generated mesh. + /// + [ReadOnly] + public float Width; + + /// + /// Should individual points scales be applied to mesh width. + /// + [ReadOnly] + public bool UsePointsScale; + + /// + /// Should both width curves (left and right) be used for mesh curve width. + /// If false then the right side curve is applied to both sides. + /// + [ReadOnly] + public bool UseAsymetricWidthCurve; + + /// + /// How UV should be generated. + /// 0 - Linear, 1 - PingPong. + /// + [ReadOnly] + public int UvMode; // 0 - Linear, 1 - PingPong + + /// + /// Should UV be mirrored. + /// + [ReadOnly] + public bool MirrorUv; + + /// + /// Is mesh looped (the first and the last points have the same position). + /// + [ReadOnly] + public bool IsLoop; + + /// + /// Source scales for spline path points. + /// + [ReadOnly] + public NativeArray Scales; + + /// + /// Source normals for spline path points. + /// + [ReadOnly] + public NativeArray Normals; + + /// + /// Source tangents for spline path points. + /// + [ReadOnly] + public NativeArray Tangents; + + /// + /// Source positions for spline path points. + /// + [ReadOnly] + public NativeArray Positions; + + /// + /// Source left side curve scales for spline path points. + /// + [ReadOnly] + public NativeArray LeftScales; + + /// + /// Source right side curve scales for spline path points. + /// + [ReadOnly] + public NativeArray RightScales; + + /// + /// Calculated indices for the generated mesh. + /// + [WriteOnly, NativeDisableParallelForRestriction] + public NativeArray IndicesResult; + + /// + /// Calculated UVs for the generated mesh. + /// + [WriteOnly, NativeDisableParallelForRestriction] + public NativeArray UvsResult; + + /// + /// Calculated vertices for the generated mesh. + /// + [WriteOnly, NativeDisableParallelForRestriction] + public NativeArray VertsResult; + + /// + /// Calculated normals for the generated mesh. + /// + [WriteOnly, NativeDisableParallelForRestriction] + public NativeArray NormalsResult; + + private static readonly int[] IndicesMap = { 0, 2, 1, 1, 2, 3 }; + + /// + /// Executes mesh generation for given index. + /// + /// Index of the point to generate mesh from. + public void Execute(int i) + { + var vertIndex = i * 2; + var trisIndex = i * 6; + + // Normals + NormalsResult[vertIndex] = Normals[i]; + NormalsResult[vertIndex + 1] = Normals[i]; + + // Vertices + var right = Vector3.Cross(Normals[i], Tangents[i]).normalized; + var rightScaledWidth = Width * (UsePointsScale ? Scales[i].x : 1) * RightScales[i]; + var leftScaledWidth = Width * (UsePointsScale ? Scales[i].x : 1) * LeftScales[i]; + VertsResult[vertIndex] = Positions[i] - (right * (UseAsymetricWidthCurve ? leftScaledWidth : rightScaledWidth)); + VertsResult[vertIndex + 1] = Positions[i] + (right * rightScaledWidth); + + // UV + var uv = GetUV(i); + UvsResult[vertIndex] = new Vector2(0, uv); + UvsResult[vertIndex + 1] = new Vector2(1, uv); + + // Triangles + if (i < Positions.Length - 1 || IsLoop) + { + for (int j = 0; j < IndicesMap.Length; j++) + { + IndicesResult[trisIndex + j] = (vertIndex + IndicesMap[j]) % VertsResult.Length; + } + } + } + + /// + /// Disposes of all the NativeArray allocated for this job. + /// + public void Dispose() + { + Scales.Dispose(); + Normals.Dispose(); + Tangents.Dispose(); + Positions.Dispose(); + LeftScales.Dispose(); + RightScales.Dispose(); + + IndicesResult.Dispose(); + UvsResult.Dispose(); + VertsResult.Dispose(); + NormalsResult.Dispose(); + } + + private float GetUV(int pointIndex) + { + var uv = pointIndex / (float)(Positions.Length - 1); + switch (UvMode) + { + case 1: // PingPong + uv = 1 - Mathf.Abs((2 * uv) - 1); + break; + case 0: // Linear + default: + break; + } + + return MirrorUv ? 1 - uv : uv; + } +} \ No newline at end of file diff --git a/Samples/Mesh Generator/Runtime/Jobs/GenerateMeshJob.cs.meta b/Samples/Mesh Generator/Runtime/Jobs/GenerateMeshJob.cs.meta new file mode 100644 index 0000000..77edbd4 --- /dev/null +++ b/Samples/Mesh Generator/Runtime/Jobs/GenerateMeshJob.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7f9417c542468e04e9826536777b40ae +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Samples/Mesh Generator/Runtime/Jobs/IDisposableJobParallelFor.cs b/Samples/Mesh Generator/Runtime/Jobs/IDisposableJobParallelFor.cs new file mode 100644 index 0000000..a53cd0c --- /dev/null +++ b/Samples/Mesh Generator/Runtime/Jobs/IDisposableJobParallelFor.cs @@ -0,0 +1,17 @@ +// +// Copyright (c) vvrvvd. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using Unity.Jobs; + +/// +/// Interface adding Dispose() method to IJobParallelFor interface. +/// +public interface IDisposableJobParallelFor : IJobParallelFor +{ + /// + /// Disposing of all the allocated memory for the job. + /// + public void Dispose(); +} diff --git a/Samples/Mesh Generator/Runtime/Jobs/IDisposableJobParallelFor.cs.meta b/Samples/Mesh Generator/Runtime/Jobs/IDisposableJobParallelFor.cs.meta new file mode 100644 index 0000000..fa0e8a5 --- /dev/null +++ b/Samples/Mesh Generator/Runtime/Jobs/IDisposableJobParallelFor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0d1e3a588a21d4e4eb79d7f87ef3d2c8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Samples/Mesh Generator/Runtime/Jobs/JobsExtensions.cs b/Samples/Mesh Generator/Runtime/Jobs/JobsExtensions.cs new file mode 100644 index 0000000..78c7f05 --- /dev/null +++ b/Samples/Mesh Generator/Runtime/Jobs/JobsExtensions.cs @@ -0,0 +1,64 @@ +// +// Copyright (c) vvrvvd. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using System; +using System.Collections; +using Unity.Jobs; +using UnityEngine; + +/// +/// Jobs extensions for simpler job execution and coroutines waiting for jobs to finish. +/// +public static class JobsExtensions +{ + /// + /// Schedules and completes jobs. After completing the job onJobCompleted action is invoked and the job is disposed. + /// + /// Job type implementing IDisposableJobParallelFor interface. + /// The job and data to Schedule. + /// The number of iterations the for loop will execute. + /// Granularity in which workstealing is performed. A value of 32, means the job queue will steal 32 iterations and then perform them in an efficient inner loop. + /// Action to be invoked on Job completion. + /// Dependencies are used to ensure that a job executes on workerthreads after the dependency has completed execution. Making sure that two jobs reading or writing to same data do not run in parallel. + public static void ScheduleAndComplete(this T jobData, int arrayLength, int interloopBatchCount, Action onJobCompleted = null, JobHandle dependsOn = default) where T : struct, IDisposableJobParallelFor + { + var handle = jobData.Schedule(arrayLength, interloopBatchCount, dependsOn); + handle.Complete(); + + onJobCompleted?.Invoke(jobData); + jobData.Dispose(); + } + + /// + /// Schedules and completes the job as soon as it's done using a coroutine awaiting for the job to finish. + /// After job is finished onJobCompleted action is invoked. + /// + /// Job type implementing IDisposableJobParallelFor interface. + /// The job and data to Schedule. + /// The number of iterations the for loop will execute. + /// Granularity in which workstealing is performed. A value of 32, means the job queue will steal 32 iterations and then perform them in an efficient inner loop. + /// MonoBehaviour to get coroutine run on. + /// Action to be invoked when Job is scheduled. + /// Action to be invoked on Job completion. + /// Dependencies are used to ensure that a job executes on workerthreads after the dependency has completed execution. Making sure that two jobs reading or writing to same data do not run in parallel. + /// Coroutine awaiting for the job to complete. + public static Coroutine ScheduleAndCompleteAsync(this T jobData, int arrayLength, int interloopBatchCount, MonoBehaviour context, Action onJobScheduled = null, Action onJobCompleted = null, JobHandle dependsOn = default) where T : struct, IDisposableJobParallelFor + { + var handle = jobData.Schedule(arrayLength, interloopBatchCount, dependsOn); + onJobScheduled?.Invoke(handle); + var coroutine = context.StartCoroutine(WaitForJobToFinish(handle, jobData, onJobCompleted)); + + return coroutine; + } + + private static IEnumerator WaitForJobToFinish(JobHandle jobHandle, T job, Action onJobFinished) where T : struct, IDisposableJobParallelFor + { + yield return new WaitWhile(() => !jobHandle.IsCompleted); + + jobHandle.Complete(); + onJobFinished?.Invoke(job); + job.Dispose(); + } +} diff --git a/Samples/Mesh Generator/Runtime/Jobs/JobsExtensions.cs.meta b/Samples/Mesh Generator/Runtime/Jobs/JobsExtensions.cs.meta new file mode 100644 index 0000000..1c8151f --- /dev/null +++ b/Samples/Mesh Generator/Runtime/Jobs/JobsExtensions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a3f97ba0b2959f24a989d8d55eb419e6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Samples/Mesh Generator/Runtime/Jobs/MeshJobExecutor.cs b/Samples/Mesh Generator/Runtime/Jobs/MeshJobExecutor.cs new file mode 100644 index 0000000..4a2aff0 --- /dev/null +++ b/Samples/Mesh Generator/Runtime/Jobs/MeshJobExecutor.cs @@ -0,0 +1,192 @@ +// +// Copyright (c) vvrvvd. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using System; +using SplineEditor; +using SplineEditor.MeshGenerator; +using Unity.Collections; +using Unity.Jobs; +#if UNITY_EDITOR +using UnityEditor; +#endif +using UnityEngine; + +/// +/// Class for scheduling and executing mesh generation using Jobs system. +/// +public class MeshJobExecutor +{ + private const int JobBatchSize = 64; + private const float SplinePathPrecision = 0.001f; + + private bool isJobScheduled = false; + private bool scheduleNextJob = false; + + private Coroutine generateMeshCoroutine; + private MonoBehaviour coroutineContext; + private GenerateMeshJob ongoingJob; + private JobHandle ongoingJobHandle; + + private SplineMesh splineMesh; + private SplinePath splinePath; + + /// + /// Initializes a new instance of the class. + /// + /// SplineMesh component for getting parameters for mesh generation. + /// SplinePath object for keeping parameters for mesh generation. + public MeshJobExecutor(SplineMesh splineMesh, SplinePath splinePath) + { + Setup(splineMesh, splinePath); + } + + public void Setup(SplineMesh splineMesh, SplinePath splinePath) + { + this.splineMesh = splineMesh; + this.splinePath = splinePath; + } + + /// + /// Prepares and generates new mesh using Jobs system. + /// On mesh generation completion it is stored in the given mesh and onMeshGenerated action is invoked. + /// + /// Mesh to be generated. + /// Action invoked on mesh generation completion. + /// Should mesh generation be forced to be executed in the same frame (on the main thread). + public void GenerateMesh(Mesh mesh, Action onMeshGenerated, bool immediate) + { + if (isJobScheduled) + { + scheduleNextJob = true; + return; + } + + isJobScheduled = true; + scheduleNextJob = false; + StopOngoingJob(); + ongoingJob = PrepareGenerateMeshJob(); + StartJob(ongoingJob, splineMesh, mesh, onMeshGenerated, immediate); + } + + private void StopOngoingJob() + { + if(!ongoingJobHandle.IsCompleted) { + ongoingJobHandle.Complete(); + ongoingJob.Dispose(); + } + + if (coroutineContext == null || generateMeshCoroutine == null) + { + return; + } + + coroutineContext.StopCoroutine(generateMeshCoroutine); + } + + private GenerateMeshJob PrepareGenerateMeshJob() + { + splineMesh.BezierSpline.GetEvenlySpacedPoints(splineMesh.Spacing, splinePath, SplinePathPrecision, false); + + var bezierSpline = splineMesh.BezierSpline; + + var leftCurveScales = new float[splinePath.Points.Count]; + var rightCurveScales = new float[splinePath.Points.Count]; + for (var i = 0; i < leftCurveScales.Length; i++) + { + var t = splinePath.ParametersT[i]; + leftCurveScales[i] = splineMesh.LeftSideCurve.Evaluate(t); + rightCurveScales[i] = splineMesh.RightSideCurve.Evaluate(t); + } + + var width = splineMesh.Width; + var scales = new NativeArray(splinePath.Scales.ToArray(), Allocator.TempJob); + var normals = new NativeArray(splinePath.Normals.ToArray(), Allocator.TempJob); + var tangents = new NativeArray(splinePath.Tangents.ToArray(), Allocator.TempJob); + var positions = new NativeArray(splinePath.Points.ToArray(), Allocator.TempJob); + var leftScale = new NativeArray(leftCurveScales, Allocator.TempJob); + var rightScale = new NativeArray(rightCurveScales, Allocator.TempJob); + + var numTris = (2 * (positions.Length - 1)) + (bezierSpline.IsLoop ? 2 : 1); + var indicesResult = new NativeArray(numTris * 3, Allocator.TempJob); + var uvsResult = new NativeArray(positions.Length * 2, Allocator.TempJob); + var vertsResult = new NativeArray(positions.Length * 2, Allocator.TempJob); + var normalsResult = new NativeArray(positions.Length * 2, Allocator.TempJob); + + GenerateMeshJob generateMeshJob = new GenerateMeshJob() + { + // Input data + Width = width, + UsePointsScale = splineMesh.UsePointsScale, + UseAsymetricWidthCurve = splineMesh.UseAsymetricWidthCurve, + UvMode = (int)splineMesh.UvMode, + MirrorUv = splineMesh.MirrorUV, + IsLoop = bezierSpline.IsLoop, + Scales = scales, + Normals = normals, + Tangents = tangents, + Positions = positions, + LeftScales = leftScale, + RightScales = rightScale, + + // Output data + IndicesResult = indicesResult, + UvsResult = uvsResult, + VertsResult = vertsResult, + NormalsResult = normalsResult, + }; + + return generateMeshJob; + } + + private void StartJob(GenerateMeshJob generateMeshJob, SplineMesh splineMesh, Mesh mesh, Action onMeshGenerated, bool immediate) + { + if (immediate) + { + generateMeshJob.ScheduleAndComplete(generateMeshJob.Positions.Length, JobBatchSize, + (generateMeshJob) => + { + OnJobCompleted(ref generateMeshJob, mesh); + onMeshGenerated?.Invoke(mesh); + isJobScheduled = false; + }); + } + else + { + StartJobCoroutine(generateMeshJob, splineMesh, mesh, onMeshGenerated); + } + } + + private void StartJobCoroutine(GenerateMeshJob generateMeshJob, SplineMesh splineMesh, Mesh mesh, Action onMeshGenerated) + { + generateMeshCoroutine = generateMeshJob.ScheduleAndCompleteAsync(generateMeshJob.Positions.Length, JobBatchSize, splineMesh, + (jobHandle) => + { + ongoingJobHandle = jobHandle; + }, + (generateMeshJob) => + { + OnJobCompleted(ref generateMeshJob, mesh); + onMeshGenerated?.Invoke(mesh); + isJobScheduled = false; + + if (scheduleNextJob) + { + splineMesh.GenerateMesh(); + } + }); + } + + private void OnJobCompleted(ref GenerateMeshJob generateMeshJob, Mesh mesh) + { +#if UNITY_EDITOR + Undo.RecordObject(splineMesh, "Generate Mesh"); +#endif + mesh.Clear(); + mesh.SetVertices(generateMeshJob.VertsResult); + mesh.SetNormals(generateMeshJob.NormalsResult); + mesh.SetUVs(0, generateMeshJob.UvsResult); + mesh.SetTriangles(generateMeshJob.IndicesResult.ToArray(), 0); + } +} diff --git a/Samples/Mesh Generator/Runtime/Jobs/MeshJobExecutor.cs.meta b/Samples/Mesh Generator/Runtime/Jobs/MeshJobExecutor.cs.meta new file mode 100644 index 0000000..5353fb3 --- /dev/null +++ b/Samples/Mesh Generator/Runtime/Jobs/MeshJobExecutor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7b154f7cd2b9de8468604f131ea297e1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Samples/Mesh Generator/Runtime/SplineEditor.Samples.MeshGenerator.asmdef b/Samples/Mesh Generator/Runtime/SplineEditor.Samples.MeshGenerator.asmdef index 39bba61..7cb7860 100644 --- a/Samples/Mesh Generator/Runtime/SplineEditor.Samples.MeshGenerator.asmdef +++ b/Samples/Mesh Generator/Runtime/SplineEditor.Samples.MeshGenerator.asmdef @@ -2,7 +2,8 @@ "name": "SplineEditor.Samples.MeshGenerator", "rootNamespace": "", "references": [ - "GUID:08bff4c7283eee24999c67b8ee6a1dbd" + "GUID:08bff4c7283eee24999c67b8ee6a1dbd", + "GUID:2665a8d13d1b3f18800f46e256720795" ], "includePlatforms": [], "excludePlatforms": [], diff --git a/Samples/Mesh Generator/Runtime/SplineMesh.cs b/Samples/Mesh Generator/Runtime/SplineMesh.cs index e78df01..ff38183 100644 --- a/Samples/Mesh Generator/Runtime/SplineMesh.cs +++ b/Samples/Mesh Generator/Runtime/SplineMesh.cs @@ -3,9 +3,10 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // +using System; +using System.Collections.Generic; using UnityEngine; using UnityEngine.Assertions; - #if UNITY_EDITOR using UnityEditor; #endif @@ -22,14 +23,9 @@ namespace SplineEditor.MeshGenerator [ExecuteAlways] public class SplineMesh : MonoBehaviour { - private const float Precision = 0.0001f; private const float MinSpacingValue = 0.1f; private const float MinWidthValue = 0.001f; -#if UNITY_EDITOR - private const int EditorLateUpdateFramesDelay = 5; -#endif - [SerializeField] private float width = 5f; [SerializeField] @@ -56,13 +52,7 @@ public class SplineMesh : MonoBehaviour private SplinePath splinePath; private Mesh cachedMesh; - -#if UNITY_EDITOR - private int editorLateUpdateCounter = 0; - private bool useEditorDelay = false; -#endif - - private bool updateMesh = false; + private MeshJobExecutor generateMeshJobExecutor; /// /// UV generation mode type. @@ -84,7 +74,7 @@ public enum UVMode /// /// Gets or sets points on generated on the spline to create the mesh. /// - public Vector3[] Points + public List Points { get => splinePath.Points; set => splinePath.Points = value; @@ -94,7 +84,7 @@ public Vector3[] Points /// Gets or sets normals corresponding to the points on mesh. /// Generated based on Tangents. /// - public Vector3[] Normals + public List Normals { get => splinePath.Normals; set => splinePath.Normals = value; @@ -103,7 +93,7 @@ public Vector3[] Normals /// /// Gets or sets tangents of the points on the mesh based on the spline. /// - public Vector3[] Tangents + public List Tangents { get => splinePath.Tangents; set => splinePath.Tangents = value; @@ -112,7 +102,7 @@ public Vector3[] Tangents /// /// Gets or sets scales of the points on the mesh. /// - public Vector3[] Scale + public List Scale { get => splinePath.Scales; set => splinePath.Scales = value; @@ -121,7 +111,7 @@ public Vector3[] Scale /// /// Gets or sets value of parameter T on the points on mesh regarding to spline. /// - public float[] ParametersT + public List ParametersT { get => splinePath.ParametersT; set => splinePath.ParametersT = value; @@ -137,11 +127,7 @@ public float Width { var newValue = Mathf.Max(MinWidthValue, value); width = newValue; - updateMesh = true; - -#if UNITY_EDITOR - useEditorDelay = false; -#endif + GenerateMesh(); } } @@ -155,11 +141,7 @@ public float Spacing { var newValue = Mathf.Max(MinSpacingValue, value); spacing = newValue; - updateMesh = true; - -#if UNITY_EDITOR - useEditorDelay = false; -#endif + GenerateMesh(); } } @@ -173,12 +155,7 @@ public bool UseAsymetricWidthCurve set { useAsymetricWidthCurve = value; - updateMesh = true; - -#if UNITY_EDITOR - useEditorDelay = false; -#endif - + GenerateMesh(); } } @@ -192,12 +169,7 @@ public CustomAnimationCurve RightSideCurve set { rightSideCurve = value; - updateMesh = true; - -#if UNITY_EDITOR - useEditorDelay = true; -#endif - + GenerateMesh(); } } @@ -211,11 +183,7 @@ public CustomAnimationCurve LeftSideCurve set { leftSideCurve = value; - updateMesh = true; - -#if UNITY_EDITOR - useEditorDelay = true; -#endif + GenerateMesh(); } } @@ -228,11 +196,7 @@ public bool UsePointsScale set { usePointsScale = value; - updateMesh = true; - -#if UNITY_EDITOR - useEditorDelay = false; -#endif + GenerateMesh(); } } @@ -244,11 +208,7 @@ public UVMode UvMode get => uvMode; set { uvMode = value; - updateMesh = true; - -#if UNITY_EDITOR - useEditorDelay = false; -#endif + GenerateMesh(); } } @@ -261,11 +221,7 @@ public bool MirrorUV get => mirrorUV; set { mirrorUV = value; - updateMesh = true; - -#if UNITY_EDITOR - useEditorDelay = false; -#endif + GenerateMesh(); } } @@ -285,72 +241,25 @@ public bool MirrorUV public BezierSpline BezierSpline => bezierSpline; /// - /// Constructs and assigned mesh based on the spline. + /// Constructs and updates spline mesh using Unity Jobs. /// [ContextMenu("Generate Mesh")] public void GenerateMesh() { - if (BezierSpline == null || MeshFilter == null) - { - return; - } - - ConstructMesh(); - meshFilter.sharedMesh = cachedMesh; + var config = SplineMeshConfiguration.Instance; + GenerateMesh(!config.UseJobsWithCorotuines); } /// - /// Constructs mesh based on the spline. + /// Constructs and assignes mesh based on the spline using Unity Jobs system. /// - /// Constructed mesh based on BezierSpline component. - public Mesh ConstructMesh() + /// Should mesh be generated in the same frame. + /// Action invoked when mesh is generated. + public void GenerateMesh(bool immediate = false, Action onMeshGenerated = null) { - int[] triangleMap = { 0, 2, 1, 1, 2, 3 }; - - if (splinePath == null) - { - splinePath = new SplinePath(); - } - - BezierSpline.RecalculateNormals(); - BezierSpline.GetEvenlySpacedPoints(Spacing, splinePath, Precision, false); - - var isLoop = BezierSpline.IsLoop; - var verts = new Vector3[Points.Length * 2]; - var normals = new Vector3[Points.Length * 2]; - var uvs = new Vector2[verts.Length]; - var numTris = (2 * (Points.Length - 1)) + (isLoop ? 2 : 1); - var tris = new int[numTris * 3]; - var vertIndex = 0; - var triIndex = 0; - - for (int i = 0; i < Points.Length; i++) + if (BezierSpline == null || MeshFilter == null) { - var normalVector = Normals[i]; - var right = Vector3.Cross(normalVector, Tangents[i]).normalized; - var rightScaledWidth = Width * (UsePointsScale ? Scale[i].x : 1f) * RightSideCurve.Evaluate(ParametersT[i]); - var leftScaledWidth = Width * (UsePointsScale ? Scale[i].x : 1f) * LeftSideCurve.Evaluate(ParametersT[i]); - - verts[vertIndex] = Points[i] - (right * (UseAsymetricWidthCurve ? leftScaledWidth : rightScaledWidth)); - verts[vertIndex + 1] = Points[i] + (right * rightScaledWidth); - - normals[vertIndex] = normalVector; - normals[vertIndex + 1] = normalVector; - - var v = GetUV(i); - uvs[vertIndex] = new Vector2(0, v); - uvs[vertIndex + 1] = new Vector2(1, v); - - if (i < Points.Length - 1 || isLoop) - { - for (int j = 0; j < triangleMap.Length; j++) - { - tris[triIndex + j] = (vertIndex + triangleMap[j]) % verts.Length; - } - } - - vertIndex += 2; - triIndex += 6; + return; } if (cachedMesh == null) @@ -358,35 +267,23 @@ public Mesh ConstructMesh() cachedMesh = new Mesh(); } - cachedMesh.Clear(); - cachedMesh.vertices = verts; - cachedMesh.normals = normals; - cachedMesh.triangles = tris; - cachedMesh.uv = uvs; - - return cachedMesh; - } + if (splinePath == null) + { + splinePath = new SplinePath(); + } - private float GetUV(int pointIndex) - { - var uv = pointIndex / (float)(Points.Length - 1); - switch (UvMode) + if (generateMeshJobExecutor == null) { - case UVMode.PingPong: - uv = 1 - Mathf.Abs((2 * uv) - 1); - break; - case UVMode.Linear: - default: - break; + generateMeshJobExecutor = new MeshJobExecutor(this, splinePath); } - return MirrorUV ? 1 - uv : uv; + generateMeshJobExecutor.Setup(this, splinePath); + generateMeshJobExecutor.GenerateMesh(cachedMesh, onMeshGenerated, immediate); + meshFilter.sharedMesh = cachedMesh; } private void OnValidate() { - updateMesh = true; - if (meshFilter == null) { meshFilter = GetComponent(); @@ -401,6 +298,16 @@ private void OnValidate() { bezierSpline = GetComponent(); } + + if (splinePath == null) + { + splinePath = new SplinePath(); + } + +#if UNITY_EDITOR + bezierSpline.OnSplineChanged -= GenerateMesh; + bezierSpline.OnSplineChanged += GenerateMesh; +#endif } private void Awake() @@ -420,44 +327,41 @@ private void Awake() bezierSpline = GetComponent(); } + if (splinePath == null) + { + splinePath = new SplinePath(); + } + Assert.IsNotNull(meshFilter); Assert.IsNotNull(meshRenderer); Assert.IsNotNull(bezierSpline); - } - private void OnEnable() - { - bezierSpline.OnSplineChanged += GenerateMesh; - } - - private void OnDisable() - { +#if UNITY_EDITOR bezierSpline.OnSplineChanged -= GenerateMesh; + bezierSpline.OnSplineChanged += GenerateMesh; +#endif } - private void LateUpdate() + private void OnEnable() { - if (!updateMesh) + if (bezierSpline == null) { return; } -#if UNITY_EDITOR + bezierSpline.OnSplineChanged -= GenerateMesh; + bezierSpline.OnSplineChanged += GenerateMesh; + GenerateMesh(); + } - if (useEditorDelay && editorLateUpdateCounter < EditorLateUpdateFramesDelay) + private void OnDisable() + { + if (bezierSpline == null) { - editorLateUpdateCounter++; return; } - else - { - editorLateUpdateCounter = 0; - useEditorDelay = false; - } -#endif - GenerateMesh(); - updateMesh = false; + bezierSpline.OnSplineChanged -= GenerateMesh; } } -} +} \ No newline at end of file diff --git a/Samples/Mesh Generator/Editor/SplineMeshEditorConfiguration.cs b/Samples/Mesh Generator/Runtime/SplineMeshConfiguration.cs similarity index 67% rename from Samples/Mesh Generator/Editor/SplineMeshEditorConfiguration.cs rename to Samples/Mesh Generator/Runtime/SplineMeshConfiguration.cs index b31df7c..a12f647 100644 --- a/Samples/Mesh Generator/Editor/SplineMeshEditorConfiguration.cs +++ b/Samples/Mesh Generator/Runtime/SplineMeshConfiguration.cs @@ -1,4 +1,4 @@ -// +// // Copyright (c) vvrvvd. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. // @@ -8,12 +8,12 @@ namespace SplineEditor.MeshGenerator { /// - /// Scriptable object containing SplineMesh editor configuration. + /// Scriptable object containing SplineMesh configuration. /// - [CreateAssetMenu(fileName = "SplineMeshEditorConfiguration", menuName = "Spline Editor/Mesh Generator/Mesh Generator Configuration", order = 1)] - public class SplineMeshEditorConfiguration : ScriptableObject + [CreateAssetMenu(fileName = "SplineMeshConfiguration", menuName = "Spline Editor/Mesh Generator/Mesh Generator Configuration", order = 1)] + public class SplineMeshConfiguration : ScriptableObject { - private static SplineMeshEditorConfiguration instance; + private static SplineMeshConfiguration instance; [Header("General")] [SerializeField] @@ -29,17 +29,22 @@ public class SplineMeshEditorConfiguration : ScriptableObject [SerializeField] private float normalVectorLength = 2.5f; + [SerializeField] + [Tooltip("Decreases the main thread overload. Helps when working on complex meshes.")] + [Header("Experimental")] + private bool useJobsWithCoroutines = false; + /// /// Gets the first SplineMesh editor configuration object found in the resources. /// Caches the result so it's loaded from resources only once. /// - public static SplineMeshEditorConfiguration Instance + public static SplineMeshConfiguration Instance { get { if (instance == null) { - var loadedInstances = Resources.LoadAll(string.Empty); + var loadedInstances = Resources.LoadAll(string.Empty); if (loadedInstances.Length == 0) { @@ -54,6 +59,13 @@ public static SplineMeshEditorConfiguration Instance } } + /// + /// Gets or sets a value indicating whether async Jobs awaiting should be used for mesh generation. + /// If set to true then a Coroutine that waits for job to be finish is created every time job is used for mesh generation. + /// Is serialized. + /// + public bool UseJobsWithCorotuines { get => useJobsWithCoroutines; set => useJobsWithCoroutines = value; } + /// /// Gets or sets material used for visualizing mesh UV in editor. /// Is serialized. diff --git a/Samples/Mesh Generator/Editor/SplineMeshEditorConfiguration.cs.meta b/Samples/Mesh Generator/Runtime/SplineMeshConfiguration.cs.meta similarity index 100% rename from Samples/Mesh Generator/Editor/SplineMeshEditorConfiguration.cs.meta rename to Samples/Mesh Generator/Runtime/SplineMeshConfiguration.cs.meta diff --git a/package.json b/package.json index 344037d..da33747 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,12 @@ { "name": "com.vvrvvd.spline-editor", - "version": "2.1.3", + "version": "2.2.3", "displayName": "Spline Editor", "description": "Unity Spline Editor is an open-source tool for creating and managing cubic bezier curves in Unity Editor. The tool let you do the basic operations like adding, removing or splitting curves but also provides you with option to factor, simplify, edit normals, draw or cast splines to camera view. You can also adjust how splines are displayed in the editor through settings window.", + "dependencies": + { + "com.unity.burst": "1.4.8" + }, "keywords": [ "spline", "curve", "bezier", "editor" ], "unity": "2020.1", "author": { @@ -13,12 +17,12 @@ "samples": [ { "displayName": "Mesh Generator", - "description": "Mesh Generator", + "description": "Generating simple flat meshes based on BezierSpline.", "path": "Samples/Mesh Generator" }, { "displayName": "Line Renderer Spline", - "description": "Line Renderer Spline", + "description": "Using Line Renderer component for visualizing BezierSpline in the runtime.", "path": "Samples/Line Renderer" }] }