This commit is contained in:
sinaioutlander
2020-11-05 17:33:04 +11:00
parent a46bc11e42
commit e175e9c438
47 changed files with 890 additions and 336 deletions

View File

@ -0,0 +1,26 @@
//using System;
//using System.Collections;
//using System.Collections.Generic;
//using System.Linq;
//using System.Text;
//using UnityExplorer.UI;
//namespace UnityExplorer.CacheObject
//{
// public class CacheEnumerated : CacheObjectBase
// {
// public int Index { get; set; }
// public IList RefIList { get; set; }
// public InteractiveEnumerable ParentEnumeration { get; set; }
// public override bool CanWrite => RefIList != null && ParentEnumeration.OwnerCacheObject.CanWrite;
// public override void SetValue()
// {
// RefIList[Index] = IValue.Value;
// ParentEnumeration.Value = RefIList;
// ParentEnumeration.OwnerCacheObject.SetValue();
// }
// }
//}

View File

@ -0,0 +1,76 @@
//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;
// }
// }
//}

View File

@ -0,0 +1,54 @@
//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);
// }
// }
//}

View File

@ -0,0 +1,226 @@
//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<object>();
// 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($"<b><color=orange>Arguments:</color></b>", 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 = $"<color={Syntax.Class_Instance}>{type}</color> ";
// label += $"<color={Syntax.Local}>{name}</color>";
// if (HasDefaultValue(this.m_arguments[i]))
// {
// label = $"<i>[{label} = {this.m_arguments[i].DefaultValue ?? "null"}]</i>";
// }
// 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 = $"<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={Syntax.StructGreen}>{cm.GenericArgs[i].Name}</color>";
// }
// m_richTextName += args;
// m_richTextName += ">";
// }
// return m_richTextName;
// }
// }
//}

View File

@ -0,0 +1,200 @@
//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<Type>();
// 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 = $"<color={Syntax.Class_Instance}>{IValue.ValueType.FullName}</color>";
// if (m_evaluated)
// {
// if (m_cachedReturnValue != null)
// {
// m_cachedReturnValue.IValue.DrawValue(window, width);
// }
// else
// {
// GUILayout.Label($"null ({typeLabel})", new GUILayoutOption[0]);
// }
// }
// else
// {
// GUILayout.Label($"<color=grey><i>Not yet evaluated</i></color> ({typeLabel})", new GUILayoutOption[0]);
// }
// }
// public void DrawGenericArgsInput()
// {
// GUILayout.Label($"<b><color=orange>Generic Arguments:</color></b>", 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 += $"<color={Syntax.Class_Instance}>{type}</color>";
// }
// }
// else
// {
// types = $"<color={Syntax.Class_Instance}>Any</color>";
// }
// var input = this.GenericArgInput[i];
// GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
// GUI.skin.label.alignment = TextAnchor.MiddleCenter;
// GUILayout.Label(
// $"<color={Syntax.StructGreen}>{this.GenericArgs[i].Name}</color>",
// 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();
// }
// }
// }
//}

View File

@ -0,0 +1,117 @@
//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();
// }
//}

View File

