Compare commits

...

11 Commits
1.8.0 ... 1.8.2

Author SHA1 Message Date
b4b5f1ec93 1.8.2
* Added support for games which use the new InputSystem module and have disabled LegacyInputModule
2020-10-01 18:57:28 +10:00
5afaf85859 Update README.md 2020-10-01 17:16:00 +10:00
b65e417ecb Update GUIUnstrip.cs 2020-09-30 01:59:35 +10:00
23723a4ffd Some more unstrip fixes, and a few cleanups 2020-09-30 01:52:49 +10:00
dab7ecd441 Cleanups and refactorings, and some small UI fixes 2020-09-29 05:40:06 +10:00
f1406d016f Update README.md 2020-09-28 16:19:23 +10:00
99e801b3bd Update README.md 2020-09-28 02:11:35 +10:00
20133e123c Update README.md 2020-09-28 02:04:03 +10:00
142a2a4750 Update README.md 2020-09-27 23:04:42 +10:00
629403a74d 1.8.0 cleanup 2020-09-27 22:52:08 +10:00
873d0f277d Update README.md 2020-09-27 22:15:54 +10:00
40 changed files with 1665 additions and 1375 deletions

View File

@ -1,5 +1,3 @@
# Explorer [![Version](https://img.shields.io/badge/MelonLoader-0.2.7.1-green.svg)](https://github.com/HerpDerpinstine/MelonLoader) [![Version](https://img.shields.io/badge/BepInEx-5.3.0-green.svg)](https://github.com/BepInEx/BepInEx)
<p align="center">
<img align="center" src="icon.png">
</p>
@ -14,6 +12,10 @@
<img src="https://img.shields.io/github/downloads/sinai-dev/Explorer/total.svg" />
</p>
<p align="center">
<img src="https://raw.githubusercontent.com/sinai-dev/Explorer/master/overview.png">
</p>
- [Current status](#current-status)
- [How to install](#how-to-install)
- [How to use](#how-to-use)
@ -25,10 +27,10 @@
## Current status
| Mod Loader | Il2Cpp | Mono |
| ----------- | ------ | ---- |
| MelonLoader | ✔ | ✔ |
| BepInEx | <b>?</b> (WIP) | ✔ |
| Mod Loader | Il2Cpp | Mono | Mono (.NET 3.5) |
| ----------- | ------ | ---- | ----|
| [MelonLoader](https://github.com/HerpDerpinstine/MelonLoader) | ✔️ [link](https://github.com/sinai-dev/Explorer/releases/latest/download/Explorer.MelonLoader.Il2Cpp.zip) | ✔️ [link](https://github.com/sinai-dev/Explorer/releases/latest/download/Explorer.MelonLoader.Mono.zip) | ✔️ [link](https://github.com/sinai-dev/Explorer/releases/latest/download/Explorer.MelonLoader.Mono.NET35.zip) |
| [BepInEx](https://github.com/BepInEx/BepInEx) | ❔ [link](https://github.com/sinai-dev/Explorer/releases/latest/download/Explorer.BepInEx.Il2Cpp.zip) | ✔️ [link](https://github.com/sinai-dev/Explorer/releases/latest/download/Explorer.BepInEx.Mono.zip) | ✔️ [link](https://github.com/sinai-dev/Explorer/releases/latest/download/Explorer.BepInEx.Mono.NET35.zip) |
<b>IL2CPP Issues:</b>
* .NET 3.5 is not currently supported (Unity 5.6.1 and older), this might change in the future.
@ -41,15 +43,15 @@
### MelonLoader
Requires [MelonLoader](https://github.com/HerpDerpinstine/MelonLoader) to be installed for your game.
1. Download the relevant <b>Explorer_MelonLoader_.zip</b> from [Releases](https://github.com/sinai-dev/Explorer/releases).
1. Download the relevant <b>Explorer_MelonLoader_.zip</b> from above.
2. Unzip the file into the `Mods` folder in your game's installation directory, created by MelonLoader.
3. Make sure it's not in a sub-folder, `Explorer.dll` and `mcs.dll` should be directly in the `Mods\` folder.
### BepInEx
Requires [BepInEx](https://github.com/BepInEx/BepInEx) to be installed for your game.
1. Download the relevant <b>Explorer_BepInEx_.zip</b> from [Releases](https://github.com/sinai-dev/Explorer/releases).
2. Unzip the file into the `BepInEx\plugins\` folder in your game's installation directory, created by MelonLoader.
1. Download the relevant <b>Explorer_BepInEx_.zip</b> from above.
2. Unzip the file into the `BepInEx\plugins\` folder in your game's installation directory, created by BepInEx.
3. Make sure it's not in a sub-folder, `Explorer.dll` and `mcs.dll` should be directly in the `plugins\` folder.
## How to use
@ -75,9 +77,6 @@ This config is generated to `[Game_Directory]\Mods\Explorer\config.xml`. Edit th
* Default: `<x>550</x> <y>700</y>`
## Features
[![](overview.png)](https://raw.githubusercontent.com/sinai-dev/Explorer/master/overview.png)
<i>An overview of the different Explorer menus.</i>
### Scene Explorer
@ -130,7 +129,7 @@ Explorer can force the mouse to be visible and unlocked when the menu is open, i
For example:
```csharp
using Explorer;
using Harmony;
using Harmony; // or 'using HarmonyLib;' for BepInEx
// ...
[HarmonyPatch(typeof(MyGame.MenuClass), nameof(MyGame.MenuClass.CursorUpdate)]
public class MenuClass_CursorUpdate

View File

@ -0,0 +1,169 @@
using System;
using System.Reflection;
using UnityEngine;
namespace Explorer
{
public static class CacheFactory
{
public static CacheObjectBase GetTypeAndCacheObject(object obj)
=> GetTypeAndCacheObject(obj, null, null);
public static CacheObjectBase GetTypeAndCacheObject(MemberInfo memberInfo, object declarer)
=> GetTypeAndCacheObject(null, memberInfo, declarer);
public static CacheObjectBase GetTypeAndCacheObject(object obj, MemberInfo memberInfo, object declarer)
{
Type type = null;
if (memberInfo != null)
{
if (memberInfo is FieldInfo fi)
{
type = fi.FieldType;
}
else if (memberInfo is PropertyInfo pi)
{
type = pi.PropertyType;
}
else if (memberInfo is MethodInfo mi)
{
type = mi.ReturnType;
}
}
else if (obj != null)
{
type = ReflectionHelpers.GetActualType(obj);
}
if (type == null)
{
return null;
}
return GetCacheObject(obj, memberInfo, declarer, type);
}
public static CacheObjectBase GetCacheObject(object obj, Type valueType)
=> GetCacheObject(obj, null, null, valueType);
private static CacheObjectBase GetCacheObject(object obj, MemberInfo memberInfo, object declaringInstance, Type valueType)
{
CacheObjectBase cached;
var pi = memberInfo as PropertyInfo;
var mi = memberInfo as MethodInfo;
// Check if can process args
if ((pi != null && !CanProcessArgs(pi.GetIndexParameters()))
|| (mi != null && !CanProcessArgs(mi.GetParameters())))
{
return null;
}
if (mi != null)
{
cached = new CacheMethod();
}
else if (valueType == typeof(GameObject) || valueType == typeof(Transform))
{
cached = new CacheGameObject();
}
else if (valueType.IsPrimitive || valueType == typeof(string))
{
cached = new CachePrimitive();
}
else if (valueType.IsEnum)
{
if (valueType.GetCustomAttributes(typeof(FlagsAttribute), true) is object[] attributes && attributes.Length > 0)
{
cached = new CacheEnumFlags();
}
else
{
cached = new CacheEnum();
}
}
else if (valueType == typeof(Vector2) || valueType == typeof(Vector3) || valueType == typeof(Vector4))
{
cached = new CacheVector();
}
else if (valueType == typeof(Quaternion))
{
cached = new CacheQuaternion();
}
else if (valueType == typeof(Color))
{
cached = new CacheColor();
}
else if (valueType == typeof(Rect))
{
cached = new CacheRect();
}
// must check this before IsEnumerable
else if (ReflectionHelpers.IsDictionary(valueType))
{
cached = new CacheDictionary();
}
else if (ReflectionHelpers.IsEnumerable(valueType))
{
cached = new CacheList();
}
else
{
cached = new CacheOther();
}
cached.Value = obj;
cached.ValueType = valueType;
if (memberInfo != null)
{
cached.MemInfo = memberInfo;
cached.DeclaringType = memberInfo.DeclaringType;
cached.DeclaringInstance = declaringInstance;
}
if (pi != null)
{
cached.m_arguments = pi.GetIndexParameters();
}
else if (mi != null)
{
cached.m_arguments = mi.GetParameters();
}
cached.m_argumentInput = new string[cached.m_arguments.Length];
cached.UpdateValue();
cached.Init();
return cached;
}
public static bool CanProcessArgs(ParameterInfo[] parameters)
{
foreach (var param in parameters)
{
var pType = param.ParameterType;
if (pType.IsByRef && pType.HasElementType)
{
pType = pType.GetElementType();
}
if (pType.IsPrimitive || pType == typeof(string))
{
continue;
}
else
{
return false;
}
}
return true;
}
}
}

View File

@ -27,278 +27,12 @@ namespace Explorer
public string RichTextName => m_richTextName ?? GetRichTextName();
private string m_richTextName;
public bool CanWrite
{
get
{
if (MemInfo is FieldInfo fi)
return !(fi.IsLiteral && !fi.IsInitOnly);
else if (MemInfo is PropertyInfo pi)
return pi.CanWrite;
else
return false;
}
}
public bool CanWrite => m_canWrite ?? GetCanWrite();
private bool? m_canWrite;
public virtual void Init() { }
public abstract void DrawValue(Rect window, float width);
/// <summary>
/// Get CacheObject from only an object instance
/// Calls GetCacheObject(obj, memberInfo, declaringInstance) with (obj, null, null)</summary>
public static CacheObjectBase GetCacheObject(object obj)
{
return GetCacheObject(obj, null, null);
}
/// <summary>
/// Get CacheObject from an object instance and provide the value type
/// Calls GetCacheObjectImpl directly</summary>
public static CacheObjectBase GetCacheObject(object obj, Type valueType)
{
return GetCacheObjectImpl(obj, null, null, valueType);
}
/// <summary>
/// Get CacheObject from only a MemberInfo and declaring instance
/// Calls GetCacheObject(obj, memberInfo, declaringInstance) with (null, memberInfo, declaringInstance)</summary>
public static CacheObjectBase GetCacheObject(MemberInfo memberInfo, object declaringInstance)
{
return GetCacheObject(null, memberInfo, declaringInstance);
}
/// <summary>
/// Get CacheObject from either an object or MemberInfo, and don't provide the type.
/// This gets the type and then calls GetCacheObjectImpl</summary>
public static CacheObjectBase GetCacheObject(object obj, MemberInfo memberInfo, object declaringInstance)
{
Type type = null;
if (memberInfo != null)
{
if (memberInfo is FieldInfo fi)
{
type = fi.FieldType;
}
else if (memberInfo is PropertyInfo pi)
{
type = pi.PropertyType;
}
else if (memberInfo is MethodInfo mi)
{
type = mi.ReturnType;
}
}
else if (obj != null)
{
type = ReflectionHelpers.GetActualType(obj);
}
if (type == null)
{
return null;
}
return GetCacheObjectImpl(obj, memberInfo, declaringInstance, type);
}
/// <summary>
/// Actual GetCacheObject implementation (private)
/// </summary>
private static CacheObjectBase GetCacheObjectImpl(object obj, MemberInfo memberInfo, object declaringInstance, Type valueType)
{
CacheObjectBase holder;
var pi = memberInfo as PropertyInfo;
var mi = memberInfo as MethodInfo;
// Check if can process args
if ((pi != null && !CanProcessArgs(pi.GetIndexParameters()))
|| (mi != null && !CanProcessArgs(mi.GetParameters())))
{
return null;
}
if (mi != null)
{
holder = new CacheMethod();
}
else if (valueType == typeof(GameObject) || valueType == typeof(Transform))
{
holder = new CacheGameObject();
}
else if (valueType.IsPrimitive || valueType == typeof(string))
{
holder = new CachePrimitive();
}
else if (valueType.IsEnum)
{
if (valueType.GetCustomAttributes(typeof(FlagsAttribute), true) is object[] attributes && attributes.Length > 0)
{
holder = new CacheEnumFlags();
}
else
{
holder = new CacheEnum();
}
}
else if (valueType == typeof(Vector2) || valueType == typeof(Vector3) || valueType == typeof(Vector4))
{
holder = new CacheVector();
}
else if (valueType == typeof(Quaternion))
{
holder = new CacheQuaternion();
}
else if (valueType == typeof(Color))
{
holder = new CacheColor();
}
else if (valueType == typeof(Rect))
{
holder = new CacheRect();
}
// must check this before IsEnumerable
else if (ReflectionHelpers.IsDictionary(valueType))
{
holder = new CacheDictionary();
}
else if (ReflectionHelpers.IsEnumerable(valueType))
{
holder = new CacheList();
}
else
{
holder = new CacheOther();
}
holder.Value = obj;
holder.ValueType = valueType;
if (memberInfo != null)
{
holder.MemInfo = memberInfo;
holder.DeclaringType = memberInfo.DeclaringType;
holder.DeclaringInstance = declaringInstance;
}
if (pi != null)
{
holder.m_arguments = pi.GetIndexParameters();
}
else if (mi != null)
{
holder.m_arguments = mi.GetParameters();
}
holder.m_argumentInput = new string[holder.m_arguments.Length];
holder.UpdateValue();
holder.Init();
return holder;
}
public static bool CanProcessArgs(ParameterInfo[] parameters)
{
foreach (var param in parameters)
{
var pType = param.ParameterType;
if (pType.IsByRef && pType.HasElementType)
{
pType = pType.GetElementType();
}
if (pType.IsPrimitive || pType == typeof(string))
{
continue;
}
else
{
return false;
}
}
return true;
}
public float CalcWhitespace(Rect window)
{
if (!(this is IExpandHeight)) return 0f;
float whitespace = (this as IExpandHeight).WhiteSpace;
if (whitespace > 0)
{
ClampLabelWidth(window, ref whitespace);
}
return whitespace;
}
public object[] ParseArguments()
{
var parsedArgs = new List<object>();
for (int i = 0; i < m_arguments.Length; i++)
{
var input = m_argumentInput[i];
var type = m_arguments[i].ParameterType;
if (type.IsByRef)
{
type = type.GetElementType();
}
if (!string.IsNullOrEmpty(input))
{
// strings can obviously just be used directly
if (type == typeof(string))
{
parsedArgs.Add(input);
continue;
}
else
{
// try to invoke the parse method and use that.
try
{
parsedArgs.Add(type.GetMethod("Parse", new Type[] { typeof(string) })
.Invoke(null, new object[] { input }));
continue;
}
catch
{
ExplorerCore.Log($"Argument #{i} '{m_arguments[i].Name}' ({type.Name}), could not parse input '{input}'.");
}
}
}
// Didn't use input, see if there is a default value.
if (HasDefaultValue(m_arguments[i]))
{
parsedArgs.Add(m_arguments[i].DefaultValue);
continue;
}
// Try add a null arg I guess
parsedArgs.Add(null);
}
return parsedArgs.ToArray();
}
public static bool HasDefaultValue(ParameterInfo arg)
{
return
#if NET35
arg.DefaultValue != null; // rip null default args in NET35
#else
arg.HasDefaultValue;
#endif
}
public abstract void DrawValue(Rect window, float width);
public virtual void UpdateValue()
{
@ -367,11 +101,77 @@ namespace Explorer
}
}
public object[] ParseArguments()
{
var parsedArgs = new List<object>();
for (int i = 0; i < m_arguments.Length; i++)
{
var input = m_argumentInput[i];
var type = m_arguments[i].ParameterType;
if (type.IsByRef)
{
type = type.GetElementType();
}
if (!string.IsNullOrEmpty(input))
{
if (type == typeof(string))
{
parsedArgs.Add(input);
continue;
}
else
{
try
{
var arg = type.GetMethod("Parse", new Type[] { typeof(string) })
.Invoke(null, new object[] { input });
parsedArgs.Add(arg);
continue;
}
catch
{
ExplorerCore.Log($"Argument #{i} '{m_arguments[i].Name}' ({type.Name}), could not parse input '{input}'.");
}
}
}
// No input, see if there is a default value.
if (HasDefaultValue(m_arguments[i]))
{
parsedArgs.Add(m_arguments[i].DefaultValue);
continue;
}
// Try add a null arg I guess
parsedArgs.Add(null);
}
return parsedArgs.ToArray();
}
public static bool HasDefaultValue(ParameterInfo arg) => arg.DefaultValue != DBNull.Value;
// ========= Gui Draw ==========
public const float MAX_LABEL_WIDTH = 400f;
public const string EVALUATE_LABEL = "<color=lime>Evaluate</color>";
public float CalcWhitespace(Rect window)
{
if (!(this is IExpandHeight)) return 0f;
float whitespace = (this as IExpandHeight).WhiteSpace;
if (whitespace > 0)
{
ClampLabelWidth(window, ref whitespace);
}
return whitespace;
}
public static void ClampLabelWidth(Rect window, ref float labelWidth)
{
float min = window.width * 0.37f;
@ -436,8 +236,11 @@ namespace Explorer
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
GUILayout.Label($"<color={UIStyles.Syntax.StructGreen}>{cm.GenericArgs[i].Name}</color>", new GUILayoutOption[] { GUILayout.Width(15) });
cm.GenericArgInput[i] = GUILayout.TextField(input, new GUILayoutOption[] { GUILayout.Width(150) });
GUILayout.Label(
$"<color={UIStyles.Syntax.StructGreen}>{cm.GenericArgs[i].Name}</color>",
new GUILayoutOption[] { GUILayout.Width(15) }
);
cm.GenericArgInput[i] = GUIUnstrip.TextField(input, new GUILayoutOption[] { GUILayout.Width(150) });
GUI.skin.label.alignment = TextAnchor.MiddleLeft;
GUILayout.Label(types, new GUILayoutOption[0]);
@ -465,7 +268,7 @@ namespace Explorer
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
GUILayout.Label(i.ToString(), new GUILayoutOption[] { GUILayout.Width(15) });
m_argumentInput[i] = GUILayout.TextField(input, new GUILayoutOption[] { GUILayout.Width(150) });
m_argumentInput[i] = GUIUnstrip.TextField(input, new GUILayoutOption[] { GUILayout.Width(150) });
GUI.skin.label.alignment = TextAnchor.MiddleLeft;
GUILayout.Label(label, new GUILayoutOption[0]);
@ -477,13 +280,9 @@ namespace Explorer
if (GUILayout.Button(EVALUATE_LABEL, new GUILayoutOption[] { GUILayout.Width(70) }))
{
if (cm != null)
{
cm.Evaluate();
}
else
{
UpdateValue();
}
}
if (GUILayout.Button("Cancel", new GUILayoutOption[] { GUILayout.Width(70) }))
{
@ -506,21 +305,17 @@ namespace Explorer
GUILayout.EndVertical();
// new line and space
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
GUIUnstrip.Space(labelWidth);
}
else if (cm != null)
{
//GUILayout.BeginHorizontal(null);
if (GUILayout.Button(EVALUATE_LABEL, new GUILayoutOption[] { GUILayout.Width(70) }))
{
cm.Evaluate();
}
// new line and space
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
GUIUnstrip.Space(labelWidth);
@ -546,6 +341,18 @@ namespace Explorer
}
}
private bool GetCanWrite()
{
if (MemInfo is FieldInfo fi)
m_canWrite = !(fi.IsLiteral && !fi.IsInitOnly);
else if (MemInfo is PropertyInfo pi)
m_canWrite = pi.CanWrite;
else
m_canWrite = false;
return (bool)m_canWrite;
}
private string GetRichTextName()
{
string memberColor = "";
@ -582,9 +389,19 @@ namespace Explorer
memberColor = UIStyles.Syntax.Prop_Instance;
}
string classColor = MemInfo.DeclaringType.IsAbstract && MemInfo.DeclaringType.IsSealed
? UIStyles.Syntax.Class_Static
: UIStyles.Syntax.Class_Instance;
string classColor;
if (MemInfo.DeclaringType.IsValueType)
{
classColor = UIStyles.Syntax.StructGreen;
}
else if (MemInfo.DeclaringType.IsAbstract && MemInfo.DeclaringType.IsSealed)
{
classColor = UIStyles.Syntax.Class_Static;
}
else
{
classColor = UIStyles.Syntax.Class_Instance;
}
m_richTextName = $"<color={classColor}>{MemInfo.DeclaringType.Name}</color>.";
if (isStatic) m_richTextName += "<i>";
@ -607,23 +424,6 @@ namespace Explorer
m_richTextName += ">";
}
// Method / Property arguments
//if (m_arguments.Length > 0 || this is CacheMethod)
//{
// m_richTextName += "(";
// var args = "";
// foreach (var param in m_arguments)
// {
// if (args != "") args += ", ";
// args += $"<color={classColor}>{param.ParameterType.Name}</color> ";
// args += $"<color={UIStyles.Syntax.Local}>{param.Name}</color>";
// }
// m_richTextName += args;
// m_richTextName += ")";
//}
return m_richTextName;
}
}

View File

@ -131,7 +131,7 @@ namespace Explorer
foreach (var key in IDict.Keys)
{
Type t = ReflectionHelpers.GetActualType(key) ?? TypeOfKeys;
var cache = GetCacheObject(key, t);
var cache = CacheFactory.GetCacheObject(key, t);
keys.Add(cache);
}
@ -139,7 +139,7 @@ namespace Explorer
foreach (var val in IDict.Values)
{
Type t = ReflectionHelpers.GetActualType(val) ?? TypeOfValues;
var cache = GetCacheObject(val, t);
var cache = CacheFactory.GetCacheObject(val, t);
values.Add(cache);
}

View File

@ -246,7 +246,7 @@ namespace Explorer
}
#endif
if (GetCacheObject(obj, t) is CacheObjectBase cached)
if (CacheFactory.GetCacheObject(obj, t) is CacheObjectBase cached)
{
list.Add(cached);
}
@ -354,6 +354,7 @@ namespace Explorer
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
GUILayout.Label($"[{i}]", new GUILayoutOption[] { GUILayout.Width(30) });
GUI.skin.label.alignment = TextAnchor.MiddleLeft;
entry.DrawValue(window, window.width - (whitespace + 85));
}

View File

@ -64,7 +64,7 @@ namespace Explorer
if (ret != null)
{
m_cachedReturnValue = GetCacheObject(ret);
m_cachedReturnValue = CacheFactory.GetTypeAndCacheObject(ret);
m_cachedReturnValue.UpdateValue();
}
else

View File

@ -64,25 +64,25 @@ namespace Explorer
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
GUIUnstrip.Space(whitespace);
GUILayout.Label("R:", new GUILayoutOption[] { GUILayout.Width(30) });
r = GUILayout.TextField(r, new GUILayoutOption[] { GUILayout.Width(120) });
r = GUIUnstrip.TextField(r, new GUILayoutOption[] { GUILayout.Width(120) });
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
GUIUnstrip.Space(whitespace);
GUILayout.Label("G:", new GUILayoutOption[] { GUILayout.Width(30) });
g = GUILayout.TextField(g, new GUILayoutOption[] { GUILayout.Width(120) });
g = GUIUnstrip.TextField(g, new GUILayoutOption[] { GUILayout.Width(120) });
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
GUIUnstrip.Space(whitespace);
GUILayout.Label("B:", new GUILayoutOption[] { GUILayout.Width(30) });
b = GUILayout.TextField(b, new GUILayoutOption[] { GUILayout.Width(120) });
b = GUIUnstrip.TextField(b, new GUILayoutOption[] { GUILayout.Width(120) });
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
GUIUnstrip.Space(whitespace);
GUILayout.Label("A:", new GUILayoutOption[] { GUILayout.Width(30) });
a = GUILayout.TextField(a, new GUILayoutOption[] { GUILayout.Width(120) });
a = GUIUnstrip.TextField(a, new GUILayoutOption[] { GUILayout.Width(120) });
GUILayout.EndHorizontal();
// draw set value button

View File

@ -10,7 +10,7 @@ namespace Explorer
public class CacheEnum : CacheObjectBase
{
// public Type EnumType;
public string[] EnumNames;
public string[] EnumNames = new string[0];
public override void Init()
{
@ -56,7 +56,7 @@ namespace Explorer
}
}
GUILayout.Label(Value.ToString() + "<color=#2df7b2><i> (" + ValueType + ")</i></color>", new GUILayoutOption[0]);
GUILayout.Label(Value.ToString() + $"<color={UIStyles.Syntax.StructGreen}><i> ({ValueType})</i></color>", new GUILayoutOption[0]);
}
public void SetEnum(int change)

View File

@ -6,9 +6,8 @@ using UnityEngine;
namespace Explorer
{
public class CacheEnumFlags : CacheObjectBase, IExpandHeight
public class CacheEnumFlags : CacheEnum, IExpandHeight
{
public string[] EnumNames = new string[0];
public bool[] m_enabledFlags = new bool[0];
public bool IsExpanded { get; set; }
@ -18,48 +17,21 @@ namespace Explorer
{
base.Init();
if (ValueType == null && Value != null)
{
ValueType = Value.GetType();
}
if (ValueType != null)
{
EnumNames = Enum.GetNames(ValueType);
m_enabledFlags = new bool[EnumNames.Length];
UpdateValue();
}
else
{
ReflectionException = "Unknown, could not get Enum names.";
}
}
public void SetFlagsFromInput()
{
string val = "";
for (int i = 0; i < EnumNames.Length; i++)
{
if (m_enabledFlags[i])
{
if (val != "") val += ", ";
val += EnumNames[i];
}
}
Value = Enum.Parse(ValueType, val);
SetValue();
UpdateValue();
}
public override void UpdateValue()
{
base.UpdateValue();
if (Value == null) return;
try
{
var enabledNames = Value.ToString().Split(',').Select(it => it.Trim());
m_enabledFlags = new bool[EnumNames.Length];
for (int i = 0; i < EnumNames.Length; i++)
{
m_enabledFlags[i] = enabledNames.Contains(EnumNames[i]);
@ -71,7 +43,6 @@ namespace Explorer
}
}
public override void DrawValue(Rect window, float width)
{
if (CanWrite)
@ -121,5 +92,20 @@ namespace Explorer
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
}
}
public void SetFlagsFromInput()
{
string val = "";
for (int i = 0; i < EnumNames.Length; i++)
{
if (m_enabledFlags[i])
{
if (val != "") val += ", ";
val += EnumNames[i];
}
}
Value = Enum.Parse(ValueType, val);
SetValue();
}
}
}

View File

@ -2,28 +2,26 @@
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;
#if CPP
using UnhollowerRuntimeLib;
#endif
using UnityEngine;
namespace Explorer
{
public class CachePrimitive : CacheObjectBase
{
private string m_valueToString;
private bool m_isBool;
private bool m_isString;
private string m_valueToString;
public MethodInfo ParseMethod => m_parseMethod ?? (m_parseMethod = Value.GetType().GetMethod("Parse", new Type[] { typeof(string) }));
private MethodInfo m_parseMethod;
private bool m_canBitwiseOperate;
private bool m_inBitwiseMode;
private string m_bitwiseOperatorInput = "0";
private string m_bitwiseToString;
//private BitArray m_bitMask; // not needed I think
private string m_binaryInput;
public override void Init()
{
@ -48,6 +46,8 @@ namespace Explorer
}
m_canBitwiseOperate = typeof(int).IsAssignableFrom(ValueType);
UpdateValue();
}
public override void UpdateValue()
@ -57,20 +57,19 @@ namespace Explorer
RefreshToString();
}
public void RefreshToString()
private void RefreshToString()
{
m_valueToString = Value?.ToString();
if (m_inBitwiseMode)
if (m_canBitwiseOperate)
{
var _int = (int)Value;
m_bitwiseToString = Convert.ToString(_int, toBase: 2);
m_binaryInput = Convert.ToString(_int, toBase: 2);
}
}
public override void DrawValue(Rect window, float width)
{
// bool uses Toggle
if (m_isBool)
{
var b = (bool)Value;
@ -81,7 +80,8 @@ namespace Explorer
b = GUILayout.Toggle(b, label, new GUILayoutOption[0]);
if (b != (bool)Value)
{
SetValueFromInput(b.ToString());
Value = b;
SetValue();
}
}
else
@ -98,39 +98,20 @@ namespace Explorer
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
// using ValueType.Name instead of ValueTypeName, because we only want the short name.
GUILayout.Label("<color=#2df7b2><i>" + ValueType.Name + "</i></color>", new GUILayoutOption[] { GUILayout.Width(50) });
int dynSize = 25 + (m_valueToString.Length * 15);
var maxwidth = window.width - 310f;
if (CanWrite) maxwidth -= 60;
if (dynSize > maxwidth)
{
m_valueToString = GUIUnstrip.TextArea(m_valueToString, new GUILayoutOption[] { GUILayout.Width(maxwidth) });
}
else
{
m_valueToString = GUILayout.TextField(m_valueToString, new GUILayoutOption[] { GUILayout.Width(dynSize) });
}
m_valueToString = GUIUnstrip.TextArea(m_valueToString, new GUILayoutOption[] { GUILayout.ExpandWidth(true) });
if (CanWrite)
{
if (GUILayout.Button("<color=#00FF00>Apply</color>", new GUILayoutOption[] { GUILayout.Width(60) }))
{
SetValueFromInput(m_valueToString);
RefreshToString();
SetValueFromInput();
}
}
if (m_canBitwiseOperate)
{
bool orig = m_inBitwiseMode;
m_inBitwiseMode = GUILayout.Toggle(m_inBitwiseMode, "Bitwise?", new GUILayoutOption[0]);
if (orig != m_inBitwiseMode)
{
RefreshToString();
}
}
GUIUnstrip.Space(10);
@ -139,79 +120,91 @@ namespace Explorer
if (m_inBitwiseMode)
{
if (CanWrite)
{
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
GUI.skin.label.alignment = TextAnchor.MiddleRight;
GUILayout.Label("RHS:", new GUILayoutOption[] { GUILayout.Width(35) });
GUI.skin.label.alignment = TextAnchor.UpperLeft;
if (GUILayout.Button("~", new GUILayoutOption[] { GUILayout.Width(25) }))
{
if (int.TryParse(m_bitwiseOperatorInput, out int bit))
{
Value = ~bit;
RefreshToString();
}
}
if (GUILayout.Button("<<", new GUILayoutOption[] { GUILayout.Width(25) }))
{
if (int.TryParse(m_bitwiseOperatorInput, out int bit))
{
Value = (int)Value << bit;
RefreshToString();
}
}
if (GUILayout.Button(">>", new GUILayoutOption[] { GUILayout.Width(25) }))
{
if (int.TryParse(m_bitwiseOperatorInput, out int bit))
{
Value = (int)Value >> bit;
RefreshToString();
}
}
if (GUILayout.Button("|", new GUILayoutOption[] { GUILayout.Width(25) }))
{
if (int.TryParse(m_bitwiseOperatorInput, out int bit))
{
Value = (int)Value | bit;
RefreshToString();
}
}
if (GUILayout.Button("&", new GUILayoutOption[] { GUILayout.Width(25) }))
{
if (int.TryParse(m_bitwiseOperatorInput, out int bit))
{
Value = (int)Value & bit;
RefreshToString();
}
}
if (GUILayout.Button("^", new GUILayoutOption[] { GUILayout.Width(25) }))
{
if (int.TryParse(m_bitwiseOperatorInput, out int bit))
{
Value = (int)Value ^ bit;
RefreshToString();
}
}
m_bitwiseOperatorInput = GUILayout.TextField(m_bitwiseOperatorInput, new GUILayoutOption[] { GUILayout.Width(55) });
GUILayout.EndHorizontal();
}
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
GUILayout.Label($"<color=cyan>Binary:</color>", new GUILayoutOption[] { GUILayout.Width(60) });
GUILayout.TextField(m_bitwiseToString, new GUILayoutOption[0]);
GUILayout.EndHorizontal();
DrawBitwise();
}
GUILayout.EndVertical();
}
public void SetValueFromInput(string valueString)
private void DrawBitwise()
{
if (CanWrite)
{
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
GUI.skin.label.alignment = TextAnchor.MiddleRight;
GUILayout.Label("RHS:", new GUILayoutOption[] { GUILayout.Width(35) });
GUI.skin.label.alignment = TextAnchor.UpperLeft;
if (GUILayout.Button("~", new GUILayoutOption[] { GUILayout.Width(25) }))
{
if (int.TryParse(m_bitwiseOperatorInput, out int bit))
{
Value = ~bit;
RefreshToString();
}
}
if (GUILayout.Button("<<", new GUILayoutOption[] { GUILayout.Width(25) }))
{
if (int.TryParse(m_bitwiseOperatorInput, out int bit))
{
Value = (int)Value << bit;
RefreshToString();
}
}
if (GUILayout.Button(">>", new GUILayoutOption[] { GUILayout.Width(25) }))
{
if (int.TryParse(m_bitwiseOperatorInput, out int bit))
{
Value = (int)Value >> bit;
RefreshToString();
}
}
if (GUILayout.Button("|", new GUILayoutOption[] { GUILayout.Width(25) }))
{
if (int.TryParse(m_bitwiseOperatorInput, out int bit))
{
Value = (int)Value | bit;
RefreshToString();
}
}
if (GUILayout.Button("&", new GUILayoutOption[] { GUILayout.Width(25) }))
{
if (int.TryParse(m_bitwiseOperatorInput, out int bit))
{
Value = (int)Value & bit;
RefreshToString();
}
}
if (GUILayout.Button("^", new GUILayoutOption[] { GUILayout.Width(25) }))
{
if (int.TryParse(m_bitwiseOperatorInput, out int bit))
{
Value = (int)Value ^ bit;
RefreshToString();
}
}
m_bitwiseOperatorInput = GUIUnstrip.TextField(m_bitwiseOperatorInput, new GUILayoutOption[] { GUILayout.Width(55) });
GUILayout.EndHorizontal();
}
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
GUILayout.Label($"<color=cyan>Binary:</color>", new GUILayoutOption[] { GUILayout.Width(60) });
m_binaryInput = GUIUnstrip.TextField(m_binaryInput, new GUILayoutOption[0]);
if (CanWrite)
{
if (GUILayout.Button("Apply", new GUILayoutOption[0]))
{
SetValueFromBinaryInput();
}
}
GUILayout.EndHorizontal();
}
public void SetValueFromInput()
{
if (MemInfo == null)
{
@ -221,23 +214,13 @@ namespace Explorer
if (m_isString)
{
Value = valueString;
Value = m_valueToString;
}
else
{
try
{
Value = ParseMethod.Invoke(null, new object[] { valueString });
//if (m_inBitwiseMode)
//{
// var method = typeof(Convert).GetMethod($"To{ValueType.Name}", new Type[] { typeof(string), typeof(int) });
// Value = method.Invoke(null, new object[] { valueString, 2 });
//}
//else
//{
// Value = ParseMethod.Invoke(null, new object[] { valueString });
//}
Value = ParseMethod.Invoke(null, new object[] { m_valueToString });
}
catch (Exception e)
{
@ -246,6 +229,23 @@ namespace Explorer
}
SetValue();
RefreshToString();
}
private void SetValueFromBinaryInput()
{
try
{
var method = typeof(Convert).GetMethod($"To{ValueType.Name}", new Type[] { typeof(string), typeof(int) });
Value = method.Invoke(null, new object[] { m_binaryInput, 2 });
SetValue();
RefreshToString();
}
catch (Exception e)
{
ExplorerCore.Log("Exception setting value: " + e.GetType() + ", " + e.Message);
}
}
}
}

View File

@ -59,19 +59,19 @@ namespace Explorer
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
GUIUnstrip.Space(whitespace);
GUILayout.Label("X:", new GUILayoutOption[] { GUILayout.Width(30) });
x = GUILayout.TextField(x, new GUILayoutOption[] { GUILayout.Width(120) });
x = GUIUnstrip.TextField(x, new GUILayoutOption[] { GUILayout.Width(120) });
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
GUIUnstrip.Space(whitespace);
GUILayout.Label("Y:", new GUILayoutOption[] { GUILayout.Width(30) });
y = GUILayout.TextField(y, new GUILayoutOption[] { GUILayout.Width(120) });
y = GUIUnstrip.TextField(y, new GUILayoutOption[] { GUILayout.Width(120) });
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
GUIUnstrip.Space(whitespace);
GUILayout.Label("Z:", new GUILayoutOption[] { GUILayout.Width(30) });
z = GUILayout.TextField(z, new GUILayoutOption[] { GUILayout.Width(120) });
z = GUIUnstrip.TextField(z, new GUILayoutOption[] { GUILayout.Width(120) });
GUILayout.EndHorizontal();
// draw set value button

View File

@ -61,25 +61,25 @@ namespace Explorer
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
GUIUnstrip.Space(whitespace);
GUILayout.Label("X:", new GUILayoutOption[] { GUILayout.Width(30) });
x = GUILayout.TextField(x, new GUILayoutOption[] { GUILayout.Width(120) });
x = GUIUnstrip.TextField(x, new GUILayoutOption[] { GUILayout.Width(120) });
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
GUIUnstrip.Space(whitespace);
GUILayout.Label("Y:", new GUILayoutOption[] { GUILayout.Width(30) });
y = GUILayout.TextField(y, new GUILayoutOption[] { GUILayout.Width(120) });
y = GUIUnstrip.TextField(y, new GUILayoutOption[] { GUILayout.Width(120) });
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
GUIUnstrip.Space(whitespace);
GUILayout.Label("W:", new GUILayoutOption[] { GUILayout.Width(30) });
w = GUILayout.TextField(w, new GUILayoutOption[] { GUILayout.Width(120) });
w = GUIUnstrip.TextField(w, new GUILayoutOption[] { GUILayout.Width(120) });
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
GUIUnstrip.Space(whitespace);
GUILayout.Label("H:", new GUILayoutOption[] { GUILayout.Width(30) });
h = GUILayout.TextField(h, new GUILayoutOption[] { GUILayout.Width(120) });
h = GUIUnstrip.TextField(h, new GUILayoutOption[] { GUILayout.Width(120) });
GUILayout.EndHorizontal();
// draw set value button

View File

@ -101,13 +101,13 @@ namespace Explorer
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
GUIUnstrip.Space(whitespace);
GUILayout.Label("X:", new GUILayoutOption[] { GUILayout.Width(30) });
x = GUILayout.TextField(x, new GUILayoutOption[] { GUILayout.Width(120) });
x = GUIUnstrip.TextField(x, new GUILayoutOption[] { GUILayout.Width(120) });
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
GUIUnstrip.Space(whitespace);
GUILayout.Label("Y:", new GUILayoutOption[] { GUILayout.Width(30) });
y = GUILayout.TextField(y, new GUILayoutOption[] { GUILayout.Width(120) });
y = GUIUnstrip.TextField(y, new GUILayoutOption[] { GUILayout.Width(120) });
GUILayout.EndHorizontal();
if (VectorSize > 2)
@ -116,7 +116,7 @@ namespace Explorer
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
GUIUnstrip.Space(whitespace);
GUILayout.Label("Z:", new GUILayoutOption[] { GUILayout.Width(30) });
z = GUILayout.TextField(z, new GUILayoutOption[] { GUILayout.Width(120) });
z = GUIUnstrip.TextField(z, new GUILayoutOption[] { GUILayout.Width(120) });
GUILayout.EndHorizontal();
}
if (VectorSize > 3)
@ -125,7 +125,7 @@ namespace Explorer
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
GUIUnstrip.Space(whitespace);
GUILayout.Label("W:", new GUILayoutOption[] { GUILayout.Width(30) });
w = GUILayout.TextField(w, new GUILayoutOption[] { GUILayout.Width(120) });
w = GUIUnstrip.TextField(w, new GUILayoutOption[] { GUILayout.Width(120) });
GUILayout.EndHorizontal();
}

View File

@ -30,9 +30,9 @@ namespace Explorer
}
// returns true if settings successfully loaded
public static bool LoadSettings(bool checkExist = true)
public static bool LoadSettings()
{
if (checkExist && !File.Exists(SETTINGS_PATH))
if (!File.Exists(SETTINGS_PATH))
return false;
try
@ -50,9 +50,9 @@ namespace Explorer
return Instance != null;
}
public static void SaveSettings(bool checkExist = true)
public static void SaveSettings()
{
if (checkExist && File.Exists(SETTINGS_PATH))
if (File.Exists(SETTINGS_PATH))
File.Delete(SETTINGS_PATH);
using (var file = File.Create(SETTINGS_PATH))

View File

@ -2,58 +2,52 @@
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Configuration Condition=" '$(Configuration)' == '' ">Release_ML_Cpp</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}</ProjectGuid>
<OutputType>Library</OutputType>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Explorer</RootNamespace>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
<TargetFrameworkProfile />
<AssemblyName>Explorer</AssemblyName>
<OutputPath>..\Release\Explorer.MelonLoader.Il2Cpp\</OutputPath>
<DefineConstants>CPP,ML</DefineConstants>
<IsCpp>true</IsCpp>
<IsMelonLoader>true</IsMelonLoader>
<IsNet35>false</IsNet35>
<!-- Set this to the MelonLoader Il2Cpp Game folder, without the ending '\' character. -->
<MLCppGameFolder>D:\Steam\steamapps\common\Hellpoint</MLCppGameFolder>
<!-- Set this to the MelonLoader Mono Game folder, without the ending '\' character. -->
<MLMonoGameFolder>D:\Steam\steamapps\common\Outward</MLMonoGameFolder>
<!-- Set this to the BepInEx Il2Cpp Game folder, without the ending '\' character. -->
<BIECppGameFolder>D:\Steam\steamapps\common\Outward - Il2Cpp</BIECppGameFolder>
<!-- Set this to the BepInEx Mono Game folder, without the ending '\' character. -->
<BIEMonoGameFolder>D:\Steam\steamapps\common\Outward</BIEMonoGameFolder>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_ML_Cpp|AnyCPU' ">
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<DebugSymbols>false</DebugSymbols>
<DebugType>none</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\Release\ML_Cpp\</OutputPath>
<DefineConstants>CPP,ML</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>x64</PlatformTarget>
<Prefer32Bit>false</Prefer32Bit>
<RootNamespace>Explorer</RootNamespace>
<AssemblyName>Explorer</AssemblyName>
<!-- Set this to the MelonLoader Il2Cpp Game folder, without the ending '\' character. -->
<MLCppGameFolder>D:\Steam\steamapps\common\Hellpoint</MLCppGameFolder>
<!--<MLCppGameFolder>D:\source\Unity Projects\Test\_BUILD</MLCppGameFolder>-->
<!-- Set this to the MelonLoader Mono Game folder, without the ending '\' character. -->
<MLMonoGameFolder>D:\Steam\steamapps\common\Outward</MLMonoGameFolder>
<!-- Set this to the BepInEx Il2Cpp Game folder, without the ending '\' character. -->
<BIECppGameFolder>D:\Steam\steamapps\common\Outward - Il2Cpp</BIECppGameFolder>
<!-- Set this to the BepInEx Mono Game folder, without the ending '\' character. -->
<BIEMonoGameFolder>D:\Steam\steamapps\common\Outward</BIEMonoGameFolder>
<!-- <BIEMonoGameFolder>D:\source\Unity Projects\! My Unity Games\NewInputSystemTest\_BUILD</BIEMonoGameFolder> -->
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_ML_Cpp|AnyCPU' ">
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<OutputPath>..\Release\Explorer.MelonLoader.Il2Cpp\</OutputPath>
<DefineConstants>CPP,ML</DefineConstants>
<IsCpp>true</IsCpp>
<IsMelonLoader>true</IsMelonLoader>
<IsNet35>false</IsNet35>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_ML_Mono|AnyCPU' ">
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<DebugSymbols>false</DebugSymbols>
<DebugType>none</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\Release\ML_Mono\</OutputPath>
<OutputPath>..\Release\Explorer.MelonLoader.Mono\</OutputPath>
<DefineConstants>MONO,ML</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>x64</PlatformTarget>
<Prefer32Bit>false</Prefer32Bit>
<IsCpp>false</IsCpp>
<IsMelonLoader>true</IsMelonLoader>
@ -61,60 +55,32 @@
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_ML_Mono_NET35|AnyCPU' ">
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<DebugSymbols>false</DebugSymbols>
<DebugType>none</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\Release\ML_Mono_NET35\</OutputPath>
<OutputPath>..\Release\Explorer.MelonLoader.Mono.NET35\</OutputPath>
<DefineConstants>MONO,ML,NET35</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>x64</PlatformTarget>
<Prefer32Bit>false</Prefer32Bit>
<IsCpp>false</IsCpp>
<IsMelonLoader>true</IsMelonLoader>
<IsNet35>true</IsNet35>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_BIE_Cpp|AnyCPU' ">
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<DebugSymbols>false</DebugSymbols>
<DebugType>none</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\Release\BIE_Cpp\</OutputPath>
<OutputPath>..\Release\Explorer.BepInEx.Il2Cpp\</OutputPath>
<DefineConstants>CPP,BIE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>x64</PlatformTarget>
<Prefer32Bit>false</Prefer32Bit>
<IsCpp>true</IsCpp>
<IsMelonLoader>false</IsMelonLoader>
<IsNet35>false</IsNet35>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_BIE_Mono|AnyCPU' ">
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<DebugSymbols>false</DebugSymbols>
<DebugType>none</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\Release\BIE_Mono\</OutputPath>
<OutputPath>..\Release\Explorer.BepInEx.Mono\</OutputPath>
<DefineConstants>MONO,BIE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>x64</PlatformTarget>
<Prefer32Bit>false</Prefer32Bit>
<IsCpp>false</IsCpp>
<IsMelonLoader>false</IsMelonLoader>
<IsNet35>false</IsNet35>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_BIE_Mono_NET35|AnyCPU' ">
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<DebugSymbols>false</DebugSymbols>
<DebugType>none</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\Release\BIE_Mono_NET35\</OutputPath>
<OutputPath>..\Release\Explorer.BepInEx.Mono.NET35\</OutputPath>
<DefineConstants>MONO,BIE,NET35</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>x64</PlatformTarget>
<Prefer32Bit>false</Prefer32Bit>
<IsCpp>false</IsCpp>
<IsMelonLoader>false</IsMelonLoader>
<IsNet35>true</IsNet35>
@ -126,7 +92,7 @@
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<!-- MCS Ref -->
<!-- MCS ref -->
<Reference Include="mcs" Condition="'$(IsNet35)'=='false'">
<HintPath>..\lib\mcs.dll</HintPath>
<Private>True</Private>
@ -135,119 +101,128 @@
<HintPath>..\lib\mcs.NET35.dll</HintPath>
<Private>True</Private>
</Reference>
<!-- MelonLoader Il2Cpp core ref -->
<Reference Include="MelonLoader.ModHandler" Condition="'$(IsMelonLoader)|$(IsCpp)'=='true|true'">
<HintPath>$(MLCppGameFolder)\MelonLoader\MelonLoader.ModHandler.dll</HintPath>
<Private>False</Private>
</Reference>
<!-- MelonLoader Mono core ref -->
<Reference Include="MelonLoader.ModHandler" Condition="'$(IsMelonLoader)|$(IsCpp)'=='true|false'">
<HintPath>$(MLMonoGameFolder)\MelonLoader\MelonLoader.ModHandler.dll</HintPath>
<Private>False</Private>
</Reference>
<!-- BepInEx Mono core ref -->
<Reference Include="BepInEx" Condition="'$(IsMelonLoader)|$(IsCpp)'=='false|false'">
<HintPath>$(BIEMonoGameFolder)\BepInEx\core\BepInEx.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="0Harmony" Condition="'$(IsMelonLoader)|$(IsCpp)'=='false|false'">
<HintPath>$(BIEMonoGameFolder)\BepInEx\core\0Harmony.dll</HintPath>
<Private>False</Private>
</Reference>
<!-- BepInEx Il2Cpp core ref -->
<Reference Include="BepInEx" Condition="'$(IsMelonLoader)|$(IsCpp)'=='false|true'">
<HintPath>$(BIECppGameFolder)\BepInEx\core\BepInEx.Core.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="0Harmony" Condition="'$(IsMelonLoader)|$(IsCpp)'=='false|true'">
<HintPath>$(BIECppGameFolder)\BepInEx\core\0Harmony.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="BepInEx.IL2CPP" Condition="'$(IsMelonLoader)|$(IsCpp)'=='false|true'">
<HintPath>$(BIECppGameFolder)\BepInEx\core\BepInEx.IL2CPP.dll</HintPath>
<Private>False</Private>
</Reference>
<!-- MONO UnityEngine.dll ref -->
<Reference Include="UnityEngine" Condition="'$(IsCpp)'=='false'">
</ItemGroup>
<!-- Universal Mono UnityEngine.dll ref (v5.3) -->
<ItemGroup Condition="'$(IsCpp)'=='false'">
<Reference Include="UnityEngine">
<HintPath>..\lib\UnityEngine.dll</HintPath>
<Private>False</Private>
</Reference>
<!-- MelonLoader Il2Cpp UnityEngine References -->
<Reference Include="UnhollowerBaseLib" Condition="'$(IsCpp)|$(IsMelonLoader)'=='true|true'">
</ItemGroup>
<!-- MelonLoader Mono ref -->
<ItemGroup Condition="'$(IsMelonLoader)|$(IsCpp)'=='true|false'">
<Reference Include="MelonLoader.ModHandler">
<HintPath>$(MLMonoGameFolder)\MelonLoader\MelonLoader.ModHandler.dll</HintPath>
<Private>False</Private>
</Reference>
</ItemGroup>
<!-- BepInEx Mono refs -->
<ItemGroup Condition="'$(IsMelonLoader)|$(IsCpp)'=='false|false'">
<Reference Include="BepInEx">
<HintPath>$(BIEMonoGameFolder)\BepInEx\core\BepInEx.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="0Harmony">
<HintPath>$(BIEMonoGameFolder)\BepInEx\core\0Harmony.dll</HintPath>
<Private>False</Private>
</Reference>
</ItemGroup>
<!-- MelonLoader Il2Cpp refs -->
<ItemGroup Condition="'$(IsMelonLoader)|$(IsCpp)'=='true|true'">
<Reference Include="MelonLoader.ModHandler">
<HintPath>$(MLCppGameFolder)\MelonLoader\MelonLoader.ModHandler.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnhollowerBaseLib">
<HintPath>$(MLCppGameFolder)\MelonLoader\Managed\UnhollowerBaseLib.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Il2Cppmscorlib" Condition="'$(IsCpp)|$(IsMelonLoader)'=='true|true'">
<Reference Include="Il2Cppmscorlib">
<HintPath>$(MLCppGameFolder)\MelonLoader\Managed\Il2Cppmscorlib.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Il2CppSystem.Core" Condition="'$(IsCpp)|$(IsMelonLoader)'=='true|true'">
<Reference Include="Il2CppSystem.Core">
<HintPath>$(MLCppGameFolder)\MelonLoader\Managed\Il2CppSystem.Core.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine" Condition="'$(IsCpp)|$(IsMelonLoader)'=='true|true'">
<Reference Include="UnityEngine">
<HintPath>$(MLCppGameFolder)\MelonLoader\Managed\UnityEngine.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.CoreModule" Condition="'$(IsCpp)|$(IsMelonLoader)'=='true|true'">
<Reference Include="UnityEngine.CoreModule">
<HintPath>$(MLCppGameFolder)\MelonLoader\Managed\UnityEngine.CoreModule.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.IMGUIModule" Condition="'$(IsCpp)|$(IsMelonLoader)'=='true|true'">
<Reference Include="UnityEngine.IMGUIModule">
<HintPath>$(MLCppGameFolder)\MelonLoader\Managed\UnityEngine.IMGUIModule.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.PhysicsModule" Condition="'$(IsCpp)|$(IsMelonLoader)'=='true|true'">
<Reference Include="UnityEngine.PhysicsModule">
<HintPath>$(MLCppGameFolder)\MelonLoader\Managed\UnityEngine.PhysicsModule.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.TextRenderingModule" Condition="'$(IsCpp)|$(IsMelonLoader)'=='true|true'">
<Reference Include="UnityEngine.TextRenderingModule">
<HintPath>$(MLCppGameFolder)\MelonLoader\Managed\UnityEngine.TextRenderingModule.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.UI" Condition="'$(IsCpp)|$(IsMelonLoader)'=='true|true'">
<Reference Include="UnityEngine.UI">
<HintPath>$(MLCppGameFolder)\MelonLoader\Managed\UnityEngine.UI.dll</HintPath>
<Private>False</Private>
</Reference>
<!-- BepInEx Il2Cpp UnityEngine References -->
<Reference Include="UnhollowerBaseLib" Condition="'$(IsCpp)|$(IsMelonLoader)'=='true|false'">
</ItemGroup>
<!-- BepInEx Il2Cpp refs -->
<ItemGroup Condition="'$(IsMelonLoader)|$(IsCpp)'=='false|true'">
<Reference Include="BepInEx">
<HintPath>$(BIECppGameFolder)\BepInEx\core\BepInEx.Core.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="0Harmony">
<HintPath>$(BIECppGameFolder)\BepInEx\core\0Harmony.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="BepInEx.IL2CPP">
<HintPath>$(BIECppGameFolder)\BepInEx\core\BepInEx.IL2CPP.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnhollowerBaseLib">
<HintPath>$(BIECppGameFolder)\BepInEx\core\UnhollowerBaseLib.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Il2Cppmscorlib" Condition="'$(IsCpp)|$(IsMelonLoader)'=='true|false'">
<Reference Include="Il2Cppmscorlib">
<HintPath>$(BIECppGameFolder)\BepInEx\unhollowed\Il2Cppmscorlib.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Il2CppSystem.Core" Condition="'$(IsCpp)|$(IsMelonLoader)'=='true|false'">
<Reference Include="Il2CppSystem.Core">
<HintPath>$(BIECppGameFolder)\BepInEx\unhollowed\Il2CppSystem.Core.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine" Condition="'$(IsCpp)|$(IsMelonLoader)'=='true|false'">
<Reference Include="UnityEngine">
<HintPath>$(BIECppGameFolder)\BepInEx\unhollowed\UnityEngine.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.CoreModule" Condition="'$(IsCpp)|$(IsMelonLoader)'=='true|false'">
<Reference Include="UnityEngine.CoreModule">
<HintPath>$(BIECppGameFolder)\BepInEx\unhollowed\UnityEngine.CoreModule.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.IMGUIModule" Condition="'$(IsCpp)|$(IsMelonLoader)'=='true|false'">
<Reference Include="UnityEngine.IMGUIModule">
<HintPath>$(BIECppGameFolder)\BepInEx\unhollowed\UnityEngine.IMGUIModule.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.PhysicsModule" Condition="'$(IsCpp)|$(IsMelonLoader)'=='true|false'">
<Reference Include="UnityEngine.PhysicsModule">
<HintPath>$(BIECppGameFolder)\BepInEx\unhollowed\UnityEngine.PhysicsModule.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.TextRenderingModule" Condition="'$(IsCpp)|$(IsMelonLoader)'=='true|false'">
<Reference Include="UnityEngine.TextRenderingModule">
<HintPath>$(BIECppGameFolder)\BepInEx\unhollowed\UnityEngine.TextRenderingModule.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.UI" Condition="'$(IsCpp)|$(IsMelonLoader)'=='true|false'">
<Reference Include="UnityEngine.UI">
<HintPath>$(BIECppGameFolder)\BepInEx\unhollowed\UnityEngine.UI.dll</HintPath>
<Private>False</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="CachedObjects\CacheFactory.cs" />
<Compile Include="CachedObjects\IExpandHeight.cs" />
<Compile Include="CachedObjects\Struct\CacheColor.cs" />
<Compile Include="CachedObjects\Object\CacheDictionary.cs" />
@ -263,15 +238,14 @@
<Compile Include="CachedObjects\Struct\CacheRect.cs" />
<Compile Include="Config\ModConfig.cs" />
<Compile Include="ExplorerCore.cs" />
<Compile Include="Explorer_BepInPlugin.cs" />
<Compile Include="Explorer_MelonMod.cs" />
<Compile Include="ExplorerBepInPlugin.cs" />
<Compile Include="ExplorerMelonMod.cs" />
<Compile Include="Extensions\ReflectionExtensions.cs" />
<Compile Include="Helpers\InputHelper.cs" />
<Compile Include="Menu\CursorControl.cs" />
<Compile Include="Tests\TestClass.cs" />
<Compile Include="UnstripFixes\GUIUnstrip.cs" />
<Compile Include="UnstripFixes\LayoutUtilityUnstrip.cs" />
<Compile Include="UnstripFixes\ScrollViewStateUnstrip.cs" />
<Compile Include="UnstripFixes\Internal_LayoutUtility.cs" />
<Compile Include="Extensions\UnityExtensions.cs" />
<Compile Include="Helpers\PageHelper.cs" />
<Compile Include="Helpers\ReflectionHelpers.cs" />
@ -279,8 +253,8 @@
<Compile Include="Helpers\UnityHelpers.cs" />
<Compile Include="Menu\InspectUnderMouse.cs" />
<Compile Include="CachedObjects\CacheObjectBase.cs" />
<Compile Include="UnstripFixes\SliderHandlerUnstrip.cs" />
<Compile Include="UnstripFixes\UnstripExtensions.cs" />
<Compile Include="UnstripFixes\Internal_ScrollViewState.cs" />
<Compile Include="UnstripFixes\Internal_SliderHandler.cs" />
<Compile Include="Menu\ResizeDrag.cs" />
<Compile Include="Menu\Windows\TabViewWindow.cs" />
<Compile Include="Menu\Windows\UIWindow.cs" />
@ -296,6 +270,8 @@
<Compile Include="Menu\MainMenu\Pages\SearchPage.cs" />
<Compile Include="Menu\UIStyles.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="UnstripFixes\Internal.cs" />
<Compile Include="UnstripFixes\Internal_SliderState.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@ -1,17 +1,12 @@
#if BIE
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.IO;
using System.Reflection;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Mono.CSharp;
using UnityEngine.SceneManagement;
using UnityEngine.Events;
using UnityEngine;
using UnityEngine.SceneManagement;
#if CPP
using UnhollowerRuntimeLib;
using BepInEx.IL2CPP;
@ -21,15 +16,16 @@ namespace Explorer
{
[BepInPlugin(ExplorerCore.GUID, ExplorerCore.NAME, ExplorerCore.VERSION)]
#if CPP
public class Explorer_BepInPlugin : BasePlugin
public class ExplorerBepInPlugin : BasePlugin
#else
public class Explorer_BepInPlugin : BaseUnityPlugin
public class ExplorerBepInPlugin : BaseUnityPlugin
#endif
{
public static Explorer_BepInPlugin Instance;
public static ExplorerBepInPlugin Instance;
public static ManualLogSource Logging =>
#if CPP
Instance.Log;
Instance?.Log;
#else
Instance?.Logger;
#endif
@ -37,8 +33,7 @@ namespace Explorer
public static readonly Harmony HarmonyInstance = new Harmony(ExplorerCore.GUID);
#if CPP
// temporary for BIE Il2Cpp
private static bool tempSceneChangeCheck;
// temporary for Il2Cpp until scene change delegate works
private static string lastSceneName;
#endif
@ -53,17 +48,16 @@ namespace Explorer
Instance = this;
#if CPP
tempSceneChangeCheck = true;
ClassInjector.RegisterTypeInIl2Cpp<DummyMB>();
ClassInjector.RegisterTypeInIl2Cpp<ExplorerBehaviour>();
GameObject.DontDestroyOnLoad(
new GameObject(
"Explorer_Dummy",
new Il2CppSystem.Type[]
{
Il2CppType.Of<DummyMB>()
})
var obj = new GameObject(
"ExplorerBehaviour",
new Il2CppSystem.Type[]
{
Il2CppType.Of<ExplorerBehaviour>()
}
);
GameObject.DontDestroyOnLoad(obj);
#else
SceneManager.activeSceneChanged += DoSceneChange;
#endif
@ -72,7 +66,7 @@ namespace Explorer
new ExplorerCore();
HarmonyInstance.PatchAll();
//HarmonyInstance.PatchAll();
}
void LoadMCS()
@ -91,47 +85,34 @@ namespace Explorer
ExplorerCore.OnSceneChange();
}
internal static void DoUpdate()
#if CPP // BepInEx Il2Cpp mod class doesn't have monobehaviour methods yet, so wrap them in a dummy.
public class ExplorerBehaviour : MonoBehaviour
{
ExplorerCore.Update();
public ExplorerBehaviour(IntPtr ptr) : base(ptr) { }
internal void Awake()
{
Logging.LogMessage("ExplorerBehaviour.Awake");
}
#endif
internal void Update()
{
ExplorerCore.Update();
#if CPP
if (tempSceneChangeCheck)
{
var scene = SceneManager.GetActiveScene();
if (scene.name != lastSceneName)
{
lastSceneName = scene.name;
DoSceneChange(scene, scene);
}
}
#endif
}
internal static void DoOnGUI()
{
ExplorerCore.OnGUI();
}
#if CPP
public class DummyMB : MonoBehaviour
{
public DummyMB(IntPtr ptr) : base(ptr) { }
internal void Awake()
{
Logging.LogMessage("DummyMB Awake");
}
#endif
internal void Update()
{
DoUpdate();
}
internal void OnGUI()
{
DoOnGUI();
ExplorerCore.OnGUI();
}
#if CPP
}

View File

@ -4,24 +4,24 @@ namespace Explorer
{
public class ExplorerCore
{
public const string NAME =
#if ML
#if CPP
"Explorer (Il2Cpp, MelonLoader)";
#else
"Explorer (Mono, MelonLoader)";
#endif
#else
#if CPP
"Explorer (Il2Cpp, BepInEx)";
#else
"Explorer (Mono, BepInEx)";
#endif
#endif
public const string VERSION = "1.8.0";
public const string NAME = "Explorer (" + PLATFORM + ", " + MODLOADER + ")";
public const string VERSION = "1.8.2";
public const string AUTHOR = "Sinai";
public const string GUID = "com.sinai.explorer";
public const string PLATFORM =
#if CPP
"Il2Cpp";
#else
"Mono";
#endif
public const string MODLOADER =
#if ML
"MelonLoader";
#else
"BepInEx";
#endif
public static ExplorerCore Instance { get; private set; }
public ExplorerCore()
@ -30,11 +30,10 @@ namespace Explorer
ModConfig.OnLoad();
InputHelper.Init();
new MainMenu();
new WindowManager();
InputHelper.Init();
CursorControl.Init();
Log($"{NAME} {VERSION} initialized.");
@ -95,7 +94,7 @@ namespace Explorer
#if ML
MelonLoader.MelonLogger.Log(message);
#else
Explorer_BepInPlugin.Logging?.LogMessage(message);
ExplorerBepInPlugin.Logging?.LogMessage(message);
#endif
}
@ -104,7 +103,7 @@ namespace Explorer
#if ML
MelonLoader.MelonLogger.LogWarning(message);
#else
Explorer_BepInPlugin.Logging?.LogWarning(message);
ExplorerBepInPlugin.Logging?.LogWarning(message);
#endif
}
@ -113,7 +112,7 @@ namespace Explorer
#if ML
MelonLoader.MelonLogger.LogError(message);
#else
Explorer_BepInPlugin.Logging?.LogError(message);
ExplorerBepInPlugin.Logging?.LogError(message);
#endif
}
}

