Compare commits

...

22 Commits
2.0.2 ... 2.1.0

Author SHA1 Message Date
f4ba14cd13 2.1.0
* Fix a bug with Il2Cpp reflection causing TargetInvocationException and other weird issues.
2020-10-30 19:24:42 +11:00
4263cef26a Update ExplorerCore.cs 2020-10-28 20:49:53 +11:00
626e680510 2.0.9
* Fix an issue in mono builds causing a crash
* Fix for games which only contain one scene
* A few small cleanups
2020-10-28 20:49:18 +11:00
7c85969085 Update ExplorerCore.cs 2020-10-24 15:46:11 +11:00
1fce3465c2 Fix bug in ForceUnlockCursor, fix mistake in Reflection Inspector, reduced amount casting with Reflection Inspector 2020-10-24 15:45:37 +11:00
8949e3dc7d Revert "some early steps remaking the GUI with UnityEngine.UI, working in all tested game so far"
This reverts commit 4280a071f6.
2020-10-23 01:48:18 +11:00
4280a071f6 some early steps remaking the GUI with UnityEngine.UI, working in all tested game so far 2020-10-23 01:48:00 +11:00
48ed78ec36 A few small fixes 2020-10-22 21:00:33 +11:00
3c964cfef9 2.0.7
* More unstripping fixes. Explorer now works 100% on a blank Unity project (so should therefore work on any Unity game, regardless of stripping).
* Some cleanups
2020-10-18 21:41:04 +11:00
184b037523 Update ReflectionHelpers.cs 2020-10-18 04:46:50 +11:00
a49a918790 faster il2cpp cast, a few cleanups 2020-10-18 04:39:50 +11:00
e3a58bf675 Update CacheMember.cs 2020-10-17 22:00:53 +11:00
cc29dbda30 Update ReflectionInspector.cs 2020-10-16 20:20:36 +11:00
bc0ad5eab6 refactored icalls using icall helper 2020-10-16 19:40:01 +11:00
bdf86a7448 2.0.6 2020-10-14 20:55:44 +11:00
968546d43c 2.0.6
* Unstrip fixes and cleanups
2020-10-14 20:47:19 +11:00
680556d74e Update README.md 2020-10-12 20:23:21 +11:00
f490203b10 2.0.5
* Added Max Results option to Search (default 5000)
* Fixed a TypeInitializationException which can happen when inspecting some classes with Dictionary members
* Fixed an issue which could prevent Input support from initializating
* Improved and fixed the display of TextAsset objects
* A few other minor fixes
2020-10-12 20:15:41 +11:00
39d9585f1d 2.0.4
* Added ability to see and change the layer of a gameobject from the GameObject inspector more easily, and shows you the actual layer name (where possible).
* Fixed an issue related to the recently-added clickthrough prevention and resize drag
* Fixed write-only properties in the inspector
* A few other minor fixes
2020-10-11 22:57:46 +11:00
2d414e544b Update README.md 2020-10-11 20:52:08 +11:00
513fcaa534 Universal click-through prevention attempt 2020-10-11 20:49:14 +11:00
b41f7211e5 2.0.3
* Fixed a few issues related to the Texture2D support/export.
2020-10-11 20:07:23 +11:00
64 changed files with 4221 additions and 1967 deletions

View File

