Allow evaluating non-primitive methods

This commit is contained in:
Sinai 2022-01-01 21:40:47 +11:00
parent 0dd19345ed
commit e585fc6da0
4 changed files with 147 additions and 56 deletions

View File

@ -162,22 +162,22 @@ namespace UnityExplorer.CacheObject
#region Cache Member Util #region Cache Member Util
public static bool CanParseArgs(ParameterInfo[] parameters) //public static bool CanParseArgs(ParameterInfo[] parameters)
{ //{
foreach (var param in parameters) // foreach (var param in parameters)
{ // {
var pType = param.ParameterType; // var pType = param.ParameterType;
//
if (pType.IsByRef && pType.HasElementType) // if (pType.IsByRef && pType.HasElementType)
pType = pType.GetElementType(); // pType = pType.GetElementType();
//
if (pType != null && ParseUtility.CanParse(pType)) // if (pType != null && ParseUtility.CanParse(pType))
continue; // continue;
else // else
return false; // return false;
} // }
return true; // return true;
} //}
public static List<CacheMember> GetCacheMembers(object inspectorTarget, Type _type, ReflectionInspector _inspector) public static List<CacheMember> GetCacheMembers(object inspectorTarget, Type _type, ReflectionInspector _inspector)
{ {
@ -250,11 +250,11 @@ namespace UnityExplorer.CacheObject
&& (mi.Name.StartsWith("get_") || mi.Name.StartsWith("set_"))) && (mi.Name.StartsWith("get_") || mi.Name.StartsWith("set_")))
return; return;
var args = mi.GetParameters(); //var args = mi.GetParameters();
if (!CanParseArgs(args)) //if (!CanParseArgs(args))
return; // return;
sig += GetArgumentString(args); sig += GetArgumentString(mi.GetParameters());
if (cachedSigs.Contains(sig)) if (cachedSigs.Contains(sig))
return; return;
@ -267,9 +267,9 @@ namespace UnityExplorer.CacheObject
{ {
var pi = member as PropertyInfo; var pi = member as PropertyInfo;
var args = pi.GetIndexParameters(); //var args = pi.GetIndexParameters();
if (!CanParseArgs(args)) //if (!CanParseArgs(args))
return; // return;
if (!pi.CanRead && pi.CanWrite) if (!pi.CanRead && pi.CanWrite)
{ {
@ -280,7 +280,7 @@ namespace UnityExplorer.CacheObject
return; return;
} }
sig += GetArgumentString(args); sig += GetArgumentString(pi.GetIndexParameters());
if (cachedSigs.Contains(sig)) if (cachedSigs.Contains(sig))
return; return;

View File

@ -26,6 +26,8 @@ namespace UnityExplorer.CacheObject.Views
private GameObject argHolder; private GameObject argHolder;
private readonly List<GameObject> argRows = new List<GameObject>(); private readonly List<GameObject> argRows = new List<GameObject>();
private readonly List<Text> argLabels = new List<Text>(); private readonly List<Text> argLabels = new List<Text>();
private readonly List<InputFieldRef> argInputFields = new List<InputFieldRef>();
private readonly List<Dropdown> argDropdowns = new List<Dropdown>();
private Type[] genericArguments; private Type[] genericArguments;
private string[] genericInput; private string[] genericInput;
@ -34,9 +36,6 @@ namespace UnityExplorer.CacheObject.Views
private readonly List<GameObject> genericArgRows = new List<GameObject>(); private readonly List<GameObject> genericArgRows = new List<GameObject>();
private readonly List<Text> genericArgLabels = new List<Text>(); private readonly List<Text> genericArgLabels = new List<Text>();
private readonly List<TypeCompleter> genericAutocompleters = new List<TypeCompleter>(); private readonly List<TypeCompleter> genericAutocompleters = new List<TypeCompleter>();
//private readonly List<InputFieldRef> inputFields = new List<InputFieldRef>();
private readonly List<InputFieldRef> argInputFields = new List<InputFieldRef>();
private readonly List<InputFieldRef> genericInputFields = new List<InputFieldRef>(); private readonly List<InputFieldRef> genericInputFields = new List<InputFieldRef>();
public void OnBorrowedFromPool(CacheMember owner) public void OnBorrowedFromPool(CacheMember owner)
@ -52,6 +51,8 @@ namespace UnityExplorer.CacheObject.Views
SetArgRows(); SetArgRows();
this.UIRoot.SetActive(true); this.UIRoot.SetActive(true);
InspectorManager.OnInspectedTabsChanged += InspectorManager_OnInspectedTabsChanged;
} }
public void OnReturnToPool() public void OnReturnToPool()
@ -62,6 +63,17 @@ namespace UnityExplorer.CacheObject.Views
input.Text = ""; input.Text = "";
this.Owner = null; 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() public Type[] TryParseGenericArguments()
@ -83,33 +95,62 @@ namespace UnityExplorer.CacheObject.Views
for (int i = 0; i < arguments.Length; i++) for (int i = 0; i < arguments.Length; i++)
{ {
var arg = arguments[i]; var paramInfo = arguments[i];
var input = argumentInput[i];
var type = arg.ParameterType; var argType = paramInfo.ParameterType;
if (type.IsByRef) if (argType.IsByRef)
type = type.GetElementType(); argType = argType.GetElementType();
if (type == typeof(string)) if (ParseUtility.CanParse(argType))
{ {
outArgs[i] = input; var input = argumentInput[i];
continue;
}
if (string.IsNullOrEmpty(input)) if (argType == typeof(string))
{ {
if (arg.IsOptional) outArgs[i] = input;
outArgs[i] = arg.DefaultValue; continue;
else }
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; outArgs[i] = null;
continue; ExplorerCore.LogWarning($"Cannot parse argument '{paramInfo.Name}' ({paramInfo.ParameterType.Name})" +
$"{(ex == null ? "" : $", {ex.GetType().Name}: {ex.Message}")}");
}
} }
else
if (!ParseUtility.TryParse(input, type, out outArgs[i], out Exception ex))
{ {
outArgs[i] = null; var dropdown = argDropdowns[i];
ExplorerCore.LogWarning($"Cannot parse argument '{arg.Name}' ({arg.ParameterType.Name})" + if (dropdown.value == 0)
$"{(ex == null ? "" : $", {ex.GetType().Name}: {ex.Message}")}"); {
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 arg = arguments[i];
var argType = arg.ParameterType;
if (argType.IsByRef)
argType = argType.GetElementType();
if (i >= argRows.Count) if (i >= argRows.Count)
AddArgRow(i, false); AddArgRow(i, false);
argRows[i].SetActive(true); argRows[i].SetActive(true);
argLabels[i].text = $"{SignatureHighlighter.Parse(arg.ParameterType, false)} <color={SignatureHighlighter.LOCAL_ARG}>{arg.Name}</color>"; argLabels[i].text =
if (arg.ParameterType == typeof(string)) $"{SignatureHighlighter.Parse(argType, false)} <color={SignatureHighlighter.LOCAL_ARG}>{arg.Name}</color>";
argInputFields[i].PlaceholderText.text = "";
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 else
{ {
var elemType = arg.ParameterType; argInputFields[i].Component.gameObject.SetActive(false);
if (elemType.IsByRef) argDropdowns[i].gameObject.SetActive(true);
elemType = elemType.GetElementType();
argInputFields[i].PlaceholderText.text = $"eg. {ParseUtility.GetExampleInput(elemType)}"; 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) private void AddArgRow(int index, bool generic)
{ {
if (!generic) if (!generic)
@ -242,7 +312,17 @@ namespace UnityExplorer.CacheObject.Views
inputField.OnValueChanged += (string val) => { inputArray[index] = val; }; inputField.OnValueChanged += (string val) => { inputArray[index] = val; };
if (!generic) 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<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
argInputFields.Add(inputField); argInputFields.Add(inputField);
argDropdowns.Add(dropdown);
}
else else
genericInputFields.Add(inputField); genericInputFields.Add(inputField);
@ -250,6 +330,11 @@ namespace UnityExplorer.CacheObject.Views
genericAutocompleters.Add(new TypeCompleter(null, inputField)); genericAutocompleters.Add(new TypeCompleter(null, inputField));
} }
private void ArgDropdownChanged(int argIndex, int value)
{
// not sure if necessary
}
public GameObject CreateContent(GameObject parent) public GameObject CreateContent(GameObject parent)
{ {
UIRoot = UIFactory.CreateVerticalGroup(parent, "EvaluateWidget", false, false, true, true, 3, new Vector4(2, 2, 2, 2), UIRoot = UIFactory.CreateVerticalGroup(parent, "EvaluateWidget", false, false, true, true, 3, new Vector4(2, 2, 2, 2),

View File

@ -16,7 +16,7 @@ namespace UnityExplorer
public static class ExplorerCore public static class ExplorerCore
{ {
public const string NAME = "UnityExplorer"; 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 AUTHOR = "Sinai";
public const string GUID = "com.sinai.unityexplorer"; public const string GUID = "com.sinai.unityexplorer";

View File

@ -23,6 +23,8 @@ namespace UnityExplorer
public static float PanelWidth; public static float PanelWidth;
public static event Action OnInspectedTabsChanged;
public static void Inspect(object obj, CacheObjectBase sourceCache = null) public static void Inspect(object obj, CacheObjectBase sourceCache = null)
{ {
if (obj.IsNullOrDestroyed()) if (obj.IsNullOrDestroyed())
@ -111,6 +113,8 @@ namespace UnityExplorer
inspector.OnBorrowedFromPool(target); inspector.OnBorrowedFromPool(target);
SetInspectorActive(inspector); SetInspectorActive(inspector);
OnInspectedTabsChanged?.Invoke();
} }
internal static void ReleaseInspector<T>(T inspector) where T : InspectorBase internal static void ReleaseInspector<T>(T inspector) where T : InspectorBase
@ -144,6 +148,8 @@ namespace UnityExplorer
UIManager.SetPanelActive(UIManager.Panels.Inspector, false); UIManager.SetPanelActive(UIManager.Panels.Inspector, false);
} }
} }
OnInspectedTabsChanged?.Invoke();
} }
internal static void Update() internal static void Update()