various improvements to reflection inspector and C# console

This commit is contained in:
sinaioutlander
2020-11-12 16:15:41 +11:00
parent 2077601464
commit a7f86227fb
28 changed files with 656 additions and 420 deletions

View File

@ -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()

View File

@ -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 = $"<color={classColor}>{MemInfo.DeclaringType.Name}</color>.";
if (isStatic) m_richTextName += "<i>";
m_richTextName += $"<color={memberColor}>{MemInfo.Name}</color>";
if (isStatic) m_richTextName += "</i>";
// 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 += $"<color={SyntaxColors.StructGreen}>{cm.GenericArgs[i].Name}</color>";
}
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<LayoutElement>();
//btnLayout.minWidth = 30;
//btnLayout.minHeight = 20;
//btnLayout.flexibleWidth = 0;
//var refreshTxt = refreshBtnObj.GetComponentInChildren<Text>();
//refreshTxt.text = "⟳";
//refreshTxt.fontSize = 16;
//var refreshBtn = refreshBtnObj.GetComponent<Button>();
//refreshBtn.onClick.AddListener(() => { ExplorerCore.Log("todo Update!"); });
var topGroupObj = UIFactory.CreateHorizontalGroup(m_mainContent, new Color(1, 1, 1, 0));
m_topRowRect = topGroupObj.GetComponent<RectTransform>();
var topLayout = topGroupObj.AddComponent<LayoutElement>();
topLayout.minHeight = 25;
topLayout.flexibleHeight = 0;
topLayout.minWidth = 300;
topLayout.flexibleWidth = 5000;
var topGroup = topGroupObj.GetComponent<HorizontalLayoutGroup>();
topGroup.childForceExpandHeight = false;
topGroup.childForceExpandWidth = false;
topGroup.childControlHeight = true;
topGroup.childControlWidth = true;
topGroup.spacing = 10;
var labelObj = UIFactory.CreateLabel(m_topContent, TextAnchor.MiddleLeft);
var labellayout = labelObj.AddComponent<LayoutElement>();
labellayout.minWidth = 225;
labellayout.flexibleWidth = 0;
// left group
var label = labelObj.GetComponent<Text>();
label.horizontalOverflow = HorizontalWrapMode.Wrap;
label.text = this.RichTextName;
m_leftGroup = UIFactory.CreateHorizontalGroup(topGroupObj, new Color(1, 1, 1, 0));
var leftLayout = m_leftGroup.AddComponent<LayoutElement>();
leftLayout.minHeight = 25;
leftLayout.flexibleHeight = 0;
leftLayout.minWidth = 125;
leftLayout.flexibleWidth = 200;
var leftGroup = m_leftGroup.GetComponent<HorizontalLayoutGroup>();
leftGroup.childForceExpandHeight = true;
leftGroup.childForceExpandWidth = false;
leftGroup.childControlHeight = true;
leftGroup.childControlWidth = true;
leftGroup.spacing = 4;
// member label
var labelObj = UIFactory.CreateLabel(m_leftGroup, TextAnchor.MiddleLeft);
var leftRect = labelObj.GetComponent<RectTransform>();
leftRect.anchorMin = Vector2.zero;
leftRect.anchorMax = Vector2.one;
leftRect.offsetMin = Vector2.zero;
leftRect.offsetMax = Vector2.zero;
leftRect.sizeDelta = Vector2.zero;
m_leftLayout = labelObj.AddComponent<LayoutElement>();
m_leftLayout.preferredWidth = 225;
m_leftLayout.minHeight = 25;
m_leftLayout.flexibleHeight = 100;
var labelFitter = labelObj.AddComponent<ContentSizeFitter>();
labelFitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
labelFitter.horizontalFit = ContentSizeFitter.FitMode.PreferredSize;
m_memLabelText = labelObj.GetComponent<Text>();
m_memLabelText.horizontalOverflow = HorizontalWrapMode.Wrap;
m_memLabelText.text = this.RichTextName;
// right group
m_rightGroup = UIFactory.CreateHorizontalGroup(topGroupObj, new Color(1, 1, 1, 0));
m_rightLayout = m_rightGroup.AddComponent<LayoutElement>();
m_rightLayout.minHeight = 25;
m_rightLayout.flexibleHeight = 480;
m_rightLayout.minWidth = 300;
m_rightLayout.flexibleWidth = 5000;
var rightGroup = m_rightGroup.GetComponent<HorizontalLayoutGroup>();
rightGroup.childForceExpandHeight = false;
rightGroup.childForceExpandWidth = true;
rightGroup.childControlHeight = true;
rightGroup.childControlWidth = true;
rightGroup.spacing = 4;
// todo check for HasParameters, etc
if (!HasParameters && IsMember)
{
//var refreshBtnObj = UIFactory.CreateButton(topRowObj, new Color(0.3f, 0.3f, 0.3f));
//var btnLayout = refreshBtnObj.AddComponent<LayoutElement>();
//btnLayout.minWidth = 30;
//btnLayout.minHeight = 20;
//btnLayout.flexibleWidth = 0;
//var refreshTxt = refreshBtnObj.GetComponentInChildren<Text>();
//refreshTxt.text = "⟳";
//refreshTxt.fontSize = 16;
//var refreshBtn = refreshBtnObj.GetComponent<Button>();
//refreshBtn.onClick.AddListener(() => { ExplorerCore.Log("todo Update!"); });
}
IValue.ConstructUI(m_rightGroup);
// todo subcontent
//m_subContent = UIFactory.CreateHorizontalGroup(m_parentContent, new Color(1, 1, 1, 0));
//var subGroup = m_subContent.GetComponent<HorizontalLayoutGroup>();
//subGroup.childForceExpandWidth = true;
//subGroup.childControlWidth = true;
//var subLayout = m_subContent.AddComponent<LayoutElement>();
//subLayout.minHeight = 25;
//subLayout.flexibleHeight = 500;
//subLayout.minWidth = 125;
//subLayout.flexibleWidth = 9000;
//m_subContent.SetActive(false);
}
#endregion

