diff --git a/src/UI/Inspectors/InspectorManager.cs b/src/Core/InspectorManager.cs similarity index 75% rename from src/UI/Inspectors/InspectorManager.cs rename to src/Core/InspectorManager.cs index f9fa3c5..87a37b3 100644 --- a/src/UI/Inspectors/InspectorManager.cs +++ b/src/Core/InspectorManager.cs @@ -4,17 +4,20 @@ using System.Linq; using System.Text; using UnityEngine; using UnityEngine.UI; +using UnityExplorer.UI; using UnityExplorer.UI.CacheObject; +using UnityExplorer.UI.Inspectors; using UnityExplorer.UI.ObjectPool; using UnityExplorer.UI.Panels; -namespace UnityExplorer.UI.Inspectors +namespace UnityExplorer { public static class InspectorManager { public static readonly List Inspectors = new List(); public static InspectorBase ActiveInspector { get; private set; } + private static InspectorBase lastActiveInspector; public static float PanelWidth; @@ -28,10 +31,6 @@ namespace UnityExplorer.UI.Inspectors if (TryFocusActiveInspector(obj)) return; - // var type = obj.GetActualType(); - //if (type.IsEnumerable()) - // CreateInspector(obj, false, sourceCache); - //// todo dict if (obj is GameObject) CreateInspector(obj); else @@ -68,9 +67,12 @@ namespace UnityExplorer.UI.Inspectors public static void UnsetActiveInspector() { if (ActiveInspector != null) + { + lastActiveInspector = ActiveInspector; ActiveInspector.OnSetInactive(); + ActiveInspector = null; + } } - private static void CreateInspector(object target, bool staticReflection = false, CacheObjectBase sourceCache = null) where T : InspectorBase { var inspector = Pool.Borrow(); @@ -96,10 +98,35 @@ namespace UnityExplorer.UI.Inspectors internal static void ReleaseInspector(T inspector) where T : InspectorBase { + if (lastActiveInspector == inspector) + lastActiveInspector = null; + + bool wasActive = ActiveInspector == inspector; + int wasIdx = Inspectors.IndexOf(inspector); + + Inspectors.Remove(inspector); inspector.OnReturnToPool(); Pool.Return(inspector); - Inspectors.Remove(inspector); + if (wasActive) + { + ActiveInspector = null; + // Try focus another inspector, or close the window. + if (lastActiveInspector != null) + { + SetInspectorActive(lastActiveInspector); + lastActiveInspector = null; + } + else if (Inspectors.Any()) + { + int newIdx = Math.Min(Inspectors.Count - 1, Math.Max(0, wasIdx - 1)); + SetInspectorActive(Inspectors[newIdx]); + } + else + { + UIManager.SetPanelActive(UIManager.Panels.Inspector, false); + } + } } internal static void Update() diff --git a/src/Core/Search/ChildFilter.cs b/src/Core/Search/ChildFilter.cs deleted file mode 100644 index 081641b..0000000 --- a/src/Core/Search/ChildFilter.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace UnityExplorer.Core.Search -{ - public enum ChildFilter - { - Any, - RootObject, - HasParent - } -} diff --git a/src/Core/Search/SceneFilter.cs b/src/Core/Search/SceneFilter.cs deleted file mode 100644 index 5310e08..0000000 --- a/src/Core/Search/SceneFilter.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace UnityExplorer.Core.Search -{ - public enum SceneFilter - { - Any, - ActivelyLoaded, - DontDestroyOnLoad, - HideAndDontSave, - } -} diff --git a/src/Core/Search/SearchContext.cs b/src/Core/Search/SearchContext.cs deleted file mode 100644 index d26fb8a..0000000 --- a/src/Core/Search/SearchContext.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace UnityExplorer.Core.Search -{ - public enum SearchContext - { - UnityObject, - GameObject, - //Component, - //Custom, - Singleton, - StaticClass - } -} diff --git a/src/Core/Tests/TestClass.cs b/src/Core/Tests/TestClass.cs index f4fb641..5f83fb3 100644 --- a/src/Core/Tests/TestClass.cs +++ b/src/Core/Tests/TestClass.cs @@ -4,6 +4,8 @@ using System.Collections.Generic; using System.Linq; using System.Text; using UnityEngine; +using UnityExplorer.UI.IValues; +using System.Reflection; #if CPP using UnhollowerRuntimeLib; using UnhollowerBaseLib; @@ -11,8 +13,69 @@ using UnhollowerBaseLib; namespace UnityExplorer.Tests { + public struct TestValueStruct + { + public const object TestIgnoreThis = null; + public const string TestIgnoreButValid = ""; + + public string aString; + public int anInt; + public float aFloat; + public bool aBool; + public Vector3 AVector3; + public Vector4 aVector4; + public DateTime aDateTime; + public Color32 aColor32; + public CameraClearFlags clearFlags; + } + + public enum TestEnum : long + { + Neg50 = -50, + Neg1 = -1, + Zero = 0, + One = 1, + Pos49 = 49, + Implicit50, + Also50 = 50, + AlsoAlso50 = 50, + }; + public enum TestEnum2 : ulong + { + Min = ulong.MinValue, + Max = ulong.MaxValue + } + [Flags] + public enum TestFlags : int + { + All = -1, + Zero = 0, + Ok = 1, + Two = 2, + Three = 4, + Four = 8, + Five = 16, + Six = 32, + Seven = 64, + Thirteen = Six | Seven, + Fifteen = Four | Five | Six, + } + public static class TestClass { + public static void ATestMethod(string s, float f, Vector3 vector, DateTime date, Quaternion quater, bool b, CameraClearFlags enumvalue) + { + ExplorerCore.Log($"{s}, {f}, {vector.ToString()}, {date}, {quater.eulerAngles.ToString()}, {b}, {enumvalue}"); + } + + public static TestValueStruct AATestStruct; + + public static TestEnum AATestEnumOne = TestEnum.Neg50; + public static TestEnum2 AATestEnumTwo = TestEnum2.Max; + public static TestFlags AATestFlags = TestFlags.Thirteen; + public static BindingFlags AATestbinding; + public static HideFlags AAHideFlags; + public static List AWritableList = new List { 1, 2, 3, 4, 5 }; public static Dictionary AWritableDict = new Dictionary { { "one", 1 }, { "two", 2 } }; @@ -67,6 +130,9 @@ namespace UnityExplorer.Tests public const int ConstantInt = 5; + public static Color AColor = Color.magenta; + public static Color32 AColor32 = Color.red; + public static byte[] ByteArray = new byte[16]; public static string LongString = new string('#', 10000); public static List BigList = new List(10000); @@ -123,7 +189,6 @@ namespace UnityExplorer.Tests } #if CPP - public static List TestWritableBoxedList; public static string testStringOne = "Test"; public static Il2CppSystem.Object testStringTwo = "string boxed as cpp object"; @@ -141,6 +206,21 @@ namespace UnityExplorer.Tests public static Il2CppSystem.Object cppDecimalBoxed; public static Il2CppSystem.Object cppVector3Boxed; + public static Il2CppSystem.Object RandomBoxedColor + { + get + { + int ran = UnityEngine.Random.Range(0, 3); + switch (ran) + { + case 1: return new Color32().BoxIl2CppObject(); + case 2: return Color.magenta.BoxIl2CppObject(); + default: + return null; + } + } + } + public static Il2CppSystem.Collections.Hashtable cppHashset; public static Dictionary CppBoxedDict; @@ -167,6 +247,7 @@ namespace UnityExplorer.Tests CppBoxedList = new List(); CppBoxedList.Add((Il2CppSystem.String)"boxedString"); CppBoxedList.Add(new Il2CppSystem.Int32 { m_value = 5 }.BoxIl2CppObject()); + CppBoxedList.Add(Color.red.BoxIl2CppObject()); try { @@ -205,12 +286,6 @@ namespace UnityExplorer.Tests cppBoxedInt = new Il2CppSystem.Int32() { m_value = 5 }.BoxIl2CppObject(); cppInt = new Il2CppSystem.Int32 { m_value = 420 }; - TestWritableBoxedList = new List(); - TestWritableBoxedList.Add(new Il2CppSystem.Int32 { m_value = 1 }.BoxIl2CppObject()); - TestWritableBoxedList.Add(new Il2CppSystem.Int32 { m_value = 2 }.BoxIl2CppObject()); - TestWritableBoxedList.Add(new Il2CppSystem.Int32 { m_value = 3 }.BoxIl2CppObject()); - TestWritableBoxedList.Add(new Il2CppSystem.Int32 { m_value = 4 }.BoxIl2CppObject()); - cppHashset = new Il2CppSystem.Collections.Hashtable(); cppHashset.Add("key1", "itemOne"); cppHashset.Add("key2", "itemTwo"); diff --git a/src/Core/Utility/ParseUtility.cs b/src/Core/Utility/ParseUtility.cs index 4fb6e82..089f81d 100644 --- a/src/Core/Utility/ParseUtility.cs +++ b/src/Core/Utility/ParseUtility.cs @@ -23,7 +23,7 @@ namespace UnityExplorer { if (string.IsNullOrEmpty(type.FullName)) return false; - return type.IsPrimitive || nonPrimitiveTypes.Contains(type) || customTypes.ContainsKey(type.FullName); + return type.IsPrimitive || type.IsEnum || nonPrimitiveTypes.Contains(type) || customTypes.ContainsKey(type.FullName); } public static bool TryParse(string input, Type type, out object obj, out Exception parseException) @@ -40,6 +40,20 @@ namespace UnityExplorer return true; } + if (type.IsEnum) + { + try + { + obj = Enum.Parse(type, input); + return true; + } + catch (Exception ex) + { + parseException = ex.GetInnerMostException(); + return false; + } + } + try { if (customTypes.ContainsKey(type.FullName)) @@ -63,6 +77,12 @@ namespace UnityExplorer return false; } + private static readonly HashSet nonFormattedTypes = new HashSet + { + typeof(IntPtr), + typeof(UIntPtr), + }; + public static string ToStringForInput(object obj, Type type) { if (type == null || obj == null) @@ -71,6 +91,13 @@ namespace UnityExplorer if (type == typeof(string)) return obj as string; + if (type.IsEnum) + { + return Enum.IsDefined(type, obj) + ? Enum.GetName(type, obj) + : obj.ToString(); + } + try { if (customTypes.ContainsKey(type.FullName)) @@ -79,10 +106,8 @@ namespace UnityExplorer } else { - if (obj is IntPtr ptr) - return ptr.ToString(); - else if (obj is UIntPtr uPtr) - return uPtr.ToString(); + if (nonFormattedTypes.Contains(type)) + return obj.ToString(); else return ReflectionUtility.GetMethodInfo(type, "ToString", new Type[] { typeof(IFormatProvider) }) .Invoke(obj, new object[] { en_US }) @@ -104,8 +129,15 @@ namespace UnityExplorer { try { - var instance = Activator.CreateInstance(type); - typeInputExamples.Add(type.AssemblyQualifiedName, ToStringForInput(instance, type)); + if (type.IsEnum) + { + typeInputExamples.Add(type.AssemblyQualifiedName, Enum.GetNames(type).First()); + } + else + { + var instance = Activator.CreateInstance(type); + typeInputExamples.Add(type.AssemblyQualifiedName, ToStringForInput(instance, type)); + } } catch (Exception ex) { diff --git a/src/Core/Utility/SignatureHighlighter.cs b/src/Core/Utility/SignatureHighlighter.cs index 3e7a1a3..03d22d3 100644 --- a/src/Core/Utility/SignatureHighlighter.cs +++ b/src/Core/Utility/SignatureHighlighter.cs @@ -231,6 +231,18 @@ namespace UnityExplorer return sb.ToString(); } + public static string GetMemberInfoColor(MemberTypes type) + { + switch (type) + { + case MemberTypes.Method: return METHOD_INSTANCE; + case MemberTypes.Property: return PROP_INSTANCE; + case MemberTypes.Field: return FIELD_INSTANCE; + default: return null; + } + } + + public static string GetMemberInfoColor(MemberInfo memberInfo, out bool isStatic) { isStatic = false; diff --git a/src/UI/CSConsole/CSConsole.cs b/src/UI/CSConsole/CSConsole.cs new file mode 100644 index 0000000..edc659b --- /dev/null +++ b/src/UI/CSConsole/CSConsole.cs @@ -0,0 +1,237 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using UnityEngine; +using UnityEngine.UI; +using UnityExplorer.Core.CSharp; +using UnityExplorer.Core.Input; +using UnityExplorer.UI.Panels; + +namespace UnityExplorer.UI.CSharpConsole +{ + public static class CSConsole + { + #region Strings / defaults + + internal const string STARTUP_TEXT = @"Welcome to the UnityExplorer C# Console. + +The following helper methods are available: + +* Log(""message"") logs a message to the debug console + +* StartCoroutine(IEnumerator routine) start the IEnumerator as a UnityEngine.Coroutine + +* CurrentTarget() returns the currently inspected target on the Home page + +* AllTargets() returns an object[] array containing all inspected instances + +* Inspect(someObject) to inspect an instance, eg. Inspect(Camera.main); + +* Inspect(typeof(SomeClass)) to inspect a Class with static reflection + +* AddUsing(""SomeNamespace"") adds a using directive to the C# console + +* GetUsing() logs the current using directives to the debug console + +* Reset() resets all using directives and variables +"; + + internal static readonly string[] DefaultUsing = new string[] + { + "System", + "System.Linq", + "System.Collections", + "System.Collections.Generic", + "System.Reflection", + "UnityEngine", +#if CPP + "UnhollowerBaseLib", + "UnhollowerRuntimeLib", +#endif + }; + + #endregion + + public static ScriptEvaluator Evaluator; + public static CSLexer Lexer; + + private static StringBuilder evaluatorOutput; + private static HashSet usingDirectives; + + private static CSConsolePanel Panel => UIManager.CSharpConsole; + private static InputField InputField => Panel.InputField.InputField; + + // Todo save as config? + public static bool EnableCtrlRShortcut { get; private set; } = true; + public static bool EnableAutoIndent { get; private set; } = true; + public static bool EnableSuggestions { get; private set; } = true; + + public static void Init() + { + try + { + Lexer = new CSLexer(); + + ResetConsole(false); + Evaluator.Compile("0 == 0"); + + Panel.OnInputChanged += OnConsoleInputChanged; + // TODO other panel listeners + + } + catch (Exception ex) + { + ExplorerCore.LogWarning(ex); + } + } + + #region Evaluating console input + + public static void ResetConsole(bool logSuccess = true) + { + if (Evaluator != null) + Evaluator.Dispose(); + + evaluatorOutput = new StringBuilder(); + Evaluator = new ScriptEvaluator(new StringWriter(evaluatorOutput)) + { + InteractiveBaseClass = typeof(ScriptInteraction) + }; + + usingDirectives = new HashSet(); + foreach (var use in DefaultUsing) + AddUsing(use); + + if (logSuccess) + ExplorerCore.Log($"C# Console reset. Using directives:\r\n{Evaluator.GetUsing()}"); + } + + public static void AddUsing(string assemblyName) + { + if (!usingDirectives.Contains(assemblyName)) + { + Evaluate($"using {assemblyName};", true); + usingDirectives.Add(assemblyName); + } + } + + public static void Evaluate(string input, bool supressLog = false) + { + try + { + Evaluator.Run(input); + + string output = ScriptEvaluator._textWriter.ToString(); + var outputSplit = output.Split('\n'); + if (outputSplit.Length >= 2) + output = outputSplit[outputSplit.Length - 2]; + evaluatorOutput.Clear(); + + if (ScriptEvaluator._reportPrinter.ErrorsCount > 0) + throw new FormatException($"Unable to compile the code. Evaluator's last output was:\r\n{output}"); + + if (!supressLog) + ExplorerCore.Log("Code executed successfully."); + } + catch (FormatException fex) + { + if (!supressLog) + ExplorerCore.LogWarning(fex.Message); + } + catch (Exception ex) + { + if (!supressLog) + ExplorerCore.LogWarning(ex); + } + } + + #endregion + + // Updating and event listeners + + private static readonly KeyCode[] onFocusKeys = + { + KeyCode.Return, KeyCode.Backspace, KeyCode.UpArrow, + KeyCode.DownArrow, KeyCode.LeftArrow, KeyCode.RightArrow + }; + + public static void Update() + { + if (EnableCtrlRShortcut) + { + if ((InputManager.GetKey(KeyCode.LeftControl) || InputManager.GetKey(KeyCode.RightControl)) + && InputManager.GetKeyDown(KeyCode.R)) + { + var text = Panel.InputField.Text.Trim(); + if (!string.IsNullOrEmpty(text)) + { + Evaluate(text); + return; + } + } + } + + if (EnableAutoIndent && InputManager.GetKeyDown(KeyCode.Return)) + DoAutoIndent(); + + //if (EnableAutocompletes && InputField.isFocused) + //{ + // if (InputManager.GetMouseButton(0) || onFocusKeys.Any(it => InputManager.GetKeyDown(it))) + // UpdateAutocompletes(); + //} + } + + private static void OnConsoleInputChanged(string input) + { + // todo update auto completes + + // todo update syntax highlight + + } + + // Autocompletes + + private static string SyntaxHighlight(string input) + { + var sb = new StringBuilder(); + int curIdx = 0; + foreach (var match in Lexer.GetMatches(input)) + { + // append non-highlighted text between last match and this + for (int i = curIdx; i < match.startIndex; i++) + sb.Append(input[i]); + + // append the highlighted match + sb.Append(match.htmlColorTag); + + for (int i = match.startIndex; i < match.endIndex; i++) + sb.Append(input[i]); + + sb.Append(SignatureHighlighter.CLOSE_COLOR); + + // update the index + curIdx = match.endIndex; + } + + return sb.ToString(); + } + + // Indent + + private static void DoAutoIndent() + { + int caret = Panel.LastCaretPosition; + Panel.InputField.Text = Lexer.AutoIndentOnEnter(InputField.text, ref caret); + InputField.caretPosition = caret; + + Panel.InputText.Rebuild(CanvasUpdate.Prelayout); + InputField.ForceLabelUpdate(); + InputField.Rebuild(CanvasUpdate.Prelayout); + + OnConsoleInputChanged(InputField.text); + } + + } +} diff --git a/src/UI/CSConsole/CSConsoleManager.cs b/src/UI/CSConsole/CSConsoleManager.cs deleted file mode 100644 index d72d33e..0000000 --- a/src/UI/CSConsole/CSConsoleManager.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace UnityExplorer.UI.CSConsole -{ - public static class CSConsoleManager - { - internal const string STARTUP_TEXT = @"Welcome to the UnityExplorer C# Console. - -The following helper methods are available: - -* Log(""message"") logs a message to the debug console - -* StartCoroutine(IEnumerator routine) start the IEnumerator as a UnityEngine.Coroutine - -* CurrentTarget() returns the currently inspected target on the Home page - -* AllTargets() returns an object[] array containing all inspected instances - -* Inspect(someObject) to inspect an instance, eg. Inspect(Camera.main); - -* Inspect(typeof(SomeClass)) to inspect a Class with static reflection - -* AddUsing(""SomeNamespace"") adds a using directive to the C# console - -* GetUsing() logs the current using directives to the debug console - -* Reset() resets all using directives and variables -"; - - } -} diff --git a/src/UI/CSConsole/CSLexer.cs b/src/UI/CSConsole/CSLexer.cs new file mode 100644 index 0000000..0555d8f --- /dev/null +++ b/src/UI/CSConsole/CSLexer.cs @@ -0,0 +1,354 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using UnityEngine.UI; +using UnityExplorer.UI.CSharpConsole.Lexer; + +namespace UnityExplorer.UI.CSharpConsole +{ + public struct LexerMatchInfo + { + public int startIndex; + public int endIndex; + public string htmlColorTag; + } + + public enum DelimiterType + { + Start, + End, + }; + + public class CSLexer + { + private string inputString; + private readonly Matcher[] matchers; + private readonly HashSet startDelimiters; + private readonly HashSet endDelimiters; + private int currentIndex; + private int currentLookaheadIndex; + + public char Current { get; private set; } + public char Previous { get; private set; } + + public bool EndOfStream => currentLookaheadIndex >= inputString.Length; + + public static char indentOpen = '{'; + public static char indentClose = '}'; + //private static StringBuilder indentBuilder = new StringBuilder(); + + public static char[] delimiters = new[] + { + '[', ']', '(', ')', '{', '}', ';', ':', ',', '.' + }; + + private static readonly CommentMatch commentMatcher = new CommentMatch(); + private static readonly SymbolMatch symbolMatcher = new SymbolMatch(); + private static readonly NumberMatch numberMatcher = new NumberMatch(); + private static readonly StringMatch stringMatcher = new StringMatch(); + private static readonly KeywordMatch keywordMatcher = new KeywordMatch(); + + public CSLexer() + { + startDelimiters = new HashSet(delimiters); + endDelimiters = new HashSet(delimiters); + + this.matchers = new Matcher[] + { + commentMatcher, + symbolMatcher, + numberMatcher, + stringMatcher, + keywordMatcher, + }; + + foreach (Matcher lexer in matchers) + { + foreach (char c in lexer.StartChars) + { + if (!startDelimiters.Contains(c)) + startDelimiters.Add(c); + } + + foreach (char c in lexer.EndChars) + { + if (!endDelimiters.Contains(c)) + endDelimiters.Add(c); + } + } + } + + public IEnumerable GetMatches(string input) + { + if (input == null || matchers == null || matchers.Length == 0) + yield break; + + inputString = input; + Current = ' '; + Previous = ' '; + currentIndex = 0; + currentLookaheadIndex = 0; + + while (!EndOfStream) + { + bool didMatchLexer = false; + + ReadWhiteSpace(); + + foreach (Matcher matcher in matchers) + { + int startIndex = currentIndex; + + bool isMatched = matcher.IsMatch(this); + + if (isMatched) + { + int endIndex = currentIndex; + + didMatchLexer = true; + + yield return new LexerMatchInfo + { + startIndex = startIndex, + endIndex = endIndex, + htmlColorTag = matcher.HexColorTag, + }; + + break; + } + } + + if (!didMatchLexer) + { + ReadNext(); + Commit(); + } + } + } + + // Lexer reading + + public char ReadNext() + { + if (EndOfStream) + return '\0'; + + Previous = Current; + + Current = inputString[currentLookaheadIndex]; + currentLookaheadIndex++; + + return Current; + } + + public void Rollback(int amount = -1) + { + if (amount == -1) + currentLookaheadIndex = currentIndex; + else + { + if (currentLookaheadIndex > currentIndex) + currentLookaheadIndex -= amount; + } + + int previousIndex = currentLookaheadIndex - 1; + + if (previousIndex >= inputString.Length) + Previous = inputString[inputString.Length - 1]; + else if (previousIndex >= 0) + Previous = inputString[previousIndex]; + else + Previous = ' '; + } + + public void Commit() + { + currentIndex = currentLookaheadIndex; + } + + public bool IsSpecialSymbol(char character, DelimiterType position = DelimiterType.Start) + { + if (position == DelimiterType.Start) + return startDelimiters.Contains(character); + + return endDelimiters.Contains(character); + } + + private void ReadWhiteSpace() + { + while (char.IsWhiteSpace(ReadNext()) == true) + Commit(); + + Rollback(); + } + + // Auto-indenting + + public int GetIndentLevel(string input, int toIndex) + { + bool stringState = false; + int indent = 0; + + for (int i = 0; i < toIndex && i < input.Length; i++) + { + char character = input[i]; + + if (character == '"') + stringState = !stringState; + else if (!stringState && character == indentOpen) + indent++; + else if (!stringState && character == indentClose) + indent--; + } + + if (indent < 0) + indent = 0; + + return indent; + } + + // TODO not quite correct, but almost there. + + public string AutoIndentOnEnter(string input, ref int caretPos) + { + var sb = new StringBuilder(input); + + bool inString = false; + bool inChar = false; + int currentIndent = 0; + int curLineIndent = 0; + bool prevWasNewLine = true; + + // process before caret position + for (int i = 0; i < caretPos; i++) + { + char c = sb[i]; + + ExplorerCore.Log(i + ": " + c); + + // update string/char state + if (!inChar && c == '\"') + inString = !inString; + else if (!inString && c == '\'') + inChar = !inChar; + + // continue if inside string or char + if (inString || inChar) + continue; + + // check for new line + if (c == '\n') + { + ExplorerCore.Log("new line, resetting line counts"); + curLineIndent = 0; + prevWasNewLine = true; + } + // check for indent + else if (c == '\t' && prevWasNewLine) + { + ExplorerCore.Log("its a tab"); + if (curLineIndent > currentIndent) + { + ExplorerCore.Log("too many tabs, removing"); + // already reached the indent we should have + sb.Remove(i, 1); + i--; + caretPos--; + curLineIndent--; + } + else + curLineIndent++; + } + // remove spaces on new lines + else if (c == ' ' && prevWasNewLine) + { + ExplorerCore.Log("removing newline-space"); + sb.Remove(i, 1); + i--; + caretPos--; + } + else + { + if (prevWasNewLine && curLineIndent < currentIndent) + { + ExplorerCore.Log("line is not indented enough"); + // line is not indented enough + int diff = currentIndent - curLineIndent; + sb.Insert(i, new string('\t', diff)); + caretPos += diff; + i += diff; + } + + // check for brackets + if (c == indentClose || c == indentOpen) + { + ExplorerCore.Log("char is a bracket"); + + if (c == indentOpen) + currentIndent++; + else if (c == indentClose) + currentIndent--; + + if (!prevWasNewLine) + { + ExplorerCore.Log("it wasnt on a new line, doing so..."); + // need to put it on a new line + sb.Insert(i, $"\n{new string('\t', currentIndent - 1)}"); + caretPos += 1 + currentIndent; + i += 1 + currentIndent; + } + } + + prevWasNewLine = false; + } + } + + // process after caret position, make sure there are equal opened/closed brackets + ExplorerCore.Log("-- after caret --"); + for (int i = caretPos; i < sb.Length; i++) + { + char c = sb[i]; + ExplorerCore.Log(i + ": " + c); + + // update string/char state + if (!inChar && c == '\"') + inString = !inString; + else if (!inString && c == '\'') + inChar = !inChar; + + if (inString || inChar) + continue; + + if (c == indentOpen) + currentIndent++; + else if (c == indentClose) + currentIndent--; + } + + if (currentIndent > 0) + { + ExplorerCore.Log("there are not enough closing brackets, curIndent is " + currentIndent); + // There are not enough close brackets + + while (currentIndent > 0) + { + ExplorerCore.Log("Inserting closing bracket with " + currentIndent + " indent"); + // append the indented '}' on a new line + sb.Insert(caretPos, $"\n{new string('\t', currentIndent - 1)}}}"); + + currentIndent--; + } + + } + //else if (currentIndent < 0) + //{ + // // There are too many close brackets + // + // // todo? + //} + + return sb.ToString(); + } + } +} diff --git a/src/UI/CSConsole/Lexer/CommentMatch.cs b/src/UI/CSConsole/Lexer/CommentMatch.cs new file mode 100644 index 0000000..d888934 --- /dev/null +++ b/src/UI/CSConsole/Lexer/CommentMatch.cs @@ -0,0 +1,48 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace UnityExplorer.UI.CSharpConsole.Lexer +{ + public class CommentMatch : Matcher + { + public string lineCommentStart = @"//"; + public string blockCommentStart = @"/*"; + public string blockCommentEnd = @"*/"; + + public override Color HighlightColor => new Color(0.34f, 0.65f, 0.29f, 1.0f); + + public override IEnumerable StartChars => new char[] { lineCommentStart[0], blockCommentStart[0] }; + public override IEnumerable EndChars => new char[] { blockCommentEnd[0] }; + + public override bool IsImplicitMatch(CSLexer lexer) => IsMatch(lexer, lineCommentStart) || IsMatch(lexer, blockCommentStart); + + private bool IsMatch(CSLexer lexer, string commentType) + { + if (!string.IsNullOrEmpty(commentType)) + { + lexer.Rollback(); + + bool match = true; + for (int i = 0; i < commentType.Length; i++) + { + if (commentType[i] != lexer.ReadNext()) + { + match = false; + break; + } + } + + if (match) + { + // Read until end of line or file + while (!IsEndLineOrEndFile(lexer, lexer.ReadNext())) { } + + return true; + } + } + return false; + } + + private bool IsEndLineOrEndFile(CSLexer lexer, char character) => lexer.EndOfStream || character == '\n' || character == '\r'; + } +} diff --git a/src/UI/CSConsole/Lexer/KeywordMatch.cs b/src/UI/CSConsole/Lexer/KeywordMatch.cs new file mode 100644 index 0000000..12f768d --- /dev/null +++ b/src/UI/CSConsole/Lexer/KeywordMatch.cs @@ -0,0 +1,91 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace UnityExplorer.UI.CSharpConsole.Lexer +{ + public class KeywordMatch : Matcher + { + public string[] Keywords = new[] { "add", "as", "ascending", "await", "bool", "break", "by", "byte", +"case", "catch", "char", "checked", "const", "continue", "decimal", "default", "descending", "do", "dynamic", +"else", "equals", "false", "finally", "float", "for", "foreach", "from", "global", "goto", "group", +"if", "in", "int", "into", "is", "join", "let", "lock", "long", "new", "null", "object", "on", "orderby", "out", +"ref", "remove", "return", "sbyte", "select", "short", "sizeof", "stackalloc", "string", +"switch", "throw", "true", "try", "typeof", "uint", "ulong", "ushort", "var", "where", "while", "yield", +"abstract", "async", "base", "class", "delegate", "enum", "explicit", "extern", "fixed", "get", +"implicit", "interface", "internal", "namespace", "operator", "override", "params", "private", "protected", "public", +"using", "partial", "readonly", "sealed", "set", "static", "struct", "this", "unchecked", "unsafe", "value", "virtual", "volatile", "void" }; + + public override Color HighlightColor => highlightColor; + public Color highlightColor = new Color(0.33f, 0.61f, 0.83f, 1.0f); + + private readonly HashSet shortlist = new HashSet(); + private readonly Stack removeList = new Stack(); + + public override bool IsImplicitMatch(CSLexer lexer) + { + if (!char.IsWhiteSpace(lexer.Previous) && + !lexer.IsSpecialSymbol(lexer.Previous, DelimiterType.End)) + { + return false; + } + + shortlist.Clear(); + + int currentIndex = 0; + char currentChar = lexer.ReadNext(); + + for (int i = 0; i < Keywords.Length; i++) + { + if (Keywords[i][0] == currentChar) + shortlist.Add(Keywords[i]); + } + + if (shortlist.Count == 0) + return false; + + do + { + if (lexer.EndOfStream) + { + RemoveLongStrings(currentIndex + 1); + break; + } + + currentChar = lexer.ReadNext(); + currentIndex++; + + if (char.IsWhiteSpace(currentChar) || + lexer.IsSpecialSymbol(currentChar, DelimiterType.Start)) + { + RemoveLongStrings(currentIndex); + lexer.Rollback(1); + break; + } + + foreach (string keyword in shortlist) + { + if (currentIndex >= keyword.Length || keyword[currentIndex] != currentChar) + removeList.Push(keyword); + } + + while (removeList.Count > 0) + shortlist.Remove(removeList.Pop()); + } + while (shortlist.Count > 0); + + return shortlist.Count > 0; + } + + private void RemoveLongStrings(int length) + { + foreach (string keyword in shortlist) + { + if (keyword.Length > length) + removeList.Push(keyword); + } + + while (removeList.Count > 0) + shortlist.Remove(removeList.Pop()); + } + } +} diff --git a/src/UI/CSConsole/Lexer/Matcher.cs b/src/UI/CSConsole/Lexer/Matcher.cs new file mode 100644 index 0000000..4c73b79 --- /dev/null +++ b/src/UI/CSConsole/Lexer/Matcher.cs @@ -0,0 +1,31 @@ +using System.Collections.Generic; +using UnityEngine; +using System.Linq; + +namespace UnityExplorer.UI.CSharpConsole.Lexer +{ + public abstract class Matcher + { + public abstract Color HighlightColor { get; } + + public string HexColorTag => htmlColor ?? (htmlColor = ""); + private string htmlColor; + + public virtual IEnumerable StartChars => Enumerable.Empty(); + public virtual IEnumerable EndChars => Enumerable.Empty(); + + public abstract bool IsImplicitMatch(CSLexer lexer); + + public bool IsMatch(CSLexer lexer) + { + if (IsImplicitMatch(lexer)) + { + lexer.Commit(); + return true; + } + + lexer.Rollback(); + return false; + } + } +} diff --git a/src/UI/CSConsole/Lexer/NumberMatch.cs b/src/UI/CSConsole/Lexer/NumberMatch.cs new file mode 100644 index 0000000..df194cf --- /dev/null +++ b/src/UI/CSConsole/Lexer/NumberMatch.cs @@ -0,0 +1,39 @@ +using UnityEngine; + +namespace UnityExplorer.UI.CSharpConsole.Lexer +{ + public class NumberMatch : Matcher + { + public override Color HighlightColor => new Color(0.58f, 0.33f, 0.33f, 1.0f); + + public override bool IsImplicitMatch(CSLexer lexer) + { + if (!char.IsWhiteSpace(lexer.Previous) && + !lexer.IsSpecialSymbol(lexer.Previous, DelimiterType.End)) + { + return false; + } + + bool matchedNumber = false; + + while (!lexer.EndOfStream) + { + if (IsNumberOrDecimalPoint(lexer.ReadNext())) + { + matchedNumber = true; + lexer.Commit(); + } + else + { + lexer.Rollback(); + break; + } + } + + return matchedNumber; + } + + private bool IsNumberOrDecimalPoint(char character) => char.IsNumber(character) || character == '.'; + } + +} diff --git a/src/UI/CSConsole/Lexer/StringMatch.cs b/src/UI/CSConsole/Lexer/StringMatch.cs new file mode 100644 index 0000000..685fbb6 --- /dev/null +++ b/src/UI/CSConsole/Lexer/StringMatch.cs @@ -0,0 +1,26 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace UnityExplorer.UI.CSharpConsole.Lexer +{ + public class StringMatch : Matcher + { + public override Color HighlightColor => new Color(0.79f, 0.52f, 0.32f, 1.0f); + + public override IEnumerable StartChars => new[] { '"' }; + public override IEnumerable EndChars => new[] { '"' }; + + public override bool IsImplicitMatch(CSLexer lexer) + { + if (lexer.ReadNext() == '"') + { + while (!IsClosingQuoteOrEndFile(lexer, lexer.ReadNext())) { } + + return true; + } + return false; + } + + private bool IsClosingQuoteOrEndFile(CSLexer lexer, char character) => lexer.EndOfStream || character == '"'; + } +} diff --git a/src/UI/CSConsole/Lexer/SymbolMatch.cs b/src/UI/CSConsole/Lexer/SymbolMatch.cs new file mode 100644 index 0000000..bc0ae23 --- /dev/null +++ b/src/UI/CSConsole/Lexer/SymbolMatch.cs @@ -0,0 +1,98 @@ +using System.Collections.Generic; +using System.Linq; +using UnityEngine; + +namespace UnityExplorer.UI.CSharpConsole.Lexer +{ + public class SymbolMatch : Matcher + { + public override Color HighlightColor => new Color(0.58f, 0.47f, 0.37f, 1.0f); + + private readonly string[] symbols = new[] + { + "[", "]", "(", ")", ".", "?", ":", "+", "-", "*", "/", "%", "&", "|", "^", "~", "=", "<", ">", + "++", "--", "&&", "||", "<<", ">>", "==", "!=", "<=", ">=", "+=", "-=", "*=", "/=", "%=", "&=", + "|=", "^=", "<<=", ">>=", "->", "??", "=>", + }; + + private static readonly List shortlist = new List(); + private static readonly Stack removeList = new Stack(); + + public override IEnumerable StartChars => symbols.Select(s => s[0]); + public override IEnumerable EndChars => symbols.Select(s => s[0]); + + public override bool IsImplicitMatch(CSLexer lexer) + { + if (lexer == null) + return false; + + if (!char.IsWhiteSpace(lexer.Previous) && + !char.IsLetter(lexer.Previous) && + !char.IsDigit(lexer.Previous) && + !lexer.IsSpecialSymbol(lexer.Previous, DelimiterType.End)) + { + return false; + } + + shortlist.Clear(); + + int currentIndex = 0; + char currentChar = lexer.ReadNext(); + + for (int i = symbols.Length - 1; i >= 0; i--) + { + if (symbols[i][0] == currentChar) + shortlist.Add(symbols[i]); + } + + if (shortlist.Count == 0) + return false; + + do + { + if (lexer.EndOfStream) + { + RemoveLongStrings(currentIndex + 1); + break; + } + + currentChar = lexer.ReadNext(); + currentIndex++; + + if (char.IsWhiteSpace(currentChar) || + char.IsLetter(currentChar) || + char.IsDigit(currentChar) || + lexer.IsSpecialSymbol(currentChar, DelimiterType.Start)) + { + RemoveLongStrings(currentIndex); + lexer.Rollback(1); + break; + } + + foreach (string symbol in shortlist) + { + if (currentIndex >= symbol.Length || symbol[currentIndex] != currentChar) + removeList.Push(symbol); + } + + while (removeList.Count > 0) + shortlist.Remove(removeList.Pop()); + } + while (shortlist.Count > 0); + + return shortlist.Count > 0; + } + + private void RemoveLongStrings(int length) + { + foreach (string keyword in shortlist) + { + if (keyword.Length > length) + removeList.Push(keyword); + } + + while (removeList.Count > 0) + shortlist.Remove(removeList.Pop()); + } + } +} diff --git a/src/Core/CSharp/ScriptEvaluator.cs b/src/UI/CSConsole/ScriptEvaluator.cs similarity index 98% rename from src/Core/CSharp/ScriptEvaluator.cs rename to src/UI/CSConsole/ScriptEvaluator.cs index 39f5ac4..cf01e8a 100644 --- a/src/Core/CSharp/ScriptEvaluator.cs +++ b/src/UI/CSConsole/ScriptEvaluator.cs @@ -65,9 +65,7 @@ namespace UnityExplorer.Core.CSharp { string name = assembly.GetName().Name; if (StdLib.Contains(name)) - { continue; - } import(assembly); } diff --git a/src/Core/CSharp/ScriptInteraction.cs b/src/UI/CSConsole/ScriptInteraction.cs similarity index 100% rename from src/Core/CSharp/ScriptInteraction.cs rename to src/UI/CSConsole/ScriptInteraction.cs diff --git a/src/UI/Inspectors/ReflectionInspector.cs b/src/UI/Inspectors/ReflectionInspector.cs index 9e9513f..8aef955 100644 --- a/src/UI/Inspectors/ReflectionInspector.cs +++ b/src/UI/Inspectors/ReflectionInspector.cs @@ -21,22 +21,27 @@ namespace UnityExplorer.UI.Inspectors public class ReflectionInspector : InspectorBase, IPoolDataSource, ICacheObjectController { public CacheObjectBase ParentCacheObject { get; set; } - public Type TargetType { get; private set; } - public bool CanWrite => true; - - // Instance state - public bool StaticOnly { get; internal set; } - - public BindingFlags FlagsFilter { get; private set; } - public string NameFilter { get; private set; } - - public bool AutoUpdateWanted { get; set; } + public bool CanWrite => true; private List members = new List(); private readonly List filteredMembers = new List(); + public bool AutoUpdateWanted { get; set; } + + private BindingFlags FlagsFilter; + private string NameFilter; + + private MemberFlags MemberFilter = MemberFlags.All; + private enum MemberFlags + { + None = 0, + Property = 1, + Field = 2, + Method = 4, + All = 7 + } // UI @@ -44,27 +49,15 @@ namespace UnityExplorer.UI.Inspectors public Text NameText; public Text AssemblyText; - - // Unity object helpers - private UnityEngine.Object ObjectRef; - private Component ComponentRef; - private Texture2D TextureRef; - private bool TextureViewerWanted; - private GameObject unityObjectRow; - private ButtonRef gameObjectButton; - private InputFieldRef nameInput; - private InputFieldRef instanceIdInput; - private ButtonRef textureButton; - private GameObject textureViewer; + private Toggle autoUpdateToggle; private readonly Color disabledButtonColor = new Color(0.24f, 0.24f, 0.24f); private readonly Color enabledButtonColor = new Color(0.2f, 0.27f, 0.2f); private readonly Dictionary scopeFilterButtons = new Dictionary(); + private readonly List memberTypeToggles = new List(); private InputFieldRef filterInputField; - //private LayoutElement memberTitleLayout; - - private Toggle autoUpdateToggle; + // Setup / return public override void OnBorrowedFromPool(object target) { @@ -144,7 +137,14 @@ namespace UnityExplorer.UI.Inspectors // Get cache members, and set filter to default this.members = CacheMember.GetCacheMembers(Target, TargetType, this); this.filterInputField.Text = ""; + SetFilter("", StaticOnly ? BindingFlags.Static : BindingFlags.Instance); + scopeFilterButtons[BindingFlags.Default].Button.gameObject.SetActive(!StaticOnly); + scopeFilterButtons[BindingFlags.Instance].Button.gameObject.SetActive(!StaticOnly); + + foreach (var toggle in memberTypeToggles) + toggle.isOn = true; + refreshWanted = true; } @@ -153,6 +153,7 @@ namespace UnityExplorer.UI.Inspectors private bool refreshWanted; private string lastNameFilter; private BindingFlags lastFlagsFilter; + private MemberFlags lastMemberFilter = MemberFlags.All; private float timeOfLastAutoUpdate; public override void Update() @@ -166,10 +167,11 @@ namespace UnityExplorer.UI.Inspectors return; } - if (refreshWanted || NameFilter != lastNameFilter || FlagsFilter != lastFlagsFilter) + if (refreshWanted || NameFilter != lastNameFilter || FlagsFilter != lastFlagsFilter || lastMemberFilter != MemberFilter) { lastNameFilter = NameFilter; lastFlagsFilter = FlagsFilter; + lastMemberFilter = MemberFilter; FilterMembers(); MemberScrollPool.Refresh(true, true); @@ -206,6 +208,14 @@ namespace UnityExplorer.UI.Inspectors } } + private void OnMemberTypeToggled(MemberFlags flag, bool val) + { + if (!val) + MemberFilter &= ~flag; + else + MemberFilter |= flag; + } + private void FilterMembers() { filteredMembers.Clear(); @@ -214,9 +224,6 @@ namespace UnityExplorer.UI.Inspectors { var member = members[i]; - if (!string.IsNullOrEmpty(NameFilter) && !member.NameForFiltering.ContainsIgnoreCase(NameFilter)) - continue; - if (FlagsFilter != BindingFlags.Default) { if (FlagsFilter == BindingFlags.Instance && member.IsStatic @@ -224,6 +231,14 @@ namespace UnityExplorer.UI.Inspectors continue; } + if ((member is CacheMethod && !MemberFilter.HasFlag(MemberFlags.Method)) + || (member is CacheField && !MemberFilter.HasFlag(MemberFlags.Field)) + || (member is CacheProperty && !MemberFilter.HasFlag(MemberFlags.Property))) + continue; + + if (!string.IsNullOrEmpty(NameFilter) && !member.NameForFiltering.ContainsIgnoreCase(NameFilter)) + continue; + filteredMembers.Add(member); } } @@ -313,9 +328,9 @@ namespace UnityExplorer.UI.Inspectors new Color(0.12f, 0.12f, 0.12f)); UIFactory.SetLayoutElement(mainContentHolder, flexibleWidth: 9999, flexibleHeight: 9999); - ConstructFilterRow(mainContentHolder); + ConstructFirstRow(mainContentHolder); - ConstructUpdateRow(mainContentHolder); + ConstructSecondRow(mainContentHolder); // Member scroll pool @@ -335,67 +350,115 @@ namespace UnityExplorer.UI.Inspectors return UIRoot; } - // Filter row + // First row - private void ConstructFilterRow(GameObject parent) + private void ConstructFirstRow(GameObject parent) { - var filterRow = UIFactory.CreateUIObject("FilterRow", parent); - UIFactory.SetLayoutGroup(filterRow, true, true, true, true, 5, 2, 2, 2, 2); - UIFactory.SetLayoutElement(filterRow, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999); + var rowObj = UIFactory.CreateUIObject("FirstRow", parent); + UIFactory.SetLayoutGroup(rowObj, true, true, true, true, 5, 2, 2, 2, 2); + UIFactory.SetLayoutElement(rowObj, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999); - var nameLabel = UIFactory.CreateLabel(filterRow, "NameFilterLabel", "Filter names:", TextAnchor.MiddleLeft, Color.grey); + var nameLabel = UIFactory.CreateLabel(rowObj, "NameFilterLabel", "Filter names:", TextAnchor.MiddleLeft, Color.grey); UIFactory.SetLayoutElement(nameLabel.gameObject, minHeight: 25, minWidth: 90, flexibleWidth: 0); - filterInputField = UIFactory.CreateInputField(filterRow, "NameFilterInput", "..."); + filterInputField = UIFactory.CreateInputField(rowObj, "NameFilterInput", "..."); UIFactory.SetLayoutElement(filterInputField.UIRoot, minHeight: 25, flexibleWidth: 300); filterInputField.OnValueChanged += (string val) => { SetFilter(val); }; - var spacer = UIFactory.CreateUIObject("Spacer", filterRow); + var spacer = UIFactory.CreateUIObject("Spacer", rowObj); UIFactory.SetLayoutElement(spacer, minWidth: 25); - var scopeLabel = UIFactory.CreateLabel(filterRow, "ScopeLabel", "Scope:", TextAnchor.MiddleLeft, Color.grey); - UIFactory.SetLayoutElement(scopeLabel.gameObject, minHeight: 25, minWidth: 60, flexibleWidth: 0); - AddFilterButton(filterRow, BindingFlags.Default, true); - AddFilterButton(filterRow, BindingFlags.Instance); - AddFilterButton(filterRow, BindingFlags.Static); + // Update button and toggle + + var updateButton = UIFactory.CreateButton(rowObj, "UpdateButton", "Update displayed values", new Color(0.22f, 0.28f, 0.22f)); + UIFactory.SetLayoutElement(updateButton.Button.gameObject, minHeight: 25, minWidth: 175, flexibleWidth: 0); + updateButton.OnClick += UpdateDisplayedMembers; + + var toggleObj = UIFactory.CreateToggle(rowObj, "AutoUpdateToggle", out autoUpdateToggle, out Text toggleText); + //GameObject.DestroyImmediate(toggleText); + UIFactory.SetLayoutElement(toggleObj, minWidth: 125, minHeight: 25); + autoUpdateToggle.isOn = false; + autoUpdateToggle.onValueChanged.AddListener((bool val) => { AutoUpdateWanted = val; }); + toggleText.text = "Auto-update"; } - private void AddFilterButton(GameObject parent, BindingFlags flags, bool setAsActive = false) + // Second row + + private void ConstructSecondRow(GameObject parent) + { + var rowObj = UIFactory.CreateUIObject("SecondRow", parent); + UIFactory.SetLayoutGroup(rowObj, false, false, true, true, 5, 2, 2, 2, 2); + UIFactory.SetLayoutElement(rowObj, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999); + + // Scope buttons + + var scopeLabel = UIFactory.CreateLabel(rowObj, "ScopeLabel", "Scope:", TextAnchor.MiddleLeft, Color.grey); + UIFactory.SetLayoutElement(scopeLabel.gameObject, minHeight: 25, minWidth: 60, flexibleWidth: 0); + AddScopeFilterButton(rowObj, BindingFlags.Default, true); + AddScopeFilterButton(rowObj, BindingFlags.Instance); + AddScopeFilterButton(rowObj, BindingFlags.Static); + + var spacer = UIFactory.CreateUIObject("Spacer", rowObj); + UIFactory.SetLayoutElement(spacer, minWidth: 15); + + // Member type toggles + + //var typeLabel = UIFactory.CreateLabel(rowObj, "MemberTypeLabel", "Show:", TextAnchor.MiddleLeft, Color.grey); + //UIFactory.SetLayoutElement(typeLabel.gameObject, minHeight: 25, minWidth: 40); + AddMemberTypeToggle(rowObj, MemberTypes.Property, 90); + AddMemberTypeToggle(rowObj, MemberTypes.Field, 70); + AddMemberTypeToggle(rowObj, MemberTypes.Method, 90); + } + + private void AddScopeFilterButton(GameObject parent, BindingFlags flags, bool setAsActive = false) { string lbl = flags == BindingFlags.Default ? "All" : flags.ToString(); var color = setAsActive ? enabledButtonColor : disabledButtonColor; var button = UIFactory.CreateButton(parent, "Filter_" + flags, lbl, color); - UIFactory.SetLayoutElement(button.Button.gameObject, minHeight: 25, flexibleHeight: 0, minWidth: 100, flexibleWidth: 0); + UIFactory.SetLayoutElement(button.Button.gameObject, minHeight: 25, flexibleHeight: 0, minWidth: 70, flexibleWidth: 0); scopeFilterButtons.Add(flags, button); button.OnClick += () => { SetFilter(flags); }; } - // Update row - - private void ConstructUpdateRow(GameObject parent) + private void AddMemberTypeToggle(GameObject parent, MemberTypes type, int width) { - var updateRow = UIFactory.CreateUIObject("UpdateRow", parent); - UIFactory.SetLayoutGroup(updateRow, false, false, true, true, 4); - UIFactory.SetLayoutElement(updateRow, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999); + var toggleObj = UIFactory.CreateToggle(parent, "Toggle_" + type, out Toggle toggle, out Text toggleText); + UIFactory.SetLayoutElement(toggleObj, minHeight: 25, minWidth: width); + toggleText.text = $"{type}"; - var updateButton = UIFactory.CreateButton(updateRow, "UpdateButton", "Update displayed values", new Color(0.22f, 0.28f, 0.22f)); - UIFactory.SetLayoutElement(updateButton.Button.gameObject, minHeight: 25, minWidth: 175, flexibleWidth: 0); - updateButton.OnClick += UpdateDisplayedMembers; + toggle.graphic.TryCast().color = new Color(0.25f, 0.25f, 0.25f); - var toggleObj = UIFactory.CreateToggle(updateRow, "AutoUpdateToggle", out autoUpdateToggle, out Text toggleText); - //GameObject.DestroyImmediate(toggleText); - UIFactory.SetLayoutElement(toggleObj, minWidth: 185, minHeight: 25); - autoUpdateToggle.isOn = false; - autoUpdateToggle.onValueChanged.AddListener((bool val) => { AutoUpdateWanted = val; }); - toggleText.text = "Auto-update displayed"; + MemberFlags flag; + switch (type) + { + case MemberTypes.Method: flag = MemberFlags.Method; break; + case MemberTypes.Property: flag = MemberFlags.Property; break; + case MemberTypes.Field: flag = MemberFlags.Field; break; + default: return; + } + + toggle.onValueChanged.AddListener((bool val) => { OnMemberTypeToggled(flag, val); }); + + memberTypeToggles.Add(toggle); } #region UNITY OBJECT SPECIFIC // Unity object helpers + private UnityEngine.Object ObjectRef; + private Component ComponentRef; + private Texture2D TextureRef; + private bool TextureViewerWanted; + private GameObject unityObjectRow; + private ButtonRef gameObjectButton; + private InputFieldRef nameInput; + private InputFieldRef instanceIdInput; + private ButtonRef textureButton; + private GameObject textureViewer; + private void SetUnityTargets() { if (!typeof(UnityEngine.Object).IsAssignableFrom(TargetType)) diff --git a/src/UI/Inspectors/TODO_InspectUnderMouse.cs b/src/UI/Inspectors/TODO_InspectUnderMouse.cs new file mode 100644 index 0000000..188618c --- /dev/null +++ b/src/UI/Inspectors/TODO_InspectUnderMouse.cs @@ -0,0 +1,327 @@ +//using System; +//using System.Collections.Generic; +//using System.Linq; +//using System.Text; +//using UnityEngine; +//using UnityEngine.EventSystems; +//using UnityEngine.UI; +//using UnityExplorer.Core; +//using UnityExplorer.Core.Input; +//using UnityExplorer.Core.Runtime; +//using UnityExplorer.UI; +//using UnityExplorer.UI.Main; +//using UnityExplorer.Inspectors; + +//namespace UnityExplorer.UI.Main.Home +//{ +// public class InspectUnderMouse +// { +// public enum MouseInspectMode +// { +// World, +// UI +// } + +// public static bool Inspecting { get; set; } + +// public static MouseInspectMode Mode { get; set; } + +// private static GameObject s_lastHit; +// private static Vector3 s_lastMousePos; + +// private static readonly List _wasDisabledGraphics = new List(); +// private static readonly List _wasDisabledCanvasGroups = new List(); +// private static readonly List _objectsAddedCastersTo = new List(); + +// internal static Camera MainCamera; +// internal static GraphicRaycaster[] graphicRaycasters; + +// public static void Init() +// { +// ConstructUI(); +// } + +// public static void StartInspect(MouseInspectMode mode) +// { +// MainCamera = Camera.main; +// if (!MainCamera) +// return; + +// Mode = mode; +// Inspecting = true; +// MainMenu.Instance.MainPanel.SetActive(false); + +// s_UIContent.SetActive(true); + +// if (mode == MouseInspectMode.UI) +// SetupUIRaycast(); +// } + +// internal static void ClearHitData() +// { +// s_lastHit = null; +// s_objNameLabel.text = "No hits..."; +// s_objPathLabel.text = ""; +// } + +// public static void StopInspect() +// { +// Inspecting = false; +// MainMenu.Instance.MainPanel.SetActive(true); +// s_UIContent.SetActive(false); + +// if (Mode == MouseInspectMode.UI) +// StopUIInspect(); + +// ClearHitData(); +// } + +// public static void UpdateInspect() +// { +// if (InputManager.GetKeyDown(KeyCode.Escape)) +// { +// StopInspect(); +// return; +// } + +// var mousePos = InputManager.MousePosition; + +// if (mousePos != s_lastMousePos) +// UpdatePosition(mousePos); + +// // actual inspect raycast + +// switch (Mode) +// { +// case MouseInspectMode.UI: +// RaycastUI(mousePos); break; +// case MouseInspectMode.World: +// RaycastWorld(mousePos); break; +// } +// } + +// internal static void UpdatePosition(Vector2 mousePos) +// { +// s_lastMousePos = mousePos; + +// var inversePos = UIManager.CanvasRoot.transform.InverseTransformPoint(mousePos); + +// s_mousePosLabel.text = $"Mouse Position: {mousePos.ToString()}"; + +// float yFix = mousePos.y < 120 ? 80 : -80; +// s_UIContent.transform.localPosition = new Vector3(inversePos.x, inversePos.y + yFix, 0); +// } + +// internal static void OnHitGameObject(GameObject obj) +// { +// if (obj != s_lastHit) +// { +// s_lastHit = obj; +// s_objNameLabel.text = $"Click to Inspect: {obj.name}"; +// s_objPathLabel.text = $"Path: {obj.transform.GetTransformPath(true)}"; +// } + +// if (InputManager.GetMouseButtonDown(0)) +// { +// StopInspect(); +// InspectorManager.Instance.Inspect(obj); +// } +// } + +// // Collider raycasting + +// internal static void RaycastWorld(Vector2 mousePos) +// { +// var ray = MainCamera.ScreenPointToRay(mousePos); +// Physics.Raycast(ray, out RaycastHit hit, 1000f); + +// if (hit.transform) +// { +// var obj = hit.transform.gameObject; +// OnHitGameObject(obj); +// } +// else +// { +// if (s_lastHit) +// ClearHitData(); +// } +// } + +// // UI Graphic raycasting + +// private static void SetupUIRaycast() +// { +// foreach (var obj in RuntimeProvider.Instance.FindObjectsOfTypeAll(typeof(Canvas))) +// { +// var canvas = obj.Cast(typeof(Canvas)) as Canvas; +// if (!canvas || !canvas.enabled || !canvas.gameObject.activeInHierarchy) +// continue; +// if (!canvas.GetComponent()) +// { +// canvas.gameObject.AddComponent(); +// //ExplorerCore.Log("Added raycaster to " + canvas.name); +// _objectsAddedCastersTo.Add(canvas.gameObject); +// } +// } + +// // recache Graphic Raycasters each time we start +// var casters = RuntimeProvider.Instance.FindObjectsOfTypeAll(typeof(GraphicRaycaster)); +// graphicRaycasters = new GraphicRaycaster[casters.Length]; +// for (int i = 0; i < casters.Length; i++) +// { +// graphicRaycasters[i] = casters[i].Cast(typeof(GraphicRaycaster)) as GraphicRaycaster; +// } + +// // enable raycastTarget on Graphics +// foreach (var obj in RuntimeProvider.Instance.FindObjectsOfTypeAll(typeof(Graphic))) +// { +// var graphic = obj.Cast(typeof(Graphic)) as Graphic; +// if (!graphic || !graphic.enabled || graphic.raycastTarget || !graphic.gameObject.activeInHierarchy) +// continue; +// graphic.raycastTarget = true; +// //ExplorerCore.Log("Enabled raycastTarget on " + graphic.name); +// _wasDisabledGraphics.Add(graphic); +// } + +// // enable blocksRaycasts on CanvasGroups +// foreach (var obj in RuntimeProvider.Instance.FindObjectsOfTypeAll(typeof(CanvasGroup))) +// { +// var canvas = obj.Cast(typeof(CanvasGroup)) as CanvasGroup; +// if (!canvas || !canvas.gameObject.activeInHierarchy || canvas.blocksRaycasts) +// continue; +// canvas.blocksRaycasts = true; +// //ExplorerCore.Log("Enabled raycasts on " + canvas.name); +// _wasDisabledCanvasGroups.Add(canvas); +// } +// } + +// internal static void RaycastUI(Vector2 mousePos) +// { +// var ped = new PointerEventData(null) +// { +// position = mousePos +// }; + +// //ExplorerCore.Log("~~~~~~~~~ begin raycast ~~~~~~~~"); +// GameObject hitObject = null; +// int highestLayer = int.MinValue; +// int highestOrder = int.MinValue; +// int highestDepth = int.MinValue; +// foreach (var gr in graphicRaycasters) +// { +// var list = new List(); +// RuntimeProvider.Instance.GraphicRaycast(gr, ped, list); + +// //gr.Raycast(ped, list); + +// if (list.Count > 0) +// { +// foreach (var hit in list) +// { +// // Manual trying to determine which object is "on top". +// // Not perfect, but not terrible. + +// if (!hit.gameObject) +// continue; + +// if (hit.gameObject.GetComponent() is CanvasGroup group && group.alpha == 0) +// continue; + +// if (hit.gameObject.GetComponent() is Graphic graphic && graphic.color.a == 0f) +// continue; + +// if (hit.sortingLayer < highestLayer) +// continue; + +// if (hit.sortingLayer > highestLayer) +// { +// highestLayer = hit.sortingLayer; +// highestDepth = int.MinValue; +// } + +// if (hit.depth < highestDepth) +// continue; + +// if (hit.depth > highestDepth) +// { +// highestDepth = hit.depth; +// highestOrder = int.MinValue; +// } + +// if (hit.sortingOrder <= highestOrder) +// continue; + +// highestOrder = hit.sortingOrder; +// hitObject = hit.gameObject; +// } +// } +// else +// { +// if (s_lastHit) +// ClearHitData(); +// } +// } + +// if (hitObject) +// OnHitGameObject(hitObject); + +// //ExplorerCore.Log("~~~~~~~~~ end raycast ~~~~~~~~"); +// } + +// private static void StopUIInspect() +// { +// foreach (var obj in _objectsAddedCastersTo) +// { +// if (obj.GetComponent() is GraphicRaycaster raycaster) +// GameObject.Destroy(raycaster); +// } + +// foreach (var graphic in _wasDisabledGraphics) +// graphic.raycastTarget = false; + +// foreach (var canvas in _wasDisabledCanvasGroups) +// canvas.blocksRaycasts = false; + +// _objectsAddedCastersTo.Clear(); +// _wasDisabledCanvasGroups.Clear(); +// _wasDisabledGraphics.Clear(); +// } + +// internal static Text s_objNameLabel; +// internal static Text s_objPathLabel; +// internal static Text s_mousePosLabel; +// internal static GameObject s_UIContent; + +// internal static void ConstructUI() +// { +// s_UIContent = UIFactory.CreatePanel("InspectUnderMouse_UI", out GameObject content); + +// var baseRect = s_UIContent.GetComponent(); +// var half = new Vector2(0.5f, 0.5f); +// baseRect.anchorMin = half; +// baseRect.anchorMax = half; +// baseRect.pivot = half; +// baseRect.sizeDelta = new Vector2(700, 150); + +// var group = content.GetComponent(); +// group.childForceExpandHeight = true; + +// // Title text + +// UIFactory.CreateLabel(content, "InspectLabel", "Mouse Inspector (press ESC to cancel)", TextAnchor.MiddleCenter); + +// s_mousePosLabel = UIFactory.CreateLabel(content, "MousePosLabel", "Mouse Position:", TextAnchor.MiddleCenter); + +// s_objNameLabel = UIFactory.CreateLabel(content, "HitLabelObj", "No hits...", TextAnchor.MiddleLeft); +// s_objNameLabel.horizontalOverflow = HorizontalWrapMode.Overflow; + +// s_objPathLabel = UIFactory.CreateLabel(content, "PathLabel", "", TextAnchor.MiddleLeft); +// s_objPathLabel.fontStyle = FontStyle.Italic; +// s_objPathLabel.horizontalOverflow = HorizontalWrapMode.Wrap; + +// UIFactory.SetLayoutElement(s_objPathLabel.gameObject, minHeight: 75); + +// s_UIContent.SetActive(false); +// } +// } +//} diff --git a/src/UI/Models/UIBehaviourModel.cs b/src/UI/Models/UIBehaviourModel.cs index 823ad04..cfa6398 100644 --- a/src/UI/Models/UIBehaviourModel.cs +++ b/src/UI/Models/UIBehaviourModel.cs @@ -40,11 +40,6 @@ namespace UnityExplorer.UI.Models Instances.Add(this); } - public virtual void Init() - { - - } - /// /// Default empty method, override and implement if NeedsUpdateTick is true. /// diff --git a/src/UI/ObjectExplorer/ObjectSearch.cs b/src/UI/ObjectExplorer/ObjectSearch.cs index c7f8a58..008e9a8 100644 --- a/src/UI/ObjectExplorer/ObjectSearch.cs +++ b/src/UI/ObjectExplorer/ObjectSearch.cs @@ -4,21 +4,21 @@ using System.Linq; using System.Text; using UnityEngine; using UnityEngine.UI; -using UnityExplorer.Core.Search; using UnityExplorer.UI.Inspectors; using UnityExplorer.UI.Models; using UnityExplorer.UI.ObjectPool; +using UnityExplorer.UI.Panels; using UnityExplorer.UI.Utility; using UnityExplorer.UI.Widgets; using UnityExplorer.UI.Widgets.AutoComplete; -namespace UnityExplorer.UI.Panels +namespace UnityExplorer.UI.ObjectExplorer { public class ObjectSearch : UIModel { - public ObjectExplorer Parent { get; } + public ObjectExplorerPanel Parent { get; } - public ObjectSearch(ObjectExplorer parent) + public ObjectSearch(ObjectExplorerPanel parent) { Parent = parent; } diff --git a/src/UI/ObjectExplorer/SceneExplorer.cs b/src/UI/ObjectExplorer/SceneExplorer.cs index c0727f2..90a0bf1 100644 --- a/src/UI/ObjectExplorer/SceneExplorer.cs +++ b/src/UI/ObjectExplorer/SceneExplorer.cs @@ -9,15 +9,16 @@ using UnityEngine.SceneManagement; using UnityEngine.UI; using UnityExplorer.Core; using UnityExplorer.UI.Models; +using UnityExplorer.UI.Panels; using UnityExplorer.UI.Widgets; -namespace UnityExplorer.UI.Panels +namespace UnityExplorer.UI.ObjectExplorer { public class SceneExplorer : UIModel { - public ObjectExplorer Parent { get; } + public ObjectExplorerPanel Parent { get; } - public SceneExplorer(ObjectExplorer parent) + public SceneExplorer(ObjectExplorerPanel parent) { Parent = parent; diff --git a/src/Core/Search/SearchProvider.cs b/src/UI/ObjectExplorer/SearchProvider.cs similarity index 93% rename from src/Core/Search/SearchProvider.cs rename to src/UI/ObjectExplorer/SearchProvider.cs index 9c40d83..7601f78 100644 --- a/src/Core/Search/SearchProvider.cs +++ b/src/UI/ObjectExplorer/SearchProvider.cs @@ -5,10 +5,34 @@ using System.Reflection; using System.Text; using UnityEngine; using UnityEngine.SceneManagement; +using UnityExplorer.Core; using UnityExplorer.Core.Runtime; -namespace UnityExplorer.Core.Search +namespace UnityExplorer.UI.ObjectExplorer { + public enum SearchContext + { + UnityObject, + GameObject, + Singleton, + StaticClass + } + + public enum ChildFilter + { + Any, + RootObject, + HasParent + } + + public enum SceneFilter + { + Any, + ActivelyLoaded, + DontDestroyOnLoad, + HideAndDontSave, + } + public static class SearchProvider { diff --git a/src/UI/Panels/CSConsolePanel.cs b/src/UI/Panels/CSConsolePanel.cs index ec7ff4b..09c7d64 100644 --- a/src/UI/Panels/CSConsolePanel.cs +++ b/src/UI/Panels/CSConsolePanel.cs @@ -6,7 +6,7 @@ using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; using UnityExplorer.Core.Config; -using UnityExplorer.UI.CSConsole; +using UnityExplorer.UI.CSharpConsole; using UnityExplorer.UI.Utility; namespace UnityExplorer.UI.Panels @@ -18,14 +18,11 @@ namespace UnityExplorer.UI.Panels public override int MinWidth => 400; public override int MinHeight => 300; - public static CSConsolePanel Instance { get; private set; } - public InputFieldRef InputField { get; private set; } public Text InputText { get; private set; } public Text HighlightText { get; private set; } public Action OnInputChanged; - //private float m_timeOfLastInputInvoke; public Action OnResetClicked; public Action OnCompileClicked; @@ -33,7 +30,7 @@ namespace UnityExplorer.UI.Panels public Action OnSuggestionsToggled; public Action OnAutoIndentToggled; - private int m_lastCaretPosition; + public int LastCaretPosition { get; private set; } private int m_desiredCaretFix; private bool m_fixWaiting; private float m_defaultInputFieldAlpha; @@ -41,10 +38,10 @@ namespace UnityExplorer.UI.Panels public void UseSuggestion(string suggestion) { string input = InputField.Text; - input = input.Insert(m_lastCaretPosition, suggestion); + input = input.Insert(LastCaretPosition, suggestion); InputField.Text = input; - m_desiredCaretFix = m_lastCaretPosition += suggestion.Length; + m_desiredCaretFix = LastCaretPosition += suggestion.Length; var color = InputField.InputField.selectionColor; color.a = 0f; @@ -56,10 +53,6 @@ namespace UnityExplorer.UI.Panels if (value.Length == UIManager.MAX_INPUTFIELD_CHARS) ExplorerCore.LogWarning($"Reached maximum InputField character length! ({UIManager.MAX_INPUTFIELD_CHARS})"); - //if (m_timeOfLastInputInvoke.OccuredEarlierThanDefault()) - // return; - // - //m_timeOfLastInputInvoke = Time.realtimeSinceStartup; OnInputChanged?.Invoke(value); } @@ -67,6 +60,8 @@ namespace UnityExplorer.UI.Panels { base.Update(); + CSConsole.Update(); + if (m_desiredCaretFix >= 0) { if (!m_fixWaiting) @@ -87,7 +82,7 @@ namespace UnityExplorer.UI.Panels } } else if (InputField.InputField.caretPosition > 0) - m_lastCaretPosition = InputField.InputField.caretPosition; + LastCaretPosition = InputField.InputField.caretPosition; } // Saving @@ -111,9 +106,6 @@ namespace UnityExplorer.UI.Panels public override void ConstructPanelContent() { - //Content = UIFactory.CreateVerticalGroup(MainMenu.Instance.PageViewport, "CSharpConsole", true, true, true, true); - //UIFactory.SetLayoutElement(Content, preferredHeight: 500, flexibleHeight: 9000); - #region TOP BAR // Main group object @@ -157,10 +149,7 @@ namespace UnityExplorer.UI.Panels int fontSize = 16; - //var inputObj = UIFactory.CreateSrollInputField(this.content, "ConsoleInput", CSConsoleManager.STARTUP_TEXT, - // out InputFieldScroller consoleScroll, fontSize); - - var inputObj = UIFactory.CreateSrollInputField(this.content, "ConsoleInput", CSConsoleManager.STARTUP_TEXT, out var inputScroller, fontSize); + var inputObj = UIFactory.CreateSrollInputField(this.content, "ConsoleInput", CSConsole.STARTUP_TEXT, out var inputScroller, fontSize); InputField = inputScroller.InputField; m_defaultInputFieldAlpha = InputField.InputField.selectionColor.a; InputField.OnValueChanged += InvokeOnValueChanged; diff --git a/src/UI/Panels/InspectorPanel.cs b/src/UI/Panels/InspectorPanel.cs index 6ce44b7..513ea64 100644 --- a/src/UI/Panels/InspectorPanel.cs +++ b/src/UI/Panels/InspectorPanel.cs @@ -19,7 +19,7 @@ namespace UnityExplorer.UI.Panels public override string Name => "Inspector"; public override UIManager.Panels PanelType => UIManager.Panels.Inspector; public override bool ShouldSaveActiveState => false; - public override int MinWidth => 550; + public override int MinWidth => 625; public override int MinHeight => 350; public GameObject NavbarHolder; diff --git a/src/UI/Panels/ObjectExplorer.cs b/src/UI/Panels/ObjectExplorerPanel.cs similarity index 98% rename from src/UI/Panels/ObjectExplorer.cs rename to src/UI/Panels/ObjectExplorerPanel.cs index 0e18eb3..1ba4aaf 100644 --- a/src/UI/Panels/ObjectExplorer.cs +++ b/src/UI/Panels/ObjectExplorerPanel.cs @@ -11,12 +11,13 @@ using UnityEngine.UI; using UnityExplorer.Core; using UnityExplorer.Core.Config; using UnityExplorer.UI.Models; +using UnityExplorer.UI.ObjectExplorer; using UnityExplorer.UI.Utility; using UnityExplorer.UI.Widgets; namespace UnityExplorer.UI.Panels { - public class ObjectExplorer : UIPanel + public class ObjectExplorerPanel : UIPanel { public override string Name => "Object Explorer"; public override UIManager.Panels PanelType => UIManager.Panels.ObjectExplorer; diff --git a/src/UI/UIFactory.cs b/src/UI/UIFactory.cs index 5ef1a72..e5cc2f5 100644 --- a/src/UI/UIFactory.cs +++ b/src/UI/UIFactory.cs @@ -893,6 +893,15 @@ namespace UnityExplorer.UI var inputField = CreateInputField(viewportObj, "InputField", placeHolderText); var content = inputField.UIRoot; + var textComp = inputField.InputField.textComponent; + textComp.alignment = TextAnchor.UpperLeft; + textComp.fontSize = fontSize; + textComp.horizontalOverflow = HorizontalWrapMode.Wrap; + inputField.InputField.lineType = InputField.LineType.MultiLineNewline; + inputField.InputField.targetGraphic.color = color; + inputField.PlaceholderText.alignment = TextAnchor.UpperLeft; + inputField.PlaceholderText.fontSize = fontSize; + inputField.PlaceholderText.horizontalOverflow = HorizontalWrapMode.Wrap; //var content = CreateInputField(viewportObj, name, placeHolderText ?? "...", out InputField inputField, fontSize, 0); SetLayoutElement(content, flexibleHeight: 9999, flexibleWidth: 9999); diff --git a/src/UI/UIManager.cs b/src/UI/UIManager.cs index 4090ce2..66815a7 100644 --- a/src/UI/UIManager.cs +++ b/src/UI/UIManager.cs @@ -8,6 +8,7 @@ using UnityEngine.EventSystems; using UnityEngine.UI; using UnityExplorer.Core.Config; using UnityExplorer.Core.Input; +using UnityExplorer.UI.CSharpConsole; using UnityExplorer.UI.Models; using UnityExplorer.UI.Panels; using UnityExplorer.UI.Utility; @@ -39,9 +40,9 @@ namespace UnityExplorer.UI // panels internal static GameObject PanelHolder { get; private set; } - public static ObjectExplorer Explorer { get; private set; } + public static ObjectExplorerPanel Explorer { get; private set; } public static InspectorPanel Inspector { get; private set; } - public static CSConsolePanel CSConsole { get; private set; } + public static CSConsolePanel CSharpConsole { get; private set; } public static AutoCompleter AutoCompleter { get; private set; } @@ -69,7 +70,7 @@ namespace UnityExplorer.UI case Panels.AutoCompleter: return AutoCompleter; case Panels.CSConsole: - return CSConsole; + return CSharpConsole; default: throw new NotImplementedException($"TODO GetPanel: {panel}"); } @@ -170,14 +171,15 @@ namespace UnityExplorer.UI AutoCompleter = new AutoCompleter(); AutoCompleter.ConstructUI(); - Explorer = new ObjectExplorer(); + Explorer = new ObjectExplorerPanel(); Explorer.ConstructUI(); Inspector = new InspectorPanel(); Inspector.ConstructUI(); - CSConsole = new CSConsolePanel(); - CSConsole.ConstructUI(); + CSharpConsole = new CSConsolePanel(); + CSharpConsole.ConstructUI(); + CSConsole.Init(); ShowMenu = !ConfigManager.Hide_On_Startup.Value; diff --git a/src/UnityExplorer.csproj b/src/UnityExplorer.csproj index ef6ab21..80171b3 100644 --- a/src/UnityExplorer.csproj +++ b/src/UnityExplorer.csproj @@ -219,8 +219,15 @@ - - + + + + + + + + + @@ -228,7 +235,7 @@ - + @@ -243,7 +250,7 @@ - + @@ -283,10 +290,7 @@ - - - - + @@ -302,7 +306,7 @@ - +