com.wallstop-studios.dxmessaging 2.0.0-rc26.1 → 2.0.0-rc26.2
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/CustomEditors/MessagingComponentEditor.cs +470 -0
- package/Editor/CustomEditors/MessagingComponentEditor.cs.meta +3 -0
- package/Editor/CustomEditors.meta +3 -0
- package/Editor/DxMessagingEditorInitializer.cs +19 -0
- package/Editor/DxMessagingEditorInitializer.cs.meta +3 -0
- package/Editor/Settings/DxMessagingSettings.cs +68 -0
- package/Editor/Settings/DxMessagingSettings.cs.meta +3 -0
- package/Editor/Settings/DxMessagingSettingsProvider.cs +55 -0
- package/Editor/Settings/DxMessagingSettingsProvider.cs.meta +3 -0
- package/Editor/Settings.meta +3 -0
- package/README.md +16 -0
- package/Runtime/Core/DataStructure/CyclicBuffer.cs +265 -0
- package/Runtime/Core/DataStructure/CyclicBuffer.cs.meta +3 -0
- package/Runtime/Core/DataStructure.meta +3 -0
- package/Runtime/Core/Diagnostics/MessageEmissionData.cs +53 -0
- package/Runtime/Core/Diagnostics/MessageEmissionData.cs.meta +3 -0
- package/Runtime/Core/Diagnostics/MessageRegistrationData.cs +25 -0
- package/Runtime/Core/Diagnostics/MessageRegistrationData.cs.meta +3 -0
- package/Runtime/Core/Diagnostics/MessageRegistrationType.cs +21 -0
- package/Runtime/Core/Diagnostics/MessageRegistrationType.cs.meta +3 -0
- package/Runtime/Core/Diagnostics.meta +3 -0
- package/Runtime/Core/Extensions/IListExtensions.cs +48 -0
- package/Runtime/Core/Extensions/IListExtensions.cs.meta +3 -0
- package/Runtime/Core/MessageBus/IMessageBus.cs +5 -3
- package/Runtime/Core/MessageBus/MessageBus.cs +28 -0
- package/Runtime/Core/MessageHandler.cs +200 -40
- package/Runtime/Core/MessageRegistrationToken.cs +645 -57
- package/Runtime/Core/Messages/ReflexiveMessage.cs +20 -1
- package/Runtime/Unity/MessagingComponent.cs +1 -1
- package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators.csproj +10 -13
- package/Tests/Runtime/Core/NominalTests.cs +2 -8
- package/Tests/Runtime/WallstopStudios.DxMessaging.Tests.Runtime.csproj +7 -1
- package/package.json +2 -1
|
@@ -0,0 +1,470 @@
|
|
|
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
|
+
|
|
31
|
+
private void OnEnable()
|
|
32
|
+
{
|
|
33
|
+
_listenerFoldouts.Clear();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
public override void OnInspectorGUI()
|
|
37
|
+
{
|
|
38
|
+
base.OnInspectorGUI();
|
|
39
|
+
|
|
40
|
+
_matchingStyle ??= new GUIStyle(EditorStyles.label)
|
|
41
|
+
{
|
|
42
|
+
normal = { textColor = Color.green },
|
|
43
|
+
fontStyle = FontStyle.Bold,
|
|
44
|
+
};
|
|
45
|
+
_potentialMatchStyle ??= new GUIStyle(EditorStyles.label)
|
|
46
|
+
{
|
|
47
|
+
normal = { textColor = Color.yellow },
|
|
48
|
+
fontStyle = FontStyle.Bold,
|
|
49
|
+
};
|
|
50
|
+
_defaultStyle ??= new GUIStyle(EditorStyles.label);
|
|
51
|
+
|
|
52
|
+
MessagingComponent component = target as MessagingComponent;
|
|
53
|
+
if (component == null)
|
|
54
|
+
{
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (component._registeredListeners.Count == 0)
|
|
59
|
+
{
|
|
60
|
+
EditorGUILayout.LabelField("No listeners registered.");
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
EditorGUILayout.Space();
|
|
65
|
+
EditorGUILayout.LabelField("Global Diagnostics", EditorStyles.boldLabel);
|
|
66
|
+
|
|
67
|
+
using (new GUILayout.HorizontalScope())
|
|
68
|
+
{
|
|
69
|
+
if (
|
|
70
|
+
component._registeredListeners.Values.Any(token => !token.DiagnosticMode)
|
|
71
|
+
&& GUILayout.Button(
|
|
72
|
+
$"Enable Diagnostics for All ({component._registeredListeners.Count})"
|
|
73
|
+
)
|
|
74
|
+
)
|
|
75
|
+
{
|
|
76
|
+
foreach (
|
|
77
|
+
MessageRegistrationToken token in component._registeredListeners.Values
|
|
78
|
+
)
|
|
79
|
+
{
|
|
80
|
+
token.DiagnosticMode = true;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (
|
|
85
|
+
component._registeredListeners.Values.Any(token => token.DiagnosticMode)
|
|
86
|
+
&& GUILayout.Button(
|
|
87
|
+
$"Disable Diagnostics for All ({component._registeredListeners.Count})"
|
|
88
|
+
)
|
|
89
|
+
)
|
|
90
|
+
{
|
|
91
|
+
foreach (
|
|
92
|
+
MessageRegistrationToken token in component._registeredListeners.Values
|
|
93
|
+
)
|
|
94
|
+
{
|
|
95
|
+
token.DiagnosticMode = false;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (!MessageHandler.MessageBus.DiagnosticsMode)
|
|
101
|
+
{
|
|
102
|
+
if (GUILayout.Button("Enable Global Diagnostics"))
|
|
103
|
+
{
|
|
104
|
+
MessageHandler.MessageBus.DiagnosticsMode = true;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
else
|
|
108
|
+
{
|
|
109
|
+
if (GUILayout.Button("Disable Global Diagnostics"))
|
|
110
|
+
{
|
|
111
|
+
MessageHandler.MessageBus.DiagnosticsMode = false;
|
|
112
|
+
}
|
|
113
|
+
else
|
|
114
|
+
{
|
|
115
|
+
EditorGUILayout.Space();
|
|
116
|
+
EditorGUILayout.LabelField("Global Buffer", EditorStyles.boldLabel);
|
|
117
|
+
|
|
118
|
+
_globalBufferExpanded = EditorGUILayout.Foldout(
|
|
119
|
+
_globalBufferExpanded,
|
|
120
|
+
"Global Messages",
|
|
121
|
+
true
|
|
122
|
+
);
|
|
123
|
+
int totalGlobalMessages = MessageHandler.MessageBus._emissionBuffer.Count;
|
|
124
|
+
if (_globalBufferExpanded && totalGlobalMessages > 0)
|
|
125
|
+
{
|
|
126
|
+
int page = _globalBufferPaging;
|
|
127
|
+
int totalPages = (totalGlobalMessages + PageSize - 1) / PageSize;
|
|
128
|
+
page = Mathf.Clamp(page, 0, totalPages - 1);
|
|
129
|
+
EditorGUI.indentLevel++;
|
|
130
|
+
if (totalPages > 1)
|
|
131
|
+
{
|
|
132
|
+
using (new EditorGUILayout.HorizontalScope())
|
|
133
|
+
{
|
|
134
|
+
GUI.enabled = page > 0;
|
|
135
|
+
if (GUILayout.Button("<< Previous"))
|
|
136
|
+
{
|
|
137
|
+
_globalBufferPaging--;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
GUI.enabled = true;
|
|
141
|
+
|
|
142
|
+
GUILayout.FlexibleSpace();
|
|
143
|
+
EditorGUILayout.LabelField($"Page {page + 1} of {totalPages}");
|
|
144
|
+
GUILayout.FlexibleSpace();
|
|
145
|
+
|
|
146
|
+
GUI.enabled = page < totalPages - 1;
|
|
147
|
+
if (GUILayout.Button("Next >>"))
|
|
148
|
+
{
|
|
149
|
+
_globalBufferPaging++;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
GUI.enabled = true;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
MessageEmissionData[] pagedGlobalMessages = MessageHandler
|
|
157
|
+
.MessageBus._emissionBuffer.Reverse()
|
|
158
|
+
.Skip(page * PageSize)
|
|
159
|
+
.Take(PageSize)
|
|
160
|
+
.ToArray();
|
|
161
|
+
foreach (MessageEmissionData globalEmissionData in pagedGlobalMessages)
|
|
162
|
+
{
|
|
163
|
+
using (new EditorGUILayout.VerticalScope("box"))
|
|
164
|
+
{
|
|
165
|
+
GUIStyle style;
|
|
166
|
+
InstanceId? context = globalEmissionData.context;
|
|
167
|
+
if (context?.Object != null)
|
|
168
|
+
{
|
|
169
|
+
Object unityObject = context.Value.Object;
|
|
170
|
+
if (
|
|
171
|
+
(
|
|
172
|
+
typeof(ITargetedMessage).IsAssignableFrom(
|
|
173
|
+
globalEmissionData.message.MessageType
|
|
174
|
+
)
|
|
175
|
+
&& (
|
|
176
|
+
unityObject == component.gameObject
|
|
177
|
+
|| component
|
|
178
|
+
.GetComponents<MonoBehaviour>()
|
|
179
|
+
.Any(script => script == unityObject)
|
|
180
|
+
)
|
|
181
|
+
)
|
|
182
|
+
|| (
|
|
183
|
+
typeof(IBroadcastMessage).IsAssignableFrom(
|
|
184
|
+
globalEmissionData.message.MessageType
|
|
185
|
+
)
|
|
186
|
+
&& (
|
|
187
|
+
component._registeredListeners.Keys.Any(script =>
|
|
188
|
+
script.gameObject == unityObject
|
|
189
|
+
|| script
|
|
190
|
+
.GetComponents<MonoBehaviour>()
|
|
191
|
+
.Any(matchedScript =>
|
|
192
|
+
matchedScript == unityObject
|
|
193
|
+
)
|
|
194
|
+
)
|
|
195
|
+
)
|
|
196
|
+
)
|
|
197
|
+
)
|
|
198
|
+
{
|
|
199
|
+
style = component._registeredListeners.Values.Any(
|
|
200
|
+
listener =>
|
|
201
|
+
listener._emissionBuffer.Contains(
|
|
202
|
+
globalEmissionData
|
|
203
|
+
)
|
|
204
|
+
)
|
|
205
|
+
? _matchingStyle
|
|
206
|
+
: _potentialMatchStyle;
|
|
207
|
+
}
|
|
208
|
+
else
|
|
209
|
+
{
|
|
210
|
+
style = _defaultStyle;
|
|
211
|
+
}
|
|
212
|
+
EditorGUILayout.LabelField(
|
|
213
|
+
"Context",
|
|
214
|
+
$"{unityObject.name} - {unityObject.GetType().Name}",
|
|
215
|
+
style
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
else
|
|
219
|
+
{
|
|
220
|
+
style = component._registeredListeners.Values.Any(listener =>
|
|
221
|
+
listener._emissionBuffer.Contains(globalEmissionData)
|
|
222
|
+
)
|
|
223
|
+
? _matchingStyle
|
|
224
|
+
: _defaultStyle;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
GUIContent labelContent = new("Message Type");
|
|
228
|
+
GUIContent valueContent = new(
|
|
229
|
+
globalEmissionData.message.MessageType.Name,
|
|
230
|
+
globalEmissionData.stackTrace
|
|
231
|
+
);
|
|
232
|
+
|
|
233
|
+
EditorGUILayout.LabelField(labelContent, valueContent, style);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
List<MonoBehaviour> listeners = new(component._registeredListeners.Keys);
|
|
240
|
+
|
|
241
|
+
EditorGUILayout.Space();
|
|
242
|
+
EditorGUILayout.LabelField("Local Buffer", EditorStyles.boldLabel);
|
|
243
|
+
foreach (MonoBehaviour listener in listeners)
|
|
244
|
+
{
|
|
245
|
+
if (!component._registeredListeners[listener].DiagnosticMode)
|
|
246
|
+
{
|
|
247
|
+
EditorGUILayout.Space();
|
|
248
|
+
EditorGUILayout.HelpBox(
|
|
249
|
+
$"Diagnostics are disabled for {listener.GetType().Name}. Enable diagnostics to view diagnostics data.",
|
|
250
|
+
MessageType.Info
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
else
|
|
254
|
+
{
|
|
255
|
+
_listenerBufferFoldouts.TryAdd(listener, false);
|
|
256
|
+
_listenerBufferFoldouts[listener] = EditorGUILayout.Foldout(
|
|
257
|
+
_listenerBufferFoldouts[listener],
|
|
258
|
+
listener.GetType().Name,
|
|
259
|
+
true
|
|
260
|
+
);
|
|
261
|
+
|
|
262
|
+
int totalMessages = component
|
|
263
|
+
._registeredListeners[listener]
|
|
264
|
+
._emissionBuffer
|
|
265
|
+
.Count;
|
|
266
|
+
if (_listenerBufferFoldouts[listener] && totalMessages > 0)
|
|
267
|
+
{
|
|
268
|
+
int page = _listenerBufferPaging.GetValueOrDefault(listener, 0);
|
|
269
|
+
int totalPages = (totalMessages + PageSize - 1) / PageSize;
|
|
270
|
+
page = Mathf.Clamp(page, 0, totalPages - 1);
|
|
271
|
+
_listenerBufferPaging[listener] = page;
|
|
272
|
+
EditorGUI.indentLevel++;
|
|
273
|
+
if (totalPages > 1)
|
|
274
|
+
{
|
|
275
|
+
using (new EditorGUILayout.HorizontalScope())
|
|
276
|
+
{
|
|
277
|
+
GUI.enabled = page > 0;
|
|
278
|
+
if (GUILayout.Button("<< Previous"))
|
|
279
|
+
{
|
|
280
|
+
_listenerBufferPaging[listener]--;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
GUI.enabled = true;
|
|
284
|
+
|
|
285
|
+
GUILayout.FlexibleSpace();
|
|
286
|
+
EditorGUILayout.LabelField($"Page {page + 1} of {totalPages}");
|
|
287
|
+
GUILayout.FlexibleSpace();
|
|
288
|
+
|
|
289
|
+
GUI.enabled = page < totalPages - 1;
|
|
290
|
+
if (GUILayout.Button("Next >>"))
|
|
291
|
+
{
|
|
292
|
+
_listenerBufferPaging[listener]++;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
GUI.enabled = true;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
MessageEmissionData[] pagedLocalMessages = component
|
|
300
|
+
._registeredListeners[listener]
|
|
301
|
+
._emissionBuffer.Reverse()
|
|
302
|
+
.Skip(page * PageSize)
|
|
303
|
+
.Take(PageSize)
|
|
304
|
+
.ToArray();
|
|
305
|
+
foreach (MessageEmissionData globalEmissionData in pagedLocalMessages)
|
|
306
|
+
{
|
|
307
|
+
using (new EditorGUILayout.VerticalScope("box"))
|
|
308
|
+
{
|
|
309
|
+
InstanceId? context = globalEmissionData.context;
|
|
310
|
+
if (context?.Object != null)
|
|
311
|
+
{
|
|
312
|
+
Object unityObject = context.Value.Object;
|
|
313
|
+
EditorGUILayout.LabelField(
|
|
314
|
+
"Context",
|
|
315
|
+
$"{unityObject.name} - {unityObject.GetType().Name}"
|
|
316
|
+
);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
GUIContent labelContent = new("Message Type");
|
|
320
|
+
GUIContent valueContent = new(
|
|
321
|
+
globalEmissionData.message.MessageType.Name,
|
|
322
|
+
globalEmissionData.stackTrace
|
|
323
|
+
);
|
|
324
|
+
|
|
325
|
+
EditorGUILayout.LabelField(labelContent, valueContent);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
EditorGUILayout.Space();
|
|
333
|
+
EditorGUILayout.LabelField("Listeners", EditorStyles.boldLabel);
|
|
334
|
+
|
|
335
|
+
foreach (MonoBehaviour listener in listeners)
|
|
336
|
+
{
|
|
337
|
+
if (listener == null)
|
|
338
|
+
{
|
|
339
|
+
continue;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
if (
|
|
343
|
+
!component._registeredListeners.TryGetValue(
|
|
344
|
+
listener,
|
|
345
|
+
out MessageRegistrationToken token
|
|
346
|
+
)
|
|
347
|
+
)
|
|
348
|
+
{
|
|
349
|
+
continue;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
_listenerFoldouts.TryAdd(listener, false);
|
|
353
|
+
_listenerFoldouts[listener] = EditorGUILayout.Foldout(
|
|
354
|
+
_listenerFoldouts[listener],
|
|
355
|
+
listener.GetType().Name,
|
|
356
|
+
true
|
|
357
|
+
);
|
|
358
|
+
if (_listenerFoldouts[listener])
|
|
359
|
+
{
|
|
360
|
+
EditorGUI.indentLevel++;
|
|
361
|
+
EditorGUILayout.ObjectField("Listener", listener, typeof(MonoBehaviour), true);
|
|
362
|
+
token.DiagnosticMode = EditorGUILayout.Toggle(
|
|
363
|
+
"Enable Diagnostics",
|
|
364
|
+
token.DiagnosticMode
|
|
365
|
+
);
|
|
366
|
+
if (token.DiagnosticMode)
|
|
367
|
+
{
|
|
368
|
+
if (token._metadata.Count == 0)
|
|
369
|
+
{
|
|
370
|
+
EditorGUILayout.LabelField("No messages registered for this listener.");
|
|
371
|
+
}
|
|
372
|
+
else
|
|
373
|
+
{
|
|
374
|
+
DrawPaginatedRegistrations(listener, token);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
else
|
|
378
|
+
{
|
|
379
|
+
EditorGUILayout.HelpBox(
|
|
380
|
+
"Enable diagnostics to view registration details.",
|
|
381
|
+
MessageType.Info
|
|
382
|
+
);
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
EditorGUI.indentLevel--;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
private void DrawPaginatedRegistrations(
|
|
391
|
+
MonoBehaviour listener,
|
|
392
|
+
MessageRegistrationToken token
|
|
393
|
+
)
|
|
394
|
+
{
|
|
395
|
+
_listenerRegistrationPaging.TryAdd(listener, 0);
|
|
396
|
+
int page = _listenerRegistrationPaging[listener];
|
|
397
|
+
int totalRegistrations = token._metadata.Count;
|
|
398
|
+
int totalPages = (totalRegistrations + PageSize - 1) / PageSize;
|
|
399
|
+
page = Mathf.Clamp(page, 0, totalPages - 1);
|
|
400
|
+
|
|
401
|
+
EditorGUILayout.LabelField("Registrations", EditorStyles.boldLabel);
|
|
402
|
+
EditorGUI.indentLevel++;
|
|
403
|
+
|
|
404
|
+
if (totalPages > 1)
|
|
405
|
+
{
|
|
406
|
+
using (new EditorGUILayout.HorizontalScope())
|
|
407
|
+
{
|
|
408
|
+
GUI.enabled = page > 0;
|
|
409
|
+
if (GUILayout.Button("<< Previous"))
|
|
410
|
+
{
|
|
411
|
+
_listenerRegistrationPaging[listener]--;
|
|
412
|
+
}
|
|
413
|
+
GUI.enabled = true;
|
|
414
|
+
|
|
415
|
+
GUILayout.FlexibleSpace();
|
|
416
|
+
EditorGUILayout.LabelField($"Page {page + 1} of {totalPages}");
|
|
417
|
+
GUILayout.FlexibleSpace();
|
|
418
|
+
|
|
419
|
+
GUI.enabled = page < totalPages - 1;
|
|
420
|
+
if (GUILayout.Button("Next >>"))
|
|
421
|
+
{
|
|
422
|
+
_listenerRegistrationPaging[listener]++;
|
|
423
|
+
}
|
|
424
|
+
GUI.enabled = true;
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
KeyValuePair<
|
|
429
|
+
MessageRegistrationHandle,
|
|
430
|
+
MessageRegistrationMetadata
|
|
431
|
+
>[] pagedRegistrations = token
|
|
432
|
+
._metadata.OrderBy(kvp => kvp.Key)
|
|
433
|
+
.Skip(page * PageSize)
|
|
434
|
+
.Take(PageSize)
|
|
435
|
+
.ToArray();
|
|
436
|
+
|
|
437
|
+
foreach (
|
|
438
|
+
(
|
|
439
|
+
MessageRegistrationHandle handle,
|
|
440
|
+
MessageRegistrationMetadata metadata
|
|
441
|
+
) in pagedRegistrations
|
|
442
|
+
)
|
|
443
|
+
{
|
|
444
|
+
int callCount = token._callCounts.GetValueOrDefault(handle, 0);
|
|
445
|
+
|
|
446
|
+
string messageName = metadata.type?.Name ?? string.Empty;
|
|
447
|
+
EditorGUILayout.LabelField(messageName, EditorStyles.boldLabel);
|
|
448
|
+
|
|
449
|
+
EditorGUI.indentLevel++;
|
|
450
|
+
|
|
451
|
+
EditorGUILayout.LabelField("Type", metadata.registrationType.ToString());
|
|
452
|
+
EditorGUILayout.LabelField("Priority", metadata.priority.ToString());
|
|
453
|
+
EditorGUILayout.LabelField("Call Count", callCount.ToString());
|
|
454
|
+
if (metadata.context?.Object != null)
|
|
455
|
+
{
|
|
456
|
+
Object unityObject = metadata.context.Value.Object;
|
|
457
|
+
EditorGUILayout.LabelField(
|
|
458
|
+
"Context",
|
|
459
|
+
$"{unityObject.name} - {unityObject.GetType().Name}"
|
|
460
|
+
);
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
EditorGUI.indentLevel--;
|
|
464
|
+
EditorGUILayout.Space();
|
|
465
|
+
}
|
|
466
|
+
EditorGUI.indentLevel--;
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
#endif
|
|
470
|
+
}
|
|
@@ -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,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,55 @@
|
|
|
1
|
+
namespace DxMessaging.Editor.Settings
|
|
2
|
+
{
|
|
3
|
+
#if UNITY_EDITOR
|
|
4
|
+
using System.Collections.Generic;
|
|
5
|
+
using UnityEditor;
|
|
6
|
+
using UnityEngine;
|
|
7
|
+
|
|
8
|
+
public sealed class DxMessagingSettingsProvider : SettingsProvider
|
|
9
|
+
{
|
|
10
|
+
private SerializedObject _messagingSettings;
|
|
11
|
+
|
|
12
|
+
private DxMessagingSettingsProvider(
|
|
13
|
+
string path,
|
|
14
|
+
SettingsScope scope = SettingsScope.Project
|
|
15
|
+
)
|
|
16
|
+
: base(path, scope) { }
|
|
17
|
+
|
|
18
|
+
public override void OnActivate(
|
|
19
|
+
string searchContext,
|
|
20
|
+
UnityEngine.UIElements.VisualElement rootElement
|
|
21
|
+
)
|
|
22
|
+
{
|
|
23
|
+
_messagingSettings = DxMessagingSettings.GetSerializedSettings();
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
public override void OnGUI(string searchContext)
|
|
27
|
+
{
|
|
28
|
+
EditorGUILayout.PropertyField(
|
|
29
|
+
_messagingSettings.FindProperty(
|
|
30
|
+
nameof(DxMessagingSettings._enableDiagnosticsInEditor)
|
|
31
|
+
),
|
|
32
|
+
new GUIContent("Global Diagnostics Mode")
|
|
33
|
+
);
|
|
34
|
+
EditorGUILayout.PropertyField(
|
|
35
|
+
_messagingSettings.FindProperty(nameof(DxMessagingSettings._messageBufferSize)),
|
|
36
|
+
new GUIContent("Message Buffer Size")
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
_messagingSettings.ApplyModifiedProperties();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
[SettingsProvider]
|
|
43
|
+
public static SettingsProvider CreateDxMessagingSettingsProvider()
|
|
44
|
+
{
|
|
45
|
+
DxMessagingSettingsProvider provider = new("Project/DxMessaging")
|
|
46
|
+
{
|
|
47
|
+
keywords = new HashSet<string>(new[] { "DxMessaging", "Diagnostics" }),
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
return provider;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
#endif
|
|
55
|
+
}
|
package/README.md
CHANGED
|
@@ -37,6 +37,8 @@ In addition to providing a richer feature set, DxMessaging is *faster* than Unit
|
|
|
37
37
|
|
|
38
38
|
For UntargetedMessages, DxMessaging is significantly faster (roughly 2x) than Unity.
|
|
39
39
|
|
|
40
|
+
## Windows
|
|
41
|
+
|
|
40
42
|
| Message Tech | Operations / Second | Allocations? |
|
|
41
43
|
| ------------ | ------------------- | ------------ |
|
|
42
44
|
| Unity | 2,649,000 | Yes |
|
|
@@ -49,6 +51,20 @@ For UntargetedMessages, DxMessaging is significantly faster (roughly 2x) than Un
|
|
|
49
51
|
| Reflexive (Two Arguments) | 1,000,400 | No |
|
|
50
52
|
| Reflexive (Three Arguments) | 993,800 | No |
|
|
51
53
|
|
|
54
|
+
## Linux
|
|
55
|
+
|
|
56
|
+
Message Tech | Operations / Second | Allocations? |
|
|
57
|
+
| ------------ | ------------------- | ------------ |
|
|
58
|
+
| Unity | 1,538,000 | Yes |
|
|
59
|
+
| DxMessaging (GameObject) - Normal | 5,653,200 | No |
|
|
60
|
+
| DxMessaging (Component) - Normal | 4,998,800 | No |
|
|
61
|
+
| DxMessaging (GameObject) - No-Copy | 6,388,800 | No |
|
|
62
|
+
| DxMessaging (Component) - No-Copy | 6,332,800 | No |
|
|
63
|
+
| DxMessaging (Untargeted) - No-Copy | 9,805,200 | No |
|
|
64
|
+
| Reflexive (One Argument) | 1,692,600 | No |
|
|
65
|
+
| Reflexive (Two Arguments) | 1,348,000 | No |
|
|
66
|
+
| Reflexive (Three Arguments) | 1,368,000 | No |
|
|
67
|
+
|
|
52
68
|
# Functionality
|
|
53
69
|
While not as fast, DxMessaging offers *additional functionality* as compared to Unity's messaging solution.
|
|
54
70
|
| Feature | Unity | DxMessaging |
|