View File

@ -19,7 +19,7 @@ namespace UnityExplorer.Inspectors.Reflection
public Type[] GenericArgs { get; private set; }
public Type[][] GenericConstraints { get; private set; }
public string[] GenericArgInput = new string[0];
public string[] m_genericArgInput = new string[0];
public CacheMethod(MethodInfo methodInfo, object declaringInstance) : base(methodInfo, declaringInstance)
{
@ -28,7 +28,7 @@ namespace UnityExplorer.Inspectors.Reflection
GenericConstraints = GenericArgs.Select(x => x.GetGenericParameterConstraints())
.ToArray();
GenericArgInput = new string[GenericArgs.Length];
m_genericArgInput = new string[GenericArgs.Length];
m_arguments = methodInfo.GetParameters();
m_argumentInput = new string[m_arguments.Length];
@ -94,7 +94,7 @@ namespace UnityExplorer.Inspectors.Reflection
var list = new List<Type>();
for (int i = 0; i < GenericArgs.Length; i++)
{
var input = GenericArgInput[i];
var input = m_genericArgInput[i];
if (ReflectionHelpers.GetTypeByName(input) is Type t)
{
if (GenericConstraints[i].Length == 0)
@ -118,7 +118,7 @@ namespace UnityExplorer.Inspectors.Reflection
else
{
ExplorerCore.LogWarning($"Generic argument #{i}, could not get any type by the name of '{input}'!" +
$" Make sure you use the full name, including the NameSpace.");
$" Make sure you use the full name including the namespace.");
return null;
}
}

View File

@ -41,7 +41,6 @@ namespace UnityExplorer.Inspectors.Reflection
if (!m_constructedUI)
{
ConstructUI();
IValue.ConstructUI(m_topContent);
UpdateValue();
}
@ -65,8 +64,6 @@ namespace UnityExplorer.Inspectors.Reflection
internal bool m_constructedUI;
internal GameObject m_parentContent;
internal GameObject m_mainContent;
internal GameObject m_topContent;
//internal GameObject m_subContent;
// Make base UI holder for CacheObject, this doesnt actually display anything.
internal virtual void ConstructUI()
@ -81,32 +78,9 @@ namespace UnityExplorer.Inspectors.Reflection
rowGroup.childControlHeight = true;
var rowLayout = m_mainContent.AddComponent<LayoutElement>();
rowLayout.minHeight = 25;
rowLayout.flexibleHeight = 0;
rowLayout.flexibleHeight = 500;
rowLayout.minWidth = 200;
rowLayout.flexibleWidth = 5000;
m_topContent = UIFactory.CreateHorizontalGroup(m_mainContent, new Color(1, 1, 1, 0));
var topLayout = m_topContent.AddComponent<LayoutElement>();
topLayout.minHeight = 25;
topLayout.flexibleHeight = 0;
var topGroup = m_topContent.GetComponent<HorizontalLayoutGroup>();
topGroup.childForceExpandHeight = false;
topGroup.childForceExpandWidth = true;
topGroup.childControlHeight = true;
topGroup.childControlWidth = true;
topGroup.spacing = 4;
//m_subContent = UIFactory.CreateHorizontalGroup(m_parentContent, new Color(1, 1, 1, 0));
//var subGroup = m_subContent.GetComponent<HorizontalLayoutGroup>();
//subGroup.childForceExpandWidth = true;
//subGroup.childControlWidth = true;
//var subLayout = m_subContent.AddComponent<LayoutElement>();
//subLayout.minHeight = 25;
//subLayout.flexibleHeight = 500;
//subLayout.minWidth = 125;
//subLayout.flexibleWidth = 9000;
//m_subContent.SetActive(false);
}
#endregion

