Cleanup runtime-specific

This commit is contained in:
Sinai 2021-04-07 17:20:09 +10:00
parent c2d9b9b59e
commit 2cc403ad17
29 changed files with 362 additions and 288 deletions

View File

@ -6,7 +6,7 @@
An in-game explorer and a suite of debugging tools for <a href="https://docs.unity3d.com/Manual/IL2CPP.html">IL2CPP</a> and <b>Mono</b> Unity games, to aid with modding development. An in-game explorer and a suite of debugging tools for <a href="https://docs.unity3d.com/Manual/IL2CPP.html">IL2CPP</a> and <b>Mono</b> Unity games, to aid with modding development.
</p> </p>
## Releases [![](https://img.shields.io/github/release/sinai-dev/Explorer.svg?label=release%20notes)](../../releases/latest) [![](https://img.shields.io/github/downloads/sinai-dev/Explorer/total.svg)](../../releases) [![](https://img.shields.io/github/downloads/sinai-dev/Explorer/latest/total.svg)](../../releases/latest) ## Releases [![](https://img.shields.io/github/release/sinai-dev/UnityExplorer.svg?label=release%20notes)](../../releases/latest) [![](https://img.shields.io/github/downloads/sinai-dev/UnityExplorer/total.svg)](../../releases) [![](https://img.shields.io/github/downloads/sinai-dev/UnityExplorer/latest/total.svg)](../../releases/latest)
| Mod Loader | IL2CPP | Mono | | Mod Loader | IL2CPP | Mono |
| ----------- | ------ | ---- | | ----------- | ------ | ---- |

View File

@ -20,7 +20,7 @@ namespace UnityExplorer.Core.CSharp
public static void StartCoroutine(IEnumerator ienumerator) public static void StartCoroutine(IEnumerator ienumerator)
{ {
RuntimeProvider.Instance.StartConsoleCoroutine(ienumerator); RuntimeProvider.Instance.StartCoroutine(ienumerator);
} }
public static void AddUsing(string directive) public static void AddUsing(string directive)

View File

@ -6,9 +6,6 @@ using UnityEngine.EventSystems;
using UnityExplorer.UI; using UnityExplorer.UI;
using System.Collections.Generic; using System.Collections.Generic;
using UnityExplorer.UI.Inspectors; using UnityExplorer.UI.Inspectors;
#if CPP
using UnhollowerRuntimeLib;
#endif
namespace UnityExplorer.Core.Input namespace UnityExplorer.Core.Input
{ {
@ -152,13 +149,9 @@ namespace UnityExplorer.Core.Input
} }
var assetType = ReflectionUtility.GetTypeByName("UnityEngine.InputSystem.InputActionAsset"); var assetType = ReflectionUtility.GetTypeByName("UnityEngine.InputSystem.InputActionAsset");
#if CPP m_newInputModule = RuntimeProvider.Instance.AddComponent<BaseInputModule>(UIManager.CanvasRoot, TInputSystemUIInputModule);
m_newInputModule = UIManager.CanvasRoot.AddComponent(Il2CppType.From(TInputSystemUIInputModule)).TryCast<BaseInputModule>(); var asset = RuntimeProvider.Instance.CreateScriptable(assetType);
var asset = ScriptableObject.CreateInstance(Il2CppType.From(assetType));
#else
m_newInputModule = (BaseInputModule)UIManager.CanvasRoot.AddComponent(TInputSystemUIInputModule);
var asset = ScriptableObject.CreateInstance(assetType);
#endif
inputExtensions = ReflectionUtility.GetTypeByName("UnityEngine.InputSystem.InputActionSetupExtensions"); inputExtensions = ReflectionUtility.GetTypeByName("UnityEngine.InputSystem.InputActionSetupExtensions");
var addMap = inputExtensions.GetMethod("AddActionMap", new Type[] { assetType, typeof(string) }); var addMap = inputExtensions.GetMethod("AddActionMap", new Type[] { assetType, typeof(string) });

View File

