namespace VRTK.Prefabs.Helpers.SceneConsole { using UnityEngine; using UnityEngine.UI; using System; using Malimbe.PropertySerializationAttribute; using Malimbe.XmlDocumentationAttribute; using Zinnia.Data.Attribute; /// /// The public interface into the SceneConsole Prefab. /// public class SceneConsoleFacade : MonoBehaviour { #region Console Settings /// /// The size of the font the log text is displayed in. /// [Serialized] [field: Header("Console Settings"), DocumentedByXml] public int FontSize { get; set; } = 10; /// /// The of the text for an info log message. /// [Serialized] [field: DocumentedByXml] public Color InfoMessage { get; set; } = Color.black; /// /// The of the text for an assertion log message. /// [Serialized] [field: DocumentedByXml] public Color AssertMessage { get; set; } = Color.black; /// /// The of the text for a warning log message. /// [Serialized] [field: DocumentedByXml] public Color WarningMessage { get; set; } = Color.yellow; /// /// The of the text for an error log message. /// [Serialized] [field: DocumentedByXml] public Color ErrorMessage { get; set; } = Color.red; /// /// The of the text for an exception log message. /// [Serialized] [field: DocumentedByXml] public Color ExceptionMessage { get; set; } = Color.red; /// /// Determines whether to collapse same messages into one message in the log. /// [Serialized] [field: DocumentedByXml] public bool CollapseLog { get; set; } #endregion #region Reference Settings /// /// The console scrollable area. /// [Serialized] [field: Header("Reference Settings"), DocumentedByXml, Restricted] public ScrollRect ScrollWindow { get; protected set; } /// /// The output content . /// [Serialized] [field: DocumentedByXml, Restricted] public RectTransform ConsoleRect { get; protected set; } /// /// The element to output the console to. /// [Serialized] [field: DocumentedByXml, Restricted] public Text ConsoleOutput { get; protected set; } #endregion /// /// The character to use for the line ending. /// protected const string newline = "\n"; /// /// The specified line buffer. /// protected const int lineBuffer = 50; /// /// The current line buffer in use. /// protected int currentBuffer; /// /// The last log message. /// protected string lastMessage; /// /// Clears the current log view of all messages /// public virtual void ClearLog() { if (ConsoleOutput != null) { ConsoleOutput.text = ""; } currentBuffer = 0; lastMessage = ""; } protected virtual void OnEnable() { Application.logMessageReceived += HandleLog; } protected virtual void OnDisable() { Application.logMessageReceived -= HandleLog; if (ConsoleRect != null) { ConsoleRect.sizeDelta = Vector2.zero; } } /// /// Gets a rich text styled message for the given . /// /// The message to style. /// The of the message. /// A rich text styled message. protected virtual string GetMessage(string message, LogType type) { Color color; switch (type) { case LogType.Error: color = ErrorMessage; break; case LogType.Assert: color = AssertMessage; break; case LogType.Warning: color = WarningMessage; break; case LogType.Log: color = InfoMessage; break; case LogType.Exception: color = ExceptionMessage; break; default: throw new ArgumentOutOfRangeException(nameof(type), type, null); } string hexadecimalColorString = ColorUtility.ToHtmlStringRGBA(color); return $"{message}{newline}"; } /// /// Digests the current Unity log stream and outputs it to the provided /// /// The message from the log stream. /// The stacktrace data from the log stream /// The type of the given log message. protected virtual void HandleLog(string message, string stackTrace, LogType type) { if (ConsoleOutput == null || ScrollWindow == null || ConsoleRect == null) { return; } string logOutput = GetMessage(message, type); string consoleOutputText = ConsoleOutput.text; if (currentBuffer >= lineBuffer) { const int halfLineBuffer = lineBuffer / 2; int lookupIndex = 0; int skippedLineCount = 0; while (skippedLineCount < halfLineBuffer && lookupIndex < consoleOutputText.Length) { int newlineIndex = consoleOutputText.IndexOf(newline, lookupIndex, StringComparison.Ordinal); if (newlineIndex == -1) { break; } lookupIndex = newlineIndex + 1; skippedLineCount++; } if (lookupIndex < consoleOutputText.Length) { consoleOutputText = consoleOutputText.Substring(lookupIndex); } currentBuffer = halfLineBuffer; } if (!CollapseLog || lastMessage != logOutput) { consoleOutputText += logOutput; lastMessage = logOutput; } ConsoleOutput.text = consoleOutputText; ConsoleOutput.fontSize = FontSize; ConsoleRect.sizeDelta = new Vector2(ConsoleOutput.preferredWidth, ConsoleOutput.preferredHeight); ScrollWindow.verticalNormalizedPosition = 0; currentBuffer++; } } }