123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193 |
- using System;
- using System.Collections.Generic;
- using UnityEditor;
- using UnityEngine;
- using Object = UnityEngine.Object;
- namespace EnhancedHierarchy {
- /// <summary>
- /// Log Entries from the console, to check if a game object has any errors or warnings.
- /// </summary>
- public sealed class LogEntry {
- private const double UPDATE_FREQUENCY = 0.75; // Every 750ms
- private static readonly Type logEntriesType;
- private static readonly Type logEntryType;
- public int RowIndex { get; private set; }
- public string Condition { get; private set; }
- public int ErrorNum { get; private set; }
- public string File { get; private set; }
- public int Line { get; private set; }
- public int Column { get; private set; }
- public EntryMode Mode { get; private set; }
- public int InstanceID { get; private set; }
- public int Identifier { get; private set; }
- public Object ObjectReference { get; private set; }
- public MonoScript Script { get; private set; }
- public Type ClassType { get; private set; }
- public static Dictionary<GameObject, List<LogEntry>> gameObjectEntries = new Dictionary<GameObject, List<LogEntry>>(100);
- public static List<LogEntry> compileEntries = new List<LogEntry>(100);
- private static int lastCount;
- private static bool entriesDirty;
- private static bool lastCompileFailedState;
- private static double lastUpdatedTime;
- private static readonly Icons.Warnings warnings = new Icons.Warnings();
- static LogEntry() {
- try {
- logEntriesType = ReflectionHelper.FindType("UnityEditorInternal.LogEntries");
- logEntryType = ReflectionHelper.FindType("UnityEditorInternal.LogEntry");
- if (logEntriesType == null)
- logEntriesType = ReflectionHelper.FindType("UnityEditor.LogEntries");
- if (logEntryType == null)
- logEntryType = ReflectionHelper.FindType("UnityEditor.LogEntry");
- ReloadReferences();
- } catch (Exception e) {
- Debug.LogException(e);
- Preferences.ForceDisableButton(new Icons.Warnings());
- }
- Application.logMessageReceived += (logString, stackTrace, type) => MarkEntriesDirty();
- EditorApplication.update += () => {
- try {
- #if UNITY_2017_1_OR_NEWER
- if (!entriesDirty && EditorUtility.scriptCompilationFailed != lastCompileFailedState) {
- lastCompileFailedState = EditorUtility.scriptCompilationFailed;
- MarkEntriesDirty();
- }
- #endif
- if (EditorApplication.timeSinceStartup - lastUpdatedTime > UPDATE_FREQUENCY) {
- if (!entriesDirty) {
- var currentCount = GetLogCount();
- if (lastCount > currentCount) { // Console possibly cleared
- if (Preferences.DebugEnabled)
- Debug.Log("Detected console clear");
- MarkEntriesDirty();
- }
- lastCount = currentCount;
- }
- if (entriesDirty)
- ReloadReferences();
- }
- } catch (Exception e) {
- Debug.LogException(e);
- Preferences.ForceDisableButton(new Icons.Warnings());
- }
- };
- }
- private LogEntry(object nativeEntry, int rowIndex) {
- RowIndex = rowIndex;
- if (nativeEntry.HasField("condition"))
- Condition = nativeEntry.GetInstanceField<string>("condition");
- else if (nativeEntry.HasField("message"))
- Condition = nativeEntry.GetInstanceField<string>("message");
- else
- throw new MissingFieldException("LogEntry doesn't have a message field");
- if (nativeEntry.HasField("errorNum"))
- ErrorNum = nativeEntry.GetInstanceField<int>("errorNum");
- File = nativeEntry.GetInstanceField<string>("file");
- Line = nativeEntry.GetInstanceField<int>("line");
- if (nativeEntry.HasField("column"))
- Column = nativeEntry.GetInstanceField<int>("column");
- Mode = nativeEntry.GetInstanceField<EntryMode>("mode");
- InstanceID = nativeEntry.GetInstanceField<int>("instanceID");
- Identifier = nativeEntry.GetInstanceField<int>("identifier");
- if (InstanceID != 0)
- ObjectReference = EditorUtility.InstanceIDToObject(InstanceID);
- if (ObjectReference)
- Script = ObjectReference as MonoScript;
- if (Script)
- ClassType = Script.GetClass();
- }
- public static void MarkEntriesDirty() {
- if (!entriesDirty && Preferences.Enabled && Preferences.IsButtonEnabled(warnings))
- entriesDirty = true;
- }
- private static void ReloadReferences() {
- if (Preferences.DebugEnabled)
- Debug.Log("Reloading Logs References");
- gameObjectEntries.Clear();
- compileEntries.Clear();
- try {
- var count = logEntriesType.InvokeStaticMethod<int>("StartGettingEntries");
- var nativeEntry = Activator.CreateInstance(logEntryType);
- for (var i = 0; i < count; i++) {
- logEntriesType.InvokeStaticMethod("GetEntryInternal", i, nativeEntry);
- var proxyEntry = new LogEntry(nativeEntry, i);
- var go = proxyEntry.ObjectReference as GameObject;
- if (proxyEntry.ObjectReference && !go) {
- var component = proxyEntry.ObjectReference as Component;
- if (component)
- go = component.gameObject;
- }
- // if(entry.HasMode(EntryMode.ScriptCompileError | EntryMode.ScriptCompileWarning | EntryMode.AssetImportWarning) && entry.ClassType != null)
- // if(!referencedComponents.Any(e => e.ClassType == entry.ClassType))
- if (proxyEntry.ClassType != null)
- compileEntries.Add(proxyEntry);
- if (go)
- if (gameObjectEntries.ContainsKey(go))
- gameObjectEntries[go].Add(proxyEntry);
- else
- gameObjectEntries.Add(go, new List<LogEntry>() { proxyEntry });
- }
- EditorApplication.RepaintHierarchyWindow();
- } catch (Exception e) {
- Debug.LogException(e);
- Preferences.ForceDisableButton(new Icons.Warnings());
- } finally {
- entriesDirty = false;
- lastUpdatedTime = EditorApplication.timeSinceStartup;
- logEntriesType.InvokeStaticMethod("EndGettingEntries");
- }
- }
- public bool HasMode(EntryMode toCheck) {
- return (Mode & toCheck) != 0;
- }
- public void OpenToEdit() {
- logEntriesType.InvokeStaticMethod("RowGotDoubleClicked", RowIndex);
- }
- private static int GetLogCount() {
- return logEntriesType.InvokeStaticMethod<int>("GetCount");
- }
- public override string ToString() {
- return Condition;
- }
- }
- }
|