Skip to content

Commit a369dbf

Browse files
committed
feat: Message banner
1 parent 62f1ab1 commit a369dbf

File tree

6 files changed

+395
-119
lines changed

6 files changed

+395
-119
lines changed

Editor/MessageBanner.cs

Lines changed: 222 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,226 @@
1-
using UnityEngine.UIElements;
1+
using System;
2+
using System.Collections.Generic;
3+
using UnityEditor;
4+
using UnityEngine;
5+
using UnityEngine.UIElements;
26

37
namespace GBG.EditorMessages.Editor
48
{
5-
public class MessageBanner : VisualElement { }
9+
public class MessageBanner : VisualElement
10+
{
11+
public Image TypeImage { get; }
12+
public Label ContentLabel { get; }
13+
public Image InfoTypeImage { get; }
14+
public Label InfoCountLabel { get; }
15+
public Image WarningTypeImage { get; }
16+
public Label WarningCountLabel { get; }
17+
public Image ErrorTypeImage { get; }
18+
public Label ErrorCountLabel { get; }
19+
20+
private bool _showMessageTypeCount;
21+
public bool ShowMessageTypeCount
22+
{
23+
get => _showMessageTypeCount;
24+
set
25+
{
26+
if (_showMessageTypeCount == value)
27+
return;
28+
29+
_showMessageTypeCount = value;
30+
RefreshMessageTypeCountDisplay();
31+
}
32+
}
33+
34+
public object Source { get; private set; }
35+
public string SourceName { get; private set; }
36+
public IList<Message> Messages { get; private set; }
37+
38+
39+
public MessageBanner(object source, string sourceName, bool showMessageTypeCount = true)
40+
: this(null, source, sourceName, showMessageTypeCount) { }
41+
42+
public MessageBanner(IList<Message> messages, object source, string sourceName,
43+
bool showMessageTypeCount = true)
44+
{
45+
_showMessageTypeCount = showMessageTypeCount;
46+
Messages = messages;
47+
Source = source;
48+
SourceName = sourceName;
49+
50+
style.flexDirection = FlexDirection.Row;
51+
style.paddingLeft = 4;
52+
style.paddingRight = 4;
53+
style.height = 20;
54+
55+
56+
float iconSize = 16;
57+
58+
TypeImage = new Image
59+
{
60+
style =
61+
{
62+
alignSelf = Align.Center,
63+
minWidth = iconSize,
64+
maxWidth = iconSize,
65+
minHeight = iconSize,
66+
maxHeight = iconSize,
67+
}
68+
};
69+
Add(TypeImage);
70+
71+
ContentLabel = new Label
72+
{
73+
style =
74+
{
75+
flexGrow = 1,
76+
flexShrink = 1,
77+
marginRight = 2,
78+
minWidth = 100,
79+
overflow = Overflow.Hidden,
80+
unityTextAlign = TextAnchor.MiddleLeft,
81+
unityFontDefinition = new StyleFontDefinition(ResCache.GetMonospaceFontAsset()),
82+
}
83+
};
84+
Add(ContentLabel);
85+
86+
InfoTypeImage = CreateMessageTypeImage(ResCache.GetInfoIcon(true), iconSize);
87+
Add(InfoTypeImage);
88+
89+
InfoCountLabel = CreateMessageTypeCountLabel();
90+
Add(InfoCountLabel);
91+
92+
WarningTypeImage = CreateMessageTypeImage(ResCache.GetWarningIcon(true), iconSize);
93+
Add(WarningTypeImage);
94+
95+
WarningCountLabel = CreateMessageTypeCountLabel();
96+
Add(WarningCountLabel);
97+
98+
ErrorTypeImage = CreateMessageTypeImage(ResCache.GetErrorIcon(true), iconSize);
99+
Add(ErrorTypeImage);
100+
101+
ErrorCountLabel = CreateMessageTypeCountLabel();
102+
Add(ErrorCountLabel);
103+
104+
RegisterCallback<ClickEvent>(OnClick);
105+
RegisterCallback<ContextClickEvent>(OnContextClick);
106+
107+
}
108+
109+
private Image CreateMessageTypeImage(Texture defaultIcon, float iconSize)
110+
{
111+
Image image = new Image
112+
{
113+
image = defaultIcon,
114+
style =
115+
{
116+
display = ShowMessageTypeCount ? DisplayStyle.Flex : DisplayStyle.None,
117+
alignSelf = Align.Center,
118+
minWidth = iconSize,
119+
maxWidth = iconSize,
120+
minHeight = iconSize,
121+
maxHeight = iconSize,
122+
}
123+
};
124+
return image;
125+
}
126+
127+
private Label CreateMessageTypeCountLabel()
128+
{
129+
Label label = new Label
130+
{
131+
text = "0",
132+
style =
133+
{
134+
display = ShowMessageTypeCount ? DisplayStyle.Flex : DisplayStyle.None,
135+
//flexShrink = 0,
136+
marginLeft = -3,
137+
marginRight = -3,
138+
paddingLeft = 0,
139+
paddingRight = 0,
140+
overflow = Overflow.Hidden,
141+
unityTextAlign = TextAnchor.MiddleCenter,
142+
unityFontDefinition = new StyleFontDefinition(ResCache.GetMonospaceFontAsset()),
143+
}
144+
};
145+
return label;
146+
}
147+
148+
149+
public void SetMessages(IList<Message> messages)
150+
{
151+
Messages = messages;
152+
Refresh();
153+
}
154+
155+
public void Refresh()
156+
{
157+
Message message = (Messages?.Count ?? 0) > 0 ? Messages[Messages.Count - 1] : null;
158+
SetMessage(message);
159+
160+
Messages.CountByType(out int infoCount, out int warningCount, out int errorCount);
161+
SetMessageCount(MessageType.Info, infoCount);
162+
SetMessageCount(MessageType.Warning, warningCount);
163+
SetMessageCount(MessageType.Error, errorCount);
164+
RefreshMessageTypeCountDisplay();
165+
}
166+
167+
private void SetMessage(Message message)
168+
{
169+
TypeImage.image = message != null ? ResCache.GetMessageTypeIcon(message.Type) : null;
170+
ContentLabel.text = message?.Content;
171+
ContentLabel.tooltip = message?.Content;
172+
}
173+
174+
private void SetMessageCount(MessageType messageType, int count)
175+
{
176+
string text = count > 999 ? "999+" : count.ToString();
177+
bool inactive = count < 1;
178+
switch (messageType)
179+
{
180+
case MessageType.Info:
181+
InfoCountLabel.text = text;
182+
InfoTypeImage.image = ResCache.GetInfoIcon(inactive);
183+
break;
184+
case MessageType.Warning:
185+
WarningCountLabel.text = text;
186+
WarningTypeImage.image = ResCache.GetWarningIcon(inactive);
187+
break;
188+
case MessageType.Error:
189+
ErrorCountLabel.text = text;
190+
ErrorTypeImage.image = ResCache.GetErrorIcon(inactive);
191+
break;
192+
default:
193+
throw new ArgumentOutOfRangeException(nameof(messageType), messageType, null);
194+
}
195+
}
196+
197+
private void RefreshMessageTypeCountDisplay()
198+
{
199+
DisplayStyle display = ShowMessageTypeCount ? DisplayStyle.Flex : DisplayStyle.None;
200+
InfoTypeImage.style.display = display;
201+
InfoCountLabel.style.display = display;
202+
WarningTypeImage.style.display = display;
203+
WarningCountLabel.style.display = display;
204+
ErrorTypeImage.style.display = display;
205+
ErrorCountLabel.style.display = display;
206+
}
207+
208+
private void OnClick(ClickEvent evt)
209+
{
210+
if (evt.clickCount == 2)
211+
{
212+
MessageViewer.Open(Messages, Source, SourceName);
213+
}
214+
}
215+
216+
private void OnContextClick(ContextClickEvent evt)
217+
{
218+
GenericMenu menu = new GenericMenu();
219+
220+
// Open Message Viewer
221+
menu.AddItem(new GUIContent("Open Message Viewer"), false, () => MessageViewer.Open(Messages, Source, SourceName));
222+
223+
menu.ShowAsContext();
224+
}
225+
}
6226
}