@ -43,6 +43,9 @@ namespace UnityExplorer
public static object Cast(this object obj, Type castTo) public static object Cast(this object obj, Type castTo)
=> ReflectionProvider.Instance.Cast(obj, castTo); => ReflectionProvider.Instance.Cast(obj, castTo);
public static T TryCast<T>(this object obj)
=> ReflectionProvider.Instance.TryCast<T>(obj);
/// <summary> /// <summary>
/// Check if the provided Type is assignable to IEnumerable. /// Check if the provided Type is assignable to IEnumerable.
/// </summary> /// </summary>
@ -201,10 +204,9 @@ namespace UnityExplorer
{ {
while (e.InnerException != null) while (e.InnerException != null)
{ {
#if CPP
if (e.InnerException is System.Runtime.CompilerServices.RuntimeWrappedException) if (e.InnerException is System.Runtime.CompilerServices.RuntimeWrappedException)
break; break;
#endif
e = e.InnerException; e = e.InnerException;
} }
} }

View File

@ -50,12 +50,47 @@ namespace UnityExplorer.Core.Runtime.Il2Cpp
ExplorerCore.Log(condition, type, true); ExplorerCore.Log(condition, type, true);
} }
public override void StartConsoleCoroutine(IEnumerator routine) public override void StartCoroutine(IEnumerator routine)
{ {
Il2CppCoroutine.Start(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 // LayerMask.LayerToName
@ -162,6 +197,26 @@ namespace UnityExplorer.Core.Runtime.Il2Cpp
return colors; 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);
}
} }
} }

View File

@ -32,6 +32,18 @@ namespace UnityExplorer.Core.Runtime.Il2Cpp
return Il2CppCast(obj, castTo); 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) public override string ProcessTypeNameInString(Type type, string theString, ref string typeName)
{ {
if (!Il2CppTypeNotNull(type)) if (!Il2CppTypeNotNull(type))
@ -367,6 +379,124 @@ namespace UnityExplorer.Core.Runtime.Il2Cpp
return s_unboxMethods[name].Invoke(obj, new object[0]); 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);
}
}
} }
} }

View File

@ -5,7 +5,7 @@ using System.Linq;
using System.Text; using System.Text;
using UnityEngine; using UnityEngine;
namespace UnityExplorer.Core.CSharp namespace UnityExplorer.Core.Runtime.Mono
{ {
public class DummyBehaviour : MonoBehaviour public class DummyBehaviour : MonoBehaviour
{ {

View File

@ -7,6 +7,7 @@ using System.Reflection;
using System.Text; using System.Text;
using UnityEngine; using UnityEngine;
using UnityEngine.Events; using UnityEngine.Events;
using UnityEngine.EventSystems;
using UnityEngine.SceneManagement; using UnityEngine.SceneManagement;
using UnityEngine.UI; using UnityEngine.UI;
using UnityExplorer.Core; using UnityExplorer.Core;
@ -20,6 +21,8 @@ namespace UnityExplorer.Core.Runtime.Mono
{ {
Reflection = new MonoReflection(); Reflection = new MonoReflection();
TextureUtil = new MonoTextureUtil(); TextureUtil = new MonoTextureUtil();
DummyBehaviour.Setup();
} }
public override void SetupEvents() public override void SetupEvents()
@ -32,11 +35,31 @@ namespace UnityExplorer.Core.Runtime.Mono
ExplorerCore.Log(condition, type, true); ExplorerCore.Log(condition, type, true);
} }
public override void StartConsoleCoroutine(IEnumerator routine) public override void StartCoroutine(IEnumerator routine)
{ {
DummyBehaviour.Instance.StartCoroutine(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) public override string LayerToName(int layer)
=> LayerMask.LayerToName(layer); => LayerMask.LayerToName(layer);

View File

@ -12,6 +12,18 @@ namespace UnityExplorer.Core.Runtime.Mono
public override object Cast(object obj, Type castTo) public override object Cast(object obj, Type castTo)
=> obj; => obj;
public override T TryCast<T>(object obj)
{
try
{
return (T)obj;
}
catch
{
return default;
}
}
// Vanilla GetType is fine for mono // Vanilla GetType is fine for mono
public override Type GetActualType(object obj) public override Type GetActualType(object obj)
=> obj.GetType(); => obj.GetType();

View File

@ -1,4 +1,5 @@
using System; using System;
using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
@ -18,6 +19,8 @@ namespace UnityExplorer.Core.Runtime
public abstract object Cast(object obj, Type castTo); 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 IsAssignableFrom(Type toAssignTo, Type toAssignFrom);
public abstract bool IsReflectionSupported(Type type); public abstract bool IsReflectionSupported(Type type);
@ -27,5 +30,13 @@ namespace UnityExplorer.Core.Runtime
public abstract bool LoadModule(string module); public abstract bool LoadModule(string module);
public abstract void BoxStringToType(ref object _string, Type castTo); 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;
} }
} }

