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;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 |