com.wallstop-studios.dxmessaging 2.0.0-rc25 → 2.0.0-rc26.1
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/.config/dotnet-tools.json +2 -2
- package/.pre-commit-config.yaml +1 -1
- package/Editor/SetupCscRsp.cs +7 -8
- package/README.md +9 -9
- package/Runtime/Core/Extensions/MessageExtensions.cs +66 -0
- package/Runtime/Core/Helper/MessageCache.cs +56 -11
- package/Runtime/Core/Helper/MessageHelperIndexer.cs +5 -0
- package/Runtime/Core/MessageBus/MessageBus.cs +75 -62
- package/Runtime/Core/MessageHandler.cs +0 -8
- package/Runtime/{Unity → Core}/Messages/GlobalStringMessage.cs +1 -2
- package/Runtime/Core/Messages/{DxReflexiveMessage.cs → ReflexiveMessage.cs} +4 -3
- package/Runtime/{Unity → Core}/Messages/StringMessage.cs +1 -2
- package/Runtime/Unity/MessageAwareComponent.cs +1 -1
- package/Tests/Runtime/Benchmarks/PerformanceTests.cs +4 -95
- package/Tests/Runtime/Core/GenericMessageTests.cs +47 -0
- package/Tests/Runtime/Core/GenericMessageTests.cs.meta +3 -0
- package/Tests/Runtime/Core/MessagingTestBase.cs +0 -1
- package/package.json +2 -1
- package/Runtime/Core/Helper/DxMessagingRuntime.cs +0 -201
- package/Runtime/Core/Helper/DxMessagingRuntime.cs.meta +0 -3
- package/Runtime/Unity/Messages.meta +0 -3
- /package/Runtime/{Unity → Core}/Messages/GlobalStringMessage.cs.meta +0 -0
- /package/Runtime/Core/Messages/{DxReflexiveMessage.cs.meta → ReflexiveMessage.cs.meta} +0 -0
- /package/Runtime/{Unity → Core}/Messages/StringMessage.cs.meta +0 -0
package/.pre-commit-config.yaml
CHANGED
|
@@ -15,7 +15,7 @@ repos:
|
|
|
15
15
|
description: Install the .NET tools listed at .config/dotnet-tools.json.
|
|
16
16
|
- id: csharpier
|
|
17
17
|
name: Run CSharpier on C# files
|
|
18
|
-
entry: dotnet tool run
|
|
18
|
+
entry: dotnet tool run Csharpier format
|
|
19
19
|
language: system
|
|
20
20
|
types:
|
|
21
21
|
- c#
|
package/Editor/SetupCscRsp.cs
CHANGED
|
@@ -62,12 +62,7 @@ namespace DxMessaging.Editor
|
|
|
62
62
|
continue;
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
-
if (
|
|
66
|
-
!dllPath.Contains(
|
|
67
|
-
"Assets/Plugins/WallstopStudios.DxMessaging",
|
|
68
|
-
StringComparison.OrdinalIgnoreCase
|
|
69
|
-
)
|
|
70
|
-
)
|
|
65
|
+
if (!dllPath.Contains("Assets/Plugins", StringComparison.OrdinalIgnoreCase))
|
|
71
66
|
{
|
|
72
67
|
string dllName = Path.GetFileName(dllPath);
|
|
73
68
|
DllNames.Add(dllName);
|
|
@@ -95,10 +90,14 @@ namespace DxMessaging.Editor
|
|
|
95
90
|
}
|
|
96
91
|
|
|
97
92
|
const string pluginsDirectory =
|
|
98
|
-
"Assets/Plugins/WallstopStudios.DxMessaging/";
|
|
93
|
+
"Assets/Plugins/Editor/WallstopStudios.DxMessaging/";
|
|
99
94
|
string outputAsset = $"{pluginsDirectory}{requiredDllName}";
|
|
100
95
|
string sourceAsset = $"{relativeDirectory}{requiredDllName}";
|
|
101
|
-
Directory.
|
|
96
|
+
if (!Directory.Exists(pluginsDirectory))
|
|
97
|
+
{
|
|
98
|
+
Directory.CreateDirectory(pluginsDirectory);
|
|
99
|
+
AssetDatabase.Refresh();
|
|
100
|
+
}
|
|
102
101
|
if (!File.Exists(outputAsset))
|
|
103
102
|
{
|
|
104
103
|
File.Copy(sourceAsset, outputAsset);
|
package/README.md
CHANGED
|
@@ -39,15 +39,15 @@ For UntargetedMessages, DxMessaging is significantly faster (roughly 2x) than Un
|
|
|
39
39
|
|
|
40
40
|
| Message Tech | Operations / Second | Allocations? |
|
|
41
41
|
| ------------ | ------------------- | ------------ |
|
|
42
|
-
| Unity | 2,
|
|
43
|
-
| DxMessaging (GameObject) - Normal | 2,
|
|
44
|
-
| DxMessaging (Component) - Normal | 2,
|
|
45
|
-
| DxMessaging (GameObject) - No-Copy | 2,
|
|
46
|
-
| DxMessaging (Component) - No-Copy | 2,
|
|
47
|
-
| DxMessaging (Untargeted) - No-Copy | 4,
|
|
48
|
-
| Reflexive (One Argument) | 2,
|
|
49
|
-
| Reflexive (Two Arguments) | 1,
|
|
50
|
-
| Reflexive (Three Arguments) |
|
|
42
|
+
| Unity | 2,649,000 | Yes |
|
|
43
|
+
| DxMessaging (GameObject) - Normal | 2,672,800 | No |
|
|
44
|
+
| DxMessaging (Component) - Normal | 2,665,600 | No |
|
|
45
|
+
| DxMessaging (GameObject) - No-Copy | 2,778,800 | No |
|
|
46
|
+
| DxMessaging (Component) - No-Copy | 2,783,800 | No |
|
|
47
|
+
| DxMessaging (Untargeted) - No-Copy | 4,205,600 | No |
|
|
48
|
+
| Reflexive (One Argument) | 2,394,800 | No |
|
|
49
|
+
| Reflexive (Two Arguments) | 1,000,400 | No |
|
|
50
|
+
| Reflexive (Three Arguments) | 993,800 | No |
|
|
51
51
|
|
|
52
52
|
# Functionality
|
|
53
53
|
While not as fast, DxMessaging offers *additional functionality* as compared to Unity's messaging solution.
|
|
@@ -174,6 +174,24 @@
|
|
|
174
174
|
messageBus.UntargetedBroadcast(ref message);
|
|
175
175
|
}
|
|
176
176
|
|
|
177
|
+
/// <summary>
|
|
178
|
+
/// Emits an UntargetedMessage of the given type.
|
|
179
|
+
/// </summary>
|
|
180
|
+
/// <param name="message">UntargetedMessage to emit.</param>
|
|
181
|
+
/// <param name="messageBus">MessageBus to emit to. If null, uses the GlobalMessageBus.</param>
|
|
182
|
+
public static void Emit<TMessage>(this TMessage message, IMessageBus messageBus = null)
|
|
183
|
+
where TMessage : class, IUntargetedMessage
|
|
184
|
+
{
|
|
185
|
+
messageBus ??= MessageHandler.MessageBus;
|
|
186
|
+
if (typeof(TMessage) == typeof(IUntargetedMessage))
|
|
187
|
+
{
|
|
188
|
+
messageBus.UntypedUntargetedBroadcast(message);
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
messageBus.UntargetedBroadcast(ref message);
|
|
193
|
+
}
|
|
194
|
+
|
|
177
195
|
/// <summary>
|
|
178
196
|
/// Emits an UntargetedMessage of the given type.
|
|
179
197
|
/// </summary>
|
|
@@ -195,6 +213,24 @@
|
|
|
195
213
|
messageBus.UntargetedBroadcast(ref message);
|
|
196
214
|
}
|
|
197
215
|
|
|
216
|
+
/// <summary>
|
|
217
|
+
/// Emits an UntargetedMessage of the given type.
|
|
218
|
+
/// </summary>
|
|
219
|
+
/// <param name="message">UntargetedMessage to emit.</param>
|
|
220
|
+
/// <param name="messageBus">MessageBus to emit to. If null, uses the GlobalMessageBus.</param>
|
|
221
|
+
public static void Emit<TMessage>(this ref TMessage message, IMessageBus messageBus = null)
|
|
222
|
+
where TMessage : struct, IUntargetedMessage
|
|
223
|
+
{
|
|
224
|
+
messageBus ??= MessageHandler.MessageBus;
|
|
225
|
+
if (typeof(TMessage) == typeof(IUntargetedMessage))
|
|
226
|
+
{
|
|
227
|
+
messageBus.UntypedUntargetedBroadcast(message);
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
messageBus.UntargetedBroadcast(ref message);
|
|
232
|
+
}
|
|
233
|
+
|
|
198
234
|
#if UNITY_2017_1_OR_NEWER
|
|
199
235
|
/// <summary>
|
|
200
236
|
/// Emits a BroadcastMessage of the given type.
|
|
@@ -338,5 +374,35 @@
|
|
|
338
374
|
|
|
339
375
|
messageBus.SourcedBroadcast(ref source, ref message);
|
|
340
376
|
}
|
|
377
|
+
|
|
378
|
+
/// <summary>
|
|
379
|
+
/// Emits a StringMessage at the target containing the provided string.
|
|
380
|
+
/// </summary>
|
|
381
|
+
/// <param name="message">Message to send to the target.</param>
|
|
382
|
+
/// <param name="target">Target to send the message to.</param>
|
|
383
|
+
/// <param name="messageBus">MessageBus to emit to. If null, uses the GlobalMessageBus.</param>
|
|
384
|
+
public static void Emit(
|
|
385
|
+
this string message,
|
|
386
|
+
InstanceId target,
|
|
387
|
+
IMessageBus messageBus = null
|
|
388
|
+
)
|
|
389
|
+
{
|
|
390
|
+
StringMessage stringMessage = new(message);
|
|
391
|
+
(messageBus ?? MessageHandler.MessageBus).TargetedBroadcast(
|
|
392
|
+
ref target,
|
|
393
|
+
ref stringMessage
|
|
394
|
+
);
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
/// <summary>
|
|
398
|
+
/// Emits a GlobalStringMessage containing the provided string.
|
|
399
|
+
/// </summary>
|
|
400
|
+
/// <param name="message">Message to send globally.</param>
|
|
401
|
+
/// <param name="messageBus">MessageBus to emit to. If null, uses the GlobalMessageBus.</param>
|
|
402
|
+
public static void Emit(this string message, IMessageBus messageBus = null)
|
|
403
|
+
{
|
|
404
|
+
GlobalStringMessage stringMessage = new(message);
|
|
405
|
+
(messageBus ?? MessageHandler.MessageBus).UntargetedBroadcast(ref stringMessage);
|
|
406
|
+
}
|
|
341
407
|
}
|
|
342
408
|
}
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
|
|
23
23
|
public bool MoveNext()
|
|
24
24
|
{
|
|
25
|
-
while (++_index < _cache._values.
|
|
25
|
+
while (++_index < _cache._values.Count)
|
|
26
26
|
{
|
|
27
27
|
_current = _cache._values[_index];
|
|
28
28
|
if (_current != null)
|
|
@@ -48,20 +48,40 @@
|
|
|
48
48
|
public void Dispose() { }
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
private readonly TValue
|
|
51
|
+
private readonly List<TValue> _values = new();
|
|
52
52
|
|
|
53
53
|
public TValue GetOrAdd<TMessage>()
|
|
54
54
|
where TMessage : IMessage
|
|
55
55
|
{
|
|
56
|
+
TValue value;
|
|
56
57
|
int index = MessageHelperIndexer<TMessage>.SequentialId;
|
|
57
|
-
|
|
58
|
-
if (value != null)
|
|
58
|
+
if (0 <= index)
|
|
59
59
|
{
|
|
60
|
-
|
|
60
|
+
while (_values.Count <= index)
|
|
61
|
+
{
|
|
62
|
+
_values.Add(null);
|
|
63
|
+
}
|
|
64
|
+
value = _values[index];
|
|
65
|
+
if (value != null)
|
|
66
|
+
{
|
|
67
|
+
return value;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
value = new TValue();
|
|
71
|
+
_values[index] = value;
|
|
72
|
+
}
|
|
73
|
+
else
|
|
74
|
+
{
|
|
75
|
+
index = MessageHelperIndexer.TotalMessages++;
|
|
76
|
+
MessageHelperIndexer<TMessage>.SequentialId = index;
|
|
77
|
+
while (_values.Count < index)
|
|
78
|
+
{
|
|
79
|
+
_values.Add(null);
|
|
80
|
+
}
|
|
81
|
+
value = new TValue();
|
|
82
|
+
_values.Add(value);
|
|
61
83
|
}
|
|
62
84
|
|
|
63
|
-
value = new TValue();
|
|
64
|
-
_values[index] = value;
|
|
65
85
|
return value;
|
|
66
86
|
}
|
|
67
87
|
|
|
@@ -69,22 +89,47 @@
|
|
|
69
89
|
where TMessage : IMessage
|
|
70
90
|
{
|
|
71
91
|
int index = MessageHelperIndexer<TMessage>.SequentialId;
|
|
72
|
-
|
|
92
|
+
if (0 <= index)
|
|
93
|
+
{
|
|
94
|
+
while (_values.Count <= index)
|
|
95
|
+
{
|
|
96
|
+
_values.Add(null);
|
|
97
|
+
}
|
|
98
|
+
_values[index] = value;
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
index = MessageHelperIndexer.TotalMessages++;
|
|
103
|
+
MessageHelperIndexer<TMessage>.SequentialId = index;
|
|
104
|
+
while (_values.Count < index)
|
|
105
|
+
{
|
|
106
|
+
_values.Add(null);
|
|
107
|
+
}
|
|
108
|
+
_values.Add(value);
|
|
73
109
|
}
|
|
74
110
|
|
|
75
111
|
public bool TryGetValue<TMessage>(out TValue value)
|
|
76
112
|
where TMessage : IMessage
|
|
77
113
|
{
|
|
78
114
|
int index = MessageHelperIndexer<TMessage>.SequentialId;
|
|
79
|
-
|
|
80
|
-
|
|
115
|
+
if (0 <= index && index < _values.Count)
|
|
116
|
+
{
|
|
117
|
+
value = _values[index];
|
|
118
|
+
return value != null;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
value = default;
|
|
122
|
+
return false;
|
|
81
123
|
}
|
|
82
124
|
|
|
83
125
|
public void Remove<TMessage>()
|
|
84
126
|
where TMessage : IMessage
|
|
85
127
|
{
|
|
86
128
|
int index = MessageHelperIndexer<TMessage>.SequentialId;
|
|
87
|
-
|
|
129
|
+
if (0 <= index && index < _values.Count)
|
|
130
|
+
{
|
|
131
|
+
_values[index] = null;
|
|
132
|
+
}
|
|
88
133
|
}
|
|
89
134
|
|
|
90
135
|
public MessageCacheEnumerator GetEnumerator()
|
|
@@ -138,14 +138,6 @@
|
|
|
138
138
|
|
|
139
139
|
private readonly RegistrationLog _log = new();
|
|
140
140
|
|
|
141
|
-
static MessageBus()
|
|
142
|
-
{
|
|
143
|
-
if (!DxMessagingRuntime.Initialized)
|
|
144
|
-
{
|
|
145
|
-
DxMessagingRuntime.Initialize();
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
141
|
public Action RegisterUntargeted<T>(MessageHandler messageHandler, int priority = 0)
|
|
150
142
|
where T : IUntargetedMessage
|
|
151
143
|
{
|
|
@@ -724,13 +716,12 @@
|
|
|
724
716
|
Dictionary<InstanceId, HandlerCache<int, HandlerCache>> targetedHandlers;
|
|
725
717
|
HandlerCache<int, HandlerCache> sortedHandlers;
|
|
726
718
|
|
|
727
|
-
if (typeof(TMessage) == typeof(
|
|
719
|
+
if (typeof(TMessage) == typeof(ReflexiveMessage))
|
|
728
720
|
{
|
|
729
721
|
#if UNITY_2017_1_OR_NEWER
|
|
730
|
-
ref
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
>(ref typedMessage);
|
|
722
|
+
ref ReflexiveMessage reflexiveMessage = ref Unsafe.As<TMessage, ReflexiveMessage>(
|
|
723
|
+
ref typedMessage
|
|
724
|
+
);
|
|
734
725
|
|
|
735
726
|
GameObject go;
|
|
736
727
|
bool found;
|
|
@@ -761,12 +752,14 @@
|
|
|
761
752
|
{
|
|
762
753
|
_recipientCache.Clear();
|
|
763
754
|
bool sentInADirection = false;
|
|
764
|
-
|
|
755
|
+
ReflexiveSendMode sendMode = reflexiveMessage.sendMode;
|
|
756
|
+
if (sendMode.HasFlagNoAlloc(ReflexiveSendMode.Upwards))
|
|
765
757
|
{
|
|
766
758
|
sentInADirection = true;
|
|
767
759
|
if (
|
|
768
|
-
!
|
|
769
|
-
&& !
|
|
760
|
+
!sendMode.HasFlagNoAlloc(ReflexiveSendMode.Downwards)
|
|
761
|
+
&& !sendMode.HasFlagNoAlloc(ReflexiveSendMode.Flat)
|
|
762
|
+
&& !sendMode.HasFlagNoAlloc(ReflexiveSendMode.OnlyIncludeActive)
|
|
770
763
|
)
|
|
771
764
|
{
|
|
772
765
|
switch (reflexiveMessage.parameters.Length)
|
|
@@ -786,17 +779,17 @@
|
|
|
786
779
|
}
|
|
787
780
|
default:
|
|
788
781
|
{
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
true
|
|
792
|
-
);
|
|
793
|
-
foreach (Component component in parentComponents)
|
|
782
|
+
Transform current = go.transform;
|
|
783
|
+
do
|
|
794
784
|
{
|
|
795
|
-
|
|
785
|
+
_componentCache.Clear();
|
|
786
|
+
current.GetComponents(_componentCache);
|
|
787
|
+
foreach (MonoBehaviour script in _componentCache)
|
|
796
788
|
{
|
|
797
|
-
SendMessage(script, ref reflexiveMessage);
|
|
789
|
+
SendMessage(script, ref reflexiveMessage, false);
|
|
798
790
|
}
|
|
799
|
-
|
|
791
|
+
current = current.parent;
|
|
792
|
+
} while (current != null);
|
|
800
793
|
|
|
801
794
|
break;
|
|
802
795
|
}
|
|
@@ -804,24 +797,25 @@
|
|
|
804
797
|
}
|
|
805
798
|
else
|
|
806
799
|
{
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
);
|
|
810
|
-
foreach (Component component in parentComponents)
|
|
800
|
+
Transform current = go.transform;
|
|
801
|
+
do
|
|
811
802
|
{
|
|
812
|
-
|
|
803
|
+
_componentCache.Clear();
|
|
804
|
+
current.GetComponents(_componentCache);
|
|
805
|
+
foreach (MonoBehaviour script in _componentCache)
|
|
813
806
|
{
|
|
814
|
-
SendMessage(script, ref reflexiveMessage);
|
|
807
|
+
SendMessage(script, ref reflexiveMessage, true);
|
|
815
808
|
}
|
|
816
|
-
|
|
809
|
+
current = current.parent;
|
|
810
|
+
} while (current != null);
|
|
817
811
|
}
|
|
818
812
|
}
|
|
819
|
-
if (
|
|
813
|
+
if (sendMode.HasFlagNoAlloc(ReflexiveSendMode.Downwards))
|
|
820
814
|
{
|
|
821
|
-
sentInADirection = true;
|
|
822
815
|
if (
|
|
823
|
-
!
|
|
824
|
-
&& !
|
|
816
|
+
!sendMode.HasFlagNoAlloc(ReflexiveSendMode.Upwards)
|
|
817
|
+
&& !sendMode.HasFlagNoAlloc(ReflexiveSendMode.Flat)
|
|
818
|
+
&& !sendMode.HasFlagNoAlloc(ReflexiveSendMode.OnlyIncludeActive)
|
|
825
819
|
)
|
|
826
820
|
{
|
|
827
821
|
switch (reflexiveMessage.parameters.Length)
|
|
@@ -845,7 +839,7 @@
|
|
|
845
839
|
go.GetComponentsInChildren(true, _componentCache);
|
|
846
840
|
foreach (MonoBehaviour parentComponent in _componentCache)
|
|
847
841
|
{
|
|
848
|
-
SendMessage(parentComponent, ref reflexiveMessage);
|
|
842
|
+
SendMessage(parentComponent, ref reflexiveMessage, false);
|
|
849
843
|
}
|
|
850
844
|
|
|
851
845
|
break;
|
|
@@ -858,39 +852,49 @@
|
|
|
858
852
|
go.GetComponentsInChildren(_componentCache);
|
|
859
853
|
foreach (MonoBehaviour parentComponent in _componentCache)
|
|
860
854
|
{
|
|
861
|
-
SendMessage(parentComponent, ref reflexiveMessage);
|
|
855
|
+
SendMessage(parentComponent, ref reflexiveMessage, true);
|
|
862
856
|
}
|
|
863
857
|
}
|
|
864
858
|
}
|
|
865
|
-
else if (
|
|
866
|
-
!sentInADirection
|
|
867
|
-
&& reflexiveMessage.sendMode.HasFlagNoAlloc(ReflexiveSendMode.Flat)
|
|
868
|
-
)
|
|
859
|
+
else if (!sentInADirection && sendMode.HasFlagNoAlloc(ReflexiveSendMode.Flat))
|
|
869
860
|
{
|
|
870
|
-
|
|
861
|
+
if (!sendMode.HasFlagNoAlloc(ReflexiveSendMode.OnlyIncludeActive))
|
|
871
862
|
{
|
|
872
|
-
|
|
873
|
-
{
|
|
874
|
-
go.SendMessage(reflexiveMessage.method);
|
|
875
|
-
break;
|
|
876
|
-
}
|
|
877
|
-
case 1:
|
|
878
|
-
{
|
|
879
|
-
go.SendMessage(
|
|
880
|
-
reflexiveMessage.method,
|
|
881
|
-
reflexiveMessage.parameters[0]
|
|
882
|
-
);
|
|
883
|
-
break;
|
|
884
|
-
}
|
|
885
|
-
default:
|
|
863
|
+
switch (reflexiveMessage.parameters.Length)
|
|
886
864
|
{
|
|
887
|
-
|
|
888
|
-
go.GetComponents(_componentCache);
|
|
889
|
-
foreach (MonoBehaviour component in _componentCache)
|
|
865
|
+
case 0:
|
|
890
866
|
{
|
|
891
|
-
SendMessage(
|
|
867
|
+
go.SendMessage(reflexiveMessage.method);
|
|
868
|
+
break;
|
|
869
|
+
}
|
|
870
|
+
case 1:
|
|
871
|
+
{
|
|
872
|
+
go.SendMessage(
|
|
873
|
+
reflexiveMessage.method,
|
|
874
|
+
reflexiveMessage.parameters[0]
|
|
875
|
+
);
|
|
876
|
+
break;
|
|
877
|
+
}
|
|
878
|
+
default:
|
|
879
|
+
{
|
|
880
|
+
_componentCache.Clear();
|
|
881
|
+
go.GetComponents(_componentCache);
|
|
882
|
+
foreach (MonoBehaviour component in _componentCache)
|
|
883
|
+
{
|
|
884
|
+
SendMessage(component, ref reflexiveMessage, false);
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
break;
|
|
892
888
|
}
|
|
893
|
-
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
else
|
|
892
|
+
{
|
|
893
|
+
_componentCache.Clear();
|
|
894
|
+
go.GetComponents(_componentCache);
|
|
895
|
+
foreach (MonoBehaviour component in _componentCache)
|
|
896
|
+
{
|
|
897
|
+
SendMessage(component, ref reflexiveMessage, true);
|
|
894
898
|
}
|
|
895
899
|
}
|
|
896
900
|
}
|
|
@@ -3392,8 +3396,17 @@
|
|
|
3392
3396
|
}
|
|
3393
3397
|
#endif
|
|
3394
3398
|
|
|
3395
|
-
private void SendMessage(
|
|
3399
|
+
private void SendMessage(
|
|
3400
|
+
MonoBehaviour recipient,
|
|
3401
|
+
ref ReflexiveMessage message,
|
|
3402
|
+
bool onlyActive
|
|
3403
|
+
)
|
|
3396
3404
|
{
|
|
3405
|
+
if (onlyActive && !recipient.enabled)
|
|
3406
|
+
{
|
|
3407
|
+
return;
|
|
3408
|
+
}
|
|
3409
|
+
|
|
3397
3410
|
if (!_recipientCache.Add(recipient))
|
|
3398
3411
|
{
|
|
3399
3412
|
return;
|
|
@@ -48,14 +48,6 @@
|
|
|
48
48
|
/// </note>
|
|
49
49
|
private readonly List<MessageCache<object>> _handlersByTypeByMessageBus;
|
|
50
50
|
|
|
51
|
-
static MessageHandler()
|
|
52
|
-
{
|
|
53
|
-
if (!DxMessagingRuntime.Initialized)
|
|
54
|
-
{
|
|
55
|
-
DxMessagingRuntime.Initialize();
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
51
|
public MessageHandler(InstanceId owner)
|
|
60
52
|
{
|
|
61
53
|
this.owner = owner;
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
Flat = 1 << 0,
|
|
11
11
|
Downwards = 1 << 1,
|
|
12
12
|
Upwards = 1 << 2,
|
|
13
|
+
OnlyIncludeActive = 1 << 3,
|
|
13
14
|
}
|
|
14
15
|
|
|
15
16
|
public readonly struct MethodSignatureKey : IEquatable<MethodSignatureKey>
|
|
@@ -84,9 +85,9 @@
|
|
|
84
85
|
}
|
|
85
86
|
}
|
|
86
87
|
|
|
87
|
-
public readonly struct
|
|
88
|
+
public readonly struct ReflexiveMessage : ITargetedMessage<ReflexiveMessage>
|
|
88
89
|
{
|
|
89
|
-
public Type MessageType => typeof(
|
|
90
|
+
public Type MessageType => typeof(ReflexiveMessage);
|
|
90
91
|
|
|
91
92
|
public readonly string method;
|
|
92
93
|
public readonly ReflexiveSendMode sendMode;
|
|
@@ -96,7 +97,7 @@
|
|
|
96
97
|
|
|
97
98
|
public readonly MethodSignatureKey signatureKey;
|
|
98
99
|
|
|
99
|
-
public
|
|
100
|
+
public ReflexiveMessage(
|
|
100
101
|
string method,
|
|
101
102
|
ReflexiveSendMode sendMode,
|
|
102
103
|
params object[] parameters
|
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
using DxMessaging.Core;
|
|
7
7
|
using DxMessaging.Core.Extensions;
|
|
8
8
|
using DxMessaging.Core.Messages;
|
|
9
|
-
using global::Unity.PerformanceTesting;
|
|
10
9
|
using NUnit.Framework;
|
|
11
10
|
using Scripts.Components;
|
|
12
11
|
using Scripts.Messages;
|
|
@@ -31,7 +30,7 @@
|
|
|
31
30
|
Debug.Log("| ------------ | ------------------- | ------------ | ");
|
|
32
31
|
|
|
33
32
|
ComplexTargetedMessage message = new(Guid.NewGuid());
|
|
34
|
-
|
|
33
|
+
ReflexiveMessage reflexiveMessage = new(
|
|
35
34
|
nameof(SimpleMessageAwareComponent.HandleSlowComplexTargetedMessage),
|
|
36
35
|
ReflexiveSendMode.Flat,
|
|
37
36
|
message
|
|
@@ -55,96 +54,6 @@
|
|
|
55
54
|
RunTest(component => ReflexiveThreeArguments(timer, timeout, component.gameObject));
|
|
56
55
|
}
|
|
57
56
|
|
|
58
|
-
[Test]
|
|
59
|
-
[Performance]
|
|
60
|
-
public void BenchmarkBroadcast()
|
|
61
|
-
{
|
|
62
|
-
GameObject go = CreateGameObject();
|
|
63
|
-
MessageRegistrationToken token = GetToken(
|
|
64
|
-
go.GetComponent<EmptyMessageAwareComponent>()
|
|
65
|
-
);
|
|
66
|
-
// ReSharper disable once NotAccessedVariable
|
|
67
|
-
int count = 0;
|
|
68
|
-
token.RegisterGameObjectBroadcast<SimpleBroadcastMessage>(go, Handle);
|
|
69
|
-
|
|
70
|
-
SimpleBroadcastMessage message = new();
|
|
71
|
-
SampleGroup time = new("Time", SampleUnit.Nanosecond);
|
|
72
|
-
|
|
73
|
-
Measure
|
|
74
|
-
.Method(() => message.EmitGameObjectBroadcast(go))
|
|
75
|
-
.SampleGroup(time)
|
|
76
|
-
.WarmupCount(10)
|
|
77
|
-
.IterationsPerMeasurement(1)
|
|
78
|
-
.MeasurementCount(10_000)
|
|
79
|
-
.Run();
|
|
80
|
-
return;
|
|
81
|
-
|
|
82
|
-
void Handle(SimpleBroadcastMessage _)
|
|
83
|
-
{
|
|
84
|
-
++count;
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
[Test]
|
|
89
|
-
[Performance]
|
|
90
|
-
public void BenchmarkTargeted()
|
|
91
|
-
{
|
|
92
|
-
GameObject go = CreateGameObject();
|
|
93
|
-
MessageRegistrationToken token = GetToken(
|
|
94
|
-
go.GetComponent<EmptyMessageAwareComponent>()
|
|
95
|
-
);
|
|
96
|
-
// ReSharper disable once NotAccessedVariable
|
|
97
|
-
int count = 0;
|
|
98
|
-
token.RegisterGameObjectTargeted<SimpleTargetedMessage>(go, Handle);
|
|
99
|
-
|
|
100
|
-
SimpleTargetedMessage message = new();
|
|
101
|
-
SampleGroup time = new("Time", SampleUnit.Nanosecond);
|
|
102
|
-
|
|
103
|
-
Measure
|
|
104
|
-
.Method(() => message.EmitGameObjectTargeted(go))
|
|
105
|
-
.SampleGroup(time)
|
|
106
|
-
.WarmupCount(10)
|
|
107
|
-
.IterationsPerMeasurement(1)
|
|
108
|
-
.MeasurementCount(10_000)
|
|
109
|
-
.Run();
|
|
110
|
-
return;
|
|
111
|
-
|
|
112
|
-
void Handle(SimpleTargetedMessage _)
|
|
113
|
-
{
|
|
114
|
-
++count;
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
[Test]
|
|
119
|
-
[Performance]
|
|
120
|
-
public void BenchmarkUntargeted()
|
|
121
|
-
{
|
|
122
|
-
GameObject go = CreateGameObject();
|
|
123
|
-
MessageRegistrationToken token = GetToken(
|
|
124
|
-
go.GetComponent<EmptyMessageAwareComponent>()
|
|
125
|
-
);
|
|
126
|
-
// ReSharper disable once NotAccessedVariable
|
|
127
|
-
int count = 0;
|
|
128
|
-
token.RegisterUntargeted<SimpleUntargetedMessage>(Handle);
|
|
129
|
-
|
|
130
|
-
SimpleUntargetedMessage message = new();
|
|
131
|
-
SampleGroup time = new("Time", SampleUnit.Nanosecond);
|
|
132
|
-
|
|
133
|
-
Measure
|
|
134
|
-
.Method(() => message.EmitUntargeted())
|
|
135
|
-
.SampleGroup(time)
|
|
136
|
-
.WarmupCount(10)
|
|
137
|
-
.IterationsPerMeasurement(1)
|
|
138
|
-
.MeasurementCount(10_000)
|
|
139
|
-
.Run();
|
|
140
|
-
return;
|
|
141
|
-
|
|
142
|
-
void Handle(SimpleUntargetedMessage _)
|
|
143
|
-
{
|
|
144
|
-
++count;
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
|
|
148
57
|
private GameObject CreateGameObject()
|
|
149
58
|
{
|
|
150
59
|
GameObject target = new(
|
|
@@ -249,7 +158,7 @@
|
|
|
249
158
|
component = go.AddComponent<SimpleMessageAwareComponent>();
|
|
250
159
|
}
|
|
251
160
|
component.reflexiveThreeArgumentHandler = () => ++count;
|
|
252
|
-
|
|
161
|
+
ReflexiveMessage message = new(
|
|
253
162
|
nameof(SimpleMessageAwareComponent.HandleReflexiveMessageThreeArguments),
|
|
254
163
|
ReflexiveSendMode.Flat,
|
|
255
164
|
1,
|
|
@@ -290,7 +199,7 @@
|
|
|
290
199
|
component = go.AddComponent<SimpleMessageAwareComponent>();
|
|
291
200
|
}
|
|
292
201
|
component.reflexiveTwoArgumentHandler = () => ++count;
|
|
293
|
-
|
|
202
|
+
ReflexiveMessage message = new(
|
|
294
203
|
nameof(SimpleMessageAwareComponent.HandleReflexiveMessageTwoArguments),
|
|
295
204
|
ReflexiveSendMode.Flat,
|
|
296
205
|
1,
|
|
@@ -326,7 +235,7 @@
|
|
|
326
235
|
Stopwatch timer,
|
|
327
236
|
TimeSpan timeout,
|
|
328
237
|
GameObject go,
|
|
329
|
-
|
|
238
|
+
ReflexiveMessage message
|
|
330
239
|
)
|
|
331
240
|
{
|
|
332
241
|
int count = 0;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
namespace DxMessaging.Tests.Runtime.Core
|
|
2
|
+
{
|
|
3
|
+
using DxMessaging.Core;
|
|
4
|
+
using DxMessaging.Core.Extensions;
|
|
5
|
+
using NUnit.Framework;
|
|
6
|
+
using Scripts.Components;
|
|
7
|
+
using Scripts.Messages;
|
|
8
|
+
using UnityEngine;
|
|
9
|
+
|
|
10
|
+
public sealed class GenericMessageTests : MessagingTestBase
|
|
11
|
+
{
|
|
12
|
+
[Test]
|
|
13
|
+
public void MultipleGenericTypesWork()
|
|
14
|
+
{
|
|
15
|
+
GameObject go = new(
|
|
16
|
+
nameof(MultipleGenericTypesWork),
|
|
17
|
+
typeof(SimpleMessageAwareComponent)
|
|
18
|
+
);
|
|
19
|
+
_spawned.Add(go);
|
|
20
|
+
|
|
21
|
+
SimpleMessageAwareComponent messaging = go.GetComponent<SimpleMessageAwareComponent>();
|
|
22
|
+
MessageRegistrationToken token = GetToken(messaging);
|
|
23
|
+
|
|
24
|
+
int totalCount = 0;
|
|
25
|
+
token.RegisterUntargeted((ref GenericUntargetedMessage<int> _) => totalCount++);
|
|
26
|
+
token.RegisterUntargeted((ref GenericUntargetedMessage<float> _) => totalCount++);
|
|
27
|
+
token.RegisterUntargeted((ref GenericUntargetedMessage<string> _) => totalCount++);
|
|
28
|
+
token.RegisterUntargeted((ref GenericUntargetedMessage<Vector3> _) => totalCount++);
|
|
29
|
+
|
|
30
|
+
GenericUntargetedMessage<int> intMessage = new();
|
|
31
|
+
intMessage.EmitUntargeted();
|
|
32
|
+
Assert.AreEqual(1, totalCount);
|
|
33
|
+
GenericUntargetedMessage<float> floatMessage = new();
|
|
34
|
+
floatMessage.EmitUntargeted();
|
|
35
|
+
Assert.AreEqual(2, totalCount);
|
|
36
|
+
GenericUntargetedMessage<string> stringMessage = new();
|
|
37
|
+
stringMessage.EmitUntargeted();
|
|
38
|
+
Assert.AreEqual(3, totalCount);
|
|
39
|
+
GenericUntargetedMessage<Vector3> vector3Message = new();
|
|
40
|
+
vector3Message.EmitUntargeted();
|
|
41
|
+
Assert.AreEqual(4, totalCount);
|
|
42
|
+
GenericUntargetedMessage<Vector4> vector4Message = new();
|
|
43
|
+
vector4Message.EmitUntargeted();
|
|
44
|
+
Assert.AreEqual(4, totalCount);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "com.wallstop-studios.dxmessaging",
|
|
3
|
-
"version": "2.0.0-
|
|
3
|
+
"version": "2.0.0-rc26.1",
|
|
4
4
|
"displayName": "DxMessaging",
|
|
5
5
|
"description": "Synchronous Event Bus for Unity",
|
|
6
6
|
"unity": "2021.3",
|
|
@@ -32,3 +32,4 @@
|
|
|
32
32
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
|
+
|
|
@@ -1,201 +0,0 @@
|
|
|
1
|
-
namespace DxMessaging.Core.Helper
|
|
2
|
-
{
|
|
3
|
-
using System;
|
|
4
|
-
using System.Collections.Generic;
|
|
5
|
-
using System.Reflection;
|
|
6
|
-
using Core;
|
|
7
|
-
using Messages;
|
|
8
|
-
#if UNITY_2017_1_OR_NEWER
|
|
9
|
-
using UnityEngine;
|
|
10
|
-
#endif
|
|
11
|
-
public static class DxMessagingRuntime
|
|
12
|
-
{
|
|
13
|
-
public static int TotalMessageTypes { get; private set; }
|
|
14
|
-
|
|
15
|
-
public static bool Initialized
|
|
16
|
-
{
|
|
17
|
-
get
|
|
18
|
-
{
|
|
19
|
-
lock (InitializationLock)
|
|
20
|
-
{
|
|
21
|
-
return _isInitialized;
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
private static bool _isInitialized;
|
|
27
|
-
private static readonly object InitializationLock = new();
|
|
28
|
-
|
|
29
|
-
static DxMessagingRuntime()
|
|
30
|
-
{
|
|
31
|
-
Initialize();
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
#if UNITY_2017_1_OR_NEWER
|
|
35
|
-
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
|
|
36
|
-
#endif
|
|
37
|
-
public static void Initialize()
|
|
38
|
-
{
|
|
39
|
-
lock (InitializationLock)
|
|
40
|
-
{
|
|
41
|
-
if (_isInitialized)
|
|
42
|
-
{
|
|
43
|
-
return;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
Log(() => "DxMessagingRuntime Initializing...", isError: false);
|
|
47
|
-
|
|
48
|
-
HashSet<Type> uniqueTypes = new();
|
|
49
|
-
List<Type> messageTypes = new();
|
|
50
|
-
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
|
|
51
|
-
|
|
52
|
-
foreach (Assembly assembly in assemblies)
|
|
53
|
-
{
|
|
54
|
-
Type[] types;
|
|
55
|
-
try
|
|
56
|
-
{
|
|
57
|
-
types = assembly.GetTypes();
|
|
58
|
-
}
|
|
59
|
-
catch (ReflectionTypeLoadException ex)
|
|
60
|
-
{
|
|
61
|
-
types = ex.Types;
|
|
62
|
-
}
|
|
63
|
-
catch
|
|
64
|
-
{
|
|
65
|
-
continue;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
foreach (Type type in types)
|
|
69
|
-
{
|
|
70
|
-
try
|
|
71
|
-
{
|
|
72
|
-
if (type == null)
|
|
73
|
-
{
|
|
74
|
-
continue;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
if (!typeof(IMessage).IsAssignableFrom(type))
|
|
78
|
-
{
|
|
79
|
-
continue;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
if (type.IsGenericTypeDefinition)
|
|
83
|
-
{
|
|
84
|
-
continue;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
if (uniqueTypes.Add(type))
|
|
88
|
-
{
|
|
89
|
-
messageTypes.Add(type);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
catch (Exception e)
|
|
93
|
-
{
|
|
94
|
-
Log(
|
|
95
|
-
() =>
|
|
96
|
-
$"Error checking if {type?.FullName} is assignable from IMessage: {e}",
|
|
97
|
-
isError: true
|
|
98
|
-
);
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
if (uniqueTypes.Add(typeof(IMessage)))
|
|
104
|
-
{
|
|
105
|
-
messageTypes.Add(typeof(IMessage));
|
|
106
|
-
}
|
|
107
|
-
if (uniqueTypes.Add(typeof(ITargetedMessage)))
|
|
108
|
-
{
|
|
109
|
-
messageTypes.Add(typeof(ITargetedMessage));
|
|
110
|
-
}
|
|
111
|
-
if (uniqueTypes.Add(typeof(IBroadcastMessage)))
|
|
112
|
-
{
|
|
113
|
-
messageTypes.Add(typeof(IBroadcastMessage));
|
|
114
|
-
}
|
|
115
|
-
if (uniqueTypes.Add(typeof(IUntargetedMessage)))
|
|
116
|
-
{
|
|
117
|
-
messageTypes.Add(typeof(IUntargetedMessage));
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
messageTypes.Sort(
|
|
121
|
-
(a, b) =>
|
|
122
|
-
string.Compare(a.FullName, b.FullName, StringComparison.OrdinalIgnoreCase)
|
|
123
|
-
);
|
|
124
|
-
|
|
125
|
-
TotalMessageTypes = messageTypes.Count;
|
|
126
|
-
Type helperIndexerGenericDef = typeof(MessageHelperIndexer<>);
|
|
127
|
-
|
|
128
|
-
for (int i = 0; i < TotalMessageTypes; ++i)
|
|
129
|
-
{
|
|
130
|
-
Type messageType = messageTypes[i];
|
|
131
|
-
try
|
|
132
|
-
{
|
|
133
|
-
Type specificHelperType = helperIndexerGenericDef.MakeGenericType(
|
|
134
|
-
messageType
|
|
135
|
-
);
|
|
136
|
-
|
|
137
|
-
FieldInfo idField = specificHelperType.GetField(
|
|
138
|
-
"SequentialId",
|
|
139
|
-
BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic
|
|
140
|
-
);
|
|
141
|
-
if (idField != null)
|
|
142
|
-
{
|
|
143
|
-
idField.SetValue(null, i);
|
|
144
|
-
}
|
|
145
|
-
else
|
|
146
|
-
{
|
|
147
|
-
Log(
|
|
148
|
-
() =>
|
|
149
|
-
$"Error: Could not find field for SequentialId on MessageHelperIndexer<{messageType.FullName}>.",
|
|
150
|
-
isError: true
|
|
151
|
-
);
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
catch (Exception ex)
|
|
155
|
-
{
|
|
156
|
-
Log(
|
|
157
|
-
() => $"Error setting SequentialId for {messageType.FullName}: {ex}",
|
|
158
|
-
isError: true
|
|
159
|
-
);
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
_isInitialized = true;
|
|
164
|
-
Log(
|
|
165
|
-
() =>
|
|
166
|
-
$"DxMessagingRuntime Initialized. Found {TotalMessageTypes} message types.",
|
|
167
|
-
isError: false
|
|
168
|
-
);
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
private static void Log(Func<string> messageProducer, bool isError)
|
|
173
|
-
{
|
|
174
|
-
try
|
|
175
|
-
{
|
|
176
|
-
string message = messageProducer();
|
|
177
|
-
#if UNITY_2017_1_OR_NEWER
|
|
178
|
-
if (isError)
|
|
179
|
-
{
|
|
180
|
-
Debug.LogError(message);
|
|
181
|
-
}
|
|
182
|
-
else
|
|
183
|
-
{
|
|
184
|
-
Debug.Log(message);
|
|
185
|
-
}
|
|
186
|
-
#else
|
|
187
|
-
Console.WriteLine(message);
|
|
188
|
-
#endif
|
|
189
|
-
}
|
|
190
|
-
catch (Exception e)
|
|
191
|
-
{
|
|
192
|
-
string errorMessage = $"Error logging message: {e}";
|
|
193
|
-
#if UNITY_2017_1_OR_NEWER
|
|
194
|
-
Debug.LogError(errorMessage);
|
|
195
|
-
#else
|
|
196
|
-
Console.WriteLine(errorMessage);
|
|
197
|
-
#endif
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|