View File

@ -2,16 +2,17 @@
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection;
using System.Text; using System.Text;
using UnityEngine; using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.SceneManagement; using UnityEngine.SceneManagement;
using UnityEngine.UI; 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 abstract class RuntimeProvider
{ {
public static RuntimeProvider Instance; public static RuntimeProvider Instance;
@ -28,24 +29,33 @@ namespace UnityExplorer.Core.Runtime
public static void Init() => public static void Init() =>
#if CPP #if CPP
Instance = new Il2Cpp.Il2CppProvider(); Instance = new Core.Runtime.Il2Cpp.Il2CppProvider();
#else #else
Instance = new Mono.MonoProvider(); Instance = new Core.Runtime.Mono.MonoProvider();
#endif #endif
public abstract void Initialize(); public abstract void Initialize();
public abstract void SetupEvents(); 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 // 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 string LayerToName(int layer);
public abstract UnityEngine.Object[] FindObjectsOfTypeAll(Type type); 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 int GetSceneHandle(Scene scene);
public abstract GameObject[] GetRootGameObjects(Scene scene); public abstract GameObject[] GetRootGameObjects(Scene scene);
@ -53,5 +63,24 @@ namespace UnityExplorer.Core.Runtime
public abstract int GetRootCount(Scene scene); public abstract int GetRootCount(Scene scene);
public abstract ColorBlock SetColorBlock(ColorBlock colors, Color? normal = null, Color? highlighted = null, Color? pressed = null); 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;
}
}
}
}
} }
} }

View File

@ -67,38 +67,8 @@ namespace UnityExplorer.Core.Search
{ {
if (!string.IsNullOrEmpty(nameFilter) && !type.FullName.ToLower().Contains(nameFilter)) if (!string.IsNullOrEmpty(nameFilter) && !type.FullName.ToLower().Contains(nameFilter))
continue; continue;
#if CPP
// Only look for Properties in IL2CPP, not for Mono. RuntimeProvider.Instance.FindSingleton(s_instanceNames, type, flags, instances);
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;
}
}
}
} }
catch { } catch { }
} }
@ -175,15 +145,9 @@ namespace UnityExplorer.Core.Search
if (canGetGameObject) if (canGetGameObject)
{ {
#if MONO
var go = context == SearchContext.GameObject
? obj as GameObject
: (obj as Component).gameObject;
#else
var go = context == SearchContext.GameObject var go = context == SearchContext.GameObject
? obj.TryCast<GameObject>() ? obj.TryCast<GameObject>()
: obj.TryCast<Component>().gameObject; : obj.TryCast<Component>().gameObject;
#endif
// scene check // scene check
if (sceneFilter != SceneFilter.Any) if (sceneFilter != SceneFilter.Any)

View File

@ -16,6 +16,7 @@ namespace UnityExplorer
public static string nullString = null; public static string nullString = null;
public static Il2CppSystem.Collections.Hashtable testHashset; public static Il2CppSystem.Collections.Hashtable testHashset;
public static Il2CppSystem.Collections.Generic.List<Il2CppSystem.Object> testList;
static TestClass() static TestClass()
{ {
@ -23,6 +24,12 @@ namespace UnityExplorer
testHashset.Add("key1", "itemOne"); testHashset.Add("key1", "itemOne");
testHashset.Add("key2", "itemTwo"); testHashset.Add("key2", "itemTwo");
testHashset.Add("key3", "itemThree"); 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 #endif
} }

View File

@ -13,7 +13,7 @@ namespace UnityExplorer
public class ExplorerCore public class ExplorerCore
{ {
public const string NAME = "UnityExplorer"; public const string NAME = "UnityExplorer";
public const string VERSION = "3.3.8"; public const string VERSION = "3.3.9";
public const string AUTHOR = "Sinai"; public const string AUTHOR = "Sinai";
public const string GUID = "com.sinai.unityexplorer"; public const string GUID = "com.sinai.unityexplorer";
@ -48,11 +48,13 @@ namespace UnityExplorer
Log($"{NAME} {VERSION} initialized."); Log($"{NAME} {VERSION} initialized.");
//InspectorManager.Instance.Inspect(typeof(TestClass)); InspectorManager.Instance.Inspect(typeof(TestClass));
} }
public static void Update() public static void Update()
{ {
RuntimeProvider.Instance.Update();
UIManager.Update(); UIManager.Update();
} }

View File

@ -23,7 +23,9 @@ namespace UnityExplorer.Loader.ML
try try
{ {
// TEMPORARY - JUST REQUIRED UNTIL ML 0.3.1 RELEASED
MelonPreferences.Mapper.RegisterMapper(KeycodeReader, KeycodeWriter); MelonPreferences.Mapper.RegisterMapper(KeycodeReader, KeycodeWriter);
MelonPreferences.Mapper.RegisterMapper(MenuPagesReader, MenuPagesWriter);
} }
catch { } catch { }
} }
@ -80,6 +82,8 @@ namespace UnityExplorer.Loader.ML
MelonPreferences.Save(); MelonPreferences.Save();
} }
// TEMPORARY - JUST REQUIRED UNTIL ML 0.3.1 RELEASED
public static KeyCode KeycodeReader(TomlObject value) public static KeyCode KeycodeReader(TomlObject value)
{ {
try try
@ -101,6 +105,28 @@ namespace UnityExplorer.Loader.ML
{ {
return MelonPreferences.Mapper.ToToml(value.ToString()); return MelonPreferences.Mapper.ToToml(value.ToString());
} }
public static UI.Main.MenuPages MenuPagesReader(TomlObject value)
{
try
{
var kc = (UI.Main.MenuPages)Enum.Parse(typeof(UI.Main.MenuPages), (value as TomlString).Value);
if (kc == default)
throw new Exception();
return kc;
}
catch
{
return UI.Main.MenuPages.Home;
}
}
public static TomlObject MenuPagesWriter(UI.Main.MenuPages value)
{
return MelonPreferences.Mapper.ToToml(value.ToString());
}
} }
} }