@ -78,11 +78,16 @@ There is a simple Mod Config for the Explorer. You can access the settings via t
* Whether or not to show the Bitwise Editing helper when inspecting integers * Whether or not to show the Bitwise Editing helper when inspecting integers
`Enable Tab View` (bool) | Default: `true` `Enable Tab View` (bool) | Default: `true`
* Whether or not all inspector windows a grouped into a single window with tabs. * Whether or not all inspector windows a grouped into a single window with tabs.
`Default Output Path` (string) | Default: `Mods\Explorer`
* Where output is generated to, by default (for Texture PNG saving, etc).
## Mouse Control ## Mouse Control
Explorer can force the mouse to be visible and unlocked when the menu is open, if you have enabled "Force Unlock Mouse" (Left-Alt toggle). However, you may also want to prevent the mouse clicking-through onto the game behind Explorer, this is possible but it requires specific patches for that game. Explorer can force the mouse to be visible and unlocked when the menu is open, if you have enabled "Force Unlock Mouse" (Left-Alt toggle). Explorer also attempts to prevent clicking-through onto the game behind the Explorer menu.
If you need more mouse control:
* For VRChat, use [VRCExplorerMouseControl](https://github.com/sinai-dev/VRCExplorerMouseControl) * For VRChat, use [VRCExplorerMouseControl](https://github.com/sinai-dev/VRCExplorerMouseControl)
* For Hellpoint, use [HPExplorerMouseControl](https://github.com/sinai-dev/Hellpoint-Mods/tree/master/HPExplorerMouseControl/HPExplorerMouseControl) * For Hellpoint, use [HPExplorerMouseControl](https://github.com/sinai-dev/Hellpoint-Mods/tree/master/HPExplorerMouseControl/HPExplorerMouseControl)
@ -93,8 +98,9 @@ For example:
using Explorer; using Explorer;
using Harmony; // or 'using HarmonyLib;' for BepInEx using Harmony; // or 'using HarmonyLib;' for BepInEx
// ... // ...
[HarmonyPatch(typeof(MyGame.MenuClass), nameof(MyGame.MenuClass.CursorUpdate)] // You will need to figure out the relevant Class and Method for your game using dnSpy.
public class MenuClass_CursorUpdate [HarmonyPatch(typeof(MyGame.InputManager), nameof(MyGame.InputManager.Update))]
public class InputManager_Update
{ {
[HarmonyPrefix] [HarmonyPrefix]
public static bool Prefix() public static bool Prefix()

View File

@ -2,6 +2,7 @@
using System.Reflection; using System.Reflection;
using Explorer.CacheObject; using Explorer.CacheObject;
using UnityEngine; using UnityEngine;
using Explorer.Helpers;
namespace Explorer namespace Explorer
{ {

View File

@ -3,6 +3,8 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Reflection; using System.Reflection;
using Explorer.UI;
using Explorer.Helpers;
namespace Explorer.CacheObject namespace Explorer.CacheObject
{ {
@ -21,6 +23,15 @@ namespace Explorer.CacheObject
public override void UpdateValue() public override void UpdateValue()
{ {
if (IValue is InteractiveDictionary iDict)
{
if (!iDict.EnsureDictionaryIsSupported())
{
ReflectionException = "Not supported due to TypeInitializationException";
return;
}
}
try try
{ {
var fi = MemInfo as FieldInfo; var fi = MemInfo as FieldInfo;

View File

@ -53,7 +53,7 @@ namespace Explorer.CacheObject
{ {
if (m_arguments.Length < 1) if (m_arguments.Length < 1)
{ {
return null; return new object[0];
} }
var parsedArgs = new List<object>(); var parsedArgs = new List<object>();
@ -123,13 +123,13 @@ namespace Explorer.CacheObject
label = $"<i>[{label} = {this.m_arguments[i].DefaultValue ?? "null"}]</i>"; label = $"<i>[{label} = {this.m_arguments[i].DefaultValue ?? "null"}]</i>";
} }
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUI.skin.label.alignment = TextAnchor.MiddleCenter; GUI.skin.label.alignment = TextAnchor.MiddleCenter;
GUILayout.Label(i.ToString(), new GUILayoutOption[] { GUILayout.Width(15) }); GUILayout.Label(i.ToString(), new GUILayoutOption[] { GUILayout.Width(15) });
GUILayout.Label(label, new GUILayoutOption[] { GUILayout.ExpandWidth(false) }); GUILayout.Label(label, new GUILayoutOption[] { GUIHelper.ExpandWidth(false) });
this.m_argumentInput[i] = GUIUnstrip.TextField(input, new GUILayoutOption[] { GUILayout.ExpandWidth(true) }); this.m_argumentInput[i] = GUIHelper.TextField(input, new GUILayoutOption[] { GUIHelper.ExpandWidth(true) });
GUI.skin.label.alignment = TextAnchor.MiddleLeft; GUI.skin.label.alignment = TextAnchor.MiddleLeft;

View File

@ -4,6 +4,7 @@ using System.Linq;
using System.Reflection; using System.Reflection;
using UnityEngine; using UnityEngine;
using Explorer.UI.Shared; using Explorer.UI.Shared;
using Explorer.Helpers;
namespace Explorer.CacheObject namespace Explorer.CacheObject
{ {
@ -181,14 +182,14 @@ namespace Explorer.CacheObject
} }
var input = this.GenericArgInput[i]; var input = this.GenericArgInput[i];
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUI.skin.label.alignment = TextAnchor.MiddleCenter; GUI.skin.label.alignment = TextAnchor.MiddleCenter;
GUILayout.Label( GUILayout.Label(
$"<color={Syntax.StructGreen}>{this.GenericArgs[i].Name}</color>", $"<color={Syntax.StructGreen}>{this.GenericArgs[i].Name}</color>",
new GUILayoutOption[] { GUILayout.Width(15) } new GUILayoutOption[] { GUILayout.Width(15) }
); );
this.GenericArgInput[i] = GUIUnstrip.TextField(input, new GUILayoutOption[] { GUILayout.Width(150) }); this.GenericArgInput[i] = GUIHelper.TextField(input, new GUILayoutOption[] { GUILayout.Width(150) });
GUI.skin.label.alignment = TextAnchor.MiddleLeft; GUI.skin.label.alignment = TextAnchor.MiddleLeft;
GUILayout.Label(types, new GUILayoutOption[0]); GUILayout.Label(types, new GUILayoutOption[0]);

View File

@ -5,6 +5,7 @@ using System.Reflection;
using UnityEngine; using UnityEngine;
using Explorer.UI; using Explorer.UI;
using Explorer.UI.Shared; using Explorer.UI.Shared;
using Explorer.Helpers;
namespace Explorer.CacheObject namespace Explorer.CacheObject
{ {
@ -37,6 +38,10 @@ namespace Explorer.CacheObject
{ {
interactive = new InteractiveTexture2D(); interactive = new InteractiveTexture2D();
} }
else if (valueType == typeof(Texture))
{
interactive = new InteractiveTexture();
}
else if (valueType == typeof(Sprite)) else if (valueType == typeof(Sprite))
{ {
interactive = new InteractiveSprite(); interactive = new InteractiveSprite();

View File

@ -3,6 +3,8 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Reflection; using System.Reflection;
using Explorer.UI;
using Explorer.Helpers;
namespace Explorer.CacheObject namespace Explorer.CacheObject
{ {
@ -32,14 +34,38 @@ namespace Explorer.CacheObject
return; return;
} }
if (IValue is InteractiveDictionary iDict)
{
if (!iDict.EnsureDictionaryIsSupported())
{
ReflectionException = "Not supported due to TypeInitializationException";
return;
}
}
try try
{ {
var pi = MemInfo as PropertyInfo; var pi = MemInfo as PropertyInfo;
var target = pi.GetAccessors()[0].IsStatic ? null : DeclaringInstance;
IValue.Value = pi.GetValue(target, ParseArguments()); if (pi.CanRead)
{
var target = pi.GetAccessors()[0].IsStatic ? null : DeclaringInstance;
base.UpdateValue(); IValue.Value = pi.GetValue(target, ParseArguments());
base.UpdateValue();
}
else // create a dummy value for Write-Only properties.
{
if (IValue.ValueType == typeof(string))
{
IValue.Value = "";
}
else
{
IValue.Value = Activator.CreateInstance(IValue.ValueType);
}
}
} }
catch (Exception e) catch (Exception e)
{ {

View File

@ -25,7 +25,7 @@
<RootNamespace>Explorer</RootNamespace> <RootNamespace>Explorer</RootNamespace>
<AssemblyName>Explorer</AssemblyName> <AssemblyName>Explorer</AssemblyName>
<!-- Set this to the MelonLoader Il2Cpp Game folder, without the ending '\' character. --> <!-- Set this to the MelonLoader Il2Cpp Game folder, without the ending '\' character. -->
<MLCppGameFolder>D:\Steam\steamapps\common\Hellpoint</MLCppGameFolder> <MLCppGameFolder>D:\Steam\steamapps\common\VRChat</MLCppGameFolder>
<!-- Set this to the MelonLoader Mono Game folder, without the ending '\' character. --> <!-- Set this to the MelonLoader Mono Game folder, without the ending '\' character. -->
<MLMonoGameFolder>D:\Steam\steamapps\common\Outward</MLMonoGameFolder> <MLMonoGameFolder>D:\Steam\steamapps\common\Outward</MLMonoGameFolder>
<!-- Set this to the BepInEx Il2Cpp Game folder, without the ending '\' character. --> <!-- Set this to the BepInEx Il2Cpp Game folder, without the ending '\' character. -->
@ -208,11 +208,13 @@
<Compile Include="CacheObject\CacheMethod.cs" /> <Compile Include="CacheObject\CacheMethod.cs" />
<Compile Include="CacheObject\CacheProperty.cs" /> <Compile Include="CacheObject\CacheProperty.cs" />
<Compile Include="CacheObject\CacheObjectBase.cs" /> <Compile Include="CacheObject\CacheObjectBase.cs" />
<Compile Include="Helpers\Texture2DHelpers.cs" />
<Compile Include="UI\InteractiveValue\InteractiveValue.cs" /> <Compile Include="UI\InteractiveValue\InteractiveValue.cs" />
<Compile Include="UI\InteractiveValue\Object\InteractiveDictionary.cs" /> <Compile Include="UI\InteractiveValue\Object\InteractiveDictionary.cs" />
<Compile Include="UI\InteractiveValue\Object\InteractiveEnumerable.cs" /> <Compile Include="UI\InteractiveValue\Object\InteractiveEnumerable.cs" />
<Compile Include="UI\InteractiveValue\Object\InteractiveGameObject.cs" /> <Compile Include="UI\InteractiveValue\Object\InteractiveGameObject.cs" />
<Compile Include="UI\InteractiveValue\Object\InteractiveSprite.cs" /> <Compile Include="UI\InteractiveValue\Object\InteractiveSprite.cs" />
<Compile Include="UI\InteractiveValue\Object\InteractiveTexture.cs" />
<Compile Include="UI\InteractiveValue\Object\InteractiveTexture2D.cs" /> <Compile Include="UI\InteractiveValue\Object\InteractiveTexture2D.cs" />
<Compile Include="UI\InteractiveValue\Struct\InteractiveQuaternion.cs" /> <Compile Include="UI\InteractiveValue\Struct\InteractiveQuaternion.cs" />
<Compile Include="UI\InteractiveValue\Struct\InteractiveRect.cs" /> <Compile Include="UI\InteractiveValue\Struct\InteractiveRect.cs" />
@ -229,7 +231,7 @@
<Compile Include="Extensions\UnityExtensions.cs" /> <Compile Include="Extensions\UnityExtensions.cs" />
<Compile Include="Helpers\ReflectionHelpers.cs" /> <Compile Include="Helpers\ReflectionHelpers.cs" />
<Compile Include="Helpers\UnityHelpers.cs" /> <Compile Include="Helpers\UnityHelpers.cs" />
<Compile Include="Input\AbstractInput.cs" /> <Compile Include="Input\IAbstractInput.cs" />
<Compile Include="Tests\TestClass.cs" /> <Compile Include="Tests\TestClass.cs" />
<Compile Include="UI\ForceUnlockCursor.cs" /> <Compile Include="UI\ForceUnlockCursor.cs" />
<Compile Include="Input\InputManager.cs" /> <Compile Include="Input\InputManager.cs" />
@ -260,14 +262,19 @@
<Compile Include="UI\WindowBase.cs" /> <Compile Include="UI\WindowBase.cs" />
<Compile Include="UI\WindowManager.cs" /> <Compile Include="UI\WindowManager.cs" />
<Compile Include="Unstrip\ImageConversion\ImageConversionUnstrip.cs" /> <Compile Include="Unstrip\ImageConversion\ImageConversionUnstrip.cs" />
<Compile Include="Unstrip\IMGUI\GUIUtilityUnstrip.cs" />
<Compile Include="Unstrip\IMGUI\TextEditorUnstrip.cs" />
<Compile Include="Helpers\ICallHelper.cs" />
<Compile Include="Unstrip\LayerMask\LayerMaskUnstrip.cs" />
<Compile Include="Unstrip\Resources\ResourcesUnstrip.cs" />
<Compile Include="Unstrip\Scene\SceneUnstrip.cs" /> <Compile Include="Unstrip\Scene\SceneUnstrip.cs" />
<Compile Include="Unstrip\IMGUI\GUIUnstrip.cs" /> <Compile Include="Unstrip\IMGUI\GUIHelper.cs" />
<Compile Include="Unstrip\IMGUI\Internal_LayoutUtility.cs" /> <Compile Include="Unstrip\IMGUI\LayoutUtilityUnstrip.cs" />
<Compile Include="Unstrip\IMGUI\Internal_ScrollViewState.cs" /> <Compile Include="Unstrip\IMGUI\ScrollViewStateUnstrip.cs" />
<Compile Include="Unstrip\IMGUI\Internal_SliderHandler.cs" /> <Compile Include="Unstrip\IMGUI\SliderHandlerUnstrip.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Unstrip\IMGUI\Internal.cs" /> <Compile Include="Unstrip\IMGUI\GUIUnstrip.cs" />
<Compile Include="Unstrip\IMGUI\Internal_SliderState.cs" /> <Compile Include="Unstrip\IMGUI\SliderStateUnstrip.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="ILRepack.targets" /> <None Include="ILRepack.targets" />

View File

@ -1,4 +1,6 @@
using Explorer.Config; using System.Collections;
using System.Linq;
using Explorer.Config;
using Explorer.UI; using Explorer.UI;
using Explorer.UI.Inspectors; using Explorer.UI.Inspectors;
using Explorer.UI.Main; using Explorer.UI.Main;
@ -10,7 +12,7 @@ namespace Explorer
public class ExplorerCore public class ExplorerCore
{ {
public const string NAME = "Explorer " + VERSION + " (" + PLATFORM + ", " + MODLOADER + ")"; public const string NAME = "Explorer " + VERSION + " (" + PLATFORM + ", " + MODLOADER + ")";
public const string VERSION = "2.0.2"; public const string VERSION = "2.1.0";
public const string AUTHOR = "Sinai"; public const string AUTHOR = "Sinai";
public const string GUID = "com.sinai.explorer"; public const string GUID = "com.sinai.explorer";
@ -31,6 +33,12 @@ namespace Explorer
public ExplorerCore() public ExplorerCore()
{ {
if (Instance != null)
{
Log("An instance of Explorer is already active!");
return;
}
Instance = this; Instance = this;
ModConfig.OnLoad(); ModConfig.OnLoad();
@ -87,6 +95,11 @@ namespace Explorer
WindowManager.Instance.OnGUI(); WindowManager.Instance.OnGUI();
InspectUnderMouse.OnGUI(); InspectUnderMouse.OnGUI();
if (!ResizeDrag.IsMouseInResizeArea && WindowManager.IsMouseInWindow)
{
InputManager.ResetInputAxes();
}
GUI.skin = origSkin; GUI.skin = origSkin;
} }
@ -99,27 +112,27 @@ namespace Explorer
public static void Log(object message) public static void Log(object message)
{ {
#if ML #if ML
MelonLoader.MelonLogger.Log(message.ToString()); MelonLoader.MelonLogger.Log(message?.ToString());
#else #else
ExplorerBepInPlugin.Logging?.LogMessage(message.ToString()); ExplorerBepInPlugin.Logging?.LogMessage(message?.ToString());
#endif #endif
} }
public static void LogWarning(object message) public static void LogWarning(object message)
{ {
#if ML #if ML
MelonLoader.MelonLogger.LogWarning(message.ToString()); MelonLoader.MelonLogger.LogWarning(message?.ToString());
#else #else
ExplorerBepInPlugin.Logging?.LogWarning(message.ToString()); ExplorerBepInPlugin.Logging?.LogWarning(message?.ToString());
#endif #endif
} }
public static void LogError(object message) public static void LogError(object message)
{ {
#if ML #if ML
MelonLoader.MelonLogger.LogError(message.ToString()); MelonLoader.MelonLogger.LogError(message?.ToString());
#else #else
ExplorerBepInPlugin.Logging?.LogError(message.ToString()); ExplorerBepInPlugin.Logging?.LogError(message?.ToString());
#endif #endif
} }
} }

View File

@ -2,6 +2,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using Explorer.Helpers;
namespace Explorer namespace Explorer
{ {

View File

@ -0,0 +1,41 @@
#if CPP
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Reflection;
using System.Diagnostics.CodeAnalysis;
namespace Explorer.Helpers
{
[SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "External methods")]
public static class ICallHelper
{
private static readonly Dictionary<string, Delegate> iCallCache = new Dictionary<string, Delegate>();
public static T GetICall<T>(string iCallName) where T : Delegate
{
if (iCallCache.ContainsKey(iCallName))
{
return (T)iCallCache[iCallName];
}
var ptr = il2cpp_resolve_icall(iCallName);
if (ptr == IntPtr.Zero)
{
throw new MissingMethodException($"Could not resolve internal call by name '{iCallName}'!");
}
var iCall = Marshal.GetDelegateForFunctionPointer(ptr, typeof(T));
iCallCache.Add(iCallName, iCall);
return (T)iCall;
}
[DllImport("GameAssembly", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
public static extern IntPtr il2cpp_resolve_icall([MarshalAs(UnmanagedType.LPStr)] string name);
}
}
#endif

View File

@ -5,94 +5,83 @@ using System.IO;
using System.Reflection; using System.Reflection;
using UnityEngine; using UnityEngine;
using BF = System.Reflection.BindingFlags; using BF = System.Reflection.BindingFlags;
using System.Diagnostics.CodeAnalysis;
#if CPP #if CPP
using ILType = Il2CppSystem.Type; using ILType = Il2CppSystem.Type;
using UnhollowerBaseLib; using UnhollowerBaseLib;
using UnhollowerRuntimeLib; using UnhollowerRuntimeLib;
using System.Runtime.InteropServices;
#endif #endif
namespace Explorer namespace Explorer.Helpers
{ {
[SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "External methods")]
public class ReflectionHelpers public class ReflectionHelpers
{ {
public static BF CommonFlags = BF.Public | BF.Instance | BF.NonPublic | BF.Static; public static BF CommonFlags = BF.Public | BF.Instance | BF.NonPublic | BF.Static;
#if CPP #if CPP
public static ILType GameObjectType => Il2CppType.Of<GameObject>(); public static ILType GameObjectType => Il2CppType.Of<GameObject>();
public static ILType TransformType => Il2CppType.Of<Transform>(); public static ILType TransformType => Il2CppType.Of<Transform>();
public static ILType ObjectType => Il2CppType.Of<UnityEngine.Object>(); public static ILType ObjectType => Il2CppType.Of<UnityEngine.Object>();
public static ILType ComponentType => Il2CppType.Of<Component>(); public static ILType ComponentType => Il2CppType.Of<Component>();
public static ILType BehaviourType => Il2CppType.Of<Behaviour>(); public static ILType BehaviourType => Il2CppType.Of<Behaviour>();
#else
public static Type GameObjectType => typeof(GameObject);
public static Type TransformType => typeof(Transform);
public static Type ObjectType => typeof(UnityEngine.Object);
public static Type ComponentType => typeof(Component);
public static Type BehaviourType => typeof(Behaviour);
#endif
private static readonly MethodInfo tryCastMethodInfo = typeof(Il2CppObjectBase).GetMethod("TryCast"); #if CPP
private static readonly Dictionary<Type, MethodInfo> cachedTryCastMethods = new Dictionary<Type, MethodInfo>(); private static readonly Dictionary<Type, IntPtr> ClassPointers = new Dictionary<Type, IntPtr>();
public static object Il2CppCast(object obj, Type castTo) public static object Il2CppCast(object obj, Type castTo)
{ {
if (!typeof(Il2CppSystem.Object).IsAssignableFrom(castTo)) return obj; if (!(obj is Il2CppSystem.Object ilObj))
return obj;
if (!cachedTryCastMethods.ContainsKey(castTo)) if (!typeof(Il2CppSystem.Object).IsAssignableFrom(castTo))
return obj as System.Object;
IntPtr castToPtr;
if (!ClassPointers.ContainsKey(castTo))
{ {
cachedTryCastMethods.Add(castTo, tryCastMethodInfo.MakeGenericMethod(castTo)); castToPtr = (IntPtr)typeof(Il2CppClassPointerStore<>)
} .MakeGenericType(new Type[] { castTo })
.GetField("NativeClassPtr", BF.Public | BF.Static)
.GetValue(null);
return cachedTryCastMethods[castTo].Invoke(obj, null); ClassPointers.Add(castTo, castToPtr);
}
#else
public static Type GameObjectType => typeof(GameObject);
public static Type TransformType => typeof(Transform);
public static Type ObjectType => typeof(UnityEngine.Object);
public static Type ComponentType => typeof(Component);
public static Type BehaviourType => typeof(Behaviour);
#endif
public static bool IsEnumerable(Type t)
{
if (typeof(IEnumerable).IsAssignableFrom(t))
{
return true;
}
#if CPP
if (t.IsGenericType && t.GetGenericTypeDefinition() is Type g)
{
return typeof(Il2CppSystem.Collections.Generic.List<>).IsAssignableFrom(g)
|| typeof(Il2CppSystem.Collections.Generic.IList<>).IsAssignableFrom(g)
|| typeof(Il2CppSystem.Collections.Generic.HashSet<>).IsAssignableFrom(g);
} }
else else
{ {
return typeof(Il2CppSystem.Collections.IList).IsAssignableFrom(t); castToPtr = ClassPointers[castTo];
}
#else
return false;
#endif
}
public static bool IsDictionary(Type t)
{
if (typeof(IDictionary).IsAssignableFrom(t))
{
return true;
} }
#if CPP if (castToPtr == IntPtr.Zero)
if (t.IsGenericType && t.GetGenericTypeDefinition() is Type g) return obj;
{
return typeof(Il2CppSystem.Collections.Generic.Dictionary<,>).IsAssignableFrom(g) var classPtr = il2cpp_object_get_class(ilObj.Pointer);
|| typeof(Il2CppSystem.Collections.Generic.IDictionary<,>).IsAssignableFrom(g);
} if (!il2cpp_class_is_assignable_from(castToPtr, classPtr))
else return obj;
{
return typeof(Il2CppSystem.Collections.IDictionary).IsAssignableFrom(t) if (RuntimeSpecificsStore.IsInjected(castToPtr))
|| typeof(Il2CppSystem.Collections.Hashtable).IsAssignableFrom(t); return UnhollowerBaseLib.Runtime.ClassInjectorBase.GetMonoObjectFromIl2CppPointer(ilObj.Pointer);
}
#else return Activator.CreateInstance(castTo, ilObj.Pointer);
return false;
#endif
} }
[DllImport("GameAssembly", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
public static extern bool il2cpp_class_is_assignable_from(IntPtr klass, IntPtr oklass);
[DllImport("GameAssembly", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
public static extern IntPtr il2cpp_object_get_class(IntPtr obj);
#endif
public static Type GetTypeByName(string fullName) public static Type GetTypeByName(string fullName)
{ {
foreach (var asm in AppDomain.CurrentDomain.GetAssemblies()) foreach (var asm in AppDomain.CurrentDomain.GetAssemblies())
@ -169,48 +158,55 @@ namespace Explorer
return false; return false;
} }
public static bool IsEnumerable(Type t)
{
if (typeof(IEnumerable).IsAssignableFrom(t))
{
return true;
}
#if CPP
if (t.IsGenericType && t.GetGenericTypeDefinition() is Type g)
{
return typeof(Il2CppSystem.Collections.Generic.List<>).IsAssignableFrom(g)
|| typeof(Il2CppSystem.Collections.Generic.IList<>).IsAssignableFrom(g)
|| typeof(Il2CppSystem.Collections.Generic.HashSet<>).IsAssignableFrom(g);
}
else
{
return typeof(Il2CppSystem.Collections.IList).IsAssignableFrom(t);
}
#else
return false;
#endif
}
public static bool IsDictionary(Type t)
{
if (typeof(IDictionary).IsAssignableFrom(t))
{
return true;
}
#if CPP
if (t.IsGenericType && t.GetGenericTypeDefinition() is Type g)
{
return typeof(Il2CppSystem.Collections.Generic.Dictionary<,>).IsAssignableFrom(g)
|| typeof(Il2CppSystem.Collections.Generic.IDictionary<,>).IsAssignableFrom(g);
}
else
{
return typeof(Il2CppSystem.Collections.IDictionary).IsAssignableFrom(t)
|| typeof(Il2CppSystem.Collections.Hashtable).IsAssignableFrom(t);
}
#else
return false;
#endif
}
public static string ExceptionToString(Exception e) public static string ExceptionToString(Exception e)
{ {
#if CPP
if (IsFailedGeneric(e))
{
return "Unable to initialize this type.";
}
else if (IsObjectCollected(e))
{
return "Garbage collected in Il2Cpp.";
}
#endif
return e.GetType() + ", " + e.Message; return e.GetType() + ", " + e.Message;
} }
#if CPP
public static bool IsFailedGeneric(Exception e)
{
return IsExceptionOfType(e, typeof(TargetInvocationException)) && IsExceptionOfType(e, typeof(TypeLoadException));
}
public static bool IsObjectCollected(Exception e)
{
return IsExceptionOfType(e, typeof(ObjectCollectedException));
}
public static bool IsExceptionOfType(Exception e, Type t, bool strict = true, bool checkInner = true)
{
bool isType;
if (strict)
isType = e.GetType() == t;
else
isType = t.IsAssignableFrom(e.GetType());
if (isType) return true;
if (e.InnerException != null && checkInner)
return IsExceptionOfType(e.InnerException, t, strict);
else
return false;
}
#endif
} }
} }

View File

@ -0,0 +1,178 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using System.IO;
using System.Reflection;
#if CPP
using Explorer.Unstrip.ImageConversion;
#endif
namespace Explorer.Helpers
{
public static class Texture2DHelpers
{
#if CPP // If Mono
#else
private static bool isNewEncodeMethod = false;
private static MethodInfo EncodeToPNGMethod => m_encodeToPNGMethod ?? GetEncodeToPNGMethod();
private static MethodInfo m_encodeToPNGMethod;
private static MethodInfo GetEncodeToPNGMethod()
{
if (ReflectionHelpers.GetTypeByName("UnityEngine.ImageConversion") is Type imageConversion)
{
isNewEncodeMethod = true;
return m_encodeToPNGMethod = imageConversion.GetMethod("EncodeToPNG", ReflectionHelpers.CommonFlags);
}
var method = typeof(Texture2D).GetMethod("EncodeToPNG", ReflectionHelpers.CommonFlags);
if (method != null)
{
return m_encodeToPNGMethod = method;
}
ExplorerCore.Log("ERROR: Cannot get any EncodeToPNG method!");
return null;
}
#endif
public static bool IsReadable(this Texture2D tex)
{
try
{
// This will cause an exception if it's not readable.
// Reason for doing it this way is not all Unity versions
// ship with the 'Texture.isReadable' property.
tex.GetPixel(0, 0);
return true;
}
catch
{
return false;
}
}
public static Texture2D Copy(Texture2D orig, Rect rect, bool isDTXnmNormal = false)
{
Color[] pixels;
if (!orig.IsReadable())
{
orig = ForceReadTexture(orig);
}
pixels = orig.GetPixels((int)rect.x, (int)rect.y, (int)rect.width, (int)rect.height);
var _newTex = new Texture2D((int)rect.width, (int)rect.height);
_newTex.SetPixels(pixels);
return _newTex;
}
public static Texture2D ForceReadTexture(Texture2D tex)
{
try
{
var origFilter = tex.filterMode;
tex.filterMode = FilterMode.Point;
var rt = RenderTexture.GetTemporary(tex.width, tex.height, 0, RenderTextureFormat.ARGB32);
rt.filterMode = FilterMode.Point;
RenderTexture.active = rt;
Graphics.Blit(tex, rt);
var _newTex = new Texture2D(tex.width, tex.height, TextureFormat.ARGB32, false);
_newTex.ReadPixels(new Rect(0, 0, tex.width, tex.height), 0, 0);
_newTex.Apply(false, false);
RenderTexture.active = null;
tex.filterMode = origFilter;
return _newTex;
}
catch (Exception e)
{
ExplorerCore.Log("Exception on ForceReadTexture: " + e.ToString());
return default;
}
}
public static void SaveTextureAsPNG(Texture2D tex, string dir, string name, bool isDTXnmNormal = false)
{
if (!Directory.Exists(dir))
{
Directory.CreateDirectory(dir);
}
byte[] data;
var savepath = dir + @"\" + name + ".png";
// Make sure we can EncodeToPNG it.
if (tex.format != TextureFormat.ARGB32 || !tex.IsReadable())
{
tex = ForceReadTexture(tex);
}
if (isDTXnmNormal)
{
tex = DTXnmToRGBA(tex);
tex.Apply(false, false);
}
#if CPP
data = tex.EncodeToPNG();
#else
if (isNewEncodeMethod)
{
data = (byte[])EncodeToPNGMethod.Invoke(null, new object[] { tex });
}
else
{
data = (byte[])EncodeToPNGMethod.Invoke(tex, new object[0]);
}
#endif
if (data == null || data.Length < 1)
{
ExplorerCore.LogWarning("Couldn't get any data for the texture!");
}
else
{
File.WriteAllBytes(savepath, data);
}
}
// Converts DTXnm-format Normal Map to RGBA-format Normal Map.
public static Texture2D DTXnmToRGBA(Texture2D tex)
{
Color[] colors = tex.GetPixels();
for (int i = 0; i < colors.Length; i++)
{
Color c = colors[i];
c.r = c.a * 2 - 1; // red <- alpha
c.g = c.g * 2 - 1; // green is always the same
Vector2 rg = new Vector2(c.r, c.g); //this is the red-green vector
c.b = Mathf.Sqrt(1 - Mathf.Clamp01(Vector2.Dot(rg, rg))); //recalculate the blue channel
colors[i] = new Color(
(c.r * 0.5f) + 0.5f,
(c.g * 0.5f) + 0.25f,
(c.b * 0.5f) + 0.5f
);
}
var newtex = new Texture2D(tex.width, tex.height, TextureFormat.ARGB32, false);
newtex.SetPixels(colors);
return newtex;
}
}
}

View File

@ -1,6 +1,6 @@
using UnityEngine; using UnityEngine;
namespace Explorer namespace Explorer.Helpers
{ {
public class UnityHelpers public class UnityHelpers
{ {

View File

@ -1,21 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
namespace Explorer.Input
{
public abstract class AbstractInput
{
public abstract void Init();
public abstract Vector2 MousePosition { get; }
public abstract bool GetKeyDown(KeyCode key);
public abstract bool GetKey(KeyCode key);
public abstract bool GetMouseButtonDown(int btn);
public abstract bool GetMouseButton(int btn);
}
}

View File

@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
namespace Explorer.Input
{
public interface IAbstractInput
{
void Init();
Vector2 MousePosition { get; }
bool GetKeyDown(KeyCode key);
bool GetKey(KeyCode key);
bool GetMouseButtonDown(int btn);
bool GetMouseButton(int btn);
}
}

View File

@ -2,73 +2,87 @@
using System.Reflection; using System.Reflection;
using UnityEngine; using UnityEngine;
using Explorer.Input; using Explorer.Input;
using Explorer.Helpers;
using System.Diagnostics.CodeAnalysis;
#if CPP #if CPP
using UnhollowerBaseLib; using UnhollowerBaseLib;
#endif #endif
namespace Explorer namespace Explorer
{ {
[SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "Unity style")]
public static class InputManager public static class InputManager
{ {
private static AbstractInput inputModule; private static IAbstractInput m_inputModule;
public static void Init() public static void Init()
{ {
if (InputSystem.TKeyboard != null || TryLoadModule("Unity.InputSystem", InputSystem.TKeyboard)) if (InputSystem.TKeyboard != null || (ReflectionHelpers.LoadModule("Unity.InputSystem") && InputSystem.TKeyboard != null))
{ {
inputModule = new InputSystem(); m_inputModule = new InputSystem();
} }
else if (LegacyInput.TInput != null || TryLoadModule("UnityEngine.InputLegacyModule", LegacyInput.TInput)) else if (LegacyInput.TInput != null || (ReflectionHelpers.LoadModule("UnityEngine.InputLegacyModule") && LegacyInput.TInput != null))
{ {
inputModule = new LegacyInput(); m_inputModule = new LegacyInput();
} }
if (inputModule == null) if (m_inputModule == null)
{ {
ExplorerCore.LogWarning("Could not find any Input module!"); ExplorerCore.LogWarning("Could not find any Input module!");
inputModule = new NoInput(); m_inputModule = new NoInput();
} }
inputModule.Init(); m_inputModule.Init();
bool TryLoadModule(string dll, Type check) => ReflectionHelpers.LoadModule(dll) && check != null;
} }
public static Vector3 MousePosition => inputModule.MousePosition; public static Vector3 MousePosition => m_inputModule.MousePosition;
public static bool GetKeyDown(KeyCode key) => inputModule.GetKeyDown(key); public static bool GetKeyDown(KeyCode key) => m_inputModule.GetKeyDown(key);
public static bool GetKey(KeyCode key) => inputModule.GetKey(key); public static bool GetKey(KeyCode key) => m_inputModule.GetKey(key);
public static bool GetMouseButtonDown(int btn) => inputModule.GetMouseButtonDown(btn); public static bool GetMouseButtonDown(int btn) => m_inputModule.GetMouseButtonDown(btn);
public static bool GetMouseButton(int btn) => inputModule.GetMouseButton(btn); public static bool GetMouseButton(int btn) => m_inputModule.GetMouseButton(btn);
//#if CPP #if CPP
//#pragma warning disable IDE1006 internal delegate void d_ResetInputAxes();
// // public extern static string compositionString { get; } public static void ResetInputAxes() => ICallHelper.GetICall<d_ResetInputAxes>("UnityEngine.Input::ResetInputAxes").Invoke();
#else
public static void ResetInputAxes() => UnityEngine.Input.ResetInputAxes();
#endif
// internal delegate string get_compositionString_delegate(); #if CPP
// internal static get_compositionString_delegate get_compositionString_iCall = // public extern static string compositionString { get; }
// IL2CPP.ResolveICall<get_compositionString_delegate>("UnityEngine.Input::get_compositionString");
// public static string compositionString => get_compositionString_iCall(); internal delegate IntPtr d_get_compositionString();
// // public extern static Vector2 compositionCursorPos { get; set; } public static string compositionString
{
get
{
var iCall = ICallHelper.GetICall<d_get_compositionString>("UnityEngine.Input::get_compositionString");
return IL2CPP.Il2CppStringToManaged(iCall.Invoke());
}
}
// internal delegate Vector2 get_compositionCursorPos_delegate(); // public extern static Vector2 compositionCursorPos { get; set; }
// internal static get_compositionCursorPos_delegate get_compositionCursorPos_iCall =
// IL2CPP.ResolveICall<get_compositionCursorPos_delegate>("UnityEngine.Input::get_compositionCursorPos");
// internal delegate void set_compositionCursorPos_delegate(Vector2 value); internal delegate void d_get_compositionCursorPos(out Vector2 ret);
// internal static set_compositionCursorPos_delegate set_compositionCursorPos_iCall = internal delegate void d_set_compositionCursorPos(ref Vector2 value);
// IL2CPP.ResolveICall<set_compositionCursorPos_delegate>("UnityEngine.Input::set_compositionCursorPos");
// public static Vector2 compositionCursorPos public static Vector2 compositionCursorPos
// { {
// get => get_compositionCursorPos_iCall(); get
// set => set_compositionCursorPos_iCall(value); {
// } var iCall = ICallHelper.GetICall<d_get_compositionCursorPos>("UnityEngine.Input::get_compositionCursorPos_Injected");
iCall.Invoke(out Vector2 ret);
//#pragma warning restore IDE1006 return ret;
//#endif }
set
{
var iCall = ICallHelper.GetICall<d_set_compositionCursorPos>("UnityEngine.Input::set_compositionCursorPos_Injected");
iCall.Invoke(ref value);
}
}
#endif
} }
} }

View File

@ -4,104 +4,105 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using UnityEngine; using UnityEngine;
using Explorer.Helpers;
namespace Explorer.Input namespace Explorer.Input
{ {
public class InputSystem : AbstractInput public class InputSystem : IAbstractInput
{ {
public static Type TKeyboard => _keyboard ?? (_keyboard = ReflectionHelpers.GetTypeByName("UnityEngine.InputSystem.Keyboard")); public static Type TKeyboard => m_tKeyboard ?? (m_tKeyboard = ReflectionHelpers.GetTypeByName("UnityEngine.InputSystem.Keyboard"));
private static Type _keyboard; private static Type m_tKeyboard;
public static Type TMouse => _mouse ?? (_mouse = ReflectionHelpers.GetTypeByName("UnityEngine.InputSystem.Mouse")); public static Type TMouse => m_tMouse ?? (m_tMouse = ReflectionHelpers.GetTypeByName("UnityEngine.InputSystem.Mouse"));
private static Type _mouse; private static Type m_tMouse;
public static Type TKey => _key ?? (_key = ReflectionHelpers.GetTypeByName("UnityEngine.InputSystem.Key")); public static Type TKey => m_tKey ?? (m_tKey = ReflectionHelpers.GetTypeByName("UnityEngine.InputSystem.Key"));
private static Type _key; private static Type m_tKey;
private static PropertyInfo _btnIsPressedProp; private static PropertyInfo m_btnIsPressedProp;
private static PropertyInfo _btnWasPressedProp; private static PropertyInfo m_btnWasPressedProp;
private static object CurrentKeyboard => _currentKeyboard ?? (_currentKeyboard = _kbCurrentProp.GetValue(null, null)); private static object CurrentKeyboard => m_currentKeyboard ?? (m_currentKeyboard = m_kbCurrentProp.GetValue(null, null));
private static object _currentKeyboard; private static object m_currentKeyboard;
private static PropertyInfo _kbCurrentProp; private static PropertyInfo m_kbCurrentProp;
private static PropertyInfo _kbIndexer; private static PropertyInfo m_kbIndexer;
private static object CurrentMouse => _currentMouse ?? (_currentMouse = _mouseCurrentProp.GetValue(null, null)); private static object CurrentMouse => m_currentMouse ?? (m_currentMouse = m_mouseCurrentProp.GetValue(null, null));
private static object _currentMouse; private static object m_currentMouse;
private static PropertyInfo _mouseCurrentProp; private static PropertyInfo m_mouseCurrentProp;
private static object LeftMouseButton => _lmb ?? (_lmb = _leftButtonProp.GetValue(CurrentMouse, null)); private static object LeftMouseButton => m_lmb ?? (m_lmb = m_leftButtonProp.GetValue(CurrentMouse, null));
private static object _lmb; private static object m_lmb;
private static PropertyInfo _leftButtonProp; private static PropertyInfo m_leftButtonProp;
private static object RightMouseButton => _rmb ?? (_rmb = _rightButtonProp.GetValue(CurrentMouse, null)); private static object RightMouseButton => m_rmb ?? (m_rmb = m_rightButtonProp.GetValue(CurrentMouse, null));
private static object _rmb; private static object m_rmb;
private static PropertyInfo _rightButtonProp; private static PropertyInfo m_rightButtonProp;
private static object MousePositionInfo => _pos ?? (_pos = _positionProp.GetValue(CurrentMouse, null)); private static object MousePositionInfo => m_pos ?? (m_pos = m_positionProp.GetValue(CurrentMouse, null));
private static object _pos; private static object m_pos;
private static PropertyInfo _positionProp; private static PropertyInfo m_positionProp;
private static MethodInfo _readVector2InputMethod; private static MethodInfo m_readVector2InputMethod;
public override Vector2 MousePosition => (Vector2)_readVector2InputMethod.Invoke(MousePositionInfo, new object[0]); public Vector2 MousePosition => (Vector2)m_readVector2InputMethod.Invoke(MousePositionInfo, new object[0]);
public override bool GetKeyDown(KeyCode key) public bool GetKeyDown(KeyCode key)
{ {
var parsedKey = Enum.Parse(TKey, key.ToString()); var parsedKey = Enum.Parse(TKey, key.ToString());
var actualKey = _kbIndexer.GetValue(CurrentKeyboard, new object[] { parsedKey }); var actualKey = m_kbIndexer.GetValue(CurrentKeyboard, new object[] { parsedKey });
return (bool)_btnWasPressedProp.GetValue(actualKey, null); return (bool)m_btnWasPressedProp.GetValue(actualKey, null);
} }
public override bool GetKey(KeyCode key) public bool GetKey(KeyCode key)
{ {
var parsed = Enum.Parse(TKey, key.ToString()); var parsed = Enum.Parse(TKey, key.ToString());
var actualKey = _kbIndexer.GetValue(CurrentKeyboard, new object[] { parsed }); var actualKey = m_kbIndexer.GetValue(CurrentKeyboard, new object[] { parsed });
return (bool)_btnIsPressedProp.GetValue(actualKey, null); return (bool)m_btnIsPressedProp.GetValue(actualKey, null);
} }
public override bool GetMouseButtonDown(int btn) public bool GetMouseButtonDown(int btn)
{ {
switch (btn) switch (btn)
{ {
case 0: return (bool)_btnWasPressedProp.GetValue(LeftMouseButton, null); case 0: return (bool)m_btnWasPressedProp.GetValue(LeftMouseButton, null);
case 1: return (bool)_btnWasPressedProp.GetValue(RightMouseButton, null); case 1: return (bool)m_btnWasPressedProp.GetValue(RightMouseButton, null);
// case 2: return (bool)_btnWasPressedProp.GetValue(MiddleMouseButton, null); // case 2: return (bool)_btnWasPressedProp.GetValue(MiddleMouseButton, null);
default: throw new NotImplementedException(); default: throw new NotImplementedException();
} }
} }
public override bool GetMouseButton(int btn) public bool GetMouseButton(int btn)
{ {
switch (btn) switch (btn)
{ {
case 0: return (bool)_btnIsPressedProp.GetValue(LeftMouseButton, null); case 0: return (bool)m_btnIsPressedProp.GetValue(LeftMouseButton, null);
case 1: return (bool)_btnIsPressedProp.GetValue(RightMouseButton, null); case 1: return (bool)m_btnIsPressedProp.GetValue(RightMouseButton, null);
// case 2: return (bool)_btnIsPressedProp.GetValue(MiddleMouseButton, null); // case 2: return (bool)_btnIsPressedProp.GetValue(MiddleMouseButton, null);
default: throw new NotImplementedException(); default: throw new NotImplementedException();
} }
} }
public override void Init() public void Init()
{ {
ExplorerCore.Log("Initializing new InputSystem support..."); ExplorerCore.Log("Initializing new InputSystem support...");
_kbCurrentProp = TKeyboard.GetProperty("current"); m_kbCurrentProp = TKeyboard.GetProperty("current");
_kbIndexer = TKeyboard.GetProperty("Item", new Type[] { TKey }); m_kbIndexer = TKeyboard.GetProperty("Item", new Type[] { TKey });
var btnControl = ReflectionHelpers.GetTypeByName("UnityEngine.InputSystem.Controls.ButtonControl"); var btnControl = ReflectionHelpers.GetTypeByName("UnityEngine.InputSystem.Controls.ButtonControl");
_btnIsPressedProp = btnControl.GetProperty("isPressed"); m_btnIsPressedProp = btnControl.GetProperty("isPressed");
_btnWasPressedProp = btnControl.GetProperty("wasPressedThisFrame"); m_btnWasPressedProp = btnControl.GetProperty("wasPressedThisFrame");
_mouseCurrentProp = TMouse.GetProperty("current"); m_mouseCurrentProp = TMouse.GetProperty("current");
_leftButtonProp = TMouse.GetProperty("leftButton"); m_leftButtonProp = TMouse.GetProperty("leftButton");
_rightButtonProp = TMouse.GetProperty("rightButton"); m_rightButtonProp = TMouse.GetProperty("rightButton");
_positionProp = ReflectionHelpers.GetTypeByName("UnityEngine.InputSystem.Pointer") m_positionProp = ReflectionHelpers.GetTypeByName("UnityEngine.InputSystem.Pointer")
.GetProperty("position"); .GetProperty("position");
_readVector2InputMethod = ReflectionHelpers.GetTypeByName("UnityEngine.InputSystem.InputControl`1") m_readVector2InputMethod = ReflectionHelpers.GetTypeByName("UnityEngine.InputSystem.InputControl`1")
.MakeGenericType(typeof(Vector2)) .MakeGenericType(typeof(Vector2))
.GetMethod("ReadValue"); .GetMethod("ReadValue");
} }

View File

@ -4,39 +4,40 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using UnityEngine; using UnityEngine;
using Explorer.Helpers;
namespace Explorer.Input namespace Explorer.Input
{ {
public class LegacyInput : AbstractInput public class LegacyInput : IAbstractInput
{ {
public static Type TInput => _input ?? (_input = ReflectionHelpers.GetTypeByName("UnityEngine.Input")); public static Type TInput => m_tInput ?? (m_tInput = ReflectionHelpers.GetTypeByName("UnityEngine.Input"));
private static Type _input; private static Type m_tInput;
private static PropertyInfo _mousePositionProp; private static PropertyInfo m_mousePositionProp;
private static MethodInfo _getKeyMethod; private static MethodInfo m_getKeyMethod;
private static MethodInfo _getKeyDownMethod; private static MethodInfo m_getKeyDownMethod;
private static MethodInfo _getMouseButtonMethod; private static MethodInfo m_getMouseButtonMethod;
private static MethodInfo _getMouseButtonDownMethod; private static MethodInfo m_getMouseButtonDownMethod;
public override Vector2 MousePosition => (Vector3)_mousePositionProp.GetValue(null, null); public Vector2 MousePosition => (Vector3)m_mousePositionProp.GetValue(null, null);
public override bool GetKey(KeyCode key) => (bool)_getKeyMethod.Invoke(null, new object[] { key }); public bool GetKey(KeyCode key) => (bool)m_getKeyMethod.Invoke(null, new object[] { key });
public override bool GetKeyDown(KeyCode key) => (bool)_getKeyDownMethod.Invoke(null, new object[] { key }); public bool GetKeyDown(KeyCode key) => (bool)m_getKeyDownMethod.Invoke(null, new object[] { key });
public override bool GetMouseButton(int btn) => (bool)_getMouseButtonMethod.Invoke(null, new object[] { btn }); public bool GetMouseButton(int btn) => (bool)m_getMouseButtonMethod.Invoke(null, new object[] { btn });
public override bool GetMouseButtonDown(int btn) => (bool)_getMouseButtonDownMethod.Invoke(null, new object[] { btn }); public bool GetMouseButtonDown(int btn) => (bool)m_getMouseButtonDownMethod.Invoke(null, new object[] { btn });
public override void Init() public void Init()
{ {
ExplorerCore.Log("Initializing Legacy Input support..."); ExplorerCore.Log("Initializing Legacy Input support...");
_mousePositionProp = TInput.GetProperty("mousePosition"); m_mousePositionProp = TInput.GetProperty("mousePosition");
_getKeyMethod = TInput.GetMethod("GetKey", new Type[] { typeof(KeyCode) }); m_getKeyMethod = TInput.GetMethod("GetKey", new Type[] { typeof(KeyCode) });
_getKeyDownMethod = TInput.GetMethod("GetKeyDown", new Type[] { typeof(KeyCode) }); m_getKeyDownMethod = TInput.GetMethod("GetKeyDown", new Type[] { typeof(KeyCode) });
_getMouseButtonMethod = TInput.GetMethod("GetMouseButton", new Type[] { typeof(int) }); m_getMouseButtonMethod = TInput.GetMethod("GetMouseButton", new Type[] { typeof(int) });
_getMouseButtonDownMethod = TInput.GetMethod("GetMouseButtonDown", new Type[] { typeof(int) }); m_getMouseButtonDownMethod = TInput.GetMethod("GetMouseButtonDown", new Type[] { typeof(int) });
} }
} }
} }

View File

@ -8,18 +8,16 @@ namespace Explorer.Input
{ {
// Just a stub for games where no Input module was able to load at all. // Just a stub for games where no Input module was able to load at all.
public class NoInput : AbstractInput public class NoInput : IAbstractInput
{ {
public override Vector2 MousePosition => Vector2.zero; public Vector2 MousePosition => Vector2.zero;
public override bool GetKey(KeyCode key) => false; public bool GetKey(KeyCode key) => false;
public bool GetKeyDown(KeyCode key) => false;
public override bool GetKeyDown(KeyCode key) => false; public bool GetMouseButton(int btn) => false;
public bool GetMouseButtonDown(int btn) => false;
public override bool GetMouseButton(int btn) => false; public void Init() { }
public override bool GetMouseButtonDown(int btn) => false;
public override void Init() { }
} }
} }

View File

@ -8,6 +8,7 @@ using Explorer.UI.Shared;
#if CPP #if CPP
using UnhollowerBaseLib; using UnhollowerBaseLib;
using UnityEngine.SceneManagement; using UnityEngine.SceneManagement;
using Explorer.Unstrip.ImageConversion;
#endif #endif
namespace Explorer.Tests namespace Explorer.Tests
@ -15,16 +16,13 @@ namespace Explorer.Tests
public static class StaticTestClass public static class StaticTestClass
{ {
public static int StaticProperty => 5; public static int StaticProperty => 5;
public static int StaticField = 69; public static int StaticField = 69;
public static List<string> StaticList = new List<string> public static List<string> StaticList = new List<string>
{ {
"one", "one",
"two", "two",
"three", "three",
}; };
public static void StaticMethod() { } public static void StaticMethod() { }
} }
@ -34,6 +32,14 @@ namespace Explorer.Tests
public static TestClass Instance => m_instance ?? (m_instance = new TestClass()); public static TestClass Instance => m_instance ?? (m_instance = new TestClass());
private static TestClass m_instance; private static TestClass m_instance;
public static bool ReadSetOnlyProperty => m_setOnlyProperty;
public static bool SetOnlyProperty
{
set => m_setOnlyProperty = value;
}
private static bool m_setOnlyProperty;
public Texture2D TestTexture = UIStyles.MakeTex(200, 200, Color.white); public Texture2D TestTexture = UIStyles.MakeTex(200, 200, Color.white);
public static Sprite TestSprite; public static Sprite TestSprite;
@ -41,16 +47,9 @@ namespace Explorer.Tests
public static int StaticField = 5; public static int StaticField = 5;
public int NonStaticField; public int NonStaticField;
#if CPP
public static IntPtr FindICall(string name) => il2cpp_resolve_icall(name);
[DllImport("GameAssembly", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
private static extern IntPtr il2cpp_resolve_icall([MarshalAs(UnmanagedType.LPStr)] string name);
#endif
#if CPP #if CPP
public static Il2CppSystem.Collections.Generic.HashSet<string> ILHashSetTest; public static Il2CppSystem.Collections.Generic.HashSet<string> ILHashSetTest;
public static Il2CppReferenceArray<Il2CppSystem.Object> testRefArray;
#endif #endif
public TestClass() public TestClass()
@ -66,6 +65,16 @@ namespace Explorer.Tests
GameObject.DontDestroyOnLoad(TestTexture); GameObject.DontDestroyOnLoad(TestTexture);
GameObject.DontDestroyOnLoad(TestSprite); GameObject.DontDestroyOnLoad(TestSprite);
testRefArray = new Il2CppReferenceArray<Il2CppSystem.Object>(5);
for (int i = 0; i < 5; i++)
{
testRefArray[i] = "hi " + i;
}
//// test loading a tex from file
//var dataToLoad = System.IO.File.ReadAllBytes(@"Mods\Explorer\Tex_Nemundis_Nebula.png");
//ExplorerCore.Log($"Tex load success: {TestTexture.LoadImage(dataToLoad, false)}");
ILHashSetTest = new Il2CppSystem.Collections.Generic.HashSet<string>(); ILHashSetTest = new Il2CppSystem.Collections.Generic.HashSet<string>();
ILHashSetTest.Add("1"); ILHashSetTest.Add("1");
ILHashSetTest.Add("2"); ILHashSetTest.Add("2");

View File

@ -1,5 +1,7 @@
using System; using System;
using UnityEngine; using UnityEngine;
using Explorer.Helpers;
using BF = System.Reflection.BindingFlags;
#if ML #if ML
using Harmony; using Harmony;
#else #else
@ -17,37 +19,38 @@ namespace Explorer.UI
} }
private static bool m_forceUnlock; private static bool m_forceUnlock;
private static CursorLockMode m_lastLockMode;
private static bool m_lastVisibleState;
private static bool m_currentlySettingCursor = false;
public static bool ShouldForceMouse => ExplorerCore.ShowMenu && Unlock; public static bool ShouldForceMouse => ExplorerCore.ShowMenu && Unlock;
private static Type CursorType => m_cursorType ?? (m_cursorType = ReflectionHelpers.GetTypeByName("UnityEngine.Cursor")); private static CursorLockMode m_lastLockMode;
private static bool m_lastVisibleState;
private static bool m_currentlySettingCursor = false;
private static Type CursorType
=> m_cursorType
?? (m_cursorType = ReflectionHelpers.GetTypeByName("UnityEngine.Cursor"));
private static Type m_cursorType; private static Type m_cursorType;
public static void Init() public static void Init()
{ {
try try
{ {
// Check if Cursor class is loaded
if (CursorType == null) if (CursorType == null)
{ {
ExplorerCore.Log("Trying to manually load Cursor module..."); throw new Exception("Could not find Type 'UnityEngine.Cursor'!");
if (ReflectionHelpers.LoadModule("UnityEngine.CoreModule") && CursorType != null)
{
ExplorerCore.Log("Ok!");
}
else
{
throw new Exception("Could not load UnityEngine.Cursor module!");
}
} }
// Get current cursor state and enable cursor // Get current cursor state and enable cursor
m_lastLockMode = Cursor.lockState; try
m_lastVisibleState = Cursor.visible; {
m_lastLockMode = (CursorLockMode)typeof(Cursor).GetProperty("lockState", BF.Public | BF.Static).GetValue(null, null);
m_lastVisibleState = (bool)typeof(Cursor).GetProperty("visible", BF.Public | BF.Static).GetValue(null, null);
}
catch
{
m_lastLockMode = CursorLockMode.None;
m_lastVisibleState = true;
}
// Setup Harmony Patches // Setup Harmony Patches
TryPatch("lockState", new HarmonyMethod(typeof(ForceUnlockCursor).GetMethod(nameof(Prefix_set_lockState))), true); TryPatch("lockState", new HarmonyMethod(typeof(ForceUnlockCursor).GetMethod(nameof(Prefix_set_lockState))), true);
@ -91,7 +94,8 @@ namespace Explorer.UI
} }
catch (Exception e) catch (Exception e)
{ {
ExplorerCore.Log($"[NON-FATAL] Couldn't patch a method: {e.Message}"); string s = setter ? "set_" : "get_" ;
ExplorerCore.Log($"Unable to patch Cursor.{s}{property}: {e.Message}");
} }
} }

View File

@ -3,6 +3,8 @@ using System.Collections.Generic;
using UnityEngine; using UnityEngine;
using Explorer.UI.Shared; using Explorer.UI.Shared;
using Explorer.UI.Main; using Explorer.UI.Main;
using Explorer.Unstrip.LayerMasks;
using Explorer.Helpers;
#if CPP #if CPP
using UnhollowerRuntimeLib; using UnhollowerRuntimeLib;
#endif #endif
@ -17,6 +19,8 @@ namespace Explorer.UI.Inspectors
public GameObject TargetGO; public GameObject TargetGO;
public bool pendingDestroy;
private static bool m_hideControls; private static bool m_hideControls;
// gui element holders // gui element holders
@ -43,6 +47,8 @@ namespace Explorer.UI.Inspectors
private bool m_autoUpdateTransform; private bool m_autoUpdateTransform;
private bool m_localContext; private bool m_localContext;
private int m_layer;
private readonly List<Component> m_cachedDestroyList = new List<Component>(); private readonly List<Component> m_cachedDestroyList = new List<Component>();
private string m_addComponentInput = ""; private string m_addComponentInput = "";
@ -104,16 +110,16 @@ namespace Explorer.UI.Inspectors
{ {
try try
{ {
if (pendingDestroy) return;
if (Target == null) if (Target == null)
{ {
ExplorerCore.Log("Target is null!"); DestroyOnException(new Exception("Target was destroyed."));
DestroyWindow();
return; return;
} }
if (!TargetGO && !GetObjectAsGameObject()) if (!TargetGO && !GetObjectAsGameObject())
{ {
ExplorerCore.Log("Target was destroyed!"); DestroyOnException(new Exception("Target was destroyed."));
DestroyWindow();
return; return;
} }
@ -132,6 +138,8 @@ namespace Explorer.UI.Inspectors
TargetGO.transform.localScale = m_frozenScale; TargetGO.transform.localScale = m_frozenScale;
} }
m_layer = TargetGO.layer;
// update child objects // update child objects
var childList = new List<Transform>(); var childList = new List<Transform>();
for (int i = 0; i < TargetGO.transform.childCount; i++) for (int i = 0; i < TargetGO.transform.childCount; i++)
@ -162,7 +170,10 @@ namespace Explorer.UI.Inspectors
private void DestroyOnException(Exception e) private void DestroyOnException(Exception e)
{ {
if (pendingDestroy) return;
ExplorerCore.Log($"Exception drawing GameObject Window: {e.GetType()}, {e.Message}"); ExplorerCore.Log($"Exception drawing GameObject Window: {e.GetType()}, {e.Message}");
pendingDestroy = true;
DestroyWindow(); DestroyWindow();
} }
@ -204,6 +215,8 @@ namespace Explorer.UI.Inspectors
public override void WindowFunction(int windowID) public override void WindowFunction(int windowID)
{ {
if (pendingDestroy) return;
try try
{ {
var rect = WindowManager.TabView ? TabViewWindow.Instance.m_rect : this.m_rect; var rect = WindowManager.TabView ? TabViewWindow.Instance.m_rect : this.m_rect;
@ -211,12 +224,12 @@ namespace Explorer.UI.Inspectors
if (!WindowManager.TabView) if (!WindowManager.TabView)
{ {
Header(); Header();
GUIUnstrip.BeginArea(new Rect(5, 25, rect.width - 10, rect.height - 35), GUI.skin.box); GUIHelper.BeginArea(new Rect(5, 25, rect.width - 10, rect.height - 35), GUI.skin.box);
} }
scroll = GUIUnstrip.BeginScrollView(scroll); scroll = GUIHelper.BeginScrollView(scroll);
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUILayout.Label("Scene: <color=cyan>" + (m_scene == "" ? "n/a" : m_scene) + "</color>", new GUILayoutOption[0]); GUILayout.Label("Scene: <color=cyan>" + (m_scene == "" ? "n/a" : m_scene) + "</color>", new GUILayoutOption[0]);
if (m_scene == UnityHelpers.ActiveSceneName) if (m_scene == UnityHelpers.ActiveSceneName)
{ {
@ -232,7 +245,7 @@ namespace Explorer.UI.Inspectors
} }
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUILayout.Label("Path:", new GUILayoutOption[] { GUILayout.Width(50) }); GUILayout.Label("Path:", new GUILayoutOption[] { GUILayout.Width(50) });
string pathlabel = TargetGO.transform.GetGameObjectPath(); string pathlabel = TargetGO.transform.GetGameObjectPath();
if (TargetGO.transform.parent != null) if (TargetGO.transform.parent != null)
@ -242,22 +255,24 @@ namespace Explorer.UI.Inspectors
InspectGameObject(TargetGO.transform.parent); InspectGameObject(TargetGO.transform.parent);
} }
} }
GUIUnstrip.TextArea(pathlabel, new GUILayoutOption[0]); GUIHelper.TextArea(pathlabel, new GUILayoutOption[0]);
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUILayout.Label("Name:", new GUILayoutOption[] { GUILayout.Width(50) }); GUILayout.Label("Name:", new GUILayoutOption[] { GUILayout.Width(50) });
GUIUnstrip.TextArea(m_name, new GUILayoutOption[0]); GUIHelper.TextArea(m_name, new GUILayoutOption[0]);
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
LayerControls();
// --- Horizontal Columns section --- // --- Horizontal Columns section ---
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUIUnstrip.BeginVertical(new GUILayoutOption[] { GUILayout.Width(rect.width / 2 - 17) }); GUIHelper.BeginVertical(new GUILayoutOption[] { GUILayout.Width(rect.width / 2 - 17) });
TransformList(rect); TransformList(rect);
GUILayout.EndVertical(); GUILayout.EndVertical();
GUIUnstrip.BeginVertical(new GUILayoutOption[] { GUILayout.Width(rect.width / 2 - 17) }); GUIHelper.BeginVertical(new GUILayoutOption[] { GUILayout.Width(rect.width / 2 - 17) });
ComponentList(rect); ComponentList(rect);
GUILayout.EndVertical(); GUILayout.EndVertical();
@ -265,13 +280,13 @@ namespace Explorer.UI.Inspectors
GameObjectControls(); GameObjectControls();
GUIUnstrip.EndScrollView(); GUIHelper.EndScrollView();
if (!WindowManager.TabView) if (!WindowManager.TabView)
{ {
m_rect = ResizeDrag.ResizeWindow(rect, windowID); m_rect = ResizeDrag.ResizeWindow(rect, windowID);
GUIUnstrip.EndArea(); GUIHelper.EndArea();
} }
} }
catch (Exception e) catch (Exception e)
@ -280,14 +295,42 @@ namespace Explorer.UI.Inspectors
} }
} }
private void LayerControls()
{
GUIHelper.BeginHorizontal();
GUILayout.Label("Layer:", new GUILayoutOption[] { GUILayout.Width(50) });
if (GUILayout.Button("<", new GUILayoutOption[] { GUILayout.Width(30) }))
{
if (m_layer > 0)
{
m_layer--;
if (TargetGO) TargetGO.layer = m_layer;
}
}
if (GUILayout.Button(">", new GUILayoutOption[] { GUILayout.Width(30) }))
{
if (m_layer < 32)
{
m_layer++;
if (TargetGO) TargetGO.layer = m_layer;
}
}
GUILayout.Label($"{m_layer} (<color=cyan>{LayerMaskUnstrip.LayerToName(m_layer)}</color>)",
new GUILayoutOption[] { GUILayout.Width(200) });
GUILayout.EndHorizontal();
}
private void TransformList(Rect m_rect) private void TransformList(Rect m_rect)
{ {
GUIUnstrip.BeginVertical(GUIContent.none, GUI.skin.box, null); GUIHelper.BeginVertical(GUIContent.none, GUI.skin.box, null);
m_transformScroll = GUIUnstrip.BeginScrollView(m_transformScroll); m_transformScroll = GUIHelper.BeginScrollView(m_transformScroll);
GUILayout.Label("<b><size=15>Children</size></b>", new GUILayoutOption[0]); GUILayout.Label("<b><size=15>Children</size></b>", new GUILayoutOption[0]);
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
ChildPages.DrawLimitInputArea(); ChildPages.DrawLimitInputArea();
if (ChildPages.ItemCount > ChildPages.ItemsPerPage) if (ChildPages.ItemCount > ChildPages.ItemsPerPage)
@ -295,7 +338,7 @@ namespace Explorer.UI.Inspectors
ChildPages.CurrentPageLabel(); ChildPages.CurrentPageLabel();
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
if (GUILayout.Button("< Prev", new GUILayoutOption[] { GUILayout.Width(80) })) if (GUILayout.Button("< Prev", new GUILayoutOption[] { GUILayout.Width(80) }))
{ {
@ -330,17 +373,17 @@ namespace Explorer.UI.Inspectors
GUILayout.Label("<i>None</i>", new GUILayoutOption[0]); GUILayout.Label("<i>None</i>", new GUILayoutOption[0]);
} }
GUIUnstrip.EndScrollView(); GUIHelper.EndScrollView();
GUILayout.EndVertical(); GUILayout.EndVertical();
} }
private void ComponentList(Rect m_rect) private void ComponentList(Rect m_rect)
{ {
GUIUnstrip.BeginVertical(GUIContent.none, GUI.skin.box, null); GUIHelper.BeginVertical(GUIContent.none, GUI.skin.box, null);
m_compScroll = GUIUnstrip.BeginScrollView(m_compScroll); m_compScroll = GUIHelper.BeginScrollView(m_compScroll);
GUILayout.Label("<b><size=15>Components</size></b>", new GUILayoutOption[0]); GUILayout.Label("<b><size=15>Components</size></b>", new GUILayoutOption[0]);
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
CompPages.DrawLimitInputArea(); CompPages.DrawLimitInputArea();
if (CompPages.ItemCount > CompPages.ItemsPerPage) if (CompPages.ItemCount > CompPages.ItemsPerPage)
@ -348,7 +391,7 @@ namespace Explorer.UI.Inspectors
CompPages.CurrentPageLabel(); CompPages.CurrentPageLabel();
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
if (GUILayout.Button("< Prev", new GUILayoutOption[] { GUILayout.Width(80) })) if (GUILayout.Button("< Prev", new GUILayoutOption[] { GUILayout.Width(80) }))
{ {
@ -361,9 +404,9 @@ namespace Explorer.UI.Inspectors
} }
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
var width = m_rect.width / 2 - 135f; var width = m_rect.width / 2 - 135f;
m_addComponentInput = GUIUnstrip.TextField(m_addComponentInput, new GUILayoutOption[] { GUILayout.Width(width) }); m_addComponentInput = GUIHelper.TextField(m_addComponentInput, new GUILayoutOption[] { GUILayout.Width(width) });
if (GUILayout.Button("Add Comp", new GUILayoutOption[0])) if (GUILayout.Button("Add Comp", new GUILayoutOption[0]))
{ {
if (ReflectionHelpers.GetTypeByName(m_addComponentInput) is Type compType) if (ReflectionHelpers.GetTypeByName(m_addComponentInput) is Type compType)
@ -410,7 +453,7 @@ namespace Explorer.UI.Inspectors
#else #else
component.GetType(); component.GetType();
#endif #endif
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
if (ReflectionHelpers.BehaviourType.IsAssignableFrom(type)) if (ReflectionHelpers.BehaviourType.IsAssignableFrom(type))
{ {
#if CPP #if CPP
@ -421,7 +464,7 @@ namespace Explorer.UI.Inspectors
} }
else else
{ {
GUIUnstrip.Space(26); GUIHelper.Space(26);
} }
if (GUILayout.Button("<color=cyan>" + type.Name + "</color>", new GUILayoutOption[] { GUILayout.Width(m_rect.width / 2 - 100) })) if (GUILayout.Button("<color=cyan>" + type.Name + "</color>", new GUILayoutOption[] { GUILayout.Width(m_rect.width / 2 - 100) }))
{ {
@ -445,7 +488,7 @@ namespace Explorer.UI.Inspectors
} }
} }
GUIUnstrip.EndScrollView(); GUIHelper.EndScrollView();
GUILayout.EndVertical(); GUILayout.EndVertical();
} }
@ -477,7 +520,7 @@ namespace Explorer.UI.Inspectors
{ {
if (m_hideControls) if (m_hideControls)
{ {
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUILayout.Label("<b><size=15>GameObject Controls</size></b>", new GUILayoutOption[] { GUILayout.Width(200) }); GUILayout.Label("<b><size=15>GameObject Controls</size></b>", new GUILayoutOption[] { GUILayout.Width(200) });
if (GUILayout.Button("^ Show ^", new GUILayoutOption[] { GUILayout.Width(75) })) if (GUILayout.Button("^ Show ^", new GUILayoutOption[] { GUILayout.Width(75) }))
{ {
@ -488,9 +531,9 @@ namespace Explorer.UI.Inspectors
return; return;
} }
GUIUnstrip.BeginVertical(GUIContent.none, GUI.skin.box, new GUILayoutOption[] { GUILayout.Width(520) }); GUIHelper.BeginVertical(GUIContent.none, GUI.skin.box, new GUILayoutOption[] { GUILayout.Width(520) });
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUILayout.Label("<b><size=15>GameObject Controls</size></b>", new GUILayoutOption[] { GUILayout.Width(200) }); GUILayout.Label("<b><size=15>GameObject Controls</size></b>", new GUILayoutOption[] { GUILayout.Width(200) });
if (GUILayout.Button("v Hide v", new GUILayoutOption[] { GUILayout.Width(75) })) if (GUILayout.Button("v Hide v", new GUILayoutOption[] { GUILayout.Width(75) }))
{ {
@ -498,7 +541,7 @@ namespace Explorer.UI.Inspectors
} }
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
bool m_active = TargetGO.activeSelf; bool m_active = TargetGO.activeSelf;
m_active = GUILayout.Toggle(m_active, (m_active ? "<color=lime>Enabled " : "<color=red>Disabled") + "</color>", m_active = GUILayout.Toggle(m_active, (m_active ? "<color=lime>Enabled " : "<color=red>Disabled") + "</color>",
new GUILayoutOption[] { GUILayout.Width(80) }); new GUILayoutOption[] { GUILayout.Width(80) });
@ -523,9 +566,9 @@ namespace Explorer.UI.Inspectors
} }
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
m_setParentInput = GUIUnstrip.TextField(m_setParentInput, new GUILayoutOption[0]); m_setParentInput = GUIHelper.TextField(m_setParentInput, new GUILayoutOption[0]);
if (GUILayout.Button("Set Parent", new GUILayoutOption[] { GUILayout.Width(80) })) if (GUILayout.Button("Set Parent", new GUILayoutOption[] { GUILayout.Width(80) }))
{ {
if (GameObject.Find(m_setParentInput) is GameObject newparent) if (GameObject.Find(m_setParentInput) is GameObject newparent)
@ -544,13 +587,13 @@ namespace Explorer.UI.Inspectors
} }
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
GUIUnstrip.BeginVertical(GUIContent.none, GUI.skin.box, null); GUIHelper.BeginVertical(GUIContent.none, GUI.skin.box, null);
m_cachedInput[0] = TranslateControl(TranslateType.Position, ref m_translateAmount, false); m_cachedInput[0] = TranslateControl(TranslateType.Position, ref m_translateAmount, false);
m_cachedInput[1] = TranslateControl(TranslateType.Rotation, ref m_rotateAmount, true); m_cachedInput[1] = TranslateControl(TranslateType.Rotation, ref m_rotateAmount, true);
m_cachedInput[2] = TranslateControl(TranslateType.Scale, ref m_scaleAmount, false); m_cachedInput[2] = TranslateControl(TranslateType.Scale, ref m_scaleAmount, false);
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
if (GUILayout.Button("<color=lime>Apply to Transform</color>", new GUILayoutOption[0]) || m_autoApplyTransform) if (GUILayout.Button("<color=lime>Apply to Transform</color>", new GUILayoutOption[0]) || m_autoApplyTransform)
{ {
if (m_localContext) if (m_localContext)
@ -576,7 +619,7 @@ namespace Explorer.UI.Inspectors
} }
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
BoolToggle(ref m_autoApplyTransform, "Auto-apply to Transform?"); BoolToggle(ref m_autoApplyTransform, "Auto-apply to Transform?");
BoolToggle(ref m_autoUpdateTransform, "Auto-update from transform?"); BoolToggle(ref m_autoUpdateTransform, "Auto-update from transform?");
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
@ -638,7 +681,7 @@ namespace Explorer.UI.Inspectors
private Vector3 TranslateControl(TranslateType mode, ref float amount, bool multByTime) private Vector3 TranslateControl(TranslateType mode, ref float amount, bool multByTime)
{ {
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUILayout.Label($"<color=cyan><b>{(m_localContext ? "Local " : "")}{mode}</b></color>:", GUILayout.Label($"<color=cyan><b>{(m_localContext ? "Local " : "")}{mode}</b></color>:",
new GUILayoutOption[] { GUILayout.Width(m_localContext ? 110 : 65) }); new GUILayoutOption[] { GUILayout.Width(m_localContext ? 110 : 65) });
@ -661,7 +704,7 @@ namespace Explorer.UI.Inspectors
Vector3 input = m_cachedInput[(int)mode]; Vector3 input = m_cachedInput[(int)mode];
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUI.skin.label.alignment = TextAnchor.MiddleRight; GUI.skin.label.alignment = TextAnchor.MiddleRight;
GUILayout.Label("<color=cyan>X:</color>", new GUILayoutOption[] { GUILayout.Width(20) }); GUILayout.Label("<color=cyan>X:</color>", new GUILayoutOption[] { GUILayout.Width(20) });
@ -675,7 +718,7 @@ namespace Explorer.UI.Inspectors
GUILayout.Label("+/-:", new GUILayoutOption[] { GUILayout.Width(30) }); GUILayout.Label("+/-:", new GUILayoutOption[] { GUILayout.Width(30) });
var amountInput = amount.ToString("F3"); var amountInput = amount.ToString("F3");
amountInput = GUIUnstrip.TextField(amountInput, new GUILayoutOption[] { GUILayout.Width(60) }); amountInput = GUIHelper.TextField(amountInput, new GUILayoutOption[] { GUILayout.Width(60) });
if (float.TryParse(amountInput, out float f)) if (float.TryParse(amountInput, out float f))
{ {
amount = f; amount = f;
@ -690,16 +733,16 @@ namespace Explorer.UI.Inspectors
private void PlusMinusFloat(ref float f, float amount, bool multByTime) private void PlusMinusFloat(ref float f, float amount, bool multByTime)
{ {
string s = f.ToString("F3"); string s = f.ToString("F3");
s = GUIUnstrip.TextField(s, new GUILayoutOption[] { GUILayout.Width(60) }); s = GUIHelper.TextField(s, new GUILayoutOption[] { GUILayout.Width(60) });
if (float.TryParse(s, out float f2)) if (float.TryParse(s, out float f2))
{ {
f = f2; f = f2;
} }
if (GUIUnstrip.RepeatButton("-", new GUILayoutOption[] { GUILayout.Width(20) })) if (GUIHelper.RepeatButton("-", new GUILayoutOption[] { GUILayout.Width(20) }))
{ {
f -= multByTime ? amount * Time.deltaTime : amount; f -= multByTime ? amount * Time.deltaTime : amount;
} }
if (GUIUnstrip.RepeatButton("+", new GUILayoutOption[] { GUILayout.Width(20) })) if (GUIHelper.RepeatButton("+", new GUILayoutOption[] { GUILayout.Width(20) }))
{ {
f += multByTime ? amount * Time.deltaTime : amount; f += multByTime ? amount * Time.deltaTime : amount;
} }

View File

@ -1,4 +1,5 @@
using UnityEngine; using UnityEngine;
using Explorer.Helpers;
namespace Explorer.UI.Inspectors namespace Explorer.UI.Inspectors
{ {

View File

@ -72,15 +72,15 @@ namespace Explorer.UI.Inspectors
public void DrawInstanceControls(Rect rect) public void DrawInstanceControls(Rect rect)
{ {
if (m_uObj) //if (m_uObj)
{ //{
GUILayout.Label("Name: " + m_uObj.name, new GUILayoutOption[0]); // GUILayout.Label("Name: " + m_uObj.name, new GUILayoutOption[0]);
} //}
GUILayout.EndHorizontal(); //GUILayout.EndHorizontal();
if (m_uObj) if (m_uObj)
{ {
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUILayout.Label("<b>Tools:</b>", new GUILayoutOption[] { GUILayout.Width(80) }); GUILayout.Label("<b>Tools:</b>", new GUILayoutOption[] { GUILayout.Width(80) });
Buttons.InstantiateButton(m_uObj); Buttons.InstantiateButton(m_uObj);
if (m_component && m_component.gameObject is GameObject obj) if (m_component && m_component.gameObject is GameObject obj)
@ -89,13 +89,17 @@ namespace Explorer.UI.Inspectors
GUILayout.Label("GameObject:", new GUILayoutOption[] { GUILayout.Width(135) }); GUILayout.Label("GameObject:", new GUILayoutOption[] { GUILayout.Width(135) });
var charWidth = obj.name.Length * 15; var charWidth = obj.name.Length * 15;
var maxWidth = rect.width - 350; var maxWidth = rect.width - 350;
var labelWidth = charWidth < maxWidth ? charWidth : maxWidth; var btnWidth = charWidth < maxWidth ? charWidth : maxWidth;
if (GUILayout.Button("<color=#00FF00>" + obj.name + "</color>", new GUILayoutOption[] { GUILayout.Width(labelWidth) })) if (GUILayout.Button("<color=#00FF00>" + obj.name + "</color>", new GUILayoutOption[] { GUILayout.Width(btnWidth) }))
{ {
WindowManager.InspectObject(obj, out bool _); WindowManager.InspectObject(obj, out bool _);
} }
GUI.skin.label.alignment = TextAnchor.UpperLeft; GUI.skin.label.alignment = TextAnchor.UpperLeft;
} }
else
{
GUILayout.Label("Name: " + m_uObj.name, new GUILayoutOption[0]);
}
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
} }
} }

View File

@ -7,8 +7,10 @@ using Explorer.UI;
using Explorer.UI.Shared; using Explorer.UI.Shared;
using Explorer.CacheObject; using Explorer.CacheObject;
using Explorer.UI.Inspectors; using Explorer.UI.Inspectors;
using Explorer.Helpers;
#if CPP #if CPP
using UnhollowerBaseLib; using UnhollowerBaseLib;
using UnhollowerRuntimeLib;
#endif #endif
namespace Explorer.UI.Inspectors namespace Explorer.UI.Inspectors
@ -98,20 +100,20 @@ namespace Explorer.UI.Inspectors
if (m_typeFilter != MemberTypes.All && m_typeFilter != holder.MemInfo?.MemberType) if (m_typeFilter != MemberTypes.All && m_typeFilter != holder.MemInfo?.MemberType)
return false; return false;
// check scope filter
if (m_scopeFilter == MemberScopes.Instance)
{
return !holder.IsStatic;
}
else if (m_scopeFilter == MemberScopes.Static)
{
return holder.IsStatic;
}
// hide failed reflection // hide failed reflection
if (!string.IsNullOrEmpty(holder.ReflectionException) && m_hideFailedReflection) if (!string.IsNullOrEmpty(holder.ReflectionException) && m_hideFailedReflection)
return false; return false;
// check scope filter
if (m_scopeFilter == MemberScopes.Instance && holder.IsStatic)
{
return false;
}
else if (m_scopeFilter == MemberScopes.Static && !holder.IsStatic)
{
return false;
}
// see if we should do name search // see if we should do name search
if (m_search == "" || holder.MemInfo == null) if (m_search == "" || holder.MemInfo == null)
return true; return true;
@ -125,7 +127,7 @@ namespace Explorer.UI.Inspectors
private void CacheMembers(Type[] types) private void CacheMembers(Type[] types)
{ {
var list = new List<CacheMember>(); var list = new List<CacheMember>();
var cachedSigs = new List<string>(); var cachedSigs = new HashSet<string>();
foreach (var declaringType in types) foreach (var declaringType in types)
{ {
@ -140,22 +142,18 @@ namespace Explorer.UI.Inspectors
continue; continue;
} }
object target = Target; var target = Target;
string exception = null;
#if CPP #if CPP
if (!IsStaticInspector && target is Il2CppSystem.Object ilObject) try
{ {
try target = target.Il2CppCast(declaringType);
{ }
target = ilObject.Il2CppCast(declaringType); catch //(Exception e)
} {
catch (Exception e) //ExplorerCore.LogWarning("Excepting casting " + target.GetType().FullName + " to " + declaringType.FullName);
{
exception = ReflectionHelpers.ExceptionToString(e);
}
} }
#endif #endif
foreach (var member in infos) foreach (var member in infos)
{ {
try try
@ -165,14 +163,13 @@ namespace Explorer.UI.Inspectors
if (m < 4 || m > 16) if (m < 4 || m > 16)
continue; continue;
var fi = member as FieldInfo;
var pi = member as PropertyInfo; var pi = member as PropertyInfo;
var mi = member as MethodInfo; var mi = member as MethodInfo;
if (IsStaticInspector) if (IsStaticInspector)
{ {
if (fi != null && !fi.IsStatic) continue; if (member is FieldInfo fi && !fi.IsStatic) continue;
else if (pi != null && !pi.GetAccessors()[0].IsStatic) continue; else if (pi != null && !pi.GetAccessors(true)[0].IsStatic) continue;
else if (mi != null && !mi.IsStatic) continue; else if (mi != null && !mi.IsStatic) continue;
} }
@ -208,16 +205,16 @@ namespace Explorer.UI.Inspectors
continue; continue;
} }
//ExplorerCore.Log($"Trying to cache member {sig}...");
try try
{ {
// ExplorerCore.Log($"Trying to cache member {sig}...");
var cached = CacheFactory.GetCacheObject(member, target); var cached = CacheFactory.GetCacheObject(member, target);
if (cached != null) if (cached != null)
{ {
cachedSigs.Add(sig); cachedSigs.Add(sig);
list.Add(cached); list.Add(cached);
cached.ReflectionException = exception;
} }
} }
catch (Exception e) catch (Exception e)
@ -250,34 +247,31 @@ namespace Explorer.UI.Inspectors
if (!WindowManager.TabView) if (!WindowManager.TabView)
{ {
Header(); Header();
GUIUnstrip.BeginArea(new Rect(5, 25, rect.width - 10, rect.height - 35), GUI.skin.box); GUIHelper.BeginArea(new Rect(5, 25, rect.width - 10, rect.height - 35), GUI.skin.box);
} }
var asInstance = this as InstanceInspector; var asInstance = this as InstanceInspector;
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
var labelWidth = (asInstance != null && asInstance.m_uObj) var labelWidth = (asInstance != null && asInstance.m_uObj)
? new GUILayoutOption[] { GUILayout.Width(245f) } ? new GUILayoutOption[] { GUILayout.Width(245f) }
: new GUILayoutOption[0]; : new GUILayoutOption[0];
GUILayout.Label("<b>Type:</b> <color=cyan>" + TargetType.FullName + "</color>", labelWidth); GUILayout.Label("<b>Type:</b> <color=cyan>" + TargetType.FullName + "</color>", labelWidth);
GUILayout.EndHorizontal();
if (asInstance != null) if (asInstance != null)
{ {
asInstance.DrawInstanceControls(rect); asInstance.DrawInstanceControls(rect);
} }
else
{
GUILayout.EndHorizontal();
}
UIStyles.HorizontalLine(Color.grey); UIStyles.HorizontalLine(Color.grey);
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUILayout.Label("<b>Search:</b>", new GUILayoutOption[] { GUILayout.Width(75) }); GUILayout.Label("<b>Search:</b>", new GUILayoutOption[] { GUILayout.Width(75) });
m_search = GUIUnstrip.TextField(m_search, new GUILayoutOption[0]); m_search = GUIHelper.TextField(m_search, new GUILayoutOption[0]);
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUILayout.Label("<b>Filter:</b>", new GUILayoutOption[] { GUILayout.Width(75) }); GUILayout.Label("<b>Filter:</b>", new GUILayoutOption[] { GUILayout.Width(75) });
FilterTypeToggle(MemberTypes.All, "All"); FilterTypeToggle(MemberTypes.All, "All");
FilterTypeToggle(MemberTypes.Property, "Properties"); FilterTypeToggle(MemberTypes.Property, "Properties");
@ -287,7 +281,7 @@ namespace Explorer.UI.Inspectors
if (this is InstanceInspector) if (this is InstanceInspector)
{ {
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUILayout.Label("<b>Scope:</b>", new GUILayoutOption[] { GUILayout.Width(75) }); GUILayout.Label("<b>Scope:</b>", new GUILayoutOption[] { GUILayout.Width(75) });
FilterScopeToggle(MemberScopes.Both, "Both"); FilterScopeToggle(MemberScopes.Both, "Both");
FilterScopeToggle(MemberScopes.Instance, "Instance"); FilterScopeToggle(MemberScopes.Instance, "Instance");
@ -295,7 +289,7 @@ namespace Explorer.UI.Inspectors
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
} }
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUILayout.Label("<b>Values:</b>", new GUILayoutOption[] { GUILayout.Width(75) }); GUILayout.Label("<b>Values:</b>", new GUILayoutOption[] { GUILayout.Width(75) });
if (GUILayout.Button("Update", new GUILayoutOption[] { GUILayout.Width(100) })) if (GUILayout.Button("Update", new GUILayoutOption[] { GUILayout.Width(100) }))
{ {
@ -308,12 +302,12 @@ namespace Explorer.UI.Inspectors
GUI.color = Color.white; GUI.color = Color.white;
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
GUIUnstrip.Space(10); GUIHelper.Space(10);
Pages.ItemCount = m_cachedMembersFiltered.Length; Pages.ItemCount = m_cachedMembersFiltered.Length;
// prev/next page buttons // prev/next page buttons
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
Pages.DrawLimitInputArea(); Pages.DrawLimitInputArea();
@ -335,13 +329,13 @@ namespace Explorer.UI.Inspectors
// ====== BODY ====== // ====== BODY ======
scroll = GUIUnstrip.BeginScrollView(scroll); scroll = GUIHelper.BeginScrollView(scroll);
GUIUnstrip.Space(10); GUIHelper.Space(10);
UIStyles.HorizontalLine(Color.grey); UIStyles.HorizontalLine(Color.grey);
GUIUnstrip.BeginVertical(GUIContent.none, GUI.skin.box, null); GUIHelper.BeginVertical(GUIContent.none, GUI.skin.box, null);
var members = this.m_cachedMembersFiltered; var members = this.m_cachedMembersFiltered;
int start = Pages.CalculateOffsetIndex(); int start = Pages.CalculateOffsetIndex();
@ -350,7 +344,7 @@ namespace Explorer.UI.Inspectors
{ {
var holder = members[j]; var holder = members[j];
GUIUnstrip.BeginHorizontal(new GUILayoutOption[] { GUILayout.Height(25) }); GUIHelper.BeginHorizontal(new GUILayoutOption[] { GUILayout.Height(25) });
try try
{ {
holder.Draw(rect, 180f); holder.Draw(rect, 180f);
@ -368,13 +362,13 @@ namespace Explorer.UI.Inspectors
} }
GUILayout.EndVertical(); GUILayout.EndVertical();
GUIUnstrip.EndScrollView(); GUIHelper.EndScrollView();
if (!WindowManager.TabView) if (!WindowManager.TabView)
{ {
m_rect = ResizeDrag.ResizeWindow(rect, windowID); m_rect = ResizeDrag.ResizeWindow(rect, windowID);
GUIUnstrip.EndArea(); GUIHelper.EndArea();
} }
} }
catch (Exception e) when (e.Message.Contains("in a group with only")) catch (Exception e) when (e.Message.Contains("in a group with only"))

View File

@ -5,6 +5,7 @@ using System.Reflection;
using UnityEngine; using UnityEngine;
using Explorer.UI.Shared; using Explorer.UI.Shared;
using Explorer.CacheObject; using Explorer.CacheObject;
using Explorer.Helpers;
namespace Explorer.UI namespace Explorer.UI
{ {
@ -70,14 +71,14 @@ namespace Explorer.UI
} }
else else
{ {
GUIUnstrip.Space(labelWidth); GUIHelper.Space(labelWidth);
} }
var cacheMethod = OwnerCacheObject as CacheMethod; var cacheMethod = OwnerCacheObject as CacheMethod;
if (cacheMember != null && cacheMember.HasParameters) if (cacheMember != null && cacheMember.HasParameters)
{ {
GUIUnstrip.BeginVertical(new GUILayoutOption[] { GUILayout.ExpandHeight(true) } ); GUIHelper.BeginVertical(new GUILayoutOption[] { GUILayout.ExpandHeight(true) } );
if (cacheMember.m_isEvaluating) if (cacheMember.m_isEvaluating)
{ {
@ -91,7 +92,7 @@ namespace Explorer.UI
cacheMember.DrawArgsInput(); cacheMember.DrawArgsInput();
} }
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
if (GUILayout.Button(EVALUATE_LABEL, new GUILayoutOption[] { GUILayout.Width(70) })) if (GUILayout.Button(EVALUATE_LABEL, new GUILayoutOption[] { GUILayout.Width(70) }))
{ {
if (cacheMethod != null) if (cacheMethod != null)
@ -121,8 +122,8 @@ namespace Explorer.UI
GUILayout.EndVertical(); GUILayout.EndVertical();
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUIUnstrip.Space(labelWidth); GUIHelper.Space(labelWidth);
} }
else if (cacheMethod != null) else if (cacheMethod != null)
{ {
@ -132,8 +133,8 @@ namespace Explorer.UI
} }
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUIUnstrip.Space(labelWidth); GUIHelper.Space(labelWidth);
} }
string typeName = $"<color={Syntax.Class_Instance}>{ValueType.FullName}</color>"; string typeName = $"<color={Syntax.Class_Instance}>{ValueType.FullName}</color>";
@ -198,31 +199,56 @@ namespace Explorer.UI
return m_toStringMethod; return m_toStringMethod;
} }
private string GetButtonLabel() public string GetButtonLabel()
{ {
if (Value == null) return null; if (Value == null) return null;
string label = (string)ToStringMethod?.Invoke(Value, null) ?? Value.ToString(); var valueType = ReflectionHelpers.GetActualType(Value);
var classColor = ValueType.IsAbstract && ValueType.IsSealed string label;
? Syntax.Class_Static
: Syntax.Class_Instance;
string typeLabel = $"<color={classColor}>{ValueType.FullName}</color>"; if (valueType == typeof(TextAsset))
if (Value is UnityEngine.Object)
{ {
label = label.Replace($"({ValueType.FullName})", $"({typeLabel})"); var textAsset = Value as TextAsset;
label = textAsset.text;
if (label.Length > 10)
{
label = $"{label.Substring(0, 10)}...";
}
label = $"\"{label}\" {textAsset.name} (<color={Syntax.Class_Instance}>UnityEngine.TextAsset</color>)";
} }
else else
{ {
if (!label.Contains(ValueType.FullName)) label = (string)ToStringMethod?.Invoke(Value, null) ?? Value.ToString();
if (label.Length > 100)
{ {
label += $" ({typeLabel})"; label = label.Substring(0, 99);
}
var classColor = valueType.IsAbstract && valueType.IsSealed
? Syntax.Class_Static
: Syntax.Class_Instance;
string typeLabel = $"<color={classColor}>{valueType.FullName}</color>";
if (Value is UnityEngine.Object)
{
label = label.Replace($"({valueType.FullName})", $"({typeLabel})");
} }
else else
{ {
label = label.Replace(ValueType.FullName, typeLabel); if (!label.Contains(valueType.FullName))
{
label += $" ({typeLabel})";
}
else
{
label = label.Replace(valueType.FullName, typeLabel);
}
} }
} }

View File

@ -2,14 +2,18 @@
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using UnityEngine; using UnityEngine;
using Explorer.UI.Shared;
using Explorer.CacheObject;
using Explorer.Helpers;
#if CPP #if CPP
using UnhollowerBaseLib; using UnhollowerBaseLib;
#endif #endif
using Explorer.UI.Shared;
using Explorer.CacheObject;
namespace Explorer.UI namespace Explorer.UI
{ {
// TODO: Re-work class using InteractiveEnumerable or maybe InteractiveCollection for the Keys/Value lists.
// Make the keys and values editable.
public class InteractiveDictionary : InteractiveValue, IExpandHeight public class InteractiveDictionary : InteractiveValue, IExpandHeight
{ {
public bool IsExpanded { get; set; } public bool IsExpanded { get; set; }
@ -158,7 +162,7 @@ namespace Explorer.UI
m_cachedValues = values.ToArray(); m_cachedValues = values.ToArray();
} }
private bool EnsureDictionaryIsSupported() public bool EnsureDictionaryIsSupported()
{ {
if (typeof(IDictionary).IsAssignableFrom(ValueType)) if (typeof(IDictionary).IsAssignableFrom(ValueType))
{ {
@ -177,6 +181,11 @@ namespace Explorer.UI
.GetField("NativeClassPtr") .GetField("NativeClassPtr")
.GetValue(null); .GetValue(null);
if (ptr == IntPtr.Zero)
{
return false;
}
return Il2CppSystem.Type.internal_from_handle(IL2CPP.il2cpp_class_get_type(ptr)) is Il2CppSystem.Type; return Il2CppSystem.Type.internal_from_handle(IL2CPP.il2cpp_class_get_type(ptr)) is Il2CppSystem.Type;
} }
} }
@ -228,7 +237,7 @@ namespace Explorer.UI
} }
GUI.skin.button.alignment = TextAnchor.MiddleCenter; GUI.skin.button.alignment = TextAnchor.MiddleCenter;
GUIUnstrip.Space(5); GUIHelper.Space(5);
if (IsExpanded) if (IsExpanded)
{ {
@ -237,9 +246,9 @@ namespace Explorer.UI
if (count > Pages.ItemsPerPage) if (count > Pages.ItemsPerPage)
{ {
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUIUnstrip.Space(whitespace); GUIHelper.Space(whitespace);
Pages.CurrentPageLabel(); Pages.CurrentPageLabel();
@ -255,7 +264,7 @@ namespace Explorer.UI
Pages.DrawLimitInputArea(); Pages.DrawLimitInputArea();
GUIUnstrip.Space(5); GUIHelper.Space(5);
} }
int offset = Pages.CalculateOffsetIndex(); int offset = Pages.CalculateOffsetIndex();
@ -267,7 +276,7 @@ namespace Explorer.UI
//collapsing the BeginHorizontal called from ReflectionWindow.WindowFunction or previous array entry //collapsing the BeginHorizontal called from ReflectionWindow.WindowFunction or previous array entry
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
//GUIUnstrip.Space(whitespace); //GUIUnstrip.Space(whitespace);

View File

@ -6,6 +6,11 @@ using System.Reflection;
using UnityEngine; using UnityEngine;
using Explorer.UI.Shared; using Explorer.UI.Shared;
using Explorer.CacheObject; using Explorer.CacheObject;
using System.Linq;
using Explorer.Helpers;
#if CPP
using UnhollowerBaseLib;
#endif
namespace Explorer.UI namespace Explorer.UI
{ {
@ -293,7 +298,7 @@ namespace Explorer.UI
} }
GUI.skin.button.alignment = TextAnchor.MiddleCenter; GUI.skin.button.alignment = TextAnchor.MiddleCenter;
GUIUnstrip.Space(5); GUIHelper.Space(5);
if (IsExpanded) if (IsExpanded)
{ {
@ -302,9 +307,9 @@ namespace Explorer.UI
if (count > Pages.ItemsPerPage) if (count > Pages.ItemsPerPage)
{ {
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUIUnstrip.Space(whitespace); GUIHelper.Space(whitespace);
Pages.CurrentPageLabel(); Pages.CurrentPageLabel();
@ -320,7 +325,7 @@ namespace Explorer.UI
Pages.DrawLimitInputArea(); Pages.DrawLimitInputArea();
GUIUnstrip.Space(5); GUIHelper.Space(5);
} }
int offset = Pages.CalculateOffsetIndex(); int offset = Pages.CalculateOffsetIndex();
@ -331,9 +336,9 @@ namespace Explorer.UI
//collapsing the BeginHorizontal called from ReflectionWindow.WindowFunction or previous array entry //collapsing the BeginHorizontal called from ReflectionWindow.WindowFunction or previous array entry
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUIUnstrip.Space(whitespace); GUIHelper.Space(whitespace);
if (entry == null || entry.IValue == null) if (entry == null || entry.IValue == null)
{ {

View File

@ -2,27 +2,55 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using Explorer.Helpers;
using UnityEngine; using UnityEngine;
namespace Explorer.UI namespace Explorer.UI
{ {
public class InteractiveSprite : InteractiveTexture2D public class InteractiveSprite : InteractiveTexture2D
{ {
public override void GetTexture2D() private Sprite refSprite;
public override void Init()
{
base.Init();
}
public override void UpdateValue()
{ {
#if CPP #if CPP
if (Value != null && Value.Il2CppCast(typeof(Sprite)) is Sprite sprite) if (Value != null && Value.Il2CppCast(typeof(Sprite)) is Sprite sprite)
{
refSprite = sprite;
}
#else #else
if (Value is Sprite sprite) if (Value is Sprite sprite)
#endif
{ {
currentTex = sprite.texture; refSprite = sprite;
texContent = new GUIContent }
{ #endif
image = currentTex
}; base.UpdateValue();
}
public override void GetTexture2D()
{
if (refSprite && refSprite.texture)
{
currentTex = refSprite.texture;
} }
} }
public override void GetGUIContent()
{
// Check if the Sprite.textureRect is just the entire texture
if (refSprite.textureRect != new Rect(0, 0, currentTex.width, currentTex.height))
{
// It's not, do a sub-copy.
currentTex = Texture2DHelpers.Copy(refSprite.texture, refSprite.textureRect);
}
base.GetGUIContent();
}
} }
} }

View File

@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
namespace Explorer.UI
{
// This class is possibly unnecessary.
// It's just for CacheMembers that have 'Texture' as the value type, but is actually a Texture2D.
public class InteractiveTexture : InteractiveTexture2D
{
public override void GetTexture2D()
{
#if CPP
if (Value != null && Value.Il2CppCast(typeof(Texture2D)) is Texture2D tex)
#else
if (Value is Texture2D tex)
#endif
{
currentTex = tex;
texContent = new GUIContent
{
image = currentTex
};
}
}
}
}

View File

@ -6,6 +6,7 @@ using Explorer.CacheObject;
using Explorer.Config; using Explorer.Config;
using UnityEngine; using UnityEngine;
using System.IO; using System.IO;
using Explorer.Helpers;
#if CPP #if CPP
using Explorer.Unstrip.ImageConversion; using Explorer.Unstrip.ImageConversion;
#endif #endif
@ -42,35 +43,37 @@ namespace Explorer.UI
if (Value is Texture2D tex) if (Value is Texture2D tex)
#endif #endif
{ {
currentTex = tex; currentTex = tex;
texContent = new GUIContent
{
image = currentTex
};
} }
} }
public virtual void GetGUIContent()
{
texContent = new GUIContent
{
image = currentTex
};
}
public override void DrawValue(Rect window, float width) public override void DrawValue(Rect window, float width)
{ {
GUIUnstrip.BeginVertical(); GUIHelper.BeginVertical();
GUIUnstrip.BeginHorizontal(); GUIHelper.BeginHorizontal();
if (currentTex) if (currentTex && !IsExpanded)
{ {
if (!IsExpanded) if (GUILayout.Button("v", new GUILayoutOption[] { GUILayout.Width(25) }))
{ {
if (GUILayout.Button("v", new GUILayoutOption[] { GUILayout.Width(25) })) IsExpanded = true;
{ GetGUIContent();
IsExpanded = true;
}
} }
else }
else if (currentTex)
{
if (GUILayout.Button("^", new GUILayoutOption[] { GUILayout.Width(25) }))
{ {
if (GUILayout.Button("^", new GUILayoutOption[] { GUILayout.Width(25) })) IsExpanded = false;
{
IsExpanded = false;
}
} }
} }
@ -102,39 +105,32 @@ namespace Explorer.UI
private void DrawTextureControls() private void DrawTextureControls()
{ {
GUIUnstrip.BeginHorizontal(); GUIHelper.BeginHorizontal();
GUILayout.Label("Save folder:", new GUILayoutOption[] { GUILayout.Width(80f) }); GUILayout.Label("Save folder:", new GUILayoutOption[] { GUILayout.Width(80f) });
saveFolder = GUIUnstrip.TextField(saveFolder, new GUILayoutOption[0]); saveFolder = GUIHelper.TextField(saveFolder, new GUILayoutOption[0]);
GUIUnstrip.Space(10f); GUIHelper.Space(10f);
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
if (GUILayout.Button("Save to PNG", new GUILayoutOption[] { GUILayout.Width(100f) })) if (GUILayout.Button("Save to PNG", new GUILayoutOption[] { GUILayout.Width(100f) }))
{ {
if (currentTex) var name = RemoveInvalidFilenameChars(currentTex.name ?? "");
if (string.IsNullOrEmpty(name))
{ {
var name = RemoveInvalidFilenameChars(currentTex.name ?? ""); if (OwnerCacheObject is CacheMember cacheMember)
if (string.IsNullOrEmpty(name))
{ {
if (OwnerCacheObject is CacheMember cacheMember) name = cacheMember.MemInfo.Name;
{ }
name = cacheMember.MemInfo.Name; else
} {
else name = "UNTITLED";
{
name = "UNTITLED";
}
} }
SaveTextureAsPNG(currentTex, saveFolder, name, false);
ExplorerCore.Log($@"Saved to {saveFolder}\{name}.png!");
}
else
{
ExplorerCore.Log("Cannot save a null texture!");
} }
Texture2DHelpers.SaveTextureAsPNG(currentTex, saveFolder, name, false);
ExplorerCore.Log($@"Saved to {saveFolder}\{name}.png!");
} }
} }
@ -148,107 +144,6 @@ namespace Explorer.UI
return s; return s;
} }
public static void SaveTextureAsPNG(Texture2D tex, string dir, string name, bool isDTXnmNormal = false)
{
if (!Directory.Exists(dir))
{
Directory.CreateDirectory(dir);
}
byte[] data;
var savepath = dir + @"\" + name + ".png";
try
{
if (isDTXnmNormal)
{
tex = DTXnmToRGBA(tex);
tex.Apply(false, false);
}
data = tex.EncodeToPNG();
if (data == null)
{
ExplorerCore.Log("Couldn't get data with EncodeToPNG (probably ReadOnly?), trying manually...");
throw new Exception();
}
}
catch
{
var origFilter = tex.filterMode;
tex.filterMode = FilterMode.Point;
RenderTexture rt = RenderTexture.GetTemporary(tex.width, tex.height);
rt.filterMode = FilterMode.Point;
RenderTexture.active = rt;
Graphics.Blit(tex, rt);
Texture2D _newTex = new Texture2D(tex.width, tex.height, TextureFormat.RGBA32, false);
_newTex.ReadPixels(new Rect(0, 0, tex.width, tex.height), 0, 0);
if (isDTXnmNormal)
{
_newTex = DTXnmToRGBA(_newTex);
}
_newTex.Apply(false, false);
RenderTexture.active = null;
tex.filterMode = origFilter;
data = _newTex.EncodeToPNG();
//data = _newTex.GetRawTextureData();
}
if (data == null || data.Length < 1)
{
ExplorerCore.LogWarning("Couldn't get any data for the texture!");
}
else
{
#if CPP
// The IL2CPP method will return invalid byte data.
// However, we can just iterate into safe C# byte[] array.
byte[] safeData = new byte[data.Length];
for (int i = 0; i < data.Length; i++)
{
safeData[i] = (byte)data[i]; // not sure if cast is needed
}
File.WriteAllBytes(savepath, safeData);
#else
File.WriteAllBytes(savepath, data);
#endif
}
}
// Converts DTXnm-format Normal Map to RGBA-format Normal Map.
public static Texture2D DTXnmToRGBA(Texture2D tex)
{
Color[] colors = tex.GetPixels();
for (int i = 0; i < colors.Length; i++)
{
Color c = colors[i];
c.r = c.a * 2 - 1; // red <- alpha
c.g = c.g * 2 - 1; // green is always the same
Vector2 rg = new Vector2(c.r, c.g); //this is the red-green vector
c.b = Mathf.Sqrt(1 - Mathf.Clamp01(Vector2.Dot(rg, rg))); //recalculate the blue channel
colors[i] = new Color(
(c.r * 0.5f) + 0.5f,
(c.g * 0.5f) + 0.25f,
(c.b * 0.5f) + 0.5f
);
}
var newtex = new Texture2D(tex.width, tex.height, TextureFormat.RGBA32, false);
newtex.SetPixels(colors);
return newtex;
}
} }
} }

View File

@ -63,40 +63,40 @@ namespace Explorer.UI
var whitespace = CalcWhitespace(window); var whitespace = CalcWhitespace(window);
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUIUnstrip.Space(whitespace); GUIHelper.Space(whitespace);
GUILayout.Label("R:", new GUILayoutOption[] { GUILayout.Width(30) }); GUILayout.Label("R:", new GUILayoutOption[] { GUILayout.Width(30) });
r = GUIUnstrip.TextField(r, new GUILayoutOption[] { GUILayout.Width(120) }); r = GUIHelper.TextField(r, new GUILayoutOption[] { GUILayout.Width(120) });
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUIUnstrip.Space(whitespace); GUIHelper.Space(whitespace);
GUILayout.Label("G:", new GUILayoutOption[] { GUILayout.Width(30) }); GUILayout.Label("G:", new GUILayoutOption[] { GUILayout.Width(30) });
g = GUIUnstrip.TextField(g, new GUILayoutOption[] { GUILayout.Width(120) }); g = GUIHelper.TextField(g, new GUILayoutOption[] { GUILayout.Width(120) });
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUIUnstrip.Space(whitespace); GUIHelper.Space(whitespace);
GUILayout.Label("B:", new GUILayoutOption[] { GUILayout.Width(30) }); GUILayout.Label("B:", new GUILayoutOption[] { GUILayout.Width(30) });
b = GUIUnstrip.TextField(b, new GUILayoutOption[] { GUILayout.Width(120) }); b = GUIHelper.TextField(b, new GUILayoutOption[] { GUILayout.Width(120) });
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUIUnstrip.Space(whitespace); GUIHelper.Space(whitespace);
GUILayout.Label("A:", new GUILayoutOption[] { GUILayout.Width(30) }); GUILayout.Label("A:", new GUILayoutOption[] { GUILayout.Width(30) });
a = GUIUnstrip.TextField(a, new GUILayoutOption[] { GUILayout.Width(120) }); a = GUIHelper.TextField(a, new GUILayoutOption[] { GUILayout.Width(120) });
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
// draw set value button // draw set value button
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUIUnstrip.Space(whitespace); GUIHelper.Space(whitespace);
if (GUILayout.Button("<color=lime>Apply</color>", new GUILayoutOption[] { GUILayout.Width(155) })) if (GUILayout.Button("<color=lime>Apply</color>", new GUILayoutOption[] { GUILayout.Width(155) }))
{ {
SetValueFromInput(); SetValueFromInput();
} }
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
} }
} }

View File

@ -75,23 +75,23 @@ namespace Explorer.UI
for (int i = 0; i < EnumNames.Length; i++) for (int i = 0; i < EnumNames.Length; i++)
{ {
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUIUnstrip.Space(whitespace); GUIHelper.Space(whitespace);
m_enabledFlags[i] = GUILayout.Toggle(m_enabledFlags[i], EnumNames[i], new GUILayoutOption[0]); m_enabledFlags[i] = GUILayout.Toggle(m_enabledFlags[i], EnumNames[i], new GUILayoutOption[0]);
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
} }
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUIUnstrip.Space(whitespace); GUIHelper.Space(whitespace);
if (GUILayout.Button("<color=lime>Apply</color>", new GUILayoutOption[] { GUILayout.Width(155) })) if (GUILayout.Button("<color=lime>Apply</color>", new GUILayoutOption[] { GUILayout.Width(155) }))
{ {
SetFlagsFromInput(); SetFlagsFromInput();
} }
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
} }
} }

View File

@ -80,12 +80,13 @@ namespace Explorer.UI
if (OwnerCacheObject.CanWrite) if (OwnerCacheObject.CanWrite)
{ {
b = GUILayout.Toggle(b, label, new GUILayoutOption[0]); Value = GUILayout.Toggle(b, label, new GUILayoutOption[] { GUILayout.Width(60) });
if (b != (bool)Value) DrawApplyButton();
{ //if (b != (bool)Value)
Value = b; //{
OwnerCacheObject.SetValue(); // Value = b;
} // OwnerCacheObject.SetValue();
//}
} }
else else
{ {
@ -97,27 +98,22 @@ namespace Explorer.UI
// all other non-bool values use TextField // all other non-bool values use TextField
GUIUnstrip.BeginVertical(new GUILayoutOption[0]); GUIHelper.BeginVertical(new GUILayoutOption[0]);
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUILayout.Label("<color=#2df7b2><i>" + ValueType.Name + "</i></color>", new GUILayoutOption[] { GUILayout.Width(50) }); GUILayout.Label("<color=#2df7b2><i>" + ValueType.Name + "</i></color>", new GUILayoutOption[] { GUILayout.Width(50) });
m_valueToString = GUIUnstrip.TextArea(m_valueToString, new GUILayoutOption[] { GUILayout.ExpandWidth(true) }); m_valueToString = GUIHelper.TextArea(m_valueToString, new GUILayoutOption[] { GUIHelper.ExpandWidth(true) });
if (OwnerCacheObject.CanWrite)
{ DrawApplyButton();
if (GUILayout.Button("<color=#00FF00>Apply</color>", new GUILayoutOption[] { GUILayout.Width(60) }))
{
SetValueFromInput();
}
}
if (ModConfig.Instance.Bitwise_Support && m_canBitwiseOperate) if (ModConfig.Instance.Bitwise_Support && m_canBitwiseOperate)
{ {
m_inBitwiseMode = GUILayout.Toggle(m_inBitwiseMode, "Bitwise?", new GUILayoutOption[0]); m_inBitwiseMode = GUILayout.Toggle(m_inBitwiseMode, "Bitwise?", new GUILayoutOption[0]);
} }
GUIUnstrip.Space(10); GUIHelper.Space(10);
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
@ -129,11 +125,29 @@ namespace Explorer.UI
GUILayout.EndVertical(); GUILayout.EndVertical();
} }
private void DrawApplyButton()
{
if (OwnerCacheObject.CanWrite)
{
if (GUILayout.Button("<color=#00FF00>Apply</color>", new GUILayoutOption[] { GUILayout.Width(60) }))
{
if (m_isBool)
{
OwnerCacheObject.SetValue();
}
else
{
SetValueFromInput();
}
}
}
}
private void DrawBitwise() private void DrawBitwise()
{ {
if (OwnerCacheObject.CanWrite) if (OwnerCacheObject.CanWrite)
{ {
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUI.skin.label.alignment = TextAnchor.MiddleRight; GUI.skin.label.alignment = TextAnchor.MiddleRight;
GUILayout.Label("RHS:", new GUILayoutOption[] { GUILayout.Width(35) }); GUILayout.Label("RHS:", new GUILayoutOption[] { GUILayout.Width(35) });
@ -189,14 +203,14 @@ namespace Explorer.UI
} }
} }
m_bitwiseOperatorInput = GUIUnstrip.TextField(m_bitwiseOperatorInput, new GUILayoutOption[] { GUILayout.Width(55) }); m_bitwiseOperatorInput = GUIHelper.TextField(m_bitwiseOperatorInput, new GUILayoutOption[] { GUILayout.Width(55) });
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
} }
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUILayout.Label($"<color=cyan>Binary:</color>", new GUILayoutOption[] { GUILayout.Width(60) }); GUILayout.Label($"<color=cyan>Binary:</color>", new GUILayoutOption[] { GUILayout.Width(60) });
m_binaryInput = GUIUnstrip.TextField(m_binaryInput, new GUILayoutOption[0]); m_binaryInput = GUIHelper.TextField(m_binaryInput, new GUILayoutOption[0]);
if (OwnerCacheObject.CanWrite) if (OwnerCacheObject.CanWrite)
{ {
if (GUILayout.Button("Apply", new GUILayoutOption[0])) if (GUILayout.Button("Apply", new GUILayoutOption[0]))

View File

@ -58,34 +58,34 @@ namespace Explorer.UI
var whitespace = CalcWhitespace(window); var whitespace = CalcWhitespace(window);
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUIUnstrip.Space(whitespace); GUIHelper.Space(whitespace);
GUILayout.Label("X:", new GUILayoutOption[] { GUILayout.Width(30) }); GUILayout.Label("X:", new GUILayoutOption[] { GUILayout.Width(30) });
x = GUIUnstrip.TextField(x, new GUILayoutOption[] { GUILayout.Width(120) }); x = GUIHelper.TextField(x, new GUILayoutOption[] { GUILayout.Width(120) });
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUIUnstrip.Space(whitespace); GUIHelper.Space(whitespace);
GUILayout.Label("Y:", new GUILayoutOption[] { GUILayout.Width(30) }); GUILayout.Label("Y:", new GUILayoutOption[] { GUILayout.Width(30) });
y = GUIUnstrip.TextField(y, new GUILayoutOption[] { GUILayout.Width(120) }); y = GUIHelper.TextField(y, new GUILayoutOption[] { GUILayout.Width(120) });
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUIUnstrip.Space(whitespace); GUIHelper.Space(whitespace);
GUILayout.Label("Z:", new GUILayoutOption[] { GUILayout.Width(30) }); GUILayout.Label("Z:", new GUILayoutOption[] { GUILayout.Width(30) });
z = GUIUnstrip.TextField(z, new GUILayoutOption[] { GUILayout.Width(120) }); z = GUIHelper.TextField(z, new GUILayoutOption[] { GUILayout.Width(120) });
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
// draw set value button // draw set value button
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUIUnstrip.Space(whitespace); GUIHelper.Space(whitespace);
if (GUILayout.Button("<color=lime>Apply</color>", new GUILayoutOption[] { GUILayout.Width(155) })) if (GUILayout.Button("<color=lime>Apply</color>", new GUILayoutOption[] { GUILayout.Width(155) }))
{ {
SetValueFromInput(); SetValueFromInput();
} }
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
} }
} }

View File

@ -60,40 +60,40 @@ namespace Explorer.UI
var whitespace = CalcWhitespace(window); var whitespace = CalcWhitespace(window);
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUIUnstrip.Space(whitespace); GUIHelper.Space(whitespace);
GUILayout.Label("X:", new GUILayoutOption[] { GUILayout.Width(30) }); GUILayout.Label("X:", new GUILayoutOption[] { GUILayout.Width(30) });
x = GUIUnstrip.TextField(x, new GUILayoutOption[] { GUILayout.Width(120) }); x = GUIHelper.TextField(x, new GUILayoutOption[] { GUILayout.Width(120) });
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUIUnstrip.Space(whitespace); GUIHelper.Space(whitespace);
GUILayout.Label("Y:", new GUILayoutOption[] { GUILayout.Width(30) }); GUILayout.Label("Y:", new GUILayoutOption[] { GUILayout.Width(30) });
y = GUIUnstrip.TextField(y, new GUILayoutOption[] { GUILayout.Width(120) }); y = GUIHelper.TextField(y, new GUILayoutOption[] { GUILayout.Width(120) });
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUIUnstrip.Space(whitespace); GUIHelper.Space(whitespace);
GUILayout.Label("W:", new GUILayoutOption[] { GUILayout.Width(30) }); GUILayout.Label("W:", new GUILayoutOption[] { GUILayout.Width(30) });
w = GUIUnstrip.TextField(w, new GUILayoutOption[] { GUILayout.Width(120) }); w = GUIHelper.TextField(w, new GUILayoutOption[] { GUILayout.Width(120) });
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUIUnstrip.Space(whitespace); GUIHelper.Space(whitespace);
GUILayout.Label("H:", new GUILayoutOption[] { GUILayout.Width(30) }); GUILayout.Label("H:", new GUILayoutOption[] { GUILayout.Width(30) });
h = GUIUnstrip.TextField(h, new GUILayoutOption[] { GUILayout.Width(120) }); h = GUIHelper.TextField(h, new GUILayoutOption[] { GUILayout.Width(120) });
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
// draw set value button // draw set value button
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUIUnstrip.Space(whitespace); GUIHelper.Space(whitespace);
if (GUILayout.Button("<color=lime>Apply</color>", new GUILayoutOption[] { GUILayout.Width(155) })) if (GUILayout.Button("<color=lime>Apply</color>", new GUILayoutOption[] { GUILayout.Width(155) }))
{ {
SetValueFromInput(); SetValueFromInput();
} }
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
} }
} }

View File

@ -100,47 +100,47 @@ namespace Explorer.UI
var whitespace = CalcWhitespace(window); var whitespace = CalcWhitespace(window);
// always draw x and y // always draw x and y
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUIUnstrip.Space(whitespace); GUIHelper.Space(whitespace);
GUILayout.Label("X:", new GUILayoutOption[] { GUILayout.Width(30) }); GUILayout.Label("X:", new GUILayoutOption[] { GUILayout.Width(30) });
x = GUIUnstrip.TextField(x, new GUILayoutOption[] { GUILayout.Width(120) }); x = GUIHelper.TextField(x, new GUILayoutOption[] { GUILayout.Width(120) });
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUIUnstrip.Space(whitespace); GUIHelper.Space(whitespace);
GUILayout.Label("Y:", new GUILayoutOption[] { GUILayout.Width(30) }); GUILayout.Label("Y:", new GUILayoutOption[] { GUILayout.Width(30) });
y = GUIUnstrip.TextField(y, new GUILayoutOption[] { GUILayout.Width(120) }); y = GUIHelper.TextField(y, new GUILayoutOption[] { GUILayout.Width(120) });
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
if (VectorSize > 2) if (VectorSize > 2)
{ {
// draw z // draw z
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUIUnstrip.Space(whitespace); GUIHelper.Space(whitespace);
GUILayout.Label("Z:", new GUILayoutOption[] { GUILayout.Width(30) }); GUILayout.Label("Z:", new GUILayoutOption[] { GUILayout.Width(30) });
z = GUIUnstrip.TextField(z, new GUILayoutOption[] { GUILayout.Width(120) }); z = GUIHelper.TextField(z, new GUILayoutOption[] { GUILayout.Width(120) });
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
} }
if (VectorSize > 3) if (VectorSize > 3)
{ {
// draw w // draw w
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUIUnstrip.Space(whitespace); GUIHelper.Space(whitespace);
GUILayout.Label("W:", new GUILayoutOption[] { GUILayout.Width(30) }); GUILayout.Label("W:", new GUILayoutOption[] { GUILayout.Width(30) });
w = GUIUnstrip.TextField(w, new GUILayoutOption[] { GUILayout.Width(120) }); w = GUIHelper.TextField(w, new GUILayoutOption[] { GUILayout.Width(120) });
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
} }
// draw set value button // draw set value button
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUIUnstrip.Space(whitespace); GUIHelper.Space(whitespace);
if (GUILayout.Button("<color=lime>Apply</color>", new GUILayoutOption[] { GUILayout.Width(155) })) if (GUILayout.Button("<color=lime>Apply</color>", new GUILayoutOption[] { GUILayout.Width(155) }))
{ {
SetValueFromInput(); SetValueFromInput();
} }
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
} }
} }

View File

@ -8,6 +8,8 @@ using System.Reflection;
using System.IO; using System.IO;
#if CPP #if CPP
using UnhollowerRuntimeLib; using UnhollowerRuntimeLib;
using TextEditor = Explorer.Unstrip.IMGUI.TextEditorUnstrip;
using Explorer.Unstrip.IMGUI;
#endif #endif
namespace Explorer.UI.Main namespace Explorer.UI.Main
@ -33,7 +35,7 @@ namespace Explorer.UI.Main
public static TextEditor textEditor; public static TextEditor textEditor;
private bool shouldRefocus; private bool shouldRefocus;
public static GUIStyle AutocompleteStyle => autocompleteStyle ?? GetCompletionStyle(); public static GUIStyle AutocompleteStyle => autocompleteStyle ?? GetAutocompleteStyle();
private static GUIStyle autocompleteStyle; private static GUIStyle autocompleteStyle;
public static readonly string[] DefaultUsing = new string[] public static readonly string[] DefaultUsing = new string[]
@ -140,15 +142,15 @@ Help();";
GUILayout.Label("Enter code here as though it is a method body:", new GUILayoutOption[0]); GUILayout.Label("Enter code here as though it is a method body:", new GUILayoutOption[0]);
inputAreaScroll = GUIUnstrip.BeginScrollView( inputAreaScroll = GUIHelper.BeginScrollView(
inputAreaScroll, inputAreaScroll,
new GUILayoutOption[] { GUILayout.Height(250), GUILayout.ExpandHeight(true) } new GUILayoutOption[] { GUILayout.Height(250), GUIHelper.ExpandHeight(true) }
); );
GUI.SetNextControlName(INPUT_CONTROL_NAME); GUI.SetNextControlName(INPUT_CONTROL_NAME);
m_input = GUIUnstrip.TextArea(m_input, new GUILayoutOption[] { GUILayout.ExpandHeight(true) }); m_input = GUIHelper.TextArea(m_input, new GUILayoutOption[] { GUIHelper.ExpandHeight(true) });
GUIUnstrip.EndScrollView(); GUIHelper.EndScrollView();
// EXECUTE BUTTON // EXECUTE BUTTON
@ -179,7 +181,7 @@ Help();";
// SUGGESTIONS // SUGGESTIONS
if (AutoCompletes.Count > 0) if (AutoCompletes.Count > 0)
{ {
autocompleteScroll = GUIUnstrip.BeginScrollView(autocompleteScroll, new GUILayoutOption[] { GUILayout.Height(150) }); autocompleteScroll = GUIHelper.BeginScrollView(autocompleteScroll, new GUILayoutOption[] { GUILayout.Height(150) });
var origSkin = GUI.skin.button; var origSkin = GUI.skin.button;
GUI.skin.button = AutocompleteStyle; GUI.skin.button = AutocompleteStyle;
@ -196,7 +198,7 @@ Help();";
GUI.skin.button = origSkin; GUI.skin.button = origSkin;
GUIUnstrip.EndScrollView(); GUIHelper.EndScrollView();
} }
if (shouldRefocus) if (shouldRefocus)
@ -209,9 +211,9 @@ Help();";
GUILayout.Label("<b>Using directives:</b>", new GUILayoutOption[0]); GUILayout.Label("<b>Using directives:</b>", new GUILayoutOption[0]);
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUILayout.Label("Add namespace:", new GUILayoutOption[] { GUILayout.Width(105) }); GUILayout.Label("Add namespace:", new GUILayoutOption[] { GUILayout.Width(105) });
m_usingInput = GUIUnstrip.TextField(m_usingInput, new GUILayoutOption[] { GUILayout.Width(150) }); m_usingInput = GUIHelper.TextField(m_usingInput, new GUILayoutOption[] { GUILayout.Width(150) });
if (GUILayout.Button("<b><color=lime>Add</color></b>", new GUILayoutOption[] { GUILayout.Width(120) })) if (GUILayout.Button("<b><color=lime>Add</color></b>", new GUILayoutOption[] { GUILayout.Width(120) }))
{ {
AddUsing(m_usingInput); AddUsing(m_usingInput);
@ -245,7 +247,8 @@ Help();";
#endif #endif
#if CPP #if CPP
textEditor = GUIUtility.GetStateObject(Il2CppType.Of<TextEditor>(), GUIUtility.keyboardControl).TryCast<TextEditor>(); //textEditor = GUIUtility.GetStateObject(Il2CppType.Of<TextEditor>(), GUIUtility.keyboardControl).TryCast<TextEditor>();
textEditor = (TextEditor)GUIUtilityUnstrip.GetMonoStateObject(typeof(TextEditor), GUIUtility.keyboardControl);
#else #else
textEditor = (TextEditor)GUIUtility.GetStateObject(typeof(TextEditor), GUIUtility.keyboardControl); textEditor = (TextEditor)GUIUtility.GetStateObject(typeof(TextEditor), GUIUtility.keyboardControl);
#endif #endif
@ -342,19 +345,21 @@ Help();";
} }
// Credit ManlyMarco // Credit ManlyMarco
private static GUIStyle GetCompletionStyle() private static GUIStyle GetAutocompleteStyle()
{ {
return autocompleteStyle = new GUIStyle(GUI.skin.button) var style = new GUIStyle
{ {
border = new RectOffset(0, 0, 0, 0), border = new RectOffset(),
margin = new RectOffset(0, 0, 0, 0), margin = new RectOffset(),
padding = new RectOffset(0, 0, 0, 0), padding = new RectOffset(),
hover = { background = Texture2D.whiteTexture, textColor = Color.black }, hover = { background = Texture2D.whiteTexture, textColor = Color.black },
normal = { background = null }, normal = { background = null },
focused = { background = Texture2D.whiteTexture, textColor = Color.black }, focused = { background = Texture2D.whiteTexture, textColor = Color.black },
active = { background = Texture2D.whiteTexture, textColor = Color.black }, active = { background = Texture2D.whiteTexture, textColor = Color.black },
alignment = TextAnchor.MiddleLeft, alignment = TextAnchor.MiddleLeft
}; };
return autocompleteStyle = style;
} }
private class VoidType private class VoidType

View File

@ -56,34 +56,44 @@ namespace Explorer.UI.Main
GUILayout.Label("<color=orange><size=16><b>Options</b></size></color>", new GUILayoutOption[0]); GUILayout.Label("<color=orange><size=16><b>Options</b></size></color>", new GUILayoutOption[0]);
GUI.skin.label.alignment = TextAnchor.MiddleLeft; GUI.skin.label.alignment = TextAnchor.MiddleLeft;
GUIUnstrip.BeginVertical(GUIContent.none, GUI.skin.box, new GUILayoutOption[0]); GUIHelper.BeginVertical(GUIContent.none, GUI.skin.box, new GUILayoutOption[0]);
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUILayout.Label($"Menu Toggle Key:", new GUILayoutOption[] { GUILayout.Width(215f) }); GUILayout.Label($"Menu Toggle Key:", new GUILayoutOption[] { GUILayout.Width(215f) });
toggleKeyInput.IValue.DrawValue(MainMenu.MainRect, MainMenu.MainRect.width - 215f); toggleKeyInput.IValue.DrawValue(MainMenu.MainRect, MainMenu.MainRect.width - 215f);
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); UIStyles.HorizontalLine(Color.black, true);
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUILayout.Label($"Default Window Size:", new GUILayoutOption[] { GUILayout.Width(215f) }); GUILayout.Label($"Default Window Size:", new GUILayoutOption[] { GUILayout.Width(215f) });
defaultSizeInput.IValue.DrawValue(MainMenu.MainRect, MainMenu.MainRect.width - 215f); defaultSizeInput.IValue.DrawValue(MainMenu.MainRect, MainMenu.MainRect.width - 215f);
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); UIStyles.HorizontalLine(Color.black, true);
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUILayout.Label($"Default Items per Page:", new GUILayoutOption[] { GUILayout.Width(215f) }); GUILayout.Label($"Default Items per Page:", new GUILayoutOption[] { GUILayout.Width(215f) });
defaultPageLimitInput.IValue.DrawValue(MainMenu.MainRect, MainMenu.MainRect.width - 215f); defaultPageLimitInput.IValue.DrawValue(MainMenu.MainRect, MainMenu.MainRect.width - 215f);
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); UIStyles.HorizontalLine(Color.black, true);
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUILayout.Label($"Enable Bitwise Editing:", new GUILayoutOption[] { GUILayout.Width(215f) }); GUILayout.Label($"Enable Bitwise Editing:", new GUILayoutOption[] { GUILayout.Width(215f) });
bitwiseSupportInput.IValue.DrawValue(MainMenu.MainRect, MainMenu.MainRect.width - 215f); bitwiseSupportInput.IValue.DrawValue(MainMenu.MainRect, MainMenu.MainRect.width - 215f);
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); UIStyles.HorizontalLine(Color.black, true);
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUILayout.Label($"Enable Tab View:", new GUILayoutOption[] { GUILayout.Width(215f) }); GUILayout.Label($"Enable Tab View:", new GUILayoutOption[] { GUILayout.Width(215f) });
tabViewInput.IValue.DrawValue(MainMenu.MainRect, MainMenu.MainRect.width - 215f); tabViewInput.IValue.DrawValue(MainMenu.MainRect, MainMenu.MainRect.width - 215f);
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); UIStyles.HorizontalLine(Color.black, true);
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUILayout.Label($"Default Output Path:", new GUILayoutOption[] { GUILayout.Width(215f) }); GUILayout.Label($"Default Output Path:", new GUILayoutOption[] { GUILayout.Width(215f) });
defaultOutputPathInput.IValue.DrawValue(MainMenu.MainRect, MainMenu.MainRect.width - 215f); defaultOutputPathInput.IValue.DrawValue(MainMenu.MainRect, MainMenu.MainRect.width - 215f);
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
@ -95,13 +105,13 @@ namespace Explorer.UI.Main
GUILayout.EndVertical(); GUILayout.EndVertical();
GUIUnstrip.Space(10f); GUIHelper.Space(10f);
GUI.skin.label.alignment = TextAnchor.MiddleCenter; GUI.skin.label.alignment = TextAnchor.MiddleCenter;
GUILayout.Label("<color=orange><size=16><b>Other</b></size></color>", new GUILayoutOption[0]); GUILayout.Label("<color=orange><size=16><b>Other</b></size></color>", new GUILayoutOption[0]);
GUI.skin.label.alignment = TextAnchor.MiddleLeft; GUI.skin.label.alignment = TextAnchor.MiddleLeft;
GUIUnstrip.BeginVertical(GUIContent.none, GUI.skin.box, new GUILayoutOption[0]); GUIHelper.BeginVertical(GUIContent.none, GUI.skin.box, new GUILayoutOption[0]);
if (GUILayout.Button("Inspect Test Class", new GUILayoutOption[0])) if (GUILayout.Button("Inspect Test Class", new GUILayoutOption[0]))
{ {

View File

@ -5,6 +5,8 @@ using UnityEngine;
using UnityEngine.SceneManagement; using UnityEngine.SceneManagement;
using Explorer.UI.Shared; using Explorer.UI.Shared;
using Explorer.CacheObject; using Explorer.CacheObject;
using Explorer.Helpers;
using Explorer.Unstrip.Resources;
namespace Explorer.UI.Main namespace Explorer.UI.Main
{ {
@ -19,8 +21,6 @@ namespace Explorer.UI.Main
private float m_timeOfLastUpdate = -1f; private float m_timeOfLastUpdate = -1f;
private const int PASSIVE_UPDATE_INTERVAL = 1; private const int PASSIVE_UPDATE_INTERVAL = 1;
private static bool m_getRootObjectsFailed;
private static string m_currentScene = ""; private static string m_currentScene = "";
// gameobject list // gameobject list
@ -35,6 +35,7 @@ namespace Explorer.UI.Main
public override void Init() public override void Init()
{ {
Instance = this; Instance = this;
m_currentScene = UnityHelpers.ActiveSceneName;
} }
public void OnSceneChange() public void OnSceneChange()
@ -50,7 +51,7 @@ namespace Explorer.UI.Main
if (m_searching) if (m_searching)
CancelSearch(); CancelSearch();
Update_Impl(true); Update_Impl();
} }
public void TraverseUp() public void TraverseUp()
@ -75,18 +76,13 @@ namespace Explorer.UI.Main
public void CancelSearch() public void CancelSearch()
{ {
m_searching = false; m_searching = false;
if (m_getRootObjectsFailed && !m_currentTransform)
{
GetRootObjectsManual_Impl();
}
} }
public List<CacheObjectBase> SearchSceneObjects(string _search) public List<CacheObjectBase> SearchSceneObjects(string _search)
{ {
var matches = new List<CacheObjectBase>(); var matches = new List<CacheObjectBase>();
foreach (var obj in Resources.FindObjectsOfTypeAll(ReflectionHelpers.GameObjectType)) foreach (var obj in ResourcesUnstrip.FindObjectsOfTypeAll(ReflectionHelpers.GameObjectType))
{ {
#if CPP #if CPP
var go = obj.TryCast<GameObject>(); var go = obj.TryCast<GameObject>();
@ -112,7 +108,7 @@ namespace Explorer.UI.Main
Update_Impl(); Update_Impl();
} }
private void Update_Impl(bool manual = false) private void Update_Impl()
{ {
List<Transform> allTransforms = new List<Transform>(); List<Transform> allTransforms = new List<Transform>();
@ -126,39 +122,23 @@ namespace Explorer.UI.Main
} }
else else
{ {
if (!m_getRootObjectsFailed) for (int i = 0; i < SceneManager.sceneCount; i++)
{ {
try var scene = SceneManager.GetSceneAt(i);
if (scene.name == m_currentScene)
{ {
for (int i = 0; i < SceneManager.sceneCount; i++) var rootObjects =
{ #if CPP
var scene = SceneManager.GetSceneAt(i); Unstrip.Scenes.SceneUnstrip.GetRootGameObjects(scene)
.Select(it => it.transform);
#else
scene.GetRootGameObjects().Select(it => it.transform);
#endif
allTransforms.AddRange(rootObjects);
if (scene.name == m_currentScene) break;
{
allTransforms.AddRange(scene.GetRootGameObjects()
.Select(it => it.transform));
break;
}
}
} }
catch
{
ExplorerCore.Log("Exception getting root scene objects, falling back to backup method...");
m_getRootObjectsFailed = true;
allTransforms.AddRange(GetRootObjectsManual_Impl());
}
}
else
{
if (!manual)
{
return;
}
allTransforms.AddRange(GetRootObjectsManual_Impl());
} }
} }
@ -178,36 +158,6 @@ namespace Explorer.UI.Main
} }
} }
private IEnumerable<Transform> GetRootObjectsManual_Impl()
{
try
{
var array = Resources.FindObjectsOfTypeAll(ReflectionHelpers.TransformType);
var list = new List<Transform>();
foreach (var obj in array)
{
#if CPP
var transform = obj.TryCast<Transform>();
#else
var transform = obj as Transform;
#endif
if (transform.parent == null && transform.gameObject.scene.name == m_currentScene)
{
list.Add(transform);
}
}
return list;
}
catch (Exception e)
{
ExplorerCore.Log("Exception getting root scene objects (manual): "
+ e.GetType() + ", " + e.Message + "\r\n"
+ e.StackTrace);
return new Transform[0];
}
}
// --------- GUI Draw Function --------- // // --------- GUI Draw Function --------- //
public override void DrawWindow() public override void DrawWindow()
@ -216,7 +166,7 @@ namespace Explorer.UI.Main
{ {
DrawHeaderArea(); DrawHeaderArea();
GUIUnstrip.BeginVertical(GUIContent.none, GUI.skin.box, null); GUIHelper.BeginVertical(GUIContent.none, GUI.skin.box, null);
DrawPageButtons(); DrawPageButtons();
@ -242,7 +192,7 @@ namespace Explorer.UI.Main
private void DrawHeaderArea() private void DrawHeaderArea()
{ {
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
// Current Scene label // Current Scene label
GUILayout.Label("Current Scene:", new GUILayoutOption[] { GUILayout.Width(120) }); GUILayout.Label("Current Scene:", new GUILayoutOption[] { GUILayout.Width(120) });
@ -252,10 +202,10 @@ namespace Explorer.UI.Main
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
// ----- GameObject Search ----- // ----- GameObject Search -----
GUIUnstrip.BeginHorizontal(GUIContent.none, GUI.skin.box, null); GUIHelper.BeginHorizontal(GUIContent.none, GUI.skin.box, null);
GUILayout.Label("<b>Search Scene:</b>", new GUILayoutOption[] { GUILayout.Width(100) }); GUILayout.Label("<b>Search Scene:</b>", new GUILayoutOption[] { GUILayout.Width(100) });
m_searchInput = GUIUnstrip.TextField(m_searchInput, new GUILayoutOption[0]); m_searchInput = GUIHelper.TextField(m_searchInput, new GUILayoutOption[0]);
if (GUILayout.Button("Search", new GUILayoutOption[] { GUILayout.Width(80) })) if (GUILayout.Button("Search", new GUILayoutOption[] { GUILayout.Width(80) }))
{ {
@ -263,7 +213,7 @@ namespace Explorer.UI.Main
} }
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
GUIUnstrip.Space(5); GUIHelper.Space(5);
} }
private void SceneChangeButtons() private void SceneChangeButtons()
@ -292,22 +242,19 @@ namespace Explorer.UI.Main
{ {
int index = names.IndexOf(m_currentScene); int index = names.IndexOf(m_currentScene);
index += changeWanted; index += changeWanted;
if (index > scenes.Count - 1)
if (index >= 0 && index < SceneManager.sceneCount)
{ {
index = 0; m_currentScene = scenes[index].name;
Update_Impl();
} }
else if (index < 0)
{
index = scenes.Count - 1;
}
m_currentScene = scenes[index].name;
} }
} }
} }
private void DrawPageButtons() private void DrawPageButtons()
{ {
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
Pages.DrawLimitInputArea(); Pages.DrawLimitInputArea();
@ -317,7 +264,7 @@ namespace Explorer.UI.Main
{ {
Pages.TurnPage(Turn.Left, ref this.scroll); Pages.TurnPage(Turn.Left, ref this.scroll);
Update_Impl(true); Update_Impl();
} }
Pages.CurrentPageLabel(); Pages.CurrentPageLabel();
@ -326,7 +273,7 @@ namespace Explorer.UI.Main
{ {
Pages.TurnPage(Turn.Right, ref this.scroll); Pages.TurnPage(Turn.Right, ref this.scroll);
Update_Impl(true); Update_Impl();
} }
} }
@ -338,7 +285,7 @@ namespace Explorer.UI.Main
{ {
if (m_currentTransform != null) if (m_currentTransform != null)
{ {
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
if (GUILayout.Button("<-", new GUILayoutOption[] { GUILayout.Width(35) })) if (GUILayout.Button("<-", new GUILayoutOption[] { GUILayout.Width(35) }))
{ {
TraverseUp(); TraverseUp();
@ -356,14 +303,6 @@ namespace Explorer.UI.Main
else else
{ {
GUILayout.Label("Scene Root GameObjects:", new GUILayoutOption[0]); GUILayout.Label("Scene Root GameObjects:", new GUILayoutOption[0]);
if (m_getRootObjectsFailed)
{
if (GUILayout.Button("Update Root Object List (auto-update failed!)", new GUILayoutOption[0]))
{
Update_Impl(true);
}
}
} }
if (m_objectList.Count > 0) if (m_objectList.Count > 0)

View File

@ -6,6 +6,8 @@ using System.Reflection;
using UnityEngine; using UnityEngine;
using Explorer.UI.Shared; using Explorer.UI.Shared;
using Explorer.CacheObject; using Explorer.CacheObject;
using Explorer.Helpers;
using Explorer.Unstrip.Resources;
namespace Explorer.UI.Main namespace Explorer.UI.Main
{ {
@ -15,9 +17,13 @@ namespace Explorer.UI.Main
public override string Name { get => "Search"; } public override string Name { get => "Search"; }
private int MaxSearchResults = 5000;
private string m_searchInput = ""; private string m_searchInput = "";
private string m_typeInput = ""; private string m_typeInput = "";
//private bool m_cachingResults;
private Vector2 resultsScroll = Vector2.zero; private Vector2 resultsScroll = Vector2.zero;
public PageHelper Pages = new PageHelper(); public PageHelper Pages = new PageHelper();
@ -58,6 +64,8 @@ namespace Explorer.UI.Main
private void CacheResults(IEnumerable results, bool isStaticClasses = false) private void CacheResults(IEnumerable results, bool isStaticClasses = false)
{ {
//m_cachingResults = true;
m_searchResults = new List<CacheObjectBase>(); m_searchResults = new List<CacheObjectBase>();
foreach (var obj in results) foreach (var obj in results)
@ -67,6 +75,9 @@ namespace Explorer.UI.Main
#if CPP #if CPP
if (toCache is Il2CppSystem.Object ilObject) if (toCache is Il2CppSystem.Object ilObject)
{ {
var type = ReflectionHelpers.GetActualType(ilObject);
ilObject = (Il2CppSystem.Object)ilObject.Il2CppCast(type);
toCache = ilObject.TryCast<GameObject>() ?? ilObject.TryCast<Transform>()?.gameObject ?? ilObject; toCache = ilObject.TryCast<GameObject>() ?? ilObject.TryCast<Transform>()?.gameObject ?? ilObject;
} }
#else #else
@ -76,6 +87,14 @@ namespace Explorer.UI.Main
} }
#endif #endif
if (toCache is TextAsset textAsset)
{
if (string.IsNullOrEmpty(textAsset.text))
{
continue;
}
}
var cache = CacheFactory.GetCacheObject(toCache); var cache = CacheFactory.GetCacheObject(toCache);
cache.IsStaticClassSearchResult = isStaticClasses; cache.IsStaticClassSearchResult = isStaticClasses;
m_searchResults.Add(cache); m_searchResults.Add(cache);
@ -83,187 +102,22 @@ namespace Explorer.UI.Main
Pages.ItemCount = m_searchResults.Count; Pages.ItemCount = m_searchResults.Count;
Pages.PageOffset = 0; Pages.PageOffset = 0;
results = null;
//m_cachingResults = false;
} }
public override void DrawWindow()
{
try
{
// helpers
GUIUnstrip.BeginHorizontal(GUIContent.none, GUI.skin.box, null);
GUILayout.Label("<b><color=orange>Helpers</color></b>", new GUILayoutOption[] { GUILayout.Width(70) });
if (GUILayout.Button("Find Static Instances", new GUILayoutOption[] { GUILayout.Width(180) }))
{
CacheResults(GetStaticInstances());
}
if (GUILayout.Button("Find Static Classes", new GUILayoutOption[] { GUILayout.Width(180) }))
{
CacheResults(GetStaticClasses(), true);
}
GUILayout.EndHorizontal();
// search box
SearchBox();
// results
GUIUnstrip.BeginVertical(GUIContent.none, GUI.skin.box, null);
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
GUILayout.Label("<b><color=orange>Results </color></b>" + " (" + m_searchResults.Count + ")", new GUILayoutOption[0]);
GUI.skin.label.alignment = TextAnchor.UpperLeft;
int count = m_searchResults.Count;
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
Pages.DrawLimitInputArea();
if (count > Pages.ItemsPerPage)
{
// prev/next page buttons
if (Pages.ItemCount > Pages.ItemsPerPage)
{
if (GUILayout.Button("< Prev", new GUILayoutOption[] { GUILayout.Width(80) }))
{
Pages.TurnPage(Turn.Left, ref this.resultsScroll);
}
Pages.CurrentPageLabel();
if (GUILayout.Button("Next >", new GUILayoutOption[] { GUILayout.Width(80) }))
{
Pages.TurnPage(Turn.Right, ref this.resultsScroll);
}
}
}
GUILayout.EndHorizontal();
resultsScroll = GUIUnstrip.BeginScrollView(resultsScroll);
var _temprect = new Rect(MainMenu.MainRect.x, MainMenu.MainRect.y, MainMenu.MainRect.width + 160, MainMenu.MainRect.height);
if (m_searchResults.Count > 0)
{
int offset = Pages.CalculateOffsetIndex();
for (int i = offset; i < offset + Pages.ItemsPerPage && i < count; i++)
{
m_searchResults[i].Draw(MainMenu.MainRect, 0f);
}
}
else
{
GUILayout.Label("<color=red><i>No results found!</i></color>", new GUILayoutOption[0]);
}
GUIUnstrip.EndScrollView();
GUILayout.EndVertical();
}
catch
{
m_searchResults.Clear();
}
}
private void SearchBox()
{
GUIUnstrip.BeginVertical(GUIContent.none, GUI.skin.box, null);
// ----- GameObject Search -----
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
GUILayout.Label("<b><color=orange>Search</color></b>", new GUILayoutOption[0]);
GUI.skin.label.alignment = TextAnchor.UpperLeft;
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
GUILayout.Label("Name Contains:", new GUILayoutOption[] { GUILayout.Width(100) });
m_searchInput = GUIUnstrip.TextField(m_searchInput, new GUILayoutOption[] { GUILayout.Width(200) });
GUILayout.EndHorizontal();
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
GUILayout.Label("Class Filter:", new GUILayoutOption[] { GUILayout.Width(100) });
ClassFilterToggle(TypeFilter.Object, "Object");
ClassFilterToggle(TypeFilter.GameObject, "GameObject");
ClassFilterToggle(TypeFilter.Component, "Component");
ClassFilterToggle(TypeFilter.Custom, "Custom");
GUILayout.EndHorizontal();
if (TypeMode == TypeFilter.Custom)
{
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
GUI.skin.label.alignment = TextAnchor.MiddleRight;
GUILayout.Label("Custom Class:", new GUILayoutOption[] { GUILayout.Width(250) });
GUI.skin.label.alignment = TextAnchor.UpperLeft;
m_typeInput = GUIUnstrip.TextField(m_typeInput, new GUILayoutOption[] { GUILayout.Width(250) });
GUILayout.EndHorizontal();
}
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
GUILayout.Label("Scene Filter:", new GUILayoutOption[] { GUILayout.Width(100) });
SceneFilterToggle(SceneFilter.Any, "Any", 60);
SceneFilterToggle(SceneFilter.This, "This Scene", 100);
SceneFilterToggle(SceneFilter.DontDestroy, "DontDestroyOnLoad", 140);
SceneFilterToggle(SceneFilter.None, "No Scene", 80);
GUILayout.EndHorizontal();
if (GUILayout.Button("<b><color=cyan>Search</color></b>", new GUILayoutOption[0]))
{
Search();
}
GUILayout.EndVertical();
}
private void ClassFilterToggle(TypeFilter mode, string label)
{
if (TypeMode == mode)
{
GUI.color = Color.green;
}
else
{
GUI.color = Color.white;
}
if (GUILayout.Button(label, new GUILayoutOption[] { GUILayout.Width(100) }))
{
TypeMode = mode;
}
GUI.color = Color.white;
}
private void SceneFilterToggle(SceneFilter mode, string label, float width)
{
if (SceneMode == mode)
{
GUI.color = Color.green;
}
else
{
GUI.color = Color.white;
}
if (GUILayout.Button(label, new GUILayoutOption[] { GUILayout.Width(width) }))
{
SceneMode = mode;
}
GUI.color = Color.white;
}
// -------------- ACTUAL METHODS (not Gui draw) ----------------- //
// ======= search functions =======
private void Search() private void Search()
{ {
Pages.PageOffset = 0; //if (m_cachingResults)
CacheResults(FindAllObjectsOfType(m_searchInput, m_typeInput)); //{
} // ExplorerCore.Log("Cannot search now, we are already caching results...");
// return;
//}
Pages.PageOffset = 0;
private List<object> FindAllObjectsOfType(string searchQuery, string typeName)
{
#if CPP #if CPP
Il2CppSystem.Type searchType = null; Il2CppSystem.Type searchType = null;
@ -272,24 +126,18 @@ namespace Explorer.UI.Main
#endif #endif
if (TypeMode == TypeFilter.Custom) if (TypeMode == TypeFilter.Custom)
{ {
try if (ReflectionHelpers.GetTypeByName(m_typeInput) is Type t)
{ {
if (ReflectionHelpers.GetTypeByName(typeName) is Type t)
{
#if CPP #if CPP
searchType = Il2CppSystem.Type.GetType(t.AssemblyQualifiedName); searchType = Il2CppSystem.Type.GetType(t.AssemblyQualifiedName);
#else #else
searchType = t; searchType = t;
#endif #endif
}
else
{
throw new Exception($"Could not find a Type by the name of '{typeName}'!");
}
} }
catch (Exception e) else
{ {
ExplorerCore.Log("Exception getting Search Type: " + e.GetType() + ", " + e.Message); ExplorerCore.Log($"Could not find a Type by the name of '{m_typeInput}'!");
return;
} }
} }
else if (TypeMode == TypeFilter.Object) else if (TypeMode == TypeFilter.Object)
@ -311,21 +159,21 @@ namespace Explorer.UI.Main
{ {
ExplorerCore.LogWarning("Your Custom Class Type must inherit from UnityEngine.Object!"); ExplorerCore.LogWarning("Your Custom Class Type must inherit from UnityEngine.Object!");
} }
return new List<object>(); return;
} }
var matches = new List<object>(); var matches = new List<object>();
var allObjectsOfType = Resources.FindObjectsOfTypeAll(searchType); var allObjectsOfType = ResourcesUnstrip.FindObjectsOfTypeAll(searchType);
//ExplorerCore.Log("Found count: " + allObjectsOfType.Length); //ExplorerCore.Log("Found count: " + allObjectsOfType.Length);
int i = 0; int i = 0;
foreach (var obj in allObjectsOfType) foreach (var obj in allObjectsOfType)
{ {
if (i >= 2000) break; if (i >= MaxSearchResults) break;
if (searchQuery != "" && !obj.name.ToLower().Contains(searchQuery.ToLower())) if (m_searchInput != "" && !obj.name.ToLower().Contains(m_searchInput.ToLower()))
{ {
continue; continue;
} }
@ -355,7 +203,7 @@ namespace Explorer.UI.Main
i++; i++;
} }
return matches; CacheResults(matches);
} }
public static bool FilterScene(object obj, SceneFilter filter) public static bool FilterScene(object obj, SceneFilter filter)
@ -394,8 +242,6 @@ namespace Explorer.UI.Main
return false; return false;
} }
// ====== other ========
private static bool FilterName(string name) private static bool FilterName(string name)
{ {
// Don't really want these instances. // Don't really want these instances.
@ -497,5 +343,202 @@ namespace Explorer.UI.Main
return list; return list;
} }
// =========== GUI DRAW ============= //
public override void DrawWindow()
{
try
{
// helpers
GUIHelper.BeginHorizontal(GUIContent.none, GUI.skin.box, null);
GUILayout.Label("<b><color=orange>Helpers</color></b>", new GUILayoutOption[] { GUILayout.Width(70) });
if (GUILayout.Button("Find Static Instances", new GUILayoutOption[] { GUILayout.Width(180) }))
{
CacheResults(GetStaticInstances());
}
if (GUILayout.Button("Find Static Classes", new GUILayoutOption[] { GUILayout.Width(180) }))
{
CacheResults(GetStaticClasses(), true);
}
GUILayout.EndHorizontal();
// search box
SearchBox();
// results
GUIHelper.BeginVertical(GUIContent.none, GUI.skin.box, null);
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
GUILayout.Label("<b><color=orange>Results </color></b>" + " (" + m_searchResults.Count + ")", new GUILayoutOption[0]);
GUI.skin.label.alignment = TextAnchor.UpperLeft;
int count = m_searchResults.Count;
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
Pages.DrawLimitInputArea();
if (count > Pages.ItemsPerPage)
{
// prev/next page buttons
if (Pages.ItemCount > Pages.ItemsPerPage)
{
if (GUILayout.Button("< Prev", new GUILayoutOption[] { GUILayout.Width(80) }))
{
Pages.TurnPage(Turn.Left, ref this.resultsScroll);
}
Pages.CurrentPageLabel();
if (GUILayout.Button("Next >", new GUILayoutOption[] { GUILayout.Width(80) }))
{
Pages.TurnPage(Turn.Right, ref this.resultsScroll);
}
}
}
GUILayout.EndHorizontal();
resultsScroll = GUIHelper.BeginScrollView(resultsScroll);
var _temprect = new Rect(MainMenu.MainRect.x, MainMenu.MainRect.y, MainMenu.MainRect.width + 160, MainMenu.MainRect.height);
if (m_searchResults.Count > 0)
{
int offset = Pages.CalculateOffsetIndex();
for (int i = offset; i < offset + Pages.ItemsPerPage && i < count; i++)
{
if (i >= m_searchResults.Count) break;
m_searchResults[i].Draw(MainMenu.MainRect, 0f);
}
}
else
{
GUILayout.Label("<color=red><i>No results found!</i></color>", new GUILayoutOption[0]);
}
GUIHelper.EndScrollView();
GUILayout.EndVertical();
}
catch (Exception e)
{
if (!e.Message.Contains("in a group with only"))
{
ExplorerCore.Log("Exception drawing search results!");
while (e != null)
{
ExplorerCore.Log(e);
e = e.InnerException;
}
m_searchResults.Clear();
}
}
}
private void SearchBox()
{
GUIHelper.BeginVertical(GUIContent.none, GUI.skin.box, null);
// ----- GameObject Search -----
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
GUILayout.Label("<b><color=orange>Search</color></b>", new GUILayoutOption[0]);
GUI.skin.label.alignment = TextAnchor.UpperLeft;
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUILayout.Label("Name Contains:", new GUILayoutOption[] { GUILayout.Width(100) });
m_searchInput = GUIHelper.TextField(m_searchInput, new GUILayoutOption[] { GUILayout.Width(200) });
GUILayout.Label("Max Results:", new GUILayoutOption[] { GUILayout.Width(100) });
var s = MaxSearchResults.ToString();
s = GUIHelper.TextField(s, new GUILayoutOption[] { GUILayout.Width(80) });
if (int.TryParse(s, out int i))
{
MaxSearchResults = i;
}
GUILayout.EndHorizontal();
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUILayout.Label("Class Filter:", new GUILayoutOption[] { GUILayout.Width(100) });
ClassFilterToggle(TypeFilter.Object, "Object");
ClassFilterToggle(TypeFilter.GameObject, "GameObject");
ClassFilterToggle(TypeFilter.Component, "Component");
ClassFilterToggle(TypeFilter.Custom, "Custom");
GUILayout.EndHorizontal();
if (TypeMode == TypeFilter.Custom)
{
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUI.skin.label.alignment = TextAnchor.MiddleRight;
GUILayout.Label("Custom Class:", new GUILayoutOption[] { GUILayout.Width(250) });
GUI.skin.label.alignment = TextAnchor.UpperLeft;
m_typeInput = GUIHelper.TextField(m_typeInput, new GUILayoutOption[] { GUILayout.Width(250) });
GUILayout.EndHorizontal();
}
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUILayout.Label("Scene Filter:", new GUILayoutOption[] { GUILayout.Width(100) });
SceneFilterToggle(SceneFilter.Any, "Any", 60);
SceneFilterToggle(SceneFilter.This, "This Scene", 100);
SceneFilterToggle(SceneFilter.DontDestroy, "DontDestroyOnLoad", 140);
SceneFilterToggle(SceneFilter.None, "No Scene", 80);
GUILayout.EndHorizontal();
if (GUILayout.Button("<b><color=cyan>Search</color></b>", new GUILayoutOption[0]))
{
Search();
}
//if (m_cachingResults)
//{
// GUILayout.Label("Searching...", new GUILayoutOption[0]);
//}
//else
//{
// if (GUILayout.Button("<b><color=cyan>Search</color></b>", new GUILayoutOption[0]))
// {
// Search();
// }
//}
GUILayout.EndVertical();
}
private void ClassFilterToggle(TypeFilter mode, string label)
{
if (TypeMode == mode)
{
GUI.color = Color.green;
}
else
{
GUI.color = Color.white;
}
if (GUILayout.Button(label, new GUILayoutOption[] { GUILayout.Width(100) }))
{
TypeMode = mode;
}
GUI.color = Color.white;
}
private void SceneFilterToggle(SceneFilter mode, string label, float width)
{
if (SceneMode == mode)
{
GUI.color = Color.green;
}
else
{
GUI.color = Color.white;
}
if (GUILayout.Button(label, new GUILayoutOption[] { GUILayout.Width(width) }))
{
SceneMode = mode;
}
GUI.color = Color.white;
}
} }
} }

View File

@ -47,7 +47,7 @@ namespace Explorer.UI
return; return;
} }
m_currentPage = index; m_currentPage = index;
GUIUnstrip.BringWindowToFront(MainWindowID); GUIHelper.BringWindowToFront(MainWindowID);
GUI.FocusWindow(MainWindowID); GUI.FocusWindow(MainWindowID);
} }
@ -58,39 +58,39 @@ namespace Explorer.UI
public void OnGUI() public void OnGUI()
{ {
MainRect = GUIUnstrip.Window(MainWindowID, MainRect, (GUI.WindowFunction)MainWindow, ExplorerCore.NAME); MainRect = GUIHelper.Window(MainWindowID, MainRect, (GUI.WindowFunction)MainWindow, ExplorerCore.NAME);
} }
private void MainWindow(int id) private void MainWindow(int id)
{ {
GUI.DragWindow(new Rect(0, 0, MainRect.width - 90, 20)); GUI.DragWindow(new Rect(0, 0, MainRect.width - 90, 20));
if (GUIUnstrip.Button(new Rect(MainRect.width - 90, 2, 80, 20), $"Hide ({ModConfig.Instance.Main_Menu_Toggle})")) if (GUIHelper.Button(new Rect(MainRect.width - 90, 2, 80, 20), $"Hide ({ModConfig.Instance.Main_Menu_Toggle})"))
{ {
ExplorerCore.ShowMenu = false; ExplorerCore.ShowMenu = false;
return; return;
} }
GUIUnstrip.BeginArea(new Rect(5, 25, MainRect.width - 10, MainRect.height - 35), GUI.skin.box); GUIHelper.BeginArea(new Rect(5, 25, MainRect.width - 10, MainRect.height - 35), GUI.skin.box);
MainHeader(); MainHeader();
var page = Pages[m_currentPage]; var page = Pages[m_currentPage];
page.scroll = GUIUnstrip.BeginScrollView(page.scroll); page.scroll = GUIHelper.BeginScrollView(page.scroll);
page.DrawWindow(); page.DrawWindow();
GUIUnstrip.EndScrollView(); GUIHelper.EndScrollView();
MainRect = ResizeDrag.ResizeWindow(MainRect, MainWindowID); MainRect = ResizeDrag.ResizeWindow(MainRect, MainWindowID);
GUIUnstrip.EndArea(); GUIHelper.EndArea();
} }
private void MainHeader() private void MainHeader()
{ {
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
for (int i = 0; i < Pages.Count; i++) for (int i = 0; i < Pages.Count; i++)
{ {
if (m_currentPage == i) if (m_currentPage == i)
@ -105,7 +105,7 @@ namespace Explorer.UI
} }
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUI.color = Color.white; GUI.color = Color.white;
InspectUnderMouse.EnableInspect = GUILayout.Toggle(InspectUnderMouse.EnableInspect, "Inspect Under Mouse (Shift + RMB)", new GUILayoutOption[0]); InspectUnderMouse.EnableInspect = GUILayout.Toggle(InspectUnderMouse.EnableInspect, "Inspect Under Mouse (Shift + RMB)", new GUILayoutOption[0]);
@ -117,7 +117,7 @@ namespace Explorer.UI
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
//GUIUnstrip.Space(10); //GUIUnstrip.Space(10);
GUIUnstrip.Space(10); GUIHelper.Space(10);
GUI.color = Color.white; GUI.color = Color.white;
} }

View File

@ -59,7 +59,7 @@ namespace Explorer.UI.Shared
// ------ toggle active button ------ // ------ toggle active button ------
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUI.skin.button.alignment = TextAnchor.UpperLeft; GUI.skin.button.alignment = TextAnchor.UpperLeft;
GUI.color = color; GUI.color = color;

View File

@ -1,4 +1,5 @@
using UnityEngine; using System;
using UnityEngine;
namespace Explorer.UI.Shared namespace Explorer.UI.Shared
{ {
@ -38,7 +39,7 @@ namespace Explorer.UI.Shared
private int CalculateMaxOffset() private int CalculateMaxOffset()
{ {
return MaxPageOffset = (int)Mathf.Ceil((float)(ItemCount / (decimal)ItemsPerPage)) - 1; return MaxPageOffset = (int)Math.Ceiling((float)(ItemCount / (decimal)ItemsPerPage)) - 1;
} }
public void CurrentPageLabel() public void CurrentPageLabel()
@ -94,7 +95,7 @@ namespace Explorer.UI.Shared
{ {
GUILayout.Label("Limit: ", new GUILayoutOption[] { GUILayout.Width(50) }); GUILayout.Label("Limit: ", new GUILayoutOption[] { GUILayout.Width(50) });
var limit = this.ItemsPerPage.ToString(); var limit = this.ItemsPerPage.ToString();
limit = GUIUnstrip.TextField(limit, new GUILayoutOption[] { GUILayout.Width(50) }); limit = GUIHelper.TextField(limit, new GUILayoutOption[] { GUILayout.Width(50) });
if (limit != ItemsPerPage.ToString() && int.TryParse(limit, out int i)) if (limit != ItemsPerPage.ToString() && int.TryParse(limit, out int i))
{ {
ItemsPerPage = i; ItemsPerPage = i;

View File

@ -8,52 +8,60 @@ namespace Explorer.UI.Shared
{ {
public class ResizeDrag public class ResizeDrag
{ {
#if CPP
private static bool RESIZE_FAILED = false; private static bool RESIZE_FAILED = false;
#endif
public static bool IsResizing = false;
public static bool IsMouseInResizeArea = false;
private static readonly GUIContent gcDrag = new GUIContent("<-- Drag to resize -->"); private static readonly GUIContent gcDrag = new GUIContent("<-- Drag to resize -->");
private static bool isResizing = false;
private static Rect m_currentResize; private static Rect m_currentResize;
private static int m_currentWindow; private static int m_currentWindow;
public static Rect ResizeWindow(Rect _rect, int ID) public static Rect ResizeWindow(Rect _rect, int ID)
{ {
#if CPP
if (!RESIZE_FAILED) if (!RESIZE_FAILED)
{ {
var origRect = _rect; var origRect = _rect;
try try
{ {
GUIUnstrip.BeginHorizontal(GUIContent.none, GUI.skin.box, null); GUIHelper.BeginHorizontal(GUIContent.none, GUI.skin.box, null);
GUI.skin.label.alignment = TextAnchor.MiddleCenter; GUI.skin.label.alignment = TextAnchor.MiddleCenter;
#if ML #if BIE
GUILayout.Button(gcDrag, GUI.skin.label, new GUILayoutOption[] { GUILayout.Height(15) }); #if CPP // Temporary for BepInEx IL2CPP
GUILayout.Button("<-- Drag to resize -->", new GUILayoutOption[] { GUILayout.Height(15) });
#else #else
GUILayout.Button("<-- Drag to resize -->", new GUILayoutOption[] { GUILayout.Height(15) }); GUILayout.Button(gcDrag, GUI.skin.label, new GUILayoutOption[] { GUILayout.Height(15) });
#endif
#else
GUILayout.Button(gcDrag, GUI.skin.label, new GUILayoutOption[] { GUILayout.Height(15) });
#endif #endif
var r = GUIUnstrip.GetLastRect(); var resizeDragArea = GUIHelper.GetLastRect();
var mousePos = InputManager.MousePosition; var mousePos = InputManager.MousePosition;
try try
{ {
var mouse = GUIUnstrip.ScreenToGUIPoint(new Vector2(mousePos.x, Screen.height - mousePos.y)); var mouse = GUIHelper.ScreenToGUIPoint(new Vector2(mousePos.x, Screen.height - mousePos.y));
if (r.Contains(mouse) && InputManager.GetMouseButtonDown(0)) if (resizeDragArea.Contains(mouse))
{ {
isResizing = true; IsMouseInResizeArea = true;
m_currentWindow = ID;
m_currentResize = new Rect(mouse.x, mouse.y, _rect.width, _rect.height); if (InputManager.GetMouseButtonDown(0))
{
IsResizing = true;
m_currentWindow = ID;
m_currentResize = new Rect(mouse.x, mouse.y, _rect.width, _rect.height);
}
} }
else if (!InputManager.GetMouseButton(0)) else if (!InputManager.GetMouseButton(0))
{ {
isResizing = false; IsMouseInResizeArea = false;
IsResizing = false;
} }
if (isResizing && ID == m_currentWindow) if (IsResizing && ID == m_currentWindow)
{ {
_rect.width = Mathf.Max(100, m_currentResize.width + (mouse.x - m_currentResize.x)); _rect.width = Mathf.Max(100, m_currentResize.width + (mouse.x - m_currentResize.x));
_rect.height = Mathf.Max(100, m_currentResize.height + (mouse.y - m_currentResize.y)); _rect.height = Mathf.Max(100, m_currentResize.height + (mouse.y - m_currentResize.y));
@ -81,74 +89,36 @@ namespace Explorer.UI.Shared
//ExplorerCore.Log(e.StackTrace); //ExplorerCore.Log(e.StackTrace);
return origRect; return origRect;
} }
GUI.skin.label.alignment = TextAnchor.UpperLeft;
} }
else else
{ {
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUILayout.Label("Resize window:", new GUILayoutOption[] { GUILayout.Width(100) }); GUILayout.Label("Resize window:", new GUILayoutOption[] { GUILayout.Width(100) });
GUI.skin.label.alignment = TextAnchor.MiddleRight; GUI.skin.label.alignment = TextAnchor.MiddleRight;
GUILayout.Label("<color=cyan>Width:</color>", new GUILayoutOption[] { GUILayout.Width(60) }); GUILayout.Label("<color=cyan>Width:</color>", new GUILayoutOption[] { GUILayout.Width(60) });
if (GUIUnstrip.RepeatButton("-", new GUILayoutOption[] { GUILayout.Width(20) })) if (GUIHelper.RepeatButton("-", new GUILayoutOption[] { GUILayout.Width(20) }))
{ {
_rect.width -= 5f; _rect.width -= 5f;
} }
if (GUIUnstrip.RepeatButton("+", new GUILayoutOption[] { GUILayout.Width(20) })) if (GUIHelper.RepeatButton("+", new GUILayoutOption[] { GUILayout.Width(20) }))
{ {
_rect.width += 5f; _rect.width += 5f;
} }
GUILayout.Label("<color=cyan>Height:</color>", new GUILayoutOption[] { GUILayout.Width(60) }); GUILayout.Label("<color=cyan>Height:</color>", new GUILayoutOption[] { GUILayout.Width(60) });
if (GUIUnstrip.RepeatButton("-", new GUILayoutOption[] { GUILayout.Width(20) })) if (GUIHelper.RepeatButton("-", new GUILayoutOption[] { GUILayout.Width(20) }))
{ {
_rect.height -= 5f; _rect.height -= 5f;
} }
if (GUIUnstrip.RepeatButton("+", new GUILayoutOption[] { GUILayout.Width(20) })) if (GUIHelper.RepeatButton("+", new GUILayoutOption[] { GUILayout.Width(20) }))
{ {
_rect.height += 5f; _rect.height += 5f;
} }
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
GUI.skin.label.alignment = TextAnchor.UpperLeft;
} }
#else // mono
GUIUnstrip.BeginHorizontal(GUIContent.none, GUI.skin.box, null);
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
GUILayout.Button(gcDrag, GUI.skin.label, new GUILayoutOption[] { GUILayout.Height(15) });
//var r = GUILayoutUtility.GetLastRect();
var r = GUILayoutUtility.GetLastRect();
var mousePos = InputManager.MousePosition;
var mouse = GUIUnstrip.ScreenToGUIPoint(new Vector2(mousePos.x, Screen.height - mousePos.y));
if (r.Contains(mouse) && InputManager.GetMouseButtonDown(0))
{
isResizing = true;
m_currentWindow = ID;
m_currentResize = new Rect(mouse.x, mouse.y, _rect.width, _rect.height);
}
else if (!InputManager.GetMouseButton(0))
{
isResizing = false;
}
if (isResizing && ID == m_currentWindow)
{
_rect.width = Mathf.Max(100, m_currentResize.width + (mouse.x - m_currentResize.x));
_rect.height = Mathf.Max(100, m_currentResize.height + (mouse.y - m_currentResize.y));
_rect.xMax = Mathf.Min(Screen.width, _rect.xMax); // modifying xMax affects width, not x
_rect.yMax = Mathf.Min(Screen.height, _rect.yMax); // modifying yMax affects height, not y
}
GUILayout.EndHorizontal();
#endif
GUI.skin.label.alignment = TextAnchor.MiddleLeft; GUI.skin.label.alignment = TextAnchor.MiddleLeft;
return _rect; return _rect;

View File

@ -52,7 +52,7 @@ namespace Explorer.UI
try try
{ {
GUI.DragWindow(new Rect(0, 0, m_rect.width - 90, 20)); GUI.DragWindow(new Rect(0, 0, m_rect.width - 90, 20));
if (GUIUnstrip.Button(new Rect(m_rect.width - 90, 2, 80, 20), "<color=red>Close All</color>")) if (GUIHelper.Button(new Rect(m_rect.width - 90, 2, 80, 20), "<color=red>Close All</color>"))
{ {
foreach (var window in WindowManager.Windows) foreach (var window in WindowManager.Windows)
{ {
@ -61,20 +61,29 @@ namespace Explorer.UI
return; return;
} }
GUIUnstrip.BeginArea(new Rect(5, 25, m_rect.width - 10, m_rect.height - 35), GUI.skin.box); GUIHelper.BeginArea(new Rect(5, 25, m_rect.width - 10, m_rect.height - 35), GUI.skin.box);
GUIUnstrip.BeginVertical(GUIContent.none, GUI.skin.box, null); GUIHelper.BeginVertical(GUIContent.none, GUI.skin.box, null);
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUI.skin.button.alignment = TextAnchor.MiddleLeft; GUI.skin.button.alignment = TextAnchor.MiddleLeft;
int tabPerRow = Mathf.FloorToInt((float)((decimal)m_rect.width / 238)); int tabPerRow = (int)Math.Floor(m_rect.width / 238);
int rowCount = 0; int rowCount = 0;
for (int i = 0; i < WindowManager.Windows.Count; i++) for (int i = 0; i < WindowManager.Windows.Count; i++)
{ {
var window = WindowManager.Windows[i];
// Prevent trying to draw destroyed UnityEngine.Objects
// before the WindowManager removes them.
if (window.Target is UnityEngine.Object uObj && !uObj)
{
continue;
}
if (rowCount >= tabPerRow) if (rowCount >= tabPerRow)
{ {
rowCount = 0; rowCount = 0;
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]); GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
} }
rowCount++; rowCount++;
@ -82,7 +91,6 @@ namespace Explorer.UI
string color = focused ? "<color=lime>" : "<color=orange>"; string color = focused ? "<color=lime>" : "<color=orange>";
GUI.color = focused ? Color.green : Color.white; GUI.color = focused ? Color.green : Color.white;
var window = WindowManager.Windows[i];
if (GUILayout.Button(color + window.Title + "</color>", new GUILayoutOption[] { GUILayout.Width(200) })) if (GUILayout.Button(color + window.Title + "</color>", new GUILayoutOption[] { GUILayout.Width(200) }))
{ {
TargetTabID = i; TargetTabID = i;
@ -101,7 +109,7 @@ namespace Explorer.UI
m_rect = ResizeDrag.ResizeWindow(m_rect, windowID); m_rect = ResizeDrag.ResizeWindow(m_rect, windowID);
GUIUnstrip.EndArea(); GUIHelper.EndArea();
} }
catch (Exception e) catch (Exception e)
{ {

View File

@ -2,6 +2,7 @@
using UnityEngine; using UnityEngine;
using Explorer.Config; using Explorer.Config;
using Explorer.UI.Inspectors; using Explorer.UI.Inspectors;
using Explorer.Helpers;
namespace Explorer.UI namespace Explorer.UI
{ {
@ -26,7 +27,15 @@ namespace Explorer.UI
{ {
var window = Activator.CreateInstance<T>(); var window = Activator.CreateInstance<T>();
#if CPP
if (target is Il2CppSystem.Object ilObject)
{
target = ilObject.Il2CppCast(ReflectionHelpers.GetActualType(ilObject));
}
#endif
window.Target = target; window.Target = target;
window.windowID = WindowManager.NextWindowID(); window.windowID = WindowManager.NextWindowID();
window.m_rect = WindowManager.GetNewWindowRect(); window.m_rect = WindowManager.GetNewWindowRect();

View File

@ -11,6 +11,26 @@ namespace Explorer.UI
public static bool TabView = Config.ModConfig.Instance.Tab_View; public static bool TabView = Config.ModConfig.Instance.Tab_View;
public static bool IsMouseInWindow
{
get
{
if (!ExplorerCore.ShowMenu)
{
return false;
}
foreach (var window in Windows)
{
if (RectContainsMouse(window.m_rect))
{
return true;
}
}
return RectContainsMouse(MainMenu.MainRect);
}
}
public static List<WindowBase> Windows = new List<WindowBase>(); public static List<WindowBase> Windows = new List<WindowBase>();
public static int CurrentWindowID { get; set; } = 500000; public static int CurrentWindowID { get; set; } = 500000;
private static Rect m_lastWindowRect; private static Rect m_lastWindowRect;
@ -90,7 +110,7 @@ namespace Explorer.UI
{ {
if (!TabView) if (!TabView)
{ {
GUIUnstrip.BringWindowToFront(window.windowID); GUIHelper.BringWindowToFront(window.windowID);
GUI.FocusWindow(window.windowID); GUI.FocusWindow(window.windowID);
} }
else else
@ -123,26 +143,6 @@ namespace Explorer.UI
return new_window; return new_window;
} }
public static bool IsMouseInWindow
{
get
{
if (!ExplorerCore.ShowMenu)
{
return false;
}
foreach (var window in Windows)
{
if (RectContainsMouse(window.m_rect))
{
return true;
}
}
return RectContainsMouse(MainMenu.MainRect);
}
}
private static bool RectContainsMouse(Rect rect) private static bool RectContainsMouse(Rect rect)
{ {
var mousePos = InputManager.MousePosition; var mousePos = InputManager.MousePosition;

View File

@ -0,0 +1,183 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;
#if CPP
using Explorer.Unstrip.IMGUI;
#endif
namespace Explorer
{
// All the pre-processor directive stuff is in this class to keep it separate.
// This is so Mono build can use this class and not have to worry.
public class GUIHelper
{
internal static GUILayoutOption ExpandWidth(bool expand)
{
#if CPP
return GUIUnstrip.ExpandWidth(expand);
#else
return GUILayout.ExpandWidth(expand);
#endif
}
internal static GUILayoutOption ExpandHeight(bool expand)
{
#if CPP
return GUIUnstrip.ExpandHeight(expand);
#else
return GUILayout.ExpandHeight(expand);
#endif
}
public static void BeginHorizontal(params GUILayoutOption[] options)
=> BeginHorizontal(GUIContent.none, GUIStyle.none, options);
public static void BeginHorizontal(GUIStyle style, params GUILayoutOption[] options)
=> BeginHorizontal(GUIContent.none, style, options);
public static void BeginHorizontal(GUIContent content, GUIStyle style, params GUILayoutOption[] options)
{
#if CPP
GUIUnstrip.BeginLayoutDirection(false, content, style, options);
#else
GUILayout.BeginHorizontal(content, style, options);
#endif
}
public static void BeginVertical(params GUILayoutOption[] options)
=> BeginVertical(GUIContent.none, GUIStyle.none, options);
public static void BeginVertical(GUIStyle style, params GUILayoutOption[] options)
=> BeginVertical(GUIContent.none, style, options);
public static void BeginVertical(GUIContent content, GUIStyle style, params GUILayoutOption[] options)
{
#if CPP
GUIUnstrip.BeginLayoutDirection(true, content, style, options);
#else
GUILayout.BeginVertical(content, style, options);
#endif
}
public static Rect GetLastRect()
{
#if CPP
return LayoutUtilityUnstrip.GetLastRect();
#else
return GUILayoutUtility.GetLastRect();
#endif
}
public static string TextField(string text, GUILayoutOption[] options)
{
#if CPP
return GUIUnstrip.TextField(text, options, false);
#else
return GUILayout.TextField(text, options);
#endif
}
public static string TextArea(string text, params GUILayoutOption[] options)
{
#if CPP
return GUIUnstrip.TextField(text, options, true);
#else
return GUILayout.TextArea(text, options);
#endif
}
public static Rect Window(int id, Rect rect, GUI.WindowFunction windowFunc, string title)
{
#if CPP
return GUI.Window(id, rect, windowFunc, GUIContent.Temp(title), GUI.skin.window);
#else
return GUI.Window(id, rect, windowFunc, title);
#endif
}
public static bool Button(Rect rect, string title)
{
#if CPP
return GUI.Button(rect, GUIContent.Temp(title), GUI.skin.button);
#else
return GUI.Button(rect, title);
#endif
}
public static void BringWindowToFront(int id)
{
#if CPP
GUIUnstrip.BringWindowToFront(id);
#else
GUI.BringWindowToFront(id);
#endif
}
public static Vector2 ScreenToGUIPoint(Vector2 screenPoint)
{
#if CPP
return GUIUnstrip.ScreenToGUIPoint(screenPoint);
#else
return GUIUtility.ScreenToGUIPoint(screenPoint);
#endif
}
public static void Space(float pixels)
{
#if CPP
GUIUnstrip.Space(pixels);
#else
GUILayout.Space(pixels);
#endif
}
public static bool RepeatButton(string text, params GUILayoutOption[] options)
{
#if CPP
return GUIUnstrip.DoRepeatButton(GUIContent.Temp(text), GUI.skin.button, options);
#else
return GUILayout.RepeatButton(text, options);
#endif
}
public static void BeginArea(Rect screenRect, GUIStyle style)
{
#if CPP
GUIUnstrip.BeginArea(screenRect, GUIContent.none, style);
#else
GUILayout.BeginArea(screenRect, style);
#endif
}
static public void EndArea()
{
#if CPP
GUIUnstrip.EndArea();
#else
GUILayout.EndArea();
#endif
}
public static Vector2 BeginScrollView(Vector2 scroll, params GUILayoutOption[] options)
{
#if CPP
return GUIUnstrip.BeginScrollView(scroll, options);
#else
return GUILayout.BeginScrollView(scroll, options);
#endif
}
public static void EndScrollView(bool handleScrollWheel = true)
{
#if CPP
GUIUnstrip.EndScrollView(handleScrollWheel);
#else
GUILayout.EndScrollView();
#endif
}
}
}

View File

@ -1,162 +1,812 @@
using System; #if CPP
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection; using System.Reflection;
using UnityEngine; using UnityEngine;
#if CPP using UnityEngineInternal;
using Explorer.Unstrip.IMGUI; using UnhollowerRuntimeLib;
#endif
namespace Explorer namespace Explorer.Unstrip.IMGUI
{ {
public class GUIUnstrip public class GUIUnstrip
{ {
public static void BeginHorizontal(params GUILayoutOption[] options) #region Properties
=> BeginHorizontal(GUIContent.none, GUIStyle.none, options); public static int s_ScrollControlId;
public static void BeginHorizontal(GUIStyle style, params GUILayoutOption[] options) public static bool ScrollFailed = false;
=> BeginHorizontal(GUIContent.none, style, options); public static bool ManualUnstripFailed = false;
public static void BeginHorizontal(GUIContent content, GUIStyle style, params GUILayoutOption[] options) public static Stack<object> ScrollStack => m_scrollStack ?? GetScrollStack();
public static Stack<object> m_scrollStack;
//public static PropertyInfo m_scrollViewStatesInfo;
public static GUIStyle SpaceStyle => m_spaceStyle ?? GetSpaceStyle();
public static GUIStyle m_spaceStyle;
public static DateTime nextScrollStepTime;
public static MethodInfo ScreenToGuiPointMethod;
public static bool m_screenToGuiAttemped;
public static MethodInfo m_bringWindowToFrontMethod;
public static bool m_bringWindowFrontAttempted;
private static Stack<object> GetScrollStack()
{ {
#if CPP m_scrollStack = new Stack<object>();
Internal.BeginLayoutDirection(false, content, style, options);
#else return m_scrollStack;
GUILayout.BeginHorizontal(content, style, options);
#endif
} }
public static void BeginVertical(params GUILayoutOption[] options) private static GUIStyle GetSpaceStyle()
=> BeginVertical(GUIContent.none, GUIStyle.none, options);
public static void BeginVertical(GUIStyle style, params GUILayoutOption[] options)
=> BeginVertical(GUIContent.none, style, options);
public static void BeginVertical(GUIContent content, GUIStyle style, params GUILayoutOption[] options)
{ {
#if CPP try
Internal.BeginLayoutDirection(true, content, style, options); {
#else m_spaceStyle = typeof(GUILayoutUtility)
GUILayout.BeginVertical(content, style, options); .GetProperty("s_SpaceStyle")
#endif .GetValue(null, null)
.Il2CppCast(typeof(GUIStyle))
as GUIStyle;
if (m_spaceStyle == null) throw new Exception();
}
catch { }
if (m_spaceStyle == null)
{
m_spaceStyle = new GUIStyle();
}
m_spaceStyle.stretchWidth = false;
return m_spaceStyle;
} }
#endregion
public static Rect GetLastRect() #region GUILayout Methods
public static GUILayoutOption ExpandWidth(bool expand)
{ {
#if CPP var ilValue = new Il2CppSystem.Int32
return Internal_LayoutUtility.GetLastRect(); {
#else m_value = (!expand) ? 0 : 1
return GUILayoutUtility.GetLastRect(); };
#endif
var option = new GUILayoutOption(GUILayoutOption.Type.stretchWidth, ilValue.BoxIl2CppObject());
return option;
} }
public static string TextField(string text, GUILayoutOption[] options) public static GUILayoutOption ExpandHeight(bool expand)
{ {
#if CPP var ilValue = new Il2CppSystem.Int32
return Internal.TextField(text, options); {
#else m_value = (!expand) ? 0 : 1
return GUILayout.TextField(text, options); };
#endif
var option = new GUILayoutOption(GUILayoutOption.Type.stretchHeight, ilValue.BoxIl2CppObject());
return option;
} }
public static Rect Window(int id, Rect rect, GUI.WindowFunction windowFunc, string title) public static void BeginLayoutDirection(bool vertical, GUIContent content, GUIStyle style, GUILayoutOption[] options)
{ {
#if CPP var g = BeginLayoutGroup(style, options, Il2CppType.Of<GUILayoutGroup>());
return GUI.Window(id, rect, windowFunc, GUIContent.Temp(title), GUI.skin.window); g.isVertical = vertical;
#else if (style != GUIStyle.none || content != GUIContent.none)
return GUI.Window(id, rect, windowFunc, title); GUI.Box(g.rect, content, style);
#endif
} }
public static bool Button(Rect rect, string title) public static GUILayoutGroup BeginLayoutGroup(GUIStyle style, GUILayoutOption[] options, Il2CppSystem.Type layoutType)
{ {
#if CPP EventType type = Event.current.type;
return GUI.Button(rect, GUIContent.Temp(title), GUI.skin.button); GUILayoutGroup guilayoutGroup;
#else if (type != EventType.Used && type != EventType.Layout)
return GUI.Button(rect, title); {
#endif guilayoutGroup = GUILayoutUtility.current.topLevel.GetNext().TryCast<GUILayoutGroup>();
if (guilayoutGroup == null)
{
throw new ArgumentException("GUILayout: Mismatched LayoutGroup." + Event.current.type);
}
guilayoutGroup.ResetCursor();
}
else
{
guilayoutGroup = GUILayoutUtility.CreateGUILayoutGroupInstanceOfType(layoutType);
guilayoutGroup.style = style;
if (options != null)
{
guilayoutGroup.ApplyOptions(options);
}
GUILayoutUtility.current.topLevel.entries.Add(guilayoutGroup);
}
GUILayoutUtility.current.layoutGroups.Push(guilayoutGroup);
GUILayoutUtility.current.topLevel = guilayoutGroup;
return guilayoutGroup;
} }
public static string TextArea(string text, params GUILayoutOption[] options) public static string TextField(string text, GUILayoutOption[] options, bool multiLine)
{ {
#if CPP text = text ?? string.Empty;
return GUILayout.DoTextField(text, -1, true, GUI.skin.textArea, options);
#else var skin = multiLine ? GUI.skin.textArea : GUI.skin.textField;
return GUILayout.TextArea(text, options);
#endif int controlID = GUIUtility.GetControlID(FocusType.Keyboard);
GUIContent guicontent = GUIContent.Temp(text);
bool flag = GUIUtility.keyboardControl != controlID;
if (flag)
{
guicontent = GUIContent.Temp(text);
}
else
{
guicontent = GUIContent.Temp(text);
// guicontent = GUIContent.Temp(text + GUIUtility.compositionString);
}
Rect rect = LayoutUtilityUnstrip.GetRect(guicontent, skin, options);
bool flag2 = GUIUtility.keyboardControl == controlID;
if (flag2)
{
guicontent = GUIContent.Temp(text);
}
DoTextField(rect, controlID, guicontent, multiLine, -1, skin);
return guicontent.text;
} }
public static void BringWindowToFront(int id) internal static void DoTextField(Rect position, int id, GUIContent content, bool multiline, int maxLength, GUIStyle style)
{ {
#if CPP if (GUIUtilityUnstrip.GetMonoStateObject(typeof(TextEditorUnstrip), id) is TextEditorUnstrip textEditor)
Internal.BringWindowToFront(id); {
#else if (maxLength >= 0 && content.text.Length > maxLength)
GUI.BringWindowToFront(id); {
#endif content.text = content.text.Substring(0, maxLength);
}
textEditor.m_Content.text = content.text;
textEditor.SaveBackup();
textEditor.position = position;
textEditor.style = style;
textEditor.multiline = multiline;
textEditor.controlID = id;
textEditor.DetectFocusChange();
HandleTextFieldEventForDesktop(position, id, content, multiline, maxLength, style, textEditor);
textEditor.UpdateScrollOffsetIfNeeded(Event.current);
}
} }
public static Vector2 ScreenToGUIPoint(Vector2 screenPoint) private static void HandleTextFieldEventForDesktop(Rect position, int id, GUIContent content, bool multiline, int maxLength,
GUIStyle style, TextEditorUnstrip editor)
{ {
#if CPP var evt = Event.current;
return Internal.ScreenToGUIPoint(screenPoint);
#else bool change = false;
return GUIUtility.ScreenToGUIPoint(screenPoint); switch (evt.type)
#endif {
case EventType.MouseDown:
if (position.Contains(evt.mousePosition))
{
GUIUtility.hotControl = id;
GUIUtility.keyboardControl = id;
editor.m_HasFocus = true;
editor.MoveCursorToPosition(Event.current.mousePosition);
if (Event.current.clickCount == 2 && GUI.skin.settings.doubleClickSelectsWord)
{
editor.SelectCurrentWord();
editor.DblClickSnap(TextEditorUnstrip.DblClickSnapping.WORDS);
editor.MouseDragSelectsWholeWords(true);
}
if (Event.current.clickCount == 3 && GUI.skin.settings.tripleClickSelectsLine)
{
editor.SelectCurrentParagraph();
editor.MouseDragSelectsWholeWords(true);
editor.DblClickSnap(TextEditorUnstrip.DblClickSnapping.PARAGRAPHS);
}
evt.Use();
}
break;
case EventType.MouseDrag:
if (GUIUtility.hotControl == id)
{
if (evt.shift)
editor.MoveCursorToPosition(Event.current.mousePosition);
else
editor.SelectToPosition(Event.current.mousePosition);
evt.Use();
}
break;
case EventType.MouseUp:
if (GUIUtility.hotControl == id)
{
editor.MouseDragSelectsWholeWords(false);
GUIUtility.hotControl = 0;
evt.Use();
}
break;
case EventType.KeyDown:
if (GUIUtility.keyboardControl != id)
return;
if (editor.HandleKeyEvent(evt))
{
evt.Use();
change = true;
content.text = editor.text;
break;
}
// Ignore tab & shift-tab in textfields
if (evt.keyCode == KeyCode.Tab || evt.character == '\t')
return;
char c = evt.character;
if (c == '\n' && !multiline && !evt.alt)
return;
// Simplest test: only allow the character if the display font supports it.
Font font = style.font;
if (!font)
font = GUI.skin.font;
if (font.HasCharacter(c) || c == '\n')
{
editor.Insert(c);
change = true;
break;
}
// On windows, keypresses also send events with keycode but no character. Eat them up here.
if (c == 0)
{
// if we have a composition string, make sure we clear the previous selection.
if (InputManager.compositionString.Length > 0)
{
editor.ReplaceSelection("");
change = true;
}
evt.Use();
}
// else {
// REALLY USEFUL:
// Debug.Log ("unhandled " +evt);
// evt.Use ();
// }
break;
case EventType.Repaint:
// If we have keyboard focus, draw the cursor
// TODO: check if this OpenGL view has keyboard focus
if (GUIUtility.keyboardControl != id)
{
style.Draw(position, content, id, false);
}
else
{
editor.DrawCursor(content.text);
}
break;
}
if (GUIUtility.keyboardControl == id)
GUIUtility.textFieldInput = true;
if (change)
{
GUI.changed = true;
content.text = editor.text;
if (maxLength >= 0 && content.text.Length > maxLength)
content.text = content.text.Substring(0, maxLength);
evt.Use();
}
}
public static bool DoRepeatButton(GUIContent content, GUIStyle style, GUILayoutOption[] options)
{
return GUI.DoRepeatButton(LayoutUtilityUnstrip.GetRect(content, style, options), content, style, FocusType.Passive);
} }
public static void Space(float pixels) public static void Space(float pixels)
{ {
#if CPP if (GUILayoutUtility.current.topLevel.isVertical)
Internal.Space(pixels); LayoutUtilityUnstrip.GetRect(0, pixels, SpaceStyle, new GUILayoutOption[] { GUILayout.Height(pixels) });
#else else
GUILayout.Space(pixels); LayoutUtilityUnstrip.GetRect(pixels, 0, SpaceStyle, new GUILayoutOption[] { GUILayout.Width(pixels) });
#endif
if (Event.current.type == EventType.Layout)
{
GUILayoutUtility.current.topLevel.entries[GUILayoutUtility.current.topLevel.entries.Count - 1].consideredForMargin = false;
}
} }
public static bool RepeatButton(string text, params GUILayoutOption[] options) public static Vector2 ScreenToGUIPoint(Vector2 screenPoint)
{ {
#if CPP if (!m_screenToGuiAttemped)
return Internal.DoRepeatButton(GUIContent.Temp(text), GUI.skin.button, options); {
#else m_screenToGuiAttemped = true;
return GUILayout.RepeatButton(text, options); ScreenToGuiPointMethod = typeof(GUIUtility).GetMethod("ScreenToGUIPoint");
#endif }
if (ScreenToGuiPointMethod == null)
{
throw new Exception("Couldn't get method 'GUIUtility.ScreenToGUIPoint'!");
}
return (Vector2)ScreenToGuiPointMethod.Invoke(null, new object[] { screenPoint });
} }
public static void BeginArea(Rect screenRect, GUIStyle style) public static void BringWindowToFront(int id)
{ {
#if CPP if (!m_bringWindowFrontAttempted)
Internal.BeginArea(screenRect, GUIContent.none, style); {
#else m_bringWindowFrontAttempted = true;
GUILayout.BeginArea(screenRect, style); m_bringWindowToFrontMethod = typeof(GUI).GetMethod("BringWindowToFront");
#endif }
if (m_bringWindowToFrontMethod == null)
{
throw new Exception("Couldn't get method 'GUIUtility.BringWindowToFront'!");
}
m_bringWindowToFrontMethod.Invoke(null, new object[] { id });
} }
static public void EndArea() public static void BeginArea(Rect screenRect, GUIContent content, GUIStyle style)
{ {
#if CPP var g = BeginLayoutArea(style, typeof(GUILayoutGroup));
Internal.EndArea(); if (Event.current.type == EventType.Layout)
#else {
GUILayout.EndArea(); g.resetCoords = true;
#endif g.minWidth = g.maxWidth = screenRect.width;
g.minHeight = g.maxHeight = screenRect.height;
g.rect = Rect.MinMaxRect(screenRect.xMin, screenRect.yMin, g.rect.xMax, g.rect.yMax);
}
BeginGroup(g.rect, content, style);
} }
internal static GUILayoutGroup BeginLayoutArea(GUIStyle style, Type layoutType)
{
EventType type = Event.current.type;
GUILayoutGroup guilayoutGroup;
if (type != EventType.Used && type != EventType.Layout)
{
guilayoutGroup = GUILayoutUtility.current.windows.GetNext().TryCast<GUILayoutGroup>();
guilayoutGroup.ResetCursor();
}
else
{
guilayoutGroup = (GUILayoutGroup)Activator.CreateInstance(layoutType);
guilayoutGroup.style = style;
GUILayoutUtility.current.windows.entries.Add(guilayoutGroup);
}
GUILayoutUtility.current.layoutGroups.Push(guilayoutGroup);
GUILayoutUtility.current.topLevel = guilayoutGroup;
return guilayoutGroup;
}
public static void BeginGroup(Rect position, GUIContent content, GUIStyle style)
{
BeginGroup(position, content, style, Vector2.zero);
}
internal static void BeginGroup(Rect position, GUIContent content, GUIStyle style, Vector2 scrollOffset)
{
int id = GUIUtility.GetControlID(GUI.s_BeginGroupHash, FocusType.Passive);
if (content != GUIContent.none || style != GUIStyle.none)
{
switch (Event.current.type)
{
case EventType.Repaint:
style.Draw(position, content, id);
break;
default:
if (position.Contains(Event.current.mousePosition))
GUIUtility.mouseUsed = true;
break;
}
}
GUIClip.Push(position, scrollOffset, Vector2.zero, false);
}
public static void EndArea()
{
if (Event.current.type == EventType.Used)
return;
GUILayoutUtility.current.layoutGroups.Pop();
GUILayoutUtility.current.topLevel = GUILayoutUtility.current.layoutGroups.Peek().TryCast<GUILayoutGroup>();
GUI.EndGroup();
}
#endregion
#region Scrolling
public static Vector2 BeginScrollView(Vector2 scroll, params GUILayoutOption[] options) public static Vector2 BeginScrollView(Vector2 scroll, params GUILayoutOption[] options)
{ {
#if CPP // First, just try normal way, may not have been stripped or was unstripped successfully.
return Internal.BeginScrollView(scroll, options); if (!ScrollFailed)
#else {
return GUILayout.BeginScrollView(scroll, options); try
#endif {
return GUILayout.BeginScrollView(scroll, options);
}
catch
{
ScrollFailed = true;
}
}
// Try manual implementation.
if (!ManualUnstripFailed)
{
try
{
return BeginScrollView_ImplLayout(scroll,
false,
false,
GUI.skin.horizontalScrollbar,
GUI.skin.verticalScrollbar,
GUI.skin.scrollView,
options);
}
catch (Exception e)
{
ExplorerCore.Log("Exception on manual BeginScrollView: " + e.GetType() + ", " + e.Message + "\r\n" + e.StackTrace);
ManualUnstripFailed = true;
}
}
// Sorry! No scrolling for you.
return scroll;
} }
public static void EndScrollView(bool handleScrollWheel = true) internal static void EndScrollView(bool handleScrollWheel)
{ {
#if CPP // Only end the scroll view for the relevant BeginScrollView option, if any.
Internal.EndScrollView(handleScrollWheel);
#else if (!ScrollFailed)
GUILayout.EndScrollView(); {
#endif GUILayout.EndScrollView();
}
else if (!ManualUnstripFailed)
{
GUILayoutUtility.EndLayoutGroup();
if (ScrollStack.Count <= 0) return;
var scrollExt = ScrollStack.Peek() as ScrollViewStateUnstrip;
//var state = ScrollStack.Peek().TryCast<ScrollViewState>();
//var scrollExt = Internal_ScrollViewState.FromPointer(state.Pointer);
//if (scrollExt == null) throw new Exception("Could not get scrollExt!");
GUIClip.Pop();
ScrollStack.Pop();
var position = scrollExt.position;
if (handleScrollWheel && Event.current.type == EventType.ScrollWheel && position.Contains(Event.current.mousePosition))
{
var pos = scrollExt.scrollPosition;
pos.x = Mathf.Clamp(scrollExt.scrollPosition.x + Event.current.delta.x * 20f, 0f, scrollExt.viewRect.width - scrollExt.visibleRect.width);
pos.y = Mathf.Clamp(scrollExt.scrollPosition.y + Event.current.delta.y * 20f, 0f, scrollExt.viewRect.height - scrollExt.visibleRect.height);
if (scrollExt.scrollPosition.x < 0f)
{
pos.x = 0f;
}
if (pos.y < 0f)
{
pos.y = 0f;
}
scrollExt.apply = true;
Event.current.Use();
}
}
}
private static Vector2 BeginScrollView_ImplLayout(Vector2 scrollPosition, bool alwaysShowHorizontal, bool alwaysShowVertical,
GUIStyle horizontalScrollbar, GUIStyle verticalScrollbar, GUIStyle background, params GUILayoutOption[] options)
{
var guiscrollGroup = GUILayoutUtility.BeginLayoutGroup(background, null, Il2CppType.Of<GUIScrollGroup>())
.TryCast<GUIScrollGroup>();
EventType type = Event.current.type;
if (type == EventType.Layout)
{
guiscrollGroup.resetCoords = true;
guiscrollGroup.isVertical = true;
guiscrollGroup.stretchWidth = 1;
guiscrollGroup.stretchHeight = 1;
guiscrollGroup.verticalScrollbar = verticalScrollbar;
guiscrollGroup.horizontalScrollbar = horizontalScrollbar;
guiscrollGroup.needsVerticalScrollbar = alwaysShowVertical;
guiscrollGroup.needsHorizontalScrollbar = alwaysShowHorizontal;
guiscrollGroup.ApplyOptions(options);
}
return BeginScrollView_Impl(guiscrollGroup.rect,
scrollPosition,
new Rect(0f, 0f, guiscrollGroup.clientWidth, guiscrollGroup.clientHeight),
alwaysShowHorizontal,
alwaysShowVertical,
horizontalScrollbar,
verticalScrollbar,
background
);
}
private static Vector2 BeginScrollView_Impl(Rect position, Vector2 scrollPosition, Rect viewRect, bool alwaysShowHorizontal,
bool alwaysShowVertical, GUIStyle horizontalScrollbar, GUIStyle verticalScrollbar, GUIStyle background)
{
// GUIUtility.CheckOnGUI();
int controlID = GUIUtility.GetControlID(GUI.s_ScrollviewHash, FocusType.Passive);
ScrollViewStateUnstrip scrollExt;
try
{
scrollExt = (ScrollViewStateUnstrip)GUIUtilityUnstrip.GetMonoStateObject(typeof(ScrollViewStateUnstrip), controlID);
}
catch
{
return Vector2.zero;
}
bool apply = scrollExt.apply;
if (apply)
{
scrollPosition = scrollExt.scrollPosition;
scrollExt.apply = false;
}
scrollExt.position = position;
scrollExt.scrollPosition = scrollPosition;
scrollExt.visibleRect = scrollExt.viewRect = viewRect;
var rect = scrollExt.visibleRect;
rect.width = position.width;
rect.height = position.height;
ScrollStack.Push(scrollExt);
Rect screenRect = new Rect(position.x, position.y, position.width, position.height);
EventType type = Event.current.type;
if (type != EventType.Layout)
{
if (type != EventType.Used)
{
bool flag = alwaysShowVertical;
bool flag2 = alwaysShowHorizontal;
if (flag2 || viewRect.width > screenRect.width)
{
rect.height = position.height - horizontalScrollbar.fixedHeight + (float)horizontalScrollbar.margin.top;
screenRect.height -= horizontalScrollbar.fixedHeight + (float)horizontalScrollbar.margin.top;
flag2 = true;
}
if (flag || viewRect.height > screenRect.height)
{
rect.width = position.width - verticalScrollbar.fixedWidth + (float)verticalScrollbar.margin.left;
screenRect.width -= verticalScrollbar.fixedWidth + (float)verticalScrollbar.margin.left;
flag = true;
if (!flag2 && viewRect.width > screenRect.width)
{
rect.height = position.height - horizontalScrollbar.fixedHeight + (float)horizontalScrollbar.margin.top;
screenRect.height -= horizontalScrollbar.fixedHeight + (float)horizontalScrollbar.margin.top;
flag2 = true;
}
}
if (Event.current.type == EventType.Repaint && background != GUIStyle.none)
{
background.Draw(position, position.Contains(Event.current.mousePosition), false, flag2 && flag, false);
}
if (flag2 && horizontalScrollbar != GUIStyle.none)
{
scrollPosition.x = HorizontalScroll(
new Rect(
position.x,
position.yMax - horizontalScrollbar.fixedHeight,
screenRect.width,
horizontalScrollbar.fixedHeight),
scrollPosition.x,
Mathf.Min(screenRect.width, viewRect.width),
0f,
viewRect.width,
horizontalScrollbar
);
}
else
{
GUIUtility.GetControlID(GUI.s_SliderHash, FocusType.Passive);
GUIUtility.GetControlID(GUI.s_RepeatButtonHash, FocusType.Passive);
GUIUtility.GetControlID(GUI.s_RepeatButtonHash, FocusType.Passive);
scrollPosition.x = ((horizontalScrollbar == GUIStyle.none)
? Mathf.Clamp(scrollPosition.x, 0f, Mathf.Max(viewRect.width - position.width, 0f))
: 0f);
}
if (flag && verticalScrollbar != GUIStyle.none)
{
scrollPosition.y = VerticalScroll(
new Rect(
screenRect.xMax + (float)verticalScrollbar.margin.left,
screenRect.y,
verticalScrollbar.fixedWidth,
screenRect.height),
scrollPosition.y,
Mathf.Min(screenRect.height, viewRect.height),
0f,
viewRect.height,
verticalScrollbar
);
}
else
{
GUIUtility.GetControlID(GUI.s_SliderHash, FocusType.Passive);
GUIUtility.GetControlID(GUI.s_RepeatButtonHash, FocusType.Passive);
GUIUtility.GetControlID(GUI.s_RepeatButtonHash, FocusType.Passive);
scrollPosition.y = ((verticalScrollbar == GUIStyle.none)
? Mathf.Clamp(scrollPosition.y, 0f, Mathf.Max(viewRect.height - position.height, 0f))
: 0f);
}
}
}
else
{
GUIUtility.GetControlID(GUI.s_SliderHash, FocusType.Passive);
GUIUtility.GetControlID(GUI.s_RepeatButtonHash, FocusType.Passive);
GUIUtility.GetControlID(GUI.s_RepeatButtonHash, FocusType.Passive);
GUIUtility.GetControlID(GUI.s_SliderHash, FocusType.Passive);
GUIUtility.GetControlID(GUI.s_RepeatButtonHash, FocusType.Passive);
GUIUtility.GetControlID(GUI.s_RepeatButtonHash, FocusType.Passive);
}
GUIClip.Push(screenRect,
new Vector2(
Mathf.Round(-scrollPosition.x - viewRect.x),
Mathf.Round(-scrollPosition.y - viewRect.y)),
Vector2.zero,
false
);
return scrollPosition;
}
public static float HorizontalScroll(Rect position, float value, float size, float leftValue, float rightValue, GUIStyle style)
{
return Scroller(position, value, size, leftValue, rightValue, style,
GUI.skin.GetStyle(style.name + "thumb"),
GUI.skin.GetStyle(style.name + "leftbutton"),
GUI.skin.GetStyle(style.name + "rightbutton"),
true);
}
public static float VerticalScroll(Rect position, float value, float size, float topValue, float bottomValue, GUIStyle style)
{
return Scroller(position, value, size, topValue, bottomValue, style,
GUI.skin.GetStyle(style.name + "thumb"),
GUI.skin.GetStyle(style.name + "upbutton"),
GUI.skin.GetStyle(style.name + "downbutton"),
false);
}
private static float Scroller(Rect position, float value, float size, float leftValue, float rightValue, GUIStyle slider,
GUIStyle thumb, GUIStyle leftButton, GUIStyle rightButton, bool horiz)
{
GUIUtility.CheckOnGUI();
int controlID = GUIUtility.GetControlID(GUI.s_SliderHash, FocusType.Passive, position);
Rect position2;
Rect rect;
Rect rect2;
if (horiz)
{
position2 = new Rect(position.x + leftButton.fixedWidth,
position.y,
position.width - leftButton.fixedWidth - rightButton.fixedWidth,
position.height);
rect = new Rect(position.x, position.y, leftButton.fixedWidth, position.height);
rect2 = new Rect(position.xMax - rightButton.fixedWidth, position.y, rightButton.fixedWidth, position.height);
}
else
{
position2 = new Rect(position.x,
position.y + leftButton.fixedHeight,
position.width,
position.height - leftButton.fixedHeight - rightButton.fixedHeight);
rect = new Rect(position.x, position.y, position.width, leftButton.fixedHeight);
rect2 = new Rect(position.x, position.yMax - rightButton.fixedHeight, position.width, rightButton.fixedHeight);
}
value = Slider(position2, value, size, leftValue, rightValue, slider, thumb, horiz, controlID);
bool flag = Event.current.type == EventType.MouseUp;
if (ScrollerRepeatButton(controlID, rect, leftButton))
{
value -= 10f * ((leftValue >= rightValue) ? -1f : 1f);
}
if (ScrollerRepeatButton(controlID, rect2, rightButton))
{
value += 10f * ((leftValue >= rightValue) ? -1f : 1f);
}
if (flag && Event.current.type == EventType.Used)
{
s_ScrollControlId = 0;
}
if (leftValue < rightValue)
{
value = Mathf.Clamp(value, leftValue, rightValue - size);
}
else
{
value = Mathf.Clamp(value, rightValue, leftValue - size);
}
return value;
}
public static float Slider(Rect position, float value, float size, float start, float end, GUIStyle slider,
GUIStyle thumb, bool horiz, int id)
{
if (id == 0)
{
id = GUIUtility.GetControlID(GUI.s_SliderHash, FocusType.Passive, position);
}
var sliderHandler = new SliderHandlerUnstrip(position, value, size, start, end, slider, thumb, horiz, id);
return sliderHandler.Handle();
}
private static bool ScrollerRepeatButton(int scrollerID, Rect rect, GUIStyle style)
{
bool result = false;
if (GUI.DoRepeatButton(rect, GUIContent.none, style, FocusType.Passive))
{
bool flag = s_ScrollControlId != scrollerID;
s_ScrollControlId = scrollerID;
if (flag)
{
result = true;
nextScrollStepTime = DateTime.Now.AddMilliseconds(250.0);
}
else if (DateTime.Now >= nextScrollStepTime)
{
result = true;
nextScrollStepTime = DateTime.Now.AddMilliseconds(30.0);
}
if (Event.current.type == EventType.Repaint)
{
GUI.InternalRepaintEditorWindow();
}
}
return result;
}
#endregion
}
#region Extensions
public static class Extensions
{
public static Rect Unstripped_GetLast(this GUILayoutGroup group)
{
Rect result;
if (group.m_Cursor > 0 && group.m_Cursor <= group.entries.Count)
{
GUILayoutEntry guilayoutEntry = group.entries[group.m_Cursor - 1];
result = guilayoutEntry.rect;
}
else
{
result = GUILayoutEntry.kDummyRect;
}
return result;
} }
} }
}
#endregion
}
#endif

View File

@ -0,0 +1,67 @@
#if CPP
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using Explorer.Helpers;
namespace Explorer.Unstrip.IMGUI
{
public class GUIUtilityUnstrip
{
public static Dictionary<int, object> MonoStateCache = new Dictionary<int, object>();
public static object GetMonoStateObject(Type type, int controlID)
{
if (!MonoStateCache.ContainsKey(controlID))
{
MonoStateCache.Add(controlID, Activator.CreateInstance(type));
}
return MonoStateCache[controlID];
}
public static Dictionary<int, Il2CppSystem.Object> StateCache => m_stateCacheDict ?? GetStateCacheDict();
public static Dictionary<int, Il2CppSystem.Object> m_stateCacheDict;
public static Il2CppSystem.Object GetStateObject(Il2CppSystem.Type type, int controlID)
{
Il2CppSystem.Object obj;
if (StateCache.ContainsKey(controlID))
{
obj = StateCache[controlID];
}
else
{
obj = Il2CppSystem.Activator.CreateInstance(type);
StateCache.Add(controlID, obj);
}
return obj;
}
private static Dictionary<int, Il2CppSystem.Object> GetStateCacheDict()
{
if (m_stateCacheDict == null)
{
try
{
m_stateCacheDict = ReflectionHelpers.GetTypeByName("UnityEngine.GUIStateObjects")
.GetProperty("s_StateCache")
.GetValue(null, null)
as Dictionary<int, Il2CppSystem.Object>;
if (m_stateCacheDict == null) throw new Exception();
}
catch
{
m_stateCacheDict = new Dictionary<int, Il2CppSystem.Object>();
}
}
return m_stateCacheDict;
}
}
}
#endif

View File

@ -1,688 +0,0 @@
#if CPP
using System;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;
using UnityEngineInternal;
using UnhollowerRuntimeLib;
namespace Explorer.Unstrip.IMGUI
{
public class Internal
{
#region Properties
public static int s_ScrollControlId;
public static bool ScrollFailed = false;
public static bool ManualUnstripFailed = false;
public static GenericStack ScrollStack => m_scrollStack ?? GetScrollStack();
public static PropertyInfo m_scrollViewStatesInfo;
public static GenericStack m_scrollStack;
public static Dictionary<int, Il2CppSystem.Object> StateCache => m_stateCacheDict ?? GetStateCacheDict();
public static Dictionary<int, Il2CppSystem.Object> m_stateCacheDict;
public static GUIStyle SpaceStyle => m_spaceStyle ?? GetSpaceStyle();
public static GUIStyle m_spaceStyle;
public static DateTime nextScrollStepTime;
public static MethodInfo ScreenToGuiPointMethod;
public static bool m_screenToGuiAttemped;
public static MethodInfo m_bringWindowToFrontMethod;
public static bool m_bringWindowFrontAttempted;
private static GenericStack GetScrollStack()
{
if (m_scrollViewStatesInfo == null)
{
if (typeof(GUI).GetProperty("scrollViewStates", ReflectionHelpers.CommonFlags) is PropertyInfo scrollStatesInfo)
{
m_scrollViewStatesInfo = scrollStatesInfo;
}
else if (typeof(GUI).GetProperty("s_ScrollViewStates", ReflectionHelpers.CommonFlags) is PropertyInfo s_scrollStatesInfo)
{
m_scrollViewStatesInfo = s_scrollStatesInfo;
}
}
if (m_scrollViewStatesInfo?.GetValue(null, null) is GenericStack stack)
{
m_scrollStack = stack;
}
else
{
m_scrollStack = new GenericStack();
}
return m_scrollStack;
}
private static Dictionary<int, Il2CppSystem.Object> GetStateCacheDict()
{
if (m_stateCacheDict == null)
{
try
{
var type = ReflectionHelpers.GetTypeByName("UnityEngine.GUIStateObjects");
m_stateCacheDict = type.GetProperty("s_StateCache")
.GetValue(null, null)
as Dictionary<int, Il2CppSystem.Object>;
if (m_stateCacheDict == null) throw new Exception();
}
catch
{
m_stateCacheDict = new Dictionary<int, Il2CppSystem.Object>();
}
}
return m_stateCacheDict;
}
private static GUIStyle GetSpaceStyle()
{
try
{
m_spaceStyle = typeof(GUILayoutUtility)
.GetProperty("s_SpaceStyle")
.GetValue(null, null)
.Il2CppCast(typeof(GUIStyle))
as GUIStyle;
if (m_spaceStyle == null) throw new Exception();
}
catch { }
if (m_spaceStyle == null)
{
m_spaceStyle = new GUIStyle();
}
m_spaceStyle.stretchWidth = false;
return m_spaceStyle;
}
#endregion
#region GUILayout Methods
public static void BeginLayoutDirection(bool vertical, GUIContent content, GUIStyle style, GUILayoutOption[] options)
{
var g = GUILayoutUtility.BeginLayoutGroup(style, options, Il2CppType.Of<GUILayoutGroup>());
g.isVertical = vertical;
if (style != GUIStyle.none || content != GUIContent.none)
GUI.Box(g.rect, content, style);
}
public static string TextField(string text, GUILayoutOption[] options)
{
text = text ?? string.Empty;
int controlID = GUIUtility.GetControlID(FocusType.Keyboard);
GUIContent guicontent = GUIContent.Temp(text);
bool flag = GUIUtility.keyboardControl != controlID;
if (flag)
{
guicontent = GUIContent.Temp(text);
}
else
{
guicontent = GUIContent.Temp(text);
// guicontent = GUIContent.Temp(text + GUIUtility.compositionString);
}
Rect rect = Internal_LayoutUtility.GetRect(guicontent, GUI.skin.textField, options);
bool flag2 = GUIUtility.keyboardControl == controlID;
if (flag2)
{
guicontent = GUIContent.Temp(text);
}
DoTextField(rect, controlID, guicontent, false, -1, GUI.skin.textField);
return guicontent.text;
}
internal static void DoTextField(Rect position, int id, GUIContent content, bool multiline, int maxLength, GUIStyle style)
{
if (GetStateObject(Il2CppType.Of<TextEditor>(), id).TryCast<TextEditor>() is TextEditor textEditor)
{
if (maxLength >= 0 && content.text.Length > maxLength)
{
content.text = content.text.Substring(0, maxLength);
}
textEditor.m_Content.text = content.text;
textEditor.SaveBackup();
textEditor.position = position;
textEditor.style = style;
textEditor.multiline = multiline;
textEditor.controlID = id;
textEditor.DetectFocusChange();
GUI.HandleTextFieldEventForDesktop(position, id, content, multiline, maxLength, style, textEditor);
textEditor.UpdateScrollOffsetIfNeeded(Event.current);
}
}
public static bool DoRepeatButton(GUIContent content, GUIStyle style, GUILayoutOption[] options)
{
return GUI.DoRepeatButton(Internal_LayoutUtility.GetRect(content, style, options), content, style, FocusType.Passive);
}
public static void Space(float pixels)
{
if (GUILayoutUtility.current.topLevel.isVertical)
Internal_LayoutUtility.GetRect(0, pixels, SpaceStyle, new GUILayoutOption[] { GUILayout.Height(pixels) });
else
Internal_LayoutUtility.GetRect(pixels, 0, SpaceStyle, new GUILayoutOption[] { GUILayout.Width(pixels) });
if (Event.current.type == EventType.Layout)
{
GUILayoutUtility.current.topLevel.entries[GUILayoutUtility.current.topLevel.entries.Count - 1].consideredForMargin = false;
}
}
public static Vector2 ScreenToGUIPoint(Vector2 screenPoint)
{
if (!m_screenToGuiAttemped)
{
m_screenToGuiAttemped = true;
ScreenToGuiPointMethod = typeof(GUIUtility).GetMethod("ScreenToGUIPoint");
}
if (ScreenToGuiPointMethod == null)
{
throw new Exception("Couldn't get method 'GUIUtility.ScreenToGUIPoint'!");
}
return (Vector2)ScreenToGuiPointMethod.Invoke(null, new object[] { screenPoint });
}
public static void BringWindowToFront(int id)
{
if (!m_bringWindowFrontAttempted)
{
m_bringWindowFrontAttempted = true;
m_bringWindowToFrontMethod = typeof(GUI).GetMethod("BringWindowToFront");
}
if (m_bringWindowToFrontMethod == null)
{
throw new Exception("Couldn't get method 'GUIUtility.BringWindowToFront'!");
}
m_bringWindowToFrontMethod.Invoke(null, new object[] { id });
}
public static void BeginArea(Rect screenRect, GUIContent content, GUIStyle style)
{
var g = BeginLayoutArea(style, typeof(GUILayoutGroup));
if (Event.current.type == EventType.Layout)
{
g.resetCoords = true;
g.minWidth = g.maxWidth = screenRect.width;
g.minHeight = g.maxHeight = screenRect.height;
g.rect = Rect.MinMaxRect(screenRect.xMin, screenRect.yMin, g.rect.xMax, g.rect.yMax);
}
BeginGroup(g.rect, content, style);
}
internal static GUILayoutGroup BeginLayoutArea(GUIStyle style, Type layoutType)
{
EventType type = Event.current.type;
GUILayoutGroup guilayoutGroup;
if (type != EventType.Used && type != EventType.Layout)
{
guilayoutGroup = GUILayoutUtility.current.windows.GetNext().TryCast<GUILayoutGroup>();
guilayoutGroup.ResetCursor();
}
else
{
guilayoutGroup = (GUILayoutGroup)Activator.CreateInstance(layoutType);
guilayoutGroup.style = style;
GUILayoutUtility.current.windows.Add(guilayoutGroup);
}
GUILayoutUtility.current.layoutGroups.Push(guilayoutGroup);
GUILayoutUtility.current.topLevel = guilayoutGroup;
return guilayoutGroup;
}
public static void BeginGroup(Rect position, GUIContent content, GUIStyle style)
{
BeginGroup(position, content, style, Vector2.zero);
}
internal static void BeginGroup(Rect position, GUIContent content, GUIStyle style, Vector2 scrollOffset)
{
int id = GUIUtility.GetControlID(GUI.s_BeginGroupHash, FocusType.Passive);
if (content != GUIContent.none || style != GUIStyle.none)
{
switch (Event.current.type)
{
case EventType.Repaint:
style.Draw(position, content, id);
break;
default:
if (position.Contains(Event.current.mousePosition))
GUIUtility.mouseUsed = true;
break;
}
}
GUIClip.Push(position, scrollOffset, Vector2.zero, false);
}
public static void EndArea()
{
if (Event.current.type == EventType.Used)
return;
GUILayoutUtility.current.layoutGroups.Pop();
GUILayoutUtility.current.topLevel = GUILayoutUtility.current.layoutGroups.Peek().TryCast<GUILayoutGroup>();
GUI.EndGroup();
}
#endregion
#region Scrolling
private static Il2CppSystem.Object GetStateObject(Il2CppSystem.Type type, int controlID)
{
Il2CppSystem.Object obj;
if (StateCache.ContainsKey(controlID))
{
obj = StateCache[controlID];
}
else
{
obj = Il2CppSystem.Activator.CreateInstance(type);
StateCache.Add(controlID, obj);
}
return obj;
}
public static Vector2 BeginScrollView(Vector2 scroll, params GUILayoutOption[] options)
{
// First, just try normal way, may not have been stripped or was unstripped successfully.
if (!ScrollFailed)
{
try
{
return GUILayout.BeginScrollView(scroll, options);
}
catch
{
ScrollFailed = true;
}
}
// Try manual implementation.
if (!ManualUnstripFailed)
{
try
{
return BeginScrollView_ImplLayout(scroll,
false,
false,
GUI.skin.horizontalScrollbar,
GUI.skin.verticalScrollbar,
GUI.skin.scrollView,
options);
}
catch (Exception e)
{
ExplorerCore.Log("Exception on manual BeginScrollView: " + e.GetType() + ", " + e.Message + "\r\n" + e.StackTrace);
ManualUnstripFailed = true;
}
}
// Sorry! No scrolling for you.
return scroll;
}
internal static void EndScrollView(bool handleScrollWheel)
{
// Only end the scroll view for the relevant BeginScrollView option, if any.
if (!ScrollFailed)
{
GUILayout.EndScrollView();
}
else if (!ManualUnstripFailed)
{
GUILayoutUtility.EndLayoutGroup();
if (ScrollStack.Count <= 0) return;
var state = ScrollStack.Peek().TryCast<ScrollViewState>();
var scrollExt = Internal_ScrollViewState.FromPointer(state.Pointer);
if (scrollExt == null) throw new Exception("Could not get scrollExt!");
GUIClip.Pop();
ScrollStack.Pop();
var position = scrollExt.position;
if (handleScrollWheel && Event.current.type == EventType.ScrollWheel && position.Contains(Event.current.mousePosition))
{
var pos = scrollExt.scrollPosition;
pos.x = Mathf.Clamp(scrollExt.scrollPosition.x + Event.current.delta.x * 20f, 0f, scrollExt.viewRect.width - scrollExt.visibleRect.width);
pos.y = Mathf.Clamp(scrollExt.scrollPosition.y + Event.current.delta.y * 20f, 0f, scrollExt.viewRect.height - scrollExt.visibleRect.height);
if (scrollExt.scrollPosition.x < 0f)
{
pos.x = 0f;
}
if (pos.y < 0f)
{
pos.y = 0f;
}
scrollExt.apply = true;
Event.current.Use();
}
}
}
private static Vector2 BeginScrollView_ImplLayout(Vector2 scrollPosition, bool alwaysShowHorizontal, bool alwaysShowVertical,
GUIStyle horizontalScrollbar, GUIStyle verticalScrollbar, GUIStyle background, params GUILayoutOption[] options)
{
var guiscrollGroup = GUILayoutUtility.BeginLayoutGroup(background, null, Il2CppType.Of<GUIScrollGroup>())
.TryCast<GUIScrollGroup>();
EventType type = Event.current.type;
if (type == EventType.Layout)
{
guiscrollGroup.resetCoords = true;
guiscrollGroup.isVertical = true;
guiscrollGroup.stretchWidth = 1;
guiscrollGroup.stretchHeight = 1;
guiscrollGroup.verticalScrollbar = verticalScrollbar;
guiscrollGroup.horizontalScrollbar = horizontalScrollbar;
guiscrollGroup.needsVerticalScrollbar = alwaysShowVertical;
guiscrollGroup.needsHorizontalScrollbar = alwaysShowHorizontal;
guiscrollGroup.ApplyOptions(options);
}
return BeginScrollView_Impl(guiscrollGroup.rect,
scrollPosition,
new Rect(0f, 0f, guiscrollGroup.clientWidth, guiscrollGroup.clientHeight),
alwaysShowHorizontal,
alwaysShowVertical,
horizontalScrollbar,
verticalScrollbar,
background
);
}
private static Vector2 BeginScrollView_Impl(Rect position, Vector2 scrollPosition, Rect viewRect, bool alwaysShowHorizontal,
bool alwaysShowVertical, GUIStyle horizontalScrollbar, GUIStyle verticalScrollbar, GUIStyle background)
{
// GUIUtility.CheckOnGUI();
int controlID = GUIUtility.GetControlID(GUI.s_ScrollviewHash, FocusType.Passive);
var scrollViewState = GetStateObject(Il2CppType.Of<ScrollViewState>(), controlID)
.TryCast<ScrollViewState>();
if (scrollViewState == null)
return scrollPosition;
var scrollExt = Internal_ScrollViewState.FromPointer(scrollViewState.Pointer);
if (scrollExt == null)
return scrollPosition;
bool apply = scrollExt.apply;
if (apply)
{
scrollPosition = scrollExt.scrollPosition;
scrollExt.apply = false;
}
scrollExt.position = position;
scrollExt.scrollPosition = scrollPosition;
scrollExt.visibleRect = scrollExt.viewRect = viewRect;
var rect = scrollExt.visibleRect;
rect.width = position.width;
rect.height = position.height;
ScrollStack.Push(scrollViewState);
Rect screenRect = new Rect(position.x, position.y, position.width, position.height);
EventType type = Event.current.type;
if (type != EventType.Layout)
{
if (type != EventType.Used)
{
bool flag = alwaysShowVertical;
bool flag2 = alwaysShowHorizontal;
if (flag2 || viewRect.width > screenRect.width)
{
rect.height = position.height - horizontalScrollbar.fixedHeight + (float)horizontalScrollbar.margin.top;
screenRect.height -= horizontalScrollbar.fixedHeight + (float)horizontalScrollbar.margin.top;
flag2 = true;
}
if (flag || viewRect.height > screenRect.height)
{
rect.width = position.width - verticalScrollbar.fixedWidth + (float)verticalScrollbar.margin.left;
screenRect.width -= verticalScrollbar.fixedWidth + (float)verticalScrollbar.margin.left;
flag = true;
if (!flag2 && viewRect.width > screenRect.width)
{
rect.height = position.height - horizontalScrollbar.fixedHeight + (float)horizontalScrollbar.margin.top;
screenRect.height -= horizontalScrollbar.fixedHeight + (float)horizontalScrollbar.margin.top;
flag2 = true;
}
}
if (Event.current.type == EventType.Repaint && background != GUIStyle.none)
{
background.Draw(position, position.Contains(Event.current.mousePosition), false, flag2 && flag, false);
}
if (flag2 && horizontalScrollbar != GUIStyle.none)
{
scrollPosition.x = HorizontalScroll(
new Rect(
position.x,
position.yMax - horizontalScrollbar.fixedHeight,
screenRect.width,
horizontalScrollbar.fixedHeight),
scrollPosition.x,
Mathf.Min(screenRect.width, viewRect.width),
0f,
viewRect.width,
horizontalScrollbar
);
}
else
{
GUIUtility.GetControlID(GUI.s_SliderHash, FocusType.Passive);
GUIUtility.GetControlID(GUI.s_RepeatButtonHash, FocusType.Passive);
GUIUtility.GetControlID(GUI.s_RepeatButtonHash, FocusType.Passive);
scrollPosition.x = ((horizontalScrollbar == GUIStyle.none)
? Mathf.Clamp(scrollPosition.x, 0f, Mathf.Max(viewRect.width - position.width, 0f))
: 0f);
}
if (flag && verticalScrollbar != GUIStyle.none)
{
scrollPosition.y = VerticalScroll(
new Rect(
screenRect.xMax + (float)verticalScrollbar.margin.left,
screenRect.y,
verticalScrollbar.fixedWidth,
screenRect.height),
scrollPosition.y,
Mathf.Min(screenRect.height, viewRect.height),
0f,
viewRect.height,
verticalScrollbar
);
}
else
{
GUIUtility.GetControlID(GUI.s_SliderHash, FocusType.Passive);
GUIUtility.GetControlID(GUI.s_RepeatButtonHash, FocusType.Passive);
GUIUtility.GetControlID(GUI.s_RepeatButtonHash, FocusType.Passive);
scrollPosition.y = ((verticalScrollbar == GUIStyle.none)
? Mathf.Clamp(scrollPosition.y, 0f, Mathf.Max(viewRect.height - position.height, 0f))
: 0f);
}
}
}
else
{
GUIUtility.GetControlID(GUI.s_SliderHash, FocusType.Passive);
GUIUtility.GetControlID(GUI.s_RepeatButtonHash, FocusType.Passive);
GUIUtility.GetControlID(GUI.s_RepeatButtonHash, FocusType.Passive);
GUIUtility.GetControlID(GUI.s_SliderHash, FocusType.Passive);
GUIUtility.GetControlID(GUI.s_RepeatButtonHash, FocusType.Passive);
GUIUtility.GetControlID(GUI.s_RepeatButtonHash, FocusType.Passive);
}
GUIClip.Push(screenRect,
new Vector2(
Mathf.Round(-scrollPosition.x - viewRect.x),
Mathf.Round(-scrollPosition.y - viewRect.y)),
Vector2.zero,
false
);
return scrollPosition;
}
public static float HorizontalScroll(Rect position, float value, float size, float leftValue, float rightValue, GUIStyle style)
{
return Scroller(position, value, size, leftValue, rightValue, style,
GUI.skin.GetStyle(style.name + "thumb"),
GUI.skin.GetStyle(style.name + "leftbutton"),
GUI.skin.GetStyle(style.name + "rightbutton"),
true);
}
public static float VerticalScroll(Rect position, float value, float size, float topValue, float bottomValue, GUIStyle style)
{
return Scroller(position, value, size, topValue, bottomValue, style,
GUI.skin.GetStyle(style.name + "thumb"),
GUI.skin.GetStyle(style.name + "upbutton"),
GUI.skin.GetStyle(style.name + "downbutton"),
false);
}
private static float Scroller(Rect position, float value, float size, float leftValue, float rightValue, GUIStyle slider,
GUIStyle thumb, GUIStyle leftButton, GUIStyle rightButton, bool horiz)
{
GUIUtility.CheckOnGUI();
int controlID = GUIUtility.GetControlID(GUI.s_SliderHash, FocusType.Passive, position);
Rect position2;
Rect rect;
Rect rect2;
if (horiz)
{
position2 = new Rect(position.x + leftButton.fixedWidth,
position.y,
position.width - leftButton.fixedWidth - rightButton.fixedWidth,
position.height);
rect = new Rect(position.x, position.y, leftButton.fixedWidth, position.height);
rect2 = new Rect(position.xMax - rightButton.fixedWidth, position.y, rightButton.fixedWidth, position.height);
}
else
{
position2 = new Rect(position.x,
position.y + leftButton.fixedHeight,
position.width,
position.height - leftButton.fixedHeight - rightButton.fixedHeight);
rect = new Rect(position.x, position.y, position.width, leftButton.fixedHeight);
rect2 = new Rect(position.x, position.yMax - rightButton.fixedHeight, position.width, rightButton.fixedHeight);
}
value = Slider(position2, value, size, leftValue, rightValue, slider, thumb, horiz, controlID);
bool flag = Event.current.type == EventType.MouseUp;
if (ScrollerRepeatButton(controlID, rect, leftButton))
{
value -= 10f * ((leftValue >= rightValue) ? -1f : 1f);
}
if (ScrollerRepeatButton(controlID, rect2, rightButton))
{
value += 10f * ((leftValue >= rightValue) ? -1f : 1f);
}
if (flag && Event.current.type == EventType.Used)
{
s_ScrollControlId = 0;
}
if (leftValue < rightValue)
{
value = Mathf.Clamp(value, leftValue, rightValue - size);
}
else
{
value = Mathf.Clamp(value, rightValue, leftValue - size);
}
return value;
}
public static float Slider(Rect position, float value, float size, float start, float end, GUIStyle slider,
GUIStyle thumb, bool horiz, int id)
{
if (id == 0)
{
id = GUIUtility.GetControlID(GUI.s_SliderHash, FocusType.Passive, position);
}
var sliderHandler = new Internal_SliderHandler(position, value, size, start, end, slider, thumb, horiz, id);
return sliderHandler.Handle();
}
private static bool ScrollerRepeatButton(int scrollerID, Rect rect, GUIStyle style)
{
bool result = false;
if (GUI.DoRepeatButton(rect, GUIContent.none, style, FocusType.Passive))
{
bool flag = s_ScrollControlId != scrollerID;
s_ScrollControlId = scrollerID;
if (flag)
{
result = true;
nextScrollStepTime = DateTime.Now.AddMilliseconds(250.0);
}
else if (DateTime.Now >= nextScrollStepTime)
{
result = true;
nextScrollStepTime = DateTime.Now.AddMilliseconds(30.0);
}
if (Event.current.type == EventType.Repaint)
{
GUI.InternalRepaintEditorWindow();
}
}
return result;
}
#endregion
}
#region Extensions
public static class Extensions
{
public static Rect Unstripped_GetLast(this GUILayoutGroup group)
{
Rect result;
if (group.m_Cursor > 0 && group.m_Cursor <= group.entries.Count)
{
GUILayoutEntry guilayoutEntry = group.entries[group.m_Cursor - 1];
result = guilayoutEntry.rect;
}
else
{
result = GUILayoutEntry.kDummyRect;
}
return result;
}
}
#endregion
}
#endif

View File

@ -1,29 +0,0 @@
#if CPP
using System;
using System.Collections.Generic;
using UnityEngine;
namespace Explorer.Unstrip.IMGUI
{
public class Internal_ScrollViewState
{
public Rect position;
public Rect visibleRect;
public Rect viewRect;
public Vector2 scrollPosition;
public bool apply;
public static Dictionary<IntPtr, Internal_ScrollViewState> Dict = new Dictionary<IntPtr, Internal_ScrollViewState>();
public static Internal_ScrollViewState FromPointer(IntPtr ptr)
{
if (!Dict.ContainsKey(ptr))
{
Dict.Add(ptr, new Internal_ScrollViewState());
}
return Dict[ptr];
}
}
}
#endif

View File

@ -1,26 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Explorer.Unstrip.IMGUI
{
public class Internal_SliderState
{
public float dragStartPos;
public float dragStartValue;
public bool isDragging;
public static Dictionary<IntPtr, Internal_SliderState> Dict = new Dictionary<IntPtr, Internal_SliderState>();
public static Internal_SliderState FromPointer(IntPtr ptr)
{
if (!Dict.ContainsKey(ptr))
{
Dict.Add(ptr, new Internal_SliderState());
}
return Dict[ptr];
}
}
}

View File

@ -3,7 +3,7 @@ using UnityEngine;
namespace Explorer.Unstrip.IMGUI namespace Explorer.Unstrip.IMGUI
{ {
public class Internal_LayoutUtility public class LayoutUtilityUnstrip
{ {
public static Rect GetRect(float width, float height, GUIStyle style, params GUILayoutOption[] options) public static Rect GetRect(float width, float height, GUIStyle style, params GUILayoutOption[] options)
{ {

View File

@ -0,0 +1,89 @@
#if CPP
using System;
using System.Collections.Generic;
using UnityEngine;
namespace Explorer.Unstrip.IMGUI
{
public class ScrollViewStateUnstrip
{
public Rect position;
public Rect visibleRect;
public Rect viewRect;
public Vector2 scrollPosition;
public bool apply;
public void ScrollTo(Rect pos)
{
this.ScrollTowards(pos, float.PositiveInfinity);
}
public bool ScrollTowards(Rect pos, float maxDelta)
{
Vector2 b = this.ScrollNeeded(pos);
bool result;
if (b.sqrMagnitude < 0.0001f)
{
result = false;
}
else if (maxDelta == 0f)
{
result = true;
}
else
{
if (b.magnitude > maxDelta)
{
b = b.normalized * maxDelta;
}
this.scrollPosition += b;
this.apply = true;
result = true;
}
return result;
}
private Vector2 ScrollNeeded(Rect pos)
{
Rect rect = this.visibleRect;
rect.x += this.scrollPosition.x;
rect.y += this.scrollPosition.y;
float num = pos.width - this.visibleRect.width;
if (num > 0f)
{
pos.width -= num;
pos.x += num * 0.5f;
}
num = pos.height - this.visibleRect.height;
if (num > 0f)
{
pos.height -= num;
pos.y += num * 0.5f;
}
Vector2 zero = Vector2.zero;
if (pos.xMax > rect.xMax)
{
zero.x += pos.xMax - rect.xMax;
}
else if (pos.xMin < rect.xMin)
{
zero.x -= rect.xMin - pos.xMin;
}
if (pos.yMax > rect.yMax)
{
zero.y += pos.yMax - rect.yMax;
}
else if (pos.yMin < rect.yMin)
{
zero.y -= rect.yMin - pos.yMin;
}
Rect rect2 = this.viewRect;
rect2.width = Mathf.Max(rect2.width, this.visibleRect.width);
rect2.height = Mathf.Max(rect2.height, this.visibleRect.height);
zero.x = Mathf.Clamp(zero.x, rect2.xMin - this.scrollPosition.x, rect2.xMax - this.visibleRect.width - this.scrollPosition.x);
zero.y = Mathf.Clamp(zero.y, rect2.yMin - this.scrollPosition.y, rect2.yMax - this.visibleRect.height - this.scrollPosition.y);
return zero;
}
}
}
#endif

View File

@ -5,7 +5,7 @@ using UnityEngine;
namespace Explorer.Unstrip.IMGUI namespace Explorer.Unstrip.IMGUI
{ {
public struct Internal_SliderHandler public struct SliderHandlerUnstrip
{ {
public static int ScrollTroughSide public static int ScrollTroughSide
{ {
@ -57,7 +57,7 @@ namespace Explorer.Unstrip.IMGUI
private readonly bool horiz; private readonly bool horiz;
private readonly int id; private readonly int id;
public Internal_SliderHandler(Rect position, float currentValue, float size, float start, public SliderHandlerUnstrip(Rect position, float currentValue, float size, float start,
float end, GUIStyle slider, GUIStyle thumb, bool horiz, int id) float end, GUIStyle slider, GUIStyle thumb, bool horiz, int id)
{ {
this.position = position; this.position = position;
@ -118,9 +118,9 @@ namespace Explorer.Unstrip.IMGUI
GUI.changed = true; GUI.changed = true;
if (this.SupportsPageMovements()) if (this.SupportsPageMovements())
{ {
var ext = Internal_SliderState.FromPointer(GetSliderState().Pointer); var state = GetSliderState();
ext.isDragging = false; state.isDragging = false;
Internal.nextScrollStepTime = DateTime.Now.AddMilliseconds(250.0); GUIUnstrip.nextScrollStepTime = DateTime.Now.AddMilliseconds(250.0);
ScrollTroughSide = this.CurrentScrollTroughSide(); ScrollTroughSide = this.CurrentScrollTroughSide();
result = this.PageMovementValue(); result = this.PageMovementValue();
} }
@ -144,8 +144,8 @@ namespace Explorer.Unstrip.IMGUI
} }
else else
{ {
var ext = Internal_SliderState.FromPointer(GetSliderState().Pointer); var state = GetSliderState();
if (!ext.isDragging) if (!state.isDragging)
{ {
result = this.currentValue; result = this.currentValue;
} }
@ -153,8 +153,8 @@ namespace Explorer.Unstrip.IMGUI
{ {
GUI.changed = true; GUI.changed = true;
this.CurrentEvent().Use(); this.CurrentEvent().Use();
float num = this.MousePosition() - ext.dragStartPos; float num = this.MousePosition() - state.dragStartPos;
float value = ext.dragStartValue + num / this.ValuesPerPixel(); float value = state.dragStartValue + num / this.ValuesPerPixel();
result = this.Clamp(value); result = this.Clamp(value);
} }
} }
@ -194,7 +194,7 @@ namespace Explorer.Unstrip.IMGUI
else else
{ {
GUI.InternalRepaintEditorWindow(); GUI.InternalRepaintEditorWindow();
if (DateTime.Now < Internal.nextScrollStepTime) if (DateTime.Now < GUIUnstrip.nextScrollStepTime)
{ {
result = this.currentValue; result = this.currentValue;
} }
@ -204,10 +204,10 @@ namespace Explorer.Unstrip.IMGUI
} }
else else
{ {
Internal.nextScrollStepTime = DateTime.Now.AddMilliseconds(30.0); GUIUnstrip.nextScrollStepTime = DateTime.Now.AddMilliseconds(30.0);
if (this.SupportsPageMovements()) if (this.SupportsPageMovements())
{ {
Internal_SliderState.FromPointer(GetSliderState().Pointer).isDragging = false; GetSliderState().isDragging = false;
GUI.changed = true; GUI.changed = true;
result = this.PageMovementValue(); result = this.PageMovementValue();
} }
@ -303,15 +303,15 @@ namespace Explorer.Unstrip.IMGUI
private void StartDraggingWithValue(float dragStartValue) private void StartDraggingWithValue(float dragStartValue)
{ {
var ext = Internal_SliderState.FromPointer(GetSliderState().Pointer); var state = GetSliderState();
ext.dragStartPos = this.MousePosition(); state.dragStartPos = this.MousePosition();
ext.dragStartValue = dragStartValue; state.dragStartValue = dragStartValue;
ext.isDragging = true; state.isDragging = true;
} }
private SliderState GetSliderState() private SliderStateUnstrip GetSliderState()
{ {
return GUIUtility.GetStateObject(Il2CppType.Of<SliderState>(), this.id).TryCast<SliderState>(); return (SliderStateUnstrip)GUIUtilityUnstrip.GetMonoStateObject(typeof(SliderStateUnstrip), this.id);
} }
private Rect ThumbRect() private Rect ThumbRect()

View File

@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Explorer.Unstrip.IMGUI
{
public class SliderStateUnstrip
{
public float dragStartPos;
public float dragStartValue;
public bool isDragging;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -6,6 +6,10 @@ using System.Text;
using UnhollowerBaseLib; using UnhollowerBaseLib;
using UnityEngine; using UnityEngine;
using System.IO; using System.IO;
using Explorer.Helpers;
using System.Runtime.InteropServices;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
namespace Explorer.Unstrip.ImageConversion namespace Explorer.Unstrip.ImageConversion
{ {
@ -13,29 +17,47 @@ namespace Explorer.Unstrip.ImageConversion
{ {
// byte[] ImageConversion.EncodeToPNG(this Texture2D image); // byte[] ImageConversion.EncodeToPNG(this Texture2D image);
internal delegate byte[] d_EncodeToPNG(IntPtr tex);
public static byte[] EncodeToPNG(this Texture2D tex) public static byte[] EncodeToPNG(this Texture2D tex)
{ {
return EncodeToPNG_iCall(tex.Pointer); var data = ICallHelper.GetICall<d_EncodeToPNG>("UnityEngine.ImageConversion::EncodeToPNG")
} .Invoke(tex.Pointer);
internal delegate byte[] EncodeToPNG_delegate(IntPtr tex); // The Il2Cpp EncodeToPNG() method does return System.Byte[],
internal static EncodeToPNG_delegate EncodeToPNG_iCall = // but for some reason it is not recognized or valid.
IL2CPP.ResolveICall<EncodeToPNG_delegate>("UnityEngine.ImageConversion::EncodeToPNG"); // Simple fix is iterating into a new array manually.
byte[] safeData = new byte[data.Length];
for (int i = 0; i < data.Length; i++)
{
safeData[i] = (byte)data[i];
}
return safeData;
}
// bool ImageConversion.LoadImage(this Texture2D tex, byte[] data, bool markNonReadable); // bool ImageConversion.LoadImage(this Texture2D tex, byte[] data, bool markNonReadable);
internal delegate bool d_LoadImage(IntPtr tex, IntPtr data, bool markNonReadable);
public static bool LoadImage(this Texture2D tex, byte[] data, bool markNonReadable) public static bool LoadImage(this Texture2D tex, byte[] data, bool markNonReadable)
{ {
return LoadImage_iCall(tex.Pointer, data, markNonReadable); var il2cppArray = new Il2CppStructArray<byte>(data.Length);
for (int i = 0; i < data.Length; i++)
{
il2cppArray[i] = data[i];
}
var ret = ICallHelper.GetICall<d_LoadImage>("UnityEngine.ImageConversion::LoadImage")
.Invoke(tex.Pointer, il2cppArray.Pointer, markNonReadable);
return ret;
} }
internal delegate bool LoadImage_delegate(IntPtr tex, byte[] data, bool markNonReadable); // Helper for LoadImage from filepath
internal static LoadImage_delegate LoadImage_iCall =
IL2CPP.ResolveICall<LoadImage_delegate>("UnityEngine.ImageConversion::LoadImage");
// Helper for LoadImage public static bool LoadImage(Texture2D tex, string filePath, bool markNonReadable)
public static bool LoadImage(this Texture2D tex, string filePath, bool markNonReadable)
{ {
if (!File.Exists(filePath)) if (!File.Exists(filePath))
{ {

View File

@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using Explorer.Helpers;
#if CPP
using UnhollowerBaseLib;
#endif
namespace Explorer.Unstrip.LayerMasks
{
public static class LayerMaskUnstrip
{
#if CPP
internal delegate IntPtr d_LayerToName(int layer);
public static string LayerToName(int layer)
{
var iCall = ICallHelper.GetICall<d_LayerToName>("UnityEngine.LayerMask::LayerToName");
return IL2CPP.Il2CppStringToManaged(iCall.Invoke(layer));
}
#else
public static string LayerToName(int layer) => LayerMask.LayerToName(layer);
#endif
}
}

View File

@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Explorer.Helpers;
using UnityEngine;
#if CPP
using UnhollowerBaseLib;
#endif
namespace Explorer.Unstrip.Resources
{
public class ResourcesUnstrip
{
#if CPP
internal delegate IntPtr d_FindObjectsOfTypeAll(IntPtr type);
public static UnityEngine.Object[] FindObjectsOfTypeAll(Il2CppSystem.Type type)
{
var arrayPtr = ICallHelper.GetICall<d_FindObjectsOfTypeAll>("UnityEngine.Resources::FindObjectsOfTypeAll")
.Invoke(type.Pointer);
var array = new Il2CppReferenceArray<UnityEngine.Object>(arrayPtr);
var ret = new UnityEngine.Object[array.Length];
for (int i = 0; i < array.Length; i++)
{
ret[i] = array[i];
}
return ret;
}
#else
public static UnityEngine.Object[] FindObjectsOfTypeAll(Type type) => UnityEngine.Resources.FindObjectsOfTypeAll(type);
#endif
}
}

View File

@ -3,6 +3,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using Explorer.Helpers;
using UnhollowerBaseLib; using UnhollowerBaseLib;
using UnityEngine; using UnityEngine;
using UnityEngine.SceneManagement; using UnityEngine.SceneManagement;
@ -12,28 +13,29 @@ namespace Explorer.Unstrip.Scenes
public class SceneUnstrip public class SceneUnstrip
{ {
//Scene.GetRootGameObjects(); //Scene.GetRootGameObjects();
internal delegate void d_GetRootGameObjects(int handle, IntPtr list);
public static GameObject[] GetRootGameObjects(Scene scene) public static GameObject[] GetRootGameObjects(Scene scene)
{ {
var list = new Il2CppSystem.Collections.Generic.List<GameObject>(GetRootCount_Internal(scene)); var list = new Il2CppSystem.Collections.Generic.List<GameObject>(GetRootCount(scene));
GetRootGameObjectsInternal_iCall(scene.handle, list.Pointer); var iCall = ICallHelper.GetICall<d_GetRootGameObjects>("UnityEngine.SceneManagement.Scene::GetRootGameObjectsInternal");
iCall.Invoke(scene.handle, list.Pointer);
return list.ToArray(); return list.ToArray();
} }
internal delegate void GetRootGameObjectsInternal_delegate(int handle, IntPtr list);
internal static GetRootGameObjectsInternal_delegate GetRootGameObjectsInternal_iCall =
IL2CPP.ResolveICall<GetRootGameObjectsInternal_delegate>("UnityEngine.SceneManagement.Scene::GetRootGameObjectsInternal");
//Scene.rootCount; //Scene.rootCount;
public static int GetRootCount_Internal(UnityEngine.SceneManagement.Scene scene)
{
return GetRootCountInternal_iCall(scene.handle);
}
internal delegate int GetRootCountInternal_delegate(int handle); internal delegate int GetRootCountInternal_delegate(int handle);
internal static GetRootCountInternal_delegate GetRootCountInternal_iCall =
IL2CPP.ResolveICall<GetRootCountInternal_delegate>("UnityEngine.SceneManagement.Scene::GetRootCountInternal"); public static int GetRootCount(Scene scene)
{
var iCall = ICallHelper.GetICall<GetRootCountInternal_delegate>("UnityEngine.SceneManagement.Scene::GetRootCountInternal");
return iCall.Invoke(scene.handle);
}
} }
} }
#endif #endif