View File

@ -30,32 +30,23 @@ namespace UnityExplorer.Inspectors.Reflection
return;
}
try
var pi = MemInfo as PropertyInfo;
if (pi.CanRead)
{
var pi = MemInfo as PropertyInfo;
var target = pi.GetAccessors(true)[0].IsStatic ? null : DeclaringInstance;
if (pi.CanRead)
{
var target = pi.GetAccessors()[0].IsStatic ? null : DeclaringInstance;
IValue.Value = pi.GetValue(target, ParseArguments());
IValue.Value = pi.GetValue(target, ParseArguments());
//base.UpdateValue();
m_evaluated = true;
ReflectionException = null;
}
else // create a dummy value for Write-Only properties.
{
if (IValue.ValueType == typeof(string))
IValue.Value = "";
else
IValue.Value = Activator.CreateInstance(IValue.ValueType);
}
m_evaluated = true;
ReflectionException = null;
}
catch (Exception e)
else // create a dummy value for Write-Only properties.
{
ReflectionException = ReflectionHelpers.ExceptionToString(e);
if (IValue.ValueType == typeof(string))
IValue.Value = "";
else
IValue.Value = Activator.CreateInstance(IValue.ValueType);
}
}

View File

@ -3,10 +3,12 @@ using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using UnityExplorer.Helpers;
using UnityExplorer.UI;
using UnityExplorer.UI.Shared;
using UnityExplorer.Unstrip;
namespace UnityExplorer.Inspectors.Reflection
{
@ -17,11 +19,12 @@ namespace UnityExplorer.Inspectors.Reflection
public object Value { get; set; }
public Type ValueType;
public string ButtonLabel => m_btnLabel ?? GetButtonLabel();
private string m_btnLabel;
public string RichTextValue => m_richValue ?? GetRichTextValue();
internal string m_richValue;
internal string m_richValueType;
public MethodInfo ToStringMethod => m_toStringMethod ?? GetToStringMethod();
private MethodInfo m_toStringMethod;
internal MethodInfo m_toStringMethod;
public virtual void Init()
{
@ -39,15 +42,14 @@ namespace UnityExplorer.Inspectors.Reflection
return;
}
if (Value == null)
{
m_text.text = "<color=red>null</color>";
}
else
{
GetButtonLabel();
m_text.text = ButtonLabel;
}
GetRichTextValue();
m_text.text = RichTextValue;
//if (Value == null)
// m_text.text = $"<color=red>null</color> {m_richValueType}";
//else
// m_text.text = RichTextValue;
}
private MethodInfo GetToStringMethod()
@ -67,85 +69,79 @@ namespace UnityExplorer.Inspectors.Reflection
return m_toStringMethod;
}
public string GetButtonLabel()
{
if (Value == null) return "";
var valueType = ReflectionHelpers.GetActualType(Value);
public string GetRichTextValue()
{
if (Value != null)
ValueType = Value.GetType();
m_richValueType = UISyntaxHighlight.GetHighlight(ValueType, true);
if (Value == null) return $"<color=grey>null</color> ({m_richValueType})";
string label;
if (valueType == typeof(TextAsset))
if (ValueType == typeof(TextAsset))
{
var textAsset = Value as TextAsset;
label = textAsset.text;
if (label.Length > 10)
{
label = $"{label.Substring(0, 10)}...";
}
label = $"\"{label}\" {textAsset.name} (<color={SyntaxColors.Class_Instance}>UnityEngine.TextAsset</color>)";
label = $"\"{label}\" {textAsset.name} ({m_richValueType})";
}
else if (ValueType == typeof(EventSystem))
{
label = m_richValueType;
}
else
{
label = (string)ToStringMethod?.Invoke(Value, null) ?? Value.ToString();
var toString = (string)ToStringMethod.Invoke(Value, null);
var classColor = valueType.IsAbstract && valueType.IsSealed
? SyntaxColors.Class_Static
: SyntaxColors.Class_Instance;
var temp = toString.Replace(ValueType.FullName, "").Trim();
string typeLabel = $"<color={classColor}>{valueType.FullName}</color>";
if (Value is UnityEngine.Object)
if (string.IsNullOrEmpty(temp))
{
label = label.Replace($"({valueType.FullName})", $"({typeLabel})");
label = m_richValueType;
}
else
{
if (!label.Contains(valueType.FullName))
{
label += $" ({typeLabel})";
}
if (toString.Length > 200)
toString = toString.Substring(0, 200) + "...";
label = toString;
var unityType = $"({ValueType.FullName})";
if (Value is UnityEngine.Object && label.Contains(unityType))
label = label.Replace(unityType, $"({m_richValueType})");
else
{
label = label.Replace(valueType.FullName, typeLabel);
}
label += $" ({m_richValueType})";
}
}
return m_btnLabel = label;
return m_richValue = label;
}
#region UI CONSTRUCTION
#region UI CONSTRUCTION
internal GameObject m_UIContent;
internal Text m_text;
public void ConstructUI(GameObject parent)
{
// TEMPORARY
m_UIContent = UIFactory.CreateLabel(parent, TextAnchor.MiddleLeft);
var mainLayout = m_UIContent.AddComponent<LayoutElement>();
mainLayout.minWidth = 100;
mainLayout.minWidth = 200;
mainLayout.flexibleWidth = 5000;
mainLayout.minHeight = 25;
m_text = m_UIContent.GetComponent<Text>();
if (OwnerCacheObject != null)
{
if (!OwnerCacheObject.HasEvaluated)
{
m_text.text = "Not yet evaluated";
}
else
{
m_text.text = ButtonLabel;
}
}
GetRichTextValue();
m_text.text = $"<i><color=grey>Not yet evaluated</color> ({m_richValueType})</i>";
}
#endregion
#endregion
}
}