View File

@ -57,7 +57,11 @@ namespace UnityExplorer.UI.CacheObject
var rowObj = UIFactory.CreateHorizontalGroup(m_mainContent, "PairedGroup", false, false, true, true, 0, new Vector4(0,0,5,2), var rowObj = UIFactory.CreateHorizontalGroup(m_mainContent, "PairedGroup", false, false, true, true, 0, new Vector4(0,0,5,2),
bgColor); bgColor);
var indexLabel = UIFactory.CreateLabel(rowObj, "IndexLabel", $"{this.PairType} {this.Index}:", TextAnchor.MiddleLeft); string lbl = $"{this.PairType}";
if (this.PairType == PairTypes.Key)
lbl = $"[{Index}] {lbl}";
var indexLabel = UIFactory.CreateLabel(rowObj, "IndexLabel", lbl, TextAnchor.MiddleLeft);
UIFactory.SetLayoutElement(indexLabel.gameObject, minWidth: 80, flexibleWidth: 30, minHeight: 25); UIFactory.SetLayoutElement(indexLabel.gameObject, minWidth: 80, flexibleWidth: 30, minHeight: 25);
IValue.m_mainContentParent = rowObj; IValue.m_mainContentParent = rowObj;

View File

@ -78,11 +78,7 @@ namespace UnityExplorer.UI.Inspectors.GameObjects
text.text = SignatureHighlighter.ParseFullSyntax(ReflectionUtility.GetActualType(comp), true); text.text = SignatureHighlighter.ParseFullSyntax(ReflectionUtility.GetActualType(comp), true);
var toggle = s_compToggles[i]; var toggle = s_compToggles[i];
#if CPP
if (comp.TryCast<Behaviour>() is Behaviour behaviour) if (comp.TryCast<Behaviour>() is Behaviour behaviour)
#else
if (comp is Behaviour behaviour)
#endif
{ {
if (!toggle.gameObject.activeSelf) if (!toggle.gameObject.activeSelf)
toggle.gameObject.SetActive(true); toggle.gameObject.SetActive(true);
@ -109,19 +105,13 @@ namespace UnityExplorer.UI.Inspectors.GameObjects
internal static void OnCompToggleClicked(int index, bool value) internal static void OnCompToggleClicked(int index, bool value)
{ {
var comp = s_compShortlist[index]; var comp = s_compShortlist[index];
#if CPP
comp.TryCast<Behaviour>().enabled = value; comp.TryCast<Behaviour>().enabled = value;
#else
(comp as Behaviour).enabled = value;
#endif
} }
internal static void OnCompListObjectClicked(int index) internal static void OnCompListObjectClicked(int index)
{ {
if (index >= s_compShortlist.Count || !s_compShortlist[index]) if (index >= s_compShortlist.Count || !s_compShortlist[index])
{
return; return;
}
InspectorManager.Instance.Inspect(s_compShortlist[index]); InspectorManager.Instance.Inspect(s_compShortlist[index]);
} }

View File

@ -203,11 +203,6 @@ namespace UnityExplorer.UI.Main.Home
position = mousePos position = mousePos
}; };
#if MONO
var list = new List<RaycastResult>();
#else
var list = new Il2CppSystem.Collections.Generic.List<RaycastResult>();
#endif
//ExplorerCore.Log("~~~~~~~~~ begin raycast ~~~~~~~~"); //ExplorerCore.Log("~~~~~~~~~ begin raycast ~~~~~~~~");
GameObject hitObject = null; GameObject hitObject = null;
int highestLayer = int.MinValue; int highestLayer = int.MinValue;
@ -215,7 +210,10 @@ namespace UnityExplorer.UI.Main.Home
int highestDepth = int.MinValue; int highestDepth = int.MinValue;
foreach (var gr in graphicRaycasters) foreach (var gr in graphicRaycasters)
{ {
gr.Raycast(ped, list); var list = new List<RaycastResult>();
RuntimeProvider.Instance.GraphicRaycast(gr, ped, list);
//gr.Raycast(ped, list);
if (list.Count > 0) if (list.Count > 0)
{ {
@ -290,8 +288,6 @@ namespace UnityExplorer.UI.Main.Home
_wasDisabledGraphics.Clear(); _wasDisabledGraphics.Clear();
} }
#region UI
internal static Text s_objNameLabel; internal static Text s_objNameLabel;
internal static Text s_objPathLabel; internal static Text s_objPathLabel;
internal static Text s_mousePosLabel; internal static Text s_mousePosLabel;
@ -328,7 +324,5 @@ namespace UnityExplorer.UI.Main.Home
s_UIContent.SetActive(false); s_UIContent.SetActive(false);
} }
#endregion
} }
} }

