com.wallstop-studios.unity-helpers 2.0.0-rc49 → 2.0.0-rc51
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/Runtime/Core/Extension/UnityExtensions.cs +8 -0
- package/Runtime/Core/Helper/SceneHelper.cs +216 -0
- package/Runtime/Core/Helper/SceneHelper.cs.meta +3 -0
- package/Runtime/Core/Helper/UnityMainThreadDispatcher.cs +32 -0
- package/Runtime/Core/Helper/UnityMainThreadDispatcher.cs.meta +3 -0
- package/Runtime/Core/Random/AbstractRandom.cs +27 -4
- package/Runtime/Core/Serialization/JsonConverters/ColorConverter.cs +88 -0
- package/Runtime/Core/Serialization/JsonConverters/ColorConverter.cs.meta +3 -0
- package/Runtime/Core/Serialization/JsonConverters/GameObjectConverter.cs +37 -0
- package/Runtime/Core/Serialization/JsonConverters/GameObjectConverter.cs.meta +3 -0
- package/Runtime/Core/Serialization/JsonConverters/Matrix4x4Converter.cs +218 -0
- package/Runtime/Core/Serialization/JsonConverters/Matrix4x4Converter.cs.meta +3 -0
- package/Runtime/Core/Serialization/JsonConverters/Vector2Converter.cs +2 -2
- package/Runtime/Core/Serialization/JsonConverters/Vector3Converter.cs +3 -3
- package/Runtime/Core/Serialization/JsonConverters/Vector4Converter.cs +88 -0
- package/Runtime/Core/Serialization/JsonConverters/Vector4Converter.cs.meta +3 -0
- package/Runtime/Core/Serialization/Serializer.cs +8 -0
- package/Runtime/Utils/DeferredDisposalResult.cs +19 -0
- package/Runtime/Utils/DeferredDisposalResult.cs.meta +3 -0
- package/Tests/Runtime/Helper/SceneHelperTests.cs +92 -0
- package/Tests/Runtime/Helper/SceneHelperTests.cs.meta +3 -0
- package/Tests/Runtime/Scenes/Test1.unity +723 -0
- package/Tests/Runtime/Scenes/Test1.unity.meta +7 -0
- package/Tests/Runtime/Scenes/Test2.unity +723 -0
- package/Tests/Runtime/Scenes/Test2.unity.meta +7 -0
- package/Tests/Runtime/Scenes.meta +3 -0
- package/Tests/Runtime/Serialization/JsonSerializationTest.cs +64 -1
- package/package.json +1 -1
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
using System;
|
|
4
4
|
using System.Collections.Generic;
|
|
5
5
|
using System.Linq;
|
|
6
|
+
using System.Threading.Tasks;
|
|
6
7
|
using DataStructure;
|
|
7
8
|
using DataStructure.Adapters;
|
|
8
9
|
using Helper;
|
|
@@ -1577,6 +1578,13 @@
|
|
|
1577
1578
|
return false;
|
|
1578
1579
|
}
|
|
1579
1580
|
|
|
1581
|
+
public static Task AsTask(this AsyncOperation asyncOp)
|
|
1582
|
+
{
|
|
1583
|
+
TaskCompletionSource<bool> taskCompletionSource = new();
|
|
1584
|
+
asyncOp.completed += _ => taskCompletionSource.SetResult(true);
|
|
1585
|
+
return taskCompletionSource.Task;
|
|
1586
|
+
}
|
|
1587
|
+
|
|
1580
1588
|
#if UNITY_EDITOR
|
|
1581
1589
|
public static IEnumerable<Sprite> GetSpritesFromClip(this AnimationClip clip)
|
|
1582
1590
|
{
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
namespace UnityHelpers.Core.Helper
|
|
2
|
+
{
|
|
3
|
+
using System;
|
|
4
|
+
using System.Linq;
|
|
5
|
+
using System.Threading.Tasks;
|
|
6
|
+
using Extension;
|
|
7
|
+
using UnityEngine;
|
|
8
|
+
using UnityEngine.Events;
|
|
9
|
+
using UnityEngine.SceneManagement;
|
|
10
|
+
using Utils;
|
|
11
|
+
using Object = UnityEngine.Object;
|
|
12
|
+
#if UNITY_EDITOR
|
|
13
|
+
using UnityEditor;
|
|
14
|
+
using UnityEditor.SceneManagement;
|
|
15
|
+
#endif
|
|
16
|
+
|
|
17
|
+
public static class SceneHelper
|
|
18
|
+
{
|
|
19
|
+
public static string[] GetAllScenePaths(string[] searchFolders = null)
|
|
20
|
+
{
|
|
21
|
+
#if UNITY_EDITOR
|
|
22
|
+
searchFolders ??= Array.Empty<string>();
|
|
23
|
+
return AssetDatabase
|
|
24
|
+
.FindAssets("t:Scene", searchFolders)
|
|
25
|
+
.Select(AssetDatabase.GUIDToAssetPath)
|
|
26
|
+
.ToArray();
|
|
27
|
+
#else
|
|
28
|
+
return Array.Empty<string>();
|
|
29
|
+
#endif
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
public static string[] GetScenesInBuild()
|
|
33
|
+
{
|
|
34
|
+
#if UNITY_EDITOR
|
|
35
|
+
return EditorBuildSettings
|
|
36
|
+
.scenes.Where(scene => scene.enabled)
|
|
37
|
+
.Select(scene => scene.path)
|
|
38
|
+
.ToArray();
|
|
39
|
+
#else
|
|
40
|
+
return Array.Empty<string>();
|
|
41
|
+
#endif
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
public static async Task<DeferredDisposalResult<T>> GetObjectOfTypeInScene<T>(
|
|
45
|
+
string scenePath
|
|
46
|
+
)
|
|
47
|
+
where T : Object
|
|
48
|
+
{
|
|
49
|
+
DeferredDisposalResult<T[]> result = await GetAllObjectsOfTypeInScene<T>(scenePath);
|
|
50
|
+
return new DeferredDisposalResult<T>(
|
|
51
|
+
result.Result.FirstOrDefault(),
|
|
52
|
+
result.DisposeAsync
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
public static async Task<DeferredDisposalResult<T[]>> GetAllObjectsOfTypeInScene<T>(
|
|
57
|
+
string scenePath
|
|
58
|
+
)
|
|
59
|
+
where T : Object
|
|
60
|
+
{
|
|
61
|
+
// Ensure singleton is created
|
|
62
|
+
_ = UnityMainThreadDispatcher.Instance;
|
|
63
|
+
TaskCompletionSource<T[]> taskCompletionSource = new();
|
|
64
|
+
|
|
65
|
+
SceneLoadScope sceneScope = new(scenePath, OnSceneLoaded);
|
|
66
|
+
return await taskCompletionSource.Task.ContinueWith(result =>
|
|
67
|
+
{
|
|
68
|
+
return new DeferredDisposalResult<T[]>(
|
|
69
|
+
result.Result,
|
|
70
|
+
async () =>
|
|
71
|
+
{
|
|
72
|
+
TaskCompletionSource<bool> disposalComplete = new();
|
|
73
|
+
UnityMainThreadDispatcher.Instance.RunOnMainThread(
|
|
74
|
+
() =>
|
|
75
|
+
sceneScope
|
|
76
|
+
.DisposeAsync()
|
|
77
|
+
.ContinueWith(_ => disposalComplete.SetResult(true))
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
await disposalComplete.Task;
|
|
81
|
+
}
|
|
82
|
+
);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
void OnSceneLoaded(Scene scene, LoadSceneMode mode)
|
|
86
|
+
{
|
|
87
|
+
if (!string.Equals(scene.path, scenePath, StringComparison.Ordinal))
|
|
88
|
+
{
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
T[] foundObjects = Object
|
|
93
|
+
.FindObjectsByType<T>(FindObjectsInactive.Include, FindObjectsSortMode.None)
|
|
94
|
+
.Where(obj =>
|
|
95
|
+
{
|
|
96
|
+
GameObject go = obj.GetGameObject();
|
|
97
|
+
if (go == null)
|
|
98
|
+
{
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return go.scene == scene;
|
|
103
|
+
})
|
|
104
|
+
.ToArray();
|
|
105
|
+
taskCompletionSource.TrySetResult(foundObjects);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
public sealed class SceneLoadScope
|
|
110
|
+
{
|
|
111
|
+
private Scene? _openedScene;
|
|
112
|
+
private readonly UnityAction<Scene, LoadSceneMode> _onSceneLoaded;
|
|
113
|
+
private readonly bool _eventAdded;
|
|
114
|
+
|
|
115
|
+
public SceneLoadScope(string scenePath, UnityAction<Scene, LoadSceneMode> onSceneLoaded)
|
|
116
|
+
{
|
|
117
|
+
_onSceneLoaded = onSceneLoaded;
|
|
118
|
+
_eventAdded = false;
|
|
119
|
+
Scene activeScene = SceneManager.GetActiveScene();
|
|
120
|
+
if (
|
|
121
|
+
!activeScene.IsValid()
|
|
122
|
+
|| !activeScene.isLoaded
|
|
123
|
+
|| !string.Equals(activeScene.path, scenePath, StringComparison.Ordinal)
|
|
124
|
+
)
|
|
125
|
+
{
|
|
126
|
+
#if UNITY_EDITOR
|
|
127
|
+
if (Application.isPlaying)
|
|
128
|
+
{
|
|
129
|
+
SceneManager.sceneLoaded += onSceneLoaded;
|
|
130
|
+
_eventAdded = true;
|
|
131
|
+
_openedScene = EditorSceneManager.LoadSceneInPlayMode(
|
|
132
|
+
scenePath,
|
|
133
|
+
new LoadSceneParameters(LoadSceneMode.Additive, LocalPhysicsMode.None)
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
else
|
|
137
|
+
{
|
|
138
|
+
_openedScene = EditorSceneManager.OpenScene(
|
|
139
|
+
scenePath,
|
|
140
|
+
OpenSceneMode.Additive
|
|
141
|
+
);
|
|
142
|
+
onSceneLoaded?.Invoke(_openedScene.Value, LoadSceneMode.Additive);
|
|
143
|
+
}
|
|
144
|
+
#else
|
|
145
|
+
SceneManager.sceneLoaded += onSceneLoaded;
|
|
146
|
+
_eventAdded = true;
|
|
147
|
+
SceneManager.sceneLoaded += LocalSceneLoaded;
|
|
148
|
+
SceneManager.LoadScene(scenePath, LoadSceneMode.Additive);
|
|
149
|
+
_openedScene = SceneManager.GetSceneByPath(scenePath);
|
|
150
|
+
|
|
151
|
+
void LocalSceneLoaded(Scene scene, LoadSceneMode mode)
|
|
152
|
+
{
|
|
153
|
+
if (!string.Equals(scene.path, scenePath, StringComparison.Ordinal))
|
|
154
|
+
{
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
_openedScene = scene;
|
|
159
|
+
SceneManager.sceneLoaded -= LocalSceneLoaded;
|
|
160
|
+
}
|
|
161
|
+
#endif
|
|
162
|
+
}
|
|
163
|
+
else
|
|
164
|
+
{
|
|
165
|
+
onSceneLoaded?.Invoke(activeScene, LoadSceneMode.Single);
|
|
166
|
+
_openedScene = null;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
public async Task DisposeAsync()
|
|
171
|
+
{
|
|
172
|
+
if (_eventAdded)
|
|
173
|
+
{
|
|
174
|
+
SceneManager.sceneLoaded -= _onSceneLoaded;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (_openedScene == null)
|
|
178
|
+
{
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
Scene openedScene = _openedScene.Value;
|
|
183
|
+
if (!openedScene.IsValid())
|
|
184
|
+
{
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if (!openedScene.isLoaded)
|
|
189
|
+
{
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
#if UNITY_EDITOR
|
|
194
|
+
if (Application.isPlaying)
|
|
195
|
+
{
|
|
196
|
+
AsyncOperation asyncOperation = SceneManager.UnloadSceneAsync(
|
|
197
|
+
openedScene,
|
|
198
|
+
UnloadSceneOptions.None
|
|
199
|
+
);
|
|
200
|
+
await asyncOperation.AsTask();
|
|
201
|
+
}
|
|
202
|
+
else
|
|
203
|
+
{
|
|
204
|
+
EditorSceneManager.CloseScene(openedScene, true);
|
|
205
|
+
}
|
|
206
|
+
#else
|
|
207
|
+
AsyncOperation asyncOperation = SceneManager.UnloadSceneAsync(
|
|
208
|
+
openedScene,
|
|
209
|
+
UnloadSceneOptions.None
|
|
210
|
+
);
|
|
211
|
+
await asyncOperation.AsTask();
|
|
212
|
+
#endif
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
namespace UnityHelpers.Core.Helper
|
|
2
|
+
{
|
|
3
|
+
using System;
|
|
4
|
+
using System.Collections.Concurrent;
|
|
5
|
+
using UnityEngine;
|
|
6
|
+
using Utils;
|
|
7
|
+
|
|
8
|
+
public sealed class UnityMainThreadDispatcher : RuntimeSingleton<UnityMainThreadDispatcher>
|
|
9
|
+
{
|
|
10
|
+
private readonly ConcurrentQueue<Action> _actions = new();
|
|
11
|
+
|
|
12
|
+
public void RunOnMainThread(Action action)
|
|
13
|
+
{
|
|
14
|
+
_actions.Enqueue(action);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
private void Update()
|
|
18
|
+
{
|
|
19
|
+
while (_actions.TryDequeue(out Action action))
|
|
20
|
+
{
|
|
21
|
+
try
|
|
22
|
+
{
|
|
23
|
+
action();
|
|
24
|
+
}
|
|
25
|
+
catch (Exception e)
|
|
26
|
+
{
|
|
27
|
+
Debug.LogException(e, this);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -67,7 +67,13 @@
|
|
|
67
67
|
throw new ArgumentException("Max cannot be zero");
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
|
|
70
|
+
uint result = (uint)(NextDouble() * max);
|
|
71
|
+
if (result == max)
|
|
72
|
+
{
|
|
73
|
+
return result - 1;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return result;
|
|
71
77
|
}
|
|
72
78
|
|
|
73
79
|
public uint NextUint(uint min, uint max)
|
|
@@ -129,7 +135,13 @@
|
|
|
129
135
|
throw new ArgumentException($"Max {max} cannot be less-than or equal-to 0");
|
|
130
136
|
}
|
|
131
137
|
|
|
132
|
-
|
|
138
|
+
long result = (long)(NextDouble() * max);
|
|
139
|
+
if (result == max)
|
|
140
|
+
{
|
|
141
|
+
return result - 1;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return result;
|
|
133
145
|
}
|
|
134
146
|
|
|
135
147
|
public long NextLong(long min, long max)
|
|
@@ -147,7 +159,13 @@
|
|
|
147
159
|
return unchecked((long)NextUlong());
|
|
148
160
|
}
|
|
149
161
|
|
|
150
|
-
|
|
162
|
+
long result = unchecked((long)(NextDouble() * range + min));
|
|
163
|
+
if (result == max)
|
|
164
|
+
{
|
|
165
|
+
return result - 1;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return result;
|
|
151
169
|
}
|
|
152
170
|
|
|
153
171
|
public ulong NextUlong()
|
|
@@ -159,7 +177,12 @@
|
|
|
159
177
|
|
|
160
178
|
public ulong NextUlong(ulong max)
|
|
161
179
|
{
|
|
162
|
-
|
|
180
|
+
ulong result = (ulong)(NextDouble() * max);
|
|
181
|
+
if (result == max)
|
|
182
|
+
{
|
|
183
|
+
return result - 1;
|
|
184
|
+
}
|
|
185
|
+
return result;
|
|
163
186
|
}
|
|
164
187
|
|
|
165
188
|
public ulong NextUlong(ulong min, ulong max)
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
namespace UnityHelpers.Core.Serialization.JsonConverters
|
|
2
|
+
{
|
|
3
|
+
using System;
|
|
4
|
+
using System.Text.Json;
|
|
5
|
+
using System.Text.Json.Serialization;
|
|
6
|
+
using UnityEngine;
|
|
7
|
+
|
|
8
|
+
public sealed class ColorConverter : JsonConverter<Color>
|
|
9
|
+
{
|
|
10
|
+
public static readonly ColorConverter Instance = new();
|
|
11
|
+
|
|
12
|
+
private ColorConverter() { }
|
|
13
|
+
|
|
14
|
+
public override Color Read(
|
|
15
|
+
ref Utf8JsonReader reader,
|
|
16
|
+
Type typeToConvert,
|
|
17
|
+
JsonSerializerOptions options
|
|
18
|
+
)
|
|
19
|
+
{
|
|
20
|
+
if (reader.TokenType != JsonTokenType.StartObject)
|
|
21
|
+
{
|
|
22
|
+
throw new JsonException($"Invalid token type {reader.TokenType}");
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
float r = 0;
|
|
26
|
+
float g = 0;
|
|
27
|
+
float b = 0;
|
|
28
|
+
float a = 1;
|
|
29
|
+
|
|
30
|
+
while (reader.Read())
|
|
31
|
+
{
|
|
32
|
+
if (reader.TokenType == JsonTokenType.EndObject)
|
|
33
|
+
{
|
|
34
|
+
return new Color(r, g, b, a);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (reader.TokenType == JsonTokenType.PropertyName)
|
|
38
|
+
{
|
|
39
|
+
string propertyName = reader.GetString();
|
|
40
|
+
reader.Read();
|
|
41
|
+
switch (propertyName)
|
|
42
|
+
{
|
|
43
|
+
case "r":
|
|
44
|
+
{
|
|
45
|
+
r = reader.GetSingle();
|
|
46
|
+
break;
|
|
47
|
+
}
|
|
48
|
+
case "g":
|
|
49
|
+
{
|
|
50
|
+
g = reader.GetSingle();
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
case "b":
|
|
54
|
+
{
|
|
55
|
+
b = reader.GetSingle();
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
case "a":
|
|
59
|
+
{
|
|
60
|
+
a = reader.GetSingle();
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
default:
|
|
64
|
+
{
|
|
65
|
+
throw new JsonException($"Unknown property: {propertyName}");
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
throw new JsonException("Incomplete JSON for Color");
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
public override void Write(
|
|
75
|
+
Utf8JsonWriter writer,
|
|
76
|
+
Color value,
|
|
77
|
+
JsonSerializerOptions options
|
|
78
|
+
)
|
|
79
|
+
{
|
|
80
|
+
writer.WriteStartObject();
|
|
81
|
+
writer.WriteNumber("r", value.r);
|
|
82
|
+
writer.WriteNumber("g", value.g);
|
|
83
|
+
writer.WriteNumber("b", value.b);
|
|
84
|
+
writer.WriteNumber("a", value.a);
|
|
85
|
+
writer.WriteEndObject();
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
namespace UnityHelpers.Core.Serialization.JsonConverters
|
|
2
|
+
{
|
|
3
|
+
using System;
|
|
4
|
+
using System.Text.Json;
|
|
5
|
+
using System.Text.Json.Serialization;
|
|
6
|
+
using UnityEngine;
|
|
7
|
+
using Object = UnityEngine.Object;
|
|
8
|
+
|
|
9
|
+
public sealed class GameObjectConverter : JsonConverter<GameObject>
|
|
10
|
+
{
|
|
11
|
+
public static readonly GameObjectConverter Instance = new();
|
|
12
|
+
|
|
13
|
+
private GameObjectConverter() { }
|
|
14
|
+
|
|
15
|
+
public override GameObject Read(
|
|
16
|
+
ref Utf8JsonReader reader,
|
|
17
|
+
Type typeToConvert,
|
|
18
|
+
JsonSerializerOptions options
|
|
19
|
+
)
|
|
20
|
+
{
|
|
21
|
+
throw new NotImplementedException(nameof(Read));
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
public override void Write(
|
|
25
|
+
Utf8JsonWriter writer,
|
|
26
|
+
GameObject value,
|
|
27
|
+
JsonSerializerOptions options
|
|
28
|
+
)
|
|
29
|
+
{
|
|
30
|
+
writer.WriteStringValue(
|
|
31
|
+
value == null
|
|
32
|
+
? "{}"
|
|
33
|
+
: new { name = value.name, type = value.GetType().FullName }.ToString()
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
namespace UnityHelpers.Core.Serialization.JsonConverters
|
|
2
|
+
{
|
|
3
|
+
using System;
|
|
4
|
+
using System.Text.Json;
|
|
5
|
+
using System.Text.Json.Serialization;
|
|
6
|
+
using UnityEngine;
|
|
7
|
+
|
|
8
|
+
public sealed class Matrix4x4Converter : JsonConverter<Matrix4x4>
|
|
9
|
+
{
|
|
10
|
+
private static readonly string[] PropertyNames =
|
|
11
|
+
{
|
|
12
|
+
"m00",
|
|
13
|
+
"m01",
|
|
14
|
+
"m02",
|
|
15
|
+
"m03",
|
|
16
|
+
"m10",
|
|
17
|
+
"m11",
|
|
18
|
+
"m12",
|
|
19
|
+
"m13",
|
|
20
|
+
"m20",
|
|
21
|
+
"m21",
|
|
22
|
+
"m22",
|
|
23
|
+
"m23",
|
|
24
|
+
"m30",
|
|
25
|
+
"m31",
|
|
26
|
+
"m32",
|
|
27
|
+
"m33",
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
public static readonly Matrix4x4Converter Instance = new();
|
|
31
|
+
|
|
32
|
+
private Matrix4x4Converter() { }
|
|
33
|
+
|
|
34
|
+
public override Matrix4x4 Read(
|
|
35
|
+
ref Utf8JsonReader reader,
|
|
36
|
+
Type typeToConvert,
|
|
37
|
+
JsonSerializerOptions options
|
|
38
|
+
)
|
|
39
|
+
{
|
|
40
|
+
if (reader.TokenType != JsonTokenType.StartObject)
|
|
41
|
+
{
|
|
42
|
+
throw new JsonException("Expected StartObject token when parsing Matrix4x4.");
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
float m00 = 0;
|
|
46
|
+
float m01 = 0;
|
|
47
|
+
float m02 = 0;
|
|
48
|
+
float m03 = 0;
|
|
49
|
+
float m10 = 0;
|
|
50
|
+
float m11 = 0;
|
|
51
|
+
float m12 = 0;
|
|
52
|
+
float m13 = 0;
|
|
53
|
+
float m20 = 0;
|
|
54
|
+
float m21 = 0;
|
|
55
|
+
float m22 = 0;
|
|
56
|
+
float m23 = 0;
|
|
57
|
+
float m30 = 0;
|
|
58
|
+
float m31 = 0;
|
|
59
|
+
float m32 = 0;
|
|
60
|
+
float m33 = 0;
|
|
61
|
+
|
|
62
|
+
bool[] found = new bool[16];
|
|
63
|
+
|
|
64
|
+
while (reader.Read())
|
|
65
|
+
{
|
|
66
|
+
if (reader.TokenType == JsonTokenType.EndObject)
|
|
67
|
+
{
|
|
68
|
+
break;
|
|
69
|
+
}
|
|
70
|
+
if (reader.TokenType != JsonTokenType.PropertyName)
|
|
71
|
+
{
|
|
72
|
+
throw new JsonException("Expected property name in Matrix4x4 JSON.");
|
|
73
|
+
}
|
|
74
|
+
string propertyName = reader.GetString();
|
|
75
|
+
if (!reader.Read())
|
|
76
|
+
{
|
|
77
|
+
throw new JsonException($"Expected value for property '{propertyName}'.");
|
|
78
|
+
}
|
|
79
|
+
float value;
|
|
80
|
+
try
|
|
81
|
+
{
|
|
82
|
+
value = reader.GetSingle();
|
|
83
|
+
}
|
|
84
|
+
catch (Exception ex)
|
|
85
|
+
{
|
|
86
|
+
throw new JsonException($"Invalid value for property '{propertyName}'.", ex);
|
|
87
|
+
}
|
|
88
|
+
switch (propertyName)
|
|
89
|
+
{
|
|
90
|
+
case "m00":
|
|
91
|
+
m00 = value;
|
|
92
|
+
found[0] = true;
|
|
93
|
+
break;
|
|
94
|
+
case "m01":
|
|
95
|
+
m01 = value;
|
|
96
|
+
found[1] = true;
|
|
97
|
+
break;
|
|
98
|
+
case "m02":
|
|
99
|
+
m02 = value;
|
|
100
|
+
found[2] = true;
|
|
101
|
+
break;
|
|
102
|
+
case "m03":
|
|
103
|
+
m03 = value;
|
|
104
|
+
found[3] = true;
|
|
105
|
+
break;
|
|
106
|
+
case "m10":
|
|
107
|
+
m10 = value;
|
|
108
|
+
found[4] = true;
|
|
109
|
+
break;
|
|
110
|
+
case "m11":
|
|
111
|
+
m11 = value;
|
|
112
|
+
found[5] = true;
|
|
113
|
+
break;
|
|
114
|
+
case "m12":
|
|
115
|
+
m12 = value;
|
|
116
|
+
found[6] = true;
|
|
117
|
+
break;
|
|
118
|
+
case "m13":
|
|
119
|
+
m13 = value;
|
|
120
|
+
found[7] = true;
|
|
121
|
+
break;
|
|
122
|
+
case "m20":
|
|
123
|
+
m20 = value;
|
|
124
|
+
found[8] = true;
|
|
125
|
+
break;
|
|
126
|
+
case "m21":
|
|
127
|
+
m21 = value;
|
|
128
|
+
found[9] = true;
|
|
129
|
+
break;
|
|
130
|
+
case "m22":
|
|
131
|
+
m22 = value;
|
|
132
|
+
found[10] = true;
|
|
133
|
+
break;
|
|
134
|
+
case "m23":
|
|
135
|
+
m23 = value;
|
|
136
|
+
found[11] = true;
|
|
137
|
+
break;
|
|
138
|
+
case "m30":
|
|
139
|
+
m30 = value;
|
|
140
|
+
found[12] = true;
|
|
141
|
+
break;
|
|
142
|
+
case "m31":
|
|
143
|
+
m31 = value;
|
|
144
|
+
found[13] = true;
|
|
145
|
+
break;
|
|
146
|
+
case "m32":
|
|
147
|
+
m32 = value;
|
|
148
|
+
found[14] = true;
|
|
149
|
+
break;
|
|
150
|
+
case "m33":
|
|
151
|
+
m33 = value;
|
|
152
|
+
found[15] = true;
|
|
153
|
+
break;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
for (int i = 0; i < found.Length; i++)
|
|
158
|
+
{
|
|
159
|
+
if (!found[i])
|
|
160
|
+
{
|
|
161
|
+
throw new JsonException(
|
|
162
|
+
$"Missing property '{PropertyNames[i]}' for Matrix4x4."
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
Matrix4x4 matrix = new()
|
|
168
|
+
{
|
|
169
|
+
m00 = m00,
|
|
170
|
+
m01 = m01,
|
|
171
|
+
m02 = m02,
|
|
172
|
+
m03 = m03,
|
|
173
|
+
m10 = m10,
|
|
174
|
+
m11 = m11,
|
|
175
|
+
m12 = m12,
|
|
176
|
+
m13 = m13,
|
|
177
|
+
m20 = m20,
|
|
178
|
+
m21 = m21,
|
|
179
|
+
m22 = m22,
|
|
180
|
+
m23 = m23,
|
|
181
|
+
m30 = m30,
|
|
182
|
+
m31 = m31,
|
|
183
|
+
m32 = m32,
|
|
184
|
+
m33 = m33,
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
return matrix;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
public override void Write(
|
|
191
|
+
Utf8JsonWriter writer,
|
|
192
|
+
Matrix4x4 matrix,
|
|
193
|
+
JsonSerializerOptions options
|
|
194
|
+
)
|
|
195
|
+
{
|
|
196
|
+
writer.WriteStartObject();
|
|
197
|
+
|
|
198
|
+
writer.WriteNumber("m00", matrix.m00);
|
|
199
|
+
writer.WriteNumber("m01", matrix.m01);
|
|
200
|
+
writer.WriteNumber("m02", matrix.m02);
|
|
201
|
+
writer.WriteNumber("m03", matrix.m03);
|
|
202
|
+
writer.WriteNumber("m10", matrix.m10);
|
|
203
|
+
writer.WriteNumber("m11", matrix.m11);
|
|
204
|
+
writer.WriteNumber("m12", matrix.m12);
|
|
205
|
+
writer.WriteNumber("m13", matrix.m13);
|
|
206
|
+
writer.WriteNumber("m20", matrix.m20);
|
|
207
|
+
writer.WriteNumber("m21", matrix.m21);
|
|
208
|
+
writer.WriteNumber("m22", matrix.m22);
|
|
209
|
+
writer.WriteNumber("m23", matrix.m23);
|
|
210
|
+
writer.WriteNumber("m30", matrix.m30);
|
|
211
|
+
writer.WriteNumber("m31", matrix.m31);
|
|
212
|
+
writer.WriteNumber("m32", matrix.m32);
|
|
213
|
+
writer.WriteNumber("m33", matrix.m33);
|
|
214
|
+
|
|
215
|
+
writer.WriteEndObject();
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|