2281 lines
60 KiB
C#
2281 lines
60 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Reflection;
|
|
using UnityEngine;
|
|
|
|
namespace DebuggingEssentials
|
|
{
|
|
[DefaultExecutionOrder(-4000000)]
|
|
[ConsoleAlias("console")]
|
|
public class RuntimeConsole : MonoBehaviour
|
|
{
|
|
public delegate void RemoteCommand(string command);
|
|
|
|
public class StringDictionarySorted
|
|
{
|
|
public Dictionary<string, CommandData> lookup = new Dictionary<string, CommandData>();
|
|
|
|
public string[] names;
|
|
|
|
public void Sort()
|
|
{
|
|
names = new string[lookup.Count];
|
|
lookup.Keys.CopyTo(names, 0);
|
|
Array.Sort(names);
|
|
}
|
|
|
|
public void Clear()
|
|
{
|
|
lookup.Clear();
|
|
names = null;
|
|
}
|
|
}
|
|
|
|
public enum MemberType
|
|
{
|
|
Method = 0,
|
|
Property = 1,
|
|
Field = 2,
|
|
Delegate = 3
|
|
}
|
|
|
|
public struct CommandData
|
|
{
|
|
public static CommandData empty;
|
|
|
|
public ConsoleCommand consoleCommand;
|
|
|
|
public object obj;
|
|
|
|
public bool isStatic;
|
|
|
|
public string syntax;
|
|
|
|
public MemberType memberType;
|
|
|
|
public MemberInfo member;
|
|
|
|
public ParameterInfo[] paramInfos;
|
|
|
|
private object[] args;
|
|
|
|
public CommandData(ConsoleCommand consoleCommand, object obj, string syntax, MemberType memberType, MemberInfo member, ParameterInfo[] paramInfos, bool isStatic)
|
|
{
|
|
this.consoleCommand = consoleCommand;
|
|
this.obj = obj;
|
|
this.syntax = syntax;
|
|
this.memberType = memberType;
|
|
this.member = member;
|
|
this.isStatic = isStatic;
|
|
if (paramInfos == null || (paramInfos != null && paramInfos.Length == 0))
|
|
{
|
|
this.paramInfos = null;
|
|
args = null;
|
|
}
|
|
else
|
|
{
|
|
this.paramInfos = paramInfos;
|
|
args = new object[paramInfos.Length];
|
|
}
|
|
}
|
|
|
|
public object GetValue()
|
|
{
|
|
object instance;
|
|
if (isStatic)
|
|
{
|
|
instance = obj;
|
|
}
|
|
else
|
|
{
|
|
int instanceWhenOnlyOne = GetInstanceWhenOnlyOne(out instance);
|
|
if (instanceWhenOnlyOne == 0)
|
|
{
|
|
return "null";
|
|
}
|
|
if (instanceWhenOnlyOne > 1)
|
|
{
|
|
return ">";
|
|
}
|
|
}
|
|
if (memberType == MemberType.Method || memberType == MemberType.Delegate)
|
|
{
|
|
return null;
|
|
}
|
|
if (memberType == MemberType.Field)
|
|
{
|
|
return ((FieldInfo)member).GetValue(instance);
|
|
}
|
|
if (memberType == MemberType.Property)
|
|
{
|
|
MethodInfo getMethod = ((PropertyInfo)member).GetGetMethod(nonPublic: true);
|
|
if (getMethod != null)
|
|
{
|
|
return getMethod.Invoke(instance, null);
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public bool IsRegistered()
|
|
{
|
|
if (isStatic)
|
|
{
|
|
return true;
|
|
}
|
|
registeredInstancesLookup.TryGetValue((Type)obj, out var value);
|
|
if (value != null)
|
|
{
|
|
return value.Count > 0;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public int GetInstanceCount()
|
|
{
|
|
if (isStatic || obj == null)
|
|
{
|
|
return -1;
|
|
}
|
|
registeredInstancesLookup.TryGetValue((Type)obj, out var value);
|
|
if (value == null)
|
|
{
|
|
return 0;
|
|
}
|
|
CheckDestroyedMonoBehaviours(value);
|
|
return value.Count;
|
|
}
|
|
|
|
public int GetInstanceWhenOnlyOne(out object instance)
|
|
{
|
|
registeredInstancesLookup.TryGetValue((Type)obj, out var value);
|
|
if (value == null)
|
|
{
|
|
instance = null;
|
|
return 0;
|
|
}
|
|
CheckDestroyedMonoBehaviours(value);
|
|
if (value.Count != 1)
|
|
{
|
|
instance = null;
|
|
return value.Count;
|
|
}
|
|
using (HashSet<object>.Enumerator enumerator = value.GetEnumerator())
|
|
{
|
|
if (enumerator.MoveNext())
|
|
{
|
|
object current = enumerator.Current;
|
|
instance = current;
|
|
return 1;
|
|
}
|
|
}
|
|
instance = null;
|
|
return 0;
|
|
}
|
|
|
|
public void Execute(FastQueue<string> arguments, string argumentString)
|
|
{
|
|
if (memberType == MemberType.Method || memberType == MemberType.Delegate)
|
|
{
|
|
ExecuteMethodOrDelegate(arguments, argumentString);
|
|
}
|
|
else if (memberType == MemberType.Field)
|
|
{
|
|
ExecuteField(arguments, argumentString);
|
|
}
|
|
else if (memberType == MemberType.Property)
|
|
{
|
|
ExecuteProperty(arguments, argumentString);
|
|
}
|
|
}
|
|
|
|
private void ExecuteMethodOrDelegate(FastQueue<string> arguments, string argumentString)
|
|
{
|
|
if (paramInfos != null)
|
|
{
|
|
int count = arguments.Count;
|
|
for (int i = 0; i < paramInfos.Length; i++)
|
|
{
|
|
ParameterInfo parameterInfo = paramInfos[i];
|
|
Type parameterType = parameterInfo.ParameterType;
|
|
if (i >= count)
|
|
{
|
|
if (!parameterInfo.IsOptional)
|
|
{
|
|
LogResultError("Can't execute because of wrong number of arguments");
|
|
return;
|
|
}
|
|
args[i] = parameterInfo.DefaultValue;
|
|
}
|
|
else if (!Parser.TryParse(parameterType, arguments, out args[i]))
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
if (arguments.Count > 0)
|
|
{
|
|
LogResultError("Too many arguments");
|
|
return;
|
|
}
|
|
if (memberType == MemberType.Method)
|
|
{
|
|
if (isStatic)
|
|
{
|
|
ExecuteMethod(member, (MethodInfo)member, obj, args, argumentString);
|
|
return;
|
|
}
|
|
HashSet<object> hashSet = registeredInstancesLookup[(Type)obj];
|
|
CheckDestroyedMonoBehaviours(hashSet);
|
|
{
|
|
foreach (object item in hashSet)
|
|
{
|
|
if (item as MonoBehaviour == null && item.GetType().IsSubclassOf(typeof(MonoBehaviour)))
|
|
{
|
|
Debug.Log("Mono = isDestroyed");
|
|
}
|
|
else
|
|
{
|
|
ExecuteMethod(member, (MethodInfo)member, item, args, argumentString);
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
if (isStatic)
|
|
{
|
|
ExecuteDelegateMethod(member, obj, args, argumentString);
|
|
return;
|
|
}
|
|
HashSet<object> hashSet2 = registeredInstancesLookup[(Type)obj];
|
|
CheckDestroyedMonoBehaviours(hashSet2);
|
|
foreach (object item2 in hashSet2)
|
|
{
|
|
ExecuteDelegateMethod(member, item2, args, argumentString);
|
|
}
|
|
}
|
|
|
|
private void ExecuteDelegateMethod(MemberInfo member, object obj, object[] args, string argumentString)
|
|
{
|
|
object value = ((FieldInfo)member).GetValue(obj);
|
|
if (value == null)
|
|
{
|
|
LogResultError(obj.ToString() + " : " + member.Name + " delegate is not assigned");
|
|
return;
|
|
}
|
|
MethodInfo method = value.GetType().GetMethod("Invoke");
|
|
ExecuteMethod(member, method, value, args, argumentString);
|
|
}
|
|
|
|
private void ExecuteMethod(MemberInfo member, MethodInfo method, object obj, object[] args, string argumentString)
|
|
{
|
|
try
|
|
{
|
|
object obj2 = method.Invoke(obj, args);
|
|
if (obj2 != null)
|
|
{
|
|
LogResult(obj.ToString() + " : " + member.Name + " " + argumentString + " = " + obj2);
|
|
}
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
Debug.LogException(exception);
|
|
}
|
|
}
|
|
|
|
private void ExecuteField(FastQueue<string> arguments, string argumentString)
|
|
{
|
|
FieldInfo fieldInfo = (FieldInfo)member;
|
|
if (arguments.Count == 0)
|
|
{
|
|
if (!isStatic)
|
|
{
|
|
HashSet<object> hashSet = registeredInstancesLookup[(Type)obj];
|
|
CheckDestroyedMonoBehaviours(hashSet);
|
|
{
|
|
foreach (object item in hashSet)
|
|
{
|
|
LogValue(fieldInfo, item);
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
LogValue(fieldInfo, obj);
|
|
}
|
|
else
|
|
{
|
|
if (!Parser.TryParse(fieldInfo.FieldType, arguments, out var result))
|
|
{
|
|
return;
|
|
}
|
|
if (arguments.Count > 0)
|
|
{
|
|
LogResultError("Too many arguments");
|
|
return;
|
|
}
|
|
if (!isStatic)
|
|
{
|
|
HashSet<object> hashSet2 = registeredInstancesLookup[(Type)obj];
|
|
CheckDestroyedMonoBehaviours(hashSet2);
|
|
{
|
|
foreach (object item2 in hashSet2)
|
|
{
|
|
SetField(fieldInfo, item2, result);
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
SetField(fieldInfo, obj, result);
|
|
}
|
|
}
|
|
|
|
private void LogValue(FieldInfo field, object obj)
|
|
{
|
|
try
|
|
{
|
|
LogResult(obj.ToString() + " : " + field.Name + " = " + field.GetValue(obj));
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
Debug.LogException(exception);
|
|
}
|
|
}
|
|
|
|
private void SetField(FieldInfo field, object obj, object arg)
|
|
{
|
|
try
|
|
{
|
|
if (arg != null)
|
|
{
|
|
field.SetValue(obj, arg);
|
|
}
|
|
LogResult(obj.ToString() + " : " + field.Name + " = " + field.GetValue(obj));
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
Debug.LogException(exception);
|
|
}
|
|
}
|
|
|
|
private void ExecuteProperty(FastQueue<string> arguments, string argumentString)
|
|
{
|
|
PropertyInfo propertyInfo = (PropertyInfo)member;
|
|
if (arguments.Count == 0)
|
|
{
|
|
if (propertyInfo.GetGetMethod(nonPublic: true) == null)
|
|
{
|
|
LogResultError(propertyInfo.Name + " doesn't have a getter");
|
|
return;
|
|
}
|
|
if (!isStatic)
|
|
{
|
|
HashSet<object> hashSet = registeredInstancesLookup[(Type)obj];
|
|
CheckDestroyedMonoBehaviours(hashSet);
|
|
{
|
|
foreach (object item in hashSet)
|
|
{
|
|
LogValue(propertyInfo, item);
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
LogValue(propertyInfo, obj);
|
|
}
|
|
else if (propertyInfo.GetSetMethod(nonPublic: true) == null)
|
|
{
|
|
LogResultError(propertyInfo.Name + " doesn't have a setter");
|
|
}
|
|
else
|
|
{
|
|
if (!Parser.TryParse(propertyInfo.PropertyType, arguments, out var result))
|
|
{
|
|
return;
|
|
}
|
|
if (arguments.Count > 0)
|
|
{
|
|
LogResultError("Too many arguments");
|
|
return;
|
|
}
|
|
if (!isStatic)
|
|
{
|
|
HashSet<object> hashSet2 = registeredInstancesLookup[(Type)obj];
|
|
CheckDestroyedMonoBehaviours(hashSet2);
|
|
{
|
|
foreach (object item2 in hashSet2)
|
|
{
|
|
SetProperty(propertyInfo, item2, result);
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
SetProperty(propertyInfo, obj, result);
|
|
}
|
|
}
|
|
|
|
private void LogValue(PropertyInfo prop, object obj)
|
|
{
|
|
try
|
|
{
|
|
LogResult(obj.ToString() + " : " + prop.Name + " = " + prop.GetValue(obj, null));
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
Debug.LogException(exception);
|
|
}
|
|
}
|
|
|
|
private void SetProperty(PropertyInfo prop, object obj, object arg)
|
|
{
|
|
try
|
|
{
|
|
if (arg != null)
|
|
{
|
|
prop.SetValue(obj, arg, null);
|
|
}
|
|
if (prop.GetGetMethod(nonPublic: true) != null)
|
|
{
|
|
LogResult(obj.ToString() + " : " + prop.Name + " = " + prop.GetValue(obj, null));
|
|
}
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
Debug.LogException(exception);
|
|
}
|
|
}
|
|
|
|
private bool CheckParameterCount(int required, int count)
|
|
{
|
|
if (required == count)
|
|
{
|
|
return true;
|
|
}
|
|
LogResultError("Can't execute because " + required + " arguments are needed");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public enum AccessMode
|
|
{
|
|
EnabledOnConsoleCommand = 0,
|
|
Enabled = 1,
|
|
Disabled = 2
|
|
}
|
|
|
|
public struct AutoComplete
|
|
{
|
|
public string command;
|
|
|
|
public CommandData commandData;
|
|
|
|
public AutoComplete(string command, CommandData commandData)
|
|
{
|
|
this.command = command;
|
|
this.commandData = commandData;
|
|
}
|
|
}
|
|
|
|
public static RuntimeConsole instance;
|
|
|
|
public static AccessLevel accessLevel;
|
|
|
|
public static bool show;
|
|
|
|
private static Dictionary<Type, HashSet<object>> registeredInstancesLookup = new Dictionary<Type, HashSet<object>>();
|
|
|
|
private static StringDictionarySorted commandsTable = new StringDictionarySorted();
|
|
|
|
private static FastList<AutoComplete> autoCompleteList = new FastList<AutoComplete>();
|
|
|
|
private static FastQueue<string> inputCommands = new FastQueue<string>(32);
|
|
|
|
private static FastList<LogEntry> threadLogEntries = new FastList<LogEntry>(256);
|
|
|
|
private static FastList<LogEntry> logEntries = new FastList<LogEntry>(256);
|
|
|
|
private SortedFastList<string> commands = new SortedFastList<string>();
|
|
|
|
private const int logSize = 8192;
|
|
|
|
private const int commandLogs = 0;
|
|
|
|
private const int frameLogs = 1;
|
|
|
|
private const int unityLogs = 2;
|
|
|
|
private const int warningLogs = 3;
|
|
|
|
private const int errorLogs = 4;
|
|
|
|
private const int exceptionLogs = 5;
|
|
|
|
private static bool setFocus;
|
|
|
|
private static int lastFrame = -1;
|
|
|
|
private static LogEntry lastFrameEntry;
|
|
|
|
private WindowSettings consoleWindow;
|
|
|
|
private int commandIndex;
|
|
|
|
private int moveInputCursor;
|
|
|
|
private int autoCompleteIndex;
|
|
|
|
private string inputCommand;
|
|
|
|
private GUIChangeBool _showStack = new GUIChangeBool(value: true);
|
|
|
|
private GUIChangeBool showUnityLogs = new GUIChangeBool(value: true);
|
|
|
|
private GUIChangeBool showLastLog = new GUIChangeBool(value: true);
|
|
|
|
private Vector2 autoCompleteScrollView;
|
|
|
|
private Double2 scrollView;
|
|
|
|
private Double2 scrollViewHeights;
|
|
|
|
private CullGroup cullGroup;
|
|
|
|
private FastList<CullList> cullLists = new FastList<CullList>();
|
|
|
|
private static CullList[] logs;
|
|
|
|
private bool calcDraw;
|
|
|
|
private bool isEnabled;
|
|
|
|
private int oldAutoCompleteCount = -1;
|
|
|
|
private bool updateAutoCompleteScrollView;
|
|
|
|
private bool isDebugBuild;
|
|
|
|
public bool showConsoleOnStart = true;
|
|
|
|
[ConsoleCommand(AccessLevel.Admin)]
|
|
public bool showConsoleOnWarning;
|
|
|
|
[ConsoleCommand(AccessLevel.Admin)]
|
|
public bool showConsoleOnError;
|
|
|
|
[ConsoleCommand(AccessLevel.Admin)]
|
|
public bool showConsoleOnException;
|
|
|
|
[ConsoleCommand(AccessLevel.Admin)]
|
|
public bool showConsoleWhenInvokingMethod = true;
|
|
|
|
[ConsoleCommand(AccessLevel.Admin)]
|
|
public bool disableUnityDevelopmentConsole = true;
|
|
|
|
public bool useSameEditorAsBuildShowKey = true;
|
|
|
|
public AdvancedKey showToggleKeyEditor = new AdvancedKey(KeyCode.F9);
|
|
|
|
public AdvancedKey showToggleKeyBuild = new AdvancedKey(KeyCode.F9);
|
|
|
|
[Tooltip("This ignores cases in commands")]
|
|
[ConsoleCommand(AccessLevel.Admin)]
|
|
public bool ignoreCasesInCommands;
|
|
|
|
[Tooltip("This ignores cases for auto-complete lookup, but still cases are needed for commands")]
|
|
[ConsoleCommand(AccessLevel.Admin)]
|
|
public bool ignoreCasesInAutoCompleteInput = true;
|
|
|
|
public AccessMode adminModeInBuild;
|
|
|
|
public string adminModeConsoleCommand = "*GetAdminAccess*";
|
|
|
|
public AccessMode specialModeInBuild;
|
|
|
|
public string specialModeConsoleCommand = "*GetSpecialAccess*";
|
|
|
|
[Tooltip("This will disable admin/special commands in Unity Editor")]
|
|
public bool testOnlyFreeConsoleCommands;
|
|
|
|
public char searchCommandPrefix = '!';
|
|
|
|
[ConsoleCommand(AccessLevel.Admin)]
|
|
public bool ignoreCasesInSearch = true;
|
|
|
|
public char executeOnAllPrefix = '#';
|
|
|
|
public char executeOnlyOnRemotePrefix = '$';
|
|
|
|
public int titleFontSize = 18;
|
|
|
|
public int frameFontSize = 14;
|
|
|
|
public int logFontSize = 14;
|
|
|
|
public int stackFontSize = 12;
|
|
|
|
public SO_ConsoleWindow windowData;
|
|
|
|
private Color selectColor = new Color(0.25f, 0.8f, 0.25f);
|
|
|
|
private Color backgroundColor = new Color(0f, 0f, 0f, 0.9f);
|
|
|
|
private Rect rectAutoComplete;
|
|
|
|
private Rect rectScroll;
|
|
|
|
private string lastAutoCompleteCommand;
|
|
|
|
private double scrollViewEndHeight;
|
|
|
|
private bool drawLogsScrollBar;
|
|
|
|
private bool addInput;
|
|
|
|
public static event RemoteCommand onRemoteCommand;
|
|
|
|
public static event SetActiveMethod onSetActive;
|
|
|
|
private void ResetStatic()
|
|
{
|
|
RuntimeConsole.onRemoteCommand = null;
|
|
accessLevel = AccessLevel.Admin;
|
|
show = false;
|
|
autoCompleteList.Clear();
|
|
inputCommands.Clear();
|
|
threadLogEntries.Clear();
|
|
logEntries.Clear();
|
|
commands.Clear();
|
|
LogEntry.ResetStatic();
|
|
logs = null;
|
|
}
|
|
|
|
private void Awake()
|
|
{
|
|
isDebugBuild = Debug.isDebugBuild;
|
|
ResetStatic();
|
|
consoleWindow = windowData.consoleWindow;
|
|
logs = new CullList[6];
|
|
cullGroup = new CullGroup(8192 * logs.Length);
|
|
for (int i = 0; i < logs.Length; i++)
|
|
{
|
|
logs[i] = new CullList(8192);
|
|
}
|
|
SetActive(showConsoleOnStart);
|
|
inputCommand = string.Empty;
|
|
logs[0].cullItems.Add(new LogEntry("-------------------------------------------------------------------------------", Color.white, titleFontSize, FontStyle.Bold));
|
|
logs[0].cullItems.Add(new LogEntry(Helper.GetApplicationInfo(), Color.white, titleFontSize, FontStyle.Bold));
|
|
logs[0].cullItems.Add(new LogEntry("-------------------------------------------------------------------------------", Color.white, titleFontSize, FontStyle.Bold));
|
|
logs[0].cullItems.Add(new LogEntry(string.Empty, Color.white, titleFontSize, FontStyle.Bold));
|
|
logs[0].cullItems.Add(new LogEntry("Type '?' to list all commands", Color.white, titleFontSize, FontStyle.Bold));
|
|
logs[0].cullItems.Add(new LogEntry(string.Empty, Color.white, titleFontSize, FontStyle.Bold));
|
|
GUIChangeBool.ApplyUpdates();
|
|
Register(this);
|
|
CalcDraw(reset: true);
|
|
if (adminModeInBuild == AccessMode.Enabled)
|
|
{
|
|
accessLevel = AccessLevel.Admin;
|
|
}
|
|
}
|
|
|
|
private void OnEnable()
|
|
{
|
|
isEnabled = true;
|
|
}
|
|
|
|
private void OnDisable()
|
|
{
|
|
isEnabled = false;
|
|
}
|
|
|
|
private void OnDestroy()
|
|
{
|
|
if (instance == this)
|
|
{
|
|
instance = null;
|
|
}
|
|
Unregister(this);
|
|
}
|
|
|
|
public void ManualUpdate()
|
|
{
|
|
if (isDebugBuild && disableUnityDevelopmentConsole)
|
|
{
|
|
Debug.developerConsoleVisible = false;
|
|
}
|
|
UpdateLogs();
|
|
if (isEnabled && EventInput.isMouseButtonUp0)
|
|
{
|
|
consoleWindow.drag = 0;
|
|
}
|
|
}
|
|
|
|
public static void SetActive(bool active)
|
|
{
|
|
instance.consoleWindow.drag = 0;
|
|
show = active;
|
|
instance.gameObject.SetActive(active);
|
|
if (show)
|
|
{
|
|
setFocus = true;
|
|
}
|
|
if (RuntimeConsole.onSetActive != null)
|
|
{
|
|
RuntimeConsole.onSetActive(show);
|
|
}
|
|
WindowManager.CheckMouseCursorState();
|
|
}
|
|
|
|
public static void Log(string logString, bool showConsole)
|
|
{
|
|
if (!(instance == null))
|
|
{
|
|
AddLog(new LogEntry(logString, null, LogType.Log, EntryType.Console, Color.white));
|
|
if (showConsole && !show)
|
|
{
|
|
SetActive(active: true);
|
|
}
|
|
}
|
|
}
|
|
|
|
public static void Log(string logString, Color color, bool showConsole)
|
|
{
|
|
if (!(instance == null))
|
|
{
|
|
AddLog(new LogEntry(logString, null, LogType.Log, EntryType.Console, color));
|
|
if (showConsole && !show)
|
|
{
|
|
SetActive(active: true);
|
|
}
|
|
}
|
|
}
|
|
|
|
public static void Log(string logString, LogType logType = LogType.Log, Color color = default(Color), bool showConsole = false)
|
|
{
|
|
if (!(instance == null))
|
|
{
|
|
AddLog(new LogEntry(logString, null, logType, EntryType.Console, color));
|
|
if (showConsole && !show)
|
|
{
|
|
SetActive(active: true);
|
|
}
|
|
}
|
|
}
|
|
|
|
public static void Log(string logString, string[] lines, LogType logType = LogType.Log, Color color = default(Color), int threadId = -1)
|
|
{
|
|
if (!(instance == null))
|
|
{
|
|
AddLog(new LogEntry(logString, lines, logType, EntryType.Unity, color, instance.logFontSize, FontStyle.Normal, threadId));
|
|
}
|
|
}
|
|
|
|
public static void Log(LogEntry logEntry)
|
|
{
|
|
if (!(instance == null))
|
|
{
|
|
AddLog(logEntry);
|
|
}
|
|
}
|
|
|
|
private static void AddLog(LogEntry logEntry)
|
|
{
|
|
if (CheckNewFrame())
|
|
{
|
|
logEntry.id = LogEntry.currentId++;
|
|
}
|
|
threadLogEntries.AddThreadSafe(logEntry);
|
|
}
|
|
|
|
private void UpdateLogs()
|
|
{
|
|
logEntries.GrabListThreadSafe(threadLogEntries);
|
|
for (int i = 0; i < logEntries.Count; i++)
|
|
{
|
|
LogEntry logEntry = logEntries.items[i];
|
|
if (logEntry.entryType == EntryType.Unity)
|
|
{
|
|
if (logEntry.logType == LogType.Log)
|
|
{
|
|
instance.windowData.logIcon.count++;
|
|
lastFrameEntry.flag |= 1;
|
|
logs[2].cullItems.Add(logEntry);
|
|
}
|
|
else if (logEntry.logType == LogType.Warning)
|
|
{
|
|
if (instance.showConsoleOnWarning && !show)
|
|
{
|
|
SetActive(active: true);
|
|
}
|
|
instance.windowData.warningIcon.count++;
|
|
lastFrameEntry.flag |= 2;
|
|
logs[3].cullItems.Add(logEntry);
|
|
}
|
|
else if (logEntry.logType == LogType.Error)
|
|
{
|
|
if (instance.showConsoleOnError && !show)
|
|
{
|
|
SetActive(active: true);
|
|
}
|
|
instance.windowData.errorIcon.count++;
|
|
lastFrameEntry.flag |= 4;
|
|
logs[4].cullItems.Add(logEntry);
|
|
}
|
|
else if (logEntry.logType == LogType.Exception)
|
|
{
|
|
if (instance.showConsoleOnException && !show)
|
|
{
|
|
SetActive(active: true);
|
|
}
|
|
instance.windowData.exceptionIcon.count++;
|
|
lastFrameEntry.flag |= 8;
|
|
logs[5].cullItems.Add(logEntry);
|
|
}
|
|
}
|
|
else if (logEntry.entryType == EntryType.Frame)
|
|
{
|
|
logs[1].cullItems.Add(lastFrameEntry);
|
|
}
|
|
else
|
|
{
|
|
lastFrameEntry.flag |= 16;
|
|
logs[0].cullItems.Add(logEntry);
|
|
}
|
|
}
|
|
logEntries.Clear();
|
|
instance.CalcDraw(reset: false);
|
|
}
|
|
|
|
private static bool CheckNewFrame()
|
|
{
|
|
if (HtmlDebug.currentFrame != lastFrame)
|
|
{
|
|
lastFrame = HtmlDebug.currentFrame;
|
|
lastFrameEntry = new LogEntry("[Frame " + lastFrame.ToString("D6") + "][Time " + Helper.ToTimeFormat(HtmlDebug.frameTime) + "] -----------------------------------------------------------------------------------------------", null, LogType.Log, EntryType.Frame, new Color(0.31f, 0.55f, 0.63f), instance.frameFontSize, FontStyle.Bold);
|
|
threadLogEntries.AddThreadSafe(lastFrameEntry);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public static void SortCommandsTable()
|
|
{
|
|
commandsTable.Sort();
|
|
}
|
|
|
|
public static void Register(object instance)
|
|
{
|
|
if (Application.isPlaying)
|
|
{
|
|
Type type = instance.GetType();
|
|
if (!registeredInstancesLookup.TryGetValue(type, out var value))
|
|
{
|
|
value = new HashSet<object>();
|
|
registeredInstancesLookup[type] = value;
|
|
}
|
|
else if (value.Contains(instance))
|
|
{
|
|
Debug.LogError("Instance " + type.Name + " is already registered");
|
|
return;
|
|
}
|
|
value.Add(instance);
|
|
}
|
|
}
|
|
|
|
public static void Unregister(object instance)
|
|
{
|
|
Type type = instance.GetType();
|
|
registeredInstancesLookup.TryGetValue(type, out var value);
|
|
if (instance == null || !value.Contains(instance))
|
|
{
|
|
Debug.LogError("Instance " + type.Name + " is not registered");
|
|
return;
|
|
}
|
|
value.Remove(instance);
|
|
if (value.Count == 0)
|
|
{
|
|
registeredInstancesLookup.Remove(type);
|
|
}
|
|
}
|
|
|
|
public static void RegisterStaticType(Type objType)
|
|
{
|
|
if (instance == null)
|
|
{
|
|
return;
|
|
}
|
|
ConsoleAlias[] array = (ConsoleAlias[])objType.GetCustomAttributes(typeof(ConsoleAlias), inherit: true);
|
|
if (array.Length != 0)
|
|
{
|
|
commandsTable.lookup[array[0].alias] = CommandData.empty;
|
|
}
|
|
MemberInfo[] members = objType.GetMembers(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
|
|
foreach (MemberInfo memberInfo in members)
|
|
{
|
|
ConsoleCommand[] array2 = (ConsoleCommand[])memberInfo.GetCustomAttributes(typeof(ConsoleCommand), inherit: false);
|
|
if (array2.Length == 0)
|
|
{
|
|
continue;
|
|
}
|
|
ConsoleCommand consoleCommand = array2[0];
|
|
if (array.Length != 0)
|
|
{
|
|
consoleCommand.alias = array[0].alias + ((consoleCommand.alias.Length > 0) ? ("." + consoleCommand.alias) : string.Empty);
|
|
}
|
|
if (AddMethod(objType, consoleCommand, memberInfo, memberInfo as MethodInfo, MemberType.Method, memberInfo.Name))
|
|
{
|
|
continue;
|
|
}
|
|
FieldInfo fieldInfo = memberInfo as FieldInfo;
|
|
if (fieldInfo != null)
|
|
{
|
|
Type fieldType = fieldInfo.FieldType;
|
|
if (typeof(Delegate).IsAssignableFrom(fieldType))
|
|
{
|
|
AddMethod(objType, consoleCommand, memberInfo, fieldType.GetMethod("Invoke"), MemberType.Delegate, fieldInfo.Name);
|
|
}
|
|
else if (ValidParam(objType, fieldInfo, fieldType))
|
|
{
|
|
if (fieldType.IsEnum && consoleCommand.description == string.Empty)
|
|
{
|
|
consoleCommand.description = string.Join(", ", Enum.GetNames(fieldType));
|
|
}
|
|
string syntax = fieldInfo.Name + " " + fieldType.Name;
|
|
AddCommand(memberInfo, consoleCommand, memberInfo.Name, new CommandData(consoleCommand, objType, syntax, MemberType.Field, memberInfo, null, fieldInfo.IsStatic));
|
|
}
|
|
continue;
|
|
}
|
|
PropertyInfo propertyInfo = memberInfo as PropertyInfo;
|
|
if (!(propertyInfo != null))
|
|
{
|
|
continue;
|
|
}
|
|
Type propertyType = propertyInfo.PropertyType;
|
|
if (!ValidParam(objType, propertyInfo, propertyType))
|
|
{
|
|
continue;
|
|
}
|
|
MethodInfo getMethod = propertyInfo.GetGetMethod(nonPublic: true);
|
|
MethodInfo setMethod = propertyInfo.GetSetMethod(nonPublic: true);
|
|
bool flag = getMethod != null;
|
|
bool flag2 = setMethod != null;
|
|
bool isStatic;
|
|
if (flag)
|
|
{
|
|
isStatic = getMethod.IsStatic;
|
|
}
|
|
else
|
|
{
|
|
if (!flag2)
|
|
{
|
|
Debug.Log("Property has no getter or setter");
|
|
continue;
|
|
}
|
|
isStatic = setMethod.IsStatic;
|
|
}
|
|
string text = propertyInfo.Name + " " + propertyType.Name;
|
|
AddCommand(commandData: new CommandData(consoleCommand, objType, (flag && !flag2) ? (text + " (get)") : ((!(flag && flag2)) ? (text + " (set)") : (text + " (get set)")), MemberType.Property, memberInfo, null, isStatic), member: memberInfo, consoleCommand: consoleCommand, commandName: memberInfo.Name);
|
|
}
|
|
}
|
|
|
|
private static bool AddMethod(Type objType, ConsoleCommand consoleCommand, MemberInfo member, MethodInfo method, MemberType memberType, string methodName, bool logFailed = true)
|
|
{
|
|
if (method != null)
|
|
{
|
|
ParameterInfo[] parameters = method.GetParameters();
|
|
if (!ValidParams(objType, method, parameters))
|
|
{
|
|
return true;
|
|
}
|
|
string syntax = method.ToString();
|
|
AddCommand(member, consoleCommand, methodName, new CommandData(consoleCommand, objType, syntax, memberType, member, parameters, method.IsStatic), logFailed);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private static void AddCommand(MemberInfo member, ConsoleCommand consoleCommand, string commandName, CommandData commandData, bool logFailed = true)
|
|
{
|
|
if (instance.ignoreCasesInCommands)
|
|
{
|
|
commandName = commandName.ToLower();
|
|
}
|
|
if (consoleCommand.command == string.Empty)
|
|
{
|
|
consoleCommand.command = commandName;
|
|
}
|
|
else
|
|
{
|
|
commandName = consoleCommand.command;
|
|
if (instance.ignoreCasesInCommands)
|
|
{
|
|
commandName = commandName.ToLower();
|
|
}
|
|
}
|
|
if (consoleCommand.alias != string.Empty)
|
|
{
|
|
if (!commandsTable.lookup.ContainsKey(consoleCommand.alias))
|
|
{
|
|
commandsTable.lookup[consoleCommand.alias] = CommandData.empty;
|
|
}
|
|
commandName = consoleCommand.alias + "." + consoleCommand.command;
|
|
}
|
|
if (commandsTable.lookup.ContainsKey(commandName))
|
|
{
|
|
if (logFailed)
|
|
{
|
|
Debug.LogError("Duplicate command: `" + commandName + "` on " + member.Name + " in " + commandData.obj.ToString() + " class ");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
commandsTable.lookup[commandName] = commandData;
|
|
}
|
|
}
|
|
|
|
public static bool ValidParams(Type objType, MethodInfo method, ParameterInfo[] paramInfos, bool logFailed = true)
|
|
{
|
|
foreach (ParameterInfo parameterInfo in paramInfos)
|
|
{
|
|
Type parameterType = parameterInfo.ParameterType;
|
|
if (!ValidParam(objType, parameterInfo.Member, parameterType, logFailed))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private static bool ValidParam(Type objType, MemberInfo member, Type type, bool logFailed = true)
|
|
{
|
|
bool flag = false;
|
|
if (type.IsPrimitive)
|
|
{
|
|
flag = true;
|
|
}
|
|
else if (type == typeof(decimal))
|
|
{
|
|
flag = true;
|
|
}
|
|
else if (type == typeof(string))
|
|
{
|
|
flag = true;
|
|
}
|
|
else if (type == typeof(Vector2) || type == typeof(Vector3) || type == typeof(Vector4))
|
|
{
|
|
flag = true;
|
|
}
|
|
else if (type.IsEnum)
|
|
{
|
|
flag = true;
|
|
}
|
|
if (!flag)
|
|
{
|
|
if (logFailed)
|
|
{
|
|
Debug.LogError("Cannot register: " + objType.Name + " => " + member.Name + " method contains parameter of type " + type.Name + ". Only primitive and string parameters are allowed at the moment.");
|
|
}
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private static void CheckDestroyedMonoBehaviours(HashSet<object> instances)
|
|
{
|
|
instances.RemoveWhere((object s) => s as MonoBehaviour == null && s.GetType().IsSubclassOf(typeof(MonoBehaviour)));
|
|
}
|
|
|
|
private static int IsRemoteCommand(ref string command)
|
|
{
|
|
int result;
|
|
if (command[0] == instance.executeOnAllPrefix)
|
|
{
|
|
result = 1;
|
|
command = command.Substring(1);
|
|
}
|
|
else if (command[0] == instance.executeOnlyOnRemotePrefix)
|
|
{
|
|
result = 2;
|
|
command = command.Substring(1);
|
|
}
|
|
else
|
|
{
|
|
result = 0;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public static void ExecuteCommand(string command)
|
|
{
|
|
command = command.Replace(',', ' ');
|
|
command = command.Trim(' ');
|
|
if (command == string.Empty)
|
|
{
|
|
return;
|
|
}
|
|
if (command == instance.adminModeConsoleCommand && (instance.adminModeInBuild == AccessMode.EnabledOnConsoleCommand || instance.testOnlyFreeConsoleCommands))
|
|
{
|
|
accessLevel = AccessLevel.Admin;
|
|
LogResult("AccessLevel = Admin");
|
|
}
|
|
else if (command == instance.specialModeConsoleCommand && (instance.specialModeInBuild == AccessMode.EnabledOnConsoleCommand || instance.testOnlyFreeConsoleCommands))
|
|
{
|
|
accessLevel = AccessLevel.Special;
|
|
LogResult("AccessLevel = Special");
|
|
}
|
|
else
|
|
{
|
|
if (command[0] == instance.searchCommandPrefix)
|
|
{
|
|
return;
|
|
}
|
|
int num = IsRemoteCommand(ref command);
|
|
int num2 = command.IndexOf(" ");
|
|
string argumentString = ((num2 == -1) ? string.Empty : command.Substring(num2 + 1));
|
|
GetArguments(command, inputCommands);
|
|
string text = inputCommands.Dequeue();
|
|
if (!commandsTable.lookup.TryGetValue(text, out var value) || value.obj == null)
|
|
{
|
|
CannotFindCommand(command, text);
|
|
return;
|
|
}
|
|
if (value.consoleCommand != null && !value.consoleCommand.HasAccess(accessLevel))
|
|
{
|
|
CannotFindCommand(command, text);
|
|
return;
|
|
}
|
|
if (!value.IsRegistered())
|
|
{
|
|
LogResultError("There is no registered instance for command '" + text + "'");
|
|
return;
|
|
}
|
|
if (num > 0)
|
|
{
|
|
if (RuntimeConsole.onRemoteCommand != null)
|
|
{
|
|
RuntimeConsole.onRemoteCommand(command);
|
|
}
|
|
command = ((num != 2) ? ("Execute on all '" + command + "'") : ("Execute only on remote '" + command + "'"));
|
|
}
|
|
Log(new LogEntry(command, null, LogType.Log, EntryType.Command, Color.green, instance.logFontSize, FontStyle.Bold));
|
|
if ((bool)HtmlDebug.instance)
|
|
{
|
|
HtmlDebug.instance.UnityDebugLog(command, null, LogType.Log, isMainThread: true, -1, null, EntryType2.Command, closeLi: false);
|
|
}
|
|
if (num != 2)
|
|
{
|
|
value.Execute(inputCommands, argumentString);
|
|
}
|
|
}
|
|
}
|
|
|
|
public static void GetArguments(string argumentString, FastQueue<string> inputCommands)
|
|
{
|
|
argumentString = argumentString.Trim(' ');
|
|
inputCommands.FastClear();
|
|
int num = 0;
|
|
for (int i = 0; i < argumentString.Length; i++)
|
|
{
|
|
char c = argumentString[i];
|
|
if (i == argumentString.Length - 1)
|
|
{
|
|
inputCommands.Enqueue(argumentString.Substring(num, i - num + 1).Trim());
|
|
break;
|
|
}
|
|
if (c == ' ')
|
|
{
|
|
if (i < argumentString.Length - 1 && argumentString[i + 1] == ' ')
|
|
{
|
|
continue;
|
|
}
|
|
int num2 = argumentString.IndexOf(' ', i + 1);
|
|
int num3 = i - num;
|
|
inputCommands.Enqueue(argumentString.Substring(num, num3).Trim());
|
|
if (num2 == -1)
|
|
{
|
|
inputCommands.Enqueue(argumentString.Substring(i + 1).Trim());
|
|
break;
|
|
}
|
|
num += num3 + 1;
|
|
}
|
|
if (c == '"')
|
|
{
|
|
int num4 = argumentString.IndexOf('"', i + 1);
|
|
if (num4 == -1)
|
|
{
|
|
LogCommandFailed(argumentString, "String closing \" is missing");
|
|
break;
|
|
}
|
|
int num5 = num4 - num;
|
|
inputCommands.Enqueue(argumentString.Substring(num + 1, num5 - 1).Trim());
|
|
num += num5 + 1;
|
|
i = num4 + 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
private static void CannotFindCommand(string command, string firstCommand)
|
|
{
|
|
string result = "Cannot find command '" + firstCommand + "'";
|
|
LogCommandFailed(command, result);
|
|
}
|
|
|
|
private static void LogCommandFailed(string command, string result)
|
|
{
|
|
Log(new LogEntry(command, null, LogType.Log, EntryType.Command, Color.green, instance.logFontSize, FontStyle.Bold));
|
|
Log(new LogEntry(result, null, LogType.Log, EntryType.CommandResult, Helper.colCommandResultFailed, instance.logFontSize, FontStyle.Bold));
|
|
if ((bool)HtmlDebug.instance)
|
|
{
|
|
HtmlDebug.instance.UnityDebugLog(result, null, LogType.Log, isMainThread: true, -1, null, EntryType2.CommandFault);
|
|
}
|
|
}
|
|
|
|
public static bool FindCommand(string command)
|
|
{
|
|
string[] array = command.Split(' ');
|
|
if (!commandsTable.lookup.TryGetValue(array[0], out var value) || value.obj == null)
|
|
{
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private static void LogResult(string result)
|
|
{
|
|
Log(new LogEntry(result, null, LogType.Log, EntryType.CommandResult, Helper.colCommandResult, instance.logFontSize, FontStyle.Bold));
|
|
if ((bool)HtmlDebug.instance)
|
|
{
|
|
HtmlDebug.instance.UnityDebugLog(result, null, LogType.Log, isMainThread: true, -1, null, EntryType2.CommandResult);
|
|
}
|
|
}
|
|
|
|
public static void LogResultError(string result, bool onlyConsoleAndHtml = true)
|
|
{
|
|
if (onlyConsoleAndHtml)
|
|
{
|
|
Log(new LogEntry(result, null, LogType.Log, EntryType.CommandResult, Helper.colCommandResultFailed, instance.logFontSize, FontStyle.Bold));
|
|
if ((bool)HtmlDebug.instance)
|
|
{
|
|
HtmlDebug.instance.UnityDebugLog(result, null, LogType.Log, isMainThread: true, -1, null, EntryType2.CommandFault);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Debug.LogError(result);
|
|
}
|
|
}
|
|
|
|
[ConsoleCommand("", "Clears all logs in the Console Window", AccessLevel.Admin)]
|
|
private static void Clear()
|
|
{
|
|
for (int i = 0; i < logs.Length; i++)
|
|
{
|
|
logs[i].cullItems.Clear();
|
|
}
|
|
instance.CalcDraw(reset: true);
|
|
instance.windowData.logIcon.count = 0;
|
|
instance.windowData.warningIcon.count = 0;
|
|
instance.windowData.errorIcon.count = 0;
|
|
instance.windowData.exceptionIcon.count = 0;
|
|
}
|
|
|
|
[ConsoleCommand("", "Change the height of the Console Window based on line height", AccessLevel.Admin)]
|
|
private static void Lines(int count = 20)
|
|
{
|
|
instance.consoleWindow.rect.height = 25 * count;
|
|
}
|
|
|
|
[ConsoleCommand("", "Open the Console Window", AccessLevel.Admin)]
|
|
private static void Open()
|
|
{
|
|
SetActive(active: true);
|
|
}
|
|
|
|
[ConsoleCommand("", "Close the Console Window", AccessLevel.Admin)]
|
|
private static void Close()
|
|
{
|
|
SetActive(active: false);
|
|
}
|
|
|
|
[ConsoleCommand("", "Unload unused Assets", AccessLevel.Admin)]
|
|
private static void UnloadUnusedAssets()
|
|
{
|
|
Resources.UnloadUnusedAssets();
|
|
}
|
|
|
|
[ConsoleCommand("", "Runs Garbage Collect", AccessLevel.Admin)]
|
|
private static void GarbageCollect()
|
|
{
|
|
GC.Collect();
|
|
}
|
|
|
|
[ConsoleCommand("", "Search for methods in assemblies", AccessLevel.Admin)]
|
|
private static void SearchMethod(string name)
|
|
{
|
|
FastList<CustomAssembly> customAssemblies = RuntimeInspector.customAssemblies;
|
|
for (int i = 0; i < customAssemblies.Count; i++)
|
|
{
|
|
CustomAssembly customAssembly = customAssemblies.items[i];
|
|
FastList<CustomType> allTypes = customAssembly.allTypes;
|
|
if (customAssembly.type != AssemblyType.Unity)
|
|
{
|
|
continue;
|
|
}
|
|
for (int j = 0; j < allTypes.Count; j++)
|
|
{
|
|
Type type = allTypes.items[j].type;
|
|
MethodInfo[] methods = type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy);
|
|
for (int k = 0; k < methods.Length; k++)
|
|
{
|
|
string text = methods[k].ToString();
|
|
if (text.IndexOf(name, StringComparison.CurrentCultureIgnoreCase) != -1)
|
|
{
|
|
Log(customAssembly.name + "." + type.Name + "." + text);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private Vector2 GetDockPos()
|
|
{
|
|
float num = WindowManager.instance.windowData.guiScale.value * 2f;
|
|
return new Vector2(((float)Screen.width / num - consoleWindow.rect.width / 2f) / (float)Screen.width, 0f);
|
|
}
|
|
|
|
private void CalcDraw(bool reset)
|
|
{
|
|
LogEntry.showCommandLogs = logs[0].show.Value;
|
|
LogEntry.showUnityLogs = logs[2].show.Value;
|
|
LogEntry.showWarningLogs = logs[3].show.Value;
|
|
LogEntry.showErrorLogs = logs[4].show.Value;
|
|
LogEntry.showExceptionLogs = logs[5].show.Value;
|
|
LogEntry.showStack = _showStack.Value;
|
|
if (reset)
|
|
{
|
|
LogEntry.lastLog = null;
|
|
}
|
|
cullLists.Clear();
|
|
if (logs[0].show.Value)
|
|
{
|
|
cullLists.Add(logs[0]);
|
|
}
|
|
if (showUnityLogs.Value)
|
|
{
|
|
for (int i = 1; i <= 5; i++)
|
|
{
|
|
if (logs[i].show.Value)
|
|
{
|
|
cullLists.Add(logs[i]);
|
|
}
|
|
}
|
|
}
|
|
cullGroup.CalcDraw(reset, cullLists);
|
|
}
|
|
|
|
public void MyOnGUI()
|
|
{
|
|
Event current = Event.current;
|
|
if (Helper.IsShowKeyPressed(current, useSameEditorAsBuildShowKey, showToggleKeyEditor, showToggleKeyBuild))
|
|
{
|
|
SetActive(!show);
|
|
}
|
|
else
|
|
{
|
|
if (!show)
|
|
{
|
|
return;
|
|
}
|
|
if (current.type == EventType.Layout && calcDraw)
|
|
{
|
|
calcDraw = false;
|
|
CalcDraw(reset: true);
|
|
}
|
|
if (consoleWindow.isDocked.Value)
|
|
{
|
|
if (consoleWindow.drag == 1)
|
|
{
|
|
if (consoleWindow.position != GetDockPos())
|
|
{
|
|
consoleWindow.isDocked.Value = false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
consoleWindow.position = GetDockPos();
|
|
}
|
|
}
|
|
consoleWindow.Update(700f, 94f);
|
|
GUI.skin = windowData.skin;
|
|
if (WindowManager.instance.useCanvas)
|
|
{
|
|
GUI.backgroundColor = new Color(1f, 1f, 1f, 0f);
|
|
}
|
|
else
|
|
{
|
|
GUI.backgroundColor = windowData.color;
|
|
}
|
|
Helper.DrawWindow(23423022, consoleWindow, DrawConsole);
|
|
DrawAutoComplete();
|
|
}
|
|
}
|
|
|
|
private void DrawConsole(int windowId)
|
|
{
|
|
WindowManager.BeginRenderTextureGUI();
|
|
Event current = Event.current;
|
|
windowData.skin.box.fontStyle = FontStyle.Bold;
|
|
Rect rect = consoleWindow.rect;
|
|
GUI.backgroundColor = Helper.GetColor(windowData, backgroundColor);
|
|
GUI.Box(new Rect(0f, 0f, rect.width, rect.height), "");
|
|
GUILayout.Box("Console");
|
|
Helper.Drag(consoleWindow, null, null, titleDrag: true, onlyRightCorner: true);
|
|
GUI.backgroundColor = Color.white;
|
|
DrawButtons();
|
|
DrawLogs(current, rect);
|
|
GUILayout.Space(1f);
|
|
DrawInput(current, rect);
|
|
drawLogsScrollBar = DrawLogsScrollBar(current);
|
|
GUILayout.Space(-1f);
|
|
Helper.Drag(consoleWindow, null, null, titleDrag: false, onlyRightCorner: true);
|
|
WindowManager.SetToolTip(windowId);
|
|
WindowManager.EndRenderTextureGUI();
|
|
}
|
|
|
|
private void DrawButtons()
|
|
{
|
|
GUISkin skin = windowData.skin;
|
|
int num = 80;
|
|
GUILayout.BeginHorizontal();
|
|
if (Helper.DrawShowButton(windowData, Helper.GetGUIContent("Commands", "Show/Hide Command Logs"), logs[0].show, selectColor, num))
|
|
{
|
|
calcDraw = true;
|
|
}
|
|
if (Helper.DrawShowButton(windowData, Helper.GetGUIContent("Unity Log", "Show/Hide Debug Logs"), showUnityLogs, selectColor, num))
|
|
{
|
|
calcDraw = true;
|
|
}
|
|
if (showUnityLogs.Value)
|
|
{
|
|
GUIContent gUIContent = windowData.logIcon.GetGUIContent();
|
|
gUIContent.tooltip = "Show/Hide Debug Logs";
|
|
float width = skin.button.CalcSize(gUIContent).x + 2f;
|
|
if (Helper.DrawShowButton(windowData, gUIContent, logs[2].show, selectColor, width))
|
|
{
|
|
calcDraw = true;
|
|
}
|
|
GUIContent gUIContent2 = windowData.warningIcon.GetGUIContent();
|
|
gUIContent2.tooltip = "Show/Hide Debug Warnings";
|
|
width = skin.button.CalcSize(gUIContent2).x + 2f;
|
|
if (Helper.DrawShowButton(windowData, gUIContent2, logs[3].show, selectColor, width))
|
|
{
|
|
calcDraw = true;
|
|
}
|
|
GUIContent gUIContent3 = windowData.errorIcon.GetGUIContent();
|
|
gUIContent3.tooltip = "Show/Hide Debug Errors";
|
|
width = skin.button.CalcSize(gUIContent3).x + 2f;
|
|
if (Helper.DrawShowButton(windowData, gUIContent3, logs[4].show, selectColor, width))
|
|
{
|
|
calcDraw = true;
|
|
}
|
|
GUIContent gUIContent4 = windowData.exceptionIcon.GetGUIContent();
|
|
gUIContent4.tooltip = "Show/Hide Debug Exceptions";
|
|
width = skin.button.CalcSize(gUIContent4).x + 2f;
|
|
if (Helper.DrawShowButton(windowData, gUIContent4, logs[5].show, selectColor, width))
|
|
{
|
|
calcDraw = true;
|
|
}
|
|
if (Helper.DrawShowButton(windowData, Helper.GetGUIContent("Stack", _showStack.Value ? windowData.texStackOn : windowData.texStackOff, "Show/Hide Stack Trace"), _showStack, selectColor, num))
|
|
{
|
|
calcDraw = true;
|
|
}
|
|
}
|
|
if (GUILayout.Button(Helper.GetGUIContent("Html Log", "Open Html Log in browser"), GUILayout.Width(num)))
|
|
{
|
|
if ((bool)HtmlDebug.instance)
|
|
{
|
|
Application.OpenURL("file://" + HtmlDebug.instance.logPathIncludingFilename);
|
|
}
|
|
else
|
|
{
|
|
Debug.LogError("Can't find Html Debug, make sure you have the 'Html Debug' GameObject in your Scene and that it's enabled");
|
|
}
|
|
}
|
|
if (GUILayout.Button(Helper.GetGUIContent("Logs Folder", "Open Logs Folder in File Exlorer"), GUILayout.Width(num)))
|
|
{
|
|
if ((bool)HtmlDebug.instance)
|
|
{
|
|
if ((bool)HtmlDebug.instance)
|
|
{
|
|
Application.OpenURL("file://" + HtmlDebug.instance.logPath);
|
|
}
|
|
else
|
|
{
|
|
Application.OpenURL("file://" + Application.persistentDataPath);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Debug.LogError("Can't find Html Debug, make sure you have the 'Html Debug' GameObject in your Scene and that it's enabled");
|
|
}
|
|
}
|
|
if (!consoleWindow.isDocked.Value && GUILayout.Button(Helper.GetGUIContent("Dock", "Centers the window in the top of the screen"), GUILayout.Width(num)))
|
|
{
|
|
consoleWindow.isDocked.Value = true;
|
|
}
|
|
GUILayout.EndHorizontal();
|
|
GUI.backgroundColor = Color.white;
|
|
}
|
|
|
|
private void DrawLogs(Event currentEvent, Rect window)
|
|
{
|
|
GUISkin skin = windowData.skin;
|
|
rectScroll = new Rect(4f, 54f, window.width - (float)(drawLogsScrollBar ? 22 : 10), window.height - 80f);
|
|
bool value = _showStack.Value;
|
|
CullList cullList = cullGroup.cullList;
|
|
if (currentEvent.type == EventType.Layout)
|
|
{
|
|
scrollViewEndHeight = 0.0;
|
|
if (cullList.cullItems.Count > 0)
|
|
{
|
|
scrollViewEndHeight = cullList.cullItems.items[cullList.cullItems.Count - 1].endHeight;
|
|
}
|
|
double y = scrollViewEndHeight - (double)rectScroll.height;
|
|
if (scrollViewEndHeight > (double)rectScroll.height && showLastLog.Value)
|
|
{
|
|
scrollView.y = y;
|
|
}
|
|
scrollViewHeights = new Double2(scrollView.y, scrollView.y + (double)rectScroll.height);
|
|
cullList.Cull(scrollViewHeights);
|
|
}
|
|
if (cullList.cullItems.Count == 0)
|
|
{
|
|
return;
|
|
}
|
|
GUILayout.BeginArea(rectScroll);
|
|
GUILayout.Space((float)(cullList.cullItems.items[cullList.startIndex].startHeight - scrollView.y));
|
|
for (int i = cullList.startIndex; i <= cullList.endIndex; i++)
|
|
{
|
|
LogEntry logEntry = (LogEntry)cullList.cullItems.items[i];
|
|
skin.label.fontSize = logEntry.fontSize;
|
|
skin.label.fontStyle = logEntry.fontStyle;
|
|
if (logEntry.entryType == EntryType.Frame)
|
|
{
|
|
GUILayout.Space(20f);
|
|
}
|
|
GUILayout.BeginHorizontal();
|
|
if (logEntry.entryType == EntryType.Unity)
|
|
{
|
|
if (logEntry.logType == LogType.Warning)
|
|
{
|
|
GUI.color = Color.yellow;
|
|
}
|
|
else if (logEntry.logType == LogType.Error)
|
|
{
|
|
GUI.color = Color.red;
|
|
}
|
|
else if (logEntry.logType == LogType.Exception)
|
|
{
|
|
GUI.color = Color.magenta;
|
|
}
|
|
else if (logEntry.logType == LogType.Log)
|
|
{
|
|
GUI.color = Color.white;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
GUI.color = logEntry.color;
|
|
}
|
|
if (logEntry.entryType == EntryType.Unity || logEntry.entryType == EntryType.Console || logEntry.entryType == EntryType.Command || logEntry.entryType == EntryType.CommandResult)
|
|
{
|
|
GUILayout.Space(30f);
|
|
}
|
|
if (logEntry.threadString != null)
|
|
{
|
|
float x = GUI.skin.label.CalcSize(Helper.GetGUIContent(logEntry.logString)).x;
|
|
GUILayout.Label(logEntry.logString, GUILayout.Width(x));
|
|
}
|
|
else
|
|
{
|
|
GUILayout.Label(logEntry.logString);
|
|
}
|
|
if (logEntry.entryType == EntryType.Unity || logEntry.entryType == EntryType.Console || logEntry.entryType == EntryType.Command)
|
|
{
|
|
Rect lastRect = GUILayoutUtility.GetLastRect();
|
|
lastRect.x -= 12f;
|
|
lastRect.y += logEntry.fontSize / 2;
|
|
if (logEntry.entryType == EntryType.Unity)
|
|
{
|
|
lastRect.width = 4f;
|
|
lastRect.height = 4f;
|
|
GUI.DrawTexture(lastRect, windowData.texDot);
|
|
}
|
|
else
|
|
{
|
|
lastRect.y -= 2f;
|
|
lastRect.width = 8f;
|
|
lastRect.height = 8f;
|
|
GUI.DrawTexture(lastRect, windowData.texArrow);
|
|
}
|
|
}
|
|
if (logEntry.threadString != null)
|
|
{
|
|
GUI.skin.label.fontStyle = FontStyle.Italic;
|
|
GUILayout.Label(logEntry.threadString);
|
|
GUI.skin.label.fontStyle = FontStyle.Normal;
|
|
}
|
|
GUILayout.EndHorizontal();
|
|
if (value && logEntry.stackLines != null)
|
|
{
|
|
skin.label.fontSize = stackFontSize;
|
|
GUILayout.Space(-3f);
|
|
GUI.color *= 0.825f;
|
|
for (int j = 0; j < logEntry.stackLines.Length; j++)
|
|
{
|
|
GUILayout.BeginHorizontal();
|
|
GUILayout.Space(30f);
|
|
GUILayout.Label(logEntry.stackLines[j]);
|
|
GUILayout.EndHorizontal();
|
|
}
|
|
}
|
|
GUI.color = Color.white;
|
|
if (!logs[0].show.RealValue && !showUnityLogs.RealValue)
|
|
{
|
|
showUnityLogs.Value = true;
|
|
}
|
|
}
|
|
skin.label.fontSize = 12;
|
|
skin.label.fontStyle = FontStyle.Normal;
|
|
GUILayout.EndArea();
|
|
}
|
|
|
|
private bool DrawLogsScrollBar(Event currentEvent)
|
|
{
|
|
Rect position = new Rect
|
|
{
|
|
y = 55f,
|
|
x = rectScroll.width + 5f,
|
|
width = 20f,
|
|
height = consoleWindow.rect.height - 80f
|
|
};
|
|
double num = scrollViewEndHeight - (double)rectScroll.height;
|
|
if (scrollViewEndHeight > (double)rectScroll.height)
|
|
{
|
|
if (currentEvent.isScrollWheel && autoCompleteList.Count == 0)
|
|
{
|
|
scrollView.y += currentEvent.delta.y * 10f;
|
|
showLastLog.Value = scrollView.y >= num;
|
|
}
|
|
if (showLastLog.Value)
|
|
{
|
|
scrollView.y = num;
|
|
}
|
|
GUI.changed = false;
|
|
scrollView.y = GUI.VerticalScrollbar(position, (float)scrollView.y, rectScroll.height, 0f, (float)scrollViewEndHeight);
|
|
if (GUI.changed)
|
|
{
|
|
showLastLog.Value = scrollView.y >= num - 0.10000000149011612;
|
|
}
|
|
return true;
|
|
}
|
|
scrollView.y = 0.0;
|
|
return false;
|
|
}
|
|
|
|
private void DrawInput(Event currentEvent, Rect window)
|
|
{
|
|
GUILayout.Space(window.height - 82f);
|
|
int num = 45;
|
|
TextEditor textEditor = (TextEditor)GUIUtility.GetStateObject(typeof(TextEditor), GUIUtility.keyboardControl);
|
|
int num2 = textEditor?.cursorIndex ?? 0;
|
|
bool flag = GUI.GetNameOfFocusedControl() == "ConsoleInput";
|
|
if (flag)
|
|
{
|
|
if (currentEvent.type == EventType.KeyDown && currentEvent.keyCode == KeyCode.Return)
|
|
{
|
|
showLastLog.Value = true;
|
|
commands.Add(inputCommand);
|
|
commandIndex = commands.Count;
|
|
if (!FindCommand(inputCommand))
|
|
{
|
|
AutoCompleteInputCommand();
|
|
}
|
|
ExecuteCommand(inputCommand);
|
|
inputCommand = string.Empty;
|
|
setFocus = true;
|
|
}
|
|
if (currentEvent.type == EventType.KeyDown)
|
|
{
|
|
if (currentEvent.keyCode == KeyCode.DownArrow && num2 > 0)
|
|
{
|
|
autoCompleteIndex++;
|
|
updateAutoCompleteScrollView = true;
|
|
}
|
|
else if (currentEvent.keyCode == KeyCode.UpArrow && num2 > 0)
|
|
{
|
|
moveInputCursor = 1;
|
|
autoCompleteIndex--;
|
|
updateAutoCompleteScrollView = true;
|
|
}
|
|
else if (currentEvent.keyCode != KeyCode.Tab)
|
|
{
|
|
autoCompleteIndex = 0;
|
|
updateAutoCompleteScrollView = true;
|
|
}
|
|
}
|
|
}
|
|
autoCompleteIndex = Helper.Repeat(autoCompleteIndex, autoCompleteList.Count);
|
|
GUILayout.BeginHorizontal();
|
|
GUILayout.Space(4f);
|
|
GUI.SetNextControlName("ConsoleInput");
|
|
GUI.color = Color.white;
|
|
GUI.backgroundColor = Color.white;
|
|
GUI.changed = false;
|
|
if (currentEvent.type == EventType.KeyDown)
|
|
{
|
|
if (currentEvent.keyCode == showToggleKeyEditor.keyCode)
|
|
{
|
|
addInput = false;
|
|
}
|
|
else if (addInput)
|
|
{
|
|
inputCommand = GUILayout.TextField(inputCommand, GUILayout.Width(window.width - 8f - (float)((num + 4) * 2 + 18)));
|
|
}
|
|
else
|
|
{
|
|
addInput = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
GUILayout.TextField(inputCommand, GUILayout.Width(window.width - 8f - (float)((num + 4) * 2 + 18)));
|
|
}
|
|
if (GUI.changed && addInput)
|
|
{
|
|
if (inputCommand.Length >= 2 && inputCommand[0] == searchCommandPrefix)
|
|
{
|
|
LogEntry.search = inputCommand.Substring(1);
|
|
LogEntry.ignoreCasesInSearch = ignoreCasesInSearch;
|
|
CalcDraw(reset: true);
|
|
}
|
|
else if (LogEntry.search != string.Empty)
|
|
{
|
|
LogEntry.search = string.Empty;
|
|
CalcDraw(reset: true);
|
|
}
|
|
}
|
|
if (moveInputCursor != 0 && textEditor != null)
|
|
{
|
|
if (moveInputCursor == 1)
|
|
{
|
|
textEditor.MoveTextEnd();
|
|
}
|
|
else if (moveInputCursor == -1)
|
|
{
|
|
textEditor.MoveTextStart();
|
|
}
|
|
moveInputCursor = 0;
|
|
}
|
|
if (GUILayout.Button(Helper.GetGUIContent("Clear", "Clear all Logs"), GUILayout.Width(num)))
|
|
{
|
|
Clear();
|
|
}
|
|
Helper.DrawShowButton(windowData, Helper.GetGUIContent("Last", "Scroll to last Log"), showLastLog, selectColor, num);
|
|
Rect lastRect = GUILayoutUtility.GetLastRect();
|
|
lastRect.x += num + 7;
|
|
lastRect.y += 9f;
|
|
lastRect.width = 10f;
|
|
lastRect.height = 10f;
|
|
if (new Rect(lastRect.x, lastRect.y, 16f, 16f).Contains(currentEvent.mousePosition))
|
|
{
|
|
GUI.color = Color.white;
|
|
}
|
|
else
|
|
{
|
|
GUI.color = Color.grey;
|
|
}
|
|
GUI.Label(lastRect, Helper.GetGUIContent(windowData.texCornerScale, "Resize console window"));
|
|
GUI.color = Color.white;
|
|
GUILayout.EndHorizontal();
|
|
if (commands.Count > 0 && num2 == 0)
|
|
{
|
|
if (currentEvent.keyCode == KeyCode.UpArrow && currentEvent.type == EventType.KeyUp)
|
|
{
|
|
commandIndex--;
|
|
if (commandIndex < 0)
|
|
{
|
|
commandIndex = 0;
|
|
}
|
|
inputCommand = commands.items[commandIndex];
|
|
}
|
|
else if (currentEvent.keyCode == KeyCode.DownArrow)
|
|
{
|
|
if (currentEvent.type == EventType.KeyUp)
|
|
{
|
|
commandIndex++;
|
|
if (commandIndex > commands.Count - 1)
|
|
{
|
|
commandIndex = commands.Count - 1;
|
|
inputCommand = string.Empty;
|
|
}
|
|
else
|
|
{
|
|
inputCommand = commands.items[commandIndex];
|
|
}
|
|
}
|
|
moveInputCursor = -1;
|
|
}
|
|
}
|
|
if (flag)
|
|
{
|
|
GetAutoCompleteList(inputCommand);
|
|
}
|
|
else
|
|
{
|
|
ClearAutoCompleteList();
|
|
}
|
|
if (currentEvent.type == EventType.Repaint && setFocus)
|
|
{
|
|
setFocus = false;
|
|
GUI.FocusControl("ConsoleInput");
|
|
}
|
|
}
|
|
|
|
private void DrawAutoComplete()
|
|
{
|
|
Event current = Event.current;
|
|
if (autoCompleteList.Count != oldAutoCompleteCount && current.type == EventType.Layout)
|
|
{
|
|
oldAutoCompleteCount = autoCompleteList.Count;
|
|
updateAutoCompleteScrollView = true;
|
|
}
|
|
if (autoCompleteList.Count > 0 && autoCompleteList.Count == oldAutoCompleteCount)
|
|
{
|
|
rectAutoComplete = consoleWindow.rect;
|
|
rectAutoComplete.y += rectAutoComplete.height;
|
|
rectAutoComplete.height = Mathf.Min(autoCompleteList.Count * 25 + 2, 302);
|
|
rectAutoComplete.width += 10f;
|
|
GUI.skin = windowData.skinAutoComplete;
|
|
GUILayout.Window(23423023, rectAutoComplete, DrawAutoComplete, GUIContent.none);
|
|
GUI.skin = windowData.skin;
|
|
}
|
|
if (current.type == EventType.KeyDown && current.keyCode == KeyCode.Tab)
|
|
{
|
|
AutoCompleteInputCommand();
|
|
}
|
|
}
|
|
|
|
private void DrawAutoComplete(int windowId)
|
|
{
|
|
WindowManager.BeginRenderTextureGUI();
|
|
GUISkin skin = windowData.skin;
|
|
GUI.backgroundColor = backgroundColor;
|
|
GUI.Box(new Rect(0f, 0f, rectAutoComplete.width - 10f, rectAutoComplete.height), string.Empty);
|
|
GUI.backgroundColor = Color.white;
|
|
if (updateAutoCompleteScrollView)
|
|
{
|
|
updateAutoCompleteScrollView = false;
|
|
autoCompleteScrollView.y = Mathf.Max((float)(autoCompleteIndex * 25) - rectAutoComplete.height / 2f, 0f);
|
|
}
|
|
autoCompleteScrollView = GUILayout.BeginScrollView(autoCompleteScrollView);
|
|
float num = 0f;
|
|
float num2 = 0f;
|
|
float num3 = 0f;
|
|
float num4 = 0f;
|
|
for (int i = 0; i < autoCompleteList.Count; i++)
|
|
{
|
|
AutoComplete autoComplete = autoCompleteList.items[i];
|
|
CommandData commandData = autoComplete.commandData;
|
|
float x = skin.button.CalcSize(Helper.GetGUIContent(autoComplete.command)).x;
|
|
if (x > num)
|
|
{
|
|
num = x;
|
|
}
|
|
if (commandData.memberType == MemberType.Field || commandData.memberType == MemberType.Property)
|
|
{
|
|
object value = commandData.GetValue();
|
|
if (value != null)
|
|
{
|
|
x = skin.label.CalcSize(Helper.GetGUIContent(value.ToString())).x;
|
|
if (x > num3)
|
|
{
|
|
num3 = x;
|
|
}
|
|
}
|
|
}
|
|
x = skin.label.CalcSize(Helper.GetGUIContent(commandData.syntax)).x;
|
|
if (x > num2)
|
|
{
|
|
num2 = x;
|
|
}
|
|
int instanceCount = commandData.GetInstanceCount();
|
|
if (instanceCount > 0)
|
|
{
|
|
x = skin.label.CalcSize(Helper.GetGUIContent("Instances: " + instanceCount)).x;
|
|
if (x > num4)
|
|
{
|
|
num4 = x;
|
|
}
|
|
}
|
|
}
|
|
num2 += 15f;
|
|
if (num3 > 0f)
|
|
{
|
|
num3 += 15f;
|
|
}
|
|
if (num4 > 0f)
|
|
{
|
|
num4 += 15f;
|
|
}
|
|
GUILayout.Space(-2f);
|
|
for (int j = 0; j < autoCompleteList.Count; j++)
|
|
{
|
|
AutoComplete autoComplete2 = autoCompleteList.items[j];
|
|
CommandData commandData2 = autoComplete2.commandData;
|
|
string command = autoComplete2.command;
|
|
if (j % 2 == 0)
|
|
{
|
|
Rect rect = GUILayoutUtility.GetRect(0f, 27f);
|
|
rect.width = rectAutoComplete.width - 11f;
|
|
rect.y += 2f;
|
|
rect.height -= 2f;
|
|
GUILayout.Space(-27f);
|
|
GUI.backgroundColor = new Color(0.0675f, 0.0675f, 0.0675f, 1f);
|
|
GUI.Box(rect, string.Empty);
|
|
GUI.backgroundColor = Color.white;
|
|
}
|
|
GUILayout.BeginHorizontal();
|
|
GUI.backgroundColor = ((j == autoCompleteIndex) ? Color.green : Color.white);
|
|
if (GUILayout.Button(command, GUILayout.Width(num)))
|
|
{
|
|
inputCommand = command;
|
|
moveInputCursor = 1;
|
|
}
|
|
GUILayout.BeginVertical();
|
|
GUILayout.Space(7f);
|
|
GUILayout.BeginHorizontal();
|
|
GUILayout.Label(commandData2.syntax, GUILayout.Width(num2));
|
|
if (num3 > 0f)
|
|
{
|
|
if (commandData2.memberType == MemberType.Field || commandData2.memberType == MemberType.Property)
|
|
{
|
|
object value2 = commandData2.GetValue();
|
|
if (value2 != null)
|
|
{
|
|
GUI.color = Color.green;
|
|
GUILayout.Label(value2.ToString(), GUILayout.Width(num3));
|
|
GUI.color = Color.white;
|
|
}
|
|
else
|
|
{
|
|
GUILayout.Space(num3);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
GUILayout.Space(num3);
|
|
}
|
|
}
|
|
if (num4 > 0f)
|
|
{
|
|
int instanceCount2 = commandData2.GetInstanceCount();
|
|
if (instanceCount2 > 0)
|
|
{
|
|
GUI.color = new Color(0.3f, 0.5f, 1f, 1f);
|
|
GUILayout.Label("Instances: " + instanceCount2, GUILayout.Width(num4));
|
|
GUI.color = Color.white;
|
|
}
|
|
else
|
|
{
|
|
GUILayout.Space(num4);
|
|
}
|
|
}
|
|
if (commandData2.consoleCommand != null && commandData2.consoleCommand.description != string.Empty)
|
|
{
|
|
GUI.color = Color.yellow;
|
|
GUILayout.Label(commandData2.consoleCommand.description);
|
|
GUI.color = Color.white;
|
|
}
|
|
GUILayout.EndHorizontal();
|
|
GUILayout.Space(-7f);
|
|
GUILayout.EndVertical();
|
|
GUILayout.EndHorizontal();
|
|
}
|
|
GUI.backgroundColor = Color.white;
|
|
GUILayout.EndScrollView();
|
|
WindowManager.EndRenderTextureGUI();
|
|
}
|
|
|
|
private void AutoCompleteInputCommand()
|
|
{
|
|
if (autoCompleteList.Count > 0)
|
|
{
|
|
inputCommand = inputCommand.TrimStart(' ');
|
|
int num = IsRemoteCommand(ref inputCommand);
|
|
string text = string.Empty;
|
|
int num2 = inputCommand.IndexOf(' ');
|
|
if (num2 != -1)
|
|
{
|
|
text = inputCommand.Substring(num2);
|
|
}
|
|
inputCommand = autoCompleteList.items[autoCompleteIndex].command + text;
|
|
switch (num)
|
|
{
|
|
case 1:
|
|
inputCommand = "#" + inputCommand;
|
|
break;
|
|
case 2:
|
|
inputCommand = "$" + inputCommand;
|
|
break;
|
|
}
|
|
if (inputCommand[inputCommand.Length - 1] == '.')
|
|
{
|
|
inputCommand = inputCommand.Substring(0, inputCommand.Length - 1);
|
|
}
|
|
moveInputCursor = 1;
|
|
}
|
|
}
|
|
|
|
private void ClearAutoCompleteList()
|
|
{
|
|
lastAutoCompleteCommand = string.Empty;
|
|
autoCompleteList.FastClear();
|
|
}
|
|
|
|
private void GetAutoCompleteList(string command)
|
|
{
|
|
if (command == lastAutoCompleteCommand)
|
|
{
|
|
if (command == string.Empty && autoCompleteList.Count > 0)
|
|
{
|
|
ClearAutoCompleteList();
|
|
}
|
|
return;
|
|
}
|
|
lastAutoCompleteCommand = command;
|
|
ClearAutoCompleteList();
|
|
command = command.Trim(' ');
|
|
if (command == string.Empty || command[0] == searchCommandPrefix)
|
|
{
|
|
return;
|
|
}
|
|
int num = command.IndexOf(" ");
|
|
if (num != -1)
|
|
{
|
|
command = command.Substring(0, num);
|
|
}
|
|
IsRemoteCommand(ref command);
|
|
if (command == string.Empty)
|
|
{
|
|
return;
|
|
}
|
|
if (command[0] == '?')
|
|
{
|
|
command = command.Substring(1);
|
|
}
|
|
string[] names = commandsTable.names;
|
|
for (int i = 0; i < names.Length; i++)
|
|
{
|
|
if (!(ignoreCasesInAutoCompleteInput ? names[i].StartsWith(command, StringComparison.CurrentCultureIgnoreCase) : names[i].StartsWith(command)))
|
|
{
|
|
continue;
|
|
}
|
|
string text = names[i];
|
|
CommandData commandData = commandsTable.lookup[text];
|
|
if (commandData.consoleCommand == null)
|
|
{
|
|
if (accessLevel != AccessLevel.Admin)
|
|
{
|
|
continue;
|
|
}
|
|
bool flag = false;
|
|
for (int j = i + 1; j < names.Length && (ignoreCasesInAutoCompleteInput ? names[j].StartsWith(text, StringComparison.CurrentCultureIgnoreCase) : names[j].StartsWith(text)); j++)
|
|
{
|
|
CommandData commandData2 = commandsTable.lookup[names[j]];
|
|
if (commandData2.consoleCommand != null && commandData2.consoleCommand.HasAccess(accessLevel) && commandData2.IsRegistered())
|
|
{
|
|
flag = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!flag)
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
else if (!commandData.consoleCommand.HasAccess(accessLevel) || !commandData.IsRegistered())
|
|
{
|
|
continue;
|
|
}
|
|
autoCompleteList.Add(new AutoComplete(text, commandData));
|
|
}
|
|
}
|
|
|
|
private static bool TryParse(Type t, FastQueue<string> paramQueue, out object result)
|
|
{
|
|
bool valid = true;
|
|
if (t == typeof(Vector2))
|
|
{
|
|
Vector2 vector = default(Vector2);
|
|
for (int i = 0; i < 2; i++)
|
|
{
|
|
object obj = ChangeType(typeof(float), paramQueue, ref valid);
|
|
if (obj != null)
|
|
{
|
|
vector[i] = (float)obj;
|
|
continue;
|
|
}
|
|
result = null;
|
|
return false;
|
|
}
|
|
result = vector;
|
|
}
|
|
else if (t == typeof(Vector3))
|
|
{
|
|
Vector3 vector2 = default(Vector3);
|
|
for (int j = 0; j < 3; j++)
|
|
{
|
|
object obj2 = ChangeType(typeof(float), paramQueue, ref valid);
|
|
if (obj2 != null)
|
|
{
|
|
vector2[j] = (float)obj2;
|
|
continue;
|
|
}
|
|
result = null;
|
|
return false;
|
|
}
|
|
result = vector2;
|
|
}
|
|
else if (t == typeof(Vector4))
|
|
{
|
|
Vector4 vector3 = default(Vector4);
|
|
for (int k = 0; k < 4; k++)
|
|
{
|
|
object obj3 = ChangeType(typeof(float), paramQueue, ref valid);
|
|
if (obj3 != null)
|
|
{
|
|
vector3[k] = (float)obj3;
|
|
continue;
|
|
}
|
|
result = null;
|
|
return false;
|
|
}
|
|
result = vector3;
|
|
}
|
|
else if (t == typeof(Quaternion))
|
|
{
|
|
Quaternion quaternion = default(Quaternion);
|
|
for (int l = 0; l < 4; l++)
|
|
{
|
|
object obj4 = ChangeType(typeof(float), paramQueue, ref valid);
|
|
if (obj4 != null)
|
|
{
|
|
quaternion[l] = (float)obj4;
|
|
continue;
|
|
}
|
|
result = null;
|
|
return false;
|
|
}
|
|
result = quaternion;
|
|
}
|
|
else
|
|
{
|
|
result = ChangeType(t, paramQueue, ref valid);
|
|
}
|
|
return valid;
|
|
}
|
|
|
|
private static object ChangeType(Type t, FastQueue<string> paramQueue, ref bool valid)
|
|
{
|
|
if (paramQueue.Count == 0)
|
|
{
|
|
LogResultError("Not enough parameters");
|
|
valid = false;
|
|
return null;
|
|
}
|
|
string text = paramQueue.Dequeue();
|
|
text = text.Trim();
|
|
if (t == typeof(string))
|
|
{
|
|
return text;
|
|
}
|
|
if (t == typeof(bool))
|
|
{
|
|
bool.TryParse(text, out var result);
|
|
return result;
|
|
}
|
|
if (t == typeof(byte))
|
|
{
|
|
byte.TryParse(text, out var result2);
|
|
return result2;
|
|
}
|
|
if (t == typeof(sbyte))
|
|
{
|
|
sbyte.TryParse(text, out var result3);
|
|
return result3;
|
|
}
|
|
if (t == typeof(char))
|
|
{
|
|
char.TryParse(text, out var result4);
|
|
return result4;
|
|
}
|
|
if (t == typeof(decimal))
|
|
{
|
|
decimal.TryParse(text, out var result5);
|
|
return result5;
|
|
}
|
|
if (t == typeof(double))
|
|
{
|
|
double.TryParse(text, out var result6);
|
|
return result6;
|
|
}
|
|
if (t == typeof(float))
|
|
{
|
|
float.TryParse(text, out var result7);
|
|
return result7;
|
|
}
|
|
if (t == typeof(int))
|
|
{
|
|
int.TryParse(text, out var result8);
|
|
return result8;
|
|
}
|
|
if (t == typeof(uint))
|
|
{
|
|
uint.TryParse(text, out var result9);
|
|
return result9;
|
|
}
|
|
if (t == typeof(long))
|
|
{
|
|
long.TryParse(text, out var result10);
|
|
return result10;
|
|
}
|
|
if (t == typeof(ulong))
|
|
{
|
|
ulong.TryParse(text, out var result11);
|
|
return result11;
|
|
}
|
|
if (t == typeof(short))
|
|
{
|
|
short.TryParse(text, out var result12);
|
|
return result12;
|
|
}
|
|
if (t == typeof(ushort))
|
|
{
|
|
ushort.TryParse(text, out var result13);
|
|
return result13;
|
|
}
|
|
if (t.IsEnum)
|
|
{
|
|
try
|
|
{
|
|
return Enum.Parse(t, text, ignoreCase: true);
|
|
}
|
|
catch (Exception)
|
|
{
|
|
LogResultError("Cannot find '" + text + "'");
|
|
}
|
|
}
|
|
valid = false;
|
|
return null;
|
|
}
|
|
}
|
|
}
|