com.wallstop-studios.unity-helpers 2.0.0-rc41 → 2.0.0-rc43

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.
@@ -0,0 +1,157 @@
1
+ namespace UnityHelpers.Core.Extension
2
+ {
3
+ #if UNITY_EDITOR
4
+ using UnityEditor;
5
+ using System;
6
+ using System.Reflection;
7
+
8
+ public static class SerializedPropertyExtensions
9
+ {
10
+ /// <summary>
11
+ /// Gets the instance object that contains the given SerializedProperty.
12
+ /// </summary>
13
+ /// <param name="property">The SerializedProperty.</param>
14
+ /// <param name="fieldInfo">Outputs the FieldInfo of the referenced field.</param>
15
+ /// <returns>The instance object that owns the field.</returns>
16
+ public static object GetEnclosingObject(
17
+ this SerializedProperty property,
18
+ out FieldInfo fieldInfo
19
+ )
20
+ {
21
+ fieldInfo = null;
22
+ object obj = property.serializedObject.targetObject;
23
+ if (obj == null)
24
+ {
25
+ return null;
26
+ }
27
+ Type type = obj.GetType();
28
+ string[] pathParts = property.propertyPath.Split('.');
29
+
30
+ // Traverse the path but stop at the second-to-last field
31
+ for (int i = 0; i < pathParts.Length - 1; ++i)
32
+ {
33
+ string fieldName = pathParts[i];
34
+
35
+ if (string.Equals(fieldName, "Array", StringComparison.Ordinal))
36
+ {
37
+ // Move to "data[i]", no need to length-check, we're guarded above
38
+
39
+ ++i;
40
+ if (
41
+ !int.TryParse(
42
+ pathParts[i]
43
+ .Replace("data[", string.Empty, StringComparison.Ordinal)
44
+ .Replace("]", string.Empty, StringComparison.Ordinal),
45
+ out int index
46
+ )
47
+ )
48
+ {
49
+ // Unexpected, die
50
+ fieldInfo = null;
51
+ return null;
52
+ }
53
+ obj = GetElementAtIndex(obj, index);
54
+ type = obj?.GetType();
55
+ continue;
56
+ }
57
+
58
+ fieldInfo = type?.GetField(
59
+ fieldName,
60
+ BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance
61
+ );
62
+ if (fieldInfo == null)
63
+ {
64
+ return null;
65
+ }
66
+
67
+ // Move deeper but stop before the last property in the path
68
+ if (i < pathParts.Length - 2)
69
+ {
70
+ obj = fieldInfo.GetValue(obj);
71
+ type = fieldInfo.FieldType;
72
+ }
73
+ }
74
+
75
+ return obj;
76
+ }
77
+
78
+ /// <summary>
79
+ /// Gets the FieldInfo and the instance object that owns the field for a given SerializedProperty.
80
+ /// </summary>
81
+ /// <param name="property">The SerializedProperty to reflect upon.</param>
82
+ /// <param name="fieldInfo">Outputs the FieldInfo of the referenced field.</param>
83
+ /// <returns>The instance object that owns the field.</returns>
84
+ public static object GetTargetObjectWithField(
85
+ this SerializedProperty property,
86
+ out FieldInfo fieldInfo
87
+ )
88
+ {
89
+ fieldInfo = null;
90
+ object obj = property.serializedObject.targetObject;
91
+ if (obj == null)
92
+ {
93
+ return null;
94
+ }
95
+
96
+ Type type = obj.GetType();
97
+ string[] pathParts = property.propertyPath.Split('.');
98
+
99
+ for (int i = 0; i < pathParts.Length; ++i)
100
+ {
101
+ string fieldName = pathParts[i];
102
+
103
+ if (string.Equals(fieldName, "Array", StringComparison.Ordinal))
104
+ {
105
+ // Move to "data[i]"
106
+ ++i;
107
+ if (pathParts.Length <= i)
108
+ {
109
+ break;
110
+ }
111
+
112
+ if (
113
+ !int.TryParse(
114
+ pathParts[i]
115
+ .Replace("data[", string.Empty, StringComparison.Ordinal)
116
+ .Replace("]", string.Empty, StringComparison.Ordinal),
117
+ out int index
118
+ )
119
+ )
120
+ {
121
+ // Unexpected, die
122
+ fieldInfo = null;
123
+ return null;
124
+ }
125
+ obj = GetElementAtIndex(obj, index);
126
+ type = obj?.GetType();
127
+ continue;
128
+ }
129
+
130
+ fieldInfo = type?.GetField(
131
+ fieldName,
132
+ BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance
133
+ );
134
+ if (fieldInfo == null)
135
+ {
136
+ return null;
137
+ }
138
+
139
+ // Move deeper into the object tree
140
+ obj = fieldInfo.GetValue(obj);
141
+ type = fieldInfo.FieldType;
142
+ }
143
+
144
+ return obj;
145
+ }
146
+
147
+ private static object GetElementAtIndex(object obj, int index)
148
+ {
149
+ if (obj is System.Collections.IList list && index >= 0 && index < list.Count)
150
+ {
151
+ return list[index];
152
+ }
153
+ return null;
154
+ }
155
+ }
156
+ #endif
157
+ }
@@ -0,0 +1,3 @@
1
+ fileFormatVersion: 2
2
+ guid: f58cbae584d8414a89cc3996d16fc5b0
3
+ timeCreated: 1742507900
@@ -18,7 +18,8 @@
18
18
  }