@ -0,0 +1,84 @@
//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());
// }
// }
//}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,170 @@
using System;
using UnityEngine;
using UnityEngine.UI;
using UnityExplorer.UI;
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 abstract GameObject Content { get; set; }
public Button tabButton;
public Text tabText;
internal bool m_pendingDestroy;
public InspectorBase(object target)
{
Target = target;
UnityTarget = target as UnityEngine.Object;
if (ObjectNullOrDestroyed(Target, UnityTarget))
{
Destroy();
return;
}
AddInspectorTab();
}
public virtual void SetContentActive()
{
Content?.SetActive(true);
}
public virtual void SetContentInactive()
{
Content?.SetActive(false);
}
public virtual void Update()
{
if (ObjectNullOrDestroyed(Target, UnityTarget))
{
Destroy();
return;
}
tabText.text = TabLabel;
}
public virtual void Destroy()
{
m_pendingDestroy = true;
GameObject tabGroup = tabButton?.transform.parent.gameObject;
if (tabGroup)
{
GameObject.Destroy(tabGroup);
}
//if (Content)
//{
// GameObject.Destroy(Content);
//}
int thisIndex = -1;
if (InspectorManager.Instance.m_currentInspectors.Contains(this))
{
thisIndex = InspectorManager.Instance.m_currentInspectors.IndexOf(this);
InspectorManager.Instance.m_currentInspectors.Remove(this);
}
if (ReferenceEquals(InspectorManager.Instance.m_activeInspector, this))
{
InspectorManager.Instance.UnsetInspectorTab();
if (InspectorManager.Instance.m_currentInspectors.Count > 0)
{
var prevTab = InspectorManager.Instance.m_currentInspectors[thisIndex > 0 ? thisIndex - 1 : 0];
InspectorManager.Instance.SetInspectorTab(prevTab);
}
}
}
public static bool ObjectNullOrDestroyed(object obj, UnityEngine.Object unityObj, bool suppressWarning = false)
{
if (obj == null)
{
if (!suppressWarning)
{
ExplorerCore.LogWarning("The target instance is null!");
}
return true;
}
else if (obj is UnityEngine.Object)
{
if (!unityObj)
{
if (!suppressWarning)
{
ExplorerCore.LogWarning("The target UnityEngine.Object was destroyed!");
}
return true;
}
}
return false;
}
#region UI CONSTRUCTION
public void AddInspectorTab()
{
var tabContent = InspectorManager.Instance.m_tabBarContent;
var tabGroupObj = UIFactory.CreateHorizontalGroup(tabContent);
var tabGroup = tabGroupObj.GetComponent<HorizontalLayoutGroup>();
tabGroup.childForceExpandWidth = true;
tabGroup.childControlWidth = true;
var tabLayout = tabGroupObj.AddComponent<LayoutElement>();
tabLayout.minWidth = 185;
tabLayout.flexibleWidth = 0;
tabGroupObj.AddComponent<Mask>();
var targetButtonObj = UIFactory.CreateButton(tabGroupObj);
var targetButtonLayout = targetButtonObj.AddComponent<LayoutElement>();
targetButtonLayout.minWidth = 165;
targetButtonLayout.flexibleWidth = 0;
tabText = targetButtonObj.GetComponentInChildren<Text>();
tabText.horizontalOverflow = HorizontalWrapMode.Overflow;
tabText.alignment = TextAnchor.MiddleLeft;
tabButton = targetButtonObj.GetComponent<Button>();
#if CPP
tabButton.onClick.AddListener(new Action(() => { InspectorManager.Instance.SetInspectorTab(this); }));
#else
tabButton.onClick.AddListener(() => { InspectorManager.Instance.SetInspectorTab(this); });
#endif
var closeBtnObj = UIFactory.CreateButton(tabGroupObj);
var closeBtnLayout = closeBtnObj.AddComponent<LayoutElement>();
closeBtnLayout.minWidth = 20;
closeBtnLayout.flexibleWidth = 0;
var closeBtnText = closeBtnObj.GetComponentInChildren<Text>();
closeBtnText.text = "X";
closeBtnText.color = new Color(1, 0, 0, 1);
var closeBtn = closeBtnObj.GetComponent<Button>();
#if CPP
closeBtn.onClick.AddListener(new Action(() => { Destroy(); }));
#else
closeBtn.onClick.AddListener(() => { Destroy(); });
#endif
var closeColors = closeBtn.colors;
closeColors.normalColor = new Color(0.2f, 0.2f, 0.2f, 1);
closeBtn.colors = closeColors;
}
#endregion
}
}

View File

