diff --git a/icon.png b/icon.png index ae791aa..05a1431 100644 Binary files a/icon.png and b/icon.png differ diff --git a/overview.png b/overview.png index f099f68..6491f9a 100644 Binary files a/overview.png and b/overview.png differ diff --git a/src/Config/ModConfig.cs b/src/Config/ModConfig.cs index 9867f1d..1ee0336 100644 --- a/src/Config/ModConfig.cs +++ b/src/Config/ModConfig.cs @@ -17,7 +17,7 @@ namespace UnityExplorer.Config // Actual configs public KeyCode Main_Menu_Toggle = KeyCode.F7; public bool Force_Unlock_Mouse = true; - public int Default_Page_Limit = 20; + public int Default_Page_Limit = 25; public string Default_Output_Path = ExplorerCore.EXPLORER_FOLDER; public bool Log_Unity_Debug = false; diff --git a/src/Console/AutoCompleter.cs b/src/Console/AutoCompleter.cs index 58e3a45..cb6dde8 100644 --- a/src/Console/AutoCompleter.cs +++ b/src/Console/AutoCompleter.cs @@ -44,7 +44,7 @@ namespace UnityExplorer.Console return; } - if (!ConsolePage.EnableAutocompletes) + if (!CodeEditor.EnableAutocompletes) { if (m_mainObj.activeSelf) { @@ -187,9 +187,9 @@ namespace UnityExplorer.Console public static void ClearAutocompletes() { - if (ConsolePage.AutoCompletes.Any()) + if (CodeEditor.AutoCompletes.Any()) { - ConsolePage.AutoCompletes.Clear(); + CodeEditor.AutoCompletes.Clear(); } } @@ -198,7 +198,7 @@ namespace UnityExplorer.Console try { // Credit ManylMarco - ConsolePage.AutoCompletes.Clear(); + CodeEditor.AutoCompletes.Clear(); string[] completions = ConsolePage.Instance.m_evaluator.GetCompletions(input, out string prefix); if (completions != null) { @@ -207,7 +207,7 @@ namespace UnityExplorer.Console prefix = input; } - ConsolePage.AutoCompletes.AddRange(completions + CodeEditor.AutoCompletes.AddRange(completions .Where(x => !string.IsNullOrEmpty(x)) .Select(x => new Suggestion(x, prefix, Suggestion.Contexts.Other)) ); @@ -226,7 +226,7 @@ namespace UnityExplorer.Console x.Substring(0, trimmed.Length), Suggestion.Contexts.Namespace)); - ConsolePage.AutoCompletes.AddRange(namespaces); + CodeEditor.AutoCompletes.AddRange(namespaces); IEnumerable keywords = Suggestion.Keywords .Where(x => x.StartsWith(trimmed) && x.Length > trimmed.Length) @@ -235,7 +235,7 @@ namespace UnityExplorer.Console x.Substring(0, trimmed.Length), Suggestion.Contexts.Keyword)); - ConsolePage.AutoCompletes.AddRange(keywords); + CodeEditor.AutoCompletes.AddRange(keywords); } catch (Exception ex) { @@ -290,7 +290,7 @@ namespace UnityExplorer.Console var hiddenChild = UIFactory.CreateUIObject("HiddenText", buttonObj); hiddenChild.SetActive(false); - var hiddenText = hiddenChild.AddGraphic(); + var hiddenText = hiddenChild.AddComponent(); m_hiddenSuggestionTexts.Add(hiddenText); #if CPP @@ -301,9 +301,7 @@ namespace UnityExplorer.Console void UseAutocompleteButton() { - ConsolePage.Instance.UseAutocomplete(hiddenText.text); - EventSystem.current.SetSelectedGameObject(ConsolePage.Instance.m_codeEditor.InputField.gameObject, - null); + ConsolePage.Instance.m_codeEditor.UseAutocomplete(hiddenText.text); } m_suggestionButtons.Add(buttonObj); diff --git a/src/Console/CodeEditor.cs b/src/Console/CodeEditor.cs index 996932e..920504a 100644 --- a/src/Console/CodeEditor.cs +++ b/src/Console/CodeEditor.cs @@ -11,11 +11,6 @@ using UnityExplorer.UI.Modules; using System.Collections.Generic; using System.Reflection; using UnityExplorer.UI.Shared; -#if CPP -using UnityExplorer.Unstrip; -using UnityExplorer.Helpers; -using UnhollowerRuntimeLib; -#endif namespace UnityExplorer.Console { @@ -27,12 +22,22 @@ namespace UnityExplorer.Console public Text InputText { get; internal set; } public int CurrentIndent { get; private set; } + public static bool EnableCtrlRShortcut { get; set; } = true; + public static bool EnableAutoIndent { get; set; } = true; + public static bool EnableAutocompletes { get; set; } = true; + public static List AutoCompletes = new List(); + public string HighlightedText => inputHighlightText.text; private Text inputHighlightText; private readonly CSharpLexer highlightLexer; private readonly StringBuilder sbHighlight; + internal int m_lastCaretPos; + internal int m_fixCaretPos; + internal bool m_fixwanted; + internal float m_lastSelectAlpha; + private static readonly KeyCode[] onFocusKeys = { KeyCode.Return, KeyCode.Backspace, KeyCode.UpArrow, @@ -76,31 +81,74 @@ The following helper methods are available: public void Update() { - // Check for new line - if (ConsolePage.EnableAutoIndent && InputManager.GetKeyDown(KeyCode.Return)) + if (EnableCtrlRShortcut) { - AutoIndentCaret(); - } - - if (EventSystem.current?.currentSelectedGameObject?.name == "InputField") - { - bool focusKeyPressed = false; - - // Check for any focus key pressed - foreach (KeyCode key in onFocusKeys) + if ((InputManager.GetKey(KeyCode.LeftControl) || InputManager.GetKey(KeyCode.RightControl)) + && InputManager.GetKeyDown(KeyCode.R)) { - if (InputManager.GetKeyDown(key)) + var text = InputField.text.Trim(); + if (!string.IsNullOrEmpty(text)) { - focusKeyPressed = true; - break; + ConsolePage.Instance.Evaluate(text); + return; } } + } - if (focusKeyPressed || InputManager.GetMouseButton(0)) + if (EnableAutoIndent && InputManager.GetKeyDown(KeyCode.Return)) + AutoIndentCaret(); + + if (EnableAutocompletes && InputField.isFocused) + { + if (InputManager.GetMouseButton(0) || onFocusKeys.Any(it => InputManager.GetKeyDown(it))) + UpdateAutocompletes(); + } + + if (m_fixCaretPos > 0) + { + if (!m_fixwanted) + m_fixwanted = true; + else { - ConsolePage.Instance.OnInputChanged(); + InputField.caretPosition = m_fixCaretPos; + InputField.selectionFocusPosition = m_fixCaretPos; + + m_fixwanted = false; + m_fixCaretPos = -1; + + var color = InputField.selectionColor; + color.a = m_lastSelectAlpha; + InputField.selectionColor = color; } } + else if (InputField.caretPosition > 0) + { + m_lastCaretPos = InputField.caretPosition; + } + } + + internal void UpdateAutocompletes() + { + AutoCompleter.CheckAutocomplete(); + AutoCompleter.SetSuggestions(AutoCompletes.ToArray()); + } + + public void UseAutocomplete(string suggestion) + { + EventSystem.current.SetSelectedGameObject(ConsolePage.Instance.m_codeEditor.InputField.gameObject, null); + + string input = InputField.text; + input = input.Insert(m_lastCaretPos, suggestion); + InputField.text = input; + + m_fixCaretPos = m_lastCaretPos += suggestion.Length; + + var color = InputField.selectionColor; + m_lastSelectAlpha = color.a; + color.a = 0f; + InputField.selectionColor = color; + + AutoCompleter.ClearAutocompletes(); } public void OnInputChanged(string newInput, bool forceUpdate = false) @@ -110,15 +158,11 @@ The following helper methods are available: UpdateIndent(newInput); if (!forceUpdate && string.IsNullOrEmpty(newText)) - { inputHighlightText.text = string.Empty; - } else - { inputHighlightText.text = SyntaxHighlightContent(newText); - } - ConsolePage.Instance.OnInputChanged(); + UpdateAutocompletes(); } private void UpdateIndent(string newText) @@ -298,12 +342,32 @@ The following helper methods are available: var topBarLabel = UIFactory.CreateLabel(topBarObj, TextAnchor.MiddleLeft); var topBarLabelLayout = topBarLabel.AddComponent(); - topBarLabelLayout.preferredWidth = 800; - topBarLabelLayout.flexibleWidth = 10; + topBarLabelLayout.preferredWidth = 150; + topBarLabelLayout.flexibleWidth = 5000; var topBarText = topBarLabel.GetComponent(); topBarText.text = "C# Console"; topBarText.fontSize = 20; + // Enable Ctrl+R toggle + + var ctrlRToggleObj = UIFactory.CreateToggle(topBarObj, out Toggle ctrlRToggle, out Text ctrlRToggleText); +#if CPP + ctrlRToggle.onValueChanged.AddListener(new Action(CtrlRToggleCallback)); +#else + ctrlRToggle.onValueChanged.AddListener(CtrlRToggleCallback); +#endif + void CtrlRToggleCallback(bool val) + { + EnableCtrlRShortcut = val; + } + + ctrlRToggleText.text = "Run on Ctrl+R"; + ctrlRToggleText.alignment = TextAnchor.UpperLeft; + var ctrlRLayout = ctrlRToggleObj.AddComponent(); + ctrlRLayout.minWidth = 140; + ctrlRLayout.flexibleWidth = 0; + ctrlRLayout.minHeight = 25; + // Enable Suggestions toggle var suggestToggleObj = UIFactory.CreateToggle(topBarObj, out Toggle suggestToggle, out Text suggestToggleText); @@ -314,24 +378,16 @@ The following helper methods are available: #endif void SuggestToggleCallback(bool val) { - ConsolePage.EnableAutocompletes = val; + EnableAutocompletes = val; AutoCompleter.Update(); } suggestToggleText.text = "Suggestions"; suggestToggleText.alignment = TextAnchor.UpperLeft; - var suggestTextPos = suggestToggleText.transform.localPosition; - suggestTextPos.y = -14; - suggestToggleText.transform.localPosition = suggestTextPos; - var suggestLayout = suggestToggleObj.AddComponent(); suggestLayout.minWidth = 120; suggestLayout.flexibleWidth = 0; - - var suggestRect = suggestToggleObj.transform.Find("Background"); - var suggestPos = suggestRect.localPosition; - suggestPos.y = -14; - suggestRect.localPosition = suggestPos; + suggestLayout.minHeight = 25; // Enable Auto-indent toggle @@ -341,22 +397,15 @@ The following helper methods are available: #else autoIndentToggle.onValueChanged.AddListener(OnIndentChanged); #endif - void OnIndentChanged(bool val) => ConsolePage.EnableAutoIndent = val; + void OnIndentChanged(bool val) => EnableAutoIndent = val; autoIndentToggleText.text = "Auto-indent"; autoIndentToggleText.alignment = TextAnchor.UpperLeft; - var autoIndentTextPos = autoIndentToggleText.transform.localPosition; - autoIndentTextPos.y = -14; - autoIndentToggleText.transform.localPosition = autoIndentTextPos; var autoIndentLayout = autoIndentToggleObj.AddComponent(); autoIndentLayout.minWidth = 120; autoIndentLayout.flexibleWidth = 0; - - var autoIndentRect = autoIndentToggleObj.transform.Find("Background"); - suggestPos = autoIndentRect.localPosition; - suggestPos.y = -14; - autoIndentRect.localPosition = suggestPos; + autoIndentLayout.minHeight = 25; #endregion @@ -385,7 +434,7 @@ The following helper methods are available: highlightTextRect.offsetMin = new Vector2(20, 0); highlightTextRect.offsetMax = new Vector2(14, 0); - var highlightTextInput = highlightTextObj.AddGraphic(); + var highlightTextInput = highlightTextObj.AddComponent(); highlightTextInput.supportRichText = true; highlightTextInput.fontSize = fontSize; diff --git a/src/Console/ScriptEvaluator.cs b/src/Console/ScriptEvaluator.cs index 652a277..0f17905 100644 --- a/src/Console/ScriptEvaluator.cs +++ b/src/Console/ScriptEvaluator.cs @@ -15,11 +15,11 @@ namespace UnityExplorer.Console "mscorlib", "System.Core", "System", "System.Xml" }; - private readonly TextWriter _logger; + private readonly TextWriter tw; - public ScriptEvaluator(TextWriter logger) : base(BuildContext(logger)) + public ScriptEvaluator(TextWriter tw) : base(BuildContext(tw)) { - _logger = logger; + this.tw = tw; ImportAppdomainAssemblies(ReferenceAssembly); AppDomain.CurrentDomain.AssemblyLoad += OnAssemblyLoad; @@ -28,7 +28,7 @@ namespace UnityExplorer.Console public void Dispose() { AppDomain.CurrentDomain.AssemblyLoad -= OnAssemblyLoad; - _logger.Dispose(); + tw.Dispose(); } private void OnAssemblyLoad(object sender, AssemblyLoadEventArgs args) diff --git a/src/ExplorerCore.cs b/src/ExplorerCore.cs index 7a57c7a..76ccd03 100644 --- a/src/ExplorerCore.cs +++ b/src/ExplorerCore.cs @@ -123,6 +123,9 @@ namespace UnityExplorer { UIManager.Init(); Log("Initialized UnityExplorer UI."); + + // temp debug + InspectorManager.Instance.Inspect(Tests.TestClass.Instance); } catch (Exception e) { diff --git a/src/Helpers/ReflectionHelpers.cs b/src/Helpers/ReflectionHelpers.cs index a2dd7c8..7d91ccd 100644 --- a/src/Helpers/ReflectionHelpers.cs +++ b/src/Helpers/ReflectionHelpers.cs @@ -237,8 +237,11 @@ namespace UnityExplorer.Helpers #endif } - public static string ExceptionToString(Exception e) + public static string ExceptionToString(Exception e, bool innerMost = false) { + while (innerMost && e.InnerException != null) + e = e.InnerException; + return e.GetType() + ", " + e.Message; } } diff --git a/src/Inspectors/GameObjects/ComponentList.cs b/src/Inspectors/GameObjects/ComponentList.cs index 8b33bdb..9e4453e 100644 --- a/src/Inspectors/GameObjects/ComponentList.cs +++ b/src/Inspectors/GameObjects/ComponentList.cs @@ -77,7 +77,7 @@ namespace UnityExplorer.Inspectors.GameObjects var text = s_compListTexts[i]; - text.text = ReflectionHelpers.GetActualType(comp).FullName; + text.text = UISyntaxHighlight.GetHighlight(ReflectionHelpers.GetActualType(comp), true); var toggle = s_compToggles[i]; if (comp is Behaviour behaviour) @@ -192,7 +192,7 @@ namespace UnityExplorer.Inspectors.GameObjects toggleLayout.minHeight = 25; toggleLayout.flexibleHeight = 0; var checkImg = toggleObj.transform.Find("Background/Checkmark").GetComponent(); - checkImg.color = SyntaxColors.Class_Instance.ToColor(); + checkImg.color = UISyntaxHighlight.Class_Instance.ToColor(); checkImg.color *= 0.66f; #if CPP toggle.onValueChanged.AddListener(new Action((bool val) => { OnCompToggleClicked(thisIndex, val); })); @@ -226,7 +226,7 @@ namespace UnityExplorer.Inspectors.GameObjects Text mainText = mainButtonObj.GetComponentInChildren(); mainText.alignment = TextAnchor.MiddleLeft; mainText.horizontalOverflow = HorizontalWrapMode.Overflow; - mainText.color = SyntaxColors.Class_Instance.ToColor(); + //mainText.color = SyntaxColors.Class_Instance.ToColor(); mainText.resizeTextForBestFit = true; mainText.resizeTextMaxSize = 14; mainText.resizeTextMinSize = 8; diff --git a/src/Inspectors/InspectorManager.cs b/src/Inspectors/InspectorManager.cs index 2da9110..c1140f2 100644 --- a/src/Inspectors/InspectorManager.cs +++ b/src/Inspectors/InspectorManager.cs @@ -7,7 +7,6 @@ using UnityExplorer.UI.Modules; using UnityEngine; using UnityEngine.SceneManagement; using UnityEngine.UI; -//using TMPro; using UnityExplorer.Inspectors.Reflection; namespace UnityExplorer.Inspectors @@ -28,8 +27,6 @@ namespace UnityExplorer.Inspectors public GameObject m_tabBarContent; public GameObject m_inspectorContent; - private readonly List testTexts = new List(); - public void Update() { for (int i = 0; i < m_currentInspectors.Count; i++) @@ -39,12 +36,6 @@ namespace UnityExplorer.Inspectors m_currentInspectors[i].Update(); } - - // ======= test ======== // - foreach (var text in testTexts) - { - text.text = Time.time.ToString(); - } } public void Inspect(object obj) diff --git a/src/Inspectors/Reflection/CacheObject/CacheField.cs b/src/Inspectors/Reflection/CacheObject/CacheField.cs index 208d8e2..33f3791 100644 --- a/src/Inspectors/Reflection/CacheObject/CacheField.cs +++ b/src/Inspectors/Reflection/CacheObject/CacheField.cs @@ -21,20 +21,11 @@ namespace UnityExplorer.Inspectors.Reflection public override void UpdateReflection() { - try - { - var fi = MemInfo as FieldInfo; - IValue.Value = fi.GetValue(fi.IsStatic ? null : DeclaringInstance); + var fi = MemInfo as FieldInfo; + IValue.Value = fi.GetValue(fi.IsStatic ? null : DeclaringInstance); - //base.UpdateValue(); - - m_evaluated = true; - ReflectionException = null; - } - catch (Exception e) - { - ReflectionException = ReflectionHelpers.ExceptionToString(e); - } + m_evaluated = true; + ReflectionException = null; } public override void SetValue() diff --git a/src/Inspectors/Reflection/CacheObject/CacheMember.cs b/src/Inspectors/Reflection/CacheObject/CacheMember.cs index f9d1bb8..970a750 100644 --- a/src/Inspectors/Reflection/CacheObject/CacheMember.cs +++ b/src/Inspectors/Reflection/CacheObject/CacheMember.cs @@ -6,6 +6,7 @@ using UnityEngine; using UnityEngine.UI; using UnityExplorer.UI; using UnityExplorer.UI.Shared; +using UnityExplorer.Helpers; #if CPP using UnhollowerBaseLib; #endif @@ -46,14 +47,29 @@ namespace UnityExplorer.Inspectors.Reflection public override void UpdateValue() { + if (HasParameters && !m_isEvaluating) + { + // need to enter args first + return; + } + + try + { #if CPP - if (!IsReflectionSupported()) - this.ReflectionException = "Type not supported with Reflection!"; - else - UpdateReflection(); -#else - UpdateReflection(); + if (!IsReflectionSupported()) + throw new Exception("Type not supported with Reflection"); #endif + UpdateReflection(); + +#if CPP + if (IValue.Value != null) + IValue.Value = IValue.Value.Il2CppCast(ReflectionHelpers.GetActualType(IValue.Value)); +#endif + } + catch (Exception e) + { + ReflectionException = ReflectionHelpers.ExceptionToString(e, true); + } base.UpdateValue(); } @@ -137,76 +153,7 @@ namespace UnityExplorer.Inspectors.Reflection private string GetRichTextName() { - string memberColor = ""; - bool isStatic = false; - - if (MemInfo is FieldInfo fi) - { - if (fi.IsStatic) - { - isStatic = true; - memberColor = SyntaxColors.Field_Static; - } - else - memberColor = SyntaxColors.Field_Instance; - } - else if (MemInfo is MethodInfo mi) - { - if (mi.IsStatic) - { - isStatic = true; - memberColor = SyntaxColors.Method_Static; - } - else - memberColor = SyntaxColors.Method_Instance; - } - else if (MemInfo is PropertyInfo pi) - { - if (pi.GetAccessors(true)[0].IsStatic) - { - isStatic = true; - memberColor = SyntaxColors.Prop_Static; - } - else - memberColor = SyntaxColors.Prop_Instance; - } - - string classColor; - if (MemInfo.DeclaringType.IsValueType) - { - classColor = SyntaxColors.StructGreen; - } - else if (MemInfo.DeclaringType.IsAbstract && MemInfo.DeclaringType.IsSealed) - { - classColor = SyntaxColors.Class_Static; - } - else - { - classColor = SyntaxColors.Class_Instance; - } - - m_richTextName = $"{MemInfo.DeclaringType.Name}."; - if (isStatic) m_richTextName += ""; - m_richTextName += $"{MemInfo.Name}"; - if (isStatic) m_richTextName += ""; - - // generic method args - if (this is CacheMethod cm && cm.GenericArgs.Length > 0) - { - m_richTextName += "<"; - - var args = ""; - for (int i = 0; i < cm.GenericArgs.Length; i++) - { - if (args != "") args += ", "; - args += $"{cm.GenericArgs[i].Name}"; - } - m_richTextName += args; - - m_richTextName += ">"; - } - - return m_richTextName; + return m_richTextName = UISyntaxHighlight.GetHighlight(MemInfo.DeclaringType, false, MemInfo); } #if CPP @@ -251,33 +198,136 @@ namespace UnityExplorer.Inspectors.Reflection } #endif - #region UI CONSTRUCTION + #region UI + internal float GetMemberLabelWidth(RectTransform scrollRect) + { + var textGenSettings = m_memLabelText.GetGenerationSettings(m_topRowRect.rect.size); + textGenSettings.scaleFactor = InputFieldScroller.canvasScaler.scaleFactor; + var textGen = m_memLabelText.cachedTextGeneratorForLayout; + float preferredWidth = textGen.GetPreferredWidth(RichTextName, textGenSettings); + + float max = scrollRect.rect.width * 0.5f; + + if (preferredWidth > max) preferredWidth = max; + + return preferredWidth < 125f ? 125f : preferredWidth; + } + + internal void SetWidths(float labelWidth, float valueWidth) + { + m_leftLayout.preferredWidth = labelWidth; + m_rightLayout.preferredWidth = valueWidth; + } + + internal GameObject m_leftGroup; + internal GameObject m_rightGroup; + internal Text m_memLabelText; + internal RectTransform m_topRowRect; + internal LayoutElement m_leftLayout; + internal LayoutElement m_rightLayout; + //internal GameObject m_subGroup; internal override void ConstructUI() { base.ConstructUI(); - //var refreshBtnObj = UIFactory.CreateButton(topRowObj, new Color(0.3f, 0.3f, 0.3f)); - //var btnLayout = refreshBtnObj.AddComponent(); - //btnLayout.minWidth = 30; - //btnLayout.minHeight = 20; - //btnLayout.flexibleWidth = 0; - //var refreshTxt = refreshBtnObj.GetComponentInChildren(); - //refreshTxt.text = "⟳"; - //refreshTxt.fontSize = 16; - //var refreshBtn = refreshBtnObj.GetComponent