com.wallstop-studios.unity-helpers 2.0.0-rc43 → 2.0.0-rc45
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/README.md +16 -0
- package/Runtime/Core/Helper/FormattingHelpers.cs +32 -0
- package/Runtime/Core/Helper/FormattingHelpers.cs.meta +3 -0
- package/Runtime/Core/Helper/Objects.cs +2 -2
- package/Runtime/Core/Helper/ReflectionHelpers.cs +156 -1
- package/Runtime/Core/Helper/SpriteHelpers.cs +7 -52
- package/Runtime/Core/Helper/WallMath.cs +5 -5
- package/Runtime/Core/Random/AbstractRandom.cs +6 -5
- package/Runtime/Core/Random/DotNetRandom.cs +2 -0
- package/Runtime/Core/Random/IRandom.cs +1 -0
- package/Runtime/Core/Random/LinearCongruentialGenerator.cs +49 -0
- package/Runtime/Core/Random/LinearCongruentialGenerator.cs.meta +3 -0
- package/Runtime/Core/Random/PcgRandom.cs +1 -1
- package/Runtime/Core/Random/RomuDuo.cs +1 -1
- package/Runtime/Core/Random/SplitMix64.cs +1 -1
- package/Runtime/Core/Random/SystemRandom.cs +1 -1
- package/Runtime/Core/Random/WyRandom.cs +1 -1
- package/Runtime/Core/Random/XorShiftRandom.cs +13 -8
- package/Runtime/Core/Random/XorShiroRandom.cs +2 -0
- package/Runtime/UI/LayeredImage.cs +2 -2
- package/Runtime/Utils/SpriteRendererMetadata.cs +104 -42
- package/Tests/Runtime/Helper/ArrayConverterTests.cs +3 -3
- package/Tests/Runtime/Helper/FormattingHelperTests.cs +129 -0
- package/Tests/Runtime/Helper/FormattingHelperTests.cs.meta +3 -0
- package/Tests/Runtime/Helper/ObjectHelperTests.cs +2 -2
- package/Tests/Runtime/Helper/ReflectionHelperTests.cs +356 -35
- package/Tests/Runtime/Helper/WallMathTests.cs +4 -4
- package/Tests/Runtime/Performance/RandomPerformanceTests.cs +21 -3
- package/Tests/Runtime/Random/LinearCongruentialGeneratorTests.cs +12 -0
- package/Tests/Runtime/Random/LinearCongruentialGeneratorTests.cs.meta +3 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -129,6 +129,22 @@ random.NextNoiseMap(width, height); // A configurable noise map generated using
|
|
|
129
129
|
- XorShift
|
|
130
130
|
- XorShiro
|
|
131
131
|
|
|
132
|
+
## Performance (Number of Operations / Second)
|
|
133
|
+
|
|
134
|
+
| Random | NextBool | Next | NextUInt | NextFloat | NextDouble | NextUint - Range | NextInt - Range |
|
|
135
|
+
| ------ | -------- | ---- | -------- | --------- | ---------- | ---------------- | --------------- |
|
|
136
|
+
| PcgRandom | 34,260,478 | 34,303,866 | 35,148,246 | 24,818,438 | 30,034,632 |22,436,474 |20,801,797 |
|
|
137
|
+
| SystemRandom | 28,698,806 | 30,040,782 | 20,435,092 | 24,079,399 | 27,284,147 |20,735,769 |19,861,780 |
|
|
138
|
+
| SquirrelRandom | 33,285,784 | 33,439,909 | 34,611,893 | 23,885,731 | 28,958,725 |21,520,279 |20,311,372 |
|
|
139
|
+
| XorShiftRandom | 34,695,989 | 35,147,320 | 35,997,718 | 25,248,238 | 31,582,991 |22,679,928 |21,255,319 |
|
|
140
|
+
| DotNetRandom | 18,097,489 | 18,191,042 | 18,783,063 | 14,061,444 | 15,730,439 |13,284,050 |12,596,913 |
|
|
141
|
+
| WyRandom | 28,490,852 | 29,086,052 | 29,724,907 | 20,252,065 | 24,542,201 |18,474,790 |17,404,641 |
|
|
142
|
+
| SplitMix64 | 34,301,843 | 34,343,404 | 35,512,284 | 24,289,416 | 30,586,231 |22,470,330 |20,850,965 |
|
|
143
|
+
| RomuDuo | 32,969,889 | 33,413,212 | 34,339,227 | 23,755,059 | 29,483,136 |21,671,641 |20,253,479 |
|
|
144
|
+
| XorShiroRandom | 31,529,025 | 31,717,709 | 32,536,277 | 22,421,715 | 27,619,417 |20,843,993 |19,270,063 |
|
|
145
|
+
| UnityRandom | 24,925,268 | 24,830,594 | 26,429,283 | 17,864,528 | 21,206,384 |16,376,626 |15,528,972 |
|
|
146
|
+
| LinearCongruentialGenerator | 35,013,818 | 35,025,182 | 35,843,533 | 25,093,401 | 31,553,487 |22,579,798 |21,211,175 |
|
|
147
|
+
|
|
132
148
|
# Spatial Trees
|
|
133
149
|
There are three implemented 2D immutable spatial trees that can store generic objects, as long as there is some resolution function that can convert them into Vector2 spatial positions.
|
|
134
150
|
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
namespace UnityHelpers.Core.Helper
|
|
2
|
+
{
|
|
3
|
+
using System;
|
|
4
|
+
|
|
5
|
+
public static class FormattingHelpers
|
|
6
|
+
{
|
|
7
|
+
private static readonly string[] ByteSizes = { "B", "KB", "MB", "GB", "TB", "PB", "EB" };
|
|
8
|
+
|
|
9
|
+
public static string FormatBytes(long bytes)
|
|
10
|
+
{
|
|
11
|
+
bytes = Math.Max(0L, bytes);
|
|
12
|
+
double len = bytes;
|
|
13
|
+
int order = 0;
|
|
14
|
+
|
|
15
|
+
const int byteInChunk = 1024;
|
|
16
|
+
while (byteInChunk <= len)
|
|
17
|
+
{
|
|
18
|
+
len /= byteInChunk;
|
|
19
|
+
if (order < ByteSizes.Length - 1)
|
|
20
|
+
{
|
|
21
|
+
++order;
|
|
22
|
+
}
|
|
23
|
+
else
|
|
24
|
+
{
|
|
25
|
+
throw new ArgumentException($"Too many bytes! Cannot parse {bytes}");
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return $"{len:0.##} {ByteSizes[order]}";
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
|
|
8
8
|
public static class Objects
|
|
9
9
|
{
|
|
10
|
-
private const int HashBase =
|
|
11
|
-
private const int HashMultiplier =
|
|
10
|
+
private const int HashBase = 5556137;
|
|
11
|
+
private const int HashMultiplier = 95785853;
|
|
12
12
|
|
|
13
13
|
public static T FromWeakReference<T>(WeakReference weakReference)
|
|
14
14
|
where T : class
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
public static Array CreateArray(Type type, int length)
|
|
21
21
|
{
|
|
22
22
|
return ArrayCreators
|
|
23
|
+
// ReSharper disable once ConvertClosureToMethodGroup
|
|
23
24
|
.GetOrAdd(type, elementType => GetArrayCreator(elementType))
|
|
24
25
|
.Invoke(length);
|
|
25
26
|
}
|
|
@@ -28,6 +29,7 @@
|
|
|
28
29
|
public static IList CreateList(Type elementType, int length)
|
|
29
30
|
{
|
|
30
31
|
return ListWithCapacityCreators
|
|
32
|
+
// ReSharper disable once ConvertClosureToMethodGroup
|
|
31
33
|
.GetOrAdd(elementType, type => GetListWithCapacityCreator(type))
|
|
32
34
|
.Invoke(length);
|
|
33
35
|
}
|
|
@@ -35,6 +37,7 @@
|
|
|
35
37
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
36
38
|
public static IList CreateList(Type elementType)
|
|
37
39
|
{
|
|
40
|
+
// ReSharper disable once ConvertClosureToMethodGroup
|
|
38
41
|
return ListCreators.GetOrAdd(elementType, type => GetListCreator(type)).Invoke();
|
|
39
42
|
}
|
|
40
43
|
|
|
@@ -44,7 +47,7 @@
|
|
|
44
47
|
return field.GetValue;
|
|
45
48
|
#else
|
|
46
49
|
DynamicMethod dynamicMethod = new(
|
|
47
|
-
$"Get{
|
|
50
|
+
$"Get{field.DeclaringType.Name}{field.Name}",
|
|
48
51
|
typeof(object),
|
|
49
52
|
new[] { typeof(object) },
|
|
50
53
|
field.DeclaringType,
|
|
@@ -72,6 +75,41 @@
|
|
|
72
75
|
#endif
|
|
73
76
|
}
|
|
74
77
|
|
|
78
|
+
public static Func<object> GetStaticFieldGetter(FieldInfo field)
|
|
79
|
+
{
|
|
80
|
+
if (!field.IsStatic)
|
|
81
|
+
{
|
|
82
|
+
throw new ArgumentException(nameof(field));
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
#if WEB_GL
|
|
86
|
+
return () => field.GetValue(null);
|
|
87
|
+
#else
|
|
88
|
+
DynamicMethod dynamicMethod = new(
|
|
89
|
+
$"Get{field.DeclaringType.Name}{field.Name}",
|
|
90
|
+
typeof(object),
|
|
91
|
+
Type.EmptyTypes, // No parameters for static fields
|
|
92
|
+
field.DeclaringType,
|
|
93
|
+
true
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
ILGenerator il = dynamicMethod.GetILGenerator();
|
|
97
|
+
|
|
98
|
+
// Load the static field
|
|
99
|
+
il.Emit(OpCodes.Ldsfld, field);
|
|
100
|
+
|
|
101
|
+
// If the field's type is a value type, box it.
|
|
102
|
+
if (field.FieldType.IsValueType)
|
|
103
|
+
{
|
|
104
|
+
il.Emit(OpCodes.Box, field.FieldType);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
il.Emit(OpCodes.Ret);
|
|
108
|
+
|
|
109
|
+
return (Func<object>)dynamicMethod.CreateDelegate(typeof(Func<object>));
|
|
110
|
+
#endif
|
|
111
|
+
}
|
|
112
|
+
|
|
75
113
|
public static Func<TInstance, TValue> GetFieldGetter<TInstance, TValue>(FieldInfo field)
|
|
76
114
|
{
|
|
77
115
|
#if WEB_GL
|
|
@@ -142,6 +180,59 @@
|
|
|
142
180
|
#endif
|
|
143
181
|
}
|
|
144
182
|
|
|
183
|
+
public static Func<TValue> GetStaticFieldGetter<TValue>(FieldInfo field)
|
|
184
|
+
{
|
|
185
|
+
if (!field.IsStatic)
|
|
186
|
+
{
|
|
187
|
+
throw new ArgumentException(nameof(field));
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
#if WEB_GL
|
|
191
|
+
return Getter;
|
|
192
|
+
TValue Getter()
|
|
193
|
+
{
|
|
194
|
+
return (TValue)field.GetValue(null);
|
|
195
|
+
}
|
|
196
|
+
#else
|
|
197
|
+
DynamicMethod dynamicMethod = new(
|
|
198
|
+
$"GetGenericStatic{field.DeclaringType.Name}{field.Name}",
|
|
199
|
+
typeof(TValue),
|
|
200
|
+
Type.EmptyTypes, // no parameters needed for static fields
|
|
201
|
+
field.DeclaringType,
|
|
202
|
+
true
|
|
203
|
+
);
|
|
204
|
+
|
|
205
|
+
ILGenerator il = dynamicMethod.GetILGenerator();
|
|
206
|
+
|
|
207
|
+
// Load the static field.
|
|
208
|
+
il.Emit(OpCodes.Ldsfld, field);
|
|
209
|
+
|
|
210
|
+
// Handle conversion from the field type to TValue.
|
|
211
|
+
if (field.FieldType.IsValueType)
|
|
212
|
+
{
|
|
213
|
+
if (!typeof(TValue).IsValueType)
|
|
214
|
+
{
|
|
215
|
+
il.Emit(OpCodes.Box, field.FieldType);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
else
|
|
219
|
+
{
|
|
220
|
+
if (typeof(TValue).IsValueType)
|
|
221
|
+
{
|
|
222
|
+
il.Emit(OpCodes.Unbox_Any, typeof(TValue));
|
|
223
|
+
}
|
|
224
|
+
else if (typeof(TValue) != field.FieldType)
|
|
225
|
+
{
|
|
226
|
+
il.Emit(OpCodes.Castclass, typeof(TValue));
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
il.Emit(OpCodes.Ret);
|
|
231
|
+
|
|
232
|
+
return (Func<TValue>)dynamicMethod.CreateDelegate(typeof(Func<TValue>));
|
|
233
|
+
#endif
|
|
234
|
+
}
|
|
235
|
+
|
|
145
236
|
public static FieldSetter<TInstance, TValue> GetFieldSetter<TInstance, TValue>(
|
|
146
237
|
FieldInfo field
|
|
147
238
|
)
|
|
@@ -184,6 +275,36 @@
|
|
|
184
275
|
#endif
|
|
185
276
|
}
|
|
186
277
|
|
|
278
|
+
public static Action<TValue> GetStaticFieldSetter<TValue>(FieldInfo field)
|
|
279
|
+
{
|
|
280
|
+
if (!field.IsStatic)
|
|
281
|
+
{
|
|
282
|
+
throw new ArgumentException(nameof(field));
|
|
283
|
+
}
|
|
284
|
+
#if WEB_GL
|
|
285
|
+
return Setter;
|
|
286
|
+
void Setter(TValue newValue)
|
|
287
|
+
{
|
|
288
|
+
field.SetValue(null, newValue);
|
|
289
|
+
}
|
|
290
|
+
#else
|
|
291
|
+
DynamicMethod dynamicMethod = new(
|
|
292
|
+
$"SetFieldGenericStatic{field.DeclaringType.Name}{field.Name}",
|
|
293
|
+
typeof(void),
|
|
294
|
+
new[] { typeof(TValue) },
|
|
295
|
+
field.Module,
|
|
296
|
+
true
|
|
297
|
+
);
|
|
298
|
+
|
|
299
|
+
ILGenerator il = dynamicMethod.GetILGenerator();
|
|
300
|
+
il.Emit(OpCodes.Ldarg_0);
|
|
301
|
+
il.Emit(OpCodes.Stsfld, field);
|
|
302
|
+
il.Emit(OpCodes.Ret);
|
|
303
|
+
|
|
304
|
+
return (Action<TValue>)dynamicMethod.CreateDelegate(typeof(Action<TValue>));
|
|
305
|
+
#endif
|
|
306
|
+
}
|
|
307
|
+
|
|
187
308
|
public static Action<object, object> GetFieldSetter(FieldInfo field)
|
|
188
309
|
{
|
|
189
310
|
#if WEB_GL
|
|
@@ -217,6 +338,40 @@
|
|
|
217
338
|
#endif
|
|
218
339
|
}
|
|
219
340
|
|
|
341
|
+
public static Action<object> GetStaticFieldSetter(FieldInfo field)
|
|
342
|
+
{
|
|
343
|
+
if (!field.IsStatic)
|
|
344
|
+
{
|
|
345
|
+
throw new ArgumentException(nameof(field));
|
|
346
|
+
}
|
|
347
|
+
#if WEB_GL
|
|
348
|
+
return value => field.SetValue(null, value);
|
|
349
|
+
#else
|
|
350
|
+
DynamicMethod dynamicMethod = new(
|
|
351
|
+
$"SetFieldStatic{field.DeclaringType.Name}{field.Name}",
|
|
352
|
+
null,
|
|
353
|
+
new[] { typeof(object) },
|
|
354
|
+
field.DeclaringType.Module,
|
|
355
|
+
true
|
|
356
|
+
);
|
|
357
|
+
|
|
358
|
+
ILGenerator il = dynamicMethod.GetILGenerator();
|
|
359
|
+
|
|
360
|
+
// Load the new value (argument 0)
|
|
361
|
+
il.Emit(OpCodes.Ldarg_0);
|
|
362
|
+
// Convert the object to the field's type (unbox or cast as needed)
|
|
363
|
+
il.Emit(
|
|
364
|
+
field.FieldType.IsValueType ? OpCodes.Unbox_Any : OpCodes.Castclass,
|
|
365
|
+
field.FieldType
|
|
366
|
+
);
|
|
367
|
+
// Set the static field
|
|
368
|
+
il.Emit(OpCodes.Stsfld, field);
|
|
369
|
+
il.Emit(OpCodes.Ret);
|
|
370
|
+
|
|
371
|
+
return (Action<object>)dynamicMethod.CreateDelegate(typeof(Action<object>));
|
|
372
|
+
#endif
|
|
373
|
+
}
|
|
374
|
+
|
|
220
375
|
public static Func<int, Array> GetArrayCreator(Type elementType)
|
|
221
376
|
{
|
|
222
377
|
#if WEB_GL
|
|
@@ -3,13 +3,12 @@
|
|
|
3
3
|
using Extension;
|
|
4
4
|
using UnityEditor;
|
|
5
5
|
using UnityEngine;
|
|
6
|
-
using Utils;
|
|
7
6
|
|
|
8
7
|
public static class SpriteHelpers
|
|
9
8
|
{
|
|
10
9
|
public static void MakeReadable(this Texture2D texture)
|
|
11
10
|
{
|
|
12
|
-
if (texture.isReadable)
|
|
11
|
+
if (texture == null || texture.isReadable)
|
|
13
12
|
{
|
|
14
13
|
return;
|
|
15
14
|
}
|
|
@@ -29,58 +28,14 @@
|
|
|
29
28
|
return;
|
|
30
29
|
}
|
|
31
30
|
|
|
32
|
-
tImporter.isReadable
|
|
33
|
-
EditorUtility.SetDirty(tImporter);
|
|
34
|
-
tImporter.SaveAndReimport();
|
|
35
|
-
EditorUtility.SetDirty(texture);
|
|
36
|
-
#endif
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
public static void SetSpritePivot(string fullSpritePath, Vector2 pivot)
|
|
40
|
-
{
|
|
41
|
-
#if UNITY_EDITOR
|
|
42
|
-
SetSpritePivot(AssetImporter.GetAtPath(fullSpritePath) as TextureImporter, pivot);
|
|
43
|
-
#endif
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
public static void SetSpritePivot(Sprite sprite, Vector2 pivot)
|
|
47
|
-
{
|
|
48
|
-
#if UNITY_EDITOR
|
|
49
|
-
SetSpritePivot(
|
|
50
|
-
AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(sprite)) as TextureImporter,
|
|
51
|
-
pivot
|
|
52
|
-
);
|
|
53
|
-
#endif
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
#if UNITY_EDITOR
|
|
57
|
-
public static void SetSpritePivot(TextureImporter textureImporter, Vector2 pivot)
|
|
58
|
-
{
|
|
59
|
-
if (textureImporter == null)
|
|
31
|
+
if (!tImporter.isReadable)
|
|
60
32
|
{
|
|
61
|
-
|
|
33
|
+
tImporter.isReadable = true;
|
|
34
|
+
EditorUtility.SetDirty(tImporter);
|
|
35
|
+
tImporter.SaveAndReimport();
|
|
36
|
+
EditorUtility.SetDirty(texture);
|
|
62
37
|
}
|
|
63
|
-
|
|
64
|
-
TextureImporterSettings textureImportSettings = new TextureImporterSettings();
|
|
65
|
-
textureImporter.ReadTextureSettings(textureImportSettings);
|
|
66
|
-
textureImportSettings.spriteAlignment = (int)SpriteAlignment.Custom;
|
|
67
|
-
textureImportSettings.wrapMode = TextureWrapMode.Clamp;
|
|
68
|
-
textureImportSettings.filterMode = FilterMode.Trilinear;
|
|
69
|
-
textureImporter.SetTextureSettings(textureImportSettings);
|
|
70
|
-
|
|
71
|
-
TextureImporterPlatformSettings importerSettings = new TextureImporterPlatformSettings
|
|
72
|
-
{
|
|
73
|
-
resizeAlgorithm = TextureResizeAlgorithm.Bilinear,
|
|
74
|
-
maxTextureSize = SetTextureImportData.RegularTextureSize,
|
|
75
|
-
textureCompression = TextureImporterCompression.Compressed,
|
|
76
|
-
format = TextureImporterFormat.Automatic,
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
textureImporter.SetPlatformTextureSettings(importerSettings);
|
|
80
|
-
textureImporter.isReadable = true;
|
|
81
|
-
textureImporter.spritePivot = pivot;
|
|
82
|
-
textureImporter.SaveAndReimport();
|
|
83
|
-
}
|
|
84
38
|
#endif
|
|
39
|
+
}
|
|
85
40
|
}
|
|
86
41
|
}
|
|
@@ -125,12 +125,12 @@
|
|
|
125
125
|
if (0 < direction.x)
|
|
126
126
|
{
|
|
127
127
|
float t2 = (max.x - center.x) / direction.x;
|
|
128
|
-
tMax =
|
|
128
|
+
tMax = Mathf.Min(tMax, t2);
|
|
129
129
|
}
|
|
130
130
|
else
|
|
131
131
|
{
|
|
132
132
|
float t1 = (min.x - center.x) / direction.x;
|
|
133
|
-
tMax =
|
|
133
|
+
tMax = Mathf.Min(tMax, t1);
|
|
134
134
|
}
|
|
135
135
|
}
|
|
136
136
|
|
|
@@ -139,12 +139,12 @@
|
|
|
139
139
|
if (direction.y > 0)
|
|
140
140
|
{
|
|
141
141
|
float t2 = (max.y - center.y) / direction.y;
|
|
142
|
-
tMax =
|
|
142
|
+
tMax = Mathf.Min(tMax, t2);
|
|
143
143
|
}
|
|
144
144
|
else
|
|
145
145
|
{
|
|
146
146
|
float t1 = (min.y - center.y) / direction.y;
|
|
147
|
-
tMax =
|
|
147
|
+
tMax = Mathf.Min(tMax, t1);
|
|
148
148
|
}
|
|
149
149
|
}
|
|
150
150
|
|
|
@@ -160,7 +160,7 @@
|
|
|
160
160
|
|
|
161
161
|
public static bool Approximately(this float lhs, float rhs, float tolerance = 0.045f)
|
|
162
162
|
{
|
|
163
|
-
return
|
|
163
|
+
return Mathf.Abs(lhs - rhs) <= tolerance;
|
|
164
164
|
}
|
|
165
165
|
}
|
|
166
166
|
}
|
|
@@ -21,6 +21,8 @@
|
|
|
21
21
|
|
|
22
22
|
public abstract RandomState InternalState { get; }
|
|
23
23
|
|
|
24
|
+
private readonly byte[] _guidBytes = new byte[16];
|
|
25
|
+
|
|
24
26
|
public virtual int Next()
|
|
25
27
|
{
|
|
26
28
|
// Mask out the MSB to ensure the value is within [0, int.MaxValue]
|
|
@@ -410,24 +412,23 @@
|
|
|
410
412
|
where T : struct, Enum
|
|
411
413
|
{
|
|
412
414
|
Type enumType = typeof(T);
|
|
413
|
-
T[] enumValues = (T[])EnumTypeCache.GetOrAdd(enumType, Enum.GetValues);
|
|
415
|
+
T[] enumValues = (T[])EnumTypeCache.GetOrAdd(enumType, type => Enum.GetValues(type));
|
|
414
416
|
|
|
415
417
|
return RandomOf(enumValues);
|
|
416
418
|
}
|
|
417
419
|
|
|
418
420
|
public Guid NextGuid()
|
|
419
421
|
{
|
|
420
|
-
return new Guid(GenerateGuidBytes());
|
|
422
|
+
return new Guid(GenerateGuidBytes(_guidBytes));
|
|
421
423
|
}
|
|
422
424
|
|
|
423
425
|
public KGuid NextKGuid()
|
|
424
426
|
{
|
|
425
|
-
return new KGuid(GenerateGuidBytes());
|
|
427
|
+
return new KGuid(GenerateGuidBytes(_guidBytes));
|
|
426
428
|
}
|
|
427
429
|
|
|
428
|
-
private byte[] GenerateGuidBytes()
|
|
430
|
+
private byte[] GenerateGuidBytes(byte[] guidBytes)
|
|
429
431
|
{
|
|
430
|
-
byte[] guidBytes = new byte[16];
|
|
431
432
|
NextBytes(guidBytes);
|
|
432
433
|
SetUuidV4Bits(guidBytes);
|
|
433
434
|
return guidBytes;
|
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
[DataContract]
|
|
9
9
|
public sealed class DotNetRandom : AbstractRandom
|
|
10
10
|
{
|
|
11
|
+
public static DotNetRandom Instance => ThreadLocalRandom<DotNetRandom>.Instance;
|
|
12
|
+
|
|
11
13
|
public override RandomState InternalState =>
|
|
12
14
|
new RandomState(unchecked((ulong)_seed), state2: _numberGenerated);
|
|
13
15
|
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
namespace UnityHelpers.Core.Random
|
|
2
|
+
{
|
|
3
|
+
using System;
|
|
4
|
+
using System.Text.Json.Serialization;
|
|
5
|
+
|
|
6
|
+
public sealed class LinearCongruentialGenerator : AbstractRandom
|
|
7
|
+
{
|
|
8
|
+
public static LinearCongruentialGenerator Instance =>
|
|
9
|
+
ThreadLocalRandom<LinearCongruentialGenerator>.Instance;
|
|
10
|
+
|
|
11
|
+
public override RandomState InternalState => new(_state, 0, _cachedGaussian);
|
|
12
|
+
|
|
13
|
+
private uint _state;
|
|
14
|
+
|
|
15
|
+
public LinearCongruentialGenerator()
|
|
16
|
+
: this(Guid.NewGuid()) { }
|
|
17
|
+
|
|
18
|
+
public LinearCongruentialGenerator(int seed)
|
|
19
|
+
{
|
|
20
|
+
_state = unchecked((uint)seed);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
public LinearCongruentialGenerator(Guid seed)
|
|
24
|
+
{
|
|
25
|
+
_state = unchecked((uint)seed.GetHashCode());
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
[JsonConstructor]
|
|
29
|
+
public LinearCongruentialGenerator(RandomState internalState)
|
|
30
|
+
{
|
|
31
|
+
_state = unchecked((uint)internalState.State1);
|
|
32
|
+
_cachedGaussian = internalState.Gaussian;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
public override uint NextUint()
|
|
36
|
+
{
|
|
37
|
+
unchecked
|
|
38
|
+
{
|
|
39
|
+
_state = _state * 1664525U + 1013904223U;
|
|
40
|
+
}
|
|
41
|
+
return _state;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
public override IRandom Copy()
|
|
45
|
+
{
|
|
46
|
+
return new LinearCongruentialGenerator(InternalState);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
IComparable,
|
|
16
16
|
IComparable<PcgRandom>
|
|
17
17
|
{
|
|
18
|
-
public static
|
|
18
|
+
public static PcgRandom Instance => ThreadLocalRandom<PcgRandom>.Instance;
|
|
19
19
|
|
|
20
20
|
public override RandomState InternalState => new(_state, _increment, _cachedGaussian);
|
|
21
21
|
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
IComparable,
|
|
16
16
|
IComparable<RomuDuo>
|
|
17
17
|
{
|
|
18
|
-
public static
|
|
18
|
+
public static RomuDuo Instance => ThreadLocalRandom<RomuDuo>.Instance;
|
|
19
19
|
public override RandomState InternalState => new(_x, _y, _cachedGaussian);
|
|
20
20
|
|
|
21
21
|
internal ulong _x;
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
IComparable,
|
|
13
13
|
IComparable<SplitMix64>
|
|
14
14
|
{
|
|
15
|
-
public static
|
|
15
|
+
public static SplitMix64 Instance => ThreadLocalRandom<SplitMix64>.Instance;
|
|
16
16
|
|
|
17
17
|
public override RandomState InternalState => new(_state, 0, _cachedGaussian);
|
|
18
18
|
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
private const int SeedArraySize = 56;
|
|
17
17
|
private const int LastSeedIndex = SeedArraySize - 1;
|
|
18
18
|
|
|
19
|
-
public static
|
|
19
|
+
public static SystemRandom Instance => ThreadLocalRandom<SystemRandom>.Instance;
|
|
20
20
|
|
|
21
21
|
public override RandomState InternalState =>
|
|
22
22
|
new(
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
private const ulong Prime0 = 0xa0761d6478bd642f;
|
|
15
15
|
private const ulong Prime1 = 0xe7037ed1a0b428db;
|
|
16
16
|
|
|
17
|
-
public static
|
|
17
|
+
public static WyRandom Instance => ThreadLocalRandom<WyRandom>.Instance;
|
|
18
18
|
|
|
19
19
|
public override RandomState InternalState => new RandomState(_state);
|
|
20
20
|
|
|
@@ -8,18 +8,25 @@
|
|
|
8
8
|
[DataContract]
|
|
9
9
|
public sealed class XorShiftRandom : AbstractRandom
|
|
10
10
|
{
|
|
11
|
-
public static
|
|
11
|
+
public static XorShiftRandom Instance => ThreadLocalRandom<XorShiftRandom>.Instance;
|
|
12
12
|
|
|
13
13
|
public override RandomState InternalState => new(_state, 0, _cachedGaussian);
|
|
14
14
|
|
|
15
15
|
private uint _state;
|
|
16
16
|
|
|
17
17
|
public XorShiftRandom()
|
|
18
|
-
: this(Guid.NewGuid()
|
|
18
|
+
: this(Guid.NewGuid()) { }
|
|
19
19
|
|
|
20
20
|
public XorShiftRandom(int state)
|
|
21
21
|
{
|
|
22
22
|
_state = unchecked((uint)state);
|
|
23
|
+
_state = _state != 0 ? _state : 2463534242U;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
public XorShiftRandom(Guid seed)
|
|
27
|
+
{
|
|
28
|
+
_state = unchecked((uint)seed.GetHashCode());
|
|
29
|
+
_state = _state != 0 ? _state : 2463534242U;
|
|
23
30
|
}
|
|
24
31
|
|
|
25
32
|
[JsonConstructor]
|
|
@@ -31,12 +38,10 @@
|
|
|
31
38
|
|
|
32
39
|
public override uint NextUint()
|
|
33
40
|
{
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
_state = state;
|
|
39
|
-
return state;
|
|
41
|
+
_state ^= _state << 13;
|
|
42
|
+
_state ^= _state >> 17;
|
|
43
|
+
_state ^= _state << 5;
|
|
44
|
+
return _state;
|
|
40
45
|
}
|
|
41
46
|
|
|
42
47
|
public override IRandom Copy()
|
|
@@ -176,7 +176,7 @@
|
|
|
176
176
|
int maxY = int.MinValue;
|
|
177
177
|
foreach (AnimatedSpriteLayer layer in _layers)
|
|
178
178
|
{
|
|
179
|
-
if (
|
|
179
|
+
if (layer.frames.Length <= 0)
|
|
180
180
|
{
|
|
181
181
|
continue;
|
|
182
182
|
}
|
|
@@ -210,7 +210,7 @@
|
|
|
210
210
|
|
|
211
211
|
foreach (AnimatedSpriteLayer layer in _layers)
|
|
212
212
|
{
|
|
213
|
-
if (
|
|
213
|
+
if (layer.frames.Length <= 0)
|
|
214
214
|
{
|
|
215
215
|
continue;
|
|
216
216
|
}
|