Decompiled source of UnityLogViewer v0.0.4

plugins/UnityLogViewer.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")]
[assembly: AssemblyCompany("UnityLogViewer")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("In-game log viewer for BepInEx")]
[assembly: AssemblyFileVersion("0.0.4.0")]
[assembly: AssemblyInformationalVersion("0.0.4+dc09153a5d65a1d272732f48daae6213985ca691")]
[assembly: AssemblyProduct("UnityLogViewer")]
[assembly: AssemblyTitle("UnityLogViewer")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.4.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace malafein.UnityLogViewer
{
	public class LogViewerUI : MonoBehaviour, ILogListener, IDisposable
	{
		private struct HighlightRule
		{
			public Regex Pattern;

			public string Color;
		}

		private readonly object logLock = new object();

		private bool isVisible = Plugin.ShowWindow.Value;

		private bool isPinned;

		private Rect windowRect;

		private Vector2 scrollPosition;

		private string filterText = "";

		private bool filterDirty = true;

		private readonly List<string> logLines = new List<string>();

		private readonly List<string> filteredLines = new List<string>();

		private bool autoScroll = true;

		private bool pendingScrollToBottom;

		private readonly List<string> renderedLines = new List<string>();

		private bool renderDirty = true;

		private readonly List<HighlightRule> highlightRules = new List<HighlightRule>();

		private bool highlightsDirty = true;

		private const float ColorCheckDelay = 1f;

		private float colorCheckAt;

		private bool clearRequested;

		private const int WindowID = 99701;

		private const float WindowHeaderHeight = 98f;

		private const float PinnedHeaderHeight = 26f;

		private float lineHeight = 20f;

		private int scrollFirstVisible;

		private int scrollLastVisible;

		private bool isResizing;

		private const float ResizeHandleSize = 20f;

		private const float MinWidth = 400f;

		private const float MinHeight = 300f;

		private Texture2D bgTexture;

		private int lastOpacity = -1;

		private GUIStyle logStyle;

		private GUIStyle closeButtonStyle;

		private GUIStyle pinButtonStyle;

		private GUIStyle pinnedWindowStyle;

		private bool stylesInitialized;

		private Rect lastSavedRect;

		private readonly List<string> validFontNames = new List<string>();

		private readonly List<Font> validFonts = new List<Font>();

		private const string FontSample = "[Info] AaBbCc 0123 {}[]";

		private readonly List<GUIStyle> fontSampleStyles = new List<GUIStyle>();

		private GUIStyle fontRowStyle;

		private GUIStyle fontNameStyle;

		private Texture2D fontRowTexture;

		private Texture2D fontRowHoverTexture;

		private int fontSelectorIndex;

		private bool fontListOpen;

		private bool fontListToggleRequested;

		private int pendingFontIndex = -1;

		private Vector2 fontListScrollPos;

		public LogLevel LogLevelFilter => (LogLevel)63;

		private int MaxLines => Plugin.BufferSize.Value;

		private void Awake()
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			windowRect = new Rect((float)Plugin.WindowX.Value, (float)Plugin.WindowY.Value, (float)Plugin.WindowWidth.Value, (float)Plugin.WindowHeight.Value);
			lastSavedRect = windowRect;
			filterText = Plugin.Filter.Value ?? "";
			isPinned = Plugin.Pinned.Value;
			Plugin.Filter.SettingChanged += delegate
			{
				filterText = Plugin.Filter.Value ?? "";
				filterDirty = true;
			};
			Plugin.ShowWindow.SettingChanged += delegate
			{
				isVisible = Plugin.ShowWindow.Value;
			};
			Plugin.Pinned.SettingChanged += delegate
			{
				isPinned = Plugin.Pinned.Value;
			};
			Plugin.WindowX.SettingChanged += delegate
			{
				((Rect)(ref windowRect)).x = Plugin.WindowX.Value;
			};
			Plugin.WindowY.SettingChanged += delegate
			{
				((Rect)(ref windowRect)).y = Plugin.WindowY.Value;
			};
			Plugin.WindowWidth.SettingChanged += delegate
			{
				((Rect)(ref windowRect)).width = Plugin.WindowWidth.Value;
			};
			Plugin.WindowHeight.SettingChanged += delegate
			{
				((Rect)(ref windowRect)).height = Plugin.WindowHeight.Value;
			};
			for (int num = 0; num < 8; num++)
			{
				Plugin.HighlightPattern[num].SettingChanged += delegate
				{
					highlightsDirty = true;
					renderDirty = true;
				};
				Plugin.HighlightColor[num].SettingChanged += delegate
				{
					highlightsDirty = true;
					renderDirty = true;
					colorCheckAt = Time.unscaledTime + 1f;
				};
			}
			Plugin.FontName.SettingChanged += delegate
			{
				int num2 = validFontNames.IndexOf(Plugin.FontName.Value);
				if (num2 >= 0)
				{
					fontSelectorIndex = num2;
				}
			};
			Logger.Listeners.Add((ILogListener)(object)this);
		}

		private void BuildValidFontList()
		{
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Expected O, but got Unknown
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Expected O, but got Unknown
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Expected O, but got Unknown
			validFontNames.Clear();
			validFontNames.Add("");
			validFonts.Clear();
			validFonts.Add(null);
			string[] oSInstalledFontNames = Font.GetOSInstalledFontNames();
			Array.Sort(oSInstalledFontNames, (IComparer<string>?)StringComparer.OrdinalIgnoreCase);
			Logger.Listeners.Remove((ILogListener)(object)this);
			string[] array = oSInstalledFontNames;
			foreach (string text in array)
			{
				bool warned = false;
				LogCallback val = delegate(string msg, string _, LogType type)
				{
					//IL_0000: Unknown result type (might be due to invalid IL or missing references)
					//IL_0002: Invalid comparison between Unknown and I4
					//IL_0004: Unknown result type (might be due to invalid IL or missing references)
					if ((int)type == 2 || (int)type == 0)
					{
						warned = true;
					}
				};
				Application.logMessageReceived += val;
				Font val2 = Font.CreateDynamicFontFromOSFont(text, 13);
				new GUIStyle(GUI.skin.label)
				{
					font = val2,
					fontSize = 13
				}.CalcSize(new GUIContent("Ag"));
				Application.logMessageReceived -= val;
				if (!warned)
				{
					validFontNames.Add(text);
					validFonts.Add(val2);
				}
			}
			Logger.Listeners.Add((ILogListener)(object)this);
			fontSelectorIndex = Math.Max(0, validFontNames.IndexOf(Plugin.FontName.Value));
			StringBuilder stringBuilder = new StringBuilder();
			for (int num = 1; num < validFontNames.Count; num++)
			{
				if (num > 1)
				{
					stringBuilder.Append(", ");
				}
				stringBuilder.Append(validFontNames[num]);
			}
			Plugin.Log.LogInfo((object)((validFontNames.Count > 1) ? $"[UnityLogViewer] {validFontNames.Count - 1} usable font(s): {stringBuilder}" : "[UnityLogViewer] No usable OS fonts found; using default UI font."));
		}

		public void LogEvent(object sender, LogEventArgs eventArgs)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			string text = $"[{eventArgs.Level}] [{eventArgs.Source.SourceName}] ";
			lock (logLock)
			{
				logLines.Add(text + eventArgs.Data);
				if (logLines.Count > MaxLines)
				{
					logLines.RemoveRange(0, logLines.Count - MaxLines);
				}
				filterDirty = true;
				if (autoScroll)
				{
					pendingScrollToBottom = true;
				}
			}
		}

		public void Dispose()
		{
		}

		private void Update()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			KeyboardShortcut value = Plugin.ToggleShortcut.Value;
			if (((KeyboardShortcut)(ref value)).IsDown())
			{
				Plugin.ShowWindow.Value = !Plugin.ShowWindow.Value;
			}
			if (colorCheckAt >= 0f && Time.unscaledTime >= colorCheckAt)
			{
				colorCheckAt = -1f;
				WarnInvalidHighlightColors();
			}
			if (!isVisible)
			{
				fontListOpen = false;
				fontListToggleRequested = false;
				return;
			}
			if (fontListToggleRequested)
			{
				fontListOpen = !fontListOpen;
				fontListToggleRequested = false;
			}
			if (pendingFontIndex >= 0)
			{
				ApplyFont(pendingFontIndex);
				pendingFontIndex = -1;
				fontListOpen = false;
			}
			if (clearRequested)
			{
				lock (logLock)
				{
					logLines.Clear();
				}
				filteredLines.Clear();
				renderedLines.Clear();
				scrollPosition = Vector2.zero;
				clearRequested = false;
			}
			if (filterDirty)
			{
				RebuildFilteredLines();
			}
			if (renderDirty)
			{
				RebuildRenderedLines();
			}
			if (pendingScrollToBottom)
			{
				scrollPosition.y = 1E+09f;
				pendingScrollToBottom = false;
			}
		}

		private void RebuildHighlightRules()
		{
			highlightRules.Clear();
			for (int i = 0; i < 8; i++)
			{
				string value = Plugin.HighlightPattern[i].Value;
				string text = Plugin.HighlightColor[i].Value?.Trim();
				if (!string.IsNullOrEmpty(value) && !string.IsNullOrEmpty(text) && IsValidColor(text))
				{
					try
					{
						highlightRules.Add(new HighlightRule
						{
							Pattern = new Regex(value, RegexOptions.IgnoreCase),
							Color = text
						});
					}
					catch (ArgumentException)
					{
					}
				}
			}
			highlightsDirty = false;
		}

		private static bool IsValidColor(string color)
		{
			Color val = default(Color);
			return ColorUtility.TryParseHtmlString(color, ref val);
		}

		private void WarnInvalidHighlightColors()
		{
			for (int i = 0; i < 8; i++)
			{
				string text = Plugin.HighlightColor[i].Value?.Trim();
				if (!string.IsNullOrEmpty(text) && !string.IsNullOrEmpty(Plugin.HighlightPattern[i].Value) && !IsValidColor(text))
				{
					Plugin.Log.LogWarning((object)$"Highlight{i + 1}Color \"{text}\" isn't a known colour name or #RRGGBB; rule skipped.");
				}
			}
		}

		private void RebuildFilteredLines()
		{
			filteredLines.Clear();
			lock (logLock)
			{
				if (string.IsNullOrEmpty(filterText))
				{
					filteredLines.AddRange(logLines);
				}
				else
				{
					try
					{
						Regex regex = new Regex(filterText, RegexOptions.IgnoreCase);
						for (int i = 0; i < logLines.Count; i++)
						{
							if (regex.IsMatch(logLines[i]))
							{
								filteredLines.Add(logLines[i]);
							}
						}
					}
					catch (ArgumentException)
					{
						for (int j = 0; j < logLines.Count; j++)
						{
							if (logLines[j].IndexOf(filterText, StringComparison.OrdinalIgnoreCase) >= 0)
							{
								filteredLines.Add(logLines[j]);
							}
						}
					}
				}
				filterDirty = false;
			}
			renderDirty = true;
		}

		private static string EscapeRichText(string text)
		{
			return text.Replace("<", "<\u200b");
		}

		private string GetColorForLine(string line)
		{
			for (int i = 0; i < highlightRules.Count; i++)
			{
				if (highlightRules[i].Pattern.IsMatch(line))
				{
					return highlightRules[i].Color;
				}
			}
			return null;
		}

		private void RebuildRenderedLines()
		{
			if (highlightsDirty)
			{
				RebuildHighlightRules();
			}
			renderedLines.Clear();
			for (int i = 0; i < filteredLines.Count; i++)
			{
				string text = EscapeRichText(filteredLines[i]);
				string colorForLine = GetColorForLine(filteredLines[i]);
				string[] array = text.Split(new char[1] { '\n' });
				for (int j = 0; j < array.Length; j++)
				{
					string text2 = array[j].TrimEnd(new char[1] { '\r' });
					renderedLines.Add((colorForLine != null) ? ("<color=" + colorForLine + ">" + text2 + "</color>") : text2);
				}
			}
			renderDirty = false;
		}

		private static Texture2D MakeSolidTexture(Color32 color)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			Texture2D val = new Texture2D(1, 1);
			val.SetPixel(0, 0, Color32.op_Implicit(color));
			val.Apply();
			return val;
		}

		private Texture2D MakeBgTexture(int opacity)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected O, but got Unknown
			byte b = (byte)(opacity * 255 / 100);
			Texture2D val = new Texture2D(1, 1);
			val.SetPixel(0, 0, Color32.op_Implicit(new Color32((byte)0, (byte)0, (byte)0, b)));
			val.Apply();
			return val;
		}

		private void InitStyles()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Expected O, but got Unknown
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Expected O, but got Unknown
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Expected O, but got Unknown
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Expected O, but got Unknown
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Expected O, but got Unknown
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Expected O, but got Unknown
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Expected O, but got Unknown
			//IL_0168: Expected O, but got Unknown
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Expected O, but got Unknown
			//IL_01ab: Expected O, but got Unknown
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: Expected O, but got Unknown
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0204: Unknown result type (might be due to invalid IL or missing references)
			//IL_0209: Unknown result type (might be due to invalid IL or missing references)
			//IL_0213: Expected O, but got Unknown
			//IL_0218: Expected O, but got Unknown
			BuildValidFontList();
			GUIStyle val = new GUIStyle(GUI.skin.label)
			{
				richText = true,
				wordWrap = false,
				fontSize = 13
			};
			val.normal.textColor = Color.white;
			val.padding = new RectOffset(4, 4, 2, 2);
			val.margin = new RectOffset(0, 0, 0, 0);
			val.font = validFonts[fontSelectorIndex];
			logStyle = val;
			lineHeight = logStyle.CalcSize(new GUIContent("Ag")).y;
			closeButtonStyle = new GUIStyle(GUI.skin.button)
			{
				fontSize = 14,
				fontStyle = (FontStyle)1,
				alignment = (TextAnchor)4
			};
			pinButtonStyle = new GUIStyle(GUI.skin.button)
			{
				fontSize = 12,
				alignment = (TextAnchor)4
			};
			fontRowTexture = MakeSolidTexture(new Color32((byte)38, (byte)38, (byte)38, byte.MaxValue));
			fontRowHoverTexture = MakeSolidTexture(new Color32((byte)70, (byte)70, (byte)70, byte.MaxValue));
			GUIStyle val2 = new GUIStyle();
			val2.normal.background = fontRowTexture;
			val2.hover.background = fontRowHoverTexture;
			val2.active.background = fontRowHoverTexture;
			val2.margin = new RectOffset(0, 0, 1, 1);
			fontRowStyle = val2;
			GUIStyle val3 = new GUIStyle(GUI.skin.label)
			{
				fontSize = 13,
				alignment = (TextAnchor)3
			};
			val3.normal.textColor = Color.white;
			val3.padding = new RectOffset(8, 4, 0, 0);
			fontNameStyle = val3;
			fontSampleStyles.Clear();
			for (int i = 0; i < validFonts.Count; i++)
			{
				fontSampleStyles.Add(new GUIStyle(fontNameStyle)
				{
					font = validFonts[i]
				});
			}
			pinnedWindowStyle = new GUIStyle(GUI.skin.box)
			{
				padding = new RectOffset(4, 4, 4, 4)
			};
			stylesInitialized = true;
		}

		private void UpdateBgTexture()
		{
			int value = Plugin.BackgroundOpacity.Value;
			if (value != lastOpacity)
			{
				if ((Object)(object)bgTexture != (Object)null)
				{
					Object.Destroy((Object)(object)bgTexture);
				}
				bgTexture = MakeBgTexture(value);
				lastOpacity = value;
				if (stylesInitialized)
				{
					pinnedWindowStyle.normal.background = bgTexture;
				}
			}
		}

		private void OnGUI()
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Expected O, but got Unknown
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			if (isVisible)
			{
				if (!stylesInitialized)
				{
					InitStyles();
				}
				UpdateBgTexture();
				ClampToScreen();
				if (isPinned)
				{
					DrawPinnedWindow();
				}
				else
				{
					Color backgroundColor = GUI.backgroundColor;
					float num = (float)Plugin.BackgroundOpacity.Value / 100f;
					GUI.backgroundColor = new Color(backgroundColor.r, backgroundColor.g, backgroundColor.b, num);
					windowRect = GUI.Window(99701, windowRect, new WindowFunction(DrawWindow), "Log Viewer");
					GUI.backgroundColor = backgroundColor;
					HandleResize();
				}
				SaveWindowRectIfChanged();
			}
		}

		private void ClampToScreen()
		{
			((Rect)(ref windowRect)).width = Mathf.Min(((Rect)(ref windowRect)).width, (float)Screen.width);
			((Rect)(ref windowRect)).height = Mathf.Min(((Rect)(ref windowRect)).height, (float)Screen.height);
			((Rect)(ref windowRect)).x = Mathf.Clamp(((Rect)(ref windowRect)).x, 0f, (float)Screen.width - ((Rect)(ref windowRect)).width);
			((Rect)(ref windowRect)).y = Mathf.Clamp(((Rect)(ref windowRect)).y, 0f, (float)Screen.height - ((Rect)(ref windowRect)).height);
		}

		private void SaveWindowRectIfChanged()
		{
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			if (!isResizing && GUIUtility.hotControl == 0 && (((Rect)(ref windowRect)).x != ((Rect)(ref lastSavedRect)).x || ((Rect)(ref windowRect)).y != ((Rect)(ref lastSavedRect)).y || ((Rect)(ref windowRect)).width != ((Rect)(ref lastSavedRect)).width || ((Rect)(ref windowRect)).height != ((Rect)(ref lastSavedRect)).height))
			{
				ConfigFile configFile = ((ConfigEntryBase)Plugin.WindowX).ConfigFile;
				bool saveOnConfigSet = configFile.SaveOnConfigSet;
				configFile.SaveOnConfigSet = false;
				Plugin.WindowX.Value = (int)((Rect)(ref windowRect)).x;
				Plugin.WindowY.Value = (int)((Rect)(ref windowRect)).y;
				Plugin.WindowWidth.Value = (int)((Rect)(ref windowRect)).width;
				Plugin.WindowHeight.Value = (int)((Rect)(ref windowRect)).height;
				configFile.SaveOnConfigSet = saveOnConfigSet;
				configFile.Save();
				lastSavedRect = windowRect;
			}
		}

		private void DrawVirtualScrollContent(float viewHeight)
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Invalid comparison between Unknown and I4
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			float num = lineHeight;
			int count = renderedLines.Count;
			float num2 = (float)count * num;
			float num3 = Mathf.Max(0f, num2 - viewHeight + 30f);
			scrollPosition.y = Mathf.Min(scrollPosition.y, num3);
			if ((int)Event.current.type == 8)
			{
				scrollFirstVisible = Mathf.Max(0, (int)(scrollPosition.y / num) - 1);
				scrollLastVisible = Mathf.Min(count - 1, scrollFirstVisible + (int)(viewHeight / num) + 3);
			}
			scrollPosition = GUILayout.BeginScrollView(scrollPosition, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(viewHeight) });
			if (scrollFirstVisible > 0)
			{
				GUILayout.Space((float)scrollFirstVisible * num);
			}
			for (int i = scrollFirstVisible; i <= scrollLastVisible; i++)
			{
				GUILayout.Label(renderedLines[i], logStyle, Array.Empty<GUILayoutOption>());
			}
			int num4 = count - scrollLastVisible - 1;
			if (num4 > 0)
			{
				GUILayout.Space((float)num4 * num);
			}
			GUILayout.EndScrollView();
		}

		private void DrawPinnedWindow()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			pinnedWindowStyle.normal.background = bgTexture;
			GUILayout.BeginArea(windowRect, pinnedWindowStyle);
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.FlexibleSpace();
			if (GUILayout.Button("□", pinButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(26f),
				GUILayout.Height(18f)
			}))
			{
				isPinned = false;
				Plugin.Pinned.Value = false;
			}
			GUILayout.EndHorizontal();
			DrawVirtualScrollContent(Mathf.Max(50f, ((Rect)(ref windowRect)).height - 26f));
			GUILayout.EndArea();
		}

		private void ApplyFont(int index)
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Expected O, but got Unknown
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			fontSelectorIndex = index;
			Plugin.FontName.Value = validFontNames[index];
			logStyle.font = validFonts[index];
			lineHeight = logStyle.CalcSize(new GUIContent("Ag")).y;
			renderDirty = true;
		}

		private void DrawWindow(int windowID)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_032d: Unknown result type (might be due to invalid IL or missing references)
			if (GUI.Button(new Rect(((Rect)(ref windowRect)).width - 25f, 2f, 22f, 18f), "X", closeButtonStyle))
			{
				Plugin.ShowWindow.Value = false;
				return;
			}
			if (GUI.Button(new Rect(((Rect)(ref windowRect)).width - 53f, 2f, 26f, 18f), "■", pinButtonStyle))
			{
				isPinned = true;
				Plugin.Pinned.Value = true;
				return;
			}
			if (validFontNames.Count > 1)
			{
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				GUILayout.Label("Font:", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(40f) });
				string obj = ((fontSelectorIndex > 0) ? validFontNames[fontSelectorIndex] : "(default)");
				string text = (fontListOpen ? " ▲" : " ▼");
				if (GUILayout.Button(obj + text, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) }))
				{
					fontListToggleRequested = true;
				}
				GUILayout.EndHorizontal();
			}
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label("Filter:", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(40f) });
			string text2 = GUILayout.TextField(filterText, Array.Empty<GUILayoutOption>());
			if (text2 != filterText)
			{
				filterText = text2;
				filterDirty = true;
			}
			if (GUILayout.Button("×", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(28f) }))
			{
				filterText = "";
				filterDirty = true;
			}
			if (GUILayout.Button("Clear", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(50f) }))
			{
				clearRequested = true;
			}
			GUILayout.EndHorizontal();
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			int count;
			lock (logLock)
			{
				count = logLines.Count;
			}
			GUILayout.Label($"{filteredLines.Count} / {count} lines", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(150f) });
			GUILayout.FlexibleSpace();
			bool flag = GUILayout.Toggle(autoScroll, "Auto-scroll", Array.Empty<GUILayoutOption>());
			if (flag != autoScroll)
			{
				autoScroll = flag;
				if (autoScroll)
				{
					pendingScrollToBottom = true;
				}
			}
			GUILayout.EndHorizontal();
			float num = ((validFontNames.Count > 1) ? 98f : 72f);
			float viewHeight = Mathf.Max(50f, ((Rect)(ref windowRect)).height - num);
			if (fontListOpen)
			{
				DrawFontList(viewHeight);
			}
			else
			{
				DrawVirtualScrollContent(viewHeight);
			}
			GUI.Label(new Rect(((Rect)(ref windowRect)).width - 20f, ((Rect)(ref windowRect)).height - 20f, 20f, 20f), "◢");
			GUI.DragWindow(new Rect(0f, 0f, ((Rect)(ref windowRect)).width - 58f, 25f));
		}

		private void DrawFontList(float viewHeight)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			Color backgroundColor = GUI.backgroundColor;
			GUI.backgroundColor = Color.white;
			float num = Mathf.Round(Mathf.Max(22f, lineHeight + 4f));
			fontListScrollPos = GUILayout.BeginScrollView(fontListScrollPos, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(viewHeight) });
			Rect val = default(Rect);
			for (int i = 0; i < validFontNames.Count; i++)
			{
				Rect rect = GUILayoutUtility.GetRect(0f, num, fontRowStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
				if (GUI.Button(rect, GUIContent.none, fontRowStyle))
				{
					pendingFontIndex = i;
				}
				((Rect)(ref val))..ctor(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, Mathf.Min(220f, ((Rect)(ref rect)).width * 0.4f), ((Rect)(ref rect)).height);
				Rect val2 = new Rect(((Rect)(ref val)).xMax, ((Rect)(ref rect)).y, ((Rect)(ref rect)).width - ((Rect)(ref val)).width, ((Rect)(ref rect)).height);
				GUI.Label(val, (i == 0) ? "(default)" : validFontNames[i], fontNameStyle);
				GUI.Label(val2, "[Info] AaBbCc 0123 {}[]", fontSampleStyles[i]);
			}
			GUILayout.EndScrollView();
			GUI.backgroundColor = backgroundColor;
		}

		private void HandleResize()
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Invalid comparison between Unknown and I4
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Invalid comparison between Unknown and I4
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Invalid comparison between Unknown and I4
			Event current = Event.current;
			Rect val = default(Rect);
			((Rect)(ref val))..ctor(((Rect)(ref windowRect)).x + ((Rect)(ref windowRect)).width - 20f, ((Rect)(ref windowRect)).y + ((Rect)(ref windowRect)).height - 20f, 20f, 20f);
			if ((int)current.type == 0 && ((Rect)(ref val)).Contains(current.mousePosition))
			{
				isResizing = true;
				current.Use();
			}
			if (isResizing && ((int)current.type == 3 || (int)current.type == 1))
			{
				((Rect)(ref windowRect)).width = Mathf.Max(400f, current.mousePosition.x - ((Rect)(ref windowRect)).x);
				((Rect)(ref windowRect)).height = Mathf.Max(300f, current.mousePosition.y - ((Rect)(ref windowRect)).y);
				if ((int)current.type == 1)
				{
					isResizing = false;
				}
				current.Use();
			}
		}

		private void OnDestroy()
		{
			Logger.Listeners.Remove((ILogListener)(object)this);
			if ((Object)(object)bgTexture != (Object)null)
			{
				Object.Destroy((Object)(object)bgTexture);
			}
			if ((Object)(object)fontRowTexture != (Object)null)
			{
				Object.Destroy((Object)(object)fontRowTexture);
			}
			if ((Object)(object)fontRowHoverTexture != (Object)null)
			{
				Object.Destroy((Object)(object)fontRowHoverTexture);
			}
		}
	}
	[BepInPlugin("com.malafein.unitylogviewer", "UnityLogViewer", "0.0.4")]
	public class Plugin : BaseUnityPlugin
	{
		internal class ConfigurationManagerAttributes
		{
			public int? Order;
		}

		public const string ModGUID = "com.malafein.unitylogviewer";

		public const string ModName = "UnityLogViewer";

		public const string ModVersion = "0.0.4";

		public static ConfigEntry<KeyboardShortcut> ToggleShortcut;

		public static ConfigEntry<bool> ShowWindow;

		public static ConfigEntry<string> Filter;

		public static ConfigEntry<int> BackgroundOpacity;

		public static ConfigEntry<bool> Pinned;

		public static ConfigEntry<int> BufferSize;

		public static ConfigEntry<string> FontName;

		public static ConfigEntry<int> WindowX;

		public static ConfigEntry<int> WindowY;

		public static ConfigEntry<int> WindowWidth;

		public static ConfigEntry<int> WindowHeight;

		public const int HighlightSlotCount = 8;

		public static ConfigEntry<string>[] HighlightPattern = new ConfigEntry<string>[8];

		public static ConfigEntry<string>[] HighlightColor = new ConfigEntry<string>[8];

		internal static ManualLogSource Log;

		private void Awake()
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Expected O, but got Unknown
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Expected O, but got Unknown
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Expected O, but got Unknown
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Expected O, but got Unknown
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Expected O, but got Unknown
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: Expected O, but got Unknown
			//IL_0200: Unknown result type (might be due to invalid IL or missing references)
			//IL_020a: Expected O, but got Unknown
			//IL_0242: Unknown result type (might be due to invalid IL or missing references)
			//IL_024c: Expected O, but got Unknown
			//IL_0284: Unknown result type (might be due to invalid IL or missing references)
			//IL_028e: Expected O, but got Unknown
			//IL_02c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d3: Expected O, but got Unknown
			//IL_030e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0318: Expected O, but got Unknown
			//IL_040d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0417: Expected O, but got Unknown
			//IL_046a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0474: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			((BaseUnityPlugin)this).Logger.LogInfo((object)"UnityLogViewer 0.0.4 is loading...");
			ShowWindow = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ShowWindow", false, new ConfigDescription("Toggle the log viewer window on/off. Use this if the hotkey doesn't work with your game's input system.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 65
				}
			}));
			ToggleShortcut = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("General", "ToggleShortcut", new KeyboardShortcut((KeyCode)288, Array.Empty<KeyCode>()), new ConfigDescription("Keyboard shortcut to toggle log view.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 60
				}
			}));
			Filter = ((BaseUnityPlugin)this).Config.Bind<string>("General", "Filter", "", new ConfigDescription("Optional filter, supports regular expressions.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 50
				}
			}));
			FontName = ((BaseUnityPlugin)this).Config.Bind<string>("General", "FontName", "", new ConfigDescription("Font to use for log text. Leave empty for the default UI font. Check the BepInEx log at startup for a list of fonts available on this system.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 45
				}
			}));
			Pinned = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Pinned", false, new ConfigDescription("Pin the log view in place. Hides window decorations and disables interaction.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 40
				}
			}));
			BufferSize = ((BaseUnityPlugin)this).Config.Bind<int>("General", "BufferSize", 500, new ConfigDescription("Maximum number of log lines to keep in the buffer.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(100, 5000), new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 20
				}
			}));
			BackgroundOpacity = ((BaseUnityPlugin)this).Config.Bind<int>("General", "BackgroundOpacity", 80, new ConfigDescription("Background opacity of the log view window (0-100).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 10
				}
			}));
			WindowX = ((BaseUnityPlugin)this).Config.Bind<int>("Window", "WindowX", 40, new ConfigDescription("Horizontal position of the log viewer window.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 40
				}
			}));
			WindowY = ((BaseUnityPlugin)this).Config.Bind<int>("Window", "WindowY", 40, new ConfigDescription("Vertical position of the log viewer window.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 30
				}
			}));
			WindowWidth = ((BaseUnityPlugin)this).Config.Bind<int>("Window", "WindowWidth", 900, new ConfigDescription("Width of the log viewer window.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 20
				}
			}));
			WindowHeight = ((BaseUnityPlugin)this).Config.Bind<int>("Window", "WindowHeight", 300, new ConfigDescription("Height of the log viewer window.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 10
				}
			}));
			string[] array = new string[8] { "\\[ERROR\\]|\\[FATAL\\]", "\\[WARNING\\]", "\\[DEBUG\\]|\\[DBG\\]", "\\[INFO\\]", "", "", "", "" };
			string[] array2 = new string[8] { "red", "yellow", "cyan", "white", "", "", "", "" };
			for (int i = 0; i < 8; i++)
			{
				int num = i + 1;
				int num2 = (8 - i) * 2;
				HighlightPattern[i] = ((BaseUnityPlugin)this).Config.Bind<string>("Highlighting", $"Highlight{num}Pattern", array[i], new ConfigDescription($"Regex pattern for highlight rule {num}. Leave empty to disable.", (AcceptableValueBase)null, new object[1]
				{
					new ConfigurationManagerAttributes
					{
						Order = num2
					}
				}));
				HighlightColor[i] = ((BaseUnityPlugin)this).Config.Bind<string>("Highlighting", $"Highlight{num}Color", array2[i], new ConfigDescription($"Color for highlight rule {num} (e.g. red, yellow, cyan, green, blue, magenta, orange, white, or #RRGGBB hex). Rules with an unknown color are skipped.", (AcceptableValueBase)null, new object[1]
				{
					new ConfigurationManagerAttributes
					{
						Order = num2 - 1
					}
				}));
			}
			if (!Application.isBatchMode)
			{
				((Component)this).gameObject.AddComponent<LogViewerUI>();
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)"UnityLogViewer loaded!");
		}
	}
}