com.wallstop-studios.dxmessaging 2.0.0-rc26.1 → 2.0.0-rc26.3

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.
Files changed (38) hide show
  1. package/Editor/Analyzers/WallstopStudios.DxMessaging.SourceGenerators.dll +0 -0
  2. package/Editor/CustomEditors/MessagingComponentEditor.cs +530 -0
  3. package/Editor/CustomEditors/MessagingComponentEditor.cs.meta +3 -0
  4. package/Editor/CustomEditors.meta +3 -0
  5. package/Editor/DxMessagingEditorInitializer.cs +19 -0
  6. package/Editor/DxMessagingEditorInitializer.cs.meta +3 -0
  7. package/Editor/Settings/DxMessagingSettings.cs +68 -0
  8. package/Editor/Settings/DxMessagingSettings.cs.meta +3 -0
  9. package/Editor/Settings/DxMessagingSettingsProvider.cs +55 -0
  10. package/Editor/Settings/DxMessagingSettingsProvider.cs.meta +3 -0
  11. package/Editor/Settings.meta +3 -0
  12. package/README.md +16 -0
  13. package/Runtime/Core/Attributes/DxAutoConstructorAttribute.cs +14 -0
  14. package/Runtime/Core/Attributes/DxAutoConstructorAttribute.cs.meta +3 -0
  15. package/Runtime/Core/DataStructure/CyclicBuffer.cs +265 -0
  16. package/Runtime/Core/DataStructure/CyclicBuffer.cs.meta +3 -0
  17. package/Runtime/Core/DataStructure.meta +3 -0
  18. package/Runtime/Core/Diagnostics/MessageEmissionData.cs +53 -0
  19. package/Runtime/Core/Diagnostics/MessageEmissionData.cs.meta +3 -0
  20. package/Runtime/Core/Diagnostics/MessageRegistrationData.cs +25 -0
  21. package/Runtime/Core/Diagnostics/MessageRegistrationData.cs.meta +3 -0
  22. package/Runtime/Core/Diagnostics/MessageRegistrationType.cs +21 -0
  23. package/Runtime/Core/Diagnostics/MessageRegistrationType.cs.meta +3 -0
  24. package/Runtime/Core/Diagnostics.meta +3 -0
  25. package/Runtime/Core/Extensions/IListExtensions.cs +48 -0
  26. package/Runtime/Core/Extensions/IListExtensions.cs.meta +3 -0
  27. package/Runtime/Core/MessageBus/IMessageBus.cs +5 -3
  28. package/Runtime/Core/MessageBus/MessageBus.cs +28 -0
  29. package/Runtime/Core/MessageHandler.cs +200 -40
  30. package/Runtime/Core/MessageRegistrationToken.cs +645 -57
  31. package/Runtime/Core/Messages/ReflexiveMessage.cs +20 -1
  32. package/Runtime/Unity/MessagingComponent.cs +1 -1
  33. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxAutoConstructorGenerator.cs +249 -0
  34. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxAutoConstructorGenerator.cs.meta +11 -0
  35. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators.csproj +10 -13
  36. package/Tests/Runtime/Core/NominalTests.cs +2 -8
  37. package/Tests/Runtime/WallstopStudios.DxMessaging.Tests.Runtime.csproj +7 -1
  38. package/package.json +3 -1