@ -0,0 +1,184 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityExplorer.Helpers;
using UnityExplorer.UI;
using UnityExplorer.UI.PageModel;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
namespace UnityExplorer.Inspectors
{
public class InspectorManager
{
public static InspectorManager Instance { get; private set; }
public InspectorManager()
{
Instance = this;
ConstructInspectorPane();
}
public InspectorBase m_activeInspector;
public readonly List<InspectorBase> m_currentInspectors = new List<InspectorBase>();
public GameObject m_tabBarContent;
public GameObject m_inspectorContent;
public void Update()
{
for (int i = 0; i < m_currentInspectors.Count; i++)
{
if (i >= m_currentInspectors.Count)
break;
m_currentInspectors[i].Update();
}
}
public void Inspect(object obj)
{
#if CPP
obj = obj.Il2CppCast(ReflectionHelpers.GetActualType(obj));
#endif
UnityEngine.Object unityObj = obj as UnityEngine.Object;
if (InspectorBase.ObjectNullOrDestroyed(obj, unityObj))
{
return;
}
MainMenu.Instance.SetPage(HomePage.Instance);
// check if currently inspecting this object
foreach (InspectorBase tab in m_currentInspectors)
{
if (ReferenceEquals(obj, tab.Target))
{
SetInspectorTab(tab);
return;
}
#if CPP
else if (unityObj && tab.Target is UnityEngine.Object uTabObj)
{
if (unityObj.m_CachedPtr == uTabObj.m_CachedPtr)
{
SetInspectorTab(tab);
return;
}
}
#endif
}
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
}
public void SetInspectorTab(InspectorBase inspector)
{
UnsetInspectorTab();
m_activeInspector = inspector;
inspector.SetContentActive();
Color activeColor = new Color(0, 0.25f, 0, 1);
ColorBlock colors = inspector.tabButton.colors;
colors.normalColor = activeColor;
colors.highlightedColor = activeColor;
inspector.tabButton.colors = colors;
}
public void UnsetInspectorTab()
{
if (m_activeInspector == null)
{
return;
}
m_activeInspector.SetContentInactive();
ColorBlock colors = m_activeInspector.tabButton.colors;
colors.normalColor = new Color(0.2f, 0.2f, 0.2f, 1);
colors.highlightedColor = new Color(0.1f, 0.3f, 0.1f, 1);
m_activeInspector.tabButton.colors = colors;
m_activeInspector = null;
}
#region INSPECTOR PANE
public void ConstructInspectorPane()
{
var mainObj = UIFactory.CreateVerticalGroup(HomePage.Instance.Content, new Color(72f / 255f, 72f / 255f, 72f / 255f));
LayoutElement rightLayout = mainObj.AddComponent<LayoutElement>();
rightLayout.flexibleWidth = 999999;
var rightGroup = mainObj.GetComponent<VerticalLayoutGroup>();
rightGroup.childForceExpandHeight = true;
rightGroup.childForceExpandWidth = true;
rightGroup.childControlHeight = true;
rightGroup.childControlWidth = true;
rightGroup.spacing = 10;
rightGroup.padding.left = 8;
rightGroup.padding.right = 8;
rightGroup.padding.top = 8;
rightGroup.padding.bottom = 8;
var inspectorTitle = UIFactory.CreateLabel(mainObj, TextAnchor.UpperLeft);
Text title = inspectorTitle.GetComponent<Text>();
title.text = "Inspector";
title.fontSize = 20;
var titleLayout = inspectorTitle.AddComponent<LayoutElement>();
titleLayout.minHeight = 30;
titleLayout.flexibleHeight = 0;
m_tabBarContent = UIFactory.CreateGridGroup(mainObj, new Vector2(185, 20), new Vector2(5, 2), new Color(0.1f, 0.1f, 0.1f, 1));
var gridGroup = m_tabBarContent.GetComponent<GridLayoutGroup>();
gridGroup.padding.top = 4;
gridGroup.padding.left = 4;
gridGroup.padding.right = 4;
gridGroup.padding.bottom = 4;
// inspector content area
m_inspectorContent = UIFactory.CreateVerticalGroup(mainObj, new Color(0.1f, 0.1f, 0.1f, 1.0f));
var contentGroup = m_inspectorContent.GetComponent<VerticalLayoutGroup>();
contentGroup.childForceExpandHeight = true;
contentGroup.childForceExpandWidth = true;
contentGroup.childControlHeight = true;
contentGroup.childControlWidth = true;
contentGroup.spacing = 5;
contentGroup.padding.top = 5;
contentGroup.padding.left = 5;
contentGroup.padding.right = 5;
contentGroup.padding.bottom = 5;
var contentLayout = m_inspectorContent.AddComponent<LayoutElement>();
contentLayout.preferredHeight = 900;
contentLayout.flexibleHeight = 10000;
}
#endregion
}
}

View File

@ -0,0 +1,28 @@
using System;
using UnityExplorer.Helpers;
namespace UnityExplorer.Inspectors
{
public class InstanceInspector : ReflectionInspector
{
// todo
public override string TabLabel => $" [R] {base.TabLabel}";
public InstanceInspector(object target) : base(target)
{
}
public override void Update()
{
base.Update();
if (m_pendingDestroy || InspectorManager.Instance.m_activeInspector != this)
{
return;
}
// todo
}
}
}

View File

