mirror of
https://github.com/GrahamKracker/UnityExplorer.git
synced 2025-07-02 03:22:41 +08:00
Compare commits
54 Commits
Author | SHA1 | Date | |
---|---|---|---|
7a539ba78b | |||
0d10f94eb5 | |||
91671bf243 | |||
a72877befb | |||
16335c1bc4 | |||
8fab9e6268 | |||
fdd9039cca | |||
dcca980635 | |||
bfcab8248e | |||
97c20144f1 | |||
aaab10a0a0 | |||
b42a8dbe6a | |||
d7008db22e | |||
8c1913fe80 | |||
8d8c9ac7c9 | |||
f35beeaf58 | |||
d150ff3455 | |||
c4fa0d6bcd | |||
a5f56cf5a3 | |||
8c822b2ee9 | |||
4681b7e192 | |||
97093733d8 | |||
615f77979f | |||
ba3cf970d9 | |||
b2fb571b18 | |||
67ce6f946a | |||
1b82ccb49f | |||
480eb5afd5 | |||
88ea2a09c9 | |||
a678aa4d78 | |||
eaf478e314 | |||
d391968b32 | |||
70349ad7c7 | |||
78f2d1070f | |||
51307563ab | |||
185d1aaa0f | |||
3d6e8fcbf8 | |||
1daf4fade4 | |||
d92fb3f83f | |||
fe24b68fe2 | |||
6bf92b9a96 | |||
9f1cab019d | |||
a131404ac7 | |||
773900d749 | |||
342fc6bdb8 | |||
e85ea6ac3a | |||
af889e64cb | |||
0274022ce4 | |||
211576e0f8 | |||
3e42d7479f | |||
df4dea20c1 | |||
ece0c43067 | |||
6311c8d09a | |||
04739d0be8 |
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
|
||||
|
118
README.md
118
README.md
@ -3,44 +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.
|
||||
* 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.
|
||||
## 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).
|
||||
|
||||
@ -49,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">
|
||||
@ -59,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
@ -16,18 +16,18 @@ namespace UnityExplorer.Core.Config
|
||||
// See the UnityExplorer.Loader namespace for the implementations.
|
||||
public static ConfigHandler Handler { get; private set; }
|
||||
|
||||
public static ConfigElement<KeyCode> Master_Toggle;
|
||||
public static ConfigElement<KeyCode> Master_Toggle;
|
||||
public static ConfigElement<UIManager.VerticalAnchor> Main_Navbar_Anchor;
|
||||
public static ConfigElement<bool> Force_Unlock_Mouse;
|
||||
public static ConfigElement<KeyCode> Force_Unlock_Toggle;
|
||||
public static ConfigElement<bool> Aggressive_Mouse_Unlock;
|
||||
public static ConfigElement<bool> Disable_EventSystem_Override;
|
||||
public static ConfigElement<string> Default_Output_Path;
|
||||
public static ConfigElement<bool> Log_Unity_Debug;
|
||||
public static ConfigElement<bool> Hide_On_Startup;
|
||||
public static ConfigElement<float> Startup_Delay_Time;
|
||||
public static ConfigElement<bool> Force_Unlock_Mouse;
|
||||
public static ConfigElement<KeyCode> Force_Unlock_Toggle;
|
||||
public static ConfigElement<bool> Aggressive_Mouse_Unlock;
|
||||
public static ConfigElement<bool> Disable_EventSystem_Override;
|
||||
public static ConfigElement<string> Default_Output_Path;
|
||||
public static ConfigElement<bool> Log_Unity_Debug;
|
||||
public static ConfigElement<bool> Hide_On_Startup;
|
||||
public static ConfigElement<float> Startup_Delay_Time;
|
||||
|
||||
public static ConfigElement<string> Reflection_Signature_Blacklist;
|
||||
public static ConfigElement<string> Reflection_Signature_Blacklist;
|
||||
|
||||
// internal configs
|
||||
internal static InternalConfigHandler InternalHandler { get; private set; }
|
||||
@ -113,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)
|
||||
|
||||
|
@ -87,9 +87,6 @@ namespace UnityExplorer.Core.Config
|
||||
foreach (var entry in ConfigManager.InternalConfigs)
|
||||
sec.AddKey(entry.Key, entry.Value.BoxedValue.ToString());
|
||||
|
||||
if (!Directory.Exists(ExplorerCore.Loader.ConfigFolder))
|
||||
Directory.CreateDirectory(ExplorerCore.Loader.ConfigFolder);
|
||||
|
||||
File.WriteAllText(INI_PATH, data.ToString());
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityExplorer.Core.Input;
|
||||
using BF = System.Reflection.BindingFlags;
|
||||
using UnityExplorer.Core.Config;
|
||||
using UnityExplorer.Core;
|
||||
using UnityExplorer.Core.Config;
|
||||
using UnityExplorer.Core.Input;
|
||||
using UnityExplorer.UI;
|
||||
using System.Collections;
|
||||
using BF = System.Reflection.BindingFlags;
|
||||
|
||||
|
||||
namespace UnityExplorer.Core.Input
|
||||
@ -62,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();
|
||||
|
@ -1,6 +1,6 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
namespace UnityExplorer.Core.Input
|
||||
@ -74,7 +74,7 @@ namespace UnityExplorer.Core.Input
|
||||
ExplorerCore.Log("Initialized Legacy Input support");
|
||||
return;
|
||||
}
|
||||
catch
|
||||
catch
|
||||
{
|
||||
// It's not working, we'll fall back to InputSystem.
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityExplorer.UI;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace UnityExplorer.Core.Input
|
||||
{
|
||||
|
@ -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,13 +26,18 @@ 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
|
||||
#region IL2CPP Extern and pointers
|
||||
|
||||
// Extern C++ methods
|
||||
[DllImport("GameAssembly", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
|
||||
@ -57,29 +63,21 @@ namespace UnityExplorer
|
||||
return il2cppPtr != IntPtr.Zero;
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
|
||||
#region Deobfuscation cache
|
||||
#region Deobfuscation cache
|
||||
|
||||
private static readonly Dictionary<string, Type> DeobfuscatedTypes = new Dictionary<string, Type>();
|
||||
private static readonly Dictionary<string, string> reverseDeobCache = new Dictionary<string, string>();
|
||||
|
||||
private static void BuildDeobfuscationCache()
|
||||
{
|
||||
float start = UnityEngine.Time.realtimeSinceStartup;
|
||||
|
||||
foreach (var asm in AppDomain.CurrentDomain.GetAssemblies())
|
||||
{
|
||||
foreach (var type in asm.TryGetTypes())
|
||||
TryCacheDeobfuscatedType(type);
|
||||
}
|
||||
|
||||
if (DeobfuscatedTypes.Count > 0)
|
||||
{
|
||||
ExplorerCore.Log($"Built deobfuscation cache in {UnityEngine.Time.realtimeSinceStartup - start} seconds, " +
|
||||
$"initial count: {DeobfuscatedTypes.Count} ");
|
||||
}
|
||||
}
|
||||
|
||||
private static void TryCacheDeobfuscatedType(Type type)
|
||||
@ -113,7 +111,7 @@ namespace UnityExplorer
|
||||
return theString;
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
|
||||
// Get type by name
|
||||
@ -126,7 +124,7 @@ namespace UnityExplorer
|
||||
return base.Internal_GetTypeByName(fullName);
|
||||
}
|
||||
|
||||
#region Get actual type
|
||||
#region Get actual type
|
||||
|
||||
internal override Type Internal_GetActualType(object obj)
|
||||
{
|
||||
@ -185,10 +183,10 @@ namespace UnityExplorer
|
||||
return monoType;
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
|
||||
#region Casting
|
||||
#region Casting
|
||||
|
||||
private static readonly Dictionary<string, IntPtr> cppClassPointers = new Dictionary<string, IntPtr>();
|
||||
|
||||
@ -280,10 +278,10 @@ namespace UnityExplorer
|
||||
// return il2cpp_class_is_assignable_from(thisTypePtr, fromTypePtr);
|
||||
//}
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
|
||||
#region Boxing and unboxing ValueTypes
|
||||
#region Boxing and unboxing ValueTypes
|
||||
|
||||
// cached il2cpp unbox methods
|
||||
internal static readonly Dictionary<string, MethodInfo> unboxMethods = new Dictionary<string, MethodInfo>();
|
||||
@ -386,10 +384,10 @@ namespace UnityExplorer
|
||||
return cppStruct;
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
|
||||
#region String boxing/unboxing
|
||||
#region String boxing/unboxing
|
||||
|
||||
private const string IL2CPP_STRING_FULLNAME = "Il2CppSystem.String";
|
||||
private const string STRING_FULLNAME = "System.String";
|
||||
@ -430,10 +428,10 @@ namespace UnityExplorer
|
||||
return s;
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
|
||||
#region Singleton finder
|
||||
#region Singleton finder
|
||||
|
||||
internal override void Internal_FindSingleton(string[] possibleNames, Type type, BF flags, List<object> instances)
|
||||
{
|
||||
@ -455,16 +453,16 @@ namespace UnityExplorer
|
||||
base.Internal_FindSingleton(possibleNames, type, flags, instances);
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
|
||||
#region Force-loading game modules
|
||||
#region Force-loading game modules
|
||||
|
||||
internal static string UnhollowedFolderPath => Path.GetFullPath(
|
||||
#if ML
|
||||
Path.Combine("MelonLoader", "Managed")
|
||||
#elif BIE
|
||||
Path.Combine("BepInEx", "unhollowed")
|
||||
Path.Combine(BepInEx.Paths.BepInExRootPath, "unhollowed")
|
||||
#else
|
||||
Path.Combine(ExplorerCore.Loader.ExplorerFolder, "Modules")
|
||||
#endif
|
||||
@ -518,9 +516,9 @@ namespace UnityExplorer
|
||||
#endregion
|
||||
|
||||
|
||||
#region Il2cpp reflection blacklist
|
||||
#region Il2cpp reflection blacklist
|
||||
|
||||
public override string DefaultReflectionBlacklist => string.Join(";", defaultIl2CppBlacklist);
|
||||
public override string[] DefaultReflectionBlacklist => defaultIl2CppBlacklist.ToArray();
|
||||
|
||||
// These methods currently cause a crash in most il2cpp games,
|
||||
// even from doing "GetParameters()" on the MemberInfo.
|
||||
@ -667,10 +665,10 @@ namespace UnityExplorer
|
||||
"UnityEngine.XR.InputDevice.SendHapticImpulse",
|
||||
};
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
|
||||
#region IL2CPP IEnumerable and IDictionary
|
||||
#region IL2CPP IEnumerable and IDictionary
|
||||
|
||||
protected override bool Internal_TryGetEntryType(Type enumerableType, out Type type)
|
||||
{
|
||||
|
@ -4,15 +4,14 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using BF = System.Reflection.BindingFlags;
|
||||
using UnityExplorer.Core.Runtime;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityExplorer.Core.Config;
|
||||
using UnityExplorer.Core.Runtime;
|
||||
using BF = System.Reflection.BindingFlags;
|
||||
|
||||
namespace UnityExplorer
|
||||
{
|
||||
|
||||
public class ReflectionUtility
|
||||
{
|
||||
public const BF FLAGS = BF.Public | BF.Instance | BF.NonPublic | BF.Static;
|
||||
@ -43,7 +42,7 @@ namespace UnityExplorer
|
||||
public static Action<Type> OnTypeLoaded;
|
||||
|
||||
/// <summary>Key: Type.FullName</summary>
|
||||
public static readonly SortedDictionary<string, Type> AllTypes = new SortedDictionary<string, Type>(StringComparer.OrdinalIgnoreCase);
|
||||
protected static readonly SortedDictionary<string, Type> AllTypes = new SortedDictionary<string, Type>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
public static readonly List<string> AllNamespaces = new List<string>();
|
||||
private static readonly HashSet<string> uniqueNamespaces = new HashSet<string>();
|
||||
@ -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)
|
||||
@ -222,7 +225,7 @@ namespace UnityExplorer
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
|
||||
#region Type and Generic Parameter implementation cache
|
||||
@ -357,7 +360,7 @@ namespace UnityExplorer
|
||||
return genericParameterInheritance[key];
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
|
||||
#region Internal MemberInfo Cache
|
||||
@ -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)
|
||||
@ -477,7 +493,7 @@ namespace UnityExplorer
|
||||
|
||||
|
||||
// Temp fix for IL2CPP until interface support improves
|
||||
|
||||
|
||||
// IsEnumerable
|
||||
|
||||
public static bool IsEnumerable(Type type) => Instance.Internal_IsEnumerable(type);
|
||||
@ -489,7 +505,7 @@ namespace UnityExplorer
|
||||
|
||||
// TryGetEnumerator (list)
|
||||
|
||||
public static bool TryGetEnumerator(object list, out IEnumerator enumerator)
|
||||
public static bool TryGetEnumerator(object list, out IEnumerator enumerator)
|
||||
=> Instance.Internal_TryGetEnumerator(list, out enumerator);
|
||||
|
||||
protected virtual bool Internal_TryGetEnumerator(object list, out IEnumerator enumerator)
|
||||
@ -530,7 +546,7 @@ namespace UnityExplorer
|
||||
type = typeof(object);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// IsDictionary
|
||||
|
||||
public static bool IsDictionary(Type type) => Instance.Internal_IsDictionary(type);
|
||||
@ -542,7 +558,7 @@ namespace UnityExplorer
|
||||
|
||||
// TryGetEnumerator (dictionary)
|
||||
|
||||
public static bool TryGetDictEnumerator(object dictionary, out IEnumerator<DictionaryEntry> dictEnumerator)
|
||||
public static bool TryGetDictEnumerator(object dictionary, out IEnumerator<DictionaryEntry> dictEnumerator)
|
||||
=> Instance.Internal_TryGetDictEnumerator(dictionary, out dictEnumerator);
|
||||
|
||||
protected virtual bool Internal_TryGetDictEnumerator(object dictionary, out IEnumerator<DictionaryEntry> dictEnumerator)
|
||||
|
@ -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)
|
||||
|
@ -143,7 +143,7 @@ public static class MonoExtensions
|
||||
{
|
||||
if (pi_childControlHeight == null)
|
||||
pi_childControlHeight = group.GetType().GetProperty("childControlHeight");
|
||||
|
||||
|
||||
pi_childControlHeight?.SetValue(group, value, null);
|
||||
}
|
||||
|
||||
|
@ -2,11 +2,11 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityExplorer.UI.CacheObject.IValues;
|
||||
using System.Reflection;
|
||||
using UnityExplorer.UI;
|
||||
using UnityExplorer.UI.CacheObject.IValues;
|
||||
#if CPP
|
||||
using UnhollowerRuntimeLib;
|
||||
using UnhollowerBaseLib;
|
||||
@ -16,7 +16,7 @@ namespace UnityExplorer.Tests
|
||||
{
|
||||
public class TestIndexer : IList<int>
|
||||
{
|
||||
private readonly List<int> list = new List<int>() { 1,2,3,4,5 };
|
||||
private readonly List<int> list = new List<int>() { 1, 2, 3, 4, 5 };
|
||||
|
||||
public int Count => list.Count;
|
||||
public bool IsReadOnly => false;
|
||||
@ -133,21 +133,21 @@ namespace UnityExplorer.Tests
|
||||
}
|
||||
}
|
||||
|
||||
private static void TestGeneric<T>()
|
||||
private static void TestGeneric<T>()
|
||||
{
|
||||
ExplorerCore.Log("Test1 " + typeof(T).FullName);
|
||||
}
|
||||
|
||||
|
||||
private static void TestGenericClass<T>() where T : class
|
||||
{
|
||||
ExplorerCore.Log("Test2 " + typeof(T).FullName);
|
||||
}
|
||||
|
||||
|
||||
private static void TestComponent<T>() where T : Component
|
||||
{
|
||||
ExplorerCore.Log("Test3 " + typeof(T).FullName);
|
||||
}
|
||||
|
||||
|
||||
private static void TestStruct<T>() where T : struct
|
||||
{
|
||||
ExplorerCore.Log("Test3 " + typeof(T).FullName);
|
||||
|
@ -22,7 +22,7 @@ namespace UnityExplorer
|
||||
public const string NUMBER_FORMAT = "0.####";
|
||||
|
||||
private static readonly Dictionary<int, string> numSequenceStrings = new Dictionary<int, string>();
|
||||
|
||||
|
||||
// Helper for formatting float/double/decimal numbers to maximum of 4 decimal points.
|
||||
public static string FormatDecimalSequence(params object[] numbers)
|
||||
{
|
||||
@ -100,7 +100,7 @@ namespace UnityExplorer
|
||||
obj = ReflectionUtility.GetMethodInfo(type, "Parse", ArgumentUtility.ParseArgs)
|
||||
.Invoke(null, new object[] { input });
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
@ -148,7 +148,7 @@ namespace UnityExplorer
|
||||
}
|
||||
else
|
||||
return obj.ToString();
|
||||
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@ -151,10 +151,10 @@ namespace UnityExplorer
|
||||
private static string HighlightType(Type type)
|
||||
{
|
||||
string key = type.ToString();
|
||||
|
||||
|
||||
if (typeToRichType.ContainsKey(key))
|
||||
return typeToRichType[key];
|
||||
|
||||
|
||||
var sb = new StringBuilder(type.Name);
|
||||
|
||||
bool isArray = false;
|
||||
@ -212,7 +212,7 @@ namespace UnityExplorer
|
||||
{
|
||||
if (args.Length < 1)
|
||||
return string.Empty;
|
||||
|
||||
|
||||
var sb = new StringBuilder();
|
||||
|
||||
for (int i = 0; i < args.Length; i++)
|
||||
@ -254,7 +254,7 @@ namespace UnityExplorer
|
||||
isStatic = true;
|
||||
return FIELD_STATIC;
|
||||
}
|
||||
|
||||
|
||||
return FIELD_INSTANCE;
|
||||
}
|
||||
else if (memberInfo is MethodInfo mi)
|
||||
@ -264,7 +264,7 @@ namespace UnityExplorer
|
||||
isStatic = true;
|
||||
return METHOD_STATIC;
|
||||
}
|
||||
|
||||
|
||||
return METHOD_INSTANCE;
|
||||
}
|
||||
else if (memberInfo is PropertyInfo pi)
|
||||
@ -274,7 +274,7 @@ namespace UnityExplorer
|
||||
isStatic = true;
|
||||
return PROP_STATIC;
|
||||
}
|
||||
|
||||
|
||||
return PROP_INSTANCE;
|
||||
}
|
||||
//else if (memberInfo is EventInfo ei)
|
||||
@ -284,7 +284,7 @@ namespace UnityExplorer
|
||||
// isStatic = true;
|
||||
// return EVENT_STATIC;
|
||||
// }
|
||||
|
||||
|
||||
// return EVENT_INSTANCE;
|
||||
//}
|
||||
|
||||
|
@ -81,7 +81,7 @@ namespace UnityExplorer
|
||||
sb.Append(PruneString(obj.name, 50, 1));
|
||||
sb.Append('"');
|
||||
}
|
||||
|
||||
|
||||
AppendRichType(sb, richType);
|
||||
}
|
||||
else if (type.FullName.StartsWith(eventSystemNamespace))
|
||||
@ -93,8 +93,8 @@ namespace UnityExplorer
|
||||
{
|
||||
var toString = ToString(value);
|
||||
|
||||
if (type.IsGenericType
|
||||
|| toString == type.FullName
|
||||
if (type.IsGenericType
|
||||
|| toString == type.FullName
|
||||
|| toString == $"{type.FullName} {type.FullName}"
|
||||
|| toString == $"Il2Cpp{type.FullName}" || type.FullName == $"Il2Cpp{toString}")
|
||||
{
|
||||
|
@ -20,7 +20,7 @@ namespace UnityExplorer
|
||||
public static class ExplorerCore
|
||||
{
|
||||
public const string NAME = "UnityExplorer";
|
||||
public const string VERSION = "4.0.7";
|
||||
public const string VERSION = "4.1.4";
|
||||
public const string AUTHOR = "Sinai";
|
||||
public const string GUID = "com.sinai.unityexplorer";
|
||||
|
||||
@ -103,15 +103,15 @@ namespace UnityExplorer
|
||||
RuntimeProvider.Instance.ProcessOnPostRender();
|
||||
}
|
||||
|
||||
#region LOGGING
|
||||
#region LOGGING
|
||||
|
||||
public static void Log(object message)
|
||||
public static void Log(object message)
|
||||
=> Log(message, LogType.Log);
|
||||
|
||||
public static void LogWarning(object message)
|
||||
public static void LogWarning(object message)
|
||||
=> Log(message, LogType.Warning);
|
||||
|
||||
public static void LogError(object message)
|
||||
public static void LogError(object message)
|
||||
=> Log(message, LogType.Error);
|
||||
|
||||
public static void LogUnity(object message, LogType logType)
|
||||
@ -146,6 +146,6 @@ namespace UnityExplorer
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
@ -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>
|
@ -27,7 +27,7 @@ namespace UnityExplorer.Loader.BIE
|
||||
|
||||
var entry = Config.Bind(CTG_NAME, config.Name, config.Value, new ConfigDescription(config.Description, null, tags));
|
||||
|
||||
entry.SettingChanged += (object o, EventArgs e) =>
|
||||
entry.SettingChanged += (object o, EventArgs e) =>
|
||||
{
|
||||
config.Value = entry.Value;
|
||||
};
|
||||
|
@ -7,12 +7,12 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityExplorer.Core.Config;
|
||||
using UnityExplorer.Loader.BIE;
|
||||
using UnityEngine;
|
||||
using UnityExplorer.Core;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityExplorer.Core;
|
||||
using UnityExplorer.Core.Config;
|
||||
using UnityExplorer.Core.Input;
|
||||
using UnityExplorer.Loader.BIE;
|
||||
#if CPP
|
||||
using BepInEx.IL2CPP;
|
||||
using UnhollowerRuntimeLib;
|
||||
@ -46,11 +46,10 @@ namespace UnityExplorer
|
||||
private static readonly Harmony s_harmony = new Harmony(ExplorerCore.GUID);
|
||||
|
||||
public string ExplorerFolder => Path.Combine(Paths.PluginPath, ExplorerCore.NAME);
|
||||
public string ConfigFolder => Path.Combine(Paths.ConfigPath, ExplorerCore.NAME);
|
||||
|
||||
public Action<object> OnLogMessage => LogSource.LogMessage;
|
||||
public Action<object> OnLogWarning => LogSource.LogWarning;
|
||||
public Action<object> OnLogError => LogSource.LogError;
|
||||
public Action<object> OnLogError => LogSource.LogError;
|
||||
|
||||
// Init common to Mono and Il2Cpp
|
||||
internal void UniversalInit()
|
||||
|
@ -10,7 +10,6 @@ namespace UnityExplorer
|
||||
{
|
||||
string ExplorerFolder { get; }
|
||||
|
||||
string ConfigFolder { get; }
|
||||
ConfigHandler ConfigHandler { get; }
|
||||
|
||||
Action<object> OnLogMessage { get; }
|
||||
|
@ -27,7 +27,6 @@ namespace UnityExplorer
|
||||
public static ExplorerMelonMod Instance;
|
||||
|
||||
public string ExplorerFolder => Path.Combine("Mods", ExplorerCore.NAME);
|
||||
public string ConfigFolder => ExplorerFolder;
|
||||
|
||||
public ConfigHandler ConfigHandler => _configHandler;
|
||||
public MelonLoaderConfigHandler _configHandler;
|
||||
|
@ -76,8 +76,6 @@ namespace UnityExplorer
|
||||
}
|
||||
private static string s_explorerFolder;
|
||||
|
||||
public string ConfigFolder => ExplorerFolder;
|
||||
|
||||
Action<object> IExplorerLoader.OnLogMessage => (object log) => { OnLog?.Invoke(log?.ToString() ?? "", LogType.Log); };
|
||||
Action<object> IExplorerLoader.OnLogWarning => (object log) => { OnLog?.Invoke(log?.ToString() ?? "", LogType.Warning); };
|
||||
Action<object> IExplorerLoader.OnLogError => (object log) => { OnLog?.Invoke(log?.ToString() ?? "", LogType.Error); };
|
||||
|
@ -13,11 +13,11 @@ namespace UnityExplorer.Loader.STANDALONE
|
||||
public class StandaloneConfigHandler : ConfigHandler
|
||||
{
|
||||
internal static IniDataParser _parser;
|
||||
internal static string INI_PATH;
|
||||
internal static string CONFIG_PATH;
|
||||
|
||||
public override void Init()
|
||||
{
|
||||
INI_PATH = Path.Combine(ExplorerCore.Loader.ConfigFolder, "config.ini");
|
||||
CONFIG_PATH = Path.Combine(ExplorerCore.Loader.ExplorerFolder, "config.ini");
|
||||
_parser = new IniDataParser();
|
||||
_parser.Configuration.CommentString = "#";
|
||||
}
|
||||
@ -49,10 +49,10 @@ namespace UnityExplorer.Loader.STANDALONE
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!File.Exists(INI_PATH))
|
||||
if (!File.Exists(CONFIG_PATH))
|
||||
return false;
|
||||
|
||||
string ini = File.ReadAllText(INI_PATH);
|
||||
string ini = File.ReadAllText(CONFIG_PATH);
|
||||
|
||||
var data = _parser.Parse(ini);
|
||||
|
||||
@ -97,10 +97,10 @@ namespace UnityExplorer.Loader.STANDALONE
|
||||
foreach (var entry in ConfigManager.ConfigElements)
|
||||
sec.AddKey(entry.Key, entry.Value.BoxedValue.ToString());
|
||||
|
||||
if (!Directory.Exists(ExplorerCore.Loader.ConfigFolder))
|
||||
Directory.CreateDirectory(ExplorerCore.Loader.ConfigFolder);
|
||||
if (!Directory.Exists(ExplorerCore.Loader.ExplorerFolder))
|
||||
Directory.CreateDirectory(ExplorerCore.Loader.ExplorerFolder);
|
||||
|
||||
File.WriteAllText(INI_PATH, data.ToString());
|
||||
File.WriteAllText(CONFIG_PATH, data.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,6 @@ namespace UnityExplorer.UI.CSConsole
|
||||
AutoCompleteModal.Instance.ReleaseOwnership(this);
|
||||
}
|
||||
|
||||
// Delimiters for completions, notably does not include '.'
|
||||
private readonly HashSet<char> delimiters = new HashSet<char>
|
||||
{
|
||||
'{', '}', ',', ';', '<', '>', '(', ')', '[', ']', '=', '|', '&', '?'
|
||||
@ -41,7 +40,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,22 +54,22 @@ 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
|
||||
|
||||
string[] evaluatorCompletions = ConsoleController.Evaluator.GetCompletions(input, out string prefix);
|
||||
|
||||
|
||||
if (evaluatorCompletions != null && evaluatorCompletions.Any())
|
||||
{
|
||||
suggestions.AddRange(from completion in evaluatorCompletions
|
||||
@ -99,7 +98,7 @@ namespace UnityExplorer.UI.CSConsole
|
||||
{
|
||||
if (!keywordHighlights.ContainsKey(kw))
|
||||
keywordHighlights.Add(kw, $"<color=#{SignatureHighlighter.keywordBlueHex}>{kw}</color>");
|
||||
|
||||
|
||||
string completion = kw.Substring(input.Length, kw.Length - input.Length);
|
||||
suggestions.Add(new Suggestion(keywordHighlights[kw], completion));
|
||||
}
|
||||
@ -123,7 +122,7 @@ namespace UnityExplorer.UI.CSConsole
|
||||
|
||||
private readonly StringBuilder highlightBuilder = new StringBuilder();
|
||||
private const string OPEN_HIGHLIGHT = "<color=cyan>";
|
||||
|
||||
|
||||
private string GetHighlightString(string prefix, string completion)
|
||||
{
|
||||
highlightBuilder.Clear();
|
||||
|
@ -1,17 +1,18 @@
|
||||
using System;
|
||||
using Mono.CSharp;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.UI.CSConsole;
|
||||
using UnityExplorer.Core.Input;
|
||||
using UnityExplorer.UI.CSConsole;
|
||||
using UnityExplorer.UI.Panels;
|
||||
using UnityExplorer.UI.Widgets.AutoComplete;
|
||||
using System.Reflection;
|
||||
|
||||
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');
|
||||
@ -221,7 +221,7 @@ namespace UnityExplorer.UI.CSConsole
|
||||
if (InputManager.GetKeyDown(KeyCode.Escape))
|
||||
{
|
||||
Input.Text = previousInput;
|
||||
|
||||
|
||||
if (EnableSuggestions && AutoCompleteModal.CheckEscape(Completer))
|
||||
OnAutocompleteEscaped();
|
||||
|
||||
@ -231,19 +231,26 @@ 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 _);
|
||||
}
|
||||
@ -257,16 +264,16 @@ 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
|
||||
@ -372,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;
|
||||
@ -410,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;
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ namespace UnityExplorer.UI.CSConsole.Lexers
|
||||
while (!lexer.EndOfInput && !(lexer.Current == '/' && lexer.Previous == '*'));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -12,12 +12,12 @@ namespace UnityExplorer.UI.CSConsole.Lexers
|
||||
public static readonly HashSet<string> keywords = new HashSet<string>
|
||||
{
|
||||
// reserved keywords
|
||||
"abstract", "as", "base", "bool", "break", "byte", "case", "catch", "char", "checked", "class", "const", "continue",
|
||||
"abstract", "as", "base", "bool", "break", "byte", "case", "catch", "char", "checked", "class", "const", "continue",
|
||||
"decimal", "default", "delegate", "do", "double", "else", "enum", "event", "explicit", "extern", "false", "finally",
|
||||
"fixed", "float", "for", "foreach", "goto", "if", "implicit", "in", "int", "interface", "internal", "is", "lock",
|
||||
"long", "namespace", "new", "null", "object", "operator", "out", "override", "params", "private", "protected", "public",
|
||||
"readonly", "ref", "return", "sbyte", "sealed", "short", "sizeof", "stackalloc", "static", "string", "struct", "switch",
|
||||
"this", "throw", "true", "try", "typeof", "uint", "ulong", "unchecked", "unsafe", "ushort", "using", "virtual", "void",
|
||||
"fixed", "float", "for", "foreach", "goto", "if", "implicit", "in", "int", "interface", "internal", "is", "lock",
|
||||
"long", "namespace", "new", "null", "object", "operator", "out", "override", "params", "private", "protected", "public",
|
||||
"readonly", "ref", "return", "sbyte", "sealed", "short", "sizeof", "stackalloc", "static", "string", "struct", "switch",
|
||||
"this", "throw", "true", "try", "typeof", "uint", "ulong", "unchecked", "unsafe", "ushort", "using", "virtual", "void",
|
||||
"volatile", "while",
|
||||
// contextual keywords
|
||||
"add", "and", "alias", "ascending", "async", "await", "by", "descending", "dynamic", "equals", "from", "get",
|
||||
@ -41,6 +41,10 @@ namespace UnityExplorer.UI.CSConsole.Lexers
|
||||
while (!lexer.EndOfInput && char.IsLetter(lexer.PeekNext()))
|
||||
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)
|
||||
|
@ -1,6 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityExplorer.UI.CSConsole.Lexers
|
||||
{
|
||||
|
@ -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);
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
using System;
|
||||
using Mono.CSharp;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using Mono.CSharp;
|
||||
|
||||
// Thanks to ManlyMarco for this
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
using System;
|
||||
using Mono.CSharp;
|
||||
using Mono.CSharp;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityExplorer.Core.Runtime;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityExplorer.Core.Runtime;
|
||||
|
||||
/*
|
||||
Welcome to the UnityExplorer C# Console!
|
||||
@ -58,7 +58,7 @@ namespace UnityExplorer.UI.CSConsole
|
||||
public static void GetClasses()
|
||||
{
|
||||
if (ReflectionUtility.GetFieldInfo(typeof(Evaluator), "source_file")
|
||||
.GetValue(Evaluator) is CompilationSourceFile sourceFile
|
||||
.GetValue(Evaluator) is CompilationSourceFile sourceFile
|
||||
&& sourceFile.Containers.Any())
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
|
@ -2,8 +2,8 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityExplorer.UI.CacheObject.Views;
|
||||
using UnityExplorer.UI.CacheObject.IValues;
|
||||
using UnityExplorer.UI.CacheObject.Views;
|
||||
|
||||
namespace UnityExplorer.UI.CacheObject
|
||||
{
|
||||
|
@ -2,8 +2,8 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityExplorer.UI.CacheObject.Views;
|
||||
using UnityExplorer.UI.CacheObject.IValues;
|
||||
using UnityExplorer.UI.CacheObject.Views;
|
||||
|
||||
namespace UnityExplorer.UI.CacheObject
|
||||
{
|
||||
|
@ -15,7 +15,7 @@ namespace UnityExplorer.UI.CacheObject
|
||||
{
|
||||
//public ReflectionInspector ParentInspector { get; internal set; }
|
||||
//public bool AutoUpdateWanted { get; internal set; }
|
||||
|
||||
|
||||
public abstract Type DeclaringType { get; }
|
||||
public string NameForFiltering { get; protected set; }
|
||||
public object DeclaringInstance => IsStatic ? null : (m_declaringInstance ?? (m_declaringInstance = Owner.Target.TryCast(DeclaringType)));
|
||||
@ -27,7 +27,7 @@ namespace UnityExplorer.UI.CacheObject
|
||||
public Type[] GenericArguments { get; protected set; } = ArgumentUtility.EmptyTypes;
|
||||
public EvaluateWidget Evaluator { get; protected set; }
|
||||
public bool Evaluating => Evaluator != null && Evaluator.UIRoot.activeSelf;
|
||||
|
||||
|
||||
public virtual void SetInspectorOwner(ReflectionInspector inspector, MemberInfo member)
|
||||
{
|
||||
this.Owner = inspector;
|
||||
@ -234,7 +234,7 @@ namespace UnityExplorer.UI.CacheObject
|
||||
return sorted;
|
||||
}
|
||||
|
||||
private static void TryCacheMember(MemberInfo member, List<CacheMember> list, HashSet<string> cachedSigs,
|
||||
private static void TryCacheMember(MemberInfo member, List<CacheMember> list, HashSet<string> cachedSigs,
|
||||
Type declaringType, ReflectionInspector _inspector, bool ignorePropertyMethodInfos = true)
|
||||
{
|
||||
try
|
||||
@ -253,7 +253,7 @@ namespace UnityExplorer.UI.CacheObject
|
||||
case MemberTypes.Method:
|
||||
{
|
||||
var mi = member as MethodInfo;
|
||||
if (ignorePropertyMethodInfos
|
||||
if (ignorePropertyMethodInfos
|
||||
&& (mi.Name.StartsWith("get_") || mi.Name.StartsWith("set_")))
|
||||
return;
|
||||
|
||||
@ -322,7 +322,7 @@ namespace UnityExplorer.UI.CacheObject
|
||||
}
|
||||
}
|
||||
|
||||
internal static string GetSig(MemberInfo member)
|
||||
internal static string GetSig(MemberInfo member)
|
||||
=> $"{member.DeclaringType.Name}.{member.Name}";
|
||||
|
||||
internal static string GetArgumentString(ParameterInfo[] args)
|
||||
|
@ -7,8 +7,8 @@ using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.Core.Runtime;
|
||||
using UnityExplorer.UI.CacheObject.Views;
|
||||
using UnityExplorer.UI.CacheObject.IValues;
|
||||
using UnityExplorer.UI.CacheObject.Views;
|
||||
using UnityExplorer.UI.Models;
|
||||
|
||||
namespace UnityExplorer.UI.CacheObject
|
||||
@ -180,8 +180,8 @@ namespace UnityExplorer.UI.CacheObject
|
||||
return ValueState.Enum;
|
||||
else if (type == typeof(Color) || type == typeof(Color32))
|
||||
return ValueState.Color;
|
||||
else if (InteractiveValueStruct.SupportsType(type))
|
||||
return ValueState.ValueStruct;
|
||||
else if (InteractiveValueStruct.SupportsType(type))
|
||||
return ValueState.ValueStruct;
|
||||
else if (ReflectionUtility.IsDictionary(type))
|
||||
return ValueState.Dictionary;
|
||||
else if (!typeof(Transform).IsAssignableFrom(type) && ReflectionUtility.IsEnumerable(type))
|
||||
@ -197,7 +197,7 @@ namespace UnityExplorer.UI.CacheObject
|
||||
switch (State)
|
||||
{
|
||||
case ValueState.NotEvaluated:
|
||||
return $"<i>{NOT_YET_EVAL} ({SignatureHighlighter.Parse(FallbackType, true)})</i>";
|
||||
return $"<i>{NOT_YET_EVAL} ({SignatureHighlighter.Parse(FallbackType, true)})</i>";
|
||||
|
||||
case ValueState.Exception:
|
||||
return $"<i><color=red>{LastException.ReflectionExToString()}</color></i>";
|
||||
@ -221,7 +221,7 @@ namespace UnityExplorer.UI.CacheObject
|
||||
return $"\"{ToStringUtility.PruneString(s, 200, 5)}\"";
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
// try to prefix the count of the collection for lists and dicts
|
||||
case ValueState.Collection:
|
||||
if (!LastValueWasNull)
|
||||
@ -263,7 +263,7 @@ namespace UnityExplorer.UI.CacheObject
|
||||
|
||||
cell.SubContentHolder.gameObject.SetActive(SubContentShowWanted);
|
||||
if (IValue != null)
|
||||
{
|
||||
{
|
||||
IValue.UIRoot.transform.SetParent(cell.SubContentHolder.transform, false);
|
||||
IValue.SetLayout();
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -20,7 +20,7 @@ namespace UnityExplorer.UI.CacheObject.IValues
|
||||
|
||||
public CachedEnumValue ValueAtIdx(int idx) => (CachedEnumValue)CurrentValues[idx];
|
||||
public CachedEnumValue ValueAtKey(object key) => (CachedEnumValue)CurrentValues[key];
|
||||
|
||||
|
||||
private Dropdown enumDropdown;
|
||||
private GameObject toggleHolder;
|
||||
private readonly List<Toggle> flagToggles = new List<Toggle>();
|
||||
|
@ -206,7 +206,7 @@ namespace UnityExplorer.UI.CacheObject.IValues
|
||||
{
|
||||
ExplorerCore.LogWarning($"Exception setting IList value: {ex}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// List entry scroll pool
|
||||
|
||||
@ -254,8 +254,8 @@ namespace UnityExplorer.UI.CacheObject.IValues
|
||||
ListScrollPool.Initialize(this, SetLayout);
|
||||
scrollLayout = scrollObj.GetComponent<LayoutElement>();
|
||||
|
||||
NotSupportedLabel = UIFactory.CreateLabel(ListScrollPool.Content.gameObject, "NotSupportedMessage",
|
||||
"The IEnumerable failed to enumerate. This is likely due to an issue with Unhollowed interfaces.",
|
||||
NotSupportedLabel = UIFactory.CreateLabel(ListScrollPool.Content.gameObject, "NotSupportedMessage",
|
||||
"The IEnumerable failed to enumerate. This is likely due to an issue with Unhollowed interfaces.",
|
||||
TextAnchor.MiddleLeft, Color.red);
|
||||
|
||||
UIFactory.SetLayoutElement(NotSupportedLabel.gameObject, minHeight: 25, flexibleWidth: 9999);
|
||||
|
@ -18,7 +18,7 @@ namespace UnityExplorer.UI.CacheObject.IValues
|
||||
|
||||
public InputFieldRef inputField;
|
||||
public ButtonRef ApplyButton;
|
||||
|
||||
|
||||
public GameObject SaveFileRow;
|
||||
public InputFieldRef SaveFilePath;
|
||||
|
||||
@ -36,7 +36,7 @@ namespace UnityExplorer.UI.CacheObject.IValues
|
||||
{
|
||||
if (s == null)
|
||||
return false;
|
||||
|
||||
|
||||
return s.Length >= UIManager.MAX_INPUTFIELD_CHARS;
|
||||
}
|
||||
|
||||
@ -83,7 +83,7 @@ namespace UnityExplorer.UI.CacheObject.IValues
|
||||
|
||||
if (File.Exists(path))
|
||||
File.Delete(path);
|
||||
|
||||
|
||||
File.WriteAllText(path, RealValue);
|
||||
}
|
||||
|
||||
@ -98,7 +98,7 @@ namespace UnityExplorer.UI.CacheObject.IValues
|
||||
UIFactory.SetLayoutElement(SaveFileRow, flexibleWidth: 9999);
|
||||
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(SaveFileRow, false, true, true, true, 3);
|
||||
|
||||
UIFactory.CreateLabel(SaveFileRow, "Info", "<color=red>String is too long! Save to file if you want to see the full string.</color>",
|
||||
UIFactory.CreateLabel(SaveFileRow, "Info", "<color=red>String is too long! Save to file if you want to see the full string.</color>",
|
||||
TextAnchor.MiddleLeft);
|
||||
|
||||
var horizRow = UIFactory.CreateUIObject("Horiz", SaveFileRow);
|
||||
|
@ -143,7 +143,7 @@ namespace UnityExplorer.UI.CacheObject.IValues
|
||||
ExplorerCore.LogWarning("Exception setting value: " + ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// UI Setup for type
|
||||
|
||||
private void SetupUIForType()
|
||||
|
@ -4,8 +4,8 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.UI.Inspectors;
|
||||
using UnityExplorer.UI.CacheObject.IValues;
|
||||
using UnityExplorer.UI.Inspectors;
|
||||
using UnityExplorer.UI.Widgets;
|
||||
|
||||
namespace UnityExplorer.UI.CacheObject.Views
|
||||
|
@ -4,8 +4,8 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.UI.Inspectors;
|
||||
using UnityExplorer.UI.CacheObject.IValues;
|
||||
using UnityExplorer.UI.Inspectors;
|
||||
using UnityExplorer.UI.Widgets;
|
||||
|
||||
namespace UnityExplorer.UI.CacheObject.Views
|
||||
|
@ -67,7 +67,7 @@ namespace UnityExplorer.UI.CacheObject.Views
|
||||
|
||||
for (int i = 0; i < genericArguments.Length; i++)
|
||||
{
|
||||
outArgs[i] = ReflectionUtility.GetTypeByName(genericInput[i])
|
||||
outArgs[i] = ReflectionUtility.GetTypeByName(genericInput[i])
|
||||
?? throw new Exception($"Could not find any type by name '{genericInput[i]}'!");
|
||||
}
|
||||
|
||||
@ -206,7 +206,7 @@ namespace UnityExplorer.UI.CacheObject.Views
|
||||
var elemType = arg.ParameterType;
|
||||
if (elemType.IsByRef)
|
||||
elemType = elemType.GetElementType();
|
||||
argInputFields[i].PlaceholderText.text = $"eg. {ParseUtility.GetExampleInput(elemType)}";
|
||||
argInputFields[i].PlaceholderText.text = $"eg. {ParseUtility.GetExampleInput(elemType)}";
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -249,7 +249,7 @@ namespace UnityExplorer.UI.CacheObject.Views
|
||||
|
||||
public GameObject CreateContent(GameObject parent)
|
||||
{
|
||||
UIRoot = UIFactory.CreateVerticalGroup(parent, "EvaluateWidget", false, false, true, true, 3, new Vector4(2, 2, 2, 2),
|
||||
UIRoot = UIFactory.CreateVerticalGroup(parent, "EvaluateWidget", false, false, true, true, 3, new Vector4(2, 2, 2, 2),
|
||||
new Color(0.15f, 0.15f, 0.15f));
|
||||
UIFactory.SetLayoutElement(UIRoot, minWidth: 50, flexibleWidth: 9999, minHeight: 50, flexibleHeight: 800);
|
||||
//UIRoot.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||||
@ -275,7 +275,7 @@ namespace UnityExplorer.UI.CacheObject.Views
|
||||
// evaluate button
|
||||
var evalButton = UIFactory.CreateButton(UIRoot, "EvaluateButton", "Evaluate", new Color(0.2f, 0.2f, 0.2f));
|
||||
UIFactory.SetLayoutElement(evalButton.Component.gameObject, minHeight: 25, minWidth: 150, flexibleWidth: 0);
|
||||
evalButton.OnClick += () =>
|
||||
evalButton.OnClick += () =>
|
||||
{
|
||||
Owner.EvaluateAndSetCell();
|
||||
};
|
||||
|
@ -147,32 +147,39 @@ namespace UnityExplorer.UI.Inspectors
|
||||
var behaviours = GOTarget.GetComponents<Behaviour>();
|
||||
|
||||
bool needRefresh = false;
|
||||
if (comps.Length != componentEntries.Count || behaviours.Length != behaviourEntries.Count)
|
||||
{
|
||||
needRefresh = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var comp in comps)
|
||||
{
|
||||
if (!compInstanceIDs.Contains(comp.GetInstanceID()))
|
||||
{
|
||||
needRefresh = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!needRefresh)
|
||||
int count = 0;
|
||||
foreach (var comp in comps)
|
||||
{
|
||||
if (!comp)
|
||||
continue;
|
||||
count++;
|
||||
if (!compInstanceIDs.Contains(comp.GetInstanceID()))
|
||||
{
|
||||
for (int i = 0; i < behaviours.Length; i++)
|
||||
needRefresh = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!needRefresh)
|
||||
{
|
||||
if (count != componentEntries.Count)
|
||||
needRefresh = true;
|
||||
else
|
||||
{
|
||||
count = 0;
|
||||
foreach (var behaviour in behaviours)
|
||||
{
|
||||
var behaviour = behaviours[i];
|
||||
if (behaviour.enabled != behaviourEnabledStates[i])
|
||||
if (!behaviour)
|
||||
continue;
|
||||
if (count >= behaviourEnabledStates.Count || behaviour.enabled != behaviourEnabledStates[count])
|
||||
{
|
||||
needRefresh = true;
|
||||
break;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
if (!needRefresh && count != behaviourEntries.Count)
|
||||
needRefresh = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -181,9 +188,9 @@ namespace UnityExplorer.UI.Inspectors
|
||||
|
||||
componentEntries.Clear();
|
||||
compInstanceIDs.Clear();
|
||||
|
||||
foreach (var comp in comps)
|
||||
{
|
||||
if (!comp) continue;
|
||||
componentEntries.Add(comp);
|
||||
compInstanceIDs.Add(comp.GetInstanceID());
|
||||
}
|
||||
@ -192,6 +199,7 @@ namespace UnityExplorer.UI.Inspectors
|
||||
behaviourEnabledStates.Clear();
|
||||
foreach (var behaviour in behaviours)
|
||||
{
|
||||
if (!behaviour) continue;
|
||||
behaviourEntries.Add(behaviour);
|
||||
behaviourEnabledStates.Add(behaviour.enabled);
|
||||
}
|
||||
@ -208,10 +216,10 @@ namespace UnityExplorer.UI.Inspectors
|
||||
|
||||
TransformTree.RefreshData(true, false);
|
||||
}
|
||||
|
||||
|
||||
private void OnAddComponentClicked(string input)
|
||||
{
|
||||
if (ReflectionUtility.AllTypes.TryGetValue(input, out Type type))
|
||||
if (ReflectionUtility.GetTypeByName(input) is Type type)
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -234,10 +242,10 @@ namespace UnityExplorer.UI.Inspectors
|
||||
|
||||
public override GameObject CreateContent(GameObject parent)
|
||||
{
|
||||
UIRoot = UIFactory.CreateVerticalGroup(parent, "GameObjectInspector", true, false, true, true, 5,
|
||||
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,
|
||||
var scrollObj = UIFactory.CreateScrollView(UIRoot, "GameObjectInspector", out Content, out var scrollbar,
|
||||
new Color(0.065f, 0.065f, 0.065f));
|
||||
UIFactory.SetLayoutElement(scrollObj, minHeight: 250, preferredHeight: 300, flexibleHeight: 0, flexibleWidth: 9999);
|
||||
|
||||
@ -245,7 +253,7 @@ namespace UnityExplorer.UI.Inspectors
|
||||
|
||||
// Construct GO Controls
|
||||
GOControls = new GameObjectControls(this);
|
||||
|
||||
|
||||
ConstructLists();
|
||||
|
||||
return UIRoot;
|
||||
|
@ -11,7 +11,7 @@ namespace UnityExplorer.UI.Inspectors
|
||||
{
|
||||
public GameObjectInspector Parent;
|
||||
|
||||
public ComponentList(ScrollPool<ComponentCell> scrollPool, Func<List<Component>> getEntriesMethod)
|
||||
public ComponentList(ScrollPool<ComponentCell> scrollPool, Func<List<Component>> getEntriesMethod)
|
||||
: base(scrollPool, getEntriesMethod, null, null, null)
|
||||
{
|
||||
base.SetICell = SetComponentCell;
|
||||
@ -112,7 +112,7 @@ namespace UnityExplorer.UI.Inspectors
|
||||
cell.BehaviourToggle.interactable = false;
|
||||
cell.BehaviourToggle.Set(true, false);
|
||||
//RuntimeProvider.Instance.SetColorBlock(cell.BehaviourToggle,)
|
||||
cell.BehaviourToggle.graphic.color = new Color(0.2f, 0.2f, 0.2f);
|
||||
cell.BehaviourToggle.graphic.color = new Color(0.2f, 0.2f, 0.2f);
|
||||
}
|
||||
|
||||
// if component is the first index it must be the transform, dont show Destroy button for it.
|
||||
|
@ -186,7 +186,7 @@ namespace UnityExplorer.UI.Inspectors
|
||||
if (parentToSet)
|
||||
DoSetParent(parentToSet);
|
||||
else
|
||||
{
|
||||
{
|
||||
ExplorerCore.LogWarning($"Could not find any GameObject name or path '{input}'!");
|
||||
UpdateGameObjectInfo(false, true);
|
||||
}
|
||||
@ -442,7 +442,7 @@ namespace UnityExplorer.UI.Inspectors
|
||||
|
||||
private void ConstructTopInfo()
|
||||
{
|
||||
var topInfoHolder = UIFactory.CreateVerticalGroup(Parent.Content, "TopInfoHolder", false, false, true, true, 3,
|
||||
var topInfoHolder = UIFactory.CreateVerticalGroup(Parent.Content, "TopInfoHolder", false, false, true, true, 3,
|
||||
new Vector4(3, 3, 3, 3), new Color(0.1f, 0.1f, 0.1f), TextAnchor.MiddleLeft);
|
||||
UIFactory.SetLayoutElement(topInfoHolder, minHeight: 100, flexibleWidth: 9999);
|
||||
topInfoHolder.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||||
@ -575,7 +575,7 @@ namespace UnityExplorer.UI.Inspectors
|
||||
var flagsDrop = UIFactory.CreateDropdown(thirdrow, out FlagsDropdown, "None", 14, OnFlagsDropdownChanged);
|
||||
FlagsDropdown.captionText.color = SignatureHighlighter.EnumGreen;
|
||||
UIFactory.SetLayoutElement(flagsDrop, minHeight: 25, minWidth: 135, flexibleWidth: 999);
|
||||
if (hideFlagsValues == null)
|
||||
if (hideFlagsValues == null)
|
||||
GetHideFlagNames();
|
||||
foreach (var name in hideFlagsValues.Keys)
|
||||
FlagsDropdown.options.Add(new Dropdown.OptionData(name));
|
||||
|
@ -68,8 +68,8 @@ namespace UnityExplorer.UI.Inspectors
|
||||
{
|
||||
MainCamera = Camera.main;
|
||||
if (!MainCamera)
|
||||
return;
|
||||
|
||||
return;
|
||||
|
||||
PanelDragger.ForceEnd();
|
||||
|
||||
Mode = mode;
|
||||
@ -95,8 +95,8 @@ namespace UnityExplorer.UI.Inspectors
|
||||
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);
|
||||
|
@ -87,7 +87,7 @@ namespace UnityExplorer
|
||||
}
|
||||
}
|
||||
|
||||
private static void CreateInspector<T>(object target, bool staticReflection = false,
|
||||
private static void CreateInspector<T>(object target, bool staticReflection = false,
|
||||
CacheObjectBase sourceCache = null) where T : InspectorBase
|
||||
{
|
||||
var inspector = Pool<T>.Borrow();
|
||||
|
@ -33,7 +33,7 @@ namespace UnityExplorer.UI.Inspectors
|
||||
|
||||
public GameObject CreateContent(GameObject parent)
|
||||
{
|
||||
UIRoot = UIFactory.CreateHorizontalGroup(parent, "TabObject", false, true, true, true, 0,
|
||||
UIRoot = UIFactory.CreateHorizontalGroup(parent, "TabObject", false, true, true, true, 0,
|
||||
default, new Color(0.13f, 0.13f, 0.13f), childAlignment: TextAnchor.MiddleLeft);
|
||||
UIFactory.SetLayoutElement(UIRoot, minWidth: 200, flexibleWidth: 0);
|
||||
UIRoot.AddComponent<Mask>();
|
||||
|
@ -54,6 +54,7 @@ namespace UnityExplorer.UI.Inspectors
|
||||
|
||||
private readonly Color disabledButtonColor = new Color(0.24f, 0.24f, 0.24f);
|
||||
private readonly Color enabledButtonColor = new Color(0.2f, 0.27f, 0.2f);
|
||||
|
||||
private readonly Dictionary<BindingFlags, ButtonRef> scopeFilterButtons = new Dictionary<BindingFlags, ButtonRef>();
|
||||
private readonly List<Toggle> memberTypeToggles = new List<Toggle>();
|
||||
private InputFieldRef filterInputField;
|
||||
@ -73,7 +74,6 @@ namespace UnityExplorer.UI.Inspectors
|
||||
private IEnumerator InitCoroutine()
|
||||
{
|
||||
yield return null;
|
||||
|
||||
LayoutRebuilder.ForceRebuildLayoutImmediate(InspectorPanel.Instance.ContentRect);
|
||||
}
|
||||
|
||||
@ -142,7 +142,7 @@ namespace UnityExplorer.UI.Inspectors
|
||||
// reset filters
|
||||
|
||||
this.filterInputField.Text = "";
|
||||
|
||||
|
||||
SetFilter("", StaticOnly ? BindingFlags.Static : BindingFlags.Instance);
|
||||
scopeFilterButtons[BindingFlags.Default].Component.gameObject.SetActive(!StaticOnly);
|
||||
scopeFilterButtons[BindingFlags.Instance].Component.gameObject.SetActive(!StaticOnly);
|
||||
@ -307,11 +307,8 @@ namespace UnityExplorer.UI.Inspectors
|
||||
|
||||
private void CalculateLayouts()
|
||||
{
|
||||
// Calculate sizes
|
||||
LeftGroupWidth = (int)Math.Max(200, (0.4f * InspectorManager.PanelWidth) - 5);// Math.Min(450f, 0.4f * InspectorManager.PanelWidth - 5));
|
||||
LeftGroupWidth = (int)Math.Max(200, (0.4f * InspectorManager.PanelWidth) - 5);
|
||||
RightGroupWidth = (int)Math.Max(200, InspectorManager.PanelWidth - LeftGroupWidth - 65);
|
||||
|
||||
//memberTitleLayout.minWidth = LeftGroupWidth;
|
||||
}
|
||||
|
||||
private void SetCellLayout(CacheObjectCell cell)
|
||||
@ -342,7 +339,7 @@ namespace UnityExplorer.UI.Inspectors
|
||||
|
||||
ConstructUnityObjectRow();
|
||||
|
||||
mainContentHolder = UIFactory.CreateVerticalGroup(UIRoot, "MemberHolder", false, false, true, true, 5, new Vector4(2,2,2,2),
|
||||
mainContentHolder = UIFactory.CreateVerticalGroup(UIRoot, "MemberHolder", false, false, true, true, 5, new Vector4(2, 2, 2, 2),
|
||||
new Color(0.12f, 0.12f, 0.12f));
|
||||
UIFactory.SetLayoutElement(mainContentHolder, flexibleWidth: 9999, flexibleHeight: 9999);
|
||||
|
||||
@ -352,7 +349,7 @@ namespace UnityExplorer.UI.Inspectors
|
||||
|
||||
// Member scroll pool
|
||||
|
||||
var memberBorder = UIFactory.CreateVerticalGroup(mainContentHolder, "ScrollPoolHolder", false, false, true, true, padding: new Vector4(2,2,2,2),
|
||||
var memberBorder = UIFactory.CreateVerticalGroup(mainContentHolder, "ScrollPoolHolder", false, false, true, true, padding: new Vector4(2, 2, 2, 2),
|
||||
bgColor: new Color(0.05f, 0.05f, 0.05f));
|
||||
UIFactory.SetLayoutElement(memberBorder, flexibleWidth: 9999, flexibleHeight: 9999);
|
||||
|
||||
@ -480,7 +477,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);
|
||||
@ -546,7 +543,7 @@ namespace UnityExplorer.UI.Inspectors
|
||||
textureButton.ButtonText.text = "Hide Texture";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// UI construction
|
||||
|
||||
private void ConstructUnityObjectRow()
|
||||
@ -617,12 +614,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);
|
||||
}
|
||||
|
@ -29,8 +29,8 @@ namespace UnityExplorer.UI
|
||||
}
|
||||
}
|
||||
|
||||
public InputFieldRef(InputField component)
|
||||
{
|
||||
public InputFieldRef(InputField component)
|
||||
{
|
||||
this.Component = component;
|
||||
Rect = component.GetComponent<RectTransform>();
|
||||
PlaceholderText = component.placeholder.TryCast<Text>();
|
||||
@ -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)
|
||||
{
|
||||
|
@ -25,7 +25,7 @@ namespace UnityExplorer.UI.ObjectExplorer
|
||||
private ChildFilter m_childFilter = ChildFilter.Any;
|
||||
private string desiredTypeInput;
|
||||
private string lastCheckedTypeInput;
|
||||
private bool lastTypeCanHaveGO;
|
||||
private bool lastTypeCanHaveGO;
|
||||
|
||||
public ButtonListHandler<object, ButtonCell> dataHandler;
|
||||
|
||||
@ -76,7 +76,7 @@ namespace UnityExplorer.UI.ObjectExplorer
|
||||
lastCheckedTypeInput = desiredTypeInput;
|
||||
|
||||
//var type = ReflectionUtility.GetTypeByName(desiredTypeInput);
|
||||
if (ReflectionUtility.AllTypes.TryGetValue(desiredTypeInput, out var cachedType))
|
||||
if (ReflectionUtility.GetTypeByName(desiredTypeInput) is Type cachedType)
|
||||
{
|
||||
var type = cachedType;
|
||||
lastTypeCanHaveGO = typeof(Component).IsAssignableFrom(type) || type == typeof(GameObject);
|
||||
@ -241,7 +241,7 @@ namespace UnityExplorer.UI.ObjectExplorer
|
||||
// RESULTS SCROLL POOL
|
||||
|
||||
dataHandler = new ButtonListHandler<object, ButtonCell>(resultsScrollPool, GetEntries, SetCell, ShouldDisplayCell, OnCellClicked);
|
||||
resultsScrollPool = UIFactory.CreateScrollPool<ButtonCell>(uiRoot, "ResultsList", out GameObject scrollObj,
|
||||
resultsScrollPool = UIFactory.CreateScrollPool<ButtonCell>(uiRoot, "ResultsList", out GameObject scrollObj,
|
||||
out GameObject scrollContent);
|
||||
|
||||
resultsScrollPool.Initialize(dataHandler);
|
||||
|
@ -201,7 +201,7 @@ namespace UnityExplorer.UI.ObjectExplorer
|
||||
//Filter input field
|
||||
var inputField = UIFactory.CreateInputField(filterRow, "FilterInput", "Search...");
|
||||
inputField.Component.targetGraphic.color = new Color(0.2f, 0.2f, 0.2f);
|
||||
RuntimeProvider.Instance.SetColorBlock(inputField.Component, new Color(0.4f, 0.4f, 0.4f), new Color(0.2f, 0.2f, 0.2f),
|
||||
RuntimeProvider.Instance.SetColorBlock(inputField.Component, new Color(0.4f, 0.4f, 0.4f), new Color(0.2f, 0.2f, 0.2f),
|
||||
new Color(0.08f, 0.08f, 0.08f));
|
||||
UIFactory.SetLayoutElement(inputField.UIRoot, minHeight: 25);
|
||||
inputField.OnValueChanged += OnFilterInput;
|
||||
|
@ -13,18 +13,18 @@ namespace UnityExplorer.UI.ObjectExplorer
|
||||
/// <summary>
|
||||
/// The currently inspected Scene.
|
||||
/// </summary>
|
||||
public static Scene? SelectedScene
|
||||
public static Scene? SelectedScene
|
||||
{
|
||||
get => m_selectedScene;
|
||||
get => selectedScene;
|
||||
internal set
|
||||
{
|
||||
if (m_selectedScene != null && m_selectedScene == value)
|
||||
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.
|
||||
@ -62,7 +62,7 @@ namespace UnityExplorer.UI.ObjectExplorer
|
||||
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;
|
||||
|
||||
@ -93,7 +93,7 @@ namespace UnityExplorer.UI.ObjectExplorer
|
||||
Type sceneUtil = ReflectionUtility.GetTypeByName("UnityEngine.SceneManagement.SceneUtility");
|
||||
if (sceneUtil == null)
|
||||
throw new Exception("This version of Unity does not ship with the 'SceneUtility' class, or it was not unstripped.");
|
||||
|
||||
|
||||
var method = sceneUtil.GetMethod("GetScenePathByBuildIndex", ReflectionUtility.FLAGS);
|
||||
int sceneCount = SceneManager.sceneCountInBuildSettings;
|
||||
for (int i = 0; i < sceneCount; i++)
|
||||
|
@ -35,7 +35,7 @@ namespace UnityExplorer.UI.ObjectExplorer
|
||||
|
||||
public static class SearchProvider
|
||||
{
|
||||
|
||||
|
||||
private static bool Filter(Scene scene, SceneFilter filter)
|
||||
{
|
||||
switch (filter)
|
||||
@ -53,7 +53,7 @@ namespace UnityExplorer.UI.ObjectExplorer
|
||||
}
|
||||
}
|
||||
|
||||
internal static List<object> UnityObjectSearch(string input, string customTypeInput, SearchContext context,
|
||||
internal static List<object> UnityObjectSearch(string input, string customTypeInput, SearchContext context,
|
||||
ChildFilter childFilter, SceneFilter sceneFilter)
|
||||
{
|
||||
var results = new List<object>();
|
||||
|
@ -61,7 +61,7 @@ namespace UnityExplorer.UI.Panels
|
||||
{
|
||||
// add close all button to titlebar
|
||||
|
||||
var closeAllBtn = UIFactory.CreateButton(this.titleBar.transform.Find("CloseHolder").gameObject, "CloseAllBtn", "Close All",
|
||||
var closeAllBtn = UIFactory.CreateButton(this.titleBar.transform.Find("CloseHolder").gameObject, "CloseAllBtn", "Close All",
|
||||
new Color(0.3f, 0.2f, 0.2f));
|
||||
UIFactory.SetLayoutElement(closeAllBtn.Component.gameObject, minHeight: 25, minWidth: 80);
|
||||
closeAllBtn.Component.transform.SetSiblingIndex(closeAllBtn.Component.transform.GetSiblingIndex() - 1);
|
||||
|
@ -1,17 +1,17 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.Core.Input;
|
||||
using System.IO;
|
||||
using System.Diagnostics;
|
||||
using UnityExplorer.UI.Models;
|
||||
using System.Linq;
|
||||
using UnityExplorer.UI.Widgets.AutoComplete;
|
||||
|
||||
namespace UnityExplorer.UI.Panels
|
||||
{
|
||||
public class PanelDragger
|
||||
public class PanelDragger
|
||||
{
|
||||
#region Static
|
||||
|
||||
@ -137,7 +137,7 @@ namespace UnityExplorer.UI.Panels
|
||||
Instances.Add(this);
|
||||
DragableArea = dragArea;
|
||||
Panel = panelToDrag;
|
||||
|
||||
|
||||
if (!canvasTransform)
|
||||
canvasTransform = Panel.GetComponentInParent<Canvas>().GetComponent<RectTransform>();
|
||||
|
||||
|
@ -146,17 +146,17 @@ namespace UnityExplorer.UI.Panels
|
||||
if (Rect.rect.height < MinHeight)
|
||||
Rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, MinHeight);
|
||||
}
|
||||
|
||||
|
||||
public static void EnsureValidPosition(RectTransform panel)
|
||||
{
|
||||
var pos = panel.localPosition;
|
||||
|
||||
|
||||
// Prevent panel going oustide screen bounds
|
||||
var halfW = Screen.width * 0.5f;
|
||||
var halfH = Screen.height * 0.5f;
|
||||
pos.x = Math.Max(-halfW, Math.Min(pos.x, halfW - panel.rect.width));
|
||||
pos.y = Math.Max(-halfH + panel.rect.height, Math.Min(pos.y, halfH));
|
||||
|
||||
|
||||
panel.localPosition = pos;
|
||||
}
|
||||
|
||||
@ -225,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);
|
||||
|
@ -419,7 +419,7 @@ namespace UnityExplorer.UI
|
||||
|
||||
toggle = toggleObj.AddComponent<Toggle>();
|
||||
toggle.isOn = true;
|
||||
|
||||
|
||||
// second reference so we can use it inside the lambda, 'toggle' is an out var.
|
||||
Toggle toggleComp = toggle;
|
||||
toggle.onValueChanged.AddListener(Deselect);
|
||||
@ -729,7 +729,7 @@ namespace UnityExplorer.UI
|
||||
|
||||
var sliderContainer = CreateVerticalGroup(mainObj, "SliderContainer",
|
||||
false, false, true, true, 0, default, new Color(0.05f, 0.05f, 0.05f));
|
||||
SetLayoutElement(sliderContainer, minWidth: 25, flexibleWidth:0, flexibleHeight: 9999);
|
||||
SetLayoutElement(sliderContainer, minWidth: 25, flexibleWidth: 0, flexibleHeight: 9999);
|
||||
sliderContainer.AddComponent<Mask>();
|
||||
|
||||
CreateSliderScrollbar(sliderContainer, out Slider slider);
|
||||
@ -837,7 +837,7 @@ namespace UnityExplorer.UI
|
||||
content.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||||
|
||||
// Slider
|
||||
|
||||
|
||||
GameObject scrollBarObj = CreateUIObject("AutoSliderScrollbar", mainObj);
|
||||
var scrollBarRect = scrollBarObj.GetComponent<RectTransform>();
|
||||
scrollBarRect.anchorMin = new Vector2(1, 0);
|
||||
@ -846,22 +846,22 @@ namespace UnityExplorer.UI
|
||||
SetLayoutGroup<VerticalLayoutGroup>(scrollBarObj, false, true, true, true);
|
||||
scrollBarObj.AddComponent<Image>().color = Color.white;
|
||||
scrollBarObj.AddComponent<Mask>().showMaskGraphic = false;
|
||||
|
||||
|
||||
GameObject hiddenBar = CreateScrollbar(scrollBarObj, "HiddenScrollviewScroller", out var hiddenScrollbar);
|
||||
hiddenScrollbar.SetDirection(Scrollbar.Direction.BottomToTop, true);
|
||||
|
||||
|
||||
for (int i = 0; i < hiddenBar.transform.childCount; i++)
|
||||
{
|
||||
var child = hiddenBar.transform.GetChild(i);
|
||||
child.gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
|
||||
CreateSliderScrollbar(scrollBarObj, out Slider scrollSlider);
|
||||
|
||||
|
||||
autoScrollbar = new AutoSliderScrollbar(hiddenScrollbar, scrollSlider, contentRect, viewportRect);
|
||||
|
||||
|
||||
// Set up the ScrollRect component
|
||||
|
||||
|
||||
var scrollRect = mainObj.AddComponent<ScrollRect>();
|
||||
scrollRect.horizontal = false;
|
||||
scrollRect.vertical = true;
|
||||
@ -870,10 +870,10 @@ namespace UnityExplorer.UI
|
||||
scrollRect.scrollSensitivity = 35;
|
||||
scrollRect.horizontalScrollbarVisibility = ScrollRect.ScrollbarVisibility.AutoHideAndExpandViewport;
|
||||
scrollRect.verticalScrollbarVisibility = ScrollRect.ScrollbarVisibility.Permanent;
|
||||
|
||||
|
||||
scrollRect.viewport = viewportRect;
|
||||
scrollRect.content = contentRect;
|
||||
|
||||
|
||||
return mainObj;
|
||||
}
|
||||
|
||||
|
@ -55,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);
|
||||
@ -80,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)
|
||||
@ -120,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 (!ConfigManager.Disable_EventSystem_Override.Value && 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");
|
||||
@ -239,37 +342,17 @@ 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);
|
||||
|
||||
NavbarAnchor = ConfigManager.Main_Navbar_Anchor.Value;
|
||||
SetNavBarAnchor();
|
||||
ConfigManager.Main_Navbar_Anchor.OnValueChanged += (VerticalAnchor val) =>
|
||||
ConfigManager.Main_Navbar_Anchor.OnValueChanged += (VerticalAnchor val) =>
|
||||
{
|
||||
NavbarAnchor = val;
|
||||
SetNavBarAnchor();
|
||||
@ -278,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
|
||||
|
||||
@ -298,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
|
||||
|
@ -169,7 +169,7 @@ namespace UnityExplorer.UI.Widgets.AutoComplete
|
||||
|
||||
// Setting autocomplete cell buttons
|
||||
|
||||
private readonly Color selectedSuggestionColor = new Color(45/255f, 75/255f, 80/255f);
|
||||
private readonly Color selectedSuggestionColor = new Color(45 / 255f, 75 / 255f, 80 / 255f);
|
||||
private readonly Color inactiveSuggestionColor = new Color(0.11f, 0.11f, 0.11f);
|
||||
|
||||
private List<Suggestion> GetEntries() => Suggestions;
|
||||
@ -300,7 +300,7 @@ namespace UnityExplorer.UI.Widgets.AutoComplete
|
||||
{
|
||||
dataHandler = new ButtonListHandler<Suggestion, ButtonCell>(scrollPool, GetEntries, SetCell, ShouldDisplay, OnCellClicked);
|
||||
|
||||
scrollPool = UIFactory.CreateScrollPool<ButtonCell>(this.content, "AutoCompleter", out GameObject scrollObj,
|
||||
scrollPool = UIFactory.CreateScrollPool<ButtonCell>(this.content, "AutoCompleter", out GameObject scrollObj,
|
||||
out GameObject scrollContent);
|
||||
scrollPool.Initialize(dataHandler);
|
||||
UIFactory.SetLayoutElement(scrollObj, flexibleHeight: 9999);
|
||||
@ -308,7 +308,7 @@ namespace UnityExplorer.UI.Widgets.AutoComplete
|
||||
|
||||
navigationTipRow = UIFactory.CreateHorizontalGroup(this.content, "BottomRow", true, true, true, true, 0, new Vector4(2, 2, 2, 2));
|
||||
UIFactory.SetLayoutElement(navigationTipRow, minHeight: 20, flexibleWidth: 9999);
|
||||
UIFactory.CreateLabel(navigationTipRow, "HelpText", "Up/Down to select, Enter to use, Esc to close",
|
||||
UIFactory.CreateLabel(navigationTipRow, "HelpText", "Up/Down to select, Enter to use, Esc to close",
|
||||
TextAnchor.MiddleLeft, Color.grey, false, 13);
|
||||
|
||||
UIRoot.SetActive(false);
|
||||
|
@ -87,7 +87,7 @@ namespace UnityExplorer.UI.Widgets.AutoComplete
|
||||
}
|
||||
|
||||
// Check for exact match first
|
||||
if (ReflectionUtility.AllTypes.TryGetValue(value, out Type t) && allowedTypes.Contains(t))
|
||||
if (ReflectionUtility.GetTypeByName(value) is Type t && allowedTypes.Contains(t))
|
||||
AddSuggestion(t);
|
||||
|
||||
foreach (var entry in allowedTypes)
|
||||
|
@ -91,7 +91,7 @@ namespace UnityExplorer.UI.Widgets
|
||||
Slider.interactable = false;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
var handleHeight = viewportHeight * Math.Min(1, viewportHeight / totalHeight);
|
||||
handleHeight = Math.Max(15f, handleHeight);
|
||||
|
||||
|
@ -26,7 +26,7 @@ namespace UnityExplorer.UI.Widgets
|
||||
}
|
||||
private string currentFilter;
|
||||
|
||||
public ButtonListHandler(ScrollPool<TCell> scrollPool, Func<List<TData>> getEntriesMethod,
|
||||
public ButtonListHandler(ScrollPool<TCell> scrollPool, Func<List<TData>> getEntriesMethod,
|
||||
Action<TCell, int> setICellMethod, Func<TData, string, bool> shouldDisplayMethod,
|
||||
Action<int> onCellClickedMethod)
|
||||
{
|
||||
|
@ -4,9 +4,9 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.Events;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.UI.Models;
|
||||
|
||||
namespace UnityExplorer.UI.Widgets
|
||||
|
@ -118,7 +118,7 @@ namespace UnityExplorer.UI.Widgets
|
||||
if (!heightCache.Any())
|
||||
return;
|
||||
|
||||
totalHeight -= heightCache[heightCache.Count - 1];
|
||||
totalHeight -= heightCache[heightCache.Count - 1];
|
||||
heightCache.RemoveAt(heightCache.Count - 1);
|
||||
|
||||
int idx = heightCache.Count;
|
||||
|
@ -11,7 +11,7 @@ using UnityExplorer.UI.Panels;
|
||||
|
||||
namespace UnityExplorer.UI.Widgets
|
||||
{
|
||||
public struct CellInfo
|
||||
public struct CellInfo
|
||||
{
|
||||
public int cellIndex, dataIndex;
|
||||
}
|
||||
@ -120,7 +120,7 @@ namespace UnityExplorer.UI.Widgets
|
||||
OnHeightChanged?.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
@ -129,7 +129,7 @@ namespace UnityExplorer.UI.Widgets
|
||||
public void Refresh(bool setCellData, bool jumpToTop = false)
|
||||
{
|
||||
if (jumpToTop)
|
||||
{
|
||||
{
|
||||
bottomDataIndex = CellPool.Count - 1;
|
||||
Content.anchoredPosition = Vector2.zero;
|
||||
}
|
||||
@ -193,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);
|
||||
|
||||
|
@ -33,10 +33,10 @@ namespace UnityExplorer.UI.Widgets
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
if (Value != transform
|
||||
|| depth != Depth
|
||||
|| ChildCount != transform.childCount
|
||||
|| Name != transform.name
|
||||
if (Value != transform
|
||||
|| depth != Depth
|
||||
|| ChildCount != transform.childCount
|
||||
|| Name != transform.name
|
||||
|| Enabled != transform.gameObject.activeSelf)
|
||||
{
|
||||
Value = transform;
|
||||
|
@ -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'">
|
||||
@ -366,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