Editor/MessageElement.cs

Lines changed: 13 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,13 @@
33
using UnityEditor;
44
using UnityEngine;
55
using UnityEngine.Assertions;
6-
using UnityEngine.TextCore.Text;
76
using UnityEngine.UIElements;
87
using UObject = UnityEngine.Object;
98

109
namespace GBG.EditorMessages.Editor
1110
{
1211
public class MessageElement : VisualElement
1312
{
14-
private static Texture _infoIcon;
15-
private static Texture _warningIcon;
16-
private static Texture _errorIcon;
17-
private static Texture _contextIcon;
18-
private static Texture _customDataIcon;
19-
//private static Font _monospaceFont;
20-
private static FontAsset _monospaceFontAsset;
21-
2213
public Label LineNumberLabel { get; }
2314
public Image TypeImage { get; }
2415
public Label TimestampLabel { get; }
@@ -40,12 +31,8 @@ public MessageElement()
4031
style.flexDirection = FlexDirection.Row;
4132
style.paddingLeft = 4;
4233
style.paddingRight = 4;
34+
style.minWidth = 100;
4335

44-
if (!_monospaceFontAsset)
45-
{
46-
//_monospaceFont = (Font)EditorGUIUtility.LoadRequired("fonts/robotomono/robotomono-regular.ttf");
47-
_monospaceFontAsset = (FontAsset)EditorGUIUtility.LoadRequired("fonts/robotomono/robotomono-regular sdf.asset");
48-
}
4936

5037
LineNumberLabel = new Label
5138
{
@@ -55,7 +42,7 @@ public MessageElement()
5542
marginRight = 2,
5643
overflow = Overflow.Hidden,
5744
unityTextAlign = TextAnchor.MiddleRight,
58-
unityFontDefinition = new StyleFontDefinition(_monospaceFontAsset),
45+
unityFontDefinition = new StyleFontDefinition(ResCache.GetMonospaceFontAsset()),
5946
}
6047
};
6148
Add(LineNumberLabel);
@@ -77,8 +64,9 @@ public MessageElement()
7764
{
7865
style =
7966
{
67+
paddingRight = 0,
8068
unityTextAlign = TextAnchor.MiddleCenter,
81-
unityFontDefinition = new StyleFontDefinition(_monospaceFontAsset),
69+
unityFontDefinition = new StyleFontDefinition(ResCache.GetMonospaceFontAsset()),
8270
}
8371
};
8472
Add(TimestampLabel);
@@ -88,8 +76,10 @@ public MessageElement()
8876
text = "|",
8977
style =
9078
{
79+
paddingLeft = 0,
80+
paddingRight = 4,
9181
unityTextAlign = TextAnchor.MiddleLeft,
92-
unityFontDefinition = new StyleFontDefinition(_monospaceFontAsset),
82+
//unityFontDefinition = new StyleFontDefinition(ResCache.GetMonospaceFontAsset()),
9383
}
9484
};
9585
Add(TimestampSeparatorLabel);
@@ -102,7 +92,7 @@ public MessageElement()
10292
flexShrink = 1,
10393
overflow = Overflow.Hidden,
10494
unityTextAlign = TextAnchor.MiddleLeft,
105-
unityFontDefinition = new StyleFontDefinition(_monospaceFontAsset),
95+
unityFontDefinition = new StyleFontDefinition(ResCache.GetMonospaceFontAsset()),
10696
}
10797
};
10898
Add(ContentLabel);
@@ -142,38 +132,11 @@ public MessageElement()
142132
public void SetMessage(Message message, int lineNumber, int lineNumberLabelWidth = -1)
143133
{
144134
Assert.IsTrue(message != null);
135+
145136
Message = message;
146137
LineNumber = lineNumber;
147138
LineNumberLabelWidth = lineNumberLabelWidth;
148-
149-
Texture typeIcon;
150-
switch (message.Type)
151-
{
152-
case MessageType.Info:
153-
if (!_infoIcon)
154-
{
155-
_infoIcon = EditorGUIUtility.IconContent("console.infoicon").image;
156-
}
157-
typeIcon = _infoIcon;
158-
break;
159-
case MessageType.Warning:
160-
if (!_warningIcon)
161-
{
162-
_warningIcon = EditorGUIUtility.IconContent("console.warnicon").image;
163-
}
164-
typeIcon = _warningIcon;
165-
break;
166-
case MessageType.Error:
167-
if (!_errorIcon)
168-
{
169-
_errorIcon = EditorGUIUtility.IconContent("console.erroricon").image;
170-
}
171-
typeIcon = _errorIcon;
172-
break;
173-
default:
174-
throw new ArgumentOutOfRangeException(nameof(message.Type), message.Type, null);
175-
}
176-
TypeImage.image = typeIcon;
139+
TypeImage.image = ResCache.GetMessageTypeIcon(message.Type);
177140
ContentLabel.text = message.Content;
178141

179142
UpdateLineNumberLabel();
@@ -217,12 +180,7 @@ private void UpdateContextImage()
217180
return;
218181
}
219182