19
19
 
20
20
  [MethodImpl(MethodImplOptions.AggressiveInlining)]
21
- public static bool Null(UnityEngine.Object instance)
21
+ public static bool Null<T>(T instance)
22
+ where T : UnityEngine.Object
22
23
  {
23
24
  return instance == null;
24
25
  }
@@ -29,7 +30,8 @@
29
30
  }
30
31
 
31
32
  [MethodImpl(MethodImplOptions.AggressiveInlining)]
32
- public static bool NotNull(UnityEngine.Object instance)
33
+ public static bool NotNull<T>(T instance)
34
+ where T : UnityEngine.Object
33
35
  {
34
36
  return instance != null;
35
37
  }
@@ -1,7 +1,6 @@
1
1
  namespace UnityHelpers.Core.Helper
2
2
  {
3
3
  using System.Collections.Generic;
4
- using System.Linq;
5
4
  using UnityEngine;
6
5
 
7
6
  public static partial class Helpers
@@ -171,10 +170,9 @@
171
170
  {
172
171
  if (component == null)
173
172
  {
174
- return Enumerable.Empty<Transform>();
173
+ yield break;
175
174
  }
176
175
 
177
- Queue<Transform> results = new();
178
176
  Queue<Transform> iteration = new();
179
177
  iteration.Enqueue(component.transform);
180
178
  while (iteration.TryDequeue(out Transform current))
@@ -182,12 +180,10 @@
182
180
  for (int i = 0; i < current.childCount; ++i)
183
181
  {
184
182
  Transform childTransform = current.GetChild(i);
185
- results.Enqueue(childTransform);
186
183
  iteration.Enqueue(childTransform);
184
+ yield return childTransform;
187
185
  }
188
186
  }
189
-
190
- return results;
191
187
  }
192
188
  }
193
189
  }
@@ -22,7 +22,7 @@
22
22
  }
23
23
  else
24
24
  {
25
- Debug.LogError("NO SUCH METHOD " + methodName + " FOR " + type);
25
+ Debug.LogError($"NO SUCH METHOD {methodName} FOR {type}");
26
26
  }
27
27
  }
28
28
 
@@ -7,6 +7,7 @@
7
7
  public sealed class SingleThreadedThreadPool : IDisposable
8
8
  {
9
9
  public ConcurrentQueue<Exception> Exceptions => _exceptions;
10
+ public int Count => _work.Count + Interlocked.CompareExchange(ref _working, 0, 0);
10
11
 
11
12
  private int _active;
12
13
  private int _working;
@@ -16,14 +17,14 @@
16
17
  private bool _disposed;
17
18
  private readonly ConcurrentQueue<Exception> _exceptions;
18
19
 
19
- public SingleThreadedThreadPool()
20
+ public SingleThreadedThreadPool(bool runInBackground = false)
20
21
  {
21
22
  _active = 1;
22
23
  _working = 1;
23
24
  _work = new ConcurrentQueue<Action>();
24
25
  _exceptions = new ConcurrentQueue<Exception>();
25
26
  _waitHandle = new AutoResetEvent(false);
26
- _worker = new Thread(DoWork);
27
+ _worker = new Thread(DoWork) { IsBackground = runInBackground };
27
28
  _worker.Start();
28
29
  }
29
30
 
@@ -32,40 +33,12 @@
32
33
  Dispose(false);
33
34
  }
