mirror of
https://github.com/sinai-dev/UnityExplorer.git
synced 2025-06-15 22:07:48 +08:00
1.31
- various performance improvements - by default, lists and arrays are now collapsed, use the "v" button to expand them. - added error handling for a TypeLoadException which can happen with some generic types.
This commit is contained in:
parent
e8b17d3583
commit
7144b6a44c
@ -16,7 +16,7 @@ namespace Explorer
|
|||||||
|
|
||||||
public const string ID = "com.sinai.cppexplorer";
|
public const string ID = "com.sinai.cppexplorer";
|
||||||
public const string NAME = "IL2CPP Runtime Explorer";
|
public const string NAME = "IL2CPP Runtime Explorer";
|
||||||
public const string VERSION = "1.3.0";
|
public const string VERSION = "1.3.1";
|
||||||
public const string AUTHOR = "Sinai";
|
public const string AUTHOR = "Sinai";
|
||||||
|
|
||||||
// fields
|
// fields
|
||||||
|
@ -112,7 +112,6 @@
|
|||||||
</Reference>
|
</Reference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="ILBehaviour.cs" />
|
|
||||||
<Compile Include="CppExplorer.cs" />
|
<Compile Include="CppExplorer.cs" />
|
||||||
<Compile Include="MainMenu\Pages\ConsolePage.cs" />
|
<Compile Include="MainMenu\Pages\ConsolePage.cs" />
|
||||||
<Compile Include="MainMenu\Pages\Console\REPL.cs" />
|
<Compile Include="MainMenu\Pages\Console\REPL.cs" />
|
||||||
|
@ -1,33 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using UnityEngine;
|
|
||||||
using MelonLoader;
|
|
||||||
using UnhollowerRuntimeLib;
|
|
||||||
|
|
||||||
namespace Explorer
|
|
||||||
{
|
|
||||||
//public class ILBehaviour : MonoBehaviour
|
|
||||||
//{
|
|
||||||
// public ILBehaviour(IntPtr intPtr) : base(intPtr) { }
|
|
||||||
|
|
||||||
// public static T AddToGameObject<T>(GameObject _go) where T : ILBehaviour
|
|
||||||
// {
|
|
||||||
// Il2CppSystem.Type ilType = UnhollowerRuntimeLib.Il2CppType.Of<T>();
|
|
||||||
|
|
||||||
// if (ilType == null)
|
|
||||||
// {
|
|
||||||
// MelonLogger.Log("Error - could not get MB as ilType");
|
|
||||||
// return null;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// var obj = typeof(T)
|
|
||||||
// .GetConstructor(new Type[] { typeof(IntPtr) })
|
|
||||||
// .Invoke(new object[] { _go.AddComponent(UnhollowerRuntimeLib.Il2CppType.Of<T>()).Pointer });
|
|
||||||
|
|
||||||
// return (T)obj;
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
}
|
|
@ -93,9 +93,13 @@ namespace Explorer
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_objectType = type;
|
try
|
||||||
GetFields(m_object);
|
{
|
||||||
GetProperties(m_object);
|
m_objectType = type;
|
||||||
|
GetFields(m_object);
|
||||||
|
GetProperties(m_object);
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
|
||||||
UpdateValues();
|
UpdateValues();
|
||||||
}
|
}
|
||||||
@ -276,7 +280,7 @@ namespace Explorer
|
|||||||
|
|
||||||
public static bool IsList(Type t)
|
public static bool IsList(Type t)
|
||||||
{
|
{
|
||||||
return t.IsGenericType
|
return t.IsGenericType
|
||||||
&& t.GetGenericTypeDefinition() is Type typeDef
|
&& t.GetGenericTypeDefinition() is Type typeDef
|
||||||
&& (typeDef.IsAssignableFrom(typeof(List<>)) || typeDef.IsAssignableFrom(typeof(Il2CppSystem.Collections.Generic.List<>)));
|
&& (typeDef.IsAssignableFrom(typeof(List<>)) || typeDef.IsAssignableFrom(typeof(Il2CppSystem.Collections.Generic.List<>)));
|
||||||
}
|
}
|
||||||
@ -292,8 +296,20 @@ namespace Explorer
|
|||||||
|
|
||||||
foreach (var type in types)
|
foreach (var type in types)
|
||||||
{
|
{
|
||||||
foreach (var pi in type.GetProperties(At.flags))
|
PropertyInfo[] propInfos = new PropertyInfo[0];
|
||||||
|
|
||||||
|
try
|
||||||
{
|
{
|
||||||
|
propInfos = type.GetProperties(At.flags);
|
||||||
|
}
|
||||||
|
catch (TypeLoadException)
|
||||||
|
{
|
||||||
|
MelonLogger.Log($"Couldn't get Properties for Type '{type.Name}', it may not support Il2Cpp Reflection at the moment.");
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var pi in propInfos)
|
||||||
|
{
|
||||||
|
// this member causes a crash when inspected, so just skipping it for now.
|
||||||
if (pi.Name == "Il2CppType")
|
if (pi.Name == "Il2CppType")
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
@ -335,7 +351,7 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* *********************
|
/* *********************
|
||||||
* PROPERTYINFO HOLDER
|
* PROPERTYINFO HOLDER
|
||||||
@ -346,6 +362,7 @@ namespace Explorer
|
|||||||
public Type classType;
|
public Type classType;
|
||||||
public PropertyInfo propInfo;
|
public PropertyInfo propInfo;
|
||||||
public object m_value;
|
public object m_value;
|
||||||
|
public bool IsExpanded;
|
||||||
|
|
||||||
public PropertyInfoHolder(Type _type, PropertyInfo _propInfo)
|
public PropertyInfoHolder(Type _type, PropertyInfo _propInfo)
|
||||||
{
|
{
|
||||||
@ -355,14 +372,7 @@ namespace Explorer
|
|||||||
|
|
||||||
public void Draw(ReflectionWindow window)
|
public void Draw(ReflectionWindow window)
|
||||||
{
|
{
|
||||||
if (propInfo.CanWrite)
|
UIStyles.DrawMember(ref m_value, ref this.IsExpanded, this.propInfo, window.m_rect, window.m_object, SetValue);
|
||||||
{
|
|
||||||
UIStyles.DrawMember(ref m_value, propInfo.PropertyType.Name, propInfo.Name, window.m_rect, window.m_object, SetValue);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UIStyles.DrawMember(ref m_value, propInfo.PropertyType.Name, propInfo.Name, window.m_rect, window.m_object);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateValue(object obj)
|
public void UpdateValue(object obj)
|
||||||
@ -389,15 +399,15 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
//MelonLogger.Log("Exception on PropertyInfoHolder.UpdateValue, Name: " + this.propInfo.Name);
|
MelonLogger.Log("Exception on PropertyInfoHolder.UpdateValue, Name: " + this.propInfo.Name);
|
||||||
//MelonLogger.Log(e.GetType() + ", " + e.Message);
|
MelonLogger.Log(e.GetType() + ", " + e.Message);
|
||||||
|
|
||||||
//var inner = e.InnerException;
|
var inner = e.InnerException;
|
||||||
//while (inner != null)
|
while (inner != null)
|
||||||
//{
|
{
|
||||||
// MelonLogger.Log("inner: " + inner.GetType() + ", " + inner.Message);
|
MelonLogger.Log("inner: " + inner.GetType() + ", " + inner.Message);
|
||||||
// inner = inner.InnerException;
|
inner = inner.InnerException;
|
||||||
//}
|
}
|
||||||
|
|
||||||
m_value = null;
|
m_value = null;
|
||||||
}
|
}
|
||||||
@ -473,6 +483,7 @@ namespace Explorer
|
|||||||
public Type classType;
|
public Type classType;
|
||||||
public FieldInfo fieldInfo;
|
public FieldInfo fieldInfo;
|
||||||
public object m_value;
|
public object m_value;
|
||||||
|
public bool IsExpanded;
|
||||||
|
|
||||||
public FieldInfoHolder(Type _type, FieldInfo _fieldInfo)
|
public FieldInfoHolder(Type _type, FieldInfo _fieldInfo)
|
||||||
{
|
{
|
||||||
@ -487,16 +498,7 @@ namespace Explorer
|
|||||||
|
|
||||||
public void Draw(ReflectionWindow window)
|
public void Draw(ReflectionWindow window)
|
||||||
{
|
{
|
||||||
bool canSet = !(fieldInfo.IsLiteral && !fieldInfo.IsInitOnly);
|
UIStyles.DrawMember(ref m_value, ref this.IsExpanded, this.fieldInfo, window.m_rect, window.m_object, SetValue);
|
||||||
|
|
||||||
if (canSet)
|
|
||||||
{
|
|
||||||
UIStyles.DrawMember(ref m_value, fieldInfo.FieldType.Name, fieldInfo.Name, window.m_rect, window.m_object, SetValue);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UIStyles.DrawMember(ref m_value, fieldInfo.FieldType.Name, fieldInfo.Name, window.m_rect, window.m_object);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetValue(object obj)
|
public void SetValue(object obj)
|
||||||
|
@ -36,17 +36,17 @@ namespace Explorer
|
|||||||
return MB.FindAll<T>();
|
return MB.FindAll<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Documentation("runCoroutine(enumerator) - runs an IEnumerator as a Unity coroutine.")]
|
//[Documentation("runCoroutine(enumerator) - runs an IEnumerator as a Unity coroutine.")]
|
||||||
public static object runCoroutine(IEnumerator i)
|
//public static object runCoroutine(IEnumerator i)
|
||||||
{
|
//{
|
||||||
return MB.RunCoroutine(i);
|
// return MB.RunCoroutine(i);
|
||||||
}
|
//}
|
||||||
|
|
||||||
[Documentation("endCoroutine(co) - ends a Unity coroutine.")]
|
//[Documentation("endCoroutine(co) - ends a Unity coroutine.")]
|
||||||
public static void endCoroutine(Coroutine c)
|
//public static void endCoroutine(Coroutine c)
|
||||||
{
|
//{
|
||||||
MB.EndCoroutine(c);
|
// MB.EndCoroutine(c);
|
||||||
}
|
//}
|
||||||
|
|
||||||
////[Documentation("type<T>() - obtain type info about a type T. Provides some Reflection helpers.")]
|
////[Documentation("type<T>() - obtain type info about a type T. Provides some Reflection helpers.")]
|
||||||
////public static TypeHelper type<T>()
|
////public static TypeHelper type<T>()
|
||||||
|
@ -21,14 +21,14 @@ namespace Explorer
|
|||||||
return FindObjectsOfType<T>();
|
return FindObjectsOfType<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public object RunCoroutine(IEnumerator enumerator)
|
//public object RunCoroutine(IEnumerator enumerator)
|
||||||
{
|
//{
|
||||||
return MelonCoroutines.Start(enumerator);
|
// return MelonCoroutines.Start(enumerator);
|
||||||
}
|
//}
|
||||||
|
|
||||||
public void EndCoroutine(Coroutine c)
|
//public void EndCoroutine(Coroutine c)
|
||||||
{
|
//{
|
||||||
StopCoroutine(c);
|
// StopCoroutine(c);
|
||||||
}
|
//}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -20,12 +20,13 @@ namespace Explorer
|
|||||||
|
|
||||||
// gameobject list
|
// gameobject list
|
||||||
private Transform m_currentTransform;
|
private Transform m_currentTransform;
|
||||||
private List<GameObject> m_objectList = new List<GameObject>();
|
private List<GameObjectCache> m_objectList = new List<GameObjectCache>();
|
||||||
|
private float m_timeOfLastUpdate = -1f;
|
||||||
|
|
||||||
// search bar
|
// search bar
|
||||||
private bool m_searching = false;
|
private bool m_searching = false;
|
||||||
private string m_searchInput = "";
|
private string m_searchInput = "";
|
||||||
private List<GameObject> m_searchResults = new List<GameObject>();
|
private List<GameObjectCache> m_searchResults = new List<GameObjectCache>();
|
||||||
|
|
||||||
// ------------ Init and Update ------------ //
|
// ------------ Init and Update ------------ //
|
||||||
|
|
||||||
@ -40,17 +41,24 @@ namespace Explorer
|
|||||||
|
|
||||||
m_currentTransform = null;
|
m_currentTransform = null;
|
||||||
CancelSearch();
|
CancelSearch();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Update()
|
public override void Update()
|
||||||
{
|
{
|
||||||
|
if (Time.time - m_timeOfLastUpdate < 1f)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_timeOfLastUpdate = Time.time;
|
||||||
|
|
||||||
|
var start = Time.realtimeSinceStartup;
|
||||||
|
|
||||||
if (!m_searching)
|
if (!m_searching)
|
||||||
{
|
{
|
||||||
m_objectList = new List<GameObject>();
|
m_objectList = new List<GameObjectCache>();
|
||||||
if (m_currentTransform)
|
if (m_currentTransform)
|
||||||
{
|
{
|
||||||
var noChildren = new List<GameObject>();
|
var endAppend = new List<GameObjectCache>();
|
||||||
for (int i = 0; i < m_currentTransform.childCount; i++)
|
for (int i = 0; i < m_currentTransform.childCount; i++)
|
||||||
{
|
{
|
||||||
var child = m_currentTransform.GetChild(i);
|
var child = m_currentTransform.GetChild(i);
|
||||||
@ -58,13 +66,13 @@ namespace Explorer
|
|||||||
if (child)
|
if (child)
|
||||||
{
|
{
|
||||||
if (child.childCount > 0)
|
if (child.childCount > 0)
|
||||||
m_objectList.Add(child.gameObject);
|
m_objectList.Add(new GameObjectCache(child.gameObject));
|
||||||
else
|
else
|
||||||
noChildren.Add(child.gameObject);
|
endAppend.Add(new GameObjectCache(child.gameObject));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_objectList.AddRange(noChildren);
|
m_objectList.AddRange(endAppend);
|
||||||
noChildren = null;
|
endAppend = null;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -74,11 +82,11 @@ namespace Explorer
|
|||||||
// add objects with children first
|
// add objects with children first
|
||||||
foreach (var obj in rootObjects.Where(x => x.transform.childCount > 0))
|
foreach (var obj in rootObjects.Where(x => x.transform.childCount > 0))
|
||||||
{
|
{
|
||||||
m_objectList.Add(obj);
|
m_objectList.Add(new GameObjectCache(obj));
|
||||||
}
|
}
|
||||||
foreach (var obj in rootObjects.Where(x => x.transform.childCount == 0))
|
foreach (var obj in rootObjects.Where(x => x.transform.childCount == 0))
|
||||||
{
|
{
|
||||||
m_objectList.Add(obj);
|
m_objectList.Add(new GameObjectCache(obj));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -161,10 +169,13 @@ namespace Explorer
|
|||||||
|
|
||||||
if (m_objectList.Count > 0)
|
if (m_objectList.Count > 0)
|
||||||
{
|
{
|
||||||
|
var start = Time.realtimeSinceStartup;
|
||||||
foreach (var obj in m_objectList)
|
foreach (var obj in m_objectList)
|
||||||
{
|
{
|
||||||
UIStyles.GameobjButton(obj, SetTransformTarget, true, MainMenu.MainRect.width - 170);
|
//UIStyles.GameobjButton(obj, SetTransformTarget, true, MainMenu.MainRect.width - 170);
|
||||||
|
UIStyles.FastGameobjButton(obj.RefGameObject, obj.EnabledColor, obj.Label, obj.RefGameObject.activeSelf, SetTransformTarget, true, MainMenu.MainRect.width - 170);
|
||||||
}
|
}
|
||||||
|
var diff = Time.realtimeSinceStartup - start;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -184,7 +195,8 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
foreach (var obj in m_searchResults)
|
foreach (var obj in m_searchResults)
|
||||||
{
|
{
|
||||||
UIStyles.GameobjButton(obj, SetTransformTarget, true, MainMenu.MainRect.width - 170);
|
//UIStyles.GameobjButton(obj, SetTransformTarget, true, MainMenu.MainRect.width - 170);
|
||||||
|
UIStyles.FastGameobjButton(obj.RefGameObject, obj.EnabledColor, obj.Label, obj.RefGameObject.activeSelf, SetTransformTarget, true, MainMenu.MainRect.width - 170);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -232,19 +244,54 @@ namespace Explorer
|
|||||||
m_searching = false;
|
m_searching = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<GameObject> SearchSceneObjects(string _search)
|
public List<GameObjectCache> SearchSceneObjects(string _search)
|
||||||
{
|
{
|
||||||
var matches = new List<GameObject>();
|
var matches = new List<GameObjectCache>();
|
||||||
|
|
||||||
foreach (var obj in Resources.FindObjectsOfTypeAll<GameObject>())
|
foreach (var obj in Resources.FindObjectsOfTypeAll<GameObject>())
|
||||||
{
|
{
|
||||||
if (obj.name.ToLower().Contains(_search.ToLower()) && obj.scene.name == m_currentScene)
|
if (obj.name.ToLower().Contains(_search.ToLower()) && obj.scene.name == m_currentScene)
|
||||||
{
|
{
|
||||||
matches.Add(obj);
|
matches.Add(new GameObjectCache(obj));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return matches;
|
return matches;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class GameObjectCache
|
||||||
|
{
|
||||||
|
public GameObject RefGameObject;
|
||||||
|
public string Label;
|
||||||
|
public Color EnabledColor;
|
||||||
|
public int ChildCount;
|
||||||
|
|
||||||
|
public GameObjectCache(GameObject obj)
|
||||||
|
{
|
||||||
|
RefGameObject = obj;
|
||||||
|
ChildCount = obj.transform.childCount;
|
||||||
|
|
||||||
|
Label = (ChildCount > 0) ? "[" + obj.transform.childCount + " children] " : "";
|
||||||
|
Label += obj.name;
|
||||||
|
|
||||||
|
bool enabled = obj.activeSelf;
|
||||||
|
int childCount = obj.transform.childCount;
|
||||||
|
if (enabled)
|
||||||
|
{
|
||||||
|
if (childCount > 0)
|
||||||
|
{
|
||||||
|
EnabledColor = Color.green;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
EnabledColor = UIStyles.LightGreen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
EnabledColor = Color.red;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -91,7 +91,8 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
var obj = m_searchResults[i];
|
var obj = m_searchResults[i];
|
||||||
|
|
||||||
UIStyles.DrawValue(ref obj, _temprect);
|
bool _ = false;
|
||||||
|
UIStyles.DrawValue(ref obj, _temprect, ref _);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -262,7 +263,6 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
var findType = CppExplorer.GetType(_type);
|
var findType = CppExplorer.GetType(_type);
|
||||||
type = Il2CppSystem.Type.GetType(findType.AssemblyQualifiedName);
|
type = Il2CppSystem.Type.GetType(findType.AssemblyQualifiedName);
|
||||||
MelonLogger.Log("Got type: " + type.AssemblyQualifiedName);
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
301
src/UIStyles.cs
301
src/UIStyles.cs
@ -5,7 +5,7 @@ using System.Linq;
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Il2CppSystem.Collections;
|
using Il2CppSystem.Collections;
|
||||||
using Il2CppSystem.Reflection;
|
//using Il2CppSystem.Reflection;
|
||||||
using MelonLoader;
|
using MelonLoader;
|
||||||
using UnhollowerBaseLib;
|
using UnhollowerBaseLib;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
@ -15,6 +15,8 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
public class UIStyles
|
public class UIStyles
|
||||||
{
|
{
|
||||||
|
public static Color LightGreen = new Color(Color.green.r - 0.3f, Color.green.g - 0.3f, Color.green.b - 0.3f);
|
||||||
|
|
||||||
public static GUISkin WindowSkin
|
public static GUISkin WindowSkin
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@ -115,42 +117,48 @@ 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<GameObject> specialInspectMethod = null, bool showSmallInspectBtn = true, float width = 380)
|
||||||
{
|
{
|
||||||
if (obj == null)
|
bool children = obj.transform.childCount > 0;
|
||||||
|
|
||||||
|
string label = children ? "[" + obj.transform.childCount + " children] " : "";
|
||||||
|
label += obj.name;
|
||||||
|
|
||||||
|
bool enabled = obj.activeSelf;
|
||||||
|
int childCount = obj.transform.childCount;
|
||||||
|
Color color;
|
||||||
|
|
||||||
|
if (enabled)
|
||||||
|
{
|
||||||
|
if (childCount > 0)
|
||||||
|
{
|
||||||
|
color = Color.green;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
color = LightGreen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
color = Color.red;
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
if (!obj)
|
||||||
{
|
{
|
||||||
GUILayout.Label("<i><color=red>null</color></i>", null);
|
GUILayout.Label("<i><color=red>null</color></i>", null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool enabled = obj.activeSelf;
|
// ------ toggle active button ------
|
||||||
bool children = obj.transform.childCount > 0;
|
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(null);
|
||||||
GUI.skin.button.alignment = TextAnchor.UpperLeft;
|
GUI.skin.button.alignment = TextAnchor.UpperLeft;
|
||||||
|
|
||||||
// ------ build name ------
|
GUI.color = activeColor;
|
||||||
|
|
||||||
string label = children ? "[" + obj.transform.childCount + " children] " : "";
|
|
||||||
label += obj.name;
|
|
||||||
|
|
||||||
// ------ Color -------
|
|
||||||
|
|
||||||
if (enabled)
|
|
||||||
{
|
|
||||||
if (children)
|
|
||||||
{
|
|
||||||
GUI.color = Color.green;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
GUI.color = new Color(Color.green.r - 0.3f, Color.green.g - 0.3f, Color.green.b - 0.3f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
GUI.color = Color.red;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------ toggle active button ------
|
|
||||||
|
|
||||||
enabled = GUILayout.Toggle(enabled, "", new GUILayoutOption[] { GUILayout.Width(18) });
|
enabled = GUILayout.Toggle(enabled, "", new GUILayoutOption[] { GUILayout.Width(18) });
|
||||||
if (obj.activeSelf != enabled)
|
if (obj.activeSelf != enabled)
|
||||||
@ -188,84 +196,114 @@ namespace Explorer
|
|||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void DrawMember(ref object value, string valueType, string memberName, Rect rect, object setTarget = null, Action<object> setAction = null, float labelWidth = 180, bool autoSet = false)
|
public static void DrawMember(ref object value, ref bool isExpanded, MemberInfo memberInfo, Rect rect, object setTarget = null, Action<object> setAction = null, float labelWidth = 180, bool autoSet = false)
|
||||||
{
|
{
|
||||||
GUILayout.Label("<color=cyan>" + memberName + ":</color>", new GUILayoutOption[] { GUILayout.Width(labelWidth) });
|
GUILayout.Label("<color=cyan>" + memberInfo.Name + ":</color>", new GUILayoutOption[] { GUILayout.Width(labelWidth) });
|
||||||
|
|
||||||
DrawValue(ref value, rect, valueType, memberName, setTarget, setAction, autoSet);
|
string valueType = "";
|
||||||
|
bool canWrite = true;
|
||||||
|
if (memberInfo is FieldInfo fi)
|
||||||
|
{
|
||||||
|
valueType = fi.FieldType.Name;
|
||||||
|
canWrite = !(fi.IsLiteral && !fi.IsInitOnly);
|
||||||
|
}
|
||||||
|
else if (memberInfo is PropertyInfo pi)
|
||||||
|
{
|
||||||
|
valueType = pi.PropertyType.Name;
|
||||||
|
canWrite = pi.CanWrite;
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawValue(ref value, rect, ref isExpanded, valueType, (canWrite ? setTarget : null), (canWrite ? setAction : null), autoSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void DrawValue(ref object value, Rect rect, string nullValueType = null, string memberName = null, object setTarget = null, Action<object> setAction = null, bool autoSet = false)
|
public static void DrawValue(ref object value, Rect rect, ref bool isExpanded, string nullValueType = null, object setTarget = null, Action<object> setAction = null, bool autoSet = false)
|
||||||
{
|
{
|
||||||
if (value == null)
|
if (value == null)
|
||||||
{
|
{
|
||||||
GUILayout.Label("<i>null (" + nullValueType + ")</i>", null);
|
GUILayout.Label("<i>null (" + nullValueType + ")</i>", null);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
var valueType = value.GetType();
|
||||||
|
if (valueType.IsPrimitive || value.GetType() == typeof(string))
|
||||||
{
|
{
|
||||||
var valueType = value.GetType();
|
DrawPrimitive(ref value, rect, setTarget, setAction);
|
||||||
if (valueType.IsPrimitive || value.GetType() == typeof(string))
|
}
|
||||||
|
else if (valueType == typeof(GameObject) || valueType == typeof(Transform))
|
||||||
|
{
|
||||||
|
GameObject go;
|
||||||
|
if (value.GetType() == typeof(Transform))
|
||||||
{
|
{
|
||||||
DrawPrimitive(ref value, rect, setTarget, setAction);
|
go = (value as Transform).gameObject;
|
||||||
}
|
}
|
||||||
else if (valueType == typeof(GameObject) || valueType == typeof(Transform))
|
else
|
||||||
{
|
{
|
||||||
GameObject go;
|
go = (value as GameObject);
|
||||||
if (value.GetType() == typeof(Transform))
|
|
||||||
{
|
|
||||||
go = (value as Transform).gameObject;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
go = (value as GameObject);
|
|
||||||
}
|
|
||||||
|
|
||||||
UIStyles.GameobjButton(go, null, false, rect.width - 250);
|
|
||||||
}
|
}
|
||||||
else if (valueType.IsEnum)
|
|
||||||
{
|
|
||||||
if (setAction != null)
|
|
||||||
{
|
|
||||||
if (GUILayout.Button("<", new GUILayoutOption[] { GUILayout.Width(25) }))
|
|
||||||
{
|
|
||||||
SetEnum(ref value, -1);
|
|
||||||
setAction.Invoke(setTarget);
|
|
||||||
}
|
|
||||||
if (GUILayout.Button(">", new GUILayoutOption[] { GUILayout.Width(25) }))
|
|
||||||
{
|
|
||||||
SetEnum(ref value, 1);
|
|
||||||
setAction.Invoke(setTarget);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GUILayout.Label(value.ToString(), null);
|
GameobjButton(go, null, false, rect.width - 250);
|
||||||
|
}
|
||||||
|
else if (valueType.IsEnum)
|
||||||
|
{
|
||||||
|
if (setAction != null)
|
||||||
|
{
|
||||||
|
if (GUILayout.Button("<", new GUILayoutOption[] { GUILayout.Width(25) }))
|
||||||
|
{
|
||||||
|
SetEnum(ref value, -1);
|
||||||
|
setAction.Invoke(setTarget);
|
||||||
|
}
|
||||||
|
if (GUILayout.Button(">", new GUILayoutOption[] { GUILayout.Width(25) }))
|
||||||
|
{
|
||||||
|
SetEnum(ref value, 1);
|
||||||
|
setAction.Invoke(setTarget);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (value is System.Collections.IEnumerable || ReflectionWindow.IsList(valueType))
|
|
||||||
|
GUILayout.Label(value.ToString(), null);
|
||||||
|
}
|
||||||
|
else if (value is System.Collections.IEnumerable || ReflectionWindow.IsList(valueType))
|
||||||
|
{
|
||||||
|
System.Collections.IEnumerable enumerable;
|
||||||
|
|
||||||
|
if (value is System.Collections.IEnumerable isEnumerable)
|
||||||
{
|
{
|
||||||
System.Collections.IEnumerable enumerable;
|
enumerable = isEnumerable;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var listValueType = value.GetType().GetGenericArguments()[0];
|
||||||
|
var listType = typeof(Il2CppSystem.Collections.Generic.List<>).MakeGenericType(new Type[] { listValueType });
|
||||||
|
var method = listType.GetMethod("ToArray");
|
||||||
|
enumerable = (System.Collections.IEnumerable)method.Invoke(value, new object[0]);
|
||||||
|
}
|
||||||
|
|
||||||
if (value is System.Collections.IEnumerable isEnumerable)
|
int count = enumerable.Cast<object>().Count();
|
||||||
|
|
||||||
|
if (!isExpanded)
|
||||||
|
{
|
||||||
|
if (GUILayout.Button("v", new GUILayoutOption[] { GUILayout.Width(25) }))
|
||||||
{
|
{
|
||||||
enumerable = isEnumerable;
|
isExpanded = true;
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (GUILayout.Button("^", new GUILayoutOption[] { GUILayout.Width(25) }))
|
||||||
{
|
{
|
||||||
var listValueType = value.GetType().GetGenericArguments()[0];
|
isExpanded = false;
|
||||||
var listType = typeof(Il2CppSystem.Collections.Generic.List<>).MakeGenericType(new Type[] { listValueType });
|
|
||||||
var method = listType.GetMethod("ToArray");
|
|
||||||
enumerable = (System.Collections.IEnumerable)method.Invoke(value, new object[0]);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int count = enumerable.Cast<object>().Count();
|
GUI.skin.button.alignment = TextAnchor.MiddleLeft;
|
||||||
|
string btnLabel = "<color=yellow>[" + count + "] " + valueType + "</color>";
|
||||||
GUI.skin.button.alignment = TextAnchor.MiddleLeft;
|
if (GUILayout.Button(btnLabel, new GUILayoutOption[] { GUILayout.MaxWidth(rect.width - 260) }))
|
||||||
string btnLabel = "<color=yellow>[" + count + "] " + valueType + "</color>";
|
{
|
||||||
if (GUILayout.Button(btnLabel, new GUILayoutOption[] { GUILayout.MaxWidth(rect.width - 230) }))
|
WindowManager.InspectObject(value, out bool _);
|
||||||
{
|
}
|
||||||
WindowManager.InspectObject(value, out bool _);
|
GUI.skin.button.alignment = TextAnchor.MiddleCenter;
|
||||||
}
|
|
||||||
GUI.skin.button.alignment = TextAnchor.MiddleCenter;
|
|
||||||
|
|
||||||
|
if (isExpanded)
|
||||||
|
{
|
||||||
var enumerator = enumerable.GetEnumerator();
|
var enumerator = enumerable.GetEnumerator();
|
||||||
if (enumerator != null)
|
if (enumerator != null)
|
||||||
{
|
{
|
||||||
@ -315,49 +353,68 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var label = value.ToString();
|
||||||
|
|
||||||
|
if (valueType == typeof(Object))
|
||||||
{
|
{
|
||||||
var label = value.ToString();
|
label = (value as Object).name;
|
||||||
|
|
||||||
if (valueType == typeof(Object))
|
|
||||||
{
|
|
||||||
label = (value as Object).name;
|
|
||||||
}
|
|
||||||
else if (value is Vector4 vec4)
|
|
||||||
{
|
|
||||||
label = vec4.ToString();
|
|
||||||
}
|
|
||||||
else if (value is Vector3 vec3)
|
|
||||||
{
|
|
||||||
label = vec3.ToString();
|
|
||||||
}
|
|
||||||
else if (value is Vector2 vec2)
|
|
||||||
{
|
|
||||||
label = vec2.ToString();
|
|
||||||
}
|
|
||||||
else if (value is Rect rec)
|
|
||||||
{
|
|
||||||
label = rec.ToString();
|
|
||||||
}
|
|
||||||
else if (value is Matrix4x4 matrix)
|
|
||||||
{
|
|
||||||
label = matrix.ToString();
|
|
||||||
}
|
|
||||||
else if (value is Color col)
|
|
||||||
{
|
|
||||||
label = col.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
GUI.skin.button.alignment = TextAnchor.MiddleLeft;
|
|
||||||
if (GUILayout.Button("<color=yellow>" + label + "</color>", new GUILayoutOption[] { GUILayout.MaxWidth(rect.width - 230) }))
|
|
||||||
{
|
|
||||||
WindowManager.InspectObject(value, out bool _);
|
|
||||||
}
|
|
||||||
GUI.skin.button.alignment = TextAnchor.MiddleCenter;
|
|
||||||
}
|
}
|
||||||
|
else if (value is Vector4 vec4)
|
||||||
|
{
|
||||||
|
label = vec4.ToString();
|
||||||
|
}
|
||||||
|
else if (value is Vector3 vec3)
|
||||||
|
{
|
||||||
|
label = vec3.ToString();
|
||||||
|
}
|
||||||
|
else if (value is Vector2 vec2)
|
||||||
|
{
|
||||||
|
label = vec2.ToString();
|
||||||
|
}
|
||||||
|
else if (value is Rect rec)
|
||||||
|
{
|
||||||
|
label = rec.ToString();
|
||||||
|
}
|
||||||
|
else if (value is Matrix4x4 matrix)
|
||||||
|
{
|
||||||
|
label = matrix.ToString();
|
||||||
|
}
|
||||||
|
else if (value is Color col)
|
||||||
|
{
|
||||||
|
label = col.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
GUI.skin.button.alignment = TextAnchor.MiddleLeft;
|
||||||
|
if (GUILayout.Button("<color=yellow>" + label + "</color>", new GUILayoutOption[] { GUILayout.MaxWidth(rect.width - 230) }))
|
||||||
|
{
|
||||||
|
WindowManager.InspectObject(value, out bool _);
|
||||||
|
}
|
||||||
|
GUI.skin.button.alignment = TextAnchor.MiddleCenter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//public static void DrawMember(ref object value, string valueType, string memberName, Rect rect, object setTarget = null, Action<object> setAction = null, float labelWidth = 180, bool autoSet = false)
|
||||||
|
//{
|
||||||
|
// GUILayout.Label("<color=cyan>" + memberName + ":</color>", new GUILayoutOption[] { GUILayout.Width(labelWidth) });
|
||||||
|
|
||||||
|
// DrawValue(ref value, rect, valueType, memberName, setTarget, setAction, autoSet);
|
||||||
|
//}
|
||||||
|
|
||||||
|
//public static void DrawValue(ref object value, Rect rect, string nullValueType = null, string memberName = null, object setTarget = null, Action<object> setAction = null, bool autoSet = false)
|
||||||
|
//{
|
||||||
|
// if (value == null)
|
||||||
|
// {
|
||||||
|
// GUILayout.Label("<i>null (" + nullValueType + ")</i>", null);
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
// Helper for drawing primitive values (with Apply button)
|
// Helper for drawing primitive values (with Apply button)
|
||||||
|
|
||||||
public static void DrawPrimitive(ref object value, Rect m_rect, object setTarget = null, Action<object> setAction = null, bool autoSet = false)
|
public static void DrawPrimitive(ref object value, Rect m_rect, object setTarget = null, Action<object> setAction = null, bool autoSet = false)
|
||||||
@ -387,10 +444,10 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
value = GUILayout.TextField(value.ToString(), new GUILayoutOption[] { GUILayout.MaxWidth(m_rect.width - 260) });
|
value = GUILayout.TextField(value.ToString(), new GUILayoutOption[] { GUILayout.MaxWidth(m_rect.width - 260) });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (autoSet || (allowSet && GUILayout.Button("<color=#00FF00>Apply</color>", new GUILayoutOption[] { GUILayout.Width(60) })))
|
if (autoSet || (allowSet && GUILayout.Button("<color=#00FF00>Apply</color>", new GUILayoutOption[] { GUILayout.Width(60) })))
|
||||||
{
|
{
|
||||||
setAction.Invoke(setTarget);
|
setAction.Invoke(setTarget);
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ namespace Explorer
|
|||||||
|
|
||||||
public const string ID = "com.sinai.cppexplorer";
|
public const string ID = "com.sinai.cppexplorer";
|
||||||
public const string NAME = "IL2CPP Runtime Explorer";
|
public const string NAME = "IL2CPP Runtime Explorer";
|
||||||
public const string VERSION = "1.3.0";
|
public const string VERSION = "1.3.1";
|
||||||
public const string AUTHOR = "Sinai";
|
public const string AUTHOR = "Sinai";
|
||||||
|
|
||||||
// fields
|
// fields
|
||||||
|
@ -104,7 +104,6 @@
|
|||||||
</Reference>
|
</Reference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="ILBehaviour.cs" />
|
|
||||||
<Compile Include="CppExplorer.cs" />
|
<Compile Include="CppExplorer.cs" />
|
||||||
<Compile Include="MainMenu\Pages\ConsolePage.cs" />
|
<Compile Include="MainMenu\Pages\ConsolePage.cs" />
|
||||||
<Compile Include="MainMenu\Pages\Console\REPL.cs" />
|
<Compile Include="MainMenu\Pages\Console\REPL.cs" />
|
||||||
|
@ -1,33 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using UnityEngine;
|
|
||||||
using MelonLoader;
|
|
||||||
using UnhollowerRuntimeLib;
|
|
||||||
|
|
||||||
namespace Explorer
|
|
||||||
{
|
|
||||||
//public class ILBehaviour : MonoBehaviour
|
|
||||||
//{
|
|
||||||
// public ILBehaviour(IntPtr intPtr) : base(intPtr) { }
|
|
||||||
|
|
||||||
// public static T AddToGameObject<T>(GameObject _go) where T : ILBehaviour
|
|
||||||
// {
|
|
||||||
// Il2CppSystem.Type ilType = UnhollowerRuntimeLib.Il2CppType.Of<T>();
|
|
||||||
|
|
||||||
// if (ilType == null)
|
|
||||||
// {
|
|
||||||
// MelonLogger.Log("Error - could not get MB as ilType");
|
|
||||||
// return null;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// var obj = typeof(T)
|
|
||||||
// .GetConstructor(new Type[] { typeof(IntPtr) })
|
|
||||||
// .Invoke(new object[] { _go.AddComponent(UnhollowerRuntimeLib.Il2CppType.Of<T>()).Pointer });
|
|
||||||
|
|
||||||
// return (T)obj;
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
}
|
|
@ -93,9 +93,13 @@ namespace Explorer
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_objectType = type;
|
try
|
||||||
GetFields(m_object);
|
{
|
||||||
GetProperties(m_object);
|
m_objectType = type;
|
||||||
|
GetFields(m_object);
|
||||||
|
GetProperties(m_object);
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
|
||||||
UpdateValues();
|
UpdateValues();
|
||||||
}
|
}
|
||||||
@ -276,7 +280,7 @@ namespace Explorer
|
|||||||
|
|
||||||
public static bool IsList(Type t)
|
public static bool IsList(Type t)
|
||||||
{
|
{
|
||||||
return t.IsGenericType
|
return t.IsGenericType
|
||||||
&& t.GetGenericTypeDefinition() is Type typeDef
|
&& t.GetGenericTypeDefinition() is Type typeDef
|
||||||
&& (typeDef.IsAssignableFrom(typeof(List<>)) || typeDef.IsAssignableFrom(typeof(Il2CppSystem.Collections.Generic.List<>)));
|
&& (typeDef.IsAssignableFrom(typeof(List<>)) || typeDef.IsAssignableFrom(typeof(Il2CppSystem.Collections.Generic.List<>)));
|
||||||
}
|
}
|
||||||
@ -292,8 +296,20 @@ namespace Explorer
|
|||||||
|
|
||||||
foreach (var type in types)
|
foreach (var type in types)
|
||||||
{
|
{
|
||||||
foreach (var pi in type.GetProperties(At.flags))
|
PropertyInfo[] propInfos = new PropertyInfo[0];
|
||||||
|
|
||||||
|
try
|
||||||
{
|
{
|
||||||
|
propInfos = type.GetProperties(At.flags);
|
||||||
|
}
|
||||||
|
catch (TypeLoadException)
|
||||||
|
{
|
||||||
|
MelonLogger.Log($"Couldn't get Properties for Type '{type.Name}', it may not support Il2Cpp Reflection at the moment.");
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var pi in propInfos)
|
||||||
|
{
|
||||||
|
// this member causes a crash when inspected, so just skipping it for now.
|
||||||
if (pi.Name == "Il2CppType")
|
if (pi.Name == "Il2CppType")
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
@ -335,7 +351,7 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* *********************
|
/* *********************
|
||||||
* PROPERTYINFO HOLDER
|
* PROPERTYINFO HOLDER
|
||||||
@ -346,6 +362,7 @@ namespace Explorer
|
|||||||
public Type classType;
|
public Type classType;
|
||||||
public PropertyInfo propInfo;
|
public PropertyInfo propInfo;
|
||||||
public object m_value;
|
public object m_value;
|
||||||
|
public bool IsExpanded;
|
||||||
|
|
||||||
public PropertyInfoHolder(Type _type, PropertyInfo _propInfo)
|
public PropertyInfoHolder(Type _type, PropertyInfo _propInfo)
|
||||||
{
|
{
|
||||||
@ -355,14 +372,7 @@ namespace Explorer
|
|||||||
|
|
||||||
public void Draw(ReflectionWindow window)
|
public void Draw(ReflectionWindow window)
|
||||||
{
|
{
|
||||||
if (propInfo.CanWrite)
|
UIStyles.DrawMember(ref m_value, ref this.IsExpanded, this.propInfo, window.m_rect, window.m_object, SetValue);
|
||||||
{
|
|
||||||
UIStyles.DrawMember(ref m_value, propInfo.PropertyType.Name, propInfo.Name, window.m_rect, window.m_object, SetValue);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UIStyles.DrawMember(ref m_value, propInfo.PropertyType.Name, propInfo.Name, window.m_rect, window.m_object);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateValue(object obj)
|
public void UpdateValue(object obj)
|
||||||
@ -389,15 +399,15 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
//MelonLogger.Log("Exception on PropertyInfoHolder.UpdateValue, Name: " + this.propInfo.Name);
|
MelonLogger.Log("Exception on PropertyInfoHolder.UpdateValue, Name: " + this.propInfo.Name);
|
||||||
//MelonLogger.Log(e.GetType() + ", " + e.Message);
|
MelonLogger.Log(e.GetType() + ", " + e.Message);
|
||||||
|
|
||||||
//var inner = e.InnerException;
|
var inner = e.InnerException;
|
||||||
//while (inner != null)
|
while (inner != null)
|
||||||
//{
|
{
|
||||||
// MelonLogger.Log("inner: " + inner.GetType() + ", " + inner.Message);
|
MelonLogger.Log("inner: " + inner.GetType() + ", " + inner.Message);
|
||||||
// inner = inner.InnerException;
|
inner = inner.InnerException;
|
||||||
//}
|
}
|
||||||
|
|
||||||
m_value = null;
|
m_value = null;
|
||||||
}
|
}
|
||||||
@ -473,6 +483,7 @@ namespace Explorer
|
|||||||
public Type classType;
|
public Type classType;
|
||||||
public FieldInfo fieldInfo;
|
public FieldInfo fieldInfo;
|
||||||
public object m_value;
|
public object m_value;
|
||||||
|
public bool IsExpanded;
|
||||||
|
|
||||||
public FieldInfoHolder(Type _type, FieldInfo _fieldInfo)
|
public FieldInfoHolder(Type _type, FieldInfo _fieldInfo)
|
||||||
{
|
{
|
||||||
@ -487,16 +498,7 @@ namespace Explorer
|
|||||||
|
|
||||||
public void Draw(ReflectionWindow window)
|
public void Draw(ReflectionWindow window)
|
||||||
{
|
{
|
||||||
bool canSet = !(fieldInfo.IsLiteral && !fieldInfo.IsInitOnly);
|
UIStyles.DrawMember(ref m_value, ref this.IsExpanded, this.fieldInfo, window.m_rect, window.m_object, SetValue);
|
||||||
|
|
||||||
if (canSet)
|
|
||||||
{
|
|
||||||
UIStyles.DrawMember(ref m_value, fieldInfo.FieldType.Name, fieldInfo.Name, window.m_rect, window.m_object, SetValue);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UIStyles.DrawMember(ref m_value, fieldInfo.FieldType.Name, fieldInfo.Name, window.m_rect, window.m_object);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetValue(object obj)
|
public void SetValue(object obj)
|
||||||
|
@ -36,17 +36,17 @@ namespace Explorer
|
|||||||
return MB.FindAll<T>();
|
return MB.FindAll<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Documentation("runCoroutine(enumerator) - runs an IEnumerator as a Unity coroutine.")]
|
//[Documentation("runCoroutine(enumerator) - runs an IEnumerator as a Unity coroutine.")]
|
||||||
public static object runCoroutine(IEnumerator i)
|
//public static object runCoroutine(IEnumerator i)
|
||||||
{
|
//{
|
||||||
return MB.RunCoroutine(i);
|
// return MB.RunCoroutine(i);
|
||||||
}
|
//}
|
||||||
|
|
||||||
[Documentation("endCoroutine(co) - ends a Unity coroutine.")]
|
//[Documentation("endCoroutine(co) - ends a Unity coroutine.")]
|
||||||
public static void endCoroutine(Coroutine c)
|
//public static void endCoroutine(Coroutine c)
|
||||||
{
|
//{
|
||||||
MB.EndCoroutine(c);
|
// MB.EndCoroutine(c);
|
||||||
}
|
//}
|
||||||
|
|
||||||
////[Documentation("type<T>() - obtain type info about a type T. Provides some Reflection helpers.")]
|
////[Documentation("type<T>() - obtain type info about a type T. Provides some Reflection helpers.")]
|
||||||
////public static TypeHelper type<T>()
|
////public static TypeHelper type<T>()
|
||||||
|
@ -21,14 +21,14 @@ namespace Explorer
|
|||||||
return FindObjectsOfType<T>();
|
return FindObjectsOfType<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public object RunCoroutine(IEnumerator enumerator)
|
//public object RunCoroutine(IEnumerator enumerator)
|
||||||
{
|
//{
|
||||||
return MelonCoroutines.Start(enumerator);
|
// return MelonCoroutines.Start(enumerator);
|
||||||
}
|
//}
|
||||||
|
|
||||||
public void EndCoroutine(Coroutine c)
|
//public void EndCoroutine(Coroutine c)
|
||||||
{
|
//{
|
||||||
StopCoroutine(c);
|
// StopCoroutine(c);
|
||||||
}
|
//}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -20,12 +20,13 @@ namespace Explorer
|
|||||||
|
|
||||||
// gameobject list
|
// gameobject list
|
||||||
private Transform m_currentTransform;
|
private Transform m_currentTransform;
|
||||||
private List<GameObject> m_objectList = new List<GameObject>();
|
private List<GameObjectCache> m_objectList = new List<GameObjectCache>();
|
||||||
|
private float m_timeOfLastUpdate = -1f;
|
||||||
|
|
||||||
// search bar
|
// search bar
|
||||||
private bool m_searching = false;
|
private bool m_searching = false;
|
||||||
private string m_searchInput = "";
|
private string m_searchInput = "";
|
||||||
private List<GameObject> m_searchResults = new List<GameObject>();
|
private List<GameObjectCache> m_searchResults = new List<GameObjectCache>();
|
||||||
|
|
||||||
// ------------ Init and Update ------------ //
|
// ------------ Init and Update ------------ //
|
||||||
|
|
||||||
@ -40,17 +41,24 @@ namespace Explorer
|
|||||||
|
|
||||||
m_currentTransform = null;
|
m_currentTransform = null;
|
||||||
CancelSearch();
|
CancelSearch();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Update()
|
public override void Update()
|
||||||
{
|
{
|
||||||
|
if (Time.time - m_timeOfLastUpdate < 1f)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_timeOfLastUpdate = Time.time;
|
||||||
|
|
||||||
|
var start = Time.realtimeSinceStartup;
|
||||||
|
|
||||||
if (!m_searching)
|
if (!m_searching)
|
||||||
{
|
{
|
||||||
m_objectList = new List<GameObject>();
|
m_objectList = new List<GameObjectCache>();
|
||||||
if (m_currentTransform)
|
if (m_currentTransform)
|
||||||
{
|
{
|
||||||
var noChildren = new List<GameObject>();
|
var endAppend = new List<GameObjectCache>();
|
||||||
for (int i = 0; i < m_currentTransform.childCount; i++)
|
for (int i = 0; i < m_currentTransform.childCount; i++)
|
||||||
{
|
{
|
||||||
var child = m_currentTransform.GetChild(i);
|
var child = m_currentTransform.GetChild(i);
|
||||||
@ -58,13 +66,13 @@ namespace Explorer
|
|||||||
if (child)
|
if (child)
|
||||||
{
|
{
|
||||||
if (child.childCount > 0)
|
if (child.childCount > 0)
|
||||||
m_objectList.Add(child.gameObject);
|
m_objectList.Add(new GameObjectCache(child.gameObject));
|
||||||
else
|
else
|
||||||
noChildren.Add(child.gameObject);
|
endAppend.Add(new GameObjectCache(child.gameObject));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_objectList.AddRange(noChildren);
|
m_objectList.AddRange(endAppend);
|
||||||
noChildren = null;
|
endAppend = null;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -74,11 +82,11 @@ namespace Explorer
|
|||||||
// add objects with children first
|
// add objects with children first
|
||||||
foreach (var obj in rootObjects.Where(x => x.transform.childCount > 0))
|
foreach (var obj in rootObjects.Where(x => x.transform.childCount > 0))
|
||||||
{
|
{
|
||||||
m_objectList.Add(obj);
|
m_objectList.Add(new GameObjectCache(obj));
|
||||||
}
|
}
|
||||||
foreach (var obj in rootObjects.Where(x => x.transform.childCount == 0))
|
foreach (var obj in rootObjects.Where(x => x.transform.childCount == 0))
|
||||||
{
|
{
|
||||||
m_objectList.Add(obj);
|
m_objectList.Add(new GameObjectCache(obj));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -120,7 +128,8 @@ namespace Explorer
|
|||||||
m_currentScene = scenes[index].name;
|
m_currentScene = scenes[index].name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
GUILayout.Label("<color=cyan>" + m_currentScene + "</color>", null);
|
GUILayout.Label("<color=cyan>" + m_currentScene + "</color>", null); //new GUILayoutOption[] { GUILayout.Width(250) });
|
||||||
|
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
// ----- GameObject Search -----
|
// ----- GameObject Search -----
|
||||||
@ -160,10 +169,13 @@ namespace Explorer
|
|||||||
|
|
||||||
if (m_objectList.Count > 0)
|
if (m_objectList.Count > 0)
|
||||||
{
|
{
|
||||||
|
var start = Time.realtimeSinceStartup;
|
||||||
foreach (var obj in m_objectList)
|
foreach (var obj in m_objectList)
|
||||||
{
|
{
|
||||||
UIStyles.GameobjButton(obj, SetTransformTarget, true, MainMenu.MainRect.width - 170);
|
//UIStyles.GameobjButton(obj, SetTransformTarget, true, MainMenu.MainRect.width - 170);
|
||||||
|
UIStyles.FastGameobjButton(obj.RefGameObject, obj.EnabledColor, obj.Label, obj.RefGameObject.activeSelf, SetTransformTarget, true, MainMenu.MainRect.width - 170);
|
||||||
}
|
}
|
||||||
|
var diff = Time.realtimeSinceStartup - start;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -183,7 +195,8 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
foreach (var obj in m_searchResults)
|
foreach (var obj in m_searchResults)
|
||||||
{
|
{
|
||||||
UIStyles.GameobjButton(obj, SetTransformTarget, true, MainMenu.MainRect.width - 170);
|
//UIStyles.GameobjButton(obj, SetTransformTarget, true, MainMenu.MainRect.width - 170);
|
||||||
|
UIStyles.FastGameobjButton(obj.RefGameObject, obj.EnabledColor, obj.Label, obj.RefGameObject.activeSelf, SetTransformTarget, true, MainMenu.MainRect.width - 170);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -231,19 +244,54 @@ namespace Explorer
|
|||||||
m_searching = false;
|
m_searching = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<GameObject> SearchSceneObjects(string _search)
|
public List<GameObjectCache> SearchSceneObjects(string _search)
|
||||||
{
|
{
|
||||||
var matches = new List<GameObject>();
|
var matches = new List<GameObjectCache>();
|
||||||
|
|
||||||
foreach (var obj in Resources.FindObjectsOfTypeAll<GameObject>())
|
foreach (var obj in Resources.FindObjectsOfTypeAll<GameObject>())
|
||||||
{
|
{
|
||||||
if (obj.name.ToLower().Contains(_search.ToLower()) && obj.scene.name == m_currentScene)
|
if (obj.name.ToLower().Contains(_search.ToLower()) && obj.scene.name == m_currentScene)
|
||||||
{
|
{
|
||||||
matches.Add(obj);
|
matches.Add(new GameObjectCache(obj));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return matches;
|
return matches;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class GameObjectCache
|
||||||
|
{
|
||||||
|
public GameObject RefGameObject;
|
||||||
|
public string Label;
|
||||||
|
public Color EnabledColor;
|
||||||
|
public int ChildCount;
|
||||||
|
|
||||||
|
public GameObjectCache(GameObject obj)
|
||||||
|
{
|
||||||
|
RefGameObject = obj;
|
||||||
|
ChildCount = obj.transform.childCount;
|
||||||
|
|
||||||
|
Label = (ChildCount > 0) ? "[" + obj.transform.childCount + " children] " : "";
|
||||||
|
Label += obj.name;
|
||||||
|
|
||||||
|
bool enabled = obj.activeSelf;
|
||||||
|
int childCount = obj.transform.childCount;
|
||||||
|
if (enabled)
|
||||||
|
{
|
||||||
|
if (childCount > 0)
|
||||||
|
{
|
||||||
|
EnabledColor = Color.green;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
EnabledColor = UIStyles.LightGreen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
EnabledColor = Color.red;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,7 @@ namespace Explorer
|
|||||||
private List<object> m_searchResults = new List<object>();
|
private List<object> m_searchResults = new List<object>();
|
||||||
private Vector2 resultsScroll = Vector2.zero;
|
private Vector2 resultsScroll = Vector2.zero;
|
||||||
|
|
||||||
public override void Init()
|
public override void Init()
|
||||||
{
|
{
|
||||||
Instance = this;
|
Instance = this;
|
||||||
}
|
}
|
||||||
@ -54,7 +54,7 @@ namespace Explorer
|
|||||||
m_searchResults.Clear();
|
m_searchResults.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Update()
|
public override void Update()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,7 +91,8 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
var obj = m_searchResults[i];
|
var obj = m_searchResults[i];
|
||||||
|
|
||||||
UIStyles.DrawValue(ref obj, _temprect);
|
bool _ = false;
|
||||||
|
UIStyles.DrawValue(ref obj, _temprect, ref _);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -147,14 +148,14 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(null);
|
||||||
GUI.skin.label.alignment = TextAnchor.MiddleRight;
|
GUI.skin.label.alignment = TextAnchor.MiddleRight;
|
||||||
GUILayout.Label("Custom Class:", new GUILayoutOption[] { GUILayout.Width(250) });
|
GUILayout.Label("Custom Class:", new GUILayoutOption[] { GUILayout.Width(250) });
|
||||||
GUI.skin.label.alignment = TextAnchor.UpperLeft;
|
GUI.skin.label.alignment = TextAnchor.UpperLeft;
|
||||||
m_typeInput = GUILayout.TextField(m_typeInput, new GUILayoutOption[] { GUILayout.Width(250) });
|
m_typeInput = GUILayout.TextField(m_typeInput, new GUILayoutOption[] { GUILayout.Width(250) });
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
}
|
}
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(null);
|
||||||
GUILayout.Label("Scene Filter:", new GUILayoutOption[] { GUILayout.Width(100) });
|
GUILayout.Label("Scene Filter:", new GUILayoutOption[] { GUILayout.Width(100) });
|
||||||
SceneFilterToggle(SceneFilter.Any, "Any", 60);
|
SceneFilterToggle(SceneFilter.Any, "Any", 60);
|
||||||
SceneFilterToggle(SceneFilter.This, "This Scene", 100);
|
SceneFilterToggle(SceneFilter.This, "This Scene", 100);
|
||||||
SceneFilterToggle(SceneFilter.DontDestroy, "DontDestroyOnLoad", 140);
|
SceneFilterToggle(SceneFilter.DontDestroy, "DontDestroyOnLoad", 140);
|
||||||
@ -262,7 +263,6 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
var findType = CppExplorer.GetType(_type);
|
var findType = CppExplorer.GetType(_type);
|
||||||
type = Il2CppSystem.Type.GetType(findType.AssemblyQualifiedName);
|
type = Il2CppSystem.Type.GetType(findType.AssemblyQualifiedName);
|
||||||
MelonLogger.Log("Got type: " + type.AssemblyQualifiedName);
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@ -372,7 +372,7 @@ namespace Explorer
|
|||||||
if (type == typeof(GameObject) || typeof(Component).IsAssignableFrom(type))
|
if (type == typeof(GameObject) || typeof(Component).IsAssignableFrom(type))
|
||||||
{
|
{
|
||||||
var go = obj as GameObject ?? (obj as Component).gameObject;
|
var go = obj as GameObject ?? (obj as Component).gameObject;
|
||||||
|
|
||||||
if (go != null && go.scene.name == CppExplorer.ActiveSceneName && go.scene.name != "DontDestroyOnLoad")
|
if (go != null && go.scene.name == CppExplorer.ActiveSceneName && go.scene.name != "DontDestroyOnLoad")
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
|
@ -5,7 +5,7 @@ using System.Linq;
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Il2CppSystem.Collections;
|
using Il2CppSystem.Collections;
|
||||||
using Il2CppSystem.Reflection;
|
//using Il2CppSystem.Reflection;
|
||||||
using MelonLoader;
|
using MelonLoader;
|
||||||
using UnhollowerBaseLib;
|
using UnhollowerBaseLib;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
@ -15,6 +15,8 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
public class UIStyles
|
public class UIStyles
|
||||||
{
|
{
|
||||||
|
public static Color LightGreen = new Color(Color.green.r - 0.3f, Color.green.g - 0.3f, Color.green.b - 0.3f);
|
||||||
|
|
||||||
public static GUISkin WindowSkin
|
public static GUISkin WindowSkin
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@ -115,42 +117,48 @@ 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<GameObject> specialInspectMethod = null, bool showSmallInspectBtn = true, float width = 380)
|
||||||
{
|
{
|
||||||
if (obj == null)
|
bool children = obj.transform.childCount > 0;
|
||||||
|
|
||||||
|
string label = children ? "[" + obj.transform.childCount + " children] " : "";
|
||||||
|
label += obj.name;
|
||||||
|
|
||||||
|
bool enabled = obj.activeSelf;
|
||||||
|
int childCount = obj.transform.childCount;
|
||||||
|
Color color;
|
||||||
|
|
||||||
|
if (enabled)
|
||||||
|
{
|
||||||
|
if (childCount > 0)
|
||||||
|
{
|
||||||
|
color = Color.green;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
color = LightGreen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
color = Color.red;
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
if (!obj)
|
||||||
{
|
{
|
||||||
GUILayout.Label("<i><color=red>null</color></i>", null);
|
GUILayout.Label("<i><color=red>null</color></i>", null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool enabled = obj.activeSelf;
|
// ------ toggle active button ------
|
||||||
bool children = obj.transform.childCount > 0;
|
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(null);
|
||||||
GUI.skin.button.alignment = TextAnchor.UpperLeft;
|
GUI.skin.button.alignment = TextAnchor.UpperLeft;
|
||||||
|
|
||||||
// ------ build name ------
|
GUI.color = activeColor;
|
||||||
|
|
||||||
string label = children ? "[" + obj.transform.childCount + " children] " : "";
|
|
||||||
label += obj.name;
|
|
||||||
|
|
||||||
// ------ Color -------
|
|
||||||
|
|
||||||
if (enabled)
|
|
||||||
{
|
|
||||||
if (children)
|
|
||||||
{
|
|
||||||
GUI.color = Color.green;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
GUI.color = new Color(Color.green.r - 0.3f, Color.green.g - 0.3f, Color.green.b - 0.3f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
GUI.color = Color.red;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------ toggle active button ------
|
|
||||||
|
|
||||||
enabled = GUILayout.Toggle(enabled, "", new GUILayoutOption[] { GUILayout.Width(18) });
|
enabled = GUILayout.Toggle(enabled, "", new GUILayoutOption[] { GUILayout.Width(18) });
|
||||||
if (obj.activeSelf != enabled)
|
if (obj.activeSelf != enabled)
|
||||||
@ -188,84 +196,114 @@ namespace Explorer
|
|||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void DrawMember(ref object value, string valueType, string memberName, Rect rect, object setTarget = null, Action<object> setAction = null, float labelWidth = 180, bool autoSet = false)
|
public static void DrawMember(ref object value, ref bool isExpanded, MemberInfo memberInfo, Rect rect, object setTarget = null, Action<object> setAction = null, float labelWidth = 180, bool autoSet = false)
|
||||||
{
|
{
|
||||||
GUILayout.Label("<color=cyan>" + memberName + ":</color>", new GUILayoutOption[] { GUILayout.Width(labelWidth) });
|
GUILayout.Label("<color=cyan>" + memberInfo.Name + ":</color>", new GUILayoutOption[] { GUILayout.Width(labelWidth) });
|
||||||
|
|
||||||
DrawValue(ref value, rect, valueType, memberName, setTarget, setAction, autoSet);
|
string valueType = "";
|
||||||
|
bool canWrite = true;
|
||||||
|
if (memberInfo is FieldInfo fi)
|
||||||
|
{
|
||||||
|
valueType = fi.FieldType.Name;
|
||||||
|
canWrite = !(fi.IsLiteral && !fi.IsInitOnly);
|
||||||
|
}
|
||||||
|
else if (memberInfo is PropertyInfo pi)
|
||||||
|
{
|
||||||
|
valueType = pi.PropertyType.Name;
|
||||||
|
canWrite = pi.CanWrite;
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawValue(ref value, rect, ref isExpanded, valueType, (canWrite ? setTarget : null), (canWrite ? setAction : null), autoSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void DrawValue(ref object value, Rect rect, string nullValueType = null, string memberName = null, object setTarget = null, Action<object> setAction = null, bool autoSet = false)
|
public static void DrawValue(ref object value, Rect rect, ref bool isExpanded, string nullValueType = null, object setTarget = null, Action<object> setAction = null, bool autoSet = false)
|
||||||
{
|
{
|
||||||
if (value == null)
|
if (value == null)
|
||||||
{
|
{
|
||||||
GUILayout.Label("<i>null (" + nullValueType + ")</i>", null);
|
GUILayout.Label("<i>null (" + nullValueType + ")</i>", null);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
var valueType = value.GetType();
|
||||||
|
if (valueType.IsPrimitive || value.GetType() == typeof(string))
|
||||||
{
|
{
|
||||||
var valueType = value.GetType();
|
DrawPrimitive(ref value, rect, setTarget, setAction);
|
||||||
if (valueType.IsPrimitive || value.GetType() == typeof(string))
|
}
|
||||||
|
else if (valueType == typeof(GameObject) || valueType == typeof(Transform))
|
||||||
|
{
|
||||||
|
GameObject go;
|
||||||
|
if (value.GetType() == typeof(Transform))
|
||||||
{
|
{
|
||||||
DrawPrimitive(ref value, rect, setTarget, setAction);
|
go = (value as Transform).gameObject;
|
||||||
}
|
}
|
||||||
else if (valueType == typeof(GameObject) || valueType == typeof(Transform))
|
else
|
||||||
{
|
{
|
||||||
GameObject go;
|
go = (value as GameObject);
|
||||||
if (value.GetType() == typeof(Transform))
|
|
||||||
{
|
|
||||||
go = (value as Transform).gameObject;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
go = (value as GameObject);
|
|
||||||
}
|
|
||||||
|
|
||||||
UIStyles.GameobjButton(go, null, false, rect.width - 250);
|
|
||||||
}
|
}
|
||||||
else if (valueType.IsEnum)
|
|
||||||
{
|
|
||||||
if (setAction != null)
|
|
||||||
{
|
|
||||||
if (GUILayout.Button("<", new GUILayoutOption[] { GUILayout.Width(25) }))
|
|
||||||
{
|
|
||||||
SetEnum(ref value, -1);
|
|
||||||
setAction.Invoke(setTarget);
|
|
||||||
}
|
|
||||||
if (GUILayout.Button(">", new GUILayoutOption[] { GUILayout.Width(25) }))
|
|
||||||
{
|
|
||||||
SetEnum(ref value, 1);
|
|
||||||
setAction.Invoke(setTarget);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GUILayout.Label(value.ToString(), null);
|
GameobjButton(go, null, false, rect.width - 250);
|
||||||
|
}
|
||||||
|
else if (valueType.IsEnum)
|
||||||
|
{
|
||||||
|
if (setAction != null)
|
||||||
|
{
|
||||||
|
if (GUILayout.Button("<", new GUILayoutOption[] { GUILayout.Width(25) }))
|
||||||
|
{
|
||||||
|
SetEnum(ref value, -1);
|
||||||
|
setAction.Invoke(setTarget);
|
||||||
|
}
|
||||||
|
if (GUILayout.Button(">", new GUILayoutOption[] { GUILayout.Width(25) }))
|
||||||
|
{
|
||||||
|
SetEnum(ref value, 1);
|
||||||
|
setAction.Invoke(setTarget);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (value is System.Collections.IEnumerable || ReflectionWindow.IsList(valueType))
|
|
||||||
|
GUILayout.Label(value.ToString(), null);
|
||||||
|
}
|
||||||
|
else if (value is System.Collections.IEnumerable || ReflectionWindow.IsList(valueType))
|
||||||
|
{
|
||||||
|
System.Collections.IEnumerable enumerable;
|
||||||
|
|
||||||
|
if (value is System.Collections.IEnumerable isEnumerable)
|
||||||
{
|
{
|
||||||
System.Collections.IEnumerable enumerable;
|
enumerable = isEnumerable;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var listValueType = value.GetType().GetGenericArguments()[0];
|
||||||
|
var listType = typeof(Il2CppSystem.Collections.Generic.List<>).MakeGenericType(new Type[] { listValueType });
|
||||||
|
var method = listType.GetMethod("ToArray");
|
||||||
|
enumerable = (System.Collections.IEnumerable)method.Invoke(value, new object[0]);
|
||||||
|
}
|
||||||
|
|
||||||
if (value is System.Collections.IEnumerable isEnumerable)
|
int count = enumerable.Cast<object>().Count();
|
||||||
|
|
||||||
|
if (!isExpanded)
|
||||||
|
{
|
||||||
|
if (GUILayout.Button("v", new GUILayoutOption[] { GUILayout.Width(25) }))
|
||||||
{
|
{
|
||||||
enumerable = isEnumerable;
|
isExpanded = true;
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (GUILayout.Button("^", new GUILayoutOption[] { GUILayout.Width(25) }))
|
||||||
{
|
{
|
||||||
var listValueType = value.GetType().GetGenericArguments()[0];
|
isExpanded = false;
|
||||||
var listType = typeof(Il2CppSystem.Collections.Generic.List<>).MakeGenericType(new Type[] { listValueType });
|
|
||||||
var method = listType.GetMethod("ToArray");
|
|
||||||
enumerable = (System.Collections.IEnumerable)method.Invoke(value, new object[0]);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int count = enumerable.Cast<object>().Count();
|
GUI.skin.button.alignment = TextAnchor.MiddleLeft;
|
||||||
|
string btnLabel = "<color=yellow>[" + count + "] " + valueType + "</color>";
|
||||||
GUI.skin.button.alignment = TextAnchor.MiddleLeft;
|
if (GUILayout.Button(btnLabel, new GUILayoutOption[] { GUILayout.MaxWidth(rect.width - 260) }))
|
||||||
string btnLabel = "<color=yellow>[" + count + "] " + valueType + "</color>";
|
{
|
||||||
if (GUILayout.Button(btnLabel, new GUILayoutOption[] { GUILayout.MaxWidth(rect.width - 230) }))
|
WindowManager.InspectObject(value, out bool _);
|
||||||
{
|
}
|
||||||
WindowManager.InspectObject(value, out bool _);
|
GUI.skin.button.alignment = TextAnchor.MiddleCenter;
|
||||||
}
|
|
||||||
GUI.skin.button.alignment = TextAnchor.MiddleCenter;
|
|
||||||
|
|
||||||
|
if (isExpanded)
|
||||||
|
{
|
||||||
var enumerator = enumerable.GetEnumerator();
|
var enumerator = enumerable.GetEnumerator();
|
||||||
if (enumerator != null)
|
if (enumerator != null)
|
||||||
{
|
{
|
||||||
@ -315,49 +353,68 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var label = value.ToString();
|
||||||
|
|
||||||
|
if (valueType == typeof(Object))
|
||||||
{
|
{
|
||||||
var label = value.ToString();
|
label = (value as Object).name;
|
||||||
|
|
||||||
if (valueType == typeof(Object))
|
|
||||||
{
|
|
||||||
label = (value as Object).name;
|
|
||||||
}
|
|
||||||
else if (value is Vector4 vec4)
|
|
||||||
{
|
|
||||||
label = vec4.ToString();
|
|
||||||
}
|
|
||||||
else if (value is Vector3 vec3)
|
|
||||||
{
|
|
||||||
label = vec3.ToString();
|
|
||||||
}
|
|
||||||
else if (value is Vector2 vec2)
|
|
||||||
{
|
|
||||||
label = vec2.ToString();
|
|
||||||
}
|
|
||||||
else if (value is Rect rec)
|
|
||||||
{
|
|
||||||
label = rec.ToString();
|
|
||||||
}
|
|
||||||
else if (value is Matrix4x4 matrix)
|
|
||||||
{
|
|
||||||
label = matrix.ToString();
|
|
||||||
}
|
|
||||||
else if (value is Color col)
|
|
||||||
{
|
|
||||||
label = col.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
GUI.skin.button.alignment = TextAnchor.MiddleLeft;
|
|
||||||
if (GUILayout.Button("<color=yellow>" + label + "</color>", new GUILayoutOption[] { GUILayout.MaxWidth(rect.width - 230) }))
|
|
||||||
{
|
|
||||||
WindowManager.InspectObject(value, out bool _);
|
|
||||||
}
|
|
||||||
GUI.skin.button.alignment = TextAnchor.MiddleCenter;
|
|
||||||
}
|
}
|
||||||
|
else if (value is Vector4 vec4)
|
||||||
|
{
|
||||||
|
label = vec4.ToString();
|
||||||
|
}
|
||||||
|
else if (value is Vector3 vec3)
|
||||||
|
{
|
||||||
|
label = vec3.ToString();
|
||||||
|
}
|
||||||
|
else if (value is Vector2 vec2)
|
||||||
|
{
|
||||||
|
label = vec2.ToString();
|
||||||
|
}
|
||||||
|
else if (value is Rect rec)
|
||||||
|
{
|
||||||
|
label = rec.ToString();
|
||||||
|
}
|
||||||
|
else if (value is Matrix4x4 matrix)
|
||||||
|
{
|
||||||
|
label = matrix.ToString();
|
||||||
|
}
|
||||||
|
else if (value is Color col)
|
||||||
|
{
|
||||||
|
label = col.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
GUI.skin.button.alignment = TextAnchor.MiddleLeft;
|
||||||
|
if (GUILayout.Button("<color=yellow>" + label + "</color>", new GUILayoutOption[] { GUILayout.MaxWidth(rect.width - 230) }))
|
||||||
|
{
|
||||||
|
WindowManager.InspectObject(value, out bool _);
|
||||||
|
}
|
||||||
|
GUI.skin.button.alignment = TextAnchor.MiddleCenter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//public static void DrawMember(ref object value, string valueType, string memberName, Rect rect, object setTarget = null, Action<object> setAction = null, float labelWidth = 180, bool autoSet = false)
|
||||||
|
//{
|
||||||
|
// GUILayout.Label("<color=cyan>" + memberName + ":</color>", new GUILayoutOption[] { GUILayout.Width(labelWidth) });
|
||||||
|
|
||||||
|
// DrawValue(ref value, rect, valueType, memberName, setTarget, setAction, autoSet);
|
||||||
|
//}
|
||||||
|
|
||||||
|
//public static void DrawValue(ref object value, Rect rect, string nullValueType = null, string memberName = null, object setTarget = null, Action<object> setAction = null, bool autoSet = false)
|
||||||
|
//{
|
||||||
|
// if (value == null)
|
||||||
|
// {
|
||||||
|
// GUILayout.Label("<i>null (" + nullValueType + ")</i>", null);
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
// Helper for drawing primitive values (with Apply button)
|
// Helper for drawing primitive values (with Apply button)
|
||||||
|
|
||||||
public static void DrawPrimitive(ref object value, Rect m_rect, object setTarget = null, Action<object> setAction = null, bool autoSet = false)
|
public static void DrawPrimitive(ref object value, Rect m_rect, object setTarget = null, Action<object> setAction = null, bool autoSet = false)
|
||||||
@ -387,10 +444,10 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
value = GUILayout.TextField(value.ToString(), new GUILayoutOption[] { GUILayout.MaxWidth(m_rect.width - 260) });
|
value = GUILayout.TextField(value.ToString(), new GUILayoutOption[] { GUILayout.MaxWidth(m_rect.width - 260) });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (autoSet || (allowSet && GUILayout.Button("<color=#00FF00>Apply</color>", new GUILayoutOption[] { GUILayout.Width(60) })))
|
if (autoSet || (allowSet && GUILayout.Button("<color=#00FF00>Apply</color>", new GUILayoutOption[] { GUILayout.Width(60) })))
|
||||||
{
|
{
|
||||||
setAction.Invoke(setTarget);
|
setAction.Invoke(setTarget);
|
||||||
}
|
}
|
||||||
|
@ -142,11 +142,11 @@ namespace Explorer
|
|||||||
|
|
||||||
// ============= Resize Window Helper ============
|
// ============= Resize Window Helper ============
|
||||||
|
|
||||||
static readonly GUIContent gcDrag = new GUIContent("<->");
|
//static readonly GUIContent gcDrag = new GUIContent("<->");
|
||||||
|
|
||||||
private static bool isResizing = false;
|
//private static bool isResizing = false;
|
||||||
private static Rect m_currentResize;
|
//private static Rect m_currentResize;
|
||||||
private static int m_currentWindow;
|
//private static int m_currentWindow;
|
||||||
|
|
||||||
public static Rect ResizeWindow(Rect _rect, int ID)
|
public static Rect ResizeWindow(Rect _rect, int ID)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user