diff --git a/src/Core/Runtime/Il2Cpp/Il2CppReflection.cs b/src/Core/Runtime/Il2Cpp/Il2CppReflection.cs index 1816c17..7a96665 100644 --- a/src/Core/Runtime/Il2Cpp/Il2CppReflection.cs +++ b/src/Core/Runtime/Il2Cpp/Il2CppReflection.cs @@ -154,21 +154,24 @@ namespace UnityExplorer.Core.Runtime.Il2Cpp /// The object, as the type (or a normal C# object) if successful or the input value if not. public static object Il2CppCast(object obj, Type castTo) { - if (!(obj is Il2CppSystem.Object ilObj)) + if (!(obj is Il2CppSystem.Object cppObj)) return obj; if (!Il2CppTypeNotNull(castTo, out IntPtr castToPtr)) 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)) return null; 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); } /// @@ -319,6 +322,14 @@ namespace UnityExplorer.Core.Runtime.Il2Cpp 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 ~~~~~~~~~~~~ // cached il2cpp unbox methods diff --git a/src/Core/Runtime/Mono/MonoReflection.cs b/src/Core/Runtime/Mono/MonoReflection.cs index 7a96427..2c2c3c1 100644 --- a/src/Core/Runtime/Mono/MonoReflection.cs +++ b/src/Core/Runtime/Mono/MonoReflection.cs @@ -27,6 +27,9 @@ namespace UnityExplorer.Core.Runtime.Mono public override string ProcessTypeNameInString(Type type, string theString, ref string typeName) => theString; + + // not necessary + public override void BoxStringToType(ref object _string, Type castTo) { } } } diff --git a/src/Core/Runtime/ReflectionProvider.cs b/src/Core/Runtime/ReflectionProvider.cs index 90b874f..769eb98 100644 --- a/src/Core/Runtime/ReflectionProvider.cs +++ b/src/Core/Runtime/ReflectionProvider.cs @@ -25,5 +25,7 @@ namespace UnityExplorer.Core.Runtime public abstract string ProcessTypeNameInString(Type type, string theString, ref string typeName); public abstract bool LoadModule(string module); + + public abstract void BoxStringToType(ref object _string, Type castTo); } } diff --git a/src/Core/TestClass.cs b/src/Core/TestClass.cs index eebe35a..e0ee4cc 100644 --- a/src/Core/TestClass.cs +++ b/src/Core/TestClass.cs @@ -5,9 +5,14 @@ using System.Text; namespace UnityExplorer { -#if CPP 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() @@ -17,6 +22,6 @@ namespace UnityExplorer testHashset.Add("key2", "itemTwo"); testHashset.Add("key3", "itemThree"); } - } #endif + } } diff --git a/src/ExplorerCore.cs b/src/ExplorerCore.cs index cf65894..3f050dc 100644 --- a/src/ExplorerCore.cs +++ b/src/ExplorerCore.cs @@ -5,6 +5,7 @@ using UnityExplorer.Core.Config; using UnityExplorer.Core.Input; using UnityExplorer.Core.Runtime; using UnityExplorer.UI; +using UnityExplorer.UI.Inspectors; using UnityExplorer.UI.Main; namespace UnityExplorer @@ -12,7 +13,7 @@ namespace UnityExplorer public class ExplorerCore { public const string NAME = "UnityExplorer"; - public const string VERSION = "3.3.5"; + public const string VERSION = "3.3.6"; public const string AUTHOR = "Sinai"; public const string GUID = "com.sinai.unityexplorer"; diff --git a/src/UI/InteractiveValues/InteractiveString.cs b/src/UI/InteractiveValues/InteractiveString.cs index d453c36..81316a6 100644 --- a/src/UI/InteractiveValues/InteractiveString.cs +++ b/src/UI/InteractiveValues/InteractiveString.cs @@ -9,6 +9,7 @@ using UnityExplorer.Core.Unity; using UnityExplorer.UI; using UnityExplorer.UI.Utility; using UnityExplorer.UI.CacheObject; +using UnityExplorer.Core.Runtime; namespace UnityExplorer.UI.InteractiveValues { @@ -27,8 +28,8 @@ namespace UnityExplorer.UI.InteractiveValues // 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 = ((Il2CppSystem.Object)Value).ToString(); + if (!(Value is string) && Value is Il2CppSystem.Object cppobj) + Value = cppobj.ToString(); #endif base.OnValueUpdated(); @@ -96,10 +97,18 @@ namespace UnityExplorer.UI.InteractiveValues m_labelLayout.flexibleWidth = 0; } - internal void OnApplyClicked() + internal void SetValueFromInput() { Value = m_valueInput.text; + + if (!typeof(string).IsAssignableFrom(Owner.FallbackType)) + ReflectionProvider.Instance.BoxStringToType(ref Value, Owner.FallbackType); + Owner.SetValue(); + + // revert back to string now + OnValueUpdated(); + RefreshUIForValue(); } @@ -170,7 +179,7 @@ namespace UnityExplorer.UI.InteractiveValues 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); } else