mirror of
https://github.com/GrahamKracker/UnityExplorer.git
synced 2025-07-15 07:56:41 +08:00
refactor
This commit is contained in:
26
src/Inspectors/CacheObject/CacheEnumerated.cs
Normal file
26
src/Inspectors/CacheObject/CacheEnumerated.cs
Normal 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();
|
||||
// }
|
||||
// }
|
||||
//}
|
76
src/Inspectors/CacheObject/CacheFactory.cs
Normal file
76
src/Inspectors/CacheObject/CacheFactory.cs
Normal 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;
|
||||
// }
|
||||
// }
|
||||
//}
|
54
src/Inspectors/CacheObject/CacheField.cs
Normal file
54
src/Inspectors/CacheObject/CacheField.cs
Normal 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);
|
||||
// }
|
||||
// }
|
||||
//}
|
226
src/Inspectors/CacheObject/CacheMember.cs
Normal file
226
src/Inspectors/CacheObject/CacheMember.cs
Normal 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;
|
||||
// }
|
||||
// }
|
||||
//}
|
200
src/Inspectors/CacheObject/CacheMethod.cs
Normal file
200
src/Inspectors/CacheObject/CacheMethod.cs
Normal 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();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
117
src/Inspectors/CacheObject/CacheObjectBase.cs
Normal file
117
src/Inspectors/CacheObject/CacheObjectBase.cs
Normal 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();
|
||||
// }
|
||||
//}
|
84
src/Inspectors/CacheObject/CacheProperty.cs
Normal file
84
src/Inspectors/CacheObject/CacheProperty.cs
Normal 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());
|
||||
// }
|
||||
// }
|
||||
//}
|
1381
src/Inspectors/GameObjectInspector.cs
Normal file
1381
src/Inspectors/GameObjectInspector.cs
Normal file
File diff suppressed because it is too large
Load Diff
170
src/Inspectors/InspectorBase.cs
Normal file
170
src/Inspectors/InspectorBase.cs
Normal 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
|
||||
}
|
||||
}
|
184
src/Inspectors/InspectorManager.cs
Normal file
184
src/Inspectors/InspectorManager.cs
Normal 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
|
||||
}
|
||||
}
|
28
src/Inspectors/InstanceInspector.cs
Normal file
28
src/Inspectors/InstanceInspector.cs
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
39
src/Inspectors/ReflectionInspector.cs
Normal file
39
src/Inspectors/ReflectionInspector.cs
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
488
src/Inspectors/SceneExplorer.cs
Normal file
488
src/Inspectors/SceneExplorer.cs
Normal 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
|
||||
}
|
||||
}
|
26
src/Inspectors/StaticInspector.cs
Normal file
26
src/Inspectors/StaticInspector.cs
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user