// shared by compute shader inspector too internal static void ShaderErrorListUI(Object shader, ShaderMessage[] messages, ref Vector2 scrollPosition) { int n = messages.Length; GUILayout.Space(kSpace); GUILayout.Label(string.Format("Errors ({0}):", n), EditorStyles.boldLabel); int errorListID = GUIUtility.GetControlID(kErrorViewHash, FocusType.Passive); float height = Mathf.Min(n * 20f + 40f, 150f); scrollPosition = GUILayout.BeginScrollView(scrollPosition, GUISkin.current.box, GUILayout.MinHeight(height)); EditorGUIUtility.SetIconSize(new Vector2(16.0f, 16.0f)); float lineHeight = Styles.messageStyle.CalcHeight(EditorGUIUtility.TempContent(Styles.errorIcon), 100); Event e = Event.current; for (int i = 0; i < n; ++i) { Rect r = EditorGUILayout.GetControlRect(false, lineHeight); string err = messages[i].message; string plat = messages[i].platform.ToString(); bool warn = messages[i].severity != ShaderCompilerMessageSeverity.Error; string fileName = FileUtil.GetLastPathNameComponent(messages[i].file); int line = messages[i].line; // Double click opens shader file at error line if (e.type == EventType.MouseDown && e.button == 0 && r.Contains(e.mousePosition)) { GUIUtility.keyboardControl = errorListID; if (e.clickCount == 2) { string filePath = messages[i].file; Object asset = string.IsNullOrEmpty(filePath) ? null : AssetDatabase.LoadMainAssetAtPath(filePath); // if we don't have an asset and the filePath is an absolute path, it's an error in a system // cginc - open that instead if (asset == null && System.IO.Path.IsPathRooted(filePath)) { ShaderUtil.OpenSystemShaderIncludeError(filePath, line); } else { AssetDatabase.OpenAsset(asset ?? shader, line); } GUIUtility.ExitGUI(); } e.Use(); } // Context menu, "Copy" if (e.type == EventType.ContextClick && r.Contains(e.mousePosition)) { e.Use(); var menu = new GenericMenu(); // need to copy current value to be used in delegate // (C# closures close over variables, not their values) var errorIndex = i; menu.AddItem(EditorGUIUtility.TrTextContent("Copy error text"), false, delegate { string errMsg = messages[errorIndex].message; if (!string.IsNullOrEmpty(messages[errorIndex].messageDetails)) { errMsg += '\n'; errMsg += messages[errorIndex].messageDetails; } EditorGUIUtility.systemCopyBuffer = errMsg; }); menu.ShowAsContext(); } // background if (e.type == EventType.Repaint) { if ((i & 1) == 0) { GUIStyle st = Styles.evenBackground; st.Draw(r, false, false, false, false); } } // error location on the right side Rect locRect = r; locRect.xMin = locRect.xMax; if (line > 0) { GUIContent gc; if (string.IsNullOrEmpty(fileName)) { gc = EditorGUIUtility.TempContent(line.ToString(CultureInfo.InvariantCulture)); } else { gc = EditorGUIUtility.TempContent(fileName + ":" + line.ToString(CultureInfo.InvariantCulture)); } // calculate size so we can right-align it Vector2 size = EditorStyles.miniLabel.CalcSize(gc); locRect.xMin -= size.x; GUI.Label(locRect, gc, EditorStyles.miniLabel); locRect.xMin -= 2; // ensure some minimum width so that platform field next will line up if (locRect.width < 30) { locRect.xMin = locRect.xMax - 30; } } // platform to the left of it Rect platRect = locRect; platRect.width = 0; if (plat.Length > 0) { GUIContent gc = EditorGUIUtility.TempContent(plat); // calculate size so we can right-align it Vector2 size = EditorStyles.miniLabel.CalcSize(gc); platRect.xMin -= size.x; // draw platform in dimmer color; it's often not very important information Color oldColor = GUI.contentColor; GUI.contentColor = new Color(1, 1, 1, 0.5f); GUI.Label(platRect, gc, EditorStyles.miniLabel); GUI.contentColor = oldColor; platRect.xMin -= 2; } // error message Rect msgRect = r; msgRect.xMax = platRect.xMin; GUI.Label(msgRect, EditorGUIUtility.TempContent(err, warn ? Styles.warningIcon : Styles.errorIcon), Styles.messageStyle); } EditorGUIUtility.SetIconSize(Vector2.zero); GUILayout.EndScrollView(); }
internal static void ShaderErrorListUI(UnityEngine.Object shader, ShaderError[] errors, ref Vector2 scrollPosition) { int num = errors.Length; GUILayout.Space(5f); GUILayout.Label(string.Format("Errors ({0}):", num), EditorStyles.boldLabel, new GUILayoutOption[0]); int controlID = GUIUtility.GetControlID(ShaderInspector.kErrorViewHash, FocusType.Passive); float minHeight = Mathf.Min((float)num * 20f + 40f, 150f); scrollPosition = GUILayout.BeginScrollView(scrollPosition, GUISkin.current.box, new GUILayoutOption[] { GUILayout.MinHeight(minHeight) }); EditorGUIUtility.SetIconSize(new Vector2(16f, 16f)); float height = ShaderInspector.Styles.messageStyle.CalcHeight(EditorGUIUtility.TempContent(ShaderInspector.Styles.errorIcon), 100f); Event current = Event.current; for (int i = 0; i < num; i++) { Rect controlRect = EditorGUILayout.GetControlRect(false, height, new GUILayoutOption[0]); string message = errors[i].message; string platform = errors[i].platform; bool flag = errors[i].warning != 0; string lastPathNameComponent = FileUtil.GetLastPathNameComponent(errors[i].file); int line = errors[i].line; if (current.type == EventType.MouseDown && current.button == 0 && controlRect.Contains(current.mousePosition)) { GUIUtility.keyboardControl = controlID; if (current.clickCount == 2) { string file = errors[i].file; UnityEngine.Object @object = (!string.IsNullOrEmpty(file)) ? AssetDatabase.LoadMainAssetAtPath(file) : null; if (@object == null && Path.IsPathRooted(file)) { ShaderUtil.OpenSystemShaderIncludeError(file, line); } else { AssetDatabase.OpenAsset(@object ?? shader, line); } GUIUtility.ExitGUI(); } current.Use(); } if (current.type == EventType.ContextClick && controlRect.Contains(current.mousePosition)) { current.Use(); GenericMenu genericMenu = new GenericMenu(); int errorIndex = i; genericMenu.AddItem(EditorGUIUtility.TrTextContent("Copy error text", null, null), false, delegate { string text = errors[errorIndex].message; if (!string.IsNullOrEmpty(errors[errorIndex].messageDetails)) { text += '\n'; text += errors[errorIndex].messageDetails; } EditorGUIUtility.systemCopyBuffer = text; }); genericMenu.ShowAsContext(); } if (current.type == EventType.Repaint) { if ((i & 1) == 0) { GUIStyle evenBackground = ShaderInspector.Styles.evenBackground; evenBackground.Draw(controlRect, false, false, false, false); } } Rect rect = controlRect; rect.xMin = rect.xMax; if (line > 0) { GUIContent content; if (string.IsNullOrEmpty(lastPathNameComponent)) { content = EditorGUIUtility.TempContent(line.ToString(CultureInfo.InvariantCulture)); } else { content = EditorGUIUtility.TempContent(lastPathNameComponent + ":" + line.ToString(CultureInfo.InvariantCulture)); } Vector2 vector = EditorStyles.miniLabel.CalcSize(content); rect.xMin -= vector.x; GUI.Label(rect, content, EditorStyles.miniLabel); rect.xMin -= 2f; if (rect.width < 30f) { rect.xMin = rect.xMax - 30f; } } Rect position = rect; position.width = 0f; if (platform.Length > 0) { GUIContent content2 = EditorGUIUtility.TempContent(platform); Vector2 vector2 = EditorStyles.miniLabel.CalcSize(content2); position.xMin -= vector2.x; Color contentColor = GUI.contentColor; GUI.contentColor = new Color(1f, 1f, 1f, 0.5f); GUI.Label(position, content2, EditorStyles.miniLabel); GUI.contentColor = contentColor; position.xMin -= 2f; } Rect position2 = controlRect; position2.xMax = position.xMin; GUI.Label(position2, EditorGUIUtility.TempContent(message, (!flag) ? ShaderInspector.Styles.errorIcon : ShaderInspector.Styles.warningIcon), ShaderInspector.Styles.messageStyle); } EditorGUIUtility.SetIconSize(Vector2.zero); GUILayout.EndScrollView(); }