mirror of
https://github.com/sinai-dev/UnityExplorer.git
synced 2025-06-22 16:42:38 +08:00
Compare commits
115 Commits
Author | SHA1 | Date | |
---|---|---|---|
eb221bd868 | |||
5b516eb4cc | |||
601567f9d2 | |||
7ff508b874 | |||
09a7cd35cf | |||
db4a338d26 | |||
c08e02057c | |||
362fcdc51a | |||
73bd172e4d | |||
454d3bd0b4 | |||
f815a13d9a | |||
65c4d49274 | |||
d99137526e | |||
92447b55cd | |||
87d5d5a2de | |||
08cff3386b | |||
6033200579 | |||
94ec1c4908 | |||
7a400e762c | |||
67f9f744bb | |||
7a59f9a2a1 | |||
9b42eef1b9 | |||
830000b019 | |||
34910ab273 | |||
86b036095e | |||
b57e5be2e6 | |||
2d8ae45814 | |||
66dc262a68 | |||
4342901206 | |||
58b7c72a5c | |||
623dc7b7be | |||
e6f4939cc9 | |||
7a539ba78b | |||
0d10f94eb5 | |||
91671bf243 | |||
a72877befb | |||
16335c1bc4 | |||
8fab9e6268 | |||
fdd9039cca | |||
dcca980635 | |||
bfcab8248e | |||
97c20144f1 | |||
aaab10a0a0 | |||
b42a8dbe6a | |||
d7008db22e | |||
8c1913fe80 | |||
8d8c9ac7c9 | |||
f35beeaf58 | |||
d150ff3455 | |||
c4fa0d6bcd | |||
a5f56cf5a3 | |||
8c822b2ee9 | |||
4681b7e192 | |||
97093733d8 | |||
615f77979f | |||
ba3cf970d9 | |||
b2fb571b18 | |||
67ce6f946a | |||
1b82ccb49f | |||
480eb5afd5 | |||
88ea2a09c9 | |||
a678aa4d78 | |||
eaf478e314 | |||
d391968b32 | |||
70349ad7c7 | |||
78f2d1070f | |||
51307563ab | |||
185d1aaa0f | |||
3d6e8fcbf8 | |||
1daf4fade4 | |||
d92fb3f83f | |||
fe24b68fe2 | |||
6bf92b9a96 | |||
9f1cab019d | |||
a131404ac7 | |||
773900d749 | |||
342fc6bdb8 | |||
e85ea6ac3a | |||
af889e64cb | |||
0274022ce4 | |||
211576e0f8 | |||
3e42d7479f | |||
df4dea20c1 | |||
ece0c43067 | |||
6311c8d09a | |||
04739d0be8 | |||
a46acba265 | |||
5515b2eae4 | |||
9992029e28 | |||
14105785f0 | |||
365269b0dd | |||
0b973393d1 | |||
701d4431ae | |||
bfa73bcb55 | |||
b0bbeb3cf8 | |||
1a26623080 | |||
041f2938f7 | |||
9e7bb1a625 | |||
36f23b7cdc | |||
b51b743df4 | |||
805aff07cc | |||
bcdaf3b97e | |||
cb8e947fdf | |||
c8899be3ae | |||
cd5c69c965 | |||
5427312f18 | |||
eb7e80d910 | |||
a54888ae3a | |||
4f0553d293 | |||
9f0f7f9b57 | |||
383c6f19e8 | |||
428fab28f9 | |||
760b2981ad | |||
eee7d6bcc4 | |||
e270f205a1 |
61
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
Normal file
61
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
name: Bug Report
|
||||||
|
description: File a bug or crash report
|
||||||
|
title: "[Bug]: "
|
||||||
|
labels: [bug]
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
Thanks for submitting a bug report, please fill out as much detail as possible.
|
||||||
|
- type: checkboxes
|
||||||
|
id: latestversion
|
||||||
|
attributes:
|
||||||
|
label: Are you on the latest version of UnityExplorer?
|
||||||
|
description: If not, you must update first.
|
||||||
|
options:
|
||||||
|
- label: Yes, I'm on the latest version of UnityExplorer.
|
||||||
|
required: true
|
||||||
|
- type: dropdown
|
||||||
|
id: version
|
||||||
|
attributes:
|
||||||
|
label: Which release are you using?
|
||||||
|
description: Please select your environment for UnityExplorer.
|
||||||
|
options:
|
||||||
|
- BepInEx IL2CPP
|
||||||
|
- BepInEx 6.X Mono
|
||||||
|
- BepInEx 5.X Mono
|
||||||
|
- MelonLoader 0.4+ IL2CPP
|
||||||
|
- MelonLoader 0.4+ Mono
|
||||||
|
- MelonLoader 0.3 IL2CPP
|
||||||
|
- MelonLoader 0.3 Mono
|
||||||
|
- Standalone IL2CPP
|
||||||
|
- Standalone Mono
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: game
|
||||||
|
attributes:
|
||||||
|
label: Which game did this occur on?
|
||||||
|
description: Please tell us the name of the game. If it's a personal or private project, just let us know the Unity version.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: what-happened
|
||||||
|
attributes:
|
||||||
|
label: Describe the issue.
|
||||||
|
description: What happened? Should something else have happened instead? Please provide steps to reproduce the issue if possible.
|
||||||
|
placeholder: Tell us what you see!
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: logs
|
||||||
|
attributes:
|
||||||
|
label: Log output
|
||||||
|
description: |
|
||||||
|
Please copy and paste your mod loader's log output.
|
||||||
|
* BepInEx: `BepInEx\LogOutput.log`
|
||||||
|
* MelonLoader: `MelonLoader\latest.log`
|
||||||
|
* Standalone: `{DLL_Location}\UnityExplorer\Logs\` (pick the most recent one)
|
||||||
|
render: shell
|
||||||
|
validations:
|
||||||
|
required: true
|
1
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
1
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
blank_issues_enabled: false
|
18
.github/ISSUE_TEMPLATE/enhancement.yaml
vendored
Normal file
18
.github/ISSUE_TEMPLATE/enhancement.yaml
vendored
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
name: New feature or enhancement
|
||||||
|
description: Suggest or discuss a feature or enhancement for UnityExplorer
|
||||||
|
title: "[Enhancement]: "
|
||||||
|
labels: [enhancement]
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
Thanks for taking the time to discuss UnityExplorer, please provide as much detail as possible.
|
||||||
|
- type: textarea
|
||||||
|
id: description
|
||||||
|
attributes:
|
||||||
|
label: Describe the new feature or enhancement
|
||||||
|
description: |
|
||||||
|
Please go into as much detail as necessary in describing the new feature or enhancement.
|
||||||
|
If providing examples or suggestions for the required C# code, please use syntax-highlighted code blocks.
|
||||||
|
validations:
|
||||||
|
required: true
|
113
.github/workflows/dotnet.yml
vendored
Normal file
113
.github/workflows/dotnet.yml
vendored
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
name: Build UnityExplorer
|
||||||
|
|
||||||
|
# Controls when the action will run.
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [master]
|
||||||
|
# Allows you to run this workflow manually from the Actions tab
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: windows-latest
|
||||||
|
if: "!contains(github.event.head_commit.message, '-noci')"
|
||||||
|
|
||||||
|
steps:
|
||||||
|
# Checkout latest with submodules
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
|
||||||
|
# Setup tools
|
||||||
|
- name: Setup msbuild
|
||||||
|
uses: microsoft/setup-msbuild@v1
|
||||||
|
|
||||||
|
- name: Setup nuget
|
||||||
|
uses: nuget/setup-nuget@v1
|
||||||
|
with:
|
||||||
|
nuget-api-key: ${{ secrets.NuGetAPIKey }}
|
||||||
|
nuget-version: '5.x'
|
||||||
|
|
||||||
|
# Build Il2CppAssemblyUnhollower
|
||||||
|
- run: msbuild lib\Il2CppAssemblyUnhollower\UnhollowerBaseLib\UnhollowerBaseLib.csproj -t:Restore -t:Rebuild -p:Platform="AnyCPU" -p:Configuration=Release
|
||||||
|
|
||||||
|
# Build mcs
|
||||||
|
- run: nuget restore lib\mcs-unity\mcs.sln
|
||||||
|
- run: msbuild lib\mcs-unity\mcs\mcs.csproj -t:Restore -t:Rebuild -p:Platform="AnyCPU" -p:Configuration=Release
|
||||||
|
|
||||||
|
# Build UnityExplorer releases, and upload artifacts
|
||||||
|
|
||||||
|
- run: nuget restore src\UnityExplorer.sln
|
||||||
|
|
||||||
|
# BepInEx Il2Cpp
|
||||||
|
- run: msbuild src\UnityExplorer.csproj -t:Rebuild -p:Platform="AnyCPU" -p:Configuration=Release_BIE_Cpp
|
||||||
|
|
||||||
|
- uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: UnityExplorer.BepInEx.Il2Cpp
|
||||||
|
path: ./Release/UnityExplorer.BepInEx.Il2Cpp/*
|
||||||
|
|
||||||
|
# BepInEx 5 Mono
|
||||||
|
- run: msbuild src\UnityExplorer.csproj -t:Rebuild -p:Platform="AnyCPU" -p:Configuration=Release_BIE5_Mono
|
||||||
|
|
||||||
|
- uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: UnityExplorer.BepInEx5.Mono
|
||||||
|
path: ./Release/UnityExplorer.BepInEx5.Mono/*
|
||||||
|
|
||||||
|
# BepInEx 6 Mono
|
||||||
|
- run: msbuild src\UnityExplorer.csproj -t:Rebuild -p:Platform="AnyCPU" -p:Configuration=Release_BIE6_Mono
|
||||||
|
|
||||||
|
- uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: UnityExplorer.BepInEx6.Mono
|
||||||
|
path: ./Release/UnityExplorer.BepInEx6.Mono/*
|
||||||
|
|
||||||
|
# MelonLoader Il2Cpp
|
||||||
|
- run: msbuild src\UnityExplorer.csproj -t:Rebuild -p:Platform="AnyCPU" -p:Configuration=Release_ML_Cpp
|
||||||
|
|
||||||
|
- uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: UnityExplorer.MelonLoader.Il2Cpp
|
||||||
|
path: ./Release/UnityExplorer.MelonLoader.Il2Cpp/*
|
||||||
|
|
||||||
|
# MelonLoader Mono
|
||||||
|
- run: msbuild src\UnityExplorer.csproj -t:Rebuild -p:Platform="AnyCPU" -p:Configuration=Release_ML_Mono
|
||||||
|
|
||||||
|
- uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: UnityExplorer.MelonLoader.Mono
|
||||||
|
path: ./Release/UnityExplorer.MelonLoader.Mono/*
|
||||||
|
|
||||||
|
# MelonLoader 0.3.0 Il2Cpp
|
||||||
|
- run: msbuild src\UnityExplorer.csproj -t:Rebuild -p:Platform="AnyCPU" -p:Configuration=Release_MLLegacy_Cpp
|
||||||
|
|
||||||
|
- uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: UnityExplorer.MelonLoader_Legacy.Il2Cpp
|
||||||
|
path: ./Release/UnityExplorer.MelonLoader_Legacy.Il2Cpp/*
|
||||||
|
|
||||||
|
# MelonLoader 0.3.0 Mono
|
||||||
|
- run: msbuild src\UnityExplorer.csproj -t:Rebuild -p:Platform="AnyCPU" -p:Configuration=Release_MLLegacy_Mono
|
||||||
|
|
||||||
|
- uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: UnityExplorer.MelonLoader_Legacy.Mono
|
||||||
|
path: ./Release/UnityExplorer.MelonLoader_Legacy.Mono/*
|
||||||
|
|
||||||
|
# Standalone Il2Cpp
|
||||||
|
- run: msbuild src\UnityExplorer.csproj -t:Rebuild -p:Platform="AnyCPU" -p:Configuration=Release_STANDALONE_Cpp
|
||||||
|
|
||||||
|
- uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: UnityExplorer.Standalone.Il2Cpp
|
||||||
|
path: ./Release/UnityExplorer.Standalone.Il2Cpp/*
|
||||||
|
|
||||||
|
# Standalone Mono
|
||||||
|
- run: msbuild src\UnityExplorer.csproj -t:Rebuild -p:Platform="AnyCPU" -p:Configuration=Release_STANDALONE_Mono
|
||||||
|
|
||||||
|
- uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: UnityExplorer.Standalone.Mono
|
||||||
|
path: ./Release/UnityExplorer.Standalone.Mono/*
|
||||||
|
|
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -1,9 +1,6 @@
|
|||||||
[submodule "lib/Il2CppAssemblyUnhollower"]
|
[submodule "lib/Il2CppAssemblyUnhollower"]
|
||||||
path = lib/Il2CppAssemblyUnhollower
|
path = lib/Il2CppAssemblyUnhollower
|
||||||
url = https://github.com/knah/Il2CppAssemblyUnhollower
|
url = https://github.com/knah/Il2CppAssemblyUnhollower
|
||||||
[submodule "lib/HarmonyX"]
|
|
||||||
path = lib/HarmonyX
|
|
||||||
url = https://github.com/BepInEx/HarmonyX
|
|
||||||
[submodule "lib/mcs-unity"]
|
[submodule "lib/mcs-unity"]
|
||||||
path = lib/mcs-unity
|
path = lib/mcs-unity
|
||||||
url = https://github.com/sinai-dev/mcs-unity
|
url = https://github.com/sinai-dev/mcs-unity
|
||||||
|
114
README.md
114
README.md
@ -3,44 +3,45 @@
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
An in-game explorer and a suite of debugging tools for <a href="https://docs.unity3d.com/Manual/IL2CPP.html">IL2CPP</a> and <b>Mono</b> Unity games, to aid with modding development.
|
🔍 An in-game UI for exploring, debugging and modifying Unity games.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
Supports most Unity games from versions 5.2 to 2020+.
|
✔️ Supports most Unity versions from 5.2 to 2021+ (IL2CPP and Mono).
|
||||||
|
</p>
|
||||||
|
<p align="center">
|
||||||
|
⚡ UnityExplorer is on <a href="https://thunderstore.io/package/sinai-dev/UnityExplorer/">Thunderstore</a>! (and as <a href="https://gtfo.thunderstore.io/package/sinai-dev/UnityExplorer_IL2CPP/">IL2CPP</a>)
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
## Releases [](../../releases/latest) [](../../releases) [](../../releases/latest)
|
# Releases [](../../releases)
|
||||||
|
|
||||||
| Mod Loader | IL2CPP | Mono |
|
[](../../releases/latest) [](https://github.com/sinai-dev/UnityExplorer/actions) [](../../releases/latest)
|
||||||
| ----------- | ------ | ---- |
|
|
||||||
| [BepInEx](https://github.com/BepInEx/BepInEx) 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) |
|
|
||||||
| [BepInEx](https://github.com/BepInEx/BepInEx) 5.X | ✖️ n/a | ✅ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.BepInEx5.Mono.zip) |
|
|
||||||
| [MelonLoader](https://github.com/HerpDerpinstine/MelonLoader) 0.3.1 | ✅ [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) |
|
|
||||||
| Standalone | ✅ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.Standalone.Il2Cpp.zip) | ✅ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.Standalone.Mono.zip) |
|
|
||||||
|
|
||||||
### Known issues
|
## BepInEx
|
||||||
* Any `MissingMethodException` or `NotSupportedException`: please report the issue and provide a copy of your mod loader log and/or Unity log.
|
|
||||||
* The C# console may unexpectedly produce a GC Mark Overflow crash when calling certain outside methods. Not clear yet what is causing this, but it's being looked into.
|
|
||||||
* In IL2CPP, some IEnumerable and IDictionary types may fail enumeration. Waiting for the Unhollower rewrite to address this any further.
|
|
||||||
* In IL2CPP, the C# console might not suggest deobfuscated (or obfuscated) names. Being looked into.
|
|
||||||
|
|
||||||
## How to install
|
| 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 5.X | ✖️ n/a | ✅ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.BepInEx5.Mono.zip) |
|
||||||
|
|
||||||
### BepInEx
|
1. Take the `UnityExplorer.BIE.[version].dll` file and put it in `BepInEx\plugins\`
|
||||||
|
2. In IL2CPP, you will need to download the [Unity libs](https://github.com/LavaGang/Unity-Runtime-Libraries) for the game's Unity version, create a folder `BepInEx\unity-libs\`, then extract the Unity libs into this folder.
|
||||||
|
|
||||||
1. Install [BepInEx](https://github.com/BepInEx/BepInEx) for your game. IL2CPP currently requires a [Bleeding Edge](https://builds.bepis.io/projects/bepinex_be) release.
|
<i>Note: BepInEx 6 is obtainable via [BepisBuilds](https://builds.bepis.io/projects/bepinex_be)</i>
|
||||||
2. Download the UnityExplorer release for BepInEx IL2CPP or Mono above.
|
|
||||||
3. Take the `UnityExplorer.BIE.___.dll` file and put it in `[GameFolder]\BepInEx\plugins\`
|
|
||||||
4. In IL2CPP, you will need to download the [Unity libs](https://github.com/LavaGang/Unity-Runtime-Libraries) for the game's Unity version and put them in the `BepInEx\unity-libs\` folder.
|
|
||||||
|
|
||||||
### MelonLoader
|
## MelonLoader
|
||||||
|
|
||||||
1. Install [MelonLoader](https://github.com/HerpDerpinstine/MelonLoader) 0.3.1+ for your game. This version can currently be obtained from [here](https://github.com/LavaGang/MelonLoader/actions).
|
| Release | IL2CPP | Mono |
|
||||||
2. Download the UnityExplorer release for MelonLoader IL2CPP or Mono above.
|
| ------- | ------ | ---- |
|
||||||
3. Take the `UnityExplorer.ML.___.dll` file and put it in the `[GameFolder]\Mods\` folder.
|
| ML 0.4.0 | ✅ [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.3.0 | ✅ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.MelonLoader_Legacy.Il2Cpp.zip) | ✅ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.MelonLoader_Legacy.Mono.zip) |
|
||||||
|
|
||||||
### Standalone
|
1. Take the `UnityExplorer.ML.[version].dll` file and put it in the `Mods\` folder created by MelonLoader.
|
||||||
|
|
||||||
|
## Standalone
|
||||||
|
|
||||||
|
| IL2CPP | Mono |
|
||||||
|
| ------ | ---- |
|
||||||
|
| ✅ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.Standalone.Il2Cpp.zip) | ✅ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.Standalone.Mono.zip) |
|
||||||
|
|
||||||
The standalone release can be used with any injector or loader of your choice, but it requires you to load the dependencies manually: HarmonyX, and the IL2CPP version also requires that you set up an [Il2CppAssemblyUnhollower runtime](https://github.com/knah/Il2CppAssemblyUnhollower#required-external-setup).
|
The standalone release can be used with any injector or loader of your choice, but it requires you to load the dependencies manually: HarmonyX, and the IL2CPP version also requires that you set up an [Il2CppAssemblyUnhollower runtime](https://github.com/knah/Il2CppAssemblyUnhollower#required-external-setup).
|
||||||
|
|
||||||
@ -49,7 +50,7 @@ The standalone release can be used with any injector or loader of your choice, b
|
|||||||
3. Create an instance of Unity Explorer with `UnityExplorer.ExplorerStandalone.CreateInstance();`
|
3. Create an instance of Unity Explorer with `UnityExplorer.ExplorerStandalone.CreateInstance();`
|
||||||
4. Optionally subscribe to the `ExplorerStandalone.OnLog` event to handle logging if you wish
|
4. Optionally subscribe to the `ExplorerStandalone.OnLog` event to handle logging if you wish
|
||||||
|
|
||||||
## Features
|
# Features
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://raw.githubusercontent.com/sinai-dev/UnityExplorer/master/img/preview.png">
|
<a href="https://raw.githubusercontent.com/sinai-dev/UnityExplorer/master/img/preview.png">
|
||||||
@ -59,48 +60,61 @@ The standalone release can be used with any injector or loader of your choice, b
|
|||||||
|
|
||||||
### Object Explorer
|
### Object Explorer
|
||||||
|
|
||||||
* Use the <b>Scene Explorer</b> tab to traverse the active scenes, as well as the DontDestroyOnLoad scene and the HideAndDontSave "scene" (assets and hidden objects).
|
* Use the <b>Scene Explorer</b> tab to traverse the active scenes, as well as the DontDestroyOnLoad and HideAndDontSave objects.
|
||||||
|
* The "HideAndDontSave" scene contains objects with that flag, as well as Assets and Resources which are not in any scene but behave the same way.
|
||||||
|
* You can use the Scene Loader to easily load any of the scenes in the build (may not work for Unity 5.X games)
|
||||||
* Use the <b>Object Search</b> tab to search for Unity objects (including GameObjects, Components, etc), C# Singletons or Static Classes.
|
* Use the <b>Object Search</b> tab to search for Unity objects (including GameObjects, Components, etc), C# Singletons or Static Classes.
|
||||||
|
* Use the UnityObject search to look for any objects which derive from `UnityEngine.Object`, with optional filters
|
||||||
|
* The singleton search will look for any classes with a typical "Instance" field, and check it for a current value. This may cause unexpected behaviour in some IL2CPP games as we cannot distinguish between true properties and field-properties, so some property accessors will be invoked.
|
||||||
|
|
||||||
### Inspector
|
### Inspector
|
||||||
|
|
||||||
The inspector is used to see detailed information on GameObjects (GameObject Inspector), C# objects (Reflection Inspector) and C# classes (Static Inspector).
|
The inspector is used to see detailed information on objects of any type and manipulate their values, as well as to inspect C# Classes with static reflection.
|
||||||
|
|
||||||
For the GameObject Inspector, you can edit any of the input fields in the inspector (excluding readonly fields) and press <b>Enter</b> to apply your changes. You can also do this to the GameObject path as a way to change the GameObject's parent. Press the <b>Escape</b> key to cancel your edits.
|
* The <b>GameObject Inspector</b> (tab prefix `[G]`) is used to inspect a `GameObject`, and to see and manipulate its Transform and Components.
|
||||||
|
* You can edit any of the input fields in the inspector (excluding readonly fields) and press <b>Enter</b> to apply your changes. You can also do this to the GameObject path as a way to change the GameObject's parent. Press the <b>Escape</b> key to cancel your edits.
|
||||||
In the Reflection Inspectors, automatic updating is not enabled by default, and you must press Apply for any changes you make to take effect.
|
* <i>note: When inspecting a GameObject with a Canvas, the transform controls may be overridden by the RectTransform anchors.</i>
|
||||||
|
* The <b>Reflection Inspectors</b> (tab prefix `[R]` and `[S]`) are used for everything else
|
||||||
|
* 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
|
||||||
|
|
||||||
### C# Console
|
### C# Console
|
||||||
|
|
||||||
The C# Console uses the `Mono.CSharp.Evaluator` to define temporary classes or run immediate REPL code.
|
* The C# Console uses the `Mono.CSharp.Evaluator` to define temporary classes or run immediate REPL code.
|
||||||
|
* You can execute a script automatically on startup by naming it `startup.cs` and placing it in the `UnityExplorer\Scripts\` folder (this folder will be created where you placed the DLL file).
|
||||||
See the "Help" dropdown in the C# console menu for more detailed information.
|
* See the "Help" dropdown in the C# console menu for more detailed information.
|
||||||
|
|
||||||
### Mouse-Inspect
|
### Mouse-Inspect
|
||||||
|
|
||||||
The "Mouse Inspect" dropdown on the main UnityExplorer navbar allows you to inspect objects under the mouse.
|
* The "Mouse Inspect" dropdown on the main UnityExplorer navbar allows you to inspect objects under the mouse.
|
||||||
|
* <b>World</b>: uses Physics.Raycast to look for Colliders
|
||||||
* <b>World</b>: uses Physics.Raycast to look for Colliders
|
* <b>UI</b>: uses GraphicRaycasters to find UI objects
|
||||||
* <b>UI</b>: uses GraphicRaycasters to find UI objects
|
|
||||||
|
|
||||||
### Settings
|
### Settings
|
||||||
|
|
||||||
You can change the settings via the "Options" page of the main menu, or directly from the config file.
|
* You can change the settings via the "Options" tab of the menu, or directly from the config file.
|
||||||
|
* BepInEx: `BepInEx\config\com.sinai.unityexplorer.cfg`
|
||||||
|
* MelonLoader: `UserData\MelonPreferences.cfg`
|
||||||
|
* Standalone `{DLL_location}\UnityExplorer\config.ini`
|
||||||
|
|
||||||
Depending on the release you are using, the config file will be found at:
|
# Building
|
||||||
* BepInEx: `BepInEx\config\com.sinai.unityexplorer.cfg`
|
|
||||||
* MelonLoader: `UserData\MelonPreferences.cfg`
|
|
||||||
* Standalone `{DLL_location}\UnityExplorer\config.ini`
|
|
||||||
|
|
||||||
## Building
|
If you fork the repository on GitHub you can build using the [dotnet workflow](https://github.com/sinai-dev/UnityExplorer/blob/master/.github/workflows/dotnet.yml):
|
||||||
|
|
||||||
|
0. Click on the Actions tab and enable workflows in your repository
|
||||||
|
1. Click on the "Build UnityExplorer" workflow, then click "Run Workflow" and run it manually, or make a new commit to trigger the workflow.
|
||||||
|
2. Take the artifact from the completed run.
|
||||||
|
|
||||||
|
For Visual Studio:
|
||||||
|
|
||||||
0. Clone the repository and run `git submodule update --init --recursive` to get the submodules.
|
0. Clone the repository and run `git submodule update --init --recursive` to get the submodules.
|
||||||
1. Open the `src\UnityExplorer.sln` project in Visual Studio.
|
1. Open the `src\UnityExplorer.sln` project.
|
||||||
2. Select `Solution 'UnityExplorer' (1 of 1 project)` in the Solution Explorer panel, and set the <b>Active config</b> property to the version you want to build, then build it. Alternatively, use "Batch Build" and select all releases.
|
2. Build `mcs` (Release/AnyCPU, you may need to run `nuget restore mcs.sln`), and if using IL2CPP then build `Il2CppAssemblyUnhollower` (Release/AnyCPU) as well.
|
||||||
3. The DLLs are built to the `Release\` folder in the root of the repository.
|
3. Build the UnityExplorer release(s) you want to use, either by selecting the config as the Active Config, or batch-building.
|
||||||
4. If ILRepack complains about an error, just change the Active config to a different release and then back again. This sometimes happens for the first time you build the project.
|
|
||||||
|
|
||||||
## Acknowledgments
|
# Acknowledgments
|
||||||
|
|
||||||
* [ManlyMarco](https://github.com/ManlyMarco) for [Runtime Unity Editor](https://github.com/ManlyMarco/RuntimeUnityEditor) \[[license](THIRDPARTY_LICENSES.md#runtimeunityeditor-license)\], the ScriptEvaluator from RUE's REPL console was used as the base for UnityExplorer's C# console.
|
* [ManlyMarco](https://github.com/ManlyMarco) for [Runtime Unity Editor](https://github.com/ManlyMarco/RuntimeUnityEditor) \[[license](THIRDPARTY_LICENSES.md#runtimeunityeditor-license)\], the ScriptEvaluator from RUE's REPL console was used as the base for UnityExplorer's C# console.
|
||||||
* [denikson](https://github.com/denikson) (aka Horse) for [mcs-unity](https://github.com/denikson/mcs-unity) \[no license\], used as the `Mono.CSharp` reference for the C# Console.
|
* [denikson](https://github.com/denikson) (aka Horse) for [mcs-unity](https://github.com/denikson/mcs-unity) \[no license\], used as the `Mono.CSharp` reference for the C# Console.
|
||||||
|
Submodule lib/HarmonyX deleted from 64462b3e31
BIN
lib/MelonLoader_Legacy/MelonLoader.dll
Normal file
BIN
lib/MelonLoader_Legacy/MelonLoader.dll
Normal file
Binary file not shown.
@ -3,10 +3,11 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityExplorer.UI.CSConsole.Lexers;
|
using UnityExplorer.CSConsole.Lexers;
|
||||||
|
using UnityExplorer.UI;
|
||||||
using UnityExplorer.UI.Widgets.AutoComplete;
|
using UnityExplorer.UI.Widgets.AutoComplete;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.CSConsole
|
namespace UnityExplorer.CSConsole
|
||||||
{
|
{
|
||||||
public class CSAutoCompleter : ISuggestionProvider
|
public class CSAutoCompleter : ISuggestionProvider
|
||||||
{
|
{
|
||||||
@ -22,7 +23,6 @@ namespace UnityExplorer.UI.CSConsole
|
|||||||
AutoCompleteModal.Instance.ReleaseOwnership(this);
|
AutoCompleteModal.Instance.ReleaseOwnership(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delimiters for completions, notably does not include '.'
|
|
||||||
private readonly HashSet<char> delimiters = new HashSet<char>
|
private readonly HashSet<char> delimiters = new HashSet<char>
|
||||||
{
|
{
|
||||||
'{', '}', ',', ';', '<', '>', '(', ')', '[', ']', '=', '|', '&', '?'
|
'{', '}', ',', ';', '<', '>', '(', ')', '[', ']', '=', '|', '&', '?'
|
||||||
@ -41,7 +41,7 @@ namespace UnityExplorer.UI.CSConsole
|
|||||||
suggestions.Clear();
|
suggestions.Clear();
|
||||||
|
|
||||||
int caret = Math.Max(0, Math.Min(InputField.Text.Length - 1, InputField.Component.caretPosition - 1));
|
int caret = Math.Max(0, Math.Min(InputField.Text.Length - 1, InputField.Component.caretPosition - 1));
|
||||||
int start = caret;
|
int startIdx = caret;
|
||||||
|
|
||||||
// If the character at the caret index is whitespace or delimiter,
|
// If the character at the caret index is whitespace or delimiter,
|
||||||
// or if the next character (if it exists) is not whitespace,
|
// or if the next character (if it exists) is not whitespace,
|
||||||
@ -55,22 +55,22 @@ namespace UnityExplorer.UI.CSConsole
|
|||||||
}
|
}
|
||||||
|
|
||||||
// get the current composition string (from caret back to last delimiter)
|
// get the current composition string (from caret back to last delimiter)
|
||||||
while (start > 0)
|
while (startIdx > 0)
|
||||||
{
|
{
|
||||||
start--;
|
startIdx--;
|
||||||
char c = InputField.Text[start];
|
char c = InputField.Text[startIdx];
|
||||||
if (delimiters.Contains(c))
|
if (delimiters.Contains(c) || char.IsWhiteSpace(c))
|
||||||
{
|
{
|
||||||
start++;
|
startIdx++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
string input = InputField.Text.Substring(start, caret - start + 1);
|
string input = InputField.Text.Substring(startIdx, caret - startIdx + 1);
|
||||||
|
|
||||||
// Get MCS completions
|
// Get MCS completions
|
||||||
|
|
||||||
string[] evaluatorCompletions = ConsoleController.Evaluator.GetCompletions(input, out string prefix);
|
string[] evaluatorCompletions = ConsoleController.Evaluator.GetCompletions(input, out string prefix);
|
||||||
|
|
||||||
if (evaluatorCompletions != null && evaluatorCompletions.Any())
|
if (evaluatorCompletions != null && evaluatorCompletions.Any())
|
||||||
{
|
{
|
||||||
suggestions.AddRange(from completion in evaluatorCompletions
|
suggestions.AddRange(from completion in evaluatorCompletions
|
||||||
@ -99,7 +99,7 @@ namespace UnityExplorer.UI.CSConsole
|
|||||||
{
|
{
|
||||||
if (!keywordHighlights.ContainsKey(kw))
|
if (!keywordHighlights.ContainsKey(kw))
|
||||||
keywordHighlights.Add(kw, $"<color=#{SignatureHighlighter.keywordBlueHex}>{kw}</color>");
|
keywordHighlights.Add(kw, $"<color=#{SignatureHighlighter.keywordBlueHex}>{kw}</color>");
|
||||||
|
|
||||||
string completion = kw.Substring(input.Length, kw.Length - input.Length);
|
string completion = kw.Substring(input.Length, kw.Length - input.Length);
|
||||||
suggestions.Add(new Suggestion(keywordHighlights[kw], completion));
|
suggestions.Add(new Suggestion(keywordHighlights[kw], completion));
|
||||||
}
|
}
|
||||||
@ -123,7 +123,7 @@ namespace UnityExplorer.UI.CSConsole
|
|||||||
|
|
||||||
private readonly StringBuilder highlightBuilder = new StringBuilder();
|
private readonly StringBuilder highlightBuilder = new StringBuilder();
|
||||||
private const string OPEN_HIGHLIGHT = "<color=cyan>";
|
private const string OPEN_HIGHLIGHT = "<color=cyan>";
|
||||||
|
|
||||||
private string GetHighlightString(string prefix, string completion)
|
private string GetHighlightString(string prefix, string completion)
|
||||||
{
|
{
|
||||||
highlightBuilder.Clear();
|
highlightBuilder.Clear();
|
@ -1,18 +1,21 @@
|
|||||||
using System;
|
using Mono.CSharp;
|
||||||
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.EventSystems;
|
using UnityEngine.EventSystems;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.UI.CSConsole;
|
|
||||||
using UnityExplorer.Core.Input;
|
using UnityExplorer.Core.Input;
|
||||||
|
using UnityExplorer.CSConsole;
|
||||||
|
using UnityExplorer.UI;
|
||||||
using UnityExplorer.UI.Panels;
|
using UnityExplorer.UI.Panels;
|
||||||
using UnityExplorer.UI.Widgets.AutoComplete;
|
using UnityExplorer.UI.Widgets.AutoComplete;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.CSConsole
|
namespace UnityExplorer.CSConsole
|
||||||
{
|
{
|
||||||
public static class ConsoleController
|
public static class ConsoleController
|
||||||
{
|
{
|
||||||
@ -34,6 +37,8 @@ namespace UnityExplorer.UI.CSConsole
|
|||||||
public static bool EnableAutoIndent { get; private set; } = true;
|
public static bool EnableAutoIndent { get; private set; } = true;
|
||||||
public static bool EnableSuggestions { get; private set; } = true;
|
public static bool EnableSuggestions { get; private set; } = true;
|
||||||
|
|
||||||
|
internal static string ScriptsFolder => Path.Combine(ExplorerCore.Loader.ExplorerFolder, "Scripts");
|
||||||
|
|
||||||
internal static readonly string[] DefaultUsing = new string[]
|
internal static readonly string[] DefaultUsing = new string[]
|
||||||
{
|
{
|
||||||
"System",
|
"System",
|
||||||
@ -49,6 +54,7 @@ namespace UnityExplorer.UI.CSConsole
|
|||||||
|
|
||||||
public static void Init()
|
public static void Init()
|
||||||
{
|
{
|
||||||
|
// Make sure console is supported on this platform
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
ResetConsole(false);
|
ResetConsole(false);
|
||||||
@ -61,19 +67,41 @@ namespace UnityExplorer.UI.CSConsole
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Setup console
|
||||||
Lexer = new LexerBuilder();
|
Lexer = new LexerBuilder();
|
||||||
Completer = new CSAutoCompleter();
|
Completer = new CSAutoCompleter();
|
||||||
|
|
||||||
SetupHelpInteraction();
|
SetupHelpInteraction();
|
||||||
|
|
||||||
Panel.OnInputChanged += OnInputChanged;
|
Panel.OnInputChanged += OnInputChanged;
|
||||||
Panel.InputScroll.OnScroll += OnInputScrolled;
|
Panel.InputScroller.OnScroll += OnInputScrolled;
|
||||||
Panel.OnCompileClicked += Evaluate;
|
Panel.OnCompileClicked += Evaluate;
|
||||||
Panel.OnResetClicked += ResetConsole;
|
Panel.OnResetClicked += ResetConsole;
|
||||||
Panel.OnHelpDropdownChanged += HelpSelected;
|
Panel.OnHelpDropdownChanged += HelpSelected;
|
||||||
Panel.OnAutoIndentToggled += OnToggleAutoIndent;
|
Panel.OnAutoIndentToggled += OnToggleAutoIndent;
|
||||||
Panel.OnCtrlRToggled += OnToggleCtrlRShortcut;
|
Panel.OnCtrlRToggled += OnToggleCtrlRShortcut;
|
||||||
Panel.OnSuggestionsToggled += OnToggleSuggestions;
|
Panel.OnSuggestionsToggled += OnToggleSuggestions;
|
||||||
|
Panel.OnPanelResized += OnInputScrolled;
|
||||||
|
|
||||||
|
// Run startup script
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!Directory.Exists(ScriptsFolder))
|
||||||
|
Directory.CreateDirectory(ScriptsFolder);
|
||||||
|
|
||||||
|
var startupPath = Path.Combine(ScriptsFolder, "startup.cs");
|
||||||
|
if (File.Exists(startupPath))
|
||||||
|
{
|
||||||
|
ExplorerCore.Log($"Executing startup script from '{startupPath}'...");
|
||||||
|
var text = File.ReadAllText(startupPath);
|
||||||
|
Input.Text = text;
|
||||||
|
Evaluate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
ExplorerCore.LogWarning($"Exception executing startup script: {ex}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -149,15 +177,16 @@ namespace UnityExplorer.UI.CSConsole
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Try to "Compile" the code (tries to interpret it as REPL)
|
// Compile the code. If it returned a CompiledMethod, it is REPL.
|
||||||
var evaluation = Evaluator.Compile(input);
|
CompiledMethod repl = Evaluator.Compile(input);
|
||||||
if (evaluation != null)
|
|
||||||
|
if (repl != null)
|
||||||
{
|
{
|
||||||
// Valid REPL, we have a delegate to the evaluation.
|
// Valid REPL, we have a delegate to the evaluation.
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
object ret = null;
|
object ret = null;
|
||||||
evaluation.Invoke(ref ret);
|
repl.Invoke(ref ret);
|
||||||
var result = ret?.ToString();
|
var result = ret?.ToString();
|
||||||
if (!string.IsNullOrEmpty(result))
|
if (!string.IsNullOrEmpty(result))
|
||||||
ExplorerCore.Log($"Invoked REPL, result: {ret}");
|
ExplorerCore.Log($"Invoked REPL, result: {ret}");
|
||||||
@ -171,9 +200,7 @@ namespace UnityExplorer.UI.CSConsole
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// The input was not recognized as an evaluation. Compile the code.
|
// The compiled code was not REPL, so it was a using directive or it defined classes.
|
||||||
|
|
||||||
Evaluator.Run(input);
|
|
||||||
|
|
||||||
string output = ScriptEvaluator._textWriter.ToString();
|
string output = ScriptEvaluator._textWriter.ToString();
|
||||||
var outputSplit = output.Split('\n');
|
var outputSplit = output.Split('\n');
|
||||||
@ -220,7 +247,7 @@ namespace UnityExplorer.UI.CSConsole
|
|||||||
if (InputManager.GetKeyDown(KeyCode.Escape))
|
if (InputManager.GetKeyDown(KeyCode.Escape))
|
||||||
{
|
{
|
||||||
Input.Text = previousInput;
|
Input.Text = previousInput;
|
||||||
|
|
||||||
if (EnableSuggestions && AutoCompleteModal.CheckEscape(Completer))
|
if (EnableSuggestions && AutoCompleteModal.CheckEscape(Completer))
|
||||||
OnAutocompleteEscaped();
|
OnAutocompleteEscaped();
|
||||||
|
|
||||||
@ -230,23 +257,32 @@ namespace UnityExplorer.UI.CSConsole
|
|||||||
previousInput = value;
|
previousInput = value;
|
||||||
|
|
||||||
if (EnableSuggestions && AutoCompleteModal.CheckEnter(Completer))
|
if (EnableSuggestions && AutoCompleteModal.CheckEnter(Completer))
|
||||||
{
|
|
||||||
OnAutocompleteEnter();
|
OnAutocompleteEnter();
|
||||||
}
|
|
||||||
else if (!settingCaretCoroutine)
|
|
||||||
{
|
|
||||||
if (EnableSuggestions)
|
|
||||||
Completer.CheckAutocompletes();
|
|
||||||
|
|
||||||
|
if (!settingCaretCoroutine)
|
||||||
|
{
|
||||||
if (EnableAutoIndent)
|
if (EnableAutoIndent)
|
||||||
DoAutoIndent();
|
DoAutoIndent();
|
||||||
}
|
}
|
||||||
|
|
||||||
HighlightVisibleInput();
|
var inStringOrComment = HighlightVisibleInput();
|
||||||
|
|
||||||
|
if (!settingCaretCoroutine)
|
||||||
|
{
|
||||||
|
if (EnableSuggestions)
|
||||||
|
{
|
||||||
|
if (inStringOrComment)
|
||||||
|
AutoCompleteModal.Instance.ReleaseOwnership(Completer);
|
||||||
|
else
|
||||||
|
Completer.CheckAutocompletes();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
UpdateCaret(out _);
|
UpdateCaret(out _);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static float timeOfLastCtrlR;
|
||||||
|
|
||||||
public static void Update()
|
public static void Update()
|
||||||
{
|
{
|
||||||
if (SRENotSupported)
|
if (SRENotSupported)
|
||||||
@ -254,22 +290,24 @@ namespace UnityExplorer.UI.CSConsole
|
|||||||
|
|
||||||
UpdateCaret(out bool caretMoved);
|
UpdateCaret(out bool caretMoved);
|
||||||
|
|
||||||
if (!settingCaretCoroutine && EnableSuggestions && AutoCompleteModal.CheckEscape(Completer))
|
if (!settingCaretCoroutine && EnableSuggestions)
|
||||||
{
|
{
|
||||||
OnAutocompleteEscaped();
|
if (AutoCompleteModal.CheckEscape(Completer))
|
||||||
return;
|
{
|
||||||
}
|
OnAutocompleteEscaped();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!settingCaretCoroutine && EnableSuggestions && caretMoved)
|
if (caretMoved)
|
||||||
{
|
AutoCompleteModal.Instance.ReleaseOwnership(Completer);
|
||||||
AutoCompleteModal.Instance.ReleaseOwnership(Completer);
|
|
||||||
//Completer.CheckAutocompletes();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (EnableCtrlRShortcut
|
if (EnableCtrlRShortcut
|
||||||
&& (InputManager.GetKey(KeyCode.LeftControl) || InputManager.GetKey(KeyCode.RightControl))
|
&& (InputManager.GetKey(KeyCode.LeftControl) || InputManager.GetKey(KeyCode.RightControl))
|
||||||
&& InputManager.GetKeyDown(KeyCode.R))
|
&& InputManager.GetKeyDown(KeyCode.R)
|
||||||
|
&& timeOfLastCtrlR.OccuredEarlierThanDefault())
|
||||||
{
|
{
|
||||||
|
timeOfLastCtrlR = Time.realtimeSinceStartup;
|
||||||
Evaluate(Panel.Input.Text);
|
Evaluate(Panel.Input.Text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -305,7 +343,7 @@ namespace UnityExplorer.UI.CSConsole
|
|||||||
var charBot = charTop - CSCONSOLE_LINEHEIGHT;
|
var charBot = charTop - CSCONSOLE_LINEHEIGHT;
|
||||||
|
|
||||||
var viewportMin = Input.Rect.rect.height - Input.Rect.anchoredPosition.y - (Input.Rect.rect.height * 0.5f);
|
var viewportMin = Input.Rect.rect.height - Input.Rect.anchoredPosition.y - (Input.Rect.rect.height * 0.5f);
|
||||||
var viewportMax = viewportMin - Panel.InputScroll.ViewportRect.rect.height;
|
var viewportMax = viewportMin - Panel.InputScroller.ViewportRect.rect.height;
|
||||||
|
|
||||||
float diff = 0f;
|
float diff = 0f;
|
||||||
if (charTop > viewportMin)
|
if (charTop > viewportMin)
|
||||||
@ -325,18 +363,31 @@ namespace UnityExplorer.UI.CSConsole
|
|||||||
{
|
{
|
||||||
settingCaretCoroutine = true;
|
settingCaretCoroutine = true;
|
||||||
Input.Component.readOnly = true;
|
Input.Component.readOnly = true;
|
||||||
RuntimeProvider.Instance.StartCoroutine(SetAutocompleteCaretCoro(caretPosition));
|
RuntimeProvider.Instance.StartCoroutine(SetCaretCoroutine(caretPosition));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IEnumerator SetAutocompleteCaretCoro(int caretPosition)
|
internal static PropertyInfo SelectionGuardProperty => selectionGuardPropInfo ?? GetSelectionGuardPropInfo();
|
||||||
|
|
||||||
|
private static PropertyInfo GetSelectionGuardPropInfo()
|
||||||
|
{
|
||||||
|
selectionGuardPropInfo = typeof(EventSystem).GetProperty("m_SelectionGuard");
|
||||||
|
if (selectionGuardPropInfo == null)
|
||||||
|
selectionGuardPropInfo = typeof(EventSystem).GetProperty("m_selectionGuard");
|
||||||
|
return selectionGuardPropInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static PropertyInfo selectionGuardPropInfo;
|
||||||
|
|
||||||
|
private static IEnumerator SetCaretCoroutine(int caretPosition)
|
||||||
{
|
{
|
||||||
var color = Input.Component.selectionColor;
|
var color = Input.Component.selectionColor;
|
||||||
color.a = 0f;
|
color.a = 0f;
|
||||||
Input.Component.selectionColor = color;
|
Input.Component.selectionColor = color;
|
||||||
EventSystem.current.SetSelectedGameObject(null, null);
|
try { EventSystem.current.SetSelectedGameObject(null, null); } catch { }
|
||||||
yield return null;
|
yield return null;
|
||||||
|
|
||||||
EventSystem.current.SetSelectedGameObject(Input.UIRoot, null);
|
try { SelectionGuardProperty.SetValue(EventSystem.current, false, null); } catch { }
|
||||||
|
try { EventSystem.current.SetSelectedGameObject(Input.UIRoot, null); } catch { }
|
||||||
Input.Component.Select();
|
Input.Component.Select();
|
||||||
yield return null;
|
yield return null;
|
||||||
|
|
||||||
@ -351,48 +402,91 @@ namespace UnityExplorer.UI.CSConsole
|
|||||||
settingCaretCoroutine = false;
|
settingCaretCoroutine = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#region Lexer Highlighting
|
#region Lexer Highlighting
|
||||||
|
|
||||||
private static void HighlightVisibleInput()
|
/// <summary>
|
||||||
|
/// Returns true if caret is inside string or comment, false otherwise
|
||||||
|
/// </summary>
|
||||||
|
private static bool HighlightVisibleInput()
|
||||||
{
|
{
|
||||||
int startIdx = 0;
|
if (string.IsNullOrEmpty(Input.Text))
|
||||||
int endIdx = Input.Text.Length - 1;
|
|
||||||
int topLine = 0;
|
|
||||||
|
|
||||||
// Calculate visible text if necessary
|
|
||||||
if (Input.Rect.rect.height > Panel.InputScroll.ViewportRect.rect.height)
|
|
||||||
{
|
{
|
||||||
topLine = -1;
|
Panel.HighlightText.text = "";
|
||||||
int bottomLine = -1;
|
Panel.LineNumberText.text = "1";
|
||||||
|
return false;
|
||||||
// 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.Rect.rect.height - Input.Rect.anchoredPosition.y - (Input.Rect.rect.height * 0.5f);
|
|
||||||
var viewportMax = viewportMin - Panel.InputScroll.ViewportRect.rect.height;
|
|
||||||
|
|
||||||
for (int i = 0; i < Input.TextGenerator.lineCount; i++)
|
|
||||||
{
|
|
||||||
var 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;
|
|
||||||
// if bottom of line is below the viewport bottom
|
|
||||||
if ((line.topY - line.height) >= viewportMax)
|
|
||||||
bottomLine = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
topLine = Math.Max(0, topLine - 1);
|
|
||||||
bottomLine = Math.Min(Input.TextGenerator.lineCount - 1, bottomLine + 1);
|
|
||||||
|
|
||||||
startIdx = Input.TextGenerator.lines[topLine].startCharIdx;
|
|
||||||
endIdx = (bottomLine >= Input.TextGenerator.lineCount - 1)
|
|
||||||
? Input.Text.Length - 1
|
|
||||||
: (Input.TextGenerator.lines[bottomLine + 1].startCharIdx - 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Calculate the visible lines
|
||||||
|
|
||||||
|
int topLine = -1;
|
||||||
|
int bottomLine = -1;
|
||||||
|
|
||||||
|
// 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.Rect.rect.height - Input.Rect.anchoredPosition.y - (Input.Rect.rect.height * 0.5f);
|
||||||
|
var viewportMax = viewportMin - Panel.InputScroller.ViewportRect.rect.height;
|
||||||
|
|
||||||
|
for (int i = 0; i < Input.TextGenerator.lineCount; i++)
|
||||||
|
{
|
||||||
|
var 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;
|
||||||
|
// if bottom of line is below the viewport bottom
|
||||||
|
if ((line.topY - line.height) >= viewportMax)
|
||||||
|
bottomLine = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
topLine = Math.Max(0, topLine - 1);
|
||||||
|
bottomLine = Math.Min(Input.TextGenerator.lineCount - 1, bottomLine + 1);
|
||||||
|
|
||||||
|
int startIdx = Input.TextGenerator.lines[topLine].startCharIdx;
|
||||||
|
int endIdx = (bottomLine >= Input.TextGenerator.lineCount - 1)
|
||||||
|
? Input.Text.Length - 1
|
||||||
|
: (Input.TextGenerator.lines[bottomLine + 1].startCharIdx - 1);
|
||||||
|
|
||||||
|
|
||||||
// Highlight the visible text with the LexerBuilder
|
// Highlight the visible text with the LexerBuilder
|
||||||
Panel.HighlightText.text = Lexer.BuildHighlightedString(Input.Text, startIdx, endIdx, topLine);
|
|
||||||
|
Panel.HighlightText.text = Lexer.BuildHighlightedString(Input.Text, startIdx, endIdx, topLine, LastCaretPosition, out bool ret);
|
||||||
|
|
||||||
|
// Set the line numbers
|
||||||
|
|
||||||
|
// determine true starting line number (not the same as the cached TextGenerator line numbers)
|
||||||
|
int realStartLine = 0;
|
||||||
|
for (int i = 0; i < startIdx; i++)
|
||||||
|
{
|
||||||
|
if (LexerBuilder.IsNewLine(Input.Text[i]))
|
||||||
|
realStartLine++;
|
||||||
|
}
|
||||||
|
realStartLine++;
|
||||||
|
char lastPrev = '\n';
|
||||||
|
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
|
||||||
|
// append leading new lines for spacing (no point rendering line numbers we cant see)
|
||||||
|
for (int i = 0; i < topLine; i++)
|
||||||
|
sb.Append('\n');
|
||||||
|
|
||||||
|
// append the displayed line numbers
|
||||||
|
for (int i = topLine; i <= bottomLine; i++)
|
||||||
|
{
|
||||||
|
if (i > 0)
|
||||||
|
lastPrev = Input.Text[Input.TextGenerator.lines[i].startCharIdx - 1];
|
||||||
|
|
||||||
|
// previous line ended with a newline character, this is an actual new line.
|
||||||
|
if (LexerBuilder.IsNewLine(lastPrev))
|
||||||
|
{
|
||||||
|
sb.Append(realStartLine.ToString());
|
||||||
|
realStartLine++;
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.Append('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
Panel.LineNumberText.text = sb.ToString();
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@ -526,7 +620,9 @@ If the game was built with Unity's stubbed netstandard 2.0 runtime, you can fix
|
|||||||
internal const string STARTUP_TEXT = @"<color=#5d8556>// Welcome to the UnityExplorer C# Console!
|
internal const string STARTUP_TEXT = @"<color=#5d8556>// Welcome to the UnityExplorer C# Console!
|
||||||
|
|
||||||
// It is recommended to use the Log panel (or a console log window) while using this tool.
|
// 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.</color>";
|
// 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>";
|
||||||
|
|
||||||
internal const string HELP_USINGS = @"// You can add a using directive to any namespace, but you must compile for it to take effect.
|
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.
|
// It will remain in effect until you Reset the console.
|
@ -5,14 +5,16 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.UI.CSConsole.Lexers;
|
using UnityExplorer.CSConsole.Lexers;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.CSConsole
|
namespace UnityExplorer.CSConsole
|
||||||
{
|
{
|
||||||
public struct MatchInfo
|
public struct MatchInfo
|
||||||
{
|
{
|
||||||
public int startIndex;
|
public int startIndex;
|
||||||
public int endIndex;
|
public int endIndex;
|
||||||
|
public bool isStringOrComment;
|
||||||
|
public bool matchToEndOfLine;
|
||||||
public string htmlColorTag;
|
public string htmlColorTag;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,8 +84,10 @@ namespace UnityExplorer.UI.CSConsole
|
|||||||
/// <param name="endIdx">The last character you want to highlight</param>
|
/// <param name="endIdx">The last character you want to highlight</param>
|
||||||
/// <param name="leadingLines">The amount of leading empty lines you want before the first character in the return string.</param>
|
/// <param name="leadingLines">The amount of leading empty lines you want before the first character in the return string.</param>
|
||||||
/// <returns>A string which contains the amount of leading lines specified, as well as the rich-text highlighted section.</returns>
|
/// <returns>A string which contains the amount of leading lines specified, as well as the rich-text highlighted section.</returns>
|
||||||
public string BuildHighlightedString(string input, int startIdx, int endIdx, int leadingLines)
|
public string BuildHighlightedString(string input, int startIdx, int endIdx, int leadingLines, int caretIdx, out bool caretInStringOrComment)
|
||||||
{
|
{
|
||||||
|
caretInStringOrComment = false;
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(input) || endIdx <= startIdx)
|
if (string.IsNullOrEmpty(input) || endIdx <= startIdx)
|
||||||
return input;
|
return input;
|
||||||
|
|
||||||
@ -105,14 +109,28 @@ namespace UnityExplorer.UI.CSConsole
|
|||||||
|
|
||||||
// append the highlighted match
|
// append the highlighted match
|
||||||
sb.Append(match.htmlColorTag);
|
sb.Append(match.htmlColorTag);
|
||||||
|
|
||||||
for (int i = match.startIndex; i <= match.endIndex && i <= currentEndIdx; i++)
|
for (int i = match.startIndex; i <= match.endIndex && i <= currentEndIdx; i++)
|
||||||
sb.Append(input[i]);
|
sb.Append(input[i]);
|
||||||
|
|
||||||
sb.Append(SignatureHighlighter.CLOSE_COLOR);
|
sb.Append(SignatureHighlighter.CLOSE_COLOR);
|
||||||
|
|
||||||
// update the last unhighlighted start index
|
// update the last unhighlighted start index
|
||||||
lastUnhighlighted = match.endIndex + 1;
|
lastUnhighlighted = match.endIndex + 1;
|
||||||
|
|
||||||
|
int matchEndIdx = match.endIndex;
|
||||||
|
if (match.matchToEndOfLine)
|
||||||
|
{
|
||||||
|
while (input.Length - 1 >= matchEndIdx)
|
||||||
|
{
|
||||||
|
if (IsNewLine(input[matchEndIdx]))
|
||||||
|
break;
|
||||||
|
matchEndIdx++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check caretIdx to determine inStringOrComment state
|
||||||
|
if (caretIdx >= match.startIndex && (caretIdx <= matchEndIdx || (caretIdx >= input.Length && matchEndIdx >= input.Length - 1)))
|
||||||
|
caretInStringOrComment = match.isStringOrComment;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Append trailing unhighlighted input
|
// Append trailing unhighlighted input
|
||||||
@ -150,6 +168,7 @@ namespace UnityExplorer.UI.CSConsole
|
|||||||
startIndex = startIndex,
|
startIndex = startIndex,
|
||||||
endIndex = CommittedIndex,
|
endIndex = CommittedIndex,
|
||||||
htmlColorTag = lexer.ColorTag,
|
htmlColorTag = lexer.ColorTag,
|
||||||
|
isStringOrComment = lexer is StringLexer || lexer is CommentLexer,
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
}
|
}
|
@ -2,7 +2,7 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.CSConsole.Lexers
|
namespace UnityExplorer.CSConsole.Lexers
|
||||||
{
|
{
|
||||||
public class CommentLexer : Lexer
|
public class CommentLexer : Lexer
|
||||||
{
|
{
|
||||||
@ -44,7 +44,7 @@ namespace UnityExplorer.UI.CSConsole.Lexers
|
|||||||
while (!lexer.EndOfInput && !(lexer.Current == '/' && lexer.Previous == '*'));
|
while (!lexer.EndOfInput && !(lexer.Current == '/' && lexer.Previous == '*'));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
@ -2,7 +2,7 @@
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.CSConsole.Lexers
|
namespace UnityExplorer.CSConsole.Lexers
|
||||||
{
|
{
|
||||||
public class KeywordLexer : Lexer
|
public class KeywordLexer : Lexer
|
||||||
{
|
{
|
||||||
@ -12,12 +12,12 @@ namespace UnityExplorer.UI.CSConsole.Lexers
|
|||||||
public static readonly HashSet<string> keywords = new HashSet<string>
|
public static readonly HashSet<string> keywords = new HashSet<string>
|
||||||
{
|
{
|
||||||
// reserved keywords
|
// reserved keywords
|
||||||
"abstract", "as", "base", "bool", "break", "byte", "case", "catch", "char", "checked", "class", "const", "continue",
|
"abstract", "as", "base", "bool", "break", "byte", "case", "catch", "char", "checked", "class", "const", "continue",
|
||||||
"decimal", "default", "delegate", "do", "double", "else", "enum", "event", "explicit", "extern", "false", "finally",
|
"decimal", "default", "delegate", "do", "double", "else", "enum", "event", "explicit", "extern", "false", "finally",
|
||||||
"fixed", "float", "for", "foreach", "goto", "if", "implicit", "in", "int", "interface", "internal", "is", "lock",
|
"fixed", "float", "for", "foreach", "goto", "if", "implicit", "in", "int", "interface", "internal", "is", "lock",
|
||||||
"long", "namespace", "new", "null", "object", "operator", "out", "override", "params", "private", "protected", "public",
|
"long", "namespace", "new", "null", "object", "operator", "out", "override", "params", "private", "protected", "public",
|
||||||
"readonly", "ref", "return", "sbyte", "sealed", "short", "sizeof", "stackalloc", "static", "string", "struct", "switch",
|
"readonly", "ref", "return", "sbyte", "sealed", "short", "sizeof", "stackalloc", "static", "string", "struct", "switch",
|
||||||
"this", "throw", "true", "try", "typeof", "uint", "ulong", "unchecked", "unsafe", "ushort", "using", "virtual", "void",
|
"this", "throw", "true", "try", "typeof", "uint", "ulong", "unchecked", "unsafe", "ushort", "using", "virtual", "void",
|
||||||
"volatile", "while",
|
"volatile", "while",
|
||||||
// contextual keywords
|
// contextual keywords
|
||||||
"add", "and", "alias", "ascending", "async", "await", "by", "descending", "dynamic", "equals", "from", "get",
|
"add", "and", "alias", "ascending", "async", "await", "by", "descending", "dynamic", "equals", "from", "get",
|
||||||
@ -41,6 +41,10 @@ namespace UnityExplorer.UI.CSConsole.Lexers
|
|||||||
while (!lexer.EndOfInput && char.IsLetter(lexer.PeekNext()))
|
while (!lexer.EndOfInput && char.IsLetter(lexer.PeekNext()))
|
||||||
sb.Append(lexer.Current);
|
sb.Append(lexer.Current);
|
||||||
|
|
||||||
|
// next must be whitespace or delimiter
|
||||||
|
if (!lexer.EndOfInput && !(char.IsWhiteSpace(lexer.Current) || lexer.IsDelimiter(lexer.Current)))
|
||||||
|
return false;
|
||||||
|
|
||||||
if (keywords.Contains(sb.ToString()))
|
if (keywords.Contains(sb.ToString()))
|
||||||
{
|
{
|
||||||
if (!lexer.EndOfInput)
|
if (!lexer.EndOfInput)
|
@ -1,8 +1,8 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using UnityEngine;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.CSConsole.Lexers
|
namespace UnityExplorer.CSConsole.Lexers
|
||||||
{
|
{
|
||||||
public abstract class Lexer
|
public abstract class Lexer
|
||||||
{
|
{
|
@ -1,6 +1,6 @@
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.CSConsole.Lexers
|
namespace UnityExplorer.CSConsole.Lexers
|
||||||
{
|
{
|
||||||
public class NumberLexer : Lexer
|
public class NumberLexer : Lexer
|
||||||
{
|
{
|
@ -1,7 +1,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.CSConsole.Lexers
|
namespace UnityExplorer.CSConsole.Lexers
|
||||||
{
|
{
|
||||||
public class StringLexer : Lexer
|
public class StringLexer : Lexer
|
||||||
{
|
{
|
@ -3,7 +3,7 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.CSConsole.Lexers
|
namespace UnityExplorer.CSConsole.Lexers
|
||||||
{
|
{
|
||||||
public class SymbolLexer : Lexer
|
public class SymbolLexer : Lexer
|
||||||
{
|
{
|
||||||
@ -11,7 +11,7 @@ namespace UnityExplorer.UI.CSConsole.Lexers
|
|||||||
protected override Color HighlightColor => new Color(0.6f, 0.6f, 0.6f);
|
protected override Color HighlightColor => new Color(0.6f, 0.6f, 0.6f);
|
||||||
|
|
||||||
// all symbols are delimiters
|
// all symbols are delimiters
|
||||||
public override IEnumerable<char> Delimiters => symbols;
|
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 bool IsSymbol(char c) => symbols.Contains(c);
|
||||||
|
|
@ -1,13 +1,13 @@
|
|||||||
using System;
|
using Mono.CSharp;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Mono.CSharp;
|
|
||||||
|
|
||||||
// Thanks to ManlyMarco for this
|
// Thanks to ManlyMarco for this
|
||||||
|
|
||||||
namespace UnityExplorer.UI.CSConsole
|
namespace UnityExplorer.CSConsole
|
||||||
{
|
{
|
||||||
public class ScriptEvaluator : Evaluator, IDisposable
|
public class ScriptEvaluator : Evaluator, IDisposable
|
||||||
{
|
{
|
@ -1,11 +1,11 @@
|
|||||||
using System;
|
using Mono.CSharp;
|
||||||
using Mono.CSharp;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using UnityEngine;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using UnityExplorer.Core.Runtime;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityExplorer.Core.Runtime;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Welcome to the UnityExplorer C# Console!
|
Welcome to the UnityExplorer C# Console!
|
||||||
@ -13,7 +13,7 @@ using System.Text;
|
|||||||
To see your output, use the Log panel or a Console Log window.
|
To see your output, use the Log panel or a Console Log window.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace UnityExplorer.UI.CSConsole
|
namespace UnityExplorer.CSConsole
|
||||||
{
|
{
|
||||||
public class ScriptInteraction : InteractiveBase
|
public class ScriptInteraction : InteractiveBase
|
||||||
{
|
{
|
||||||
@ -58,7 +58,7 @@ namespace UnityExplorer.UI.CSConsole
|
|||||||
public static void GetClasses()
|
public static void GetClasses()
|
||||||
{
|
{
|
||||||
if (ReflectionUtility.GetFieldInfo(typeof(Evaluator), "source_file")
|
if (ReflectionUtility.GetFieldInfo(typeof(Evaluator), "source_file")
|
||||||
.GetValue(Evaluator) is CompilationSourceFile sourceFile
|
.GetValue(Evaluator) is CompilationSourceFile sourceFile
|
||||||
&& sourceFile.Containers.Any())
|
&& sourceFile.Containers.Any())
|
||||||
{
|
{
|
||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
@ -3,9 +3,9 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityExplorer.Core.Config;
|
using UnityExplorer.Core.Config;
|
||||||
using UnityExplorer.UI.CacheObject.Views;
|
using UnityExplorer.CacheObject.Views;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.CacheObject
|
namespace UnityExplorer.CacheObject
|
||||||
{
|
{
|
||||||
public class CacheConfigEntry : CacheObjectBase
|
public class CacheConfigEntry : CacheObjectBase
|
||||||
{
|
{
|
@ -3,9 +3,9 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityExplorer.UI.Inspectors;
|
using UnityExplorer.Inspectors;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.CacheObject
|
namespace UnityExplorer.CacheObject
|
||||||
{
|
{
|
||||||
public class CacheField : CacheMember
|
public class CacheField : CacheMember
|
||||||
{
|
{
|
@ -2,11 +2,10 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityExplorer.UI.CacheObject.Views;
|
using UnityExplorer.CacheObject.IValues;
|
||||||
using UnityExplorer.UI.IValues;
|
using UnityExplorer.CacheObject.Views;
|
||||||
using UnityExplorer.UI.Utility;
|
|
||||||
|
|
||||||
namespace UnityExplorer.UI.CacheObject
|
namespace UnityExplorer.CacheObject
|
||||||
{
|
{
|
||||||
public class CacheKeyValuePair : CacheObjectBase
|
public class CacheKeyValuePair : CacheObjectBase
|
||||||
{
|
{
|
@ -2,10 +2,10 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityExplorer.UI.CacheObject.Views;
|
using UnityExplorer.CacheObject.IValues;
|
||||||
using UnityExplorer.UI.IValues;
|
using UnityExplorer.CacheObject.Views;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.CacheObject
|
namespace UnityExplorer.CacheObject
|
||||||
{
|
{
|
||||||
public class CacheListEntry : CacheObjectBase
|
public class CacheListEntry : CacheObjectBase
|
||||||
{
|
{
|
@ -5,18 +5,18 @@ using System.Reflection;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityExplorer.Core.Runtime;
|
using UnityExplorer.Core.Runtime;
|
||||||
using UnityExplorer.UI.CacheObject.Views;
|
using UnityExplorer.CacheObject.Views;
|
||||||
using UnityExplorer.UI.Inspectors;
|
using UnityExplorer.Inspectors;
|
||||||
using UnityExplorer.UI.ObjectPool;
|
using UnityExplorer.UI.Models;
|
||||||
using UnityExplorer.UI.Utility;
|
using UnityExplorer.UI;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.CacheObject
|
namespace UnityExplorer.CacheObject
|
||||||
{
|
{
|
||||||
public abstract class CacheMember : CacheObjectBase
|
public abstract class CacheMember : CacheObjectBase
|
||||||
{
|
{
|
||||||
//public ReflectionInspector ParentInspector { get; internal set; }
|
//public ReflectionInspector ParentInspector { get; internal set; }
|
||||||
//public bool AutoUpdateWanted { get; internal set; }
|
//public bool AutoUpdateWanted { get; internal set; }
|
||||||
|
|
||||||
public abstract Type DeclaringType { get; }
|
public abstract Type DeclaringType { get; }
|
||||||
public string NameForFiltering { get; protected set; }
|
public string NameForFiltering { get; protected set; }
|
||||||
public object DeclaringInstance => IsStatic ? null : (m_declaringInstance ?? (m_declaringInstance = Owner.Target.TryCast(DeclaringType)));
|
public object DeclaringInstance => IsStatic ? null : (m_declaringInstance ?? (m_declaringInstance = Owner.Target.TryCast(DeclaringType)));
|
||||||
@ -28,7 +28,7 @@ namespace UnityExplorer.UI.CacheObject
|
|||||||
public Type[] GenericArguments { get; protected set; } = ArgumentUtility.EmptyTypes;
|
public Type[] GenericArguments { get; protected set; } = ArgumentUtility.EmptyTypes;
|
||||||
public EvaluateWidget Evaluator { get; protected set; }
|
public EvaluateWidget Evaluator { get; protected set; }
|
||||||
public bool Evaluating => Evaluator != null && Evaluator.UIRoot.activeSelf;
|
public bool Evaluating => Evaluator != null && Evaluator.UIRoot.activeSelf;
|
||||||
|
|
||||||
public virtual void SetInspectorOwner(ReflectionInspector inspector, MemberInfo member)
|
public virtual void SetInspectorOwner(ReflectionInspector inspector, MemberInfo member)
|
||||||
{
|
{
|
||||||
this.Owner = inspector;
|
this.Owner = inspector;
|
||||||
@ -235,7 +235,7 @@ namespace UnityExplorer.UI.CacheObject
|
|||||||
return sorted;
|
return sorted;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void TryCacheMember(MemberInfo member, List<CacheMember> list, HashSet<string> cachedSigs,
|
private static void TryCacheMember(MemberInfo member, List<CacheMember> list, HashSet<string> cachedSigs,
|
||||||
Type declaringType, ReflectionInspector _inspector, bool ignorePropertyMethodInfos = true)
|
Type declaringType, ReflectionInspector _inspector, bool ignorePropertyMethodInfos = true)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@ -254,7 +254,7 @@ namespace UnityExplorer.UI.CacheObject
|
|||||||
case MemberTypes.Method:
|
case MemberTypes.Method:
|
||||||
{
|
{
|
||||||
var mi = member as MethodInfo;
|
var mi = member as MethodInfo;
|
||||||
if (ignorePropertyMethodInfos
|
if (ignorePropertyMethodInfos
|
||||||
&& (mi.Name.StartsWith("get_") || mi.Name.StartsWith("set_")))
|
&& (mi.Name.StartsWith("get_") || mi.Name.StartsWith("set_")))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -323,7 +323,7 @@ namespace UnityExplorer.UI.CacheObject
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static string GetSig(MemberInfo member)
|
internal static string GetSig(MemberInfo member)
|
||||||
=> $"{member.DeclaringType.Name}.{member.Name}";
|
=> $"{member.DeclaringType.Name}.{member.Name}";
|
||||||
|
|
||||||
internal static string GetArgumentString(ParameterInfo[] args)
|
internal static string GetArgumentString(ParameterInfo[] args)
|
@ -3,9 +3,9 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityExplorer.UI.Inspectors;
|
using UnityExplorer.Inspectors;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.CacheObject
|
namespace UnityExplorer.CacheObject
|
||||||
{
|
{
|
||||||
public class CacheMethod : CacheMember
|
public class CacheMethod : CacheMember
|
||||||
{
|
{
|
@ -7,12 +7,12 @@ using System.Text;
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.Core.Runtime;
|
using UnityExplorer.Core.Runtime;
|
||||||
using UnityExplorer.UI.CacheObject.Views;
|
using UnityExplorer.CacheObject.IValues;
|
||||||
using UnityExplorer.UI.IValues;
|
using UnityExplorer.CacheObject.Views;
|
||||||
using UnityExplorer.UI.ObjectPool;
|
using UnityExplorer.UI.Models;
|
||||||
using UnityExplorer.UI.Utility;
|
using UnityExplorer.UI;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.CacheObject
|
namespace UnityExplorer.CacheObject
|
||||||
{
|
{
|
||||||
public enum ValueState
|
public enum ValueState
|
||||||
{
|
{
|
||||||
@ -181,8 +181,8 @@ namespace UnityExplorer.UI.CacheObject
|
|||||||
return ValueState.Enum;
|
return ValueState.Enum;
|
||||||
else if (type == typeof(Color) || type == typeof(Color32))
|
else if (type == typeof(Color) || type == typeof(Color32))
|
||||||
return ValueState.Color;
|
return ValueState.Color;
|
||||||
else if (InteractiveValueStruct.SupportsType(type))
|
else if (InteractiveValueStruct.SupportsType(type))
|
||||||
return ValueState.ValueStruct;
|
return ValueState.ValueStruct;
|
||||||
else if (ReflectionUtility.IsDictionary(type))
|
else if (ReflectionUtility.IsDictionary(type))
|
||||||
return ValueState.Dictionary;
|
return ValueState.Dictionary;
|
||||||
else if (!typeof(Transform).IsAssignableFrom(type) && ReflectionUtility.IsEnumerable(type))
|
else if (!typeof(Transform).IsAssignableFrom(type) && ReflectionUtility.IsEnumerable(type))
|
||||||
@ -198,7 +198,7 @@ namespace UnityExplorer.UI.CacheObject
|
|||||||
switch (State)
|
switch (State)
|
||||||
{
|
{
|
||||||
case ValueState.NotEvaluated:
|
case ValueState.NotEvaluated:
|
||||||
return $"<i>{NOT_YET_EVAL} ({SignatureHighlighter.Parse(FallbackType, true)})</i>";
|
return $"<i>{NOT_YET_EVAL} ({SignatureHighlighter.Parse(FallbackType, true)})</i>";
|
||||||
|
|
||||||
case ValueState.Exception:
|
case ValueState.Exception:
|
||||||
return $"<i><color=red>{LastException.ReflectionExToString()}</color></i>";
|
return $"<i><color=red>{LastException.ReflectionExToString()}</color></i>";
|
||||||
@ -222,7 +222,7 @@ namespace UnityExplorer.UI.CacheObject
|
|||||||
return $"\"{ToStringUtility.PruneString(s, 200, 5)}\"";
|
return $"\"{ToStringUtility.PruneString(s, 200, 5)}\"";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// try to prefix the count of the collection for lists and dicts
|
// try to prefix the count of the collection for lists and dicts
|
||||||
case ValueState.Collection:
|
case ValueState.Collection:
|
||||||
if (!LastValueWasNull)
|
if (!LastValueWasNull)
|
||||||
@ -264,7 +264,7 @@ namespace UnityExplorer.UI.CacheObject
|
|||||||
|
|
||||||
cell.SubContentHolder.gameObject.SetActive(SubContentShowWanted);
|
cell.SubContentHolder.gameObject.SetActive(SubContentShowWanted);
|
||||||
if (IValue != null)
|
if (IValue != null)
|
||||||
{
|
{
|
||||||
IValue.UIRoot.transform.SetParent(cell.SubContentHolder.transform, false);
|
IValue.UIRoot.transform.SetParent(cell.SubContentHolder.transform, false);
|
||||||
IValue.SetLayout();
|
IValue.SetLayout();
|
||||||
}
|
}
|
@ -3,9 +3,9 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityExplorer.UI.Inspectors;
|
using UnityExplorer.Inspectors;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.CacheObject
|
namespace UnityExplorer.CacheObject
|
||||||
{
|
{
|
||||||
public class CacheProperty : CacheMember
|
public class CacheProperty : CacheMember
|
||||||
{
|
{
|
||||||
@ -28,10 +28,11 @@ namespace UnityExplorer.UI.CacheObject
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
object ret;
|
||||||
if (HasArguments)
|
if (HasArguments)
|
||||||
return PropertyInfo.GetValue(DeclaringInstance, this.Evaluator.TryParseArguments());
|
ret = PropertyInfo.GetValue(DeclaringInstance, this.Evaluator.TryParseArguments());
|
||||||
|
else
|
||||||
var ret = PropertyInfo.GetValue(DeclaringInstance, null);
|
ret = PropertyInfo.GetValue(DeclaringInstance, null);
|
||||||
HadException = false;
|
HadException = false;
|
||||||
LastException = null;
|
LastException = null;
|
||||||
return ret;
|
return ret;
|
@ -3,10 +3,10 @@ using System.Collections;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityExplorer.UI.CacheObject;
|
using UnityExplorer.CacheObject;
|
||||||
using UnityExplorer.UI.CacheObject.Views;
|
using UnityExplorer.CacheObject.Views;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.CacheObject
|
namespace UnityExplorer.CacheObject
|
||||||
{
|
{
|
||||||
public interface ICacheObjectController
|
public interface ICacheObjectController
|
||||||
{
|
{
|
@ -4,9 +4,10 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.UI.CacheObject;
|
using UnityExplorer.CacheObject;
|
||||||
|
using UnityExplorer.UI;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.IValues
|
namespace UnityExplorer.CacheObject.IValues
|
||||||
{
|
{
|
||||||
public class InteractiveColor : InteractiveValue
|
public class InteractiveColor : InteractiveValue
|
||||||
{
|
{
|
@ -5,14 +5,14 @@ using System.Linq;
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.UI.CacheObject;
|
using UnityExplorer.CacheObject;
|
||||||
using UnityExplorer.UI.CacheObject.Views;
|
using UnityExplorer.CacheObject.Views;
|
||||||
using UnityExplorer.UI.Inspectors;
|
using UnityExplorer.Inspectors;
|
||||||
|
using UnityExplorer.UI;
|
||||||
using UnityExplorer.UI.Panels;
|
using UnityExplorer.UI.Panels;
|
||||||
using UnityExplorer.UI.Utility;
|
|
||||||
using UnityExplorer.UI.Widgets;
|
using UnityExplorer.UI.Widgets;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.IValues
|
namespace UnityExplorer.CacheObject.IValues
|
||||||
{
|
{
|
||||||
public class InteractiveDictionary : InteractiveValue, ICellPoolDataSource<CacheKeyValuePairCell>, ICacheObjectController
|
public class InteractiveDictionary : InteractiveValue, ICellPoolDataSource<CacheKeyValuePairCell>, ICacheObjectController
|
||||||
{
|
{
|
@ -5,9 +5,10 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.UI.CacheObject;
|
using UnityExplorer.CacheObject;
|
||||||
|
using UnityExplorer.UI;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.IValues
|
namespace UnityExplorer.CacheObject.IValues
|
||||||
{
|
{
|
||||||
public class InteractiveEnum : InteractiveValue
|
public class InteractiveEnum : InteractiveValue
|
||||||
{
|
{
|
||||||
@ -20,7 +21,7 @@ namespace UnityExplorer.UI.IValues
|
|||||||
|
|
||||||
public CachedEnumValue ValueAtIdx(int idx) => (CachedEnumValue)CurrentValues[idx];
|
public CachedEnumValue ValueAtIdx(int idx) => (CachedEnumValue)CurrentValues[idx];
|
||||||
public CachedEnumValue ValueAtKey(object key) => (CachedEnumValue)CurrentValues[key];
|
public CachedEnumValue ValueAtKey(object key) => (CachedEnumValue)CurrentValues[key];
|
||||||
|
|
||||||
private Dropdown enumDropdown;
|
private Dropdown enumDropdown;
|
||||||
private GameObject toggleHolder;
|
private GameObject toggleHolder;
|
||||||
private readonly List<Toggle> flagToggles = new List<Toggle>();
|
private readonly List<Toggle> flagToggles = new List<Toggle>();
|
@ -5,14 +5,14 @@ using System.Linq;
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.UI.CacheObject;
|
using UnityExplorer.CacheObject;
|
||||||
using UnityExplorer.UI.CacheObject.Views;
|
using UnityExplorer.CacheObject.Views;
|
||||||
using UnityExplorer.UI.Inspectors;
|
using UnityExplorer.Inspectors;
|
||||||
|
using UnityExplorer.UI;
|
||||||
using UnityExplorer.UI.Panels;
|
using UnityExplorer.UI.Panels;
|
||||||
using UnityExplorer.UI.Utility;
|
|
||||||
using UnityExplorer.UI.Widgets;
|
using UnityExplorer.UI.Widgets;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.IValues
|
namespace UnityExplorer.CacheObject.IValues
|
||||||
{
|
{
|
||||||
public class InteractiveList : InteractiveValue, ICellPoolDataSource<CacheListEntryCell>, ICacheObjectController
|
public class InteractiveList : InteractiveValue, ICellPoolDataSource<CacheListEntryCell>, ICacheObjectController
|
||||||
{
|
{
|
||||||
@ -207,7 +207,7 @@ namespace UnityExplorer.UI.IValues
|
|||||||
{
|
{
|
||||||
ExplorerCore.LogWarning($"Exception setting IList value: {ex}");
|
ExplorerCore.LogWarning($"Exception setting IList value: {ex}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// List entry scroll pool
|
// List entry scroll pool
|
||||||
|
|
||||||
@ -255,8 +255,8 @@ namespace UnityExplorer.UI.IValues
|
|||||||
ListScrollPool.Initialize(this, SetLayout);
|
ListScrollPool.Initialize(this, SetLayout);
|
||||||
scrollLayout = scrollObj.GetComponent<LayoutElement>();
|
scrollLayout = scrollObj.GetComponent<LayoutElement>();
|
||||||
|
|
||||||
NotSupportedLabel = UIFactory.CreateLabel(ListScrollPool.Content.gameObject, "NotSupportedMessage",
|
NotSupportedLabel = UIFactory.CreateLabel(ListScrollPool.Content.gameObject, "NotSupportedMessage",
|
||||||
"The IEnumerable failed to enumerate. This is likely due to an issue with Unhollowed interfaces.",
|
"The IEnumerable failed to enumerate. This is likely due to an issue with Unhollowed interfaces.",
|
||||||
TextAnchor.MiddleLeft, Color.red);
|
TextAnchor.MiddleLeft, Color.red);
|
||||||
|
|
||||||
UIFactory.SetLayoutElement(NotSupportedLabel.gameObject, minHeight: 25, flexibleWidth: 9999);
|
UIFactory.SetLayoutElement(NotSupportedLabel.gameObject, minHeight: 25, flexibleWidth: 9999);
|
@ -6,10 +6,11 @@ using System.Text;
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.Core.Config;
|
using UnityExplorer.Core.Config;
|
||||||
using UnityExplorer.UI.CacheObject;
|
using UnityExplorer.CacheObject;
|
||||||
using UnityExplorer.UI.Widgets;
|
using UnityExplorer.UI.Widgets;
|
||||||
|
using UnityExplorer.UI;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.IValues
|
namespace UnityExplorer.CacheObject.IValues
|
||||||
{
|
{
|
||||||
public class InteractiveString : InteractiveValue
|
public class InteractiveString : InteractiveValue
|
||||||
{
|
{
|
||||||
@ -18,7 +19,7 @@ namespace UnityExplorer.UI.IValues
|
|||||||
|
|
||||||
public InputFieldRef inputField;
|
public InputFieldRef inputField;
|
||||||
public ButtonRef ApplyButton;
|
public ButtonRef ApplyButton;
|
||||||
|
|
||||||
public GameObject SaveFileRow;
|
public GameObject SaveFileRow;
|
||||||
public InputFieldRef SaveFilePath;
|
public InputFieldRef SaveFilePath;
|
||||||
|
|
||||||
@ -36,7 +37,7 @@ namespace UnityExplorer.UI.IValues
|
|||||||
{
|
{
|
||||||
if (s == null)
|
if (s == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return s.Length >= UIManager.MAX_INPUTFIELD_CHARS;
|
return s.Length >= UIManager.MAX_INPUTFIELD_CHARS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,7 +84,7 @@ namespace UnityExplorer.UI.IValues
|
|||||||
|
|
||||||
if (File.Exists(path))
|
if (File.Exists(path))
|
||||||
File.Delete(path);
|
File.Delete(path);
|
||||||
|
|
||||||
File.WriteAllText(path, RealValue);
|
File.WriteAllText(path, RealValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,7 +99,7 @@ namespace UnityExplorer.UI.IValues
|
|||||||
UIFactory.SetLayoutElement(SaveFileRow, flexibleWidth: 9999);
|
UIFactory.SetLayoutElement(SaveFileRow, flexibleWidth: 9999);
|
||||||
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(SaveFileRow, false, true, true, true, 3);
|
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(SaveFileRow, false, true, true, true, 3);
|
||||||
|
|
||||||
UIFactory.CreateLabel(SaveFileRow, "Info", "<color=red>String is too long! Save to file if you want to see the full string.</color>",
|
UIFactory.CreateLabel(SaveFileRow, "Info", "<color=red>String is too long! Save to file if you want to see the full string.</color>",
|
||||||
TextAnchor.MiddleLeft);
|
TextAnchor.MiddleLeft);
|
||||||
|
|
||||||
var horizRow = UIFactory.CreateUIObject("Horiz", SaveFileRow);
|
var horizRow = UIFactory.CreateUIObject("Horiz", SaveFileRow);
|
@ -4,10 +4,11 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.UI.CacheObject;
|
using UnityExplorer.CacheObject;
|
||||||
using UnityExplorer.UI.ObjectPool;
|
using UnityExplorer.UI;
|
||||||
|
using UnityExplorer.UI.Models;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.IValues
|
namespace UnityExplorer.CacheObject.IValues
|
||||||
{
|
{
|
||||||
public abstract class InteractiveValue : IPooledObject
|
public abstract class InteractiveValue : IPooledObject
|
||||||
{
|
{
|
@ -5,10 +5,10 @@ using System.Reflection;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.UI.CacheObject;
|
using UnityExplorer.CacheObject;
|
||||||
using UnityExplorer.UI.Utility;
|
using UnityExplorer.UI;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.IValues
|
namespace UnityExplorer.CacheObject.IValues
|
||||||
{
|
{
|
||||||
public class InteractiveValueStruct : InteractiveValue
|
public class InteractiveValueStruct : InteractiveValue
|
||||||
{
|
{
|
||||||
@ -144,7 +144,7 @@ namespace UnityExplorer.UI.IValues
|
|||||||
ExplorerCore.LogWarning("Exception setting value: " + ex);
|
ExplorerCore.LogWarning("Exception setting value: " + ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// UI Setup for type
|
// UI Setup for type
|
||||||
|
|
||||||
private void SetupUIForType()
|
private void SetupUIForType()
|
@ -4,8 +4,9 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
|
using UnityExplorer.UI;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.CacheObject.Views
|
namespace UnityExplorer.CacheObject.Views
|
||||||
{
|
{
|
||||||
public class ConfigEntryCell : CacheObjectCell
|
public class ConfigEntryCell : CacheObjectCell
|
||||||
{
|
{
|
@ -4,11 +4,12 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.UI.Inspectors;
|
using UnityExplorer.CacheObject.IValues;
|
||||||
using UnityExplorer.UI.IValues;
|
using UnityExplorer.Inspectors;
|
||||||
|
using UnityExplorer.UI;
|
||||||
using UnityExplorer.UI.Widgets;
|
using UnityExplorer.UI.Widgets;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.CacheObject.Views
|
namespace UnityExplorer.CacheObject.Views
|
||||||
{
|
{
|
||||||
public class CacheKeyValuePairCell : CacheObjectCell
|
public class CacheKeyValuePairCell : CacheObjectCell
|
||||||
{
|
{
|
@ -4,9 +4,9 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.UI.IValues;
|
using UnityExplorer.CacheObject.IValues;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.CacheObject.Views
|
namespace UnityExplorer.CacheObject.Views
|
||||||
{
|
{
|
||||||
public class CacheListEntryCell : CacheObjectCell
|
public class CacheListEntryCell : CacheObjectCell
|
||||||
{
|
{
|
@ -4,9 +4,10 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
|
using UnityExplorer.UI;
|
||||||
using UnityExplorer.UI.Widgets;
|
using UnityExplorer.UI.Widgets;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.CacheObject.Views
|
namespace UnityExplorer.CacheObject.Views
|
||||||
{
|
{
|
||||||
public class CacheMemberCell : CacheObjectCell
|
public class CacheMemberCell : CacheObjectCell
|
||||||
{
|
{
|
@ -4,13 +4,12 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.UI.Inspectors;
|
using UnityExplorer.CacheObject.IValues;
|
||||||
using UnityExplorer.UI.IValues;
|
using UnityExplorer.Inspectors;
|
||||||
using UnityExplorer.UI.ObjectPool;
|
using UnityExplorer.UI;
|
||||||
using UnityExplorer.UI.Utility;
|
|
||||||
using UnityExplorer.UI.Widgets;
|
using UnityExplorer.UI.Widgets;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.CacheObject.Views
|
namespace UnityExplorer.CacheObject.Views
|
||||||
{
|
{
|
||||||
public abstract class CacheObjectCell : ICell
|
public abstract class CacheObjectCell : ICell
|
||||||
{
|
{
|
@ -5,11 +5,11 @@ using System.Reflection;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.UI.ObjectPool;
|
using UnityExplorer.UI;
|
||||||
using UnityExplorer.UI.Utility;
|
using UnityExplorer.UI.Models;
|
||||||
using UnityExplorer.UI.Widgets.AutoComplete;
|
using UnityExplorer.UI.Widgets.AutoComplete;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.CacheObject.Views
|
namespace UnityExplorer.CacheObject.Views
|
||||||
{
|
{
|
||||||
public class EvaluateWidget : IPooledObject
|
public class EvaluateWidget : IPooledObject
|
||||||
{
|
{
|
||||||
@ -68,7 +68,7 @@ namespace UnityExplorer.UI.CacheObject.Views
|
|||||||
|
|
||||||
for (int i = 0; i < genericArguments.Length; i++)
|
for (int i = 0; i < genericArguments.Length; i++)
|
||||||
{
|
{
|
||||||
outArgs[i] = ReflectionUtility.GetTypeByName(genericInput[i])
|
outArgs[i] = ReflectionUtility.GetTypeByName(genericInput[i])
|
||||||
?? throw new Exception($"Could not find any type by name '{genericInput[i]}'!");
|
?? throw new Exception($"Could not find any type by name '{genericInput[i]}'!");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,7 +207,7 @@ namespace UnityExplorer.UI.CacheObject.Views
|
|||||||
var elemType = arg.ParameterType;
|
var elemType = arg.ParameterType;
|
||||||
if (elemType.IsByRef)
|
if (elemType.IsByRef)
|
||||||
elemType = elemType.GetElementType();
|
elemType = elemType.GetElementType();
|
||||||
argInputFields[i].PlaceholderText.text = $"eg. {ParseUtility.GetExampleInput(elemType)}";
|
argInputFields[i].PlaceholderText.text = $"eg. {ParseUtility.GetExampleInput(elemType)}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -250,7 +250,7 @@ namespace UnityExplorer.UI.CacheObject.Views
|
|||||||
|
|
||||||
public GameObject CreateContent(GameObject parent)
|
public GameObject CreateContent(GameObject parent)
|
||||||
{
|
{
|
||||||
UIRoot = UIFactory.CreateVerticalGroup(parent, "EvaluateWidget", false, false, true, true, 3, new Vector4(2, 2, 2, 2),
|
UIRoot = UIFactory.CreateVerticalGroup(parent, "EvaluateWidget", false, false, true, true, 3, new Vector4(2, 2, 2, 2),
|
||||||
new Color(0.15f, 0.15f, 0.15f));
|
new Color(0.15f, 0.15f, 0.15f));
|
||||||
UIFactory.SetLayoutElement(UIRoot, minWidth: 50, flexibleWidth: 9999, minHeight: 50, flexibleHeight: 800);
|
UIFactory.SetLayoutElement(UIRoot, minWidth: 50, flexibleWidth: 9999, minHeight: 50, flexibleHeight: 800);
|
||||||
//UIRoot.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
//UIRoot.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||||||
@ -276,7 +276,7 @@ namespace UnityExplorer.UI.CacheObject.Views
|
|||||||
// evaluate button
|
// evaluate button
|
||||||
var evalButton = UIFactory.CreateButton(UIRoot, "EvaluateButton", "Evaluate", new Color(0.2f, 0.2f, 0.2f));
|
var evalButton = UIFactory.CreateButton(UIRoot, "EvaluateButton", "Evaluate", new Color(0.2f, 0.2f, 0.2f));
|
||||||
UIFactory.SetLayoutElement(evalButton.Component.gameObject, minHeight: 25, minWidth: 150, flexibleWidth: 0);
|
UIFactory.SetLayoutElement(evalButton.Component.gameObject, minHeight: 25, minWidth: 150, flexibleWidth: 0);
|
||||||
evalButton.OnClick += () =>
|
evalButton.OnClick += () =>
|
||||||
{
|
{
|
||||||
Owner.EvaluateAndSetCell();
|
Owner.EvaluateAndSetCell();
|
||||||
};
|
};
|
@ -16,17 +16,18 @@ namespace UnityExplorer.Core.Config
|
|||||||
// See the UnityExplorer.Loader namespace for the implementations.
|
// See the UnityExplorer.Loader namespace for the implementations.
|
||||||
public static ConfigHandler Handler { get; private set; }
|
public static ConfigHandler Handler { get; private set; }
|
||||||
|
|
||||||
public static ConfigElement<KeyCode> Master_Toggle;
|
public static ConfigElement<KeyCode> Master_Toggle;
|
||||||
public static ConfigElement<UIManager.VerticalAnchor> Main_Navbar_Anchor;
|
public static ConfigElement<UIManager.VerticalAnchor> Main_Navbar_Anchor;
|
||||||
public static ConfigElement<bool> Force_Unlock_Mouse;
|
public static ConfigElement<bool> Force_Unlock_Mouse;
|
||||||
public static ConfigElement<KeyCode> Force_Unlock_Toggle;
|
public static ConfigElement<KeyCode> Force_Unlock_Toggle;
|
||||||
public static ConfigElement<bool> Aggressive_Mouse_Unlock;
|
public static ConfigElement<bool> Aggressive_Mouse_Unlock;
|
||||||
public static ConfigElement<string> Default_Output_Path;
|
public static ConfigElement<bool> Disable_EventSystem_Override;
|
||||||
public static ConfigElement<bool> Log_Unity_Debug;
|
public static ConfigElement<string> Default_Output_Path;
|
||||||
public static ConfigElement<bool> Hide_On_Startup;
|
public static ConfigElement<bool> Log_Unity_Debug;
|
||||||
public static ConfigElement<float> Startup_Delay_Time;
|
public static ConfigElement<bool> Hide_On_Startup;
|
||||||
|
public static ConfigElement<float> Startup_Delay_Time;
|
||||||
|
|
||||||
public static ConfigElement<string> Reflection_Signature_Blacklist;
|
public static ConfigElement<string> Reflection_Signature_Blacklist;
|
||||||
|
|
||||||
// internal configs
|
// internal configs
|
||||||
internal static InternalConfigHandler InternalHandler { get; private set; }
|
internal static InternalConfigHandler InternalHandler { get; private set; }
|
||||||
@ -93,7 +94,11 @@ namespace UnityExplorer.Core.Config
|
|||||||
KeyCode.None);
|
KeyCode.None);
|
||||||
|
|
||||||
Aggressive_Mouse_Unlock = new ConfigElement<bool>("Aggressive Mouse Unlock",
|
Aggressive_Mouse_Unlock = new ConfigElement<bool>("Aggressive Mouse Unlock",
|
||||||
"Use WaitForEndOfFrame to aggressively force the Mouse to be unlocked (requires game restart).",
|
"Use WaitForEndOfFrame to aggressively force the Mouse to be unlocked.\n<b>Requires restart to take effect.</b>",
|
||||||
|
false);
|
||||||
|
|
||||||
|
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);
|
false);
|
||||||
|
|
||||||
Log_Unity_Debug = new ConfigElement<bool>("Log Unity Debug",
|
Log_Unity_Debug = new ConfigElement<bool>("Log Unity Debug",
|
||||||
@ -108,10 +113,11 @@ namespace UnityExplorer.Core.Config
|
|||||||
"The delay on startup before the UI is created.",
|
"The delay on startup before the UI is created.",
|
||||||
1f);
|
1f);
|
||||||
|
|
||||||
Reflection_Signature_Blacklist = new ConfigElement<string>("Reflection Signature Blacklist",
|
Reflection_Signature_Blacklist = new ConfigElement<string>("Member Signature Blacklist",
|
||||||
"Use this to blacklist certain member signatures if they are known to cause a crash or other issues." +
|
"Use this to blacklist certain member signatures if they are known to cause a crash or other issues.\r\n" +
|
||||||
"\r\nSeperate signatures with a semicolon ';'.",
|
"Seperate signatures with a semicolon ';'.\r\n" +
|
||||||
"DEFAULT");
|
"For example, to blacklist Camera.main, you would add 'Camera.main;'",
|
||||||
|
"");
|
||||||
|
|
||||||
// Internal configs (panel save data)
|
// Internal configs (panel save data)
|
||||||
|
|
||||||
|
@ -87,9 +87,6 @@ namespace UnityExplorer.Core.Config
|
|||||||
foreach (var entry in ConfigManager.InternalConfigs)
|
foreach (var entry in ConfigManager.InternalConfigs)
|
||||||
sec.AddKey(entry.Key, entry.Value.BoxedValue.ToString());
|
sec.AddKey(entry.Key, entry.Value.BoxedValue.ToString());
|
||||||
|
|
||||||
if (!Directory.Exists(ExplorerCore.Loader.ConfigFolder))
|
|
||||||
Directory.CreateDirectory(ExplorerCore.Loader.ConfigFolder);
|
|
||||||
|
|
||||||
File.WriteAllText(INI_PATH, data.ToString());
|
File.WriteAllText(INI_PATH, data.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,16 +32,32 @@ namespace UnityExplorer
|
|||||||
public ExplorerBehaviour(IntPtr ptr) : base(ptr) { }
|
public ExplorerBehaviour(IntPtr ptr) : base(ptr) { }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
private static bool onPostRenderFailed;
|
||||||
|
|
||||||
internal void Awake()
|
internal void Awake()
|
||||||
{
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
#if CPP
|
#if CPP
|
||||||
Camera.onPostRender = Camera.onPostRender == null
|
Camera.onPostRender = Camera.onPostRender == null
|
||||||
? new Action<Camera>(OnPostRender)
|
? new Action<Camera>(OnPostRender)
|
||||||
: Il2CppSystem.Delegate.Combine(Camera.onPostRender, (Camera.CameraCallback)new Action<Camera>(OnPostRender)).Cast<Camera.CameraCallback>();
|
: Il2CppSystem.Delegate.Combine(Camera.onPostRender,
|
||||||
|
(Camera.CameraCallback)new Action<Camera>(OnPostRender)).Cast<Camera.CameraCallback>();
|
||||||
|
|
||||||
|
if (Camera.onPostRender == null || Camera.onPostRender.delegates == null)
|
||||||
|
{
|
||||||
|
ExplorerCore.LogWarning("Failed to add Camera.onPostRender listener, falling back to LateUpdate instead!");
|
||||||
|
onPostRenderFailed = true;
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
Camera.onPostRender += OnPostRender;
|
Camera.onPostRender += OnPostRender;
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
ExplorerCore.LogWarning($"Exception adding onPostRender listener: {ex.ReflectionExToString()}\r\nFalling back to LateUpdate!");
|
||||||
|
onPostRenderFailed = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void Update()
|
internal void Update()
|
||||||
@ -54,7 +70,13 @@ namespace UnityExplorer
|
|||||||
ExplorerCore.FixedUpdate();
|
ExplorerCore.FixedUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void OnPostRender(Camera camera)
|
internal void LateUpdate()
|
||||||
|
{
|
||||||
|
if (onPostRenderFailed)
|
||||||
|
OnPostRender(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void OnPostRender(Camera _)
|
||||||
{
|
{
|
||||||
ExplorerCore.OnPostRender();
|
ExplorerCore.OnPostRender();
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.EventSystems;
|
using UnityEngine.EventSystems;
|
||||||
using UnityExplorer.Core.Input;
|
|
||||||
using BF = System.Reflection.BindingFlags;
|
|
||||||
using UnityExplorer.Core.Config;
|
|
||||||
using UnityExplorer.Core;
|
using UnityExplorer.Core;
|
||||||
|
using UnityExplorer.Core.Config;
|
||||||
|
using UnityExplorer.Core.Input;
|
||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
using System.Collections;
|
using BF = System.Reflection.BindingFlags;
|
||||||
using HarmonyLib;
|
|
||||||
|
|
||||||
namespace UnityExplorer.Core.Input
|
namespace UnityExplorer.Core.Input
|
||||||
{
|
{
|
||||||
@ -37,12 +37,15 @@ namespace UnityExplorer.Core.Input
|
|||||||
lastVisibleState = Cursor.visible;
|
lastVisibleState = Cursor.visible;
|
||||||
|
|
||||||
SetupPatches();
|
SetupPatches();
|
||||||
|
|
||||||
UpdateCursorControl();
|
UpdateCursorControl();
|
||||||
|
|
||||||
|
// Hook up config values
|
||||||
|
|
||||||
|
// Force Unlock Mouse
|
||||||
Unlock = ConfigManager.Force_Unlock_Mouse.Value;
|
Unlock = ConfigManager.Force_Unlock_Mouse.Value;
|
||||||
ConfigManager.Force_Unlock_Mouse.OnValueChanged += (bool val) => { Unlock = val; };
|
ConfigManager.Force_Unlock_Mouse.OnValueChanged += (bool val) => { Unlock = val; };
|
||||||
|
|
||||||
|
// Aggressive Mouse Unlock
|
||||||
if (ConfigManager.Aggressive_Mouse_Unlock.Value)
|
if (ConfigManager.Aggressive_Mouse_Unlock.Value)
|
||||||
SetupAggressiveUnlock();
|
SetupAggressiveUnlock();
|
||||||
}
|
}
|
||||||
@ -59,13 +62,13 @@ namespace UnityExplorer.Core.Input
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly WaitForEndOfFrame _waitForEndOfFrame = new WaitForEndOfFrame();
|
private static WaitForEndOfFrame _waitForEndOfFrame = new WaitForEndOfFrame();
|
||||||
|
|
||||||
private static IEnumerator AggressiveUnlockCoroutine()
|
private static IEnumerator AggressiveUnlockCoroutine()
|
||||||
{
|
{
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
yield return _waitForEndOfFrame;
|
yield return _waitForEndOfFrame ?? (_waitForEndOfFrame = new WaitForEndOfFrame());
|
||||||
|
|
||||||
if (UIManager.ShowMenu)
|
if (UIManager.ShowMenu)
|
||||||
UpdateCursorControl();
|
UpdateCursorControl();
|
||||||
@ -83,7 +86,7 @@ namespace UnityExplorer.Core.Input
|
|||||||
Cursor.lockState = CursorLockMode.None;
|
Cursor.lockState = CursorLockMode.None;
|
||||||
Cursor.visible = true;
|
Cursor.visible = true;
|
||||||
|
|
||||||
if (UIManager.EventSys)
|
if (!ConfigManager.Disable_EventSystem_Override.Value && UIManager.EventSys)
|
||||||
SetEventSystem();
|
SetEventSystem();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -91,7 +94,7 @@ namespace UnityExplorer.Core.Input
|
|||||||
Cursor.lockState = lastLockMode;
|
Cursor.lockState = lastLockMode;
|
||||||
Cursor.visible = lastVisibleState;
|
Cursor.visible = lastVisibleState;
|
||||||
|
|
||||||
if (UIManager.EventSys)
|
if (!ConfigManager.Disable_EventSystem_Override.Value && UIManager.EventSys)
|
||||||
ReleaseEventSystem();
|
ReleaseEventSystem();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,26 +163,19 @@ namespace UnityExplorer.Core.Input
|
|||||||
|
|
||||||
public static void Prefix_EventSystem_set_current(ref EventSystem value)
|
public static void Prefix_EventSystem_set_current(ref EventSystem value)
|
||||||
{
|
{
|
||||||
if (!UIManager.EventSys)
|
if (!settingEventSystem && value)
|
||||||
{
|
|
||||||
if (value)
|
|
||||||
{
|
|
||||||
lastEventSystem = value;
|
|
||||||
lastInputModule = value.currentInputModule;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!settingEventSystem && value != UIManager.EventSys)
|
|
||||||
{
|
{
|
||||||
lastEventSystem = value;
|
lastEventSystem = value;
|
||||||
lastInputModule = value?.currentInputModule;
|
lastInputModule = value.currentInputModule;
|
||||||
|
}
|
||||||
|
|
||||||
if (ShouldActuallyUnlock)
|
if (!UIManager.EventSys)
|
||||||
{
|
return;
|
||||||
value = UIManager.EventSys;
|
|
||||||
value.enabled = true;
|
if (!settingEventSystem && ShouldActuallyUnlock && !ConfigManager.Disable_EventSystem_Override.Value)
|
||||||
}
|
{
|
||||||
|
value = UIManager.EventSys;
|
||||||
|
value.enabled = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using UnityEngine;
|
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using UnityEngine;
|
||||||
using UnityEngine.EventSystems;
|
using UnityEngine.EventSystems;
|
||||||
|
|
||||||
namespace UnityExplorer.Core.Input
|
namespace UnityExplorer.Core.Input
|
||||||
@ -74,7 +74,7 @@ namespace UnityExplorer.Core.Input
|
|||||||
ExplorerCore.Log("Initialized Legacy Input support");
|
ExplorerCore.Log("Initialized Legacy Input support");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
// It's not working, we'll fall back to InputSystem.
|
// It's not working, we'll fall back to InputSystem.
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.EventSystems;
|
using UnityEngine.EventSystems;
|
||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace UnityExplorer.Core.Input
|
namespace UnityExplorer.Core.Input
|
||||||
{
|
{
|
||||||
|
@ -99,8 +99,10 @@ namespace UnityExplorer
|
|||||||
|
|
||||||
public static Exception GetInnerMostException(this Exception e)
|
public static Exception GetInnerMostException(this Exception e)
|
||||||
{
|
{
|
||||||
while (e.InnerException != null)
|
while (e != null)
|
||||||
{
|
{
|
||||||
|
if (e.InnerException == null)
|
||||||
|
break;
|
||||||
#if CPP
|
#if CPP
|
||||||
if (e.InnerException is System.Runtime.CompilerServices.RuntimeWrappedException)
|
if (e.InnerException is System.Runtime.CompilerServices.RuntimeWrappedException)
|
||||||
break;
|
break;
|
||||||
|
@ -16,6 +16,7 @@ using CppType = Il2CppSystem.Type;
|
|||||||
using BF = System.Reflection.BindingFlags;
|
using BF = System.Reflection.BindingFlags;
|
||||||
using UnityExplorer.Core.Config;
|
using UnityExplorer.Core.Config;
|
||||||
using UnhollowerBaseLib.Attributes;
|
using UnhollowerBaseLib.Attributes;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
namespace UnityExplorer
|
namespace UnityExplorer
|
||||||
{
|
{
|
||||||
@ -25,13 +26,18 @@ namespace UnityExplorer
|
|||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
|
|
||||||
|
float start = Time.realtimeSinceStartup;
|
||||||
TryLoadGameModules();
|
TryLoadGameModules();
|
||||||
|
ExplorerCore.Log($"Loaded Unhollowed modules in {Time.realtimeSinceStartup - start} seconds");
|
||||||
|
|
||||||
|
start = Time.realtimeSinceStartup;
|
||||||
BuildDeobfuscationCache();
|
BuildDeobfuscationCache();
|
||||||
OnTypeLoaded += TryCacheDeobfuscatedType;
|
OnTypeLoaded += TryCacheDeobfuscatedType;
|
||||||
|
ExplorerCore.Log($"Setup IL2CPP reflection in {Time.realtimeSinceStartup - start} seconds, " +
|
||||||
|
$"deobfuscated types count: {DeobfuscatedTypes.Count}");
|
||||||
}
|
}
|
||||||
|
|
||||||
#region IL2CPP Extern and pointers
|
#region IL2CPP Extern and pointers
|
||||||
|
|
||||||
// Extern C++ methods
|
// Extern C++ methods
|
||||||
[DllImport("GameAssembly", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
|
[DllImport("GameAssembly", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
|
||||||
@ -44,23 +50,23 @@ namespace UnityExplorer
|
|||||||
|
|
||||||
public static bool Il2CppTypeNotNull(Type type, out IntPtr il2cppPtr)
|
public static bool Il2CppTypeNotNull(Type type, out IntPtr il2cppPtr)
|
||||||
{
|
{
|
||||||
if (cppClassPointers.TryGetValue(type.AssemblyQualifiedName, out il2cppPtr))
|
if (!cppClassPointers.TryGetValue(type.AssemblyQualifiedName, out il2cppPtr))
|
||||||
return il2cppPtr != IntPtr.Zero;
|
{
|
||||||
|
il2cppPtr = (IntPtr)typeof(Il2CppClassPointerStore<>)
|
||||||
il2cppPtr = (IntPtr)typeof(Il2CppClassPointerStore<>)
|
|
||||||
.MakeGenericType(new Type[] { type })
|
.MakeGenericType(new Type[] { type })
|
||||||
.GetField("NativeClassPtr", BF.Public | BF.Static)
|
.GetField("NativeClassPtr", BF.Public | BF.Static)
|
||||||
.GetValue(null);
|
.GetValue(null);
|
||||||
|
|
||||||
cppClassPointers.Add(type.AssemblyQualifiedName, il2cppPtr);
|
cppClassPointers.Add(type.AssemblyQualifiedName, il2cppPtr);
|
||||||
|
}
|
||||||
|
|
||||||
return il2cppPtr != IntPtr.Zero;
|
return il2cppPtr != IntPtr.Zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
#region Deobfuscation cache
|
#region Deobfuscation cache
|
||||||
|
|
||||||
private static readonly Dictionary<string, Type> DeobfuscatedTypes = new Dictionary<string, Type>();
|
private static readonly Dictionary<string, Type> DeobfuscatedTypes = new Dictionary<string, Type>();
|
||||||
private static readonly Dictionary<string, string> reverseDeobCache = new Dictionary<string, string>();
|
private static readonly Dictionary<string, string> reverseDeobCache = new Dictionary<string, string>();
|
||||||
@ -72,9 +78,6 @@ namespace UnityExplorer
|
|||||||
foreach (var type in asm.TryGetTypes())
|
foreach (var type in asm.TryGetTypes())
|
||||||
TryCacheDeobfuscatedType(type);
|
TryCacheDeobfuscatedType(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DeobfuscatedTypes.Count > 0)
|
|
||||||
ExplorerCore.Log($"Built IL2CPP deobfuscation cache, initial count: {DeobfuscatedTypes.Count}");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void TryCacheDeobfuscatedType(Type type)
|
private static void TryCacheDeobfuscatedType(Type type)
|
||||||
@ -108,7 +111,7 @@ namespace UnityExplorer
|
|||||||
return theString;
|
return theString;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
// Get type by name
|
// Get type by name
|
||||||
@ -121,7 +124,7 @@ namespace UnityExplorer
|
|||||||
return base.Internal_GetTypeByName(fullName);
|
return base.Internal_GetTypeByName(fullName);
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Get actual type
|
#region Get actual type
|
||||||
|
|
||||||
internal override Type Internal_GetActualType(object obj)
|
internal override Type Internal_GetActualType(object obj)
|
||||||
{
|
{
|
||||||
@ -129,7 +132,6 @@ namespace UnityExplorer
|
|||||||
return null;
|
return null;
|
||||||
|
|
||||||
var type = obj.GetType();
|
var type = obj.GetType();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (IsString(obj))
|
if (IsString(obj))
|
||||||
@ -180,10 +182,10 @@ namespace UnityExplorer
|
|||||||
return monoType;
|
return monoType;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
#region Casting
|
#region Casting
|
||||||
|
|
||||||
private static readonly Dictionary<string, IntPtr> cppClassPointers = new Dictionary<string, IntPtr>();
|
private static readonly Dictionary<string, IntPtr> cppClassPointers = new Dictionary<string, IntPtr>();
|
||||||
|
|
||||||
@ -213,7 +215,7 @@ namespace UnityExplorer
|
|||||||
// from other structs to il2cpp object
|
// from other structs to il2cpp object
|
||||||
else if (typeof(Il2CppSystem.Object).IsAssignableFrom(castTo))
|
else if (typeof(Il2CppSystem.Object).IsAssignableFrom(castTo))
|
||||||
{
|
{
|
||||||
return BoxIl2CppObject(obj);
|
return BoxIl2CppObject(obj).TryCast(castTo);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return obj;
|
return obj;
|
||||||
@ -237,11 +239,11 @@ namespace UnityExplorer
|
|||||||
else if (castTo == typeof(string))
|
else if (castTo == typeof(string))
|
||||||
return UnboxString(obj);
|
return UnboxString(obj);
|
||||||
|
|
||||||
// Casting from il2cpp object to il2cpp object...
|
|
||||||
|
|
||||||
if (!Il2CppTypeNotNull(castTo, out IntPtr castToPtr))
|
if (!Il2CppTypeNotNull(castTo, out IntPtr castToPtr))
|
||||||
return obj;
|
return obj;
|
||||||
|
|
||||||
|
// Casting from il2cpp object to il2cpp object...
|
||||||
|
|
||||||
IntPtr castFromPtr = il2cpp_object_get_class(cppObj.Pointer);
|
IntPtr castFromPtr = il2cpp_object_get_class(cppObj.Pointer);
|
||||||
|
|
||||||
if (!il2cpp_class_is_assignable_from(castToPtr, castFromPtr))
|
if (!il2cpp_class_is_assignable_from(castToPtr, castFromPtr))
|
||||||
@ -275,10 +277,10 @@ namespace UnityExplorer
|
|||||||
// return il2cpp_class_is_assignable_from(thisTypePtr, fromTypePtr);
|
// return il2cpp_class_is_assignable_from(thisTypePtr, fromTypePtr);
|
||||||
//}
|
//}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
#region Boxing and unboxing ValueTypes
|
#region Boxing and unboxing ValueTypes
|
||||||
|
|
||||||
// cached il2cpp unbox methods
|
// cached il2cpp unbox methods
|
||||||
internal static readonly Dictionary<string, MethodInfo> unboxMethods = new Dictionary<string, MethodInfo>();
|
internal static readonly Dictionary<string, MethodInfo> unboxMethods = new Dictionary<string, MethodInfo>();
|
||||||
@ -292,7 +294,27 @@ namespace UnityExplorer
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (toType.IsEnum)
|
if (toType.IsEnum)
|
||||||
|
{
|
||||||
|
// Check for nullable enums
|
||||||
|
var type = cppObj.GetType();
|
||||||
|
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Il2CppSystem.Nullable<>))
|
||||||
|
{
|
||||||
|
var nullable = cppObj.TryCast(type);
|
||||||
|
var nullableHasValueProperty = type.GetProperty("HasValue");
|
||||||
|
if ((bool)nullableHasValueProperty.GetValue(nullable, null))
|
||||||
|
{
|
||||||
|
// nullable has a value.
|
||||||
|
var nullableValueProperty = type.GetProperty("Value");
|
||||||
|
return Enum.Parse(toType, nullableValueProperty.GetValue(nullable, null).ToString());
|
||||||
|
}
|
||||||
|
// nullable and no current value.
|
||||||
|
return cppObj;
|
||||||
|
}
|
||||||
|
|
||||||
return Enum.Parse(toType, cppObj.ToString());
|
return Enum.Parse(toType, cppObj.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not enum, unbox with Il2CppObjectBase.Unbox
|
||||||
|
|
||||||
var name = toType.AssemblyQualifiedName;
|
var name = toType.AssemblyQualifiedName;
|
||||||
|
|
||||||
@ -381,10 +403,10 @@ namespace UnityExplorer
|
|||||||
return cppStruct;
|
return cppStruct;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
#region String boxing/unboxing
|
#region String boxing/unboxing
|
||||||
|
|
||||||
private const string IL2CPP_STRING_FULLNAME = "Il2CppSystem.String";
|
private const string IL2CPP_STRING_FULLNAME = "Il2CppSystem.String";
|
||||||
private const string STRING_FULLNAME = "System.String";
|
private const string STRING_FULLNAME = "System.String";
|
||||||
@ -425,10 +447,10 @@ namespace UnityExplorer
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
#region Singleton finder
|
#region Singleton finder
|
||||||
|
|
||||||
internal override void Internal_FindSingleton(string[] possibleNames, Type type, BF flags, List<object> instances)
|
internal override void Internal_FindSingleton(string[] possibleNames, Type type, BF flags, List<object> instances)
|
||||||
{
|
{
|
||||||
@ -450,16 +472,16 @@ namespace UnityExplorer
|
|||||||
base.Internal_FindSingleton(possibleNames, type, flags, instances);
|
base.Internal_FindSingleton(possibleNames, type, flags, instances);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
#region Force-loading game modules
|
#region Force-loading game modules
|
||||||
|
|
||||||
internal static string UnhollowedFolderPath => Path.GetFullPath(
|
internal static string UnhollowedFolderPath => Path.GetFullPath(
|
||||||
#if ML
|
#if ML
|
||||||
Path.Combine("MelonLoader", "Managed")
|
Path.Combine("MelonLoader", "Managed")
|
||||||
#elif BIE
|
#elif BIE
|
||||||
Path.Combine("BepInEx", "unhollowed")
|
Path.Combine(BepInEx.Paths.BepInExRootPath, "unhollowed")
|
||||||
#else
|
#else
|
||||||
Path.Combine(ExplorerCore.Loader.ExplorerFolder, "Modules")
|
Path.Combine(ExplorerCore.Loader.ExplorerFolder, "Modules")
|
||||||
#endif
|
#endif
|
||||||
@ -513,9 +535,9 @@ namespace UnityExplorer
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
#region Il2cpp reflection blacklist
|
#region Il2cpp reflection blacklist
|
||||||
|
|
||||||
public override string DefaultReflectionBlacklist => string.Join(";", defaultIl2CppBlacklist);
|
public override string[] DefaultReflectionBlacklist => defaultIl2CppBlacklist.ToArray();
|
||||||
|
|
||||||
// These methods currently cause a crash in most il2cpp games,
|
// These methods currently cause a crash in most il2cpp games,
|
||||||
// even from doing "GetParameters()" on the MemberInfo.
|
// even from doing "GetParameters()" on the MemberInfo.
|
||||||
@ -662,10 +684,10 @@ namespace UnityExplorer
|
|||||||
"UnityEngine.XR.InputDevice.SendHapticImpulse",
|
"UnityEngine.XR.InputDevice.SendHapticImpulse",
|
||||||
};
|
};
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
#region IL2CPP IEnumerable and IDictionary
|
#region IL2CPP IEnumerable and IDictionary
|
||||||
|
|
||||||
protected override bool Internal_TryGetEntryType(Type enumerableType, out Type type)
|
protected override bool Internal_TryGetEntryType(Type enumerableType, out Type type)
|
||||||
{
|
{
|
||||||
@ -782,7 +804,9 @@ namespace UnityExplorer
|
|||||||
|
|
||||||
if (!getEnumeratorMethods.ContainsKey(key))
|
if (!getEnumeratorMethods.ContainsKey(key))
|
||||||
{
|
{
|
||||||
getEnumeratorMethods.Add(key, type.GetMethod("GetEnumerator"));
|
var method = type.GetMethod("System_Collections_IEnumerable_GetEnumerator", FLAGS)
|
||||||
|
?? type.GetMethod("GetEnumerator");
|
||||||
|
getEnumeratorMethods.Add(key, method);
|
||||||
|
|
||||||
// ensure the enumerator type is supported
|
// ensure the enumerator type is supported
|
||||||
try
|
try
|
||||||
@ -868,7 +892,9 @@ namespace UnityExplorer
|
|||||||
var cacheKey = keys.GetType().AssemblyQualifiedName;
|
var cacheKey = keys.GetType().AssemblyQualifiedName;
|
||||||
if (!getEnumeratorMethods.ContainsKey(cacheKey))
|
if (!getEnumeratorMethods.ContainsKey(cacheKey))
|
||||||
{
|
{
|
||||||
getEnumeratorMethods.Add(cacheKey, keyCollType.GetMethod("GetEnumerator"));
|
var method = keyCollType.GetMethod("System_Collections_IDictionary_GetEnumerator", FLAGS)
|
||||||
|
?? keyCollType.GetMethod("GetEnumerator");
|
||||||
|
getEnumeratorMethods.Add(cacheKey, method);
|
||||||
|
|
||||||
// test support
|
// test support
|
||||||
try
|
try
|
||||||
|
@ -4,15 +4,14 @@ using System.Collections.Generic;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using BF = System.Reflection.BindingFlags;
|
|
||||||
using UnityExplorer.Core.Runtime;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityExplorer.Core.Config;
|
using UnityExplorer.Core.Config;
|
||||||
|
using UnityExplorer.Core.Runtime;
|
||||||
|
using BF = System.Reflection.BindingFlags;
|
||||||
|
|
||||||
namespace UnityExplorer
|
namespace UnityExplorer
|
||||||
{
|
{
|
||||||
|
|
||||||
public class ReflectionUtility
|
public class ReflectionUtility
|
||||||
{
|
{
|
||||||
public const BF FLAGS = BF.Public | BF.Instance | BF.NonPublic | BF.Static;
|
public const BF FLAGS = BF.Public | BF.Instance | BF.NonPublic | BF.Static;
|
||||||
@ -43,7 +42,7 @@ namespace UnityExplorer
|
|||||||
public static Action<Type> OnTypeLoaded;
|
public static Action<Type> OnTypeLoaded;
|
||||||
|
|
||||||
/// <summary>Key: Type.FullName</summary>
|
/// <summary>Key: Type.FullName</summary>
|
||||||
public static readonly SortedDictionary<string, Type> AllTypes = new SortedDictionary<string, Type>(StringComparer.OrdinalIgnoreCase);
|
protected static readonly SortedDictionary<string, Type> AllTypes = new SortedDictionary<string, Type>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
public static readonly List<string> AllNamespaces = new List<string>();
|
public static readonly List<string> AllNamespaces = new List<string>();
|
||||||
private static readonly HashSet<string> uniqueNamespaces = new HashSet<string>();
|
private static readonly HashSet<string> uniqueNamespaces = new HashSet<string>();
|
||||||
@ -66,10 +65,14 @@ namespace UnityExplorer
|
|||||||
|
|
||||||
private static void SetupTypeCache()
|
private static void SetupTypeCache()
|
||||||
{
|
{
|
||||||
|
float start = Time.realtimeSinceStartup;
|
||||||
|
|
||||||
foreach (var asm in AppDomain.CurrentDomain.GetAssemblies())
|
foreach (var asm in AppDomain.CurrentDomain.GetAssemblies())
|
||||||
CacheTypes(asm);
|
CacheTypes(asm);
|
||||||
|
|
||||||
AppDomain.CurrentDomain.AssemblyLoad += AssemblyLoaded;
|
AppDomain.CurrentDomain.AssemblyLoad += AssemblyLoaded;
|
||||||
|
|
||||||
|
ExplorerCore.Log($"Cached AppDomain assemblies in {Time.realtimeSinceStartup - start} seconds");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void AssemblyLoaded(object sender, AssemblyLoadEventArgs args)
|
private static void AssemblyLoaded(object sender, AssemblyLoadEventArgs args)
|
||||||
@ -84,6 +87,7 @@ namespace UnityExplorer
|
|||||||
{
|
{
|
||||||
foreach (var type in asm.TryGetTypes())
|
foreach (var type in asm.TryGetTypes())
|
||||||
{
|
{
|
||||||
|
// Cache namespace if there is one
|
||||||
if (!string.IsNullOrEmpty(type.Namespace) && !uniqueNamespaces.Contains(type.Namespace))
|
if (!string.IsNullOrEmpty(type.Namespace) && !uniqueNamespaces.Contains(type.Namespace))
|
||||||
{
|
{
|
||||||
uniqueNamespaces.Add(type.Namespace);
|
uniqueNamespaces.Add(type.Namespace);
|
||||||
@ -97,16 +101,16 @@ namespace UnityExplorer
|
|||||||
AllNamespaces.Insert(i, type.Namespace);
|
AllNamespaces.Insert(i, type.Namespace);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Cache the type. Overwrite type if one exists with the full name
|
||||||
if (AllTypes.ContainsKey(type.FullName))
|
if (AllTypes.ContainsKey(type.FullName))
|
||||||
AllTypes[type.FullName] = type;
|
AllTypes[type.FullName] = type;
|
||||||
else
|
else
|
||||||
{
|
|
||||||
AllTypes.Add(type.FullName, type);
|
AllTypes.Add(type.FullName, type);
|
||||||
//allTypeNames.Add(type.FullName);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Invoke listener
|
||||||
OnTypeLoaded?.Invoke(type);
|
OnTypeLoaded?.Invoke(type);
|
||||||
|
|
||||||
|
// Check type inheritance cache, add this to any lists it should be in
|
||||||
foreach (var key in typeInheritance.Keys)
|
foreach (var key in typeInheritance.Keys)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@ -151,13 +155,6 @@ namespace UnityExplorer
|
|||||||
internal virtual string Internal_ProcessTypeInString(string theString, Type type)
|
internal virtual string Internal_ProcessTypeInString(string theString, Type type)
|
||||||
=> theString;
|
=> theString;
|
||||||
|
|
||||||
//// Force loading modules
|
|
||||||
//public static bool LoadModule(string moduleName)
|
|
||||||
// => Instance.Internal_LoadModule(moduleName);
|
|
||||||
//
|
|
||||||
//internal virtual bool Internal_LoadModule(string moduleName)
|
|
||||||
// => false;
|
|
||||||
|
|
||||||
// Singleton finder
|
// Singleton finder
|
||||||
|
|
||||||
public static void FindSingleton(string[] possibleNames, Type type, BindingFlags flags, List<object> instances)
|
public static void FindSingleton(string[] possibleNames, Type type, BindingFlags flags, List<object> instances)
|
||||||
@ -222,7 +219,7 @@ namespace UnityExplorer
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
#region Type and Generic Parameter implementation cache
|
#region Type and Generic Parameter implementation cache
|
||||||
@ -357,7 +354,7 @@ namespace UnityExplorer
|
|||||||
return genericParameterInheritance[key];
|
return genericParameterInheritance[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
#region Internal MemberInfo Cache
|
#region Internal MemberInfo Cache
|
||||||
@ -434,31 +431,44 @@ namespace UnityExplorer
|
|||||||
|
|
||||||
#region Reflection Blacklist
|
#region Reflection Blacklist
|
||||||
|
|
||||||
public virtual string DefaultReflectionBlacklist => string.Empty;
|
public virtual string[] DefaultReflectionBlacklist => new string[0];
|
||||||
|
|
||||||
public static void LoadBlacklistString(string blacklist)
|
public static void LoadBlacklistString(string blacklist)
|
||||||
{
|
{
|
||||||
if (string.Equals(blacklist, "DEFAULT", StringComparison.InvariantCultureIgnoreCase))
|
try
|
||||||
{
|
{
|
||||||
blacklist = Instance.DefaultReflectionBlacklist;
|
if (string.IsNullOrEmpty(blacklist) && !Instance.DefaultReflectionBlacklist.Any())
|
||||||
ConfigManager.Reflection_Signature_Blacklist.Value = blacklist;
|
return;
|
||||||
ConfigManager.Handler.SaveConfig();
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var sigs = blacklist.Split(';');
|
||||||
|
foreach (var sig in sigs)
|
||||||
|
{
|
||||||
|
var s = sig.Trim();
|
||||||
|
if (string.IsNullOrEmpty(s))
|
||||||
|
continue;
|
||||||
|
if (!currentBlacklist.Contains(s))
|
||||||
|
currentBlacklist.Add(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
ExplorerCore.LogWarning($"Exception parsing blacklist string: {ex.ReflectionExToString()}");
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var sig in Instance.DefaultReflectionBlacklist)
|
||||||
|
{
|
||||||
|
if (!currentBlacklist.Contains(sig))
|
||||||
|
currentBlacklist.Add(sig);
|
||||||
|
}
|
||||||
|
|
||||||
|
Mono.CSharp.IL2CPP.Blacklist.SignatureBlacklist = currentBlacklist;
|
||||||
}
|
}
|
||||||
|
catch (Exception ex)
|
||||||
if (string.IsNullOrEmpty(blacklist))
|
|
||||||
return;
|
|
||||||
|
|
||||||
var sigs = blacklist.Split(';');
|
|
||||||
foreach (var sig in sigs)
|
|
||||||
{
|
{
|
||||||
var s = sig.Trim();
|
ExplorerCore.LogWarning($"Exception setting up reflection blacklist: {ex.ReflectionExToString()}");
|
||||||
if (string.IsNullOrEmpty(s))
|
|
||||||
continue;
|
|
||||||
if (!currentBlacklist.Contains(s))
|
|
||||||
currentBlacklist.Add(s);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Mono.CSharp.IL2CPP.Blacklist.SignatureBlacklist = currentBlacklist;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool IsBlacklisted(MemberInfo member)
|
public static bool IsBlacklisted(MemberInfo member)
|
||||||
@ -477,7 +487,7 @@ namespace UnityExplorer
|
|||||||
|
|
||||||
|
|
||||||
// Temp fix for IL2CPP until interface support improves
|
// Temp fix for IL2CPP until interface support improves
|
||||||
|
|
||||||
// IsEnumerable
|
// IsEnumerable
|
||||||
|
|
||||||
public static bool IsEnumerable(Type type) => Instance.Internal_IsEnumerable(type);
|
public static bool IsEnumerable(Type type) => Instance.Internal_IsEnumerable(type);
|
||||||
@ -489,7 +499,7 @@ namespace UnityExplorer
|
|||||||
|
|
||||||
// TryGetEnumerator (list)
|
// TryGetEnumerator (list)
|
||||||
|
|
||||||
public static bool TryGetEnumerator(object list, out IEnumerator enumerator)
|
public static bool TryGetEnumerator(object list, out IEnumerator enumerator)
|
||||||
=> Instance.Internal_TryGetEnumerator(list, out enumerator);
|
=> Instance.Internal_TryGetEnumerator(list, out enumerator);
|
||||||
|
|
||||||
protected virtual bool Internal_TryGetEnumerator(object list, out IEnumerator enumerator)
|
protected virtual bool Internal_TryGetEnumerator(object list, out IEnumerator enumerator)
|
||||||
@ -530,7 +540,7 @@ namespace UnityExplorer
|
|||||||
type = typeof(object);
|
type = typeof(object);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsDictionary
|
// IsDictionary
|
||||||
|
|
||||||
public static bool IsDictionary(Type type) => Instance.Internal_IsDictionary(type);
|
public static bool IsDictionary(Type type) => Instance.Internal_IsDictionary(type);
|
||||||
@ -542,7 +552,7 @@ namespace UnityExplorer
|
|||||||
|
|
||||||
// TryGetEnumerator (dictionary)
|
// TryGetEnumerator (dictionary)
|
||||||
|
|
||||||
public static bool TryGetDictEnumerator(object dictionary, out IEnumerator<DictionaryEntry> dictEnumerator)
|
public static bool TryGetDictEnumerator(object dictionary, out IEnumerator<DictionaryEntry> dictEnumerator)
|
||||||
=> Instance.Internal_TryGetDictEnumerator(dictionary, out dictEnumerator);
|
=> Instance.Internal_TryGetDictEnumerator(dictionary, out dictEnumerator);
|
||||||
|
|
||||||
protected virtual bool Internal_TryGetDictEnumerator(object dictionary, out IEnumerator<DictionaryEntry> dictEnumerator)
|
protected virtual bool Internal_TryGetDictEnumerator(object dictionary, out IEnumerator<DictionaryEntry> dictEnumerator)
|
||||||
|
@ -43,9 +43,9 @@ namespace UnityExplorer.Core.Runtime.Il2Cpp
|
|||||||
ExplorerCore.LogUnity(condition, type);
|
ExplorerCore.LogUnity(condition, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void StartCoroutine(IEnumerator routine)
|
public override void Update()
|
||||||
{
|
{
|
||||||
Il2CppCoroutine.Start(routine);
|
Il2CppCoroutine.Process();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal override void ProcessOnPostRender()
|
internal override void ProcessOnPostRender()
|
||||||
@ -53,9 +53,14 @@ namespace UnityExplorer.Core.Runtime.Il2Cpp
|
|||||||
Il2CppCoroutine.ProcessWaitForEndOfFrame();
|
Il2CppCoroutine.ProcessWaitForEndOfFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Update()
|
internal override void ProcessFixedUpdate()
|
||||||
{
|
{
|
||||||
Il2CppCoroutine.Process();
|
Il2CppCoroutine.ProcessWaitForFixedUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void StartCoroutine(IEnumerator routine)
|
||||||
|
{
|
||||||
|
Il2CppCoroutine.Start(routine);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override T AddComponent<T>(GameObject obj, Type type)
|
public override T AddComponent<T>(GameObject obj, Type type)
|
||||||
|
@ -143,7 +143,7 @@ public static class MonoExtensions
|
|||||||
{
|
{
|
||||||
if (pi_childControlHeight == null)
|
if (pi_childControlHeight == null)
|
||||||
pi_childControlHeight = group.GetType().GetProperty("childControlHeight");
|
pi_childControlHeight = group.GetType().GetProperty("childControlHeight");
|
||||||
|
|
||||||
pi_childControlHeight?.SetValue(group, value, null);
|
pi_childControlHeight?.SetValue(group, value, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,11 +2,11 @@
|
|||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityExplorer.UI.IValues;
|
|
||||||
using System.Reflection;
|
|
||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
|
using UnityExplorer.CacheObject.IValues;
|
||||||
#if CPP
|
#if CPP
|
||||||
using UnhollowerRuntimeLib;
|
using UnhollowerRuntimeLib;
|
||||||
using UnhollowerBaseLib;
|
using UnhollowerBaseLib;
|
||||||
@ -16,7 +16,7 @@ namespace UnityExplorer.Tests
|
|||||||
{
|
{
|
||||||
public class TestIndexer : IList<int>
|
public class TestIndexer : IList<int>
|
||||||
{
|
{
|
||||||
private readonly List<int> list = new List<int>() { 1,2,3,4,5 };
|
private readonly List<int> list = new List<int>() { 1, 2, 3, 4, 5 };
|
||||||
|
|
||||||
public int Count => list.Count;
|
public int Count => list.Count;
|
||||||
public bool IsReadOnly => false;
|
public bool IsReadOnly => false;
|
||||||
@ -133,21 +133,21 @@ namespace UnityExplorer.Tests
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void TestGeneric<T>()
|
private static void TestGeneric<T>()
|
||||||
{
|
{
|
||||||
ExplorerCore.Log("Test1 " + typeof(T).FullName);
|
ExplorerCore.Log("Test1 " + typeof(T).FullName);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void TestGenericClass<T>() where T : class
|
private static void TestGenericClass<T>() where T : class
|
||||||
{
|
{
|
||||||
ExplorerCore.Log("Test2 " + typeof(T).FullName);
|
ExplorerCore.Log("Test2 " + typeof(T).FullName);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void TestComponent<T>() where T : Component
|
private static void TestComponent<T>() where T : Component
|
||||||
{
|
{
|
||||||
ExplorerCore.Log("Test3 " + typeof(T).FullName);
|
ExplorerCore.Log("Test3 " + typeof(T).FullName);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void TestStruct<T>() where T : struct
|
private static void TestStruct<T>() where T : struct
|
||||||
{
|
{
|
||||||
ExplorerCore.Log("Test3 " + typeof(T).FullName);
|
ExplorerCore.Log("Test3 " + typeof(T).FullName);
|
||||||
|
@ -22,7 +22,7 @@ namespace UnityExplorer
|
|||||||
public const string NUMBER_FORMAT = "0.####";
|
public const string NUMBER_FORMAT = "0.####";
|
||||||
|
|
||||||
private static readonly Dictionary<int, string> numSequenceStrings = new Dictionary<int, string>();
|
private static readonly Dictionary<int, string> numSequenceStrings = new Dictionary<int, string>();
|
||||||
|
|
||||||
// Helper for formatting float/double/decimal numbers to maximum of 4 decimal points.
|
// Helper for formatting float/double/decimal numbers to maximum of 4 decimal points.
|
||||||
public static string FormatDecimalSequence(params object[] numbers)
|
public static string FormatDecimalSequence(params object[] numbers)
|
||||||
{
|
{
|
||||||
@ -100,7 +100,7 @@ namespace UnityExplorer
|
|||||||
obj = ReflectionUtility.GetMethodInfo(type, "Parse", ArgumentUtility.ParseArgs)
|
obj = ReflectionUtility.GetMethodInfo(type, "Parse", ArgumentUtility.ParseArgs)
|
||||||
.Invoke(null, new object[] { input });
|
.Invoke(null, new object[] { input });
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@ -148,7 +148,7 @@ namespace UnityExplorer
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
return obj.ToString();
|
return obj.ToString();
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
@ -151,10 +151,10 @@ namespace UnityExplorer
|
|||||||
private static string HighlightType(Type type)
|
private static string HighlightType(Type type)
|
||||||
{
|
{
|
||||||
string key = type.ToString();
|
string key = type.ToString();
|
||||||
|
|
||||||
if (typeToRichType.ContainsKey(key))
|
if (typeToRichType.ContainsKey(key))
|
||||||
return typeToRichType[key];
|
return typeToRichType[key];
|
||||||
|
|
||||||
var sb = new StringBuilder(type.Name);
|
var sb = new StringBuilder(type.Name);
|
||||||
|
|
||||||
bool isArray = false;
|
bool isArray = false;
|
||||||
@ -212,7 +212,7 @@ namespace UnityExplorer
|
|||||||
{
|
{
|
||||||
if (args.Length < 1)
|
if (args.Length < 1)
|
||||||
return string.Empty;
|
return string.Empty;
|
||||||
|
|
||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
|
|
||||||
for (int i = 0; i < args.Length; i++)
|
for (int i = 0; i < args.Length; i++)
|
||||||
@ -254,7 +254,7 @@ namespace UnityExplorer
|
|||||||
isStatic = true;
|
isStatic = true;
|
||||||
return FIELD_STATIC;
|
return FIELD_STATIC;
|
||||||
}
|
}
|
||||||
|
|
||||||
return FIELD_INSTANCE;
|
return FIELD_INSTANCE;
|
||||||
}
|
}
|
||||||
else if (memberInfo is MethodInfo mi)
|
else if (memberInfo is MethodInfo mi)
|
||||||
@ -264,7 +264,7 @@ namespace UnityExplorer
|
|||||||
isStatic = true;
|
isStatic = true;
|
||||||
return METHOD_STATIC;
|
return METHOD_STATIC;
|
||||||
}
|
}
|
||||||
|
|
||||||
return METHOD_INSTANCE;
|
return METHOD_INSTANCE;
|
||||||
}
|
}
|
||||||
else if (memberInfo is PropertyInfo pi)
|
else if (memberInfo is PropertyInfo pi)
|
||||||
@ -274,7 +274,7 @@ namespace UnityExplorer
|
|||||||
isStatic = true;
|
isStatic = true;
|
||||||
return PROP_STATIC;
|
return PROP_STATIC;
|
||||||
}
|
}
|
||||||
|
|
||||||
return PROP_INSTANCE;
|
return PROP_INSTANCE;
|
||||||
}
|
}
|
||||||
//else if (memberInfo is EventInfo ei)
|
//else if (memberInfo is EventInfo ei)
|
||||||
@ -284,7 +284,7 @@ namespace UnityExplorer
|
|||||||
// isStatic = true;
|
// isStatic = true;
|
||||||
// return EVENT_STATIC;
|
// return EVENT_STATIC;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// return EVENT_INSTANCE;
|
// return EVENT_INSTANCE;
|
||||||
//}
|
//}
|
||||||
|
|
||||||
|
@ -13,7 +13,6 @@ namespace UnityExplorer
|
|||||||
public static class ToStringUtility
|
public static class ToStringUtility
|
||||||
{
|
{
|
||||||
internal static Dictionary<string, MethodInfo> toStringMethods = new Dictionary<string, MethodInfo>();
|
internal static Dictionary<string, MethodInfo> toStringMethods = new Dictionary<string, MethodInfo>();
|
||||||
internal static Dictionary<string, MethodInfo> toStringFormattedMethods = new Dictionary<string, MethodInfo>();
|
|
||||||
|
|
||||||
private const string nullString = "<color=grey>null</color>";
|
private const string nullString = "<color=grey>null</color>";
|
||||||
private const string nullUnknown = nullString + " (?)";
|
private const string nullUnknown = nullString + " (?)";
|
||||||
@ -82,7 +81,7 @@ namespace UnityExplorer
|
|||||||
sb.Append(PruneString(obj.name, 50, 1));
|
sb.Append(PruneString(obj.name, 50, 1));
|
||||||
sb.Append('"');
|
sb.Append('"');
|
||||||
}
|
}
|
||||||
|
|
||||||
AppendRichType(sb, richType);
|
AppendRichType(sb, richType);
|
||||||
}
|
}
|
||||||
else if (type.FullName.StartsWith(eventSystemNamespace))
|
else if (type.FullName.StartsWith(eventSystemNamespace))
|
||||||
@ -94,8 +93,8 @@ namespace UnityExplorer
|
|||||||
{
|
{
|
||||||
var toString = ToString(value);
|
var toString = ToString(value);
|
||||||
|
|
||||||
if (type.IsGenericType
|
if (type.IsGenericType
|
||||||
|| toString == type.FullName
|
|| toString == type.FullName
|
||||||
|| toString == $"{type.FullName} {type.FullName}"
|
|| toString == $"{type.FullName} {type.FullName}"
|
||||||
|| toString == $"Il2Cpp{type.FullName}" || type.FullName == $"Il2Cpp{toString}")
|
|| toString == $"Il2Cpp{type.FullName}" || type.FullName == $"Il2Cpp{toString}")
|
||||||
{
|
{
|
||||||
@ -132,22 +131,12 @@ namespace UnityExplorer
|
|||||||
|
|
||||||
var type = value.GetActualType();
|
var type = value.GetActualType();
|
||||||
|
|
||||||
// Find and cache the relevant ToString method for this Type, if haven't already.
|
// Find and cache the ToString method for this Type, if haven't already.
|
||||||
|
|
||||||
if (!toStringMethods.ContainsKey(type.AssemblyQualifiedName))
|
if (!toStringMethods.ContainsKey(type.AssemblyQualifiedName))
|
||||||
{
|
{
|
||||||
try
|
var toStringMethod = type.GetMethod("ToString", ArgumentUtility.EmptyTypes);
|
||||||
{
|
toStringMethods.Add(type.AssemblyQualifiedName, toStringMethod);
|
||||||
var formatMethod = type.GetMethod("ToString", ArgumentUtility.ParseArgs);
|
|
||||||
formatMethod.Invoke(value, new object[] { ParseUtility.NUMBER_FORMAT });
|
|
||||||
toStringFormattedMethods.Add(type.AssemblyQualifiedName, formatMethod);
|
|
||||||
toStringMethods.Add(type.AssemblyQualifiedName, null);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
var toStringMethod = type.GetMethod("ToString", ArgumentUtility.EmptyTypes);
|
|
||||||
toStringMethods.Add(type.AssemblyQualifiedName, toStringMethod);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Invoke the ToString method on the object
|
// Invoke the ToString method on the object
|
||||||
@ -157,10 +146,7 @@ namespace UnityExplorer
|
|||||||
string toString;
|
string toString;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (toStringFormattedMethods.TryGetValue(type.AssemblyQualifiedName, out MethodInfo formatMethod))
|
toString = (string)toStringMethods[type.AssemblyQualifiedName].Invoke(value, ArgumentUtility.EmptyArgs);
|
||||||
toString = (string)formatMethod.Invoke(value, new object[] { ParseUtility.NUMBER_FORMAT });
|
|
||||||
else
|
|
||||||
toString = (string)toStringMethods[type.AssemblyQualifiedName].Invoke(value, ArgumentUtility.EmptyArgs);
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
@ -2,9 +2,11 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.Events;
|
using UnityEngine.Events;
|
||||||
|
using UnityEngine.UI;
|
||||||
using Object = UnityEngine.Object;
|
using Object = UnityEngine.Object;
|
||||||
|
|
||||||
// Project-wide namespace for accessibility
|
// Project-wide namespace for accessibility
|
||||||
@ -107,5 +109,16 @@ namespace UnityExplorer
|
|||||||
|
|
||||||
return color;
|
return color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static PropertyInfo onEndEdit;
|
||||||
|
|
||||||
|
public static UnityEvent<string> GetOnEndEdit(this InputField _this)
|
||||||
|
{
|
||||||
|
if (onEndEdit == null)
|
||||||
|
onEndEdit = typeof(InputField).GetProperty("onEndEdit")
|
||||||
|
?? throw new Exception("Could not get InputField.onEndEdit property!");
|
||||||
|
|
||||||
|
return onEndEdit.GetValue(_this, null).TryCast<UnityEvent<string>>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,8 @@ using UnityExplorer.Core.Input;
|
|||||||
using UnityExplorer.Core.Runtime;
|
using UnityExplorer.Core.Runtime;
|
||||||
using UnityExplorer.Tests;
|
using UnityExplorer.Tests;
|
||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
using UnityExplorer.UI.Inspectors;
|
using UnityExplorer.Inspectors;
|
||||||
|
using UnityExplorer.ObjectExplorer;
|
||||||
using UnityExplorer.UI.Panels;
|
using UnityExplorer.UI.Panels;
|
||||||
|
|
||||||
namespace UnityExplorer
|
namespace UnityExplorer
|
||||||
@ -19,7 +20,7 @@ namespace UnityExplorer
|
|||||||
public static class ExplorerCore
|
public static class ExplorerCore
|
||||||
{
|
{
|
||||||
public const string NAME = "UnityExplorer";
|
public const string NAME = "UnityExplorer";
|
||||||
public const string VERSION = "4.0.2";
|
public const string VERSION = "4.1.8";
|
||||||
public const string AUTHOR = "Sinai";
|
public const string AUTHOR = "Sinai";
|
||||||
public const string GUID = "com.sinai.unityexplorer";
|
public const string GUID = "com.sinai.unityexplorer";
|
||||||
|
|
||||||
@ -102,15 +103,15 @@ namespace UnityExplorer
|
|||||||
RuntimeProvider.Instance.ProcessOnPostRender();
|
RuntimeProvider.Instance.ProcessOnPostRender();
|
||||||
}
|
}
|
||||||
|
|
||||||
#region LOGGING
|
#region LOGGING
|
||||||
|
|
||||||
public static void Log(object message)
|
public static void Log(object message)
|
||||||
=> Log(message, LogType.Log);
|
=> Log(message, LogType.Log);
|
||||||
|
|
||||||
public static void LogWarning(object message)
|
public static void LogWarning(object message)
|
||||||
=> Log(message, LogType.Warning);
|
=> Log(message, LogType.Warning);
|
||||||
|
|
||||||
public static void LogError(object message)
|
public static void LogError(object message)
|
||||||
=> Log(message, LogType.Error);
|
=> Log(message, LogType.Error);
|
||||||
|
|
||||||
public static void LogUnity(object message, LogType logType)
|
public static void LogUnity(object message, LogType logType)
|
||||||
@ -145,6 +146,6 @@ namespace UnityExplorer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,19 +2,32 @@
|
|||||||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
|
||||||
<Target Name="ILRepacker" AfterTargets="Build">
|
<Target Name="ILRepacker" AfterTargets="Build">
|
||||||
|
<!-- Actual merged assemblies -->
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<InputAssemblies Include="$(OutputPath)$(AssemblyName).dll" />
|
<InputAssemblies Include="$(OutputPath)$(AssemblyName).dll" />
|
||||||
<InputAssemblies Include="..\lib\mcs-unity\mcs\bin\Release\mcs.dll" />
|
<InputAssemblies Include="..\lib\mcs-unity\mcs\bin\Release\mcs.dll" />
|
||||||
<InputAssemblies Include="packages\ini-parser.2.5.2\lib\net20\INIFileParser.dll" />
|
<InputAssemblies Include="packages\ini-parser.2.5.2\lib\net20\INIFileParser.dll" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<!-- MonoMod for MelonLoader 0.3.0 -->
|
||||||
|
<ItemGroup Condition="'$(IsMelonLoaderLegacy)'=='true'">
|
||||||
|
<InputAssemblies Include="packages\Mono.Cecil.0.10.4\lib\net35\Mono.Cecil.dll" />
|
||||||
|
<InputAssemblies Include="packages\Mono.Cecil.0.10.4\lib\net35\Mono.Cecil.Mdb.dll" />
|
||||||
|
<InputAssemblies Include="packages\Mono.Cecil.0.10.4\lib\net35\Mono.Cecil.Pdb.dll" />
|
||||||
|
<InputAssemblies Include="packages\Mono.Cecil.0.10.4\lib\net35\Mono.Cecil.Rocks.dll" />
|
||||||
|
<InputAssemblies Include="packages\MonoMod.RuntimeDetour.20.1.1.4\lib\net35\MonoMod.RuntimeDetour.dll" />
|
||||||
|
<InputAssemblies Include="packages\MonoMod.Utils.20.1.1.4\lib\net35\MonoMod.Utils.dll" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<!-- Required references for ILRepack -->
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ReferenceFolders Include="..\lib\" />
|
<ReferenceFolders Include="packages\HarmonyX.2.4.2\lib\net35\" />
|
||||||
<ReferenceFolders Include="..\lib\HarmonyX\Harmony\bin\Release\net35\" />
|
|
||||||
<ReferenceFolders Include="..\lib\BepInEx.6.IL2CPP\" />
|
<ReferenceFolders Include="..\lib\BepInEx.6.IL2CPP\" />
|
||||||
<ReferenceFolders Include="..\lib\BepInEx.6.Mono\" />
|
<ReferenceFolders Include="..\lib\BepInEx.6.Mono\" />
|
||||||
<ReferenceFolders Include="..\lib\BepInEx.5\" />
|
<ReferenceFolders Include="..\lib\BepInEx.5\" />
|
||||||
<ReferenceFolders Include="..\lib\MelonLoader\" />
|
<ReferenceFolders Include="..\lib\MelonLoader\" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ILRepack
|
<ILRepack
|
||||||
Parallel="true"
|
Parallel="true"
|
||||||
Internalize="true"
|
Internalize="true"
|
||||||
@ -22,7 +35,8 @@
|
|||||||
LibraryPath="@(ReferenceFolders)"
|
LibraryPath="@(ReferenceFolders)"
|
||||||
InputAssemblies="@(InputAssemblies)"
|
InputAssemblies="@(InputAssemblies)"
|
||||||
TargetKind="Dll"
|
TargetKind="Dll"
|
||||||
OutputFile="$(OutputPath)$(AssemblyName).dll" />
|
OutputFile="$(OutputPath)$(AssemblyName).dll"
|
||||||
|
/>
|
||||||
</Target>
|
</Target>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
@ -6,13 +6,13 @@ using System.Text;
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.Core.Input;
|
using UnityExplorer.Core.Input;
|
||||||
using UnityExplorer.UI.ObjectPool;
|
using UnityExplorer.UI;
|
||||||
|
using UnityExplorer.UI.Models;
|
||||||
using UnityExplorer.UI.Panels;
|
using UnityExplorer.UI.Panels;
|
||||||
using UnityExplorer.UI.Utility;
|
|
||||||
using UnityExplorer.UI.Widgets;
|
using UnityExplorer.UI.Widgets;
|
||||||
using UnityExplorer.UI.Widgets.AutoComplete;
|
using UnityExplorer.UI.Widgets.AutoComplete;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Inspectors
|
namespace UnityExplorer.Inspectors
|
||||||
{
|
{
|
||||||
public class GameObjectInspector : InspectorBase
|
public class GameObjectInspector : InspectorBase
|
||||||
{
|
{
|
||||||
@ -64,7 +64,7 @@ namespace UnityExplorer.UI.Inspectors
|
|||||||
addCompInput.Text = "";
|
addCompInput.Text = "";
|
||||||
|
|
||||||
TransformTree.Clear();
|
TransformTree.Clear();
|
||||||
ComponentList.Clear();
|
UpdateComponents();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CloseInspector()
|
public override void CloseInspector()
|
||||||
@ -113,6 +113,9 @@ namespace UnityExplorer.UI.Inspectors
|
|||||||
|
|
||||||
private IEnumerable<GameObject> GetTransformEntries()
|
private IEnumerable<GameObject> GetTransformEntries()
|
||||||
{
|
{
|
||||||
|
if (!GOTarget)
|
||||||
|
return Enumerable.Empty<GameObject>();
|
||||||
|
|
||||||
cachedChildren.Clear();
|
cachedChildren.Clear();
|
||||||
for (int i = 0; i < GOTarget.transform.childCount; i++)
|
for (int i = 0; i < GOTarget.transform.childCount; i++)
|
||||||
cachedChildren.Add(GOTarget.transform.GetChild(i).gameObject);
|
cachedChildren.Add(GOTarget.transform.GetChild(i).gameObject);
|
||||||
@ -125,41 +128,59 @@ namespace UnityExplorer.UI.Inspectors
|
|||||||
private readonly List<bool> behaviourEnabledStates = new List<bool>();
|
private readonly List<bool> behaviourEnabledStates = new List<bool>();
|
||||||
|
|
||||||
// ComponentList.GetRootEntriesMethod
|
// ComponentList.GetRootEntriesMethod
|
||||||
private List<Component> GetComponentEntries() => componentEntries;
|
private List<Component> GetComponentEntries() => GOTarget ? componentEntries : Enumerable.Empty<Component>().ToList();
|
||||||
|
|
||||||
public void UpdateComponents()
|
public void UpdateComponents()
|
||||||
{
|
{
|
||||||
|
if (!GOTarget)
|
||||||
|
{
|
||||||
|
componentEntries.Clear();
|
||||||
|
compInstanceIDs.Clear();
|
||||||
|
behaviourEntries.Clear();
|
||||||
|
behaviourEnabledStates.Clear();
|
||||||
|
ComponentList.RefreshData();
|
||||||
|
ComponentList.ScrollPool.Refresh(true, true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Check if we actually need to refresh the component cells or not.
|
// Check if we actually need to refresh the component cells or not.
|
||||||
var comps = GOTarget.GetComponents<Component>();
|
var comps = GOTarget.GetComponents<Component>();
|
||||||
var behaviours = GOTarget.GetComponents<Behaviour>();
|
var behaviours = GOTarget.GetComponents<Behaviour>();
|
||||||
|
|
||||||
bool needRefresh = false;
|
bool needRefresh = false;
|
||||||
if (comps.Length != componentEntries.Count || behaviours.Length != behaviourEntries.Count)
|
|
||||||
{
|
|
||||||
needRefresh = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach (var comp in comps)
|
|
||||||
{
|
|
||||||
if (!compInstanceIDs.Contains(comp.GetInstanceID()))
|
|
||||||
{
|
|
||||||
needRefresh = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!needRefresh)
|
int count = 0;
|
||||||
|
foreach (var comp in comps)
|
||||||
|
{
|
||||||
|
if (!comp)
|
||||||
|
continue;
|
||||||
|
count++;
|
||||||
|
if (!compInstanceIDs.Contains(comp.GetInstanceID()))
|
||||||
{
|
{
|
||||||
for (int i = 0; i < behaviours.Length; i++)
|
needRefresh = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!needRefresh)
|
||||||
|
{
|
||||||
|
if (count != componentEntries.Count)
|
||||||
|
needRefresh = true;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
count = 0;
|
||||||
|
foreach (var behaviour in behaviours)
|
||||||
{
|
{
|
||||||
var behaviour = behaviours[i];
|
if (!behaviour)
|
||||||
if (behaviour.enabled != behaviourEnabledStates[i])
|
continue;
|
||||||
|
if (count >= behaviourEnabledStates.Count || behaviour.enabled != behaviourEnabledStates[count])
|
||||||
{
|
{
|
||||||
needRefresh = true;
|
needRefresh = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
count++;
|
||||||
}
|
}
|
||||||
|
if (!needRefresh && count != behaviourEntries.Count)
|
||||||
|
needRefresh = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,9 +189,9 @@ namespace UnityExplorer.UI.Inspectors
|
|||||||
|
|
||||||
componentEntries.Clear();
|
componentEntries.Clear();
|
||||||
compInstanceIDs.Clear();
|
compInstanceIDs.Clear();
|
||||||
|
|
||||||
foreach (var comp in comps)
|
foreach (var comp in comps)
|
||||||
{
|
{
|
||||||
|
if (!comp) continue;
|
||||||
componentEntries.Add(comp);
|
componentEntries.Add(comp);
|
||||||
compInstanceIDs.Add(comp.GetInstanceID());
|
compInstanceIDs.Add(comp.GetInstanceID());
|
||||||
}
|
}
|
||||||
@ -179,6 +200,7 @@ namespace UnityExplorer.UI.Inspectors
|
|||||||
behaviourEnabledStates.Clear();
|
behaviourEnabledStates.Clear();
|
||||||
foreach (var behaviour in behaviours)
|
foreach (var behaviour in behaviours)
|
||||||
{
|
{
|
||||||
|
if (!behaviour) continue;
|
||||||
behaviourEntries.Add(behaviour);
|
behaviourEntries.Add(behaviour);
|
||||||
behaviourEnabledStates.Add(behaviour.enabled);
|
behaviourEnabledStates.Add(behaviour.enabled);
|
||||||
}
|
}
|
||||||
@ -195,10 +217,10 @@ namespace UnityExplorer.UI.Inspectors
|
|||||||
|
|
||||||
TransformTree.RefreshData(true, false);
|
TransformTree.RefreshData(true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnAddComponentClicked(string input)
|
private void OnAddComponentClicked(string input)
|
||||||
{
|
{
|
||||||
if (ReflectionUtility.AllTypes.TryGetValue(input, out Type type))
|
if (ReflectionUtility.GetTypeByName(input) is Type type)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -221,10 +243,10 @@ namespace UnityExplorer.UI.Inspectors
|
|||||||
|
|
||||||
public override GameObject CreateContent(GameObject parent)
|
public override GameObject CreateContent(GameObject parent)
|
||||||
{
|
{
|
||||||
UIRoot = UIFactory.CreateVerticalGroup(Pool<GameObjectInspector>.Instance.InactiveHolder,
|
UIRoot = UIFactory.CreateVerticalGroup(parent, "GameObjectInspector", true, false, true, true, 5,
|
||||||
"GameObjectInspector", true, false, true, true, 5, new Vector4(4, 4, 4, 4), new Color(0.065f, 0.065f, 0.065f));
|
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,
|
var scrollObj = UIFactory.CreateScrollView(UIRoot, "GameObjectInspector", out Content, out var scrollbar,
|
||||||
new Color(0.065f, 0.065f, 0.065f));
|
new Color(0.065f, 0.065f, 0.065f));
|
||||||
UIFactory.SetLayoutElement(scrollObj, minHeight: 250, preferredHeight: 300, flexibleHeight: 0, flexibleWidth: 9999);
|
UIFactory.SetLayoutElement(scrollObj, minHeight: 250, preferredHeight: 300, flexibleHeight: 0, flexibleWidth: 9999);
|
||||||
|
|
||||||
@ -232,7 +254,7 @@ namespace UnityExplorer.UI.Inspectors
|
|||||||
|
|
||||||
// Construct GO Controls
|
// Construct GO Controls
|
||||||
GOControls = new GameObjectControls(this);
|
GOControls = new GameObjectControls(this);
|
||||||
|
|
||||||
ConstructLists();
|
ConstructLists();
|
||||||
|
|
||||||
return UIRoot;
|
return UIRoot;
|
@ -4,9 +4,10 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
|
using UnityExplorer.UI;
|
||||||
using UnityExplorer.UI.Widgets;
|
using UnityExplorer.UI.Widgets;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Inspectors
|
namespace UnityExplorer.Inspectors
|
||||||
{
|
{
|
||||||
public class ComponentCell : ButtonCell
|
public class ComponentCell : ButtonCell
|
||||||
{
|
{
|
@ -5,13 +5,13 @@ using System.Text;
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityExplorer.UI.Widgets;
|
using UnityExplorer.UI.Widgets;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Inspectors
|
namespace UnityExplorer.Inspectors
|
||||||
{
|
{
|
||||||
public class ComponentList : ButtonListHandler<Component, ComponentCell>
|
public class ComponentList : ButtonListHandler<Component, ComponentCell>
|
||||||
{
|
{
|
||||||
public GameObjectInspector Parent;
|
public GameObjectInspector Parent;
|
||||||
|
|
||||||
public ComponentList(ScrollPool<ComponentCell> scrollPool, Func<List<Component>> getEntriesMethod)
|
public ComponentList(ScrollPool<ComponentCell> scrollPool, Func<List<Component>> getEntriesMethod)
|
||||||
: base(scrollPool, getEntriesMethod, null, null, null)
|
: base(scrollPool, getEntriesMethod, null, null, null)
|
||||||
{
|
{
|
||||||
base.SetICell = SetComponentCell;
|
base.SetICell = SetComponentCell;
|
||||||
@ -21,7 +21,8 @@ namespace UnityExplorer.UI.Inspectors
|
|||||||
|
|
||||||
public void Clear()
|
public void Clear()
|
||||||
{
|
{
|
||||||
this.currentEntries.Clear();
|
RefreshData();
|
||||||
|
ScrollPool.Refresh(true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool CheckShouldDisplay(Component _, string __) => true;
|
private bool CheckShouldDisplay(Component _, string __) => true;
|
||||||
@ -111,7 +112,7 @@ namespace UnityExplorer.UI.Inspectors
|
|||||||
cell.BehaviourToggle.interactable = false;
|
cell.BehaviourToggle.interactable = false;
|
||||||
cell.BehaviourToggle.Set(true, false);
|
cell.BehaviourToggle.Set(true, false);
|
||||||
//RuntimeProvider.Instance.SetColorBlock(cell.BehaviourToggle,)
|
//RuntimeProvider.Instance.SetColorBlock(cell.BehaviourToggle,)
|
||||||
cell.BehaviourToggle.graphic.color = new Color(0.2f, 0.2f, 0.2f);
|
cell.BehaviourToggle.graphic.color = new Color(0.2f, 0.2f, 0.2f);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if component is the first index it must be the transform, dont show Destroy button for it.
|
// if component is the first index it must be the transform, dont show Destroy button for it.
|
@ -5,8 +5,9 @@ using System.Text;
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.Core.Input;
|
using UnityExplorer.Core.Input;
|
||||||
|
using UnityExplorer.UI;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Inspectors
|
namespace UnityExplorer.Inspectors
|
||||||
{
|
{
|
||||||
public class GameObjectControls
|
public class GameObjectControls
|
||||||
{
|
{
|
||||||
@ -186,7 +187,7 @@ namespace UnityExplorer.UI.Inspectors
|
|||||||
if (parentToSet)
|
if (parentToSet)
|
||||||
DoSetParent(parentToSet);
|
DoSetParent(parentToSet);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ExplorerCore.LogWarning($"Could not find any GameObject name or path '{input}'!");
|
ExplorerCore.LogWarning($"Could not find any GameObject name or path '{input}'!");
|
||||||
UpdateGameObjectInfo(false, true);
|
UpdateGameObjectInfo(false, true);
|
||||||
}
|
}
|
||||||
@ -232,6 +233,12 @@ namespace UnityExplorer.UI.Inspectors
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
private void OnLayerDropdownChanged(int value)
|
||||||
{
|
{
|
||||||
GOTarget.layer = value;
|
GOTarget.layer = value;
|
||||||
@ -436,7 +443,7 @@ namespace UnityExplorer.UI.Inspectors
|
|||||||
|
|
||||||
private void ConstructTopInfo()
|
private void ConstructTopInfo()
|
||||||
{
|
{
|
||||||
var topInfoHolder = UIFactory.CreateVerticalGroup(Parent.Content, "TopInfoHolder", false, false, true, true, 3,
|
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);
|
new Vector4(3, 3, 3, 3), new Color(0.1f, 0.1f, 0.1f), TextAnchor.MiddleLeft);
|
||||||
UIFactory.SetLayoutElement(topInfoHolder, minHeight: 100, flexibleWidth: 9999);
|
UIFactory.SetLayoutElement(topInfoHolder, minHeight: 100, flexibleWidth: 9999);
|
||||||
topInfoHolder.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
topInfoHolder.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||||||
@ -462,7 +469,7 @@ namespace UnityExplorer.UI.Inspectors
|
|||||||
//UIFactory.SetLayoutElement(pathApplyBtn.Component.gameObject, minHeight: 25, minWidth: 120);
|
//UIFactory.SetLayoutElement(pathApplyBtn.Component.gameObject, minHeight: 25, minWidth: 120);
|
||||||
//pathApplyBtn.OnClick += () => { OnPathEndEdit(PathInput.Text); };
|
//pathApplyBtn.OnClick += () => { OnPathEndEdit(PathInput.Text); };
|
||||||
|
|
||||||
PathInput.Component.onEndEdit.AddListener((string val) => { OnPathEndEdit(val); });
|
PathInput.Component.GetOnEndEdit().AddListener((string val) => { OnPathEndEdit(val); });
|
||||||
|
|
||||||
// Title and update row
|
// Title and update row
|
||||||
|
|
||||||
@ -478,7 +485,7 @@ namespace UnityExplorer.UI.Inspectors
|
|||||||
NameInput = UIFactory.CreateInputField(titleRow, "NameInput", "untitled");
|
NameInput = UIFactory.CreateInputField(titleRow, "NameInput", "untitled");
|
||||||
UIFactory.SetLayoutElement(NameInput.Component.gameObject, minHeight: 30, minWidth: 100, flexibleWidth: 9999);
|
UIFactory.SetLayoutElement(NameInput.Component.gameObject, minHeight: 30, minWidth: 100, flexibleWidth: 9999);
|
||||||
NameInput.Component.textComponent.fontSize = 15;
|
NameInput.Component.textComponent.fontSize = 15;
|
||||||
NameInput.Component.onEndEdit.AddListener((string val) => { OnNameEndEdit(val); });
|
NameInput.Component.GetOnEndEdit().AddListener((string val) => { OnNameEndEdit(val); });
|
||||||
|
|
||||||
// second row (toggles, instanceID, tag, buttons)
|
// second row (toggles, instanceID, tag, buttons)
|
||||||
|
|
||||||
@ -515,7 +522,7 @@ namespace UnityExplorer.UI.Inspectors
|
|||||||
TagInput = UIFactory.CreateInputField(secondRow, "TagInput", "none");
|
TagInput = UIFactory.CreateInputField(secondRow, "TagInput", "none");
|
||||||
UIFactory.SetLayoutElement(TagInput.Component.gameObject, minHeight: 25, minWidth: 100, flexibleWidth: 999);
|
UIFactory.SetLayoutElement(TagInput.Component.gameObject, minHeight: 25, minWidth: 100, flexibleWidth: 999);
|
||||||
TagInput.Component.textComponent.color = Color.white;
|
TagInput.Component.textComponent.color = Color.white;
|
||||||
TagInput.Component.onEndEdit.AddListener((string val) => { OnTagEndEdit(val); });
|
TagInput.Component.GetOnEndEdit().AddListener((string val) => { OnTagEndEdit(val); });
|
||||||
|
|
||||||
// Instantiate
|
// Instantiate
|
||||||
var instantiateBtn = UIFactory.CreateButton(secondRow, "InstantiateBtn", "Instantiate", new Color(0.2f, 0.2f, 0.2f));
|
var instantiateBtn = UIFactory.CreateButton(secondRow, "InstantiateBtn", "Instantiate", new Color(0.2f, 0.2f, 0.2f));
|
||||||
@ -533,6 +540,12 @@ namespace UnityExplorer.UI.Inspectors
|
|||||||
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(thirdrow, false, false, true, true, 5, 0, 0, 0, 0, default);
|
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(thirdrow, false, false, true, true, 5, 0, 0, 0, 0, default);
|
||||||
UIFactory.SetLayoutElement(thirdrow, minHeight: 25, flexibleWidth: 9999);
|
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
|
// Scene
|
||||||
var sceneLabel = UIFactory.CreateLabel(thirdrow, "SceneLabel", "Scene:", TextAnchor.MiddleLeft, Color.grey);
|
var sceneLabel = UIFactory.CreateLabel(thirdrow, "SceneLabel", "Scene:", TextAnchor.MiddleLeft, Color.grey);
|
||||||
UIFactory.SetLayoutElement(sceneLabel.gameObject, minHeight: 25, minWidth: 50);
|
UIFactory.SetLayoutElement(sceneLabel.gameObject, minHeight: 25, minWidth: 50);
|
||||||
@ -547,7 +560,7 @@ namespace UnityExplorer.UI.Inspectors
|
|||||||
UIFactory.SetLayoutElement(layerLabel.gameObject, minHeight: 25, minWidth: 50);
|
UIFactory.SetLayoutElement(layerLabel.gameObject, minHeight: 25, minWidth: 50);
|
||||||
|
|
||||||
var layerDrop = UIFactory.CreateDropdown(thirdrow, out LayerDropdown, "0", 14, OnLayerDropdownChanged);
|
var layerDrop = UIFactory.CreateDropdown(thirdrow, out LayerDropdown, "0", 14, OnLayerDropdownChanged);
|
||||||
UIFactory.SetLayoutElement(layerDrop, minHeight: 25, minWidth: 120, flexibleWidth: 999);
|
UIFactory.SetLayoutElement(layerDrop, minHeight: 25, minWidth: 110, flexibleWidth: 999);
|
||||||
LayerDropdown.captionText.color = SignatureHighlighter.EnumGreen;
|
LayerDropdown.captionText.color = SignatureHighlighter.EnumGreen;
|
||||||
if (layerToNames == null)
|
if (layerToNames == null)
|
||||||
GetLayerNames();
|
GetLayerNames();
|
||||||
@ -563,7 +576,7 @@ namespace UnityExplorer.UI.Inspectors
|
|||||||
var flagsDrop = UIFactory.CreateDropdown(thirdrow, out FlagsDropdown, "None", 14, OnFlagsDropdownChanged);
|
var flagsDrop = UIFactory.CreateDropdown(thirdrow, out FlagsDropdown, "None", 14, OnFlagsDropdownChanged);
|
||||||
FlagsDropdown.captionText.color = SignatureHighlighter.EnumGreen;
|
FlagsDropdown.captionText.color = SignatureHighlighter.EnumGreen;
|
||||||
UIFactory.SetLayoutElement(flagsDrop, minHeight: 25, minWidth: 135, flexibleWidth: 999);
|
UIFactory.SetLayoutElement(flagsDrop, minHeight: 25, minWidth: 135, flexibleWidth: 999);
|
||||||
if (hideFlagsValues == null)
|
if (hideFlagsValues == null)
|
||||||
GetHideFlagNames();
|
GetHideFlagNames();
|
||||||
foreach (var name in hideFlagsValues.Keys)
|
foreach (var name in hideFlagsValues.Keys)
|
||||||
FlagsDropdown.options.Add(new Dropdown.OptionData(name));
|
FlagsDropdown.options.Add(new Dropdown.OptionData(name));
|
||||||
@ -632,7 +645,7 @@ namespace UnityExplorer.UI.Inspectors
|
|||||||
var inputField = UIFactory.CreateInputField(rowObj, "InputField", "...");
|
var inputField = UIFactory.CreateInputField(rowObj, "InputField", "...");
|
||||||
UIFactory.SetLayoutElement(inputField.Component.gameObject, minHeight: 25, minWidth: 100, flexibleWidth: 999);
|
UIFactory.SetLayoutElement(inputField.Component.gameObject, minHeight: 25, minWidth: 100, flexibleWidth: 999);
|
||||||
|
|
||||||
inputField.Component.onEndEdit.AddListener((string value) => { OnTransformInputEndEdit(type, value); });
|
inputField.Component.GetOnEndEdit().AddListener((string value) => { OnTransformInputEndEdit(type, value); });
|
||||||
|
|
||||||
var control = new TransformControl(type, inputField);
|
var control = new TransformControl(type, inputField);
|
||||||
|
|
@ -11,7 +11,7 @@ using UnityExplorer.Core.Runtime;
|
|||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
using UnityExplorer.UI.Panels;
|
using UnityExplorer.UI.Panels;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Inspectors
|
namespace UnityExplorer.Inspectors
|
||||||
{
|
{
|
||||||
public enum MouseInspectMode
|
public enum MouseInspectMode
|
||||||
{
|
{
|
||||||
@ -64,12 +64,15 @@ namespace UnityExplorer.UI.Inspectors
|
|||||||
internal static Camera MainCamera;
|
internal static Camera MainCamera;
|
||||||
internal static GraphicRaycaster[] graphicRaycasters;
|
internal static GraphicRaycaster[] graphicRaycasters;
|
||||||
|
|
||||||
|
|
||||||
public void StartInspect(MouseInspectMode mode)
|
public void StartInspect(MouseInspectMode mode)
|
||||||
{
|
{
|
||||||
MainCamera = Camera.main;
|
MainCamera = Camera.main;
|
||||||
if (!MainCamera)
|
|
||||||
|
if (!MainCamera && mode == MouseInspectMode.World)
|
||||||
|
{
|
||||||
|
ExplorerCore.LogWarning("No MainCamera found! Cannot inspect world!");
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
PanelDragger.ForceEnd();
|
PanelDragger.ForceEnd();
|
||||||
|
|
||||||
@ -94,8 +97,14 @@ namespace UnityExplorer.UI.Inspectors
|
|||||||
public void StopInspect()
|
public void StopInspect()
|
||||||
{
|
{
|
||||||
Inspecting = false;
|
Inspecting = false;
|
||||||
|
|
||||||
UIManager.NavBarRect.gameObject.SetActive(true);
|
UIManager.NavBarRect.gameObject.SetActive(true);
|
||||||
UIManager.PanelHolder.SetActive(true);
|
UIManager.PanelHolder.SetActive(true);
|
||||||
|
|
||||||
|
var drop = UIManager.MouseInspectDropdown;
|
||||||
|
if (drop.transform.Find("Dropdown List") is Transform list)
|
||||||
|
drop.DestroyDropdownList(list.gameObject);
|
||||||
|
|
||||||
UIRoot.SetActive(false);
|
UIRoot.SetActive(false);
|
||||||
|
|
||||||
if (Mode == MouseInspectMode.UI)
|
if (Mode == MouseInspectMode.UI)
|
@ -4,10 +4,11 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.UI.ObjectPool;
|
using UnityExplorer.UI;
|
||||||
|
using UnityExplorer.UI.Models;
|
||||||
using UnityExplorer.UI.Panels;
|
using UnityExplorer.UI.Panels;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Inspectors
|
namespace UnityExplorer.Inspectors
|
||||||
{
|
{
|
||||||
public abstract class InspectorBase : IPooledObject
|
public abstract class InspectorBase : IPooledObject
|
||||||
{
|
{
|
@ -5,9 +5,9 @@ using System.Text;
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
using UnityExplorer.UI.CacheObject;
|
using UnityExplorer.CacheObject;
|
||||||
using UnityExplorer.UI.Inspectors;
|
using UnityExplorer.Inspectors;
|
||||||
using UnityExplorer.UI.ObjectPool;
|
using UnityExplorer.UI.Models;
|
||||||
using UnityExplorer.UI.Panels;
|
using UnityExplorer.UI.Panels;
|
||||||
|
|
||||||
namespace UnityExplorer
|
namespace UnityExplorer
|
||||||
@ -87,7 +87,7 @@ namespace UnityExplorer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void CreateInspector<T>(object target, bool staticReflection = false,
|
private static void CreateInspector<T>(object target, bool staticReflection = false,
|
||||||
CacheObjectBase sourceCache = null) where T : InspectorBase
|
CacheObjectBase sourceCache = null) where T : InspectorBase
|
||||||
{
|
{
|
||||||
var inspector = Pool<T>.Borrow();
|
var inspector = Pool<T>.Borrow();
|
@ -4,10 +4,11 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.UI.ObjectPool;
|
using UnityExplorer.UI;
|
||||||
|
using UnityExplorer.UI.Models;
|
||||||
using UnityExplorer.UI.Widgets;
|
using UnityExplorer.UI.Widgets;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Inspectors
|
namespace UnityExplorer.Inspectors
|
||||||
{
|
{
|
||||||
public class InspectorTab : IPooledObject
|
public class InspectorTab : IPooledObject
|
||||||
{
|
{
|
||||||
@ -33,7 +34,7 @@ namespace UnityExplorer.UI.Inspectors
|
|||||||
|
|
||||||
public GameObject CreateContent(GameObject parent)
|
public GameObject CreateContent(GameObject parent)
|
||||||
{
|
{
|
||||||
UIRoot = UIFactory.CreateHorizontalGroup(parent, "TabObject", false, true, true, true, 0,
|
UIRoot = UIFactory.CreateHorizontalGroup(parent, "TabObject", false, true, true, true, 0,
|
||||||
default, new Color(0.13f, 0.13f, 0.13f), childAlignment: TextAnchor.MiddleLeft);
|
default, new Color(0.13f, 0.13f, 0.13f), childAlignment: TextAnchor.MiddleLeft);
|
||||||
UIFactory.SetLayoutElement(UIRoot, minWidth: 200, flexibleWidth: 0);
|
UIFactory.SetLayoutElement(UIRoot, minWidth: 200, flexibleWidth: 0);
|
||||||
UIRoot.AddComponent<Mask>();
|
UIRoot.AddComponent<Mask>();
|
@ -10,14 +10,13 @@ using UnityEngine;
|
|||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.Core.Config;
|
using UnityExplorer.Core.Config;
|
||||||
using UnityExplorer.Core.Runtime;
|
using UnityExplorer.Core.Runtime;
|
||||||
using UnityExplorer.UI.CacheObject;
|
using UnityExplorer.CacheObject;
|
||||||
using UnityExplorer.UI.CacheObject.Views;
|
using UnityExplorer.CacheObject.Views;
|
||||||
using UnityExplorer.UI.ObjectPool;
|
|
||||||
using UnityExplorer.UI.Panels;
|
using UnityExplorer.UI.Panels;
|
||||||
using UnityExplorer.UI.Utility;
|
|
||||||
using UnityExplorer.UI.Widgets;
|
using UnityExplorer.UI.Widgets;
|
||||||
|
using UnityExplorer.UI;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Inspectors
|
namespace UnityExplorer.Inspectors
|
||||||
{
|
{
|
||||||
public class ReflectionInspector : InspectorBase, ICellPoolDataSource<CacheMemberCell>, ICacheObjectController
|
public class ReflectionInspector : InspectorBase, ICellPoolDataSource<CacheMemberCell>, ICacheObjectController
|
||||||
{
|
{
|
||||||
@ -56,6 +55,7 @@ namespace UnityExplorer.UI.Inspectors
|
|||||||
|
|
||||||
private readonly Color disabledButtonColor = new Color(0.24f, 0.24f, 0.24f);
|
private readonly Color disabledButtonColor = new Color(0.24f, 0.24f, 0.24f);
|
||||||
private readonly Color enabledButtonColor = new Color(0.2f, 0.27f, 0.2f);
|
private readonly Color enabledButtonColor = new Color(0.2f, 0.27f, 0.2f);
|
||||||
|
|
||||||
private readonly Dictionary<BindingFlags, ButtonRef> scopeFilterButtons = new Dictionary<BindingFlags, ButtonRef>();
|
private readonly Dictionary<BindingFlags, ButtonRef> scopeFilterButtons = new Dictionary<BindingFlags, ButtonRef>();
|
||||||
private readonly List<Toggle> memberTypeToggles = new List<Toggle>();
|
private readonly List<Toggle> memberTypeToggles = new List<Toggle>();
|
||||||
private InputFieldRef filterInputField;
|
private InputFieldRef filterInputField;
|
||||||
@ -75,7 +75,6 @@ namespace UnityExplorer.UI.Inspectors
|
|||||||
private IEnumerator InitCoroutine()
|
private IEnumerator InitCoroutine()
|
||||||
{
|
{
|
||||||
yield return null;
|
yield return null;
|
||||||
|
|
||||||
LayoutRebuilder.ForceRebuildLayoutImmediate(InspectorPanel.Instance.ContentRect);
|
LayoutRebuilder.ForceRebuildLayoutImmediate(InspectorPanel.Instance.ContentRect);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,7 +143,7 @@ namespace UnityExplorer.UI.Inspectors
|
|||||||
// reset filters
|
// reset filters
|
||||||
|
|
||||||
this.filterInputField.Text = "";
|
this.filterInputField.Text = "";
|
||||||
|
|
||||||
SetFilter("", StaticOnly ? BindingFlags.Static : BindingFlags.Instance);
|
SetFilter("", StaticOnly ? BindingFlags.Static : BindingFlags.Instance);
|
||||||
scopeFilterButtons[BindingFlags.Default].Component.gameObject.SetActive(!StaticOnly);
|
scopeFilterButtons[BindingFlags.Default].Component.gameObject.SetActive(!StaticOnly);
|
||||||
scopeFilterButtons[BindingFlags.Instance].Component.gameObject.SetActive(!StaticOnly);
|
scopeFilterButtons[BindingFlags.Instance].Component.gameObject.SetActive(!StaticOnly);
|
||||||
@ -309,11 +308,8 @@ namespace UnityExplorer.UI.Inspectors
|
|||||||
|
|
||||||
private void CalculateLayouts()
|
private void CalculateLayouts()
|
||||||
{
|
{
|
||||||
// Calculate sizes
|
LeftGroupWidth = (int)Math.Max(200, (0.4f * InspectorManager.PanelWidth) - 5);
|
||||||
LeftGroupWidth = (int)Math.Max(200, (0.4f * InspectorManager.PanelWidth) - 5);// Math.Min(450f, 0.4f * InspectorManager.PanelWidth - 5));
|
|
||||||
RightGroupWidth = (int)Math.Max(200, InspectorManager.PanelWidth - LeftGroupWidth - 65);
|
RightGroupWidth = (int)Math.Max(200, InspectorManager.PanelWidth - LeftGroupWidth - 65);
|
||||||
|
|
||||||
//memberTitleLayout.minWidth = LeftGroupWidth;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetCellLayout(CacheObjectCell cell)
|
private void SetCellLayout(CacheObjectCell cell)
|
||||||
@ -344,7 +340,7 @@ namespace UnityExplorer.UI.Inspectors
|
|||||||
|
|
||||||
ConstructUnityObjectRow();
|
ConstructUnityObjectRow();
|
||||||
|
|
||||||
mainContentHolder = UIFactory.CreateVerticalGroup(UIRoot, "MemberHolder", false, false, true, true, 5, new Vector4(2,2,2,2),
|
mainContentHolder = UIFactory.CreateVerticalGroup(UIRoot, "MemberHolder", false, false, true, true, 5, new Vector4(2, 2, 2, 2),
|
||||||
new Color(0.12f, 0.12f, 0.12f));
|
new Color(0.12f, 0.12f, 0.12f));
|
||||||
UIFactory.SetLayoutElement(mainContentHolder, flexibleWidth: 9999, flexibleHeight: 9999);
|
UIFactory.SetLayoutElement(mainContentHolder, flexibleWidth: 9999, flexibleHeight: 9999);
|
||||||
|
|
||||||
@ -354,7 +350,7 @@ namespace UnityExplorer.UI.Inspectors
|
|||||||
|
|
||||||
// Member scroll pool
|
// Member scroll pool
|
||||||
|
|
||||||
var memberBorder = UIFactory.CreateVerticalGroup(mainContentHolder, "ScrollPoolHolder", false, false, true, true, padding: new Vector4(2,2,2,2),
|
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));
|
bgColor: new Color(0.05f, 0.05f, 0.05f));
|
||||||
UIFactory.SetLayoutElement(memberBorder, flexibleWidth: 9999, flexibleHeight: 9999);
|
UIFactory.SetLayoutElement(memberBorder, flexibleWidth: 9999, flexibleHeight: 9999);
|
||||||
|
|
||||||
@ -482,7 +478,7 @@ namespace UnityExplorer.UI.Inspectors
|
|||||||
|
|
||||||
private void SetUnityTargets()
|
private void SetUnityTargets()
|
||||||
{
|
{
|
||||||
if (!typeof(UnityEngine.Object).IsAssignableFrom(TargetType))
|
if (StaticOnly || !typeof(UnityEngine.Object).IsAssignableFrom(TargetType))
|
||||||
{
|
{
|
||||||
unityObjectRow.SetActive(false);
|
unityObjectRow.SetActive(false);
|
||||||
textureViewer.SetActive(false);
|
textureViewer.SetActive(false);
|
||||||
@ -548,7 +544,7 @@ namespace UnityExplorer.UI.Inspectors
|
|||||||
textureButton.ButtonText.text = "Hide Texture";
|
textureButton.ButtonText.text = "Hide Texture";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// UI construction
|
// UI construction
|
||||||
|
|
||||||
private void ConstructUnityObjectRow()
|
private void ConstructUnityObjectRow()
|
||||||
@ -619,12 +615,15 @@ namespace UnityExplorer.UI.Inspectors
|
|||||||
|
|
||||||
// Actual texture viewer
|
// Actual texture viewer
|
||||||
|
|
||||||
var imageObj = UIFactory.CreateUIObject("TextureViewerImage", textureViewer);
|
var imageViewport = UIFactory.CreateVerticalGroup(textureViewer, "Viewport", false, false, true, true);
|
||||||
textureImage = imageObj.AddComponent<Image>();
|
imageViewport.GetComponent<Image>().color = Color.white;
|
||||||
textureImageLayout = textureImage.gameObject.AddComponent<LayoutElement>();
|
imageViewport.AddComponent<Mask>().showMaskGraphic = false;
|
||||||
|
|
||||||
|
var imageObj = UIFactory.CreateUIObject("Image", imageViewport);
|
||||||
var fitter = imageObj.AddComponent<ContentSizeFitter>();
|
var fitter = imageObj.AddComponent<ContentSizeFitter>();
|
||||||
fitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
fitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||||||
|
textureImage = imageObj.AddComponent<Image>();
|
||||||
|
textureImageLayout = UIFactory.SetLayoutElement(imageObj, flexibleWidth: 9999, flexibleHeight: 9999);
|
||||||
|
|
||||||
textureViewer.SetActive(false);
|
textureViewer.SetActive(false);
|
||||||
}
|
}
|
@ -21,13 +21,9 @@ namespace UnityExplorer.Loader.BIE
|
|||||||
|
|
||||||
public override void RegisterConfigElement<T>(ConfigElement<T> config)
|
public override void RegisterConfigElement<T>(ConfigElement<T> config)
|
||||||
{
|
{
|
||||||
object[] tags = null;
|
var entry = Config.Bind(CTG_NAME, config.Name, config.Value, config.Description);
|
||||||
if (config.IsInternal)
|
|
||||||
tags = new[] { "Advanced" };
|
|
||||||
|
|
||||||
var entry = Config.Bind(CTG_NAME, config.Name, config.Value, new ConfigDescription(config.Description, null, tags));
|
entry.SettingChanged += (object o, EventArgs e) =>
|
||||||
|
|
||||||
entry.SettingChanged += (object o, EventArgs e) =>
|
|
||||||
{
|
{
|
||||||
config.Value = entry.Value;
|
config.Value = entry.Value;
|
||||||
};
|
};
|
||||||
|
@ -7,12 +7,12 @@ using System.Collections.Generic;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityExplorer.Core.Config;
|
|
||||||
using UnityExplorer.Loader.BIE;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityExplorer.Core;
|
|
||||||
using UnityEngine.EventSystems;
|
using UnityEngine.EventSystems;
|
||||||
|
using UnityExplorer.Core;
|
||||||
|
using UnityExplorer.Core.Config;
|
||||||
using UnityExplorer.Core.Input;
|
using UnityExplorer.Core.Input;
|
||||||
|
using UnityExplorer.Loader.BIE;
|
||||||
#if CPP
|
#if CPP
|
||||||
using BepInEx.IL2CPP;
|
using BepInEx.IL2CPP;
|
||||||
using UnhollowerRuntimeLib;
|
using UnhollowerRuntimeLib;
|
||||||
@ -46,11 +46,10 @@ namespace UnityExplorer
|
|||||||
private static readonly Harmony s_harmony = new Harmony(ExplorerCore.GUID);
|
private static readonly Harmony s_harmony = new Harmony(ExplorerCore.GUID);
|
||||||
|
|
||||||
public string ExplorerFolder => Path.Combine(Paths.PluginPath, ExplorerCore.NAME);
|
public string ExplorerFolder => Path.Combine(Paths.PluginPath, ExplorerCore.NAME);
|
||||||
public string ConfigFolder => Path.Combine(Paths.ConfigPath, ExplorerCore.NAME);
|
|
||||||
|
|
||||||
public Action<object> OnLogMessage => LogSource.LogMessage;
|
public Action<object> OnLogMessage => LogSource.LogMessage;
|
||||||
public Action<object> OnLogWarning => LogSource.LogWarning;
|
public Action<object> OnLogWarning => LogSource.LogWarning;
|
||||||
public Action<object> OnLogError => LogSource.LogError;
|
public Action<object> OnLogError => LogSource.LogError;
|
||||||
|
|
||||||
// Init common to Mono and Il2Cpp
|
// Init common to Mono and Il2Cpp
|
||||||
internal void UniversalInit()
|
internal void UniversalInit()
|
||||||
|
@ -10,7 +10,6 @@ namespace UnityExplorer
|
|||||||
{
|
{
|
||||||
string ExplorerFolder { get; }
|
string ExplorerFolder { get; }
|
||||||
|
|
||||||
string ConfigFolder { get; }
|
|
||||||
ConfigHandler ConfigHandler { get; }
|
ConfigHandler ConfigHandler { get; }
|
||||||
|
|
||||||
Action<object> OnLogMessage { get; }
|
Action<object> OnLogMessage { get; }
|
||||||
|
@ -9,11 +9,15 @@ using UnityExplorer.Core;
|
|||||||
using UnityExplorer.Core.Config;
|
using UnityExplorer.Core.Config;
|
||||||
using UnityExplorer.Core.Input;
|
using UnityExplorer.Core.Input;
|
||||||
using UnityExplorer.Loader.ML;
|
using UnityExplorer.Loader.ML;
|
||||||
|
#if ML_LEGACY
|
||||||
|
using Harmony;
|
||||||
|
#else
|
||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
|
[assembly: MelonPlatformDomain(MelonPlatformDomainAttribute.CompatibleDomains.UNIVERSAL)]
|
||||||
|
#endif
|
||||||
|
|
||||||
[assembly: MelonInfo(typeof(ExplorerMelonMod), ExplorerCore.NAME, ExplorerCore.VERSION, ExplorerCore.AUTHOR)]
|
[assembly: MelonInfo(typeof(ExplorerMelonMod), ExplorerCore.NAME, ExplorerCore.VERSION, ExplorerCore.AUTHOR)]
|
||||||
[assembly: MelonGame(null, null)]
|
[assembly: MelonGame(null, null)]
|
||||||
[assembly: MelonPlatformDomain(MelonPlatformDomainAttribute.CompatibleDomains.UNIVERSAL)]
|
|
||||||
[assembly: MelonColor(ConsoleColor.DarkCyan)]
|
[assembly: MelonColor(ConsoleColor.DarkCyan)]
|
||||||
|
|
||||||
namespace UnityExplorer
|
namespace UnityExplorer
|
||||||
@ -23,7 +27,6 @@ namespace UnityExplorer
|
|||||||
public static ExplorerMelonMod Instance;
|
public static ExplorerMelonMod Instance;
|
||||||
|
|
||||||
public string ExplorerFolder => Path.Combine("Mods", ExplorerCore.NAME);
|
public string ExplorerFolder => Path.Combine("Mods", ExplorerCore.NAME);
|
||||||
public string ConfigFolder => ExplorerFolder;
|
|
||||||
|
|
||||||
public ConfigHandler ConfigHandler => _configHandler;
|
public ConfigHandler ConfigHandler => _configHandler;
|
||||||
public MelonLoaderConfigHandler _configHandler;
|
public MelonLoaderConfigHandler _configHandler;
|
||||||
@ -67,7 +70,11 @@ namespace UnityExplorer
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var prop = type.GetProperty(property);
|
var prop = type.GetProperty(property);
|
||||||
|
#if ML_LEGACY
|
||||||
|
this.Harmony.Patch(prop.GetSetMethod(), prefix: prefix);
|
||||||
|
#else
|
||||||
HarmonyInstance.Patch(prop.GetSetMethod(), prefix: prefix);
|
HarmonyInstance.Patch(prop.GetSetMethod(), prefix: prefix);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
#if ML
|
#if ML
|
||||||
|
|
||||||
|
#if !ML_LEGACY // ML 0.3.1+ config handler
|
||||||
|
|
||||||
using MelonLoader;
|
using MelonLoader;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@ -75,4 +78,129 @@ namespace UnityExplorer.Loader.ML
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else // ML 0.3.0 config handler
|
||||||
|
|
||||||
|
using MelonLoader;
|
||||||
|
using MelonLoader.Tomlyn.Model;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityExplorer.Core;
|
||||||
|
using UnityExplorer.Core.Config;
|
||||||
|
|
||||||
|
namespace UnityExplorer.Loader.ML
|
||||||
|
{
|
||||||
|
public class MelonLoaderConfigHandler : ConfigHandler
|
||||||
|
{
|
||||||
|
internal const string CTG_NAME = "UnityExplorer";
|
||||||
|
|
||||||
|
internal MelonPreferences_Category prefCategory;
|
||||||
|
|
||||||
|
public override void Init()
|
||||||
|
{
|
||||||
|
prefCategory = MelonPreferences.CreateCategory(CTG_NAME, $"{CTG_NAME} Settings");
|
||||||
|
|
||||||
|
try { MelonPreferences.Mapper.RegisterMapper(KeycodeReader, KeycodeWriter); } catch { }
|
||||||
|
try { MelonPreferences.Mapper.RegisterMapper(AnchorReader, AnchorWriter); } catch { }
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void LoadConfig()
|
||||||
|
{
|
||||||
|
foreach (var entry in ConfigManager.ConfigElements)
|
||||||
|
{
|
||||||
|
var key = entry.Key;
|
||||||
|
if (prefCategory.GetEntry(key) is MelonPreferences_Entry)
|
||||||
|
{
|
||||||
|
var config = entry.Value;
|
||||||
|
config.BoxedValue = config.GetLoaderConfigValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void RegisterConfigElement<T>(ConfigElement<T> config)
|
||||||
|
{
|
||||||
|
var entry = prefCategory.CreateEntry(config.Name, config.Value, null, config.IsInternal) as MelonPreferences_Entry<T>;
|
||||||
|
|
||||||
|
entry.OnValueChangedUntyped += () =>
|
||||||
|
{
|
||||||
|
if ((entry.Value == null && config.Value == null) || config.Value.Equals(entry.Value))
|
||||||
|
return;
|
||||||
|
|
||||||
|
config.Value = entry.Value;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void SetConfigValue<T>(ConfigElement<T> config, T value)
|
||||||
|
{
|
||||||
|
if (prefCategory.GetEntry<T>(config.Name) is MelonPreferences_Entry<T> entry)
|
||||||
|
{
|
||||||
|
entry.Value = value;
|
||||||
|
entry.Save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override T GetConfigValue<T>(ConfigElement<T> config)
|
||||||
|
{
|
||||||
|
if (prefCategory.GetEntry<T>(config.Name) is MelonPreferences_Entry<T> entry)
|
||||||
|
return entry.Value;
|
||||||
|
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnAnyConfigChanged()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void SaveConfig()
|
||||||
|
{
|
||||||
|
MelonPreferences.Save();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enum config handlers
|
||||||
|
|
||||||
|
public static KeyCode KeycodeReader(TomlObject value)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
KeyCode kc = (KeyCode)Enum.Parse(typeof(KeyCode), (value as TomlString).Value);
|
||||||
|
|
||||||
|
if (kc == default)
|
||||||
|
throw new Exception();
|
||||||
|
|
||||||
|
return kc;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return KeyCode.F7;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TomlObject KeycodeWriter(KeyCode value)
|
||||||
|
{
|
||||||
|
return MelonPreferences.Mapper.ToToml(value.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UI.UIManager.VerticalAnchor AnchorReader(TomlObject value)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return (UI.UIManager.VerticalAnchor)Enum.Parse(typeof(UI.UIManager.VerticalAnchor), (value as TomlString).Value);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return UI.UIManager.VerticalAnchor.Top;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TomlObject AnchorWriter(UI.UIManager.VerticalAnchor anchor)
|
||||||
|
{
|
||||||
|
return MelonPreferences.Mapper.ToToml(anchor.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -76,8 +76,6 @@ namespace UnityExplorer
|
|||||||
}
|
}
|
||||||
private static string s_explorerFolder;
|
private static string s_explorerFolder;
|
||||||
|
|
||||||
public string ConfigFolder => ExplorerFolder;
|
|
||||||
|
|
||||||
Action<object> IExplorerLoader.OnLogMessage => (object log) => { OnLog?.Invoke(log?.ToString() ?? "", LogType.Log); };
|
Action<object> IExplorerLoader.OnLogMessage => (object log) => { OnLog?.Invoke(log?.ToString() ?? "", LogType.Log); };
|
||||||
Action<object> IExplorerLoader.OnLogWarning => (object log) => { OnLog?.Invoke(log?.ToString() ?? "", LogType.Warning); };
|
Action<object> IExplorerLoader.OnLogWarning => (object log) => { OnLog?.Invoke(log?.ToString() ?? "", LogType.Warning); };
|
||||||
Action<object> IExplorerLoader.OnLogError => (object log) => { OnLog?.Invoke(log?.ToString() ?? "", LogType.Error); };
|
Action<object> IExplorerLoader.OnLogError => (object log) => { OnLog?.Invoke(log?.ToString() ?? "", LogType.Error); };
|
||||||
|
@ -13,11 +13,11 @@ namespace UnityExplorer.Loader.STANDALONE
|
|||||||
public class StandaloneConfigHandler : ConfigHandler
|
public class StandaloneConfigHandler : ConfigHandler
|
||||||
{
|
{
|
||||||
internal static IniDataParser _parser;
|
internal static IniDataParser _parser;
|
||||||
internal static string INI_PATH;
|
internal static string CONFIG_PATH;
|
||||||
|
|
||||||
public override void Init()
|
public override void Init()
|
||||||
{
|
{
|
||||||
INI_PATH = Path.Combine(ExplorerCore.Loader.ConfigFolder, "config.ini");
|
CONFIG_PATH = Path.Combine(ExplorerCore.Loader.ExplorerFolder, "config.ini");
|
||||||
_parser = new IniDataParser();
|
_parser = new IniDataParser();
|
||||||
_parser.Configuration.CommentString = "#";
|
_parser.Configuration.CommentString = "#";
|
||||||
}
|
}
|
||||||
@ -49,10 +49,10 @@ namespace UnityExplorer.Loader.STANDALONE
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (!File.Exists(INI_PATH))
|
if (!File.Exists(CONFIG_PATH))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
string ini = File.ReadAllText(INI_PATH);
|
string ini = File.ReadAllText(CONFIG_PATH);
|
||||||
|
|
||||||
var data = _parser.Parse(ini);
|
var data = _parser.Parse(ini);
|
||||||
|
|
||||||
@ -97,10 +97,10 @@ namespace UnityExplorer.Loader.STANDALONE
|
|||||||
foreach (var entry in ConfigManager.ConfigElements)
|
foreach (var entry in ConfigManager.ConfigElements)
|
||||||
sec.AddKey(entry.Key, entry.Value.BoxedValue.ToString());
|
sec.AddKey(entry.Key, entry.Value.BoxedValue.ToString());
|
||||||
|
|
||||||
if (!Directory.Exists(ExplorerCore.Loader.ConfigFolder))
|
if (!Directory.Exists(ExplorerCore.Loader.ExplorerFolder))
|
||||||
Directory.CreateDirectory(ExplorerCore.Loader.ConfigFolder);
|
Directory.CreateDirectory(ExplorerCore.Loader.ExplorerFolder);
|
||||||
|
|
||||||
File.WriteAllText(INI_PATH, data.ToString());
|
File.WriteAllText(CONFIG_PATH, data.ToString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,15 +4,13 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.UI.Inspectors;
|
using UnityExplorer.UI;
|
||||||
using UnityExplorer.UI.Models;
|
using UnityExplorer.UI.Models;
|
||||||
using UnityExplorer.UI.ObjectPool;
|
|
||||||
using UnityExplorer.UI.Panels;
|
using UnityExplorer.UI.Panels;
|
||||||
using UnityExplorer.UI.Utility;
|
|
||||||
using UnityExplorer.UI.Widgets;
|
using UnityExplorer.UI.Widgets;
|
||||||
using UnityExplorer.UI.Widgets.AutoComplete;
|
using UnityExplorer.UI.Widgets.AutoComplete;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.ObjectExplorer
|
namespace UnityExplorer.ObjectExplorer
|
||||||
{
|
{
|
||||||
public class ObjectSearch : UIModel
|
public class ObjectSearch : UIModel
|
||||||
{
|
{
|
||||||
@ -28,7 +26,7 @@ namespace UnityExplorer.UI.ObjectExplorer
|
|||||||
private ChildFilter m_childFilter = ChildFilter.Any;
|
private ChildFilter m_childFilter = ChildFilter.Any;
|
||||||
private string desiredTypeInput;
|
private string desiredTypeInput;
|
||||||
private string lastCheckedTypeInput;
|
private string lastCheckedTypeInput;
|
||||||
private bool lastTypeCanHaveGO;
|
private bool lastTypeCanHaveGO;
|
||||||
|
|
||||||
public ButtonListHandler<object, ButtonCell> dataHandler;
|
public ButtonListHandler<object, ButtonCell> dataHandler;
|
||||||
|
|
||||||
@ -55,8 +53,8 @@ namespace UnityExplorer.UI.ObjectExplorer
|
|||||||
|
|
||||||
if (m_context == SearchContext.Singleton)
|
if (m_context == SearchContext.Singleton)
|
||||||
currentResults = SearchProvider.SingletonSearch(nameInputField.Text);
|
currentResults = SearchProvider.SingletonSearch(nameInputField.Text);
|
||||||
else if (m_context == SearchContext.StaticClass)
|
else if (m_context == SearchContext.Class)
|
||||||
currentResults = SearchProvider.StaticClassSearch(nameInputField.Text);
|
currentResults = SearchProvider.ClassSearch(nameInputField.Text);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
string compType = "";
|
string compType = "";
|
||||||
@ -79,7 +77,7 @@ namespace UnityExplorer.UI.ObjectExplorer
|
|||||||
lastCheckedTypeInput = desiredTypeInput;
|
lastCheckedTypeInput = desiredTypeInput;
|
||||||
|
|
||||||
//var type = ReflectionUtility.GetTypeByName(desiredTypeInput);
|
//var type = ReflectionUtility.GetTypeByName(desiredTypeInput);
|
||||||
if (ReflectionUtility.AllTypes.TryGetValue(desiredTypeInput, out var cachedType))
|
if (ReflectionUtility.GetTypeByName(desiredTypeInput) is Type cachedType)
|
||||||
{
|
{
|
||||||
var type = cachedType;
|
var type = cachedType;
|
||||||
lastTypeCanHaveGO = typeof(Component).IsAssignableFrom(type) || type == typeof(GameObject);
|
lastTypeCanHaveGO = typeof(Component).IsAssignableFrom(type) || type == typeof(GameObject);
|
||||||
@ -132,8 +130,11 @@ namespace UnityExplorer.UI.ObjectExplorer
|
|||||||
if (!cachedCellTexts.ContainsKey(index))
|
if (!cachedCellTexts.ContainsKey(index))
|
||||||
{
|
{
|
||||||
string text;
|
string text;
|
||||||
if (m_context == SearchContext.StaticClass)
|
if (m_context == SearchContext.Class)
|
||||||
text = SignatureHighlighter.Parse(currentResults[index] as Type, true);
|
{
|
||||||
|
var type = currentResults[index] as Type;
|
||||||
|
text = $"{SignatureHighlighter.Parse(type, true)} <color=grey><i>({type.Assembly.GetName().Name})</i></color>";
|
||||||
|
}
|
||||||
else
|
else
|
||||||
text = ToStringUtility.ToStringWithType(currentResults[index], currentResults[index]?.GetActualType());
|
text = ToStringUtility.ToStringWithType(currentResults[index], currentResults[index]?.GetActualType());
|
||||||
|
|
||||||
@ -145,7 +146,7 @@ namespace UnityExplorer.UI.ObjectExplorer
|
|||||||
|
|
||||||
private void OnCellClicked(int dataIndex)
|
private void OnCellClicked(int dataIndex)
|
||||||
{
|
{
|
||||||
if (m_context == SearchContext.StaticClass)
|
if (m_context == SearchContext.Class)
|
||||||
InspectorManager.Inspect(currentResults[dataIndex] as Type);
|
InspectorManager.Inspect(currentResults[dataIndex] as Type);
|
||||||
else
|
else
|
||||||
InspectorManager.Inspect(currentResults[dataIndex]);
|
InspectorManager.Inspect(currentResults[dataIndex]);
|
||||||
@ -244,7 +245,7 @@ namespace UnityExplorer.UI.ObjectExplorer
|
|||||||
// RESULTS SCROLL POOL
|
// RESULTS SCROLL POOL
|
||||||
|
|
||||||
dataHandler = new ButtonListHandler<object, ButtonCell>(resultsScrollPool, GetEntries, SetCell, ShouldDisplayCell, OnCellClicked);
|
dataHandler = new ButtonListHandler<object, ButtonCell>(resultsScrollPool, GetEntries, SetCell, ShouldDisplayCell, OnCellClicked);
|
||||||
resultsScrollPool = UIFactory.CreateScrollPool<ButtonCell>(uiRoot, "ResultsList", out GameObject scrollObj,
|
resultsScrollPool = UIFactory.CreateScrollPool<ButtonCell>(uiRoot, "ResultsList", out GameObject scrollObj,
|
||||||
out GameObject scrollContent);
|
out GameObject scrollContent);
|
||||||
|
|
||||||
resultsScrollPool.Initialize(dataHandler);
|
resultsScrollPool.Initialize(dataHandler);
|
@ -8,11 +8,12 @@ using UnityEngine;
|
|||||||
using UnityEngine.SceneManagement;
|
using UnityEngine.SceneManagement;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.Core;
|
using UnityExplorer.Core;
|
||||||
|
using UnityExplorer.UI;
|
||||||
using UnityExplorer.UI.Models;
|
using UnityExplorer.UI.Models;
|
||||||
using UnityExplorer.UI.Panels;
|
using UnityExplorer.UI.Panels;
|
||||||
using UnityExplorer.UI.Widgets;
|
using UnityExplorer.UI.Widgets;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.ObjectExplorer
|
namespace UnityExplorer.ObjectExplorer
|
||||||
{
|
{
|
||||||
public class SceneExplorer : UIModel
|
public class SceneExplorer : UIModel
|
||||||
{
|
{
|
||||||
@ -39,7 +40,7 @@ namespace UnityExplorer.UI.ObjectExplorer
|
|||||||
|
|
||||||
private GameObject refreshRow;
|
private GameObject refreshRow;
|
||||||
private Dropdown sceneDropdown;
|
private Dropdown sceneDropdown;
|
||||||
private readonly Dictionary<int, Dropdown.OptionData> sceneToDropdownOption = new Dictionary<int, Dropdown.OptionData>();
|
private readonly Dictionary<Scene, Dropdown.OptionData> sceneToDropdownOption = new Dictionary<Scene, Dropdown.OptionData>();
|
||||||
|
|
||||||
private IEnumerable<GameObject> GetRootEntries() => SceneHandler.CurrentRootObjects;
|
private IEnumerable<GameObject> GetRootEntries() => SceneHandler.CurrentRootObjects;
|
||||||
|
|
||||||
@ -58,6 +59,26 @@ namespace UnityExplorer.UI.ObjectExplorer
|
|||||||
Tree.RefreshData(true);
|
Tree.RefreshData(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void JumpToTransform(Transform transform)
|
||||||
|
{
|
||||||
|
if (!transform)
|
||||||
|
return;
|
||||||
|
|
||||||
|
UIManager.SetPanelActive(this.Parent, true);
|
||||||
|
this.Parent.SetTab(0);
|
||||||
|
|
||||||
|
// select the transform's scene
|
||||||
|
var go = transform.gameObject;
|
||||||
|
if (SceneHandler.SelectedScene != go.scene)
|
||||||
|
{
|
||||||
|
int idx = sceneDropdown.options.IndexOf(sceneToDropdownOption[go.scene]);
|
||||||
|
sceneDropdown.value = idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Let the TransformTree handle the rest
|
||||||
|
Tree.JumpAndExpandToTransform(transform);
|
||||||
|
}
|
||||||
|
|
||||||
private void OnDropdownChanged(int value)
|
private void OnDropdownChanged(int value)
|
||||||
{
|
{
|
||||||
if (value < 0 || SceneHandler.LoadedScenes.Count <= value)
|
if (value < 0 || SceneHandler.LoadedScenes.Count <= value)
|
||||||
@ -71,12 +92,12 @@ namespace UnityExplorer.UI.ObjectExplorer
|
|||||||
|
|
||||||
private void SceneHandler_OnInspectedSceneChanged(Scene scene)
|
private void SceneHandler_OnInspectedSceneChanged(Scene scene)
|
||||||
{
|
{
|
||||||
if (!sceneToDropdownOption.ContainsKey(scene.handle))
|
if (!sceneToDropdownOption.ContainsKey(scene))
|
||||||
PopulateSceneDropdown();
|
PopulateSceneDropdown();
|
||||||
|
|
||||||
if (sceneToDropdownOption.ContainsKey(scene.handle))
|
if (sceneToDropdownOption.ContainsKey(scene))
|
||||||
{
|
{
|
||||||
var opt = sceneToDropdownOption[scene.handle];
|
var opt = sceneToDropdownOption[scene];
|
||||||
int idx = sceneDropdown.options.IndexOf(opt);
|
int idx = sceneDropdown.options.IndexOf(opt);
|
||||||
if (sceneDropdown.value != idx)
|
if (sceneDropdown.value != idx)
|
||||||
sceneDropdown.value = idx;
|
sceneDropdown.value = idx;
|
||||||
@ -114,7 +135,7 @@ namespace UnityExplorer.UI.ObjectExplorer
|
|||||||
|
|
||||||
var option = new Dropdown.OptionData(name);
|
var option = new Dropdown.OptionData(name);
|
||||||
sceneDropdown.options.Add(option);
|
sceneDropdown.options.Add(option);
|
||||||
sceneToDropdownOption.Add(scene.handle, option);
|
sceneToDropdownOption.Add(scene, option);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,7 +143,7 @@ namespace UnityExplorer.UI.ObjectExplorer
|
|||||||
{
|
{
|
||||||
if ((!string.IsNullOrEmpty(input) && !Tree.Filtering) || (string.IsNullOrEmpty(input) && Tree.Filtering))
|
if ((!string.IsNullOrEmpty(input) && !Tree.Filtering) || (string.IsNullOrEmpty(input) && Tree.Filtering))
|
||||||
{
|
{
|
||||||
Tree.displayedObjects.Clear();
|
Tree.cachedTransforms.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
Tree.CurrentFilter = input;
|
Tree.CurrentFilter = input;
|
||||||
@ -181,7 +202,7 @@ namespace UnityExplorer.UI.ObjectExplorer
|
|||||||
//Filter input field
|
//Filter input field
|
||||||
var inputField = UIFactory.CreateInputField(filterRow, "FilterInput", "Search...");
|
var inputField = UIFactory.CreateInputField(filterRow, "FilterInput", "Search...");
|
||||||
inputField.Component.targetGraphic.color = new Color(0.2f, 0.2f, 0.2f);
|
inputField.Component.targetGraphic.color = new Color(0.2f, 0.2f, 0.2f);
|
||||||
RuntimeProvider.Instance.SetColorBlock(inputField.Component, new Color(0.4f, 0.4f, 0.4f), new Color(0.2f, 0.2f, 0.2f),
|
RuntimeProvider.Instance.SetColorBlock(inputField.Component, new Color(0.4f, 0.4f, 0.4f), new Color(0.2f, 0.2f, 0.2f),
|
||||||
new Color(0.08f, 0.08f, 0.08f));
|
new Color(0.08f, 0.08f, 0.08f));
|
||||||
UIFactory.SetLayoutElement(inputField.UIRoot, minHeight: 25);
|
UIFactory.SetLayoutElement(inputField.UIRoot, minHeight: 25);
|
||||||
inputField.OnValueChanged += OnFilterInput;
|
inputField.OnValueChanged += OnFilterInput;
|
@ -6,25 +6,25 @@ using System.Text;
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.SceneManagement;
|
using UnityEngine.SceneManagement;
|
||||||
|
|
||||||
namespace UnityExplorer.Core
|
namespace UnityExplorer.ObjectExplorer
|
||||||
{
|
{
|
||||||
public static class SceneHandler
|
public static class SceneHandler
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The currently inspected Scene.
|
/// The currently inspected Scene.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static Scene? SelectedScene
|
public static Scene? SelectedScene
|
||||||
{
|
{
|
||||||
get => m_selectedScene;
|
get => selectedScene;
|
||||||
internal set
|
internal set
|
||||||
{
|
{
|
||||||
if (m_selectedScene != null && m_selectedScene?.handle == value?.handle)
|
if (selectedScene != null && selectedScene == value)
|
||||||
return;
|
return;
|
||||||
m_selectedScene = value;
|
selectedScene = value;
|
||||||
OnInspectedSceneChanged?.Invoke((Scene)m_selectedScene);
|
OnInspectedSceneChanged?.Invoke((Scene)selectedScene);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private static Scene? m_selectedScene;
|
private static Scene? selectedScene;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The GameObjects in the currently inspected scene.
|
/// The GameObjects in the currently inspected scene.
|
||||||
@ -37,6 +37,7 @@ namespace UnityExplorer.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static ReadOnlyCollection<Scene> LoadedScenes => new ReadOnlyCollection<Scene>(allLoadedScenes);
|
public static ReadOnlyCollection<Scene> LoadedScenes => new ReadOnlyCollection<Scene>(allLoadedScenes);
|
||||||
private static readonly List<Scene> allLoadedScenes = new List<Scene>();
|
private static readonly List<Scene> allLoadedScenes = new List<Scene>();
|
||||||
|
private static HashSet<Scene> previousLoadedScenes;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The names of all scenes in the build settings, if they could be retrieved.
|
/// The names of all scenes in the build settings, if they could be retrieved.
|
||||||
@ -61,7 +62,7 @@ namespace UnityExplorer.Core
|
|||||||
public static event Action<ReadOnlyCollection<Scene>> OnLoadedScenesChanged;
|
public static event Action<ReadOnlyCollection<Scene>> OnLoadedScenesChanged;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Equivalent to <see cref="SceneManager.sceneCount"/> + 2, to include 'DontDestroyOnLoad'.
|
/// Equivalent to <see cref="SceneManager.sceneCount"/> + 2, to include 'DontDestroyOnLoad' and the 'None' scene.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static int LoadedSceneCount => SceneManager.sceneCount + 2;
|
public static int LoadedSceneCount => SceneManager.sceneCount + 2;
|
||||||
|
|
||||||
@ -82,25 +83,7 @@ namespace UnityExplorer.Core
|
|||||||
}
|
}
|
||||||
private static GameObject dontDestroyObject;
|
private static GameObject dontDestroyObject;
|
||||||
|
|
||||||
public static bool InspectingAssetScene => SelectedScene == AssetScene;
|
public static bool InspectingAssetScene => SelectedScene.HasValue && SelectedScene.Value == default;
|
||||||
|
|
||||||
internal static Scene AssetScene => AssetObject.scene;
|
|
||||||
internal static int AssetHandle => AssetScene.handle;
|
|
||||||
|
|
||||||
internal static GameObject AssetObject
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (!assetObject)
|
|
||||||
{
|
|
||||||
assetObject = RuntimeProvider.Instance.FindObjectsOfTypeAll(typeof(GameObject))
|
|
||||||
.First(it => !it.TryCast<GameObject>().scene.IsValid())
|
|
||||||
.TryCast<GameObject>();
|
|
||||||
}
|
|
||||||
return assetObject;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private static GameObject assetObject;
|
|
||||||
|
|
||||||
internal static void Init()
|
internal static void Init()
|
||||||
{
|
{
|
||||||
@ -110,7 +93,7 @@ namespace UnityExplorer.Core
|
|||||||
Type sceneUtil = ReflectionUtility.GetTypeByName("UnityEngine.SceneManagement.SceneUtility");
|
Type sceneUtil = ReflectionUtility.GetTypeByName("UnityEngine.SceneManagement.SceneUtility");
|
||||||
if (sceneUtil == null)
|
if (sceneUtil == null)
|
||||||
throw new Exception("This version of Unity does not ship with the 'SceneUtility' class, or it was not unstripped.");
|
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);
|
var method = sceneUtil.GetMethod("GetScenePathByBuildIndex", ReflectionUtility.FLAGS);
|
||||||
int sceneCount = SceneManager.sceneCountInBuildSettings;
|
int sceneCount = SceneManager.sceneCountInBuildSettings;
|
||||||
for (int i = 0; i < sceneCount; i++)
|
for (int i = 0; i < sceneCount; i++)
|
||||||
@ -122,46 +105,40 @@ namespace UnityExplorer.Core
|
|||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
gotAllScenesInBuild = false;
|
gotAllScenesInBuild = false;
|
||||||
ExplorerCore.Log($"Unable to generate list of all Scenes in the build: {ex}");
|
ExplorerCore.LogWarning($"Unable to generate list of all Scenes in the build: {ex}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void Update()
|
internal static void Update()
|
||||||
{
|
{
|
||||||
int curHandle = SelectedScene?.handle ?? -1;
|
// check if the loaded scenes changed. always confirm DontDestroy / HideAndDontSave
|
||||||
// DontDestroyOnLoad always exists, so default to true if our curHandle is that handle.
|
int confirmedCount = 2;
|
||||||
// otherwise we will check while iterating.
|
bool inspectedExists = SelectedScene == DontDestroyScene || (SelectedScene.HasValue && SelectedScene.Value == default);
|
||||||
bool inspectedExists = curHandle == DontDestroyHandle || curHandle == AssetHandle;
|
|
||||||
|
|
||||||
// Quick sanity check if the loaded scenes changed
|
|
||||||
bool anyChange = LoadedSceneCount != allLoadedScenes.Count;
|
|
||||||
// otherwise keep a lookup table of the previous handles to check if the list changed at all.
|
|
||||||
HashSet<int> previousHandles = null;
|
|
||||||
if (!anyChange)
|
|
||||||
previousHandles = new HashSet<int>(allLoadedScenes.Select(it => it.handle));
|
|
||||||
|
|
||||||
allLoadedScenes.Clear();
|
allLoadedScenes.Clear();
|
||||||
|
|
||||||
for (int i = 0; i < SceneManager.sceneCount; i++)
|
for (int i = 0; i < SceneManager.sceneCount; i++)
|
||||||
{
|
{
|
||||||
Scene scene = SceneManager.GetSceneAt(i);
|
Scene scene = SceneManager.GetSceneAt(i);
|
||||||
if (scene == default || scene.handle == -1 || !scene.isLoaded)
|
if (scene == default || !scene.isLoaded)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// If no changes yet, ensure the previous list contained this handle.
|
// If no changes yet, ensure the previous list contained the scene
|
||||||
if (!anyChange && !previousHandles.Contains(scene.handle))
|
if (previousLoadedScenes != null && previousLoadedScenes.Contains(scene))
|
||||||
anyChange = true;
|
confirmedCount++;
|
||||||
|
|
||||||
// If we have not yet confirmed inspectedExists, check if this scene is our currently inspected one.
|
// If we have not yet confirmed inspectedExists, check if this scene is our currently inspected one.
|
||||||
if (curHandle != -1 && !inspectedExists && scene.handle == curHandle)
|
if (!inspectedExists && scene == SelectedScene)
|
||||||
inspectedExists = true;
|
inspectedExists = true;
|
||||||
|
|
||||||
allLoadedScenes.Add(scene);
|
allLoadedScenes.Add(scene);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Always add the DontDestroyOnLoad scene and the "none" scene.
|
bool anyChange = confirmedCount != allLoadedScenes.Count;
|
||||||
|
|
||||||
allLoadedScenes.Add(DontDestroyScene);
|
allLoadedScenes.Add(DontDestroyScene);
|
||||||
allLoadedScenes.Add(AssetScene);
|
allLoadedScenes.Add(default);
|
||||||
|
previousLoadedScenes = new HashSet<Scene>(allLoadedScenes);
|
||||||
|
|
||||||
// Default to first scene if none selected or previous selection no longer exists.
|
// Default to first scene if none selected or previous selection no longer exists.
|
||||||
if (!inspectedExists)
|
if (!inspectedExists)
|
||||||
@ -181,14 +158,14 @@ namespace UnityExplorer.Core
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
var allObjects = RuntimeProvider.Instance.FindObjectsOfTypeAll(typeof(GameObject));
|
var allObjects = RuntimeProvider.Instance.FindObjectsOfTypeAll(typeof(GameObject));
|
||||||
var list = new List<GameObject>();
|
var objects = new List<GameObject>();
|
||||||
foreach (var obj in allObjects)
|
foreach (var obj in allObjects)
|
||||||
{
|
{
|
||||||
var go = obj.TryCast<GameObject>();
|
var go = obj.TryCast<GameObject>();
|
||||||
if (go.transform.parent == null && !go.scene.IsValid())
|
if (go.transform.parent == null && !go.scene.IsValid())
|
||||||
list.Add(go);
|
objects.Add(go);
|
||||||
}
|
}
|
||||||
rootObjects = list.ToArray();
|
rootObjects = objects.ToArray();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -8,14 +8,13 @@ using UnityEngine.SceneManagement;
|
|||||||
using UnityExplorer.Core;
|
using UnityExplorer.Core;
|
||||||
using UnityExplorer.Core.Runtime;
|
using UnityExplorer.Core.Runtime;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.ObjectExplorer
|
namespace UnityExplorer.ObjectExplorer
|
||||||
{
|
{
|
||||||
public enum SearchContext
|
public enum SearchContext
|
||||||
{
|
{
|
||||||
UnityObject,
|
UnityObject,
|
||||||
// GameObject,
|
|
||||||
Singleton,
|
Singleton,
|
||||||
StaticClass
|
Class
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum ChildFilter
|
public enum ChildFilter
|
||||||
@ -35,7 +34,7 @@ namespace UnityExplorer.UI.ObjectExplorer
|
|||||||
|
|
||||||
public static class SearchProvider
|
public static class SearchProvider
|
||||||
{
|
{
|
||||||
|
|
||||||
private static bool Filter(Scene scene, SceneFilter filter)
|
private static bool Filter(Scene scene, SceneFilter filter)
|
||||||
{
|
{
|
||||||
switch (filter)
|
switch (filter)
|
||||||
@ -45,52 +44,35 @@ namespace UnityExplorer.UI.ObjectExplorer
|
|||||||
case SceneFilter.DontDestroyOnLoad:
|
case SceneFilter.DontDestroyOnLoad:
|
||||||
return scene == SceneHandler.DontDestroyScene;
|
return scene == SceneHandler.DontDestroyScene;
|
||||||
case SceneFilter.HideAndDontSave:
|
case SceneFilter.HideAndDontSave:
|
||||||
return scene == SceneHandler.AssetScene;
|
return scene == default;
|
||||||
case SceneFilter.ActivelyLoaded:
|
case SceneFilter.ActivelyLoaded:
|
||||||
return scene != SceneHandler.DontDestroyScene && scene != SceneHandler.AssetScene;
|
return scene != SceneHandler.DontDestroyScene && scene != default;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static List<object> UnityObjectSearch(string input, string customTypeInput, SearchContext context,
|
internal static List<object> UnityObjectSearch(string input, string customTypeInput, SearchContext context,
|
||||||
ChildFilter childFilter, SceneFilter sceneFilter)
|
ChildFilter childFilter, SceneFilter sceneFilter)
|
||||||
{
|
{
|
||||||
var results = new List<object>();
|
var results = new List<object>();
|
||||||
|
|
||||||
Type searchType;
|
Type searchType = null;
|
||||||
switch (context)
|
if (!string.IsNullOrEmpty(customTypeInput))
|
||||||
{
|
{
|
||||||
//case SearchContext.GameObject:
|
if (ReflectionUtility.GetTypeByName(customTypeInput) is Type customType)
|
||||||
// searchType = typeof(GameObject);
|
{
|
||||||
// break;
|
if (typeof(UnityEngine.Object).IsAssignableFrom(customType))
|
||||||
|
searchType = customType;
|
||||||
case SearchContext.UnityObject:
|
else
|
||||||
default:
|
ExplorerCore.LogWarning($"Custom type '{customType.FullName}' is not assignable from UnityEngine.Object!");
|
||||||
|
}
|
||||||
if (!string.IsNullOrEmpty(customTypeInput))
|
else
|
||||||
{
|
ExplorerCore.LogWarning($"Could not find any type by name '{customTypeInput}'!");
|
||||||
if (ReflectionUtility.GetTypeByName(customTypeInput) is Type customType)
|
|
||||||
{
|
|
||||||
if (typeof(UnityEngine.Object).IsAssignableFrom(customType))
|
|
||||||
{
|
|
||||||
searchType = customType;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ExplorerCore.LogWarning($"Custom type '{customType.FullName}' is not assignable from UnityEngine.Object!");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ExplorerCore.LogWarning($"Could not find any type by name '{customTypeInput}'!");
|
|
||||||
}
|
|
||||||
|
|
||||||
searchType = typeof(UnityEngine.Object);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (searchType == null)
|
if (searchType == null)
|
||||||
return results;
|
searchType = typeof(UnityEngine.Object);
|
||||||
|
|
||||||
var allObjects = RuntimeProvider.Instance.FindObjectsOfTypeAll(searchType);
|
var allObjects = RuntimeProvider.Instance.FindObjectsOfTypeAll(searchType);
|
||||||
|
|
||||||
@ -100,7 +82,7 @@ namespace UnityExplorer.UI.ObjectExplorer
|
|||||||
if (!string.IsNullOrEmpty(input))
|
if (!string.IsNullOrEmpty(input))
|
||||||
nameFilter = input;
|
nameFilter = input;
|
||||||
|
|
||||||
bool canGetGameObject = searchType == typeof(GameObject) || typeof(Component).IsAssignableFrom(searchType);
|
bool shouldFilterGOs = searchType == typeof(GameObject) || typeof(Component).IsAssignableFrom(searchType);
|
||||||
|
|
||||||
foreach (var obj in allObjects)
|
foreach (var obj in allObjects)
|
||||||
{
|
{
|
||||||
@ -108,13 +90,21 @@ namespace UnityExplorer.UI.ObjectExplorer
|
|||||||
if (!string.IsNullOrEmpty(nameFilter) && !obj.name.ContainsIgnoreCase(nameFilter))
|
if (!string.IsNullOrEmpty(nameFilter) && !obj.name.ContainsIgnoreCase(nameFilter))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (canGetGameObject)
|
GameObject go = null;
|
||||||
{
|
var type = obj.GetActualType();
|
||||||
var go = searchType == typeof(GameObject)
|
|
||||||
? obj.TryCast<GameObject>()
|
|
||||||
: obj.TryCast<Component>().gameObject;
|
|
||||||
|
|
||||||
if (go)
|
if (type == typeof(GameObject))
|
||||||
|
go = obj.TryCast<GameObject>();
|
||||||
|
else if (typeof(Component).IsAssignableFrom(type))
|
||||||
|
go = obj.TryCast<Component>()?.gameObject;
|
||||||
|
|
||||||
|
if (go)
|
||||||
|
{
|
||||||
|
// hide unityexplorer objects
|
||||||
|
if (go.transform.root.name == "ExplorerCanvas")
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (shouldFilterGOs)
|
||||||
{
|
{
|
||||||
// scene check
|
// scene check
|
||||||
if (sceneFilter != SceneFilter.Any)
|
if (sceneFilter != SceneFilter.Any)
|
||||||
@ -143,7 +133,7 @@ namespace UnityExplorer.UI.ObjectExplorer
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static List<object> StaticClassSearch(string input)
|
internal static List<object> ClassSearch(string input)
|
||||||
{
|
{
|
||||||
var list = new List<object>();
|
var list = new List<object>();
|
||||||
|
|
||||||
@ -153,11 +143,10 @@ namespace UnityExplorer.UI.ObjectExplorer
|
|||||||
|
|
||||||
foreach (var asm in AppDomain.CurrentDomain.GetAssemblies())
|
foreach (var asm in AppDomain.CurrentDomain.GetAssemblies())
|
||||||
{
|
{
|
||||||
foreach (var type in asm.TryGetTypes().Where(it => it.IsSealed && it.IsAbstract))
|
foreach (var type in asm.TryGetTypes())
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(nameFilter) && !type.FullName.ContainsIgnoreCase(nameFilter))
|
if (!string.IsNullOrEmpty(nameFilter) && !type.FullName.ContainsIgnoreCase(nameFilter))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
list.Add(type);
|
list.Add(type);
|
||||||
}
|
}
|
||||||
}
|
}
|
Binary file not shown.
@ -16,8 +16,11 @@ namespace UnityExplorer.UI
|
|||||||
{
|
{
|
||||||
if (inputsPendingUpdate.Any())
|
if (inputsPendingUpdate.Any())
|
||||||
{
|
{
|
||||||
foreach (var entry in inputsPendingUpdate)
|
var array = inputsPendingUpdate.ToArray();
|
||||||
|
|
||||||
|
for (int i = array.Length - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
|
var entry = array[i];
|
||||||
LayoutRebuilder.MarkLayoutForRebuild(entry.Rect);
|
LayoutRebuilder.MarkLayoutForRebuild(entry.Rect);
|
||||||
entry.OnValueChanged?.Invoke(entry.Component.text);
|
entry.OnValueChanged?.Invoke(entry.Component.text);
|
||||||
}
|
}
|
||||||
@ -26,8 +29,8 @@ namespace UnityExplorer.UI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public InputFieldRef(InputField component)
|
public InputFieldRef(InputField component)
|
||||||
{
|
{
|
||||||
this.Component = component;
|
this.Component = component;
|
||||||
Rect = component.GetComponent<RectTransform>();
|
Rect = component.GetComponent<RectTransform>();
|
||||||
PlaceholderText = component.placeholder.TryCast<Text>();
|
PlaceholderText = component.placeholder.TryCast<Text>();
|
||||||
@ -47,8 +50,8 @@ namespace UnityExplorer.UI
|
|||||||
}
|
}
|
||||||
|
|
||||||
public TextGenerator TextGenerator => Component.cachedInputTextGenerator;
|
public TextGenerator TextGenerator => Component.cachedInputTextGenerator;
|
||||||
public bool ReachedMaxVerts => TextGenerator.vertexCount >= UIManager.MAX_TEXT_VERTS;
|
|
||||||
|
|
||||||
|
public bool ReachedMaxVerts => TextGenerator.vertexCount >= UIManager.MAX_TEXT_VERTS;
|
||||||
|
|
||||||
private void OnInputChanged(string value)
|
private void OnInputChanged(string value)
|
||||||
{
|
{
|
||||||
|
@ -1,19 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace UnityExplorer.UI.ObjectPool
|
|
||||||
{
|
|
||||||
public interface IPooledObject
|
|
||||||
{
|
|
||||||
GameObject UIRoot { get; set; }
|
|
||||||
|
|
||||||
GameObject CreateContent(GameObject parent);
|
|
||||||
|
|
||||||
float DefaultHeight { get; }
|
|
||||||
|
|
||||||
//GameObject CreatePrototype();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
@ -6,8 +7,8 @@ using UnityEngine;
|
|||||||
using UnityEngine.EventSystems;
|
using UnityEngine.EventSystems;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.Core.Config;
|
using UnityExplorer.Core.Config;
|
||||||
using UnityExplorer.UI.CSConsole;
|
using UnityExplorer.CSConsole;
|
||||||
using UnityExplorer.UI.Utility;
|
using UnityExplorer.UI.Widgets;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Panels
|
namespace UnityExplorer.UI.Panels
|
||||||
{
|
{
|
||||||
@ -18,10 +19,11 @@ namespace UnityExplorer.UI.Panels
|
|||||||
public override int MinWidth => 750;
|
public override int MinWidth => 750;
|
||||||
public override int MinHeight => 300;
|
public override int MinHeight => 300;
|
||||||
|
|
||||||
public InputFieldScroller InputScroll { get; private set; }
|
public InputFieldScroller InputScroller { get; private set; }
|
||||||
public InputFieldRef Input => InputScroll.InputField;
|
public InputFieldRef Input => InputScroller.InputField;
|
||||||
public Text InputText { get; private set; }
|
public Text InputText { get; private set; }
|
||||||
public Text HighlightText { get; private set; }
|
public Text HighlightText { get; private set; }
|
||||||
|
public Text LineNumberText { get; private set; }
|
||||||
|
|
||||||
public Dropdown HelpDropdown { get; private set; }
|
public Dropdown HelpDropdown { get; private set; }
|
||||||
|
|
||||||
@ -33,6 +35,7 @@ namespace UnityExplorer.UI.Panels
|
|||||||
public Action<bool> OnCtrlRToggled;
|
public Action<bool> OnCtrlRToggled;
|
||||||
public Action<bool> OnSuggestionsToggled;
|
public Action<bool> OnSuggestionsToggled;
|
||||||
public Action<bool> OnAutoIndentToggled;
|
public Action<bool> OnAutoIndentToggled;
|
||||||
|
public Action OnPanelResized;
|
||||||
|
|
||||||
private void InvokeOnValueChanged(string value)
|
private void InvokeOnValueChanged(string value)
|
||||||
{
|
{
|
||||||
@ -60,6 +63,11 @@ namespace UnityExplorer.UI.Panels
|
|||||||
|
|
||||||
// UI Construction
|
// UI Construction
|
||||||
|
|
||||||
|
public override void OnFinishResize(RectTransform panel)
|
||||||
|
{
|
||||||
|
OnPanelResized?.Invoke();
|
||||||
|
}
|
||||||
|
|
||||||
protected internal override void DoSetDefaultPosAndAnchors()
|
protected internal override void DoSetDefaultPosAndAnchors()
|
||||||
{
|
{
|
||||||
Rect.localPosition = Vector2.zero;
|
Rect.localPosition = Vector2.zero;
|
||||||
@ -121,19 +129,53 @@ namespace UnityExplorer.UI.Panels
|
|||||||
|
|
||||||
// Console Input
|
// Console Input
|
||||||
|
|
||||||
|
var inputArea = UIFactory.CreateUIObject("InputGroup", content);
|
||||||
|
UIFactory.SetLayoutElement(inputArea, flexibleWidth: 9999, flexibleHeight: 9999);
|
||||||
|
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(inputArea, false, true, true, true);
|
||||||
|
inputArea.AddComponent<Image>().color = Color.white;
|
||||||
|
inputArea.AddComponent<Mask>().showMaskGraphic = false;
|
||||||
|
|
||||||
|
// line numbers
|
||||||
|
|
||||||
|
var linesHolder = UIFactory.CreateUIObject("LinesHolder", inputArea);
|
||||||
|
var linesRect = linesHolder.GetComponent<RectTransform>();
|
||||||
|
linesRect.pivot = new Vector2(0, 1);
|
||||||
|
linesRect.anchorMin = new Vector2(0, 0);
|
||||||
|
linesRect.anchorMax = new Vector2(0, 1);
|
||||||
|
linesRect.sizeDelta = new Vector2(0, 305000);
|
||||||
|
linesRect.SetInsetAndSizeFromParentEdge(RectTransform.Edge.Left, 0, 50);
|
||||||
|
linesHolder.AddComponent<Image>().color = new Color(0.05f, 0.05f, 0.05f);
|
||||||
|
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(linesHolder, true, true, true, true);
|
||||||
|
|
||||||
|
LineNumberText = UIFactory.CreateLabel(linesHolder, "LineNumbers", "1", TextAnchor.UpperCenter, Color.grey, fontSize: 16);
|
||||||
|
LineNumberText.font = UIManager.ConsoleFont;
|
||||||
|
|
||||||
|
// input field
|
||||||
|
|
||||||
int fontSize = 16;
|
int fontSize = 16;
|
||||||
|
|
||||||
var inputObj = UIFactory.CreateScrollInputField(this.content, "ConsoleInput", ConsoleController.STARTUP_TEXT, out var inputScroller, fontSize);
|
var inputObj = UIFactory.CreateScrollInputField(inputArea, "ConsoleInput", ConsoleController.STARTUP_TEXT,
|
||||||
InputScroll = inputScroller;
|
out var inputScroller, fontSize);
|
||||||
|
InputScroller = inputScroller;
|
||||||
ConsoleController.defaultInputFieldAlpha = Input.Component.selectionColor.a;
|
ConsoleController.defaultInputFieldAlpha = Input.Component.selectionColor.a;
|
||||||
Input.OnValueChanged += InvokeOnValueChanged;
|
Input.OnValueChanged += InvokeOnValueChanged;
|
||||||
|
|
||||||
|
// move line number text with input field
|
||||||
|
linesRect.transform.SetParent(inputObj.transform.Find("Viewport"), false);
|
||||||
|
inputScroller.Slider.Scrollbar.onValueChanged.AddListener((float val) => { SetLinesPosition(); });
|
||||||
|
inputScroller.Slider.Slider.onValueChanged.AddListener((float val) => { SetLinesPosition(); });
|
||||||
|
void SetLinesPosition()
|
||||||
|
{
|
||||||
|
linesRect.anchoredPosition = new Vector2(linesRect.anchoredPosition.x, inputScroller.ContentRect.anchoredPosition.y);
|
||||||
|
//SetInputLayout();
|
||||||
|
}
|
||||||
|
|
||||||
InputText = Input.Component.textComponent;
|
InputText = Input.Component.textComponent;
|
||||||
InputText.supportRichText = false;
|
InputText.supportRichText = false;
|
||||||
Input.PlaceholderText.fontSize = fontSize;
|
|
||||||
InputText.color = Color.clear;
|
InputText.color = Color.clear;
|
||||||
Input.Component.customCaretColor = true;
|
Input.Component.customCaretColor = true;
|
||||||
Input.Component.caretColor = Color.white;
|
Input.Component.caretColor = Color.white;
|
||||||
|
Input.PlaceholderText.fontSize = fontSize;
|
||||||
|
|
||||||
// Lexer highlight text overlay
|
// Lexer highlight text overlay
|
||||||
var highlightTextObj = UIFactory.CreateUIObject("HighlightText", InputText.gameObject);
|
var highlightTextObj = UIFactory.CreateUIObject("HighlightText", InputText.gameObject);
|
||||||
@ -154,7 +196,19 @@ namespace UnityExplorer.UI.Panels
|
|||||||
Input.PlaceholderText.font = UIManager.ConsoleFont;
|
Input.PlaceholderText.font = UIManager.ConsoleFont;
|
||||||
HighlightText.font = UIManager.ConsoleFont;
|
HighlightText.font = UIManager.ConsoleFont;
|
||||||
|
|
||||||
|
RuntimeProvider.Instance.StartCoroutine(DelayedLayoutSetup());
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerator DelayedLayoutSetup()
|
||||||
|
{
|
||||||
|
yield return null;
|
||||||
|
SetInputLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetInputLayout()
|
||||||
|
{
|
||||||
|
Input.Rect.offsetMin = new Vector2(52, Input.Rect.offsetMin.y);
|
||||||
|
Input.Rect.offsetMax = new Vector2(2, Input.Rect.offsetMax.y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ using System.Text;
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.Core.Config;
|
using UnityExplorer.Core.Config;
|
||||||
using UnityExplorer.UI.Inspectors;
|
using UnityExplorer.Inspectors;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Panels
|
namespace UnityExplorer.UI.Panels
|
||||||
{
|
{
|
||||||
@ -61,7 +61,7 @@ namespace UnityExplorer.UI.Panels
|
|||||||
{
|
{
|
||||||
// add close all button to titlebar
|
// add close all button to titlebar
|
||||||
|
|
||||||
var closeAllBtn = UIFactory.CreateButton(this.titleBar.transform.Find("CloseHolder").gameObject, "CloseAllBtn", "Close All",
|
var closeAllBtn = UIFactory.CreateButton(this.titleBar.transform.Find("CloseHolder").gameObject, "CloseAllBtn", "Close All",
|
||||||
new Color(0.3f, 0.2f, 0.2f));
|
new Color(0.3f, 0.2f, 0.2f));
|
||||||
UIFactory.SetLayoutElement(closeAllBtn.Component.gameObject, minHeight: 25, minWidth: 80);
|
UIFactory.SetLayoutElement(closeAllBtn.Component.gameObject, minHeight: 25, minWidth: 80);
|
||||||
closeAllBtn.Component.transform.SetSiblingIndex(closeAllBtn.Component.transform.GetSiblingIndex() - 1);
|
closeAllBtn.Component.transform.SetSiblingIndex(closeAllBtn.Component.transform.GetSiblingIndex() - 1);
|
||||||
|
@ -11,8 +11,7 @@ using UnityEngine.UI;
|
|||||||
using UnityExplorer.Core;
|
using UnityExplorer.Core;
|
||||||
using UnityExplorer.Core.Config;
|
using UnityExplorer.Core.Config;
|
||||||
using UnityExplorer.UI.Models;
|
using UnityExplorer.UI.Models;
|
||||||
using UnityExplorer.UI.ObjectExplorer;
|
using UnityExplorer.ObjectExplorer;
|
||||||
using UnityExplorer.UI.Utility;
|
|
||||||
using UnityExplorer.UI.Widgets;
|
using UnityExplorer.UI.Widgets;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Panels
|
namespace UnityExplorer.UI.Panels
|
||||||
|
@ -5,8 +5,8 @@ using System.Text;
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.Core.Config;
|
using UnityExplorer.Core.Config;
|
||||||
using UnityExplorer.UI.CacheObject;
|
using UnityExplorer.CacheObject;
|
||||||
using UnityExplorer.UI.CacheObject.Views;
|
using UnityExplorer.CacheObject.Views;
|
||||||
using UnityExplorer.UI.Widgets;
|
using UnityExplorer.UI.Widgets;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Panels
|
namespace UnityExplorer.UI.Panels
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.Core.Input;
|
using UnityExplorer.Core.Input;
|
||||||
using System.IO;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using UnityExplorer.UI.Models;
|
using UnityExplorer.UI.Models;
|
||||||
using System.Linq;
|
|
||||||
using UnityExplorer.UI.Widgets.AutoComplete;
|
using UnityExplorer.UI.Widgets.AutoComplete;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Panels
|
namespace UnityExplorer.UI.Panels
|
||||||
{
|
{
|
||||||
public class PanelDragger
|
public class PanelDragger
|
||||||
{
|
{
|
||||||
#region Static
|
#region Static
|
||||||
|
|
||||||
@ -23,6 +23,7 @@ namespace UnityExplorer.UI.Panels
|
|||||||
{
|
{
|
||||||
s_resizeCursorObj.SetActive(false);
|
s_resizeCursorObj.SetActive(false);
|
||||||
wasAnyDragging = false;
|
wasAnyDragging = false;
|
||||||
|
Resizing = false;
|
||||||
|
|
||||||
foreach (var instance in Instances)
|
foreach (var instance in Instances)
|
||||||
{
|
{
|
||||||
@ -137,7 +138,7 @@ namespace UnityExplorer.UI.Panels
|
|||||||
Instances.Add(this);
|
Instances.Add(this);
|
||||||
DragableArea = dragArea;
|
DragableArea = dragArea;
|
||||||
Panel = panelToDrag;
|
Panel = panelToDrag;
|
||||||
|
|
||||||
if (!canvasTransform)
|
if (!canvasTransform)
|
||||||
canvasTransform = Panel.GetComponentInParent<Canvas>().GetComponent<RectTransform>();
|
canvasTransform = Panel.GetComponentInParent<Canvas>().GetComponent<RectTransform>();
|
||||||
|
|
||||||
|
@ -8,7 +8,6 @@ using UnityEngine.UI;
|
|||||||
using UnityExplorer.Core.Config;
|
using UnityExplorer.Core.Config;
|
||||||
using UnityExplorer.Core.Input;
|
using UnityExplorer.Core.Input;
|
||||||
using UnityExplorer.UI.Models;
|
using UnityExplorer.UI.Models;
|
||||||
using UnityExplorer.UI.Utility;
|
|
||||||
using UnityExplorer.UI.Widgets;
|
using UnityExplorer.UI.Widgets;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Panels
|
namespace UnityExplorer.UI.Panels
|
||||||
@ -147,22 +146,21 @@ namespace UnityExplorer.UI.Panels
|
|||||||
if (Rect.rect.height < MinHeight)
|
if (Rect.rect.height < MinHeight)
|
||||||
Rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, MinHeight);
|
Rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, MinHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void EnsureValidPosition(RectTransform panel)
|
public static void EnsureValidPosition(RectTransform panel)
|
||||||
{
|
{
|
||||||
var pos = panel.localPosition;
|
var pos = panel.localPosition;
|
||||||
|
|
||||||
// Prevent panel going oustide screen bounds
|
// Prevent panel going oustide screen bounds
|
||||||
var halfW = Screen.width * 0.5f;
|
var halfW = Screen.width * 0.5f;
|
||||||
var halfH = Screen.height * 0.5f;
|
var halfH = Screen.height * 0.5f;
|
||||||
pos.x = Math.Max(-halfW, Math.Min(pos.x, halfW - panel.rect.width));
|
|
||||||
pos.y = Math.Max(-halfH + panel.rect.height, Math.Min(pos.y, halfH));
|
pos.x = Math.Max(-halfW - panel.rect.width + 50, Math.Min(pos.x, halfW - 50));
|
||||||
|
pos.y = Math.Max(-halfH + 50, Math.Min(pos.y, halfH));
|
||||||
|
|
||||||
panel.localPosition = pos;
|
panel.localPosition = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#region Save Data
|
#region Save Data
|
||||||
|
|
||||||
public abstract void DoSaveToConfigElement();
|
public abstract void DoSaveToConfigElement();
|
||||||
@ -226,7 +224,7 @@ namespace UnityExplorer.UI.Panels
|
|||||||
{
|
{
|
||||||
// create navbar button
|
// create navbar button
|
||||||
|
|
||||||
NavButton = UIFactory.CreateButton(UIManager.NavbarButtonHolder, $"Button_{PanelType}", Name);
|
NavButton = UIFactory.CreateButton(UIManager.NavbarTabButtonHolder, $"Button_{PanelType}", Name);
|
||||||
var navBtn = NavButton.Component.gameObject;
|
var navBtn = NavButton.Component.gameObject;
|
||||||
navBtn.AddComponent<ContentSizeFitter>().horizontalFit = ContentSizeFitter.FitMode.PreferredSize;
|
navBtn.AddComponent<ContentSizeFitter>().horizontalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||||||
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(navBtn, false, true, true, true, 0, 0, 0, 5, 5, TextAnchor.MiddleCenter);
|
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(navBtn, false, true, true, true, 0, 0, 0, 5, 5, TextAnchor.MiddleCenter);
|
||||||
|
@ -4,9 +4,16 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.ObjectPool
|
namespace UnityExplorer.UI
|
||||||
{
|
{
|
||||||
// Abstract non-generic class, handles the pool dictionary and interfacing with the generic pools.
|
public interface IPooledObject
|
||||||
|
{
|
||||||
|
GameObject UIRoot { get; set; }
|
||||||
|
float DefaultHeight { get; }
|
||||||
|
|
||||||
|
GameObject CreateContent(GameObject parent);
|
||||||
|
}
|
||||||
|
|
||||||
public abstract class Pool
|
public abstract class Pool
|
||||||
{
|
{
|
||||||
protected static readonly Dictionary<Type, Pool> pools = new Dictionary<Type, Pool>();
|
protected static readonly Dictionary<Type, Pool> pools = new Dictionary<Type, Pool>();
|
||||||
@ -39,7 +46,6 @@ namespace UnityExplorer.UI.ObjectPool
|
|||||||
protected abstract void TryReturn(IPooledObject obj);
|
protected abstract void TryReturn(IPooledObject obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Each generic implementation has its own pool, business logic is here
|
|
||||||
public class Pool<T> : Pool where T : IPooledObject
|
public class Pool<T> : Pool where T : IPooledObject
|
||||||
{
|
{
|
||||||
public static Pool<T> GetPool() => (Pool<T>)GetPool(typeof(T));
|
public static Pool<T> GetPool() => (Pool<T>)GetPool(typeof(T));
|
@ -5,7 +5,6 @@ using UnityEngine.UI;
|
|||||||
using UnityExplorer.Core.Config;
|
using UnityExplorer.Core.Config;
|
||||||
using UnityExplorer.Core.Runtime;
|
using UnityExplorer.Core.Runtime;
|
||||||
using UnityExplorer.UI.Models;
|
using UnityExplorer.UI.Models;
|
||||||
using UnityExplorer.UI.Utility;
|
|
||||||
using UnityExplorer.UI.Widgets;
|
using UnityExplorer.UI.Widgets;
|
||||||
|
|
||||||
namespace UnityExplorer.UI
|
namespace UnityExplorer.UI
|
||||||
@ -410,56 +409,49 @@ namespace UnityExplorer.UI
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a Toggle control.
|
/// Create a Toggle control.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static GameObject CreateToggle(GameObject parent, string name, out Toggle toggle, out Text text, Color bgColor = default)
|
public static GameObject CreateToggle(GameObject parent, string name, out Toggle toggle, out Text text, Color bgColor = default,
|
||||||
|
int checkWidth = 20, int checkHeight = 20)
|
||||||
{
|
{
|
||||||
|
// Main obj
|
||||||
GameObject toggleObj = CreateUIObject(name, parent, _smallElementSize);
|
GameObject toggleObj = CreateUIObject(name, parent, _smallElementSize);
|
||||||
|
SetLayoutGroup<HorizontalLayoutGroup>(toggleObj, false, false, true, true, 5, 0,0,0,0, childAlignment: TextAnchor.MiddleLeft);
|
||||||
GameObject bgObj = CreateUIObject("Background", toggleObj);
|
|
||||||
GameObject checkObj = CreateUIObject("Checkmark", bgObj);
|
|
||||||
GameObject labelObj = CreateUIObject("Label", toggleObj);
|
|
||||||
|
|
||||||
toggle = toggleObj.AddComponent<Toggle>();
|
toggle = toggleObj.AddComponent<Toggle>();
|
||||||
toggle.isOn = true;
|
toggle.isOn = true;
|
||||||
|
SetDefaultSelectableColors(toggle);
|
||||||
// second reference so we can use it inside the lambda, 'toggle' is an out var.
|
// need a second reference so we can use it inside the lambda, since 'toggle' is an out var.
|
||||||
Toggle toggleComp = toggle;
|
Toggle t2 = toggle;
|
||||||
toggle.onValueChanged.AddListener(Deselect);
|
toggle.onValueChanged.AddListener((bool _) => { t2.OnDeselect(null); });
|
||||||
void Deselect(bool _)
|
|
||||||
{
|
|
||||||
toggleComp.OnDeselect(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
Image bgImage = bgObj.AddComponent<Image>();
|
// Check mark background
|
||||||
|
|
||||||
|
GameObject checkBgObj = CreateUIObject("Background", toggleObj);
|
||||||
|
Image bgImage = checkBgObj.AddComponent<Image>();
|
||||||
bgImage.color = bgColor == default ? new Color(0.04f, 0.04f, 0.04f, 0.75f) : bgColor;
|
bgImage.color = bgColor == default ? new Color(0.04f, 0.04f, 0.04f, 0.75f) : bgColor;
|
||||||
|
|
||||||
Image checkImage = checkObj.AddComponent<Image>();
|
SetLayoutGroup<HorizontalLayoutGroup>(checkBgObj, true, true, true, true, 0, 2, 2, 2, 2);
|
||||||
|
SetLayoutElement(checkBgObj, minWidth: checkWidth, flexibleWidth: 0, minHeight: checkHeight, flexibleHeight: 0);
|
||||||
|
|
||||||
|
// Check mark image
|
||||||
|
|
||||||
|
GameObject checkMarkObj = CreateUIObject("Checkmark", checkBgObj);
|
||||||
|
Image checkImage = checkMarkObj.AddComponent<Image>();
|
||||||
checkImage.color = new Color(0.8f, 1, 0.8f, 0.3f);
|
checkImage.color = new Color(0.8f, 1, 0.8f, 0.3f);
|
||||||
|
|
||||||
|
// Label
|
||||||
|
|
||||||
|
GameObject labelObj = CreateUIObject("Label", toggleObj);
|
||||||
text = labelObj.AddComponent<Text>();
|
text = labelObj.AddComponent<Text>();
|
||||||
text.text = "Toggle";
|
text.text = "";
|
||||||
|
text.alignment = TextAnchor.MiddleLeft;
|
||||||
SetDefaultTextValues(text);
|
SetDefaultTextValues(text);
|
||||||
|
|
||||||
|
SetLayoutElement(labelObj, minWidth: 0, flexibleWidth: 0, minHeight: checkHeight, flexibleHeight: 0);
|
||||||
|
|
||||||
|
// References
|
||||||
|
|
||||||
toggle.graphic = checkImage;
|
toggle.graphic = checkImage;
|
||||||
toggle.targetGraphic = bgImage;
|
toggle.targetGraphic = bgImage;
|
||||||
SetDefaultSelectableColors(toggle);
|
|
||||||
|
|
||||||
RectTransform bgRect = bgObj.GetComponent<RectTransform>();
|
|
||||||
bgRect.anchorMin = new Vector2(0f, 1f);
|
|
||||||
bgRect.anchorMax = new Vector2(0f, 1f);
|
|
||||||
bgRect.anchoredPosition = new Vector2(13f, -13f);
|
|
||||||
bgRect.sizeDelta = new Vector2(20f, 20f);
|
|
||||||
|
|
||||||
RectTransform checkRect = checkObj.GetComponent<RectTransform>();
|
|
||||||
checkRect.anchorMin = new Vector2(0.5f, 0.5f);
|
|
||||||
checkRect.anchorMax = new Vector2(0.5f, 0.5f);
|
|
||||||
checkRect.anchoredPosition = Vector2.zero;
|
|
||||||
checkRect.sizeDelta = new Vector2(14f, 14f);
|
|
||||||
|
|
||||||
RectTransform labelRect = labelObj.GetComponent<RectTransform>();
|
|
||||||
labelRect.anchorMin = new Vector2(0f, 0f);
|
|
||||||
labelRect.anchorMax = new Vector2(1f, 1f);
|
|
||||||
labelRect.offsetMin = new Vector2(28f, 2f);
|
|
||||||
labelRect.offsetMax = new Vector2(-5f, -5f);
|
|
||||||
return toggleObj;
|
return toggleObj;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -730,7 +722,7 @@ namespace UnityExplorer.UI
|
|||||||
|
|
||||||
var sliderContainer = CreateVerticalGroup(mainObj, "SliderContainer",
|
var sliderContainer = CreateVerticalGroup(mainObj, "SliderContainer",
|
||||||
false, false, true, true, 0, default, new Color(0.05f, 0.05f, 0.05f));
|
false, false, true, true, 0, default, new Color(0.05f, 0.05f, 0.05f));
|
||||||
SetLayoutElement(sliderContainer, minWidth: 25, flexibleWidth:0, flexibleHeight: 9999);
|
SetLayoutElement(sliderContainer, minWidth: 25, flexibleWidth: 0, flexibleHeight: 9999);
|
||||||
sliderContainer.AddComponent<Mask>();
|
sliderContainer.AddComponent<Mask>();
|
||||||
|
|
||||||
CreateSliderScrollbar(sliderContainer, out Slider slider);
|
CreateSliderScrollbar(sliderContainer, out Slider slider);
|
||||||
@ -838,7 +830,7 @@ namespace UnityExplorer.UI
|
|||||||
content.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
content.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||||||
|
|
||||||
// Slider
|
// Slider
|
||||||
|
|
||||||
GameObject scrollBarObj = CreateUIObject("AutoSliderScrollbar", mainObj);
|
GameObject scrollBarObj = CreateUIObject("AutoSliderScrollbar", mainObj);
|
||||||
var scrollBarRect = scrollBarObj.GetComponent<RectTransform>();
|
var scrollBarRect = scrollBarObj.GetComponent<RectTransform>();
|
||||||
scrollBarRect.anchorMin = new Vector2(1, 0);
|
scrollBarRect.anchorMin = new Vector2(1, 0);
|
||||||
@ -847,22 +839,22 @@ namespace UnityExplorer.UI
|
|||||||
SetLayoutGroup<VerticalLayoutGroup>(scrollBarObj, false, true, true, true);
|
SetLayoutGroup<VerticalLayoutGroup>(scrollBarObj, false, true, true, true);
|
||||||
scrollBarObj.AddComponent<Image>().color = Color.white;
|
scrollBarObj.AddComponent<Image>().color = Color.white;
|
||||||
scrollBarObj.AddComponent<Mask>().showMaskGraphic = false;
|
scrollBarObj.AddComponent<Mask>().showMaskGraphic = false;
|
||||||
|
|
||||||
GameObject hiddenBar = CreateScrollbar(scrollBarObj, "HiddenScrollviewScroller", out var hiddenScrollbar);
|
GameObject hiddenBar = CreateScrollbar(scrollBarObj, "HiddenScrollviewScroller", out var hiddenScrollbar);
|
||||||
hiddenScrollbar.SetDirection(Scrollbar.Direction.BottomToTop, true);
|
hiddenScrollbar.SetDirection(Scrollbar.Direction.BottomToTop, true);
|
||||||
|
|
||||||
for (int i = 0; i < hiddenBar.transform.childCount; i++)
|
for (int i = 0; i < hiddenBar.transform.childCount; i++)
|
||||||
{
|
{
|
||||||
var child = hiddenBar.transform.GetChild(i);
|
var child = hiddenBar.transform.GetChild(i);
|
||||||
child.gameObject.SetActive(false);
|
child.gameObject.SetActive(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
CreateSliderScrollbar(scrollBarObj, out Slider scrollSlider);
|
CreateSliderScrollbar(scrollBarObj, out Slider scrollSlider);
|
||||||
|
|
||||||
autoScrollbar = new AutoSliderScrollbar(hiddenScrollbar, scrollSlider, contentRect, viewportRect);
|
autoScrollbar = new AutoSliderScrollbar(hiddenScrollbar, scrollSlider, contentRect, viewportRect);
|
||||||
|
|
||||||
// Set up the ScrollRect component
|
// Set up the ScrollRect component
|
||||||
|
|
||||||
var scrollRect = mainObj.AddComponent<ScrollRect>();
|
var scrollRect = mainObj.AddComponent<ScrollRect>();
|
||||||
scrollRect.horizontal = false;
|
scrollRect.horizontal = false;
|
||||||
scrollRect.vertical = true;
|
scrollRect.vertical = true;
|
||||||
@ -871,10 +863,10 @@ namespace UnityExplorer.UI
|
|||||||
scrollRect.scrollSensitivity = 35;
|
scrollRect.scrollSensitivity = 35;
|
||||||
scrollRect.horizontalScrollbarVisibility = ScrollRect.ScrollbarVisibility.AutoHideAndExpandViewport;
|
scrollRect.horizontalScrollbarVisibility = ScrollRect.ScrollbarVisibility.AutoHideAndExpandViewport;
|
||||||
scrollRect.verticalScrollbarVisibility = ScrollRect.ScrollbarVisibility.Permanent;
|
scrollRect.verticalScrollbarVisibility = ScrollRect.ScrollbarVisibility.Permanent;
|
||||||
|
|
||||||
scrollRect.viewport = viewportRect;
|
scrollRect.viewport = viewportRect;
|
||||||
scrollRect.content = contentRect;
|
scrollRect.content = contentRect;
|
||||||
|
|
||||||
return mainObj;
|
return mainObj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,11 +8,10 @@ using UnityEngine.EventSystems;
|
|||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.Core.Config;
|
using UnityExplorer.Core.Config;
|
||||||
using UnityExplorer.Core.Input;
|
using UnityExplorer.Core.Input;
|
||||||
using UnityExplorer.UI.CSConsole;
|
using UnityExplorer.CSConsole;
|
||||||
using UnityExplorer.UI.Inspectors;
|
using UnityExplorer.Inspectors;
|
||||||
using UnityExplorer.UI.Models;
|
using UnityExplorer.UI.Models;
|
||||||
using UnityExplorer.UI.Panels;
|
using UnityExplorer.UI.Panels;
|
||||||
using UnityExplorer.UI.Utility;
|
|
||||||
using UnityExplorer.UI.Widgets;
|
using UnityExplorer.UI.Widgets;
|
||||||
using UnityExplorer.UI.Widgets.AutoComplete;
|
using UnityExplorer.UI.Widgets.AutoComplete;
|
||||||
|
|
||||||
@ -56,9 +55,15 @@ namespace UnityExplorer.UI
|
|||||||
internal static Shader BackupShader { get; private set; }
|
internal static Shader BackupShader { get; private set; }
|
||||||
|
|
||||||
public static RectTransform NavBarRect;
|
public static RectTransform NavBarRect;
|
||||||
public static GameObject NavbarButtonHolder;
|
public static GameObject NavbarTabButtonHolder;
|
||||||
public static Dropdown MouseInspectDropdown;
|
public static Dropdown MouseInspectDropdown;
|
||||||
|
|
||||||
|
private static ButtonRef closeBtn;
|
||||||
|
private static ButtonRef pauseBtn;
|
||||||
|
private static InputFieldRef timeInput;
|
||||||
|
private static bool pauseButtonPausing;
|
||||||
|
private static float lastTimeScale;
|
||||||
|
|
||||||
// defaults
|
// defaults
|
||||||
internal static readonly Color enabledButtonColor = new Color(0.2f, 0.4f, 0.28f);
|
internal static readonly Color enabledButtonColor = new Color(0.2f, 0.4f, 0.28f);
|
||||||
internal static readonly Color disabledButtonColor = new Color(0.25f, 0.25f, 0.25f);
|
internal static readonly Color disabledButtonColor = new Color(0.25f, 0.25f, 0.25f);
|
||||||
@ -81,6 +86,105 @@ namespace UnityExplorer.UI
|
|||||||
}
|
}
|
||||||
public static bool s_showMenu = true;
|
public static bool s_showMenu = true;
|
||||||
|
|
||||||
|
// Initialization
|
||||||
|
|
||||||
|
internal static void InitUI()
|
||||||
|
{
|
||||||
|
LoadBundle();
|
||||||
|
|
||||||
|
UIFactory.Init();
|
||||||
|
|
||||||
|
CreateRootCanvas();
|
||||||
|
|
||||||
|
// Global UI Pool Holder
|
||||||
|
PoolHolder = new GameObject("PoolHolder");
|
||||||
|
PoolHolder.transform.parent = CanvasRoot.transform;
|
||||||
|
PoolHolder.SetActive(false);
|
||||||
|
|
||||||
|
CreateTopNavBar();
|
||||||
|
|
||||||
|
UIPanels.Add(Panels.AutoCompleter, new AutoCompleteModal());
|
||||||
|
UIPanels.Add(Panels.ObjectExplorer, new ObjectExplorerPanel());
|
||||||
|
UIPanels.Add(Panels.Inspector, new InspectorPanel());
|
||||||
|
UIPanels.Add(Panels.CSConsole, new CSConsolePanel());
|
||||||
|
UIPanels.Add(Panels.ConsoleLog, new LogPanel());
|
||||||
|
UIPanels.Add(Panels.Options, new OptionsPanel());
|
||||||
|
UIPanels.Add(Panels.MouseInspector, new InspectUnderMouse());
|
||||||
|
|
||||||
|
foreach (var panel in UIPanels.Values)
|
||||||
|
panel.ConstructUI();
|
||||||
|
|
||||||
|
ConsoleController.Init();
|
||||||
|
|
||||||
|
ShowMenu = !ConfigManager.Hide_On_Startup.Value;
|
||||||
|
|
||||||
|
lastScreenWidth = Screen.width;
|
||||||
|
lastScreenHeight = Screen.height;
|
||||||
|
|
||||||
|
Initializing = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Main UI Update loop
|
||||||
|
|
||||||
|
private static int lastScreenWidth;
|
||||||
|
private static int lastScreenHeight;
|
||||||
|
|
||||||
|
public static void Update()
|
||||||
|
{
|
||||||
|
if (!CanvasRoot || Initializing)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// if doing Mouse Inspect, update that and return.
|
||||||
|
if (InspectUnderMouse.Inspecting)
|
||||||
|
{
|
||||||
|
InspectUnderMouse.Instance.UpdateInspect();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check master toggle
|
||||||
|
if (InputManager.GetKeyDown(ConfigManager.Master_Toggle.Value))
|
||||||
|
ShowMenu = !ShowMenu;
|
||||||
|
|
||||||
|
// return if menu closed
|
||||||
|
if (!ShowMenu)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Check forceUnlockMouse toggle
|
||||||
|
if (InputManager.GetKeyDown(ConfigManager.Force_Unlock_Toggle.Value))
|
||||||
|
CursorUnlocker.Unlock = !CursorUnlocker.Unlock;
|
||||||
|
|
||||||
|
// check event system state
|
||||||
|
if (!ConfigManager.Disable_EventSystem_Override.Value && EventSystem.current != EventSys)
|
||||||
|
CursorUnlocker.SetEventSystem();
|
||||||
|
|
||||||
|
// update focused panel
|
||||||
|
UIPanel.UpdateFocus();
|
||||||
|
// update UI model instances
|
||||||
|
PanelDragger.UpdateInstances();
|
||||||
|
InputFieldRef.UpdateInstances();
|
||||||
|
UIBehaviourModel.UpdateInstances();
|
||||||
|
|
||||||
|
// update the timescale value
|
||||||
|
if (!timeInput.Component.isFocused && lastTimeScale != Time.timeScale)
|
||||||
|
{
|
||||||
|
if (pauseButtonPausing && Time.timeScale != 0.0f)
|
||||||
|
{
|
||||||
|
pauseButtonPausing = false;
|
||||||
|
OnPauseButtonToggled();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pauseButtonPausing)
|
||||||
|
{
|
||||||
|
timeInput.Text = Time.timeScale.ToString("F2");
|
||||||
|
lastTimeScale = Time.timeScale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check screen dimension change
|
||||||
|
if (Screen.width != lastScreenWidth || Screen.height != lastScreenHeight)
|
||||||
|
OnScreenDimensionsChanged();
|
||||||
|
}
|
||||||
|
|
||||||
// Panels
|
// Panels
|
||||||
|
|
||||||
public static UIPanel GetPanel(Panels panel)
|
public static UIPanel GetPanel(Panels panel)
|
||||||
@ -121,91 +225,89 @@ namespace UnityExplorer.UI
|
|||||||
SetPanelActive(panel, value);
|
SetPanelActive(panel, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Main UI Update loop
|
// navbar
|
||||||
|
|
||||||
private static int lastScreenWidth;
|
public static void SetNavBarAnchor()
|
||||||
private static int lastScreenHeight;
|
|
||||||
|
|
||||||
public static void Update()
|
|
||||||
{
|
{
|
||||||
if (!CanvasRoot || Initializing)
|
switch (NavbarAnchor)
|
||||||
return;
|
|
||||||
|
|
||||||
if (InspectUnderMouse.Inspecting)
|
|
||||||
{
|
{
|
||||||
InspectUnderMouse.Instance.UpdateInspect();
|
case VerticalAnchor.Top:
|
||||||
return;
|
NavBarRect.anchorMin = new Vector2(0.5f, 1f);
|
||||||
}
|
NavBarRect.anchorMax = new Vector2(0.5f, 1f);
|
||||||
|
NavBarRect.anchoredPosition = new Vector2(NavBarRect.anchoredPosition.x, 0);
|
||||||
|
NavBarRect.sizeDelta = new Vector2(1000f, 35f);
|
||||||
|
break;
|
||||||
|
|
||||||
if (InputManager.GetKeyDown(ConfigManager.Master_Toggle.Value))
|
case VerticalAnchor.Bottom:
|
||||||
ShowMenu = !ShowMenu;
|
NavBarRect.anchorMin = new Vector2(0.5f, 0f);
|
||||||
|
NavBarRect.anchorMax = new Vector2(0.5f, 0f);
|
||||||
if (!ShowMenu)
|
NavBarRect.anchoredPosition = new Vector2(NavBarRect.anchoredPosition.x, 35);
|
||||||
return;
|
NavBarRect.sizeDelta = new Vector2(1000f, 35f);
|
||||||
|
break;
|
||||||
if (InputManager.GetKeyDown(ConfigManager.Force_Unlock_Toggle.Value))
|
|
||||||
CursorUnlocker.Unlock = !CursorUnlocker.Unlock;
|
|
||||||
|
|
||||||
if (EventSystem.current != EventSys)
|
|
||||||
CursorUnlocker.SetEventSystem();
|
|
||||||
|
|
||||||
UIPanel.UpdateFocus();
|
|
||||||
PanelDragger.UpdateInstances();
|
|
||||||
InputFieldRef.UpdateInstances();
|
|
||||||
UIBehaviourModel.UpdateInstances();
|
|
||||||
|
|
||||||
if (Screen.width != lastScreenWidth || Screen.height != lastScreenHeight)
|
|
||||||
{
|
|
||||||
lastScreenWidth = Screen.width;
|
|
||||||
lastScreenHeight = Screen.height;
|
|
||||||
|
|
||||||
foreach (var panel in UIPanels)
|
|
||||||
{
|
|
||||||
panel.Value.EnsureValidSize();
|
|
||||||
UIPanel.EnsureValidPosition(panel.Value.Rect);
|
|
||||||
panel.Value.Dragger.OnEndResize();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialization and UI Construction
|
// listeners
|
||||||
|
|
||||||
internal static void InitUI()
|
private static void OnScreenDimensionsChanged()
|
||||||
{
|
{
|
||||||
LoadBundle();
|
|
||||||
|
|
||||||
UIFactory.Init();
|
|
||||||
|
|
||||||
CreateRootCanvas();
|
|
||||||
|
|
||||||
// Global UI Pool Holder
|
|
||||||
PoolHolder = new GameObject("PoolHolder");
|
|
||||||
PoolHolder.transform.parent = CanvasRoot.transform;
|
|
||||||
PoolHolder.SetActive(false);
|
|
||||||
|
|
||||||
CreateTopNavBar();
|
|
||||||
|
|
||||||
UIPanels.Add(Panels.AutoCompleter, new AutoCompleteModal());
|
|
||||||
UIPanels.Add(Panels.ObjectExplorer, new ObjectExplorerPanel());
|
|
||||||
UIPanels.Add(Panels.Inspector, new InspectorPanel());
|
|
||||||
UIPanels.Add(Panels.CSConsole, new CSConsolePanel());
|
|
||||||
UIPanels.Add(Panels.ConsoleLog, new LogPanel());
|
|
||||||
UIPanels.Add(Panels.Options, new OptionsPanel());
|
|
||||||
UIPanels.Add(Panels.MouseInspector, new InspectUnderMouse());
|
|
||||||
|
|
||||||
foreach (var panel in UIPanels.Values)
|
|
||||||
panel.ConstructUI();
|
|
||||||
|
|
||||||
ConsoleController.Init();
|
|
||||||
|
|
||||||
ShowMenu = !ConfigManager.Hide_On_Startup.Value;
|
|
||||||
|
|
||||||
lastScreenWidth = Screen.width;
|
lastScreenWidth = Screen.width;
|
||||||
lastScreenHeight = Screen.height;
|
lastScreenHeight = Screen.height;
|
||||||
|
|
||||||
Initializing = false;
|
foreach (var panel in UIPanels)
|
||||||
|
{
|
||||||
|
panel.Value.EnsureValidSize();
|
||||||
|
UIPanel.EnsureValidPosition(panel.Value.Rect);
|
||||||
|
panel.Value.Dragger.OnEndResize();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void OnCloseButtonClicked()
|
||||||
|
{
|
||||||
|
ShowMenu = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void Master_Toggle_OnValueChanged(KeyCode val)
|
||||||
|
{
|
||||||
|
closeBtn.ButtonText.text = val.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void OnTimeInputEndEdit(string val)
|
||||||
|
{
|
||||||
|
if (pauseButtonPausing)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (float.TryParse(val, out float f))
|
||||||
|
{
|
||||||
|
Time.timeScale = f;
|
||||||
|
lastTimeScale = f;
|
||||||
|
}
|
||||||
|
|
||||||
|
timeInput.Text = Time.timeScale.ToString("F2");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void OnPauseButtonClicked()
|
||||||
|
{
|
||||||
|
pauseButtonPausing = !pauseButtonPausing;
|
||||||
|
|
||||||
|
Time.timeScale = pauseButtonPausing ? 0f : lastTimeScale;
|
||||||
|
|
||||||
|
OnPauseButtonToggled();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void OnPauseButtonToggled()
|
||||||
|
{
|
||||||
|
timeInput.Component.text = Time.timeScale.ToString("F2");
|
||||||
|
timeInput.Component.readOnly = pauseButtonPausing;
|
||||||
|
timeInput.Component.textComponent.color = pauseButtonPausing ? Color.grey : Color.white;
|
||||||
|
|
||||||
|
Color color = pauseButtonPausing ? new Color(0.3f, 0.3f, 0.2f) : new Color(0.2f, 0.2f, 0.2f);
|
||||||
|
RuntimeProvider.Instance.SetColorBlock(pauseBtn.Component, color, color * 1.2f, color * 0.7f);
|
||||||
|
pauseBtn.ButtonText.text = pauseButtonPausing ? "►" : "||";
|
||||||
|
}
|
||||||
|
|
||||||
|
// UI Construction
|
||||||
|
|
||||||
private static void CreateRootCanvas()
|
private static void CreateRootCanvas()
|
||||||
{
|
{
|
||||||
CanvasRoot = new GameObject("ExplorerCanvas");
|
CanvasRoot = new GameObject("ExplorerCanvas");
|
||||||
@ -240,37 +342,17 @@ namespace UnityExplorer.UI
|
|||||||
PanelHolder.transform.SetAsFirstSibling();
|
PanelHolder.transform.SetAsFirstSibling();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SetNavBarAnchor()
|
|
||||||
{
|
|
||||||
switch (NavbarAnchor)
|
|
||||||
{
|
|
||||||
case VerticalAnchor.Top:
|
|
||||||
NavBarRect.anchorMin = new Vector2(0.5f, 1f);
|
|
||||||
NavBarRect.anchorMax = new Vector2(0.5f, 1f);
|
|
||||||
NavBarRect.anchoredPosition = new Vector2(NavBarRect.anchoredPosition.x, 0);
|
|
||||||
NavBarRect.sizeDelta = new Vector2(900f, 35f);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case VerticalAnchor.Bottom:
|
|
||||||
NavBarRect.anchorMin = new Vector2(0.5f, 0f);
|
|
||||||
NavBarRect.anchorMax = new Vector2(0.5f, 0f);
|
|
||||||
NavBarRect.anchoredPosition = new Vector2(NavBarRect.anchoredPosition.x, 35);
|
|
||||||
NavBarRect.sizeDelta = new Vector2(900f, 35f);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void CreateTopNavBar()
|
private static void CreateTopNavBar()
|
||||||
{
|
{
|
||||||
var navbarPanel = UIFactory.CreateUIObject("MainNavbar", CanvasRoot);
|
var navbarPanel = UIFactory.CreateUIObject("MainNavbar", CanvasRoot);
|
||||||
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(navbarPanel, false, true, true, true, 5, 4, 4, 4, 4, TextAnchor.MiddleCenter);
|
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(navbarPanel, false, false, true, true, 5, 4, 4, 4, 4, TextAnchor.MiddleCenter);
|
||||||
navbarPanel.AddComponent<Image>().color = new Color(0.1f, 0.1f, 0.1f);
|
navbarPanel.AddComponent<Image>().color = new Color(0.1f, 0.1f, 0.1f);
|
||||||
NavBarRect = navbarPanel.GetComponent<RectTransform>();
|
NavBarRect = navbarPanel.GetComponent<RectTransform>();
|
||||||
NavBarRect.pivot = new Vector2(0.5f, 1f);
|
NavBarRect.pivot = new Vector2(0.5f, 1f);
|
||||||
|
|
||||||
NavbarAnchor = ConfigManager.Main_Navbar_Anchor.Value;
|
NavbarAnchor = ConfigManager.Main_Navbar_Anchor.Value;
|
||||||
SetNavBarAnchor();
|
SetNavBarAnchor();
|
||||||
ConfigManager.Main_Navbar_Anchor.OnValueChanged += (VerticalAnchor val) =>
|
ConfigManager.Main_Navbar_Anchor.OnValueChanged += (VerticalAnchor val) =>
|
||||||
{
|
{
|
||||||
NavbarAnchor = val;
|
NavbarAnchor = val;
|
||||||
SetNavBarAnchor();
|
SetNavBarAnchor();
|
||||||
@ -279,14 +361,28 @@ namespace UnityExplorer.UI
|
|||||||
// UnityExplorer title
|
// UnityExplorer title
|
||||||
|
|
||||||
string titleTxt = $"{ExplorerCore.NAME} <i><color=grey>{ExplorerCore.VERSION}</color></i>";
|
string titleTxt = $"{ExplorerCore.NAME} <i><color=grey>{ExplorerCore.VERSION}</color></i>";
|
||||||
var title = UIFactory.CreateLabel(navbarPanel, "Title", titleTxt, TextAnchor.MiddleLeft, default, true, 18);
|
var title = UIFactory.CreateLabel(navbarPanel, "Title", titleTxt, TextAnchor.MiddleLeft, default, true, 17);
|
||||||
UIFactory.SetLayoutElement(title.gameObject, minWidth: 180, flexibleWidth: 0);
|
UIFactory.SetLayoutElement(title.gameObject, minWidth: 170, flexibleWidth: 0);
|
||||||
|
|
||||||
// Navbar
|
// panel tabs
|
||||||
|
|
||||||
NavbarButtonHolder = UIFactory.CreateUIObject("NavButtonHolder", navbarPanel);
|
NavbarTabButtonHolder = UIFactory.CreateUIObject("NavTabButtonHolder", navbarPanel);
|
||||||
UIFactory.SetLayoutElement(NavbarButtonHolder, flexibleHeight: 999, flexibleWidth: 999);
|
UIFactory.SetLayoutElement(NavbarTabButtonHolder, minHeight: 25, flexibleHeight: 999, flexibleWidth: 999);
|
||||||
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(NavbarButtonHolder, false, true, true, true, 4, 2, 2, 2, 2);
|
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(NavbarTabButtonHolder, false, true, true, true, 4, 2, 2, 2, 2);
|
||||||
|
|
||||||
|
// Time controls
|
||||||
|
|
||||||
|
var timeLabel = UIFactory.CreateLabel(navbarPanel, "TimeLabel", "Time:", TextAnchor.MiddleRight, Color.grey);
|
||||||
|
UIFactory.SetLayoutElement(timeLabel.gameObject, minHeight: 25, minWidth: 50);
|
||||||
|
|
||||||
|
timeInput = UIFactory.CreateInputField(navbarPanel, "TimeInput", "timeScale");
|
||||||
|
UIFactory.SetLayoutElement(timeInput.Component.gameObject, minHeight: 25, minWidth: 40);
|
||||||
|
timeInput.Text = Time.timeScale.ToString("F2");
|
||||||
|
timeInput.Component.GetOnEndEdit().AddListener(OnTimeInputEndEdit);
|
||||||
|
|
||||||
|
pauseBtn = UIFactory.CreateButton(navbarPanel, "PauseButton", "||", new Color(0.2f, 0.2f, 0.2f));
|
||||||
|
UIFactory.SetLayoutElement(pauseBtn.Component.gameObject, minHeight: 25, minWidth: 25);
|
||||||
|
pauseBtn.OnClick += OnPauseButtonClicked;
|
||||||
|
|
||||||
// Inspect under mouse dropdown
|
// Inspect under mouse dropdown
|
||||||
|
|
||||||
@ -299,14 +395,13 @@ namespace UnityExplorer.UI
|
|||||||
|
|
||||||
// Hide menu button
|
// Hide menu button
|
||||||
|
|
||||||
var closeBtn = UIFactory.CreateButton(navbarPanel, "CloseButton", ConfigManager.Master_Toggle.Value.ToString());
|
closeBtn = UIFactory.CreateButton(navbarPanel, "CloseButton", ConfigManager.Master_Toggle.Value.ToString());
|
||||||
UIFactory.SetLayoutElement(closeBtn.Component.gameObject, minHeight: 25, minWidth: 80, flexibleWidth: 0);
|
UIFactory.SetLayoutElement(closeBtn.Component.gameObject, minHeight: 25, minWidth: 80, flexibleWidth: 0);
|
||||||
RuntimeProvider.Instance.SetColorBlock(closeBtn.Component, new Color(0.63f, 0.32f, 0.31f),
|
RuntimeProvider.Instance.SetColorBlock(closeBtn.Component, new Color(0.63f, 0.32f, 0.31f),
|
||||||
new Color(0.81f, 0.25f, 0.2f), new Color(0.6f, 0.18f, 0.16f));
|
new Color(0.81f, 0.25f, 0.2f), new Color(0.6f, 0.18f, 0.16f));
|
||||||
|
|
||||||
ConfigManager.Master_Toggle.OnValueChanged += (KeyCode val) => { closeBtn.ButtonText.text = val.ToString(); };
|
ConfigManager.Master_Toggle.OnValueChanged += Master_Toggle_OnValueChanged;
|
||||||
|
closeBtn.OnClick += OnCloseButtonClicked;
|
||||||
closeBtn.OnClick += () => { ShowMenu = false; };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#region UI AssetBundle
|
#region UI AssetBundle
|
||||||
|
@ -7,7 +7,6 @@ using UnityEngine.UI;
|
|||||||
using UnityExplorer.Core.Input;
|
using UnityExplorer.Core.Input;
|
||||||
using UnityExplorer.Core.Runtime;
|
using UnityExplorer.Core.Runtime;
|
||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
using UnityExplorer.UI.ObjectPool;
|
|
||||||
using UnityExplorer.UI.Panels;
|
using UnityExplorer.UI.Panels;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Widgets.AutoComplete
|
namespace UnityExplorer.UI.Widgets.AutoComplete
|
||||||
@ -170,7 +169,7 @@ namespace UnityExplorer.UI.Widgets.AutoComplete
|
|||||||
|
|
||||||
// Setting autocomplete cell buttons
|
// Setting autocomplete cell buttons
|
||||||
|
|
||||||
private readonly Color selectedSuggestionColor = new Color(45/255f, 75/255f, 80/255f);
|
private readonly Color selectedSuggestionColor = new Color(45 / 255f, 75 / 255f, 80 / 255f);
|
||||||
private readonly Color inactiveSuggestionColor = new Color(0.11f, 0.11f, 0.11f);
|
private readonly Color inactiveSuggestionColor = new Color(0.11f, 0.11f, 0.11f);
|
||||||
|
|
||||||
private List<Suggestion> GetEntries() => Suggestions;
|
private List<Suggestion> GetEntries() => Suggestions;
|
||||||
@ -301,7 +300,7 @@ namespace UnityExplorer.UI.Widgets.AutoComplete
|
|||||||
{
|
{
|
||||||
dataHandler = new ButtonListHandler<Suggestion, ButtonCell>(scrollPool, GetEntries, SetCell, ShouldDisplay, OnCellClicked);
|
dataHandler = new ButtonListHandler<Suggestion, ButtonCell>(scrollPool, GetEntries, SetCell, ShouldDisplay, OnCellClicked);
|
||||||
|
|
||||||
scrollPool = UIFactory.CreateScrollPool<ButtonCell>(this.content, "AutoCompleter", out GameObject scrollObj,
|
scrollPool = UIFactory.CreateScrollPool<ButtonCell>(this.content, "AutoCompleter", out GameObject scrollObj,
|
||||||
out GameObject scrollContent);
|
out GameObject scrollContent);
|
||||||
scrollPool.Initialize(dataHandler);
|
scrollPool.Initialize(dataHandler);
|
||||||
UIFactory.SetLayoutElement(scrollObj, flexibleHeight: 9999);
|
UIFactory.SetLayoutElement(scrollObj, flexibleHeight: 9999);
|
||||||
@ -309,7 +308,7 @@ namespace UnityExplorer.UI.Widgets.AutoComplete
|
|||||||
|
|
||||||
navigationTipRow = UIFactory.CreateHorizontalGroup(this.content, "BottomRow", true, true, true, true, 0, new Vector4(2, 2, 2, 2));
|
navigationTipRow = UIFactory.CreateHorizontalGroup(this.content, "BottomRow", true, true, true, true, 0, new Vector4(2, 2, 2, 2));
|
||||||
UIFactory.SetLayoutElement(navigationTipRow, minHeight: 20, flexibleWidth: 9999);
|
UIFactory.SetLayoutElement(navigationTipRow, minHeight: 20, flexibleWidth: 9999);
|
||||||
UIFactory.CreateLabel(navigationTipRow, "HelpText", "Up/Down to select, Enter to use, Esc to close",
|
UIFactory.CreateLabel(navigationTipRow, "HelpText", "Up/Down to select, Enter to use, Esc to close",
|
||||||
TextAnchor.MiddleLeft, Color.grey, false, 13);
|
TextAnchor.MiddleLeft, Color.grey, false, 13);
|
||||||
|
|
||||||
UIRoot.SetActive(false);
|
UIRoot.SetActive(false);
|
||||||
|
@ -9,7 +9,6 @@ using UnityExplorer.Core.Input;
|
|||||||
using UnityExplorer.Core.Runtime;
|
using UnityExplorer.Core.Runtime;
|
||||||
using UnityExplorer.UI.Models;
|
using UnityExplorer.UI.Models;
|
||||||
using UnityExplorer.UI.Panels;
|
using UnityExplorer.UI.Panels;
|
||||||
using UnityExplorer.UI.Utility;
|
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Widgets.AutoComplete
|
namespace UnityExplorer.UI.Widgets.AutoComplete
|
||||||
{
|
{
|
||||||
@ -88,7 +87,7 @@ namespace UnityExplorer.UI.Widgets.AutoComplete
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check for exact match first
|
// Check for exact match first
|
||||||
if (ReflectionUtility.AllTypes.TryGetValue(value, out Type t) && allowedTypes.Contains(t))
|
if (ReflectionUtility.GetTypeByName(value) is Type t && allowedTypes.Contains(t))
|
||||||
AddSuggestion(t);
|
AddSuggestion(t);
|
||||||
|
|
||||||
foreach (var entry in allowedTypes)
|
foreach (var entry in allowedTypes)
|
||||||
|
@ -10,7 +10,7 @@ using UnityExplorer.Core;
|
|||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
using UnityExplorer.UI.Models;
|
using UnityExplorer.UI.Models;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Utility
|
namespace UnityExplorer.UI.Widgets
|
||||||
{
|
{
|
||||||
public class AutoSliderScrollbar : UIBehaviourModel
|
public class AutoSliderScrollbar : UIBehaviourModel
|
||||||
{
|
{
|
||||||
@ -91,7 +91,7 @@ namespace UnityExplorer.UI.Utility
|
|||||||
Slider.interactable = false;
|
Slider.interactable = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var handleHeight = viewportHeight * Math.Min(1, viewportHeight / totalHeight);
|
var handleHeight = viewportHeight * Math.Min(1, viewportHeight / totalHeight);
|
||||||
handleHeight = Math.Max(15f, handleHeight);
|
handleHeight = Math.Max(15f, handleHeight);
|
||||||
|
|
||||||
|
@ -4,7 +4,6 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.UI.ObjectPool;
|
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Widgets
|
namespace UnityExplorer.UI.Widgets
|
||||||
{
|
{
|
||||||
|
@ -4,9 +4,6 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
|
||||||
using UnityExplorer.UI.ObjectPool;
|
|
||||||
using UnityExplorer.UI.Widgets;
|
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Widgets
|
namespace UnityExplorer.UI.Widgets
|
||||||
{
|
{
|
||||||
@ -29,7 +26,7 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
}
|
}
|
||||||
private string currentFilter;
|
private string currentFilter;
|
||||||
|
|
||||||
public ButtonListHandler(ScrollPool<TCell> scrollPool, Func<List<TData>> getEntriesMethod,
|
public ButtonListHandler(ScrollPool<TCell> scrollPool, Func<List<TData>> getEntriesMethod,
|
||||||
Action<TCell, int> setICellMethod, Func<TData, string, bool> shouldDisplayMethod,
|
Action<TCell, int> setICellMethod, Func<TData, string, bool> shouldDisplayMethod,
|
||||||
Action<int> onCellClickedMethod)
|
Action<int> onCellClickedMethod)
|
||||||
{
|
{
|
||||||
|
@ -4,12 +4,12 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
|
||||||
using UnityEngine.EventSystems;
|
|
||||||
using UnityEngine.Events;
|
using UnityEngine.Events;
|
||||||
|
using UnityEngine.EventSystems;
|
||||||
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.UI.Models;
|
using UnityExplorer.UI.Models;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Utility
|
namespace UnityExplorer.UI.Widgets
|
||||||
{
|
{
|
||||||
// To fix an issue with Input Fields and allow them to go inside a ScrollRect nicely.
|
// To fix an issue with Input Fields and allow them to go inside a ScrollRect nicely.
|
||||||
|
|
||||||
@ -80,12 +80,12 @@ namespace UnityExplorer.UI.Utility
|
|||||||
|
|
||||||
if (ContentRect.rect.height < desiredHeight)
|
if (ContentRect.rect.height < desiredHeight)
|
||||||
{
|
{
|
||||||
ContentRect.sizeDelta = new Vector2(0, desiredHeight);
|
ContentRect.sizeDelta = new Vector2(ContentRect.sizeDelta.x, desiredHeight);
|
||||||
this.Slider.UpdateSliderHandle();
|
this.Slider.UpdateSliderHandle();
|
||||||
}
|
}
|
||||||
else if (ContentRect.rect.height > desiredHeight)
|
else if (ContentRect.rect.height > desiredHeight)
|
||||||
{
|
{
|
||||||
ContentRect.sizeDelta = new Vector2(0, desiredHeight);
|
ContentRect.sizeDelta = new Vector2(ContentRect.sizeDelta.x, desiredHeight);
|
||||||
this.Slider.UpdateSliderHandle();
|
this.Slider.UpdateSliderHandle();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,15 +6,6 @@ using UnityEngine;
|
|||||||
|
|
||||||
namespace UnityExplorer.UI.Widgets
|
namespace UnityExplorer.UI.Widgets
|
||||||
{
|
{
|
||||||
public class DataViewInfo
|
|
||||||
{
|
|
||||||
public int dataIndex;
|
|
||||||
public float height, startPosition;
|
|
||||||
public int normalizedSpread;
|
|
||||||
|
|
||||||
public static implicit operator float(DataViewInfo it) => it.height;
|
|
||||||
}
|
|
||||||
|
|
||||||
public class DataHeightCache<T> where T : ICell
|
public class DataHeightCache<T> where T : ICell
|
||||||
{
|
{
|
||||||
private ScrollPool<T> ScrollPool { get; }
|
private ScrollPool<T> ScrollPool { get; }
|
||||||
@ -53,14 +44,8 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
/// <summary>Get the first range (division of DefaultHeight) which the position appears in.</summary>
|
/// <summary>Get the first range (division of DefaultHeight) which the position appears in.</summary>
|
||||||
private int GetRangeFloorOfPosition(float position) => (int)Math.Floor((decimal)position / (decimal)DefaultHeight);
|
private int GetRangeFloorOfPosition(float position) => (int)Math.Floor((decimal)position / (decimal)DefaultHeight);
|
||||||
|
|
||||||
/// <summary>Get the data index at the specified position of the total height cache.</summary>
|
public int GetFirstDataIndexAtPosition(float desiredHeight)
|
||||||
public int GetFirstDataIndexAtPosition(float desiredHeight) => GetFirstDataIndexAtPosition(desiredHeight, out _);
|
|
||||||
|
|
||||||
/// <summary>Get the data index and DataViewInfo at the specified position of the total height cache.</summary>
|
|
||||||
public int GetFirstDataIndexAtPosition(float desiredHeight, out DataViewInfo cache)
|
|
||||||
{
|
{
|
||||||
cache = default;
|
|
||||||
|
|
||||||
if (!heightCache.Any())
|
if (!heightCache.Any())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -72,23 +57,21 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
if (rangeIndex >= rangeCache.Count)
|
if (rangeIndex >= rangeCache.Count)
|
||||||
{
|
{
|
||||||
int idx = ScrollPool.DataSource.ItemCount - 1;
|
int idx = ScrollPool.DataSource.ItemCount - 1;
|
||||||
cache = heightCache[idx];
|
|
||||||
return idx;
|
return idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
int dataIndex = rangeCache[rangeIndex];
|
int dataIndex = rangeCache[rangeIndex];
|
||||||
cache = heightCache[dataIndex];
|
var cache = heightCache[dataIndex];
|
||||||
|
|
||||||
// if the DataViewInfo is outdated, need to rebuild
|
// if the DataViewInfo is outdated, need to rebuild
|
||||||
int expectedMin = GetRangeCeilingOfPosition(cache.startPosition);
|
int expectedMin = GetRangeCeilingOfPosition(cache.startPosition);
|
||||||
int expectedMax = expectedMin + cache.normalizedSpread - 1;
|
int expectedMax = expectedMin + cache.normalizedSpread - 1;
|
||||||
if (rangeIndex < expectedMin || rangeIndex > expectedMax)
|
if (rangeIndex < expectedMin || rangeIndex > expectedMax)
|
||||||
{
|
{
|
||||||
RecalculateStartPositions(Math.Max(dataIndex, expectedMax));
|
RecalculateStartPositions(ScrollPool.DataSource.ItemCount - 1);
|
||||||
|
|
||||||
rangeIndex = GetRangeFloorOfPosition(desiredHeight);
|
rangeIndex = GetRangeFloorOfPosition(desiredHeight);
|
||||||
dataIndex = rangeCache[rangeIndex];
|
dataIndex = rangeCache[rangeIndex];
|
||||||
cache = heightCache[dataIndex];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return dataIndex;
|
return dataIndex;
|
||||||
@ -116,17 +99,11 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
/// <summary>Append a data index to the cache with the provided height value.</summary>
|
/// <summary>Append a data index to the cache with the provided height value.</summary>
|
||||||
public void Add(float value)
|
public void Add(float value)
|
||||||
{
|
{
|
||||||
value = (float)Math.Floor(value);
|
|
||||||
value = Math.Max(DefaultHeight, value);
|
value = Math.Max(DefaultHeight, value);
|
||||||
|
|
||||||
int spread = GetRangeSpread(totalHeight, value);
|
int spread = GetRangeSpread(totalHeight, value);
|
||||||
|
|
||||||
heightCache.Add(new DataViewInfo()
|
heightCache.Add(new DataViewInfo(heightCache.Count, value, totalHeight, spread));
|
||||||
{
|
|
||||||
height = value,
|
|
||||||
startPosition = TotalHeight,
|
|
||||||
normalizedSpread = spread,
|
|
||||||
});
|
|
||||||
|
|
||||||
int dataIdx = heightCache.Count - 1;
|
int dataIdx = heightCache.Count - 1;
|
||||||
for (int i = 0; i < spread; i++)
|
for (int i = 0; i < spread; i++)
|
||||||
@ -141,8 +118,7 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
if (!heightCache.Any())
|
if (!heightCache.Any())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var val = heightCache[heightCache.Count - 1];
|
totalHeight -= heightCache[heightCache.Count - 1];
|
||||||
totalHeight -= val;
|
|
||||||
heightCache.RemoveAt(heightCache.Count - 1);
|
heightCache.RemoveAt(heightCache.Count - 1);
|
||||||
|
|
||||||
int idx = heightCache.Count;
|
int idx = heightCache.Count;
|
||||||
@ -195,28 +171,31 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
int spread = GetRangeSpread(cache.startPosition, height);
|
int spread = GetRangeSpread(cache.startPosition, height);
|
||||||
|
|
||||||
// If the previous item in the range cache is not the previous data index, there is a gap.
|
// If the previous item in the range cache is not the previous data index, there is a gap.
|
||||||
if (dataIndex > 0 && rangeCache[rangeIndex - 1] != (dataIndex - 1))
|
if (rangeCache[rangeIndex] != dataIndex)
|
||||||
{
|
{
|
||||||
// Recalculate start positions up to this index. The gap could be anywhere before here.
|
// Recalculate start positions up to this index. The gap could be anywhere before here.
|
||||||
RecalculateStartPositions(dataIndex + 1);
|
RecalculateStartPositions(ScrollPool.DataSource.ItemCount - 1);
|
||||||
// Get the range index and spread again after rebuilding
|
// Get the range index and spread again after rebuilding
|
||||||
rangeIndex = GetRangeCeilingOfPosition(cache.startPosition);
|
rangeIndex = GetRangeCeilingOfPosition(cache.startPosition);
|
||||||
spread = GetRangeSpread(cache.startPosition, height);
|
spread = GetRangeSpread(cache.startPosition, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rangeCache.Count <= rangeIndex || rangeCache[rangeIndex] != dataIndex)
|
if (rangeCache[rangeIndex] != dataIndex)
|
||||||
throw new Exception("ScrollPool data height cache is corrupt or invalid, rebuild failed!");
|
throw new IndexOutOfRangeException($"Trying to set dataIndex {dataIndex} at rangeIndex {rangeIndex}, but cache is corrupt or invalid!");
|
||||||
|
|
||||||
if (spread != cache.normalizedSpread)
|
if (spread != cache.normalizedSpread)
|
||||||
{
|
{
|
||||||
int spreadDiff = spread - cache.normalizedSpread;
|
int spreadDiff = spread - cache.normalizedSpread;
|
||||||
cache.normalizedSpread = spread;
|
cache.normalizedSpread = spread;
|
||||||
|
|
||||||
SetSpread(dataIndex, rangeIndex, spreadDiff);
|
UpdateSpread(dataIndex, rangeIndex, spreadDiff);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set the struct back to the array
|
||||||
|
heightCache[dataIndex] = cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetSpread(int dataIndex, int rangeIndex, int spreadDiff)
|
private void UpdateSpread(int dataIndex, int rangeIndex, int spreadDiff)
|
||||||
{
|
{
|
||||||
if (spreadDiff > 0)
|
if (spreadDiff > 0)
|
||||||
{
|
{
|
||||||
@ -233,8 +212,6 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
rangeCache.RemoveAt(rangeIndex);
|
rangeCache.RemoveAt(rangeIndex);
|
||||||
spreadDiff++;
|
spreadDiff++;
|
||||||
}
|
}
|
||||||
//for (int i = 0; i < -spreadDiff; i++)
|
|
||||||
// rangeCache.RemoveAt(rangeIndex);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -243,38 +220,60 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
if (heightCache.Count <= 1)
|
if (heightCache.Count <= 1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
DataViewInfo cache;
|
rangeCache.Clear();
|
||||||
DataViewInfo prev = null;
|
|
||||||
for (int i = 0; i <= toIndex && i < heightCache.Count; i++)
|
|
||||||
{
|
|
||||||
cache = heightCache[i];
|
|
||||||
|
|
||||||
if (prev != null)
|
DataViewInfo cache;
|
||||||
|
DataViewInfo prev = DataViewInfo.None;
|
||||||
|
for (int idx = 0; idx <= toIndex && idx < heightCache.Count; idx++)
|
||||||
|
{
|
||||||
|
cache = heightCache[idx];
|
||||||
|
|
||||||
|
if (!prev.Equals(DataViewInfo.None))
|
||||||
cache.startPosition = prev.startPosition + prev.height;
|
cache.startPosition = prev.startPosition + prev.height;
|
||||||
else
|
else
|
||||||
cache.startPosition = 0;
|
cache.startPosition = 0;
|
||||||
|
|
||||||
var origSpread = cache.normalizedSpread;
|
|
||||||
cache.normalizedSpread = GetRangeSpread(cache.startPosition, cache.height);
|
cache.normalizedSpread = GetRangeSpread(cache.startPosition, cache.height);
|
||||||
if (cache.normalizedSpread != origSpread)
|
for (int i = 0; i < cache.normalizedSpread; i++)
|
||||||
SetSpread(i, GetRangeCeilingOfPosition(cache.startPosition), cache.normalizedSpread - origSpread);
|
rangeCache.Add(cache.dataIndex);
|
||||||
|
|
||||||
|
heightCache[idx] = cache;
|
||||||
|
|
||||||
prev = cache;
|
prev = cache;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//private void HardRebuildRanges()
|
public struct DataViewInfo
|
||||||
//{
|
{
|
||||||
// var tempList = new List<float>();
|
// static
|
||||||
// for (int i = 0; i < heightCache.Count; i++)
|
public static DataViewInfo None => s_default;
|
||||||
// tempList.Add(heightCache[i]);
|
private static DataViewInfo s_default = default;
|
||||||
//
|
|
||||||
// heightCache.Clear();
|
public static implicit operator float(DataViewInfo it) => it.height;
|
||||||
// rangeCache.Clear();
|
|
||||||
// totalHeight = 0;
|
public DataViewInfo(int index, float height, float startPos, int spread)
|
||||||
//
|
{
|
||||||
// for (int i = 0; i < tempList.Count; i++)
|
this.dataIndex = index;
|
||||||
// SetIndex(i, tempList[i]);
|
this.height = height;
|
||||||
//}
|
this.startPosition = startPos;
|
||||||
|
this.normalizedSpread = spread;
|
||||||
|
}
|
||||||
|
|
||||||
|
// instance
|
||||||
|
public int dataIndex, normalizedSpread;
|
||||||
|
public float height, startPosition;
|
||||||
|
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
var other = (DataViewInfo)obj;
|
||||||
|
|
||||||
|
return this.dataIndex == other.dataIndex
|
||||||
|
&& this.height == other.height
|
||||||
|
&& this.startPosition == other.startPosition
|
||||||
|
&& this.normalizedSpread == other.normalizedSpread;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode() => base.GetHashCode();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityExplorer.UI.ObjectPool;
|
using UnityExplorer.UI.Models;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Widgets
|
namespace UnityExplorer.UI.Widgets
|
||||||
{
|
{
|
||||||
|
@ -7,12 +7,11 @@ using UnityEngine;
|
|||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.Core.Input;
|
using UnityExplorer.Core.Input;
|
||||||
using UnityExplorer.UI.Models;
|
using UnityExplorer.UI.Models;
|
||||||
using UnityExplorer.UI.ObjectPool;
|
|
||||||
using UnityExplorer.UI.Panels;
|
using UnityExplorer.UI.Panels;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Widgets
|
namespace UnityExplorer.UI.Widgets
|
||||||
{
|
{
|
||||||
public struct CellInfo
|
public struct CellInfo
|
||||||
{
|
{
|
||||||
public int cellIndex, dataIndex;
|
public int cellIndex, dataIndex;
|
||||||
}
|
}
|
||||||
@ -20,7 +19,7 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// An object-pooled ScrollRect, attempts to support content of any size and provide a scrollbar for it.
|
/// An object-pooled ScrollRect, attempts to support content of any size and provide a scrollbar for it.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ScrollPool<T> : UIBehaviourModel where T : ICell
|
public class ScrollPool<T> : UIBehaviourModel, IEnumerable<CellInfo> where T : ICell
|
||||||
{
|
{
|
||||||
public ScrollPool(ScrollRect scrollRect)
|
public ScrollPool(ScrollRect scrollRect)
|
||||||
{
|
{
|
||||||
@ -121,7 +120,7 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
OnHeightChanged?.Invoke();
|
OnHeightChanged?.Invoke();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@ -130,7 +129,7 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
public void Refresh(bool setCellData, bool jumpToTop = false)
|
public void Refresh(bool setCellData, bool jumpToTop = false)
|
||||||
{
|
{
|
||||||
if (jumpToTop)
|
if (jumpToTop)
|
||||||
{
|
{
|
||||||
bottomDataIndex = CellPool.Count - 1;
|
bottomDataIndex = CellPool.Count - 1;
|
||||||
Content.anchoredPosition = Vector2.zero;
|
Content.anchoredPosition = Vector2.zero;
|
||||||
}
|
}
|
||||||
@ -138,9 +137,42 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
RefreshCells(setCellData, true);
|
RefreshCells(setCellData, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize
|
public void JumpToIndex(int index, Action<T> onJumped)
|
||||||
|
{
|
||||||
|
RefreshCells(true, true);
|
||||||
|
|
||||||
//private bool Initialized;
|
// Slide to the normalized position of the index
|
||||||
|
var cache = HeightCache[index];
|
||||||
|
float normalized = (cache.startPosition + (cache.height * 0.5f)) / HeightCache.TotalHeight;
|
||||||
|
|
||||||
|
RuntimeProvider.Instance.StartCoroutine(ForceDelayedJump(index, normalized, onJumped));
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerator ForceDelayedJump(int dataIndex, float normalizedPos, Action<T> onJumped)
|
||||||
|
{
|
||||||
|
// Yielding two frames seems necessary in case the Explorer tab had not been opened before the jump.
|
||||||
|
yield return null;
|
||||||
|
yield return null;
|
||||||
|
slider.value = normalizedPos;
|
||||||
|
|
||||||
|
// Get the cell containing the data index and invoke the onJumped listener for it
|
||||||
|
foreach (var cellInfo in this)
|
||||||
|
{
|
||||||
|
if (cellInfo.dataIndex == dataIndex)
|
||||||
|
{
|
||||||
|
onJumped?.Invoke(CellPool[cellInfo.cellIndex]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// IEnumerable
|
||||||
|
|
||||||
|
public IEnumerator<CellInfo> GetEnumerator() => EnumerateCellPool();
|
||||||
|
|
||||||
|
IEnumerator IEnumerable.GetEnumerator() => EnumerateCellPool();
|
||||||
|
|
||||||
|
// Initialize
|
||||||
|
|
||||||
/// <summary>Should be called only once, when the scroll pool is created.</summary>
|
/// <summary>Should be called only once, when the scroll pool is created.</summary>
|
||||||
public void Initialize(ICellPoolDataSource<T> dataSource, Action onHeightChangedListener = null)
|
public void Initialize(ICellPoolDataSource<T> dataSource, Action onHeightChangedListener = null)
|
||||||
@ -161,13 +193,11 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
RuntimeProvider.Instance.StartCoroutine(InitCoroutine(onHeightChangedListener));
|
RuntimeProvider.Instance.StartCoroutine(InitCoroutine(onHeightChangedListener));
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly WaitForEndOfFrame waitForEndOfFrame = new WaitForEndOfFrame();
|
|
||||||
|
|
||||||
private IEnumerator InitCoroutine(Action onHeightChangedListener)
|
private IEnumerator InitCoroutine(Action onHeightChangedListener)
|
||||||
{
|
{
|
||||||
ScrollRect.content.anchoredPosition = Vector2.zero;
|
ScrollRect.content.anchoredPosition = Vector2.zero;
|
||||||
//yield return null;
|
yield return null;
|
||||||
yield return waitForEndOfFrame;
|
yield return null;
|
||||||
|
|
||||||
LayoutRebuilder.ForceRebuildLayoutImmediate(Content);
|
LayoutRebuilder.ForceRebuildLayoutImmediate(Content);
|
||||||
|
|
||||||
@ -178,9 +208,8 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
// create initial cell pool and set cells
|
// create initial cell pool and set cells
|
||||||
CreateCellPool();
|
CreateCellPool();
|
||||||
|
|
||||||
var enumerator = GetPoolEnumerator();
|
foreach (var cell in this)
|
||||||
while (enumerator.MoveNext())
|
SetCell(CellPool[cell.cellIndex], cell.dataIndex);
|
||||||
SetCell(CellPool[enumerator.Current.cellIndex], enumerator.Current.dataIndex);
|
|
||||||
|
|
||||||
LayoutRebuilder.ForceRebuildLayoutImmediate(Content);
|
LayoutRebuilder.ForceRebuildLayoutImmediate(Content);
|
||||||
prevContentHeight = Content.rect.height;
|
prevContentHeight = Content.rect.height;
|
||||||
@ -217,18 +246,18 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
|
|
||||||
// Cell pool
|
// Cell pool
|
||||||
|
|
||||||
private CellInfo _cellInfo = new CellInfo();
|
private CellInfo _current;
|
||||||
|
|
||||||
public IEnumerator<CellInfo> GetPoolEnumerator()
|
private IEnumerator<CellInfo> EnumerateCellPool()
|
||||||
{
|
{
|
||||||
int cellIdx = topPoolIndex;
|
int cellIdx = topPoolIndex;
|
||||||
int dataIndex = TopDataIndex;
|
int dataIndex = TopDataIndex;
|
||||||
int iterated = 0;
|
int iterated = 0;
|
||||||
while (iterated < CellPool.Count)
|
while (iterated < CellPool.Count)
|
||||||
{
|
{
|
||||||
_cellInfo.cellIndex = cellIdx;
|
_current.cellIndex = cellIdx;
|
||||||
_cellInfo.dataIndex = dataIndex;
|
_current.dataIndex = dataIndex;
|
||||||
yield return _cellInfo;
|
yield return _current;
|
||||||
|
|
||||||
cellIdx++;
|
cellIdx++;
|
||||||
if (cellIdx >= CellPool.Count)
|
if (cellIdx >= CellPool.Count)
|
||||||
@ -298,7 +327,7 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
if (CellPool.Count > 1)
|
if (CellPool.Count > 1)
|
||||||
{
|
{
|
||||||
int index = CellPool.Count - 1 - (topPoolIndex % (CellPool.Count - 1));
|
int index = CellPool.Count - 1 - (topPoolIndex % (CellPool.Count - 1));
|
||||||
cell.Rect.SetSiblingIndex(index);
|
cell.Rect.SetSiblingIndex(index + 1);
|
||||||
|
|
||||||
if (bottomPoolIndex == index - 1)
|
if (bottomPoolIndex == index - 1)
|
||||||
bottomPoolIndex++;
|
bottomPoolIndex++;
|
||||||
@ -368,16 +397,13 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
CheckDataSourceCountChange(out bool jumpToBottom);
|
CheckDataSourceCountChange(out bool jumpToBottom);
|
||||||
|
|
||||||
// update date height cache, and set cells if 'andReload'
|
// update date height cache, and set cells if 'andReload'
|
||||||
var enumerator = GetPoolEnumerator();
|
foreach (var cellInfo in this)
|
||||||
while (enumerator.MoveNext())
|
|
||||||
{
|
{
|
||||||
var curr = enumerator.Current;
|
var cell = CellPool[cellInfo.cellIndex];
|
||||||
var cell = CellPool[curr.cellIndex];
|
|
||||||
|
|
||||||
if (andReloadFromDataSource)
|
if (andReloadFromDataSource)
|
||||||
SetCell(cell, curr.dataIndex);
|
SetCell(cell, cellInfo.dataIndex);
|
||||||
else
|
else
|
||||||
HeightCache.SetIndex(curr.dataIndex, cell.Rect.rect.height);
|
HeightCache.SetIndex(cellInfo.dataIndex, cell.Rect.rect.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
// force check recycles
|
// force check recycles
|
||||||
@ -405,12 +431,8 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
|
|
||||||
private void RefreshCellHeightsFast()
|
private void RefreshCellHeightsFast()
|
||||||
{
|
{
|
||||||
var enumerator = GetPoolEnumerator();
|
foreach (var cellInfo in this)
|
||||||
while (enumerator.MoveNext())
|
HeightCache.SetIndex(cellInfo.dataIndex, CellPool[cellInfo.cellIndex].Rect.rect.height);
|
||||||
{
|
|
||||||
var curr = enumerator.Current;
|
|
||||||
HeightCache.SetIndex(curr.dataIndex, CellPool[curr.cellIndex].Rect.rect.height);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetCell(T cachedCell, int dataIndex)
|
private void SetCell(T cachedCell, int dataIndex)
|
||||||
@ -619,12 +641,10 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
bottomDataIndex = desiredBottomIndex;
|
bottomDataIndex = desiredBottomIndex;
|
||||||
var enumerator = GetPoolEnumerator();
|
foreach (var info in this)
|
||||||
while (enumerator.MoveNext())
|
|
||||||
{
|
{
|
||||||
var curr = enumerator.Current;
|
var cell = CellPool[info.cellIndex];
|
||||||
var cell = CellPool[curr.cellIndex];
|
SetCell(cell, info.dataIndex);
|
||||||
SetCell(cell, curr.dataIndex);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user