com.wallstop-studios.unity-helpers 2.0.0-rc76.1 → 2.0.0-rc76.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Editor/Sprites/SpriteCropper.cs +9 -2
- package/Editor/Sprites/SpritePivotAdjustor.cs +259 -0
- package/Editor/Sprites/SpritePivotAdjustor.cs.meta +3 -0
- package/Runtime/Core/DataStructure/Circle.cs +1 -1
- package/Runtime/Core/DataStructure/CyclicBuffer.cs +65 -2
- package/Runtime/Core/DataStructure/ISpatialTree.cs +7 -46
- package/Runtime/Core/DataStructure/KDTree.cs +266 -130
- package/Runtime/Core/DataStructure/QuadTree.cs +258 -128
- package/Runtime/Core/DataStructure/Trie.cs +359 -0
- package/Runtime/Core/DataStructure/Trie.cs.meta +3 -0
- package/Runtime/Core/Extension/EnumExtensions.cs +4 -4
- package/Runtime/Core/Helper/UnityMainThreadDispatcher.cs +3 -1
- package/Runtime/Core/Threading/SingleThreadedThreadPool.cs +7 -2
- package/Runtime/UI/LayeredImage.cs +0 -1
- package/Tests/Runtime/DataStructures/SpatialTreeTests.cs +6 -6
- package/Tests/Runtime/Performance/QuadTreePerformanceTests.cs +1 -1
- package/Tests/Runtime/Performance/SpatialTreePerformanceTest.cs +23 -18
- package/package.json +4 -1
- package/Editor/UI.meta +0 -3
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
using System;
|
|
4
4
|
using System.Collections.Generic;
|
|
5
5
|
using System.Collections.Immutable;
|
|
6
|
-
using System.Linq;
|
|
7
6
|
using Extension;
|
|
8
7
|
using UnityEngine;
|
|
9
8
|
using Utils;
|
|
@@ -14,90 +13,111 @@
|
|
|
14
13
|
private const int NumChildren = 4;
|
|
15
14
|
|
|
16
15
|
[Serializable]
|
|
17
|
-
public
|
|
16
|
+
public readonly struct Entry
|
|
18
17
|
{
|
|
19
|
-
|
|
18
|
+
public readonly T value;
|
|
19
|
+
public readonly Vector2 position;
|
|
20
|
+
|
|
21
|
+
public Entry(T value, Vector2 position)
|
|
22
|
+
{
|
|
23
|
+
this.value = value;
|
|
24
|
+
this.position = position;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
[Serializable]
|
|
29
|
+
public sealed class QuadTreeNode
|
|
30
|
+
{
|
|
31
|
+
private static readonly List<Entry>[] Buffers = new List<Entry>[NumChildren];
|
|
32
|
+
|
|
33
|
+
static QuadTreeNode()
|
|
34
|
+
{
|
|
35
|
+
for (int i = 0; i < Buffers.Length; ++i)
|
|
36
|
+
{
|
|
37
|
+
Buffers[i] = new List<Entry>();
|
|
38
|
+
}
|
|
39
|
+
}
|
|
20
40
|
|
|
21
41
|
public readonly Bounds boundary;
|
|
22
|
-
internal readonly QuadTreeNode
|
|
23
|
-
public readonly
|
|
42
|
+
internal readonly QuadTreeNode[] children;
|
|
43
|
+
public readonly Entry[] elements;
|
|
24
44
|
public readonly bool isTerminal;
|
|
25
45
|
|
|
26
|
-
public QuadTreeNode(
|
|
27
|
-
V[] elements,
|
|
28
|
-
Func<V, Vector2> elementTransformer,
|
|
29
|
-
Bounds boundary,
|
|
30
|
-
int bucketSize
|
|
31
|
-
)
|
|
46
|
+
public QuadTreeNode(Entry[] elements, Bounds boundary, int bucketSize)
|
|
32
47
|
{
|
|
33
48
|
this.boundary = boundary;
|
|
34
49
|
this.elements = elements;
|
|
35
50
|
isTerminal = elements.Length <= bucketSize;
|
|
36
51
|
if (isTerminal)
|
|
37
52
|
{
|
|
38
|
-
children = Array.Empty<QuadTreeNode
|
|
53
|
+
children = Array.Empty<QuadTreeNode>();
|
|
39
54
|
return;
|
|
40
55
|
}
|
|
41
|
-
children = new QuadTreeNode<V>[NumChildren];
|
|
42
56
|
|
|
43
|
-
|
|
44
|
-
Vector2 halfQuadrantSize = quadrantSize / 2f;
|
|
57
|
+
children = new QuadTreeNode[NumChildren];
|
|
45
58
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
59
|
+
Vector3 quadrantSize = boundary.size / 2f;
|
|
60
|
+
quadrantSize.z = 1;
|
|
61
|
+
Vector3 halfQuadrantSize = quadrantSize / 2f;
|
|
62
|
+
|
|
63
|
+
Vector3 boundaryCenter = boundary.center;
|
|
64
|
+
Span<Bounds> quadrants = stackalloc Bounds[4];
|
|
65
|
+
quadrants[0] = new Bounds(
|
|
66
|
+
new Vector3(
|
|
67
|
+
boundaryCenter.x - halfQuadrantSize.x,
|
|
68
|
+
boundaryCenter.y + halfQuadrantSize.y
|
|
55
69
|
),
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
quadrantSize
|
|
70
|
+
quadrantSize
|
|
71
|
+
);
|
|
72
|
+
quadrants[1] = new Bounds(
|
|
73
|
+
new Vector3(
|
|
74
|
+
boundaryCenter.x + halfQuadrantSize.x,
|
|
75
|
+
boundaryCenter.y + halfQuadrantSize.y
|
|
63
76
|
),
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
quadrantSize
|
|
77
|
+
quadrantSize
|
|
78
|
+
);
|
|
79
|
+
quadrants[2] = new Bounds(
|
|
80
|
+
new Vector3(
|
|
81
|
+
boundaryCenter.x + halfQuadrantSize.x,
|
|
82
|
+
boundaryCenter.y - halfQuadrantSize.y
|
|
71
83
|
),
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
quadrantSize
|
|
84
|
+
quadrantSize
|
|
85
|
+
);
|
|
86
|
+
quadrants[3] = new Bounds(
|
|
87
|
+
new Vector3(
|
|
88
|
+
boundaryCenter.x - halfQuadrantSize.x,
|
|
89
|
+
boundaryCenter.y - halfQuadrantSize.y
|
|
79
90
|
),
|
|
80
|
-
|
|
91
|
+
quadrantSize
|
|
92
|
+
);
|
|
81
93
|
|
|
82
|
-
|
|
94
|
+
foreach (List<Entry> buffer in Buffers)
|
|
95
|
+
{
|
|
96
|
+
buffer.Clear();
|
|
97
|
+
}
|
|
98
|
+
foreach (Entry element in elements)
|
|
83
99
|
{
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
foreach (V element in elements)
|
|
100
|
+
Vector2 position = element.position;
|
|
101
|
+
for (int i = 0; i < quadrants.Length; i++)
|
|
87
102
|
{
|
|
88
|
-
|
|
103
|
+
Bounds quadrant = quadrants[i];
|
|
104
|
+
if (quadrant.FastContains2D(position))
|
|
89
105
|
{
|
|
90
|
-
|
|
106
|
+
Buffers[i].Add(element);
|
|
107
|
+
break;
|
|
91
108
|
}
|
|
92
109
|
}
|
|
93
|
-
|
|
94
|
-
children[i] = new QuadTreeNode<V>(
|
|
95
|
-
Buffer.ToArray(),
|
|
96
|
-
elementTransformer,
|
|
97
|
-
quadrant,
|
|
98
|
-
bucketSize
|
|
99
|
-
);
|
|
100
110
|
}
|
|
111
|
+
|
|
112
|
+
Entry[] entriesOne = Buffers[0].ToArray();
|
|
113
|
+
Entry[] entriesTwo = Buffers[1].ToArray();
|
|
114
|
+
Entry[] entriesThree = Buffers[2].ToArray();
|
|
115
|
+
Entry[] entriesFour = Buffers[3].ToArray();
|
|
116
|
+
|
|
117
|
+
children[0] = new QuadTreeNode(entriesOne, quadrants[0], bucketSize);
|
|
118
|
+
children[1] = new QuadTreeNode(entriesTwo, quadrants[1], bucketSize);
|
|
119
|
+
children[2] = new QuadTreeNode(entriesThree, quadrants[2], bucketSize);
|
|
120
|
+
children[3] = new QuadTreeNode(entriesFour, quadrants[3], bucketSize);
|
|
101
121
|
}
|
|
102
122
|
}
|
|
103
123
|
|
|
@@ -105,11 +125,9 @@
|
|
|
105
125
|
|
|
106
126
|
public readonly ImmutableArray<T> elements;
|
|
107
127
|
public Bounds Boundary => _bounds;
|
|
108
|
-
public Func<T, Vector2> ElementTransformer => _elementTransformer;
|
|
109
128
|
|
|
110
129
|
private readonly Bounds _bounds;
|
|
111
|
-
private readonly
|
|
112
|
-
private readonly QuadTreeNode<T> _head;
|
|
130
|
+
private readonly QuadTreeNode _head;
|
|
113
131
|
|
|
114
132
|
public QuadTree(
|
|
115
133
|
IEnumerable<T> points,
|
|
@@ -118,62 +136,164 @@
|
|
|
118
136
|
int bucketSize = DefaultBucketSize
|
|
119
137
|
)
|
|
120
138
|
{
|
|
121
|
-
|
|
122
|
-
|
|
139
|
+
if (elementTransformer is null)
|
|
140
|
+
{
|
|
141
|
+
throw new ArgumentNullException(nameof(elementTransformer));
|
|
142
|
+
}
|
|
123
143
|
elements =
|
|
124
144
|
points?.ToImmutableArray() ?? throw new ArgumentNullException(nameof(points));
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
145
|
+
bool anyPoints = false;
|
|
146
|
+
Bounds bounds = new();
|
|
147
|
+
Entry[] entries = new Entry[elements.Length];
|
|
148
|
+
for (int i = 0; i < elements.Length; i++)
|
|
149
|
+
{
|
|
150
|
+
T element = elements[i];
|
|
151
|
+
Vector2 position = elementTransformer(element);
|
|
152
|
+
entries[i] = new Entry(element, position);
|
|
153
|
+
if (!anyPoints)
|
|
154
|
+
{
|
|
155
|
+
bounds = new Bounds(position, new Vector3(0, 0, 1f));
|
|
156
|
+
}
|
|
157
|
+
else
|
|
158
|
+
{
|
|
159
|
+
bounds.Encapsulate(position);
|
|
160
|
+
}
|
|
133
161
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
162
|
+
anyPoints = true;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
_bounds = bounds;
|
|
166
|
+
_head = new QuadTreeNode(entries, _bounds, bucketSize);
|
|
138
167
|
}
|
|
139
168
|
|
|
140
|
-
public
|
|
169
|
+
public List<T> GetElementsInRange(
|
|
170
|
+
Vector2 position,
|
|
171
|
+
float range,
|
|
172
|
+
List<T> elementsInRange,
|
|
173
|
+
float minimumRange = 0
|
|
174
|
+
)
|
|
141
175
|
{
|
|
176
|
+
elementsInRange.Clear();
|
|
177
|
+
Bounds bounds = new(position, new Vector3(range * 2, range * 2, 1f));
|
|
178
|
+
|
|
142
179
|
if (!bounds.FastIntersects2D(_bounds))
|
|
143
180
|
{
|
|
144
|
-
|
|
181
|
+
return elementsInRange;
|
|
145
182
|
}
|
|
146
183
|
|
|
147
|
-
Stack<QuadTreeNode
|
|
184
|
+
Stack<QuadTreeNode> nodesToVisit = Buffers<QuadTreeNode>.Stack;
|
|
148
185
|
nodesToVisit.Clear();
|
|
149
186
|
nodesToVisit.Push(_head);
|
|
150
187
|
|
|
151
|
-
|
|
188
|
+
List<QuadTreeNode> resultBuffer = Buffers<QuadTreeNode>.List;
|
|
189
|
+
resultBuffer.Clear();
|
|
190
|
+
|
|
191
|
+
while (nodesToVisit.TryPop(out QuadTreeNode currentNode))
|
|
152
192
|
{
|
|
153
|
-
if (currentNode.isTerminal)
|
|
193
|
+
if (currentNode.isTerminal || bounds.Overlaps2D(currentNode.boundary))
|
|
154
194
|
{
|
|
155
|
-
|
|
195
|
+
resultBuffer.Add(currentNode);
|
|
196
|
+
continue;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
foreach (QuadTreeNode child in currentNode.children)
|
|
200
|
+
{
|
|
201
|
+
if (child.elements.Length == 0)
|
|
156
202
|
{
|
|
157
|
-
|
|
203
|
+
continue;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
if (!bounds.FastIntersects2D(child.boundary))
|
|
207
|
+
{
|
|
208
|
+
continue;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
nodesToVisit.Push(child);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
float rangeSquared = range * range;
|
|
216
|
+
if (0 < minimumRange)
|
|
217
|
+
{
|
|
218
|
+
float minimumRangeSquared = minimumRange * minimumRange;
|
|
219
|
+
foreach (QuadTreeNode node in resultBuffer)
|
|
220
|
+
{
|
|
221
|
+
foreach (Entry element in node.elements)
|
|
222
|
+
{
|
|
223
|
+
float squareDistance = (element.position - position).sqrMagnitude;
|
|
224
|
+
if (squareDistance <= minimumRangeSquared || rangeSquared < squareDistance)
|
|
158
225
|
{
|
|
159
|
-
|
|
226
|
+
continue;
|
|
160
227
|
}
|
|
228
|
+
|
|
229
|
+
elementsInRange.Add(element.value);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
else
|
|
234
|
+
{
|
|
235
|
+
foreach (QuadTreeNode node in resultBuffer)
|
|
236
|
+
{
|
|
237
|
+
foreach (Entry element in node.elements)
|
|
238
|
+
{
|
|
239
|
+
if ((element.position - position).sqrMagnitude <= rangeSquared)
|
|
240
|
+
{
|
|
241
|
+
elementsInRange.Add(element.value);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
return elementsInRange;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
public List<T> GetElementsInBounds(Bounds bounds, List<T> elementsInBounds)
|
|
251
|
+
{
|
|
252
|
+
return GetElementsInBounds(bounds, elementsInBounds, Buffers<QuadTreeNode>.Stack);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
public List<T> GetElementsInBounds(
|
|
256
|
+
Bounds bounds,
|
|
257
|
+
List<T> elementsInBounds,
|
|
258
|
+
Stack<QuadTreeNode> nodeBuffer
|
|
259
|
+
)
|
|
260
|
+
{
|
|
261
|
+
elementsInBounds.Clear();
|
|
262
|
+
if (!bounds.FastIntersects2D(_bounds))
|
|
263
|
+
{
|
|
264
|
+
return elementsInBounds;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
Stack<QuadTreeNode> nodesToVisit = nodeBuffer ?? new Stack<QuadTreeNode>();
|
|
268
|
+
nodesToVisit.Clear();
|
|
269
|
+
nodesToVisit.Push(_head);
|
|
270
|
+
|
|
271
|
+
while (nodesToVisit.TryPop(out QuadTreeNode currentNode))
|
|
272
|
+
{
|
|
273
|
+
if (bounds.Overlaps2D(currentNode.boundary))
|
|
274
|
+
{
|
|
275
|
+
foreach (Entry element in currentNode.elements)
|
|
276
|
+
{
|
|
277
|
+
elementsInBounds.Add(element.value);
|
|
161
278
|
}
|
|
162
279
|
|
|
163
280
|
continue;
|
|
164
281
|
}
|
|
165
282
|
|
|
166
|
-
if (
|
|
283
|
+
if (currentNode.isTerminal)
|
|
167
284
|
{
|
|
168
|
-
foreach (
|
|
285
|
+
foreach (Entry element in currentNode.elements)
|
|
169
286
|
{
|
|
170
|
-
|
|
287
|
+
if (bounds.FastContains2D(element.position))
|
|
288
|
+
{
|
|
289
|
+
elementsInBounds.Add(element.value);
|
|
290
|
+
}
|
|
171
291
|
}
|
|
172
292
|
|
|
173
293
|
continue;
|
|
174
294
|
}
|
|
175
295
|
|
|
176
|
-
foreach (QuadTreeNode
|
|
296
|
+
foreach (QuadTreeNode child in currentNode.children)
|
|
177
297
|
{
|
|
178
298
|
if (child.elements.Length <= 0)
|
|
179
299
|
{
|
|
@@ -188,6 +308,8 @@
|
|
|
188
308
|
nodesToVisit.Push(child);
|
|
189
309
|
}
|
|
190
310
|
}
|
|
311
|
+
|
|
312
|
+
return elementsInBounds;
|
|
191
313
|
}
|
|
192
314
|
|
|
193
315
|
public void GetApproximateNearestNeighbors(
|
|
@@ -196,16 +318,18 @@
|
|
|
196
318
|
List<T> nearestNeighbors
|
|
197
319
|
)
|
|
198
320
|
{
|
|
199
|
-
Stack<QuadTreeNode
|
|
200
|
-
List<QuadTreeNode
|
|
321
|
+
Stack<QuadTreeNode> nodeBuffer = Buffers<QuadTreeNode>.Stack;
|
|
322
|
+
List<QuadTreeNode> childrenBuffer = Buffers<QuadTreeNode>.List;
|
|
201
323
|
HashSet<T> nearestNeighborBuffer = Buffers<T>.HashSet;
|
|
324
|
+
List<Entry> nearestNeighborsCache = Buffers<Entry>.List;
|
|
202
325
|
GetApproximateNearestNeighbors(
|
|
203
326
|
position,
|
|
204
327
|
count,
|
|
205
328
|
nearestNeighbors,
|
|
206
329
|
nodeBuffer,
|
|
207
330
|
childrenBuffer,
|
|
208
|
-
nearestNeighborBuffer
|
|
331
|
+
nearestNeighborBuffer,
|
|
332
|
+
nearestNeighborsCache
|
|
209
333
|
);
|
|
210
334
|
}
|
|
211
335
|
|
|
@@ -214,71 +338,77 @@
|
|
|
214
338
|
Vector2 position,
|
|
215
339
|
int count,
|
|
216
340
|
List<T> nearestNeighbors,
|
|
217
|
-
Stack<QuadTreeNode
|
|
218
|
-
List<QuadTreeNode
|
|
219
|
-
HashSet<T> nearestNeighborBuffer
|
|
341
|
+
Stack<QuadTreeNode> nodeBuffer,
|
|
342
|
+
List<QuadTreeNode> childrenBuffer,
|
|
343
|
+
HashSet<T> nearestNeighborBuffer,
|
|
344
|
+
List<Entry> nearestNeighborsCache
|
|
220
345
|
)
|
|
221
346
|
{
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
Comparison<QuadTreeNode<T>> comparison = Comparison;
|
|
347
|
+
QuadTreeNode current = _head;
|
|
348
|
+
nodeBuffer ??= new Stack<QuadTreeNode>();
|
|
349
|
+
nodeBuffer.Clear();
|
|
350
|
+
nodeBuffer.Push(_head);
|
|
351
|
+
childrenBuffer ??= new List<QuadTreeNode>(NumChildren);
|
|
352
|
+
childrenBuffer.Clear();
|
|
353
|
+
nearestNeighborBuffer ??= new HashSet<T>(count);
|
|
354
|
+
nearestNeighborBuffer.Clear();
|
|
355
|
+
nearestNeighborsCache ??= new List<Entry>(count);
|
|
356
|
+
nearestNeighborsCache.Clear();
|
|
357
|
+
|
|
358
|
+
Comparison<QuadTreeNode> comparison = Comparison;
|
|
235
359
|
while (!current.isTerminal)
|
|
236
360
|
{
|
|
237
|
-
|
|
238
|
-
foreach (QuadTreeNode
|
|
361
|
+
childrenBuffer.Clear();
|
|
362
|
+
foreach (QuadTreeNode child in current.children)
|
|
239
363
|
{
|
|
240
|
-
|
|
364
|
+
childrenBuffer.Add(child);
|
|
241
365
|
}
|
|
242
|
-
|
|
243
|
-
for (int i =
|
|
366
|
+
childrenBuffer.Sort(comparison);
|
|
367
|
+
for (int i = childrenBuffer.Count - 1; 0 <= i; --i)
|
|
244
368
|
{
|
|
245
|
-
|
|
369
|
+
nodeBuffer.Push(childrenBuffer[i]);
|
|
246
370
|
}
|
|
247
371
|
|
|
248
|
-
current =
|
|
372
|
+
current = childrenBuffer[0];
|
|
249
373
|
if (current.elements.Length <= count)
|
|
250
374
|
{
|
|
251
375
|
break;
|
|
252
376
|
}
|
|
253
377
|
}
|
|
254
378
|
|
|
255
|
-
while (
|
|
379
|
+
while (
|
|
380
|
+
nearestNeighborBuffer.Count < count && nodeBuffer.TryPop(out QuadTreeNode selected)
|
|
381
|
+
)
|
|
256
382
|
{
|
|
257
|
-
foreach (
|
|
383
|
+
foreach (Entry element in selected.elements)
|
|
258
384
|
{
|
|
259
|
-
|
|
385
|
+
if (nearestNeighborBuffer.Add(element.value))
|
|
386
|
+
{
|
|
387
|
+
nearestNeighborsCache.Add(element);
|
|
388
|
+
}
|
|
260
389
|
}
|
|
261
390
|
}
|
|
262
391
|
|
|
263
|
-
|
|
264
|
-
{
|
|
265
|
-
nearestNeighbors.Add(element);
|
|
266
|
-
}
|
|
267
|
-
if (count < nearestNeighbors.Count)
|
|
392
|
+
if (count < nearestNeighborsCache.Count)
|
|
268
393
|
{
|
|
269
394
|
Vector2 localPosition = position;
|
|
270
|
-
|
|
271
|
-
nearestNeighbors.RemoveRange(count, nearestNeighbors.Count - count);
|
|
395
|
+
nearestNeighborsCache.Sort(NearestComparison);
|
|
272
396
|
|
|
273
|
-
int NearestComparison(
|
|
274
|
-
(
|
|
275
|
-
(
|
|
397
|
+
int NearestComparison(Entry lhs, Entry rhs) =>
|
|
398
|
+
(lhs.position - localPosition).sqrMagnitude.CompareTo(
|
|
399
|
+
(rhs.position - localPosition).sqrMagnitude
|
|
276
400
|
);
|
|
277
401
|
}
|
|
278
402
|
|
|
403
|
+
nearestNeighbors.Clear();
|
|
404
|
+
for (int i = 0; i < nearestNeighborsCache.Count && i < count; ++i)
|
|
405
|
+
{
|
|
406
|
+
nearestNeighbors.Add(nearestNeighborsCache[i].value);
|
|
407
|
+
}
|
|
408
|
+
|
|
279
409
|
return;
|
|
280
410
|
|
|
281
|
-
int Comparison(QuadTreeNode
|
|
411
|
+
int Comparison(QuadTreeNode lhs, QuadTreeNode rhs) =>
|
|
282
412
|
((Vector2)lhs.boundary.center - position).sqrMagnitude.CompareTo(
|
|
283
413
|
((Vector2)rhs.boundary.center - position).sqrMagnitude
|
|
284
414
|
);
|