220-
if (!_contextIcon)
221-
{
222-
_contextIcon = EditorGUIUtility.IconContent("gameobject icon").image;
223-
}
224-
225-
ContextImage.image = _contextIcon;
183+
ContextImage.image = ResCache.GetContextIcon();
226184
ContextImage.style.display = DisplayStyle.Flex;
227185
}
228186

@@ -234,12 +192,7 @@ private void UpdateCustomDataImage()
234192
return;
235193
}
236194

237-
if (!_customDataIcon)
238-
{
239-
_customDataIcon = EditorGUIUtility.IconContent("customized").image;
240-
}
241-
242-
CustomDataImage.image = _customDataIcon;
195+
CustomDataImage.image = ResCache.GetCustomDataIcon();
243196
CustomDataImage.style.display = DisplayStyle.Flex;
244197
}
245198

@@ -253,8 +206,7 @@ private void OnClick(ClickEvent evt)
253206
EditorGUIUtility.PingObject(context);
254207
}
255208
}
256-
257-
if (evt.clickCount == 2 && !string.IsNullOrEmpty(Message?.CustomData))
209+
else if (evt.clickCount == 2 && !string.IsNullOrEmpty(Message?.CustomData))
258210
{
259211
if (WantsToProcessCustomData != null)
260212
{

0 commit comments

Comments
 (0)