View File

@ -54,21 +54,11 @@ namespace UnityExplorer.UI.Inspectors
// check if currently inspecting this object // check if currently inspecting this object
foreach (InspectorBase tab in m_currentInspectors) foreach (InspectorBase tab in m_currentInspectors)
{ {
if (ReferenceEquals(obj, tab.Target)) if (RuntimeProvider.Instance.IsReferenceEqual(obj, tab.Target))
{ {
SetInspectorTab(tab); SetInspectorTab(tab);
return; return;
} }
#if CPP
else if (unityObj && tab.Target is UnityEngine.Object uTabObj)
{
if (unityObj.m_CachedPtr == uTabObj.m_CachedPtr)
{
SetInspectorTab(tab);
return;
}
}
#endif
} }
InspectorBase inspector; InspectorBase inspector;

View File

@ -13,7 +13,9 @@ using UnityExplorer.UI.CacheObject;
using UnityExplorer.Core; using UnityExplorer.Core;
using UnityExplorer.UI.Utility; using UnityExplorer.UI.Utility;
#if CPP #if CPP
using CppDictionary = Il2CppSystem.Collections.IDictionary; using AltIDictionary = Il2CppSystem.Collections.IDictionary;
#else
using AltIDictionary = System.Collections.IDictionary;
#endif #endif
namespace UnityExplorer.UI.InteractiveValues namespace UnityExplorer.UI.InteractiveValues
@ -48,11 +50,7 @@ namespace UnityExplorer.UI.InteractiveValues
} }
internal IDictionary RefIDictionary; internal IDictionary RefIDictionary;
#if CPP internal AltIDictionary RefAltIDictionary;
internal CppDictionary RefCppDictionary;
#else
internal IDictionary RefCppDictionary = null;
#endif
internal Type m_typeOfKeys; internal Type m_typeOfKeys;
internal Type m_typeofValues; internal Type m_typeofValues;
@ -73,10 +71,11 @@ namespace UnityExplorer.UI.InteractiveValues
{ {
RefIDictionary = Value as IDictionary; RefIDictionary = Value as IDictionary;
#if CPP if (RefIDictionary == null)
try { RefCppDictionary = (Value as Il2CppSystem.Object).TryCast<CppDictionary>(); } {
try { RefAltIDictionary = Value.TryCast<AltIDictionary>(); }
catch { } catch { }
#endif }
if (m_subContentParent.activeSelf) if (m_subContentParent.activeSelf)
{ {
@ -129,10 +128,8 @@ namespace UnityExplorer.UI.InteractiveValues
m_entries.Clear(); m_entries.Clear();
} }
#if CPP
if (RefIDictionary == null && Value != null) if (RefIDictionary == null && Value != null)
RefIDictionary = EnumerateWithReflection(); RefIDictionary = RuntimeProvider.Instance.Reflection.EnumerateDictionary(Value, m_typeOfKeys, m_typeofValues);
#endif
if (RefIDictionary != null) if (RefIDictionary != null)
{ {
@ -212,82 +209,11 @@ namespace UnityExplorer.UI.InteractiveValues
RefreshDisplay(); RefreshDisplay();
} }
#region CPP fixes
#if CPP
// temp fix for Il2Cpp IDictionary until interfaces are fixed
private IDictionary EnumerateWithReflection()
{
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(m_typeOfKeys, m_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);
}
}
#endif
#endregion
#region UI CONSTRUCTION
internal GameObject m_listContent; internal GameObject m_listContent;
internal LayoutElement m_listLayout; internal LayoutElement m_listLayout;
internal PageHandler m_pageHandler; internal PageHandler m_pageHandler;
//internal List<GameObject> m_rowHolders = new List<GameObject>();
public override void ConstructUI(GameObject parent, GameObject subGroup) public override void ConstructUI(GameObject parent, GameObject subGroup)
{ {
base.ConstructUI(parent, subGroup); base.ConstructUI(parent, subGroup);
@ -317,7 +243,5 @@ namespace UnityExplorer.UI.InteractiveValues
contentFitter.horizontalFit = ContentSizeFitter.FitMode.Unconstrained; contentFitter.horizontalFit = ContentSizeFitter.FitMode.Unconstrained;
contentFitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize; contentFitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
} }
#endregion
} }
} }

