├── LICENSE ├── README.md ├── README.md.meta ├── SceneViewNotification.cs └── SceneViewNotification.cs.meta /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Jonny10 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Scene view notification 2 | Notification log for Unity's scene view. 3 | 4 | Instructions 5 | ------------ 6 | 7 | Call the static function `SceneViewNotification.Add(string text, NotificationType type)` from an editor script to display a message. `NotificationType` can be `Info, Warning, Error`. 8 | 9 | ![alt text](https://i.imgur.com/khUofTA.gif "") 10 | 11 | Under `Edit->Preferences` you can configure the maximum lifetime of a message, and the time it takes to fade one out. 12 | 13 | ![alt text](https://i.imgur.com/0UGSaM3.png "") 14 | 15 | License 16 | ------- 17 | 18 | MIT License (see [LICENSE](LICENSE.md)) -------------------------------------------------------------------------------- /README.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: bf30a338712543b41850307155a42c20 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /SceneViewNotification.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | #if UNITY_EDITOR 6 | using UnityEditor; 7 | #endif 8 | using UnityEngine; 9 | 10 | #if UNITY_EDITOR 11 | public class SceneViewNotification : Editor 12 | { 13 | static List notifications = new List(); 14 | 15 | public enum NotificationType 16 | { 17 | Info, 18 | Warning, 19 | Error 20 | } 21 | 22 | private class Notification 23 | { 24 | public string text; 25 | public DateTime dateTime; 26 | public NotificationType type; 27 | } 28 | 29 | public static void Add(string text, NotificationType type) 30 | { 31 | Notification n = new Notification(); 32 | n.dateTime = DateTime.Now; 33 | n.text = text; 34 | n.type = type; 35 | 36 | if (notifications.Count >= MaxItems) notifications.RemoveAt(notifications.Count - 1); 37 | 38 | notifications.Insert(0, n); 39 | } 40 | 41 | public static void Clear() 42 | { 43 | notifications.Clear(); 44 | } 45 | 46 | const float width = 300f; 47 | const float height = 155f; 48 | const int lineHeight = 20; 49 | private static float linePos; 50 | 51 | public static int MaxItems 52 | { 53 | get { return EditorPrefs.GetInt("SVN_MAX_ITEMS", 30); } 54 | set { EditorPrefs.SetInt("SVN_MAX_ITEMS", value); } 55 | } 56 | public static float MaxLifetime 57 | { 58 | get { return EditorPrefs.GetFloat("SVN_LIFETIME", 3f); } 59 | set { EditorPrefs.SetFloat("SVN_LIFETIME", value); } 60 | } 61 | public static float FadeoutDuration 62 | { 63 | get { return EditorPrefs.GetFloat("SVN_FADE_DUR", 2f); } 64 | set { EditorPrefs.SetFloat("SVN_FADE_DUR", value); } 65 | } 66 | 67 | private static bool mouseOver; 68 | 69 | private static void OnScene(SceneView sceneView) 70 | { 71 | Handles.BeginGUI(); 72 | 73 | //Get rekt 74 | Rect highlightRect = new Rect(5, sceneView.camera.pixelHeight - 5 - 100, 100, 150); 75 | Rect lineRect = new Rect(10, sceneView.camera.pixelHeight - 25, width - 10f, lineHeight); 76 | Rect iconRect = new Rect(10, sceneView.camera.pixelHeight - 25, width - 10f, lineHeight); 77 | lineRect.x += 20f; //Make room for icon 78 | 79 | Vector2 mousePos = Event.current.mousePosition; 80 | mouseOver = highlightRect.Contains(mousePos); 81 | 82 | //Move everything up 20px to make room for the clear button 83 | lineRect.y = (mouseOver) ? lineRect.y - 20f : lineRect.y; 84 | iconRect.y = (mouseOver) ? iconRect.y - 20f : iconRect.y; 85 | 86 | //Show button on mouseover 87 | if (mouseOver) if (GUI.Button(new Rect(0, sceneView.camera.pixelHeight - 18f, 55f, 20f), "Clear log", EditorStyles.toolbarButton)) Clear(); 88 | 89 | foreach (Notification n in notifications) 90 | { 91 | //Time alive running from 0 and up 92 | float lifetime = ((float)DateTime.Now.Subtract(n.dateTime).TotalMilliseconds); 93 | 94 | float alpha = 1; 95 | //When past maximum lifetime, start fadeTime at 0 96 | if (lifetime >= (MaxLifetime * 1000)) 97 | { 98 | float fadeTime = lifetime - (MaxLifetime * 1000); 99 | alpha = 1 - (fadeTime / (FadeoutDuration * 1000)); 100 | } 101 | 102 | Color originalColor = GUI.color; 103 | Color textColor = GUI.color; 104 | Texture icon = null; 105 | switch (n.type) 106 | { 107 | case NotificationType.Info: 108 | { 109 | textColor = Color.white; 110 | icon = EditorGUIUtility.IconContent("console.infoicon.sml").image; 111 | } 112 | break; 113 | case NotificationType.Warning: 114 | { 115 | textColor = new Color(252f / 255f, 174f / 255f, 78f / 255f); 116 | icon = EditorGUIUtility.IconContent("console.warnicon.sml").image; 117 | } 118 | break; 119 | case NotificationType.Error: 120 | { 121 | textColor = new Color(255f / 255f, 112f / 255f, 112f / 255f); 122 | icon = EditorGUIUtility.IconContent("console.erroricon.sml").image; 123 | } 124 | break; 125 | } 126 | 127 | GUI.color = new Color(1f, 1f, 1f, mouseOver ? 1f : alpha); 128 | GUI.Label(iconRect, icon); 129 | 130 | GUI.color = new Color(textColor.r, textColor.g, textColor.b, mouseOver ? 1f : alpha); 131 | 132 | string hourString = ((n.dateTime.Hour <= 9) ? "0" : "") + n.dateTime.Hour; 133 | string minuteString = ((n.dateTime.Minute <= 9) ? "0" : "") + n.dateTime.Minute; 134 | string secString = ((n.dateTime.Second <= 9) ? "0" : "") + n.dateTime.Second; 135 | string timeString = "[" + hourString + ":" + minuteString + ":" + secString + "] "; 136 | 137 | GUI.Label(lineRect, new GUIContent(" " + timeString + "" + n.text + ""), LogText); 138 | 139 | //Decrease height pos of next line 140 | lineRect.y -= lineHeight; 141 | iconRect.y -= lineHeight; 142 | 143 | GUI.color = originalColor; 144 | } 145 | 146 | Handles.EndGUI(); 147 | } 148 | 149 | static string[] infoMessages = new string[] { "Ding dong!", "So informative!", "So important!", "Something happened!" }; 150 | static string[] warningMessages = new string[] { "Oops!", "Careful", "Warning!", "Thin ice" }; 151 | static string[] errorMessages = new string[] { "Error!", "Dun goofed!", "Made a boo boo!" }; 152 | 153 | #if UNITY_2019_1_OR_NEWER 154 | [SettingsProvider] 155 | public static SettingsProvider SceneViewNotificationSettings() 156 | { 157 | var provider = new SettingsProvider("Editor/Scene Notifications", SettingsScope.Project) 158 | { 159 | label = "Scene Notifications", 160 | guiHandler = (searchContent) => 161 | { 162 | MaxLifetime = EditorGUILayout.Slider("Life time", MaxLifetime, 0.1f, 10f); 163 | FadeoutDuration = EditorGUILayout.Slider("Fade time", FadeoutDuration, 0.1f, 10f); 164 | MaxItems = EditorGUILayout.IntField("Maximum lines", MaxItems); 165 | 166 | EditorGUILayout.Space(); 167 | 168 | using (new EditorGUILayout.HorizontalScope()) 169 | { 170 | EditorGUILayout.PrefixLabel(" "); 171 | if (GUILayout.Button("Test message")) 172 | { 173 | NotificationType type = (NotificationType)(int)UnityEngine.Random.Range(0, 3); 174 | 175 | string[] messages = new string[4]; 176 | if (type == NotificationType.Info) messages = infoMessages; 177 | if (type == NotificationType.Warning) messages = warningMessages; 178 | if (type == NotificationType.Error) messages = errorMessages; 179 | 180 | string text = messages[UnityEngine.Random.Range(0, messages.Length)]; 181 | 182 | Add(text, type); 183 | } 184 | } 185 | }, 186 | 187 | keywords = new HashSet(new[] { "Scene", "Notifications", "Log" }) 188 | }; 189 | 190 | return provider; 191 | } 192 | #else 193 | [PreferenceItem("Scene Notifications")] 194 | public static void PreferencesGUI() 195 | { 196 | MaxLifetime = EditorGUILayout.Slider("Life time", MaxLifetime, 0.1f, 10f); 197 | FadeoutDuration = EditorGUILayout.Slider("Fade time", FadeoutDuration, 0.1f, 10f); 198 | MaxItems = EditorGUILayout.IntField("Maximum lines", MaxItems); 199 | 200 | EditorGUILayout.Space(); 201 | 202 | using (new EditorGUILayout.HorizontalScope()) 203 | { 204 | EditorGUILayout.PrefixLabel(" "); 205 | if (GUILayout.Button("Test message")) 206 | { 207 | NotificationType type = (NotificationType)(int)UnityEngine.Random.Range(0, 3); 208 | 209 | string[] messages = new string[4]; 210 | if (type == NotificationType.Info) messages = infoMessages; 211 | if (type == NotificationType.Warning) messages = warningMessages; 212 | if (type == NotificationType.Error) messages = errorMessages; 213 | 214 | string text = messages[UnityEngine.Random.Range(0, messages.Length)]; 215 | 216 | Add(text, type); 217 | } 218 | } 219 | } 220 | #endif 221 | 222 | [InitializeOnLoad] 223 | sealed class InitializeOnLoad : Editor 224 | { 225 | [InitializeOnLoadMethod] 226 | public static void Initialize() 227 | { 228 | if (EditorApplication.isPlaying) return; 229 | 230 | #if UNITY_2019_1_OR_NEWER 231 | SceneView.duringSceneGui += OnScene; 232 | #else 233 | SceneView.onSceneGUIDelegate += OnScene; 234 | #endif 235 | } 236 | } 237 | 238 | private static GUIStyle _LogText; 239 | public static GUIStyle LogText 240 | { 241 | get 242 | { 243 | if (_LogText == null) 244 | { 245 | _LogText = new GUIStyle(UnityEngine.GUI.skin.label) 246 | { 247 | richText = true, 248 | alignment = TextAnchor.MiddleLeft, 249 | wordWrap = false, 250 | fontSize = 12, 251 | stretchWidth = true, 252 | font = (Font)EditorGUIUtility.LoadRequired("Fonts/Lucida Grande.ttf"), 253 | //fontStyle = FontStyle.Bold, 254 | padding = new RectOffset() 255 | { 256 | left = 0, 257 | right = 0, 258 | top = 0, 259 | bottom = 0 260 | }, 261 | clipping = TextClipping.Overflow 262 | }; 263 | } 264 | 265 | return _LogText; 266 | } 267 | } 268 | } 269 | #endif -------------------------------------------------------------------------------- /SceneViewNotification.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e6628e0622149884b906cd5743ecf9f2 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | --------------------------------------------------------------------------------