180 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			C#
		
	
	
	
			
		
		
	
	
			180 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			C#
		
	
	
	
| namespace SRDebugger.Services.Implementation
 | |
| {
 | |
|     using SRF.Service;
 | |
|     using UnityEngine;
 | |
| 
 | |
|     [Service(typeof (IConsoleService))]
 | |
|     public class StandardConsoleService : IConsoleService
 | |
|     {
 | |
|         private readonly bool _collapseEnabled;
 | |
|         private bool _hasCleared;
 | |
| 
 | |
|         private readonly CircularBuffer<ConsoleEntry> _allConsoleEntries;
 | |
|         private CircularBuffer<ConsoleEntry> _consoleEntries;
 | |
|         private readonly object _threadLock = new object();
 | |
| 
 | |
|         public StandardConsoleService()
 | |
|         {
 | |
|             Application.logMessageReceivedThreaded += UnityLogCallback;
 | |
| 
 | |
|             SRServiceManager.RegisterService<IConsoleService>(this);
 | |
|             _collapseEnabled = Settings.Instance.CollapseDuplicateLogEntries;
 | |
|             _allConsoleEntries = new CircularBuffer<ConsoleEntry>(Settings.Instance.MaximumConsoleEntries);
 | |
|         }
 | |
| 
 | |
|         public int ErrorCount { get; private set; }
 | |
|         public int WarningCount { get; private set; }
 | |
|         public int InfoCount { get; private set; }
 | |
| 
 | |
|         public event ConsoleUpdatedEventHandler Updated;
 | |
|         public event ConsoleUpdatedEventHandler Error;
 | |
| 
 | |
|         public IReadOnlyList<ConsoleEntry> Entries
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 if (!_hasCleared)
 | |
|                 {
 | |
|                     return _allConsoleEntries;
 | |
|                 }
 | |
| 
 | |
|                 return _consoleEntries;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public IReadOnlyList<ConsoleEntry> AllEntries
 | |
|         {
 | |
|             get { return _allConsoleEntries; }
 | |
|         }
 | |
| 
 | |
|         public void Clear()
 | |
|         {
 | |
|             lock (_threadLock)
 | |
|             {
 | |
|                 _hasCleared = true;
 | |
| 
 | |
|                 if (_consoleEntries == null)
 | |
|                 {
 | |
|                     _consoleEntries = new CircularBuffer<ConsoleEntry>(Settings.Instance.MaximumConsoleEntries);
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     _consoleEntries.Clear();
 | |
|                 }
 | |
| 
 | |
|                 ErrorCount = WarningCount = InfoCount = 0;
 | |
|             }
 | |
| 
 | |
|             OnUpdated();
 | |
|         }
 | |
| 
 | |
|         protected void OnEntryAdded(ConsoleEntry entry)
 | |
|         {
 | |
|             if (_hasCleared)
 | |
|             {
 | |
|                 // Decrement counters if adding this entry will push another
 | |
|                 // entry from the buffer.
 | |
|                 if (_consoleEntries.IsFull)
 | |
|                 {
 | |
|                     AdjustCounter(_consoleEntries.Front().LogType, -1);
 | |
|                     _consoleEntries.PopFront();
 | |
|                 }
 | |
| 
 | |
|                 _consoleEntries.PushBack(entry);
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 if (_allConsoleEntries.IsFull)
 | |
|                 {
 | |
|                     AdjustCounter(_allConsoleEntries.Front().LogType, -1);
 | |
|                     _allConsoleEntries.PopFront();
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             _allConsoleEntries.PushBack(entry);
 | |
|             OnUpdated();
 | |
|         }
 | |
| 
 | |
|         protected void OnEntryDuplicated(ConsoleEntry entry)
 | |
|         {
 | |
|             entry.Count++;
 | |
|             OnUpdated();
 | |
| 
 | |
|             // If has cleared, add this entry again for the current list
 | |
|             if (_hasCleared && _consoleEntries.Count == 0)
 | |
|             {
 | |
|                 OnEntryAdded(new ConsoleEntry(entry) {Count = 1});
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         private void OnUpdated()
 | |
|         {
 | |
|             if (Updated != null)
 | |
|             {
 | |
|                 try
 | |
|                 {
 | |
|                     Updated(this);
 | |
|                 }
 | |
|                 catch {}
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         private void UnityLogCallback(string condition, string stackTrace, LogType type)
 | |
|         {                
 | |
|             //if (condition.StartsWith("[SRConsole]"))
 | |
|             //    return;
 | |
| 
 | |
|             lock (_threadLock)
 | |
|             {
 | |
|                 var prevMessage = _collapseEnabled && _allConsoleEntries.Count > 0
 | |
|                     ? _allConsoleEntries[_allConsoleEntries.Count - 1]
 | |
|                     : null;
 | |
| 
 | |
|                 AdjustCounter(type, 1);
 | |
| 
 | |
|                 if (prevMessage != null && prevMessage.LogType == type && prevMessage.Message == condition &&
 | |
|                     prevMessage.StackTrace == stackTrace)
 | |
|                 {
 | |
|                     OnEntryDuplicated(prevMessage);
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     var newEntry = new ConsoleEntry
 | |
|                     {
 | |
|                         LogType = type,
 | |
|                         StackTrace = stackTrace,
 | |
|                         Message = condition
 | |
|                     };
 | |
| 
 | |
|                     OnEntryAdded(newEntry);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         private void AdjustCounter(LogType type, int amount)
 | |
|         {
 | |
|             switch (type)
 | |
|             {
 | |
|                 case LogType.Assert:
 | |
|                 case LogType.Error:
 | |
|                 case LogType.Exception:
 | |
|                     ErrorCount += amount;
 | |
| 
 | |
|                     if (Error != null)
 | |
|                     {
 | |
|                         Error.Invoke(this);
 | |
|                     }
 | |
|                     break;
 | |
| 
 | |
|                 case LogType.Warning:
 | |
|                     WarningCount += amount;
 | |
|                     break;
 | |
| 
 | |
|                 case LogType.Log:
 | |
|                     InfoCount += amount;
 | |
|                     break;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| }
 |