View File

@ -39,11 +39,6 @@ namespace UnityExplorer.UI.InteractiveValues
internal IEnumerable RefIEnumerable; internal IEnumerable RefIEnumerable;
internal IList RefIList; internal IList RefIList;
//#if CPP
// internal object CppICollection;
//#else
// internal object CppICollection = null;
//#endif
internal readonly Type m_baseEntryType; internal readonly Type m_baseEntryType;
@ -56,18 +51,6 @@ namespace UnityExplorer.UI.InteractiveValues
RefIEnumerable = Value as IEnumerable; RefIEnumerable = Value as IEnumerable;
RefIList = Value as IList; RefIList = Value as IList;
//#if CPP
// if (Value != null && RefIList == null)
// {
// try
// {
// var type = typeof(Il2CppSystem.Collections.ICollection).MakeGenericType(this.m_baseEntryType);
// CppICollection = (Value as Il2CppSystem.Object).Cast(type);
// }
// catch { }
// }
//#endif
if (m_subContentParent.activeSelf) if (m_subContentParent.activeSelf)
{ {
GetCacheEntries(); GetCacheEntries();
@ -96,8 +79,8 @@ namespace UnityExplorer.UI.InteractiveValues
if (Value != null) if (Value != null)
{ {
string count = "?"; string count = "?";
if (m_recacheWanted && RefIList != null)// || CppICollection != null)) if (m_recacheWanted && RefIList != null)
count = RefIList.Count.ToString();// ?? CppICollection.Count.ToString(); count = RefIList.Count.ToString();
else if (!m_recacheWanted) else if (!m_recacheWanted)
count = m_entries.Count.ToString(); count = m_entries.Count.ToString();
@ -121,10 +104,8 @@ namespace UnityExplorer.UI.InteractiveValues
m_entries.Clear(); m_entries.Clear();
} }
#if CPP
if (RefIEnumerable == null && Value != null) if (RefIEnumerable == null && Value != null)
RefIEnumerable = EnumerateWithReflection(); RefIEnumerable = RuntimeProvider.Instance.Reflection.EnumerateEnumerable(Value);
#endif
if (RefIEnumerable != null) if (RefIEnumerable != null)
{ {
@ -188,62 +169,6 @@ namespace UnityExplorer.UI.InteractiveValues
RefreshDisplay(); RefreshDisplay();
} }
#region CPP Helpers
#if CPP
// some temp fixes for Il2Cpp IEnumerables until interfaces are fixed
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;
}
private IEnumerable EnumerateWithReflection()
{
if (Value == null)
return null;
// new test
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;
}
#endif
#endregion
#region UI CONSTRUCTION
internal GameObject m_listContent; internal GameObject m_listContent;
internal LayoutElement m_listLayout; internal LayoutElement m_listLayout;
@ -278,7 +203,5 @@ namespace UnityExplorer.UI.InteractiveValues
contentFitter.horizontalFit = ContentSizeFitter.FitMode.Unconstrained; contentFitter.horizontalFit = ContentSizeFitter.FitMode.Unconstrained;
contentFitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize; contentFitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
} }
#endregion
} }
} }

