mirror of
https://github.com/sinai-dev/UnityExplorer.git
synced 2025-06-23 17:02:36 +08:00
Compare commits
119 Commits
Author | SHA1 | Date | |
---|---|---|---|
7a5570a070 | |||
d40537775f | |||
9b6f3fd3ea | |||
bacac929e9 | |||
4e3d3a2e5c | |||
7dbc8fd66e | |||
892cefcc91 | |||
a986b92963 | |||
8837119781 | |||
7eda249ddb | |||
710b4ba74a | |||
4bee55fb25 | |||
c71748d22a | |||
621035c732 | |||
2285a495be | |||
efdf2446bd | |||
6ad45ac8ae | |||
2d3c83cfa3 | |||
3213717ff6 | |||
a6a1a4d046 | |||
078c2e2b51 | |||
49bce650b4 | |||
bd9e80f2b4 | |||
d1eb5671bf | |||
f1ca484712 | |||
3b71b40843 | |||
1292affe6d | |||
6614762fe8 | |||
d81d6d034b | |||
5dfe3bbf0c | |||
dc81451ce5 | |||
d7ab0a23c6 | |||
1a01c740e2 | |||
040fb1f11a | |||
e44ff9e207 | |||
b5c69fc1ea | |||
4fdb2aacd8 | |||
48e688cb75 | |||
647b0d353d | |||
2b715f3dbe | |||
938a991594 | |||
f00134b283 | |||
3b6b9768fb | |||
5fbfa1b7aa | |||
7d26965c12 | |||
862523399a | |||
0afccadc64 | |||
0e37e8030c | |||
621a9cd72e | |||
56be5414f9 | |||
b8c4be473f | |||
b6966f8836 | |||
ad8c5293a0 | |||
a7165c849c | |||
79f2514109 | |||
4e76eca73a | |||
2f0876466c | |||
fdefc3d567 | |||
64193ff1b0 | |||
a90292f47f | |||
d0bccae50c | |||
bdf08f014f | |||
df8522963e | |||
f6d0acab7b | |||
d4fbc89158 | |||
9e49f09a79 | |||
b9a3ab7439 | |||
03661cdd0b | |||
10f2b7e849 | |||
4602f07c34 | |||
18bcfed434 | |||
c7d2ce6d36 | |||
f961add7f4 | |||
798b881dcb | |||
c90f339882 | |||
c351ce5a6d | |||
9985ed0fd8 | |||
f35232bb64 | |||
49cc1f7df3 | |||
9f78c50854 | |||
bc64a04339 | |||
7d961ce8ad | |||
c7d7569f71 | |||
ee8f33a754 | |||
a95d91c824 | |||
177b78f4e7 | |||
3804d0aab0 | |||
97a82c1661 | |||
96a1cc69fb | |||
589abe6193 | |||
91bb58b020 | |||
d67507ead2 | |||
d730fbe49c | |||
9e0784ce54 | |||
67c602b32f | |||
8fb7d87ca6 | |||
c740c3c54d | |||
ea7b91f7fd | |||
c79223f537 | |||
aae248bf69 | |||
a73e992a0c | |||
3984550bb6 | |||
7928363aeb | |||
12758606fa | |||
c927ac54be | |||
9f1df11940 | |||
62354b6aa2 | |||
44e57c32c3 | |||
274352d665 | |||
7b477a8b0e | |||
e585fc6da0 | |||
0dd19345ed | |||
0050cff185 | |||
5f1d635eb3 | |||
e0f7fad00e | |||
f92c215a88 | |||
d58a5df82c | |||
12dd85ecfd | |||
03fb165967 |
3
.github/FUNDING.yml
vendored
Normal file
3
.github/FUNDING.yml
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# These are supported funding model platforms
|
||||||
|
|
||||||
|
ko_fi: sinaidev
|
4
.github/workflows/dotnet.yml
vendored
4
.github/workflows/dotnet.yml
vendored
@ -28,15 +28,13 @@ jobs:
|
|||||||
nuget-api-key: ${{ secrets.NuGetAPIKey }}
|
nuget-api-key: ${{ secrets.NuGetAPIKey }}
|
||||||
nuget-version: '5.x'
|
nuget-version: '5.x'
|
||||||
|
|
||||||
# Build Il2CppAssemblyUnhollower
|
|
||||||
- run: msbuild lib\Il2CppAssemblyUnhollower\UnhollowerBaseLib\UnhollowerBaseLib.csproj -t:Restore -t:Rebuild -p:Platform="AnyCPU" -p:Configuration=Release
|
|
||||||
|
|
||||||
# Build mcs
|
# Build mcs
|
||||||
- run: nuget restore lib\mcs-unity\mcs.sln
|
- run: nuget restore lib\mcs-unity\mcs.sln
|
||||||
- run: msbuild lib\mcs-unity\mcs\mcs.csproj -t:Restore -t:Rebuild -p:Platform="AnyCPU" -p:Configuration=Release
|
- run: msbuild lib\mcs-unity\mcs\mcs.csproj -t:Restore -t:Rebuild -p:Platform="AnyCPU" -p:Configuration=Release
|
||||||
|
|
||||||
# Build UnityExplorer releases, and upload artifacts
|
# Build UnityExplorer releases, and upload artifacts
|
||||||
|
|
||||||
|
- run: dotnet nuget add source https://nuget.bepinex.dev/v3/index.json
|
||||||
- run: nuget restore src\UnityExplorer.sln
|
- run: nuget restore src\UnityExplorer.sln
|
||||||
|
|
||||||
# BepInEx Il2Cpp
|
# BepInEx Il2Cpp
|
||||||
|
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -1,6 +1,3 @@
|
|||||||
[submodule "lib/Il2CppAssemblyUnhollower"]
|
|
||||||
path = lib/Il2CppAssemblyUnhollower
|
|
||||||
url = https://github.com/knah/Il2CppAssemblyUnhollower
|
|
||||||
[submodule "lib/mcs-unity"]
|
[submodule "lib/mcs-unity"]
|
||||||
path = lib/mcs-unity
|
path = lib/mcs-unity
|
||||||
url = https://github.com/sinai-dev/mcs-unity
|
url = https://github.com/sinai-dev/mcs-unity
|
||||||
|
36
README.md
36
README.md
@ -25,7 +25,7 @@
|
|||||||
| BIE 6.X | ✅ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.BepInEx.Il2Cpp.zip) | ✅ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.BepInEx6.Mono.zip) |
|
| BIE 6.X | ✅ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.BepInEx.Il2Cpp.zip) | ✅ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.BepInEx6.Mono.zip) |
|
||||||
| BIE 5.X | ✖️ n/a | ✅ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.BepInEx5.Mono.zip) |
|
| BIE 5.X | ✖️ n/a | ✅ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.BepInEx5.Mono.zip) |
|
||||||
|
|
||||||
1. Take the `UnityExplorer.BIE.[version].dll` file and put it in `BepInEx\plugins\`
|
1. Take the `UnityExplorer.BIE.[version].dll` and the `UniverseLib.[version].dll` files and put them in `BepInEx\plugins\`
|
||||||
|
|
||||||
<i>Note: BepInEx 6 is obtainable via [BepisBuilds](https://builds.bepis.io/projects/bepinex_be)</i>
|
<i>Note: BepInEx 6 is obtainable via [BepisBuilds](https://builds.bepis.io/projects/bepinex_be)</i>
|
||||||
|
|
||||||
@ -35,7 +35,7 @@
|
|||||||
| ------- | ------ | ---- |
|
| ------- | ------ | ---- |
|
||||||
| ML 0.4+ | ✅ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.MelonLoader.Il2Cpp.zip) | ✅ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.MelonLoader.Mono.zip) |
|
| ML 0.4+ | ✅ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.MelonLoader.Il2Cpp.zip) | ✅ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.MelonLoader.Mono.zip) |
|
||||||
|
|
||||||
1. Take the `UnityExplorer.ML.[version].dll` file and put it in the `Mods\` folder created by MelonLoader.
|
1. Take the `UnityExplorer.ML.[version].dll` file and put them in the `Mods\` folder created by MelonLoader, and then put the `UniverseLib.[version].dll` file in the `UserLibs\` folder.
|
||||||
|
|
||||||
## Standalone
|
## Standalone
|
||||||
|
|
||||||
@ -43,13 +43,20 @@
|
|||||||
| ------ | ---- |
|
| ------ | ---- |
|
||||||
| ✅ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.Standalone.Il2Cpp.zip) | ✅ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.Standalone.Mono.zip) |
|
| ✅ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.Standalone.Il2Cpp.zip) | ✅ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.Standalone.Mono.zip) |
|
||||||
|
|
||||||
The standalone release can be used with any injector or loader of your choice, but it requires you to load the dependencies manually: HarmonyX, and the IL2CPP version also requires that you set up an [Il2CppAssemblyUnhollower runtime](https://github.com/knah/Il2CppAssemblyUnhollower#required-external-setup).
|
The standalone release can be used with any injector or loader of your choice, but it requires you to load the dependencies manually.
|
||||||
|
|
||||||
1. Load the required libs - UniverseLib, HarmonyX, and Il2CppAssemblyUnhollower if IL2CPP
|
1. Ensure the required libs are loaded - UniverseLib, HarmonyX and MonoMod. Take them from the [`UnityExplorer.Editor`](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.Editor.zip) release if you need them.
|
||||||
|
2. For IL2CPP, load Il2CppAssemblyUnhollower and start an [Il2CppAssemblyUnhollower runtime](https://github.com/knah/Il2CppAssemblyUnhollower#required-external-setup)
|
||||||
2. Load the UnityExplorer DLL
|
2. Load the UnityExplorer DLL
|
||||||
3. Create an instance of Unity Explorer with `UnityExplorer.ExplorerStandalone.CreateInstance();`
|
3. Create an instance of Unity Explorer with `UnityExplorer.ExplorerStandalone.CreateInstance();`
|
||||||
4. Optionally subscribe to the `ExplorerStandalone.OnLog` event to handle logging if you wish
|
4. Optionally subscribe to the `ExplorerStandalone.OnLog` event to handle logging if you wish
|
||||||
|
|
||||||
|
## Unity Editor
|
||||||
|
|
||||||
|
1. Download the [`UnityExplorer.Editor`](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.Editor.zip) release.
|
||||||
|
2. Install the package, either by using the Package Manager and importing the `package.json` file, or by manually dragging the folder into your `Assets` folder.
|
||||||
|
3. Drag the `Runtime/UnityExplorer` prefab into your scene, or create a GameObject and add the `Explorer Editor Behaviour` script to it.
|
||||||
|
|
||||||
# Common issues and solutions
|
# Common issues and solutions
|
||||||
|
|
||||||
Although UnityExplorer should work out of the box for most Unity games, in some cases you may need to tweak the settings for it to work properly.
|
Although UnityExplorer should work out of the box for most Unity games, in some cases you may need to tweak the settings for it to work properly.
|
||||||
@ -57,7 +64,7 @@ Although UnityExplorer should work out of the box for most Unity games, in some
|
|||||||
To adjust the settings, open the config file:
|
To adjust the settings, open the config file:
|
||||||
* BepInEx: `BepInEx\config\com.sinai.unityexplorer.cfg`
|
* BepInEx: `BepInEx\config\com.sinai.unityexplorer.cfg`
|
||||||
* MelonLoader: `UserData\MelonPreferences.cfg`
|
* MelonLoader: `UserData\MelonPreferences.cfg`
|
||||||
* Standalone: `UnityExplorer\config.ini`
|
* Standalone: `UnityExplorer\config.cfg`
|
||||||
|
|
||||||
Try adjusting the following settings and see if it fixes your issues:
|
Try adjusting the following settings and see if it fixes your issues:
|
||||||
* `Startup_Delay_Time` - increase to 5-10 seconds (or more as needed), can fix issues with UnityExplorer being destroyed or corrupted during startup.
|
* `Startup_Delay_Time` - increase to 5-10 seconds (or more as needed), can fix issues with UnityExplorer being destroyed or corrupted during startup.
|
||||||
@ -109,24 +116,30 @@ The inspector is used to see detailed information on objects of any type and man
|
|||||||
|
|
||||||
### Mouse-Inspect
|
### Mouse-Inspect
|
||||||
|
|
||||||
* The "Mouse Inspect" dropdown on the main UnityExplorer navbar allows you to inspect objects under the mouse.
|
* The "Mouse Inspect" dropdown in the "Inspector" panel allows you to inspect objects under the mouse.
|
||||||
* <b>World</b>: uses Physics.Raycast to look for Colliders
|
* <b>World</b>: uses Physics.Raycast to look for Colliders
|
||||||
* <b>UI</b>: uses GraphicRaycasters to find UI objects
|
* <b>UI</b>: uses GraphicRaycasters to find UI objects
|
||||||
|
|
||||||
|
### Clipboard
|
||||||
|
|
||||||
|
* The "Clipboard" panel allows you to see your current paste value, or clear it (resets it to `null`)
|
||||||
|
* Can copy the value from any member in a Reflection Inspector, Enumerable or Dictionary, and from the target of any Inspector tab
|
||||||
|
* Can paste values onto any member in a Reflection Inspector
|
||||||
|
* Non-parsable arguments in Method/Property Evaluators allow pasting values
|
||||||
|
* The C# Console has helper methods `Copy(obj)` and `Paste()` for accessing the Clipboard
|
||||||
|
|
||||||
### Settings
|
### Settings
|
||||||
|
|
||||||
* You can change the settings via the "Options" tab of the menu, or directly from the config file.
|
* You can change the settings via the "Options" tab of the menu, or directly from the config file.
|
||||||
* BepInEx: `BepInEx\config\com.sinai.unityexplorer.cfg`
|
* BepInEx: `BepInEx\config\com.sinai.unityexplorer.cfg`
|
||||||
* MelonLoader: `UserData\MelonPreferences.cfg`
|
* MelonLoader: `UserData\MelonPreferences.cfg`
|
||||||
* Standalone `{DLL_location}\UnityExplorer\config.ini`
|
* Standalone `{DLL_location}\UnityExplorer\config.cfg`
|
||||||
|
|
||||||
# Building
|
# Building
|
||||||
|
|
||||||
For Visual Studio:
|
|
||||||
|
|
||||||
0. Clone the repository and run `git submodule update --init --recursive` to get the submodules.
|
0. Clone the repository and run `git submodule update --init --recursive` to get the submodules.
|
||||||
1. Open the `src\UnityExplorer.sln` project.
|
1. Open the `src\UnityExplorer.sln` project.
|
||||||
2. Build `mcs` (Release/AnyCPU, you may need to run `nuget restore mcs.sln`), and if using IL2CPP then build `Il2CppAssemblyUnhollower` (Release/AnyCPU) as well.
|
2. Build `mcs` (Release/AnyCPU, you may need to run `nuget restore mcs.sln`)
|
||||||
3. Build the UnityExplorer release(s) you want to use, either by selecting the config as the Active Config, or batch-building.
|
3. Build the UnityExplorer release(s) you want to use, either by selecting the config as the Active Config, or batch-building.
|
||||||
|
|
||||||
If you fork the repository on GitHub you can build using the [dotnet workflow](https://github.com/sinai-dev/UnityExplorer/blob/master/.github/workflows/dotnet.yml):
|
If you fork the repository on GitHub you can build using the [dotnet workflow](https://github.com/sinai-dev/UnityExplorer/blob/master/.github/workflows/dotnet.yml):
|
||||||
@ -138,8 +151,7 @@ If you fork the repository on GitHub you can build using the [dotnet workflow](h
|
|||||||
# Acknowledgments
|
# Acknowledgments
|
||||||
|
|
||||||
* [ManlyMarco](https://github.com/ManlyMarco) for [Runtime Unity Editor](https://github.com/ManlyMarco/RuntimeUnityEditor) \[[license](THIRDPARTY_LICENSES.md#runtimeunityeditor-license)\], the ScriptEvaluator from RUE's REPL console was used as the base 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)\], the ScriptEvaluator from RUE's REPL console was used as the base for UnityExplorer's 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.
|
* [Geoffrey Horsington](https://github.com/ghorsington) for [mcs-unity](https://github.com/sinai-dev/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/6cc958ec23b5e2e8453a73bc2e0d5aa353d4f0d1/MelonLoader.Support.Il2Cpp/MelonCoroutines.cs) \[[license](THIRDPARTY_LICENSES.md#melonloader-license)\], they were included for standalone IL2CPP coroutine support.
|
|
||||||
|
|
||||||
### Disclaimer
|
### Disclaimer
|
||||||
|
|
||||||
|
BIN
img/social.png
BIN
img/social.png
Binary file not shown.
Before Width: | Height: | Size: 232 KiB |
Binary file not shown.
Submodule lib/Il2CppAssemblyUnhollower deleted from 0099c25069
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
lib/unhollowed/UnityEngine.AudioModule.dll
Normal file
BIN
lib/unhollowed/UnityEngine.AudioModule.dll
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -8,6 +8,8 @@ using UnityExplorer.UI;
|
|||||||
using UnityExplorer.UI.Widgets.AutoComplete;
|
using UnityExplorer.UI.Widgets.AutoComplete;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
|
using UniverseLib.UI.Models;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.CSConsole
|
namespace UnityExplorer.CSConsole
|
||||||
{
|
{
|
||||||
@ -25,7 +27,7 @@ namespace UnityExplorer.CSConsole
|
|||||||
AutoCompleteModal.Instance.ReleaseOwnership(this);
|
AutoCompleteModal.Instance.ReleaseOwnership(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly HashSet<char> delimiters = new HashSet<char>
|
private readonly HashSet<char> delimiters = new()
|
||||||
{
|
{
|
||||||
'{', '}', ',', ';', '<', '>', '(', ')', '[', ']', '=', '|', '&', '?'
|
'{', '}', ',', ';', '<', '>', '(', ')', '[', ']', '=', '|', '&', '?'
|
||||||
};
|
};
|
||||||
|
@ -16,6 +16,10 @@ using UnityExplorer.UI.Panels;
|
|||||||
using UnityExplorer.UI.Widgets.AutoComplete;
|
using UnityExplorer.UI.Widgets.AutoComplete;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
|
using UniverseLib.UI.Models;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
using HarmonyLib;
|
||||||
|
using UniverseLib.Runtime;
|
||||||
|
|
||||||
namespace UnityExplorer.CSConsole
|
namespace UnityExplorer.CSConsole
|
||||||
{
|
{
|
||||||
@ -27,6 +31,7 @@ namespace UnityExplorer.CSConsole
|
|||||||
|
|
||||||
private static HashSet<string> usingDirectives;
|
private static HashSet<string> usingDirectives;
|
||||||
private static StringBuilder evaluatorOutput;
|
private static StringBuilder evaluatorOutput;
|
||||||
|
private static StringWriter evaluatorStringWriter;
|
||||||
|
|
||||||
public static CSConsolePanel Panel => UIManager.GetPanel<CSConsolePanel>(UIManager.Panels.CSConsole);
|
public static CSConsolePanel Panel => UIManager.GetPanel<CSConsolePanel>(UIManager.Panels.CSConsole);
|
||||||
public static InputFieldRef Input => Panel.Input;
|
public static InputFieldRef Input => Panel.Input;
|
||||||
@ -46,6 +51,7 @@ namespace UnityExplorer.CSConsole
|
|||||||
"System",
|
"System",
|
||||||
"System.Linq",
|
"System.Linq",
|
||||||
"System.Text",
|
"System.Text",
|
||||||
|
"System.Collections",
|
||||||
"System.Collections.Generic",
|
"System.Collections.Generic",
|
||||||
"UnityEngine",
|
"UnityEngine",
|
||||||
#if CPP
|
#if CPP
|
||||||
@ -56,6 +62,8 @@ namespace UnityExplorer.CSConsole
|
|||||||
|
|
||||||
public static void Init()
|
public static void Init()
|
||||||
{
|
{
|
||||||
|
InitEventSystemPropertyHandlers();
|
||||||
|
|
||||||
// Make sure console is supported on this platform
|
// Make sure console is supported on this platform
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -130,6 +138,12 @@ namespace UnityExplorer.CSConsole
|
|||||||
|
|
||||||
#region Evaluating
|
#region Evaluating
|
||||||
|
|
||||||
|
private static void GenerateTextWriter()
|
||||||
|
{
|
||||||
|
evaluatorOutput = new StringBuilder();
|
||||||
|
evaluatorStringWriter = new StringWriter(evaluatorOutput);
|
||||||
|
}
|
||||||
|
|
||||||
public static void ResetConsole() => ResetConsole(true);
|
public static void ResetConsole() => ResetConsole(true);
|
||||||
|
|
||||||
public static void ResetConsole(bool logSuccess = true)
|
public static void ResetConsole(bool logSuccess = true)
|
||||||
@ -140,8 +154,8 @@ namespace UnityExplorer.CSConsole
|
|||||||
if (Evaluator != null)
|
if (Evaluator != null)
|
||||||
Evaluator.Dispose();
|
Evaluator.Dispose();
|
||||||
|
|
||||||
evaluatorOutput = new StringBuilder();
|
GenerateTextWriter();
|
||||||
Evaluator = new ScriptEvaluator(new StringWriter(evaluatorOutput))
|
Evaluator = new ScriptEvaluator(evaluatorStringWriter)
|
||||||
{
|
{
|
||||||
InteractiveBaseClass = typeof(ScriptInteraction)
|
InteractiveBaseClass = typeof(ScriptInteraction)
|
||||||
};
|
};
|
||||||
@ -176,6 +190,12 @@ namespace UnityExplorer.CSConsole
|
|||||||
if (SRENotSupported)
|
if (SRENotSupported)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (evaluatorStringWriter == null || evaluatorOutput == null)
|
||||||
|
{
|
||||||
|
GenerateTextWriter();
|
||||||
|
Evaluator._textWriter = evaluatorStringWriter;
|
||||||
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Compile the code. If it returned a CompiledMethod, it is REPL.
|
// Compile the code. If it returned a CompiledMethod, it is REPL.
|
||||||
@ -343,7 +363,7 @@ namespace UnityExplorer.CSConsole
|
|||||||
var charTop = charInfo.cursorPos.y;
|
var charTop = charInfo.cursorPos.y;
|
||||||
var charBot = charTop - CSCONSOLE_LINEHEIGHT;
|
var charBot = charTop - CSCONSOLE_LINEHEIGHT;
|
||||||
|
|
||||||
var viewportMin = Input.Rect.rect.height - Input.Rect.anchoredPosition.y - (Input.Rect.rect.height * 0.5f);
|
var viewportMin = Input.Transform.rect.height - Input.Transform.anchoredPosition.y - (Input.Transform.rect.height * 0.5f);
|
||||||
var viewportMax = viewportMin - Panel.InputScroller.ViewportRect.rect.height;
|
var viewportMax = viewportMin - Panel.InputScroller.ViewportRect.rect.height;
|
||||||
|
|
||||||
float diff = 0f;
|
float diff = 0f;
|
||||||
@ -354,7 +374,7 @@ namespace UnityExplorer.CSConsole
|
|||||||
|
|
||||||
if (Math.Abs(diff) > 1)
|
if (Math.Abs(diff) > 1)
|
||||||
{
|
{
|
||||||
var rect = Input.Rect;
|
var rect = Input.Transform;
|
||||||
rect.anchoredPosition = new Vector2(rect.anchoredPosition.x, rect.anchoredPosition.y - diff);
|
rect.anchoredPosition = new Vector2(rect.anchoredPosition.x, rect.anchoredPosition.y - diff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -364,33 +384,84 @@ namespace UnityExplorer.CSConsole
|
|||||||
{
|
{
|
||||||
settingCaretCoroutine = true;
|
settingCaretCoroutine = true;
|
||||||
Input.Component.readOnly = true;
|
Input.Component.readOnly = true;
|
||||||
RuntimeProvider.Instance.StartCoroutine(SetCaretCoroutine(caretPosition));
|
RuntimeHelper.StartCoroutine(SetCaretCoroutine(caretPosition));
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static PropertyInfo SelectionGuardProperty => selectionGuardPropInfo ?? GetSelectionGuardPropInfo();
|
static void InitEventSystemPropertyHandlers()
|
||||||
|
|
||||||
private static PropertyInfo GetSelectionGuardPropInfo()
|
|
||||||
{
|
{
|
||||||
selectionGuardPropInfo = typeof(EventSystem).GetProperty("m_SelectionGuard");
|
try
|
||||||
if (selectionGuardPropInfo == null)
|
{
|
||||||
selectionGuardPropInfo = typeof(EventSystem).GetProperty("m_selectionGuard");
|
foreach (var member in typeof(EventSystem).GetMembers(AccessTools.all))
|
||||||
return selectionGuardPropInfo;
|
{
|
||||||
|
if (member.Name == "m_CurrentSelected")
|
||||||
|
{
|
||||||
|
Type backingType;
|
||||||
|
if (member.MemberType == MemberTypes.Property)
|
||||||
|
backingType = (member as PropertyInfo).PropertyType;
|
||||||
|
else
|
||||||
|
backingType = (member as FieldInfo).FieldType;
|
||||||
|
|
||||||
|
usingEventSystemDictionaryMembers = ReflectionUtility.IsDictionary(backingType);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
ExplorerCore.LogWarning($"Exception checking EventSystem property backing type: {ex}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static PropertyInfo selectionGuardPropInfo;
|
static bool usingEventSystemDictionaryMembers;
|
||||||
|
|
||||||
|
static readonly AmbiguousMemberHandler<EventSystem, GameObject> m_CurrentSelected_Handler_Normal
|
||||||
|
= new(true, true, "m_CurrentSelected", "m_currentSelected");
|
||||||
|
static readonly AmbiguousMemberHandler<EventSystem, Dictionary<int, GameObject>> m_CurrentSelected_Handler_Dictionary
|
||||||
|
= new(true, true, "m_CurrentSelected", "m_currentSelected");
|
||||||
|
|
||||||
|
static readonly AmbiguousMemberHandler<EventSystem, bool> m_SelectionGuard_Handler_Normal
|
||||||
|
= new(true, true, "m_SelectionGuard", "m_selectionGuard");
|
||||||
|
static readonly AmbiguousMemberHandler<EventSystem, Dictionary<int, bool>> m_SelectionGuard_Handler_Dictionary
|
||||||
|
= new(true, true, "m_SelectionGuard", "m_selectionGuard");
|
||||||
|
|
||||||
|
static void SetCurrentSelectedGameObject(EventSystem instance, GameObject value)
|
||||||
|
{
|
||||||
|
instance.SetSelectedGameObject(value);
|
||||||
|
|
||||||
|
if (usingEventSystemDictionaryMembers)
|
||||||
|
m_CurrentSelected_Handler_Dictionary.GetValue(instance)[0] = value;
|
||||||
|
else
|
||||||
|
m_CurrentSelected_Handler_Normal.SetValue(instance, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SetSelectionGuard(EventSystem instance, bool value)
|
||||||
|
{
|
||||||
|
if (usingEventSystemDictionaryMembers)
|
||||||
|
m_SelectionGuard_Handler_Dictionary.GetValue(instance)[0] = value;
|
||||||
|
else
|
||||||
|
m_SelectionGuard_Handler_Normal.SetValue(instance, value);
|
||||||
|
}
|
||||||
|
|
||||||
private static IEnumerator SetCaretCoroutine(int caretPosition)
|
private static IEnumerator SetCaretCoroutine(int caretPosition)
|
||||||
{
|
{
|
||||||
var color = Input.Component.selectionColor;
|
var color = Input.Component.selectionColor;
|
||||||
color.a = 0f;
|
color.a = 0f;
|
||||||
Input.Component.selectionColor = color;
|
Input.Component.selectionColor = color;
|
||||||
try { EventSystem.current.SetSelectedGameObject(null, null); } catch { }
|
|
||||||
yield return null;
|
|
||||||
|
|
||||||
try { SelectionGuardProperty.SetValue(EventSystem.current, false, null); } catch { }
|
try { SetCurrentSelectedGameObject(CursorUnlocker.CurrentEventSystem, null); }
|
||||||
try { EventSystem.current.SetSelectedGameObject(Input.UIRoot, null); } catch { }
|
catch (Exception ex) { ExplorerCore.Log($"Failed removing selected object: {ex}"); }
|
||||||
|
|
||||||
|
yield return null; // ~~~~~~~ YIELD FRAME ~~~~~~~~~
|
||||||
|
|
||||||
|
try { SetSelectionGuard(CursorUnlocker.CurrentEventSystem, false); }
|
||||||
|
catch (Exception ex) { ExplorerCore.Log($"Failed setting selection guard: {ex}"); }
|
||||||
|
|
||||||
|
try { SetCurrentSelectedGameObject(CursorUnlocker.CurrentEventSystem, Input.GameObject); }
|
||||||
|
catch (Exception ex) { ExplorerCore.Log($"Failed setting selected gameobject: {ex}"); }
|
||||||
|
|
||||||
|
yield return null; // ~~~~~~~ YIELD FRAME ~~~~~~~~~
|
||||||
|
|
||||||
Input.Component.Select();
|
Input.Component.Select();
|
||||||
yield return null;
|
|
||||||
|
|
||||||
Input.Component.caretPosition = caretPosition;
|
Input.Component.caretPosition = caretPosition;
|
||||||
Input.Component.selectionFocusPosition = caretPosition;
|
Input.Component.selectionFocusPosition = caretPosition;
|
||||||
@ -424,7 +495,7 @@ namespace UnityExplorer.CSConsole
|
|||||||
|
|
||||||
// the top and bottom position of the viewport in relation to the text height
|
// the top and bottom position of the viewport in relation to the text height
|
||||||
// they need the half-height adjustment to normalize against the 'line.topY' value.
|
// they need the half-height adjustment to normalize against the 'line.topY' value.
|
||||||
var viewportMin = Input.Rect.rect.height - Input.Rect.anchoredPosition.y - (Input.Rect.rect.height * 0.5f);
|
var viewportMin = Input.Transform.rect.height - Input.Transform.anchoredPosition.y - (Input.Transform.rect.height * 0.5f);
|
||||||
var viewportMax = viewportMin - Panel.InputScroller.ViewportRect.rect.height;
|
var viewportMax = viewportMin - Panel.InputScroller.ViewportRect.rect.height;
|
||||||
|
|
||||||
for (int i = 0; i < Input.TextGenerator.lineCount; i++)
|
for (int i = 0; i < Input.TextGenerator.lineCount; i++)
|
||||||
@ -589,7 +660,7 @@ If the game was built with Unity's stubbed netstandard 2.0 runtime, you can fix
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly Dictionary<string, string> helpDict = new Dictionary<string, string>();
|
private static readonly Dictionary<string, string> helpDict = new();
|
||||||
|
|
||||||
public static void SetupHelpInteraction()
|
public static void SetupHelpInteraction()
|
||||||
{
|
{
|
||||||
@ -644,15 +715,18 @@ var x = 5;
|
|||||||
++x;
|
++x;
|
||||||
|
|
||||||
/* The following helpers are available in REPL mode:
|
/* The following helpers are available in REPL mode:
|
||||||
|
* CurrentTarget; - System.Object, the target of the active Inspector tab
|
||||||
|
* AllTargets; - System.Object[], the targets of all Inspector tabs
|
||||||
|
* Log(obj); - prints a message to the console log
|
||||||
|
* Inspect(obj); - inspect the object with the Inspector
|
||||||
|
* Inspect(someType); - inspect a Type with static reflection
|
||||||
|
* Start(enumerator); - Coroutine, starts the IEnumerator as a Coroutine, and returns the Coroutine.
|
||||||
|
* Stop(coroutine); - stop the Coroutine ONLY if it was started with Start(ienumerator).
|
||||||
|
* Copy(obj); - copies the object to the UnityExplorer Clipboard
|
||||||
|
* Paste(); - System.Object, the contents of the Clipboard.
|
||||||
* GetUsing(); - prints the current using directives to the console log
|
* GetUsing(); - prints the current using directives to the console log
|
||||||
* GetVars(); - prints the names and values of the REPL variables you have defined
|
* GetVars(); - prints the names and values of the REPL variables you have defined
|
||||||
* GetClasses(); - prints the names and members of the classes you have defined
|
* GetClasses(); - prints the names and members of the classes you have defined
|
||||||
* Log(obj); - prints a message to the console log
|
|
||||||
* CurrentTarget; - System.Object, the target of the active Inspector tab
|
|
||||||
* AllTargets; - System.Object[], the targets of all Inspector tabs
|
|
||||||
* Inspect(obj); - inspect the object with the Inspector
|
|
||||||
* Inspect(someType); - inspect a Type with static reflection
|
|
||||||
* Start(enumerator); - starts the IEnumerator as a Coroutine
|
|
||||||
* help; - the default REPL help command, contains additional helpers.
|
* help; - the default REPL help command, contains additional helpers.
|
||||||
*/";
|
*/";
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ using UnityEngine;
|
|||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.CSConsole.Lexers;
|
using UnityExplorer.CSConsole.Lexers;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.CSConsole
|
namespace UnityExplorer.CSConsole
|
||||||
{
|
{
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.CSConsole.Lexers
|
namespace UnityExplorer.CSConsole.Lexers
|
||||||
{
|
{
|
||||||
|
@ -51,13 +51,8 @@ namespace UnityExplorer.CSConsole
|
|||||||
ReferenceAssembly(asm);
|
ReferenceAssembly(asm);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static CompilerContext context;
|
|
||||||
|
|
||||||
private static CompilerContext BuildContext(TextWriter tw)
|
private static CompilerContext BuildContext(TextWriter tw)
|
||||||
{
|
{
|
||||||
if (context != null)
|
|
||||||
return context;
|
|
||||||
|
|
||||||
_reportPrinter = new StreamReportPrinter(tw);
|
_reportPrinter = new StreamReportPrinter(tw);
|
||||||
|
|
||||||
var settings = new CompilerSettings
|
var settings = new CompilerSettings
|
||||||
@ -70,7 +65,7 @@ namespace UnityExplorer.CSConsole
|
|||||||
EnhancedWarnings = false
|
EnhancedWarnings = false
|
||||||
};
|
};
|
||||||
|
|
||||||
return context = new CompilerContext(settings, _reportPrinter);
|
return new CompilerContext(settings, _reportPrinter);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ImportAppdomainAssemblies(Action<Assembly> import)
|
private static void ImportAppdomainAssemblies(Action<Assembly> import)
|
||||||
|
@ -1,45 +1,48 @@
|
|||||||
using Mono.CSharp;
|
using HarmonyLib;
|
||||||
|
using Mono.CSharp;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityExplorer.Core.Runtime;
|
using UnityExplorer.Runtime;
|
||||||
|
using UnityExplorer.UI.Panels;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
|
|
||||||
namespace UnityExplorer.CSConsole
|
namespace UnityExplorer.CSConsole
|
||||||
{
|
{
|
||||||
public class ScriptInteraction : InteractiveBase
|
public class ScriptInteraction : InteractiveBase
|
||||||
{
|
{
|
||||||
|
public static object CurrentTarget
|
||||||
|
=> InspectorManager.ActiveInspector?.Target;
|
||||||
|
|
||||||
|
public static object[] AllTargets
|
||||||
|
=> InspectorManager.Inspectors.Select(it => it.Target).ToArray();
|
||||||
|
|
||||||
public static void Log(object message)
|
public static void Log(object message)
|
||||||
{
|
=> ExplorerCore.Log(message);
|
||||||
ExplorerCore.Log(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static object CurrentTarget => InspectorManager.ActiveInspector?.Target;
|
|
||||||
|
|
||||||
public static object[] AllTargets => InspectorManager.Inspectors.Select(it => it.Target).ToArray();
|
|
||||||
|
|
||||||
public static void Inspect(object obj)
|
public static void Inspect(object obj)
|
||||||
{
|
=> InspectorManager.Inspect(obj);
|
||||||
InspectorManager.Inspect(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Inspect(Type type)
|
public static void Inspect(Type type)
|
||||||
{
|
=> InspectorManager.Inspect(type);
|
||||||
InspectorManager.Inspect(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Start(IEnumerator ienumerator)
|
public static Coroutine Start(IEnumerator ienumerator)
|
||||||
{
|
=> RuntimeHelper.StartCoroutine(ienumerator);
|
||||||
RuntimeProvider.Instance.StartCoroutine(ienumerator);
|
|
||||||
}
|
public static void Stop(Coroutine coro)
|
||||||
|
=> RuntimeHelper.StopCoroutine(coro);
|
||||||
|
|
||||||
|
public static void Copy(object obj)
|
||||||
|
=> ClipboardPanel.Copy(obj);
|
||||||
|
|
||||||
|
public static object Paste()
|
||||||
|
=> ClipboardPanel.Current;
|
||||||
|
|
||||||
public static void GetUsing()
|
public static void GetUsing()
|
||||||
{
|
=> Log(Evaluator.GetUsing());
|
||||||
Log(Evaluator.GetUsing());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void GetVars()
|
public static void GetVars()
|
||||||
{
|
{
|
||||||
@ -52,7 +55,7 @@ namespace UnityExplorer.CSConsole
|
|||||||
|
|
||||||
public static void GetClasses()
|
public static void GetClasses()
|
||||||
{
|
{
|
||||||
if (ReflectionUtility.GetFieldInfo(typeof(Evaluator), "source_file")
|
if (AccessTools.Field(typeof(Evaluator), "source_file")
|
||||||
.GetValue(Evaluator) is CompilationSourceFile sourceFile
|
.GetValue(Evaluator) is CompilationSourceFile sourceFile
|
||||||
&& sourceFile.Containers.Any())
|
&& sourceFile.Containers.Any())
|
||||||
{
|
{
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityExplorer.Core.Config;
|
using UnityExplorer.Config;
|
||||||
using UnityExplorer.CacheObject.Views;
|
using UnityExplorer.CacheObject.Views;
|
||||||
|
|
||||||
namespace UnityExplorer.CacheObject
|
namespace UnityExplorer.CacheObject
|
||||||
@ -44,6 +44,6 @@ namespace UnityExplorer.CacheObject
|
|||||||
RefConfigElement.BoxedValue = value;
|
RefConfigElement.BoxedValue = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool SetCellEvaluateState(CacheObjectCell cell) => false;
|
protected override bool TryAutoEvaluateIfUnitialized(CacheObjectCell cell) => true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
87
src/CacheObject/CacheConstructor.cs
Normal file
87
src/CacheObject/CacheConstructor.cs
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
using UnityExplorer.Inspectors;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
|
namespace UnityExplorer.CacheObject
|
||||||
|
{
|
||||||
|
public class CacheConstructor : CacheMember
|
||||||
|
{
|
||||||
|
public ConstructorInfo CtorInfo { get; }
|
||||||
|
readonly Type typeForStructConstructor;
|
||||||
|
|
||||||
|
public override Type DeclaringType => typeForStructConstructor ?? CtorInfo.DeclaringType;
|
||||||
|
public override bool IsStatic => true;
|
||||||
|
public override bool ShouldAutoEvaluate => false;
|
||||||
|
public override bool CanWrite => false;
|
||||||
|
|
||||||
|
public CacheConstructor(ConstructorInfo ci)
|
||||||
|
{
|
||||||
|
this.CtorInfo = ci;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CacheConstructor(Type typeForStructConstructor)
|
||||||
|
{
|
||||||
|
this.typeForStructConstructor = typeForStructConstructor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void SetInspectorOwner(ReflectionInspector inspector, MemberInfo member)
|
||||||
|
{
|
||||||
|
Type ctorReturnType;
|
||||||
|
// if is parameterless struct ctor
|
||||||
|
if (typeForStructConstructor != null)
|
||||||
|
{
|
||||||
|
ctorReturnType = typeForStructConstructor;
|
||||||
|
this.Owner = inspector;
|
||||||
|
|
||||||
|
// eg. Vector3.Vector3()
|
||||||
|
this.NameLabelText = SignatureHighlighter.Parse(typeForStructConstructor, false);
|
||||||
|
NameLabelText += $".{NameLabelText}()";
|
||||||
|
|
||||||
|
this.NameForFiltering = SignatureHighlighter.RemoveHighlighting(NameLabelText);
|
||||||
|
this.NameLabelTextRaw = NameForFiltering;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
base.SetInspectorOwner(inspector, member);
|
||||||
|
|
||||||
|
Arguments = CtorInfo.GetParameters();
|
||||||
|
ctorReturnType = CtorInfo.DeclaringType;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctorReturnType.IsGenericTypeDefinition)
|
||||||
|
GenericArguments = ctorReturnType.GetGenericArguments();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override object TryEvaluate()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Type returnType = DeclaringType;
|
||||||
|
|
||||||
|
if (returnType.IsGenericTypeDefinition)
|
||||||
|
returnType = DeclaringType.MakeGenericType(Evaluator.TryParseGenericArguments());
|
||||||
|
|
||||||
|
object ret;
|
||||||
|
if (HasArguments)
|
||||||
|
ret = Activator.CreateInstance(returnType, Evaluator.TryParseArguments());
|
||||||
|
else
|
||||||
|
ret = Activator.CreateInstance(returnType, ArgumentUtility.EmptyArgs);
|
||||||
|
|
||||||
|
LastException = null;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LastException = ex;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void TrySetValue(object value) => throw new NotImplementedException("You can't set a constructor");
|
||||||
|
}
|
||||||
|
}
|
@ -17,6 +17,11 @@ namespace UnityExplorer.CacheObject
|
|||||||
|
|
||||||
public override bool ShouldAutoEvaluate => true;
|
public override bool ShouldAutoEvaluate => true;
|
||||||
|
|
||||||
|
public CacheField(FieldInfo fi)
|
||||||
|
{
|
||||||
|
this.FieldInfo = fi;
|
||||||
|
}
|
||||||
|
|
||||||
public override void SetInspectorOwner(ReflectionInspector inspector, MemberInfo member)
|
public override void SetInspectorOwner(ReflectionInspector inspector, MemberInfo member)
|
||||||
{
|
{
|
||||||
base.SetInspectorOwner(inspector, member);
|
base.SetInspectorOwner(inspector, member);
|
||||||
@ -27,13 +32,11 @@ namespace UnityExplorer.CacheObject
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var ret = FieldInfo.GetValue(DeclaringInstance);
|
var ret = FieldInfo.GetValue(DeclaringInstance);
|
||||||
HadException = false;
|
|
||||||
LastException = null;
|
LastException = null;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
HadException = true;
|
|
||||||
LastException = ex;
|
LastException = ex;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ using System.Text;
|
|||||||
using UnityExplorer.CacheObject.IValues;
|
using UnityExplorer.CacheObject.IValues;
|
||||||
using UnityExplorer.CacheObject.Views;
|
using UnityExplorer.CacheObject.Views;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.CacheObject
|
namespace UnityExplorer.CacheObject
|
||||||
{
|
{
|
||||||
@ -92,10 +93,6 @@ namespace UnityExplorer.CacheObject
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected override bool SetCellEvaluateState(CacheObjectCell cell)
|
protected override bool TryAutoEvaluateIfUnitialized(CacheObjectCell cell) => true;
|
||||||
{
|
|
||||||
// not needed
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ namespace UnityExplorer.CacheObject
|
|||||||
|
|
||||||
public override bool ShouldAutoEvaluate => true;
|
public override bool ShouldAutoEvaluate => true;
|
||||||
public override bool HasArguments => false;
|
public override bool HasArguments => false;
|
||||||
public override bool CanWrite => Owner.CanWrite;
|
public override bool CanWrite => Owner?.CanWrite ?? false;
|
||||||
|
|
||||||
public void SetListOwner(InteractiveList list, int listIndex)
|
public void SetListOwner(InteractiveList list, int listIndex)
|
||||||
{
|
{
|
||||||
@ -37,11 +37,6 @@ namespace UnityExplorer.CacheObject
|
|||||||
(Owner as InteractiveList).TrySetValueToIndex(value, this.ListIndex);
|
(Owner as InteractiveList).TrySetValueToIndex(value, this.ListIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override bool TryAutoEvaluateIfUnitialized(CacheObjectCell cell) => true;
|
||||||
protected override bool SetCellEvaluateState(CacheObjectCell cell)
|
|
||||||
{
|
|
||||||
// not needed
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,13 +4,18 @@ using System.Linq;
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityExplorer.Core.Runtime;
|
using UnityExplorer.Runtime;
|
||||||
using UnityExplorer.CacheObject.Views;
|
using UnityExplorer.CacheObject.Views;
|
||||||
using UnityExplorer.Inspectors;
|
using UnityExplorer.Inspectors;
|
||||||
using UniverseLib.UI.Models;
|
using UniverseLib.UI.Models;
|
||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
|
using UnityExplorer.UI.Widgets;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
using UniverseLib.UI.ObjectPool;
|
||||||
|
using System.Collections;
|
||||||
|
using HarmonyLib;
|
||||||
|
|
||||||
namespace UnityExplorer.CacheObject
|
namespace UnityExplorer.CacheObject
|
||||||
{
|
{
|
||||||
@ -18,7 +23,7 @@ namespace UnityExplorer.CacheObject
|
|||||||
{
|
{
|
||||||
public abstract Type DeclaringType { get; }
|
public abstract Type DeclaringType { get; }
|
||||||
public string NameForFiltering { get; protected set; }
|
public string NameForFiltering { get; protected set; }
|
||||||
public object DeclaringInstance => IsStatic ? null : (m_declaringInstance ?? (m_declaringInstance = Owner.Target.TryCast(DeclaringType)));
|
public object DeclaringInstance => IsStatic ? null : (m_declaringInstance ??= Owner.Target.TryCast(DeclaringType));
|
||||||
private object m_declaringInstance;
|
private object m_declaringInstance;
|
||||||
|
|
||||||
public abstract bool IsStatic { get; }
|
public abstract bool IsStatic { get; }
|
||||||
@ -31,8 +36,14 @@ namespace UnityExplorer.CacheObject
|
|||||||
public virtual void SetInspectorOwner(ReflectionInspector inspector, MemberInfo member)
|
public virtual void SetInspectorOwner(ReflectionInspector inspector, MemberInfo member)
|
||||||
{
|
{
|
||||||
this.Owner = inspector;
|
this.Owner = inspector;
|
||||||
this.NameLabelText = SignatureHighlighter.Parse(member.DeclaringType, false, member);
|
this.NameLabelText = this switch
|
||||||
this.NameForFiltering = $"{member.DeclaringType.Name}.{member.Name}";
|
{
|
||||||
|
CacheMethod => SignatureHighlighter.HighlightMethod(member as MethodInfo),
|
||||||
|
CacheConstructor => SignatureHighlighter.HighlightConstructor(member as ConstructorInfo),
|
||||||
|
_ => SignatureHighlighter.Parse(member.DeclaringType, false, member),
|
||||||
|
};
|
||||||
|
|
||||||
|
this.NameForFiltering = SignatureHighlighter.RemoveHighlighting(NameLabelText);
|
||||||
this.NameLabelTextRaw = NameForFiltering;
|
this.NameLabelTextRaw = NameForFiltering;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,10 +100,10 @@ namespace UnityExplorer.CacheObject
|
|||||||
base.SetValueState(cell, args);
|
base.SetValueState(cell, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly Color evalEnabledColor = new Color(0.15f, 0.25f, 0.15f);
|
private static readonly Color evalEnabledColor = new(0.15f, 0.25f, 0.15f);
|
||||||
private static readonly Color evalDisabledColor = new Color(0.15f, 0.15f, 0.15f);
|
private static readonly Color evalDisabledColor = new(0.15f, 0.15f, 0.15f);
|
||||||
|
|
||||||
protected override bool SetCellEvaluateState(CacheObjectCell objectcell)
|
protected override bool TryAutoEvaluateIfUnitialized(CacheObjectCell objectcell)
|
||||||
{
|
{
|
||||||
var cell = objectcell as CacheMemberCell;
|
var cell = objectcell as CacheMemberCell;
|
||||||
|
|
||||||
@ -108,14 +119,14 @@ namespace UnityExplorer.CacheObject
|
|||||||
{
|
{
|
||||||
cell.EvaluateButton.ButtonText.text = "Hide";
|
cell.EvaluateButton.ButtonText.text = "Hide";
|
||||||
Evaluator.UIRoot.transform.SetParent(cell.EvaluateHolder.transform, false);
|
Evaluator.UIRoot.transform.SetParent(cell.EvaluateHolder.transform, false);
|
||||||
RuntimeProvider.Instance.SetColorBlock(cell.EvaluateButton.Component, evalEnabledColor, evalEnabledColor * 1.3f);
|
RuntimeHelper.SetColorBlock(cell.EvaluateButton.Component, evalEnabledColor, evalEnabledColor * 1.3f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
cell.EvaluateButton.ButtonText.text = "Evaluate";
|
cell.EvaluateButton.ButtonText.text = "Evaluate";
|
||||||
|
|
||||||
if (!Evaluating)
|
if (!Evaluating)
|
||||||
RuntimeProvider.Instance.SetColorBlock(cell.EvaluateButton.Component, evalDisabledColor, evalDisabledColor * 1.3f);
|
RuntimeHelper.SetColorBlock(cell.EvaluateButton.Component, evalDisabledColor, evalDisabledColor * 1.3f);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (State == ValueState.NotEvaluated && !ShouldAutoEvaluate)
|
if (State == ValueState.NotEvaluated && !ShouldAutoEvaluate)
|
||||||
@ -123,13 +134,13 @@ namespace UnityExplorer.CacheObject
|
|||||||
SetValueState(cell, ValueStateArgs.Default);
|
SetValueState(cell, ValueStateArgs.Default);
|
||||||
cell.RefreshSubcontentButton();
|
cell.RefreshSubcontentButton();
|
||||||
|
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (State == ValueState.NotEvaluated)
|
if (State == ValueState.NotEvaluated)
|
||||||
Evaluate();
|
Evaluate();
|
||||||
|
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnEvaluateClicked()
|
public void OnEvaluateClicked()
|
||||||
@ -145,7 +156,7 @@ namespace UnityExplorer.CacheObject
|
|||||||
this.Evaluator = Pool<EvaluateWidget>.Borrow();
|
this.Evaluator = Pool<EvaluateWidget>.Borrow();
|
||||||
Evaluator.OnBorrowedFromPool(this);
|
Evaluator.OnBorrowedFromPool(this);
|
||||||
Evaluator.UIRoot.transform.SetParent((CellView as CacheMemberCell).EvaluateHolder.transform, false);
|
Evaluator.UIRoot.transform.SetParent((CellView as CacheMemberCell).EvaluateHolder.transform, false);
|
||||||
SetCellEvaluateState(CellView);
|
TryAutoEvaluateIfUnitialized(CellView);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -154,188 +165,9 @@ namespace UnityExplorer.CacheObject
|
|||||||
else
|
else
|
||||||
Evaluator.UIRoot.SetActive(true);
|
Evaluator.UIRoot.SetActive(true);
|
||||||
|
|
||||||
SetCellEvaluateState(CellView);
|
TryAutoEvaluateIfUnitialized(CellView);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#region Cache Member Util
|
|
||||||
|
|
||||||
public static bool CanParseArgs(ParameterInfo[] parameters)
|
|
||||||
{
|
|
||||||
foreach (var param in parameters)
|
|
||||||
{
|
|
||||||
var pType = param.ParameterType;
|
|
||||||
|
|
||||||
if (pType.IsByRef && pType.HasElementType)
|
|
||||||
pType = pType.GetElementType();
|
|
||||||
|
|
||||||
if (pType != null && ParseUtility.CanParse(pType))
|
|
||||||
continue;
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<CacheMember> GetCacheMembers(object inspectorTarget, Type _type, ReflectionInspector _inspector)
|
|
||||||
{
|
|
||||||
var list = new List<CacheMember>();
|
|
||||||
var cachedSigs = new HashSet<string>();
|
|
||||||
|
|
||||||
var types = ReflectionUtility.GetAllBaseTypes(_type);
|
|
||||||
|
|
||||||
var flags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static;
|
|
||||||
if (!_inspector.StaticOnly)
|
|
||||||
flags |= BindingFlags.Instance;
|
|
||||||
|
|
||||||
var infos = new List<MemberInfo>();
|
|
||||||
|
|
||||||
foreach (var declaringType in types)
|
|
||||||
{
|
|
||||||
var target = inspectorTarget;
|
|
||||||
if (!_inspector.StaticOnly)
|
|
||||||
target = target.TryCast(declaringType);
|
|
||||||
|
|
||||||
infos.Clear();
|
|
||||||
infos.AddRange(declaringType.GetProperties(flags));
|
|
||||||
infos.AddRange(declaringType.GetFields(flags));
|
|
||||||
infos.AddRange(declaringType.GetMethods(flags));
|
|
||||||
|
|
||||||
foreach (var member in infos)
|
|
||||||
{
|
|
||||||
if (member.DeclaringType != declaringType)
|
|
||||||
continue;
|
|
||||||
TryCacheMember(member, list, cachedSigs, declaringType, _inspector);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var typeList = types.ToList();
|
|
||||||
|
|
||||||
var sorted = new List<CacheMember>();
|
|
||||||
sorted.AddRange(list.Where(it => it is CacheProperty)
|
|
||||||
.OrderBy(it => typeList.IndexOf(it.DeclaringType))
|
|
||||||
.ThenBy(it => it.NameForFiltering));
|
|
||||||
sorted.AddRange(list.Where(it => it is CacheField)
|
|
||||||
.OrderBy(it => typeList.IndexOf(it.DeclaringType))
|
|
||||||
.ThenBy(it => it.NameForFiltering));
|
|
||||||
sorted.AddRange(list.Where(it => it is CacheMethod)
|
|
||||||
.OrderBy(it => typeList.IndexOf(it.DeclaringType))
|
|
||||||
.ThenBy(it => it.NameForFiltering));
|
|
||||||
|
|
||||||
return sorted;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void TryCacheMember(MemberInfo member, List<CacheMember> list, HashSet<string> cachedSigs,
|
|
||||||
Type declaringType, ReflectionInspector _inspector, bool ignorePropertyMethodInfos = true)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (RuntimeHelper.IsBlacklisted(member))
|
|
||||||
return;
|
|
||||||
|
|
||||||
var sig = GetSig(member);
|
|
||||||
|
|
||||||
//ExplorerCore.Log($"Trying to cache member {sig}... ({member.MemberType})");
|
|
||||||
|
|
||||||
CacheMember cached;
|
|
||||||
Type returnType;
|
|
||||||
switch (member.MemberType)
|
|
||||||
{
|
|
||||||
case MemberTypes.Method:
|
|
||||||
{
|
|
||||||
var mi = member as MethodInfo;
|
|
||||||
if (ignorePropertyMethodInfos
|
|
||||||
&& (mi.Name.StartsWith("get_") || mi.Name.StartsWith("set_")))
|
|
||||||
return;
|
|
||||||
|
|
||||||
var args = mi.GetParameters();
|
|
||||||
if (!CanParseArgs(args))
|
|
||||||
return;
|
|
||||||
|
|
||||||
sig += GetArgumentString(args);
|
|
||||||
if (cachedSigs.Contains(sig))
|
|
||||||
return;
|
|
||||||
|
|
||||||
cached = new CacheMethod() { MethodInfo = mi };
|
|
||||||
returnType = mi.ReturnType;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case MemberTypes.Property:
|
|
||||||
{
|
|
||||||
var pi = member as PropertyInfo;
|
|
||||||
|
|
||||||
var args = pi.GetIndexParameters();
|
|
||||||
if (!CanParseArgs(args))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!pi.CanRead && pi.CanWrite)
|
|
||||||
{
|
|
||||||
// write-only property, cache the set method instead.
|
|
||||||
var setMethod = pi.GetSetMethod(true);
|
|
||||||
if (setMethod != null)
|
|
||||||
TryCacheMember(setMethod, list, cachedSigs, declaringType, _inspector, false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
sig += GetArgumentString(args);
|
|
||||||
if (cachedSigs.Contains(sig))
|
|
||||||
return;
|
|
||||||
|
|
||||||
cached = new CacheProperty() { PropertyInfo = pi };
|
|
||||||
returnType = pi.PropertyType;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case MemberTypes.Field:
|
|
||||||
{
|
|
||||||
var fi = member as FieldInfo;
|
|
||||||
cached = new CacheField() { FieldInfo = fi };
|
|
||||||
returnType = fi.FieldType;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default: return;
|
|
||||||
}
|
|
||||||
|
|
||||||
cachedSigs.Add(sig);
|
|
||||||
|
|
||||||
cached.SetFallbackType(returnType);
|
|
||||||
cached.SetInspectorOwner(_inspector, member);
|
|
||||||
|
|
||||||
list.Add(cached);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
ExplorerCore.LogWarning($"Exception caching member {member.DeclaringType.FullName}.{member.Name}!");
|
|
||||||
ExplorerCore.Log(e.ToString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static string GetSig(MemberInfo member)
|
|
||||||
=> $"{member.DeclaringType.Name}.{member.Name}";
|
|
||||||
|
|
||||||
internal static string GetArgumentString(ParameterInfo[] args)
|
|
||||||
{
|
|
||||||
var sb = new StringBuilder();
|
|
||||||
sb.Append(' ');
|
|
||||||
sb.Append('(');
|
|
||||||
foreach (var param in args)
|
|
||||||
{
|
|
||||||
sb.Append(param.ParameterType.Name);
|
|
||||||
sb.Append(' ');
|
|
||||||
sb.Append(param.Name);
|
|
||||||
sb.Append(',');
|
|
||||||
sb.Append(' ');
|
|
||||||
}
|
|
||||||
sb.Append(')');
|
|
||||||
return sb.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
170
src/CacheObject/CacheMemberFactory.cs
Normal file
170
src/CacheObject/CacheMemberFactory.cs
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
using UnityExplorer.Inspectors;
|
||||||
|
using UnityExplorer.Runtime;
|
||||||
|
using UniverseLib;
|
||||||
|
using HarmonyLib;
|
||||||
|
using HarmonyLib.Tools;
|
||||||
|
|
||||||
|
namespace UnityExplorer.CacheObject
|
||||||
|
{
|
||||||
|
public static class CacheMemberFactory
|
||||||
|
{
|
||||||
|
public static List<CacheMember> GetCacheMembers(Type type, ReflectionInspector inspector)
|
||||||
|
{
|
||||||
|
//var list = new List<CacheMember>();
|
||||||
|
HashSet<string> cachedSigs = new();
|
||||||
|
List<CacheMember> props = new();
|
||||||
|
List<CacheMember> fields = new();
|
||||||
|
List<CacheMember> ctors = new();
|
||||||
|
List<CacheMember> methods = new();
|
||||||
|
|
||||||
|
var types = ReflectionUtility.GetAllBaseTypes(type);
|
||||||
|
|
||||||
|
var flags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static;
|
||||||
|
if (!inspector.StaticOnly)
|
||||||
|
flags |= BindingFlags.Instance;
|
||||||
|
|
||||||
|
if (!type.IsAbstract)
|
||||||
|
{
|
||||||
|
// Get non-static constructors of the main type.
|
||||||
|
// There's no reason to get the static cctor, it will be invoked when we inspect the class.
|
||||||
|
// Also no point getting ctors on inherited types.
|
||||||
|
foreach (var ctor in type.GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
|
||||||
|
TryCacheMember(ctor, ctors, cachedSigs, type, inspector);
|
||||||
|
|
||||||
|
// structs always have a parameterless constructor
|
||||||
|
if (type.IsValueType)
|
||||||
|
{
|
||||||
|
CacheConstructor cached = new(type);
|
||||||
|
cached.SetFallbackType(type);
|
||||||
|
cached.SetInspectorOwner(inspector, null);
|
||||||
|
ctors.Add(cached);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var declaringType in types)
|
||||||
|
{
|
||||||
|
foreach (var prop in declaringType.GetProperties(flags))
|
||||||
|
if (prop.DeclaringType == declaringType)
|
||||||
|
TryCacheMember(prop, props, cachedSigs, declaringType, inspector);
|
||||||
|
|
||||||
|
foreach (var field in declaringType.GetFields(flags))
|
||||||
|
if (field.DeclaringType == declaringType)
|
||||||
|
TryCacheMember(field, fields, cachedSigs, declaringType, inspector);
|
||||||
|
|
||||||
|
foreach (var method in declaringType.GetMethods(flags))
|
||||||
|
if (method.DeclaringType == declaringType)
|
||||||
|
TryCacheMember(method, methods, cachedSigs, declaringType, inspector);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var sorted = new List<CacheMember>();
|
||||||
|
sorted.AddRange(props.OrderBy(it => Array.IndexOf(types, it.DeclaringType))
|
||||||
|
.ThenBy(it => it.NameForFiltering));
|
||||||
|
sorted.AddRange(fields.OrderBy(it => Array.IndexOf(types, it.DeclaringType))
|
||||||
|
.ThenBy(it => it.NameForFiltering));
|
||||||
|
sorted.AddRange(ctors.OrderBy(it => Array.IndexOf(types, it.DeclaringType))
|
||||||
|
.ThenBy(it => it.NameForFiltering));
|
||||||
|
sorted.AddRange(methods.OrderBy(it => Array.IndexOf(types, it.DeclaringType))
|
||||||
|
.ThenBy(it => it.NameForFiltering));
|
||||||
|
return sorted;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void TryCacheMember<T>(MemberInfo member, List<T> list, HashSet<string> cachedSigs,
|
||||||
|
Type declaringType, ReflectionInspector inspector, bool ignorePropertyMethodInfos = true)
|
||||||
|
where T : CacheMember
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (UERuntimeHelper.IsBlacklisted(member))
|
||||||
|
return;
|
||||||
|
|
||||||
|
string sig = member switch
|
||||||
|
{
|
||||||
|
// method or constructor
|
||||||
|
MethodBase mb => mb.FullDescription(),
|
||||||
|
// property or field
|
||||||
|
PropertyInfo or FieldInfo => $"{member.DeclaringType.FullDescription()}.{member.Name}",
|
||||||
|
_ => throw new NotImplementedException(),
|
||||||
|
};
|
||||||
|
|
||||||
|
if (cachedSigs.Contains(sig))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// ExplorerCore.Log($"Trying to cache member {sig}... ({member.MemberType})");
|
||||||
|
|
||||||
|
CacheMember cached;
|
||||||
|
Type returnType;
|
||||||
|
|
||||||
|
switch (member.MemberType)
|
||||||
|
{
|
||||||
|
case MemberTypes.Constructor:
|
||||||
|
{
|
||||||
|
var ci = member as ConstructorInfo;
|
||||||
|
cached = new CacheConstructor(ci);
|
||||||
|
returnType = ci.DeclaringType;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MemberTypes.Method:
|
||||||
|
{
|
||||||
|
var mi = member as MethodInfo;
|
||||||
|
if (ignorePropertyMethodInfos
|
||||||
|
&& (mi.Name.StartsWith("get_") || mi.Name.StartsWith("set_")))
|
||||||
|
return;
|
||||||
|
|
||||||
|
cached = new CacheMethod(mi);
|
||||||
|
returnType = mi.ReturnType;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case MemberTypes.Property:
|
||||||
|
{
|
||||||
|
var pi = member as PropertyInfo;
|
||||||
|
|
||||||
|
if (!pi.CanRead && pi.CanWrite)
|
||||||
|
{
|
||||||
|
// write-only property, cache the set method instead.
|
||||||
|
var setMethod = pi.GetSetMethod(true);
|
||||||
|
if (setMethod != null)
|
||||||
|
TryCacheMember(setMethod, list, cachedSigs, declaringType, inspector, false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cached = new CacheProperty(pi);
|
||||||
|
returnType = pi.PropertyType;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case MemberTypes.Field:
|
||||||
|
{
|
||||||
|
var fi = member as FieldInfo;
|
||||||
|
cached = new CacheField(fi);
|
||||||
|
returnType = fi.FieldType;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
cachedSigs.Add(sig);
|
||||||
|
|
||||||
|
cached.SetFallbackType(returnType);
|
||||||
|
cached.SetInspectorOwner(inspector, member);
|
||||||
|
|
||||||
|
list.Add((T)cached);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ExplorerCore.LogWarning($"Exception caching member {member.DeclaringType.FullName}.{member.Name}!");
|
||||||
|
ExplorerCore.Log(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -5,18 +5,24 @@ using System.Reflection;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityExplorer.Inspectors;
|
using UnityExplorer.Inspectors;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.CacheObject
|
namespace UnityExplorer.CacheObject
|
||||||
{
|
{
|
||||||
public class CacheMethod : CacheMember
|
public class CacheMethod : CacheMember
|
||||||
{
|
{
|
||||||
public MethodInfo MethodInfo { get; internal set; }
|
public MethodInfo MethodInfo { get; }
|
||||||
public override Type DeclaringType => MethodInfo.DeclaringType;
|
public override Type DeclaringType => MethodInfo.DeclaringType;
|
||||||
public override bool CanWrite => false;
|
public override bool CanWrite => false;
|
||||||
public override bool IsStatic => MethodInfo.IsStatic;
|
public override bool IsStatic => MethodInfo.IsStatic;
|
||||||
|
|
||||||
public override bool ShouldAutoEvaluate => false;
|
public override bool ShouldAutoEvaluate => false;
|
||||||
|
|
||||||
|
public CacheMethod (MethodInfo mi)
|
||||||
|
{
|
||||||
|
this.MethodInfo = mi;
|
||||||
|
}
|
||||||
|
|
||||||
public override void SetInspectorOwner(ReflectionInspector inspector, MemberInfo member)
|
public override void SetInspectorOwner(ReflectionInspector inspector, MemberInfo member)
|
||||||
{
|
{
|
||||||
base.SetInspectorOwner(inspector, member);
|
base.SetInspectorOwner(inspector, member);
|
||||||
@ -39,13 +45,11 @@ namespace UnityExplorer.CacheObject
|
|||||||
ret = methodInfo.Invoke(DeclaringInstance, Evaluator.TryParseArguments());
|
ret = methodInfo.Invoke(DeclaringInstance, Evaluator.TryParseArguments());
|
||||||
else
|
else
|
||||||
ret = methodInfo.Invoke(DeclaringInstance, ArgumentUtility.EmptyArgs);
|
ret = methodInfo.Invoke(DeclaringInstance, ArgumentUtility.EmptyArgs);
|
||||||
HadException = false;
|
|
||||||
LastException = null;
|
LastException = null;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
HadException = true;
|
|
||||||
LastException = ex;
|
LastException = ex;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -6,13 +6,15 @@ using System.Reflection;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.Core.Runtime;
|
using UnityExplorer.Runtime;
|
||||||
using UnityExplorer.CacheObject.IValues;
|
using UnityExplorer.CacheObject.IValues;
|
||||||
using UnityExplorer.CacheObject.Views;
|
using UnityExplorer.CacheObject.Views;
|
||||||
using UniverseLib.UI.Models;
|
using UniverseLib.UI.Models;
|
||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
using UniverseLib.UI.ObjectPool;
|
||||||
|
|
||||||
namespace UnityExplorer.CacheObject
|
namespace UnityExplorer.CacheObject
|
||||||
{
|
{
|
||||||
@ -55,7 +57,6 @@ namespace UnityExplorer.CacheObject
|
|||||||
public abstract bool ShouldAutoEvaluate { get; }
|
public abstract bool ShouldAutoEvaluate { get; }
|
||||||
public abstract bool HasArguments { get; }
|
public abstract bool HasArguments { get; }
|
||||||
public abstract bool CanWrite { get; }
|
public abstract bool CanWrite { get; }
|
||||||
public bool HadException { get; protected set; }
|
|
||||||
public Exception LastException { get; protected set; }
|
public Exception LastException { get; protected set; }
|
||||||
|
|
||||||
public virtual void SetFallbackType(Type fallbackType)
|
public virtual void SetFallbackType(Type fallbackType)
|
||||||
@ -104,8 +105,8 @@ namespace UnityExplorer.CacheObject
|
|||||||
if (CellView != null)
|
if (CellView != null)
|
||||||
SetDataToCell(CellView);
|
SetDataToCell(CellView);
|
||||||
|
|
||||||
// If the owner's parent CacheObject is set, we are setting the value of an inspected struct.
|
// If the owner's ParentCacheObject is set, we are setting the value of an inspected struct.
|
||||||
// Set the inspector target as the value back to that parent cacheobject.
|
// Set the inspector target as the value back to that parent.
|
||||||
if (Owner.ParentCacheObject != null)
|
if (Owner.ParentCacheObject != null)
|
||||||
Owner.ParentCacheObject.SetUserValue(Owner.Target);
|
Owner.ParentCacheObject.SetUserValue(Owner.Target);
|
||||||
}
|
}
|
||||||
@ -135,7 +136,7 @@ namespace UnityExplorer.CacheObject
|
|||||||
{
|
{
|
||||||
var prevState = State;
|
var prevState = State;
|
||||||
|
|
||||||
if (HadException)
|
if (LastException != null)
|
||||||
{
|
{
|
||||||
LastValueWasNull = true;
|
LastValueWasNull = true;
|
||||||
LastValueType = FallbackType;
|
LastValueType = FallbackType;
|
||||||
@ -156,7 +157,7 @@ namespace UnityExplorer.CacheObject
|
|||||||
{
|
{
|
||||||
// If we changed states (always needs IValue change)
|
// If we changed states (always needs IValue change)
|
||||||
// or if the value is null, and the fallback type isnt string (we always want to edit strings).
|
// or if the value is null, and the fallback type isnt string (we always want to edit strings).
|
||||||
if (State != prevState || (State != ValueState.String && Value.IsNullOrDestroyed()))
|
if (State != prevState || (State != ValueState.String && State != ValueState.Exception && Value.IsNullOrDestroyed()))
|
||||||
{
|
{
|
||||||
// need to return IValue
|
// need to return IValue
|
||||||
ReleaseIValue();
|
ReleaseIValue();
|
||||||
@ -204,7 +205,7 @@ namespace UnityExplorer.CacheObject
|
|||||||
return $"<i>{NOT_YET_EVAL} ({SignatureHighlighter.Parse(FallbackType, true)})</i>";
|
return $"<i>{NOT_YET_EVAL} ({SignatureHighlighter.Parse(FallbackType, true)})</i>";
|
||||||
|
|
||||||
case ValueState.Exception:
|
case ValueState.Exception:
|
||||||
return $"<i><color=red>{LastException.ReflectionExToString()}</color></i>";
|
return $"<i><color=#eb4034>{LastException.ReflectionExToString()}</color></i>";
|
||||||
|
|
||||||
// bool and number dont want the label for the value at all
|
// bool and number dont want the label for the value at all
|
||||||
case ValueState.Boolean:
|
case ValueState.Boolean:
|
||||||
@ -220,10 +221,7 @@ namespace UnityExplorer.CacheObject
|
|||||||
// string wants it trimmed to max 200 chars
|
// string wants it trimmed to max 200 chars
|
||||||
case ValueState.String:
|
case ValueState.String:
|
||||||
if (!LastValueWasNull)
|
if (!LastValueWasNull)
|
||||||
{
|
return $"\"{ToStringUtility.PruneString(Value as string, 200, 5)}\"";
|
||||||
string s = Value as string;
|
|
||||||
return $"\"{ToStringUtility.PruneString(s, 200, 5)}\"";
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// try to prefix the count of the collection for lists and dicts
|
// try to prefix the count of the collection for lists and dicts
|
||||||
@ -257,14 +255,14 @@ namespace UnityExplorer.CacheObject
|
|||||||
|
|
||||||
// Setting cell state from our model
|
// Setting cell state from our model
|
||||||
|
|
||||||
/// <summary>Return true if SetCell should abort, false if it should continue.</summary>
|
/// <summary>Return false if SetCell should abort, true if it should continue.</summary>
|
||||||
protected abstract bool SetCellEvaluateState(CacheObjectCell cell);
|
protected abstract bool TryAutoEvaluateIfUnitialized(CacheObjectCell cell);
|
||||||
|
|
||||||
public virtual void SetDataToCell(CacheObjectCell cell)
|
public virtual void SetDataToCell(CacheObjectCell cell)
|
||||||
{
|
{
|
||||||
cell.NameLabel.text = NameLabelText;
|
cell.NameLabel.text = NameLabelText;
|
||||||
if (cell.HiddenNameLabel != null)
|
if (cell.HiddenNameLabel != null)
|
||||||
cell.HiddenNameLabel.Text = NameLabelTextRaw;
|
cell.HiddenNameLabel.Text = NameLabelTextRaw ?? string.Empty;
|
||||||
cell.ValueLabel.gameObject.SetActive(true);
|
cell.ValueLabel.gameObject.SetActive(true);
|
||||||
|
|
||||||
cell.SubContentHolder.gameObject.SetActive(SubContentShowWanted);
|
cell.SubContentHolder.gameObject.SetActive(SubContentShowWanted);
|
||||||
@ -274,42 +272,54 @@ namespace UnityExplorer.CacheObject
|
|||||||
IValue.SetLayout();
|
IValue.SetLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SetCellEvaluateState(cell))
|
bool evaluated = TryAutoEvaluateIfUnitialized(cell);
|
||||||
|
|
||||||
|
if (cell.CopyButton != null)
|
||||||
|
{
|
||||||
|
bool hasEvaluated = State != ValueState.NotEvaluated && State != ValueState.Exception;
|
||||||
|
cell.CopyButton.Component.gameObject.SetActive(hasEvaluated);
|
||||||
|
cell.PasteButton.Component.gameObject.SetActive(hasEvaluated && this.CanWrite);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!evaluated)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// The following only executes if the object has evaluated.
|
||||||
|
// For members and properties with args, they will return by default now.
|
||||||
|
|
||||||
switch (State)
|
switch (State)
|
||||||
{
|
{
|
||||||
case ValueState.Exception:
|
case ValueState.Exception:
|
||||||
SetValueState(cell, ValueStateArgs.Default);
|
SetValueState(cell, new(true, subContentButtonActive: true));
|
||||||
break;
|
break;
|
||||||
case ValueState.Boolean:
|
case ValueState.Boolean:
|
||||||
SetValueState(cell, new ValueStateArgs(false, toggleActive: true, applyActive: CanWrite));
|
SetValueState(cell, new(false, toggleActive: true, applyActive: CanWrite));
|
||||||
break;
|
break;
|
||||||
case ValueState.Number:
|
case ValueState.Number:
|
||||||
SetValueState(cell, new ValueStateArgs(false, typeLabelActive: true, inputActive: true, applyActive: CanWrite));
|
SetValueState(cell, new(false, typeLabelActive: true, inputActive: true, applyActive: CanWrite));
|
||||||
break;
|
break;
|
||||||
case ValueState.String:
|
case ValueState.String:
|
||||||
if (LastValueWasNull)
|
if (LastValueWasNull)
|
||||||
SetValueState(cell, new ValueStateArgs(true, subContentButtonActive: true));
|
SetValueState(cell, new(true, subContentButtonActive: true));
|
||||||
else
|
else
|
||||||
SetValueState(cell, new ValueStateArgs(true, false, SignatureHighlighter.StringOrange, subContentButtonActive: true));
|
SetValueState(cell, new(true, false, SignatureHighlighter.StringOrange, subContentButtonActive: true));
|
||||||
break;
|
break;
|
||||||
case ValueState.Enum:
|
case ValueState.Enum:
|
||||||
SetValueState(cell, new ValueStateArgs(true, subContentButtonActive: CanWrite));
|
SetValueState(cell, new(true, subContentButtonActive: CanWrite));
|
||||||
break;
|
break;
|
||||||
case ValueState.Color:
|
case ValueState.Color:
|
||||||
case ValueState.ValueStruct:
|
case ValueState.ValueStruct:
|
||||||
if (ParseUtility.CanParse(LastValueType))
|
if (ParseUtility.CanParse(LastValueType))
|
||||||
SetValueState(cell, new ValueStateArgs(false, false, null, true, false, true, CanWrite, true, true));
|
SetValueState(cell, new(false, false, null, true, false, true, CanWrite, true, true));
|
||||||
else
|
else
|
||||||
SetValueState(cell, new ValueStateArgs(true, inspectActive: true, subContentButtonActive: true));
|
SetValueState(cell, new(true, inspectActive: true, subContentButtonActive: true));
|
||||||
break;
|
break;
|
||||||
case ValueState.Collection:
|
case ValueState.Collection:
|
||||||
case ValueState.Dictionary:
|
case ValueState.Dictionary:
|
||||||
SetValueState(cell, new ValueStateArgs(true, inspectActive: !LastValueWasNull, subContentButtonActive: !LastValueWasNull));
|
SetValueState(cell, new(true, inspectActive: !LastValueWasNull, subContentButtonActive: !LastValueWasNull));
|
||||||
break;
|
break;
|
||||||
case ValueState.Unsupported:
|
case ValueState.Unsupported:
|
||||||
SetValueState(cell, new ValueStateArgs(true, inspectActive: !LastValueWasNull));
|
SetValueState(cell, new (true, inspectActive: !LastValueWasNull));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -357,8 +367,10 @@ namespace UnityExplorer.CacheObject
|
|||||||
if (cell.InspectButton != null)
|
if (cell.InspectButton != null)
|
||||||
cell.InspectButton.Component.gameObject.SetActive(args.inspectActive && !LastValueWasNull);
|
cell.InspectButton.Component.gameObject.SetActive(args.inspectActive && !LastValueWasNull);
|
||||||
|
|
||||||
// allow IValue for null strings though
|
// set subcontent button if needed, and for null strings and exceptions
|
||||||
cell.SubContentButton.Component.gameObject.SetActive(args.subContentButtonActive && (!LastValueWasNull || State == ValueState.String));
|
cell.SubContentButton.Component.gameObject.SetActive(
|
||||||
|
args.subContentButtonActive
|
||||||
|
&& (!LastValueWasNull || State == ValueState.String || State == ValueState.Exception));
|
||||||
}
|
}
|
||||||
|
|
||||||
// CacheObjectCell Apply
|
// CacheObjectCell Apply
|
||||||
@ -390,7 +402,7 @@ namespace UnityExplorer.CacheObject
|
|||||||
{
|
{
|
||||||
if (this.IValue == null)
|
if (this.IValue == null)
|
||||||
{
|
{
|
||||||
var ivalueType = InteractiveValue.GetIValueTypeForState(State);
|
Type ivalueType = InteractiveValue.GetIValueTypeForState(State);
|
||||||
|
|
||||||
if (ivalueType == null)
|
if (ivalueType == null)
|
||||||
return;
|
return;
|
||||||
@ -444,6 +456,7 @@ namespace UnityExplorer.CacheObject
|
|||||||
{
|
{
|
||||||
inactiveIValueHolder = new GameObject("Temp_IValue_Holder");
|
inactiveIValueHolder = new GameObject("Temp_IValue_Holder");
|
||||||
GameObject.DontDestroyOnLoad(inactiveIValueHolder);
|
GameObject.DontDestroyOnLoad(inactiveIValueHolder);
|
||||||
|
inactiveIValueHolder.hideFlags = HideFlags.HideAndDontSave;
|
||||||
inactiveIValueHolder.transform.parent = UniversalUI.PoolHolder.transform;
|
inactiveIValueHolder.transform.parent = UniversalUI.PoolHolder.transform;
|
||||||
inactiveIValueHolder.SetActive(false);
|
inactiveIValueHolder.SetActive(false);
|
||||||
}
|
}
|
||||||
@ -456,9 +469,20 @@ namespace UnityExplorer.CacheObject
|
|||||||
|
|
||||||
public struct ValueStateArgs
|
public struct ValueStateArgs
|
||||||
{
|
{
|
||||||
public ValueStateArgs(bool valueActive = true, bool valueRichText = true, Color? valueColor = null,
|
public static ValueStateArgs Default { get; } = new(true);
|
||||||
bool typeLabelActive = false, bool toggleActive = false, bool inputActive = false, bool applyActive = false,
|
|
||||||
bool inspectActive = false, bool subContentButtonActive = false)
|
public Color valueColor;
|
||||||
|
public bool valueActive, valueRichText, typeLabelActive, toggleActive, inputActive, applyActive, inspectActive, subContentButtonActive;
|
||||||
|
|
||||||
|
public ValueStateArgs(bool valueActive = true,
|
||||||
|
bool valueRichText = true,
|
||||||
|
Color? valueColor = null,
|
||||||
|
bool typeLabelActive = false,
|
||||||
|
bool toggleActive = false,
|
||||||
|
bool inputActive = false,
|
||||||
|
bool applyActive = false,
|
||||||
|
bool inspectActive = false,
|
||||||
|
bool subContentButtonActive = false)
|
||||||
{
|
{
|
||||||
this.valueActive = valueActive;
|
this.valueActive = valueActive;
|
||||||
this.valueRichText = valueRichText;
|
this.valueRichText = valueRichText;
|
||||||
@ -470,14 +494,6 @@ namespace UnityExplorer.CacheObject
|
|||||||
this.inspectActive = inspectActive;
|
this.inspectActive = inspectActive;
|
||||||
this.subContentButtonActive = subContentButtonActive;
|
this.subContentButtonActive = subContentButtonActive;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ValueStateArgs Default => _default;
|
|
||||||
private static ValueStateArgs _default = new ValueStateArgs(true);
|
|
||||||
|
|
||||||
public bool valueActive, valueRichText, typeLabelActive, toggleActive,
|
|
||||||
inputActive, applyActive, inspectActive, subContentButtonActive;
|
|
||||||
|
|
||||||
public Color valueColor;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,9 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using UnityEngine;
|
||||||
using UnityExplorer.Inspectors;
|
using UnityExplorer.Inspectors;
|
||||||
|
using UnityExplorer.Runtime;
|
||||||
|
|
||||||
namespace UnityExplorer.CacheObject
|
namespace UnityExplorer.CacheObject
|
||||||
{
|
{
|
||||||
@ -17,6 +19,11 @@ namespace UnityExplorer.CacheObject
|
|||||||
|
|
||||||
public override bool ShouldAutoEvaluate => !HasArguments;
|
public override bool ShouldAutoEvaluate => !HasArguments;
|
||||||
|
|
||||||
|
public CacheProperty(PropertyInfo pi)
|
||||||
|
{
|
||||||
|
this.PropertyInfo = pi;
|
||||||
|
}
|
||||||
|
|
||||||
public override void SetInspectorOwner(ReflectionInspector inspector, MemberInfo member)
|
public override void SetInspectorOwner(ReflectionInspector inspector, MemberInfo member)
|
||||||
{
|
{
|
||||||
base.SetInspectorOwner(inspector, member);
|
base.SetInspectorOwner(inspector, member);
|
||||||
@ -33,13 +40,11 @@ namespace UnityExplorer.CacheObject
|
|||||||
ret = PropertyInfo.GetValue(DeclaringInstance, this.Evaluator.TryParseArguments());
|
ret = PropertyInfo.GetValue(DeclaringInstance, this.Evaluator.TryParseArguments());
|
||||||
else
|
else
|
||||||
ret = PropertyInfo.GetValue(DeclaringInstance, null);
|
ret = PropertyInfo.GetValue(DeclaringInstance, null);
|
||||||
HadException = false;
|
|
||||||
LastException = null;
|
LastException = null;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
HadException = true;
|
|
||||||
LastException = ex;
|
LastException = ex;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,8 @@ using UnityEngine.UI;
|
|||||||
using UnityExplorer.CacheObject;
|
using UnityExplorer.CacheObject;
|
||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
|
using UniverseLib.UI.Models;
|
||||||
|
using UniverseLib;
|
||||||
|
|
||||||
namespace UnityExplorer.CacheObject.IValues
|
namespace UnityExplorer.CacheObject.IValues
|
||||||
{
|
{
|
||||||
@ -16,11 +18,11 @@ namespace UnityExplorer.CacheObject.IValues
|
|||||||
|
|
||||||
public Color EditedColor;
|
public Color EditedColor;
|
||||||
|
|
||||||
private Image m_colorImage;
|
private Image colorImage;
|
||||||
private readonly InputFieldRef[] m_inputs = new InputFieldRef[4];
|
private readonly InputFieldRef[] inputs = new InputFieldRef[4];
|
||||||
private readonly Slider[] m_sliders = new Slider[4];
|
private readonly Slider[] sliders = new Slider[4];
|
||||||
|
|
||||||
private ButtonRef m_applyButton;
|
private ButtonRef applyButton;
|
||||||
|
|
||||||
private static readonly string[] fieldNames = new[] { "R", "G", "B", "A" };
|
private static readonly string[] fieldNames = new[] { "R", "G", "B", "A" };
|
||||||
|
|
||||||
@ -28,11 +30,11 @@ namespace UnityExplorer.CacheObject.IValues
|
|||||||
{
|
{
|
||||||
base.OnBorrowed(owner);
|
base.OnBorrowed(owner);
|
||||||
|
|
||||||
m_applyButton.Component.gameObject.SetActive(owner.CanWrite);
|
applyButton.Component.gameObject.SetActive(owner.CanWrite);
|
||||||
|
|
||||||
foreach (var slider in m_sliders)
|
foreach (var slider in sliders)
|
||||||
slider.interactable = owner.CanWrite;
|
slider.interactable = owner.CanWrite;
|
||||||
foreach (var input in m_inputs)
|
foreach (var input in inputs)
|
||||||
input.Component.readOnly = !owner.CanWrite;
|
input.Component.readOnly = !owner.CanWrite;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,27 +50,27 @@ namespace UnityExplorer.CacheObject.IValues
|
|||||||
{
|
{
|
||||||
IsValueColor32 = true;
|
IsValueColor32 = true;
|
||||||
EditedColor = c32;
|
EditedColor = c32;
|
||||||
m_inputs[0].Text = c32.r.ToString();
|
inputs[0].Text = c32.r.ToString();
|
||||||
m_inputs[1].Text = c32.g.ToString();
|
inputs[1].Text = c32.g.ToString();
|
||||||
m_inputs[2].Text = c32.b.ToString();
|
inputs[2].Text = c32.b.ToString();
|
||||||
m_inputs[3].Text = c32.a.ToString();
|
inputs[3].Text = c32.a.ToString();
|
||||||
foreach (var slider in m_sliders)
|
foreach (var slider in sliders)
|
||||||
slider.maxValue = 255;
|
slider.maxValue = 255;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
IsValueColor32 = false;
|
IsValueColor32 = false;
|
||||||
EditedColor = (Color)value;
|
EditedColor = (Color)value;
|
||||||
m_inputs[0].Text = EditedColor.r.ToString();
|
inputs[0].Text = EditedColor.r.ToString();
|
||||||
m_inputs[1].Text = EditedColor.g.ToString();
|
inputs[1].Text = EditedColor.g.ToString();
|
||||||
m_inputs[2].Text = EditedColor.b.ToString();
|
inputs[2].Text = EditedColor.b.ToString();
|
||||||
m_inputs[3].Text = EditedColor.a.ToString();
|
inputs[3].Text = EditedColor.a.ToString();
|
||||||
foreach (var slider in m_sliders)
|
foreach (var slider in sliders)
|
||||||
slider.maxValue = 1;
|
slider.maxValue = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_colorImage)
|
if (colorImage)
|
||||||
m_colorImage.color = EditedColor;
|
colorImage.color = EditedColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
// setting value to owner
|
// setting value to owner
|
||||||
@ -91,8 +93,8 @@ namespace UnityExplorer.CacheObject.IValues
|
|||||||
case 3: EditedColor.a = val; break;
|
case 3: EditedColor.a = val; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_colorImage)
|
if (colorImage)
|
||||||
m_colorImage.color = EditedColor;
|
colorImage.color = EditedColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnInputChanged(string val, int fieldIndex)
|
private void OnInputChanged(string val, int fieldIndex)
|
||||||
@ -103,13 +105,13 @@ namespace UnityExplorer.CacheObject.IValues
|
|||||||
if (IsValueColor32)
|
if (IsValueColor32)
|
||||||
{
|
{
|
||||||
byte value = byte.Parse(val);
|
byte value = byte.Parse(val);
|
||||||
m_sliders[fieldIndex].value = value;
|
sliders[fieldIndex].value = value;
|
||||||
f = (float)((decimal)value / 255);
|
f = (float)((decimal)value / 255);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
f = float.Parse(val);
|
f = float.Parse(val);
|
||||||
m_sliders[fieldIndex].value = f;
|
sliders[fieldIndex].value = f;
|
||||||
}
|
}
|
||||||
|
|
||||||
SetColorField(f, fieldIndex);
|
SetColorField(f, fieldIndex);
|
||||||
@ -129,12 +131,12 @@ namespace UnityExplorer.CacheObject.IValues
|
|||||||
{
|
{
|
||||||
if (IsValueColor32)
|
if (IsValueColor32)
|
||||||
{
|
{
|
||||||
m_inputs[fieldIndex].Text = ((byte)val).ToString();
|
inputs[fieldIndex].Text = ((byte)val).ToString();
|
||||||
val /= 255f;
|
val /= 255f;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_inputs[fieldIndex].Text = val.ToString();
|
inputs[fieldIndex].Text = val.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
SetColorField(val, fieldIndex);
|
SetColorField(val, fieldIndex);
|
||||||
@ -167,15 +169,15 @@ namespace UnityExplorer.CacheObject.IValues
|
|||||||
|
|
||||||
// apply button
|
// apply button
|
||||||
|
|
||||||
m_applyButton = UIFactory.CreateButton(horiGroup, "ApplyButton", "Apply", new Color(0.2f, 0.26f, 0.2f));
|
applyButton = UIFactory.CreateButton(horiGroup, "ApplyButton", "Apply", new Color(0.2f, 0.26f, 0.2f));
|
||||||
UIFactory.SetLayoutElement(m_applyButton.Component.gameObject, minHeight: 25, minWidth: 90);
|
UIFactory.SetLayoutElement(applyButton.Component.gameObject, minHeight: 25, minWidth: 90);
|
||||||
m_applyButton.OnClick += SetValueToOwner;
|
applyButton.OnClick += SetValueToOwner;
|
||||||
|
|
||||||
// image of color
|
// image of color
|
||||||
|
|
||||||
var imgObj = UIFactory.CreateUIObject("ColorImageHelper", horiGroup);
|
var imgObj = UIFactory.CreateUIObject("ColorImageHelper", horiGroup);
|
||||||
UIFactory.SetLayoutElement(imgObj, minHeight: 25, minWidth: 50, flexibleWidth: 50);
|
UIFactory.SetLayoutElement(imgObj, minHeight: 25, minWidth: 50, flexibleWidth: 50);
|
||||||
m_colorImage = imgObj.AddComponent<Image>();
|
colorImage = imgObj.AddComponent<Image>();
|
||||||
|
|
||||||
return UIRoot;
|
return UIRoot;
|
||||||
}
|
}
|
||||||
@ -190,11 +192,11 @@ namespace UnityExplorer.CacheObject.IValues
|
|||||||
|
|
||||||
var input = UIFactory.CreateInputField(row, "Input", "...");
|
var input = UIFactory.CreateInputField(row, "Input", "...");
|
||||||
UIFactory.SetLayoutElement(input.UIRoot, minWidth: 40, minHeight: 25, flexibleHeight: 0);
|
UIFactory.SetLayoutElement(input.UIRoot, minWidth: 40, minHeight: 25, flexibleHeight: 0);
|
||||||
m_inputs[index] = input;
|
inputs[index] = input;
|
||||||
input.OnValueChanged += (string val) => { OnInputChanged(val, index); };
|
input.OnValueChanged += (string val) => { OnInputChanged(val, index); };
|
||||||
|
|
||||||
var sliderObj = UIFactory.CreateSlider(row, "Slider", out Slider slider);
|
var sliderObj = UIFactory.CreateSlider(row, "Slider", out Slider slider);
|
||||||
m_sliders[index] = slider;
|
sliders[index] = slider;
|
||||||
UIFactory.SetLayoutElement(sliderObj, minHeight: 25, minWidth: 70, flexibleWidth: 999, flexibleHeight: 0);
|
UIFactory.SetLayoutElement(sliderObj, minHeight: 25, minWidth: 70, flexibleWidth: 999, flexibleHeight: 0);
|
||||||
slider.minValue = 0;
|
slider.minValue = 0;
|
||||||
slider.maxValue = 1;
|
slider.maxValue = 1;
|
||||||
|
@ -14,6 +14,8 @@ using UnityExplorer.UI.Widgets;
|
|||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
using UniverseLib.UI.Widgets;
|
using UniverseLib.UI.Widgets;
|
||||||
|
using UniverseLib.UI.Widgets.ScrollView;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.CacheObject.IValues
|
namespace UnityExplorer.CacheObject.IValues
|
||||||
{
|
{
|
||||||
|
@ -7,7 +7,11 @@ using UnityEngine;
|
|||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.CacheObject;
|
using UnityExplorer.CacheObject;
|
||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
|
using UnityExplorer.UI.Widgets.AutoComplete;
|
||||||
|
using UniverseLib;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
|
using UniverseLib.UI.Models;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.CacheObject.IValues
|
namespace UnityExplorer.CacheObject.IValues
|
||||||
{
|
{
|
||||||
@ -20,13 +24,16 @@ namespace UnityExplorer.CacheObject.IValues
|
|||||||
|
|
||||||
public OrderedDictionary CurrentValues;
|
public OrderedDictionary CurrentValues;
|
||||||
|
|
||||||
public CachedEnumValue ValueAtIdx(int idx) => (CachedEnumValue)CurrentValues[idx];
|
private InputFieldRef inputField;
|
||||||
public CachedEnumValue ValueAtKey(object key) => (CachedEnumValue)CurrentValues[key];
|
private ButtonRef enumHelperButton;
|
||||||
|
private EnumCompleter enumCompleter;
|
||||||
|
|
||||||
private Dropdown enumDropdown;
|
|
||||||
private GameObject toggleHolder;
|
private GameObject toggleHolder;
|
||||||
private readonly List<Toggle> flagToggles = new List<Toggle>();
|
private readonly List<Toggle> flagToggles = new();
|
||||||
private readonly List<Text> flagTexts = new List<Text>();
|
private readonly List<Text> flagTexts = new();
|
||||||
|
|
||||||
|
public CachedEnumValue ValueAtIndex(int idx) => (CachedEnumValue)CurrentValues[idx];
|
||||||
|
public CachedEnumValue ValueAtKey(object key) => (CachedEnumValue)CurrentValues[key];
|
||||||
|
|
||||||
// Setting value from owner
|
// Setting value from owner
|
||||||
public override void SetValue(object value)
|
public override void SetValue(object value)
|
||||||
@ -35,38 +42,63 @@ namespace UnityExplorer.CacheObject.IValues
|
|||||||
|
|
||||||
if (lastType != EnumType)
|
if (lastType != EnumType)
|
||||||
{
|
{
|
||||||
CurrentValues = GetEnumValues(EnumType, out IsFlags);
|
CurrentValues = GetEnumValues(EnumType);
|
||||||
|
|
||||||
|
IsFlags = EnumType.GetCustomAttributes(typeof(FlagsAttribute), true) is object[] fa && fa.Any();
|
||||||
if (IsFlags)
|
if (IsFlags)
|
||||||
SetupTogglesForEnumType();
|
SetupTogglesForEnumType();
|
||||||
else
|
else
|
||||||
SetupDropdownForEnumType();
|
{
|
||||||
|
inputField.Component.gameObject.SetActive(true);
|
||||||
|
enumHelperButton.Component.gameObject.SetActive(true);
|
||||||
|
toggleHolder.SetActive(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
enumCompleter.EnumType = EnumType;
|
||||||
|
enumCompleter.CacheEnumValues();
|
||||||
|
|
||||||
lastType = EnumType;
|
lastType = EnumType;
|
||||||
}
|
}
|
||||||
|
|
||||||
// setup ui for changes
|
if (!IsFlags)
|
||||||
if (IsFlags)
|
inputField.Text = value.ToString();
|
||||||
SetTogglesForValue(value);
|
|
||||||
else
|
else
|
||||||
SetDropdownForValue(value);
|
SetTogglesForValue(value);
|
||||||
|
|
||||||
|
this.enumCompleter.chosenSuggestion = value.ToString();
|
||||||
|
AutoCompleteModal.Instance.ReleaseOwnership(this.enumCompleter);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetTogglesForValue(object value)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
for (int i = 0; i < CurrentValues.Count; i++)
|
||||||
|
flagToggles[i].isOn = (value as Enum).HasFlag(ValueAtIndex(i).ActualValue as Enum);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
ExplorerCore.LogWarning("Exception setting flag toggles: " + ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setting value to owner
|
// Setting value to owner
|
||||||
|
|
||||||
private void OnApplyClicked()
|
private void OnApplyClicked()
|
||||||
{
|
|
||||||
if (IsFlags)
|
|
||||||
SetValueFromFlags();
|
|
||||||
else
|
|
||||||
SetValueFromDropdown();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SetValueFromDropdown()
|
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
CurrentOwner.SetUserValue(ValueAtIdx(enumDropdown.value).ActualValue);
|
if (!IsFlags)
|
||||||
|
{
|
||||||
|
if (ParseUtility.TryParse(this.inputField.Text, EnumType, out object value, out Exception ex))
|
||||||
|
CurrentOwner.SetUserValue(value);
|
||||||
|
else
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SetValueFromFlags();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@ -82,7 +114,7 @@ namespace UnityExplorer.CacheObject.IValues
|
|||||||
for (int i = 0; i < CurrentValues.Count; i++)
|
for (int i = 0; i < CurrentValues.Count; i++)
|
||||||
{
|
{
|
||||||
if (flagToggles[i].isOn)
|
if (flagToggles[i].isOn)
|
||||||
values.Add(ValueAtIdx(i).Name);
|
values.Add(ValueAtIndex(i).Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
CurrentOwner.SetUserValue(Enum.Parse(EnumType, string.Join(", ", values.ToArray())));
|
CurrentOwner.SetUserValue(Enum.Parse(EnumType, string.Join(", ", values.ToArray())));
|
||||||
@ -93,59 +125,50 @@ namespace UnityExplorer.CacheObject.IValues
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// setting UI state for value
|
// UI Construction
|
||||||
|
|
||||||
private void SetDropdownForValue(object value)
|
private void EnumHelper_OnClick()
|
||||||
{
|
{
|
||||||
if (CurrentValues.Contains(value))
|
enumCompleter.HelperButtonClicked();
|
||||||
{
|
|
||||||
var cached = ValueAtKey(value);
|
|
||||||
enumDropdown.value = cached.EnumIndex;
|
|
||||||
enumDropdown.RefreshShownValue();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ExplorerCore.LogWarning("CurrentValues does not contain key '" + value?.ToString() ?? "<null>" + "'");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetTogglesForValue(object value)
|
public override GameObject CreateContent(GameObject parent)
|
||||||
{
|
{
|
||||||
try
|
UIRoot = UIFactory.CreateVerticalGroup(parent, "InteractiveEnum", false, false, true, true, 3, new Vector4(4, 4, 4, 4),
|
||||||
{
|
new Color(0.06f, 0.06f, 0.06f));
|
||||||
var split = value.ToString().Split(',');
|
UIFactory.SetLayoutElement(UIRoot, minHeight: 25, flexibleHeight: 9999, flexibleWidth: 9999);
|
||||||
var set = new HashSet<string>();
|
|
||||||
foreach (var s in split)
|
|
||||||
set.Add(s.Trim());
|
|
||||||
|
|
||||||
for (int i = 0; i < CurrentValues.Count; i++)
|
var hori = UIFactory.CreateUIObject("Hori", UIRoot);
|
||||||
flagToggles[i].isOn = set.Contains(ValueAtIdx(i).Name);
|
UIFactory.SetLayoutElement(hori, minHeight: 25, flexibleWidth: 9999);
|
||||||
}
|
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(hori, false, false, true, true, 2);
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
ExplorerCore.LogWarning("Exception setting flag toggles: " + ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setting up the UI for the enum type when it changes or is first set
|
var applyButton = UIFactory.CreateButton(hori, "ApplyButton", "Apply", new Color(0.2f, 0.27f, 0.2f));
|
||||||
|
UIFactory.SetLayoutElement(applyButton.Component.gameObject, minHeight: 25, minWidth: 100);
|
||||||
|
applyButton.OnClick += OnApplyClicked;
|
||||||
|
|
||||||
private void SetupDropdownForEnumType()
|
inputField = UIFactory.CreateInputField(hori, "InputField", "Enter name or underlying value...");
|
||||||
{
|
UIFactory.SetLayoutElement(inputField.UIRoot, minHeight: 25, flexibleHeight: 50, minWidth: 100, flexibleWidth: 1000);
|
||||||
toggleHolder.SetActive(false);
|
inputField.Component.lineType = InputField.LineType.MultiLineNewline;
|
||||||
enumDropdown.gameObject.SetActive(true);
|
inputField.UIRoot.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||||||
|
|
||||||
// create dropdown entries
|
enumHelperButton = UIFactory.CreateButton(hori, "EnumHelper", "▼");
|
||||||
enumDropdown.options.Clear();
|
UIFactory.SetLayoutElement(enumHelperButton.Component.gameObject, minWidth: 25, minHeight: 25, flexibleWidth: 0, flexibleHeight: 0);
|
||||||
|
enumHelperButton.OnClick += EnumHelper_OnClick;
|
||||||
|
|
||||||
foreach (CachedEnumValue entry in CurrentValues.Values)
|
enumCompleter = new EnumCompleter(this.EnumType, this.inputField);
|
||||||
enumDropdown.options.Add(new Dropdown.OptionData(entry.Name));
|
|
||||||
|
|
||||||
enumDropdown.value = 0;
|
toggleHolder = UIFactory.CreateUIObject("ToggleHolder", UIRoot);
|
||||||
enumDropdown.RefreshShownValue();
|
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(toggleHolder, false, false, true, true, 4);
|
||||||
|
UIFactory.SetLayoutElement(toggleHolder, minHeight: 25, flexibleWidth: 9999, flexibleHeight: 9999);
|
||||||
|
|
||||||
|
return UIRoot;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetupTogglesForEnumType()
|
private void SetupTogglesForEnumType()
|
||||||
{
|
{
|
||||||
toggleHolder.SetActive(true);
|
toggleHolder.SetActive(true);
|
||||||
enumDropdown.gameObject.SetActive(false);
|
inputField.Component.gameObject.SetActive(false);
|
||||||
|
enumHelperButton.Component.gameObject.SetActive(false);
|
||||||
|
|
||||||
// create / set / hide toggles
|
// create / set / hide toggles
|
||||||
for (int i = 0; i < CurrentValues.Count || i < flagToggles.Count; i++)
|
for (int i = 0; i < CurrentValues.Count || i < flagToggles.Count; i++)
|
||||||
@ -163,7 +186,7 @@ namespace UnityExplorer.CacheObject.IValues
|
|||||||
AddToggleRow();
|
AddToggleRow();
|
||||||
|
|
||||||
flagToggles[i].isOn = false;
|
flagToggles[i].isOn = false;
|
||||||
flagTexts[i].text = ValueAtIdx(i).Name;
|
flagTexts[i].text = ValueAtIndex(i).Name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -180,54 +203,13 @@ namespace UnityExplorer.CacheObject.IValues
|
|||||||
flagTexts.Add(toggleText);
|
flagTexts.Add(toggleText);
|
||||||
}
|
}
|
||||||
|
|
||||||
// UI Construction
|
|
||||||
|
|
||||||
public override GameObject CreateContent(GameObject parent)
|
|
||||||
{
|
|
||||||
UIRoot = UIFactory.CreateVerticalGroup(parent, "InteractiveEnum", false, false, true, true, 3, new Vector4(4, 4, 4, 4),
|
|
||||||
new Color(0.06f, 0.06f, 0.06f));
|
|
||||||
UIFactory.SetLayoutElement(UIRoot, minHeight: 25, flexibleHeight: 9999, flexibleWidth: 9999);
|
|
||||||
|
|
||||||
var hori = UIFactory.CreateUIObject("Hori", UIRoot);
|
|
||||||
UIFactory.SetLayoutElement(hori, minHeight: 25, flexibleWidth: 9999);
|
|
||||||
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(hori, false, false, true, true, 2);
|
|
||||||
|
|
||||||
var applyButton = UIFactory.CreateButton(hori, "ApplyButton", "Apply", new Color(0.2f, 0.27f, 0.2f));
|
|
||||||
UIFactory.SetLayoutElement(applyButton.Component.gameObject, minHeight: 25, minWidth: 100);
|
|
||||||
applyButton.OnClick += OnApplyClicked;
|
|
||||||
|
|
||||||
var dropdownObj = UIFactory.CreateDropdown(hori, out enumDropdown, "not set", 14, null);
|
|
||||||
UIFactory.SetLayoutElement(dropdownObj, minHeight: 25, flexibleWidth: 600);
|
|
||||||
|
|
||||||
toggleHolder = UIFactory.CreateUIObject("ToggleHolder", UIRoot);
|
|
||||||
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(toggleHolder, false, false, true, true, 4);
|
|
||||||
UIFactory.SetLayoutElement(toggleHolder, minHeight: 25, flexibleWidth: 9999, flexibleHeight: 9999);
|
|
||||||
|
|
||||||
return UIRoot;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#region Enum cache
|
#region Enum cache
|
||||||
|
|
||||||
public struct CachedEnumValue
|
|
||||||
{
|
|
||||||
public CachedEnumValue(object value, int index, string name)
|
|
||||||
{
|
|
||||||
EnumIndex = index;
|
|
||||||
Name = name;
|
|
||||||
ActualValue = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public readonly object ActualValue;
|
|
||||||
public int EnumIndex;
|
|
||||||
public readonly string Name;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static readonly Dictionary<string, OrderedDictionary> enumCache = new Dictionary<string, OrderedDictionary>();
|
internal static readonly Dictionary<string, OrderedDictionary> enumCache = new Dictionary<string, OrderedDictionary>();
|
||||||
|
|
||||||
internal static OrderedDictionary GetEnumValues(Type enumType, out bool isFlags)
|
internal static OrderedDictionary GetEnumValues(Type enumType)
|
||||||
{
|
{
|
||||||
isFlags = enumType.GetCustomAttributes(typeof(FlagsAttribute), true) is object[] fa && fa.Any();
|
//isFlags = enumType.GetCustomAttributes(typeof(FlagsAttribute), true) is object[] fa && fa.Any();
|
||||||
|
|
||||||
if (!enumCache.ContainsKey(enumType.AssemblyQualifiedName))
|
if (!enumCache.ContainsKey(enumType.AssemblyQualifiedName))
|
||||||
{
|
{
|
||||||
@ -254,4 +236,18 @@ namespace UnityExplorer.CacheObject.IValues
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public struct CachedEnumValue
|
||||||
|
{
|
||||||
|
public CachedEnumValue(object value, int index, string name)
|
||||||
|
{
|
||||||
|
EnumIndex = index;
|
||||||
|
Name = name;
|
||||||
|
ActualValue = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public readonly object ActualValue;
|
||||||
|
public int EnumIndex;
|
||||||
|
public readonly string Name;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,8 @@ using UnityExplorer.UI.Widgets;
|
|||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
using UniverseLib.UI.Widgets;
|
using UniverseLib.UI.Widgets;
|
||||||
|
using UniverseLib.UI.Widgets.ScrollView;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.CacheObject.IValues
|
namespace UnityExplorer.CacheObject.IValues
|
||||||
{
|
{
|
||||||
@ -32,11 +34,13 @@ namespace UnityExplorer.CacheObject.IValues
|
|||||||
private PropertyInfo genericIndexer;
|
private PropertyInfo genericIndexer;
|
||||||
|
|
||||||
public int ItemCount => cachedEntries.Count;
|
public int ItemCount => cachedEntries.Count;
|
||||||
private readonly List<CacheListEntry> cachedEntries = new List<CacheListEntry>();
|
private readonly List<CacheListEntry> cachedEntries = new();
|
||||||
|
|
||||||
public ScrollPool<CacheListEntryCell> ListScrollPool { get; private set; }
|
public ScrollPool<CacheListEntryCell> ListScrollPool { get; private set; }
|
||||||
|
|
||||||
public Text TopLabel;
|
public Text TopLabel;
|
||||||
|
private LayoutElement scrollLayout;
|
||||||
|
private Text NotSupportedLabel;
|
||||||
|
|
||||||
public override void OnBorrowed(CacheObjectBase owner)
|
public override void OnBorrowed(CacheObjectBase owner)
|
||||||
{
|
{
|
||||||
@ -65,6 +69,28 @@ namespace UnityExplorer.CacheObject.IValues
|
|||||||
cachedEntries.Clear();
|
cachedEntries.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// List entry scroll pool
|
||||||
|
|
||||||
|
public override void SetLayout()
|
||||||
|
{
|
||||||
|
var minHeight = 5f;
|
||||||
|
|
||||||
|
foreach (var cell in ListScrollPool.CellPool)
|
||||||
|
{
|
||||||
|
if (cell.Enabled)
|
||||||
|
minHeight += cell.Rect.rect.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.scrollLayout.minHeight = Math.Min(InspectorPanel.CurrentPanelHeight - 400f, minHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnCellBorrowed(CacheListEntryCell cell) { } // not needed
|
||||||
|
|
||||||
|
public void SetCell(CacheListEntryCell cell, int index)
|
||||||
|
{
|
||||||
|
CacheObjectControllerHelper.SetCell(cell, index, cachedEntries, null);
|
||||||
|
}
|
||||||
|
|
||||||
// Setting the List value itself to this model
|
// Setting the List value itself to this model
|
||||||
public override void SetValue(object value)
|
public override void SetValue(object value)
|
||||||
{
|
{
|
||||||
@ -212,32 +238,6 @@ namespace UnityExplorer.CacheObject.IValues
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// List entry scroll pool
|
|
||||||
|
|
||||||
public override void SetLayout()
|
|
||||||
{
|
|
||||||
var minHeight = 5f;
|
|
||||||
|
|
||||||
foreach (var cell in ListScrollPool.CellPool)
|
|
||||||
{
|
|
||||||
if (cell.Enabled)
|
|
||||||
minHeight += cell.Rect.rect.height;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.scrollLayout.minHeight = Math.Min(InspectorPanel.CurrentPanelHeight - 400f, minHeight);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnCellBorrowed(CacheListEntryCell cell) { } // not needed
|
|
||||||
|
|
||||||
public void SetCell(CacheListEntryCell cell, int index)
|
|
||||||
{
|
|
||||||
CacheObjectControllerHelper.SetCell(cell, index, cachedEntries, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
private LayoutElement scrollLayout;
|
|
||||||
|
|
||||||
private Text NotSupportedLabel;
|
|
||||||
|
|
||||||
public override GameObject CreateContent(GameObject parent)
|
public override GameObject CreateContent(GameObject parent)
|
||||||
{
|
{
|
||||||
UIRoot = UIFactory.CreateVerticalGroup(parent, "InteractiveList", true, true, true, true, 6, new Vector4(10, 3, 15, 4),
|
UIRoot = UIFactory.CreateVerticalGroup(parent, "InteractiveList", true, true, true, true, 6, new Vector4(10, 3, 15, 4),
|
||||||
|
@ -5,12 +5,14 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.Core.Config;
|
using UnityExplorer.Config;
|
||||||
using UnityExplorer.CacheObject;
|
using UnityExplorer.CacheObject;
|
||||||
using UnityExplorer.UI.Widgets;
|
using UnityExplorer.UI.Widgets;
|
||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
|
using UniverseLib.UI.Models;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.CacheObject.IValues
|
namespace UnityExplorer.CacheObject.IValues
|
||||||
{
|
{
|
||||||
@ -29,8 +31,9 @@ namespace UnityExplorer.CacheObject.IValues
|
|||||||
{
|
{
|
||||||
base.OnBorrowed(owner);
|
base.OnBorrowed(owner);
|
||||||
|
|
||||||
inputField.Component.readOnly = !owner.CanWrite;
|
bool canWrite = owner.CanWrite && owner.State != ValueState.Exception;
|
||||||
ApplyButton.Component.gameObject.SetActive(owner.CanWrite);
|
inputField.Component.readOnly = !canWrite;
|
||||||
|
ApplyButton.Component.gameObject.SetActive(canWrite);
|
||||||
|
|
||||||
SaveFilePath.Text = Path.Combine(ConfigManager.Default_Output_Path.Value, "untitled.txt");
|
SaveFilePath.Text = Path.Combine(ConfigManager.Default_Output_Path.Value, "untitled.txt");
|
||||||
}
|
}
|
||||||
@ -45,6 +48,9 @@ namespace UnityExplorer.CacheObject.IValues
|
|||||||
|
|
||||||
public override void SetValue(object value)
|
public override void SetValue(object value)
|
||||||
{
|
{
|
||||||
|
if (CurrentOwner.State == ValueState.Exception)
|
||||||
|
value = CurrentOwner.LastException.ToString();
|
||||||
|
|
||||||
RealValue = value as string;
|
RealValue = value as string;
|
||||||
SaveFileRow.SetActive(IsStringTooLong(RealValue));
|
SaveFileRow.SetActive(IsStringTooLong(RealValue));
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ using UnityExplorer.CacheObject;
|
|||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
using UniverseLib.UI.Models;
|
using UniverseLib.UI.Models;
|
||||||
|
using UniverseLib.UI.ObjectPool;
|
||||||
|
|
||||||
namespace UnityExplorer.CacheObject.IValues
|
namespace UnityExplorer.CacheObject.IValues
|
||||||
{
|
{
|
||||||
@ -15,22 +16,16 @@ namespace UnityExplorer.CacheObject.IValues
|
|||||||
{
|
{
|
||||||
public static Type GetIValueTypeForState(ValueState state)
|
public static Type GetIValueTypeForState(ValueState state)
|
||||||
{
|
{
|
||||||
switch (state)
|
return state switch
|
||||||
{
|
{
|
||||||
case ValueState.String:
|
ValueState.Exception or ValueState.String => typeof(InteractiveString),
|
||||||
return typeof(InteractiveString);
|
ValueState.Enum => typeof(InteractiveEnum),
|
||||||
case ValueState.Enum:
|
ValueState.Collection => typeof(InteractiveList),
|
||||||
return typeof(InteractiveEnum);
|
ValueState.Dictionary => typeof(InteractiveDictionary),
|
||||||
case ValueState.Collection:
|
ValueState.ValueStruct => typeof(InteractiveValueStruct),
|
||||||
return typeof(InteractiveList);
|
ValueState.Color => typeof(InteractiveColor),
|
||||||
case ValueState.Dictionary:
|
_ => null,
|
||||||
return typeof(InteractiveDictionary);
|
};
|
||||||
case ValueState.ValueStruct:
|
|
||||||
return typeof(InteractiveValueStruct);
|
|
||||||
case ValueState.Color:
|
|
||||||
return typeof(InteractiveColor);
|
|
||||||
default: return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public GameObject UIRoot { get; set; }
|
public GameObject UIRoot { get; set; }
|
||||||
@ -38,28 +33,28 @@ namespace UnityExplorer.CacheObject.IValues
|
|||||||
|
|
||||||
public virtual bool CanWrite => this.CurrentOwner.CanWrite;
|
public virtual bool CanWrite => this.CurrentOwner.CanWrite;
|
||||||
|
|
||||||
public CacheObjectBase CurrentOwner => m_owner;
|
public CacheObjectBase CurrentOwner => owner;
|
||||||
private CacheObjectBase m_owner;
|
private CacheObjectBase owner;
|
||||||
|
|
||||||
public bool PendingValueWanted;
|
public bool PendingValueWanted;
|
||||||
|
|
||||||
public virtual void OnBorrowed(CacheObjectBase owner)
|
public virtual void OnBorrowed(CacheObjectBase owner)
|
||||||
{
|
{
|
||||||
if (this.m_owner != null)
|
if (this.owner != null)
|
||||||
{
|
{
|
||||||
ExplorerCore.LogWarning("Setting an IValue's owner but there is already one set. Maybe it wasn't cleaned up?");
|
ExplorerCore.LogWarning("Setting an IValue's owner but there is already one set. Maybe it wasn't cleaned up?");
|
||||||
ReleaseFromOwner();
|
ReleaseFromOwner();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.m_owner = owner;
|
this.owner = owner;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void ReleaseFromOwner()
|
public virtual void ReleaseFromOwner()
|
||||||
{
|
{
|
||||||
if (this.m_owner == null)
|
if (this.owner == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.m_owner = null;
|
this.owner = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void SetValue(object value);
|
public abstract void SetValue(object value);
|
||||||
|
@ -9,6 +9,8 @@ using UnityExplorer.CacheObject;
|
|||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
|
using UniverseLib.UI.Models;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.CacheObject.IValues
|
namespace UnityExplorer.CacheObject.IValues
|
||||||
{
|
{
|
||||||
@ -55,7 +57,7 @@ namespace UnityExplorer.CacheObject.IValues
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly Dictionary<string, StructInfo> typeSupportCache = new Dictionary<string, StructInfo>();
|
private static readonly Dictionary<string, StructInfo> typeSupportCache = new();
|
||||||
|
|
||||||
private const BindingFlags INSTANCE_FLAGS = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public;
|
private const BindingFlags INSTANCE_FLAGS = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public;
|
||||||
private const string SYSTEM_VOID = "System.Void";
|
private const string SYSTEM_VOID = "System.Void";
|
||||||
|
@ -7,6 +7,7 @@ using UnityEngine.UI;
|
|||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.CacheObject.Views
|
namespace UnityExplorer.CacheObject.Views
|
||||||
{
|
{
|
||||||
|
@ -9,6 +9,7 @@ using UnityExplorer.Inspectors;
|
|||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
using UnityExplorer.UI.Widgets;
|
using UnityExplorer.UI.Widgets;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
|
using UniverseLib.UI.Models;
|
||||||
|
|
||||||
namespace UnityExplorer.CacheObject.Views
|
namespace UnityExplorer.CacheObject.Views
|
||||||
{
|
{
|
||||||
|
@ -7,20 +7,17 @@ using UnityEngine.UI;
|
|||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
using UnityExplorer.UI.Widgets;
|
using UnityExplorer.UI.Widgets;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
|
using UniverseLib.UI.Models;
|
||||||
|
|
||||||
namespace UnityExplorer.CacheObject.Views
|
namespace UnityExplorer.CacheObject.Views
|
||||||
{
|
{
|
||||||
public class CacheMemberCell : CacheObjectCell
|
public class CacheMemberCell : CacheObjectCell
|
||||||
{
|
{
|
||||||
//public ReflectionInspector Owner { get; set; }
|
|
||||||
|
|
||||||
public CacheMember MemberOccupant => Occupant as CacheMember;
|
public CacheMember MemberOccupant => Occupant as CacheMember;
|
||||||
|
|
||||||
public GameObject EvaluateHolder;
|
public GameObject EvaluateHolder;
|
||||||
public ButtonRef EvaluateButton;
|
public ButtonRef EvaluateButton;
|
||||||
|
|
||||||
//public Toggle UpdateToggle;
|
|
||||||
|
|
||||||
protected virtual void EvaluateClicked()
|
protected virtual void EvaluateClicked()
|
||||||
{
|
{
|
||||||
this.MemberOccupant.OnEvaluateClicked();
|
this.MemberOccupant.OnEvaluateClicked();
|
||||||
@ -38,16 +35,5 @@ namespace UnityExplorer.CacheObject.Views
|
|||||||
UIFactory.SetLayoutElement(EvaluateButton.Component.gameObject, minWidth: 100, minHeight: 25);
|
UIFactory.SetLayoutElement(EvaluateButton.Component.gameObject, minWidth: 100, minHeight: 25);
|
||||||
EvaluateButton.OnClick += EvaluateClicked;
|
EvaluateButton.OnClick += EvaluateClicked;
|
||||||
}
|
}
|
||||||
|
|
||||||
//protected override void ConstructUpdateToggle(GameObject parent)
|
|
||||||
//{
|
|
||||||
// // Auto-update toggle
|
|
||||||
//
|
|
||||||
// var updateToggle = UIFactory.CreateToggle(parent, "AutoUpdate", out UpdateToggle, out Text autoText);
|
|
||||||
// UIFactory.SetLayoutElement(updateToggle, minHeight: 25, minWidth: 30, flexibleWidth: 0, flexibleHeight: 0);
|
|
||||||
// GameObject.Destroy(autoText);
|
|
||||||
// UpdateToggle.isOn = false;
|
|
||||||
// UpdateToggle.onValueChanged.AddListener((bool val) => { MemberOccupant.AutoUpdateWanted = val; });
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,13 +4,12 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.CacheObject.IValues;
|
using UnityExplorer.UI.Panels;
|
||||||
using UnityExplorer.Inspectors;
|
|
||||||
using UnityExplorer.UI;
|
|
||||||
using UnityExplorer.UI.Widgets;
|
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
using UniverseLib.UI.Widgets;
|
using UniverseLib.UI.Models;
|
||||||
|
using UniverseLib.UI.Widgets.ScrollView;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.CacheObject.Views
|
namespace UnityExplorer.CacheObject.Views
|
||||||
{
|
{
|
||||||
@ -45,10 +44,12 @@ namespace UnityExplorer.CacheObject.Views
|
|||||||
public bool SubContentActive => SubContentHolder.activeSelf;
|
public bool SubContentActive => SubContentHolder.activeSelf;
|
||||||
|
|
||||||
public LayoutElement NameLayout;
|
public LayoutElement NameLayout;
|
||||||
|
public GameObject RightGroupContent;
|
||||||
public LayoutElement RightGroupLayout;
|
public LayoutElement RightGroupLayout;
|
||||||
|
public GameObject SubContentHolder;
|
||||||
|
|
||||||
public Text NameLabel;
|
public Text NameLabel;
|
||||||
public InputFieldRef HiddenNameLabel;
|
public InputFieldRef HiddenNameLabel; // for selecting the name label
|
||||||
public Text TypeLabel;
|
public Text TypeLabel;
|
||||||
public Text ValueLabel;
|
public Text ValueLabel;
|
||||||
public Toggle Toggle;
|
public Toggle Toggle;
|
||||||
@ -59,7 +60,11 @@ namespace UnityExplorer.CacheObject.Views
|
|||||||
public ButtonRef SubContentButton;
|
public ButtonRef SubContentButton;
|
||||||
public ButtonRef ApplyButton;
|
public ButtonRef ApplyButton;
|
||||||
|
|
||||||
public GameObject SubContentHolder;
|
public ButtonRef CopyButton;
|
||||||
|
public ButtonRef PasteButton;
|
||||||
|
|
||||||
|
public readonly Color subInactiveColor = new(0.23f, 0.23f, 0.23f);
|
||||||
|
public readonly Color subActiveColor = new(0.23f, 0.33f, 0.23f);
|
||||||
|
|
||||||
protected virtual void ApplyClicked()
|
protected virtual void ApplyClicked()
|
||||||
{
|
{
|
||||||
@ -81,26 +86,26 @@ namespace UnityExplorer.CacheObject.Views
|
|||||||
this.Occupant.OnCellSubContentToggle();
|
this.Occupant.OnCellSubContentToggle();
|
||||||
}
|
}
|
||||||
|
|
||||||
public readonly Color subInactiveColor = new Color(0.23f, 0.23f, 0.23f);
|
protected virtual void OnCopyClicked()
|
||||||
public readonly Color subActiveColor = new Color(0.23f, 0.33f, 0.23f);
|
{
|
||||||
|
ClipboardPanel.Copy(this.Occupant.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void OnPasteClicked()
|
||||||
|
{
|
||||||
|
if (ClipboardPanel.TryPaste(this.Occupant.FallbackType, out object paste))
|
||||||
|
this.Occupant.SetUserValue(paste);
|
||||||
|
}
|
||||||
|
|
||||||
public void RefreshSubcontentButton()
|
public void RefreshSubcontentButton()
|
||||||
{
|
{
|
||||||
if (!this.SubContentHolder.activeSelf)
|
this.SubContentButton.ButtonText.text = SubContentHolder.activeSelf ? "▼" : "▲";
|
||||||
{
|
Color color = SubContentHolder.activeSelf ? subActiveColor : subInactiveColor;
|
||||||
this.SubContentButton.ButtonText.text = "▲";
|
RuntimeHelper.SetColorBlock(SubContentButton.Component, color, color * 1.3f);
|
||||||
RuntimeProvider.Instance.SetColorBlock(SubContentButton.Component, subInactiveColor, subInactiveColor * 1.3f);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this.SubContentButton.ButtonText.text = "▼";
|
|
||||||
RuntimeProvider.Instance.SetColorBlock(SubContentButton.Component, subActiveColor, subActiveColor * 1.3f);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract void ConstructEvaluateHolder(GameObject parent);
|
protected abstract void ConstructEvaluateHolder(GameObject parent);
|
||||||
|
|
||||||
|
|
||||||
public virtual GameObject CreateContent(GameObject parent)
|
public virtual GameObject CreateContent(GameObject parent)
|
||||||
{
|
{
|
||||||
// Main layout
|
// Main layout
|
||||||
@ -136,16 +141,16 @@ namespace UnityExplorer.CacheObject.Views
|
|||||||
|
|
||||||
// Right vertical group
|
// Right vertical group
|
||||||
|
|
||||||
var rightGroupHolder = UIFactory.CreateUIObject("RightGroup", horiRow);
|
RightGroupContent = UIFactory.CreateUIObject("RightGroup", horiRow);
|
||||||
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(rightGroupHolder, false, false, true, true, 4, childAlignment: TextAnchor.UpperLeft);
|
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(RightGroupContent, false, false, true, true, 4, childAlignment: TextAnchor.UpperLeft);
|
||||||
UIFactory.SetLayoutElement(rightGroupHolder, minHeight: 25, minWidth: 200, flexibleWidth: 9999, flexibleHeight: 800);
|
UIFactory.SetLayoutElement(RightGroupContent, minHeight: 25, minWidth: 200, flexibleWidth: 9999, flexibleHeight: 800);
|
||||||
RightGroupLayout = rightGroupHolder.GetComponent<LayoutElement>();
|
RightGroupLayout = RightGroupContent.GetComponent<LayoutElement>();
|
||||||
|
|
||||||
ConstructEvaluateHolder(rightGroupHolder);
|
ConstructEvaluateHolder(RightGroupContent);
|
||||||
|
|
||||||
// Right horizontal group
|
// Right horizontal group
|
||||||
|
|
||||||
var rightHoriGroup = UIFactory.CreateUIObject("RightHoriGroup", rightGroupHolder);
|
var rightHoriGroup = UIFactory.CreateUIObject("RightHoriGroup", RightGroupContent);
|
||||||
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(rightHoriGroup, false, false, true, true, 4, childAlignment: TextAnchor.UpperLeft);
|
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(rightHoriGroup, false, false, true, true, 4, childAlignment: TextAnchor.UpperLeft);
|
||||||
UIFactory.SetLayoutElement(rightHoriGroup, minHeight: 25, minWidth: 200, flexibleWidth: 9999, flexibleHeight: 800);
|
UIFactory.SetLayoutElement(rightHoriGroup, minHeight: 25, minWidth: 200, flexibleWidth: 9999, flexibleHeight: 800);
|
||||||
|
|
||||||
@ -157,7 +162,7 @@ namespace UnityExplorer.CacheObject.Views
|
|||||||
|
|
||||||
TypeLabel = UIFactory.CreateLabel(rightHoriGroup, "ReturnLabel", "<notset>", TextAnchor.MiddleLeft);
|
TypeLabel = UIFactory.CreateLabel(rightHoriGroup, "ReturnLabel", "<notset>", TextAnchor.MiddleLeft);
|
||||||
TypeLabel.horizontalOverflow = HorizontalWrapMode.Wrap;
|
TypeLabel.horizontalOverflow = HorizontalWrapMode.Wrap;
|
||||||
UIFactory.SetLayoutElement(TypeLabel.gameObject, minHeight: 25, flexibleHeight: 150, minWidth: 60, flexibleWidth: 0);
|
UIFactory.SetLayoutElement(TypeLabel.gameObject, minHeight: 25, flexibleHeight: 150, minWidth: 45, flexibleWidth: 0);
|
||||||
|
|
||||||
// Bool and number value interaction
|
// Bool and number value interaction
|
||||||
|
|
||||||
@ -187,6 +192,24 @@ namespace UnityExplorer.CacheObject.Views
|
|||||||
ValueLabel.horizontalOverflow = HorizontalWrapMode.Wrap;
|
ValueLabel.horizontalOverflow = HorizontalWrapMode.Wrap;
|
||||||
UIFactory.SetLayoutElement(ValueLabel.gameObject, minHeight: 25, flexibleHeight: 150, flexibleWidth: 9999);
|
UIFactory.SetLayoutElement(ValueLabel.gameObject, minHeight: 25, flexibleHeight: 150, flexibleWidth: 9999);
|
||||||
|
|
||||||
|
// Copy and Paste buttons
|
||||||
|
|
||||||
|
var buttonHolder = UIFactory.CreateHorizontalGroup(rightHoriGroup, "CopyPasteButtons", false, false, true, true, 4,
|
||||||
|
bgColor: new(1,1,1,0), childAlignment: TextAnchor.MiddleLeft);
|
||||||
|
UIFactory.SetLayoutElement(buttonHolder, minWidth: 60, flexibleWidth: 0);
|
||||||
|
|
||||||
|
CopyButton = UIFactory.CreateButton(buttonHolder, "CopyButton", "Copy", new Color(0.13f, 0.13f, 0.13f, 1f));
|
||||||
|
UIFactory.SetLayoutElement(CopyButton.Component.gameObject, minHeight: 25, minWidth: 28, flexibleWidth: 0);
|
||||||
|
CopyButton.ButtonText.color = Color.yellow;
|
||||||
|
CopyButton.ButtonText.fontSize = 10;
|
||||||
|
CopyButton.OnClick += OnCopyClicked;
|
||||||
|
|
||||||
|
PasteButton = UIFactory.CreateButton(buttonHolder, "PasteButton", "Paste", new Color(0.13f, 0.13f, 0.13f, 1f));
|
||||||
|
UIFactory.SetLayoutElement(PasteButton.Component.gameObject, minHeight: 25, minWidth: 28, flexibleWidth: 0);
|
||||||
|
PasteButton.ButtonText.color = Color.green;
|
||||||
|
PasteButton.ButtonText.fontSize = 10;
|
||||||
|
PasteButton.OnClick += OnPasteClicked;
|
||||||
|
|
||||||
// Subcontent
|
// Subcontent
|
||||||
|
|
||||||
SubContentHolder = UIFactory.CreateUIObject("SubContent", UIRoot);
|
SubContentHolder = UIFactory.CreateUIObject("SubContent", UIRoot);
|
||||||
|
@ -1,289 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Text;
|
|
||||||
using UnityEngine;
|
|
||||||
using UnityEngine.UI;
|
|
||||||
using UnityExplorer.UI;
|
|
||||||
using UniverseLib.UI.Models;
|
|
||||||
using UnityExplorer.UI.Widgets.AutoComplete;
|
|
||||||
using UniverseLib.UI;
|
|
||||||
using UniverseLib;
|
|
||||||
|
|
||||||
namespace UnityExplorer.CacheObject.Views
|
|
||||||
{
|
|
||||||
public class EvaluateWidget : IPooledObject
|
|
||||||
{
|
|
||||||
public CacheMember Owner { get; set; }
|
|
||||||
|
|
||||||
public GameObject UIRoot { get; set; }
|
|
||||||
public float DefaultHeight => -1f;
|
|
||||||
|
|
||||||
private ParameterInfo[] arguments;
|
|
||||||
private string[] argumentInput;
|
|
||||||
|
|
||||||
private GameObject argHolder;
|
|
||||||
private readonly List<GameObject> argRows = new List<GameObject>();
|
|
||||||
private readonly List<Text> argLabels = new List<Text>();
|
|
||||||
|
|
||||||
private Type[] genericArguments;
|
|
||||||
private string[] genericInput;
|
|
||||||
|
|
||||||
private GameObject genericArgHolder;
|
|
||||||
private readonly List<GameObject> genericArgRows = new List<GameObject>();
|
|
||||||
private readonly List<Text> genericArgLabels = new List<Text>();
|
|
||||||
private readonly List<TypeCompleter> genericAutocompleters = new List<TypeCompleter>();
|
|
||||||
|
|
||||||
//private readonly List<InputFieldRef> inputFields = new List<InputFieldRef>();
|
|
||||||
private readonly List<InputFieldRef> argInputFields = new List<InputFieldRef>();
|
|
||||||
private readonly List<InputFieldRef> genericInputFields = new List<InputFieldRef>();
|
|
||||||
|
|
||||||
public void OnBorrowedFromPool(CacheMember owner)
|
|
||||||
{
|
|
||||||
this.Owner = owner;
|
|
||||||
|
|
||||||
arguments = owner.Arguments;
|
|
||||||
argumentInput = new string[arguments.Length];
|
|
||||||
|
|
||||||
genericArguments = owner.GenericArguments;
|
|
||||||
genericInput = new string[genericArguments.Length];
|
|
||||||
|
|
||||||
SetArgRows();
|
|
||||||
|
|
||||||
this.UIRoot.SetActive(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnReturnToPool()
|
|
||||||
{
|
|
||||||
foreach (var input in argInputFields)
|
|
||||||
input.Text = "";
|
|
||||||
foreach (var input in genericInputFields)
|
|
||||||
input.Text = "";
|
|
||||||
|
|
||||||
this.Owner = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Type[] TryParseGenericArguments()
|
|
||||||
{
|
|
||||||
Type[] outArgs = new Type[genericArguments.Length];
|
|
||||||
|
|
||||||
for (int i = 0; i < genericArguments.Length; i++)
|
|
||||||
{
|
|
||||||
outArgs[i] = ReflectionUtility.GetTypeByName(genericInput[i])
|
|
||||||
?? throw new Exception($"Could not find any type by name '{genericInput[i]}'!");
|
|
||||||
}
|
|
||||||
|
|
||||||
return outArgs;
|
|
||||||
}
|
|
||||||
|
|
||||||
public object[] TryParseArguments()
|
|
||||||
{
|
|
||||||
object[] outArgs = new object[arguments.Length];
|
|
||||||
|
|
||||||
for (int i = 0; i < arguments.Length; i++)
|
|
||||||
{
|
|
||||||
var arg = arguments[i];
|
|
||||||
var input = argumentInput[i];
|
|
||||||
|
|
||||||
var type = arg.ParameterType;
|
|
||||||
if (type.IsByRef)
|
|
||||||
type = type.GetElementType();
|
|
||||||
|
|
||||||
if (type == typeof(string))
|
|
||||||
{
|
|
||||||
outArgs[i] = input;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(input))
|
|
||||||
{
|
|
||||||
if (arg.IsOptional)
|
|
||||||
outArgs[i] = arg.DefaultValue;
|
|
||||||
else
|
|
||||||
outArgs[i] = null;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ParseUtility.TryParse(input, type, out outArgs[i], out Exception ex))
|
|
||||||
{
|
|
||||||
outArgs[i] = null;
|
|
||||||
ExplorerCore.LogWarning($"Cannot parse argument '{arg.Name}' ({arg.ParameterType.Name})" +
|
|
||||||
$"{(ex == null ? "" : $", {ex.GetType().Name}: {ex.Message}")}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return outArgs;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SetArgRows()
|
|
||||||
{
|
|
||||||
if (genericArguments.Any())
|
|
||||||
{
|
|
||||||
genericArgHolder.SetActive(true);
|
|
||||||
SetGenericRows();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
genericArgHolder.SetActive(false);
|
|
||||||
|
|
||||||
if (arguments.Any())
|
|
||||||
{
|
|
||||||
argHolder.SetActive(true);
|
|
||||||
SetNormalArgRows();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
argHolder.SetActive(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SetGenericRows()
|
|
||||||
{
|
|
||||||
for (int i = 0; i < genericArguments.Length || i < genericArgRows.Count; i++)
|
|
||||||
{
|
|
||||||
if (i >= genericArguments.Length)
|
|
||||||
{
|
|
||||||
if (i >= genericArgRows.Count)
|
|
||||||
break;
|
|
||||||
else
|
|
||||||
// exceeded actual args, but still iterating so there must be views left, disable them
|
|
||||||
genericArgRows[i].SetActive(false);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var arg = genericArguments[i];
|
|
||||||
|
|
||||||
if (i >= genericArgRows.Count)
|
|
||||||
AddArgRow(i, true);
|
|
||||||
|
|
||||||
genericArgRows[i].SetActive(true);
|
|
||||||
|
|
||||||
var autoCompleter = genericAutocompleters[i];
|
|
||||||
autoCompleter.BaseType = arg;
|
|
||||||
autoCompleter.CacheTypes();
|
|
||||||
|
|
||||||
var constraints = arg.GetGenericParameterConstraints();
|
|
||||||
autoCompleter.GenericConstraints = constraints;
|
|
||||||
|
|
||||||
var sb = new StringBuilder($"<color={SignatureHighlighter.CONST}>{arg.Name}</color>");
|
|
||||||
|
|
||||||
for (int j = 0; j < constraints.Length; j++)
|
|
||||||
{
|
|
||||||
if (j == 0) sb.Append(' ').Append('(');
|
|
||||||
else sb.Append(',').Append(' ');
|
|
||||||
|
|
||||||
sb.Append(SignatureHighlighter.Parse(constraints[j], false));
|
|
||||||
|
|
||||||
if (j + 1 == constraints.Length)
|
|
||||||
sb.Append(')');
|
|
||||||
}
|
|
||||||
|
|
||||||
genericArgLabels[i].text = sb.ToString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SetNormalArgRows()
|
|
||||||
{
|
|
||||||
for (int i = 0; i < arguments.Length || i < argRows.Count; i++)
|
|
||||||
{
|
|
||||||
if (i >= arguments.Length)
|
|
||||||
{
|
|
||||||
if (i >= argRows.Count)
|
|
||||||
break;
|
|
||||||
else
|
|
||||||
// exceeded actual args, but still iterating so there must be views left, disable them
|
|
||||||
argRows[i].SetActive(false);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var arg = arguments[i];
|
|
||||||
|
|
||||||
|
|
||||||
if (i >= argRows.Count)
|
|
||||||
AddArgRow(i, false);
|
|
||||||
|
|
||||||
argRows[i].SetActive(true);
|
|
||||||
argLabels[i].text = $"{SignatureHighlighter.Parse(arg.ParameterType, false)} <color={SignatureHighlighter.LOCAL_ARG}>{arg.Name}</color>";
|
|
||||||
if (arg.ParameterType == typeof(string))
|
|
||||||
argInputFields[i].PlaceholderText.text = "";
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var elemType = arg.ParameterType;
|
|
||||||
if (elemType.IsByRef)
|
|
||||||
elemType = elemType.GetElementType();
|
|
||||||
argInputFields[i].PlaceholderText.text = $"eg. {ParseUtility.GetExampleInput(elemType)}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void AddArgRow(int index, bool generic)
|
|
||||||
{
|
|
||||||
if (!generic)
|
|
||||||
AddArgRow(index, argHolder, argRows, argLabels, argumentInput, false);
|
|
||||||
else
|
|
||||||
AddArgRow(index, genericArgHolder, genericArgRows, genericArgLabels, genericInput, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void AddArgRow(int index, GameObject parent, List<GameObject> objectList, List<Text> labelList, string[] inputArray, bool generic)
|
|
||||||
{
|
|
||||||
var horiGroup = UIFactory.CreateUIObject("ArgRow_" + index, parent);
|
|
||||||
UIFactory.SetLayoutElement(horiGroup, minHeight: 25, flexibleHeight: 50, minWidth: 50, flexibleWidth: 9999);
|
|
||||||
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(horiGroup, false, false, true, true, 5);
|
|
||||||
horiGroup.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
|
||||||
objectList.Add(horiGroup);
|
|
||||||
|
|
||||||
var label = UIFactory.CreateLabel(horiGroup, "ArgLabel", "not set", TextAnchor.MiddleLeft);
|
|
||||||
UIFactory.SetLayoutElement(label.gameObject, minWidth: 40, flexibleWidth: 90, minHeight: 25, flexibleHeight: 50);
|
|
||||||
labelList.Add(label);
|
|
||||||
label.horizontalOverflow = HorizontalWrapMode.Wrap;
|
|
||||||
|
|
||||||
var inputField = UIFactory.CreateInputField(horiGroup, "InputField", "...");
|
|
||||||
UIFactory.SetLayoutElement(inputField.UIRoot, minHeight: 25, flexibleHeight: 50, minWidth: 100, flexibleWidth: 1000);
|
|
||||||
inputField.Component.lineType = InputField.LineType.MultiLineNewline;
|
|
||||||
inputField.UIRoot.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
|
||||||
inputField.OnValueChanged += (string val) => { inputArray[index] = val; };
|
|
||||||
|
|
||||||
if (!generic)
|
|
||||||
argInputFields.Add(inputField);
|
|
||||||
else
|
|
||||||
genericInputFields.Add(inputField);
|
|
||||||
|
|
||||||
if (generic)
|
|
||||||
genericAutocompleters.Add(new TypeCompleter(null, inputField));
|
|
||||||
}
|
|
||||||
|
|
||||||
public GameObject CreateContent(GameObject parent)
|
|
||||||
{
|
|
||||||
UIRoot = UIFactory.CreateVerticalGroup(parent, "EvaluateWidget", false, false, true, true, 3, new Vector4(2, 2, 2, 2),
|
|
||||||
new Color(0.15f, 0.15f, 0.15f));
|
|
||||||
UIFactory.SetLayoutElement(UIRoot, minWidth: 50, flexibleWidth: 9999, minHeight: 50, flexibleHeight: 800);
|
|
||||||
//UIRoot.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
|
||||||
|
|
||||||
// generic args
|
|
||||||
this.genericArgHolder = UIFactory.CreateUIObject("GenericHolder", UIRoot);
|
|
||||||
UIFactory.SetLayoutElement(genericArgHolder, flexibleWidth: 1000);
|
|
||||||
var genericsTitle = UIFactory.CreateLabel(genericArgHolder, "GenericsTitle", "Generic Arguments", TextAnchor.MiddleLeft);
|
|
||||||
UIFactory.SetLayoutElement(genericsTitle.gameObject, minHeight: 25, flexibleWidth: 1000);
|
|
||||||
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(genericArgHolder, false, false, true, true, 3);
|
|
||||||
UIFactory.SetLayoutElement(genericArgHolder, minHeight: 25, flexibleHeight: 750, minWidth: 50, flexibleWidth: 9999);
|
|
||||||
//genericArgHolder.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
|
||||||
|
|
||||||
// args
|
|
||||||
this.argHolder = UIFactory.CreateUIObject("ArgHolder", UIRoot);
|
|
||||||
UIFactory.SetLayoutElement(argHolder, flexibleWidth: 1000);
|
|
||||||
var argsTitle = UIFactory.CreateLabel(argHolder, "ArgsTitle", "Arguments", TextAnchor.MiddleLeft);
|
|
||||||
UIFactory.SetLayoutElement(argsTitle.gameObject, minHeight: 25, flexibleWidth: 1000);
|
|
||||||
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(argHolder, false, false, true, true, 3);
|
|
||||||
UIFactory.SetLayoutElement(argHolder, minHeight: 25, flexibleHeight: 750, minWidth: 50, flexibleWidth: 9999);
|
|
||||||
//argHolder.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
|
||||||
|
|
||||||
// evaluate button
|
|
||||||
var evalButton = UIFactory.CreateButton(UIRoot, "EvaluateButton", "Evaluate", new Color(0.2f, 0.2f, 0.2f));
|
|
||||||
UIFactory.SetLayoutElement(evalButton.Component.gameObject, minHeight: 25, minWidth: 150, flexibleWidth: 0);
|
|
||||||
evalButton.OnClick += () =>
|
|
||||||
{
|
|
||||||
Owner.EvaluateAndSetCell();
|
|
||||||
};
|
|
||||||
|
|
||||||
return UIRoot;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -3,7 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace UnityExplorer.Core.Config
|
namespace UnityExplorer.Config
|
||||||
{
|
{
|
||||||
public class ConfigElement<T> : IConfigElement
|
public class ConfigElement<T> : IConfigElement
|
||||||
{
|
{
|
@ -3,7 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace UnityExplorer.Core.Config
|
namespace UnityExplorer.Config
|
||||||
{
|
{
|
||||||
public abstract class ConfigHandler
|
public abstract class ConfigHandler
|
||||||
{
|
{
|
@ -8,15 +8,20 @@ using System.Text;
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
|
|
||||||
namespace UnityExplorer.Core.Config
|
namespace UnityExplorer.Config
|
||||||
{
|
{
|
||||||
public static class ConfigManager
|
public static class ConfigManager
|
||||||
{
|
{
|
||||||
|
internal static readonly Dictionary<string, IConfigElement> ConfigElements = new();
|
||||||
|
internal static readonly Dictionary<string, IConfigElement> InternalConfigs = new();
|
||||||
|
|
||||||
// Each Mod Loader has its own ConfigHandler.
|
// Each Mod Loader has its own ConfigHandler.
|
||||||
// See the UnityExplorer.Loader namespace for the implementations.
|
// See the UnityExplorer.Loader namespace for the implementations.
|
||||||
public static ConfigHandler Handler { get; private set; }
|
public static ConfigHandler Handler { get; private set; }
|
||||||
|
|
||||||
|
// Actual UE Settings
|
||||||
public static ConfigElement<KeyCode> Master_Toggle;
|
public static ConfigElement<KeyCode> Master_Toggle;
|
||||||
|
public static ConfigElement<int> Target_Display;
|
||||||
public static ConfigElement<UIManager.VerticalAnchor> Main_Navbar_Anchor;
|
public static ConfigElement<UIManager.VerticalAnchor> Main_Navbar_Anchor;
|
||||||
public static ConfigElement<bool> Force_Unlock_Mouse;
|
public static ConfigElement<bool> Force_Unlock_Mouse;
|
||||||
public static ConfigElement<KeyCode> Force_Unlock_Toggle;
|
public static ConfigElement<KeyCode> Force_Unlock_Toggle;
|
||||||
@ -26,21 +31,20 @@ namespace UnityExplorer.Core.Config
|
|||||||
public static ConfigElement<bool> Log_Unity_Debug;
|
public static ConfigElement<bool> Log_Unity_Debug;
|
||||||
public static ConfigElement<bool> Hide_On_Startup;
|
public static ConfigElement<bool> Hide_On_Startup;
|
||||||
public static ConfigElement<float> Startup_Delay_Time;
|
public static ConfigElement<float> Startup_Delay_Time;
|
||||||
|
|
||||||
public static ConfigElement<string> Reflection_Signature_Blacklist;
|
public static ConfigElement<string> Reflection_Signature_Blacklist;
|
||||||
|
public static ConfigElement<KeyCode> World_MouseInspect_Keybind;
|
||||||
|
public static ConfigElement<KeyCode> UI_MouseInspect_Keybind;
|
||||||
|
|
||||||
// internal configs
|
// internal configs
|
||||||
internal static InternalConfigHandler InternalHandler { get; private set; }
|
internal static InternalConfigHandler InternalHandler { get; private set; }
|
||||||
|
internal static readonly Dictionary<UIManager.Panels, ConfigElement<string>> PanelSaveData = new();
|
||||||
|
|
||||||
public static ConfigElement<string> ObjectExplorerData;
|
internal static ConfigElement<string> GetPanelSaveData(UIManager.Panels panel)
|
||||||
public static ConfigElement<string> InspectorData;
|
{
|
||||||
public static ConfigElement<string> CSConsoleData;
|
if (!PanelSaveData.ContainsKey(panel))
|
||||||
public static ConfigElement<string> OptionsPanelData;
|
PanelSaveData.Add(panel, new ConfigElement<string>(panel.ToString(), string.Empty, string.Empty, true));
|
||||||
public static ConfigElement<string> ConsoleLogData;
|
return PanelSaveData[panel];
|
||||||
public static ConfigElement<string> HookManagerData;
|
}
|
||||||
|
|
||||||
internal static readonly Dictionary<string, IConfigElement> ConfigElements = new Dictionary<string, IConfigElement>();
|
|
||||||
internal static readonly Dictionary<string, IConfigElement> InternalConfigs = new Dictionary<string, IConfigElement>();
|
|
||||||
|
|
||||||
public static void Init(ConfigHandler configHandler)
|
public static void Init(ConfigHandler configHandler)
|
||||||
{
|
{
|
||||||
@ -78,6 +82,11 @@ namespace UnityExplorer.Core.Config
|
|||||||
"The key to enable or disable UnityExplorer's menu and features.",
|
"The key to enable or disable UnityExplorer's menu and features.",
|
||||||
KeyCode.F7);
|
KeyCode.F7);
|
||||||
|
|
||||||
|
Target_Display = new ConfigElement<int>("Target Display",
|
||||||
|
"The monitor index for UnityExplorer to use, if you have multiple. 0 is the default display, 1 is secondary, etc. " +
|
||||||
|
"Restart recommended when changing this setting. Make sure your extra monitors are the same resolution as your primary monitor.",
|
||||||
|
0);
|
||||||
|
|
||||||
Main_Navbar_Anchor = new ConfigElement<UIManager.VerticalAnchor>("Main Navbar Anchor",
|
Main_Navbar_Anchor = new ConfigElement<UIManager.VerticalAnchor>("Main Navbar Anchor",
|
||||||
"The vertical anchor of the main UnityExplorer Navbar, in case you want to move it.",
|
"The vertical anchor of the main UnityExplorer Navbar, in case you want to move it.",
|
||||||
UIManager.VerticalAnchor.Top);
|
UIManager.VerticalAnchor.Top);
|
||||||
@ -86,13 +95,18 @@ namespace UnityExplorer.Core.Config
|
|||||||
"Should UnityExplorer be hidden on startup?",
|
"Should UnityExplorer be hidden on startup?",
|
||||||
false);
|
false);
|
||||||
|
|
||||||
|
World_MouseInspect_Keybind = new("World Mouse-Inspect Keybind",
|
||||||
|
"Optional keybind to being a World-mode Mouse Inspect.",
|
||||||
|
KeyCode.None);
|
||||||
|
|
||||||
|
UI_MouseInspect_Keybind = new("UI Mouse-Inspect Keybind",
|
||||||
|
"Optional keybind to begin a UI_mode Mouse Inspect.",
|
||||||
|
KeyCode.None);
|
||||||
|
|
||||||
Force_Unlock_Mouse = new ConfigElement<bool>("Force Unlock Mouse",
|
Force_Unlock_Mouse = new ConfigElement<bool>("Force Unlock Mouse",
|
||||||
"Force the Cursor to be unlocked (visible) when the UnityExplorer menu is open.",
|
"Force the Cursor to be unlocked (visible) when the UnityExplorer menu is open.",
|
||||||
true);
|
true);
|
||||||
Force_Unlock_Mouse.OnValueChanged += (bool value) =>
|
Force_Unlock_Mouse.OnValueChanged += (bool value) => UniverseLib.Config.ConfigManager.Force_Unlock_Mouse = value;
|
||||||
{
|
|
||||||
UniverseLib.Config.ConfigManager.Force_Unlock_Mouse = value;
|
|
||||||
};
|
|
||||||
|
|
||||||
Force_Unlock_Toggle = new ConfigElement<KeyCode>("Force Unlock Toggle Key",
|
Force_Unlock_Toggle = new ConfigElement<KeyCode>("Force Unlock Toggle Key",
|
||||||
"The keybind to toggle the 'Force Unlock Mouse' setting. Only usable when UnityExplorer is open.",
|
"The keybind to toggle the 'Force Unlock Mouse' setting. Only usable when UnityExplorer is open.",
|
||||||
@ -101,10 +115,7 @@ namespace UnityExplorer.Core.Config
|
|||||||
Disable_EventSystem_Override = new ConfigElement<bool>("Disable EventSystem override",
|
Disable_EventSystem_Override = new ConfigElement<bool>("Disable EventSystem override",
|
||||||
"If enabled, UnityExplorer will not override the EventSystem from the game.\n<b>May require restart to take effect.</b>",
|
"If enabled, UnityExplorer will not override the EventSystem from the game.\n<b>May require restart to take effect.</b>",
|
||||||
false);
|
false);
|
||||||
Disable_EventSystem_Override.OnValueChanged += (bool value) =>
|
Disable_EventSystem_Override.OnValueChanged += (bool value) => UniverseLib.Config.ConfigManager.Disable_EventSystem_Override = value;
|
||||||
{
|
|
||||||
UniverseLib.Config.ConfigManager.Disable_EventSystem_Override = value;
|
|
||||||
};
|
|
||||||
|
|
||||||
Log_Unity_Debug = new ConfigElement<bool>("Log Unity Debug",
|
Log_Unity_Debug = new ConfigElement<bool>("Log Unity Debug",
|
||||||
"Should UnityEngine.Debug.Log messages be printed to UnityExplorer's log?",
|
"Should UnityEngine.Debug.Log messages be printed to UnityExplorer's log?",
|
||||||
@ -123,15 +134,6 @@ namespace UnityExplorer.Core.Config
|
|||||||
"Seperate signatures with a semicolon ';'.\r\n" +
|
"Seperate signatures with a semicolon ';'.\r\n" +
|
||||||
"For example, to blacklist Camera.main, you would add 'UnityEngine.Camera.main;'",
|
"For example, to blacklist Camera.main, you would add 'UnityEngine.Camera.main;'",
|
||||||
"");
|
"");
|
||||||
|
|
||||||
// Internal configs (panel save data)
|
|
||||||
|
|
||||||
ObjectExplorerData = new ConfigElement<string>("ObjectExplorer", "", "", true);
|
|
||||||
InspectorData = new ConfigElement<string>("Inspector", "", "", true);
|
|
||||||
CSConsoleData = new ConfigElement<string>("CSConsole", "", "", true);
|
|
||||||
OptionsPanelData = new ConfigElement<string>("OptionsPanel", "", "", true);
|
|
||||||
ConsoleLogData = new ConfigElement<string>("ConsoleLog", "", "", true);
|
|
||||||
HookManagerData = new ConfigElement<string>("HookManager", "", "", true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,6 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace UnityExplorer.Core.Config
|
namespace UnityExplorer.Config
|
||||||
{
|
{
|
||||||
public interface IConfigElement
|
public interface IConfigElement
|
||||||
{
|
{
|
79
src/Config/InternalConfigHandler.cs
Normal file
79
src/Config/InternalConfigHandler.cs
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityExplorer.UI;
|
||||||
|
using Tomlet;
|
||||||
|
using Tomlet.Models;
|
||||||
|
|
||||||
|
namespace UnityExplorer.Config
|
||||||
|
{
|
||||||
|
public class InternalConfigHandler : ConfigHandler
|
||||||
|
{
|
||||||
|
internal static string CONFIG_PATH;
|
||||||
|
|
||||||
|
public override void Init()
|
||||||
|
{
|
||||||
|
CONFIG_PATH = Path.Combine(ExplorerCore.Loader.ExplorerFolder, "data.cfg");
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void LoadConfig()
|
||||||
|
{
|
||||||
|
if (!TryLoadConfig())
|
||||||
|
SaveConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void RegisterConfigElement<T>(ConfigElement<T> element)
|
||||||
|
{
|
||||||
|
// Not necessary
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void SetConfigValue<T>(ConfigElement<T> element, T value)
|
||||||
|
{
|
||||||
|
// Not necessary
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not necessary, just return the value.
|
||||||
|
public override T GetConfigValue<T>(ConfigElement<T> element) => element.Value;
|
||||||
|
|
||||||
|
// Always just auto-save.
|
||||||
|
public override void OnAnyConfigChanged() => SaveConfig();
|
||||||
|
|
||||||
|
public bool TryLoadConfig()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!File.Exists(CONFIG_PATH))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
TomlDocument document = TomlParser.ParseFile(CONFIG_PATH);
|
||||||
|
foreach (var key in document.Keys)
|
||||||
|
{
|
||||||
|
var panelKey = (UIManager.Panels)Enum.Parse(typeof(UIManager.Panels), key);
|
||||||
|
ConfigManager.GetPanelSaveData(panelKey).Value = document.GetString(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
ExplorerCore.LogWarning("Error loading internal data: " + ex.ToString());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void SaveConfig()
|
||||||
|
{
|
||||||
|
if (UIManager.Initializing)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var tomlDocument = TomlDocument.CreateEmpty();
|
||||||
|
foreach (var entry in ConfigManager.InternalConfigs)
|
||||||
|
tomlDocument.Put(entry.Key, entry.Value.BoxedValue as string, false);
|
||||||
|
|
||||||
|
File.WriteAllText(CONFIG_PATH, tomlDocument.SerializedValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,105 +0,0 @@
|
|||||||
using IniParser.Parser;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using UnityEngine;
|
|
||||||
using UnityExplorer.UI;
|
|
||||||
|
|
||||||
namespace UnityExplorer.Core.Config
|
|
||||||
{
|
|
||||||
public class InternalConfigHandler : ConfigHandler
|
|
||||||
{
|
|
||||||
internal static IniDataParser _parser;
|
|
||||||
internal static string INI_PATH;
|
|
||||||
|
|
||||||
public override void Init()
|
|
||||||
{
|
|
||||||
INI_PATH = Path.Combine(ExplorerCore.Loader.ExplorerFolder, "data.ini");
|
|
||||||
_parser = new IniDataParser();
|
|
||||||
_parser.Configuration.CommentString = "#";
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void LoadConfig()
|
|
||||||
{
|
|
||||||
if (!TryLoadConfig())
|
|
||||||
SaveConfig();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void RegisterConfigElement<T>(ConfigElement<T> element)
|
|
||||||
{
|
|
||||||
// Not necessary
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void SetConfigValue<T>(ConfigElement<T> element, T value)
|
|
||||||
{
|
|
||||||
// Not necessary
|
|
||||||
}
|
|
||||||
|
|
||||||
public override T GetConfigValue<T>(ConfigElement<T> element)
|
|
||||||
{
|
|
||||||
// Not necessary, just return the value.
|
|
||||||
return element.Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void OnAnyConfigChanged()
|
|
||||||
{
|
|
||||||
SaveConfig();
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool TryLoadConfig()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (!File.Exists(INI_PATH))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
string ini = File.ReadAllText(INI_PATH);
|
|
||||||
|
|
||||||
var data = _parser.Parse(ini);
|
|
||||||
|
|
||||||
foreach (var config in data.Sections["Config"])
|
|
||||||
{
|
|
||||||
if (ConfigManager.InternalConfigs.TryGetValue(config.KeyName, out IConfigElement configElement))
|
|
||||||
configElement.BoxedValue = StringToConfigValue(config.Value, configElement.ElementType);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
ExplorerCore.LogWarning("Error loading internal data: " + ex.ToString());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void SaveConfig()
|
|
||||||
{
|
|
||||||
if (UIManager.Initializing)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var data = new IniParser.Model.IniData();
|
|
||||||
|
|
||||||
data.Sections.AddSection("Config");
|
|
||||||
var sec = data.Sections["Config"];
|
|
||||||
|
|
||||||
foreach (var entry in ConfigManager.InternalConfigs)
|
|
||||||
sec.AddKey(entry.Key, entry.Value.BoxedValue.ToString());
|
|
||||||
|
|
||||||
File.WriteAllText(INI_PATH, data.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
public object StringToConfigValue(string value, Type elementType)
|
|
||||||
{
|
|
||||||
if (elementType.IsEnum)
|
|
||||||
return Enum.Parse(elementType, value);
|
|
||||||
else if (elementType == typeof(bool))
|
|
||||||
return bool.Parse(value);
|
|
||||||
else if (elementType == typeof(int))
|
|
||||||
return int.Parse(value);
|
|
||||||
else
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -9,29 +9,26 @@ using UnhollowerRuntimeLib;
|
|||||||
|
|
||||||
namespace UnityExplorer
|
namespace UnityExplorer
|
||||||
{
|
{
|
||||||
// Handles all Behaviour update calls for UnityExplorer (Update, FixedUpdate, OnPostRender).
|
|
||||||
// Basically just a wrapper which calls the corresponding methods in ExplorerCore.
|
|
||||||
|
|
||||||
public class ExplorerBehaviour : MonoBehaviour
|
public class ExplorerBehaviour : MonoBehaviour
|
||||||
{
|
{
|
||||||
internal static ExplorerBehaviour Instance { get; private set; }
|
internal static ExplorerBehaviour Instance { get; private set; }
|
||||||
|
|
||||||
|
#if CPP
|
||||||
|
public ExplorerBehaviour(IntPtr ptr) : base(ptr) { }
|
||||||
|
#endif
|
||||||
|
|
||||||
internal static void Setup()
|
internal static void Setup()
|
||||||
{
|
{
|
||||||
#if CPP
|
#if CPP
|
||||||
ClassInjector.RegisterTypeInIl2Cpp<ExplorerBehaviour>();
|
ClassInjector.RegisterTypeInIl2Cpp<ExplorerBehaviour>();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
var obj = new GameObject("ExplorerBehaviour");
|
GameObject obj = new("ExplorerBehaviour");
|
||||||
GameObject.DontDestroyOnLoad(obj);
|
DontDestroyOnLoad(obj);
|
||||||
obj.hideFlags |= HideFlags.HideAndDontSave;
|
obj.hideFlags = HideFlags.HideAndDontSave;
|
||||||
Instance = obj.AddComponent<ExplorerBehaviour>();
|
Instance = obj.AddComponent<ExplorerBehaviour>();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if CPP
|
|
||||||
public ExplorerBehaviour(IntPtr ptr) : base(ptr) { }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
internal void Update()
|
internal void Update()
|
||||||
{
|
{
|
||||||
ExplorerCore.Update();
|
ExplorerCore.Update();
|
@ -1,14 +1,13 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityExplorer.CacheObject;
|
||||||
using UnityExplorer.Core.Config;
|
using UnityExplorer.Config;
|
||||||
using UnityExplorer.UI;
|
|
||||||
using UnityExplorer.ObjectExplorer;
|
using UnityExplorer.ObjectExplorer;
|
||||||
|
using UnityExplorer.Runtime;
|
||||||
|
using UnityExplorer.UI;
|
||||||
using UnityExplorer.UI.Panels;
|
using UnityExplorer.UI.Panels;
|
||||||
using UnityExplorer.Core.Runtime;
|
using UniverseLib;
|
||||||
using UniverseLib.Input;
|
using UniverseLib.Input;
|
||||||
|
|
||||||
namespace UnityExplorer
|
namespace UnityExplorer
|
||||||
@ -16,7 +15,7 @@ namespace UnityExplorer
|
|||||||
public static class ExplorerCore
|
public static class ExplorerCore
|
||||||
{
|
{
|
||||||
public const string NAME = "UnityExplorer";
|
public const string NAME = "UnityExplorer";
|
||||||
public const string VERSION = "4.4.0";
|
public const string VERSION = "4.6.3";
|
||||||
public const string AUTHOR = "Sinai";
|
public const string AUTHOR = "Sinai";
|
||||||
public const string GUID = "com.sinai.unityexplorer";
|
public const string GUID = "com.sinai.unityexplorer";
|
||||||
|
|
||||||
@ -30,35 +29,31 @@ namespace UnityExplorer
|
|||||||
public static void Init(IExplorerLoader loader)
|
public static void Init(IExplorerLoader loader)
|
||||||
{
|
{
|
||||||
if (Loader != null)
|
if (Loader != null)
|
||||||
{
|
throw new Exception("UnityExplorer is already loaded.");
|
||||||
LogWarning("UnityExplorer is already loaded!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Loader = loader;
|
Loader = loader;
|
||||||
|
|
||||||
Log($"{NAME} {VERSION} initializing...");
|
Log($"{NAME} {VERSION} initializing...");
|
||||||
|
|
||||||
if (!Directory.Exists(Loader.ExplorerFolder))
|
Directory.CreateDirectory(Loader.ExplorerFolder);
|
||||||
Directory.CreateDirectory(Loader.ExplorerFolder);
|
|
||||||
|
|
||||||
ConfigManager.Init(Loader.ConfigHandler);
|
ConfigManager.Init(Loader.ConfigHandler);
|
||||||
RuntimeHelper.Init();
|
|
||||||
ExplorerBehaviour.Setup();
|
|
||||||
|
|
||||||
UniverseLib.Universe.Init(ConfigManager.Startup_Delay_Time.Value, LateInit, Log, new UniverseLib.Config.UUConfig
|
UERuntimeHelper.Init();
|
||||||
|
ExplorerBehaviour.Setup();
|
||||||
|
UnityCrashPrevention.Init();
|
||||||
|
|
||||||
|
Universe.Init(ConfigManager.Startup_Delay_Time.Value, LateInit, Log, new()
|
||||||
{
|
{
|
||||||
Disable_EventSystem_Override = ConfigManager.Disable_EventSystem_Override.Value,
|
Disable_EventSystem_Override = ConfigManager.Disable_EventSystem_Override.Value,
|
||||||
Force_Unlock_Mouse = ConfigManager.Force_Unlock_Mouse.Value,
|
Force_Unlock_Mouse = ConfigManager.Force_Unlock_Mouse.Value,
|
||||||
Unhollowed_Modules_Folder = loader.UnhollowedModulesFolder
|
Unhollowed_Modules_Folder = loader.UnhollowedModulesFolder
|
||||||
});
|
});
|
||||||
|
|
||||||
Log($"Finished core setup, waiting for late setup...");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do a delayed setup so that objects aren't destroyed instantly.
|
// Do a delayed setup so that objects aren't destroyed instantly.
|
||||||
// This can happen for a multitude of reasons.
|
// This can happen for a multitude of reasons.
|
||||||
// Default delay is 1 second which is usually enough.
|
// Default delay is 1 second which is usually enough.
|
||||||
private static void LateInit()
|
static void LateInit()
|
||||||
{
|
{
|
||||||
Log($"Setting up late core features...");
|
Log($"Setting up late core features...");
|
||||||
|
|
||||||
@ -68,19 +63,18 @@ namespace UnityExplorer
|
|||||||
|
|
||||||
UIManager.InitUI();
|
UIManager.InitUI();
|
||||||
|
|
||||||
Log($"{NAME} {VERSION} initialized.");
|
Log($"{NAME} {VERSION} ({Universe.Context}) initialized.");
|
||||||
|
|
||||||
|
//InspectorManager.Inspect(typeof(Tests.TestClass));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
internal static void Update()
|
||||||
/// Should be called once per frame.
|
|
||||||
/// </summary>
|
|
||||||
public static void Update()
|
|
||||||
{
|
{
|
||||||
UIManager.Update();
|
|
||||||
|
|
||||||
// check master toggle
|
// check master toggle
|
||||||
if (InputManager.GetKeyDown(ConfigManager.Master_Toggle.Value))
|
if (InputManager.GetKeyDown(ConfigManager.Master_Toggle.Value))
|
||||||
UIManager.ShowMenu = !UIManager.ShowMenu;
|
UIManager.ShowMenu = !UIManager.ShowMenu;
|
||||||
|
|
||||||
|
UIManager.Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
#region LOGGING
|
#region LOGGING
|
||||||
|
@ -7,7 +7,9 @@ using UnityEngine.UI;
|
|||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
using UnityExplorer.UI.Widgets;
|
using UnityExplorer.UI.Widgets;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
|
using UniverseLib.UI.Models;
|
||||||
using UniverseLib.UI.Widgets;
|
using UniverseLib.UI.Widgets;
|
||||||
|
using UniverseLib.UI.Widgets.ScrollView;
|
||||||
|
|
||||||
namespace UnityExplorer.Hooks
|
namespace UnityExplorer.Hooks
|
||||||
{
|
{
|
||||||
|
@ -5,7 +5,9 @@ using System.Text;
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
|
using UniverseLib.UI.Models;
|
||||||
using UniverseLib.UI.Widgets;
|
using UniverseLib.UI.Widgets;
|
||||||
|
using UniverseLib.UI.Widgets.ScrollView;
|
||||||
|
|
||||||
namespace UnityExplorer.Hooks
|
namespace UnityExplorer.Hooks
|
||||||
{
|
{
|
||||||
|
@ -52,9 +52,9 @@ namespace UnityExplorer.Hooks
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Evaluator.source_file
|
// Evaluator.source_file
|
||||||
private static readonly FieldInfo fi_sourceFile = ReflectionUtility.GetFieldInfo(typeof(Evaluator), "source_file");
|
private static readonly FieldInfo fi_sourceFile = AccessTools.Field(typeof(Evaluator), "source_file");
|
||||||
// TypeDefinition.Definition
|
// TypeDefinition.Definition
|
||||||
private static readonly PropertyInfo pi_Definition = ReflectionUtility.GetPropertyInfo(typeof(TypeDefinition), "Definition");
|
private static readonly PropertyInfo pi_Definition = AccessTools.Property(typeof(TypeDefinition), "Definition");
|
||||||
|
|
||||||
public bool CompileAndGenerateProcessor(string patchSource)
|
public bool CompileAndGenerateProcessor(string patchSource)
|
||||||
{
|
{
|
||||||
|
@ -6,13 +6,15 @@ using System.Reflection;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityExplorer.Core.Runtime;
|
using UnityExplorer.Runtime;
|
||||||
using UnityExplorer.CSConsole;
|
using UnityExplorer.CSConsole;
|
||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
using UnityExplorer.UI.Panels;
|
using UnityExplorer.UI.Panels;
|
||||||
using UnityExplorer.UI.Widgets;
|
using UnityExplorer.UI.Widgets;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
using UniverseLib.UI.Widgets;
|
using UniverseLib.UI.Widgets;
|
||||||
|
using UniverseLib.UI.Widgets.ScrollView;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.Hooks
|
namespace UnityExplorer.Hooks
|
||||||
{
|
{
|
||||||
@ -84,10 +86,10 @@ namespace UnityExplorer.Hooks
|
|||||||
cell.CurrentDisplayedIndex = index;
|
cell.CurrentDisplayedIndex = index;
|
||||||
var hook = (HookInstance)this.currentHooks[index];
|
var hook = (HookInstance)this.currentHooks[index];
|
||||||
|
|
||||||
cell.MethodNameLabel.text = HighlightMethod(hook.TargetMethod);
|
cell.MethodNameLabel.text = SignatureHighlighter.HighlightMethod(hook.TargetMethod);
|
||||||
|
|
||||||
cell.ToggleActiveButton.ButtonText.text = hook.Enabled ? "Enabled" : "Disabled";
|
cell.ToggleActiveButton.ButtonText.text = hook.Enabled ? "Enabled" : "Disabled";
|
||||||
RuntimeProvider.Instance.SetColorBlockAuto(cell.ToggleActiveButton.Component,
|
RuntimeHelper.SetColorBlockAuto(cell.ToggleActiveButton.Component,
|
||||||
hook.Enabled ? new Color(0.15f, 0.2f, 0.15f) : new Color(0.2f, 0.2f, 0.15f));
|
hook.Enabled ? new Color(0.15f, 0.2f, 0.15f) : new Color(0.2f, 0.2f, 0.15f));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,7 +111,7 @@ namespace UnityExplorer.Hooks
|
|||||||
currentAddEligableMethods.Clear();
|
currentAddEligableMethods.Clear();
|
||||||
foreach (var method in type.GetMethods(ReflectionUtility.FLAGS))
|
foreach (var method in type.GetMethods(ReflectionUtility.FLAGS))
|
||||||
{
|
{
|
||||||
if (method.IsGenericMethod /* || method.IsAbstract */ || RuntimeHelper.IsBlacklisted(method))
|
if (method.IsGenericMethod || UERuntimeHelper.IsBlacklisted(method))
|
||||||
continue;
|
continue;
|
||||||
currentAddEligableMethods.Add(method);
|
currentAddEligableMethods.Add(method);
|
||||||
filteredEligableMethods.Add(method);
|
filteredEligableMethods.Add(method);
|
||||||
@ -183,7 +185,7 @@ namespace UnityExplorer.Hooks
|
|||||||
cell.CurrentDisplayedIndex = index;
|
cell.CurrentDisplayedIndex = index;
|
||||||
var method = this.filteredEligableMethods[index];
|
var method = this.filteredEligableMethods[index];
|
||||||
|
|
||||||
cell.MethodNameLabel.text = HighlightMethod(method);
|
cell.MethodNameLabel.text = SignatureHighlighter.HighlightMethod(method);
|
||||||
|
|
||||||
var sig = method.FullDescription();
|
var sig = method.FullDescription();
|
||||||
if (hookedSignatures.Contains(sig))
|
if (hookedSignatures.Contains(sig))
|
||||||
@ -225,50 +227,5 @@ namespace UnityExplorer.Hooks
|
|||||||
Panel.SetPage(HookManagerPanel.Pages.CurrentHooks);
|
Panel.SetPage(HookManagerPanel.Pages.CurrentHooks);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ~~~~~~~~~~ Method syntax highlighting
|
|
||||||
|
|
||||||
private static readonly Dictionary<string, string> highlightedMethods = new Dictionary<string, string>();
|
|
||||||
|
|
||||||
private string HighlightMethod(MethodInfo method)
|
|
||||||
{
|
|
||||||
var sig = method.FullDescription();
|
|
||||||
if (highlightedMethods.ContainsKey(sig))
|
|
||||||
return highlightedMethods[sig];
|
|
||||||
|
|
||||||
var sb = new StringBuilder();
|
|
||||||
|
|
||||||
// declaring type
|
|
||||||
sb.Append(SignatureHighlighter.Parse(method.DeclaringType, false));
|
|
||||||
sb.Append('.');
|
|
||||||
|
|
||||||
// method name
|
|
||||||
var color = !method.IsStatic
|
|
||||||
? SignatureHighlighter.METHOD_INSTANCE
|
|
||||||
: SignatureHighlighter.METHOD_STATIC;
|
|
||||||
sb.Append($"<color={color}>{method.Name}</color>");
|
|
||||||
|
|
||||||
// arguments
|
|
||||||
sb.Append('(');
|
|
||||||
var args = method.GetParameters();
|
|
||||||
if (args != null && args.Any())
|
|
||||||
{
|
|
||||||
int i = 0;
|
|
||||||
foreach (var param in args)
|
|
||||||
{
|
|
||||||
sb.Append(SignatureHighlighter.Parse(param.ParameterType, false));
|
|
||||||
sb.Append(' ');
|
|
||||||
sb.Append($"<color={SignatureHighlighter.LOCAL_ARG}>{param.Name}</color>");
|
|
||||||
i++;
|
|
||||||
if (i < args.Length)
|
|
||||||
sb.Append(", ");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sb.Append(')');
|
|
||||||
|
|
||||||
var ret = sb.ToString();
|
|
||||||
highlightedMethods.Add(sig, ret);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<InputAssemblies Include="$(OutputPath)$(AssemblyName).dll" />
|
<InputAssemblies Include="$(OutputPath)$(AssemblyName).dll" />
|
||||||
<InputAssemblies Include="..\lib\mcs-unity\mcs\bin\Release\mcs.dll" />
|
<InputAssemblies Include="..\lib\mcs-unity\mcs\bin\Release\mcs.dll" />
|
||||||
<InputAssemblies Include="packages\ini-parser.2.5.2\lib\net20\INIFileParser.dll" />
|
<InputAssemblies Include="packages\Samboy063.Tomlet.3.1.3\lib\net35\Tomlet.dll" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<!-- Required references for ILRepack -->
|
<!-- Required references for ILRepack -->
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ReferenceFolders Include="packages\HarmonyX.2.5.2\lib\net35\" />
|
<ReferenceFolders Include="packages\HarmonyX.2.5.2\lib\net35\" />
|
||||||
|
@ -14,6 +14,8 @@ using UnityExplorer.UI.Widgets.AutoComplete;
|
|||||||
using UniverseLib.UI.Widgets;
|
using UniverseLib.UI.Widgets;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
|
using UniverseLib.UI.Widgets.ScrollView;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.Inspectors
|
namespace UnityExplorer.Inspectors
|
||||||
{
|
{
|
||||||
@ -44,7 +46,7 @@ namespace UnityExplorer.Inspectors
|
|||||||
GOControls.UpdateGameObjectInfo(true, true);
|
GOControls.UpdateGameObjectInfo(true, true);
|
||||||
GOControls.UpdateTransformControlValues(true);
|
GOControls.UpdateTransformControlValues(true);
|
||||||
|
|
||||||
RuntimeProvider.Instance.StartCoroutine(InitCoroutine());
|
RuntimeHelper.StartCoroutine(InitCoroutine());
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerator InitCoroutine()
|
private IEnumerator InitCoroutine()
|
||||||
@ -80,7 +82,7 @@ namespace UnityExplorer.Inspectors
|
|||||||
this.Target = newTarget;
|
this.Target = newTarget;
|
||||||
GOControls.UpdateGameObjectInfo(true, true);
|
GOControls.UpdateGameObjectInfo(true, true);
|
||||||
GOControls.UpdateTransformControlValues(true);
|
GOControls.UpdateTransformControlValues(true);
|
||||||
TransformTree.RefreshData(true, false);
|
TransformTree.RefreshData(true, false, true, false);
|
||||||
UpdateComponents();
|
UpdateComponents();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,7 +109,7 @@ namespace UnityExplorer.Inspectors
|
|||||||
|
|
||||||
GOControls.UpdateGameObjectInfo(false, false);
|
GOControls.UpdateGameObjectInfo(false, false);
|
||||||
|
|
||||||
TransformTree.RefreshData(true, false);
|
TransformTree.RefreshData(true, false, false, false);
|
||||||
UpdateComponents();
|
UpdateComponents();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -218,7 +220,7 @@ namespace UnityExplorer.Inspectors
|
|||||||
var newObject = new GameObject(input);
|
var newObject = new GameObject(input);
|
||||||
newObject.transform.parent = GOTarget.transform;
|
newObject.transform.parent = GOTarget.transform;
|
||||||
|
|
||||||
TransformTree.RefreshData(true, false);
|
TransformTree.RefreshData(true, false, true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnAddComponentClicked(string input)
|
private void OnAddComponentClicked(string input)
|
||||||
@ -227,7 +229,7 @@ namespace UnityExplorer.Inspectors
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
RuntimeProvider.Instance.AddComponent<Component>(GOTarget, type);
|
RuntimeHelper.AddComponent<Component>(GOTarget, type);
|
||||||
UpdateComponents();
|
UpdateComponents();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@ -241,7 +243,6 @@ namespace UnityExplorer.Inspectors
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#region UI Construction
|
#region UI Construction
|
||||||
|
|
||||||
public override GameObject CreateContent(GameObject parent)
|
public override GameObject CreateContent(GameObject parent)
|
||||||
|
@ -4,10 +4,10 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.UI;
|
using UniverseLib;
|
||||||
using UnityExplorer.UI.Widgets;
|
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
using UniverseLib.UI.Widgets;
|
using UniverseLib.UI.Models;
|
||||||
|
using UniverseLib.UI.Widgets.ButtonList;
|
||||||
|
|
||||||
namespace UnityExplorer.Inspectors
|
namespace UnityExplorer.Inspectors
|
||||||
{
|
{
|
||||||
@ -34,7 +34,8 @@ namespace UnityExplorer.Inspectors
|
|||||||
var root = base.CreateContent(parent);
|
var root = base.CreateContent(parent);
|
||||||
|
|
||||||
// Add mask to button so text doesnt overlap on Close button
|
// Add mask to button so text doesnt overlap on Close button
|
||||||
this.Button.Component.gameObject.AddComponent<Mask>().showMaskGraphic = true;
|
//this.Button.Component.gameObject.AddComponent<Mask>().showMaskGraphic = true;
|
||||||
|
this.Button.ButtonText.horizontalOverflow = HorizontalWrapMode.Wrap;
|
||||||
|
|
||||||
// Behaviour toggle
|
// Behaviour toggle
|
||||||
|
|
||||||
|
@ -3,9 +3,10 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityExplorer.UI.Widgets;
|
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
using UniverseLib.UI.Widgets;
|
using UniverseLib.UI.Widgets.ButtonList;
|
||||||
|
using UniverseLib.UI.Widgets.ScrollView;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.Inspectors
|
namespace UnityExplorer.Inspectors
|
||||||
{
|
{
|
||||||
@ -113,7 +114,7 @@ namespace UnityExplorer.Inspectors
|
|||||||
{
|
{
|
||||||
cell.BehaviourToggle.interactable = false;
|
cell.BehaviourToggle.interactable = false;
|
||||||
cell.BehaviourToggle.Set(true, false);
|
cell.BehaviourToggle.Set(true, false);
|
||||||
//RuntimeProvider.Instance.SetColorBlock(cell.BehaviourToggle,)
|
//RuntimeHelper.SetColorBlock(cell.BehaviourToggle,)
|
||||||
cell.BehaviourToggle.graphic.color = new Color(0.2f, 0.2f, 0.2f);
|
cell.BehaviourToggle.graphic.color = new Color(0.2f, 0.2f, 0.2f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,9 @@ using UniverseLib.Input;
|
|||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
|
using UnityExplorer.UI.Panels;
|
||||||
|
using UniverseLib.UI.Models;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.Inspectors
|
namespace UnityExplorer.Inspectors
|
||||||
{
|
{
|
||||||
@ -51,6 +54,11 @@ namespace UnityExplorer.Inspectors
|
|||||||
ConstructTransformControls();
|
ConstructTransformControls();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnCopyClicked()
|
||||||
|
{
|
||||||
|
ClipboardPanel.Copy(this.GOTarget);
|
||||||
|
}
|
||||||
|
|
||||||
#region GO Controls
|
#region GO Controls
|
||||||
|
|
||||||
private string lastGoName;
|
private string lastGoName;
|
||||||
@ -169,7 +177,7 @@ namespace UnityExplorer.Inspectors
|
|||||||
{
|
{
|
||||||
// look for inactive objects
|
// look for inactive objects
|
||||||
var name = input.Split('/').Last();
|
var name = input.Split('/').Last();
|
||||||
var allObjects = RuntimeProvider.Instance.FindObjectsOfTypeAll(typeof(GameObject));
|
var allObjects = RuntimeHelper.FindObjectsOfTypeAll(typeof(GameObject));
|
||||||
var shortList = new List<GameObject>();
|
var shortList = new List<GameObject>();
|
||||||
foreach (var obj in allObjects)
|
foreach (var obj in allObjects)
|
||||||
if (obj.name == name) shortList.Add(obj.TryCast<GameObject>());
|
if (obj.name == name) shortList.Add(obj.TryCast<GameObject>());
|
||||||
@ -467,6 +475,11 @@ namespace UnityExplorer.Inspectors
|
|||||||
UIFactory.SetLayoutElement(PathInput.UIRoot, minHeight: 25, minWidth: 100, flexibleWidth: 9999);
|
UIFactory.SetLayoutElement(PathInput.UIRoot, minHeight: 25, minWidth: 100, flexibleWidth: 9999);
|
||||||
PathInput.Component.lineType = InputField.LineType.MultiLineSubmit;
|
PathInput.Component.lineType = InputField.LineType.MultiLineSubmit;
|
||||||
|
|
||||||
|
var copyButton = UIFactory.CreateButton(firstRow, "CopyButton", "Copy to Clipboard", new Color(0.2f, 0.2f, 0.2f, 1));
|
||||||
|
copyButton.ButtonText.color = Color.yellow;
|
||||||
|
UIFactory.SetLayoutElement(copyButton.Component.gameObject, minHeight: 25, minWidth: 120);
|
||||||
|
copyButton.OnClick += OnCopyClicked;
|
||||||
|
|
||||||
//var pathApplyBtn = UIFactory.CreateButton(firstRow, "PathButton", "Set Parent Path", new Color(0.2f, 0.2f, 0.2f));
|
//var pathApplyBtn = UIFactory.CreateButton(firstRow, "PathButton", "Set Parent Path", new Color(0.2f, 0.2f, 0.2f));
|
||||||
//UIFactory.SetLayoutElement(pathApplyBtn.Component.gameObject, minHeight: 25, minWidth: 120);
|
//UIFactory.SetLayoutElement(pathApplyBtn.Component.gameObject, minHeight: 25, minWidth: 120);
|
||||||
//pathApplyBtn.OnClick += () => { OnPathEndEdit(PathInput.Text); };
|
//pathApplyBtn.OnClick += () => { OnPathEndEdit(PathInput.Text); };
|
||||||
@ -561,7 +574,7 @@ namespace UnityExplorer.Inspectors
|
|||||||
var layerLabel = UIFactory.CreateLabel(thirdrow, "LayerLabel", "Layer:", TextAnchor.MiddleLeft, Color.grey);
|
var layerLabel = UIFactory.CreateLabel(thirdrow, "LayerLabel", "Layer:", TextAnchor.MiddleLeft, Color.grey);
|
||||||
UIFactory.SetLayoutElement(layerLabel.gameObject, minHeight: 25, minWidth: 50);
|
UIFactory.SetLayoutElement(layerLabel.gameObject, minHeight: 25, minWidth: 50);
|
||||||
|
|
||||||
var layerDrop = UIFactory.CreateDropdown(thirdrow, out LayerDropdown, "0", 14, OnLayerDropdownChanged);
|
var layerDrop = UIFactory.CreateDropdown(thirdrow, "LayerDropdown", out LayerDropdown, "0", 14, OnLayerDropdownChanged);
|
||||||
UIFactory.SetLayoutElement(layerDrop, minHeight: 25, minWidth: 110, flexibleWidth: 999);
|
UIFactory.SetLayoutElement(layerDrop, minHeight: 25, minWidth: 110, flexibleWidth: 999);
|
||||||
LayerDropdown.captionText.color = SignatureHighlighter.EnumGreen;
|
LayerDropdown.captionText.color = SignatureHighlighter.EnumGreen;
|
||||||
if (layerToNames == null)
|
if (layerToNames == null)
|
||||||
@ -575,7 +588,7 @@ namespace UnityExplorer.Inspectors
|
|||||||
var flagsLabel = UIFactory.CreateLabel(thirdrow, "FlagsLabel", "Flags:", TextAnchor.MiddleRight, Color.grey);
|
var flagsLabel = UIFactory.CreateLabel(thirdrow, "FlagsLabel", "Flags:", TextAnchor.MiddleRight, Color.grey);
|
||||||
UIFactory.SetLayoutElement(flagsLabel.gameObject, minHeight: 25, minWidth: 50);
|
UIFactory.SetLayoutElement(flagsLabel.gameObject, minHeight: 25, minWidth: 50);
|
||||||
|
|
||||||
var flagsDrop = UIFactory.CreateDropdown(thirdrow, out FlagsDropdown, "None", 14, OnFlagsDropdownChanged);
|
var flagsDrop = UIFactory.CreateDropdown(thirdrow, "FlagsDropdown", out FlagsDropdown, "None", 14, OnFlagsDropdownChanged);
|
||||||
FlagsDropdown.captionText.color = SignatureHighlighter.EnumGreen;
|
FlagsDropdown.captionText.color = SignatureHighlighter.EnumGreen;
|
||||||
UIFactory.SetLayoutElement(flagsDrop, minHeight: 25, minWidth: 135, flexibleWidth: 999);
|
UIFactory.SetLayoutElement(flagsDrop, minHeight: 25, minWidth: 135, flexibleWidth: 999);
|
||||||
if (hideFlagsValues == null)
|
if (hideFlagsValues == null)
|
||||||
@ -593,7 +606,7 @@ namespace UnityExplorer.Inspectors
|
|||||||
layerToNames = new List<string>();
|
layerToNames = new List<string>();
|
||||||
for (int i = 0; i < 32; i++)
|
for (int i = 0; i < 32; i++)
|
||||||
{
|
{
|
||||||
var name = RuntimeProvider.Instance.LayerToName(i);
|
var name = RuntimeHelper.LayerToName(i);
|
||||||
if (string.IsNullOrEmpty(name))
|
if (string.IsNullOrEmpty(name))
|
||||||
name = i.ToString();
|
name = i.ToString();
|
||||||
layerToNames.Add(name);
|
layerToNames.Add(name);
|
||||||
|
@ -8,6 +8,7 @@ using UnityExplorer.UI;
|
|||||||
using UniverseLib.UI.Models;
|
using UniverseLib.UI.Models;
|
||||||
using UnityExplorer.UI.Panels;
|
using UnityExplorer.UI.Panels;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
|
using UniverseLib.UI.ObjectPool;
|
||||||
|
|
||||||
namespace UnityExplorer.Inspectors
|
namespace UnityExplorer.Inspectors
|
||||||
{
|
{
|
||||||
|
@ -11,18 +11,22 @@ using UniverseLib.UI.Models;
|
|||||||
using UnityExplorer.UI.Panels;
|
using UnityExplorer.UI.Panels;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
|
using UniverseLib.UI.ObjectPool;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer
|
namespace UnityExplorer
|
||||||
{
|
{
|
||||||
public static class InspectorManager
|
public static class InspectorManager
|
||||||
{
|
{
|
||||||
public static readonly List<InspectorBase> Inspectors = new List<InspectorBase>();
|
public static readonly List<InspectorBase> Inspectors = new();
|
||||||
|
|
||||||
public static InspectorBase ActiveInspector { get; private set; }
|
public static InspectorBase ActiveInspector { get; private set; }
|
||||||
private static InspectorBase lastActiveInspector;
|
private static InspectorBase lastActiveInspector;
|
||||||
|
|
||||||
public static float PanelWidth;
|
public static float PanelWidth;
|
||||||
|
|
||||||
|
public static event Action OnInspectedTabsChanged;
|
||||||
|
|
||||||
public static void Inspect(object obj, CacheObjectBase sourceCache = null)
|
public static void Inspect(object obj, CacheObjectBase sourceCache = null)
|
||||||
{
|
{
|
||||||
if (obj.IsNullOrDestroyed())
|
if (obj.IsNullOrDestroyed())
|
||||||
@ -90,17 +94,17 @@ namespace UnityExplorer
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void CreateInspector<T>(object target, bool staticReflection = false,
|
private static void CreateInspector<T>(object target, bool staticReflection = false,
|
||||||
CacheObjectBase sourceCache = null) where T : InspectorBase
|
CacheObjectBase parentObject = null) where T : InspectorBase
|
||||||
{
|
{
|
||||||
var inspector = Pool<T>.Borrow();
|
var inspector = Pool<T>.Borrow();
|
||||||
Inspectors.Add(inspector);
|
Inspectors.Add(inspector);
|
||||||
inspector.Target = target;
|
inspector.Target = target;
|
||||||
|
|
||||||
if (sourceCache != null && sourceCache.CanWrite)
|
if (parentObject != null && parentObject.CanWrite)
|
||||||
{
|
{
|
||||||
// only set parent cache object if we are inspecting a struct, otherwise there is no point.
|
// only set parent cache object if we are inspecting a struct, otherwise there is no point.
|
||||||
if (target.GetType().IsValueType && inspector is ReflectionInspector ri)
|
if (target.GetType().IsValueType && inspector is ReflectionInspector ri)
|
||||||
ri.ParentCacheObject = sourceCache;
|
ri.ParentCacheObject = parentObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
UIManager.SetPanelActive(UIManager.Panels.Inspector, true);
|
UIManager.SetPanelActive(UIManager.Panels.Inspector, true);
|
||||||
@ -111,6 +115,8 @@ namespace UnityExplorer
|
|||||||
|
|
||||||
inspector.OnBorrowedFromPool(target);
|
inspector.OnBorrowedFromPool(target);
|
||||||
SetInspectorActive(inspector);
|
SetInspectorActive(inspector);
|
||||||
|
|
||||||
|
OnInspectedTabsChanged?.Invoke();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void ReleaseInspector<T>(T inspector) where T : InspectorBase
|
internal static void ReleaseInspector<T>(T inspector) where T : InspectorBase
|
||||||
@ -144,6 +150,8 @@ namespace UnityExplorer
|
|||||||
UIManager.SetPanelActive(UIManager.Panels.Inspector, false);
|
UIManager.SetPanelActive(UIManager.Panels.Inspector, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OnInspectedTabsChanged?.Invoke();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void Update()
|
internal static void Update()
|
||||||
|
@ -9,52 +9,51 @@ using UniverseLib.UI.Models;
|
|||||||
using UnityExplorer.UI.Widgets;
|
using UnityExplorer.UI.Widgets;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
|
using UnityExplorer.UI.Panels;
|
||||||
|
using UniverseLib.UI.ObjectPool;
|
||||||
|
|
||||||
namespace UnityExplorer.Inspectors
|
namespace UnityExplorer.Inspectors
|
||||||
{
|
{
|
||||||
public class InspectorTab : IPooledObject
|
public class InspectorTab : IPooledObject
|
||||||
{
|
{
|
||||||
public GameObject UIRoot { get; set; }
|
public GameObject UIRoot { get; set; }
|
||||||
|
|
||||||
public float DefaultHeight => 25f;
|
public float DefaultHeight => 25f;
|
||||||
|
|
||||||
public ButtonRef TabButton;
|
public ButtonRef TabButton;
|
||||||
public Text TabText;
|
public Text TabText;
|
||||||
|
|
||||||
public ButtonRef CloseButton;
|
public ButtonRef CloseButton;
|
||||||
|
|
||||||
private static readonly Color _enabledTabColor = new Color(0.15f, 0.22f, 0.15f);
|
private static readonly Color enabledTabColor = new(0.15f, 0.22f, 0.15f);
|
||||||
private static readonly Color _disabledTabColor = new Color(0.13f, 0.13f, 0.13f);
|
private static readonly Color disabledTabColor = new(0.13f, 0.13f, 0.13f);
|
||||||
|
|
||||||
public void SetTabColor(bool active)
|
public void SetTabColor(bool active)
|
||||||
{
|
{
|
||||||
if (active)
|
Color color = active ? enabledTabColor : disabledTabColor;
|
||||||
RuntimeProvider.Instance.SetColorBlock(TabButton.Component, _enabledTabColor, _enabledTabColor * 1.2f);
|
RuntimeHelper.SetColorBlock(TabButton.Component, color, color * 1.2f);
|
||||||
else
|
|
||||||
RuntimeProvider.Instance.SetColorBlock(TabButton.Component, _disabledTabColor, _disabledTabColor * 1.2f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public GameObject CreateContent(GameObject parent)
|
public GameObject CreateContent(GameObject parent)
|
||||||
{
|
{
|
||||||
UIRoot = UIFactory.CreateHorizontalGroup(parent, "TabObject", false, true, true, true, 0,
|
UIRoot = UIFactory.CreateHorizontalGroup(parent, "TabObject", false, true, true, true, 1,
|
||||||
default, new Color(0.13f, 0.13f, 0.13f), childAlignment: TextAnchor.MiddleLeft);
|
default, new Color(0.13f, 0.13f, 0.13f), childAlignment: TextAnchor.MiddleLeft);
|
||||||
UIFactory.SetLayoutElement(UIRoot, minWidth: 200, flexibleWidth: 0);
|
UIFactory.SetLayoutElement(UIRoot, minWidth: 200, flexibleWidth: 0);
|
||||||
UIRoot.AddComponent<Mask>();
|
UIRoot.AddComponent<Mask>();
|
||||||
|
UIRoot.AddComponent<Outline>();
|
||||||
|
|
||||||
TabButton = UIFactory.CreateButton(UIRoot, "TabButton", "");
|
TabButton = UIFactory.CreateButton(UIRoot, "TabButton", "");
|
||||||
UIFactory.SetLayoutElement(TabButton.Component.gameObject, minWidth: 175, flexibleWidth: 0);
|
UIFactory.SetLayoutElement(TabButton.Component.gameObject, minWidth: 173, flexibleWidth: 0);
|
||||||
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(TabButton.Component.gameObject, false, false, true, true, 0, 0, 0, 3);
|
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(TabButton.Component.gameObject, false, false, true, true, 0, 0, 0, 3);
|
||||||
|
TabButton.GameObject.AddComponent<Mask>();
|
||||||
|
|
||||||
TabText = TabButton.Component.GetComponentInChildren<Text>();
|
TabText = TabButton.ButtonText;
|
||||||
UIFactory.SetLayoutElement(TabText.gameObject, minHeight: 25, minWidth: 175, flexibleWidth: 0);
|
UIFactory.SetLayoutElement(TabText.gameObject, minHeight: 25, minWidth: 150, flexibleWidth: 0);
|
||||||
TabText.alignment = TextAnchor.MiddleLeft;
|
TabText.alignment = TextAnchor.MiddleLeft;
|
||||||
TabText.fontSize = 12;
|
TabText.fontSize = 12;
|
||||||
TabText.horizontalOverflow = HorizontalWrapMode.Overflow;
|
TabText.horizontalOverflow = HorizontalWrapMode.Overflow;
|
||||||
|
|
||||||
CloseButton = UIFactory.CreateButton(UIRoot, "CloseButton", "X", new Color(0.2f, 0.2f, 0.2f, 1));
|
CloseButton = UIFactory.CreateButton(UIRoot, "CloseButton", "X", new Color(0.15f, 0.15f, 0.15f, 1));
|
||||||
UIFactory.SetLayoutElement(CloseButton.Component.gameObject, minHeight: 25, minWidth: 25, flexibleWidth: 0);
|
UIFactory.SetLayoutElement(CloseButton.Component.gameObject, minHeight: 25, minWidth: 25, flexibleWidth: 0);
|
||||||
var closeBtnText = CloseButton.Component.GetComponentInChildren<Text>();
|
CloseButton.ButtonText.color = Color.red;
|
||||||
closeBtnText.color = Color.red;
|
|
||||||
|
|
||||||
return UIRoot;
|
return UIRoot;
|
||||||
}
|
}
|
||||||
|
@ -5,14 +5,15 @@ using System.Text;
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.EventSystems;
|
using UnityEngine.EventSystems;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.Core;
|
|
||||||
using UniverseLib.Input;
|
using UniverseLib.Input;
|
||||||
using UnityExplorer.Core.Runtime;
|
using UnityExplorer.Runtime;
|
||||||
using UnityExplorer.Inspectors.MouseInspectors;
|
using UnityExplorer.Inspectors.MouseInspectors;
|
||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
using UnityExplorer.UI.Panels;
|
using UnityExplorer.UI.Panels;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
using UnityExplorer.Config;
|
||||||
|
|
||||||
namespace UnityExplorer.Inspectors
|
namespace UnityExplorer.Inspectors
|
||||||
{
|
{
|
||||||
@ -22,9 +23,9 @@ namespace UnityExplorer.Inspectors
|
|||||||
UI
|
UI
|
||||||
}
|
}
|
||||||
|
|
||||||
public class InspectUnderMouse : UIPanel
|
public class MouseInspector : UIPanel
|
||||||
{
|
{
|
||||||
public static InspectUnderMouse Instance { get; private set; }
|
public static MouseInspector Instance { get; private set; }
|
||||||
|
|
||||||
private readonly WorldInspector worldInspector;
|
private readonly WorldInspector worldInspector;
|
||||||
private readonly UiInspector uiInspector;
|
private readonly UiInspector uiInspector;
|
||||||
@ -32,24 +33,19 @@ namespace UnityExplorer.Inspectors
|
|||||||
public static bool Inspecting { get; set; }
|
public static bool Inspecting { get; set; }
|
||||||
public static MouseInspectMode Mode { get; set; }
|
public static MouseInspectMode Mode { get; set; }
|
||||||
|
|
||||||
|
public MouseInspectorBase CurrentInspector => Mode switch
|
||||||
|
{
|
||||||
|
MouseInspectMode.UI => uiInspector,
|
||||||
|
MouseInspectMode.World => worldInspector,
|
||||||
|
_ => null,
|
||||||
|
};
|
||||||
|
|
||||||
private static Vector3 lastMousePos;
|
private static Vector3 lastMousePos;
|
||||||
|
|
||||||
public MouseInspectorBase CurrentInspector
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
switch (Mode)
|
|
||||||
{
|
|
||||||
case MouseInspectMode.UI:
|
|
||||||
return uiInspector;
|
|
||||||
case MouseInspectMode.World:
|
|
||||||
return worldInspector;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// UIPanel
|
// UIPanel
|
||||||
|
internal static readonly string UIBaseGUID = $"{ExplorerCore.GUID}.MouseInspector";
|
||||||
|
private UIBase inspectorUIBase;
|
||||||
|
|
||||||
public override string Name => "Inspect Under Mouse";
|
public override string Name => "Inspect Under Mouse";
|
||||||
public override UIManager.Panels PanelType => UIManager.Panels.MouseInspector;
|
public override UIManager.Panels PanelType => UIManager.Panels.MouseInspector;
|
||||||
public override int MinWidth => -1;
|
public override int MinWidth => -1;
|
||||||
@ -63,7 +59,7 @@ namespace UnityExplorer.Inspectors
|
|||||||
internal Text objPathLabel;
|
internal Text objPathLabel;
|
||||||
internal Text mousePosLabel;
|
internal Text mousePosLabel;
|
||||||
|
|
||||||
public InspectUnderMouse()
|
public MouseInspector()
|
||||||
{
|
{
|
||||||
Instance = this;
|
Instance = this;
|
||||||
worldInspector = new WorldInspector();
|
worldInspector = new WorldInspector();
|
||||||
@ -78,7 +74,7 @@ namespace UnityExplorer.Inspectors
|
|||||||
case 1: Instance.StartInspect(MouseInspectMode.World); break;
|
case 1: Instance.StartInspect(MouseInspectMode.World); break;
|
||||||
case 2: Instance.StartInspect(MouseInspectMode.UI); break;
|
case 2: Instance.StartInspect(MouseInspectMode.UI); break;
|
||||||
}
|
}
|
||||||
UIManager.MouseInspectDropdown.value = 0;
|
InspectorPanel.Instance.MouseInspectDropdown.value = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void StartInspect(MouseInspectMode mode)
|
public void StartInspect(MouseInspectMode mode)
|
||||||
@ -112,7 +108,7 @@ namespace UnityExplorer.Inspectors
|
|||||||
UIManager.NavBarRect.gameObject.SetActive(true);
|
UIManager.NavBarRect.gameObject.SetActive(true);
|
||||||
UIManager.PanelHolder.SetActive(true);
|
UIManager.PanelHolder.SetActive(true);
|
||||||
|
|
||||||
var drop = UIManager.MouseInspectDropdown;
|
var drop = InspectorPanel.Instance.MouseInspectDropdown;
|
||||||
if (drop.transform.Find("Dropdown List") is Transform list)
|
if (drop.transform.Find("Dropdown List") is Transform list)
|
||||||
drop.DestroyDropdownList(list.gameObject);
|
drop.DestroyDropdownList(list.gameObject);
|
||||||
|
|
||||||
@ -121,6 +117,26 @@ namespace UnityExplorer.Inspectors
|
|||||||
|
|
||||||
private static float timeOfLastRaycast;
|
private static float timeOfLastRaycast;
|
||||||
|
|
||||||
|
public bool TryUpdate()
|
||||||
|
{
|
||||||
|
if (ConfigManager.World_MouseInspect_Keybind.Value != KeyCode.None)
|
||||||
|
{
|
||||||
|
if (InputManager.GetKeyDown(ConfigManager.World_MouseInspect_Keybind.Value))
|
||||||
|
Instance.StartInspect(MouseInspectMode.World);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ConfigManager.World_MouseInspect_Keybind.Value != KeyCode.None)
|
||||||
|
{
|
||||||
|
if (InputManager.GetKeyDown(ConfigManager.World_MouseInspect_Keybind.Value))
|
||||||
|
Instance.StartInspect(MouseInspectMode.World);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Inspecting)
|
||||||
|
UpdateInspect();
|
||||||
|
|
||||||
|
return Inspecting;
|
||||||
|
}
|
||||||
|
|
||||||
public void UpdateInspect()
|
public void UpdateInspect()
|
||||||
{
|
{
|
||||||
if (InputManager.GetKeyDown(KeyCode.Escape))
|
if (InputManager.GetKeyDown(KeyCode.Escape))
|
||||||
@ -165,7 +181,7 @@ namespace UnityExplorer.Inspectors
|
|||||||
mousePos.y -= 10;
|
mousePos.y -= 10;
|
||||||
|
|
||||||
// calculate and set our UI position
|
// calculate and set our UI position
|
||||||
var inversePos = UIManager.UIRoot.transform.InverseTransformPoint(mousePos);
|
var inversePos = inspectorUIBase.RootObject.transform.InverseTransformPoint(mousePos);
|
||||||
UIRoot.transform.localPosition = new Vector3(inversePos.x, inversePos.y, 0);
|
UIRoot.transform.localPosition = new Vector3(inversePos.x, inversePos.y, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,10 +198,10 @@ namespace UnityExplorer.Inspectors
|
|||||||
public override void ConstructPanelContent()
|
public override void ConstructPanelContent()
|
||||||
{
|
{
|
||||||
// hide title bar
|
// hide title bar
|
||||||
this.titleBar.SetActive(false);
|
this.TitleBar.SetActive(false);
|
||||||
this.UIRoot.transform.SetParent(UIManager.UIRoot.transform, false);
|
this.UIRoot.transform.SetParent(UIManager.UIRoot.transform, false);
|
||||||
|
|
||||||
var inspectContent = UIFactory.CreateVerticalGroup(this.content, "InspectContent", true, true, true, true, 3, new Vector4(2, 2, 2, 2));
|
var inspectContent = UIFactory.CreateVerticalGroup(this.uiContent, "InspectContent", true, true, true, true, 3, new Vector4(2, 2, 2, 2));
|
||||||
UIFactory.SetLayoutElement(inspectContent, flexibleWidth: 9999, flexibleHeight: 9999);
|
UIFactory.SetLayoutElement(inspectContent, flexibleWidth: 9999, flexibleHeight: 9999);
|
||||||
|
|
||||||
// Title text
|
// Title text
|
||||||
@ -208,10 +224,12 @@ namespace UnityExplorer.Inspectors
|
|||||||
UIFactory.SetLayoutElement(objPathLabel.gameObject, minHeight: 75);
|
UIFactory.SetLayoutElement(objPathLabel.gameObject, minHeight: 75);
|
||||||
|
|
||||||
UIRoot.SetActive(false);
|
UIRoot.SetActive(false);
|
||||||
|
|
||||||
|
// Create a new canvas for this panel to live on.
|
||||||
|
// It needs to always be shown on the main display, other panels can move displays.
|
||||||
|
|
||||||
|
inspectorUIBase = UniversalUI.RegisterUI(UIBaseGUID, null);
|
||||||
|
UIRoot.transform.SetParent(inspectorUIBase.RootObject.transform);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void DoSaveToConfigElement() { }
|
|
||||||
|
|
||||||
public override string GetSaveDataFromConfigManager() => null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
@ -8,6 +9,7 @@ using UnityEngine.UI;
|
|||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
using UnityExplorer.UI.Panels;
|
using UnityExplorer.UI.Panels;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
|
using UniverseLib.Input;
|
||||||
|
|
||||||
namespace UnityExplorer.Inspectors.MouseInspectors
|
namespace UnityExplorer.Inspectors.MouseInspectors
|
||||||
{
|
{
|
||||||
@ -26,7 +28,7 @@ namespace UnityExplorer.Inspectors.MouseInspectors
|
|||||||
public override void OnBeginMouseInspect()
|
public override void OnBeginMouseInspect()
|
||||||
{
|
{
|
||||||
SetupUIRaycast();
|
SetupUIRaycast();
|
||||||
InspectUnderMouse.Instance.objPathLabel.text = "";
|
MouseInspector.Instance.objPathLabel.text = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void ClearHitData()
|
public override void ClearHitData()
|
||||||
@ -38,6 +40,12 @@ namespace UnityExplorer.Inspectors.MouseInspectors
|
|||||||
{
|
{
|
||||||
LastHitObjects.Clear();
|
LastHitObjects.Clear();
|
||||||
LastHitObjects.AddRange(currentHitObjects);
|
LastHitObjects.AddRange(currentHitObjects);
|
||||||
|
RuntimeHelper.StartCoroutine(SetPanelActiveCoro());
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerator SetPanelActiveCoro()
|
||||||
|
{
|
||||||
|
yield return null;
|
||||||
var panel = UIManager.GetPanel<UiInspectorResultsPanel>(UIManager.Panels.UIInspectorResults);
|
var panel = UIManager.GetPanel<UiInspectorResultsPanel>(UIManager.Panels.UIInspectorResults);
|
||||||
panel.SetActive(true);
|
panel.SetActive(true);
|
||||||
panel.ShowResults();
|
panel.ShowResults();
|
||||||
@ -58,7 +66,7 @@ namespace UnityExplorer.Inspectors.MouseInspectors
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
var list = new List<RaycastResult>();
|
var list = new List<RaycastResult>();
|
||||||
RuntimeProvider.Instance.GraphicRaycast(gr, ped, list);
|
RuntimeHelper.GraphicRaycast(gr, ped, list);
|
||||||
if (list.Count > 0)
|
if (list.Count > 0)
|
||||||
{
|
{
|
||||||
foreach (var hit in list)
|
foreach (var hit in list)
|
||||||
@ -70,14 +78,14 @@ namespace UnityExplorer.Inspectors.MouseInspectors
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (currentHitObjects.Any())
|
if (currentHitObjects.Any())
|
||||||
InspectUnderMouse.Instance.objNameLabel.text = $"Click to view UI Objects under mouse: {currentHitObjects.Count}";
|
MouseInspector.Instance.objNameLabel.text = $"Click to view UI Objects under mouse: {currentHitObjects.Count}";
|
||||||
else
|
else
|
||||||
InspectUnderMouse.Instance.objNameLabel.text = $"No UI objects under mouse.";
|
MouseInspector.Instance.objNameLabel.text = $"No UI objects under mouse.";
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void SetupUIRaycast()
|
private static void SetupUIRaycast()
|
||||||
{
|
{
|
||||||
foreach (var obj in RuntimeProvider.Instance.FindObjectsOfTypeAll(typeof(Canvas)))
|
foreach (var obj in RuntimeHelper.FindObjectsOfTypeAll(typeof(Canvas)))
|
||||||
{
|
{
|
||||||
var canvas = obj.TryCast<Canvas>();
|
var canvas = obj.TryCast<Canvas>();
|
||||||
if (!canvas || !canvas.enabled || !canvas.gameObject.activeInHierarchy)
|
if (!canvas || !canvas.enabled || !canvas.gameObject.activeInHierarchy)
|
||||||
@ -91,7 +99,7 @@ namespace UnityExplorer.Inspectors.MouseInspectors
|
|||||||
}
|
}
|
||||||
|
|
||||||
// recache Graphic Raycasters each time we start
|
// recache Graphic Raycasters each time we start
|
||||||
var casters = RuntimeProvider.Instance.FindObjectsOfTypeAll(typeof(GraphicRaycaster));
|
var casters = RuntimeHelper.FindObjectsOfTypeAll(typeof(GraphicRaycaster));
|
||||||
graphicRaycasters = new GraphicRaycaster[casters.Length];
|
graphicRaycasters = new GraphicRaycaster[casters.Length];
|
||||||
for (int i = 0; i < casters.Length; i++)
|
for (int i = 0; i < casters.Length; i++)
|
||||||
{
|
{
|
||||||
@ -99,7 +107,7 @@ namespace UnityExplorer.Inspectors.MouseInspectors
|
|||||||
}
|
}
|
||||||
|
|
||||||
// enable raycastTarget on Graphics
|
// enable raycastTarget on Graphics
|
||||||
foreach (var obj in RuntimeProvider.Instance.FindObjectsOfTypeAll(typeof(Graphic)))
|
foreach (var obj in RuntimeHelper.FindObjectsOfTypeAll(typeof(Graphic)))
|
||||||
{
|
{
|
||||||
var graphic = obj.TryCast<Graphic>();
|
var graphic = obj.TryCast<Graphic>();
|
||||||
if (!graphic || !graphic.enabled || graphic.raycastTarget || !graphic.gameObject.activeInHierarchy)
|
if (!graphic || !graphic.enabled || graphic.raycastTarget || !graphic.gameObject.activeInHierarchy)
|
||||||
@ -110,7 +118,7 @@ namespace UnityExplorer.Inspectors.MouseInspectors
|
|||||||
}
|
}
|
||||||
|
|
||||||
// enable blocksRaycasts on CanvasGroups
|
// enable blocksRaycasts on CanvasGroups
|
||||||
foreach (var obj in RuntimeProvider.Instance.FindObjectsOfTypeAll(typeof(CanvasGroup)))
|
foreach (var obj in RuntimeHelper.FindObjectsOfTypeAll(typeof(CanvasGroup)))
|
||||||
{
|
{
|
||||||
var canvas = obj.TryCast<CanvasGroup>();
|
var canvas = obj.TryCast<CanvasGroup>();
|
||||||
if (!canvas || !canvas.gameObject.activeInHierarchy || canvas.blocksRaycasts)
|
if (!canvas || !canvas.gameObject.activeInHierarchy || canvas.blocksRaycasts)
|
||||||
|
@ -4,6 +4,7 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.Inspectors.MouseInspectors
|
namespace UnityExplorer.Inspectors.MouseInspectors
|
||||||
{
|
{
|
||||||
@ -35,13 +36,22 @@ namespace UnityExplorer.Inspectors.MouseInspectors
|
|||||||
|
|
||||||
public override void UpdateMouseInspect(Vector2 mousePos)
|
public override void UpdateMouseInspect(Vector2 mousePos)
|
||||||
{
|
{
|
||||||
|
if (!MainCamera)
|
||||||
|
MainCamera = Camera.main;
|
||||||
|
if (!MainCamera)
|
||||||
|
{
|
||||||
|
ExplorerCore.LogWarning("No Main Camera was found, unable to inspect world!");
|
||||||
|
MouseInspector.Instance.StopInspect();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var ray = MainCamera.ScreenPointToRay(mousePos);
|
var ray = MainCamera.ScreenPointToRay(mousePos);
|
||||||
Physics.Raycast(ray, out RaycastHit hit, 1000f);
|
Physics.Raycast(ray, out RaycastHit hit, 1000f);
|
||||||
|
|
||||||
if (hit.transform)
|
if (hit.transform)
|
||||||
OnHitGameObject(hit.transform.gameObject);
|
OnHitGameObject(hit.transform.gameObject);
|
||||||
else if (lastHitObject)
|
else if (lastHitObject)
|
||||||
InspectUnderMouse.Instance.ClearHitData();
|
MouseInspector.Instance.ClearHitData();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void OnHitGameObject(GameObject obj)
|
internal void OnHitGameObject(GameObject obj)
|
||||||
@ -49,8 +59,8 @@ namespace UnityExplorer.Inspectors.MouseInspectors
|
|||||||
if (obj != lastHitObject)
|
if (obj != lastHitObject)
|
||||||
{
|
{
|
||||||
lastHitObject = obj;
|
lastHitObject = obj;
|
||||||
InspectUnderMouse.Instance.objNameLabel.text = $"<b>Click to Inspect:</b> <color=cyan>{obj.name}</color>";
|
MouseInspector.Instance.objNameLabel.text = $"<b>Click to Inspect:</b> <color=cyan>{obj.name}</color>";
|
||||||
InspectUnderMouse.Instance.objPathLabel.text = $"Path: {obj.transform.GetTransformPath(true)}";
|
MouseInspector.Instance.objPathLabel.text = $"Path: {obj.transform.GetTransformPath(true)}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,26 +2,34 @@
|
|||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Reflection.Emit;
|
using System.Reflection.Emit;
|
||||||
using System.Text;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.Core.Config;
|
|
||||||
using UnityExplorer.Core.Runtime;
|
|
||||||
using UnityExplorer.CacheObject;
|
using UnityExplorer.CacheObject;
|
||||||
using UnityExplorer.CacheObject.Views;
|
using UnityExplorer.CacheObject.Views;
|
||||||
using UnityExplorer.UI.Panels;
|
using UnityExplorer.UI.Panels;
|
||||||
using UnityExplorer.UI.Widgets;
|
using UnityExplorer.UI.Widgets;
|
||||||
using UnityExplorer.UI;
|
|
||||||
using UniverseLib.UI.Widgets;
|
|
||||||
using UniverseLib.UI;
|
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
using UniverseLib.Runtime;
|
using UniverseLib.UI;
|
||||||
|
using UniverseLib.UI.Models;
|
||||||
|
using UniverseLib.UI.ObjectPool;
|
||||||
|
using UniverseLib.UI.Widgets.ScrollView;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.Inspectors
|
namespace UnityExplorer.Inspectors
|
||||||
{
|
{
|
||||||
|
[Flags]
|
||||||
|
public enum MemberFilter
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
Property = 1,
|
||||||
|
Field = 2,
|
||||||
|
Constructor = 4,
|
||||||
|
Method = 8,
|
||||||
|
All = Property | Field | Method | Constructor,
|
||||||
|
}
|
||||||
|
|
||||||
public class ReflectionInspector : InspectorBase, ICellPoolDataSource<CacheMemberCell>, ICacheObjectController
|
public class ReflectionInspector : InspectorBase, ICellPoolDataSource<CacheMemberCell>, ICacheObjectController
|
||||||
{
|
{
|
||||||
public CacheObjectBase ParentCacheObject { get; set; }
|
public CacheObjectBase ParentCacheObject { get; set; }
|
||||||
@ -29,43 +37,52 @@ namespace UnityExplorer.Inspectors
|
|||||||
public bool StaticOnly { get; internal set; }
|
public bool StaticOnly { get; internal set; }
|
||||||
public bool CanWrite => true;
|
public bool CanWrite => true;
|
||||||
|
|
||||||
private List<CacheMember> members = new List<CacheMember>();
|
|
||||||
private readonly List<CacheMember> filteredMembers = new List<CacheMember>();
|
|
||||||
|
|
||||||
public bool AutoUpdateWanted => autoUpdateToggle.isOn;
|
public bool AutoUpdateWanted => autoUpdateToggle.isOn;
|
||||||
|
|
||||||
private BindingFlags FlagsFilter;
|
private List<CacheMember> members = new();
|
||||||
private string NameFilter;
|
private readonly List<CacheMember> filteredMembers = new();
|
||||||
|
|
||||||
private MemberFlags MemberFilter = MemberFlags.All;
|
private BindingFlags scopeFlagsFilter;
|
||||||
private enum MemberFlags
|
private string nameFilter;
|
||||||
{
|
|
||||||
None = 0,
|
private MemberFilter MemberFilter = MemberFilter.All;
|
||||||
Property = 1,
|
|
||||||
Field = 2,
|
// Updating
|
||||||
Method = 4,
|
|
||||||
All = 7
|
private bool refreshWanted;
|
||||||
}
|
private string lastNameFilter;
|
||||||
|
private BindingFlags lastFlagsFilter;
|
||||||
|
private MemberFilter lastMemberFilter = MemberFilter.All;
|
||||||
|
private float timeOfLastAutoUpdate;
|
||||||
|
|
||||||
// UI
|
// UI
|
||||||
|
|
||||||
|
internal GameObject mainContentHolder;
|
||||||
|
private static int LeftGroupWidth { get; set; }
|
||||||
|
private static int RightGroupWidth { get; set; }
|
||||||
|
|
||||||
public ScrollPool<CacheMemberCell> MemberScrollPool { get; private set; }
|
public ScrollPool<CacheMemberCell> MemberScrollPool { get; private set; }
|
||||||
|
public int ItemCount => filteredMembers.Count;
|
||||||
|
|
||||||
|
public UnityObjectWidget UnityWidget;
|
||||||
|
|
||||||
public InputFieldRef HiddenNameText;
|
public InputFieldRef HiddenNameText;
|
||||||
public Text NameText;
|
public Text NameText;
|
||||||
public Text AssemblyText;
|
public Text AssemblyText;
|
||||||
private Toggle autoUpdateToggle;
|
private Toggle autoUpdateToggle;
|
||||||
|
|
||||||
private string currentBaseTabText;
|
internal string currentBaseTabText;
|
||||||
|
|
||||||
private readonly Color disabledButtonColor = new Color(0.24f, 0.24f, 0.24f);
|
private readonly Dictionary<BindingFlags, ButtonRef> scopeFilterButtons = new();
|
||||||
private readonly Color enabledButtonColor = new Color(0.2f, 0.27f, 0.2f);
|
private readonly List<Toggle> memberTypeToggles = new();
|
||||||
|
|
||||||
private readonly Dictionary<BindingFlags, ButtonRef> scopeFilterButtons = new Dictionary<BindingFlags, ButtonRef>();
|
|
||||||
private readonly List<Toggle> memberTypeToggles = new List<Toggle>();
|
|
||||||
private InputFieldRef filterInputField;
|
private InputFieldRef filterInputField;
|
||||||
|
|
||||||
// Setup / return
|
// const
|
||||||
|
|
||||||
|
private readonly Color disabledButtonColor = new(0.24f, 0.24f, 0.24f);
|
||||||
|
private readonly Color enabledButtonColor = new(0.2f, 0.27f, 0.2f);
|
||||||
|
|
||||||
|
// Setup
|
||||||
|
|
||||||
public override void OnBorrowedFromPool(object target)
|
public override void OnBorrowedFromPool(object target)
|
||||||
{
|
{
|
||||||
@ -74,7 +91,7 @@ namespace UnityExplorer.Inspectors
|
|||||||
|
|
||||||
SetTarget(target);
|
SetTarget(target);
|
||||||
|
|
||||||
RuntimeProvider.Instance.StartCoroutine(InitCoroutine());
|
RuntimeHelper.StartCoroutine(InitCoroutine());
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerator InitCoroutine()
|
private IEnumerator InitCoroutine()
|
||||||
@ -101,10 +118,12 @@ namespace UnityExplorer.Inspectors
|
|||||||
|
|
||||||
autoUpdateToggle.isOn = false;
|
autoUpdateToggle.isOn = false;
|
||||||
|
|
||||||
UnityObjectRef = null;
|
if (UnityWidget != null)
|
||||||
ComponentRef = null;
|
{
|
||||||
TextureRef = null;
|
UnityWidget.OnReturnToPool();
|
||||||
CleanupTextureViewer();
|
Pool.Return(UnityWidget.GetType(), UnityWidget);
|
||||||
|
this.UnityWidget = null;
|
||||||
|
}
|
||||||
|
|
||||||
base.OnReturnToPool();
|
base.OnReturnToPool();
|
||||||
}
|
}
|
||||||
@ -130,7 +149,7 @@ namespace UnityExplorer.Inspectors
|
|||||||
currentBaseTabText = $"{prefix} {SignatureHighlighter.Parse(TargetType, false)}";
|
currentBaseTabText = $"{prefix} {SignatureHighlighter.Parse(TargetType, false)}";
|
||||||
Tab.TabText.text = currentBaseTabText;
|
Tab.TabText.text = currentBaseTabText;
|
||||||
NameText.text = SignatureHighlighter.Parse(TargetType, true);
|
NameText.text = SignatureHighlighter.Parse(TargetType, true);
|
||||||
HiddenNameText.Text = TargetType.FullName;
|
HiddenNameText.Text = SignatureHighlighter.RemoveHighlighting(NameText.text);
|
||||||
|
|
||||||
string asmText;
|
string asmText;
|
||||||
if (TargetType.Assembly is AssemblyBuilder || string.IsNullOrEmpty(TargetType.Assembly.Location))
|
if (TargetType.Assembly is AssemblyBuilder || string.IsNullOrEmpty(TargetType.Assembly.Location))
|
||||||
@ -139,18 +158,20 @@ namespace UnityExplorer.Inspectors
|
|||||||
asmText = Path.GetFileName(TargetType.Assembly.Location);
|
asmText = Path.GetFileName(TargetType.Assembly.Location);
|
||||||
AssemblyText.text = $"<color=grey>Assembly:</color> {asmText}";
|
AssemblyText.text = $"<color=grey>Assembly:</color> {asmText}";
|
||||||
|
|
||||||
// unity helpers
|
// Unity object helper widget
|
||||||
SetUnityTargets();
|
|
||||||
|
if (!StaticOnly)
|
||||||
|
this.UnityWidget = UnityObjectWidget.GetUnityWidget(target, TargetType, this);
|
||||||
|
|
||||||
// Get cache members
|
// Get cache members
|
||||||
|
|
||||||
this.members = CacheMember.GetCacheMembers(Target, TargetType, this);
|
this.members = CacheMemberFactory.GetCacheMembers(TargetType, this);
|
||||||
|
|
||||||
// reset filters
|
// reset filters
|
||||||
|
|
||||||
this.filterInputField.Text = "";
|
this.filterInputField.Text = string.Empty;
|
||||||
|
|
||||||
SetFilter("", StaticOnly ? BindingFlags.Static : BindingFlags.Instance);
|
SetFilter(string.Empty, StaticOnly ? BindingFlags.Static : BindingFlags.Default);
|
||||||
scopeFilterButtons[BindingFlags.Default].Component.gameObject.SetActive(!StaticOnly);
|
scopeFilterButtons[BindingFlags.Default].Component.gameObject.SetActive(!StaticOnly);
|
||||||
scopeFilterButtons[BindingFlags.Instance].Component.gameObject.SetActive(!StaticOnly);
|
scopeFilterButtons[BindingFlags.Instance].Component.gameObject.SetActive(!StaticOnly);
|
||||||
|
|
||||||
@ -162,12 +183,6 @@ namespace UnityExplorer.Inspectors
|
|||||||
|
|
||||||
// Updating
|
// Updating
|
||||||
|
|
||||||
private bool refreshWanted;
|
|
||||||
private string lastNameFilter;
|
|
||||||
private BindingFlags lastFlagsFilter;
|
|
||||||
private MemberFlags lastMemberFilter = MemberFlags.All;
|
|
||||||
private float timeOfLastAutoUpdate;
|
|
||||||
|
|
||||||
public override void Update()
|
public override void Update()
|
||||||
{
|
{
|
||||||
if (!this.IsActive)
|
if (!this.IsActive)
|
||||||
@ -180,10 +195,10 @@ namespace UnityExplorer.Inspectors
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check filter changes or force-refresh
|
// check filter changes or force-refresh
|
||||||
if (refreshWanted || NameFilter != lastNameFilter || FlagsFilter != lastFlagsFilter || lastMemberFilter != MemberFilter)
|
if (refreshWanted || nameFilter != lastNameFilter || scopeFlagsFilter != lastFlagsFilter || lastMemberFilter != MemberFilter)
|
||||||
{
|
{
|
||||||
lastNameFilter = NameFilter;
|
lastNameFilter = nameFilter;
|
||||||
lastFlagsFilter = FlagsFilter;
|
lastFlagsFilter = scopeFlagsFilter;
|
||||||
lastMemberFilter = MemberFilter;
|
lastMemberFilter = MemberFilter;
|
||||||
|
|
||||||
FilterMembers();
|
FilterMembers();
|
||||||
@ -196,11 +211,8 @@ namespace UnityExplorer.Inspectors
|
|||||||
{
|
{
|
||||||
timeOfLastAutoUpdate = Time.realtimeSinceStartup;
|
timeOfLastAutoUpdate = Time.realtimeSinceStartup;
|
||||||
|
|
||||||
if (this.UnityObjectRef)
|
if (this.UnityWidget != null)
|
||||||
{
|
UnityWidget.Update();
|
||||||
nameInput.Text = UnityObjectRef.name;
|
|
||||||
this.Tab.TabText.text = $"{currentBaseTabText} \"{UnityObjectRef.name}\"";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (AutoUpdateWanted)
|
if (AutoUpdateWanted)
|
||||||
UpdateDisplayedMembers();
|
UpdateDisplayedMembers();
|
||||||
@ -214,26 +226,26 @@ namespace UnityExplorer.Inspectors
|
|||||||
|
|
||||||
// Filtering
|
// Filtering
|
||||||
|
|
||||||
public void SetFilter(string filter) => SetFilter(filter, FlagsFilter);
|
public void SetFilter(string name) => SetFilter(name, scopeFlagsFilter);
|
||||||
|
|
||||||
public void SetFilter(BindingFlags flagsFilter) => SetFilter(NameFilter, flagsFilter);
|
public void SetFilter(BindingFlags flags) => SetFilter(nameFilter, flags);
|
||||||
|
|
||||||
public void SetFilter(string nameFilter, BindingFlags flagsFilter)
|
public void SetFilter(string name, BindingFlags flags)
|
||||||
{
|
{
|
||||||
this.NameFilter = nameFilter;
|
this.nameFilter = name;
|
||||||
|
|
||||||
if (flagsFilter != FlagsFilter)
|
if (flags != scopeFlagsFilter)
|
||||||
{
|
{
|
||||||
var btn = scopeFilterButtons[FlagsFilter].Component;
|
var btn = scopeFilterButtons[scopeFlagsFilter].Component;
|
||||||
RuntimeProvider.Instance.SetColorBlock(btn, disabledButtonColor, disabledButtonColor * 1.3f);
|
RuntimeHelper.SetColorBlock(btn, disabledButtonColor, disabledButtonColor * 1.3f);
|
||||||
|
|
||||||
this.FlagsFilter = flagsFilter;
|
this.scopeFlagsFilter = flags;
|
||||||
btn = scopeFilterButtons[FlagsFilter].Component;
|
btn = scopeFilterButtons[scopeFlagsFilter].Component;
|
||||||
RuntimeProvider.Instance.SetColorBlock(btn, enabledButtonColor, enabledButtonColor * 1.3f);
|
RuntimeHelper.SetColorBlock(btn, enabledButtonColor, enabledButtonColor * 1.3f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnMemberTypeToggled(MemberFlags flag, bool val)
|
private void OnMemberTypeToggled(MemberFilter flag, bool val)
|
||||||
{
|
{
|
||||||
if (!val)
|
if (!val)
|
||||||
MemberFilter &= ~flag;
|
MemberFilter &= ~flag;
|
||||||
@ -249,19 +261,20 @@ namespace UnityExplorer.Inspectors
|
|||||||
{
|
{
|
||||||
var member = members[i];
|
var member = members[i];
|
||||||
|
|
||||||
if (FlagsFilter != BindingFlags.Default)
|
if (scopeFlagsFilter != BindingFlags.Default)
|
||||||
{
|
{
|
||||||
if (FlagsFilter == BindingFlags.Instance && member.IsStatic
|
if (scopeFlagsFilter == BindingFlags.Instance && member.IsStatic
|
||||||
|| FlagsFilter == BindingFlags.Static && !member.IsStatic)
|
|| scopeFlagsFilter == BindingFlags.Static && !member.IsStatic)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((member is CacheMethod && !MemberFilter.HasFlag(MemberFlags.Method))
|
if ((member is CacheMethod && !MemberFilter.HasFlag(MemberFilter.Method))
|
||||||
|| (member is CacheField && !MemberFilter.HasFlag(MemberFlags.Field))
|
|| (member is CacheField && !MemberFilter.HasFlag(MemberFilter.Field))
|
||||||
|| (member is CacheProperty && !MemberFilter.HasFlag(MemberFlags.Property)))
|
|| (member is CacheProperty && !MemberFilter.HasFlag(MemberFilter.Property))
|
||||||
|
|| (member is CacheConstructor && !MemberFilter.HasFlag(MemberFilter.Constructor)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(NameFilter) && !member.NameForFiltering.ContainsIgnoreCase(NameFilter))
|
if (!string.IsNullOrEmpty(nameFilter) && !member.NameForFiltering.ContainsIgnoreCase(nameFilter))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
filteredMembers.Add(member);
|
filteredMembers.Add(member);
|
||||||
@ -290,8 +303,6 @@ namespace UnityExplorer.Inspectors
|
|||||||
|
|
||||||
// Member cells
|
// Member cells
|
||||||
|
|
||||||
public int ItemCount => filteredMembers.Count;
|
|
||||||
|
|
||||||
public void OnCellBorrowed(CacheMemberCell cell) { } // not needed
|
public void OnCellBorrowed(CacheMemberCell cell) { } // not needed
|
||||||
|
|
||||||
public void SetCell(CacheMemberCell cell, int index)
|
public void SetCell(CacheMemberCell cell, int index)
|
||||||
@ -301,9 +312,6 @@ namespace UnityExplorer.Inspectors
|
|||||||
|
|
||||||
// Cell layout (fake table alignment)
|
// Cell layout (fake table alignment)
|
||||||
|
|
||||||
private static int LeftGroupWidth { get; set; }
|
|
||||||
private static int RightGroupWidth { get; set; }
|
|
||||||
|
|
||||||
internal void SetLayouts()
|
internal void SetLayouts()
|
||||||
{
|
{
|
||||||
CalculateLayouts();
|
CalculateLayouts();
|
||||||
@ -327,9 +335,12 @@ namespace UnityExplorer.Inspectors
|
|||||||
cell.Occupant.IValue.SetLayout();
|
cell.Occupant.IValue.SetLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
// UI Construction
|
private void OnCopyClicked()
|
||||||
|
{
|
||||||
|
ClipboardPanel.Copy(this.Target ?? this.TargetType);
|
||||||
|
}
|
||||||
|
|
||||||
private GameObject mainContentHolder;
|
// UI Construction
|
||||||
|
|
||||||
public override GameObject CreateContent(GameObject parent)
|
public override GameObject CreateContent(GameObject parent)
|
||||||
{
|
{
|
||||||
@ -338,7 +349,10 @@ namespace UnityExplorer.Inspectors
|
|||||||
|
|
||||||
// Class name, assembly
|
// Class name, assembly
|
||||||
|
|
||||||
var titleHolder = UIFactory.CreateUIObject("TitleHolder", UIRoot);
|
var topRow = UIFactory.CreateHorizontalGroup(UIRoot, "TopRow", false, false, true, true, 4, default, new(1, 1, 1, 0), TextAnchor.MiddleLeft);
|
||||||
|
UIFactory.SetLayoutElement(topRow, minHeight: 25, flexibleWidth: 9999);
|
||||||
|
|
||||||
|
var titleHolder = UIFactory.CreateUIObject("TitleHolder", topRow);
|
||||||
UIFactory.SetLayoutElement(titleHolder, minHeight: 35, flexibleHeight: 0, flexibleWidth: 9999);
|
UIFactory.SetLayoutElement(titleHolder, minHeight: 35, flexibleHeight: 0, flexibleWidth: 9999);
|
||||||
|
|
||||||
NameText = UIFactory.CreateLabel(titleHolder, "VisibleTitle", "NotSet", TextAnchor.MiddleLeft);
|
NameText = UIFactory.CreateLabel(titleHolder, "VisibleTitle", "NotSet", TextAnchor.MiddleLeft);
|
||||||
@ -360,11 +374,14 @@ namespace UnityExplorer.Inspectors
|
|||||||
HiddenNameText.Component.textComponent.color = Color.clear;
|
HiddenNameText.Component.textComponent.color = Color.clear;
|
||||||
UIFactory.SetLayoutElement(HiddenNameText.Component.gameObject, minHeight: 35, flexibleHeight: 0, flexibleWidth: 9999);
|
UIFactory.SetLayoutElement(HiddenNameText.Component.gameObject, minHeight: 35, flexibleHeight: 0, flexibleWidth: 9999);
|
||||||
|
|
||||||
|
var copyButton = UIFactory.CreateButton(topRow, "CopyButton", "Copy to Clipboard", new Color(0.2f, 0.2f, 0.2f, 1));
|
||||||
|
copyButton.ButtonText.color = Color.yellow;
|
||||||
|
UIFactory.SetLayoutElement(copyButton.Component.gameObject, minHeight: 25, minWidth: 120, flexibleWidth: 0);
|
||||||
|
copyButton.OnClick += OnCopyClicked;
|
||||||
|
|
||||||
AssemblyText = UIFactory.CreateLabel(UIRoot, "AssemblyLabel", "not set", TextAnchor.MiddleLeft);
|
AssemblyText = UIFactory.CreateLabel(UIRoot, "AssemblyLabel", "not set", TextAnchor.MiddleLeft);
|
||||||
UIFactory.SetLayoutElement(AssemblyText.gameObject, minHeight: 25, flexibleWidth: 9999);
|
UIFactory.SetLayoutElement(AssemblyText.gameObject, minHeight: 25, flexibleWidth: 9999);
|
||||||
|
|
||||||
ConstructUnityObjectRow();
|
|
||||||
|
|
||||||
mainContentHolder = UIFactory.CreateVerticalGroup(UIRoot, "MemberHolder", false, false, true, true, 5, new Vector4(2, 2, 2, 2),
|
mainContentHolder = UIFactory.CreateVerticalGroup(UIRoot, "MemberHolder", false, false, true, true, 5, new Vector4(2, 2, 2, 2),
|
||||||
new Color(0.12f, 0.12f, 0.12f));
|
new Color(0.12f, 0.12f, 0.12f));
|
||||||
UIFactory.SetLayoutElement(mainContentHolder, flexibleWidth: 9999, flexibleHeight: 9999);
|
UIFactory.SetLayoutElement(mainContentHolder, flexibleWidth: 9999, flexibleHeight: 9999);
|
||||||
@ -446,6 +463,7 @@ namespace UnityExplorer.Inspectors
|
|||||||
AddMemberTypeToggle(rowObj, MemberTypes.Property, 90);
|
AddMemberTypeToggle(rowObj, MemberTypes.Property, 90);
|
||||||
AddMemberTypeToggle(rowObj, MemberTypes.Field, 70);
|
AddMemberTypeToggle(rowObj, MemberTypes.Field, 70);
|
||||||
AddMemberTypeToggle(rowObj, MemberTypes.Method, 90);
|
AddMemberTypeToggle(rowObj, MemberTypes.Method, 90);
|
||||||
|
AddMemberTypeToggle(rowObj, MemberTypes.Constructor, 110);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddScopeFilterButton(GameObject parent, BindingFlags flags, bool setAsActive = false)
|
private void AddScopeFilterButton(GameObject parent, BindingFlags flags, bool setAsActive = false)
|
||||||
@ -464,255 +482,30 @@ namespace UnityExplorer.Inspectors
|
|||||||
{
|
{
|
||||||
var toggleObj = UIFactory.CreateToggle(parent, "Toggle_" + type, out Toggle toggle, out Text toggleText);
|
var toggleObj = UIFactory.CreateToggle(parent, "Toggle_" + type, out Toggle toggle, out Text toggleText);
|
||||||
UIFactory.SetLayoutElement(toggleObj, minHeight: 25, minWidth: width);
|
UIFactory.SetLayoutElement(toggleObj, minHeight: 25, minWidth: width);
|
||||||
var color = SignatureHighlighter.GetMemberInfoColor(type);
|
string color = type switch
|
||||||
|
{
|
||||||
|
MemberTypes.Method => SignatureHighlighter.METHOD_INSTANCE,
|
||||||
|
MemberTypes.Field => SignatureHighlighter.FIELD_INSTANCE,
|
||||||
|
MemberTypes.Property => SignatureHighlighter.PROP_INSTANCE,
|
||||||
|
MemberTypes.Constructor => SignatureHighlighter.CLASS_INSTANCE,
|
||||||
|
_ => throw new NotImplementedException()
|
||||||
|
};
|
||||||
toggleText.text = $"<color={color}>{type}</color>";
|
toggleText.text = $"<color={color}>{type}</color>";
|
||||||
|
|
||||||
toggle.graphic.TryCast<Image>().color = color.ToColor() * 0.65f;
|
toggle.graphic.TryCast<Image>().color = color.ToColor() * 0.65f;
|
||||||
|
|
||||||
MemberFlags flag;
|
MemberFilter flag = type switch
|
||||||
switch (type)
|
|
||||||
{
|
{
|
||||||
case MemberTypes.Method: flag = MemberFlags.Method; break;
|
MemberTypes.Method => MemberFilter.Method,
|
||||||
case MemberTypes.Property: flag = MemberFlags.Property; break;
|
MemberTypes.Property => MemberFilter.Property,
|
||||||
case MemberTypes.Field: flag = MemberFlags.Field; break;
|
MemberTypes.Field => MemberFilter.Field,
|
||||||
default: return;
|
MemberTypes.Constructor => MemberFilter.Constructor,
|
||||||
}
|
_ => throw new NotImplementedException()
|
||||||
|
};
|
||||||
|
|
||||||
toggle.onValueChanged.AddListener((bool val) => { OnMemberTypeToggled(flag, val); });
|
toggle.onValueChanged.AddListener((bool val) => { OnMemberTypeToggled(flag, val); });
|
||||||
|
|
||||||
memberTypeToggles.Add(toggle);
|
memberTypeToggles.Add(toggle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Todo should probably put this in a separate class or maybe as a widget
|
|
||||||
|
|
||||||
#region UNITY OBJECT SPECIFIC
|
|
||||||
|
|
||||||
// Unity object helpers
|
|
||||||
|
|
||||||
private UnityEngine.Object UnityObjectRef;
|
|
||||||
private Component ComponentRef;
|
|
||||||
private Texture2D TextureRef;
|
|
||||||
private bool TextureViewerWanted;
|
|
||||||
private GameObject unityObjectRow;
|
|
||||||
private ButtonRef gameObjectButton;
|
|
||||||
private InputFieldRef nameInput;
|
|
||||||
private InputFieldRef instanceIdInput;
|
|
||||||
private ButtonRef textureButton;
|
|
||||||
private GameObject textureViewer;
|
|
||||||
|
|
||||||
private void SetUnityTargets()
|
|
||||||
{
|
|
||||||
if (StaticOnly || !typeof(UnityEngine.Object).IsAssignableFrom(TargetType))
|
|
||||||
{
|
|
||||||
unityObjectRow.SetActive(false);
|
|
||||||
textureViewer.SetActive(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
UnityObjectRef = (UnityEngine.Object)Target.TryCast(typeof(UnityEngine.Object));
|
|
||||||
unityObjectRow.SetActive(true);
|
|
||||||
|
|
||||||
nameInput.Text = UnityObjectRef.name;
|
|
||||||
instanceIdInput.Text = UnityObjectRef.GetInstanceID().ToString();
|
|
||||||
|
|
||||||
if (typeof(Component).IsAssignableFrom(TargetType))
|
|
||||||
{
|
|
||||||
ComponentRef = (Component)Target.TryCast(typeof(Component));
|
|
||||||
gameObjectButton.Component.gameObject.SetActive(true);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
gameObjectButton.Component.gameObject.SetActive(false);
|
|
||||||
|
|
||||||
if (typeof(Texture2D).IsAssignableFrom(TargetType))
|
|
||||||
{
|
|
||||||
TextureRef = (Texture2D)Target.TryCast(typeof(Texture2D));
|
|
||||||
textureButton.Component.gameObject.SetActive(true);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
textureButton.Component.gameObject.SetActive(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnGameObjectButtonClicked()
|
|
||||||
{
|
|
||||||
if (!ComponentRef)
|
|
||||||
{
|
|
||||||
ExplorerCore.LogWarning("Component reference is null or destroyed!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
InspectorManager.Inspect(ComponentRef.gameObject);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ToggleTextureViewer()
|
|
||||||
{
|
|
||||||
if (TextureViewerWanted)
|
|
||||||
{
|
|
||||||
// disable
|
|
||||||
TextureViewerWanted = false;
|
|
||||||
textureViewer.SetActive(false);
|
|
||||||
mainContentHolder.SetActive(true);
|
|
||||||
textureButton.ButtonText.text = "View Texture";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!textureImage.sprite)
|
|
||||||
{
|
|
||||||
// First show, need to create sprite for displaying texture
|
|
||||||
SetTextureViewer();
|
|
||||||
}
|
|
||||||
|
|
||||||
// enable
|
|
||||||
TextureViewerWanted = true;
|
|
||||||
textureViewer.SetActive(true);
|
|
||||||
mainContentHolder.gameObject.SetActive(false);
|
|
||||||
textureButton.ButtonText.text = "Hide Texture";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// UI construction
|
|
||||||
|
|
||||||
private void ConstructUnityObjectRow()
|
|
||||||
{
|
|
||||||
unityObjectRow = UIFactory.CreateUIObject("UnityObjectRow", UIRoot);
|
|
||||||
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(unityObjectRow, false, false, true, true, 5);
|
|
||||||
UIFactory.SetLayoutElement(unityObjectRow, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999);
|
|
||||||
|
|
||||||
textureButton = UIFactory.CreateButton(unityObjectRow, "TextureButton", "View Texture", new Color(0.2f, 0.2f, 0.2f));
|
|
||||||
UIFactory.SetLayoutElement(textureButton.Component.gameObject, minHeight: 25, minWidth: 150);
|
|
||||||
textureButton.OnClick += ToggleTextureViewer;
|
|
||||||
|
|
||||||
var nameLabel = UIFactory.CreateLabel(unityObjectRow, "NameLabel", "Name:", TextAnchor.MiddleLeft, Color.grey);
|
|
||||||
UIFactory.SetLayoutElement(nameLabel.gameObject, minHeight: 25, minWidth: 45, flexibleWidth: 0);
|
|
||||||
|
|
||||||
nameInput = UIFactory.CreateInputField(unityObjectRow, "NameInput", "untitled");
|
|
||||||
UIFactory.SetLayoutElement(nameInput.UIRoot, minHeight: 25, minWidth: 100, flexibleWidth: 1000);
|
|
||||||
nameInput.Component.readOnly = true;
|
|
||||||
|
|
||||||
gameObjectButton = UIFactory.CreateButton(unityObjectRow, "GameObjectButton", "Inspect GameObject", new Color(0.2f, 0.2f, 0.2f));
|
|
||||||
UIFactory.SetLayoutElement(gameObjectButton.Component.gameObject, minHeight: 25, minWidth: 160);
|
|
||||||
gameObjectButton.OnClick += OnGameObjectButtonClicked;
|
|
||||||
|
|
||||||
var instanceLabel = UIFactory.CreateLabel(unityObjectRow, "InstanceLabel", "Instance ID:", TextAnchor.MiddleRight, Color.grey);
|
|
||||||
UIFactory.SetLayoutElement(instanceLabel.gameObject, minHeight: 25, minWidth: 100, flexibleWidth: 0);
|
|
||||||
|
|
||||||
instanceIdInput = UIFactory.CreateInputField(unityObjectRow, "InstanceIDInput", "ERROR");
|
|
||||||
UIFactory.SetLayoutElement(instanceIdInput.UIRoot, minHeight: 25, minWidth: 100, flexibleWidth: 0);
|
|
||||||
instanceIdInput.Component.readOnly = true;
|
|
||||||
|
|
||||||
unityObjectRow.SetActive(false);
|
|
||||||
|
|
||||||
ConstructTextureHelper();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Texture viewer helper
|
|
||||||
|
|
||||||
private InputFieldRef textureSavePathInput;
|
|
||||||
private Image textureImage;
|
|
||||||
private LayoutElement textureImageLayout;
|
|
||||||
|
|
||||||
private void CleanupTextureViewer()
|
|
||||||
{
|
|
||||||
if (textureImage.sprite)
|
|
||||||
GameObject.Destroy(textureImage.sprite);
|
|
||||||
|
|
||||||
if (TextureViewerWanted)
|
|
||||||
ToggleTextureViewer();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ConstructTextureHelper()
|
|
||||||
{
|
|
||||||
textureViewer = UIFactory.CreateVerticalGroup(UIRoot, "TextureViewer", false, false, true, true, 2, new Vector4(5, 5, 5, 5),
|
|
||||||
new Color(0.1f, 0.1f, 0.1f));
|
|
||||||
UIFactory.SetLayoutElement(textureViewer, flexibleWidth: 9999, flexibleHeight: 9999);
|
|
||||||
|
|
||||||
// Save helper
|
|
||||||
|
|
||||||
var saveRowObj = UIFactory.CreateHorizontalGroup(textureViewer, "SaveRow", false, false, true, true, 2, new Vector4(2, 2, 2, 2),
|
|
||||||
new Color(0.1f, 0.1f, 0.1f));
|
|
||||||
|
|
||||||
var saveBtn = UIFactory.CreateButton(saveRowObj, "SaveButton", "Save .PNG", new Color(0.2f, 0.25f, 0.2f));
|
|
||||||
UIFactory.SetLayoutElement(saveBtn.Component.gameObject, minHeight: 25, minWidth: 100, flexibleWidth: 0);
|
|
||||||
saveBtn.OnClick += OnSaveTextureClicked;
|
|
||||||
|
|
||||||
textureSavePathInput = UIFactory.CreateInputField(saveRowObj, "SaveInput", "...");
|
|
||||||
UIFactory.SetLayoutElement(textureSavePathInput.UIRoot, minHeight: 25, minWidth: 100, flexibleWidth: 9999);
|
|
||||||
|
|
||||||
// Actual texture viewer
|
|
||||||
|
|
||||||
var imageViewport = UIFactory.CreateVerticalGroup(textureViewer, "Viewport", false, false, true, true);
|
|
||||||
imageViewport.GetComponent<Image>().color = Color.white;
|
|
||||||
imageViewport.AddComponent<Mask>().showMaskGraphic = false;
|
|
||||||
|
|
||||||
var imageObj = UIFactory.CreateUIObject("Image", imageViewport);
|
|
||||||
var fitter = imageObj.AddComponent<ContentSizeFitter>();
|
|
||||||
fitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
|
||||||
textureImage = imageObj.AddComponent<Image>();
|
|
||||||
textureImageLayout = UIFactory.SetLayoutElement(imageObj, flexibleWidth: 1, flexibleHeight: 1);
|
|
||||||
|
|
||||||
textureViewer.SetActive(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SetTextureViewer()
|
|
||||||
{
|
|
||||||
if (!this.TextureRef)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var name = TextureRef.name;
|
|
||||||
if (string.IsNullOrEmpty(name))
|
|
||||||
name = "untitled";
|
|
||||||
|
|
||||||
textureSavePathInput.Text = Path.Combine(ConfigManager.Default_Output_Path.Value, $"{name}.png");
|
|
||||||
|
|
||||||
var sprite = TextureUtilProvider.Instance.CreateSprite(TextureRef);
|
|
||||||
textureImage.sprite = sprite;
|
|
||||||
|
|
||||||
textureImageLayout.preferredHeight = sprite.rect.height;
|
|
||||||
// not really working, its always stretched horizontally for some reason.
|
|
||||||
textureImageLayout.preferredWidth = sprite.rect.width;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnSaveTextureClicked()
|
|
||||||
{
|
|
||||||
if (!TextureRef)
|
|
||||||
{
|
|
||||||
ExplorerCore.LogWarning("Ref Texture is null, maybe it was destroyed?");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(textureSavePathInput.Text))
|
|
||||||
{
|
|
||||||
ExplorerCore.LogWarning("Save path cannot be empty!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var path = textureSavePathInput.Text;
|
|
||||||
if (!path.EndsWith(".png", StringComparison.InvariantCultureIgnoreCase))
|
|
||||||
{
|
|
||||||
ExplorerCore.LogWarning("Desired save path must end with '.png'!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
path = IOUtility.EnsureValidFilePath(path);
|
|
||||||
|
|
||||||
if (File.Exists(path))
|
|
||||||
File.Delete(path);
|
|
||||||
|
|
||||||
var tex = TextureRef;
|
|
||||||
|
|
||||||
if (!TextureUtilProvider.IsReadable(tex))
|
|
||||||
tex = TextureUtilProvider.ForceReadTexture(tex);
|
|
||||||
|
|
||||||
byte[] data = TextureUtilProvider.Instance.EncodeToPNG(tex);
|
|
||||||
File.WriteAllBytes(path, data);
|
|
||||||
|
|
||||||
if (tex != TextureRef)
|
|
||||||
{
|
|
||||||
// cleanup temp texture if we had to force-read it.
|
|
||||||
GameObject.Destroy(tex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityExplorer.Core.Config;
|
using UnityExplorer.Config;
|
||||||
|
|
||||||
namespace UnityExplorer.Loader.BIE
|
namespace UnityExplorer.Loader.BIE
|
||||||
{
|
{
|
||||||
|
@ -9,8 +9,7 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.EventSystems;
|
using UnityEngine.EventSystems;
|
||||||
using UnityExplorer.Core;
|
using UnityExplorer.Config;
|
||||||
using UnityExplorer.Core.Config;
|
|
||||||
using UniverseLib.Input;
|
using UniverseLib.Input;
|
||||||
using UnityExplorer.Loader.BIE;
|
using UnityExplorer.Loader.BIE;
|
||||||
#if CPP
|
#if CPP
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityExplorer.Core.Config;
|
using UnityExplorer.Config;
|
||||||
|
|
||||||
namespace UnityExplorer
|
namespace UnityExplorer
|
||||||
{
|
{
|
||||||
|
@ -3,10 +3,15 @@ using System;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using MelonLoader;
|
using MelonLoader;
|
||||||
using UnityExplorer;
|
using UnityExplorer;
|
||||||
using UnityExplorer.Core.Config;
|
using UnityExplorer.Config;
|
||||||
using UnityExplorer.Loader.ML;
|
using UnityExplorer.Loader.ML;
|
||||||
|
|
||||||
[assembly: MelonPlatformDomain(MelonPlatformDomainAttribute.CompatibleDomains.UNIVERSAL)]
|
#if CPP
|
||||||
|
[assembly: MelonPlatformDomain(MelonPlatformDomainAttribute.CompatibleDomains.IL2CPP)]
|
||||||
|
#else
|
||||||
|
[assembly: MelonPlatformDomain(MelonPlatformDomainAttribute.CompatibleDomains.MONO)]
|
||||||
|
#endif
|
||||||
|
|
||||||
[assembly: MelonInfo(typeof(ExplorerMelonMod), ExplorerCore.NAME, ExplorerCore.VERSION, ExplorerCore.AUTHOR)]
|
[assembly: MelonInfo(typeof(ExplorerMelonMod), ExplorerCore.NAME, ExplorerCore.VERSION, ExplorerCore.AUTHOR)]
|
||||||
[assembly: MelonGame(null, null)]
|
[assembly: MelonGame(null, null)]
|
||||||
[assembly: MelonColor(ConsoleColor.DarkCyan)]
|
[assembly: MelonColor(ConsoleColor.DarkCyan)]
|
||||||
@ -26,9 +31,9 @@ namespace UnityExplorer
|
|||||||
public ConfigHandler ConfigHandler => _configHandler;
|
public ConfigHandler ConfigHandler => _configHandler;
|
||||||
public MelonLoaderConfigHandler _configHandler;
|
public MelonLoaderConfigHandler _configHandler;
|
||||||
|
|
||||||
public Action<object> OnLogMessage => MelonLogger.Msg;
|
public Action<object> OnLogMessage => LoggerInstance.Msg;
|
||||||
public Action<object> OnLogWarning => MelonLogger.Warning;
|
public Action<object> OnLogWarning => LoggerInstance.Warning;
|
||||||
public Action<object> OnLogError => MelonLogger.Error;
|
public Action<object> OnLogError => LoggerInstance.Error;
|
||||||
|
|
||||||
public override void OnApplicationStart()
|
public override void OnApplicationStart()
|
||||||
{
|
{
|
||||||
|
@ -5,8 +5,7 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityExplorer.Core;
|
using UnityExplorer.Config;
|
||||||
using UnityExplorer.Core.Config;
|
|
||||||
|
|
||||||
namespace UnityExplorer.Loader.ML
|
namespace UnityExplorer.Loader.ML
|
||||||
{
|
{
|
||||||
|
33
src/Loader/Standalone/Editor/ExplorerEditorBehaviour.cs
Normal file
33
src/Loader/Standalone/Editor/ExplorerEditorBehaviour.cs
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#if STANDALONE
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace UnityExplorer.Loader.Standalone
|
||||||
|
{
|
||||||
|
public class ExplorerEditorBehaviour : MonoBehaviour
|
||||||
|
{
|
||||||
|
internal void Awake()
|
||||||
|
{
|
||||||
|
ExplorerEditorLoader.Initialize();
|
||||||
|
DontDestroyOnLoad(this);
|
||||||
|
this.gameObject.hideFlags = HideFlags.HideAndDontSave;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void OnDestroy()
|
||||||
|
{
|
||||||
|
OnApplicationQuit();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void OnApplicationQuit()
|
||||||
|
{
|
||||||
|
if (UI.UIManager.UIRoot)
|
||||||
|
Destroy(UI.UIManager.UIRoot.transform.root.gameObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
41
src/Loader/Standalone/Editor/ExplorerEditorLoader.cs
Normal file
41
src/Loader/Standalone/Editor/ExplorerEditorLoader.cs
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
#if STANDALONE
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace UnityExplorer.Loader.Standalone
|
||||||
|
{
|
||||||
|
public class ExplorerEditorLoader : ExplorerStandalone
|
||||||
|
{
|
||||||
|
public static void Initialize()
|
||||||
|
{
|
||||||
|
Instance = new ExplorerEditorLoader();
|
||||||
|
OnLog += LogHandler;
|
||||||
|
Instance.configHandler = new StandaloneConfigHandler();
|
||||||
|
|
||||||
|
ExplorerCore.Init(Instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void LogHandler(string message, LogType logType)
|
||||||
|
{
|
||||||
|
switch (logType)
|
||||||
|
{
|
||||||
|
case LogType.Assert: Debug.LogError(message); break;
|
||||||
|
case LogType.Error: Debug.LogError(message); break;
|
||||||
|
case LogType.Exception: Debug.LogError(message); break;
|
||||||
|
case LogType.Log: Debug.Log(message); break;
|
||||||
|
case LogType.Warning: Debug.LogWarning(message); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void CheckExplorerFolder()
|
||||||
|
{
|
||||||
|
if (explorerFolder == null)
|
||||||
|
explorerFolder = Path.Combine(Application.dataPath, "UnityExplorer~");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
@ -4,11 +4,10 @@ using System;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityExplorer.Core.Config;
|
using UnityExplorer.Config;
|
||||||
using UnityExplorer.Loader.STANDALONE;
|
|
||||||
using UnityEngine.EventSystems;
|
using UnityEngine.EventSystems;
|
||||||
using UniverseLib.Input;
|
using UniverseLib.Input;
|
||||||
using UnityExplorer.Core;
|
using UnityExplorer.Loader.Standalone;
|
||||||
#if CPP
|
#if CPP
|
||||||
using UnhollowerRuntimeLib;
|
using UnhollowerRuntimeLib;
|
||||||
#endif
|
#endif
|
||||||
@ -17,6 +16,33 @@ namespace UnityExplorer
|
|||||||
{
|
{
|
||||||
public class ExplorerStandalone : IExplorerLoader
|
public class ExplorerStandalone : IExplorerLoader
|
||||||
{
|
{
|
||||||
|
public static ExplorerStandalone Instance { get; protected set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invoked whenever Explorer logs something. Subscribe to this to handle logging.
|
||||||
|
/// </summary>
|
||||||
|
public static event Action<string, LogType> OnLog;
|
||||||
|
|
||||||
|
public string UnhollowedModulesFolder => unhollowedPath;
|
||||||
|
private string unhollowedPath;
|
||||||
|
|
||||||
|
public ConfigHandler ConfigHandler => configHandler;
|
||||||
|
internal StandaloneConfigHandler configHandler;
|
||||||
|
|
||||||
|
public string ExplorerFolder
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
CheckExplorerFolder();
|
||||||
|
return explorerFolder;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
protected static string explorerFolder;
|
||||||
|
|
||||||
|
Action<object> IExplorerLoader.OnLogMessage => (object log) => { OnLog?.Invoke(log?.ToString() ?? "", LogType.Log); };
|
||||||
|
Action<object> IExplorerLoader.OnLogWarning => (object log) => { OnLog?.Invoke(log?.ToString() ?? "", LogType.Warning); };
|
||||||
|
Action<object> IExplorerLoader.OnLogError => (object log) => { OnLog?.Invoke(log?.ToString() ?? "", LogType.Error); };
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Call this to initialize UnityExplorer without adding a log listener or Unhollowed modules path.
|
/// Call this to initialize UnityExplorer without adding a log listener or Unhollowed modules path.
|
||||||
/// The default Unhollowed path "UnityExplorer\Modules\" will be used.
|
/// The default Unhollowed path "UnityExplorer\Modules\" will be used.
|
||||||
@ -51,60 +77,33 @@ namespace UnityExplorer
|
|||||||
OnLog += logListener;
|
OnLog += logListener;
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(unhollowedModulesPath) || !Directory.Exists(unhollowedModulesPath))
|
if (string.IsNullOrEmpty(unhollowedModulesPath) || !Directory.Exists(unhollowedModulesPath))
|
||||||
instance._unhollowedPath = Path.Combine(instance.ExplorerFolder, "Modules");
|
instance.unhollowedPath = Path.Combine(instance.ExplorerFolder, "Modules");
|
||||||
else
|
else
|
||||||
instance._unhollowedPath = unhollowedModulesPath;
|
instance.unhollowedPath = unhollowedModulesPath;
|
||||||
|
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ExplorerStandalone Instance { get; private set; }
|
internal void Init()
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Invoked whenever Explorer logs something. Subscribe to this to handle logging.
|
|
||||||
/// </summary>
|
|
||||||
public static event Action<string, LogType> OnLog;
|
|
||||||
|
|
||||||
public string UnhollowedModulesFolder => _unhollowedPath;
|
|
||||||
private string _unhollowedPath;
|
|
||||||
|
|
||||||
public ConfigHandler ConfigHandler => _configHandler;
|
|
||||||
private StandaloneConfigHandler _configHandler;
|
|
||||||
|
|
||||||
public string ExplorerFolder
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
CheckExplorerFolder();
|
|
||||||
return s_explorerFolder;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private static string s_explorerFolder;
|
|
||||||
|
|
||||||
Action<object> IExplorerLoader.OnLogMessage => (object log) => { OnLog?.Invoke(log?.ToString() ?? "", LogType.Log); };
|
|
||||||
Action<object> IExplorerLoader.OnLogWarning => (object log) => { OnLog?.Invoke(log?.ToString() ?? "", LogType.Warning); };
|
|
||||||
Action<object> IExplorerLoader.OnLogError => (object log) => { OnLog?.Invoke(log?.ToString() ?? "", LogType.Error); };
|
|
||||||
|
|
||||||
private void Init()
|
|
||||||
{
|
{
|
||||||
Instance = this;
|
Instance = this;
|
||||||
_configHandler = new StandaloneConfigHandler();
|
configHandler = new StandaloneConfigHandler();
|
||||||
|
|
||||||
ExplorerCore.Init(this);
|
ExplorerCore.Init(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CheckExplorerFolder()
|
protected virtual void CheckExplorerFolder()
|
||||||
{
|
{
|
||||||
if (s_explorerFolder == null)
|
if (explorerFolder == null)
|
||||||
{
|
{
|
||||||
s_explorerFolder =
|
explorerFolder =
|
||||||
Path.Combine(
|
Path.Combine(
|
||||||
Path.GetDirectoryName(
|
Path.GetDirectoryName(
|
||||||
Uri.UnescapeDataString(new Uri(Assembly.GetExecutingAssembly().CodeBase).AbsolutePath)),
|
Uri.UnescapeDataString(new Uri(Assembly.GetExecutingAssembly().CodeBase).AbsolutePath)),
|
||||||
"UnityExplorer");
|
"UnityExplorer");
|
||||||
|
|
||||||
if (!Directory.Exists(s_explorerFolder))
|
if (!Directory.Exists(explorerFolder))
|
||||||
Directory.CreateDirectory(s_explorerFolder);
|
Directory.CreateDirectory(explorerFolder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,23 +3,21 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityExplorer.Core.Config;
|
using UnityExplorer.Config;
|
||||||
using IniParser.Parser;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using Tomlet;
|
||||||
|
using Tomlet.Models;
|
||||||
|
|
||||||
namespace UnityExplorer.Loader.STANDALONE
|
namespace UnityExplorer.Loader.Standalone
|
||||||
{
|
{
|
||||||
public class StandaloneConfigHandler : ConfigHandler
|
public class StandaloneConfigHandler : ConfigHandler
|
||||||
{
|
{
|
||||||
internal static IniDataParser _parser;
|
|
||||||
internal static string CONFIG_PATH;
|
internal static string CONFIG_PATH;
|
||||||
|
|
||||||
public override void Init()
|
public override void Init()
|
||||||
{
|
{
|
||||||
CONFIG_PATH = Path.Combine(ExplorerCore.Loader.ExplorerFolder, "config.ini");
|
CONFIG_PATH = Path.Combine(ExplorerCore.Loader.ExplorerFolder, "config.cfg");
|
||||||
_parser = new IniDataParser();
|
|
||||||
_parser.Configuration.CommentString = "#";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void LoadConfig()
|
public override void LoadConfig()
|
||||||
@ -52,14 +50,11 @@ namespace UnityExplorer.Loader.STANDALONE
|
|||||||
if (!File.Exists(CONFIG_PATH))
|
if (!File.Exists(CONFIG_PATH))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
string ini = File.ReadAllText(CONFIG_PATH);
|
var document = TomlParser.ParseFile(CONFIG_PATH);
|
||||||
|
foreach (var key in document.Keys)
|
||||||
var data = _parser.Parse(ini);
|
|
||||||
|
|
||||||
foreach (var config in data.Sections["Config"])
|
|
||||||
{
|
{
|
||||||
if (ConfigManager.ConfigElements.TryGetValue(config.KeyName, out IConfigElement configElement))
|
var config = ConfigManager.ConfigElements[key];
|
||||||
configElement.BoxedValue = StringToConfigValue(config.Value, configElement.ElementType);
|
config.BoxedValue = StringToConfigValue(document.GetValue(key).StringValue, config.ElementType);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -78,7 +73,11 @@ namespace UnityExplorer.Loader.STANDALONE
|
|||||||
return bool.Parse(value);
|
return bool.Parse(value);
|
||||||
else if (elementType == typeof(int))
|
else if (elementType == typeof(int))
|
||||||
return int.Parse(value);
|
return int.Parse(value);
|
||||||
else
|
else if (elementType == typeof(float))
|
||||||
|
return float.Parse(value);
|
||||||
|
else if (elementType.IsEnum)
|
||||||
|
return Enum.Parse(elementType, value);
|
||||||
|
else
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,18 +88,14 @@ namespace UnityExplorer.Loader.STANDALONE
|
|||||||
|
|
||||||
public override void SaveConfig()
|
public override void SaveConfig()
|
||||||
{
|
{
|
||||||
var data = new IniParser.Model.IniData();
|
var document = TomlDocument.CreateEmpty();
|
||||||
|
foreach (var config in ConfigManager.ConfigElements)
|
||||||
data.Sections.AddSection("Config");
|
document.Put(config.Key, config.Value.BoxedValue.ToString());
|
||||||
var sec = data.Sections["Config"];
|
|
||||||
|
|
||||||
foreach (var entry in ConfigManager.ConfigElements)
|
|
||||||
sec.AddKey(entry.Key, entry.Value.BoxedValue.ToString());
|
|
||||||
|
|
||||||
if (!Directory.Exists(ExplorerCore.Loader.ExplorerFolder))
|
if (!Directory.Exists(ExplorerCore.Loader.ExplorerFolder))
|
||||||
Directory.CreateDirectory(ExplorerCore.Loader.ExplorerFolder);
|
Directory.CreateDirectory(ExplorerCore.Loader.ExplorerFolder);
|
||||||
|
|
||||||
File.WriteAllText(CONFIG_PATH, data.ToString());
|
File.WriteAllText(CONFIG_PATH, document.SerializedValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,14 +4,14 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.UI;
|
|
||||||
using UniverseLib.UI.Models;
|
using UniverseLib.UI.Models;
|
||||||
using UnityExplorer.UI.Panels;
|
using UnityExplorer.UI.Panels;
|
||||||
using UnityExplorer.UI.Widgets;
|
|
||||||
using UnityExplorer.UI.Widgets.AutoComplete;
|
using UnityExplorer.UI.Widgets.AutoComplete;
|
||||||
using UniverseLib.UI.Widgets;
|
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
|
using UniverseLib.UI.Widgets.ButtonList;
|
||||||
|
using UniverseLib.UI.Widgets.ScrollView;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.ObjectExplorer
|
namespace UnityExplorer.ObjectExplorer
|
||||||
{
|
{
|
||||||
@ -24,28 +24,25 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
Parent = parent;
|
Parent = parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
private SearchContext m_context = SearchContext.UnityObject;
|
private SearchContext context = SearchContext.UnityObject;
|
||||||
private SceneFilter m_sceneFilter = SceneFilter.Any;
|
private SceneFilter sceneFilter = SceneFilter.Any;
|
||||||
private ChildFilter m_childFilter = ChildFilter.Any;
|
private ChildFilter childFilter = ChildFilter.Any;
|
||||||
private string desiredTypeInput;
|
private string desiredTypeInput;
|
||||||
private string lastCheckedTypeInput;
|
private string lastCheckedTypeInput;
|
||||||
private bool lastTypeCanHaveGO;
|
private bool lastTypeCanHaveGameObject;
|
||||||
|
|
||||||
public ButtonListHandler<object, ButtonCell> dataHandler;
|
public ButtonListHandler<object, ButtonCell> dataHandler;
|
||||||
|
|
||||||
private ScrollPool<ButtonCell> resultsScrollPool;
|
private ScrollPool<ButtonCell> resultsScrollPool;
|
||||||
private List<object> currentResults = new List<object>();
|
private List<object> currentResults = new();
|
||||||
|
|
||||||
public TypeCompleter typeAutocompleter;
|
|
||||||
|
|
||||||
public override GameObject UIRoot => uiRoot;
|
public override GameObject UIRoot => uiRoot;
|
||||||
private GameObject uiRoot;
|
private GameObject uiRoot;
|
||||||
|
|
||||||
private GameObject sceneFilterRow;
|
private GameObject sceneFilterRow;
|
||||||
private GameObject childFilterRow;
|
private GameObject childFilterRow;
|
||||||
private GameObject unityObjectClassRow;
|
private GameObject classInputRow;
|
||||||
|
public TypeCompleter typeAutocompleter;
|
||||||
|
private GameObject nameInputRow;
|
||||||
private InputFieldRef nameInputField;
|
private InputFieldRef nameInputField;
|
||||||
|
|
||||||
private Text resultsLabel;
|
private Text resultsLabel;
|
||||||
|
|
||||||
public List<object> GetEntries() => currentResults;
|
public List<object> GetEntries() => currentResults;
|
||||||
@ -54,12 +51,12 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
{
|
{
|
||||||
cachedCellTexts.Clear();
|
cachedCellTexts.Clear();
|
||||||
|
|
||||||
if (m_context == SearchContext.Singleton)
|
if (context == SearchContext.Singleton)
|
||||||
currentResults = SearchProvider.SingletonSearch(nameInputField.Text);
|
currentResults = SearchProvider.InstanceSearch(desiredTypeInput).ToList();
|
||||||
else if (m_context == SearchContext.Class)
|
else if (context == SearchContext.Class)
|
||||||
currentResults = SearchProvider.ClassSearch(nameInputField.Text);
|
currentResults = SearchProvider.ClassSearch(desiredTypeInput);
|
||||||
else
|
else
|
||||||
currentResults = SearchProvider.UnityObjectSearch(nameInputField.Text, desiredTypeInput, m_context, m_childFilter, m_sceneFilter);
|
currentResults = SearchProvider.UnityObjectSearch(nameInputField.Text, desiredTypeInput, childFilter, sceneFilter);
|
||||||
|
|
||||||
dataHandler.RefreshData();
|
dataHandler.RefreshData();
|
||||||
resultsScrollPool.Refresh(true);
|
resultsScrollPool.Refresh(true);
|
||||||
@ -69,7 +66,7 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
|
|
||||||
public void Update()
|
public void Update()
|
||||||
{
|
{
|
||||||
if (m_context == SearchContext.UnityObject && lastCheckedTypeInput != desiredTypeInput)
|
if (context == SearchContext.UnityObject && lastCheckedTypeInput != desiredTypeInput)
|
||||||
{
|
{
|
||||||
lastCheckedTypeInput = desiredTypeInput;
|
lastCheckedTypeInput = desiredTypeInput;
|
||||||
|
|
||||||
@ -77,15 +74,15 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
if (ReflectionUtility.GetTypeByName(desiredTypeInput) is Type cachedType)
|
if (ReflectionUtility.GetTypeByName(desiredTypeInput) is Type cachedType)
|
||||||
{
|
{
|
||||||
var type = cachedType;
|
var type = cachedType;
|
||||||
lastTypeCanHaveGO = typeof(Component).IsAssignableFrom(type) || type == typeof(GameObject);
|
lastTypeCanHaveGameObject = typeof(Component).IsAssignableFrom(type) || type == typeof(GameObject);
|
||||||
sceneFilterRow.SetActive(lastTypeCanHaveGO);
|
sceneFilterRow.SetActive(lastTypeCanHaveGameObject);
|
||||||
childFilterRow.SetActive(lastTypeCanHaveGO);
|
childFilterRow.SetActive(lastTypeCanHaveGameObject);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sceneFilterRow.SetActive(false);
|
sceneFilterRow.SetActive(false);
|
||||||
childFilterRow.SetActive(false);
|
childFilterRow.SetActive(false);
|
||||||
lastTypeCanHaveGO = false;
|
lastTypeCanHaveGameObject = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -94,18 +91,27 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
|
|
||||||
private void OnContextDropdownChanged(int value)
|
private void OnContextDropdownChanged(int value)
|
||||||
{
|
{
|
||||||
m_context = (SearchContext)value;
|
context = (SearchContext)value;
|
||||||
|
|
||||||
lastCheckedTypeInput = null;
|
lastCheckedTypeInput = null;
|
||||||
sceneFilterRow.SetActive(false);
|
sceneFilterRow.SetActive(false);
|
||||||
childFilterRow.SetActive(false);
|
childFilterRow.SetActive(false);
|
||||||
|
|
||||||
unityObjectClassRow.SetActive(m_context == SearchContext.UnityObject);
|
nameInputRow.SetActive(context == SearchContext.UnityObject);
|
||||||
|
|
||||||
|
if (context == SearchContext.Class)
|
||||||
|
typeAutocompleter.AllTypes = true;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
typeAutocompleter.BaseType = context == SearchContext.UnityObject ? typeof(UnityEngine.Object) : typeof(object);
|
||||||
|
typeAutocompleter.AllTypes = false;
|
||||||
|
}
|
||||||
|
typeAutocompleter.CacheTypes();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnSceneFilterDropChanged(int value) => m_sceneFilter = (SceneFilter)value;
|
private void OnSceneFilterDropChanged(int value) => sceneFilter = (SceneFilter)value;
|
||||||
|
|
||||||
private void OnChildFilterDropChanged(int value) => m_childFilter = (ChildFilter)value;
|
private void OnChildFilterDropChanged(int value) => childFilter = (ChildFilter)value;
|
||||||
|
|
||||||
private void OnTypeInputChanged(string val)
|
private void OnTypeInputChanged(string val)
|
||||||
{
|
{
|
||||||
@ -120,14 +126,14 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Cache the syntax-highlighted text for each search result to reduce allocs.
|
// Cache the syntax-highlighted text for each search result to reduce allocs.
|
||||||
private static readonly Dictionary<int, string> cachedCellTexts = new Dictionary<int, string>();
|
private static readonly Dictionary<int, string> cachedCellTexts = new();
|
||||||
|
|
||||||
public void SetCell(ButtonCell cell, int index)
|
public void SetCell(ButtonCell cell, int index)
|
||||||
{
|
{
|
||||||
if (!cachedCellTexts.ContainsKey(index))
|
if (!cachedCellTexts.ContainsKey(index))
|
||||||
{
|
{
|
||||||
string text;
|
string text;
|
||||||
if (m_context == SearchContext.Class)
|
if (context == SearchContext.Class)
|
||||||
{
|
{
|
||||||
var type = currentResults[index] as Type;
|
var type = currentResults[index] as Type;
|
||||||
text = $"{SignatureHighlighter.Parse(type, true)} <color=grey><i>({type.Assembly.GetName().Name})</i></color>";
|
text = $"{SignatureHighlighter.Parse(type, true)} <color=grey><i>({type.Assembly.GetName().Name})</i></color>";
|
||||||
@ -143,7 +149,7 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
|
|
||||||
private void OnCellClicked(int dataIndex)
|
private void OnCellClicked(int dataIndex)
|
||||||
{
|
{
|
||||||
if (m_context == SearchContext.Class)
|
if (context == SearchContext.Class)
|
||||||
InspectorManager.Inspect(currentResults[dataIndex] as Type);
|
InspectorManager.Inspect(currentResults[dataIndex] as Type);
|
||||||
else
|
else
|
||||||
InspectorManager.Inspect(currentResults[dataIndex]);
|
InspectorManager.Inspect(currentResults[dataIndex]);
|
||||||
@ -164,20 +170,20 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
var contextLbl = UIFactory.CreateLabel(contextGroup, "SearchContextLabel", "Searching for:", TextAnchor.MiddleLeft);
|
var contextLbl = UIFactory.CreateLabel(contextGroup, "SearchContextLabel", "Searching for:", TextAnchor.MiddleLeft);
|
||||||
UIFactory.SetLayoutElement(contextLbl.gameObject, minWidth: 110, flexibleWidth: 0);
|
UIFactory.SetLayoutElement(contextLbl.gameObject, minWidth: 110, flexibleWidth: 0);
|
||||||
|
|
||||||
var contextDropObj = UIFactory.CreateDropdown(contextGroup, out Dropdown contextDrop, null, 14, OnContextDropdownChanged);
|
var contextDropObj = UIFactory.CreateDropdown(contextGroup, "ContextDropdown", out Dropdown contextDrop, null, 14, OnContextDropdownChanged);
|
||||||
foreach (var name in Enum.GetNames(typeof(SearchContext)))
|
foreach (var name in Enum.GetNames(typeof(SearchContext)))
|
||||||
contextDrop.options.Add(new Dropdown.OptionData(name));
|
contextDrop.options.Add(new Dropdown.OptionData(name));
|
||||||
UIFactory.SetLayoutElement(contextDropObj, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999);
|
UIFactory.SetLayoutElement(contextDropObj, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999);
|
||||||
|
|
||||||
// Unity class input
|
// Class input
|
||||||
|
|
||||||
unityObjectClassRow = UIFactory.CreateHorizontalGroup(uiRoot, "UnityClassRow", false, true, true, true, 2, new Vector4(2, 2, 2, 2));
|
classInputRow = UIFactory.CreateHorizontalGroup(uiRoot, "ClassRow", false, true, true, true, 2, new Vector4(2, 2, 2, 2));
|
||||||
UIFactory.SetLayoutElement(unityObjectClassRow, minHeight: 25, flexibleHeight: 0);
|
UIFactory.SetLayoutElement(classInputRow, minHeight: 25, flexibleHeight: 0);
|
||||||
|
|
||||||
var unityClassLbl = UIFactory.CreateLabel(unityObjectClassRow, "UnityClassLabel", "Class filter:", TextAnchor.MiddleLeft);
|
var unityClassLbl = UIFactory.CreateLabel(classInputRow, "ClassLabel", "Class filter:", TextAnchor.MiddleLeft);
|
||||||
UIFactory.SetLayoutElement(unityClassLbl.gameObject, minWidth: 110, flexibleWidth: 0);
|
UIFactory.SetLayoutElement(unityClassLbl.gameObject, minWidth: 110, flexibleWidth: 0);
|
||||||
|
|
||||||
var classInputField = UIFactory.CreateInputField(unityObjectClassRow, "ClassInput", "...");
|
var classInputField = UIFactory.CreateInputField(classInputRow, "ClassInput", "...");
|
||||||
UIFactory.SetLayoutElement(classInputField.UIRoot, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999);
|
UIFactory.SetLayoutElement(classInputField.UIRoot, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999);
|
||||||
|
|
||||||
typeAutocompleter = new TypeCompleter(typeof(UnityEngine.Object), classInputField);
|
typeAutocompleter = new TypeCompleter(typeof(UnityEngine.Object), classInputField);
|
||||||
@ -193,7 +199,7 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
var childLbl = UIFactory.CreateLabel(childFilterRow, "ChildLabel", "Child filter:", TextAnchor.MiddleLeft);
|
var childLbl = UIFactory.CreateLabel(childFilterRow, "ChildLabel", "Child filter:", TextAnchor.MiddleLeft);
|
||||||
UIFactory.SetLayoutElement(childLbl.gameObject, minWidth: 110, flexibleWidth: 0);
|
UIFactory.SetLayoutElement(childLbl.gameObject, minWidth: 110, flexibleWidth: 0);
|
||||||
|
|
||||||
var childDropObj = UIFactory.CreateDropdown(childFilterRow, out Dropdown childDrop, null, 14, OnChildFilterDropChanged);
|
var childDropObj = UIFactory.CreateDropdown(childFilterRow, "ChildFilterDropdown", out Dropdown childDrop, null, 14, OnChildFilterDropChanged);
|
||||||
foreach (var name in Enum.GetNames(typeof(ChildFilter)))
|
foreach (var name in Enum.GetNames(typeof(ChildFilter)))
|
||||||
childDrop.options.Add(new Dropdown.OptionData(name));
|
childDrop.options.Add(new Dropdown.OptionData(name));
|
||||||
UIFactory.SetLayoutElement(childDropObj, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999);
|
UIFactory.SetLayoutElement(childDropObj, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999);
|
||||||
@ -208,22 +214,26 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
var sceneLbl = UIFactory.CreateLabel(sceneFilterRow, "SceneLabel", "Scene filter:", TextAnchor.MiddleLeft);
|
var sceneLbl = UIFactory.CreateLabel(sceneFilterRow, "SceneLabel", "Scene filter:", TextAnchor.MiddleLeft);
|
||||||
UIFactory.SetLayoutElement(sceneLbl.gameObject, minWidth: 110, flexibleWidth: 0);
|
UIFactory.SetLayoutElement(sceneLbl.gameObject, minWidth: 110, flexibleWidth: 0);
|
||||||
|
|
||||||
var sceneDropObj = UIFactory.CreateDropdown(sceneFilterRow, out Dropdown sceneDrop, null, 14, OnSceneFilterDropChanged);
|
var sceneDropObj = UIFactory.CreateDropdown(sceneFilterRow, "SceneFilterDropdown", out Dropdown sceneDrop, null, 14, OnSceneFilterDropChanged);
|
||||||
foreach (var name in Enum.GetNames(typeof(SceneFilter)))
|
foreach (var name in Enum.GetNames(typeof(SceneFilter)))
|
||||||
|
{
|
||||||
|
if (!SceneHandler.DontDestroyExists && name == "DontDestroyOnLoad")
|
||||||
|
continue;
|
||||||
sceneDrop.options.Add(new Dropdown.OptionData(name));
|
sceneDrop.options.Add(new Dropdown.OptionData(name));
|
||||||
|
}
|
||||||
UIFactory.SetLayoutElement(sceneDropObj, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999);
|
UIFactory.SetLayoutElement(sceneDropObj, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999);
|
||||||
|
|
||||||
sceneFilterRow.SetActive(false);
|
sceneFilterRow.SetActive(false);
|
||||||
|
|
||||||
// Name filter input
|
// Name filter input
|
||||||
|
|
||||||
var nameRow = UIFactory.CreateHorizontalGroup(uiRoot, "NameRow", true, true, true, true, 2, new Vector4(2, 2, 2, 2));
|
nameInputRow = UIFactory.CreateHorizontalGroup(uiRoot, "NameRow", true, true, true, true, 2, new Vector4(2, 2, 2, 2));
|
||||||
UIFactory.SetLayoutElement(nameRow, minHeight: 25, flexibleHeight: 0);
|
UIFactory.SetLayoutElement(nameInputRow, minHeight: 25, flexibleHeight: 0);
|
||||||
|
|
||||||
var nameLbl = UIFactory.CreateLabel(nameRow, "NameFilterLabel", "Name contains:", TextAnchor.MiddleLeft);
|
var nameLbl = UIFactory.CreateLabel(nameInputRow, "NameFilterLabel", "Name contains:", TextAnchor.MiddleLeft);
|
||||||
UIFactory.SetLayoutElement(nameLbl.gameObject, minWidth: 110, flexibleWidth: 0);
|
UIFactory.SetLayoutElement(nameLbl.gameObject, minWidth: 110, flexibleWidth: 0);
|
||||||
|
|
||||||
nameInputField = UIFactory.CreateInputField(nameRow, "NameFilterInput", "...");
|
nameInputField = UIFactory.CreateInputField(nameInputRow, "NameFilterInput", "...");
|
||||||
UIFactory.SetLayoutElement(nameInputField.UIRoot, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999);
|
UIFactory.SetLayoutElement(nameInputField.UIRoot, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999);
|
||||||
|
|
||||||
// Search button
|
// Search button
|
||||||
|
@ -7,13 +7,14 @@ using System.Text;
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.SceneManagement;
|
using UnityEngine.SceneManagement;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.Core;
|
|
||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
using UniverseLib.UI.Models;
|
using UniverseLib.UI.Models;
|
||||||
using UnityExplorer.UI.Panels;
|
using UnityExplorer.UI.Panels;
|
||||||
using UnityExplorer.UI.Widgets;
|
using UnityExplorer.UI.Widgets;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
|
using System.Collections;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.ObjectExplorer
|
namespace UnityExplorer.ObjectExplorer
|
||||||
{
|
{
|
||||||
@ -26,11 +27,11 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
Parent = parent;
|
Parent = parent;
|
||||||
|
|
||||||
SceneHandler.OnInspectedSceneChanged += SceneHandler_OnInspectedSceneChanged;
|
SceneHandler.OnInspectedSceneChanged += SceneHandler_OnInspectedSceneChanged;
|
||||||
SceneHandler.OnLoadedScenesChanged += SceneHandler_OnLoadedScenesChanged;
|
SceneHandler.OnLoadedScenesUpdated += SceneHandler_OnLoadedScenesUpdated;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override GameObject UIRoot => m_uiRoot;
|
public override GameObject UIRoot => uiRoot;
|
||||||
private GameObject m_uiRoot;
|
private GameObject uiRoot;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether to automatically update per auto-update interval or not.
|
/// Whether to automatically update per auto-update interval or not.
|
||||||
@ -42,7 +43,7 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
|
|
||||||
private GameObject refreshRow;
|
private GameObject refreshRow;
|
||||||
private Dropdown sceneDropdown;
|
private Dropdown sceneDropdown;
|
||||||
private readonly Dictionary<Scene, Dropdown.OptionData> sceneToDropdownOption = new Dictionary<Scene, Dropdown.OptionData>();
|
private readonly Dictionary<Scene, Dropdown.OptionData> sceneToDropdownOption = new();
|
||||||
|
|
||||||
// scene loader
|
// scene loader
|
||||||
private Dropdown allSceneDropdown;
|
private Dropdown allSceneDropdown;
|
||||||
@ -63,7 +64,7 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
public void UpdateTree()
|
public void UpdateTree()
|
||||||
{
|
{
|
||||||
SceneHandler.Update();
|
SceneHandler.Update();
|
||||||
Tree.RefreshData(true);
|
Tree.RefreshData(true, false, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void JumpToTransform(Transform transform)
|
public void JumpToTransform(Transform transform)
|
||||||
@ -86,21 +87,21 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
Tree.JumpAndExpandToTransform(transform);
|
Tree.JumpAndExpandToTransform(transform);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDropdownChanged(int value)
|
private void OnSceneSelectionDropdownChanged(int value)
|
||||||
{
|
{
|
||||||
if (value < 0 || SceneHandler.LoadedScenes.Count <= value)
|
if (value < 0 || SceneHandler.LoadedScenes.Count <= value)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
SceneHandler.SelectedScene = SceneHandler.LoadedScenes[value];
|
SceneHandler.SelectedScene = SceneHandler.LoadedScenes[value];
|
||||||
SceneHandler.Update();
|
SceneHandler.Update();
|
||||||
Tree.RefreshData(true);
|
Tree.RefreshData(true, true, true, false);
|
||||||
OnSelectedSceneChanged(SceneHandler.SelectedScene.Value);
|
OnSelectedSceneChanged(SceneHandler.SelectedScene.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SceneHandler_OnInspectedSceneChanged(Scene scene)
|
private void SceneHandler_OnInspectedSceneChanged(Scene scene)
|
||||||
{
|
{
|
||||||
if (!sceneToDropdownOption.ContainsKey(scene))
|
if (!sceneToDropdownOption.ContainsKey(scene))
|
||||||
PopulateSceneDropdown();
|
PopulateSceneDropdown(SceneHandler.LoadedScenes);
|
||||||
|
|
||||||
if (sceneToDropdownOption.ContainsKey(scene))
|
if (sceneToDropdownOption.ContainsKey(scene))
|
||||||
{
|
{
|
||||||
@ -121,17 +122,17 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
refreshRow.SetActive(!scene.IsValid());
|
refreshRow.SetActive(!scene.IsValid());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SceneHandler_OnLoadedScenesChanged(List<Scene> loadedScenes)
|
private void SceneHandler_OnLoadedScenesUpdated(List<Scene> loadedScenes)
|
||||||
{
|
{
|
||||||
PopulateSceneDropdown();
|
PopulateSceneDropdown(loadedScenes);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PopulateSceneDropdown()
|
private void PopulateSceneDropdown(List<Scene> loadedScenes)
|
||||||
{
|
{
|
||||||
sceneToDropdownOption.Clear();
|
sceneToDropdownOption.Clear();
|
||||||
sceneDropdown.options.Clear();
|
sceneDropdown.options.Clear();
|
||||||
|
|
||||||
foreach (var scene in SceneHandler.LoadedScenes)
|
foreach (var scene in loadedScenes)
|
||||||
{
|
{
|
||||||
if (sceneToDropdownOption.ContainsKey(scene))
|
if (sceneToDropdownOption.ContainsKey(scene))
|
||||||
continue;
|
continue;
|
||||||
@ -157,7 +158,7 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
}
|
}
|
||||||
|
|
||||||
Tree.CurrentFilter = input;
|
Tree.CurrentFilter = input;
|
||||||
Tree.RefreshData(true, true);
|
Tree.RefreshData(true, false, true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void TryLoadScene(LoadSceneMode mode, Dropdown allSceneDrop)
|
private void TryLoadScene(LoadSceneMode mode, Dropdown allSceneDrop)
|
||||||
@ -180,13 +181,13 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
|
|
||||||
public override void ConstructUI(GameObject content)
|
public override void ConstructUI(GameObject content)
|
||||||
{
|
{
|
||||||
m_uiRoot = UIFactory.CreateUIObject("SceneExplorer", content);
|
uiRoot = UIFactory.CreateUIObject("SceneExplorer", content);
|
||||||
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(m_uiRoot, true, true, true, true, 0, 2, 2, 2, 2);
|
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(uiRoot, true, true, true, true, 0, 2, 2, 2, 2);
|
||||||
UIFactory.SetLayoutElement(m_uiRoot, flexibleHeight: 9999);
|
UIFactory.SetLayoutElement(uiRoot, flexibleHeight: 9999);
|
||||||
|
|
||||||
// Tool bar (top area)
|
// Tool bar (top area)
|
||||||
|
|
||||||
var toolbar = UIFactory.CreateVerticalGroup(m_uiRoot, "Toolbar", true, true, true, true, 2, new Vector4(2, 2, 2, 2),
|
var toolbar = UIFactory.CreateVerticalGroup(uiRoot, "Toolbar", true, true, true, true, 2, new Vector4(2, 2, 2, 2),
|
||||||
new Color(0.15f, 0.15f, 0.15f));
|
new Color(0.15f, 0.15f, 0.15f));
|
||||||
|
|
||||||
// Scene selector dropdown
|
// Scene selector dropdown
|
||||||
@ -197,11 +198,11 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
var dropLabel = UIFactory.CreateLabel(dropRow, "SelectorLabel", "Scene:", TextAnchor.MiddleLeft, Color.cyan, false, 15);
|
var dropLabel = UIFactory.CreateLabel(dropRow, "SelectorLabel", "Scene:", TextAnchor.MiddleLeft, Color.cyan, false, 15);
|
||||||
UIFactory.SetLayoutElement(dropLabel.gameObject, minHeight: 25, minWidth: 60, flexibleWidth: 0);
|
UIFactory.SetLayoutElement(dropLabel.gameObject, minHeight: 25, minWidth: 60, flexibleWidth: 0);
|
||||||
|
|
||||||
var dropdownObj = UIFactory.CreateDropdown(dropRow, out sceneDropdown, "<notset>", 13, OnDropdownChanged);
|
var dropdownObj = UIFactory.CreateDropdown(dropRow, "SceneDropdown", out sceneDropdown, "<notset>", 13, OnSceneSelectionDropdownChanged);
|
||||||
UIFactory.SetLayoutElement(dropdownObj, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999);
|
UIFactory.SetLayoutElement(dropdownObj, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999);
|
||||||
|
|
||||||
SceneHandler.Update();
|
SceneHandler.Update();
|
||||||
PopulateSceneDropdown();
|
PopulateSceneDropdown(SceneHandler.LoadedScenes);
|
||||||
sceneDropdown.captionText.text = sceneToDropdownOption.First().Value.text;
|
sceneDropdown.captionText.text = sceneToDropdownOption.First().Value.text;
|
||||||
|
|
||||||
// Filter row
|
// Filter row
|
||||||
@ -210,12 +211,13 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
UIFactory.SetLayoutElement(filterRow, minHeight: 25, flexibleHeight: 0);
|
UIFactory.SetLayoutElement(filterRow, minHeight: 25, flexibleHeight: 0);
|
||||||
|
|
||||||
//Filter input field
|
//Filter input field
|
||||||
var inputField = UIFactory.CreateInputField(filterRow, "FilterInput", "Search...");
|
var inputField = UIFactory.CreateInputField(filterRow, "FilterInput", "Search and press enter...");
|
||||||
inputField.Component.targetGraphic.color = new Color(0.2f, 0.2f, 0.2f);
|
inputField.Component.targetGraphic.color = new Color(0.2f, 0.2f, 0.2f);
|
||||||
RuntimeProvider.Instance.SetColorBlock(inputField.Component, new Color(0.4f, 0.4f, 0.4f), new Color(0.2f, 0.2f, 0.2f),
|
RuntimeHelper.SetColorBlock(inputField.Component, new Color(0.4f, 0.4f, 0.4f), new Color(0.2f, 0.2f, 0.2f),
|
||||||
new Color(0.08f, 0.08f, 0.08f));
|
new Color(0.08f, 0.08f, 0.08f));
|
||||||
UIFactory.SetLayoutElement(inputField.UIRoot, minHeight: 25);
|
UIFactory.SetLayoutElement(inputField.UIRoot, minHeight: 25);
|
||||||
inputField.OnValueChanged += OnFilterInput;
|
//inputField.OnValueChanged += OnFilterInput;
|
||||||
|
inputField.Component.GetOnEndEdit().AddListener(OnFilterInput);
|
||||||
|
|
||||||
// refresh row
|
// refresh row
|
||||||
|
|
||||||
@ -237,22 +239,48 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
|
|
||||||
refreshRow.SetActive(false);
|
refreshRow.SetActive(false);
|
||||||
|
|
||||||
|
// tree labels row
|
||||||
|
|
||||||
|
var labelsRow = UIFactory.CreateHorizontalGroup(toolbar, "LabelsRow", true, true, true, true, 2, new Vector4(2, 2, 2, 2));
|
||||||
|
UIFactory.SetLayoutElement(labelsRow, minHeight: 30, flexibleHeight: 0);
|
||||||
|
|
||||||
|
var nameLabel = UIFactory.CreateLabel(labelsRow, "NameLabel", "Name", TextAnchor.MiddleLeft, color: Color.grey);
|
||||||
|
UIFactory.SetLayoutElement(nameLabel.gameObject, flexibleWidth: 9999, minHeight: 25);
|
||||||
|
|
||||||
|
var indexLabel = UIFactory.CreateLabel(labelsRow, "IndexLabel", "Sibling Index", TextAnchor.MiddleLeft, fontSize: 12, color: Color.grey);
|
||||||
|
UIFactory.SetLayoutElement(indexLabel.gameObject, minWidth: 100, flexibleWidth: 0, minHeight: 25);
|
||||||
|
|
||||||
// Transform Tree
|
// Transform Tree
|
||||||
|
|
||||||
var scrollPool = UIFactory.CreateScrollPool<TransformCell>(m_uiRoot, "TransformTree", out GameObject scrollObj,
|
var scrollPool = UIFactory.CreateScrollPool<TransformCell>(uiRoot, "TransformTree", out GameObject scrollObj,
|
||||||
out GameObject scrollContent, new Color(0.11f, 0.11f, 0.11f));
|
out GameObject scrollContent, new Color(0.11f, 0.11f, 0.11f));
|
||||||
UIFactory.SetLayoutElement(scrollObj, flexibleHeight: 9999);
|
UIFactory.SetLayoutElement(scrollObj, flexibleHeight: 9999);
|
||||||
UIFactory.SetLayoutElement(scrollContent, flexibleHeight: 9999);
|
UIFactory.SetLayoutElement(scrollContent, flexibleHeight: 9999);
|
||||||
|
|
||||||
Tree = new TransformTree(scrollPool, GetRootEntries);
|
Tree = new TransformTree(scrollPool, GetRootEntries);
|
||||||
Tree.Init();
|
Tree.Init();
|
||||||
Tree.RefreshData(true, true);
|
Tree.RefreshData(true, true, true, false);
|
||||||
//scrollPool.Viewport.GetComponent<Mask>().enabled = false;
|
//scrollPool.Viewport.GetComponent<Mask>().enabled = false;
|
||||||
//UIRoot.GetComponent<Mask>().enabled = false;
|
//UIRoot.GetComponent<Mask>().enabled = false;
|
||||||
|
|
||||||
// Scene Loader
|
// Scene Loader
|
||||||
|
|
||||||
ConstructSceneLoader();
|
ConstructSceneLoader();
|
||||||
|
|
||||||
|
RuntimeHelper.StartCoroutine(TempFixCoro());
|
||||||
|
}
|
||||||
|
|
||||||
|
// To "fix" a strange FPS drop issue with MelonLoader.
|
||||||
|
private IEnumerator TempFixCoro()
|
||||||
|
{
|
||||||
|
float start = Time.realtimeSinceStartup;
|
||||||
|
|
||||||
|
while (Time.realtimeSinceStartup - start < 2.5f)
|
||||||
|
yield return null;
|
||||||
|
|
||||||
|
// Select "HideAndDontSave" and then go back to first scene.
|
||||||
|
this.sceneDropdown.value = sceneDropdown.options.Count - 1;
|
||||||
|
this.sceneDropdown.value = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private const string DEFAULT_LOAD_TEXT = "[Select a scene]";
|
private const string DEFAULT_LOAD_TEXT = "[Select a scene]";
|
||||||
@ -296,7 +324,7 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
{
|
{
|
||||||
if (SceneHandler.WasAbleToGetScenesInBuild)
|
if (SceneHandler.WasAbleToGetScenesInBuild)
|
||||||
{
|
{
|
||||||
var sceneLoaderObj = UIFactory.CreateVerticalGroup(m_uiRoot, "SceneLoader", true, true, true, true);
|
var sceneLoaderObj = UIFactory.CreateVerticalGroup(uiRoot, "SceneLoader", true, true, true, true);
|
||||||
UIFactory.SetLayoutElement(sceneLoaderObj, minHeight: 25);
|
UIFactory.SetLayoutElement(sceneLoaderObj, minHeight: 25);
|
||||||
|
|
||||||
// Title
|
// Title
|
||||||
@ -312,7 +340,7 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
|
|
||||||
// Dropdown
|
// Dropdown
|
||||||
|
|
||||||
var allSceneDropObj = UIFactory.CreateDropdown(sceneLoaderObj, out allSceneDropdown, "", 14, null);
|
var allSceneDropObj = UIFactory.CreateDropdown(sceneLoaderObj, "SceneLoaderDropdown", out allSceneDropdown, "", 14, null);
|
||||||
UIFactory.SetLayoutElement(allSceneDropObj, minHeight: 25, minWidth: 150, flexibleWidth: 0, flexibleHeight: 0);
|
UIFactory.SetLayoutElement(allSceneDropObj, minHeight: 25, minWidth: 150, flexibleWidth: 0, flexibleHeight: 0);
|
||||||
|
|
||||||
RefreshSceneLoaderOptions(string.Empty);
|
RefreshSceneLoaderOptions(string.Empty);
|
||||||
@ -336,8 +364,8 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
};
|
};
|
||||||
|
|
||||||
var disabledColor = new Color(0.24f, 0.24f, 0.24f);
|
var disabledColor = new Color(0.24f, 0.24f, 0.24f);
|
||||||
RuntimeProvider.Instance.SetColorBlock(loadButton.Component, disabled: disabledColor);
|
RuntimeHelper.SetColorBlock(loadButton.Component, disabled: disabledColor);
|
||||||
RuntimeProvider.Instance.SetColorBlock(loadAdditiveButton.Component, disabled: disabledColor);
|
RuntimeHelper.SetColorBlock(loadAdditiveButton.Component, disabled: disabledColor);
|
||||||
|
|
||||||
loadButton.Component.interactable = false;
|
loadButton.Component.interactable = false;
|
||||||
loadAdditiveButton.Component.interactable = false;
|
loadAdditiveButton.Component.interactable = false;
|
||||||
|
@ -11,15 +11,13 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
{
|
{
|
||||||
public static class SceneHandler
|
public static class SceneHandler
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>The currently inspected Scene.</summary>
|
||||||
/// The currently inspected Scene.
|
|
||||||
/// </summary>
|
|
||||||
public static Scene? SelectedScene
|
public static Scene? SelectedScene
|
||||||
{
|
{
|
||||||
get => selectedScene;
|
get => selectedScene;
|
||||||
internal set
|
internal set
|
||||||
{
|
{
|
||||||
if (selectedScene != null && selectedScene == value)
|
if (selectedScene.HasValue && selectedScene == value)
|
||||||
return;
|
return;
|
||||||
selectedScene = value;
|
selectedScene = value;
|
||||||
OnInspectedSceneChanged?.Invoke((Scene)selectedScene);
|
OnInspectedSceneChanged?.Invoke((Scene)selectedScene);
|
||||||
@ -27,63 +25,39 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
}
|
}
|
||||||
private static Scene? selectedScene;
|
private static Scene? selectedScene;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>The GameObjects in the currently inspected scene.</summary>
|
||||||
/// The GameObjects in the currently inspected scene.
|
public static IEnumerable<GameObject> CurrentRootObjects { get; private set; } = new GameObject[0];
|
||||||
/// </summary>
|
|
||||||
public static GameObject[] CurrentRootObjects { get; private set; } = new GameObject[0];
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>All currently loaded Scenes.</summary>
|
||||||
/// All currently loaded Scenes.
|
public static List<Scene> LoadedScenes { get; private set; } = new();
|
||||||
/// </summary>
|
//private static HashSet<Scene> previousLoadedScenes;
|
||||||
public static List<Scene> LoadedScenes { get; private set; } = new List<Scene>();
|
|
||||||
private static HashSet<Scene> previousLoadedScenes;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>The names of all scenes in the build settings, if they could be retrieved.</summary>
|
||||||
/// The names of all scenes in the build settings, if they could be retrieved.
|
public static List<string> AllSceneNames { get; private set; } = new();
|
||||||
/// </summary>
|
|
||||||
public static readonly List<string> AllSceneNames = new List<string>();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>Invoked when the currently inspected Scene changes. The argument is the new scene.</summary>
|
||||||
/// Whether or not we successfuly retrieved the names of the scenes in the build settings.
|
|
||||||
/// </summary>
|
|
||||||
public static bool WasAbleToGetScenesInBuild { get; private set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Invoked when the currently inspected Scene changes. The argument is the new scene.
|
|
||||||
/// </summary>
|
|
||||||
public static event Action<Scene> OnInspectedSceneChanged;
|
public static event Action<Scene> OnInspectedSceneChanged;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>Invoked whenever the list of currently loaded Scenes changes. The argument contains all loaded scenes after the change.</summary>
|
||||||
/// Invoked whenever the list of currently loaded Scenes changes. The argument contains all loaded scenes after the change.
|
public static event Action<List<Scene>> OnLoadedScenesUpdated;
|
||||||
/// </summary>
|
|
||||||
public static event Action<List<Scene>> OnLoadedScenesChanged;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>Generally will be 2, unless DontDestroyExists == false, then this will be 1.</summary>
|
||||||
/// Equivalent to <see cref="SceneManager.sceneCount"/> + 2, to include 'DontDestroyOnLoad' and the 'None' scene.
|
internal static int DefaultSceneCount => 1 + (DontDestroyExists ? 1 : 0);
|
||||||
/// </summary>
|
|
||||||
public static int LoadedSceneCount => SceneManager.sceneCount + 2;
|
|
||||||
|
|
||||||
internal static Scene DontDestroyScene => DontDestroyMe.scene;
|
|
||||||
internal static int DontDestroyHandle => DontDestroyScene.handle;
|
|
||||||
|
|
||||||
internal static GameObject DontDestroyMe
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (!dontDestroyObject)
|
|
||||||
{
|
|
||||||
dontDestroyObject = new GameObject("DontDestroyMe");
|
|
||||||
GameObject.DontDestroyOnLoad(dontDestroyObject);
|
|
||||||
}
|
|
||||||
return dontDestroyObject;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private static GameObject dontDestroyObject;
|
|
||||||
|
|
||||||
|
/// <summary>Whether or not we are currently inspecting the "HideAndDontSave" asset scene.</summary>
|
||||||
public static bool InspectingAssetScene => SelectedScene.HasValue && SelectedScene.Value == default;
|
public static bool InspectingAssetScene => SelectedScene.HasValue && SelectedScene.Value == default;
|
||||||
|
|
||||||
|
/// <summary>Whether or not we successfuly retrieved the names of the scenes in the build settings.</summary>
|
||||||
|
public static bool WasAbleToGetScenesInBuild { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>Whether or not the "DontDestroyOnLoad" scene exists in this game.</summary>
|
||||||
|
public static bool DontDestroyExists { get; private set; }
|
||||||
|
|
||||||
internal static void Init()
|
internal static void Init()
|
||||||
{
|
{
|
||||||
|
// Check if the game has "DontDestroyOnLoad"
|
||||||
|
DontDestroyExists = Scene.GetNameInternal(-12) == "DontDestroyOnLoad";
|
||||||
|
|
||||||
// Try to get all scenes in the build settings. This may not work.
|
// Try to get all scenes in the build settings. This may not work.
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -110,22 +84,20 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
|
|
||||||
internal static void Update()
|
internal static void Update()
|
||||||
{
|
{
|
||||||
// check if the loaded scenes changed. always confirm DontDestroy / HideAndDontSave
|
// Inspected scene will exist if it's DontDestroyOnLoad or HideAndDontSave
|
||||||
int confirmedCount = 2;
|
bool inspectedExists =
|
||||||
bool inspectedExists = SelectedScene == DontDestroyScene || (SelectedScene.HasValue && SelectedScene.Value == default);
|
SelectedScene.HasValue
|
||||||
|
&& ((DontDestroyExists && SelectedScene.Value.handle == -12)
|
||||||
|
|| SelectedScene.Value.handle == -1);
|
||||||
|
|
||||||
LoadedScenes.Clear();
|
LoadedScenes.Clear();
|
||||||
|
|
||||||
for (int i = 0; i < SceneManager.sceneCount; i++)
|
for (int i = 0; i < SceneManager.sceneCount; i++)
|
||||||
{
|
{
|
||||||
Scene scene = SceneManager.GetSceneAt(i);
|
Scene scene = SceneManager.GetSceneAt(i);
|
||||||
if (scene == default || !scene.isLoaded)
|
if (scene == default || !scene.isLoaded || !scene.IsValid())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// If no changes yet, ensure the previous list contained the scene
|
|
||||||
if (previousLoadedScenes != null && previousLoadedScenes.Contains(scene))
|
|
||||||
confirmedCount++;
|
|
||||||
|
|
||||||
// If we have not yet confirmed inspectedExists, check if this scene is our currently inspected one.
|
// If we have not yet confirmed inspectedExists, check if this scene is our currently inspected one.
|
||||||
if (!inspectedExists && scene == SelectedScene)
|
if (!inspectedExists && scene == SelectedScene)
|
||||||
inspectedExists = true;
|
inspectedExists = true;
|
||||||
@ -133,26 +105,23 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
LoadedScenes.Add(scene);
|
LoadedScenes.Add(scene);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool anyChange = confirmedCount != LoadedScenes.Count;
|
if (DontDestroyExists)
|
||||||
|
LoadedScenes.Add(new Scene { m_Handle = -12 });
|
||||||
LoadedScenes.Add(DontDestroyScene);
|
LoadedScenes.Add(new Scene { m_Handle = -1 });
|
||||||
LoadedScenes.Add(default);
|
|
||||||
previousLoadedScenes = new HashSet<Scene>(LoadedScenes);
|
|
||||||
|
|
||||||
// Default to first scene if none selected or previous selection no longer exists.
|
// Default to first scene if none selected or previous selection no longer exists.
|
||||||
if (!inspectedExists)
|
if (!inspectedExists)
|
||||||
SelectedScene = LoadedScenes.First();
|
SelectedScene = LoadedScenes.First();
|
||||||
|
|
||||||
// Notify on the list changing at all
|
// Notify on the list changing at all
|
||||||
if (anyChange)
|
OnLoadedScenesUpdated?.Invoke(LoadedScenes);
|
||||||
OnLoadedScenesChanged?.Invoke(LoadedScenes);
|
|
||||||
|
|
||||||
// Finally, update the root objects list.
|
// Finally, update the root objects list.
|
||||||
if (SelectedScene != null && ((Scene)SelectedScene).IsValid())
|
if (SelectedScene != null && ((Scene)SelectedScene).IsValid())
|
||||||
CurrentRootObjects = RuntimeProvider.Instance.GetRootGameObjects((Scene)SelectedScene);
|
CurrentRootObjects = RuntimeHelper.GetRootGameObjects((Scene)SelectedScene);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var allObjects = RuntimeProvider.Instance.FindObjectsOfTypeAll(typeof(GameObject));
|
var allObjects = RuntimeHelper.FindObjectsOfTypeAll(typeof(GameObject));
|
||||||
var objects = new List<GameObject>();
|
var objects = new List<GameObject>();
|
||||||
foreach (var obj in allObjects)
|
foreach (var obj in allObjects)
|
||||||
{
|
{
|
||||||
@ -160,7 +129,7 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
if (go.transform.parent == null && !go.scene.IsValid())
|
if (go.transform.parent == null && !go.scene.IsValid())
|
||||||
objects.Add(go);
|
objects.Add(go);
|
||||||
}
|
}
|
||||||
CurrentRootObjects = objects.ToArray();
|
CurrentRootObjects = objects;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,9 +5,10 @@ using System.Reflection;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.SceneManagement;
|
using UnityEngine.SceneManagement;
|
||||||
using UnityExplorer.Core;
|
using UnityExplorer.Runtime;
|
||||||
using UnityExplorer.Core.Runtime;
|
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
|
using UniverseLib.Input;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.ObjectExplorer
|
namespace UnityExplorer.ObjectExplorer
|
||||||
{
|
{
|
||||||
@ -35,26 +36,19 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
|
|
||||||
public static class SearchProvider
|
public static class SearchProvider
|
||||||
{
|
{
|
||||||
|
|
||||||
private static bool Filter(Scene scene, SceneFilter filter)
|
private static bool Filter(Scene scene, SceneFilter filter)
|
||||||
{
|
{
|
||||||
switch (filter)
|
return filter switch
|
||||||
{
|
{
|
||||||
case SceneFilter.Any:
|
SceneFilter.Any => true,
|
||||||
return true;
|
SceneFilter.DontDestroyOnLoad => scene.handle == -12,
|
||||||
case SceneFilter.DontDestroyOnLoad:
|
SceneFilter.HideAndDontSave => scene == default,
|
||||||
return scene == SceneHandler.DontDestroyScene;
|
SceneFilter.ActivelyLoaded => scene.buildIndex != -1,
|
||||||
case SceneFilter.HideAndDontSave:
|
_ => false,
|
||||||
return scene == default;
|
};
|
||||||
case SceneFilter.ActivelyLoaded:
|
|
||||||
return scene != SceneHandler.DontDestroyScene && scene != default;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static List<object> UnityObjectSearch(string input, string customTypeInput, SearchContext context,
|
internal static List<object> UnityObjectSearch(string input, string customTypeInput, ChildFilter childFilter, SceneFilter sceneFilter)
|
||||||
ChildFilter childFilter, SceneFilter sceneFilter)
|
|
||||||
{
|
{
|
||||||
var results = new List<object>();
|
var results = new List<object>();
|
||||||
|
|
||||||
@ -75,7 +69,7 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
if (searchType == null)
|
if (searchType == null)
|
||||||
searchType = typeof(UnityEngine.Object);
|
searchType = typeof(UnityEngine.Object);
|
||||||
|
|
||||||
var allObjects = RuntimeProvider.Instance.FindObjectsOfTypeAll(searchType);
|
var allObjects = RuntimeHelper.FindObjectsOfTypeAll(searchType);
|
||||||
|
|
||||||
// perform filter comparers
|
// perform filter comparers
|
||||||
|
|
||||||
@ -169,7 +163,7 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
"<instance>k__BackingField",
|
"<instance>k__BackingField",
|
||||||
};
|
};
|
||||||
|
|
||||||
internal static List<object> SingletonSearch(string input)
|
internal static List<object> InstanceSearch(string input)
|
||||||
{
|
{
|
||||||
var instances = new List<object>();
|
var instances = new List<object>();
|
||||||
|
|
||||||
@ -178,7 +172,7 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
nameFilter = input;
|
nameFilter = input;
|
||||||
|
|
||||||
var flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static;
|
var flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static;
|
||||||
|
|
||||||
foreach (var asm in AppDomain.CurrentDomain.GetAssemblies())
|
foreach (var asm in AppDomain.CurrentDomain.GetAssemblies())
|
||||||
{
|
{
|
||||||
// Search all non-static, non-enum classes.
|
// Search all non-static, non-enum classes.
|
||||||
@ -188,13 +182,13 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(nameFilter) && !type.FullName.ContainsIgnoreCase(nameFilter))
|
if (!string.IsNullOrEmpty(nameFilter) && !type.FullName.ContainsIgnoreCase(nameFilter))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
ReflectionUtility.FindSingleton(instanceNames, type, flags, instances);
|
ReflectionUtility.FindSingleton(instanceNames, type, flags, instances);
|
||||||
}
|
}
|
||||||
catch { }
|
catch { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return instances;
|
return instances;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,21 +2,11 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
|
||||||
using BF = System.Reflection.BindingFlags;
|
|
||||||
using System.Text;
|
|
||||||
using UnhollowerBaseLib;
|
|
||||||
using UnhollowerRuntimeLib;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.Events;
|
|
||||||
using UnityEngine.SceneManagement;
|
|
||||||
using System.Collections;
|
|
||||||
using UnityEngine.UI;
|
|
||||||
using UnityEngine.EventSystems;
|
|
||||||
|
|
||||||
namespace UnityExplorer.Core.Runtime
|
namespace UnityExplorer.Runtime
|
||||||
{
|
{
|
||||||
public class Il2CppProvider : RuntimeHelper
|
public class Il2CppHelper : UERuntimeHelper
|
||||||
{
|
{
|
||||||
public override void SetupEvents()
|
public override void SetupEvents()
|
||||||
{
|
{
|
||||||
@ -41,7 +31,7 @@ namespace UnityExplorer.Core.Runtime
|
|||||||
// These methods currently cause a crash in most il2cpp games,
|
// These methods currently cause a crash in most il2cpp games,
|
||||||
// even from doing "GetParameters()" on the MemberInfo.
|
// even from doing "GetParameters()" on the MemberInfo.
|
||||||
// Blacklisting until the issue is fixed in Unhollower.
|
// Blacklisting until the issue is fixed in Unhollower.
|
||||||
public static HashSet<string> defaultIl2CppBlacklist = new HashSet<string>
|
public static HashSet<string> defaultIl2CppBlacklist = new()
|
||||||
{
|
{
|
||||||
// These were deprecated a long time ago, still show up in some IL2CPP games for some reason
|
// These were deprecated a long time ago, still show up in some IL2CPP games for some reason
|
||||||
"UnityEngine.MonoBehaviour.allowPrefabModeInPlayMode",
|
"UnityEngine.MonoBehaviour.allowPrefabModeInPlayMode",
|
@ -1,20 +1,9 @@
|
|||||||
#if MONO
|
#if MONO
|
||||||
using System;
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Text;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.Events;
|
|
||||||
using UnityEngine.EventSystems;
|
|
||||||
using UnityEngine.SceneManagement;
|
|
||||||
using UnityEngine.UI;
|
|
||||||
using UnityExplorer;
|
|
||||||
|
|
||||||
namespace UnityExplorer.Core.Runtime
|
namespace UnityExplorer.Runtime
|
||||||
{
|
{
|
||||||
public class MonoProvider : RuntimeHelper
|
public class MonoHelper : UERuntimeHelper
|
||||||
{
|
{
|
||||||
public override void SetupEvents()
|
public override void SetupEvents()
|
||||||
{
|
{
|
@ -8,21 +8,23 @@ using UnityEngine;
|
|||||||
using UnityEngine.EventSystems;
|
using UnityEngine.EventSystems;
|
||||||
using UnityEngine.SceneManagement;
|
using UnityEngine.SceneManagement;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.Core.Config;
|
using UnityExplorer.Config;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
|
|
||||||
namespace UnityExplorer.Core.Runtime
|
namespace UnityExplorer.Runtime
|
||||||
{
|
{
|
||||||
public abstract class RuntimeHelper
|
// Not really that necessary anymore, can eventually just be refactored away into the few classes that use this class.
|
||||||
|
|
||||||
|
public abstract class UERuntimeHelper
|
||||||
{
|
{
|
||||||
public static RuntimeHelper Instance;
|
public static UERuntimeHelper Instance;
|
||||||
|
|
||||||
public static void Init()
|
public static void Init()
|
||||||
{
|
{
|
||||||
#if CPP
|
#if CPP
|
||||||
Instance = new Il2CppProvider();
|
Instance = new Il2CppHelper();
|
||||||
#else
|
#else
|
||||||
Instance = new MonoProvider();
|
Instance = new MonoHelper();
|
||||||
#endif
|
#endif
|
||||||
Instance.SetupEvents();
|
Instance.SetupEvents();
|
||||||
|
|
||||||
@ -35,9 +37,7 @@ namespace UnityExplorer.Core.Runtime
|
|||||||
|
|
||||||
public abstract void SetupEvents();
|
public abstract void SetupEvents();
|
||||||
|
|
||||||
#region Reflection Blacklist
|
private static readonly HashSet<string> currentBlacklist = new();
|
||||||
|
|
||||||
private static readonly HashSet<string> currentBlacklist = new HashSet<string>();
|
|
||||||
|
|
||||||
public virtual string[] DefaultReflectionBlacklist => new string[0];
|
public virtual string[] DefaultReflectionBlacklist => new string[0];
|
||||||
|
|
||||||
@ -88,7 +88,5 @@ namespace UnityExplorer.Core.Runtime
|
|||||||
|
|
||||||
return currentBlacklist.Contains(sig);
|
return currentBlacklist.Contains(sig);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
}
|
||||||
}
|
}
|
38
src/Runtime/UnityCrashPrevention.cs
Normal file
38
src/Runtime/UnityCrashPrevention.cs
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
using HarmonyLib;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityExplorer.CacheObject;
|
||||||
|
|
||||||
|
namespace UnityExplorer.Runtime
|
||||||
|
{
|
||||||
|
internal static class UnityCrashPrevention
|
||||||
|
{
|
||||||
|
internal static void Init()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ExplorerCore.Harmony.PatchAll(typeof(UnityCrashPrevention));
|
||||||
|
ExplorerCore.Log("Initialized UnityCrashPrevention.");
|
||||||
|
}
|
||||||
|
catch //(Exception ex)
|
||||||
|
{
|
||||||
|
//ExplorerCore.Log($"Exception setting up Canvas crash prevention patch: {ex}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// In Unity 2020 they introduced "Canvas.renderingDisplaySize".
|
||||||
|
// If you try to get the value on a Canvas which has a renderMode value of WorldSpace and no worldCamera set,
|
||||||
|
// the game will Crash (I think from Unity trying to read from null ptr).
|
||||||
|
[HarmonyPatch(typeof(Canvas), "renderingDisplaySize", MethodType.Getter)]
|
||||||
|
[HarmonyPrefix]
|
||||||
|
internal static void Prefix_Canvas_renderingDisplaySize(Canvas __instance)
|
||||||
|
{
|
||||||
|
if (__instance.renderMode == RenderMode.WorldSpace && !__instance.worldCamera)
|
||||||
|
throw new InvalidOperationException(
|
||||||
|
"Canvas is set to RenderMode.WorldSpace but not worldCamera is set, cannot get renderingDisplaySize.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -14,7 +14,7 @@ using UnhollowerBaseLib;
|
|||||||
|
|
||||||
namespace UnityExplorer.Tests
|
namespace UnityExplorer.Tests
|
||||||
{
|
{
|
||||||
public static class TestClass
|
public class TestClass
|
||||||
{
|
{
|
||||||
static TestClass()
|
static TestClass()
|
||||||
{
|
{
|
||||||
@ -24,21 +24,35 @@ namespace UnityExplorer.Tests
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#region MONO
|
||||||
|
|
||||||
|
public static object LiterallyAnything = null;
|
||||||
|
|
||||||
|
public static string Exception => throw new Exception("This is a test.");
|
||||||
|
|
||||||
// Test enumerables
|
// Test enumerables
|
||||||
|
public static int[,,] MultiDimensionalArray = new int[45, 45, 45];
|
||||||
public static List<object> ListOfInts;
|
public static List<object> ListOfInts;
|
||||||
public static List<List<List<string>>> NestedList;
|
public static List<List<List<string>>> NestedList;
|
||||||
public static IDictionary MixedDictionary;
|
public static IDictionary MixedDictionary;
|
||||||
public static Hashtable Hashtable;
|
public static Hashtable Hashtable;
|
||||||
public static byte[] ByteArray = new byte[16];
|
public static byte[] ByteArray = new byte[16];
|
||||||
public static List<short> ABigList = new List<short>(10000);
|
public static List<short> ABigList = new(10000);
|
||||||
|
|
||||||
// Test const behaviour (should be a readonly field)
|
// Test const behaviour (should be a readonly field)
|
||||||
public const int ConstantInt5 = 5;
|
public const int ConstantInt5 = 5;
|
||||||
|
|
||||||
// Testing other InteractiveValues
|
// Testing other InteractiveValues
|
||||||
|
public static BindingFlags EnumTest;
|
||||||
|
public static CameraClearFlags EnumTest2;
|
||||||
public static Color Color = Color.magenta;
|
public static Color Color = Color.magenta;
|
||||||
public static Color32 Color32 = Color.red;
|
public static Color32 Color32 = Color.red;
|
||||||
public static string ALongString = new string('#', 10000);
|
public static string ALongString = new('#', 10000);
|
||||||
|
|
||||||
|
public static float[] AParseTest(ref List<float[,,]> arg0, ref float[,] arg1)
|
||||||
|
{
|
||||||
|
return new float[] { 1, 2, 3 };
|
||||||
|
}
|
||||||
|
|
||||||
public static List<object> RandomList
|
public static List<object> RandomList
|
||||||
{
|
{
|
||||||
@ -52,25 +66,27 @@ namespace UnityExplorer.Tests
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int this[int index]
|
||||||
|
{
|
||||||
|
get => UnityEngine.Random.Range(0, int.MaxValue);
|
||||||
|
set => ExplorerCore.Log(index);
|
||||||
|
}
|
||||||
|
|
||||||
// Test methods
|
// Test methods
|
||||||
|
|
||||||
private static object GetRandomObject()
|
private static object GetRandomObject()
|
||||||
{
|
{
|
||||||
object ret = null;
|
return UnityEngine.Random.Range(0, 7) switch
|
||||||
|
|
||||||
int ran = UnityEngine.Random.Range(0, 7);
|
|
||||||
switch (ran)
|
|
||||||
{
|
{
|
||||||
case 0: return null;
|
0 => null,
|
||||||
case 1: return 123;
|
1 => 123,
|
||||||
case 2: return true;
|
2 => true,
|
||||||
case 3: return "hello";
|
3 => "hello",
|
||||||
case 4: return 50.5f;
|
4 => 50.5f,
|
||||||
case 5: return CameraClearFlags.Color;
|
5 => CameraClearFlags.Color,
|
||||||
case 6: return new List<string> { "one", "two" };
|
6 => new List<string> { "one", "two" },
|
||||||
}
|
_ => null,
|
||||||
|
};
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void TestComponent<T>() where T : Component
|
public static void TestComponent<T>() where T : Component
|
||||||
@ -78,9 +94,19 @@ namespace UnityExplorer.Tests
|
|||||||
ExplorerCore.Log($"Test3 {typeof(T).FullName}");
|
ExplorerCore.Log($"Test3 {typeof(T).FullName}");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void TestArgumentParse(string s, int i, Color color, CameraClearFlags flags, Vector3 vector, Quaternion quaternion)
|
public static void TestArgumentParse(string _string,
|
||||||
|
int integer,
|
||||||
|
Color color,
|
||||||
|
CameraClearFlags flags,
|
||||||
|
Vector3 vector,
|
||||||
|
Quaternion quaternion,
|
||||||
|
object obj,
|
||||||
|
Type type,
|
||||||
|
GameObject go)
|
||||||
{
|
{
|
||||||
ExplorerCore.Log($"{s}, {i}, {color.ToString()}, {flags}, {vector.ToString()}, {quaternion.ToString()}");
|
ExplorerCore.Log($"_string: {_string}, integer: {integer}, color: {color.ToString()}, flags: {flags}, " +
|
||||||
|
$"vector: {vector.ToString()}, quaternion: {quaternion.ToString()}, obj: {obj?.ToString() ?? "null"}," +
|
||||||
|
$"type: {type?.FullName ?? "null"}, go: {go?.ToString() ?? "null"}");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void Init_Mono()
|
private static void Init_Mono()
|
||||||
@ -123,23 +149,25 @@ namespace UnityExplorer.Tests
|
|||||||
ExplorerCore.Log("Finished TestClass Init_Mono");
|
ExplorerCore.Log("Finished TestClass Init_Mono");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
#if CPP
|
#if CPP
|
||||||
|
public static Il2CppSystem.Collections.Generic.Dictionary<string, string> IL2CPP_Dict;
|
||||||
|
public static Il2CppSystem.Collections.Generic.HashSet<string> IL2CPP_HashSet;
|
||||||
public static Il2CppSystem.Collections.Generic.List<string> IL2CPP_ListString;
|
public static Il2CppSystem.Collections.Generic.List<string> IL2CPP_ListString;
|
||||||
|
public static Il2CppSystem.Collections.Hashtable IL2CPP_HashTable;
|
||||||
public static List<Il2CppSystem.Object> IL2CPP_listOfBoxedObjects;
|
public static List<Il2CppSystem.Object> IL2CPP_listOfBoxedObjects;
|
||||||
public static Il2CppStructArray<int> IL2CPP_structArray;
|
public static Il2CppStructArray<int> IL2CPP_structArray;
|
||||||
public static Il2CppReferenceArray<Il2CppSystem.Object> IL2CPP_ReferenceArray;
|
public static Il2CppReferenceArray<Il2CppSystem.Object> IL2CPP_ReferenceArray;
|
||||||
public static Il2CppSystem.Collections.IDictionary IL2CPP_IDict;
|
public static Il2CppSystem.Collections.IDictionary IL2CPP_IDict;
|
||||||
public static Il2CppSystem.Collections.IList IL2CPP_IList;
|
public static Il2CppSystem.Collections.IList IL2CPP_IList;
|
||||||
public static Dictionary<Il2CppSystem.String, Il2CppSystem.Object> CppBoxedDict;
|
public static Dictionary<Il2CppSystem.Object, Il2CppSystem.Object> IL2CPP_BoxedDict;
|
||||||
|
|
||||||
public static Il2CppSystem.Collections.Generic.HashSet<string> IL2CPP_HashSet;
|
public static Il2CppSystem.Object IL2CPP_BoxedInt;
|
||||||
public static Il2CppSystem.Collections.Generic.Dictionary<string, string> IL2CPP_Dict;
|
public static Il2CppSystem.Int32 IL2CPP_Int;
|
||||||
public static Il2CppSystem.Collections.Hashtable IL2CPP_HashTable;
|
public static Il2CppSystem.Decimal IL2CPP_Decimal;
|
||||||
public static Il2CppSystem.Object cppBoxedInt;
|
public static Il2CppSystem.Object IL2CPP_DecimalBoxed;
|
||||||
public static Il2CppSystem.Int32 cppInt;
|
public static Il2CppSystem.Object IL2CPP_Vector3Boxed;
|
||||||
public static Il2CppSystem.Decimal cppDecimal;
|
|
||||||
public static Il2CppSystem.Object cppDecimalBoxed;
|
|
||||||
public static Il2CppSystem.Object cppVector3Boxed;
|
|
||||||
public static string IL2CPP_systemString = "Test";
|
public static string IL2CPP_systemString = "Test";
|
||||||
public static Il2CppSystem.Object IL2CPP_objectString = "string boxed as cpp object";
|
public static Il2CppSystem.Object IL2CPP_objectString = "string boxed as cpp object";
|
||||||
public static Il2CppSystem.String IL2CPP_il2cppString = "string boxed as cpp string";
|
public static Il2CppSystem.String IL2CPP_il2cppString = "string boxed as cpp string";
|
||||||
@ -153,6 +181,11 @@ namespace UnityExplorer.Tests
|
|||||||
IL2CPP_Dict.Add("key2", "value2");
|
IL2CPP_Dict.Add("key2", "value2");
|
||||||
IL2CPP_Dict.Add("key3", "value3");
|
IL2CPP_Dict.Add("key3", "value3");
|
||||||
|
|
||||||
|
ExplorerCore.Log($"IL2CPP 6: Il2Cpp HashSet of strings");
|
||||||
|
IL2CPP_HashSet = new Il2CppSystem.Collections.Generic.HashSet<string>();
|
||||||
|
IL2CPP_HashSet.Add("one");
|
||||||
|
IL2CPP_HashSet.Add("two");
|
||||||
|
|
||||||
ExplorerCore.Log($"IL2CPP 2: Il2Cpp Hashtable");
|
ExplorerCore.Log($"IL2CPP 2: Il2Cpp Hashtable");
|
||||||
IL2CPP_HashTable = new Il2CppSystem.Collections.Hashtable();
|
IL2CPP_HashTable = new Il2CppSystem.Collections.Hashtable();
|
||||||
IL2CPP_HashTable.Add("key1", "value1");
|
IL2CPP_HashTable.Add("key1", "value1");
|
||||||
@ -175,17 +208,13 @@ namespace UnityExplorer.Tests
|
|||||||
IL2CPP_ListString.Add("hello,");
|
IL2CPP_ListString.Add("hello,");
|
||||||
IL2CPP_ListString.Add("world!");
|
IL2CPP_ListString.Add("world!");
|
||||||
|
|
||||||
ExplorerCore.Log($"IL2CPP 6: Il2Cpp HashSet of strings");
|
|
||||||
IL2CPP_HashSet = new Il2CppSystem.Collections.Generic.HashSet<string>();
|
|
||||||
IL2CPP_HashSet.Add("one");
|
|
||||||
IL2CPP_HashSet.Add("two");
|
|
||||||
|
|
||||||
ExplorerCore.Log($"IL2CPP 7: Dictionary of Il2Cpp String and Il2Cpp Object");
|
ExplorerCore.Log($"IL2CPP 7: Dictionary of Il2Cpp String and Il2Cpp Object");
|
||||||
CppBoxedDict = new Dictionary<Il2CppSystem.String, Il2CppSystem.Object>();
|
IL2CPP_BoxedDict = new();
|
||||||
CppBoxedDict.Add("1", new Il2CppSystem.Int32 { m_value = 1 }.BoxIl2CppObject());
|
IL2CPP_BoxedDict[(Il2CppSystem.String)"one"] = new Il2CppSystem.Int32 { m_value = 1 }.BoxIl2CppObject();
|
||||||
CppBoxedDict.Add("2", new Il2CppSystem.Int32 { m_value = 2 }.BoxIl2CppObject());
|
IL2CPP_BoxedDict[(Il2CppSystem.String)"two"] = new Il2CppSystem.Int32 { m_value = 2 }.BoxIl2CppObject();
|
||||||
CppBoxedDict.Add("3", new Il2CppSystem.Int32 { m_value = 3 }.BoxIl2CppObject());
|
IL2CPP_BoxedDict[(Il2CppSystem.String)"three"] = new Il2CppSystem.Int32 { m_value = 3 }.BoxIl2CppObject();
|
||||||
CppBoxedDict.Add("4", new Il2CppSystem.Int32 { m_value = 4 }.BoxIl2CppObject());
|
IL2CPP_BoxedDict[(Il2CppSystem.String)"four"] = new Il2CppSystem.Int32 { m_value = 4 }.BoxIl2CppObject();
|
||||||
|
|
||||||
ExplorerCore.Log($"IL2CPP 8: List of boxed Il2Cpp Objects");
|
ExplorerCore.Log($"IL2CPP 8: List of boxed Il2Cpp Objects");
|
||||||
IL2CPP_listOfBoxedObjects = new List<Il2CppSystem.Object>();
|
IL2CPP_listOfBoxedObjects = new List<Il2CppSystem.Object>();
|
||||||
@ -226,14 +255,15 @@ namespace UnityExplorer.Tests
|
|||||||
IL2CPP_ReferenceArray[2] = (Il2CppSystem.String)"whats up";
|
IL2CPP_ReferenceArray[2] = (Il2CppSystem.String)"whats up";
|
||||||
|
|
||||||
ExplorerCore.Log($"IL2CPP 11: Misc il2cpp members");
|
ExplorerCore.Log($"IL2CPP 11: Misc il2cpp members");
|
||||||
cppBoxedInt = new Il2CppSystem.Int32() { m_value = 5 }.BoxIl2CppObject();
|
IL2CPP_BoxedInt = new Il2CppSystem.Int32() { m_value = 5 }.BoxIl2CppObject();
|
||||||
cppInt = new Il2CppSystem.Int32 { m_value = 420 };
|
IL2CPP_Int = new Il2CppSystem.Int32 { m_value = 420 };
|
||||||
cppDecimal = new Il2CppSystem.Decimal(1f);
|
IL2CPP_Decimal = new Il2CppSystem.Decimal(1f);
|
||||||
cppDecimalBoxed = new Il2CppSystem.Decimal(1f).BoxIl2CppObject();
|
IL2CPP_DecimalBoxed = new Il2CppSystem.Decimal(1f).BoxIl2CppObject();
|
||||||
cppVector3Boxed = Vector3.down.BoxIl2CppObject();
|
IL2CPP_Vector3Boxed = Vector3.down.BoxIl2CppObject();
|
||||||
|
|
||||||
ExplorerCore.Log($"Finished Init_Il2Cpp");
|
ExplorerCore.Log($"Finished Init_Il2Cpp");
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
83
src/UI/DisplayManager.cs
Normal file
83
src/UI/DisplayManager.cs
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityExplorer.Config;
|
||||||
|
using UniverseLib;
|
||||||
|
using UniverseLib.Input;
|
||||||
|
|
||||||
|
namespace UnityExplorer.UI
|
||||||
|
{
|
||||||
|
public static class DisplayManager
|
||||||
|
{
|
||||||
|
public static int ActiveDisplayIndex { get; private set; }
|
||||||
|
public static Display ActiveDisplay => Display.displays[ActiveDisplayIndex];
|
||||||
|
|
||||||
|
public static int Width => ActiveDisplay.renderingWidth;
|
||||||
|
public static int Height => ActiveDisplay.renderingHeight;
|
||||||
|
|
||||||
|
public static Vector3 MousePosition => Application.isEditor
|
||||||
|
? InputManager.MousePosition
|
||||||
|
: Display.RelativeMouseAt(InputManager.MousePosition);
|
||||||
|
|
||||||
|
public static bool MouseInTargetDisplay => MousePosition.z == ActiveDisplayIndex;
|
||||||
|
|
||||||
|
private static Camera canvasCamera;
|
||||||
|
|
||||||
|
internal static void Init()
|
||||||
|
{
|
||||||
|
SetDisplay(ConfigManager.Target_Display.Value);
|
||||||
|
ConfigManager.Target_Display.OnValueChanged += SetDisplay;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void SetDisplay(int display)
|
||||||
|
{
|
||||||
|
if (ActiveDisplayIndex == display)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (Display.displays.Length <= display)
|
||||||
|
{
|
||||||
|
ExplorerCore.LogWarning($"Cannot set display index to {display} as there are not enough monitors connected!");
|
||||||
|
|
||||||
|
if (ConfigManager.Target_Display.Value == display)
|
||||||
|
ConfigManager.Target_Display.Value = 0;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ActiveDisplayIndex = display;
|
||||||
|
ActiveDisplay.Activate();
|
||||||
|
|
||||||
|
UIManager.UICanvas.targetDisplay = display;
|
||||||
|
|
||||||
|
// ensure a camera is targeting the display
|
||||||
|
if (!Camera.main || Camera.main.targetDisplay != display)
|
||||||
|
{
|
||||||
|
if (!canvasCamera)
|
||||||
|
{
|
||||||
|
canvasCamera = new GameObject("UnityExplorer_CanvasCamera").AddComponent<Camera>();
|
||||||
|
GameObject.DontDestroyOnLoad(canvasCamera.gameObject);
|
||||||
|
canvasCamera.hideFlags = HideFlags.HideAndDontSave;
|
||||||
|
}
|
||||||
|
canvasCamera.targetDisplay = display;
|
||||||
|
}
|
||||||
|
|
||||||
|
RuntimeHelper.StartCoroutine(FixPanels());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IEnumerator FixPanels()
|
||||||
|
{
|
||||||
|
yield return null;
|
||||||
|
yield return null;
|
||||||
|
|
||||||
|
foreach (var panel in UIManager.UIPanels.Values)
|
||||||
|
{
|
||||||
|
panel.EnsureValidSize();
|
||||||
|
panel.EnsureValidPosition();
|
||||||
|
panel.Dragger.OnEndResize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
55
src/UI/Notification.cs
Normal file
55
src/UI/Notification.cs
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
using UniverseLib.Input;
|
||||||
|
using UniverseLib.UI;
|
||||||
|
|
||||||
|
namespace UnityExplorer.UI
|
||||||
|
{
|
||||||
|
public static class Notification
|
||||||
|
{
|
||||||
|
private static Text popupLabel;
|
||||||
|
|
||||||
|
private static string _currentNotification;
|
||||||
|
private static float _timeOfLastNotification;
|
||||||
|
|
||||||
|
public static void Init()
|
||||||
|
{
|
||||||
|
ConstructUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ShowMessage(string message)
|
||||||
|
{
|
||||||
|
popupLabel.text = message;
|
||||||
|
_currentNotification = message;
|
||||||
|
_timeOfLastNotification = Time.realtimeSinceStartup;
|
||||||
|
|
||||||
|
popupLabel.transform.localPosition = UIManager.UIRootRect.InverseTransformPoint(DisplayManager.MousePosition) + (Vector3.up * 25);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Update()
|
||||||
|
{
|
||||||
|
if (_currentNotification != null)
|
||||||
|
{
|
||||||
|
if (Time.realtimeSinceStartup - _timeOfLastNotification > 2f)
|
||||||
|
{
|
||||||
|
_currentNotification = null;
|
||||||
|
popupLabel.text = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ConstructUI()
|
||||||
|
{
|
||||||
|
|
||||||
|
popupLabel = UIFactory.CreateLabel(UIManager.UIRoot, "ClipboardNotification", "", TextAnchor.MiddleCenter);
|
||||||
|
popupLabel.rectTransform.sizeDelta = new(500, 100);
|
||||||
|
popupLabel.gameObject.AddComponent<Outline>();
|
||||||
|
var popupGroup = popupLabel.gameObject.AddComponent<CanvasGroup>();
|
||||||
|
popupGroup.blocksRaycasts = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -5,12 +5,15 @@ using UnityEngine;
|
|||||||
using UnityEngine.EventSystems;
|
using UnityEngine.EventSystems;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UniverseLib.Input;
|
using UniverseLib.Input;
|
||||||
using UnityExplorer.Core.Runtime;
|
using UnityExplorer.Runtime;
|
||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
using UnityExplorer.UI.Panels;
|
using UnityExplorer.UI.Panels;
|
||||||
using UniverseLib.UI.Widgets;
|
using UniverseLib.UI.Widgets;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
|
using UniverseLib.UI.Widgets.ButtonList;
|
||||||
|
using UniverseLib.UI.Widgets.ScrollView;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Widgets.AutoComplete
|
namespace UnityExplorer.UI.Widgets.AutoComplete
|
||||||
{
|
{
|
||||||
@ -27,17 +30,17 @@ namespace UnityExplorer.UI.Widgets.AutoComplete
|
|||||||
public override int MinWidth => -1;
|
public override int MinWidth => -1;
|
||||||
public override int MinHeight => -1;
|
public override int MinHeight => -1;
|
||||||
|
|
||||||
public override bool CanDragAndResize => false;
|
public override bool CanDragAndResize => true;
|
||||||
public override bool ShouldSaveActiveState => false;
|
public override bool ShouldSaveActiveState => false;
|
||||||
public override bool NavButtonWanted => false;
|
public override bool NavButtonWanted => false;
|
||||||
|
|
||||||
public static ISuggestionProvider CurrentHandler { get; private set; }
|
public static ISuggestionProvider CurrentHandler { get; private set; }
|
||||||
|
|
||||||
public static ButtonListHandler<Suggestion, ButtonCell> dataHandler;
|
public static ButtonListHandler<Suggestion, ButtonCell> buttonListDataHandler;
|
||||||
public static ScrollPool<ButtonCell> scrollPool;
|
public static ScrollPool<ButtonCell> scrollPool;
|
||||||
private static GameObject navigationTipRow;
|
private static GameObject navigationTipRow;
|
||||||
|
|
||||||
private static List<Suggestion> Suggestions = new List<Suggestion>();
|
private static List<Suggestion> Suggestions = new();
|
||||||
private static int SelectedIndex = 0;
|
private static int SelectedIndex = 0;
|
||||||
|
|
||||||
public static Suggestion SelectedSuggestion => Suggestions[SelectedIndex];
|
public static Suggestion SelectedSuggestion => Suggestions[SelectedIndex];
|
||||||
@ -79,7 +82,7 @@ namespace UnityExplorer.UI.Widgets.AutoComplete
|
|||||||
{
|
{
|
||||||
base.UIRoot.SetActive(true);
|
base.UIRoot.SetActive(true);
|
||||||
base.UIRoot.transform.SetAsLastSibling();
|
base.UIRoot.transform.SetAsLastSibling();
|
||||||
dataHandler.RefreshData();
|
buttonListDataHandler.RefreshData();
|
||||||
scrollPool.Refresh(true, true);
|
scrollPool.Refresh(true, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -164,9 +167,7 @@ namespace UnityExplorer.UI.Widgets.AutoComplete
|
|||||||
if (!CurrentHandler.InputField.UIRoot.activeInHierarchy)
|
if (!CurrentHandler.InputField.UIRoot.activeInHierarchy)
|
||||||
ReleaseOwnership(CurrentHandler);
|
ReleaseOwnership(CurrentHandler);
|
||||||
else
|
else
|
||||||
{
|
|
||||||
UpdatePosition();
|
UpdatePosition();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -215,10 +216,10 @@ namespace UnityExplorer.UI.Widgets.AutoComplete
|
|||||||
scrollPool.Content.anchoredPosition = pos;
|
scrollPool.Content.anchoredPosition = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
RuntimeProvider.Instance.SetColorBlock(cell.Button.Component, selectedSuggestionColor);
|
RuntimeHelper.SetColorBlock(cell.Button.Component, selectedSuggestionColor);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
RuntimeProvider.Instance.SetColorBlock(cell.Button.Component, inactiveSuggestionColor);
|
RuntimeHelper.SetColorBlock(cell.Button.Component, inactiveSuggestionColor);
|
||||||
|
|
||||||
setFirstCell = true;
|
setFirstCell = true;
|
||||||
}
|
}
|
||||||
@ -228,9 +229,9 @@ namespace UnityExplorer.UI.Widgets.AutoComplete
|
|||||||
private int lastCaretPosition;
|
private int lastCaretPosition;
|
||||||
private Vector3 lastInputPosition;
|
private Vector3 lastInputPosition;
|
||||||
|
|
||||||
private void UpdatePosition()
|
internal void UpdatePosition()
|
||||||
{
|
{
|
||||||
if (CurrentHandler == null || !CurrentHandler.InputField.Component.isFocused)
|
if (CurrentHandler == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var input = CurrentHandler.InputField;
|
var input = CurrentHandler.InputField;
|
||||||
@ -249,15 +250,16 @@ namespace UnityExplorer.UI.Widgets.AutoComplete
|
|||||||
Vector3 caretPos = textGen.characters[caretIdx].cursorPos;
|
Vector3 caretPos = textGen.characters[caretIdx].cursorPos;
|
||||||
// transform to world point
|
// transform to world point
|
||||||
caretPos = input.UIRoot.transform.TransformPoint(caretPos);
|
caretPos = input.UIRoot.transform.TransformPoint(caretPos);
|
||||||
caretPos += new Vector3(input.Rect.rect.width * 0.5f, -(input.Rect.rect.height * 0.5f), 0);
|
caretPos += new Vector3(input.Transform.rect.width * 0.5f, -(input.Transform.rect.height * 0.5f), 0);
|
||||||
|
|
||||||
uiRoot.transform.position = new Vector3(caretPos.x + 10, caretPos.y - 30, 0);
|
uiRoot.transform.position = new Vector3(caretPos.x + 10, caretPos.y - 30, 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var textGen = input.Component.textComponent.cachedTextGenerator;
|
uiRoot.transform.position = input.Transform.position + new Vector3(-(input.Transform.rect.width / 2) + 10, -20, 0);
|
||||||
var pos = input.UIRoot.transform.TransformPoint(textGen.characters[0].cursorPos);
|
//var textGen = input.Component.textComponent.cachedTextGenerator;
|
||||||
uiRoot.transform.position = new Vector3(pos.x + 10, pos.y - 20, 0);
|
//var pos = input.UIRoot.transform.TransformPoint(textGen.characters[0].cursorPos);
|
||||||
|
//uiRoot.transform.position = new Vector3(pos.x + 10, pos.y - 20, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.Dragger.OnEndResize();
|
this.Dragger.OnEndResize();
|
||||||
@ -292,36 +294,49 @@ namespace UnityExplorer.UI.Widgets.AutoComplete
|
|||||||
|
|
||||||
// UI Construction
|
// UI Construction
|
||||||
|
|
||||||
|
const float MIN_X = 0.42f;
|
||||||
|
const float MAX_Y = 0.6f;
|
||||||
|
|
||||||
protected internal override void DoSetDefaultPosAndAnchors()
|
protected internal override void DoSetDefaultPosAndAnchors()
|
||||||
{
|
{
|
||||||
Rect.pivot = new Vector2(0f, 1f);
|
Rect.pivot = new Vector2(0f, 1f);
|
||||||
Rect.anchorMin = new Vector2(0.42f, 0.4f);
|
Rect.anchorMin = new Vector2(MIN_X, 0.4f);
|
||||||
Rect.anchorMax = new Vector2(0.68f, 0.6f);
|
Rect.anchorMax = new Vector2(0.68f, MAX_Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnFinishResize(RectTransform panel)
|
||||||
|
{
|
||||||
|
float xDiff = panel.anchorMin.x - MIN_X;
|
||||||
|
float yDiff = panel.anchorMax.y - MAX_Y;
|
||||||
|
|
||||||
|
if (xDiff != 0 || yDiff != 0)
|
||||||
|
{
|
||||||
|
panel.anchorMin = new(MIN_X, panel.anchorMin.y - yDiff);
|
||||||
|
panel.anchorMax = new(panel.anchorMax.x - xDiff, MAX_Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
base.OnFinishResize(panel);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void ConstructPanelContent()
|
public override void ConstructPanelContent()
|
||||||
{
|
{
|
||||||
dataHandler = new ButtonListHandler<Suggestion, ButtonCell>(scrollPool, GetEntries, SetCell, ShouldDisplay, OnCellClicked);
|
// hide the titlebar
|
||||||
|
this.TitleBar.gameObject.SetActive(false);
|
||||||
|
|
||||||
scrollPool = UIFactory.CreateScrollPool<ButtonCell>(this.content, "AutoCompleter", out GameObject scrollObj,
|
buttonListDataHandler = new ButtonListHandler<Suggestion, ButtonCell>(scrollPool, GetEntries, SetCell, ShouldDisplay, OnCellClicked);
|
||||||
|
|
||||||
|
scrollPool = UIFactory.CreateScrollPool<ButtonCell>(this.uiContent, "AutoCompleter", out GameObject scrollObj,
|
||||||
out GameObject scrollContent);
|
out GameObject scrollContent);
|
||||||
scrollPool.Initialize(dataHandler);
|
scrollPool.Initialize(buttonListDataHandler);
|
||||||
UIFactory.SetLayoutElement(scrollObj, flexibleHeight: 9999);
|
UIFactory.SetLayoutElement(scrollObj, flexibleHeight: 9999);
|
||||||
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(scrollContent, true, false, true, false);
|
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(scrollContent, true, false, true, false);
|
||||||
|
|
||||||
navigationTipRow = UIFactory.CreateHorizontalGroup(this.content, "BottomRow", true, true, true, true, 0, new Vector4(2, 2, 2, 2));
|
navigationTipRow = UIFactory.CreateHorizontalGroup(this.uiContent, "BottomRow", true, true, true, true, 0, new Vector4(2, 2, 2, 2));
|
||||||
UIFactory.SetLayoutElement(navigationTipRow, minHeight: 20, flexibleWidth: 9999);
|
UIFactory.SetLayoutElement(navigationTipRow, minHeight: 20, flexibleWidth: 9999);
|
||||||
UIFactory.CreateLabel(navigationTipRow, "HelpText", "Up/Down to select, Enter to use, Esc to close",
|
UIFactory.CreateLabel(navigationTipRow, "HelpText", "Up/Down to select, Enter to use, Esc to close",
|
||||||
TextAnchor.MiddleLeft, Color.grey, false, 13);
|
TextAnchor.MiddleLeft, Color.grey, false, 13);
|
||||||
|
|
||||||
UIRoot.SetActive(false);
|
UIRoot.SetActive(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void DoSaveToConfigElement()
|
|
||||||
{
|
|
||||||
// not savable
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string GetSaveDataFromConfigManager() => null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -6,11 +6,12 @@ using System.Text;
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.EventSystems;
|
using UnityEngine.EventSystems;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.Core.Config;
|
using UnityExplorer.Config;
|
||||||
using UnityExplorer.CSConsole;
|
using UnityExplorer.CSConsole;
|
||||||
using UnityExplorer.UI.Widgets;
|
using UnityExplorer.UI.Widgets;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
|
using UniverseLib.UI.Models;
|
||||||
using UniverseLib.UI.Widgets;
|
using UniverseLib.UI.Widgets;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Panels
|
namespace UnityExplorer.UI.Panels
|
||||||
@ -55,15 +56,6 @@ namespace UnityExplorer.UI.Panels
|
|||||||
ConsoleController.Update();
|
ConsoleController.Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Saving
|
|
||||||
|
|
||||||
public override void DoSaveToConfigElement()
|
|
||||||
{
|
|
||||||
ConfigManager.CSConsoleData.Value = this.ToSaveData();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string GetSaveDataFromConfigManager() => ConfigManager.CSConsoleData.Value;
|
|
||||||
|
|
||||||
// UI Construction
|
// UI Construction
|
||||||
|
|
||||||
public override void OnFinishResize(RectTransform panel)
|
public override void OnFinishResize(RectTransform panel)
|
||||||
@ -83,7 +75,7 @@ namespace UnityExplorer.UI.Panels
|
|||||||
{
|
{
|
||||||
// Tools Row
|
// Tools Row
|
||||||
|
|
||||||
var toolsRow = UIFactory.CreateHorizontalGroup(this.content, "ToggleRow", false, false, true, true, 5, new Vector4(8, 8, 10, 5),
|
var toolsRow = UIFactory.CreateHorizontalGroup(this.uiContent, "ToggleRow", false, false, true, true, 5, new Vector4(8, 8, 10, 5),
|
||||||
default, TextAnchor.MiddleLeft);
|
default, TextAnchor.MiddleLeft);
|
||||||
UIFactory.SetLayoutElement(toolsRow, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999);
|
UIFactory.SetLayoutElement(toolsRow, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999);
|
||||||
|
|
||||||
@ -101,7 +93,7 @@ namespace UnityExplorer.UI.Panels
|
|||||||
|
|
||||||
// Help dropdown
|
// Help dropdown
|
||||||
|
|
||||||
var helpDrop = UIFactory.CreateDropdown(toolsRow, out var dropdown, "Help", 14, null);
|
var helpDrop = UIFactory.CreateDropdown(toolsRow, "HelpDropdown", out var dropdown, "Help", 14, null);
|
||||||
UIFactory.SetLayoutElement(helpDrop, minHeight: 25, minWidth: 100);
|
UIFactory.SetLayoutElement(helpDrop, minHeight: 25, minWidth: 100);
|
||||||
HelpDropdown = dropdown;
|
HelpDropdown = dropdown;
|
||||||
HelpDropdown.onValueChanged.AddListener((int val) => { this.OnHelpDropdownChanged?.Invoke(val); });
|
HelpDropdown.onValueChanged.AddListener((int val) => { this.OnHelpDropdownChanged?.Invoke(val); });
|
||||||
@ -132,7 +124,7 @@ namespace UnityExplorer.UI.Panels
|
|||||||
|
|
||||||
// Console Input
|
// Console Input
|
||||||
|
|
||||||
var inputArea = UIFactory.CreateUIObject("InputGroup", content);
|
var inputArea = UIFactory.CreateUIObject("InputGroup", uiContent);
|
||||||
UIFactory.SetLayoutElement(inputArea, flexibleWidth: 9999, flexibleHeight: 9999);
|
UIFactory.SetLayoutElement(inputArea, flexibleWidth: 9999, flexibleHeight: 9999);
|
||||||
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(inputArea, false, true, true, true);
|
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(inputArea, false, true, true, true);
|
||||||
inputArea.AddComponent<Image>().color = Color.white;
|
inputArea.AddComponent<Image>().color = Color.white;
|
||||||
@ -199,7 +191,7 @@ namespace UnityExplorer.UI.Panels
|
|||||||
Input.PlaceholderText.font = UniversalUI.ConsoleFont;
|
Input.PlaceholderText.font = UniversalUI.ConsoleFont;
|
||||||
HighlightText.font = UniversalUI.ConsoleFont;
|
HighlightText.font = UniversalUI.ConsoleFont;
|
||||||
|
|
||||||
RuntimeProvider.Instance.StartCoroutine(DelayedLayoutSetup());
|
RuntimeHelper.StartCoroutine(DelayedLayoutSetup());
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerator DelayedLayoutSetup()
|
private IEnumerator DelayedLayoutSetup()
|
||||||
@ -210,8 +202,8 @@ namespace UnityExplorer.UI.Panels
|
|||||||
|
|
||||||
public void SetInputLayout()
|
public void SetInputLayout()
|
||||||
{
|
{
|
||||||
Input.Rect.offsetMin = new Vector2(52, Input.Rect.offsetMin.y);
|
Input.Transform.offsetMin = new Vector2(52, Input.Transform.offsetMin.y);
|
||||||
Input.Rect.offsetMax = new Vector2(2, Input.Rect.offsetMax.y);
|
Input.Transform.offsetMax = new Vector2(2, Input.Transform.offsetMax.y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
119
src/UI/Panels/ClipboardPanel.cs
Normal file
119
src/UI/Panels/ClipboardPanel.cs
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
using UnityExplorer.CacheObject;
|
||||||
|
using UnityExplorer.CacheObject.Views;
|
||||||
|
using UnityExplorer.Config;
|
||||||
|
using UniverseLib;
|
||||||
|
using UniverseLib.Input;
|
||||||
|
using UniverseLib.UI;
|
||||||
|
using UniverseLib.UI.Widgets;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
|
namespace UnityExplorer.UI.Panels
|
||||||
|
{
|
||||||
|
public class ClipboardPanel : UIPanel
|
||||||
|
{
|
||||||
|
public static object Current { get; private set; }
|
||||||
|
|
||||||
|
public override UIManager.Panels PanelType => UIManager.Panels.Clipboard;
|
||||||
|
public override string Name => "Clipboard";
|
||||||
|
public override int MinWidth => 500;
|
||||||
|
public override int MinHeight => 95;
|
||||||
|
public override bool CanDragAndResize => true;
|
||||||
|
public override bool NavButtonWanted => true;
|
||||||
|
public override bool ShouldSaveActiveState => true;
|
||||||
|
public override bool ShowByDefault => true;
|
||||||
|
|
||||||
|
private static Text CurrentPasteLabel;
|
||||||
|
|
||||||
|
public static void Copy(object obj)
|
||||||
|
{
|
||||||
|
Current = obj;
|
||||||
|
Notification.ShowMessage("Copied!");
|
||||||
|
UpdateCurrentPasteInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool TryPaste(Type targetType, out object paste)
|
||||||
|
{
|
||||||
|
paste = Current;
|
||||||
|
var pasteType = Current?.GetActualType();
|
||||||
|
|
||||||
|
if (Current != null && !targetType.IsAssignableFrom(pasteType))
|
||||||
|
{
|
||||||
|
Notification.ShowMessage($"Cannot assign '{pasteType.Name}' to '{targetType.Name}'!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Notification.ShowMessage("Pasted!");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ClearClipboard()
|
||||||
|
{
|
||||||
|
Current = null;
|
||||||
|
UpdateCurrentPasteInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void UpdateCurrentPasteInfo()
|
||||||
|
{
|
||||||
|
CurrentPasteLabel.text = ToStringUtility.ToStringWithType(Current, typeof(object), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void InspectClipboard()
|
||||||
|
{
|
||||||
|
if (Current.IsNullOrDestroyed())
|
||||||
|
{
|
||||||
|
Notification.ShowMessage("Cannot inspect a null or destroyed object!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
InspectorManager.Inspect(Current);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected internal override void DoSetDefaultPosAndAnchors()
|
||||||
|
{
|
||||||
|
this.Rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, MinWidth);
|
||||||
|
this.Rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, MinHeight);
|
||||||
|
this.Rect.anchorMin = new Vector2(0.1f, 0.05f);
|
||||||
|
this.Rect.anchorMax = new Vector2(0.4f, 0.15f);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void ConstructPanelContent()
|
||||||
|
{
|
||||||
|
this.UIRoot.GetComponent<Image>().color = new(0.1f, 0.1f, 0.1f);
|
||||||
|
|
||||||
|
// Actual panel content
|
||||||
|
|
||||||
|
var firstRow = UIFactory.CreateHorizontalGroup(uiContent, "FirstRow", false, false, true, true, 5, new(2,2,2,2), new(1,1,1,0));
|
||||||
|
UIFactory.SetLayoutElement(firstRow, minHeight: 25, flexibleWidth: 999);
|
||||||
|
|
||||||
|
// Title for "Current Paste:"
|
||||||
|
var currentPasteTitle = UIFactory.CreateLabel(firstRow, "CurrentPasteTitle", "Current paste:", TextAnchor.MiddleLeft, color: Color.grey);
|
||||||
|
UIFactory.SetLayoutElement(currentPasteTitle.gameObject, minHeight: 25, minWidth: 100, flexibleWidth: 999);
|
||||||
|
|
||||||
|
// Clear clipboard button
|
||||||
|
var clearButton = UIFactory.CreateButton(firstRow, "ClearPasteButton", "Clear Clipboard");
|
||||||
|
UIFactory.SetLayoutElement(clearButton.Component.gameObject, minWidth: 120, minHeight: 25, flexibleWidth: 0);
|
||||||
|
clearButton.OnClick += () => Copy(null);
|
||||||
|
|
||||||
|
// Current Paste info row
|
||||||
|
var currentPasteHolder = UIFactory.CreateHorizontalGroup(uiContent, "SecondRow", false, false, true, true, 0,
|
||||||
|
new(2, 2, 2, 2), childAlignment: TextAnchor.UpperCenter);
|
||||||
|
|
||||||
|
// Actual current paste info label
|
||||||
|
CurrentPasteLabel = UIFactory.CreateLabel(currentPasteHolder, "CurrentPasteInfo", "not set", TextAnchor.UpperLeft);
|
||||||
|
UIFactory.SetLayoutElement(CurrentPasteLabel.gameObject, minHeight: 25, minWidth: 100, flexibleWidth: 999, flexibleHeight: 999);
|
||||||
|
UpdateCurrentPasteInfo();
|
||||||
|
|
||||||
|
// Inspect button
|
||||||
|
var inspectButton = UIFactory.CreateButton(currentPasteHolder, "InspectButton", "Inspect");
|
||||||
|
UIFactory.SetLayoutElement(inspectButton.Component.gameObject, minHeight: 25, flexibleHeight: 0, minWidth: 80, flexibleWidth: 0);
|
||||||
|
inspectButton.OnClick += InspectClipboard;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -4,12 +4,14 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.Core.Config;
|
using UnityExplorer.Config;
|
||||||
using UnityExplorer.Hooks;
|
using UnityExplorer.Hooks;
|
||||||
using UnityExplorer.UI.Widgets;
|
using UnityExplorer.UI.Widgets;
|
||||||
using UnityExplorer.UI.Widgets.AutoComplete;
|
using UnityExplorer.UI.Widgets.AutoComplete;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
|
using UniverseLib.UI.Models;
|
||||||
using UniverseLib.UI.Widgets;
|
using UniverseLib.UI.Widgets;
|
||||||
|
using UniverseLib.UI.Widgets.ScrollView;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Panels
|
namespace UnityExplorer.UI.Panels
|
||||||
{
|
{
|
||||||
@ -46,10 +48,6 @@ namespace UnityExplorer.UI.Panels
|
|||||||
public Text EditorInputText { get; private set; }
|
public Text EditorInputText { get; private set; }
|
||||||
public Text EditorHighlightText { get; private set; }
|
public Text EditorHighlightText { get; private set; }
|
||||||
|
|
||||||
public override string GetSaveDataFromConfigManager() => ConfigManager.HookManagerData.Value;
|
|
||||||
|
|
||||||
public override void DoSaveToConfigElement() => ConfigManager.HookManagerData.Value = this.ToSaveData();
|
|
||||||
|
|
||||||
private void OnClassInputAddClicked()
|
private void OnClassInputAddClicked()
|
||||||
{
|
{
|
||||||
HookManager.Instance.OnClassSelectedForHooks(this.classSelectorInputField.Text);
|
HookManager.Instance.OnClassSelectedForHooks(this.classSelectorInputField.Text);
|
||||||
@ -85,7 +83,7 @@ namespace UnityExplorer.UI.Panels
|
|||||||
{
|
{
|
||||||
// ~~~~~~~~~ Active hooks scroll pool
|
// ~~~~~~~~~ Active hooks scroll pool
|
||||||
|
|
||||||
currentHooksPanel = UIFactory.CreateUIObject("CurrentHooksPanel", this.content);
|
currentHooksPanel = UIFactory.CreateUIObject("CurrentHooksPanel", this.uiContent);
|
||||||
UIFactory.SetLayoutElement(currentHooksPanel, flexibleHeight: 9999, flexibleWidth: 9999);
|
UIFactory.SetLayoutElement(currentHooksPanel, flexibleHeight: 9999, flexibleWidth: 9999);
|
||||||
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(currentHooksPanel, true, true, true, true);
|
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(currentHooksPanel, true, true, true, true);
|
||||||
|
|
||||||
@ -111,7 +109,7 @@ namespace UnityExplorer.UI.Panels
|
|||||||
|
|
||||||
// ~~~~~~~~~ Add hooks panel
|
// ~~~~~~~~~ Add hooks panel
|
||||||
|
|
||||||
addHooksPanel = UIFactory.CreateUIObject("AddHooksPanel", this.content);
|
addHooksPanel = UIFactory.CreateUIObject("AddHooksPanel", this.uiContent);
|
||||||
UIFactory.SetLayoutElement(addHooksPanel, flexibleHeight: 9999, flexibleWidth: 9999);
|
UIFactory.SetLayoutElement(addHooksPanel, flexibleHeight: 9999, flexibleWidth: 9999);
|
||||||
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(addHooksPanel, true, true, true, true);
|
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(addHooksPanel, true, true, true, true);
|
||||||
|
|
||||||
@ -138,7 +136,7 @@ namespace UnityExplorer.UI.Panels
|
|||||||
|
|
||||||
// ~~~~~~~~~ Hook source editor panel
|
// ~~~~~~~~~ Hook source editor panel
|
||||||
|
|
||||||
editorPanel = UIFactory.CreateUIObject("HookSourceEditor", this.content);
|
editorPanel = UIFactory.CreateUIObject("HookSourceEditor", this.uiContent);
|
||||||
UIFactory.SetLayoutElement(editorPanel, flexibleHeight: 9999, flexibleWidth: 9999);
|
UIFactory.SetLayoutElement(editorPanel, flexibleHeight: 9999, flexibleWidth: 9999);
|
||||||
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(editorPanel, true, true, true, true);
|
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(editorPanel, true, true, true, true);
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.Core.Config;
|
using UnityExplorer.Config;
|
||||||
using UnityExplorer.Inspectors;
|
using UnityExplorer.Inspectors;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
|
|
||||||
@ -24,6 +24,7 @@ namespace UnityExplorer.UI.Panels
|
|||||||
public override int MinHeight => 350;
|
public override int MinHeight => 350;
|
||||||
|
|
||||||
public GameObject NavbarHolder;
|
public GameObject NavbarHolder;
|
||||||
|
public Dropdown MouseInspectDropdown;
|
||||||
public GameObject ContentHolder;
|
public GameObject ContentHolder;
|
||||||
public RectTransform ContentRect;
|
public RectTransform ContentRect;
|
||||||
|
|
||||||
@ -43,13 +44,6 @@ namespace UnityExplorer.UI.Panels
|
|||||||
InspectorManager.OnPanelResized(panel.rect.width);
|
InspectorManager.OnPanelResized(panel.rect.width);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string GetSaveDataFromConfigManager() => ConfigManager.InspectorData.Value;
|
|
||||||
|
|
||||||
public override void DoSaveToConfigElement()
|
|
||||||
{
|
|
||||||
ConfigManager.InspectorData.Value = this.ToSaveData();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected internal override void DoSetDefaultPosAndAnchors()
|
protected internal override void DoSetDefaultPosAndAnchors()
|
||||||
{
|
{
|
||||||
Rect.localPosition = Vector2.zero;
|
Rect.localPosition = Vector2.zero;
|
||||||
@ -60,9 +54,21 @@ namespace UnityExplorer.UI.Panels
|
|||||||
|
|
||||||
public override void ConstructPanelContent()
|
public override void ConstructPanelContent()
|
||||||
{
|
{
|
||||||
|
var closeHolder = this.TitleBar.transform.Find("CloseHolder").gameObject;
|
||||||
|
|
||||||
|
// Inspect under mouse dropdown on title bar
|
||||||
|
|
||||||
|
var mouseDropdown = UIFactory.CreateDropdown(closeHolder, "MouseInspectDropdown", out MouseInspectDropdown, "Mouse Inspect", 14,
|
||||||
|
MouseInspector.OnDropdownSelect);
|
||||||
|
UIFactory.SetLayoutElement(mouseDropdown, minHeight: 25, minWidth: 140);
|
||||||
|
MouseInspectDropdown.options.Add(new Dropdown.OptionData("Mouse Inspect"));
|
||||||
|
MouseInspectDropdown.options.Add(new Dropdown.OptionData("World"));
|
||||||
|
MouseInspectDropdown.options.Add(new Dropdown.OptionData("UI"));
|
||||||
|
mouseDropdown.transform.SetSiblingIndex(0);
|
||||||
|
|
||||||
// add close all button to titlebar
|
// add close all button to titlebar
|
||||||
|
|
||||||
var closeAllBtn = UIFactory.CreateButton(this.titleBar.transform.Find("CloseHolder").gameObject, "CloseAllBtn", "Close All",
|
var closeAllBtn = UIFactory.CreateButton(closeHolder.gameObject, "CloseAllBtn", "Close All",
|
||||||
new Color(0.3f, 0.2f, 0.2f));
|
new Color(0.3f, 0.2f, 0.2f));
|
||||||
UIFactory.SetLayoutElement(closeAllBtn.Component.gameObject, minHeight: 25, minWidth: 80);
|
UIFactory.SetLayoutElement(closeAllBtn.Component.gameObject, minHeight: 25, minWidth: 80);
|
||||||
closeAllBtn.Component.transform.SetSiblingIndex(closeAllBtn.Component.transform.GetSiblingIndex() - 1);
|
closeAllBtn.Component.transform.SetSiblingIndex(closeAllBtn.Component.transform.GetSiblingIndex() - 1);
|
||||||
@ -70,14 +76,14 @@ namespace UnityExplorer.UI.Panels
|
|||||||
|
|
||||||
// this.UIRoot.GetComponent<Mask>().enabled = false;
|
// this.UIRoot.GetComponent<Mask>().enabled = false;
|
||||||
|
|
||||||
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(this.content, true, true, true, true, 4, padLeft: 5, padRight: 5);
|
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(this.uiContent, true, true, true, true, 4, padLeft: 5, padRight: 5);
|
||||||
|
|
||||||
this.NavbarHolder = UIFactory.CreateGridGroup(this.content, "Navbar", new Vector2(200, 22), new Vector2(4, 4),
|
this.NavbarHolder = UIFactory.CreateGridGroup(this.uiContent, "Navbar", new Vector2(200, 22), new Vector2(4, 4),
|
||||||
new Color(0.05f, 0.05f, 0.05f));
|
new Color(0.05f, 0.05f, 0.05f));
|
||||||
//UIFactory.SetLayoutElement(NavbarHolder, flexibleWidth: 9999, minHeight: 0, preferredHeight: 0, flexibleHeight: 9999);
|
//UIFactory.SetLayoutElement(NavbarHolder, flexibleWidth: 9999, minHeight: 0, preferredHeight: 0, flexibleHeight: 9999);
|
||||||
NavbarHolder.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
NavbarHolder.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||||||
|
|
||||||
this.ContentHolder = UIFactory.CreateVerticalGroup(this.content, "ContentHolder", true, true, true, true, 0, default,
|
this.ContentHolder = UIFactory.CreateVerticalGroup(this.uiContent, "ContentHolder", true, true, true, true, 0, default,
|
||||||
new Color(0.1f, 0.1f, 0.1f));
|
new Color(0.1f, 0.1f, 0.1f));
|
||||||
UIFactory.SetLayoutElement(ContentHolder, flexibleHeight: 9999);
|
UIFactory.SetLayoutElement(ContentHolder, flexibleHeight: 9999);
|
||||||
ContentRect = ContentHolder.GetComponent<RectTransform>();
|
ContentRect = ContentHolder.GetComponent<RectTransform>();
|
||||||
|
@ -6,11 +6,14 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.Core.Config;
|
using UnityExplorer.Config;
|
||||||
using UnityExplorer.UI.Widgets;
|
using UnityExplorer.UI.Widgets;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
|
using UniverseLib.UI.Models;
|
||||||
using UniverseLib.UI.Widgets;
|
using UniverseLib.UI.Widgets;
|
||||||
|
using UniverseLib.UI.Widgets.ScrollView;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Panels
|
namespace UnityExplorer.UI.Panels
|
||||||
{
|
{
|
||||||
@ -141,19 +144,7 @@ namespace UnityExplorer.UI.Panels
|
|||||||
cell.Input.Component.textComponent.color = logColors[log.type];
|
cell.Input.Component.textComponent.color = logColors[log.type];
|
||||||
|
|
||||||
var color = index % 2 == 0 ? logEvenColor : logOddColor;
|
var color = index % 2 == 0 ? logEvenColor : logOddColor;
|
||||||
RuntimeProvider.Instance.SetColorBlock(cell.Input.Component, color);
|
RuntimeHelper.SetColorBlock(cell.Input.Component, color);
|
||||||
}
|
|
||||||
|
|
||||||
// Panel save data
|
|
||||||
|
|
||||||
public override string GetSaveDataFromConfigManager()
|
|
||||||
{
|
|
||||||
return ConfigManager.ConsoleLogData.Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void DoSaveToConfigElement()
|
|
||||||
{
|
|
||||||
ConfigManager.ConsoleLogData.Value = this.ToSaveData();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected internal override void DoSetDefaultPosAndAnchors()
|
protected internal override void DoSetDefaultPosAndAnchors()
|
||||||
@ -170,13 +161,13 @@ namespace UnityExplorer.UI.Panels
|
|||||||
{
|
{
|
||||||
// Log scroll pool
|
// Log scroll pool
|
||||||
|
|
||||||
logScrollPool = UIFactory.CreateScrollPool<ConsoleLogCell>(this.content, "Logs", out GameObject scrollObj,
|
logScrollPool = UIFactory.CreateScrollPool<ConsoleLogCell>(this.uiContent, "Logs", out GameObject scrollObj,
|
||||||
out GameObject scrollContent, new Color(0.03f, 0.03f, 0.03f));
|
out GameObject scrollContent, new Color(0.03f, 0.03f, 0.03f));
|
||||||
UIFactory.SetLayoutElement(scrollObj, flexibleWidth: 9999, flexibleHeight: 9999);
|
UIFactory.SetLayoutElement(scrollObj, flexibleWidth: 9999, flexibleHeight: 9999);
|
||||||
|
|
||||||
// Buttons and toggles
|
// Buttons and toggles
|
||||||
|
|
||||||
var optionsRow = UIFactory.CreateUIObject("OptionsRow", this.content);
|
var optionsRow = UIFactory.CreateUIObject("OptionsRow", this.uiContent);
|
||||||
UIFactory.SetLayoutElement(optionsRow, minHeight: 25, flexibleWidth: 9999);
|
UIFactory.SetLayoutElement(optionsRow, minHeight: 25, flexibleWidth: 9999);
|
||||||
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(optionsRow, false, false, true, true, 5, 2, 2, 2, 2);
|
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(optionsRow, false, false, true, true, 5, 2, 2, 2, 2);
|
||||||
|
|
||||||
@ -229,7 +220,7 @@ namespace UnityExplorer.UI.Panels
|
|||||||
Input = UIFactory.CreateInputField(UIRoot, "Input", "");
|
Input = UIFactory.CreateInputField(UIRoot, "Input", "");
|
||||||
//Input.Component.gameObject.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
//Input.Component.gameObject.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||||||
UIFactory.SetLayoutElement(Input.UIRoot, minHeight: 25, flexibleWidth: 9999);
|
UIFactory.SetLayoutElement(Input.UIRoot, minHeight: 25, flexibleWidth: 9999);
|
||||||
RuntimeProvider.Instance.SetColorBlock(Input.Component, new Color(0.1f, 0.1f, 0.1f), new Color(0.13f, 0.13f, 0.13f),
|
RuntimeHelper.SetColorBlock(Input.Component, new Color(0.1f, 0.1f, 0.1f), new Color(0.13f, 0.13f, 0.13f),
|
||||||
new Color(0.07f, 0.07f, 0.07f));
|
new Color(0.07f, 0.07f, 0.07f));
|
||||||
Input.Component.GetComponent<Image>().color = new Color(0.2f, 0.2f, 0.2f);
|
Input.Component.GetComponent<Image>().color = new Color(0.2f, 0.2f, 0.2f);
|
||||||
|
|
||||||
|
@ -8,8 +8,7 @@ using System.Text;
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.SceneManagement;
|
using UnityEngine.SceneManagement;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.Core;
|
using UnityExplorer.Config;
|
||||||
using UnityExplorer.Core.Config;
|
|
||||||
using UniverseLib.UI.Models;
|
using UniverseLib.UI.Models;
|
||||||
using UnityExplorer.ObjectExplorer;
|
using UnityExplorer.ObjectExplorer;
|
||||||
using UnityExplorer.UI.Widgets;
|
using UnityExplorer.UI.Widgets;
|
||||||
@ -44,16 +43,16 @@ namespace UnityExplorer.UI.Panels
|
|||||||
content.SetActive(true);
|
content.SetActive(true);
|
||||||
|
|
||||||
var button = tabButtons[tabIndex];
|
var button = tabButtons[tabIndex];
|
||||||
RuntimeProvider.Instance.SetColorBlock(button.Component, UniversalUI.enabledButtonColor, UniversalUI.enabledButtonColor * 1.2f);
|
RuntimeHelper.SetColorBlock(button.Component, UniversalUI.EnabledButtonColor, UniversalUI.EnabledButtonColor * 1.2f);
|
||||||
|
|
||||||
SelectedTab = tabIndex;
|
SelectedTab = tabIndex;
|
||||||
SaveToConfigManager();
|
SaveInternalData();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DisableTab(int tabIndex)
|
private void DisableTab(int tabIndex)
|
||||||
{
|
{
|
||||||
tabPages[tabIndex].SetActive(false);
|
tabPages[tabIndex].SetActive(false);
|
||||||
RuntimeProvider.Instance.SetColorBlock(tabButtons[tabIndex].Component, UniversalUI.disabledButtonColor, UniversalUI.disabledButtonColor * 1.2f);
|
RuntimeHelper.SetColorBlock(tabButtons[tabIndex].Component, UniversalUI.DisabledButtonColor, UniversalUI.DisabledButtonColor * 1.2f);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Update()
|
public override void Update()
|
||||||
@ -64,21 +63,12 @@ namespace UnityExplorer.UI.Panels
|
|||||||
ObjectSearch.Update();
|
ObjectSearch.Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string GetSaveDataFromConfigManager() => ConfigManager.ObjectExplorerData.Value;
|
|
||||||
|
|
||||||
public override void DoSaveToConfigElement()
|
|
||||||
{
|
|
||||||
ConfigManager.ObjectExplorerData.Value = this.ToSaveData();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToSaveData()
|
public override string ToSaveData()
|
||||||
{
|
{
|
||||||
string ret = base.ToSaveData();
|
return string.Join("|", new string[] { base.ToSaveData(), SelectedTab.ToString() });
|
||||||
ret += "|" + SelectedTab;
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void ApplySaveData(string data)
|
protected override void ApplySaveData(string data)
|
||||||
{
|
{
|
||||||
base.ApplySaveData(data);
|
base.ApplySaveData(data);
|
||||||
|
|
||||||
@ -109,17 +99,17 @@ namespace UnityExplorer.UI.Panels
|
|||||||
public override void ConstructPanelContent()
|
public override void ConstructPanelContent()
|
||||||
{
|
{
|
||||||
// Tab bar
|
// Tab bar
|
||||||
var tabGroup = UIFactory.CreateHorizontalGroup(content, "TabBar", true, true, true, true, 2, new Vector4(2, 2, 2, 2));
|
var tabGroup = UIFactory.CreateHorizontalGroup(uiContent, "TabBar", true, true, true, true, 2, new Vector4(2, 2, 2, 2));
|
||||||
UIFactory.SetLayoutElement(tabGroup, minHeight: 25, flexibleHeight: 0);
|
UIFactory.SetLayoutElement(tabGroup, minHeight: 25, flexibleHeight: 0);
|
||||||
|
|
||||||
// Scene Explorer
|
// Scene Explorer
|
||||||
SceneExplorer = new SceneExplorer(this);
|
SceneExplorer = new SceneExplorer(this);
|
||||||
SceneExplorer.ConstructUI(content);
|
SceneExplorer.ConstructUI(uiContent);
|
||||||
tabPages.Add(SceneExplorer);
|
tabPages.Add(SceneExplorer);
|
||||||
|
|
||||||
// Object search
|
// Object search
|
||||||
ObjectSearch = new ObjectSearch(this);
|
ObjectSearch = new ObjectSearch(this);
|
||||||
ObjectSearch.ConstructUI(content);
|
ObjectSearch.ConstructUI(uiContent);
|
||||||
tabPages.Add(ObjectSearch);
|
tabPages.Add(ObjectSearch);
|
||||||
|
|
||||||
// set up tabs
|
// set up tabs
|
||||||
|
@ -4,12 +4,13 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.Core.Config;
|
using UnityExplorer.Config;
|
||||||
using UnityExplorer.CacheObject;
|
using UnityExplorer.CacheObject;
|
||||||
using UnityExplorer.CacheObject.Views;
|
using UnityExplorer.CacheObject.Views;
|
||||||
using UnityExplorer.UI.Widgets;
|
using UnityExplorer.UI.Widgets;
|
||||||
using UniverseLib.UI.Widgets;
|
using UniverseLib.UI.Widgets;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
|
using UniverseLib.UI.Widgets.ScrollView;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Panels
|
namespace UnityExplorer.UI.Panels
|
||||||
{
|
{
|
||||||
@ -55,17 +56,7 @@ namespace UnityExplorer.UI.Panels
|
|||||||
CacheObjectControllerHelper.SetCell(cell, index, this.configEntries, null);
|
CacheObjectControllerHelper.SetCell(cell, index, this.configEntries, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Panel save data
|
// UI Construction
|
||||||
|
|
||||||
public override string GetSaveDataFromConfigManager()
|
|
||||||
{
|
|
||||||
return ConfigManager.OptionsPanelData.Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void DoSaveToConfigElement()
|
|
||||||
{
|
|
||||||
ConfigManager.OptionsPanelData.Value = this.ToSaveData();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected internal override void DoSetDefaultPosAndAnchors()
|
protected internal override void DoSetDefaultPosAndAnchors()
|
||||||
{
|
{
|
||||||
@ -76,19 +67,17 @@ namespace UnityExplorer.UI.Panels
|
|||||||
Rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, 600f);
|
Rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, 600f);
|
||||||
}
|
}
|
||||||
|
|
||||||
// UI Construction
|
|
||||||
|
|
||||||
public override void ConstructPanelContent()
|
public override void ConstructPanelContent()
|
||||||
{
|
{
|
||||||
// Save button
|
// Save button
|
||||||
|
|
||||||
var saveBtn = UIFactory.CreateButton(this.content, "Save", "Save Options", new Color(0.2f, 0.3f, 0.2f));
|
var saveBtn = UIFactory.CreateButton(this.uiContent, "Save", "Save Options", new Color(0.2f, 0.3f, 0.2f));
|
||||||
UIFactory.SetLayoutElement(saveBtn.Component.gameObject, flexibleWidth: 9999, minHeight: 30, flexibleHeight: 0);
|
UIFactory.SetLayoutElement(saveBtn.Component.gameObject, flexibleWidth: 9999, minHeight: 30, flexibleHeight: 0);
|
||||||
saveBtn.OnClick += ConfigManager.Handler.SaveConfig;
|
saveBtn.OnClick += ConfigManager.Handler.SaveConfig;
|
||||||
|
|
||||||
// Config entries
|
// Config entries
|
||||||
|
|
||||||
var scrollPool = UIFactory.CreateScrollPool<ConfigEntryCell>(this.content, "ConfigEntries", out GameObject scrollObj,
|
var scrollPool = UIFactory.CreateScrollPool<ConfigEntryCell>(this.uiContent, "ConfigEntries", out GameObject scrollObj,
|
||||||
out GameObject scrollContent);
|
out GameObject scrollContent);
|
||||||
|
|
||||||
scrollPool.Initialize(this);
|
scrollPool.Initialize(this);
|
||||||
|
@ -10,20 +10,39 @@ using UniverseLib.UI.Models;
|
|||||||
using UnityExplorer.UI.Widgets.AutoComplete;
|
using UnityExplorer.UI.Widgets.AutoComplete;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Panels
|
namespace UnityExplorer.UI.Panels
|
||||||
{
|
{
|
||||||
public class PanelDragger
|
public class PanelDragger
|
||||||
{
|
{
|
||||||
|
private enum MouseState
|
||||||
|
{
|
||||||
|
Down,
|
||||||
|
Held,
|
||||||
|
NotPressed
|
||||||
|
}
|
||||||
|
|
||||||
#region Static
|
#region Static
|
||||||
|
|
||||||
public static bool Resizing { get; private set; }
|
public static bool Resizing { get; private set; }
|
||||||
|
public static bool ResizePrompting => resizeCursorObj && resizeCursorObj.activeSelf;
|
||||||
|
|
||||||
public static bool ResizePrompting => s_resizeCursorObj && s_resizeCursorObj.activeSelf;
|
public static GameObject resizeCursorObj;
|
||||||
|
internal static bool wasAnyDragging;
|
||||||
|
|
||||||
|
internal static List<PanelDragger> Instances = new();
|
||||||
|
|
||||||
|
private static bool handledInstanceThisFrame;
|
||||||
|
|
||||||
|
static PanelDragger()
|
||||||
|
{
|
||||||
|
UIPanel.OnPanelsReordered += OnPanelsReordered;
|
||||||
|
}
|
||||||
|
|
||||||
internal static void ForceEnd()
|
internal static void ForceEnd()
|
||||||
{
|
{
|
||||||
s_resizeCursorObj.SetActive(false);
|
resizeCursorObj.SetActive(false);
|
||||||
wasAnyDragging = false;
|
wasAnyDragging = false;
|
||||||
Resizing = false;
|
Resizing = false;
|
||||||
|
|
||||||
@ -34,13 +53,6 @@ namespace UnityExplorer.UI.Panels
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static List<PanelDragger> Instances = new List<PanelDragger>();
|
|
||||||
|
|
||||||
static PanelDragger()
|
|
||||||
{
|
|
||||||
UIPanel.OnPanelsReordered += OnPanelsReordered;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void OnPanelsReordered()
|
public static void OnPanelsReordered()
|
||||||
{
|
{
|
||||||
Instances.Sort((a, b) => b.Panel.GetSiblingIndex().CompareTo(a.Panel.GetSiblingIndex()));
|
Instances.Sort((a, b) => b.Panel.GetSiblingIndex().CompareTo(a.Panel.GetSiblingIndex()));
|
||||||
@ -54,18 +66,12 @@ namespace UnityExplorer.UI.Panels
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private enum MouseState
|
|
||||||
{
|
|
||||||
Down,
|
|
||||||
Held,
|
|
||||||
NotPressed
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool handledInstanceThisFrame;
|
|
||||||
|
|
||||||
public static void UpdateInstances()
|
public static void UpdateInstances()
|
||||||
{
|
{
|
||||||
if (!s_resizeCursorObj)
|
if (!DisplayManager.MouseInTargetDisplay)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!resizeCursorObj)
|
||||||
CreateCursorUI();
|
CreateCursorUI();
|
||||||
|
|
||||||
MouseState state;
|
MouseState state;
|
||||||
@ -76,7 +82,7 @@ namespace UnityExplorer.UI.Panels
|
|||||||
else
|
else
|
||||||
state = MouseState.NotPressed;
|
state = MouseState.NotPressed;
|
||||||
|
|
||||||
var mousePos = InputManager.MousePosition;
|
var mousePos = DisplayManager.MousePosition;
|
||||||
|
|
||||||
handledInstanceThisFrame = false;
|
handledInstanceThisFrame = false;
|
||||||
foreach (var instance in Instances)
|
foreach (var instance in Instances)
|
||||||
@ -99,10 +105,6 @@ namespace UnityExplorer.UI.Panels
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
public static GameObject s_resizeCursorObj;
|
|
||||||
|
|
||||||
internal static bool wasAnyDragging;
|
|
||||||
|
|
||||||
// Instance
|
// Instance
|
||||||
|
|
||||||
public UIPanel UIPanel { get; private set; }
|
public UIPanel UIPanel { get; private set; }
|
||||||
@ -112,27 +114,23 @@ namespace UnityExplorer.UI.Panels
|
|||||||
public event Action<RectTransform> OnFinishResize;
|
public event Action<RectTransform> OnFinishResize;
|
||||||
public event Action<RectTransform> OnFinishDrag;
|
public event Action<RectTransform> OnFinishDrag;
|
||||||
|
|
||||||
private readonly RectTransform canvasTransform;
|
|
||||||
|
|
||||||
// Dragging
|
// Dragging
|
||||||
public RectTransform DragableArea { get; set; }
|
public RectTransform DragableArea { get; set; }
|
||||||
public bool WasDragging { get; set; }
|
public bool WasDragging { get; set; }
|
||||||
private Vector2 m_lastDragPosition;
|
private Vector2 lastDragPosition;
|
||||||
|
|
||||||
// Resizing
|
// Resizing
|
||||||
private const int RESIZE_THICKNESS = 10;
|
private const int RESIZE_THICKNESS = 10;
|
||||||
|
|
||||||
//internal readonly Vector2 minResize = new Vector2(200, 50);
|
|
||||||
|
|
||||||
private bool WasResizing { get; set; }
|
private bool WasResizing { get; set; }
|
||||||
private ResizeTypes m_currentResizeType = ResizeTypes.NONE;
|
private ResizeTypes currentResizeType = ResizeTypes.NONE;
|
||||||
private Vector2 m_lastResizePos;
|
private Vector2 lastResizePos;
|
||||||
|
|
||||||
private bool WasHoveringResize => s_resizeCursorObj.activeInHierarchy;
|
private bool WasHoveringResize => resizeCursorObj.activeInHierarchy;
|
||||||
|
|
||||||
private ResizeTypes m_lastResizeHoverType;
|
private ResizeTypes lastResizeHoverType;
|
||||||
|
|
||||||
private Rect m_totalResizeRect;
|
private Rect totalResizeRect;
|
||||||
|
|
||||||
public PanelDragger(RectTransform dragArea, RectTransform panelToDrag, UIPanel panel)
|
public PanelDragger(RectTransform dragArea, RectTransform panelToDrag, UIPanel panel)
|
||||||
{
|
{
|
||||||
@ -141,16 +139,13 @@ namespace UnityExplorer.UI.Panels
|
|||||||
DragableArea = dragArea;
|
DragableArea = dragArea;
|
||||||
Panel = panelToDrag;
|
Panel = panelToDrag;
|
||||||
|
|
||||||
if (!canvasTransform)
|
|
||||||
canvasTransform = Panel.GetComponentInParent<Canvas>().GetComponent<RectTransform>();
|
|
||||||
|
|
||||||
UpdateResizeCache();
|
UpdateResizeCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Destroy()
|
public void Destroy()
|
||||||
{
|
{
|
||||||
if (s_resizeCursorObj)
|
if (resizeCursorObj)
|
||||||
GameObject.Destroy(s_resizeCursorObj);
|
GameObject.Destroy(resizeCursorObj);
|
||||||
|
|
||||||
if (Instances.Contains(this))
|
if (Instances.Contains(this))
|
||||||
Instances.Remove(this);
|
Instances.Remove(this);
|
||||||
@ -166,7 +161,7 @@ namespace UnityExplorer.UI.Panels
|
|||||||
Vector3 dragPos = DragableArea.InverseTransformPoint(rawMousePos);
|
Vector3 dragPos = DragableArea.InverseTransformPoint(rawMousePos);
|
||||||
bool inDragPos = DragableArea.rect.Contains(dragPos);
|
bool inDragPos = DragableArea.rect.Contains(dragPos);
|
||||||
|
|
||||||
if (WasHoveringResize && s_resizeCursorObj)
|
if (WasHoveringResize && resizeCursorObj)
|
||||||
UpdateHoverImagePos();
|
UpdateHoverImagePos();
|
||||||
|
|
||||||
switch (state)
|
switch (state)
|
||||||
@ -243,15 +238,15 @@ namespace UnityExplorer.UI.Panels
|
|||||||
{
|
{
|
||||||
wasAnyDragging = true;
|
wasAnyDragging = true;
|
||||||
WasDragging = true;
|
WasDragging = true;
|
||||||
m_lastDragPosition = InputManager.MousePosition;
|
lastDragPosition = DisplayManager.MousePosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnDrag()
|
public void OnDrag()
|
||||||
{
|
{
|
||||||
var mousePos = InputManager.MousePosition;
|
var mousePos = DisplayManager.MousePosition;
|
||||||
|
|
||||||
Vector2 diff = (Vector2)mousePos - m_lastDragPosition;
|
Vector2 diff = (Vector2)mousePos - lastDragPosition;
|
||||||
m_lastDragPosition = mousePos;
|
lastDragPosition = mousePos;
|
||||||
|
|
||||||
Panel.localPosition = Panel.localPosition + (Vector3)diff;
|
Panel.localPosition = Panel.localPosition + (Vector3)diff;
|
||||||
|
|
||||||
@ -269,7 +264,7 @@ namespace UnityExplorer.UI.Panels
|
|||||||
|
|
||||||
#region RESIZE
|
#region RESIZE
|
||||||
|
|
||||||
private readonly Dictionary<ResizeTypes, Rect> m_resizeMask = new Dictionary<ResizeTypes, Rect>
|
private readonly Dictionary<ResizeTypes, Rect> m_resizeMask = new()
|
||||||
{
|
{
|
||||||
{ ResizeTypes.Top, default },
|
{ ResizeTypes.Top, default },
|
||||||
{ ResizeTypes.Left, default },
|
{ ResizeTypes.Left, default },
|
||||||
@ -296,7 +291,7 @@ namespace UnityExplorer.UI.Panels
|
|||||||
|
|
||||||
private void UpdateResizeCache()
|
private void UpdateResizeCache()
|
||||||
{
|
{
|
||||||
m_totalResizeRect = new Rect(Panel.rect.x - RESIZE_THICKNESS + 1,
|
totalResizeRect = new Rect(Panel.rect.x - RESIZE_THICKNESS + 1,
|
||||||
Panel.rect.y - RESIZE_THICKNESS + 1,
|
Panel.rect.y - RESIZE_THICKNESS + 1,
|
||||||
Panel.rect.width + DBL_THICKESS - 2,
|
Panel.rect.width + DBL_THICKESS - 2,
|
||||||
Panel.rect.height + DBL_THICKESS - 2);
|
Panel.rect.height + DBL_THICKESS - 2);
|
||||||
@ -305,34 +300,34 @@ namespace UnityExplorer.UI.Panels
|
|||||||
if (AllowDragAndResize)
|
if (AllowDragAndResize)
|
||||||
{
|
{
|
||||||
m_resizeMask[ResizeTypes.Bottom] = new Rect(
|
m_resizeMask[ResizeTypes.Bottom] = new Rect(
|
||||||
m_totalResizeRect.x,
|
totalResizeRect.x,
|
||||||
m_totalResizeRect.y,
|
totalResizeRect.y,
|
||||||
m_totalResizeRect.width,
|
totalResizeRect.width,
|
||||||
RESIZE_THICKNESS);
|
RESIZE_THICKNESS);
|
||||||
|
|
||||||
m_resizeMask[ResizeTypes.Left] = new Rect(
|
m_resizeMask[ResizeTypes.Left] = new Rect(
|
||||||
m_totalResizeRect.x,
|
totalResizeRect.x,
|
||||||
m_totalResizeRect.y,
|
totalResizeRect.y,
|
||||||
RESIZE_THICKNESS,
|
RESIZE_THICKNESS,
|
||||||
m_totalResizeRect.height);
|
totalResizeRect.height);
|
||||||
|
|
||||||
m_resizeMask[ResizeTypes.Top] = new Rect(
|
m_resizeMask[ResizeTypes.Top] = new Rect(
|
||||||
m_totalResizeRect.x,
|
totalResizeRect.x,
|
||||||
Panel.rect.y + Panel.rect.height - 2,
|
Panel.rect.y + Panel.rect.height - 2,
|
||||||
m_totalResizeRect.width,
|
totalResizeRect.width,
|
||||||
RESIZE_THICKNESS);
|
RESIZE_THICKNESS);
|
||||||
|
|
||||||
m_resizeMask[ResizeTypes.Right] = new Rect(
|
m_resizeMask[ResizeTypes.Right] = new Rect(
|
||||||
m_totalResizeRect.x + Panel.rect.width + RESIZE_THICKNESS - 2,
|
totalResizeRect.x + Panel.rect.width + RESIZE_THICKNESS - 2,
|
||||||
m_totalResizeRect.y,
|
totalResizeRect.y,
|
||||||
RESIZE_THICKNESS,
|
RESIZE_THICKNESS,
|
||||||
m_totalResizeRect.height);
|
totalResizeRect.height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool MouseInResizeArea(Vector2 mousePos)
|
private bool MouseInResizeArea(Vector2 mousePos)
|
||||||
{
|
{
|
||||||
return m_totalResizeRect.Contains(mousePos);
|
return totalResizeRect.Contains(mousePos);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ResizeTypes GetResizeType(Vector2 mousePos)
|
private ResizeTypes GetResizeType(Vector2 mousePos)
|
||||||
@ -361,16 +356,16 @@ namespace UnityExplorer.UI.Panels
|
|||||||
|
|
||||||
public void OnHoverResize(ResizeTypes resizeType)
|
public void OnHoverResize(ResizeTypes resizeType)
|
||||||
{
|
{
|
||||||
if (WasHoveringResize && m_lastResizeHoverType == resizeType)
|
if (WasHoveringResize && lastResizeHoverType == resizeType)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// we are entering resize, or the resize type has changed.
|
// we are entering resize, or the resize type has changed.
|
||||||
|
|
||||||
//WasHoveringResize = true;
|
//WasHoveringResize = true;
|
||||||
m_lastResizeHoverType = resizeType;
|
lastResizeHoverType = resizeType;
|
||||||
|
|
||||||
s_resizeCursorObj.SetActive(true);
|
resizeCursorObj.SetActive(true);
|
||||||
s_resizeCursorObj.transform.SetAsLastSibling();
|
resizeCursorObj.transform.SetAsLastSibling();
|
||||||
|
|
||||||
// set the rotation for the resize icon
|
// set the rotation for the resize icon
|
||||||
float iconRotation = 0f;
|
float iconRotation = 0f;
|
||||||
@ -387,9 +382,9 @@ namespace UnityExplorer.UI.Panels
|
|||||||
iconRotation = 135f; break;
|
iconRotation = 135f; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Quaternion rot = s_resizeCursorObj.transform.rotation;
|
Quaternion rot = resizeCursorObj.transform.rotation;
|
||||||
rot.eulerAngles = new Vector3(0, 0, iconRotation);
|
rot.eulerAngles = new Vector3(0, 0, iconRotation);
|
||||||
s_resizeCursorObj.transform.rotation = rot;
|
resizeCursorObj.transform.rotation = rot;
|
||||||
|
|
||||||
UpdateHoverImagePos();
|
UpdateHoverImagePos();
|
||||||
}
|
}
|
||||||
@ -397,50 +392,50 @@ namespace UnityExplorer.UI.Panels
|
|||||||
// update the resize icon position to be above the mouse
|
// update the resize icon position to be above the mouse
|
||||||
private void UpdateHoverImagePos()
|
private void UpdateHoverImagePos()
|
||||||
{
|
{
|
||||||
s_resizeCursorObj.transform.localPosition = canvasTransform.InverseTransformPoint(InputManager.MousePosition);
|
resizeCursorObj.transform.localPosition = UIManager.UIRootRect.InverseTransformPoint(DisplayManager.MousePosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnHoverResizeEnd()
|
public void OnHoverResizeEnd()
|
||||||
{
|
{
|
||||||
//WasHoveringResize = false;
|
//WasHoveringResize = false;
|
||||||
s_resizeCursorObj.SetActive(false);
|
resizeCursorObj.SetActive(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnBeginResize(ResizeTypes resizeType)
|
public void OnBeginResize(ResizeTypes resizeType)
|
||||||
{
|
{
|
||||||
m_currentResizeType = resizeType;
|
currentResizeType = resizeType;
|
||||||
m_lastResizePos = InputManager.MousePosition;
|
lastResizePos = DisplayManager.MousePosition;
|
||||||
WasResizing = true;
|
WasResizing = true;
|
||||||
Resizing = true;
|
Resizing = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnResize()
|
public void OnResize()
|
||||||
{
|
{
|
||||||
Vector3 mousePos = InputManager.MousePosition;
|
Vector3 mousePos = DisplayManager.MousePosition;
|
||||||
Vector2 diff = m_lastResizePos - (Vector2)mousePos;
|
Vector2 diff = lastResizePos - (Vector2)mousePos;
|
||||||
|
|
||||||
if ((Vector2)mousePos == m_lastResizePos)
|
if ((Vector2)mousePos == lastResizePos)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (mousePos.x < 0 || mousePos.y < 0 || mousePos.x > Screen.width || mousePos.y > Screen.height)
|
if (mousePos.x < 0 || mousePos.y < 0 || mousePos.x > DisplayManager.Width || mousePos.y > DisplayManager.Height)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_lastResizePos = mousePos;
|
lastResizePos = mousePos;
|
||||||
|
|
||||||
float diffX = (float)((decimal)diff.x / Screen.width);
|
float diffX = (float)((decimal)diff.x / DisplayManager.Width);
|
||||||
float diffY = (float)((decimal)diff.y / Screen.height);
|
float diffY = (float)((decimal)diff.y / DisplayManager.Height);
|
||||||
|
|
||||||
Vector2 anchorMin = Panel.anchorMin;
|
Vector2 anchorMin = Panel.anchorMin;
|
||||||
Vector2 anchorMax = Panel.anchorMax;
|
Vector2 anchorMax = Panel.anchorMax;
|
||||||
|
|
||||||
if (m_currentResizeType.HasFlag(ResizeTypes.Left))
|
if (currentResizeType.HasFlag(ResizeTypes.Left))
|
||||||
anchorMin.x -= diffX;
|
anchorMin.x -= diffX;
|
||||||
else if (m_currentResizeType.HasFlag(ResizeTypes.Right))
|
else if (currentResizeType.HasFlag(ResizeTypes.Right))
|
||||||
anchorMax.x -= diffX;
|
anchorMax.x -= diffX;
|
||||||
|
|
||||||
if (m_currentResizeType.HasFlag(ResizeTypes.Top))
|
if (currentResizeType.HasFlag(ResizeTypes.Top))
|
||||||
anchorMax.y -= diffY;
|
anchorMax.y -= diffY;
|
||||||
else if (m_currentResizeType.HasFlag(ResizeTypes.Bottom))
|
else if (currentResizeType.HasFlag(ResizeTypes.Bottom))
|
||||||
anchorMin.y -= diffY;
|
anchorMin.y -= diffY;
|
||||||
|
|
||||||
var prevMin = Panel.anchorMin;
|
var prevMin = Panel.anchorMin;
|
||||||
@ -475,13 +470,16 @@ namespace UnityExplorer.UI.Panels
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var text = UIFactory.CreateLabel(UIManager.UIRoot, "ResizeCursor", "↔", TextAnchor.MiddleCenter, Color.white, true, 35);
|
var text = UIFactory.CreateLabel(UIManager.UIRoot, "ResizeCursor", "↔", TextAnchor.MiddleCenter, Color.white, true, 35);
|
||||||
s_resizeCursorObj = text.gameObject;
|
resizeCursorObj = text.gameObject;
|
||||||
|
var outline = text.gameObject.AddComponent<Outline>();
|
||||||
|
outline.effectColor = Color.black;
|
||||||
|
outline.effectDistance = new(1, 1);
|
||||||
|
|
||||||
RectTransform rect = s_resizeCursorObj.GetComponent<RectTransform>();
|
RectTransform rect = resizeCursorObj.GetComponent<RectTransform>();
|
||||||
rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, 64);
|
rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, 64);
|
||||||
rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, 64);
|
rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, 64);
|
||||||
|
|
||||||
s_resizeCursorObj.SetActive(false);
|
resizeCursorObj.SetActive(false);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user