A game about forced loneliness, made by TACStudios
at master 256 lines 10 kB view raw
1using System.Collections.Generic; 2using Unity.Burst; 3using Unity.Collections; 4using Unity.Collections.LowLevel.Unsafe; 5using Unity.Mathematics; 6using UnityEditor.U2D.Common; 7using UnityEngine; 8using UnityEngine.U2D.Animation; 9 10namespace UnityEditor.U2D.Animation 11{ 12 [BurstCompile] 13 internal static class BatchedDrawing 14 { 15 class Batch 16 { 17 public UnsafeList<float3> vertices; 18 public UnsafeList<Color> vertexColors; 19 public UnsafeList<int> indices; 20 21 public Batch() 22 { 23 vertices = new UnsafeList<float3>(1, Allocator.Persistent); 24 indices = new UnsafeList<int>(1, Allocator.Persistent); 25 vertexColors = new UnsafeList<Color>(1, Allocator.Persistent); 26 } 27 28 ~Batch() 29 { 30 vertices.Dispose(); 31 indices.Dispose(); 32 vertexColors.Dispose(); 33 } 34 35 public void Clear() 36 { 37 vertices.Clear(); 38 indices.Clear(); 39 vertexColors.Clear(); 40 } 41 } 42 43 // Unity's max index limit for meshes. 44 const int k_MaxIndexLimit = 65535; 45 46 static readonly int s_HandleSize = Shader.PropertyToID("_HandleSize"); 47 48 static readonly List<Batch> s_Batches = new List<Batch>(1) { new Batch() }; 49 static Mesh s_Mesh; 50 static NativeArray<float3> s_VertexTmpCache = default; 51 52 public static unsafe void RegisterLine(float3 p1, float3 p2, float3 normal, float widthP1, float widthP2, Color color) 53 { 54 var up = math.cross(normal, p2 - p1); 55 up = math.normalize(up); 56 57 const int dataToAdd = 6; 58 var batch = GetBatch(dataToAdd); 59 var startIndex = batch.vertices.Length; 60 61 batch.indices.Resize(startIndex + dataToAdd); 62 batch.vertexColors.Resize(startIndex + dataToAdd); 63 batch.vertices.Resize(startIndex + dataToAdd); 64 65 var vertexPtr = batch.vertices.Ptr; 66 vertexPtr[startIndex] = p1 + up * (widthP1 * 0.5f); 67 vertexPtr[startIndex + 1] = p1 - up * (widthP1 * 0.5f); 68 vertexPtr[startIndex + 2] = p2 - up * (widthP2 * 0.5f); 69 vertexPtr[startIndex + 3] = p1 + up * (widthP1 * 0.5f); 70 vertexPtr[startIndex + 4] = p2 - up * (widthP2 * 0.5f); 71 vertexPtr[startIndex + 5] = p2 + up * (widthP2 * 0.5f); 72 73 for (var i = 0; i < dataToAdd; ++i) 74 { 75 batch.indices.Ptr[startIndex + i] = startIndex + i; 76 batch.vertexColors.Ptr[startIndex + i] = color; 77 } 78 } 79 80 public static void RegisterSolidDisc(float3 center, float3 normal, float radius, Color color) 81 { 82 var from = math.cross(normal, math.up()); 83 if (math.lengthsq(from) < 1.0 / 1000.0) 84 from = math.cross(normal, math.right()); 85 RegisterSolidArc(center, normal, from, 360f, radius, color); 86 } 87 88 public static unsafe void RegisterSolidArc(float3 center, float3 normal, float3 from, float angle, float radius, Color color, int numSamples = 60) 89 { 90 numSamples = math.clamp(numSamples, 3, 60); 91 92 if (s_VertexTmpCache == default) 93 s_VertexTmpCache = new NativeArray<float3>(60, Allocator.Persistent); 94 SetDiscSectionPoints(ref s_VertexTmpCache, numSamples, in normal, in from, angle); 95 96 var dataToAdd = (numSamples - 1) * 3; 97 var batch = GetBatch(dataToAdd); 98 var startIndex = batch.vertices.Length; 99 100 batch.indices.Resize(startIndex + dataToAdd); 101 batch.vertexColors.Resize(startIndex + dataToAdd); 102 batch.vertices.Resize(startIndex + dataToAdd); 103 104 CreateSolidArcVertices(ref batch.vertices, startIndex, in s_VertexTmpCache, in center, numSamples, radius); 105 106 for (var i = 0; i < dataToAdd; ++i) 107 { 108 batch.indices.Ptr[startIndex + i] = startIndex + i; 109 batch.vertexColors.Ptr[startIndex + i] = color; 110 } 111 } 112 113 [BurstCompile] 114 static void CreateSolidArcVertices( 115 ref UnsafeList<float3> vertexPtr, 116 int startIndex, 117 in NativeArray<float3> vertexCache, 118 in float3 center, 119 int numSamples, 120 float radius) 121 { 122 var count = 0; 123 for (var i = 1; i < numSamples; i++, count += 3) 124 { 125 var index = startIndex + count; 126 vertexPtr[index] = center; 127 vertexPtr[index + 1] = center + vertexCache[i - 1] * radius; 128 vertexPtr[index + 2] = center + vertexCache[i] * radius; 129 } 130 } 131 132 public static unsafe void RegisterSolidArcWithOutline(float3 center, float3 normal, float3 from, float angle, 133 float radius, float outlineScale, Color color, int numSamples = 60) 134 { 135 numSamples = Mathf.Clamp(numSamples, 3, 60); 136 137 if (s_VertexTmpCache == default) 138 s_VertexTmpCache = new NativeArray<float3>(60, Allocator.Persistent); 139 SetDiscSectionPoints(ref s_VertexTmpCache, numSamples, in normal, in from, angle); 140 141 var dataToAdd = (numSamples - 1) * 6; 142 var batch = GetBatch(dataToAdd); 143 var startIndex = batch.vertices.Length; 144 145 batch.indices.Resize(startIndex + dataToAdd); 146 batch.vertexColors.Resize(startIndex + dataToAdd); 147 batch.vertices.Resize(startIndex + dataToAdd); 148 149 // var vertexPtr = batch.vertices.Ptr + startIndex; 150 CreateSolidArcWithOutlineVertices(ref batch.vertices, startIndex, in s_VertexTmpCache, in center, numSamples, outlineScale, radius); 151 152 for (var i = 0; i < dataToAdd; ++i) 153 { 154 batch.indices.Ptr[startIndex + i] = startIndex + i; 155 batch.vertexColors.Ptr[startIndex + i] = color; 156 } 157 } 158 159 [BurstCompile] 160 static void CreateSolidArcWithOutlineVertices( 161 ref UnsafeList<float3> vertexPtr, 162 int startIndex, 163 in NativeArray<float3> vertexCache, 164 in float3 center, 165 int numSamples, 166 float outlineScale, 167 float radius) 168 { 169 var count = 0; 170 for (var i = 1; i < numSamples; i++, count += 6) 171 { 172 var index = startIndex + count; 173 vertexPtr[index] = center + vertexCache[i - 1] * (radius * outlineScale); 174 vertexPtr[index + 1] = center + vertexCache[i - 1] * radius; 175 vertexPtr[index + 2] = center + vertexCache[i] * radius; 176 vertexPtr[index + 3] = center + vertexCache[i - 1] * (radius * outlineScale); 177 vertexPtr[index + 4] = center + vertexCache[i] * radius; 178 vertexPtr[index + 5] = center + vertexCache[i] * (radius * outlineScale); 179 } 180 } 181 182 [BurstCompile] 183 static void SetDiscSectionPoints(ref NativeArray<float3> dest, int count, in float3 normal, in float3 from, float angle) 184 { 185 var angleInRadians = math.degrees(angle / (float)(count - 1)); 186 var rotation = quaternion.AxisAngle(normal, angleInRadians); 187 188 var vector = math.normalize(from); 189 for (var i = 0; i < count; i++) 190 { 191 dest[i] = vector; 192 vector = math.mul(rotation, vector); 193 } 194 } 195 196 static Batch GetBatch(int dataToAdd) 197 { 198 for (var i = 0; i < s_Batches.Count; ++i) 199 { 200 if ((s_Batches[i].indices.Length + dataToAdd) < k_MaxIndexLimit) 201 return s_Batches[i]; 202 } 203 204 var newBatch = new Batch(); 205 s_Batches.Add(newBatch); 206 return newBatch; 207 } 208 209 public static void Draw() 210 { 211 if (s_Batches[0].indices.Length == 0) 212 return; 213 if (Event.current.type != EventType.Repaint) 214 return; 215 216 Shader.SetGlobalFloat(s_HandleSize, 1); 217 InternalEditorBridge.ApplyWireMaterial(); 218 219 for (var i = 0; i < s_Batches.Count; ++i) 220 { 221 DrawBatch(s_Batches[i]); 222 s_Batches[i].Clear(); 223 } 224 225 s_VertexTmpCache.DisposeIfCreated(); 226 s_VertexTmpCache = default; 227 } 228 229 static unsafe void DrawBatch(Batch batch) 230 { 231 var vertexPtr = batch.vertices.Ptr; 232 var indexPtr = batch.indices.Ptr; 233 var vertexColorPtr = batch.vertexColors.Ptr; 234 235 var vertexCount = batch.vertices.Length; 236 237 var vertexArr = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray<Vector3>(vertexPtr, vertexCount, batch.vertices.Allocator.ToAllocator); 238 var indexArr = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray<int>(indexPtr, vertexCount, batch.indices.Allocator.ToAllocator); 239 var colorArr = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray<Color>(vertexColorPtr, vertexCount, batch.vertexColors.Allocator.ToAllocator); 240 241 NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref vertexArr, AtomicSafetyHandle.GetTempUnsafePtrSliceHandle()); 242 NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref indexArr, AtomicSafetyHandle.GetTempUnsafePtrSliceHandle()); 243 NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref colorArr, AtomicSafetyHandle.GetTempUnsafePtrSliceHandle()); 244 245 if (s_Mesh == null) 246 s_Mesh = new Mesh(); 247 else 248 s_Mesh.Clear(); 249 250 s_Mesh.SetVertices(vertexArr); 251 s_Mesh.SetIndices(indexArr, MeshTopology.Triangles, 0); 252 s_Mesh.SetColors(colorArr); 253 Graphics.DrawMeshNow(s_Mesh, Handles.matrix); 254 } 255 } 256}