View File

@ -24,13 +24,7 @@ namespace UnityExplorer.UI.InteractiveValues
public override void OnValueUpdated() public override void OnValueUpdated()
{ {
#if CPP Value = RuntimeProvider.Instance.Reflection.UnboxString(Value);
// 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)
Value = cppobj.ToString();
#endif
base.OnValueUpdated(); base.OnValueUpdated();
} }

View File

@ -7,9 +7,19 @@ using UnityEngine.UI;
namespace UnityExplorer.UI.Main namespace UnityExplorer.UI.Main
{ {
public enum MenuPages
{
Home,
Search,
CSConsole,
Options
}
public abstract class BaseMenuPage public abstract class BaseMenuPage
{ {
public abstract string Name { get; } public abstract string Name { get; }
public abstract MenuPages Type { get; }
public bool WasDisabled { get; internal set; }
public GameObject Content; public GameObject Content;
public Button RefNavbarButton { get; set; } public Button RefNavbarButton { get; set; }
@ -20,7 +30,6 @@ namespace UnityExplorer.UI.Main
set => Content?.SetActive(true); set => Content?.SetActive(true);
} }
public abstract bool Init(); public abstract bool Init();
public abstract void Update(); public abstract void Update();
} }

View File

@ -13,15 +13,13 @@ using UnityExplorer.UI.Main.CSConsole;
using UnityExplorer.Core; using UnityExplorer.Core;
using UnityExplorer.Core.Unity; using UnityExplorer.Core.Unity;
using UnityExplorer.UI.Utility; using UnityExplorer.UI.Utility;
#if CPP
using UnityExplorer.Core.Runtime.Il2Cpp;
#endif
namespace UnityExplorer.UI.Main.CSConsole namespace UnityExplorer.UI.Main.CSConsole
{ {
public class CSharpConsole : BaseMenuPage public class CSharpConsole : BaseMenuPage
{ {
public override string Name => "C# Console"; public override string Name => "C# Console";
public override MenuPages Type => MenuPages.CSConsole;
public static CSharpConsole Instance { get; private set; } public static CSharpConsole Instance { get; private set; }
@ -53,9 +51,6 @@ namespace UnityExplorer.UI.Main.CSConsole
InitConsole(); InitConsole();
AutoCompleter.Init(); AutoCompleter.Init();
#if MONO
DummyBehaviour.Setup();
#endif
ResetConsole(false); ResetConsole(false);
// Make sure compiler is supported on this platform // Make sure compiler is supported on this platform
@ -102,9 +97,6 @@ namespace UnityExplorer.UI.Main.CSConsole
UpdateConsole(); UpdateConsole();
AutoCompleter.Update(); AutoCompleter.Update();
#if CPP
Il2CppCoroutine.Process();
#endif
} }
public void AddUsing(string asm) public void AddUsing(string asm)

View File

@ -219,7 +219,7 @@
<Compile Include="Core\Config\ConfigManager.cs" /> <Compile Include="Core\Config\ConfigManager.cs" />
<Compile Include="Core\Config\IConfigElement.cs" /> <Compile Include="Core\Config\IConfigElement.cs" />
<Compile Include="Core\Config\ConfigHandler.cs" /> <Compile Include="Core\Config\ConfigHandler.cs" />
<Compile Include="Core\CSharp\DummyBehaviour.cs" /> <Compile Include="Core\Runtime\Mono\DummyBehaviour.cs" />
<Compile Include="Core\CSharp\ScriptEvaluator.cs" /> <Compile Include="Core\CSharp\ScriptEvaluator.cs" />
<Compile Include="Core\CSharp\ScriptInteraction.cs" /> <Compile Include="Core\CSharp\ScriptInteraction.cs" />
<Compile Include="Core\CSharp\Suggestion.cs" /> <Compile Include="Core\CSharp\Suggestion.cs" />