mirror of
https://github.com/sinai-dev/UnityExplorer.git
synced 2025-06-22 16:42:38 +08:00
Compare commits
71 Commits
Author | SHA1 | Date | |
---|---|---|---|
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 |
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"]
|
||||
path = lib/Il2CppAssemblyUnhollower
|
||||
url = https://github.com/knah/Il2CppAssemblyUnhollower
|
||||
[submodule "lib/HarmonyX"]
|
||||
path = lib/HarmonyX
|
||||
url = https://github.com/BepInEx/HarmonyX
|
||||
[submodule "lib/mcs-unity"]
|
||||
path = lib/mcs-unity
|
||||
url = https://github.com/sinai-dev/mcs-unity
|
||||
|
119
README.md
119
README.md
@ -3,45 +3,45 @@
|
||||
</p>
|
||||
|
||||
<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 align="center">
|
||||
Supports most Unity games from versions 5.2 to 2020+.
|
||||
✔️ Supports most Unity versions from 5.2 to 2020+ (IL2CPP and Mono).
|
||||
</p>
|
||||
<p align="center">
|
||||
☕ Enjoy this tool? Consider supporting me on <a href="https://ko-fi.com/sinaidev">ko-fi</a>!
|
||||
</p>
|
||||
|
||||
## Releases [](../../releases/latest) [](../../releases) [](../../releases/latest)
|
||||
# Releases [](../../releases)
|
||||
|
||||
| Mod Loader | IL2CPP | Mono |
|
||||
| ----------- | ------ | ---- |
|
||||
| [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) |
|
||||
| [MelonLoader](https://github.com/HerpDerpinstine/MelonLoader) 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 | ✅ [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) |
|
||||
[](../../releases/latest) [](https://github.com/sinai-dev/UnityExplorer/actions) [](../../releases/latest)
|
||||
|
||||
### Known issues
|
||||
* 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.
|
||||
## BepInEx
|
||||
|
||||
## 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.
|
||||
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.
|
||||
<i>Note: BepInEx 6 is obtainable via [BepisBuilds](https://builds.bepis.io/projects/bepinex_be)</i>
|
||||
|
||||
### MelonLoader
|
||||
## MelonLoader
|
||||
|
||||
1. Install [MelonLoader](https://github.com/HerpDerpinstine/MelonLoader) 0.3.1+ for your game (or use `MelonLoader_Legacy` for `0.3.0`). This version can currently be obtained from [here](https://github.com/LavaGang/MelonLoader/actions).
|
||||
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.
|
||||
| Release | IL2CPP | Mono |
|
||||
| ------- | ------ | ---- |
|
||||
| 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).
|
||||
|
||||
@ -50,7 +50,12 @@ 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();`
|
||||
4. Optionally subscribe to the `ExplorerStandalone.OnLog` event to handle logging if you wish
|
||||
|
||||
## Features
|
||||
# Known issues
|
||||
* Any `MissingMethodException` or `NotSupportedException`: please report the issue and provide a copy of your mod loader log and/or Unity log.
|
||||
* In IL2CPP, some IEnumerable and IDictionary types may fail enumeration. Waiting for the Unhollower rewrite to address this any further.
|
||||
* The C# Console's completions have some minor issues such as not suggestion global classes which have no namespace, and erronously suggesting classes from using directives when they shouldn't be suggested. These are issues with mcs itself which I am looking into.
|
||||
|
||||
# Features
|
||||
|
||||
<p align="center">
|
||||
<a href="https://raw.githubusercontent.com/sinai-dev/UnityExplorer/master/img/preview.png">
|
||||
@ -60,48 +65,60 @@ The standalone release can be used with any injector or loader of your choice, b
|
||||
|
||||
### 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 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
|
||||
|
||||
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.
|
||||
|
||||
In the Reflection Inspectors, automatic updating is not enabled by default, and you must press Apply for any changes you make to take effect.
|
||||
* 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.
|
||||
* <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
|
||||
|
||||
The C# Console uses the `Mono.CSharp.Evaluator` to define temporary classes or run immediate REPL code.
|
||||
|
||||
See the "Help" dropdown in the C# console menu for more detailed information.
|
||||
* The C# Console uses the `Mono.CSharp.Evaluator` to define temporary classes or run immediate REPL code.
|
||||
* See the "Help" dropdown in the C# console menu for more detailed information.
|
||||
|
||||
### Mouse-Inspect
|
||||
|
||||
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>UI</b>: uses GraphicRaycasters to find UI objects
|
||||
* 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>UI</b>: uses GraphicRaycasters to find UI objects
|
||||
|
||||
### 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:
|
||||
* BepInEx: `BepInEx\config\com.sinai.unityexplorer.cfg`
|
||||
* MelonLoader: `UserData\MelonPreferences.cfg`
|
||||
* Standalone `{DLL_location}\UnityExplorer\config.ini`
|
||||
# Building
|
||||
|
||||
## 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.
|
||||
1. Open the `src\UnityExplorer.sln` project in Visual Studio.
|
||||
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.
|
||||
3. The DLLs are built to the `Release\` folder in the root of the repository.
|
||||
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.
|
||||
1. Open the `src\UnityExplorer.sln` project.
|
||||
2. Build `mcs`, and if using IL2CPP then build `UnhollowerBaseLib` as well.
|
||||
3. Build the UnityExplorer release(s) you want to use, either by selecting the config as the Active Config, or batch-building.
|
||||
|
||||
## 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.
|
||||
* [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
@ -21,6 +21,7 @@ namespace UnityExplorer.Core.Config
|
||||
public static ConfigElement<bool> Force_Unlock_Mouse;
|
||||
public static ConfigElement<KeyCode> Force_Unlock_Toggle;
|
||||
public static ConfigElement<bool> Aggressive_Mouse_Unlock;
|
||||
public static ConfigElement<bool> Disable_EventSystem_Override;
|
||||
public static ConfigElement<string> Default_Output_Path;
|
||||
public static ConfigElement<bool> Log_Unity_Debug;
|
||||
public static ConfigElement<bool> Hide_On_Startup;
|
||||
@ -93,7 +94,11 @@ namespace UnityExplorer.Core.Config
|
||||
KeyCode.None);
|
||||
|
||||
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);
|
||||
|
||||
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.",
|
||||
1f);
|
||||
|
||||
Reflection_Signature_Blacklist = new ConfigElement<string>("Reflection Signature Blacklist",
|
||||
"Use this to blacklist certain member signatures if they are known to cause a crash or other issues." +
|
||||
"\r\nSeperate signatures with a semicolon ';'.",
|
||||
"DEFAULT");
|
||||
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.\r\n" +
|
||||
"Seperate signatures with a semicolon ';'.\r\n" +
|
||||
"For example, to blacklist Camera.main, you would add 'Camera.main;'",
|
||||
"");
|
||||
|
||||
// Internal configs (panel save data)
|
||||
|
||||
|
@ -32,16 +32,32 @@ namespace UnityExplorer
|
||||
public ExplorerBehaviour(IntPtr ptr) : base(ptr) { }
|
||||
#endif
|
||||
|
||||
private static bool onPostRenderFailed;
|
||||
|
||||
internal void Awake()
|
||||
{
|
||||
try
|
||||
{
|
||||
#if CPP
|
||||
Camera.onPostRender = Camera.onPostRender == null
|
||||
? new Action<Camera>(OnPostRender)
|
||||
: Il2CppSystem.Delegate.Combine(Camera.onPostRender, (Camera.CameraCallback)new Action<Camera>(OnPostRender)).Cast<Camera.CameraCallback>();
|
||||
Camera.onPostRender = Camera.onPostRender == null
|
||||
? new Action<Camera>(OnPostRender)
|
||||
: 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
|
||||
Camera.onPostRender += OnPostRender;
|
||||
Camera.onPostRender += OnPostRender;
|
||||
#endif
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ExplorerCore.LogWarning($"Exception adding onPostRender listener: {ex.ReflectionExToString()}\r\nFalling back to LateUpdate!");
|
||||
onPostRenderFailed = true;
|
||||
}
|
||||
}
|
||||
|
||||
internal void Update()
|
||||
@ -54,7 +70,13 @@ namespace UnityExplorer
|
||||
ExplorerCore.FixedUpdate();
|
||||
}
|
||||
|
||||
internal static void OnPostRender(Camera camera)
|
||||
internal void LateUpdate()
|
||||
{
|
||||
if (onPostRenderFailed)
|
||||
OnPostRender(null);
|
||||
}
|
||||
|
||||
internal static void OnPostRender(Camera _)
|
||||
{
|
||||
ExplorerCore.OnPostRender();
|
||||
}
|
||||
|
@ -37,12 +37,15 @@ namespace UnityExplorer.Core.Input
|
||||
lastVisibleState = Cursor.visible;
|
||||
|
||||
SetupPatches();
|
||||
|
||||
UpdateCursorControl();
|
||||
|
||||
// Hook up config values
|
||||
|
||||
// Force Unlock Mouse
|
||||
Unlock = ConfigManager.Force_Unlock_Mouse.Value;
|
||||
ConfigManager.Force_Unlock_Mouse.OnValueChanged += (bool val) => { Unlock = val; };
|
||||
|
||||
// Aggressive Mouse Unlock
|
||||
if (ConfigManager.Aggressive_Mouse_Unlock.Value)
|
||||
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()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
yield return _waitForEndOfFrame;
|
||||
yield return _waitForEndOfFrame ?? (_waitForEndOfFrame = new WaitForEndOfFrame());
|
||||
|
||||
if (UIManager.ShowMenu)
|
||||
UpdateCursorControl();
|
||||
@ -83,7 +86,7 @@ namespace UnityExplorer.Core.Input
|
||||
Cursor.lockState = CursorLockMode.None;
|
||||
Cursor.visible = true;
|
||||
|
||||
if (UIManager.EventSys)
|
||||
if (!ConfigManager.Disable_EventSystem_Override.Value && UIManager.EventSys)
|
||||
SetEventSystem();
|
||||
}
|
||||
else
|
||||
@ -91,7 +94,7 @@ namespace UnityExplorer.Core.Input
|
||||
Cursor.lockState = lastLockMode;
|
||||
Cursor.visible = lastVisibleState;
|
||||
|
||||
if (UIManager.EventSys)
|
||||
if (!ConfigManager.Disable_EventSystem_Override.Value && UIManager.EventSys)
|
||||
ReleaseEventSystem();
|
||||
}
|
||||
|
||||
@ -160,26 +163,19 @@ namespace UnityExplorer.Core.Input
|
||||
|
||||
public static void Prefix_EventSystem_set_current(ref EventSystem value)
|
||||
{
|
||||
if (!UIManager.EventSys)
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
lastEventSystem = value;
|
||||
lastInputModule = value.currentInputModule;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!settingEventSystem && value != UIManager.EventSys)
|
||||
if (!settingEventSystem && value)
|
||||
{
|
||||
lastEventSystem = value;
|
||||
lastInputModule = value?.currentInputModule;
|
||||
lastInputModule = value.currentInputModule;
|
||||
}
|
||||
|
||||
if (ShouldActuallyUnlock)
|
||||
{
|
||||
value = UIManager.EventSys;
|
||||
value.enabled = true;
|
||||
}
|
||||
if (!UIManager.EventSys)
|
||||
return;
|
||||
|
||||
if (!settingEventSystem && ShouldActuallyUnlock && !ConfigManager.Disable_EventSystem_Override.Value)
|
||||
{
|
||||
value = UIManager.EventSys;
|
||||
value.enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,7 @@ using CppType = Il2CppSystem.Type;
|
||||
using BF = System.Reflection.BindingFlags;
|
||||
using UnityExplorer.Core.Config;
|
||||
using UnhollowerBaseLib.Attributes;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityExplorer
|
||||
{
|
||||
@ -25,10 +26,15 @@ namespace UnityExplorer
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
float start = Time.realtimeSinceStartup;
|
||||
TryLoadGameModules();
|
||||
ExplorerCore.Log($"Loaded Unhollowed modules in {Time.realtimeSinceStartup - start} seconds");
|
||||
|
||||
start = Time.realtimeSinceStartup;
|
||||
BuildDeobfuscationCache();
|
||||
OnTypeLoaded += TryCacheDeobfuscatedType;
|
||||
ExplorerCore.Log($"Setup IL2CPP reflection in {Time.realtimeSinceStartup - start} seconds, " +
|
||||
$"deobfuscated types count: {DeobfuscatedTypes.Count}");
|
||||
}
|
||||
|
||||
#region IL2CPP Extern and pointers
|
||||
@ -44,15 +50,15 @@ namespace UnityExplorer
|
||||
|
||||
public static bool Il2CppTypeNotNull(Type type, out IntPtr il2cppPtr)
|
||||
{
|
||||
if (cppClassPointers.TryGetValue(type.AssemblyQualifiedName, out il2cppPtr))
|
||||
return il2cppPtr != IntPtr.Zero;
|
||||
|
||||
il2cppPtr = (IntPtr)typeof(Il2CppClassPointerStore<>)
|
||||
if (!cppClassPointers.TryGetValue(type.AssemblyQualifiedName, out il2cppPtr))
|
||||
{
|
||||
il2cppPtr = (IntPtr)typeof(Il2CppClassPointerStore<>)
|
||||
.MakeGenericType(new Type[] { type })
|
||||
.GetField("NativeClassPtr", BF.Public | BF.Static)
|
||||
.GetValue(null);
|
||||
|
||||
cppClassPointers.Add(type.AssemblyQualifiedName, il2cppPtr);
|
||||
cppClassPointers.Add(type.AssemblyQualifiedName, il2cppPtr);
|
||||
}
|
||||
|
||||
return il2cppPtr != IntPtr.Zero;
|
||||
}
|
||||
@ -72,9 +78,6 @@ namespace UnityExplorer
|
||||
foreach (var type in asm.TryGetTypes())
|
||||
TryCacheDeobfuscatedType(type);
|
||||
}
|
||||
|
||||
if (DeobfuscatedTypes.Count > 0)
|
||||
ExplorerCore.Log($"Built IL2CPP deobfuscation cache, initial count: {DeobfuscatedTypes.Count}");
|
||||
}
|
||||
|
||||
private static void TryCacheDeobfuscatedType(Type type)
|
||||
@ -237,11 +240,11 @@ namespace UnityExplorer
|
||||
else if (castTo == typeof(string))
|
||||
return UnboxString(obj);
|
||||
|
||||
// Casting from il2cpp object to il2cpp object...
|
||||
|
||||
if (!Il2CppTypeNotNull(castTo, out IntPtr castToPtr))
|
||||
return obj;
|
||||
|
||||
// Casting from il2cpp object to il2cpp object...
|
||||
|
||||
IntPtr castFromPtr = il2cpp_object_get_class(cppObj.Pointer);
|
||||
|
||||
if (!il2cpp_class_is_assignable_from(castToPtr, castFromPtr))
|
||||
@ -510,12 +513,12 @@ namespace UnityExplorer
|
||||
return false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
|
||||
#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,
|
||||
// even from doing "GetParameters()" on the MemberInfo.
|
||||
|
@ -12,7 +12,6 @@ using UnityExplorer.Core.Config;
|
||||
|
||||
namespace UnityExplorer
|
||||
{
|
||||
|
||||
public class ReflectionUtility
|
||||
{
|
||||
public const BF FLAGS = BF.Public | BF.Instance | BF.NonPublic | BF.Static;
|
||||
@ -66,10 +65,14 @@ namespace UnityExplorer
|
||||
|
||||
private static void SetupTypeCache()
|
||||
{
|
||||
float start = Time.realtimeSinceStartup;
|
||||
|
||||
foreach (var asm in AppDomain.CurrentDomain.GetAssemblies())
|
||||
CacheTypes(asm);
|
||||
|
||||
AppDomain.CurrentDomain.AssemblyLoad += AssemblyLoaded;
|
||||
|
||||
ExplorerCore.Log($"Cached AppDomain assemblies in {Time.realtimeSinceStartup - start} seconds");
|
||||
}
|
||||
|
||||
private static void AssemblyLoaded(object sender, AssemblyLoadEventArgs args)
|
||||
@ -434,31 +437,44 @@ namespace UnityExplorer
|
||||
|
||||
#region Reflection Blacklist
|
||||
|
||||
public virtual string DefaultReflectionBlacklist => string.Empty;
|
||||
public virtual string[] DefaultReflectionBlacklist => new string[0];
|
||||
|
||||
public static void LoadBlacklistString(string blacklist)
|
||||
{
|
||||
if (string.Equals(blacklist, "DEFAULT", StringComparison.InvariantCultureIgnoreCase))
|
||||
try
|
||||
{
|
||||
blacklist = Instance.DefaultReflectionBlacklist;
|
||||
ConfigManager.Reflection_Signature_Blacklist.Value = blacklist;
|
||||
ConfigManager.Handler.SaveConfig();
|
||||
if (string.IsNullOrEmpty(blacklist) && !Instance.DefaultReflectionBlacklist.Any())
|
||||
return;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(blacklist))
|
||||
return;
|
||||
|
||||
var sigs = blacklist.Split(';');
|
||||
foreach (var sig in sigs)
|
||||
catch (Exception ex)
|
||||
{
|
||||
var s = sig.Trim();
|
||||
if (string.IsNullOrEmpty(s))
|
||||
continue;
|
||||
if (!currentBlacklist.Contains(s))
|
||||
currentBlacklist.Add(s);
|
||||
ExplorerCore.LogWarning($"Exception setting up reflection blacklist: {ex.ReflectionExToString()}");
|
||||
}
|
||||
|
||||
Mono.CSharp.IL2CPP.Blacklist.SignatureBlacklist = currentBlacklist;
|
||||
}
|
||||
|
||||
public static bool IsBlacklisted(MemberInfo member)
|
||||
|
@ -43,9 +43,9 @@ namespace UnityExplorer.Core.Runtime.Il2Cpp
|
||||
ExplorerCore.LogUnity(condition, type);
|
||||
}
|
||||
|
||||
public override void StartCoroutine(IEnumerator routine)
|
||||
public override void Update()
|
||||
{
|
||||
Il2CppCoroutine.Start(routine);
|
||||
Il2CppCoroutine.Process();
|
||||
}
|
||||
|
||||
internal override void ProcessOnPostRender()
|
||||
@ -53,9 +53,14 @@ namespace UnityExplorer.Core.Runtime.Il2Cpp
|
||||
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)
|
||||
|
@ -4,7 +4,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityExplorer.UI.IValues;
|
||||
using UnityExplorer.UI.CacheObject.IValues;
|
||||
using System.Reflection;
|
||||
using UnityExplorer.UI;
|
||||
#if CPP
|
||||
|
@ -12,6 +12,7 @@ using UnityExplorer.Core.Runtime;
|
||||
using UnityExplorer.Tests;
|
||||
using UnityExplorer.UI;
|
||||
using UnityExplorer.UI.Inspectors;
|
||||
using UnityExplorer.UI.ObjectExplorer;
|
||||
using UnityExplorer.UI.Panels;
|
||||
|
||||
namespace UnityExplorer
|
||||
@ -19,7 +20,7 @@ namespace UnityExplorer
|
||||
public static class ExplorerCore
|
||||
{
|
||||
public const string NAME = "UnityExplorer";
|
||||
public const string VERSION = "4.0.4";
|
||||
public const string VERSION = "4.1.3";
|
||||
public const string AUTHOR = "Sinai";
|
||||
public const string GUID = "com.sinai.unityexplorer";
|
||||
|
||||
|
@ -11,18 +11,17 @@
|
||||
|
||||
<!-- MonoMod for MelonLoader 0.3.0 -->
|
||||
<ItemGroup Condition="'$(IsMelonLoaderLegacy)'=='true'">
|
||||
<InputAssemblies Include="..\lib\HarmonyX\Harmony\bin\Release\net45\Mono.Cecil.dll" />
|
||||
<InputAssemblies Include="..\lib\HarmonyX\Harmony\bin\Release\net45\Mono.Cecil.Mdb.dll" />
|
||||
<InputAssemblies Include="..\lib\HarmonyX\Harmony\bin\Release\net45\Mono.Cecil.Pdb.dll" />
|
||||
<InputAssemblies Include="..\lib\HarmonyX\Harmony\bin\Release\net45\Mono.Cecil.Rocks.dll" />
|
||||
<InputAssemblies Include="..\lib\HarmonyX\Harmony\bin\Release\net45\MonoMod.RuntimeDetour.dll" />
|
||||
<InputAssemblies Include="..\lib\HarmonyX\Harmony\bin\Release\net45\MonoMod.Utils.dll" />
|
||||
<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>
|
||||
<ReferenceFolders Include="..\lib\" />
|
||||
<ReferenceFolders Include="..\lib\HarmonyX\Harmony\bin\Release\net35\" />
|
||||
<ReferenceFolders Include="packages\HarmonyX.2.4.2\lib\net35\" />
|
||||
<ReferenceFolders Include="..\lib\BepInEx.6.IL2CPP\" />
|
||||
<ReferenceFolders Include="..\lib\BepInEx.6.Mono\" />
|
||||
<ReferenceFolders Include="..\lib\BepInEx.5\" />
|
||||
@ -36,7 +35,8 @@
|
||||
LibraryPath="@(ReferenceFolders)"
|
||||
InputAssemblies="@(InputAssemblies)"
|
||||
TargetKind="Dll"
|
||||
OutputFile="$(OutputPath)$(AssemblyName).dll" />
|
||||
OutputFile="$(OutputPath)$(AssemblyName).dll"
|
||||
/>
|
||||
</Target>
|
||||
|
||||
</Project>
|
Binary file not shown.
@ -41,7 +41,7 @@ namespace UnityExplorer.UI.CSConsole
|
||||
suggestions.Clear();
|
||||
|
||||
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,
|
||||
// or if the next character (if it exists) is not whitespace,
|
||||
@ -55,17 +55,18 @@ namespace UnityExplorer.UI.CSConsole
|
||||
}
|
||||
|
||||
// get the current composition string (from caret back to last delimiter)
|
||||
while (start > 0)
|
||||
while (startIdx > 0)
|
||||
{
|
||||
start--;
|
||||
char c = InputField.Text[start];
|
||||
if (delimiters.Contains(c))
|
||||
startIdx--;
|
||||
char c = InputField.Text[startIdx];
|
||||
if (delimiters.Contains(c) || char.IsWhiteSpace(c))
|
||||
{
|
||||
start++;
|
||||
startIdx++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
string input = InputField.Text.Substring(start, caret - start + 1);
|
||||
string input = InputField.Text.Substring(startIdx, caret - startIdx + 1);
|
||||
|
||||
|
||||
// Get MCS completions
|
||||
|
||||
|
@ -12,6 +12,7 @@ using UnityExplorer.Core.Input;
|
||||
using UnityExplorer.UI.Panels;
|
||||
using UnityExplorer.UI.Widgets.AutoComplete;
|
||||
using System.Reflection;
|
||||
using Mono.CSharp;
|
||||
|
||||
namespace UnityExplorer.UI.CSConsole
|
||||
{
|
||||
@ -150,15 +151,16 @@ namespace UnityExplorer.UI.CSConsole
|
||||
|
||||
try
|
||||
{
|
||||
// Try to "Compile" the code (tries to interpret it as REPL)
|
||||
var evaluation = Evaluator.Compile(input);
|
||||
if (evaluation != null)
|
||||
// Compile the code. If it returned a CompiledMethod, it is REPL.
|
||||
CompiledMethod repl = Evaluator.Compile(input);
|
||||
|
||||
if (repl != null)
|
||||
{
|
||||
// Valid REPL, we have a delegate to the evaluation.
|
||||
try
|
||||
{
|
||||
object ret = null;
|
||||
evaluation.Invoke(ref ret);
|
||||
repl.Invoke(ref ret);
|
||||
var result = ret?.ToString();
|
||||
if (!string.IsNullOrEmpty(result))
|
||||
ExplorerCore.Log($"Invoked REPL, result: {ret}");
|
||||
@ -172,9 +174,7 @@ namespace UnityExplorer.UI.CSConsole
|
||||
}
|
||||
else
|
||||
{
|
||||
// The input was not recognized as an evaluation. Compile the code.
|
||||
|
||||
Evaluator.Run(input);
|
||||
// The compiled code was not REPL, so it was a using directive or it defined classes.
|
||||
|
||||
string output = ScriptEvaluator._textWriter.ToString();
|
||||
var outputSplit = output.Split('\n');
|
||||
@ -231,23 +231,32 @@ namespace UnityExplorer.UI.CSConsole
|
||||
previousInput = value;
|
||||
|
||||
if (EnableSuggestions && AutoCompleteModal.CheckEnter(Completer))
|
||||
{
|
||||
OnAutocompleteEnter();
|
||||
}
|
||||
else if (!settingCaretCoroutine)
|
||||
{
|
||||
if (EnableSuggestions)
|
||||
Completer.CheckAutocompletes();
|
||||
|
||||
if (!settingCaretCoroutine)
|
||||
{
|
||||
if (EnableAutoIndent)
|
||||
DoAutoIndent();
|
||||
}
|
||||
|
||||
HighlightVisibleInput();
|
||||
var inStringOrComment = HighlightVisibleInput();
|
||||
|
||||
if (!settingCaretCoroutine)
|
||||
{
|
||||
if (EnableSuggestions)
|
||||
{
|
||||
if (inStringOrComment)
|
||||
AutoCompleteModal.Instance.ReleaseOwnership(Completer);
|
||||
else
|
||||
Completer.CheckAutocompletes();
|
||||
}
|
||||
}
|
||||
|
||||
UpdateCaret(out _);
|
||||
}
|
||||
|
||||
private static float timeOfLastCtrlR;
|
||||
|
||||
public static void Update()
|
||||
{
|
||||
if (SRENotSupported)
|
||||
@ -255,22 +264,24 @@ namespace UnityExplorer.UI.CSConsole
|
||||
|
||||
UpdateCaret(out bool caretMoved);
|
||||
|
||||
if (!settingCaretCoroutine && EnableSuggestions && AutoCompleteModal.CheckEscape(Completer))
|
||||
if (!settingCaretCoroutine && EnableSuggestions)
|
||||
{
|
||||
OnAutocompleteEscaped();
|
||||
return;
|
||||
}
|
||||
if (AutoCompleteModal.CheckEscape(Completer))
|
||||
{
|
||||
OnAutocompleteEscaped();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!settingCaretCoroutine && EnableSuggestions && caretMoved)
|
||||
{
|
||||
AutoCompleteModal.Instance.ReleaseOwnership(Completer);
|
||||
//Completer.CheckAutocompletes();
|
||||
if (caretMoved)
|
||||
AutoCompleteModal.Instance.ReleaseOwnership(Completer);
|
||||
}
|
||||
|
||||
if (EnableCtrlRShortcut
|
||||
&& (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);
|
||||
}
|
||||
}
|
||||
@ -368,7 +379,10 @@ namespace UnityExplorer.UI.CSConsole
|
||||
|
||||
#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;
|
||||
int endIdx = Input.Text.Length - 1;
|
||||
@ -406,7 +420,8 @@ namespace UnityExplorer.UI.CSConsole
|
||||
}
|
||||
|
||||
// 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);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
@ -14,6 +14,7 @@ namespace UnityExplorer.UI.CSConsole
|
||||
public int startIndex;
|
||||
public int endIndex;
|
||||
public string htmlColorTag;
|
||||
public bool isStringOrComment;
|
||||
}
|
||||
|
||||
public class LexerBuilder
|
||||
@ -82,8 +83,10 @@ namespace UnityExplorer.UI.CSConsole
|
||||
/// <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>
|
||||
/// <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)
|
||||
return input;
|
||||
|
||||
@ -105,12 +108,14 @@ namespace UnityExplorer.UI.CSConsole
|
||||
|
||||
// append the highlighted match
|
||||
sb.Append(match.htmlColorTag);
|
||||
|
||||
for (int i = match.startIndex; i <= match.endIndex && i <= currentEndIdx; i++)
|
||||
sb.Append(input[i]);
|
||||
|
||||
sb.Append(SignatureHighlighter.CLOSE_COLOR);
|
||||
|
||||
// check caretIdx to determine inStringOrComment state
|
||||
if (caretIdx >= match.startIndex && (caretIdx <= match.endIndex || (caretIdx >= input.Length && match.endIndex >= input.Length - 1)))
|
||||
caretInStringOrComment = match.isStringOrComment;
|
||||
|
||||
// update the last unhighlighted start index
|
||||
lastUnhighlighted = match.endIndex + 1;
|
||||
}
|
||||
@ -150,6 +155,7 @@ namespace UnityExplorer.UI.CSConsole
|
||||
startIndex = startIndex,
|
||||
endIndex = CommittedIndex,
|
||||
htmlColorTag = lexer.ColorTag,
|
||||
isStringOrComment = lexer is StringLexer || lexer is CommentLexer,
|
||||
};
|
||||
break;
|
||||
}
|
||||
|
@ -41,6 +41,10 @@ namespace UnityExplorer.UI.CSConsole.Lexers
|
||||
while (!lexer.EndOfInput && char.IsLetter(lexer.PeekNext()))
|
||||
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 (!lexer.EndOfInput)
|
||||
|
@ -11,7 +11,7 @@ namespace UnityExplorer.UI.CSConsole.Lexers
|
||||
protected override Color HighlightColor => new Color(0.6f, 0.6f, 0.6f);
|
||||
|
||||
// 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);
|
||||
|
||||
|
@ -3,8 +3,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityExplorer.UI.CacheObject.Views;
|
||||
using UnityExplorer.UI.IValues;
|
||||
using UnityExplorer.UI.Utility;
|
||||
using UnityExplorer.UI.CacheObject.IValues;
|
||||
|
||||
namespace UnityExplorer.UI.CacheObject
|
||||
{
|
||||
|
@ -3,7 +3,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityExplorer.UI.CacheObject.Views;
|
||||
using UnityExplorer.UI.IValues;
|
||||
using UnityExplorer.UI.CacheObject.IValues;
|
||||
|
||||
namespace UnityExplorer.UI.CacheObject
|
||||
{
|
||||
|
@ -7,8 +7,7 @@ using UnityEngine;
|
||||
using UnityExplorer.Core.Runtime;
|
||||
using UnityExplorer.UI.CacheObject.Views;
|
||||
using UnityExplorer.UI.Inspectors;
|
||||
using UnityExplorer.UI.ObjectPool;
|
||||
using UnityExplorer.UI.Utility;
|
||||
using UnityExplorer.UI.Models;
|
||||
|
||||
namespace UnityExplorer.UI.CacheObject
|
||||
{
|
||||
|
@ -8,9 +8,8 @@ using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.Core.Runtime;
|
||||
using UnityExplorer.UI.CacheObject.Views;
|
||||
using UnityExplorer.UI.IValues;
|
||||
using UnityExplorer.UI.ObjectPool;
|
||||
using UnityExplorer.UI.Utility;
|
||||
using UnityExplorer.UI.CacheObject.IValues;
|
||||
using UnityExplorer.UI.Models;
|
||||
|
||||
namespace UnityExplorer.UI.CacheObject
|
||||
{
|
||||
|
@ -28,10 +28,11 @@ namespace UnityExplorer.UI.CacheObject
|
||||
{
|
||||
try
|
||||
{
|
||||
object ret;
|
||||
if (HasArguments)
|
||||
return PropertyInfo.GetValue(DeclaringInstance, this.Evaluator.TryParseArguments());
|
||||
|
||||
var ret = PropertyInfo.GetValue(DeclaringInstance, null);
|
||||
ret = PropertyInfo.GetValue(DeclaringInstance, this.Evaluator.TryParseArguments());
|
||||
else
|
||||
ret = PropertyInfo.GetValue(DeclaringInstance, null);
|
||||
HadException = false;
|
||||
LastException = null;
|
||||
return ret;
|
||||
|
@ -6,7 +6,7 @@ using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.UI.CacheObject;
|
||||
|
||||
namespace UnityExplorer.UI.IValues
|
||||
namespace UnityExplorer.UI.CacheObject.IValues
|
||||
{
|
||||
public class InteractiveColor : InteractiveValue
|
||||
{
|
@ -9,10 +9,9 @@ using UnityExplorer.UI.CacheObject;
|
||||
using UnityExplorer.UI.CacheObject.Views;
|
||||
using UnityExplorer.UI.Inspectors;
|
||||
using UnityExplorer.UI.Panels;
|
||||
using UnityExplorer.UI.Utility;
|
||||
using UnityExplorer.UI.Widgets;
|
||||
|
||||
namespace UnityExplorer.UI.IValues
|
||||
namespace UnityExplorer.UI.CacheObject.IValues
|
||||
{
|
||||
public class InteractiveDictionary : InteractiveValue, ICellPoolDataSource<CacheKeyValuePairCell>, ICacheObjectController
|
||||
{
|
@ -7,7 +7,7 @@ using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.UI.CacheObject;
|
||||
|
||||
namespace UnityExplorer.UI.IValues
|
||||
namespace UnityExplorer.UI.CacheObject.IValues
|
||||
{
|
||||
public class InteractiveEnum : InteractiveValue
|
||||
{
|
@ -9,10 +9,9 @@ using UnityExplorer.UI.CacheObject;
|
||||
using UnityExplorer.UI.CacheObject.Views;
|
||||
using UnityExplorer.UI.Inspectors;
|
||||
using UnityExplorer.UI.Panels;
|
||||
using UnityExplorer.UI.Utility;
|
||||
using UnityExplorer.UI.Widgets;
|
||||
|
||||
namespace UnityExplorer.UI.IValues
|
||||
namespace UnityExplorer.UI.CacheObject.IValues
|
||||
{
|
||||
public class InteractiveList : InteractiveValue, ICellPoolDataSource<CacheListEntryCell>, ICacheObjectController
|
||||
{
|
@ -9,7 +9,7 @@ using UnityExplorer.Core.Config;
|
||||
using UnityExplorer.UI.CacheObject;
|
||||
using UnityExplorer.UI.Widgets;
|
||||
|
||||
namespace UnityExplorer.UI.IValues
|
||||
namespace UnityExplorer.UI.CacheObject.IValues
|
||||
{
|
||||
public class InteractiveString : InteractiveValue
|
||||
{
|
@ -5,9 +5,9 @@ using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.UI.CacheObject;
|
||||
using UnityExplorer.UI.ObjectPool;
|
||||
using UnityExplorer.UI.Models;
|
||||
|
||||
namespace UnityExplorer.UI.IValues
|
||||
namespace UnityExplorer.UI.CacheObject.IValues
|
||||
{
|
||||
public abstract class InteractiveValue : IPooledObject
|
||||
{
|
@ -6,9 +6,8 @@ using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.UI.CacheObject;
|
||||
using UnityExplorer.UI.Utility;
|
||||
|
||||
namespace UnityExplorer.UI.IValues
|
||||
namespace UnityExplorer.UI.CacheObject.IValues
|
||||
{
|
||||
public class InteractiveValueStruct : InteractiveValue
|
||||
{
|
@ -5,7 +5,7 @@ using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.UI.Inspectors;
|
||||
using UnityExplorer.UI.IValues;
|
||||
using UnityExplorer.UI.CacheObject.IValues;
|
||||
using UnityExplorer.UI.Widgets;
|
||||
|
||||
namespace UnityExplorer.UI.CacheObject.Views
|
||||
|
@ -4,7 +4,7 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.UI.IValues;
|
||||
using UnityExplorer.UI.CacheObject.IValues;
|
||||
|
||||
namespace UnityExplorer.UI.CacheObject.Views
|
||||
{
|
||||
|
@ -5,9 +5,7 @@ using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.UI.Inspectors;
|
||||
using UnityExplorer.UI.IValues;
|
||||
using UnityExplorer.UI.ObjectPool;
|
||||
using UnityExplorer.UI.Utility;
|
||||
using UnityExplorer.UI.CacheObject.IValues;
|
||||
using UnityExplorer.UI.Widgets;
|
||||
|
||||
namespace UnityExplorer.UI.CacheObject.Views
|
||||
|
@ -5,8 +5,7 @@ using System.Reflection;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.UI.ObjectPool;
|
||||
using UnityExplorer.UI.Utility;
|
||||
using UnityExplorer.UI.Models;
|
||||
using UnityExplorer.UI.Widgets.AutoComplete;
|
||||
|
||||
namespace UnityExplorer.UI.CacheObject.Views
|
||||
|
@ -6,9 +6,8 @@ using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.Core.Input;
|
||||
using UnityExplorer.UI.ObjectPool;
|
||||
using UnityExplorer.UI.Models;
|
||||
using UnityExplorer.UI.Panels;
|
||||
using UnityExplorer.UI.Utility;
|
||||
using UnityExplorer.UI.Widgets;
|
||||
using UnityExplorer.UI.Widgets.AutoComplete;
|
||||
|
||||
@ -64,7 +63,7 @@ namespace UnityExplorer.UI.Inspectors
|
||||
addCompInput.Text = "";
|
||||
|
||||
TransformTree.Clear();
|
||||
ComponentList.Clear();
|
||||
UpdateComponents();
|
||||
}
|
||||
|
||||
public override void CloseInspector()
|
||||
@ -113,6 +112,9 @@ namespace UnityExplorer.UI.Inspectors
|
||||
|
||||
private IEnumerable<GameObject> GetTransformEntries()
|
||||
{
|
||||
if (!GOTarget)
|
||||
return Enumerable.Empty<GameObject>();
|
||||
|
||||
cachedChildren.Clear();
|
||||
for (int i = 0; i < GOTarget.transform.childCount; i++)
|
||||
cachedChildren.Add(GOTarget.transform.GetChild(i).gameObject);
|
||||
@ -125,10 +127,21 @@ namespace UnityExplorer.UI.Inspectors
|
||||
private readonly List<bool> behaviourEnabledStates = new List<bool>();
|
||||
|
||||
// ComponentList.GetRootEntriesMethod
|
||||
private List<Component> GetComponentEntries() => componentEntries;
|
||||
private List<Component> GetComponentEntries() => GOTarget ? componentEntries : Enumerable.Empty<Component>().ToList();
|
||||
|
||||
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.
|
||||
var comps = GOTarget.GetComponents<Component>();
|
||||
var behaviours = GOTarget.GetComponents<Behaviour>();
|
||||
@ -221,8 +234,8 @@ namespace UnityExplorer.UI.Inspectors
|
||||
|
||||
public override GameObject CreateContent(GameObject parent)
|
||||
{
|
||||
UIRoot = UIFactory.CreateVerticalGroup(Pool<GameObjectInspector>.Instance.InactiveHolder,
|
||||
"GameObjectInspector", true, false, true, true, 5, new Vector4(4, 4, 4, 4), new Color(0.065f, 0.065f, 0.065f));
|
||||
UIRoot = UIFactory.CreateVerticalGroup(parent, "GameObjectInspector", true, false, true, true, 5,
|
||||
new Vector4(4, 4, 4, 4), new Color(0.065f, 0.065f, 0.065f));
|
||||
|
||||
var scrollObj = UIFactory.CreateScrollView(UIRoot, "GameObjectInspector", out Content, out var scrollbar,
|
||||
new Color(0.065f, 0.065f, 0.065f));
|
||||
|
@ -21,7 +21,8 @@ namespace UnityExplorer.UI.Inspectors
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
this.currentEntries.Clear();
|
||||
RefreshData();
|
||||
ScrollPool.Refresh(true, true);
|
||||
}
|
||||
|
||||
private bool CheckShouldDisplay(Component _, string __) => true;
|
||||
|
@ -232,6 +232,12 @@ namespace UnityExplorer.UI.Inspectors
|
||||
}
|
||||
}
|
||||
|
||||
private void OnExploreButtonClicked()
|
||||
{
|
||||
var panel = UIManager.GetPanel<Panels.ObjectExplorerPanel>(UIManager.Panels.ObjectExplorer);
|
||||
panel.SceneExplorer.JumpToTransform(this.Parent.GOTarget.transform);
|
||||
}
|
||||
|
||||
private void OnLayerDropdownChanged(int value)
|
||||
{
|
||||
GOTarget.layer = value;
|
||||
@ -533,6 +539,12 @@ namespace UnityExplorer.UI.Inspectors
|
||||
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(thirdrow, false, false, true, true, 5, 0, 0, 0, 0, default);
|
||||
UIFactory.SetLayoutElement(thirdrow, minHeight: 25, flexibleWidth: 9999);
|
||||
|
||||
// Inspect in Explorer button
|
||||
var explorerBtn = UIFactory.CreateButton(thirdrow, "ExploreBtn", "Show in Explorer", new Color(0.15f, 0.15f, 0.15f));
|
||||
UIFactory.SetLayoutElement(explorerBtn.Component.gameObject, minHeight: 25, minWidth: 100);
|
||||
explorerBtn.ButtonText.fontSize = 12;
|
||||
explorerBtn.OnClick += OnExploreButtonClicked;
|
||||
|
||||
// Scene
|
||||
var sceneLabel = UIFactory.CreateLabel(thirdrow, "SceneLabel", "Scene:", TextAnchor.MiddleLeft, Color.grey);
|
||||
UIFactory.SetLayoutElement(sceneLabel.gameObject, minHeight: 25, minWidth: 50);
|
||||
@ -547,7 +559,7 @@ namespace UnityExplorer.UI.Inspectors
|
||||
UIFactory.SetLayoutElement(layerLabel.gameObject, minHeight: 25, minWidth: 50);
|
||||
|
||||
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;
|
||||
if (layerToNames == null)
|
||||
GetLayerNames();
|
||||
|
@ -64,13 +64,12 @@ namespace UnityExplorer.UI.Inspectors
|
||||
internal static Camera MainCamera;
|
||||
internal static GraphicRaycaster[] graphicRaycasters;
|
||||
|
||||
|
||||
public void StartInspect(MouseInspectMode mode)
|
||||
{
|
||||
MainCamera = Camera.main;
|
||||
if (!MainCamera)
|
||||
return;
|
||||
|
||||
return;
|
||||
|
||||
PanelDragger.ForceEnd();
|
||||
|
||||
Mode = mode;
|
||||
@ -94,8 +93,14 @@ namespace UnityExplorer.UI.Inspectors
|
||||
public void StopInspect()
|
||||
{
|
||||
Inspecting = false;
|
||||
|
||||
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);
|
||||
|
||||
if (Mode == MouseInspectMode.UI)
|
||||
|
@ -4,7 +4,7 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.UI.ObjectPool;
|
||||
using UnityExplorer.UI.Models;
|
||||
using UnityExplorer.UI.Panels;
|
||||
|
||||
namespace UnityExplorer.UI.Inspectors
|
||||
|
@ -7,7 +7,7 @@ using UnityEngine.UI;
|
||||
using UnityExplorer.UI;
|
||||
using UnityExplorer.UI.CacheObject;
|
||||
using UnityExplorer.UI.Inspectors;
|
||||
using UnityExplorer.UI.ObjectPool;
|
||||
using UnityExplorer.UI.Models;
|
||||
using UnityExplorer.UI.Panels;
|
||||
|
||||
namespace UnityExplorer
|
||||
|
@ -4,7 +4,7 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.UI.ObjectPool;
|
||||
using UnityExplorer.UI.Models;
|
||||
using UnityExplorer.UI.Widgets;
|
||||
|
||||
namespace UnityExplorer.UI.Inspectors
|
||||
|
@ -12,9 +12,7 @@ using UnityExplorer.Core.Config;
|
||||
using UnityExplorer.Core.Runtime;
|
||||
using UnityExplorer.UI.CacheObject;
|
||||
using UnityExplorer.UI.CacheObject.Views;
|
||||
using UnityExplorer.UI.ObjectPool;
|
||||
using UnityExplorer.UI.Panels;
|
||||
using UnityExplorer.UI.Utility;
|
||||
using UnityExplorer.UI.Widgets;
|
||||
|
||||
namespace UnityExplorer.UI.Inspectors
|
||||
@ -482,7 +480,7 @@ namespace UnityExplorer.UI.Inspectors
|
||||
|
||||
private void SetUnityTargets()
|
||||
{
|
||||
if (!typeof(UnityEngine.Object).IsAssignableFrom(TargetType))
|
||||
if (StaticOnly || !typeof(UnityEngine.Object).IsAssignableFrom(TargetType))
|
||||
{
|
||||
unityObjectRow.SetActive(false);
|
||||
textureViewer.SetActive(false);
|
||||
@ -619,12 +617,15 @@ namespace UnityExplorer.UI.Inspectors
|
||||
|
||||
// Actual texture viewer
|
||||
|
||||
var imageObj = UIFactory.CreateUIObject("TextureViewerImage", textureViewer);
|
||||
textureImage = imageObj.AddComponent<Image>();
|
||||
textureImageLayout = textureImage.gameObject.AddComponent<LayoutElement>();
|
||||
var imageViewport = UIFactory.CreateVerticalGroup(textureViewer, "Viewport", false, false, true, true);
|
||||
imageViewport.GetComponent<Image>().color = Color.white;
|
||||
imageViewport.AddComponent<Mask>().showMaskGraphic = false;
|
||||
|
||||
var imageObj = UIFactory.CreateUIObject("Image", imageViewport);
|
||||
var fitter = imageObj.AddComponent<ContentSizeFitter>();
|
||||
fitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||||
textureImage = imageObj.AddComponent<Image>();
|
||||
textureImageLayout = UIFactory.SetLayoutElement(imageObj, flexibleWidth: 9999, flexibleHeight: 9999);
|
||||
|
||||
textureViewer.SetActive(false);
|
||||
}
|
||||
|
@ -50,8 +50,8 @@ namespace UnityExplorer.UI
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -4,11 +4,8 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.UI.Inspectors;
|
||||
using UnityExplorer.UI.Models;
|
||||
using UnityExplorer.UI.ObjectPool;
|
||||
using UnityExplorer.UI.Panels;
|
||||
using UnityExplorer.UI.Utility;
|
||||
using UnityExplorer.UI.Widgets;
|
||||
using UnityExplorer.UI.Widgets.AutoComplete;
|
||||
|
||||
|
@ -39,7 +39,7 @@ namespace UnityExplorer.UI.ObjectExplorer
|
||||
|
||||
private GameObject refreshRow;
|
||||
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;
|
||||
|
||||
@ -58,6 +58,26 @@ namespace UnityExplorer.UI.ObjectExplorer
|
||||
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)
|
||||
{
|
||||
if (value < 0 || SceneHandler.LoadedScenes.Count <= value)
|
||||
@ -71,12 +91,12 @@ namespace UnityExplorer.UI.ObjectExplorer
|
||||
|
||||
private void SceneHandler_OnInspectedSceneChanged(Scene scene)
|
||||
{
|
||||
if (!sceneToDropdownOption.ContainsKey(scene.handle))
|
||||
if (!sceneToDropdownOption.ContainsKey(scene))
|
||||
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);
|
||||
if (sceneDropdown.value != idx)
|
||||
sceneDropdown.value = idx;
|
||||
@ -114,7 +134,7 @@ namespace UnityExplorer.UI.ObjectExplorer
|
||||
|
||||
var option = new Dropdown.OptionData(name);
|
||||
sceneDropdown.options.Add(option);
|
||||
sceneToDropdownOption.Add(scene.handle, option);
|
||||
sceneToDropdownOption.Add(scene, option);
|
||||
}
|
||||
}
|
||||
|
||||
@ -122,7 +142,7 @@ namespace UnityExplorer.UI.ObjectExplorer
|
||||
{
|
||||
if ((!string.IsNullOrEmpty(input) && !Tree.Filtering) || (string.IsNullOrEmpty(input) && Tree.Filtering))
|
||||
{
|
||||
Tree.displayedObjects.Clear();
|
||||
Tree.cachedTransforms.Clear();
|
||||
}
|
||||
|
||||
Tree.CurrentFilter = input;
|
||||
|
@ -6,7 +6,7 @@ using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
namespace UnityExplorer.Core
|
||||
namespace UnityExplorer.UI.ObjectExplorer
|
||||
{
|
||||
public static class SceneHandler
|
||||
{
|
||||
@ -15,16 +15,16 @@ namespace UnityExplorer.Core
|
||||
/// </summary>
|
||||
public static Scene? SelectedScene
|
||||
{
|
||||
get => m_selectedScene;
|
||||
get => selectedScene;
|
||||
internal set
|
||||
{
|
||||
if (m_selectedScene != null && m_selectedScene?.handle == value?.handle)
|
||||
if (selectedScene != null && selectedScene == value)
|
||||
return;
|
||||
m_selectedScene = value;
|
||||
OnInspectedSceneChanged?.Invoke((Scene)m_selectedScene);
|
||||
selectedScene = value;
|
||||
OnInspectedSceneChanged?.Invoke((Scene)selectedScene);
|
||||
}
|
||||
}
|
||||
private static Scene? m_selectedScene;
|
||||
private static Scene? selectedScene;
|
||||
|
||||
/// <summary>
|
||||
/// The GameObjects in the currently inspected scene.
|
||||
@ -37,6 +37,7 @@ namespace UnityExplorer.Core
|
||||
/// </summary>
|
||||
public static ReadOnlyCollection<Scene> LoadedScenes => new ReadOnlyCollection<Scene>(allLoadedScenes);
|
||||
private static readonly List<Scene> allLoadedScenes = new List<Scene>();
|
||||
private static HashSet<Scene> previousLoadedScenes;
|
||||
|
||||
/// <summary>
|
||||
/// 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;
|
||||
|
||||
/// <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>
|
||||
public static int LoadedSceneCount => SceneManager.sceneCount + 2;
|
||||
|
||||
@ -82,7 +83,7 @@ namespace UnityExplorer.Core
|
||||
}
|
||||
private static GameObject dontDestroyObject;
|
||||
|
||||
public static bool InspectingAssetScene => !SelectedScene?.IsValid() ?? false;
|
||||
public static bool InspectingAssetScene => SelectedScene.HasValue && SelectedScene.Value == default;
|
||||
|
||||
internal static void Init()
|
||||
{
|
||||
@ -110,17 +111,9 @@ namespace UnityExplorer.Core
|
||||
|
||||
internal static void Update()
|
||||
{
|
||||
int curHandle = SelectedScene?.handle ?? -1;
|
||||
// DontDestroyOnLoad always exists, so default to true if our curHandle is that handle.
|
||||
// otherwise we will check while iterating.
|
||||
bool inspectedExists = curHandle == DontDestroyHandle || curHandle == 0;
|
||||
|
||||
// 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));
|
||||
// check if the loaded scenes changed. always confirm DontDestroy / HideAndDontSave
|
||||
int confirmedCount = 2;
|
||||
bool inspectedExists = SelectedScene == DontDestroyScene || (SelectedScene.HasValue && SelectedScene.Value == default);
|
||||
|
||||
allLoadedScenes.Clear();
|
||||
|
||||
@ -130,20 +123,22 @@ namespace UnityExplorer.Core
|
||||
if (scene == default || !scene.isLoaded)
|
||||
continue;
|
||||
|
||||
// If no changes yet, ensure the previous list contained this handle.
|
||||
if (!anyChange && !previousHandles.Contains(scene.handle))
|
||||
anyChange = true;
|
||||
// If no changes yet, ensure the previous list contained the scene
|
||||
if (previousLoadedScenes != null && previousLoadedScenes.Contains(scene))
|
||||
confirmedCount++;
|
||||
|
||||
// If we have not yet confirmed inspectedExists, check if this scene is our currently inspected one.
|
||||
if (curHandle != -1 && !inspectedExists && scene.handle == curHandle)
|
||||
if (!inspectedExists && scene == SelectedScene)
|
||||
inspectedExists = true;
|
||||
|
||||
allLoadedScenes.Add(scene);
|
||||
}
|
||||
|
||||
// Always add the DontDestroyOnLoad scene and the "none" scene.
|
||||
bool anyChange = confirmedCount != allLoadedScenes.Count;
|
||||
|
||||
allLoadedScenes.Add(DontDestroyScene);
|
||||
allLoadedScenes.Add(default);
|
||||
previousLoadedScenes = new HashSet<Scene>(allLoadedScenes);
|
||||
|
||||
// Default to first scene if none selected or previous selection no longer exists.
|
||||
if (!inspectedExists)
|
||||
@ -163,14 +158,14 @@ namespace UnityExplorer.Core
|
||||
else
|
||||
{
|
||||
var allObjects = RuntimeProvider.Instance.FindObjectsOfTypeAll(typeof(GameObject));
|
||||
var list = new List<GameObject>();
|
||||
var objects = new List<GameObject>();
|
||||
foreach (var obj in allObjects)
|
||||
{
|
||||
var go = obj.TryCast<GameObject>();
|
||||
if (go.transform.parent == null && !go.scene.IsValid())
|
||||
list.Add(go);
|
||||
objects.Add(go);
|
||||
}
|
||||
rootObjects = list.ToArray();
|
||||
rootObjects = objects.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
@ -58,39 +58,22 @@ namespace UnityExplorer.UI.ObjectExplorer
|
||||
{
|
||||
var results = new List<object>();
|
||||
|
||||
Type searchType;
|
||||
switch (context)
|
||||
Type searchType = null;
|
||||
if (!string.IsNullOrEmpty(customTypeInput))
|
||||
{
|
||||
//case SearchContext.GameObject:
|
||||
// searchType = typeof(GameObject);
|
||||
// break;
|
||||
|
||||
case SearchContext.UnityObject:
|
||||
default:
|
||||
|
||||
if (!string.IsNullOrEmpty(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 (ReflectionUtility.GetTypeByName(customTypeInput) is Type customType)
|
||||
{
|
||||
if (typeof(UnityEngine.Object).IsAssignableFrom(customType))
|
||||
searchType = customType;
|
||||
else
|
||||
ExplorerCore.LogWarning($"Custom type '{customType.FullName}' is not assignable from UnityEngine.Object!");
|
||||
}
|
||||
else
|
||||
ExplorerCore.LogWarning($"Could not find any type by name '{customTypeInput}'!");
|
||||
}
|
||||
|
||||
|
||||
if (searchType == null)
|
||||
return results;
|
||||
searchType = typeof(UnityEngine.Object);
|
||||
|
||||
var allObjects = RuntimeProvider.Instance.FindObjectsOfTypeAll(searchType);
|
||||
|
||||
@ -100,7 +83,7 @@ namespace UnityExplorer.UI.ObjectExplorer
|
||||
if (!string.IsNullOrEmpty(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)
|
||||
{
|
||||
@ -108,13 +91,21 @@ namespace UnityExplorer.UI.ObjectExplorer
|
||||
if (!string.IsNullOrEmpty(nameFilter) && !obj.name.ContainsIgnoreCase(nameFilter))
|
||||
continue;
|
||||
|
||||
if (canGetGameObject)
|
||||
{
|
||||
var go = searchType == typeof(GameObject)
|
||||
? obj.TryCast<GameObject>()
|
||||
: obj.TryCast<Component>().gameObject;
|
||||
GameObject go = null;
|
||||
var type = obj.GetActualType();
|
||||
|
||||
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
|
||||
if (sceneFilter != SceneFilter.Any)
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
@ -7,7 +7,7 @@ using UnityEngine.EventSystems;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.Core.Config;
|
||||
using UnityExplorer.UI.CSConsole;
|
||||
using UnityExplorer.UI.Utility;
|
||||
using UnityExplorer.UI.Widgets;
|
||||
|
||||
namespace UnityExplorer.UI.Panels
|
||||
{
|
||||
|
@ -12,7 +12,6 @@ using UnityExplorer.Core;
|
||||
using UnityExplorer.Core.Config;
|
||||
using UnityExplorer.UI.Models;
|
||||
using UnityExplorer.UI.ObjectExplorer;
|
||||
using UnityExplorer.UI.Utility;
|
||||
using UnityExplorer.UI.Widgets;
|
||||
|
||||
namespace UnityExplorer.UI.Panels
|
||||
|
@ -8,7 +8,6 @@ using UnityEngine.UI;
|
||||
using UnityExplorer.Core.Config;
|
||||
using UnityExplorer.Core.Input;
|
||||
using UnityExplorer.UI.Models;
|
||||
using UnityExplorer.UI.Utility;
|
||||
using UnityExplorer.UI.Widgets;
|
||||
|
||||
namespace UnityExplorer.UI.Panels
|
||||
@ -226,7 +225,7 @@ namespace UnityExplorer.UI.Panels
|
||||
{
|
||||
// create navbar button
|
||||
|
||||
NavButton = UIFactory.CreateButton(UIManager.NavbarButtonHolder, $"Button_{PanelType}", Name);
|
||||
NavButton = UIFactory.CreateButton(UIManager.NavbarTabButtonHolder, $"Button_{PanelType}", Name);
|
||||
var navBtn = NavButton.Component.gameObject;
|
||||
navBtn.AddComponent<ContentSizeFitter>().horizontalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||||
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 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
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
// Each generic implementation has its own pool, business logic is here
|
||||
public class Pool<T> : Pool where T : IPooledObject
|
||||
{
|
||||
public static Pool<T> GetPool() => (Pool<T>)GetPool(typeof(T));
|
@ -5,7 +5,6 @@ using UnityEngine.UI;
|
||||
using UnityExplorer.Core.Config;
|
||||
using UnityExplorer.Core.Runtime;
|
||||
using UnityExplorer.UI.Models;
|
||||
using UnityExplorer.UI.Utility;
|
||||
using UnityExplorer.UI.Widgets;
|
||||
|
||||
namespace UnityExplorer.UI
|
||||
|
@ -12,7 +12,6 @@ using UnityExplorer.UI.CSConsole;
|
||||
using UnityExplorer.UI.Inspectors;
|
||||
using UnityExplorer.UI.Models;
|
||||
using UnityExplorer.UI.Panels;
|
||||
using UnityExplorer.UI.Utility;
|
||||
using UnityExplorer.UI.Widgets;
|
||||
using UnityExplorer.UI.Widgets.AutoComplete;
|
||||
|
||||
@ -56,9 +55,15 @@ namespace UnityExplorer.UI
|
||||
internal static Shader BackupShader { get; private set; }
|
||||
|
||||
public static RectTransform NavBarRect;
|
||||
public static GameObject NavbarButtonHolder;
|
||||
public static GameObject NavbarTabButtonHolder;
|
||||
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
|
||||
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);
|
||||
@ -81,6 +86,105 @@ namespace UnityExplorer.UI
|
||||
}
|
||||
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
|
||||
|
||||
public static UIPanel GetPanel(Panels panel)
|
||||
@ -121,91 +225,89 @@ namespace UnityExplorer.UI
|
||||
SetPanelActive(panel, value);
|
||||
}
|
||||
|
||||
// Main UI Update loop
|
||||
// navbar
|
||||
|
||||
private static int lastScreenWidth;
|
||||
private static int lastScreenHeight;
|
||||
|
||||
public static void Update()
|
||||
public static void SetNavBarAnchor()
|
||||
{
|
||||
if (!CanvasRoot || Initializing)
|
||||
return;
|
||||
|
||||
if (InspectUnderMouse.Inspecting)
|
||||
switch (NavbarAnchor)
|
||||
{
|
||||
InspectUnderMouse.Instance.UpdateInspect();
|
||||
return;
|
||||
}
|
||||
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(1000f, 35f);
|
||||
break;
|
||||
|
||||
if (InputManager.GetKeyDown(ConfigManager.Master_Toggle.Value))
|
||||
ShowMenu = !ShowMenu;
|
||||
|
||||
if (!ShowMenu)
|
||||
return;
|
||||
|
||||
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();
|
||||
}
|
||||
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(1000f, 35f);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
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()
|
||||
{
|
||||
CanvasRoot = new GameObject("ExplorerCanvas");
|
||||
@ -240,30 +342,10 @@ namespace UnityExplorer.UI
|
||||
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()
|
||||
{
|
||||
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);
|
||||
NavBarRect = navbarPanel.GetComponent<RectTransform>();
|
||||
NavBarRect.pivot = new Vector2(0.5f, 1f);
|
||||
@ -279,14 +361,28 @@ namespace UnityExplorer.UI
|
||||
// UnityExplorer title
|
||||
|
||||
string titleTxt = $"{ExplorerCore.NAME} <i><color=grey>{ExplorerCore.VERSION}</color></i>";
|
||||
var title = UIFactory.CreateLabel(navbarPanel, "Title", titleTxt, TextAnchor.MiddleLeft, default, true, 18);
|
||||
UIFactory.SetLayoutElement(title.gameObject, minWidth: 180, flexibleWidth: 0);
|
||||
var title = UIFactory.CreateLabel(navbarPanel, "Title", titleTxt, TextAnchor.MiddleLeft, default, true, 17);
|
||||
UIFactory.SetLayoutElement(title.gameObject, minWidth: 170, flexibleWidth: 0);
|
||||
|
||||
// Navbar
|
||||
// panel tabs
|
||||
|
||||
NavbarButtonHolder = UIFactory.CreateUIObject("NavButtonHolder", navbarPanel);
|
||||
UIFactory.SetLayoutElement(NavbarButtonHolder, flexibleHeight: 999, flexibleWidth: 999);
|
||||
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(NavbarButtonHolder, false, true, true, true, 4, 2, 2, 2, 2);
|
||||
NavbarTabButtonHolder = UIFactory.CreateUIObject("NavTabButtonHolder", navbarPanel);
|
||||
UIFactory.SetLayoutElement(NavbarTabButtonHolder, minHeight: 25, flexibleHeight: 999, flexibleWidth: 999);
|
||||
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.onEndEdit.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
|
||||
|
||||
@ -299,14 +395,13 @@ namespace UnityExplorer.UI
|
||||
|
||||
// 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);
|
||||
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));
|
||||
|
||||
ConfigManager.Master_Toggle.OnValueChanged += (KeyCode val) => { closeBtn.ButtonText.text = val.ToString(); };
|
||||
|
||||
closeBtn.OnClick += () => { ShowMenu = false; };
|
||||
ConfigManager.Master_Toggle.OnValueChanged += Master_Toggle_OnValueChanged;
|
||||
closeBtn.OnClick += OnCloseButtonClicked;
|
||||
}
|
||||
|
||||
#region UI AssetBundle
|
||||
|
@ -7,7 +7,6 @@ using UnityEngine.UI;
|
||||
using UnityExplorer.Core.Input;
|
||||
using UnityExplorer.Core.Runtime;
|
||||
using UnityExplorer.UI;
|
||||
using UnityExplorer.UI.ObjectPool;
|
||||
using UnityExplorer.UI.Panels;
|
||||
|
||||
namespace UnityExplorer.UI.Widgets.AutoComplete
|
||||
|
@ -9,7 +9,6 @@ using UnityExplorer.Core.Input;
|
||||
using UnityExplorer.Core.Runtime;
|
||||
using UnityExplorer.UI.Models;
|
||||
using UnityExplorer.UI.Panels;
|
||||
using UnityExplorer.UI.Utility;
|
||||
|
||||
namespace UnityExplorer.UI.Widgets.AutoComplete
|
||||
{
|
||||
|
@ -10,7 +10,7 @@ using UnityExplorer.Core;
|
||||
using UnityExplorer.UI;
|
||||
using UnityExplorer.UI.Models;
|
||||
|
||||
namespace UnityExplorer.UI.Utility
|
||||
namespace UnityExplorer.UI.Widgets
|
||||
{
|
||||
public class AutoSliderScrollbar : UIBehaviourModel
|
||||
{
|
||||
|
@ -4,7 +4,6 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.UI.ObjectPool;
|
||||
|
||||
namespace UnityExplorer.UI.Widgets
|
||||
{
|
||||
|
@ -4,9 +4,6 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.UI.ObjectPool;
|
||||
using UnityExplorer.UI.Widgets;
|
||||
|
||||
namespace UnityExplorer.UI.Widgets
|
||||
{
|
||||
|
@ -9,7 +9,7 @@ using UnityEngine.EventSystems;
|
||||
using UnityEngine.Events;
|
||||
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.
|
||||
|
||||
|
@ -6,15 +6,6 @@ using UnityEngine;
|
||||
|
||||
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
|
||||
{
|
||||
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>
|
||||
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) => 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)
|
||||
public int GetFirstDataIndexAtPosition(float desiredHeight)
|
||||
{
|
||||
cache = default;
|
||||
|
||||
if (!heightCache.Any())
|
||||
return 0;
|
||||
|
||||
@ -72,23 +57,21 @@ namespace UnityExplorer.UI.Widgets
|
||||
if (rangeIndex >= rangeCache.Count)
|
||||
{
|
||||
int idx = ScrollPool.DataSource.ItemCount - 1;
|
||||
cache = heightCache[idx];
|
||||
return idx;
|
||||
}
|
||||
|
||||
int dataIndex = rangeCache[rangeIndex];
|
||||
cache = heightCache[dataIndex];
|
||||
var cache = heightCache[dataIndex];
|
||||
|
||||
// if the DataViewInfo is outdated, need to rebuild
|
||||
int expectedMin = GetRangeCeilingOfPosition(cache.startPosition);
|
||||
int expectedMax = expectedMin + cache.normalizedSpread - 1;
|
||||
if (rangeIndex < expectedMin || rangeIndex > expectedMax)
|
||||
{
|
||||
RecalculateStartPositions(Math.Max(dataIndex, expectedMax));
|
||||
RecalculateStartPositions(ScrollPool.DataSource.ItemCount - 1);
|
||||
|
||||
rangeIndex = GetRangeFloorOfPosition(desiredHeight);
|
||||
dataIndex = rangeCache[rangeIndex];
|
||||
cache = heightCache[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>
|
||||
public void Add(float value)
|
||||
{
|
||||
value = (float)Math.Floor(value);
|
||||
value = Math.Max(DefaultHeight, value);
|
||||
|
||||
int spread = GetRangeSpread(totalHeight, value);
|
||||
|
||||
heightCache.Add(new DataViewInfo()
|
||||
{
|
||||
height = value,
|
||||
startPosition = TotalHeight,
|
||||
normalizedSpread = spread,
|
||||
});
|
||||
heightCache.Add(new DataViewInfo(heightCache.Count, value, totalHeight, spread));
|
||||
|
||||
int dataIdx = heightCache.Count - 1;
|
||||
for (int i = 0; i < spread; i++)
|
||||
@ -141,8 +118,7 @@ namespace UnityExplorer.UI.Widgets
|
||||
if (!heightCache.Any())
|
||||
return;
|
||||
|
||||
var val = heightCache[heightCache.Count - 1];
|
||||
totalHeight -= val;
|
||||
totalHeight -= heightCache[heightCache.Count - 1];
|
||||
heightCache.RemoveAt(heightCache.Count - 1);
|
||||
|
||||
int idx = heightCache.Count;
|
||||
@ -195,28 +171,31 @@ namespace UnityExplorer.UI.Widgets
|
||||
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 (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.
|
||||
RecalculateStartPositions(dataIndex + 1);
|
||||
RecalculateStartPositions(ScrollPool.DataSource.ItemCount - 1);
|
||||
// Get the range index and spread again after rebuilding
|
||||
rangeIndex = GetRangeCeilingOfPosition(cache.startPosition);
|
||||
spread = GetRangeSpread(cache.startPosition, height);
|
||||
}
|
||||
|
||||
if (rangeCache.Count <= rangeIndex || rangeCache[rangeIndex] != dataIndex)
|
||||
throw new Exception("ScrollPool data height cache is corrupt or invalid, rebuild failed!");
|
||||
if (rangeCache[rangeIndex] != dataIndex)
|
||||
throw new IndexOutOfRangeException($"Trying to set dataIndex {dataIndex} at rangeIndex {rangeIndex}, but cache is corrupt or invalid!");
|
||||
|
||||
if (spread != cache.normalizedSpread)
|
||||
{
|
||||
int spreadDiff = spread - cache.normalizedSpread;
|
||||
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)
|
||||
{
|
||||
@ -233,8 +212,6 @@ namespace UnityExplorer.UI.Widgets
|
||||
rangeCache.RemoveAt(rangeIndex);
|
||||
spreadDiff++;
|
||||
}
|
||||
//for (int i = 0; i < -spreadDiff; i++)
|
||||
// rangeCache.RemoveAt(rangeIndex);
|
||||
}
|
||||
}
|
||||
|
||||
@ -243,38 +220,60 @@ namespace UnityExplorer.UI.Widgets
|
||||
if (heightCache.Count <= 1)
|
||||
return;
|
||||
|
||||
DataViewInfo cache;
|
||||
DataViewInfo prev = null;
|
||||
for (int i = 0; i <= toIndex && i < heightCache.Count; i++)
|
||||
{
|
||||
cache = heightCache[i];
|
||||
rangeCache.Clear();
|
||||
|
||||
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;
|
||||
else
|
||||
cache.startPosition = 0;
|
||||
|
||||
var origSpread = cache.normalizedSpread;
|
||||
cache.normalizedSpread = GetRangeSpread(cache.startPosition, cache.height);
|
||||
if (cache.normalizedSpread != origSpread)
|
||||
SetSpread(i, GetRangeCeilingOfPosition(cache.startPosition), cache.normalizedSpread - origSpread);
|
||||
for (int i = 0; i < cache.normalizedSpread; i++)
|
||||
rangeCache.Add(cache.dataIndex);
|
||||
|
||||
heightCache[idx] = cache;
|
||||
|
||||
prev = cache;
|
||||
}
|
||||
}
|
||||
|
||||
//private void HardRebuildRanges()
|
||||
//{
|
||||
// var tempList = new List<float>();
|
||||
// for (int i = 0; i < heightCache.Count; i++)
|
||||
// tempList.Add(heightCache[i]);
|
||||
//
|
||||
// heightCache.Clear();
|
||||
// rangeCache.Clear();
|
||||
// totalHeight = 0;
|
||||
//
|
||||
// for (int i = 0; i < tempList.Count; i++)
|
||||
// SetIndex(i, tempList[i]);
|
||||
//}
|
||||
public struct DataViewInfo
|
||||
{
|
||||
// static
|
||||
public static DataViewInfo None => s_default;
|
||||
private static DataViewInfo s_default = default;
|
||||
|
||||
public static implicit operator float(DataViewInfo it) => it.height;
|
||||
|
||||
public DataViewInfo(int index, float height, float startPos, int spread)
|
||||
{
|
||||
this.dataIndex = index;
|
||||
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.Text;
|
||||
using UnityEngine;
|
||||
using UnityExplorer.UI.ObjectPool;
|
||||
using UnityExplorer.UI.Models;
|
||||
|
||||
namespace UnityExplorer.UI.Widgets
|
||||
{
|
||||
|
@ -7,7 +7,6 @@ using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.Core.Input;
|
||||
using UnityExplorer.UI.Models;
|
||||
using UnityExplorer.UI.ObjectPool;
|
||||
using UnityExplorer.UI.Panels;
|
||||
|
||||
namespace UnityExplorer.UI.Widgets
|
||||
@ -20,7 +19,7 @@ namespace UnityExplorer.UI.Widgets
|
||||
/// <summary>
|
||||
/// An object-pooled ScrollRect, attempts to support content of any size and provide a scrollbar for it.
|
||||
/// </summary>
|
||||
public class ScrollPool<T> : UIBehaviourModel where T : ICell
|
||||
public class ScrollPool<T> : UIBehaviourModel, IEnumerable<CellInfo> where T : ICell
|
||||
{
|
||||
public ScrollPool(ScrollRect scrollRect)
|
||||
{
|
||||
@ -138,9 +137,42 @@ namespace UnityExplorer.UI.Widgets
|
||||
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>
|
||||
public void Initialize(ICellPoolDataSource<T> dataSource, Action onHeightChangedListener = null)
|
||||
@ -161,13 +193,12 @@ namespace UnityExplorer.UI.Widgets
|
||||
RuntimeProvider.Instance.StartCoroutine(InitCoroutine(onHeightChangedListener));
|
||||
}
|
||||
|
||||
private readonly WaitForEndOfFrame waitForEndOfFrame = new WaitForEndOfFrame();
|
||||
private WaitForEndOfFrame waitForEndOfFrame = new WaitForEndOfFrame();
|
||||
|
||||
private IEnumerator InitCoroutine(Action onHeightChangedListener)
|
||||
{
|
||||
ScrollRect.content.anchoredPosition = Vector2.zero;
|
||||
//yield return null;
|
||||
yield return waitForEndOfFrame;
|
||||
yield return waitForEndOfFrame ?? (waitForEndOfFrame = new WaitForEndOfFrame());
|
||||
|
||||
LayoutRebuilder.ForceRebuildLayoutImmediate(Content);
|
||||
|
||||
@ -178,9 +209,8 @@ namespace UnityExplorer.UI.Widgets
|
||||
// create initial cell pool and set cells
|
||||
CreateCellPool();
|
||||
|
||||
var enumerator = GetPoolEnumerator();
|
||||
while (enumerator.MoveNext())
|
||||
SetCell(CellPool[enumerator.Current.cellIndex], enumerator.Current.dataIndex);
|
||||
foreach (var cell in this)
|
||||
SetCell(CellPool[cell.cellIndex], cell.dataIndex);
|
||||
|
||||
LayoutRebuilder.ForceRebuildLayoutImmediate(Content);
|
||||
prevContentHeight = Content.rect.height;
|
||||
@ -217,18 +247,18 @@ namespace UnityExplorer.UI.Widgets
|
||||
|
||||
// Cell pool
|
||||
|
||||
private CellInfo _cellInfo = new CellInfo();
|
||||
private CellInfo _current;
|
||||
|
||||
public IEnumerator<CellInfo> GetPoolEnumerator()
|
||||
private IEnumerator<CellInfo> EnumerateCellPool()
|
||||
{
|
||||
int cellIdx = topPoolIndex;
|
||||
int dataIndex = TopDataIndex;
|
||||
int iterated = 0;
|
||||
while (iterated < CellPool.Count)
|
||||
{
|
||||
_cellInfo.cellIndex = cellIdx;
|
||||
_cellInfo.dataIndex = dataIndex;
|
||||
yield return _cellInfo;
|
||||
_current.cellIndex = cellIdx;
|
||||
_current.dataIndex = dataIndex;
|
||||
yield return _current;
|
||||
|
||||
cellIdx++;
|
||||
if (cellIdx >= CellPool.Count)
|
||||
@ -368,16 +398,13 @@ namespace UnityExplorer.UI.Widgets
|
||||
CheckDataSourceCountChange(out bool jumpToBottom);
|
||||
|
||||
// update date height cache, and set cells if 'andReload'
|
||||
var enumerator = GetPoolEnumerator();
|
||||
while (enumerator.MoveNext())
|
||||
foreach (var cellInfo in this)
|
||||
{
|
||||
var curr = enumerator.Current;
|
||||
var cell = CellPool[curr.cellIndex];
|
||||
|
||||
var cell = CellPool[cellInfo.cellIndex];
|
||||
if (andReloadFromDataSource)
|
||||
SetCell(cell, curr.dataIndex);
|
||||
SetCell(cell, cellInfo.dataIndex);
|
||||
else
|
||||
HeightCache.SetIndex(curr.dataIndex, cell.Rect.rect.height);
|
||||
HeightCache.SetIndex(cellInfo.dataIndex, cell.Rect.rect.height);
|
||||
}
|
||||
|
||||
// force check recycles
|
||||
@ -405,12 +432,8 @@ namespace UnityExplorer.UI.Widgets
|
||||
|
||||
private void RefreshCellHeightsFast()
|
||||
{
|
||||
var enumerator = GetPoolEnumerator();
|
||||
while (enumerator.MoveNext())
|
||||
{
|
||||
var curr = enumerator.Current;
|
||||
HeightCache.SetIndex(curr.dataIndex, CellPool[curr.cellIndex].Rect.rect.height);
|
||||
}
|
||||
foreach (var cellInfo in this)
|
||||
HeightCache.SetIndex(cellInfo.dataIndex, CellPool[cellInfo.cellIndex].Rect.rect.height);
|
||||
}
|
||||
|
||||
private void SetCell(T cachedCell, int dataIndex)
|
||||
@ -619,12 +642,10 @@ namespace UnityExplorer.UI.Widgets
|
||||
else
|
||||
{
|
||||
bottomDataIndex = desiredBottomIndex;
|
||||
var enumerator = GetPoolEnumerator();
|
||||
while (enumerator.MoveNext())
|
||||
foreach (var info in this)
|
||||
{
|
||||
var curr = enumerator.Current;
|
||||
var cell = CellPool[curr.cellIndex];
|
||||
SetCell(cell, curr.dataIndex);
|
||||
var cell = CellPool[info.cellIndex];
|
||||
SetCell(cell, info.dataIndex);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,8 +6,6 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.UI.ObjectPool;
|
||||
using UnityExplorer.UI.Widgets;
|
||||
|
||||
namespace UnityExplorer.UI.Widgets
|
||||
{
|
||||
@ -22,13 +20,17 @@ namespace UnityExplorer.UI.Widgets
|
||||
/// Key: UnityEngine.Transform instance ID<br/>
|
||||
/// Value: CachedTransform
|
||||
/// </summary>
|
||||
internal readonly OrderedDictionary displayedObjects = new OrderedDictionary();
|
||||
internal readonly OrderedDictionary cachedTransforms = new OrderedDictionary();
|
||||
|
||||
// for keeping track of which actual transforms are expanded or not, outside of the cache data.
|
||||
private readonly HashSet<int> expandedInstanceIDs = new HashSet<int>();
|
||||
private readonly HashSet<int> autoExpandedIDs = new HashSet<int>();
|
||||
|
||||
public int ItemCount => displayedObjects.Count;
|
||||
private readonly HashSet<int> visited = new HashSet<int>();
|
||||
private bool needRefresh;
|
||||
private int displayIndex;
|
||||
|
||||
public int ItemCount => cachedTransforms.Count;
|
||||
|
||||
public bool Filtering => !string.IsNullOrEmpty(currentFilter);
|
||||
private bool wasFiltering;
|
||||
@ -50,6 +52,25 @@ namespace UnityExplorer.UI.Widgets
|
||||
}
|
||||
private string currentFilter;
|
||||
|
||||
public TransformTree(ScrollPool<TransformCell> scrollPool, Func<IEnumerable<GameObject>> getRootEntriesMethod)
|
||||
{
|
||||
ScrollPool = scrollPool;
|
||||
GetRootEntriesMethod = getRootEntriesMethod;
|
||||
}
|
||||
|
||||
public void OnCellBorrowed(TransformCell cell)
|
||||
{
|
||||
cell.OnExpandToggled += ToggleExpandCell;
|
||||
cell.OnGameObjectClicked += OnGameObjectClicked;
|
||||
}
|
||||
|
||||
private void OnGameObjectClicked(GameObject obj)
|
||||
{
|
||||
if (OnClickOverrideHandler != null)
|
||||
OnClickOverrideHandler.Invoke(obj);
|
||||
else
|
||||
InspectorManager.Inspect(obj);
|
||||
}
|
||||
|
||||
public void Init()
|
||||
{
|
||||
@ -58,29 +79,11 @@ namespace UnityExplorer.UI.Widgets
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
this.displayedObjects.Clear();
|
||||
this.cachedTransforms.Clear();
|
||||
displayIndex = 0;
|
||||
autoExpandedIDs.Clear();
|
||||
expandedInstanceIDs.Clear();
|
||||
}
|
||||
|
||||
|
||||
public void OnGameObjectClicked(GameObject obj)
|
||||
{
|
||||
if (OnClickOverrideHandler != null)
|
||||
{
|
||||
OnClickOverrideHandler.Invoke(obj);
|
||||
}
|
||||
else
|
||||
{
|
||||
InspectorManager.Inspect(obj);
|
||||
}
|
||||
}
|
||||
|
||||
public TransformTree(ScrollPool<TransformCell> scrollPool, Func<IEnumerable<GameObject>> getRootEntriesMethod)
|
||||
{
|
||||
ScrollPool = scrollPool;
|
||||
GetRootEntriesMethod = getRootEntriesMethod;
|
||||
this.ScrollPool.Refresh(true, true);
|
||||
}
|
||||
|
||||
public bool IsCellExpanded(int instanceID)
|
||||
@ -89,6 +92,53 @@ namespace UnityExplorer.UI.Widgets
|
||||
: expandedInstanceIDs.Contains(instanceID);
|
||||
}
|
||||
|
||||
public void JumpAndExpandToTransform(Transform transform)
|
||||
{
|
||||
// make sure all parents of the object are expanded
|
||||
var parent = transform.parent;
|
||||
while (parent)
|
||||
{
|
||||
int pid = parent.GetInstanceID();
|
||||
if (!expandedInstanceIDs.Contains(pid))
|
||||
expandedInstanceIDs.Add(pid);
|
||||
|
||||
parent = parent.parent;
|
||||
}
|
||||
|
||||
// Refresh cached transforms (no UI rebuild yet)
|
||||
RefreshData(false);
|
||||
|
||||
int transformID = transform.GetInstanceID();
|
||||
|
||||
// find the index of our transform in the list and jump to it
|
||||
int idx;
|
||||
for (idx = 0; idx < cachedTransforms.Count; idx++)
|
||||
{
|
||||
var cache = (CachedTransform)cachedTransforms[idx];
|
||||
if (cache.InstanceID == transformID)
|
||||
break;
|
||||
}
|
||||
|
||||
ScrollPool.JumpToIndex(idx, OnCellJumpedTo);
|
||||
}
|
||||
|
||||
private void OnCellJumpedTo(TransformCell cell)
|
||||
{
|
||||
RuntimeProvider.Instance.StartCoroutine(HighlightCellCoroutine(cell));
|
||||
}
|
||||
|
||||
private IEnumerator HighlightCellCoroutine(TransformCell cell)
|
||||
{
|
||||
var button = cell.NameButton.Component;
|
||||
button.StartColorTween(new Color(0.2f, 0.3f, 0.2f), false);
|
||||
|
||||
float start = Time.realtimeSinceStartup;
|
||||
while (Time.realtimeSinceStartup - start < 1.5f)
|
||||
yield return null;
|
||||
|
||||
button.OnDeselect(null);
|
||||
}
|
||||
|
||||
public void Rebuild()
|
||||
{
|
||||
autoExpandedIDs.Clear();
|
||||
@ -97,10 +147,6 @@ namespace UnityExplorer.UI.Widgets
|
||||
RefreshData(true, true);
|
||||
}
|
||||
|
||||
private readonly HashSet<int> visited = new HashSet<int>();
|
||||
private bool needRefresh;
|
||||
private int displayIndex;
|
||||
|
||||
public void RefreshData(bool andReload = false, bool jumpToTop = false)
|
||||
{
|
||||
visited.Clear();
|
||||
@ -114,12 +160,12 @@ namespace UnityExplorer.UI.Widgets
|
||||
if (obj) Traverse(obj.transform);
|
||||
|
||||
// Prune displayed transforms that we didnt visit in that traverse
|
||||
for (int i = displayedObjects.Count - 1; i >= 0; i--)
|
||||
for (int i = cachedTransforms.Count - 1; i >= 0; i--)
|
||||
{
|
||||
var obj = (CachedTransform)displayedObjects[i];
|
||||
var obj = (CachedTransform)cachedTransforms[i];
|
||||
if (!visited.Contains(obj.InstanceID))
|
||||
{
|
||||
displayedObjects.Remove(obj.InstanceID);
|
||||
cachedTransforms.Remove(obj.InstanceID);
|
||||
needRefresh = true;
|
||||
}
|
||||
}
|
||||
@ -159,9 +205,9 @@ namespace UnityExplorer.UI.Widgets
|
||||
visited.Add(instanceID);
|
||||
|
||||
CachedTransform cached;
|
||||
if (displayedObjects.Contains(instanceID))
|
||||
if (cachedTransforms.Contains(instanceID))
|
||||
{
|
||||
cached = (CachedTransform)displayedObjects[(object)instanceID];
|
||||
cached = (CachedTransform)cachedTransforms[(object)instanceID];
|
||||
if (cached.Update(transform, depth))
|
||||
needRefresh = true;
|
||||
}
|
||||
@ -169,10 +215,10 @@ namespace UnityExplorer.UI.Widgets
|
||||
{
|
||||
needRefresh = true;
|
||||
cached = new CachedTransform(this, transform, depth, parent);
|
||||
if (displayedObjects.Count <= displayIndex)
|
||||
displayedObjects.Add(instanceID, cached);
|
||||
if (cachedTransforms.Count <= displayIndex)
|
||||
cachedTransforms.Add(instanceID, cached);
|
||||
else
|
||||
displayedObjects.Insert(displayIndex, instanceID, cached);
|
||||
cachedTransforms.Insert(displayIndex, instanceID, cached);
|
||||
}
|
||||
|
||||
displayIndex++;
|
||||
@ -201,9 +247,9 @@ namespace UnityExplorer.UI.Widgets
|
||||
|
||||
public void SetCell(TransformCell cell, int index)
|
||||
{
|
||||
if (index < displayedObjects.Count)
|
||||
if (index < cachedTransforms.Count)
|
||||
{
|
||||
cell.ConfigureCell((CachedTransform)displayedObjects[index], index);
|
||||
cell.ConfigureCell((CachedTransform)cachedTransforms[index], index);
|
||||
if (Filtering)
|
||||
{
|
||||
if (cell.cachedTransform.Name.ContainsIgnoreCase(currentFilter))
|
||||
@ -226,16 +272,5 @@ namespace UnityExplorer.UI.Widgets
|
||||
|
||||
RefreshData(true);
|
||||
}
|
||||
|
||||
public void OnCellBorrowed(TransformCell cell)
|
||||
{
|
||||
cell.OnExpandToggled += ToggleExpandCell;
|
||||
cell.OnGameObjectClicked += OnGameObjectClicked;
|
||||
}
|
||||
|
||||
//public void ReleaseCell(TransformCell cell)
|
||||
//{
|
||||
// cell.OnExpandToggled -= ToggleExpandCell;
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
@ -143,12 +143,12 @@
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<!-- BepInEx universal refs -->
|
||||
<ItemGroup Condition="'$(IsBepInEx)'=='true'">
|
||||
<Reference Include="0Harmony">
|
||||
<HintPath>..\lib\HarmonyX\Harmony\bin\Release\net35\0Harmony.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="'$(IsBepInEx)'=='true'">
|
||||
<Reference Include="0Harmony">
|
||||
<HintPath>packages\HarmonyX.2.4.2\lib\net35\0Harmony.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<!-- BepInEx 5 Mono refs -->
|
||||
<ItemGroup Condition="'$(IsBepInEx)|$(IsCpp)|$(Configuration)'=='true|false|Release_BIE5_Mono'">
|
||||
<Reference Include="BepInEx">
|
||||
@ -180,10 +180,10 @@
|
||||
</ItemGroup>
|
||||
<!-- Standalone refs -->
|
||||
<ItemGroup Condition="'$(IsStandalone)'=='true'">
|
||||
<Reference Include="0Harmony">
|
||||
<HintPath>..\lib\HarmonyX\Harmony\bin\Release\net35\0Harmony.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="0Harmony">
|
||||
<HintPath>packages\HarmonyX.2.4.2\lib\net35\0Harmony.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<!-- Mono refs -->
|
||||
<ItemGroup Condition="'$(IsCpp)'=='false'">
|
||||
@ -281,17 +281,16 @@
|
||||
<Compile Include="UI\Inspectors\InspectorManager.cs" />
|
||||
<Compile Include="UI\Inspectors\InspectorTab.cs" />
|
||||
<Compile Include="UI\Inspectors\InspectorBase.cs" />
|
||||
<Compile Include="UI\IValues\InteractiveColor.cs" />
|
||||
<Compile Include="UI\IValues\InteractiveDictionary.cs" />
|
||||
<Compile Include="UI\IValues\InteractiveEnum.cs" />
|
||||
<Compile Include="UI\IValues\InteractiveList.cs" />
|
||||
<Compile Include="UI\IValues\InteractiveString.cs" />
|
||||
<Compile Include="UI\IValues\InteractiveValue.cs" />
|
||||
<Compile Include="UI\CacheObject\IValues\InteractiveColor.cs" />
|
||||
<Compile Include="UI\CacheObject\IValues\InteractiveDictionary.cs" />
|
||||
<Compile Include="UI\CacheObject\IValues\InteractiveEnum.cs" />
|
||||
<Compile Include="UI\CacheObject\IValues\InteractiveList.cs" />
|
||||
<Compile Include="UI\CacheObject\IValues\InteractiveString.cs" />
|
||||
<Compile Include="UI\CacheObject\IValues\InteractiveValue.cs" />
|
||||
<Compile Include="UI\Inspectors\ReflectionInspector.cs" />
|
||||
<Compile Include="UI\IValues\InteractiveValueStruct.cs" />
|
||||
<Compile Include="UI\CacheObject\IValues\InteractiveValueStruct.cs" />
|
||||
<Compile Include="UI\Models\InputFieldRef.cs" />
|
||||
<Compile Include="UI\ObjectPool\IPooledObject.cs" />
|
||||
<Compile Include="UI\ObjectPool\Pool.cs" />
|
||||
<Compile Include="UI\Pool.cs" />
|
||||
<Compile Include="UI\Panels\LogPanel.cs" />
|
||||
<Compile Include="UI\Panels\CSConsolePanel.cs" />
|
||||
<Compile Include="Core\Utility\IOUtility.cs" />
|
||||
@ -319,7 +318,7 @@
|
||||
<Compile Include="Core\Runtime\RuntimeContext.cs" />
|
||||
<Compile Include="Core\Runtime\RuntimeProvider.cs" />
|
||||
<Compile Include="Core\Runtime\TextureUtilProvider.cs" />
|
||||
<Compile Include="Core\SceneHandler.cs" />
|
||||
<Compile Include="UI\ObjectExplorer\SceneHandler.cs" />
|
||||
<Compile Include="UI\ObjectExplorer\SearchProvider.cs" />
|
||||
<Compile Include="Core\Tests\TestClass.cs" />
|
||||
<Compile Include="Core\Utility\UnityHelpers.cs" />
|
||||
@ -367,11 +366,11 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Import Project="packages\ILRepack.Lib.MSBuild.Task.2.0.18.1\build\ILRepack.Lib.MSBuild.Task.targets" Condition="Exists('packages\ILRepack.Lib.MSBuild.Task.2.0.18.1\build\ILRepack.Lib.MSBuild.Task.targets')" />
|
||||
<Import Project="packages\ILRepack.Lib.MSBuild.Task.2.0.18.2\build\ILRepack.Lib.MSBuild.Task.targets" Condition="Exists('packages\ILRepack.Lib.MSBuild.Task.2.0.18.2\build\ILRepack.Lib.MSBuild.Task.targets')" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('packages\ILRepack.Lib.MSBuild.Task.2.0.18.1\build\ILRepack.Lib.MSBuild.Task.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\ILRepack.Lib.MSBuild.Task.2.0.18.1\build\ILRepack.Lib.MSBuild.Task.targets'))" />
|
||||
<Error Condition="!Exists('packages\ILRepack.Lib.MSBuild.Task.2.0.18.2\build\ILRepack.Lib.MSBuild.Task.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\ILRepack.Lib.MSBuild.Task.2.0.18.2\build\ILRepack.Lib.MSBuild.Task.targets'))" />
|
||||
</Target>
|
||||
</Project>
|
@ -3,8 +3,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.30128.74
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Harmony", "..\lib\HarmonyX\Harmony\Harmony.csproj", "{F2D7872C-5D4D-49EB-A656-C3D496DB4204}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnhollowerBaseLib", "..\lib\Il2CppAssemblyUnhollower\UnhollowerBaseLib\UnhollowerBaseLib.csproj", "{7B7E5024-385D-4A46-9196-A6AF8F7FBDD5}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "mcs", "..\lib\mcs-unity\mcs\mcs.csproj", "{E4989E4C-0875-4528-9031-08E2C0E70103}"
|
||||
@ -24,24 +22,6 @@ Global
|
||||
Release_STANDALONE_Mono|Any CPU = Release_STANDALONE_Mono|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{F2D7872C-5D4D-49EB-A656-C3D496DB4204}.Release_BIE_Cpp|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F2D7872C-5D4D-49EB-A656-C3D496DB4204}.Release_BIE_Cpp|Any CPU.Build.0 = Release|Any CPU
|
||||
{F2D7872C-5D4D-49EB-A656-C3D496DB4204}.Release_BIE5_Mono|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F2D7872C-5D4D-49EB-A656-C3D496DB4204}.Release_BIE5_Mono|Any CPU.Build.0 = Release|Any CPU
|
||||
{F2D7872C-5D4D-49EB-A656-C3D496DB4204}.Release_BIE6_Mono|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F2D7872C-5D4D-49EB-A656-C3D496DB4204}.Release_BIE6_Mono|Any CPU.Build.0 = Release|Any CPU
|
||||
{F2D7872C-5D4D-49EB-A656-C3D496DB4204}.Release_ML_Cpp|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F2D7872C-5D4D-49EB-A656-C3D496DB4204}.Release_ML_Cpp|Any CPU.Build.0 = Release|Any CPU
|
||||
{F2D7872C-5D4D-49EB-A656-C3D496DB4204}.Release_ML_Mono|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F2D7872C-5D4D-49EB-A656-C3D496DB4204}.Release_ML_Mono|Any CPU.Build.0 = Release|Any CPU
|
||||
{F2D7872C-5D4D-49EB-A656-C3D496DB4204}.Release_MLLegacy_Cpp|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F2D7872C-5D4D-49EB-A656-C3D496DB4204}.Release_MLLegacy_Cpp|Any CPU.Build.0 = Release|Any CPU
|
||||
{F2D7872C-5D4D-49EB-A656-C3D496DB4204}.Release_MLLegacy_Mono|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F2D7872C-5D4D-49EB-A656-C3D496DB4204}.Release_MLLegacy_Mono|Any CPU.Build.0 = Release|Any CPU
|
||||
{F2D7872C-5D4D-49EB-A656-C3D496DB4204}.Release_STANDALONE_Cpp|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F2D7872C-5D4D-49EB-A656-C3D496DB4204}.Release_STANDALONE_Cpp|Any CPU.Build.0 = Release|Any CPU
|
||||
{F2D7872C-5D4D-49EB-A656-C3D496DB4204}.Release_STANDALONE_Mono|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F2D7872C-5D4D-49EB-A656-C3D496DB4204}.Release_STANDALONE_Mono|Any CPU.Build.0 = Release|Any CPU
|
||||
{7B7E5024-385D-4A46-9196-A6AF8F7FBDD5}.Release_BIE_Cpp|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7B7E5024-385D-4A46-9196-A6AF8F7FBDD5}.Release_BIE_Cpp|Any CPU.Build.0 = Release|Any CPU
|
||||
{7B7E5024-385D-4A46-9196-A6AF8F7FBDD5}.Release_BIE5_Mono|Any CPU.ActiveCfg = Release|Any CPU
|
||||
|
@ -1,5 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="ILRepack.Lib.MSBuild.Task" version="2.0.18.1" targetFramework="net472" />
|
||||
<package id="HarmonyX" version="2.4.2" targetFramework="net35" />
|
||||
<package id="ILRepack.Lib.MSBuild.Task" version="2.0.18.2" targetFramework="net35" />
|
||||
<package id="ini-parser" version="2.5.2" targetFramework="net35" />
|
||||
<package id="Mono.Cecil" version="0.10.4" targetFramework="net35" />
|
||||
</packages>
|
Reference in New Issue
Block a user