com.valectric.mooserunner 2.1.21 → 2.1.23
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/CHANGELOG.md +23 -23
- package/CLI~/mooserunnerCli.exe +0 -0
- package/CLI~/mooserunnerCliDaemon.exe +0 -0
- package/Editor/HotReloadIntegration/MooseRunner.HotReloadIntegration.dll +0 -0
- package/Editor/HotReloadIntegration/MooseRunner.HotReloadIntegration.dll.meta +32 -32
- package/Editor/MooseRunner.Editor.asmdef +15 -15
- package/Editor/MooseRunner.Editor.asmdef.meta +6 -6
- package/Editor/MooseRunner.Internal.Editor.dll +0 -0
- package/Editor/MooseRunner.Internal.Editor.dll.meta +32 -32
- package/Editor/MooseRunner.Worker.dll +0 -0
- package/Editor/MooseRunner.Worker.dll.meta +32 -32
- package/Editor/SessionRecorder/MooseRunner.SessionRecorder.dll +0 -0
- package/Editor/SessionRecorder/MooseRunner.SessionRecorder.dll.meta +32 -32
- package/Editor/_WrapperStub.cs.meta +10 -10
- package/LICENSE.md +28 -28
- package/Runtime/MooseRunner.Helpers.Runtime.dll +0 -0
- package/Runtime/MooseRunner.Helpers.Runtime.dll.meta +26 -26
- package/Runtime/MooseRunner.Internal.dll +0 -0
- package/Runtime/MooseRunner.Internal.dll.meta +26 -26
- package/Runtime/MooseRunner.Multiplaytest.Types.dll +0 -0
- package/Runtime/MooseRunner.Multiplaytest.Types.dll.meta +26 -26
- package/Runtime/MooseRunner.Runtime.asmdef +15 -15
- package/Runtime/MooseRunner.Runtime.asmdef.meta +6 -6
- package/Runtime/MooseRunner.SessionRecorder.Public.dll +0 -0
- package/Runtime/MooseRunner.SessionRecorder.Public.dll.meta +26 -26
- package/Runtime/MooseRunner.SessionRecorder.Runtime.dll +0 -0
- package/Runtime/MooseRunner.SessionRecorder.Runtime.dll.meta +26 -26
- package/Runtime/MooseRunner.dll +0 -0
- package/Runtime/MooseRunner.dll.meta +26 -26
- package/Runtime/_WrapperStub.cs.meta +10 -10
- package/Samples~/Demos/MooseRunner.Demo.CancellationTokens.Tests/BatchCancellationTests.cs +37 -37
- package/Samples~/Demos/MooseRunner.Demo.CancellationTokens.Tests/CancellationTokenTests.cs +186 -186
- package/Samples~/Demos/MooseRunner.Demo.CancellationTokens.Tests/SetupTeardownCancellationTests.cs +85 -85
- package/Samples~/Demos/MooseRunner.Demo.Flow.TestSupport/LogEntry.cs +51 -51
- package/Samples~/Demos/MooseRunner.Demo.Flow.TestSupport/LogFileParser.cs +69 -69
- package/Samples~/Demos/MooseRunner.Demo.OrderAttribute/MethodOrderAttributeTests.cs +62 -62
- package/Samples~/Demos/MooseRunner.Demo.RealUseCase/Enemy.cs +100 -100
- package/Samples~/Demos/MooseRunner.Demo.RealUseCase/FireComponent.cs +18 -18
- package/Samples~/Demos/MooseRunner.Demo.Support/MessageDisplayManager.cs +291 -291
- package/Samples~/Demos/MooseRunner.Demo.Support/MooseRunnerSampleVersionCheck.cs +57 -57
- package/Samples~/Demos/MooseRunner.Demo.Support/MooseRunnerSampleVersionCheck.cs.meta +1 -1
- package/Samples~/Demos/MooseRunner.Demo.Tests/ExplicitAttributeTests.cs +36 -36
- package/Samples~/Demos/MooseRunner.Demo.Tests/InstanceHandlingVerificationTest.cs +99 -99
- package/Third Party Notices.md +37 -37
- package/package.json +1 -1
|
@@ -1,291 +1,291 @@
|
|
|
1
|
-
using UnityEngine;
|
|
2
|
-
using UnityEngine.UI;
|
|
3
|
-
using System.Collections.Generic;
|
|
4
|
-
using System.Diagnostics;
|
|
5
|
-
using System.Reflection;
|
|
6
|
-
using static UnityEngine.EventSystems.EventTrigger;
|
|
7
|
-
using Debug = System.Diagnostics.Debug;
|
|
8
|
-
|
|
9
|
-
namespace MooseRunner.Internal.Tests
|
|
10
|
-
{
|
|
11
|
-
/// <summary>
|
|
12
|
-
/// Manages the display of messages in a persistent UI canvas.
|
|
13
|
-
/// Messages are displayed in a vertical list and are automatically removed after their lifetime expires.
|
|
14
|
-
/// </summary>
|
|
15
|
-
public class MessageDisplayManager : MonoBehaviour
|
|
16
|
-
{
|
|
17
|
-
/// <summary>
|
|
18
|
-
/// The singleton instance of the <see cref="MessageDisplayManager"/>.
|
|
19
|
-
/// </summary>
|
|
20
|
-
private static MessageDisplayManager _instance;
|
|
21
|
-
|
|
22
|
-
/// <summary>
|
|
23
|
-
/// Provides global access to the <see cref="MessageDisplayManager"/> instance.
|
|
24
|
-
/// Ensures that the manager is created and persists across scenes.
|
|
25
|
-
/// </summary>
|
|
26
|
-
public static MessageDisplayManager Instance
|
|
27
|
-
{
|
|
28
|
-
get
|
|
29
|
-
{
|
|
30
|
-
// If instance exists, return it
|
|
31
|
-
if (_instance != null) return _instance;
|
|
32
|
-
|
|
33
|
-
// 1. Find any existing instance in the scene
|
|
34
|
-
MessageDisplayManager[] instances = FindObjectsByType<MessageDisplayManager>(FindObjectsSortMode.None);
|
|
35
|
-
if (instances.Length > 0)
|
|
36
|
-
{
|
|
37
|
-
_instance = instances[0];
|
|
38
|
-
|
|
39
|
-
if (instances.Length > 1)
|
|
40
|
-
{
|
|
41
|
-
UnityEngine.Debug.LogWarning("Multiple TestRunnerHelper instances found! Using the first one.");
|
|
42
|
-
// Optionally, destroy duplicates here
|
|
43
|
-
for (int i = 1; i < instances.Length; i++)
|
|
44
|
-
{
|
|
45
|
-
Destroy(instances[i].gameObject);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
return _instance;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// 2. No instance found, instantiate the prefab
|
|
52
|
-
if (_instance == null)
|
|
53
|
-
{
|
|
54
|
-
GameObject obj = new GameObject("MessageDisplayManager");
|
|
55
|
-
_instance = obj.AddComponent<MessageDisplayManager>();
|
|
56
|
-
DontDestroyOnLoad(obj); // Ensure it persists across scenes
|
|
57
|
-
}
|
|
58
|
-
return _instance;
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/// <summary>
|
|
63
|
-
/// The canvas used to display the message UI.
|
|
64
|
-
/// </summary>
|
|
65
|
-
private Canvas _canvas;
|
|
66
|
-
|
|
67
|
-
/// <summary>
|
|
68
|
-
/// The content area within the canvas that holds all displayed messages.
|
|
69
|
-
/// </summary>
|
|
70
|
-
private RectTransform _contentArea;
|
|
71
|
-
|
|
72
|
-
/// <summary>
|
|
73
|
-
/// A dictionary that stores active messages, indexed by a unique key derived from the caller's context.
|
|
74
|
-
/// </summary>
|
|
75
|
-
private readonly Dictionary<string, MessageEntry> _messages = new Dictionary<string, MessageEntry>();
|
|
76
|
-
|
|
77
|
-
/// <summary>
|
|
78
|
-
/// The default duration (in seconds) for which a message remains visible.
|
|
79
|
-
/// </summary>
|
|
80
|
-
private const float MessageLifetime = 10f;
|
|
81
|
-
|
|
82
|
-
///<summary>
|
|
83
|
-
///Keeps track of last method
|
|
84
|
-
/// </summary>
|
|
85
|
-
private string _lastMethod;
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
/// <summary>
|
|
89
|
-
/// Represents a single message entry in the display manager.
|
|
90
|
-
/// </summary>
|
|
91
|
-
private class MessageEntry
|
|
92
|
-
{
|
|
93
|
-
/// <summary>
|
|
94
|
-
/// The text content of the message.
|
|
95
|
-
/// </summary>
|
|
96
|
-
public string DisplayText;
|
|
97
|
-
|
|
98
|
-
/// <summary>
|
|
99
|
-
/// The remaining lifetime of the message, in seconds.
|
|
100
|
-
/// </summary>
|
|
101
|
-
public float RemainingTime;
|
|
102
|
-
|
|
103
|
-
/// <summary>
|
|
104
|
-
/// The UI element used to display the message.
|
|
105
|
-
/// </summary>
|
|
106
|
-
public Text UIElement;
|
|
107
|
-
|
|
108
|
-
/// <summary>
|
|
109
|
-
/// Initializes a new instance of the <see cref="MessageEntry"/> class.
|
|
110
|
-
/// </summary>
|
|
111
|
-
/// <param name="text">The message text to display.</param>
|
|
112
|
-
/// <param name="duration">The duration the message should remain visible.</param>
|
|
113
|
-
/// <param name="uiElement">The UI text element associated with the message.</param>
|
|
114
|
-
public MessageEntry(string text, float duration, Text uiElement)
|
|
115
|
-
{
|
|
116
|
-
DisplayText = text;
|
|
117
|
-
RemainingTime = duration;
|
|
118
|
-
UIElement = uiElement;
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
/// <summary>
|
|
123
|
-
/// Ensures that the UI elements for displaying messages are created and properly configured.
|
|
124
|
-
/// </summary>
|
|
125
|
-
private void EnsureUIExists()
|
|
126
|
-
{
|
|
127
|
-
if (_canvas == null)
|
|
128
|
-
{
|
|
129
|
-
|
|
130
|
-
// Create Canvas
|
|
131
|
-
_canvas = gameObject.AddComponent<Canvas>();
|
|
132
|
-
_canvas.renderMode = RenderMode.ScreenSpaceOverlay;
|
|
133
|
-
DontDestroyOnLoad(gameObject);
|
|
134
|
-
|
|
135
|
-
// Add a Canvas Scaler
|
|
136
|
-
CanvasScaler scaler = gameObject.AddComponent<CanvasScaler>();
|
|
137
|
-
scaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
|
|
138
|
-
|
|
139
|
-
// Add a Scroll View for Messages
|
|
140
|
-
GameObject scrollViewObj = new GameObject("ScrollView");
|
|
141
|
-
scrollViewObj.transform.SetParent(gameObject.transform);
|
|
142
|
-
RectTransform scrollRectTransform = scrollViewObj.AddComponent<RectTransform>();
|
|
143
|
-
scrollRectTransform.anchorMin = new Vector2(0, 0);
|
|
144
|
-
scrollRectTransform.anchorMax = new Vector2(1, 1);
|
|
145
|
-
scrollRectTransform.sizeDelta = Vector2.zero;
|
|
146
|
-
scrollRectTransform.offsetMin = new Vector2(10, 10);
|
|
147
|
-
scrollRectTransform.offsetMax = new Vector2(-10, -10);
|
|
148
|
-
|
|
149
|
-
ScrollRect scrollRect = scrollViewObj.AddComponent<ScrollRect>();
|
|
150
|
-
scrollRect.horizontal = false;
|
|
151
|
-
|
|
152
|
-
// Create Content Area
|
|
153
|
-
GameObject contentObj = new GameObject("Content");
|
|
154
|
-
contentObj.transform.SetParent(scrollViewObj.transform);
|
|
155
|
-
_contentArea = contentObj.AddComponent<RectTransform>();
|
|
156
|
-
|
|
157
|
-
_contentArea.anchorMin = new Vector2(0, 1);
|
|
158
|
-
_contentArea.anchorMax = new Vector2(1, 1);
|
|
159
|
-
_contentArea.pivot = new Vector2(0.5f, 1);
|
|
160
|
-
_contentArea.sizeDelta = new Vector2(0, 0);
|
|
161
|
-
_contentArea.offsetMin = new Vector2(0, 0);
|
|
162
|
-
_contentArea.offsetMax = new Vector2(0, 0);
|
|
163
|
-
|
|
164
|
-
scrollRect.content = _contentArea;
|
|
165
|
-
|
|
166
|
-
VerticalLayoutGroup layoutGroup = contentObj.AddComponent<VerticalLayoutGroup>();
|
|
167
|
-
layoutGroup.childAlignment = TextAnchor.UpperCenter;
|
|
168
|
-
layoutGroup.childScaleWidth = true;
|
|
169
|
-
layoutGroup.childScaleHeight = true;
|
|
170
|
-
layoutGroup.childControlWidth = false;
|
|
171
|
-
layoutGroup.childControlHeight = false;
|
|
172
|
-
layoutGroup.childForceExpandWidth = false;
|
|
173
|
-
layoutGroup.childForceExpandHeight = false;
|
|
174
|
-
|
|
175
|
-
Mask mask = scrollViewObj.AddComponent<Mask>();
|
|
176
|
-
mask.showMaskGraphic = false;
|
|
177
|
-
scrollViewObj.AddComponent<Image>();
|
|
178
|
-
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
/// <summary>
|
|
183
|
-
/// Displays a message in the UI with an optional duration.
|
|
184
|
-
/// </summary>
|
|
185
|
-
/// <param name="message">The message text to display.</param>
|
|
186
|
-
/// <param name="duration">The duration the message remains visible (in seconds).</param>
|
|
187
|
-
public void ShowMessage(string message, float duration = MessageLifetime)
|
|
188
|
-
{
|
|
189
|
-
EnsureUIExists();
|
|
190
|
-
|
|
191
|
-
// Get caller details using reflection
|
|
192
|
-
StackFrame frame = new StackFrame(1);
|
|
193
|
-
MethodBase method = frame.GetMethod();
|
|
194
|
-
string assemblyName = method.Module.Assembly.GetName().Name;
|
|
195
|
-
string methodKey = $"{assemblyName}.{method.ReflectedType.FullName}.{method.Name}";
|
|
196
|
-
if(_lastMethod != methodKey)
|
|
197
|
-
{
|
|
198
|
-
//Removes any method key which comes back so that they are in right order.
|
|
199
|
-
if (_messages.ContainsKey(methodKey)){
|
|
200
|
-
MessageEntry curr = _messages[methodKey];
|
|
201
|
-
Destroy(curr.UIElement.gameObject);
|
|
202
|
-
_messages.Remove(methodKey);
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
_lastMethod = methodKey;
|
|
206
|
-
|
|
207
|
-
if (_messages.ContainsKey(methodKey))
|
|
208
|
-
{
|
|
209
|
-
_messages[methodKey].DisplayText = message;
|
|
210
|
-
_messages[methodKey].RemainingTime = duration;
|
|
211
|
-
}
|
|
212
|
-
else
|
|
213
|
-
{
|
|
214
|
-
GameObject messageObj = new GameObject("Message");
|
|
215
|
-
messageObj.transform.SetParent(_contentArea.transform);
|
|
216
|
-
|
|
217
|
-
Text messageText = messageObj.AddComponent<Text>();
|
|
218
|
-
messageText.fontStyle = FontStyle.Normal;
|
|
219
|
-
messageText.font = Resources.GetBuiltinResource<Font>("LegacyRuntime.ttf");
|
|
220
|
-
messageText.fontSize = 70;
|
|
221
|
-
messageText.color = Color.black;
|
|
222
|
-
|
|
223
|
-
_messages[methodKey] = new MessageEntry(message, duration, messageText);
|
|
224
|
-
|
|
225
|
-
RectTransform rectTransform = messageText.GetComponent<RectTransform>();
|
|
226
|
-
rectTransform.anchorMin = new Vector2(0, 1);
|
|
227
|
-
rectTransform.anchorMax = new Vector2(1, 1);
|
|
228
|
-
rectTransform.pivot = new Vector2(0.5f, 1);
|
|
229
|
-
rectTransform.sizeDelta = new Vector2(3000, 100);
|
|
230
|
-
rectTransform.localScale = new Vector3(0.2f, 0.2f, 1);
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
UpdateDisplayedMessages();
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
/// <summary>
|
|
237
|
-
/// Unity's Update method. Manages message lifetime and removes expired messages.
|
|
238
|
-
/// </summary>
|
|
239
|
-
private void Update()
|
|
240
|
-
{
|
|
241
|
-
if (_instance == null)
|
|
242
|
-
{
|
|
243
|
-
Transform content = gameObject.transform.GetChild(0).GetChild(0);
|
|
244
|
-
for (int i = content.childCount - 1; i >= 0; i--)
|
|
245
|
-
{
|
|
246
|
-
Destroy(content.GetChild(i).gameObject);
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
}
|
|
250
|
-
List<string> keysToRemove = new List<string>();
|
|
251
|
-
bool displayDirty = false;
|
|
252
|
-
|
|
253
|
-
foreach (var entry in _messages)
|
|
254
|
-
{
|
|
255
|
-
entry.Value.RemainingTime -= Time.unscaledDeltaTime;
|
|
256
|
-
if (entry.Value.RemainingTime <= 0)
|
|
257
|
-
{
|
|
258
|
-
Destroy(entry.Value.UIElement.gameObject);
|
|
259
|
-
keysToRemove.Add(entry.Key);
|
|
260
|
-
displayDirty = true;
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
foreach (var key in keysToRemove)
|
|
265
|
-
{
|
|
266
|
-
_messages.Remove(key);
|
|
267
|
-
displayDirty = true;
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
if (displayDirty)
|
|
271
|
-
{
|
|
272
|
-
UpdateDisplayedMessages();
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
/// <summary>
|
|
277
|
-
/// Updates the layout and content size of the displayed messages.
|
|
278
|
-
/// </summary>
|
|
279
|
-
private void UpdateDisplayedMessages()
|
|
280
|
-
{
|
|
281
|
-
float contentHeight = 0;
|
|
282
|
-
foreach (var entry in _messages.Values)
|
|
283
|
-
{
|
|
284
|
-
entry.UIElement.text = entry.DisplayText;
|
|
285
|
-
contentHeight += entry.UIElement.preferredHeight;
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
_contentArea.sizeDelta = new Vector2(_contentArea.sizeDelta.x, contentHeight);
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
}
|
|
1
|
+
using UnityEngine;
|
|
2
|
+
using UnityEngine.UI;
|
|
3
|
+
using System.Collections.Generic;
|
|
4
|
+
using System.Diagnostics;
|
|
5
|
+
using System.Reflection;
|
|
6
|
+
using static UnityEngine.EventSystems.EventTrigger;
|
|
7
|
+
using Debug = System.Diagnostics.Debug;
|
|
8
|
+
|
|
9
|
+
namespace MooseRunner.Internal.Tests
|
|
10
|
+
{
|
|
11
|
+
/// <summary>
|
|
12
|
+
/// Manages the display of messages in a persistent UI canvas.
|
|
13
|
+
/// Messages are displayed in a vertical list and are automatically removed after their lifetime expires.
|
|
14
|
+
/// </summary>
|
|
15
|
+
public class MessageDisplayManager : MonoBehaviour
|
|
16
|
+
{
|
|
17
|
+
/// <summary>
|
|
18
|
+
/// The singleton instance of the <see cref="MessageDisplayManager"/>.
|
|
19
|
+
/// </summary>
|
|
20
|
+
private static MessageDisplayManager _instance;
|
|
21
|
+
|
|
22
|
+
/// <summary>
|
|
23
|
+
/// Provides global access to the <see cref="MessageDisplayManager"/> instance.
|
|
24
|
+
/// Ensures that the manager is created and persists across scenes.
|
|
25
|
+
/// </summary>
|
|
26
|
+
public static MessageDisplayManager Instance
|
|
27
|
+
{
|
|
28
|
+
get
|
|
29
|
+
{
|
|
30
|
+
// If instance exists, return it
|
|
31
|
+
if (_instance != null) return _instance;
|
|
32
|
+
|
|
33
|
+
// 1. Find any existing instance in the scene
|
|
34
|
+
MessageDisplayManager[] instances = FindObjectsByType<MessageDisplayManager>(FindObjectsSortMode.None);
|
|
35
|
+
if (instances.Length > 0)
|
|
36
|
+
{
|
|
37
|
+
_instance = instances[0];
|
|
38
|
+
|
|
39
|
+
if (instances.Length > 1)
|
|
40
|
+
{
|
|
41
|
+
UnityEngine.Debug.LogWarning("Multiple TestRunnerHelper instances found! Using the first one.");
|
|
42
|
+
// Optionally, destroy duplicates here
|
|
43
|
+
for (int i = 1; i < instances.Length; i++)
|
|
44
|
+
{
|
|
45
|
+
Destroy(instances[i].gameObject);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return _instance;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// 2. No instance found, instantiate the prefab
|
|
52
|
+
if (_instance == null)
|
|
53
|
+
{
|
|
54
|
+
GameObject obj = new GameObject("MessageDisplayManager");
|
|
55
|
+
_instance = obj.AddComponent<MessageDisplayManager>();
|
|
56
|
+
DontDestroyOnLoad(obj); // Ensure it persists across scenes
|
|
57
|
+
}
|
|
58
|
+
return _instance;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/// <summary>
|
|
63
|
+
/// The canvas used to display the message UI.
|
|
64
|
+
/// </summary>
|
|
65
|
+
private Canvas _canvas;
|
|
66
|
+
|
|
67
|
+
/// <summary>
|
|
68
|
+
/// The content area within the canvas that holds all displayed messages.
|
|
69
|
+
/// </summary>
|
|
70
|
+
private RectTransform _contentArea;
|
|
71
|
+
|
|
72
|
+
/// <summary>
|
|
73
|
+
/// A dictionary that stores active messages, indexed by a unique key derived from the caller's context.
|
|
74
|
+
/// </summary>
|
|
75
|
+
private readonly Dictionary<string, MessageEntry> _messages = new Dictionary<string, MessageEntry>();
|
|
76
|
+
|
|
77
|
+
/// <summary>
|
|
78
|
+
/// The default duration (in seconds) for which a message remains visible.
|
|
79
|
+
/// </summary>
|
|
80
|
+
private const float MessageLifetime = 10f;
|
|
81
|
+
|
|
82
|
+
///<summary>
|
|
83
|
+
///Keeps track of last method
|
|
84
|
+
/// </summary>
|
|
85
|
+
private string _lastMethod;
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
/// <summary>
|
|
89
|
+
/// Represents a single message entry in the display manager.
|
|
90
|
+
/// </summary>
|
|
91
|
+
private class MessageEntry
|
|
92
|
+
{
|
|
93
|
+
/// <summary>
|
|
94
|
+
/// The text content of the message.
|
|
95
|
+
/// </summary>
|
|
96
|
+
public string DisplayText;
|
|
97
|
+
|
|
98
|
+
/// <summary>
|
|
99
|
+
/// The remaining lifetime of the message, in seconds.
|
|
100
|
+
/// </summary>
|
|
101
|
+
public float RemainingTime;
|
|
102
|
+
|
|
103
|
+
/// <summary>
|
|
104
|
+
/// The UI element used to display the message.
|
|
105
|
+
/// </summary>
|
|
106
|
+
public Text UIElement;
|
|
107
|
+
|
|
108
|
+
/// <summary>
|
|
109
|
+
/// Initializes a new instance of the <see cref="MessageEntry"/> class.
|
|
110
|
+
/// </summary>
|
|
111
|
+
/// <param name="text">The message text to display.</param>
|
|
112
|
+
/// <param name="duration">The duration the message should remain visible.</param>
|
|
113
|
+
/// <param name="uiElement">The UI text element associated with the message.</param>
|
|
114
|
+
public MessageEntry(string text, float duration, Text uiElement)
|
|
115
|
+
{
|
|
116
|
+
DisplayText = text;
|
|
117
|
+
RemainingTime = duration;
|
|
118
|
+
UIElement = uiElement;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/// <summary>
|
|
123
|
+
/// Ensures that the UI elements for displaying messages are created and properly configured.
|
|
124
|
+
/// </summary>
|
|
125
|
+
private void EnsureUIExists()
|
|
126
|
+
{
|
|
127
|
+
if (_canvas == null)
|
|
128
|
+
{
|
|
129
|
+
|
|
130
|
+
// Create Canvas
|
|
131
|
+
_canvas = gameObject.AddComponent<Canvas>();
|
|
132
|
+
_canvas.renderMode = RenderMode.ScreenSpaceOverlay;
|
|
133
|
+
DontDestroyOnLoad(gameObject);
|
|
134
|
+
|
|
135
|
+
// Add a Canvas Scaler
|
|
136
|
+
CanvasScaler scaler = gameObject.AddComponent<CanvasScaler>();
|
|
137
|
+
scaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
|
|
138
|
+
|
|
139
|
+
// Add a Scroll View for Messages
|
|
140
|
+
GameObject scrollViewObj = new GameObject("ScrollView");
|
|
141
|
+
scrollViewObj.transform.SetParent(gameObject.transform);
|
|
142
|
+
RectTransform scrollRectTransform = scrollViewObj.AddComponent<RectTransform>();
|
|
143
|
+
scrollRectTransform.anchorMin = new Vector2(0, 0);
|
|
144
|
+
scrollRectTransform.anchorMax = new Vector2(1, 1);
|
|
145
|
+
scrollRectTransform.sizeDelta = Vector2.zero;
|
|
146
|
+
scrollRectTransform.offsetMin = new Vector2(10, 10);
|
|
147
|
+
scrollRectTransform.offsetMax = new Vector2(-10, -10);
|
|
148
|
+
|
|
149
|
+
ScrollRect scrollRect = scrollViewObj.AddComponent<ScrollRect>();
|
|
150
|
+
scrollRect.horizontal = false;
|
|
151
|
+
|
|
152
|
+
// Create Content Area
|
|
153
|
+
GameObject contentObj = new GameObject("Content");
|
|
154
|
+
contentObj.transform.SetParent(scrollViewObj.transform);
|
|
155
|
+
_contentArea = contentObj.AddComponent<RectTransform>();
|
|
156
|
+
|
|
157
|
+
_contentArea.anchorMin = new Vector2(0, 1);
|
|
158
|
+
_contentArea.anchorMax = new Vector2(1, 1);
|
|
159
|
+
_contentArea.pivot = new Vector2(0.5f, 1);
|
|
160
|
+
_contentArea.sizeDelta = new Vector2(0, 0);
|
|
161
|
+
_contentArea.offsetMin = new Vector2(0, 0);
|
|
162
|
+
_contentArea.offsetMax = new Vector2(0, 0);
|
|
163
|
+
|
|
164
|
+
scrollRect.content = _contentArea;
|
|
165
|
+
|
|
166
|
+
VerticalLayoutGroup layoutGroup = contentObj.AddComponent<VerticalLayoutGroup>();
|
|
167
|
+
layoutGroup.childAlignment = TextAnchor.UpperCenter;
|
|
168
|
+
layoutGroup.childScaleWidth = true;
|
|
169
|
+
layoutGroup.childScaleHeight = true;
|
|
170
|
+
layoutGroup.childControlWidth = false;
|
|
171
|
+
layoutGroup.childControlHeight = false;
|
|
172
|
+
layoutGroup.childForceExpandWidth = false;
|
|
173
|
+
layoutGroup.childForceExpandHeight = false;
|
|
174
|
+
|
|
175
|
+
Mask mask = scrollViewObj.AddComponent<Mask>();
|
|
176
|
+
mask.showMaskGraphic = false;
|
|
177
|
+
scrollViewObj.AddComponent<Image>();
|
|
178
|
+
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/// <summary>
|
|
183
|
+
/// Displays a message in the UI with an optional duration.
|
|
184
|
+
/// </summary>
|
|
185
|
+
/// <param name="message">The message text to display.</param>
|
|
186
|
+
/// <param name="duration">The duration the message remains visible (in seconds).</param>
|
|
187
|
+
public void ShowMessage(string message, float duration = MessageLifetime)
|
|
188
|
+
{
|
|
189
|
+
EnsureUIExists();
|
|
190
|
+
|
|
191
|
+
// Get caller details using reflection
|
|
192
|
+
StackFrame frame = new StackFrame(1);
|
|
193
|
+
MethodBase method = frame.GetMethod();
|
|
194
|
+
string assemblyName = method.Module.Assembly.GetName().Name;
|
|
195
|
+
string methodKey = $"{assemblyName}.{method.ReflectedType.FullName}.{method.Name}";
|
|
196
|
+
if(_lastMethod != methodKey)
|
|
197
|
+
{
|
|
198
|
+
//Removes any method key which comes back so that they are in right order.
|
|
199
|
+
if (_messages.ContainsKey(methodKey)){
|
|
200
|
+
MessageEntry curr = _messages[methodKey];
|
|
201
|
+
Destroy(curr.UIElement.gameObject);
|
|
202
|
+
_messages.Remove(methodKey);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
_lastMethod = methodKey;
|
|
206
|
+
|
|
207
|
+
if (_messages.ContainsKey(methodKey))
|
|
208
|
+
{
|
|
209
|
+
_messages[methodKey].DisplayText = message;
|
|
210
|
+
_messages[methodKey].RemainingTime = duration;
|
|
211
|
+
}
|
|
212
|
+
else
|
|
213
|
+
{
|
|
214
|
+
GameObject messageObj = new GameObject("Message");
|
|
215
|
+
messageObj.transform.SetParent(_contentArea.transform);
|
|
216
|
+
|
|
217
|
+
Text messageText = messageObj.AddComponent<Text>();
|
|
218
|
+
messageText.fontStyle = FontStyle.Normal;
|
|
219
|
+
messageText.font = Resources.GetBuiltinResource<Font>("LegacyRuntime.ttf");
|
|
220
|
+
messageText.fontSize = 70;
|
|
221
|
+
messageText.color = Color.black;
|
|
222
|
+
|
|
223
|
+
_messages[methodKey] = new MessageEntry(message, duration, messageText);
|
|
224
|
+
|
|
225
|
+
RectTransform rectTransform = messageText.GetComponent<RectTransform>();
|
|
226
|
+
rectTransform.anchorMin = new Vector2(0, 1);
|
|
227
|
+
rectTransform.anchorMax = new Vector2(1, 1);
|
|
228
|
+
rectTransform.pivot = new Vector2(0.5f, 1);
|
|
229
|
+
rectTransform.sizeDelta = new Vector2(3000, 100);
|
|
230
|
+
rectTransform.localScale = new Vector3(0.2f, 0.2f, 1);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
UpdateDisplayedMessages();
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/// <summary>
|
|
237
|
+
/// Unity's Update method. Manages message lifetime and removes expired messages.
|
|
238
|
+
/// </summary>
|
|
239
|
+
private void Update()
|
|
240
|
+
{
|
|
241
|
+
if (_instance == null)
|
|
242
|
+
{
|
|
243
|
+
Transform content = gameObject.transform.GetChild(0).GetChild(0);
|
|
244
|
+
for (int i = content.childCount - 1; i >= 0; i--)
|
|
245
|
+
{
|
|
246
|
+
Destroy(content.GetChild(i).gameObject);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
}
|
|
250
|
+
List<string> keysToRemove = new List<string>();
|
|
251
|
+
bool displayDirty = false;
|
|
252
|
+
|
|
253
|
+
foreach (var entry in _messages)
|
|
254
|
+
{
|
|
255
|
+
entry.Value.RemainingTime -= Time.unscaledDeltaTime;
|
|
256
|
+
if (entry.Value.RemainingTime <= 0)
|
|
257
|
+
{
|
|
258
|
+
Destroy(entry.Value.UIElement.gameObject);
|
|
259
|
+
keysToRemove.Add(entry.Key);
|
|
260
|
+
displayDirty = true;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
foreach (var key in keysToRemove)
|
|
265
|
+
{
|
|
266
|
+
_messages.Remove(key);
|
|
267
|
+
displayDirty = true;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
if (displayDirty)
|
|
271
|
+
{
|
|
272
|
+
UpdateDisplayedMessages();
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/// <summary>
|
|
277
|
+
/// Updates the layout and content size of the displayed messages.
|
|
278
|
+
/// </summary>
|
|
279
|
+
private void UpdateDisplayedMessages()
|
|
280
|
+
{
|
|
281
|
+
float contentHeight = 0;
|
|
282
|
+
foreach (var entry in _messages.Values)
|
|
283
|
+
{
|
|
284
|
+
entry.UIElement.text = entry.DisplayText;
|
|
285
|
+
contentHeight += entry.UIElement.preferredHeight;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
_contentArea.sizeDelta = new Vector2(_contentArea.sizeDelta.x, contentHeight);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|