mirror of
https://github.com/sinai-dev/UnityExplorer.git
synced 2025-06-18 15:07:49 +08:00
Compare commits
113 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
1e1fb0e27b | ||
![]() |
6b8a7d90c8 | ||
![]() |
1b4657dead | ||
![]() |
1af20ead9f | ||
![]() |
706a18d1f6 | ||
![]() |
81dd8bad0e | ||
![]() |
97dffc81e1 | ||
![]() |
bf2b22e768 | ||
![]() |
d1fbbfa62d | ||
![]() |
56a3cef245 | ||
![]() |
61e7915a55 | ||
![]() |
88e63c8d6a | ||
![]() |
048e5980a0 | ||
![]() |
3b851b6e08 | ||
![]() |
4c029dad90 | ||
![]() |
3d61011e59 | ||
![]() |
5285239bc5 | ||
![]() |
57d3a3f52e | ||
![]() |
c88182c831 | ||
![]() |
02e0102041 | ||
![]() |
6adecef785 | ||
![]() |
ff6c03e1f3 | ||
![]() |
1aedc505b2 | ||
![]() |
dbe993a7c7 | ||
![]() |
5a1676fb84 | ||
![]() |
a7a663aefa | ||
![]() |
76c77fb082 | ||
![]() |
a25017df69 | ||
![]() |
a1fab0c4a7 | ||
![]() |
4599747bfe | ||
![]() |
3856e84c08 | ||
![]() |
104288a912 | ||
![]() |
41e8a5ae33 | ||
![]() |
ef4bc75d5e | ||
![]() |
68b81c6b53 | ||
![]() |
bd86f09313 | ||
![]() |
b35d6f5787 | ||
![]() |
b97eada516 | ||
![]() |
0a05848bef | ||
![]() |
6e5610129a | ||
![]() |
acd30880a8 | ||
![]() |
f54ff89290 | ||
![]() |
62d565777d | ||
![]() |
870f82ab26 | ||
![]() |
9370c5e0e6 | ||
![]() |
b8cf96438c | ||
![]() |
7be7daf4d7 | ||
![]() |
8f54415ae0 | ||
![]() |
aef4e11c01 | ||
![]() |
af7e32ec49 | ||
![]() |
6f44a3376b | ||
![]() |
3a6b573ac3 | ||
![]() |
cbe17927fb | ||
![]() |
15f3f37948 | ||
![]() |
de6760e427 | ||
![]() |
83edd1b9bb | ||
![]() |
613be34e95 | ||
![]() |
58c65b9b8b | ||
![]() |
6fcf6a521c | ||
![]() |
81a174f865 | ||
![]() |
b5e3cc2ea5 | ||
![]() |
14f46ade6a | ||
![]() |
e92556805b | ||
![]() |
8662742461 | ||
![]() |
63393a9d66 | ||
![]() |
13986f95c1 | ||
![]() |
b47bfa1e83 | ||
![]() |
12c51248fe | ||
![]() |
9b9cb54a79 | ||
![]() |
6a28a93e3a | ||
![]() |
32e718faeb | ||
![]() |
4d46b74d54 | ||
![]() |
7e5246cead | ||
![]() |
abf5267364 | ||
![]() |
3afee7254c | ||
![]() |
1643d4b7dd | ||
![]() |
cef8c12d20 | ||
![]() |
5e07847356 | ||
![]() |
2dc6e386df | ||
![]() |
ff882296fd | ||
![]() |
ecc33927ee | ||
![]() |
6e91f2a792 | ||
![]() |
97cb14d6fc | ||
![]() |
8b861f7c77 | ||
![]() |
9379e0f813 | ||
![]() |
bdda12a040 | ||
![]() |
75bd654a94 | ||
![]() |
f174c7543a | ||
![]() |
08f2c6035e | ||
![]() |
475e24a66a | ||
![]() |
c62b93535d | ||
![]() |
374d0b3bae | ||
![]() |
1f87e89b97 | ||
![]() |
495bc41a8d | ||
![]() |
9cf62c3250 | ||
![]() |
4c9b3115cd | ||
![]() |
ebdce70418 | ||
![]() |
7c0b37440b | ||
![]() |
0d8ab8bf14 | ||
![]() |
5a3cad9be2 | ||
![]() |
70d67f1dad | ||
![]() |
469484d129 | ||
![]() |
c5e262d1c3 | ||
![]() |
53c8dfcb6d | ||
![]() |
ae3ac21992 | ||
![]() |
7765b64748 | ||
![]() |
a5023d03f4 | ||
![]() |
a5e6b65dee | ||
![]() |
c45cd8c1e1 | ||
![]() |
e46e24e1af | ||
![]() |
3d66493f9c | ||
![]() |
7e0f98ef91 | ||
![]() |
693f5818be |
24
.github/workflows/dotnet.yml
vendored
24
.github/workflows/dotnet.yml
vendored
@ -34,53 +34,59 @@ jobs:
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: UnityExplorer.BepInEx.IL2CPP.zip
|
||||
path: ./Release/UnityExplorer.BepInEx.IL2CPP.zip
|
||||
path: ./Release/UnityExplorer.BepInEx.IL2CPP/
|
||||
|
||||
# BepInEx IL2CPP CoreCLR
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: UnityExplorer.BepInEx.IL2CPP.CoreCLR.zip
|
||||
path: ./Release/UnityExplorer.BepInEx.IL2CPP.CoreCLR/
|
||||
|
||||
# BepInEx 5 Mono
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: UnityExplorer.BepInEx5.Mono.zip
|
||||
path: ./Release/UnityExplorer.BepInEx5.Mono.zip
|
||||
path: ./Release/UnityExplorer.BepInEx5.Mono/
|
||||
|
||||
# BepInEx 6 Mono
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: UnityExplorer.BepInEx6.Mono.zip
|
||||
path: ./Release/UnityExplorer.BepInEx6.Mono.zip
|
||||
path: ./Release/UnityExplorer.BepInEx6.Mono/
|
||||
|
||||
# Editor
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: UnityExplorer.Editor.zip
|
||||
path: ./Release/UnityExplorer.Editor.zip
|
||||
path: ./UnityEditorPackage/
|
||||
|
||||
# MelonLoader IL2CPP net6preview
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: UnityExplorer.MelonLoader.IL2CPP.net6preview.zip
|
||||
path: ./Release/UnityExplorer.MelonLoader.IL2CPP.net6preview.zip
|
||||
path: ./Release/UnityExplorer.MelonLoader.IL2CPP.net6preview/
|
||||
|
||||
# MelonLoader IL2CPP net472
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: UnityExplorer.MelonLoader.IL2CPP.zip
|
||||
path: ./Release/UnityExplorer.MelonLoader.IL2CPP.zip
|
||||
path: ./Release/UnityExplorer.MelonLoader.IL2CPP/
|
||||
|
||||
# MelonLoader Mono
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: UnityExplorer.MelonLoader.Mono.zip
|
||||
path: ./Release/UnityExplorer.MelonLoader.Mono.zip
|
||||
path: ./Release/UnityExplorer.MelonLoader.Mono/
|
||||
|
||||
# Standalone Il2Cpp
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: UnityExplorer.Standalone.IL2CPP.zip
|
||||
path: ./Release/UnityExplorer.Standalone.IL2CPP.zip
|
||||
path: ./Release/UnityExplorer.Standalone.IL2CPP/
|
||||
|
||||
# Standalone Mono
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: UnityExplorer.Standalone.Mono.zip
|
||||
path: ./Release/UnityExplorer.Standalone.Mono.zip
|
||||
path: ./Release/UnityExplorer.Standalone.Mono/
|
||||
|
||||
|
41
README.md
41
README.md
@ -18,11 +18,18 @@
|
||||
|
||||
⚡ Thunderstore releases: [BepInEx Mono](https://thunderstore.io/package/sinai-dev/UnityExplorer) | [BepInEx IL2CPP](https://gtfo.thunderstore.io/package/sinai-dev/UnityExplorer_IL2CPP) | [MelonLoader IL2CPP](https://boneworks.thunderstore.io/package/sinai-dev/UnityExplorer_IL2CPP_ML)
|
||||
|
||||
## Release schedule
|
||||
|
||||
Releases will be posted at most once per week, generally on weekends.
|
||||
|
||||
Nightly builds can be found [here](https://github.com/sinai-dev/UnityExplorer/actions).
|
||||
|
||||
## BepInEx
|
||||
|
||||
| Release | IL2CPP | Mono |
|
||||
| ------- | ------ | ---- |
|
||||
| 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 (CoreCLR) | ✅ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.BepInEx.IL2CPP.CoreCLR.zip) | ✖ |
|
||||
| BIE 5.X | ✖️ n/a | ✅ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.BepInEx5.Mono.zip) |
|
||||
|
||||
1. Unzip the release file into a folder
|
||||
@ -32,10 +39,10 @@
|
||||
|
||||
## MelonLoader
|
||||
|
||||
| Release | IL2CPP | Mono |
|
||||
| ---------- | ------ | ---- |
|
||||
| ML 0.4/0.5 | ✅ [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.6 | ✅ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.MelonLoader.IL2CPP.net6preview.zip) | ✖️ |
|
||||
| Release | IL2CPP | Mono |
|
||||
| ------- | ------ | ---- |
|
||||
| ML 0.5 | ✅ [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.6 | ✅ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.MelonLoader.IL2CPP.net6preview.zip) | ✖️ |
|
||||
|
||||
1. Unzip the release file into a folder
|
||||
2. Copy the DLL inside the `Mods` folder into your MelonLoader `Mods` folder
|
||||
@ -84,6 +91,20 @@ If these fixes do not work, please create an issue in this repo and I'll do my b
|
||||
</a>
|
||||
</p>
|
||||
|
||||
### Inspector API
|
||||
|
||||
If you want to inspect an object or Type from outside the C# console, use the `InspectorManager` class:
|
||||
|
||||
**To inspect an object:**
|
||||
```csharp
|
||||
UnityExplorer.InspectorManager.Inspect(theObject);
|
||||
```
|
||||
|
||||
**To inspect a Type:**
|
||||
```cs
|
||||
UnityExplorer.InspectorManager.Inspect(typeof(SomeClass));
|
||||
```
|
||||
|
||||
### Object Explorer
|
||||
|
||||
* Use the <b>Scene Explorer</b> tab to traverse the active scenes, as well as the DontDestroyOnLoad and HideAndDontSave objects.
|
||||
@ -104,7 +125,8 @@ The inspector is used to see detailed information on objects of any type and man
|
||||
* Automatic updating is not enabled by default, and you must press Apply for any changes you make to take effect.
|
||||
* Press the `▼` button to expand certain values such as strings, enums, lists, dictionaries, some structs, etc
|
||||
* Use the filters at the top to quickly find the members you are looking for
|
||||
* For `Texture2D` objects, there is a `View Texture` button at the top of the inspector which lets you view it and save it as a PNG file. Currently there are no other similar helpers yet, but I may add more at some point for Mesh, Sprite, Material, etc
|
||||
* For `Texture2D`, `Image`, `Sprite` and `Material` objects, there is a `View Texture` button at the top of the inspector which lets you view the Texture(s) and save them as a PNG file.
|
||||
* For `AudioClip` objects there is a `Show Player` button which opens an audio player widget. For clips which are loaded as `DecompressOnLoad`, there is also a button to save them to a `.wav` file.
|
||||
|
||||
### C# Console
|
||||
|
||||
@ -115,7 +137,7 @@ The inspector is used to see detailed information on objects of any type and man
|
||||
### Hook Manager
|
||||
|
||||
* The Hooks panel allows you to hook methods at the click of a button for debugging purposes.
|
||||
* Simply enter any class (generic types not yet supported) and hook the methods you want from the menu.
|
||||
* Simply enter any class and hook the methods you want from the menu.
|
||||
* You can edit the source code of the generated hook with the "Edit Hook Source" button. Accepted method names are `Prefix` (which can return `bool` or `void`), `Postfix`, `Finalizer` (which can return `Exception` or `void`), and `Transpiler` (which must return `IEnumerable<HarmonyLib.CodeInstruction>`). You can define multiple patches if you wish.
|
||||
|
||||
### Mouse-Inspect
|
||||
@ -124,6 +146,13 @@ The inspector is used to see detailed information on objects of any type and man
|
||||
* <b>World</b>: uses Physics.Raycast to look for Colliders
|
||||
* <b>UI</b>: uses GraphicRaycasters to find UI objects
|
||||
|
||||
### Freecam
|
||||
|
||||
* UnityExplorer provides a basic Free Camera which you can control with your keyboard and mouse.
|
||||
* Unlike all other features of UnityExplorer, you can still use Freecam while UnityExplorer's menu is hidden.
|
||||
* Supports using the game's main Camera or a separate custom Camera.
|
||||
* See the Freecam panel for further instructions and details.
|
||||
|
||||
### Clipboard
|
||||
|
||||
* The "Clipboard" panel allows you to see your current paste value, or clear it (resets it to `null`)
|
||||
|
@ -62,9 +62,7 @@ The inspector is used to see detailed information on objects of any type and man
|
||||
### Settings
|
||||
|
||||
* 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`
|
||||
* MelonLoader: `UserData\MelonPreferences.cfg`
|
||||
* Standalone `{DLL_location}\UnityExplorer\config.cfg`
|
||||
* <AssetsFolder>/sinai-dev-UnityExplorer~/config.cfg
|
||||
|
||||
# Acknowledgments
|
||||
|
||||
|
Binary file not shown.
Binary file not shown.
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "com.sinai-dev.unityexplorer",
|
||||
"version": "4.7.0",
|
||||
"version": "4.7.12",
|
||||
"displayName": "UnityExplorer",
|
||||
"description": "An in-game UI for exploring, debugging and modifying Unity games.",
|
||||
"unity": "2017.1",
|
||||
|
194
build.ps1
194
build.ps1
@ -1,97 +1,155 @@
|
||||
# MelonLoader IL2CPP (net6)
|
||||
dotnet build src\UnityExplorer.sln -c Release_ML_Cpp_net6
|
||||
# (cleanup and move files)
|
||||
# ----------- MelonLoader IL2CPP (net6) -----------
|
||||
dotnet build src/UnityExplorer.sln -c Release_ML_Cpp_net6
|
||||
$Path = "Release\UnityExplorer.MelonLoader.IL2CPP.net6preview"
|
||||
Remove-Item $Path\UnityExplorer.ML.IL2CPP.net6preview.deps.json
|
||||
Remove-Item $Path\Tomlet.dll
|
||||
# ILRepack
|
||||
lib/ILRepack.exe /target:library /lib:lib/net6 /lib:lib/unhollowed /lib:$Path /internalize /out:$Path/UnityExplorer.ML.IL2CPP.net6preview.dll $Path/UnityExplorer.ML.IL2CPP.net6preview.dll $Path/mcs.dll
|
||||
# (cleanup and move files)
|
||||
Remove-Item $Path/UnityExplorer.ML.IL2CPP.net6preview.deps.json
|
||||
Remove-Item $Path/Tomlet.dll
|
||||
Remove-Item $Path/mcs.dll
|
||||
Remove-Item $Path/Iced.dll
|
||||
Remove-Item $Path/UnhollowerBaseLib.dll
|
||||
New-Item -Path "$Path" -Name "Mods" -ItemType "directory" -Force
|
||||
Move-Item -Path $Path\UnityExplorer.ML.IL2CPP.net6preview.dll -Destination $Path\Mods -Force
|
||||
Move-Item -Path $Path/UnityExplorer.ML.IL2CPP.net6preview.dll -Destination $Path/Mods -Force
|
||||
New-Item -Path "$Path" -Name "UserLibs" -ItemType "directory" -Force
|
||||
Move-Item -Path $Path\mcs.dll -Destination $Path\UserLibs -Force
|
||||
Move-Item -Path $Path\UniverseLib.IL2CPP.dll -Destination $Path\UserLibs -Force
|
||||
Move-Item -Path $Path/UniverseLib.IL2CPP.Unhollower.dll -Destination $Path/UserLibs -Force
|
||||
# (create zip archive)
|
||||
Compress-Archive -Path $Path\* -CompressionLevel Fastest -DestinationPath $Path\..\UnityExplorer.MelonLoader.IL2CPP.net6preview.zip -Force
|
||||
Remove-Item $Path/../UnityExplorer.MelonLoader.IL2CPP.net6preview.zip -ErrorAction SilentlyContinue
|
||||
7z a $Path/../UnityExplorer.MelonLoader.IL2CPP.net6preview.zip .\$Path\*
|
||||
|
||||
# MelonLoader IL2CPP (net472)
|
||||
dotnet build src\UnityExplorer.sln -c Release_ML_Cpp_net472
|
||||
# ----------- MelonLoader IL2CPP (net472) -----------
|
||||
dotnet build src/UnityExplorer.sln -c Release_ML_Cpp_net472
|
||||
$Path = "Release/UnityExplorer.MelonLoader.IL2CPP"
|
||||
# ILRepack
|
||||
lib/ILRepack.exe /target:library /lib:lib/net472 /lib:lib/net35 /lib:lib/unhollowed /lib:$Path /internalize /out:$Path/UnityExplorer.ML.IL2CPP.dll $Path/UnityExplorer.ML.IL2CPP.dll $Path/mcs.dll
|
||||
# (cleanup and move files)
|
||||
$Path = "Release\UnityExplorer.MelonLoader.IL2CPP"
|
||||
Remove-Item $Path\Tomlet.dll
|
||||
Remove-Item $Path/Tomlet.dll
|
||||
Remove-Item $Path/mcs.dll
|
||||
Remove-Item $Path/Iced.dll
|
||||
Remove-Item $Path/UnhollowerBaseLib.dll
|
||||
New-Item -Path "$Path" -Name "Mods" -ItemType "directory" -Force
|
||||
Move-Item -Path $Path\UnityExplorer.ML.IL2CPP.dll -Destination $Path\Mods -Force
|
||||
Move-Item -Path $Path/UnityExplorer.ML.IL2CPP.dll -Destination $Path/Mods -Force
|
||||
New-Item -Path "$Path" -Name "UserLibs" -ItemType "directory" -Force
|
||||
Move-Item -Path $Path\mcs.dll -Destination $Path\UserLibs -Force
|
||||
Move-Item -Path $Path\UniverseLib.IL2CPP.dll -Destination $Path\UserLibs -Force
|
||||
Move-Item -Path $Path/UniverseLib.IL2CPP.Unhollower.dll -Destination $Path/UserLibs -Force
|
||||
# (create zip archive)
|
||||
Compress-Archive -Path $Path\* -CompressionLevel Fastest -DestinationPath $Path\..\UnityExplorer.MelonLoader.IL2CPP.zip -Force
|
||||
Remove-Item $Path/../UnityExplorer.MelonLoader.IL2CPP.zip -ErrorAction SilentlyContinue
|
||||
7z a $Path/../UnityExplorer.MelonLoader.IL2CPP.zip .\$Path\*
|
||||
|
||||
# MelonLoader Mono
|
||||
dotnet build src\UnityExplorer.sln -c Release_ML_Mono
|
||||
# ----------- MelonLoader Mono -----------
|
||||
dotnet build src/UnityExplorer.sln -c Release_ML_Mono
|
||||
$Path = "Release/UnityExplorer.MelonLoader.Mono"
|
||||
# ILRepack
|
||||
lib/ILRepack.exe /target:library /lib:lib/net35 /lib:$Path /internalize /out:$Path/UnityExplorer.ML.Mono.dll $Path/UnityExplorer.ML.Mono.dll $Path/mcs.dll
|
||||
# (cleanup and move files)
|
||||
$Path = "Release\UnityExplorer.MelonLoader.Mono"
|
||||
Remove-Item $Path\Tomlet.dll
|
||||
Remove-Item $Path/Tomlet.dll
|
||||
Remove-Item $Path/mcs.dll
|
||||
New-Item -Path "$Path" -Name "Mods" -ItemType "directory" -Force
|
||||
Move-Item -Path $Path\UnityExplorer.ML.Mono.dll -Destination $Path\Mods -Force
|
||||
Move-Item -Path $Path/UnityExplorer.ML.Mono.dll -Destination $Path/Mods -Force
|
||||
New-Item -Path "$Path" -Name "UserLibs" -ItemType "directory" -Force
|
||||
Move-Item -Path $Path\mcs.dll -Destination $Path\UserLibs -Force
|
||||
Move-Item -Path $Path\UniverseLib.Mono.dll -Destination $Path\UserLibs -Force
|
||||
Move-Item -Path $Path/UniverseLib.Mono.dll -Destination $Path/UserLibs -Force
|
||||
# (create zip archive)
|
||||
Compress-Archive -Path $Path\* -CompressionLevel Fastest -DestinationPath $Path\..\UnityExplorer.MelonLoader.Mono.zip -Force
|
||||
Remove-Item $Path/../UnityExplorer.MelonLoader.Mono.zip -ErrorAction SilentlyContinue
|
||||
7z a $Path/../UnityExplorer.MelonLoader.Mono.zip .\$Path\*
|
||||
|
||||
# BepInEx IL2CPP
|
||||
dotnet build src\UnityExplorer.sln -c Release_BIE_Cpp
|
||||
# ----------- BepInEx IL2CPP -----------
|
||||
dotnet build src/UnityExplorer.sln -c Release_BIE_Cpp
|
||||
$Path = "Release/UnityExplorer.BepInEx.IL2CPP"
|
||||
# ILRepack
|
||||
lib/ILRepack.exe /target:library /lib:lib/net472 /lib:lib/unhollowed /lib:$Path /internalize /out:$Path/UnityExplorer.BIE.IL2CPP.dll $Path/UnityExplorer.BIE.IL2CPP.dll $Path/mcs.dll $Path/Tomlet.dll
|
||||
# (cleanup and move files)
|
||||
$Path = "Release\UnityExplorer.BepInEx.IL2CPP"
|
||||
Remove-Item $Path/Tomlet.dll
|
||||
Remove-Item $Path/mcs.dll
|
||||
Remove-Item $Path/Iced.dll
|
||||
Remove-Item $Path/UnhollowerBaseLib.dll
|
||||
New-Item -Path "$Path" -Name "plugins" -ItemType "directory" -Force
|
||||
New-Item -Path "$Path" -Name "plugins\sinai-dev-UnityExplorer" -ItemType "directory" -Force
|
||||
Move-Item -Path $Path\UnityExplorer.BIE.IL2CPP.dll -Destination $Path\plugins\sinai-dev-UnityExplorer -Force
|
||||
Move-Item -Path $Path\mcs.dll -Destination $Path\plugins\sinai-dev-UnityExplorer -Force
|
||||
Move-Item -Path $Path\Tomlet.dll -Destination $Path\plugins\sinai-dev-UnityExplorer -Force
|
||||
Move-Item -Path $Path\UniverseLib.IL2CPP.dll -Destination $Path\plugins\sinai-dev-UnityExplorer -Force
|
||||
New-Item -Path "$Path" -Name "plugins/sinai-dev-UnityExplorer" -ItemType "directory" -Force
|
||||
Move-Item -Path $Path/UnityExplorer.BIE.IL2CPP.dll -Destination $Path/plugins/sinai-dev-UnityExplorer -Force
|
||||
Move-Item -Path $Path/UniverseLib.IL2CPP.Unhollower.dll -Destination $Path/plugins/sinai-dev-UnityExplorer -Force
|
||||
# (create zip archive)
|
||||
Compress-Archive -Path $Path\* -CompressionLevel Fastest -DestinationPath $Path\..\UnityExplorer.BepInEx.IL2CPP.zip -Force
|
||||
Remove-Item $Path/../UnityExplorer.BepInEx.IL2CPP.zip -ErrorAction SilentlyContinue
|
||||
7z a $Path/../UnityExplorer.BepInEx.IL2CPP.zip .\$Path\*
|
||||
|
||||
# BepInEx 5 Mono
|
||||
dotnet build src\UnityExplorer.sln -c Release_BIE5_Mono
|
||||
# ----------- BepInEx IL2CPP CoreCLR -----------
|
||||
dotnet build src/UnityExplorer.sln -c Release_BIE_CoreCLR
|
||||
$Path = "Release/UnityExplorer.BepInEx.IL2CPP.CoreCLR"
|
||||
# ILRepack
|
||||
lib/ILRepack.exe /target:library /lib:lib/net472 /lib:lib/net6/ /lib:lib/interop/ /lib:$Path /internalize /out:$Path/UnityExplorer.BIE.IL2CPP.CoreCLR.dll $Path/UnityExplorer.BIE.IL2CPP.CoreCLR.dll $Path/mcs.dll $Path/Tomlet.dll
|
||||
# (cleanup and move files)
|
||||
$Path = "Release\UnityExplorer.BepInEx5.Mono"
|
||||
Remove-Item $Path/Tomlet.dll
|
||||
Remove-Item $Path/mcs.dll
|
||||
Remove-Item $Path/Iced.dll
|
||||
Remove-Item $Path/Il2CppInterop.Common.dll
|
||||
Remove-Item $Path/Il2CppInterop.Runtime.dll
|
||||
Remove-Item $Path/Microsoft.Extensions.Logging.Abstractions.dll
|
||||
Remove-Item $Path/UnityExplorer.BIE.IL2CPP.CoreCLR.deps.json
|
||||
New-Item -Path "$Path" -Name "plugins" -ItemType "directory" -Force
|
||||
New-Item -Path "$Path" -Name "plugins\sinai-dev-UnityExplorer" -ItemType "directory" -Force
|
||||
Move-Item -Path $Path\UnityExplorer.BIE5.Mono.dll -Destination $Path\plugins\sinai-dev-UnityExplorer -Force
|
||||
Move-Item -Path $Path\mcs.dll -Destination $Path\plugins\sinai-dev-UnityExplorer -Force
|
||||
Move-Item -Path $Path\Tomlet.dll -Destination $Path\plugins\sinai-dev-UnityExplorer -Force
|
||||
Move-Item -Path $Path\UniverseLib.Mono.dll -Destination $Path\plugins\sinai-dev-UnityExplorer -Force
|
||||
New-Item -Path "$Path" -Name "plugins/sinai-dev-UnityExplorer" -ItemType "directory" -Force
|
||||
Move-Item -Path $Path/UnityExplorer.BIE.IL2CPP.CoreCLR.dll -Destination $Path/plugins/sinai-dev-UnityExplorer -Force
|
||||
Move-Item -Path $Path/UniverseLib.IL2CPP.Interop.dll -Destination $Path/plugins/sinai-dev-UnityExplorer -Force
|
||||
# (create zip archive)
|
||||
Compress-Archive -Path $Path\* -CompressionLevel Fastest -DestinationPath $Path\..\UnityExplorer.BepInEx5.Mono.zip -Force
|
||||
Remove-Item $Path/../UnityExplorer.BepInEx.IL2CPP.CoreCLR.zip -ErrorAction SilentlyContinue
|
||||
7z a $Path/../UnityExplorer.BepInEx.IL2CPP.CoreCLR.zip .\$Path\*
|
||||
|
||||
# BepInEx 6 Mono
|
||||
dotnet build src\UnityExplorer.sln -c Release_BIE6_Mono
|
||||
# ----------- BepInEx 5 Mono -----------
|
||||
dotnet build src/UnityExplorer.sln -c Release_BIE5_Mono
|
||||
$Path = "Release/UnityExplorer.BepInEx5.Mono"
|
||||
# ILRepack
|
||||
lib/ILRepack.exe /target:library /lib:lib/net35 /lib:$Path /internalize /out:$Path/UnityExplorer.BIE5.Mono.dll $Path/UnityExplorer.BIE5.Mono.dll $Path/mcs.dll $Path/Tomlet.dll
|
||||
# (cleanup and move files)
|
||||
$Path = "Release\UnityExplorer.BepInEx6.Mono"
|
||||
Remove-Item $Path/Tomlet.dll
|
||||
Remove-Item $Path/mcs.dll
|
||||
New-Item -Path "$Path" -Name "plugins" -ItemType "directory" -Force
|
||||
New-Item -Path "$Path" -Name "plugins\sinai-dev-UnityExplorer" -ItemType "directory" -Force
|
||||
Move-Item -Path $Path\UnityExplorer.BIE6.Mono.dll -Destination $Path\plugins\sinai-dev-UnityExplorer -Force
|
||||
Move-Item -Path $Path\mcs.dll -Destination $Path\plugins\sinai-dev-UnityExplorer -Force
|
||||
Move-Item -Path $Path\Tomlet.dll -Destination $Path\plugins\sinai-dev-UnityExplorer -Force
|
||||
Move-Item -Path $Path\UniverseLib.Mono.dll -Destination $Path\plugins\sinai-dev-UnityExplorer -Force
|
||||
New-Item -Path "$Path" -Name "plugins/sinai-dev-UnityExplorer" -ItemType "directory" -Force
|
||||
Move-Item -Path $Path/UnityExplorer.BIE5.Mono.dll -Destination $Path/plugins/sinai-dev-UnityExplorer -Force
|
||||
Move-Item -Path $Path/UniverseLib.Mono.dll -Destination $Path/plugins/sinai-dev-UnityExplorer -Force
|
||||
# (create zip archive)
|
||||
Compress-Archive -Path $Path\* -CompressionLevel Fastest -DestinationPath $Path\..\UnityExplorer.BepInEx6.Mono.zip -Force
|
||||
Remove-Item $Path/../UnityExplorer.BepInEx5.Mono.zip -ErrorAction SilentlyContinue
|
||||
7z a $Path/../UnityExplorer.BepInEx5.Mono.zip .\$Path\*
|
||||
|
||||
# Standalone Mono
|
||||
dotnet build src\UnityExplorer.sln -c Release_STANDALONE_Mono
|
||||
$Path = "Release\UnityExplorer.Standalone.Mono"
|
||||
Compress-Archive -Path $Path\* -CompressionLevel Fastest -DestinationPath $Path\..\UnityExplorer.Standalone.Mono.zip -Force
|
||||
# ----------- BepInEx 6 Mono -----------
|
||||
dotnet build src/UnityExplorer.sln -c Release_BIE6_Mono
|
||||
$Path = "Release/UnityExplorer.BepInEx6.Mono"
|
||||
# ILRepack
|
||||
lib/ILRepack.exe /target:library /lib:lib/net35 /lib:$Path /internalize /out:$Path/UnityExplorer.BIE6.Mono.dll $Path/UnityExplorer.BIE6.Mono.dll $Path/mcs.dll $Path/Tomlet.dll
|
||||
# (cleanup and move files)
|
||||
Remove-Item $Path/Tomlet.dll
|
||||
Remove-Item $Path/mcs.dll
|
||||
New-Item -Path "$Path" -Name "plugins" -ItemType "directory" -Force
|
||||
New-Item -Path "$Path" -Name "plugins/sinai-dev-UnityExplorer" -ItemType "directory" -Force
|
||||
Move-Item -Path $Path/UnityExplorer.BIE6.Mono.dll -Destination $Path/plugins/sinai-dev-UnityExplorer -Force
|
||||
Move-Item -Path $Path/UniverseLib.Mono.dll -Destination $Path/plugins/sinai-dev-UnityExplorer -Force
|
||||
# (create zip archive)
|
||||
Remove-Item $Path/../UnityExplorer.BepInEx6.Mono.zip -ErrorAction SilentlyContinue
|
||||
7z a $Path/../UnityExplorer.BepInEx6.Mono.zip .\$Path\*
|
||||
|
||||
# Standalone IL2CPP
|
||||
dotnet build src\UnityExplorer.sln -c Release_STANDALONE_Cpp
|
||||
$Path = "Release\UnityExplorer.Standalone.IL2CPP"
|
||||
Compress-Archive -Path $Path\* -CompressionLevel Fastest -DestinationPath $Path\..\UnityExplorer.Standalone.IL2CPP.zip -Force
|
||||
# ----------- Standalone Mono -----------
|
||||
dotnet build src/UnityExplorer.sln -c Release_STANDALONE_Mono
|
||||
$Path = "Release/UnityExplorer.Standalone.Mono"
|
||||
# ILRepack
|
||||
lib/ILRepack.exe /target:library /lib:lib/net35 /lib:$Path /internalize /out:$Path/UnityExplorer.Standalone.Mono.dll $Path/UnityExplorer.Standalone.Mono.dll $Path/mcs.dll $Path/Tomlet.dll
|
||||
# (cleanup and move files)
|
||||
Remove-Item $Path/Tomlet.dll
|
||||
Remove-Item $Path/mcs.dll
|
||||
Remove-Item $Path/../UnityExplorer.Standalone.Mono.zip -ErrorAction SilentlyContinue
|
||||
7z a $Path/../UnityExplorer.Standalone.Mono.zip .\$Path\*
|
||||
|
||||
# Editor (mono)
|
||||
$Path1 = "Release\UnityExplorer.Standalone.Mono"
|
||||
$Path2 = "UnityEditorPackage\Runtime"
|
||||
Copy-Item $Path1\UnityExplorer.STANDALONE.Mono.dll -Destination $Path2
|
||||
Copy-Item $Path1\mcs.dll -Destination $Path2
|
||||
Copy-Item $Path1\Tomlet.dll -Destination $Path2
|
||||
Copy-Item $Path1\UniverseLib.Mono.dll -Destination $Path2
|
||||
Compress-Archive -Path UnityEditorPackage\* -CompressionLevel Fastest -DestinationPath Release\UnityExplorer.Editor.zip -Force
|
||||
# ----------- Standalone IL2CPP -----------
|
||||
dotnet build src/UnityExplorer.sln -c Release_STANDALONE_Cpp
|
||||
$Path = "Release/UnityExplorer.Standalone.IL2CPP"
|
||||
# ILRepack
|
||||
lib/ILRepack.exe /target:library /lib:lib/net472 /lib:lib/unhollowed /lib:$Path /internalize /out:$Path/UnityExplorer.Standalone.IL2CPP.dll $Path/UnityExplorer.Standalone.IL2CPP.dll $Path/mcs.dll $Path/Tomlet.dll
|
||||
# (cleanup and move files)
|
||||
Remove-Item $Path/Tomlet.dll
|
||||
Remove-Item $Path/mcs.dll
|
||||
Remove-Item $Path/Iced.dll
|
||||
Remove-Item $Path/UnhollowerBaseLib.dll
|
||||
Remove-Item $Path/../UnityExplorer.Standalone.IL2CPP.zip -ErrorAction SilentlyContinue
|
||||
7z a $Path/../UnityExplorer.Standalone.IL2CPP.zip .\$Path\*
|
||||
|
||||
# ----------- Editor (mono) -----------
|
||||
$Path1 = "Release/UnityExplorer.Standalone.Mono"
|
||||
$Path2 = "UnityEditorPackage/Runtime"
|
||||
Copy-Item $Path1/UnityExplorer.STANDALONE.Mono.dll -Destination $Path2
|
||||
Copy-Item $Path1/UniverseLib.Mono.dll -Destination $Path2
|
||||
Remove-Item Release/UnityExplorer.Editor.zip -ErrorAction SilentlyContinue
|
||||
7z a Release/UnityExplorer.Editor.zip .\UnityEditorPackage\*
|
BIN
lib/ILRepack.exe
Normal file
BIN
lib/ILRepack.exe
Normal file
Binary file not shown.
BIN
lib/interop/Il2CppSystem.Core.dll
Normal file
BIN
lib/interop/Il2CppSystem.Core.dll
Normal file
Binary file not shown.
BIN
lib/interop/Il2Cppmscorlib.dll
Normal file
BIN
lib/interop/Il2Cppmscorlib.dll
Normal file
Binary file not shown.
BIN
lib/interop/UnityEngine.AssetBundleModule.dll
Normal file
BIN
lib/interop/UnityEngine.AssetBundleModule.dll
Normal file
Binary file not shown.
BIN
lib/interop/UnityEngine.AudioModule.dll
Normal file
BIN
lib/interop/UnityEngine.AudioModule.dll
Normal file
Binary file not shown.
BIN
lib/interop/UnityEngine.CoreModule.dll
Normal file
BIN
lib/interop/UnityEngine.CoreModule.dll
Normal file
Binary file not shown.
BIN
lib/interop/UnityEngine.IMGUIModule.dll
Normal file
BIN
lib/interop/UnityEngine.IMGUIModule.dll
Normal file
Binary file not shown.
BIN
lib/interop/UnityEngine.PhysicsModule.dll
Normal file
BIN
lib/interop/UnityEngine.PhysicsModule.dll
Normal file
Binary file not shown.
BIN
lib/interop/UnityEngine.TextRenderingModule.dll
Normal file
BIN
lib/interop/UnityEngine.TextRenderingModule.dll
Normal file
Binary file not shown.
BIN
lib/interop/UnityEngine.UI.dll
Normal file
BIN
lib/interop/UnityEngine.UI.dll
Normal file
Binary file not shown.
BIN
lib/interop/UnityEngine.UIModule.dll
Normal file
BIN
lib/interop/UnityEngine.UIModule.dll
Normal file
Binary file not shown.
BIN
lib/interop/UnityEngine.dll
Normal file
BIN
lib/interop/UnityEngine.dll
Normal file
Binary file not shown.
BIN
lib/net6/System.Runtime.dll
Normal file
BIN
lib/net6/System.Runtime.dll
Normal file
Binary file not shown.
@ -1,15 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using System.Text;
|
||||
using UnityExplorer.CSConsole.Lexers;
|
||||
using UnityExplorer.UI;
|
||||
using UnityExplorer.UI.Panels;
|
||||
using UnityExplorer.UI.Widgets.AutoComplete;
|
||||
using UniverseLib;
|
||||
using UniverseLib.UI;
|
||||
using UniverseLib.UI.Models;
|
||||
using UniverseLib.Utility;
|
||||
|
||||
namespace UnityExplorer.CSConsole
|
||||
{
|
||||
@ -29,10 +22,23 @@ namespace UnityExplorer.CSConsole
|
||||
|
||||
private readonly HashSet<char> delimiters = new()
|
||||
{
|
||||
'{', '}', ',', ';', '<', '>', '(', ')', '[', ']', '=', '|', '&', '?'
|
||||
'{',
|
||||
'}',
|
||||
',',
|
||||
';',
|
||||
'<',
|
||||
'>',
|
||||
'(',
|
||||
')',
|
||||
'[',
|
||||
']',
|
||||
'=',
|
||||
'|',
|
||||
'&',
|
||||
'?'
|
||||
};
|
||||
|
||||
private readonly List<Suggestion> suggestions = new List<Suggestion>();
|
||||
private readonly List<Suggestion> suggestions = new();
|
||||
|
||||
public void CheckAutocompletes()
|
||||
{
|
||||
@ -83,7 +89,7 @@ namespace UnityExplorer.CSConsole
|
||||
|
||||
// Get manual namespace completions
|
||||
|
||||
foreach (var ns in ReflectionUtility.AllNamespaces)
|
||||
foreach (string ns in ReflectionUtility.AllNamespaces)
|
||||
{
|
||||
if (ns.StartsWith(input))
|
||||
{
|
||||
@ -97,7 +103,7 @@ namespace UnityExplorer.CSConsole
|
||||
|
||||
// Get manual keyword completions
|
||||
|
||||
foreach (var kw in KeywordLexer.keywords)
|
||||
foreach (string kw in KeywordLexer.keywords)
|
||||
{
|
||||
if (kw.StartsWith(input))// && kw.Length > input.Length)
|
||||
{
|
||||
@ -121,11 +127,11 @@ namespace UnityExplorer.CSConsole
|
||||
}
|
||||
|
||||
|
||||
private readonly Dictionary<string, string> namespaceHighlights = new Dictionary<string, string>();
|
||||
private readonly Dictionary<string, string> namespaceHighlights = new();
|
||||
|
||||
private readonly Dictionary<string, string> keywordHighlights = new Dictionary<string, string>();
|
||||
private readonly Dictionary<string, string> keywordHighlights = new();
|
||||
|
||||
private readonly StringBuilder highlightBuilder = new StringBuilder();
|
||||
private readonly StringBuilder highlightBuilder = new();
|
||||
private const string OPEN_HIGHLIGHT = "<color=cyan>";
|
||||
|
||||
private string GetHighlightString(string prefix, string completion)
|
||||
|
@ -1,70 +1,61 @@
|
||||
using System;
|
||||
using Mono.CSharp;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.UI;
|
||||
using UniverseLib.Input;
|
||||
using UnityExplorer.CSConsole;
|
||||
using UnityExplorer.UI;
|
||||
using UnityExplorer.UI.Panels;
|
||||
using UnityExplorer.UI.Widgets.AutoComplete;
|
||||
using UniverseLib.UI;
|
||||
using UniverseLib;
|
||||
using UniverseLib.Input;
|
||||
using UniverseLib.UI.Models;
|
||||
using UniverseLib.Utility;
|
||||
using HarmonyLib;
|
||||
using UniverseLib.Runtime;
|
||||
using Mono.CSharp;
|
||||
|
||||
namespace UnityExplorer.CSConsole
|
||||
{
|
||||
public static class ConsoleController
|
||||
{
|
||||
public static ScriptEvaluator Evaluator;
|
||||
public static LexerBuilder Lexer;
|
||||
public static CSAutoCompleter Completer;
|
||||
|
||||
private static HashSet<string> usingDirectives;
|
||||
private static StringBuilder evaluatorOutput;
|
||||
private static StringWriter evaluatorStringWriter;
|
||||
|
||||
public static CSConsolePanel Panel => UIManager.GetPanel<CSConsolePanel>(UIManager.Panels.CSConsole);
|
||||
public static InputFieldRef Input => Panel.Input;
|
||||
public static ScriptEvaluator Evaluator { get; private set; }
|
||||
public static LexerBuilder Lexer { get; private set; }
|
||||
public static CSAutoCompleter Completer { get; private set; }
|
||||
|
||||
public static bool SRENotSupported { get; private set; }
|
||||
public static int LastCaretPosition { get; private set; }
|
||||
internal static float defaultInputFieldAlpha;
|
||||
public static float DefaultInputFieldAlpha { get; set; }
|
||||
|
||||
// Todo save as config?
|
||||
public static bool EnableCtrlRShortcut { get; private set; } = true;
|
||||
public static bool EnableAutoIndent { get; private set; } = true;
|
||||
public static bool EnableSuggestions { get; private set; } = true;
|
||||
|
||||
internal static string ScriptsFolder => Path.Combine(ExplorerCore.ExplorerFolder, "Scripts");
|
||||
public static CSConsolePanel Panel => UIManager.GetPanel<CSConsolePanel>(UIManager.Panels.CSConsole);
|
||||
public static InputFieldRef Input => Panel.Input;
|
||||
|
||||
internal static readonly string[] DefaultUsing = new string[]
|
||||
public static string ScriptsFolder => Path.Combine(ExplorerCore.ExplorerFolder, "Scripts");
|
||||
|
||||
static HashSet<string> usingDirectives;
|
||||
static StringBuilder evaluatorOutput;
|
||||
static StringWriter evaluatorStringWriter;
|
||||
static float timeOfLastCtrlR;
|
||||
|
||||
static bool settingCaretCoroutine;
|
||||
static string previousInput;
|
||||
static int previousContentLength = 0;
|
||||
|
||||
static readonly string[] DefaultUsing = new string[]
|
||||
{
|
||||
"System",
|
||||
"System.Linq",
|
||||
"System.Text",
|
||||
"System.Collections",
|
||||
"System.Collections.Generic",
|
||||
"System.Reflection",
|
||||
"UnityEngine",
|
||||
"UniverseLib",
|
||||
#if CPP
|
||||
"UnhollowerBaseLib",
|
||||
"UnhollowerRuntimeLib",
|
||||
#endif
|
||||
};
|
||||
|
||||
const int CSCONSOLE_LINEHEIGHT = 18;
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
InitEventSystemPropertyHandlers();
|
||||
|
||||
// Make sure console is supported on this platform
|
||||
try
|
||||
{
|
||||
ResetConsole(false);
|
||||
@ -99,11 +90,11 @@ namespace UnityExplorer.CSConsole
|
||||
if (!Directory.Exists(ScriptsFolder))
|
||||
Directory.CreateDirectory(ScriptsFolder);
|
||||
|
||||
var startupPath = Path.Combine(ScriptsFolder, "startup.cs");
|
||||
string startupPath = Path.Combine(ScriptsFolder, "startup.cs");
|
||||
if (File.Exists(startupPath))
|
||||
{
|
||||
ExplorerCore.Log($"Executing startup script from '{startupPath}'...");
|
||||
var text = File.ReadAllText(startupPath);
|
||||
string text = File.ReadAllText(startupPath);
|
||||
Input.Text = text;
|
||||
Evaluate();
|
||||
}
|
||||
@ -114,31 +105,10 @@ namespace UnityExplorer.CSConsole
|
||||
}
|
||||
}
|
||||
|
||||
#region UI Listeners and options
|
||||
|
||||
// TODO save
|
||||
|
||||
private static void OnToggleAutoIndent(bool value)
|
||||
{
|
||||
EnableAutoIndent = value;
|
||||
}
|
||||
|
||||
private static void OnToggleCtrlRShortcut(bool value)
|
||||
{
|
||||
EnableCtrlRShortcut = value;
|
||||
}
|
||||
|
||||
private static void OnToggleSuggestions(bool value)
|
||||
{
|
||||
EnableSuggestions = value;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Evaluating
|
||||
|
||||
private static void GenerateTextWriter()
|
||||
static void GenerateTextWriter()
|
||||
{
|
||||
evaluatorOutput = new StringBuilder();
|
||||
evaluatorStringWriter = new StringWriter(evaluatorOutput);
|
||||
@ -153,7 +123,7 @@ namespace UnityExplorer.CSConsole
|
||||
|
||||
if (Evaluator != null)
|
||||
Evaluator.Dispose();
|
||||
|
||||
|
||||
GenerateTextWriter();
|
||||
Evaluator = new ScriptEvaluator(evaluatorStringWriter)
|
||||
{
|
||||
@ -161,7 +131,7 @@ namespace UnityExplorer.CSConsole
|
||||
};
|
||||
|
||||
usingDirectives = new HashSet<string>();
|
||||
foreach (var use in DefaultUsing)
|
||||
foreach (string use in DefaultUsing)
|
||||
AddUsing(use);
|
||||
|
||||
if (logSuccess)
|
||||
@ -200,7 +170,7 @@ namespace UnityExplorer.CSConsole
|
||||
{
|
||||
// Compile the code. If it returned a CompiledMethod, it is REPL.
|
||||
CompiledMethod repl = Evaluator.Compile(input);
|
||||
|
||||
|
||||
if (repl != null)
|
||||
{
|
||||
// Valid REPL, we have a delegate to the evaluation.
|
||||
@ -208,7 +178,7 @@ namespace UnityExplorer.CSConsole
|
||||
{
|
||||
object ret = null;
|
||||
repl.Invoke(ref ret);
|
||||
var result = ret?.ToString();
|
||||
string result = ret?.ToString();
|
||||
if (!string.IsNullOrEmpty(result))
|
||||
ExplorerCore.Log($"Invoked REPL, result: {ret}");
|
||||
else
|
||||
@ -222,13 +192,13 @@ namespace UnityExplorer.CSConsole
|
||||
else
|
||||
{
|
||||
// The compiled code was not REPL, so it was a using directive or it defined classes.
|
||||
|
||||
|
||||
string output = Evaluator._textWriter.ToString();
|
||||
var outputSplit = output.Split('\n');
|
||||
string[] outputSplit = output.Split('\n');
|
||||
if (outputSplit.Length >= 2)
|
||||
output = outputSplit[outputSplit.Length - 2];
|
||||
evaluatorOutput.Clear();
|
||||
|
||||
|
||||
if (ScriptEvaluator._reportPrinter.ErrorsCount > 0)
|
||||
throw new FormatException($"Unable to compile the code. Evaluator's last output was:\r\n{output}");
|
||||
else if (!supressLog)
|
||||
@ -250,16 +220,48 @@ namespace UnityExplorer.CSConsole
|
||||
#endregion
|
||||
|
||||
|
||||
// Updating and event listeners
|
||||
#region Update loop and event listeners
|
||||
|
||||
private static bool settingCaretCoroutine;
|
||||
public static void Update()
|
||||
{
|
||||
if (SRENotSupported)
|
||||
return;
|
||||
|
||||
private static void OnInputScrolled() => HighlightVisibleInput();
|
||||
if (!InputManager.GetKey(KeyCode.LeftControl) && !InputManager.GetKey(KeyCode.RightControl))
|
||||
{
|
||||
if (InputManager.GetKeyDown(KeyCode.Home))
|
||||
JumpToStartOrEndOfLine(true);
|
||||
else if (InputManager.GetKeyDown(KeyCode.End))
|
||||
JumpToStartOrEndOfLine(false);
|
||||
}
|
||||
|
||||
private static string previousInput;
|
||||
UpdateCaret(out bool caretMoved);
|
||||
|
||||
// Invoked at most once per frame
|
||||
private static void OnInputChanged(string value)
|
||||
if (!settingCaretCoroutine && EnableSuggestions)
|
||||
{
|
||||
if (AutoCompleteModal.CheckEscape(Completer))
|
||||
{
|
||||
OnAutocompleteEscaped();
|
||||
return;
|
||||
}
|
||||
|
||||
if (caretMoved)
|
||||
AutoCompleteModal.Instance.ReleaseOwnership(Completer);
|
||||
}
|
||||
|
||||
if (EnableCtrlRShortcut
|
||||
&& (InputManager.GetKey(KeyCode.LeftControl) || InputManager.GetKey(KeyCode.RightControl))
|
||||
&& InputManager.GetKeyDown(KeyCode.R)
|
||||
&& timeOfLastCtrlR.OccuredEarlierThanDefault())
|
||||
{
|
||||
timeOfLastCtrlR = Time.realtimeSinceStartup;
|
||||
Evaluate(Panel.Input.Text);
|
||||
}
|
||||
}
|
||||
|
||||
static void OnInputScrolled() => HighlightVisibleInput(out _);
|
||||
|
||||
static void OnInputChanged(string value)
|
||||
{
|
||||
if (SRENotSupported)
|
||||
return;
|
||||
@ -286,7 +288,7 @@ namespace UnityExplorer.CSConsole
|
||||
DoAutoIndent();
|
||||
}
|
||||
|
||||
var inStringOrComment = HighlightVisibleInput();
|
||||
HighlightVisibleInput(out bool inStringOrComment);
|
||||
|
||||
if (!settingCaretCoroutine)
|
||||
{
|
||||
@ -302,40 +304,27 @@ namespace UnityExplorer.CSConsole
|
||||
UpdateCaret(out _);
|
||||
}
|
||||
|
||||
private static float timeOfLastCtrlR;
|
||||
|
||||
public static void Update()
|
||||
static void OnToggleAutoIndent(bool value)
|
||||
{
|
||||
if (SRENotSupported)
|
||||
return;
|
||||
|
||||
UpdateCaret(out bool caretMoved);
|
||||
|
||||
if (!settingCaretCoroutine && EnableSuggestions)
|
||||
{
|
||||
if (AutoCompleteModal.CheckEscape(Completer))
|
||||
{
|
||||
OnAutocompleteEscaped();
|
||||
return;
|
||||
}
|
||||
|
||||
if (caretMoved)
|
||||
AutoCompleteModal.Instance.ReleaseOwnership(Completer);
|
||||
}
|
||||
|
||||
if (EnableCtrlRShortcut
|
||||
&& (InputManager.GetKey(KeyCode.LeftControl) || InputManager.GetKey(KeyCode.RightControl))
|
||||
&& InputManager.GetKeyDown(KeyCode.R)
|
||||
&& timeOfLastCtrlR.OccuredEarlierThanDefault())
|
||||
{
|
||||
timeOfLastCtrlR = Time.realtimeSinceStartup;
|
||||
Evaluate(Panel.Input.Text);
|
||||
}
|
||||
EnableAutoIndent = value;
|
||||
}
|
||||
|
||||
private const int CSCONSOLE_LINEHEIGHT = 18;
|
||||
static void OnToggleCtrlRShortcut(bool value)
|
||||
{
|
||||
EnableCtrlRShortcut = value;
|
||||
}
|
||||
|
||||
private static void UpdateCaret(out bool caretMoved)
|
||||
static void OnToggleSuggestions(bool value)
|
||||
{
|
||||
EnableSuggestions = value;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Caret position
|
||||
|
||||
static void UpdateCaret(out bool caretMoved)
|
||||
{
|
||||
int prevCaret = LastCaretPosition;
|
||||
caretMoved = false;
|
||||
@ -359,12 +348,12 @@ namespace UnityExplorer.CSConsole
|
||||
// If caret moved, ensure caret is visible in the viewport
|
||||
if (caretMoved)
|
||||
{
|
||||
var charInfo = Input.TextGenerator.characters[LastCaretPosition];
|
||||
var charTop = charInfo.cursorPos.y;
|
||||
var charBot = charTop - CSCONSOLE_LINEHEIGHT;
|
||||
UICharInfo charInfo = Input.TextGenerator.characters[LastCaretPosition];
|
||||
float charTop = charInfo.cursorPos.y;
|
||||
float charBot = charTop - CSCONSOLE_LINEHEIGHT;
|
||||
|
||||
var viewportMin = Input.Transform.rect.height - Input.Transform.anchoredPosition.y - (Input.Transform.rect.height * 0.5f);
|
||||
var viewportMax = viewportMin - Panel.InputScroller.ViewportRect.rect.height;
|
||||
float viewportMin = Input.Transform.rect.height - Input.Transform.anchoredPosition.y - (Input.Transform.rect.height * 0.5f);
|
||||
float viewportMax = viewportMin - Panel.InputScroller.ViewportRect.rect.height;
|
||||
|
||||
float diff = 0f;
|
||||
if (charTop > viewportMin)
|
||||
@ -374,118 +363,101 @@ namespace UnityExplorer.CSConsole
|
||||
|
||||
if (Math.Abs(diff) > 1)
|
||||
{
|
||||
var rect = Input.Transform;
|
||||
RectTransform rect = Input.Transform;
|
||||
rect.anchoredPosition = new Vector2(rect.anchoredPosition.x, rect.anchoredPosition.y - diff);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void SetCaretPosition(int caretPosition)
|
||||
public static void SetCaretPosition(int caretPosition)
|
||||
{
|
||||
Input.Component.caretPosition = caretPosition;
|
||||
|
||||
// Fix to make sure we always really set the caret position.
|
||||
// Yields a frame and fixes text-selection issues.
|
||||
settingCaretCoroutine = true;
|
||||
Input.Component.readOnly = true;
|
||||
RuntimeHelper.StartCoroutine(SetCaretCoroutine(caretPosition));
|
||||
RuntimeHelper.StartCoroutine(DoSetCaretCoroutine(caretPosition));
|
||||
}
|
||||
|
||||
static void InitEventSystemPropertyHandlers()
|
||||
static IEnumerator DoSetCaretCoroutine(int caretPosition)
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (var member in typeof(EventSystem).GetMembers(AccessTools.all))
|
||||
{
|
||||
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}");
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
var color = Input.Component.selectionColor;
|
||||
Color color = Input.Component.selectionColor;
|
||||
color.a = 0f;
|
||||
Input.Component.selectionColor = color;
|
||||
|
||||
try { SetCurrentSelectedGameObject(CursorUnlocker.CurrentEventSystem, null); }
|
||||
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 ~~~~~~~~~
|
||||
|
||||
EventSystemHelper.SetSelectionGuard(false);
|
||||
Input.Component.Select();
|
||||
|
||||
yield return null; // ~~~~~~~ YIELD FRAME ~~~~~~~~~
|
||||
|
||||
Input.Component.caretPosition = caretPosition;
|
||||
Input.Component.selectionFocusPosition = caretPosition;
|
||||
LastCaretPosition = Input.Component.caretPosition;
|
||||
|
||||
color.a = defaultInputFieldAlpha;
|
||||
color.a = DefaultInputFieldAlpha;
|
||||
Input.Component.selectionColor = color;
|
||||
|
||||
Input.Component.readOnly = false;
|
||||
settingCaretCoroutine = false;
|
||||
}
|
||||
|
||||
// For Home and End keys
|
||||
static void JumpToStartOrEndOfLine(bool toStart)
|
||||
{
|
||||
// Determine the current and next line
|
||||
UILineInfo thisline = default;
|
||||
UILineInfo? nextLine = null;
|
||||
for (int i = 0; i < Input.Component.cachedInputTextGenerator.lineCount; i++)
|
||||
{
|
||||
UILineInfo line = Input.Component.cachedInputTextGenerator.lines[i];
|
||||
|
||||
if (line.startCharIdx > LastCaretPosition)
|
||||
{
|
||||
nextLine = line;
|
||||
break;
|
||||
}
|
||||
thisline = line;
|
||||
}
|
||||
|
||||
if (toStart)
|
||||
{
|
||||
// Determine where the indented text begins
|
||||
int endOfLine = nextLine == null ? Input.Text.Length : nextLine.Value.startCharIdx;
|
||||
int indentedStart = thisline.startCharIdx;
|
||||
while (indentedStart < endOfLine - 1 && char.IsWhiteSpace(Input.Text[indentedStart]))
|
||||
indentedStart++;
|
||||
|
||||
// Jump to either the true start or the non-whitespace position,
|
||||
// depending on which one we are not at.
|
||||
if (LastCaretPosition == indentedStart)
|
||||
SetCaretPosition(thisline.startCharIdx);
|
||||
else
|
||||
SetCaretPosition(indentedStart);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If there is no next line, jump to the end of this line (+1, to the invisible next character position)
|
||||
if (nextLine == null)
|
||||
SetCaretPosition(Input.Text.Length);
|
||||
else // jump to the next line start index - 1, ie. end of this line
|
||||
SetCaretPosition(nextLine.Value.startCharIdx - 1);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Lexer Highlighting
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if caret is inside string or comment, false otherwise
|
||||
/// </summary>
|
||||
private static bool HighlightVisibleInput()
|
||||
private static void HighlightVisibleInput(out bool inStringOrComment)
|
||||
{
|
||||
inStringOrComment = false;
|
||||
if (string.IsNullOrEmpty(Input.Text))
|
||||
{
|
||||
Panel.HighlightText.text = "";
|
||||
Panel.LineNumberText.text = "1";
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate the visible lines
|
||||
@ -495,12 +467,12 @@ namespace UnityExplorer.CSConsole
|
||||
|
||||
// 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.
|
||||
var viewportMin = Input.Transform.rect.height - Input.Transform.anchoredPosition.y - (Input.Transform.rect.height * 0.5f);
|
||||
var viewportMax = viewportMin - Panel.InputScroller.ViewportRect.rect.height;
|
||||
float viewportMin = Input.Transform.rect.height - Input.Transform.anchoredPosition.y - (Input.Transform.rect.height * 0.5f);
|
||||
float viewportMax = viewportMin - Panel.InputScroller.ViewportRect.rect.height;
|
||||
|
||||
for (int i = 0; i < Input.TextGenerator.lineCount; i++)
|
||||
{
|
||||
var line = Input.TextGenerator.lines[i];
|
||||
UILineInfo line = Input.TextGenerator.lines[i];
|
||||
// if not set the top line yet, and top of line is below the viewport top
|
||||
if (topLine == -1 && line.topY <= viewportMin)
|
||||
topLine = i;
|
||||
@ -520,7 +492,7 @@ namespace UnityExplorer.CSConsole
|
||||
|
||||
// Highlight the visible text with the LexerBuilder
|
||||
|
||||
Panel.HighlightText.text = Lexer.BuildHighlightedString(Input.Text, startIdx, endIdx, topLine, LastCaretPosition, out bool ret);
|
||||
Panel.HighlightText.text = Lexer.BuildHighlightedString(Input.Text, startIdx, endIdx, topLine, LastCaretPosition, out inStringOrComment);
|
||||
|
||||
// Set the line numbers
|
||||
|
||||
@ -534,7 +506,7 @@ namespace UnityExplorer.CSConsole
|
||||
realStartLine++;
|
||||
char lastPrev = '\n';
|
||||
|
||||
var sb = new StringBuilder();
|
||||
StringBuilder sb = new();
|
||||
|
||||
// append leading new lines for spacing (no point rendering line numbers we cant see)
|
||||
for (int i = 0; i < topLine; i++)
|
||||
@ -558,7 +530,7 @@ namespace UnityExplorer.CSConsole
|
||||
|
||||
Panel.LineNumberText.text = sb.ToString();
|
||||
|
||||
return ret;
|
||||
return;
|
||||
}
|
||||
|
||||
#endregion
|
||||
@ -598,13 +570,11 @@ namespace UnityExplorer.CSConsole
|
||||
|
||||
#region Auto indenting
|
||||
|
||||
private static int prevContentLen = 0;
|
||||
|
||||
private static void DoAutoIndent()
|
||||
{
|
||||
if (Input.Text.Length > prevContentLen)
|
||||
if (Input.Text.Length > previousContentLength)
|
||||
{
|
||||
int inc = Input.Text.Length - prevContentLen;
|
||||
int inc = Input.Text.Length - previousContentLength;
|
||||
|
||||
if (inc == 1)
|
||||
{
|
||||
@ -623,7 +593,7 @@ namespace UnityExplorer.CSConsole
|
||||
}
|
||||
}
|
||||
|
||||
prevContentLen = Input.Text.Length;
|
||||
previousContentLength = Input.Text.Length;
|
||||
}
|
||||
|
||||
#endregion
|
||||
@ -631,8 +601,6 @@ namespace UnityExplorer.CSConsole
|
||||
|
||||
#region "Help" interaction
|
||||
|
||||
private static bool SRENotSupported;
|
||||
|
||||
private static void DisableConsole(Exception ex)
|
||||
{
|
||||
SRENotSupported = true;
|
||||
@ -676,7 +644,7 @@ Doorstop example:
|
||||
|
||||
public static void SetupHelpInteraction()
|
||||
{
|
||||
var drop = Panel.HelpDropdown;
|
||||
Dropdown drop = Panel.HelpDropdown;
|
||||
|
||||
helpDict.Add("Help", "");
|
||||
helpDict.Add("Usings", HELP_USINGS);
|
||||
@ -684,7 +652,7 @@ Doorstop example:
|
||||
helpDict.Add("Classes", HELP_CLASSES);
|
||||
helpDict.Add("Coroutines", HELP_COROUTINES);
|
||||
|
||||
foreach (var opt in helpDict)
|
||||
foreach (KeyValuePair<string, string> opt in helpDict)
|
||||
drop.options.Add(new Dropdown.OptionData(opt.Key));
|
||||
}
|
||||
|
||||
@ -693,7 +661,7 @@ Doorstop example:
|
||||
if (index == 0)
|
||||
return;
|
||||
|
||||
var helpText = helpDict.ElementAt(index);
|
||||
KeyValuePair<string, string> helpText = helpDict.ElementAt(index);
|
||||
|
||||
Input.Text = helpText.Value;
|
||||
|
||||
@ -706,7 +674,7 @@ Doorstop example:
|
||||
// It is recommended to use the Log panel (or a console log window) while using this tool.
|
||||
// Use the Help dropdown to see detailed examples of how to use the console.
|
||||
|
||||
// To execute a script automatically on startup, put the script at 'UnityExplorer\Scripts\startup.cs'</color>";
|
||||
// To execute a script automatically on startup, put the script at 'sinai-dev-UnityExplorer\Scripts\startup.cs'</color>";
|
||||
|
||||
internal const string HELP_USINGS = @"// You can add a using directive to any namespace, but you must compile for it to take effect.
|
||||
// It will remain in effect until you Reset the console.
|
||||
|
@ -1,13 +1,5 @@
|
||||
using Mono.CSharp;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using System.Text;
|
||||
using UnityExplorer.CSConsole.Lexers;
|
||||
using UniverseLib;
|
||||
using UniverseLib.Utility;
|
||||
|
||||
namespace UnityExplorer.CSConsole
|
||||
{
|
||||
@ -22,17 +14,15 @@ namespace UnityExplorer.CSConsole
|
||||
|
||||
public class LexerBuilder
|
||||
{
|
||||
#region Core and initialization
|
||||
|
||||
public const char WHITESPACE = ' ';
|
||||
public readonly HashSet<char> IndentOpenChars = new HashSet<char> { '{', '(' };
|
||||
public readonly HashSet<char> IndentCloseChars = new HashSet<char> { '}', ')' };
|
||||
public readonly HashSet<char> IndentOpenChars = new() { '{', '(' };
|
||||
public readonly HashSet<char> IndentCloseChars = new() { '}', ')' };
|
||||
|
||||
private readonly Lexer[] lexers;
|
||||
private readonly HashSet<char> delimiters = new HashSet<char>();
|
||||
private readonly HashSet<char> delimiters = new();
|
||||
|
||||
private readonly StringLexer stringLexer = new StringLexer();
|
||||
private readonly CommentLexer commentLexer = new CommentLexer();
|
||||
private readonly StringLexer stringLexer = new();
|
||||
private readonly CommentLexer commentLexer = new();
|
||||
|
||||
public LexerBuilder()
|
||||
{
|
||||
@ -45,7 +35,7 @@ namespace UnityExplorer.CSConsole
|
||||
new KeywordLexer(),
|
||||
};
|
||||
|
||||
foreach (var matcher in lexers)
|
||||
foreach (Lexer matcher in lexers)
|
||||
{
|
||||
foreach (char c in matcher.Delimiters)
|
||||
{
|
||||
@ -55,8 +45,6 @@ namespace UnityExplorer.CSConsole
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>The last committed index for a match or no-match. Starts at -1 for a new parse.</summary>
|
||||
public int CommittedIndex { get; private set; }
|
||||
/// <summary>The index of the character we are currently parsing, at minimum it will be CommittedIndex + 1.</summary>
|
||||
@ -97,13 +85,13 @@ namespace UnityExplorer.CSConsole
|
||||
currentStartIdx = startIdx;
|
||||
currentEndIdx = endIdx;
|
||||
|
||||
var sb = new StringBuilder();
|
||||
StringBuilder sb = new();
|
||||
|
||||
for (int i = 0; i < leadingLines; i++)
|
||||
sb.Append('\n');
|
||||
|
||||
int lastUnhighlighted = startIdx;
|
||||
foreach (var match in GetMatches())
|
||||
foreach (MatchInfo match in GetMatches())
|
||||
{
|
||||
// append non-highlighted text between last match and this
|
||||
for (int i = lastUnhighlighted; i < match.startIndex; i++)
|
||||
@ -130,7 +118,7 @@ namespace UnityExplorer.CSConsole
|
||||
}
|
||||
|
||||
// check caretIdx to determine inStringOrComment state
|
||||
if (caretIdx >= match.startIndex && (caretIdx <= (matchEndIdx+1) || (caretIdx >= input.Length && matchEndIdx >= input.Length - 1)))
|
||||
if (caretIdx >= match.startIndex && (caretIdx <= (matchEndIdx + 1) || (caretIdx >= input.Length && matchEndIdx >= input.Length - 1)))
|
||||
caretInStringOrComment = match.isStringOrComment;
|
||||
}
|
||||
|
||||
@ -158,7 +146,7 @@ namespace UnityExplorer.CSConsole
|
||||
bool anyMatch = false;
|
||||
int startIndex = CommittedIndex + 1;
|
||||
|
||||
foreach (var lexer in lexers)
|
||||
foreach (Lexer lexer in lexers)
|
||||
{
|
||||
if (lexer.TryMatchCurrent(this))
|
||||
{
|
||||
|
@ -1,8 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityExplorer.CSConsole.Lexers
|
||||
namespace UnityExplorer.CSConsole.Lexers
|
||||
{
|
||||
public class CommentLexer : Lexer
|
||||
{
|
||||
@ -13,7 +9,7 @@ namespace UnityExplorer.CSConsole.Lexers
|
||||
}
|
||||
|
||||
// forest green
|
||||
protected override Color HighlightColor => new Color(0.34f, 0.65f, 0.29f, 1.0f);
|
||||
protected override Color HighlightColor => new(0.34f, 0.65f, 0.29f, 1.0f);
|
||||
|
||||
public override bool TryMatchCurrent(LexerBuilder lexer)
|
||||
{
|
||||
|
@ -1,15 +1,13 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using System.Text;
|
||||
|
||||
namespace UnityExplorer.CSConsole.Lexers
|
||||
{
|
||||
public class KeywordLexer : Lexer
|
||||
{
|
||||
// system blue
|
||||
protected override Color HighlightColor => new Color(0.33f, 0.61f, 0.83f, 1.0f);
|
||||
protected override Color HighlightColor => new(0.33f, 0.61f, 0.83f, 1.0f);
|
||||
|
||||
public static readonly HashSet<string> keywords = new HashSet<string>
|
||||
public static readonly HashSet<string> keywords = new()
|
||||
{
|
||||
// reserved keywords
|
||||
"abstract", "as", "base", "bool", "break", "byte", "case", "catch", "char", "checked", "class", "const", "continue",
|
||||
@ -28,15 +26,15 @@ namespace UnityExplorer.CSConsole.Lexers
|
||||
|
||||
public override bool TryMatchCurrent(LexerBuilder lexer)
|
||||
{
|
||||
var prev = lexer.Previous;
|
||||
var first = lexer.Current;
|
||||
char prev = lexer.Previous;
|
||||
char first = lexer.Current;
|
||||
|
||||
// check for keywords
|
||||
if (lexer.IsDelimiter(prev, true) && char.IsLetter(first))
|
||||
{
|
||||
// can be a keyword...
|
||||
|
||||
var sb = new StringBuilder();
|
||||
StringBuilder sb = new();
|
||||
sb.Append(lexer.Current);
|
||||
while (!lexer.EndOfInput && char.IsLetter(lexer.PeekNext()))
|
||||
sb.Append(lexer.Current);
|
||||
|
@ -1,10 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UniverseLib;
|
||||
using UniverseLib.Utility;
|
||||
|
||||
namespace UnityExplorer.CSConsole.Lexers
|
||||
namespace UnityExplorer.CSConsole.Lexers
|
||||
{
|
||||
public abstract class Lexer
|
||||
{
|
||||
|
@ -1,11 +1,9 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityExplorer.CSConsole.Lexers
|
||||
namespace UnityExplorer.CSConsole.Lexers
|
||||
{
|
||||
public class NumberLexer : Lexer
|
||||
{
|
||||
// Maroon
|
||||
protected override Color HighlightColor => new Color(0.58f, 0.33f, 0.33f, 1.0f);
|
||||
protected override Color HighlightColor => new(0.58f, 0.33f, 0.33f, 1.0f);
|
||||
|
||||
private bool IsNumeric(char c) => char.IsNumber(c) || c == '.';
|
||||
|
||||
|
@ -1,14 +1,11 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityExplorer.CSConsole.Lexers
|
||||
namespace UnityExplorer.CSConsole.Lexers
|
||||
{
|
||||
public class StringLexer : Lexer
|
||||
{
|
||||
public override IEnumerable<char> Delimiters => new[] { '"', '\'', };
|
||||
|
||||
// orange
|
||||
protected override Color HighlightColor => new Color(0.79f, 0.52f, 0.32f, 1.0f);
|
||||
protected override Color HighlightColor => new(0.79f, 0.52f, 0.32f, 1.0f);
|
||||
|
||||
public override bool TryMatchCurrent(LexerBuilder lexer)
|
||||
{
|
||||
|
@ -1,21 +1,16 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityExplorer.CSConsole.Lexers
|
||||
namespace UnityExplorer.CSConsole.Lexers
|
||||
{
|
||||
public class SymbolLexer : Lexer
|
||||
{
|
||||
// silver
|
||||
protected override Color HighlightColor => new Color(0.6f, 0.6f, 0.6f);
|
||||
protected override Color HighlightColor => new(0.6f, 0.6f, 0.6f);
|
||||
|
||||
// all symbols are delimiters
|
||||
public override IEnumerable<char> Delimiters => symbols.Where(it => it != '.'); // '.' is not a delimiter, only a separator.
|
||||
|
||||
public static bool IsSymbol(char c) => symbols.Contains(c);
|
||||
|
||||
public static readonly HashSet<char> symbols = new HashSet<char>
|
||||
public static readonly HashSet<char> symbols = new()
|
||||
{
|
||||
'[', '{', '(', // open
|
||||
']', '}', ')', // close
|
||||
@ -33,13 +28,7 @@ namespace UnityExplorer.CSConsole.Lexers
|
||||
|
||||
if (IsSymbol(lexer.Current))
|
||||
{
|
||||
do
|
||||
{
|
||||
lexer.Commit();
|
||||
lexer.PeekNext();
|
||||
}
|
||||
while (IsSymbol(lexer.Current));
|
||||
|
||||
lexer.Commit();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,5 @@
|
||||
using Mono.CSharp;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using UnityExplorer.Config;
|
||||
|
||||
// Thanks to ManlyMarco for this
|
||||
|
||||
@ -11,14 +7,17 @@ namespace UnityExplorer.CSConsole
|
||||
{
|
||||
public class ScriptEvaluator : Evaluator, IDisposable
|
||||
{
|
||||
private static readonly HashSet<string> StdLib = new(StringComparer.InvariantCultureIgnoreCase)
|
||||
{
|
||||
"mscorlib", "System.Core", "System", "System.Xml"
|
||||
};
|
||||
|
||||
internal TextWriter _textWriter;
|
||||
internal static StreamReportPrinter _reportPrinter;
|
||||
|
||||
private static readonly HashSet<string> StdLib = new(StringComparer.InvariantCultureIgnoreCase)
|
||||
{
|
||||
"mscorlib",
|
||||
"System.Core",
|
||||
"System",
|
||||
"System.Xml"
|
||||
};
|
||||
|
||||
public ScriptEvaluator(TextWriter tw) : base(BuildContext(tw))
|
||||
{
|
||||
_textWriter = tw;
|
||||
@ -45,9 +44,20 @@ namespace UnityExplorer.CSConsole
|
||||
|
||||
private void Reference(Assembly asm)
|
||||
{
|
||||
var name = asm.GetName().Name;
|
||||
if (name == "completions")
|
||||
string name = asm.GetName().Name;
|
||||
|
||||
if (name == "completions") // ignore assemblies generated by mcs' autocomplete.
|
||||
return;
|
||||
|
||||
foreach (string blacklisted in ConfigManager.CSConsole_Assembly_Blacklist.Value.Split(';'))
|
||||
{
|
||||
string bl = blacklisted;
|
||||
if (bl.EndsWith(".dll", StringComparison.OrdinalIgnoreCase))
|
||||
bl = blacklisted.Substring(0, bl.Length - 4);
|
||||
if (string.Equals(bl, name, StringComparison.OrdinalIgnoreCase))
|
||||
return;
|
||||
}
|
||||
|
||||
ReferenceAssembly(asm);
|
||||
}
|
||||
|
||||
@ -55,7 +65,7 @@ namespace UnityExplorer.CSConsole
|
||||
{
|
||||
_reportPrinter = new StreamReportPrinter(tw);
|
||||
|
||||
var settings = new CompilerSettings
|
||||
CompilerSettings settings = new()
|
||||
{
|
||||
Version = LanguageVersion.Experimental,
|
||||
GenerateDebugInfo = false,
|
||||
|
@ -1,14 +1,8 @@
|
||||
using HarmonyLib;
|
||||
using Mono.CSharp;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityExplorer.Runtime;
|
||||
using UnityExplorer.UI.Panels;
|
||||
using UniverseLib;
|
||||
|
||||
namespace UnityExplorer.CSConsole
|
||||
{
|
||||
@ -29,16 +23,16 @@ namespace UnityExplorer.CSConsole
|
||||
public static void Inspect(Type type)
|
||||
=> InspectorManager.Inspect(type);
|
||||
|
||||
public static Coroutine Start(IEnumerator ienumerator)
|
||||
public static Coroutine Start(IEnumerator ienumerator)
|
||||
=> RuntimeHelper.StartCoroutine(ienumerator);
|
||||
|
||||
public static void Stop(Coroutine coro)
|
||||
=> RuntimeHelper.StopCoroutine(coro);
|
||||
|
||||
public static void Copy(object obj)
|
||||
public static void Copy(object obj)
|
||||
=> ClipboardPanel.Copy(obj);
|
||||
|
||||
public static object Paste()
|
||||
public static object Paste()
|
||||
=> ClipboardPanel.Current;
|
||||
|
||||
public static void GetUsing()
|
||||
@ -46,7 +40,7 @@ namespace UnityExplorer.CSConsole
|
||||
|
||||
public static void GetVars()
|
||||
{
|
||||
var vars = Evaluator.GetVars()?.Trim();
|
||||
string vars = Evaluator.GetVars()?.Trim();
|
||||
if (string.IsNullOrEmpty(vars))
|
||||
ExplorerCore.LogWarning("No variables seem to be defined!");
|
||||
else
|
||||
@ -59,12 +53,12 @@ namespace UnityExplorer.CSConsole
|
||||
.GetValue(Evaluator) is CompilationSourceFile sourceFile
|
||||
&& sourceFile.Containers.Any())
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
StringBuilder sb = new();
|
||||
sb.Append($"There are {sourceFile.Containers.Count} defined classes:");
|
||||
foreach (TypeDefinition type in sourceFile.Containers.Where(it => it is TypeDefinition))
|
||||
{
|
||||
sb.Append($"\n\n{type.MemberName.Name}:");
|
||||
foreach (var member in type.Members)
|
||||
foreach (MemberCore member in type.Members)
|
||||
sb.Append($"\n\t- {member.AttributeTargets}: \"{member.MemberName.Name}\" ({member.ModFlags})");
|
||||
}
|
||||
Log(sb.ToString());
|
||||
|
@ -1,9 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityExplorer.CacheObject.Views;
|
||||
using UnityExplorer.Config;
|
||||
using UnityExplorer.CacheObject.Views;
|
||||
|
||||
namespace UnityExplorer.CacheObject
|
||||
{
|
||||
|
@ -1,10 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using UnityExplorer.Inspectors;
|
||||
using UniverseLib.Utility;
|
||||
using UnityExplorer.Inspectors;
|
||||
|
||||
namespace UnityExplorer.CacheObject
|
||||
{
|
||||
@ -52,7 +46,7 @@ namespace UnityExplorer.CacheObject
|
||||
Arguments = CtorInfo.GetParameters();
|
||||
ctorReturnType = CtorInfo.DeclaringType;
|
||||
}
|
||||
|
||||
|
||||
if (ctorReturnType.IsGenericTypeDefinition)
|
||||
GenericArguments = ctorReturnType.GetGenericArguments();
|
||||
}
|
||||
|
@ -1,9 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using UnityExplorer.Inspectors;
|
||||
using UnityExplorer.Inspectors;
|
||||
|
||||
namespace UnityExplorer.CacheObject
|
||||
{
|
||||
@ -31,7 +26,7 @@ namespace UnityExplorer.CacheObject
|
||||
{
|
||||
try
|
||||
{
|
||||
var ret = FieldInfo.GetValue(DeclaringInstance);
|
||||
object ret = FieldInfo.GetValue(DeclaringInstance);
|
||||
LastException = null;
|
||||
return ret;
|
||||
}
|
||||
|
@ -1,11 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityExplorer.CacheObject.IValues;
|
||||
using UnityExplorer.CacheObject.IValues;
|
||||
using UnityExplorer.CacheObject.Views;
|
||||
using UniverseLib;
|
||||
using UniverseLib.Utility;
|
||||
|
||||
namespace UnityExplorer.CacheObject
|
||||
{
|
||||
@ -41,7 +35,7 @@ namespace UnityExplorer.CacheObject
|
||||
this.DictKey = key;
|
||||
this.DisplayedKey = key.TryCast();
|
||||
|
||||
var type = DisplayedKey.GetType();
|
||||
Type type = DisplayedKey.GetType();
|
||||
if (ParseUtility.CanParse(type))
|
||||
{
|
||||
KeyInputWanted = true;
|
||||
@ -60,7 +54,7 @@ namespace UnityExplorer.CacheObject
|
||||
{
|
||||
base.SetDataToCell(cell);
|
||||
|
||||
var kvpCell = cell as CacheKeyValuePairCell;
|
||||
CacheKeyValuePairCell kvpCell = cell as CacheKeyValuePairCell;
|
||||
|
||||
kvpCell.NameLabel.text = $"{DictIndex}:";
|
||||
kvpCell.HiddenNameLabel.Text = "";
|
||||
|
@ -1,8 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityExplorer.CacheObject.IValues;
|
||||
using UnityExplorer.CacheObject.IValues;
|
||||
using UnityExplorer.CacheObject.Views;
|
||||
|
||||
namespace UnityExplorer.CacheObject
|
||||
@ -25,7 +21,7 @@ namespace UnityExplorer.CacheObject
|
||||
{
|
||||
base.SetDataToCell(cell);
|
||||
|
||||
var listCell = cell as CacheListEntryCell;
|
||||
CacheListEntryCell listCell = cell as CacheListEntryCell;
|
||||
|
||||
listCell.NameLabel.text = $"{ListIndex}:";
|
||||
listCell.HiddenNameLabel.Text = "";
|
||||
|
@ -1,21 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityExplorer.Runtime;
|
||||
using UnityExplorer.CacheObject.Views;
|
||||
using UnityExplorer.CacheObject.Views;
|
||||
using UnityExplorer.Inspectors;
|
||||
using UniverseLib.UI.Models;
|
||||
using UnityExplorer.UI;
|
||||
using UniverseLib;
|
||||
using UniverseLib.UI;
|
||||
using UnityExplorer.UI.Widgets;
|
||||
using UniverseLib.Utility;
|
||||
using UniverseLib.UI.ObjectPool;
|
||||
using System.Collections;
|
||||
using HarmonyLib;
|
||||
|
||||
namespace UnityExplorer.CacheObject
|
||||
{
|
||||
@ -38,8 +24,8 @@ namespace UnityExplorer.CacheObject
|
||||
this.Owner = inspector;
|
||||
this.NameLabelText = this switch
|
||||
{
|
||||
CacheMethod => SignatureHighlighter.HighlightMethod(member as MethodInfo),
|
||||
CacheConstructor => SignatureHighlighter.HighlightConstructor(member as ConstructorInfo),
|
||||
CacheMethod => SignatureHighlighter.ParseMethod(member as MethodInfo),
|
||||
CacheConstructor => SignatureHighlighter.ParseConstructor(member as ConstructorInfo),
|
||||
_ => SignatureHighlighter.Parse(member.DeclaringType, false, member),
|
||||
};
|
||||
|
||||
@ -105,7 +91,7 @@ namespace UnityExplorer.CacheObject
|
||||
|
||||
protected override bool TryAutoEvaluateIfUnitialized(CacheObjectCell objectcell)
|
||||
{
|
||||
var cell = objectcell as CacheMemberCell;
|
||||
CacheMemberCell cell = objectcell as CacheMemberCell;
|
||||
|
||||
cell.EvaluateHolder.SetActive(!ShouldAutoEvaluate);
|
||||
if (!ShouldAutoEvaluate)
|
||||
|
@ -1,14 +1,6 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using HarmonyLib;
|
||||
using UnityExplorer.Inspectors;
|
||||
using UnityExplorer.Runtime;
|
||||
using UniverseLib;
|
||||
using HarmonyLib;
|
||||
using HarmonyLib.Tools;
|
||||
|
||||
namespace UnityExplorer.CacheObject
|
||||
{
|
||||
@ -75,8 +67,8 @@ namespace UnityExplorer.CacheObject
|
||||
return sorted;
|
||||
}
|
||||
|
||||
static void TryCacheMember<T>(MemberInfo member, List<T> list, HashSet<string> cachedSigs,
|
||||
Type declaringType, ReflectionInspector inspector, bool ignorePropertyMethodInfos = true)
|
||||
static void TryCacheMember<T>(MemberInfo member, List<T> list, HashSet<string> cachedSigs,
|
||||
Type declaringType, ReflectionInspector inspector, bool ignorePropertyMethodInfos = true)
|
||||
where T : CacheMember
|
||||
{
|
||||
try
|
||||
|
@ -1,11 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using UnityExplorer.Inspectors;
|
||||
using UniverseLib;
|
||||
using UniverseLib.Utility;
|
||||
using UnityExplorer.Inspectors;
|
||||
|
||||
namespace UnityExplorer.CacheObject
|
||||
{
|
||||
@ -18,7 +11,7 @@ namespace UnityExplorer.CacheObject
|
||||
|
||||
public override bool ShouldAutoEvaluate => false;
|
||||
|
||||
public CacheMethod (MethodInfo mi)
|
||||
public CacheMethod(MethodInfo mi)
|
||||
{
|
||||
this.MethodInfo = mi;
|
||||
}
|
||||
@ -36,14 +29,14 @@ namespace UnityExplorer.CacheObject
|
||||
{
|
||||
try
|
||||
{
|
||||
var methodInfo = MethodInfo;
|
||||
MethodInfo methodInfo = MethodInfo;
|
||||
if (methodInfo.IsGenericMethod)
|
||||
methodInfo = MethodInfo.MakeGenericMethod(Evaluator.TryParseGenericArguments());
|
||||
|
||||
object ret;
|
||||
if (HasArguments)
|
||||
ret = methodInfo.Invoke(DeclaringInstance, Evaluator.TryParseArguments());
|
||||
else
|
||||
else
|
||||
ret = methodInfo.Invoke(DeclaringInstance, ArgumentUtility.EmptyArgs);
|
||||
LastException = null;
|
||||
return ret;
|
||||
|
@ -1,19 +1,7 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.Runtime;
|
||||
using System.Collections;
|
||||
using UnityExplorer.CacheObject.IValues;
|
||||
using UnityExplorer.CacheObject.Views;
|
||||
using UniverseLib.UI.Models;
|
||||
using UnityExplorer.UI;
|
||||
using UniverseLib;
|
||||
using UniverseLib.UI;
|
||||
using UniverseLib.Utility;
|
||||
using UniverseLib.UI.ObjectPool;
|
||||
|
||||
namespace UnityExplorer.CacheObject
|
||||
@ -36,28 +24,31 @@ namespace UnityExplorer.CacheObject
|
||||
public abstract class CacheObjectBase
|
||||
{
|
||||
public ICacheObjectController Owner { get; set; }
|
||||
|
||||
public CacheObjectCell CellView { get; internal set; }
|
||||
|
||||
public object Value { get; protected set; }
|
||||
public Type FallbackType { get; protected set; }
|
||||
public bool LastValueWasNull { get; private set; }
|
||||
|
||||
public ValueState State = ValueState.NotEvaluated;
|
||||
public Type LastValueType;
|
||||
public ValueState State { get; set; }
|
||||
public Exception LastException { get; protected set; }
|
||||
bool valueIsNull;
|
||||
Type currentValueType;
|
||||
|
||||
// InteractiveValues
|
||||
public InteractiveValue IValue { get; private set; }
|
||||
public Type CurrentIValueType { get; private set; }
|
||||
public bool SubContentShowWanted { get; private set; }
|
||||
|
||||
// UI
|
||||
public string NameLabelText { get; protected set; }
|
||||
public string NameLabelTextRaw { get; protected set; }
|
||||
public string ValueLabelText { get; protected set; }
|
||||
|
||||
// Abstract
|
||||
public abstract bool ShouldAutoEvaluate { get; }
|
||||
public abstract bool HasArguments { get; }
|
||||
public abstract bool CanWrite { get; }
|
||||
public Exception LastException { get; protected set; }
|
||||
|
||||
protected const string NOT_YET_EVAL = "<color=grey>Not yet evaluated</color>";
|
||||
|
||||
public virtual void SetFallbackType(Type fallbackType)
|
||||
{
|
||||
@ -65,17 +56,6 @@ namespace UnityExplorer.CacheObject
|
||||
this.ValueLabelText = GetValueLabel();
|
||||
}
|
||||
|
||||
protected const string NOT_YET_EVAL = "<color=grey>Not yet evaluated</color>";
|
||||
|
||||
public virtual void ReleasePooledObjects()
|
||||
{
|
||||
if (this.IValue != null)
|
||||
ReleaseIValue();
|
||||
|
||||
if (this.CellView != null)
|
||||
UnlinkFromView();
|
||||
}
|
||||
|
||||
public virtual void SetView(CacheObjectCell cellView)
|
||||
{
|
||||
this.CellView = cellView;
|
||||
@ -94,6 +74,15 @@ namespace UnityExplorer.CacheObject
|
||||
this.IValue.UIRoot.transform.SetParent(InactiveIValueHolder.transform, false);
|
||||
}
|
||||
|
||||
public virtual void ReleasePooledObjects()
|
||||
{
|
||||
if (this.IValue != null)
|
||||
ReleaseIValue();
|
||||
|
||||
if (this.CellView != null)
|
||||
UnlinkFromView();
|
||||
}
|
||||
|
||||
// Updating and applying values
|
||||
|
||||
// The only method which sets the CacheObjectBase.Value
|
||||
@ -134,22 +123,22 @@ namespace UnityExplorer.CacheObject
|
||||
|
||||
protected virtual void ProcessOnEvaluate()
|
||||
{
|
||||
var prevState = State;
|
||||
ValueState prevState = State;
|
||||
|
||||
if (LastException != null)
|
||||
{
|
||||
LastValueWasNull = true;
|
||||
LastValueType = FallbackType;
|
||||
valueIsNull = true;
|
||||
currentValueType = FallbackType;
|
||||
State = ValueState.Exception;
|
||||
}
|
||||
else if (Value.IsNullOrDestroyed())
|
||||
{
|
||||
LastValueWasNull = true;
|
||||
valueIsNull = true;
|
||||
State = GetStateForType(FallbackType);
|
||||
}
|
||||
else
|
||||
{
|
||||
LastValueWasNull = false;
|
||||
valueIsNull = false;
|
||||
State = GetStateForType(Value.GetActualType());
|
||||
}
|
||||
|
||||
@ -171,10 +160,10 @@ namespace UnityExplorer.CacheObject
|
||||
|
||||
public ValueState GetStateForType(Type type)
|
||||
{
|
||||
if (LastValueType == type && (State != ValueState.Exception || LastException != null))
|
||||
if (currentValueType == type && (State != ValueState.Exception || LastException != null))
|
||||
return State;
|
||||
|
||||
LastValueType = type;
|
||||
currentValueType = type;
|
||||
if (type == typeof(bool))
|
||||
return ValueState.Boolean;
|
||||
else if (type.IsPrimitive || type == typeof(decimal))
|
||||
@ -197,7 +186,7 @@ namespace UnityExplorer.CacheObject
|
||||
|
||||
protected string GetValueLabel()
|
||||
{
|
||||
string label = "";
|
||||
string label = string.Empty;
|
||||
|
||||
switch (State)
|
||||
{
|
||||
@ -214,19 +203,19 @@ namespace UnityExplorer.CacheObject
|
||||
|
||||
// and valuestruct also doesnt want it if we can parse it
|
||||
case ValueState.ValueStruct:
|
||||
if (ParseUtility.CanParse(LastValueType))
|
||||
if (ParseUtility.CanParse(currentValueType))
|
||||
return null;
|
||||
break;
|
||||
|
||||
// string wants it trimmed to max 200 chars
|
||||
case ValueState.String:
|
||||
if (!LastValueWasNull)
|
||||
if (!valueIsNull)
|
||||
return $"\"{ToStringUtility.PruneString(Value as string, 200, 5)}\"";
|
||||
break;
|
||||
|
||||
// try to prefix the count of the collection for lists and dicts
|
||||
case ValueState.Collection:
|
||||
if (!LastValueWasNull)
|
||||
if (!valueIsNull)
|
||||
{
|
||||
if (Value is IList iList)
|
||||
label = $"[{iList.Count}] ";
|
||||
@ -238,7 +227,7 @@ namespace UnityExplorer.CacheObject
|
||||
break;
|
||||
|
||||
case ValueState.Dictionary:
|
||||
if (!LastValueWasNull)
|
||||
if (!valueIsNull)
|
||||
{
|
||||
if (Value is IDictionary iDict)
|
||||
label = $"[{iDict.Count}] ";
|
||||
@ -276,9 +265,9 @@ namespace UnityExplorer.CacheObject
|
||||
|
||||
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);
|
||||
bool canCopy = State != ValueState.NotEvaluated && State != ValueState.Exception;
|
||||
cell.CopyButton.Component.gameObject.SetActive(canCopy);
|
||||
cell.PasteButton.Component.gameObject.SetActive(canCopy && this.CanWrite);
|
||||
}
|
||||
|
||||
if (!evaluated)
|
||||
@ -299,7 +288,7 @@ namespace UnityExplorer.CacheObject
|
||||
SetValueState(cell, new(false, typeLabelActive: true, inputActive: true, applyActive: CanWrite));
|
||||
break;
|
||||
case ValueState.String:
|
||||
if (LastValueWasNull)
|
||||
if (valueIsNull)
|
||||
SetValueState(cell, new(true, subContentButtonActive: true));
|
||||
else
|
||||
SetValueState(cell, new(true, false, SignatureHighlighter.StringOrange, subContentButtonActive: true));
|
||||
@ -309,17 +298,17 @@ namespace UnityExplorer.CacheObject
|
||||
break;
|
||||
case ValueState.Color:
|
||||
case ValueState.ValueStruct:
|
||||
if (ParseUtility.CanParse(LastValueType))
|
||||
if (ParseUtility.CanParse(currentValueType))
|
||||
SetValueState(cell, new(false, false, null, true, false, true, CanWrite, true, true));
|
||||
else
|
||||
SetValueState(cell, new(true, inspectActive: true, subContentButtonActive: true));
|
||||
break;
|
||||
case ValueState.Collection:
|
||||
case ValueState.Dictionary:
|
||||
SetValueState(cell, new(true, inspectActive: !LastValueWasNull, subContentButtonActive: !LastValueWasNull));
|
||||
SetValueState(cell, new(true, inspectActive: !valueIsNull, subContentButtonActive: !valueIsNull));
|
||||
break;
|
||||
case ValueState.Unsupported:
|
||||
SetValueState(cell, new (true, inspectActive: !LastValueWasNull));
|
||||
SetValueState(cell, new(true, inspectActive: !valueIsNull));
|
||||
break;
|
||||
}
|
||||
|
||||
@ -341,7 +330,7 @@ namespace UnityExplorer.CacheObject
|
||||
// Type label (for primitives)
|
||||
cell.TypeLabel.gameObject.SetActive(args.typeLabelActive);
|
||||
if (args.typeLabelActive)
|
||||
cell.TypeLabel.text = SignatureHighlighter.Parse(LastValueType, false);
|
||||
cell.TypeLabel.text = SignatureHighlighter.Parse(currentValueType, false);
|
||||
|
||||
// toggle for bools
|
||||
cell.Toggle.gameObject.SetActive(args.toggleActive);
|
||||
@ -356,7 +345,7 @@ namespace UnityExplorer.CacheObject
|
||||
cell.InputField.UIRoot.SetActive(args.inputActive);
|
||||
if (args.inputActive)
|
||||
{
|
||||
cell.InputField.Text = ParseUtility.ToStringForInput(Value, LastValueType);
|
||||
cell.InputField.Text = ParseUtility.ToStringForInput(Value, currentValueType);
|
||||
cell.InputField.Component.readOnly = !CanWrite;
|
||||
}
|
||||
|
||||
@ -365,12 +354,12 @@ namespace UnityExplorer.CacheObject
|
||||
|
||||
// Inspect button only if last value not null.
|
||||
if (cell.InspectButton != null)
|
||||
cell.InspectButton.Component.gameObject.SetActive(args.inspectActive && !LastValueWasNull);
|
||||
cell.InspectButton.Component.gameObject.SetActive(args.inspectActive && !valueIsNull);
|
||||
|
||||
// set subcontent button if needed, and for null strings and exceptions
|
||||
cell.SubContentButton.Component.gameObject.SetActive(
|
||||
args.subContentButtonActive
|
||||
&& (!LastValueWasNull || State == ValueState.String || State == ValueState.Exception));
|
||||
args.subContentButtonActive
|
||||
&& (!valueIsNull || State == ValueState.String || State == ValueState.Exception));
|
||||
}
|
||||
|
||||
// CacheObjectCell Apply
|
||||
@ -381,7 +370,7 @@ namespace UnityExplorer.CacheObject
|
||||
SetUserValue(this.CellView.Toggle.isOn);
|
||||
else
|
||||
{
|
||||
if (ParseUtility.TryParse(CellView.InputField.Text, LastValueType, out object value, out Exception ex))
|
||||
if (ParseUtility.TryParse(CellView.InputField.Text, currentValueType, out object value, out Exception ex))
|
||||
{
|
||||
SetUserValue(value);
|
||||
}
|
||||
@ -474,12 +463,12 @@ namespace UnityExplorer.CacheObject
|
||||
public Color valueColor;
|
||||
public bool valueActive, valueRichText, typeLabelActive, toggleActive, inputActive, applyActive, inspectActive, subContentButtonActive;
|
||||
|
||||
public ValueStateArgs(bool valueActive = true,
|
||||
bool valueRichText = true,
|
||||
public ValueStateArgs(bool valueActive = true,
|
||||
bool valueRichText = true,
|
||||
Color? valueColor = null,
|
||||
bool typeLabelActive = false,
|
||||
bool toggleActive = false,
|
||||
bool inputActive = false,
|
||||
bool typeLabelActive = false,
|
||||
bool toggleActive = false,
|
||||
bool inputActive = false,
|
||||
bool applyActive = false,
|
||||
bool inspectActive = false,
|
||||
bool subContentButtonActive = false)
|
||||
|
@ -1,11 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityExplorer.Inspectors;
|
||||
using UnityExplorer.Runtime;
|
||||
using UnityExplorer.Inspectors;
|
||||
|
||||
namespace UnityExplorer.CacheObject
|
||||
{
|
||||
|
@ -1,9 +1,4 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityExplorer.CacheObject;
|
||||
using System.Collections;
|
||||
using UnityExplorer.CacheObject.Views;
|
||||
|
||||
namespace UnityExplorer.CacheObject
|
||||
@ -33,7 +28,7 @@ namespace UnityExplorer.CacheObject
|
||||
return;
|
||||
}
|
||||
|
||||
var entry = (CacheObjectBase)cachedEntries[index];
|
||||
CacheObjectBase entry = (CacheObjectBase)cachedEntries[index];
|
||||
|
||||
if (entry.CellView != null && entry.CellView != cell)
|
||||
entry.UnlinkFromView();
|
||||
|
@ -1,14 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.CacheObject;
|
||||
using UnityExplorer.UI;
|
||||
using UniverseLib.UI;
|
||||
using UniverseLib.UI;
|
||||
using UniverseLib.UI.Models;
|
||||
using UniverseLib;
|
||||
|
||||
namespace UnityExplorer.CacheObject.IValues
|
||||
{
|
||||
@ -32,9 +23,9 @@ namespace UnityExplorer.CacheObject.IValues
|
||||
|
||||
applyButton.Component.gameObject.SetActive(owner.CanWrite);
|
||||
|
||||
foreach (var slider in sliders)
|
||||
foreach (Slider slider in sliders)
|
||||
slider.interactable = owner.CanWrite;
|
||||
foreach (var input in inputs)
|
||||
foreach (InputFieldRef input in inputs)
|
||||
input.Component.readOnly = !owner.CanWrite;
|
||||
}
|
||||
|
||||
@ -54,7 +45,7 @@ namespace UnityExplorer.CacheObject.IValues
|
||||
inputs[1].Text = c32.g.ToString();
|
||||
inputs[2].Text = c32.b.ToString();
|
||||
inputs[3].Text = c32.a.ToString();
|
||||
foreach (var slider in sliders)
|
||||
foreach (Slider slider in sliders)
|
||||
slider.maxValue = 255;
|
||||
}
|
||||
else
|
||||
@ -65,7 +56,7 @@ namespace UnityExplorer.CacheObject.IValues
|
||||
inputs[1].Text = EditedColor.g.ToString();
|
||||
inputs[2].Text = EditedColor.b.ToString();
|
||||
inputs[3].Text = EditedColor.a.ToString();
|
||||
foreach (var slider in sliders)
|
||||
foreach (Slider slider in sliders)
|
||||
slider.maxValue = 1;
|
||||
}
|
||||
|
||||
@ -156,12 +147,12 @@ namespace UnityExplorer.CacheObject.IValues
|
||||
|
||||
// hori group
|
||||
|
||||
var horiGroup = UIFactory.CreateHorizontalGroup(UIRoot, "ColorEditor", false, false, true, true, 5,
|
||||
GameObject horiGroup = UIFactory.CreateHorizontalGroup(UIRoot, "ColorEditor", false, false, true, true, 5,
|
||||
default, new Color(1, 1, 1, 0), TextAnchor.MiddleLeft);
|
||||
|
||||
// sliders / inputs
|
||||
|
||||
var grid = UIFactory.CreateGridGroup(horiGroup, "Grid", new Vector2(140, 25), new Vector2(2, 2), new Color(1, 1, 1, 0));
|
||||
GameObject grid = UIFactory.CreateGridGroup(horiGroup, "Grid", new Vector2(140, 25), new Vector2(2, 2), new Color(1, 1, 1, 0));
|
||||
UIFactory.SetLayoutElement(grid, minWidth: 580, minHeight: 25, flexibleWidth: 0);
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
@ -175,7 +166,7 @@ namespace UnityExplorer.CacheObject.IValues
|
||||
|
||||
// image of color
|
||||
|
||||
var imgObj = UIFactory.CreateUIObject("ColorImageHelper", horiGroup);
|
||||
GameObject imgObj = UIFactory.CreateUIObject("ColorImageHelper", horiGroup);
|
||||
UIFactory.SetLayoutElement(imgObj, minHeight: 25, minWidth: 50, flexibleWidth: 50);
|
||||
colorImage = imgObj.AddComponent<Image>();
|
||||
|
||||
@ -184,18 +175,18 @@ namespace UnityExplorer.CacheObject.IValues
|
||||
|
||||
internal void AddEditorRow(int index, GameObject groupObj)
|
||||
{
|
||||
var row = UIFactory.CreateHorizontalGroup(groupObj, "EditorRow_" + fieldNames[index],
|
||||
GameObject row = UIFactory.CreateHorizontalGroup(groupObj, "EditorRow_" + fieldNames[index],
|
||||
false, true, true, true, 5, default, new Color(1, 1, 1, 0));
|
||||
|
||||
var label = UIFactory.CreateLabel(row, "RowLabel", $"{fieldNames[index]}:", TextAnchor.MiddleRight, Color.cyan);
|
||||
Text label = UIFactory.CreateLabel(row, "RowLabel", $"{fieldNames[index]}:", TextAnchor.MiddleRight, Color.cyan);
|
||||
UIFactory.SetLayoutElement(label.gameObject, minWidth: 17, flexibleWidth: 0, minHeight: 25);
|
||||
|
||||
var input = UIFactory.CreateInputField(row, "Input", "...");
|
||||
InputFieldRef input = UIFactory.CreateInputField(row, "Input", "...");
|
||||
UIFactory.SetLayoutElement(input.UIRoot, minWidth: 40, minHeight: 25, flexibleHeight: 0);
|
||||
inputs[index] = input;
|
||||
input.OnValueChanged += (string val) => { OnInputChanged(val, index); };
|
||||
|
||||
var sliderObj = UIFactory.CreateSlider(row, "Slider", out Slider slider);
|
||||
GameObject sliderObj = UIFactory.CreateSlider(row, "Slider", out Slider slider);
|
||||
sliders[index] = slider;
|
||||
UIFactory.SetLayoutElement(sliderObj, minHeight: 25, minWidth: 70, flexibleWidth: 999, flexibleHeight: 0);
|
||||
slider.minValue = 0;
|
||||
|
@ -1,21 +1,8 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.CacheObject;
|
||||
using System.Collections;
|
||||
using UnityExplorer.CacheObject.Views;
|
||||
using UnityExplorer.Inspectors;
|
||||
using UnityExplorer.UI;
|
||||
using UnityExplorer.UI.Panels;
|
||||
using UnityExplorer.UI.Widgets;
|
||||
using UniverseLib;
|
||||
using UniverseLib.UI;
|
||||
using UniverseLib.UI.Widgets;
|
||||
using UniverseLib.UI.Widgets.ScrollView;
|
||||
using UniverseLib.Utility;
|
||||
|
||||
namespace UnityExplorer.CacheObject.IValues
|
||||
{
|
||||
@ -32,7 +19,7 @@ namespace UnityExplorer.CacheObject.IValues
|
||||
public IDictionary RefIDictionary;
|
||||
|
||||
public int ItemCount => cachedEntries.Count;
|
||||
private readonly List<CacheKeyValuePair> cachedEntries = new List<CacheKeyValuePair>();
|
||||
private readonly List<CacheKeyValuePair> cachedEntries = new();
|
||||
|
||||
public ScrollPool<CacheKeyValuePairCell> DictScrollPool { get; private set; }
|
||||
|
||||
@ -61,7 +48,7 @@ namespace UnityExplorer.CacheObject.IValues
|
||||
{
|
||||
RefIDictionary = null;
|
||||
|
||||
foreach (var entry in cachedEntries)
|
||||
foreach (CacheKeyValuePair entry in cachedEntries)
|
||||
{
|
||||
entry.UnlinkFromView();
|
||||
entry.ReleasePooledObjects();
|
||||
@ -80,7 +67,7 @@ namespace UnityExplorer.CacheObject.IValues
|
||||
}
|
||||
else
|
||||
{
|
||||
var type = value.GetActualType();
|
||||
Type type = value.GetActualType();
|
||||
ReflectionUtility.TryGetEntryTypes(type, out KeysType, out ValuesType);
|
||||
|
||||
CacheEntries(value);
|
||||
@ -124,7 +111,7 @@ namespace UnityExplorer.CacheObject.IValues
|
||||
{
|
||||
for (int i = cachedEntries.Count - 1; i >= idx; i--)
|
||||
{
|
||||
var cache = cachedEntries[i];
|
||||
CacheKeyValuePair cache = cachedEntries[i];
|
||||
if (cache.CellView != null)
|
||||
cache.UnlinkFromView();
|
||||
|
||||
@ -153,7 +140,7 @@ namespace UnityExplorer.CacheObject.IValues
|
||||
|
||||
RefIDictionary[key] = value;
|
||||
|
||||
var entry = cachedEntries[keyIndex];
|
||||
CacheKeyValuePair entry = cachedEntries[keyIndex];
|
||||
entry.SetValueFromSource(value);
|
||||
if (entry.CellView != null)
|
||||
entry.SetDataToCell(entry.CellView);
|
||||
@ -177,12 +164,12 @@ namespace UnityExplorer.CacheObject.IValues
|
||||
|
||||
public override void SetLayout()
|
||||
{
|
||||
var minHeight = 5f;
|
||||
float minHeight = 5f;
|
||||
|
||||
KeyTitleLayout.minWidth = AdjustedWidth * 0.44f;
|
||||
ValueTitleLayout.minWidth = AdjustedWidth * 0.55f;
|
||||
|
||||
foreach (var cell in DictScrollPool.CellPool)
|
||||
foreach (CacheKeyValuePairCell cell in DictScrollPool.CellPool)
|
||||
{
|
||||
SetCellLayout(cell);
|
||||
if (cell.Enabled)
|
||||
@ -194,7 +181,7 @@ namespace UnityExplorer.CacheObject.IValues
|
||||
|
||||
private void SetCellLayout(CacheObjectCell objcell)
|
||||
{
|
||||
var cell = objcell as CacheKeyValuePairCell;
|
||||
CacheKeyValuePairCell cell = objcell as CacheKeyValuePairCell;
|
||||
cell.KeyGroupLayout.minWidth = cell.AdjustedWidth * 0.44f;
|
||||
cell.RightGroupLayout.minWidth = cell.AdjustedWidth * 0.55f;
|
||||
|
||||
@ -221,15 +208,15 @@ namespace UnityExplorer.CacheObject.IValues
|
||||
|
||||
// key / value titles
|
||||
|
||||
var titleGroup = UIFactory.CreateUIObject("TitleGroup", UIRoot);
|
||||
GameObject titleGroup = UIFactory.CreateUIObject("TitleGroup", UIRoot);
|
||||
UIFactory.SetLayoutElement(titleGroup, minHeight: 25, flexibleWidth: 9999, flexibleHeight: 0);
|
||||
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(titleGroup, false, true, true, true, padLeft: 65, padRight: 0, childAlignment: TextAnchor.LowerLeft);
|
||||
|
||||
var keyTitle = UIFactory.CreateLabel(titleGroup, "KeyTitle", "Keys", TextAnchor.MiddleLeft);
|
||||
Text keyTitle = UIFactory.CreateLabel(titleGroup, "KeyTitle", "Keys", TextAnchor.MiddleLeft);
|
||||
UIFactory.SetLayoutElement(keyTitle.gameObject, minWidth: 100, flexibleWidth: 0);
|
||||
KeyTitleLayout = keyTitle.GetComponent<LayoutElement>();
|
||||
|
||||
var valueTitle = UIFactory.CreateLabel(titleGroup, "ValueTitle", "Values", TextAnchor.MiddleLeft);
|
||||
Text valueTitle = UIFactory.CreateLabel(titleGroup, "ValueTitle", "Values", TextAnchor.MiddleLeft);
|
||||
UIFactory.SetLayoutElement(valueTitle.gameObject, minWidth: 100, flexibleWidth: 0);
|
||||
ValueTitleLayout = valueTitle.GetComponent<LayoutElement>();
|
||||
|
||||
|
@ -1,17 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.CacheObject;
|
||||
using UnityExplorer.UI;
|
||||
using System.Collections.Specialized;
|
||||
using UnityExplorer.UI.Panels;
|
||||
using UnityExplorer.UI.Widgets.AutoComplete;
|
||||
using UniverseLib;
|
||||
using UniverseLib.UI;
|
||||
using UniverseLib.UI.Models;
|
||||
using UniverseLib.Utility;
|
||||
|
||||
namespace UnityExplorer.CacheObject.IValues
|
||||
{
|
||||
@ -110,7 +101,7 @@ namespace UnityExplorer.CacheObject.IValues
|
||||
{
|
||||
try
|
||||
{
|
||||
List<string> values = new List<string>();
|
||||
List<string> values = new();
|
||||
for (int i = 0; i < CurrentValues.Count; i++)
|
||||
{
|
||||
if (flagToggles[i].isOn)
|
||||
@ -138,11 +129,11 @@ namespace UnityExplorer.CacheObject.IValues
|
||||
new Color(0.06f, 0.06f, 0.06f));
|
||||
UIFactory.SetLayoutElement(UIRoot, minHeight: 25, flexibleHeight: 9999, flexibleWidth: 9999);
|
||||
|
||||
var hori = UIFactory.CreateUIObject("Hori", UIRoot);
|
||||
GameObject 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));
|
||||
ButtonRef 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;
|
||||
|
||||
@ -192,11 +183,11 @@ namespace UnityExplorer.CacheObject.IValues
|
||||
|
||||
private void AddToggleRow()
|
||||
{
|
||||
var row = UIFactory.CreateUIObject("ToggleRow", toggleHolder);
|
||||
GameObject row = UIFactory.CreateUIObject("ToggleRow", toggleHolder);
|
||||
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(row, false, false, true, true, 2);
|
||||
UIFactory.SetLayoutElement(row, minHeight: 25, flexibleWidth: 9999);
|
||||
|
||||
var toggleObj = UIFactory.CreateToggle(row, "ToggleObj", out Toggle toggle, out Text toggleText);
|
||||
GameObject toggleObj = UIFactory.CreateToggle(row, "ToggleObj", out Toggle toggle, out Text toggleText);
|
||||
UIFactory.SetLayoutElement(toggleObj, minHeight: 25, flexibleWidth: 9999);
|
||||
|
||||
flagToggles.Add(toggle);
|
||||
@ -205,7 +196,7 @@ namespace UnityExplorer.CacheObject.IValues
|
||||
|
||||
#region Enum cache
|
||||
|
||||
internal static readonly Dictionary<string, OrderedDictionary> enumCache = new Dictionary<string, OrderedDictionary>();
|
||||
internal static readonly Dictionary<string, OrderedDictionary> enumCache = new();
|
||||
|
||||
internal static OrderedDictionary GetEnumValues(Type enumType)
|
||||
{
|
||||
@ -213,13 +204,13 @@ namespace UnityExplorer.CacheObject.IValues
|
||||
|
||||
if (!enumCache.ContainsKey(enumType.AssemblyQualifiedName))
|
||||
{
|
||||
var dict = new OrderedDictionary();
|
||||
var addedNames = new HashSet<string>();
|
||||
OrderedDictionary dict = new();
|
||||
HashSet<string> addedNames = new();
|
||||
|
||||
int i = 0;
|
||||
foreach (var value in Enum.GetValues(enumType))
|
||||
foreach (object value in Enum.GetValues(enumType))
|
||||
{
|
||||
var name = value.ToString();
|
||||
string name = value.ToString();
|
||||
if (addedNames.Contains(name))
|
||||
continue;
|
||||
addedNames.Add(name);
|
||||
|
@ -1,21 +1,8 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.CacheObject;
|
||||
using System.Collections;
|
||||
using UnityExplorer.CacheObject.Views;
|
||||
using UnityExplorer.Inspectors;
|
||||
using UnityExplorer.UI;
|
||||
using UnityExplorer.UI.Panels;
|
||||
using UnityExplorer.UI.Widgets;
|
||||
using UniverseLib;
|
||||
using UniverseLib.UI;
|
||||
using UniverseLib.UI.Widgets;
|
||||
using UniverseLib.UI.Widgets.ScrollView;
|
||||
using UniverseLib.Utility;
|
||||
|
||||
namespace UnityExplorer.CacheObject.IValues
|
||||
{
|
||||
@ -60,7 +47,7 @@ namespace UnityExplorer.CacheObject.IValues
|
||||
{
|
||||
RefIList = null;
|
||||
|
||||
foreach (var entry in cachedEntries)
|
||||
foreach (CacheListEntry entry in cachedEntries)
|
||||
{
|
||||
entry.UnlinkFromView();
|
||||
entry.ReleasePooledObjects();
|
||||
@ -73,9 +60,9 @@ namespace UnityExplorer.CacheObject.IValues
|
||||
|
||||
public override void SetLayout()
|
||||
{
|
||||
var minHeight = 5f;
|
||||
float minHeight = 5f;
|
||||
|
||||
foreach (var cell in ListScrollPool.CellPool)
|
||||
foreach (CacheListEntryCell cell in ListScrollPool.CellPool)
|
||||
{
|
||||
if (cell.Enabled)
|
||||
minHeight += cell.Rect.rect.height;
|
||||
@ -102,7 +89,7 @@ namespace UnityExplorer.CacheObject.IValues
|
||||
}
|
||||
else
|
||||
{
|
||||
var type = value.GetActualType();
|
||||
Type type = value.GetActualType();
|
||||
ReflectionUtility.TryGetEntryType(type, out EntryType);
|
||||
|
||||
CacheEntries(value);
|
||||
@ -132,7 +119,7 @@ namespace UnityExplorer.CacheObject.IValues
|
||||
|
||||
while (enumerator.MoveNext())
|
||||
{
|
||||
var entry = enumerator.Current;
|
||||
object entry = enumerator.Current;
|
||||
|
||||
// If list count increased, create new cache entries
|
||||
CacheListEntry cache;
|
||||
@ -155,7 +142,7 @@ namespace UnityExplorer.CacheObject.IValues
|
||||
{
|
||||
for (int i = cachedEntries.Count - 1; i >= idx; i--)
|
||||
{
|
||||
var cache = cachedEntries[i];
|
||||
CacheListEntry cache = cachedEntries[i];
|
||||
if (cache.CellView != null)
|
||||
cache.UnlinkFromView();
|
||||
|
||||
@ -174,7 +161,7 @@ namespace UnityExplorer.CacheObject.IValues
|
||||
{
|
||||
try
|
||||
{
|
||||
var type = value.GetType();
|
||||
Type type = value.GetType();
|
||||
if (type.GetInterfaces().Any(it => it.IsGenericType && it.GetGenericTypeDefinition() == typeof(IList<>)))
|
||||
IsWritableGenericIList = !(bool)type.GetProperty("IsReadOnly").GetValue(value, null);
|
||||
else
|
||||
@ -184,7 +171,7 @@ namespace UnityExplorer.CacheObject.IValues
|
||||
{
|
||||
// Find the "this[int index]" property.
|
||||
// It might be a private implementation.
|
||||
foreach (var prop in type.GetProperties(ReflectionUtility.FLAGS))
|
||||
foreach (PropertyInfo prop in type.GetProperties(ReflectionUtility.FLAGS))
|
||||
{
|
||||
if ((prop.Name == "Item"
|
||||
|| (prop.Name.StartsWith("System.Collections.Generic.IList<") && prop.Name.EndsWith(">.Item")))
|
||||
@ -226,7 +213,7 @@ namespace UnityExplorer.CacheObject.IValues
|
||||
genericIndexer.SetValue(CurrentOwner.Value, value, new object[] { index });
|
||||
}
|
||||
|
||||
var entry = cachedEntries[index];
|
||||
CacheListEntry entry = cachedEntries[index];
|
||||
entry.SetValueFromSource(value);
|
||||
|
||||
if (entry.CellView != null)
|
||||
|
@ -1,18 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.Config;
|
||||
using UnityExplorer.CacheObject;
|
||||
using UnityExplorer.UI.Widgets;
|
||||
using UnityExplorer.UI;
|
||||
using UnityExplorer.Config;
|
||||
using UniverseLib.UI;
|
||||
using UniverseLib;
|
||||
using UniverseLib.UI.Models;
|
||||
using UniverseLib.Utility;
|
||||
|
||||
namespace UnityExplorer.CacheObject.IValues
|
||||
{
|
||||
@ -88,7 +76,7 @@ namespace UnityExplorer.CacheObject.IValues
|
||||
return;
|
||||
}
|
||||
|
||||
var path = IOUtility.EnsureValidFilePath(SaveFilePath.Text);
|
||||
string path = IOUtility.EnsureValidFilePath(SaveFilePath.Text);
|
||||
|
||||
if (File.Exists(path))
|
||||
File.Delete(path);
|
||||
@ -110,10 +98,10 @@ namespace UnityExplorer.CacheObject.IValues
|
||||
UIFactory.CreateLabel(SaveFileRow, "Info", "<color=red>String is too long! Save to file if you want to see the full string.</color>",
|
||||
TextAnchor.MiddleLeft);
|
||||
|
||||
var horizRow = UIFactory.CreateUIObject("Horiz", SaveFileRow);
|
||||
GameObject horizRow = UIFactory.CreateUIObject("Horiz", SaveFileRow);
|
||||
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(horizRow, false, false, true, true, 4);
|
||||
|
||||
var saveButton = UIFactory.CreateButton(horizRow, "SaveButton", "Save file");
|
||||
ButtonRef saveButton = UIFactory.CreateButton(horizRow, "SaveButton", "Save file");
|
||||
UIFactory.SetLayoutElement(saveButton.Component.gameObject, minHeight: 25, minWidth: 100, flexibleWidth: 0);
|
||||
saveButton.OnClick += OnSaveFileClicked;
|
||||
|
||||
|
@ -1,14 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.CacheObject;
|
||||
using UnityExplorer.UI;
|
||||
using UniverseLib.UI;
|
||||
using UniverseLib.UI.Models;
|
||||
using UniverseLib.UI.ObjectPool;
|
||||
using UniverseLib.UI.ObjectPool;
|
||||
|
||||
namespace UnityExplorer.CacheObject.IValues
|
||||
{
|
||||
|
@ -1,16 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.CacheObject;
|
||||
using UnityExplorer.UI;
|
||||
using UniverseLib;
|
||||
using UniverseLib.UI;
|
||||
using UniverseLib.UI;
|
||||
using UniverseLib.UI.Models;
|
||||
using UniverseLib.Utility;
|
||||
|
||||
namespace UnityExplorer.CacheObject.IValues
|
||||
{
|
||||
@ -31,7 +20,7 @@ namespace UnityExplorer.CacheObject.IValues
|
||||
|
||||
public void SetValue(object instance, string input, int fieldIndex)
|
||||
{
|
||||
var field = Fields[fieldIndex];
|
||||
FieldInfo field = Fields[fieldIndex];
|
||||
|
||||
object val;
|
||||
if (field.FieldType == typeof(string))
|
||||
@ -51,8 +40,8 @@ namespace UnityExplorer.CacheObject.IValues
|
||||
|
||||
public string GetValue(object instance, int fieldIndex)
|
||||
{
|
||||
var field = Fields[fieldIndex];
|
||||
var value = field.GetValue(instance);
|
||||
FieldInfo field = Fields[fieldIndex];
|
||||
object value = field.GetValue(instance);
|
||||
return ParseUtility.ToStringForInput(value, field.FieldType);
|
||||
}
|
||||
}
|
||||
@ -67,12 +56,12 @@ namespace UnityExplorer.CacheObject.IValues
|
||||
if (!type.IsValueType || string.IsNullOrEmpty(type.AssemblyQualifiedName) || type.FullName == SYSTEM_VOID)
|
||||
return false;
|
||||
|
||||
if (typeSupportCache.TryGetValue(type.AssemblyQualifiedName, out var info))
|
||||
if (typeSupportCache.TryGetValue(type.AssemblyQualifiedName, out StructInfo info))
|
||||
return info.IsSupported;
|
||||
|
||||
var supported = false;
|
||||
bool supported = false;
|
||||
|
||||
var fields = type.GetFields(INSTANCE_FLAGS);
|
||||
FieldInfo[] fields = type.GetFields(INSTANCE_FLAGS);
|
||||
if (fields.Length > 0)
|
||||
{
|
||||
if (fields.Any(it => !ParseUtility.CanParse(it.FieldType)))
|
||||
@ -100,9 +89,9 @@ namespace UnityExplorer.CacheObject.IValues
|
||||
private Type lastStructType;
|
||||
|
||||
private ButtonRef applyButton;
|
||||
private readonly List<GameObject> fieldRows = new List<GameObject>();
|
||||
private readonly List<InputFieldRef> inputFields = new List<InputFieldRef>();
|
||||
private readonly List<Text> labels = new List<Text>();
|
||||
private readonly List<GameObject> fieldRows = new();
|
||||
private readonly List<InputFieldRef> inputFields = new();
|
||||
private readonly List<Text> labels = new();
|
||||
|
||||
public override void OnBorrowed(CacheObjectBase owner)
|
||||
{
|
||||
@ -117,7 +106,7 @@ namespace UnityExplorer.CacheObject.IValues
|
||||
{
|
||||
RefInstance = value;
|
||||
|
||||
var type = RefInstance.GetType();
|
||||
Type type = RefInstance.GetType();
|
||||
|
||||
if (type != lastStructType)
|
||||
{
|
||||
@ -177,21 +166,21 @@ namespace UnityExplorer.CacheObject.IValues
|
||||
|
||||
private void AddEditorRow()
|
||||
{
|
||||
var row = UIFactory.CreateUIObject("HoriGroup", UIRoot);
|
||||
GameObject row = UIFactory.CreateUIObject("HoriGroup", UIRoot);
|
||||
//row.AddComponent<ContentSizeFitter>().horizontalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||||
UIFactory.SetLayoutElement(row, minHeight: 25, flexibleWidth: 9999);
|
||||
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(row, false, false, true, true, 8, childAlignment: TextAnchor.MiddleLeft);
|
||||
|
||||
fieldRows.Add(row);
|
||||
|
||||
var label = UIFactory.CreateLabel(row, "Label", "notset", TextAnchor.MiddleLeft);
|
||||
Text label = UIFactory.CreateLabel(row, "Label", "notset", TextAnchor.MiddleLeft);
|
||||
UIFactory.SetLayoutElement(label.gameObject, minHeight: 25, minWidth: 50, flexibleWidth: 0);
|
||||
label.horizontalOverflow = HorizontalWrapMode.Wrap;
|
||||
labels.Add(label);
|
||||
|
||||
var input = UIFactory.CreateInputField(row, "InputField", "...");
|
||||
InputFieldRef input = UIFactory.CreateInputField(row, "InputField", "...");
|
||||
UIFactory.SetLayoutElement(input.UIRoot, minHeight: 25, minWidth: 200);
|
||||
var fitter = input.UIRoot.AddComponent<ContentSizeFitter>();
|
||||
ContentSizeFitter fitter = input.UIRoot.AddComponent<ContentSizeFitter>();
|
||||
fitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||||
fitter.horizontalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||||
input.Component.lineType = InputField.LineType.MultiLineNewline;
|
||||
|
@ -1,13 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.UI;
|
||||
using UniverseLib;
|
||||
using UniverseLib.UI;
|
||||
using UniverseLib.Utility;
|
||||
using UniverseLib.UI;
|
||||
|
||||
namespace UnityExplorer.CacheObject.Views
|
||||
{
|
||||
@ -32,7 +23,7 @@ namespace UnityExplorer.CacheObject.Views
|
||||
|
||||
// horizontal group
|
||||
|
||||
var horiGroup = UIFactory.CreateUIObject("RightHoriGroup", UIRoot);
|
||||
GameObject horiGroup = UIFactory.CreateUIObject("RightHoriGroup", UIRoot);
|
||||
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(horiGroup, false, false, true, true, 4, childAlignment: TextAnchor.UpperLeft);
|
||||
UIFactory.SetLayoutElement(horiGroup, minHeight: 25, minWidth: 200, flexibleWidth: 9999, flexibleHeight: 800);
|
||||
|
||||
@ -48,7 +39,7 @@ namespace UnityExplorer.CacheObject.Views
|
||||
|
||||
// Bool and number value interaction
|
||||
|
||||
var toggleObj = UIFactory.CreateToggle(horiGroup, "Toggle", out Toggle, out ToggleText);
|
||||
GameObject toggleObj = UIFactory.CreateToggle(horiGroup, "Toggle", out Toggle, out ToggleText);
|
||||
UIFactory.SetLayoutElement(toggleObj, minWidth: 70, minHeight: 25, flexibleWidth: 0, flexibleHeight: 0);
|
||||
ToggleText.color = SignatureHighlighter.KeywordBlue;
|
||||
Toggle.onValueChanged.AddListener(ToggleClicked);
|
||||
@ -77,7 +68,7 @@ namespace UnityExplorer.CacheObject.Views
|
||||
SubContentHolder.SetActive(false);
|
||||
|
||||
// Bottom separator
|
||||
var separator = UIFactory.CreateUIObject("BottomSeperator", UIRoot);
|
||||
GameObject separator = UIFactory.CreateUIObject("BottomSeperator", UIRoot);
|
||||
UIFactory.SetLayoutElement(separator, minHeight: 1, flexibleHeight: 0, flexibleWidth: 9999);
|
||||
separator.AddComponent<Image>().color = Color.black;
|
||||
|
||||
|
@ -1,13 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.CacheObject.IValues;
|
||||
using UnityExplorer.Inspectors;
|
||||
using UnityExplorer.UI;
|
||||
using UnityExplorer.UI.Widgets;
|
||||
using UnityExplorer.CacheObject.IValues;
|
||||
using UniverseLib.UI;
|
||||
using UniverseLib.UI.Models;
|
||||
|
||||
@ -24,8 +15,8 @@ namespace UnityExplorer.CacheObject.Views
|
||||
public InputFieldRef KeyInputField;
|
||||
public Text KeyInputTypeLabel;
|
||||
|
||||
public static Color EvenColor = new Color(0.07f, 0.07f, 0.07f);
|
||||
public static Color OddColor = new Color(0.063f, 0.063f, 0.063f);
|
||||
public static Color EvenColor = new(0.07f, 0.07f, 0.07f);
|
||||
public static Color OddColor = new(0.063f, 0.063f, 0.063f);
|
||||
|
||||
public int AdjustedWidth => (int)Rect.rect.width - 70;
|
||||
|
||||
@ -40,7 +31,7 @@ namespace UnityExplorer.CacheObject.Views
|
||||
|
||||
public override GameObject CreateContent(GameObject parent)
|
||||
{
|
||||
var root = base.CreateContent(parent);
|
||||
GameObject root = base.CreateContent(parent);
|
||||
|
||||
Image = root.AddComponent<Image>();
|
||||
|
||||
@ -53,7 +44,7 @@ namespace UnityExplorer.CacheObject.Views
|
||||
this.RightGroupLayout.minWidth = AdjustedWidth * 0.55f;
|
||||
|
||||
// Key area
|
||||
var keyGroup = UIFactory.CreateUIObject("KeyHolder", root.transform.Find("HoriGroup").gameObject);
|
||||
GameObject keyGroup = UIFactory.CreateUIObject("KeyHolder", root.transform.Find("HoriGroup").gameObject);
|
||||
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(keyGroup, false, false, true, true, 2, 0, 0, 4, 4, childAlignment: TextAnchor.MiddleLeft);
|
||||
KeyGroupLayout = UIFactory.SetLayoutElement(keyGroup, minHeight: 30, minWidth: (int)(AdjustedWidth * 0.44f), flexibleWidth: 0);
|
||||
|
||||
|
@ -1,10 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.CacheObject.IValues;
|
||||
using UnityExplorer.CacheObject.IValues;
|
||||
|
||||
namespace UnityExplorer.CacheObject.Views
|
||||
{
|
||||
@ -13,12 +7,12 @@ namespace UnityExplorer.CacheObject.Views
|
||||
public Image Image { get; private set; }
|
||||
public InteractiveList ListOwner => Occupant.Owner as InteractiveList;
|
||||
|
||||
public static Color EvenColor = new Color(0.12f, 0.12f, 0.12f);
|
||||
public static Color OddColor = new Color(0.1f, 0.1f, 0.1f);
|
||||
public static Color EvenColor = new(0.12f, 0.12f, 0.12f);
|
||||
public static Color OddColor = new(0.1f, 0.1f, 0.1f);
|
||||
|
||||
public override GameObject CreateContent(GameObject parent)
|
||||
{
|
||||
var root = base.CreateContent(parent);
|
||||
GameObject root = base.CreateContent(parent);
|
||||
|
||||
Image = root.AddComponent<Image>();
|
||||
|
||||
|
@ -1,12 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.UI;
|
||||
using UnityExplorer.UI.Widgets;
|
||||
using UniverseLib.UI;
|
||||
using UniverseLib.UI;
|
||||
using UniverseLib.UI.Models;
|
||||
|
||||
namespace UnityExplorer.CacheObject.Views
|
||||
|
@ -1,15 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.UI.Panels;
|
||||
using UniverseLib;
|
||||
using UnityExplorer.UI.Panels;
|
||||
using UniverseLib.UI;
|
||||
using UniverseLib.UI.Models;
|
||||
using UniverseLib.UI.Widgets.ScrollView;
|
||||
using UniverseLib.Utility;
|
||||
|
||||
namespace UnityExplorer.CacheObject.Views
|
||||
{
|
||||
@ -116,7 +108,7 @@ namespace UnityExplorer.CacheObject.Views
|
||||
UIFactory.SetLayoutElement(UIRoot, minWidth: 100, flexibleWidth: 9999, minHeight: 30, flexibleHeight: 600);
|
||||
UIRoot.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||||
|
||||
var horiRow = UIFactory.CreateUIObject("HoriGroup", UIRoot);
|
||||
GameObject horiRow = UIFactory.CreateUIObject("HoriGroup", UIRoot);
|
||||
UIFactory.SetLayoutElement(horiRow, minHeight: 29, flexibleHeight: 150, flexibleWidth: 9999);
|
||||
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(horiRow, false, false, true, true, 5, 2, childAlignment: TextAnchor.UpperLeft);
|
||||
horiRow.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||||
@ -129,7 +121,7 @@ namespace UnityExplorer.CacheObject.Views
|
||||
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(NameLabel.gameObject, true, true, true, true);
|
||||
|
||||
HiddenNameLabel = UIFactory.CreateInputField(NameLabel.gameObject, "HiddenNameLabel", "");
|
||||
var hiddenRect = HiddenNameLabel.Component.GetComponent<RectTransform>();
|
||||
RectTransform hiddenRect = HiddenNameLabel.Component.GetComponent<RectTransform>();
|
||||
hiddenRect.anchorMin = Vector2.zero;
|
||||
hiddenRect.anchorMax = Vector2.one;
|
||||
HiddenNameLabel.Component.readOnly = true;
|
||||
@ -150,7 +142,7 @@ namespace UnityExplorer.CacheObject.Views
|
||||
|
||||
// Right horizontal group
|
||||
|
||||
var rightHoriGroup = UIFactory.CreateUIObject("RightHoriGroup", RightGroupContent);
|
||||
GameObject rightHoriGroup = UIFactory.CreateUIObject("RightHoriGroup", RightGroupContent);
|
||||
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(rightHoriGroup, false, false, true, true, 4, childAlignment: TextAnchor.UpperLeft);
|
||||
UIFactory.SetLayoutElement(rightHoriGroup, minHeight: 25, minWidth: 200, flexibleWidth: 9999, flexibleHeight: 800);
|
||||
|
||||
@ -166,7 +158,7 @@ namespace UnityExplorer.CacheObject.Views
|
||||
|
||||
// Bool and number value interaction
|
||||
|
||||
var toggleObj = UIFactory.CreateToggle(rightHoriGroup, "Toggle", out Toggle, out ToggleText);
|
||||
GameObject toggleObj = UIFactory.CreateToggle(rightHoriGroup, "Toggle", out Toggle, out ToggleText);
|
||||
UIFactory.SetLayoutElement(toggleObj, minWidth: 70, minHeight: 25, flexibleWidth: 0, flexibleHeight: 0);
|
||||
ToggleText.color = SignatureHighlighter.KeywordBlue;
|
||||
Toggle.onValueChanged.AddListener(ToggleClicked);
|
||||
@ -194,8 +186,8 @@ namespace UnityExplorer.CacheObject.Views
|
||||
|
||||
// Copy and Paste buttons
|
||||
|
||||
var buttonHolder = UIFactory.CreateHorizontalGroup(rightHoriGroup, "CopyPasteButtons", false, false, true, true, 4,
|
||||
bgColor: new(1,1,1,0), childAlignment: TextAnchor.MiddleLeft);
|
||||
GameObject 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));
|
||||
@ -219,7 +211,7 @@ namespace UnityExplorer.CacheObject.Views
|
||||
SubContentHolder.SetActive(false);
|
||||
|
||||
// Bottom separator
|
||||
var separator = UIFactory.CreateUIObject("BottomSeperator", UIRoot);
|
||||
GameObject separator = UIFactory.CreateUIObject("BottomSeperator", UIRoot);
|
||||
UIFactory.SetLayoutElement(separator, minHeight: 1, flexibleHeight: 0, flexibleWidth: 9999);
|
||||
separator.AddComponent<Image>().color = Color.black;
|
||||
|
||||
|
@ -1,9 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace UnityExplorer.Config
|
||||
namespace UnityExplorer.Config
|
||||
{
|
||||
public class ConfigElement<T> : IConfigElement
|
||||
{
|
||||
|
@ -1,9 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace UnityExplorer.Config
|
||||
namespace UnityExplorer.Config
|
||||
{
|
||||
public abstract class ConfigHandler
|
||||
{
|
||||
|
@ -1,11 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityExplorer.UI;
|
||||
using UnityExplorer.UI;
|
||||
|
||||
namespace UnityExplorer.Config
|
||||
{
|
||||
@ -20,19 +13,20 @@ namespace UnityExplorer.Config
|
||||
|
||||
// Actual UE Settings
|
||||
public static ConfigElement<KeyCode> Master_Toggle;
|
||||
public static ConfigElement<int> Target_Display;
|
||||
public static ConfigElement<UIManager.VerticalAnchor> Main_Navbar_Anchor;
|
||||
public static ConfigElement<bool> Force_Unlock_Mouse;
|
||||
public static ConfigElement<KeyCode> Force_Unlock_Toggle;
|
||||
public static ConfigElement<bool> Aggressive_Mouse_Unlock;
|
||||
public static ConfigElement<bool> Disable_EventSystem_Override;
|
||||
public static ConfigElement<string> Default_Output_Path;
|
||||
public static ConfigElement<bool> Log_Unity_Debug;
|
||||
public static ConfigElement<bool> Hide_On_Startup;
|
||||
public static ConfigElement<float> Startup_Delay_Time;
|
||||
public static ConfigElement<string> Reflection_Signature_Blacklist;
|
||||
public static ConfigElement<bool> Disable_EventSystem_Override;
|
||||
public static ConfigElement<int> Target_Display;
|
||||
public static ConfigElement<bool> Force_Unlock_Mouse;
|
||||
public static ConfigElement<KeyCode> Force_Unlock_Toggle;
|
||||
public static ConfigElement<string> Default_Output_Path;
|
||||
public static ConfigElement<string> DnSpy_Path;
|
||||
public static ConfigElement<bool> Log_Unity_Debug;
|
||||
public static ConfigElement<UIManager.VerticalAnchor> Main_Navbar_Anchor;
|
||||
public static ConfigElement<KeyCode> World_MouseInspect_Keybind;
|
||||
public static ConfigElement<KeyCode> UI_MouseInspect_Keybind;
|
||||
public static ConfigElement<string> CSConsole_Assembly_Blacklist;
|
||||
public static ConfigElement<string> Reflection_Signature_Blacklist;
|
||||
|
||||
// internal configs
|
||||
internal static InternalConfigHandler InternalHandler { get; private set; }
|
||||
@ -58,7 +52,9 @@ namespace UnityExplorer.Config
|
||||
Handler.LoadConfig();
|
||||
InternalHandler.LoadConfig();
|
||||
|
||||
//InitConsoleCallback();
|
||||
#if STANDALONE
|
||||
Loader.Standalone.ExplorerEditorBehaviour.Instance?.LoadConfigs();
|
||||
#endif
|
||||
}
|
||||
|
||||
internal static void RegisterConfigElement<T>(ConfigElement<T> configElement)
|
||||
@ -77,58 +73,68 @@ namespace UnityExplorer.Config
|
||||
|
||||
private static void CreateConfigElements()
|
||||
{
|
||||
Master_Toggle = new ConfigElement<KeyCode>("UnityExplorer Toggle",
|
||||
Master_Toggle = new("UnityExplorer Toggle",
|
||||
"The key to enable or disable UnityExplorer's menu and features.",
|
||||
KeyCode.F7);
|
||||
|
||||
Target_Display = new ConfigElement<int>("Target Display",
|
||||
Hide_On_Startup = new("Hide On Startup",
|
||||
"Should UnityExplorer be hidden on startup?",
|
||||
false);
|
||||
|
||||
Startup_Delay_Time = new("Startup Delay Time",
|
||||
"The delay on startup before the UI is created.",
|
||||
1f);
|
||||
|
||||
Target_Display = new("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",
|
||||
Force_Unlock_Mouse = new("Force Unlock Mouse",
|
||||
"Force the Cursor to be unlocked (visible) when the UnityExplorer menu is open.",
|
||||
true);
|
||||
Force_Unlock_Mouse.OnValueChanged += (bool value) => UniverseLib.Config.ConfigManager.Force_Unlock_Mouse = value;
|
||||
|
||||
Force_Unlock_Toggle = new("Force Unlock Toggle Key",
|
||||
"The keybind to toggle the 'Force Unlock Mouse' setting. Only usable when UnityExplorer is open.",
|
||||
KeyCode.None);
|
||||
|
||||
Disable_EventSystem_Override = new("Disable EventSystem override",
|
||||
"If enabled, UnityExplorer will not override the EventSystem from the game.\n<b>May require restart to take effect.</b>",
|
||||
false);
|
||||
Disable_EventSystem_Override.OnValueChanged += (bool value) => UniverseLib.Config.ConfigManager.Disable_EventSystem_Override = value;
|
||||
|
||||
Default_Output_Path = new("Default Output Path",
|
||||
"The default output path when exporting things from UnityExplorer.",
|
||||
Path.Combine(ExplorerCore.ExplorerFolder, "Output"));
|
||||
|
||||
DnSpy_Path = new("dnSpy Path",
|
||||
"The full path to dnSpy.exe (64-bit).",
|
||||
@"C:/Program Files/dnspy/dnSpy.exe");
|
||||
|
||||
Main_Navbar_Anchor = new("Main Navbar Anchor",
|
||||
"The vertical anchor of the main UnityExplorer Navbar, in case you want to move it.",
|
||||
UIManager.VerticalAnchor.Top);
|
||||
|
||||
Hide_On_Startup = new ConfigElement<bool>("Hide On Startup",
|
||||
"Should UnityExplorer be hidden on startup?",
|
||||
Log_Unity_Debug = new("Log Unity Debug",
|
||||
"Should UnityEngine.Debug.Log messages be printed to UnityExplorer's log?",
|
||||
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.",
|
||||
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 the Cursor to be unlocked (visible) when the UnityExplorer menu is open.",
|
||||
true);
|
||||
Force_Unlock_Mouse.OnValueChanged += (bool value) => UniverseLib.Config.ConfigManager.Force_Unlock_Mouse = value;
|
||||
CSConsole_Assembly_Blacklist = new("CSharp Console Assembly Blacklist",
|
||||
"Use this to blacklist Assembly names from being referenced by the C# Console. Requires a Reset of the C# Console.\n" +
|
||||
"Separate each Assembly with a semicolon ';'." +
|
||||
"For example, to blacklist Assembly-CSharp, you would add 'Assembly-CSharp;'",
|
||||
"");
|
||||
|
||||
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.",
|
||||
KeyCode.None);
|
||||
|
||||
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>",
|
||||
false);
|
||||
Disable_EventSystem_Override.OnValueChanged += (bool value) => UniverseLib.Config.ConfigManager.Disable_EventSystem_Override = value;
|
||||
|
||||
Log_Unity_Debug = new ConfigElement<bool>("Log Unity Debug",
|
||||
"Should UnityEngine.Debug.Log messages be printed to UnityExplorer's log?",
|
||||
false);
|
||||
|
||||
Default_Output_Path = new ConfigElement<string>("Default Output Path",
|
||||
"The default output path when exporting things from UnityExplorer.",
|
||||
Path.Combine(ExplorerCore.ExplorerFolder, "Output"));
|
||||
|
||||
Startup_Delay_Time = new ConfigElement<float>("Startup Delay Time",
|
||||
"The delay on startup before the UI is created.",
|
||||
1f);
|
||||
|
||||
Reflection_Signature_Blacklist = new ConfigElement<string>("Member Signature Blacklist",
|
||||
Reflection_Signature_Blacklist = new("Member Signature Blacklist",
|
||||
"Use this to blacklist certain member signatures if they are known to cause a crash or other issues.\r\n" +
|
||||
"Seperate signatures with a semicolon ';'.\r\n" +
|
||||
"For example, to blacklist Camera.main, you would add 'UnityEngine.Camera.main;'",
|
||||
|
@ -1,6 +1,4 @@
|
||||
using System;
|
||||
|
||||
namespace UnityExplorer.Config
|
||||
namespace UnityExplorer.Config
|
||||
{
|
||||
public interface IConfigElement
|
||||
{
|
||||
|
@ -1,12 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityExplorer.UI;
|
||||
using Tomlet;
|
||||
using Tomlet;
|
||||
using Tomlet.Models;
|
||||
using UnityExplorer.UI;
|
||||
|
||||
namespace UnityExplorer.Config
|
||||
{
|
||||
@ -49,9 +43,12 @@ namespace UnityExplorer.Config
|
||||
return false;
|
||||
|
||||
TomlDocument document = TomlParser.ParseFile(CONFIG_PATH);
|
||||
foreach (var key in document.Keys)
|
||||
foreach (string key in document.Keys)
|
||||
{
|
||||
var panelKey = (UIManager.Panels)Enum.Parse(typeof(UIManager.Panels), key);
|
||||
if (!Enum.IsDefined(typeof(UIManager.Panels), key))
|
||||
continue;
|
||||
|
||||
UIManager.Panels panelKey = (UIManager.Panels)Enum.Parse(typeof(UIManager.Panels), key);
|
||||
ConfigManager.GetPanelSaveData(panelKey).Value = document.GetString(key);
|
||||
}
|
||||
|
||||
@ -69,8 +66,8 @@ namespace UnityExplorer.Config
|
||||
if (UIManager.Initializing)
|
||||
return;
|
||||
|
||||
var tomlDocument = TomlDocument.CreateEmpty();
|
||||
foreach (var entry in ConfigManager.InternalConfigs)
|
||||
TomlDocument tomlDocument = TomlDocument.CreateEmpty();
|
||||
foreach (KeyValuePair<string, IConfigElement> entry in ConfigManager.InternalConfigs)
|
||||
tomlDocument.Put(entry.Key, entry.Value.BoxedValue as string, false);
|
||||
|
||||
File.WriteAllText(CONFIG_PATH, tomlDocument.SerializedValue);
|
||||
|
@ -1,10 +1,10 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityExplorer.UI;
|
||||
#if CPP
|
||||
#if UNHOLLOWER
|
||||
using UnhollowerRuntimeLib;
|
||||
#else
|
||||
using Il2CppInterop.Runtime.Injection;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace UnityExplorer
|
||||
@ -14,7 +14,7 @@ namespace UnityExplorer
|
||||
internal static ExplorerBehaviour Instance { get; private set; }
|
||||
|
||||
#if CPP
|
||||
public ExplorerBehaviour(IntPtr ptr) : base(ptr) { }
|
||||
public ExplorerBehaviour(System.IntPtr ptr) : base(ptr) { }
|
||||
#endif
|
||||
|
||||
internal static void Setup()
|
||||
@ -33,5 +33,39 @@ namespace UnityExplorer
|
||||
{
|
||||
ExplorerCore.Update();
|
||||
}
|
||||
|
||||
// For editor, to clean up objects
|
||||
|
||||
internal void OnDestroy()
|
||||
{
|
||||
OnApplicationQuit();
|
||||
}
|
||||
|
||||
internal bool quitting;
|
||||
|
||||
internal void OnApplicationQuit()
|
||||
{
|
||||
if (quitting) return;
|
||||
quitting = true;
|
||||
|
||||
TryDestroy(UIManager.UIRoot?.transform.root.gameObject);
|
||||
|
||||
TryDestroy((typeof(Universe).Assembly.GetType("UniverseLib.UniversalBehaviour")
|
||||
.GetProperty("Instance", BindingFlags.Static | BindingFlags.NonPublic)
|
||||
.GetValue(null, null)
|
||||
as Component).gameObject);
|
||||
|
||||
TryDestroy(this.gameObject);
|
||||
}
|
||||
|
||||
internal void TryDestroy(GameObject obj)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (obj)
|
||||
Destroy(obj);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +1,17 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
using UnityExplorer.CacheObject;
|
||||
global using System;
|
||||
global using System.Collections.Generic;
|
||||
global using System.IO;
|
||||
global using System.Linq;
|
||||
global using System.Reflection;
|
||||
global using UnityEngine;
|
||||
global using UnityEngine.UI;
|
||||
global using UniverseLib;
|
||||
global using UniverseLib.Utility;
|
||||
using UnityExplorer.Config;
|
||||
using UnityExplorer.ObjectExplorer;
|
||||
using UnityExplorer.Runtime;
|
||||
using UnityExplorer.UI;
|
||||
using UnityExplorer.UI.Panels;
|
||||
using UniverseLib;
|
||||
using UniverseLib.Input;
|
||||
|
||||
namespace UnityExplorer
|
||||
@ -15,7 +19,7 @@ namespace UnityExplorer
|
||||
public static class ExplorerCore
|
||||
{
|
||||
public const string NAME = "UnityExplorer";
|
||||
public const string VERSION = "4.7.0";
|
||||
public const string VERSION = "4.9.0";
|
||||
public const string AUTHOR = "Sinai";
|
||||
public const string GUID = "com.sinai.unityexplorer";
|
||||
|
||||
@ -58,8 +62,6 @@ namespace UnityExplorer
|
||||
// Default delay is 1 second which is usually enough.
|
||||
static void LateInit()
|
||||
{
|
||||
Log($"Setting up late core features...");
|
||||
|
||||
SceneHandler.Init();
|
||||
|
||||
Log($"Creating UI...");
|
||||
@ -67,71 +69,19 @@ namespace UnityExplorer
|
||||
UIManager.InitUI();
|
||||
|
||||
Log($"{NAME} {VERSION} ({Universe.Context}) initialized.");
|
||||
|
||||
// InspectorManager.Inspect(typeof(Tests.TestClass));
|
||||
}
|
||||
|
||||
internal static void Update()
|
||||
{
|
||||
// check master toggle
|
||||
if (InputManager.GetKeyDown(ConfigManager.Master_Toggle.Value))
|
||||
{
|
||||
UIManager.ShowMenu = !UIManager.ShowMenu;
|
||||
|
||||
UIManager.Update();
|
||||
}
|
||||
|
||||
// Can be removed eventually. For migration from <4.7.0
|
||||
static void CheckLegacyExplorerFolder()
|
||||
{
|
||||
string legacyPath = Path.Combine(Loader.ExplorerFolderDestination, "UnityExplorer");
|
||||
if (Directory.Exists(legacyPath))
|
||||
{
|
||||
LogWarning($"Attempting to migrate old 'UnityExplorer/' folder to 'sinai-dev-UnityExplorer/'...");
|
||||
|
||||
// If new folder doesn't exist yet, let's just use Move().
|
||||
if (!Directory.Exists(ExplorerFolder))
|
||||
{
|
||||
try
|
||||
{
|
||||
Directory.Move(legacyPath, ExplorerFolder);
|
||||
Log("Migrated successfully.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogWarning($"Exception migrating folder: {ex}");
|
||||
}
|
||||
}
|
||||
else // We have to merge
|
||||
{
|
||||
try
|
||||
{
|
||||
CopyAll(new(legacyPath), new(ExplorerFolder));
|
||||
Directory.Delete(legacyPath, true);
|
||||
Log("Migrated successfully.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogWarning($"Exception migrating folder: {ex}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void CopyAll(DirectoryInfo source, DirectoryInfo target)
|
||||
{
|
||||
// Check if the target directory exists, if not, create it.
|
||||
if (!Directory.Exists(target.FullName))
|
||||
Directory.CreateDirectory(target.FullName);
|
||||
|
||||
// Copy each file into it's new directory.
|
||||
foreach (FileInfo fi in source.GetFiles())
|
||||
fi.MoveTo(Path.Combine(target.ToString(), fi.Name));
|
||||
|
||||
// Copy each subdirectory using recursion.
|
||||
foreach (DirectoryInfo diSourceSubDir in source.GetDirectories())
|
||||
{
|
||||
DirectoryInfo nextTargetSubDir = target.CreateSubdirectory(diSourceSubDir.Name);
|
||||
CopyAll(diSourceSubDir, nextTargetSubDir);
|
||||
}
|
||||
}
|
||||
|
||||
#region LOGGING
|
||||
|
||||
@ -177,5 +127,63 @@ namespace UnityExplorer
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region LEGACY FOLDER MIGRATION
|
||||
|
||||
// Can be removed eventually. For migration from <4.7.0
|
||||
static void CheckLegacyExplorerFolder()
|
||||
{
|
||||
string legacyPath = Path.Combine(Loader.ExplorerFolderDestination, "UnityExplorer");
|
||||
if (Directory.Exists(legacyPath))
|
||||
{
|
||||
LogWarning($"Attempting to migrate old 'UnityExplorer/' folder to 'sinai-dev-UnityExplorer/'...");
|
||||
|
||||
// If new folder doesn't exist yet, let's just use Move().
|
||||
if (!Directory.Exists(ExplorerFolder))
|
||||
{
|
||||
try
|
||||
{
|
||||
Directory.Move(legacyPath, ExplorerFolder);
|
||||
Log("Migrated successfully.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogWarning($"Exception migrating folder: {ex}");
|
||||
}
|
||||
}
|
||||
else // We have to merge
|
||||
{
|
||||
try
|
||||
{
|
||||
CopyAll(new(legacyPath), new(ExplorerFolder));
|
||||
Directory.Delete(legacyPath, true);
|
||||
Log("Migrated successfully.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogWarning($"Exception migrating folder: {ex}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void CopyAll(DirectoryInfo source, DirectoryInfo target)
|
||||
{
|
||||
Directory.CreateDirectory(target.FullName);
|
||||
|
||||
// Copy each file into it's new directory.
|
||||
foreach (FileInfo fi in source.GetFiles())
|
||||
fi.MoveTo(Path.Combine(target.ToString(), fi.Name));
|
||||
|
||||
// Copy each subdirectory using recursion.
|
||||
foreach (DirectoryInfo diSourceSubDir in source.GetDirectories())
|
||||
{
|
||||
DirectoryInfo nextTargetSubDir = target.CreateSubdirectory(diSourceSubDir.Name);
|
||||
CopyAll(diSourceSubDir, nextTargetSubDir);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.UI;
|
||||
using UnityExplorer.UI.Widgets;
|
||||
using UniverseLib.UI;
|
||||
using UniverseLib.UI;
|
||||
using UniverseLib.UI.Models;
|
||||
using UniverseLib.UI.Widgets;
|
||||
using UniverseLib.UI.Widgets.ScrollView;
|
||||
|
||||
namespace UnityExplorer.Hooks
|
||||
@ -23,14 +14,13 @@ namespace UnityExplorer.Hooks
|
||||
public float DefaultHeight => 30;
|
||||
|
||||
public Text MethodNameLabel;
|
||||
public Text HookedLabel;
|
||||
public ButtonRef HookButton;
|
||||
|
||||
public int CurrentDisplayedIndex;
|
||||
|
||||
private void OnHookClicked()
|
||||
{
|
||||
HookManager.Instance.AddHookClicked(CurrentDisplayedIndex);
|
||||
HookCreator.AddHookClicked(CurrentDisplayedIndex);
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
@ -51,9 +41,6 @@ namespace UnityExplorer.Hooks
|
||||
UIFactory.SetLayoutElement(UIRoot, minWidth: 100, flexibleWidth: 9999, minHeight: 30, flexibleHeight: 600);
|
||||
UIRoot.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||||
|
||||
HookedLabel = UIFactory.CreateLabel(UIRoot, "HookedLabel", "✓", TextAnchor.MiddleCenter, Color.green);
|
||||
UIFactory.SetLayoutElement(HookedLabel.gameObject, minHeight: 25, minWidth: 100);
|
||||
|
||||
HookButton = UIFactory.CreateButton(UIRoot, "HookButton", "Hook", new Color(0.2f, 0.25f, 0.2f));
|
||||
UIFactory.SetLayoutElement(HookButton.Component.gameObject, minHeight: 25, minWidth: 100);
|
||||
HookButton.OnClick += OnHookClicked;
|
||||
|
@ -1,12 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UniverseLib.UI;
|
||||
using UniverseLib.UI;
|
||||
using UniverseLib.UI.Models;
|
||||
using UniverseLib.UI.Widgets;
|
||||
using UniverseLib.UI.Widgets.ScrollView;
|
||||
|
||||
namespace UnityExplorer.Hooks
|
||||
@ -29,17 +22,18 @@ namespace UnityExplorer.Hooks
|
||||
|
||||
private void OnToggleActiveClicked()
|
||||
{
|
||||
HookManager.Instance.EnableOrDisableHookClicked(CurrentDisplayedIndex);
|
||||
HookList.EnableOrDisableHookClicked(CurrentDisplayedIndex);
|
||||
}
|
||||
|
||||
private void OnDeleteClicked()
|
||||
{
|
||||
HookManager.Instance.DeleteHookClicked(CurrentDisplayedIndex);
|
||||
HookList.DeleteHookClicked(CurrentDisplayedIndex);
|
||||
HookCreator.AddHooksScrollPool.Refresh(true, false);
|
||||
}
|
||||
|
||||
private void OnEditPatchClicked()
|
||||
{
|
||||
HookManager.Instance.EditPatchClicked(CurrentDisplayedIndex);
|
||||
HookList.EditPatchClicked(CurrentDisplayedIndex);
|
||||
}
|
||||
|
||||
public GameObject CreateContent(GameObject parent)
|
||||
@ -53,18 +47,18 @@ namespace UnityExplorer.Hooks
|
||||
MethodNameLabel = UIFactory.CreateLabel(UIRoot, "MethodName", "NOT SET", TextAnchor.MiddleLeft);
|
||||
UIFactory.SetLayoutElement(MethodNameLabel.gameObject, minHeight: 25, flexibleWidth: 9999);
|
||||
|
||||
ToggleActiveButton = UIFactory.CreateButton(UIRoot, "ToggleActiveBtn", "Enabled", new Color(0.15f, 0.2f, 0.15f));
|
||||
UIFactory.SetLayoutElement(ToggleActiveButton.Component.gameObject, minHeight: 25, minWidth: 100);
|
||||
ToggleActiveButton = UIFactory.CreateButton(UIRoot, "ToggleActiveBtn", "On", new Color(0.15f, 0.2f, 0.15f));
|
||||
UIFactory.SetLayoutElement(ToggleActiveButton.Component.gameObject, minHeight: 25, minWidth: 35);
|
||||
ToggleActiveButton.OnClick += OnToggleActiveClicked;
|
||||
|
||||
DeleteButton = UIFactory.CreateButton(UIRoot, "DeleteButton", "Delete", new Color(0.2f, 0.15f, 0.15f));
|
||||
UIFactory.SetLayoutElement(DeleteButton.Component.gameObject, minHeight: 25, minWidth: 100);
|
||||
DeleteButton.OnClick += OnDeleteClicked;
|
||||
|
||||
EditPatchButton = UIFactory.CreateButton(UIRoot, "EditButton", "Edit Hook Source", new Color(0.15f, 0.15f, 0.15f));
|
||||
UIFactory.SetLayoutElement(EditPatchButton.Component.gameObject, minHeight: 25, minWidth: 150);
|
||||
EditPatchButton = UIFactory.CreateButton(UIRoot, "EditButton", "Edit", new Color(0.15f, 0.15f, 0.15f));
|
||||
UIFactory.SetLayoutElement(EditPatchButton.Component.gameObject, minHeight: 25, minWidth: 35);
|
||||
EditPatchButton.OnClick += OnEditPatchClicked;
|
||||
|
||||
DeleteButton = UIFactory.CreateButton(UIRoot, "DeleteButton", "X", new Color(0.2f, 0.15f, 0.15f));
|
||||
UIFactory.SetLayoutElement(DeleteButton.Component.gameObject, minHeight: 25, minWidth: 35);
|
||||
DeleteButton.OnClick += OnDeleteClicked;
|
||||
|
||||
return UIRoot;
|
||||
}
|
||||
|
||||
|
333
src/Hooks/HookCreator.cs
Normal file
333
src/Hooks/HookCreator.cs
Normal file
@ -0,0 +1,333 @@
|
||||
using HarmonyLib;
|
||||
using UnityExplorer.CSConsole;
|
||||
using UnityExplorer.Runtime;
|
||||
using UnityExplorer.UI.Panels;
|
||||
using UnityExplorer.UI.Widgets.AutoComplete;
|
||||
using UniverseLib.UI;
|
||||
using UniverseLib.UI.Models;
|
||||
using UniverseLib.UI.Widgets;
|
||||
using UniverseLib.UI.Widgets.ScrollView;
|
||||
|
||||
namespace UnityExplorer.Hooks
|
||||
{
|
||||
public class HookCreator : ICellPoolDataSource<AddHookCell>
|
||||
{
|
||||
public int ItemCount => filteredEligibleMethods.Count;
|
||||
|
||||
static readonly List<MethodInfo> currentAddEligibleMethods = new();
|
||||
static readonly List<MethodInfo> filteredEligibleMethods = new();
|
||||
static readonly List<string> currentEligibleNamesForFiltering = new();
|
||||
|
||||
// hook editor
|
||||
static readonly LexerBuilder Lexer = new();
|
||||
internal static HookInstance CurrentEditedHook;
|
||||
|
||||
// Add Hooks UI
|
||||
internal static GameObject AddHooksRoot;
|
||||
internal static ScrollPool<AddHookCell> AddHooksScrollPool;
|
||||
internal static Text AddHooksLabel;
|
||||
internal static InputFieldRef AddHooksMethodFilterInput;
|
||||
internal static InputFieldRef ClassSelectorInputField;
|
||||
internal static Type pendingGenericDefinition;
|
||||
internal static MethodInfo pendingGenericMethod;
|
||||
|
||||
public static bool PendingGeneric => pendingGenericDefinition != null || pendingGenericMethod != null;
|
||||
|
||||
// Hook Source Editor UI
|
||||
public static GameObject EditorRoot { get; private set; }
|
||||
public static Text EditingHookLabel { get; private set; }
|
||||
public static InputFieldScroller EditorInputScroller { get; private set; }
|
||||
public static InputFieldRef EditorInput => EditorInputScroller.InputField;
|
||||
public static Text EditorInputText { get; private set; }
|
||||
public static Text EditorHighlightText { get; private set; }
|
||||
|
||||
// ~~~~~~ New hook method selector ~~~~~~~
|
||||
|
||||
public void OnClassSelectedForHooks(string typeFullName)
|
||||
{
|
||||
Type type = ReflectionUtility.GetTypeByName(typeFullName);
|
||||
if (type == null)
|
||||
{
|
||||
ExplorerCore.LogWarning($"Could not find any type by name {typeFullName}!");
|
||||
return;
|
||||
}
|
||||
if (type.IsGenericType)
|
||||
{
|
||||
pendingGenericDefinition = type;
|
||||
HookManagerPanel.genericArgsHandler.Show(OnGenericClassChosen, OnGenericClassCancel, type);
|
||||
HookManagerPanel.Instance.SetPage(HookManagerPanel.Pages.GenericArgsSelector);
|
||||
return;
|
||||
}
|
||||
|
||||
ShowMethodsForType(type);
|
||||
}
|
||||
|
||||
void ShowMethodsForType(Type type)
|
||||
{
|
||||
SetAddHooksLabelType(SignatureHighlighter.Parse(type, true));
|
||||
|
||||
AddHooksMethodFilterInput.Text = string.Empty;
|
||||
|
||||
filteredEligibleMethods.Clear();
|
||||
currentAddEligibleMethods.Clear();
|
||||
currentEligibleNamesForFiltering.Clear();
|
||||
foreach (MethodInfo method in type.GetMethods(ReflectionUtility.FLAGS))
|
||||
{
|
||||
if (UERuntimeHelper.IsBlacklisted(method))
|
||||
continue;
|
||||
currentAddEligibleMethods.Add(method);
|
||||
currentEligibleNamesForFiltering.Add(SignatureHighlighter.RemoveHighlighting(SignatureHighlighter.ParseMethod(method)));
|
||||
filteredEligibleMethods.Add(method);
|
||||
}
|
||||
|
||||
AddHooksScrollPool.Refresh(true, true);
|
||||
}
|
||||
|
||||
void OnGenericClassChosen(Type[] genericArgs)
|
||||
{
|
||||
Type generic = pendingGenericDefinition.MakeGenericType(genericArgs);
|
||||
ShowMethodsForType(generic);
|
||||
HookManagerPanel.Instance.SetPage(HookManagerPanel.Pages.ClassMethodSelector);
|
||||
}
|
||||
|
||||
void OnGenericClassCancel()
|
||||
{
|
||||
pendingGenericDefinition = null;
|
||||
HookManagerPanel.Instance.SetPage(HookManagerPanel.Pages.ClassMethodSelector);
|
||||
}
|
||||
|
||||
public void SetAddHooksLabelType(string typeText)
|
||||
{
|
||||
AddHooksLabel.text = $"Adding hooks to: {typeText}";
|
||||
|
||||
AddHooksMethodFilterInput.GameObject.SetActive(true);
|
||||
AddHooksScrollPool.UIRoot.SetActive(true);
|
||||
}
|
||||
|
||||
public static void AddHookClicked(int index)
|
||||
{
|
||||
if (index >= filteredEligibleMethods.Count)
|
||||
return;
|
||||
|
||||
MethodInfo method = filteredEligibleMethods[index];
|
||||
if (!method.IsGenericMethod && HookList.hookedSignatures.Contains(method.FullDescription()))
|
||||
{
|
||||
ExplorerCore.Log($"Non-generic methods can only be hooked once.");
|
||||
return;
|
||||
}
|
||||
else if (method.IsGenericMethod)
|
||||
{
|
||||
pendingGenericMethod = method;
|
||||
HookManagerPanel.genericArgsHandler.Show(OnGenericMethodChosen, OnGenericMethodCancel, method);
|
||||
HookManagerPanel.Instance.SetPage(HookManagerPanel.Pages.GenericArgsSelector);
|
||||
return;
|
||||
}
|
||||
|
||||
AddHook(filteredEligibleMethods[index]);
|
||||
}
|
||||
|
||||
static void OnGenericMethodChosen(Type[] arguments)
|
||||
{
|
||||
MethodInfo generic = pendingGenericMethod.MakeGenericMethod(arguments);
|
||||
AddHook(generic);
|
||||
}
|
||||
|
||||
static void OnGenericMethodCancel()
|
||||
{
|
||||
pendingGenericMethod = null;
|
||||
HookManagerPanel.Instance.SetPage(HookManagerPanel.Pages.ClassMethodSelector);
|
||||
}
|
||||
|
||||
public static void AddHook(MethodInfo method)
|
||||
{
|
||||
HookManagerPanel.Instance.SetPage(HookManagerPanel.Pages.ClassMethodSelector);
|
||||
|
||||
string sig = method.FullDescription();
|
||||
if (HookList.hookedSignatures.Contains(sig))
|
||||
{
|
||||
ExplorerCore.LogWarning($"Method is already hooked!");
|
||||
return;
|
||||
}
|
||||
|
||||
HookInstance hook = new(method);
|
||||
HookList.hookedSignatures.Add(sig);
|
||||
HookList.currentHooks.Add(sig, hook);
|
||||
|
||||
AddHooksScrollPool.Refresh(true, false);
|
||||
HookList.HooksScrollPool.Refresh(true, false);
|
||||
}
|
||||
|
||||
public void OnAddHookFilterInputChanged(string input)
|
||||
{
|
||||
filteredEligibleMethods.Clear();
|
||||
|
||||
if (string.IsNullOrEmpty(input))
|
||||
filteredEligibleMethods.AddRange(currentAddEligibleMethods);
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < currentAddEligibleMethods.Count; i++)
|
||||
{
|
||||
MethodInfo eligible = currentAddEligibleMethods[i];
|
||||
string sig = currentEligibleNamesForFiltering[i];
|
||||
if (sig.ContainsIgnoreCase(input))
|
||||
filteredEligibleMethods.Add(eligible);
|
||||
}
|
||||
}
|
||||
|
||||
AddHooksScrollPool.Refresh(true, true);
|
||||
}
|
||||
|
||||
// Set eligible method cell
|
||||
|
||||
public void OnCellBorrowed(AddHookCell cell) { }
|
||||
|
||||
public void SetCell(AddHookCell cell, int index)
|
||||
{
|
||||
if (index >= filteredEligibleMethods.Count)
|
||||
{
|
||||
cell.Disable();
|
||||
return;
|
||||
}
|
||||
|
||||
cell.CurrentDisplayedIndex = index;
|
||||
MethodInfo method = filteredEligibleMethods[index];
|
||||
|
||||
cell.MethodNameLabel.text = SignatureHighlighter.ParseMethod(method);
|
||||
}
|
||||
|
||||
// ~~~~~~~~ Hook source editor ~~~~~~~~
|
||||
|
||||
internal static void SetEditedHook(HookInstance hook)
|
||||
{
|
||||
CurrentEditedHook = hook;
|
||||
EditingHookLabel.text = $"Editing: {SignatureHighlighter.Parse(hook.TargetMethod.DeclaringType, false, hook.TargetMethod)}";
|
||||
EditorInput.Text = hook.PatchSourceCode;
|
||||
}
|
||||
|
||||
internal static void OnEditorInputChanged(string value)
|
||||
{
|
||||
EditorHighlightText.text = Lexer.BuildHighlightedString(value, 0, value.Length - 1, 0, EditorInput.Component.caretPosition, out _);
|
||||
}
|
||||
|
||||
internal static void EditorInputCancel()
|
||||
{
|
||||
CurrentEditedHook = null;
|
||||
HookManagerPanel.Instance.SetPage(HookManagerPanel.Pages.ClassMethodSelector);
|
||||
}
|
||||
|
||||
internal static void EditorInputSave()
|
||||
{
|
||||
string input = EditorInput.Text;
|
||||
bool wasEnabled = CurrentEditedHook.Enabled;
|
||||
if (CurrentEditedHook.CompileAndGenerateProcessor(input))
|
||||
{
|
||||
if (wasEnabled)
|
||||
CurrentEditedHook.Patch();
|
||||
|
||||
CurrentEditedHook.PatchSourceCode = input;
|
||||
CurrentEditedHook = null;
|
||||
HookManagerPanel.Instance.SetPage(HookManagerPanel.Pages.ClassMethodSelector);
|
||||
}
|
||||
|
||||
HookList.HooksScrollPool.Refresh(true, false);
|
||||
}
|
||||
|
||||
// UI Construction
|
||||
|
||||
internal void ConstructAddHooksView(GameObject rightGroup)
|
||||
{
|
||||
AddHooksRoot = UIFactory.CreateUIObject("AddHooksPanel", rightGroup);
|
||||
UIFactory.SetLayoutElement(AddHooksRoot, flexibleHeight: 9999, flexibleWidth: 9999);
|
||||
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(AddHooksRoot, false, false, true, true);
|
||||
|
||||
GameObject addRow = UIFactory.CreateHorizontalGroup(AddHooksRoot, "AddRow", false, true, true, true, 4,
|
||||
new Vector4(2, 2, 2, 2), new Color(0.2f, 0.2f, 0.2f));
|
||||
UIFactory.SetLayoutElement(addRow, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999);
|
||||
|
||||
ClassSelectorInputField = UIFactory.CreateInputField(addRow, "ClassInput", "Enter a class to add hooks to...");
|
||||
UIFactory.SetLayoutElement(ClassSelectorInputField.Component.gameObject, flexibleWidth: 9999, minHeight: 25, flexibleHeight: 0);
|
||||
TypeCompleter completer = new(typeof(object), ClassSelectorInputField, true, false, true);
|
||||
//completer.AllTypes = true;
|
||||
|
||||
ButtonRef addButton = UIFactory.CreateButton(addRow, "AddButton", "View Methods");
|
||||
UIFactory.SetLayoutElement(addButton.Component.gameObject, minWidth: 110, minHeight: 25);
|
||||
addButton.OnClick += () => { OnClassSelectedForHooks(ClassSelectorInputField.Text); };
|
||||
|
||||
AddHooksLabel = UIFactory.CreateLabel(AddHooksRoot, "AddLabel", "Choose a class to begin...", TextAnchor.MiddleCenter);
|
||||
UIFactory.SetLayoutElement(AddHooksLabel.gameObject, minHeight: 30, minWidth: 100, flexibleWidth: 9999);
|
||||
|
||||
AddHooksMethodFilterInput = UIFactory.CreateInputField(AddHooksRoot, "FilterInputField", "Filter method names...");
|
||||
UIFactory.SetLayoutElement(AddHooksMethodFilterInput.Component.gameObject, minHeight: 30, flexibleWidth: 9999);
|
||||
AddHooksMethodFilterInput.OnValueChanged += OnAddHookFilterInputChanged;
|
||||
|
||||
AddHooksScrollPool = UIFactory.CreateScrollPool<AddHookCell>(AddHooksRoot, "MethodAddScrollPool",
|
||||
out GameObject addScrollRoot, out GameObject addContent);
|
||||
UIFactory.SetLayoutElement(addScrollRoot, flexibleHeight: 9999);
|
||||
AddHooksScrollPool.Initialize(this);
|
||||
|
||||
AddHooksMethodFilterInput.GameObject.SetActive(false);
|
||||
AddHooksScrollPool.UIRoot.SetActive(false);
|
||||
}
|
||||
|
||||
public void ConstructEditor(GameObject parent)
|
||||
{
|
||||
EditorRoot = UIFactory.CreateUIObject("HookSourceEditor", parent);
|
||||
UIFactory.SetLayoutElement(EditorRoot, flexibleHeight: 9999, flexibleWidth: 9999);
|
||||
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(EditorRoot, true, true, true, true, 2, 3, 3, 3, 3);
|
||||
|
||||
EditingHookLabel = UIFactory.CreateLabel(EditorRoot, "EditingHookLabel", "NOT SET", TextAnchor.MiddleCenter);
|
||||
EditingHookLabel.fontStyle = FontStyle.Bold;
|
||||
UIFactory.SetLayoutElement(EditingHookLabel.gameObject, flexibleWidth: 9999, minHeight: 25);
|
||||
|
||||
Text editorLabel = UIFactory.CreateLabel(EditorRoot,
|
||||
"EditorLabel",
|
||||
"* Accepted method names are <b>Prefix</b>, <b>Postfix</b>, <b>Finalizer</b> and <b>Transpiler</b> (can define multiple).\n" +
|
||||
"* Your patch methods must be static.\n" +
|
||||
"* Hooks are temporary! Copy the source into your IDE to avoid losing work if you wish to keep it!",
|
||||
TextAnchor.MiddleLeft);
|
||||
UIFactory.SetLayoutElement(editorLabel.gameObject, minHeight: 25, flexibleWidth: 9999);
|
||||
|
||||
GameObject editorButtonRow = UIFactory.CreateHorizontalGroup(EditorRoot, "ButtonRow", false, false, true, true, 5);
|
||||
UIFactory.SetLayoutElement(editorButtonRow, minHeight: 25, flexibleWidth: 9999);
|
||||
|
||||
ButtonRef editorSaveButton = UIFactory.CreateButton(editorButtonRow, "DoneButton", "Save and Return", new Color(0.2f, 0.3f, 0.2f));
|
||||
UIFactory.SetLayoutElement(editorSaveButton.Component.gameObject, minHeight: 25, flexibleWidth: 9999);
|
||||
editorSaveButton.OnClick += EditorInputSave;
|
||||
|
||||
ButtonRef editorDoneButton = UIFactory.CreateButton(editorButtonRow, "DoneButton", "Cancel and Return", new Color(0.2f, 0.2f, 0.2f));
|
||||
UIFactory.SetLayoutElement(editorDoneButton.Component.gameObject, minHeight: 25, flexibleWidth: 9999);
|
||||
editorDoneButton.OnClick += EditorInputCancel;
|
||||
|
||||
int fontSize = 16;
|
||||
GameObject inputObj = UIFactory.CreateScrollInputField(EditorRoot, "EditorInput", "", out InputFieldScroller inputScroller, fontSize);
|
||||
EditorInputScroller = inputScroller;
|
||||
EditorInput.OnValueChanged += OnEditorInputChanged;
|
||||
|
||||
EditorInputText = EditorInput.Component.textComponent;
|
||||
EditorInputText.supportRichText = false;
|
||||
EditorInputText.color = Color.clear;
|
||||
EditorInput.Component.customCaretColor = true;
|
||||
EditorInput.Component.caretColor = Color.white;
|
||||
EditorInput.PlaceholderText.fontSize = fontSize;
|
||||
|
||||
// Lexer highlight text overlay
|
||||
GameObject highlightTextObj = UIFactory.CreateUIObject("HighlightText", EditorInputText.gameObject);
|
||||
RectTransform highlightTextRect = highlightTextObj.GetComponent<RectTransform>();
|
||||
highlightTextRect.pivot = new Vector2(0, 1);
|
||||
highlightTextRect.anchorMin = Vector2.zero;
|
||||
highlightTextRect.anchorMax = Vector2.one;
|
||||
highlightTextRect.offsetMin = Vector2.zero;
|
||||
highlightTextRect.offsetMax = Vector2.zero;
|
||||
|
||||
EditorHighlightText = highlightTextObj.AddComponent<Text>();
|
||||
EditorHighlightText.color = Color.white;
|
||||
EditorHighlightText.supportRichText = true;
|
||||
EditorHighlightText.fontSize = fontSize;
|
||||
|
||||
// Set fonts
|
||||
EditorInputText.font = UniversalUI.ConsoleFont;
|
||||
EditorInput.PlaceholderText.font = UniversalUI.ConsoleFont;
|
||||
EditorHighlightText.font = UniversalUI.ConsoleFont;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,13 +1,7 @@
|
||||
using System;
|
||||
using System.CodeDom.Compiler;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using HarmonyLib;
|
||||
using HarmonyLib;
|
||||
using Mono.CSharp;
|
||||
using System.Text;
|
||||
using UnityExplorer.CSConsole;
|
||||
using UniverseLib;
|
||||
|
||||
namespace UnityExplorer.Hooks
|
||||
{
|
||||
@ -15,12 +9,13 @@ namespace UnityExplorer.Hooks
|
||||
{
|
||||
// Static
|
||||
|
||||
private static readonly StringBuilder evalOutput = new();
|
||||
private static readonly ScriptEvaluator scriptEvaluator = new(new StringWriter(evalOutput));
|
||||
static readonly StringBuilder evaluatorOutput;
|
||||
static readonly ScriptEvaluator scriptEvaluator = new(new StringWriter(evaluatorOutput = new StringBuilder()));
|
||||
|
||||
static HookInstance()
|
||||
{
|
||||
scriptEvaluator.Run("using System;");
|
||||
scriptEvaluator.Run("using System.Text;");
|
||||
scriptEvaluator.Run("using System.Reflection;");
|
||||
scriptEvaluator.Run("using System.Collections;");
|
||||
scriptEvaluator.Run("using System.Collections.Generic;");
|
||||
@ -29,21 +24,22 @@ namespace UnityExplorer.Hooks
|
||||
// Instance
|
||||
|
||||
public bool Enabled;
|
||||
|
||||
public MethodInfo TargetMethod;
|
||||
public string PatchSourceCode;
|
||||
|
||||
private readonly string shortSignature;
|
||||
private PatchProcessor patchProcessor;
|
||||
readonly string signature;
|
||||
PatchProcessor patchProcessor;
|
||||
|
||||
private MethodInfo postfix;
|
||||
private MethodInfo prefix;
|
||||
private MethodInfo finalizer;
|
||||
private MethodInfo transpiler;
|
||||
MethodInfo postfix;
|
||||
MethodInfo prefix;
|
||||
MethodInfo finalizer;
|
||||
MethodInfo transpiler;
|
||||
|
||||
public HookInstance(MethodInfo targetMethod)
|
||||
{
|
||||
this.TargetMethod = targetMethod;
|
||||
this.shortSignature = $"{targetMethod.DeclaringType.Name}.{targetMethod.Name}";
|
||||
this.signature = TargetMethod.FullDescription();
|
||||
|
||||
GenerateDefaultPatchSourceCode(targetMethod);
|
||||
|
||||
@ -60,15 +56,15 @@ namespace UnityExplorer.Hooks
|
||||
{
|
||||
Unpatch();
|
||||
|
||||
StringBuilder codeBuilder = new();
|
||||
|
||||
try
|
||||
{
|
||||
patchProcessor = ExplorerCore.Harmony.CreateProcessor(TargetMethod);
|
||||
|
||||
// Dynamically compile the patch method
|
||||
|
||||
var codeBuilder = new StringBuilder();
|
||||
|
||||
codeBuilder.AppendLine($"public class DynamicPatch_{DateTime.Now.Ticks}");
|
||||
codeBuilder.AppendLine($"static class DynamicPatch_{DateTime.Now.Ticks}");
|
||||
codeBuilder.AppendLine("{");
|
||||
codeBuilder.AppendLine(patchSource);
|
||||
codeBuilder.AppendLine("}");
|
||||
@ -80,11 +76,11 @@ namespace UnityExplorer.Hooks
|
||||
|
||||
// TODO: Publicize MCS to avoid this reflection
|
||||
// Get the most recent Patch type in the source file
|
||||
var typeContainer = ((CompilationSourceFile)fi_sourceFile.GetValue(scriptEvaluator))
|
||||
TypeContainer typeContainer = ((CompilationSourceFile)fi_sourceFile.GetValue(scriptEvaluator))
|
||||
.Containers
|
||||
.Last(it => it.MemberName.Name.StartsWith("DynamicPatch_"));
|
||||
// Get the TypeSpec from the TypeDefinition, then get its "MetaInfo" (System.Type)
|
||||
var patchClass = ((TypeSpec)pi_Definition.GetValue((Class)typeContainer, null)).GetMetaInfo();
|
||||
Type patchClass = ((TypeSpec)pi_Definition.GetValue((Class)typeContainer, null)).GetMetaInfo();
|
||||
|
||||
// Create the harmony patches as defined
|
||||
|
||||
@ -108,85 +104,108 @@ namespace UnityExplorer.Hooks
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ExplorerCore.LogWarning($"Exception creating patch processor for target method {TargetMethod.FullDescription()}!\r\n{ex}");
|
||||
if (ex is FormatException)
|
||||
{
|
||||
string output = scriptEvaluator._textWriter.ToString();
|
||||
string[] outputSplit = output.Split('\n');
|
||||
if (outputSplit.Length >= 2)
|
||||
output = outputSplit[outputSplit.Length - 2];
|
||||
evaluatorOutput.Clear();
|
||||
|
||||
if (ScriptEvaluator._reportPrinter.ErrorsCount > 0)
|
||||
ExplorerCore.LogWarning($"Unable to compile the code. Evaluator's last output was:\r\n{output}");
|
||||
else
|
||||
ExplorerCore.LogWarning($"Exception generating patch source code: {ex}");
|
||||
}
|
||||
else
|
||||
ExplorerCore.LogWarning($"Exception generating patch source code: {ex}");
|
||||
|
||||
// ExplorerCore.Log(codeBuilder.ToString());
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static string FullDescriptionClean(Type type)
|
||||
{
|
||||
string description = type.FullDescription().Replace("+", ".");
|
||||
if (description.EndsWith("&"))
|
||||
description = $"ref {description.Substring(0, description.Length - 1)}";
|
||||
return description;
|
||||
}
|
||||
|
||||
private string GenerateDefaultPatchSourceCode(MethodInfo targetMethod)
|
||||
{
|
||||
var codeBuilder = new StringBuilder();
|
||||
// Arguments
|
||||
StringBuilder codeBuilder = new();
|
||||
|
||||
codeBuilder.Append("public static void Postfix(System.Reflection.MethodBase __originalMethod");
|
||||
codeBuilder.Append("static void Postfix(");
|
||||
|
||||
if (!targetMethod.IsStatic)
|
||||
codeBuilder.Append($", {targetMethod.DeclaringType.FullName} __instance");
|
||||
bool isStatic = targetMethod.IsStatic;
|
||||
|
||||
List<string> arguments = new();
|
||||
|
||||
if (!isStatic)
|
||||
arguments.Add($"{FullDescriptionClean(targetMethod.DeclaringType)} __instance");
|
||||
|
||||
if (targetMethod.ReturnType != typeof(void))
|
||||
codeBuilder.Append($", {targetMethod.ReturnType.FullName} __result");
|
||||
arguments.Add($"{FullDescriptionClean(targetMethod.ReturnType)} __result");
|
||||
|
||||
var parameters = targetMethod.GetParameters();
|
||||
ParameterInfo[] parameters = targetMethod.GetParameters();
|
||||
|
||||
int paramIdx = 0;
|
||||
foreach (var param in parameters)
|
||||
foreach (ParameterInfo param in parameters)
|
||||
{
|
||||
codeBuilder.Append($", {param.ParameterType.FullDescription().Replace("&", "")} __{paramIdx}");
|
||||
arguments.Add($"{FullDescriptionClean(param.ParameterType)} __{paramIdx}");
|
||||
paramIdx++;
|
||||
}
|
||||
|
||||
codeBuilder.Append(string.Join(", ", arguments.ToArray()));
|
||||
|
||||
codeBuilder.Append(")\n");
|
||||
|
||||
// Patch body
|
||||
|
||||
codeBuilder.AppendLine("{");
|
||||
|
||||
codeBuilder.AppendLine(" try {");
|
||||
|
||||
// Log message
|
||||
|
||||
var logMessage = new StringBuilder();
|
||||
logMessage.Append($"Patch called: {shortSignature}\\n");
|
||||
codeBuilder.AppendLine(" StringBuilder sb = new StringBuilder();");
|
||||
codeBuilder.AppendLine($" sb.AppendLine(\"--------------------\");");
|
||||
codeBuilder.AppendLine($" sb.AppendLine(\"{signature}\");");
|
||||
|
||||
if (!targetMethod.IsStatic)
|
||||
logMessage.Append("__instance: {__instance.ToString()}\\n");
|
||||
codeBuilder.AppendLine($" sb.Append(\"- __instance: \").AppendLine(__instance.ToString());");
|
||||
|
||||
paramIdx = 0;
|
||||
foreach (var param in parameters)
|
||||
foreach (ParameterInfo param in parameters)
|
||||
{
|
||||
logMessage.Append($"Parameter {paramIdx} {param.Name}: ");
|
||||
codeBuilder.Append($" sb.Append(\"- Parameter {paramIdx} '{param.Name}': \")");
|
||||
|
||||
Type pType = param.ParameterType;
|
||||
if (pType.IsByRef) pType = pType.GetElementType();
|
||||
if (pType.IsValueType)
|
||||
logMessage.Append($"{{__{paramIdx}.ToString()}}");
|
||||
codeBuilder.AppendLine($".AppendLine(__{paramIdx}.ToString());");
|
||||
else
|
||||
logMessage.Append($"{{__{paramIdx}?.ToString() ?? \"null\"}}");
|
||||
logMessage.Append("\\n");
|
||||
codeBuilder.AppendLine($".AppendLine(__{paramIdx}?.ToString() ?? \"null\");");
|
||||
|
||||
paramIdx++;
|
||||
}
|
||||
|
||||
if (targetMethod.ReturnType != typeof(void))
|
||||
{
|
||||
logMessage.Append("Return value: ");
|
||||
codeBuilder.Append(" sb.Append(\"- Return value: \")");
|
||||
if (targetMethod.ReturnType.IsValueType)
|
||||
logMessage.Append("{__result.ToString()}");
|
||||
codeBuilder.AppendLine(".AppendLine(__result.ToString());");
|
||||
else
|
||||
logMessage.Append("{__result?.ToString() ?? \"null\"}");
|
||||
logMessage.Append("\\n");
|
||||
codeBuilder.AppendLine(".AppendLine(__result?.ToString() ?? \"null\");");
|
||||
}
|
||||
|
||||
codeBuilder.AppendLine($" UnityExplorer.ExplorerCore.Log($\"{logMessage}\");");
|
||||
codeBuilder.AppendLine($" UnityExplorer.ExplorerCore.Log(sb.ToString());");
|
||||
codeBuilder.AppendLine(" }");
|
||||
codeBuilder.AppendLine(" catch (System.Exception ex) {");
|
||||
codeBuilder.AppendLine($" UnityExplorer.ExplorerCore.LogWarning($\"Exception in patch of {shortSignature}:\\n{{ex}}\");");
|
||||
codeBuilder.AppendLine($" UnityExplorer.ExplorerCore.LogWarning($\"Exception in patch of {signature}:\\n{{ex}}\");");
|
||||
codeBuilder.AppendLine(" }");
|
||||
|
||||
// End patch body
|
||||
|
||||
codeBuilder.AppendLine("}");
|
||||
|
||||
//ExplorerCore.Log(codeBuilder.ToString());
|
||||
|
||||
return PatchSourceCode = codeBuilder.ToString();
|
||||
}
|
||||
|
||||
|
90
src/Hooks/HookList.cs
Normal file
90
src/Hooks/HookList.cs
Normal file
@ -0,0 +1,90 @@
|
||||
using HarmonyLib;
|
||||
using System.Collections.Specialized;
|
||||
using UnityExplorer.UI.Panels;
|
||||
using UniverseLib.UI;
|
||||
using UniverseLib.UI.Widgets.ScrollView;
|
||||
|
||||
namespace UnityExplorer.Hooks
|
||||
{
|
||||
public class HookList : ICellPoolDataSource<HookCell>
|
||||
{
|
||||
public int ItemCount => currentHooks.Count;
|
||||
|
||||
internal static readonly HashSet<string> hookedSignatures = new();
|
||||
internal static readonly OrderedDictionary currentHooks = new();
|
||||
|
||||
internal static GameObject UIRoot;
|
||||
internal static ScrollPool<HookCell> HooksScrollPool;
|
||||
|
||||
public static void EnableOrDisableHookClicked(int index)
|
||||
{
|
||||
HookInstance hook = (HookInstance)currentHooks[index];
|
||||
hook.TogglePatch();
|
||||
|
||||
HooksScrollPool.Refresh(true, false);
|
||||
}
|
||||
|
||||
public static void DeleteHookClicked(int index)
|
||||
{
|
||||
HookInstance hook = (HookInstance)currentHooks[index];
|
||||
|
||||
if (HookCreator.CurrentEditedHook == hook)
|
||||
HookCreator.EditorInputCancel();
|
||||
|
||||
hook.Unpatch();
|
||||
currentHooks.RemoveAt(index);
|
||||
hookedSignatures.Remove(hook.TargetMethod.FullDescription());
|
||||
|
||||
HooksScrollPool.Refresh(true, false);
|
||||
}
|
||||
|
||||
public static void EditPatchClicked(int index)
|
||||
{
|
||||
if (HookCreator.PendingGeneric)
|
||||
HookManagerPanel.genericArgsHandler.Cancel();
|
||||
|
||||
HookManagerPanel.Instance.SetPage(HookManagerPanel.Pages.HookSourceEditor);
|
||||
HookInstance hook = (HookInstance)currentHooks[index];
|
||||
HookCreator.SetEditedHook(hook);
|
||||
}
|
||||
|
||||
// Set current hook cell
|
||||
|
||||
public void OnCellBorrowed(HookCell cell) { }
|
||||
|
||||
public void SetCell(HookCell cell, int index)
|
||||
{
|
||||
if (index >= currentHooks.Count)
|
||||
{
|
||||
cell.Disable();
|
||||
return;
|
||||
}
|
||||
|
||||
cell.CurrentDisplayedIndex = index;
|
||||
HookInstance hook = (HookInstance)currentHooks[index];
|
||||
|
||||
cell.MethodNameLabel.text = SignatureHighlighter.ParseMethod(hook.TargetMethod);
|
||||
|
||||
cell.ToggleActiveButton.ButtonText.text = hook.Enabled ? "On" : "Off";
|
||||
RuntimeHelper.SetColorBlockAuto(cell.ToggleActiveButton.Component,
|
||||
hook.Enabled ? new Color(0.15f, 0.2f, 0.15f) : new Color(0.2f, 0.2f, 0.15f));
|
||||
}
|
||||
|
||||
// UI
|
||||
|
||||
internal void ConstructUI(GameObject leftGroup)
|
||||
{
|
||||
UIRoot = UIFactory.CreateUIObject("CurrentHooksPanel", leftGroup);
|
||||
UIFactory.SetLayoutElement(UIRoot, preferredHeight: 150, flexibleHeight: 0, flexibleWidth: 9999);
|
||||
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(UIRoot, true, true, true, true);
|
||||
|
||||
Text hooksLabel = UIFactory.CreateLabel(UIRoot, "HooksLabel", "Current Hooks", TextAnchor.MiddleCenter);
|
||||
UIFactory.SetLayoutElement(hooksLabel.gameObject, minHeight: 30, flexibleWidth: 9999);
|
||||
|
||||
HooksScrollPool = UIFactory.CreateScrollPool<HookCell>(UIRoot, "HooksScrollPool",
|
||||
out GameObject hooksScroll, out GameObject hooksContent);
|
||||
UIFactory.SetLayoutElement(hooksScroll, flexibleHeight: 9999);
|
||||
HooksScrollPool.Initialize(this);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,231 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using HarmonyLib;
|
||||
using UnityEngine;
|
||||
using UnityExplorer.Runtime;
|
||||
using UnityExplorer.CSConsole;
|
||||
using UnityExplorer.UI;
|
||||
using UnityExplorer.UI.Panels;
|
||||
using UnityExplorer.UI.Widgets;
|
||||
using UniverseLib;
|
||||
using UniverseLib.UI.Widgets;
|
||||
using UniverseLib.UI.Widgets.ScrollView;
|
||||
using UniverseLib.Utility;
|
||||
|
||||
namespace UnityExplorer.Hooks
|
||||
{
|
||||
public class HookManager : ICellPoolDataSource<HookCell>, ICellPoolDataSource<AddHookCell>
|
||||
{
|
||||
private static HookManager s_instance;
|
||||
public static HookManager Instance => s_instance ?? (s_instance = new HookManager());
|
||||
|
||||
public HookManagerPanel Panel => UIManager.GetPanel<HookManagerPanel>(UIManager.Panels.HookManager);
|
||||
|
||||
// This class acts as the data source for both current hooks and eligable methods when adding hooks.
|
||||
// 'isAddingMethods' keeps track of which pool is currently the displayed one, so our ItemCount reflects the
|
||||
// correct pool cells.
|
||||
private bool isAddingMethods;
|
||||
public int ItemCount => isAddingMethods ? filteredEligableMethods.Count : currentHooks.Count;
|
||||
|
||||
// current hooks
|
||||
private readonly HashSet<string> hookedSignatures = new HashSet<string>();
|
||||
private readonly OrderedDictionary currentHooks = new OrderedDictionary();
|
||||
|
||||
// adding hooks
|
||||
private readonly List<MethodInfo> currentAddEligableMethods = new List<MethodInfo>();
|
||||
private readonly List<MethodInfo> filteredEligableMethods = new List<MethodInfo>();
|
||||
|
||||
// hook editor
|
||||
private readonly LexerBuilder Lexer = new LexerBuilder();
|
||||
private HookInstance currentEditedHook;
|
||||
|
||||
// ~~~~~~~~~~~ Main Current Hooks window ~~~~~~~~~~~
|
||||
|
||||
public void EnableOrDisableHookClicked(int index)
|
||||
{
|
||||
var hook = (HookInstance)currentHooks[index];
|
||||
hook.TogglePatch();
|
||||
|
||||
Panel.HooksScrollPool.Refresh(true, false);
|
||||
}
|
||||
|
||||
public void DeleteHookClicked(int index)
|
||||
{
|
||||
var hook = (HookInstance)currentHooks[index];
|
||||
hook.Unpatch();
|
||||
currentHooks.RemoveAt(index);
|
||||
hookedSignatures.Remove(hook.TargetMethod.FullDescription());
|
||||
|
||||
Panel.HooksScrollPool.Refresh(true, false);
|
||||
}
|
||||
|
||||
public void EditPatchClicked(int index)
|
||||
{
|
||||
Panel.SetPage(HookManagerPanel.Pages.HookSourceEditor);
|
||||
var hook = (HookInstance)currentHooks[index];
|
||||
currentEditedHook = hook;
|
||||
Panel.EditorInput.Text = hook.PatchSourceCode;
|
||||
}
|
||||
|
||||
// Set current hook cell
|
||||
|
||||
public void OnCellBorrowed(HookCell cell) { }
|
||||
|
||||
public void SetCell(HookCell cell, int index)
|
||||
{
|
||||
if (index >= this.currentHooks.Count)
|
||||
{
|
||||
cell.Disable();
|
||||
return;
|
||||
}
|
||||
|
||||
cell.CurrentDisplayedIndex = index;
|
||||
var hook = (HookInstance)this.currentHooks[index];
|
||||
|
||||
cell.MethodNameLabel.text = SignatureHighlighter.HighlightMethod(hook.TargetMethod);
|
||||
|
||||
cell.ToggleActiveButton.ButtonText.text = hook.Enabled ? "Enabled" : "Disabled";
|
||||
RuntimeHelper.SetColorBlockAuto(cell.ToggleActiveButton.Component,
|
||||
hook.Enabled ? new Color(0.15f, 0.2f, 0.15f) : new Color(0.2f, 0.2f, 0.15f));
|
||||
}
|
||||
|
||||
// ~~~~~~~~~~~ Add Hooks window ~~~~~~~~~~~
|
||||
|
||||
public void OnClassSelectedForHooks(string typeFullName)
|
||||
{
|
||||
var type = ReflectionUtility.GetTypeByName(typeFullName);
|
||||
if (type == null)
|
||||
{
|
||||
ExplorerCore.LogWarning($"Could not find any type by name {typeFullName}!");
|
||||
return;
|
||||
}
|
||||
|
||||
Panel.SetAddHooksLabelType(SignatureHighlighter.Parse(type, true));
|
||||
|
||||
Panel.ResetMethodFilter();
|
||||
filteredEligableMethods.Clear();
|
||||
currentAddEligableMethods.Clear();
|
||||
foreach (var method in type.GetMethods(ReflectionUtility.FLAGS))
|
||||
{
|
||||
if (method.IsGenericMethod || UERuntimeHelper.IsBlacklisted(method))
|
||||
continue;
|
||||
currentAddEligableMethods.Add(method);
|
||||
filteredEligableMethods.Add(method);
|
||||
}
|
||||
|
||||
isAddingMethods = true;
|
||||
Panel.SetPage(HookManagerPanel.Pages.ClassMethodSelector);
|
||||
Panel.AddHooksScrollPool.Refresh(true, true);
|
||||
}
|
||||
|
||||
public void DoneAddingHooks()
|
||||
{
|
||||
isAddingMethods = false;
|
||||
Panel.SetPage(HookManagerPanel.Pages.CurrentHooks);
|
||||
Panel.HooksScrollPool.Refresh(true, false);
|
||||
}
|
||||
|
||||
public void AddHookClicked(int index)
|
||||
{
|
||||
if (index >= this.filteredEligableMethods.Count)
|
||||
return;
|
||||
|
||||
AddHook(filteredEligableMethods[index]);
|
||||
Panel.AddHooksScrollPool.Refresh(true, false);
|
||||
}
|
||||
|
||||
public void AddHook(MethodInfo method)
|
||||
{
|
||||
var sig = method.FullDescription();
|
||||
if (hookedSignatures.Contains(sig))
|
||||
return;
|
||||
|
||||
var hook = new HookInstance(method);
|
||||
if (hook.Enabled)
|
||||
{
|
||||
hookedSignatures.Add(sig);
|
||||
currentHooks.Add(sig, hook);
|
||||
}
|
||||
}
|
||||
|
||||
public void OnAddHookFilterInputChanged(string input)
|
||||
{
|
||||
filteredEligableMethods.Clear();
|
||||
|
||||
if (string.IsNullOrEmpty(input))
|
||||
filteredEligableMethods.AddRange(currentAddEligableMethods);
|
||||
else
|
||||
{
|
||||
foreach (var method in currentAddEligableMethods)
|
||||
{
|
||||
if (method.Name.ContainsIgnoreCase(input))
|
||||
filteredEligableMethods.Add(method);
|
||||
}
|
||||
}
|
||||
|
||||
Panel.AddHooksScrollPool.Refresh(true, true);
|
||||
}
|
||||
|
||||
// Set eligable method cell
|
||||
|
||||
public void OnCellBorrowed(AddHookCell cell) { }
|
||||
|
||||
public void SetCell(AddHookCell cell, int index)
|
||||
{
|
||||
if (index >= this.filteredEligableMethods.Count)
|
||||
{
|
||||
cell.Disable();
|
||||
return;
|
||||
}
|
||||
|
||||
cell.CurrentDisplayedIndex = index;
|
||||
var method = this.filteredEligableMethods[index];
|
||||
|
||||
cell.MethodNameLabel.text = SignatureHighlighter.HighlightMethod(method);
|
||||
|
||||
var sig = method.FullDescription();
|
||||
if (hookedSignatures.Contains(sig))
|
||||
{
|
||||
cell.HookButton.Component.gameObject.SetActive(false);
|
||||
cell.HookedLabel.gameObject.SetActive(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
cell.HookButton.Component.gameObject.SetActive(true);
|
||||
cell.HookedLabel.gameObject.SetActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
// ~~~~~~~~~~~ Hook source editor window ~~~~~~~~~~~
|
||||
|
||||
public void OnEditorInputChanged(string value)
|
||||
{
|
||||
Panel.EditorHighlightText.text = Lexer.BuildHighlightedString(value, 0, value.Length - 1, 0,
|
||||
Panel.EditorInput.Component.caretPosition, out _);
|
||||
}
|
||||
|
||||
public void EditorInputCancel()
|
||||
{
|
||||
currentEditedHook = null;
|
||||
Panel.SetPage(HookManagerPanel.Pages.CurrentHooks);
|
||||
}
|
||||
|
||||
public void EditorInputSave()
|
||||
{
|
||||
var input = Panel.EditorInput.Text;
|
||||
bool wasEnabled = currentEditedHook.Enabled;
|
||||
if (currentEditedHook.CompileAndGenerateProcessor(input))
|
||||
{
|
||||
if (wasEnabled)
|
||||
currentEditedHook.Patch();
|
||||
currentEditedHook.PatchSourceCode = input;
|
||||
currentEditedHook = null;
|
||||
Panel.SetPage(HookManagerPanel.Pages.CurrentHooks);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,35 +1,25 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UniverseLib.Input;
|
||||
using UnityExplorer.UI;
|
||||
using UniverseLib.UI.Models;
|
||||
using System.Collections;
|
||||
using UnityExplorer.UI.Panels;
|
||||
using UnityExplorer.UI.Widgets;
|
||||
using UnityExplorer.UI.Widgets.AutoComplete;
|
||||
using UniverseLib.UI.Widgets;
|
||||
using UniverseLib.UI;
|
||||
using UniverseLib;
|
||||
using UniverseLib.UI.Models;
|
||||
using UniverseLib.UI.Widgets;
|
||||
using UniverseLib.UI.Widgets.ScrollView;
|
||||
using UniverseLib.Utility;
|
||||
|
||||
namespace UnityExplorer.Inspectors
|
||||
{
|
||||
public class GameObjectInspector : InspectorBase
|
||||
{
|
||||
public GameObject GOTarget => Target as GameObject;
|
||||
public new GameObject Target => base.Target as GameObject;
|
||||
|
||||
public GameObject Content;
|
||||
|
||||
public GameObjectControls GOControls;
|
||||
public GameObjectControls Controls;
|
||||
|
||||
public TransformTree TransformTree;
|
||||
private ScrollPool<TransformCell> transformScroll;
|
||||
private readonly List<GameObject> cachedChildren = new List<GameObject>();
|
||||
private readonly List<GameObject> cachedChildren = new();
|
||||
|
||||
public ComponentList ComponentList;
|
||||
private ScrollPool<ComponentCell> componentScroll;
|
||||
@ -41,10 +31,10 @@ namespace UnityExplorer.Inspectors
|
||||
{
|
||||
base.OnBorrowedFromPool(target);
|
||||
|
||||
Target = target as GameObject;
|
||||
base.Target = target as GameObject;
|
||||
|
||||
GOControls.UpdateGameObjectInfo(true, true);
|
||||
GOControls.UpdateTransformControlValues(true);
|
||||
Controls.UpdateGameObjectInfo(true, true);
|
||||
Controls.TransformControl.UpdateTransformControlValues(true);
|
||||
|
||||
RuntimeHelper.StartCoroutine(InitCoroutine());
|
||||
}
|
||||
@ -77,11 +67,11 @@ namespace UnityExplorer.Inspectors
|
||||
InspectorManager.ReleaseInspector(this);
|
||||
}
|
||||
|
||||
public void ChangeTarget(GameObject newTarget)
|
||||
public void OnTransformCellClicked(GameObject newTarget)
|
||||
{
|
||||
this.Target = newTarget;
|
||||
GOControls.UpdateGameObjectInfo(true, true);
|
||||
GOControls.UpdateTransformControlValues(true);
|
||||
base.Target = newTarget;
|
||||
Controls.UpdateGameObjectInfo(true, true);
|
||||
Controls.TransformControl.UpdateTransformControlValues(true);
|
||||
TransformTree.RefreshData(true, false, true, false);
|
||||
UpdateComponents();
|
||||
}
|
||||
@ -93,21 +83,21 @@ namespace UnityExplorer.Inspectors
|
||||
if (!this.IsActive)
|
||||
return;
|
||||
|
||||
if (Target.IsNullOrDestroyed(false))
|
||||
if (base.Target.IsNullOrDestroyed(false))
|
||||
{
|
||||
InspectorManager.ReleaseInspector(this);
|
||||
return;
|
||||
}
|
||||
|
||||
GOControls.UpdateVectorSlider();
|
||||
GOControls.UpdateTransformControlValues(false);
|
||||
Controls.UpdateVectorSlider();
|
||||
Controls.TransformControl.UpdateTransformControlValues(false);
|
||||
|
||||
// Slow update
|
||||
if (timeOfLastUpdate.OccuredEarlierThan(1))
|
||||
{
|
||||
timeOfLastUpdate = Time.realtimeSinceStartup;
|
||||
|
||||
GOControls.UpdateGameObjectInfo(false, false);
|
||||
Controls.UpdateGameObjectInfo(false, false);
|
||||
|
||||
TransformTree.RefreshData(true, false, false, false);
|
||||
UpdateComponents();
|
||||
@ -118,26 +108,26 @@ namespace UnityExplorer.Inspectors
|
||||
|
||||
private IEnumerable<GameObject> GetTransformEntries()
|
||||
{
|
||||
if (!GOTarget)
|
||||
if (!Target)
|
||||
return Enumerable.Empty<GameObject>();
|
||||
|
||||
cachedChildren.Clear();
|
||||
for (int i = 0; i < GOTarget.transform.childCount; i++)
|
||||
cachedChildren.Add(GOTarget.transform.GetChild(i).gameObject);
|
||||
for (int i = 0; i < Target.transform.childCount; i++)
|
||||
cachedChildren.Add(Target.transform.GetChild(i).gameObject);
|
||||
return cachedChildren;
|
||||
}
|
||||
|
||||
private readonly List<Component> componentEntries = new List<Component>();
|
||||
private readonly HashSet<int> compInstanceIDs = new HashSet<int>();
|
||||
private readonly List<Behaviour> behaviourEntries = new List<Behaviour>();
|
||||
private readonly List<bool> behaviourEnabledStates = new List<bool>();
|
||||
private readonly List<Component> componentEntries = new();
|
||||
private readonly HashSet<int> compInstanceIDs = new();
|
||||
private readonly List<Behaviour> behaviourEntries = new();
|
||||
private readonly List<bool> behaviourEnabledStates = new();
|
||||
|
||||
// ComponentList.GetRootEntriesMethod
|
||||
private List<Component> GetComponentEntries() => GOTarget ? componentEntries : Enumerable.Empty<Component>().ToList();
|
||||
private List<Component> GetComponentEntries() => Target ? componentEntries : Enumerable.Empty<Component>().ToList();
|
||||
|
||||
public void UpdateComponents()
|
||||
{
|
||||
if (!GOTarget)
|
||||
if (!Target)
|
||||
{
|
||||
componentEntries.Clear();
|
||||
compInstanceIDs.Clear();
|
||||
@ -149,13 +139,13 @@ namespace UnityExplorer.Inspectors
|
||||
}
|
||||
|
||||
// Check if we actually need to refresh the component cells or not.
|
||||
var comps = GOTarget.GetComponents<Component>();
|
||||
var behaviours = GOTarget.GetComponents<Behaviour>();
|
||||
IEnumerable<Component> comps = Target.GetComponents<Component>();
|
||||
IEnumerable<Behaviour> behaviours = Target.GetComponents<Behaviour>();
|
||||
|
||||
bool needRefresh = false;
|
||||
|
||||
int count = 0;
|
||||
foreach (var comp in comps)
|
||||
foreach (Component comp in comps)
|
||||
{
|
||||
if (!comp)
|
||||
continue;
|
||||
@ -173,7 +163,7 @@ namespace UnityExplorer.Inspectors
|
||||
else
|
||||
{
|
||||
count = 0;
|
||||
foreach (var behaviour in behaviours)
|
||||
foreach (Behaviour behaviour in behaviours)
|
||||
{
|
||||
if (!behaviour)
|
||||
continue;
|
||||
@ -194,19 +184,35 @@ namespace UnityExplorer.Inspectors
|
||||
|
||||
componentEntries.Clear();
|
||||
compInstanceIDs.Clear();
|
||||
foreach (var comp in comps)
|
||||
foreach (Component comp in comps)
|
||||
{
|
||||
if (!comp) continue;
|
||||
if (!comp)
|
||||
continue;
|
||||
componentEntries.Add(comp);
|
||||
compInstanceIDs.Add(comp.GetInstanceID());
|
||||
}
|
||||
|
||||
behaviourEntries.Clear();
|
||||
behaviourEnabledStates.Clear();
|
||||
foreach (var behaviour in behaviours)
|
||||
foreach (Behaviour behaviour in behaviours)
|
||||
{
|
||||
if (!behaviour) continue;
|
||||
behaviourEntries.Add(behaviour);
|
||||
if (!behaviour)
|
||||
continue;
|
||||
|
||||
// Don't ask me how, but in some games this can be true for certain components.
|
||||
// They get picked up from GetComponents<Behaviour>, but they are not actually Behaviour...?
|
||||
if (!typeof(Behaviour).IsAssignableFrom(behaviour.GetType()))
|
||||
continue;
|
||||
|
||||
try
|
||||
{
|
||||
behaviourEntries.Add(behaviour);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ExplorerCore.LogWarning(ex);
|
||||
}
|
||||
|
||||
behaviourEnabledStates.Add(behaviour.enabled);
|
||||
}
|
||||
|
||||
@ -217,8 +223,8 @@ namespace UnityExplorer.Inspectors
|
||||
|
||||
private void OnAddChildClicked(string input)
|
||||
{
|
||||
var newObject = new GameObject(input);
|
||||
newObject.transform.parent = GOTarget.transform;
|
||||
GameObject newObject = new(input);
|
||||
newObject.transform.parent = Target.transform;
|
||||
|
||||
TransformTree.RefreshData(true, false, true, false);
|
||||
}
|
||||
@ -229,7 +235,7 @@ namespace UnityExplorer.Inspectors
|
||||
{
|
||||
try
|
||||
{
|
||||
RuntimeHelper.AddComponent<Component>(GOTarget, type);
|
||||
RuntimeHelper.AddComponent<Component>(Target, type);
|
||||
UpdateComponents();
|
||||
}
|
||||
catch (Exception ex)
|
||||
@ -250,14 +256,14 @@ namespace UnityExplorer.Inspectors
|
||||
UIRoot = UIFactory.CreateVerticalGroup(parent, "GameObjectInspector", true, false, true, true, 5,
|
||||
new Vector4(4, 4, 4, 4), new Color(0.065f, 0.065f, 0.065f));
|
||||
|
||||
var scrollObj = UIFactory.CreateScrollView(UIRoot, "GameObjectInspector", out Content, out var scrollbar,
|
||||
GameObject scrollObj = UIFactory.CreateScrollView(UIRoot, "GameObjectInspector", out Content, out AutoSliderScrollbar scrollbar,
|
||||
new Color(0.065f, 0.065f, 0.065f));
|
||||
UIFactory.SetLayoutElement(scrollObj, minHeight: 250, preferredHeight: 300, flexibleHeight: 0, flexibleWidth: 9999);
|
||||
|
||||
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(Content, spacing: 3, padTop: 2, padBottom: 2, padLeft: 2, padRight: 2);
|
||||
|
||||
// Construct GO Controls
|
||||
GOControls = new GameObjectControls(this);
|
||||
Controls = new GameObjectControls(this);
|
||||
|
||||
ConstructLists();
|
||||
|
||||
@ -268,27 +274,27 @@ namespace UnityExplorer.Inspectors
|
||||
|
||||
private void ConstructLists()
|
||||
{
|
||||
var listHolder = UIFactory.CreateUIObject("ListHolders", UIRoot);
|
||||
GameObject listHolder = UIFactory.CreateUIObject("ListHolders", UIRoot);
|
||||
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(listHolder, false, true, true, true, 8, 2, 2, 2, 2);
|
||||
UIFactory.SetLayoutElement(listHolder, minHeight: 150, flexibleWidth: 9999, flexibleHeight: 9999);
|
||||
|
||||
// Left group (Children)
|
||||
|
||||
var leftGroup = UIFactory.CreateUIObject("ChildrenGroup", listHolder);
|
||||
GameObject leftGroup = UIFactory.CreateUIObject("ChildrenGroup", listHolder);
|
||||
UIFactory.SetLayoutElement(leftGroup, flexibleWidth: 9999, flexibleHeight: 9999);
|
||||
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(leftGroup, false, false, true, true, 2);
|
||||
|
||||
var childrenLabel = UIFactory.CreateLabel(leftGroup, "ChildListTitle", "Children", TextAnchor.MiddleCenter, default, false, 16);
|
||||
Text childrenLabel = UIFactory.CreateLabel(leftGroup, "ChildListTitle", "Children", TextAnchor.MiddleCenter, default, false, 16);
|
||||
UIFactory.SetLayoutElement(childrenLabel.gameObject, flexibleWidth: 9999);
|
||||
|
||||
// Add Child
|
||||
var addChildRow = UIFactory.CreateUIObject("AddChildRow", leftGroup);
|
||||
GameObject addChildRow = UIFactory.CreateUIObject("AddChildRow", leftGroup);
|
||||
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(addChildRow, false, false, true, true, 2);
|
||||
|
||||
addChildInput = UIFactory.CreateInputField(addChildRow, "AddChildInput", "Enter a name...");
|
||||
UIFactory.SetLayoutElement(addChildInput.Component.gameObject, minHeight: 25, preferredWidth: 9999);
|
||||
|
||||
var addChildButton = UIFactory.CreateButton(addChildRow, "AddChildButton", "Add Child");
|
||||
ButtonRef addChildButton = UIFactory.CreateButton(addChildRow, "AddChildButton", "Add Child");
|
||||
UIFactory.SetLayoutElement(addChildButton.Component.gameObject, minHeight: 25, minWidth: 80);
|
||||
addChildButton.OnClick += () => { OnAddChildClicked(addChildInput.Text); };
|
||||
|
||||
@ -296,35 +302,31 @@ namespace UnityExplorer.Inspectors
|
||||
|
||||
transformScroll = UIFactory.CreateScrollPool<TransformCell>(leftGroup, "TransformTree", out GameObject transformObj,
|
||||
out GameObject transformContent, new Color(0.11f, 0.11f, 0.11f));
|
||||
UIFactory.SetLayoutElement(transformObj, flexibleHeight: 9999);
|
||||
UIFactory.SetLayoutElement(transformContent, flexibleHeight: 9999);
|
||||
|
||||
TransformTree = new TransformTree(transformScroll, GetTransformEntries);
|
||||
TransformTree.Init();
|
||||
TransformTree.OnClickOverrideHandler = ChangeTarget;
|
||||
TransformTree = new TransformTree(transformScroll, GetTransformEntries, OnTransformCellClicked);
|
||||
|
||||
// Right group (Components)
|
||||
|
||||
var rightGroup = UIFactory.CreateUIObject("ComponentGroup", listHolder);
|
||||
GameObject rightGroup = UIFactory.CreateUIObject("ComponentGroup", listHolder);
|
||||
UIFactory.SetLayoutElement(rightGroup, flexibleWidth: 9999, flexibleHeight: 9999);
|
||||
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(rightGroup, false, false, true, true, 2);
|
||||
|
||||
var compLabel = UIFactory.CreateLabel(rightGroup, "CompListTitle", "Components", TextAnchor.MiddleCenter, default, false, 16);
|
||||
Text compLabel = UIFactory.CreateLabel(rightGroup, "CompListTitle", "Components", TextAnchor.MiddleCenter, default, false, 16);
|
||||
UIFactory.SetLayoutElement(compLabel.gameObject, flexibleWidth: 9999);
|
||||
|
||||
// Add Comp
|
||||
var addCompRow = UIFactory.CreateUIObject("AddCompRow", rightGroup);
|
||||
GameObject addCompRow = UIFactory.CreateUIObject("AddCompRow", rightGroup);
|
||||
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(addCompRow, false, false, true, true, 2);
|
||||
|
||||
addCompInput = UIFactory.CreateInputField(addCompRow, "AddCompInput", "Enter a Component type...");
|
||||
UIFactory.SetLayoutElement(addCompInput.Component.gameObject, minHeight: 25, preferredWidth: 9999);
|
||||
|
||||
var addCompButton = UIFactory.CreateButton(addCompRow, "AddCompButton", "Add Comp");
|
||||
ButtonRef addCompButton = UIFactory.CreateButton(addCompRow, "AddCompButton", "Add Comp");
|
||||
UIFactory.SetLayoutElement(addCompButton.Component.gameObject, minHeight: 25, minWidth: 80);
|
||||
addCompButton.OnClick += () => { OnAddComponentClicked(addCompInput.Text); };
|
||||
|
||||
// comp autocompleter
|
||||
new TypeCompleter(typeof(Component), addCompInput);
|
||||
new TypeCompleter(typeof(Component), addCompInput, false, false, false);
|
||||
|
||||
// Component List
|
||||
|
||||
@ -333,8 +335,10 @@ namespace UnityExplorer.Inspectors
|
||||
UIFactory.SetLayoutElement(compObj, flexibleHeight: 9999);
|
||||
UIFactory.SetLayoutElement(compContent, flexibleHeight: 9999);
|
||||
|
||||
ComponentList = new ComponentList(componentScroll, GetComponentEntries);
|
||||
ComponentList.Parent = this;
|
||||
ComponentList = new ComponentList(componentScroll, GetComponentEntries)
|
||||
{
|
||||
Parent = this
|
||||
};
|
||||
componentScroll.Initialize(ComponentList);
|
||||
}
|
||||
|
||||
|
@ -1,697 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UniverseLib.Input;
|
||||
using UnityExplorer.UI;
|
||||
using UniverseLib.UI;
|
||||
using UniverseLib;
|
||||
using UnityExplorer.UI.Panels;
|
||||
using UniverseLib.UI.Models;
|
||||
using UniverseLib.Utility;
|
||||
|
||||
namespace UnityExplorer.Inspectors
|
||||
{
|
||||
public class GameObjectControls
|
||||
{
|
||||
public GameObjectInspector Parent;
|
||||
private GameObject GOTarget => Parent.GOTarget;
|
||||
|
||||
// Top info
|
||||
|
||||
private ButtonRef ViewParentButton;
|
||||
private InputFieldRef PathInput;
|
||||
|
||||
private InputFieldRef NameInput;
|
||||
private Toggle ActiveSelfToggle;
|
||||
private Text ActiveSelfText;
|
||||
private Toggle IsStaticToggle;
|
||||
|
||||
private InputFieldRef SceneInput;
|
||||
private InputFieldRef InstanceIDInput;
|
||||
private InputFieldRef TagInput;
|
||||
|
||||
private Dropdown LayerDropdown;
|
||||
private Dropdown FlagsDropdown;
|
||||
|
||||
// transform controls
|
||||
|
||||
private TransformControl PositionControl;
|
||||
private TransformControl LocalPositionControl;
|
||||
private TransformControl RotationControl;
|
||||
private TransformControl ScaleControl;
|
||||
|
||||
private VectorSlider currentSlidingVectorControl;
|
||||
private float currentVectorValue;
|
||||
|
||||
public GameObjectControls(GameObjectInspector parent)
|
||||
{
|
||||
this.Parent = parent;
|
||||
|
||||
ConstructTopInfo();
|
||||
ConstructTransformControls();
|
||||
}
|
||||
|
||||
private void OnCopyClicked()
|
||||
{
|
||||
ClipboardPanel.Copy(this.GOTarget);
|
||||
}
|
||||
|
||||
#region GO Controls
|
||||
|
||||
private string lastGoName;
|
||||
private string lastPath;
|
||||
private bool lastParentState;
|
||||
private int lastSceneHandle;
|
||||
private string lastTag;
|
||||
private int lastLayer;
|
||||
private int lastFlags;
|
||||
|
||||
public void UpdateGameObjectInfo(bool firstUpdate, bool force)
|
||||
{
|
||||
if (firstUpdate)
|
||||
{
|
||||
InstanceIDInput.Text = GOTarget.GetInstanceID().ToString();
|
||||
}
|
||||
|
||||
if (force || (!NameInput.Component.isFocused && GOTarget.name != lastGoName))
|
||||
{
|
||||
lastGoName = GOTarget.name;
|
||||
Parent.Tab.TabText.text = $"[G] {GOTarget.name}";
|
||||
NameInput.Text = GOTarget.name;
|
||||
}
|
||||
|
||||
if (force || !PathInput.Component.isFocused)
|
||||
{
|
||||
string path = GOTarget.transform.GetTransformPath();
|
||||
if (path != lastPath)
|
||||
{
|
||||
lastPath = path;
|
||||
PathInput.Text = path;
|
||||
}
|
||||
}
|
||||
|
||||
if (force || GOTarget.transform.parent != lastParentState)
|
||||
{
|
||||
lastParentState = GOTarget.transform.parent;
|
||||
ViewParentButton.Component.interactable = lastParentState;
|
||||
if (lastParentState)
|
||||
{
|
||||
ViewParentButton.ButtonText.color = Color.white;
|
||||
ViewParentButton.ButtonText.text = "◄ View Parent";
|
||||
}
|
||||
else
|
||||
{
|
||||
ViewParentButton.ButtonText.color = Color.grey;
|
||||
ViewParentButton.ButtonText.text = "No parent";
|
||||
}
|
||||
}
|
||||
|
||||
if (force || GOTarget.activeSelf != ActiveSelfToggle.isOn)
|
||||
{
|
||||
ActiveSelfToggle.Set(GOTarget.activeSelf, false);
|
||||
ActiveSelfText.color = ActiveSelfToggle.isOn ? Color.green : Color.red;
|
||||
}
|
||||
|
||||
if (force || GOTarget.isStatic != IsStaticToggle.isOn)
|
||||
{
|
||||
IsStaticToggle.Set(GOTarget.isStatic, false);
|
||||
}
|
||||
|
||||
if (force || GOTarget.scene.handle != lastSceneHandle)
|
||||
{
|
||||
lastSceneHandle = GOTarget.scene.handle;
|
||||
SceneInput.Text = GOTarget.scene.IsValid() ? GOTarget.scene.name : "None (Asset/Resource)";
|
||||
}
|
||||
|
||||
if (force || (!TagInput.Component.isFocused && GOTarget.tag != lastTag))
|
||||
{
|
||||
lastTag = GOTarget.tag;
|
||||
TagInput.Text = lastTag;
|
||||
}
|
||||
|
||||
if (force || (GOTarget.layer != lastLayer))
|
||||
{
|
||||
lastLayer = GOTarget.layer;
|
||||
LayerDropdown.value = GOTarget.layer;
|
||||
}
|
||||
|
||||
if (force || ((int)GOTarget.hideFlags != lastFlags))
|
||||
{
|
||||
lastFlags = (int)GOTarget.hideFlags;
|
||||
FlagsDropdown.captionText.text = GOTarget.hideFlags.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnViewParentClicked()
|
||||
{
|
||||
if (this.GOTarget && this.GOTarget.transform.parent)
|
||||
{
|
||||
Parent.ChangeTarget(this.GOTarget.transform.parent.gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPathEndEdit(string input)
|
||||
{
|
||||
lastPath = input;
|
||||
|
||||
if (string.IsNullOrEmpty(input))
|
||||
{
|
||||
DoSetParent(null);
|
||||
}
|
||||
else
|
||||
{
|
||||
Transform parentToSet = null;
|
||||
|
||||
if (input.EndsWith("/"))
|
||||
input = input.Remove(input.Length - 1);
|
||||
|
||||
// try the easy way
|
||||
if (GameObject.Find(input) is GameObject found)
|
||||
{
|
||||
parentToSet = found.transform;
|
||||
}
|
||||
else
|
||||
{
|
||||
// look for inactive objects
|
||||
var name = input.Split('/').Last();
|
||||
var allObjects = RuntimeHelper.FindObjectsOfTypeAll(typeof(GameObject));
|
||||
var shortList = new List<GameObject>();
|
||||
foreach (var obj in allObjects)
|
||||
if (obj.name == name) shortList.Add(obj.TryCast<GameObject>());
|
||||
foreach (var go in shortList)
|
||||
{
|
||||
var path = go.transform.GetTransformPath(true);
|
||||
if (path.EndsWith("/"))
|
||||
path = path.Remove(path.Length - 1);
|
||||
if (path == input)
|
||||
{
|
||||
parentToSet = go.transform;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (parentToSet)
|
||||
DoSetParent(parentToSet);
|
||||
else
|
||||
{
|
||||
ExplorerCore.LogWarning($"Could not find any GameObject name or path '{input}'!");
|
||||
UpdateGameObjectInfo(false, true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void DoSetParent(Transform transform)
|
||||
{
|
||||
ExplorerCore.Log($"Setting target's transform parent to: {(transform == null ? "null" : $"'{transform.name}'")}");
|
||||
|
||||
if (GOTarget.GetComponent<RectTransform>())
|
||||
GOTarget.transform.SetParent(transform, false);
|
||||
else
|
||||
GOTarget.transform.parent = transform;
|
||||
|
||||
UpdateGameObjectInfo(false, false);
|
||||
UpdateTransformControlValues(false);
|
||||
}
|
||||
|
||||
private void OnNameEndEdit(string value)
|
||||
{
|
||||
GOTarget.name = value;
|
||||
UpdateGameObjectInfo(false, true);
|
||||
}
|
||||
|
||||
private void OnActiveSelfToggled(bool value)
|
||||
{
|
||||
GOTarget.SetActive(value);
|
||||
UpdateGameObjectInfo(false, true);
|
||||
}
|
||||
|
||||
private void OnTagEndEdit(string value)
|
||||
{
|
||||
try
|
||||
{
|
||||
GOTarget.tag = value;
|
||||
UpdateGameObjectInfo(false, true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ExplorerCore.LogWarning($"Exception setting tag! {ex.ReflectionExToString()}");
|
||||
}
|
||||
}
|
||||
|
||||
private void OnExploreButtonClicked()
|
||||
{
|
||||
var panel = UIManager.GetPanel<UI.Panels.ObjectExplorerPanel>(UIManager.Panels.ObjectExplorer);
|
||||
panel.SceneExplorer.JumpToTransform(this.Parent.GOTarget.transform);
|
||||
}
|
||||
|
||||
private void OnLayerDropdownChanged(int value)
|
||||
{
|
||||
GOTarget.layer = value;
|
||||
UpdateGameObjectInfo(false, true);
|
||||
}
|
||||
|
||||
private void OnFlagsDropdownChanged(int value)
|
||||
{
|
||||
try
|
||||
{
|
||||
var enumVal = hideFlagsValues[FlagsDropdown.options[value].text];
|
||||
GOTarget.hideFlags = enumVal;
|
||||
|
||||
UpdateGameObjectInfo(false, true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ExplorerCore.LogWarning($"Exception setting hideFlags: {ex}");
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDestroyClicked()
|
||||
{
|
||||
GameObject.Destroy(this.GOTarget);
|
||||
InspectorManager.ReleaseInspector(Parent);
|
||||
}
|
||||
|
||||
private void OnInstantiateClicked()
|
||||
{
|
||||
var clone = GameObject.Instantiate(this.GOTarget);
|
||||
InspectorManager.Inspect(clone);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Transform Controls
|
||||
|
||||
private enum TransformType { Position, LocalPosition, Rotation, Scale }
|
||||
|
||||
private class TransformControl
|
||||
{
|
||||
public TransformType Type;
|
||||
public InputFieldRef Input;
|
||||
|
||||
public TransformControl(TransformType type, InputFieldRef input)
|
||||
{
|
||||
this.Type = type;
|
||||
this.Input = input;
|
||||
}
|
||||
}
|
||||
|
||||
private class VectorSlider
|
||||
{
|
||||
public int axis;
|
||||
public Slider slider;
|
||||
public TransformControl parentControl;
|
||||
|
||||
public VectorSlider(int axis, Slider slider, TransformControl parentControl)
|
||||
{
|
||||
this.axis = axis;
|
||||
this.slider = slider;
|
||||
this.parentControl = parentControl;
|
||||
}
|
||||
}
|
||||
|
||||
private Vector3 lastPosValue;
|
||||
private Vector3 lastLocalValue;
|
||||
private Quaternion lastRotValue;
|
||||
private Vector3 lastScaleValue;
|
||||
|
||||
public void UpdateTransformControlValues(bool force)
|
||||
{
|
||||
var transform = GOTarget.transform;
|
||||
if (force || (!PositionControl.Input.Component.isFocused && lastPosValue != transform.position))
|
||||
{
|
||||
PositionControl.Input.Text = ParseUtility.ToStringForInput(transform.position, typeof(Vector3));
|
||||
lastPosValue = transform.position;
|
||||
}
|
||||
if (force || (!LocalPositionControl.Input.Component.isFocused && lastLocalValue != transform.localPosition))
|
||||
{
|
||||
LocalPositionControl.Input.Text = ParseUtility.ToStringForInput(transform.localPosition, typeof(Vector3));
|
||||
lastLocalValue = transform.localPosition;
|
||||
}
|
||||
if (force || (!RotationControl.Input.Component.isFocused && lastRotValue != transform.localRotation))
|
||||
{
|
||||
RotationControl.Input.Text = ParseUtility.ToStringForInput(transform.localRotation, typeof(Quaternion));
|
||||
lastRotValue = transform.localRotation;
|
||||
}
|
||||
if (force || (!ScaleControl.Input.Component.isFocused && lastScaleValue != transform.localScale))
|
||||
{
|
||||
ScaleControl.Input.Text = ParseUtility.ToStringForInput(transform.localScale, typeof(Vector3));
|
||||
lastScaleValue = transform.localScale;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnTransformInputEndEdit(TransformType type, string input)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case TransformType.Position:
|
||||
{
|
||||
if (ParseUtility.TryParse(input, typeof(Vector3), out object boxed, out _))
|
||||
GOTarget.transform.position = (Vector3)boxed;
|
||||
}
|
||||
break;
|
||||
case TransformType.LocalPosition:
|
||||
{
|
||||
if (ParseUtility.TryParse(input, typeof(Vector3), out object boxed, out _))
|
||||
GOTarget.transform.localPosition = (Vector3)boxed;
|
||||
}
|
||||
break;
|
||||
case TransformType.Rotation:
|
||||
{
|
||||
if (ParseUtility.TryParse(input, typeof(Quaternion), out object boxed, out _))
|
||||
GOTarget.transform.localRotation = (Quaternion)boxed;
|
||||
}
|
||||
break;
|
||||
case TransformType.Scale:
|
||||
{
|
||||
if (ParseUtility.TryParse(input, typeof(Vector3), out object boxed, out _))
|
||||
GOTarget.transform.localScale = (Vector3)boxed;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
UpdateTransformControlValues(true);
|
||||
}
|
||||
|
||||
private void OnVectorSliderChanged(VectorSlider slider, float value)
|
||||
{
|
||||
if (value == 0f)
|
||||
{
|
||||
currentSlidingVectorControl = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
currentSlidingVectorControl = slider;
|
||||
currentVectorValue = value;
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateVectorSlider()
|
||||
{
|
||||
if (currentSlidingVectorControl == null)
|
||||
return;
|
||||
|
||||
if (!InputManager.GetMouseButton(0))
|
||||
{
|
||||
currentSlidingVectorControl.slider.value = 0f;
|
||||
currentSlidingVectorControl = null;
|
||||
currentVectorValue = 0f;
|
||||
return;
|
||||
}
|
||||
|
||||
var transform = GOTarget.transform;
|
||||
|
||||
Vector3 vector = Vector2.zero;
|
||||
switch (currentSlidingVectorControl.parentControl.Type)
|
||||
{
|
||||
case TransformType.Position:
|
||||
vector = transform.position; break;
|
||||
case TransformType.LocalPosition:
|
||||
vector = transform.localPosition; break;
|
||||
case TransformType.Rotation:
|
||||
vector = transform.eulerAngles; break;
|
||||
case TransformType.Scale:
|
||||
vector = transform.localScale; break;
|
||||
}
|
||||
|
||||
// apply vector value change
|
||||
switch (currentSlidingVectorControl.axis)
|
||||
{
|
||||
case 0:
|
||||
vector.x += currentVectorValue; break;
|
||||
case 1:
|
||||
vector.y += currentVectorValue; break;
|
||||
case 2:
|
||||
vector.z += currentVectorValue; break;
|
||||
}
|
||||
|
||||
// set vector back to transform
|
||||
switch (currentSlidingVectorControl.parentControl.Type)
|
||||
{
|
||||
case TransformType.Position:
|
||||
transform.position = vector; break;
|
||||
case TransformType.LocalPosition:
|
||||
transform.localPosition = vector; break;
|
||||
case TransformType.Rotation:
|
||||
transform.eulerAngles = vector; break;
|
||||
case TransformType.Scale:
|
||||
transform.localScale = vector; break;
|
||||
}
|
||||
|
||||
UpdateTransformControlValues(false);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region GO Controls UI Construction
|
||||
|
||||
private void ConstructTopInfo()
|
||||
{
|
||||
var topInfoHolder = UIFactory.CreateVerticalGroup(Parent.Content, "TopInfoHolder", false, false, true, true, 3,
|
||||
new Vector4(3, 3, 3, 3), new Color(0.1f, 0.1f, 0.1f), TextAnchor.MiddleLeft);
|
||||
UIFactory.SetLayoutElement(topInfoHolder, minHeight: 100, flexibleWidth: 9999);
|
||||
topInfoHolder.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||||
|
||||
// first row (parent, path)
|
||||
|
||||
var firstRow = UIFactory.CreateUIObject("ParentRow", topInfoHolder);
|
||||
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(firstRow, false, false, true, true, 5, 0, 0, 0, 0, default);
|
||||
UIFactory.SetLayoutElement(firstRow, minHeight: 25, flexibleWidth: 9999);
|
||||
|
||||
ViewParentButton = UIFactory.CreateButton(firstRow, "ViewParentButton", "◄ View Parent", new Color(0.2f, 0.2f, 0.2f));
|
||||
ViewParentButton.ButtonText.fontSize = 13;
|
||||
UIFactory.SetLayoutElement(ViewParentButton.Component.gameObject, minHeight: 25, minWidth: 100);
|
||||
ViewParentButton.OnClick += OnViewParentClicked;
|
||||
|
||||
this.PathInput = UIFactory.CreateInputField(firstRow, "PathInput", "...");
|
||||
PathInput.Component.textComponent.color = Color.grey;
|
||||
PathInput.Component.textComponent.fontSize = 14;
|
||||
UIFactory.SetLayoutElement(PathInput.UIRoot, minHeight: 25, minWidth: 100, flexibleWidth: 9999);
|
||||
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));
|
||||
//UIFactory.SetLayoutElement(pathApplyBtn.Component.gameObject, minHeight: 25, minWidth: 120);
|
||||
//pathApplyBtn.OnClick += () => { OnPathEndEdit(PathInput.Text); };
|
||||
|
||||
PathInput.Component.GetOnEndEdit().AddListener((string val) => { OnPathEndEdit(val); });
|
||||
|
||||
// Title and update row
|
||||
|
||||
var titleRow = UIFactory.CreateUIObject("TitleRow", topInfoHolder);
|
||||
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(titleRow, false, false, true, true, 5);
|
||||
|
||||
var titleLabel = UIFactory.CreateLabel(titleRow, "Title", SignatureHighlighter.Parse(typeof(GameObject), false),
|
||||
TextAnchor.MiddleLeft, fontSize: 17);
|
||||
UIFactory.SetLayoutElement(titleLabel.gameObject, minHeight: 30, minWidth: 100);
|
||||
|
||||
// name
|
||||
|
||||
NameInput = UIFactory.CreateInputField(titleRow, "NameInput", "untitled");
|
||||
UIFactory.SetLayoutElement(NameInput.Component.gameObject, minHeight: 30, minWidth: 100, flexibleWidth: 9999);
|
||||
NameInput.Component.textComponent.fontSize = 15;
|
||||
NameInput.Component.GetOnEndEdit().AddListener((string val) => { OnNameEndEdit(val); });
|
||||
|
||||
// second row (toggles, instanceID, tag, buttons)
|
||||
|
||||
var secondRow = UIFactory.CreateUIObject("ParentRow", topInfoHolder);
|
||||
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(secondRow, false, false, true, true, 5, 0, 0, 0, 0, default);
|
||||
UIFactory.SetLayoutElement(secondRow, minHeight: 25, flexibleWidth: 9999);
|
||||
|
||||
// activeSelf
|
||||
var activeToggleObj = UIFactory.CreateToggle(secondRow, "ActiveSelf", out ActiveSelfToggle, out ActiveSelfText);
|
||||
UIFactory.SetLayoutElement(activeToggleObj, minHeight: 25, minWidth: 100);
|
||||
ActiveSelfText.text = "ActiveSelf";
|
||||
ActiveSelfToggle.onValueChanged.AddListener(OnActiveSelfToggled);
|
||||
|
||||
// isStatic
|
||||
var isStaticObj = UIFactory.CreateToggle(secondRow, "IsStatic", out IsStaticToggle, out Text staticText);
|
||||
UIFactory.SetLayoutElement(isStaticObj, minHeight: 25, minWidth: 80);
|
||||
staticText.text = "IsStatic";
|
||||
staticText.color = Color.grey;
|
||||
IsStaticToggle.interactable = false;
|
||||
|
||||
// InstanceID
|
||||
var instanceIdLabel = UIFactory.CreateLabel(secondRow, "InstanceIDLabel", "Instance ID:", TextAnchor.MiddleRight, Color.grey);
|
||||
UIFactory.SetLayoutElement(instanceIdLabel.gameObject, minHeight: 25, minWidth: 90);
|
||||
|
||||
InstanceIDInput = UIFactory.CreateInputField(secondRow, "InstanceIDInput", "error");
|
||||
UIFactory.SetLayoutElement(InstanceIDInput.Component.gameObject, minHeight: 25, minWidth: 110);
|
||||
InstanceIDInput.Component.textComponent.color = Color.grey;
|
||||
InstanceIDInput.Component.readOnly = true;
|
||||
|
||||
//Tag
|
||||
var tagLabel = UIFactory.CreateLabel(secondRow, "TagLabel", "Tag:", TextAnchor.MiddleRight, Color.grey);
|
||||
UIFactory.SetLayoutElement(tagLabel.gameObject, minHeight: 25, minWidth: 40);
|
||||
|
||||
TagInput = UIFactory.CreateInputField(secondRow, "TagInput", "none");
|
||||
UIFactory.SetLayoutElement(TagInput.Component.gameObject, minHeight: 25, minWidth: 100, flexibleWidth: 999);
|
||||
TagInput.Component.textComponent.color = Color.white;
|
||||
TagInput.Component.GetOnEndEdit().AddListener((string val) => { OnTagEndEdit(val); });
|
||||
|
||||
// Instantiate
|
||||
var instantiateBtn = UIFactory.CreateButton(secondRow, "InstantiateBtn", "Instantiate", new Color(0.2f, 0.2f, 0.2f));
|
||||
UIFactory.SetLayoutElement(instantiateBtn.Component.gameObject, minHeight: 25, minWidth: 120);
|
||||
instantiateBtn.OnClick += OnInstantiateClicked;
|
||||
|
||||
// Destroy
|
||||
var destroyBtn = UIFactory.CreateButton(secondRow, "DestroyBtn", "Destroy", new Color(0.3f, 0.2f, 0.2f));
|
||||
UIFactory.SetLayoutElement(destroyBtn.Component.gameObject, minHeight: 25, minWidth: 80);
|
||||
destroyBtn.OnClick += OnDestroyClicked;
|
||||
|
||||
// third row (scene, layer, flags)
|
||||
|
||||
var thirdrow = UIFactory.CreateUIObject("ParentRow", topInfoHolder);
|
||||
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(thirdrow, false, false, true, true, 5, 0, 0, 0, 0, default);
|
||||
UIFactory.SetLayoutElement(thirdrow, minHeight: 25, flexibleWidth: 9999);
|
||||
|
||||
// Inspect in Explorer button
|
||||
var explorerBtn = UIFactory.CreateButton(thirdrow, "ExploreBtn", "Show in Explorer", new Color(0.15f, 0.15f, 0.15f));
|
||||
UIFactory.SetLayoutElement(explorerBtn.Component.gameObject, minHeight: 25, minWidth: 100);
|
||||
explorerBtn.ButtonText.fontSize = 12;
|
||||
explorerBtn.OnClick += OnExploreButtonClicked;
|
||||
|
||||
// Scene
|
||||
var sceneLabel = UIFactory.CreateLabel(thirdrow, "SceneLabel", "Scene:", TextAnchor.MiddleLeft, Color.grey);
|
||||
UIFactory.SetLayoutElement(sceneLabel.gameObject, minHeight: 25, minWidth: 50);
|
||||
|
||||
SceneInput = UIFactory.CreateInputField(thirdrow, "SceneInput", "untitled");
|
||||
UIFactory.SetLayoutElement(SceneInput.Component.gameObject, minHeight: 25, minWidth: 120, flexibleWidth: 999);
|
||||
SceneInput.Component.readOnly = true;
|
||||
SceneInput.Component.textComponent.color = new Color(0.7f, 0.7f, 0.7f);
|
||||
|
||||
// Layer
|
||||
var layerLabel = UIFactory.CreateLabel(thirdrow, "LayerLabel", "Layer:", TextAnchor.MiddleLeft, Color.grey);
|
||||
UIFactory.SetLayoutElement(layerLabel.gameObject, minHeight: 25, minWidth: 50);
|
||||
|
||||
var layerDrop = UIFactory.CreateDropdown(thirdrow, "LayerDropdown", out LayerDropdown, "0", 14, OnLayerDropdownChanged);
|
||||
UIFactory.SetLayoutElement(layerDrop, minHeight: 25, minWidth: 110, flexibleWidth: 999);
|
||||
LayerDropdown.captionText.color = SignatureHighlighter.EnumGreen;
|
||||
if (layerToNames == null)
|
||||
GetLayerNames();
|
||||
foreach (var name in layerToNames)
|
||||
LayerDropdown.options.Add(new Dropdown.OptionData(name));
|
||||
LayerDropdown.value = 0;
|
||||
LayerDropdown.RefreshShownValue();
|
||||
|
||||
// Flags
|
||||
var flagsLabel = UIFactory.CreateLabel(thirdrow, "FlagsLabel", "Flags:", TextAnchor.MiddleRight, Color.grey);
|
||||
UIFactory.SetLayoutElement(flagsLabel.gameObject, minHeight: 25, minWidth: 50);
|
||||
|
||||
var flagsDrop = UIFactory.CreateDropdown(thirdrow, "FlagsDropdown", out FlagsDropdown, "None", 14, OnFlagsDropdownChanged);
|
||||
FlagsDropdown.captionText.color = SignatureHighlighter.EnumGreen;
|
||||
UIFactory.SetLayoutElement(flagsDrop, minHeight: 25, minWidth: 135, flexibleWidth: 999);
|
||||
if (hideFlagsValues == null)
|
||||
GetHideFlagNames();
|
||||
foreach (var name in hideFlagsValues.Keys)
|
||||
FlagsDropdown.options.Add(new Dropdown.OptionData(name));
|
||||
FlagsDropdown.value = 0;
|
||||
FlagsDropdown.RefreshShownValue();
|
||||
}
|
||||
|
||||
private static List<string> layerToNames;
|
||||
|
||||
private static void GetLayerNames()
|
||||
{
|
||||
layerToNames = new List<string>();
|
||||
for (int i = 0; i < 32; i++)
|
||||
{
|
||||
var name = RuntimeHelper.LayerToName(i);
|
||||
if (string.IsNullOrEmpty(name))
|
||||
name = i.ToString();
|
||||
layerToNames.Add(name);
|
||||
}
|
||||
}
|
||||
|
||||
private static Dictionary<string, HideFlags> hideFlagsValues;
|
||||
|
||||
private static void GetHideFlagNames()
|
||||
{
|
||||
hideFlagsValues = new Dictionary<string, HideFlags>();
|
||||
|
||||
var names = Enum.GetValues(typeof(HideFlags));
|
||||
foreach (HideFlags value in names)
|
||||
{
|
||||
hideFlagsValues.Add(value.ToString(), value);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Transform Controls UI Construction
|
||||
|
||||
private void ConstructTransformControls()
|
||||
{
|
||||
var transformGroup = UIFactory.CreateVerticalGroup(Parent.Content, "TransformControls", false, false, true, true, 2,
|
||||
new Vector4(2, 2, 0, 0), new Color(0.1f, 0.1f, 0.1f));
|
||||
UIFactory.SetLayoutElement(transformGroup, minHeight: 100, flexibleWidth: 9999);
|
||||
//transformGroup.SetActive(false);
|
||||
//var groupRect = transformGroup.GetComponent<RectTransform>();
|
||||
//groupRect.anchorMin = new Vector2(0, 1);
|
||||
//groupRect.anchorMax = new Vector2(1, 1);
|
||||
//groupRect.SetInsetAndSizeFromParentEdge(RectTransform.Edge.Top, 0, 100);
|
||||
|
||||
PositionControl = AddTransformRow(transformGroup, "Position:", TransformType.Position);
|
||||
LocalPositionControl = AddTransformRow(transformGroup, "Local Position:", TransformType.LocalPosition);
|
||||
RotationControl = AddTransformRow(transformGroup, "Rotation:", TransformType.Rotation);
|
||||
ScaleControl = AddTransformRow(transformGroup, "Scale:", TransformType.Scale);
|
||||
}
|
||||
|
||||
private TransformControl AddTransformRow(GameObject transformGroup, string title, TransformType type)
|
||||
{
|
||||
var rowObj = UIFactory.CreateUIObject("Row_" + title, transformGroup);
|
||||
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(rowObj, false, false, true, true, 5, 0, 0, 0, 0, default);
|
||||
UIFactory.SetLayoutElement(rowObj, minHeight: 25, flexibleWidth: 9999);
|
||||
|
||||
var titleLabel = UIFactory.CreateLabel(rowObj, "PositionLabel", title, TextAnchor.MiddleRight, Color.grey);
|
||||
UIFactory.SetLayoutElement(titleLabel.gameObject, minHeight: 25, minWidth: 110);
|
||||
|
||||
var inputField = UIFactory.CreateInputField(rowObj, "InputField", "...");
|
||||
UIFactory.SetLayoutElement(inputField.Component.gameObject, minHeight: 25, minWidth: 100, flexibleWidth: 999);
|
||||
|
||||
inputField.Component.GetOnEndEdit().AddListener((string value) => { OnTransformInputEndEdit(type, value); });
|
||||
|
||||
var control = new TransformControl(type, inputField);
|
||||
|
||||
AddVectorAxisSlider(rowObj, "X", 0, control);
|
||||
AddVectorAxisSlider(rowObj, "Y", 1, control);
|
||||
AddVectorAxisSlider(rowObj, "Z", 2, control);
|
||||
|
||||
return control;
|
||||
}
|
||||
|
||||
private VectorSlider AddVectorAxisSlider(GameObject parent, string title, int axis, TransformControl control)
|
||||
{
|
||||
var label = UIFactory.CreateLabel(parent, "Label_" + title, title + ":", TextAnchor.MiddleRight, Color.grey);
|
||||
UIFactory.SetLayoutElement(label.gameObject, minHeight: 25, minWidth: 30);
|
||||
|
||||
var sliderObj = UIFactory.CreateSlider(parent, "Slider_" + title, out var slider);
|
||||
UIFactory.SetLayoutElement(sliderObj, minHeight: 25, minWidth: 120, flexibleWidth: 0);
|
||||
slider.m_FillImage.color = Color.clear;
|
||||
|
||||
slider.minValue = -1;
|
||||
slider.maxValue = 1;
|
||||
var sliderControl = new VectorSlider(axis, slider, control);
|
||||
|
||||
slider.onValueChanged.AddListener((float val) =>
|
||||
{
|
||||
OnVectorSliderChanged(sliderControl, val);
|
||||
});
|
||||
|
||||
return sliderControl;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
@ -1,13 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.UI;
|
||||
using UniverseLib.UI.Models;
|
||||
using UnityExplorer.UI.Panels;
|
||||
using UniverseLib.UI;
|
||||
using UnityExplorer.UI.Panels;
|
||||
using UniverseLib.UI.ObjectPool;
|
||||
|
||||
namespace UnityExplorer.Inspectors
|
||||
@ -16,6 +7,7 @@ namespace UnityExplorer.Inspectors
|
||||
{
|
||||
public bool IsActive { get; internal set; }
|
||||
public object Target { get; set; }
|
||||
public Type TargetType { get; protected set; }
|
||||
|
||||
public InspectorTab Tab { get; internal set; }
|
||||
|
||||
@ -31,6 +23,8 @@ namespace UnityExplorer.Inspectors
|
||||
public virtual void OnBorrowedFromPool(object target)
|
||||
{
|
||||
this.Target = target;
|
||||
this.TargetType = target is Type type ? type : target.GetActualType();
|
||||
|
||||
Tab = Pool<InspectorTab>.Borrow();
|
||||
Tab.UIRoot.transform.SetParent(InspectorPanel.Instance.NavbarHolder.transform, false);
|
||||
|
||||
|
@ -1,18 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.UI;
|
||||
using UnityExplorer.CacheObject;
|
||||
using UnityExplorer.CacheObject;
|
||||
using UnityExplorer.Inspectors;
|
||||
using UniverseLib.UI.Models;
|
||||
using UnityExplorer.UI;
|
||||
using UnityExplorer.UI.Panels;
|
||||
using UniverseLib;
|
||||
using UniverseLib.UI;
|
||||
using UniverseLib.UI.ObjectPool;
|
||||
using UniverseLib.Utility;
|
||||
|
||||
namespace UnityExplorer
|
||||
{
|
||||
@ -27,7 +17,7 @@ namespace UnityExplorer
|
||||
|
||||
public static event Action OnInspectedTabsChanged;
|
||||
|
||||
public static void Inspect(object obj, CacheObjectBase sourceCache = null)
|
||||
public static void Inspect(object obj, CacheObjectBase parent = null)
|
||||
{
|
||||
if (obj.IsNullOrDestroyed())
|
||||
return;
|
||||
@ -40,19 +30,34 @@ namespace UnityExplorer
|
||||
if (obj is GameObject)
|
||||
CreateInspector<GameObjectInspector>(obj);
|
||||
else
|
||||
CreateInspector<ReflectionInspector>(obj, false, sourceCache);
|
||||
CreateInspector<ReflectionInspector>(obj, false, parent);
|
||||
}
|
||||
|
||||
public static void Inspect(Type type)
|
||||
{
|
||||
if (TryFocusActiveInspector(type))
|
||||
return;
|
||||
|
||||
CreateInspector<ReflectionInspector>(type, true);
|
||||
}
|
||||
|
||||
private static bool TryFocusActiveInspector(object target)
|
||||
static bool TryFocusActiveInspector(object target)
|
||||
{
|
||||
foreach (var inspector in Inspectors)
|
||||
foreach (InspectorBase inspector in Inspectors)
|
||||
{
|
||||
if (inspector.Target.ReferenceEqual(target))
|
||||
bool shouldFocus = false;
|
||||
|
||||
if (target is Type targetAsType)
|
||||
{
|
||||
if (inspector.TargetType.FullName == targetAsType.FullName)
|
||||
shouldFocus = true;
|
||||
}
|
||||
else if(inspector.Target.ReferenceEqual(target))
|
||||
{
|
||||
shouldFocus = true;
|
||||
}
|
||||
|
||||
if (shouldFocus)
|
||||
{
|
||||
UIManager.SetPanelActive(UIManager.Panels.Inspector, true);
|
||||
SetInspectorActive(inspector);
|
||||
@ -80,7 +85,7 @@ namespace UnityExplorer
|
||||
}
|
||||
}
|
||||
|
||||
internal static void CloseAllTabs()
|
||||
public static void CloseAllTabs()
|
||||
{
|
||||
if (Inspectors.Any())
|
||||
{
|
||||
@ -93,18 +98,17 @@ namespace UnityExplorer
|
||||
UIManager.SetPanelActive(UIManager.Panels.Inspector, false);
|
||||
}
|
||||
|
||||
private static void CreateInspector<T>(object target, bool staticReflection = false,
|
||||
CacheObjectBase parentObject = null) where T : InspectorBase
|
||||
static void CreateInspector<T>(object target, bool staticReflection = false, CacheObjectBase parent = null) where T : InspectorBase
|
||||
{
|
||||
var inspector = Pool<T>.Borrow();
|
||||
T inspector = Pool<T>.Borrow();
|
||||
Inspectors.Add(inspector);
|
||||
inspector.Target = target;
|
||||
|
||||
if (parentObject != null && parentObject.CanWrite)
|
||||
if (parent != null && parent.CanWrite)
|
||||
{
|
||||
// only set parent cache object if we are inspecting a struct, otherwise there is no point.
|
||||
if (target.GetType().IsValueType && inspector is ReflectionInspector ri)
|
||||
ri.ParentCacheObject = parentObject;
|
||||
ri.ParentCacheObject = parent;
|
||||
}
|
||||
|
||||
UIManager.SetPanelActive(UIManager.Panels.Inspector, true);
|
||||
@ -119,7 +123,7 @@ namespace UnityExplorer
|
||||
OnInspectedTabsChanged?.Invoke();
|
||||
}
|
||||
|
||||
internal static void ReleaseInspector<T>(T inspector) where T : InspectorBase
|
||||
public static void ReleaseInspector<T>(T inspector) where T : InspectorBase
|
||||
{
|
||||
if (lastActiveInspector == inspector)
|
||||
lastActiveInspector = null;
|
||||
@ -164,7 +168,7 @@ namespace UnityExplorer
|
||||
{
|
||||
PanelWidth = width;
|
||||
|
||||
foreach (var obj in Inspectors)
|
||||
foreach (InspectorBase obj in Inspectors)
|
||||
{
|
||||
if (obj is ReflectionInspector inspector)
|
||||
{
|
||||
|
@ -1,15 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.UI;
|
||||
using UniverseLib.UI;
|
||||
using UniverseLib.UI.Models;
|
||||
using UnityExplorer.UI.Widgets;
|
||||
using UniverseLib.UI;
|
||||
using UniverseLib;
|
||||
using UnityExplorer.UI.Panels;
|
||||
using UniverseLib.UI.ObjectPool;
|
||||
|
||||
namespace UnityExplorer.Inspectors
|
||||
|
@ -1,19 +1,10 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.UI;
|
||||
using UniverseLib.Input;
|
||||
using UnityExplorer.Runtime;
|
||||
using UnityExplorer.Config;
|
||||
using UnityExplorer.Inspectors.MouseInspectors;
|
||||
using UnityExplorer.UI;
|
||||
using UnityExplorer.UI.Panels;
|
||||
using UniverseLib;
|
||||
using UniverseLib.Input;
|
||||
using UniverseLib.UI;
|
||||
using UniverseLib.Utility;
|
||||
using UnityExplorer.Config;
|
||||
using UniverseLib.UI.Panels;
|
||||
|
||||
namespace UnityExplorer.Inspectors
|
||||
{
|
||||
@ -23,7 +14,7 @@ namespace UnityExplorer.Inspectors
|
||||
UI
|
||||
}
|
||||
|
||||
public class MouseInspector : UIPanel
|
||||
public class MouseInspector : PanelBase
|
||||
{
|
||||
public static MouseInspector Instance { get; private set; }
|
||||
|
||||
@ -44,22 +35,21 @@ namespace UnityExplorer.Inspectors
|
||||
|
||||
// UIPanel
|
||||
internal static readonly string UIBaseGUID = $"{ExplorerCore.GUID}.MouseInspector";
|
||||
private UIBase inspectorUIBase;
|
||||
internal static UIBase inspectorUIBase;
|
||||
|
||||
public override string Name => "Inspect Under Mouse";
|
||||
public override UIManager.Panels PanelType => UIManager.Panels.MouseInspector;
|
||||
public override int MinWidth => -1;
|
||||
public override int MinHeight => -1;
|
||||
public override Vector2 DefaultAnchorMin => Vector2.zero;
|
||||
public override Vector2 DefaultAnchorMax => Vector2.zero;
|
||||
|
||||
public override bool CanDragAndResize => false;
|
||||
public override bool NavButtonWanted => false;
|
||||
public override bool ShouldSaveActiveState => false;
|
||||
public override bool ShowByDefault => false;
|
||||
|
||||
internal Text objNameLabel;
|
||||
internal Text objPathLabel;
|
||||
internal Text mousePosLabel;
|
||||
|
||||
public MouseInspector()
|
||||
public MouseInspector(UIBase owner) : base(owner)
|
||||
{
|
||||
Instance = this;
|
||||
worldInspector = new WorldInspector();
|
||||
@ -84,11 +74,12 @@ namespace UnityExplorer.Inspectors
|
||||
|
||||
CurrentInspector.OnBeginMouseInspect();
|
||||
|
||||
PanelDragger.ForceEnd();
|
||||
PanelManager.ForceEndResize();
|
||||
UIManager.NavBarRect.gameObject.SetActive(false);
|
||||
UIManager.PanelHolder.SetActive(false);
|
||||
UIManager.UiBase.Panels.PanelHolder.SetActive(false);
|
||||
UIManager.UiBase.SetOnTop();
|
||||
|
||||
UIRoot.SetActive(true);
|
||||
SetActive(true);
|
||||
}
|
||||
|
||||
internal void ClearHitData()
|
||||
@ -106,9 +97,9 @@ namespace UnityExplorer.Inspectors
|
||||
Inspecting = false;
|
||||
|
||||
UIManager.NavBarRect.gameObject.SetActive(true);
|
||||
UIManager.PanelHolder.SetActive(true);
|
||||
UIManager.UiBase.Panels.PanelHolder.SetActive(true);
|
||||
|
||||
var drop = InspectorPanel.Instance.MouseInspectDropdown;
|
||||
Dropdown drop = InspectorPanel.Instance.MouseInspectDropdown;
|
||||
if (drop.transform.Find("Dropdown List") is Transform list)
|
||||
drop.DestroyDropdownList(list.gameObject);
|
||||
|
||||
@ -119,18 +110,12 @@ namespace UnityExplorer.Inspectors
|
||||
|
||||
public bool TryUpdate()
|
||||
{
|
||||
if (ConfigManager.World_MouseInspect_Keybind.Value != KeyCode.None)
|
||||
{
|
||||
if (InputManager.GetKeyDown(ConfigManager.World_MouseInspect_Keybind.Value))
|
||||
Instance.StartInspect(MouseInspectMode.World);
|
||||
}
|
||||
if (InputManager.GetKeyDown(ConfigManager.World_MouseInspect_Keybind.Value))
|
||||
Instance.StartInspect(MouseInspectMode.World);
|
||||
|
||||
if (InputManager.GetKeyDown(ConfigManager.UI_MouseInspect_Keybind.Value))
|
||||
Instance.StartInspect(MouseInspectMode.UI);
|
||||
|
||||
if (ConfigManager.World_MouseInspect_Keybind.Value != KeyCode.None)
|
||||
{
|
||||
if (InputManager.GetKeyDown(ConfigManager.World_MouseInspect_Keybind.Value))
|
||||
Instance.StartInspect(MouseInspectMode.World);
|
||||
}
|
||||
|
||||
if (Inspecting)
|
||||
UpdateInspect();
|
||||
|
||||
@ -152,7 +137,7 @@ namespace UnityExplorer.Inspectors
|
||||
return;
|
||||
}
|
||||
|
||||
var mousePos = InputManager.MousePosition;
|
||||
Vector3 mousePos = InputManager.MousePosition;
|
||||
if (mousePos != lastMousePos)
|
||||
UpdatePosition(mousePos);
|
||||
|
||||
@ -181,34 +166,36 @@ namespace UnityExplorer.Inspectors
|
||||
mousePos.y -= 10;
|
||||
|
||||
// calculate and set our UI position
|
||||
var inversePos = inspectorUIBase.RootObject.transform.InverseTransformPoint(mousePos);
|
||||
Vector3 inversePos = inspectorUIBase.RootObject.transform.InverseTransformPoint(mousePos);
|
||||
UIRoot.transform.localPosition = new Vector3(inversePos.x, inversePos.y, 0);
|
||||
}
|
||||
|
||||
// UI Construction
|
||||
|
||||
protected internal override void DoSetDefaultPosAndAnchors()
|
||||
public override void SetDefaultSizeAndPosition()
|
||||
{
|
||||
base.SetDefaultSizeAndPosition();
|
||||
|
||||
Rect.anchorMin = Vector2.zero;
|
||||
Rect.anchorMax = Vector2.zero;
|
||||
Rect.pivot = new Vector2(0.5f, 1);
|
||||
Rect.sizeDelta = new Vector2(700, 150);
|
||||
}
|
||||
|
||||
public override void ConstructPanelContent()
|
||||
protected override void ConstructPanelContent()
|
||||
{
|
||||
// hide title bar
|
||||
this.TitleBar.SetActive(false);
|
||||
this.UIRoot.transform.SetParent(UIManager.UIRoot.transform, false);
|
||||
|
||||
var inspectContent = UIFactory.CreateVerticalGroup(this.uiContent, "InspectContent", true, true, true, true, 3, new Vector4(2, 2, 2, 2));
|
||||
GameObject inspectContent = UIFactory.CreateVerticalGroup(this.ContentRoot, "InspectContent", true, true, true, true, 3, new Vector4(2, 2, 2, 2));
|
||||
UIFactory.SetLayoutElement(inspectContent, flexibleWidth: 9999, flexibleHeight: 9999);
|
||||
|
||||
// Title text
|
||||
|
||||
var title = UIFactory.CreateLabel(inspectContent,
|
||||
Text title = UIFactory.CreateLabel(inspectContent,
|
||||
"InspectLabel",
|
||||
"<b>Mouse Inspector</b> (press <b>ESC</b> to cancel)",
|
||||
"<b>Mouse Inspector</b> (press <b>ESC</b> to cancel)",
|
||||
TextAnchor.MiddleCenter);
|
||||
UIFactory.SetLayoutElement(title.gameObject, flexibleWidth: 9999);
|
||||
|
||||
@ -225,11 +212,10 @@ namespace UnityExplorer.Inspectors
|
||||
|
||||
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);
|
||||
//// 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.
|
||||
//
|
||||
//UIRoot.transform.SetParent(inspectorUIBase.RootObject.transform);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityExplorer.Inspectors.MouseInspectors
|
||||
namespace UnityExplorer.Inspectors.MouseInspectors
|
||||
{
|
||||
public abstract class MouseInspectorBase
|
||||
{
|
||||
|
@ -1,29 +1,21 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.UI;
|
||||
using UnityExplorer.UI.Panels;
|
||||
using UniverseLib;
|
||||
using UniverseLib.Input;
|
||||
|
||||
namespace UnityExplorer.Inspectors.MouseInspectors
|
||||
{
|
||||
public class UiInspector : MouseInspectorBase
|
||||
{
|
||||
public static readonly List<GameObject> LastHitObjects = new List<GameObject>();
|
||||
public static readonly List<GameObject> LastHitObjects = new();
|
||||
|
||||
private static GraphicRaycaster[] graphicRaycasters;
|
||||
|
||||
private static readonly List<GameObject> currentHitObjects = new List<GameObject>();
|
||||
private static readonly List<GameObject> currentHitObjects = new();
|
||||
|
||||
private static readonly List<Graphic> wasDisabledGraphics = new List<Graphic>();
|
||||
private static readonly List<CanvasGroup> wasDisabledCanvasGroups = new List<CanvasGroup>();
|
||||
private static readonly List<GameObject> objectsAddedCastersTo = new List<GameObject>();
|
||||
private static readonly List<Graphic> wasDisabledGraphics = new();
|
||||
private static readonly List<CanvasGroup> wasDisabledCanvasGroups = new();
|
||||
private static readonly List<GameObject> objectsAddedCastersTo = new();
|
||||
|
||||
public override void OnBeginMouseInspect()
|
||||
{
|
||||
@ -46,7 +38,7 @@ namespace UnityExplorer.Inspectors.MouseInspectors
|
||||
IEnumerator SetPanelActiveCoro()
|
||||
{
|
||||
yield return null;
|
||||
var panel = UIManager.GetPanel<MouseInspectorResultsPanel>(UIManager.Panels.UIInspectorResults);
|
||||
MouseInspectorResultsPanel panel = UIManager.GetPanel<MouseInspectorResultsPanel>(UIManager.Panels.UIInspectorResults);
|
||||
panel.SetActive(true);
|
||||
panel.ShowResults();
|
||||
}
|
||||
@ -55,28 +47,28 @@ namespace UnityExplorer.Inspectors.MouseInspectors
|
||||
{
|
||||
currentHitObjects.Clear();
|
||||
|
||||
var ped = new PointerEventData(null)
|
||||
PointerEventData ped = new(null)
|
||||
{
|
||||
position = mousePos
|
||||
};
|
||||
|
||||
foreach (var gr in graphicRaycasters)
|
||||
foreach (GraphicRaycaster gr in graphicRaycasters)
|
||||
{
|
||||
if (!gr || !gr.canvas)
|
||||
continue;
|
||||
|
||||
var list = new List<RaycastResult>();
|
||||
|
||||
List<RaycastResult> list = new();
|
||||
RuntimeHelper.GraphicRaycast(gr, ped, list);
|
||||
if (list.Count > 0)
|
||||
{
|
||||
foreach (var hit in list)
|
||||
foreach (RaycastResult hit in list)
|
||||
{
|
||||
if (hit.gameObject)
|
||||
currentHitObjects.Add(hit.gameObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (currentHitObjects.Any())
|
||||
MouseInspector.Instance.objNameLabel.text = $"Click to view UI Objects under mouse: {currentHitObjects.Count}";
|
||||
else
|
||||
@ -85,9 +77,9 @@ namespace UnityExplorer.Inspectors.MouseInspectors
|
||||
|
||||
private static void SetupUIRaycast()
|
||||
{
|
||||
foreach (var obj in RuntimeHelper.FindObjectsOfTypeAll(typeof(Canvas)))
|
||||
foreach (UnityEngine.Object obj in RuntimeHelper.FindObjectsOfTypeAll(typeof(Canvas)))
|
||||
{
|
||||
var canvas = obj.TryCast<Canvas>();
|
||||
Canvas canvas = obj.TryCast<Canvas>();
|
||||
if (!canvas || !canvas.enabled || !canvas.gameObject.activeInHierarchy)
|
||||
continue;
|
||||
if (!canvas.GetComponent<GraphicRaycaster>())
|
||||
@ -99,7 +91,7 @@ namespace UnityExplorer.Inspectors.MouseInspectors
|
||||
}
|
||||
|
||||
// recache Graphic Raycasters each time we start
|
||||
var casters = RuntimeHelper.FindObjectsOfTypeAll(typeof(GraphicRaycaster));
|
||||
UnityEngine.Object[] casters = RuntimeHelper.FindObjectsOfTypeAll(typeof(GraphicRaycaster));
|
||||
graphicRaycasters = new GraphicRaycaster[casters.Length];
|
||||
for (int i = 0; i < casters.Length; i++)
|
||||
{
|
||||
@ -107,9 +99,9 @@ namespace UnityExplorer.Inspectors.MouseInspectors
|
||||
}
|
||||
|
||||
// enable raycastTarget on Graphics
|
||||
foreach (var obj in RuntimeHelper.FindObjectsOfTypeAll(typeof(Graphic)))
|
||||
foreach (UnityEngine.Object obj in RuntimeHelper.FindObjectsOfTypeAll(typeof(Graphic)))
|
||||
{
|
||||
var graphic = obj.TryCast<Graphic>();
|
||||
Graphic graphic = obj.TryCast<Graphic>();
|
||||
if (!graphic || !graphic.enabled || graphic.raycastTarget || !graphic.gameObject.activeInHierarchy)
|
||||
continue;
|
||||
graphic.raycastTarget = true;
|
||||
@ -118,9 +110,9 @@ namespace UnityExplorer.Inspectors.MouseInspectors
|
||||
}
|
||||
|
||||
// enable blocksRaycasts on CanvasGroups
|
||||
foreach (var obj in RuntimeHelper.FindObjectsOfTypeAll(typeof(CanvasGroup)))
|
||||
foreach (UnityEngine.Object obj in RuntimeHelper.FindObjectsOfTypeAll(typeof(CanvasGroup)))
|
||||
{
|
||||
var canvas = obj.TryCast<CanvasGroup>();
|
||||
CanvasGroup canvas = obj.TryCast<CanvasGroup>();
|
||||
if (!canvas || !canvas.gameObject.activeInHierarchy || canvas.blocksRaycasts)
|
||||
continue;
|
||||
canvas.blocksRaycasts = true;
|
||||
@ -131,16 +123,16 @@ namespace UnityExplorer.Inspectors.MouseInspectors
|
||||
|
||||
public override void OnEndInspect()
|
||||
{
|
||||
foreach (var obj in objectsAddedCastersTo)
|
||||
foreach (GameObject obj in objectsAddedCastersTo)
|
||||
{
|
||||
if (obj.GetComponent<GraphicRaycaster>() is GraphicRaycaster raycaster)
|
||||
GameObject.Destroy(raycaster);
|
||||
}
|
||||
|
||||
foreach (var graphic in wasDisabledGraphics)
|
||||
foreach (Graphic graphic in wasDisabledGraphics)
|
||||
graphic.raycastTarget = false;
|
||||
|
||||
foreach (var canvas in wasDisabledCanvasGroups)
|
||||
foreach (CanvasGroup canvas in wasDisabledCanvasGroups)
|
||||
canvas.blocksRaycasts = false;
|
||||
|
||||
objectsAddedCastersTo.Clear();
|
||||
|
@ -1,12 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UniverseLib;
|
||||
using UniverseLib.Utility;
|
||||
|
||||
namespace UnityExplorer.Inspectors.MouseInspectors
|
||||
namespace UnityExplorer.Inspectors.MouseInspectors
|
||||
{
|
||||
public class WorldInspector : MouseInspectorBase
|
||||
{
|
||||
@ -45,7 +37,7 @@ namespace UnityExplorer.Inspectors.MouseInspectors
|
||||
return;
|
||||
}
|
||||
|
||||
var ray = MainCamera.ScreenPointToRay(mousePos);
|
||||
Ray ray = MainCamera.ScreenPointToRay(mousePos);
|
||||
Physics.Raycast(ray, out RaycastHit hit, 1000f);
|
||||
|
||||
if (hit.transform)
|
||||
|
@ -1,21 +1,16 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Collections;
|
||||
using System.Diagnostics;
|
||||
using System.Reflection.Emit;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.CacheObject;
|
||||
using UnityExplorer.CacheObject.Views;
|
||||
using UnityExplorer.Config;
|
||||
using UnityExplorer.UI;
|
||||
using UnityExplorer.UI.Panels;
|
||||
using UnityExplorer.UI.Widgets;
|
||||
using UniverseLib;
|
||||
using UniverseLib.UI;
|
||||
using UniverseLib.UI.Models;
|
||||
using UniverseLib.UI.ObjectPool;
|
||||
using UniverseLib.UI.Widgets.ScrollView;
|
||||
using UniverseLib.Utility;
|
||||
|
||||
namespace UnityExplorer.Inspectors
|
||||
{
|
||||
@ -33,54 +28,53 @@ namespace UnityExplorer.Inspectors
|
||||
public class ReflectionInspector : InspectorBase, ICellPoolDataSource<CacheMemberCell>, ICacheObjectController
|
||||
{
|
||||
public CacheObjectBase ParentCacheObject { get; set; }
|
||||
public Type TargetType { get; private set; }
|
||||
public bool StaticOnly { get; internal set; }
|
||||
public bool CanWrite => true;
|
||||
|
||||
public bool AutoUpdateWanted => autoUpdateToggle.isOn;
|
||||
|
||||
private List<CacheMember> members = new();
|
||||
private readonly List<CacheMember> filteredMembers = new();
|
||||
List<CacheMember> members = new();
|
||||
readonly List<CacheMember> filteredMembers = new();
|
||||
|
||||
private BindingFlags scopeFlagsFilter;
|
||||
private string nameFilter;
|
||||
|
||||
private MemberFilter MemberFilter = MemberFilter.All;
|
||||
string nameFilter;
|
||||
BindingFlags scopeFlagsFilter;
|
||||
MemberFilter memberFilter = MemberFilter.All;
|
||||
|
||||
// Updating
|
||||
|
||||
private bool refreshWanted;
|
||||
private string lastNameFilter;
|
||||
private BindingFlags lastFlagsFilter;
|
||||
private MemberFilter lastMemberFilter = MemberFilter.All;
|
||||
private float timeOfLastAutoUpdate;
|
||||
bool refreshWanted;
|
||||
string lastNameFilter;
|
||||
BindingFlags lastFlagsFilter;
|
||||
MemberFilter lastMemberFilter = MemberFilter.All;
|
||||
float timeOfLastAutoUpdate;
|
||||
|
||||
// UI
|
||||
|
||||
internal GameObject mainContentHolder;
|
||||
private static int LeftGroupWidth { get; set; }
|
||||
private static int RightGroupWidth { get; set; }
|
||||
static int LeftGroupWidth { get; set; }
|
||||
static int RightGroupWidth { get; set; }
|
||||
|
||||
static readonly Color disabledButtonColor = new(0.24f, 0.24f, 0.24f);
|
||||
static readonly Color enabledButtonColor = new(0.2f, 0.27f, 0.2f);
|
||||
|
||||
public GameObject ContentRoot { get; private set; }
|
||||
public ScrollPool<CacheMemberCell> MemberScrollPool { get; private set; }
|
||||
public int ItemCount => filteredMembers.Count;
|
||||
public UnityObjectWidget UnityWidget { get; private set; }
|
||||
public string TabButtonText { get; set; }
|
||||
|
||||
public UnityObjectWidget UnityWidget;
|
||||
InputFieldRef hiddenNameText;
|
||||
Text nameText;
|
||||
Text assemblyText;
|
||||
Toggle autoUpdateToggle;
|
||||
|
||||
public InputFieldRef HiddenNameText;
|
||||
public Text NameText;
|
||||
public Text AssemblyText;
|
||||
private Toggle autoUpdateToggle;
|
||||
ButtonRef dnSpyButton;
|
||||
|
||||
internal string currentBaseTabText;
|
||||
ButtonRef makeGenericButton;
|
||||
GenericConstructorWidget genericConstructor;
|
||||
|
||||
private readonly Dictionary<BindingFlags, ButtonRef> scopeFilterButtons = new();
|
||||
private readonly List<Toggle> memberTypeToggles = new();
|
||||
private InputFieldRef filterInputField;
|
||||
|
||||
// const
|
||||
|
||||
private readonly Color disabledButtonColor = new(0.24f, 0.24f, 0.24f);
|
||||
private readonly Color enabledButtonColor = new(0.2f, 0.27f, 0.2f);
|
||||
InputFieldRef filterInputField;
|
||||
readonly List<Toggle> memberTypeToggles = new();
|
||||
readonly Dictionary<BindingFlags, ButtonRef> scopeFilterButtons = new();
|
||||
|
||||
// Setup
|
||||
|
||||
@ -107,7 +101,7 @@ namespace UnityExplorer.Inspectors
|
||||
|
||||
public override void OnReturnToPool()
|
||||
{
|
||||
foreach (var member in members)
|
||||
foreach (CacheMember member in members)
|
||||
{
|
||||
member.UnlinkFromView();
|
||||
member.ReleasePooledObjects();
|
||||
@ -125,6 +119,8 @@ namespace UnityExplorer.Inspectors
|
||||
this.UnityWidget = null;
|
||||
}
|
||||
|
||||
genericConstructor?.Cancel();
|
||||
|
||||
base.OnReturnToPool();
|
||||
}
|
||||
|
||||
@ -138,6 +134,8 @@ namespace UnityExplorer.Inspectors
|
||||
Target = null;
|
||||
TargetType = target as Type;
|
||||
prefix = "[S]";
|
||||
|
||||
makeGenericButton.GameObject.SetActive(TargetType.IsGenericTypeDefinition);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -146,17 +144,23 @@ namespace UnityExplorer.Inspectors
|
||||
}
|
||||
|
||||
// Setup main labels and tab text
|
||||
currentBaseTabText = $"{prefix} {SignatureHighlighter.Parse(TargetType, false)}";
|
||||
Tab.TabText.text = currentBaseTabText;
|
||||
NameText.text = SignatureHighlighter.Parse(TargetType, true);
|
||||
HiddenNameText.Text = SignatureHighlighter.RemoveHighlighting(NameText.text);
|
||||
TabButtonText = $"{prefix} {SignatureHighlighter.Parse(TargetType, false)}";
|
||||
Tab.TabText.text = TabButtonText;
|
||||
nameText.text = SignatureHighlighter.Parse(TargetType, true);
|
||||
hiddenNameText.Text = SignatureHighlighter.RemoveHighlighting(nameText.text);
|
||||
|
||||
string asmText;
|
||||
if (TargetType.Assembly is AssemblyBuilder || string.IsNullOrEmpty(TargetType.Assembly.Location))
|
||||
{
|
||||
asmText = $"{TargetType.Assembly.GetName().Name} <color=grey><i>(in memory)</i></color>";
|
||||
dnSpyButton.GameObject.SetActive(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
asmText = Path.GetFileName(TargetType.Assembly.Location);
|
||||
AssemblyText.text = $"<color=grey>Assembly:</color> {asmText}";
|
||||
dnSpyButton.GameObject.SetActive(true);
|
||||
}
|
||||
assemblyText.text = $"<color=grey>Assembly:</color> {asmText}";
|
||||
|
||||
// Unity object helper widget
|
||||
|
||||
@ -175,7 +179,7 @@ namespace UnityExplorer.Inspectors
|
||||
scopeFilterButtons[BindingFlags.Default].Component.gameObject.SetActive(!StaticOnly);
|
||||
scopeFilterButtons[BindingFlags.Instance].Component.gameObject.SetActive(!StaticOnly);
|
||||
|
||||
foreach (var toggle in memberTypeToggles)
|
||||
foreach (Toggle toggle in memberTypeToggles)
|
||||
toggle.isOn = true;
|
||||
|
||||
refreshWanted = true;
|
||||
@ -195,11 +199,11 @@ namespace UnityExplorer.Inspectors
|
||||
}
|
||||
|
||||
// check filter changes or force-refresh
|
||||
if (refreshWanted || nameFilter != lastNameFilter || scopeFlagsFilter != lastFlagsFilter || lastMemberFilter != MemberFilter)
|
||||
if (refreshWanted || nameFilter != lastNameFilter || scopeFlagsFilter != lastFlagsFilter || lastMemberFilter != memberFilter)
|
||||
{
|
||||
lastNameFilter = nameFilter;
|
||||
lastFlagsFilter = scopeFlagsFilter;
|
||||
lastMemberFilter = MemberFilter;
|
||||
lastMemberFilter = memberFilter;
|
||||
|
||||
FilterMembers();
|
||||
MemberScrollPool.Refresh(true, true);
|
||||
@ -219,24 +223,15 @@ namespace UnityExplorer.Inspectors
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateClicked()
|
||||
{
|
||||
UpdateDisplayedMembers();
|
||||
}
|
||||
|
||||
// Filtering
|
||||
|
||||
public void SetFilter(string name) => SetFilter(name, scopeFlagsFilter);
|
||||
|
||||
public void SetFilter(BindingFlags flags) => SetFilter(nameFilter, flags);
|
||||
|
||||
public void SetFilter(string name, BindingFlags flags)
|
||||
{
|
||||
this.nameFilter = name;
|
||||
|
||||
if (flags != scopeFlagsFilter)
|
||||
{
|
||||
var btn = scopeFilterButtons[scopeFlagsFilter].Component;
|
||||
Button btn = scopeFilterButtons[scopeFlagsFilter].Component;
|
||||
RuntimeHelper.SetColorBlock(btn, disabledButtonColor, disabledButtonColor * 1.3f);
|
||||
|
||||
this.scopeFlagsFilter = flags;
|
||||
@ -245,21 +240,13 @@ namespace UnityExplorer.Inspectors
|
||||
}
|
||||
}
|
||||
|
||||
private void OnMemberTypeToggled(MemberFilter flag, bool val)
|
||||
{
|
||||
if (!val)
|
||||
MemberFilter &= ~flag;
|
||||
else
|
||||
MemberFilter |= flag;
|
||||
}
|
||||
|
||||
private void FilterMembers()
|
||||
void FilterMembers()
|
||||
{
|
||||
filteredMembers.Clear();
|
||||
|
||||
for (int i = 0; i < members.Count; i++)
|
||||
{
|
||||
var member = members[i];
|
||||
CacheMember member = members[i];
|
||||
|
||||
if (scopeFlagsFilter != BindingFlags.Default)
|
||||
{
|
||||
@ -268,10 +255,10 @@ namespace UnityExplorer.Inspectors
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((member is CacheMethod && !MemberFilter.HasFlag(MemberFilter.Method))
|
||||
|| (member is CacheField && !MemberFilter.HasFlag(MemberFilter.Field))
|
||||
|| (member is CacheProperty && !MemberFilter.HasFlag(MemberFilter.Property))
|
||||
|| (member is CacheConstructor && !MemberFilter.HasFlag(MemberFilter.Constructor)))
|
||||
if ((member is CacheMethod && !memberFilter.HasFlag(MemberFilter.Method))
|
||||
|| (member is CacheField && !memberFilter.HasFlag(MemberFilter.Field))
|
||||
|| (member is CacheProperty && !memberFilter.HasFlag(MemberFilter.Property))
|
||||
|| (member is CacheConstructor && !memberFilter.HasFlag(MemberFilter.Constructor)))
|
||||
continue;
|
||||
|
||||
if (!string.IsNullOrEmpty(nameFilter) && !member.NameForFiltering.ContainsIgnoreCase(nameFilter))
|
||||
@ -281,14 +268,14 @@ namespace UnityExplorer.Inspectors
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateDisplayedMembers()
|
||||
void UpdateDisplayedMembers()
|
||||
{
|
||||
bool shouldRefresh = false;
|
||||
foreach (var cell in MemberScrollPool.CellPool)
|
||||
foreach (CacheMemberCell cell in MemberScrollPool.CellPool)
|
||||
{
|
||||
if (!cell.Enabled || cell.Occupant == null)
|
||||
continue;
|
||||
var member = cell.MemberOccupant;
|
||||
CacheMember member = cell.MemberOccupant;
|
||||
if (member.ShouldAutoEvaluate)
|
||||
{
|
||||
shouldRefresh = true;
|
||||
@ -316,17 +303,17 @@ namespace UnityExplorer.Inspectors
|
||||
{
|
||||
CalculateLayouts();
|
||||
|
||||
foreach (var cell in MemberScrollPool.CellPool)
|
||||
foreach (CacheMemberCell cell in MemberScrollPool.CellPool)
|
||||
SetCellLayout(cell);
|
||||
}
|
||||
|
||||
private void CalculateLayouts()
|
||||
void CalculateLayouts()
|
||||
{
|
||||
LeftGroupWidth = (int)Math.Max(200, (0.4f * InspectorManager.PanelWidth) - 5);
|
||||
RightGroupWidth = (int)Math.Max(200, InspectorManager.PanelWidth - LeftGroupWidth - 65);
|
||||
}
|
||||
|
||||
private void SetCellLayout(CacheObjectCell cell)
|
||||
void SetCellLayout(CacheObjectCell cell)
|
||||
{
|
||||
cell.NameLayout.minWidth = LeftGroupWidth;
|
||||
cell.RightGroupLayout.minWidth = RightGroupWidth;
|
||||
@ -335,11 +322,85 @@ namespace UnityExplorer.Inspectors
|
||||
cell.Occupant.IValue.SetLayout();
|
||||
}
|
||||
|
||||
private void OnCopyClicked()
|
||||
// UI listeners
|
||||
|
||||
void OnUpdateClicked()
|
||||
{
|
||||
UpdateDisplayedMembers();
|
||||
}
|
||||
|
||||
public void OnSetNameFilter(string name)
|
||||
{
|
||||
SetFilter(name, scopeFlagsFilter);
|
||||
}
|
||||
|
||||
public void OnSetFlags(BindingFlags flags)
|
||||
{
|
||||
SetFilter(nameFilter, flags);
|
||||
}
|
||||
|
||||
void OnMemberTypeToggled(MemberFilter flag, bool val)
|
||||
{
|
||||
if (!val)
|
||||
memberFilter &= ~flag;
|
||||
else
|
||||
memberFilter |= flag;
|
||||
}
|
||||
|
||||
void OnCopyClicked()
|
||||
{
|
||||
ClipboardPanel.Copy(this.Target ?? this.TargetType);
|
||||
}
|
||||
|
||||
void OnDnSpyButtonClicked()
|
||||
{
|
||||
string path = ConfigManager.DnSpy_Path.Value;
|
||||
if (File.Exists(path) && path.EndsWith("dnspy.exe", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
Type type = TargetType;
|
||||
// if constructed generic type, use the generic type definition
|
||||
if (type.IsGenericType && !type.IsGenericTypeDefinition)
|
||||
type = type.GetGenericTypeDefinition();
|
||||
|
||||
string args = $"\"{type.Assembly.Location}\" --select T:{type.FullName}";
|
||||
Process.Start(path, args);
|
||||
}
|
||||
else
|
||||
{
|
||||
Notification.ShowMessage($"Please set a valid dnSpy path in UnityExplorer Settings.");
|
||||
}
|
||||
}
|
||||
|
||||
void OnMakeGenericClicked()
|
||||
{
|
||||
ContentRoot.SetActive(false);
|
||||
|
||||
if (genericConstructor == null)
|
||||
{
|
||||
genericConstructor = new();
|
||||
genericConstructor.ConstructUI(UIRoot);
|
||||
}
|
||||
|
||||
genericConstructor.UIRoot.SetActive(true);
|
||||
genericConstructor.Show(OnGenericSubmit, OnGenericCancel, TargetType);
|
||||
}
|
||||
|
||||
void OnGenericSubmit(Type[] args)
|
||||
{
|
||||
ContentRoot.SetActive(true);
|
||||
genericConstructor.UIRoot.SetActive(false);
|
||||
|
||||
Type newType = TargetType.MakeGenericType(args);
|
||||
InspectorManager.Inspect(newType);
|
||||
//InspectorManager.ReleaseInspector(this);
|
||||
}
|
||||
|
||||
void OnGenericCancel()
|
||||
{
|
||||
ContentRoot.SetActive(true);
|
||||
genericConstructor.UIRoot.SetActive(false);
|
||||
}
|
||||
|
||||
// UI Construction
|
||||
|
||||
public override GameObject CreateContent(GameObject parent)
|
||||
@ -349,51 +410,68 @@ namespace UnityExplorer.Inspectors
|
||||
|
||||
// Class name, assembly
|
||||
|
||||
var topRow = UIFactory.CreateHorizontalGroup(UIRoot, "TopRow", false, false, true, true, 4, default, new(1, 1, 1, 0), TextAnchor.MiddleLeft);
|
||||
GameObject topRow = UIFactory.CreateHorizontalGroup(UIRoot, "TopRow", false, false, true, true, 4, default,
|
||||
new(0.1f, 0.1f, 0.1f), TextAnchor.MiddleLeft);
|
||||
UIFactory.SetLayoutElement(topRow, minHeight: 25, flexibleWidth: 9999);
|
||||
|
||||
var titleHolder = UIFactory.CreateUIObject("TitleHolder", topRow);
|
||||
GameObject titleHolder = UIFactory.CreateUIObject("TitleHolder", topRow);
|
||||
UIFactory.SetLayoutElement(titleHolder, minHeight: 35, flexibleHeight: 0, flexibleWidth: 9999);
|
||||
|
||||
NameText = UIFactory.CreateLabel(titleHolder, "VisibleTitle", "NotSet", TextAnchor.MiddleLeft);
|
||||
var namerect = NameText.GetComponent<RectTransform>();
|
||||
nameText = UIFactory.CreateLabel(titleHolder, "VisibleTitle", "NotSet", TextAnchor.MiddleLeft);
|
||||
RectTransform namerect = nameText.GetComponent<RectTransform>();
|
||||
namerect.anchorMin = new Vector2(0, 0);
|
||||
namerect.anchorMax = new Vector2(1, 1);
|
||||
NameText.fontSize = 17;
|
||||
UIFactory.SetLayoutElement(NameText.gameObject, minHeight: 35, flexibleHeight: 0, minWidth: 300, flexibleWidth: 9999);
|
||||
nameText.fontSize = 17;
|
||||
UIFactory.SetLayoutElement(nameText.gameObject, minHeight: 35, flexibleHeight: 0, minWidth: 300, flexibleWidth: 9999);
|
||||
|
||||
HiddenNameText = UIFactory.CreateInputField(titleHolder, "Title", "not set");
|
||||
var hiddenrect = HiddenNameText.Component.gameObject.GetComponent<RectTransform>();
|
||||
hiddenNameText = UIFactory.CreateInputField(titleHolder, "Title", "not set");
|
||||
RectTransform hiddenrect = hiddenNameText.Component.gameObject.GetComponent<RectTransform>();
|
||||
hiddenrect.anchorMin = new Vector2(0, 0);
|
||||
hiddenrect.anchorMax = new Vector2(1, 1);
|
||||
HiddenNameText.Component.readOnly = true;
|
||||
HiddenNameText.Component.lineType = InputField.LineType.MultiLineNewline;
|
||||
HiddenNameText.Component.gameObject.GetComponent<Image>().color = Color.clear;
|
||||
HiddenNameText.Component.textComponent.horizontalOverflow = HorizontalWrapMode.Wrap;
|
||||
HiddenNameText.Component.textComponent.fontSize = 17;
|
||||
HiddenNameText.Component.textComponent.color = Color.clear;
|
||||
UIFactory.SetLayoutElement(HiddenNameText.Component.gameObject, minHeight: 35, flexibleHeight: 0, flexibleWidth: 9999);
|
||||
hiddenNameText.Component.readOnly = true;
|
||||
hiddenNameText.Component.lineType = InputField.LineType.MultiLineNewline;
|
||||
hiddenNameText.Component.gameObject.GetComponent<Image>().color = Color.clear;
|
||||
hiddenNameText.Component.textComponent.horizontalOverflow = HorizontalWrapMode.Wrap;
|
||||
hiddenNameText.Component.textComponent.fontSize = 17;
|
||||
hiddenNameText.Component.textComponent.color = Color.clear;
|
||||
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));
|
||||
makeGenericButton = UIFactory.CreateButton(topRow, "MakeGenericButton", "Construct Generic", new Color(0.2f, 0.3f, 0.2f));
|
||||
UIFactory.SetLayoutElement(makeGenericButton.GameObject, minWidth: 140, minHeight: 25);
|
||||
makeGenericButton.OnClick += OnMakeGenericClicked;
|
||||
makeGenericButton.GameObject.SetActive(false);
|
||||
|
||||
ButtonRef 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);
|
||||
UIFactory.SetLayoutElement(AssemblyText.gameObject, minHeight: 25, flexibleWidth: 9999);
|
||||
// Assembly row
|
||||
|
||||
mainContentHolder = UIFactory.CreateVerticalGroup(UIRoot, "MemberHolder", false, false, true, true, 5, new Vector4(2, 2, 2, 2),
|
||||
GameObject asmRow = UIFactory.CreateHorizontalGroup(UIRoot, "AssemblyRow", false, false, true, true, 5, default, new(1, 1, 1, 0));
|
||||
UIFactory.SetLayoutElement(asmRow, flexibleWidth: 9999, minHeight: 25);
|
||||
|
||||
assemblyText = UIFactory.CreateLabel(asmRow, "AssemblyLabel", "not set", TextAnchor.MiddleLeft);
|
||||
UIFactory.SetLayoutElement(assemblyText.gameObject, minHeight: 25, flexibleWidth: 9999);
|
||||
|
||||
dnSpyButton = UIFactory.CreateButton(asmRow, "DnSpyButton", "View in dnSpy");
|
||||
UIFactory.SetLayoutElement(dnSpyButton.GameObject, minWidth: 120, minHeight: 25);
|
||||
dnSpyButton.OnClick += OnDnSpyButtonClicked;
|
||||
|
||||
// Content
|
||||
|
||||
ContentRoot = UIFactory.CreateVerticalGroup(UIRoot, "ContentRoot", false, false, true, true, 5, new Vector4(2, 2, 2, 2),
|
||||
new Color(0.12f, 0.12f, 0.12f));
|
||||
UIFactory.SetLayoutElement(mainContentHolder, flexibleWidth: 9999, flexibleHeight: 9999);
|
||||
UIFactory.SetLayoutElement(ContentRoot, flexibleWidth: 9999, flexibleHeight: 9999);
|
||||
|
||||
ConstructFirstRow(mainContentHolder);
|
||||
ConstructFirstRow(ContentRoot);
|
||||
|
||||
ConstructSecondRow(mainContentHolder);
|
||||
ConstructSecondRow(ContentRoot);
|
||||
|
||||
// Member scroll pool
|
||||
|
||||
var memberBorder = UIFactory.CreateVerticalGroup(mainContentHolder, "ScrollPoolHolder", false, false, true, true, padding: new Vector4(2, 2, 2, 2),
|
||||
bgColor: new Color(0.05f, 0.05f, 0.05f));
|
||||
GameObject memberBorder = UIFactory.CreateVerticalGroup(ContentRoot, "ScrollPoolHolder", false, false, true, true,
|
||||
padding: new Vector4(2, 2, 2, 2), bgColor: new Color(0.05f, 0.05f, 0.05f));
|
||||
UIFactory.SetLayoutElement(memberBorder, flexibleWidth: 9999, flexibleHeight: 9999);
|
||||
|
||||
MemberScrollPool = UIFactory.CreateScrollPool<CacheMemberCell>(memberBorder, "MemberList", out GameObject scrollObj,
|
||||
@ -411,29 +489,29 @@ namespace UnityExplorer.Inspectors
|
||||
|
||||
// First row
|
||||
|
||||
private void ConstructFirstRow(GameObject parent)
|
||||
void ConstructFirstRow(GameObject parent)
|
||||
{
|
||||
var rowObj = UIFactory.CreateUIObject("FirstRow", parent);
|
||||
GameObject rowObj = UIFactory.CreateUIObject("FirstRow", parent);
|
||||
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(rowObj, true, true, true, true, 5, 2, 2, 2, 2);
|
||||
UIFactory.SetLayoutElement(rowObj, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999);
|
||||
|
||||
var nameLabel = UIFactory.CreateLabel(rowObj, "NameFilterLabel", "Filter names:", TextAnchor.MiddleLeft, Color.grey);
|
||||
Text nameLabel = UIFactory.CreateLabel(rowObj, "NameFilterLabel", "Filter names:", TextAnchor.MiddleLeft, Color.grey);
|
||||
UIFactory.SetLayoutElement(nameLabel.gameObject, minHeight: 25, minWidth: 90, flexibleWidth: 0);
|
||||
|
||||
filterInputField = UIFactory.CreateInputField(rowObj, "NameFilterInput", "...");
|
||||
UIFactory.SetLayoutElement(filterInputField.UIRoot, minHeight: 25, flexibleWidth: 300);
|
||||
filterInputField.OnValueChanged += (string val) => { SetFilter(val); };
|
||||
filterInputField.OnValueChanged += (string val) => { OnSetNameFilter(val); };
|
||||
|
||||
var spacer = UIFactory.CreateUIObject("Spacer", rowObj);
|
||||
GameObject spacer = UIFactory.CreateUIObject("Spacer", rowObj);
|
||||
UIFactory.SetLayoutElement(spacer, minWidth: 25);
|
||||
|
||||
// Update button and toggle
|
||||
|
||||
var updateButton = UIFactory.CreateButton(rowObj, "UpdateButton", "Update displayed values", new Color(0.22f, 0.28f, 0.22f));
|
||||
ButtonRef updateButton = UIFactory.CreateButton(rowObj, "UpdateButton", "Update displayed values", new Color(0.22f, 0.28f, 0.22f));
|
||||
UIFactory.SetLayoutElement(updateButton.Component.gameObject, minHeight: 25, minWidth: 175, flexibleWidth: 0);
|
||||
updateButton.OnClick += UpdateClicked;
|
||||
updateButton.OnClick += OnUpdateClicked;
|
||||
|
||||
var toggleObj = UIFactory.CreateToggle(rowObj, "AutoUpdateToggle", out autoUpdateToggle, out Text toggleText);
|
||||
GameObject toggleObj = UIFactory.CreateToggle(rowObj, "AutoUpdateToggle", out autoUpdateToggle, out Text toggleText);
|
||||
UIFactory.SetLayoutElement(toggleObj, minWidth: 125, minHeight: 25);
|
||||
autoUpdateToggle.isOn = false;
|
||||
toggleText.text = "Auto-update";
|
||||
@ -441,21 +519,21 @@ namespace UnityExplorer.Inspectors
|
||||
|
||||
// Second row
|
||||
|
||||
private void ConstructSecondRow(GameObject parent)
|
||||
void ConstructSecondRow(GameObject parent)
|
||||
{
|
||||
var rowObj = UIFactory.CreateUIObject("SecondRow", parent);
|
||||
GameObject rowObj = UIFactory.CreateUIObject("SecondRow", parent);
|
||||
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(rowObj, false, false, true, true, 5, 2, 2, 2, 2);
|
||||
UIFactory.SetLayoutElement(rowObj, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999);
|
||||
|
||||
// Scope buttons
|
||||
|
||||
var scopeLabel = UIFactory.CreateLabel(rowObj, "ScopeLabel", "Scope:", TextAnchor.MiddleLeft, Color.grey);
|
||||
Text scopeLabel = UIFactory.CreateLabel(rowObj, "ScopeLabel", "Scope:", TextAnchor.MiddleLeft, Color.grey);
|
||||
UIFactory.SetLayoutElement(scopeLabel.gameObject, minHeight: 25, minWidth: 60, flexibleWidth: 0);
|
||||
AddScopeFilterButton(rowObj, BindingFlags.Default, true);
|
||||
AddScopeFilterButton(rowObj, BindingFlags.Instance);
|
||||
AddScopeFilterButton(rowObj, BindingFlags.Static);
|
||||
|
||||
var spacer = UIFactory.CreateUIObject("Spacer", rowObj);
|
||||
GameObject spacer = UIFactory.CreateUIObject("Spacer", rowObj);
|
||||
UIFactory.SetLayoutElement(spacer, minWidth: 15);
|
||||
|
||||
// Member type toggles
|
||||
@ -466,21 +544,21 @@ namespace UnityExplorer.Inspectors
|
||||
AddMemberTypeToggle(rowObj, MemberTypes.Constructor, 110);
|
||||
}
|
||||
|
||||
private void AddScopeFilterButton(GameObject parent, BindingFlags flags, bool setAsActive = false)
|
||||
void AddScopeFilterButton(GameObject parent, BindingFlags flags, bool setAsActive = false)
|
||||
{
|
||||
string lbl = flags == BindingFlags.Default ? "All" : flags.ToString();
|
||||
var color = setAsActive ? enabledButtonColor : disabledButtonColor;
|
||||
Color color = setAsActive ? enabledButtonColor : disabledButtonColor;
|
||||
|
||||
var button = UIFactory.CreateButton(parent, "Filter_" + flags, lbl, color);
|
||||
ButtonRef button = UIFactory.CreateButton(parent, "Filter_" + flags, lbl, color);
|
||||
UIFactory.SetLayoutElement(button.Component.gameObject, minHeight: 25, flexibleHeight: 0, minWidth: 70, flexibleWidth: 0);
|
||||
scopeFilterButtons.Add(flags, button);
|
||||
|
||||
button.OnClick += () => { SetFilter(flags); };
|
||||
button.OnClick += () => { OnSetFlags(flags); };
|
||||
}
|
||||
|
||||
private void AddMemberTypeToggle(GameObject parent, MemberTypes type, int width)
|
||||
void AddMemberTypeToggle(GameObject parent, MemberTypes type, int width)
|
||||
{
|
||||
var toggleObj = UIFactory.CreateToggle(parent, "Toggle_" + type, out Toggle toggle, out Text toggleText);
|
||||
GameObject toggleObj = UIFactory.CreateToggle(parent, "Toggle_" + type, out Toggle toggle, out Text toggleText);
|
||||
UIFactory.SetLayoutElement(toggleObj, minHeight: 25, minWidth: width);
|
||||
string color = type switch
|
||||
{
|
||||
|
@ -1,9 +1,5 @@
|
||||
#if BIE
|
||||
using BepInEx.Configuration;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityExplorer.Config;
|
||||
|
||||
namespace UnityExplorer.Loader.BIE
|
||||
@ -21,7 +17,7 @@ namespace UnityExplorer.Loader.BIE
|
||||
|
||||
public override void RegisterConfigElement<T>(ConfigElement<T> config)
|
||||
{
|
||||
var entry = Config.Bind(CTG_NAME, config.Name, config.Value, config.Description);
|
||||
ConfigEntry<T> entry = Config.Bind(CTG_NAME, config.Name, config.Value, config.Description);
|
||||
|
||||
entry.SettingChanged += (object o, EventArgs e) =>
|
||||
{
|
||||
@ -47,13 +43,13 @@ namespace UnityExplorer.Loader.BIE
|
||||
|
||||
public override void LoadConfig()
|
||||
{
|
||||
foreach (var entry in ConfigManager.ConfigElements)
|
||||
foreach (KeyValuePair<string, IConfigElement> entry in ConfigManager.ConfigElements)
|
||||
{
|
||||
var key = entry.Key;
|
||||
var def = new ConfigDefinition(CTG_NAME, key);
|
||||
string key = entry.Key;
|
||||
ConfigDefinition def = new(CTG_NAME, key);
|
||||
if (Config.ContainsKey(def) && Config[def] is ConfigEntryBase configEntry)
|
||||
{
|
||||
var config = entry.Value;
|
||||
IConfigElement config = entry.Value;
|
||||
config.BoxedValue = configEntry.BoxedValue;
|
||||
}
|
||||
}
|
||||
@ -61,7 +57,7 @@ namespace UnityExplorer.Loader.BIE
|
||||
|
||||
public override void SaveConfig()
|
||||
{
|
||||
// not required
|
||||
Config.Save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,19 +2,10 @@
|
||||
using BepInEx;
|
||||
using BepInEx.Logging;
|
||||
using HarmonyLib;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityExplorer.Config;
|
||||
using UniverseLib.Input;
|
||||
using UnityExplorer.Loader.BIE;
|
||||
#if CPP
|
||||
using BepInEx.IL2CPP;
|
||||
using UnhollowerRuntimeLib;
|
||||
#endif
|
||||
|
||||
namespace UnityExplorer
|
||||
@ -37,15 +28,21 @@ namespace UnityExplorer
|
||||
#else
|
||||
=> Log;
|
||||
#endif
|
||||
|
||||
public string UnhollowedModulesFolder => Path.Combine(Paths.BepInExRootPath, "unhollowed");
|
||||
const string IL2CPP_LIBS_FOLDER =
|
||||
#if UNHOLLOWER
|
||||
"unhollowed"
|
||||
#else
|
||||
"interop"
|
||||
#endif
|
||||
;
|
||||
public string UnhollowedModulesFolder => Path.Combine(Paths.BepInExRootPath, IL2CPP_LIBS_FOLDER);
|
||||
|
||||
public ConfigHandler ConfigHandler => _configHandler;
|
||||
private BepInExConfigHandler _configHandler;
|
||||
|
||||
public Harmony HarmonyInstance => s_harmony;
|
||||
private static readonly Harmony s_harmony = new(ExplorerCore.GUID);
|
||||
|
||||
|
||||
public string ExplorerFolderName => ExplorerCore.DEFAULT_EXPLORER_FOLDER_NAME;
|
||||
public string ExplorerFolderDestination => Paths.PluginPath;
|
||||
|
||||
|
@ -1,8 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityExplorer.Config;
|
||||
using UnityExplorer.Config;
|
||||
|
||||
namespace UnityExplorer
|
||||
{
|
||||
|
@ -6,27 +6,53 @@ using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityExplorer.Config;
|
||||
using UnityExplorer.UI;
|
||||
using UniverseLib;
|
||||
|
||||
namespace UnityExplorer.Loader.Standalone
|
||||
{
|
||||
public class ExplorerEditorBehaviour : MonoBehaviour
|
||||
{
|
||||
internal static ExplorerEditorBehaviour Instance { get; private set; }
|
||||
|
||||
public bool Hide_On_Startup = true;
|
||||
public KeyCode Master_Toggle_Key = KeyCode.F7;
|
||||
public UIManager.VerticalAnchor Main_Navbar_Anchor = UIManager.VerticalAnchor.Top;
|
||||
public bool Log_Unity_Debug = false;
|
||||
public float Startup_Delay_Time = 1f;
|
||||
public KeyCode World_MouseInspect_Keybind;
|
||||
public KeyCode UI_MouseInspect_Keybind;
|
||||
public bool Force_Unlock_Mouse = true;
|
||||
public KeyCode Force_Unlock_Toggle;
|
||||
public bool Disable_EventSystem_Override;
|
||||
|
||||
internal void Awake()
|
||||
{
|
||||
Instance = this;
|
||||
|
||||
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);
|
||||
Destroy(this.gameObject);
|
||||
}
|
||||
|
||||
internal void LoadConfigs()
|
||||
{
|
||||
ConfigManager.Hide_On_Startup.Value = this.Hide_On_Startup;
|
||||
ConfigManager.Master_Toggle.Value = this.Master_Toggle_Key;
|
||||
ConfigManager.Main_Navbar_Anchor.Value = this.Main_Navbar_Anchor;
|
||||
ConfigManager.Log_Unity_Debug.Value = this.Log_Unity_Debug;
|
||||
ConfigManager.Startup_Delay_Time.Value = this.Startup_Delay_Time;
|
||||
ConfigManager.World_MouseInspect_Keybind.Value = this.World_MouseInspect_Keybind;
|
||||
ConfigManager.UI_MouseInspect_Keybind.Value = this.UI_MouseInspect_Keybind;
|
||||
ConfigManager.Force_Unlock_Mouse.Value = this.Force_Unlock_Mouse;
|
||||
ConfigManager.Force_Unlock_Toggle.Value = this.Force_Unlock_Toggle;
|
||||
ConfigManager.Disable_EventSystem_Override.Value = this.Disable_EventSystem_Override;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ namespace UnityExplorer.Loader.Standalone
|
||||
protected override void CheckExplorerFolder()
|
||||
{
|
||||
if (explorerFolderDest == null)
|
||||
explorerFolderDest = Application.dataPath;
|
||||
explorerFolderDest = Path.GetDirectoryName(Application.dataPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,17 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UniverseLib.UI.Models;
|
||||
using UnityExplorer.UI.Panels;
|
||||
using UnityExplorer.UI.Panels;
|
||||
using UnityExplorer.UI.Widgets.AutoComplete;
|
||||
using UniverseLib.UI;
|
||||
using UniverseLib;
|
||||
using UniverseLib.UI.Models;
|
||||
using UniverseLib.UI.Widgets.ButtonList;
|
||||
using UniverseLib.UI.Widgets.ScrollView;
|
||||
using UniverseLib.Utility;
|
||||
|
||||
namespace UnityExplorer.ObjectExplorer
|
||||
{
|
||||
@ -35,12 +27,15 @@ namespace UnityExplorer.ObjectExplorer
|
||||
private ScrollPool<ButtonCell> resultsScrollPool;
|
||||
private List<object> currentResults = new();
|
||||
|
||||
//public TypeCompleter typeAutocompleter;
|
||||
public TypeCompleter unityObjectTypeCompleter;
|
||||
public TypeCompleter allTypesCompleter;
|
||||
|
||||
public override GameObject UIRoot => uiRoot;
|
||||
private GameObject uiRoot;
|
||||
private GameObject sceneFilterRow;
|
||||
private GameObject childFilterRow;
|
||||
private GameObject classInputRow;
|
||||
public TypeCompleter typeAutocompleter;
|
||||
private GameObject nameInputRow;
|
||||
private InputFieldRef nameInputField;
|
||||
private Text resultsLabel;
|
||||
@ -73,7 +68,7 @@ namespace UnityExplorer.ObjectExplorer
|
||||
//var type = ReflectionUtility.GetTypeByName(desiredTypeInput);
|
||||
if (ReflectionUtility.GetTypeByName(desiredTypeInput) is Type cachedType)
|
||||
{
|
||||
var type = cachedType;
|
||||
Type type = cachedType;
|
||||
lastTypeCanHaveGameObject = typeof(Component).IsAssignableFrom(type) || type == typeof(GameObject);
|
||||
sceneFilterRow.SetActive(lastTypeCanHaveGameObject);
|
||||
childFilterRow.SetActive(lastTypeCanHaveGameObject);
|
||||
@ -99,14 +94,18 @@ namespace UnityExplorer.ObjectExplorer
|
||||
|
||||
nameInputRow.SetActive(context == SearchContext.UnityObject);
|
||||
|
||||
if (context == SearchContext.Class)
|
||||
typeAutocompleter.AllTypes = true;
|
||||
else
|
||||
switch (context)
|
||||
{
|
||||
typeAutocompleter.BaseType = context == SearchContext.UnityObject ? typeof(UnityEngine.Object) : typeof(object);
|
||||
typeAutocompleter.AllTypes = false;
|
||||
case SearchContext.UnityObject:
|
||||
unityObjectTypeCompleter.Enabled = true;
|
||||
allTypesCompleter.Enabled = false;
|
||||
break;
|
||||
case SearchContext.Singleton:
|
||||
case SearchContext.Class:
|
||||
allTypesCompleter.Enabled = true;
|
||||
unityObjectTypeCompleter.Enabled = false;
|
||||
break;
|
||||
}
|
||||
typeAutocompleter.CacheTypes();
|
||||
}
|
||||
|
||||
private void OnSceneFilterDropChanged(int value) => sceneFilter = (SceneFilter)value;
|
||||
@ -135,7 +134,7 @@ namespace UnityExplorer.ObjectExplorer
|
||||
string text;
|
||||
if (context == SearchContext.Class)
|
||||
{
|
||||
var type = currentResults[index] as Type;
|
||||
Type type = currentResults[index] as Type;
|
||||
text = $"{SignatureHighlighter.Parse(type, true)} <color=grey><i>({type.Assembly.GetName().Name})</i></color>";
|
||||
}
|
||||
else
|
||||
@ -164,14 +163,14 @@ namespace UnityExplorer.ObjectExplorer
|
||||
|
||||
// Search context row
|
||||
|
||||
var contextGroup = UIFactory.CreateHorizontalGroup(uiRoot, "SearchContextRow", false, true, true, true, 2, new Vector4(2, 2, 2, 2));
|
||||
GameObject contextGroup = UIFactory.CreateHorizontalGroup(uiRoot, "SearchContextRow", false, true, true, true, 2, new Vector4(2, 2, 2, 2));
|
||||
UIFactory.SetLayoutElement(contextGroup, minHeight: 25, flexibleHeight: 0);
|
||||
|
||||
var contextLbl = UIFactory.CreateLabel(contextGroup, "SearchContextLabel", "Searching for:", TextAnchor.MiddleLeft);
|
||||
Text contextLbl = UIFactory.CreateLabel(contextGroup, "SearchContextLabel", "Searching for:", TextAnchor.MiddleLeft);
|
||||
UIFactory.SetLayoutElement(contextLbl.gameObject, minWidth: 110, flexibleWidth: 0);
|
||||
|
||||
var contextDropObj = UIFactory.CreateDropdown(contextGroup, "ContextDropdown", out Dropdown contextDrop, null, 14, OnContextDropdownChanged);
|
||||
foreach (var name in Enum.GetNames(typeof(SearchContext)))
|
||||
GameObject contextDropObj = UIFactory.CreateDropdown(contextGroup, "ContextDropdown", out Dropdown contextDrop, null, 14, OnContextDropdownChanged);
|
||||
foreach (string name in Enum.GetNames(typeof(SearchContext)))
|
||||
contextDrop.options.Add(new Dropdown.OptionData(name));
|
||||
UIFactory.SetLayoutElement(contextDropObj, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999);
|
||||
|
||||
@ -180,13 +179,15 @@ namespace UnityExplorer.ObjectExplorer
|
||||
classInputRow = UIFactory.CreateHorizontalGroup(uiRoot, "ClassRow", false, true, true, true, 2, new Vector4(2, 2, 2, 2));
|
||||
UIFactory.SetLayoutElement(classInputRow, minHeight: 25, flexibleHeight: 0);
|
||||
|
||||
var unityClassLbl = UIFactory.CreateLabel(classInputRow, "ClassLabel", "Class filter:", TextAnchor.MiddleLeft);
|
||||
Text unityClassLbl = UIFactory.CreateLabel(classInputRow, "ClassLabel", "Class filter:", TextAnchor.MiddleLeft);
|
||||
UIFactory.SetLayoutElement(unityClassLbl.gameObject, minWidth: 110, flexibleWidth: 0);
|
||||
|
||||
var classInputField = UIFactory.CreateInputField(classInputRow, "ClassInput", "...");
|
||||
InputFieldRef classInputField = UIFactory.CreateInputField(classInputRow, "ClassInput", "...");
|
||||
UIFactory.SetLayoutElement(classInputField.UIRoot, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999);
|
||||
|
||||
typeAutocompleter = new TypeCompleter(typeof(UnityEngine.Object), classInputField);
|
||||
unityObjectTypeCompleter = new(typeof(UnityEngine.Object), classInputField, true, false, true);
|
||||
allTypesCompleter = new(null, classInputField, true, false, true);
|
||||
allTypesCompleter.Enabled = false;
|
||||
classInputField.OnValueChanged += OnTypeInputChanged;
|
||||
|
||||
//unityObjectClassRow.SetActive(false);
|
||||
@ -196,11 +197,11 @@ namespace UnityExplorer.ObjectExplorer
|
||||
childFilterRow = UIFactory.CreateHorizontalGroup(uiRoot, "ChildFilterRow", false, true, true, true, 2, new Vector4(2, 2, 2, 2));
|
||||
UIFactory.SetLayoutElement(childFilterRow, minHeight: 25, flexibleHeight: 0);
|
||||
|
||||
var childLbl = UIFactory.CreateLabel(childFilterRow, "ChildLabel", "Child filter:", TextAnchor.MiddleLeft);
|
||||
Text childLbl = UIFactory.CreateLabel(childFilterRow, "ChildLabel", "Child filter:", TextAnchor.MiddleLeft);
|
||||
UIFactory.SetLayoutElement(childLbl.gameObject, minWidth: 110, flexibleWidth: 0);
|
||||
|
||||
var childDropObj = UIFactory.CreateDropdown(childFilterRow, "ChildFilterDropdown", out Dropdown childDrop, null, 14, OnChildFilterDropChanged);
|
||||
foreach (var name in Enum.GetNames(typeof(ChildFilter)))
|
||||
GameObject childDropObj = UIFactory.CreateDropdown(childFilterRow, "ChildFilterDropdown", out Dropdown childDrop, null, 14, OnChildFilterDropChanged);
|
||||
foreach (string name in Enum.GetNames(typeof(ChildFilter)))
|
||||
childDrop.options.Add(new Dropdown.OptionData(name));
|
||||
UIFactory.SetLayoutElement(childDropObj, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999);
|
||||
|
||||
@ -211,11 +212,11 @@ namespace UnityExplorer.ObjectExplorer
|
||||
sceneFilterRow = UIFactory.CreateHorizontalGroup(uiRoot, "SceneFilterRow", false, true, true, true, 2, new Vector4(2, 2, 2, 2));
|
||||
UIFactory.SetLayoutElement(sceneFilterRow, minHeight: 25, flexibleHeight: 0);
|
||||
|
||||
var sceneLbl = UIFactory.CreateLabel(sceneFilterRow, "SceneLabel", "Scene filter:", TextAnchor.MiddleLeft);
|
||||
Text sceneLbl = UIFactory.CreateLabel(sceneFilterRow, "SceneLabel", "Scene filter:", TextAnchor.MiddleLeft);
|
||||
UIFactory.SetLayoutElement(sceneLbl.gameObject, minWidth: 110, flexibleWidth: 0);
|
||||
|
||||
var sceneDropObj = UIFactory.CreateDropdown(sceneFilterRow, "SceneFilterDropdown", out Dropdown sceneDrop, null, 14, OnSceneFilterDropChanged);
|
||||
foreach (var name in Enum.GetNames(typeof(SceneFilter)))
|
||||
GameObject sceneDropObj = UIFactory.CreateDropdown(sceneFilterRow, "SceneFilterDropdown", out Dropdown sceneDrop, null, 14, OnSceneFilterDropChanged);
|
||||
foreach (string name in Enum.GetNames(typeof(SceneFilter)))
|
||||
{
|
||||
if (!SceneHandler.DontDestroyExists && name == "DontDestroyOnLoad")
|
||||
continue;
|
||||
@ -230,7 +231,7 @@ namespace UnityExplorer.ObjectExplorer
|
||||
nameInputRow = UIFactory.CreateHorizontalGroup(uiRoot, "NameRow", true, true, true, true, 2, new Vector4(2, 2, 2, 2));
|
||||
UIFactory.SetLayoutElement(nameInputRow, minHeight: 25, flexibleHeight: 0);
|
||||
|
||||
var nameLbl = UIFactory.CreateLabel(nameInputRow, "NameFilterLabel", "Name contains:", TextAnchor.MiddleLeft);
|
||||
Text nameLbl = UIFactory.CreateLabel(nameInputRow, "NameFilterLabel", "Name contains:", TextAnchor.MiddleLeft);
|
||||
UIFactory.SetLayoutElement(nameLbl.gameObject, minWidth: 110, flexibleWidth: 0);
|
||||
|
||||
nameInputField = UIFactory.CreateInputField(nameInputRow, "NameFilterInput", "...");
|
||||
@ -238,13 +239,13 @@ namespace UnityExplorer.ObjectExplorer
|
||||
|
||||
// Search button
|
||||
|
||||
var searchButton = UIFactory.CreateButton(uiRoot, "SearchButton", "Search");
|
||||
ButtonRef searchButton = UIFactory.CreateButton(uiRoot, "SearchButton", "Search");
|
||||
UIFactory.SetLayoutElement(searchButton.Component.gameObject, minHeight: 25, flexibleHeight: 0);
|
||||
searchButton.OnClick += DoSearch;
|
||||
|
||||
// Results count label
|
||||
|
||||
var resultsCountRow = UIFactory.CreateHorizontalGroup(uiRoot, "ResultsCountRow", true, true, true, true);
|
||||
GameObject resultsCountRow = UIFactory.CreateHorizontalGroup(uiRoot, "ResultsCountRow", true, true, true, true);
|
||||
UIFactory.SetLayoutElement(resultsCountRow, minHeight: 25, flexibleHeight: 0);
|
||||
|
||||
resultsLabel = UIFactory.CreateLabel(resultsCountRow, "ResultsLabel", "0 results", TextAnchor.MiddleCenter);
|
||||
|
@ -1,20 +1,10 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
using UnityEngine.SceneManagement;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.UI;
|
||||
using UniverseLib.UI.Models;
|
||||
using UnityExplorer.UI.Panels;
|
||||
using UnityExplorer.UI.Widgets;
|
||||
using UniverseLib.UI;
|
||||
using UniverseLib;
|
||||
using System.Collections;
|
||||
using UniverseLib.Utility;
|
||||
using UniverseLib.UI.Models;
|
||||
using UniverseLib.UI.Widgets;
|
||||
|
||||
namespace UnityExplorer.ObjectExplorer
|
||||
{
|
||||
@ -76,7 +66,7 @@ namespace UnityExplorer.ObjectExplorer
|
||||
this.Parent.SetTab(0);
|
||||
|
||||
// select the transform's scene
|
||||
var go = transform.gameObject;
|
||||
GameObject go = transform.gameObject;
|
||||
if (SceneHandler.SelectedScene != go.scene)
|
||||
{
|
||||
int idx;
|
||||
@ -109,7 +99,7 @@ namespace UnityExplorer.ObjectExplorer
|
||||
|
||||
if (sceneToDropdownOption.ContainsKey(scene))
|
||||
{
|
||||
var opt = sceneToDropdownOption[scene];
|
||||
Dropdown.OptionData opt = sceneToDropdownOption[scene];
|
||||
int idx = sceneDropdown.options.IndexOf(opt);
|
||||
if (sceneDropdown.value != idx)
|
||||
sceneDropdown.value = idx;
|
||||
@ -136,7 +126,7 @@ namespace UnityExplorer.ObjectExplorer
|
||||
sceneToDropdownOption.Clear();
|
||||
sceneDropdown.options.Clear();
|
||||
|
||||
foreach (var scene in loadedScenes)
|
||||
foreach (Scene scene in loadedScenes)
|
||||
{
|
||||
if (sceneToDropdownOption.ContainsKey(scene))
|
||||
continue;
|
||||
@ -148,7 +138,7 @@ namespace UnityExplorer.ObjectExplorer
|
||||
else if (string.IsNullOrEmpty(name))
|
||||
name = "<untitled>";
|
||||
|
||||
var option = new Dropdown.OptionData(name);
|
||||
Dropdown.OptionData option = new(name);
|
||||
sceneDropdown.options.Add(option);
|
||||
sceneToDropdownOption.Add(scene, option);
|
||||
}
|
||||
@ -158,7 +148,7 @@ namespace UnityExplorer.ObjectExplorer
|
||||
{
|
||||
if ((!string.IsNullOrEmpty(input) && !Tree.Filtering) || (string.IsNullOrEmpty(input) && Tree.Filtering))
|
||||
{
|
||||
Tree.cachedTransforms.Clear();
|
||||
Tree.Clear();
|
||||
}
|
||||
|
||||
Tree.CurrentFilter = input;
|
||||
@ -167,7 +157,7 @@ namespace UnityExplorer.ObjectExplorer
|
||||
|
||||
private void TryLoadScene(LoadSceneMode mode, Dropdown allSceneDrop)
|
||||
{
|
||||
var text = allSceneDrop.captionText.text;
|
||||
string text = allSceneDrop.captionText.text;
|
||||
|
||||
if (text == DEFAULT_LOAD_TEXT)
|
||||
return;
|
||||
@ -191,18 +181,18 @@ namespace UnityExplorer.ObjectExplorer
|
||||
|
||||
// Tool bar (top area)
|
||||
|
||||
var toolbar = UIFactory.CreateVerticalGroup(uiRoot, "Toolbar", true, true, true, true, 2, new Vector4(2, 2, 2, 2),
|
||||
GameObject toolbar = UIFactory.CreateVerticalGroup(uiRoot, "Toolbar", true, true, true, true, 2, new Vector4(2, 2, 2, 2),
|
||||
new Color(0.15f, 0.15f, 0.15f));
|
||||
|
||||
// Scene selector dropdown
|
||||
|
||||
var dropRow = UIFactory.CreateHorizontalGroup(toolbar, "DropdownRow", true, true, true, true, 5, default, new Color(1, 1, 1, 0));
|
||||
GameObject dropRow = UIFactory.CreateHorizontalGroup(toolbar, "DropdownRow", true, true, true, true, 5, default, new Color(1, 1, 1, 0));
|
||||
UIFactory.SetLayoutElement(dropRow, minHeight: 25, flexibleWidth: 9999);
|
||||
|
||||
var dropLabel = UIFactory.CreateLabel(dropRow, "SelectorLabel", "Scene:", TextAnchor.MiddleLeft, Color.cyan, false, 15);
|
||||
Text dropLabel = UIFactory.CreateLabel(dropRow, "SelectorLabel", "Scene:", TextAnchor.MiddleLeft, Color.cyan, false, 15);
|
||||
UIFactory.SetLayoutElement(dropLabel.gameObject, minHeight: 25, minWidth: 60, flexibleWidth: 0);
|
||||
|
||||
var dropdownObj = UIFactory.CreateDropdown(dropRow, "SceneDropdown", out sceneDropdown, "<notset>", 13, OnSceneSelectionDropdownChanged);
|
||||
GameObject dropdownObj = UIFactory.CreateDropdown(dropRow, "SceneDropdown", out sceneDropdown, "<notset>", 13, OnSceneSelectionDropdownChanged);
|
||||
UIFactory.SetLayoutElement(dropdownObj, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999);
|
||||
|
||||
SceneHandler.Update();
|
||||
@ -211,11 +201,11 @@ namespace UnityExplorer.ObjectExplorer
|
||||
|
||||
// Filter row
|
||||
|
||||
var filterRow = UIFactory.CreateHorizontalGroup(toolbar, "FilterGroup", true, true, true, true, 2, new Vector4(2, 2, 2, 2));
|
||||
GameObject filterRow = UIFactory.CreateHorizontalGroup(toolbar, "FilterGroup", true, true, true, true, 2, new Vector4(2, 2, 2, 2));
|
||||
UIFactory.SetLayoutElement(filterRow, minHeight: 25, flexibleHeight: 0);
|
||||
|
||||
//Filter input field
|
||||
var inputField = UIFactory.CreateInputField(filterRow, "FilterInput", "Search and press enter...");
|
||||
InputFieldRef inputField = UIFactory.CreateInputField(filterRow, "FilterInput", "Search and press enter...");
|
||||
inputField.Component.targetGraphic.color = 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));
|
||||
@ -228,11 +218,11 @@ namespace UnityExplorer.ObjectExplorer
|
||||
refreshRow = UIFactory.CreateHorizontalGroup(toolbar, "RefreshGroup", true, true, true, true, 2, new Vector4(2, 2, 2, 2));
|
||||
UIFactory.SetLayoutElement(refreshRow, minHeight: 30, flexibleHeight: 0);
|
||||
|
||||
var refreshButton = UIFactory.CreateButton(refreshRow, "RefreshButton", "Update");
|
||||
ButtonRef refreshButton = UIFactory.CreateButton(refreshRow, "RefreshButton", "Update");
|
||||
UIFactory.SetLayoutElement(refreshButton.Component.gameObject, minWidth: 65, flexibleWidth: 0);
|
||||
refreshButton.OnClick += UpdateTree;
|
||||
|
||||
var refreshToggle = UIFactory.CreateToggle(refreshRow, "RefreshToggle", out Toggle toggle, out Text text);
|
||||
GameObject refreshToggle = UIFactory.CreateToggle(refreshRow, "RefreshToggle", out Toggle toggle, out Text text);
|
||||
UIFactory.SetLayoutElement(refreshToggle, flexibleWidth: 9999);
|
||||
text.text = "Auto-update (1 second)";
|
||||
text.alignment = TextAnchor.MiddleLeft;
|
||||
@ -245,24 +235,23 @@ namespace UnityExplorer.ObjectExplorer
|
||||
|
||||
// tree labels row
|
||||
|
||||
var labelsRow = UIFactory.CreateHorizontalGroup(toolbar, "LabelsRow", true, true, true, true, 2, new Vector4(2, 2, 2, 2));
|
||||
GameObject 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);
|
||||
Text 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);
|
||||
Text 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
|
||||
|
||||
var scrollPool = UIFactory.CreateScrollPool<TransformCell>(uiRoot, "TransformTree", out GameObject scrollObj,
|
||||
UniverseLib.UI.Widgets.ScrollView.ScrollPool<TransformCell> scrollPool = UIFactory.CreateScrollPool<TransformCell>(uiRoot, "TransformTree", out GameObject scrollObj,
|
||||
out GameObject scrollContent, new Color(0.11f, 0.11f, 0.11f));
|
||||
UIFactory.SetLayoutElement(scrollObj, flexibleHeight: 9999);
|
||||
UIFactory.SetLayoutElement(scrollContent, flexibleHeight: 9999);
|
||||
|
||||
Tree = new TransformTree(scrollPool, GetRootEntries);
|
||||
Tree.Init();
|
||||
Tree = new TransformTree(scrollPool, GetRootEntries, OnCellClicked);
|
||||
Tree.RefreshData(true, true, true, false);
|
||||
//scrollPool.Viewport.GetComponent<Mask>().enabled = false;
|
||||
//UIRoot.GetComponent<Mask>().enabled = false;
|
||||
@ -274,6 +263,8 @@ namespace UnityExplorer.ObjectExplorer
|
||||
RuntimeHelper.StartCoroutine(TempFixCoro());
|
||||
}
|
||||
|
||||
void OnCellClicked(GameObject obj) => InspectorManager.Inspect(obj);
|
||||
|
||||
// To "fix" a strange FPS drop issue with MelonLoader.
|
||||
private IEnumerator TempFixCoro()
|
||||
{
|
||||
@ -294,7 +285,7 @@ namespace UnityExplorer.ObjectExplorer
|
||||
allSceneDropdown.options.Clear();
|
||||
allSceneDropdown.options.Add(new Dropdown.OptionData(DEFAULT_LOAD_TEXT));
|
||||
|
||||
foreach (var scene in SceneHandler.AllSceneNames)
|
||||
foreach (string scene in SceneHandler.AllSceneNames)
|
||||
{
|
||||
if (string.IsNullOrEmpty(filter) || scene.ContainsIgnoreCase(filter))
|
||||
allSceneDropdown.options.Add(new Dropdown.OptionData(Path.GetFileNameWithoutExtension(scene)));
|
||||
@ -308,7 +299,7 @@ namespace UnityExplorer.ObjectExplorer
|
||||
|
||||
private void RefreshSceneLoaderButtons()
|
||||
{
|
||||
var text = allSceneDropdown.captionText.text;
|
||||
string text = allSceneDropdown.captionText.text;
|
||||
if (text == DEFAULT_LOAD_TEXT)
|
||||
{
|
||||
loadButton.Component.interactable = false;
|
||||
@ -328,30 +319,30 @@ namespace UnityExplorer.ObjectExplorer
|
||||
{
|
||||
if (SceneHandler.WasAbleToGetScenesInBuild)
|
||||
{
|
||||
var sceneLoaderObj = UIFactory.CreateVerticalGroup(uiRoot, "SceneLoader", true, true, true, true);
|
||||
GameObject sceneLoaderObj = UIFactory.CreateVerticalGroup(uiRoot, "SceneLoader", true, true, true, true);
|
||||
UIFactory.SetLayoutElement(sceneLoaderObj, minHeight: 25);
|
||||
|
||||
// Title
|
||||
|
||||
var loaderTitle = UIFactory.CreateLabel(sceneLoaderObj, "SceneLoaderLabel", "Scene Loader", TextAnchor.MiddleLeft, Color.white, true, 14);
|
||||
Text loaderTitle = UIFactory.CreateLabel(sceneLoaderObj, "SceneLoaderLabel", "Scene Loader", TextAnchor.MiddleLeft, Color.white, true, 14);
|
||||
UIFactory.SetLayoutElement(loaderTitle.gameObject, minHeight: 25, flexibleHeight: 0);
|
||||
|
||||
// Search filter
|
||||
|
||||
var searchFilterObj = UIFactory.CreateInputField(sceneLoaderObj, "SearchFilterInput", "Filter scene names...");
|
||||
InputFieldRef searchFilterObj = UIFactory.CreateInputField(sceneLoaderObj, "SearchFilterInput", "Filter scene names...");
|
||||
UIFactory.SetLayoutElement(searchFilterObj.UIRoot, minHeight: 25, flexibleHeight: 0);
|
||||
searchFilterObj.OnValueChanged += RefreshSceneLoaderOptions;
|
||||
|
||||
// Dropdown
|
||||
|
||||
var allSceneDropObj = UIFactory.CreateDropdown(sceneLoaderObj, "SceneLoaderDropdown", out allSceneDropdown, "", 14, null);
|
||||
GameObject allSceneDropObj = UIFactory.CreateDropdown(sceneLoaderObj, "SceneLoaderDropdown", out allSceneDropdown, "", 14, null);
|
||||
UIFactory.SetLayoutElement(allSceneDropObj, minHeight: 25, minWidth: 150, flexibleWidth: 0, flexibleHeight: 0);
|
||||
|
||||
RefreshSceneLoaderOptions(string.Empty);
|
||||
|
||||
// Button row
|
||||
|
||||
var buttonRow = UIFactory.CreateHorizontalGroup(sceneLoaderObj, "LoadButtons", true, true, true, true, 4);
|
||||
GameObject buttonRow = UIFactory.CreateHorizontalGroup(sceneLoaderObj, "LoadButtons", true, true, true, true, 4);
|
||||
|
||||
loadButton = UIFactory.CreateButton(buttonRow, "LoadSceneButton", "Load (Single)", new Color(0.1f, 0.3f, 0.3f));
|
||||
UIFactory.SetLayoutElement(loadButton.Component.gameObject, minHeight: 25, minWidth: 150);
|
||||
@ -367,7 +358,7 @@ namespace UnityExplorer.ObjectExplorer
|
||||
TryLoadScene(LoadSceneMode.Additive, allSceneDropdown);
|
||||
};
|
||||
|
||||
var disabledColor = new Color(0.24f, 0.24f, 0.24f);
|
||||
Color disabledColor = new(0.24f, 0.24f, 0.24f);
|
||||
RuntimeHelper.SetColorBlock(loadButton.Component, disabled: disabledColor);
|
||||
RuntimeHelper.SetColorBlock(loadAdditiveButton.Component, disabled: disabledColor);
|
||||
|
||||
|
@ -1,11 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
using UniverseLib;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
namespace UnityExplorer.ObjectExplorer
|
||||
{
|
||||
@ -65,11 +58,11 @@ namespace UnityExplorer.ObjectExplorer
|
||||
if (sceneUtil == null)
|
||||
throw new Exception("This version of Unity does not ship with the 'SceneUtility' class, or it was not unstripped.");
|
||||
|
||||
var method = sceneUtil.GetMethod("GetScenePathByBuildIndex", ReflectionUtility.FLAGS);
|
||||
System.Reflection.MethodInfo method = sceneUtil.GetMethod("GetScenePathByBuildIndex", ReflectionUtility.FLAGS);
|
||||
int sceneCount = SceneManager.sceneCountInBuildSettings;
|
||||
for (int i = 0; i < sceneCount; i++)
|
||||
{
|
||||
var scenePath = (string)method.Invoke(null, new object[] { i });
|
||||
string scenePath = (string)method.Invoke(null, new object[] { i });
|
||||
AllSceneNames.Add(scenePath);
|
||||
}
|
||||
|
||||
@ -85,9 +78,9 @@ namespace UnityExplorer.ObjectExplorer
|
||||
internal static void Update()
|
||||
{
|
||||
// Inspected scene will exist if it's DontDestroyOnLoad or HideAndDontSave
|
||||
bool inspectedExists =
|
||||
SelectedScene.HasValue
|
||||
&& ((DontDestroyExists && SelectedScene.Value.handle == -12)
|
||||
bool inspectedExists =
|
||||
SelectedScene.HasValue
|
||||
&& ((DontDestroyExists && SelectedScene.Value.handle == -12)
|
||||
|| SelectedScene.Value.handle == -1);
|
||||
|
||||
LoadedScenes.Clear();
|
||||
@ -121,11 +114,11 @@ namespace UnityExplorer.ObjectExplorer
|
||||
CurrentRootObjects = RuntimeHelper.GetRootGameObjects((Scene)SelectedScene);
|
||||
else
|
||||
{
|
||||
var allObjects = RuntimeHelper.FindObjectsOfTypeAll(typeof(GameObject));
|
||||
var objects = new List<GameObject>();
|
||||
foreach (var obj in allObjects)
|
||||
UnityEngine.Object[] allObjects = RuntimeHelper.FindObjectsOfTypeAll(typeof(GameObject));
|
||||
List<GameObject> objects = new();
|
||||
foreach (UnityEngine.Object obj in allObjects)
|
||||
{
|
||||
var go = obj.TryCast<GameObject>();
|
||||
GameObject go = obj.TryCast<GameObject>();
|
||||
if (go.transform.parent == null && !go.scene.IsValid())
|
||||
objects.Add(go);
|
||||
}
|
||||
|
@ -1,14 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
using UnityExplorer.Runtime;
|
||||
using UniverseLib;
|
||||
using UniverseLib.Input;
|
||||
using UniverseLib.Utility;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
namespace UnityExplorer.ObjectExplorer
|
||||
{
|
||||
@ -50,7 +40,7 @@ namespace UnityExplorer.ObjectExplorer
|
||||
|
||||
internal static List<object> UnityObjectSearch(string input, string customTypeInput, ChildFilter childFilter, SceneFilter sceneFilter)
|
||||
{
|
||||
var results = new List<object>();
|
||||
List<object> results = new();
|
||||
|
||||
Type searchType = null;
|
||||
if (!string.IsNullOrEmpty(customTypeInput))
|
||||
@ -69,7 +59,7 @@ namespace UnityExplorer.ObjectExplorer
|
||||
if (searchType == null)
|
||||
searchType = typeof(UnityEngine.Object);
|
||||
|
||||
var allObjects = RuntimeHelper.FindObjectsOfTypeAll(searchType);
|
||||
UnityEngine.Object[] allObjects = RuntimeHelper.FindObjectsOfTypeAll(searchType);
|
||||
|
||||
// perform filter comparers
|
||||
|
||||
@ -79,14 +69,14 @@ namespace UnityExplorer.ObjectExplorer
|
||||
|
||||
bool shouldFilterGOs = searchType == typeof(GameObject) || typeof(Component).IsAssignableFrom(searchType);
|
||||
|
||||
foreach (var obj in allObjects)
|
||||
foreach (UnityEngine.Object obj in allObjects)
|
||||
{
|
||||
// name check
|
||||
if (!string.IsNullOrEmpty(nameFilter) && !obj.name.ContainsIgnoreCase(nameFilter))
|
||||
continue;
|
||||
|
||||
GameObject go = null;
|
||||
var type = obj.GetActualType();
|
||||
Type type = obj.GetActualType();
|
||||
|
||||
if (type == typeof(GameObject))
|
||||
go = obj.TryCast<GameObject>();
|
||||
@ -130,15 +120,15 @@ namespace UnityExplorer.ObjectExplorer
|
||||
|
||||
internal static List<object> ClassSearch(string input)
|
||||
{
|
||||
var list = new List<object>();
|
||||
List<object> list = new();
|
||||
|
||||
var nameFilter = "";
|
||||
string nameFilter = "";
|
||||
if (!string.IsNullOrEmpty(input))
|
||||
nameFilter = input;
|
||||
|
||||
foreach (var asm in AppDomain.CurrentDomain.GetAssemblies())
|
||||
foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies())
|
||||
{
|
||||
foreach (var type in asm.TryGetTypes())
|
||||
foreach (Type type in asm.GetTypes())
|
||||
{
|
||||
if (!string.IsNullOrEmpty(nameFilter) && !type.FullName.ContainsIgnoreCase(nameFilter))
|
||||
continue;
|
||||
@ -165,30 +155,30 @@ namespace UnityExplorer.ObjectExplorer
|
||||
|
||||
internal static List<object> InstanceSearch(string input)
|
||||
{
|
||||
var instances = new List<object>();
|
||||
List<object> instances = new();
|
||||
|
||||
var nameFilter = "";
|
||||
string nameFilter = "";
|
||||
if (!string.IsNullOrEmpty(input))
|
||||
nameFilter = input;
|
||||
|
||||
var flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static;
|
||||
|
||||
foreach (var asm in AppDomain.CurrentDomain.GetAssemblies())
|
||||
BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static;
|
||||
|
||||
foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies())
|
||||
{
|
||||
// Search all non-static, non-enum classes.
|
||||
foreach (var type in asm.TryGetTypes().Where(it => !(it.IsSealed && it.IsAbstract) && !it.IsEnum))
|
||||
foreach (Type type in asm.GetTypes().Where(it => !(it.IsSealed && it.IsAbstract) && !it.IsEnum))
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!string.IsNullOrEmpty(nameFilter) && !type.FullName.ContainsIgnoreCase(nameFilter))
|
||||
continue;
|
||||
|
||||
|
||||
ReflectionUtility.FindSingleton(instanceNames, type, flags, instances);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return instances;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using UnityExplorer;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
|
@ -1,5 +1,4 @@
|
||||
#if MONO
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityExplorer.Runtime
|
||||
{
|
||||
|
@ -1,15 +1,4 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.SceneManagement;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.Config;
|
||||
using UniverseLib;
|
||||
using UnityExplorer.Config;
|
||||
|
||||
namespace UnityExplorer.Runtime
|
||||
{
|
||||
@ -20,7 +9,7 @@ namespace UnityExplorer.Runtime
|
||||
public static UERuntimeHelper Instance;
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
{
|
||||
#if CPP
|
||||
Instance = new Il2CppHelper();
|
||||
#else
|
||||
@ -50,10 +39,10 @@ namespace UnityExplorer.Runtime
|
||||
|
||||
try
|
||||
{
|
||||
var sigs = blacklist.Split(';');
|
||||
foreach (var sig in sigs)
|
||||
string[] sigs = blacklist.Split(';');
|
||||
foreach (string sig in sigs)
|
||||
{
|
||||
var s = sig.Trim();
|
||||
string s = sig.Trim();
|
||||
if (string.IsNullOrEmpty(s))
|
||||
continue;
|
||||
if (!currentBlacklist.Contains(s))
|
||||
@ -65,7 +54,7 @@ namespace UnityExplorer.Runtime
|
||||
ExplorerCore.LogWarning($"Exception parsing blacklist string: {ex.ReflectionExToString()}");
|
||||
}
|
||||
|
||||
foreach (var sig in Instance.DefaultReflectionBlacklist)
|
||||
foreach (string sig in Instance.DefaultReflectionBlacklist)
|
||||
{
|
||||
if (!currentBlacklist.Contains(sig))
|
||||
currentBlacklist.Add(sig);
|
||||
@ -84,7 +73,7 @@ namespace UnityExplorer.Runtime
|
||||
if (string.IsNullOrEmpty(member.DeclaringType?.Namespace))
|
||||
return false;
|
||||
|
||||
var sig = $"{member.DeclaringType.FullName}.{member.Name}";
|
||||
string sig = $"{member.DeclaringType.FullName}.{member.Name}";
|
||||
|
||||
return currentBlacklist.Contains(sig);
|
||||
}
|
||||
|
@ -1,16 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityExplorer.CacheObject;
|
||||
|
||||
namespace UnityExplorer.Runtime
|
||||
namespace UnityExplorer.Runtime
|
||||
{
|
||||
internal static class UnityCrashPrevention
|
||||
{
|
||||
static readonly HarmonyLib.Harmony harmony = new ($"{ExplorerCore.GUID}.crashprevention");
|
||||
static readonly HarmonyLib.Harmony harmony = new($"{ExplorerCore.GUID}.crashprevention");
|
||||
|
||||
internal static void Init()
|
||||
{
|
||||
@ -27,7 +19,7 @@ namespace UnityExplorer.Runtime
|
||||
try
|
||||
{
|
||||
harmony.Patch(
|
||||
HarmonyLib.AccessTools.Method(typeof(T), orig, argTypes),
|
||||
HarmonyLib.AccessTools.Method(typeof(T), orig, argTypes),
|
||||
new HarmonyLib.HarmonyMethod(HarmonyLib.AccessTools.Method(typeof(UnityCrashPrevention), prefix)));
|
||||
}
|
||||
catch //(Exception ex)
|
||||
|
@ -1,16 +1,13 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityExplorer.UI;
|
||||
using UnityExplorer.CacheObject.IValues;
|
||||
using System.Collections;
|
||||
#if CPP
|
||||
#if INTEROP
|
||||
using Il2CppInterop.Runtime.InteropTypes.Arrays;
|
||||
using Il2CppInterop.Runtime;
|
||||
#else
|
||||
using UnhollowerRuntimeLib;
|
||||
using UnhollowerBaseLib;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace UnityExplorer.Tests
|
||||
{
|
||||
@ -74,7 +71,7 @@ namespace UnityExplorer.Tests
|
||||
{
|
||||
get
|
||||
{
|
||||
var list = new List<object>();
|
||||
List<object> list = new();
|
||||
int count = UnityEngine.Random.Range(0, 100);
|
||||
for (int i = 0; i < count; i++)
|
||||
list.Add(GetRandomObject());
|
||||
@ -178,6 +175,7 @@ namespace UnityExplorer.Tests
|
||||
public static Il2CppSystem.Collections.IDictionary IL2CPP_IDict;
|
||||
public static Il2CppSystem.Collections.IList IL2CPP_IList;
|
||||
public static Dictionary<Il2CppSystem.Object, Il2CppSystem.Object> IL2CPP_BoxedDict;
|
||||
public static Il2CppSystem.Array IL2CPP_NonGenericArray;
|
||||
|
||||
public static Il2CppSystem.Object IL2CPP_BoxedInt;
|
||||
public static Il2CppSystem.Int32 IL2CPP_Int;
|
||||
@ -191,6 +189,9 @@ namespace UnityExplorer.Tests
|
||||
|
||||
private static void Init_IL2CPP()
|
||||
{
|
||||
ExplorerCore.Log("IL2CPP 0: Non-generic array");
|
||||
IL2CPP_NonGenericArray = new Il2CppStructArray<int>(5).TryCast<Il2CppSystem.Array>();
|
||||
|
||||
ExplorerCore.Log($"IL2CPP 1: Il2Cpp Dictionary<string, string>");
|
||||
IL2CPP_Dict = new Il2CppSystem.Collections.Generic.Dictionary<string, string>();
|
||||
IL2CPP_Dict.Add("key1", "value1");
|
||||
@ -209,12 +210,12 @@ namespace UnityExplorer.Tests
|
||||
IL2CPP_HashTable.Add("key3", "value3");
|
||||
|
||||
ExplorerCore.Log($"IL2CPP 3: Il2Cpp IDictionary");
|
||||
var dict2 = new Il2CppSystem.Collections.Generic.Dictionary<string, string>();
|
||||
Il2CppSystem.Collections.Generic.Dictionary<string, string> dict2 = new Il2CppSystem.Collections.Generic.Dictionary<string, string>();
|
||||
dict2.Add("key1", "value1");
|
||||
IL2CPP_IDict = dict2.TryCast<Il2CppSystem.Collections.IDictionary>();
|
||||
|
||||
ExplorerCore.Log($"IL2CPP 4: Il2Cpp List of Il2Cpp Object");
|
||||
var list = new Il2CppSystem.Collections.Generic.List<Il2CppSystem.Object>(5);
|
||||
Il2CppSystem.Collections.Generic.List<Il2CppSystem.Object> list = new Il2CppSystem.Collections.Generic.List<Il2CppSystem.Object>(5);
|
||||
list.Add("one");
|
||||
list.Add("two");
|
||||
IL2CPP_IList = list.TryCast<Il2CppSystem.Collections.IList>();
|
||||
@ -240,14 +241,14 @@ namespace UnityExplorer.Tests
|
||||
// boxed enum test
|
||||
try
|
||||
{
|
||||
var cppType = Il2CppType.Of<CameraClearFlags>();
|
||||
if (cppType != null)
|
||||
Il2CppSystem.Type cppType = Il2CppType.Of<CameraClearFlags>();
|
||||
if (cppType is not null)
|
||||
{
|
||||
var boxedEnum = Il2CppSystem.Enum.Parse(cppType, "Color");
|
||||
Il2CppSystem.Object boxedEnum = Il2CppSystem.Enum.Parse(cppType, "Color");
|
||||
IL2CPP_listOfBoxedObjects.Add(boxedEnum);
|
||||
}
|
||||
|
||||
var structBox = Vector3.one.BoxIl2CppObject();
|
||||
Il2CppSystem.Object structBox = Vector3.one.BoxIl2CppObject();
|
||||
IL2CPP_listOfBoxedObjects.Add(structBox);
|
||||
|
||||
}
|
||||
@ -257,7 +258,7 @@ namespace UnityExplorer.Tests
|
||||
}
|
||||
|
||||
ExplorerCore.Log($"IL2CPP 9: Il2Cpp struct array of ints");
|
||||
IL2CPP_structArray = new UnhollowerBaseLib.Il2CppStructArray<int>(5);
|
||||
IL2CPP_structArray = new Il2CppStructArray<int>(5);
|
||||
IL2CPP_structArray[0] = 0;
|
||||
IL2CPP_structArray[1] = 1;
|
||||
IL2CPP_structArray[2] = 2;
|
||||
@ -265,7 +266,7 @@ namespace UnityExplorer.Tests
|
||||
IL2CPP_structArray[4] = 4;
|
||||
|
||||
ExplorerCore.Log($"IL2CPP 10: Il2Cpp reference array of boxed objects");
|
||||
IL2CPP_ReferenceArray = new UnhollowerBaseLib.Il2CppReferenceArray<Il2CppSystem.Object>(3);
|
||||
IL2CPP_ReferenceArray = new Il2CppReferenceArray<Il2CppSystem.Object>(3);
|
||||
IL2CPP_ReferenceArray[0] = new Il2CppSystem.Int32 { m_value = 5 }.BoxIl2CppObject();
|
||||
IL2CPP_ReferenceArray[1] = null;
|
||||
IL2CPP_ReferenceArray[2] = (Il2CppSystem.String)"whats up";
|
||||
|
@ -1,11 +1,5 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
using UnityExplorer.Config;
|
||||
using UniverseLib;
|
||||
using UniverseLib.Input;
|
||||
|
||||
namespace UnityExplorer.UI
|
||||
@ -45,7 +39,7 @@ namespace UnityExplorer.UI
|
||||
ConfigManager.Target_Display.Value = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ActiveDisplayIndex = display;
|
||||
ActiveDisplay.Activate();
|
||||
@ -72,7 +66,7 @@ namespace UnityExplorer.UI
|
||||
yield return null;
|
||||
yield return null;
|
||||
|
||||
foreach (var panel in UIManager.UIPanels.Values)
|
||||
foreach (Panels.UEPanel panel in UIManager.UIPanels.Values)
|
||||
{
|
||||
panel.EnsureValidSize();
|
||||
panel.EnsureValidPosition();
|
||||
|
15
src/UI/ExplorerUIBase.cs
Normal file
15
src/UI/ExplorerUIBase.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using UniverseLib.UI;
|
||||
using UniverseLib.UI.Panels;
|
||||
|
||||
namespace UnityExplorer.UI
|
||||
{
|
||||
internal class ExplorerUIBase : UIBase
|
||||
{
|
||||
public ExplorerUIBase(string id, Action updateMethod) : base(id, updateMethod) { }
|
||||
|
||||
protected override PanelManager CreatePanelManager()
|
||||
{
|
||||
return new UEPanelManager(this);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,11 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UniverseLib.Input;
|
||||
using UniverseLib.UI;
|
||||
using UniverseLib.UI;
|
||||
|
||||
namespace UnityExplorer.UI
|
||||
{
|
||||
@ -44,11 +37,10 @@ namespace UnityExplorer.UI
|
||||
|
||||
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>();
|
||||
CanvasGroup popupGroup = popupLabel.gameObject.AddComponent<CanvasGroup>();
|
||||
popupGroup.blocksRaycasts = false;
|
||||
}
|
||||
}
|
||||
|
@ -1,35 +1,29 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.UI.Widgets.AutoComplete;
|
||||
using UniverseLib.Input;
|
||||
using UnityExplorer.Runtime;
|
||||
using UnityExplorer.UI;
|
||||
using UnityExplorer.UI.Panels;
|
||||
using UniverseLib.UI.Widgets;
|
||||
using UniverseLib;
|
||||
using UniverseLib.UI;
|
||||
using UniverseLib.UI.Models;
|
||||
using UniverseLib.UI.Widgets.ButtonList;
|
||||
using UniverseLib.UI.Widgets.ScrollView;
|
||||
using UniverseLib.Utility;
|
||||
using UniverseLib.UI.Models;
|
||||
|
||||
namespace UnityExplorer.UI.Widgets.AutoComplete
|
||||
namespace UnityExplorer.UI.Panels
|
||||
{
|
||||
// Shared modal panel for "AutoComplete" suggestions.
|
||||
// A data source implements ISuggestionProvider and uses TakeOwnership and ReleaseOwnership
|
||||
// for control, and SetSuggestions to set the actual suggestion data.
|
||||
|
||||
public class AutoCompleteModal : UIPanel
|
||||
public class AutoCompleteModal : UEPanel
|
||||
{
|
||||
public static AutoCompleteModal Instance => UIManager.GetPanel<AutoCompleteModal>(UIManager.Panels.AutoCompleter);
|
||||
|
||||
public override string Name => "AutoCompleter";
|
||||
public override UIManager.Panels PanelType => UIManager.Panels.AutoCompleter;
|
||||
public override int MinWidth => -1;
|
||||
public override int MinHeight => -1;
|
||||
|
||||
public override int MinWidth => 100;
|
||||
public override int MinHeight => 25;
|
||||
public override Vector2 DefaultAnchorMin => new(MIN_X, 0.4f);
|
||||
public override Vector2 DefaultAnchorMax => new(0.68f, MAX_Y);
|
||||
const float MIN_X = 0.42f;
|
||||
const float MAX_Y = 0.6f;
|
||||
|
||||
public override bool CanDragAndResize => true;
|
||||
public override bool ShouldSaveActiveState => false;
|
||||
@ -48,10 +42,10 @@ namespace UnityExplorer.UI.Widgets.AutoComplete
|
||||
|
||||
public static bool Suggesting(ISuggestionProvider handler) => CurrentHandler == handler && Instance.UIRoot.activeSelf;
|
||||
|
||||
public AutoCompleteModal()
|
||||
public AutoCompleteModal(UIBase owner) : base(owner)
|
||||
{
|
||||
OnPanelsReordered += UIPanel_OnPanelsReordered;
|
||||
OnClickedOutsidePanels += AutoCompleter_OnClickedOutsidePanels;
|
||||
UIManager.UiBase.Panels.OnPanelsReordered += UIPanel_OnPanelsReordered;
|
||||
UIManager.UiBase.Panels.OnClickedOutsidePanels += AutoCompleter_OnClickedOutsidePanels;
|
||||
}
|
||||
|
||||
public static void TakeOwnership(ISuggestionProvider provider)
|
||||
@ -67,15 +61,22 @@ namespace UnityExplorer.UI.Widgets.AutoComplete
|
||||
|
||||
if (CurrentHandler == provider)
|
||||
{
|
||||
Suggestions.Clear();
|
||||
CurrentHandler = null;
|
||||
UIRoot.SetActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetSuggestions(IEnumerable<Suggestion> suggestions)
|
||||
public void SetSuggestions(List<Suggestion> suggestions, bool jumpToTop = true)
|
||||
{
|
||||
Suggestions = suggestions as List<Suggestion> ?? suggestions.ToList();
|
||||
SelectedIndex = 0;
|
||||
Suggestions = suggestions;
|
||||
|
||||
if (jumpToTop)
|
||||
{
|
||||
SelectedIndex = 0;
|
||||
if (scrollPool.DataSource.ItemCount > 0)
|
||||
scrollPool.JumpToIndex(0, null);
|
||||
}
|
||||
|
||||
if (!Suggestions.Any())
|
||||
base.UIRoot.SetActive(false);
|
||||
@ -84,7 +85,7 @@ namespace UnityExplorer.UI.Widgets.AutoComplete
|
||||
base.UIRoot.SetActive(true);
|
||||
base.UIRoot.transform.SetAsLastSibling();
|
||||
buttonListDataHandler.RefreshData();
|
||||
scrollPool.Refresh(true, true);
|
||||
scrollPool.Refresh(true, jumpToTop);
|
||||
}
|
||||
}
|
||||
|
||||
@ -184,7 +185,7 @@ namespace UnityExplorer.UI.Widgets.AutoComplete
|
||||
|
||||
private void OnCellClicked(int dataIndex)
|
||||
{
|
||||
var suggestion = Suggestions[dataIndex];
|
||||
Suggestion suggestion = Suggestions[dataIndex];
|
||||
CurrentHandler.OnSuggestionClicked(suggestion);
|
||||
}
|
||||
|
||||
@ -192,13 +193,19 @@ namespace UnityExplorer.UI.Widgets.AutoComplete
|
||||
|
||||
private void SetCell(ButtonCell cell, int index)
|
||||
{
|
||||
if (CurrentHandler == null)
|
||||
{
|
||||
UIRoot.SetActive(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (index < 0 || index >= Suggestions.Count)
|
||||
{
|
||||
cell.Disable();
|
||||
return;
|
||||
}
|
||||
|
||||
var suggestion = Suggestions[index];
|
||||
Suggestion suggestion = Suggestions[index];
|
||||
cell.Button.ButtonText.text = suggestion.DisplayText;
|
||||
|
||||
if (CurrentHandler.AllowNavigation && index == SelectedIndex && setFirstCell)
|
||||
@ -223,14 +230,19 @@ namespace UnityExplorer.UI.Widgets.AutoComplete
|
||||
|
||||
InputFieldRef input = CurrentHandler.InputField;
|
||||
|
||||
if (!input.Component.isFocused || input.Component.caretPosition == lastCaretPosition && input.UIRoot.transform.position == lastInputPosition)
|
||||
return;
|
||||
lastInputPosition = input.UIRoot.transform.position;
|
||||
lastCaretPosition = input.Component.caretPosition;
|
||||
//if (!input.Component.isFocused
|
||||
// || (input.Component.caretPosition == lastCaretPosition && input.UIRoot.transform.position == lastInputPosition))
|
||||
// return;
|
||||
|
||||
if (input.Component.caretPosition == lastCaretPosition && input.UIRoot.transform.position == lastInputPosition)
|
||||
return;
|
||||
|
||||
if (CurrentHandler.AnchorToCaretPosition)
|
||||
{
|
||||
var textGen = input.Component.cachedInputTextGenerator;
|
||||
if (!input.Component.isFocused)
|
||||
return;
|
||||
|
||||
TextGenerator textGen = input.Component.cachedInputTextGenerator;
|
||||
int caretIdx = Math.Max(0, Math.Min(textGen.characterCount - 1, input.Component.caretPosition));
|
||||
|
||||
// normalize the caret horizontal position
|
||||
@ -246,6 +258,9 @@ namespace UnityExplorer.UI.Widgets.AutoComplete
|
||||
uiRoot.transform.position = input.Transform.position + new Vector3(-(input.Transform.rect.width / 2) + 10, -20, 0);
|
||||
}
|
||||
|
||||
lastInputPosition = input.UIRoot.transform.position;
|
||||
lastCaretPosition = input.Component.caretPosition;
|
||||
|
||||
this.Dragger.OnEndResize();
|
||||
}
|
||||
|
||||
@ -267,7 +282,7 @@ namespace UnityExplorer.UI.Widgets.AutoComplete
|
||||
if (!this.UIRoot || !this.UIRoot.activeInHierarchy)
|
||||
return;
|
||||
|
||||
if (this.UIRoot.transform.GetSiblingIndex() != UIManager.PanelHolder.transform.childCount - 1)
|
||||
if (this.UIRoot.transform.GetSiblingIndex() != UIManager.UiBase.Panels.PanelHolder.transform.childCount - 1)
|
||||
{
|
||||
if (CurrentHandler != null)
|
||||
ReleaseOwnership(CurrentHandler);
|
||||
@ -276,46 +291,36 @@ namespace UnityExplorer.UI.Widgets.AutoComplete
|
||||
}
|
||||
}
|
||||
|
||||
// UI Construction
|
||||
|
||||
const float MIN_X = 0.42f;
|
||||
const float MAX_Y = 0.6f;
|
||||
|
||||
protected internal override void DoSetDefaultPosAndAnchors()
|
||||
public override void OnFinishResize()
|
||||
{
|
||||
Rect.pivot = new Vector2(0f, 1f);
|
||||
Rect.anchorMin = new Vector2(MIN_X, 0.4f);
|
||||
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;
|
||||
float xDiff = Rect.anchorMin.x - MIN_X;
|
||||
float yDiff = Rect.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);
|
||||
Rect.anchorMin = new(MIN_X, Rect.anchorMin.y - yDiff);
|
||||
Rect.anchorMax = new(Rect.anchorMax.x - xDiff, MAX_Y);
|
||||
}
|
||||
|
||||
base.OnFinishResize(panel);
|
||||
base.OnFinishResize();
|
||||
}
|
||||
|
||||
public override void ConstructPanelContent()
|
||||
// UI Construction
|
||||
|
||||
protected override void ConstructPanelContent()
|
||||
{
|
||||
// hide the titlebar
|
||||
this.TitleBar.gameObject.SetActive(false);
|
||||
|
||||
buttonListDataHandler = new ButtonListHandler<Suggestion, ButtonCell>(scrollPool, GetEntries, SetCell, ShouldDisplay, OnCellClicked);
|
||||
|
||||
scrollPool = UIFactory.CreateScrollPool<ButtonCell>(this.uiContent, "AutoCompleter", out GameObject scrollObj,
|
||||
scrollPool = UIFactory.CreateScrollPool<ButtonCell>(this.ContentRoot, "AutoCompleter", out GameObject scrollObj,
|
||||
out GameObject scrollContent);
|
||||
scrollPool.Initialize(buttonListDataHandler);
|
||||
UIFactory.SetLayoutElement(scrollObj, flexibleHeight: 9999);
|
||||
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(scrollContent, true, false, true, false);
|
||||
|
||||
navigationTipRow = UIFactory.CreateHorizontalGroup(this.uiContent, "BottomRow", true, true, true, true, 0, new Vector4(2, 2, 2, 2));
|
||||
navigationTipRow = UIFactory.CreateHorizontalGroup(this.ContentRoot, "BottomRow", true, true, true, true, 0, new Vector4(2, 2, 2, 2));
|
||||
UIFactory.SetLayoutElement(navigationTipRow, minHeight: 20, flexibleWidth: 9999);
|
||||
UIFactory.CreateLabel(navigationTipRow, "HelpText", "Up/Down to select, Enter to use, Esc to close",
|
||||
TextAnchor.MiddleLeft, Color.grey, false, 13);
|
||||
|
@ -1,27 +1,20 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.Config;
|
||||
using System.Collections;
|
||||
using UnityExplorer.CSConsole;
|
||||
using UnityExplorer.UI.Widgets;
|
||||
using UniverseLib;
|
||||
using UniverseLib.UI;
|
||||
using UniverseLib.UI.Models;
|
||||
using UniverseLib.UI.Widgets;
|
||||
|
||||
namespace UnityExplorer.UI.Panels
|
||||
{
|
||||
public class CSConsolePanel : UIPanel
|
||||
public class CSConsolePanel : UEPanel
|
||||
{
|
||||
public override string Name => "C# Console";
|
||||
public override UIManager.Panels PanelType => UIManager.Panels.CSConsole;
|
||||
|
||||
public override int MinWidth => 750;
|
||||
public override int MinHeight => 300;
|
||||
public override Vector2 DefaultAnchorMin => new(0.4f, 0.175f);
|
||||
public override Vector2 DefaultAnchorMax => new(0.85f, 0.925f);
|
||||
|
||||
public InputFieldScroller InputScroller { get; private set; }
|
||||
public InputFieldRef Input => InputScroller.InputField;
|
||||
@ -41,6 +34,10 @@ namespace UnityExplorer.UI.Panels
|
||||
public Action<bool> OnAutoIndentToggled;
|
||||
public Action OnPanelResized;
|
||||
|
||||
public CSConsolePanel(UIBase owner) : base(owner)
|
||||
{
|
||||
}
|
||||
|
||||
private void InvokeOnValueChanged(string value)
|
||||
{
|
||||
if (value.Length == UniversalUI.MAX_INPUTFIELD_CHARS)
|
||||
@ -58,49 +55,41 @@ namespace UnityExplorer.UI.Panels
|
||||
|
||||
// UI Construction
|
||||
|
||||
public override void OnFinishResize(RectTransform panel)
|
||||
public override void OnFinishResize()
|
||||
{
|
||||
OnPanelResized?.Invoke();
|
||||
}
|
||||
|
||||
protected internal override void DoSetDefaultPosAndAnchors()
|
||||
{
|
||||
Rect.localPosition = Vector2.zero;
|
||||
Rect.pivot = new Vector2(0f, 1f);
|
||||
Rect.anchorMin = new Vector2(0.4f, 0.175f);
|
||||
Rect.anchorMax = new Vector2(0.85f, 0.925f);
|
||||
}
|
||||
|
||||
public override void ConstructPanelContent()
|
||||
protected override void ConstructPanelContent()
|
||||
{
|
||||
// Tools Row
|
||||
|
||||
var toolsRow = UIFactory.CreateHorizontalGroup(this.uiContent, "ToggleRow", false, false, true, true, 5, new Vector4(8, 8, 10, 5),
|
||||
GameObject toolsRow = UIFactory.CreateHorizontalGroup(this.ContentRoot, "ToggleRow", false, false, true, true, 5, new Vector4(8, 8, 10, 5),
|
||||
default, TextAnchor.MiddleLeft);
|
||||
UIFactory.SetLayoutElement(toolsRow, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999);
|
||||
|
||||
// Buttons
|
||||
|
||||
var compileButton = UIFactory.CreateButton(toolsRow, "CompileButton", "Compile", new Color(0.33f, 0.5f, 0.33f));
|
||||
ButtonRef compileButton = UIFactory.CreateButton(toolsRow, "CompileButton", "Compile", new Color(0.33f, 0.5f, 0.33f));
|
||||
UIFactory.SetLayoutElement(compileButton.Component.gameObject, minHeight: 28, minWidth: 130, flexibleHeight: 0);
|
||||
compileButton.ButtonText.fontSize = 15;
|
||||
compileButton.OnClick += () => { OnCompileClicked?.Invoke(); };
|
||||
|
||||
var resetButton = UIFactory.CreateButton(toolsRow, "ResetButton", "Reset", new Color(0.33f, 0.33f, 0.33f));
|
||||
ButtonRef resetButton = UIFactory.CreateButton(toolsRow, "ResetButton", "Reset", new Color(0.33f, 0.33f, 0.33f));
|
||||
UIFactory.SetLayoutElement(resetButton.Component.gameObject, minHeight: 28, minWidth: 80, flexibleHeight: 0);
|
||||
resetButton.ButtonText.fontSize = 15;
|
||||
resetButton.OnClick += () => { OnResetClicked?.Invoke(); };
|
||||
|
||||
// Help dropdown
|
||||
|
||||
var helpDrop = UIFactory.CreateDropdown(toolsRow, "HelpDropdown", out var dropdown, "Help", 14, null);
|
||||
GameObject helpDrop = UIFactory.CreateDropdown(toolsRow, "HelpDropdown", out Dropdown dropdown, "Help", 14, null);
|
||||
UIFactory.SetLayoutElement(helpDrop, minHeight: 25, minWidth: 100);
|
||||
HelpDropdown = dropdown;
|
||||
HelpDropdown.onValueChanged.AddListener((int val) => { this.OnHelpDropdownChanged?.Invoke(val); });
|
||||
|
||||
// Enable Ctrl+R toggle
|
||||
|
||||
var ctrlRToggleObj = UIFactory.CreateToggle(toolsRow, "CtrlRToggle", out var CtrlRToggle, out Text ctrlRToggleText);
|
||||
GameObject ctrlRToggleObj = UIFactory.CreateToggle(toolsRow, "CtrlRToggle", out Toggle CtrlRToggle, out Text ctrlRToggleText);
|
||||
UIFactory.SetLayoutElement(ctrlRToggleObj, minWidth: 150, flexibleWidth: 0, minHeight: 25);
|
||||
ctrlRToggleText.alignment = TextAnchor.UpperLeft;
|
||||
ctrlRToggleText.text = "Compile on Ctrl+R";
|
||||
@ -108,7 +97,7 @@ namespace UnityExplorer.UI.Panels
|
||||
|
||||
// Enable Suggestions toggle
|
||||
|
||||
var suggestToggleObj = UIFactory.CreateToggle(toolsRow, "SuggestionToggle", out var SuggestionsToggle, out Text suggestToggleText);
|
||||
GameObject suggestToggleObj = UIFactory.CreateToggle(toolsRow, "SuggestionToggle", out Toggle SuggestionsToggle, out Text suggestToggleText);
|
||||
UIFactory.SetLayoutElement(suggestToggleObj, minWidth: 120, flexibleWidth: 0, minHeight: 25);
|
||||
suggestToggleText.alignment = TextAnchor.UpperLeft;
|
||||
suggestToggleText.text = "Suggestions";
|
||||
@ -116,7 +105,7 @@ namespace UnityExplorer.UI.Panels
|
||||
|
||||
// Enable Auto-indent toggle
|
||||
|
||||
var autoIndentToggleObj = UIFactory.CreateToggle(toolsRow, "IndentToggle", out var AutoIndentToggle, out Text autoIndentToggleText);
|
||||
GameObject autoIndentToggleObj = UIFactory.CreateToggle(toolsRow, "IndentToggle", out Toggle AutoIndentToggle, out Text autoIndentToggleText);
|
||||
UIFactory.SetLayoutElement(autoIndentToggleObj, minWidth: 120, flexibleWidth: 0, minHeight: 25);
|
||||
autoIndentToggleText.alignment = TextAnchor.UpperLeft;
|
||||
autoIndentToggleText.text = "Auto-indent";
|
||||
@ -124,7 +113,7 @@ namespace UnityExplorer.UI.Panels
|
||||
|
||||
// Console Input
|
||||
|
||||
var inputArea = UIFactory.CreateUIObject("InputGroup", uiContent);
|
||||
GameObject inputArea = UIFactory.CreateUIObject("InputGroup", ContentRoot);
|
||||
UIFactory.SetLayoutElement(inputArea, flexibleWidth: 9999, flexibleHeight: 9999);
|
||||
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(inputArea, false, true, true, true);
|
||||
inputArea.AddComponent<Image>().color = Color.white;
|
||||
@ -132,8 +121,8 @@ namespace UnityExplorer.UI.Panels
|
||||
|
||||
// line numbers
|
||||
|
||||
var linesHolder = UIFactory.CreateUIObject("LinesHolder", inputArea);
|
||||
var linesRect = linesHolder.GetComponent<RectTransform>();
|
||||
GameObject linesHolder = UIFactory.CreateUIObject("LinesHolder", inputArea);
|
||||
RectTransform linesRect = linesHolder.GetComponent<RectTransform>();
|
||||
linesRect.pivot = new Vector2(0, 1);
|
||||
linesRect.anchorMin = new Vector2(0, 0);
|
||||
linesRect.anchorMax = new Vector2(0, 1);
|
||||
@ -149,10 +138,10 @@ namespace UnityExplorer.UI.Panels
|
||||
|
||||
int fontSize = 16;
|
||||
|
||||
var inputObj = UIFactory.CreateScrollInputField(inputArea, "ConsoleInput", ConsoleController.STARTUP_TEXT,
|
||||
out var inputScroller, fontSize);
|
||||
GameObject inputObj = UIFactory.CreateScrollInputField(inputArea, "ConsoleInput", ConsoleController.STARTUP_TEXT,
|
||||
out InputFieldScroller inputScroller, fontSize);
|
||||
InputScroller = inputScroller;
|
||||
ConsoleController.defaultInputFieldAlpha = Input.Component.selectionColor.a;
|
||||
ConsoleController.DefaultInputFieldAlpha = Input.Component.selectionColor.a;
|
||||
Input.OnValueChanged += InvokeOnValueChanged;
|
||||
|
||||
// move line number text with input field
|
||||
@ -173,8 +162,8 @@ namespace UnityExplorer.UI.Panels
|
||||
Input.PlaceholderText.fontSize = fontSize;
|
||||
|
||||
// Lexer highlight text overlay
|
||||
var highlightTextObj = UIFactory.CreateUIObject("HighlightText", InputText.gameObject);
|
||||
var highlightTextRect = highlightTextObj.GetComponent<RectTransform>();
|
||||
GameObject highlightTextObj = UIFactory.CreateUIObject("HighlightText", InputText.gameObject);
|
||||
RectTransform highlightTextRect = highlightTextObj.GetComponent<RectTransform>();
|
||||
highlightTextRect.pivot = new Vector2(0, 1);
|
||||
highlightTextRect.anchorMin = Vector2.zero;
|
||||
highlightTextRect.anchorMax = Vector2.one;
|
||||
|
@ -1,29 +1,19 @@
|
||||
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;
|
||||
using UniverseLib.UI;
|
||||
|
||||
namespace UnityExplorer.UI.Panels
|
||||
{
|
||||
public class ClipboardPanel : UIPanel
|
||||
public class ClipboardPanel : UEPanel
|
||||
{
|
||||
public static object Current { get; private set; }
|
||||
|
||||
public override UIManager.Panels PanelType => UIManager.Panels.Clipboard;
|
||||
public override string Name => "Clipboard";
|
||||
public override UIManager.Panels PanelType => UIManager.Panels.Clipboard;
|
||||
|
||||
public override int MinWidth => 500;
|
||||
public override int MinHeight => 95;
|
||||
public override Vector2 DefaultAnchorMin => new(0.1f, 0.05f);
|
||||
public override Vector2 DefaultAnchorMax => new(0.4f, 0.15f);
|
||||
|
||||
public override bool CanDragAndResize => true;
|
||||
public override bool NavButtonWanted => true;
|
||||
public override bool ShouldSaveActiveState => true;
|
||||
@ -31,6 +21,10 @@ namespace UnityExplorer.UI.Panels
|
||||
|
||||
private static Text CurrentPasteLabel;
|
||||
|
||||
public ClipboardPanel(UIBase owner) : base(owner)
|
||||
{
|
||||
}
|
||||
|
||||
public static void Copy(object obj)
|
||||
{
|
||||
Current = obj;
|
||||
@ -41,14 +35,14 @@ namespace UnityExplorer.UI.Panels
|
||||
public static bool TryPaste(Type targetType, out object paste)
|
||||
{
|
||||
paste = Current;
|
||||
var pasteType = Current?.GetActualType();
|
||||
Type 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;
|
||||
}
|
||||
@ -74,35 +68,35 @@ namespace UnityExplorer.UI.Panels
|
||||
|
||||
InspectorManager.Inspect(Current);
|
||||
}
|
||||
|
||||
protected internal override void DoSetDefaultPosAndAnchors()
|
||||
|
||||
public override void SetDefaultSizeAndPosition()
|
||||
{
|
||||
base.SetDefaultSizeAndPosition();
|
||||
|
||||
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()
|
||||
protected 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));
|
||||
GameObject firstRow = UIFactory.CreateHorizontalGroup(ContentRoot, "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);
|
||||
Text 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");
|
||||
UniverseLib.UI.Models.ButtonRef 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,
|
||||
GameObject currentPasteHolder = UIFactory.CreateHorizontalGroup(ContentRoot, "SecondRow", false, false, true, true, 0,
|
||||
new(2, 2, 2, 2), childAlignment: TextAnchor.UpperCenter);
|
||||
|
||||
// Actual current paste info label
|
||||
@ -111,7 +105,7 @@ namespace UnityExplorer.UI.Panels
|
||||
UpdateCurrentPasteInfo();
|
||||
|
||||
// Inspect button
|
||||
var inspectButton = UIFactory.CreateButton(currentPasteHolder, "InspectButton", "Inspect");
|
||||
UniverseLib.UI.Models.ButtonRef inspectButton = UIFactory.CreateButton(currentPasteHolder, "InspectButton", "Inspect");
|
||||
UIFactory.SetLayoutElement(inspectButton.Component.gameObject, minHeight: 25, flexibleHeight: 0, minWidth: 80, flexibleWidth: 0);
|
||||
inspectButton.OnClick += InspectClipboard;
|
||||
}
|
||||
|
392
src/UI/Panels/FreeCamPanel.cs
Normal file
392
src/UI/Panels/FreeCamPanel.cs
Normal file
@ -0,0 +1,392 @@
|
||||
using UniverseLib.Input;
|
||||
using UniverseLib.UI;
|
||||
using UniverseLib.UI.Models;
|
||||
#if UNHOLLOWER
|
||||
using UnhollowerRuntimeLib;
|
||||
#endif
|
||||
#if INTEROP
|
||||
using Il2CppInterop.Runtime.Injection;
|
||||
#endif
|
||||
|
||||
namespace UnityExplorer.UI.Panels
|
||||
{
|
||||
internal class FreeCamPanel : UEPanel
|
||||
{
|
||||
public FreeCamPanel(UIBase owner) : base(owner)
|
||||
{
|
||||
}
|
||||
|
||||
public override string Name => "Freecam";
|
||||
public override UIManager.Panels PanelType => UIManager.Panels.Freecam;
|
||||
public override int MinWidth => 400;
|
||||
public override int MinHeight => 320;
|
||||
public override Vector2 DefaultAnchorMin => new(0.4f, 0.4f);
|
||||
public override Vector2 DefaultAnchorMax => new(0.6f, 0.6f);
|
||||
public override bool NavButtonWanted => true;
|
||||
public override bool ShouldSaveActiveState => true;
|
||||
|
||||
internal static bool inFreeCamMode;
|
||||
internal static bool usingGameCamera;
|
||||
internal static Camera ourCamera;
|
||||
internal static Camera lastMainCamera;
|
||||
internal static FreeCamBehaviour freeCamScript;
|
||||
|
||||
internal static float desiredMoveSpeed = 10f;
|
||||
|
||||
internal static Vector3 originalCameraPosition;
|
||||
internal static Quaternion originalCameraRotation;
|
||||
|
||||
internal static Vector3? currentUserCameraPosition;
|
||||
internal static Quaternion? currentUserCameraRotation;
|
||||
|
||||
internal static Vector3 previousMousePosition;
|
||||
|
||||
internal static Vector3 lastSetCameraPosition;
|
||||
|
||||
static ButtonRef startStopButton;
|
||||
static Toggle useGameCameraToggle;
|
||||
static InputFieldRef positionInput;
|
||||
static InputFieldRef moveSpeedInput;
|
||||
static ButtonRef inspectButton;
|
||||
|
||||
internal static void BeginFreecam()
|
||||
{
|
||||
inFreeCamMode = true;
|
||||
|
||||
previousMousePosition = InputManager.MousePosition;
|
||||
|
||||
CacheMainCamera();
|
||||
SetupFreeCamera();
|
||||
|
||||
inspectButton.GameObject.SetActive(true);
|
||||
}
|
||||
|
||||
static void CacheMainCamera()
|
||||
{
|
||||
Camera currentMain = Camera.main;
|
||||
if (currentMain)
|
||||
{
|
||||
lastMainCamera = currentMain;
|
||||
originalCameraPosition = currentMain.transform.position;
|
||||
originalCameraRotation = currentMain.transform.rotation;
|
||||
|
||||
if (currentUserCameraPosition == null)
|
||||
{
|
||||
currentUserCameraPosition = currentMain.transform.position;
|
||||
currentUserCameraRotation = currentMain.transform.rotation;
|
||||
}
|
||||
}
|
||||
else
|
||||
originalCameraRotation = Quaternion.identity;
|
||||
}
|
||||
|
||||
static void SetupFreeCamera()
|
||||
{
|
||||
if (useGameCameraToggle.isOn)
|
||||
{
|
||||
if (!lastMainCamera)
|
||||
{
|
||||
ExplorerCore.LogWarning($"There is no previous Camera found, reverting to default Free Cam.");
|
||||
useGameCameraToggle.isOn = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
usingGameCamera = true;
|
||||
ourCamera = lastMainCamera;
|
||||
}
|
||||
}
|
||||
|
||||
if (!useGameCameraToggle.isOn)
|
||||
{
|
||||
usingGameCamera = false;
|
||||
|
||||
if (lastMainCamera)
|
||||
lastMainCamera.enabled = false;
|
||||
}
|
||||
|
||||
if (!ourCamera)
|
||||
{
|
||||
ourCamera = new GameObject("UE_Freecam").AddComponent<Camera>();
|
||||
ourCamera.gameObject.tag = "MainCamera";
|
||||
GameObject.DontDestroyOnLoad(ourCamera.gameObject);
|
||||
ourCamera.gameObject.hideFlags = HideFlags.HideAndDontSave;
|
||||
}
|
||||
|
||||
if (!freeCamScript)
|
||||
freeCamScript = ourCamera.gameObject.AddComponent<FreeCamBehaviour>();
|
||||
|
||||
ourCamera.transform.position = (Vector3)currentUserCameraPosition;
|
||||
ourCamera.transform.rotation = (Quaternion)currentUserCameraRotation;
|
||||
|
||||
ourCamera.gameObject.SetActive(true);
|
||||
ourCamera.enabled = true;
|
||||
}
|
||||
|
||||
internal static void EndFreecam()
|
||||
{
|
||||
inFreeCamMode = false;
|
||||
|
||||
if (usingGameCamera)
|
||||
{
|
||||
ourCamera = null;
|
||||
|
||||
if (lastMainCamera)
|
||||
{
|
||||
lastMainCamera.transform.position = originalCameraPosition;
|
||||
lastMainCamera.transform.rotation = originalCameraRotation;
|
||||
}
|
||||
}
|
||||
|
||||
if (ourCamera)
|
||||
ourCamera.gameObject.SetActive(false);
|
||||
else
|
||||
inspectButton.GameObject.SetActive(false);
|
||||
|
||||
if (freeCamScript)
|
||||
{
|
||||
GameObject.Destroy(freeCamScript);
|
||||
freeCamScript = null;
|
||||
}
|
||||
|
||||
if (lastMainCamera)
|
||||
lastMainCamera.enabled = true;
|
||||
}
|
||||
|
||||
static void SetCameraPosition(Vector3 pos)
|
||||
{
|
||||
if (!ourCamera || lastSetCameraPosition == pos)
|
||||
return;
|
||||
|
||||
ourCamera.transform.position = pos;
|
||||
lastSetCameraPosition = pos;
|
||||
}
|
||||
|
||||
internal static void UpdatePositionInput()
|
||||
{
|
||||
if (!ourCamera)
|
||||
return;
|
||||
|
||||
if (positionInput.Component.isFocused)
|
||||
return;
|
||||
|
||||
lastSetCameraPosition = ourCamera.transform.position;
|
||||
positionInput.Text = ParseUtility.ToStringForInput<Vector3>(lastSetCameraPosition);
|
||||
}
|
||||
|
||||
// ~~~~~~~~ UI construction / callbacks ~~~~~~~~
|
||||
|
||||
protected override void ConstructPanelContent()
|
||||
{
|
||||
startStopButton = UIFactory.CreateButton(ContentRoot, "ToggleButton", "Freecam");
|
||||
UIFactory.SetLayoutElement(startStopButton.GameObject, minWidth: 150, minHeight: 25, flexibleWidth: 9999);
|
||||
startStopButton.OnClick += StartStopButton_OnClick;
|
||||
SetToggleButtonState();
|
||||
|
||||
AddSpacer(5);
|
||||
|
||||
GameObject toggleObj = UIFactory.CreateToggle(ContentRoot, "UseGameCameraToggle", out useGameCameraToggle, out Text toggleText);
|
||||
UIFactory.SetLayoutElement(toggleObj, minHeight: 25, flexibleWidth: 9999);
|
||||
useGameCameraToggle.onValueChanged.AddListener(OnUseGameCameraToggled);
|
||||
useGameCameraToggle.isOn = false;
|
||||
toggleText.text = "Use Game Camera?";
|
||||
|
||||
AddSpacer(5);
|
||||
|
||||
GameObject posRow = AddInputField("Position", "Freecam Pos:", "eg. 0 0 0", out positionInput, PositionInput_OnEndEdit);
|
||||
|
||||
ButtonRef resetPosButton = UIFactory.CreateButton(posRow, "ResetButton", "Reset");
|
||||
UIFactory.SetLayoutElement(resetPosButton.GameObject, minWidth: 70, minHeight: 25);
|
||||
resetPosButton.OnClick += OnResetPosButtonClicked;
|
||||
|
||||
AddSpacer(5);
|
||||
|
||||
AddInputField("MoveSpeed", "Move Speed:", "Default: 1", out moveSpeedInput, MoveSpeedInput_OnEndEdit);
|
||||
moveSpeedInput.Text = desiredMoveSpeed.ToString();
|
||||
|
||||
AddSpacer(5);
|
||||
|
||||
string instructions = @"Controls:
|
||||
- WASD / Arrows: Movement
|
||||
- Space / PgUp: Move up
|
||||
- LeftCtrl / PgDown: Move down
|
||||
- Right Mouse Button: Free look
|
||||
- Shift: Super speed";
|
||||
|
||||
Text instructionsText = UIFactory.CreateLabel(ContentRoot, "Instructions", instructions, TextAnchor.UpperLeft);
|
||||
UIFactory.SetLayoutElement(instructionsText.gameObject, flexibleWidth: 9999, flexibleHeight: 9999);
|
||||
|
||||
AddSpacer(5);
|
||||
|
||||
inspectButton = UIFactory.CreateButton(ContentRoot, "InspectButton", "Inspect Free Camera");
|
||||
UIFactory.SetLayoutElement(inspectButton.GameObject, flexibleWidth: 9999, minHeight: 25);
|
||||
inspectButton.OnClick += () => { InspectorManager.Inspect(ourCamera); };
|
||||
inspectButton.GameObject.SetActive(false);
|
||||
|
||||
AddSpacer(5);
|
||||
}
|
||||
|
||||
void AddSpacer(int height)
|
||||
{
|
||||
GameObject obj = UIFactory.CreateUIObject("Spacer", ContentRoot);
|
||||
UIFactory.SetLayoutElement(obj, minHeight: height, flexibleHeight: 0);
|
||||
}
|
||||
|
||||
GameObject AddInputField(string name, string labelText, string placeHolder, out InputFieldRef inputField, Action<string> onInputEndEdit)
|
||||
{
|
||||
GameObject row = UIFactory.CreateHorizontalGroup(ContentRoot, $"{name}_Group", false, false, true, true, 3, default, new(1, 1, 1, 0));
|
||||
|
||||
Text posLabel = UIFactory.CreateLabel(row, $"{name}_Label", labelText);
|
||||
UIFactory.SetLayoutElement(posLabel.gameObject, minWidth: 100, minHeight: 25);
|
||||
|
||||
inputField = UIFactory.CreateInputField(row, $"{name}_Input", placeHolder);
|
||||
UIFactory.SetLayoutElement(inputField.GameObject, minWidth: 125, minHeight: 25, flexibleWidth: 9999);
|
||||
inputField.Component.GetOnEndEdit().AddListener(onInputEndEdit);
|
||||
|
||||
return row;
|
||||
}
|
||||
|
||||
void StartStopButton_OnClick()
|
||||
{
|
||||
EventSystemHelper.SetSelectedGameObject(null);
|
||||
|
||||
if (inFreeCamMode)
|
||||
EndFreecam();
|
||||
else
|
||||
BeginFreecam();
|
||||
|
||||
SetToggleButtonState();
|
||||
}
|
||||
|
||||
void SetToggleButtonState()
|
||||
{
|
||||
if (inFreeCamMode)
|
||||
{
|
||||
RuntimeHelper.SetColorBlockAuto(startStopButton.Component, new(0.4f, 0.2f, 0.2f));
|
||||
startStopButton.ButtonText.text = "End Freecam";
|
||||
}
|
||||
else
|
||||
{
|
||||
RuntimeHelper.SetColorBlockAuto(startStopButton.Component, new(0.2f, 0.4f, 0.2f));
|
||||
startStopButton.ButtonText.text = "Begin Freecam";
|
||||
}
|
||||
}
|
||||
|
||||
void OnUseGameCameraToggled(bool value)
|
||||
{
|
||||
EventSystemHelper.SetSelectedGameObject(null);
|
||||
|
||||
if (!inFreeCamMode)
|
||||
return;
|
||||
|
||||
EndFreecam();
|
||||
BeginFreecam();
|
||||
}
|
||||
|
||||
void OnResetPosButtonClicked()
|
||||
{
|
||||
currentUserCameraPosition = originalCameraPosition;
|
||||
currentUserCameraRotation = originalCameraRotation;
|
||||
|
||||
if (inFreeCamMode && ourCamera)
|
||||
{
|
||||
ourCamera.transform.position = (Vector3)currentUserCameraPosition;
|
||||
ourCamera.transform.rotation = (Quaternion)currentUserCameraRotation;
|
||||
}
|
||||
|
||||
positionInput.Text = ParseUtility.ToStringForInput<Vector3>(originalCameraPosition);
|
||||
}
|
||||
|
||||
void PositionInput_OnEndEdit(string input)
|
||||
{
|
||||
EventSystemHelper.SetSelectedGameObject(null);
|
||||
|
||||
if (!ParseUtility.TryParse(input, out Vector3 parsed, out Exception parseEx))
|
||||
{
|
||||
ExplorerCore.LogWarning($"Could not parse position to Vector3: {parseEx.ReflectionExToString()}");
|
||||
UpdatePositionInput();
|
||||
return;
|
||||
}
|
||||
|
||||
SetCameraPosition(parsed);
|
||||
}
|
||||
|
||||
void MoveSpeedInput_OnEndEdit(string input)
|
||||
{
|
||||
EventSystemHelper.SetSelectedGameObject(null);
|
||||
|
||||
if (!ParseUtility.TryParse(input, out float parsed, out Exception parseEx))
|
||||
{
|
||||
ExplorerCore.LogWarning($"Could not parse value: {parseEx.ReflectionExToString()}");
|
||||
moveSpeedInput.Text = desiredMoveSpeed.ToString();
|
||||
return;
|
||||
}
|
||||
|
||||
desiredMoveSpeed = parsed;
|
||||
}
|
||||
}
|
||||
|
||||
internal class FreeCamBehaviour : MonoBehaviour
|
||||
{
|
||||
#if CPP
|
||||
static FreeCamBehaviour()
|
||||
{
|
||||
ClassInjector.RegisterTypeInIl2Cpp<FreeCamBehaviour>();
|
||||
}
|
||||
|
||||
public FreeCamBehaviour(IntPtr ptr) : base(ptr) { }
|
||||
#endif
|
||||
|
||||
internal void Update()
|
||||
{
|
||||
if (FreeCamPanel.inFreeCamMode)
|
||||
{
|
||||
if (!FreeCamPanel.ourCamera)
|
||||
{
|
||||
FreeCamPanel.EndFreecam();
|
||||
return;
|
||||
}
|
||||
|
||||
Transform transform = FreeCamPanel.ourCamera.transform;
|
||||
|
||||
FreeCamPanel.currentUserCameraPosition = transform.position;
|
||||
FreeCamPanel.currentUserCameraRotation = transform.rotation;
|
||||
|
||||
float moveSpeed = FreeCamPanel.desiredMoveSpeed * Time.deltaTime;
|
||||
|
||||
if (InputManager.GetKey(KeyCode.LeftShift) || InputManager.GetKey(KeyCode.RightShift))
|
||||
moveSpeed *= 10f;
|
||||
|
||||
if (InputManager.GetKey(KeyCode.LeftArrow) || InputManager.GetKey(KeyCode.A))
|
||||
transform.position += transform.right * -1 * moveSpeed;
|
||||
|
||||
if (InputManager.GetKey(KeyCode.RightArrow) || InputManager.GetKey(KeyCode.D))
|
||||
transform.position += transform.right * moveSpeed;
|
||||
|
||||
if (InputManager.GetKey(KeyCode.UpArrow) || InputManager.GetKey(KeyCode.W))
|
||||
transform.position += transform.forward * moveSpeed;
|
||||
|
||||
if (InputManager.GetKey(KeyCode.DownArrow) || InputManager.GetKey(KeyCode.S))
|
||||
transform.position += transform.forward * -1 * moveSpeed;
|
||||
|
||||
if (InputManager.GetKey(KeyCode.Space) || InputManager.GetKey(KeyCode.PageUp))
|
||||
transform.position += transform.up * moveSpeed;
|
||||
|
||||
if (InputManager.GetKey(KeyCode.LeftControl) || InputManager.GetKey(KeyCode.PageDown))
|
||||
transform.position += transform.up * -1 * moveSpeed;
|
||||
|
||||
if (InputManager.GetMouseButton(1))
|
||||
{
|
||||
Vector3 mouseDelta = InputManager.MousePosition - FreeCamPanel.previousMousePosition;
|
||||
|
||||
float newRotationX = transform.localEulerAngles.y + mouseDelta.x * 0.3f;
|
||||
float newRotationY = transform.localEulerAngles.x - mouseDelta.y * 0.3f;
|
||||
transform.localEulerAngles = new Vector3(newRotationY, newRotationX, 0f);
|
||||
}
|
||||
|
||||
FreeCamPanel.UpdatePositionInput();
|
||||
|
||||
FreeCamPanel.previousMousePosition = InputManager.MousePosition;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,203 +1,102 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.Config;
|
||||
using UnityExplorer.Hooks;
|
||||
using UnityExplorer.Hooks;
|
||||
using UnityExplorer.UI.Widgets;
|
||||
using UnityExplorer.UI.Widgets.AutoComplete;
|
||||
using UniverseLib.UI;
|
||||
using UniverseLib.UI.Models;
|
||||
using UniverseLib.UI.Widgets;
|
||||
using UniverseLib.UI.Widgets.ScrollView;
|
||||
|
||||
namespace UnityExplorer.UI.Panels
|
||||
{
|
||||
public class HookManagerPanel : UIPanel
|
||||
public class HookManagerPanel : UEPanel
|
||||
{
|
||||
public static HookManagerPanel Instance { get; private set; }
|
||||
|
||||
public enum Pages
|
||||
{
|
||||
CurrentHooks,
|
||||
ClassMethodSelector,
|
||||
HookSourceEditor
|
||||
HookSourceEditor,
|
||||
GenericArgsSelector,
|
||||
}
|
||||
|
||||
public static HookCreator hookCreator;
|
||||
public static HookList hookList;
|
||||
public static GenericConstructorWidget genericArgsHandler;
|
||||
|
||||
// Panel
|
||||
public override UIManager.Panels PanelType => UIManager.Panels.HookManager;
|
||||
|
||||
public override string Name => "Hooks";
|
||||
public override int MinWidth => 500;
|
||||
public override int MinHeight => 600;
|
||||
public override bool ShowByDefault => false;
|
||||
public override int MinWidth => 400;
|
||||
public override int MinHeight => 400;
|
||||
public override Vector2 DefaultAnchorMin => new(0.5f, 0.5f);
|
||||
public override Vector2 DefaultAnchorMax => new(0.5f, 0.5f);
|
||||
|
||||
public Pages CurrentPage { get; private set; } = Pages.CurrentHooks;
|
||||
public Pages CurrentPage { get; private set; } = Pages.ClassMethodSelector;
|
||||
|
||||
private GameObject currentHooksPanel;
|
||||
public ScrollPool<HookCell> HooksScrollPool;
|
||||
private InputFieldRef classSelectorInputField;
|
||||
|
||||
private GameObject addHooksPanel;
|
||||
public ScrollPool<AddHookCell> AddHooksScrollPool;
|
||||
private Text addHooksLabel;
|
||||
private InputFieldRef AddHooksMethodFilterInput;
|
||||
|
||||
private GameObject editorPanel;
|
||||
public InputFieldScroller EditorInputScroller { get; private set; }
|
||||
public InputFieldRef EditorInput => EditorInputScroller.InputField;
|
||||
public Text EditorInputText { get; private set; }
|
||||
public Text EditorHighlightText { get; private set; }
|
||||
|
||||
private void OnClassInputAddClicked()
|
||||
public HookManagerPanel(UIBase owner) : base(owner)
|
||||
{
|
||||
HookManager.Instance.OnClassSelectedForHooks(this.classSelectorInputField.Text);
|
||||
}
|
||||
|
||||
public void SetAddHooksLabelType(string typeText) => addHooksLabel.text = $"Adding hooks to: {typeText}";
|
||||
|
||||
public void SetPage(Pages page)
|
||||
{
|
||||
switch (page)
|
||||
{
|
||||
case Pages.CurrentHooks:
|
||||
currentHooksPanel.SetActive(true);
|
||||
addHooksPanel.SetActive(false);
|
||||
editorPanel.SetActive(false);
|
||||
break;
|
||||
case Pages.ClassMethodSelector:
|
||||
currentHooksPanel.SetActive(false);
|
||||
addHooksPanel.SetActive(true);
|
||||
editorPanel.SetActive(false);
|
||||
HookCreator.AddHooksRoot.SetActive(true);
|
||||
HookCreator.EditorRoot.SetActive(false);
|
||||
genericArgsHandler.UIRoot.SetActive(false);
|
||||
break;
|
||||
|
||||
case Pages.HookSourceEditor:
|
||||
currentHooksPanel.SetActive(false);
|
||||
addHooksPanel.SetActive(false);
|
||||
editorPanel.SetActive(true);
|
||||
HookCreator.AddHooksRoot.SetActive(false);
|
||||
HookCreator.EditorRoot.SetActive(true);
|
||||
genericArgsHandler.UIRoot.SetActive(false);
|
||||
break;
|
||||
|
||||
case Pages.GenericArgsSelector:
|
||||
HookCreator.AddHooksRoot.SetActive(false);
|
||||
HookCreator.EditorRoot.SetActive(false);
|
||||
genericArgsHandler.UIRoot.SetActive(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void ResetMethodFilter() => AddHooksMethodFilterInput.Text = string.Empty;
|
||||
|
||||
public override void ConstructPanelContent()
|
||||
public override void SetDefaultSizeAndPosition()
|
||||
{
|
||||
// ~~~~~~~~~ Active hooks scroll pool
|
||||
base.SetDefaultSizeAndPosition();
|
||||
|
||||
currentHooksPanel = UIFactory.CreateUIObject("CurrentHooksPanel", this.uiContent);
|
||||
UIFactory.SetLayoutElement(currentHooksPanel, flexibleHeight: 9999, flexibleWidth: 9999);
|
||||
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(currentHooksPanel, true, true, true, true);
|
||||
|
||||
var addRow = UIFactory.CreateHorizontalGroup(currentHooksPanel, "AddRow", false, true, true, true, 4,
|
||||
new Vector4(2, 2, 2, 2), new Color(0.2f, 0.2f, 0.2f));
|
||||
UIFactory.SetLayoutElement(addRow, minHeight: 30, flexibleWidth: 9999);
|
||||
|
||||
classSelectorInputField = UIFactory.CreateInputField(addRow, "ClassInput", "Enter a class to add hooks to...");
|
||||
UIFactory.SetLayoutElement(classSelectorInputField.Component.gameObject, flexibleWidth: 9999);
|
||||
new TypeCompleter(typeof(object), classSelectorInputField, true, false);
|
||||
|
||||
var addButton = UIFactory.CreateButton(addRow, "AddButton", "Add Hooks");
|
||||
UIFactory.SetLayoutElement(addButton.Component.gameObject, minWidth: 100, minHeight: 25);
|
||||
addButton.OnClick += OnClassInputAddClicked;
|
||||
|
||||
var hooksLabel = UIFactory.CreateLabel(currentHooksPanel, "HooksLabel", "Current Hooks", TextAnchor.MiddleCenter);
|
||||
UIFactory.SetLayoutElement(hooksLabel.gameObject, minHeight: 30, flexibleWidth: 9999);
|
||||
|
||||
HooksScrollPool = UIFactory.CreateScrollPool<HookCell>(currentHooksPanel, "HooksScrollPool",
|
||||
out GameObject hooksScroll, out GameObject hooksContent);
|
||||
UIFactory.SetLayoutElement(hooksScroll, flexibleHeight: 9999);
|
||||
HooksScrollPool.Initialize(HookManager.Instance);
|
||||
|
||||
// ~~~~~~~~~ Add hooks panel
|
||||
|
||||
addHooksPanel = UIFactory.CreateUIObject("AddHooksPanel", this.uiContent);
|
||||
UIFactory.SetLayoutElement(addHooksPanel, flexibleHeight: 9999, flexibleWidth: 9999);
|
||||
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(addHooksPanel, true, true, true, true);
|
||||
|
||||
addHooksLabel = UIFactory.CreateLabel(addHooksPanel, "AddLabel", "NOT SET", TextAnchor.MiddleCenter);
|
||||
UIFactory.SetLayoutElement(addHooksLabel.gameObject, minHeight: 30, minWidth: 100, flexibleWidth: 9999);
|
||||
|
||||
var buttonRow = UIFactory.CreateHorizontalGroup(addHooksPanel, "ButtonRow", false, false, true, true, 5);
|
||||
UIFactory.SetLayoutElement(buttonRow, minHeight: 25, flexibleWidth: 9999);
|
||||
|
||||
var doneButton = UIFactory.CreateButton(buttonRow, "DoneButton", "Done", new Color(0.2f, 0.3f, 0.2f));
|
||||
UIFactory.SetLayoutElement(doneButton.Component.gameObject, minHeight: 25, flexibleWidth: 9999);
|
||||
doneButton.OnClick += HookManager.Instance.DoneAddingHooks;
|
||||
|
||||
AddHooksMethodFilterInput = UIFactory.CreateInputField(addHooksPanel, "FilterInputField", "Filter method names...");
|
||||
UIFactory.SetLayoutElement(AddHooksMethodFilterInput.Component.gameObject, minHeight: 30, flexibleWidth: 9999);
|
||||
AddHooksMethodFilterInput.OnValueChanged += HookManager.Instance.OnAddHookFilterInputChanged;
|
||||
|
||||
AddHooksScrollPool = UIFactory.CreateScrollPool<AddHookCell>(addHooksPanel, "MethodAddScrollPool",
|
||||
out GameObject addScrollRoot, out GameObject addContent);
|
||||
UIFactory.SetLayoutElement(addScrollRoot, flexibleHeight: 9999);
|
||||
AddHooksScrollPool.Initialize(HookManager.Instance);
|
||||
|
||||
addHooksPanel.gameObject.SetActive(false);
|
||||
|
||||
// ~~~~~~~~~ Hook source editor panel
|
||||
|
||||
editorPanel = UIFactory.CreateUIObject("HookSourceEditor", this.uiContent);
|
||||
UIFactory.SetLayoutElement(editorPanel, flexibleHeight: 9999, flexibleWidth: 9999);
|
||||
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(editorPanel, true, true, true, true);
|
||||
|
||||
var editorLabel = UIFactory.CreateLabel(editorPanel,
|
||||
"EditorLabel",
|
||||
"Edit Harmony patch source as desired. Accepted method names are Prefix, Postfix, Finalizer and Transpiler (can define multiple).\n\n" +
|
||||
"Hooks are temporary! Please copy the source into your IDE to avoid losing work if you wish to keep it!",
|
||||
TextAnchor.MiddleLeft);
|
||||
UIFactory.SetLayoutElement(editorLabel.gameObject, minHeight: 25, flexibleWidth: 9999);
|
||||
|
||||
var editorButtonRow = UIFactory.CreateHorizontalGroup(editorPanel, "ButtonRow", false, false, true, true, 5);
|
||||
UIFactory.SetLayoutElement(editorButtonRow, minHeight: 25, flexibleWidth: 9999);
|
||||
|
||||
var editorSaveButton = UIFactory.CreateButton(editorButtonRow, "DoneButton", "Save and Return", new Color(0.2f, 0.3f, 0.2f));
|
||||
UIFactory.SetLayoutElement(editorSaveButton.Component.gameObject, minHeight: 25, flexibleWidth: 9999);
|
||||
editorSaveButton.OnClick += HookManager.Instance.EditorInputSave;
|
||||
|
||||
var editorDoneButton = UIFactory.CreateButton(editorButtonRow, "DoneButton", "Cancel and Return", new Color(0.2f, 0.2f, 0.2f));
|
||||
UIFactory.SetLayoutElement(editorDoneButton.Component.gameObject, minHeight: 25, flexibleWidth: 9999);
|
||||
editorDoneButton.OnClick += HookManager.Instance.EditorInputCancel;
|
||||
|
||||
int fontSize = 16;
|
||||
var inputObj = UIFactory.CreateScrollInputField(editorPanel, "EditorInput", "", out var inputScroller, fontSize);
|
||||
EditorInputScroller = inputScroller;
|
||||
EditorInput.OnValueChanged += HookManager.Instance.OnEditorInputChanged;
|
||||
|
||||
EditorInputText = EditorInput.Component.textComponent;
|
||||
EditorInputText.supportRichText = false;
|
||||
EditorInputText.color = Color.clear;
|
||||
EditorInput.Component.customCaretColor = true;
|
||||
EditorInput.Component.caretColor = Color.white;
|
||||
EditorInput.PlaceholderText.fontSize = fontSize;
|
||||
|
||||
// Lexer highlight text overlay
|
||||
var highlightTextObj = UIFactory.CreateUIObject("HighlightText", EditorInputText.gameObject);
|
||||
var highlightTextRect = highlightTextObj.GetComponent<RectTransform>();
|
||||
highlightTextRect.pivot = new Vector2(0, 1);
|
||||
highlightTextRect.anchorMin = Vector2.zero;
|
||||
highlightTextRect.anchorMax = Vector2.one;
|
||||
highlightTextRect.offsetMin = Vector2.zero;
|
||||
highlightTextRect.offsetMax = Vector2.zero;
|
||||
|
||||
EditorHighlightText = highlightTextObj.AddComponent<Text>();
|
||||
EditorHighlightText.color = Color.white;
|
||||
EditorHighlightText.supportRichText = true;
|
||||
EditorHighlightText.fontSize = fontSize;
|
||||
|
||||
// Set fonts
|
||||
EditorInputText.font = UniversalUI.ConsoleFont;
|
||||
EditorInput.PlaceholderText.font = UniversalUI.ConsoleFont;
|
||||
EditorHighlightText.font = UniversalUI.ConsoleFont;
|
||||
|
||||
editorPanel.SetActive(false);
|
||||
}
|
||||
|
||||
protected internal override void DoSetDefaultPosAndAnchors()
|
||||
{
|
||||
this.Rect.anchorMin = new Vector2(0.5f, 0.5f);
|
||||
this.Rect.anchorMax = new Vector2(0.5f, 0.5f);
|
||||
this.Rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, MinWidth);
|
||||
this.Rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, MinHeight);
|
||||
}
|
||||
|
||||
protected override void ConstructPanelContent()
|
||||
{
|
||||
Instance = this;
|
||||
hookList = new();
|
||||
hookCreator = new();
|
||||
genericArgsHandler = new();
|
||||
|
||||
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(ContentRoot, true, false);
|
||||
|
||||
// GameObject baseHoriGroup = UIFactory.CreateHorizontalGroup(ContentRoot, "HoriGroup", true, true, true, true);
|
||||
// UIFactory.SetLayoutElement(baseHoriGroup, flexibleWidth: 9999, flexibleHeight: 9999);
|
||||
|
||||
// // Left Group
|
||||
|
||||
//GameObject leftGroup = UIFactory.CreateVerticalGroup(ContentRoot, "LeftGroup", true, true, true, true);
|
||||
UIFactory.SetLayoutElement(ContentRoot.gameObject, minWidth: 300, flexibleWidth: 9999, flexibleHeight: 9999);
|
||||
|
||||
hookList.ConstructUI(ContentRoot);
|
||||
|
||||
// // Right Group
|
||||
|
||||
//GameObject rightGroup = UIFactory.CreateVerticalGroup(ContentRoot, "RightGroup", true, true, true, true);
|
||||
UIFactory.SetLayoutElement(ContentRoot, minWidth: 300, flexibleWidth: 9999, flexibleHeight: 9999);
|
||||
|
||||
hookCreator.ConstructAddHooksView(ContentRoot);
|
||||
|
||||
hookCreator.ConstructEditor(ContentRoot);
|
||||
HookCreator.EditorRoot.SetActive(false);
|
||||
|
||||
genericArgsHandler.ConstructUI(ContentRoot);
|
||||
genericArgsHandler.UIRoot.SetActive(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,27 +1,20 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.Config;
|
||||
using UnityExplorer.Inspectors;
|
||||
using UnityExplorer.Inspectors;
|
||||
using UniverseLib.UI;
|
||||
|
||||
namespace UnityExplorer.UI.Panels
|
||||
{
|
||||
public class InspectorPanel : UIPanel
|
||||
public class InspectorPanel : UEPanel
|
||||
{
|
||||
public static InspectorPanel Instance { get; private set; }
|
||||
|
||||
public InspectorPanel() { Instance = this; }
|
||||
|
||||
public override string Name => "Inspector";
|
||||
public override UIManager.Panels PanelType => UIManager.Panels.Inspector;
|
||||
public override bool ShouldSaveActiveState => false;
|
||||
|
||||
public override int MinWidth => 810;
|
||||
public override int MinHeight => 350;
|
||||
public override Vector2 DefaultAnchorMin => new(0.35f, 0.175f);
|
||||
public override Vector2 DefaultAnchorMax => new(0.8f, 0.925f);
|
||||
|
||||
public GameObject NavbarHolder;
|
||||
public Dropdown MouseInspectDropdown;
|
||||
@ -31,34 +24,31 @@ namespace UnityExplorer.UI.Panels
|
||||
public static float CurrentPanelWidth => Instance.Rect.rect.width;
|
||||
public static float CurrentPanelHeight => Instance.Rect.rect.height;
|
||||
|
||||
public InspectorPanel(UIBase owner) : base(owner)
|
||||
{
|
||||
Instance = this;
|
||||
}
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
InspectorManager.Update();
|
||||
}
|
||||
|
||||
public override void OnFinishResize(RectTransform panel)
|
||||
public override void OnFinishResize()
|
||||
{
|
||||
base.OnFinishResize(panel);
|
||||
base.OnFinishResize();
|
||||
|
||||
InspectorManager.PanelWidth = this.Rect.rect.width;
|
||||
InspectorManager.OnPanelResized(panel.rect.width);
|
||||
InspectorManager.OnPanelResized(Rect.rect.width);
|
||||
}
|
||||
|
||||
protected internal override void DoSetDefaultPosAndAnchors()
|
||||
protected override void ConstructPanelContent()
|
||||
{
|
||||
Rect.localPosition = Vector2.zero;
|
||||
Rect.pivot = new Vector2(0f, 1f);
|
||||
Rect.anchorMin = new Vector2(0.35f, 0.175f);
|
||||
Rect.anchorMax = new Vector2(0.8f, 0.925f);
|
||||
}
|
||||
|
||||
public override void ConstructPanelContent()
|
||||
{
|
||||
var closeHolder = this.TitleBar.transform.Find("CloseHolder").gameObject;
|
||||
GameObject 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,
|
||||
GameObject 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"));
|
||||
@ -68,7 +58,7 @@ namespace UnityExplorer.UI.Panels
|
||||
|
||||
// add close all button to titlebar
|
||||
|
||||
var closeAllBtn = UIFactory.CreateButton(closeHolder.gameObject, "CloseAllBtn", "Close All",
|
||||
UniverseLib.UI.Models.ButtonRef closeAllBtn = UIFactory.CreateButton(closeHolder.gameObject, "CloseAllBtn", "Close All",
|
||||
new Color(0.3f, 0.2f, 0.2f));
|
||||
UIFactory.SetLayoutElement(closeAllBtn.Component.gameObject, minHeight: 25, minWidth: 80);
|
||||
closeAllBtn.Component.transform.SetSiblingIndex(closeAllBtn.Component.transform.GetSiblingIndex() - 1);
|
||||
@ -76,19 +66,19 @@ namespace UnityExplorer.UI.Panels
|
||||
|
||||
// this.UIRoot.GetComponent<Mask>().enabled = false;
|
||||
|
||||
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(this.uiContent, true, true, true, true, 4, padLeft: 5, padRight: 5);
|
||||
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(this.ContentRoot, true, true, true, true, 4, padLeft: 5, padRight: 5);
|
||||
|
||||
this.NavbarHolder = UIFactory.CreateGridGroup(this.uiContent, "Navbar", new Vector2(200, 22), new Vector2(4, 4),
|
||||
this.NavbarHolder = UIFactory.CreateGridGroup(this.ContentRoot, "Navbar", new Vector2(200, 22), new Vector2(4, 4),
|
||||
new Color(0.05f, 0.05f, 0.05f));
|
||||
//UIFactory.SetLayoutElement(NavbarHolder, flexibleWidth: 9999, minHeight: 0, preferredHeight: 0, flexibleHeight: 9999);
|
||||
NavbarHolder.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||||
|
||||
this.ContentHolder = UIFactory.CreateVerticalGroup(this.uiContent, "ContentHolder", true, true, true, true, 0, default,
|
||||
this.ContentHolder = UIFactory.CreateVerticalGroup(this.ContentRoot, "ContentHolder", true, true, true, true, 0, default,
|
||||
new Color(0.1f, 0.1f, 0.1f));
|
||||
UIFactory.SetLayoutElement(ContentHolder, flexibleHeight: 9999);
|
||||
ContentRect = ContentHolder.GetComponent<RectTransform>();
|
||||
|
||||
UIManager.SetPanelActive(PanelType, false);
|
||||
this.SetActive(false);
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user