mirror of
https://github.com/sinai-dev/UnityExplorer.git
synced 2025-06-24 01:12:41 +08:00
Compare commits
8 Commits
Author | SHA1 | Date | |
---|---|---|---|
6ca117b070 | |||
113f2fd922 | |||
7443f6500e | |||
92566c2729 | |||
713f87f455 | |||
4241e7e207 | |||
6d479a6703 | |||
6539f818c3 |
85
README.md
85
README.md
@ -6,7 +6,7 @@
|
|||||||
An in-game explorer and a suite of debugging tools for <a href="https://docs.unity3d.com/Manual/IL2CPP.html">IL2CPP</a> and <b>Mono</b> Unity games, to aid with modding development.
|
An in-game explorer and a suite of debugging tools for <a href="https://docs.unity3d.com/Manual/IL2CPP.html">IL2CPP</a> and <b>Mono</b> Unity games, to aid with modding development.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
## Releases [](../../releases/latest) []() []()
|
## Releases [](../../releases/latest) [](../../releases) [](../../releases/latest)
|
||||||
|
|
||||||
| Mod Loader | IL2CPP | Mono |
|
| Mod Loader | IL2CPP | Mono |
|
||||||
| ----------- | ------ | ---- |
|
| ----------- | ------ | ---- |
|
||||||
@ -19,24 +19,24 @@
|
|||||||
|
|
||||||
### BepInEx
|
### BepInEx
|
||||||
|
|
||||||
0. Install [BepInEx](https://github.com/BepInEx/BepInEx) for your game. For IL2CPP you should use [BepInEx 6 (Bleeding Edge)](https://builds.bepis.io/projects/bepinex_be), for Mono you should use [BepInEx 5](https://github.com/BepInEx/BepInEx/releases) (until Mono support stabilizes in BepInEx 6).
|
1. Install [BepInEx](https://github.com/BepInEx/BepInEx) for your game. For IL2CPP you should use [BepInEx 6 (Bleeding Edge)](https://builds.bepis.io/projects/bepinex_be), for Mono you should use [BepInEx 5](https://github.com/BepInEx/BepInEx/releases) (until Mono support stabilizes in BepInEx 6).
|
||||||
1. Download the UnityExplorer release for BepInEx IL2CPP or Mono above.
|
2. Download the UnityExplorer release for BepInEx IL2CPP or Mono above.
|
||||||
2. Take the `UnityExplorer.BIE.___.dll` file and put it in `[GameFolder]\BepInEx\plugins\`
|
3. Take the `UnityExplorer.BIE.___.dll` file and put it in `[GameFolder]\BepInEx\plugins\`
|
||||||
3. In IL2CPP, you will need to download the [Unity libs](https://github.com/LavaGang/Unity-Runtime-Libraries) for the game's Unity version and put them in the `BepInEx\unity-libs\` folder.
|
4. In IL2CPP, you will need to download the [Unity libs](https://github.com/LavaGang/Unity-Runtime-Libraries) for the game's Unity version and put them in the `BepInEx\unity-libs\` folder.
|
||||||
|
|
||||||
### MelonLoader
|
### MelonLoader
|
||||||
|
|
||||||
0. Install [MelonLoader](https://github.com/HerpDerpinstine/MelonLoader) 0.3+ for your game. Version 0.3 is currently in pre-release, so you must "Enable ALPHA Releases" in your MelonLoader Installer settings to see the option for it.
|
1. Install [MelonLoader](https://github.com/HerpDerpinstine/MelonLoader) 0.3+ for your game. Version 0.3 is currently in pre-release, so you must "Enable ALPHA Releases" in your MelonLoader Installer settings to see the option for it.
|
||||||
1. Download the UnityExplorer release for MelonLoader IL2CPP or Mono above.
|
2. Download the UnityExplorer release for MelonLoader IL2CPP or Mono above.
|
||||||
2. Take the `UnityExplorer.ML.___.dll` file and put it in the `[GameFolder]\Mods\` folder.
|
3. Take the `UnityExplorer.ML.___.dll` file and put it in the `[GameFolder]\Mods\` folder.
|
||||||
|
|
||||||
### Standalone
|
### Standalone
|
||||||
|
|
||||||
The standalone release is based on the BepInEx build, so it requires Harmony 2.0 (or HarmonyX) to function properly.
|
The standalone release requires you to also load `0Harmony.dll` (HarmonyX, from the `lib\` folder) to function properly, and the IL2CPP also requires `UnhollowerBaseLib.dll` as well. The Mono release should be fairly easy to use with any loader, but the IL2CPP one may be tricky, I'd recommend just using BepInEx or MelonLoader for IL2CPP.
|
||||||
|
|
||||||
0. Load the DLL from your mod or inject it. You must also make sure `0Harmony.dll` is loaded, and `UnhollowerBaseLib.dll` for IL2CPP as well.
|
1. Load the UnityExplorer DLL from your mod or inject it, as well as `0Harmony.dll` and `UnhollowerBaseLib.dll` as required.
|
||||||
1. Create an instance of Unity Explorer with `UnityExplorer.ExplorerStandalone.CreateInstance();`
|
2. Create an instance of Unity Explorer with `UnityExplorer.ExplorerStandalone.CreateInstance();`
|
||||||
2. Optionally subscribe to the `ExplorerStandalone.OnLog` event to handle logging if you wish.
|
3. Optionally subscribe to the `ExplorerStandalone.OnLog` event to handle logging if you wish.
|
||||||
|
|
||||||
## Issues and contributions
|
## Issues and contributions
|
||||||
|
|
||||||
@ -46,7 +46,19 @@ Both issue reports and PR contributions are welcome in this repository.
|
|||||||
|
|
||||||
To report an issue with UnityExplorer, please use the following template (as well as any other information / images you can provide).
|
To report an issue with UnityExplorer, please use the following template (as well as any other information / images you can provide).
|
||||||
|
|
||||||
Please upload your Unity log file to [Pastebin](https://pastebin.com/) and provide a link to the paste.
|
Template:
|
||||||
|
|
||||||
|
```
|
||||||
|
* Game issue occurs on:
|
||||||
|
* UnityExplorer version: (eg BIE.IL2CPP v3.3.3, etc)
|
||||||
|
|
||||||
|
* Description of issue:
|
||||||
|
|
||||||
|
* Unity log link:
|
||||||
|
* Mod Loader log link:
|
||||||
|
```
|
||||||
|
|
||||||
|
Please upload your Unity log file to [Pastebin](https://pastebin.com/) (or equivalent service) and provide a link to the paste.
|
||||||
|
|
||||||
* The log should be found at `%userprofile%\AppData\LocalLow\[Company]\[Game]\` unless redirected by your Mod Loader.
|
* The log should be found at `%userprofile%\AppData\LocalLow\[Company]\[Game]\` unless redirected by your Mod Loader.
|
||||||
* The file will be called either `output_log.txt` or `Player.log`
|
* The file will be called either `output_log.txt` or `Player.log`
|
||||||
@ -56,20 +68,6 @@ As well as the Unity log, please upload your Mod Loader's log:
|
|||||||
* BepInEx: `BepInEx\LogOutput.log`
|
* BepInEx: `BepInEx\LogOutput.log`
|
||||||
* MelonLoader: `MelonLoader\Latest.log`
|
* MelonLoader: `MelonLoader\Latest.log`
|
||||||
|
|
||||||
Template:
|
|
||||||
|
|
||||||
```
|
|
||||||
* OS Platform:
|
|
||||||
* Display resolution:
|
|
||||||
* Game(s) tested on:
|
|
||||||
* UnityExplorer version(s) tested:
|
|
||||||
|
|
||||||
* Description of issue:
|
|
||||||
|
|
||||||
* Unity log pastebin link:
|
|
||||||
* Mod Loader log pastebin link:
|
|
||||||
```
|
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
@ -126,31 +124,6 @@ Depending on the release you are using, the config file will be found at:
|
|||||||
* MelonLoader: `UserData\MelonPreferences.cfg`
|
* MelonLoader: `UserData\MelonPreferences.cfg`
|
||||||
* Standalone `{DLL_location}\UnityExplorer\config.ini`
|
* Standalone `{DLL_location}\UnityExplorer\config.ini`
|
||||||
|
|
||||||
`Main Menu Toggle` (KeyCode)
|
|
||||||
* Default: `F7`
|
|
||||||
* See [this article](https://docs.unity3d.com/ScriptReference/KeyCode.html) for a full list of all accepted KeyCodes.
|
|
||||||
|
|
||||||
`Force Unlock Mouse` (bool)
|
|
||||||
* Default: `true`
|
|
||||||
* Forces the cursor to be unlocked and visible while the UnityExplorer menu is open, and prevents anything else taking control.
|
|
||||||
|
|
||||||
`Default Page Limit` (int)
|
|
||||||
* Default: `25`
|
|
||||||
* Sets the default items per page when viewing lists or search results.
|
|
||||||
* <b>Requires a restart to take effect</b>, apart from Reflection Inspector tabs.
|
|
||||||
|
|
||||||
`Default Output Path` (string)
|
|
||||||
* Default: `Mods\UnityExplorer`
|
|
||||||
* Where output is generated to, by default (for Texture PNG saving, etc).
|
|
||||||
|
|
||||||
`Log Unity Debug` (bool)
|
|
||||||
* Default: `false`
|
|
||||||
* Listens for Unity `Debug.Log` messages and prints them to UnityExplorer's log.
|
|
||||||
|
|
||||||
`Hide on Startup` (bool)
|
|
||||||
* Default: `false`
|
|
||||||
* If true, UnityExplorer will be hidden when you start the game, you must open it via the keybind.
|
|
||||||
|
|
||||||
## Building
|
## Building
|
||||||
|
|
||||||
Building the project should be straight-forward, the references are all inside the `lib\` folder.
|
Building the project should be straight-forward, the references are all inside the `lib\` folder.
|
||||||
@ -162,10 +135,10 @@ Building the project should be straight-forward, the references are all inside t
|
|||||||
|
|
||||||
## Acknowledgments
|
## Acknowledgments
|
||||||
|
|
||||||
* [ManlyMarco](https://github.com/ManlyMarco) for [Runtime Unity Editor](https://github.com/ManlyMarco/RuntimeUnityEditor), snippets from the REPL Console were used for UnityExplorer's C# Console.
|
* [ManlyMarco](https://github.com/ManlyMarco) for [Runtime Unity Editor](https://github.com/ManlyMarco/RuntimeUnityEditor) \[[license](THIRDPARTY_LICENSES.md#runtimeunityeditor-license)\], snippets from the REPL Console were used for UnityExplorer's C# Console.
|
||||||
* [denikson](https://github.com/denikson) (aka Horse) for [mcs-unity](https://github.com/denikson/mcs-unity), used as the `Mono.CSharp` reference for the C# Console.
|
* [denikson](https://github.com/denikson) (aka Horse) for [mcs-unity](https://github.com/denikson/mcs-unity) \[no license\], used as the `Mono.CSharp` reference for the C# Console.
|
||||||
* [HerpDerpenstine](https://github.com/HerpDerpinstine) for [MelonCoroutines](https://github.com/LavaGang/MelonLoader/blob/master/MelonLoader.Support.Il2Cpp/MelonCoroutines.cs), they were included for standalone IL2CPP coroutine support.
|
* [HerpDerpenstine](https://github.com/HerpDerpinstine) for [MelonCoroutines](https://github.com/LavaGang/MelonLoader/blob/6cc958ec23b5e2e8453a73bc2e0d5aa353d4f0d1/MelonLoader.Support.Il2Cpp/MelonCoroutines.cs) \[[license](THIRDPARTY_LICENSES.md#melonloader-license)\], they were included for standalone IL2CPP coroutine support.
|
||||||
* [InGameCodeEditor](https://assetstore.unity.com/packages/tools/gui/ingame-code-editor-144254) was used as the base for the syntax highlighting for UnityExplorer's C# console (`UnityExplorer.UI.Main.CSConsole.Lexer`).
|
* [InGameCodeEditor](https://assetstore.unity.com/packages/tools/gui/ingame-code-editor-144254) \[[license](THIRDPARTY_LICENSES.md#ingamecodeeditor-license)\] was used as the base for the syntax highlighting for UnityExplorer's C# console (`UnityExplorer.UI.Main.CSConsole.Lexer`).
|
||||||
|
|
||||||
### Disclaimer
|
### Disclaimer
|
||||||
|
|
||||||
|
1067
THIRDPARTY_LICENSES.md
Normal file
1067
THIRDPARTY_LICENSES.md
Normal file
File diff suppressed because it is too large
Load Diff
BIN
lib/BepInEx.dll
BIN
lib/BepInEx.dll
Binary file not shown.
@ -7,6 +7,7 @@ using System.Linq;
|
|||||||
using UnityExplorer.Core.Runtime;
|
using UnityExplorer.Core.Runtime;
|
||||||
using UnityExplorer.UI.Main.CSConsole;
|
using UnityExplorer.UI.Main.CSConsole;
|
||||||
using UnityExplorer.UI.Main.Home;
|
using UnityExplorer.UI.Main.Home;
|
||||||
|
using UnityExplorer.UI.Inspectors;
|
||||||
|
|
||||||
namespace UnityExplorer.Core.CSharp
|
namespace UnityExplorer.Core.CSharp
|
||||||
{
|
{
|
||||||
|
@ -46,7 +46,7 @@ namespace UnityExplorer.Core.Config
|
|||||||
|
|
||||||
private void SetValue(T value)
|
private void SetValue(T value)
|
||||||
{
|
{
|
||||||
if ((m_value == null && value == null) || m_value.Equals(value))
|
if ((m_value == null && value == null) || (m_value != null && m_value.Equals(value)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_value = value;
|
m_value = value;
|
||||||
|
@ -46,81 +46,16 @@ namespace UnityExplorer.Core.Input
|
|||||||
|
|
||||||
UpdateCursorControl();
|
UpdateCursorControl();
|
||||||
|
|
||||||
Unlock = true;
|
Unlock = ConfigManager.Force_Unlock_Mouse.Value;
|
||||||
ConfigManager.Force_Unlock_Mouse.OnValueChanged += (bool val) => { Unlock = val; };
|
ConfigManager.Force_Unlock_Mouse.OnValueChanged += (bool val) => { Unlock = val; };
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void SetupPatches()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (CursorType == null)
|
|
||||||
{
|
|
||||||
throw new Exception("Could not find Type 'UnityEngine.Cursor'!");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get current cursor state and enable cursor
|
|
||||||
try
|
|
||||||
{
|
|
||||||
m_lastLockMode = (CursorLockMode?)typeof(Cursor).GetProperty("lockState", BF.Public | BF.Static)?.GetValue(null, null)
|
|
||||||
?? CursorLockMode.None;
|
|
||||||
|
|
||||||
m_lastVisibleState = (bool?)typeof(Cursor).GetProperty("visible", BF.Public | BF.Static)?.GetValue(null, null)
|
|
||||||
?? false;
|
|
||||||
}
|
|
||||||
catch { }
|
|
||||||
|
|
||||||
// Setup Harmony Patches
|
|
||||||
TryPatch(typeof(Cursor),
|
|
||||||
"lockState",
|
|
||||||
new HarmonyMethod(typeof(CursorUnlocker).GetMethod(nameof(Prefix_set_lockState))),
|
|
||||||
true);
|
|
||||||
|
|
||||||
TryPatch(typeof(Cursor),
|
|
||||||
"visible",
|
|
||||||
new HarmonyMethod(typeof(CursorUnlocker).GetMethod(nameof(Prefix_set_visible))),
|
|
||||||
true);
|
|
||||||
|
|
||||||
TryPatch(typeof(EventSystem),
|
|
||||||
"current",
|
|
||||||
new HarmonyMethod(typeof(CursorUnlocker).GetMethod(nameof(Prefix_EventSystem_set_current))),
|
|
||||||
true);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
ExplorerCore.Log($"Exception on ForceUnlockCursor.Init! {e.GetType()}, {e.Message}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void TryPatch(Type type, string property, HarmonyMethod patch, bool setter)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var harmony = ExplorerCore.Loader.HarmonyInstance;
|
|
||||||
|
|
||||||
var prop = type.GetProperty(property);
|
|
||||||
|
|
||||||
if (setter) // setter is prefix
|
|
||||||
{
|
|
||||||
harmony.Patch(prop.GetSetMethod(), prefix: patch);
|
|
||||||
}
|
|
||||||
else // getter is postfix
|
|
||||||
{
|
|
||||||
harmony.Patch(prop.GetGetMethod(), postfix: patch);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
string suf = setter ? "set_" : "get_";
|
|
||||||
ExplorerCore.Log($"Unable to patch {type.Name}.{suf}{property}: {e.Message}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void UpdateCursorControl()
|
public static void UpdateCursorControl()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
m_currentlySettingCursor = true;
|
m_currentlySettingCursor = true;
|
||||||
|
|
||||||
if (ShouldActuallyUnlock)
|
if (ShouldActuallyUnlock)
|
||||||
{
|
{
|
||||||
Cursor.lockState = CursorLockMode.None;
|
Cursor.lockState = CursorLockMode.None;
|
||||||
@ -137,6 +72,7 @@ namespace UnityExplorer.Core.Input
|
|||||||
if (UIManager.EventSys)
|
if (UIManager.EventSys)
|
||||||
ReleaseEventSystem();
|
ReleaseEventSystem();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_currentlySettingCursor = false;
|
m_currentlySettingCursor = false;
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
@ -163,9 +99,7 @@ namespace UnityExplorer.Core.Input
|
|||||||
if (!m_lastEventSystem)
|
if (!m_lastEventSystem)
|
||||||
m_lastEventSystem = EventSystem.current;
|
m_lastEventSystem = EventSystem.current;
|
||||||
|
|
||||||
//ExplorerCore.Log("Disabling current event system...");
|
|
||||||
m_lastEventSystem.enabled = false;
|
m_lastEventSystem.enabled = false;
|
||||||
//m_lastEventSystem.gameObject.SetActive(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set to our current system
|
// Set to our current system
|
||||||
@ -184,7 +118,6 @@ namespace UnityExplorer.Core.Input
|
|||||||
if (m_lastEventSystem)
|
if (m_lastEventSystem)
|
||||||
{
|
{
|
||||||
m_lastEventSystem.enabled = true;
|
m_lastEventSystem.enabled = true;
|
||||||
//m_lastEventSystem.gameObject.SetActive(true);
|
|
||||||
|
|
||||||
m_settingEventSystem = true;
|
m_settingEventSystem = true;
|
||||||
EventSystem.current = m_lastEventSystem;
|
EventSystem.current = m_lastEventSystem;
|
||||||
@ -193,7 +126,30 @@ namespace UnityExplorer.Core.Input
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[HarmonyPrefix]
|
// Patches
|
||||||
|
|
||||||
|
private static void SetupPatches()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (CursorType == null)
|
||||||
|
throw new Exception("Could not load Type 'UnityEngine.Cursor'!");
|
||||||
|
|
||||||
|
// Get current cursor state and enable cursor
|
||||||
|
m_lastLockMode = (CursorLockMode?)CursorType.GetProperty("lockState", BF.Public | BF.Static)?.GetValue(null, null)
|
||||||
|
?? CursorLockMode.None;
|
||||||
|
|
||||||
|
m_lastVisibleState = (bool?)CursorType.GetProperty("visible", BF.Public | BF.Static)?.GetValue(null, null)
|
||||||
|
?? false;
|
||||||
|
|
||||||
|
ExplorerCore.Loader.SetupPatches();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ExplorerCore.Log($"Error on CursorUnlocker.Init! {e.GetType()}, {e.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static void Prefix_EventSystem_set_current(ref EventSystem value)
|
public static void Prefix_EventSystem_set_current(ref EventSystem value)
|
||||||
{
|
{
|
||||||
if (!m_settingEventSystem)
|
if (!m_settingEventSystem)
|
||||||
@ -210,7 +166,6 @@ namespace UnityExplorer.Core.Input
|
|||||||
// Also keep track of when anything else tries to set Cursor state, this will be the
|
// Also keep track of when anything else tries to set Cursor state, this will be the
|
||||||
// value that we set back to when we close the menu or disable force-unlock.
|
// value that we set back to when we close the menu or disable force-unlock.
|
||||||
|
|
||||||
[HarmonyPrefix]
|
|
||||||
public static void Prefix_set_lockState(ref CursorLockMode value)
|
public static void Prefix_set_lockState(ref CursorLockMode value)
|
||||||
{
|
{
|
||||||
if (!m_currentlySettingCursor)
|
if (!m_currentlySettingCursor)
|
||||||
@ -222,7 +177,6 @@ namespace UnityExplorer.Core.Input
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[HarmonyPrefix]
|
|
||||||
public static void Prefix_set_visible(ref bool value)
|
public static void Prefix_set_visible(ref bool value)
|
||||||
{
|
{
|
||||||
if (!m_currentlySettingCursor)
|
if (!m_currentlySettingCursor)
|
||||||
|
@ -7,7 +7,7 @@ using System.Reflection;
|
|||||||
using BF = System.Reflection.BindingFlags;
|
using BF = System.Reflection.BindingFlags;
|
||||||
using UnityExplorer.Core.Runtime;
|
using UnityExplorer.Core.Runtime;
|
||||||
|
|
||||||
namespace UnityExplorer.Core
|
namespace UnityExplorer
|
||||||
{
|
{
|
||||||
public static class ReflectionUtility
|
public static class ReflectionUtility
|
||||||
{
|
{
|
||||||
@ -18,7 +18,7 @@ namespace UnityExplorer.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="obj">The object to get the true Type for.</param>
|
/// <param name="obj">The object to get the true Type for.</param>
|
||||||
/// <returns>The most accurate Type of the object which could be identified.</returns>
|
/// <returns>The most accurate Type of the object which could be identified.</returns>
|
||||||
public static Type GetType(this object obj)
|
public static Type GetActualType(this object obj)
|
||||||
{
|
{
|
||||||
if (obj == null)
|
if (obj == null)
|
||||||
return null;
|
return null;
|
||||||
@ -32,7 +32,7 @@ namespace UnityExplorer.Core
|
|||||||
/// <param name="obj">The object to cast</param>
|
/// <param name="obj">The object to cast</param>
|
||||||
/// <returns>The object, cast to the underlying Type if possible, otherwise the original object.</returns>
|
/// <returns>The object, cast to the underlying Type if possible, otherwise the original object.</returns>
|
||||||
public static object Cast(this object obj)
|
public static object Cast(this object obj)
|
||||||
=> ReflectionProvider.Instance.Cast(obj, GetType(obj));
|
=> ReflectionProvider.Instance.Cast(obj, GetActualType(obj));
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Cast an object to a Type, if possible.
|
/// Cast an object to a Type, if possible.
|
||||||
@ -105,7 +105,7 @@ namespace UnityExplorer.Core
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get all base types of the provided Type, including itself.
|
/// Get all base types of the provided Type, including itself.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static Type[] GetAllBaseTypes(this object obj) => GetAllBaseTypes(GetType(obj));
|
public static Type[] GetAllBaseTypes(this object obj) => GetAllBaseTypes(GetActualType(obj));
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get all base types of the provided Type, including itself.
|
/// Get all base types of the provided Type, including itself.
|
||||||
|
@ -154,21 +154,24 @@ namespace UnityExplorer.Core.Runtime.Il2Cpp
|
|||||||
/// <returns>The object, as the type (or a normal C# object) if successful or the input value if not.</returns>
|
/// <returns>The object, as the type (or a normal C# object) if successful or the input value if not.</returns>
|
||||||
public static object Il2CppCast(object obj, Type castTo)
|
public static object Il2CppCast(object obj, Type castTo)
|
||||||
{
|
{
|
||||||
if (!(obj is Il2CppSystem.Object ilObj))
|
if (!(obj is Il2CppSystem.Object cppObj))
|
||||||
return obj;
|
return obj;
|
||||||
|
|
||||||
if (!Il2CppTypeNotNull(castTo, out IntPtr castToPtr))
|
if (!Il2CppTypeNotNull(castTo, out IntPtr castToPtr))
|
||||||
return obj;
|
return obj;
|
||||||
|
|
||||||
IntPtr castFromPtr = il2cpp_object_get_class(ilObj.Pointer);
|
IntPtr castFromPtr = il2cpp_object_get_class(cppObj.Pointer);
|
||||||
|
|
||||||
if (!il2cpp_class_is_assignable_from(castToPtr, castFromPtr))
|
if (!il2cpp_class_is_assignable_from(castToPtr, castFromPtr))
|
||||||
return obj;
|
return null;
|
||||||
|
|
||||||
if (RuntimeSpecificsStore.IsInjected(castToPtr))
|
if (RuntimeSpecificsStore.IsInjected(castToPtr))
|
||||||
return UnhollowerBaseLib.Runtime.ClassInjectorBase.GetMonoObjectFromIl2CppPointer(ilObj.Pointer);
|
return UnhollowerBaseLib.Runtime.ClassInjectorBase.GetMonoObjectFromIl2CppPointer(cppObj.Pointer);
|
||||||
|
|
||||||
return Activator.CreateInstance(castTo, ilObj.Pointer);
|
if (castTo == typeof(string))
|
||||||
|
return cppObj.ToString();
|
||||||
|
|
||||||
|
return Activator.CreateInstance(castTo, cppObj.Pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -319,6 +322,14 @@ namespace UnityExplorer.Core.Runtime.Il2Cpp
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void BoxStringToType(ref object value, Type castTo)
|
||||||
|
{
|
||||||
|
if (castTo == typeof(Il2CppSystem.String))
|
||||||
|
value = (Il2CppSystem.String)(value as string);
|
||||||
|
else
|
||||||
|
value = (Il2CppSystem.Object)(value as string);
|
||||||
|
}
|
||||||
|
|
||||||
// ~~~~~~~~~~ not used ~~~~~~~~~~~~
|
// ~~~~~~~~~~ not used ~~~~~~~~~~~~
|
||||||
|
|
||||||
// cached il2cpp unbox methods
|
// cached il2cpp unbox methods
|
||||||
|
@ -27,6 +27,9 @@ namespace UnityExplorer.Core.Runtime.Mono
|
|||||||
|
|
||||||
public override string ProcessTypeNameInString(Type type, string theString, ref string typeName)
|
public override string ProcessTypeNameInString(Type type, string theString, ref string typeName)
|
||||||
=> theString;
|
=> theString;
|
||||||
|
|
||||||
|
// not necessary
|
||||||
|
public override void BoxStringToType(ref object _string, Type castTo) { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,5 +25,7 @@ namespace UnityExplorer.Core.Runtime
|
|||||||
public abstract string ProcessTypeNameInString(Type type, string theString, ref string typeName);
|
public abstract string ProcessTypeNameInString(Type type, string theString, ref string typeName);
|
||||||
|
|
||||||
public abstract bool LoadModule(string module);
|
public abstract bool LoadModule(string module);
|
||||||
|
|
||||||
|
public abstract void BoxStringToType(ref object _string, Type castTo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
27
src/Core/TestClass.cs
Normal file
27
src/Core/TestClass.cs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace UnityExplorer
|
||||||
|
{
|
||||||
|
public static class TestClass
|
||||||
|
{
|
||||||
|
#if CPP
|
||||||
|
public static string testStringOne = "Test";
|
||||||
|
public static Il2CppSystem.Object testStringTwo = "string boxed as cpp object";
|
||||||
|
public static Il2CppSystem.String testStringThree = "string boxed as cpp string";
|
||||||
|
public static string nullString = null;
|
||||||
|
|
||||||
|
public static Il2CppSystem.Collections.Hashtable testHashset;
|
||||||
|
|
||||||
|
static TestClass()
|
||||||
|
{
|
||||||
|
testHashset = new Il2CppSystem.Collections.Hashtable();
|
||||||
|
testHashset.Add("key1", "itemOne");
|
||||||
|
testHashset.Add("key2", "itemTwo");
|
||||||
|
testHashset.Add("key3", "itemThree");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
@ -5,6 +5,7 @@ using UnityExplorer.Core.Config;
|
|||||||
using UnityExplorer.Core.Input;
|
using UnityExplorer.Core.Input;
|
||||||
using UnityExplorer.Core.Runtime;
|
using UnityExplorer.Core.Runtime;
|
||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
|
using UnityExplorer.UI.Inspectors;
|
||||||
using UnityExplorer.UI.Main;
|
using UnityExplorer.UI.Main;
|
||||||
|
|
||||||
namespace UnityExplorer
|
namespace UnityExplorer
|
||||||
@ -12,7 +13,7 @@ namespace UnityExplorer
|
|||||||
public class ExplorerCore
|
public class ExplorerCore
|
||||||
{
|
{
|
||||||
public const string NAME = "UnityExplorer";
|
public const string NAME = "UnityExplorer";
|
||||||
public const string VERSION = "3.3.3";
|
public const string VERSION = "3.3.6";
|
||||||
public const string AUTHOR = "Sinai";
|
public const string AUTHOR = "Sinai";
|
||||||
public const string GUID = "com.sinai.unityexplorer";
|
public const string GUID = "com.sinai.unityexplorer";
|
||||||
|
|
||||||
@ -46,6 +47,8 @@ namespace UnityExplorer
|
|||||||
UIManager.Init();
|
UIManager.Init();
|
||||||
|
|
||||||
Log($"{NAME} {VERSION} initialized.");
|
Log($"{NAME} {VERSION} initialized.");
|
||||||
|
|
||||||
|
// InspectorManager.Instance.Inspect(typeof(TestClass));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Update()
|
public static void Update()
|
||||||
|
@ -10,6 +10,9 @@ using System.Text;
|
|||||||
using UnityExplorer.Core.Config;
|
using UnityExplorer.Core.Config;
|
||||||
using UnityExplorer.Loader.BIE;
|
using UnityExplorer.Loader.BIE;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using UnityExplorer.Core;
|
||||||
|
using UnityEngine.EventSystems;
|
||||||
|
using UnityExplorer.Core.Input;
|
||||||
#if CPP
|
#if CPP
|
||||||
using BepInEx.IL2CPP;
|
using BepInEx.IL2CPP;
|
||||||
using UnhollowerRuntimeLib;
|
using UnhollowerRuntimeLib;
|
||||||
@ -75,10 +78,8 @@ namespace UnityExplorer
|
|||||||
|
|
||||||
ClassInjector.RegisterTypeInIl2Cpp<ExplorerBehaviour>();
|
ClassInjector.RegisterTypeInIl2Cpp<ExplorerBehaviour>();
|
||||||
|
|
||||||
var obj = new GameObject(
|
var obj = new GameObject("ExplorerBehaviour");
|
||||||
"ExplorerBehaviour",
|
obj.AddComponent<ExplorerBehaviour>();
|
||||||
new Il2CppSystem.Type[] { Il2CppType.Of<ExplorerBehaviour>() }
|
|
||||||
);
|
|
||||||
obj.hideFlags = HideFlags.HideAndDontSave;
|
obj.hideFlags = HideFlags.HideAndDontSave;
|
||||||
GameObject.DontDestroyOnLoad(obj);
|
GameObject.DontDestroyOnLoad(obj);
|
||||||
|
|
||||||
@ -101,6 +102,48 @@ namespace UnityExplorer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
public void SetupPatches()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.HarmonyInstance.PatchAll();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
ExplorerCore.Log($"Exception setting up Harmony patches:\r\n{ex.ReflectionExToString()}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPatch(typeof(EventSystem), "current", MethodType.Setter)]
|
||||||
|
public class PATCH_EventSystem_current
|
||||||
|
{
|
||||||
|
[HarmonyPrefix]
|
||||||
|
public static void Prefix_EventSystem_set_current(ref EventSystem value)
|
||||||
|
{
|
||||||
|
CursorUnlocker.Prefix_EventSystem_set_current(ref value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPatch(typeof(Cursor), "lockState", MethodType.Setter)]
|
||||||
|
public class PATCH_Cursor_lockState
|
||||||
|
{
|
||||||
|
[HarmonyPrefix]
|
||||||
|
public static void Prefix_set_lockState(ref CursorLockMode value)
|
||||||
|
{
|
||||||
|
CursorUnlocker.Prefix_set_lockState(ref value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPatch(typeof(Cursor), "visible", MethodType.Setter)]
|
||||||
|
public class PATCH_Cursor_visible
|
||||||
|
{
|
||||||
|
[HarmonyPrefix]
|
||||||
|
public static void Prefix_set_visible(ref bool value)
|
||||||
|
{
|
||||||
|
CursorUnlocker.Prefix_set_visible(ref value);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
@ -17,10 +17,6 @@ namespace UnityExplorer
|
|||||||
Action<object> OnLogWarning { get; }
|
Action<object> OnLogWarning { get; }
|
||||||
Action<object> OnLogError { get; }
|
Action<object> OnLogError { get; }
|
||||||
|
|
||||||
#if ML
|
void SetupPatches();
|
||||||
Harmony.HarmonyInstance HarmonyInstance { get; }
|
|
||||||
#else
|
|
||||||
HarmonyLib.Harmony HarmonyInstance { get; }
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,14 @@
|
|||||||
#if ML
|
#if ML
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using Harmony;
|
||||||
using MelonLoader;
|
using MelonLoader;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using UnityEngine.EventSystems;
|
||||||
using UnityExplorer;
|
using UnityExplorer;
|
||||||
|
using UnityExplorer.Core;
|
||||||
using UnityExplorer.Core.Config;
|
using UnityExplorer.Core.Config;
|
||||||
|
using UnityExplorer.Core.Input;
|
||||||
using UnityExplorer.Loader.ML;
|
using UnityExplorer.Loader.ML;
|
||||||
|
|
||||||
[assembly: MelonInfo(typeof(ExplorerMelonMod), ExplorerCore.NAME, ExplorerCore.VERSION, ExplorerCore.AUTHOR)]
|
[assembly: MelonInfo(typeof(ExplorerMelonMod), ExplorerCore.NAME, ExplorerCore.VERSION, ExplorerCore.AUTHOR)]
|
||||||
@ -40,6 +44,41 @@ namespace UnityExplorer
|
|||||||
{
|
{
|
||||||
ExplorerCore.Update();
|
ExplorerCore.Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SetupPatches()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
PrefixProperty(typeof(Cursor),
|
||||||
|
"lockState",
|
||||||
|
new HarmonyMethod(typeof(CursorUnlocker).GetMethod(nameof(CursorUnlocker.Prefix_set_lockState))));
|
||||||
|
|
||||||
|
PrefixProperty(typeof(Cursor),
|
||||||
|
"visible",
|
||||||
|
new HarmonyMethod(typeof(CursorUnlocker).GetMethod(nameof(CursorUnlocker.Prefix_set_visible))));
|
||||||
|
|
||||||
|
PrefixProperty(typeof(EventSystem),
|
||||||
|
"current",
|
||||||
|
new HarmonyMethod(typeof(CursorUnlocker).GetMethod(nameof(CursorUnlocker.Prefix_EventSystem_set_current))));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
ExplorerCore.Log($"Exception setting up Harmony patches:\r\n{ex.ReflectionExToString()}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PrefixProperty(Type type, string property, HarmonyMethod prefix)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var prop = type.GetProperty(property);
|
||||||
|
this.Harmony.Patch(prop.GetSetMethod(), prefix: prefix);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ExplorerCore.Log($"Unable to patch {type.Name}.set_{property}: {e.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
@ -21,8 +21,12 @@ namespace UnityExplorer.Loader.ML
|
|||||||
{
|
{
|
||||||
prefCategory = MelonPreferences.CreateCategory(CTG_NAME, $"{CTG_NAME} Settings");
|
prefCategory = MelonPreferences.CreateCategory(CTG_NAME, $"{CTG_NAME} Settings");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
MelonPreferences.Mapper.RegisterMapper(KeycodeReader, KeycodeWriter);
|
MelonPreferences.Mapper.RegisterMapper(KeycodeReader, KeycodeWriter);
|
||||||
}
|
}
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
|
|
||||||
public override void LoadConfig()
|
public override void LoadConfig()
|
||||||
{
|
{
|
||||||
|
@ -6,6 +6,9 @@ using System.Reflection;
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityExplorer.Core.Config;
|
using UnityExplorer.Core.Config;
|
||||||
using UnityExplorer.Loader.STANDALONE;
|
using UnityExplorer.Loader.STANDALONE;
|
||||||
|
using UnityEngine.EventSystems;
|
||||||
|
using UnityExplorer.Core.Input;
|
||||||
|
using UnityExplorer.Core;
|
||||||
#if CPP
|
#if CPP
|
||||||
using UnhollowerRuntimeLib;
|
using UnhollowerRuntimeLib;
|
||||||
#endif
|
#endif
|
||||||
@ -86,17 +89,9 @@ namespace UnityExplorer
|
|||||||
|
|
||||||
#if CPP
|
#if CPP
|
||||||
ClassInjector.RegisterTypeInIl2Cpp<ExplorerBehaviour>();
|
ClassInjector.RegisterTypeInIl2Cpp<ExplorerBehaviour>();
|
||||||
|
|
||||||
var obj = new GameObject(
|
|
||||||
"ExplorerBehaviour",
|
|
||||||
new Il2CppSystem.Type[] { Il2CppType.Of<ExplorerBehaviour>() }
|
|
||||||
);
|
|
||||||
#else
|
|
||||||
var obj = new GameObject(
|
|
||||||
"ExplorerBehaviour",
|
|
||||||
new Type[] { typeof(ExplorerBehaviour) }
|
|
||||||
);
|
|
||||||
#endif
|
#endif
|
||||||
|
var obj = new GameObject("ExplorerBehaviour");
|
||||||
|
obj.AddComponent<ExplorerBehaviour>();
|
||||||
|
|
||||||
GameObject.DontDestroyOnLoad(obj);
|
GameObject.DontDestroyOnLoad(obj);
|
||||||
obj.hideFlags = HideFlags.HideAndDontSave;
|
obj.hideFlags = HideFlags.HideAndDontSave;
|
||||||
@ -114,6 +109,48 @@ namespace UnityExplorer
|
|||||||
ExplorerCore.Update();
|
ExplorerCore.Update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SetupPatches()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.HarmonyInstance.PatchAll();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
ExplorerCore.Log($"Exception setting up Harmony patches:\r\n{ex.ReflectionExToString()}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPatch(typeof(EventSystem), "current", MethodType.Setter)]
|
||||||
|
public class PATCH_EventSystem_current
|
||||||
|
{
|
||||||
|
[HarmonyPrefix]
|
||||||
|
public static void Prefix_EventSystem_set_current(ref EventSystem value)
|
||||||
|
{
|
||||||
|
CursorUnlocker.Prefix_EventSystem_set_current(ref value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPatch(typeof(Cursor), "lockState", MethodType.Setter)]
|
||||||
|
public class PATCH_Cursor_lockState
|
||||||
|
{
|
||||||
|
[HarmonyPrefix]
|
||||||
|
public static void Prefix_set_lockState(ref CursorLockMode value)
|
||||||
|
{
|
||||||
|
CursorUnlocker.Prefix_set_lockState(ref value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPatch(typeof(Cursor), "visible", MethodType.Setter)]
|
||||||
|
public class PATCH_Cursor_visible
|
||||||
|
{
|
||||||
|
[HarmonyPrefix]
|
||||||
|
public static void Prefix_set_visible(ref bool value)
|
||||||
|
{
|
||||||
|
CursorUnlocker.Prefix_set_visible(ref value);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
@ -10,7 +10,7 @@ using UnityExplorer.Core.Runtime;
|
|||||||
using UnityExplorer.Core;
|
using UnityExplorer.Core;
|
||||||
using UnityExplorer.UI.Utility;
|
using UnityExplorer.UI.Utility;
|
||||||
using UnityExplorer.UI.InteractiveValues;
|
using UnityExplorer.UI.InteractiveValues;
|
||||||
using UnityExplorer.UI.Main.Home.Inspectors.Reflection;
|
using UnityExplorer.UI.Inspectors.Reflection;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.CacheObject
|
namespace UnityExplorer.UI.CacheObject
|
||||||
{
|
{
|
||||||
@ -86,7 +86,7 @@ namespace UnityExplorer.UI.CacheObject
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Type baseType = ReflectionUtility.GetType(IValue.Value) ?? FallbackType;
|
Type baseType = ReflectionUtility.GetActualType(IValue.Value) ?? FallbackType;
|
||||||
|
|
||||||
if (!ReflectionProvider.Instance.IsReflectionSupported(baseType))
|
if (!ReflectionProvider.Instance.IsReflectionSupported(baseType))
|
||||||
throw new Exception("Type not supported with reflection");
|
throw new Exception("Type not supported with reflection");
|
||||||
@ -94,7 +94,7 @@ namespace UnityExplorer.UI.CacheObject
|
|||||||
UpdateReflection();
|
UpdateReflection();
|
||||||
|
|
||||||
if (IValue.Value != null)
|
if (IValue.Value != null)
|
||||||
IValue.Value = IValue.Value.Cast(ReflectionUtility.GetType(IValue.Value));
|
IValue.Value = IValue.Value.Cast(ReflectionUtility.GetActualType(IValue.Value));
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
@ -55,7 +55,7 @@ namespace UnityExplorer.UI.CacheObject
|
|||||||
// if the type has changed fundamentally, make a new interactivevalue for it
|
// if the type has changed fundamentally, make a new interactivevalue for it
|
||||||
var type = value == null
|
var type = value == null
|
||||||
? FallbackType
|
? FallbackType
|
||||||
: ReflectionUtility.GetType(value);
|
: ReflectionUtility.GetActualType(value);
|
||||||
|
|
||||||
var ivalueType = InteractiveValue.GetIValueForType(type);
|
var ivalueType = InteractiveValue.GetIValueForType(type);
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ using UnityEngine.UI;
|
|||||||
using UnityExplorer.Core.Runtime;
|
using UnityExplorer.Core.Runtime;
|
||||||
using UnityExplorer.UI.Utility;
|
using UnityExplorer.UI.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Main.Home.Inspectors.GameObjects
|
namespace UnityExplorer.UI.Inspectors.GameObjects
|
||||||
{
|
{
|
||||||
public class ChildList
|
public class ChildList
|
||||||
{
|
{
|
@ -8,7 +8,7 @@ using UnityExplorer.Core;
|
|||||||
using UnityExplorer.Core.Runtime;
|
using UnityExplorer.Core.Runtime;
|
||||||
using UnityExplorer.UI.Utility;
|
using UnityExplorer.UI.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Main.Home.Inspectors.GameObjects
|
namespace UnityExplorer.UI.Inspectors.GameObjects
|
||||||
{
|
{
|
||||||
public class ComponentList
|
public class ComponentList
|
||||||
{
|
{
|
||||||
@ -75,7 +75,7 @@ namespace UnityExplorer.UI.Main.Home.Inspectors.GameObjects
|
|||||||
|
|
||||||
var text = s_compListTexts[i];
|
var text = s_compListTexts[i];
|
||||||
|
|
||||||
text.text = SignatureHighlighter.ParseFullSyntax(ReflectionUtility.GetType(comp), true);
|
text.text = SignatureHighlighter.ParseFullSyntax(ReflectionUtility.GetActualType(comp), true);
|
||||||
|
|
||||||
var toggle = s_compToggles[i];
|
var toggle = s_compToggles[i];
|
||||||
#if CPP
|
#if CPP
|
@ -8,7 +8,7 @@ using UnityExplorer.Core.Input;
|
|||||||
using UnityExplorer.Core.Runtime;
|
using UnityExplorer.Core.Runtime;
|
||||||
using UnityExplorer.Core.Unity;
|
using UnityExplorer.Core.Unity;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Main.Home.Inspectors.GameObjects
|
namespace UnityExplorer.UI.Inspectors.GameObjects
|
||||||
{
|
{
|
||||||
public class GameObjectControls
|
public class GameObjectControls
|
||||||
{
|
{
|
@ -7,7 +7,7 @@ using UnityEngine.UI;
|
|||||||
using UnityExplorer.Core.Runtime;
|
using UnityExplorer.Core.Runtime;
|
||||||
using UnityExplorer.Core.Unity;
|
using UnityExplorer.Core.Unity;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Main.Home.Inspectors.GameObjects
|
namespace UnityExplorer.UI.Inspectors.GameObjects
|
||||||
{
|
{
|
||||||
public class GameObjectInspector : InspectorBase
|
public class GameObjectInspector : InspectorBase
|
||||||
{
|
{
|
@ -11,6 +11,7 @@ using UnityExplorer.Core.Input;
|
|||||||
using UnityExplorer.Core.Runtime;
|
using UnityExplorer.Core.Runtime;
|
||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
using UnityExplorer.UI.Main;
|
using UnityExplorer.UI.Main;
|
||||||
|
using UnityExplorer.UI.Inspectors;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Main.Home
|
namespace UnityExplorer.UI.Main.Home
|
||||||
{
|
{
|
@ -3,7 +3,7 @@ using UnityEngine;
|
|||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.Core.Unity;
|
using UnityExplorer.Core.Unity;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Main.Home.Inspectors
|
namespace UnityExplorer.UI.Inspectors
|
||||||
{
|
{
|
||||||
public abstract class InspectorBase
|
public abstract class InspectorBase
|
||||||
{
|
{
|
@ -9,12 +9,11 @@ using UnityEngine.SceneManagement;
|
|||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.Core.Runtime;
|
using UnityExplorer.Core.Runtime;
|
||||||
using UnityExplorer.UI.Main.Home;
|
using UnityExplorer.UI.Main.Home;
|
||||||
using UnityExplorer.UI.Main.Home.Inspectors;
|
|
||||||
using UnityExplorer.UI.CacheObject;
|
using UnityExplorer.UI.CacheObject;
|
||||||
using UnityExplorer.UI.Main.Home.Inspectors.GameObjects;
|
using UnityExplorer.UI.Inspectors.GameObjects;
|
||||||
using UnityExplorer.UI.Main.Home.Inspectors.Reflection;
|
using UnityExplorer.UI.Inspectors.Reflection;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Main.Home
|
namespace UnityExplorer.UI.Inspectors
|
||||||
{
|
{
|
||||||
public class InspectorManager
|
public class InspectorManager
|
||||||
{
|
{
|
@ -9,7 +9,7 @@ using UnityExplorer.Core;
|
|||||||
using UnityExplorer.Core.Config;
|
using UnityExplorer.Core.Config;
|
||||||
using UnityExplorer.Core.Runtime;
|
using UnityExplorer.Core.Runtime;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Main.Home.Inspectors.Reflection
|
namespace UnityExplorer.UI.Inspectors.Reflection
|
||||||
{
|
{
|
||||||
public enum MemberScopes
|
public enum MemberScopes
|
||||||
{
|
{
|
@ -9,9 +9,11 @@ using UnityExplorer.Core;
|
|||||||
using UnityExplorer.Core.Config;
|
using UnityExplorer.Core.Config;
|
||||||
using UnityExplorer.Core.Runtime;
|
using UnityExplorer.Core.Runtime;
|
||||||
using UnityExplorer.UI.CacheObject;
|
using UnityExplorer.UI.CacheObject;
|
||||||
|
using UnityExplorer.UI.Main;
|
||||||
|
using UnityExplorer.UI.Main.Home;
|
||||||
using UnityExplorer.UI.Utility;
|
using UnityExplorer.UI.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Main.Home.Inspectors.Reflection
|
namespace UnityExplorer.UI.Inspectors.Reflection
|
||||||
{
|
{
|
||||||
public class ReflectionInspector : InspectorBase
|
public class ReflectionInspector : InspectorBase
|
||||||
{
|
{
|
||||||
@ -78,7 +80,7 @@ namespace UnityExplorer.UI.Main.Home.Inspectors.Reflection
|
|||||||
if (this is StaticInspector)
|
if (this is StaticInspector)
|
||||||
m_targetType = target as Type;
|
m_targetType = target as Type;
|
||||||
else
|
else
|
||||||
m_targetType = ReflectionUtility.GetType(target);
|
m_targetType = ReflectionUtility.GetActualType(target);
|
||||||
|
|
||||||
m_targetTypeShortName = SignatureHighlighter.ParseFullSyntax(m_targetType, false);
|
m_targetTypeShortName = SignatureHighlighter.ParseFullSyntax(m_targetType, false);
|
||||||
|
|
@ -3,7 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Main.Home.Inspectors.Reflection
|
namespace UnityExplorer.UI.Inspectors.Reflection
|
||||||
{
|
{
|
||||||
public class StaticInspector : ReflectionInspector
|
public class StaticInspector : ReflectionInspector
|
||||||
{
|
{
|
@ -218,32 +218,37 @@ namespace UnityExplorer.UI.InteractiveValues
|
|||||||
|
|
||||||
private IDictionary EnumerateWithReflection()
|
private IDictionary EnumerateWithReflection()
|
||||||
{
|
{
|
||||||
var valueType = ReflectionUtility.GetType(Value);
|
var valueType = ReflectionUtility.GetActualType(Value);
|
||||||
|
|
||||||
// get keys and values
|
|
||||||
var keys = valueType.GetProperty("Keys").GetValue(Value, null);
|
|
||||||
var values = valueType.GetProperty("Values").GetValue(Value, null);
|
|
||||||
|
|
||||||
// create lists to hold them
|
|
||||||
var keyList = new List<object>();
|
var keyList = new List<object>();
|
||||||
var valueList = new List<object>();
|
var valueList = new List<object>();
|
||||||
|
|
||||||
// store entries with reflection
|
var hashtable = Value.Cast(typeof(Il2CppSystem.Collections.Hashtable)) as Il2CppSystem.Collections.Hashtable;
|
||||||
EnumerateCollection(keys, keyList);
|
|
||||||
EnumerateCollection(values, valueList);
|
|
||||||
|
|
||||||
// make actual mono dictionary
|
if (hashtable != null)
|
||||||
var dict = (IDictionary)Activator.CreateInstance(typeof(Dictionary<,>)
|
{
|
||||||
.MakeGenericType(m_typeOfKeys, m_typeofValues));
|
EnumerateCppHashtable(hashtable, keyList, valueList);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var keys = valueType.GetProperty("Keys").GetValue(Value, null);
|
||||||
|
var values = valueType.GetProperty("Values").GetValue(Value, null);
|
||||||
|
|
||||||
|
EnumerateCppIDictionary(keys, keyList);
|
||||||
|
EnumerateCppIDictionary(values, valueList);
|
||||||
|
}
|
||||||
|
|
||||||
|
var dict = Activator.CreateInstance(typeof(Dictionary<,>)
|
||||||
|
.MakeGenericType(m_typeOfKeys, m_typeofValues))
|
||||||
|
as IDictionary;
|
||||||
|
|
||||||
// finally iterate into mono dictionary
|
|
||||||
for (int i = 0; i < keyList.Count; i++)
|
for (int i = 0; i < keyList.Count; i++)
|
||||||
dict.Add(keyList[i], valueList[i]);
|
dict.Add(keyList[i], valueList[i]);
|
||||||
|
|
||||||
return dict;
|
return dict;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void EnumerateCollection(object collection, List<object> list)
|
private void EnumerateCppIDictionary(object collection, List<object> list)
|
||||||
{
|
{
|
||||||
// invoke GetEnumerator
|
// invoke GetEnumerator
|
||||||
var enumerator = collection.GetType().GetMethod("GetEnumerator").Invoke(collection, null);
|
var enumerator = collection.GetType().GetMethod("GetEnumerator").Invoke(collection, null);
|
||||||
@ -258,11 +263,23 @@ namespace UnityExplorer.UI.InteractiveValues
|
|||||||
list.Add(current.GetValue(enumerator, null));
|
list.Add(current.GetValue(enumerator, null));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void EnumerateCppHashtable(Il2CppSystem.Collections.Hashtable hashtable, List<object> keys, List<object> values)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < hashtable.buckets.Count; i++)
|
||||||
|
{
|
||||||
|
var bucket = hashtable.buckets[i];
|
||||||
|
if (bucket == null || bucket.key == null)
|
||||||
|
continue;
|
||||||
|
keys.Add(bucket.key);
|
||||||
|
values.Add(bucket.val);
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region UI CONSTRUCTION
|
#region UI CONSTRUCTION
|
||||||
|
|
||||||
internal GameObject m_listContent;
|
internal GameObject m_listContent;
|
||||||
internal LayoutElement m_listLayout;
|
internal LayoutElement m_listLayout;
|
||||||
|
@ -6,6 +6,7 @@ using System.Reflection;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
|
using UnityExplorer.Core;
|
||||||
using UnityExplorer.Core.Config;
|
using UnityExplorer.Core.Config;
|
||||||
using UnityExplorer.Core.Unity;
|
using UnityExplorer.Core.Unity;
|
||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
@ -38,11 +39,11 @@ namespace UnityExplorer.UI.InteractiveValues
|
|||||||
|
|
||||||
internal IEnumerable RefIEnumerable;
|
internal IEnumerable RefIEnumerable;
|
||||||
internal IList RefIList;
|
internal IList RefIList;
|
||||||
#if CPP
|
//#if CPP
|
||||||
internal Il2CppSystem.Collections.ICollection CppICollection;
|
// internal object CppICollection;
|
||||||
#else
|
//#else
|
||||||
internal ICollection CppICollection = null;
|
// internal object CppICollection = null;
|
||||||
#endif
|
//#endif
|
||||||
|
|
||||||
internal readonly Type m_baseEntryType;
|
internal readonly Type m_baseEntryType;
|
||||||
|
|
||||||
@ -55,13 +56,17 @@ namespace UnityExplorer.UI.InteractiveValues
|
|||||||
RefIEnumerable = Value as IEnumerable;
|
RefIEnumerable = Value as IEnumerable;
|
||||||
RefIList = Value as IList;
|
RefIList = Value as IList;
|
||||||
|
|
||||||
#if CPP
|
//#if CPP
|
||||||
if (Value != null && RefIList == null)
|
// if (Value != null && RefIList == null)
|
||||||
{
|
// {
|
||||||
try { CppICollection = (Value as Il2CppSystem.Object).TryCast<Il2CppSystem.Collections.ICollection>(); }
|
// try
|
||||||
catch { }
|
// {
|
||||||
}
|
// var type = typeof(Il2CppSystem.Collections.ICollection).MakeGenericType(this.m_baseEntryType);
|
||||||
#endif
|
// CppICollection = (Value as Il2CppSystem.Object).Cast(type);
|
||||||
|
// }
|
||||||
|
// catch { }
|
||||||
|
// }
|
||||||
|
//#endif
|
||||||
|
|
||||||
if (m_subContentParent.activeSelf)
|
if (m_subContentParent.activeSelf)
|
||||||
{
|
{
|
||||||
@ -91,8 +96,8 @@ namespace UnityExplorer.UI.InteractiveValues
|
|||||||
if (Value != null)
|
if (Value != null)
|
||||||
{
|
{
|
||||||
string count = "?";
|
string count = "?";
|
||||||
if (m_recacheWanted && (RefIList != null || CppICollection != null))
|
if (m_recacheWanted && RefIList != null)// || CppICollection != null))
|
||||||
count = RefIList?.Count.ToString() ?? CppICollection.Count.ToString();
|
count = RefIList.Count.ToString();// ?? CppICollection.Count.ToString();
|
||||||
else if (!m_recacheWanted)
|
else if (!m_recacheWanted)
|
||||||
count = m_entries.Count.ToString();
|
count = m_entries.Count.ToString();
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ using UnityExplorer.Core.Unity;
|
|||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
using UnityExplorer.UI.Utility;
|
using UnityExplorer.UI.Utility;
|
||||||
using UnityExplorer.UI.CacheObject;
|
using UnityExplorer.UI.CacheObject;
|
||||||
|
using UnityExplorer.Core.Runtime;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.InteractiveValues
|
namespace UnityExplorer.UI.InteractiveValues
|
||||||
{
|
{
|
||||||
@ -23,6 +24,14 @@ namespace UnityExplorer.UI.InteractiveValues
|
|||||||
|
|
||||||
public override void OnValueUpdated()
|
public override void OnValueUpdated()
|
||||||
{
|
{
|
||||||
|
#if CPP
|
||||||
|
// strings boxed as Il2CppSystem.Objects can behave weirdly.
|
||||||
|
// GetActualType will find they are a string, but if its boxed
|
||||||
|
// then we need to unbox it like this...
|
||||||
|
if (!(Value is string) && Value is Il2CppSystem.Object cppobj)
|
||||||
|
Value = cppobj.ToString();
|
||||||
|
#endif
|
||||||
|
|
||||||
base.OnValueUpdated();
|
base.OnValueUpdated();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,10 +97,18 @@ namespace UnityExplorer.UI.InteractiveValues
|
|||||||
m_labelLayout.flexibleWidth = 0;
|
m_labelLayout.flexibleWidth = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void OnApplyClicked()
|
internal void SetValueFromInput()
|
||||||
{
|
{
|
||||||
Value = m_valueInput.text;
|
Value = m_valueInput.text;
|
||||||
|
|
||||||
|
if (!typeof(string).IsAssignableFrom(Owner.FallbackType))
|
||||||
|
ReflectionProvider.Instance.BoxStringToType(ref Value, Owner.FallbackType);
|
||||||
|
|
||||||
Owner.SetValue();
|
Owner.SetValue();
|
||||||
|
|
||||||
|
// revert back to string now
|
||||||
|
OnValueUpdated();
|
||||||
|
|
||||||
RefreshUIForValue();
|
RefreshUIForValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -162,7 +179,7 @@ namespace UnityExplorer.UI.InteractiveValues
|
|||||||
|
|
||||||
if (Owner.CanWrite)
|
if (Owner.CanWrite)
|
||||||
{
|
{
|
||||||
var apply = UIFactory.CreateButton(groupObj, "ApplyButton", "Apply", OnApplyClicked, new Color(0.2f, 0.2f, 0.2f));
|
var apply = UIFactory.CreateButton(groupObj, "ApplyButton", "Apply", SetValueFromInput, new Color(0.2f, 0.2f, 0.2f));
|
||||||
UIFactory.SetLayoutElement(apply.gameObject, minWidth: 50, minHeight: 25, flexibleWidth: 0);
|
UIFactory.SetLayoutElement(apply.gameObject, minWidth: 50, minHeight: 25, flexibleWidth: 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -12,6 +12,7 @@ using UnityExplorer.UI;
|
|||||||
using UnityExplorer.UI.Utility;
|
using UnityExplorer.UI.Utility;
|
||||||
using UnityExplorer.UI.CacheObject;
|
using UnityExplorer.UI.CacheObject;
|
||||||
using UnityExplorer.UI.Main.Home;
|
using UnityExplorer.UI.Main.Home;
|
||||||
|
using UnityExplorer.UI.Inspectors;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.InteractiveValues
|
namespace UnityExplorer.UI.InteractiveValues
|
||||||
{
|
{
|
||||||
@ -66,7 +67,7 @@ namespace UnityExplorer.UI.InteractiveValues
|
|||||||
|
|
||||||
public static InteractiveValue Create(object value, Type fallbackType)
|
public static InteractiveValue Create(object value, Type fallbackType)
|
||||||
{
|
{
|
||||||
var type = ReflectionUtility.GetType(value) ?? fallbackType;
|
var type = ReflectionUtility.GetActualType(value) ?? fallbackType;
|
||||||
var iType = GetIValueForType(type);
|
var iType = GetIValueForType(type);
|
||||||
|
|
||||||
return (InteractiveValue)Activator.CreateInstance(iType, new object[] { value, type });
|
return (InteractiveValue)Activator.CreateInstance(iType, new object[] { value, type });
|
||||||
|
@ -217,7 +217,6 @@ namespace UnityExplorer.UI.Main
|
|||||||
{
|
{
|
||||||
LogUnity = val;
|
LogUnity = val;
|
||||||
ConfigManager.Log_Unity_Debug.Value = val;
|
ConfigManager.Log_Unity_Debug.Value = val;
|
||||||
ConfigManager.Handler.SaveConfig();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
ConfigManager.Log_Unity_Debug.OnValueChanged += (bool val) => { unityToggle.isOn = val; };
|
ConfigManager.Log_Unity_Debug.OnValueChanged += (bool val) => { unityToggle.isOn = val; };
|
||||||
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
|
using UnityExplorer.UI.Inspectors;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Main.Home
|
namespace UnityExplorer.UI.Main.Home
|
||||||
{
|
{
|
||||||
|
@ -13,6 +13,7 @@ using UnityExplorer.UI.Utility;
|
|||||||
using UnityExplorer.UI.Main.Search;
|
using UnityExplorer.UI.Main.Search;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using UnityExplorer.Core;
|
using UnityExplorer.Core;
|
||||||
|
using UnityExplorer.UI.Inspectors;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Main.Home
|
namespace UnityExplorer.UI.Main.Home
|
||||||
{
|
{
|
||||||
|
@ -10,6 +10,7 @@ using UnityExplorer.Core;
|
|||||||
using UnityExplorer.UI.Utility;
|
using UnityExplorer.UI.Utility;
|
||||||
using UnityExplorer.Core.Search;
|
using UnityExplorer.Core.Search;
|
||||||
using UnityExplorer.UI.Main.Home;
|
using UnityExplorer.UI.Main.Home;
|
||||||
|
using UnityExplorer.UI.Inspectors;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Main.Search
|
namespace UnityExplorer.UI.Main.Search
|
||||||
{
|
{
|
||||||
@ -129,7 +130,7 @@ namespace UnityExplorer.UI.Main.Search
|
|||||||
|
|
||||||
if (m_context != SearchContext.StaticClass)
|
if (m_context != SearchContext.StaticClass)
|
||||||
{
|
{
|
||||||
var name = SignatureHighlighter.ParseFullSyntax(ReflectionUtility.GetType(obj), true);
|
var name = SignatureHighlighter.ParseFullSyntax(ReflectionUtility.GetActualType(obj), true);
|
||||||
|
|
||||||
if (unityObj && m_context != SearchContext.Singleton)
|
if (unityObj && m_context != SearchContext.Singleton)
|
||||||
{
|
{
|
||||||
|
@ -246,6 +246,7 @@
|
|||||||
<Compile Include="Core\Search\SceneFilter.cs" />
|
<Compile Include="Core\Search\SceneFilter.cs" />
|
||||||
<Compile Include="Core\Search\SearchContext.cs" />
|
<Compile Include="Core\Search\SearchContext.cs" />
|
||||||
<Compile Include="Core\Search\SearchProvider.cs" />
|
<Compile Include="Core\Search\SearchProvider.cs" />
|
||||||
|
<Compile Include="Core\TestClass.cs" />
|
||||||
<Compile Include="Core\Unity\UnityHelpers.cs" />
|
<Compile Include="Core\Unity\UnityHelpers.cs" />
|
||||||
<Compile Include="Loader\BIE\BepInExConfigHandler.cs" />
|
<Compile Include="Loader\BIE\BepInExConfigHandler.cs" />
|
||||||
<Compile Include="Loader\BIE\ExplorerBepInPlugin.cs" />
|
<Compile Include="Loader\BIE\ExplorerBepInPlugin.cs" />
|
||||||
@ -286,16 +287,16 @@
|
|||||||
<Compile Include="UI\Main\CSConsole\Lexer\SymbolMatch.cs" />
|
<Compile Include="UI\Main\CSConsole\Lexer\SymbolMatch.cs" />
|
||||||
<Compile Include="UI\Main\DebugConsole.cs" />
|
<Compile Include="UI\Main\DebugConsole.cs" />
|
||||||
<Compile Include="UI\Main\Home\HomePage.cs" />
|
<Compile Include="UI\Main\Home\HomePage.cs" />
|
||||||
<Compile Include="UI\Main\Home\InspectorManager.cs" />
|
<Compile Include="UI\Inspectors\InspectorManager.cs" />
|
||||||
<Compile Include="UI\Main\Home\Inspectors\GameObjects\ChildList.cs" />
|
<Compile Include="UI\Inspectors\GameObjects\ChildList.cs" />
|
||||||
<Compile Include="UI\Main\Home\Inspectors\GameObjects\ComponentList.cs" />
|
<Compile Include="UI\Inspectors\GameObjects\ComponentList.cs" />
|
||||||
<Compile Include="UI\Main\Home\Inspectors\GameObjects\GameObjectControls.cs" />
|
<Compile Include="UI\Inspectors\GameObjects\GameObjectControls.cs" />
|
||||||
<Compile Include="UI\Main\Home\Inspectors\GameObjects\GameObjectInspector.cs" />
|
<Compile Include="UI\Inspectors\GameObjects\GameObjectInspector.cs" />
|
||||||
<Compile Include="UI\Main\Home\Inspectors\InspectorBase.cs" />
|
<Compile Include="UI\Inspectors\InspectorBase.cs" />
|
||||||
<Compile Include="UI\Main\Home\Inspectors\Reflection\InstanceInspector.cs" />
|
<Compile Include="UI\Inspectors\Reflection\InstanceInspector.cs" />
|
||||||
<Compile Include="UI\Main\Home\Inspectors\Reflection\ReflectionInspector.cs" />
|
<Compile Include="UI\Inspectors\Reflection\ReflectionInspector.cs" />
|
||||||
<Compile Include="UI\Main\Home\Inspectors\Reflection\StaticInspector.cs" />
|
<Compile Include="UI\Inspectors\Reflection\StaticInspector.cs" />
|
||||||
<Compile Include="UI\Main\Home\InspectUnderMouse.cs" />
|
<Compile Include="UI\Inspectors\InspectUnderMouse.cs" />
|
||||||
<Compile Include="UI\Main\Home\SceneExplorer.cs" />
|
<Compile Include="UI\Main\Home\SceneExplorer.cs" />
|
||||||
<Compile Include="UI\Main\MainMenu.cs" />
|
<Compile Include="UI\Main\MainMenu.cs" />
|
||||||
<Compile Include="UI\Main\Options\OptionsPage.cs" />
|
<Compile Include="UI\Main\Options\OptionsPage.cs" />
|
||||||
|
Reference in New Issue
Block a user