mirror of
https://github.com/sinai-dev/UnityExplorer.git
synced 2025-06-23 00:52:31 +08:00
Compare commits
29 Commits
Author | SHA1 | Date | |
---|---|---|---|
6920ca1129 | |||
748e0cabcb | |||
b4b5f1ec93 | |||
5afaf85859 | |||
b65e417ecb | |||
23723a4ffd | |||
dab7ecd441 | |||
f1406d016f | |||
99e801b3bd | |||
20133e123c | |||
142a2a4750 | |||
629403a74d | |||
873d0f277d | |||
99719fafaf | |||
b550356f14 | |||
8c6202c194 | |||
f203ae37fc | |||
2006a9ea76 | |||
c9bc450d09 | |||
a1198f3a92 | |||
04248a89ce | |||
3639824df3 | |||
939861b5f0 | |||
ad5fc04a3b | |||
c39e097378 | |||
129a7e3765 | |||
643bb4519c | |||
b154cbf39d | |||
db91968519 |
93
README.md
93
README.md
@ -1,23 +1,22 @@
|
|||||||
# CppExplorer [](https://github.com/HerpDerpinstine/MelonLoader)
|
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<img align="center" src="icon.png">
|
<img align="center" src="icon.png">
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
An in-game explorer and a suite of debugging tools for <a href="https://docs.unity3d.com/Manual/IL2CPP.html">IL2CPP</a> Unity games, using <a href="https://github.com/HerpDerpinstine/MelonLoader">MelonLoader</a>.<br><br>
|
An in-game explorer and a suite of debugging tools for <a href="https://docs.unity3d.com/Manual/IL2CPP.html">IL2CPP</a> and <b>Mono</b> Unity games, using <a href="https://github.com/HerpDerpinstine/MelonLoader">MelonLoader</a> and <a href="https://github.com/BepInEx/BepInEx">BepInEx</a>.<br><br>
|
||||||
|
|
||||||
<a href="../../releases/latest">
|
<a href="../../releases/latest">
|
||||||
<img src="https://img.shields.io/github/release/sinai-dev/CppExplorer.svg" />
|
<img src="https://img.shields.io/github/release/sinai-dev/Explorer.svg" />
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<img src="https://img.shields.io/github/downloads/sinai-dev/CppExplorer/total.svg" />
|
<img src="https://img.shields.io/github/downloads/sinai-dev/Explorer/total.svg" />
|
||||||
</p>
|
|
||||||
<p align="center">
|
|
||||||
<a href="https://github.com/sinai-dev/MonoExplorer">Looking for a Mono version?</a>
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
- [Known issues](#known-issues)
|
<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 install](#how-to-install)
|
||||||
- [How to use](#how-to-use)
|
- [How to use](#how-to-use)
|
||||||
- [Mod Config](#mod-config)
|
- [Mod Config](#mod-config)
|
||||||
@ -26,21 +25,34 @@
|
|||||||
- [Building](#building)
|
- [Building](#building)
|
||||||
- [Credits](#credits)
|
- [Credits](#credits)
|
||||||
|
|
||||||
## Known issues
|
## Current status
|
||||||
As of version 1.7+, CppExplorer has reached a fairly stable state for most Il2Cpp games.
|
|
||||||
|
|
||||||
|
| 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.
|
* .NET 3.5 is not currently supported (Unity 5.6.1 and older), this might change in the future.
|
||||||
* Some methods may still fail with a `MissingMethodException`, please let me know if you experience this (with full MelonLoader log please).
|
* Some methods may still fail with a `MissingMethodException`, please let me know if you experience this (with full MelonLoader log please).
|
||||||
* Reflection may fail with certain types, see [here](https://github.com/knah/Il2CppAssemblyUnhollower#known-issues) for more details.
|
* Reflection may fail with certain types, see [here](https://github.com/knah/Il2CppAssemblyUnhollower#known-issues) for more details.
|
||||||
* Scrolling with mouse wheel in the CppExplorer menu may not work on all games at the moment.
|
* Scrolling with mouse wheel in the Explorer menu may not work on all games at the moment.
|
||||||
|
|
||||||
## How to install
|
## How to install
|
||||||
|
|
||||||
|
### MelonLoader
|
||||||
Requires [MelonLoader](https://github.com/HerpDerpinstine/MelonLoader) to be installed for your game.
|
Requires [MelonLoader](https://github.com/HerpDerpinstine/MelonLoader) to be installed for your game.
|
||||||
|
|
||||||
1. Download <b>CppExplorer.zip</b> from [Releases](https://github.com/sinai-dev/CppExplorer/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.
|
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, `CppExplorer.dll` and `mcs.dll` should be directly in the `Mods\` folder.
|
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 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
|
## How to use
|
||||||
|
|
||||||
@ -50,24 +62,23 @@ Requires [MelonLoader](https://github.com/HerpDerpinstine/MelonLoader) to be ins
|
|||||||
|
|
||||||
### Mod Config
|
### Mod Config
|
||||||
|
|
||||||
There is a simple Mod Config for the CppExplorer, which is generated the first time you run it.
|
There is a simple Mod Config for the Explorer. You can access the settings via the "Options" page of the main menu.
|
||||||
|
|
||||||
This config is generated to `Mods\CppExplorer\config.xml`. Edit the config while the game is closed if you wish to change it.
|
`Main Menu Toggle` (KeyCode)
|
||||||
|
* Sets the keybinding for the Main Menu toggle (show/hide all Explorer windows)
|
||||||
`Main_Menu_Toggle` (KeyCode)
|
|
||||||
* Sets the keybinding for the Main Menu toggle (show/hide all CppExplorer windows)
|
|
||||||
* See [this article](https://docs.unity3d.com/ScriptReference/KeyCode.html) for a full list of all accepted KeyCodes.
|
* See [this article](https://docs.unity3d.com/ScriptReference/KeyCode.html) for a full list of all accepted KeyCodes.
|
||||||
* Default: `F7`
|
* Default: `F7`
|
||||||
|
|
||||||
`Default_Window_Size` (Vector2)
|
`Default Window Size` (Vector2)
|
||||||
* Sets the default width and height for all CppExplorer windows when created.
|
* Sets the default width and height for all Explorer windows when created.
|
||||||
* `x` is width, `y` is height.
|
* `x` is width, `y` is height.
|
||||||
* Default: `<x>550</x> <y>700</y>`
|
* Default: `<x>550</x> <y>700</y>`
|
||||||
|
|
||||||
## Features
|
`Default Items per Page` (Int)
|
||||||
[](overview.png)
|
* Sets the default items per page when viewing lists or search results.
|
||||||
|
* Default: `20`
|
||||||
|
|
||||||
<i>An overview of the different CppExplorer menus.</i>
|
## Features
|
||||||
|
|
||||||
### Scene Explorer
|
### Scene Explorer
|
||||||
|
|
||||||
@ -76,7 +87,7 @@ This config is generated to `Mods\CppExplorer\config.xml`. Edit the config while
|
|||||||
|
|
||||||
### Inspectors
|
### Inspectors
|
||||||
|
|
||||||
CppExplorer has two main inspector modes: <b>GameObject Inspector</b>, and <b>Reflection Inspector</b>.
|
Explorer has two main inspector modes: <b>GameObject Inspector</b>, and <b>Reflection Inspector</b>.
|
||||||
|
|
||||||
<b>Tips:</b>
|
<b>Tips:</b>
|
||||||
* When in Tab View, GameObjects are denoted by a [G] prefix, and Reflection objects are denoted by a [R] prefix.
|
* When in Tab View, GameObjects are denoted by a [G] prefix, and Reflection objects are denoted by a [R] prefix.
|
||||||
@ -99,19 +110,19 @@ CppExplorer has two main inspector modes: <b>GameObject Inspector</b>, and <b>Re
|
|||||||
* Filter by name, type, etc.
|
* Filter by name, type, etc.
|
||||||
* For GameObjects and Transforms you can filter which scene they are found in too.
|
* For GameObjects and Transforms you can filter which scene they are found in too.
|
||||||
|
|
||||||
### C# REPL console
|
### C# console
|
||||||
|
|
||||||
* A simple C# REPL console, allows you to execute a method body on the fly.
|
* A simple C# console, allows you to execute a method body on the fly.
|
||||||
|
|
||||||
### Inspect-under-mouse
|
### Inspect-under-mouse
|
||||||
|
|
||||||
* Press Shift+RMB (Right Mouse Button) while the CppExplorer menu is open to begin Inspect-Under-Mouse.
|
* Press Shift+RMB (Right Mouse Button) while the Explorer menu is open to begin Inspect-Under-Mouse.
|
||||||
* Hover over your desired object, if you see the name appear then you can click on it to inspect it.
|
* Hover over your desired object, if you see the name appear then you can click on it to inspect it.
|
||||||
* Only objects with Colliders are supported.
|
* Only objects with Colliders are supported.
|
||||||
|
|
||||||
### Mouse Control
|
### Mouse Control
|
||||||
|
|
||||||
CppExplorer can force the mouse to be visible and unlocked when the menu is open, if you have enabled "Force Unlock Mouse" (Left-Alt toggle). However, you may also want to prevent the mouse clicking-through onto the game behind CppExplorer, this is possible but it requires specific patches for that game.
|
Explorer can force the mouse to be visible and unlocked when the menu is open, if you have enabled "Force Unlock Mouse" (Left-Alt toggle). However, you may also want to prevent the mouse clicking-through onto the game behind Explorer, this is possible but it requires specific patches for that game.
|
||||||
|
|
||||||
* For VRChat, use [VRCExplorerMouseControl](https://github.com/sinai-dev/VRCExplorerMouseControl)
|
* For VRChat, use [VRCExplorerMouseControl](https://github.com/sinai-dev/VRCExplorerMouseControl)
|
||||||
* For Hellpoint, use [HPExplorerMouseControl](https://github.com/sinai-dev/Hellpoint-Mods/tree/master/HPExplorerMouseControl/HPExplorerMouseControl)
|
* For Hellpoint, use [HPExplorerMouseControl](https://github.com/sinai-dev/Hellpoint-Mods/tree/master/HPExplorerMouseControl/HPExplorerMouseControl)
|
||||||
@ -120,17 +131,17 @@ CppExplorer can force the mouse to be visible and unlocked when the menu is open
|
|||||||
For example:
|
For example:
|
||||||
```csharp
|
```csharp
|
||||||
using Explorer;
|
using Explorer;
|
||||||
using Harmony;
|
using Harmony; // or 'using HarmonyLib;' for BepInEx
|
||||||
// ...
|
// ...
|
||||||
[HarmonyPatch(typeof(MyGame.MenuClass), nameof(MyGame.MenuClass.CursorUpdate)]
|
[HarmonyPatch(typeof(MyGame.MenuClass), nameof(MyGame.MenuClass.CursorUpdate)]
|
||||||
public class MenuClass_CursorUpdate
|
public class MenuClass_CursorUpdate
|
||||||
{
|
{
|
||||||
[HarmonyPrefix]
|
[HarmonyPrefix]
|
||||||
public static bool Prefix()
|
public static bool Prefix()
|
||||||
{
|
{
|
||||||
// prevent method running if menu open, let it run if not.
|
// prevent method running if menu open, let it run if not.
|
||||||
return !CppExplorer.ShowMenu;
|
return !ExplorerCore.ShowMenu;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -139,11 +150,11 @@ public class MenuClass_CursorUpdate
|
|||||||
If you'd like to build this yourself, everything you need (other than MelonLoader) is included with this repository, there is no need for recursive cloning etc.
|
If you'd like to build this yourself, everything you need (other than MelonLoader) is included with this repository, there is no need for recursive cloning etc.
|
||||||
|
|
||||||
1. Install MelonLoader for your game.
|
1. Install MelonLoader for your game.
|
||||||
2. Open the `src\CppExplorer.csproj` file in a text editor.
|
2. Open the `src\Explorer.csproj` file in a text editor.
|
||||||
3. Scroll down until you see the `<ItemGroup>` containing the References.
|
3. Set the relevant `GameFolder` value(s) for the version(s) you want to build, eg. set `MLCppGameFolder` if you want to build for a MelonLoader Il2Cpp game.
|
||||||
4. Fix all of the paths in the `..\Steam\` directory for your game (use the full path if you need to).
|
4. Open the `src\Explorer.sln` project.
|
||||||
5. Open the `src\CppExplorer.sln` project and build it.
|
5. Select `Solution 'Explorer' (1 of 1 project)` in the Solution Explorer panel, and set the <b>Active config</b> to the version you want to build, then build it.
|
||||||
6. The dll is built to the `Release\` folder in the root of the repository.
|
5. The DLLs are built to the `Release\` folder in the root of the repository.
|
||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
|
|
||||||
|
BIN
icon.png
BIN
icon.png
Binary file not shown.
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 23 KiB |
BIN
lib/UnityEngine.dll
Normal file
BIN
lib/UnityEngine.dll
Normal file
Binary file not shown.
BIN
overview.png
BIN
overview.png
Binary file not shown.
Before Width: | Height: | Size: 523 KiB After Width: | Height: | Size: 479 KiB |
169
src/CachedObjects/CacheFactory.cs
Normal file
169
src/CachedObjects/CacheFactory.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -2,10 +2,6 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using MelonLoader;
|
|
||||||
using UnhollowerBaseLib;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer
|
||||||
@ -13,14 +9,14 @@ namespace Explorer
|
|||||||
public abstract class CacheObjectBase
|
public abstract class CacheObjectBase
|
||||||
{
|
{
|
||||||
public object Value;
|
public object Value;
|
||||||
public string ValueTypeName;
|
|
||||||
public Type ValueType;
|
public Type ValueType;
|
||||||
|
|
||||||
public MemberInfo MemInfo { get; set; }
|
public MemberInfo MemInfo { get; set; }
|
||||||
public Type DeclaringType { get; set; }
|
public Type DeclaringType { get; set; }
|
||||||
public object DeclaringInstance { get; set; }
|
public object DeclaringInstance { get; set; }
|
||||||
|
|
||||||
public bool HasParameters => m_arguments != null && m_arguments.Length > 0;
|
public virtual bool HasParameters => m_arguments != null && m_arguments.Length > 0;
|
||||||
|
|
||||||
public bool m_evaluated = false;
|
public bool m_evaluated = false;
|
||||||
public bool m_isEvaluating;
|
public bool m_isEvaluating;
|
||||||
public ParameterInfo[] m_arguments = new ParameterInfo[0];
|
public ParameterInfo[] m_arguments = new ParameterInfo[0];
|
||||||
@ -31,257 +27,12 @@ namespace Explorer
|
|||||||
public string RichTextName => m_richTextName ?? GetRichTextName();
|
public string RichTextName => m_richTextName ?? GetRichTextName();
|
||||||
private string m_richTextName;
|
private string m_richTextName;
|
||||||
|
|
||||||
public bool CanWrite
|
public bool CanWrite => m_canWrite ?? GetCanWrite();
|
||||||
{
|
private bool? m_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 virtual void Init() { }
|
public virtual void Init() { }
|
||||||
|
|
||||||
public abstract void DrawValue(Rect window, float width);
|
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;
|
|
||||||
|
|
||||||
// if PropertyInfo, check if can process args
|
|
||||||
if (pi != null && !CanProcessArgs(pi.GetIndexParameters()))
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is pretty ugly, could probably make a cleaner implementation.
|
|
||||||
// However, the only cleaner ways I can think of are slower and probably not worth it.
|
|
||||||
|
|
||||||
// Note: the order is somewhat important.
|
|
||||||
|
|
||||||
if (mi != null)
|
|
||||||
{
|
|
||||||
if (CacheMethod.CanEvaluate(mi))
|
|
||||||
{
|
|
||||||
holder = new CacheMethod();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
holder.ValueTypeName = valueType.FullName;
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
if (!param.ParameterType.IsPrimitive && param.ParameterType != typeof(string))
|
|
||||||
{
|
|
||||||
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 (!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
|
|
||||||
{
|
|
||||||
MelonLogger.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 (m_arguments[i].HasDefaultValue)
|
|
||||||
{
|
|
||||||
parsedArgs.Add(m_arguments[i].DefaultValue);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try add a null arg I guess
|
|
||||||
parsedArgs.Add(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
return parsedArgs.ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual void UpdateValue()
|
public virtual void UpdateValue()
|
||||||
{
|
{
|
||||||
@ -308,14 +59,7 @@ namespace Explorer
|
|||||||
var pi = MemInfo as PropertyInfo;
|
var pi = MemInfo as PropertyInfo;
|
||||||
var target = pi.GetAccessors()[0].IsStatic ? null : DeclaringInstance;
|
var target = pi.GetAccessors()[0].IsStatic ? null : DeclaringInstance;
|
||||||
|
|
||||||
if (HasParameters)
|
Value = pi.GetValue(target, ParseArguments());
|
||||||
{
|
|
||||||
Value = pi.GetValue(target, ParseArguments());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Value = pi.GetValue(target, null);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ReflectionException = null;
|
ReflectionException = null;
|
||||||
@ -347,21 +91,87 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pi.SetValue(pi.GetAccessors()[0].IsStatic ? null : DeclaringInstance, Value);
|
pi.SetValue(pi.GetAccessors()[0].IsStatic ? null : DeclaringInstance, Value, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
MelonLogger.LogWarning($"Error setting value: {e.GetType()}, {e.Message}");
|
ExplorerCore.LogWarning($"Error setting value: {e.GetType()}, {e.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 ==========
|
// ========= Gui Draw ==========
|
||||||
|
|
||||||
public const float MAX_LABEL_WIDTH = 400f;
|
public const float MAX_LABEL_WIDTH = 400f;
|
||||||
public const string EVALUATE_LABEL = "<color=lime>Evaluate</color>";
|
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)
|
public static void ClampLabelWidth(Rect window, ref float labelWidth)
|
||||||
{
|
{
|
||||||
float min = window.width * 0.37f;
|
float min = window.width * 0.37f;
|
||||||
@ -390,42 +200,89 @@ namespace Explorer
|
|||||||
|
|
||||||
if (HasParameters)
|
if (HasParameters)
|
||||||
{
|
{
|
||||||
GUILayout.BeginVertical(null);
|
GUILayout.BeginVertical(new GUILayoutOption[0]);
|
||||||
|
|
||||||
if (m_isEvaluating)
|
if (m_isEvaluating)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < m_arguments.Length; i++)
|
if (cm != null && cm.GenericArgs.Length > 0)
|
||||||
{
|
{
|
||||||
var name = m_arguments[i].Name;
|
GUILayout.Label($"<b><color=orange>Generic Arguments:</color></b>", new GUILayoutOption[0]);
|
||||||
var input = m_argumentInput[i];
|
|
||||||
var type = m_arguments[i].ParameterType.Name;
|
|
||||||
|
|
||||||
var label = "<color=#2df7b2>" + type + "</color> <color=#a6e9e9>" + name + "</color>";
|
for (int i = 0; i < cm.GenericArgs.Length; i++)
|
||||||
if (m_arguments[i].HasDefaultValue)
|
|
||||||
{
|
{
|
||||||
label = $"<i>[{label} = {m_arguments[i].DefaultValue}]</i>";
|
string types = "";
|
||||||
|
if (cm.GenericConstraints[i].Length > 0)
|
||||||
|
{
|
||||||
|
foreach (var constraint in cm.GenericConstraints[i])
|
||||||
|
{
|
||||||
|
if (types != "") types += ", ";
|
||||||
|
|
||||||
|
string type;
|
||||||
|
|
||||||
|
if (constraint == null)
|
||||||
|
type = "Any";
|
||||||
|
else
|
||||||
|
type = constraint.ToString();
|
||||||
|
|
||||||
|
types += $"<color={UIStyles.Syntax.Class_Instance}>{type}</color>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
types = $"<color={UIStyles.Syntax.Class_Instance}>Any</color>";
|
||||||
|
}
|
||||||
|
var input = cm.GenericArgInput[i];
|
||||||
|
|
||||||
|
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] = GUIUnstrip.TextField(input, new GUILayoutOption[] { GUILayout.Width(150) });
|
||||||
|
GUI.skin.label.alignment = TextAnchor.MiddleLeft;
|
||||||
|
GUILayout.Label(types, new GUILayoutOption[0]);
|
||||||
|
|
||||||
|
GUILayout.EndHorizontal();
|
||||||
}
|
}
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(null);
|
|
||||||
|
|
||||||
GUILayout.Label(i.ToString(), new GUILayoutOption[] { GUILayout.Width(20) });
|
|
||||||
m_argumentInput[i] = GUILayout.TextField(input, new GUILayoutOption[] { GUILayout.Width(150) });
|
|
||||||
GUILayout.Label(label, null);
|
|
||||||
|
|
||||||
GUILayout.EndHorizontal();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(null);
|
if (m_arguments.Length > 0)
|
||||||
|
{
|
||||||
|
GUILayout.Label($"<b><color=orange>Arguments:</color></b>", new GUILayoutOption[0]);
|
||||||
|
for (int i = 0; i < m_arguments.Length; i++)
|
||||||
|
{
|
||||||
|
var name = m_arguments[i].Name;
|
||||||
|
var input = m_argumentInput[i];
|
||||||
|
var type = m_arguments[i].ParameterType.Name;
|
||||||
|
|
||||||
|
var label = $"<color={UIStyles.Syntax.Class_Instance}>{type}</color> ";
|
||||||
|
label += $"<color={UIStyles.Syntax.Local}>{name}</color>";
|
||||||
|
if (HasDefaultValue(m_arguments[i]))
|
||||||
|
{
|
||||||
|
label = $"<i>[{label} = {m_arguments[i].DefaultValue ?? "null"}]</i>";
|
||||||
|
}
|
||||||
|
|
||||||
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
|
|
||||||
|
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
|
||||||
|
GUILayout.Label(i.ToString(), new GUILayoutOption[] { GUILayout.Width(15) });
|
||||||
|
m_argumentInput[i] = GUIUnstrip.TextField(input, new GUILayoutOption[] { GUILayout.Width(150) });
|
||||||
|
GUI.skin.label.alignment = TextAnchor.MiddleLeft;
|
||||||
|
GUILayout.Label(label, new GUILayoutOption[0]);
|
||||||
|
|
||||||
|
GUILayout.EndHorizontal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
if (GUILayout.Button(EVALUATE_LABEL, new GUILayoutOption[] { GUILayout.Width(70) }))
|
if (GUILayout.Button(EVALUATE_LABEL, new GUILayoutOption[] { GUILayout.Width(70) }))
|
||||||
{
|
{
|
||||||
if (cm != null)
|
if (cm != null)
|
||||||
{
|
|
||||||
cm.Evaluate();
|
cm.Evaluate();
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
UpdateValue();
|
UpdateValue();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (GUILayout.Button("Cancel", new GUILayoutOption[] { GUILayout.Width(70) }))
|
if (GUILayout.Button("Cancel", new GUILayoutOption[] { GUILayout.Width(70) }))
|
||||||
{
|
{
|
||||||
@ -435,7 +292,12 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (GUILayout.Button($"Evaluate ({m_arguments.Length} params)", new GUILayoutOption[] { GUILayout.Width(150) }))
|
var lbl = $"Evaluate (";
|
||||||
|
int len = m_arguments.Length;
|
||||||
|
if (cm != null) len += cm.GenericArgs.Length;
|
||||||
|
lbl += len + " params)";
|
||||||
|
|
||||||
|
if (GUILayout.Button(lbl, new GUILayoutOption[] { GUILayout.Width(150) }))
|
||||||
{
|
{
|
||||||
m_isEvaluating = true;
|
m_isEvaluating = true;
|
||||||
}
|
}
|
||||||
@ -443,37 +305,35 @@ namespace Explorer
|
|||||||
|
|
||||||
GUILayout.EndVertical();
|
GUILayout.EndVertical();
|
||||||
|
|
||||||
// new line and space
|
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUIUnstrip.Space(labelWidth);
|
GUIUnstrip.Space(labelWidth);
|
||||||
}
|
}
|
||||||
else if (cm != null)
|
else if (cm != null)
|
||||||
{
|
{
|
||||||
//GUILayout.BeginHorizontal(null);
|
|
||||||
|
|
||||||
if (GUILayout.Button(EVALUATE_LABEL, new GUILayoutOption[] { GUILayout.Width(70) }))
|
if (GUILayout.Button(EVALUATE_LABEL, new GUILayoutOption[] { GUILayout.Width(70) }))
|
||||||
{
|
{
|
||||||
cm.Evaluate();
|
cm.Evaluate();
|
||||||
}
|
}
|
||||||
|
|
||||||
// new line and space
|
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUIUnstrip.Space(labelWidth);
|
GUIUnstrip.Space(labelWidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string typeName = $"<color={UIStyles.Syntax.Class_Instance}>{ValueType.FullName}</color>";
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(ReflectionException))
|
if (!string.IsNullOrEmpty(ReflectionException))
|
||||||
{
|
{
|
||||||
GUILayout.Label("<color=red>Reflection failed!</color> (" + ReflectionException + ")", null);
|
GUILayout.Label("<color=red>Reflection failed!</color> (" + ReflectionException + ")", new GUILayoutOption[0]);
|
||||||
}
|
}
|
||||||
else if ((HasParameters || this is CacheMethod) && !m_evaluated)
|
else if ((HasParameters || this is CacheMethod) && !m_evaluated)
|
||||||
{
|
{
|
||||||
GUILayout.Label($"<color=grey><i>Not yet evaluated</i></color> (<color=#2df7b2>{ValueTypeName}</color>)", null);
|
GUILayout.Label($"<color=grey><i>Not yet evaluated</i></color> ({typeName})", new GUILayoutOption[0]);
|
||||||
}
|
}
|
||||||
else if (Value == null && !(this is CacheMethod))
|
else if (Value == null && !(this is CacheMethod))
|
||||||
{
|
{
|
||||||
GUILayout.Label("<i>null (" + ValueTypeName + ")</i>", null);
|
GUILayout.Label($"<i>null ({typeName})</i>", new GUILayoutOption[0]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -481,33 +341,87 @@ 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()
|
private string GetRichTextName()
|
||||||
{
|
{
|
||||||
string memberColor = "";
|
string memberColor = "";
|
||||||
switch (MemInfo.MemberType)
|
bool isStatic = false;
|
||||||
{
|
|
||||||
case MemberTypes.Field:
|
|
||||||
memberColor = "#c266ff"; break;
|
|
||||||
case MemberTypes.Property:
|
|
||||||
memberColor = "#72a6a6"; break;
|
|
||||||
case MemberTypes.Method:
|
|
||||||
memberColor = "#ff8000"; break;
|
|
||||||
};
|
|
||||||
|
|
||||||
m_richTextName = $"<color=#2df7b2>{MemInfo.DeclaringType.Name}</color>.<color={memberColor}>{MemInfo.Name}</color>";
|
if (MemInfo is FieldInfo fi)
|
||||||
|
|
||||||
if (m_arguments.Length > 0 || this is CacheMethod)
|
|
||||||
{
|
{
|
||||||
m_richTextName += "(";
|
if (fi.IsStatic)
|
||||||
var _params = "";
|
|
||||||
foreach (var param in m_arguments)
|
|
||||||
{
|
{
|
||||||
if (_params != "") _params += ", ";
|
isStatic = true;
|
||||||
|
memberColor = UIStyles.Syntax.Field_Static;
|
||||||
_params += $"<color=#2df7b2>{param.ParameterType.Name}</color> <color=#a6e9e9>{param.Name}</color>";
|
|
||||||
}
|
}
|
||||||
m_richTextName += _params;
|
else
|
||||||
m_richTextName += ")";
|
memberColor = UIStyles.Syntax.Field_Instance;
|
||||||
|
}
|
||||||
|
else if (MemInfo is MethodInfo mi)
|
||||||
|
{
|
||||||
|
if (mi.IsStatic)
|
||||||
|
{
|
||||||
|
isStatic = true;
|
||||||
|
memberColor = UIStyles.Syntax.Method_Static;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
memberColor = UIStyles.Syntax.Method_Instance;
|
||||||
|
}
|
||||||
|
else if (MemInfo is PropertyInfo pi)
|
||||||
|
{
|
||||||
|
if (pi.GetAccessors()[0].IsStatic)
|
||||||
|
{
|
||||||
|
isStatic = true;
|
||||||
|
memberColor = UIStyles.Syntax.Prop_Static;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
memberColor = UIStyles.Syntax.Prop_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>";
|
||||||
|
m_richTextName += $"<color={memberColor}>{MemInfo.Name}</color>";
|
||||||
|
if (isStatic) m_richTextName += "</i>";
|
||||||
|
|
||||||
|
// generic method args
|
||||||
|
if (this is CacheMethod cm && cm.GenericArgs.Length > 0)
|
||||||
|
{
|
||||||
|
m_richTextName += "<";
|
||||||
|
|
||||||
|
var args = "";
|
||||||
|
for (int i = 0; i < cm.GenericArgs.Length; i++)
|
||||||
|
{
|
||||||
|
if (args != "") args += ", ";
|
||||||
|
args += $"<color={UIStyles.Syntax.StructGreen}>{cm.GenericArgs[i].Name}</color>";
|
||||||
|
}
|
||||||
|
m_richTextName += args;
|
||||||
|
|
||||||
|
m_richTextName += ">";
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_richTextName;
|
return m_richTextName;
|
||||||
|
@ -1,10 +1,4 @@
|
|||||||
using System;
|
namespace Explorer
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Explorer
|
|
||||||
{
|
{
|
||||||
interface IExpandHeight
|
interface IExpandHeight
|
||||||
{
|
{
|
||||||
|
@ -1,13 +1,10 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using MelonLoader;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using System.Reflection;
|
#if CPP
|
||||||
using UnhollowerBaseLib;
|
using UnhollowerBaseLib;
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer
|
||||||
{
|
{
|
||||||
@ -56,8 +53,8 @@ namespace Explorer
|
|||||||
// note: "ValueType" is the Dictionary itself, TypeOfValues is the 'Dictionary.Values' type.
|
// note: "ValueType" is the Dictionary itself, TypeOfValues is the 'Dictionary.Values' type.
|
||||||
|
|
||||||
// get keys and values
|
// get keys and values
|
||||||
var keys = ValueType.GetProperty("Keys") .GetValue(Value);
|
var keys = ValueType.GetProperty("Keys") .GetValue(Value, null);
|
||||||
var values = ValueType.GetProperty("Values").GetValue(Value);
|
var values = ValueType.GetProperty("Values").GetValue(Value, null);
|
||||||
|
|
||||||
// create lists to hold them
|
// create lists to hold them
|
||||||
var keyList = new List<object>();
|
var keyList = new List<object>();
|
||||||
@ -92,7 +89,7 @@ namespace Explorer
|
|||||||
// iterate
|
// iterate
|
||||||
while ((bool)moveNext.Invoke(enumerator, null))
|
while ((bool)moveNext.Invoke(enumerator, null))
|
||||||
{
|
{
|
||||||
list.Add(current.GetValue(enumerator));
|
list.Add(current.GetValue(enumerator, null));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,14 +130,16 @@ namespace Explorer
|
|||||||
var keys = new List<CacheObjectBase>();
|
var keys = new List<CacheObjectBase>();
|
||||||
foreach (var key in IDict.Keys)
|
foreach (var key in IDict.Keys)
|
||||||
{
|
{
|
||||||
var cache = GetCacheObject(key, TypeOfKeys);
|
Type t = ReflectionHelpers.GetActualType(key) ?? TypeOfKeys;
|
||||||
|
var cache = CacheFactory.GetCacheObject(key, t);
|
||||||
keys.Add(cache);
|
keys.Add(cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
var values = new List<CacheObjectBase>();
|
var values = new List<CacheObjectBase>();
|
||||||
foreach (var val in IDict.Values)
|
foreach (var val in IDict.Values)
|
||||||
{
|
{
|
||||||
var cache = GetCacheObject(val, TypeOfValues);
|
Type t = ReflectionHelpers.GetActualType(val) ?? TypeOfValues;
|
||||||
|
var cache = CacheFactory.GetCacheObject(val, t);
|
||||||
values.Add(cache);
|
values.Add(cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -155,6 +154,7 @@ namespace Explorer
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if CPP
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return Check(TypeOfKeys) && Check(TypeOfValues);
|
return Check(TypeOfKeys) && Check(TypeOfValues);
|
||||||
@ -173,6 +173,9 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============= GUI Draw =============
|
// ============= GUI Draw =============
|
||||||
@ -181,7 +184,7 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
if (m_cachedKeys == null || m_cachedValues == null)
|
if (m_cachedKeys == null || m_cachedValues == null)
|
||||||
{
|
{
|
||||||
GUILayout.Label("Cached keys or values is null!", null);
|
GUILayout.Label("Cached keys or values is null!", new GUILayoutOption[0]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -223,7 +226,7 @@ namespace Explorer
|
|||||||
if (count > Pages.ItemsPerPage)
|
if (count > Pages.ItemsPerPage)
|
||||||
{
|
{
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
|
|
||||||
GUIUnstrip.Space(whitespace);
|
GUIUnstrip.Space(whitespace);
|
||||||
|
|
||||||
@ -253,19 +256,20 @@ namespace Explorer
|
|||||||
|
|
||||||
//collapsing the BeginHorizontal called from ReflectionWindow.WindowFunction or previous array entry
|
//collapsing the BeginHorizontal called from ReflectionWindow.WindowFunction or previous array entry
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
|
|
||||||
//GUIUnstrip.Space(whitespace);
|
//GUIUnstrip.Space(whitespace);
|
||||||
|
|
||||||
if (key == null || val == null)
|
if (key == null || val == null)
|
||||||
{
|
{
|
||||||
GUILayout.Label($"[{i}] <i><color=grey>(null)</color></i>", null);
|
GUILayout.Label($"[{i}] <i><color=grey>(null)</color></i>", new GUILayoutOption[0]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
|
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
|
||||||
GUILayout.Label($"[{i}]", new GUILayoutOption[] { GUILayout.Width(30) });
|
GUILayout.Label($"[{i}]", new GUILayoutOption[] { GUILayout.Width(30) });
|
||||||
|
|
||||||
|
GUI.skin.label.alignment = TextAnchor.MiddleLeft;
|
||||||
GUILayout.Label("Key:", new GUILayoutOption[] { GUILayout.Width(40) });
|
GUILayout.Label("Key:", new GUILayoutOption[] { GUILayout.Width(40) });
|
||||||
key.DrawValue(window, (window.width / 2) - 80f);
|
key.DrawValue(window, (window.width / 2) - 80f);
|
||||||
|
|
||||||
|
@ -1,10 +1,4 @@
|
|||||||
using System;
|
using UnityEngine;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using MelonLoader;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer
|
||||||
{
|
{
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using MelonLoader;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer
|
||||||
@ -104,6 +102,7 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
if (Value == null) return null;
|
if (Value == null) return null;
|
||||||
|
|
||||||
|
#if CPP
|
||||||
if (GenericTypeDef == typeof(Il2CppSystem.Collections.Generic.List<>))
|
if (GenericTypeDef == typeof(Il2CppSystem.Collections.Generic.List<>))
|
||||||
{
|
{
|
||||||
return (IEnumerable)CppListToArrayMethod?.Invoke(Value, new object[0]);
|
return (IEnumerable)CppListToArrayMethod?.Invoke(Value, new object[0]);
|
||||||
@ -116,8 +115,12 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
return CppIListToMono();
|
return CppIListToMono();
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
return Value as IEnumerable;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if CPP
|
||||||
private IEnumerable CppHashSetToMono()
|
private IEnumerable CppHashSetToMono()
|
||||||
{
|
{
|
||||||
var set = new HashSet<object>();
|
var set = new HashSet<object>();
|
||||||
@ -159,10 +162,11 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
MelonLogger.Log("Exception converting Il2Cpp IList to Mono IList: " + e.GetType() + ", " + e.Message);
|
ExplorerCore.Log("Exception converting Il2Cpp IList to Mono IList: " + e.GetType() + ", " + e.Message);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
private Type GetEntryType()
|
private Type GetEntryType()
|
||||||
{
|
{
|
||||||
@ -227,6 +231,7 @@ namespace Explorer
|
|||||||
|
|
||||||
if (obj != null && ReflectionHelpers.GetActualType(obj) is Type t)
|
if (obj != null && ReflectionHelpers.GetActualType(obj) is Type t)
|
||||||
{
|
{
|
||||||
|
#if CPP
|
||||||
if (obj is Il2CppSystem.Object iObj)
|
if (obj is Il2CppSystem.Object iObj)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@ -239,8 +244,9 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
catch { }
|
catch { }
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (GetCacheObject(obj, t) is CacheObjectBase cached)
|
if (CacheFactory.GetCacheObject(obj, t) is CacheObjectBase cached)
|
||||||
{
|
{
|
||||||
list.Add(cached);
|
list.Add(cached);
|
||||||
}
|
}
|
||||||
@ -264,7 +270,7 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
if (m_cachedEntries == null)
|
if (m_cachedEntries == null)
|
||||||
{
|
{
|
||||||
GUILayout.Label("m_cachedEntries is null!", null);
|
GUILayout.Label("m_cachedEntries is null!", new GUILayoutOption[0]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -291,7 +297,7 @@ namespace Explorer
|
|||||||
|
|
||||||
GUI.skin.button.alignment = TextAnchor.MiddleLeft;
|
GUI.skin.button.alignment = TextAnchor.MiddleLeft;
|
||||||
string btnLabel = $"[{count}] <color=#2df7b2>{EntryType.FullName}</color>";
|
string btnLabel = $"[{count}] <color=#2df7b2>{EntryType.FullName}</color>";
|
||||||
if (GUILayout.Button(btnLabel, new GUILayoutOption[] { GUILayout.MaxWidth(negativeWhitespace) }))
|
if (GUILayout.Button(btnLabel, new GUILayoutOption[] { GUILayout.Width(negativeWhitespace) }))
|
||||||
{
|
{
|
||||||
WindowManager.InspectObject(Value, out bool _);
|
WindowManager.InspectObject(Value, out bool _);
|
||||||
}
|
}
|
||||||
@ -306,7 +312,7 @@ namespace Explorer
|
|||||||
if (count > Pages.ItemsPerPage)
|
if (count > Pages.ItemsPerPage)
|
||||||
{
|
{
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
|
|
||||||
GUIUnstrip.Space(whitespace);
|
GUIUnstrip.Space(whitespace);
|
||||||
|
|
||||||
@ -335,19 +341,20 @@ namespace Explorer
|
|||||||
|
|
||||||
//collapsing the BeginHorizontal called from ReflectionWindow.WindowFunction or previous array entry
|
//collapsing the BeginHorizontal called from ReflectionWindow.WindowFunction or previous array entry
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
|
|
||||||
GUIUnstrip.Space(whitespace);
|
GUIUnstrip.Space(whitespace);
|
||||||
|
|
||||||
if (entry == null || entry.Value == null)
|
if (entry == null || entry.Value == null)
|
||||||
{
|
{
|
||||||
GUILayout.Label($"[{i}] <i><color=grey>(null)</color></i>", null);
|
GUILayout.Label($"[{i}] <i><color=grey>(null)</color></i>", new GUILayoutOption[0]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
|
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
|
||||||
GUILayout.Label($"[{i}]", new GUILayoutOption[] { GUILayout.Width(30) });
|
GUILayout.Label($"[{i}]", new GUILayoutOption[] { GUILayout.Width(30) });
|
||||||
|
|
||||||
|
GUI.skin.label.alignment = TextAnchor.MiddleLeft;
|
||||||
entry.DrawValue(window, window.width - (whitespace + 85));
|
entry.DrawValue(window, window.width - (whitespace + 85));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,11 +1,8 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using MelonLoader;
|
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer
|
||||||
{
|
{
|
||||||
@ -13,16 +10,24 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
private CacheObjectBase m_cachedReturnValue;
|
private CacheObjectBase m_cachedReturnValue;
|
||||||
|
|
||||||
public static bool CanEvaluate(MethodInfo mi)
|
public override bool HasParameters => base.HasParameters || GenericArgs.Length > 0;
|
||||||
{
|
|
||||||
// TODO generic args
|
|
||||||
if (mi.GetGenericArguments().Length > 0)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// primitive and string args supported
|
public Type[] GenericArgs { get; private set; }
|
||||||
return CanProcessArgs(mi.GetParameters());
|
public Type[][] GenericConstraints { get; private set; }
|
||||||
|
|
||||||
|
public string[] GenericArgInput = new string[0];
|
||||||
|
|
||||||
|
public override void Init()
|
||||||
|
{
|
||||||
|
var mi = (MemInfo as MethodInfo);
|
||||||
|
GenericArgs = mi.GetGenericArguments();
|
||||||
|
|
||||||
|
GenericConstraints = GenericArgs.Select(x => x.GetGenericParameterConstraints())
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
GenericArgInput = new string[GenericArgs.Length];
|
||||||
|
|
||||||
|
ValueType = mi.ReturnType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void UpdateValue()
|
public override void UpdateValue()
|
||||||
@ -32,32 +37,34 @@ namespace Explorer
|
|||||||
|
|
||||||
public void Evaluate()
|
public void Evaluate()
|
||||||
{
|
{
|
||||||
m_isEvaluating = false;
|
MethodInfo mi;
|
||||||
|
if (GenericArgs.Length > 0)
|
||||||
var mi = MemInfo as MethodInfo;
|
|
||||||
object ret = null;
|
|
||||||
|
|
||||||
if (!HasParameters)
|
|
||||||
{
|
{
|
||||||
ret = mi.Invoke(mi.IsStatic ? null : DeclaringInstance, new object[0]);
|
mi = MakeGenericMethodFromInput();
|
||||||
m_evaluated = true;
|
if (mi == null) return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
try
|
mi = MemInfo as MethodInfo;
|
||||||
{
|
}
|
||||||
ret = mi.Invoke(mi.IsStatic ? null : DeclaringInstance, ParseArguments());
|
|
||||||
m_evaluated = true;
|
object ret = null;
|
||||||
}
|
|
||||||
catch (Exception e)
|
try
|
||||||
{
|
{
|
||||||
MelonLogger.Log($"Exception evaluating: {e.GetType()}, {e.Message}");
|
ret = mi.Invoke(mi.IsStatic ? null : DeclaringInstance, ParseArguments());
|
||||||
}
|
m_evaluated = true;
|
||||||
|
m_isEvaluating = false;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ExplorerCore.LogWarning($"Exception evaluating: {e.GetType()}, {e.Message}");
|
||||||
|
ReflectionException = ReflectionHelpers.ExceptionToString(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret != null)
|
if (ret != null)
|
||||||
{
|
{
|
||||||
m_cachedReturnValue = GetCacheObject(ret);
|
m_cachedReturnValue = CacheFactory.GetTypeAndCacheObject(ret);
|
||||||
m_cachedReturnValue.UpdateValue();
|
m_cachedReturnValue.UpdateValue();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -66,10 +73,54 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private MethodInfo MakeGenericMethodFromInput()
|
||||||
|
{
|
||||||
|
var mi = MemInfo as MethodInfo;
|
||||||
|
|
||||||
|
var list = new List<Type>();
|
||||||
|
for (int i = 0; i < GenericArgs.Length; i++)
|
||||||
|
{
|
||||||
|
var input = GenericArgInput[i];
|
||||||
|
if (ReflectionHelpers.GetTypeByName(input) is Type t)
|
||||||
|
{
|
||||||
|
if (GenericConstraints[i].Length == 0)
|
||||||
|
{
|
||||||
|
list.Add(t);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach (var constraint in GenericConstraints[i].Where(x => x != null))
|
||||||
|
{
|
||||||
|
if (!constraint.IsAssignableFrom(t))
|
||||||
|
{
|
||||||
|
ExplorerCore.LogWarning($"Generic argument #{i}, '{input}' is not assignable from the constraint '{constraint}'!");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
list.Add(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ExplorerCore.LogWarning($"Generic argument #{i}, could not get any type by the name of '{input}'!" +
|
||||||
|
$" Make sure you use the full name, including the NameSpace.");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// make into a generic with type list
|
||||||
|
mi = mi.MakeGenericMethod(list.ToArray());
|
||||||
|
|
||||||
|
return mi;
|
||||||
|
}
|
||||||
|
|
||||||
// ==== GUI DRAW ====
|
// ==== GUI DRAW ====
|
||||||
|
|
||||||
public override void DrawValue(Rect window, float width)
|
public override void DrawValue(Rect window, float width)
|
||||||
{
|
{
|
||||||
|
string typeLabel = $"<color={UIStyles.Syntax.Class_Instance}>{ValueType.FullName}</color>";
|
||||||
|
|
||||||
if (m_evaluated)
|
if (m_evaluated)
|
||||||
{
|
{
|
||||||
if (m_cachedReturnValue != null)
|
if (m_cachedReturnValue != null)
|
||||||
@ -78,12 +129,12 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GUILayout.Label($"null (<color=#2df7b2>{ValueTypeName}</color>)", null);
|
GUILayout.Label($"null ({typeLabel})", new GUILayoutOption[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GUILayout.Label($"<color=grey><i>Not yet evaluated</i></color> (<color=#2df7b2>{ValueTypeName}</color>)", null);
|
GUILayout.Label($"<color=grey><i>Not yet evaluated</i></color> ({typeLabel})", new GUILayoutOption[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
@ -11,55 +6,75 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
public class CacheOther : CacheObjectBase
|
public class CacheOther : CacheObjectBase
|
||||||
{
|
{
|
||||||
|
public string ButtonLabel => m_btnLabel ?? GetButtonLabel();
|
||||||
|
private string m_btnLabel;
|
||||||
|
|
||||||
|
public MethodInfo ToStringMethod => m_toStringMethod ?? GetToStringMethod();
|
||||||
private MethodInfo m_toStringMethod;
|
private MethodInfo m_toStringMethod;
|
||||||
|
|
||||||
public MethodInfo ToStringMethod
|
public override void UpdateValue()
|
||||||
{
|
{
|
||||||
get
|
base.UpdateValue();
|
||||||
{
|
|
||||||
if (m_toStringMethod == null)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
m_toStringMethod = ReflectionHelpers.GetActualType(Value).GetMethod("ToString", new Type[0])
|
|
||||||
?? typeof(object).GetMethod("ToString", new Type[0]);
|
|
||||||
|
|
||||||
// test invoke
|
GetButtonLabel();
|
||||||
m_toStringMethod.Invoke(Value, null);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
m_toStringMethod = typeof(object).GetMethod("ToString", new Type[0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return m_toStringMethod;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void DrawValue(Rect window, float width)
|
public override void DrawValue(Rect window, float width)
|
||||||
{
|
{
|
||||||
string label = (string)ToStringMethod?.Invoke(Value, null) ?? Value.ToString();
|
|
||||||
|
|
||||||
if (!label.Contains(ValueTypeName))
|
|
||||||
{
|
|
||||||
label += $" (<color=#2df7b2>{ValueTypeName}</color>)";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
label = label.Replace(ValueTypeName, $"<color=#2df7b2>{ValueTypeName}</color>");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Value is UnityEngine.Object unityObj && !label.Contains(unityObj.name))
|
|
||||||
{
|
|
||||||
label = unityObj.name + " | " + label;
|
|
||||||
}
|
|
||||||
|
|
||||||
GUI.skin.button.alignment = TextAnchor.MiddleLeft;
|
GUI.skin.button.alignment = TextAnchor.MiddleLeft;
|
||||||
if (GUILayout.Button(label, new GUILayoutOption[] { GUILayout.Width(width - 15) }))
|
if (GUILayout.Button(ButtonLabel, new GUILayoutOption[] { GUILayout.Width(width - 15) }))
|
||||||
{
|
{
|
||||||
WindowManager.InspectObject(Value, out bool _);
|
WindowManager.InspectObject(Value, out bool _);
|
||||||
}
|
}
|
||||||
GUI.skin.button.alignment = TextAnchor.MiddleCenter;
|
GUI.skin.button.alignment = TextAnchor.MiddleCenter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private MethodInfo GetToStringMethod()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
m_toStringMethod = ReflectionHelpers.GetActualType(Value).GetMethod("ToString", new Type[0])
|
||||||
|
?? typeof(object).GetMethod("ToString", new Type[0]);
|
||||||
|
|
||||||
|
// test invoke
|
||||||
|
m_toStringMethod.Invoke(Value, null);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
m_toStringMethod = typeof(object).GetMethod("ToString", new Type[0]);
|
||||||
|
}
|
||||||
|
return m_toStringMethod;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetButtonLabel()
|
||||||
|
{
|
||||||
|
if (Value == null) return null;
|
||||||
|
|
||||||
|
string label = (string)ToStringMethod?.Invoke(Value, null) ?? Value.ToString();
|
||||||
|
|
||||||
|
var classColor = ValueType.IsAbstract && ValueType.IsSealed
|
||||||
|
? UIStyles.Syntax.Class_Static
|
||||||
|
: UIStyles.Syntax.Class_Instance;
|
||||||
|
|
||||||
|
string typeLabel = $"<color={classColor}>{ValueType.FullName}</color>";
|
||||||
|
|
||||||
|
if (Value is UnityEngine.Object)
|
||||||
|
{
|
||||||
|
label = label.Replace($"({ValueType.FullName})", $"({typeLabel})");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!label.Contains(ValueType.FullName))
|
||||||
|
{
|
||||||
|
label += $" ({typeLabel})";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
label = label.Replace(ValueType.FullName, typeLabel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_btnLabel = label;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer
|
||||||
@ -21,6 +20,8 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
base.UpdateValue();
|
base.UpdateValue();
|
||||||
|
|
||||||
|
if (Value == null) return;
|
||||||
|
|
||||||
var color = (Color)Value;
|
var color = (Color)Value;
|
||||||
|
|
||||||
r = color.r.ToString();
|
r = color.r.ToString();
|
||||||
@ -51,7 +52,7 @@ namespace Explorer
|
|||||||
|
|
||||||
//var c = (Color)Value;
|
//var c = (Color)Value;
|
||||||
//GUI.color = c;
|
//GUI.color = c;
|
||||||
GUILayout.Label($"<color=#2df7b2>Color:</color> {((Color)Value).ToString()}", null);
|
GUILayout.Label($"<color=#2df7b2>Color:</color> {((Color)Value).ToString()}", new GUILayoutOption[0]);
|
||||||
//GUI.color = Color.white;
|
//GUI.color = Color.white;
|
||||||
|
|
||||||
if (CanWrite && IsExpanded)
|
if (CanWrite && IsExpanded)
|
||||||
@ -60,32 +61,32 @@ namespace Explorer
|
|||||||
|
|
||||||
var whitespace = CalcWhitespace(window);
|
var whitespace = CalcWhitespace(window);
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUIUnstrip.Space(whitespace);
|
GUIUnstrip.Space(whitespace);
|
||||||
GUILayout.Label("R:", new GUILayoutOption[] { GUILayout.Width(30) });
|
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.EndHorizontal();
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUIUnstrip.Space(whitespace);
|
GUIUnstrip.Space(whitespace);
|
||||||
GUILayout.Label("G:", new GUILayoutOption[] { GUILayout.Width(30) });
|
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.EndHorizontal();
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUIUnstrip.Space(whitespace);
|
GUIUnstrip.Space(whitespace);
|
||||||
GUILayout.Label("B:", new GUILayoutOption[] { GUILayout.Width(30) });
|
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.EndHorizontal();
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUIUnstrip.Space(whitespace);
|
GUIUnstrip.Space(whitespace);
|
||||||
GUILayout.Label("A:", new GUILayoutOption[] { GUILayout.Width(30) });
|
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();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
// draw set value button
|
// draw set value button
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUIUnstrip.Space(whitespace);
|
GUIUnstrip.Space(whitespace);
|
||||||
if (GUILayout.Button("<color=lime>Apply</color>", new GUILayoutOption[] { GUILayout.Width(155) }))
|
if (GUILayout.Button("<color=lime>Apply</color>", new GUILayoutOption[] { GUILayout.Width(155) }))
|
||||||
{
|
{
|
||||||
@ -93,7 +94,7 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,7 +105,7 @@ namespace Explorer
|
|||||||
&& float.TryParse(b, out float fB)
|
&& float.TryParse(b, out float fB)
|
||||||
&& float.TryParse(a, out float fA))
|
&& float.TryParse(a, out float fA))
|
||||||
{
|
{
|
||||||
Value = new Color(fR, fB, fG, fA);
|
Value = new Color(fR, fG, fB, fA);
|
||||||
SetValue();
|
SetValue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,32 +2,37 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using MelonLoader;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer
|
||||||
{
|
{
|
||||||
public class CacheEnum : CacheObjectBase
|
public class CacheEnum : CacheObjectBase
|
||||||
{
|
{
|
||||||
public Type EnumType;
|
// public Type EnumType;
|
||||||
public string[] EnumNames;
|
public string[] EnumNames = new string[0];
|
||||||
|
|
||||||
public override void Init()
|
public override void Init()
|
||||||
{
|
{
|
||||||
try
|
if (ValueType == null && Value != null)
|
||||||
{
|
{
|
||||||
EnumType = Value.GetType();
|
ValueType = Value.GetType();
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
EnumType = (MemInfo as FieldInfo)?.FieldType ?? (MemInfo as PropertyInfo).PropertyType;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (EnumType != null)
|
if (ValueType != null)
|
||||||
{
|
{
|
||||||
EnumNames = Enum.GetNames(EnumType);
|
// using GetValues not GetNames, to catch instances of weird enums (eg CameraClearFlags)
|
||||||
|
var values = Enum.GetValues(ValueType);
|
||||||
|
|
||||||
|
var list = new List<string>();
|
||||||
|
foreach (var value in values)
|
||||||
|
{
|
||||||
|
var v = value.ToString();
|
||||||
|
if (list.Contains(v)) continue;
|
||||||
|
list.Add(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
EnumNames = list.ToArray();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -41,28 +46,28 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
if (GUILayout.Button("<", new GUILayoutOption[] { GUILayout.Width(25) }))
|
if (GUILayout.Button("<", new GUILayoutOption[] { GUILayout.Width(25) }))
|
||||||
{
|
{
|
||||||
SetEnum(ref Value, -1);
|
SetEnum(-1);
|
||||||
SetValue();
|
SetValue();
|
||||||
}
|
}
|
||||||
if (GUILayout.Button(">", new GUILayoutOption[] { GUILayout.Width(25) }))
|
if (GUILayout.Button(">", new GUILayoutOption[] { GUILayout.Width(25) }))
|
||||||
{
|
{
|
||||||
SetEnum(ref Value, 1);
|
SetEnum(1);
|
||||||
SetValue();
|
SetValue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GUILayout.Label(Value.ToString() + "<color=#2df7b2><i> (" + ValueType + ")</i></color>", null);
|
GUILayout.Label(Value.ToString() + $"<color={UIStyles.Syntax.StructGreen}><i> ({ValueType})</i></color>", new GUILayoutOption[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetEnum(ref object value, int change)
|
public void SetEnum(int change)
|
||||||
{
|
{
|
||||||
var names = EnumNames.ToList();
|
var names = EnumNames.ToList();
|
||||||
|
|
||||||
int newindex = names.IndexOf(value.ToString()) + change;
|
int newindex = names.IndexOf(Value.ToString()) + change;
|
||||||
|
|
||||||
if ((change < 0 && newindex >= 0) || (change > 0 && newindex < names.Count))
|
if (newindex >= 0 && newindex < names.Count)
|
||||||
{
|
{
|
||||||
value = Enum.Parse(EnumType, names[newindex]);
|
Value = Enum.Parse(ValueType, EnumNames[newindex]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
111
src/CachedObjects/Struct/CacheEnumFlags.cs
Normal file
111
src/CachedObjects/Struct/CacheEnumFlags.cs
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Explorer
|
||||||
|
{
|
||||||
|
public class CacheEnumFlags : CacheEnum, IExpandHeight
|
||||||
|
{
|
||||||
|
public bool[] m_enabledFlags = new bool[0];
|
||||||
|
|
||||||
|
public bool IsExpanded { get; set; }
|
||||||
|
public float WhiteSpace { get; set; } = 215f;
|
||||||
|
|
||||||
|
public override void Init()
|
||||||
|
{
|
||||||
|
base.Init();
|
||||||
|
|
||||||
|
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]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ExplorerCore.Log(e.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void DrawValue(Rect window, float width)
|
||||||
|
{
|
||||||
|
if (CanWrite)
|
||||||
|
{
|
||||||
|
if (!IsExpanded)
|
||||||
|
{
|
||||||
|
if (GUILayout.Button("v", new GUILayoutOption[] { GUILayout.Width(25) }))
|
||||||
|
{
|
||||||
|
IsExpanded = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (GUILayout.Button("^", new GUILayoutOption[] { GUILayout.Width(25) }))
|
||||||
|
{
|
||||||
|
IsExpanded = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GUILayout.Label(Value.ToString() + "<color=#2df7b2><i> (" + ValueType + ")</i></color>", new GUILayoutOption[0]);
|
||||||
|
|
||||||
|
if (IsExpanded)
|
||||||
|
{
|
||||||
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
|
var whitespace = CalcWhitespace(window);
|
||||||
|
|
||||||
|
for (int i = 0; i < EnumNames.Length; i++)
|
||||||
|
{
|
||||||
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
|
GUIUnstrip.Space(whitespace);
|
||||||
|
|
||||||
|
m_enabledFlags[i] = GUILayout.Toggle(m_enabledFlags[i], EnumNames[i], new GUILayoutOption[0]);
|
||||||
|
|
||||||
|
GUILayout.EndHorizontal();
|
||||||
|
}
|
||||||
|
|
||||||
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
|
GUIUnstrip.Space(whitespace);
|
||||||
|
if (GUILayout.Button("<color=lime>Apply</color>", new GUILayoutOption[] { GUILayout.Width(155) }))
|
||||||
|
{
|
||||||
|
SetFlagsFromInput();
|
||||||
|
}
|
||||||
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,21 +1,28 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using MelonLoader;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
#if CPP
|
||||||
|
using UnhollowerRuntimeLib;
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer
|
||||||
{
|
{
|
||||||
public class CachePrimitive : CacheObjectBase
|
public class CachePrimitive : CacheObjectBase
|
||||||
{
|
{
|
||||||
|
private string m_valueToString;
|
||||||
private bool m_isBool;
|
private bool m_isBool;
|
||||||
private bool m_isString;
|
private bool m_isString;
|
||||||
|
|
||||||
private string m_valueToString;
|
|
||||||
|
|
||||||
public MethodInfo ParseMethod => m_parseMethod ?? (m_parseMethod = Value.GetType().GetMethod("Parse", new Type[] { typeof(string) }));
|
public MethodInfo ParseMethod => m_parseMethod ?? (m_parseMethod = Value.GetType().GetMethod("Parse", new Type[] { typeof(string) }));
|
||||||
private MethodInfo m_parseMethod;
|
private MethodInfo m_parseMethod;
|
||||||
|
|
||||||
|
private bool m_canBitwiseOperate;
|
||||||
|
private bool m_inBitwiseMode;
|
||||||
|
private string m_bitwiseOperatorInput = "0";
|
||||||
|
private string m_binaryInput;
|
||||||
|
|
||||||
public override void Init()
|
public override void Init()
|
||||||
{
|
{
|
||||||
if (ValueType == null)
|
if (ValueType == null)
|
||||||
@ -37,13 +44,28 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
m_isBool = true;
|
m_isBool = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_canBitwiseOperate = typeof(int).IsAssignableFrom(ValueType);
|
||||||
|
|
||||||
|
UpdateValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void UpdateValue()
|
public override void UpdateValue()
|
||||||
{
|
{
|
||||||
base.UpdateValue();
|
base.UpdateValue();
|
||||||
|
|
||||||
|
RefreshToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RefreshToString()
|
||||||
|
{
|
||||||
m_valueToString = Value?.ToString();
|
m_valueToString = Value?.ToString();
|
||||||
|
|
||||||
|
if (m_canBitwiseOperate)
|
||||||
|
{
|
||||||
|
var _int = (int)Value;
|
||||||
|
m_binaryInput = Convert.ToString(_int, toBase: 2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void DrawValue(Rect window, float width)
|
public override void DrawValue(Rect window, float width)
|
||||||
@ -55,72 +77,175 @@ namespace Explorer
|
|||||||
|
|
||||||
if (CanWrite)
|
if (CanWrite)
|
||||||
{
|
{
|
||||||
b = GUILayout.Toggle(b, label, null);
|
b = GUILayout.Toggle(b, label, new GUILayoutOption[0]);
|
||||||
if (b != (bool)Value)
|
if (b != (bool)Value)
|
||||||
{
|
{
|
||||||
SetValueFromInput(b.ToString());
|
Value = b;
|
||||||
|
SetValue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GUILayout.Label(label, null);
|
GUILayout.Label(label, new GUILayoutOption[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
// all other non-bool values use TextField
|
||||||
|
|
||||||
|
GUILayout.BeginVertical(new GUILayoutOption[0]);
|
||||||
|
|
||||||
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
|
|
||||||
|
GUILayout.Label("<color=#2df7b2><i>" + ValueType.Name + "</i></color>", new GUILayoutOption[] { GUILayout.Width(50) });
|
||||||
|
|
||||||
|
m_valueToString = GUIUnstrip.TextArea(m_valueToString, new GUILayoutOption[] { GUILayout.ExpandWidth(true) });
|
||||||
|
if (CanWrite)
|
||||||
{
|
{
|
||||||
// using ValueType.Name instead of ValueTypeName, because we only want the short name.
|
if (GUILayout.Button("<color=#00FF00>Apply</color>", new GUILayoutOption[] { GUILayout.Width(60) }))
|
||||||
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 = GUILayout.TextArea(m_valueToString, new GUILayoutOption[] { GUILayout.MaxWidth(maxwidth) });
|
SetValueFromInput();
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
m_valueToString = GUILayout.TextField(m_valueToString, new GUILayoutOption[] { GUILayout.MaxWidth(dynSize) });
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CanWrite)
|
|
||||||
{
|
|
||||||
if (GUILayout.Button("<color=#00FF00>Apply</color>", new GUILayoutOption[] { GUILayout.Width(60) }))
|
|
||||||
{
|
|
||||||
SetValueFromInput(m_valueToString);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GUIUnstrip.Space(10);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_canBitwiseOperate)
|
||||||
|
{
|
||||||
|
m_inBitwiseMode = GUILayout.Toggle(m_inBitwiseMode, "Bitwise?", new GUILayoutOption[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
GUIUnstrip.Space(10);
|
||||||
|
|
||||||
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
|
if (m_inBitwiseMode)
|
||||||
|
{
|
||||||
|
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)
|
if (MemInfo == null)
|
||||||
{
|
{
|
||||||
MelonLogger.Log("Trying to SetValue but the MemberInfo is null!");
|
ExplorerCore.Log("Trying to SetValue but the MemberInfo is null!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_isString)
|
if (m_isString)
|
||||||
{
|
{
|
||||||
Value = valueString;
|
Value = m_valueToString;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Value = ParseMethod.Invoke(null, new object[] { valueString });
|
Value = ParseMethod.Invoke(null, new object[] { m_valueToString });
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
MelonLogger.Log("Exception parsing value: " + e.GetType() + ", " + e.Message);
|
ExplorerCore.Log("Exception parsing value: " + e.GetType() + ", " + e.Message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SetValue();
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer
|
||||||
@ -20,6 +19,8 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
base.UpdateValue();
|
base.UpdateValue();
|
||||||
|
|
||||||
|
if (Value == null) return;
|
||||||
|
|
||||||
var euler = ((Quaternion)Value).eulerAngles;
|
var euler = ((Quaternion)Value).eulerAngles;
|
||||||
|
|
||||||
x = euler.x.ToString();
|
x = euler.x.ToString();
|
||||||
@ -47,7 +48,7 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GUILayout.Label($"<color=#2df7b2>Quaternion</color>: {((Quaternion)Value).eulerAngles.ToString()}", null);
|
GUILayout.Label($"<color=#2df7b2>Quaternion</color>: {((Quaternion)Value).eulerAngles.ToString()}", new GUILayoutOption[0]);
|
||||||
|
|
||||||
if (CanWrite && IsExpanded)
|
if (CanWrite && IsExpanded)
|
||||||
{
|
{
|
||||||
@ -55,26 +56,26 @@ namespace Explorer
|
|||||||
|
|
||||||
var whitespace = CalcWhitespace(window);
|
var whitespace = CalcWhitespace(window);
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUIUnstrip.Space(whitespace);
|
GUIUnstrip.Space(whitespace);
|
||||||
GUILayout.Label("X:", new GUILayoutOption[] { GUILayout.Width(30) });
|
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.EndHorizontal();
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUIUnstrip.Space(whitespace);
|
GUIUnstrip.Space(whitespace);
|
||||||
GUILayout.Label("Y:", new GUILayoutOption[] { GUILayout.Width(30) });
|
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.EndHorizontal();
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUIUnstrip.Space(whitespace);
|
GUIUnstrip.Space(whitespace);
|
||||||
GUILayout.Label("Z:", new GUILayoutOption[] { GUILayout.Width(30) });
|
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();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
// draw set value button
|
// draw set value button
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUIUnstrip.Space(whitespace);
|
GUIUnstrip.Space(whitespace);
|
||||||
if (GUILayout.Button("<color=lime>Apply</color>", new GUILayoutOption[] { GUILayout.Width(155) }))
|
if (GUILayout.Button("<color=lime>Apply</color>", new GUILayoutOption[] { GUILayout.Width(155) }))
|
||||||
{
|
{
|
||||||
@ -82,7 +83,7 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer
|
||||||
@ -21,6 +20,8 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
base.UpdateValue();
|
base.UpdateValue();
|
||||||
|
|
||||||
|
if (Value == null) return;
|
||||||
|
|
||||||
var rect = (Rect)Value;
|
var rect = (Rect)Value;
|
||||||
|
|
||||||
x = rect.x.ToString();
|
x = rect.x.ToString();
|
||||||
@ -49,7 +50,7 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GUILayout.Label($"<color=#2df7b2>Rect</color>: {((Rect)Value).ToString()}", null);
|
GUILayout.Label($"<color=#2df7b2>Rect</color>: {((Rect)Value).ToString()}", new GUILayoutOption[0]);
|
||||||
|
|
||||||
if (CanWrite && IsExpanded)
|
if (CanWrite && IsExpanded)
|
||||||
{
|
{
|
||||||
@ -57,32 +58,32 @@ namespace Explorer
|
|||||||
|
|
||||||
var whitespace = CalcWhitespace(window);
|
var whitespace = CalcWhitespace(window);
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUIUnstrip.Space(whitespace);
|
GUIUnstrip.Space(whitespace);
|
||||||
GUILayout.Label("X:", new GUILayoutOption[] { GUILayout.Width(30) });
|
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.EndHorizontal();
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUIUnstrip.Space(whitespace);
|
GUIUnstrip.Space(whitespace);
|
||||||
GUILayout.Label("Y:", new GUILayoutOption[] { GUILayout.Width(30) });
|
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.EndHorizontal();
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUIUnstrip.Space(whitespace);
|
GUIUnstrip.Space(whitespace);
|
||||||
GUILayout.Label("W:", new GUILayoutOption[] { GUILayout.Width(30) });
|
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.EndHorizontal();
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUIUnstrip.Space(whitespace);
|
GUIUnstrip.Space(whitespace);
|
||||||
GUILayout.Label("H:", new GUILayoutOption[] { GUILayout.Width(30) });
|
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();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
// draw set value button
|
// draw set value button
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUIUnstrip.Space(whitespace);
|
GUIUnstrip.Space(whitespace);
|
||||||
if (GUILayout.Button("<color=lime>Apply</color>", new GUILayoutOption[] { GUILayout.Width(155) }))
|
if (GUILayout.Button("<color=lime>Apply</color>", new GUILayoutOption[] { GUILayout.Width(155) }))
|
||||||
{
|
{
|
||||||
@ -90,7 +91,7 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
@ -24,20 +23,26 @@ namespace Explorer
|
|||||||
|
|
||||||
public override void Init()
|
public override void Init()
|
||||||
{
|
{
|
||||||
if (Value is Vector2)
|
if (ValueType == null && Value != null)
|
||||||
|
{
|
||||||
|
ValueType = Value.GetType();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ValueType == typeof(Vector2))
|
||||||
{
|
{
|
||||||
VectorSize = 2;
|
VectorSize = 2;
|
||||||
|
m_toStringMethod = typeof(Vector2).GetMethod("ToString", new Type[0]);
|
||||||
}
|
}
|
||||||
else if (Value is Vector3)
|
else if (ValueType == typeof(Vector3))
|
||||||
{
|
{
|
||||||
VectorSize = 3;
|
VectorSize = 3;
|
||||||
|
m_toStringMethod = typeof(Vector3).GetMethod("ToString", new Type[0]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
VectorSize = 4;
|
VectorSize = 4;
|
||||||
|
m_toStringMethod = typeof(Vector4).GetMethod("ToString", new Type[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_toStringMethod = Value.GetType().GetMethod("ToString", new Type[0]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void UpdateValue()
|
public override void UpdateValue()
|
||||||
@ -84,7 +89,7 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GUILayout.Label($"<color=#2df7b2>Vector{VectorSize}</color>: {(string)m_toStringMethod.Invoke(Value, new object[0])}", null);
|
GUILayout.Label($"<color=#2df7b2>Vector{VectorSize}</color>: {(string)m_toStringMethod.Invoke(Value, new object[0])}", new GUILayoutOption[0]);
|
||||||
|
|
||||||
if (CanWrite && IsExpanded)
|
if (CanWrite && IsExpanded)
|
||||||
{
|
{
|
||||||
@ -93,39 +98,39 @@ namespace Explorer
|
|||||||
var whitespace = CalcWhitespace(window);
|
var whitespace = CalcWhitespace(window);
|
||||||
|
|
||||||
// always draw x and y
|
// always draw x and y
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUIUnstrip.Space(whitespace);
|
GUIUnstrip.Space(whitespace);
|
||||||
GUILayout.Label("X:", new GUILayoutOption[] { GUILayout.Width(30) });
|
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.EndHorizontal();
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUIUnstrip.Space(whitespace);
|
GUIUnstrip.Space(whitespace);
|
||||||
GUILayout.Label("Y:", new GUILayoutOption[] { GUILayout.Width(30) });
|
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.EndHorizontal();
|
||||||
|
|
||||||
if (VectorSize > 2)
|
if (VectorSize > 2)
|
||||||
{
|
{
|
||||||
// draw z
|
// draw z
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUIUnstrip.Space(whitespace);
|
GUIUnstrip.Space(whitespace);
|
||||||
GUILayout.Label("Z:", new GUILayoutOption[] { GUILayout.Width(30) });
|
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();
|
GUILayout.EndHorizontal();
|
||||||
}
|
}
|
||||||
if (VectorSize > 3)
|
if (VectorSize > 3)
|
||||||
{
|
{
|
||||||
// draw w
|
// draw w
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUIUnstrip.Space(whitespace);
|
GUIUnstrip.Space(whitespace);
|
||||||
GUILayout.Label("W:", new GUILayoutOption[] { GUILayout.Width(30) });
|
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.EndHorizontal();
|
||||||
}
|
}
|
||||||
|
|
||||||
// draw set value button
|
// draw set value button
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUIUnstrip.Space(whitespace);
|
GUIUnstrip.Space(whitespace);
|
||||||
if (GUILayout.Button("<color=lime>Apply</color>", new GUILayoutOption[] { GUILayout.Width(155) }))
|
if (GUILayout.Button("<color=lime>Apply</color>", new GUILayoutOption[] { GUILayout.Width(155) }))
|
||||||
{
|
{
|
||||||
@ -133,7 +138,7 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,9 +1,4 @@
|
|||||||
using System;
|
using System.IO;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Xml.Serialization;
|
using System.Xml.Serialization;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
@ -13,13 +8,14 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
[XmlIgnore] public static readonly XmlSerializer Serializer = new XmlSerializer(typeof(ModConfig));
|
[XmlIgnore] public static readonly XmlSerializer Serializer = new XmlSerializer(typeof(ModConfig));
|
||||||
|
|
||||||
[XmlIgnore] private const string EXPLORER_FOLDER = @"Mods\CppExplorer";
|
[XmlIgnore] private const string EXPLORER_FOLDER = @"Mods\Explorer";
|
||||||
[XmlIgnore] private const string SETTINGS_PATH = EXPLORER_FOLDER + @"\config.xml";
|
[XmlIgnore] private const string SETTINGS_PATH = EXPLORER_FOLDER + @"\config.xml";
|
||||||
|
|
||||||
[XmlIgnore] public static ModConfig Instance;
|
[XmlIgnore] public static ModConfig Instance;
|
||||||
|
|
||||||
public KeyCode Main_Menu_Toggle = KeyCode.F7;
|
public KeyCode Main_Menu_Toggle = KeyCode.F7;
|
||||||
public Vector2 Default_Window_Size = new Vector2(550, 700);
|
public Vector2 Default_Window_Size = new Vector2(550, 700);
|
||||||
|
public int Default_Page_Limit = 20;
|
||||||
|
|
||||||
public static void OnLoad()
|
public static void OnLoad()
|
||||||
{
|
{
|
||||||
@ -35,9 +31,9 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
|
|
||||||
// returns true if settings successfully loaded
|
// 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;
|
return false;
|
||||||
|
|
||||||
try
|
try
|
||||||
@ -55,9 +51,9 @@ namespace Explorer
|
|||||||
return Instance != null;
|
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);
|
File.Delete(SETTINGS_PATH);
|
||||||
|
|
||||||
using (var file = File.Create(SETTINGS_PATH))
|
using (var file = File.Create(SETTINGS_PATH))
|
||||||
|
@ -1,127 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<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>
|
|
||||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
|
||||||
<ProjectGuid>{B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}</ProjectGuid>
|
|
||||||
<OutputType>Library</OutputType>
|
|
||||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
|
||||||
<RootNamespace>Explorer</RootNamespace>
|
|
||||||
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
|
||||||
<FileAlignment>512</FileAlignment>
|
|
||||||
<Deterministic>true</Deterministic>
|
|
||||||
<TargetFrameworkProfile />
|
|
||||||
<AssemblyName>CppExplorer</AssemblyName>
|
|
||||||
<DebugSymbols>false</DebugSymbols>
|
|
||||||
<DebugType>none</DebugType>
|
|
||||||
<Optimize>false</Optimize>
|
|
||||||
<OutputPath>..\Release\</OutputPath>
|
|
||||||
<DefineConstants />
|
|
||||||
<ErrorReport>prompt</ErrorReport>
|
|
||||||
<WarningLevel>4</WarningLevel>
|
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
|
||||||
<Prefer32Bit>false</Prefer32Bit>
|
|
||||||
</PropertyGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<!-- Replace the '..\Steam\..` references with ones from your game (make sure to use the 'MelonLoader\' folder) -->
|
|
||||||
<Reference Include="Il2Cppmscorlib">
|
|
||||||
<HintPath>..\..\..\..\..\Steam\steamapps\common\Hellpoint\MelonLoader\Managed\Il2Cppmscorlib.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="Il2CppSystem.Core">
|
|
||||||
<HintPath>..\..\..\Steam\steamapps\common\Hellpoint\MelonLoader\Managed\Il2CppSystem.Core.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="mcs">
|
|
||||||
<HintPath>..\lib\mcs.dll</HintPath>
|
|
||||||
<Private>True</Private>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="MelonLoader.ModHandler">
|
|
||||||
<HintPath>..\..\..\..\..\Steam\steamapps\common\Hellpoint\MelonLoader\MelonLoader.ModHandler.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="System" />
|
|
||||||
<Reference Include="System.Core" />
|
|
||||||
<Reference Include="System.Xml.Linq" />
|
|
||||||
<Reference Include="System.Data.DataSetExtensions" />
|
|
||||||
<Reference Include="System.Data" />
|
|
||||||
<Reference Include="System.Xml" />
|
|
||||||
<Reference Include="UnhollowerBaseLib">
|
|
||||||
<HintPath>..\..\..\..\..\Steam\steamapps\common\Hellpoint\MelonLoader\Managed\UnhollowerBaseLib.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="UnityEngine">
|
|
||||||
<HintPath>..\..\..\Steam\steamapps\common\Hellpoint\MelonLoader\Managed\UnityEngine.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="UnityEngine.CoreModule">
|
|
||||||
<HintPath>..\..\..\Steam\steamapps\common\Hellpoint\MelonLoader\Managed\UnityEngine.CoreModule.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="UnityEngine.IMGUIModule">
|
|
||||||
<HintPath>..\..\..\Steam\steamapps\common\Hellpoint\MelonLoader\Managed\UnityEngine.IMGUIModule.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="UnityEngine.PhysicsModule">
|
|
||||||
<HintPath>..\..\..\Steam\steamapps\common\Hellpoint\MelonLoader\Managed\UnityEngine.PhysicsModule.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="UnityEngine.TextRenderingModule">
|
|
||||||
<HintPath>..\..\..\Steam\steamapps\common\Hellpoint\MelonLoader\Managed\UnityEngine.TextRenderingModule.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="UnityEngine.UI">
|
|
||||||
<HintPath>..\..\..\Steam\steamapps\common\Hellpoint\MelonLoader\Managed\UnityEngine.UI.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
|
||||||
</Reference>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Compile Include="CachedObjects\IExpandHeight.cs" />
|
|
||||||
<Compile Include="CachedObjects\Struct\CacheColor.cs" />
|
|
||||||
<Compile Include="CachedObjects\Object\CacheDictionary.cs" />
|
|
||||||
<Compile Include="CachedObjects\Struct\CacheEnum.cs" />
|
|
||||||
<Compile Include="CachedObjects\Object\CacheGameObject.cs" />
|
|
||||||
<Compile Include="CachedObjects\Object\CacheList.cs" />
|
|
||||||
<Compile Include="CachedObjects\Struct\CachePrimitive.cs" />
|
|
||||||
<Compile Include="CachedObjects\Other\CacheOther.cs" />
|
|
||||||
<Compile Include="CachedObjects\Other\CacheMethod.cs" />
|
|
||||||
<Compile Include="CachedObjects\Struct\CacheQuaternion.cs" />
|
|
||||||
<Compile Include="CachedObjects\Struct\CacheVector.cs" />
|
|
||||||
<Compile Include="CachedObjects\Struct\CacheRect.cs" />
|
|
||||||
<Compile Include="Config\ModConfig.cs" />
|
|
||||||
<Compile Include="CppExplorer.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="Extensions\UnityExtensions.cs" />
|
|
||||||
<Compile Include="Helpers\PageHelper.cs" />
|
|
||||||
<Compile Include="Helpers\ReflectionHelpers.cs" />
|
|
||||||
<Compile Include="Menu\UIHelpers.cs" />
|
|
||||||
<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="Menu\ResizeDrag.cs" />
|
|
||||||
<Compile Include="Menu\Windows\TabViewWindow.cs" />
|
|
||||||
<Compile Include="Menu\Windows\UIWindow.cs" />
|
|
||||||
<Compile Include="Menu\MainMenu\Pages\ConsolePage.cs" />
|
|
||||||
<Compile Include="Menu\MainMenu\Pages\Console\REPL.cs" />
|
|
||||||
<Compile Include="Menu\MainMenu\Pages\Console\REPLHelper.cs" />
|
|
||||||
<Compile Include="Menu\MainMenu\Pages\WindowPage.cs" />
|
|
||||||
<Compile Include="Menu\Windows\WindowManager.cs" />
|
|
||||||
<Compile Include="Menu\MainMenu\MainMenu.cs" />
|
|
||||||
<Compile Include="Menu\Windows\GameObjectWindow.cs" />
|
|
||||||
<Compile Include="Menu\Windows\ReflectionWindow.cs" />
|
|
||||||
<Compile Include="Menu\MainMenu\Pages\ScenePage.cs" />
|
|
||||||
<Compile Include="Menu\MainMenu\Pages\SearchPage.cs" />
|
|
||||||
<Compile Include="Menu\UIStyles.cs" />
|
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
|
||||||
</ItemGroup>
|
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
|
||||||
</Project>
|
|
@ -1,22 +0,0 @@
|
|||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
|
||||||
# Visual Studio Version 16
|
|
||||||
VisualStudioVersion = 16.0.30128.74
|
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CppExplorer", "CppExplorer.csproj", "{B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}"
|
|
||||||
EndProject
|
|
||||||
Global
|
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
|
||||||
Release|Any CPU = Release|Any CPU
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
|
||||||
{B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}.Release|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}.Release|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
|
||||||
HideSolutionNode = FALSE
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
|
||||||
SolutionGuid = {DD5C0A5D-03F1-4CC3-8B4D-E10834908C5A}
|
|
||||||
EndGlobalSection
|
|
||||||
EndGlobal
|
|
278
src/Explorer.csproj
Normal file
278
src/Explorer.csproj
Normal file
@ -0,0 +1,278 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<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)' == '' ">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>
|
||||||
|
<FileAlignment>512</FileAlignment>
|
||||||
|
<Deterministic>true</Deterministic>
|
||||||
|
<TargetFrameworkProfile />
|
||||||
|
<OutputPath>..\Release\Explorer.MelonLoader.Il2Cpp\</OutputPath>
|
||||||
|
<DefineConstants>CPP,ML</DefineConstants>
|
||||||
|
<IsCpp>true</IsCpp>
|
||||||
|
<IsMelonLoader>true</IsMelonLoader>
|
||||||
|
<IsNet35>false</IsNet35>
|
||||||
|
<DebugSymbols>false</DebugSymbols>
|
||||||
|
<DebugType>none</DebugType>
|
||||||
|
<Optimize>false</Optimize>
|
||||||
|
<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>
|
||||||
|
<OutputPath>..\Release\Explorer.MelonLoader.Mono\</OutputPath>
|
||||||
|
<DefineConstants>MONO,ML</DefineConstants>
|
||||||
|
<Prefer32Bit>false</Prefer32Bit>
|
||||||
|
<IsCpp>false</IsCpp>
|
||||||
|
<IsMelonLoader>true</IsMelonLoader>
|
||||||
|
<IsNet35>false</IsNet35>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_ML_Mono_NET35|AnyCPU' ">
|
||||||
|
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
||||||
|
<OutputPath>..\Release\Explorer.MelonLoader.Mono.NET35\</OutputPath>
|
||||||
|
<DefineConstants>MONO,ML,NET35</DefineConstants>
|
||||||
|
<IsCpp>false</IsCpp>
|
||||||
|
<IsMelonLoader>true</IsMelonLoader>
|
||||||
|
<IsNet35>true</IsNet35>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_BIE_Cpp|AnyCPU' ">
|
||||||
|
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
||||||
|
<OutputPath>..\Release\Explorer.BepInEx.Il2Cpp\</OutputPath>
|
||||||
|
<DefineConstants>CPP,BIE</DefineConstants>
|
||||||
|
<IsCpp>true</IsCpp>
|
||||||
|
<IsMelonLoader>false</IsMelonLoader>
|
||||||
|
<IsNet35>false</IsNet35>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_BIE_Mono|AnyCPU' ">
|
||||||
|
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
||||||
|
<OutputPath>..\Release\Explorer.BepInEx.Mono\</OutputPath>
|
||||||
|
<DefineConstants>MONO,BIE</DefineConstants>
|
||||||
|
<IsCpp>false</IsCpp>
|
||||||
|
<IsMelonLoader>false</IsMelonLoader>
|
||||||
|
<IsNet35>false</IsNet35>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_BIE_Mono_NET35|AnyCPU' ">
|
||||||
|
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
||||||
|
<OutputPath>..\Release\Explorer.BepInEx.Mono.NET35\</OutputPath>
|
||||||
|
<DefineConstants>MONO,BIE,NET35</DefineConstants>
|
||||||
|
<IsCpp>false</IsCpp>
|
||||||
|
<IsMelonLoader>false</IsMelonLoader>
|
||||||
|
<IsNet35>true</IsNet35>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="System" />
|
||||||
|
<Reference Include="System.Core" />
|
||||||
|
<Reference Include="System.Xml.Linq" />
|
||||||
|
<Reference Include="System.Data.DataSetExtensions" />
|
||||||
|
<Reference Include="System.Data" />
|
||||||
|
<Reference Include="System.Xml" />
|
||||||
|
<!-- MCS ref -->
|
||||||
|
<Reference Include="mcs" Condition="'$(IsNet35)'=='false'">
|
||||||
|
<HintPath>..\lib\mcs.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="mcs" Condition="'$(IsNet35)'=='true'">
|
||||||
|
<HintPath>..\lib\mcs.NET35.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
|
</Reference>
|
||||||
|
</ItemGroup>
|
||||||
|
<!-- Universal Mono UnityEngine.dll ref (v5.3) -->
|
||||||
|
<ItemGroup Condition="'$(IsCpp)'=='false'">
|
||||||
|
<Reference Include="UnityEngine">
|
||||||
|
<HintPath>..\lib\UnityEngine.dll</HintPath>
|
||||||
|
<Private>False</Private>
|
||||||
|
</Reference>
|
||||||
|
</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">
|
||||||
|
<HintPath>$(MLCppGameFolder)\MelonLoader\Managed\Il2Cppmscorlib.dll</HintPath>
|
||||||
|
<Private>False</Private>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Il2CppSystem.Core">
|
||||||
|
<HintPath>$(MLCppGameFolder)\MelonLoader\Managed\Il2CppSystem.Core.dll</HintPath>
|
||||||
|
<Private>False</Private>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="UnityEngine">
|
||||||
|
<HintPath>$(MLCppGameFolder)\MelonLoader\Managed\UnityEngine.dll</HintPath>
|
||||||
|
<Private>False</Private>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="UnityEngine.CoreModule">
|
||||||
|
<HintPath>$(MLCppGameFolder)\MelonLoader\Managed\UnityEngine.CoreModule.dll</HintPath>
|
||||||
|
<Private>False</Private>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="UnityEngine.IMGUIModule">
|
||||||
|
<HintPath>$(MLCppGameFolder)\MelonLoader\Managed\UnityEngine.IMGUIModule.dll</HintPath>
|
||||||
|
<Private>False</Private>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="UnityEngine.PhysicsModule">
|
||||||
|
<HintPath>$(MLCppGameFolder)\MelonLoader\Managed\UnityEngine.PhysicsModule.dll</HintPath>
|
||||||
|
<Private>False</Private>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="UnityEngine.TextRenderingModule">
|
||||||
|
<HintPath>$(MLCppGameFolder)\MelonLoader\Managed\UnityEngine.TextRenderingModule.dll</HintPath>
|
||||||
|
<Private>False</Private>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="UnityEngine.UI">
|
||||||
|
<HintPath>$(MLCppGameFolder)\MelonLoader\Managed\UnityEngine.UI.dll</HintPath>
|
||||||
|
<Private>False</Private>
|
||||||
|
</Reference>
|
||||||
|
</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">
|
||||||
|
<HintPath>$(BIECppGameFolder)\BepInEx\unhollowed\Il2Cppmscorlib.dll</HintPath>
|
||||||
|
<Private>False</Private>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Il2CppSystem.Core">
|
||||||
|
<HintPath>$(BIECppGameFolder)\BepInEx\unhollowed\Il2CppSystem.Core.dll</HintPath>
|
||||||
|
<Private>False</Private>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="UnityEngine">
|
||||||
|
<HintPath>$(BIECppGameFolder)\BepInEx\unhollowed\UnityEngine.dll</HintPath>
|
||||||
|
<Private>False</Private>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="UnityEngine.CoreModule">
|
||||||
|
<HintPath>$(BIECppGameFolder)\BepInEx\unhollowed\UnityEngine.CoreModule.dll</HintPath>
|
||||||
|
<Private>False</Private>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="UnityEngine.IMGUIModule">
|
||||||
|
<HintPath>$(BIECppGameFolder)\BepInEx\unhollowed\UnityEngine.IMGUIModule.dll</HintPath>
|
||||||
|
<Private>False</Private>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="UnityEngine.PhysicsModule">
|
||||||
|
<HintPath>$(BIECppGameFolder)\BepInEx\unhollowed\UnityEngine.PhysicsModule.dll</HintPath>
|
||||||
|
<Private>False</Private>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="UnityEngine.TextRenderingModule">
|
||||||
|
<HintPath>$(BIECppGameFolder)\BepInEx\unhollowed\UnityEngine.TextRenderingModule.dll</HintPath>
|
||||||
|
<Private>False</Private>
|
||||||
|
</Reference>
|
||||||
|
<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" />
|
||||||
|
<Compile Include="CachedObjects\Struct\CacheEnum.cs" />
|
||||||
|
<Compile Include="CachedObjects\Object\CacheGameObject.cs" />
|
||||||
|
<Compile Include="CachedObjects\Object\CacheList.cs" />
|
||||||
|
<Compile Include="CachedObjects\Struct\CacheEnumFlags.cs" />
|
||||||
|
<Compile Include="CachedObjects\Struct\CachePrimitive.cs" />
|
||||||
|
<Compile Include="CachedObjects\Other\CacheOther.cs" />
|
||||||
|
<Compile Include="CachedObjects\Other\CacheMethod.cs" />
|
||||||
|
<Compile Include="CachedObjects\Struct\CacheQuaternion.cs" />
|
||||||
|
<Compile Include="CachedObjects\Struct\CacheVector.cs" />
|
||||||
|
<Compile Include="CachedObjects\Struct\CacheRect.cs" />
|
||||||
|
<Compile Include="Config\ModConfig.cs" />
|
||||||
|
<Compile Include="ExplorerCore.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="Menu\MainMenu\Pages\OptionsPage.cs" />
|
||||||
|
<Compile Include="Tests\TestClass.cs" />
|
||||||
|
<Compile Include="UnstripFixes\GUIUnstrip.cs" />
|
||||||
|
<Compile Include="UnstripFixes\Internal_LayoutUtility.cs" />
|
||||||
|
<Compile Include="Extensions\UnityExtensions.cs" />
|
||||||
|
<Compile Include="Helpers\PageHelper.cs" />
|
||||||
|
<Compile Include="Helpers\ReflectionHelpers.cs" />
|
||||||
|
<Compile Include="Menu\UIHelpers.cs" />
|
||||||
|
<Compile Include="Helpers\UnityHelpers.cs" />
|
||||||
|
<Compile Include="Menu\InspectUnderMouse.cs" />
|
||||||
|
<Compile Include="CachedObjects\CacheObjectBase.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" />
|
||||||
|
<Compile Include="Menu\MainMenu\Pages\ConsolePage.cs" />
|
||||||
|
<Compile Include="Menu\MainMenu\Pages\Console\REPL.cs" />
|
||||||
|
<Compile Include="Menu\MainMenu\Pages\Console\REPLHelper.cs" />
|
||||||
|
<Compile Include="Menu\MainMenu\Pages\WindowPage.cs" />
|
||||||
|
<Compile Include="Menu\Windows\WindowManager.cs" />
|
||||||
|
<Compile Include="Menu\MainMenu\MainMenu.cs" />
|
||||||
|
<Compile Include="Menu\Windows\GameObjectWindow.cs" />
|
||||||
|
<Compile Include="Menu\Windows\ReflectionWindow.cs" />
|
||||||
|
<Compile Include="Menu\MainMenu\Pages\ScenePage.cs" />
|
||||||
|
<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>
|
37
src/Explorer.sln
Normal file
37
src/Explorer.sln
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio Version 16
|
||||||
|
VisualStudioVersion = 16.0.30128.74
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Explorer", "Explorer.csproj", "{B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Release_BIE_Cpp|Any CPU = Release_BIE_Cpp|Any CPU
|
||||||
|
Release_BIE_Mono_NET35|Any CPU = Release_BIE_Mono_NET35|Any CPU
|
||||||
|
Release_BIE_Mono|Any CPU = Release_BIE_Mono|Any CPU
|
||||||
|
Release_ML_Cpp|Any CPU = Release_ML_Cpp|Any CPU
|
||||||
|
Release_ML_Mono_NET35|Any CPU = Release_ML_Mono_NET35|Any CPU
|
||||||
|
Release_ML_Mono|Any CPU = Release_ML_Mono|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}.Release_BIE_Cpp|Any CPU.ActiveCfg = Release_BIE_Cpp|Any CPU
|
||||||
|
{B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}.Release_BIE_Cpp|Any CPU.Build.0 = Release_BIE_Cpp|Any CPU
|
||||||
|
{B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}.Release_BIE_Mono_NET35|Any CPU.ActiveCfg = Release_BIE_Mono_NET35|Any CPU
|
||||||
|
{B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}.Release_BIE_Mono_NET35|Any CPU.Build.0 = Release_BIE_Mono_NET35|Any CPU
|
||||||
|
{B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}.Release_BIE_Mono|Any CPU.ActiveCfg = Release_BIE_Mono|Any CPU
|
||||||
|
{B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}.Release_BIE_Mono|Any CPU.Build.0 = Release_BIE_Mono|Any CPU
|
||||||
|
{B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}.Release_ML_Cpp|Any CPU.ActiveCfg = Release_ML_Cpp|Any CPU
|
||||||
|
{B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}.Release_ML_Cpp|Any CPU.Build.0 = Release_ML_Cpp|Any CPU
|
||||||
|
{B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}.Release_ML_Mono_NET35|Any CPU.ActiveCfg = Release_ML_Mono_NET35|Any CPU
|
||||||
|
{B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}.Release_ML_Mono_NET35|Any CPU.Build.0 = Release_ML_Mono_NET35|Any CPU
|
||||||
|
{B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}.Release_ML_Mono|Any CPU.ActiveCfg = Release_ML_Mono|Any CPU
|
||||||
|
{B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}.Release_ML_Mono|Any CPU.Build.0 = Release_ML_Mono|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {DD5C0A5D-03F1-4CC3-8B4D-E10834908C5A}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
122
src/ExplorerBepInPlugin.cs
Normal file
122
src/ExplorerBepInPlugin.cs
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
#if BIE
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Reflection;
|
||||||
|
using BepInEx;
|
||||||
|
using BepInEx.Logging;
|
||||||
|
using HarmonyLib;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.SceneManagement;
|
||||||
|
#if CPP
|
||||||
|
using UnhollowerRuntimeLib;
|
||||||
|
using BepInEx.IL2CPP;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace Explorer
|
||||||
|
{
|
||||||
|
[BepInPlugin(ExplorerCore.GUID, ExplorerCore.NAME, ExplorerCore.VERSION)]
|
||||||
|
#if CPP
|
||||||
|
public class ExplorerBepInPlugin : BasePlugin
|
||||||
|
#else
|
||||||
|
public class ExplorerBepInPlugin : BaseUnityPlugin
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
public static ExplorerBepInPlugin Instance;
|
||||||
|
|
||||||
|
public static ManualLogSource Logging =>
|
||||||
|
#if CPP
|
||||||
|
Instance?.Log;
|
||||||
|
#else
|
||||||
|
Instance?.Logger;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
public static readonly Harmony HarmonyInstance = new Harmony(ExplorerCore.GUID);
|
||||||
|
|
||||||
|
#if CPP
|
||||||
|
// temporary for Il2Cpp until scene change delegate works
|
||||||
|
private static string lastSceneName;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Init
|
||||||
|
#if CPP
|
||||||
|
public override void Load()
|
||||||
|
{
|
||||||
|
#else
|
||||||
|
internal void Awake()
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
Instance = this;
|
||||||
|
|
||||||
|
#if CPP
|
||||||
|
ClassInjector.RegisterTypeInIl2Cpp<ExplorerBehaviour>();
|
||||||
|
|
||||||
|
var obj = new GameObject(
|
||||||
|
"ExplorerBehaviour",
|
||||||
|
new Il2CppSystem.Type[]
|
||||||
|
{
|
||||||
|
Il2CppType.Of<ExplorerBehaviour>()
|
||||||
|
}
|
||||||
|
);
|
||||||
|
GameObject.DontDestroyOnLoad(obj);
|
||||||
|
#else
|
||||||
|
SceneManager.activeSceneChanged += DoSceneChange;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
LoadMCS();
|
||||||
|
|
||||||
|
new ExplorerCore();
|
||||||
|
|
||||||
|
//HarmonyInstance.PatchAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoadMCS()
|
||||||
|
{
|
||||||
|
#if NET35
|
||||||
|
var path = @"BepInEx\plugins\mcs.NET35.dll";
|
||||||
|
#else
|
||||||
|
var path = @"BepInEx\plugins\mcs.dll";
|
||||||
|
#endif
|
||||||
|
Assembly.Load(File.ReadAllBytes(path));
|
||||||
|
ExplorerCore.Log("Loaded mcs!");
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void DoSceneChange(Scene arg0, Scene arg1)
|
||||||
|
{
|
||||||
|
ExplorerCore.OnSceneChange();
|
||||||
|
}
|
||||||
|
|
||||||
|
#if CPP // BepInEx Il2Cpp mod class doesn't have monobehaviour methods yet, so wrap them in a dummy.
|
||||||
|
public class ExplorerBehaviour : MonoBehaviour
|
||||||
|
{
|
||||||
|
public ExplorerBehaviour(IntPtr ptr) : base(ptr) { }
|
||||||
|
|
||||||
|
internal void Awake()
|
||||||
|
{
|
||||||
|
Logging.LogMessage("ExplorerBehaviour.Awake");
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
internal void Update()
|
||||||
|
{
|
||||||
|
ExplorerCore.Update();
|
||||||
|
|
||||||
|
#if CPP
|
||||||
|
var scene = SceneManager.GetActiveScene();
|
||||||
|
if (scene.name != lastSceneName)
|
||||||
|
{
|
||||||
|
lastSceneName = scene.name;
|
||||||
|
DoSceneChange(scene, scene);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void OnGUI()
|
||||||
|
{
|
||||||
|
ExplorerCore.OnGUI();
|
||||||
|
}
|
||||||
|
#if CPP
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
@ -1,23 +1,43 @@
|
|||||||
using System;
|
using UnityEngine;
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
|
||||||
using Harmony;
|
|
||||||
using MelonLoader;
|
|
||||||
using UnhollowerBaseLib;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer
|
||||||
{
|
{
|
||||||
public class CppExplorer : MelonMod
|
public class ExplorerCore
|
||||||
{
|
{
|
||||||
public const string NAME = "CppExplorer";
|
public const string NAME = "Explorer (" + PLATFORM + ", " + MODLOADER + ")";
|
||||||
public const string VERSION = "1.7.31";
|
public const string VERSION = "1.8.21";
|
||||||
public const string AUTHOR = "Sinai";
|
public const string AUTHOR = "Sinai";
|
||||||
public const string GUID = "com.sinai.cppexplorer";
|
public const string GUID = "com.sinai.explorer";
|
||||||
|
|
||||||
public static CppExplorer Instance { get; private set; }
|
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()
|
||||||
|
{
|
||||||
|
Instance = this;
|
||||||
|
|
||||||
|
ModConfig.OnLoad();
|
||||||
|
|
||||||
|
new MainMenu();
|
||||||
|
new WindowManager();
|
||||||
|
|
||||||
|
InputHelper.Init();
|
||||||
|
CursorControl.Init();
|
||||||
|
|
||||||
|
Log($"{NAME} {VERSION} initialized.");
|
||||||
|
}
|
||||||
|
|
||||||
public static bool ShowMenu
|
public static bool ShowMenu
|
||||||
{
|
{
|
||||||
@ -32,29 +52,7 @@ namespace Explorer
|
|||||||
CursorControl.UpdateCursorControl();
|
CursorControl.UpdateCursorControl();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnApplicationStart()
|
public static void Update()
|
||||||
{
|
|
||||||
Instance = this;
|
|
||||||
|
|
||||||
ModConfig.OnLoad();
|
|
||||||
|
|
||||||
InputHelper.Init();
|
|
||||||
|
|
||||||
new MainMenu();
|
|
||||||
new WindowManager();
|
|
||||||
|
|
||||||
CursorControl.Init();
|
|
||||||
|
|
||||||
MelonLogger.Log($"CppExplorer {VERSION} initialized.");
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void OnLevelWasLoaded(int level)
|
|
||||||
{
|
|
||||||
ScenePage.Instance?.OnSceneChange();
|
|
||||||
SearchPage.Instance?.OnSceneChange();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void OnUpdate()
|
|
||||||
{
|
{
|
||||||
if (InputHelper.GetKeyDown(ModConfig.Instance.Main_Menu_Toggle))
|
if (InputHelper.GetKeyDown(ModConfig.Instance.Main_Menu_Toggle))
|
||||||
{
|
{
|
||||||
@ -71,7 +69,7 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnGUI()
|
public static void OnGUI()
|
||||||
{
|
{
|
||||||
if (!ShowMenu) return;
|
if (!ShowMenu) return;
|
||||||
|
|
||||||
@ -84,5 +82,38 @@ namespace Explorer
|
|||||||
|
|
||||||
GUI.skin = origSkin;
|
GUI.skin = origSkin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void OnSceneChange()
|
||||||
|
{
|
||||||
|
ScenePage.Instance?.OnSceneChange();
|
||||||
|
SearchPage.Instance?.OnSceneChange();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Log(string message)
|
||||||
|
{
|
||||||
|
#if ML
|
||||||
|
MelonLoader.MelonLogger.Log(message);
|
||||||
|
#else
|
||||||
|
ExplorerBepInPlugin.Logging?.LogMessage(message);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void LogWarning(string message)
|
||||||
|
{
|
||||||
|
#if ML
|
||||||
|
MelonLoader.MelonLogger.LogWarning(message);
|
||||||
|
#else
|
||||||
|
ExplorerBepInPlugin.Logging?.LogWarning(message);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void LogError(string message)
|
||||||
|
{
|
||||||
|
#if ML
|
||||||
|
MelonLoader.MelonLogger.LogError(message);
|
||||||
|
#else
|
||||||
|
ExplorerBepInPlugin.Logging?.LogError(message);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
37
src/ExplorerMelonMod.cs
Normal file
37
src/ExplorerMelonMod.cs
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#if ML
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using MelonLoader;
|
||||||
|
|
||||||
|
namespace Explorer
|
||||||
|
{
|
||||||
|
public class ExplorerMelonMod : MelonMod
|
||||||
|
{
|
||||||
|
public static ExplorerMelonMod Instance;
|
||||||
|
|
||||||
|
public override void OnApplicationStart()
|
||||||
|
{
|
||||||
|
Instance = this;
|
||||||
|
|
||||||
|
new ExplorerCore();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnLevelWasLoaded(int level)
|
||||||
|
{
|
||||||
|
ExplorerCore.OnSceneChange();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnUpdate()
|
||||||
|
{
|
||||||
|
ExplorerCore.Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnGUI()
|
||||||
|
{
|
||||||
|
ExplorerCore.OnGUI();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
@ -1,26 +1,19 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer
|
||||||
{
|
{
|
||||||
public static class ReflectionExtensions
|
public static class ReflectionExtensions
|
||||||
{
|
{
|
||||||
/// <summary>
|
#if CPP
|
||||||
/// 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)
|
public static object Il2CppCast(this object obj, Type castTo)
|
||||||
{
|
{
|
||||||
return ReflectionHelpers.Il2CppCast(obj, 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)
|
public static IEnumerable<Type> TryGetTypes(this Assembly asm)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@ -29,7 +22,14 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
catch (ReflectionTypeLoadException e)
|
catch (ReflectionTypeLoadException e)
|
||||||
{
|
{
|
||||||
return e.Types.Where(t => t != null);
|
try
|
||||||
|
{
|
||||||
|
return asm.GetExportedTypes();
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return e.Types.Where(t => t != null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
|
@ -1,10 +1,4 @@
|
|||||||
using System;
|
using UnityEngine;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using UnhollowerBaseLib;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer
|
||||||
{
|
{
|
||||||
|
@ -1,28 +1,45 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using MelonLoader;
|
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Version-agnostic UnityEngine Input module using Reflection.
|
/// Version-agnostic Input module using Reflection.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static class InputHelper
|
public static class InputHelper
|
||||||
{
|
{
|
||||||
// If Input module failed to load at all
|
// If Input module failed to load at all
|
||||||
public static bool NO_INPUT;
|
public static bool NO_INPUT;
|
||||||
|
|
||||||
// Base UnityEngine.Input class
|
// If using new InputSystem module
|
||||||
private static Type Input => _input ?? (_input = ReflectionHelpers.GetTypeByName("UnityEngine.Input"));
|
public static bool USING_NEW_INPUT;
|
||||||
|
|
||||||
|
// Cached Types
|
||||||
|
private static Type TInput => _input ?? (_input = ReflectionHelpers.GetTypeByName("UnityEngine.Input"));
|
||||||
private static Type _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 PropertyInfo _mousePosition;
|
||||||
private static MethodInfo _getKey;
|
private static MethodInfo _getKey;
|
||||||
private static MethodInfo _getKeyDown;
|
private static MethodInfo _getKeyDown;
|
||||||
@ -31,49 +48,153 @@ namespace Explorer
|
|||||||
|
|
||||||
public static void Init()
|
public static void Init()
|
||||||
{
|
{
|
||||||
if (Input == null && !TryManuallyLoadInput())
|
if (TKeyboard != null || TryManuallyLoadNewInput())
|
||||||
{
|
{
|
||||||
NO_INPUT = true;
|
InitNewInput();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cache reflection now that we know Input is loaded
|
if (TInput != null || TryManuallyLoadLegacyInput())
|
||||||
|
{
|
||||||
|
InitLegacyInput();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
_mousePosition = Input.GetProperty("mousePosition");
|
ExplorerCore.LogWarning("Could not find any Input module!");
|
||||||
|
NO_INPUT = true;
|
||||||
_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) });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma warning disable IDE1006 // Camel-case property (Unity style)
|
private static void InitNewInput()
|
||||||
public static Vector3 mousePosition
|
{
|
||||||
|
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
|
get
|
||||||
{
|
{
|
||||||
if (NO_INPUT) return Vector3.zero;
|
if (NO_INPUT) return Vector3.zero;
|
||||||
return (Vector3)_mousePosition.GetValue(null);
|
|
||||||
|
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)
|
public static bool GetKeyDown(KeyCode key)
|
||||||
{
|
{
|
||||||
if (NO_INPUT) return false;
|
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 });
|
return (bool)_getKeyDown.Invoke(null, new object[] { key });
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool GetKey(KeyCode key)
|
public static bool GetKey(KeyCode key)
|
||||||
{
|
{
|
||||||
if (NO_INPUT) return false;
|
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 });
|
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)
|
public static bool GetMouseButtonDown(int btn)
|
||||||
{
|
{
|
||||||
if (NO_INPUT) return false;
|
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 });
|
return (bool)_getMouseButtonDown.Invoke(null, new object[] { btn });
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,24 +202,21 @@ namespace Explorer
|
|||||||
public static bool GetMouseButton(int btn)
|
public static bool GetMouseButton(int btn)
|
||||||
{
|
{
|
||||||
if (NO_INPUT) return false;
|
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 });
|
return (bool)_getMouseButton.Invoke(null, new object[] { btn });
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool TryManuallyLoadInput()
|
|
||||||
{
|
|
||||||
MelonLogger.Log("UnityEngine.Input is null, trying to load manually....");
|
|
||||||
|
|
||||||
if ((ReflectionHelpers.LoadModule("UnityEngine.InputLegacyModule.dll") || ReflectionHelpers.LoadModule("UnityEngine.CoreModule.dll"))
|
|
||||||
&& Input != null)
|
|
||||||
{
|
|
||||||
MelonLogger.Log("Ok!");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
MelonLogger.Log("Could not load Input module!");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,4 @@
|
|||||||
using System;
|
using UnityEngine;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer
|
||||||
{
|
{
|
||||||
@ -26,7 +21,7 @@ namespace Explorer
|
|||||||
CalculateMaxOffset();
|
CalculateMaxOffset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private int m_itemsPerPage = 20;
|
private int m_itemsPerPage = ModConfig.Instance.Default_Page_Limit;
|
||||||
|
|
||||||
public int ItemCount
|
public int ItemCount
|
||||||
{
|
{
|
||||||
@ -99,7 +94,7 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
GUILayout.Label("Limit: ", new GUILayoutOption[] { GUILayout.Width(50) });
|
GUILayout.Label("Limit: ", new GUILayoutOption[] { GUILayout.Width(50) });
|
||||||
var limit = this.ItemsPerPage.ToString();
|
var limit = this.ItemsPerPage.ToString();
|
||||||
limit = 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))
|
if (limit != ItemsPerPage.ToString() && int.TryParse(limit, out int i))
|
||||||
{
|
{
|
||||||
ItemsPerPage = i;
|
ItemsPerPage = i;
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using MelonLoader;
|
using System.Reflection;
|
||||||
using UnhollowerBaseLib;
|
|
||||||
using UnhollowerRuntimeLib;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using BF = System.Reflection.BindingFlags;
|
using BF = System.Reflection.BindingFlags;
|
||||||
|
|
||||||
|
#if CPP
|
||||||
using ILType = Il2CppSystem.Type;
|
using ILType = Il2CppSystem.Type;
|
||||||
|
using UnhollowerBaseLib;
|
||||||
|
using UnhollowerRuntimeLib;
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer
|
||||||
{
|
{
|
||||||
@ -17,31 +18,43 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
public static BF CommonFlags = BF.Public | BF.Instance | BF.NonPublic | BF.Static;
|
public static BF CommonFlags = BF.Public | BF.Instance | BF.NonPublic | BF.Static;
|
||||||
|
|
||||||
public static ILType GameObjectType => Il2CppType.Of<GameObject>();
|
#if CPP
|
||||||
public static ILType TransformType => Il2CppType.Of<Transform>();
|
public static ILType GameObjectType => Il2CppType.Of<GameObject>();
|
||||||
public static ILType ObjectType => Il2CppType.Of<UnityEngine.Object>();
|
public static ILType TransformType => Il2CppType.Of<Transform>();
|
||||||
public static ILType ComponentType => Il2CppType.Of<Component>();
|
public static ILType ObjectType => Il2CppType.Of<UnityEngine.Object>();
|
||||||
public static ILType BehaviourType => Il2CppType.Of<Behaviour>();
|
public static ILType ComponentType => Il2CppType.Of<Component>();
|
||||||
|
public static ILType BehaviourType => Il2CppType.Of<Behaviour>();
|
||||||
|
|
||||||
private static readonly MethodInfo m_tryCastMethodInfo = typeof(Il2CppObjectBase).GetMethod("TryCast");
|
private static readonly MethodInfo tryCastMethodInfo = typeof(Il2CppObjectBase).GetMethod("TryCast");
|
||||||
|
private static readonly Dictionary<Type, MethodInfo> cachedTryCastMethods = new Dictionary<Type, MethodInfo>();
|
||||||
|
|
||||||
public static object Il2CppCast(object obj, Type castTo)
|
public static object Il2CppCast(object obj, Type castTo)
|
||||||
{
|
{
|
||||||
if (!typeof(Il2CppSystem.Object).IsAssignableFrom(castTo)) return obj;
|
if (!typeof(Il2CppSystem.Object).IsAssignableFrom(castTo)) return obj;
|
||||||
|
|
||||||
return m_tryCastMethodInfo
|
if (!cachedTryCastMethods.ContainsKey(castTo))
|
||||||
.MakeGenericMethod(castTo)
|
{
|
||||||
.Invoke(obj, null);
|
cachedTryCastMethods.Add(castTo, tryCastMethodInfo.MakeGenericMethod(castTo));
|
||||||
|
}
|
||||||
|
|
||||||
|
return cachedTryCastMethods[castTo].Invoke(obj, null);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
public static Type GameObjectType => typeof(GameObject);
|
||||||
|
public static Type TransformType => typeof(Transform);
|
||||||
|
public static Type ObjectType => typeof(UnityEngine.Object);
|
||||||
|
public static Type ComponentType => typeof(Component);
|
||||||
|
public static Type BehaviourType => typeof(Behaviour);
|
||||||
|
#endif
|
||||||
|
|
||||||
public static bool IsEnumerable(Type t)
|
public static bool IsEnumerable(Type t)
|
||||||
{
|
{
|
||||||
return typeof(IEnumerable).IsAssignableFrom(t) || IsCppEnumerable(t);
|
if (typeof(IEnumerable).IsAssignableFrom(t))
|
||||||
}
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// Checks for Il2Cpp List or HashSet.
|
#if CPP
|
||||||
public static bool IsCppEnumerable(Type t)
|
|
||||||
{
|
|
||||||
if (t.IsGenericType && t.GetGenericTypeDefinition() is Type g)
|
if (t.IsGenericType && t.GetGenericTypeDefinition() is Type g)
|
||||||
{
|
{
|
||||||
return typeof(Il2CppSystem.Collections.Generic.List<>).IsAssignableFrom(g)
|
return typeof(Il2CppSystem.Collections.Generic.List<>).IsAssignableFrom(g)
|
||||||
@ -52,6 +65,9 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
return typeof(Il2CppSystem.Collections.IList).IsAssignableFrom(t);
|
return typeof(Il2CppSystem.Collections.IList).IsAssignableFrom(t);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool IsDictionary(Type t)
|
public static bool IsDictionary(Type t)
|
||||||
@ -61,6 +77,7 @@ namespace Explorer
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if CPP
|
||||||
if (t.IsGenericType && t.GetGenericTypeDefinition() is Type g)
|
if (t.IsGenericType && t.GetGenericTypeDefinition() is Type g)
|
||||||
{
|
{
|
||||||
return typeof(Il2CppSystem.Collections.Generic.Dictionary<,>).IsAssignableFrom(g)
|
return typeof(Il2CppSystem.Collections.Generic.Dictionary<,>).IsAssignableFrom(g)
|
||||||
@ -71,6 +88,9 @@ namespace Explorer
|
|||||||
return typeof(Il2CppSystem.Collections.IDictionary).IsAssignableFrom(t)
|
return typeof(Il2CppSystem.Collections.IDictionary).IsAssignableFrom(t)
|
||||||
|| typeof(Il2CppSystem.Collections.Hashtable).IsAssignableFrom(t);
|
|| typeof(Il2CppSystem.Collections.Hashtable).IsAssignableFrom(t);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Type GetTypeByName(string fullName)
|
public static Type GetTypeByName(string fullName)
|
||||||
@ -93,6 +113,7 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
if (obj == null) return null;
|
if (obj == null) return null;
|
||||||
|
|
||||||
|
#if CPP
|
||||||
// Need to use GetIl2CppType for Il2CppSystem Objects
|
// Need to use GetIl2CppType for Il2CppSystem Objects
|
||||||
if (obj is Il2CppSystem.Object ilObject)
|
if (obj is Il2CppSystem.Object ilObject)
|
||||||
{
|
{
|
||||||
@ -104,6 +125,7 @@ namespace Explorer
|
|||||||
|
|
||||||
return Type.GetType(ilObject.GetIl2CppType().AssemblyQualifiedName) ?? obj.GetType();
|
return Type.GetType(ilObject.GetIl2CppType().AssemblyQualifiedName) ?? obj.GetType();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// It's a normal object, this is fine
|
// It's a normal object, this is fine
|
||||||
return obj.GetType();
|
return obj.GetType();
|
||||||
@ -126,7 +148,12 @@ namespace Explorer
|
|||||||
|
|
||||||
public static bool LoadModule(string module)
|
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;
|
if (!File.Exists(path)) return false;
|
||||||
|
|
||||||
try
|
try
|
||||||
@ -136,13 +163,15 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
MelonLogger.Log(e.GetType() + ", " + e.Message);
|
ExplorerCore.Log(e.GetType() + ", " + e.Message);
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string ExceptionToString(Exception e)
|
public static string ExceptionToString(Exception e)
|
||||||
{
|
{
|
||||||
|
#if CPP
|
||||||
if (IsFailedGeneric(e))
|
if (IsFailedGeneric(e))
|
||||||
{
|
{
|
||||||
return "Unable to initialize this type.";
|
return "Unable to initialize this type.";
|
||||||
@ -151,10 +180,11 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
return "Garbage collected in Il2Cpp.";
|
return "Garbage collected in Il2Cpp.";
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
return e.GetType() + ", " + e.Message;
|
return e.GetType() + ", " + e.Message;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if CPP
|
||||||
public static bool IsFailedGeneric(Exception e)
|
public static bool IsFailedGeneric(Exception e)
|
||||||
{
|
{
|
||||||
return IsExceptionOfType(e, typeof(TargetInvocationException)) && IsExceptionOfType(e, typeof(TypeLoadException));
|
return IsExceptionOfType(e, typeof(TargetInvocationException)) && IsExceptionOfType(e, typeof(TypeLoadException));
|
||||||
@ -181,5 +211,6 @@ namespace Explorer
|
|||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,4 @@
|
|||||||
using System;
|
using UnityEngine;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer
|
||||||
{
|
{
|
||||||
|
@ -1,12 +1,10 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
#if ML
|
||||||
using Harmony;
|
using Harmony;
|
||||||
using MelonLoader;
|
#else
|
||||||
using System.Reflection;
|
using HarmonyLib;
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer
|
||||||
{
|
{
|
||||||
@ -22,7 +20,7 @@ namespace Explorer
|
|||||||
private static bool m_lastVisibleState;
|
private static bool m_lastVisibleState;
|
||||||
private static bool m_currentlySettingCursor = false;
|
private static bool m_currentlySettingCursor = false;
|
||||||
|
|
||||||
public static bool ShouldForceMouse => CppExplorer.ShowMenu && ForceUnlockMouse;
|
public static bool ShouldForceMouse => ExplorerCore.ShowMenu && ForceUnlockMouse;
|
||||||
|
|
||||||
private static Type CursorType => m_cursorType ?? (m_cursorType = ReflectionHelpers.GetTypeByName("UnityEngine.Cursor"));
|
private static Type CursorType => m_cursorType ?? (m_cursorType = ReflectionHelpers.GetTypeByName("UnityEngine.Cursor"));
|
||||||
private static Type m_cursorType;
|
private static Type m_cursorType;
|
||||||
@ -34,11 +32,11 @@ namespace Explorer
|
|||||||
// Check if Cursor class is loaded
|
// Check if Cursor class is loaded
|
||||||
if (CursorType == null)
|
if (CursorType == null)
|
||||||
{
|
{
|
||||||
MelonLogger.Log("Trying to manually load Cursor module...");
|
ExplorerCore.Log("Trying to manually load Cursor module...");
|
||||||
|
|
||||||
if (ReflectionHelpers.LoadModule("UnityEngine.CoreModule") && CursorType != null)
|
if (ReflectionHelpers.LoadModule("UnityEngine.CoreModule") && CursorType != null)
|
||||||
{
|
{
|
||||||
MelonLogger.Log("Ok!");
|
ExplorerCore.Log("Ok!");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -59,12 +57,12 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
MelonLogger.Log($"Exception on CursorControl.Init! {e.GetType()}, {e.Message}");
|
ExplorerCore.Log($"Exception on CursorControl.Init! {e.GetType()}, {e.Message}");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable ShowMenu and ForceUnlockMouse
|
// Enable ShowMenu and ForceUnlockMouse
|
||||||
// (set m_showMenu directly to not call UpdateCursorState twice)
|
// (set m_showMenu directly to not call UpdateCursorState twice)
|
||||||
CppExplorer.m_showMenu = true;
|
ExplorerCore.m_showMenu = true;
|
||||||
ForceUnlockMouse = true;
|
ForceUnlockMouse = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,7 +70,16 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var harmony = CppExplorer.Instance.harmonyInstance;
|
// var harmony = ExplorerCore.Instance.harmonyInstance;
|
||||||
|
|
||||||
|
var harmony =
|
||||||
|
#if ML
|
||||||
|
ExplorerMelonMod.Instance.harmonyInstance;
|
||||||
|
#else
|
||||||
|
ExplorerBepInPlugin.HarmonyInstance;
|
||||||
|
#endif
|
||||||
|
;
|
||||||
|
|
||||||
var prop = typeof(Cursor).GetProperty(property);
|
var prop = typeof(Cursor).GetProperty(property);
|
||||||
|
|
||||||
if (setter)
|
if (setter)
|
||||||
@ -88,7 +95,7 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
MelonLogger.Log($"[NON-FATAL] Couldn't patch a method: {e.Message}");
|
ExplorerCore.Log($"[NON-FATAL] Couldn't patch a method: {e.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,7 +133,7 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
MelonLogger.Log($"Exception setting Cursor state: {e.GetType()}, {e.Message}");
|
ExplorerCore.Log($"Exception setting Cursor state: {e.GetType()}, {e.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,9 +1,4 @@
|
|||||||
using System;
|
using UnityEngine;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer
|
||||||
{
|
{
|
||||||
@ -15,7 +10,7 @@ namespace Explorer
|
|||||||
|
|
||||||
public static void Update()
|
public static void Update()
|
||||||
{
|
{
|
||||||
if (CppExplorer.ShowMenu)
|
if (ExplorerCore.ShowMenu)
|
||||||
{
|
{
|
||||||
if (InputHelper.GetKey(KeyCode.LeftShift) && InputHelper.GetMouseButtonDown(1))
|
if (InputHelper.GetKey(KeyCode.LeftShift) && InputHelper.GetMouseButtonDown(1))
|
||||||
{
|
{
|
||||||
@ -38,7 +33,7 @@ namespace Explorer
|
|||||||
if (!UnityHelpers.MainCamera)
|
if (!UnityHelpers.MainCamera)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var ray = UnityHelpers.MainCamera.ScreenPointToRay(InputHelper.mousePosition);
|
var ray = UnityHelpers.MainCamera.ScreenPointToRay(InputHelper.MousePosition);
|
||||||
|
|
||||||
if (Physics.Raycast(ray, out RaycastHit hit, 1000f))
|
if (Physics.Raycast(ray, out RaycastHit hit, 1000f))
|
||||||
{
|
{
|
||||||
@ -66,7 +61,7 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
if (m_objUnderMouseName != "")
|
if (m_objUnderMouseName != "")
|
||||||
{
|
{
|
||||||
var pos = InputHelper.mousePosition;
|
var pos = InputHelper.MousePosition;
|
||||||
var rect = new Rect(
|
var rect = new Rect(
|
||||||
pos.x - (Screen.width / 2), // x
|
pos.x - (Screen.width / 2), // x
|
||||||
Screen.height - pos.y - 50, // y
|
Screen.height - pos.y - 50, // y
|
||||||
|
@ -3,7 +3,6 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using MelonLoader;
|
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer
|
||||||
{
|
{
|
||||||
@ -18,16 +17,20 @@ namespace Explorer
|
|||||||
Pages.Add(new ScenePage());
|
Pages.Add(new ScenePage());
|
||||||
Pages.Add(new SearchPage());
|
Pages.Add(new SearchPage());
|
||||||
Pages.Add(new ConsolePage());
|
Pages.Add(new ConsolePage());
|
||||||
|
Pages.Add(new OptionsPage());
|
||||||
|
|
||||||
for (int i = 0; i < Pages.Count; i++)
|
for (int i = 0; i < Pages.Count; i++)
|
||||||
{
|
{
|
||||||
var page = Pages[i];
|
var page = Pages[i];
|
||||||
page.Init();
|
page.Init();
|
||||||
|
|
||||||
|
// If page failed to init, it will remove itself from the list. Lower the iterate counter.
|
||||||
|
if (!Pages.Contains(page)) i--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public const int MainWindowID = 5000;
|
public const int MainWindowID = 5000;
|
||||||
public static Rect MainRect = new Rect(5,5, ModConfig.Instance.Default_Window_Size.x,ModConfig.Instance.Default_Window_Size.y);
|
public static Rect MainRect = new Rect(5, 5, ModConfig.Instance.Default_Window_Size.x, ModConfig.Instance.Default_Window_Size.y);
|
||||||
|
|
||||||
public static readonly List<WindowPage> Pages = new List<WindowPage>();
|
public static readonly List<WindowPage> Pages = new List<WindowPage>();
|
||||||
private static int m_currentPage = 0;
|
private static int m_currentPage = 0;
|
||||||
@ -36,11 +39,11 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
if (index < 0 || Pages.Count <= index)
|
if (index < 0 || Pages.Count <= index)
|
||||||
{
|
{
|
||||||
MelonLogger.Log("cannot set page " + index);
|
ExplorerCore.Log("cannot set page " + index);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_currentPage = index;
|
m_currentPage = index;
|
||||||
GUI.BringWindowToFront(MainWindowID);
|
GUIUnstrip.BringWindowToFront(MainWindowID);
|
||||||
GUI.FocusWindow(MainWindowID);
|
GUI.FocusWindow(MainWindowID);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,16 +54,16 @@ namespace Explorer
|
|||||||
|
|
||||||
public void OnGUI()
|
public void OnGUI()
|
||||||
{
|
{
|
||||||
MainRect = GUI.Window(MainWindowID, MainRect, (GUI.WindowFunction)MainWindow, CppExplorer.NAME);
|
MainRect = GUIUnstrip.Window(MainWindowID, MainRect, (GUI.WindowFunction)MainWindow, ExplorerCore.NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void MainWindow(int id)
|
private void MainWindow(int id)
|
||||||
{
|
{
|
||||||
GUI.DragWindow(new Rect(0, 0, MainRect.width - 90, 20));
|
GUI.DragWindow(new Rect(0, 0, MainRect.width - 90, 20));
|
||||||
|
|
||||||
if (GUI.Button(new Rect(MainRect.width - 90, 2, 80, 20), $"Hide ({ModConfig.Instance.Main_Menu_Toggle})"))
|
if (GUIUnstrip.Button(new Rect(MainRect.width - 90, 2, 80, 20), $"Hide ({ModConfig.Instance.Main_Menu_Toggle})"))
|
||||||
{
|
{
|
||||||
CppExplorer.ShowMenu = false;
|
ExplorerCore.ShowMenu = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,7 +86,7 @@ namespace Explorer
|
|||||||
|
|
||||||
private void MainHeader()
|
private void MainHeader()
|
||||||
{
|
{
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
for (int i = 0; i < Pages.Count; i++)
|
for (int i = 0; i < Pages.Count; i++)
|
||||||
{
|
{
|
||||||
if (m_currentPage == i)
|
if (m_currentPage == i)
|
||||||
@ -91,22 +94,22 @@ namespace Explorer
|
|||||||
else
|
else
|
||||||
GUI.color = Color.white;
|
GUI.color = Color.white;
|
||||||
|
|
||||||
if (GUILayout.Button(Pages[i].Name, null))
|
if (GUILayout.Button(Pages[i].Name, new GUILayoutOption[0]))
|
||||||
{
|
{
|
||||||
m_currentPage = i;
|
m_currentPage = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUI.color = Color.white;
|
GUI.color = Color.white;
|
||||||
InspectUnderMouse.EnableInspect = GUILayout.Toggle(InspectUnderMouse.EnableInspect, "Inspect Under Mouse (Shift + RMB)", null);
|
InspectUnderMouse.EnableInspect = GUILayout.Toggle(InspectUnderMouse.EnableInspect, "Inspect Under Mouse (Shift + RMB)", new GUILayoutOption[0]);
|
||||||
|
|
||||||
bool mouseState = CursorControl.ForceUnlockMouse;
|
bool mouseState = CursorControl.ForceUnlockMouse;
|
||||||
bool setMouse = GUILayout.Toggle(mouseState, "Force Unlock Mouse (Left Alt)", null);
|
bool setMouse = GUILayout.Toggle(mouseState, "Force Unlock Mouse (Left Alt)", new GUILayoutOption[0]);
|
||||||
if (setMouse != mouseState) CursorControl.ForceUnlockMouse = setMouse;
|
if (setMouse != mouseState) CursorControl.ForceUnlockMouse = setMouse;
|
||||||
|
|
||||||
WindowManager.TabView = GUILayout.Toggle(WindowManager.TabView, "Tab View", null);
|
WindowManager.TabView = GUILayout.Toggle(WindowManager.TabView, "Tab View", new GUILayoutOption[0]);
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
//GUIUnstrip.Space(10);
|
//GUIUnstrip.Space(10);
|
||||||
|
@ -1,9 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Text;
|
|
||||||
using Mono.CSharp;
|
using Mono.CSharp;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using Attribute = System.Attribute;
|
using Attribute = System.Attribute;
|
||||||
|
@ -1,15 +1,14 @@
|
|||||||
using System.Collections;
|
using System;
|
||||||
//using Il2CppSystem;
|
|
||||||
using MelonLoader;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using System;
|
|
||||||
using Object = UnityEngine.Object;
|
using Object = UnityEngine.Object;
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer
|
||||||
{
|
{
|
||||||
public class ReplHelper : MonoBehaviour
|
public class ReplHelper : MonoBehaviour
|
||||||
{
|
{
|
||||||
|
#if CPP
|
||||||
public ReplHelper(IntPtr intPtr) : base(intPtr) { }
|
public ReplHelper(IntPtr intPtr) : base(intPtr) { }
|
||||||
|
#endif
|
||||||
|
|
||||||
public T Find<T>() where T : Object
|
public T Find<T>() where T : Object
|
||||||
{
|
{
|
||||||
|
@ -1,14 +1,10 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using UnityEngine;
|
|
||||||
using System.Reflection;
|
|
||||||
using Mono.CSharp;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using MelonLoader;
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
using Mono.CSharp;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer
|
||||||
{
|
{
|
||||||
@ -34,20 +30,28 @@ namespace Explorer
|
|||||||
"System.Collections",
|
"System.Collections",
|
||||||
"System.Collections.Generic",
|
"System.Collections.Generic",
|
||||||
"System.Reflection",
|
"System.Reflection",
|
||||||
|
#if ML
|
||||||
"MelonLoader"
|
"MelonLoader"
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
public override void Init()
|
public override void Init()
|
||||||
{
|
{
|
||||||
|
#if CPP
|
||||||
UnhollowerRuntimeLib.ClassInjector.RegisterTypeInIl2Cpp<ReplHelper>();
|
UnhollowerRuntimeLib.ClassInjector.RegisterTypeInIl2Cpp<ReplHelper>();
|
||||||
|
#endif
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
MethodInput = @"// This is a basic C# REPL console.
|
MethodInput = @"// This is a basic C# console.
|
||||||
// Some common using directives are added by default, you can add more below.
|
// Some common using directives are added by default, you can add more below.
|
||||||
// If you want to return some output, MelonLogger.Log() it.
|
// If you want to return some output, Debug.Log() or MelonLogger.Log() it.
|
||||||
|
"
|
||||||
MelonLogger.Log(""hello world"");";
|
#if ML
|
||||||
|
+ @"MelonLogger.Log(""hello world"");";
|
||||||
|
#else
|
||||||
|
+ @"Debug.Log(""hello world"");";
|
||||||
|
#endif
|
||||||
|
;
|
||||||
|
|
||||||
ResetConsole();
|
ResetConsole();
|
||||||
|
|
||||||
@ -58,7 +62,7 @@ MelonLogger.Log(""hello world"");";
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
MelonLogger.Log($"Error setting up console!\r\nMessage: {e.Message}");
|
ExplorerCore.Log($"Error setting up console!\r\nMessage: {e.Message}");
|
||||||
MainMenu.SetCurrentPage(0);
|
MainMenu.SetCurrentPage(0);
|
||||||
MainMenu.Pages.Remove(this);
|
MainMenu.Pages.Remove(this);
|
||||||
}
|
}
|
||||||
@ -113,7 +117,7 @@ MelonLogger.Log(""hello world"");";
|
|||||||
{
|
{
|
||||||
if (!suppressWarning)
|
if (!suppressWarning)
|
||||||
{
|
{
|
||||||
MelonLogger.LogWarning(e.GetType() + ", " + e.Message);
|
ExplorerCore.LogWarning(e.GetType() + ", " + e.Message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,19 +127,19 @@ MelonLogger.Log(""hello world"");";
|
|||||||
|
|
||||||
public override void DrawWindow()
|
public override void DrawWindow()
|
||||||
{
|
{
|
||||||
GUILayout.Label("<b><size=15><color=cyan>C# REPL Console</color></size></b>", null);
|
GUILayout.Label("<b><size=15><color=cyan>C# Console</color></size></b>", new GUILayoutOption[0]);
|
||||||
|
|
||||||
GUI.skin.label.alignment = TextAnchor.UpperLeft;
|
GUI.skin.label.alignment = TextAnchor.UpperLeft;
|
||||||
|
|
||||||
GUILayout.Label("Enter code here as though it is a method body:", null);
|
GUILayout.Label("Enter code here as though it is a method body:", new GUILayoutOption[0]);
|
||||||
|
|
||||||
inputAreaScroll = GUIUnstrip.BeginScrollView(inputAreaScroll, new GUILayoutOption[] { GUILayout.Height(250) });
|
inputAreaScroll = GUIUnstrip.BeginScrollView(inputAreaScroll, new GUILayoutOption[] { GUILayout.Height(250) });
|
||||||
|
|
||||||
MethodInput = GUILayout.TextArea(MethodInput, new GUILayoutOption[] { GUILayout.ExpandHeight(true) });
|
MethodInput = GUIUnstrip.TextArea(MethodInput, new GUILayoutOption[] { GUILayout.ExpandHeight(true) });
|
||||||
|
|
||||||
GUIUnstrip.EndScrollView();
|
GUIUnstrip.EndScrollView();
|
||||||
|
|
||||||
if (GUILayout.Button("<color=cyan><b>Execute</b></color>", null))
|
if (GUILayout.Button("<color=cyan><b>Execute</b></color>", new GUILayoutOption[0]))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -147,21 +151,21 @@ MelonLogger.Log(""hello world"");";
|
|||||||
|
|
||||||
if (result != null && !Equals(result, VoidType.Value))
|
if (result != null && !Equals(result, VoidType.Value))
|
||||||
{
|
{
|
||||||
MelonLogger.Log("[Console Output]\r\n" + result.ToString());
|
ExplorerCore.Log("[Console Output]\r\n" + result.ToString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
MelonLogger.LogError("Exception compiling!\r\nMessage: " + e.Message + "\r\nStack: " + e.StackTrace);
|
ExplorerCore.LogError("Exception compiling!\r\nMessage: " + e.Message + "\r\nStack: " + e.StackTrace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GUILayout.Label("<b>Using directives:</b>", null);
|
GUILayout.Label("<b>Using directives:</b>", new GUILayoutOption[0]);
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUILayout.Label("Add namespace:", new GUILayoutOption[] { GUILayout.Width(105) });
|
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) }))
|
if (GUILayout.Button("<b><color=lime>Add</color></b>", new GUILayoutOption[] { GUILayout.Width(120) }))
|
||||||
{
|
{
|
||||||
AddUsing(UsingInput);
|
AddUsing(UsingInput);
|
||||||
@ -174,7 +178,7 @@ MelonLogger.Log(""hello world"");";
|
|||||||
|
|
||||||
foreach (var asm in UsingDirectives)
|
foreach (var asm in UsingDirectives)
|
||||||
{
|
{
|
||||||
GUILayout.Label(AsmToUsing(asm, true), null);
|
GUILayout.Label(AsmToUsing(asm, true), new GUILayoutOption[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
99
src/Menu/MainMenu/Pages/OptionsPage.cs
Normal file
99
src/Menu/MainMenu/Pages/OptionsPage.cs
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using Explorer.Tests;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Explorer
|
||||||
|
{
|
||||||
|
public class OptionsPage : WindowPage
|
||||||
|
{
|
||||||
|
public override string Name => "Options";
|
||||||
|
|
||||||
|
public string toggleKeyInputString = "";
|
||||||
|
public Vector2 defaultSizeInputVector;
|
||||||
|
public int defaultPageLimit;
|
||||||
|
|
||||||
|
private CacheObjectBase toggleKeyInput;
|
||||||
|
private CacheObjectBase defaultSizeInput;
|
||||||
|
private CacheObjectBase defaultPageLimitInput;
|
||||||
|
|
||||||
|
public override void Init()
|
||||||
|
{
|
||||||
|
toggleKeyInputString = ModConfig.Instance.Main_Menu_Toggle.ToString();
|
||||||
|
toggleKeyInput = CacheFactory.GetTypeAndCacheObject(typeof(OptionsPage).GetField("toggleKeyInputString"), this);
|
||||||
|
|
||||||
|
defaultSizeInputVector = ModConfig.Instance.Default_Window_Size;
|
||||||
|
defaultSizeInput = CacheFactory.GetTypeAndCacheObject(typeof(OptionsPage).GetField("defaultSizeInputVector"), this);
|
||||||
|
|
||||||
|
defaultPageLimit = ModConfig.Instance.Default_Page_Limit;
|
||||||
|
defaultPageLimitInput = CacheFactory.GetTypeAndCacheObject(typeof(OptionsPage).GetField("defaultPageLimit"), this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Update() { }
|
||||||
|
|
||||||
|
public override void DrawWindow()
|
||||||
|
{
|
||||||
|
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
|
||||||
|
GUILayout.Label("<color=orange><size=16><b>Settings</b></size></color>", new GUILayoutOption[0]);
|
||||||
|
GUI.skin.label.alignment = TextAnchor.MiddleLeft;
|
||||||
|
|
||||||
|
GUILayout.BeginVertical(GUIContent.none, GUI.skin.box, new GUILayoutOption[0]);
|
||||||
|
|
||||||
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
|
GUILayout.Label($"Menu Toggle Key:", new GUILayoutOption[] { GUILayout.Width(215f) });
|
||||||
|
toggleKeyInput.DrawValue(MainMenu.MainRect, MainMenu.MainRect.width - 215f);
|
||||||
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
|
GUILayout.Label($"Default Window Size:", new GUILayoutOption[] { GUILayout.Width(215f) });
|
||||||
|
defaultSizeInput.DrawValue(MainMenu.MainRect, MainMenu.MainRect.width - 215f);
|
||||||
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
|
GUILayout.Label($"Default Items per Page:", new GUILayoutOption[] { GUILayout.Width(215f) });
|
||||||
|
defaultPageLimitInput.DrawValue(MainMenu.MainRect, MainMenu.MainRect.width - 215f);
|
||||||
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
|
if (GUILayout.Button("<color=lime><b>Apply and Save</b></color>", new GUILayoutOption[0]))
|
||||||
|
{
|
||||||
|
ApplyAndSave();
|
||||||
|
}
|
||||||
|
|
||||||
|
GUILayout.EndVertical();
|
||||||
|
|
||||||
|
//GUIUnstrip.Space(10f);
|
||||||
|
|
||||||
|
//GUI.skin.label.alignment = TextAnchor.MiddleCenter;
|
||||||
|
//GUILayout.Label("<color=orange><size=16><b>Other</b></size></color>", new GUILayoutOption[0]);
|
||||||
|
//GUI.skin.label.alignment = TextAnchor.MiddleLeft;
|
||||||
|
|
||||||
|
//GUILayout.BeginVertical(GUIContent.none, GUI.skin.box, new GUILayoutOption[0]);
|
||||||
|
|
||||||
|
//if (GUILayout.Button("Inspect Test Class", new GUILayoutOption[0]))
|
||||||
|
//{
|
||||||
|
// WindowManager.InspectObject(TestClass.Instance, out bool _);
|
||||||
|
//}
|
||||||
|
|
||||||
|
//GUILayout.EndVertical();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ApplyAndSave()
|
||||||
|
{
|
||||||
|
if (Enum.Parse(typeof(KeyCode), toggleKeyInputString) is KeyCode key)
|
||||||
|
{
|
||||||
|
ModConfig.Instance.Main_Menu_Toggle = key;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ExplorerCore.LogWarning($"Could not parse '{toggleKeyInputString}' to KeyCode!");
|
||||||
|
}
|
||||||
|
|
||||||
|
ModConfig.Instance.Default_Window_Size = defaultSizeInputVector;
|
||||||
|
ModConfig.Instance.Default_Page_Limit = defaultPageLimit;
|
||||||
|
|
||||||
|
ModConfig.SaveSettings();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,8 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
|
||||||
using MelonLoader;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.SceneManagement;
|
using UnityEngine.SceneManagement;
|
||||||
|
|
||||||
@ -12,7 +10,7 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
public static ScenePage Instance;
|
public static ScenePage Instance;
|
||||||
|
|
||||||
public override string Name { get => "Scene Explorer"; }
|
public override string Name { get => "Scenes"; }
|
||||||
|
|
||||||
public PageHelper Pages = new PageHelper();
|
public PageHelper Pages = new PageHelper();
|
||||||
|
|
||||||
@ -88,7 +86,11 @@ namespace Explorer
|
|||||||
|
|
||||||
foreach (var obj in Resources.FindObjectsOfTypeAll(ReflectionHelpers.GameObjectType))
|
foreach (var obj in Resources.FindObjectsOfTypeAll(ReflectionHelpers.GameObjectType))
|
||||||
{
|
{
|
||||||
|
#if CPP
|
||||||
var go = obj.TryCast<GameObject>();
|
var go = obj.TryCast<GameObject>();
|
||||||
|
#else
|
||||||
|
var go = obj as GameObject;
|
||||||
|
#endif
|
||||||
if (go.name.ToLower().Contains(_search.ToLower()) && go.scene.name == m_currentScene)
|
if (go.name.ToLower().Contains(_search.ToLower()) && go.scene.name == m_currentScene)
|
||||||
{
|
{
|
||||||
matches.Add(new GameObjectCache(go));
|
matches.Add(new GameObjectCache(go));
|
||||||
@ -126,14 +128,22 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var scene = SceneManager.GetSceneByName(m_currentScene);
|
for (int i = 0; i < SceneManager.sceneCount; i++)
|
||||||
|
{
|
||||||
|
var scene = SceneManager.GetSceneAt(i);
|
||||||
|
|
||||||
allTransforms.AddRange(scene.GetRootGameObjects()
|
if (scene.name == m_currentScene)
|
||||||
.Select(it => it.transform));
|
{
|
||||||
|
allTransforms.AddRange(scene.GetRootGameObjects()
|
||||||
|
.Select(it => it.transform));
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
MelonLogger.Log("Exception getting root scene objects, falling back to backup method...");
|
ExplorerCore.Log("Exception getting root scene objects, falling back to backup method...");
|
||||||
|
|
||||||
m_getRootObjectsFailed = true;
|
m_getRootObjectsFailed = true;
|
||||||
allTransforms.AddRange(GetRootObjectsManual_Impl());
|
allTransforms.AddRange(GetRootObjectsManual_Impl());
|
||||||
@ -175,7 +185,11 @@ namespace Explorer
|
|||||||
var list = new List<Transform>();
|
var list = new List<Transform>();
|
||||||
foreach (var obj in array)
|
foreach (var obj in array)
|
||||||
{
|
{
|
||||||
|
#if CPP
|
||||||
var transform = obj.TryCast<Transform>();
|
var transform = obj.TryCast<Transform>();
|
||||||
|
#else
|
||||||
|
var transform = obj as Transform;
|
||||||
|
#endif
|
||||||
if (transform.parent == null && transform.gameObject.scene.name == m_currentScene)
|
if (transform.parent == null && transform.gameObject.scene.name == m_currentScene)
|
||||||
{
|
{
|
||||||
list.Add(transform);
|
list.Add(transform);
|
||||||
@ -185,7 +199,7 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
MelonLogger.Log("Exception getting root scene objects (manual): "
|
ExplorerCore.Log("Exception getting root scene objects (manual): "
|
||||||
+ e.GetType() + ", " + e.Message + "\r\n"
|
+ e.GetType() + ", " + e.Message + "\r\n"
|
||||||
+ e.StackTrace);
|
+ e.StackTrace);
|
||||||
return new Transform[0];
|
return new Transform[0];
|
||||||
@ -200,7 +214,7 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
DrawHeaderArea();
|
DrawHeaderArea();
|
||||||
|
|
||||||
GUILayout.BeginVertical(GUI.skin.box, null);
|
GUILayout.BeginVertical(GUIContent.none, GUI.skin.box, null);
|
||||||
|
|
||||||
DrawPageButtons();
|
DrawPageButtons();
|
||||||
|
|
||||||
@ -215,28 +229,31 @@ namespace Explorer
|
|||||||
|
|
||||||
GUILayout.EndVertical();
|
GUILayout.EndVertical();
|
||||||
}
|
}
|
||||||
catch
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
// supress
|
if (!e.Message.Contains("in a group with only"))
|
||||||
|
{
|
||||||
|
ExplorerCore.Log(e.ToString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawHeaderArea()
|
private void DrawHeaderArea()
|
||||||
{
|
{
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
|
|
||||||
// Current Scene label
|
// Current Scene label
|
||||||
GUILayout.Label("Current Scene:", new GUILayoutOption[] { GUILayout.Width(120) });
|
GUILayout.Label("Current Scene:", new GUILayoutOption[] { GUILayout.Width(120) });
|
||||||
SceneChangeButtons();
|
SceneChangeButtons();
|
||||||
GUILayout.Label("<color=cyan>" + m_currentScene + "</color>", null); //new GUILayoutOption[] { GUILayout.Width(250) });
|
GUILayout.Label("<color=cyan>" + m_currentScene + "</color>", new GUILayoutOption[0]);
|
||||||
|
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
// ----- GameObject Search -----
|
// ----- GameObject Search -----
|
||||||
GUILayout.BeginHorizontal(GUI.skin.box, null);
|
GUILayout.BeginHorizontal(GUIContent.none, GUI.skin.box, null);
|
||||||
GUILayout.Label("<b>Search Scene:</b>", new GUILayoutOption[] { GUILayout.Width(100) });
|
GUILayout.Label("<b>Search Scene:</b>", new GUILayoutOption[] { GUILayout.Width(100) });
|
||||||
|
|
||||||
m_searchInput = GUILayout.TextField(m_searchInput, null);
|
m_searchInput = GUIUnstrip.TextField(m_searchInput, new GUILayoutOption[0]);
|
||||||
|
|
||||||
if (GUILayout.Button("Search", new GUILayoutOption[] { GUILayout.Width(80) }))
|
if (GUILayout.Button("Search", new GUILayoutOption[] { GUILayout.Width(80) }))
|
||||||
{
|
{
|
||||||
@ -249,8 +266,14 @@ namespace Explorer
|
|||||||
|
|
||||||
private void SceneChangeButtons()
|
private void SceneChangeButtons()
|
||||||
{
|
{
|
||||||
// Need to do 'ToList()' so the object isn't cleaned up by Il2Cpp GC.
|
var scenes = new List<Scene>();
|
||||||
var scenes = SceneManager.GetAllScenes().ToList();
|
var names = new List<string>();
|
||||||
|
for (int i = 0; i < SceneManager.sceneCount; i++)
|
||||||
|
{
|
||||||
|
var scene = SceneManager.GetSceneAt(i);
|
||||||
|
names.Add(scene.name);
|
||||||
|
scenes.Add(scene);
|
||||||
|
}
|
||||||
|
|
||||||
if (scenes.Count > 1)
|
if (scenes.Count > 1)
|
||||||
{
|
{
|
||||||
@ -265,7 +288,7 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
if (changeWanted != 0)
|
if (changeWanted != 0)
|
||||||
{
|
{
|
||||||
int index = scenes.IndexOf(SceneManager.GetSceneByName(m_currentScene));
|
int index = names.IndexOf(m_currentScene);
|
||||||
index += changeWanted;
|
index += changeWanted;
|
||||||
if (index > scenes.Count - 1)
|
if (index > scenes.Count - 1)
|
||||||
{
|
{
|
||||||
@ -282,7 +305,7 @@ namespace Explorer
|
|||||||
|
|
||||||
private void DrawPageButtons()
|
private void DrawPageButtons()
|
||||||
{
|
{
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
|
|
||||||
Pages.DrawLimitInputArea();
|
Pages.DrawLimitInputArea();
|
||||||
|
|
||||||
@ -313,7 +336,7 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
if (m_currentTransform != null)
|
if (m_currentTransform != null)
|
||||||
{
|
{
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
if (GUILayout.Button("<-", new GUILayoutOption[] { GUILayout.Width(35) }))
|
if (GUILayout.Button("<-", new GUILayoutOption[] { GUILayout.Width(35) }))
|
||||||
{
|
{
|
||||||
TraverseUp();
|
TraverseUp();
|
||||||
@ -330,11 +353,11 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GUILayout.Label("Scene Root GameObjects:", null);
|
GUILayout.Label("Scene Root GameObjects:", new GUILayoutOption[0]);
|
||||||
|
|
||||||
if (m_getRootObjectsFailed)
|
if (m_getRootObjectsFailed)
|
||||||
{
|
{
|
||||||
if (GUILayout.Button("Update Root Object List (auto-update failed!)", null))
|
if (GUILayout.Button("Update Root Object List (auto-update failed!)", new GUILayoutOption[0]))
|
||||||
{
|
{
|
||||||
Update_Impl(true);
|
Update_Impl(true);
|
||||||
}
|
}
|
||||||
@ -359,7 +382,7 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
|
|
||||||
label += "</i></color>";
|
label += "</i></color>";
|
||||||
GUILayout.Label(label, null);
|
GUILayout.Label(label, new GUILayoutOption[0]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -382,7 +405,7 @@ namespace Explorer
|
|||||||
CancelSearch();
|
CancelSearch();
|
||||||
}
|
}
|
||||||
|
|
||||||
GUILayout.Label("Search Results:", null);
|
GUILayout.Label("Search Results:", new GUILayoutOption[0]);
|
||||||
|
|
||||||
if (m_searchResults.Count > 0)
|
if (m_searchResults.Count > 0)
|
||||||
{
|
{
|
||||||
@ -404,13 +427,13 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GUILayout.Label("<i><color=red>Null or destroyed!</color></i>", null);
|
GUILayout.Label("<i><color=red>Null or destroyed!</color></i>", new GUILayoutOption[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GUILayout.Label("<color=red><i>No results found!</i></color>", null);
|
GUILayout.Label("<color=red><i>No results found!</i></color>", new GUILayoutOption[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,10 +2,8 @@
|
|||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
|
||||||
using UnityEngine;
|
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using MelonLoader;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer
|
||||||
{
|
{
|
||||||
@ -66,12 +64,19 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
var toCache = obj;
|
var toCache = obj;
|
||||||
|
|
||||||
|
#if CPP
|
||||||
if (toCache is Il2CppSystem.Object ilObject)
|
if (toCache is Il2CppSystem.Object ilObject)
|
||||||
{
|
{
|
||||||
toCache = ilObject.TryCast<GameObject>() ?? ilObject.TryCast<Transform>()?.gameObject ?? ilObject;
|
toCache = ilObject.TryCast<GameObject>() ?? ilObject.TryCast<Transform>()?.gameObject ?? ilObject;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
if (toCache is GameObject || toCache is Transform)
|
||||||
|
{
|
||||||
|
toCache = toCache as GameObject ?? (toCache as Transform).gameObject;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
var cache = CacheObjectBase.GetCacheObject(toCache);
|
var cache = CacheFactory.GetTypeAndCacheObject(toCache);
|
||||||
m_searchResults.Add(cache);
|
m_searchResults.Add(cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,7 +89,7 @@ namespace Explorer
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
// helpers
|
// helpers
|
||||||
GUILayout.BeginHorizontal(GUI.skin.box, null);
|
GUILayout.BeginHorizontal(GUIContent.none, GUI.skin.box, null);
|
||||||
GUILayout.Label("<b><color=orange>Helpers</color></b>", new GUILayoutOption[] { GUILayout.Width(70) });
|
GUILayout.Label("<b><color=orange>Helpers</color></b>", new GUILayoutOption[] { GUILayout.Width(70) });
|
||||||
if (GUILayout.Button("Find Static Instances", new GUILayoutOption[] { GUILayout.Width(180) }))
|
if (GUILayout.Button("Find Static Instances", new GUILayoutOption[] { GUILayout.Width(180) }))
|
||||||
{
|
{
|
||||||
@ -97,15 +102,15 @@ namespace Explorer
|
|||||||
SearchBox();
|
SearchBox();
|
||||||
|
|
||||||
// results
|
// results
|
||||||
GUILayout.BeginVertical(GUI.skin.box, null);
|
GUILayout.BeginVertical(GUIContent.none, GUI.skin.box, null);
|
||||||
|
|
||||||
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
|
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
|
||||||
GUILayout.Label("<b><color=orange>Results </color></b>" + " (" + m_searchResults.Count + ")", null);
|
GUILayout.Label("<b><color=orange>Results </color></b>" + " (" + m_searchResults.Count + ")", new GUILayoutOption[0]);
|
||||||
GUI.skin.label.alignment = TextAnchor.UpperLeft;
|
GUI.skin.label.alignment = TextAnchor.UpperLeft;
|
||||||
|
|
||||||
int count = m_searchResults.Count;
|
int count = m_searchResults.Count;
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
|
|
||||||
Pages.DrawLimitInputArea();
|
Pages.DrawLimitInputArea();
|
||||||
|
|
||||||
@ -146,7 +151,7 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GUILayout.Label("<color=red><i>No results found!</i></color>", null);
|
GUILayout.Label("<color=red><i>No results found!</i></color>", new GUILayoutOption[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
GUIUnstrip.EndScrollView();
|
GUIUnstrip.EndScrollView();
|
||||||
@ -160,21 +165,21 @@ namespace Explorer
|
|||||||
|
|
||||||
private void SearchBox()
|
private void SearchBox()
|
||||||
{
|
{
|
||||||
GUILayout.BeginVertical(GUI.skin.box, null);
|
GUILayout.BeginVertical(GUIContent.none, GUI.skin.box, null);
|
||||||
|
|
||||||
// ----- GameObject Search -----
|
// ----- GameObject Search -----
|
||||||
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
|
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
|
||||||
GUILayout.Label("<b><color=orange>Search</color></b>", null);
|
GUILayout.Label("<b><color=orange>Search</color></b>", new GUILayoutOption[0]);
|
||||||
GUI.skin.label.alignment = TextAnchor.UpperLeft;
|
GUI.skin.label.alignment = TextAnchor.UpperLeft;
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
|
|
||||||
GUILayout.Label("Name Contains:", new GUILayoutOption[] { GUILayout.Width(100) });
|
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();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
|
|
||||||
GUILayout.Label("Class Filter:", new GUILayoutOption[] { GUILayout.Width(100) });
|
GUILayout.Label("Class Filter:", new GUILayoutOption[] { GUILayout.Width(100) });
|
||||||
ClassFilterToggle(TypeFilter.Object, "Object");
|
ClassFilterToggle(TypeFilter.Object, "Object");
|
||||||
@ -184,15 +189,15 @@ namespace Explorer
|
|||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
if (TypeMode == TypeFilter.Custom)
|
if (TypeMode == TypeFilter.Custom)
|
||||||
{
|
{
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUI.skin.label.alignment = TextAnchor.MiddleRight;
|
GUI.skin.label.alignment = TextAnchor.MiddleRight;
|
||||||
GUILayout.Label("Custom Class:", new GUILayoutOption[] { GUILayout.Width(250) });
|
GUILayout.Label("Custom Class:", new GUILayoutOption[] { GUILayout.Width(250) });
|
||||||
GUI.skin.label.alignment = TextAnchor.UpperLeft;
|
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();
|
GUILayout.EndHorizontal();
|
||||||
}
|
}
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUILayout.Label("Scene Filter:", new GUILayoutOption[] { GUILayout.Width(100) });
|
GUILayout.Label("Scene Filter:", new GUILayoutOption[] { GUILayout.Width(100) });
|
||||||
SceneFilterToggle(SceneFilter.Any, "Any", 60);
|
SceneFilterToggle(SceneFilter.Any, "Any", 60);
|
||||||
SceneFilterToggle(SceneFilter.This, "This Scene", 100);
|
SceneFilterToggle(SceneFilter.This, "This Scene", 100);
|
||||||
@ -200,7 +205,7 @@ namespace Explorer
|
|||||||
SceneFilterToggle(SceneFilter.None, "No Scene", 80);
|
SceneFilterToggle(SceneFilter.None, "No Scene", 80);
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
if (GUILayout.Button("<b><color=cyan>Search</color></b>", null))
|
if (GUILayout.Button("<b><color=cyan>Search</color></b>", new GUILayoutOption[0]))
|
||||||
{
|
{
|
||||||
Search();
|
Search();
|
||||||
}
|
}
|
||||||
@ -255,15 +260,23 @@ namespace Explorer
|
|||||||
|
|
||||||
private List<object> FindAllObjectsOfType(string searchQuery, string typeName)
|
private List<object> FindAllObjectsOfType(string searchQuery, string typeName)
|
||||||
{
|
{
|
||||||
|
#if CPP
|
||||||
Il2CppSystem.Type searchType = null;
|
Il2CppSystem.Type searchType = null;
|
||||||
|
|
||||||
|
#else
|
||||||
|
Type searchType = null;
|
||||||
|
#endif
|
||||||
if (TypeMode == TypeFilter.Custom)
|
if (TypeMode == TypeFilter.Custom)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (ReflectionHelpers.GetTypeByName(typeName) is Type t)
|
if (ReflectionHelpers.GetTypeByName(typeName) is Type t)
|
||||||
{
|
{
|
||||||
|
#if CPP
|
||||||
searchType = Il2CppSystem.Type.GetType(t.AssemblyQualifiedName);
|
searchType = Il2CppSystem.Type.GetType(t.AssemblyQualifiedName);
|
||||||
|
#else
|
||||||
|
searchType = t;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -272,7 +285,7 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
MelonLogger.Log("Exception getting Search Type: " + e.GetType() + ", " + e.Message);
|
ExplorerCore.Log("Exception getting Search Type: " + e.GetType() + ", " + e.Message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (TypeMode == TypeFilter.Object)
|
else if (TypeMode == TypeFilter.Object)
|
||||||
@ -292,7 +305,7 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
if (searchType != null)
|
if (searchType != null)
|
||||||
{
|
{
|
||||||
MelonLogger.LogWarning("Your Custom Class Type must inherit from UnityEngine.Object!");
|
ExplorerCore.LogWarning("Your Custom Class Type must inherit from UnityEngine.Object!");
|
||||||
}
|
}
|
||||||
return new List<object>();
|
return new List<object>();
|
||||||
}
|
}
|
||||||
@ -301,7 +314,7 @@ namespace Explorer
|
|||||||
|
|
||||||
var allObjectsOfType = Resources.FindObjectsOfTypeAll(searchType);
|
var allObjectsOfType = Resources.FindObjectsOfTypeAll(searchType);
|
||||||
|
|
||||||
//MelonLogger.Log("Found count: " + allObjectsOfType.Length);
|
//ExplorerCore.Log("Found count: " + allObjectsOfType.Length);
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
foreach (var obj in allObjectsOfType)
|
foreach (var obj in allObjectsOfType)
|
||||||
@ -314,7 +327,11 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (searchType.FullName == ReflectionHelpers.ComponentType.FullName
|
if (searchType.FullName == ReflectionHelpers.ComponentType.FullName
|
||||||
|
#if CPP
|
||||||
&& ReflectionHelpers.TransformType.IsAssignableFrom(obj.GetIl2CppType()))
|
&& ReflectionHelpers.TransformType.IsAssignableFrom(obj.GetIl2CppType()))
|
||||||
|
#else
|
||||||
|
&& ReflectionHelpers.TransformType.IsAssignableFrom(obj.GetType()))
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
// Transforms shouldn't really be counted as Components, skip them.
|
// Transforms shouldn't really be counted as Components, skip them.
|
||||||
// They're more akin to GameObjects.
|
// They're more akin to GameObjects.
|
||||||
@ -339,15 +356,18 @@ namespace Explorer
|
|||||||
|
|
||||||
public static bool FilterScene(object obj, SceneFilter filter)
|
public static bool FilterScene(object obj, SceneFilter filter)
|
||||||
{
|
{
|
||||||
GameObject go;
|
GameObject go = null;
|
||||||
|
#if CPP
|
||||||
if (obj is Il2CppSystem.Object ilObject)
|
if (obj is Il2CppSystem.Object ilObject)
|
||||||
{
|
{
|
||||||
go = ilObject.TryCast<GameObject>() ?? ilObject.TryCast<Component>().gameObject;
|
go = ilObject.TryCast<GameObject>() ?? ilObject.TryCast<Component>().gameObject;
|
||||||
}
|
}
|
||||||
else
|
#else
|
||||||
|
if (obj is GameObject || obj is Component)
|
||||||
{
|
{
|
||||||
go = (obj as GameObject) ?? (obj as Component).gameObject;
|
go = (obj as GameObject) ?? (obj as Component).gameObject;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!go)
|
if (!go)
|
||||||
{
|
{
|
||||||
@ -405,7 +425,7 @@ namespace Explorer
|
|||||||
|
|
||||||
if (pi != null)
|
if (pi != null)
|
||||||
{
|
{
|
||||||
obj = pi.GetValue(null);
|
obj = pi.GetValue(null, null);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1,9 +1,4 @@
|
|||||||
using System;
|
using UnityEngine;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer
|
||||||
{
|
{
|
||||||
|
@ -1,17 +1,16 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
#if CPP
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using UnityEngine;
|
|
||||||
using MelonLoader;
|
|
||||||
using UnhollowerBaseLib;
|
using UnhollowerBaseLib;
|
||||||
|
#endif
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer
|
||||||
{
|
{
|
||||||
public class ResizeDrag
|
public class ResizeDrag
|
||||||
{
|
{
|
||||||
|
#if CPP
|
||||||
private static bool RESIZE_FAILED = false;
|
private static bool RESIZE_FAILED = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
private static readonly GUIContent gcDrag = new GUIContent("<-- Drag to resize -->");
|
private static readonly GUIContent gcDrag = new GUIContent("<-- Drag to resize -->");
|
||||||
private static bool isResizing = false;
|
private static bool isResizing = false;
|
||||||
@ -20,25 +19,30 @@ namespace Explorer
|
|||||||
|
|
||||||
public static Rect ResizeWindow(Rect _rect, int ID)
|
public static Rect ResizeWindow(Rect _rect, int ID)
|
||||||
{
|
{
|
||||||
|
#if CPP
|
||||||
if (!RESIZE_FAILED)
|
if (!RESIZE_FAILED)
|
||||||
{
|
{
|
||||||
var origRect = _rect;
|
var origRect = _rect;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
GUILayout.BeginHorizontal(GUI.skin.box, null);
|
GUILayout.BeginHorizontal(GUIContent.none, GUI.skin.box, null);
|
||||||
|
|
||||||
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
|
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
|
||||||
|
#if ML
|
||||||
GUILayout.Button(gcDrag, GUI.skin.label, new GUILayoutOption[] { GUILayout.Height(15) });
|
GUILayout.Button(gcDrag, GUI.skin.label, new GUILayoutOption[] { GUILayout.Height(15) });
|
||||||
|
#else
|
||||||
|
GUILayout.Button(gcDrag.ToString(), new GUILayoutOption[] { GUILayout.Height(15) });
|
||||||
|
#endif
|
||||||
|
|
||||||
//var r = GUILayoutUtility.GetLastRect();
|
//var r = GUILayoutUtility.GetLastRect();
|
||||||
var r = LayoutUtilityUnstrip.GetLastRect();
|
var r = Internal_LayoutUtility.GetLastRect();
|
||||||
|
|
||||||
var mousePos = InputHelper.mousePosition;
|
var mousePos = InputHelper.MousePosition;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var mouse = GUIUtility.ScreenToGUIPoint(new Vector2(mousePos.x, Screen.height - mousePos.y));
|
var mouse = GUIUnstrip.ScreenToGUIPoint(new Vector2(mousePos.x, Screen.height - mousePos.y));
|
||||||
if (r.Contains(mouse) && InputHelper.GetMouseButtonDown(0))
|
if (r.Contains(mouse) && InputHelper.GetMouseButtonDown(0))
|
||||||
{
|
{
|
||||||
isResizing = true;
|
isResizing = true;
|
||||||
@ -66,7 +70,7 @@ namespace Explorer
|
|||||||
|
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
}
|
}
|
||||||
catch (Il2CppException e) when (e.Message.StartsWith("System.ArgumentException"))
|
catch (Exception e) when (e.Message.StartsWith("System.ArgumentException"))
|
||||||
{
|
{
|
||||||
// suppress
|
// suppress
|
||||||
return origRect;
|
return origRect;
|
||||||
@ -74,8 +78,8 @@ namespace Explorer
|
|||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
RESIZE_FAILED = true;
|
RESIZE_FAILED = true;
|
||||||
MelonLogger.Log("Exception on GuiResize: " + e.GetType() + ", " + e.Message);
|
ExplorerCore.Log("Exception on GuiResize: " + e.GetType() + ", " + e.Message);
|
||||||
//MelonLogger.Log(e.StackTrace);
|
//ExplorerCore.Log(e.StackTrace);
|
||||||
return origRect;
|
return origRect;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,7 +87,7 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GUILayout.BeginHorizontal(GUI.skin.box, null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
|
|
||||||
GUILayout.Label("Resize window:", new GUILayoutOption[] { GUILayout.Width(100) });
|
GUILayout.Label("Resize window:", new GUILayoutOption[] { GUILayout.Width(100) });
|
||||||
|
|
||||||
@ -111,6 +115,43 @@ namespace Explorer
|
|||||||
GUI.skin.label.alignment = TextAnchor.UpperLeft;
|
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
|
||||||
|
GUI.skin.label.alignment = TextAnchor.MiddleLeft;
|
||||||
|
|
||||||
return _rect;
|
return _rect;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Reflection;
|
|
||||||
using UnhollowerRuntimeLib;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using Object = UnityEngine.Object;
|
using Object = UnityEngine.Object;
|
||||||
|
|
||||||
@ -62,13 +56,13 @@ namespace Explorer
|
|||||||
|
|
||||||
if (!obj)
|
if (!obj)
|
||||||
{
|
{
|
||||||
GUILayout.Label("<i><color=red>null</color></i>", null);
|
GUILayout.Label("<i><color=red>null</color></i>", new GUILayoutOption[0]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------ toggle active button ------
|
// ------ toggle active button ------
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUI.skin.button.alignment = TextAnchor.UpperLeft;
|
GUI.skin.button.alignment = TextAnchor.UpperLeft;
|
||||||
|
|
||||||
GUI.color = activeColor;
|
GUI.color = activeColor;
|
||||||
@ -108,7 +102,7 @@ namespace Explorer
|
|||||||
|
|
||||||
public static void SmallInspectButton(object obj)
|
public static void SmallInspectButton(object obj)
|
||||||
{
|
{
|
||||||
if (GUILayout.Button("Inspect", null))
|
if (GUILayout.Button("Inspect", new GUILayoutOption[0]))
|
||||||
{
|
{
|
||||||
WindowManager.InspectObject(obj, out bool _);
|
WindowManager.InspectObject(obj, out bool _);
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,29 @@
|
|||||||
using System;
|
using UnityEngine;
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Text;
|
|
||||||
using UnityEngine;
|
|
||||||
using Object = UnityEngine.Object;
|
using Object = UnityEngine.Object;
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer
|
||||||
{
|
{
|
||||||
public class UIStyles
|
public class UIStyles
|
||||||
{
|
{
|
||||||
|
public class Syntax
|
||||||
|
{
|
||||||
|
public const string Field_Static = "#8d8dc6";
|
||||||
|
public const string Field_Instance = "#c266ff";
|
||||||
|
|
||||||
|
public const string Method_Static = "#b55b02";
|
||||||
|
public const string Method_Instance = "#ff8000";
|
||||||
|
|
||||||
|
public const string Prop_Static = "#588075";
|
||||||
|
public const string Prop_Instance = "#55a38e";
|
||||||
|
|
||||||
|
public const string Class_Static = "#3a8d71";
|
||||||
|
public const string Class_Instance = "#2df7b2";
|
||||||
|
|
||||||
|
public const string Local = "#a6e9e9";
|
||||||
|
|
||||||
|
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);
|
public static Color LightGreen = new Color(Color.green.r - 0.3f, Color.green.g - 0.3f, Color.green.b - 0.3f);
|
||||||
|
|
||||||
public static GUISkin WindowSkin
|
public static GUISkin WindowSkin
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using MelonLoader;
|
|
||||||
using UnhollowerRuntimeLib;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.SceneManagement;
|
|
||||||
|
#if CPP
|
||||||
|
using UnhollowerRuntimeLib;
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer
|
||||||
{
|
{
|
||||||
@ -63,7 +62,7 @@ namespace Explorer
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
MelonLogger.Log("Error: Target is null or not a GameObject/Transform!");
|
ExplorerCore.Log("Error: Target is null or not a GameObject/Transform!");
|
||||||
DestroyWindow();
|
DestroyWindow();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -106,7 +105,7 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
if (Target == null)
|
if (Target == null)
|
||||||
{
|
{
|
||||||
MelonLogger.Log("Target is null!");
|
ExplorerCore.Log("Target is null!");
|
||||||
DestroyWindow();
|
DestroyWindow();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -114,7 +113,7 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
if (!uObj)
|
if (!uObj)
|
||||||
{
|
{
|
||||||
MelonLogger.Log("Target was destroyed!");
|
ExplorerCore.Log("Target was destroyed!");
|
||||||
DestroyWindow();
|
DestroyWindow();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -152,10 +151,13 @@ namespace Explorer
|
|||||||
ChildPages.ItemCount = m_children.Length;
|
ChildPages.ItemCount = m_children.Length;
|
||||||
|
|
||||||
// update components
|
// update components
|
||||||
|
#if CPP
|
||||||
var compList = new Il2CppSystem.Collections.Generic.List<Component>();
|
var compList = new Il2CppSystem.Collections.Generic.List<Component>();
|
||||||
TargetGO.GetComponentsInternal(ReflectionHelpers.ComponentType, true, false, true, false, compList);
|
TargetGO.GetComponentsInternal(ReflectionHelpers.ComponentType, true, false, true, false, compList);
|
||||||
|
|
||||||
m_components = compList.ToArray();
|
m_components = compList.ToArray();
|
||||||
|
#else
|
||||||
|
m_components = TargetGO.GetComponents<Component>();
|
||||||
|
#endif
|
||||||
|
|
||||||
CompPages.ItemCount = m_components.Length;
|
CompPages.ItemCount = m_components.Length;
|
||||||
}
|
}
|
||||||
@ -167,7 +169,7 @@ namespace Explorer
|
|||||||
|
|
||||||
private void DestroyOnException(Exception e)
|
private void DestroyOnException(Exception e)
|
||||||
{
|
{
|
||||||
MelonLogger.Log($"Exception drawing GameObject Window: {e.GetType()}, {e.Message}");
|
ExplorerCore.Log($"Exception drawing GameObject Window: {e.GetType()}, {e.Message}");
|
||||||
DestroyWindow();
|
DestroyWindow();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,8 +184,12 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if CPP
|
||||||
private void ReflectObject(Il2CppSystem.Object obj)
|
private void ReflectObject(Il2CppSystem.Object obj)
|
||||||
{
|
#else
|
||||||
|
private void ReflectObject(object obj)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
var window = WindowManager.InspectObject(obj, out bool created, true);
|
var window = WindowManager.InspectObject(obj, out bool created, true);
|
||||||
|
|
||||||
if (created)
|
if (created)
|
||||||
@ -217,8 +223,8 @@ namespace Explorer
|
|||||||
|
|
||||||
scroll = GUIUnstrip.BeginScrollView(scroll);
|
scroll = GUIUnstrip.BeginScrollView(scroll);
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUILayout.Label("Scene: <color=cyan>" + (m_scene == "" ? "n/a" : m_scene) + "</color>", null);
|
GUILayout.Label("Scene: <color=cyan>" + (m_scene == "" ? "n/a" : m_scene) + "</color>", new GUILayoutOption[0]);
|
||||||
if (m_scene == UnityHelpers.ActiveSceneName)
|
if (m_scene == UnityHelpers.ActiveSceneName)
|
||||||
{
|
{
|
||||||
if (GUILayout.Button("<color=#00FF00>Send to Scene View</color>", new GUILayoutOption[] { GUILayout.Width(150) }))
|
if (GUILayout.Button("<color=#00FF00>Send to Scene View</color>", new GUILayoutOption[] { GUILayout.Width(150) }))
|
||||||
@ -233,7 +239,7 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUILayout.Label("Path:", new GUILayoutOption[] { GUILayout.Width(50) });
|
GUILayout.Label("Path:", new GUILayoutOption[] { GUILayout.Width(50) });
|
||||||
string pathlabel = TargetGO.transform.GetGameObjectPath();
|
string pathlabel = TargetGO.transform.GetGameObjectPath();
|
||||||
if (TargetGO.transform.parent != null)
|
if (TargetGO.transform.parent != null)
|
||||||
@ -243,16 +249,16 @@ namespace Explorer
|
|||||||
InspectGameObject(TargetGO.transform.parent);
|
InspectGameObject(TargetGO.transform.parent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
GUILayout.TextArea(pathlabel, null);
|
GUIUnstrip.TextArea(pathlabel, new GUILayoutOption[0]);
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUILayout.Label("Name:", new GUILayoutOption[] { GUILayout.Width(50) });
|
GUILayout.Label("Name:", new GUILayoutOption[] { GUILayout.Width(50) });
|
||||||
GUILayout.TextArea(m_name, null);
|
GUIUnstrip.TextArea(m_name, new GUILayoutOption[0]);
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
// --- Horizontal Columns section ---
|
// --- Horizontal Columns section ---
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
|
|
||||||
GUILayout.BeginVertical(new GUILayoutOption[] { GUILayout.Width(rect.width / 2 - 17) });
|
GUILayout.BeginVertical(new GUILayoutOption[] { GUILayout.Width(rect.width / 2 - 17) });
|
||||||
TransformList(rect);
|
TransformList(rect);
|
||||||
@ -283,12 +289,12 @@ namespace Explorer
|
|||||||
|
|
||||||
private void TransformList(Rect m_rect)
|
private void TransformList(Rect m_rect)
|
||||||
{
|
{
|
||||||
GUILayout.BeginVertical(GUI.skin.box, null);
|
GUILayout.BeginVertical(GUIContent.none, GUI.skin.box, null);
|
||||||
m_transformScroll = GUIUnstrip.BeginScrollView(m_transformScroll);
|
m_transformScroll = GUIUnstrip.BeginScrollView(m_transformScroll);
|
||||||
|
|
||||||
GUILayout.Label("<b><size=15>Children</size></b>", null);
|
GUILayout.Label("<b><size=15>Children</size></b>", new GUILayoutOption[0]);
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
ChildPages.DrawLimitInputArea();
|
ChildPages.DrawLimitInputArea();
|
||||||
|
|
||||||
if (ChildPages.ItemCount > ChildPages.ItemsPerPage)
|
if (ChildPages.ItemCount > ChildPages.ItemsPerPage)
|
||||||
@ -296,7 +302,7 @@ namespace Explorer
|
|||||||
ChildPages.CurrentPageLabel();
|
ChildPages.CurrentPageLabel();
|
||||||
|
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
|
|
||||||
if (GUILayout.Button("< Prev", new GUILayoutOption[] { GUILayout.Width(80) }))
|
if (GUILayout.Button("< Prev", new GUILayoutOption[] { GUILayout.Width(80) }))
|
||||||
{
|
{
|
||||||
@ -319,7 +325,7 @@ namespace Explorer
|
|||||||
|
|
||||||
if (!obj)
|
if (!obj)
|
||||||
{
|
{
|
||||||
GUILayout.Label("null", null);
|
GUILayout.Label("null", new GUILayoutOption[0]);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -328,7 +334,7 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GUILayout.Label("<i>None</i>", null);
|
GUILayout.Label("<i>None</i>", new GUILayoutOption[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
GUIUnstrip.EndScrollView();
|
GUIUnstrip.EndScrollView();
|
||||||
@ -337,11 +343,11 @@ namespace Explorer
|
|||||||
|
|
||||||
private void ComponentList(Rect m_rect)
|
private void ComponentList(Rect m_rect)
|
||||||
{
|
{
|
||||||
GUILayout.BeginVertical(GUI.skin.box, null);
|
GUILayout.BeginVertical(GUIContent.none, GUI.skin.box, null);
|
||||||
m_compScroll = GUIUnstrip.BeginScrollView(m_compScroll);
|
m_compScroll = GUIUnstrip.BeginScrollView(m_compScroll);
|
||||||
GUILayout.Label("<b><size=15>Components</size></b>", null);
|
GUILayout.Label("<b><size=15>Components</size></b>", new GUILayoutOption[0]);
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
CompPages.DrawLimitInputArea();
|
CompPages.DrawLimitInputArea();
|
||||||
|
|
||||||
if (CompPages.ItemCount > CompPages.ItemsPerPage)
|
if (CompPages.ItemCount > CompPages.ItemsPerPage)
|
||||||
@ -349,7 +355,7 @@ namespace Explorer
|
|||||||
CompPages.CurrentPageLabel();
|
CompPages.CurrentPageLabel();
|
||||||
|
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
|
|
||||||
if (GUILayout.Button("< Prev", new GUILayoutOption[] { GUILayout.Width(80) }))
|
if (GUILayout.Button("< Prev", new GUILayoutOption[] { GUILayout.Width(80) }))
|
||||||
{
|
{
|
||||||
@ -362,24 +368,29 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
m_addComponentInput = GUILayout.TextField(m_addComponentInput, new GUILayoutOption[] { GUILayout.Width(130) });
|
var width = m_rect.width / 2 - 135f;
|
||||||
if (GUILayout.Button("Add Comp", null))
|
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)
|
if (ReflectionHelpers.GetTypeByName(m_addComponentInput) is Type compType)
|
||||||
{
|
{
|
||||||
if (typeof(Component).IsAssignableFrom(compType))
|
if (typeof(Component).IsAssignableFrom(compType))
|
||||||
{
|
{
|
||||||
|
#if CPP
|
||||||
TargetGO.AddComponent(Il2CppType.From(compType));
|
TargetGO.AddComponent(Il2CppType.From(compType));
|
||||||
|
#else
|
||||||
|
TargetGO.AddComponent(compType);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
MelonLogger.LogWarning($"Type '{compType.Name}' is not assignable from Component!");
|
ExplorerCore.LogWarning($"Type '{compType.Name}' is not assignable from Component!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
MelonLogger.LogWarning($"Could not find a type by the name of '{m_addComponentInput}'!");
|
ExplorerCore.LogWarning($"Could not find a type by the name of '{m_addComponentInput}'!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
@ -400,18 +411,26 @@ namespace Explorer
|
|||||||
|
|
||||||
if (!component) continue;
|
if (!component) continue;
|
||||||
|
|
||||||
var ilType = component.GetIl2CppType();
|
var type =
|
||||||
|
#if CPP
|
||||||
GUILayout.BeginHorizontal(null);
|
component.GetIl2CppType();
|
||||||
if (ReflectionHelpers.BehaviourType.IsAssignableFrom(ilType))
|
#else
|
||||||
|
component.GetType();
|
||||||
|
#endif
|
||||||
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
|
if (ReflectionHelpers.BehaviourType.IsAssignableFrom(type))
|
||||||
{
|
{
|
||||||
|
#if CPP
|
||||||
BehaviourEnabledBtn(component.TryCast<Behaviour>());
|
BehaviourEnabledBtn(component.TryCast<Behaviour>());
|
||||||
|
#else
|
||||||
|
BehaviourEnabledBtn(component as Behaviour);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GUIUnstrip.Space(26);
|
GUIUnstrip.Space(26);
|
||||||
}
|
}
|
||||||
if (GUILayout.Button("<color=cyan>" + ilType.Name + "</color>", new GUILayoutOption[] { GUILayout.Width(m_rect.width / 2 - 100) }))
|
if (GUILayout.Button("<color=cyan>" + type.Name + "</color>", new GUILayoutOption[] { GUILayout.Width(m_rect.width / 2 - 100) }))
|
||||||
{
|
{
|
||||||
ReflectObject(component);
|
ReflectObject(component);
|
||||||
}
|
}
|
||||||
@ -465,7 +484,7 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
if (m_hideControls)
|
if (m_hideControls)
|
||||||
{
|
{
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUILayout.Label("<b><size=15>GameObject Controls</size></b>", new GUILayoutOption[] { GUILayout.Width(200) });
|
GUILayout.Label("<b><size=15>GameObject Controls</size></b>", new GUILayoutOption[] { GUILayout.Width(200) });
|
||||||
if (GUILayout.Button("^ Show ^", new GUILayoutOption[] { GUILayout.Width(75) }))
|
if (GUILayout.Button("^ Show ^", new GUILayoutOption[] { GUILayout.Width(75) }))
|
||||||
{
|
{
|
||||||
@ -476,9 +495,9 @@ namespace Explorer
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
GUILayout.BeginVertical(GUI.skin.box, new GUILayoutOption[] { GUILayout.Width(520) });
|
GUILayout.BeginVertical(GUIContent.none, GUI.skin.box, new GUILayoutOption[] { GUILayout.Width(520) });
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUILayout.Label("<b><size=15>GameObject Controls</size></b>", new GUILayoutOption[] { GUILayout.Width(200) });
|
GUILayout.Label("<b><size=15>GameObject Controls</size></b>", new GUILayoutOption[] { GUILayout.Width(200) });
|
||||||
if (GUILayout.Button("v Hide v", new GUILayoutOption[] { GUILayout.Width(75) }))
|
if (GUILayout.Button("v Hide v", new GUILayoutOption[] { GUILayout.Width(75) }))
|
||||||
{
|
{
|
||||||
@ -486,7 +505,7 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
bool m_active = TargetGO.activeSelf;
|
bool m_active = TargetGO.activeSelf;
|
||||||
m_active = GUILayout.Toggle(m_active, (m_active ? "<color=lime>Enabled " : "<color=red>Disabled") + "</color>",
|
m_active = GUILayout.Toggle(m_active, (m_active ? "<color=lime>Enabled " : "<color=red>Disabled") + "</color>",
|
||||||
new GUILayoutOption[] { GUILayout.Width(80) });
|
new GUILayoutOption[] { GUILayout.Width(80) });
|
||||||
@ -511,9 +530,9 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
|
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
|
|
||||||
m_setParentInput = GUILayout.TextField(m_setParentInput, null);
|
m_setParentInput = GUIUnstrip.TextField(m_setParentInput, new GUILayoutOption[0]);
|
||||||
if (GUILayout.Button("Set Parent", new GUILayoutOption[] { GUILayout.Width(80) }))
|
if (GUILayout.Button("Set Parent", new GUILayoutOption[] { GUILayout.Width(80) }))
|
||||||
{
|
{
|
||||||
if (GameObject.Find(m_setParentInput) is GameObject newparent)
|
if (GameObject.Find(m_setParentInput) is GameObject newparent)
|
||||||
@ -522,7 +541,7 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
MelonLogger.LogWarning($"Could not find gameobject '{m_setParentInput}'");
|
ExplorerCore.LogWarning($"Could not find gameobject '{m_setParentInput}'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -532,14 +551,14 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
GUILayout.BeginVertical(GUI.skin.box, null);
|
GUILayout.BeginVertical(GUIContent.none, GUI.skin.box, null);
|
||||||
|
|
||||||
m_cachedInput[0] = TranslateControl(TranslateType.Position, ref m_translateAmount, false);
|
m_cachedInput[0] = TranslateControl(TranslateType.Position, ref m_translateAmount, false);
|
||||||
m_cachedInput[1] = TranslateControl(TranslateType.Rotation, ref m_rotateAmount, true);
|
m_cachedInput[1] = TranslateControl(TranslateType.Rotation, ref m_rotateAmount, true);
|
||||||
m_cachedInput[2] = TranslateControl(TranslateType.Scale, ref m_scaleAmount, false);
|
m_cachedInput[2] = TranslateControl(TranslateType.Scale, ref m_scaleAmount, false);
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
if (GUILayout.Button("<color=lime>Apply to Transform</color>", null) || m_autoApplyTransform)
|
if (GUILayout.Button("<color=lime>Apply to Transform</color>", new GUILayoutOption[0]) || m_autoApplyTransform)
|
||||||
{
|
{
|
||||||
if (m_localContext)
|
if (m_localContext)
|
||||||
{
|
{
|
||||||
@ -558,19 +577,19 @@ namespace Explorer
|
|||||||
UpdateFreeze();
|
UpdateFreeze();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (GUILayout.Button("<color=lime>Update from Transform</color>", null) || m_autoUpdateTransform)
|
if (GUILayout.Button("<color=lime>Update from Transform</color>", new GUILayoutOption[0]) || m_autoUpdateTransform)
|
||||||
{
|
{
|
||||||
CacheTransformValues();
|
CacheTransformValues();
|
||||||
}
|
}
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
BoolToggle(ref m_autoApplyTransform, "Auto-apply to Transform?");
|
BoolToggle(ref m_autoApplyTransform, "Auto-apply to Transform?");
|
||||||
BoolToggle(ref m_autoUpdateTransform, "Auto-update from transform?");
|
BoolToggle(ref m_autoUpdateTransform, "Auto-update from transform?");
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
bool b = m_localContext;
|
bool b = m_localContext;
|
||||||
b = GUILayout.Toggle(b, "<color=" + (b ? "lime" : "red") + ">Use local transform values?</color>", null);
|
b = GUILayout.Toggle(b, "<color=" + (b ? "lime" : "orange") + ">Use local transform values?</color>", new GUILayoutOption[0]);
|
||||||
if (b != m_localContext)
|
if (b != m_localContext)
|
||||||
{
|
{
|
||||||
m_localContext = b;
|
m_localContext = b;
|
||||||
@ -611,10 +630,10 @@ namespace Explorer
|
|||||||
private void BoolToggle(ref bool value, string message)
|
private void BoolToggle(ref bool value, string message)
|
||||||
{
|
{
|
||||||
string lbl = "<color=";
|
string lbl = "<color=";
|
||||||
lbl += value ? "lime" : "red";
|
lbl += value ? "lime" : "orange";
|
||||||
lbl += $">{message}</color>";
|
lbl += $">{message}</color>";
|
||||||
|
|
||||||
value = GUILayout.Toggle(value, lbl, null);
|
value = GUILayout.Toggle(value, lbl, new GUILayoutOption[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum TranslateType
|
public enum TranslateType
|
||||||
@ -626,7 +645,7 @@ namespace Explorer
|
|||||||
|
|
||||||
private Vector3 TranslateControl(TranslateType mode, ref float amount, bool multByTime)
|
private Vector3 TranslateControl(TranslateType mode, ref float amount, bool multByTime)
|
||||||
{
|
{
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUILayout.Label($"<color=cyan><b>{(m_localContext ? "Local " : "")}{mode}</b></color>:",
|
GUILayout.Label($"<color=cyan><b>{(m_localContext ? "Local " : "")}{mode}</b></color>:",
|
||||||
new GUILayoutOption[] { GUILayout.Width(m_localContext ? 110 : 65) });
|
new GUILayoutOption[] { GUILayout.Width(m_localContext ? 110 : 65) });
|
||||||
|
|
||||||
@ -649,7 +668,7 @@ namespace Explorer
|
|||||||
|
|
||||||
Vector3 input = m_cachedInput[(int)mode];
|
Vector3 input = m_cachedInput[(int)mode];
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUI.skin.label.alignment = TextAnchor.MiddleRight;
|
GUI.skin.label.alignment = TextAnchor.MiddleRight;
|
||||||
|
|
||||||
GUILayout.Label("<color=cyan>X:</color>", new GUILayoutOption[] { GUILayout.Width(20) });
|
GUILayout.Label("<color=cyan>X:</color>", new GUILayoutOption[] { GUILayout.Width(20) });
|
||||||
@ -663,7 +682,7 @@ namespace Explorer
|
|||||||
|
|
||||||
GUILayout.Label("+/-:", new GUILayoutOption[] { GUILayout.Width(30) });
|
GUILayout.Label("+/-:", new GUILayoutOption[] { GUILayout.Width(30) });
|
||||||
var amountInput = amount.ToString("F3");
|
var amountInput = amount.ToString("F3");
|
||||||
amountInput = GUILayout.TextField(amountInput, new GUILayoutOption[] { GUILayout.Width(60) });
|
amountInput = GUIUnstrip.TextField(amountInput, new GUILayoutOption[] { GUILayout.Width(60) });
|
||||||
if (float.TryParse(amountInput, out float f))
|
if (float.TryParse(amountInput, out float f))
|
||||||
{
|
{
|
||||||
amount = f;
|
amount = f;
|
||||||
@ -678,7 +697,7 @@ namespace Explorer
|
|||||||
private void PlusMinusFloat(ref float f, float amount, bool multByTime)
|
private void PlusMinusFloat(ref float f, float amount, bool multByTime)
|
||||||
{
|
{
|
||||||
string s = f.ToString("F3");
|
string s = f.ToString("F3");
|
||||||
s = GUILayout.TextField(s, new GUILayoutOption[] { GUILayout.Width(60) });
|
s = GUIUnstrip.TextField(s, new GUILayoutOption[] { GUILayout.Width(60) });
|
||||||
if (float.TryParse(s, out float f2))
|
if (float.TryParse(s, out float f2))
|
||||||
{
|
{
|
||||||
f = f2;
|
f = f2;
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.CodeDom;
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using MelonLoader;
|
|
||||||
using UnhollowerBaseLib;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
#if CPP
|
||||||
|
using UnhollowerBaseLib;
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer
|
||||||
{
|
{
|
||||||
@ -54,6 +53,7 @@ namespace Explorer
|
|||||||
CacheMembers(ReflectionHelpers.GetAllBaseTypes(Target));
|
CacheMembers(ReflectionHelpers.GetAllBaseTypes(Target));
|
||||||
|
|
||||||
// cache the extra cast-caching
|
// cache the extra cast-caching
|
||||||
|
#if CPP
|
||||||
if (Target is Il2CppSystem.Object ilObject)
|
if (Target is Il2CppSystem.Object ilObject)
|
||||||
{
|
{
|
||||||
var unityObj = ilObject.TryCast<UnityEngine.Object>();
|
var unityObj = ilObject.TryCast<UnityEngine.Object>();
|
||||||
@ -68,6 +68,10 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
m_uObj = Target as UnityEngine.Object;
|
||||||
|
m_component = Target as Component;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Update()
|
public override void Update()
|
||||||
@ -136,13 +140,14 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
MelonLogger.Log($"Exception getting members for type: {declaringType.FullName}");
|
ExplorerCore.Log($"Exception getting members for type: {declaringType.FullName}");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
object target = Target;
|
object target = Target;
|
||||||
string exception = null;
|
string exception = null;
|
||||||
|
|
||||||
|
#if CPP
|
||||||
if (target is Il2CppSystem.Object ilObject)
|
if (target is Il2CppSystem.Object ilObject)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@ -154,6 +159,7 @@ namespace Explorer
|
|||||||
exception = ReflectionHelpers.ExceptionToString(e);
|
exception = ReflectionHelpers.ExceptionToString(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
foreach (var member in infos)
|
foreach (var member in infos)
|
||||||
{
|
{
|
||||||
@ -163,15 +169,13 @@ namespace Explorer
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
// check blacklisted members
|
// check blacklisted members
|
||||||
var name = member.DeclaringType.Name + "." + member.Name;
|
var sig = $"{member.DeclaringType.Name}.{member.Name}";
|
||||||
if (_typeAndMemberBlacklist.Any(it => it == name))
|
if (_typeAndMemberBlacklist.Any(it => it == sig))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (_methodStartsWithBlacklist.Any(it => member.Name.StartsWith(it)))
|
if (_methodStartsWithBlacklist.Any(it => member.Name.StartsWith(it)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// compare signature to already cached members
|
|
||||||
var signature = $"{member.DeclaringType.Name}.{member.Name}";
|
|
||||||
if (member is MethodInfo mi)
|
if (member is MethodInfo mi)
|
||||||
{
|
{
|
||||||
AppendParams(mi.GetParameters());
|
AppendParams(mi.GetParameters());
|
||||||
@ -183,35 +187,35 @@ namespace Explorer
|
|||||||
|
|
||||||
void AppendParams(ParameterInfo[] _args)
|
void AppendParams(ParameterInfo[] _args)
|
||||||
{
|
{
|
||||||
signature += " (";
|
sig += " (";
|
||||||
foreach (var param in _args)
|
foreach (var param in _args)
|
||||||
{
|
{
|
||||||
signature += $"{param.ParameterType.Name} {param.Name}, ";
|
sig += $"{param.ParameterType.Name} {param.Name}, ";
|
||||||
}
|
}
|
||||||
signature += ")";
|
sig += ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cachedSigs.Contains(signature))
|
if (cachedSigs.Contains(sig))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// MelonLogger.Log($"Trying to cache member {signature}...");
|
// ExplorerCore.Log($"Trying to cache member {signature}...");
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var cached = CacheObjectBase.GetCacheObject(member, target);
|
var cached = CacheFactory.GetTypeAndCacheObject(member, target);
|
||||||
if (cached != null)
|
if (cached != null)
|
||||||
{
|
{
|
||||||
cachedSigs.Add(signature);
|
cachedSigs.Add(sig);
|
||||||
list.Add(cached);
|
list.Add(cached);
|
||||||
cached.ReflectionException = exception;
|
cached.ReflectionException = exception;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
MelonLogger.LogWarning($"Exception caching member {signature}!");
|
ExplorerCore.LogWarning($"Exception caching member {sig}!");
|
||||||
MelonLogger.Log(e.ToString());
|
ExplorerCore.Log(e.ToString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -235,17 +239,17 @@ namespace Explorer
|
|||||||
GUIUnstrip.BeginArea(new Rect(5, 25, rect.width - 10, rect.height - 35), GUI.skin.box);
|
GUIUnstrip.BeginArea(new Rect(5, 25, rect.width - 10, rect.height - 35), GUI.skin.box);
|
||||||
}
|
}
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUILayout.Label("<b>Type:</b> <color=cyan>" + TargetType.FullName + "</color>", new GUILayoutOption[] { GUILayout.Width(245f) });
|
GUILayout.Label("<b>Type:</b> <color=cyan>" + TargetType.FullName + "</color>", new GUILayoutOption[] { GUILayout.Width(245f) });
|
||||||
if (m_uObj)
|
if (m_uObj)
|
||||||
{
|
{
|
||||||
GUILayout.Label("Name: " + m_uObj.name, null);
|
GUILayout.Label("Name: " + m_uObj.name, new GUILayoutOption[0]);
|
||||||
}
|
}
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
if (m_uObj)
|
if (m_uObj)
|
||||||
{
|
{
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUILayout.Label("<b>Tools:</b>", new GUILayoutOption[] { GUILayout.Width(80) });
|
GUILayout.Label("<b>Tools:</b>", new GUILayoutOption[] { GUILayout.Width(80) });
|
||||||
UIHelpers.InstantiateButton(m_uObj);
|
UIHelpers.InstantiateButton(m_uObj);
|
||||||
if (m_component && m_component.gameObject is GameObject obj)
|
if (m_component && m_component.gameObject is GameObject obj)
|
||||||
@ -266,12 +270,12 @@ namespace Explorer
|
|||||||
|
|
||||||
UIStyles.HorizontalLine(Color.grey);
|
UIStyles.HorizontalLine(Color.grey);
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUILayout.Label("<b>Search:</b>", new GUILayoutOption[] { GUILayout.Width(75) });
|
GUILayout.Label("<b>Search:</b>", new GUILayoutOption[] { GUILayout.Width(75) });
|
||||||
m_search = GUILayout.TextField(m_search, null);
|
m_search = GUIUnstrip.TextField(m_search, new GUILayoutOption[0]);
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUILayout.Label("<b>Filter:</b>", new GUILayoutOption[] { GUILayout.Width(75) });
|
GUILayout.Label("<b>Filter:</b>", new GUILayoutOption[] { GUILayout.Width(75) });
|
||||||
FilterToggle(MemberTypes.All, "All");
|
FilterToggle(MemberTypes.All, "All");
|
||||||
FilterToggle(MemberTypes.Property, "Properties");
|
FilterToggle(MemberTypes.Property, "Properties");
|
||||||
@ -279,7 +283,7 @@ namespace Explorer
|
|||||||
FilterToggle(MemberTypes.Method, "Methods");
|
FilterToggle(MemberTypes.Method, "Methods");
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUILayout.Label("<b>Values:</b>", new GUILayoutOption[] { GUILayout.Width(75) });
|
GUILayout.Label("<b>Values:</b>", new GUILayoutOption[] { GUILayout.Width(75) });
|
||||||
if (GUILayout.Button("Update", new GUILayoutOption[] { GUILayout.Width(100) }))
|
if (GUILayout.Button("Update", new GUILayoutOption[] { GUILayout.Width(100) }))
|
||||||
{
|
{
|
||||||
@ -297,7 +301,7 @@ namespace Explorer
|
|||||||
Pages.ItemCount = m_cachedMembersFiltered.Length;
|
Pages.ItemCount = m_cachedMembersFiltered.Length;
|
||||||
|
|
||||||
// prev/next page buttons
|
// prev/next page buttons
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
|
|
||||||
Pages.DrawLimitInputArea();
|
Pages.DrawLimitInputArea();
|
||||||
|
|
||||||
@ -325,7 +329,7 @@ namespace Explorer
|
|||||||
|
|
||||||
UIStyles.HorizontalLine(Color.grey);
|
UIStyles.HorizontalLine(Color.grey);
|
||||||
|
|
||||||
GUILayout.BeginVertical(GUI.skin.box, null);
|
GUILayout.BeginVertical(GUIContent.none, GUI.skin.box, null);
|
||||||
|
|
||||||
var members = this.m_cachedMembersFiltered;
|
var members = this.m_cachedMembersFiltered;
|
||||||
int start = Pages.CalculateOffsetIndex();
|
int start = Pages.CalculateOffsetIndex();
|
||||||
@ -361,16 +365,13 @@ namespace Explorer
|
|||||||
GUIUnstrip.EndArea();
|
GUIUnstrip.EndArea();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Il2CppException e)
|
catch (Exception e) when (e.Message.Contains("in a group with only"))
|
||||||
{
|
{
|
||||||
if (!e.Message.Contains("in a group with only"))
|
// suppress
|
||||||
{
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
MelonLogger.LogWarning("Exception drawing ReflectionWindow: " + e.GetType() + ", " + e.Message);
|
ExplorerCore.LogWarning("Exception drawing ReflectionWindow: " + e.GetType() + ", " + e.Message);
|
||||||
DestroyWindow();
|
DestroyWindow();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,4 @@
|
|||||||
using System;
|
using UnityEngine;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using MelonLoader;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer
|
||||||
{
|
{
|
||||||
@ -56,7 +50,7 @@ namespace Explorer
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
GUI.DragWindow(new Rect(0, 0, m_rect.width - 90, 20));
|
GUI.DragWindow(new Rect(0, 0, m_rect.width - 90, 20));
|
||||||
if (GUI.Button(new Rect(m_rect.width - 90, 2, 80, 20), "<color=red>Close All</color>"))
|
if (GUIUnstrip.Button(new Rect(m_rect.width - 90, 2, 80, 20), "<color=red>Close All</color>"))
|
||||||
{
|
{
|
||||||
foreach (var window in WindowManager.Windows)
|
foreach (var window in WindowManager.Windows)
|
||||||
{
|
{
|
||||||
@ -67,8 +61,8 @@ namespace Explorer
|
|||||||
|
|
||||||
GUIUnstrip.BeginArea(new Rect(5, 25, m_rect.width - 10, m_rect.height - 35), GUI.skin.box);
|
GUIUnstrip.BeginArea(new Rect(5, 25, m_rect.width - 10, m_rect.height - 35), GUI.skin.box);
|
||||||
|
|
||||||
GUILayout.BeginVertical(GUI.skin.box, null);
|
GUILayout.BeginVertical(GUIContent.none, GUI.skin.box, null);
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUI.skin.button.alignment = TextAnchor.MiddleLeft;
|
GUI.skin.button.alignment = TextAnchor.MiddleLeft;
|
||||||
int tabPerRow = Mathf.FloorToInt((float)((decimal)m_rect.width / 238));
|
int tabPerRow = Mathf.FloorToInt((float)((decimal)m_rect.width / 238));
|
||||||
int rowCount = 0;
|
int rowCount = 0;
|
||||||
@ -78,7 +72,7 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
rowCount = 0;
|
rowCount = 0;
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
}
|
}
|
||||||
rowCount++;
|
rowCount++;
|
||||||
|
|
||||||
|
@ -1,11 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using Harmony;
|
|
||||||
using MelonLoader;
|
|
||||||
using UnhollowerBaseLib;
|
|
||||||
using UnhollowerRuntimeLib;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer
|
||||||
@ -49,7 +42,11 @@ namespace Explorer
|
|||||||
|
|
||||||
public void OnGUI()
|
public void OnGUI()
|
||||||
{
|
{
|
||||||
m_rect = GUI.Window(windowID, m_rect, (GUI.WindowFunction)WindowFunction, Title);
|
#if CPP
|
||||||
|
m_rect = GUI.Window(windowID, m_rect, (GUI.WindowFunction)WindowFunction, GUIContent.Temp(Title), GUI.skin.window);
|
||||||
|
#else
|
||||||
|
m_rect = GUI.Window(windowID, m_rect, WindowFunction, Title);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Header()
|
public void Header()
|
||||||
@ -57,8 +54,12 @@ namespace Explorer
|
|||||||
if (!WindowManager.TabView)
|
if (!WindowManager.TabView)
|
||||||
{
|
{
|
||||||
GUI.DragWindow(new Rect(0, 0, m_rect.width - 90, 20));
|
GUI.DragWindow(new Rect(0, 0, m_rect.width - 90, 20));
|
||||||
|
|
||||||
if (GUI.Button(new Rect(m_rect.width - 90, 2, 80, 20), "<color=red><b>X</b></color>"))
|
#if CPP
|
||||||
|
if (GUI.Button(new Rect(m_rect.width - 90, 2, 80, 20), GUIContent.Temp("<color=red><b>X</b></color>"), GUI.skin.button))
|
||||||
|
#else
|
||||||
|
if (GUI.Button(new Rect(m_rect.width - 90, 2, 80, 20), "<color=red><b>X</b></color>", GUI.skin.button))
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
DestroyWindow();
|
DestroyWindow();
|
||||||
return;
|
return;
|
||||||
|
@ -1,13 +1,5 @@
|
|||||||
using System;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using Harmony;
|
|
||||||
using MelonLoader;
|
|
||||||
using UnhollowerBaseLib;
|
|
||||||
using UnhollowerRuntimeLib;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.Events;
|
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer
|
||||||
{
|
{
|
||||||
@ -93,12 +85,16 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
forceReflection = true;
|
forceReflection = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if CPP
|
||||||
Il2CppSystem.Object iObj = null;
|
Il2CppSystem.Object iObj = null;
|
||||||
if (obj is Il2CppSystem.Object isObj)
|
if (obj is Il2CppSystem.Object isObj)
|
||||||
{
|
{
|
||||||
iObj = isObj;
|
iObj = isObj;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
var iObj = obj;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!forceReflection)
|
if (!forceReflection)
|
||||||
{
|
{
|
||||||
@ -106,6 +102,7 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
bool equals = ReferenceEquals(obj, window.Target);
|
bool equals = ReferenceEquals(obj, window.Target);
|
||||||
|
|
||||||
|
#if CPP
|
||||||
if (!equals && iObj is Il2CppSystem.Object iCurrent && window.Target is Il2CppSystem.Object iTarget)
|
if (!equals && iObj is Il2CppSystem.Object iCurrent && window.Target is Il2CppSystem.Object iTarget)
|
||||||
{
|
{
|
||||||
if (iCurrent.GetIl2CppType().FullName != iTarget.GetIl2CppType().FullName)
|
if (iCurrent.GetIl2CppType().FullName != iTarget.GetIl2CppType().FullName)
|
||||||
@ -118,6 +115,7 @@ namespace Explorer
|
|||||||
|
|
||||||
equals = iCurrent.Pointer == iTarget.Pointer;
|
equals = iCurrent.Pointer == iTarget.Pointer;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (equals)
|
if (equals)
|
||||||
{
|
{
|
||||||
@ -142,7 +140,7 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
if (!TabView)
|
if (!TabView)
|
||||||
{
|
{
|
||||||
GUI.BringWindowToFront(window.windowID);
|
GUIUnstrip.BringWindowToFront(window.windowID);
|
||||||
GUI.FocusWindow(window.windowID);
|
GUI.FocusWindow(window.windowID);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -173,7 +171,7 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (!CppExplorer.ShowMenu)
|
if (!ExplorerCore.ShowMenu)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -191,7 +189,7 @@ namespace Explorer
|
|||||||
|
|
||||||
private static bool RectContainsMouse(Rect rect)
|
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));
|
return rect.Contains(new Vector2(mousePos.x, Screen.height - mousePos.y));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,19 +2,22 @@
|
|||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using Explorer;
|
using Explorer;
|
||||||
|
|
||||||
|
#if ML
|
||||||
using MelonLoader;
|
using MelonLoader;
|
||||||
|
|
||||||
[assembly: MelonInfo(typeof(CppExplorer), CppExplorer.NAME, CppExplorer.VERSION, CppExplorer.AUTHOR)]
|
[assembly: MelonInfo(typeof(ExplorerMelonMod), "Explorer", ExplorerCore.VERSION, ExplorerCore.AUTHOR)]
|
||||||
[assembly: MelonGame(null, null)]
|
[assembly: MelonGame(null, null)]
|
||||||
|
#endif
|
||||||
|
|
||||||
// General Information about an assembly is controlled through the following
|
// General Information about an assembly is controlled through the following
|
||||||
// set of attributes. Change these attribute values to modify the information
|
// set of attributes. Change these attribute values to modify the information
|
||||||
// associated with an assembly.
|
// associated with an assembly.
|
||||||
[assembly: AssemblyTitle(CppExplorer.NAME)]
|
[assembly: AssemblyTitle(ExplorerCore.NAME)]
|
||||||
[assembly: AssemblyDescription("")]
|
[assembly: AssemblyDescription("")]
|
||||||
[assembly: AssemblyConfiguration("")]
|
[assembly: AssemblyConfiguration("")]
|
||||||
[assembly: AssemblyCompany(CppExplorer.AUTHOR)]
|
[assembly: AssemblyCompany(ExplorerCore.AUTHOR)]
|
||||||
[assembly: AssemblyProduct(CppExplorer.NAME)]
|
[assembly: AssemblyProduct(ExplorerCore.NAME)]
|
||||||
[assembly: AssemblyCopyright("")]
|
[assembly: AssemblyCopyright("")]
|
||||||
[assembly: AssemblyTrademark("")]
|
[assembly: AssemblyTrademark("")]
|
||||||
[assembly: AssemblyCulture("")]
|
[assembly: AssemblyCulture("")]
|
||||||
|
@ -1,27 +1,86 @@
|
|||||||
using System;
|
using System.Collections;
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System;
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using MelonLoader;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Collections.Specialized;
|
||||||
|
|
||||||
|
// used to test multiple generic constraints
|
||||||
|
public class TestGeneric : IComparable<string>
|
||||||
|
{
|
||||||
|
public TestGeneric() { }
|
||||||
|
|
||||||
|
public int CompareTo(string other) => throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Flags]
|
||||||
|
public enum TestFlags
|
||||||
|
{
|
||||||
|
Red,
|
||||||
|
Green,
|
||||||
|
Blue
|
||||||
|
}
|
||||||
|
|
||||||
|
// test non-flags weird enum
|
||||||
|
public enum WeirdEnum
|
||||||
|
{
|
||||||
|
First = 1,
|
||||||
|
Second,
|
||||||
|
Third = 2,
|
||||||
|
Fourth,
|
||||||
|
Fifth
|
||||||
|
}
|
||||||
|
|
||||||
namespace Explorer.Tests
|
namespace Explorer.Tests
|
||||||
{
|
{
|
||||||
public class TestClass
|
public class TestClass
|
||||||
{
|
{
|
||||||
|
public static TestFlags testFlags = TestFlags.Blue | TestFlags.Green;
|
||||||
|
public static WeirdEnum testWeird = WeirdEnum.First;
|
||||||
|
|
||||||
|
public static int testBitmask;
|
||||||
|
|
||||||
public static TestClass Instance => m_instance ?? (m_instance = new TestClass());
|
public static TestClass Instance => m_instance ?? (m_instance = new TestClass());
|
||||||
private static TestClass m_instance;
|
private static TestClass m_instance;
|
||||||
|
|
||||||
|
#if CPP
|
||||||
|
public static Il2CppSystem.Collections.Generic.HashSet<string> ILHashSetTest;
|
||||||
|
#endif
|
||||||
|
|
||||||
public TestClass()
|
public TestClass()
|
||||||
{
|
{
|
||||||
|
#if CPP
|
||||||
ILHashSetTest = new Il2CppSystem.Collections.Generic.HashSet<string>();
|
ILHashSetTest = new Il2CppSystem.Collections.Generic.HashSet<string>();
|
||||||
ILHashSetTest.Add("1");
|
ILHashSetTest.Add("1");
|
||||||
ILHashSetTest.Add("2");
|
ILHashSetTest.Add("2");
|
||||||
ILHashSetTest.Add("3");
|
ILHashSetTest.Add("3");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
testBitmask = 1 | 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int StaticProperty => 5;
|
||||||
|
public static int StaticField = 5;
|
||||||
|
public int NonStaticField;
|
||||||
|
|
||||||
|
public static string TestGeneric<C, T>(string arg0) where C : Component where T : TestGeneric, IComparable<string>
|
||||||
|
{
|
||||||
|
return $"C: '{typeof(C).FullName}', T: '{typeof(T).FullName}', arg0: '{arg0}'";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string TestRefInOutGeneric<T>(ref string arg0, in int arg1, out string arg2)
|
||||||
|
{
|
||||||
|
arg2 = "this is arg2";
|
||||||
|
|
||||||
|
return $"T: '{typeof(T).FullName}', ref arg0: '{arg0}', in arg1: '{arg1}', out arg2: '{arg2}'";
|
||||||
|
}
|
||||||
|
|
||||||
|
//// this type of generic is not supported, due to requiring a non-primitive argument.
|
||||||
|
//public static T TestDifferentGeneric<T>(T obj) where T : Component
|
||||||
|
//{
|
||||||
|
// return obj;
|
||||||
|
//}
|
||||||
|
|
||||||
// test a non-generic dictionary
|
// test a non-generic dictionary
|
||||||
|
|
||||||
public Hashtable TestNonGenericDict()
|
public Hashtable TestNonGenericDict()
|
||||||
@ -55,7 +114,6 @@ namespace Explorer.Tests
|
|||||||
"Three"
|
"Three"
|
||||||
};
|
};
|
||||||
|
|
||||||
public static Il2CppSystem.Collections.Generic.HashSet<string> ILHashSetTest;
|
|
||||||
|
|
||||||
// Test indexed parameter
|
// Test indexed parameter
|
||||||
|
|
||||||
|
@ -1,497 +1,124 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using UnityEngine;
|
|
||||||
using MelonLoader;
|
|
||||||
using UnhollowerBaseLib;
|
|
||||||
using UnhollowerRuntimeLib;
|
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using UnityEngine;
|
||||||
|
#if CPP
|
||||||
|
using Explorer.UnstripInternals;
|
||||||
using UnityEngineInternal;
|
using UnityEngineInternal;
|
||||||
using Harmony;
|
using UnhollowerRuntimeLib;
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer
|
||||||
{
|
{
|
||||||
public class GUIUnstrip
|
public class GUIUnstrip
|
||||||
{
|
{
|
||||||
public static int s_ScrollControlId;
|
public static string TextField(string text, GUILayoutOption[] options)
|
||||||
|
|
||||||
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 GenericStack GetScrollStack()
|
|
||||||
{
|
{
|
||||||
if (m_scrollViewStatesInfo == null)
|
#if CPP
|
||||||
{
|
return Internal.TextField(text, options);
|
||||||
if (typeof(GUI).GetProperty("scrollViewStates", ReflectionHelpers.CommonFlags) is PropertyInfo scrollStatesInfo)
|
#else
|
||||||
{
|
return GUILayout.TextField(text, options);
|
||||||
m_scrollViewStatesInfo = scrollStatesInfo;
|
#endif
|
||||||
}
|
}
|
||||||
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)
|
public static Rect Window(int id, Rect rect, GUI.WindowFunction windowFunc, string title)
|
||||||
{
|
{
|
||||||
m_scrollStack = stack;
|
#if CPP
|
||||||
}
|
return GUI.Window(id, rect, windowFunc, GUIContent.Temp(title), GUI.skin.window);
|
||||||
else
|
#else
|
||||||
{
|
return GUI.Window(id, rect, windowFunc, title);
|
||||||
m_scrollStack = new GenericStack();
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_scrollStack;
|
public static bool Button(Rect rect, string title)
|
||||||
|
{
|
||||||
|
#if CPP
|
||||||
|
return GUI.Button(rect, GUIContent.Temp(title), GUI.skin.button);
|
||||||
|
#else
|
||||||
|
return GUI.Button(rect, title);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string TextArea(string text, params GUILayoutOption[] options)
|
||||||
|
{
|
||||||
|
#if CPP
|
||||||
|
return GUILayout.DoTextField(text, -1, true, GUI.skin.textArea, options);
|
||||||
|
#else
|
||||||
|
return GUILayout.TextArea(text, options);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void BringWindowToFront(int id)
|
||||||
|
{
|
||||||
|
#if CPP
|
||||||
|
Internal.BringWindowToFront(id);
|
||||||
|
#else
|
||||||
|
GUI.BringWindowToFront(id);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Vector2 ScreenToGUIPoint(Vector2 screenPoint)
|
||||||
|
{
|
||||||
|
#if CPP
|
||||||
|
return Internal.ScreenToGUIPoint(screenPoint);
|
||||||
|
#else
|
||||||
|
return GUIUtility.ScreenToGUIPoint(screenPoint);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Space(float pixels)
|
public static void Space(float pixels)
|
||||||
{
|
{
|
||||||
GUIUtility.CheckOnGUI();
|
#if CPP
|
||||||
|
Internal.Space(pixels);
|
||||||
if (GUILayoutUtility.current.topLevel.isVertical)
|
#else
|
||||||
LayoutUtilityUnstrip.GetRect(0, pixels, GUILayoutUtility.spaceStyle, new GUILayoutOption[] { GUILayout.Height(pixels) });
|
GUILayout.Space(pixels);
|
||||||
else
|
#endif
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// fix for repeatbutton
|
public static bool RepeatButton(string text, params GUILayoutOption[] options)
|
||||||
|
|
||||||
static public bool RepeatButton(Texture image, params GUILayoutOption[] options) { return DoRepeatButton(GUIContent.Temp(image), GUI.skin.button, options); }
|
|
||||||
static public bool RepeatButton(string text, params GUILayoutOption[] options) { return DoRepeatButton(GUIContent.Temp(text), 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); }
|
|
||||||
static public bool RepeatButton(string text, GUIStyle style, params GUILayoutOption[] options) { return DoRepeatButton(GUIContent.Temp(text), style, options); }
|
|
||||||
// Make a repeating button. The button returns true as long as the user holds down the mouse
|
|
||||||
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.RepeatButton(LayoutUtilityUnstrip.GetRect(content, style, options), content, style); }
|
|
||||||
|
|
||||||
// Fix for BeginArea
|
|
||||||
|
|
||||||
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, GUIStyle style) { BeginArea(screenRect, GUIContent.none, style); }
|
|
||||||
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); }
|
|
||||||
|
|
||||||
// Begin a GUILayout block of GUI controls in a fixed screen area.
|
|
||||||
static public void BeginArea(Rect screenRect, GUIContent content, GUIStyle style)
|
|
||||||
{
|
{
|
||||||
GUILayoutGroup g = GUILayoutUtility.BeginLayoutArea(style, Il2CppType.Of<GUILayoutGroup>());
|
#if CPP
|
||||||
if (Event.current.type == EventType.Layout)
|
return Internal.DoRepeatButton(GUIContent.Temp(text), GUI.skin.button, options);
|
||||||
{
|
#else
|
||||||
g.resetCoords = true;
|
return GUILayout.RepeatButton(text, options);
|
||||||
g.minWidth = g.maxWidth = screenRect.width;
|
#endif
|
||||||
g.minHeight = g.maxHeight = screenRect.height;
|
}
|
||||||
g.rect = Rect.MinMaxRect(screenRect.xMin, screenRect.yMin, g.rect.xMax, g.rect.yMax);
|
|
||||||
}
|
public static void BeginArea(Rect screenRect, GUIStyle style)
|
||||||
|
{
|
||||||
GUI.BeginGroup(g.rect, content, style);
|
#if CPP
|
||||||
|
Internal.BeginArea(screenRect, GUIContent.none, style);
|
||||||
|
#else
|
||||||
|
GUILayout.BeginArea(screenRect, style);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close a GUILayout block started with BeginArea
|
|
||||||
static public void EndArea()
|
static public void EndArea()
|
||||||
{
|
{
|
||||||
if (Event.current.type == EventType.Used)
|
#if CPP
|
||||||
return;
|
Internal.EndArea();
|
||||||
GUILayoutUtility.current.layoutGroups.Pop();
|
#else
|
||||||
GUILayoutUtility.current.topLevel = GUILayoutUtility.current.layoutGroups.Peek().TryCast<GUILayoutGroup>();
|
GUILayout.EndArea();
|
||||||
GUI.EndGroup();
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fix for BeginGroup
|
|
||||||
|
|
||||||
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); }
|
|
||||||
|
|
||||||
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 EndGroup()
|
|
||||||
{
|
|
||||||
GUIClip.Internal_Pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fix for BeginScrollView.
|
|
||||||
|
|
||||||
public static Vector2 BeginScrollView(Vector2 scroll, params GUILayoutOption[] options)
|
public static Vector2 BeginScrollView(Vector2 scroll, params GUILayoutOption[] options)
|
||||||
{
|
{
|
||||||
// First, just try normal way, may not have been stripped or was unstripped successfully.
|
#if CPP
|
||||||
if (!ScrollFailed)
|
return Internal.BeginScrollView(scroll, options);
|
||||||
{
|
#else
|
||||||
try
|
return GUILayout.BeginScrollView(scroll, options);
|
||||||
{
|
#endif
|
||||||
return GUILayout.BeginScrollView(scroll, options);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
ScrollFailed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try manual implementation.
|
|
||||||
if (!ManualUnstripFailed)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return BeginScrollView_ImplLayout(scroll, false, false, GUI.skin.horizontalScrollbar, GUI.skin.verticalScrollbar, GUI.skin.scrollView, options);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
MelonLogger.Log("Exception on manual BeginScrollView: " + e.GetType() + ", " + e.Message + "\r\n" + e.StackTrace);
|
|
||||||
ManualUnstripFailed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sorry! No scrolling for you.
|
|
||||||
return scroll;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void EndScrollView(bool handleScrollWheel = true)
|
public static void EndScrollView(bool handleScrollWheel = true)
|
||||||
{
|
{
|
||||||
// Only end the scroll view for the relevant BeginScrollView option, if any.
|
#if CPP
|
||||||
|
Internal.EndScrollView(handleScrollWheel);
|
||||||
if (!ScrollFailed)
|
#else
|
||||||
{
|
GUILayout.EndScrollView();
|
||||||
GUILayout.EndScrollView();
|
#endif
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
680
src/UnstripFixes/Internal.cs
Normal file
680
src/UnstripFixes/Internal.cs
Normal file
@ -0,0 +1,680 @@
|
|||||||
|
#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)
|
||||||
|
{
|
||||||
|
text = text ?? "";
|
||||||
|
|
||||||
|
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
|
@ -1,38 +1,17 @@
|
|||||||
using System;
|
#if CPP
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using Explorer.UnstripInternals;
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer
|
||||||
{
|
{
|
||||||
public class LayoutUtilityUnstrip
|
public class Internal_LayoutUtility
|
||||||
{
|
{
|
||||||
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)
|
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)
|
switch (Event.current.type)
|
||||||
{
|
{
|
||||||
case EventType.Layout:
|
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;
|
return GUILayoutUtility.kDummyRect;
|
||||||
case EventType.Used:
|
case EventType.Used:
|
||||||
return GUILayoutUtility.kDummyRect;
|
return GUILayoutUtility.kDummyRect;
|
||||||
@ -40,14 +19,14 @@ namespace Explorer
|
|||||||
return GUILayoutUtility.current.topLevel.GetNext().rect;
|
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)
|
||||||
public static Rect GetRect(GUIContent content, GUIStyle style, params GUILayoutOption[] options) { return DoGetRect(content, style, options); }
|
{
|
||||||
|
return DoGetRect(content, style, options);
|
||||||
|
}
|
||||||
|
|
||||||
static Rect DoGetRect(GUIContent content, GUIStyle style, GUILayoutOption[] options)
|
static Rect DoGetRect(GUIContent content, GUIStyle style, GUILayoutOption[] options)
|
||||||
{
|
{
|
||||||
GUIUtility.CheckOnGUI();
|
|
||||||
|
|
||||||
switch (Event.current.type)
|
switch (Event.current.type)
|
||||||
{
|
{
|
||||||
case EventType.Layout:
|
case EventType.Layout:
|
||||||
@ -100,13 +79,14 @@ namespace Explorer
|
|||||||
Rect last;
|
Rect last;
|
||||||
if (type != EventType.Layout && type != EventType.Used)
|
if (type != EventType.Layout && type != EventType.Used)
|
||||||
{
|
{
|
||||||
last = GUILayoutUtility.current.topLevel.GetLastUnstripped();
|
last = GUILayoutUtility.current.topLevel.Unstripped_GetLast();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
last = GUILayoutUtility.kDummyRect;
|
last = GUILayoutUtility.kDummyRect;
|
||||||
}
|
}
|
||||||
return last;
|
return last;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
29
src/UnstripFixes/Internal_ScrollViewState.cs
Normal file
29
src/UnstripFixes/Internal_ScrollViewState.cs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#if CPP
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Explorer
|
||||||
|
{
|
||||||
|
public class Internal_ScrollViewState
|
||||||
|
{
|
||||||
|
public Rect position;
|
||||||
|
public Rect visibleRect;
|
||||||
|
public Rect viewRect;
|
||||||
|
public Vector2 scrollPosition;
|
||||||
|
public bool apply;
|
||||||
|
|
||||||
|
public static Dictionary<IntPtr, Internal_ScrollViewState> Dict = new Dictionary<IntPtr, Internal_ScrollViewState>();
|
||||||
|
|
||||||
|
public static Internal_ScrollViewState FromPointer(IntPtr ptr)
|
||||||
|
{
|
||||||
|
if (!Dict.ContainsKey(ptr))
|
||||||
|
{
|
||||||
|
Dict.Add(ptr, new Internal_ScrollViewState());
|
||||||
|
}
|
||||||
|
|
||||||
|
return Dict[ptr];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
@ -1,15 +1,54 @@
|
|||||||
using System;
|
#if CPP
|
||||||
using System.Collections.Generic;
|
using System;
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using UnityEngine;
|
|
||||||
using UnhollowerRuntimeLib;
|
using UnhollowerRuntimeLib;
|
||||||
|
using UnityEngine;
|
||||||
|
using Explorer.UnstripInternals;
|
||||||
|
using Il2CppSystem.Reflection;
|
||||||
|
|
||||||
namespace Explorer
|
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 Rect position;
|
||||||
private readonly float currentValue;
|
private readonly float currentValue;
|
||||||
private readonly float size;
|
private readonly float size;
|
||||||
@ -20,7 +59,8 @@ namespace Explorer
|
|||||||
private readonly bool horiz;
|
private readonly bool horiz;
|
||||||
private readonly int id;
|
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.position = position;
|
||||||
this.currentValue = currentValue;
|
this.currentValue = currentValue;
|
||||||
@ -67,7 +107,7 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GUI.scrollTroughSide = 0;
|
ScrollTroughSide = 0;
|
||||||
GUIUtility.hotControl = this.id;
|
GUIUtility.hotControl = this.id;
|
||||||
this.CurrentEvent().Use();
|
this.CurrentEvent().Use();
|
||||||
if (this.ThumbSelectionRect().Contains(this.CurrentEvent().mousePosition))
|
if (this.ThumbSelectionRect().Contains(this.CurrentEvent().mousePosition))
|
||||||
@ -80,9 +120,10 @@ namespace Explorer
|
|||||||
GUI.changed = true;
|
GUI.changed = true;
|
||||||
if (this.SupportsPageMovements())
|
if (this.SupportsPageMovements())
|
||||||
{
|
{
|
||||||
this.SliderState().isDragging = false;
|
var ext = Internal_SliderState.FromPointer(GetSliderState().Pointer);
|
||||||
GUIUnstrip.nextScrollStepTime = DateTime.Now.AddMilliseconds(250.0);
|
ext.isDragging = false;
|
||||||
GUI.scrollTroughSide = this.CurrentScrollTroughSide();
|
Internal.nextScrollStepTime = DateTime.Now.AddMilliseconds(250.0);
|
||||||
|
ScrollTroughSide = this.CurrentScrollTroughSide();
|
||||||
result = this.PageMovementValue();
|
result = this.PageMovementValue();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -105,8 +146,8 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SliderState sliderState = this.SliderState();
|
var ext = Internal_SliderState.FromPointer(GetSliderState().Pointer);
|
||||||
if (!sliderState.isDragging)
|
if (!ext.isDragging)
|
||||||
{
|
{
|
||||||
result = this.currentValue;
|
result = this.currentValue;
|
||||||
}
|
}
|
||||||
@ -114,8 +155,8 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
GUI.changed = true;
|
GUI.changed = true;
|
||||||
this.CurrentEvent().Use();
|
this.CurrentEvent().Use();
|
||||||
float num = this.MousePosition() - sliderState.dragStartPos;
|
float num = this.MousePosition() - ext.dragStartPos;
|
||||||
float value = sliderState.dragStartValue + num / this.ValuesPerPixel();
|
float value = ext.dragStartValue + num / this.ValuesPerPixel();
|
||||||
result = this.Clamp(value);
|
result = this.Clamp(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -146,7 +187,7 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
else if (this.ThumbRect().Contains(this.CurrentEvent().mousePosition))
|
else if (this.ThumbRect().Contains(this.CurrentEvent().mousePosition))
|
||||||
{
|
{
|
||||||
if (GUI.scrollTroughSide != 0)
|
if (ScrollTroughSide != 0)
|
||||||
{
|
{
|
||||||
GUIUtility.hotControl = 0;
|
GUIUtility.hotControl = 0;
|
||||||
}
|
}
|
||||||
@ -155,20 +196,20 @@ namespace Explorer
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
GUI.InternalRepaintEditorWindow();
|
GUI.InternalRepaintEditorWindow();
|
||||||
if (DateTime.Now < GUIUnstrip.nextScrollStepTime)
|
if (DateTime.Now < Internal.nextScrollStepTime)
|
||||||
{
|
{
|
||||||
result = this.currentValue;
|
result = this.currentValue;
|
||||||
}
|
}
|
||||||
else if (this.CurrentScrollTroughSide() != GUI.scrollTroughSide)
|
else if (this.CurrentScrollTroughSide() != ScrollTroughSide)
|
||||||
{
|
{
|
||||||
result = this.currentValue;
|
result = this.currentValue;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GUIUnstrip.nextScrollStepTime = DateTime.Now.AddMilliseconds(30.0);
|
Internal.nextScrollStepTime = DateTime.Now.AddMilliseconds(30.0);
|
||||||
if (this.SupportsPageMovements())
|
if (this.SupportsPageMovements())
|
||||||
{
|
{
|
||||||
this.SliderState().isDragging = false;
|
Internal_SliderState.FromPointer(GetSliderState().Pointer).isDragging = false;
|
||||||
GUI.changed = true;
|
GUI.changed = true;
|
||||||
result = this.PageMovementValue();
|
result = this.PageMovementValue();
|
||||||
}
|
}
|
||||||
@ -264,15 +305,15 @@ namespace Explorer
|
|||||||
|
|
||||||
private void StartDraggingWithValue(float dragStartValue)
|
private void StartDraggingWithValue(float dragStartValue)
|
||||||
{
|
{
|
||||||
SliderState sliderState = this.SliderState();
|
var ext = Internal_SliderState.FromPointer(GetSliderState().Pointer);
|
||||||
sliderState.dragStartPos = this.MousePosition();
|
ext.dragStartPos = this.MousePosition();
|
||||||
sliderState.dragStartValue = dragStartValue;
|
ext.dragStartValue = dragStartValue;
|
||||||
sliderState.isDragging = true;
|
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()
|
private Rect ThumbRect()
|
||||||
@ -369,3 +410,4 @@ namespace Explorer
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
26
src/UnstripFixes/Internal_SliderState.cs
Normal file
26
src/UnstripFixes/Internal_SliderState.cs
Normal 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];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,32 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Harmony;
|
|
||||||
using MelonLoader;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace Explorer
|
|
||||||
{
|
|
||||||
public class ScrollViewStateUnstrip
|
|
||||||
{
|
|
||||||
public Rect position;
|
|
||||||
public Rect visibleRect;
|
|
||||||
public Rect viewRect;
|
|
||||||
public Vector2 scrollPosition;
|
|
||||||
public bool apply;
|
|
||||||
|
|
||||||
public static Dictionary<IntPtr, ScrollViewStateUnstrip> Dict = new Dictionary<IntPtr, ScrollViewStateUnstrip>();
|
|
||||||
|
|
||||||
public static ScrollViewStateUnstrip FromPointer(IntPtr ptr)
|
|
||||||
{
|
|
||||||
if (!Dict.ContainsKey(ptr))
|
|
||||||
{
|
|
||||||
Dict.Add(ptr, new ScrollViewStateUnstrip());
|
|
||||||
}
|
|
||||||
|
|
||||||
return Dict[ptr];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,27 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Reference in New Issue
Block a user