@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityExplorer.Helpers;
using UnityEngine;
namespace UnityExplorer.Inspectors
{
public class ReflectionInspector : InspectorBase
{
public override string TabLabel => m_targetTypeShortName;
private GameObject m_content;
public override GameObject Content
{
get => m_content;
set => m_content = value;
}
private readonly string m_targetTypeShortName;
public ReflectionInspector(object target) : base(target)
{
Type type = ReflectionHelpers.GetActualType(target);
if (type == null)
{
// TODO
return;
}
m_targetTypeShortName = type.Name;
}
}
}

View File

@ -0,0 +1,488 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityExplorer.UI;
using UnityExplorer.UI.PageModel;
using UnityExplorer.UI.Shared;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using UnityExplorer.Unstrip.Scenes;
namespace UnityExplorer.Inspectors
{
public class SceneExplorer
{
public static SceneExplorer Instance;
public SceneExplorer()
{
Instance = this;
ConstructScenePane();
}
private const float UPDATE_INTERVAL = 1f;
private float m_timeOfLastSceneUpdate;
private GameObject m_selectedSceneObject;
private int m_currentSceneHandle = -1;
private int m_lastCount;
private Dropdown m_sceneDropdown;
private Text m_scenePathText;
private GameObject m_mainInspectBtn;
private GameObject m_backButtonObj;
public PageHandler m_sceneListPageHandler;
private GameObject[] m_allSceneListObjects = new GameObject[0];
private readonly List<GameObject> m_sceneShortList = new List<GameObject>();
private GameObject m_sceneListContent;
private readonly List<Text> m_sceneListTexts = new List<Text>();
public static int DontDestroyHandle => DontDestroyObject.scene.handle;
internal static GameObject DontDestroyObject
{
get
{
if (!m_dontDestroyObject)
{
m_dontDestroyObject = new GameObject("DontDestroyMe");
GameObject.DontDestroyOnLoad(m_dontDestroyObject);
}
return m_dontDestroyObject;
}
}
internal static GameObject m_dontDestroyObject;
public void Init()
{
RefreshActiveScenes();
}
public void Update()
{
if (Time.realtimeSinceStartup - m_timeOfLastSceneUpdate < UPDATE_INTERVAL)
{
return;
}
RefreshActiveScenes();
if (!m_selectedSceneObject)
{
if (m_currentSceneHandle != -1)
{
SetSceneObjectList(SceneUnstrip.GetRootGameObjects(m_currentSceneHandle));
}
}
else
{
RefreshSelectedSceneObject();
}
}
public int GetSceneHandle(string sceneName)
{
if (sceneName == "DontDestroyOnLoad")
return DontDestroyHandle;
for (int i = 0; i < SceneManager.sceneCount; i++)
{
var scene = SceneManager.GetSceneAt(i);
if (scene.name == sceneName)
return scene.handle;
}
return -1;
}
internal void OnSceneChange()
{
m_sceneDropdown.OnCancel(null);
RefreshActiveScenes();
}
private void RefreshActiveScenes()
{
var names = new List<string>();
var handles = new List<int>();
for (int i = 0; i < SceneManager.sceneCount; i++)
{
Scene scene = SceneManager.GetSceneAt(i);
int handle = scene.handle;
if (scene == null || handle == -1 || string.IsNullOrEmpty(scene.name))
continue;
handles.Add(handle);
names.Add(scene.name);
}
names.Add("DontDestroyOnLoad");
handles.Add(DontDestroyHandle);
m_sceneDropdown.options.Clear();
foreach (string scene in names)
{
m_sceneDropdown.options.Add(new Dropdown.OptionData
{
text = scene
});
}
if (!handles.Contains(m_currentSceneHandle))
{
m_sceneDropdown.transform.Find("Label").GetComponent<Text>().text = names[0];
SetTargetScene(handles[0]);
}
}
public void SetTargetScene(string name) => SetTargetScene(GetSceneHandle(name));
public void SetTargetScene(int handle)
{
if (handle == -1)
return;
m_currentSceneHandle = handle;
GameObject[] rootObjs = SceneUnstrip.GetRootGameObjects(handle);
SetSceneObjectList(rootObjs);
m_selectedSceneObject = null;
if (m_backButtonObj.activeSelf)
{
m_backButtonObj.SetActive(false);
m_mainInspectBtn.SetActive(false);
}
m_scenePathText.text = "Scene root:";
//m_scenePathText.ForceMeshUpdate();
}
public void SetTargetObject(GameObject obj)
{
if (!obj)
return;
m_scenePathText.text = obj.name;
//m_scenePathText.ForceMeshUpdate();
m_selectedSceneObject = obj;
RefreshSelectedSceneObject();
if (!m_backButtonObj.activeSelf)
{
m_backButtonObj.SetActive(true);
m_mainInspectBtn.SetActive(true);
}
}
private void RefreshSelectedSceneObject()
{
GameObject[] list = new GameObject[m_selectedSceneObject.transform.childCount];
for (int i = 0; i < m_selectedSceneObject.transform.childCount; i++)
{
list[i] = m_selectedSceneObject.transform.GetChild(i).gameObject;
}
SetSceneObjectList(list);
}
private void SetSceneObjectList(GameObject[] objects)
{
m_allSceneListObjects = objects;
RefreshSceneObjectList();
}
private void SceneListObjectClicked(int index)
{
if (index >= m_sceneShortList.Count || !m_sceneShortList[index])
{
return;
}
SetTargetObject(m_sceneShortList[index]);
}
private void OnSceneListPageTurn()
{
RefreshSceneObjectList();
}
private void RefreshSceneObjectList()
{
m_timeOfLastSceneUpdate = Time.realtimeSinceStartup;
var objects = m_allSceneListObjects;
m_sceneListPageHandler.ListCount = objects.Length;
//int startIndex = m_sceneListPageHandler.StartIndex;
int newCount = 0;
foreach (var itemIndex in m_sceneListPageHandler)
{
newCount++;
// normalized index starting from 0
var i = itemIndex - m_sceneListPageHandler.StartIndex;
if (itemIndex >= objects.Length)
{
if (i > m_lastCount || i >= m_sceneListTexts.Count)
break;
GameObject label = m_sceneListTexts[i].transform.parent.parent.gameObject;
if (label.activeSelf)
label.SetActive(false);
}
else
{
GameObject obj = objects[itemIndex];
if (!obj)
continue;
if (i >= m_sceneShortList.Count)
{
m_sceneShortList.Add(obj);
AddObjectListButton();
}
else
{
m_sceneShortList[i] = obj;
}
var text = m_sceneListTexts[i];
var name = obj.name;
if (obj.transform.childCount > 0)
name = $"<color=grey>[{obj.transform.childCount}]</color> {name}";
text.text = name;
text.color = obj.activeSelf ? Color.green : Color.red;
var label = text.transform.parent.parent.gameObject;
if (!label.activeSelf)
{
label.SetActive(true);
}
}
}
m_lastCount = newCount;
}
#region UI CONSTRUCTION
public void ConstructScenePane()
{
GameObject leftPane = UIFactory.CreateVerticalGroup(HomePage.Instance.Content, new Color(72f / 255f, 72f / 255f, 72f / 255f));
LayoutElement leftLayout = leftPane.AddComponent<LayoutElement>();
leftLayout.minWidth = 350;
leftLayout.flexibleWidth = 0;
VerticalLayoutGroup leftGroup = leftPane.GetComponent<VerticalLayoutGroup>();
leftGroup.padding.left = 8;
leftGroup.padding.right = 8;
leftGroup.padding.top = 8;
leftGroup.padding.bottom = 8;
leftGroup.spacing = 5;
leftGroup.childControlWidth = true;
leftGroup.childControlHeight = true;
leftGroup.childForceExpandWidth = true;
leftGroup.childForceExpandHeight = true;
GameObject titleObj = UIFactory.CreateLabel(leftPane, TextAnchor.UpperLeft);
Text titleLabel = titleObj.GetComponent<Text>();
titleLabel.text = "Scene Explorer";
titleLabel.fontSize = 20;
LayoutElement titleLayout = titleObj.AddComponent<LayoutElement>();
titleLayout.minHeight = 30;
titleLayout.flexibleHeight = 0;
GameObject sceneDropdownObj = UIFactory.CreateDropdown(leftPane, out m_sceneDropdown);
LayoutElement dropdownLayout = sceneDropdownObj.AddComponent<LayoutElement>();
dropdownLayout.minHeight = 40;
dropdownLayout.flexibleHeight = 0;
dropdownLayout.minWidth = 320;
dropdownLayout.flexibleWidth = 2;
#if CPP
m_sceneDropdown.onValueChanged.AddListener(new Action<int>((int val) => { SetSceneFromDropdown(val); }));
#else
m_sceneDropdown.onValueChanged.AddListener((int val) => { SetSceneFromDropdown(val); });
#endif
void SetSceneFromDropdown(int val)
{
string scene = m_sceneDropdown.options[val].text;
SetTargetScene(scene);
}
GameObject scenePathGroupObj = UIFactory.CreateHorizontalGroup(leftPane, new Color(1, 1, 1, 0f));
HorizontalLayoutGroup scenePathGroup = scenePathGroupObj.GetComponent<HorizontalLayoutGroup>();
scenePathGroup.childControlHeight = true;
scenePathGroup.childControlWidth = true;
scenePathGroup.childForceExpandHeight = true;
scenePathGroup.childForceExpandWidth = true;
scenePathGroup.spacing = 5;
LayoutElement scenePathLayout = scenePathGroupObj.AddComponent<LayoutElement>();
scenePathLayout.minHeight = 20;
scenePathLayout.minWidth = 335;
scenePathLayout.flexibleWidth = 0;
m_backButtonObj = UIFactory.CreateButton(scenePathGroupObj);
Text backButtonText = m_backButtonObj.GetComponentInChildren<Text>();
backButtonText.text = "<";
LayoutElement backButtonLayout = m_backButtonObj.AddComponent<LayoutElement>();
backButtonLayout.minWidth = 40;
backButtonLayout.flexibleWidth = 0;
Button backButton = m_backButtonObj.GetComponent<Button>();
#if CPP
backButton.onClick.AddListener(new Action(() => { SetSceneObjectParent(); }));
#else
backButton.onClick.AddListener(() => { SetSceneObjectParent(); });
#endif
void SetSceneObjectParent()
{
if (!m_selectedSceneObject || !m_selectedSceneObject.transform.parent?.gameObject)
{
m_selectedSceneObject = null;
SetTargetScene(m_currentSceneHandle);
}
else
{
SetTargetObject(m_selectedSceneObject.transform.parent.gameObject);
}
}
GameObject scenePathLabel = UIFactory.CreateHorizontalGroup(scenePathGroupObj);
Image image = scenePathLabel.GetComponent<Image>();
image.color = Color.white;
LayoutElement scenePathLabelLayout = scenePathLabel.AddComponent<LayoutElement>();
scenePathLabelLayout.minWidth = 210;
scenePathLabelLayout.minHeight = 20;
scenePathLabelLayout.flexibleHeight = 0;
scenePathLabelLayout.flexibleWidth = 120;
scenePathLabel.AddComponent<Mask>().showMaskGraphic = false;
GameObject scenePathLabelText = UIFactory.CreateLabel(scenePathLabel, TextAnchor.MiddleLeft);
m_scenePathText = scenePathLabelText.GetComponent<Text>();
m_scenePathText.text = "Scene root:";
m_scenePathText.fontSize = 15;
m_scenePathText.horizontalOverflow = HorizontalWrapMode.Overflow;
LayoutElement textLayout = scenePathLabelText.gameObject.AddComponent<LayoutElement>();
textLayout.minWidth = 210;
textLayout.flexibleWidth = 120;
textLayout.minHeight = 20;
textLayout.flexibleHeight = 0;
m_mainInspectBtn = UIFactory.CreateButton(scenePathGroupObj);
Text inspectButtonText = m_mainInspectBtn.GetComponentInChildren<Text>();
inspectButtonText.text = "Inspect";
LayoutElement inspectButtonLayout = m_mainInspectBtn.AddComponent<LayoutElement>();
inspectButtonLayout.minWidth = 65;
inspectButtonLayout.flexibleWidth = 0;
Button inspectButton = m_mainInspectBtn.GetComponent<Button>();
#if CPP
inspectButton.onClick.AddListener(new Action(() => { InspectorManager.Instance.Inspect(m_selectedSceneObject); }));
#else
inspectButton.onClick.AddListener(() => { InspectorManager.Instance.Inspect(m_selectedSceneObject); });
#endif
GameObject scrollObj = UIFactory.CreateScrollView(leftPane, out m_sceneListContent, new Color(0.1f, 0.1f, 0.1f));
Scrollbar scroll = scrollObj.transform.Find("Scrollbar Vertical").GetComponent<Scrollbar>();
ColorBlock colors = scroll.colors;
colors.normalColor = new Color(0.6f, 0.6f, 0.6f, 1.0f);
scroll.colors = colors;
var horiScroll = scrollObj.transform.Find("Scrollbar Horizontal");
horiScroll.gameObject.SetActive(false);
var scrollRect = scrollObj.GetComponentInChildren<ScrollRect>();
scrollRect.horizontalScrollbar = null;
var sceneGroup = m_sceneListContent.GetComponent<VerticalLayoutGroup>();
sceneGroup.childControlHeight = true;
sceneGroup.spacing = 2;
m_sceneListPageHandler = new PageHandler();
m_sceneListPageHandler.ConstructUI(leftPane);
m_sceneListPageHandler.OnPageChanged += OnSceneListPageTurn;
}
private void AddObjectListButton()
{
int thisIndex = m_sceneListTexts.Count();
GameObject btnGroupObj = UIFactory.CreateHorizontalGroup(m_sceneListContent, new Color(0.1f, 0.1f, 0.1f));
HorizontalLayoutGroup btnGroup = btnGroupObj.GetComponent<HorizontalLayoutGroup>();
btnGroup.childForceExpandWidth = true;
btnGroup.childControlWidth = true;
btnGroup.childForceExpandHeight = false;
btnGroup.childControlHeight = true;
LayoutElement btnLayout = btnGroupObj.AddComponent<LayoutElement>();
btnLayout.flexibleWidth = 320;
btnLayout.minHeight = 25;
btnLayout.flexibleHeight = 0;
btnGroupObj.AddComponent<Mask>();
GameObject mainButtonObj = UIFactory.CreateButton(btnGroupObj);
LayoutElement mainBtnLayout = mainButtonObj.AddComponent<LayoutElement>();
mainBtnLayout.minHeight = 25;
mainBtnLayout.flexibleHeight = 0;
mainBtnLayout.minWidth = 240;
mainBtnLayout.flexibleWidth = 0;
Button mainBtn = mainButtonObj.GetComponent<Button>();
ColorBlock mainColors = mainBtn.colors;
mainColors.normalColor = new Color(0.1f, 0.1f, 0.1f);
mainColors.highlightedColor = new Color(0.2f, 0.2f, 0.2f, 1);
mainBtn.colors = mainColors;
#if CPP
mainBtn.onClick.AddListener(new Action(() => { SceneListObjectClicked(thisIndex); }));
#else
mainBtn.onClick.AddListener(() => { SceneListObjectClicked(thisIndex); });
#endif
Text mainText = mainButtonObj.GetComponentInChildren<Text>();
mainText.alignment = TextAnchor.MiddleLeft;
mainText.horizontalOverflow = HorizontalWrapMode.Overflow;
m_sceneListTexts.Add(mainText);
GameObject inspectBtnObj = UIFactory.CreateButton(btnGroupObj);
LayoutElement inspectBtnLayout = inspectBtnObj.AddComponent<LayoutElement>();
inspectBtnLayout.minWidth = 60;
inspectBtnLayout.flexibleWidth = 0;
inspectBtnLayout.minHeight = 25;
inspectBtnLayout.flexibleHeight = 0;
Text inspectText = inspectBtnObj.GetComponentInChildren<Text>();
inspectText.text = "Inspect";
inspectText.color = Color.white;
Button inspectBtn = inspectBtnObj.GetComponent<Button>();
ColorBlock inspectColors = inspectBtn.colors;
inspectColors.normalColor = new Color(0.15f, 0.15f, 0.15f);
mainColors.highlightedColor = new Color(0.2f, 0.2f, 0.2f, 0.5f);
inspectBtn.colors = inspectColors;
#if CPP
inspectBtn.onClick.AddListener(new Action(() => { InspectorManager.Instance.Inspect(m_sceneShortList[thisIndex]); }));
#else
inspectBtn.onClick.AddListener(() => { InspectorManager.Instance.Inspect(m_sceneShortList[thisIndex]); });
#endif
}
#endregion
}
}

View File

@ -0,0 +1,26 @@
using System;
namespace UnityExplorer.Inspectors
{
public class StaticInspector : ReflectionInspector
{
public override string TabLabel => $" [S] {base.TabLabel}";
public StaticInspector(Type type) : base(type)
{
// TODO
}
public override void Update()
{
base.Update();
if (m_pendingDestroy || InspectorManager.Instance.m_activeInspector != this)
{
return;
}
// todo
}
}
}