mirror of
https://github.com/sinai-dev/UnityExplorer.git
synced 2025-01-05 17:13:43 +08:00
1.5.1
* Added support for Properties with an index parameter on the Reflection Window (ie. "this[index]") * Fixed a crash that occured when inspecting Il2CppSystem.Type objects * Back-end cleanups
This commit is contained in:
parent
916bdea59b
commit
2f3b779199
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using System.Reflection;
|
||||||
using MelonLoader;
|
using MelonLoader;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
@ -14,10 +15,25 @@ namespace Explorer
|
|||||||
public string[] EnumNames;
|
public string[] EnumNames;
|
||||||
|
|
||||||
public override void Init()
|
public override void Init()
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
EnumType = Value.GetType();
|
EnumType = Value.GetType();
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
EnumType = (MemInfo as FieldInfo)?.FieldType ?? (MemInfo as PropertyInfo).PropertyType;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (EnumType != null)
|
||||||
|
{
|
||||||
EnumNames = Enum.GetNames(EnumType);
|
EnumNames = Enum.GetNames(EnumType);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ReflectionException = "Unknown, could not get Enum names.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override void DrawValue(Rect window, float width)
|
public override void DrawValue(Rect window, float width)
|
||||||
{
|
{
|
||||||
|
@ -145,16 +145,16 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
if (m_entryType == null)
|
if (m_entryType == null)
|
||||||
{
|
{
|
||||||
if (this.MemberInfo != null)
|
if (this.MemInfo != null)
|
||||||
{
|
{
|
||||||
Type memberType = null;
|
Type memberType = null;
|
||||||
switch (this.MemberInfo.MemberType)
|
switch (this.MemInfo.MemberType)
|
||||||
{
|
{
|
||||||
case MemberTypes.Field:
|
case MemberTypes.Field:
|
||||||
memberType = (MemberInfo as FieldInfo).FieldType;
|
memberType = (MemInfo as FieldInfo).FieldType;
|
||||||
break;
|
break;
|
||||||
case MemberTypes.Property:
|
case MemberTypes.Property:
|
||||||
memberType = (MemberInfo as PropertyInfo).PropertyType;
|
memberType = (MemInfo as PropertyInfo).PropertyType;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -201,18 +201,48 @@ namespace Explorer
|
|||||||
while (enumerator.MoveNext())
|
while (enumerator.MoveNext())
|
||||||
{
|
{
|
||||||
var obj = enumerator.Current;
|
var obj = enumerator.Current;
|
||||||
var type = ReflectionHelpers.GetActualType(obj);
|
|
||||||
|
|
||||||
|
if (obj != null && ReflectionHelpers.GetActualType(obj) is Type t)
|
||||||
|
{
|
||||||
if (obj is Il2CppSystem.Object iObj)
|
if (obj is Il2CppSystem.Object iObj)
|
||||||
{
|
{
|
||||||
obj = iObj.Il2CppCast(type);
|
try
|
||||||
|
{
|
||||||
|
var cast = iObj.Il2CppCast(t);
|
||||||
|
if (cast != null)
|
||||||
|
{
|
||||||
|
obj = cast;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
}
|
}
|
||||||
|
|
||||||
var cached = GetCacheObject(obj, null, null, type);
|
if (GetCacheObject(obj, t) is CacheObjectBase cached)
|
||||||
cached.UpdateValue();
|
{
|
||||||
|
|
||||||
list.Add(cached);
|
list.Add(cached);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
list.Add(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
list.Add(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
//var type = ReflectionHelpers.GetActualType(obj);
|
||||||
|
|
||||||
|
//if (obj is Il2CppSystem.Object iObj)
|
||||||
|
//{
|
||||||
|
// obj = iObj.Il2CppCast(type);
|
||||||
|
//}
|
||||||
|
|
||||||
|
//var cached = GetCacheObject(obj, null, null, type);
|
||||||
|
//cached.UpdateValue();
|
||||||
|
|
||||||
|
//list.Add(cached);
|
||||||
|
}
|
||||||
|
|
||||||
m_cachedEntries = list.ToArray();
|
m_cachedEntries = list.ToArray();
|
||||||
}
|
}
|
||||||
@ -310,16 +340,18 @@ namespace Explorer
|
|||||||
|
|
||||||
GUILayout.Space(whitespace);
|
GUILayout.Space(whitespace);
|
||||||
|
|
||||||
if (entry.Value == null)
|
if (entry == null || entry.Value == null)
|
||||||
{
|
{
|
||||||
GUILayout.Label(i + "<i><color=grey> (null)</color></i>", null);
|
GUILayout.Label($"[{i}] <i><color=grey>(null)</color></i>", null);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
|
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
|
||||||
GUILayout.Label($"[{i}]", new GUILayoutOption[] { GUILayout.Width(30) });
|
GUILayout.Label($"[{i}]", new GUILayoutOption[] { GUILayout.Width(30) });
|
||||||
|
|
||||||
entry.DrawValue(window, window.width - (whitespace + 85));
|
entry.DrawValue(window, window.width - (whitespace + 85));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GUI.skin.label.alignment = TextAnchor.UpperLeft;
|
GUI.skin.label.alignment = TextAnchor.UpperLeft;
|
||||||
|
@ -24,7 +24,7 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
if (m_hasParams == null)
|
if (m_hasParams == null)
|
||||||
{
|
{
|
||||||
m_hasParams = (MemberInfo as MethodInfo).GetParameters().Length > 0;
|
m_hasParams = (MemInfo as MethodInfo).GetParameters().Length > 0;
|
||||||
}
|
}
|
||||||
return (bool)m_hasParams;
|
return (bool)m_hasParams;
|
||||||
}
|
}
|
||||||
@ -55,7 +55,7 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
base.Init();
|
base.Init();
|
||||||
|
|
||||||
var mi = MemberInfo as MethodInfo;
|
var mi = MemInfo as MethodInfo;
|
||||||
|
|
||||||
m_arguments = mi.GetParameters();
|
m_arguments = mi.GetParameters();
|
||||||
m_argumentInput = new string[m_arguments.Length];
|
m_argumentInput = new string[m_arguments.Length];
|
||||||
@ -136,12 +136,12 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GUILayout.Label($"null (<color=yellow>{ValueType}</color>)", null);
|
GUILayout.Label($"null (<color=yellow>{ValueTypeName}</color>)", null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GUILayout.Label($"<color=grey><i>Not yet evaluated</i></color> (<color=yellow>{ValueType}</color>)", null);
|
GUILayout.Label($"<color=grey><i>Not yet evaluated</i></color> (<color=yellow>{ValueTypeName}</color>)", null);
|
||||||
}
|
}
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
@ -150,7 +150,7 @@ namespace Explorer
|
|||||||
|
|
||||||
private void Evaluate()
|
private void Evaluate()
|
||||||
{
|
{
|
||||||
var mi = MemberInfo as MethodInfo;
|
var mi = MemInfo as MethodInfo;
|
||||||
|
|
||||||
object ret = null;
|
object ret = null;
|
||||||
|
|
||||||
|
@ -13,67 +13,70 @@ namespace Explorer
|
|||||||
public abstract class CacheObjectBase
|
public abstract class CacheObjectBase
|
||||||
{
|
{
|
||||||
public object Value;
|
public object Value;
|
||||||
public string ValueType;
|
public string ValueTypeName;
|
||||||
|
|
||||||
// Reflection window only
|
// Reflection Inspector only
|
||||||
public MemberInfo MemberInfo { get; set; }
|
public MemberInfo MemInfo { get; set; }
|
||||||
public Type DeclaringType { get; set; }
|
public Type DeclaringType { get; set; }
|
||||||
public object DeclaringInstance { get; set; }
|
public object DeclaringInstance { get; set; }
|
||||||
|
public string ReflectionException { get; set; }
|
||||||
|
|
||||||
public string RichTextName
|
public int PropertyIndex { get; private set; }
|
||||||
{
|
private string m_propertyIndexInput = "0";
|
||||||
get
|
|
||||||
{
|
public string RichTextName => m_richTextName ?? GetRichTextName();
|
||||||
if (m_richTextName == null)
|
|
||||||
{
|
|
||||||
GetRichTextName();
|
|
||||||
}
|
|
||||||
return m_richTextName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private string m_richTextName;
|
private string m_richTextName;
|
||||||
|
|
||||||
public string ReflectionException;
|
|
||||||
|
|
||||||
public bool CanWrite
|
public bool CanWrite
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (MemberInfo is FieldInfo fi)
|
if (MemInfo is FieldInfo fi)
|
||||||
{
|
|
||||||
return !(fi.IsLiteral && !fi.IsInitOnly);
|
return !(fi.IsLiteral && !fi.IsInitOnly);
|
||||||
}
|
else if (MemInfo is PropertyInfo pi)
|
||||||
else if (MemberInfo is PropertyInfo pi)
|
|
||||||
{
|
|
||||||
return pi.CanWrite;
|
return pi.CanWrite;
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// methods
|
// ===== Abstract/Virtual Methods ===== //
|
||||||
|
|
||||||
public virtual void Init() { }
|
public virtual void Init() { }
|
||||||
|
|
||||||
public abstract void DrawValue(Rect window, float width);
|
public abstract void DrawValue(Rect window, float width);
|
||||||
|
|
||||||
|
// ===== Static Methods ===== //
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get CacheObject from only an object instance
|
||||||
|
/// Calls GetCacheObject(obj, memberInfo, declaringInstance) with (obj, null, null)</summary>
|
||||||
public static CacheObjectBase GetCacheObject(object obj)
|
public static CacheObjectBase GetCacheObject(object obj)
|
||||||
{
|
{
|
||||||
return GetCacheObject(obj, null, null);
|
return GetCacheObject(obj, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the CacheObject subclass for an object or MemberInfo
|
/// Get CacheObject from an object instance and provide the value type
|
||||||
/// </summary>
|
/// Calls GetCacheObjectImpl directly</summary>
|
||||||
/// <param name="obj">The current value (can be null if memberInfo is not null)</param>
|
public static CacheObjectBase GetCacheObject(object obj, Type valueType)
|
||||||
/// <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>
|
return GetCacheObjectImpl(obj, null, null, valueType);
|
||||||
/// <returns></returns>
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get CacheObject from only a MemberInfo and declaring instance
|
||||||
|
/// Calls GetCacheObject(obj, memberInfo, declaringInstance) with (null, memberInfo, declaringInstance)</summary>
|
||||||
|
public static CacheObjectBase GetCacheObject(MemberInfo memberInfo, object declaringInstance)
|
||||||
|
{
|
||||||
|
return GetCacheObject(null, memberInfo, declaringInstance);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get CacheObject from either an object or MemberInfo, and don't provide the type.
|
||||||
|
/// This gets the type and then calls GetCacheObjectImpl</summary>
|
||||||
public static CacheObjectBase GetCacheObject(object obj, MemberInfo memberInfo, object declaringInstance)
|
public static CacheObjectBase GetCacheObject(object obj, MemberInfo memberInfo, object declaringInstance)
|
||||||
{
|
{
|
||||||
//var type = ReflectionHelpers.GetActualType(obj) ?? (memberInfo as FieldInfo)?.FieldType ?? (memberInfo as PropertyInfo)?.PropertyType;
|
|
||||||
|
|
||||||
Type type = null;
|
Type type = null;
|
||||||
|
|
||||||
if (obj != null)
|
if (obj != null)
|
||||||
@ -101,18 +104,13 @@ namespace Explorer
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return GetCacheObject(obj, memberInfo, declaringInstance, type);
|
return GetCacheObjectImpl(obj, memberInfo, declaringInstance, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the CacheObject subclass for an object or MemberInfo
|
/// Actual GetCacheObject implementation (private)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="obj">The current value (can be null if memberInfo is not null)</param>
|
private static CacheObjectBase GetCacheObjectImpl(object obj, MemberInfo memberInfo, object declaringInstance, Type valueType)
|
||||||
/// <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="valueType">The type of the object or MemberInfo value.</param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static CacheObjectBase GetCacheObject(object obj, MemberInfo memberInfo, object declaringInstance, Type valueType)
|
|
||||||
{
|
{
|
||||||
CacheObjectBase holder;
|
CacheObjectBase holder;
|
||||||
|
|
||||||
@ -153,11 +151,11 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
|
|
||||||
holder.Value = obj;
|
holder.Value = obj;
|
||||||
holder.ValueType = valueType.FullName;
|
holder.ValueTypeName = valueType.FullName;
|
||||||
|
|
||||||
if (memberInfo != null)
|
if (memberInfo != null)
|
||||||
{
|
{
|
||||||
holder.MemberInfo = memberInfo;
|
holder.MemInfo = memberInfo;
|
||||||
holder.DeclaringType = memberInfo.DeclaringType;
|
holder.DeclaringType = memberInfo.DeclaringType;
|
||||||
holder.DeclaringInstance = declaringInstance;
|
holder.DeclaringInstance = declaringInstance;
|
||||||
|
|
||||||
@ -169,30 +167,40 @@ namespace Explorer
|
|||||||
return holder;
|
return holder;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ======== Updating and Setting Value (memberinfo only) =========
|
// ======== Instance Methods =========
|
||||||
|
|
||||||
public virtual void UpdateValue()
|
public virtual void UpdateValue()
|
||||||
{
|
{
|
||||||
if (MemberInfo == null || !string.IsNullOrEmpty(ReflectionException))
|
if (MemInfo == null || !string.IsNullOrEmpty(ReflectionException))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (MemberInfo.MemberType == MemberTypes.Field)
|
if (MemInfo.MemberType == MemberTypes.Field)
|
||||||
{
|
{
|
||||||
var fi = MemberInfo as FieldInfo;
|
var fi = MemInfo as FieldInfo;
|
||||||
Value = fi.GetValue(fi.IsStatic ? null : DeclaringInstance);
|
Value = fi.GetValue(fi.IsStatic ? null : DeclaringInstance);
|
||||||
}
|
}
|
||||||
else if (MemberInfo.MemberType == MemberTypes.Property)
|
else if (MemInfo.MemberType == MemberTypes.Property)
|
||||||
{
|
{
|
||||||
var pi = MemberInfo as PropertyInfo;
|
var pi = MemInfo as PropertyInfo;
|
||||||
bool isStatic = pi.GetAccessors()[0].IsStatic;
|
bool isStatic = pi.GetAccessors()[0].IsStatic;
|
||||||
var target = isStatic ? null : DeclaringInstance;
|
var target = isStatic ? null : DeclaringInstance;
|
||||||
|
|
||||||
|
if (pi.GetIndexParameters().Length > 0)
|
||||||
|
{
|
||||||
|
var indexes = new object[] { PropertyIndex };
|
||||||
|
Value = pi.GetValue(target, indexes);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
Value = pi.GetValue(target, null);
|
Value = pi.GetValue(target, null);
|
||||||
}
|
}
|
||||||
//ReflectionException = null;
|
}
|
||||||
|
|
||||||
|
ReflectionException = null;
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@ -204,24 +212,33 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (MemberInfo.MemberType == MemberTypes.Field)
|
if (MemInfo.MemberType == MemberTypes.Field)
|
||||||
{
|
{
|
||||||
var fi = MemberInfo as FieldInfo;
|
var fi = MemInfo as FieldInfo;
|
||||||
fi.SetValue(fi.IsStatic ? null : DeclaringInstance, Value);
|
fi.SetValue(fi.IsStatic ? null : DeclaringInstance, Value);
|
||||||
}
|
}
|
||||||
else if (MemberInfo.MemberType == MemberTypes.Property)
|
else if (MemInfo.MemberType == MemberTypes.Property)
|
||||||
|
{
|
||||||
|
var pi = MemInfo as PropertyInfo;
|
||||||
|
|
||||||
|
if (pi.GetIndexParameters().Length > 0)
|
||||||
|
{
|
||||||
|
var indexes = new object[] { PropertyIndex };
|
||||||
|
pi.SetValue(pi.GetAccessors()[0].IsStatic ? null : DeclaringInstance, Value, indexes);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
var pi = MemberInfo as PropertyInfo;
|
|
||||||
pi.SetValue(pi.GetAccessors()[0].IsStatic ? null : DeclaringInstance, Value);
|
pi.SetValue(pi.GetAccessors()[0].IsStatic ? null : DeclaringInstance, Value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
MelonLogger.LogWarning($"Error setting value: {e.GetType()}, {e.Message}");
|
MelonLogger.LogWarning($"Error setting value: {e.GetType()}, {e.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ========= Gui Draw ==========
|
// ========= Instance Gui Draw ==========
|
||||||
|
|
||||||
public const float MAX_LABEL_WIDTH = 400f;
|
public const float MAX_LABEL_WIDTH = 400f;
|
||||||
|
|
||||||
@ -240,11 +257,15 @@ namespace Explorer
|
|||||||
ClampLabelWidth(window, ref labelWidth);
|
ClampLabelWidth(window, ref labelWidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MemberInfo != null)
|
if (MemInfo != null)
|
||||||
{
|
{
|
||||||
|
var name = RichTextName;
|
||||||
|
if (MemInfo is PropertyInfo pi && pi.GetIndexParameters().Length > 0)
|
||||||
|
{
|
||||||
|
name += $"[{PropertyIndex}]";
|
||||||
|
}
|
||||||
|
|
||||||
|
GUILayout.Label(name, new GUILayoutOption[] { GUILayout.Width(labelWidth) });
|
||||||
GUILayout.Label(RichTextName, new GUILayoutOption[] { GUILayout.Width(labelWidth) });
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -255,20 +276,44 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
GUILayout.Label("<color=red>Reflection failed!</color> (" + ReflectionException + ")", null);
|
GUILayout.Label("<color=red>Reflection failed!</color> (" + ReflectionException + ")", null);
|
||||||
}
|
}
|
||||||
else if (Value == null && MemberInfo?.MemberType != MemberTypes.Method)
|
else if (Value == null && MemInfo?.MemberType != MemberTypes.Method)
|
||||||
{
|
{
|
||||||
GUILayout.Label("<i>null (" + ValueType + ")</i>", null);
|
GUILayout.Label("<i>null (" + ValueTypeName + ")</i>", null);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (MemInfo is PropertyInfo pi && pi.GetIndexParameters().Length > 0)
|
||||||
|
{
|
||||||
|
GUILayout.Label("index:", new GUILayoutOption[] { GUILayout.Width(50) });
|
||||||
|
|
||||||
|
m_propertyIndexInput = GUILayout.TextField(m_propertyIndexInput, new GUILayoutOption[] { GUILayout.Width(100) });
|
||||||
|
if (GUILayout.Button("Set", new GUILayoutOption[] { GUILayout.Width(60) }))
|
||||||
|
{
|
||||||
|
if (int.TryParse(m_propertyIndexInput, out int i))
|
||||||
|
{
|
||||||
|
PropertyIndex = i;
|
||||||
|
UpdateValue();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MelonLogger.Log($"Could not parse '{m_propertyIndexInput}' to an int!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// new line and space
|
||||||
|
GUILayout.EndHorizontal();
|
||||||
|
GUILayout.BeginHorizontal(null);
|
||||||
|
GUILayout.Space(labelWidth);
|
||||||
|
}
|
||||||
|
|
||||||
DrawValue(window, window.width - labelWidth - 90);
|
DrawValue(window, window.width - labelWidth - 90);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GetRichTextName()
|
private string GetRichTextName()
|
||||||
{
|
{
|
||||||
string memberColor = "";
|
string memberColor = "";
|
||||||
switch (MemberInfo.MemberType)
|
switch (MemInfo.MemberType)
|
||||||
{
|
{
|
||||||
case MemberTypes.Field:
|
case MemberTypes.Field:
|
||||||
memberColor = "#c266ff"; break;
|
memberColor = "#c266ff"; break;
|
||||||
@ -278,9 +323,9 @@ namespace Explorer
|
|||||||
memberColor = "#ff8000"; break;
|
memberColor = "#ff8000"; break;
|
||||||
};
|
};
|
||||||
|
|
||||||
m_richTextName = $"<color=#2df7b2>{MemberInfo.DeclaringType.Name}</color>.<color={memberColor}>{MemberInfo.Name}</color>";
|
m_richTextName = $"<color=#2df7b2>{MemInfo.DeclaringType.Name}</color>.<color={memberColor}>{MemInfo.Name}</color>";
|
||||||
|
|
||||||
if (MemberInfo is MethodInfo mi)
|
if (MemInfo is MethodInfo mi)
|
||||||
{
|
{
|
||||||
m_richTextName += "(";
|
m_richTextName += "(";
|
||||||
var _params = "";
|
var _params = "";
|
||||||
@ -293,6 +338,8 @@ namespace Explorer
|
|||||||
m_richTextName += _params;
|
m_richTextName += _params;
|
||||||
m_richTextName += ")";
|
m_richTextName += ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return m_richTextName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,34 +12,26 @@ namespace Explorer
|
|||||||
public class CacheOther : CacheObjectBase
|
public class CacheOther : CacheObjectBase
|
||||||
{
|
{
|
||||||
private MethodInfo m_toStringMethod;
|
private MethodInfo m_toStringMethod;
|
||||||
private bool m_triedToGetMethod;
|
|
||||||
|
|
||||||
public MethodInfo ToStringMethod
|
public MethodInfo ToStringMethod
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (m_toStringMethod == null && !m_triedToGetMethod)
|
if (m_toStringMethod == null)
|
||||||
{
|
{
|
||||||
if (Value == null) return null;
|
|
||||||
|
|
||||||
m_triedToGetMethod = true;
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var methods = ReflectionHelpers.GetActualType(Value)
|
m_toStringMethod = ReflectionHelpers.GetActualType(Value).GetMethod("ToString", new Type[0])
|
||||||
.GetMethods(ReflectionHelpers.CommonFlags)
|
?? typeof(object).GetMethod("ToString", new Type[0]);
|
||||||
.Where(x => x.Name == "ToString")
|
|
||||||
.GetEnumerator();
|
|
||||||
|
|
||||||
while (methods.MoveNext())
|
// test invoke
|
||||||
|
m_toStringMethod.Invoke(Value, null);
|
||||||
|
}
|
||||||
|
catch
|
||||||
{
|
{
|
||||||
// just get the first (top-most level) method, then break.
|
m_toStringMethod = typeof(object).GetMethod("ToString", new Type[0]);
|
||||||
m_toStringMethod = methods.Current;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch { }
|
|
||||||
}
|
|
||||||
return m_toStringMethod;
|
return m_toStringMethod;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -48,9 +40,9 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
string label = (string)ToStringMethod?.Invoke(Value, null) ?? Value.ToString();
|
string label = (string)ToStringMethod?.Invoke(Value, null) ?? Value.ToString();
|
||||||
|
|
||||||
if (!label.Contains(ValueType))
|
if (!label.Contains(ValueTypeName))
|
||||||
{
|
{
|
||||||
label += $" ({ValueType})";
|
label += $" ({ValueTypeName})";
|
||||||
}
|
}
|
||||||
if (Value is UnityEngine.Object unityObj && !label.Contains(unityObj.name))
|
if (Value is UnityEngine.Object unityObj && !label.Contains(unityObj.name))
|
||||||
{
|
{
|
||||||
@ -58,7 +50,7 @@ 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 + 40) }))
|
if (GUILayout.Button("<color=yellow>" + label + "</color>", new GUILayoutOption[] { GUILayout.Width(width) }))
|
||||||
{
|
{
|
||||||
WindowManager.InspectObject(Value, out bool _);
|
WindowManager.InspectObject(Value, out bool _);
|
||||||
}
|
}
|
||||||
|
@ -152,7 +152,7 @@ namespace Explorer
|
|||||||
|
|
||||||
public void SetValueFromInput(string value)
|
public void SetValueFromInput(string value)
|
||||||
{
|
{
|
||||||
if (MemberInfo == null)
|
if (MemInfo == null)
|
||||||
{
|
{
|
||||||
MelonLogger.Log("Trying to SetValue but the MemberInfo is null!");
|
MelonLogger.Log("Trying to SetValue but the MemberInfo is null!");
|
||||||
return;
|
return;
|
||||||
|
@ -133,7 +133,7 @@ namespace Explorer
|
|||||||
// value that we set back to when we close the menu or disable force-unlock.
|
// value that we set back to when we close the menu or disable force-unlock.
|
||||||
|
|
||||||
[HarmonyPatch(typeof(Cursor), nameof(Cursor.lockState), MethodType.Setter)]
|
[HarmonyPatch(typeof(Cursor), nameof(Cursor.lockState), MethodType.Setter)]
|
||||||
public class Cursor_lockState
|
public class Cursor_set_lockState
|
||||||
{
|
{
|
||||||
[HarmonyPrefix]
|
[HarmonyPrefix]
|
||||||
public static void Prefix(ref CursorLockMode value)
|
public static void Prefix(ref CursorLockMode value)
|
||||||
@ -170,19 +170,6 @@ namespace Explorer
|
|||||||
|
|
||||||
// Make it appear as though UnlockMouse is disabled to the rest of the application.
|
// Make it appear as though UnlockMouse is disabled to the rest of the application.
|
||||||
|
|
||||||
[HarmonyPatch(typeof(Cursor), nameof(Cursor.visible), MethodType.Getter)]
|
|
||||||
public class Cursor_get_visible
|
|
||||||
{
|
|
||||||
[HarmonyPostfix]
|
|
||||||
public static void Postfix(ref bool __result)
|
|
||||||
{
|
|
||||||
if (ShouldForceMouse)
|
|
||||||
{
|
|
||||||
__result = m_lastVisibleState;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[HarmonyPatch(typeof(Cursor), nameof(Cursor.lockState), MethodType.Getter)]
|
[HarmonyPatch(typeof(Cursor), nameof(Cursor.lockState), MethodType.Getter)]
|
||||||
public class Cursor_get_lockState
|
public class Cursor_get_lockState
|
||||||
{
|
{
|
||||||
@ -195,5 +182,18 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HarmonyPatch(typeof(Cursor), nameof(Cursor.visible), MethodType.Getter)]
|
||||||
|
public class Cursor_get_visible
|
||||||
|
{
|
||||||
|
[HarmonyPostfix]
|
||||||
|
public static void Postfix(ref bool __result)
|
||||||
|
{
|
||||||
|
if (ShouldForceMouse)
|
||||||
|
{
|
||||||
|
__result = m_lastVisibleState;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,9 @@
|
|||||||
<HintPath>..\..\..\..\..\Steam\steamapps\common\Hellpoint\MelonLoader\Managed\UnhollowerBaseLib.dll</HintPath>
|
<HintPath>..\..\..\..\..\Steam\steamapps\common\Hellpoint\MelonLoader\Managed\UnhollowerBaseLib.dll</HintPath>
|
||||||
<Private>False</Private>
|
<Private>False</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
|
||||||
<!-- Unity 2019 build (InputLegacyModule.dll) -->
|
<!-- Unity 2019 build (InputLegacyModule.dll) -->
|
||||||
|
|
||||||
<Reference Include="UnityEngine" Condition="'$(Configuration)'=='Debug'">
|
<Reference Include="UnityEngine" Condition="'$(Configuration)'=='Debug'">
|
||||||
<HintPath>..\..\..\Steam\steamapps\common\Hellpoint\MelonLoader\Managed\UnityEngine.dll</HintPath>
|
<HintPath>..\..\..\Steam\steamapps\common\Hellpoint\MelonLoader\Managed\UnityEngine.dll</HintPath>
|
||||||
<Private>False</Private>
|
<Private>False</Private>
|
||||||
@ -89,7 +91,9 @@
|
|||||||
<HintPath>..\..\..\Steam\steamapps\common\Hellpoint\MelonLoader\Managed\UnityEngine.UI.dll</HintPath>
|
<HintPath>..\..\..\Steam\steamapps\common\Hellpoint\MelonLoader\Managed\UnityEngine.UI.dll</HintPath>
|
||||||
<Private>False</Private>
|
<Private>False</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
|
||||||
<!-- Unity 2018 build (InputModule.dll) -->
|
<!-- Unity 2018 build (InputModule.dll) -->
|
||||||
|
|
||||||
<Reference Include="UnityEngine" Condition="'$(Configuration)'=='Release_Unity2018'">
|
<Reference Include="UnityEngine" Condition="'$(Configuration)'=='Release_Unity2018'">
|
||||||
<HintPath>..\..\..\Steam\steamapps\common\VRChat\MelonLoader\Managed\UnityEngine.dll</HintPath>
|
<HintPath>..\..\..\Steam\steamapps\common\VRChat\MelonLoader\Managed\UnityEngine.dll</HintPath>
|
||||||
<Private>False</Private>
|
<Private>False</Private>
|
||||||
@ -118,6 +122,7 @@
|
|||||||
<HintPath>..\..\..\Steam\steamapps\common\VRChat\MelonLoader\Managed\UnityEngine.UI.dll</HintPath>
|
<HintPath>..\..\..\Steam\steamapps\common\VRChat\MelonLoader\Managed\UnityEngine.UI.dll</HintPath>
|
||||||
<Private>False</Private>
|
<Private>False</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="CachedObjects\CacheDictionary.cs" />
|
<Compile Include="CachedObjects\CacheDictionary.cs" />
|
||||||
|
@ -8,6 +8,7 @@ using UnhollowerBaseLib;
|
|||||||
using UnhollowerRuntimeLib;
|
using UnhollowerRuntimeLib;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using BF = System.Reflection.BindingFlags;
|
using BF = System.Reflection.BindingFlags;
|
||||||
|
using MelonLoader;
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer
|
||||||
{
|
{
|
||||||
@ -27,8 +28,9 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
if (!typeof(Il2CppSystem.Object).IsAssignableFrom(castTo)) return obj;
|
if (!typeof(Il2CppSystem.Object).IsAssignableFrom(castTo)) return obj;
|
||||||
|
|
||||||
var generic = m_tryCastMethodInfo.MakeGenericMethod(castTo);
|
return m_tryCastMethodInfo
|
||||||
return generic.Invoke(obj, null);
|
.MakeGenericMethod(castTo)
|
||||||
|
.Invoke(obj, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string ExceptionToString(Exception e)
|
public static string ExceptionToString(Exception e)
|
||||||
@ -81,9 +83,10 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
if (t.IsGenericType)
|
if (t.IsGenericType)
|
||||||
{
|
{
|
||||||
return t.GetGenericTypeDefinition() is Type typeDef
|
var generic = t.GetGenericTypeDefinition();
|
||||||
&& (typeDef.IsAssignableFrom(typeof(Il2CppSystem.Collections.Generic.List<>))
|
|
||||||
|| typeDef.IsAssignableFrom(typeof(Il2CppSystem.Collections.Generic.IList<>)));
|
return generic.IsAssignableFrom(typeof(Il2CppSystem.Collections.Generic.List<>))
|
||||||
|
|| generic.IsAssignableFrom(typeof(Il2CppSystem.Collections.Generic.IList<>));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -115,59 +118,37 @@ namespace Explorer
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Type GetActualType(object m_object)
|
public static Type GetActualType(object obj)
|
||||||
{
|
{
|
||||||
if (m_object == null) return null;
|
if (obj == null) return null;
|
||||||
|
|
||||||
if (m_object is Il2CppSystem.Object ilObject)
|
if (obj is Il2CppSystem.Object ilObject)
|
||||||
{
|
{
|
||||||
var iltype = ilObject.GetIl2CppType();
|
var ilTypeName = ilObject.GetIl2CppType().AssemblyQualifiedName;
|
||||||
if (Type.GetType(iltype.AssemblyQualifiedName) is Type type)
|
|
||||||
|
if (Type.GetType(ilTypeName) is Type t && !t.FullName.Contains("System.RuntimeType"))
|
||||||
{
|
{
|
||||||
return type;
|
return t;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
return ilObject.GetType();
|
return ilObject.GetType();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
return obj.GetType();
|
||||||
{
|
|
||||||
return m_object.GetType();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Type[] GetAllBaseTypes(object m_object)
|
public static Type[] GetAllBaseTypes(object obj)
|
||||||
{
|
{
|
||||||
var list = new List<Type>();
|
var list = new List<Type>();
|
||||||
|
|
||||||
if (m_object is Il2CppSystem.Object ilObject)
|
var type = GetActualType(obj);
|
||||||
{
|
|
||||||
var ilType = ilObject.GetIl2CppType();
|
|
||||||
if (Type.GetType(ilType.AssemblyQualifiedName) is Type ilTypeToManaged)
|
|
||||||
{
|
|
||||||
list.Add(ilTypeToManaged);
|
|
||||||
|
|
||||||
while (ilType.BaseType != null)
|
|
||||||
{
|
|
||||||
ilType = ilType.BaseType;
|
|
||||||
if (Type.GetType(ilType.AssemblyQualifiedName) is Type ilBaseTypeToManaged)
|
|
||||||
{
|
|
||||||
list.Add(ilBaseTypeToManaged);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var type = m_object.GetType();
|
|
||||||
list.Add(type);
|
list.Add(type);
|
||||||
|
|
||||||
while (type.BaseType != null)
|
while (type.BaseType != null)
|
||||||
{
|
{
|
||||||
type = type.BaseType;
|
type = type.BaseType;
|
||||||
list.Add(type);
|
list.Add(type);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return list.ToArray();
|
return list.ToArray();
|
||||||
}
|
}
|
||||||
|
@ -33,12 +33,14 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void HorizontalLine(Color color)
|
public static void HorizontalLine(Color _color, bool small = false)
|
||||||
{
|
{
|
||||||
var c = GUI.color;
|
var orig = GUI.color;
|
||||||
GUI.color = color;
|
|
||||||
GUILayout.Box(GUIContent.none, HorizontalBar, null);
|
GUI.color = _color;
|
||||||
GUI.color = c;
|
GUILayout.Box(GUIContent.none, !small ? HorizontalBar : HorizontalBarSmall, null);
|
||||||
|
|
||||||
|
GUI.color = orig;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static GUISkin _customSkin;
|
private static GUISkin _customSkin;
|
||||||
@ -46,8 +48,6 @@ namespace Explorer
|
|||||||
public static Texture2D m_nofocusTex;
|
public static Texture2D m_nofocusTex;
|
||||||
public static Texture2D m_focusTex;
|
public static Texture2D m_focusTex;
|
||||||
|
|
||||||
private static GUIStyle _horizBarStyle;
|
|
||||||
|
|
||||||
private static GUIStyle HorizontalBar
|
private static GUIStyle HorizontalBar
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@ -63,6 +63,24 @@ namespace Explorer
|
|||||||
return _horizBarStyle;
|
return _horizBarStyle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
private static GUIStyle _horizBarStyle;
|
||||||
|
|
||||||
|
private static GUIStyle HorizontalBarSmall
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_horizBarSmallStyle == null)
|
||||||
|
{
|
||||||
|
_horizBarSmallStyle = new GUIStyle();
|
||||||
|
_horizBarSmallStyle.normal.background = Texture2D.whiteTexture;
|
||||||
|
_horizBarSmallStyle.margin = new RectOffset(0, 0, 2, 2);
|
||||||
|
_horizBarSmallStyle.fixedHeight = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _horizBarSmallStyle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private static GUIStyle _horizBarSmallStyle;
|
||||||
|
|
||||||
private static GUISkin CreateWindowSkin()
|
private static GUISkin CreateWindowSkin()
|
||||||
{
|
{
|
||||||
|
@ -13,10 +13,10 @@ namespace Explorer
|
|||||||
public class ReflectionWindow : UIWindow
|
public class ReflectionWindow : UIWindow
|
||||||
{
|
{
|
||||||
public override string Title => WindowManager.TabView
|
public override string Title => WindowManager.TabView
|
||||||
? $"<color=cyan>[R]</color> {ObjectType.Name}"
|
? $"<color=cyan>[R]</color> {TargetType.Name}"
|
||||||
: $"Reflection Inspector ({ObjectType.Name})";
|
: $"Reflection Inspector ({TargetType.Name})";
|
||||||
|
|
||||||
public Type ObjectType;
|
public Type TargetType;
|
||||||
|
|
||||||
private CacheObjectBase[] m_allCachedMembers;
|
private CacheObjectBase[] m_allCachedMembers;
|
||||||
private CacheObjectBase[] m_cachedMembersFiltered;
|
private CacheObjectBase[] m_cachedMembersFiltered;
|
||||||
@ -35,16 +35,11 @@ namespace Explorer
|
|||||||
public override void Init()
|
public override void Init()
|
||||||
{
|
{
|
||||||
var type = ReflectionHelpers.GetActualType(Target);
|
var type = ReflectionHelpers.GetActualType(Target);
|
||||||
if (type == null)
|
|
||||||
{
|
|
||||||
MelonLogger.Log($"Could not get underlying type for object! Type: {Target?.GetType().AssemblyQualifiedName}, Value ToString: {Target?.ToString()}");
|
|
||||||
DestroyWindow();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ObjectType = type;
|
TargetType = type;
|
||||||
|
|
||||||
var types = ReflectionHelpers.GetAllBaseTypes(Target);
|
var types = ReflectionHelpers.GetAllBaseTypes(Target);
|
||||||
|
|
||||||
CacheMembers(types);
|
CacheMembers(types);
|
||||||
|
|
||||||
if (Target is Il2CppSystem.Object ilObject)
|
if (Target is Il2CppSystem.Object ilObject)
|
||||||
@ -90,13 +85,13 @@ namespace Explorer
|
|||||||
|
|
||||||
private bool ShouldProcessMember(CacheObjectBase holder)
|
private bool ShouldProcessMember(CacheObjectBase holder)
|
||||||
{
|
{
|
||||||
if (m_filter != MemberTypes.All && m_filter != holder.MemberInfo?.MemberType) return false;
|
if (m_filter != MemberTypes.All && m_filter != holder.MemInfo?.MemberType) return false;
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(holder.ReflectionException) && m_hideFailedReflection) return false;
|
if (!string.IsNullOrEmpty(holder.ReflectionException) && m_hideFailedReflection) return false;
|
||||||
|
|
||||||
if (m_search == "" || holder.MemberInfo == null) return true;
|
if (m_search == "" || holder.MemInfo == null) return true;
|
||||||
|
|
||||||
var name = holder.MemberInfo.DeclaringType.Name + "." + holder.MemberInfo.Name;
|
var name = holder.MemInfo.DeclaringType.Name + "." + holder.MemInfo.Name;
|
||||||
|
|
||||||
return name.ToLower().Contains(m_search.ToLower());
|
return name.ToLower().Contains(m_search.ToLower());
|
||||||
}
|
}
|
||||||
@ -118,7 +113,7 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
MelonLogger.Log("Exception getting members for type: " + declaringType.Name);
|
MelonLogger.Log($"Exception getting members for type: {declaringType.FullName}");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,11 +135,14 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
if (member.MemberType == MemberTypes.Field || member.MemberType == MemberTypes.Property || member.MemberType == MemberTypes.Method)
|
if (member.MemberType == MemberTypes.Field || member.MemberType == MemberTypes.Property || member.MemberType == MemberTypes.Method)
|
||||||
{
|
{
|
||||||
// ignore these
|
var name = $"{member.DeclaringType.Name}.{member.Name}";
|
||||||
if (member.Name.Contains("Il2CppType") || member.Name.StartsWith("get_") || member.Name.StartsWith("set_"))
|
|
||||||
continue;
|
// blacklist (should probably make a proper implementation)
|
||||||
|
if (name == "Type.DeclaringMethod" || member.Name.Contains("Il2CppType") || member.Name.StartsWith("get_") || member.Name.StartsWith("set_"))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
var name = member.DeclaringType.Name + "." + member.Name;
|
|
||||||
if (member is MethodInfo mi)
|
if (member is MethodInfo mi)
|
||||||
{
|
{
|
||||||
name += " (";
|
name += " (";
|
||||||
@ -161,7 +159,7 @@ namespace Explorer
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var cached = CacheObjectBase.GetCacheObject(null, member, target);
|
var cached = CacheObjectBase.GetCacheObject(member, target);
|
||||||
if (cached != null)
|
if (cached != null)
|
||||||
{
|
{
|
||||||
names.Add(name);
|
names.Add(name);
|
||||||
@ -198,7 +196,7 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(null);
|
||||||
GUILayout.Label("<b>Type:</b> <color=cyan>" + ObjectType.FullName + "</color>", new GUILayoutOption[] { GUILayout.Width(245f) });
|
GUILayout.Label("<b>Type:</b> <color=cyan>" + TargetType.FullName + "</color>", new GUILayoutOption[] { GUILayout.Width(245f) });
|
||||||
if (m_uObj)
|
if (m_uObj)
|
||||||
{
|
{
|
||||||
GUILayout.Label("Name: " + m_uObj.name, null);
|
GUILayout.Label("Name: " + m_uObj.name, null);
|
||||||
@ -298,11 +296,10 @@ namespace Explorer
|
|||||||
|
|
||||||
GUILayout.BeginVertical(GUI.skin.box, null);
|
GUILayout.BeginVertical(GUI.skin.box, null);
|
||||||
|
|
||||||
int index = 0;
|
|
||||||
var members = this.m_cachedMembersFiltered;
|
var members = this.m_cachedMembersFiltered;
|
||||||
int offsetIndex = (m_pageOffset * m_limitPerPage) + index;
|
int start = m_pageOffset * m_limitPerPage;
|
||||||
|
|
||||||
if (offsetIndex >= count)
|
if (start >= count)
|
||||||
{
|
{
|
||||||
int maxOffset = (int)Mathf.Ceil((float)(m_cachedMembersFiltered.Length / (decimal)m_limitPerPage)) - 1;
|
int maxOffset = (int)Mathf.Ceil((float)(m_cachedMembersFiltered.Length / (decimal)m_limitPerPage)) - 1;
|
||||||
if (m_pageOffset > maxOffset)
|
if (m_pageOffset > maxOffset)
|
||||||
@ -311,21 +308,25 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int j = offsetIndex; (j < offsetIndex + m_limitPerPage && j < members.Length); j++)
|
for (int j = start; (j < start + m_limitPerPage && j < members.Length); j++)
|
||||||
{
|
{
|
||||||
var holder = members[j];
|
var holder = members[j];
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[] { GUILayout.Height(25) });
|
GUILayout.BeginHorizontal(new GUILayoutOption[] { GUILayout.Height(25) });
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
holder.Draw(rect, 180f);
|
holder.Draw(rect, 180f);
|
||||||
}
|
}
|
||||||
catch { }
|
catch
|
||||||
|
{
|
||||||
|
GUILayout.EndHorizontal();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
index++;
|
// if not last element
|
||||||
|
if (!(j == (start + m_limitPerPage - 1) || j == (members.Length - 1)))
|
||||||
|
UIStyles.HorizontalLine(new Color(0.07f, 0.07f, 0.07f), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
GUILayout.EndVertical();
|
GUILayout.EndVertical();
|
||||||
|
@ -86,61 +86,6 @@ namespace Explorer
|
|||||||
|
|
||||||
// ========= Public Helpers =========
|
// ========= Public Helpers =========
|
||||||
|
|
||||||
public static bool IsMouseInWindow
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (!CppExplorer.ShowMenu)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var window in Windows)
|
|
||||||
{
|
|
||||||
if (RectContainsMouse(window.m_rect))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return RectContainsMouse(MainMenu.MainRect);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool RectContainsMouse(Rect rect)
|
|
||||||
{
|
|
||||||
return rect.Contains(new Vector2(Input.mousePosition.x, Screen.height - Input.mousePosition.y));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int NextWindowID()
|
|
||||||
{
|
|
||||||
return CurrentWindowID++;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Rect GetNewWindowRect()
|
|
||||||
{
|
|
||||||
return GetNewWindowRect(ref m_lastWindowRect);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Rect GetNewWindowRect(ref Rect lastRect)
|
|
||||||
{
|
|
||||||
Rect rect = new Rect(0, 0, 550, 700);
|
|
||||||
|
|
||||||
var mainrect = MainMenu.MainRect;
|
|
||||||
if (mainrect.x <= (Screen.width - mainrect.width - 100))
|
|
||||||
{
|
|
||||||
rect = new Rect(mainrect.x + mainrect.width + 20, mainrect.y, rect.width, rect.height);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lastRect.x == rect.x)
|
|
||||||
{
|
|
||||||
rect = new Rect(rect.x + 25, rect.y + 25, rect.width, rect.height);
|
|
||||||
}
|
|
||||||
|
|
||||||
lastRect = rect;
|
|
||||||
|
|
||||||
return rect;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static UIWindow InspectObject(object obj, out bool createdNew)
|
public static UIWindow InspectObject(object obj, out bool createdNew)
|
||||||
{
|
{
|
||||||
createdNew = false;
|
createdNew = false;
|
||||||
@ -206,5 +151,62 @@ namespace Explorer
|
|||||||
|
|
||||||
return new_window;
|
return new_window;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// === Misc Helpers ===
|
||||||
|
|
||||||
|
public static bool IsMouseInWindow
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (!CppExplorer.ShowMenu)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var window in Windows)
|
||||||
|
{
|
||||||
|
if (RectContainsMouse(window.m_rect))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return RectContainsMouse(MainMenu.MainRect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool RectContainsMouse(Rect rect)
|
||||||
|
{
|
||||||
|
return rect.Contains(new Vector2(Input.mousePosition.x, Screen.height - Input.mousePosition.y));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int NextWindowID()
|
||||||
|
{
|
||||||
|
return CurrentWindowID++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Rect GetNewWindowRect()
|
||||||
|
{
|
||||||
|
return GetNewWindowRect(ref m_lastWindowRect);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Rect GetNewWindowRect(ref Rect lastRect)
|
||||||
|
{
|
||||||
|
Rect rect = new Rect(0, 0, 550, 700);
|
||||||
|
|
||||||
|
var mainrect = MainMenu.MainRect;
|
||||||
|
if (mainrect.x <= (Screen.width - mainrect.width - 100))
|
||||||
|
{
|
||||||
|
rect = new Rect(mainrect.x + mainrect.width + 20, mainrect.y, rect.width, rect.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lastRect.x == rect.x)
|
||||||
|
{
|
||||||
|
rect = new Rect(rect.x + 25, rect.y + 25, rect.width, rect.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
lastRect = rect;
|
||||||
|
|
||||||
|
return rect;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user