From e585fc6da0d9f1963d79ef908690fefb3b198e18 Mon Sep 17 00:00:00 2001 From: Sinai <49360850+sinai-dev@users.noreply.github.com> Date: Sat, 1 Jan 2022 21:40:47 +1100 Subject: [PATCH] Allow evaluating non-primitive methods --- src/CacheObject/CacheMember.cs | 48 ++++---- src/CacheObject/Views/EvaluateWidget.cs | 147 +++++++++++++++++++----- src/ExplorerCore.cs | 2 +- src/Inspectors/InspectorManager.cs | 6 + 4 files changed, 147 insertions(+), 56 deletions(-) diff --git a/src/CacheObject/CacheMember.cs b/src/CacheObject/CacheMember.cs index 20f3241..846f950 100644 --- a/src/CacheObject/CacheMember.cs +++ b/src/CacheObject/CacheMember.cs @@ -162,22 +162,22 @@ namespace UnityExplorer.CacheObject #region Cache Member Util - public static bool CanParseArgs(ParameterInfo[] parameters) - { - foreach (var param in parameters) - { - var pType = param.ParameterType; - - if (pType.IsByRef && pType.HasElementType) - pType = pType.GetElementType(); - - if (pType != null && ParseUtility.CanParse(pType)) - continue; - else - return false; - } - return true; - } + //public static bool CanParseArgs(ParameterInfo[] parameters) + //{ + // foreach (var param in parameters) + // { + // var pType = param.ParameterType; + // + // if (pType.IsByRef && pType.HasElementType) + // pType = pType.GetElementType(); + // + // if (pType != null && ParseUtility.CanParse(pType)) + // continue; + // else + // return false; + // } + // return true; + //} public static List GetCacheMembers(object inspectorTarget, Type _type, ReflectionInspector _inspector) { @@ -250,11 +250,11 @@ namespace UnityExplorer.CacheObject && (mi.Name.StartsWith("get_") || mi.Name.StartsWith("set_"))) return; - var args = mi.GetParameters(); - if (!CanParseArgs(args)) - return; + //var args = mi.GetParameters(); + //if (!CanParseArgs(args)) + // return; - sig += GetArgumentString(args); + sig += GetArgumentString(mi.GetParameters()); if (cachedSigs.Contains(sig)) return; @@ -267,9 +267,9 @@ namespace UnityExplorer.CacheObject { var pi = member as PropertyInfo; - var args = pi.GetIndexParameters(); - if (!CanParseArgs(args)) - return; + //var args = pi.GetIndexParameters(); + //if (!CanParseArgs(args)) + // return; if (!pi.CanRead && pi.CanWrite) { @@ -280,7 +280,7 @@ namespace UnityExplorer.CacheObject return; } - sig += GetArgumentString(args); + sig += GetArgumentString(pi.GetIndexParameters()); if (cachedSigs.Contains(sig)) return; diff --git a/src/CacheObject/Views/EvaluateWidget.cs b/src/CacheObject/Views/EvaluateWidget.cs index 23cdac6..2dd235d 100644 --- a/src/CacheObject/Views/EvaluateWidget.cs +++ b/src/CacheObject/Views/EvaluateWidget.cs @@ -26,6 +26,8 @@ namespace UnityExplorer.CacheObject.Views private GameObject argHolder; private readonly List argRows = new List(); private readonly List argLabels = new List(); + private readonly List argInputFields = new List(); + private readonly List argDropdowns = new List(); private Type[] genericArguments; private string[] genericInput; @@ -34,9 +36,6 @@ namespace UnityExplorer.CacheObject.Views private readonly List genericArgRows = new List(); private readonly List genericArgLabels = new List(); private readonly List genericAutocompleters = new List(); - - //private readonly List inputFields = new List(); - private readonly List argInputFields = new List(); private readonly List genericInputFields = new List(); public void OnBorrowedFromPool(CacheMember owner) @@ -52,6 +51,8 @@ namespace UnityExplorer.CacheObject.Views SetArgRows(); this.UIRoot.SetActive(true); + + InspectorManager.OnInspectedTabsChanged += InspectorManager_OnInspectedTabsChanged; } public void OnReturnToPool() @@ -62,6 +63,17 @@ namespace UnityExplorer.CacheObject.Views input.Text = ""; this.Owner = null; + + InspectorManager.OnInspectedTabsChanged -= InspectorManager_OnInspectedTabsChanged; + } + + private void InspectorManager_OnInspectedTabsChanged() + { + for (int i = 0; i < argDropdowns.Count; i++) + { + var drop = argDropdowns[i]; + PopulateNonPrimitiveArgumentDropdown(drop, i); + } } public Type[] TryParseGenericArguments() @@ -83,33 +95,62 @@ namespace UnityExplorer.CacheObject.Views for (int i = 0; i < arguments.Length; i++) { - var arg = arguments[i]; - var input = argumentInput[i]; + var paramInfo = arguments[i]; - var type = arg.ParameterType; - if (type.IsByRef) - type = type.GetElementType(); + var argType = paramInfo.ParameterType; + if (argType.IsByRef) + argType = argType.GetElementType(); - if (type == typeof(string)) + if (ParseUtility.CanParse(argType)) { - outArgs[i] = input; - continue; - } + var input = argumentInput[i]; - if (string.IsNullOrEmpty(input)) - { - if (arg.IsOptional) - outArgs[i] = arg.DefaultValue; - else + if (argType == typeof(string)) + { + outArgs[i] = input; + continue; + } + + if (string.IsNullOrEmpty(input)) + { + if (paramInfo.IsOptional) + outArgs[i] = paramInfo.DefaultValue; + else + outArgs[i] = null; + continue; + } + + if (!ParseUtility.TryParse(input, argType, out outArgs[i], out Exception ex)) + { outArgs[i] = null; - continue; + ExplorerCore.LogWarning($"Cannot parse argument '{paramInfo.Name}' ({paramInfo.ParameterType.Name})" + + $"{(ex == null ? "" : $", {ex.GetType().Name}: {ex.Message}")}"); + } } - - if (!ParseUtility.TryParse(input, type, out outArgs[i], out Exception ex)) + else { - outArgs[i] = null; - ExplorerCore.LogWarning($"Cannot parse argument '{arg.Name}' ({arg.ParameterType.Name})" + - $"{(ex == null ? "" : $", {ex.GetType().Name}: {ex.Message}")}"); + var dropdown = argDropdowns[i]; + if (dropdown.value == 0) + { + outArgs[i] = null; + } + else + { + // Probably should do this in a better way... + // Parse the text of the dropdown option to get the inspector tab index. + string tabIndexString = ""; + for (int j = 4; ; j++) + { + char c = dropdown.options[dropdown.value].text[j]; + if (c == ':') + break; + tabIndexString += c; + } + int tabIndex = int.Parse(tabIndexString); + var tab = InspectorManager.Inspectors[tabIndex - 1]; + + outArgs[i] = tab.Target; + } } } @@ -195,25 +236,54 @@ namespace UnityExplorer.CacheObject.Views } var arg = arguments[i]; - + var argType = arg.ParameterType; + if (argType.IsByRef) + argType = argType.GetElementType(); if (i >= argRows.Count) AddArgRow(i, false); argRows[i].SetActive(true); - argLabels[i].text = $"{SignatureHighlighter.Parse(arg.ParameterType, false)} {arg.Name}"; - if (arg.ParameterType == typeof(string)) - argInputFields[i].PlaceholderText.text = ""; + argLabels[i].text = + $"{SignatureHighlighter.Parse(argType, false)} {arg.Name}"; + + if (ParseUtility.CanParse(argType)) + { + argInputFields[i].Component.gameObject.SetActive(true); + argDropdowns[i].gameObject.SetActive(false); + + if (arg.ParameterType == typeof(string)) + argInputFields[i].PlaceholderText.text = ""; + else + argInputFields[i].PlaceholderText.text = $"eg. {ParseUtility.GetExampleInput(argType)}"; + } else { - var elemType = arg.ParameterType; - if (elemType.IsByRef) - elemType = elemType.GetElementType(); - argInputFields[i].PlaceholderText.text = $"eg. {ParseUtility.GetExampleInput(elemType)}"; + argInputFields[i].Component.gameObject.SetActive(false); + argDropdowns[i].gameObject.SetActive(true); + + PopulateNonPrimitiveArgumentDropdown(argDropdowns[i], i); } } } + private void PopulateNonPrimitiveArgumentDropdown(Dropdown dropdown, int argIndex) + { + dropdown.options.Clear(); + dropdown.options.Add(new Dropdown.OptionData("null")); + + var argType = arguments[argIndex].ParameterType; + + int tabIndex = 0; + foreach (var tab in InspectorManager.Inspectors) + { + tabIndex++; + + if (argType.IsAssignableFrom(tab.Target.GetActualType())) + dropdown.options.Add(new Dropdown.OptionData($"Tab {tabIndex}: {tab.Tab.TabText.text}")); + } + } + private void AddArgRow(int index, bool generic) { if (!generic) @@ -242,7 +312,17 @@ namespace UnityExplorer.CacheObject.Views inputField.OnValueChanged += (string val) => { inputArray[index] = val; }; if (!generic) + { + var dropdownObj = UIFactory.CreateDropdown(horiGroup, out Dropdown dropdown, "Select argument...", 14, (int val) => + { + ArgDropdownChanged(index, val); + }); + UIFactory.SetLayoutElement(dropdownObj, minHeight: 25, flexibleHeight: 50, minWidth: 100, flexibleWidth: 1000); + dropdownObj.AddComponent().verticalFit = ContentSizeFitter.FitMode.PreferredSize; + argInputFields.Add(inputField); + argDropdowns.Add(dropdown); + } else genericInputFields.Add(inputField); @@ -250,6 +330,11 @@ namespace UnityExplorer.CacheObject.Views genericAutocompleters.Add(new TypeCompleter(null, inputField)); } + private void ArgDropdownChanged(int argIndex, int value) + { + // not sure if necessary + } + public GameObject CreateContent(GameObject parent) { UIRoot = UIFactory.CreateVerticalGroup(parent, "EvaluateWidget", false, false, true, true, 3, new Vector4(2, 2, 2, 2), diff --git a/src/ExplorerCore.cs b/src/ExplorerCore.cs index 7459796..4e75ab7 100644 --- a/src/ExplorerCore.cs +++ b/src/ExplorerCore.cs @@ -16,7 +16,7 @@ namespace UnityExplorer public static class ExplorerCore { public const string NAME = "UnityExplorer"; - public const string VERSION = "4.4.2"; + public const string VERSION = "4.4.3"; public const string AUTHOR = "Sinai"; public const string GUID = "com.sinai.unityexplorer"; diff --git a/src/Inspectors/InspectorManager.cs b/src/Inspectors/InspectorManager.cs index 04337f0..935c741 100644 --- a/src/Inspectors/InspectorManager.cs +++ b/src/Inspectors/InspectorManager.cs @@ -23,6 +23,8 @@ namespace UnityExplorer public static float PanelWidth; + public static event Action OnInspectedTabsChanged; + public static void Inspect(object obj, CacheObjectBase sourceCache = null) { if (obj.IsNullOrDestroyed()) @@ -111,6 +113,8 @@ namespace UnityExplorer inspector.OnBorrowedFromPool(target); SetInspectorActive(inspector); + + OnInspectedTabsChanged?.Invoke(); } internal static void ReleaseInspector(T inspector) where T : InspectorBase @@ -144,6 +148,8 @@ namespace UnityExplorer UIManager.SetPanelActive(UIManager.Panels.Inspector, false); } } + + OnInspectedTabsChanged?.Invoke(); } internal static void Update()