diff --git a/src/Input/InputManager.cs b/src/Input/InputManager.cs index 81015a4..127d495 100644 --- a/src/Input/InputManager.cs +++ b/src/Input/InputManager.cs @@ -8,7 +8,6 @@ using UnhollowerBaseLib; namespace UnityExplorer.Input { - [SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "Unity style")] public static class InputManager { private static IHandleInput m_inputModule; diff --git a/src/Inspectors/GameObjectInspector.cs b/src/Inspectors/GameObjectInspector.cs index 787b1a0..b27fedf 100644 --- a/src/Inspectors/GameObjectInspector.cs +++ b/src/Inspectors/GameObjectInspector.cs @@ -7,13 +7,13 @@ using UnityExplorer.Unstrip; using TMPro; using UnityEngine; using UnityEngine.UI; -using UnityExplorer.Inspectors.GOInspector; +using UnityExplorer.Inspectors.GameObjects; namespace UnityExplorer.Inspectors { public class GameObjectInspector : InspectorBase { - public override string TabLabel => $" [G] {TargetGO?.name}"; + public override string TabLabel => $" [G] {TargetGO?.name}"; public static GameObjectInspector ActiveInstance { get; private set; } @@ -35,12 +35,15 @@ namespace UnityExplorer.Inspectors set => s_content = value; } - public static TMP_InputField m_nameInput; private static string m_lastName; - public static TMP_InputField m_pathInput; + public static TMP_InputField m_nameInput; + private static string m_lastPath; + public static TMP_InputField m_pathInput; + private static RectTransform m_pathInputRect; private static GameObject m_pathGroupObj; private static Text m_hiddenPathText; + private static RectTransform m_hiddenPathRect; private static Toggle m_enabledToggle; private static Text m_enabledText; @@ -77,15 +80,15 @@ namespace UnityExplorer.Inspectors } } - public override void SetContentActive() + public override void SetActive() { - base.SetContentActive(); + base.SetActive(); ActiveInstance = this; } - public override void SetContentInactive() + public override void SetInactive() { - base.SetContentInactive(); + base.SetInactive(); ActiveInstance = null; } @@ -103,7 +106,7 @@ namespace UnityExplorer.Inspectors { base.Update(); - if (m_pendingDestroy || ActiveInstance != this) + if (m_pendingDestroy || !this.IsActive) return; RefreshTopInfo(); @@ -135,9 +138,12 @@ namespace UnityExplorer.Inspectors if (m_lastPath != path) { m_lastPath = path; + m_pathInput.text = path; m_hiddenPathText.text = path; - m_pathInput.ForceLabelUpdate(); + + LayoutRebuilder.ForceRebuildLayoutImmediate(m_pathInputRect); + LayoutRebuilder.ForceRebuildLayoutImmediate(m_hiddenPathRect); } } else if (m_pathGroupObj.activeSelf) @@ -271,8 +277,8 @@ namespace UnityExplorer.Inspectors hiddenFitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize; var hiddenLayout = pathHiddenTextObj.AddComponent(); hiddenLayout.minHeight = 25; - hiddenLayout.flexibleHeight = 75; - hiddenLayout.minWidth = 400; + hiddenLayout.flexibleHeight = 125; + hiddenLayout.minWidth = 250; hiddenLayout.flexibleWidth = 9000; var hiddenGroup = pathHiddenTextObj.AddComponent(); hiddenGroup.childForceExpandWidth = true; @@ -297,13 +303,16 @@ namespace UnityExplorer.Inspectors m_pathInput.textComponent.color = new Color(0.75f, 0.75f, 0.75f); m_pathInput.textComponent.lineSpacing = 1.5f; + m_pathInputRect = m_pathInput.GetComponent(); + m_hiddenPathRect = m_hiddenPathText.GetComponent(); + // name row var nameRowObj = UIFactory.CreateHorizontalGroup(scrollContent, new Color(0.1f, 0.1f, 0.1f)); var nameGroup = nameRowObj.GetComponent(); nameGroup.childForceExpandHeight = false; nameGroup.childForceExpandWidth = false; - nameGroup.childControlHeight = false; + nameGroup.childControlHeight = true; nameGroup.childControlWidth = true; nameGroup.spacing = 5; var nameRect = nameRowObj.GetComponent(); diff --git a/src/Inspectors/GOInspector/ChildList.cs b/src/Inspectors/GameObjects/ChildList.cs similarity index 99% rename from src/Inspectors/GOInspector/ChildList.cs rename to src/Inspectors/GameObjects/ChildList.cs index e249be2..c3d31ec 100644 --- a/src/Inspectors/GOInspector/ChildList.cs +++ b/src/Inspectors/GameObjects/ChildList.cs @@ -9,7 +9,7 @@ using UnityEngine; using UnityEngine.UI; using UnityExplorer.Input; -namespace UnityExplorer.Inspectors.GOInspector +namespace UnityExplorer.Inspectors.GameObjects { public class ChildList { diff --git a/src/Inspectors/GOInspector/ComponentList.cs b/src/Inspectors/GameObjects/ComponentList.cs similarity index 99% rename from src/Inspectors/GOInspector/ComponentList.cs rename to src/Inspectors/GameObjects/ComponentList.cs index 7049308..23b6b6a 100644 --- a/src/Inspectors/GOInspector/ComponentList.cs +++ b/src/Inspectors/GameObjects/ComponentList.cs @@ -10,7 +10,7 @@ using UnityEngine; using UnityEngine.UI; using UnityExplorer.Input; -namespace UnityExplorer.Inspectors.GOInspector +namespace UnityExplorer.Inspectors.GameObjects { public class ComponentList { diff --git a/src/Inspectors/GOInspector/GameObjectControls.cs b/src/Inspectors/GameObjects/GameObjectControls.cs similarity index 99% rename from src/Inspectors/GOInspector/GameObjectControls.cs rename to src/Inspectors/GameObjects/GameObjectControls.cs index a454f8a..e6008d8 100644 --- a/src/Inspectors/GOInspector/GameObjectControls.cs +++ b/src/Inspectors/GameObjects/GameObjectControls.cs @@ -9,7 +9,7 @@ using UnityEngine.UI; using UnityExplorer.Input; using UnityExplorer.Unstrip; -namespace UnityExplorer.Inspectors.GOInspector +namespace UnityExplorer.Inspectors.GameObjects { public class GameObjectControls { diff --git a/src/Inspectors/InspectorBase.cs b/src/Inspectors/InspectorBase.cs index 7440ed1..567ce1a 100644 --- a/src/Inspectors/InspectorBase.cs +++ b/src/Inspectors/InspectorBase.cs @@ -8,11 +8,11 @@ namespace UnityExplorer.Inspectors public abstract class InspectorBase { public object Target; - // just to cache a cast public UnityEngine.Object UnityTarget; public abstract string TabLabel { get; } + public bool IsActive { get; private set; } public abstract GameObject Content { get; set; } public Button tabButton; public Text tabText; @@ -33,13 +33,15 @@ namespace UnityExplorer.Inspectors AddInspectorTab(); } - public virtual void SetContentActive() + public virtual void SetActive() { + this.IsActive = true; Content?.SetActive(true); } - public virtual void SetContentInactive() + public virtual void SetInactive() { + this.IsActive = false; Content?.SetActive(false); } @@ -65,11 +67,6 @@ namespace UnityExplorer.Inspectors GameObject.Destroy(tabGroup); } - //if (Content) - //{ - // GameObject.Destroy(Content); - //} - int thisIndex = -1; if (InspectorManager.Instance.m_currentInspectors.Contains(this)) { diff --git a/src/Inspectors/InspectorManager.cs b/src/Inspectors/InspectorManager.cs index 0dda33d..c0efa93 100644 --- a/src/Inspectors/InspectorManager.cs +++ b/src/Inspectors/InspectorManager.cs @@ -8,6 +8,7 @@ using UnityEngine; using UnityEngine.SceneManagement; using UnityEngine.UI; using TMPro; +using UnityExplorer.Inspectors.Reflection; namespace UnityExplorer.Inspectors { @@ -82,23 +83,29 @@ namespace UnityExplorer.Inspectors InspectorBase inspector; if (obj is GameObject go) - { inspector = new GameObjectInspector(go); - } else - { inspector = new InstanceInspector(obj); - } m_currentInspectors.Add(inspector); - inspector.SetContentInactive(); - SetInspectorTab(inspector); } public void Inspect(Type type) { - // TODO static type inspection + foreach (var tab in m_currentInspectors) + { + if (ReferenceEquals(tab.Target as Type, type)) + { + SetInspectorTab(tab); + return; + } + } + + var inspector = new StaticInspector(type); + + m_currentInspectors.Add(inspector); + SetInspectorTab(inspector); } public void SetInspectorTab(InspectorBase inspector) @@ -107,7 +114,7 @@ namespace UnityExplorer.Inspectors m_activeInspector = inspector; - inspector.SetContentActive(); + inspector.SetActive(); Color activeColor = new Color(0, 0.25f, 0, 1); ColorBlock colors = inspector.tabButton.colors; @@ -119,11 +126,9 @@ namespace UnityExplorer.Inspectors public void UnsetInspectorTab() { if (m_activeInspector == null) - { return; - } - m_activeInspector.SetContentInactive(); + m_activeInspector.SetInactive(); ColorBlock colors = m_activeInspector.tabButton.colors; colors.normalColor = new Color(0.2f, 0.2f, 0.2f, 1); diff --git a/src/Inspectors/ReflectionInspector/CacheObject/CacheEnumerated.cs b/src/Inspectors/Reflection/CacheObject/CacheEnumerated.cs similarity index 93% rename from src/Inspectors/ReflectionInspector/CacheObject/CacheEnumerated.cs rename to src/Inspectors/Reflection/CacheObject/CacheEnumerated.cs index 201f2ea..f978d08 100644 --- a/src/Inspectors/ReflectionInspector/CacheObject/CacheEnumerated.cs +++ b/src/Inspectors/Reflection/CacheObject/CacheEnumerated.cs @@ -5,7 +5,7 @@ //using System.Text; //using UnityExplorer.UI; -//namespace UnityExplorer.CacheObject +//namespace UnityExplorer.Inspectors.Reflection //{ // public class CacheEnumerated : CacheObjectBase // { diff --git a/src/Inspectors/Reflection/CacheObject/CacheFactory.cs b/src/Inspectors/Reflection/CacheObject/CacheFactory.cs new file mode 100644 index 0000000..ffb6ee9 --- /dev/null +++ b/src/Inspectors/Reflection/CacheObject/CacheFactory.cs @@ -0,0 +1,75 @@ +using System; +using System.Reflection; +using UnityEngine; +using UnityExplorer.Helpers; + +namespace UnityExplorer.Inspectors.Reflection +{ + public static class CacheFactory + { + // Don't think I need these with new structure. + // Will possibly need something for CacheEnumerated / InteractiveEnumeration though. + + //public static CacheObjectBase GetCacheObject(object obj) + //{ + // if (obj == null) return null; + + // return GetCacheObject(obj, ReflectionHelpers.GetActualType(obj)); + //} + + //public static CacheObjectBase GetCacheObject(object obj, Type type) + //{ + // var ret = new CacheObjectBase(); + // ret.InitValue(obj, type); + // return ret; + //} + + public static CacheMember GetCacheObject(MemberInfo member, object declaringInstance) + { + CacheMember ret; + + if (member is MethodInfo mi && CanProcessArgs(mi.GetParameters())) + { + ret = new CacheMethod(mi, declaringInstance); + } + else if (member is PropertyInfo pi && CanProcessArgs(pi.GetIndexParameters())) + { + ret = new CacheProperty(pi, declaringInstance); + } + else if (member is FieldInfo fi) + { + ret = new CacheField(fi, declaringInstance); + } + else + { + return null; + } + + return ret; + } + + public static bool CanProcessArgs(ParameterInfo[] parameters) + { + foreach (var param in parameters) + { + var pType = param.ParameterType; + + if (pType.IsByRef && pType.HasElementType) + { + pType = pType.GetElementType(); + } + + if (pType.IsPrimitive || pType == typeof(string)) + { + continue; + } + else + { + return false; + } + } + + return true; + } + } +} diff --git a/src/Inspectors/Reflection/CacheObject/CacheField.cs b/src/Inspectors/Reflection/CacheObject/CacheField.cs new file mode 100644 index 0000000..c57b9dc --- /dev/null +++ b/src/Inspectors/Reflection/CacheObject/CacheField.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Reflection; +using UnityExplorer.UI; +using UnityExplorer.Helpers; + +namespace UnityExplorer.Inspectors.Reflection +{ + public class CacheField : CacheMember + { + public override bool IsStatic => (MemInfo as FieldInfo).IsStatic; + + public CacheField(FieldInfo fieldInfo, object declaringInstance) : base(fieldInfo, declaringInstance) + { + base.InitValue(null, fieldInfo.FieldType); + + UpdateValue(); + } + + public override void UpdateValue() + { + //if (IValue is InteractiveDictionary iDict) + //{ + // if (!iDict.EnsureDictionaryIsSupported()) + // { + // ReflectionException = "Not supported due to TypeInitializationException"; + // return; + // } + //} + + try + { + var fi = MemInfo as FieldInfo; + IValue.Value = fi.GetValue(fi.IsStatic ? null : DeclaringInstance); + + base.UpdateValue(); + } + catch (Exception e) + { + ReflectionException = ReflectionHelpers.ExceptionToString(e); + } + } + + public override void SetValue() + { + var fi = MemInfo as FieldInfo; + fi.SetValue(fi.IsStatic ? null : DeclaringInstance, IValue.Value); + } + } +} diff --git a/src/Inspectors/Reflection/CacheObject/CacheMember.cs b/src/Inspectors/Reflection/CacheObject/CacheMember.cs new file mode 100644 index 0000000..b7910eb --- /dev/null +++ b/src/Inspectors/Reflection/CacheObject/CacheMember.cs @@ -0,0 +1,222 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using UnityEngine; +using UnityExplorer.UI; +using UnityExplorer.UI.Shared; + +namespace UnityExplorer.Inspectors.Reflection +{ + public class CacheMember : CacheObjectBase + { + public MemberInfo MemInfo { get; set; } + public Type DeclaringType { get; set; } + public object DeclaringInstance { get; set; } + + public virtual bool IsStatic { get; private set; } + + public override bool HasParameters => m_arguments != null && m_arguments.Length > 0; + public override bool IsMember => true; + + public string RichTextName => m_richTextName ?? GetRichTextName(); + private string m_richTextName; + + public override bool CanWrite => m_canWrite ?? GetCanWrite(); + private bool? m_canWrite; + + public string ReflectionException { get; set; } + + public bool m_evaluated = false; + public bool m_isEvaluating; + public ParameterInfo[] m_arguments = new ParameterInfo[0]; + public string[] m_argumentInput = new string[0]; + + public CacheMember(MemberInfo memberInfo, object declaringInstance) + { + MemInfo = memberInfo; + DeclaringType = memberInfo.DeclaringType; + DeclaringInstance = declaringInstance; + } + + //public virtual void InitMember(MemberInfo member, object declaringInstance) + //{ + // MemInfo = member; + // DeclaringInstance = declaringInstance; + // DeclaringType = member.DeclaringType; + //} + + public override void UpdateValue() + { + base.UpdateValue(); + } + + public override void SetValue() + { + // ... + } + + public object[] ParseArguments() + { + if (m_arguments.Length < 1) + { + return new object[0]; + } + + var parsedArgs = new List(); + for (int i = 0; i < m_arguments.Length; i++) + { + var input = m_argumentInput[i]; + var type = m_arguments[i].ParameterType; + + if (type.IsByRef) + { + type = type.GetElementType(); + } + + if (!string.IsNullOrEmpty(input)) + { + if (type == typeof(string)) + { + parsedArgs.Add(input); + continue; + } + else + { + try + { + var arg = type.GetMethod("Parse", new Type[] { typeof(string) }) + .Invoke(null, new object[] { input }); + + parsedArgs.Add(arg); + continue; + } + catch + { + ExplorerCore.Log($"Argument #{i} '{m_arguments[i].Name}' ({type.Name}), could not parse input '{input}'."); + } + } + } + + // No input, see if there is a default value. + if (HasDefaultValue(m_arguments[i])) + { + parsedArgs.Add(m_arguments[i].DefaultValue); + continue; + } + + // Try add a null arg I guess + parsedArgs.Add(null); + } + + return parsedArgs.ToArray(); + } + + public static bool HasDefaultValue(ParameterInfo arg) => arg.DefaultValue != DBNull.Value; + + //public void DrawArgsInput() + //{ + // for (int i = 0; i < this.m_arguments.Length; i++) + // { + // var name = this.m_arguments[i].Name; + // var input = this.m_argumentInput[i]; + // var type = this.m_arguments[i].ParameterType.Name; + + // var label = $"{type} "; + // label += $"{name}"; + // if (HasDefaultValue(this.m_arguments[i])) + // { + // label = $"[{label} = {this.m_arguments[i].DefaultValue ?? "null"}]"; + // } + + + // } + //} + + private bool GetCanWrite() + { + if (MemInfo is FieldInfo fi) + m_canWrite = !(fi.IsLiteral && !fi.IsInitOnly); + else if (MemInfo is PropertyInfo pi) + m_canWrite = pi.CanWrite; + else + m_canWrite = false; + + return (bool)m_canWrite; + } + + 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()[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; + } + } +} diff --git a/src/Inspectors/Reflection/CacheObject/CacheMethod.cs b/src/Inspectors/Reflection/CacheObject/CacheMethod.cs new file mode 100644 index 0000000..e9274da --- /dev/null +++ b/src/Inspectors/Reflection/CacheObject/CacheMethod.cs @@ -0,0 +1,198 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using UnityEngine; +using UnityExplorer.UI.Shared; +using UnityExplorer.Helpers; + +namespace UnityExplorer.Inspectors.Reflection +{ + public class CacheMethod : CacheMember + { + private CacheObjectBase m_cachedReturnValue; + + public override bool HasParameters => base.HasParameters || GenericArgs.Length > 0; + + public override bool IsStatic => (MemInfo as MethodInfo).IsStatic; + + public Type[] GenericArgs { get; private set; } + public Type[][] GenericConstraints { get; private set; } + + public string[] GenericArgInput = new string[0]; + + public CacheMethod(MethodInfo methodInfo, object declaringInstance) : base(methodInfo, declaringInstance) + { + GenericArgs = methodInfo.GetGenericArguments(); + + GenericConstraints = GenericArgs.Select(x => x.GetGenericParameterConstraints()) + .ToArray(); + + GenericArgInput = new string[GenericArgs.Length]; + + m_arguments = methodInfo.GetParameters(); + m_argumentInput = new string[m_arguments.Length]; + + base.InitValue(null, methodInfo.ReturnType); + } + + public override void UpdateValue() + { + // CacheMethod cannot UpdateValue directly. Need to Evaluate. + } + + public void Evaluate() + { + MethodInfo mi; + if (GenericArgs.Length > 0) + { + mi = MakeGenericMethodFromInput(); + if (mi == null) return; + } + else + { + mi = MemInfo as MethodInfo; + } + + object ret = null; + + try + { + ret = mi.Invoke(mi.IsStatic ? null : DeclaringInstance, ParseArguments()); + m_evaluated = true; + m_isEvaluating = false; + } + catch (Exception e) + { + ExplorerCore.LogWarning($"Exception evaluating: {e.GetType()}, {e.Message}"); + ReflectionException = ReflectionHelpers.ExceptionToString(e); + } + + if (ret != null) + { + //m_cachedReturnValue = CacheFactory.GetTypeAndCacheObject(ret); + + //m_cachedReturnValue = CacheFactory.GetCacheObject(ret); + m_cachedReturnValue.UpdateValue(); + } + else + { + m_cachedReturnValue = null; + } + } + + private MethodInfo MakeGenericMethodFromInput() + { + var mi = MemInfo as MethodInfo; + + var list = new List(); + for (int i = 0; i < GenericArgs.Length; i++) + { + var input = GenericArgInput[i]; + if (ReflectionHelpers.GetTypeByName(input) is Type t) + { + if (GenericConstraints[i].Length == 0) + { + list.Add(t); + } + else + { + foreach (var constraint in GenericConstraints[i].Where(x => x != null)) + { + if (!constraint.IsAssignableFrom(t)) + { + ExplorerCore.LogWarning($"Generic argument #{i}, '{input}' is not assignable from the constraint '{constraint}'!"); + return null; + } + } + + list.Add(t); + } + } + 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."); + return null; + } + } + + // make into a generic with type list + mi = mi.MakeGenericMethod(list.ToArray()); + + return mi; + } + + // ==== GUI DRAW ==== + + //public override void Draw(Rect window, float width) + //{ + // base.Draw(window, width); + //} + + public void DrawValue(Rect window, float width) + { + string typeLabel = $"{IValue.ValueType.FullName}"; + + if (m_evaluated) + { + if (m_cachedReturnValue != null) + { + //m_cachedReturnValue.IValue.DrawValue(window, width); + } + else + { + GUILayout.Label($"null ({typeLabel})", new GUILayoutOption[0]); + } + } + else + { + GUILayout.Label($"Not yet evaluated ({typeLabel})", new GUILayoutOption[0]); + } + } + + //public void DrawGenericArgsInput() + //{ + // GUILayout.Label($"Generic Arguments:", new GUILayoutOption[0]); + + // for (int i = 0; i < this.GenericArgs.Length; i++) + // { + // string types = ""; + // if (this.GenericConstraints[i].Length > 0) + // { + // foreach (var constraint in this.GenericConstraints[i]) + // { + // if (types != "") types += ", "; + + // string type; + + // if (constraint == null) + // type = "Any"; + // else + // type = constraint.ToString(); + + // types += $"{type}"; + // } + // } + // else + // { + // types = $"Any"; + // } + // var input = this.GenericArgInput[i]; + + // GUIHelper.BeginHorizontal(new GUILayoutOption[0]); + + // GUI.skin.label.alignment = TextAnchor.MiddleCenter; + // GUILayout.Label( + // $"{this.GenericArgs[i].Name}", + // new GUILayoutOption[] { GUILayout.Width(15) } + // ); + // this.GenericArgInput[i] = GUIHelper.TextField(input, new GUILayoutOption[] { GUILayout.Width(150) }); + // GUI.skin.label.alignment = TextAnchor.MiddleLeft; + // GUILayout.Label(types, new GUILayoutOption[0]); + + // GUILayout.EndHorizontal(); + // } + //} + } +} diff --git a/src/Inspectors/Reflection/CacheObject/CacheObjectBase.cs b/src/Inspectors/Reflection/CacheObject/CacheObjectBase.cs new file mode 100644 index 0000000..3b81d39 --- /dev/null +++ b/src/Inspectors/Reflection/CacheObject/CacheObjectBase.cs @@ -0,0 +1,119 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using UnityEngine; +using UnityExplorer.UI; +using UnityExplorer.UI.Shared; +using UnityExplorer.Helpers; + +namespace UnityExplorer.Inspectors.Reflection +{ + public class CacheObjectBase + { + public InteractiveValue IValue; + + public virtual bool CanWrite => false; + public virtual bool HasParameters => false; + public virtual bool IsMember => false; + + //public bool IsStaticClassSearchResult { get; set; } + + + // TODO + public virtual void InitValue(object value, Type valueType) + { + if (valueType == null && value == null) + { + return; + } + + //ExplorerCore.Log("Initializing InteractiveValue of type " + valueType.FullName); + + // InteractiveValue interactive; + + //if (valueType == typeof(GameObject) || valueType == typeof(Transform)) + //{ + // interactive = new InteractiveGameObject(); + //} + //else if (valueType == typeof(Texture2D)) + //{ + // interactive = new InteractiveTexture2D(); + //} + //else if (valueType == typeof(Texture)) + //{ + // interactive = new InteractiveTexture(); + //} + //else if (valueType == typeof(Sprite)) + //{ + // interactive = new InteractiveSprite(); + //} + //else if (valueType.IsPrimitive || valueType == typeof(string)) + //{ + // interactive = new InteractivePrimitive(); + //} + //else if (valueType.IsEnum) + //{ + // if (valueType.GetCustomAttributes(typeof(FlagsAttribute), true) is object[] attributes && attributes.Length > 0) + // { + // interactive = new InteractiveFlags(); + // } + // else + // { + // interactive = new InteractiveEnum(); + // } + //} + //else if (valueType == typeof(Vector2) || valueType == typeof(Vector3) || valueType == typeof(Vector4)) + //{ + // interactive = new InteractiveVector(); + //} + //else if (valueType == typeof(Quaternion)) + //{ + // interactive = new InteractiveQuaternion(); + //} + //else if (valueType == typeof(Color)) + //{ + // interactive = new InteractiveColor(); + //} + //else if (valueType == typeof(Rect)) + //{ + // interactive = new InteractiveRect(); + //} + //// must check this before IsEnumerable + //else if (ReflectionHelpers.IsDictionary(valueType)) + //{ + // interactive = new InteractiveDictionary(); + //} + //else if (ReflectionHelpers.IsEnumerable(valueType)) + //{ + // interactive = new InteractiveEnumerable(); + //} + //else + //{ + // interactive = new InteractiveValue(); + //} + + //interactive.Value = obj; + //interactive.ValueType = valueType; + + //this.IValue = interactive; + //this.IValue.OwnerCacheObject = this; + + //UpdateValue(); + + //this.IValue.Init(); + } + + public virtual void Draw(Rect window, float width) + { + // IValue.Draw(window, width); + } + + public virtual void UpdateValue() + { + IValue.UpdateValue(); + } + + public virtual void SetValue() => throw new NotImplementedException(); + } +} diff --git a/src/Inspectors/Reflection/CacheObject/CacheProperty.cs b/src/Inspectors/Reflection/CacheObject/CacheProperty.cs new file mode 100644 index 0000000..b68c94f --- /dev/null +++ b/src/Inspectors/Reflection/CacheObject/CacheProperty.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Reflection; +using UnityExplorer.UI; +using UnityExplorer.Helpers; + +namespace UnityExplorer.Inspectors.Reflection +{ + public class CacheProperty : CacheMember + { + public override bool IsStatic => (MemInfo as PropertyInfo).GetAccessors()[0].IsStatic; + + public CacheProperty(PropertyInfo propertyInfo, object declaringInstance) : base(propertyInfo, declaringInstance) + { + this.m_arguments = propertyInfo.GetIndexParameters(); + this.m_argumentInput = new string[m_arguments.Length]; + + base.InitValue(null, propertyInfo.PropertyType); + + UpdateValue(); + } + + public override void UpdateValue() + { + if (HasParameters && !m_isEvaluating) + { + // Need to enter parameters first. + return; + } + + //if (IValue is InteractiveDictionary iDict) + //{ + // if (!iDict.EnsureDictionaryIsSupported()) + // { + // ReflectionException = "Not supported due to TypeInitializationException"; + // return; + // } + //} + + try + { + var pi = MemInfo as PropertyInfo; + + if (pi.CanRead) + { + var target = pi.GetAccessors()[0].IsStatic ? null : DeclaringInstance; + + IValue.Value = pi.GetValue(target, ParseArguments()); + + base.UpdateValue(); + } + else // create a dummy value for Write-Only properties. + { + if (IValue.ValueType == typeof(string)) + { + IValue.Value = ""; + } + else + { + IValue.Value = Activator.CreateInstance(IValue.ValueType); + } + } + } + catch (Exception e) + { + ReflectionException = ReflectionHelpers.ExceptionToString(e); + } + } + + public override void SetValue() + { + var pi = MemInfo as PropertyInfo; + var target = pi.GetAccessors()[0].IsStatic ? null : DeclaringInstance; + + pi.SetValue(target, IValue.Value, ParseArguments()); + } + } +} diff --git a/src/Inspectors/ReflectionInspector/InstanceInspector.cs b/src/Inspectors/Reflection/InstanceInspector.cs similarity index 77% rename from src/Inspectors/ReflectionInspector/InstanceInspector.cs rename to src/Inspectors/Reflection/InstanceInspector.cs index 4a66cef..f066770 100644 --- a/src/Inspectors/ReflectionInspector/InstanceInspector.cs +++ b/src/Inspectors/Reflection/InstanceInspector.cs @@ -1,16 +1,14 @@ using System; using UnityExplorer.Helpers; -namespace UnityExplorer.Inspectors +namespace UnityExplorer.Inspectors.Reflection { public class InstanceInspector : ReflectionInspector { - // todo - public override string TabLabel => $" [R] {base.TabLabel}"; + public override string TabLabel => $" [R] {base.TabLabel}"; public InstanceInspector(object target) : base(target) { - } public override void Update() diff --git a/src/Inspectors/Reflection/InteractiveValue/InteractiveValue.cs b/src/Inspectors/Reflection/InteractiveValue/InteractiveValue.cs new file mode 100644 index 0000000..2c5aae9 --- /dev/null +++ b/src/Inspectors/Reflection/InteractiveValue/InteractiveValue.cs @@ -0,0 +1,104 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using UnityEngine; +using UnityExplorer.Helpers; +using UnityExplorer.UI.Shared; + +namespace UnityExplorer.Inspectors.Reflection +{ + public class InteractiveValue + { + public CacheObjectBase OwnerCacheObject; + + public object Value { get; set; } + public Type ValueType; + + public string ButtonLabel => m_btnLabel ?? GetButtonLabel(); + private string m_btnLabel; + + public MethodInfo ToStringMethod => m_toStringMethod ?? GetToStringMethod(); + private MethodInfo m_toStringMethod; + + public virtual void Init() + { + UpdateValue(); + } + + public virtual void UpdateValue() + { + GetButtonLabel(); + } + + + + private MethodInfo GetToStringMethod() + { + try + { + m_toStringMethod = ReflectionHelpers.GetActualType(Value).GetMethod("ToString", new Type[0]) + ?? typeof(object).GetMethod("ToString", new Type[0]); + + // test invoke + m_toStringMethod.Invoke(Value, null); + } + catch + { + m_toStringMethod = typeof(object).GetMethod("ToString", new Type[0]); + } + return m_toStringMethod; + } + + public string GetButtonLabel() + { + if (Value == null) return null; + + var valueType = ReflectionHelpers.GetActualType(Value); + + string label; + + 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} (UnityEngine.TextAsset)"; + } + else + { + label = (string)ToStringMethod?.Invoke(Value, null) ?? Value.ToString(); + + var classColor = valueType.IsAbstract && valueType.IsSealed + ? SyntaxColors.Class_Static + : SyntaxColors.Class_Instance; + + string typeLabel = $"{valueType.FullName}"; + + if (Value is UnityEngine.Object) + { + label = label.Replace($"({valueType.FullName})", $"({typeLabel})"); + } + else + { + if (!label.Contains(valueType.FullName)) + { + label += $" ({typeLabel})"; + } + else + { + label = label.Replace(valueType.FullName, typeLabel); + } + } + } + + return m_btnLabel = label; + } + } +} diff --git a/src/Inspectors/ReflectionInspector/StaticInspector.cs b/src/Inspectors/Reflection/StaticInspector.cs similarity index 76% rename from src/Inspectors/ReflectionInspector/StaticInspector.cs rename to src/Inspectors/Reflection/StaticInspector.cs index adcfe05..e898eed 100644 --- a/src/Inspectors/ReflectionInspector/StaticInspector.cs +++ b/src/Inspectors/Reflection/StaticInspector.cs @@ -1,10 +1,10 @@ using System; -namespace UnityExplorer.Inspectors +namespace UnityExplorer.Inspectors.Reflection { public class StaticInspector : ReflectionInspector { - public override string TabLabel => $" [S] {base.TabLabel}"; + public override string TabLabel => $" [S] {base.TabLabel}"; public StaticInspector(Type type) : base(type) { diff --git a/src/Inspectors/ReflectionInspector.cs b/src/Inspectors/ReflectionInspector.cs index 3e1003c..5a7a2af 100644 --- a/src/Inspectors/ReflectionInspector.cs +++ b/src/Inspectors/ReflectionInspector.cs @@ -4,6 +4,12 @@ using System.Linq; using System.Text; using UnityExplorer.Helpers; using UnityEngine; +using UnityExplorer.Inspectors.Reflection; +using UnityExplorer.UI.Shared; +using System.Reflection; +using UnityExplorer.UI; +using UnityEngine.UI; +using TMPro; namespace UnityExplorer.Inspectors { @@ -11,6 +17,18 @@ namespace UnityExplorer.Inspectors { public override string TabLabel => m_targetTypeShortName; + internal readonly Type m_targetType; + internal readonly string m_targetTypeShortName; + + // all cached members of the target + internal CacheMember[] m_allMembers; + // filtered members based on current filters + internal CacheMember[] m_membersFiltered; + // actual shortlist of displayed members + internal CacheMember[] m_membersShortlist; + + // UI members + private GameObject m_content; public override GameObject Content { @@ -18,22 +36,260 @@ namespace UnityExplorer.Inspectors set => m_content = value; } - private readonly string m_targetTypeShortName; + internal PageHandler m_pageHandler; + + // Blacklists + private static readonly HashSet s_typeAndMemberBlacklist = new HashSet + { + "Type.DeclaringMethod", + "Rigidbody2D.Cast", + }; + private static readonly HashSet s_methodStartsWithBlacklist = new HashSet + { + "get_", + "set_", + }; + + // Ctor public ReflectionInspector(object target) : base(target) { - Type type = ReflectionHelpers.GetActualType(target); + if (this is StaticInspector) + m_targetType = target as Type; + else + m_targetType = ReflectionHelpers.GetActualType(target); - if (type == null) - { - // TODO - return; - } + m_targetTypeShortName = m_targetType.Name; - m_targetTypeShortName = type.Name; + CacheMembers(m_targetType); + + ConstructUI(); } + // Methods + public override void Update() + { + base.Update(); + // todo + } + + public override void Destroy() + { + base.Destroy(); + + if (this.Content) + GameObject.Destroy(this.Content); + } + + public void CacheMembers(Type type) + { + var list = new List(); + var cachedSigs = new HashSet(); + + var types = ReflectionHelpers.GetAllBaseTypes(type); + + foreach (var declaringType in types) + { + MemberInfo[] infos; + try + { + infos = declaringType.GetMembers(ReflectionHelpers.CommonFlags); + } + catch + { + ExplorerCore.Log($"Exception getting members for type: {declaringType.FullName}"); + continue; + } + + var target = Target; +#if CPP + try + { + target = target.Il2CppCast(declaringType); + } + catch //(Exception e) + { + //ExplorerCore.LogWarning("Excepting casting " + target.GetType().FullName + " to " + declaringType.FullName); + } +#endif + + foreach (var member in infos) + { + try + { + // make sure member type is Field, Method or Property (4 / 8 / 16) + int m = (int)member.MemberType; + if (m < 4 || m > 16) + continue; + + var pi = member as PropertyInfo; + var mi = member as MethodInfo; + + if (this is StaticInspector) + { + if (member is FieldInfo fi && !fi.IsStatic) continue; + else if (pi != null && !pi.GetAccessors(true)[0].IsStatic) continue; + else if (mi != null && !mi.IsStatic) continue; + } + + // check blacklisted members + var sig = $"{member.DeclaringType.Name}.{member.Name}"; + if (s_typeAndMemberBlacklist.Any(it => it == sig)) + continue; + + if (s_methodStartsWithBlacklist.Any(it => member.Name.StartsWith(it))) + continue; + + if (mi != null) + { + AppendParams(mi.GetParameters()); + } + else if (pi != null) + { + AppendParams(pi.GetIndexParameters()); + } + + void AppendParams(ParameterInfo[] _args) + { + sig += " ("; + foreach (var param in _args) + { + sig += $"{param.ParameterType.Name} {param.Name}, "; + } + sig += ")"; + } + + if (cachedSigs.Contains(sig)) + { + continue; + } + + try + { + //ExplorerCore.Log($"Trying to cache member {sig}..."); + + var cached = CacheFactory.GetCacheObject(member, target); + + if (cached != null) + { + cachedSigs.Add(sig); + list.Add(cached); + } + } + catch (Exception e) + { + ExplorerCore.LogWarning($"Exception caching member {sig}!"); + ExplorerCore.Log(e.ToString()); + } + } + catch (Exception e) + { + ExplorerCore.LogWarning($"Exception caching member {member.DeclaringType.FullName}.{member.Name}!"); + ExplorerCore.Log(e.ToString()); + } + } + } + + m_allMembers = list.ToArray(); + + ExplorerCore.Log("Cached " + m_allMembers.Length + " members"); + } + + #region UI CONSTRUCTION + + internal void ConstructUI() + { + var parent = InspectorManager.Instance.m_inspectorContent; + this.Content = UIFactory.CreateVerticalGroup(parent, new Color(0.15f, 0.15f, 0.15f)); + var mainGroup = Content.GetComponent(); + mainGroup.childForceExpandHeight = false; + mainGroup.childForceExpandWidth = true; + mainGroup.childControlHeight = true; + mainGroup.childControlWidth = true; + mainGroup.spacing = 5; + mainGroup.padding.top = 4; + mainGroup.padding.left = 4; + mainGroup.padding.right = 4; + mainGroup.padding.bottom = 4; + + ConstructTopArea(); + + ConstructFilterArea(); + + ConstructMemberList(); + } + + internal void ConstructTopArea() + { + var typeRowObj = UIFactory.CreateHorizontalGroup(Content, new Color(1, 1, 1, 0)); + var typeRowGroup = typeRowObj.GetComponent(); + typeRowGroup.childForceExpandWidth = true; + typeRowGroup.childForceExpandHeight = true; + typeRowGroup.childControlHeight = true; + typeRowGroup.childControlWidth = true; + var typeRowLayout = typeRowObj.AddComponent(); + typeRowLayout.minHeight = 25; + typeRowLayout.flexibleHeight = 0; + typeRowLayout.minWidth = 200; + typeRowLayout.flexibleWidth = 5000; + + var typeLabel = UIFactory.CreateLabel(typeRowObj, TextAnchor.MiddleLeft); + var typeLabelText = typeLabel.GetComponent(); + typeLabelText.text = "Type:"; + var typeLabelTextLayout = typeLabel.AddComponent(); + typeLabelTextLayout.minWidth = 60; + typeLabelTextLayout.flexibleWidth = 0; + typeLabelTextLayout.minHeight = 25; + + var typeLabelInputObj = UIFactory.CreateTMPInput(typeRowObj, 14, 0, (int)TextAlignmentOptions.MidlineLeft); + var typeLabelInput = typeLabelInputObj.GetComponent(); + typeLabelInput.readOnly = true; + var typeLabelLayout = typeLabelInputObj.AddComponent(); + typeLabelLayout.minWidth = 150; + typeLabelLayout.flexibleWidth = 5000; + + string classColor = SyntaxColors.Class_Instance; + if (m_targetType.IsSealed && m_targetType.IsAbstract) + classColor = SyntaxColors.Class_Static; + else if (m_targetType.IsValueType) + classColor = SyntaxColors.StructGreen; + + typeLabelInput.text = $"{m_targetType.Namespace}.{m_targetType.Name}"; + } + + internal void ConstructFilterArea() + { + + } + + internal void ConstructMemberList() + { + // TEMPORARY + + var scrollobj = UIFactory.CreateScrollView(Content, out GameObject scrollContent, out SliderScrollbar scroller, new Color(0.1f, 0.1f, 0.1f)); + + foreach (var member in this.m_allMembers) + { + var rowObj = UIFactory.CreateHorizontalGroup(scrollContent, new Color(1, 1, 1, 0)); + var rowGroup = rowObj.GetComponent(); + rowGroup.childForceExpandWidth = true; + rowGroup.childControlWidth = true; + var rowLayout = rowObj.AddComponent(); + rowLayout.minHeight = 25; + rowLayout.flexibleHeight = 0; + rowLayout.minWidth = 125; + rowLayout.flexibleWidth = 9000; + + var labelObj = UIFactory.CreateLabel(rowObj, TextAnchor.MiddleLeft); + + var label = labelObj.GetComponent(); + label.text = member.RichTextName; + + } + } + + #endregion } } diff --git a/src/Inspectors/ReflectionInspector/CacheObject/CacheFactory.cs b/src/Inspectors/ReflectionInspector/CacheObject/CacheFactory.cs deleted file mode 100644 index 16564b7..0000000 --- a/src/Inspectors/ReflectionInspector/CacheObject/CacheFactory.cs +++ /dev/null @@ -1,76 +0,0 @@ -//using System; -//using System.Reflection; -//using UnityExplorer.CacheObject; -//using UnityEngine; -//using UnityExplorer.Helpers; - -//namespace Explorer -//{ -// public static class CacheFactory -// { -// public static CacheObjectBase GetCacheObject(object obj) -// { -// if (obj == null) return null; - -// return GetCacheObject(obj, ReflectionHelpers.GetActualType(obj)); -// } - -// public static CacheObjectBase GetCacheObject(object obj, Type type) -// { -// var ret = new CacheObjectBase(); -// ret.Init(obj, type); -// return ret; -// } - -// public static CacheMember GetCacheObject(MemberInfo member, object declaringInstance) -// { -// CacheMember ret; - -// if (member is MethodInfo mi && CanProcessArgs(mi.GetParameters())) -// { -// ret = new CacheMethod(); -// ret.InitMember(mi, declaringInstance); -// } -// else if (member is PropertyInfo pi && CanProcessArgs(pi.GetIndexParameters())) -// { -// ret = new CacheProperty(); -// ret.InitMember(pi, declaringInstance); -// } -// else if (member is FieldInfo fi) -// { -// ret = new CacheField(); -// ret.InitMember(fi, declaringInstance); -// } -// else -// { -// return null; -// } - -// return ret; -// } - -// public static bool CanProcessArgs(ParameterInfo[] parameters) -// { -// foreach (var param in parameters) -// { -// var pType = param.ParameterType; - -// if (pType.IsByRef && pType.HasElementType) -// { -// pType = pType.GetElementType(); -// } - -// if (pType.IsPrimitive || pType == typeof(string)) -// { -// continue; -// } -// else -// { -// return false; -// } -// } - -// return true; -// } -// } -//} diff --git a/src/Inspectors/ReflectionInspector/CacheObject/CacheField.cs b/src/Inspectors/ReflectionInspector/CacheObject/CacheField.cs deleted file mode 100644 index 68d4809..0000000 --- a/src/Inspectors/ReflectionInspector/CacheObject/CacheField.cs +++ /dev/null @@ -1,54 +0,0 @@ -//using System; -//using System.Collections.Generic; -//using System.Linq; -//using System.Text; -//using System.Reflection; -//using UnityExplorer.UI; -//using UnityExplorer.Helpers; - -//namespace UnityExplorer.CacheObject -//{ -// public class CacheField : CacheMember -// { -// public override bool IsStatic => (MemInfo as FieldInfo).IsStatic; - -// public override void InitMember(MemberInfo member, object declaringInstance) -// { -// base.InitMember(member, declaringInstance); - -// base.Init(null, (member as FieldInfo).FieldType); - -// UpdateValue(); -// } - -// public override void UpdateValue() -// { -// if (IValue is InteractiveDictionary iDict) -// { -// if (!iDict.EnsureDictionaryIsSupported()) -// { -// ReflectionException = "Not supported due to TypeInitializationException"; -// return; -// } -// } - -// try -// { -// var fi = MemInfo as FieldInfo; -// IValue.Value = fi.GetValue(fi.IsStatic ? null : DeclaringInstance); - -// base.UpdateValue(); -// } -// catch (Exception e) -// { -// ReflectionException = ReflectionHelpers.ExceptionToString(e); -// } -// } - -// public override void SetValue() -// { -// var fi = MemInfo as FieldInfo; -// fi.SetValue(fi.IsStatic ? null : DeclaringInstance, IValue.Value); -// } -// } -//} diff --git a/src/Inspectors/ReflectionInspector/CacheObject/CacheMember.cs b/src/Inspectors/ReflectionInspector/CacheObject/CacheMember.cs deleted file mode 100644 index ef8e0a4..0000000 --- a/src/Inspectors/ReflectionInspector/CacheObject/CacheMember.cs +++ /dev/null @@ -1,226 +0,0 @@ -//using System; -//using System.Collections.Generic; -//using System.Linq; -//using System.Reflection; -//using UnityEngine; -//using UnityExplorer.UI; -//using UnityExplorer.UI.Shared; - -//namespace UnityExplorer.CacheObject -//{ -// public class CacheMember : CacheObjectBase -// { -// public MemberInfo MemInfo { get; set; } -// public Type DeclaringType { get; set; } -// public object DeclaringInstance { get; set; } - -// public virtual bool IsStatic { get; private set; } - -// public override bool HasParameters => m_arguments != null && m_arguments.Length > 0; -// public override bool IsMember => true; - -// public string RichTextName => m_richTextName ?? GetRichTextName(); -// private string m_richTextName; - -// public override bool CanWrite => m_canWrite ?? GetCanWrite(); -// private bool? m_canWrite; - -// public string ReflectionException { get; set; } - -// public bool m_evaluated = false; -// public bool m_isEvaluating; -// public ParameterInfo[] m_arguments = new ParameterInfo[0]; -// public string[] m_argumentInput = new string[0]; - -// public virtual void InitMember(MemberInfo member, object declaringInstance) -// { -// MemInfo = member; -// DeclaringInstance = declaringInstance; -// DeclaringType = member.DeclaringType; -// } - -// public override void UpdateValue() -// { -// base.UpdateValue(); -// } - -// public override void SetValue() -// { -// // ... -// } - -// public object[] ParseArguments() -// { -// if (m_arguments.Length < 1) -// { -// return new object[0]; -// } - -// var parsedArgs = new List(); -// for (int i = 0; i < m_arguments.Length; i++) -// { -// var input = m_argumentInput[i]; -// var type = m_arguments[i].ParameterType; - -// if (type.IsByRef) -// { -// type = type.GetElementType(); -// } - -// if (!string.IsNullOrEmpty(input)) -// { -// if (type == typeof(string)) -// { -// parsedArgs.Add(input); -// continue; -// } -// else -// { -// try -// { -// var arg = type.GetMethod("Parse", new Type[] { typeof(string) }) -// .Invoke(null, new object[] { input }); - -// parsedArgs.Add(arg); -// continue; -// } -// catch -// { -// ExplorerCore.Log($"Argument #{i} '{m_arguments[i].Name}' ({type.Name}), could not parse input '{input}'."); -// } -// } -// } - -// // No input, see if there is a default value. -// if (HasDefaultValue(m_arguments[i])) -// { -// parsedArgs.Add(m_arguments[i].DefaultValue); -// continue; -// } - -// // Try add a null arg I guess -// parsedArgs.Add(null); -// } - -// return parsedArgs.ToArray(); -// } - -// public static bool HasDefaultValue(ParameterInfo arg) => arg.DefaultValue != DBNull.Value; - -// public void DrawArgsInput() -// { -// GUILayout.Label($"Arguments:", new GUILayoutOption[0]); -// for (int i = 0; i < this.m_arguments.Length; i++) -// { -// var name = this.m_arguments[i].Name; -// var input = this.m_argumentInput[i]; -// var type = this.m_arguments[i].ParameterType.Name; - -// var label = $"{type} "; -// label += $"{name}"; -// if (HasDefaultValue(this.m_arguments[i])) -// { -// label = $"[{label} = {this.m_arguments[i].DefaultValue ?? "null"}]"; -// } - -// GUIHelper.BeginHorizontal(new GUILayoutOption[0]); - -// GUI.skin.label.alignment = TextAnchor.MiddleCenter; - -// GUILayout.Label(i.ToString(), new GUILayoutOption[] { GUILayout.Width(15) }); -// GUILayout.Label(label, new GUILayoutOption[] { GUILayout.ExpandWidth(false) }); -// this.m_argumentInput[i] = GUIHelper.TextField(input, new GUILayoutOption[] { GUILayout.ExpandWidth(true) }); - -// GUI.skin.label.alignment = TextAnchor.MiddleLeft; - -// GUILayout.EndHorizontal(); -// } -// } - -// private bool GetCanWrite() -// { -// if (MemInfo is FieldInfo fi) -// m_canWrite = !(fi.IsLiteral && !fi.IsInitOnly); -// else if (MemInfo is PropertyInfo pi) -// m_canWrite = pi.CanWrite; -// else -// m_canWrite = false; - -// return (bool)m_canWrite; -// } - -// private string GetRichTextName() -// { -// string memberColor = ""; -// bool isStatic = false; - -// if (MemInfo is FieldInfo fi) -// { -// if (fi.IsStatic) -// { -// isStatic = true; -// memberColor = Syntax.Field_Static; -// } -// else -// memberColor = Syntax.Field_Instance; -// } -// else if (MemInfo is MethodInfo mi) -// { -// if (mi.IsStatic) -// { -// isStatic = true; -// memberColor = Syntax.Method_Static; -// } -// else -// memberColor = Syntax.Method_Instance; -// } -// else if (MemInfo is PropertyInfo pi) -// { -// if (pi.GetAccessors()[0].IsStatic) -// { -// isStatic = true; -// memberColor = Syntax.Prop_Static; -// } -// else -// memberColor = Syntax.Prop_Instance; -// } - -// string classColor; -// if (MemInfo.DeclaringType.IsValueType) -// { -// classColor = Syntax.StructGreen; -// } -// else if (MemInfo.DeclaringType.IsAbstract && MemInfo.DeclaringType.IsSealed) -// { -// classColor = Syntax.Class_Static; -// } -// else -// { -// classColor = Syntax.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; -// } -// } -//} diff --git a/src/Inspectors/ReflectionInspector/CacheObject/CacheMethod.cs b/src/Inspectors/ReflectionInspector/CacheObject/CacheMethod.cs deleted file mode 100644 index a2b08be..0000000 --- a/src/Inspectors/ReflectionInspector/CacheObject/CacheMethod.cs +++ /dev/null @@ -1,200 +0,0 @@ -//using System; -//using System.Collections.Generic; -//using System.Linq; -//using System.Reflection; -//using UnityEngine; -//using UnityExplorer.UI.Shared; -//using UnityExplorer.Helpers; - -//namespace UnityExplorer.CacheObject -//{ -// public class CacheMethod : CacheMember -// { -// private CacheObjectBase m_cachedReturnValue; - -// public override bool HasParameters => base.HasParameters || GenericArgs.Length > 0; - -// public override bool IsStatic => (MemInfo as MethodInfo).IsStatic; - -// public Type[] GenericArgs { get; private set; } -// public Type[][] GenericConstraints { get; private set; } - -// public string[] GenericArgInput = new string[0]; - -// public override void InitMember(MemberInfo member, object declaringInstance) -// { -// base.InitMember(member, declaringInstance); - -// var mi = MemInfo as MethodInfo; -// GenericArgs = mi.GetGenericArguments(); - -// GenericConstraints = GenericArgs.Select(x => x.GetGenericParameterConstraints()) -// .ToArray(); - -// GenericArgInput = new string[GenericArgs.Length]; - -// m_arguments = mi.GetParameters(); -// m_argumentInput = new string[m_arguments.Length]; - -// base.Init(null, mi.ReturnType); -// } - -// public override void UpdateValue() -// { -// // CacheMethod cannot UpdateValue directly. Need to Evaluate. -// } - -// public void Evaluate() -// { -// MethodInfo mi; -// if (GenericArgs.Length > 0) -// { -// mi = MakeGenericMethodFromInput(); -// if (mi == null) return; -// } -// else -// { -// mi = MemInfo as MethodInfo; -// } - -// object ret = null; - -// try -// { -// ret = mi.Invoke(mi.IsStatic ? null : DeclaringInstance, ParseArguments()); -// m_evaluated = true; -// m_isEvaluating = false; -// } -// catch (Exception e) -// { -// ExplorerCore.LogWarning($"Exception evaluating: {e.GetType()}, {e.Message}"); -// ReflectionException = ReflectionHelpers.ExceptionToString(e); -// } - -// if (ret != null) -// { -// //m_cachedReturnValue = CacheFactory.GetTypeAndCacheObject(ret); -// m_cachedReturnValue = CacheFactory.GetCacheObject(ret); -// m_cachedReturnValue.UpdateValue(); -// } -// else -// { -// m_cachedReturnValue = null; -// } -// } - -// private MethodInfo MakeGenericMethodFromInput() -// { -// var mi = MemInfo as MethodInfo; - -// var list = new List(); -// for (int i = 0; i < GenericArgs.Length; i++) -// { -// var input = GenericArgInput[i]; -// if (ReflectionHelpers.GetTypeByName(input) is Type t) -// { -// if (GenericConstraints[i].Length == 0) -// { -// list.Add(t); -// } -// else -// { -// foreach (var constraint in GenericConstraints[i].Where(x => x != null)) -// { -// if (!constraint.IsAssignableFrom(t)) -// { -// ExplorerCore.LogWarning($"Generic argument #{i}, '{input}' is not assignable from the constraint '{constraint}'!"); -// return null; -// } -// } - -// list.Add(t); -// } -// } -// 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."); -// return null; -// } -// } - -// // make into a generic with type list -// mi = mi.MakeGenericMethod(list.ToArray()); - -// return mi; -// } - -// // ==== GUI DRAW ==== - -// //public override void Draw(Rect window, float width) -// //{ -// // base.Draw(window, width); -// //} - -// public void DrawValue(Rect window, float width) -// { -// string typeLabel = $"{IValue.ValueType.FullName}"; - -// if (m_evaluated) -// { -// if (m_cachedReturnValue != null) -// { -// m_cachedReturnValue.IValue.DrawValue(window, width); -// } -// else -// { -// GUILayout.Label($"null ({typeLabel})", new GUILayoutOption[0]); -// } -// } -// else -// { -// GUILayout.Label($"Not yet evaluated ({typeLabel})", new GUILayoutOption[0]); -// } -// } - -// public void DrawGenericArgsInput() -// { -// GUILayout.Label($"Generic Arguments:", new GUILayoutOption[0]); - -// for (int i = 0; i < this.GenericArgs.Length; i++) -// { -// string types = ""; -// if (this.GenericConstraints[i].Length > 0) -// { -// foreach (var constraint in this.GenericConstraints[i]) -// { -// if (types != "") types += ", "; - -// string type; - -// if (constraint == null) -// type = "Any"; -// else -// type = constraint.ToString(); - -// types += $"{type}"; -// } -// } -// else -// { -// types = $"Any"; -// } -// var input = this.GenericArgInput[i]; - -// GUIHelper.BeginHorizontal(new GUILayoutOption[0]); - -// GUI.skin.label.alignment = TextAnchor.MiddleCenter; -// GUILayout.Label( -// $"{this.GenericArgs[i].Name}", -// new GUILayoutOption[] { GUILayout.Width(15) } -// ); -// this.GenericArgInput[i] = GUIHelper.TextField(input, new GUILayoutOption[] { GUILayout.Width(150) }); -// GUI.skin.label.alignment = TextAnchor.MiddleLeft; -// GUILayout.Label(types, new GUILayoutOption[0]); - -// GUILayout.EndHorizontal(); -// } -// } -// } -//} diff --git a/src/Inspectors/ReflectionInspector/CacheObject/CacheObjectBase.cs b/src/Inspectors/ReflectionInspector/CacheObject/CacheObjectBase.cs deleted file mode 100644 index acedf1a..0000000 --- a/src/Inspectors/ReflectionInspector/CacheObject/CacheObjectBase.cs +++ /dev/null @@ -1,117 +0,0 @@ -//using System; -//using System.Collections.Generic; -//using System.Linq; -//using System.Reflection; -//using UnityEngine; -//using UnityExplorer.UI; -//using UnityExplorer.UI.Shared; -//using UnityExplorer.Helpers; - -//namespace UnityExplorer.CacheObject -//{ -// public class CacheObjectBase -// { -// public InteractiveValue IValue; - -// public virtual bool CanWrite => false; -// public virtual bool HasParameters => false; -// public virtual bool IsMember => false; - -// public bool IsStaticClassSearchResult { get; set; } - -// public virtual void Init(object obj, Type valueType) -// { -// if (valueType == null && obj == null) -// { -// return; -// } - -// //ExplorerCore.Log("Initializing InteractiveValue of type " + valueType.FullName); - -// InteractiveValue interactive; - -// if (valueType == typeof(GameObject) || valueType == typeof(Transform)) -// { -// interactive = new InteractiveGameObject(); -// } -// else if (valueType == typeof(Texture2D)) -// { -// interactive = new InteractiveTexture2D(); -// } -// else if (valueType == typeof(Texture)) -// { -// interactive = new InteractiveTexture(); -// } -// else if (valueType == typeof(Sprite)) -// { -// interactive = new InteractiveSprite(); -// } -// else if (valueType.IsPrimitive || valueType == typeof(string)) -// { -// interactive = new InteractivePrimitive(); -// } -// else if (valueType.IsEnum) -// { -// if (valueType.GetCustomAttributes(typeof(FlagsAttribute), true) is object[] attributes && attributes.Length > 0) -// { -// interactive = new InteractiveFlags(); -// } -// else -// { -// interactive = new InteractiveEnum(); -// } -// } -// else if (valueType == typeof(Vector2) || valueType == typeof(Vector3) || valueType == typeof(Vector4)) -// { -// interactive = new InteractiveVector(); -// } -// else if (valueType == typeof(Quaternion)) -// { -// interactive = new InteractiveQuaternion(); -// } -// else if (valueType == typeof(Color)) -// { -// interactive = new InteractiveColor(); -// } -// else if (valueType == typeof(Rect)) -// { -// interactive = new InteractiveRect(); -// } -// // must check this before IsEnumerable -// else if (ReflectionHelpers.IsDictionary(valueType)) -// { -// interactive = new InteractiveDictionary(); -// } -// else if (ReflectionHelpers.IsEnumerable(valueType)) -// { -// interactive = new InteractiveEnumerable(); -// } -// else -// { -// interactive = new InteractiveValue(); -// } - -// interactive.Value = obj; -// interactive.ValueType = valueType; - -// this.IValue = interactive; -// this.IValue.OwnerCacheObject = this; - -// UpdateValue(); - -// this.IValue.Init(); -// } - -// public virtual void Draw(Rect window, float width) -// { -// IValue.Draw(window, width); -// } - -// public virtual void UpdateValue() -// { -// IValue.UpdateValue(); -// } - -// public virtual void SetValue() => throw new NotImplementedException(); -// } -//} diff --git a/src/Inspectors/ReflectionInspector/CacheObject/CacheProperty.cs b/src/Inspectors/ReflectionInspector/CacheObject/CacheProperty.cs deleted file mode 100644 index 8f0b9c9..0000000 --- a/src/Inspectors/ReflectionInspector/CacheObject/CacheProperty.cs +++ /dev/null @@ -1,84 +0,0 @@ -//using System; -//using System.Collections.Generic; -//using System.Linq; -//using System.Text; -//using System.Reflection; -//using UnityExplorer.UI; -//using UnityExplorer.Helpers; - -//namespace UnityExplorer.CacheObject -//{ -// public class CacheProperty : CacheMember -// { -// public override bool IsStatic => (MemInfo as PropertyInfo).GetAccessors()[0].IsStatic; - -// public override void InitMember(MemberInfo member, object declaringInstance) -// { -// base.InitMember(member, declaringInstance); - -// var pi = member as PropertyInfo; - -// this.m_arguments = pi.GetIndexParameters(); -// this.m_argumentInput = new string[m_arguments.Length]; - -// base.Init(null, pi.PropertyType); - -// UpdateValue(); -// } - -// public override void UpdateValue() -// { -// if (HasParameters && !m_isEvaluating) -// { -// // Need to enter parameters first. -// return; -// } - -// if (IValue is InteractiveDictionary iDict) -// { -// if (!iDict.EnsureDictionaryIsSupported()) -// { -// ReflectionException = "Not supported due to TypeInitializationException"; -// return; -// } -// } - -// try -// { -// var pi = MemInfo as PropertyInfo; - -// if (pi.CanRead) -// { -// var target = pi.GetAccessors()[0].IsStatic ? null : DeclaringInstance; - -// IValue.Value = pi.GetValue(target, ParseArguments()); - -// base.UpdateValue(); -// } -// else // create a dummy value for Write-Only properties. -// { -// if (IValue.ValueType == typeof(string)) -// { -// IValue.Value = ""; -// } -// else -// { -// IValue.Value = Activator.CreateInstance(IValue.ValueType); -// } -// } -// } -// catch (Exception e) -// { -// ReflectionException = ReflectionHelpers.ExceptionToString(e); -// } -// } - -// public override void SetValue() -// { -// var pi = MemInfo as PropertyInfo; -// var target = pi.GetAccessors()[0].IsStatic ? null : DeclaringInstance; - -// pi.SetValue(target, IValue.Value, ParseArguments()); -// } -// } -//} diff --git a/src/UI/InteractiveValue/InteractiveValue.cs b/src/UI/InteractiveValue/InteractiveValue.cs deleted file mode 100644 index ff8a818..0000000 --- a/src/UI/InteractiveValue/InteractiveValue.cs +++ /dev/null @@ -1,108 +0,0 @@ -//using System; -//using System.Collections.Generic; -//using System.Linq; -//using System.Reflection; -//using UnityEngine; -//using UnityExplorer.CacheObject; -//using UnityExplorer.Helpers; -//using UnityExplorer.UI.Shared; - -//namespace UnityExplorer.UI.InteractiveValue -//{ -// public class InteractiveValue -// { -// //public const float MAX_LABEL_WIDTH = 400f; -// //public const string EVALUATE_LABEL = "Evaluate"; - -// public CacheObjectBase OwnerCacheObject; - -// public object Value { get; set; } -// public Type ValueType; - -// public string ButtonLabel => m_btnLabel ?? GetButtonLabel(); -// private string m_btnLabel; - -// public MethodInfo ToStringMethod => m_toStringMethod ?? GetToStringMethod(); -// private MethodInfo m_toStringMethod; - -// public virtual void Init() -// { -// UpdateValue(); -// } - -// public virtual void UpdateValue() -// { -// GetButtonLabel(); -// } - - - -// private MethodInfo GetToStringMethod() -// { -// try -// { -// m_toStringMethod = ReflectionHelpers.GetActualType(Value).GetMethod("ToString", new Type[0]) -// ?? typeof(object).GetMethod("ToString", new Type[0]); - -// // test invoke -// m_toStringMethod.Invoke(Value, null); -// } -// catch -// { -// m_toStringMethod = typeof(object).GetMethod("ToString", new Type[0]); -// } -// return m_toStringMethod; -// } - -// public string GetButtonLabel() -// { -// if (Value == null) return null; - -// var valueType = ReflectionHelpers.GetActualType(Value); - -// string label; - -// 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} (UnityEngine.TextAsset)"; -// } -// else -// { -// label = (string)ToStringMethod?.Invoke(Value, null) ?? Value.ToString(); - -// var classColor = valueType.IsAbstract && valueType.IsSealed -// ? Syntax.Class_Static -// : Syntax.Class_Instance; - -// string typeLabel = $"{valueType.FullName}"; - -// if (Value is UnityEngine.Object) -// { -// label = label.Replace($"({valueType.FullName})", $"({typeLabel})"); -// } -// else -// { -// if (!label.Contains(valueType.FullName)) -// { -// label += $" ({typeLabel})"; -// } -// else -// { -// label = label.Replace(valueType.FullName, typeLabel); -// } -// } -// } - -// return m_btnLabel = label; -// } -// } -//} diff --git a/src/UnityExplorer.csproj b/src/UnityExplorer.csproj index f6f12d6..417c797 100644 --- a/src/UnityExplorer.csproj +++ b/src/UnityExplorer.csproj @@ -324,13 +324,13 @@ - - - - - - - + + + + + + + @@ -338,9 +338,9 @@ - - - + + + @@ -369,13 +369,13 @@ - - + + - +