mirror of
https://github.com/GrahamKracker/UnityExplorer.git
synced 2025-07-16 00:07:52 +08:00
Cleanup runtime-specific
This commit is contained in:
@ -20,7 +20,7 @@ namespace UnityExplorer.Core.CSharp
|
||||
|
||||
public static void StartCoroutine(IEnumerator ienumerator)
|
||||
{
|
||||
RuntimeProvider.Instance.StartConsoleCoroutine(ienumerator);
|
||||
RuntimeProvider.Instance.StartCoroutine(ienumerator);
|
||||
}
|
||||
|
||||
public static void AddUsing(string directive)
|
||||
|
@ -189,4 +189,4 @@ namespace UnityExplorer.Core.Input
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -18,4 +18,4 @@ namespace UnityExplorer.Core.Input
|
||||
void AddUIInputModule();
|
||||
void ActivateModule();
|
||||
}
|
||||
}
|
||||
}
|
@ -6,9 +6,6 @@ using UnityEngine.EventSystems;
|
||||
using UnityExplorer.UI;
|
||||
using System.Collections.Generic;
|
||||
using UnityExplorer.UI.Inspectors;
|
||||
#if CPP
|
||||
using UnhollowerRuntimeLib;
|
||||
#endif
|
||||
|
||||
namespace UnityExplorer.Core.Input
|
||||
{
|
||||
@ -152,13 +149,9 @@ namespace UnityExplorer.Core.Input
|
||||
}
|
||||
|
||||
var assetType = ReflectionUtility.GetTypeByName("UnityEngine.InputSystem.InputActionAsset");
|
||||
#if CPP
|
||||
m_newInputModule = UIManager.CanvasRoot.AddComponent(Il2CppType.From(TInputSystemUIInputModule)).TryCast<BaseInputModule>();
|
||||
var asset = ScriptableObject.CreateInstance(Il2CppType.From(assetType));
|
||||
#else
|
||||
m_newInputModule = (BaseInputModule)UIManager.CanvasRoot.AddComponent(TInputSystemUIInputModule);
|
||||
var asset = ScriptableObject.CreateInstance(assetType);
|
||||
#endif
|
||||
m_newInputModule = RuntimeProvider.Instance.AddComponent<BaseInputModule>(UIManager.CanvasRoot, TInputSystemUIInputModule);
|
||||
var asset = RuntimeProvider.Instance.CreateScriptable(assetType);
|
||||
|
||||
inputExtensions = ReflectionUtility.GetTypeByName("UnityEngine.InputSystem.InputActionSetupExtensions");
|
||||
|
||||
var addMap = inputExtensions.GetMethod("AddActionMap", new Type[] { assetType, typeof(string) });
|
||||
@ -205,4 +198,4 @@ namespace UnityExplorer.Core.Input
|
||||
UI_Enable.Invoke(UI_ActionMap, new object[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -54,4 +54,4 @@ namespace UnityExplorer.Core.Input
|
||||
m_inputModule.ActivateModule();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -19,4 +19,4 @@ namespace UnityExplorer.Core.Input
|
||||
public void ActivateModule() { }
|
||||
public void AddUIInputModule() { }
|
||||
}
|
||||
}
|
||||
}
|
@ -43,6 +43,9 @@ namespace UnityExplorer
|
||||
public static object Cast(this object obj, Type castTo)
|
||||
=> ReflectionProvider.Instance.Cast(obj, castTo);
|
||||
|
||||
public static T TryCast<T>(this object obj)
|
||||
=> ReflectionProvider.Instance.TryCast<T>(obj);
|
||||
|
||||
/// <summary>
|
||||
/// Check if the provided Type is assignable to IEnumerable.
|
||||
/// </summary>
|
||||
@ -201,10 +204,9 @@ namespace UnityExplorer
|
||||
{
|
||||
while (e.InnerException != null)
|
||||
{
|
||||
#if CPP
|
||||
if (e.InnerException is System.Runtime.CompilerServices.RuntimeWrappedException)
|
||||
break;
|
||||
#endif
|
||||
|
||||
e = e.InnerException;
|
||||
}
|
||||
}
|
||||
|
@ -50,12 +50,47 @@ namespace UnityExplorer.Core.Runtime.Il2Cpp
|
||||
ExplorerCore.Log(condition, type, true);
|
||||
}
|
||||
|
||||
public override void StartConsoleCoroutine(IEnumerator routine)
|
||||
public override void StartCoroutine(IEnumerator routine)
|
||||
{
|
||||
Il2CppCoroutine.Start(routine);
|
||||
}
|
||||
|
||||
// Unity API Handlers
|
||||
public override void Update()
|
||||
{
|
||||
Il2CppCoroutine.Process();
|
||||
}
|
||||
|
||||
public override T AddComponent<T>(GameObject obj, Type type)
|
||||
{
|
||||
return obj.AddComponent(Il2CppType.From(type)).TryCast<T>();
|
||||
}
|
||||
|
||||
public override ScriptableObject CreateScriptable(Type type)
|
||||
{
|
||||
return ScriptableObject.CreateInstance(Il2CppType.From(type));
|
||||
}
|
||||
|
||||
public override void GraphicRaycast(GraphicRaycaster raycaster, PointerEventData data, List<RaycastResult> list)
|
||||
{
|
||||
var il2cppList = new Il2CppSystem.Collections.Generic.List<RaycastResult>();
|
||||
|
||||
raycaster.Raycast(data, il2cppList);
|
||||
|
||||
if (il2cppList.Count > 0)
|
||||
list.AddRange(il2cppList.ToArray());
|
||||
}
|
||||
|
||||
public override bool IsReferenceEqual(object a, object b)
|
||||
{
|
||||
if (a.TryCast<UnityEngine.Object>() is UnityEngine.Object ua)
|
||||
{
|
||||
var ub = b.TryCast<UnityEngine.Object>();
|
||||
if (ub && ua.m_CachedPtr == ub.m_CachedPtr)
|
||||
return true;
|
||||
}
|
||||
|
||||
return base.IsReferenceEqual(a, b);
|
||||
}
|
||||
|
||||
// LayerMask.LayerToName
|
||||
|
||||
@ -162,6 +197,26 @@ namespace UnityExplorer.Core.Runtime.Il2Cpp
|
||||
|
||||
return colors;
|
||||
}
|
||||
|
||||
public override void FindSingleton(string[] possibleNames, Type type, BF flags, List<object> instances)
|
||||
{
|
||||
PropertyInfo pi;
|
||||
foreach (var name in possibleNames)
|
||||
{
|
||||
pi = type.GetProperty(name, flags);
|
||||
if (pi != null)
|
||||
{
|
||||
var instance = pi.GetValue(null, null);
|
||||
if (instance != null)
|
||||
{
|
||||
instances.Add(instance);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
base.FindSingleton(possibleNames, type, flags, instances);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -32,6 +32,18 @@ namespace UnityExplorer.Core.Runtime.Il2Cpp
|
||||
return Il2CppCast(obj, castTo);
|
||||
}
|
||||
|
||||
public override T TryCast<T>(object obj)
|
||||
{
|
||||
try
|
||||
{
|
||||
return (T)Il2CppCast(obj, typeof(T));
|
||||
}
|
||||
catch
|
||||
{
|
||||
return default;
|
||||
}
|
||||
}
|
||||
|
||||
public override string ProcessTypeNameInString(Type type, string theString, ref string typeName)
|
||||
{
|
||||
if (!Il2CppTypeNotNull(type))
|
||||
@ -367,6 +379,124 @@ namespace UnityExplorer.Core.Runtime.Il2Cpp
|
||||
|
||||
return s_unboxMethods[name].Invoke(obj, new object[0]);
|
||||
}
|
||||
|
||||
public override string UnboxString(object value)
|
||||
{
|
||||
string s = null;
|
||||
// strings boxed as Il2CppSystem.Objects can behave weirdly.
|
||||
// GetActualType will find they are a string, but if its boxed
|
||||
// then we need to unbox it like this...
|
||||
if (!(value is string) && value is Il2CppSystem.Object cppobj)
|
||||
s = cppobj.ToString();
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
internal static readonly Dictionary<Type, MethodInfo> s_getEnumeratorMethods = new Dictionary<Type, MethodInfo>();
|
||||
|
||||
internal static readonly Dictionary<Type, EnumeratorInfo> s_enumeratorInfos = new Dictionary<Type, EnumeratorInfo>();
|
||||
|
||||
internal class EnumeratorInfo
|
||||
{
|
||||
internal MethodInfo moveNext;
|
||||
internal PropertyInfo current;
|
||||
}
|
||||
|
||||
public override IEnumerable EnumerateEnumerable(object value)
|
||||
{
|
||||
if (value == null)
|
||||
return null;
|
||||
|
||||
var cppEnumerable = (value as Il2CppSystem.Object)?.TryCast<Il2CppSystem.Collections.IEnumerable>();
|
||||
if (cppEnumerable != null)
|
||||
{
|
||||
var type = value.GetType();
|
||||
if (!s_getEnumeratorMethods.ContainsKey(type))
|
||||
s_getEnumeratorMethods.Add(type, type.GetMethod("GetEnumerator"));
|
||||
|
||||
var enumerator = s_getEnumeratorMethods[type].Invoke(value, null);
|
||||
var enumeratorType = enumerator.GetType();
|
||||
|
||||
if (!s_enumeratorInfos.ContainsKey(enumeratorType))
|
||||
{
|
||||
s_enumeratorInfos.Add(enumeratorType, new EnumeratorInfo
|
||||
{
|
||||
current = enumeratorType.GetProperty("Current"),
|
||||
moveNext = enumeratorType.GetMethod("MoveNext"),
|
||||
});
|
||||
}
|
||||
var info = s_enumeratorInfos[enumeratorType];
|
||||
|
||||
// iterate
|
||||
var list = new List<object>();
|
||||
while ((bool)info.moveNext.Invoke(enumerator, null))
|
||||
list.Add(info.current.GetValue(enumerator));
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public override IDictionary EnumerateDictionary(object value, Type typeOfKeys, Type typeOfValues)
|
||||
{
|
||||
var valueType = ReflectionUtility.GetActualType(value);
|
||||
|
||||
var keyList = new List<object>();
|
||||
var valueList = new List<object>();
|
||||
|
||||
var hashtable = value.Cast(typeof(Il2CppSystem.Collections.Hashtable)) as Il2CppSystem.Collections.Hashtable;
|
||||
|
||||
if (hashtable != null)
|
||||
{
|
||||
EnumerateCppHashtable(hashtable, keyList, valueList);
|
||||
}
|
||||
else
|
||||
{
|
||||
var keys = valueType.GetProperty("Keys").GetValue(value, null);
|
||||
var values = valueType.GetProperty("Values").GetValue(value, null);
|
||||
|
||||
EnumerateCppIDictionary(keys, keyList);
|
||||
EnumerateCppIDictionary(values, valueList);
|
||||
}
|
||||
|
||||
var dict = Activator.CreateInstance(typeof(Dictionary<,>)
|
||||
.MakeGenericType(typeOfKeys, typeOfValues))
|
||||
as IDictionary;
|
||||
|
||||
for (int i = 0; i < keyList.Count; i++)
|
||||
dict.Add(keyList[i], valueList[i]);
|
||||
|
||||
return dict;
|
||||
}
|
||||
|
||||
private void EnumerateCppIDictionary(object collection, List<object> list)
|
||||
{
|
||||
// invoke GetEnumerator
|
||||
var enumerator = collection.GetType().GetMethod("GetEnumerator").Invoke(collection, null);
|
||||
// get the type of it
|
||||
var enumeratorType = enumerator.GetType();
|
||||
// reflect MoveNext and Current
|
||||
var moveNext = enumeratorType.GetMethod("MoveNext");
|
||||
var current = enumeratorType.GetProperty("Current");
|
||||
// iterate
|
||||
while ((bool)moveNext.Invoke(enumerator, null))
|
||||
{
|
||||
list.Add(current.GetValue(enumerator, null));
|
||||
}
|
||||
}
|
||||
|
||||
private void EnumerateCppHashtable(Il2CppSystem.Collections.Hashtable hashtable, List<object> keys, List<object> values)
|
||||
{
|
||||
for (int i = 0; i < hashtable.buckets.Count; i++)
|
||||
{
|
||||
var bucket = hashtable.buckets[i];
|
||||
if (bucket == null || bucket.key == null)
|
||||
continue;
|
||||
keys.Add(bucket.key);
|
||||
values.Add(bucket.val);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityExplorer.Core.CSharp
|
||||
namespace UnityExplorer.Core.Runtime.Mono
|
||||
{
|
||||
public class DummyBehaviour : MonoBehaviour
|
||||
{
|
@ -7,6 +7,7 @@ using System.Reflection;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.SceneManagement;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.Core;
|
||||
@ -20,6 +21,8 @@ namespace UnityExplorer.Core.Runtime.Mono
|
||||
{
|
||||
Reflection = new MonoReflection();
|
||||
TextureUtil = new MonoTextureUtil();
|
||||
|
||||
DummyBehaviour.Setup();
|
||||
}
|
||||
|
||||
public override void SetupEvents()
|
||||
@ -32,11 +35,31 @@ namespace UnityExplorer.Core.Runtime.Mono
|
||||
ExplorerCore.Log(condition, type, true);
|
||||
}
|
||||
|
||||
public override void StartConsoleCoroutine(IEnumerator routine)
|
||||
public override void StartCoroutine(IEnumerator routine)
|
||||
{
|
||||
DummyBehaviour.Instance.StartCoroutine(routine);
|
||||
}
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public override T AddComponent<T>(GameObject obj, Type type)
|
||||
{
|
||||
return (T)obj.AddComponent(type);
|
||||
}
|
||||
|
||||
public override ScriptableObject CreateScriptable(Type type)
|
||||
{
|
||||
return ScriptableObject.CreateInstance(type);
|
||||
}
|
||||
|
||||
public override void GraphicRaycast(GraphicRaycaster raycaster, PointerEventData data, List<RaycastResult> list)
|
||||
{
|
||||
raycaster.Raycast(data, list);
|
||||
}
|
||||
|
||||
public override string LayerToName(int layer)
|
||||
=> LayerMask.LayerToName(layer);
|
||||
|
||||
|
@ -12,6 +12,18 @@ namespace UnityExplorer.Core.Runtime.Mono
|
||||
public override object Cast(object obj, Type castTo)
|
||||
=> obj;
|
||||
|
||||
public override T TryCast<T>(object obj)
|
||||
{
|
||||
try
|
||||
{
|
||||
return (T)obj;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return default;
|
||||
}
|
||||
}
|
||||
|
||||
// Vanilla GetType is fine for mono
|
||||
public override Type GetActualType(object obj)
|
||||
=> obj.GetType();
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
@ -18,6 +19,8 @@ namespace UnityExplorer.Core.Runtime
|
||||
|
||||
public abstract object Cast(object obj, Type castTo);
|
||||
|
||||
public abstract T TryCast<T>(object obj);
|
||||
|
||||
public abstract bool IsAssignableFrom(Type toAssignTo, Type toAssignFrom);
|
||||
|
||||
public abstract bool IsReflectionSupported(Type type);
|
||||
@ -27,5 +30,13 @@ namespace UnityExplorer.Core.Runtime
|
||||
public abstract bool LoadModule(string module);
|
||||
|
||||
public abstract void BoxStringToType(ref object _string, Type castTo);
|
||||
|
||||
public virtual string UnboxString(object value) => (string)value;
|
||||
|
||||
public virtual IDictionary EnumerateDictionary(object value, Type typeOfKeys, Type typeOfValues)
|
||||
=> null;
|
||||
|
||||
public virtual IEnumerable EnumerateEnumerable(object value)
|
||||
=> null;
|
||||
}
|
||||
}
|
||||
|
@ -2,16 +2,17 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.SceneManagement;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.Core.Runtime;
|
||||
|
||||
namespace UnityExplorer.Core.Runtime
|
||||
// Intentionally project-wide namespace so that its always easily accessible.
|
||||
namespace UnityExplorer
|
||||
{
|
||||
// Work in progress, this will be used to replace all the "if CPP / if MONO"
|
||||
// pre-processor directives all over the codebase.
|
||||
|
||||
public abstract class RuntimeProvider
|
||||
{
|
||||
public static RuntimeProvider Instance;
|
||||
@ -28,24 +29,33 @@ namespace UnityExplorer.Core.Runtime
|
||||
|
||||
public static void Init() =>
|
||||
#if CPP
|
||||
Instance = new Il2Cpp.Il2CppProvider();
|
||||
Instance = new Core.Runtime.Il2Cpp.Il2CppProvider();
|
||||
#else
|
||||
Instance = new Mono.MonoProvider();
|
||||
Instance = new Core.Runtime.Mono.MonoProvider();
|
||||
#endif
|
||||
|
||||
|
||||
public abstract void Initialize();
|
||||
|
||||
public abstract void SetupEvents();
|
||||
|
||||
public abstract void StartConsoleCoroutine(IEnumerator routine);
|
||||
public abstract void StartCoroutine(IEnumerator routine);
|
||||
|
||||
public abstract void Update();
|
||||
|
||||
public virtual bool IsReferenceEqual(object a, object b) => ReferenceEquals(a, b);
|
||||
|
||||
// Unity API handlers
|
||||
|
||||
public abstract T AddComponent<T>(GameObject obj, Type type) where T : Component;
|
||||
|
||||
public abstract ScriptableObject CreateScriptable(Type type);
|
||||
|
||||
public abstract string LayerToName(int layer);
|
||||
|
||||
public abstract UnityEngine.Object[] FindObjectsOfTypeAll(Type type);
|
||||
|
||||
public abstract void GraphicRaycast(GraphicRaycaster raycaster, PointerEventData data, List<RaycastResult> list);
|
||||
|
||||
public abstract int GetSceneHandle(Scene scene);
|
||||
|
||||
public abstract GameObject[] GetRootGameObjects(Scene scene);
|
||||
@ -53,5 +63,24 @@ namespace UnityExplorer.Core.Runtime
|
||||
public abstract int GetRootCount(Scene scene);
|
||||
|
||||
public abstract ColorBlock SetColorBlock(ColorBlock colors, Color? normal = null, Color? highlighted = null, Color? pressed = null);
|
||||
|
||||
public virtual void FindSingleton(string[] s_instanceNames, Type type, BindingFlags flags, List<object> instances)
|
||||
{
|
||||
// Look for a typical Instance backing field.
|
||||
FieldInfo fi;
|
||||
foreach (var name in s_instanceNames)
|
||||
{
|
||||
fi = type.GetField(name, flags);
|
||||
if (fi != null)
|
||||
{
|
||||
var instance = fi.GetValue(null);
|
||||
if (instance != null)
|
||||
{
|
||||
instances.Add(instance);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -67,38 +67,8 @@ namespace UnityExplorer.Core.Search
|
||||
{
|
||||
if (!string.IsNullOrEmpty(nameFilter) && !type.FullName.ToLower().Contains(nameFilter))
|
||||
continue;
|
||||
#if CPP
|
||||
// Only look for Properties in IL2CPP, not for Mono.
|
||||
PropertyInfo pi;
|
||||
foreach (var name in s_instanceNames)
|
||||
{
|
||||
pi = type.GetProperty(name, flags);
|
||||
if (pi != null)
|
||||
{
|
||||
var instance = pi.GetValue(null, null);
|
||||
if (instance != null)
|
||||
{
|
||||
instances.Add(instance);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// Look for a typical Instance backing field.
|
||||
FieldInfo fi;
|
||||
foreach (var name in s_instanceNames)
|
||||
{
|
||||
fi = type.GetField(name, flags);
|
||||
if (fi != null)
|
||||
{
|
||||
var instance = fi.GetValue(null);
|
||||
if (instance != null)
|
||||
{
|
||||
instances.Add(instance);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RuntimeProvider.Instance.FindSingleton(s_instanceNames, type, flags, instances);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
@ -175,15 +145,9 @@ namespace UnityExplorer.Core.Search
|
||||
|
||||
if (canGetGameObject)
|
||||
{
|
||||
#if MONO
|
||||
var go = context == SearchContext.GameObject
|
||||
? obj as GameObject
|
||||
: (obj as Component).gameObject;
|
||||
#else
|
||||
var go = context == SearchContext.GameObject
|
||||
? obj.TryCast<GameObject>()
|
||||
: obj.TryCast<Component>().gameObject;
|
||||
#endif
|
||||
|
||||
// scene check
|
||||
if (sceneFilter != SceneFilter.Any)
|
||||
|
@ -16,6 +16,7 @@ namespace UnityExplorer
|
||||
public static string nullString = null;
|
||||
|
||||
public static Il2CppSystem.Collections.Hashtable testHashset;
|
||||
public static Il2CppSystem.Collections.Generic.List<Il2CppSystem.Object> testList;
|
||||
|
||||
static TestClass()
|
||||
{
|
||||
@ -23,6 +24,12 @@ namespace UnityExplorer
|
||||
testHashset.Add("key1", "itemOne");
|
||||
testHashset.Add("key2", "itemTwo");
|
||||
testHashset.Add("key3", "itemThree");
|
||||
|
||||
testList = new Il2CppSystem.Collections.Generic.List<Il2CppSystem.Object>(3);
|
||||
testList.Add("One");
|
||||
testList.Add("Two");
|
||||
testList.Add("Three");
|
||||
//testIList = list.TryCast<Il2CppSystem.Collections.IList>();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
Reference in New Issue
Block a user