@@ -0,0 +1,530 @@
1
+ namespace DxMessaging.Editor.CustomEditors
2
+ {
3
+ #if UNITY_EDITOR
4
+ using System.Collections.Generic;
5
+ using System.Linq;
6
+ using Core;
7
+ using Core.Diagnostics;
8
+ using Core.Messages;
9
+ using Unity;
10
+ using UnityEditor;
11
+ using UnityEngine;
12
+ using Object = UnityEngine.Object;
13
+
14
+ [CustomEditor(typeof(MessagingComponent))]
15
+ public sealed class MessagingComponentEditor : Editor
16
+ {
17
+ private const int PageSize = 5;
18
+
19
+ private readonly Dictionary<MonoBehaviour, bool> _listenerFoldouts = new();
20
+ private readonly Dictionary<MonoBehaviour, int> _listenerRegistrationPaging = new();
21
+ private readonly Dictionary<MonoBehaviour, bool> _listenerBufferFoldouts = new();
22
+ private readonly Dictionary<MonoBehaviour, int> _listenerBufferPaging = new();
23
+
24
+ private bool _globalBufferExpanded;
25
+ private int _globalBufferPaging;
26
+
27
+ private GUIStyle _matchingStyle;
28
+ private GUIStyle _potentialMatchStyle;
29
+ private GUIStyle _defaultStyle;
30
+ private GUIStyle _leftAlignedStyle;
31
+ private GUIStyle _rightAlignedStyle;
32
+
33
+ private void OnEnable()
34
+ {
35
+ _listenerFoldouts.Clear();
36
+ }
37
+
38
+ public override void OnInspectorGUI()
39
+ {
40
+ base.OnInspectorGUI();
41
+
42
+ _matchingStyle ??= new GUIStyle(EditorStyles.label)
43
+ {
44
+ normal = { textColor = Color.green },
45
+ fontStyle = FontStyle.Bold,
46
+ };
47
+ _potentialMatchStyle ??= new GUIStyle(EditorStyles.label)
48
+ {
49
+ normal = { textColor = Color.yellow },
50
+ fontStyle = FontStyle.Bold,
51
+ };
52
+ _defaultStyle ??= new GUIStyle(EditorStyles.label);
53
+ _leftAlignedStyle ??= new GUIStyle(EditorStyles.label)
54
+ {
55
+ alignment = TextAnchor.MiddleLeft,
56
+ };
57
+ _rightAlignedStyle ??= new GUIStyle(EditorStyles.label)
58
+ {
59
+ alignment = TextAnchor.MiddleRight,
60
+ };
61
+
62
+ MessagingComponent component = target as MessagingComponent;
63
+ if (component == null)
64
+ {
65
+ return;
66
+ }
67
+
68
+ if (component._registeredListeners.Count == 0)
69
+ {
70
+ EditorGUILayout.LabelField("No listeners registered.");
71
+ return;
72
+ }
73
+
74
+ EditorGUILayout.Space();
75
+ EditorGUILayout.LabelField("Global Diagnostics", EditorStyles.boldLabel);
76
+
77
+ using (new GUILayout.HorizontalScope())
78
+ {
79
+ if (
80
+ component._registeredListeners.Values.Any(token => !token.DiagnosticMode)
81
+ && GUILayout.Button(
82
+ $"Enable Diagnostics for All ({component._registeredListeners.Count})"
83
+ )
84
+ )
85
+ {
86
+ foreach (
87
+ MessageRegistrationToken token in component._registeredListeners.Values
88
+ )
89
+ {
90
+ token.DiagnosticMode = true;
91
+ }
92
+ }
93
+
94
+ if (
95
+ component._registeredListeners.Values.Any(token => token.DiagnosticMode)
96
+ && GUILayout.Button(
97
+ $"Disable Diagnostics for All ({component._registeredListeners.Count})"
98
+ )
99
+ )
100
+ {
101
+ foreach (
102
+ MessageRegistrationToken token in component._registeredListeners.Values
103
+ )
104
+ {
105
+ token.DiagnosticMode = false;
106
+ }
107
+ }
108
+ }
109
+
110
+ if (!MessageHandler.MessageBus.DiagnosticsMode)
111
+ {
112
+ if (GUILayout.Button("Enable Global Diagnostics"))
113
+ {
114
+ MessageHandler.MessageBus.DiagnosticsMode = true;
115
+ }
116
+ }
117
+ else
118
+ {
119
+ if (GUILayout.Button("Disable Global Diagnostics"))
120
+ {
121
+ MessageHandler.MessageBus.DiagnosticsMode = false;
122
+ }
123
+ else
124
+ {
125
+ EditorGUILayout.Space();
126
+ EditorGUILayout.LabelField("Global Buffer", EditorStyles.boldLabel);
127
+
128
+ _globalBufferExpanded = EditorGUILayout.Foldout(
129
+ _globalBufferExpanded,
130
+ "Global Messages",
131
+ true
132
+ );
133
+ int totalGlobalMessages = MessageHandler.MessageBus._emissionBuffer.Count;
134
+ if (_globalBufferExpanded && totalGlobalMessages > 0)
135
+ {
136
+ int page = _globalBufferPaging;
137
+ int totalPages = (totalGlobalMessages + PageSize - 1) / PageSize;
138
+ page = Mathf.Clamp(page, 0, totalPages - 1);
139
+ EditorGUI.indentLevel++;
140
+ if (totalPages > 1)
141
+ {
142
+ using (new EditorGUILayout.HorizontalScope())
143
+ {
144
+ GUI.enabled = page > 0;
145
+ if (GUILayout.Button("<< Previous"))
146
+ {
147
+ _globalBufferPaging--;
148
+ }
149
+
150
+ GUI.enabled = true;
151
+
152
+ GUILayout.FlexibleSpace();
153
+ EditorGUILayout.LabelField($"Page {page + 1} of {totalPages}");
154
+ GUILayout.FlexibleSpace();
155
+
156
+ GUI.enabled = page < totalPages - 1;
157
+ if (GUILayout.Button("Next >>"))
158
+ {
159
+ _globalBufferPaging++;
160
+ }
161
+
162
+ GUI.enabled = true;
163
+ }
164
+ }
165
+
166
+ MessageEmissionData[] pagedGlobalMessages = MessageHandler
167
+ .MessageBus._emissionBuffer.Reverse()
168
+ .Skip(page * PageSize)
169
+ .Take(PageSize)
170
+ .ToArray();
171
+ foreach (MessageEmissionData globalEmissionData in pagedGlobalMessages)
172
+ {
173
+ using (new EditorGUILayout.VerticalScope("box"))
174
+ {
175
+ GUIStyle style;
176
+ InstanceId? context = globalEmissionData.context;
177
+ if (context?.Object != null)
178
+ {
179
+ Object unityObject = context.Value.Object;
180
+ if (
181
+ (
182
+ typeof(ITargetedMessage).IsAssignableFrom(
183
+ globalEmissionData.message.MessageType
184
+ )
185
+ && (
186
+ unityObject == component.gameObject
187
+ || component
188
+ .GetComponents<MonoBehaviour>()
189
+ .Any(script => script == unityObject)
190
+ )
191
+ )
192
+ || (
193
+ typeof(IBroadcastMessage).IsAssignableFrom(
194
+ globalEmissionData.message.MessageType
195
+ )
196
+ && (
197
+ component._registeredListeners.Keys.Any(script =>
198
+ script.gameObject == unityObject
199
+ || script
200
+ .GetComponents<MonoBehaviour>()
201
+ .Any(matchedScript =>
202
+ matchedScript == unityObject
203
+ )
204
+ )
205
+ )
206
+ )
207
+ )
208
+ {
209
+ style = component._registeredListeners.Values.Any(
210
+ listener =>
211
+ listener._emissionBuffer.Contains(
212
+ globalEmissionData
213
+ )
214
+ )
215
+ ? _matchingStyle
216
+ : _potentialMatchStyle;
217
+ }
218
+ else
219
+ {
220
+ style = _defaultStyle;
221
+ }
222
+ }
223
+ else
224
+ {
225
+ style = component._registeredListeners.Values.Any(listener =>
226
+ listener._emissionBuffer.Contains(globalEmissionData)
227
+ )
228
+ ? _matchingStyle
229
+ : _defaultStyle;
230
+ }
231
+
232
+ GUIContent labelContent = new("Message Type");
233
+ GUIContent valueContent = new(
234
+ globalEmissionData.message.MessageType.Name,
235
+ globalEmissionData.stackTrace
236
+ );
237
+
238
+ EditorGUILayout.LabelField(labelContent, valueContent, style);
239
+ if (context?.Object != null)
240
+ {
241
+ Object unityObject = context.Value.Object;
242
+ string label = "Context";
243
+ if (
244
+ typeof(ITargetedMessage).IsAssignableFrom(
245
+ globalEmissionData.message.MessageType
246
+ )
247
+ )
248
+ {
249
+ label = "Target";
250
+ }
251
+ else if (
252
+ typeof(IBroadcastMessage).IsAssignableFrom(
253
+ globalEmissionData.message.MessageType
254
+ )
255
+ )
256
+ {
257
+ label = "Source";
258
+ }
259
+ EditorGUILayout.ObjectField(
260
+ label,
261
+ unityObject,
262
+ typeof(Object),
263
+ true
264
+ );
265
+ }
266
+ }
267
+ }
268
+ }
269
+ }
270
+ }
271
+ List<MonoBehaviour> listeners = new(component._registeredListeners.Keys);
272
+
273
+ EditorGUILayout.Space();
274
+ EditorGUILayout.LabelField("Local Buffer", EditorStyles.boldLabel);
275
+ foreach (MonoBehaviour listener in listeners)
276
+ {
277
+ if (!component._registeredListeners[listener].DiagnosticMode)
278
+ {
279
+ EditorGUILayout.Space();
280
+ EditorGUILayout.HelpBox(
281
+ $"Diagnostics are disabled for {listener.GetType().Name}. Enable diagnostics to view diagnostics data.",
282
+ MessageType.Info
283
+ );
284
+ }
285
+ else
286
+ {
287
+ _listenerBufferFoldouts.TryAdd(listener, false);
288
+ _listenerBufferFoldouts[listener] = EditorGUILayout.Foldout(
289
+ _listenerBufferFoldouts[listener],
290
+ listener.GetType().Name,
291
+ true
292
+ );
293
+
294
+ int totalMessages = component
295
+ ._registeredListeners[listener]
296
+ ._emissionBuffer
297
+ .Count;
298
+ if (_listenerBufferFoldouts[listener] && totalMessages > 0)
299
+ {
300
+ int page = _listenerBufferPaging.GetValueOrDefault(listener, 0);
301
+ int totalPages = (totalMessages + PageSize - 1) / PageSize;
302
+ page = Mathf.Clamp(page, 0, totalPages - 1);
303
+ _listenerBufferPaging[listener] = page;
304
+ EditorGUI.indentLevel++;
305
+ if (totalPages > 1)
306
+ {
307
+ using (new EditorGUILayout.HorizontalScope())
308
+ {
309
+ GUI.enabled = page > 0;
310
+ if (GUILayout.Button("<< Previous"))
311
+ {
312
+ _listenerBufferPaging[listener]--;
313
+ }
314
+
315
+ GUI.enabled = true;
316
+
317
+ GUILayout.FlexibleSpace();
318
+ EditorGUILayout.LabelField($"Page {page + 1} of {totalPages}");
319
+ GUILayout.FlexibleSpace();
320
+
321
+ GUI.enabled = page < totalPages - 1;
322
+ if (GUILayout.Button("Next >>"))
323
+ {
324
+ _listenerBufferPaging[listener]++;
325
+ }
326
+
327
+ GUI.enabled = true;
328
+ }
329
+ }
330
+
331
+ MessageEmissionData[] pagedLocalMessages = component
332
+ ._registeredListeners[listener]
333
+ ._emissionBuffer.Reverse()
334
+ .Skip(page * PageSize)
335
+ .Take(PageSize)
336
+ .ToArray();
337
+ foreach (MessageEmissionData globalEmissionData in pagedLocalMessages)
338
+ {
339
+ using (new EditorGUILayout.VerticalScope("box"))
340
+ {
341
+ GUIContent labelContent = new("Message Type");
342
+ GUIContent valueContent = new(
343
+ globalEmissionData.message.MessageType.Name,
344
+ globalEmissionData.stackTrace
345
+ );
346
+
347
+ EditorGUILayout.LabelField(labelContent, valueContent);
348
+
349
+ InstanceId? context = globalEmissionData.context;
350
+ if (context?.Object != null)
351
+ {
352
+ Object unityObject = context.Value.Object;
353
+ string label = "Context";
354
+ if (
355
+ typeof(ITargetedMessage).IsAssignableFrom(
356
+ globalEmissionData.message.MessageType
357
+ )
358
+ )
359
+ {
360
+ label = "Target";
361
+ }
362
+ else if (
363
+ typeof(IBroadcastMessage).IsAssignableFrom(
364
+ globalEmissionData.message.MessageType
365
+ )
366
+ )
367
+ {
368
+ label = "Source";
369
+ }
370
+ EditorGUILayout.ObjectField(
371
+ label,
372
+ unityObject,
373
+ typeof(Object),
374
+ true
375
+ );
376
+ }
377
+ }
378
+ }
379
+ }
380
+ }
381
+ }
382
+
383
+ EditorGUILayout.Space();
384
+ EditorGUILayout.LabelField("Listeners", EditorStyles.boldLabel);
385
+
386
+ foreach (MonoBehaviour listener in listeners)
387
+ {
388
+ if (listener == null)
389
+ {
390
+ continue;
391
+ }
392
+
393
+ if (
394
+ !component._registeredListeners.TryGetValue(
395
+ listener,
396
+ out MessageRegistrationToken token
397
+ )
398
+ )
399
+ {
400
+ continue;
401
+ }
402
+
403
+ _listenerFoldouts.TryAdd(listener, false);
404
+ _listenerFoldouts[listener] = EditorGUILayout.Foldout(
405
+ _listenerFoldouts[listener],
406
+ listener.GetType().Name,
407
+ true
408
+ );
409
+ if (_listenerFoldouts[listener])
410
+ {
411
+ EditorGUI.indentLevel++;
412
+ EditorGUILayout.ObjectField("Listener", listener, typeof(MonoBehaviour), true);
413
+ token.DiagnosticMode = EditorGUILayout.Toggle(
414
+ "Enable Diagnostics",
415
+ token.DiagnosticMode
416
+ );
417
+ if (token.DiagnosticMode)
418
+ {
419
+ if (token._metadata.Count == 0)
420
+ {
421
+ EditorGUILayout.LabelField("No messages registered for this listener.");
422
+ }
423
+ else
424
+ {
425
+ DrawPaginatedRegistrations(listener, token);
426
+ }
427
+ }
428
+ else
429
+ {
430
+ EditorGUILayout.HelpBox(
431
+ "Enable diagnostics to view registration details.",
432
+ MessageType.Info
433
+ );
434
+ }
435
+
436
+ EditorGUI.indentLevel--;
437
+ }
438
+ }
439
+ }
440
+
441
+ private void DrawPaginatedRegistrations(
442
+ MonoBehaviour listener,
443
+ MessageRegistrationToken token
444
+ )
445
+ {
446
+ _listenerRegistrationPaging.TryAdd(listener, 0);
447
+ int page = _listenerRegistrationPaging[listener];
448
+ int totalRegistrations = token._metadata.Count;
449
+ int totalPages = (totalRegistrations + PageSize - 1) / PageSize;
450
+ page = Mathf.Clamp(page, 0, totalPages - 1);
451
+
452
+ EditorGUILayout.LabelField("Registrations", EditorStyles.boldLabel);
453
+ EditorGUI.indentLevel++;
454
+
455
+ if (totalPages > 1)
456
+ {
457
+ using (new EditorGUILayout.HorizontalScope())
458
+ {
459
+ GUI.enabled = page > 0;
460
+ if (GUILayout.Button("<< Previous"))
461
+ {
462
+ _listenerRegistrationPaging[listener]--;
463
+ }
464
+ GUI.enabled = true;
465
+
466
+ GUILayout.FlexibleSpace();
467
+ EditorGUILayout.LabelField($"Page {page + 1} of {totalPages}");
468
+ GUILayout.FlexibleSpace();
469
+
470
+ GUI.enabled = page < totalPages - 1;
471
+ if (GUILayout.Button("Next >>"))
472
+ {
473
+ _listenerRegistrationPaging[listener]++;
474
+ }
475
+ GUI.enabled = true;
476
+ }
477
+ }
478
+
479
+ KeyValuePair<
480
+ MessageRegistrationHandle,
481
+ MessageRegistrationMetadata
482
+ >[] pagedRegistrations = token
483
+ ._metadata.OrderBy(kvp => kvp.Key)
484
+ .Skip(page * PageSize)
485
+ .Take(PageSize)
486
+ .ToArray();
487
+
488
+ foreach (
489
+ (
490
+ MessageRegistrationHandle handle,
491
+ MessageRegistrationMetadata metadata
492
+ ) in pagedRegistrations
493
+ )
494
+ {
495
+ using (new EditorGUILayout.VerticalScope("box"))
496
+ {
497
+ int callCount = token._callCounts.GetValueOrDefault(handle, 0);
498
+
499
+ string messageName = metadata.type?.Name ?? string.Empty;
500
+ GUIContent labelContent = new(messageName, $"Priority: {metadata.priority}");
501
+ GUIContent valueContent = new(
502
+ metadata.registrationType.ToString(),
503
+ $"Priority: {metadata.priority}"
504
+ );
505
+
506
+ EditorGUILayout.LabelField(labelContent, valueContent);
507
+ if (metadata.context?.Object != null)
508
+ {
509
+ Object unityObject = metadata.context.Value.Object;
510
+ string label = "Context";
511
+ if (typeof(ITargetedMessage).IsAssignableFrom(metadata.type))
512
+ {
513
+ label = "Target";
514
+ }
515
+ else if (typeof(IBroadcastMessage).IsAssignableFrom(metadata.type))
516
+ {
517
+ label = "Source";
518
+ }
519
+ EditorGUILayout.ObjectField(label, unityObject, typeof(Object), true);
520
+ }
521
+
522
+ EditorGUILayout.LabelField("Call Count", callCount.ToString());
523
+ EditorGUILayout.Space();
524
+ }
525
+ }
526
+ EditorGUI.indentLevel--;
527
+ }
528
+ }
529
+ #endif
530
+ }
@@ -0,0 +1,3 @@
1
+ fileFormatVersion: 2
2
+ guid: e078b310572343318b79a3c00d0f274d
3
+ timeCreated: 1749666380
@@ -0,0 +1,3 @@
1
+ fileFormatVersion: 2
2
+ guid: 652cab55c8444567a5101966444e9071
3
+ timeCreated: 1749666371
@@ -0,0 +1,19 @@
1
+ namespace DxMessaging.Editor
2
+ {
3
+ #if UNITY_EDITOR
4
+ using Core.MessageBus;
5
+ using Settings;
6
+ using UnityEditor;
7
+
8
+ [InitializeOnLoad]
9
+ public static class DxMessagingEditorInitializer
10
+ {
11
+ static DxMessagingEditorInitializer()
12
+ {
13
+ DxMessagingSettings settings = DxMessagingSettings.GetOrCreateSettings();
14
+ IMessageBus.GlobalDiagnosticsMode = settings.EnableDiagnosticsInEditor;
15
+ IMessageBus.GlobalMessageBufferSize = settings.MessageBufferSize;
16
+ }
17
+ }
18
+ #endif
19
+ }
@@ -0,0 +1,3 @@
1
+ fileFormatVersion: 2
2
+ guid: b5eeb11bcc9d4d70861d5dc7084daae5
3
+ timeCreated: 1749668189
@@ -0,0 +1,68 @@
1
+ namespace DxMessaging.Editor.Settings
2
+ {
3
+ #if UNITY_EDITOR
4
+ using System.Linq;
5
+ using UnityEditor;
6
+ using UnityEngine;
7
+
8
+ public sealed class DxMessagingSettings : ScriptableObject
9
+ {
10
+ private const int DefaultBufferSize = 100;
11
+ private const string SettingsPath = "Assets/Editor/DxMessagingSettings.asset";
12
+
13
+ [SerializeField]
14
+ internal bool _enableDiagnosticsInEditor;
15
+
16
+ [SerializeField]
17
+ internal int _messageBufferSize = DefaultBufferSize;
18
+
19
+ public bool EnableDiagnosticsInEditor
20
+ {
21
+ get => _enableDiagnosticsInEditor;
22
+ set => _enableDiagnosticsInEditor = value;
23
+ }
24
+
25
+ public int MessageBufferSize
26
+ {
27
+ get => _messageBufferSize;
28
+ set => _messageBufferSize = value;
29
+ }
30
+
31
+ internal static DxMessagingSettings GetOrCreateSettings()
32
+ {
33
+ DxMessagingSettings settings = AssetDatabase.LoadAssetAtPath<DxMessagingSettings>(
34
+ SettingsPath
35
+ );
36
+
37
+ if (settings == null)
38
+ {
39
+ settings = AssetDatabase
40
+ .FindAssets($"t:{nameof(DxMessagingSettings)}")
41
+ .Select(AssetDatabase.GUIDToAssetPath)
42
+ .Select(AssetDatabase.LoadAssetAtPath<DxMessagingSettings>)
43
+ .FirstOrDefault(asset => asset != null);
44
+ }
45
+
46
+ if (settings == null)
47
+ {
48
+ settings = CreateInstance<DxMessagingSettings>();
49
+ settings._enableDiagnosticsInEditor = false;
50
+ settings._messageBufferSize = DefaultBufferSize;
51
+ if (!AssetDatabase.IsValidFolder("Assets/Editor"))
52
+ {
53
+ AssetDatabase.CreateFolder("Assets", "Editor");
54
+ }
55
+ AssetDatabase.CreateAsset(settings, SettingsPath);
56
+ AssetDatabase.SaveAssets();
57
+ }
58
+
59
+ return settings;
60
+ }
61
+
62
+ internal static SerializedObject GetSerializedSettings()
63
+ {
64
+ return new SerializedObject(GetOrCreateSettings());
65
+ }
66
+ }
67
+ #endif
68
+ }
@@ -0,0 +1,3 @@
1
+ fileFormatVersion: 2
2
+ guid: 477d53eef70c4496b945199c62169dfb
3
+ timeCreated: 1749668079