View File

@ -7,9 +7,9 @@ using MelonLoader;
namespace Explorer
{
public class Explorer_MelonMod : MelonMod
public class ExplorerMelonMod : MelonMod
{
public static Explorer_MelonMod Instance;
public static ExplorerMelonMod Instance;
public override void OnApplicationStart()
{

View File

@ -8,19 +8,12 @@ namespace Explorer
public static class ReflectionExtensions
{
#if CPP
/// <summary>
/// Extension to allow for easy, non-generic Il2Cpp casting.
/// The extension is on System.Object, but only Il2Cpp objects would be a valid target.
/// </summary>
public static object Il2CppCast(this object obj, Type castTo)
{
return ReflectionHelpers.Il2CppCast(obj, castTo);
}
#endif
/// <summary>
/// Extension to safely try to get all Types from an Assembly, with a fallback for ReflectionTypeLoadException.
/// </summary>
public static IEnumerable<Type> TryGetTypes(this Assembly asm)
{
try
@ -29,7 +22,14 @@ namespace Explorer
}
catch (ReflectionTypeLoadException e)
{
return e.Types.Where(t => t != null);
try
{
return asm.GetExportedTypes();
}
catch
{
return e.Types.Where(t => t != null);
}
}
catch
{

View File

@ -5,18 +5,41 @@ using UnityEngine;
namespace Explorer
{
/// <summary>
/// Version-agnostic UnityEngine Input module using Reflection.
/// Version-agnostic Input module using Reflection.
/// </summary>
public static class InputHelper
{
// If Input module failed to load at all
public static bool NO_INPUT;
// Base UnityEngine.Input class
private static Type Input => _input ?? (_input = ReflectionHelpers.GetTypeByName("UnityEngine.Input"));
// If using new InputSystem module
public static bool USING_NEW_INPUT;
// Cached Types
private static Type TInput => _input ?? (_input = ReflectionHelpers.GetTypeByName("UnityEngine.Input"));
private static Type _input;
// Cached member infos
private static Type TKeyboard => _keyboardSys ?? (_keyboardSys = ReflectionHelpers.GetTypeByName("UnityEngine.InputSystem.Keyboard"));
private static Type _keyboardSys;
private static Type TMouse => _mouseSys ?? (_mouseSys = ReflectionHelpers.GetTypeByName("UnityEngine.InputSystem.Mouse"));
private static Type _mouseSys;
private static Type TKey => _key ?? (_key = ReflectionHelpers.GetTypeByName("UnityEngine.InputSystem.Key"));
private static Type _key;
// Cached member infos (new system)
private static PropertyInfo _keyboardCurrent;
private static PropertyInfo _kbItemProp;
private static PropertyInfo _isPressed;
private static PropertyInfo _wasPressedThisFrame;
private static PropertyInfo _mouseCurrent;
private static PropertyInfo _leftButton;
private static PropertyInfo _rightButton;
private static PropertyInfo _position;
private static MethodInfo _readValueMethod;
// Cached member infos (legacy)
private static PropertyInfo _mousePosition;
private static MethodInfo _getKey;
private static MethodInfo _getKeyDown;
@ -25,49 +48,153 @@ namespace Explorer
public static void Init()
{
if (Input == null && !TryManuallyLoadInput())
if (TKeyboard != null || TryManuallyLoadNewInput())
{
NO_INPUT = true;
InitNewInput();
return;
}
// Cache reflection now that we know Input is loaded
if (TInput != null || TryManuallyLoadLegacyInput())
{
InitLegacyInput();
return;
}
_mousePosition = Input.GetProperty("mousePosition");
_getKey = Input.GetMethod("GetKey", new Type[] { typeof(KeyCode) });
_getKeyDown = Input.GetMethod("GetKeyDown", new Type[] { typeof(KeyCode) });
_getMouseButton = Input.GetMethod("GetMouseButton", new Type[] { typeof(int) });
_getMouseButtonDown = Input.GetMethod("GetMouseButtonDown", new Type[] { typeof(int) });
ExplorerCore.LogWarning("Could not find any Input module!");
NO_INPUT = true;
}
#pragma warning disable IDE1006 // Camel-case property (Unity style)
public static Vector3 mousePosition
private static void InitNewInput()
{
ExplorerCore.Log("Initializing new InputSystem support...");
USING_NEW_INPUT = true;
_keyboardCurrent = TKeyboard.GetProperty("current");
_kbItemProp = TKeyboard.GetProperty("Item", new Type[] { TKey });
var btnControl = ReflectionHelpers.GetTypeByName("UnityEngine.InputSystem.Controls.ButtonControl");
_isPressed = btnControl.GetProperty("isPressed");
_wasPressedThisFrame = btnControl.GetProperty("wasPressedThisFrame");
_mouseCurrent = TMouse.GetProperty("current");
_leftButton = TMouse.GetProperty("leftButton");
_rightButton = TMouse.GetProperty("rightButton");
_position = ReflectionHelpers.GetTypeByName("UnityEngine.InputSystem.Pointer")
.GetProperty("position");
_readValueMethod = ReflectionHelpers.GetTypeByName("UnityEngine.InputSystem.InputControl`1")
.MakeGenericType(typeof(Vector2))
.GetMethod("ReadValue");
}
private static void InitLegacyInput()
{
ExplorerCore.Log("Initializing Legacy Input support...");
_mousePosition = TInput.GetProperty("mousePosition");
_getKey = TInput.GetMethod("GetKey", new Type[] { typeof(KeyCode) });
_getKeyDown = TInput.GetMethod("GetKeyDown", new Type[] { typeof(KeyCode) });
_getMouseButton = TInput.GetMethod("GetMouseButton", new Type[] { typeof(int) });
_getMouseButtonDown = TInput.GetMethod("GetMouseButtonDown", new Type[] { typeof(int) });
}
private static bool TryManuallyLoadNewInput()
{
if (ReflectionHelpers.LoadModule("Unity.InputSystem") && TKeyboard != null)
{
ExplorerCore.Log("Loaded new InputSystem module!");
return true;
}
else
{
return false;
}
}
private static bool TryManuallyLoadLegacyInput()
{
if ((ReflectionHelpers.LoadModule("UnityEngine.InputLegacyModule") || ReflectionHelpers.LoadModule("UnityEngine.CoreModule"))
&& TInput != null)
{
ExplorerCore.Log("Loaded legacy InputModule!");
return true;
}
else
{
return false;
}
}
public static Vector3 MousePosition
{
get
{
if (NO_INPUT) return Vector3.zero;
if (USING_NEW_INPUT)
{
var mouse = _mouseCurrent.GetValue(null, null);
var pos = _position.GetValue(mouse, null);
return (Vector2)_readValueMethod.Invoke(pos, new object[0]);
}
return (Vector3)_mousePosition.GetValue(null, null);
}
}
#pragma warning restore IDE1006
public static bool GetKeyDown(KeyCode key)
{
if (NO_INPUT) return false;
if (USING_NEW_INPUT)
{
var parsed = Enum.Parse(TKey, key.ToString());
var currentKB = _keyboardCurrent.GetValue(null, null);
var actualKey = _kbItemProp.GetValue(currentKB, new object[] { parsed });
return (bool)_wasPressedThisFrame.GetValue(actualKey, null);
}
return (bool)_getKeyDown.Invoke(null, new object[] { key });
}
public static bool GetKey(KeyCode key)
{
if (NO_INPUT) return false;
if (USING_NEW_INPUT)
{
var parsed = Enum.Parse(TKey, key.ToString());
var currentKB = _keyboardCurrent.GetValue(null, null);
var actualKey = _kbItemProp.GetValue(currentKB, new object[] { parsed });
return (bool)_isPressed.GetValue(actualKey, null);
}
return (bool)_getKey.Invoke(null, new object[] { key });
}
/// <param name="btn">1 = left, 2 = middle, 3 = right, etc</param>
/// <param name="btn">0/1 = left, 2 = middle, 3 = right, etc</param>
public static bool GetMouseButtonDown(int btn)
{
if (NO_INPUT) return false;
if (USING_NEW_INPUT)
{
var mouse = _mouseCurrent.GetValue(null, null);
PropertyInfo btnProp;
if (btn < 2) btnProp = _leftButton;
else btnProp = _rightButton;
var actualBtn = btnProp.GetValue(mouse, null);
return (bool)_wasPressedThisFrame.GetValue(actualBtn, null);
}
return (bool)_getMouseButtonDown.Invoke(null, new object[] { btn });
}
@ -75,24 +202,21 @@ namespace Explorer
public static bool GetMouseButton(int btn)
{
if (NO_INPUT) return false;
if (USING_NEW_INPUT)
{
var mouse = _mouseCurrent.GetValue(null, null);
PropertyInfo btnProp;
if (btn < 2) btnProp = _leftButton;
else btnProp = _rightButton;
var actualBtn = btnProp.GetValue(mouse, null);
return (bool)_isPressed.GetValue(actualBtn, null);
}
return (bool)_getMouseButton.Invoke(null, new object[] { btn });
}
private static bool TryManuallyLoadInput()
{
ExplorerCore.Log("UnityEngine.Input is null, trying to load manually....");
if ((ReflectionHelpers.LoadModule("UnityEngine.InputLegacyModule.dll") || ReflectionHelpers.LoadModule("UnityEngine.CoreModule.dll"))
&& Input != null)
{
ExplorerCore.Log("Ok!");
return true;
}
else
{
ExplorerCore.Log("Could not load Input module!");
return false;
}
}
}
}

View File

@ -94,7 +94,7 @@ namespace Explorer
{
GUILayout.Label("Limit: ", new GUILayoutOption[] { GUILayout.Width(50) });
var limit = this.ItemsPerPage.ToString();
limit = GUILayout.TextField(limit, new GUILayoutOption[] { GUILayout.Width(50) });
limit = GUIUnstrip.TextField(limit, new GUILayoutOption[] { GUILayout.Width(50) });
if (limit != ItemsPerPage.ToString() && int.TryParse(limit, out int i))
{
ItemsPerPage = i;

View File

@ -20,10 +20,10 @@ namespace Explorer
#if CPP
public static ILType GameObjectType => Il2CppType.Of<GameObject>();
public static ILType TransformType => Il2CppType.Of<Transform>();
public static ILType ObjectType => Il2CppType.Of<UnityEngine.Object>();
public static ILType ComponentType => Il2CppType.Of<Component>();
public static ILType BehaviourType => Il2CppType.Of<Behaviour>();
public static ILType TransformType => Il2CppType.Of<Transform>();
public static ILType ObjectType => Il2CppType.Of<UnityEngine.Object>();
public static ILType ComponentType => Il2CppType.Of<Component>();
public static ILType BehaviourType => Il2CppType.Of<Behaviour>();
private static readonly MethodInfo tryCastMethodInfo = typeof(Il2CppObjectBase).GetMethod("TryCast");
private static readonly Dictionary<Type, MethodInfo> cachedTryCastMethods = new Dictionary<Type, MethodInfo>();
@ -41,10 +41,10 @@ namespace Explorer
}
#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);
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)
@ -148,7 +148,12 @@ namespace Explorer
public static bool LoadModule(string module)
{
var path = $@"MelonLoader\Managed\{module}";
#if CPP
#if ML
var path = $@"MelonLoader\Managed\{module}.dll";
#else
var path = $@"BepInEx\unhollowed\{module}.dll";
#endif
if (!File.Exists(path)) return false;
try
@ -159,8 +164,9 @@ namespace Explorer
catch (Exception e)
{
ExplorerCore.Log(e.GetType() + ", " + e.Message);
return false;
}
#endif
return false;
}
public static string ExceptionToString(Exception e)
@ -175,7 +181,6 @@ namespace Explorer
return "Garbage collected in Il2Cpp.";
}
#endif
return e.GetType() + ", " + e.Message;
}

View File

@ -74,9 +74,9 @@ namespace Explorer
var harmony =
#if ML
Explorer_MelonMod.Instance.harmonyInstance;
ExplorerMelonMod.Instance.harmonyInstance;
#else
Explorer_BepInPlugin.HarmonyInstance;
ExplorerBepInPlugin.HarmonyInstance;
#endif
;

View File

@ -33,7 +33,7 @@ namespace Explorer
if (!UnityHelpers.MainCamera)
return;
var ray = UnityHelpers.MainCamera.ScreenPointToRay(InputHelper.mousePosition);
var ray = UnityHelpers.MainCamera.ScreenPointToRay(InputHelper.MousePosition);
if (Physics.Raycast(ray, out RaycastHit hit, 1000f))
{
@ -61,7 +61,7 @@ namespace Explorer
{
if (m_objUnderMouseName != "")
{
var pos = InputHelper.mousePosition;
var pos = InputHelper.MousePosition;
var rect = new Rect(
pos.x - (Screen.width / 2), // x
Screen.height - pos.y - 50, // y

View File

@ -30,7 +30,9 @@ namespace Explorer
"System.Collections",
"System.Collections.Generic",
"System.Reflection",
#if ML
"MelonLoader"
#endif
};
public override void Init()
@ -42,9 +44,14 @@ namespace Explorer
{
MethodInput = @"// This is a basic C# console.
// Some common using directives are added by default, you can add more below.
// If you want to return some output, Debug.Log() it.
Debug.Log(""hello world"");";
// If you want to return some output, Debug.Log() or MelonLogger.Log() it.
"
#if ML
+ @"MelonLogger.Log(""hello world"");";
#else
+ @"Debug.Log(""hello world"");";
#endif
;
ResetConsole();
@ -158,7 +165,7 @@ Debug.Log(""hello world"");";
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
GUILayout.Label("Add namespace:", new GUILayoutOption[] { GUILayout.Width(105) });
UsingInput = GUILayout.TextField(UsingInput, new GUILayoutOption[] { GUILayout.Width(150) });
UsingInput = GUIUnstrip.TextField(UsingInput, new GUILayoutOption[] { GUILayout.Width(150) });
if (GUILayout.Button("<b><color=lime>Add</color></b>", new GUILayoutOption[] { GUILayout.Width(120) }))
{
AddUsing(UsingInput);

View File

@ -229,9 +229,12 @@ namespace Explorer
GUILayout.EndVertical();
}
catch
catch (Exception e)
{
// supress
if (!e.Message.Contains("in a group with only"))
{
ExplorerCore.Log(e.ToString());
}
}
}
@ -250,7 +253,7 @@ namespace Explorer
GUILayout.BeginHorizontal(GUIContent.none, GUI.skin.box, null);
GUILayout.Label("<b>Search Scene:</b>", new GUILayoutOption[] { GUILayout.Width(100) });
m_searchInput = GUILayout.TextField(m_searchInput, new GUILayoutOption[0]);
m_searchInput = GUIUnstrip.TextField(m_searchInput, new GUILayoutOption[0]);
if (GUILayout.Button("Search", new GUILayoutOption[] { GUILayout.Width(80) }))
{

View File

@ -76,7 +76,7 @@ namespace Explorer
}
#endif
var cache = CacheObjectBase.GetCacheObject(toCache);
var cache = CacheFactory.GetTypeAndCacheObject(toCache);
m_searchResults.Add(cache);
}
@ -175,7 +175,7 @@ namespace Explorer
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
GUILayout.Label("Name Contains:", new GUILayoutOption[] { GUILayout.Width(100) });
m_searchInput = GUILayout.TextField(m_searchInput, new GUILayoutOption[] { GUILayout.Width(200) });
m_searchInput = GUIUnstrip.TextField(m_searchInput, new GUILayoutOption[] { GUILayout.Width(200) });
GUILayout.EndHorizontal();
@ -193,7 +193,7 @@ namespace Explorer
GUI.skin.label.alignment = TextAnchor.MiddleRight;
GUILayout.Label("Custom Class:", new GUILayoutOption[] { GUILayout.Width(250) });
GUI.skin.label.alignment = TextAnchor.UpperLeft;
m_typeInput = GUILayout.TextField(m_typeInput, new GUILayoutOption[] { GUILayout.Width(250) });
m_typeInput = GUIUnstrip.TextField(m_typeInput, new GUILayoutOption[] { GUILayout.Width(250) });
GUILayout.EndHorizontal();
}

View File

@ -8,7 +8,9 @@ namespace Explorer
{
public class ResizeDrag
{
#if CPP
private static bool RESIZE_FAILED = false;
#endif
private static readonly GUIContent gcDrag = new GUIContent("<-- Drag to resize -->");
private static bool isResizing = false;
@ -17,6 +19,7 @@ namespace Explorer
public static Rect ResizeWindow(Rect _rect, int ID)
{
#if CPP
if (!RESIZE_FAILED)
{
var origRect = _rect;
@ -26,20 +29,16 @@ namespace Explorer
GUILayout.BeginHorizontal(GUIContent.none, GUI.skin.box, null);
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
#if CPP
#if ML
GUILayout.Button(gcDrag, GUI.skin.label, new GUILayoutOption[] { GUILayout.Height(15) });
#else
GUILayout.Button(gcDrag.ToString(), new GUILayoutOption[] { GUILayout.Height(15) });
#endif
#else
GUILayout.Button(gcDrag, GUI.skin.label, new GUILayoutOption[] { GUILayout.Height(15) });
#endif
//var r = GUILayoutUtility.GetLastRect();
var r = LayoutUtilityUnstrip.GetLastRect();
var r = Internal_LayoutUtility.GetLastRect();
var mousePos = InputHelper.mousePosition;
var mousePos = InputHelper.MousePosition;
try
{
@ -116,6 +115,42 @@ namespace Explorer
GUI.skin.label.alignment = TextAnchor.UpperLeft;
}
#else // mono
GUILayout.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 = InputHelper.MousePosition;
var mouse = GUIUnstrip.ScreenToGUIPoint(new Vector2(mousePos.x, Screen.height - mousePos.y));
if (r.Contains(mouse) && InputHelper.GetMouseButtonDown(0))
{
isResizing = true;
m_currentWindow = ID;
m_currentResize = new Rect(mouse.x, mouse.y, _rect.width, _rect.height);
}
else if (!InputHelper.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
return _rect;
}
}

View File

@ -21,7 +21,7 @@ namespace Explorer
public const string Local = "#a6e9e9";
public const string StructGreen = "#b8d7a3";
public const string StructGreen = "#92c470";
}
public static Color LightGreen = new Color(Color.green.r - 0.3f, Color.green.g - 0.3f, Color.green.b - 0.3f);

View File

@ -369,8 +369,8 @@ namespace Explorer
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
var width = m_rect.width / 2 - 115f;
m_addComponentInput = GUILayout.TextField(m_addComponentInput, new GUILayoutOption[] { GUILayout.Width(width) });
var width = m_rect.width / 2 - 135f;
m_addComponentInput = GUIUnstrip.TextField(m_addComponentInput, new GUILayoutOption[] { GUILayout.Width(width) });
if (GUILayout.Button("Add Comp", new GUILayoutOption[0]))
{
if (ReflectionHelpers.GetTypeByName(m_addComponentInput) is Type compType)
@ -532,7 +532,7 @@ namespace Explorer
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
m_setParentInput = GUILayout.TextField(m_setParentInput, new GUILayoutOption[0]);
m_setParentInput = GUIUnstrip.TextField(m_setParentInput, new GUILayoutOption[0]);
if (GUILayout.Button("Set Parent", new GUILayoutOption[] { GUILayout.Width(80) }))
{
if (GameObject.Find(m_setParentInput) is GameObject newparent)
@ -682,7 +682,7 @@ namespace Explorer
GUILayout.Label("+/-:", new GUILayoutOption[] { GUILayout.Width(30) });
var amountInput = amount.ToString("F3");
amountInput = GUILayout.TextField(amountInput, new GUILayoutOption[] { GUILayout.Width(60) });
amountInput = GUIUnstrip.TextField(amountInput, new GUILayoutOption[] { GUILayout.Width(60) });
if (float.TryParse(amountInput, out float f))
{
amount = f;
@ -697,7 +697,7 @@ namespace Explorer
private void PlusMinusFloat(ref float f, float amount, bool multByTime)
{
string s = f.ToString("F3");
s = GUILayout.TextField(s, new GUILayoutOption[] { GUILayout.Width(60) });
s = GUIUnstrip.TextField(s, new GUILayoutOption[] { GUILayout.Width(60) });
if (float.TryParse(s, out float f2))
{
f = f2;

View File

@ -204,7 +204,7 @@ namespace Explorer
try
{
var cached = CacheObjectBase.GetCacheObject(member, target);
var cached = CacheFactory.GetTypeAndCacheObject(member, target);
if (cached != null)
{
cachedSigs.Add(sig);
@ -272,7 +272,7 @@ namespace Explorer
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
GUILayout.Label("<b>Search:</b>", new GUILayoutOption[] { GUILayout.Width(75) });
m_search = GUILayout.TextField(m_search, new GUILayoutOption[0]);
m_search = GUIUnstrip.TextField(m_search, new GUILayoutOption[0]);
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal(new GUILayoutOption[0]);

View File

@ -189,7 +189,7 @@ namespace Explorer
private static bool RectContainsMouse(Rect rect)
{
var mousePos = InputHelper.mousePosition;
var mousePos = InputHelper.MousePosition;
return rect.Contains(new Vector2(mousePos.x, Screen.height - mousePos.y));
}

View File

@ -6,7 +6,7 @@ using Explorer;
#if ML
using MelonLoader;
[assembly: MelonInfo(typeof(Explorer_MelonMod), ExplorerCore.NAME, ExplorerCore.VERSION, ExplorerCore.AUTHOR)]
[assembly: MelonInfo(typeof(ExplorerMelonMod), "Explorer", ExplorerCore.VERSION, ExplorerCore.AUTHOR)]
[assembly: MelonGame(null, null)]
#endif

View File

@ -1,7 +1,9 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;
#if CPP
using Explorer.UnstripInternals;
using UnityEngineInternal;
using UnhollowerRuntimeLib;
#endif
@ -10,50 +12,14 @@ namespace Explorer
{
public class GUIUnstrip
{
#if CPP
public static int s_ScrollControlId;
public static bool ScrollFailed = false;
public static bool ManualUnstripFailed = false;
private static GenericStack ScrollStack => m_scrollStack ?? GetScrollStack();
private static PropertyInfo m_scrollViewStatesInfo;
private static GenericStack m_scrollStack;
public static DateTime nextScrollStepTime;
private static MethodInfo ScreenToGuiPointMethod;
private static bool m_screenToGuiAttemped;
private static MethodInfo m_bringWindowToFrontMethod;
private static bool m_bringWindowFrontAttempted;
private static GenericStack GetScrollStack()
public static string TextField(string text, GUILayoutOption[] options)
{
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;
}
#if CPP
return Internal.TextField(text, options);
#else
return GUILayout.TextField(text, options);
#endif
}
public static Rect Window(int id, Rect rect, GUI.WindowFunction windowFunc, string title)
{
@ -85,17 +51,7 @@ namespace Explorer
public static void BringWindowToFront(int id)
{
#if CPP
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 });
Internal.BringWindowToFront(id);
#else
GUI.BringWindowToFront(id);
#endif
@ -104,16 +60,7 @@ namespace Explorer
public static Vector2 ScreenToGUIPoint(Vector2 screenPoint)
{
#if CPP
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 });
return Internal.ScreenToGUIPoint(screenPoint);
#else
return GUIUtility.ScreenToGUIPoint(screenPoint);
#endif
@ -122,499 +69,56 @@ namespace Explorer
public static void Space(float pixels)
{
#if CPP
if (GUILayoutUtility.current.topLevel.isVertical)
LayoutUtilityUnstrip.GetRect(0, pixels, GUILayoutUtility.spaceStyle, new GUILayoutOption[] { GUILayout.Height(pixels) });
else
LayoutUtilityUnstrip.GetRect(pixels, 0, GUILayoutUtility.spaceStyle, new GUILayoutOption[] { GUILayout.Width(pixels) });
if (Event.current.type == EventType.Layout)
{
GUILayoutUtility.current.topLevel.entries[GUILayoutUtility.current.topLevel.entries.Count - 1].consideredForMargin = false;
}
Internal.Space(pixels);
#else
GUILayout.Space(pixels);
#endif
}
// fix for repeatbutton
public static bool RepeatButton(string text, params GUILayoutOption[] options)
{
#if CPP
#if ML
static public bool RepeatButton(Texture image, params GUILayoutOption[] options) { return DoRepeatButton(GUIContent.Temp(image), GUI.skin.button, options); }
static public bool RepeatButton(GUIContent content, params GUILayoutOption[] options) { return DoRepeatButton(content, GUI.skin.button, options); }
static public bool RepeatButton(Texture image, GUIStyle style, params GUILayoutOption[] options) { return DoRepeatButton(GUIContent.Temp(image), style, options); }
// Make a repeating button. The button returns true as long as the user holds down the mouse
#endif
static public bool RepeatButton(string text, params GUILayoutOption[] options) { return DoRepeatButton(GUIContent.Temp(text), GUI.skin.button, options); }
static public bool RepeatButton(GUIContent content, GUIStyle style, params GUILayoutOption[] options) { return DoRepeatButton(content, style, options); }
static bool DoRepeatButton(GUIContent content, GUIStyle style, GUILayoutOption[] options)
{
return GUI.DoRepeatButton(LayoutUtilityUnstrip.GetRect(content, style, options), content, style, FocusType.Passive);
}
#else // mono
public static bool RepeatButton(string text, params GUILayoutOption[] args)
{
return GUILayout.RepeatButton(text, args);
}
#endif
// Fix for BeginArea
#if CPP
#if ML
static public void BeginArea(Rect screenRect) { BeginArea(screenRect, GUIContent.none, GUIStyle.none); }
static public void BeginArea(Rect screenRect, string text) { BeginArea(screenRect, GUIContent.Temp(text), GUIStyle.none); }
static public void BeginArea(Rect screenRect, Texture image) { BeginArea(screenRect, GUIContent.Temp(image), GUIStyle.none); }
static public void BeginArea(Rect screenRect, GUIContent content) { BeginArea(screenRect, content, GUIStyle.none); }
static public void BeginArea(Rect screenRect, string text, GUIStyle style) { BeginArea(screenRect, GUIContent.Temp(text), style); }
static public void BeginArea(Rect screenRect, Texture image, GUIStyle style) { BeginArea(screenRect, GUIContent.Temp(image), style); }
#endif
static public void BeginArea(Rect screenRect, GUIStyle style) { BeginArea(screenRect, GUIContent.none, style); }
static public void BeginArea(Rect screenRect, GUIContent content, GUIStyle style)
{
GUILayoutGroup g = GUILayoutUtility.BeginLayoutArea(style, Il2CppType.Of<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);
}
GUI.BeginGroup(g.rect, content, style);
}
return Internal.DoRepeatButton(GUIContent.Temp(text), GUI.skin.button, options);
#else
public static void BeginArea(Rect rect, GUIStyle skin)
{
GUILayout.BeginArea(rect, skin);
}
return GUILayout.RepeatButton(text, options);
#endif
}
// Close a GUILayout block started with BeginArea
public static void BeginArea(Rect screenRect, GUIStyle style)
{
#if CPP
Internal.BeginArea(screenRect, GUIContent.none, style);
#else
GUILayout.BeginArea(screenRect, style);
#endif
}
static public void EndArea()
{
if (Event.current.type == EventType.Used)
return;
GUILayoutUtility.current.layoutGroups.Pop();
GUILayoutUtility.current.topLevel = GUILayoutUtility.current.layoutGroups.Peek().TryCast<GUILayoutGroup>();
GUI.EndGroup();
}
#if CPP
Internal.EndArea();
#else
public static void EndArea()
{
GUILayout.EndArea();
}
#endif
// Fix for BeginGroup
#if CPP
#if ML
public static void BeginGroup(Rect position) { BeginGroup(position, GUIContent.none, GUIStyle.none); }
public static void BeginGroup(Rect position, string text) { BeginGroup(position, GUIContent.Temp(text), GUIStyle.none); }
public static void BeginGroup(Rect position, Texture image) { BeginGroup(position, GUIContent.Temp(image), GUIStyle.none); }
public static void BeginGroup(Rect position, GUIContent content) { BeginGroup(position, content, GUIStyle.none); }
public static void BeginGroup(Rect position, GUIStyle style) { BeginGroup(position, GUIContent.none, style); }
public static void BeginGroup(Rect position, string text, GUIStyle style) { BeginGroup(position, GUIContent.Temp(text), style); }
public static void BeginGroup(Rect position, Texture image, GUIStyle style) { BeginGroup(position, GUIContent.Temp(image), style); }
#endif
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);
}
#else
public static void BeginGroup(Rect rect, GUIStyle style)
{
GUI.BeginGroup(rect, style);
}
#endif
#if CPP
public static void EndGroup()
{
GUIClip.Internal_Pop();
}
#else
public static void EndGroup()
{
GUI.EndGroup();
}
#endif
// Fix for BeginScrollView.
#if CPP
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;
#if CPP
return Internal.BeginScrollView(scroll, options);
#else
return GUILayout.BeginScrollView(scroll, options);
#endif
}
public static void EndScrollView(bool handleScrollWheel = true)
{
// Only end the scroll view for the relevant BeginScrollView option, if any.
if (!ScrollFailed)
{
GUILayout.EndScrollView();
}
else if (!ManualUnstripFailed)
{
GUILayoutUtility.EndLayoutGroup();
EndScrollView_Impl(handleScrollWheel);
}
}
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 = GUIUtility.GetStateObject(Il2CppType.Of<ScrollViewState>(), controlID).TryCast<ScrollViewState>();
var scrollExt = ScrollViewStateUnstrip.FromPointer(scrollViewState.Pointer);
if (scrollExt == null) throw new Exception($"Could not get scrollExt for pointer '{scrollViewState.Pointer}'!");
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 = HorizBar_Impl(
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 = VertBar_Impl(
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 HorizBar_Impl(Rect position, float value, float size, float leftValue, float rightValue, GUIStyle style)
{
return Scroller_Impl(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 VertBar_Impl(Rect position, float value, float size, float topValue, float bottomValue, GUIStyle style)
{
return Scroller_Impl(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 void EndScrollView_Impl(bool handleScrollWheel)
{
GUIUtility.CheckOnGUI();
if (ScrollStack.Count <= 0) return;
var state = ScrollStack.Peek().TryCast<ScrollViewState>();
var scrollExt = ScrollViewStateUnstrip.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 float Scroller_Impl(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_Impl(position2, value, size, leftValue, rightValue, slider, thumb, horiz, controlID);
bool flag = Event.current.type == EventType.MouseUp;
if (ScrollerRepeatButton_Impl(controlID, rect, leftButton))
{
value -= 10f * ((leftValue >= rightValue) ? -1f : 1f);
}
if (ScrollerRepeatButton_Impl(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_Impl(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_Impl(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;
}
#if CPP
Internal.EndScrollView(handleScrollWheel);
#else
public static Vector2 BeginScrollView(Vector2 scroll, params GUILayoutOption[] options)
{
return GUILayout.BeginScrollView(scroll, options);
}
public static void EndScrollView()
{
GUILayout.EndScrollView();
}
#endif
}
}
}

View File

@ -0,0 +1,678 @@
#if CPP
using System;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;
using UnityEngineInternal;
using UnhollowerRuntimeLib;
namespace Explorer.UnstripInternals
{
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 string TextField(string text, GUILayoutOption[] options)
{
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,34 +1,17 @@
using UnityEngine;
#if CPP
using UnityEngine;
using Explorer.UnstripInternals;
namespace Explorer
{
public class LayoutUtilityUnstrip
public class Internal_LayoutUtility
{
#if CPP
public static Rect GetRect(float width, float height) { return DoGetRect(width, width, height, height, GUIStyle.none, null); }
public static Rect GetRect(float width, float height, GUIStyle style) { return DoGetRect(width, width, height, height, style, null); }
public static Rect GetRect(float width, float height, params GUILayoutOption[] options) { return DoGetRect(width, width, height, height, GUIStyle.none, options); }
// Reserve layout space for a rectangle with a fixed content area.
public static Rect GetRect(float width, float height, GUIStyle style, params GUILayoutOption[] options)
{ return DoGetRect(width, width, height, height, style, options); }
public static Rect GetRect(float minWidth, float maxWidth, float minHeight, float maxHeight)
{ return DoGetRect(minWidth, maxWidth, minHeight, maxHeight, GUIStyle.none, null); }
public static Rect GetRect(float minWidth, float maxWidth, float minHeight, float maxHeight, GUIStyle style)
{ return DoGetRect(minWidth, maxWidth, minHeight, maxHeight, style, null); }
public static Rect GetRect(float minWidth, float maxWidth, float minHeight, float maxHeight, params GUILayoutOption[] options)
{ return DoGetRect(minWidth, maxWidth, minHeight, maxHeight, GUIStyle.none, options); }
// Reserve layout space for a flexible rect.
public static Rect GetRect(float minWidth, float maxWidth, float minHeight, float maxHeight, GUIStyle style, params GUILayoutOption[] options)
{ return DoGetRect(minWidth, maxWidth, minHeight, maxHeight, style, options); }
static Rect DoGetRect(float minWidth, float maxWidth, float minHeight, float maxHeight, GUIStyle style, GUILayoutOption[] options)
{
switch (Event.current.type)
{
case EventType.Layout:
GUILayoutUtility.current.topLevel.Add(new GUILayoutEntry(minWidth, maxWidth, minHeight, maxHeight, style, options));
GUILayoutUtility.current.topLevel.Add(new GUILayoutEntry(width, width, height, height, style, options));
return GUILayoutUtility.kDummyRect;
case EventType.Used:
return GUILayoutUtility.kDummyRect;
@ -36,14 +19,14 @@ namespace Explorer
return GUILayoutUtility.current.topLevel.GetNext().rect;
}
}
public static Rect GetRect(GUIContent content, GUIStyle style) { return DoGetRect(content, style, null); }
// Reserve layout space for a rectangle for displaying some contents with a specific style.
public static Rect GetRect(GUIContent content, GUIStyle style, params GUILayoutOption[] options) { return DoGetRect(content, style, options); }
public static Rect GetRect(GUIContent content, GUIStyle style, params GUILayoutOption[] options)
{
return DoGetRect(content, style, options);
}
static Rect DoGetRect(GUIContent content, GUIStyle style, GUILayoutOption[] options)
{
GUIUtility.CheckOnGUI();
switch (Event.current.type)
{
case EventType.Layout:
@ -96,7 +79,7 @@ namespace Explorer
Rect last;
if (type != EventType.Layout && type != EventType.Used)
{
last = GUILayoutUtility.current.topLevel.GetLastUnstripped();
last = GUILayoutUtility.current.topLevel.Unstripped_GetLast();
}
else
{
@ -104,11 +87,6 @@ namespace Explorer
}
return last;
}
#else
public static Rect GetLastRect()
{
return GUILayoutUtility.GetLastRect();
}
#endif
}
}
}
#endif

View File

@ -5,7 +5,7 @@ using UnityEngine;
namespace Explorer
{
public class ScrollViewStateUnstrip
public class Internal_ScrollViewState
{
public Rect position;
public Rect visibleRect;
@ -13,18 +13,17 @@ namespace Explorer
public Vector2 scrollPosition;
public bool apply;
public static Dictionary<IntPtr, ScrollViewStateUnstrip> Dict = new Dictionary<IntPtr, ScrollViewStateUnstrip>();
public static Dictionary<IntPtr, Internal_ScrollViewState> Dict = new Dictionary<IntPtr, Internal_ScrollViewState>();
public static ScrollViewStateUnstrip FromPointer(IntPtr ptr)
public static Internal_ScrollViewState FromPointer(IntPtr ptr)
{
if (!Dict.ContainsKey(ptr))
{
Dict.Add(ptr, new ScrollViewStateUnstrip());
Dict.Add(ptr, new Internal_ScrollViewState());
}
return Dict[ptr];
}
}
}
#endif

View File

@ -2,11 +2,53 @@
using System;
using UnhollowerRuntimeLib;
using UnityEngine;
using Explorer.UnstripInternals;
using Il2CppSystem.Reflection;
namespace Explorer
{
public struct SliderHandlerUnstrip
public struct Internal_SliderHandler
{
public static int ScrollTroughSide
{
get
{
if (!m_getScrollTroughSideFailed)
{
try
{
return GUI.scrollTroughSide;
}
catch
{
m_getScrollTroughSideFailed = true;
}
}
return m_manualScrollTrough;
}
set
{
if (!m_setScrollTroughSideFailed)
{
try
{
GUI.scrollTroughSide = value;
return;
}
catch
{
m_setScrollTroughSideFailed = true;
}
}
m_manualScrollTrough = value;
}
}
private static bool m_getScrollTroughSideFailed;
private static bool m_setScrollTroughSideFailed;
private static int m_manualScrollTrough;
private readonly Rect position;
private readonly float currentValue;
private readonly float size;
@ -17,7 +59,8 @@ namespace Explorer
private readonly bool horiz;
private readonly int id;
public SliderHandlerUnstrip(Rect position, float currentValue, float size, float start, float end, GUIStyle slider, GUIStyle thumb, bool horiz, int id)
public Internal_SliderHandler(Rect position, float currentValue, float size, float start,
float end, GUIStyle slider, GUIStyle thumb, bool horiz, int id)
{
this.position = position;
this.currentValue = currentValue;
@ -64,7 +107,7 @@ namespace Explorer
}
else
{
GUI.scrollTroughSide = 0;
ScrollTroughSide = 0;
GUIUtility.hotControl = this.id;
this.CurrentEvent().Use();
if (this.ThumbSelectionRect().Contains(this.CurrentEvent().mousePosition))
@ -77,9 +120,10 @@ namespace Explorer
GUI.changed = true;
if (this.SupportsPageMovements())
{
this.SliderState().isDragging = false;
GUIUnstrip.nextScrollStepTime = DateTime.Now.AddMilliseconds(250.0);
GUI.scrollTroughSide = this.CurrentScrollTroughSide();
var ext = Internal_SliderState.FromPointer(GetSliderState().Pointer);
ext.isDragging = false;
Internal.nextScrollStepTime = DateTime.Now.AddMilliseconds(250.0);
ScrollTroughSide = this.CurrentScrollTroughSide();
result = this.PageMovementValue();
}
else
@ -102,8 +146,8 @@ namespace Explorer
}
else
{
SliderState sliderState = this.SliderState();
if (!sliderState.isDragging)
var ext = Internal_SliderState.FromPointer(GetSliderState().Pointer);
if (!ext.isDragging)
{
result = this.currentValue;
}
@ -111,8 +155,8 @@ namespace Explorer
{
GUI.changed = true;
this.CurrentEvent().Use();
float num = this.MousePosition() - sliderState.dragStartPos;
float value = sliderState.dragStartValue + num / this.ValuesPerPixel();
float num = this.MousePosition() - ext.dragStartPos;
float value = ext.dragStartValue + num / this.ValuesPerPixel();
result = this.Clamp(value);
}
}
@ -143,7 +187,7 @@ namespace Explorer
}
else if (this.ThumbRect().Contains(this.CurrentEvent().mousePosition))
{
if (GUI.scrollTroughSide != 0)
if (ScrollTroughSide != 0)
{
GUIUtility.hotControl = 0;
}
@ -152,20 +196,20 @@ namespace Explorer
else
{
GUI.InternalRepaintEditorWindow();
if (DateTime.Now < GUIUnstrip.nextScrollStepTime)
if (DateTime.Now < Internal.nextScrollStepTime)
{
result = this.currentValue;
}
else if (this.CurrentScrollTroughSide() != GUI.scrollTroughSide)
else if (this.CurrentScrollTroughSide() != ScrollTroughSide)
{
result = this.currentValue;
}
else
{
GUIUnstrip.nextScrollStepTime = DateTime.Now.AddMilliseconds(30.0);
Internal.nextScrollStepTime = DateTime.Now.AddMilliseconds(30.0);
if (this.SupportsPageMovements())
{
this.SliderState().isDragging = false;
Internal_SliderState.FromPointer(GetSliderState().Pointer).isDragging = false;
GUI.changed = true;
result = this.PageMovementValue();
}
@ -261,15 +305,15 @@ namespace Explorer
private void StartDraggingWithValue(float dragStartValue)
{
SliderState sliderState = this.SliderState();
sliderState.dragStartPos = this.MousePosition();
sliderState.dragStartValue = dragStartValue;
sliderState.isDragging = true;
var ext = Internal_SliderState.FromPointer(GetSliderState().Pointer);
ext.dragStartPos = this.MousePosition();
ext.dragStartValue = dragStartValue;
ext.isDragging = true;
}
private SliderState SliderState()
private SliderState GetSliderState()
{
return (SliderState)GUIUtility.GetStateObject(Il2CppType.Of<SliderState>(), this.id).TryCast<SliderState>();
return GUIUtility.GetStateObject(Il2CppType.Of<SliderState>(), this.id).TryCast<SliderState>();
}
private Rect ThumbRect()

View File

@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Explorer
{
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

@ -1,24 +0,0 @@
#if CPP
using UnityEngine;
namespace Explorer
{
public static class UnstripExtensions
{
public static Rect GetLastUnstripped(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;
}
}
}
#endif