34
35
 
35
- private void DoWork()
36
- {
37
- while (Interlocked.CompareExchange(ref _active, 0, 0) != 0)
38
- {
39
- _ = Interlocked.Exchange(ref _working, 0);
40
- if (_work.TryDequeue(out Action workItem))
41
- {
42
- _ = Interlocked.Exchange(ref _working, 1);
43
- try
44
- {
45
- workItem();
46
- }
47
- catch (Exception e)
48
- {
49
- _exceptions.Enqueue(e);
50
- }
51
- }
52
- else
53
- {
54
- _ = _waitHandle.WaitOne(TimeSpan.FromSeconds(1));
55
- }
56
-
57
- _ = Interlocked.Exchange(ref _working, 0);
58
- }
59
- }
60
-
61
36
  public void Enqueue(Action work)
62
37
  {
63
38
  _work.Enqueue(work);
64
39
  _ = _waitHandle.Set();
65
40
  }
66
41
 
67
- public int Count => _work.Count + Interlocked.CompareExchange(ref _working, 0, 0);
68
-
69
42
  public void Dispose()
70
43
  {
71
44
  Dispose(true);
@@ -79,17 +52,16 @@
79
52
  return;
80
53
  }
81
54
 
82
- int active;
83
- do
55
+ while (Interlocked.CompareExchange(ref _active, 0, _active) != 0)
84
56
  {
85
- active = Interlocked.CompareExchange(ref _active, 0, _active);
86
- } while (active != 0);
57
+ // Spin
58
+ }
87
59
 
88
60
  if (disposing)
89
61
  {
90
62
  try
91
63
  {
92
- _worker?.Join();
64
+ _worker?.Join(TimeSpan.FromSeconds(30));
93
65
  _waitHandle?.Dispose();
94
66
  }
95
67
  catch
@@ -103,5 +75,42 @@
103
75
 
104
76
  _disposed = true;
105
77
  }
78
+
79
+ private void DoWork()
80
+ {
81
+ while (Interlocked.CompareExchange(ref _active, 0, 0) != 0)
82
+ {
83
+ try
84
+ {
85
+ if (_work.TryDequeue(out Action workItem))
86
+ {
87
+ _ = Interlocked.Exchange(ref _working, 1);
88
+ try
89
+ {
90
+ workItem();
91
+ }
92
+ catch (Exception e)
93
+ {
94
+ _exceptions.Enqueue(e);
95
+ }
96
+ }
97
+ else
98
+ {
99
+ try
100
+ {
101
+ _ = _waitHandle?.WaitOne(TimeSpan.FromSeconds(1));
102
+ }
103
+ catch (ObjectDisposedException)
104
+ {
105
+ return;
106
+ }
107
+ }
108
+ }
109
+ finally
110
+ {
111
+ _ = Interlocked.Exchange(ref _working, 0);
112
+ }
113
+ }
114
+ }
106
115
  }
107
116
  }
@@ -7,7 +7,6 @@
7
7
  {
8
8
  public const int BufferSize = 10_000;
9
9
 
10
- public static readonly HashSet<Collider2D> UniqueColliders = new();
11
10
  public static readonly Collider2D[] Colliders = new Collider2D[BufferSize];
12
11
  public static readonly RaycastHit2D[] RaycastHits = new RaycastHit2D[BufferSize];
13
12
 
@@ -16,6 +15,8 @@
16
15
  DO NOT USE with random values.
17
16
  */
18
17
  public static readonly Dictionary<float, WaitForSeconds> WaitForSeconds = new();
18
+ public static readonly Dictionary<float, WaitForSecondsRealtime> WaitForSecondsRealtime =
19
+ new();
19
20
  public static readonly System.Random Random = new();
20
21
  public static readonly WaitForFixedUpdate WaitForFixedUpdate = new();
21
22
  public static readonly WaitForEndOfFrame WaitForEndOfFrame = new();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "com.wallstop-studios.unity-helpers",
3
- "version": "2.0.0-rc41",
3
+ "version": "2.0.0-rc43",
4
4
  "displayName": "Unity Helpers",
5
5
  "description": "Various Unity Helper Library",
6
6
  "dependencies": {},