mirror of
https://github.com/sinai-dev/UnityExplorer.git
synced 2025-06-22 16:42:38 +08:00
Compare commits
15 Commits
Author | SHA1 | Date | |
---|---|---|---|
f203ae37fc | |||
2006a9ea76 | |||
c9bc450d09 | |||
a1198f3a92 | |||
04248a89ce | |||
3639824df3 | |||
939861b5f0 | |||
ad5fc04a3b | |||
c39e097378 | |||
129a7e3765 | |||
643bb4519c | |||
b154cbf39d | |||
db91968519 | |||
5d58993b07 | |||
eea581f8d5 |
@ -65,7 +65,7 @@ This config is generated to `Mods\CppExplorer\config.xml`. Edit the config while
|
||||
* Default: `<x>550</x> <y>700</y>`
|
||||
|
||||
## Features
|
||||
[](overview.png)
|
||||
[](https://raw.githubusercontent.com/sinai-dev/CppExplorer/master/overview.png)
|
||||
|
||||
<i>An overview of the different CppExplorer menus.</i>
|
||||
|
||||
@ -99,9 +99,9 @@ CppExplorer has two main inspector modes: <b>GameObject Inspector</b>, and <b>Re
|
||||
* Filter by name, type, etc.
|
||||
* For GameObjects and Transforms you can filter which scene they are found in too.
|
||||
|
||||
### C# REPL console
|
||||
### C# console
|
||||
|
||||
* A simple C# REPL console, allows you to execute a method body on the fly.
|
||||
* A simple C# console, allows you to execute a method body on the fly.
|
||||
|
||||
### Inspect-under-mouse
|
||||
|
||||
|
@ -2,10 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using MelonLoader;
|
||||
using UnhollowerBaseLib;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Explorer
|
||||
@ -13,14 +10,14 @@ namespace Explorer
|
||||
public abstract class CacheObjectBase
|
||||
{
|
||||
public object Value;
|
||||
public string ValueTypeName;
|
||||
public Type ValueType;
|
||||
|
||||
public MemberInfo MemInfo { get; set; }
|
||||
public Type DeclaringType { get; set; }
|
||||
public object DeclaringInstance { get; set; }
|
||||
|
||||
public bool HasParameters => m_arguments != null && m_arguments.Length > 0;
|
||||
public virtual bool HasParameters => m_arguments != null && m_arguments.Length > 0;
|
||||
|
||||
public bool m_evaluated = false;
|
||||
public bool m_isEvaluating;
|
||||
public ParameterInfo[] m_arguments = new ParameterInfo[0];
|
||||
@ -117,27 +114,16 @@ namespace Explorer
|
||||
var pi = memberInfo as PropertyInfo;
|
||||
var mi = memberInfo as MethodInfo;
|
||||
|
||||
// if PropertyInfo, check if can process args
|
||||
if (pi != null && !CanProcessArgs(pi.GetIndexParameters()))
|
||||
// Check if can process args
|
||||
if ((pi != null && !CanProcessArgs(pi.GetIndexParameters()))
|
||||
|| (mi != null && !CanProcessArgs(mi.GetParameters())))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// This is pretty ugly, could probably make a cleaner implementation.
|
||||
// However, the only cleaner ways I can think of are slower and probably not worth it.
|
||||
|
||||
// Note: the order is somewhat important.
|
||||
|
||||
if (mi != null)
|
||||
{
|
||||
if (CacheMethod.CanEvaluate(mi))
|
||||
{
|
||||
holder = new CacheMethod();
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
holder = new CacheMethod();
|
||||
}
|
||||
else if (valueType == typeof(GameObject) || valueType == typeof(Transform))
|
||||
{
|
||||
@ -149,7 +135,14 @@ namespace Explorer
|
||||
}
|
||||
else if (valueType.IsEnum)
|
||||
{
|
||||
holder = new CacheEnum();
|
||||
if (valueType.GetCustomAttributes(typeof(FlagsAttribute), false) is object[] attributes && attributes.Length > 0)
|
||||
{
|
||||
holder = new CacheEnumFlags();
|
||||
}
|
||||
else
|
||||
{
|
||||
holder = new CacheEnum();
|
||||
}
|
||||
}
|
||||
else if (valueType == typeof(Vector2) || valueType == typeof(Vector3) || valueType == typeof(Vector4))
|
||||
{
|
||||
@ -172,7 +165,7 @@ namespace Explorer
|
||||
{
|
||||
holder = new CacheDictionary();
|
||||
}
|
||||
else if (ReflectionHelpers.IsEnumerable(valueType) || ReflectionHelpers.IsCppEnumerable(valueType))
|
||||
else if (ReflectionHelpers.IsEnumerable(valueType))
|
||||
{
|
||||
holder = new CacheList();
|
||||
}
|
||||
@ -183,7 +176,6 @@ namespace Explorer
|
||||
|
||||
holder.Value = obj;
|
||||
holder.ValueType = valueType;
|
||||
holder.ValueTypeName = valueType.FullName;
|
||||
|
||||
if (memberInfo != null)
|
||||
{
|
||||
@ -214,7 +206,18 @@ namespace Explorer
|
||||
{
|
||||
foreach (var param in parameters)
|
||||
{
|
||||
if (!param.ParameterType.IsPrimitive && param.ParameterType != typeof(string))
|
||||
var pType = param.ParameterType;
|
||||
|
||||
if (pType.IsByRef && pType.HasElementType)
|
||||
{
|
||||
pType = pType.GetElementType();
|
||||
}
|
||||
|
||||
if (pType.IsPrimitive || pType == typeof(string))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -244,6 +247,11 @@ namespace Explorer
|
||||
var input = m_argumentInput[i];
|
||||
var type = m_arguments[i].ParameterType;
|
||||
|
||||
if (type.IsByRef)
|
||||
{
|
||||
type = type.GetElementType();
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(input))
|
||||
{
|
||||
// strings can obviously just be used directly
|
||||
@ -308,14 +316,7 @@ namespace Explorer
|
||||
var pi = MemInfo as PropertyInfo;
|
||||
var target = pi.GetAccessors()[0].IsStatic ? null : DeclaringInstance;
|
||||
|
||||
if (HasParameters)
|
||||
{
|
||||
Value = pi.GetValue(target, ParseArguments());
|
||||
}
|
||||
else
|
||||
{
|
||||
Value = pi.GetValue(target, null);
|
||||
}
|
||||
Value = pi.GetValue(target, ParseArguments());
|
||||
}
|
||||
|
||||
ReflectionException = null;
|
||||
@ -394,25 +395,73 @@ namespace Explorer
|
||||
|
||||
if (m_isEvaluating)
|
||||
{
|
||||
for (int i = 0; i < m_arguments.Length; i++)
|
||||
if (cm != null && cm.GenericArgs.Length > 0)
|
||||
{
|
||||
var name = m_arguments[i].Name;
|
||||
var input = m_argumentInput[i];
|
||||
var type = m_arguments[i].ParameterType.Name;
|
||||
GUILayout.Label($"<b><color=orange>Generic Arguments:</color></b>", null);
|
||||
|
||||
var label = "<color=#2df7b2>" + type + "</color> <color=#a6e9e9>" + name + "</color>";
|
||||
if (m_arguments[i].HasDefaultValue)
|
||||
for (int i = 0; i < cm.GenericArgs.Length; i++)
|
||||
{
|
||||
label = $"<i>[{label} = {m_arguments[i].DefaultValue}]</i>";
|
||||
string types = "";
|
||||
if (cm.GenericConstraints[i].Length > 0)
|
||||
{
|
||||
foreach (var constraint in cm.GenericConstraints[i])
|
||||
{
|
||||
if (types != "") types += ", ";
|
||||
|
||||
string type;
|
||||
|
||||
if (constraint == null)
|
||||
type = "Any";
|
||||
else
|
||||
type = constraint.ToString();
|
||||
|
||||
types += $"<color={UIStyles.Syntax.Class_Instance}>{type}</color>";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
types = $"<color={UIStyles.Syntax.Class_Instance}>Any</color>";
|
||||
}
|
||||
var input = cm.GenericArgInput[i];
|
||||
|
||||
GUILayout.BeginHorizontal(null);
|
||||
|
||||
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
|
||||
GUILayout.Label($"<color={UIStyles.Syntax.StructGreen}>{cm.GenericArgs[i].Name}</color>", new GUILayoutOption[] { GUILayout.Width(15) });
|
||||
cm.GenericArgInput[i] = GUILayout.TextField(input, new GUILayoutOption[] { GUILayout.Width(150) });
|
||||
GUI.skin.label.alignment = TextAnchor.MiddleLeft;
|
||||
GUILayout.Label(types, null);
|
||||
|
||||
GUILayout.EndHorizontal();
|
||||
}
|
||||
}
|
||||
|
||||
GUILayout.BeginHorizontal(null);
|
||||
if (m_arguments.Length > 0)
|
||||
{
|
||||
GUILayout.Label($"<b><color=orange>Arguments:</color></b>", null);
|
||||
for (int i = 0; i < m_arguments.Length; i++)
|
||||
{
|
||||
var name = m_arguments[i].Name;
|
||||
var input = m_argumentInput[i];
|
||||
var type = m_arguments[i].ParameterType.Name;
|
||||
|
||||
GUILayout.Label(i.ToString(), new GUILayoutOption[] { GUILayout.Width(20) });
|
||||
m_argumentInput[i] = GUILayout.TextField(input, new GUILayoutOption[] { GUILayout.Width(150) });
|
||||
GUILayout.Label(label, null);
|
||||
var label = $"<color={UIStyles.Syntax.Class_Instance}>{type}</color> ";
|
||||
label += $"<color={UIStyles.Syntax.Local}>{name}</color>";
|
||||
if (m_arguments[i].HasDefaultValue)
|
||||
{
|
||||
label = $"<i>[{label} = {m_arguments[i].DefaultValue ?? "null"}]</i>";
|
||||
}
|
||||
|
||||
GUILayout.EndHorizontal();
|
||||
GUILayout.BeginHorizontal(null);
|
||||
|
||||
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
|
||||
GUILayout.Label(i.ToString(), new GUILayoutOption[] { GUILayout.Width(15) });
|
||||
m_argumentInput[i] = GUILayout.TextField(input, new GUILayoutOption[] { GUILayout.Width(150) });
|
||||
GUI.skin.label.alignment = TextAnchor.MiddleLeft;
|
||||
GUILayout.Label(label, null);
|
||||
|
||||
GUILayout.EndHorizontal();
|
||||
}
|
||||
}
|
||||
|
||||
GUILayout.BeginHorizontal(null);
|
||||
@ -435,7 +484,12 @@ namespace Explorer
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GUILayout.Button($"Evaluate ({m_arguments.Length} params)", new GUILayoutOption[] { GUILayout.Width(150) }))
|
||||
var lbl = $"Evaluate (";
|
||||
int len = m_arguments.Length;
|
||||
if (cm != null) len += cm.GenericArgs.Length;
|
||||
lbl += len + " params)";
|
||||
|
||||
if (GUILayout.Button(lbl, new GUILayoutOption[] { GUILayout.Width(150) }))
|
||||
{
|
||||
m_isEvaluating = true;
|
||||
}
|
||||
@ -463,17 +517,19 @@ namespace Explorer
|
||||
GUIUnstrip.Space(labelWidth);
|
||||
}
|
||||
|
||||
string typeName = $"<color={UIStyles.Syntax.Class_Instance}>{ValueType.FullName}</color>";
|
||||
|
||||
if (!string.IsNullOrEmpty(ReflectionException))
|
||||
{
|
||||
GUILayout.Label("<color=red>Reflection failed!</color> (" + ReflectionException + ")", null);
|
||||
}
|
||||
else if ((HasParameters || this is CacheMethod) && !m_evaluated)
|
||||
{
|
||||
GUILayout.Label($"<color=grey><i>Not yet evaluated</i></color> (<color=#2df7b2>{ValueTypeName}</color>)", null);
|
||||
GUILayout.Label($"<color=grey><i>Not yet evaluated</i></color> ({typeName})", null);
|
||||
}
|
||||
else if (Value == null && !(this is CacheMethod))
|
||||
{
|
||||
GUILayout.Label("<i>null (" + ValueTypeName + ")</i>", null);
|
||||
GUILayout.Label($"<i>null ({typeName})</i>", null);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -484,31 +540,80 @@ namespace Explorer
|
||||
private string GetRichTextName()
|
||||
{
|
||||
string memberColor = "";
|
||||
switch (MemInfo.MemberType)
|
||||
{
|
||||
case MemberTypes.Field:
|
||||
memberColor = "#c266ff"; break;
|
||||
case MemberTypes.Property:
|
||||
memberColor = "#72a6a6"; break;
|
||||
case MemberTypes.Method:
|
||||
memberColor = "#ff8000"; break;
|
||||
};
|
||||
bool isStatic = false;
|
||||
|
||||
m_richTextName = $"<color=#2df7b2>{MemInfo.DeclaringType.Name}</color>.<color={memberColor}>{MemInfo.Name}</color>";
|
||||
|
||||
if (m_arguments.Length > 0 || this is CacheMethod)
|
||||
if (MemInfo is FieldInfo fi)
|
||||
{
|
||||
m_richTextName += "(";
|
||||
var _params = "";
|
||||
foreach (var param in m_arguments)
|
||||
if (fi.IsStatic)
|
||||
{
|
||||
if (_params != "") _params += ", ";
|
||||
|
||||
_params += $"<color=#2df7b2>{param.ParameterType.Name}</color> <color=#a6e9e9>{param.Name}</color>";
|
||||
isStatic = true;
|
||||
memberColor = UIStyles.Syntax.Field_Static;
|
||||
}
|
||||
m_richTextName += _params;
|
||||
m_richTextName += ")";
|
||||
else
|
||||
memberColor = UIStyles.Syntax.Field_Instance;
|
||||
}
|
||||
else if (MemInfo is MethodInfo mi)
|
||||
{
|
||||
if (mi.IsStatic)
|
||||
{
|
||||
isStatic = true;
|
||||
memberColor = UIStyles.Syntax.Method_Static;
|
||||
}
|
||||
else
|
||||
memberColor = UIStyles.Syntax.Method_Instance;
|
||||
}
|
||||
else if (MemInfo is PropertyInfo pi)
|
||||
{
|
||||
if (pi.GetAccessors()[0].IsStatic)
|
||||
{
|
||||
isStatic = true;
|
||||
memberColor = UIStyles.Syntax.Prop_Static;
|
||||
}
|
||||
else
|
||||
memberColor = UIStyles.Syntax.Prop_Instance;
|
||||
}
|
||||
|
||||
string classColor = MemInfo.DeclaringType.IsAbstract && MemInfo.DeclaringType.IsSealed
|
||||
? UIStyles.Syntax.Class_Static
|
||||
: UIStyles.Syntax.Class_Instance;
|
||||
|
||||
m_richTextName = $"<color={classColor}>{MemInfo.DeclaringType.Name}</color>.";
|
||||
if (isStatic) m_richTextName += "<i>";
|
||||
m_richTextName += $"<color={memberColor}>{MemInfo.Name}</color>";
|
||||
if (isStatic) m_richTextName += "</i>";
|
||||
|
||||
// generic method args
|
||||
if (this is CacheMethod cm && cm.GenericArgs.Length > 0)
|
||||
{
|
||||
m_richTextName += "<";
|
||||
|
||||
var args = "";
|
||||
for (int i = 0; i < cm.GenericArgs.Length; i++)
|
||||
{
|
||||
if (args != "") args += ", ";
|
||||
args += $"<color={UIStyles.Syntax.StructGreen}>{cm.GenericArgs[i].Name}</color>";
|
||||
}
|
||||
m_richTextName += args;
|
||||
|
||||
m_richTextName += ">";
|
||||
}
|
||||
|
||||
// Method / Property arguments
|
||||
|
||||
//if (m_arguments.Length > 0 || this is CacheMethod)
|
||||
//{
|
||||
// m_richTextName += "(";
|
||||
// var args = "";
|
||||
// foreach (var param in m_arguments)
|
||||
// {
|
||||
// if (args != "") args += ", ";
|
||||
|
||||
// args += $"<color={classColor}>{param.ParameterType.Name}</color> ";
|
||||
// args += $"<color={UIStyles.Syntax.Local}>{param.Name}</color>";
|
||||
// }
|
||||
// m_richTextName += args;
|
||||
// m_richTextName += ")";
|
||||
//}
|
||||
|
||||
return m_richTextName;
|
||||
}
|
||||
|
@ -1,10 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Explorer
|
||||
namespace Explorer
|
||||
{
|
||||
interface IExpandHeight
|
||||
{
|
||||
|
@ -1,13 +1,8 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using MelonLoader;
|
||||
using UnityEngine;
|
||||
using System.Reflection;
|
||||
using UnhollowerBaseLib;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Explorer
|
||||
{
|
||||
@ -98,37 +93,16 @@ namespace Explorer
|
||||
|
||||
private void GetGenericArguments()
|
||||
{
|
||||
if (this.MemInfo != null)
|
||||
if (ValueType.IsGenericType)
|
||||
{
|
||||
Type memberType = null;
|
||||
switch (this.MemInfo.MemberType)
|
||||
{
|
||||
case MemberTypes.Field:
|
||||
memberType = (MemInfo as FieldInfo).FieldType;
|
||||
break;
|
||||
case MemberTypes.Property:
|
||||
memberType = (MemInfo as PropertyInfo).PropertyType;
|
||||
break;
|
||||
}
|
||||
|
||||
if (memberType != null && memberType.IsGenericType)
|
||||
{
|
||||
m_keysType = memberType.GetGenericArguments()[0];
|
||||
m_valuesType = memberType.GetGenericArguments()[1];
|
||||
}
|
||||
m_keysType = ValueType.GetGenericArguments()[0];
|
||||
m_valuesType = ValueType.GetGenericArguments()[1];
|
||||
}
|
||||
else if (Value != null)
|
||||
else
|
||||
{
|
||||
var type = Value.GetType();
|
||||
if (type.IsGenericType)
|
||||
{
|
||||
m_keysType = type.GetGenericArguments()[0];
|
||||
m_valuesType = type.GetGenericArguments()[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
MelonLogger.Log("TODO? Dictionary is of type: " + Value.GetType().FullName);
|
||||
}
|
||||
// It's non-generic, just use System.Object to allow for anything.
|
||||
m_keysType = typeof(object);
|
||||
m_valuesType = typeof(object);
|
||||
}
|
||||
}
|
||||
|
||||
@ -154,14 +128,16 @@ namespace Explorer
|
||||
var keys = new List<CacheObjectBase>();
|
||||
foreach (var key in IDict.Keys)
|
||||
{
|
||||
var cache = GetCacheObject(key, TypeOfKeys);
|
||||
Type t = ReflectionHelpers.GetActualType(key) ?? TypeOfKeys;
|
||||
var cache = GetCacheObject(key, t);
|
||||
keys.Add(cache);
|
||||
}
|
||||
|
||||
var values = new List<CacheObjectBase>();
|
||||
foreach (var val in IDict.Values)
|
||||
{
|
||||
var cache = GetCacheObject(val, TypeOfValues);
|
||||
Type t = ReflectionHelpers.GetActualType(val) ?? TypeOfValues;
|
||||
var cache = GetCacheObject(val, t);
|
||||
values.Add(cache);
|
||||
}
|
||||
|
||||
@ -288,10 +264,10 @@ namespace Explorer
|
||||
GUILayout.Label($"[{i}]", new GUILayoutOption[] { GUILayout.Width(30) });
|
||||
|
||||
GUILayout.Label("Key:", new GUILayoutOption[] { GUILayout.Width(40) });
|
||||
key.DrawValue(window, (window.width / 2) - 30f);
|
||||
key.DrawValue(window, (window.width / 2) - 80f);
|
||||
|
||||
GUILayout.Label("Value:", new GUILayoutOption[] { GUILayout.Width(40) });
|
||||
val.DrawValue(window, (window.width / 2) - 30f);
|
||||
val.DrawValue(window, (window.width / 2) - 80f);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,10 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using MelonLoader;
|
||||
using UnityEngine;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Explorer
|
||||
{
|
||||
|
@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using MelonLoader;
|
||||
using UnityEngine;
|
||||
|
@ -1,11 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
using MelonLoader;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Explorer
|
||||
{
|
||||
@ -13,16 +11,24 @@ namespace Explorer
|
||||
{
|
||||
private CacheObjectBase m_cachedReturnValue;
|
||||
|
||||
public static bool CanEvaluate(MethodInfo mi)
|
||||
{
|
||||
// TODO generic args
|
||||
if (mi.GetGenericArguments().Length > 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
public override bool HasParameters => base.HasParameters || GenericArgs.Length > 0;
|
||||
|
||||
// primitive and string args supported
|
||||
return CanProcessArgs(mi.GetParameters());
|
||||
public Type[] GenericArgs { get; private set; }
|
||||
public Type[][] GenericConstraints { get; private set; }
|
||||
|
||||
public string[] GenericArgInput = new string[0];
|
||||
|
||||
public override void Init()
|
||||
{
|
||||
var mi = (MemInfo as MethodInfo);
|
||||
GenericArgs = mi.GetGenericArguments();
|
||||
|
||||
GenericConstraints = GenericArgs.Select(x => x.GetGenericParameterConstraints())
|
||||
.ToArray();
|
||||
|
||||
GenericArgInput = new string[GenericArgs.Length];
|
||||
|
||||
ValueType = mi.ReturnType;
|
||||
}
|
||||
|
||||
public override void UpdateValue()
|
||||
@ -32,27 +38,29 @@ namespace Explorer
|
||||
|
||||
public void Evaluate()
|
||||
{
|
||||
m_isEvaluating = false;
|
||||
|
||||
var mi = MemInfo as MethodInfo;
|
||||
object ret = null;
|
||||
|
||||
if (!HasParameters)
|
||||
MethodInfo mi;
|
||||
if (GenericArgs.Length > 0)
|
||||
{
|
||||
ret = mi.Invoke(mi.IsStatic ? null : DeclaringInstance, new object[0]);
|
||||
m_evaluated = true;
|
||||
mi = MakeGenericMethodFromInput();
|
||||
if (mi == null) return;
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
ret = mi.Invoke(mi.IsStatic ? null : DeclaringInstance, ParseArguments());
|
||||
m_evaluated = true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
MelonLogger.Log($"Exception evaluating: {e.GetType()}, {e.Message}");
|
||||
}
|
||||
mi = MemInfo as MethodInfo;
|
||||
}
|
||||
|
||||
object ret = null;
|
||||
|
||||
try
|
||||
{
|
||||
ret = mi.Invoke(mi.IsStatic ? null : DeclaringInstance, ParseArguments());
|
||||
m_evaluated = true;
|
||||
m_isEvaluating = false;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
MelonLogger.LogWarning($"Exception evaluating: {e.GetType()}, {e.Message}");
|
||||
ReflectionException = ReflectionHelpers.ExceptionToString(e);
|
||||
}
|
||||
|
||||
if (ret != null)
|
||||
@ -66,10 +74,54 @@ namespace Explorer
|
||||
}
|
||||
}
|
||||
|
||||
private MethodInfo MakeGenericMethodFromInput()
|
||||
{
|
||||
var mi = MemInfo as MethodInfo;
|
||||
|
||||
var list = new List<Type>();
|
||||
for (int i = 0; i < GenericArgs.Length; i++)
|
||||
{
|
||||
var input = GenericArgInput[i];
|
||||
if (ReflectionHelpers.GetTypeByName(input) is Type t)
|
||||
{
|
||||
if (GenericConstraints[i].Length == 0)
|
||||
{
|
||||
list.Add(t);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var constraint in GenericConstraints[i].Where(x => x != null))
|
||||
{
|
||||
if (!constraint.IsAssignableFrom(t))
|
||||
{
|
||||
MelonLogger.LogWarning($"Generic argument #{i}, '{input}' is not assignable from the constraint '{constraint}'!");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
list.Add(t);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MelonLogger.LogWarning($"Generic argument #{i}, could not get any type by the name of '{input}'!" +
|
||||
$" Make sure you use the full name, including the NameSpace.");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// make into a generic with type list
|
||||
mi = mi.MakeGenericMethod(list.ToArray());
|
||||
|
||||
return mi;
|
||||
}
|
||||
|
||||
// ==== GUI DRAW ====
|
||||
|
||||
public override void DrawValue(Rect window, float width)
|
||||
{
|
||||
string typeLabel = $"<color={UIStyles.Syntax.Class_Instance}>{ValueType.FullName}</color>";
|
||||
|
||||
if (m_evaluated)
|
||||
{
|
||||
if (m_cachedReturnValue != null)
|
||||
@ -78,12 +130,12 @@ namespace Explorer
|
||||
}
|
||||
else
|
||||
{
|
||||
GUILayout.Label($"null (<color=#2df7b2>{ValueTypeName}</color>)", null);
|
||||
GUILayout.Label($"null ({typeLabel})", null);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GUILayout.Label($"<color=grey><i>Not yet evaluated</i></color> (<color=#2df7b2>{ValueTypeName}</color>)", null);
|
||||
GUILayout.Label($"<color=grey><i>Not yet evaluated</i></color> ({typeLabel})", null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,4 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
|
||||
@ -11,55 +6,75 @@ namespace Explorer
|
||||
{
|
||||
public class CacheOther : CacheObjectBase
|
||||
{
|
||||
public string ButtonLabel => m_btnLabel ?? GetButtonLabel();
|
||||
private string m_btnLabel;
|
||||
|
||||
public MethodInfo ToStringMethod => m_toStringMethod ?? GetToStringMethod();
|
||||
private MethodInfo m_toStringMethod;
|
||||
|
||||
public MethodInfo ToStringMethod
|
||||
public override void UpdateValue()
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_toStringMethod == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
m_toStringMethod = ReflectionHelpers.GetActualType(Value).GetMethod("ToString", new Type[0])
|
||||
?? typeof(object).GetMethod("ToString", new Type[0]);
|
||||
base.UpdateValue();
|
||||
|
||||
// test invoke
|
||||
m_toStringMethod.Invoke(Value, null);
|
||||
}
|
||||
catch
|
||||
{
|
||||
m_toStringMethod = typeof(object).GetMethod("ToString", new Type[0]);
|
||||
}
|
||||
}
|
||||
return m_toStringMethod;
|
||||
}
|
||||
GetButtonLabel();
|
||||
}
|
||||
|
||||
public override void DrawValue(Rect window, float width)
|
||||
{
|
||||
string label = (string)ToStringMethod?.Invoke(Value, null) ?? Value.ToString();
|
||||
|
||||
if (!label.Contains(ValueTypeName))
|
||||
{
|
||||
label += $" (<color=#2df7b2>{ValueTypeName}</color>)";
|
||||
}
|
||||
else
|
||||
{
|
||||
label = label.Replace(ValueTypeName, $"<color=#2df7b2>{ValueTypeName}</color>");
|
||||
}
|
||||
|
||||
if (Value is UnityEngine.Object unityObj && !label.Contains(unityObj.name))
|
||||
{
|
||||
label = unityObj.name + " | " + label;
|
||||
}
|
||||
|
||||
GUI.skin.button.alignment = TextAnchor.MiddleLeft;
|
||||
if (GUILayout.Button(label, new GUILayoutOption[] { GUILayout.Width(width - 15) }))
|
||||
if (GUILayout.Button(ButtonLabel, new GUILayoutOption[] { GUILayout.Width(width - 15) }))
|
||||
{
|
||||
WindowManager.InspectObject(Value, out bool _);
|
||||
}
|
||||
GUI.skin.button.alignment = TextAnchor.MiddleCenter;
|
||||
}
|
||||
|
||||
private MethodInfo GetToStringMethod()
|
||||
{
|
||||
try
|
||||
{
|
||||
m_toStringMethod = ReflectionHelpers.GetActualType(Value).GetMethod("ToString", new Type[0])
|
||||
?? typeof(object).GetMethod("ToString", new Type[0]);
|
||||
|
||||
// test invoke
|
||||
m_toStringMethod.Invoke(Value, null);
|
||||
}
|
||||
catch
|
||||
{
|
||||
m_toStringMethod = typeof(object).GetMethod("ToString", new Type[0]);
|
||||
}
|
||||
return m_toStringMethod;
|
||||
}
|
||||
|
||||
private string GetButtonLabel()
|
||||
{
|
||||
if (Value == null) return null;
|
||||
|
||||
string label = (string)ToStringMethod?.Invoke(Value, null) ?? Value.ToString();
|
||||
|
||||
var classColor = ValueType.IsAbstract && ValueType.IsSealed
|
||||
? UIStyles.Syntax.Class_Static
|
||||
: UIStyles.Syntax.Class_Instance;
|
||||
|
||||
string typeLabel = $"<color={classColor}>{ValueType.FullName}</color>";
|
||||
|
||||
if (Value is UnityEngine.Object)
|
||||
{
|
||||
label = label.Replace($"({ValueType.FullName})", $"({typeLabel})");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!label.Contains(ValueType.FullName))
|
||||
{
|
||||
label += $" ({typeLabel})";
|
||||
}
|
||||
else
|
||||
{
|
||||
label = label.Replace(ValueType.FullName, typeLabel);
|
||||
}
|
||||
}
|
||||
|
||||
return m_btnLabel = label;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,6 +21,8 @@ namespace Explorer
|
||||
{
|
||||
base.UpdateValue();
|
||||
|
||||
if (Value == null) return;
|
||||
|
||||
var color = (Color)Value;
|
||||
|
||||
r = color.r.ToString();
|
||||
@ -104,7 +106,7 @@ namespace Explorer
|
||||
&& float.TryParse(b, out float fB)
|
||||
&& float.TryParse(a, out float fA))
|
||||
{
|
||||
Value = new Color(fR, fB, fG, fA);
|
||||
Value = new Color(fR, fG, fB, fA);
|
||||
SetValue();
|
||||
}
|
||||
}
|
||||
|
@ -11,23 +11,30 @@ namespace Explorer
|
||||
{
|
||||
public class CacheEnum : CacheObjectBase
|
||||
{
|
||||
public Type EnumType;
|
||||
// public Type EnumType;
|
||||
public string[] EnumNames;
|
||||
|
||||
public override void Init()
|
||||
{
|
||||
try
|
||||
if (ValueType == null && Value != null)
|
||||
{
|
||||
EnumType = Value.GetType();
|
||||
}
|
||||
catch
|
||||
{
|
||||
EnumType = (MemInfo as FieldInfo)?.FieldType ?? (MemInfo as PropertyInfo).PropertyType;
|
||||
ValueType = Value.GetType();
|
||||
}
|
||||
|
||||
if (EnumType != null)
|
||||
if (ValueType != null)
|
||||
{
|
||||
EnumNames = Enum.GetNames(EnumType);
|
||||
// using GetValues not GetNames, to catch instances of weird enums (eg CameraClearFlags)
|
||||
var values = Enum.GetValues(ValueType);
|
||||
|
||||
var list = new List<string>();
|
||||
foreach (var value in values)
|
||||
{
|
||||
var v = value.ToString();
|
||||
if (list.Contains(v)) continue;
|
||||
list.Add(v);
|
||||
}
|
||||
|
||||
EnumNames = list.ToArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -41,12 +48,12 @@ namespace Explorer
|
||||
{
|
||||
if (GUILayout.Button("<", new GUILayoutOption[] { GUILayout.Width(25) }))
|
||||
{
|
||||
SetEnum(ref Value, -1);
|
||||
SetEnum(-1);
|
||||
SetValue();
|
||||
}
|
||||
if (GUILayout.Button(">", new GUILayoutOption[] { GUILayout.Width(25) }))
|
||||
{
|
||||
SetEnum(ref Value, 1);
|
||||
SetEnum(1);
|
||||
SetValue();
|
||||
}
|
||||
}
|
||||
@ -54,15 +61,15 @@ namespace Explorer
|
||||
GUILayout.Label(Value.ToString() + "<color=#2df7b2><i> (" + ValueType + ")</i></color>", null);
|
||||
}
|
||||
|
||||
public void SetEnum(ref object value, int change)
|
||||
public void SetEnum(int change)
|
||||
{
|
||||
var names = EnumNames.ToList();
|
||||
|
||||
int newindex = names.IndexOf(value.ToString()) + change;
|
||||
int newindex = names.IndexOf(Value.ToString()) + change;
|
||||
|
||||
if ((change < 0 && newindex >= 0) || (change > 0 && newindex < names.Count))
|
||||
if (newindex >= 0 && newindex < names.Count)
|
||||
{
|
||||
value = Enum.Parse(EnumType, names[newindex]);
|
||||
Value = Enum.Parse(ValueType, EnumNames[newindex]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
127
src/CachedObjects/Struct/CacheEnumFlags.cs
Normal file
127
src/CachedObjects/Struct/CacheEnumFlags.cs
Normal file
@ -0,0 +1,127 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using MelonLoader;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Explorer
|
||||
{
|
||||
public class CacheEnumFlags : CacheObjectBase, IExpandHeight
|
||||
{
|
||||
public string[] EnumNames = new string[0];
|
||||
public bool[] m_enabledFlags = new bool[0];
|
||||
|
||||
public bool IsExpanded { get; set; }
|
||||
public float WhiteSpace { get; set; } = 215f;
|
||||
|
||||
public override void Init()
|
||||
{
|
||||
base.Init();
|
||||
|
||||
if (ValueType == null && Value != null)
|
||||
{
|
||||
ValueType = Value.GetType();
|
||||
}
|
||||
|
||||
if (ValueType != null)
|
||||
{
|
||||
EnumNames = Enum.GetNames(ValueType);
|
||||
|
||||
m_enabledFlags = new bool[EnumNames.Length];
|
||||
|
||||
UpdateValue();
|
||||
}
|
||||
else
|
||||
{
|
||||
ReflectionException = "Unknown, could not get Enum names.";
|
||||
}
|
||||
}
|
||||
|
||||
public void SetFlagsFromInput()
|
||||
{
|
||||
string val = "";
|
||||
for (int i = 0; i < EnumNames.Length; i++)
|
||||
{
|
||||
if (m_enabledFlags[i])
|
||||
{
|
||||
if (val != "") val += ", ";
|
||||
val += EnumNames[i];
|
||||
}
|
||||
}
|
||||
Value = Enum.Parse(ValueType, val);
|
||||
SetValue();
|
||||
}
|
||||
|
||||
public override void UpdateValue()
|
||||
{
|
||||
base.UpdateValue();
|
||||
|
||||
try
|
||||
{
|
||||
var enabledNames = Value.ToString().Split(',').Select(it => it.Trim());
|
||||
|
||||
for (int i = 0; i < EnumNames.Length; i++)
|
||||
{
|
||||
m_enabledFlags[i] = enabledNames.Contains(EnumNames[i]);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
MelonLogger.Log(e.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public override void DrawValue(Rect window, float width)
|
||||
{
|
||||
if (CanWrite)
|
||||
{
|
||||
if (!IsExpanded)
|
||||
{
|
||||
if (GUILayout.Button("v", new GUILayoutOption[] { GUILayout.Width(25) }))
|
||||
{
|
||||
IsExpanded = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GUILayout.Button("^", new GUILayoutOption[] { GUILayout.Width(25) }))
|
||||
{
|
||||
IsExpanded = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GUILayout.Label(Value.ToString() + "<color=#2df7b2><i> (" + ValueType + ")</i></color>", null);
|
||||
|
||||
if (IsExpanded)
|
||||
{
|
||||
GUILayout.EndHorizontal();
|
||||
|
||||
var whitespace = CalcWhitespace(window);
|
||||
|
||||
for (int i = 0; i < EnumNames.Length; i++)
|
||||
{
|
||||
GUILayout.BeginHorizontal(null);
|
||||
GUIUnstrip.Space(whitespace);
|
||||
|
||||
m_enabledFlags[i] = GUILayout.Toggle(m_enabledFlags[i], EnumNames[i], null);
|
||||
|
||||
GUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
GUILayout.BeginHorizontal(null);
|
||||
GUIUnstrip.Space(whitespace);
|
||||
if (GUILayout.Button("<color=lime>Apply</color>", new GUILayoutOption[] { GUILayout.Width(155) }))
|
||||
{
|
||||
SetFlagsFromInput();
|
||||
}
|
||||
GUILayout.EndHorizontal();
|
||||
|
||||
GUILayout.BeginHorizontal(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,7 +1,9 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using MelonLoader;
|
||||
using UnhollowerRuntimeLib;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Explorer
|
||||
@ -16,6 +18,12 @@ namespace Explorer
|
||||
public MethodInfo ParseMethod => m_parseMethod ?? (m_parseMethod = Value.GetType().GetMethod("Parse", new Type[] { typeof(string) }));
|
||||
private MethodInfo m_parseMethod;
|
||||
|
||||
private bool m_canBitwiseOperate;
|
||||
private bool m_inBitwiseMode;
|
||||
private string m_bitwiseOperatorInput = "0";
|
||||
private string m_bitwiseToString;
|
||||
//private BitArray m_bitMask; // not needed I think
|
||||
|
||||
public override void Init()
|
||||
{
|
||||
if (ValueType == null)
|
||||
@ -37,17 +45,31 @@ namespace Explorer
|
||||
{
|
||||
m_isBool = true;
|
||||
}
|
||||
|
||||
m_canBitwiseOperate = typeof(int).IsAssignableFrom(ValueType);
|
||||
}
|
||||
|
||||
public override void UpdateValue()
|
||||
{
|
||||
base.UpdateValue();
|
||||
|
||||
RefreshToString();
|
||||
}
|
||||
|
||||
public void RefreshToString()
|
||||
{
|
||||
m_valueToString = Value?.ToString();
|
||||
|
||||
if (m_inBitwiseMode)
|
||||
{
|
||||
var _int = (int)Value;
|
||||
m_bitwiseToString = Convert.ToString(_int, toBase: 2);
|
||||
}
|
||||
}
|
||||
|
||||
public override void DrawValue(Rect window, float width)
|
||||
{
|
||||
// bool uses Toggle
|
||||
if (m_isBool)
|
||||
{
|
||||
var b = (bool)Value;
|
||||
@ -65,35 +87,127 @@ namespace Explorer
|
||||
{
|
||||
GUILayout.Label(label, null);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// all other non-bool values use TextField
|
||||
|
||||
GUILayout.BeginVertical(null);
|
||||
|
||||
GUILayout.BeginHorizontal(null);
|
||||
|
||||
// using ValueType.Name instead of ValueTypeName, because we only want the short name.
|
||||
GUILayout.Label("<color=#2df7b2><i>" + ValueType.Name + "</i></color>", new GUILayoutOption[] { GUILayout.Width(50) });
|
||||
|
||||
int dynSize = 25 + (m_valueToString.Length * 15);
|
||||
var maxwidth = window.width - 310f;
|
||||
if (CanWrite) maxwidth -= 60;
|
||||
|
||||
if (dynSize > maxwidth)
|
||||
{
|
||||
m_valueToString = GUILayout.TextArea(m_valueToString, new GUILayoutOption[] { GUILayout.MaxWidth(maxwidth) });
|
||||
}
|
||||
else
|
||||
{
|
||||
// using ValueType.Name instead of ValueTypeName, because we only want the short name.
|
||||
GUILayout.Label("<color=#2df7b2><i>" + ValueType.Name + "</i></color>", new GUILayoutOption[] { GUILayout.Width(50) });
|
||||
m_valueToString = GUILayout.TextField(m_valueToString, new GUILayoutOption[] { GUILayout.MaxWidth(dynSize) });
|
||||
}
|
||||
|
||||
int dynSize = 25 + (m_valueToString.Length * 15);
|
||||
var maxwidth = window.width - 310f;
|
||||
if (CanWrite) maxwidth -= 60;
|
||||
|
||||
if (dynSize > maxwidth)
|
||||
if (CanWrite)
|
||||
{
|
||||
if (GUILayout.Button("<color=#00FF00>Apply</color>", new GUILayoutOption[] { GUILayout.Width(60) }))
|
||||
{
|
||||
m_valueToString = GUILayout.TextArea(m_valueToString, new GUILayoutOption[] { GUILayout.MaxWidth(maxwidth) });
|
||||
}
|
||||
else
|
||||
{
|
||||
m_valueToString = GUILayout.TextField(m_valueToString, new GUILayoutOption[] { GUILayout.MaxWidth(dynSize) });
|
||||
SetValueFromInput(m_valueToString);
|
||||
RefreshToString();
|
||||
}
|
||||
}
|
||||
|
||||
if (m_canBitwiseOperate)
|
||||
{
|
||||
bool orig = m_inBitwiseMode;
|
||||
m_inBitwiseMode = GUILayout.Toggle(m_inBitwiseMode, "Bitwise?", null);
|
||||
if (orig != m_inBitwiseMode)
|
||||
{
|
||||
RefreshToString();
|
||||
}
|
||||
}
|
||||
|
||||
GUIUnstrip.Space(10);
|
||||
|
||||
GUILayout.EndHorizontal();
|
||||
|
||||
if (m_inBitwiseMode)
|
||||
{
|
||||
if (CanWrite)
|
||||
{
|
||||
if (GUILayout.Button("<color=#00FF00>Apply</color>", new GUILayoutOption[] { GUILayout.Width(60) }))
|
||||
GUILayout.BeginHorizontal(null);
|
||||
|
||||
GUI.skin.label.alignment = TextAnchor.MiddleRight;
|
||||
GUILayout.Label("RHS:", new GUILayoutOption[] { GUILayout.Width(35) });
|
||||
GUI.skin.label.alignment = TextAnchor.UpperLeft;
|
||||
|
||||
if (GUILayout.Button("~", new GUILayoutOption[] { GUILayout.Width(25) }))
|
||||
{
|
||||
SetValueFromInput(m_valueToString);
|
||||
if (int.TryParse(m_bitwiseOperatorInput, out int bit))
|
||||
{
|
||||
Value = ~bit;
|
||||
RefreshToString();
|
||||
}
|
||||
}
|
||||
|
||||
if (GUILayout.Button("<<", new GUILayoutOption[] { GUILayout.Width(25) }))
|
||||
{
|
||||
if (int.TryParse(m_bitwiseOperatorInput, out int bit))
|
||||
{
|
||||
Value = (int)Value << bit;
|
||||
RefreshToString();
|
||||
}
|
||||
}
|
||||
if (GUILayout.Button(">>", new GUILayoutOption[] { GUILayout.Width(25) }))
|
||||
{
|
||||
if (int.TryParse(m_bitwiseOperatorInput, out int bit))
|
||||
{
|
||||
Value = (int)Value >> bit;
|
||||
RefreshToString();
|
||||
}
|
||||
}
|
||||
if (GUILayout.Button("|", new GUILayoutOption[] { GUILayout.Width(25) }))
|
||||
{
|
||||
if (int.TryParse(m_bitwiseOperatorInput, out int bit))
|
||||
{
|
||||
Value = (int)Value | bit;
|
||||
RefreshToString();
|
||||
}
|
||||
}
|
||||
if (GUILayout.Button("&", new GUILayoutOption[] { GUILayout.Width(25) }))
|
||||
{
|
||||
if (int.TryParse(m_bitwiseOperatorInput, out int bit))
|
||||
{
|
||||
Value = (int)Value & bit;
|
||||
RefreshToString();
|
||||
}
|
||||
}
|
||||
if (GUILayout.Button("^", new GUILayoutOption[] { GUILayout.Width(25) }))
|
||||
{
|
||||
if (int.TryParse(m_bitwiseOperatorInput, out int bit))
|
||||
{
|
||||
Value = (int)Value ^ bit;
|
||||
RefreshToString();
|
||||
}
|
||||
}
|
||||
|
||||
m_bitwiseOperatorInput = GUILayout.TextField(m_bitwiseOperatorInput, new GUILayoutOption[] { GUILayout.Width(55) });
|
||||
|
||||
GUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
GUIUnstrip.Space(10);
|
||||
GUILayout.BeginHorizontal(null);
|
||||
GUILayout.Label($"<color=cyan>Binary:</color>", new GUILayoutOption[] { GUILayout.Width(60) });
|
||||
GUILayout.TextField(m_bitwiseToString, null);
|
||||
GUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
GUILayout.EndVertical();
|
||||
}
|
||||
|
||||
public void SetValueFromInput(string valueString)
|
||||
@ -113,6 +227,16 @@ namespace Explorer
|
||||
try
|
||||
{
|
||||
Value = ParseMethod.Invoke(null, new object[] { valueString });
|
||||
|
||||
//if (m_inBitwiseMode)
|
||||
//{
|
||||
// var method = typeof(Convert).GetMethod($"To{ValueType.Name}", new Type[] { typeof(string), typeof(int) });
|
||||
// Value = method.Invoke(null, new object[] { valueString, 2 });
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// Value = ParseMethod.Invoke(null, new object[] { valueString });
|
||||
//}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
@ -20,6 +20,8 @@ namespace Explorer
|
||||
{
|
||||
base.UpdateValue();
|
||||
|
||||
if (Value == null) return;
|
||||
|
||||
var euler = ((Quaternion)Value).eulerAngles;
|
||||
|
||||
x = euler.x.ToString();
|
||||
|
@ -21,6 +21,8 @@ namespace Explorer
|
||||
{
|
||||
base.UpdateValue();
|
||||
|
||||
if (Value == null) return;
|
||||
|
||||
var rect = (Rect)Value;
|
||||
|
||||
x = rect.x.ToString();
|
||||
|
@ -24,20 +24,26 @@ namespace Explorer
|
||||
|
||||
public override void Init()
|
||||
{
|
||||
if (Value is Vector2)
|
||||
if (ValueType == null && Value != null)
|
||||
{
|
||||
ValueType = Value.GetType();
|
||||
}
|
||||
|
||||
if (ValueType == typeof(Vector2))
|
||||
{
|
||||
VectorSize = 2;
|
||||
m_toStringMethod = typeof(Vector2).GetMethod("ToString", new Type[0]);
|
||||
}
|
||||
else if (Value is Vector3)
|
||||
else if (ValueType == typeof(Vector3))
|
||||
{
|
||||
VectorSize = 3;
|
||||
m_toStringMethod = typeof(Vector3).GetMethod("ToString", new Type[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
VectorSize = 4;
|
||||
m_toStringMethod = typeof(Vector4).GetMethod("ToString", new Type[0]);
|
||||
}
|
||||
|
||||
m_toStringMethod = Value.GetType().GetMethod("ToString", new Type[0]);
|
||||
}
|
||||
|
||||
public override void UpdateValue()
|
||||
|
@ -1,9 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.IO;
|
||||
using System.Xml.Serialization;
|
||||
using UnityEngine;
|
||||
|
||||
|
@ -1,11 +1,4 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Harmony;
|
||||
using MelonLoader;
|
||||
using UnhollowerBaseLib;
|
||||
using MelonLoader;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Explorer
|
||||
@ -13,7 +6,7 @@ namespace Explorer
|
||||
public class CppExplorer : MelonMod
|
||||
{
|
||||
public const string NAME = "CppExplorer";
|
||||
public const string VERSION = "1.7.3";
|
||||
public const string VERSION = "1.7.5";
|
||||
public const string AUTHOR = "Sinai";
|
||||
public const string GUID = "com.sinai.cppexplorer";
|
||||
|
||||
|
@ -83,6 +83,7 @@
|
||||
<Compile Include="CachedObjects\Struct\CacheEnum.cs" />
|
||||
<Compile Include="CachedObjects\Object\CacheGameObject.cs" />
|
||||
<Compile Include="CachedObjects\Object\CacheList.cs" />
|
||||
<Compile Include="CachedObjects\Struct\CacheEnumFlags.cs" />
|
||||
<Compile Include="CachedObjects\Struct\CachePrimitive.cs" />
|
||||
<Compile Include="CachedObjects\Other\CacheOther.cs" />
|
||||
<Compile Include="CachedObjects\Other\CacheMethod.cs" />
|
||||
|
@ -1,8 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Explorer
|
||||
|
@ -1,10 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnhollowerBaseLib;
|
||||
using UnityEngine;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Explorer
|
||||
{
|
||||
|
@ -1,12 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
using MelonLoader;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Explorer
|
||||
{
|
||||
|
@ -1,9 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Explorer
|
||||
{
|
||||
|
@ -1,9 +1,8 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using MelonLoader;
|
||||
using UnhollowerBaseLib;
|
||||
using UnhollowerRuntimeLib;
|
||||
@ -23,20 +22,24 @@ namespace Explorer
|
||||
public static ILType ComponentType => Il2CppType.Of<Component>();
|
||||
public static ILType BehaviourType => Il2CppType.Of<Behaviour>();
|
||||
|
||||
private static readonly MethodInfo m_tryCastMethodInfo = typeof(Il2CppObjectBase).GetMethod("TryCast");
|
||||
private static readonly MethodInfo tryCastMethodInfo = typeof(Il2CppObjectBase).GetMethod("TryCast");
|
||||
private static readonly Dictionary<Type, MethodInfo> cachedTryCastMethods = new Dictionary<Type, MethodInfo>();
|
||||
|
||||
public static object Il2CppCast(object obj, Type castTo)
|
||||
{
|
||||
if (!typeof(Il2CppSystem.Object).IsAssignableFrom(castTo)) return obj;
|
||||
|
||||
return m_tryCastMethodInfo
|
||||
.MakeGenericMethod(castTo)
|
||||
.Invoke(obj, null);
|
||||
if (!cachedTryCastMethods.ContainsKey(castTo))
|
||||
{
|
||||
cachedTryCastMethods.Add(castTo, tryCastMethodInfo.MakeGenericMethod(castTo));
|
||||
}
|
||||
|
||||
return cachedTryCastMethods[castTo].Invoke(obj, null);
|
||||
}
|
||||
|
||||
public static bool IsEnumerable(Type t)
|
||||
{
|
||||
return typeof(IEnumerable).IsAssignableFrom(t);
|
||||
return typeof(IEnumerable).IsAssignableFrom(t) || IsCppEnumerable(t);
|
||||
}
|
||||
|
||||
// Checks for Il2Cpp List or HashSet.
|
||||
@ -68,7 +71,8 @@ namespace Explorer
|
||||
}
|
||||
else
|
||||
{
|
||||
return typeof(Il2CppSystem.Collections.IDictionary).IsAssignableFrom(t);
|
||||
return typeof(Il2CppSystem.Collections.IDictionary).IsAssignableFrom(t)
|
||||
|| typeof(Il2CppSystem.Collections.Hashtable).IsAssignableFrom(t);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Explorer
|
||||
{
|
||||
|
@ -1,12 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using Harmony;
|
||||
using MelonLoader;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Explorer
|
||||
{
|
||||
|
@ -1,9 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Explorer
|
||||
{
|
||||
|
@ -1,9 +1,4 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using Mono.CSharp;
|
||||
using UnityEngine;
|
||||
using Attribute = System.Attribute;
|
||||
|
@ -1,8 +1,5 @@
|
||||
using System.Collections;
|
||||
//using Il2CppSystem;
|
||||
using MelonLoader;
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using System;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace Explorer
|
||||
|
@ -1,14 +1,11 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using System.Reflection;
|
||||
using Mono.CSharp;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using MelonLoader;
|
||||
using Mono.CSharp;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Explorer
|
||||
{
|
||||
@ -43,7 +40,7 @@ namespace Explorer
|
||||
|
||||
try
|
||||
{
|
||||
MethodInput = @"// This is a basic C# REPL console.
|
||||
MethodInput = @"// This is a basic C# console.
|
||||
// Some common using directives are added by default, you can add more below.
|
||||
// If you want to return some output, MelonLogger.Log() it.
|
||||
|
||||
@ -123,7 +120,7 @@ MelonLogger.Log(""hello world"");";
|
||||
|
||||
public override void DrawWindow()
|
||||
{
|
||||
GUILayout.Label("<b><size=15><color=cyan>C# REPL Console</color></size></b>", null);
|
||||
GUILayout.Label("<b><size=15><color=cyan>C# Console</color></size></b>", null);
|
||||
|
||||
GUI.skin.label.alignment = TextAnchor.UpperLeft;
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using MelonLoader;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
@ -2,10 +2,9 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using System.Reflection;
|
||||
using MelonLoader;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Explorer
|
||||
{
|
||||
@ -428,7 +427,7 @@ namespace Explorer
|
||||
{
|
||||
var t = ReflectionHelpers.GetActualType(obj);
|
||||
|
||||
if (!FilterName(t.FullName) || ReflectionHelpers.IsEnumerable(t) || ReflectionHelpers.IsCppEnumerable(t))
|
||||
if (!FilterName(t.FullName) || ReflectionHelpers.IsEnumerable(t))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
@ -1,9 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Explorer
|
||||
{
|
||||
|
@ -1,11 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using MelonLoader;
|
||||
using UnhollowerBaseLib;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Explorer
|
||||
{
|
||||
@ -58,7 +54,11 @@ namespace Explorer
|
||||
_rect.yMax = Mathf.Min(Screen.height, _rect.yMax); // modifying yMax affects height, not y
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
catch
|
||||
{
|
||||
// throw safe Managed exception
|
||||
throw new Exception("");
|
||||
}
|
||||
|
||||
GUILayout.EndHorizontal();
|
||||
}
|
||||
|
@ -1,10 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Reflection;
|
||||
using UnhollowerRuntimeLib;
|
||||
using UnityEngine;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
|
@ -1,16 +1,29 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace Explorer
|
||||
{
|
||||
public class UIStyles
|
||||
{
|
||||
public class Syntax
|
||||
{
|
||||
public const string Field_Static = "#8d8dc6";
|
||||
public const string Field_Instance = "#c266ff";
|
||||
|
||||
public const string Method_Static = "#b55b02";
|
||||
public const string Method_Instance = "#ff8000";
|
||||
|
||||
public const string Prop_Static = "#588075";
|
||||
public const string Prop_Instance = "#55a38e";
|
||||
|
||||
public const string Class_Static = "#3a8d71";
|
||||
public const string Class_Instance = "#2df7b2";
|
||||
|
||||
public const string Local = "#a6e9e9";
|
||||
|
||||
public const string StructGreen = "#b8d7a3";
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -1,11 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using MelonLoader;
|
||||
using UnhollowerRuntimeLib;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
namespace Explorer
|
||||
{
|
||||
@ -363,7 +360,8 @@ namespace Explorer
|
||||
GUILayout.EndHorizontal();
|
||||
|
||||
GUILayout.BeginHorizontal(null);
|
||||
m_addComponentInput = GUILayout.TextField(m_addComponentInput, new GUILayoutOption[] { GUILayout.Width(130) });
|
||||
var width = m_rect.width / 2 - 115f;
|
||||
m_addComponentInput = GUILayout.TextField(m_addComponentInput, new GUILayoutOption[] { GUILayout.Width(width) });
|
||||
if (GUILayout.Button("Add Comp", null))
|
||||
{
|
||||
if (ReflectionHelpers.GetTypeByName(m_addComponentInput) is Type compType)
|
||||
@ -570,7 +568,7 @@ namespace Explorer
|
||||
GUILayout.EndHorizontal();
|
||||
|
||||
bool b = m_localContext;
|
||||
b = GUILayout.Toggle(b, "<color=" + (b ? "lime" : "red") + ">Use local transform values?</color>", null);
|
||||
b = GUILayout.Toggle(b, "<color=" + (b ? "lime" : "orange") + ">Use local transform values?</color>", null);
|
||||
if (b != m_localContext)
|
||||
{
|
||||
m_localContext = b;
|
||||
@ -611,7 +609,7 @@ namespace Explorer
|
||||
private void BoolToggle(ref bool value, string message)
|
||||
{
|
||||
string lbl = "<color=";
|
||||
lbl += value ? "lime" : "red";
|
||||
lbl += value ? "lime" : "orange";
|
||||
lbl += $">{message}</color>";
|
||||
|
||||
value = GUILayout.Toggle(value, lbl, null);
|
||||
|
@ -1,6 +1,4 @@
|
||||
using System;
|
||||
using System.CodeDom;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
@ -163,15 +161,13 @@ namespace Explorer
|
||||
continue;
|
||||
|
||||
// check blacklisted members
|
||||
var name = member.DeclaringType.Name + "." + member.Name;
|
||||
if (_typeAndMemberBlacklist.Any(it => it == name))
|
||||
var sig = $"{member.DeclaringType.Name}.{member.Name}";
|
||||
if (_typeAndMemberBlacklist.Any(it => it == sig))
|
||||
continue;
|
||||
|
||||
if (_methodStartsWithBlacklist.Any(it => member.Name.StartsWith(it)))
|
||||
continue;
|
||||
|
||||
// compare signature to already cached members
|
||||
var signature = $"{member.DeclaringType.Name}.{member.Name}";
|
||||
if (member is MethodInfo mi)
|
||||
{
|
||||
AppendParams(mi.GetParameters());
|
||||
@ -183,15 +179,15 @@ namespace Explorer
|
||||
|
||||
void AppendParams(ParameterInfo[] _args)
|
||||
{
|
||||
signature += " (";
|
||||
sig += " (";
|
||||
foreach (var param in _args)
|
||||
{
|
||||
signature += $"{param.ParameterType.Name} {param.Name}, ";
|
||||
sig += $"{param.ParameterType.Name} {param.Name}, ";
|
||||
}
|
||||
signature += ")";
|
||||
sig += ")";
|
||||
}
|
||||
|
||||
if (cachedSigs.Contains(signature))
|
||||
if (cachedSigs.Contains(sig))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@ -203,14 +199,14 @@ namespace Explorer
|
||||
var cached = CacheObjectBase.GetCacheObject(member, target);
|
||||
if (cached != null)
|
||||
{
|
||||
cachedSigs.Add(signature);
|
||||
cachedSigs.Add(sig);
|
||||
list.Add(cached);
|
||||
cached.ReflectionException = exception;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
MelonLogger.LogWarning($"Exception caching member {signature}!");
|
||||
MelonLogger.LogWarning($"Exception caching member {sig}!");
|
||||
MelonLogger.Log(e.ToString());
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using MelonLoader;
|
||||
using UnityEngine;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Explorer
|
||||
{
|
||||
|
@ -1,11 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Harmony;
|
||||
using MelonLoader;
|
||||
using UnhollowerBaseLib;
|
||||
using UnhollowerRuntimeLib;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Explorer
|
||||
|
@ -1,13 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Harmony;
|
||||
using MelonLoader;
|
||||
using UnhollowerBaseLib;
|
||||
using UnhollowerRuntimeLib;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
|
||||
namespace Explorer
|
||||
{
|
||||
|
@ -1,16 +1,46 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using MelonLoader;
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using System.Reflection;
|
||||
using System.Collections.Specialized;
|
||||
using MelonLoader;
|
||||
|
||||
// used to test multiple generic constraints
|
||||
public class TestGeneric : IComparable<string>
|
||||
{
|
||||
public TestGeneric() { }
|
||||
|
||||
public int CompareTo(string other) => throw new NotImplementedException();
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum TestFlags
|
||||
{
|
||||
Red,
|
||||
Green,
|
||||
Blue
|
||||
}
|
||||
|
||||
// test non-flags weird enum
|
||||
public enum WeirdEnum
|
||||
{
|
||||
First = 1,
|
||||
Second,
|
||||
Third = 2,
|
||||
Fourth,
|
||||
Fifth
|
||||
}
|
||||
|
||||
namespace Explorer.Tests
|
||||
{
|
||||
public class TestClass
|
||||
{
|
||||
public static TestFlags testFlags = TestFlags.Blue | TestFlags.Green;
|
||||
public static WeirdEnum testWeird = WeirdEnum.First;
|
||||
|
||||
public static int testBitmask;
|
||||
|
||||
public static TestClass Instance => m_instance ?? (m_instance = new TestClass());
|
||||
private static TestClass m_instance;
|
||||
|
||||
@ -20,8 +50,56 @@ namespace Explorer.Tests
|
||||
ILHashSetTest.Add("1");
|
||||
ILHashSetTest.Add("2");
|
||||
ILHashSetTest.Add("3");
|
||||
|
||||
testBitmask = 1 | 2;
|
||||
}
|
||||
|
||||
public static int StaticProperty => 5;
|
||||
public static int StaticField = 5;
|
||||
public int NonStaticField;
|
||||
|
||||
public static string TestGeneric<C, T>(string arg0) where C : Component where T : TestGeneric, IComparable<string>
|
||||
{
|
||||
return $"C: '{typeof(C).FullName}', T: '{typeof(T).FullName}', arg0: '{arg0}'";
|
||||
}
|
||||
|
||||
public static string TestRefInOutGeneric<T>(ref string arg0, in int arg1, out string arg2)
|
||||
{
|
||||
arg2 = "this is arg2";
|
||||
|
||||
return $"T: '{typeof(T).FullName}', ref arg0: '{arg0}', in arg1: '{arg1}', out arg2: '{arg2}'";
|
||||
}
|
||||
|
||||
//// this type of generic is not supported, due to requiring a non-primitive argument.
|
||||
//public static T TestDifferentGeneric<T>(T obj) where T : Component
|
||||
//{
|
||||
// return obj;
|
||||
//}
|
||||
|
||||
// test a non-generic dictionary
|
||||
|
||||
public Hashtable TestNonGenericDict()
|
||||
{
|
||||
return new Hashtable
|
||||
{
|
||||
{ "One", 1 },
|
||||
{ "Two", 2 },
|
||||
{ "Three", 3 },
|
||||
};
|
||||
}
|
||||
|
||||
// IL2CPP HASHTABLE NOT SUPPORTED! Cannot assign Il2CppSystem.Object from primitive struct / string.
|
||||
// Technically they are "supported" but if they contain System types they will not work.
|
||||
|
||||
//public Il2CppSystem.Collections.Hashtable TestIl2CppNonGenericDict()
|
||||
//{
|
||||
// var table = new Il2CppSystem.Collections.Hashtable();
|
||||
// table.Add("One", 1);
|
||||
// table.Add("One", 2);
|
||||
// table.Add("One", 3);
|
||||
// return table;
|
||||
//}
|
||||
|
||||
// test HashSets
|
||||
|
||||
public static HashSet<string> HashSetTest = new HashSet<string>
|
||||
|
@ -1,15 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using MelonLoader;
|
||||
using UnhollowerBaseLib;
|
||||
using UnhollowerRuntimeLib;
|
||||
using System.Reflection;
|
||||
using MelonLoader;
|
||||
using UnhollowerRuntimeLib;
|
||||
using UnityEngine;
|
||||
using UnityEngineInternal;
|
||||
using Harmony;
|
||||
|
||||
namespace Explorer
|
||||
{
|
||||
|
@ -1,9 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Explorer
|
||||
{
|
||||
|
@ -1,10 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Harmony;
|
||||
using MelonLoader;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Explorer
|
||||
|
@ -1,14 +1,10 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using UnhollowerRuntimeLib;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Explorer
|
||||
{
|
||||
public struct SliderHandlerUnstrip
|
||||
public struct SliderHandlerUnstrip
|
||||
{
|
||||
private readonly Rect position;
|
||||
private readonly float currentValue;
|
||||
|
@ -1,9 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Explorer
|
||||
{
|
||||
|
Reference in New Issue
Block a user