Compare commits

..

6 Commits
3.3.4 ... 3.3.6

Author SHA1 Message Date
6ca117b070 Fix strings boxed as Il2CppSystem.Objects 2021-04-04 13:44:58 +10:00
113f2fd922 3.3.5 - fix Il2Cpp Hashtable, boxed strings 2021-04-04 03:41:36 +10:00
7443f6500e Update README.md 2021-04-03 17:24:28 +11:00
92566c2729 Update README.md 2021-04-02 19:56:18 +11:00
713f87f455 Update THIRDPARTY_LICENSES.md 2021-04-02 17:45:50 +11:00
4241e7e207 Include third-party licenses 2021-04-02 17:44:49 +11:00
31 changed files with 1242 additions and 79 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)]() [![](https://img.shields.io/github/downloads/sinai-dev/Explorer/latest/total.svg)]() ## 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)
| Mod Loader | IL2CPP | Mono | | Mod Loader | IL2CPP | Mono |
| ----------- | ------ | ---- | | ----------- | ------ | ---- |
@ -135,10 +135,10 @@ Building the project should be straight-forward, the references are all inside t
## Acknowledgments ## Acknowledgments
* [ManlyMarco](https://github.com/ManlyMarco) for [Runtime Unity Editor](https://github.com/ManlyMarco/RuntimeUnityEditor), snippets from the REPL Console were used for UnityExplorer's C# Console. * [ManlyMarco](https://github.com/ManlyMarco) for [Runtime Unity Editor](https://github.com/ManlyMarco/RuntimeUnityEditor) \[[license](THIRDPARTY_LICENSES.md#runtimeunityeditor-license)\], snippets from the REPL Console were used for UnityExplorer's C# Console.
* [denikson](https://github.com/denikson) (aka Horse) for [mcs-unity](https://github.com/denikson/mcs-unity), used as the `Mono.CSharp` reference for the C# Console. * [denikson](https://github.com/denikson) (aka Horse) for [mcs-unity](https://github.com/denikson/mcs-unity) \[no license\], used as the `Mono.CSharp` reference for the C# Console.
* [HerpDerpenstine](https://github.com/HerpDerpinstine) for [MelonCoroutines](https://github.com/LavaGang/MelonLoader/blob/master/MelonLoader.Support.Il2Cpp/MelonCoroutines.cs), they were included for standalone IL2CPP coroutine support. * [HerpDerpenstine](https://github.com/HerpDerpinstine) for [MelonCoroutines](https://github.com/LavaGang/MelonLoader/blob/6cc958ec23b5e2e8453a73bc2e0d5aa353d4f0d1/MelonLoader.Support.Il2Cpp/MelonCoroutines.cs) \[[license](THIRDPARTY_LICENSES.md#melonloader-license)\], they were included for standalone IL2CPP coroutine support.
* [InGameCodeEditor](https://assetstore.unity.com/packages/tools/gui/ingame-code-editor-144254) was used as the base for the syntax highlighting for UnityExplorer's C# console (`UnityExplorer.UI.Main.CSConsole.Lexer`). * [InGameCodeEditor](https://assetstore.unity.com/packages/tools/gui/ingame-code-editor-144254) \[[license](THIRDPARTY_LICENSES.md#ingamecodeeditor-license)\] was used as the base for the syntax highlighting for UnityExplorer's C# console (`UnityExplorer.UI.Main.CSConsole.Lexer`).
### Disclaimer ### Disclaimer

1067
THIRDPARTY_LICENSES.md Normal file

File diff suppressed because it is too large Load Diff

View File

@ -7,6 +7,7 @@ using System.Linq;
using UnityExplorer.Core.Runtime; using UnityExplorer.Core.Runtime;
using UnityExplorer.UI.Main.CSConsole; using UnityExplorer.UI.Main.CSConsole;
using UnityExplorer.UI.Main.Home; using UnityExplorer.UI.Main.Home;
using UnityExplorer.UI.Inspectors;
namespace UnityExplorer.Core.CSharp namespace UnityExplorer.Core.CSharp
{ {

View File

@ -7,7 +7,7 @@ using System.Reflection;
using BF = System.Reflection.BindingFlags; using BF = System.Reflection.BindingFlags;
using UnityExplorer.Core.Runtime; using UnityExplorer.Core.Runtime;
namespace UnityExplorer.Core namespace UnityExplorer
{ {
public static class ReflectionUtility public static class ReflectionUtility
{ {
@ -18,7 +18,7 @@ namespace UnityExplorer.Core
/// </summary> /// </summary>
/// <param name="obj">The object to get the true Type for.</param> /// <param name="obj">The object to get the true Type for.</param>
/// <returns>The most accurate Type of the object which could be identified.</returns> /// <returns>The most accurate Type of the object which could be identified.</returns>
public static Type GetType(this object obj) public static Type GetActualType(this object obj)
{ {
if (obj == null) if (obj == null)
return null; return null;
@ -32,7 +32,7 @@ namespace UnityExplorer.Core
/// <param name="obj">The object to cast</param> /// <param name="obj">The object to cast</param>
/// <returns>The object, cast to the underlying Type if possible, otherwise the original object.</returns> /// <returns>The object, cast to the underlying Type if possible, otherwise the original object.</returns>
public static object Cast(this object obj) public static object Cast(this object obj)
=> ReflectionProvider.Instance.Cast(obj, GetType(obj)); => ReflectionProvider.Instance.Cast(obj, GetActualType(obj));
/// <summary> /// <summary>
/// Cast an object to a Type, if possible. /// Cast an object to a Type, if possible.
@ -105,7 +105,7 @@ namespace UnityExplorer.Core
/// <summary> /// <summary>
/// Get all base types of the provided Type, including itself. /// Get all base types of the provided Type, including itself.
/// </summary> /// </summary>
public static Type[] GetAllBaseTypes(this object obj) => GetAllBaseTypes(GetType(obj)); public static Type[] GetAllBaseTypes(this object obj) => GetAllBaseTypes(GetActualType(obj));
/// <summary> /// <summary>
/// Get all base types of the provided Type, including itself. /// Get all base types of the provided Type, including itself.

View File

@ -154,21 +154,24 @@ namespace UnityExplorer.Core.Runtime.Il2Cpp
/// <returns>The object, as the type (or a normal C# object) if successful or the input value if not.</returns> /// <returns>The object, as the type (or a normal C# object) if successful or the input value if not.</returns>
public static object Il2CppCast(object obj, Type castTo) public static object Il2CppCast(object obj, Type castTo)
{ {
if (!(obj is Il2CppSystem.Object ilObj)) if (!(obj is Il2CppSystem.Object cppObj))
return obj; return obj;
if (!Il2CppTypeNotNull(castTo, out IntPtr castToPtr)) if (!Il2CppTypeNotNull(castTo, out IntPtr castToPtr))
return obj; return obj;
IntPtr castFromPtr = il2cpp_object_get_class(ilObj.Pointer); IntPtr castFromPtr = il2cpp_object_get_class(cppObj.Pointer);
if (!il2cpp_class_is_assignable_from(castToPtr, castFromPtr)) if (!il2cpp_class_is_assignable_from(castToPtr, castFromPtr))
return obj; return null;
if (RuntimeSpecificsStore.IsInjected(castToPtr)) if (RuntimeSpecificsStore.IsInjected(castToPtr))
return UnhollowerBaseLib.Runtime.ClassInjectorBase.GetMonoObjectFromIl2CppPointer(ilObj.Pointer); return UnhollowerBaseLib.Runtime.ClassInjectorBase.GetMonoObjectFromIl2CppPointer(cppObj.Pointer);
return Activator.CreateInstance(castTo, ilObj.Pointer); if (castTo == typeof(string))
return cppObj.ToString();
return Activator.CreateInstance(castTo, cppObj.Pointer);
} }
/// <summary> /// <summary>
@ -319,6 +322,14 @@ namespace UnityExplorer.Core.Runtime.Il2Cpp
return false; return false;
} }
public override void BoxStringToType(ref object value, Type castTo)
{
if (castTo == typeof(Il2CppSystem.String))
value = (Il2CppSystem.String)(value as string);
else
value = (Il2CppSystem.Object)(value as string);
}
// ~~~~~~~~~~ not used ~~~~~~~~~~~~ // ~~~~~~~~~~ not used ~~~~~~~~~~~~
// cached il2cpp unbox methods // cached il2cpp unbox methods

View File

@ -27,6 +27,9 @@ namespace UnityExplorer.Core.Runtime.Mono
public override string ProcessTypeNameInString(Type type, string theString, ref string typeName) public override string ProcessTypeNameInString(Type type, string theString, ref string typeName)
=> theString; => theString;
// not necessary
public override void BoxStringToType(ref object _string, Type castTo) { }
} }
} }

View File

@ -25,5 +25,7 @@ namespace UnityExplorer.Core.Runtime
public abstract string ProcessTypeNameInString(Type type, string theString, ref string typeName); public abstract string ProcessTypeNameInString(Type type, string theString, ref string typeName);
public abstract bool LoadModule(string module); public abstract bool LoadModule(string module);
public abstract void BoxStringToType(ref object _string, Type castTo);
} }
} }

27
src/Core/TestClass.cs Normal file
View File

@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace UnityExplorer
{
public static class TestClass
{
#if CPP
public static string testStringOne = "Test";
public static Il2CppSystem.Object testStringTwo = "string boxed as cpp object";
public static Il2CppSystem.String testStringThree = "string boxed as cpp string";
public static string nullString = null;
public static Il2CppSystem.Collections.Hashtable testHashset;
static TestClass()
{
testHashset = new Il2CppSystem.Collections.Hashtable();
testHashset.Add("key1", "itemOne");
testHashset.Add("key2", "itemTwo");
testHashset.Add("key3", "itemThree");
}
#endif
}
}

View File

@ -5,6 +5,7 @@ using UnityExplorer.Core.Config;
using UnityExplorer.Core.Input; using UnityExplorer.Core.Input;
using UnityExplorer.Core.Runtime; using UnityExplorer.Core.Runtime;
using UnityExplorer.UI; using UnityExplorer.UI;
using UnityExplorer.UI.Inspectors;
using UnityExplorer.UI.Main; using UnityExplorer.UI.Main;
namespace UnityExplorer namespace UnityExplorer
@ -12,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.4"; public const string VERSION = "3.3.6";
public const string AUTHOR = "Sinai"; public const string AUTHOR = "Sinai";
public const string GUID = "com.sinai.unityexplorer"; public const string GUID = "com.sinai.unityexplorer";
@ -46,6 +47,8 @@ namespace UnityExplorer
UIManager.Init(); UIManager.Init();
Log($"{NAME} {VERSION} initialized."); Log($"{NAME} {VERSION} initialized.");
// InspectorManager.Instance.Inspect(typeof(TestClass));
} }
public static void Update() public static void Update()

View File

@ -21,8 +21,12 @@ namespace UnityExplorer.Loader.ML
{ {
prefCategory = MelonPreferences.CreateCategory(CTG_NAME, $"{CTG_NAME} Settings"); prefCategory = MelonPreferences.CreateCategory(CTG_NAME, $"{CTG_NAME} Settings");
try
{
MelonPreferences.Mapper.RegisterMapper(KeycodeReader, KeycodeWriter); MelonPreferences.Mapper.RegisterMapper(KeycodeReader, KeycodeWriter);
} }
catch { }
}
public override void LoadConfig() public override void LoadConfig()
{ {

View File

@ -10,7 +10,7 @@ using UnityExplorer.Core.Runtime;
using UnityExplorer.Core; using UnityExplorer.Core;
using UnityExplorer.UI.Utility; using UnityExplorer.UI.Utility;
using UnityExplorer.UI.InteractiveValues; using UnityExplorer.UI.InteractiveValues;
using UnityExplorer.UI.Main.Home.Inspectors.Reflection; using UnityExplorer.UI.Inspectors.Reflection;
namespace UnityExplorer.UI.CacheObject namespace UnityExplorer.UI.CacheObject
{ {
@ -86,7 +86,7 @@ namespace UnityExplorer.UI.CacheObject
{ {
try try
{ {
Type baseType = ReflectionUtility.GetType(IValue.Value) ?? FallbackType; Type baseType = ReflectionUtility.GetActualType(IValue.Value) ?? FallbackType;
if (!ReflectionProvider.Instance.IsReflectionSupported(baseType)) if (!ReflectionProvider.Instance.IsReflectionSupported(baseType))
throw new Exception("Type not supported with reflection"); throw new Exception("Type not supported with reflection");
@ -94,7 +94,7 @@ namespace UnityExplorer.UI.CacheObject
UpdateReflection(); UpdateReflection();
if (IValue.Value != null) if (IValue.Value != null)
IValue.Value = IValue.Value.Cast(ReflectionUtility.GetType(IValue.Value)); IValue.Value = IValue.Value.Cast(ReflectionUtility.GetActualType(IValue.Value));
} }
catch (Exception e) catch (Exception e)
{ {

View File

@ -55,7 +55,7 @@ namespace UnityExplorer.UI.CacheObject
// if the type has changed fundamentally, make a new interactivevalue for it // if the type has changed fundamentally, make a new interactivevalue for it
var type = value == null var type = value == null
? FallbackType ? FallbackType
: ReflectionUtility.GetType(value); : ReflectionUtility.GetActualType(value);
var ivalueType = InteractiveValue.GetIValueForType(type); var ivalueType = InteractiveValue.GetIValueForType(type);

View File

@ -7,7 +7,7 @@ using UnityEngine.UI;
using UnityExplorer.Core.Runtime; using UnityExplorer.Core.Runtime;
using UnityExplorer.UI.Utility; using UnityExplorer.UI.Utility;
namespace UnityExplorer.UI.Main.Home.Inspectors.GameObjects namespace UnityExplorer.UI.Inspectors.GameObjects
{ {
public class ChildList public class ChildList
{ {

View File

@ -8,7 +8,7 @@ using UnityExplorer.Core;
using UnityExplorer.Core.Runtime; using UnityExplorer.Core.Runtime;
using UnityExplorer.UI.Utility; using UnityExplorer.UI.Utility;
namespace UnityExplorer.UI.Main.Home.Inspectors.GameObjects namespace UnityExplorer.UI.Inspectors.GameObjects
{ {
public class ComponentList public class ComponentList
{ {
@ -75,7 +75,7 @@ namespace UnityExplorer.UI.Main.Home.Inspectors.GameObjects
var text = s_compListTexts[i]; var text = s_compListTexts[i];
text.text = SignatureHighlighter.ParseFullSyntax(ReflectionUtility.GetType(comp), true); text.text = SignatureHighlighter.ParseFullSyntax(ReflectionUtility.GetActualType(comp), true);
var toggle = s_compToggles[i]; var toggle = s_compToggles[i];
#if CPP #if CPP

View File

@ -8,7 +8,7 @@ using UnityExplorer.Core.Input;
using UnityExplorer.Core.Runtime; using UnityExplorer.Core.Runtime;
using UnityExplorer.Core.Unity; using UnityExplorer.Core.Unity;
namespace UnityExplorer.UI.Main.Home.Inspectors.GameObjects namespace UnityExplorer.UI.Inspectors.GameObjects
{ {
public class GameObjectControls public class GameObjectControls
{ {

View File

@ -7,7 +7,7 @@ using UnityEngine.UI;
using UnityExplorer.Core.Runtime; using UnityExplorer.Core.Runtime;
using UnityExplorer.Core.Unity; using UnityExplorer.Core.Unity;
namespace UnityExplorer.UI.Main.Home.Inspectors.GameObjects namespace UnityExplorer.UI.Inspectors.GameObjects
{ {
public class GameObjectInspector : InspectorBase public class GameObjectInspector : InspectorBase
{ {

View File

@ -11,6 +11,7 @@ using UnityExplorer.Core.Input;
using UnityExplorer.Core.Runtime; using UnityExplorer.Core.Runtime;
using UnityExplorer.UI; using UnityExplorer.UI;
using UnityExplorer.UI.Main; using UnityExplorer.UI.Main;
using UnityExplorer.UI.Inspectors;
namespace UnityExplorer.UI.Main.Home namespace UnityExplorer.UI.Main.Home
{ {

View File

@ -3,7 +3,7 @@ using UnityEngine;
using UnityEngine.UI; using UnityEngine.UI;
using UnityExplorer.Core.Unity; using UnityExplorer.Core.Unity;
namespace UnityExplorer.UI.Main.Home.Inspectors namespace UnityExplorer.UI.Inspectors
{ {
public abstract class InspectorBase public abstract class InspectorBase
{ {

View File

@ -9,12 +9,11 @@ using UnityEngine.SceneManagement;
using UnityEngine.UI; using UnityEngine.UI;
using UnityExplorer.Core.Runtime; using UnityExplorer.Core.Runtime;
using UnityExplorer.UI.Main.Home; using UnityExplorer.UI.Main.Home;
using UnityExplorer.UI.Main.Home.Inspectors;
using UnityExplorer.UI.CacheObject; using UnityExplorer.UI.CacheObject;
using UnityExplorer.UI.Main.Home.Inspectors.GameObjects; using UnityExplorer.UI.Inspectors.GameObjects;
using UnityExplorer.UI.Main.Home.Inspectors.Reflection; using UnityExplorer.UI.Inspectors.Reflection;
namespace UnityExplorer.UI.Main.Home namespace UnityExplorer.UI.Inspectors
{ {
public class InspectorManager public class InspectorManager
{ {

View File

@ -9,7 +9,7 @@ using UnityExplorer.Core;
using UnityExplorer.Core.Config; using UnityExplorer.Core.Config;
using UnityExplorer.Core.Runtime; using UnityExplorer.Core.Runtime;
namespace UnityExplorer.UI.Main.Home.Inspectors.Reflection namespace UnityExplorer.UI.Inspectors.Reflection
{ {
public enum MemberScopes public enum MemberScopes
{ {

View File

@ -9,9 +9,11 @@ using UnityExplorer.Core;
using UnityExplorer.Core.Config; using UnityExplorer.Core.Config;
using UnityExplorer.Core.Runtime; using UnityExplorer.Core.Runtime;
using UnityExplorer.UI.CacheObject; using UnityExplorer.UI.CacheObject;
using UnityExplorer.UI.Main;
using UnityExplorer.UI.Main.Home;
using UnityExplorer.UI.Utility; using UnityExplorer.UI.Utility;
namespace UnityExplorer.UI.Main.Home.Inspectors.Reflection namespace UnityExplorer.UI.Inspectors.Reflection
{ {
public class ReflectionInspector : InspectorBase public class ReflectionInspector : InspectorBase
{ {
@ -78,7 +80,7 @@ namespace UnityExplorer.UI.Main.Home.Inspectors.Reflection
if (this is StaticInspector) if (this is StaticInspector)
m_targetType = target as Type; m_targetType = target as Type;
else else
m_targetType = ReflectionUtility.GetType(target); m_targetType = ReflectionUtility.GetActualType(target);
m_targetTypeShortName = SignatureHighlighter.ParseFullSyntax(m_targetType, false); m_targetTypeShortName = SignatureHighlighter.ParseFullSyntax(m_targetType, false);

View File

@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
namespace UnityExplorer.UI.Main.Home.Inspectors.Reflection namespace UnityExplorer.UI.Inspectors.Reflection
{ {
public class StaticInspector : ReflectionInspector public class StaticInspector : ReflectionInspector
{ {

View File

@ -218,32 +218,37 @@ namespace UnityExplorer.UI.InteractiveValues
private IDictionary EnumerateWithReflection() private IDictionary EnumerateWithReflection()
{ {
var valueType = ReflectionUtility.GetType(Value); var valueType = ReflectionUtility.GetActualType(Value);
// get keys and values
var keys = valueType.GetProperty("Keys").GetValue(Value, null);
var values = valueType.GetProperty("Values").GetValue(Value, null);
// create lists to hold them
var keyList = new List<object>(); var keyList = new List<object>();
var valueList = new List<object>(); var valueList = new List<object>();
// store entries with reflection var hashtable = Value.Cast(typeof(Il2CppSystem.Collections.Hashtable)) as Il2CppSystem.Collections.Hashtable;
EnumerateCollection(keys, keyList);
EnumerateCollection(values, valueList);
// make actual mono dictionary if (hashtable != null)
var dict = (IDictionary)Activator.CreateInstance(typeof(Dictionary<,>) {
.MakeGenericType(m_typeOfKeys, m_typeofValues)); 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;
// finally iterate into mono dictionary
for (int i = 0; i < keyList.Count; i++) for (int i = 0; i < keyList.Count; i++)
dict.Add(keyList[i], valueList[i]); dict.Add(keyList[i], valueList[i]);
return dict; return dict;
} }
private void EnumerateCollection(object collection, List<object> list) private void EnumerateCppIDictionary(object collection, List<object> list)
{ {
// invoke GetEnumerator // invoke GetEnumerator
var enumerator = collection.GetType().GetMethod("GetEnumerator").Invoke(collection, null); var enumerator = collection.GetType().GetMethod("GetEnumerator").Invoke(collection, null);
@ -258,6 +263,18 @@ namespace UnityExplorer.UI.InteractiveValues
list.Add(current.GetValue(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 #endif
#endregion #endregion

View File

@ -6,6 +6,7 @@ using System.Reflection;
using System.Text; using System.Text;
using UnityEngine; using UnityEngine;
using UnityEngine.UI; using UnityEngine.UI;
using UnityExplorer.Core;
using UnityExplorer.Core.Config; using UnityExplorer.Core.Config;
using UnityExplorer.Core.Unity; using UnityExplorer.Core.Unity;
using UnityExplorer.UI; using UnityExplorer.UI;
@ -38,11 +39,11 @@ namespace UnityExplorer.UI.InteractiveValues
internal IEnumerable RefIEnumerable; internal IEnumerable RefIEnumerable;
internal IList RefIList; internal IList RefIList;
#if CPP //#if CPP
internal Il2CppSystem.Collections.ICollection CppICollection; // internal object CppICollection;
#else //#else
internal ICollection CppICollection = null; // internal object CppICollection = null;
#endif //#endif
internal readonly Type m_baseEntryType; internal readonly Type m_baseEntryType;
@ -55,13 +56,17 @@ namespace UnityExplorer.UI.InteractiveValues
RefIEnumerable = Value as IEnumerable; RefIEnumerable = Value as IEnumerable;
RefIList = Value as IList; RefIList = Value as IList;
#if CPP //#if CPP
if (Value != null && RefIList == null) // if (Value != null && RefIList == null)
{ // {
try { CppICollection = (Value as Il2CppSystem.Object).TryCast<Il2CppSystem.Collections.ICollection>(); } // try
catch { } // {
} // var type = typeof(Il2CppSystem.Collections.ICollection).MakeGenericType(this.m_baseEntryType);
#endif // CppICollection = (Value as Il2CppSystem.Object).Cast(type);
// }
// catch { }
// }
//#endif
if (m_subContentParent.activeSelf) if (m_subContentParent.activeSelf)
{ {
@ -91,8 +96,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)// || CppICollection != null))
count = RefIList?.Count.ToString() ?? CppICollection.Count.ToString(); count = RefIList.Count.ToString();// ?? CppICollection.Count.ToString();
else if (!m_recacheWanted) else if (!m_recacheWanted)
count = m_entries.Count.ToString(); count = m_entries.Count.ToString();

View File

@ -9,6 +9,7 @@ using UnityExplorer.Core.Unity;
using UnityExplorer.UI; using UnityExplorer.UI;
using UnityExplorer.UI.Utility; using UnityExplorer.UI.Utility;
using UnityExplorer.UI.CacheObject; using UnityExplorer.UI.CacheObject;
using UnityExplorer.Core.Runtime;
namespace UnityExplorer.UI.InteractiveValues namespace UnityExplorer.UI.InteractiveValues
{ {
@ -23,6 +24,14 @@ namespace UnityExplorer.UI.InteractiveValues
public override void OnValueUpdated() public override void OnValueUpdated()
{ {
#if CPP
// 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();
} }
@ -88,10 +97,18 @@ namespace UnityExplorer.UI.InteractiveValues
m_labelLayout.flexibleWidth = 0; m_labelLayout.flexibleWidth = 0;
} }
internal void OnApplyClicked() internal void SetValueFromInput()
{ {
Value = m_valueInput.text; Value = m_valueInput.text;
if (!typeof(string).IsAssignableFrom(Owner.FallbackType))
ReflectionProvider.Instance.BoxStringToType(ref Value, Owner.FallbackType);
Owner.SetValue(); Owner.SetValue();
// revert back to string now
OnValueUpdated();
RefreshUIForValue(); RefreshUIForValue();
} }
@ -162,7 +179,7 @@ namespace UnityExplorer.UI.InteractiveValues
if (Owner.CanWrite) if (Owner.CanWrite)
{ {
var apply = UIFactory.CreateButton(groupObj, "ApplyButton", "Apply", OnApplyClicked, new Color(0.2f, 0.2f, 0.2f)); var apply = UIFactory.CreateButton(groupObj, "ApplyButton", "Apply", SetValueFromInput, new Color(0.2f, 0.2f, 0.2f));
UIFactory.SetLayoutElement(apply.gameObject, minWidth: 50, minHeight: 25, flexibleWidth: 0); UIFactory.SetLayoutElement(apply.gameObject, minWidth: 50, minHeight: 25, flexibleWidth: 0);
} }
else else

View File

@ -12,6 +12,7 @@ using UnityExplorer.UI;
using UnityExplorer.UI.Utility; using UnityExplorer.UI.Utility;
using UnityExplorer.UI.CacheObject; using UnityExplorer.UI.CacheObject;
using UnityExplorer.UI.Main.Home; using UnityExplorer.UI.Main.Home;
using UnityExplorer.UI.Inspectors;
namespace UnityExplorer.UI.InteractiveValues namespace UnityExplorer.UI.InteractiveValues
{ {
@ -66,7 +67,7 @@ namespace UnityExplorer.UI.InteractiveValues
public static InteractiveValue Create(object value, Type fallbackType) public static InteractiveValue Create(object value, Type fallbackType)
{ {
var type = ReflectionUtility.GetType(value) ?? fallbackType; var type = ReflectionUtility.GetActualType(value) ?? fallbackType;
var iType = GetIValueForType(type); var iType = GetIValueForType(type);
return (InteractiveValue)Activator.CreateInstance(iType, new object[] { value, type }); return (InteractiveValue)Activator.CreateInstance(iType, new object[] { value, type });

View File

@ -217,7 +217,6 @@ namespace UnityExplorer.UI.Main
{ {
LogUnity = val; LogUnity = val;
ConfigManager.Log_Unity_Debug.Value = val; ConfigManager.Log_Unity_Debug.Value = val;
ConfigManager.Handler.SaveConfig();
}); });
ConfigManager.Log_Unity_Debug.OnValueChanged += (bool val) => { unityToggle.isOn = val; }; ConfigManager.Log_Unity_Debug.OnValueChanged += (bool val) => { unityToggle.isOn = val; };

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using UnityEngine; using UnityEngine;
using UnityEngine.UI; using UnityEngine.UI;
using UnityExplorer.UI.Inspectors;
namespace UnityExplorer.UI.Main.Home namespace UnityExplorer.UI.Main.Home
{ {

View File

@ -13,6 +13,7 @@ using UnityExplorer.UI.Utility;
using UnityExplorer.UI.Main.Search; using UnityExplorer.UI.Main.Search;
using System.IO; using System.IO;
using UnityExplorer.Core; using UnityExplorer.Core;
using UnityExplorer.UI.Inspectors;
namespace UnityExplorer.UI.Main.Home namespace UnityExplorer.UI.Main.Home
{ {

View File

@ -10,6 +10,7 @@ using UnityExplorer.Core;
using UnityExplorer.UI.Utility; using UnityExplorer.UI.Utility;
using UnityExplorer.Core.Search; using UnityExplorer.Core.Search;
using UnityExplorer.UI.Main.Home; using UnityExplorer.UI.Main.Home;
using UnityExplorer.UI.Inspectors;
namespace UnityExplorer.UI.Main.Search namespace UnityExplorer.UI.Main.Search
{ {
@ -129,7 +130,7 @@ namespace UnityExplorer.UI.Main.Search
if (m_context != SearchContext.StaticClass) if (m_context != SearchContext.StaticClass)
{ {
var name = SignatureHighlighter.ParseFullSyntax(ReflectionUtility.GetType(obj), true); var name = SignatureHighlighter.ParseFullSyntax(ReflectionUtility.GetActualType(obj), true);
if (unityObj && m_context != SearchContext.Singleton) if (unityObj && m_context != SearchContext.Singleton)
{ {

View File

@ -246,6 +246,7 @@
<Compile Include="Core\Search\SceneFilter.cs" /> <Compile Include="Core\Search\SceneFilter.cs" />
<Compile Include="Core\Search\SearchContext.cs" /> <Compile Include="Core\Search\SearchContext.cs" />
<Compile Include="Core\Search\SearchProvider.cs" /> <Compile Include="Core\Search\SearchProvider.cs" />
<Compile Include="Core\TestClass.cs" />
<Compile Include="Core\Unity\UnityHelpers.cs" /> <Compile Include="Core\Unity\UnityHelpers.cs" />
<Compile Include="Loader\BIE\BepInExConfigHandler.cs" /> <Compile Include="Loader\BIE\BepInExConfigHandler.cs" />
<Compile Include="Loader\BIE\ExplorerBepInPlugin.cs" /> <Compile Include="Loader\BIE\ExplorerBepInPlugin.cs" />
@ -286,16 +287,16 @@
<Compile Include="UI\Main\CSConsole\Lexer\SymbolMatch.cs" /> <Compile Include="UI\Main\CSConsole\Lexer\SymbolMatch.cs" />
<Compile Include="UI\Main\DebugConsole.cs" /> <Compile Include="UI\Main\DebugConsole.cs" />
<Compile Include="UI\Main\Home\HomePage.cs" /> <Compile Include="UI\Main\Home\HomePage.cs" />
<Compile Include="UI\Main\Home\InspectorManager.cs" /> <Compile Include="UI\Inspectors\InspectorManager.cs" />
<Compile Include="UI\Main\Home\Inspectors\GameObjects\ChildList.cs" /> <Compile Include="UI\Inspectors\GameObjects\ChildList.cs" />
<Compile Include="UI\Main\Home\Inspectors\GameObjects\ComponentList.cs" /> <Compile Include="UI\Inspectors\GameObjects\ComponentList.cs" />
<Compile Include="UI\Main\Home\Inspectors\GameObjects\GameObjectControls.cs" /> <Compile Include="UI\Inspectors\GameObjects\GameObjectControls.cs" />
<Compile Include="UI\Main\Home\Inspectors\GameObjects\GameObjectInspector.cs" /> <Compile Include="UI\Inspectors\GameObjects\GameObjectInspector.cs" />
<Compile Include="UI\Main\Home\Inspectors\InspectorBase.cs" /> <Compile Include="UI\Inspectors\InspectorBase.cs" />
<Compile Include="UI\Main\Home\Inspectors\Reflection\InstanceInspector.cs" /> <Compile Include="UI\Inspectors\Reflection\InstanceInspector.cs" />
<Compile Include="UI\Main\Home\Inspectors\Reflection\ReflectionInspector.cs" /> <Compile Include="UI\Inspectors\Reflection\ReflectionInspector.cs" />
<Compile Include="UI\Main\Home\Inspectors\Reflection\StaticInspector.cs" /> <Compile Include="UI\Inspectors\Reflection\StaticInspector.cs" />
<Compile Include="UI\Main\Home\InspectUnderMouse.cs" /> <Compile Include="UI\Inspectors\InspectUnderMouse.cs" />
<Compile Include="UI\Main\Home\SceneExplorer.cs" /> <Compile Include="UI\Main\Home\SceneExplorer.cs" />
<Compile Include="UI\Main\MainMenu.cs" /> <Compile Include="UI\Main\MainMenu.cs" />
<Compile Include="UI\Main\Options\OptionsPage.cs" /> <Compile Include="UI\Main\Options\OptionsPage.cs" />