mirror of
https://github.com/sinai-dev/UnityExplorer.git
synced 2025-06-16 14:17:51 +08:00
1.4.2
* Fixed a bug on the Reflection window which would prevent primitive values from being applied * Improved some parts of the Scene Explorer and the Reflection Window interfaces * Scene Explorer now has "page view" like other lists * Various minor cleanups and refactorings
This commit is contained in:
parent
e3d1add090
commit
45b5ce0ef8
@ -10,21 +10,18 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
public class CacheEnum : CacheObject
|
public class CacheEnum : CacheObject
|
||||||
{
|
{
|
||||||
private readonly Type m_enumType;
|
public Type EnumType;
|
||||||
private readonly string[] m_names;
|
public string[] EnumNames;
|
||||||
|
|
||||||
public CacheEnum(object obj)
|
public override void Init()
|
||||||
{
|
{
|
||||||
if (obj != null)
|
EnumType = Value.GetType();
|
||||||
{
|
EnumNames = Enum.GetNames(EnumType);
|
||||||
m_enumType = obj.GetType();
|
|
||||||
m_names = Enum.GetNames(m_enumType);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void DrawValue(Rect window, float width)
|
public override void DrawValue(Rect window, float width)
|
||||||
{
|
{
|
||||||
if (MemberInfo != null)
|
if (CanWrite)
|
||||||
{
|
{
|
||||||
if (GUILayout.Button("<", new GUILayoutOption[] { GUILayout.Width(25) }))
|
if (GUILayout.Button("<", new GUILayoutOption[] { GUILayout.Width(25) }))
|
||||||
{
|
{
|
||||||
@ -38,34 +35,18 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GUILayout.Label(Value.ToString(), null);
|
GUILayout.Label(Value.ToString(), null);// + "<color=yellow><i> (" + ValueType + ")</i></color>", null);
|
||||||
}
|
|
||||||
|
|
||||||
public override void SetValue()
|
|
||||||
{
|
|
||||||
if (MemberInfo == null)
|
|
||||||
{
|
|
||||||
MelonLogger.Log("Trying to SetValue but the MemberInfo is null!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Enum.Parse(m_enumType, Value.ToString()) is object enumValue && enumValue != null)
|
|
||||||
{
|
|
||||||
Value = enumValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
SetValue(Value, MemberInfo, DeclaringInstance);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetEnum(ref object value, int change)
|
public void SetEnum(ref object value, int change)
|
||||||
{
|
{
|
||||||
var names = m_names.ToList();
|
var names = EnumNames.ToList();
|
||||||
|
|
||||||
int newindex = names.IndexOf(value.ToString()) + change;
|
int newindex = names.IndexOf(value.ToString()) + change;
|
||||||
|
|
||||||
if ((change < 0 && newindex >= 0) || (change > 0 && newindex < names.Count))
|
if ((change < 0 && newindex >= 0) || (change > 0 && newindex < names.Count))
|
||||||
{
|
{
|
||||||
value = Enum.Parse(m_enumType, names[newindex]);
|
value = Enum.Parse(EnumType, names[newindex]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,44 +10,37 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
public class CacheGameObject : CacheObject
|
public class CacheGameObject : CacheObject
|
||||||
{
|
{
|
||||||
private GameObject m_gameObject;
|
private GameObject GameObj
|
||||||
|
|
||||||
public CacheGameObject(object obj)
|
|
||||||
{
|
{
|
||||||
if (obj != null)
|
get
|
||||||
m_gameObject = GetGameObject(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
private GameObject GetGameObject(object obj)
|
|
||||||
{
|
|
||||||
if (obj is Il2CppSystem.Object ilObj)
|
|
||||||
{
|
{
|
||||||
var ilType = ilObj.GetIl2CppType();
|
if (m_gameObject == null)
|
||||||
|
|
||||||
if (ilType == ReflectionHelpers.GameObjectType || ilType == ReflectionHelpers.TransformType)
|
|
||||||
{
|
{
|
||||||
return ilObj.TryCast<GameObject>() ?? ilObj.TryCast<Transform>()?.gameObject;
|
if (Value is Il2CppSystem.Object ilObj)
|
||||||
}
|
{
|
||||||
}
|
var ilType = ilObj.GetIl2CppType();
|
||||||
|
|
||||||
return null;
|
if (ilType == ReflectionHelpers.GameObjectType || ilType == ReflectionHelpers.TransformType)
|
||||||
|
{
|
||||||
|
m_gameObject = ilObj.TryCast<GameObject>() ?? ilObj.TryCast<Transform>()?.gameObject;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_gameObject;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private GameObject m_gameObject;
|
||||||
|
|
||||||
public override void DrawValue(Rect window, float width)
|
public override void DrawValue(Rect window, float width)
|
||||||
{
|
{
|
||||||
UIHelpers.GameobjButton(m_gameObject, null, false, width);
|
UIHelpers.GameobjButton(GameObj, null, false, width);
|
||||||
}
|
|
||||||
|
|
||||||
public override void SetValue()
|
|
||||||
{
|
|
||||||
throw new NotImplementedException("TODO");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void UpdateValue()
|
public override void UpdateValue()
|
||||||
{
|
{
|
||||||
base.UpdateValue();
|
base.UpdateValue();
|
||||||
|
|
||||||
m_gameObject = GetGameObject(Value);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
public bool IsExpanded { get; set; }
|
public bool IsExpanded { get; set; }
|
||||||
public int ArrayOffset { get; set; }
|
public int ArrayOffset { get; set; }
|
||||||
|
public int ArrayLimit { get; set; } = 20;
|
||||||
|
|
||||||
public Type EntryType
|
public Type EntryType
|
||||||
{
|
{
|
||||||
@ -47,15 +48,6 @@ namespace Explorer
|
|||||||
private IEnumerable m_enumerable;
|
private IEnumerable m_enumerable;
|
||||||
private CacheObject[] m_cachedEntries;
|
private CacheObject[] m_cachedEntries;
|
||||||
|
|
||||||
public CacheList(object obj)
|
|
||||||
{
|
|
||||||
if (obj != null)
|
|
||||||
{
|
|
||||||
Value = obj;
|
|
||||||
EntryType = obj.GetType().GetGenericArguments()[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private IEnumerable CppListToEnumerable(object list)
|
private IEnumerable CppListToEnumerable(object list)
|
||||||
{
|
{
|
||||||
if (EntryType == null) return null;
|
if (EntryType == null) return null;
|
||||||
@ -95,12 +87,12 @@ namespace Explorer
|
|||||||
|
|
||||||
if (IsExpanded)
|
if (IsExpanded)
|
||||||
{
|
{
|
||||||
if (count > CppExplorer.ArrayLimit)
|
if (count > ArrayLimit)
|
||||||
{
|
{
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(null);
|
||||||
GUILayout.Space(190);
|
GUILayout.Space(190);
|
||||||
int maxOffset = (int)Mathf.Ceil((float)(count / (decimal)CppExplorer.ArrayLimit)) - 1;
|
int maxOffset = (int)Mathf.Ceil((float)(count / (decimal)ArrayLimit)) - 1;
|
||||||
GUILayout.Label($"Page {ArrayOffset + 1}/{maxOffset + 1}", new GUILayoutOption[] { GUILayout.Width(80) });
|
GUILayout.Label($"Page {ArrayOffset + 1}/{maxOffset + 1}", new GUILayoutOption[] { GUILayout.Width(80) });
|
||||||
// prev/next page buttons
|
// prev/next page buttons
|
||||||
if (GUILayout.Button("< Prev", null))
|
if (GUILayout.Button("< Prev", null))
|
||||||
@ -111,13 +103,20 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
if (ArrayOffset < maxOffset) ArrayOffset++;
|
if (ArrayOffset < maxOffset) ArrayOffset++;
|
||||||
}
|
}
|
||||||
|
GUILayout.Label("Limit: ", new GUILayoutOption[] { GUILayout.Width(50) });
|
||||||
|
var limit = this.ArrayLimit.ToString();
|
||||||
|
limit = GUILayout.TextField(limit, new GUILayoutOption[] { GUILayout.Width(50) });
|
||||||
|
if (limit != ArrayLimit.ToString() && int.TryParse(limit, out int i))
|
||||||
|
{
|
||||||
|
ArrayLimit = i;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int offset = ArrayOffset * CppExplorer.ArrayLimit;
|
int offset = ArrayOffset * ArrayLimit;
|
||||||
|
|
||||||
if (offset >= count) offset = 0;
|
if (offset >= count) offset = 0;
|
||||||
|
|
||||||
for (int i = offset; i < offset + CppExplorer.ArrayLimit && i < count; i++)
|
for (int i = offset; i < offset + ArrayLimit && i < count; i++)
|
||||||
{
|
{
|
||||||
var entry = m_cachedEntries[i];
|
var entry = m_cachedEntries[i];
|
||||||
|
|
||||||
@ -140,11 +139,6 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void SetValue()
|
|
||||||
{
|
|
||||||
throw new NotImplementedException("TODO");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Called when the user presses the "Update" button, or if AutoUpdate is on.
|
/// Called when the user presses the "Update" button, or if AutoUpdate is on.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -161,7 +155,7 @@ namespace Explorer
|
|||||||
var list = new List<CacheObject>();
|
var list = new List<CacheObject>();
|
||||||
while (enumerator.MoveNext())
|
while (enumerator.MoveNext())
|
||||||
{
|
{
|
||||||
list.Add(GetCacheObject(enumerator.Current));
|
list.Add(GetCacheObject(enumerator.Current, null, null, this.EntryType));
|
||||||
}
|
}
|
||||||
|
|
||||||
m_cachedEntries = list.ToArray();
|
m_cachedEntries = list.ToArray();
|
||||||
|
@ -17,15 +17,45 @@ namespace Explorer
|
|||||||
|
|
||||||
// Reflection window only
|
// Reflection window only
|
||||||
public MemberInfo MemberInfo { get; set; }
|
public MemberInfo MemberInfo { get; set; }
|
||||||
public ReflectionWindow.MemberInfoType MemberInfoType { get; set; }
|
// public ReflectionWindow.MemberInfoType MemberInfoType { get; set; }
|
||||||
public Type DeclaringType { get; set; }
|
public Type DeclaringType { get; set; }
|
||||||
public object DeclaringInstance { get; set; }
|
public object DeclaringInstance { get; set; }
|
||||||
public string FullName => $"{MemberInfo.DeclaringType.Name}.{MemberInfo.Name}";
|
public string FullName => $"{MemberInfo.DeclaringType.Name}.{MemberInfo.Name}";
|
||||||
public string ReflectionException;
|
public string ReflectionException;
|
||||||
|
|
||||||
|
public bool CanWrite
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (MemberInfo is FieldInfo fi)
|
||||||
|
{
|
||||||
|
return !(fi.IsLiteral && !fi.IsInitOnly);
|
||||||
|
}
|
||||||
|
else if (MemberInfo is PropertyInfo pi)
|
||||||
|
{
|
||||||
|
return pi.CanWrite;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReflectionWindow.MemberInfoType MemberInfoType
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (MemberInfo is FieldInfo) return ReflectionWindow.MemberInfoType.Field;
|
||||||
|
if (MemberInfo is PropertyInfo) return ReflectionWindow.MemberInfoType.Property;
|
||||||
|
if (MemberInfo is MethodInfo) return ReflectionWindow.MemberInfoType.Method;
|
||||||
|
return ReflectionWindow.MemberInfoType.All;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// methods
|
// methods
|
||||||
|
public virtual void Init() { }
|
||||||
public abstract void DrawValue(Rect window, float width);
|
public abstract void DrawValue(Rect window, float width);
|
||||||
public abstract void SetValue();
|
|
||||||
|
|
||||||
public static CacheObject GetCacheObject(object obj)
|
public static CacheObject GetCacheObject(object obj)
|
||||||
{
|
{
|
||||||
@ -41,63 +71,72 @@ namespace Explorer
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static CacheObject GetCacheObject(object obj, MemberInfo memberInfo, object declaringInstance)
|
public static CacheObject GetCacheObject(object obj, MemberInfo memberInfo, object declaringInstance)
|
||||||
{
|
{
|
||||||
CacheObject holder;
|
|
||||||
|
|
||||||
var type = ReflectionHelpers.GetActualType(obj) ?? (memberInfo as FieldInfo)?.FieldType ?? (memberInfo as PropertyInfo)?.PropertyType;
|
var type = ReflectionHelpers.GetActualType(obj) ?? (memberInfo as FieldInfo)?.FieldType ?? (memberInfo as PropertyInfo)?.PropertyType;
|
||||||
|
|
||||||
|
if (type == null)
|
||||||
|
{
|
||||||
|
MelonLogger.Log("Could not get type for object or memberinfo!");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GetCacheObject(obj, memberInfo, declaringInstance, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the CacheObject subclass for an object or MemberInfo
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="obj">The current value (can be null if memberInfo is not null)</param>
|
||||||
|
/// <param name="memberInfo">The MemberInfo (can be null if obj is not null)</param>
|
||||||
|
/// <param name="declaringInstance">If MemberInfo is not null, the declaring class instance. Can be null if static.</param>
|
||||||
|
/// <param name="type">The type of the object or MemberInfo value.</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static CacheObject GetCacheObject(object obj, MemberInfo memberInfo, object declaringInstance, Type type)
|
||||||
|
{
|
||||||
|
CacheObject holder;
|
||||||
|
|
||||||
if ((obj is Il2CppSystem.Object || typeof(Il2CppSystem.Object).IsAssignableFrom(type))
|
if ((obj is Il2CppSystem.Object || typeof(Il2CppSystem.Object).IsAssignableFrom(type))
|
||||||
&& (type.FullName.Contains("UnityEngine.GameObject") || type.FullName.Contains("UnityEngine.Transform")))
|
&& (type.FullName.Contains("UnityEngine.GameObject") || type.FullName.Contains("UnityEngine.Transform")))
|
||||||
{
|
{
|
||||||
holder = new CacheGameObject(obj);
|
holder = new CacheGameObject();
|
||||||
}
|
}
|
||||||
else if (type.IsPrimitive || type == typeof(string))
|
else if (type.IsPrimitive || type == typeof(string))
|
||||||
{
|
{
|
||||||
holder = new CachePrimitive(obj);
|
holder = new CachePrimitive();
|
||||||
}
|
}
|
||||||
else if (type.IsEnum)
|
else if (type.IsEnum)
|
||||||
{
|
{
|
||||||
holder = new CacheEnum(obj);
|
holder = new CacheEnum();
|
||||||
}
|
}
|
||||||
else if (typeof(System.Collections.IEnumerable).IsAssignableFrom(type) || ReflectionHelpers.IsList(type))
|
else if (typeof(System.Collections.IEnumerable).IsAssignableFrom(type) || ReflectionHelpers.IsList(type))
|
||||||
{
|
{
|
||||||
holder = new CacheList(obj);
|
holder = new CacheList();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
holder = new CacheOther();
|
holder = new CacheOther();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
holder.Value = obj;
|
||||||
|
holder.ValueType = type.FullName;
|
||||||
|
|
||||||
if (memberInfo != null)
|
if (memberInfo != null)
|
||||||
{
|
{
|
||||||
holder.MemberInfo = memberInfo;
|
holder.MemberInfo = memberInfo;
|
||||||
holder.DeclaringType = memberInfo.DeclaringType;
|
holder.DeclaringType = memberInfo.DeclaringType;
|
||||||
holder.DeclaringInstance = declaringInstance;
|
holder.DeclaringInstance = declaringInstance;
|
||||||
|
|
||||||
if (memberInfo.MemberType == MemberTypes.Field)
|
|
||||||
{
|
|
||||||
holder.MemberInfoType = ReflectionWindow.MemberInfoType.Field;
|
|
||||||
}
|
|
||||||
else if (memberInfo.MemberType == MemberTypes.Property)
|
|
||||||
{
|
|
||||||
holder.MemberInfoType = ReflectionWindow.MemberInfoType.Property;
|
|
||||||
}
|
|
||||||
else if (memberInfo.MemberType == MemberTypes.Method)
|
|
||||||
{
|
|
||||||
holder.MemberInfoType = ReflectionWindow.MemberInfoType.Method;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
holder.Value = obj;
|
holder.UpdateValue();
|
||||||
holder.ValueType = type.FullName;
|
holder.Init();
|
||||||
|
|
||||||
return holder;
|
return holder;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Draw(Rect window, float labelWidth = 180f)
|
public void Draw(Rect window, float labelWidth = 215f)
|
||||||
{
|
{
|
||||||
if (MemberInfo != null)
|
if (MemberInfo != null)
|
||||||
{
|
{
|
||||||
GUILayout.Label("<color=cyan>" + FullName + ":</color>", new GUILayoutOption[] { GUILayout.Width(labelWidth) });
|
GUILayout.Label("<color=cyan>" + FullName + "</color>", new GUILayoutOption[] { GUILayout.Width(labelWidth) });
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -110,7 +149,7 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
else if (Value == null)
|
else if (Value == null)
|
||||||
{
|
{
|
||||||
GUILayout.Label("<i>null (" + this.ValueType + ")</i>", null);
|
GUILayout.Label("<i>null (" + ValueType + ")</i>", null);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -147,25 +186,19 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetValue(object value, MemberInfo memberInfo, object declaringInstance)
|
public void SetValue()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (memberInfo.MemberType == MemberTypes.Field)
|
if (MemberInfo.MemberType == MemberTypes.Field)
|
||||||
{
|
{
|
||||||
var fi = memberInfo as FieldInfo;
|
var fi = MemberInfo as FieldInfo;
|
||||||
if (!(fi.IsLiteral && !fi.IsInitOnly))
|
fi.SetValue(fi.IsStatic ? null : DeclaringInstance, Value);
|
||||||
{
|
|
||||||
fi.SetValue(fi.IsStatic ? null : declaringInstance, value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (memberInfo.MemberType == MemberTypes.Property)
|
else if (MemberInfo.MemberType == MemberTypes.Property)
|
||||||
{
|
{
|
||||||
var pi = memberInfo as PropertyInfo;
|
var pi = MemberInfo as PropertyInfo;
|
||||||
if (pi.CanWrite)
|
pi.SetValue(pi.GetAccessors()[0].IsStatic ? null : DeclaringInstance, Value);
|
||||||
{
|
|
||||||
pi.SetValue(pi.GetAccessors()[0].IsStatic ? null : declaringInstance, value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
|
@ -58,21 +58,11 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
|
|
||||||
GUI.skin.button.alignment = TextAnchor.MiddleLeft;
|
GUI.skin.button.alignment = TextAnchor.MiddleLeft;
|
||||||
if (GUILayout.Button("<color=yellow>" + label + "</color>", new GUILayoutOption[] { GUILayout.MaxWidth(width) }))
|
if (GUILayout.Button("<color=yellow>" + label + "</color>", new GUILayoutOption[] { GUILayout.MaxWidth(width + 40) }))
|
||||||
{
|
{
|
||||||
WindowManager.InspectObject(Value, out bool _);
|
WindowManager.InspectObject(Value, out bool _);
|
||||||
}
|
}
|
||||||
GUI.skin.button.alignment = TextAnchor.MiddleCenter;
|
GUI.skin.button.alignment = TextAnchor.MiddleCenter;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void SetValue()
|
|
||||||
{
|
|
||||||
throw new NotImplementedException("TODO");
|
|
||||||
}
|
|
||||||
|
|
||||||
//public override void UpdateValue(object obj)
|
|
||||||
//{
|
|
||||||
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Reflection;
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using MelonLoader;
|
using MelonLoader;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
@ -10,7 +7,7 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
public class CachePrimitive : CacheObject
|
public class CachePrimitive : CacheObject
|
||||||
{
|
{
|
||||||
public enum PrimitiveType
|
public enum PrimitiveTypes
|
||||||
{
|
{
|
||||||
Bool,
|
Bool,
|
||||||
Double,
|
Double,
|
||||||
@ -19,69 +16,122 @@ namespace Explorer
|
|||||||
String
|
String
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly PrimitiveType m_primitiveType;
|
private string m_valueToString;
|
||||||
|
|
||||||
public CachePrimitive(object obj)
|
public PrimitiveTypes PrimitiveType;
|
||||||
|
|
||||||
|
public MethodInfo ParseMethod
|
||||||
{
|
{
|
||||||
if (obj == null) return;
|
get
|
||||||
|
{
|
||||||
|
if (m_parseMethod == null)
|
||||||
|
{
|
||||||
|
Type t = null;
|
||||||
|
switch (PrimitiveType)
|
||||||
|
{
|
||||||
|
case PrimitiveTypes.Bool:
|
||||||
|
t = typeof(bool); break;
|
||||||
|
case PrimitiveTypes.Double:
|
||||||
|
t = typeof(double); break;
|
||||||
|
case PrimitiveTypes.Float:
|
||||||
|
t = typeof(float); break;
|
||||||
|
case PrimitiveTypes.Int:
|
||||||
|
t = typeof(int); break;
|
||||||
|
case PrimitiveTypes.String:
|
||||||
|
t = typeof(string); break;
|
||||||
|
}
|
||||||
|
m_parseMethod = t.GetMethod("Parse", new Type[] { typeof(string) });
|
||||||
|
}
|
||||||
|
return m_parseMethod;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (obj is bool)
|
private MethodInfo m_parseMethod;
|
||||||
|
|
||||||
|
public override void Init()
|
||||||
|
{
|
||||||
|
if (Value == null)
|
||||||
{
|
{
|
||||||
m_primitiveType = PrimitiveType.Bool;
|
// this must mean it is a string? no other primitive type should be nullable
|
||||||
|
PrimitiveType = PrimitiveTypes.String;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else if (obj is double)
|
|
||||||
|
m_valueToString = Value.ToString();
|
||||||
|
var type = Value.GetType();
|
||||||
|
|
||||||
|
if (type == typeof(bool))
|
||||||
{
|
{
|
||||||
m_primitiveType = PrimitiveType.Double;
|
PrimitiveType = PrimitiveTypes.Bool;
|
||||||
}
|
}
|
||||||
else if (obj is float)
|
else if (type == typeof(double))
|
||||||
{
|
{
|
||||||
m_primitiveType = PrimitiveType.Float;
|
PrimitiveType = PrimitiveTypes.Double;
|
||||||
}
|
}
|
||||||
else if (obj is int || obj is IntPtr || obj is uint)
|
else if (type == typeof(float))
|
||||||
{
|
{
|
||||||
m_primitiveType = PrimitiveType.Int;
|
PrimitiveType = PrimitiveTypes.Float;
|
||||||
}
|
}
|
||||||
else if (obj is string)
|
else if (type == typeof(int) || type == typeof(long) || type == typeof(uint) || type == typeof(ulong) || type == typeof(IntPtr))
|
||||||
{
|
{
|
||||||
m_primitiveType = PrimitiveType.String;
|
PrimitiveType = PrimitiveTypes.Int;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (type != typeof(string))
|
||||||
|
{
|
||||||
|
MelonLogger.Log("Unsupported primitive: " + type);
|
||||||
|
}
|
||||||
|
|
||||||
|
PrimitiveType = PrimitiveTypes.String;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void UpdateValue()
|
||||||
|
{
|
||||||
|
base.UpdateValue();
|
||||||
|
|
||||||
|
m_valueToString = Value?.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void DrawValue(Rect window, float width)
|
public override void DrawValue(Rect window, float width)
|
||||||
{
|
{
|
||||||
if (m_primitiveType == PrimitiveType.Bool && Value is bool b)
|
if (PrimitiveType == PrimitiveTypes.Bool)
|
||||||
{
|
{
|
||||||
|
var b = (bool)Value;
|
||||||
var color = "<color=" + (b ? "lime>" : "red>");
|
var color = "<color=" + (b ? "lime>" : "red>");
|
||||||
Value = GUILayout.Toggle((bool)Value, color + Value.ToString() + "</color>", null);
|
b = GUILayout.Toggle(b, color + b.ToString() + "</color>", null);
|
||||||
|
|
||||||
if (b != (bool)Value)
|
if (b != (bool)Value)
|
||||||
{
|
{
|
||||||
SetValue();
|
SetValue(m_valueToString);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var toString = Value.ToString();
|
GUILayout.Label("<color=yellow><i>" + PrimitiveType + "</i></color>", new GUILayoutOption[] { GUILayout.Width(50) });
|
||||||
if (toString.Length > 37)
|
|
||||||
|
var _width = window.width - 200;
|
||||||
|
if (m_valueToString.Length > 37)
|
||||||
{
|
{
|
||||||
Value = GUILayout.TextArea(toString, new GUILayoutOption[] { GUILayout.MaxWidth(window.width - 260) });
|
m_valueToString = GUILayout.TextArea(m_valueToString, new GUILayoutOption[] { GUILayout.MaxWidth(_width) });
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Value = GUILayout.TextField(toString, new GUILayoutOption[] { GUILayout.MaxWidth(window.width - 260) });
|
m_valueToString = GUILayout.TextField(m_valueToString, new GUILayoutOption[] { GUILayout.MaxWidth(_width) });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MemberInfo != null)
|
if (CanWrite)
|
||||||
{
|
{
|
||||||
if (GUILayout.Button("<color=#00FF00>Apply</color>", new GUILayoutOption[] { GUILayout.Width(60) }))
|
if (GUILayout.Button("<color=#00FF00>Apply</color>", new GUILayoutOption[] { GUILayout.Width(60) }))
|
||||||
{
|
{
|
||||||
SetValue();
|
SetValue(m_valueToString);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void SetValue()
|
public void SetValue(string value)
|
||||||
{
|
{
|
||||||
if (MemberInfo == null)
|
if (MemberInfo == null)
|
||||||
{
|
{
|
||||||
@ -89,19 +139,24 @@ namespace Explorer
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (m_primitiveType)
|
if (PrimitiveType == PrimitiveTypes.String)
|
||||||
{
|
{
|
||||||
case PrimitiveType.Bool:
|
Value = value;
|
||||||
SetValue(bool.Parse(Value.ToString()), MemberInfo, DeclaringInstance); return;
|
|
||||||
case PrimitiveType.Double:
|
|
||||||
SetValue(double.Parse(Value.ToString()), MemberInfo, DeclaringInstance); return;
|
|
||||||
case PrimitiveType.Float:
|
|
||||||
SetValue(float.Parse(Value.ToString()), MemberInfo, DeclaringInstance); return;
|
|
||||||
case PrimitiveType.Int:
|
|
||||||
SetValue(int.Parse(Value.ToString()), MemberInfo, DeclaringInstance); return;
|
|
||||||
case PrimitiveType.String:
|
|
||||||
SetValue(Value.ToString(), MemberInfo, DeclaringInstance); return;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var val = ParseMethod.Invoke(null, new object[] { value });
|
||||||
|
Value = val;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
MelonLogger.Log("Exception parsing value: " + e.GetType() + ", " + e.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SetValue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ namespace Explorer
|
|||||||
// consts
|
// consts
|
||||||
|
|
||||||
public const string ID = "com.sinai.cppexplorer";
|
public const string ID = "com.sinai.cppexplorer";
|
||||||
public const string VERSION = "1.4.1";
|
public const string VERSION = "1.4.2";
|
||||||
public const string AUTHOR = "Sinai";
|
public const string AUTHOR = "Sinai";
|
||||||
|
|
||||||
public const string NAME = "CppExplorer"
|
public const string NAME = "CppExplorer"
|
||||||
@ -29,7 +29,6 @@ namespace Explorer
|
|||||||
// props
|
// props
|
||||||
|
|
||||||
public static bool ShowMenu { get; set; } = false;
|
public static bool ShowMenu { get; set; } = false;
|
||||||
public static int ArrayLimit { get; set; } = 20;
|
|
||||||
|
|
||||||
// methods
|
// methods
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ namespace Explorer
|
|||||||
public static Il2CppSystem.Type TransformType => Il2CppType.Of<Transform>();
|
public static Il2CppSystem.Type TransformType => Il2CppType.Of<Transform>();
|
||||||
public static Il2CppSystem.Type ObjectType => Il2CppType.Of<UnityEngine.Object>();
|
public static Il2CppSystem.Type ObjectType => Il2CppType.Of<UnityEngine.Object>();
|
||||||
public static Il2CppSystem.Type ComponentType => Il2CppType.Of<Component>();
|
public static Il2CppSystem.Type ComponentType => Il2CppType.Of<Component>();
|
||||||
|
public static Il2CppSystem.Type BehaviourType => Il2CppType.Of<Behaviour>();
|
||||||
|
|
||||||
private static readonly MethodInfo m_tryCastMethodInfo = typeof(Il2CppObjectBase).GetMethod("TryCast");
|
private static readonly MethodInfo m_tryCastMethodInfo = typeof(Il2CppObjectBase).GetMethod("TryCast");
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
|
|
||||||
// helper for drawing a styled button for a GameObject or Transform
|
// helper for drawing a styled button for a GameObject or Transform
|
||||||
public static void GameobjButton(GameObject obj, Action<GameObject> specialInspectMethod = null, bool showSmallInspectBtn = true, float width = 380)
|
public static void GameobjButton(GameObject obj, Action<Transform> specialInspectMethod = null, bool showSmallInspectBtn = true, float width = 380)
|
||||||
{
|
{
|
||||||
bool children = obj.transform.childCount > 0;
|
bool children = obj.transform.childCount > 0;
|
||||||
|
|
||||||
@ -52,7 +52,7 @@ namespace Explorer
|
|||||||
FastGameobjButton(obj, color, label, obj.activeSelf, specialInspectMethod, showSmallInspectBtn, width);
|
FastGameobjButton(obj, color, label, obj.activeSelf, specialInspectMethod, showSmallInspectBtn, width);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void FastGameobjButton(GameObject obj, Color activeColor, string label, bool enabled, Action<GameObject> specialInspectMethod = null, bool showSmallInspectBtn = true, float width = 380)
|
public static void FastGameobjButton(GameObject obj, Color activeColor, string label, bool enabled, Action<Transform> specialInspectMethod = null, bool showSmallInspectBtn = true, float width = 380)
|
||||||
{
|
{
|
||||||
if (!obj)
|
if (!obj)
|
||||||
{
|
{
|
||||||
@ -79,7 +79,7 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
if (specialInspectMethod != null)
|
if (specialInspectMethod != null)
|
||||||
{
|
{
|
||||||
specialInspectMethod(obj);
|
specialInspectMethod(obj.transform);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -94,13 +94,18 @@ namespace Explorer
|
|||||||
|
|
||||||
if (showSmallInspectBtn)
|
if (showSmallInspectBtn)
|
||||||
{
|
{
|
||||||
if (GUILayout.Button("Inspect", null))
|
SmallInspectButton(obj);
|
||||||
{
|
|
||||||
WindowManager.InspectObject(obj, out bool _);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void SmallInspectButton(object obj)
|
||||||
|
{
|
||||||
|
if (GUILayout.Button("Inspect", null))
|
||||||
|
{
|
||||||
|
WindowManager.InspectObject(obj, out bool _);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -88,19 +88,6 @@ namespace Explorer
|
|||||||
|
|
||||||
private void MainHeader()
|
private void MainHeader()
|
||||||
{
|
{
|
||||||
GUILayout.BeginHorizontal(null);
|
|
||||||
GUILayout.Label("<b>Options:</b>", new GUILayoutOption[] { GUILayout.Width(70) });
|
|
||||||
GUI.skin.label.alignment = TextAnchor.MiddleRight;
|
|
||||||
GUILayout.Label("Array Limit:", new GUILayoutOption[] { GUILayout.Width(70) });
|
|
||||||
GUI.skin.label.alignment = TextAnchor.UpperLeft;
|
|
||||||
var _input = GUILayout.TextField(CppExplorer.ArrayLimit.ToString(), new GUILayoutOption[] { GUILayout.Width(60) });
|
|
||||||
if (int.TryParse(_input, out int _lim))
|
|
||||||
{
|
|
||||||
CppExplorer.ArrayLimit = _lim;
|
|
||||||
}
|
|
||||||
InspectUnderMouse.EnableInspect = GUILayout.Toggle(InspectUnderMouse.EnableInspect, "Inspect Under Mouse (Shift + RMB)", null);
|
|
||||||
GUILayout.EndHorizontal();
|
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(null);
|
||||||
for (int i = 0; i < Pages.Count; i++)
|
for (int i = 0; i < Pages.Count; i++)
|
||||||
{
|
{
|
||||||
@ -116,6 +103,9 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
|
GUI.color = Color.white;
|
||||||
|
InspectUnderMouse.EnableInspect = GUILayout.Toggle(InspectUnderMouse.EnableInspect, "Inspect Under Mouse (Shift + RMB)", null);
|
||||||
|
|
||||||
GUILayout.Space(10);
|
GUILayout.Space(10);
|
||||||
GUI.color = Color.white;
|
GUI.color = Color.white;
|
||||||
}
|
}
|
||||||
|
@ -14,9 +14,15 @@ namespace Explorer
|
|||||||
|
|
||||||
public override string Name { get => "Scene Explorer"; set => base.Name = value; }
|
public override string Name { get => "Scene Explorer"; set => base.Name = value; }
|
||||||
|
|
||||||
// ----- Holders for GUI elements ----- //
|
private int m_pageOffset = 0;
|
||||||
|
private int m_limit = 20;
|
||||||
|
private int m_currentTotalCount = 0;
|
||||||
|
|
||||||
private string m_currentScene = "";
|
private float m_timeOfLastUpdate = -1f;
|
||||||
|
|
||||||
|
// ----- Holders for GUI elements ----- //
|
||||||
|
|
||||||
|
private string m_currentScene = "";
|
||||||
|
|
||||||
// gameobject list
|
// gameobject list
|
||||||
private Transform m_currentTransform;
|
private Transform m_currentTransform;
|
||||||
@ -37,190 +43,84 @@ namespace Explorer
|
|||||||
public void OnSceneChange()
|
public void OnSceneChange()
|
||||||
{
|
{
|
||||||
m_currentScene = UnityHelpers.ActiveSceneName;
|
m_currentScene = UnityHelpers.ActiveSceneName;
|
||||||
|
SetTransformTarget(null);
|
||||||
|
}
|
||||||
|
|
||||||
m_currentTransform = null;
|
public void CheckOffset(ref int offset, int childCount)
|
||||||
CancelSearch();
|
{
|
||||||
|
if (offset >= childCount)
|
||||||
|
{
|
||||||
|
offset = 0;
|
||||||
|
m_pageOffset = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Update()
|
public override void Update()
|
||||||
{
|
{
|
||||||
if (!m_searching)
|
if (m_searching) return;
|
||||||
|
|
||||||
|
if (Time.time - m_timeOfLastUpdate < 1f) return;
|
||||||
|
m_timeOfLastUpdate = Time.time;
|
||||||
|
|
||||||
|
m_objectList = new List<GameObjectCache>();
|
||||||
|
int offset = m_pageOffset * m_limit;
|
||||||
|
|
||||||
|
var allTransforms = new List<Transform>();
|
||||||
|
|
||||||
|
// get current list of all transforms (either scene root or our current transform children)
|
||||||
|
if (m_currentTransform)
|
||||||
{
|
{
|
||||||
m_objectList = new List<GameObjectCache>();
|
for (int i = 0; i < m_currentTransform.childCount; i++)
|
||||||
if (m_currentTransform)
|
|
||||||
{
|
{
|
||||||
var endAppend = new List<GameObjectCache>();
|
allTransforms.Add(m_currentTransform.GetChild(i));
|
||||||
for (int i = 0; i < m_currentTransform.childCount; i++)
|
|
||||||
{
|
|
||||||
var child = m_currentTransform.GetChild(i);
|
|
||||||
|
|
||||||
if (child)
|
|
||||||
{
|
|
||||||
if (child.childCount > 0)
|
|
||||||
m_objectList.Add(new GameObjectCache(child.gameObject));
|
|
||||||
else
|
|
||||||
endAppend.Add(new GameObjectCache(child.gameObject));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m_objectList.AddRange(endAppend);
|
|
||||||
endAppend = null;
|
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var scene = SceneManager.GetSceneByName(m_currentScene);
|
||||||
|
var rootObjects = scene.GetRootGameObjects();
|
||||||
|
|
||||||
|
foreach (var obj in rootObjects)
|
||||||
{
|
{
|
||||||
var scene = SceneManager.GetSceneByName(m_currentScene);
|
allTransforms.Add(obj.transform);
|
||||||
var rootObjects = scene.GetRootGameObjects();
|
|
||||||
|
|
||||||
// add objects with children first
|
|
||||||
foreach (var obj in rootObjects.Where(x => x.transform.childCount > 0))
|
|
||||||
{
|
|
||||||
m_objectList.Add(new GameObjectCache(obj));
|
|
||||||
}
|
|
||||||
foreach (var obj in rootObjects.Where(x => x.transform.childCount == 0))
|
|
||||||
{
|
|
||||||
m_objectList.Add(new GameObjectCache(obj));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_currentTotalCount = allTransforms.Count;
|
||||||
|
|
||||||
|
// make sure offset doesn't exceed count
|
||||||
|
CheckOffset(ref offset, m_currentTotalCount);
|
||||||
|
|
||||||
|
// sort by childcount
|
||||||
|
allTransforms.Sort((a, b) => b.childCount.CompareTo(a.childCount));
|
||||||
|
|
||||||
|
for (int i = offset; i < offset + m_limit && i < m_currentTotalCount; i++)
|
||||||
|
{
|
||||||
|
var child = allTransforms[i];
|
||||||
|
m_objectList.Add(new GameObjectCache(child.gameObject));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------- GUI Draw Functions --------- //
|
public void SetTransformTarget(Transform t)
|
||||||
|
|
||||||
public override void DrawWindow()
|
|
||||||
{
|
{
|
||||||
try
|
m_currentTransform = t;
|
||||||
{
|
|
||||||
GUILayout.BeginHorizontal(null);
|
|
||||||
// Current Scene label
|
|
||||||
GUILayout.Label("Current Scene:", new GUILayoutOption[] { GUILayout.Width(120) });
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// Need to do 'ToList()' so the object isn't cleaned up by Il2Cpp GC.
|
|
||||||
var scenes = SceneManager.GetAllScenes().ToList();
|
|
||||||
|
|
||||||
if (scenes.Count > 1)
|
if (m_searching)
|
||||||
{
|
CancelSearch();
|
||||||
int changeWanted = 0;
|
|
||||||
if (GUILayout.Button("<", new GUILayoutOption[] { GUILayout.Width(30) }))
|
|
||||||
{
|
|
||||||
changeWanted = -1;
|
|
||||||
}
|
|
||||||
if (GUILayout.Button(">", new GUILayoutOption[] { GUILayout.Width(30) }))
|
|
||||||
{
|
|
||||||
changeWanted = 1;
|
|
||||||
}
|
|
||||||
if (changeWanted != 0)
|
|
||||||
{
|
|
||||||
int index = scenes.IndexOf(SceneManager.GetSceneByName(m_currentScene));
|
|
||||||
index += changeWanted;
|
|
||||||
if (index > scenes.Count - 1)
|
|
||||||
{
|
|
||||||
index = 0;
|
|
||||||
}
|
|
||||||
else if (index < 0)
|
|
||||||
{
|
|
||||||
index = scenes.Count - 1;
|
|
||||||
}
|
|
||||||
m_currentScene = scenes[index].name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch { }
|
|
||||||
GUILayout.Label("<color=cyan>" + m_currentScene + "</color>", null); //new GUILayoutOption[] { GUILayout.Width(250) });
|
|
||||||
|
|
||||||
GUILayout.EndHorizontal();
|
m_timeOfLastUpdate = -1f;
|
||||||
|
Update();
|
||||||
// ----- GameObject Search -----
|
|
||||||
GUILayout.BeginHorizontal(GUI.skin.box, null);
|
|
||||||
GUILayout.Label("<b>Search Scene:</b>", new GUILayoutOption[] { GUILayout.Width(100) });
|
|
||||||
m_searchInput = GUILayout.TextField(m_searchInput, null);
|
|
||||||
if (GUILayout.Button("Search", new GUILayoutOption[] { GUILayout.Width(80) }))
|
|
||||||
{
|
|
||||||
Search();
|
|
||||||
}
|
|
||||||
GUILayout.EndHorizontal();
|
|
||||||
|
|
||||||
GUILayout.Space(15);
|
|
||||||
|
|
||||||
// ************** GameObject list ***************
|
|
||||||
|
|
||||||
// ----- main explorer ------
|
|
||||||
if (!m_searching)
|
|
||||||
{
|
|
||||||
if (m_currentTransform != null)
|
|
||||||
{
|
|
||||||
GUILayout.BeginHorizontal(null);
|
|
||||||
if (GUILayout.Button("<-", new GUILayoutOption[] { GUILayout.Width(35) }))
|
|
||||||
{
|
|
||||||
TraverseUp();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
GUILayout.Label(m_currentTransform.GetGameObjectPath(), null);
|
|
||||||
}
|
|
||||||
GUILayout.EndHorizontal();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
GUILayout.Label("Scene Root GameObjects:", null);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_objectList.Count > 0)
|
|
||||||
{
|
|
||||||
foreach (var obj in m_objectList)
|
|
||||||
{
|
|
||||||
//UIStyles.GameobjButton(obj, SetTransformTarget, true, MainMenu.MainRect.width - 170);
|
|
||||||
UIHelpers.FastGameobjButton(obj.RefGameObject, obj.EnabledColor, obj.Label, obj.RefGameObject.activeSelf, SetTransformTarget, true, MainMenu.MainRect.width - 170);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else // ------ Scene Search results ------
|
|
||||||
{
|
|
||||||
if (GUILayout.Button("<-", new GUILayoutOption[] { GUILayout.Width(35) }))
|
|
||||||
{
|
|
||||||
CancelSearch();
|
|
||||||
}
|
|
||||||
|
|
||||||
GUILayout.Label("Search Results:", null);
|
|
||||||
|
|
||||||
if (m_searchResults.Count > 0)
|
|
||||||
{
|
|
||||||
foreach (var obj in m_searchResults)
|
|
||||||
{
|
|
||||||
//UIStyles.GameobjButton(obj, SetTransformTarget, true, MainMenu.MainRect.width - 170);
|
|
||||||
UIHelpers.FastGameobjButton(obj.RefGameObject, obj.EnabledColor, obj.Label, obj.RefGameObject.activeSelf, SetTransformTarget, true, MainMenu.MainRect.width - 170);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
GUILayout.Label("<color=red><i>No results found!</i></color>", null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
m_currentTransform = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// -------- Actual Methods (not drawing GUI) ---------- //
|
|
||||||
|
|
||||||
public void SetTransformTarget(GameObject obj)
|
|
||||||
{
|
|
||||||
m_currentTransform = obj.transform;
|
|
||||||
CancelSearch();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void TraverseUp()
|
public void TraverseUp()
|
||||||
{
|
{
|
||||||
if (m_currentTransform.parent != null)
|
if (m_currentTransform.parent != null)
|
||||||
{
|
{
|
||||||
m_currentTransform = m_currentTransform.parent;
|
SetTransformTarget(m_currentTransform.parent);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_currentTransform = null;
|
SetTransformTarget(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -228,6 +128,7 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
m_searchResults = SearchSceneObjects(m_searchInput);
|
m_searchResults = SearchSceneObjects(m_searchInput);
|
||||||
m_searching = true;
|
m_searching = true;
|
||||||
|
m_currentTotalCount = m_searchResults.Count;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CancelSearch()
|
public void CancelSearch()
|
||||||
@ -250,6 +151,220 @@ namespace Explorer
|
|||||||
return matches;
|
return matches;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --------- GUI Draw Function --------- //
|
||||||
|
|
||||||
|
public override void DrawWindow()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
DrawHeaderArea();
|
||||||
|
|
||||||
|
GUILayout.BeginVertical(GUI.skin.box, null);
|
||||||
|
|
||||||
|
DrawPageButtons();
|
||||||
|
|
||||||
|
if (!m_searching)
|
||||||
|
{
|
||||||
|
DrawGameObjectList();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DrawSearchResultsList();
|
||||||
|
}
|
||||||
|
|
||||||
|
GUILayout.EndVertical();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
MelonLogger.Log("Exception drawing ScenePage! " + e.GetType() + ", " + e.Message);
|
||||||
|
MelonLogger.Log(e.StackTrace);
|
||||||
|
m_currentTransform = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawHeaderArea()
|
||||||
|
{
|
||||||
|
GUILayout.BeginHorizontal(null);
|
||||||
|
|
||||||
|
// Current Scene label
|
||||||
|
GUILayout.Label("Current Scene:", new GUILayoutOption[] { GUILayout.Width(120) });
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Need to do 'ToList()' so the object isn't cleaned up by Il2Cpp GC.
|
||||||
|
var scenes = SceneManager.GetAllScenes().ToList();
|
||||||
|
|
||||||
|
if (scenes.Count > 1)
|
||||||
|
{
|
||||||
|
int changeWanted = 0;
|
||||||
|
if (GUILayout.Button("<", new GUILayoutOption[] { GUILayout.Width(30) }))
|
||||||
|
{
|
||||||
|
changeWanted = -1;
|
||||||
|
}
|
||||||
|
if (GUILayout.Button(">", new GUILayoutOption[] { GUILayout.Width(30) }))
|
||||||
|
{
|
||||||
|
changeWanted = 1;
|
||||||
|
}
|
||||||
|
if (changeWanted != 0)
|
||||||
|
{
|
||||||
|
int index = scenes.IndexOf(SceneManager.GetSceneByName(m_currentScene));
|
||||||
|
index += changeWanted;
|
||||||
|
if (index > scenes.Count - 1)
|
||||||
|
{
|
||||||
|
index = 0;
|
||||||
|
}
|
||||||
|
else if (index < 0)
|
||||||
|
{
|
||||||
|
index = scenes.Count - 1;
|
||||||
|
}
|
||||||
|
m_currentScene = scenes[index].name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
GUILayout.Label("<color=cyan>" + m_currentScene + "</color>", null); //new GUILayoutOption[] { GUILayout.Width(250) });
|
||||||
|
|
||||||
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
|
// ----- GameObject Search -----
|
||||||
|
GUILayout.BeginHorizontal(GUI.skin.box, null);
|
||||||
|
GUILayout.Label("<b>Search Scene:</b>", new GUILayoutOption[] { GUILayout.Width(100) });
|
||||||
|
m_searchInput = GUILayout.TextField(m_searchInput, null);
|
||||||
|
if (GUILayout.Button("Search", new GUILayoutOption[] { GUILayout.Width(80) }))
|
||||||
|
{
|
||||||
|
Search();
|
||||||
|
}
|
||||||
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
|
GUILayout.Space(5);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawPageButtons()
|
||||||
|
{
|
||||||
|
GUILayout.BeginHorizontal(null);
|
||||||
|
|
||||||
|
GUILayout.Label("Limit per page: ", new GUILayoutOption[] { GUILayout.Width(100) });
|
||||||
|
var limit = m_limit.ToString();
|
||||||
|
limit = GUILayout.TextField(limit, new GUILayoutOption[] { GUILayout.Width(30) });
|
||||||
|
if (int.TryParse(limit, out int lim))
|
||||||
|
{
|
||||||
|
m_limit = lim;
|
||||||
|
}
|
||||||
|
|
||||||
|
// prev/next page buttons
|
||||||
|
if (m_currentTotalCount > m_limit)
|
||||||
|
{
|
||||||
|
int count = m_currentTotalCount;
|
||||||
|
int maxOffset = (int)Mathf.Ceil((float)(count / (decimal)m_limit)) - 1;
|
||||||
|
if (GUILayout.Button("< Prev", null))
|
||||||
|
{
|
||||||
|
if (m_pageOffset > 0) m_pageOffset--;
|
||||||
|
m_timeOfLastUpdate = -1f;
|
||||||
|
Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
|
||||||
|
GUILayout.Label($"Page {m_pageOffset + 1}/{maxOffset + 1}", new GUILayoutOption[] { GUILayout.Width(80) });
|
||||||
|
|
||||||
|
if (GUILayout.Button("Next >", null))
|
||||||
|
{
|
||||||
|
if (m_pageOffset < maxOffset) m_pageOffset++;
|
||||||
|
m_timeOfLastUpdate = -1f;
|
||||||
|
Update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GUILayout.EndHorizontal();
|
||||||
|
GUI.skin.label.alignment = TextAnchor.UpperLeft;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawGameObjectList()
|
||||||
|
{
|
||||||
|
if (m_currentTransform != null)
|
||||||
|
{
|
||||||
|
GUILayout.BeginHorizontal(null);
|
||||||
|
if (GUILayout.Button("<-", new GUILayoutOption[] { GUILayout.Width(35) }))
|
||||||
|
{
|
||||||
|
TraverseUp();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GUILayout.Label("<color=cyan>" + m_currentTransform.GetGameObjectPath() + "</color>",
|
||||||
|
new GUILayoutOption[] { GUILayout.Width(MainMenu.MainRect.width - 187f) });
|
||||||
|
}
|
||||||
|
|
||||||
|
UIHelpers.SmallInspectButton(m_currentTransform);
|
||||||
|
|
||||||
|
GUILayout.EndHorizontal();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GUILayout.Label("Scene Root GameObjects:", null);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_objectList.Count > 0)
|
||||||
|
{
|
||||||
|
foreach (var obj in m_objectList)
|
||||||
|
{
|
||||||
|
if (!obj.RefGameObject)
|
||||||
|
{
|
||||||
|
string label = "<color=red><i>null";
|
||||||
|
|
||||||
|
if (obj.RefGameObject != null)
|
||||||
|
{
|
||||||
|
label += " (Destroyed)";
|
||||||
|
}
|
||||||
|
|
||||||
|
label += "</i></color>";
|
||||||
|
GUILayout.Label(label, null);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UIHelpers.FastGameobjButton(obj.RefGameObject,
|
||||||
|
obj.EnabledColor,
|
||||||
|
obj.Label,
|
||||||
|
obj.RefGameObject.activeSelf,
|
||||||
|
SetTransformTarget,
|
||||||
|
true,
|
||||||
|
MainMenu.MainRect.width - 170);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawSearchResultsList()
|
||||||
|
{
|
||||||
|
if (GUILayout.Button("<- Cancel Search", new GUILayoutOption[] { GUILayout.Width(150) }))
|
||||||
|
{
|
||||||
|
CancelSearch();
|
||||||
|
}
|
||||||
|
|
||||||
|
GUILayout.Label("Search Results:", null);
|
||||||
|
|
||||||
|
if (m_searchResults.Count > 0)
|
||||||
|
{
|
||||||
|
int offset = m_pageOffset * m_limit;
|
||||||
|
|
||||||
|
if (offset >= m_searchResults.Count)
|
||||||
|
{
|
||||||
|
offset = 0;
|
||||||
|
m_pageOffset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = offset; i < offset + m_limit && offset < m_searchResults.Count; i++)
|
||||||
|
{
|
||||||
|
var obj = m_searchResults[i];
|
||||||
|
|
||||||
|
UIHelpers.FastGameobjButton(obj.RefGameObject, obj.EnabledColor, obj.Label, obj.RefGameObject.activeSelf, SetTransformTarget, true, MainMenu.MainRect.width - 170);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GUILayout.Label("<color=red><i>No results found!</i></color>", null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------- Mini GameObjectCache class ---------- //
|
||||||
|
|
||||||
public class GameObjectCache
|
public class GameObjectCache
|
||||||
{
|
{
|
||||||
public GameObject RefGameObject;
|
public GameObject RefGameObject;
|
||||||
|
@ -135,7 +135,7 @@ namespace Explorer
|
|||||||
int offset = m_pageOffset * this.m_limit;
|
int offset = m_pageOffset * this.m_limit;
|
||||||
if (offset >= count) m_pageOffset = 0;
|
if (offset >= count) m_pageOffset = 0;
|
||||||
|
|
||||||
for (int i = offset; i < offset + CppExplorer.ArrayLimit && i < count; i++)
|
for (int i = offset; i < offset + m_limit && i < count; i++)
|
||||||
{
|
{
|
||||||
m_searchResults[i].Draw(MainMenu.MainRect, 0f);
|
m_searchResults[i].Draw(MainMenu.MainRect, 0f);
|
||||||
//m_searchResults[i].DrawValue(MainMenu.MainRect);
|
//m_searchResults[i].DrawValue(MainMenu.MainRect);
|
||||||
|
@ -29,7 +29,7 @@ namespace Explorer
|
|||||||
private float m_rotateAmount = 50f;
|
private float m_rotateAmount = 50f;
|
||||||
private float m_scaleAmount = 0.1f;
|
private float m_scaleAmount = 0.1f;
|
||||||
|
|
||||||
List<Component> m_cachedDestroyList = new List<Component>();
|
private List<Component> m_cachedDestroyList = new List<Component>();
|
||||||
//private string m_addComponentInput = "";
|
//private string m_addComponentInput = "";
|
||||||
|
|
||||||
private string m_setParentInput = "";
|
private string m_setParentInput = "";
|
||||||
@ -91,7 +91,7 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InspectGameObject(GameObject obj)
|
private void InspectGameObject(Transform obj)
|
||||||
{
|
{
|
||||||
var window = WindowManager.InspectObject(obj, out bool created);
|
var window = WindowManager.InspectObject(obj, out bool created);
|
||||||
|
|
||||||
@ -137,7 +137,7 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
if (GUILayout.Button("<color=#00FF00>< View in Scene Explorer</color>", new GUILayoutOption[] { GUILayout.Width(230) }))
|
if (GUILayout.Button("<color=#00FF00>< View in Scene Explorer</color>", new GUILayoutOption[] { GUILayout.Width(230) }))
|
||||||
{
|
{
|
||||||
ScenePage.Instance.SetTransformTarget(m_object);
|
ScenePage.Instance.SetTransformTarget(m_object.transform);
|
||||||
MainMenu.SetCurrentPage(0);
|
MainMenu.SetCurrentPage(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -150,7 +150,7 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
if (GUILayout.Button("<-", new GUILayoutOption[] { GUILayout.Width(35) }))
|
if (GUILayout.Button("<-", new GUILayoutOption[] { GUILayout.Width(35) }))
|
||||||
{
|
{
|
||||||
InspectGameObject(m_object.transform.parent.gameObject);
|
InspectGameObject(m_object.transform.parent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
GUILayout.TextArea(pathlabel, null);
|
GUILayout.TextArea(pathlabel, null);
|
||||||
@ -235,18 +235,16 @@ namespace Explorer
|
|||||||
var m_components = new Il2CppSystem.Collections.Generic.List<Component>();
|
var m_components = new Il2CppSystem.Collections.Generic.List<Component>();
|
||||||
m_object.GetComponentsInternal(Il2CppType.Of<Component>(), false, false, true, false, m_components);
|
m_object.GetComponentsInternal(Il2CppType.Of<Component>(), false, false, true, false, m_components);
|
||||||
|
|
||||||
var ilTypeOfTransform = Il2CppType.Of<Transform>();
|
|
||||||
var ilTypeOfBehaviour = Il2CppType.Of<Behaviour>();
|
|
||||||
foreach (var component in m_components)
|
foreach (var component in m_components)
|
||||||
{
|
{
|
||||||
var ilType = component.GetIl2CppType();
|
var ilType = component.GetIl2CppType();
|
||||||
if (ilType == ilTypeOfTransform)
|
if (ilType == ReflectionHelpers.TransformType)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(null);
|
||||||
if (ilTypeOfBehaviour.IsAssignableFrom(ilType))
|
if (ReflectionHelpers.BehaviourType.IsAssignableFrom(ilType))
|
||||||
{
|
{
|
||||||
BehaviourEnabledBtn(component.TryCast<Behaviour>());
|
BehaviourEnabledBtn(component.TryCast<Behaviour>());
|
||||||
}
|
}
|
||||||
@ -274,24 +272,6 @@ namespace Explorer
|
|||||||
|
|
||||||
GUILayout.EndScrollView();
|
GUILayout.EndScrollView();
|
||||||
|
|
||||||
//GUILayout.BeginHorizontal(null);
|
|
||||||
//m_addComponentInput = GUILayout.TextField(m_addComponentInput, new GUILayoutOption[] { GUILayout.Width(m_rect.width / 2 - 150) });
|
|
||||||
//if (GUILayout.Button("Add Component", new GUILayoutOption[] { GUILayout.Width(120) }))
|
|
||||||
//{
|
|
||||||
// if (HPExplorer.GetType(m_addComponentInput) is Type type && typeof(Component).IsAssignableFrom(type))
|
|
||||||
// {
|
|
||||||
// var comp = m_object.AddComponent(type);
|
|
||||||
// var list = m_components.ToList();
|
|
||||||
// list.Add(comp);
|
|
||||||
// m_components = list.ToArray();
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// MelonLogger.LogWarning($"Could not get type '{m_addComponentInput}'. If it's not a typo, try the fully qualified name.");
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
//GUILayout.EndHorizontal();
|
|
||||||
|
|
||||||
GUILayout.EndVertical();
|
GUILayout.EndVertical();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ namespace Explorer
|
|||||||
private bool m_autoUpdate = false;
|
private bool m_autoUpdate = false;
|
||||||
private string m_search = "";
|
private string m_search = "";
|
||||||
public MemberInfoType m_filter = MemberInfoType.Property;
|
public MemberInfoType m_filter = MemberInfoType.Property;
|
||||||
private bool m_hideFailedReflection = true;
|
private bool m_hideFailedReflection = false;
|
||||||
|
|
||||||
public enum MemberInfoType
|
public enum MemberInfoType
|
||||||
{
|
{
|
||||||
@ -135,13 +135,25 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
if (member.Name == "Il2CppType") continue;
|
if (member.Name == "Il2CppType") continue;
|
||||||
|
|
||||||
var name = member.DeclaringType.Name + "." + member.Name;
|
try
|
||||||
if (names.Contains(name)) continue;
|
{
|
||||||
names.Add(name);
|
var name = member.DeclaringType.Name + "." + member.Name;
|
||||||
|
if (names.Contains(name)) continue;
|
||||||
|
names.Add(name);
|
||||||
|
|
||||||
var cached = CacheObject.GetCacheObject(null, member, target);
|
var cached = CacheObject.GetCacheObject(null, member, target);
|
||||||
list.Add(cached);
|
if (cached != null)
|
||||||
cached.ReflectionException = exception;
|
{
|
||||||
|
list.Add(cached);
|
||||||
|
cached.ReflectionException = exception;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
MelonLogger.Log("Exception caching member!");
|
||||||
|
MelonLogger.Log(e.GetType() + ", " + e.Message);
|
||||||
|
MelonLogger.Log(e.StackTrace);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -160,7 +172,7 @@ namespace Explorer
|
|||||||
GUILayout.BeginArea(new Rect(5, 25, m_rect.width - 10, m_rect.height - 35), GUI.skin.box);
|
GUILayout.BeginArea(new Rect(5, 25, m_rect.width - 10, m_rect.height - 35), GUI.skin.box);
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(null);
|
||||||
GUILayout.Label("<b>Type:</b> <color=cyan>" + ObjectType.Name + "</color>", null);
|
GUILayout.Label("<b>Type:</b> <color=cyan>" + ObjectType.FullName + "</color>", null);
|
||||||
|
|
||||||
bool unityObj = Target is UnityEngine.Object;
|
bool unityObj = Target is UnityEngine.Object;
|
||||||
|
|
||||||
@ -238,6 +250,7 @@ namespace Explorer
|
|||||||
if (GUILayout.Button("< Prev", null))
|
if (GUILayout.Button("< Prev", null))
|
||||||
{
|
{
|
||||||
if (m_pageOffset > 0) m_pageOffset--;
|
if (m_pageOffset > 0) m_pageOffset--;
|
||||||
|
scroll = Vector2.zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
GUILayout.Label($"Page {m_pageOffset + 1}/{maxOffset + 1}", new GUILayoutOption[] { GUILayout.Width(80) });
|
GUILayout.Label($"Page {m_pageOffset + 1}/{maxOffset + 1}", new GUILayoutOption[] { GUILayout.Width(80) });
|
||||||
@ -245,6 +258,7 @@ namespace Explorer
|
|||||||
if (GUILayout.Button("Next >", null))
|
if (GUILayout.Button("Next >", null))
|
||||||
{
|
{
|
||||||
if (m_pageOffset < maxOffset) m_pageOffset++;
|
if (m_pageOffset < maxOffset) m_pageOffset++;
|
||||||
|
scroll = Vector2.zero;
|
||||||
}
|
}
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
}
|
}
|
||||||
|
@ -104,7 +104,7 @@ namespace Explorer
|
|||||||
|
|
||||||
foreach (var window in Windows)
|
foreach (var window in Windows)
|
||||||
{
|
{
|
||||||
if (obj == window.Target)
|
if (ReferenceEquals(obj, window.Target))
|
||||||
{
|
{
|
||||||
GUI.BringWindowToFront(window.windowID);
|
GUI.BringWindowToFront(window.windowID);
|
||||||
GUI.FocusWindow(window.windowID);
|
GUI.FocusWindow(window.windowID);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user