mirror of
https://github.com/GrahamKracker/UnityExplorer.git
synced 2025-07-04 20:42:22 +08:00
Compare commits
96 Commits
Author | SHA1 | Date | |
---|---|---|---|
7a5570a070 | |||
d40537775f | |||
9b6f3fd3ea | |||
bacac929e9 | |||
4e3d3a2e5c | |||
7dbc8fd66e | |||
892cefcc91 | |||
a986b92963 | |||
8837119781 | |||
7eda249ddb | |||
710b4ba74a | |||
4bee55fb25 | |||
c71748d22a | |||
621035c732 | |||
2285a495be | |||
efdf2446bd | |||
6ad45ac8ae | |||
2d3c83cfa3 | |||
3213717ff6 | |||
a6a1a4d046 | |||
078c2e2b51 | |||
49bce650b4 | |||
bd9e80f2b4 | |||
d1eb5671bf | |||
f1ca484712 | |||
3b71b40843 | |||
1292affe6d | |||
6614762fe8 | |||
d81d6d034b | |||
5dfe3bbf0c | |||
dc81451ce5 | |||
d7ab0a23c6 | |||
1a01c740e2 | |||
040fb1f11a | |||
e44ff9e207 | |||
b5c69fc1ea | |||
4fdb2aacd8 | |||
48e688cb75 | |||
647b0d353d | |||
2b715f3dbe | |||
938a991594 | |||
f00134b283 | |||
3b6b9768fb | |||
5fbfa1b7aa | |||
7d26965c12 | |||
862523399a | |||
0afccadc64 | |||
0e37e8030c | |||
621a9cd72e | |||
56be5414f9 | |||
b8c4be473f | |||
b6966f8836 | |||
ad8c5293a0 | |||
a7165c849c | |||
79f2514109 | |||
4e76eca73a | |||
2f0876466c | |||
fdefc3d567 | |||
64193ff1b0 | |||
a90292f47f | |||
d0bccae50c | |||
bdf08f014f | |||
df8522963e | |||
f6d0acab7b | |||
d4fbc89158 | |||
9e49f09a79 | |||
b9a3ab7439 | |||
03661cdd0b | |||
10f2b7e849 | |||
4602f07c34 | |||
18bcfed434 | |||
c7d2ce6d36 | |||
f961add7f4 | |||
798b881dcb | |||
c90f339882 | |||
c351ce5a6d | |||
9985ed0fd8 | |||
f35232bb64 | |||
49cc1f7df3 | |||
9f78c50854 | |||
bc64a04339 | |||
7d961ce8ad | |||
c7d7569f71 | |||
ee8f33a754 | |||
a95d91c824 | |||
177b78f4e7 | |||
3804d0aab0 | |||
97a82c1661 | |||
96a1cc69fb | |||
589abe6193 | |||
91bb58b020 | |||
d67507ead2 | |||
d730fbe49c | |||
9e0784ce54 | |||
67c602b32f | |||
8fb7d87ca6 |
3
.github/FUNDING.yml
vendored
Normal file
3
.github/FUNDING.yml
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# These are supported funding model platforms
|
||||||
|
|
||||||
|
ko_fi: sinaidev
|
4
.github/workflows/dotnet.yml
vendored
4
.github/workflows/dotnet.yml
vendored
@ -28,15 +28,13 @@ jobs:
|
|||||||
nuget-api-key: ${{ secrets.NuGetAPIKey }}
|
nuget-api-key: ${{ secrets.NuGetAPIKey }}
|
||||||
nuget-version: '5.x'
|
nuget-version: '5.x'
|
||||||
|
|
||||||
# Build Il2CppAssemblyUnhollower
|
|
||||||
- run: msbuild lib\Il2CppAssemblyUnhollower\UnhollowerBaseLib\UnhollowerBaseLib.csproj -t:Restore -t:Rebuild -p:Platform="AnyCPU" -p:Configuration=Release
|
|
||||||
|
|
||||||
# Build mcs
|
# Build mcs
|
||||||
- run: nuget restore lib\mcs-unity\mcs.sln
|
- run: nuget restore lib\mcs-unity\mcs.sln
|
||||||
- run: msbuild lib\mcs-unity\mcs\mcs.csproj -t:Restore -t:Rebuild -p:Platform="AnyCPU" -p:Configuration=Release
|
- run: msbuild lib\mcs-unity\mcs\mcs.csproj -t:Restore -t:Rebuild -p:Platform="AnyCPU" -p:Configuration=Release
|
||||||
|
|
||||||
# Build UnityExplorer releases, and upload artifacts
|
# Build UnityExplorer releases, and upload artifacts
|
||||||
|
|
||||||
|
- run: dotnet nuget add source https://nuget.bepinex.dev/v3/index.json
|
||||||
- run: nuget restore src\UnityExplorer.sln
|
- run: nuget restore src\UnityExplorer.sln
|
||||||
|
|
||||||
# BepInEx Il2Cpp
|
# BepInEx Il2Cpp
|
||||||
|
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -1,6 +1,3 @@
|
|||||||
[submodule "lib/Il2CppAssemblyUnhollower"]
|
|
||||||
path = lib/Il2CppAssemblyUnhollower
|
|
||||||
url = https://github.com/knah/Il2CppAssemblyUnhollower
|
|
||||||
[submodule "lib/mcs-unity"]
|
[submodule "lib/mcs-unity"]
|
||||||
path = lib/mcs-unity
|
path = lib/mcs-unity
|
||||||
url = https://github.com/sinai-dev/mcs-unity
|
url = https://github.com/sinai-dev/mcs-unity
|
||||||
|
23
README.md
23
README.md
@ -35,7 +35,7 @@
|
|||||||
| ------- | ------ | ---- |
|
| ------- | ------ | ---- |
|
||||||
| ML 0.4+ | ✅ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.MelonLoader.Il2Cpp.zip) | ✅ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.MelonLoader.Mono.zip) |
|
| ML 0.4+ | ✅ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.MelonLoader.Il2Cpp.zip) | ✅ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.MelonLoader.Mono.zip) |
|
||||||
|
|
||||||
1. Take the `UnityExplorer.ML.[version].dll` and the `UniverseLib.[version].dll` files and put them in the `Mods\` folder created by MelonLoader.
|
1. Take the `UnityExplorer.ML.[version].dll` file and put them in the `Mods\` folder created by MelonLoader, and then put the `UniverseLib.[version].dll` file in the `UserLibs\` folder.
|
||||||
|
|
||||||
## Standalone
|
## Standalone
|
||||||
|
|
||||||
@ -43,13 +43,20 @@
|
|||||||
| ------ | ---- |
|
| ------ | ---- |
|
||||||
| ✅ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.Standalone.Il2Cpp.zip) | ✅ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.Standalone.Mono.zip) |
|
| ✅ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.Standalone.Il2Cpp.zip) | ✅ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.Standalone.Mono.zip) |
|
||||||
|
|
||||||
The standalone release can be used with any injector or loader of your choice, but it requires you to load the dependencies manually: HarmonyX, and the IL2CPP version also requires that you set up an [Il2CppAssemblyUnhollower runtime](https://github.com/knah/Il2CppAssemblyUnhollower#required-external-setup).
|
The standalone release can be used with any injector or loader of your choice, but it requires you to load the dependencies manually.
|
||||||
|
|
||||||
1. Load the required libs - UniverseLib, HarmonyX, and Il2CppAssemblyUnhollower if IL2CPP
|
1. Ensure the required libs are loaded - UniverseLib, HarmonyX and MonoMod. Take them from the [`UnityExplorer.Editor`](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.Editor.zip) release if you need them.
|
||||||
|
2. For IL2CPP, load Il2CppAssemblyUnhollower and start an [Il2CppAssemblyUnhollower runtime](https://github.com/knah/Il2CppAssemblyUnhollower#required-external-setup)
|
||||||
2. Load the UnityExplorer DLL
|
2. Load the UnityExplorer DLL
|
||||||
3. Create an instance of Unity Explorer with `UnityExplorer.ExplorerStandalone.CreateInstance();`
|
3. Create an instance of Unity Explorer with `UnityExplorer.ExplorerStandalone.CreateInstance();`
|
||||||
4. Optionally subscribe to the `ExplorerStandalone.OnLog` event to handle logging if you wish
|
4. Optionally subscribe to the `ExplorerStandalone.OnLog` event to handle logging if you wish
|
||||||
|
|
||||||
|
## Unity Editor
|
||||||
|
|
||||||
|
1. Download the [`UnityExplorer.Editor`](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.Editor.zip) release.
|
||||||
|
2. Install the package, either by using the Package Manager and importing the `package.json` file, or by manually dragging the folder into your `Assets` folder.
|
||||||
|
3. Drag the `Runtime/UnityExplorer` prefab into your scene, or create a GameObject and add the `Explorer Editor Behaviour` script to it.
|
||||||
|
|
||||||
# Common issues and solutions
|
# Common issues and solutions
|
||||||
|
|
||||||
Although UnityExplorer should work out of the box for most Unity games, in some cases you may need to tweak the settings for it to work properly.
|
Although UnityExplorer should work out of the box for most Unity games, in some cases you may need to tweak the settings for it to work properly.
|
||||||
@ -57,7 +64,7 @@ Although UnityExplorer should work out of the box for most Unity games, in some
|
|||||||
To adjust the settings, open the config file:
|
To adjust the settings, open the config file:
|
||||||
* BepInEx: `BepInEx\config\com.sinai.unityexplorer.cfg`
|
* BepInEx: `BepInEx\config\com.sinai.unityexplorer.cfg`
|
||||||
* MelonLoader: `UserData\MelonPreferences.cfg`
|
* MelonLoader: `UserData\MelonPreferences.cfg`
|
||||||
* Standalone: `UnityExplorer\config.ini`
|
* Standalone: `UnityExplorer\config.cfg`
|
||||||
|
|
||||||
Try adjusting the following settings and see if it fixes your issues:
|
Try adjusting the following settings and see if it fixes your issues:
|
||||||
* `Startup_Delay_Time` - increase to 5-10 seconds (or more as needed), can fix issues with UnityExplorer being destroyed or corrupted during startup.
|
* `Startup_Delay_Time` - increase to 5-10 seconds (or more as needed), can fix issues with UnityExplorer being destroyed or corrupted during startup.
|
||||||
@ -126,15 +133,13 @@ The inspector is used to see detailed information on objects of any type and man
|
|||||||
* You can change the settings via the "Options" tab of the menu, or directly from the config file.
|
* You can change the settings via the "Options" tab of the menu, or directly from the config file.
|
||||||
* BepInEx: `BepInEx\config\com.sinai.unityexplorer.cfg`
|
* BepInEx: `BepInEx\config\com.sinai.unityexplorer.cfg`
|
||||||
* MelonLoader: `UserData\MelonPreferences.cfg`
|
* MelonLoader: `UserData\MelonPreferences.cfg`
|
||||||
* Standalone `{DLL_location}\UnityExplorer\config.ini`
|
* Standalone `{DLL_location}\UnityExplorer\config.cfg`
|
||||||
|
|
||||||
# Building
|
# Building
|
||||||
|
|
||||||
For Visual Studio:
|
|
||||||
|
|
||||||
0. Clone the repository and run `git submodule update --init --recursive` to get the submodules.
|
0. Clone the repository and run `git submodule update --init --recursive` to get the submodules.
|
||||||
1. Open the `src\UnityExplorer.sln` project.
|
1. Open the `src\UnityExplorer.sln` project.
|
||||||
2. Build `mcs` (Release/AnyCPU, you may need to run `nuget restore mcs.sln`), and if using IL2CPP then build `Il2CppAssemblyUnhollower` (Release/AnyCPU) as well.
|
2. Build `mcs` (Release/AnyCPU, you may need to run `nuget restore mcs.sln`)
|
||||||
3. Build the UnityExplorer release(s) you want to use, either by selecting the config as the Active Config, or batch-building.
|
3. Build the UnityExplorer release(s) you want to use, either by selecting the config as the Active Config, or batch-building.
|
||||||
|
|
||||||
If you fork the repository on GitHub you can build using the [dotnet workflow](https://github.com/sinai-dev/UnityExplorer/blob/master/.github/workflows/dotnet.yml):
|
If you fork the repository on GitHub you can build using the [dotnet workflow](https://github.com/sinai-dev/UnityExplorer/blob/master/.github/workflows/dotnet.yml):
|
||||||
@ -146,7 +151,7 @@ If you fork the repository on GitHub you can build using the [dotnet workflow](h
|
|||||||
# Acknowledgments
|
# Acknowledgments
|
||||||
|
|
||||||
* [ManlyMarco](https://github.com/ManlyMarco) for [Runtime Unity Editor](https://github.com/ManlyMarco/RuntimeUnityEditor) \[[license](THIRDPARTY_LICENSES.md#runtimeunityeditor-license)\], the ScriptEvaluator from RUE's REPL console was used as the base for UnityExplorer's C# console.
|
* [ManlyMarco](https://github.com/ManlyMarco) for [Runtime Unity Editor](https://github.com/ManlyMarco/RuntimeUnityEditor) \[[license](THIRDPARTY_LICENSES.md#runtimeunityeditor-license)\], the ScriptEvaluator from RUE's REPL console was used as the base for UnityExplorer's C# console.
|
||||||
* [denikson](https://github.com/denikson) (aka Horse) for [mcs-unity](https://github.com/denikson/mcs-unity) \[no license\], used as the `Mono.CSharp` reference for the C# Console.
|
* [Geoffrey Horsington](https://github.com/ghorsington) for [mcs-unity](https://github.com/sinai-dev/mcs-unity) \[no license\], used as the `Mono.CSharp` reference for the C# Console.
|
||||||
|
|
||||||
### Disclaimer
|
### Disclaimer
|
||||||
|
|
||||||
|
BIN
img/social.png
BIN
img/social.png
Binary file not shown.
Before Width: | Height: | Size: 232 KiB |
Binary file not shown.
Submodule lib/Il2CppAssemblyUnhollower deleted from f1adce3318
Binary file not shown.
BIN
lib/unhollowed/UnityEngine.AudioModule.dll
Normal file
BIN
lib/unhollowed/UnityEngine.AudioModule.dll
Normal file
Binary file not shown.
@ -8,6 +8,8 @@ using UnityExplorer.UI;
|
|||||||
using UnityExplorer.UI.Widgets.AutoComplete;
|
using UnityExplorer.UI.Widgets.AutoComplete;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
|
using UniverseLib.UI.Models;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.CSConsole
|
namespace UnityExplorer.CSConsole
|
||||||
{
|
{
|
||||||
@ -25,7 +27,7 @@ namespace UnityExplorer.CSConsole
|
|||||||
AutoCompleteModal.Instance.ReleaseOwnership(this);
|
AutoCompleteModal.Instance.ReleaseOwnership(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly HashSet<char> delimiters = new HashSet<char>
|
private readonly HashSet<char> delimiters = new()
|
||||||
{
|
{
|
||||||
'{', '}', ',', ';', '<', '>', '(', ')', '[', ']', '=', '|', '&', '?'
|
'{', '}', ',', ';', '<', '>', '(', ')', '[', ']', '=', '|', '&', '?'
|
||||||
};
|
};
|
||||||
|
@ -16,6 +16,10 @@ using UnityExplorer.UI.Panels;
|
|||||||
using UnityExplorer.UI.Widgets.AutoComplete;
|
using UnityExplorer.UI.Widgets.AutoComplete;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
|
using UniverseLib.UI.Models;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
using HarmonyLib;
|
||||||
|
using UniverseLib.Runtime;
|
||||||
|
|
||||||
namespace UnityExplorer.CSConsole
|
namespace UnityExplorer.CSConsole
|
||||||
{
|
{
|
||||||
@ -58,6 +62,8 @@ namespace UnityExplorer.CSConsole
|
|||||||
|
|
||||||
public static void Init()
|
public static void Init()
|
||||||
{
|
{
|
||||||
|
InitEventSystemPropertyHandlers();
|
||||||
|
|
||||||
// Make sure console is supported on this platform
|
// Make sure console is supported on this platform
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -357,7 +363,7 @@ namespace UnityExplorer.CSConsole
|
|||||||
var charTop = charInfo.cursorPos.y;
|
var charTop = charInfo.cursorPos.y;
|
||||||
var charBot = charTop - CSCONSOLE_LINEHEIGHT;
|
var charBot = charTop - CSCONSOLE_LINEHEIGHT;
|
||||||
|
|
||||||
var viewportMin = Input.Rect.rect.height - Input.Rect.anchoredPosition.y - (Input.Rect.rect.height * 0.5f);
|
var viewportMin = Input.Transform.rect.height - Input.Transform.anchoredPosition.y - (Input.Transform.rect.height * 0.5f);
|
||||||
var viewportMax = viewportMin - Panel.InputScroller.ViewportRect.rect.height;
|
var viewportMax = viewportMin - Panel.InputScroller.ViewportRect.rect.height;
|
||||||
|
|
||||||
float diff = 0f;
|
float diff = 0f;
|
||||||
@ -368,7 +374,7 @@ namespace UnityExplorer.CSConsole
|
|||||||
|
|
||||||
if (Math.Abs(diff) > 1)
|
if (Math.Abs(diff) > 1)
|
||||||
{
|
{
|
||||||
var rect = Input.Rect;
|
var rect = Input.Transform;
|
||||||
rect.anchoredPosition = new Vector2(rect.anchoredPosition.x, rect.anchoredPosition.y - diff);
|
rect.anchoredPosition = new Vector2(rect.anchoredPosition.x, rect.anchoredPosition.y - diff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -378,33 +384,84 @@ namespace UnityExplorer.CSConsole
|
|||||||
{
|
{
|
||||||
settingCaretCoroutine = true;
|
settingCaretCoroutine = true;
|
||||||
Input.Component.readOnly = true;
|
Input.Component.readOnly = true;
|
||||||
RuntimeProvider.Instance.StartCoroutine(SetCaretCoroutine(caretPosition));
|
RuntimeHelper.StartCoroutine(SetCaretCoroutine(caretPosition));
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static PropertyInfo SelectionGuardProperty => selectionGuardPropInfo ?? GetSelectionGuardPropInfo();
|
static void InitEventSystemPropertyHandlers()
|
||||||
|
|
||||||
private static PropertyInfo GetSelectionGuardPropInfo()
|
|
||||||
{
|
{
|
||||||
selectionGuardPropInfo = typeof(EventSystem).GetProperty("m_SelectionGuard");
|
try
|
||||||
if (selectionGuardPropInfo == null)
|
{
|
||||||
selectionGuardPropInfo = typeof(EventSystem).GetProperty("m_selectionGuard");
|
foreach (var member in typeof(EventSystem).GetMembers(AccessTools.all))
|
||||||
return selectionGuardPropInfo;
|
{
|
||||||
|
if (member.Name == "m_CurrentSelected")
|
||||||
|
{
|
||||||
|
Type backingType;
|
||||||
|
if (member.MemberType == MemberTypes.Property)
|
||||||
|
backingType = (member as PropertyInfo).PropertyType;
|
||||||
|
else
|
||||||
|
backingType = (member as FieldInfo).FieldType;
|
||||||
|
|
||||||
|
usingEventSystemDictionaryMembers = ReflectionUtility.IsDictionary(backingType);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
ExplorerCore.LogWarning($"Exception checking EventSystem property backing type: {ex}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static PropertyInfo selectionGuardPropInfo;
|
static bool usingEventSystemDictionaryMembers;
|
||||||
|
|
||||||
|
static readonly AmbiguousMemberHandler<EventSystem, GameObject> m_CurrentSelected_Handler_Normal
|
||||||
|
= new(true, true, "m_CurrentSelected", "m_currentSelected");
|
||||||
|
static readonly AmbiguousMemberHandler<EventSystem, Dictionary<int, GameObject>> m_CurrentSelected_Handler_Dictionary
|
||||||
|
= new(true, true, "m_CurrentSelected", "m_currentSelected");
|
||||||
|
|
||||||
|
static readonly AmbiguousMemberHandler<EventSystem, bool> m_SelectionGuard_Handler_Normal
|
||||||
|
= new(true, true, "m_SelectionGuard", "m_selectionGuard");
|
||||||
|
static readonly AmbiguousMemberHandler<EventSystem, Dictionary<int, bool>> m_SelectionGuard_Handler_Dictionary
|
||||||
|
= new(true, true, "m_SelectionGuard", "m_selectionGuard");
|
||||||
|
|
||||||
|
static void SetCurrentSelectedGameObject(EventSystem instance, GameObject value)
|
||||||
|
{
|
||||||
|
instance.SetSelectedGameObject(value);
|
||||||
|
|
||||||
|
if (usingEventSystemDictionaryMembers)
|
||||||
|
m_CurrentSelected_Handler_Dictionary.GetValue(instance)[0] = value;
|
||||||
|
else
|
||||||
|
m_CurrentSelected_Handler_Normal.SetValue(instance, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SetSelectionGuard(EventSystem instance, bool value)
|
||||||
|
{
|
||||||
|
if (usingEventSystemDictionaryMembers)
|
||||||
|
m_SelectionGuard_Handler_Dictionary.GetValue(instance)[0] = value;
|
||||||
|
else
|
||||||
|
m_SelectionGuard_Handler_Normal.SetValue(instance, value);
|
||||||
|
}
|
||||||
|
|
||||||
private static IEnumerator SetCaretCoroutine(int caretPosition)
|
private static IEnumerator SetCaretCoroutine(int caretPosition)
|
||||||
{
|
{
|
||||||
var color = Input.Component.selectionColor;
|
var color = Input.Component.selectionColor;
|
||||||
color.a = 0f;
|
color.a = 0f;
|
||||||
Input.Component.selectionColor = color;
|
Input.Component.selectionColor = color;
|
||||||
try { EventSystem.current.SetSelectedGameObject(null, null); } catch { }
|
|
||||||
yield return null;
|
|
||||||
|
|
||||||
try { SelectionGuardProperty.SetValue(EventSystem.current, false, null); } catch { }
|
try { SetCurrentSelectedGameObject(CursorUnlocker.CurrentEventSystem, null); }
|
||||||
try { EventSystem.current.SetSelectedGameObject(Input.UIRoot, null); } catch { }
|
catch (Exception ex) { ExplorerCore.Log($"Failed removing selected object: {ex}"); }
|
||||||
|
|
||||||
|
yield return null; // ~~~~~~~ YIELD FRAME ~~~~~~~~~
|
||||||
|
|
||||||
|
try { SetSelectionGuard(CursorUnlocker.CurrentEventSystem, false); }
|
||||||
|
catch (Exception ex) { ExplorerCore.Log($"Failed setting selection guard: {ex}"); }
|
||||||
|
|
||||||
|
try { SetCurrentSelectedGameObject(CursorUnlocker.CurrentEventSystem, Input.GameObject); }
|
||||||
|
catch (Exception ex) { ExplorerCore.Log($"Failed setting selected gameobject: {ex}"); }
|
||||||
|
|
||||||
|
yield return null; // ~~~~~~~ YIELD FRAME ~~~~~~~~~
|
||||||
|
|
||||||
Input.Component.Select();
|
Input.Component.Select();
|
||||||
yield return null;
|
|
||||||
|
|
||||||
Input.Component.caretPosition = caretPosition;
|
Input.Component.caretPosition = caretPosition;
|
||||||
Input.Component.selectionFocusPosition = caretPosition;
|
Input.Component.selectionFocusPosition = caretPosition;
|
||||||
@ -438,7 +495,7 @@ namespace UnityExplorer.CSConsole
|
|||||||
|
|
||||||
// the top and bottom position of the viewport in relation to the text height
|
// the top and bottom position of the viewport in relation to the text height
|
||||||
// they need the half-height adjustment to normalize against the 'line.topY' value.
|
// they need the half-height adjustment to normalize against the 'line.topY' value.
|
||||||
var viewportMin = Input.Rect.rect.height - Input.Rect.anchoredPosition.y - (Input.Rect.rect.height * 0.5f);
|
var viewportMin = Input.Transform.rect.height - Input.Transform.anchoredPosition.y - (Input.Transform.rect.height * 0.5f);
|
||||||
var viewportMax = viewportMin - Panel.InputScroller.ViewportRect.rect.height;
|
var viewportMax = viewportMin - Panel.InputScroller.ViewportRect.rect.height;
|
||||||
|
|
||||||
for (int i = 0; i < Input.TextGenerator.lineCount; i++)
|
for (int i = 0; i < Input.TextGenerator.lineCount; i++)
|
||||||
@ -663,7 +720,8 @@ var x = 5;
|
|||||||
* Log(obj); - prints a message to the console log
|
* Log(obj); - prints a message to the console log
|
||||||
* Inspect(obj); - inspect the object with the Inspector
|
* Inspect(obj); - inspect the object with the Inspector
|
||||||
* Inspect(someType); - inspect a Type with static reflection
|
* Inspect(someType); - inspect a Type with static reflection
|
||||||
* Start(enumerator); - starts the IEnumerator as a Coroutine
|
* Start(enumerator); - Coroutine, starts the IEnumerator as a Coroutine, and returns the Coroutine.
|
||||||
|
* Stop(coroutine); - stop the Coroutine ONLY if it was started with Start(ienumerator).
|
||||||
* Copy(obj); - copies the object to the UnityExplorer Clipboard
|
* Copy(obj); - copies the object to the UnityExplorer Clipboard
|
||||||
* Paste(); - System.Object, the contents of the Clipboard.
|
* Paste(); - System.Object, the contents of the Clipboard.
|
||||||
* GetUsing(); - prints the current using directives to the console log
|
* GetUsing(); - prints the current using directives to the console log
|
||||||
|
@ -7,6 +7,7 @@ using UnityEngine;
|
|||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.CSConsole.Lexers;
|
using UnityExplorer.CSConsole.Lexers;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.CSConsole
|
namespace UnityExplorer.CSConsole
|
||||||
{
|
{
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.CSConsole.Lexers
|
namespace UnityExplorer.CSConsole.Lexers
|
||||||
{
|
{
|
||||||
|
@ -51,13 +51,8 @@ namespace UnityExplorer.CSConsole
|
|||||||
ReferenceAssembly(asm);
|
ReferenceAssembly(asm);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static CompilerContext context;
|
|
||||||
|
|
||||||
private static CompilerContext BuildContext(TextWriter tw)
|
private static CompilerContext BuildContext(TextWriter tw)
|
||||||
{
|
{
|
||||||
if (context != null)
|
|
||||||
return context;
|
|
||||||
|
|
||||||
_reportPrinter = new StreamReportPrinter(tw);
|
_reportPrinter = new StreamReportPrinter(tw);
|
||||||
|
|
||||||
var settings = new CompilerSettings
|
var settings = new CompilerSettings
|
||||||
@ -70,7 +65,7 @@ namespace UnityExplorer.CSConsole
|
|||||||
EnhancedWarnings = false
|
EnhancedWarnings = false
|
||||||
};
|
};
|
||||||
|
|
||||||
return context = new CompilerContext(settings, _reportPrinter);
|
return new CompilerContext(settings, _reportPrinter);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ImportAppdomainAssemblies(Action<Assembly> import)
|
private static void ImportAppdomainAssemblies(Action<Assembly> import)
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using Mono.CSharp;
|
using HarmonyLib;
|
||||||
|
using Mono.CSharp;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@ -28,8 +29,11 @@ namespace UnityExplorer.CSConsole
|
|||||||
public static void Inspect(Type type)
|
public static void Inspect(Type type)
|
||||||
=> InspectorManager.Inspect(type);
|
=> InspectorManager.Inspect(type);
|
||||||
|
|
||||||
public static void Start(IEnumerator ienumerator)
|
public static Coroutine Start(IEnumerator ienumerator)
|
||||||
=> RuntimeProvider.Instance.StartCoroutine(ienumerator);
|
=> RuntimeHelper.StartCoroutine(ienumerator);
|
||||||
|
|
||||||
|
public static void Stop(Coroutine coro)
|
||||||
|
=> RuntimeHelper.StopCoroutine(coro);
|
||||||
|
|
||||||
public static void Copy(object obj)
|
public static void Copy(object obj)
|
||||||
=> ClipboardPanel.Copy(obj);
|
=> ClipboardPanel.Copy(obj);
|
||||||
@ -51,7 +55,7 @@ namespace UnityExplorer.CSConsole
|
|||||||
|
|
||||||
public static void GetClasses()
|
public static void GetClasses()
|
||||||
{
|
{
|
||||||
if (ReflectionUtility.GetFieldInfo(typeof(Evaluator), "source_file")
|
if (AccessTools.Field(typeof(Evaluator), "source_file")
|
||||||
.GetValue(Evaluator) is CompilationSourceFile sourceFile
|
.GetValue(Evaluator) is CompilationSourceFile sourceFile
|
||||||
&& sourceFile.Containers.Any())
|
&& sourceFile.Containers.Any())
|
||||||
{
|
{
|
||||||
|
87
src/CacheObject/CacheConstructor.cs
Normal file
87
src/CacheObject/CacheConstructor.cs
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
using UnityExplorer.Inspectors;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
|
namespace UnityExplorer.CacheObject
|
||||||
|
{
|
||||||
|
public class CacheConstructor : CacheMember
|
||||||
|
{
|
||||||
|
public ConstructorInfo CtorInfo { get; }
|
||||||
|
readonly Type typeForStructConstructor;
|
||||||
|
|
||||||
|
public override Type DeclaringType => typeForStructConstructor ?? CtorInfo.DeclaringType;
|
||||||
|
public override bool IsStatic => true;
|
||||||
|
public override bool ShouldAutoEvaluate => false;
|
||||||
|
public override bool CanWrite => false;
|
||||||
|
|
||||||
|
public CacheConstructor(ConstructorInfo ci)
|
||||||
|
{
|
||||||
|
this.CtorInfo = ci;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CacheConstructor(Type typeForStructConstructor)
|
||||||
|
{
|
||||||
|
this.typeForStructConstructor = typeForStructConstructor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void SetInspectorOwner(ReflectionInspector inspector, MemberInfo member)
|
||||||
|
{
|
||||||
|
Type ctorReturnType;
|
||||||
|
// if is parameterless struct ctor
|
||||||
|
if (typeForStructConstructor != null)
|
||||||
|
{
|
||||||
|
ctorReturnType = typeForStructConstructor;
|
||||||
|
this.Owner = inspector;
|
||||||
|
|
||||||
|
// eg. Vector3.Vector3()
|
||||||
|
this.NameLabelText = SignatureHighlighter.Parse(typeForStructConstructor, false);
|
||||||
|
NameLabelText += $".{NameLabelText}()";
|
||||||
|
|
||||||
|
this.NameForFiltering = SignatureHighlighter.RemoveHighlighting(NameLabelText);
|
||||||
|
this.NameLabelTextRaw = NameForFiltering;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
base.SetInspectorOwner(inspector, member);
|
||||||
|
|
||||||
|
Arguments = CtorInfo.GetParameters();
|
||||||
|
ctorReturnType = CtorInfo.DeclaringType;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctorReturnType.IsGenericTypeDefinition)
|
||||||
|
GenericArguments = ctorReturnType.GetGenericArguments();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override object TryEvaluate()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Type returnType = DeclaringType;
|
||||||
|
|
||||||
|
if (returnType.IsGenericTypeDefinition)
|
||||||
|
returnType = DeclaringType.MakeGenericType(Evaluator.TryParseGenericArguments());
|
||||||
|
|
||||||
|
object ret;
|
||||||
|
if (HasArguments)
|
||||||
|
ret = Activator.CreateInstance(returnType, Evaluator.TryParseArguments());
|
||||||
|
else
|
||||||
|
ret = Activator.CreateInstance(returnType, ArgumentUtility.EmptyArgs);
|
||||||
|
|
||||||
|
LastException = null;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LastException = ex;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void TrySetValue(object value) => throw new NotImplementedException("You can't set a constructor");
|
||||||
|
}
|
||||||
|
}
|
@ -17,6 +17,11 @@ namespace UnityExplorer.CacheObject
|
|||||||
|
|
||||||
public override bool ShouldAutoEvaluate => true;
|
public override bool ShouldAutoEvaluate => true;
|
||||||
|
|
||||||
|
public CacheField(FieldInfo fi)
|
||||||
|
{
|
||||||
|
this.FieldInfo = fi;
|
||||||
|
}
|
||||||
|
|
||||||
public override void SetInspectorOwner(ReflectionInspector inspector, MemberInfo member)
|
public override void SetInspectorOwner(ReflectionInspector inspector, MemberInfo member)
|
||||||
{
|
{
|
||||||
base.SetInspectorOwner(inspector, member);
|
base.SetInspectorOwner(inspector, member);
|
||||||
@ -27,13 +32,11 @@ namespace UnityExplorer.CacheObject
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var ret = FieldInfo.GetValue(DeclaringInstance);
|
var ret = FieldInfo.GetValue(DeclaringInstance);
|
||||||
HadException = false;
|
|
||||||
LastException = null;
|
LastException = null;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
HadException = true;
|
|
||||||
LastException = ex;
|
LastException = ex;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ using System.Text;
|
|||||||
using UnityExplorer.CacheObject.IValues;
|
using UnityExplorer.CacheObject.IValues;
|
||||||
using UnityExplorer.CacheObject.Views;
|
using UnityExplorer.CacheObject.Views;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.CacheObject
|
namespace UnityExplorer.CacheObject
|
||||||
{
|
{
|
||||||
|
@ -12,6 +12,10 @@ using UnityExplorer.UI;
|
|||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
using UnityExplorer.UI.Widgets;
|
using UnityExplorer.UI.Widgets;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
using UniverseLib.UI.ObjectPool;
|
||||||
|
using System.Collections;
|
||||||
|
using HarmonyLib;
|
||||||
|
|
||||||
namespace UnityExplorer.CacheObject
|
namespace UnityExplorer.CacheObject
|
||||||
{
|
{
|
||||||
@ -19,7 +23,7 @@ namespace UnityExplorer.CacheObject
|
|||||||
{
|
{
|
||||||
public abstract Type DeclaringType { get; }
|
public abstract Type DeclaringType { get; }
|
||||||
public string NameForFiltering { get; protected set; }
|
public string NameForFiltering { get; protected set; }
|
||||||
public object DeclaringInstance => IsStatic ? null : (m_declaringInstance ?? (m_declaringInstance = Owner.Target.TryCast(DeclaringType)));
|
public object DeclaringInstance => IsStatic ? null : (m_declaringInstance ??= Owner.Target.TryCast(DeclaringType));
|
||||||
private object m_declaringInstance;
|
private object m_declaringInstance;
|
||||||
|
|
||||||
public abstract bool IsStatic { get; }
|
public abstract bool IsStatic { get; }
|
||||||
@ -32,10 +36,14 @@ namespace UnityExplorer.CacheObject
|
|||||||
public virtual void SetInspectorOwner(ReflectionInspector inspector, MemberInfo member)
|
public virtual void SetInspectorOwner(ReflectionInspector inspector, MemberInfo member)
|
||||||
{
|
{
|
||||||
this.Owner = inspector;
|
this.Owner = inspector;
|
||||||
this.NameLabelText = this is CacheMethod
|
this.NameLabelText = this switch
|
||||||
? SignatureHighlighter.HighlightMethod(member as MethodInfo)
|
{
|
||||||
: SignatureHighlighter.Parse(member.DeclaringType, false, member);
|
CacheMethod => SignatureHighlighter.HighlightMethod(member as MethodInfo),
|
||||||
this.NameForFiltering = $"{member.DeclaringType.Name}.{member.Name}";
|
CacheConstructor => SignatureHighlighter.HighlightConstructor(member as ConstructorInfo),
|
||||||
|
_ => SignatureHighlighter.Parse(member.DeclaringType, false, member),
|
||||||
|
};
|
||||||
|
|
||||||
|
this.NameForFiltering = SignatureHighlighter.RemoveHighlighting(NameLabelText);
|
||||||
this.NameLabelTextRaw = NameForFiltering;
|
this.NameLabelTextRaw = NameForFiltering;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,8 +100,8 @@ namespace UnityExplorer.CacheObject
|
|||||||
base.SetValueState(cell, args);
|
base.SetValueState(cell, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly Color evalEnabledColor = new Color(0.15f, 0.25f, 0.15f);
|
private static readonly Color evalEnabledColor = new(0.15f, 0.25f, 0.15f);
|
||||||
private static readonly Color evalDisabledColor = new Color(0.15f, 0.15f, 0.15f);
|
private static readonly Color evalDisabledColor = new(0.15f, 0.15f, 0.15f);
|
||||||
|
|
||||||
protected override bool TryAutoEvaluateIfUnitialized(CacheObjectCell objectcell)
|
protected override bool TryAutoEvaluateIfUnitialized(CacheObjectCell objectcell)
|
||||||
{
|
{
|
||||||
@ -111,14 +119,14 @@ namespace UnityExplorer.CacheObject
|
|||||||
{
|
{
|
||||||
cell.EvaluateButton.ButtonText.text = "Hide";
|
cell.EvaluateButton.ButtonText.text = "Hide";
|
||||||
Evaluator.UIRoot.transform.SetParent(cell.EvaluateHolder.transform, false);
|
Evaluator.UIRoot.transform.SetParent(cell.EvaluateHolder.transform, false);
|
||||||
RuntimeProvider.Instance.SetColorBlock(cell.EvaluateButton.Component, evalEnabledColor, evalEnabledColor * 1.3f);
|
RuntimeHelper.SetColorBlock(cell.EvaluateButton.Component, evalEnabledColor, evalEnabledColor * 1.3f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
cell.EvaluateButton.ButtonText.text = "Evaluate";
|
cell.EvaluateButton.ButtonText.text = "Evaluate";
|
||||||
|
|
||||||
if (!Evaluating)
|
if (!Evaluating)
|
||||||
RuntimeProvider.Instance.SetColorBlock(cell.EvaluateButton.Component, evalDisabledColor, evalDisabledColor * 1.3f);
|
RuntimeHelper.SetColorBlock(cell.EvaluateButton.Component, evalDisabledColor, evalDisabledColor * 1.3f);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (State == ValueState.NotEvaluated && !ShouldAutoEvaluate)
|
if (State == ValueState.NotEvaluated && !ShouldAutoEvaluate)
|
||||||
@ -161,184 +169,5 @@ namespace UnityExplorer.CacheObject
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#region Cache Member Util
|
|
||||||
|
|
||||||
//public static bool CanParseArgs(ParameterInfo[] parameters)
|
|
||||||
//{
|
|
||||||
// foreach (var param in parameters)
|
|
||||||
// {
|
|
||||||
// var pType = param.ParameterType;
|
|
||||||
//
|
|
||||||
// if (pType.IsByRef && pType.HasElementType)
|
|
||||||
// pType = pType.GetElementType();
|
|
||||||
//
|
|
||||||
// if (pType != null && ParseUtility.CanParse(pType))
|
|
||||||
// continue;
|
|
||||||
// else
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
// return true;
|
|
||||||
//}
|
|
||||||
|
|
||||||
public static List<CacheMember> GetCacheMembers(object inspectorTarget, Type _type, ReflectionInspector _inspector)
|
|
||||||
{
|
|
||||||
var list = new List<CacheMember>();
|
|
||||||
var cachedSigs = new HashSet<string>();
|
|
||||||
|
|
||||||
var types = ReflectionUtility.GetAllBaseTypes(_type);
|
|
||||||
|
|
||||||
var flags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static;
|
|
||||||
if (!_inspector.StaticOnly)
|
|
||||||
flags |= BindingFlags.Instance;
|
|
||||||
|
|
||||||
var infos = new List<MemberInfo>();
|
|
||||||
|
|
||||||
foreach (var declaringType in types)
|
|
||||||
{
|
|
||||||
var target = inspectorTarget;
|
|
||||||
if (!_inspector.StaticOnly)
|
|
||||||
target = target.TryCast(declaringType);
|
|
||||||
|
|
||||||
infos.Clear();
|
|
||||||
infos.AddRange(declaringType.GetProperties(flags));
|
|
||||||
infos.AddRange(declaringType.GetFields(flags));
|
|
||||||
infos.AddRange(declaringType.GetMethods(flags));
|
|
||||||
|
|
||||||
foreach (var member in infos)
|
|
||||||
{
|
|
||||||
if (member.DeclaringType != declaringType)
|
|
||||||
continue;
|
|
||||||
TryCacheMember(member, list, cachedSigs, declaringType, _inspector);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var typeList = types.ToList();
|
|
||||||
|
|
||||||
var sorted = new List<CacheMember>();
|
|
||||||
sorted.AddRange(list.Where(it => it is CacheProperty)
|
|
||||||
.OrderBy(it => typeList.IndexOf(it.DeclaringType))
|
|
||||||
.ThenBy(it => it.NameForFiltering));
|
|
||||||
sorted.AddRange(list.Where(it => it is CacheField)
|
|
||||||
.OrderBy(it => typeList.IndexOf(it.DeclaringType))
|
|
||||||
.ThenBy(it => it.NameForFiltering));
|
|
||||||
sorted.AddRange(list.Where(it => it is CacheMethod)
|
|
||||||
.OrderBy(it => typeList.IndexOf(it.DeclaringType))
|
|
||||||
.ThenBy(it => it.NameForFiltering));
|
|
||||||
|
|
||||||
return sorted;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void TryCacheMember(MemberInfo member, List<CacheMember> list, HashSet<string> cachedSigs,
|
|
||||||
Type declaringType, ReflectionInspector _inspector, bool ignorePropertyMethodInfos = true)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (RuntimeHelper.IsBlacklisted(member))
|
|
||||||
return;
|
|
||||||
|
|
||||||
var sig = GetSig(member);
|
|
||||||
|
|
||||||
//ExplorerCore.Log($"Trying to cache member {sig}... ({member.MemberType})");
|
|
||||||
|
|
||||||
CacheMember cached;
|
|
||||||
Type returnType;
|
|
||||||
switch (member.MemberType)
|
|
||||||
{
|
|
||||||
case MemberTypes.Method:
|
|
||||||
{
|
|
||||||
var mi = member as MethodInfo;
|
|
||||||
if (ignorePropertyMethodInfos
|
|
||||||
&& (mi.Name.StartsWith("get_") || mi.Name.StartsWith("set_")))
|
|
||||||
return;
|
|
||||||
|
|
||||||
//var args = mi.GetParameters();
|
|
||||||
//if (!CanParseArgs(args))
|
|
||||||
// return;
|
|
||||||
|
|
||||||
sig += GetArgumentString(mi.GetParameters());
|
|
||||||
if (cachedSigs.Contains(sig))
|
|
||||||
return;
|
|
||||||
|
|
||||||
cached = new CacheMethod() { MethodInfo = mi };
|
|
||||||
returnType = mi.ReturnType;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case MemberTypes.Property:
|
|
||||||
{
|
|
||||||
var pi = member as PropertyInfo;
|
|
||||||
|
|
||||||
//var args = pi.GetIndexParameters();
|
|
||||||
//if (!CanParseArgs(args))
|
|
||||||
// return;
|
|
||||||
|
|
||||||
if (!pi.CanRead && pi.CanWrite)
|
|
||||||
{
|
|
||||||
// write-only property, cache the set method instead.
|
|
||||||
var setMethod = pi.GetSetMethod(true);
|
|
||||||
if (setMethod != null)
|
|
||||||
TryCacheMember(setMethod, list, cachedSigs, declaringType, _inspector, false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
sig += GetArgumentString(pi.GetIndexParameters());
|
|
||||||
if (cachedSigs.Contains(sig))
|
|
||||||
return;
|
|
||||||
|
|
||||||
cached = new CacheProperty() { PropertyInfo = pi };
|
|
||||||
returnType = pi.PropertyType;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case MemberTypes.Field:
|
|
||||||
{
|
|
||||||
var fi = member as FieldInfo;
|
|
||||||
cached = new CacheField() { FieldInfo = fi };
|
|
||||||
returnType = fi.FieldType;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default: return;
|
|
||||||
}
|
|
||||||
|
|
||||||
cachedSigs.Add(sig);
|
|
||||||
|
|
||||||
cached.SetFallbackType(returnType);
|
|
||||||
cached.SetInspectorOwner(_inspector, member);
|
|
||||||
|
|
||||||
list.Add(cached);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
ExplorerCore.LogWarning($"Exception caching member {member.DeclaringType.FullName}.{member.Name}!");
|
|
||||||
ExplorerCore.Log(e.ToString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static string GetSig(MemberInfo member)
|
|
||||||
=> $"{member.DeclaringType.Name}.{member.Name}";
|
|
||||||
|
|
||||||
internal static string GetArgumentString(ParameterInfo[] args)
|
|
||||||
{
|
|
||||||
var sb = new StringBuilder();
|
|
||||||
sb.Append(' ');
|
|
||||||
sb.Append('(');
|
|
||||||
foreach (var param in args)
|
|
||||||
{
|
|
||||||
sb.Append(param.ParameterType.Name);
|
|
||||||
sb.Append(' ');
|
|
||||||
sb.Append(param.Name);
|
|
||||||
sb.Append(',');
|
|
||||||
sb.Append(' ');
|
|
||||||
}
|
|
||||||
sb.Append(')');
|
|
||||||
return sb.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
170
src/CacheObject/CacheMemberFactory.cs
Normal file
170
src/CacheObject/CacheMemberFactory.cs
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
using UnityExplorer.Inspectors;
|
||||||
|
using UnityExplorer.Runtime;
|
||||||
|
using UniverseLib;
|
||||||
|
using HarmonyLib;
|
||||||
|
using HarmonyLib.Tools;
|
||||||
|
|
||||||
|
namespace UnityExplorer.CacheObject
|
||||||
|
{
|
||||||
|
public static class CacheMemberFactory
|
||||||
|
{
|
||||||
|
public static List<CacheMember> GetCacheMembers(Type type, ReflectionInspector inspector)
|
||||||
|
{
|
||||||
|
//var list = new List<CacheMember>();
|
||||||
|
HashSet<string> cachedSigs = new();
|
||||||
|
List<CacheMember> props = new();
|
||||||
|
List<CacheMember> fields = new();
|
||||||
|
List<CacheMember> ctors = new();
|
||||||
|
List<CacheMember> methods = new();
|
||||||
|
|
||||||
|
var types = ReflectionUtility.GetAllBaseTypes(type);
|
||||||
|
|
||||||
|
var flags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static;
|
||||||
|
if (!inspector.StaticOnly)
|
||||||
|
flags |= BindingFlags.Instance;
|
||||||
|
|
||||||
|
if (!type.IsAbstract)
|
||||||
|
{
|
||||||
|
// Get non-static constructors of the main type.
|
||||||
|
// There's no reason to get the static cctor, it will be invoked when we inspect the class.
|
||||||
|
// Also no point getting ctors on inherited types.
|
||||||
|
foreach (var ctor in type.GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
|
||||||
|
TryCacheMember(ctor, ctors, cachedSigs, type, inspector);
|
||||||
|
|
||||||
|
// structs always have a parameterless constructor
|
||||||
|
if (type.IsValueType)
|
||||||
|
{
|
||||||
|
CacheConstructor cached = new(type);
|
||||||
|
cached.SetFallbackType(type);
|
||||||
|
cached.SetInspectorOwner(inspector, null);
|
||||||
|
ctors.Add(cached);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var declaringType in types)
|
||||||
|
{
|
||||||
|
foreach (var prop in declaringType.GetProperties(flags))
|
||||||
|
if (prop.DeclaringType == declaringType)
|
||||||
|
TryCacheMember(prop, props, cachedSigs, declaringType, inspector);
|
||||||
|
|
||||||
|
foreach (var field in declaringType.GetFields(flags))
|
||||||
|
if (field.DeclaringType == declaringType)
|
||||||
|
TryCacheMember(field, fields, cachedSigs, declaringType, inspector);
|
||||||
|
|
||||||
|
foreach (var method in declaringType.GetMethods(flags))
|
||||||
|
if (method.DeclaringType == declaringType)
|
||||||
|
TryCacheMember(method, methods, cachedSigs, declaringType, inspector);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var sorted = new List<CacheMember>();
|
||||||
|
sorted.AddRange(props.OrderBy(it => Array.IndexOf(types, it.DeclaringType))
|
||||||
|
.ThenBy(it => it.NameForFiltering));
|
||||||
|
sorted.AddRange(fields.OrderBy(it => Array.IndexOf(types, it.DeclaringType))
|
||||||
|
.ThenBy(it => it.NameForFiltering));
|
||||||
|
sorted.AddRange(ctors.OrderBy(it => Array.IndexOf(types, it.DeclaringType))
|
||||||
|
.ThenBy(it => it.NameForFiltering));
|
||||||
|
sorted.AddRange(methods.OrderBy(it => Array.IndexOf(types, it.DeclaringType))
|
||||||
|
.ThenBy(it => it.NameForFiltering));
|
||||||
|
return sorted;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void TryCacheMember<T>(MemberInfo member, List<T> list, HashSet<string> cachedSigs,
|
||||||
|
Type declaringType, ReflectionInspector inspector, bool ignorePropertyMethodInfos = true)
|
||||||
|
where T : CacheMember
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (UERuntimeHelper.IsBlacklisted(member))
|
||||||
|
return;
|
||||||
|
|
||||||
|
string sig = member switch
|
||||||
|
{
|
||||||
|
// method or constructor
|
||||||
|
MethodBase mb => mb.FullDescription(),
|
||||||
|
// property or field
|
||||||
|
PropertyInfo or FieldInfo => $"{member.DeclaringType.FullDescription()}.{member.Name}",
|
||||||
|
_ => throw new NotImplementedException(),
|
||||||
|
};
|
||||||
|
|
||||||
|
if (cachedSigs.Contains(sig))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// ExplorerCore.Log($"Trying to cache member {sig}... ({member.MemberType})");
|
||||||
|
|
||||||
|
CacheMember cached;
|
||||||
|
Type returnType;
|
||||||
|
|
||||||
|
switch (member.MemberType)
|
||||||
|
{
|
||||||
|
case MemberTypes.Constructor:
|
||||||
|
{
|
||||||
|
var ci = member as ConstructorInfo;
|
||||||
|
cached = new CacheConstructor(ci);
|
||||||
|
returnType = ci.DeclaringType;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MemberTypes.Method:
|
||||||
|
{
|
||||||
|
var mi = member as MethodInfo;
|
||||||
|
if (ignorePropertyMethodInfos
|
||||||
|
&& (mi.Name.StartsWith("get_") || mi.Name.StartsWith("set_")))
|
||||||
|
return;
|
||||||
|
|
||||||
|
cached = new CacheMethod(mi);
|
||||||
|
returnType = mi.ReturnType;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case MemberTypes.Property:
|
||||||
|
{
|
||||||
|
var pi = member as PropertyInfo;
|
||||||
|
|
||||||
|
if (!pi.CanRead && pi.CanWrite)
|
||||||
|
{
|
||||||
|
// write-only property, cache the set method instead.
|
||||||
|
var setMethod = pi.GetSetMethod(true);
|
||||||
|
if (setMethod != null)
|
||||||
|
TryCacheMember(setMethod, list, cachedSigs, declaringType, inspector, false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cached = new CacheProperty(pi);
|
||||||
|
returnType = pi.PropertyType;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case MemberTypes.Field:
|
||||||
|
{
|
||||||
|
var fi = member as FieldInfo;
|
||||||
|
cached = new CacheField(fi);
|
||||||
|
returnType = fi.FieldType;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
cachedSigs.Add(sig);
|
||||||
|
|
||||||
|
cached.SetFallbackType(returnType);
|
||||||
|
cached.SetInspectorOwner(inspector, member);
|
||||||
|
|
||||||
|
list.Add((T)cached);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ExplorerCore.LogWarning($"Exception caching member {member.DeclaringType.FullName}.{member.Name}!");
|
||||||
|
ExplorerCore.Log(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -5,18 +5,24 @@ using System.Reflection;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityExplorer.Inspectors;
|
using UnityExplorer.Inspectors;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.CacheObject
|
namespace UnityExplorer.CacheObject
|
||||||
{
|
{
|
||||||
public class CacheMethod : CacheMember
|
public class CacheMethod : CacheMember
|
||||||
{
|
{
|
||||||
public MethodInfo MethodInfo { get; internal set; }
|
public MethodInfo MethodInfo { get; }
|
||||||
public override Type DeclaringType => MethodInfo.DeclaringType;
|
public override Type DeclaringType => MethodInfo.DeclaringType;
|
||||||
public override bool CanWrite => false;
|
public override bool CanWrite => false;
|
||||||
public override bool IsStatic => MethodInfo.IsStatic;
|
public override bool IsStatic => MethodInfo.IsStatic;
|
||||||
|
|
||||||
public override bool ShouldAutoEvaluate => false;
|
public override bool ShouldAutoEvaluate => false;
|
||||||
|
|
||||||
|
public CacheMethod (MethodInfo mi)
|
||||||
|
{
|
||||||
|
this.MethodInfo = mi;
|
||||||
|
}
|
||||||
|
|
||||||
public override void SetInspectorOwner(ReflectionInspector inspector, MemberInfo member)
|
public override void SetInspectorOwner(ReflectionInspector inspector, MemberInfo member)
|
||||||
{
|
{
|
||||||
base.SetInspectorOwner(inspector, member);
|
base.SetInspectorOwner(inspector, member);
|
||||||
@ -39,13 +45,11 @@ namespace UnityExplorer.CacheObject
|
|||||||
ret = methodInfo.Invoke(DeclaringInstance, Evaluator.TryParseArguments());
|
ret = methodInfo.Invoke(DeclaringInstance, Evaluator.TryParseArguments());
|
||||||
else
|
else
|
||||||
ret = methodInfo.Invoke(DeclaringInstance, ArgumentUtility.EmptyArgs);
|
ret = methodInfo.Invoke(DeclaringInstance, ArgumentUtility.EmptyArgs);
|
||||||
HadException = false;
|
|
||||||
LastException = null;
|
LastException = null;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
HadException = true;
|
|
||||||
LastException = ex;
|
LastException = ex;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,8 @@ using UniverseLib.UI.Models;
|
|||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
using UniverseLib.UI.ObjectPool;
|
||||||
|
|
||||||
namespace UnityExplorer.CacheObject
|
namespace UnityExplorer.CacheObject
|
||||||
{
|
{
|
||||||
@ -55,7 +57,6 @@ namespace UnityExplorer.CacheObject
|
|||||||
public abstract bool ShouldAutoEvaluate { get; }
|
public abstract bool ShouldAutoEvaluate { get; }
|
||||||
public abstract bool HasArguments { get; }
|
public abstract bool HasArguments { get; }
|
||||||
public abstract bool CanWrite { get; }
|
public abstract bool CanWrite { get; }
|
||||||
public bool HadException { get; protected set; }
|
|
||||||
public Exception LastException { get; protected set; }
|
public Exception LastException { get; protected set; }
|
||||||
|
|
||||||
public virtual void SetFallbackType(Type fallbackType)
|
public virtual void SetFallbackType(Type fallbackType)
|
||||||
@ -104,8 +105,8 @@ namespace UnityExplorer.CacheObject
|
|||||||
if (CellView != null)
|
if (CellView != null)
|
||||||
SetDataToCell(CellView);
|
SetDataToCell(CellView);
|
||||||
|
|
||||||
// If the owner's parent CacheObject is set, we are setting the value of an inspected struct.
|
// If the owner's ParentCacheObject is set, we are setting the value of an inspected struct.
|
||||||
// Set the inspector target as the value back to that parent cacheobject.
|
// Set the inspector target as the value back to that parent.
|
||||||
if (Owner.ParentCacheObject != null)
|
if (Owner.ParentCacheObject != null)
|
||||||
Owner.ParentCacheObject.SetUserValue(Owner.Target);
|
Owner.ParentCacheObject.SetUserValue(Owner.Target);
|
||||||
}
|
}
|
||||||
@ -135,7 +136,7 @@ namespace UnityExplorer.CacheObject
|
|||||||
{
|
{
|
||||||
var prevState = State;
|
var prevState = State;
|
||||||
|
|
||||||
if (HadException)
|
if (LastException != null)
|
||||||
{
|
{
|
||||||
LastValueWasNull = true;
|
LastValueWasNull = true;
|
||||||
LastValueType = FallbackType;
|
LastValueType = FallbackType;
|
||||||
@ -156,7 +157,7 @@ namespace UnityExplorer.CacheObject
|
|||||||
{
|
{
|
||||||
// If we changed states (always needs IValue change)
|
// If we changed states (always needs IValue change)
|
||||||
// or if the value is null, and the fallback type isnt string (we always want to edit strings).
|
// or if the value is null, and the fallback type isnt string (we always want to edit strings).
|
||||||
if (State != prevState || (State != ValueState.String && Value.IsNullOrDestroyed()))
|
if (State != prevState || (State != ValueState.String && State != ValueState.Exception && Value.IsNullOrDestroyed()))
|
||||||
{
|
{
|
||||||
// need to return IValue
|
// need to return IValue
|
||||||
ReleaseIValue();
|
ReleaseIValue();
|
||||||
@ -204,7 +205,7 @@ namespace UnityExplorer.CacheObject
|
|||||||
return $"<i>{NOT_YET_EVAL} ({SignatureHighlighter.Parse(FallbackType, true)})</i>";
|
return $"<i>{NOT_YET_EVAL} ({SignatureHighlighter.Parse(FallbackType, true)})</i>";
|
||||||
|
|
||||||
case ValueState.Exception:
|
case ValueState.Exception:
|
||||||
return $"<i><color=red>{LastException.ReflectionExToString()}</color></i>";
|
return $"<i><color=#eb4034>{LastException.ReflectionExToString()}</color></i>";
|
||||||
|
|
||||||
// bool and number dont want the label for the value at all
|
// bool and number dont want the label for the value at all
|
||||||
case ValueState.Boolean:
|
case ValueState.Boolean:
|
||||||
@ -261,7 +262,7 @@ namespace UnityExplorer.CacheObject
|
|||||||
{
|
{
|
||||||
cell.NameLabel.text = NameLabelText;
|
cell.NameLabel.text = NameLabelText;
|
||||||
if (cell.HiddenNameLabel != null)
|
if (cell.HiddenNameLabel != null)
|
||||||
cell.HiddenNameLabel.Text = NameLabelTextRaw;
|
cell.HiddenNameLabel.Text = NameLabelTextRaw ?? string.Empty;
|
||||||
cell.ValueLabel.gameObject.SetActive(true);
|
cell.ValueLabel.gameObject.SetActive(true);
|
||||||
|
|
||||||
cell.SubContentHolder.gameObject.SetActive(SubContentShowWanted);
|
cell.SubContentHolder.gameObject.SetActive(SubContentShowWanted);
|
||||||
@ -289,36 +290,36 @@ namespace UnityExplorer.CacheObject
|
|||||||
switch (State)
|
switch (State)
|
||||||
{
|
{
|
||||||
case ValueState.Exception:
|
case ValueState.Exception:
|
||||||
SetValueState(cell, ValueStateArgs.Default);
|
SetValueState(cell, new(true, subContentButtonActive: true));
|
||||||
break;
|
break;
|
||||||
case ValueState.Boolean:
|
case ValueState.Boolean:
|
||||||
SetValueState(cell, new ValueStateArgs(false, toggleActive: true, applyActive: CanWrite));
|
SetValueState(cell, new(false, toggleActive: true, applyActive: CanWrite));
|
||||||
break;
|
break;
|
||||||
case ValueState.Number:
|
case ValueState.Number:
|
||||||
SetValueState(cell, new ValueStateArgs(false, typeLabelActive: true, inputActive: true, applyActive: CanWrite));
|
SetValueState(cell, new(false, typeLabelActive: true, inputActive: true, applyActive: CanWrite));
|
||||||
break;
|
break;
|
||||||
case ValueState.String:
|
case ValueState.String:
|
||||||
if (LastValueWasNull)
|
if (LastValueWasNull)
|
||||||
SetValueState(cell, new ValueStateArgs(true, subContentButtonActive: true));
|
SetValueState(cell, new(true, subContentButtonActive: true));
|
||||||
else
|
else
|
||||||
SetValueState(cell, new ValueStateArgs(true, false, SignatureHighlighter.StringOrange, subContentButtonActive: true));
|
SetValueState(cell, new(true, false, SignatureHighlighter.StringOrange, subContentButtonActive: true));
|
||||||
break;
|
break;
|
||||||
case ValueState.Enum:
|
case ValueState.Enum:
|
||||||
SetValueState(cell, new ValueStateArgs(true, subContentButtonActive: CanWrite));
|
SetValueState(cell, new(true, subContentButtonActive: CanWrite));
|
||||||
break;
|
break;
|
||||||
case ValueState.Color:
|
case ValueState.Color:
|
||||||
case ValueState.ValueStruct:
|
case ValueState.ValueStruct:
|
||||||
if (ParseUtility.CanParse(LastValueType))
|
if (ParseUtility.CanParse(LastValueType))
|
||||||
SetValueState(cell, new ValueStateArgs(false, false, null, true, false, true, CanWrite, true, true));
|
SetValueState(cell, new(false, false, null, true, false, true, CanWrite, true, true));
|
||||||
else
|
else
|
||||||
SetValueState(cell, new ValueStateArgs(true, inspectActive: true, subContentButtonActive: true));
|
SetValueState(cell, new(true, inspectActive: true, subContentButtonActive: true));
|
||||||
break;
|
break;
|
||||||
case ValueState.Collection:
|
case ValueState.Collection:
|
||||||
case ValueState.Dictionary:
|
case ValueState.Dictionary:
|
||||||
SetValueState(cell, new ValueStateArgs(true, inspectActive: !LastValueWasNull, subContentButtonActive: !LastValueWasNull));
|
SetValueState(cell, new(true, inspectActive: !LastValueWasNull, subContentButtonActive: !LastValueWasNull));
|
||||||
break;
|
break;
|
||||||
case ValueState.Unsupported:
|
case ValueState.Unsupported:
|
||||||
SetValueState(cell, new ValueStateArgs(true, inspectActive: !LastValueWasNull));
|
SetValueState(cell, new (true, inspectActive: !LastValueWasNull));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -366,8 +367,10 @@ namespace UnityExplorer.CacheObject
|
|||||||
if (cell.InspectButton != null)
|
if (cell.InspectButton != null)
|
||||||
cell.InspectButton.Component.gameObject.SetActive(args.inspectActive && !LastValueWasNull);
|
cell.InspectButton.Component.gameObject.SetActive(args.inspectActive && !LastValueWasNull);
|
||||||
|
|
||||||
// allow IValue for null strings though
|
// set subcontent button if needed, and for null strings and exceptions
|
||||||
cell.SubContentButton.Component.gameObject.SetActive(args.subContentButtonActive && (!LastValueWasNull || State == ValueState.String));
|
cell.SubContentButton.Component.gameObject.SetActive(
|
||||||
|
args.subContentButtonActive
|
||||||
|
&& (!LastValueWasNull || State == ValueState.String || State == ValueState.Exception));
|
||||||
}
|
}
|
||||||
|
|
||||||
// CacheObjectCell Apply
|
// CacheObjectCell Apply
|
||||||
@ -399,7 +402,7 @@ namespace UnityExplorer.CacheObject
|
|||||||
{
|
{
|
||||||
if (this.IValue == null)
|
if (this.IValue == null)
|
||||||
{
|
{
|
||||||
var ivalueType = InteractiveValue.GetIValueTypeForState(State);
|
Type ivalueType = InteractiveValue.GetIValueTypeForState(State);
|
||||||
|
|
||||||
if (ivalueType == null)
|
if (ivalueType == null)
|
||||||
return;
|
return;
|
||||||
@ -453,6 +456,7 @@ namespace UnityExplorer.CacheObject
|
|||||||
{
|
{
|
||||||
inactiveIValueHolder = new GameObject("Temp_IValue_Holder");
|
inactiveIValueHolder = new GameObject("Temp_IValue_Holder");
|
||||||
GameObject.DontDestroyOnLoad(inactiveIValueHolder);
|
GameObject.DontDestroyOnLoad(inactiveIValueHolder);
|
||||||
|
inactiveIValueHolder.hideFlags = HideFlags.HideAndDontSave;
|
||||||
inactiveIValueHolder.transform.parent = UniversalUI.PoolHolder.transform;
|
inactiveIValueHolder.transform.parent = UniversalUI.PoolHolder.transform;
|
||||||
inactiveIValueHolder.SetActive(false);
|
inactiveIValueHolder.SetActive(false);
|
||||||
}
|
}
|
||||||
@ -465,9 +469,20 @@ namespace UnityExplorer.CacheObject
|
|||||||
|
|
||||||
public struct ValueStateArgs
|
public struct ValueStateArgs
|
||||||
{
|
{
|
||||||
public ValueStateArgs(bool valueActive = true, bool valueRichText = true, Color? valueColor = null,
|
public static ValueStateArgs Default { get; } = new(true);
|
||||||
bool typeLabelActive = false, bool toggleActive = false, bool inputActive = false, bool applyActive = false,
|
|
||||||
bool inspectActive = false, bool subContentButtonActive = false)
|
public Color valueColor;
|
||||||
|
public bool valueActive, valueRichText, typeLabelActive, toggleActive, inputActive, applyActive, inspectActive, subContentButtonActive;
|
||||||
|
|
||||||
|
public ValueStateArgs(bool valueActive = true,
|
||||||
|
bool valueRichText = true,
|
||||||
|
Color? valueColor = null,
|
||||||
|
bool typeLabelActive = false,
|
||||||
|
bool toggleActive = false,
|
||||||
|
bool inputActive = false,
|
||||||
|
bool applyActive = false,
|
||||||
|
bool inspectActive = false,
|
||||||
|
bool subContentButtonActive = false)
|
||||||
{
|
{
|
||||||
this.valueActive = valueActive;
|
this.valueActive = valueActive;
|
||||||
this.valueRichText = valueRichText;
|
this.valueRichText = valueRichText;
|
||||||
@ -479,14 +494,6 @@ namespace UnityExplorer.CacheObject
|
|||||||
this.inspectActive = inspectActive;
|
this.inspectActive = inspectActive;
|
||||||
this.subContentButtonActive = subContentButtonActive;
|
this.subContentButtonActive = subContentButtonActive;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ValueStateArgs Default => _default;
|
|
||||||
private static ValueStateArgs _default = new ValueStateArgs(true);
|
|
||||||
|
|
||||||
public bool valueActive, valueRichText, typeLabelActive, toggleActive,
|
|
||||||
inputActive, applyActive, inspectActive, subContentButtonActive;
|
|
||||||
|
|
||||||
public Color valueColor;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,9 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using UnityEngine;
|
||||||
using UnityExplorer.Inspectors;
|
using UnityExplorer.Inspectors;
|
||||||
|
using UnityExplorer.Runtime;
|
||||||
|
|
||||||
namespace UnityExplorer.CacheObject
|
namespace UnityExplorer.CacheObject
|
||||||
{
|
{
|
||||||
@ -17,6 +19,11 @@ namespace UnityExplorer.CacheObject
|
|||||||
|
|
||||||
public override bool ShouldAutoEvaluate => !HasArguments;
|
public override bool ShouldAutoEvaluate => !HasArguments;
|
||||||
|
|
||||||
|
public CacheProperty(PropertyInfo pi)
|
||||||
|
{
|
||||||
|
this.PropertyInfo = pi;
|
||||||
|
}
|
||||||
|
|
||||||
public override void SetInspectorOwner(ReflectionInspector inspector, MemberInfo member)
|
public override void SetInspectorOwner(ReflectionInspector inspector, MemberInfo member)
|
||||||
{
|
{
|
||||||
base.SetInspectorOwner(inspector, member);
|
base.SetInspectorOwner(inspector, member);
|
||||||
@ -33,13 +40,11 @@ namespace UnityExplorer.CacheObject
|
|||||||
ret = PropertyInfo.GetValue(DeclaringInstance, this.Evaluator.TryParseArguments());
|
ret = PropertyInfo.GetValue(DeclaringInstance, this.Evaluator.TryParseArguments());
|
||||||
else
|
else
|
||||||
ret = PropertyInfo.GetValue(DeclaringInstance, null);
|
ret = PropertyInfo.GetValue(DeclaringInstance, null);
|
||||||
HadException = false;
|
|
||||||
LastException = null;
|
LastException = null;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
HadException = true;
|
|
||||||
LastException = ex;
|
LastException = ex;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,8 @@ using UnityEngine.UI;
|
|||||||
using UnityExplorer.CacheObject;
|
using UnityExplorer.CacheObject;
|
||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
|
using UniverseLib.UI.Models;
|
||||||
|
using UniverseLib;
|
||||||
|
|
||||||
namespace UnityExplorer.CacheObject.IValues
|
namespace UnityExplorer.CacheObject.IValues
|
||||||
{
|
{
|
||||||
@ -16,11 +18,11 @@ namespace UnityExplorer.CacheObject.IValues
|
|||||||
|
|
||||||
public Color EditedColor;
|
public Color EditedColor;
|
||||||
|
|
||||||
private Image m_colorImage;
|
private Image colorImage;
|
||||||
private readonly InputFieldRef[] m_inputs = new InputFieldRef[4];
|
private readonly InputFieldRef[] inputs = new InputFieldRef[4];
|
||||||
private readonly Slider[] m_sliders = new Slider[4];
|
private readonly Slider[] sliders = new Slider[4];
|
||||||
|
|
||||||
private ButtonRef m_applyButton;
|
private ButtonRef applyButton;
|
||||||
|
|
||||||
private static readonly string[] fieldNames = new[] { "R", "G", "B", "A" };
|
private static readonly string[] fieldNames = new[] { "R", "G", "B", "A" };
|
||||||
|
|
||||||
@ -28,11 +30,11 @@ namespace UnityExplorer.CacheObject.IValues
|
|||||||
{
|
{
|
||||||
base.OnBorrowed(owner);
|
base.OnBorrowed(owner);
|
||||||
|
|
||||||
m_applyButton.Component.gameObject.SetActive(owner.CanWrite);
|
applyButton.Component.gameObject.SetActive(owner.CanWrite);
|
||||||
|
|
||||||
foreach (var slider in m_sliders)
|
foreach (var slider in sliders)
|
||||||
slider.interactable = owner.CanWrite;
|
slider.interactable = owner.CanWrite;
|
||||||
foreach (var input in m_inputs)
|
foreach (var input in inputs)
|
||||||
input.Component.readOnly = !owner.CanWrite;
|
input.Component.readOnly = !owner.CanWrite;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,27 +50,27 @@ namespace UnityExplorer.CacheObject.IValues
|
|||||||
{
|
{
|
||||||
IsValueColor32 = true;
|
IsValueColor32 = true;
|
||||||
EditedColor = c32;
|
EditedColor = c32;
|
||||||
m_inputs[0].Text = c32.r.ToString();
|
inputs[0].Text = c32.r.ToString();
|
||||||
m_inputs[1].Text = c32.g.ToString();
|
inputs[1].Text = c32.g.ToString();
|
||||||
m_inputs[2].Text = c32.b.ToString();
|
inputs[2].Text = c32.b.ToString();
|
||||||
m_inputs[3].Text = c32.a.ToString();
|
inputs[3].Text = c32.a.ToString();
|
||||||
foreach (var slider in m_sliders)
|
foreach (var slider in sliders)
|
||||||
slider.maxValue = 255;
|
slider.maxValue = 255;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
IsValueColor32 = false;
|
IsValueColor32 = false;
|
||||||
EditedColor = (Color)value;
|
EditedColor = (Color)value;
|
||||||
m_inputs[0].Text = EditedColor.r.ToString();
|
inputs[0].Text = EditedColor.r.ToString();
|
||||||
m_inputs[1].Text = EditedColor.g.ToString();
|
inputs[1].Text = EditedColor.g.ToString();
|
||||||
m_inputs[2].Text = EditedColor.b.ToString();
|
inputs[2].Text = EditedColor.b.ToString();
|
||||||
m_inputs[3].Text = EditedColor.a.ToString();
|
inputs[3].Text = EditedColor.a.ToString();
|
||||||
foreach (var slider in m_sliders)
|
foreach (var slider in sliders)
|
||||||
slider.maxValue = 1;
|
slider.maxValue = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_colorImage)
|
if (colorImage)
|
||||||
m_colorImage.color = EditedColor;
|
colorImage.color = EditedColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
// setting value to owner
|
// setting value to owner
|
||||||
@ -91,8 +93,8 @@ namespace UnityExplorer.CacheObject.IValues
|
|||||||
case 3: EditedColor.a = val; break;
|
case 3: EditedColor.a = val; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_colorImage)
|
if (colorImage)
|
||||||
m_colorImage.color = EditedColor;
|
colorImage.color = EditedColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnInputChanged(string val, int fieldIndex)
|
private void OnInputChanged(string val, int fieldIndex)
|
||||||
@ -103,13 +105,13 @@ namespace UnityExplorer.CacheObject.IValues
|
|||||||
if (IsValueColor32)
|
if (IsValueColor32)
|
||||||
{
|
{
|
||||||
byte value = byte.Parse(val);
|
byte value = byte.Parse(val);
|
||||||
m_sliders[fieldIndex].value = value;
|
sliders[fieldIndex].value = value;
|
||||||
f = (float)((decimal)value / 255);
|
f = (float)((decimal)value / 255);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
f = float.Parse(val);
|
f = float.Parse(val);
|
||||||
m_sliders[fieldIndex].value = f;
|
sliders[fieldIndex].value = f;
|
||||||
}
|
}
|
||||||
|
|
||||||
SetColorField(f, fieldIndex);
|
SetColorField(f, fieldIndex);
|
||||||
@ -129,12 +131,12 @@ namespace UnityExplorer.CacheObject.IValues
|
|||||||
{
|
{
|
||||||
if (IsValueColor32)
|
if (IsValueColor32)
|
||||||
{
|
{
|
||||||
m_inputs[fieldIndex].Text = ((byte)val).ToString();
|
inputs[fieldIndex].Text = ((byte)val).ToString();
|
||||||
val /= 255f;
|
val /= 255f;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_inputs[fieldIndex].Text = val.ToString();
|
inputs[fieldIndex].Text = val.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
SetColorField(val, fieldIndex);
|
SetColorField(val, fieldIndex);
|
||||||
@ -167,15 +169,15 @@ namespace UnityExplorer.CacheObject.IValues
|
|||||||
|
|
||||||
// apply button
|
// apply button
|
||||||
|
|
||||||
m_applyButton = UIFactory.CreateButton(horiGroup, "ApplyButton", "Apply", new Color(0.2f, 0.26f, 0.2f));
|
applyButton = UIFactory.CreateButton(horiGroup, "ApplyButton", "Apply", new Color(0.2f, 0.26f, 0.2f));
|
||||||
UIFactory.SetLayoutElement(m_applyButton.Component.gameObject, minHeight: 25, minWidth: 90);
|
UIFactory.SetLayoutElement(applyButton.Component.gameObject, minHeight: 25, minWidth: 90);
|
||||||
m_applyButton.OnClick += SetValueToOwner;
|
applyButton.OnClick += SetValueToOwner;
|
||||||
|
|
||||||
// image of color
|
// image of color
|
||||||
|
|
||||||
var imgObj = UIFactory.CreateUIObject("ColorImageHelper", horiGroup);
|
var imgObj = UIFactory.CreateUIObject("ColorImageHelper", horiGroup);
|
||||||
UIFactory.SetLayoutElement(imgObj, minHeight: 25, minWidth: 50, flexibleWidth: 50);
|
UIFactory.SetLayoutElement(imgObj, minHeight: 25, minWidth: 50, flexibleWidth: 50);
|
||||||
m_colorImage = imgObj.AddComponent<Image>();
|
colorImage = imgObj.AddComponent<Image>();
|
||||||
|
|
||||||
return UIRoot;
|
return UIRoot;
|
||||||
}
|
}
|
||||||
@ -190,11 +192,11 @@ namespace UnityExplorer.CacheObject.IValues
|
|||||||
|
|
||||||
var input = UIFactory.CreateInputField(row, "Input", "...");
|
var input = UIFactory.CreateInputField(row, "Input", "...");
|
||||||
UIFactory.SetLayoutElement(input.UIRoot, minWidth: 40, minHeight: 25, flexibleHeight: 0);
|
UIFactory.SetLayoutElement(input.UIRoot, minWidth: 40, minHeight: 25, flexibleHeight: 0);
|
||||||
m_inputs[index] = input;
|
inputs[index] = input;
|
||||||
input.OnValueChanged += (string val) => { OnInputChanged(val, index); };
|
input.OnValueChanged += (string val) => { OnInputChanged(val, index); };
|
||||||
|
|
||||||
var sliderObj = UIFactory.CreateSlider(row, "Slider", out Slider slider);
|
var sliderObj = UIFactory.CreateSlider(row, "Slider", out Slider slider);
|
||||||
m_sliders[index] = slider;
|
sliders[index] = slider;
|
||||||
UIFactory.SetLayoutElement(sliderObj, minHeight: 25, minWidth: 70, flexibleWidth: 999, flexibleHeight: 0);
|
UIFactory.SetLayoutElement(sliderObj, minHeight: 25, minWidth: 70, flexibleWidth: 999, flexibleHeight: 0);
|
||||||
slider.minValue = 0;
|
slider.minValue = 0;
|
||||||
slider.maxValue = 1;
|
slider.maxValue = 1;
|
||||||
|
@ -14,6 +14,8 @@ using UnityExplorer.UI.Widgets;
|
|||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
using UniverseLib.UI.Widgets;
|
using UniverseLib.UI.Widgets;
|
||||||
|
using UniverseLib.UI.Widgets.ScrollView;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.CacheObject.IValues
|
namespace UnityExplorer.CacheObject.IValues
|
||||||
{
|
{
|
||||||
|
@ -10,6 +10,8 @@ using UnityExplorer.UI;
|
|||||||
using UnityExplorer.UI.Widgets.AutoComplete;
|
using UnityExplorer.UI.Widgets.AutoComplete;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
|
using UniverseLib.UI.Models;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.CacheObject.IValues
|
namespace UnityExplorer.CacheObject.IValues
|
||||||
{
|
{
|
||||||
@ -27,8 +29,11 @@ namespace UnityExplorer.CacheObject.IValues
|
|||||||
private EnumCompleter enumCompleter;
|
private EnumCompleter enumCompleter;
|
||||||
|
|
||||||
private GameObject toggleHolder;
|
private GameObject toggleHolder;
|
||||||
private readonly List<Toggle> flagToggles = new List<Toggle>();
|
private readonly List<Toggle> flagToggles = new();
|
||||||
private readonly List<Text> flagTexts = new List<Text>();
|
private readonly List<Text> flagTexts = new();
|
||||||
|
|
||||||
|
public CachedEnumValue ValueAtIndex(int idx) => (CachedEnumValue)CurrentValues[idx];
|
||||||
|
public CachedEnumValue ValueAtKey(object key) => (CachedEnumValue)CurrentValues[key];
|
||||||
|
|
||||||
// Setting value from owner
|
// Setting value from owner
|
||||||
public override void SetValue(object value)
|
public override void SetValue(object value)
|
||||||
@ -68,13 +73,8 @@ namespace UnityExplorer.CacheObject.IValues
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var split = value.ToString().Split(',');
|
|
||||||
var set = new HashSet<string>();
|
|
||||||
foreach (var s in split)
|
|
||||||
set.Add(s.Trim());
|
|
||||||
|
|
||||||
for (int i = 0; i < CurrentValues.Count; i++)
|
for (int i = 0; i < CurrentValues.Count; i++)
|
||||||
flagToggles[i].isOn = set.Contains(ValueAtIdx(i).Name);
|
flagToggles[i].isOn = (value as Enum).HasFlag(ValueAtIndex(i).ActualValue as Enum);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@ -114,7 +114,7 @@ namespace UnityExplorer.CacheObject.IValues
|
|||||||
for (int i = 0; i < CurrentValues.Count; i++)
|
for (int i = 0; i < CurrentValues.Count; i++)
|
||||||
{
|
{
|
||||||
if (flagToggles[i].isOn)
|
if (flagToggles[i].isOn)
|
||||||
values.Add(ValueAtIdx(i).Name);
|
values.Add(ValueAtIndex(i).Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
CurrentOwner.SetUserValue(Enum.Parse(EnumType, string.Join(", ", values.ToArray())));
|
CurrentOwner.SetUserValue(Enum.Parse(EnumType, string.Join(", ", values.ToArray())));
|
||||||
@ -164,9 +164,6 @@ namespace UnityExplorer.CacheObject.IValues
|
|||||||
return UIRoot;
|
return UIRoot;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CachedEnumValue ValueAtIdx(int idx) => (CachedEnumValue)CurrentValues[idx];
|
|
||||||
public CachedEnumValue ValueAtKey(object key) => (CachedEnumValue)CurrentValues[key];
|
|
||||||
|
|
||||||
private void SetupTogglesForEnumType()
|
private void SetupTogglesForEnumType()
|
||||||
{
|
{
|
||||||
toggleHolder.SetActive(true);
|
toggleHolder.SetActive(true);
|
||||||
@ -189,7 +186,7 @@ namespace UnityExplorer.CacheObject.IValues
|
|||||||
AddToggleRow();
|
AddToggleRow();
|
||||||
|
|
||||||
flagToggles[i].isOn = false;
|
flagToggles[i].isOn = false;
|
||||||
flagTexts[i].text = ValueAtIdx(i).Name;
|
flagTexts[i].text = ValueAtIndex(i).Name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,6 +14,8 @@ using UnityExplorer.UI.Widgets;
|
|||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
using UniverseLib.UI.Widgets;
|
using UniverseLib.UI.Widgets;
|
||||||
|
using UniverseLib.UI.Widgets.ScrollView;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.CacheObject.IValues
|
namespace UnityExplorer.CacheObject.IValues
|
||||||
{
|
{
|
||||||
|
@ -11,6 +11,8 @@ using UnityExplorer.UI.Widgets;
|
|||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
|
using UniverseLib.UI.Models;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.CacheObject.IValues
|
namespace UnityExplorer.CacheObject.IValues
|
||||||
{
|
{
|
||||||
@ -29,8 +31,9 @@ namespace UnityExplorer.CacheObject.IValues
|
|||||||
{
|
{
|
||||||
base.OnBorrowed(owner);
|
base.OnBorrowed(owner);
|
||||||
|
|
||||||
inputField.Component.readOnly = !owner.CanWrite;
|
bool canWrite = owner.CanWrite && owner.State != ValueState.Exception;
|
||||||
ApplyButton.Component.gameObject.SetActive(owner.CanWrite);
|
inputField.Component.readOnly = !canWrite;
|
||||||
|
ApplyButton.Component.gameObject.SetActive(canWrite);
|
||||||
|
|
||||||
SaveFilePath.Text = Path.Combine(ConfigManager.Default_Output_Path.Value, "untitled.txt");
|
SaveFilePath.Text = Path.Combine(ConfigManager.Default_Output_Path.Value, "untitled.txt");
|
||||||
}
|
}
|
||||||
@ -45,6 +48,9 @@ namespace UnityExplorer.CacheObject.IValues
|
|||||||
|
|
||||||
public override void SetValue(object value)
|
public override void SetValue(object value)
|
||||||
{
|
{
|
||||||
|
if (CurrentOwner.State == ValueState.Exception)
|
||||||
|
value = CurrentOwner.LastException.ToString();
|
||||||
|
|
||||||
RealValue = value as string;
|
RealValue = value as string;
|
||||||
SaveFileRow.SetActive(IsStringTooLong(RealValue));
|
SaveFileRow.SetActive(IsStringTooLong(RealValue));
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ using UnityExplorer.CacheObject;
|
|||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
using UniverseLib.UI.Models;
|
using UniverseLib.UI.Models;
|
||||||
|
using UniverseLib.UI.ObjectPool;
|
||||||
|
|
||||||
namespace UnityExplorer.CacheObject.IValues
|
namespace UnityExplorer.CacheObject.IValues
|
||||||
{
|
{
|
||||||
@ -15,22 +16,16 @@ namespace UnityExplorer.CacheObject.IValues
|
|||||||
{
|
{
|
||||||
public static Type GetIValueTypeForState(ValueState state)
|
public static Type GetIValueTypeForState(ValueState state)
|
||||||
{
|
{
|
||||||
switch (state)
|
return state switch
|
||||||
{
|
{
|
||||||
case ValueState.String:
|
ValueState.Exception or ValueState.String => typeof(InteractiveString),
|
||||||
return typeof(InteractiveString);
|
ValueState.Enum => typeof(InteractiveEnum),
|
||||||
case ValueState.Enum:
|
ValueState.Collection => typeof(InteractiveList),
|
||||||
return typeof(InteractiveEnum);
|
ValueState.Dictionary => typeof(InteractiveDictionary),
|
||||||
case ValueState.Collection:
|
ValueState.ValueStruct => typeof(InteractiveValueStruct),
|
||||||
return typeof(InteractiveList);
|
ValueState.Color => typeof(InteractiveColor),
|
||||||
case ValueState.Dictionary:
|
_ => null,
|
||||||
return typeof(InteractiveDictionary);
|
};
|
||||||
case ValueState.ValueStruct:
|
|
||||||
return typeof(InteractiveValueStruct);
|
|
||||||
case ValueState.Color:
|
|
||||||
return typeof(InteractiveColor);
|
|
||||||
default: return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public GameObject UIRoot { get; set; }
|
public GameObject UIRoot { get; set; }
|
||||||
@ -38,28 +33,28 @@ namespace UnityExplorer.CacheObject.IValues
|
|||||||
|
|
||||||
public virtual bool CanWrite => this.CurrentOwner.CanWrite;
|
public virtual bool CanWrite => this.CurrentOwner.CanWrite;
|
||||||
|
|
||||||
public CacheObjectBase CurrentOwner => m_owner;
|
public CacheObjectBase CurrentOwner => owner;
|
||||||
private CacheObjectBase m_owner;
|
private CacheObjectBase owner;
|
||||||
|
|
||||||
public bool PendingValueWanted;
|
public bool PendingValueWanted;
|
||||||
|
|
||||||
public virtual void OnBorrowed(CacheObjectBase owner)
|
public virtual void OnBorrowed(CacheObjectBase owner)
|
||||||
{
|
{
|
||||||
if (this.m_owner != null)
|
if (this.owner != null)
|
||||||
{
|
{
|
||||||
ExplorerCore.LogWarning("Setting an IValue's owner but there is already one set. Maybe it wasn't cleaned up?");
|
ExplorerCore.LogWarning("Setting an IValue's owner but there is already one set. Maybe it wasn't cleaned up?");
|
||||||
ReleaseFromOwner();
|
ReleaseFromOwner();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.m_owner = owner;
|
this.owner = owner;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void ReleaseFromOwner()
|
public virtual void ReleaseFromOwner()
|
||||||
{
|
{
|
||||||
if (this.m_owner == null)
|
if (this.owner == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.m_owner = null;
|
this.owner = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void SetValue(object value);
|
public abstract void SetValue(object value);
|
||||||
|
@ -9,6 +9,8 @@ using UnityExplorer.CacheObject;
|
|||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
|
using UniverseLib.UI.Models;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.CacheObject.IValues
|
namespace UnityExplorer.CacheObject.IValues
|
||||||
{
|
{
|
||||||
@ -55,7 +57,7 @@ namespace UnityExplorer.CacheObject.IValues
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly Dictionary<string, StructInfo> typeSupportCache = new Dictionary<string, StructInfo>();
|
private static readonly Dictionary<string, StructInfo> typeSupportCache = new();
|
||||||
|
|
||||||
private const BindingFlags INSTANCE_FLAGS = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public;
|
private const BindingFlags INSTANCE_FLAGS = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public;
|
||||||
private const string SYSTEM_VOID = "System.Void";
|
private const string SYSTEM_VOID = "System.Void";
|
||||||
|
@ -7,6 +7,7 @@ using UnityEngine.UI;
|
|||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.CacheObject.Views
|
namespace UnityExplorer.CacheObject.Views
|
||||||
{
|
{
|
||||||
|
@ -9,6 +9,7 @@ using UnityExplorer.Inspectors;
|
|||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
using UnityExplorer.UI.Widgets;
|
using UnityExplorer.UI.Widgets;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
|
using UniverseLib.UI.Models;
|
||||||
|
|
||||||
namespace UnityExplorer.CacheObject.Views
|
namespace UnityExplorer.CacheObject.Views
|
||||||
{
|
{
|
||||||
|
@ -7,6 +7,7 @@ using UnityEngine.UI;
|
|||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
using UnityExplorer.UI.Widgets;
|
using UnityExplorer.UI.Widgets;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
|
using UniverseLib.UI.Models;
|
||||||
|
|
||||||
namespace UnityExplorer.CacheObject.Views
|
namespace UnityExplorer.CacheObject.Views
|
||||||
{
|
{
|
||||||
|
@ -4,14 +4,12 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.CacheObject.IValues;
|
|
||||||
using UnityExplorer.Inspectors;
|
|
||||||
using UnityExplorer.UI;
|
|
||||||
using UnityExplorer.UI.Panels;
|
using UnityExplorer.UI.Panels;
|
||||||
using UnityExplorer.UI.Widgets;
|
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
using UniverseLib.UI.Widgets;
|
using UniverseLib.UI.Models;
|
||||||
|
using UniverseLib.UI.Widgets.ScrollView;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.CacheObject.Views
|
namespace UnityExplorer.CacheObject.Views
|
||||||
{
|
{
|
||||||
@ -103,7 +101,7 @@ namespace UnityExplorer.CacheObject.Views
|
|||||||
{
|
{
|
||||||
this.SubContentButton.ButtonText.text = SubContentHolder.activeSelf ? "▼" : "▲";
|
this.SubContentButton.ButtonText.text = SubContentHolder.activeSelf ? "▼" : "▲";
|
||||||
Color color = SubContentHolder.activeSelf ? subActiveColor : subInactiveColor;
|
Color color = SubContentHolder.activeSelf ? subActiveColor : subInactiveColor;
|
||||||
RuntimeProvider.Instance.SetColorBlock(SubContentButton.Component, color, color * 1.3f);
|
RuntimeHelper.SetColorBlock(SubContentButton.Component, color, color * 1.3f);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract void ConstructEvaluateHolder(GameObject parent);
|
protected abstract void ConstructEvaluateHolder(GameObject parent);
|
||||||
|
@ -12,11 +12,16 @@ namespace UnityExplorer.Config
|
|||||||
{
|
{
|
||||||
public static class ConfigManager
|
public static class ConfigManager
|
||||||
{
|
{
|
||||||
|
internal static readonly Dictionary<string, IConfigElement> ConfigElements = new();
|
||||||
|
internal static readonly Dictionary<string, IConfigElement> InternalConfigs = new();
|
||||||
|
|
||||||
// Each Mod Loader has its own ConfigHandler.
|
// Each Mod Loader has its own ConfigHandler.
|
||||||
// See the UnityExplorer.Loader namespace for the implementations.
|
// See the UnityExplorer.Loader namespace for the implementations.
|
||||||
public static ConfigHandler Handler { get; private set; }
|
public static ConfigHandler Handler { get; private set; }
|
||||||
|
|
||||||
|
// Actual UE Settings
|
||||||
public static ConfigElement<KeyCode> Master_Toggle;
|
public static ConfigElement<KeyCode> Master_Toggle;
|
||||||
|
public static ConfigElement<int> Target_Display;
|
||||||
public static ConfigElement<UIManager.VerticalAnchor> Main_Navbar_Anchor;
|
public static ConfigElement<UIManager.VerticalAnchor> Main_Navbar_Anchor;
|
||||||
public static ConfigElement<bool> Force_Unlock_Mouse;
|
public static ConfigElement<bool> Force_Unlock_Mouse;
|
||||||
public static ConfigElement<KeyCode> Force_Unlock_Toggle;
|
public static ConfigElement<KeyCode> Force_Unlock_Toggle;
|
||||||
@ -26,22 +31,20 @@ namespace UnityExplorer.Config
|
|||||||
public static ConfigElement<bool> Log_Unity_Debug;
|
public static ConfigElement<bool> Log_Unity_Debug;
|
||||||
public static ConfigElement<bool> Hide_On_Startup;
|
public static ConfigElement<bool> Hide_On_Startup;
|
||||||
public static ConfigElement<float> Startup_Delay_Time;
|
public static ConfigElement<float> Startup_Delay_Time;
|
||||||
|
|
||||||
public static ConfigElement<string> Reflection_Signature_Blacklist;
|
public static ConfigElement<string> Reflection_Signature_Blacklist;
|
||||||
|
public static ConfigElement<KeyCode> World_MouseInspect_Keybind;
|
||||||
|
public static ConfigElement<KeyCode> UI_MouseInspect_Keybind;
|
||||||
|
|
||||||
// internal configs
|
// internal configs
|
||||||
internal static InternalConfigHandler InternalHandler { get; private set; }
|
internal static InternalConfigHandler InternalHandler { get; private set; }
|
||||||
|
internal static readonly Dictionary<UIManager.Panels, ConfigElement<string>> PanelSaveData = new();
|
||||||
|
|
||||||
public static ConfigElement<string> ObjectExplorerData;
|
internal static ConfigElement<string> GetPanelSaveData(UIManager.Panels panel)
|
||||||
public static ConfigElement<string> InspectorData;
|
{
|
||||||
public static ConfigElement<string> CSConsoleData;
|
if (!PanelSaveData.ContainsKey(panel))
|
||||||
public static ConfigElement<string> OptionsPanelData;
|
PanelSaveData.Add(panel, new ConfigElement<string>(panel.ToString(), string.Empty, string.Empty, true));
|
||||||
public static ConfigElement<string> ConsoleLogData;
|
return PanelSaveData[panel];
|
||||||
public static ConfigElement<string> HookManagerData;
|
}
|
||||||
public static ConfigElement<string> ClipboardData;
|
|
||||||
|
|
||||||
internal static readonly Dictionary<string, IConfigElement> ConfigElements = new Dictionary<string, IConfigElement>();
|
|
||||||
internal static readonly Dictionary<string, IConfigElement> InternalConfigs = new Dictionary<string, IConfigElement>();
|
|
||||||
|
|
||||||
public static void Init(ConfigHandler configHandler)
|
public static void Init(ConfigHandler configHandler)
|
||||||
{
|
{
|
||||||
@ -79,6 +82,11 @@ namespace UnityExplorer.Config
|
|||||||
"The key to enable or disable UnityExplorer's menu and features.",
|
"The key to enable or disable UnityExplorer's menu and features.",
|
||||||
KeyCode.F7);
|
KeyCode.F7);
|
||||||
|
|
||||||
|
Target_Display = new ConfigElement<int>("Target Display",
|
||||||
|
"The monitor index for UnityExplorer to use, if you have multiple. 0 is the default display, 1 is secondary, etc. " +
|
||||||
|
"Restart recommended when changing this setting. Make sure your extra monitors are the same resolution as your primary monitor.",
|
||||||
|
0);
|
||||||
|
|
||||||
Main_Navbar_Anchor = new ConfigElement<UIManager.VerticalAnchor>("Main Navbar Anchor",
|
Main_Navbar_Anchor = new ConfigElement<UIManager.VerticalAnchor>("Main Navbar Anchor",
|
||||||
"The vertical anchor of the main UnityExplorer Navbar, in case you want to move it.",
|
"The vertical anchor of the main UnityExplorer Navbar, in case you want to move it.",
|
||||||
UIManager.VerticalAnchor.Top);
|
UIManager.VerticalAnchor.Top);
|
||||||
@ -87,13 +95,18 @@ namespace UnityExplorer.Config
|
|||||||
"Should UnityExplorer be hidden on startup?",
|
"Should UnityExplorer be hidden on startup?",
|
||||||
false);
|
false);
|
||||||
|
|
||||||
|
World_MouseInspect_Keybind = new("World Mouse-Inspect Keybind",
|
||||||
|
"Optional keybind to being a World-mode Mouse Inspect.",
|
||||||
|
KeyCode.None);
|
||||||
|
|
||||||
|
UI_MouseInspect_Keybind = new("UI Mouse-Inspect Keybind",
|
||||||
|
"Optional keybind to begin a UI_mode Mouse Inspect.",
|
||||||
|
KeyCode.None);
|
||||||
|
|
||||||
Force_Unlock_Mouse = new ConfigElement<bool>("Force Unlock Mouse",
|
Force_Unlock_Mouse = new ConfigElement<bool>("Force Unlock Mouse",
|
||||||
"Force the Cursor to be unlocked (visible) when the UnityExplorer menu is open.",
|
"Force the Cursor to be unlocked (visible) when the UnityExplorer menu is open.",
|
||||||
true);
|
true);
|
||||||
Force_Unlock_Mouse.OnValueChanged += (bool value) =>
|
Force_Unlock_Mouse.OnValueChanged += (bool value) => UniverseLib.Config.ConfigManager.Force_Unlock_Mouse = value;
|
||||||
{
|
|
||||||
UniverseLib.Config.ConfigManager.Force_Unlock_Mouse = value;
|
|
||||||
};
|
|
||||||
|
|
||||||
Force_Unlock_Toggle = new ConfigElement<KeyCode>("Force Unlock Toggle Key",
|
Force_Unlock_Toggle = new ConfigElement<KeyCode>("Force Unlock Toggle Key",
|
||||||
"The keybind to toggle the 'Force Unlock Mouse' setting. Only usable when UnityExplorer is open.",
|
"The keybind to toggle the 'Force Unlock Mouse' setting. Only usable when UnityExplorer is open.",
|
||||||
@ -102,10 +115,7 @@ namespace UnityExplorer.Config
|
|||||||
Disable_EventSystem_Override = new ConfigElement<bool>("Disable EventSystem override",
|
Disable_EventSystem_Override = new ConfigElement<bool>("Disable EventSystem override",
|
||||||
"If enabled, UnityExplorer will not override the EventSystem from the game.\n<b>May require restart to take effect.</b>",
|
"If enabled, UnityExplorer will not override the EventSystem from the game.\n<b>May require restart to take effect.</b>",
|
||||||
false);
|
false);
|
||||||
Disable_EventSystem_Override.OnValueChanged += (bool value) =>
|
Disable_EventSystem_Override.OnValueChanged += (bool value) => UniverseLib.Config.ConfigManager.Disable_EventSystem_Override = value;
|
||||||
{
|
|
||||||
UniverseLib.Config.ConfigManager.Disable_EventSystem_Override = value;
|
|
||||||
};
|
|
||||||
|
|
||||||
Log_Unity_Debug = new ConfigElement<bool>("Log Unity Debug",
|
Log_Unity_Debug = new ConfigElement<bool>("Log Unity Debug",
|
||||||
"Should UnityEngine.Debug.Log messages be printed to UnityExplorer's log?",
|
"Should UnityEngine.Debug.Log messages be printed to UnityExplorer's log?",
|
||||||
@ -124,16 +134,6 @@ namespace UnityExplorer.Config
|
|||||||
"Seperate signatures with a semicolon ';'.\r\n" +
|
"Seperate signatures with a semicolon ';'.\r\n" +
|
||||||
"For example, to blacklist Camera.main, you would add 'UnityEngine.Camera.main;'",
|
"For example, to blacklist Camera.main, you would add 'UnityEngine.Camera.main;'",
|
||||||
"");
|
"");
|
||||||
|
|
||||||
// Internal configs (panel save data)
|
|
||||||
|
|
||||||
ObjectExplorerData = new ConfigElement<string>("ObjectExplorer", "", "", true);
|
|
||||||
InspectorData = new ConfigElement<string>("Inspector", "", "", true);
|
|
||||||
CSConsoleData = new ConfigElement<string>("CSConsole", "", "", true);
|
|
||||||
OptionsPanelData = new ConfigElement<string>("OptionsPanel", "", "", true);
|
|
||||||
ConsoleLogData = new ConfigElement<string>("ConsoleLog", "", "", true);
|
|
||||||
HookManagerData = new ConfigElement<string>("HookManager", "", "", true);
|
|
||||||
ClipboardData = new ConfigElement<string>("Clipboard", "", "", true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,24 +1,22 @@
|
|||||||
using IniParser.Parser;
|
using System;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
|
using Tomlet;
|
||||||
|
using Tomlet.Models;
|
||||||
|
|
||||||
namespace UnityExplorer.Config
|
namespace UnityExplorer.Config
|
||||||
{
|
{
|
||||||
public class InternalConfigHandler : ConfigHandler
|
public class InternalConfigHandler : ConfigHandler
|
||||||
{
|
{
|
||||||
internal static IniDataParser _parser;
|
internal static string CONFIG_PATH;
|
||||||
internal static string INI_PATH;
|
|
||||||
|
|
||||||
public override void Init()
|
public override void Init()
|
||||||
{
|
{
|
||||||
INI_PATH = Path.Combine(ExplorerCore.Loader.ExplorerFolder, "data.ini");
|
CONFIG_PATH = Path.Combine(ExplorerCore.Loader.ExplorerFolder, "data.cfg");
|
||||||
_parser = new IniDataParser();
|
|
||||||
_parser.Configuration.CommentString = "#";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void LoadConfig()
|
public override void LoadConfig()
|
||||||
@ -37,32 +35,24 @@ namespace UnityExplorer.Config
|
|||||||
// Not necessary
|
// Not necessary
|
||||||
}
|
}
|
||||||
|
|
||||||
public override T GetConfigValue<T>(ConfigElement<T> element)
|
// Not necessary, just return the value.
|
||||||
{
|
public override T GetConfigValue<T>(ConfigElement<T> element) => element.Value;
|
||||||
// Not necessary, just return the value.
|
|
||||||
return element.Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void OnAnyConfigChanged()
|
// Always just auto-save.
|
||||||
{
|
public override void OnAnyConfigChanged() => SaveConfig();
|
||||||
SaveConfig();
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool TryLoadConfig()
|
public bool TryLoadConfig()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (!File.Exists(INI_PATH))
|
if (!File.Exists(CONFIG_PATH))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
string ini = File.ReadAllText(INI_PATH);
|
TomlDocument document = TomlParser.ParseFile(CONFIG_PATH);
|
||||||
|
foreach (var key in document.Keys)
|
||||||
var data = _parser.Parse(ini);
|
|
||||||
|
|
||||||
foreach (var config in data.Sections["Config"])
|
|
||||||
{
|
{
|
||||||
if (ConfigManager.InternalConfigs.TryGetValue(config.KeyName, out IConfigElement configElement))
|
var panelKey = (UIManager.Panels)Enum.Parse(typeof(UIManager.Panels), key);
|
||||||
configElement.BoxedValue = StringToConfigValue(config.Value, configElement.ElementType);
|
ConfigManager.GetPanelSaveData(panelKey).Value = document.GetString(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -79,27 +69,11 @@ namespace UnityExplorer.Config
|
|||||||
if (UIManager.Initializing)
|
if (UIManager.Initializing)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var data = new IniParser.Model.IniData();
|
var tomlDocument = TomlDocument.CreateEmpty();
|
||||||
|
|
||||||
data.Sections.AddSection("Config");
|
|
||||||
var sec = data.Sections["Config"];
|
|
||||||
|
|
||||||
foreach (var entry in ConfigManager.InternalConfigs)
|
foreach (var entry in ConfigManager.InternalConfigs)
|
||||||
sec.AddKey(entry.Key, entry.Value.BoxedValue.ToString());
|
tomlDocument.Put(entry.Key, entry.Value.BoxedValue as string, false);
|
||||||
|
|
||||||
File.WriteAllText(INI_PATH, data.ToString());
|
File.WriteAllText(CONFIG_PATH, tomlDocument.SerializedValue);
|
||||||
}
|
|
||||||
|
|
||||||
public object StringToConfigValue(string value, Type elementType)
|
|
||||||
{
|
|
||||||
if (elementType.IsEnum)
|
|
||||||
return Enum.Parse(elementType, value);
|
|
||||||
else if (elementType == typeof(bool))
|
|
||||||
return bool.Parse(value);
|
|
||||||
else if (elementType == typeof(int))
|
|
||||||
return int.Parse(value);
|
|
||||||
else
|
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,29 +9,26 @@ using UnhollowerRuntimeLib;
|
|||||||
|
|
||||||
namespace UnityExplorer
|
namespace UnityExplorer
|
||||||
{
|
{
|
||||||
// Handles all Behaviour update calls for UnityExplorer (Update, FixedUpdate, OnPostRender).
|
|
||||||
// Basically just a wrapper which calls the corresponding methods in ExplorerCore.
|
|
||||||
|
|
||||||
public class ExplorerBehaviour : MonoBehaviour
|
public class ExplorerBehaviour : MonoBehaviour
|
||||||
{
|
{
|
||||||
internal static ExplorerBehaviour Instance { get; private set; }
|
internal static ExplorerBehaviour Instance { get; private set; }
|
||||||
|
|
||||||
|
#if CPP
|
||||||
|
public ExplorerBehaviour(IntPtr ptr) : base(ptr) { }
|
||||||
|
#endif
|
||||||
|
|
||||||
internal static void Setup()
|
internal static void Setup()
|
||||||
{
|
{
|
||||||
#if CPP
|
#if CPP
|
||||||
ClassInjector.RegisterTypeInIl2Cpp<ExplorerBehaviour>();
|
ClassInjector.RegisterTypeInIl2Cpp<ExplorerBehaviour>();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
var obj = new GameObject("ExplorerBehaviour");
|
GameObject obj = new("ExplorerBehaviour");
|
||||||
GameObject.DontDestroyOnLoad(obj);
|
DontDestroyOnLoad(obj);
|
||||||
obj.hideFlags |= HideFlags.HideAndDontSave;
|
obj.hideFlags = HideFlags.HideAndDontSave;
|
||||||
Instance = obj.AddComponent<ExplorerBehaviour>();
|
Instance = obj.AddComponent<ExplorerBehaviour>();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if CPP
|
|
||||||
public ExplorerBehaviour(IntPtr ptr) : base(ptr) { }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
internal void Update()
|
internal void Update()
|
||||||
{
|
{
|
||||||
ExplorerCore.Update();
|
ExplorerCore.Update();
|
||||||
|
@ -1,14 +1,13 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityExplorer.CacheObject;
|
||||||
using UnityExplorer.Config;
|
using UnityExplorer.Config;
|
||||||
using UnityExplorer.UI;
|
|
||||||
using UnityExplorer.ObjectExplorer;
|
using UnityExplorer.ObjectExplorer;
|
||||||
using UnityExplorer.UI.Panels;
|
|
||||||
using UnityExplorer.Runtime;
|
using UnityExplorer.Runtime;
|
||||||
|
using UnityExplorer.UI;
|
||||||
|
using UnityExplorer.UI.Panels;
|
||||||
|
using UniverseLib;
|
||||||
using UniverseLib.Input;
|
using UniverseLib.Input;
|
||||||
|
|
||||||
namespace UnityExplorer
|
namespace UnityExplorer
|
||||||
@ -16,7 +15,7 @@ namespace UnityExplorer
|
|||||||
public static class ExplorerCore
|
public static class ExplorerCore
|
||||||
{
|
{
|
||||||
public const string NAME = "UnityExplorer";
|
public const string NAME = "UnityExplorer";
|
||||||
public const string VERSION = "4.5.0";
|
public const string VERSION = "4.6.3";
|
||||||
public const string AUTHOR = "Sinai";
|
public const string AUTHOR = "Sinai";
|
||||||
public const string GUID = "com.sinai.unityexplorer";
|
public const string GUID = "com.sinai.unityexplorer";
|
||||||
|
|
||||||
@ -30,22 +29,20 @@ namespace UnityExplorer
|
|||||||
public static void Init(IExplorerLoader loader)
|
public static void Init(IExplorerLoader loader)
|
||||||
{
|
{
|
||||||
if (Loader != null)
|
if (Loader != null)
|
||||||
{
|
throw new Exception("UnityExplorer is already loaded.");
|
||||||
LogWarning("UnityExplorer is already loaded!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Loader = loader;
|
Loader = loader;
|
||||||
|
|
||||||
Log($"{NAME} {VERSION} initializing...");
|
Log($"{NAME} {VERSION} initializing...");
|
||||||
|
|
||||||
if (!Directory.Exists(Loader.ExplorerFolder))
|
Directory.CreateDirectory(Loader.ExplorerFolder);
|
||||||
Directory.CreateDirectory(Loader.ExplorerFolder);
|
|
||||||
|
|
||||||
ConfigManager.Init(Loader.ConfigHandler);
|
ConfigManager.Init(Loader.ConfigHandler);
|
||||||
RuntimeHelper.Init();
|
|
||||||
ExplorerBehaviour.Setup();
|
|
||||||
|
|
||||||
UniverseLib.Universe.Init(ConfigManager.Startup_Delay_Time.Value, LateInit, Log, new()
|
UERuntimeHelper.Init();
|
||||||
|
ExplorerBehaviour.Setup();
|
||||||
|
UnityCrashPrevention.Init();
|
||||||
|
|
||||||
|
Universe.Init(ConfigManager.Startup_Delay_Time.Value, LateInit, Log, new()
|
||||||
{
|
{
|
||||||
Disable_EventSystem_Override = ConfigManager.Disable_EventSystem_Override.Value,
|
Disable_EventSystem_Override = ConfigManager.Disable_EventSystem_Override.Value,
|
||||||
Force_Unlock_Mouse = ConfigManager.Force_Unlock_Mouse.Value,
|
Force_Unlock_Mouse = ConfigManager.Force_Unlock_Mouse.Value,
|
||||||
@ -56,7 +53,7 @@ namespace UnityExplorer
|
|||||||
// Do a delayed setup so that objects aren't destroyed instantly.
|
// Do a delayed setup so that objects aren't destroyed instantly.
|
||||||
// This can happen for a multitude of reasons.
|
// This can happen for a multitude of reasons.
|
||||||
// Default delay is 1 second which is usually enough.
|
// Default delay is 1 second which is usually enough.
|
||||||
private static void LateInit()
|
static void LateInit()
|
||||||
{
|
{
|
||||||
Log($"Setting up late core features...");
|
Log($"Setting up late core features...");
|
||||||
|
|
||||||
@ -66,21 +63,18 @@ namespace UnityExplorer
|
|||||||
|
|
||||||
UIManager.InitUI();
|
UIManager.InitUI();
|
||||||
|
|
||||||
Log($"{NAME} {VERSION} initialized.");
|
Log($"{NAME} {VERSION} ({Universe.Context}) initialized.");
|
||||||
|
|
||||||
//InspectorManager.Inspect(typeof(Tests.TestClass));
|
//InspectorManager.Inspect(typeof(Tests.TestClass));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
internal static void Update()
|
||||||
/// Should be called once per frame.
|
|
||||||
/// </summary>
|
|
||||||
public static void Update()
|
|
||||||
{
|
{
|
||||||
UIManager.Update();
|
|
||||||
|
|
||||||
// check master toggle
|
// check master toggle
|
||||||
if (InputManager.GetKeyDown(ConfigManager.Master_Toggle.Value))
|
if (InputManager.GetKeyDown(ConfigManager.Master_Toggle.Value))
|
||||||
UIManager.ShowMenu = !UIManager.ShowMenu;
|
UIManager.ShowMenu = !UIManager.ShowMenu;
|
||||||
|
|
||||||
|
UIManager.Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
#region LOGGING
|
#region LOGGING
|
||||||
|
@ -7,7 +7,9 @@ using UnityEngine.UI;
|
|||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
using UnityExplorer.UI.Widgets;
|
using UnityExplorer.UI.Widgets;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
|
using UniverseLib.UI.Models;
|
||||||
using UniverseLib.UI.Widgets;
|
using UniverseLib.UI.Widgets;
|
||||||
|
using UniverseLib.UI.Widgets.ScrollView;
|
||||||
|
|
||||||
namespace UnityExplorer.Hooks
|
namespace UnityExplorer.Hooks
|
||||||
{
|
{
|
||||||
|
@ -5,7 +5,9 @@ using System.Text;
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
|
using UniverseLib.UI.Models;
|
||||||
using UniverseLib.UI.Widgets;
|
using UniverseLib.UI.Widgets;
|
||||||
|
using UniverseLib.UI.Widgets.ScrollView;
|
||||||
|
|
||||||
namespace UnityExplorer.Hooks
|
namespace UnityExplorer.Hooks
|
||||||
{
|
{
|
||||||
|
@ -52,9 +52,9 @@ namespace UnityExplorer.Hooks
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Evaluator.source_file
|
// Evaluator.source_file
|
||||||
private static readonly FieldInfo fi_sourceFile = ReflectionUtility.GetFieldInfo(typeof(Evaluator), "source_file");
|
private static readonly FieldInfo fi_sourceFile = AccessTools.Field(typeof(Evaluator), "source_file");
|
||||||
// TypeDefinition.Definition
|
// TypeDefinition.Definition
|
||||||
private static readonly PropertyInfo pi_Definition = ReflectionUtility.GetPropertyInfo(typeof(TypeDefinition), "Definition");
|
private static readonly PropertyInfo pi_Definition = AccessTools.Property(typeof(TypeDefinition), "Definition");
|
||||||
|
|
||||||
public bool CompileAndGenerateProcessor(string patchSource)
|
public bool CompileAndGenerateProcessor(string patchSource)
|
||||||
{
|
{
|
||||||
|
@ -13,6 +13,8 @@ using UnityExplorer.UI.Panels;
|
|||||||
using UnityExplorer.UI.Widgets;
|
using UnityExplorer.UI.Widgets;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
using UniverseLib.UI.Widgets;
|
using UniverseLib.UI.Widgets;
|
||||||
|
using UniverseLib.UI.Widgets.ScrollView;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.Hooks
|
namespace UnityExplorer.Hooks
|
||||||
{
|
{
|
||||||
@ -87,7 +89,7 @@ namespace UnityExplorer.Hooks
|
|||||||
cell.MethodNameLabel.text = SignatureHighlighter.HighlightMethod(hook.TargetMethod);
|
cell.MethodNameLabel.text = SignatureHighlighter.HighlightMethod(hook.TargetMethod);
|
||||||
|
|
||||||
cell.ToggleActiveButton.ButtonText.text = hook.Enabled ? "Enabled" : "Disabled";
|
cell.ToggleActiveButton.ButtonText.text = hook.Enabled ? "Enabled" : "Disabled";
|
||||||
RuntimeProvider.Instance.SetColorBlockAuto(cell.ToggleActiveButton.Component,
|
RuntimeHelper.SetColorBlockAuto(cell.ToggleActiveButton.Component,
|
||||||
hook.Enabled ? new Color(0.15f, 0.2f, 0.15f) : new Color(0.2f, 0.2f, 0.15f));
|
hook.Enabled ? new Color(0.15f, 0.2f, 0.15f) : new Color(0.2f, 0.2f, 0.15f));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,7 +111,7 @@ namespace UnityExplorer.Hooks
|
|||||||
currentAddEligableMethods.Clear();
|
currentAddEligableMethods.Clear();
|
||||||
foreach (var method in type.GetMethods(ReflectionUtility.FLAGS))
|
foreach (var method in type.GetMethods(ReflectionUtility.FLAGS))
|
||||||
{
|
{
|
||||||
if (method.IsGenericMethod /* || method.IsAbstract */ || RuntimeHelper.IsBlacklisted(method))
|
if (method.IsGenericMethod || UERuntimeHelper.IsBlacklisted(method))
|
||||||
continue;
|
continue;
|
||||||
currentAddEligableMethods.Add(method);
|
currentAddEligableMethods.Add(method);
|
||||||
filteredEligableMethods.Add(method);
|
filteredEligableMethods.Add(method);
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<InputAssemblies Include="$(OutputPath)$(AssemblyName).dll" />
|
<InputAssemblies Include="$(OutputPath)$(AssemblyName).dll" />
|
||||||
<InputAssemblies Include="..\lib\mcs-unity\mcs\bin\Release\mcs.dll" />
|
<InputAssemblies Include="..\lib\mcs-unity\mcs\bin\Release\mcs.dll" />
|
||||||
<InputAssemblies Include="packages\ini-parser.2.5.2\lib\net20\INIFileParser.dll" />
|
<InputAssemblies Include="packages\Samboy063.Tomlet.3.1.3\lib\net35\Tomlet.dll" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<!-- Required references for ILRepack -->
|
<!-- Required references for ILRepack -->
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ReferenceFolders Include="packages\HarmonyX.2.5.2\lib\net35\" />
|
<ReferenceFolders Include="packages\HarmonyX.2.5.2\lib\net35\" />
|
||||||
|
@ -14,6 +14,8 @@ using UnityExplorer.UI.Widgets.AutoComplete;
|
|||||||
using UniverseLib.UI.Widgets;
|
using UniverseLib.UI.Widgets;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
|
using UniverseLib.UI.Widgets.ScrollView;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.Inspectors
|
namespace UnityExplorer.Inspectors
|
||||||
{
|
{
|
||||||
@ -44,7 +46,7 @@ namespace UnityExplorer.Inspectors
|
|||||||
GOControls.UpdateGameObjectInfo(true, true);
|
GOControls.UpdateGameObjectInfo(true, true);
|
||||||
GOControls.UpdateTransformControlValues(true);
|
GOControls.UpdateTransformControlValues(true);
|
||||||
|
|
||||||
RuntimeProvider.Instance.StartCoroutine(InitCoroutine());
|
RuntimeHelper.StartCoroutine(InitCoroutine());
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerator InitCoroutine()
|
private IEnumerator InitCoroutine()
|
||||||
@ -80,7 +82,7 @@ namespace UnityExplorer.Inspectors
|
|||||||
this.Target = newTarget;
|
this.Target = newTarget;
|
||||||
GOControls.UpdateGameObjectInfo(true, true);
|
GOControls.UpdateGameObjectInfo(true, true);
|
||||||
GOControls.UpdateTransformControlValues(true);
|
GOControls.UpdateTransformControlValues(true);
|
||||||
TransformTree.RefreshData(true, false);
|
TransformTree.RefreshData(true, false, true, false);
|
||||||
UpdateComponents();
|
UpdateComponents();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,7 +109,7 @@ namespace UnityExplorer.Inspectors
|
|||||||
|
|
||||||
GOControls.UpdateGameObjectInfo(false, false);
|
GOControls.UpdateGameObjectInfo(false, false);
|
||||||
|
|
||||||
TransformTree.RefreshData(true, false);
|
TransformTree.RefreshData(true, false, false, false);
|
||||||
UpdateComponents();
|
UpdateComponents();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -218,7 +220,7 @@ namespace UnityExplorer.Inspectors
|
|||||||
var newObject = new GameObject(input);
|
var newObject = new GameObject(input);
|
||||||
newObject.transform.parent = GOTarget.transform;
|
newObject.transform.parent = GOTarget.transform;
|
||||||
|
|
||||||
TransformTree.RefreshData(true, false);
|
TransformTree.RefreshData(true, false, true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnAddComponentClicked(string input)
|
private void OnAddComponentClicked(string input)
|
||||||
@ -227,7 +229,7 @@ namespace UnityExplorer.Inspectors
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
RuntimeProvider.Instance.AddComponent<Component>(GOTarget, type);
|
RuntimeHelper.AddComponent<Component>(GOTarget, type);
|
||||||
UpdateComponents();
|
UpdateComponents();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
@ -4,10 +4,10 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.UI;
|
using UniverseLib;
|
||||||
using UnityExplorer.UI.Widgets;
|
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
using UniverseLib.UI.Widgets;
|
using UniverseLib.UI.Models;
|
||||||
|
using UniverseLib.UI.Widgets.ButtonList;
|
||||||
|
|
||||||
namespace UnityExplorer.Inspectors
|
namespace UnityExplorer.Inspectors
|
||||||
{
|
{
|
||||||
|
@ -3,9 +3,10 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityExplorer.UI.Widgets;
|
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
using UniverseLib.UI.Widgets;
|
using UniverseLib.UI.Widgets.ButtonList;
|
||||||
|
using UniverseLib.UI.Widgets.ScrollView;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.Inspectors
|
namespace UnityExplorer.Inspectors
|
||||||
{
|
{
|
||||||
@ -113,7 +114,7 @@ namespace UnityExplorer.Inspectors
|
|||||||
{
|
{
|
||||||
cell.BehaviourToggle.interactable = false;
|
cell.BehaviourToggle.interactable = false;
|
||||||
cell.BehaviourToggle.Set(true, false);
|
cell.BehaviourToggle.Set(true, false);
|
||||||
//RuntimeProvider.Instance.SetColorBlock(cell.BehaviourToggle,)
|
//RuntimeHelper.SetColorBlock(cell.BehaviourToggle,)
|
||||||
cell.BehaviourToggle.graphic.color = new Color(0.2f, 0.2f, 0.2f);
|
cell.BehaviourToggle.graphic.color = new Color(0.2f, 0.2f, 0.2f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,6 +9,8 @@ using UnityExplorer.UI;
|
|||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
using UnityExplorer.UI.Panels;
|
using UnityExplorer.UI.Panels;
|
||||||
|
using UniverseLib.UI.Models;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.Inspectors
|
namespace UnityExplorer.Inspectors
|
||||||
{
|
{
|
||||||
@ -175,7 +177,7 @@ namespace UnityExplorer.Inspectors
|
|||||||
{
|
{
|
||||||
// look for inactive objects
|
// look for inactive objects
|
||||||
var name = input.Split('/').Last();
|
var name = input.Split('/').Last();
|
||||||
var allObjects = RuntimeProvider.Instance.FindObjectsOfTypeAll(typeof(GameObject));
|
var allObjects = RuntimeHelper.FindObjectsOfTypeAll(typeof(GameObject));
|
||||||
var shortList = new List<GameObject>();
|
var shortList = new List<GameObject>();
|
||||||
foreach (var obj in allObjects)
|
foreach (var obj in allObjects)
|
||||||
if (obj.name == name) shortList.Add(obj.TryCast<GameObject>());
|
if (obj.name == name) shortList.Add(obj.TryCast<GameObject>());
|
||||||
@ -572,7 +574,7 @@ namespace UnityExplorer.Inspectors
|
|||||||
var layerLabel = UIFactory.CreateLabel(thirdrow, "LayerLabel", "Layer:", TextAnchor.MiddleLeft, Color.grey);
|
var layerLabel = UIFactory.CreateLabel(thirdrow, "LayerLabel", "Layer:", TextAnchor.MiddleLeft, Color.grey);
|
||||||
UIFactory.SetLayoutElement(layerLabel.gameObject, minHeight: 25, minWidth: 50);
|
UIFactory.SetLayoutElement(layerLabel.gameObject, minHeight: 25, minWidth: 50);
|
||||||
|
|
||||||
var layerDrop = UIFactory.CreateDropdown(thirdrow, out LayerDropdown, "0", 14, OnLayerDropdownChanged);
|
var layerDrop = UIFactory.CreateDropdown(thirdrow, "LayerDropdown", out LayerDropdown, "0", 14, OnLayerDropdownChanged);
|
||||||
UIFactory.SetLayoutElement(layerDrop, minHeight: 25, minWidth: 110, flexibleWidth: 999);
|
UIFactory.SetLayoutElement(layerDrop, minHeight: 25, minWidth: 110, flexibleWidth: 999);
|
||||||
LayerDropdown.captionText.color = SignatureHighlighter.EnumGreen;
|
LayerDropdown.captionText.color = SignatureHighlighter.EnumGreen;
|
||||||
if (layerToNames == null)
|
if (layerToNames == null)
|
||||||
@ -586,7 +588,7 @@ namespace UnityExplorer.Inspectors
|
|||||||
var flagsLabel = UIFactory.CreateLabel(thirdrow, "FlagsLabel", "Flags:", TextAnchor.MiddleRight, Color.grey);
|
var flagsLabel = UIFactory.CreateLabel(thirdrow, "FlagsLabel", "Flags:", TextAnchor.MiddleRight, Color.grey);
|
||||||
UIFactory.SetLayoutElement(flagsLabel.gameObject, minHeight: 25, minWidth: 50);
|
UIFactory.SetLayoutElement(flagsLabel.gameObject, minHeight: 25, minWidth: 50);
|
||||||
|
|
||||||
var flagsDrop = UIFactory.CreateDropdown(thirdrow, out FlagsDropdown, "None", 14, OnFlagsDropdownChanged);
|
var flagsDrop = UIFactory.CreateDropdown(thirdrow, "FlagsDropdown", out FlagsDropdown, "None", 14, OnFlagsDropdownChanged);
|
||||||
FlagsDropdown.captionText.color = SignatureHighlighter.EnumGreen;
|
FlagsDropdown.captionText.color = SignatureHighlighter.EnumGreen;
|
||||||
UIFactory.SetLayoutElement(flagsDrop, minHeight: 25, minWidth: 135, flexibleWidth: 999);
|
UIFactory.SetLayoutElement(flagsDrop, minHeight: 25, minWidth: 135, flexibleWidth: 999);
|
||||||
if (hideFlagsValues == null)
|
if (hideFlagsValues == null)
|
||||||
@ -604,7 +606,7 @@ namespace UnityExplorer.Inspectors
|
|||||||
layerToNames = new List<string>();
|
layerToNames = new List<string>();
|
||||||
for (int i = 0; i < 32; i++)
|
for (int i = 0; i < 32; i++)
|
||||||
{
|
{
|
||||||
var name = RuntimeProvider.Instance.LayerToName(i);
|
var name = RuntimeHelper.LayerToName(i);
|
||||||
if (string.IsNullOrEmpty(name))
|
if (string.IsNullOrEmpty(name))
|
||||||
name = i.ToString();
|
name = i.ToString();
|
||||||
layerToNames.Add(name);
|
layerToNames.Add(name);
|
||||||
|
@ -8,6 +8,7 @@ using UnityExplorer.UI;
|
|||||||
using UniverseLib.UI.Models;
|
using UniverseLib.UI.Models;
|
||||||
using UnityExplorer.UI.Panels;
|
using UnityExplorer.UI.Panels;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
|
using UniverseLib.UI.ObjectPool;
|
||||||
|
|
||||||
namespace UnityExplorer.Inspectors
|
namespace UnityExplorer.Inspectors
|
||||||
{
|
{
|
||||||
|
@ -11,12 +11,14 @@ using UniverseLib.UI.Models;
|
|||||||
using UnityExplorer.UI.Panels;
|
using UnityExplorer.UI.Panels;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
|
using UniverseLib.UI.ObjectPool;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer
|
namespace UnityExplorer
|
||||||
{
|
{
|
||||||
public static class InspectorManager
|
public static class InspectorManager
|
||||||
{
|
{
|
||||||
public static readonly List<InspectorBase> Inspectors = new List<InspectorBase>();
|
public static readonly List<InspectorBase> Inspectors = new();
|
||||||
|
|
||||||
public static InspectorBase ActiveInspector { get; private set; }
|
public static InspectorBase ActiveInspector { get; private set; }
|
||||||
private static InspectorBase lastActiveInspector;
|
private static InspectorBase lastActiveInspector;
|
||||||
@ -92,17 +94,17 @@ namespace UnityExplorer
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void CreateInspector<T>(object target, bool staticReflection = false,
|
private static void CreateInspector<T>(object target, bool staticReflection = false,
|
||||||
CacheObjectBase sourceCache = null) where T : InspectorBase
|
CacheObjectBase parentObject = null) where T : InspectorBase
|
||||||
{
|
{
|
||||||
var inspector = Pool<T>.Borrow();
|
var inspector = Pool<T>.Borrow();
|
||||||
Inspectors.Add(inspector);
|
Inspectors.Add(inspector);
|
||||||
inspector.Target = target;
|
inspector.Target = target;
|
||||||
|
|
||||||
if (sourceCache != null && sourceCache.CanWrite)
|
if (parentObject != null && parentObject.CanWrite)
|
||||||
{
|
{
|
||||||
// only set parent cache object if we are inspecting a struct, otherwise there is no point.
|
// only set parent cache object if we are inspecting a struct, otherwise there is no point.
|
||||||
if (target.GetType().IsValueType && inspector is ReflectionInspector ri)
|
if (target.GetType().IsValueType && inspector is ReflectionInspector ri)
|
||||||
ri.ParentCacheObject = sourceCache;
|
ri.ParentCacheObject = parentObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
UIManager.SetPanelActive(UIManager.Panels.Inspector, true);
|
UIManager.SetPanelActive(UIManager.Panels.Inspector, true);
|
||||||
|
@ -10,6 +10,7 @@ using UnityExplorer.UI.Widgets;
|
|||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
using UnityExplorer.UI.Panels;
|
using UnityExplorer.UI.Panels;
|
||||||
|
using UniverseLib.UI.ObjectPool;
|
||||||
|
|
||||||
namespace UnityExplorer.Inspectors
|
namespace UnityExplorer.Inspectors
|
||||||
{
|
{
|
||||||
@ -28,7 +29,7 @@ namespace UnityExplorer.Inspectors
|
|||||||
public void SetTabColor(bool active)
|
public void SetTabColor(bool active)
|
||||||
{
|
{
|
||||||
Color color = active ? enabledTabColor : disabledTabColor;
|
Color color = active ? enabledTabColor : disabledTabColor;
|
||||||
RuntimeProvider.Instance.SetColorBlock(TabButton.Component, color, color * 1.2f);
|
RuntimeHelper.SetColorBlock(TabButton.Component, color, color * 1.2f);
|
||||||
}
|
}
|
||||||
|
|
||||||
public GameObject CreateContent(GameObject parent)
|
public GameObject CreateContent(GameObject parent)
|
||||||
@ -42,9 +43,10 @@ namespace UnityExplorer.Inspectors
|
|||||||
TabButton = UIFactory.CreateButton(UIRoot, "TabButton", "");
|
TabButton = UIFactory.CreateButton(UIRoot, "TabButton", "");
|
||||||
UIFactory.SetLayoutElement(TabButton.Component.gameObject, minWidth: 173, flexibleWidth: 0);
|
UIFactory.SetLayoutElement(TabButton.Component.gameObject, minWidth: 173, flexibleWidth: 0);
|
||||||
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(TabButton.Component.gameObject, false, false, true, true, 0, 0, 0, 3);
|
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(TabButton.Component.gameObject, false, false, true, true, 0, 0, 0, 3);
|
||||||
|
TabButton.GameObject.AddComponent<Mask>();
|
||||||
|
|
||||||
TabText = TabButton.Component.GetComponentInChildren<Text>();
|
TabText = TabButton.ButtonText;
|
||||||
UIFactory.SetLayoutElement(TabText.gameObject, minHeight: 25, minWidth: 173, flexibleWidth: 0);
|
UIFactory.SetLayoutElement(TabText.gameObject, minHeight: 25, minWidth: 150, flexibleWidth: 0);
|
||||||
TabText.alignment = TextAnchor.MiddleLeft;
|
TabText.alignment = TextAnchor.MiddleLeft;
|
||||||
TabText.fontSize = 12;
|
TabText.fontSize = 12;
|
||||||
TabText.horizontalOverflow = HorizontalWrapMode.Overflow;
|
TabText.horizontalOverflow = HorizontalWrapMode.Overflow;
|
||||||
|
@ -12,6 +12,8 @@ using UnityExplorer.UI;
|
|||||||
using UnityExplorer.UI.Panels;
|
using UnityExplorer.UI.Panels;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
using UnityExplorer.Config;
|
||||||
|
|
||||||
namespace UnityExplorer.Inspectors
|
namespace UnityExplorer.Inspectors
|
||||||
{
|
{
|
||||||
@ -21,9 +23,9 @@ namespace UnityExplorer.Inspectors
|
|||||||
UI
|
UI
|
||||||
}
|
}
|
||||||
|
|
||||||
public class InspectUnderMouse : UIPanel
|
public class MouseInspector : UIPanel
|
||||||
{
|
{
|
||||||
public static InspectUnderMouse Instance { get; private set; }
|
public static MouseInspector Instance { get; private set; }
|
||||||
|
|
||||||
private readonly WorldInspector worldInspector;
|
private readonly WorldInspector worldInspector;
|
||||||
private readonly UiInspector uiInspector;
|
private readonly UiInspector uiInspector;
|
||||||
@ -31,24 +33,19 @@ namespace UnityExplorer.Inspectors
|
|||||||
public static bool Inspecting { get; set; }
|
public static bool Inspecting { get; set; }
|
||||||
public static MouseInspectMode Mode { get; set; }
|
public static MouseInspectMode Mode { get; set; }
|
||||||
|
|
||||||
|
public MouseInspectorBase CurrentInspector => Mode switch
|
||||||
|
{
|
||||||
|
MouseInspectMode.UI => uiInspector,
|
||||||
|
MouseInspectMode.World => worldInspector,
|
||||||
|
_ => null,
|
||||||
|
};
|
||||||
|
|
||||||
private static Vector3 lastMousePos;
|
private static Vector3 lastMousePos;
|
||||||
|
|
||||||
public MouseInspectorBase CurrentInspector
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
switch (Mode)
|
|
||||||
{
|
|
||||||
case MouseInspectMode.UI:
|
|
||||||
return uiInspector;
|
|
||||||
case MouseInspectMode.World:
|
|
||||||
return worldInspector;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// UIPanel
|
// UIPanel
|
||||||
|
internal static readonly string UIBaseGUID = $"{ExplorerCore.GUID}.MouseInspector";
|
||||||
|
private UIBase inspectorUIBase;
|
||||||
|
|
||||||
public override string Name => "Inspect Under Mouse";
|
public override string Name => "Inspect Under Mouse";
|
||||||
public override UIManager.Panels PanelType => UIManager.Panels.MouseInspector;
|
public override UIManager.Panels PanelType => UIManager.Panels.MouseInspector;
|
||||||
public override int MinWidth => -1;
|
public override int MinWidth => -1;
|
||||||
@ -62,7 +59,7 @@ namespace UnityExplorer.Inspectors
|
|||||||
internal Text objPathLabel;
|
internal Text objPathLabel;
|
||||||
internal Text mousePosLabel;
|
internal Text mousePosLabel;
|
||||||
|
|
||||||
public InspectUnderMouse()
|
public MouseInspector()
|
||||||
{
|
{
|
||||||
Instance = this;
|
Instance = this;
|
||||||
worldInspector = new WorldInspector();
|
worldInspector = new WorldInspector();
|
||||||
@ -120,6 +117,26 @@ namespace UnityExplorer.Inspectors
|
|||||||
|
|
||||||
private static float timeOfLastRaycast;
|
private static float timeOfLastRaycast;
|
||||||
|
|
||||||
|
public bool TryUpdate()
|
||||||
|
{
|
||||||
|
if (ConfigManager.World_MouseInspect_Keybind.Value != KeyCode.None)
|
||||||
|
{
|
||||||
|
if (InputManager.GetKeyDown(ConfigManager.World_MouseInspect_Keybind.Value))
|
||||||
|
Instance.StartInspect(MouseInspectMode.World);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ConfigManager.World_MouseInspect_Keybind.Value != KeyCode.None)
|
||||||
|
{
|
||||||
|
if (InputManager.GetKeyDown(ConfigManager.World_MouseInspect_Keybind.Value))
|
||||||
|
Instance.StartInspect(MouseInspectMode.World);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Inspecting)
|
||||||
|
UpdateInspect();
|
||||||
|
|
||||||
|
return Inspecting;
|
||||||
|
}
|
||||||
|
|
||||||
public void UpdateInspect()
|
public void UpdateInspect()
|
||||||
{
|
{
|
||||||
if (InputManager.GetKeyDown(KeyCode.Escape))
|
if (InputManager.GetKeyDown(KeyCode.Escape))
|
||||||
@ -164,7 +181,7 @@ namespace UnityExplorer.Inspectors
|
|||||||
mousePos.y -= 10;
|
mousePos.y -= 10;
|
||||||
|
|
||||||
// calculate and set our UI position
|
// calculate and set our UI position
|
||||||
var inversePos = UIManager.UIRoot.transform.InverseTransformPoint(mousePos);
|
var inversePos = inspectorUIBase.RootObject.transform.InverseTransformPoint(mousePos);
|
||||||
UIRoot.transform.localPosition = new Vector3(inversePos.x, inversePos.y, 0);
|
UIRoot.transform.localPosition = new Vector3(inversePos.x, inversePos.y, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -181,10 +198,10 @@ namespace UnityExplorer.Inspectors
|
|||||||
public override void ConstructPanelContent()
|
public override void ConstructPanelContent()
|
||||||
{
|
{
|
||||||
// hide title bar
|
// hide title bar
|
||||||
this.titleBar.SetActive(false);
|
this.TitleBar.SetActive(false);
|
||||||
this.UIRoot.transform.SetParent(UIManager.UIRoot.transform, false);
|
this.UIRoot.transform.SetParent(UIManager.UIRoot.transform, false);
|
||||||
|
|
||||||
var inspectContent = UIFactory.CreateVerticalGroup(this.content, "InspectContent", true, true, true, true, 3, new Vector4(2, 2, 2, 2));
|
var inspectContent = UIFactory.CreateVerticalGroup(this.uiContent, "InspectContent", true, true, true, true, 3, new Vector4(2, 2, 2, 2));
|
||||||
UIFactory.SetLayoutElement(inspectContent, flexibleWidth: 9999, flexibleHeight: 9999);
|
UIFactory.SetLayoutElement(inspectContent, flexibleWidth: 9999, flexibleHeight: 9999);
|
||||||
|
|
||||||
// Title text
|
// Title text
|
||||||
@ -207,10 +224,12 @@ namespace UnityExplorer.Inspectors
|
|||||||
UIFactory.SetLayoutElement(objPathLabel.gameObject, minHeight: 75);
|
UIFactory.SetLayoutElement(objPathLabel.gameObject, minHeight: 75);
|
||||||
|
|
||||||
UIRoot.SetActive(false);
|
UIRoot.SetActive(false);
|
||||||
|
|
||||||
|
// Create a new canvas for this panel to live on.
|
||||||
|
// It needs to always be shown on the main display, other panels can move displays.
|
||||||
|
|
||||||
|
inspectorUIBase = UniversalUI.RegisterUI(UIBaseGUID, null);
|
||||||
|
UIRoot.transform.SetParent(inspectorUIBase.RootObject.transform);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void DoSaveToConfigElement() { }
|
|
||||||
|
|
||||||
public override string GetSaveDataFromConfigManager() => null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
@ -8,6 +9,7 @@ using UnityEngine.UI;
|
|||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
using UnityExplorer.UI.Panels;
|
using UnityExplorer.UI.Panels;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
|
using UniverseLib.Input;
|
||||||
|
|
||||||
namespace UnityExplorer.Inspectors.MouseInspectors
|
namespace UnityExplorer.Inspectors.MouseInspectors
|
||||||
{
|
{
|
||||||
@ -26,7 +28,7 @@ namespace UnityExplorer.Inspectors.MouseInspectors
|
|||||||
public override void OnBeginMouseInspect()
|
public override void OnBeginMouseInspect()
|
||||||
{
|
{
|
||||||
SetupUIRaycast();
|
SetupUIRaycast();
|
||||||
InspectUnderMouse.Instance.objPathLabel.text = "";
|
MouseInspector.Instance.objPathLabel.text = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void ClearHitData()
|
public override void ClearHitData()
|
||||||
@ -38,6 +40,12 @@ namespace UnityExplorer.Inspectors.MouseInspectors
|
|||||||
{
|
{
|
||||||
LastHitObjects.Clear();
|
LastHitObjects.Clear();
|
||||||
LastHitObjects.AddRange(currentHitObjects);
|
LastHitObjects.AddRange(currentHitObjects);
|
||||||
|
RuntimeHelper.StartCoroutine(SetPanelActiveCoro());
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerator SetPanelActiveCoro()
|
||||||
|
{
|
||||||
|
yield return null;
|
||||||
var panel = UIManager.GetPanel<UiInspectorResultsPanel>(UIManager.Panels.UIInspectorResults);
|
var panel = UIManager.GetPanel<UiInspectorResultsPanel>(UIManager.Panels.UIInspectorResults);
|
||||||
panel.SetActive(true);
|
panel.SetActive(true);
|
||||||
panel.ShowResults();
|
panel.ShowResults();
|
||||||
@ -58,7 +66,7 @@ namespace UnityExplorer.Inspectors.MouseInspectors
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
var list = new List<RaycastResult>();
|
var list = new List<RaycastResult>();
|
||||||
RuntimeProvider.Instance.GraphicRaycast(gr, ped, list);
|
RuntimeHelper.GraphicRaycast(gr, ped, list);
|
||||||
if (list.Count > 0)
|
if (list.Count > 0)
|
||||||
{
|
{
|
||||||
foreach (var hit in list)
|
foreach (var hit in list)
|
||||||
@ -70,14 +78,14 @@ namespace UnityExplorer.Inspectors.MouseInspectors
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (currentHitObjects.Any())
|
if (currentHitObjects.Any())
|
||||||
InspectUnderMouse.Instance.objNameLabel.text = $"Click to view UI Objects under mouse: {currentHitObjects.Count}";
|
MouseInspector.Instance.objNameLabel.text = $"Click to view UI Objects under mouse: {currentHitObjects.Count}";
|
||||||
else
|
else
|
||||||
InspectUnderMouse.Instance.objNameLabel.text = $"No UI objects under mouse.";
|
MouseInspector.Instance.objNameLabel.text = $"No UI objects under mouse.";
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void SetupUIRaycast()
|
private static void SetupUIRaycast()
|
||||||
{
|
{
|
||||||
foreach (var obj in RuntimeProvider.Instance.FindObjectsOfTypeAll(typeof(Canvas)))
|
foreach (var obj in RuntimeHelper.FindObjectsOfTypeAll(typeof(Canvas)))
|
||||||
{
|
{
|
||||||
var canvas = obj.TryCast<Canvas>();
|
var canvas = obj.TryCast<Canvas>();
|
||||||
if (!canvas || !canvas.enabled || !canvas.gameObject.activeInHierarchy)
|
if (!canvas || !canvas.enabled || !canvas.gameObject.activeInHierarchy)
|
||||||
@ -91,7 +99,7 @@ namespace UnityExplorer.Inspectors.MouseInspectors
|
|||||||
}
|
}
|
||||||
|
|
||||||
// recache Graphic Raycasters each time we start
|
// recache Graphic Raycasters each time we start
|
||||||
var casters = RuntimeProvider.Instance.FindObjectsOfTypeAll(typeof(GraphicRaycaster));
|
var casters = RuntimeHelper.FindObjectsOfTypeAll(typeof(GraphicRaycaster));
|
||||||
graphicRaycasters = new GraphicRaycaster[casters.Length];
|
graphicRaycasters = new GraphicRaycaster[casters.Length];
|
||||||
for (int i = 0; i < casters.Length; i++)
|
for (int i = 0; i < casters.Length; i++)
|
||||||
{
|
{
|
||||||
@ -99,7 +107,7 @@ namespace UnityExplorer.Inspectors.MouseInspectors
|
|||||||
}
|
}
|
||||||
|
|
||||||
// enable raycastTarget on Graphics
|
// enable raycastTarget on Graphics
|
||||||
foreach (var obj in RuntimeProvider.Instance.FindObjectsOfTypeAll(typeof(Graphic)))
|
foreach (var obj in RuntimeHelper.FindObjectsOfTypeAll(typeof(Graphic)))
|
||||||
{
|
{
|
||||||
var graphic = obj.TryCast<Graphic>();
|
var graphic = obj.TryCast<Graphic>();
|
||||||
if (!graphic || !graphic.enabled || graphic.raycastTarget || !graphic.gameObject.activeInHierarchy)
|
if (!graphic || !graphic.enabled || graphic.raycastTarget || !graphic.gameObject.activeInHierarchy)
|
||||||
@ -110,7 +118,7 @@ namespace UnityExplorer.Inspectors.MouseInspectors
|
|||||||
}
|
}
|
||||||
|
|
||||||
// enable blocksRaycasts on CanvasGroups
|
// enable blocksRaycasts on CanvasGroups
|
||||||
foreach (var obj in RuntimeProvider.Instance.FindObjectsOfTypeAll(typeof(CanvasGroup)))
|
foreach (var obj in RuntimeHelper.FindObjectsOfTypeAll(typeof(CanvasGroup)))
|
||||||
{
|
{
|
||||||
var canvas = obj.TryCast<CanvasGroup>();
|
var canvas = obj.TryCast<CanvasGroup>();
|
||||||
if (!canvas || !canvas.gameObject.activeInHierarchy || canvas.blocksRaycasts)
|
if (!canvas || !canvas.gameObject.activeInHierarchy || canvas.blocksRaycasts)
|
||||||
|
@ -4,6 +4,7 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.Inspectors.MouseInspectors
|
namespace UnityExplorer.Inspectors.MouseInspectors
|
||||||
{
|
{
|
||||||
@ -40,7 +41,7 @@ namespace UnityExplorer.Inspectors.MouseInspectors
|
|||||||
if (!MainCamera)
|
if (!MainCamera)
|
||||||
{
|
{
|
||||||
ExplorerCore.LogWarning("No Main Camera was found, unable to inspect world!");
|
ExplorerCore.LogWarning("No Main Camera was found, unable to inspect world!");
|
||||||
InspectUnderMouse.Instance.StopInspect();
|
MouseInspector.Instance.StopInspect();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,7 +51,7 @@ namespace UnityExplorer.Inspectors.MouseInspectors
|
|||||||
if (hit.transform)
|
if (hit.transform)
|
||||||
OnHitGameObject(hit.transform.gameObject);
|
OnHitGameObject(hit.transform.gameObject);
|
||||||
else if (lastHitObject)
|
else if (lastHitObject)
|
||||||
InspectUnderMouse.Instance.ClearHitData();
|
MouseInspector.Instance.ClearHitData();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void OnHitGameObject(GameObject obj)
|
internal void OnHitGameObject(GameObject obj)
|
||||||
@ -58,8 +59,8 @@ namespace UnityExplorer.Inspectors.MouseInspectors
|
|||||||
if (obj != lastHitObject)
|
if (obj != lastHitObject)
|
||||||
{
|
{
|
||||||
lastHitObject = obj;
|
lastHitObject = obj;
|
||||||
InspectUnderMouse.Instance.objNameLabel.text = $"<b>Click to Inspect:</b> <color=cyan>{obj.name}</color>";
|
MouseInspector.Instance.objNameLabel.text = $"<b>Click to Inspect:</b> <color=cyan>{obj.name}</color>";
|
||||||
InspectUnderMouse.Instance.objPathLabel.text = $"Path: {obj.transform.GetTransformPath(true)}";
|
MouseInspector.Instance.objPathLabel.text = $"Path: {obj.transform.GetTransformPath(true)}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,26 +2,34 @@
|
|||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Reflection.Emit;
|
using System.Reflection.Emit;
|
||||||
using System.Text;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.Config;
|
|
||||||
using UnityExplorer.Runtime;
|
|
||||||
using UnityExplorer.CacheObject;
|
using UnityExplorer.CacheObject;
|
||||||
using UnityExplorer.CacheObject.Views;
|
using UnityExplorer.CacheObject.Views;
|
||||||
using UnityExplorer.UI.Panels;
|
using UnityExplorer.UI.Panels;
|
||||||
using UnityExplorer.UI.Widgets;
|
using UnityExplorer.UI.Widgets;
|
||||||
using UnityExplorer.UI;
|
|
||||||
using UniverseLib.UI.Widgets;
|
|
||||||
using UniverseLib.UI;
|
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
using UniverseLib.Runtime;
|
using UniverseLib.UI;
|
||||||
|
using UniverseLib.UI.Models;
|
||||||
|
using UniverseLib.UI.ObjectPool;
|
||||||
|
using UniverseLib.UI.Widgets.ScrollView;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.Inspectors
|
namespace UnityExplorer.Inspectors
|
||||||
{
|
{
|
||||||
|
[Flags]
|
||||||
|
public enum MemberFilter
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
Property = 1,
|
||||||
|
Field = 2,
|
||||||
|
Constructor = 4,
|
||||||
|
Method = 8,
|
||||||
|
All = Property | Field | Method | Constructor,
|
||||||
|
}
|
||||||
|
|
||||||
public class ReflectionInspector : InspectorBase, ICellPoolDataSource<CacheMemberCell>, ICacheObjectController
|
public class ReflectionInspector : InspectorBase, ICellPoolDataSource<CacheMemberCell>, ICacheObjectController
|
||||||
{
|
{
|
||||||
public CacheObjectBase ParentCacheObject { get; set; }
|
public CacheObjectBase ParentCacheObject { get; set; }
|
||||||
@ -29,43 +37,52 @@ namespace UnityExplorer.Inspectors
|
|||||||
public bool StaticOnly { get; internal set; }
|
public bool StaticOnly { get; internal set; }
|
||||||
public bool CanWrite => true;
|
public bool CanWrite => true;
|
||||||
|
|
||||||
private List<CacheMember> members = new List<CacheMember>();
|
|
||||||
private readonly List<CacheMember> filteredMembers = new List<CacheMember>();
|
|
||||||
|
|
||||||
public bool AutoUpdateWanted => autoUpdateToggle.isOn;
|
public bool AutoUpdateWanted => autoUpdateToggle.isOn;
|
||||||
|
|
||||||
private BindingFlags FlagsFilter;
|
private List<CacheMember> members = new();
|
||||||
private string NameFilter;
|
private readonly List<CacheMember> filteredMembers = new();
|
||||||
|
|
||||||
private MemberFlags MemberFilter = MemberFlags.All;
|
private BindingFlags scopeFlagsFilter;
|
||||||
private enum MemberFlags
|
private string nameFilter;
|
||||||
{
|
|
||||||
None = 0,
|
private MemberFilter MemberFilter = MemberFilter.All;
|
||||||
Property = 1,
|
|
||||||
Field = 2,
|
// Updating
|
||||||
Method = 4,
|
|
||||||
All = 7
|
private bool refreshWanted;
|
||||||
}
|
private string lastNameFilter;
|
||||||
|
private BindingFlags lastFlagsFilter;
|
||||||
|
private MemberFilter lastMemberFilter = MemberFilter.All;
|
||||||
|
private float timeOfLastAutoUpdate;
|
||||||
|
|
||||||
// UI
|
// UI
|
||||||
|
|
||||||
|
internal GameObject mainContentHolder;
|
||||||
|
private static int LeftGroupWidth { get; set; }
|
||||||
|
private static int RightGroupWidth { get; set; }
|
||||||
|
|
||||||
public ScrollPool<CacheMemberCell> MemberScrollPool { get; private set; }
|
public ScrollPool<CacheMemberCell> MemberScrollPool { get; private set; }
|
||||||
|
public int ItemCount => filteredMembers.Count;
|
||||||
|
|
||||||
|
public UnityObjectWidget UnityWidget;
|
||||||
|
|
||||||
public InputFieldRef HiddenNameText;
|
public InputFieldRef HiddenNameText;
|
||||||
public Text NameText;
|
public Text NameText;
|
||||||
public Text AssemblyText;
|
public Text AssemblyText;
|
||||||
private Toggle autoUpdateToggle;
|
private Toggle autoUpdateToggle;
|
||||||
|
|
||||||
private string currentBaseTabText;
|
internal string currentBaseTabText;
|
||||||
|
|
||||||
private readonly Color disabledButtonColor = new Color(0.24f, 0.24f, 0.24f);
|
private readonly Dictionary<BindingFlags, ButtonRef> scopeFilterButtons = new();
|
||||||
private readonly Color enabledButtonColor = new Color(0.2f, 0.27f, 0.2f);
|
private readonly List<Toggle> memberTypeToggles = new();
|
||||||
|
|
||||||
private readonly Dictionary<BindingFlags, ButtonRef> scopeFilterButtons = new Dictionary<BindingFlags, ButtonRef>();
|
|
||||||
private readonly List<Toggle> memberTypeToggles = new List<Toggle>();
|
|
||||||
private InputFieldRef filterInputField;
|
private InputFieldRef filterInputField;
|
||||||
|
|
||||||
// Setup / return
|
// const
|
||||||
|
|
||||||
|
private readonly Color disabledButtonColor = new(0.24f, 0.24f, 0.24f);
|
||||||
|
private readonly Color enabledButtonColor = new(0.2f, 0.27f, 0.2f);
|
||||||
|
|
||||||
|
// Setup
|
||||||
|
|
||||||
public override void OnBorrowedFromPool(object target)
|
public override void OnBorrowedFromPool(object target)
|
||||||
{
|
{
|
||||||
@ -74,7 +91,7 @@ namespace UnityExplorer.Inspectors
|
|||||||
|
|
||||||
SetTarget(target);
|
SetTarget(target);
|
||||||
|
|
||||||
RuntimeProvider.Instance.StartCoroutine(InitCoroutine());
|
RuntimeHelper.StartCoroutine(InitCoroutine());
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerator InitCoroutine()
|
private IEnumerator InitCoroutine()
|
||||||
@ -101,10 +118,12 @@ namespace UnityExplorer.Inspectors
|
|||||||
|
|
||||||
autoUpdateToggle.isOn = false;
|
autoUpdateToggle.isOn = false;
|
||||||
|
|
||||||
UnityObjectRef = null;
|
if (UnityWidget != null)
|
||||||
ComponentRef = null;
|
{
|
||||||
TextureRef = null;
|
UnityWidget.OnReturnToPool();
|
||||||
CleanupTextureViewer();
|
Pool.Return(UnityWidget.GetType(), UnityWidget);
|
||||||
|
this.UnityWidget = null;
|
||||||
|
}
|
||||||
|
|
||||||
base.OnReturnToPool();
|
base.OnReturnToPool();
|
||||||
}
|
}
|
||||||
@ -130,7 +149,7 @@ namespace UnityExplorer.Inspectors
|
|||||||
currentBaseTabText = $"{prefix} {SignatureHighlighter.Parse(TargetType, false)}";
|
currentBaseTabText = $"{prefix} {SignatureHighlighter.Parse(TargetType, false)}";
|
||||||
Tab.TabText.text = currentBaseTabText;
|
Tab.TabText.text = currentBaseTabText;
|
||||||
NameText.text = SignatureHighlighter.Parse(TargetType, true);
|
NameText.text = SignatureHighlighter.Parse(TargetType, true);
|
||||||
HiddenNameText.Text = TargetType.FullName;
|
HiddenNameText.Text = SignatureHighlighter.RemoveHighlighting(NameText.text);
|
||||||
|
|
||||||
string asmText;
|
string asmText;
|
||||||
if (TargetType.Assembly is AssemblyBuilder || string.IsNullOrEmpty(TargetType.Assembly.Location))
|
if (TargetType.Assembly is AssemblyBuilder || string.IsNullOrEmpty(TargetType.Assembly.Location))
|
||||||
@ -139,18 +158,20 @@ namespace UnityExplorer.Inspectors
|
|||||||
asmText = Path.GetFileName(TargetType.Assembly.Location);
|
asmText = Path.GetFileName(TargetType.Assembly.Location);
|
||||||
AssemblyText.text = $"<color=grey>Assembly:</color> {asmText}";
|
AssemblyText.text = $"<color=grey>Assembly:</color> {asmText}";
|
||||||
|
|
||||||
// unity helpers
|
// Unity object helper widget
|
||||||
SetUnityTargets();
|
|
||||||
|
if (!StaticOnly)
|
||||||
|
this.UnityWidget = UnityObjectWidget.GetUnityWidget(target, TargetType, this);
|
||||||
|
|
||||||
// Get cache members
|
// Get cache members
|
||||||
|
|
||||||
this.members = CacheMember.GetCacheMembers(Target, TargetType, this);
|
this.members = CacheMemberFactory.GetCacheMembers(TargetType, this);
|
||||||
|
|
||||||
// reset filters
|
// reset filters
|
||||||
|
|
||||||
this.filterInputField.Text = "";
|
this.filterInputField.Text = string.Empty;
|
||||||
|
|
||||||
SetFilter("", StaticOnly ? BindingFlags.Static : BindingFlags.Instance);
|
SetFilter(string.Empty, StaticOnly ? BindingFlags.Static : BindingFlags.Default);
|
||||||
scopeFilterButtons[BindingFlags.Default].Component.gameObject.SetActive(!StaticOnly);
|
scopeFilterButtons[BindingFlags.Default].Component.gameObject.SetActive(!StaticOnly);
|
||||||
scopeFilterButtons[BindingFlags.Instance].Component.gameObject.SetActive(!StaticOnly);
|
scopeFilterButtons[BindingFlags.Instance].Component.gameObject.SetActive(!StaticOnly);
|
||||||
|
|
||||||
@ -162,12 +183,6 @@ namespace UnityExplorer.Inspectors
|
|||||||
|
|
||||||
// Updating
|
// Updating
|
||||||
|
|
||||||
private bool refreshWanted;
|
|
||||||
private string lastNameFilter;
|
|
||||||
private BindingFlags lastFlagsFilter;
|
|
||||||
private MemberFlags lastMemberFilter = MemberFlags.All;
|
|
||||||
private float timeOfLastAutoUpdate;
|
|
||||||
|
|
||||||
public override void Update()
|
public override void Update()
|
||||||
{
|
{
|
||||||
if (!this.IsActive)
|
if (!this.IsActive)
|
||||||
@ -180,10 +195,10 @@ namespace UnityExplorer.Inspectors
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check filter changes or force-refresh
|
// check filter changes or force-refresh
|
||||||
if (refreshWanted || NameFilter != lastNameFilter || FlagsFilter != lastFlagsFilter || lastMemberFilter != MemberFilter)
|
if (refreshWanted || nameFilter != lastNameFilter || scopeFlagsFilter != lastFlagsFilter || lastMemberFilter != MemberFilter)
|
||||||
{
|
{
|
||||||
lastNameFilter = NameFilter;
|
lastNameFilter = nameFilter;
|
||||||
lastFlagsFilter = FlagsFilter;
|
lastFlagsFilter = scopeFlagsFilter;
|
||||||
lastMemberFilter = MemberFilter;
|
lastMemberFilter = MemberFilter;
|
||||||
|
|
||||||
FilterMembers();
|
FilterMembers();
|
||||||
@ -196,11 +211,8 @@ namespace UnityExplorer.Inspectors
|
|||||||
{
|
{
|
||||||
timeOfLastAutoUpdate = Time.realtimeSinceStartup;
|
timeOfLastAutoUpdate = Time.realtimeSinceStartup;
|
||||||
|
|
||||||
if (this.UnityObjectRef)
|
if (this.UnityWidget != null)
|
||||||
{
|
UnityWidget.Update();
|
||||||
nameInput.Text = UnityObjectRef.name;
|
|
||||||
this.Tab.TabText.text = $"{currentBaseTabText} \"{UnityObjectRef.name}\"";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (AutoUpdateWanted)
|
if (AutoUpdateWanted)
|
||||||
UpdateDisplayedMembers();
|
UpdateDisplayedMembers();
|
||||||
@ -214,26 +226,26 @@ namespace UnityExplorer.Inspectors
|
|||||||
|
|
||||||
// Filtering
|
// Filtering
|
||||||
|
|
||||||
public void SetFilter(string filter) => SetFilter(filter, FlagsFilter);
|
public void SetFilter(string name) => SetFilter(name, scopeFlagsFilter);
|
||||||
|
|
||||||
public void SetFilter(BindingFlags flagsFilter) => SetFilter(NameFilter, flagsFilter);
|
public void SetFilter(BindingFlags flags) => SetFilter(nameFilter, flags);
|
||||||
|
|
||||||
public void SetFilter(string nameFilter, BindingFlags flagsFilter)
|
public void SetFilter(string name, BindingFlags flags)
|
||||||
{
|
{
|
||||||
this.NameFilter = nameFilter;
|
this.nameFilter = name;
|
||||||
|
|
||||||
if (flagsFilter != FlagsFilter)
|
if (flags != scopeFlagsFilter)
|
||||||
{
|
{
|
||||||
var btn = scopeFilterButtons[FlagsFilter].Component;
|
var btn = scopeFilterButtons[scopeFlagsFilter].Component;
|
||||||
RuntimeProvider.Instance.SetColorBlock(btn, disabledButtonColor, disabledButtonColor * 1.3f);
|
RuntimeHelper.SetColorBlock(btn, disabledButtonColor, disabledButtonColor * 1.3f);
|
||||||
|
|
||||||
this.FlagsFilter = flagsFilter;
|
this.scopeFlagsFilter = flags;
|
||||||
btn = scopeFilterButtons[FlagsFilter].Component;
|
btn = scopeFilterButtons[scopeFlagsFilter].Component;
|
||||||
RuntimeProvider.Instance.SetColorBlock(btn, enabledButtonColor, enabledButtonColor * 1.3f);
|
RuntimeHelper.SetColorBlock(btn, enabledButtonColor, enabledButtonColor * 1.3f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnMemberTypeToggled(MemberFlags flag, bool val)
|
private void OnMemberTypeToggled(MemberFilter flag, bool val)
|
||||||
{
|
{
|
||||||
if (!val)
|
if (!val)
|
||||||
MemberFilter &= ~flag;
|
MemberFilter &= ~flag;
|
||||||
@ -249,19 +261,20 @@ namespace UnityExplorer.Inspectors
|
|||||||
{
|
{
|
||||||
var member = members[i];
|
var member = members[i];
|
||||||
|
|
||||||
if (FlagsFilter != BindingFlags.Default)
|
if (scopeFlagsFilter != BindingFlags.Default)
|
||||||
{
|
{
|
||||||
if (FlagsFilter == BindingFlags.Instance && member.IsStatic
|
if (scopeFlagsFilter == BindingFlags.Instance && member.IsStatic
|
||||||
|| FlagsFilter == BindingFlags.Static && !member.IsStatic)
|
|| scopeFlagsFilter == BindingFlags.Static && !member.IsStatic)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((member is CacheMethod && !MemberFilter.HasFlag(MemberFlags.Method))
|
if ((member is CacheMethod && !MemberFilter.HasFlag(MemberFilter.Method))
|
||||||
|| (member is CacheField && !MemberFilter.HasFlag(MemberFlags.Field))
|
|| (member is CacheField && !MemberFilter.HasFlag(MemberFilter.Field))
|
||||||
|| (member is CacheProperty && !MemberFilter.HasFlag(MemberFlags.Property)))
|
|| (member is CacheProperty && !MemberFilter.HasFlag(MemberFilter.Property))
|
||||||
|
|| (member is CacheConstructor && !MemberFilter.HasFlag(MemberFilter.Constructor)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(NameFilter) && !member.NameForFiltering.ContainsIgnoreCase(NameFilter))
|
if (!string.IsNullOrEmpty(nameFilter) && !member.NameForFiltering.ContainsIgnoreCase(nameFilter))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
filteredMembers.Add(member);
|
filteredMembers.Add(member);
|
||||||
@ -290,8 +303,6 @@ namespace UnityExplorer.Inspectors
|
|||||||
|
|
||||||
// Member cells
|
// Member cells
|
||||||
|
|
||||||
public int ItemCount => filteredMembers.Count;
|
|
||||||
|
|
||||||
public void OnCellBorrowed(CacheMemberCell cell) { } // not needed
|
public void OnCellBorrowed(CacheMemberCell cell) { } // not needed
|
||||||
|
|
||||||
public void SetCell(CacheMemberCell cell, int index)
|
public void SetCell(CacheMemberCell cell, int index)
|
||||||
@ -301,9 +312,6 @@ namespace UnityExplorer.Inspectors
|
|||||||
|
|
||||||
// Cell layout (fake table alignment)
|
// Cell layout (fake table alignment)
|
||||||
|
|
||||||
private static int LeftGroupWidth { get; set; }
|
|
||||||
private static int RightGroupWidth { get; set; }
|
|
||||||
|
|
||||||
internal void SetLayouts()
|
internal void SetLayouts()
|
||||||
{
|
{
|
||||||
CalculateLayouts();
|
CalculateLayouts();
|
||||||
@ -334,8 +342,6 @@ namespace UnityExplorer.Inspectors
|
|||||||
|
|
||||||
// UI Construction
|
// UI Construction
|
||||||
|
|
||||||
private GameObject mainContentHolder;
|
|
||||||
|
|
||||||
public override GameObject CreateContent(GameObject parent)
|
public override GameObject CreateContent(GameObject parent)
|
||||||
{
|
{
|
||||||
UIRoot = UIFactory.CreateVerticalGroup(parent, "ReflectionInspector", true, true, true, true, 5,
|
UIRoot = UIFactory.CreateVerticalGroup(parent, "ReflectionInspector", true, true, true, true, 5,
|
||||||
@ -376,8 +382,6 @@ namespace UnityExplorer.Inspectors
|
|||||||
AssemblyText = UIFactory.CreateLabel(UIRoot, "AssemblyLabel", "not set", TextAnchor.MiddleLeft);
|
AssemblyText = UIFactory.CreateLabel(UIRoot, "AssemblyLabel", "not set", TextAnchor.MiddleLeft);
|
||||||
UIFactory.SetLayoutElement(AssemblyText.gameObject, minHeight: 25, flexibleWidth: 9999);
|
UIFactory.SetLayoutElement(AssemblyText.gameObject, minHeight: 25, flexibleWidth: 9999);
|
||||||
|
|
||||||
ConstructUnityObjectRow();
|
|
||||||
|
|
||||||
mainContentHolder = UIFactory.CreateVerticalGroup(UIRoot, "MemberHolder", false, false, true, true, 5, new Vector4(2, 2, 2, 2),
|
mainContentHolder = UIFactory.CreateVerticalGroup(UIRoot, "MemberHolder", false, false, true, true, 5, new Vector4(2, 2, 2, 2),
|
||||||
new Color(0.12f, 0.12f, 0.12f));
|
new Color(0.12f, 0.12f, 0.12f));
|
||||||
UIFactory.SetLayoutElement(mainContentHolder, flexibleWidth: 9999, flexibleHeight: 9999);
|
UIFactory.SetLayoutElement(mainContentHolder, flexibleWidth: 9999, flexibleHeight: 9999);
|
||||||
@ -459,6 +463,7 @@ namespace UnityExplorer.Inspectors
|
|||||||
AddMemberTypeToggle(rowObj, MemberTypes.Property, 90);
|
AddMemberTypeToggle(rowObj, MemberTypes.Property, 90);
|
||||||
AddMemberTypeToggle(rowObj, MemberTypes.Field, 70);
|
AddMemberTypeToggle(rowObj, MemberTypes.Field, 70);
|
||||||
AddMemberTypeToggle(rowObj, MemberTypes.Method, 90);
|
AddMemberTypeToggle(rowObj, MemberTypes.Method, 90);
|
||||||
|
AddMemberTypeToggle(rowObj, MemberTypes.Constructor, 110);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddScopeFilterButton(GameObject parent, BindingFlags flags, bool setAsActive = false)
|
private void AddScopeFilterButton(GameObject parent, BindingFlags flags, bool setAsActive = false)
|
||||||
@ -477,255 +482,30 @@ namespace UnityExplorer.Inspectors
|
|||||||
{
|
{
|
||||||
var toggleObj = UIFactory.CreateToggle(parent, "Toggle_" + type, out Toggle toggle, out Text toggleText);
|
var toggleObj = UIFactory.CreateToggle(parent, "Toggle_" + type, out Toggle toggle, out Text toggleText);
|
||||||
UIFactory.SetLayoutElement(toggleObj, minHeight: 25, minWidth: width);
|
UIFactory.SetLayoutElement(toggleObj, minHeight: 25, minWidth: width);
|
||||||
var color = SignatureHighlighter.GetMemberInfoColor(type);
|
string color = type switch
|
||||||
|
{
|
||||||
|
MemberTypes.Method => SignatureHighlighter.METHOD_INSTANCE,
|
||||||
|
MemberTypes.Field => SignatureHighlighter.FIELD_INSTANCE,
|
||||||
|
MemberTypes.Property => SignatureHighlighter.PROP_INSTANCE,
|
||||||
|
MemberTypes.Constructor => SignatureHighlighter.CLASS_INSTANCE,
|
||||||
|
_ => throw new NotImplementedException()
|
||||||
|
};
|
||||||
toggleText.text = $"<color={color}>{type}</color>";
|
toggleText.text = $"<color={color}>{type}</color>";
|
||||||
|
|
||||||
toggle.graphic.TryCast<Image>().color = color.ToColor() * 0.65f;
|
toggle.graphic.TryCast<Image>().color = color.ToColor() * 0.65f;
|
||||||
|
|
||||||
MemberFlags flag;
|
MemberFilter flag = type switch
|
||||||
switch (type)
|
|
||||||
{
|
{
|
||||||
case MemberTypes.Method: flag = MemberFlags.Method; break;
|
MemberTypes.Method => MemberFilter.Method,
|
||||||
case MemberTypes.Property: flag = MemberFlags.Property; break;
|
MemberTypes.Property => MemberFilter.Property,
|
||||||
case MemberTypes.Field: flag = MemberFlags.Field; break;
|
MemberTypes.Field => MemberFilter.Field,
|
||||||
default: return;
|
MemberTypes.Constructor => MemberFilter.Constructor,
|
||||||
}
|
_ => throw new NotImplementedException()
|
||||||
|
};
|
||||||
|
|
||||||
toggle.onValueChanged.AddListener((bool val) => { OnMemberTypeToggled(flag, val); });
|
toggle.onValueChanged.AddListener((bool val) => { OnMemberTypeToggled(flag, val); });
|
||||||
|
|
||||||
memberTypeToggles.Add(toggle);
|
memberTypeToggles.Add(toggle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Todo should probably put this in a separate class or maybe as a widget
|
|
||||||
|
|
||||||
#region UNITY OBJECT SPECIFIC
|
|
||||||
|
|
||||||
// Unity object helpers
|
|
||||||
|
|
||||||
private UnityEngine.Object UnityObjectRef;
|
|
||||||
private Component ComponentRef;
|
|
||||||
private Texture2D TextureRef;
|
|
||||||
private bool TextureViewerWanted;
|
|
||||||
private GameObject unityObjectRow;
|
|
||||||
private ButtonRef gameObjectButton;
|
|
||||||
private InputFieldRef nameInput;
|
|
||||||
private InputFieldRef instanceIdInput;
|
|
||||||
private ButtonRef textureButton;
|
|
||||||
private GameObject textureViewer;
|
|
||||||
|
|
||||||
private void SetUnityTargets()
|
|
||||||
{
|
|
||||||
if (StaticOnly || !typeof(UnityEngine.Object).IsAssignableFrom(TargetType))
|
|
||||||
{
|
|
||||||
unityObjectRow.SetActive(false);
|
|
||||||
textureViewer.SetActive(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
UnityObjectRef = (UnityEngine.Object)Target.TryCast(typeof(UnityEngine.Object));
|
|
||||||
unityObjectRow.SetActive(true);
|
|
||||||
|
|
||||||
nameInput.Text = UnityObjectRef.name;
|
|
||||||
instanceIdInput.Text = UnityObjectRef.GetInstanceID().ToString();
|
|
||||||
|
|
||||||
if (typeof(Component).IsAssignableFrom(TargetType))
|
|
||||||
{
|
|
||||||
ComponentRef = (Component)Target.TryCast(typeof(Component));
|
|
||||||
gameObjectButton.Component.gameObject.SetActive(true);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
gameObjectButton.Component.gameObject.SetActive(false);
|
|
||||||
|
|
||||||
if (typeof(Texture2D).IsAssignableFrom(TargetType))
|
|
||||||
{
|
|
||||||
TextureRef = (Texture2D)Target.TryCast(typeof(Texture2D));
|
|
||||||
textureButton.Component.gameObject.SetActive(true);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
textureButton.Component.gameObject.SetActive(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnGameObjectButtonClicked()
|
|
||||||
{
|
|
||||||
if (!ComponentRef)
|
|
||||||
{
|
|
||||||
ExplorerCore.LogWarning("Component reference is null or destroyed!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
InspectorManager.Inspect(ComponentRef.gameObject);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ToggleTextureViewer()
|
|
||||||
{
|
|
||||||
if (TextureViewerWanted)
|
|
||||||
{
|
|
||||||
// disable
|
|
||||||
TextureViewerWanted = false;
|
|
||||||
textureViewer.SetActive(false);
|
|
||||||
mainContentHolder.SetActive(true);
|
|
||||||
textureButton.ButtonText.text = "View Texture";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!textureImage.sprite)
|
|
||||||
{
|
|
||||||
// First show, need to create sprite for displaying texture
|
|
||||||
SetTextureViewer();
|
|
||||||
}
|
|
||||||
|
|
||||||
// enable
|
|
||||||
TextureViewerWanted = true;
|
|
||||||
textureViewer.SetActive(true);
|
|
||||||
mainContentHolder.gameObject.SetActive(false);
|
|
||||||
textureButton.ButtonText.text = "Hide Texture";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// UI construction
|
|
||||||
|
|
||||||
private void ConstructUnityObjectRow()
|
|
||||||
{
|
|
||||||
unityObjectRow = UIFactory.CreateUIObject("UnityObjectRow", UIRoot);
|
|
||||||
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(unityObjectRow, false, false, true, true, 5);
|
|
||||||
UIFactory.SetLayoutElement(unityObjectRow, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999);
|
|
||||||
|
|
||||||
textureButton = UIFactory.CreateButton(unityObjectRow, "TextureButton", "View Texture", new Color(0.2f, 0.2f, 0.2f));
|
|
||||||
UIFactory.SetLayoutElement(textureButton.Component.gameObject, minHeight: 25, minWidth: 150);
|
|
||||||
textureButton.OnClick += ToggleTextureViewer;
|
|
||||||
|
|
||||||
var nameLabel = UIFactory.CreateLabel(unityObjectRow, "NameLabel", "Name:", TextAnchor.MiddleLeft, Color.grey);
|
|
||||||
UIFactory.SetLayoutElement(nameLabel.gameObject, minHeight: 25, minWidth: 45, flexibleWidth: 0);
|
|
||||||
|
|
||||||
nameInput = UIFactory.CreateInputField(unityObjectRow, "NameInput", "untitled");
|
|
||||||
UIFactory.SetLayoutElement(nameInput.UIRoot, minHeight: 25, minWidth: 100, flexibleWidth: 1000);
|
|
||||||
nameInput.Component.readOnly = true;
|
|
||||||
|
|
||||||
gameObjectButton = UIFactory.CreateButton(unityObjectRow, "GameObjectButton", "Inspect GameObject", new Color(0.2f, 0.2f, 0.2f));
|
|
||||||
UIFactory.SetLayoutElement(gameObjectButton.Component.gameObject, minHeight: 25, minWidth: 160);
|
|
||||||
gameObjectButton.OnClick += OnGameObjectButtonClicked;
|
|
||||||
|
|
||||||
var instanceLabel = UIFactory.CreateLabel(unityObjectRow, "InstanceLabel", "Instance ID:", TextAnchor.MiddleRight, Color.grey);
|
|
||||||
UIFactory.SetLayoutElement(instanceLabel.gameObject, minHeight: 25, minWidth: 100, flexibleWidth: 0);
|
|
||||||
|
|
||||||
instanceIdInput = UIFactory.CreateInputField(unityObjectRow, "InstanceIDInput", "ERROR");
|
|
||||||
UIFactory.SetLayoutElement(instanceIdInput.UIRoot, minHeight: 25, minWidth: 100, flexibleWidth: 0);
|
|
||||||
instanceIdInput.Component.readOnly = true;
|
|
||||||
|
|
||||||
unityObjectRow.SetActive(false);
|
|
||||||
|
|
||||||
ConstructTextureHelper();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Texture viewer helper
|
|
||||||
|
|
||||||
private InputFieldRef textureSavePathInput;
|
|
||||||
private Image textureImage;
|
|
||||||
private LayoutElement textureImageLayout;
|
|
||||||
|
|
||||||
private void CleanupTextureViewer()
|
|
||||||
{
|
|
||||||
if (textureImage.sprite)
|
|
||||||
GameObject.Destroy(textureImage.sprite);
|
|
||||||
|
|
||||||
if (TextureViewerWanted)
|
|
||||||
ToggleTextureViewer();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ConstructTextureHelper()
|
|
||||||
{
|
|
||||||
textureViewer = UIFactory.CreateVerticalGroup(UIRoot, "TextureViewer", false, false, true, true, 2, new Vector4(5, 5, 5, 5),
|
|
||||||
new Color(0.1f, 0.1f, 0.1f));
|
|
||||||
UIFactory.SetLayoutElement(textureViewer, flexibleWidth: 9999, flexibleHeight: 9999);
|
|
||||||
|
|
||||||
// Save helper
|
|
||||||
|
|
||||||
var saveRowObj = UIFactory.CreateHorizontalGroup(textureViewer, "SaveRow", false, false, true, true, 2, new Vector4(2, 2, 2, 2),
|
|
||||||
new Color(0.1f, 0.1f, 0.1f));
|
|
||||||
|
|
||||||
var saveBtn = UIFactory.CreateButton(saveRowObj, "SaveButton", "Save .PNG", new Color(0.2f, 0.25f, 0.2f));
|
|
||||||
UIFactory.SetLayoutElement(saveBtn.Component.gameObject, minHeight: 25, minWidth: 100, flexibleWidth: 0);
|
|
||||||
saveBtn.OnClick += OnSaveTextureClicked;
|
|
||||||
|
|
||||||
textureSavePathInput = UIFactory.CreateInputField(saveRowObj, "SaveInput", "...");
|
|
||||||
UIFactory.SetLayoutElement(textureSavePathInput.UIRoot, minHeight: 25, minWidth: 100, flexibleWidth: 9999);
|
|
||||||
|
|
||||||
// Actual texture viewer
|
|
||||||
|
|
||||||
var imageViewport = UIFactory.CreateVerticalGroup(textureViewer, "Viewport", false, false, true, true);
|
|
||||||
imageViewport.GetComponent<Image>().color = Color.white;
|
|
||||||
imageViewport.AddComponent<Mask>().showMaskGraphic = false;
|
|
||||||
|
|
||||||
var imageObj = UIFactory.CreateUIObject("Image", imageViewport);
|
|
||||||
var fitter = imageObj.AddComponent<ContentSizeFitter>();
|
|
||||||
fitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
|
||||||
textureImage = imageObj.AddComponent<Image>();
|
|
||||||
textureImageLayout = UIFactory.SetLayoutElement(imageObj, flexibleWidth: 1, flexibleHeight: 1);
|
|
||||||
|
|
||||||
textureViewer.SetActive(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SetTextureViewer()
|
|
||||||
{
|
|
||||||
if (!this.TextureRef)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var name = TextureRef.name;
|
|
||||||
if (string.IsNullOrEmpty(name))
|
|
||||||
name = "untitled";
|
|
||||||
|
|
||||||
textureSavePathInput.Text = Path.Combine(ConfigManager.Default_Output_Path.Value, $"{name}.png");
|
|
||||||
|
|
||||||
var sprite = TextureUtilProvider.Instance.CreateSprite(TextureRef);
|
|
||||||
textureImage.sprite = sprite;
|
|
||||||
|
|
||||||
textureImageLayout.preferredHeight = sprite.rect.height;
|
|
||||||
// not really working, its always stretched horizontally for some reason.
|
|
||||||
textureImageLayout.preferredWidth = sprite.rect.width;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnSaveTextureClicked()
|
|
||||||
{
|
|
||||||
if (!TextureRef)
|
|
||||||
{
|
|
||||||
ExplorerCore.LogWarning("Ref Texture is null, maybe it was destroyed?");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(textureSavePathInput.Text))
|
|
||||||
{
|
|
||||||
ExplorerCore.LogWarning("Save path cannot be empty!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var path = textureSavePathInput.Text;
|
|
||||||
if (!path.EndsWith(".png", StringComparison.InvariantCultureIgnoreCase))
|
|
||||||
{
|
|
||||||
ExplorerCore.LogWarning("Desired save path must end with '.png'!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
path = IOUtility.EnsureValidFilePath(path);
|
|
||||||
|
|
||||||
if (File.Exists(path))
|
|
||||||
File.Delete(path);
|
|
||||||
|
|
||||||
var tex = TextureRef;
|
|
||||||
|
|
||||||
if (!TextureUtilProvider.IsReadable(tex))
|
|
||||||
tex = TextureUtilProvider.ForceReadTexture(tex);
|
|
||||||
|
|
||||||
byte[] data = TextureUtilProvider.Instance.EncodeToPNG(tex);
|
|
||||||
File.WriteAllBytes(path, data);
|
|
||||||
|
|
||||||
if (tex != TextureRef)
|
|
||||||
{
|
|
||||||
// cleanup temp texture if we had to force-read it.
|
|
||||||
GameObject.Destroy(tex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,12 @@ using UnityExplorer;
|
|||||||
using UnityExplorer.Config;
|
using UnityExplorer.Config;
|
||||||
using UnityExplorer.Loader.ML;
|
using UnityExplorer.Loader.ML;
|
||||||
|
|
||||||
[assembly: MelonPlatformDomain(MelonPlatformDomainAttribute.CompatibleDomains.UNIVERSAL)]
|
#if CPP
|
||||||
|
[assembly: MelonPlatformDomain(MelonPlatformDomainAttribute.CompatibleDomains.IL2CPP)]
|
||||||
|
#else
|
||||||
|
[assembly: MelonPlatformDomain(MelonPlatformDomainAttribute.CompatibleDomains.MONO)]
|
||||||
|
#endif
|
||||||
|
|
||||||
[assembly: MelonInfo(typeof(ExplorerMelonMod), ExplorerCore.NAME, ExplorerCore.VERSION, ExplorerCore.AUTHOR)]
|
[assembly: MelonInfo(typeof(ExplorerMelonMod), ExplorerCore.NAME, ExplorerCore.VERSION, ExplorerCore.AUTHOR)]
|
||||||
[assembly: MelonGame(null, null)]
|
[assembly: MelonGame(null, null)]
|
||||||
[assembly: MelonColor(ConsoleColor.DarkCyan)]
|
[assembly: MelonColor(ConsoleColor.DarkCyan)]
|
||||||
@ -26,9 +31,9 @@ namespace UnityExplorer
|
|||||||
public ConfigHandler ConfigHandler => _configHandler;
|
public ConfigHandler ConfigHandler => _configHandler;
|
||||||
public MelonLoaderConfigHandler _configHandler;
|
public MelonLoaderConfigHandler _configHandler;
|
||||||
|
|
||||||
public Action<object> OnLogMessage => MelonLogger.Msg;
|
public Action<object> OnLogMessage => LoggerInstance.Msg;
|
||||||
public Action<object> OnLogWarning => MelonLogger.Warning;
|
public Action<object> OnLogWarning => LoggerInstance.Warning;
|
||||||
public Action<object> OnLogError => MelonLogger.Error;
|
public Action<object> OnLogError => LoggerInstance.Error;
|
||||||
|
|
||||||
public override void OnApplicationStart()
|
public override void OnApplicationStart()
|
||||||
{
|
{
|
||||||
|
33
src/Loader/Standalone/Editor/ExplorerEditorBehaviour.cs
Normal file
33
src/Loader/Standalone/Editor/ExplorerEditorBehaviour.cs
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#if STANDALONE
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace UnityExplorer.Loader.Standalone
|
||||||
|
{
|
||||||
|
public class ExplorerEditorBehaviour : MonoBehaviour
|
||||||
|
{
|
||||||
|
internal void Awake()
|
||||||
|
{
|
||||||
|
ExplorerEditorLoader.Initialize();
|
||||||
|
DontDestroyOnLoad(this);
|
||||||
|
this.gameObject.hideFlags = HideFlags.HideAndDontSave;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void OnDestroy()
|
||||||
|
{
|
||||||
|
OnApplicationQuit();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void OnApplicationQuit()
|
||||||
|
{
|
||||||
|
if (UI.UIManager.UIRoot)
|
||||||
|
Destroy(UI.UIManager.UIRoot.transform.root.gameObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
41
src/Loader/Standalone/Editor/ExplorerEditorLoader.cs
Normal file
41
src/Loader/Standalone/Editor/ExplorerEditorLoader.cs
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
#if STANDALONE
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace UnityExplorer.Loader.Standalone
|
||||||
|
{
|
||||||
|
public class ExplorerEditorLoader : ExplorerStandalone
|
||||||
|
{
|
||||||
|
public static void Initialize()
|
||||||
|
{
|
||||||
|
Instance = new ExplorerEditorLoader();
|
||||||
|
OnLog += LogHandler;
|
||||||
|
Instance.configHandler = new StandaloneConfigHandler();
|
||||||
|
|
||||||
|
ExplorerCore.Init(Instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void LogHandler(string message, LogType logType)
|
||||||
|
{
|
||||||
|
switch (logType)
|
||||||
|
{
|
||||||
|
case LogType.Assert: Debug.LogError(message); break;
|
||||||
|
case LogType.Error: Debug.LogError(message); break;
|
||||||
|
case LogType.Exception: Debug.LogError(message); break;
|
||||||
|
case LogType.Log: Debug.Log(message); break;
|
||||||
|
case LogType.Warning: Debug.LogWarning(message); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void CheckExplorerFolder()
|
||||||
|
{
|
||||||
|
if (explorerFolder == null)
|
||||||
|
explorerFolder = Path.Combine(Application.dataPath, "UnityExplorer~");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
@ -5,9 +5,9 @@ using System.IO;
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityExplorer.Config;
|
using UnityExplorer.Config;
|
||||||
using UnityExplorer.Loader.STANDALONE;
|
|
||||||
using UnityEngine.EventSystems;
|
using UnityEngine.EventSystems;
|
||||||
using UniverseLib.Input;
|
using UniverseLib.Input;
|
||||||
|
using UnityExplorer.Loader.Standalone;
|
||||||
#if CPP
|
#if CPP
|
||||||
using UnhollowerRuntimeLib;
|
using UnhollowerRuntimeLib;
|
||||||
#endif
|
#endif
|
||||||
@ -16,6 +16,33 @@ namespace UnityExplorer
|
|||||||
{
|
{
|
||||||
public class ExplorerStandalone : IExplorerLoader
|
public class ExplorerStandalone : IExplorerLoader
|
||||||
{
|
{
|
||||||
|
public static ExplorerStandalone Instance { get; protected set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invoked whenever Explorer logs something. Subscribe to this to handle logging.
|
||||||
|
/// </summary>
|
||||||
|
public static event Action<string, LogType> OnLog;
|
||||||
|
|
||||||
|
public string UnhollowedModulesFolder => unhollowedPath;
|
||||||
|
private string unhollowedPath;
|
||||||
|
|
||||||
|
public ConfigHandler ConfigHandler => configHandler;
|
||||||
|
internal StandaloneConfigHandler configHandler;
|
||||||
|
|
||||||
|
public string ExplorerFolder
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
CheckExplorerFolder();
|
||||||
|
return explorerFolder;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
protected static string explorerFolder;
|
||||||
|
|
||||||
|
Action<object> IExplorerLoader.OnLogMessage => (object log) => { OnLog?.Invoke(log?.ToString() ?? "", LogType.Log); };
|
||||||
|
Action<object> IExplorerLoader.OnLogWarning => (object log) => { OnLog?.Invoke(log?.ToString() ?? "", LogType.Warning); };
|
||||||
|
Action<object> IExplorerLoader.OnLogError => (object log) => { OnLog?.Invoke(log?.ToString() ?? "", LogType.Error); };
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Call this to initialize UnityExplorer without adding a log listener or Unhollowed modules path.
|
/// Call this to initialize UnityExplorer without adding a log listener or Unhollowed modules path.
|
||||||
/// The default Unhollowed path "UnityExplorer\Modules\" will be used.
|
/// The default Unhollowed path "UnityExplorer\Modules\" will be used.
|
||||||
@ -50,60 +77,33 @@ namespace UnityExplorer
|
|||||||
OnLog += logListener;
|
OnLog += logListener;
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(unhollowedModulesPath) || !Directory.Exists(unhollowedModulesPath))
|
if (string.IsNullOrEmpty(unhollowedModulesPath) || !Directory.Exists(unhollowedModulesPath))
|
||||||
instance._unhollowedPath = Path.Combine(instance.ExplorerFolder, "Modules");
|
instance.unhollowedPath = Path.Combine(instance.ExplorerFolder, "Modules");
|
||||||
else
|
else
|
||||||
instance._unhollowedPath = unhollowedModulesPath;
|
instance.unhollowedPath = unhollowedModulesPath;
|
||||||
|
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ExplorerStandalone Instance { get; private set; }
|
internal void Init()
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Invoked whenever Explorer logs something. Subscribe to this to handle logging.
|
|
||||||
/// </summary>
|
|
||||||
public static event Action<string, LogType> OnLog;
|
|
||||||
|
|
||||||
public string UnhollowedModulesFolder => _unhollowedPath;
|
|
||||||
private string _unhollowedPath;
|
|
||||||
|
|
||||||
public ConfigHandler ConfigHandler => _configHandler;
|
|
||||||
private StandaloneConfigHandler _configHandler;
|
|
||||||
|
|
||||||
public string ExplorerFolder
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
CheckExplorerFolder();
|
|
||||||
return s_explorerFolder;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private static string s_explorerFolder;
|
|
||||||
|
|
||||||
Action<object> IExplorerLoader.OnLogMessage => (object log) => { OnLog?.Invoke(log?.ToString() ?? "", LogType.Log); };
|
|
||||||
Action<object> IExplorerLoader.OnLogWarning => (object log) => { OnLog?.Invoke(log?.ToString() ?? "", LogType.Warning); };
|
|
||||||
Action<object> IExplorerLoader.OnLogError => (object log) => { OnLog?.Invoke(log?.ToString() ?? "", LogType.Error); };
|
|
||||||
|
|
||||||
private void Init()
|
|
||||||
{
|
{
|
||||||
Instance = this;
|
Instance = this;
|
||||||
_configHandler = new StandaloneConfigHandler();
|
configHandler = new StandaloneConfigHandler();
|
||||||
|
|
||||||
ExplorerCore.Init(this);
|
ExplorerCore.Init(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CheckExplorerFolder()
|
protected virtual void CheckExplorerFolder()
|
||||||
{
|
{
|
||||||
if (s_explorerFolder == null)
|
if (explorerFolder == null)
|
||||||
{
|
{
|
||||||
s_explorerFolder =
|
explorerFolder =
|
||||||
Path.Combine(
|
Path.Combine(
|
||||||
Path.GetDirectoryName(
|
Path.GetDirectoryName(
|
||||||
Uri.UnescapeDataString(new Uri(Assembly.GetExecutingAssembly().CodeBase).AbsolutePath)),
|
Uri.UnescapeDataString(new Uri(Assembly.GetExecutingAssembly().CodeBase).AbsolutePath)),
|
||||||
"UnityExplorer");
|
"UnityExplorer");
|
||||||
|
|
||||||
if (!Directory.Exists(s_explorerFolder))
|
if (!Directory.Exists(explorerFolder))
|
||||||
Directory.CreateDirectory(s_explorerFolder);
|
Directory.CreateDirectory(explorerFolder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,22 +4,20 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityExplorer.Config;
|
using UnityExplorer.Config;
|
||||||
using IniParser.Parser;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using Tomlet;
|
||||||
|
using Tomlet.Models;
|
||||||
|
|
||||||
namespace UnityExplorer.Loader.STANDALONE
|
namespace UnityExplorer.Loader.Standalone
|
||||||
{
|
{
|
||||||
public class StandaloneConfigHandler : ConfigHandler
|
public class StandaloneConfigHandler : ConfigHandler
|
||||||
{
|
{
|
||||||
internal static IniDataParser _parser;
|
|
||||||
internal static string CONFIG_PATH;
|
internal static string CONFIG_PATH;
|
||||||
|
|
||||||
public override void Init()
|
public override void Init()
|
||||||
{
|
{
|
||||||
CONFIG_PATH = Path.Combine(ExplorerCore.Loader.ExplorerFolder, "config.ini");
|
CONFIG_PATH = Path.Combine(ExplorerCore.Loader.ExplorerFolder, "config.cfg");
|
||||||
_parser = new IniDataParser();
|
|
||||||
_parser.Configuration.CommentString = "#";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void LoadConfig()
|
public override void LoadConfig()
|
||||||
@ -52,14 +50,11 @@ namespace UnityExplorer.Loader.STANDALONE
|
|||||||
if (!File.Exists(CONFIG_PATH))
|
if (!File.Exists(CONFIG_PATH))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
string ini = File.ReadAllText(CONFIG_PATH);
|
var document = TomlParser.ParseFile(CONFIG_PATH);
|
||||||
|
foreach (var key in document.Keys)
|
||||||
var data = _parser.Parse(ini);
|
|
||||||
|
|
||||||
foreach (var config in data.Sections["Config"])
|
|
||||||
{
|
{
|
||||||
if (ConfigManager.ConfigElements.TryGetValue(config.KeyName, out IConfigElement configElement))
|
var config = ConfigManager.ConfigElements[key];
|
||||||
configElement.BoxedValue = StringToConfigValue(config.Value, configElement.ElementType);
|
config.BoxedValue = StringToConfigValue(document.GetValue(key).StringValue, config.ElementType);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -78,7 +73,11 @@ namespace UnityExplorer.Loader.STANDALONE
|
|||||||
return bool.Parse(value);
|
return bool.Parse(value);
|
||||||
else if (elementType == typeof(int))
|
else if (elementType == typeof(int))
|
||||||
return int.Parse(value);
|
return int.Parse(value);
|
||||||
else
|
else if (elementType == typeof(float))
|
||||||
|
return float.Parse(value);
|
||||||
|
else if (elementType.IsEnum)
|
||||||
|
return Enum.Parse(elementType, value);
|
||||||
|
else
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,18 +88,14 @@ namespace UnityExplorer.Loader.STANDALONE
|
|||||||
|
|
||||||
public override void SaveConfig()
|
public override void SaveConfig()
|
||||||
{
|
{
|
||||||
var data = new IniParser.Model.IniData();
|
var document = TomlDocument.CreateEmpty();
|
||||||
|
foreach (var config in ConfigManager.ConfigElements)
|
||||||
data.Sections.AddSection("Config");
|
document.Put(config.Key, config.Value.BoxedValue.ToString());
|
||||||
var sec = data.Sections["Config"];
|
|
||||||
|
|
||||||
foreach (var entry in ConfigManager.ConfigElements)
|
|
||||||
sec.AddKey(entry.Key, entry.Value.BoxedValue.ToString());
|
|
||||||
|
|
||||||
if (!Directory.Exists(ExplorerCore.Loader.ExplorerFolder))
|
if (!Directory.Exists(ExplorerCore.Loader.ExplorerFolder))
|
||||||
Directory.CreateDirectory(ExplorerCore.Loader.ExplorerFolder);
|
Directory.CreateDirectory(ExplorerCore.Loader.ExplorerFolder);
|
||||||
|
|
||||||
File.WriteAllText(CONFIG_PATH, data.ToString());
|
File.WriteAllText(CONFIG_PATH, document.SerializedValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,14 +4,14 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.UI;
|
|
||||||
using UniverseLib.UI.Models;
|
using UniverseLib.UI.Models;
|
||||||
using UnityExplorer.UI.Panels;
|
using UnityExplorer.UI.Panels;
|
||||||
using UnityExplorer.UI.Widgets;
|
|
||||||
using UnityExplorer.UI.Widgets.AutoComplete;
|
using UnityExplorer.UI.Widgets.AutoComplete;
|
||||||
using UniverseLib.UI.Widgets;
|
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
|
using UniverseLib.UI.Widgets.ButtonList;
|
||||||
|
using UniverseLib.UI.Widgets.ScrollView;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.ObjectExplorer
|
namespace UnityExplorer.ObjectExplorer
|
||||||
{
|
{
|
||||||
@ -24,28 +24,25 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
Parent = parent;
|
Parent = parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
private SearchContext m_context = SearchContext.UnityObject;
|
private SearchContext context = SearchContext.UnityObject;
|
||||||
private SceneFilter m_sceneFilter = SceneFilter.Any;
|
private SceneFilter sceneFilter = SceneFilter.Any;
|
||||||
private ChildFilter m_childFilter = ChildFilter.Any;
|
private ChildFilter childFilter = ChildFilter.Any;
|
||||||
private string desiredTypeInput;
|
private string desiredTypeInput;
|
||||||
private string lastCheckedTypeInput;
|
private string lastCheckedTypeInput;
|
||||||
private bool lastTypeCanHaveGO;
|
private bool lastTypeCanHaveGameObject;
|
||||||
|
|
||||||
public ButtonListHandler<object, ButtonCell> dataHandler;
|
public ButtonListHandler<object, ButtonCell> dataHandler;
|
||||||
|
|
||||||
private ScrollPool<ButtonCell> resultsScrollPool;
|
private ScrollPool<ButtonCell> resultsScrollPool;
|
||||||
private List<object> currentResults = new List<object>();
|
private List<object> currentResults = new();
|
||||||
|
|
||||||
public TypeCompleter typeAutocompleter;
|
|
||||||
|
|
||||||
public override GameObject UIRoot => uiRoot;
|
public override GameObject UIRoot => uiRoot;
|
||||||
private GameObject uiRoot;
|
private GameObject uiRoot;
|
||||||
|
|
||||||
private GameObject sceneFilterRow;
|
private GameObject sceneFilterRow;
|
||||||
private GameObject childFilterRow;
|
private GameObject childFilterRow;
|
||||||
private GameObject unityObjectClassRow;
|
private GameObject classInputRow;
|
||||||
|
public TypeCompleter typeAutocompleter;
|
||||||
|
private GameObject nameInputRow;
|
||||||
private InputFieldRef nameInputField;
|
private InputFieldRef nameInputField;
|
||||||
|
|
||||||
private Text resultsLabel;
|
private Text resultsLabel;
|
||||||
|
|
||||||
public List<object> GetEntries() => currentResults;
|
public List<object> GetEntries() => currentResults;
|
||||||
@ -54,12 +51,12 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
{
|
{
|
||||||
cachedCellTexts.Clear();
|
cachedCellTexts.Clear();
|
||||||
|
|
||||||
if (m_context == SearchContext.Singleton)
|
if (context == SearchContext.Singleton)
|
||||||
currentResults = SearchProvider.SingletonSearch(nameInputField.Text);
|
currentResults = SearchProvider.InstanceSearch(desiredTypeInput).ToList();
|
||||||
else if (m_context == SearchContext.Class)
|
else if (context == SearchContext.Class)
|
||||||
currentResults = SearchProvider.ClassSearch(nameInputField.Text);
|
currentResults = SearchProvider.ClassSearch(desiredTypeInput);
|
||||||
else
|
else
|
||||||
currentResults = SearchProvider.UnityObjectSearch(nameInputField.Text, desiredTypeInput, m_context, m_childFilter, m_sceneFilter);
|
currentResults = SearchProvider.UnityObjectSearch(nameInputField.Text, desiredTypeInput, childFilter, sceneFilter);
|
||||||
|
|
||||||
dataHandler.RefreshData();
|
dataHandler.RefreshData();
|
||||||
resultsScrollPool.Refresh(true);
|
resultsScrollPool.Refresh(true);
|
||||||
@ -69,7 +66,7 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
|
|
||||||
public void Update()
|
public void Update()
|
||||||
{
|
{
|
||||||
if (m_context == SearchContext.UnityObject && lastCheckedTypeInput != desiredTypeInput)
|
if (context == SearchContext.UnityObject && lastCheckedTypeInput != desiredTypeInput)
|
||||||
{
|
{
|
||||||
lastCheckedTypeInput = desiredTypeInput;
|
lastCheckedTypeInput = desiredTypeInput;
|
||||||
|
|
||||||
@ -77,15 +74,15 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
if (ReflectionUtility.GetTypeByName(desiredTypeInput) is Type cachedType)
|
if (ReflectionUtility.GetTypeByName(desiredTypeInput) is Type cachedType)
|
||||||
{
|
{
|
||||||
var type = cachedType;
|
var type = cachedType;
|
||||||
lastTypeCanHaveGO = typeof(Component).IsAssignableFrom(type) || type == typeof(GameObject);
|
lastTypeCanHaveGameObject = typeof(Component).IsAssignableFrom(type) || type == typeof(GameObject);
|
||||||
sceneFilterRow.SetActive(lastTypeCanHaveGO);
|
sceneFilterRow.SetActive(lastTypeCanHaveGameObject);
|
||||||
childFilterRow.SetActive(lastTypeCanHaveGO);
|
childFilterRow.SetActive(lastTypeCanHaveGameObject);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sceneFilterRow.SetActive(false);
|
sceneFilterRow.SetActive(false);
|
||||||
childFilterRow.SetActive(false);
|
childFilterRow.SetActive(false);
|
||||||
lastTypeCanHaveGO = false;
|
lastTypeCanHaveGameObject = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -94,18 +91,27 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
|
|
||||||
private void OnContextDropdownChanged(int value)
|
private void OnContextDropdownChanged(int value)
|
||||||
{
|
{
|
||||||
m_context = (SearchContext)value;
|
context = (SearchContext)value;
|
||||||
|
|
||||||
lastCheckedTypeInput = null;
|
lastCheckedTypeInput = null;
|
||||||
sceneFilterRow.SetActive(false);
|
sceneFilterRow.SetActive(false);
|
||||||
childFilterRow.SetActive(false);
|
childFilterRow.SetActive(false);
|
||||||
|
|
||||||
unityObjectClassRow.SetActive(m_context == SearchContext.UnityObject);
|
nameInputRow.SetActive(context == SearchContext.UnityObject);
|
||||||
|
|
||||||
|
if (context == SearchContext.Class)
|
||||||
|
typeAutocompleter.AllTypes = true;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
typeAutocompleter.BaseType = context == SearchContext.UnityObject ? typeof(UnityEngine.Object) : typeof(object);
|
||||||
|
typeAutocompleter.AllTypes = false;
|
||||||
|
}
|
||||||
|
typeAutocompleter.CacheTypes();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnSceneFilterDropChanged(int value) => m_sceneFilter = (SceneFilter)value;
|
private void OnSceneFilterDropChanged(int value) => sceneFilter = (SceneFilter)value;
|
||||||
|
|
||||||
private void OnChildFilterDropChanged(int value) => m_childFilter = (ChildFilter)value;
|
private void OnChildFilterDropChanged(int value) => childFilter = (ChildFilter)value;
|
||||||
|
|
||||||
private void OnTypeInputChanged(string val)
|
private void OnTypeInputChanged(string val)
|
||||||
{
|
{
|
||||||
@ -120,14 +126,14 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Cache the syntax-highlighted text for each search result to reduce allocs.
|
// Cache the syntax-highlighted text for each search result to reduce allocs.
|
||||||
private static readonly Dictionary<int, string> cachedCellTexts = new Dictionary<int, string>();
|
private static readonly Dictionary<int, string> cachedCellTexts = new();
|
||||||
|
|
||||||
public void SetCell(ButtonCell cell, int index)
|
public void SetCell(ButtonCell cell, int index)
|
||||||
{
|
{
|
||||||
if (!cachedCellTexts.ContainsKey(index))
|
if (!cachedCellTexts.ContainsKey(index))
|
||||||
{
|
{
|
||||||
string text;
|
string text;
|
||||||
if (m_context == SearchContext.Class)
|
if (context == SearchContext.Class)
|
||||||
{
|
{
|
||||||
var type = currentResults[index] as Type;
|
var type = currentResults[index] as Type;
|
||||||
text = $"{SignatureHighlighter.Parse(type, true)} <color=grey><i>({type.Assembly.GetName().Name})</i></color>";
|
text = $"{SignatureHighlighter.Parse(type, true)} <color=grey><i>({type.Assembly.GetName().Name})</i></color>";
|
||||||
@ -143,7 +149,7 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
|
|
||||||
private void OnCellClicked(int dataIndex)
|
private void OnCellClicked(int dataIndex)
|
||||||
{
|
{
|
||||||
if (m_context == SearchContext.Class)
|
if (context == SearchContext.Class)
|
||||||
InspectorManager.Inspect(currentResults[dataIndex] as Type);
|
InspectorManager.Inspect(currentResults[dataIndex] as Type);
|
||||||
else
|
else
|
||||||
InspectorManager.Inspect(currentResults[dataIndex]);
|
InspectorManager.Inspect(currentResults[dataIndex]);
|
||||||
@ -164,20 +170,20 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
var contextLbl = UIFactory.CreateLabel(contextGroup, "SearchContextLabel", "Searching for:", TextAnchor.MiddleLeft);
|
var contextLbl = UIFactory.CreateLabel(contextGroup, "SearchContextLabel", "Searching for:", TextAnchor.MiddleLeft);
|
||||||
UIFactory.SetLayoutElement(contextLbl.gameObject, minWidth: 110, flexibleWidth: 0);
|
UIFactory.SetLayoutElement(contextLbl.gameObject, minWidth: 110, flexibleWidth: 0);
|
||||||
|
|
||||||
var contextDropObj = UIFactory.CreateDropdown(contextGroup, out Dropdown contextDrop, null, 14, OnContextDropdownChanged);
|
var contextDropObj = UIFactory.CreateDropdown(contextGroup, "ContextDropdown", out Dropdown contextDrop, null, 14, OnContextDropdownChanged);
|
||||||
foreach (var name in Enum.GetNames(typeof(SearchContext)))
|
foreach (var name in Enum.GetNames(typeof(SearchContext)))
|
||||||
contextDrop.options.Add(new Dropdown.OptionData(name));
|
contextDrop.options.Add(new Dropdown.OptionData(name));
|
||||||
UIFactory.SetLayoutElement(contextDropObj, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999);
|
UIFactory.SetLayoutElement(contextDropObj, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999);
|
||||||
|
|
||||||
// Unity class input
|
// Class input
|
||||||
|
|
||||||
unityObjectClassRow = UIFactory.CreateHorizontalGroup(uiRoot, "UnityClassRow", false, true, true, true, 2, new Vector4(2, 2, 2, 2));
|
classInputRow = UIFactory.CreateHorizontalGroup(uiRoot, "ClassRow", false, true, true, true, 2, new Vector4(2, 2, 2, 2));
|
||||||
UIFactory.SetLayoutElement(unityObjectClassRow, minHeight: 25, flexibleHeight: 0);
|
UIFactory.SetLayoutElement(classInputRow, minHeight: 25, flexibleHeight: 0);
|
||||||
|
|
||||||
var unityClassLbl = UIFactory.CreateLabel(unityObjectClassRow, "UnityClassLabel", "Class filter:", TextAnchor.MiddleLeft);
|
var unityClassLbl = UIFactory.CreateLabel(classInputRow, "ClassLabel", "Class filter:", TextAnchor.MiddleLeft);
|
||||||
UIFactory.SetLayoutElement(unityClassLbl.gameObject, minWidth: 110, flexibleWidth: 0);
|
UIFactory.SetLayoutElement(unityClassLbl.gameObject, minWidth: 110, flexibleWidth: 0);
|
||||||
|
|
||||||
var classInputField = UIFactory.CreateInputField(unityObjectClassRow, "ClassInput", "...");
|
var classInputField = UIFactory.CreateInputField(classInputRow, "ClassInput", "...");
|
||||||
UIFactory.SetLayoutElement(classInputField.UIRoot, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999);
|
UIFactory.SetLayoutElement(classInputField.UIRoot, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999);
|
||||||
|
|
||||||
typeAutocompleter = new TypeCompleter(typeof(UnityEngine.Object), classInputField);
|
typeAutocompleter = new TypeCompleter(typeof(UnityEngine.Object), classInputField);
|
||||||
@ -193,7 +199,7 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
var childLbl = UIFactory.CreateLabel(childFilterRow, "ChildLabel", "Child filter:", TextAnchor.MiddleLeft);
|
var childLbl = UIFactory.CreateLabel(childFilterRow, "ChildLabel", "Child filter:", TextAnchor.MiddleLeft);
|
||||||
UIFactory.SetLayoutElement(childLbl.gameObject, minWidth: 110, flexibleWidth: 0);
|
UIFactory.SetLayoutElement(childLbl.gameObject, minWidth: 110, flexibleWidth: 0);
|
||||||
|
|
||||||
var childDropObj = UIFactory.CreateDropdown(childFilterRow, out Dropdown childDrop, null, 14, OnChildFilterDropChanged);
|
var childDropObj = UIFactory.CreateDropdown(childFilterRow, "ChildFilterDropdown", out Dropdown childDrop, null, 14, OnChildFilterDropChanged);
|
||||||
foreach (var name in Enum.GetNames(typeof(ChildFilter)))
|
foreach (var name in Enum.GetNames(typeof(ChildFilter)))
|
||||||
childDrop.options.Add(new Dropdown.OptionData(name));
|
childDrop.options.Add(new Dropdown.OptionData(name));
|
||||||
UIFactory.SetLayoutElement(childDropObj, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999);
|
UIFactory.SetLayoutElement(childDropObj, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999);
|
||||||
@ -208,22 +214,26 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
var sceneLbl = UIFactory.CreateLabel(sceneFilterRow, "SceneLabel", "Scene filter:", TextAnchor.MiddleLeft);
|
var sceneLbl = UIFactory.CreateLabel(sceneFilterRow, "SceneLabel", "Scene filter:", TextAnchor.MiddleLeft);
|
||||||
UIFactory.SetLayoutElement(sceneLbl.gameObject, minWidth: 110, flexibleWidth: 0);
|
UIFactory.SetLayoutElement(sceneLbl.gameObject, minWidth: 110, flexibleWidth: 0);
|
||||||
|
|
||||||
var sceneDropObj = UIFactory.CreateDropdown(sceneFilterRow, out Dropdown sceneDrop, null, 14, OnSceneFilterDropChanged);
|
var sceneDropObj = UIFactory.CreateDropdown(sceneFilterRow, "SceneFilterDropdown", out Dropdown sceneDrop, null, 14, OnSceneFilterDropChanged);
|
||||||
foreach (var name in Enum.GetNames(typeof(SceneFilter)))
|
foreach (var name in Enum.GetNames(typeof(SceneFilter)))
|
||||||
|
{
|
||||||
|
if (!SceneHandler.DontDestroyExists && name == "DontDestroyOnLoad")
|
||||||
|
continue;
|
||||||
sceneDrop.options.Add(new Dropdown.OptionData(name));
|
sceneDrop.options.Add(new Dropdown.OptionData(name));
|
||||||
|
}
|
||||||
UIFactory.SetLayoutElement(sceneDropObj, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999);
|
UIFactory.SetLayoutElement(sceneDropObj, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999);
|
||||||
|
|
||||||
sceneFilterRow.SetActive(false);
|
sceneFilterRow.SetActive(false);
|
||||||
|
|
||||||
// Name filter input
|
// Name filter input
|
||||||
|
|
||||||
var nameRow = UIFactory.CreateHorizontalGroup(uiRoot, "NameRow", true, true, true, true, 2, new Vector4(2, 2, 2, 2));
|
nameInputRow = UIFactory.CreateHorizontalGroup(uiRoot, "NameRow", true, true, true, true, 2, new Vector4(2, 2, 2, 2));
|
||||||
UIFactory.SetLayoutElement(nameRow, minHeight: 25, flexibleHeight: 0);
|
UIFactory.SetLayoutElement(nameInputRow, minHeight: 25, flexibleHeight: 0);
|
||||||
|
|
||||||
var nameLbl = UIFactory.CreateLabel(nameRow, "NameFilterLabel", "Name contains:", TextAnchor.MiddleLeft);
|
var nameLbl = UIFactory.CreateLabel(nameInputRow, "NameFilterLabel", "Name contains:", TextAnchor.MiddleLeft);
|
||||||
UIFactory.SetLayoutElement(nameLbl.gameObject, minWidth: 110, flexibleWidth: 0);
|
UIFactory.SetLayoutElement(nameLbl.gameObject, minWidth: 110, flexibleWidth: 0);
|
||||||
|
|
||||||
nameInputField = UIFactory.CreateInputField(nameRow, "NameFilterInput", "...");
|
nameInputField = UIFactory.CreateInputField(nameInputRow, "NameFilterInput", "...");
|
||||||
UIFactory.SetLayoutElement(nameInputField.UIRoot, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999);
|
UIFactory.SetLayoutElement(nameInputField.UIRoot, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999);
|
||||||
|
|
||||||
// Search button
|
// Search button
|
||||||
|
@ -14,6 +14,7 @@ using UnityExplorer.UI.Widgets;
|
|||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.ObjectExplorer
|
namespace UnityExplorer.ObjectExplorer
|
||||||
{
|
{
|
||||||
@ -26,11 +27,11 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
Parent = parent;
|
Parent = parent;
|
||||||
|
|
||||||
SceneHandler.OnInspectedSceneChanged += SceneHandler_OnInspectedSceneChanged;
|
SceneHandler.OnInspectedSceneChanged += SceneHandler_OnInspectedSceneChanged;
|
||||||
SceneHandler.OnLoadedScenesChanged += SceneHandler_OnLoadedScenesChanged;
|
SceneHandler.OnLoadedScenesUpdated += SceneHandler_OnLoadedScenesUpdated;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override GameObject UIRoot => m_uiRoot;
|
public override GameObject UIRoot => uiRoot;
|
||||||
private GameObject m_uiRoot;
|
private GameObject uiRoot;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether to automatically update per auto-update interval or not.
|
/// Whether to automatically update per auto-update interval or not.
|
||||||
@ -42,7 +43,7 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
|
|
||||||
private GameObject refreshRow;
|
private GameObject refreshRow;
|
||||||
private Dropdown sceneDropdown;
|
private Dropdown sceneDropdown;
|
||||||
private readonly Dictionary<Scene, Dropdown.OptionData> sceneToDropdownOption = new Dictionary<Scene, Dropdown.OptionData>();
|
private readonly Dictionary<Scene, Dropdown.OptionData> sceneToDropdownOption = new();
|
||||||
|
|
||||||
// scene loader
|
// scene loader
|
||||||
private Dropdown allSceneDropdown;
|
private Dropdown allSceneDropdown;
|
||||||
@ -63,7 +64,7 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
public void UpdateTree()
|
public void UpdateTree()
|
||||||
{
|
{
|
||||||
SceneHandler.Update();
|
SceneHandler.Update();
|
||||||
Tree.RefreshData(true);
|
Tree.RefreshData(true, false, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void JumpToTransform(Transform transform)
|
public void JumpToTransform(Transform transform)
|
||||||
@ -86,21 +87,21 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
Tree.JumpAndExpandToTransform(transform);
|
Tree.JumpAndExpandToTransform(transform);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDropdownChanged(int value)
|
private void OnSceneSelectionDropdownChanged(int value)
|
||||||
{
|
{
|
||||||
if (value < 0 || SceneHandler.LoadedScenes.Count <= value)
|
if (value < 0 || SceneHandler.LoadedScenes.Count <= value)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
SceneHandler.SelectedScene = SceneHandler.LoadedScenes[value];
|
SceneHandler.SelectedScene = SceneHandler.LoadedScenes[value];
|
||||||
SceneHandler.Update();
|
SceneHandler.Update();
|
||||||
Tree.RefreshData(true);
|
Tree.RefreshData(true, true, true, false);
|
||||||
OnSelectedSceneChanged(SceneHandler.SelectedScene.Value);
|
OnSelectedSceneChanged(SceneHandler.SelectedScene.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SceneHandler_OnInspectedSceneChanged(Scene scene)
|
private void SceneHandler_OnInspectedSceneChanged(Scene scene)
|
||||||
{
|
{
|
||||||
if (!sceneToDropdownOption.ContainsKey(scene))
|
if (!sceneToDropdownOption.ContainsKey(scene))
|
||||||
PopulateSceneDropdown();
|
PopulateSceneDropdown(SceneHandler.LoadedScenes);
|
||||||
|
|
||||||
if (sceneToDropdownOption.ContainsKey(scene))
|
if (sceneToDropdownOption.ContainsKey(scene))
|
||||||
{
|
{
|
||||||
@ -121,17 +122,17 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
refreshRow.SetActive(!scene.IsValid());
|
refreshRow.SetActive(!scene.IsValid());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SceneHandler_OnLoadedScenesChanged(List<Scene> loadedScenes)
|
private void SceneHandler_OnLoadedScenesUpdated(List<Scene> loadedScenes)
|
||||||
{
|
{
|
||||||
PopulateSceneDropdown();
|
PopulateSceneDropdown(loadedScenes);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PopulateSceneDropdown()
|
private void PopulateSceneDropdown(List<Scene> loadedScenes)
|
||||||
{
|
{
|
||||||
sceneToDropdownOption.Clear();
|
sceneToDropdownOption.Clear();
|
||||||
sceneDropdown.options.Clear();
|
sceneDropdown.options.Clear();
|
||||||
|
|
||||||
foreach (var scene in SceneHandler.LoadedScenes)
|
foreach (var scene in loadedScenes)
|
||||||
{
|
{
|
||||||
if (sceneToDropdownOption.ContainsKey(scene))
|
if (sceneToDropdownOption.ContainsKey(scene))
|
||||||
continue;
|
continue;
|
||||||
@ -157,7 +158,7 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
}
|
}
|
||||||
|
|
||||||
Tree.CurrentFilter = input;
|
Tree.CurrentFilter = input;
|
||||||
Tree.RefreshData(true, true);
|
Tree.RefreshData(true, false, true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void TryLoadScene(LoadSceneMode mode, Dropdown allSceneDrop)
|
private void TryLoadScene(LoadSceneMode mode, Dropdown allSceneDrop)
|
||||||
@ -180,13 +181,13 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
|
|
||||||
public override void ConstructUI(GameObject content)
|
public override void ConstructUI(GameObject content)
|
||||||
{
|
{
|
||||||
m_uiRoot = UIFactory.CreateUIObject("SceneExplorer", content);
|
uiRoot = UIFactory.CreateUIObject("SceneExplorer", content);
|
||||||
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(m_uiRoot, true, true, true, true, 0, 2, 2, 2, 2);
|
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(uiRoot, true, true, true, true, 0, 2, 2, 2, 2);
|
||||||
UIFactory.SetLayoutElement(m_uiRoot, flexibleHeight: 9999);
|
UIFactory.SetLayoutElement(uiRoot, flexibleHeight: 9999);
|
||||||
|
|
||||||
// Tool bar (top area)
|
// Tool bar (top area)
|
||||||
|
|
||||||
var toolbar = UIFactory.CreateVerticalGroup(m_uiRoot, "Toolbar", true, true, true, true, 2, new Vector4(2, 2, 2, 2),
|
var toolbar = UIFactory.CreateVerticalGroup(uiRoot, "Toolbar", true, true, true, true, 2, new Vector4(2, 2, 2, 2),
|
||||||
new Color(0.15f, 0.15f, 0.15f));
|
new Color(0.15f, 0.15f, 0.15f));
|
||||||
|
|
||||||
// Scene selector dropdown
|
// Scene selector dropdown
|
||||||
@ -197,11 +198,11 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
var dropLabel = UIFactory.CreateLabel(dropRow, "SelectorLabel", "Scene:", TextAnchor.MiddleLeft, Color.cyan, false, 15);
|
var dropLabel = UIFactory.CreateLabel(dropRow, "SelectorLabel", "Scene:", TextAnchor.MiddleLeft, Color.cyan, false, 15);
|
||||||
UIFactory.SetLayoutElement(dropLabel.gameObject, minHeight: 25, minWidth: 60, flexibleWidth: 0);
|
UIFactory.SetLayoutElement(dropLabel.gameObject, minHeight: 25, minWidth: 60, flexibleWidth: 0);
|
||||||
|
|
||||||
var dropdownObj = UIFactory.CreateDropdown(dropRow, out sceneDropdown, "<notset>", 13, OnDropdownChanged);
|
var dropdownObj = UIFactory.CreateDropdown(dropRow, "SceneDropdown", out sceneDropdown, "<notset>", 13, OnSceneSelectionDropdownChanged);
|
||||||
UIFactory.SetLayoutElement(dropdownObj, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999);
|
UIFactory.SetLayoutElement(dropdownObj, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999);
|
||||||
|
|
||||||
SceneHandler.Update();
|
SceneHandler.Update();
|
||||||
PopulateSceneDropdown();
|
PopulateSceneDropdown(SceneHandler.LoadedScenes);
|
||||||
sceneDropdown.captionText.text = sceneToDropdownOption.First().Value.text;
|
sceneDropdown.captionText.text = sceneToDropdownOption.First().Value.text;
|
||||||
|
|
||||||
// Filter row
|
// Filter row
|
||||||
@ -212,7 +213,7 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
//Filter input field
|
//Filter input field
|
||||||
var inputField = UIFactory.CreateInputField(filterRow, "FilterInput", "Search and press enter...");
|
var inputField = UIFactory.CreateInputField(filterRow, "FilterInput", "Search and press enter...");
|
||||||
inputField.Component.targetGraphic.color = new Color(0.2f, 0.2f, 0.2f);
|
inputField.Component.targetGraphic.color = new Color(0.2f, 0.2f, 0.2f);
|
||||||
RuntimeProvider.Instance.SetColorBlock(inputField.Component, new Color(0.4f, 0.4f, 0.4f), new Color(0.2f, 0.2f, 0.2f),
|
RuntimeHelper.SetColorBlock(inputField.Component, new Color(0.4f, 0.4f, 0.4f), new Color(0.2f, 0.2f, 0.2f),
|
||||||
new Color(0.08f, 0.08f, 0.08f));
|
new Color(0.08f, 0.08f, 0.08f));
|
||||||
UIFactory.SetLayoutElement(inputField.UIRoot, minHeight: 25);
|
UIFactory.SetLayoutElement(inputField.UIRoot, minHeight: 25);
|
||||||
//inputField.OnValueChanged += OnFilterInput;
|
//inputField.OnValueChanged += OnFilterInput;
|
||||||
@ -238,16 +239,27 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
|
|
||||||
refreshRow.SetActive(false);
|
refreshRow.SetActive(false);
|
||||||
|
|
||||||
|
// tree labels row
|
||||||
|
|
||||||
|
var labelsRow = UIFactory.CreateHorizontalGroup(toolbar, "LabelsRow", true, true, true, true, 2, new Vector4(2, 2, 2, 2));
|
||||||
|
UIFactory.SetLayoutElement(labelsRow, minHeight: 30, flexibleHeight: 0);
|
||||||
|
|
||||||
|
var nameLabel = UIFactory.CreateLabel(labelsRow, "NameLabel", "Name", TextAnchor.MiddleLeft, color: Color.grey);
|
||||||
|
UIFactory.SetLayoutElement(nameLabel.gameObject, flexibleWidth: 9999, minHeight: 25);
|
||||||
|
|
||||||
|
var indexLabel = UIFactory.CreateLabel(labelsRow, "IndexLabel", "Sibling Index", TextAnchor.MiddleLeft, fontSize: 12, color: Color.grey);
|
||||||
|
UIFactory.SetLayoutElement(indexLabel.gameObject, minWidth: 100, flexibleWidth: 0, minHeight: 25);
|
||||||
|
|
||||||
// Transform Tree
|
// Transform Tree
|
||||||
|
|
||||||
var scrollPool = UIFactory.CreateScrollPool<TransformCell>(m_uiRoot, "TransformTree", out GameObject scrollObj,
|
var scrollPool = UIFactory.CreateScrollPool<TransformCell>(uiRoot, "TransformTree", out GameObject scrollObj,
|
||||||
out GameObject scrollContent, new Color(0.11f, 0.11f, 0.11f));
|
out GameObject scrollContent, new Color(0.11f, 0.11f, 0.11f));
|
||||||
UIFactory.SetLayoutElement(scrollObj, flexibleHeight: 9999);
|
UIFactory.SetLayoutElement(scrollObj, flexibleHeight: 9999);
|
||||||
UIFactory.SetLayoutElement(scrollContent, flexibleHeight: 9999);
|
UIFactory.SetLayoutElement(scrollContent, flexibleHeight: 9999);
|
||||||
|
|
||||||
Tree = new TransformTree(scrollPool, GetRootEntries);
|
Tree = new TransformTree(scrollPool, GetRootEntries);
|
||||||
Tree.Init();
|
Tree.Init();
|
||||||
Tree.RefreshData(true, true);
|
Tree.RefreshData(true, true, true, false);
|
||||||
//scrollPool.Viewport.GetComponent<Mask>().enabled = false;
|
//scrollPool.Viewport.GetComponent<Mask>().enabled = false;
|
||||||
//UIRoot.GetComponent<Mask>().enabled = false;
|
//UIRoot.GetComponent<Mask>().enabled = false;
|
||||||
|
|
||||||
@ -255,7 +267,7 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
|
|
||||||
ConstructSceneLoader();
|
ConstructSceneLoader();
|
||||||
|
|
||||||
RuntimeProvider.Instance.StartCoroutine(TempFixCoro());
|
RuntimeHelper.StartCoroutine(TempFixCoro());
|
||||||
}
|
}
|
||||||
|
|
||||||
// To "fix" a strange FPS drop issue with MelonLoader.
|
// To "fix" a strange FPS drop issue with MelonLoader.
|
||||||
@ -312,7 +324,7 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
{
|
{
|
||||||
if (SceneHandler.WasAbleToGetScenesInBuild)
|
if (SceneHandler.WasAbleToGetScenesInBuild)
|
||||||
{
|
{
|
||||||
var sceneLoaderObj = UIFactory.CreateVerticalGroup(m_uiRoot, "SceneLoader", true, true, true, true);
|
var sceneLoaderObj = UIFactory.CreateVerticalGroup(uiRoot, "SceneLoader", true, true, true, true);
|
||||||
UIFactory.SetLayoutElement(sceneLoaderObj, minHeight: 25);
|
UIFactory.SetLayoutElement(sceneLoaderObj, minHeight: 25);
|
||||||
|
|
||||||
// Title
|
// Title
|
||||||
@ -328,7 +340,7 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
|
|
||||||
// Dropdown
|
// Dropdown
|
||||||
|
|
||||||
var allSceneDropObj = UIFactory.CreateDropdown(sceneLoaderObj, out allSceneDropdown, "", 14, null);
|
var allSceneDropObj = UIFactory.CreateDropdown(sceneLoaderObj, "SceneLoaderDropdown", out allSceneDropdown, "", 14, null);
|
||||||
UIFactory.SetLayoutElement(allSceneDropObj, minHeight: 25, minWidth: 150, flexibleWidth: 0, flexibleHeight: 0);
|
UIFactory.SetLayoutElement(allSceneDropObj, minHeight: 25, minWidth: 150, flexibleWidth: 0, flexibleHeight: 0);
|
||||||
|
|
||||||
RefreshSceneLoaderOptions(string.Empty);
|
RefreshSceneLoaderOptions(string.Empty);
|
||||||
@ -352,8 +364,8 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
};
|
};
|
||||||
|
|
||||||
var disabledColor = new Color(0.24f, 0.24f, 0.24f);
|
var disabledColor = new Color(0.24f, 0.24f, 0.24f);
|
||||||
RuntimeProvider.Instance.SetColorBlock(loadButton.Component, disabled: disabledColor);
|
RuntimeHelper.SetColorBlock(loadButton.Component, disabled: disabledColor);
|
||||||
RuntimeProvider.Instance.SetColorBlock(loadAdditiveButton.Component, disabled: disabledColor);
|
RuntimeHelper.SetColorBlock(loadAdditiveButton.Component, disabled: disabledColor);
|
||||||
|
|
||||||
loadButton.Component.interactable = false;
|
loadButton.Component.interactable = false;
|
||||||
loadAdditiveButton.Component.interactable = false;
|
loadAdditiveButton.Component.interactable = false;
|
||||||
|
@ -11,15 +11,13 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
{
|
{
|
||||||
public static class SceneHandler
|
public static class SceneHandler
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>The currently inspected Scene.</summary>
|
||||||
/// The currently inspected Scene.
|
|
||||||
/// </summary>
|
|
||||||
public static Scene? SelectedScene
|
public static Scene? SelectedScene
|
||||||
{
|
{
|
||||||
get => selectedScene;
|
get => selectedScene;
|
||||||
internal set
|
internal set
|
||||||
{
|
{
|
||||||
if (selectedScene != null && selectedScene == value)
|
if (selectedScene.HasValue && selectedScene == value)
|
||||||
return;
|
return;
|
||||||
selectedScene = value;
|
selectedScene = value;
|
||||||
OnInspectedSceneChanged?.Invoke((Scene)selectedScene);
|
OnInspectedSceneChanged?.Invoke((Scene)selectedScene);
|
||||||
@ -27,63 +25,39 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
}
|
}
|
||||||
private static Scene? selectedScene;
|
private static Scene? selectedScene;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>The GameObjects in the currently inspected scene.</summary>
|
||||||
/// The GameObjects in the currently inspected scene.
|
public static IEnumerable<GameObject> CurrentRootObjects { get; private set; } = new GameObject[0];
|
||||||
/// </summary>
|
|
||||||
public static GameObject[] CurrentRootObjects { get; private set; } = new GameObject[0];
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>All currently loaded Scenes.</summary>
|
||||||
/// All currently loaded Scenes.
|
public static List<Scene> LoadedScenes { get; private set; } = new();
|
||||||
/// </summary>
|
//private static HashSet<Scene> previousLoadedScenes;
|
||||||
public static List<Scene> LoadedScenes { get; private set; } = new List<Scene>();
|
|
||||||
private static HashSet<Scene> previousLoadedScenes;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>The names of all scenes in the build settings, if they could be retrieved.</summary>
|
||||||
/// The names of all scenes in the build settings, if they could be retrieved.
|
public static List<string> AllSceneNames { get; private set; } = new();
|
||||||
/// </summary>
|
|
||||||
public static readonly List<string> AllSceneNames = new List<string>();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>Invoked when the currently inspected Scene changes. The argument is the new scene.</summary>
|
||||||
/// Whether or not we successfuly retrieved the names of the scenes in the build settings.
|
|
||||||
/// </summary>
|
|
||||||
public static bool WasAbleToGetScenesInBuild { get; private set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Invoked when the currently inspected Scene changes. The argument is the new scene.
|
|
||||||
/// </summary>
|
|
||||||
public static event Action<Scene> OnInspectedSceneChanged;
|
public static event Action<Scene> OnInspectedSceneChanged;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>Invoked whenever the list of currently loaded Scenes changes. The argument contains all loaded scenes after the change.</summary>
|
||||||
/// Invoked whenever the list of currently loaded Scenes changes. The argument contains all loaded scenes after the change.
|
public static event Action<List<Scene>> OnLoadedScenesUpdated;
|
||||||
/// </summary>
|
|
||||||
public static event Action<List<Scene>> OnLoadedScenesChanged;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>Generally will be 2, unless DontDestroyExists == false, then this will be 1.</summary>
|
||||||
/// Equivalent to <see cref="SceneManager.sceneCount"/> + 2, to include 'DontDestroyOnLoad' and the 'None' scene.
|
internal static int DefaultSceneCount => 1 + (DontDestroyExists ? 1 : 0);
|
||||||
/// </summary>
|
|
||||||
public static int LoadedSceneCount => SceneManager.sceneCount + 2;
|
|
||||||
|
|
||||||
internal static Scene DontDestroyScene => DontDestroyMe.scene;
|
|
||||||
internal static int DontDestroyHandle => DontDestroyScene.handle;
|
|
||||||
|
|
||||||
internal static GameObject DontDestroyMe
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (!dontDestroyObject)
|
|
||||||
{
|
|
||||||
dontDestroyObject = new GameObject("DontDestroyMe");
|
|
||||||
GameObject.DontDestroyOnLoad(dontDestroyObject);
|
|
||||||
}
|
|
||||||
return dontDestroyObject;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private static GameObject dontDestroyObject;
|
|
||||||
|
|
||||||
|
/// <summary>Whether or not we are currently inspecting the "HideAndDontSave" asset scene.</summary>
|
||||||
public static bool InspectingAssetScene => SelectedScene.HasValue && SelectedScene.Value == default;
|
public static bool InspectingAssetScene => SelectedScene.HasValue && SelectedScene.Value == default;
|
||||||
|
|
||||||
|
/// <summary>Whether or not we successfuly retrieved the names of the scenes in the build settings.</summary>
|
||||||
|
public static bool WasAbleToGetScenesInBuild { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>Whether or not the "DontDestroyOnLoad" scene exists in this game.</summary>
|
||||||
|
public static bool DontDestroyExists { get; private set; }
|
||||||
|
|
||||||
internal static void Init()
|
internal static void Init()
|
||||||
{
|
{
|
||||||
|
// Check if the game has "DontDestroyOnLoad"
|
||||||
|
DontDestroyExists = Scene.GetNameInternal(-12) == "DontDestroyOnLoad";
|
||||||
|
|
||||||
// Try to get all scenes in the build settings. This may not work.
|
// Try to get all scenes in the build settings. This may not work.
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -110,22 +84,20 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
|
|
||||||
internal static void Update()
|
internal static void Update()
|
||||||
{
|
{
|
||||||
// check if the loaded scenes changed. always confirm DontDestroy / HideAndDontSave
|
// Inspected scene will exist if it's DontDestroyOnLoad or HideAndDontSave
|
||||||
int confirmedCount = 2;
|
bool inspectedExists =
|
||||||
bool inspectedExists = SelectedScene == DontDestroyScene || (SelectedScene.HasValue && SelectedScene.Value == default);
|
SelectedScene.HasValue
|
||||||
|
&& ((DontDestroyExists && SelectedScene.Value.handle == -12)
|
||||||
|
|| SelectedScene.Value.handle == -1);
|
||||||
|
|
||||||
LoadedScenes.Clear();
|
LoadedScenes.Clear();
|
||||||
|
|
||||||
for (int i = 0; i < SceneManager.sceneCount; i++)
|
for (int i = 0; i < SceneManager.sceneCount; i++)
|
||||||
{
|
{
|
||||||
Scene scene = SceneManager.GetSceneAt(i);
|
Scene scene = SceneManager.GetSceneAt(i);
|
||||||
if (scene == default || !scene.isLoaded)
|
if (scene == default || !scene.isLoaded || !scene.IsValid())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// If no changes yet, ensure the previous list contained the scene
|
|
||||||
if (previousLoadedScenes != null && previousLoadedScenes.Contains(scene))
|
|
||||||
confirmedCount++;
|
|
||||||
|
|
||||||
// If we have not yet confirmed inspectedExists, check if this scene is our currently inspected one.
|
// If we have not yet confirmed inspectedExists, check if this scene is our currently inspected one.
|
||||||
if (!inspectedExists && scene == SelectedScene)
|
if (!inspectedExists && scene == SelectedScene)
|
||||||
inspectedExists = true;
|
inspectedExists = true;
|
||||||
@ -133,27 +105,23 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
LoadedScenes.Add(scene);
|
LoadedScenes.Add(scene);
|
||||||
}
|
}
|
||||||
|
|
||||||
LoadedScenes.Add(DontDestroyScene);
|
if (DontDestroyExists)
|
||||||
LoadedScenes.Add(default);
|
LoadedScenes.Add(new Scene { m_Handle = -12 });
|
||||||
|
LoadedScenes.Add(new Scene { m_Handle = -1 });
|
||||||
bool anyChange = confirmedCount != LoadedScenes.Count;
|
|
||||||
|
|
||||||
previousLoadedScenes = new HashSet<Scene>(LoadedScenes);
|
|
||||||
|
|
||||||
// Default to first scene if none selected or previous selection no longer exists.
|
// Default to first scene if none selected or previous selection no longer exists.
|
||||||
if (!inspectedExists)
|
if (!inspectedExists)
|
||||||
SelectedScene = LoadedScenes.First();
|
SelectedScene = LoadedScenes.First();
|
||||||
|
|
||||||
// Notify on the list changing at all
|
// Notify on the list changing at all
|
||||||
if (anyChange)
|
OnLoadedScenesUpdated?.Invoke(LoadedScenes);
|
||||||
OnLoadedScenesChanged?.Invoke(LoadedScenes);
|
|
||||||
|
|
||||||
// Finally, update the root objects list.
|
// Finally, update the root objects list.
|
||||||
if (SelectedScene != null && ((Scene)SelectedScene).IsValid())
|
if (SelectedScene != null && ((Scene)SelectedScene).IsValid())
|
||||||
CurrentRootObjects = RuntimeProvider.Instance.GetRootGameObjects((Scene)SelectedScene);
|
CurrentRootObjects = RuntimeHelper.GetRootGameObjects((Scene)SelectedScene);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var allObjects = RuntimeProvider.Instance.FindObjectsOfTypeAll(typeof(GameObject));
|
var allObjects = RuntimeHelper.FindObjectsOfTypeAll(typeof(GameObject));
|
||||||
var objects = new List<GameObject>();
|
var objects = new List<GameObject>();
|
||||||
foreach (var obj in allObjects)
|
foreach (var obj in allObjects)
|
||||||
{
|
{
|
||||||
@ -161,7 +129,7 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
if (go.transform.parent == null && !go.scene.IsValid())
|
if (go.transform.parent == null && !go.scene.IsValid())
|
||||||
objects.Add(go);
|
objects.Add(go);
|
||||||
}
|
}
|
||||||
CurrentRootObjects = objects.ToArray();
|
CurrentRootObjects = objects;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,8 @@ using UnityEngine;
|
|||||||
using UnityEngine.SceneManagement;
|
using UnityEngine.SceneManagement;
|
||||||
using UnityExplorer.Runtime;
|
using UnityExplorer.Runtime;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
|
using UniverseLib.Input;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.ObjectExplorer
|
namespace UnityExplorer.ObjectExplorer
|
||||||
{
|
{
|
||||||
@ -34,26 +36,19 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
|
|
||||||
public static class SearchProvider
|
public static class SearchProvider
|
||||||
{
|
{
|
||||||
|
|
||||||
private static bool Filter(Scene scene, SceneFilter filter)
|
private static bool Filter(Scene scene, SceneFilter filter)
|
||||||
{
|
{
|
||||||
switch (filter)
|
return filter switch
|
||||||
{
|
{
|
||||||
case SceneFilter.Any:
|
SceneFilter.Any => true,
|
||||||
return true;
|
SceneFilter.DontDestroyOnLoad => scene.handle == -12,
|
||||||
case SceneFilter.DontDestroyOnLoad:
|
SceneFilter.HideAndDontSave => scene == default,
|
||||||
return scene == SceneHandler.DontDestroyScene;
|
SceneFilter.ActivelyLoaded => scene.buildIndex != -1,
|
||||||
case SceneFilter.HideAndDontSave:
|
_ => false,
|
||||||
return scene == default;
|
};
|
||||||
case SceneFilter.ActivelyLoaded:
|
|
||||||
return scene != SceneHandler.DontDestroyScene && scene != default;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static List<object> UnityObjectSearch(string input, string customTypeInput, SearchContext context,
|
internal static List<object> UnityObjectSearch(string input, string customTypeInput, ChildFilter childFilter, SceneFilter sceneFilter)
|
||||||
ChildFilter childFilter, SceneFilter sceneFilter)
|
|
||||||
{
|
{
|
||||||
var results = new List<object>();
|
var results = new List<object>();
|
||||||
|
|
||||||
@ -74,7 +69,7 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
if (searchType == null)
|
if (searchType == null)
|
||||||
searchType = typeof(UnityEngine.Object);
|
searchType = typeof(UnityEngine.Object);
|
||||||
|
|
||||||
var allObjects = RuntimeProvider.Instance.FindObjectsOfTypeAll(searchType);
|
var allObjects = RuntimeHelper.FindObjectsOfTypeAll(searchType);
|
||||||
|
|
||||||
// perform filter comparers
|
// perform filter comparers
|
||||||
|
|
||||||
@ -168,7 +163,7 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
"<instance>k__BackingField",
|
"<instance>k__BackingField",
|
||||||
};
|
};
|
||||||
|
|
||||||
internal static List<object> SingletonSearch(string input)
|
internal static List<object> InstanceSearch(string input)
|
||||||
{
|
{
|
||||||
var instances = new List<object>();
|
var instances = new List<object>();
|
||||||
|
|
||||||
@ -177,7 +172,7 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
nameFilter = input;
|
nameFilter = input;
|
||||||
|
|
||||||
var flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static;
|
var flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static;
|
||||||
|
|
||||||
foreach (var asm in AppDomain.CurrentDomain.GetAssemblies())
|
foreach (var asm in AppDomain.CurrentDomain.GetAssemblies())
|
||||||
{
|
{
|
||||||
// Search all non-static, non-enum classes.
|
// Search all non-static, non-enum classes.
|
||||||
@ -187,13 +182,13 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(nameFilter) && !type.FullName.ContainsIgnoreCase(nameFilter))
|
if (!string.IsNullOrEmpty(nameFilter) && !type.FullName.ContainsIgnoreCase(nameFilter))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
ReflectionUtility.FindSingleton(instanceNames, type, flags, instances);
|
ReflectionUtility.FindSingleton(instanceNames, type, flags, instances);
|
||||||
}
|
}
|
||||||
catch { }
|
catch { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return instances;
|
return instances;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,21 +2,11 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
|
||||||
using BF = System.Reflection.BindingFlags;
|
|
||||||
using System.Text;
|
|
||||||
using UnhollowerBaseLib;
|
|
||||||
using UnhollowerRuntimeLib;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.Events;
|
|
||||||
using UnityEngine.SceneManagement;
|
|
||||||
using System.Collections;
|
|
||||||
using UnityEngine.UI;
|
|
||||||
using UnityEngine.EventSystems;
|
|
||||||
|
|
||||||
namespace UnityExplorer.Runtime
|
namespace UnityExplorer.Runtime
|
||||||
{
|
{
|
||||||
public class Il2CppProvider : RuntimeHelper
|
public class Il2CppHelper : UERuntimeHelper
|
||||||
{
|
{
|
||||||
public override void SetupEvents()
|
public override void SetupEvents()
|
||||||
{
|
{
|
||||||
@ -41,7 +31,7 @@ namespace UnityExplorer.Runtime
|
|||||||
// These methods currently cause a crash in most il2cpp games,
|
// These methods currently cause a crash in most il2cpp games,
|
||||||
// even from doing "GetParameters()" on the MemberInfo.
|
// even from doing "GetParameters()" on the MemberInfo.
|
||||||
// Blacklisting until the issue is fixed in Unhollower.
|
// Blacklisting until the issue is fixed in Unhollower.
|
||||||
public static HashSet<string> defaultIl2CppBlacklist = new HashSet<string>
|
public static HashSet<string> defaultIl2CppBlacklist = new()
|
||||||
{
|
{
|
||||||
// These were deprecated a long time ago, still show up in some IL2CPP games for some reason
|
// These were deprecated a long time ago, still show up in some IL2CPP games for some reason
|
||||||
"UnityEngine.MonoBehaviour.allowPrefabModeInPlayMode",
|
"UnityEngine.MonoBehaviour.allowPrefabModeInPlayMode",
|
@ -1,20 +1,9 @@
|
|||||||
#if MONO
|
#if MONO
|
||||||
using System;
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Text;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.Events;
|
|
||||||
using UnityEngine.EventSystems;
|
|
||||||
using UnityEngine.SceneManagement;
|
|
||||||
using UnityEngine.UI;
|
|
||||||
using UnityExplorer;
|
|
||||||
|
|
||||||
namespace UnityExplorer.Runtime
|
namespace UnityExplorer.Runtime
|
||||||
{
|
{
|
||||||
public class MonoProvider : RuntimeHelper
|
public class MonoHelper : UERuntimeHelper
|
||||||
{
|
{
|
||||||
public override void SetupEvents()
|
public override void SetupEvents()
|
||||||
{
|
{
|
@ -13,16 +13,18 @@ using UniverseLib;
|
|||||||
|
|
||||||
namespace UnityExplorer.Runtime
|
namespace UnityExplorer.Runtime
|
||||||
{
|
{
|
||||||
public abstract class RuntimeHelper
|
// Not really that necessary anymore, can eventually just be refactored away into the few classes that use this class.
|
||||||
|
|
||||||
|
public abstract class UERuntimeHelper
|
||||||
{
|
{
|
||||||
public static RuntimeHelper Instance;
|
public static UERuntimeHelper Instance;
|
||||||
|
|
||||||
public static void Init()
|
public static void Init()
|
||||||
{
|
{
|
||||||
#if CPP
|
#if CPP
|
||||||
Instance = new Il2CppProvider();
|
Instance = new Il2CppHelper();
|
||||||
#else
|
#else
|
||||||
Instance = new MonoProvider();
|
Instance = new MonoHelper();
|
||||||
#endif
|
#endif
|
||||||
Instance.SetupEvents();
|
Instance.SetupEvents();
|
||||||
|
|
||||||
@ -35,9 +37,7 @@ namespace UnityExplorer.Runtime
|
|||||||
|
|
||||||
public abstract void SetupEvents();
|
public abstract void SetupEvents();
|
||||||
|
|
||||||
#region Reflection Blacklist
|
private static readonly HashSet<string> currentBlacklist = new();
|
||||||
|
|
||||||
private static readonly HashSet<string> currentBlacklist = new HashSet<string>();
|
|
||||||
|
|
||||||
public virtual string[] DefaultReflectionBlacklist => new string[0];
|
public virtual string[] DefaultReflectionBlacklist => new string[0];
|
||||||
|
|
||||||
@ -88,7 +88,5 @@ namespace UnityExplorer.Runtime
|
|||||||
|
|
||||||
return currentBlacklist.Contains(sig);
|
return currentBlacklist.Contains(sig);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
}
|
||||||
}
|
}
|
38
src/Runtime/UnityCrashPrevention.cs
Normal file
38
src/Runtime/UnityCrashPrevention.cs
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
using HarmonyLib;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityExplorer.CacheObject;
|
||||||
|
|
||||||
|
namespace UnityExplorer.Runtime
|
||||||
|
{
|
||||||
|
internal static class UnityCrashPrevention
|
||||||
|
{
|
||||||
|
internal static void Init()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ExplorerCore.Harmony.PatchAll(typeof(UnityCrashPrevention));
|
||||||
|
ExplorerCore.Log("Initialized UnityCrashPrevention.");
|
||||||
|
}
|
||||||
|
catch //(Exception ex)
|
||||||
|
{
|
||||||
|
//ExplorerCore.Log($"Exception setting up Canvas crash prevention patch: {ex}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// In Unity 2020 they introduced "Canvas.renderingDisplaySize".
|
||||||
|
// If you try to get the value on a Canvas which has a renderMode value of WorldSpace and no worldCamera set,
|
||||||
|
// the game will Crash (I think from Unity trying to read from null ptr).
|
||||||
|
[HarmonyPatch(typeof(Canvas), "renderingDisplaySize", MethodType.Getter)]
|
||||||
|
[HarmonyPrefix]
|
||||||
|
internal static void Prefix_Canvas_renderingDisplaySize(Canvas __instance)
|
||||||
|
{
|
||||||
|
if (__instance.renderMode == RenderMode.WorldSpace && !__instance.worldCamera)
|
||||||
|
throw new InvalidOperationException(
|
||||||
|
"Canvas is set to RenderMode.WorldSpace but not worldCamera is set, cannot get renderingDisplaySize.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -24,8 +24,12 @@ namespace UnityExplorer.Tests
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#region MONO
|
||||||
|
|
||||||
public static object LiterallyAnything = null;
|
public static object LiterallyAnything = null;
|
||||||
|
|
||||||
|
public static string Exception => throw new Exception("This is a test.");
|
||||||
|
|
||||||
// Test enumerables
|
// Test enumerables
|
||||||
public static int[,,] MultiDimensionalArray = new int[45, 45, 45];
|
public static int[,,] MultiDimensionalArray = new int[45, 45, 45];
|
||||||
public static List<object> ListOfInts;
|
public static List<object> ListOfInts;
|
||||||
@ -90,12 +94,12 @@ namespace UnityExplorer.Tests
|
|||||||
ExplorerCore.Log($"Test3 {typeof(T).FullName}");
|
ExplorerCore.Log($"Test3 {typeof(T).FullName}");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void TestArgumentParse(string _string,
|
public static void TestArgumentParse(string _string,
|
||||||
int integer,
|
int integer,
|
||||||
Color color,
|
Color color,
|
||||||
CameraClearFlags flags,
|
CameraClearFlags flags,
|
||||||
Vector3 vector,
|
Vector3 vector,
|
||||||
Quaternion quaternion,
|
Quaternion quaternion,
|
||||||
object obj,
|
object obj,
|
||||||
Type type,
|
Type type,
|
||||||
GameObject go)
|
GameObject go)
|
||||||
@ -145,23 +149,25 @@ namespace UnityExplorer.Tests
|
|||||||
ExplorerCore.Log("Finished TestClass Init_Mono");
|
ExplorerCore.Log("Finished TestClass Init_Mono");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
#if CPP
|
#if CPP
|
||||||
|
public static Il2CppSystem.Collections.Generic.Dictionary<string, string> IL2CPP_Dict;
|
||||||
|
public static Il2CppSystem.Collections.Generic.HashSet<string> IL2CPP_HashSet;
|
||||||
public static Il2CppSystem.Collections.Generic.List<string> IL2CPP_ListString;
|
public static Il2CppSystem.Collections.Generic.List<string> IL2CPP_ListString;
|
||||||
|
public static Il2CppSystem.Collections.Hashtable IL2CPP_HashTable;
|
||||||
public static List<Il2CppSystem.Object> IL2CPP_listOfBoxedObjects;
|
public static List<Il2CppSystem.Object> IL2CPP_listOfBoxedObjects;
|
||||||
public static Il2CppStructArray<int> IL2CPP_structArray;
|
public static Il2CppStructArray<int> IL2CPP_structArray;
|
||||||
public static Il2CppReferenceArray<Il2CppSystem.Object> IL2CPP_ReferenceArray;
|
public static Il2CppReferenceArray<Il2CppSystem.Object> IL2CPP_ReferenceArray;
|
||||||
public static Il2CppSystem.Collections.IDictionary IL2CPP_IDict;
|
public static Il2CppSystem.Collections.IDictionary IL2CPP_IDict;
|
||||||
public static Il2CppSystem.Collections.IList IL2CPP_IList;
|
public static Il2CppSystem.Collections.IList IL2CPP_IList;
|
||||||
public static Dictionary<Il2CppSystem.String, Il2CppSystem.Object> CppBoxedDict;
|
public static Dictionary<Il2CppSystem.Object, Il2CppSystem.Object> IL2CPP_BoxedDict;
|
||||||
|
|
||||||
public static Il2CppSystem.Collections.Generic.HashSet<string> IL2CPP_HashSet;
|
public static Il2CppSystem.Object IL2CPP_BoxedInt;
|
||||||
public static Il2CppSystem.Collections.Generic.Dictionary<string, string> IL2CPP_Dict;
|
public static Il2CppSystem.Int32 IL2CPP_Int;
|
||||||
public static Il2CppSystem.Collections.Hashtable IL2CPP_HashTable;
|
public static Il2CppSystem.Decimal IL2CPP_Decimal;
|
||||||
public static Il2CppSystem.Object cppBoxedInt;
|
public static Il2CppSystem.Object IL2CPP_DecimalBoxed;
|
||||||
public static Il2CppSystem.Int32 cppInt;
|
public static Il2CppSystem.Object IL2CPP_Vector3Boxed;
|
||||||
public static Il2CppSystem.Decimal cppDecimal;
|
|
||||||
public static Il2CppSystem.Object cppDecimalBoxed;
|
|
||||||
public static Il2CppSystem.Object cppVector3Boxed;
|
|
||||||
public static string IL2CPP_systemString = "Test";
|
public static string IL2CPP_systemString = "Test";
|
||||||
public static Il2CppSystem.Object IL2CPP_objectString = "string boxed as cpp object";
|
public static Il2CppSystem.Object IL2CPP_objectString = "string boxed as cpp object";
|
||||||
public static Il2CppSystem.String IL2CPP_il2cppString = "string boxed as cpp string";
|
public static Il2CppSystem.String IL2CPP_il2cppString = "string boxed as cpp string";
|
||||||
@ -175,6 +181,11 @@ namespace UnityExplorer.Tests
|
|||||||
IL2CPP_Dict.Add("key2", "value2");
|
IL2CPP_Dict.Add("key2", "value2");
|
||||||
IL2CPP_Dict.Add("key3", "value3");
|
IL2CPP_Dict.Add("key3", "value3");
|
||||||
|
|
||||||
|
ExplorerCore.Log($"IL2CPP 6: Il2Cpp HashSet of strings");
|
||||||
|
IL2CPP_HashSet = new Il2CppSystem.Collections.Generic.HashSet<string>();
|
||||||
|
IL2CPP_HashSet.Add("one");
|
||||||
|
IL2CPP_HashSet.Add("two");
|
||||||
|
|
||||||
ExplorerCore.Log($"IL2CPP 2: Il2Cpp Hashtable");
|
ExplorerCore.Log($"IL2CPP 2: Il2Cpp Hashtable");
|
||||||
IL2CPP_HashTable = new Il2CppSystem.Collections.Hashtable();
|
IL2CPP_HashTable = new Il2CppSystem.Collections.Hashtable();
|
||||||
IL2CPP_HashTable.Add("key1", "value1");
|
IL2CPP_HashTable.Add("key1", "value1");
|
||||||
@ -197,17 +208,13 @@ namespace UnityExplorer.Tests
|
|||||||
IL2CPP_ListString.Add("hello,");
|
IL2CPP_ListString.Add("hello,");
|
||||||
IL2CPP_ListString.Add("world!");
|
IL2CPP_ListString.Add("world!");
|
||||||
|
|
||||||
ExplorerCore.Log($"IL2CPP 6: Il2Cpp HashSet of strings");
|
|
||||||
IL2CPP_HashSet = new Il2CppSystem.Collections.Generic.HashSet<string>();
|
|
||||||
IL2CPP_HashSet.Add("one");
|
|
||||||
IL2CPP_HashSet.Add("two");
|
|
||||||
|
|
||||||
ExplorerCore.Log($"IL2CPP 7: Dictionary of Il2Cpp String and Il2Cpp Object");
|
ExplorerCore.Log($"IL2CPP 7: Dictionary of Il2Cpp String and Il2Cpp Object");
|
||||||
CppBoxedDict = new Dictionary<Il2CppSystem.String, Il2CppSystem.Object>();
|
IL2CPP_BoxedDict = new();
|
||||||
CppBoxedDict.Add("1", new Il2CppSystem.Int32 { m_value = 1 }.BoxIl2CppObject());
|
IL2CPP_BoxedDict[(Il2CppSystem.String)"one"] = new Il2CppSystem.Int32 { m_value = 1 }.BoxIl2CppObject();
|
||||||
CppBoxedDict.Add("2", new Il2CppSystem.Int32 { m_value = 2 }.BoxIl2CppObject());
|
IL2CPP_BoxedDict[(Il2CppSystem.String)"two"] = new Il2CppSystem.Int32 { m_value = 2 }.BoxIl2CppObject();
|
||||||
CppBoxedDict.Add("3", new Il2CppSystem.Int32 { m_value = 3 }.BoxIl2CppObject());
|
IL2CPP_BoxedDict[(Il2CppSystem.String)"three"] = new Il2CppSystem.Int32 { m_value = 3 }.BoxIl2CppObject();
|
||||||
CppBoxedDict.Add("4", new Il2CppSystem.Int32 { m_value = 4 }.BoxIl2CppObject());
|
IL2CPP_BoxedDict[(Il2CppSystem.String)"four"] = new Il2CppSystem.Int32 { m_value = 4 }.BoxIl2CppObject();
|
||||||
|
|
||||||
ExplorerCore.Log($"IL2CPP 8: List of boxed Il2Cpp Objects");
|
ExplorerCore.Log($"IL2CPP 8: List of boxed Il2Cpp Objects");
|
||||||
IL2CPP_listOfBoxedObjects = new List<Il2CppSystem.Object>();
|
IL2CPP_listOfBoxedObjects = new List<Il2CppSystem.Object>();
|
||||||
@ -248,14 +255,15 @@ namespace UnityExplorer.Tests
|
|||||||
IL2CPP_ReferenceArray[2] = (Il2CppSystem.String)"whats up";
|
IL2CPP_ReferenceArray[2] = (Il2CppSystem.String)"whats up";
|
||||||
|
|
||||||
ExplorerCore.Log($"IL2CPP 11: Misc il2cpp members");
|
ExplorerCore.Log($"IL2CPP 11: Misc il2cpp members");
|
||||||
cppBoxedInt = new Il2CppSystem.Int32() { m_value = 5 }.BoxIl2CppObject();
|
IL2CPP_BoxedInt = new Il2CppSystem.Int32() { m_value = 5 }.BoxIl2CppObject();
|
||||||
cppInt = new Il2CppSystem.Int32 { m_value = 420 };
|
IL2CPP_Int = new Il2CppSystem.Int32 { m_value = 420 };
|
||||||
cppDecimal = new Il2CppSystem.Decimal(1f);
|
IL2CPP_Decimal = new Il2CppSystem.Decimal(1f);
|
||||||
cppDecimalBoxed = new Il2CppSystem.Decimal(1f).BoxIl2CppObject();
|
IL2CPP_DecimalBoxed = new Il2CppSystem.Decimal(1f).BoxIl2CppObject();
|
||||||
cppVector3Boxed = Vector3.down.BoxIl2CppObject();
|
IL2CPP_Vector3Boxed = Vector3.down.BoxIl2CppObject();
|
||||||
|
|
||||||
ExplorerCore.Log($"Finished Init_Il2Cpp");
|
ExplorerCore.Log($"Finished Init_Il2Cpp");
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
83
src/UI/DisplayManager.cs
Normal file
83
src/UI/DisplayManager.cs
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityExplorer.Config;
|
||||||
|
using UniverseLib;
|
||||||
|
using UniverseLib.Input;
|
||||||
|
|
||||||
|
namespace UnityExplorer.UI
|
||||||
|
{
|
||||||
|
public static class DisplayManager
|
||||||
|
{
|
||||||
|
public static int ActiveDisplayIndex { get; private set; }
|
||||||
|
public static Display ActiveDisplay => Display.displays[ActiveDisplayIndex];
|
||||||
|
|
||||||
|
public static int Width => ActiveDisplay.renderingWidth;
|
||||||
|
public static int Height => ActiveDisplay.renderingHeight;
|
||||||
|
|
||||||
|
public static Vector3 MousePosition => Application.isEditor
|
||||||
|
? InputManager.MousePosition
|
||||||
|
: Display.RelativeMouseAt(InputManager.MousePosition);
|
||||||
|
|
||||||
|
public static bool MouseInTargetDisplay => MousePosition.z == ActiveDisplayIndex;
|
||||||
|
|
||||||
|
private static Camera canvasCamera;
|
||||||
|
|
||||||
|
internal static void Init()
|
||||||
|
{
|
||||||
|
SetDisplay(ConfigManager.Target_Display.Value);
|
||||||
|
ConfigManager.Target_Display.OnValueChanged += SetDisplay;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void SetDisplay(int display)
|
||||||
|
{
|
||||||
|
if (ActiveDisplayIndex == display)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (Display.displays.Length <= display)
|
||||||
|
{
|
||||||
|
ExplorerCore.LogWarning($"Cannot set display index to {display} as there are not enough monitors connected!");
|
||||||
|
|
||||||
|
if (ConfigManager.Target_Display.Value == display)
|
||||||
|
ConfigManager.Target_Display.Value = 0;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ActiveDisplayIndex = display;
|
||||||
|
ActiveDisplay.Activate();
|
||||||
|
|
||||||
|
UIManager.UICanvas.targetDisplay = display;
|
||||||
|
|
||||||
|
// ensure a camera is targeting the display
|
||||||
|
if (!Camera.main || Camera.main.targetDisplay != display)
|
||||||
|
{
|
||||||
|
if (!canvasCamera)
|
||||||
|
{
|
||||||
|
canvasCamera = new GameObject("UnityExplorer_CanvasCamera").AddComponent<Camera>();
|
||||||
|
GameObject.DontDestroyOnLoad(canvasCamera.gameObject);
|
||||||
|
canvasCamera.hideFlags = HideFlags.HideAndDontSave;
|
||||||
|
}
|
||||||
|
canvasCamera.targetDisplay = display;
|
||||||
|
}
|
||||||
|
|
||||||
|
RuntimeHelper.StartCoroutine(FixPanels());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IEnumerator FixPanels()
|
||||||
|
{
|
||||||
|
yield return null;
|
||||||
|
yield return null;
|
||||||
|
|
||||||
|
foreach (var panel in UIManager.UIPanels.Values)
|
||||||
|
{
|
||||||
|
panel.EnsureValidSize();
|
||||||
|
panel.EnsureValidPosition();
|
||||||
|
panel.Dragger.OnEndResize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -27,7 +27,7 @@ namespace UnityExplorer.UI
|
|||||||
_currentNotification = message;
|
_currentNotification = message;
|
||||||
_timeOfLastNotification = Time.realtimeSinceStartup;
|
_timeOfLastNotification = Time.realtimeSinceStartup;
|
||||||
|
|
||||||
popupLabel.transform.localPosition = UIManager.UIRootRect.InverseTransformPoint(InputManager.MousePosition) + (Vector3.up * 25);
|
popupLabel.transform.localPosition = UIManager.UIRootRect.InverseTransformPoint(DisplayManager.MousePosition) + (Vector3.up * 25);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Update()
|
public static void Update()
|
||||||
|
@ -11,6 +11,9 @@ using UnityExplorer.UI.Panels;
|
|||||||
using UniverseLib.UI.Widgets;
|
using UniverseLib.UI.Widgets;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
|
using UniverseLib.UI.Widgets.ButtonList;
|
||||||
|
using UniverseLib.UI.Widgets.ScrollView;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Widgets.AutoComplete
|
namespace UnityExplorer.UI.Widgets.AutoComplete
|
||||||
{
|
{
|
||||||
@ -27,17 +30,17 @@ namespace UnityExplorer.UI.Widgets.AutoComplete
|
|||||||
public override int MinWidth => -1;
|
public override int MinWidth => -1;
|
||||||
public override int MinHeight => -1;
|
public override int MinHeight => -1;
|
||||||
|
|
||||||
public override bool CanDragAndResize => false;
|
public override bool CanDragAndResize => true;
|
||||||
public override bool ShouldSaveActiveState => false;
|
public override bool ShouldSaveActiveState => false;
|
||||||
public override bool NavButtonWanted => false;
|
public override bool NavButtonWanted => false;
|
||||||
|
|
||||||
public static ISuggestionProvider CurrentHandler { get; private set; }
|
public static ISuggestionProvider CurrentHandler { get; private set; }
|
||||||
|
|
||||||
public static ButtonListHandler<Suggestion, ButtonCell> dataHandler;
|
public static ButtonListHandler<Suggestion, ButtonCell> buttonListDataHandler;
|
||||||
public static ScrollPool<ButtonCell> scrollPool;
|
public static ScrollPool<ButtonCell> scrollPool;
|
||||||
private static GameObject navigationTipRow;
|
private static GameObject navigationTipRow;
|
||||||
|
|
||||||
private static List<Suggestion> Suggestions = new List<Suggestion>();
|
private static List<Suggestion> Suggestions = new();
|
||||||
private static int SelectedIndex = 0;
|
private static int SelectedIndex = 0;
|
||||||
|
|
||||||
public static Suggestion SelectedSuggestion => Suggestions[SelectedIndex];
|
public static Suggestion SelectedSuggestion => Suggestions[SelectedIndex];
|
||||||
@ -79,7 +82,7 @@ namespace UnityExplorer.UI.Widgets.AutoComplete
|
|||||||
{
|
{
|
||||||
base.UIRoot.SetActive(true);
|
base.UIRoot.SetActive(true);
|
||||||
base.UIRoot.transform.SetAsLastSibling();
|
base.UIRoot.transform.SetAsLastSibling();
|
||||||
dataHandler.RefreshData();
|
buttonListDataHandler.RefreshData();
|
||||||
scrollPool.Refresh(true, true);
|
scrollPool.Refresh(true, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -213,10 +216,10 @@ namespace UnityExplorer.UI.Widgets.AutoComplete
|
|||||||
scrollPool.Content.anchoredPosition = pos;
|
scrollPool.Content.anchoredPosition = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
RuntimeProvider.Instance.SetColorBlock(cell.Button.Component, selectedSuggestionColor);
|
RuntimeHelper.SetColorBlock(cell.Button.Component, selectedSuggestionColor);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
RuntimeProvider.Instance.SetColorBlock(cell.Button.Component, inactiveSuggestionColor);
|
RuntimeHelper.SetColorBlock(cell.Button.Component, inactiveSuggestionColor);
|
||||||
|
|
||||||
setFirstCell = true;
|
setFirstCell = true;
|
||||||
}
|
}
|
||||||
@ -247,13 +250,13 @@ namespace UnityExplorer.UI.Widgets.AutoComplete
|
|||||||
Vector3 caretPos = textGen.characters[caretIdx].cursorPos;
|
Vector3 caretPos = textGen.characters[caretIdx].cursorPos;
|
||||||
// transform to world point
|
// transform to world point
|
||||||
caretPos = input.UIRoot.transform.TransformPoint(caretPos);
|
caretPos = input.UIRoot.transform.TransformPoint(caretPos);
|
||||||
caretPos += new Vector3(input.Rect.rect.width * 0.5f, -(input.Rect.rect.height * 0.5f), 0);
|
caretPos += new Vector3(input.Transform.rect.width * 0.5f, -(input.Transform.rect.height * 0.5f), 0);
|
||||||
|
|
||||||
uiRoot.transform.position = new Vector3(caretPos.x + 10, caretPos.y - 30, 0);
|
uiRoot.transform.position = new Vector3(caretPos.x + 10, caretPos.y - 30, 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
uiRoot.transform.position = input.Rect.position + new Vector3(-(input.Rect.rect.width / 2) + 10, -20, 0);
|
uiRoot.transform.position = input.Transform.position + new Vector3(-(input.Transform.rect.width / 2) + 10, -20, 0);
|
||||||
//var textGen = input.Component.textComponent.cachedTextGenerator;
|
//var textGen = input.Component.textComponent.cachedTextGenerator;
|
||||||
//var pos = input.UIRoot.transform.TransformPoint(textGen.characters[0].cursorPos);
|
//var pos = input.UIRoot.transform.TransformPoint(textGen.characters[0].cursorPos);
|
||||||
//uiRoot.transform.position = new Vector3(pos.x + 10, pos.y - 20, 0);
|
//uiRoot.transform.position = new Vector3(pos.x + 10, pos.y - 20, 0);
|
||||||
@ -291,36 +294,49 @@ namespace UnityExplorer.UI.Widgets.AutoComplete
|
|||||||
|
|
||||||
// UI Construction
|
// UI Construction
|
||||||
|
|
||||||
|
const float MIN_X = 0.42f;
|
||||||
|
const float MAX_Y = 0.6f;
|
||||||
|
|
||||||
protected internal override void DoSetDefaultPosAndAnchors()
|
protected internal override void DoSetDefaultPosAndAnchors()
|
||||||
{
|
{
|
||||||
Rect.pivot = new Vector2(0f, 1f);
|
Rect.pivot = new Vector2(0f, 1f);
|
||||||
Rect.anchorMin = new Vector2(0.42f, 0.4f);
|
Rect.anchorMin = new Vector2(MIN_X, 0.4f);
|
||||||
Rect.anchorMax = new Vector2(0.68f, 0.6f);
|
Rect.anchorMax = new Vector2(0.68f, MAX_Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnFinishResize(RectTransform panel)
|
||||||
|
{
|
||||||
|
float xDiff = panel.anchorMin.x - MIN_X;
|
||||||
|
float yDiff = panel.anchorMax.y - MAX_Y;
|
||||||
|
|
||||||
|
if (xDiff != 0 || yDiff != 0)
|
||||||
|
{
|
||||||
|
panel.anchorMin = new(MIN_X, panel.anchorMin.y - yDiff);
|
||||||
|
panel.anchorMax = new(panel.anchorMax.x - xDiff, MAX_Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
base.OnFinishResize(panel);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void ConstructPanelContent()
|
public override void ConstructPanelContent()
|
||||||
{
|
{
|
||||||
dataHandler = new ButtonListHandler<Suggestion, ButtonCell>(scrollPool, GetEntries, SetCell, ShouldDisplay, OnCellClicked);
|
// hide the titlebar
|
||||||
|
this.TitleBar.gameObject.SetActive(false);
|
||||||
|
|
||||||
scrollPool = UIFactory.CreateScrollPool<ButtonCell>(this.content, "AutoCompleter", out GameObject scrollObj,
|
buttonListDataHandler = new ButtonListHandler<Suggestion, ButtonCell>(scrollPool, GetEntries, SetCell, ShouldDisplay, OnCellClicked);
|
||||||
|
|
||||||
|
scrollPool = UIFactory.CreateScrollPool<ButtonCell>(this.uiContent, "AutoCompleter", out GameObject scrollObj,
|
||||||
out GameObject scrollContent);
|
out GameObject scrollContent);
|
||||||
scrollPool.Initialize(dataHandler);
|
scrollPool.Initialize(buttonListDataHandler);
|
||||||
UIFactory.SetLayoutElement(scrollObj, flexibleHeight: 9999);
|
UIFactory.SetLayoutElement(scrollObj, flexibleHeight: 9999);
|
||||||
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(scrollContent, true, false, true, false);
|
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(scrollContent, true, false, true, false);
|
||||||
|
|
||||||
navigationTipRow = UIFactory.CreateHorizontalGroup(this.content, "BottomRow", true, true, true, true, 0, new Vector4(2, 2, 2, 2));
|
navigationTipRow = UIFactory.CreateHorizontalGroup(this.uiContent, "BottomRow", true, true, true, true, 0, new Vector4(2, 2, 2, 2));
|
||||||
UIFactory.SetLayoutElement(navigationTipRow, minHeight: 20, flexibleWidth: 9999);
|
UIFactory.SetLayoutElement(navigationTipRow, minHeight: 20, flexibleWidth: 9999);
|
||||||
UIFactory.CreateLabel(navigationTipRow, "HelpText", "Up/Down to select, Enter to use, Esc to close",
|
UIFactory.CreateLabel(navigationTipRow, "HelpText", "Up/Down to select, Enter to use, Esc to close",
|
||||||
TextAnchor.MiddleLeft, Color.grey, false, 13);
|
TextAnchor.MiddleLeft, Color.grey, false, 13);
|
||||||
|
|
||||||
UIRoot.SetActive(false);
|
UIRoot.SetActive(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void DoSaveToConfigElement()
|
|
||||||
{
|
|
||||||
// not savable
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string GetSaveDataFromConfigManager() => null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -11,6 +11,7 @@ using UnityExplorer.CSConsole;
|
|||||||
using UnityExplorer.UI.Widgets;
|
using UnityExplorer.UI.Widgets;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
|
using UniverseLib.UI.Models;
|
||||||
using UniverseLib.UI.Widgets;
|
using UniverseLib.UI.Widgets;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Panels
|
namespace UnityExplorer.UI.Panels
|
||||||
@ -55,15 +56,6 @@ namespace UnityExplorer.UI.Panels
|
|||||||
ConsoleController.Update();
|
ConsoleController.Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Saving
|
|
||||||
|
|
||||||
public override void DoSaveToConfigElement()
|
|
||||||
{
|
|
||||||
ConfigManager.CSConsoleData.Value = this.ToSaveData();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string GetSaveDataFromConfigManager() => ConfigManager.CSConsoleData.Value;
|
|
||||||
|
|
||||||
// UI Construction
|
// UI Construction
|
||||||
|
|
||||||
public override void OnFinishResize(RectTransform panel)
|
public override void OnFinishResize(RectTransform panel)
|
||||||
@ -83,7 +75,7 @@ namespace UnityExplorer.UI.Panels
|
|||||||
{
|
{
|
||||||
// Tools Row
|
// Tools Row
|
||||||
|
|
||||||
var toolsRow = UIFactory.CreateHorizontalGroup(this.content, "ToggleRow", false, false, true, true, 5, new Vector4(8, 8, 10, 5),
|
var toolsRow = UIFactory.CreateHorizontalGroup(this.uiContent, "ToggleRow", false, false, true, true, 5, new Vector4(8, 8, 10, 5),
|
||||||
default, TextAnchor.MiddleLeft);
|
default, TextAnchor.MiddleLeft);
|
||||||
UIFactory.SetLayoutElement(toolsRow, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999);
|
UIFactory.SetLayoutElement(toolsRow, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999);
|
||||||
|
|
||||||
@ -101,7 +93,7 @@ namespace UnityExplorer.UI.Panels
|
|||||||
|
|
||||||
// Help dropdown
|
// Help dropdown
|
||||||
|
|
||||||
var helpDrop = UIFactory.CreateDropdown(toolsRow, out var dropdown, "Help", 14, null);
|
var helpDrop = UIFactory.CreateDropdown(toolsRow, "HelpDropdown", out var dropdown, "Help", 14, null);
|
||||||
UIFactory.SetLayoutElement(helpDrop, minHeight: 25, minWidth: 100);
|
UIFactory.SetLayoutElement(helpDrop, minHeight: 25, minWidth: 100);
|
||||||
HelpDropdown = dropdown;
|
HelpDropdown = dropdown;
|
||||||
HelpDropdown.onValueChanged.AddListener((int val) => { this.OnHelpDropdownChanged?.Invoke(val); });
|
HelpDropdown.onValueChanged.AddListener((int val) => { this.OnHelpDropdownChanged?.Invoke(val); });
|
||||||
@ -132,7 +124,7 @@ namespace UnityExplorer.UI.Panels
|
|||||||
|
|
||||||
// Console Input
|
// Console Input
|
||||||
|
|
||||||
var inputArea = UIFactory.CreateUIObject("InputGroup", content);
|
var inputArea = UIFactory.CreateUIObject("InputGroup", uiContent);
|
||||||
UIFactory.SetLayoutElement(inputArea, flexibleWidth: 9999, flexibleHeight: 9999);
|
UIFactory.SetLayoutElement(inputArea, flexibleWidth: 9999, flexibleHeight: 9999);
|
||||||
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(inputArea, false, true, true, true);
|
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(inputArea, false, true, true, true);
|
||||||
inputArea.AddComponent<Image>().color = Color.white;
|
inputArea.AddComponent<Image>().color = Color.white;
|
||||||
@ -199,7 +191,7 @@ namespace UnityExplorer.UI.Panels
|
|||||||
Input.PlaceholderText.font = UniversalUI.ConsoleFont;
|
Input.PlaceholderText.font = UniversalUI.ConsoleFont;
|
||||||
HighlightText.font = UniversalUI.ConsoleFont;
|
HighlightText.font = UniversalUI.ConsoleFont;
|
||||||
|
|
||||||
RuntimeProvider.Instance.StartCoroutine(DelayedLayoutSetup());
|
RuntimeHelper.StartCoroutine(DelayedLayoutSetup());
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerator DelayedLayoutSetup()
|
private IEnumerator DelayedLayoutSetup()
|
||||||
@ -210,8 +202,8 @@ namespace UnityExplorer.UI.Panels
|
|||||||
|
|
||||||
public void SetInputLayout()
|
public void SetInputLayout()
|
||||||
{
|
{
|
||||||
Input.Rect.offsetMin = new Vector2(52, Input.Rect.offsetMin.y);
|
Input.Transform.offsetMin = new Vector2(52, Input.Transform.offsetMin.y);
|
||||||
Input.Rect.offsetMax = new Vector2(2, Input.Rect.offsetMax.y);
|
Input.Transform.offsetMax = new Vector2(2, Input.Transform.offsetMax.y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ using UniverseLib;
|
|||||||
using UniverseLib.Input;
|
using UniverseLib.Input;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
using UniverseLib.UI.Widgets;
|
using UniverseLib.UI.Widgets;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Panels
|
namespace UnityExplorer.UI.Panels
|
||||||
{
|
{
|
||||||
@ -27,8 +28,6 @@ namespace UnityExplorer.UI.Panels
|
|||||||
public override bool NavButtonWanted => true;
|
public override bool NavButtonWanted => true;
|
||||||
public override bool ShouldSaveActiveState => true;
|
public override bool ShouldSaveActiveState => true;
|
||||||
public override bool ShowByDefault => true;
|
public override bool ShowByDefault => true;
|
||||||
public override string GetSaveDataFromConfigManager() => ConfigManager.ClipboardData.Value;
|
|
||||||
public override void DoSaveToConfigElement() => ConfigManager.ClipboardData.Value = this.ToSaveData();
|
|
||||||
|
|
||||||
private static Text CurrentPasteLabel;
|
private static Text CurrentPasteLabel;
|
||||||
|
|
||||||
@ -90,7 +89,7 @@ namespace UnityExplorer.UI.Panels
|
|||||||
|
|
||||||
// Actual panel content
|
// Actual panel content
|
||||||
|
|
||||||
var firstRow = UIFactory.CreateHorizontalGroup(UIRoot, "FirstRow", false, false, true, true, 5, new(2,2,2,2), new(1,1,1,0));
|
var firstRow = UIFactory.CreateHorizontalGroup(uiContent, "FirstRow", false, false, true, true, 5, new(2,2,2,2), new(1,1,1,0));
|
||||||
UIFactory.SetLayoutElement(firstRow, minHeight: 25, flexibleWidth: 999);
|
UIFactory.SetLayoutElement(firstRow, minHeight: 25, flexibleWidth: 999);
|
||||||
|
|
||||||
// Title for "Current Paste:"
|
// Title for "Current Paste:"
|
||||||
@ -103,7 +102,7 @@ namespace UnityExplorer.UI.Panels
|
|||||||
clearButton.OnClick += () => Copy(null);
|
clearButton.OnClick += () => Copy(null);
|
||||||
|
|
||||||
// Current Paste info row
|
// Current Paste info row
|
||||||
var currentPasteHolder = UIFactory.CreateHorizontalGroup(UIRoot, "SecondRow", false, false, true, true, 0,
|
var currentPasteHolder = UIFactory.CreateHorizontalGroup(uiContent, "SecondRow", false, false, true, true, 0,
|
||||||
new(2, 2, 2, 2), childAlignment: TextAnchor.UpperCenter);
|
new(2, 2, 2, 2), childAlignment: TextAnchor.UpperCenter);
|
||||||
|
|
||||||
// Actual current paste info label
|
// Actual current paste info label
|
||||||
|
@ -9,7 +9,9 @@ using UnityExplorer.Hooks;
|
|||||||
using UnityExplorer.UI.Widgets;
|
using UnityExplorer.UI.Widgets;
|
||||||
using UnityExplorer.UI.Widgets.AutoComplete;
|
using UnityExplorer.UI.Widgets.AutoComplete;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
|
using UniverseLib.UI.Models;
|
||||||
using UniverseLib.UI.Widgets;
|
using UniverseLib.UI.Widgets;
|
||||||
|
using UniverseLib.UI.Widgets.ScrollView;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Panels
|
namespace UnityExplorer.UI.Panels
|
||||||
{
|
{
|
||||||
@ -46,10 +48,6 @@ namespace UnityExplorer.UI.Panels
|
|||||||
public Text EditorInputText { get; private set; }
|
public Text EditorInputText { get; private set; }
|
||||||
public Text EditorHighlightText { get; private set; }
|
public Text EditorHighlightText { get; private set; }
|
||||||
|
|
||||||
public override string GetSaveDataFromConfigManager() => ConfigManager.HookManagerData.Value;
|
|
||||||
|
|
||||||
public override void DoSaveToConfigElement() => ConfigManager.HookManagerData.Value = this.ToSaveData();
|
|
||||||
|
|
||||||
private void OnClassInputAddClicked()
|
private void OnClassInputAddClicked()
|
||||||
{
|
{
|
||||||
HookManager.Instance.OnClassSelectedForHooks(this.classSelectorInputField.Text);
|
HookManager.Instance.OnClassSelectedForHooks(this.classSelectorInputField.Text);
|
||||||
@ -85,7 +83,7 @@ namespace UnityExplorer.UI.Panels
|
|||||||
{
|
{
|
||||||
// ~~~~~~~~~ Active hooks scroll pool
|
// ~~~~~~~~~ Active hooks scroll pool
|
||||||
|
|
||||||
currentHooksPanel = UIFactory.CreateUIObject("CurrentHooksPanel", this.content);
|
currentHooksPanel = UIFactory.CreateUIObject("CurrentHooksPanel", this.uiContent);
|
||||||
UIFactory.SetLayoutElement(currentHooksPanel, flexibleHeight: 9999, flexibleWidth: 9999);
|
UIFactory.SetLayoutElement(currentHooksPanel, flexibleHeight: 9999, flexibleWidth: 9999);
|
||||||
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(currentHooksPanel, true, true, true, true);
|
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(currentHooksPanel, true, true, true, true);
|
||||||
|
|
||||||
@ -111,7 +109,7 @@ namespace UnityExplorer.UI.Panels
|
|||||||
|
|
||||||
// ~~~~~~~~~ Add hooks panel
|
// ~~~~~~~~~ Add hooks panel
|
||||||
|
|
||||||
addHooksPanel = UIFactory.CreateUIObject("AddHooksPanel", this.content);
|
addHooksPanel = UIFactory.CreateUIObject("AddHooksPanel", this.uiContent);
|
||||||
UIFactory.SetLayoutElement(addHooksPanel, flexibleHeight: 9999, flexibleWidth: 9999);
|
UIFactory.SetLayoutElement(addHooksPanel, flexibleHeight: 9999, flexibleWidth: 9999);
|
||||||
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(addHooksPanel, true, true, true, true);
|
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(addHooksPanel, true, true, true, true);
|
||||||
|
|
||||||
@ -138,7 +136,7 @@ namespace UnityExplorer.UI.Panels
|
|||||||
|
|
||||||
// ~~~~~~~~~ Hook source editor panel
|
// ~~~~~~~~~ Hook source editor panel
|
||||||
|
|
||||||
editorPanel = UIFactory.CreateUIObject("HookSourceEditor", this.content);
|
editorPanel = UIFactory.CreateUIObject("HookSourceEditor", this.uiContent);
|
||||||
UIFactory.SetLayoutElement(editorPanel, flexibleHeight: 9999, flexibleWidth: 9999);
|
UIFactory.SetLayoutElement(editorPanel, flexibleHeight: 9999, flexibleWidth: 9999);
|
||||||
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(editorPanel, true, true, true, true);
|
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(editorPanel, true, true, true, true);
|
||||||
|
|
||||||
|
@ -44,10 +44,6 @@ namespace UnityExplorer.UI.Panels
|
|||||||
InspectorManager.OnPanelResized(panel.rect.width);
|
InspectorManager.OnPanelResized(panel.rect.width);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string GetSaveDataFromConfigManager() => ConfigManager.InspectorData.Value;
|
|
||||||
|
|
||||||
public override void DoSaveToConfigElement() => ConfigManager.InspectorData.Value = this.ToSaveData();
|
|
||||||
|
|
||||||
protected internal override void DoSetDefaultPosAndAnchors()
|
protected internal override void DoSetDefaultPosAndAnchors()
|
||||||
{
|
{
|
||||||
Rect.localPosition = Vector2.zero;
|
Rect.localPosition = Vector2.zero;
|
||||||
@ -58,12 +54,12 @@ namespace UnityExplorer.UI.Panels
|
|||||||
|
|
||||||
public override void ConstructPanelContent()
|
public override void ConstructPanelContent()
|
||||||
{
|
{
|
||||||
var closeHolder = this.titleBar.transform.Find("CloseHolder").gameObject;
|
var closeHolder = this.TitleBar.transform.Find("CloseHolder").gameObject;
|
||||||
|
|
||||||
// Inspect under mouse dropdown on title bar
|
// Inspect under mouse dropdown on title bar
|
||||||
|
|
||||||
var mouseDropdown = UIFactory.CreateDropdown(closeHolder, out MouseInspectDropdown, "Mouse Inspect", 14,
|
var mouseDropdown = UIFactory.CreateDropdown(closeHolder, "MouseInspectDropdown", out MouseInspectDropdown, "Mouse Inspect", 14,
|
||||||
InspectUnderMouse.OnDropdownSelect);
|
MouseInspector.OnDropdownSelect);
|
||||||
UIFactory.SetLayoutElement(mouseDropdown, minHeight: 25, minWidth: 140);
|
UIFactory.SetLayoutElement(mouseDropdown, minHeight: 25, minWidth: 140);
|
||||||
MouseInspectDropdown.options.Add(new Dropdown.OptionData("Mouse Inspect"));
|
MouseInspectDropdown.options.Add(new Dropdown.OptionData("Mouse Inspect"));
|
||||||
MouseInspectDropdown.options.Add(new Dropdown.OptionData("World"));
|
MouseInspectDropdown.options.Add(new Dropdown.OptionData("World"));
|
||||||
@ -80,14 +76,14 @@ namespace UnityExplorer.UI.Panels
|
|||||||
|
|
||||||
// this.UIRoot.GetComponent<Mask>().enabled = false;
|
// this.UIRoot.GetComponent<Mask>().enabled = false;
|
||||||
|
|
||||||
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(this.content, true, true, true, true, 4, padLeft: 5, padRight: 5);
|
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(this.uiContent, true, true, true, true, 4, padLeft: 5, padRight: 5);
|
||||||
|
|
||||||
this.NavbarHolder = UIFactory.CreateGridGroup(this.content, "Navbar", new Vector2(200, 22), new Vector2(4, 4),
|
this.NavbarHolder = UIFactory.CreateGridGroup(this.uiContent, "Navbar", new Vector2(200, 22), new Vector2(4, 4),
|
||||||
new Color(0.05f, 0.05f, 0.05f));
|
new Color(0.05f, 0.05f, 0.05f));
|
||||||
//UIFactory.SetLayoutElement(NavbarHolder, flexibleWidth: 9999, minHeight: 0, preferredHeight: 0, flexibleHeight: 9999);
|
//UIFactory.SetLayoutElement(NavbarHolder, flexibleWidth: 9999, minHeight: 0, preferredHeight: 0, flexibleHeight: 9999);
|
||||||
NavbarHolder.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
NavbarHolder.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||||||
|
|
||||||
this.ContentHolder = UIFactory.CreateVerticalGroup(this.content, "ContentHolder", true, true, true, true, 0, default,
|
this.ContentHolder = UIFactory.CreateVerticalGroup(this.uiContent, "ContentHolder", true, true, true, true, 0, default,
|
||||||
new Color(0.1f, 0.1f, 0.1f));
|
new Color(0.1f, 0.1f, 0.1f));
|
||||||
UIFactory.SetLayoutElement(ContentHolder, flexibleHeight: 9999);
|
UIFactory.SetLayoutElement(ContentHolder, flexibleHeight: 9999);
|
||||||
ContentRect = ContentHolder.GetComponent<RectTransform>();
|
ContentRect = ContentHolder.GetComponent<RectTransform>();
|
||||||
|
@ -10,7 +10,10 @@ using UnityExplorer.Config;
|
|||||||
using UnityExplorer.UI.Widgets;
|
using UnityExplorer.UI.Widgets;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
|
using UniverseLib.UI.Models;
|
||||||
using UniverseLib.UI.Widgets;
|
using UniverseLib.UI.Widgets;
|
||||||
|
using UniverseLib.UI.Widgets.ScrollView;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Panels
|
namespace UnityExplorer.UI.Panels
|
||||||
{
|
{
|
||||||
@ -141,19 +144,7 @@ namespace UnityExplorer.UI.Panels
|
|||||||
cell.Input.Component.textComponent.color = logColors[log.type];
|
cell.Input.Component.textComponent.color = logColors[log.type];
|
||||||
|
|
||||||
var color = index % 2 == 0 ? logEvenColor : logOddColor;
|
var color = index % 2 == 0 ? logEvenColor : logOddColor;
|
||||||
RuntimeProvider.Instance.SetColorBlock(cell.Input.Component, color);
|
RuntimeHelper.SetColorBlock(cell.Input.Component, color);
|
||||||
}
|
|
||||||
|
|
||||||
// Panel save data
|
|
||||||
|
|
||||||
public override string GetSaveDataFromConfigManager()
|
|
||||||
{
|
|
||||||
return ConfigManager.ConsoleLogData.Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void DoSaveToConfigElement()
|
|
||||||
{
|
|
||||||
ConfigManager.ConsoleLogData.Value = this.ToSaveData();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected internal override void DoSetDefaultPosAndAnchors()
|
protected internal override void DoSetDefaultPosAndAnchors()
|
||||||
@ -170,13 +161,13 @@ namespace UnityExplorer.UI.Panels
|
|||||||
{
|
{
|
||||||
// Log scroll pool
|
// Log scroll pool
|
||||||
|
|
||||||
logScrollPool = UIFactory.CreateScrollPool<ConsoleLogCell>(this.content, "Logs", out GameObject scrollObj,
|
logScrollPool = UIFactory.CreateScrollPool<ConsoleLogCell>(this.uiContent, "Logs", out GameObject scrollObj,
|
||||||
out GameObject scrollContent, new Color(0.03f, 0.03f, 0.03f));
|
out GameObject scrollContent, new Color(0.03f, 0.03f, 0.03f));
|
||||||
UIFactory.SetLayoutElement(scrollObj, flexibleWidth: 9999, flexibleHeight: 9999);
|
UIFactory.SetLayoutElement(scrollObj, flexibleWidth: 9999, flexibleHeight: 9999);
|
||||||
|
|
||||||
// Buttons and toggles
|
// Buttons and toggles
|
||||||
|
|
||||||
var optionsRow = UIFactory.CreateUIObject("OptionsRow", this.content);
|
var optionsRow = UIFactory.CreateUIObject("OptionsRow", this.uiContent);
|
||||||
UIFactory.SetLayoutElement(optionsRow, minHeight: 25, flexibleWidth: 9999);
|
UIFactory.SetLayoutElement(optionsRow, minHeight: 25, flexibleWidth: 9999);
|
||||||
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(optionsRow, false, false, true, true, 5, 2, 2, 2, 2);
|
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(optionsRow, false, false, true, true, 5, 2, 2, 2, 2);
|
||||||
|
|
||||||
@ -229,7 +220,7 @@ namespace UnityExplorer.UI.Panels
|
|||||||
Input = UIFactory.CreateInputField(UIRoot, "Input", "");
|
Input = UIFactory.CreateInputField(UIRoot, "Input", "");
|
||||||
//Input.Component.gameObject.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
//Input.Component.gameObject.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||||||
UIFactory.SetLayoutElement(Input.UIRoot, minHeight: 25, flexibleWidth: 9999);
|
UIFactory.SetLayoutElement(Input.UIRoot, minHeight: 25, flexibleWidth: 9999);
|
||||||
RuntimeProvider.Instance.SetColorBlock(Input.Component, new Color(0.1f, 0.1f, 0.1f), new Color(0.13f, 0.13f, 0.13f),
|
RuntimeHelper.SetColorBlock(Input.Component, new Color(0.1f, 0.1f, 0.1f), new Color(0.13f, 0.13f, 0.13f),
|
||||||
new Color(0.07f, 0.07f, 0.07f));
|
new Color(0.07f, 0.07f, 0.07f));
|
||||||
Input.Component.GetComponent<Image>().color = new Color(0.2f, 0.2f, 0.2f);
|
Input.Component.GetComponent<Image>().color = new Color(0.2f, 0.2f, 0.2f);
|
||||||
|
|
||||||
|
@ -43,16 +43,16 @@ namespace UnityExplorer.UI.Panels
|
|||||||
content.SetActive(true);
|
content.SetActive(true);
|
||||||
|
|
||||||
var button = tabButtons[tabIndex];
|
var button = tabButtons[tabIndex];
|
||||||
RuntimeProvider.Instance.SetColorBlock(button.Component, UniversalUI.enabledButtonColor, UniversalUI.enabledButtonColor * 1.2f);
|
RuntimeHelper.SetColorBlock(button.Component, UniversalUI.EnabledButtonColor, UniversalUI.EnabledButtonColor * 1.2f);
|
||||||
|
|
||||||
SelectedTab = tabIndex;
|
SelectedTab = tabIndex;
|
||||||
SaveToConfigManager();
|
SaveInternalData();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DisableTab(int tabIndex)
|
private void DisableTab(int tabIndex)
|
||||||
{
|
{
|
||||||
tabPages[tabIndex].SetActive(false);
|
tabPages[tabIndex].SetActive(false);
|
||||||
RuntimeProvider.Instance.SetColorBlock(tabButtons[tabIndex].Component, UniversalUI.disabledButtonColor, UniversalUI.disabledButtonColor * 1.2f);
|
RuntimeHelper.SetColorBlock(tabButtons[tabIndex].Component, UniversalUI.DisabledButtonColor, UniversalUI.DisabledButtonColor * 1.2f);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Update()
|
public override void Update()
|
||||||
@ -63,21 +63,12 @@ namespace UnityExplorer.UI.Panels
|
|||||||
ObjectSearch.Update();
|
ObjectSearch.Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string GetSaveDataFromConfigManager() => ConfigManager.ObjectExplorerData.Value;
|
|
||||||
|
|
||||||
public override void DoSaveToConfigElement()
|
|
||||||
{
|
|
||||||
ConfigManager.ObjectExplorerData.Value = this.ToSaveData();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToSaveData()
|
public override string ToSaveData()
|
||||||
{
|
{
|
||||||
string ret = base.ToSaveData();
|
return string.Join("|", new string[] { base.ToSaveData(), SelectedTab.ToString() });
|
||||||
ret += "|" + SelectedTab;
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void ApplySaveData(string data)
|
protected override void ApplySaveData(string data)
|
||||||
{
|
{
|
||||||
base.ApplySaveData(data);
|
base.ApplySaveData(data);
|
||||||
|
|
||||||
@ -108,17 +99,17 @@ namespace UnityExplorer.UI.Panels
|
|||||||
public override void ConstructPanelContent()
|
public override void ConstructPanelContent()
|
||||||
{
|
{
|
||||||
// Tab bar
|
// Tab bar
|
||||||
var tabGroup = UIFactory.CreateHorizontalGroup(content, "TabBar", true, true, true, true, 2, new Vector4(2, 2, 2, 2));
|
var tabGroup = UIFactory.CreateHorizontalGroup(uiContent, "TabBar", true, true, true, true, 2, new Vector4(2, 2, 2, 2));
|
||||||
UIFactory.SetLayoutElement(tabGroup, minHeight: 25, flexibleHeight: 0);
|
UIFactory.SetLayoutElement(tabGroup, minHeight: 25, flexibleHeight: 0);
|
||||||
|
|
||||||
// Scene Explorer
|
// Scene Explorer
|
||||||
SceneExplorer = new SceneExplorer(this);
|
SceneExplorer = new SceneExplorer(this);
|
||||||
SceneExplorer.ConstructUI(content);
|
SceneExplorer.ConstructUI(uiContent);
|
||||||
tabPages.Add(SceneExplorer);
|
tabPages.Add(SceneExplorer);
|
||||||
|
|
||||||
// Object search
|
// Object search
|
||||||
ObjectSearch = new ObjectSearch(this);
|
ObjectSearch = new ObjectSearch(this);
|
||||||
ObjectSearch.ConstructUI(content);
|
ObjectSearch.ConstructUI(uiContent);
|
||||||
tabPages.Add(ObjectSearch);
|
tabPages.Add(ObjectSearch);
|
||||||
|
|
||||||
// set up tabs
|
// set up tabs
|
||||||
|
@ -10,6 +10,7 @@ using UnityExplorer.CacheObject.Views;
|
|||||||
using UnityExplorer.UI.Widgets;
|
using UnityExplorer.UI.Widgets;
|
||||||
using UniverseLib.UI.Widgets;
|
using UniverseLib.UI.Widgets;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
|
using UniverseLib.UI.Widgets.ScrollView;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Panels
|
namespace UnityExplorer.UI.Panels
|
||||||
{
|
{
|
||||||
@ -55,17 +56,7 @@ namespace UnityExplorer.UI.Panels
|
|||||||
CacheObjectControllerHelper.SetCell(cell, index, this.configEntries, null);
|
CacheObjectControllerHelper.SetCell(cell, index, this.configEntries, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Panel save data
|
// UI Construction
|
||||||
|
|
||||||
public override string GetSaveDataFromConfigManager()
|
|
||||||
{
|
|
||||||
return ConfigManager.OptionsPanelData.Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void DoSaveToConfigElement()
|
|
||||||
{
|
|
||||||
ConfigManager.OptionsPanelData.Value = this.ToSaveData();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected internal override void DoSetDefaultPosAndAnchors()
|
protected internal override void DoSetDefaultPosAndAnchors()
|
||||||
{
|
{
|
||||||
@ -76,19 +67,17 @@ namespace UnityExplorer.UI.Panels
|
|||||||
Rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, 600f);
|
Rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, 600f);
|
||||||
}
|
}
|
||||||
|
|
||||||
// UI Construction
|
|
||||||
|
|
||||||
public override void ConstructPanelContent()
|
public override void ConstructPanelContent()
|
||||||
{
|
{
|
||||||
// Save button
|
// Save button
|
||||||
|
|
||||||
var saveBtn = UIFactory.CreateButton(this.content, "Save", "Save Options", new Color(0.2f, 0.3f, 0.2f));
|
var saveBtn = UIFactory.CreateButton(this.uiContent, "Save", "Save Options", new Color(0.2f, 0.3f, 0.2f));
|
||||||
UIFactory.SetLayoutElement(saveBtn.Component.gameObject, flexibleWidth: 9999, minHeight: 30, flexibleHeight: 0);
|
UIFactory.SetLayoutElement(saveBtn.Component.gameObject, flexibleWidth: 9999, minHeight: 30, flexibleHeight: 0);
|
||||||
saveBtn.OnClick += ConfigManager.Handler.SaveConfig;
|
saveBtn.OnClick += ConfigManager.Handler.SaveConfig;
|
||||||
|
|
||||||
// Config entries
|
// Config entries
|
||||||
|
|
||||||
var scrollPool = UIFactory.CreateScrollPool<ConfigEntryCell>(this.content, "ConfigEntries", out GameObject scrollObj,
|
var scrollPool = UIFactory.CreateScrollPool<ConfigEntryCell>(this.uiContent, "ConfigEntries", out GameObject scrollObj,
|
||||||
out GameObject scrollContent);
|
out GameObject scrollContent);
|
||||||
|
|
||||||
scrollPool.Initialize(this);
|
scrollPool.Initialize(this);
|
||||||
|
@ -10,6 +10,7 @@ using UniverseLib.UI.Models;
|
|||||||
using UnityExplorer.UI.Widgets.AutoComplete;
|
using UnityExplorer.UI.Widgets.AutoComplete;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Panels
|
namespace UnityExplorer.UI.Panels
|
||||||
{
|
{
|
||||||
@ -67,6 +68,9 @@ namespace UnityExplorer.UI.Panels
|
|||||||
|
|
||||||
public static void UpdateInstances()
|
public static void UpdateInstances()
|
||||||
{
|
{
|
||||||
|
if (!DisplayManager.MouseInTargetDisplay)
|
||||||
|
return;
|
||||||
|
|
||||||
if (!resizeCursorObj)
|
if (!resizeCursorObj)
|
||||||
CreateCursorUI();
|
CreateCursorUI();
|
||||||
|
|
||||||
@ -78,7 +82,7 @@ namespace UnityExplorer.UI.Panels
|
|||||||
else
|
else
|
||||||
state = MouseState.NotPressed;
|
state = MouseState.NotPressed;
|
||||||
|
|
||||||
var mousePos = InputManager.MousePosition;
|
var mousePos = DisplayManager.MousePosition;
|
||||||
|
|
||||||
handledInstanceThisFrame = false;
|
handledInstanceThisFrame = false;
|
||||||
foreach (var instance in Instances)
|
foreach (var instance in Instances)
|
||||||
@ -234,12 +238,12 @@ namespace UnityExplorer.UI.Panels
|
|||||||
{
|
{
|
||||||
wasAnyDragging = true;
|
wasAnyDragging = true;
|
||||||
WasDragging = true;
|
WasDragging = true;
|
||||||
lastDragPosition = InputManager.MousePosition;
|
lastDragPosition = DisplayManager.MousePosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnDrag()
|
public void OnDrag()
|
||||||
{
|
{
|
||||||
var mousePos = InputManager.MousePosition;
|
var mousePos = DisplayManager.MousePosition;
|
||||||
|
|
||||||
Vector2 diff = (Vector2)mousePos - lastDragPosition;
|
Vector2 diff = (Vector2)mousePos - lastDragPosition;
|
||||||
lastDragPosition = mousePos;
|
lastDragPosition = mousePos;
|
||||||
@ -260,7 +264,7 @@ namespace UnityExplorer.UI.Panels
|
|||||||
|
|
||||||
#region RESIZE
|
#region RESIZE
|
||||||
|
|
||||||
private readonly Dictionary<ResizeTypes, Rect> m_resizeMask = new Dictionary<ResizeTypes, Rect>
|
private readonly Dictionary<ResizeTypes, Rect> m_resizeMask = new()
|
||||||
{
|
{
|
||||||
{ ResizeTypes.Top, default },
|
{ ResizeTypes.Top, default },
|
||||||
{ ResizeTypes.Left, default },
|
{ ResizeTypes.Left, default },
|
||||||
@ -388,7 +392,7 @@ namespace UnityExplorer.UI.Panels
|
|||||||
// update the resize icon position to be above the mouse
|
// update the resize icon position to be above the mouse
|
||||||
private void UpdateHoverImagePos()
|
private void UpdateHoverImagePos()
|
||||||
{
|
{
|
||||||
resizeCursorObj.transform.localPosition = UIManager.UIRootRect.InverseTransformPoint(InputManager.MousePosition);
|
resizeCursorObj.transform.localPosition = UIManager.UIRootRect.InverseTransformPoint(DisplayManager.MousePosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnHoverResizeEnd()
|
public void OnHoverResizeEnd()
|
||||||
@ -400,26 +404,26 @@ namespace UnityExplorer.UI.Panels
|
|||||||
public void OnBeginResize(ResizeTypes resizeType)
|
public void OnBeginResize(ResizeTypes resizeType)
|
||||||
{
|
{
|
||||||
currentResizeType = resizeType;
|
currentResizeType = resizeType;
|
||||||
lastResizePos = InputManager.MousePosition;
|
lastResizePos = DisplayManager.MousePosition;
|
||||||
WasResizing = true;
|
WasResizing = true;
|
||||||
Resizing = true;
|
Resizing = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnResize()
|
public void OnResize()
|
||||||
{
|
{
|
||||||
Vector3 mousePos = InputManager.MousePosition;
|
Vector3 mousePos = DisplayManager.MousePosition;
|
||||||
Vector2 diff = lastResizePos - (Vector2)mousePos;
|
Vector2 diff = lastResizePos - (Vector2)mousePos;
|
||||||
|
|
||||||
if ((Vector2)mousePos == lastResizePos)
|
if ((Vector2)mousePos == lastResizePos)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (mousePos.x < 0 || mousePos.y < 0 || mousePos.x > Screen.width || mousePos.y > Screen.height)
|
if (mousePos.x < 0 || mousePos.y < 0 || mousePos.x > DisplayManager.Width || mousePos.y > DisplayManager.Height)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
lastResizePos = mousePos;
|
lastResizePos = mousePos;
|
||||||
|
|
||||||
float diffX = (float)((decimal)diff.x / Screen.width);
|
float diffX = (float)((decimal)diff.x / DisplayManager.Width);
|
||||||
float diffY = (float)((decimal)diff.y / Screen.height);
|
float diffY = (float)((decimal)diff.y / DisplayManager.Height);
|
||||||
|
|
||||||
Vector2 anchorMin = Panel.anchorMin;
|
Vector2 anchorMin = Panel.anchorMin;
|
||||||
Vector2 anchorMax = Panel.anchorMax;
|
Vector2 anchorMax = Panel.anchorMax;
|
||||||
@ -467,6 +471,9 @@ namespace UnityExplorer.UI.Panels
|
|||||||
{
|
{
|
||||||
var text = UIFactory.CreateLabel(UIManager.UIRoot, "ResizeCursor", "↔", TextAnchor.MiddleCenter, Color.white, true, 35);
|
var text = UIFactory.CreateLabel(UIManager.UIRoot, "ResizeCursor", "↔", TextAnchor.MiddleCenter, Color.white, true, 35);
|
||||||
resizeCursorObj = text.gameObject;
|
resizeCursorObj = text.gameObject;
|
||||||
|
var outline = text.gameObject.AddComponent<Outline>();
|
||||||
|
outline.effectColor = Color.black;
|
||||||
|
outline.effectDistance = new(1, 1);
|
||||||
|
|
||||||
RectTransform rect = resizeCursorObj.GetComponent<RectTransform>();
|
RectTransform rect = resizeCursorObj.GetComponent<RectTransform>();
|
||||||
rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, 64);
|
rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, 64);
|
||||||
|
@ -11,6 +11,7 @@ using UnityExplorer.UI.Widgets;
|
|||||||
using UniverseLib.UI.Models;
|
using UniverseLib.UI.Models;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
|
using System.Collections;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Panels
|
namespace UnityExplorer.UI.Panels
|
||||||
{
|
{
|
||||||
@ -32,10 +33,11 @@ namespace UnityExplorer.UI.Panels
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// if the user is clicking
|
// if the user is clicking
|
||||||
if (InputManager.GetMouseButtonDown(0) || InputManager.GetMouseButtonDown(1))
|
if (DisplayManager.MouseInTargetDisplay
|
||||||
|
&& (InputManager.GetMouseButtonDown(0) || InputManager.GetMouseButtonDown(1)))
|
||||||
{
|
{
|
||||||
int count = UIManager.PanelHolder.transform.childCount;
|
int count = UIManager.PanelHolder.transform.childCount;
|
||||||
var mousePos = InputManager.MousePosition;
|
var mousePos = DisplayManager.MousePosition;
|
||||||
bool clickedInAny = false;
|
bool clickedInAny = false;
|
||||||
|
|
||||||
for (int i = count - 1; i >= 0; i--)
|
for (int i = count - 1; i >= 0; i--)
|
||||||
@ -85,46 +87,48 @@ namespace UnityExplorer.UI.Panels
|
|||||||
public virtual bool CanDragAndResize => true;
|
public virtual bool CanDragAndResize => true;
|
||||||
public virtual bool NavButtonWanted => true;
|
public virtual bool NavButtonWanted => true;
|
||||||
|
|
||||||
public ButtonRef NavButton;
|
public ButtonRef NavButton { get; internal set; }
|
||||||
public PanelDragger Dragger;
|
public PanelDragger Dragger { get; internal set; }
|
||||||
|
|
||||||
public override GameObject UIRoot => uiRoot;
|
public override GameObject UIRoot => uiRoot;
|
||||||
protected GameObject uiRoot;
|
protected GameObject uiRoot;
|
||||||
public RectTransform Rect;
|
protected GameObject uiContent;
|
||||||
public GameObject content;
|
public RectTransform Rect { get; private set; }
|
||||||
|
public GameObject TitleBar { get; private set; }
|
||||||
public GameObject titleBar;
|
|
||||||
|
|
||||||
public abstract void ConstructPanelContent();
|
|
||||||
|
|
||||||
public virtual void OnFinishResize(RectTransform panel)
|
public virtual void OnFinishResize(RectTransform panel)
|
||||||
{
|
{
|
||||||
SaveToConfigManager();
|
SaveInternalData();
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void OnFinishDrag(RectTransform panel)
|
public virtual void OnFinishDrag(RectTransform panel)
|
||||||
{
|
{
|
||||||
SaveToConfigManager();
|
SaveInternalData();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void SetActive(bool active)
|
public override void SetActive(bool active)
|
||||||
{
|
{
|
||||||
if (this.Enabled == active)
|
if (this.Enabled != active)
|
||||||
return;
|
|
||||||
|
|
||||||
base.SetActive(active);
|
|
||||||
|
|
||||||
if (!ApplyingSaveData)
|
|
||||||
SaveToConfigManager();
|
|
||||||
|
|
||||||
if (NavButtonWanted)
|
|
||||||
{
|
{
|
||||||
var color = active ? UniversalUI.enabledButtonColor : UniversalUI.disabledButtonColor;
|
base.SetActive(active);
|
||||||
RuntimeProvider.Instance.SetColorBlock(NavButton.Component, color, color * 1.2f);
|
|
||||||
|
if (!ApplyingSaveData)
|
||||||
|
SaveInternalData();
|
||||||
|
|
||||||
|
if (NavButtonWanted)
|
||||||
|
{
|
||||||
|
var color = active ? UniversalUI.EnabledButtonColor : UniversalUI.DisabledButtonColor;
|
||||||
|
RuntimeHelper.SetColorBlock(NavButton.Component, color, color * 1.2f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!active)
|
if (!active)
|
||||||
this.Dragger.WasDragging = false;
|
this.Dragger.WasDragging = false;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.UIRoot.transform.SetAsLastSibling();
|
||||||
|
InvokeOnPanelsReordered();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Destroy()
|
public override void Destroy()
|
||||||
@ -148,13 +152,15 @@ namespace UnityExplorer.UI.Panels
|
|||||||
Rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, MinHeight);
|
Rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, MinHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void EnsureValidPosition() => EnsureValidPosition(this.Rect);
|
||||||
|
|
||||||
public static void EnsureValidPosition(RectTransform panel)
|
public static void EnsureValidPosition(RectTransform panel)
|
||||||
{
|
{
|
||||||
var pos = panel.localPosition;
|
var pos = panel.localPosition;
|
||||||
|
|
||||||
// Prevent panel going oustide screen bounds
|
// Prevent panel going oustide screen bounds
|
||||||
var halfW = Screen.width * 0.5f;
|
var halfW = DisplayManager.Width * 0.5f;
|
||||||
var halfH = Screen.height * 0.5f;
|
var halfH = DisplayManager.Height * 0.5f;
|
||||||
|
|
||||||
pos.x = Math.Max(-halfW - panel.rect.width + 50, Math.Min(pos.x, halfW - 50));
|
pos.x = Math.Max(-halfW - panel.rect.width + 50, Math.Min(pos.x, halfW - 50));
|
||||||
pos.y = Math.Max(-halfH + 50, Math.Min(pos.y, halfH));
|
pos.y = Math.Max(-halfH + 50, Math.Min(pos.y, halfH));
|
||||||
@ -162,29 +168,30 @@ namespace UnityExplorer.UI.Panels
|
|||||||
panel.localPosition = pos;
|
panel.localPosition = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Save Data
|
// Save Data
|
||||||
|
|
||||||
public abstract void DoSaveToConfigElement();
|
public bool ApplyingSaveData { get; set; }
|
||||||
|
|
||||||
public void SaveToConfigManager()
|
public void SaveInternalData()
|
||||||
{
|
{
|
||||||
if (UIManager.Initializing)
|
if (UIManager.Initializing)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
DoSaveToConfigElement();
|
SetSaveDataToConfigValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract string GetSaveDataFromConfigManager();
|
private void SetSaveDataToConfigValue() => ConfigManager.GetPanelSaveData(this.PanelType).Value = this.ToSaveData();
|
||||||
|
|
||||||
public bool ApplyingSaveData { get; set; }
|
|
||||||
|
|
||||||
public virtual string ToSaveData()
|
public virtual string ToSaveData()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return $"{ShouldSaveActiveState && Enabled}" +
|
return string.Join("|", new string[]
|
||||||
$"|{Rect.RectAnchorsToString()}" +
|
{
|
||||||
$"|{Rect.RectPositionToString()}";
|
$"{ShouldSaveActiveState && Enabled}",
|
||||||
|
Rect.RectAnchorsToString(),
|
||||||
|
Rect.RectPositionToString()
|
||||||
|
});
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@ -193,7 +200,13 @@ namespace UnityExplorer.UI.Panels
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void ApplySaveData(string data)
|
public virtual void ApplySaveData()
|
||||||
|
{
|
||||||
|
string data = ConfigManager.GetPanelSaveData(this.PanelType).Value;
|
||||||
|
ApplySaveData(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void ApplySaveData(string data)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(data))
|
if (string.IsNullOrEmpty(data))
|
||||||
return;
|
return;
|
||||||
@ -210,17 +223,14 @@ namespace UnityExplorer.UI.Panels
|
|||||||
{
|
{
|
||||||
ExplorerCore.LogWarning("Invalid or corrupt panel save data! Restoring to default.");
|
ExplorerCore.LogWarning("Invalid or corrupt panel save data! Restoring to default.");
|
||||||
SetTransformDefaults();
|
SetTransformDefaults();
|
||||||
UIManager.Initializing = false;
|
SetSaveDataToConfigValue();
|
||||||
DoSaveToConfigElement();
|
|
||||||
ConfigManager.InternalHandler.SaveConfig();
|
|
||||||
UIManager.Initializing = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
// UI Construction
|
// UI Construction
|
||||||
|
|
||||||
|
public abstract void ConstructPanelContent();
|
||||||
|
|
||||||
public void ConstructUI()
|
public void ConstructUI()
|
||||||
{
|
{
|
||||||
//this.Enabled = true;
|
//this.Enabled = true;
|
||||||
@ -235,7 +245,7 @@ namespace UnityExplorer.UI.Panels
|
|||||||
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(navBtn, false, true, true, true, 0, 0, 0, 5, 5, TextAnchor.MiddleCenter);
|
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(navBtn, false, true, true, true, 0, 0, 0, 5, 5, TextAnchor.MiddleCenter);
|
||||||
UIFactory.SetLayoutElement(navBtn, minWidth: 80);
|
UIFactory.SetLayoutElement(navBtn, minWidth: 80);
|
||||||
|
|
||||||
RuntimeProvider.Instance.SetColorBlock(NavButton.Component, UniversalUI.disabledButtonColor, UniversalUI.disabledButtonColor * 1.2f);
|
RuntimeHelper.SetColorBlock(NavButton.Component, UniversalUI.DisabledButtonColor, UniversalUI.DisabledButtonColor * 1.2f);
|
||||||
NavButton.OnClick += () => { UIManager.TogglePanel(PanelType); };
|
NavButton.OnClick += () => { UIManager.TogglePanel(PanelType); };
|
||||||
|
|
||||||
var txtObj = navBtn.transform.Find("Text").gameObject;
|
var txtObj = navBtn.transform.Find("Text").gameObject;
|
||||||
@ -243,47 +253,46 @@ namespace UnityExplorer.UI.Panels
|
|||||||
}
|
}
|
||||||
|
|
||||||
// create core canvas
|
// create core canvas
|
||||||
uiRoot = UIFactory.CreatePanel(Name, UIManager.PanelHolder, out GameObject panelContent);
|
uiRoot = UIFactory.CreatePanel(Name, UIManager.PanelHolder, out uiContent);
|
||||||
Rect = this.uiRoot.GetComponent<RectTransform>();
|
Rect = this.uiRoot.GetComponent<RectTransform>();
|
||||||
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(this.uiRoot, false, false, true, true, 0, 2, 2, 2, 2, TextAnchor.UpperLeft);
|
//UIFactory.SetLayoutGroup<VerticalLayoutGroup>(this.uiRoot, false, false, true, true, 0, 2, 2, 2, 2, TextAnchor.UpperLeft);
|
||||||
|
|
||||||
int id = this.uiRoot.transform.GetInstanceID();
|
int id = this.uiRoot.transform.GetInstanceID();
|
||||||
transformToPanelDict.Add(id, this);
|
transformToPanelDict.Add(id, this);
|
||||||
|
|
||||||
content = panelContent;
|
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(this.uiContent, false, false, true, true, 2, 2, 2, 2, 2, TextAnchor.UpperLeft);
|
||||||
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(this.content, false, false, true, true, 2, 2, 2, 2, 2, TextAnchor.UpperLeft);
|
|
||||||
|
|
||||||
// Title bar
|
// Title bar
|
||||||
titleBar = UIFactory.CreateHorizontalGroup(content, "TitleBar", false, true, true, true, 2,
|
TitleBar = UIFactory.CreateHorizontalGroup(uiContent, "TitleBar", false, true, true, true, 2,
|
||||||
new Vector4(2, 2, 2, 2), new Color(0.06f, 0.06f, 0.06f));
|
new Vector4(2, 2, 2, 2), new Color(0.06f, 0.06f, 0.06f));
|
||||||
UIFactory.SetLayoutElement(titleBar, minHeight: 25, flexibleHeight: 0);
|
UIFactory.SetLayoutElement(TitleBar, minHeight: 25, flexibleHeight: 0);
|
||||||
|
|
||||||
// Title text
|
// Title text
|
||||||
|
|
||||||
var titleTxt = UIFactory.CreateLabel(titleBar, "TitleBar", Name, TextAnchor.MiddleLeft);
|
var titleTxt = UIFactory.CreateLabel(TitleBar, "TitleBar", Name, TextAnchor.MiddleLeft);
|
||||||
UIFactory.SetLayoutElement(titleTxt.gameObject, minWidth: 250, minHeight: 25, flexibleHeight: 0);
|
UIFactory.SetLayoutElement(titleTxt.gameObject, minWidth: 250, minHeight: 25, flexibleHeight: 0);
|
||||||
|
|
||||||
// close button
|
// close button
|
||||||
|
|
||||||
var closeHolder = UIFactory.CreateUIObject("CloseHolder", titleBar);
|
var closeHolder = UIFactory.CreateUIObject("CloseHolder", TitleBar);
|
||||||
UIFactory.SetLayoutElement(closeHolder, minHeight: 25, flexibleHeight: 0, minWidth: 30, flexibleWidth: 9999);
|
UIFactory.SetLayoutElement(closeHolder, minHeight: 25, flexibleHeight: 0, minWidth: 30, flexibleWidth: 9999);
|
||||||
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(closeHolder, false, false, true, true, 3, childAlignment: TextAnchor.MiddleRight);
|
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(closeHolder, false, false, true, true, 3, childAlignment: TextAnchor.MiddleRight);
|
||||||
var closeBtn = UIFactory.CreateButton(closeHolder, "CloseButton", "—");
|
var closeBtn = UIFactory.CreateButton(closeHolder, "CloseButton", "—");
|
||||||
UIFactory.SetLayoutElement(closeBtn.Component.gameObject, minHeight: 25, minWidth: 25, flexibleWidth: 0);
|
UIFactory.SetLayoutElement(closeBtn.Component.gameObject, minHeight: 25, minWidth: 25, flexibleWidth: 0);
|
||||||
RuntimeProvider.Instance.SetColorBlock(closeBtn.Component, new Color(0.33f, 0.32f, 0.31f));
|
RuntimeHelper.SetColorBlock(closeBtn.Component, new Color(0.33f, 0.32f, 0.31f));
|
||||||
|
|
||||||
closeBtn.OnClick += () =>
|
closeBtn.OnClick += () =>
|
||||||
{
|
{
|
||||||
UIManager.SetPanelActive(this.PanelType, false);
|
UIManager.SetPanelActive(this.PanelType, false);
|
||||||
SaveToConfigManager();
|
SaveInternalData();
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!CanDragAndResize)
|
if (!CanDragAndResize)
|
||||||
titleBar.SetActive(false);
|
TitleBar.SetActive(false);
|
||||||
|
|
||||||
// Panel dragger
|
// Panel dragger
|
||||||
|
|
||||||
Dragger = new PanelDragger(titleBar.GetComponent<RectTransform>(), Rect, this);
|
Dragger = new PanelDragger(TitleBar.GetComponent<RectTransform>(), Rect, this);
|
||||||
Dragger.OnFinishResize += OnFinishResize;
|
Dragger.OnFinishResize += OnFinishResize;
|
||||||
Dragger.OnFinishDrag += OnFinishDrag;
|
Dragger.OnFinishDrag += OnFinishDrag;
|
||||||
|
|
||||||
@ -300,7 +309,7 @@ namespace UnityExplorer.UI.Panels
|
|||||||
// apply panel save data or revert to default
|
// apply panel save data or revert to default
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
ApplySaveData(GetSaveDataFromConfigManager());
|
ApplySaveData();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@ -308,7 +317,20 @@ namespace UnityExplorer.UI.Panels
|
|||||||
SetTransformDefaults();
|
SetTransformDefaults();
|
||||||
}
|
}
|
||||||
|
|
||||||
LayoutRebuilder.ForceRebuildLayoutImmediate(this.Rect);
|
RuntimeHelper.StartCoroutine(LateSetupCoroutine());
|
||||||
|
|
||||||
|
// simple listener for saving enabled state
|
||||||
|
this.OnToggleEnabled += (bool val) =>
|
||||||
|
{
|
||||||
|
SaveInternalData();
|
||||||
|
};
|
||||||
|
|
||||||
|
ApplyingSaveData = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerator LateSetupCoroutine()
|
||||||
|
{
|
||||||
|
yield return null;
|
||||||
|
|
||||||
// ensure initialized position is valid
|
// ensure initialized position is valid
|
||||||
EnsureValidSize();
|
EnsureValidSize();
|
||||||
@ -316,14 +338,6 @@ namespace UnityExplorer.UI.Panels
|
|||||||
|
|
||||||
// update dragger and save data
|
// update dragger and save data
|
||||||
Dragger.OnEndResize();
|
Dragger.OnEndResize();
|
||||||
|
|
||||||
// simple listener for saving enabled state
|
|
||||||
this.OnToggleEnabled += (bool val) =>
|
|
||||||
{
|
|
||||||
SaveToConfigManager();
|
|
||||||
};
|
|
||||||
|
|
||||||
ApplyingSaveData = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void ConstructUI(GameObject parent) => ConstructUI();
|
public override void ConstructUI(GameObject parent) => ConstructUI();
|
||||||
@ -380,7 +394,7 @@ namespace UnityExplorer.UI.Panels
|
|||||||
|
|
||||||
return string.Format(CultureInfo.InvariantCulture, "{0},{1}", new object[]
|
return string.Format(CultureInfo.InvariantCulture, "{0},{1}", new object[]
|
||||||
{
|
{
|
||||||
rect.localPosition.x, rect.localPosition.y
|
rect.anchoredPosition.x, rect.anchoredPosition.y
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -398,10 +412,10 @@ namespace UnityExplorer.UI.Panels
|
|||||||
if (split.Length != 2)
|
if (split.Length != 2)
|
||||||
throw new Exception($"stringPosition split is unexpected length: {split.Length}");
|
throw new Exception($"stringPosition split is unexpected length: {split.Length}");
|
||||||
|
|
||||||
Vector3 vector = rect.localPosition;
|
Vector3 vector = rect.anchoredPosition;
|
||||||
vector.x = float.Parse(split[0], CultureInfo.InvariantCulture);
|
vector.x = float.Parse(split[0], CultureInfo.InvariantCulture);
|
||||||
vector.y = float.Parse(split[1], CultureInfo.InvariantCulture);
|
vector.y = float.Parse(split[1], CultureInfo.InvariantCulture);
|
||||||
rect.localPosition = vector;
|
rect.anchoredPosition = vector;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,9 @@ using UnityExplorer.UI.Widgets;
|
|||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
using UniverseLib.UI.Widgets;
|
using UniverseLib.UI.Widgets;
|
||||||
|
using UniverseLib.UI.Widgets.ButtonList;
|
||||||
|
using UniverseLib.UI.Widgets.ScrollView;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Panels
|
namespace UnityExplorer.UI.Panels
|
||||||
{
|
{
|
||||||
@ -58,7 +61,7 @@ namespace UnityExplorer.UI.Panels
|
|||||||
{
|
{
|
||||||
dataHandler = new ButtonListHandler<GameObject, ButtonCell>(buttonScrollPool, GetEntries, SetCell, ShouldDisplayCell, OnCellClicked);
|
dataHandler = new ButtonListHandler<GameObject, ButtonCell>(buttonScrollPool, GetEntries, SetCell, ShouldDisplayCell, OnCellClicked);
|
||||||
|
|
||||||
buttonScrollPool = UIFactory.CreateScrollPool<ButtonCell>(this.content, "ResultsList", out GameObject scrollObj,
|
buttonScrollPool = UIFactory.CreateScrollPool<ButtonCell>(this.uiContent, "ResultsList", out GameObject scrollObj,
|
||||||
out GameObject scrollContent);
|
out GameObject scrollContent);
|
||||||
|
|
||||||
buttonScrollPool.Initialize(dataHandler);
|
buttonScrollPool.Initialize(dataHandler);
|
||||||
@ -72,8 +75,5 @@ namespace UnityExplorer.UI.Panels
|
|||||||
this.Rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, 500f);
|
this.Rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, 500f);
|
||||||
this.Rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, 500f);
|
this.Rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, 500f);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void DoSaveToConfigElement() { }
|
|
||||||
public override string GetSaveDataFromConfigManager() => null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,24 +1,19 @@
|
|||||||
using HarmonyLib;
|
using System.Collections.Generic;
|
||||||
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;
|
||||||
using UnityEngine.EventSystems;
|
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.Config;
|
using UnityExplorer.Config;
|
||||||
using UnityExplorer.CSConsole;
|
using UnityExplorer.CSConsole;
|
||||||
using UnityExplorer.Inspectors;
|
using UnityExplorer.Inspectors;
|
||||||
using UnityExplorer.UI.Panels;
|
using UnityExplorer.UI.Panels;
|
||||||
using UnityExplorer.UI.Widgets;
|
|
||||||
using UnityExplorer.UI.Widgets.AutoComplete;
|
using UnityExplorer.UI.Widgets.AutoComplete;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
using UniverseLib.Input;
|
using UniverseLib.Input;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
|
using UniverseLib.UI.Models;
|
||||||
|
using UniverseLib.UI.ObjectPool;
|
||||||
using UniverseLib.UI.Widgets;
|
using UniverseLib.UI.Widgets;
|
||||||
|
using UniverseLib.UI.Widgets.ScrollView;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.UI
|
namespace UnityExplorer.UI
|
||||||
{
|
{
|
||||||
@ -48,13 +43,13 @@ namespace UnityExplorer.UI
|
|||||||
|
|
||||||
public static bool Initializing { get; internal set; } = true;
|
public static bool Initializing { get; internal set; } = true;
|
||||||
|
|
||||||
private static UIBase uiBase;
|
internal static UIBase UiBase { get; private set; }
|
||||||
public static GameObject UIRoot => uiBase?.RootObject;
|
public static GameObject UIRoot => UiBase?.RootObject;
|
||||||
public static RectTransform UIRootRect => _uiRootRect ??= UIRoot.GetComponent<RectTransform>();
|
public static RectTransform UIRootRect { get; private set; }
|
||||||
private static RectTransform _uiRootRect;
|
public static Canvas UICanvas { get; private set; }
|
||||||
|
|
||||||
internal static GameObject PanelHolder { get; private set; }
|
internal static GameObject PanelHolder { get; private set; }
|
||||||
private static readonly Dictionary<Panels, UIPanel> UIPanels = new();
|
internal static readonly Dictionary<Panels, UIPanel> UIPanels = new();
|
||||||
|
|
||||||
public static RectTransform NavBarRect;
|
public static RectTransform NavBarRect;
|
||||||
public static GameObject NavbarTabButtonHolder;
|
public static GameObject NavbarTabButtonHolder;
|
||||||
@ -71,13 +66,14 @@ namespace UnityExplorer.UI
|
|||||||
|
|
||||||
public static bool ShowMenu
|
public static bool ShowMenu
|
||||||
{
|
{
|
||||||
get => uiBase != null && uiBase.Enabled;
|
get => UiBase != null && UiBase.Enabled;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (uiBase == null || !UIRoot || uiBase.Enabled == value)
|
if (UiBase == null || !UIRoot || UiBase.Enabled == value)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
UniversalUI.SetUIActive(ExplorerCore.GUID, value);
|
UniversalUI.SetUIActive(ExplorerCore.GUID, value);
|
||||||
|
UniversalUI.SetUIActive(MouseInspector.UIBaseGUID, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,11 +81,16 @@ namespace UnityExplorer.UI
|
|||||||
|
|
||||||
internal static void InitUI()
|
internal static void InitUI()
|
||||||
{
|
{
|
||||||
uiBase = UniversalUI.RegisterUI(ExplorerCore.GUID, Update);
|
UiBase = UniversalUI.RegisterUI(ExplorerCore.GUID, Update);
|
||||||
|
|
||||||
lastScreenWidth = Screen.width;
|
UIRootRect = UIRoot.GetComponent<RectTransform>();
|
||||||
lastScreenHeight = Screen.height;
|
UICanvas = UIRoot.GetComponent<Canvas>();
|
||||||
|
|
||||||
|
DisplayManager.Init();
|
||||||
|
|
||||||
|
Display display = DisplayManager.ActiveDisplay;
|
||||||
|
lastScreenWidth = display.renderingWidth;
|
||||||
|
lastScreenHeight = display.renderingHeight;
|
||||||
|
|
||||||
// Create UI.
|
// Create UI.
|
||||||
CreatePanelHolder();
|
CreatePanelHolder();
|
||||||
@ -105,7 +106,7 @@ namespace UnityExplorer.UI
|
|||||||
UIPanels.Add(Panels.ConsoleLog, new LogPanel());
|
UIPanels.Add(Panels.ConsoleLog, new LogPanel());
|
||||||
UIPanels.Add(Panels.Options, new OptionsPanel());
|
UIPanels.Add(Panels.Options, new OptionsPanel());
|
||||||
UIPanels.Add(Panels.UIInspectorResults, new UiInspectorResultsPanel());
|
UIPanels.Add(Panels.UIInspectorResults, new UiInspectorResultsPanel());
|
||||||
UIPanels.Add(Panels.MouseInspector, new InspectUnderMouse());
|
UIPanels.Add(Panels.MouseInspector, new MouseInspector());
|
||||||
|
|
||||||
foreach (var panel in UIPanels.Values)
|
foreach (var panel in UIPanels.Values)
|
||||||
panel.ConstructUI();
|
panel.ConstructUI();
|
||||||
@ -134,12 +135,9 @@ namespace UnityExplorer.UI
|
|||||||
if (!UIRoot)
|
if (!UIRoot)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// if doing Mouse Inspect, update that and return.
|
// If we are doing a Mouse Inspect, we don't need to update anything else.
|
||||||
if (InspectUnderMouse.Inspecting)
|
if (MouseInspector.Instance.TryUpdate())
|
||||||
{
|
|
||||||
InspectUnderMouse.Instance.UpdateInspect();
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
// Update Notification modal
|
// Update Notification modal
|
||||||
Notification.Update();
|
Notification.Update();
|
||||||
@ -169,7 +167,8 @@ namespace UnityExplorer.UI
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check screen dimension change
|
// check screen dimension change
|
||||||
if (Screen.width != lastScreenWidth || Screen.height != lastScreenHeight)
|
var display = DisplayManager.ActiveDisplay;
|
||||||
|
if (display.renderingWidth != lastScreenWidth || display.renderingHeight != lastScreenHeight)
|
||||||
OnScreenDimensionsChanged();
|
OnScreenDimensionsChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,26 +184,21 @@ namespace UnityExplorer.UI
|
|||||||
SetPanelActive(panel, !uiPanel.Enabled);
|
SetPanelActive(panel, !uiPanel.Enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SetPanelActive(Panels panel, bool active)
|
public static void SetPanelActive(Panels panelType, bool active)
|
||||||
{
|
{
|
||||||
var obj = GetPanel(panel);
|
GetPanel(panelType)
|
||||||
SetPanelActive(obj, active);
|
.SetActive(active);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SetPanelActive(UIPanel panel, bool active)
|
public static void SetPanelActive(UIPanel panel, bool active)
|
||||||
{
|
{
|
||||||
panel.SetActive(active);
|
panel.SetActive(active);
|
||||||
if (active)
|
|
||||||
{
|
|
||||||
panel.UIRoot.transform.SetAsLastSibling();
|
|
||||||
UIPanel.InvokeOnPanelsReordered();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void SetPanelActive(Transform transform, bool value)
|
internal static void SetPanelActive(Transform transform, bool value)
|
||||||
{
|
{
|
||||||
if (UIPanel.transformToPanelDict.TryGetValue(transform.GetInstanceID(), out UIPanel panel))
|
if (UIPanel.transformToPanelDict.TryGetValue(transform.GetInstanceID(), out UIPanel panel))
|
||||||
SetPanelActive(panel, value);
|
panel.SetActive(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// navbar
|
// navbar
|
||||||
@ -233,8 +227,9 @@ namespace UnityExplorer.UI
|
|||||||
|
|
||||||
private static void OnScreenDimensionsChanged()
|
private static void OnScreenDimensionsChanged()
|
||||||
{
|
{
|
||||||
lastScreenWidth = Screen.width;
|
var display = DisplayManager.ActiveDisplay;
|
||||||
lastScreenHeight = Screen.height;
|
lastScreenWidth = display.renderingWidth;
|
||||||
|
lastScreenHeight = display.renderingHeight;
|
||||||
|
|
||||||
foreach (var panel in UIPanels)
|
foreach (var panel in UIPanels)
|
||||||
{
|
{
|
||||||
@ -254,6 +249,8 @@ namespace UnityExplorer.UI
|
|||||||
closeBtn.ButtonText.text = val.ToString();
|
closeBtn.ButtonText.text = val.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Time controls
|
||||||
|
|
||||||
private static void OnTimeInputEndEdit(string val)
|
private static void OnTimeInputEndEdit(string val)
|
||||||
{
|
{
|
||||||
if (pauseButtonPausing)
|
if (pauseButtonPausing)
|
||||||
@ -284,7 +281,7 @@ namespace UnityExplorer.UI
|
|||||||
timeInput.Component.textComponent.color = pauseButtonPausing ? Color.grey : Color.white;
|
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);
|
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);
|
RuntimeHelper.SetColorBlock(pauseBtn.Component, color, color * 1.2f, color * 0.7f);
|
||||||
pauseBtn.ButtonText.text = pauseButtonPausing ? "►" : "||";
|
pauseBtn.ButtonText.text = pauseButtonPausing ? "►" : "||";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -352,7 +349,7 @@ namespace UnityExplorer.UI
|
|||||||
|
|
||||||
closeBtn = UIFactory.CreateButton(navbarPanel, "CloseButton", ConfigManager.Master_Toggle.Value.ToString());
|
closeBtn = UIFactory.CreateButton(navbarPanel, "CloseButton", ConfigManager.Master_Toggle.Value.ToString());
|
||||||
UIFactory.SetLayoutElement(closeBtn.Component.gameObject, minHeight: 25, minWidth: 80, flexibleWidth: 0);
|
UIFactory.SetLayoutElement(closeBtn.Component.gameObject, minHeight: 25, minWidth: 80, flexibleWidth: 0);
|
||||||
RuntimeProvider.Instance.SetColorBlock(closeBtn.Component, new Color(0.63f, 0.32f, 0.31f),
|
RuntimeHelper.SetColorBlock(closeBtn.Component, new Color(0.63f, 0.32f, 0.31f),
|
||||||
new Color(0.81f, 0.25f, 0.2f), new Color(0.6f, 0.18f, 0.16f));
|
new Color(0.81f, 0.25f, 0.2f), new Color(0.6f, 0.18f, 0.16f));
|
||||||
|
|
||||||
ConfigManager.Master_Toggle.OnValueChanged += Master_Toggle_OnValueChanged;
|
ConfigManager.Master_Toggle.OnValueChanged += Master_Toggle_OnValueChanged;
|
||||||
|
@ -4,6 +4,8 @@ using System.Collections.Specialized;
|
|||||||
using UnityExplorer.CacheObject.IValues;
|
using UnityExplorer.CacheObject.IValues;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
|
using UniverseLib.UI.Models;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Widgets.AutoComplete
|
namespace UnityExplorer.UI.Widgets.AutoComplete
|
||||||
{
|
{
|
||||||
|
@ -5,6 +5,7 @@ using System.Text;
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
|
using UniverseLib.UI.Models;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Widgets.AutoComplete
|
namespace UnityExplorer.UI.Widgets.AutoComplete
|
||||||
{
|
{
|
||||||
|
@ -1,14 +1,16 @@
|
|||||||
using System;
|
using HarmonyLib;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
|
using UniverseLib.UI.Models;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Widgets.AutoComplete
|
namespace UnityExplorer.UI.Widgets.AutoComplete
|
||||||
{
|
{
|
||||||
public class TypeCompleter : ISuggestionProvider
|
public class TypeCompleter : ISuggestionProvider
|
||||||
{
|
{
|
||||||
internal static readonly Dictionary<string, string> sharedTypeToLabel = new Dictionary<string, string>(4096);
|
|
||||||
|
|
||||||
public bool Enabled
|
public bool Enabled
|
||||||
{
|
{
|
||||||
get => _enabled;
|
get => _enabled;
|
||||||
@ -25,14 +27,16 @@ namespace UnityExplorer.UI.Widgets.AutoComplete
|
|||||||
|
|
||||||
public Type BaseType { get; set; }
|
public Type BaseType { get; set; }
|
||||||
public Type[] GenericConstraints { get; set; }
|
public Type[] GenericConstraints { get; set; }
|
||||||
|
public bool AllTypes { get; set; }
|
||||||
|
|
||||||
private readonly bool allowAbstract;
|
private readonly bool allowAbstract;
|
||||||
private readonly bool allowEnum;
|
private readonly bool allowEnum;
|
||||||
|
|
||||||
public InputFieldRef InputField { get; }
|
public InputFieldRef InputField { get; }
|
||||||
public bool AnchorToCaretPosition => false;
|
public bool AnchorToCaretPosition => false;
|
||||||
|
|
||||||
private readonly List<Suggestion> suggestions = new List<Suggestion>();
|
private readonly List<Suggestion> suggestions = new();
|
||||||
private readonly HashSet<string> suggestedNames = new HashSet<string>();
|
private readonly HashSet<string> suggestedNames = new();
|
||||||
|
|
||||||
private HashSet<Type> allowedTypes;
|
private HashSet<Type> allowedTypes;
|
||||||
|
|
||||||
@ -58,7 +62,24 @@ namespace UnityExplorer.UI.Widgets.AutoComplete
|
|||||||
|
|
||||||
public void CacheTypes()
|
public void CacheTypes()
|
||||||
{
|
{
|
||||||
allowedTypes = ReflectionUtility.GetImplementationsOf(BaseType, allowAbstract, allowEnum, false);
|
if (!AllTypes)
|
||||||
|
allowedTypes = ReflectionUtility.GetImplementationsOf(BaseType, allowAbstract, allowEnum, false);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
allowedTypes = new();
|
||||||
|
foreach (var entry in ReflectionUtility.AllTypes)
|
||||||
|
{
|
||||||
|
// skip <PrivateImplementationDetails> and <AnonymousClass> classes
|
||||||
|
var type = entry.Value;
|
||||||
|
if (type.FullName.Contains("PrivateImplementationDetails")
|
||||||
|
|| type.FullName.Contains("DisplayClass")
|
||||||
|
|| type.FullName.Contains('<'))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
allowedTypes.Add(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnSuggestionClicked(Suggestion suggestion)
|
public void OnSuggestionClicked(Suggestion suggestion)
|
||||||
@ -112,6 +133,8 @@ namespace UnityExplorer.UI.Widgets.AutoComplete
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static readonly Dictionary<string, string> sharedTypeToLabel = new();
|
||||||
|
|
||||||
void AddSuggestion(Type type)
|
void AddSuggestion(Type type)
|
||||||
{
|
{
|
||||||
if (suggestedNames.Contains(type.FullName))
|
if (suggestedNames.Contains(type.FullName))
|
||||||
|
@ -7,6 +7,7 @@ using UnityEngine.UI;
|
|||||||
using UnityExplorer.UI.Widgets.AutoComplete;
|
using UnityExplorer.UI.Widgets.AutoComplete;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
using UniverseLib.UI.Models;
|
using UniverseLib.UI.Models;
|
||||||
|
using UniverseLib.UI.ObjectPool;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Widgets
|
namespace UnityExplorer.UI.Widgets
|
||||||
{
|
{
|
||||||
|
@ -11,6 +11,8 @@ using UnityExplorer.UI.Widgets.AutoComplete;
|
|||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
using UnityExplorer.CacheObject;
|
using UnityExplorer.CacheObject;
|
||||||
|
using UniverseLib.UI.ObjectPool;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Widgets
|
namespace UnityExplorer.UI.Widgets
|
||||||
{
|
{
|
||||||
@ -75,6 +77,9 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
|
|
||||||
public object[] TryParseArguments()
|
public object[] TryParseArguments()
|
||||||
{
|
{
|
||||||
|
if (!parameters.Any())
|
||||||
|
return ArgumentUtility.EmptyArgs;
|
||||||
|
|
||||||
object[] outArgs = new object[parameters.Length];
|
object[] outArgs = new object[parameters.Length];
|
||||||
|
|
||||||
for (int i = 0; i < parameters.Length; i++)
|
for (int i = 0; i < parameters.Length; i++)
|
||||||
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Widgets
|
namespace UnityExplorer.UI.Widgets
|
||||||
{
|
{
|
||||||
|
@ -10,6 +10,8 @@ using UnityExplorer.UI.Panels;
|
|||||||
using UnityExplorer.UI.Widgets.AutoComplete;
|
using UnityExplorer.UI.Widgets.AutoComplete;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
|
using UniverseLib.UI.Models;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Widgets
|
namespace UnityExplorer.UI.Widgets
|
||||||
{
|
{
|
||||||
|
@ -10,43 +10,50 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
{
|
{
|
||||||
public TransformTree Tree { get; }
|
public TransformTree Tree { get; }
|
||||||
public Transform Value { get; private set; }
|
public Transform Value { get; private set; }
|
||||||
public int InstanceID { get; private set; }
|
public int InstanceID { get; }
|
||||||
public CachedTransform Parent { get; internal set; }
|
public CachedTransform Parent { get; internal set; }
|
||||||
|
|
||||||
public int Depth { get; internal set; }
|
public int Depth { get; internal set; }
|
||||||
public int ChildCount { get; internal set; }
|
public int ChildCount { get; internal set; }
|
||||||
public string Name { get; internal set; }
|
public string Name { get; internal set; }
|
||||||
public bool Enabled { get; internal set; }
|
public bool Enabled { get; internal set; }
|
||||||
|
public int SiblingIndex { get; internal set; }
|
||||||
|
|
||||||
public bool Expanded => Tree.IsCellExpanded(InstanceID);
|
public bool Expanded => Tree.IsTransformExpanded(InstanceID);
|
||||||
|
|
||||||
public CachedTransform(TransformTree tree, Transform transform, int depth, CachedTransform parent = null)
|
public CachedTransform(TransformTree tree, Transform transform, int depth, CachedTransform parent = null)
|
||||||
{
|
{
|
||||||
|
InstanceID = transform.GetInstanceID();
|
||||||
|
|
||||||
Tree = tree;
|
Tree = tree;
|
||||||
Value = transform;
|
Value = transform;
|
||||||
Parent = parent;
|
Parent = parent;
|
||||||
InstanceID = transform.GetInstanceID();
|
SiblingIndex = transform.GetSiblingIndex();
|
||||||
Update(transform, depth);
|
Update(transform, depth);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Update(Transform transform, int depth)
|
public bool Update(Transform transform, int depth)
|
||||||
{
|
{
|
||||||
bool ret = false;
|
bool changed = false;
|
||||||
|
|
||||||
if (Value != transform
|
if (Value != transform
|
||||||
|| depth != Depth
|
|| depth != Depth
|
||||||
|| ChildCount != transform.childCount
|
|| ChildCount != transform.childCount
|
||||||
|| Name != transform.name
|
|| Name != transform.name
|
||||||
|| Enabled != transform.gameObject.activeSelf)
|
|| Enabled != transform.gameObject.activeSelf
|
||||||
|
|| SiblingIndex != transform.GetSiblingIndex())
|
||||||
{
|
{
|
||||||
|
changed = true;
|
||||||
|
|
||||||
Value = transform;
|
Value = transform;
|
||||||
Depth = depth;
|
Depth = depth;
|
||||||
ChildCount = transform.childCount;
|
ChildCount = transform.childCount;
|
||||||
Name = transform.name;
|
Name = transform.name;
|
||||||
Enabled = transform.gameObject.activeSelf;
|
Enabled = transform.gameObject.activeSelf;
|
||||||
ret = true;
|
SiblingIndex = transform.GetSiblingIndex();
|
||||||
}
|
}
|
||||||
return ret;
|
|
||||||
|
return changed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
using System;
|
using HarmonyLib;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
@ -8,7 +10,10 @@ using UnityExplorer.Inspectors;
|
|||||||
using UnityExplorer.UI.Widgets;
|
using UnityExplorer.UI.Widgets;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
|
using UniverseLib.UI.Models;
|
||||||
using UniverseLib.UI.Widgets;
|
using UniverseLib.UI.Widgets;
|
||||||
|
using UniverseLib.UI.Widgets.ScrollView;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Widgets
|
namespace UnityExplorer.UI.Widgets
|
||||||
{
|
{
|
||||||
@ -16,15 +21,14 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
{
|
{
|
||||||
public float DefaultHeight => 25f;
|
public float DefaultHeight => 25f;
|
||||||
|
|
||||||
public bool Enabled => m_enabled;
|
public bool Enabled => enabled;
|
||||||
private bool m_enabled;
|
private bool enabled;
|
||||||
|
|
||||||
public Action<CachedTransform> OnExpandToggled;
|
public Action<CachedTransform> OnExpandToggled;
|
||||||
public Action<CachedTransform> OnEnableToggled;
|
public Action<CachedTransform> OnEnableToggled;
|
||||||
public Action<GameObject> OnGameObjectClicked;
|
public Action<GameObject> OnGameObjectClicked;
|
||||||
|
|
||||||
public CachedTransform cachedTransform;
|
public CachedTransform cachedTransform;
|
||||||
public int _cellIndex;
|
|
||||||
|
|
||||||
public GameObject UIRoot { get; set; }
|
public GameObject UIRoot { get; set; }
|
||||||
public RectTransform Rect { get; set; }
|
public RectTransform Rect { get; set; }
|
||||||
@ -32,22 +36,23 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
public ButtonRef ExpandButton;
|
public ButtonRef ExpandButton;
|
||||||
public ButtonRef NameButton;
|
public ButtonRef NameButton;
|
||||||
public Toggle EnabledToggle;
|
public Toggle EnabledToggle;
|
||||||
|
public InputFieldRef SiblingIndex;
|
||||||
|
|
||||||
public LayoutElement spacer;
|
public LayoutElement spacer;
|
||||||
|
|
||||||
public void Enable()
|
public void Enable()
|
||||||
{
|
{
|
||||||
m_enabled = true;
|
enabled = true;
|
||||||
UIRoot.SetActive(true);
|
UIRoot.SetActive(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Disable()
|
public void Disable()
|
||||||
{
|
{
|
||||||
m_enabled = false;
|
enabled = false;
|
||||||
UIRoot.SetActive(false);
|
UIRoot.SetActive(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ConfigureCell(CachedTransform cached, int cellIndex)
|
public void ConfigureCell(CachedTransform cached)
|
||||||
{
|
{
|
||||||
if (cached == null)
|
if (cached == null)
|
||||||
{
|
{
|
||||||
@ -58,18 +63,29 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
if (!Enabled)
|
if (!Enabled)
|
||||||
Enable();
|
Enable();
|
||||||
|
|
||||||
_cellIndex = cellIndex;
|
|
||||||
cachedTransform = cached;
|
cachedTransform = cached;
|
||||||
|
|
||||||
spacer.minWidth = cached.Depth * 15;
|
spacer.minWidth = cached.Depth * 15;
|
||||||
|
|
||||||
if (cached.Value)
|
if (cached.Value)
|
||||||
{
|
{
|
||||||
NameButton.ButtonText.text = cached.Value.name;
|
string name = cached.Value.name?.Trim();
|
||||||
|
if (string.IsNullOrEmpty(name))
|
||||||
|
name = "<i><color=grey>untitled</color></i>";
|
||||||
|
NameButton.ButtonText.text = name;
|
||||||
NameButton.ButtonText.color = cached.Value.gameObject.activeSelf ? Color.white : Color.grey;
|
NameButton.ButtonText.color = cached.Value.gameObject.activeSelf ? Color.white : Color.grey;
|
||||||
|
|
||||||
EnabledToggle.Set(cached.Value.gameObject.activeSelf, false);
|
EnabledToggle.Set(cached.Value.gameObject.activeSelf, false);
|
||||||
|
|
||||||
|
if (!cached.Value.parent)
|
||||||
|
SiblingIndex.GameObject.SetActive(false);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SiblingIndex.GameObject.SetActive(true);
|
||||||
|
if (!SiblingIndex.Component.isFocused)
|
||||||
|
SiblingIndex.Text = cached.Value.GetSiblingIndex().ToString();
|
||||||
|
}
|
||||||
|
|
||||||
int childCount = cached.Value.childCount;
|
int childCount = cached.Value.childCount;
|
||||||
if (childCount > 0)
|
if (childCount > 0)
|
||||||
{
|
{
|
||||||
@ -90,6 +106,8 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
{
|
{
|
||||||
NameButton.ButtonText.text = $"[Destroyed]";
|
NameButton.ButtonText.text = $"[Destroyed]";
|
||||||
NameButton.ButtonText.color = Color.red;
|
NameButton.ButtonText.color = Color.red;
|
||||||
|
|
||||||
|
SiblingIndex.GameObject.SetActive(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,6 +129,17 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
OnEnableToggled?.Invoke(cachedTransform);
|
OnEnableToggled?.Invoke(cachedTransform);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnSiblingIndexEndEdit(string input)
|
||||||
|
{
|
||||||
|
if (this.cachedTransform == null || !this.cachedTransform.Value)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (int.TryParse(input.Trim(), out int index))
|
||||||
|
this.cachedTransform.Value.SetSiblingIndex(index);
|
||||||
|
|
||||||
|
this.SiblingIndex.Text = this.cachedTransform.Value.GetSiblingIndex().ToString();
|
||||||
|
}
|
||||||
|
|
||||||
public GameObject CreateContent(GameObject parent)
|
public GameObject CreateContent(GameObject parent)
|
||||||
{
|
{
|
||||||
UIRoot = UIFactory.CreateUIObject("TransformCell", parent);
|
UIRoot = UIFactory.CreateUIObject("TransformCell", parent);
|
||||||
@ -122,7 +151,7 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
Rect.sizeDelta = new Vector2(25, 25);
|
Rect.sizeDelta = new Vector2(25, 25);
|
||||||
UIFactory.SetLayoutElement(UIRoot, minWidth: 100, flexibleWidth: 9999, minHeight: 25, flexibleHeight: 0);
|
UIFactory.SetLayoutElement(UIRoot, minWidth: 100, flexibleWidth: 9999, minHeight: 25, flexibleHeight: 0);
|
||||||
|
|
||||||
var spacerObj = UIFactory.CreateUIObject("Spacer", UIRoot, new Vector2(0, 0));
|
GameObject spacerObj = UIFactory.CreateUIObject("Spacer", UIRoot, new Vector2(0, 0));
|
||||||
UIFactory.SetLayoutElement(spacerObj, minWidth: 0, flexibleWidth: 0, minHeight: 0, flexibleHeight: 0);
|
UIFactory.SetLayoutElement(spacerObj, minWidth: 0, flexibleWidth: 0, minHeight: 0, flexibleHeight: 0);
|
||||||
this.spacer = spacerObj.GetComponent<LayoutElement>();
|
this.spacer = spacerObj.GetComponent<LayoutElement>();
|
||||||
|
|
||||||
@ -133,24 +162,41 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
|
|
||||||
// Enabled toggle
|
// Enabled toggle
|
||||||
|
|
||||||
var toggleObj = UIFactory.CreateToggle(UIRoot, "BehaviourToggle", out EnabledToggle, out var behavText, default, 17, 17);
|
GameObject toggleObj = UIFactory.CreateToggle(UIRoot, "BehaviourToggle", out EnabledToggle, out Text behavText, default, 17, 17);
|
||||||
UIFactory.SetLayoutElement(toggleObj, minHeight: 17, flexibleHeight: 0, minWidth: 17);
|
UIFactory.SetLayoutElement(toggleObj, minHeight: 17, flexibleHeight: 0, minWidth: 17);
|
||||||
EnabledToggle.onValueChanged.AddListener(OnEnableClicked);
|
EnabledToggle.onValueChanged.AddListener(OnEnableClicked);
|
||||||
|
|
||||||
// Name button
|
// Name button
|
||||||
|
|
||||||
NameButton = UIFactory.CreateButton(this.UIRoot, "NameButton", "Name", null);
|
GameObject nameBtnHolder = UIFactory.CreateHorizontalGroup(this.UIRoot, "NameButtonHolder",
|
||||||
|
false, false, true, true, childAlignment: TextAnchor.MiddleLeft);
|
||||||
|
UIFactory.SetLayoutElement(nameBtnHolder, flexibleWidth: 9999, minHeight: 25, flexibleHeight: 0);
|
||||||
|
nameBtnHolder.AddComponent<Mask>().showMaskGraphic = false;
|
||||||
|
|
||||||
|
NameButton = UIFactory.CreateButton(nameBtnHolder, "NameButton", "Name", null);
|
||||||
UIFactory.SetLayoutElement(NameButton.Component.gameObject, flexibleWidth: 9999, minHeight: 25, flexibleHeight: 0);
|
UIFactory.SetLayoutElement(NameButton.Component.gameObject, flexibleWidth: 9999, minHeight: 25, flexibleHeight: 0);
|
||||||
var nameLabel = NameButton.Component.GetComponentInChildren<Text>();
|
Text nameLabel = NameButton.Component.GetComponentInChildren<Text>();
|
||||||
nameLabel.horizontalOverflow = HorizontalWrapMode.Overflow;
|
nameLabel.horizontalOverflow = HorizontalWrapMode.Overflow;
|
||||||
nameLabel.alignment = TextAnchor.MiddleLeft;
|
nameLabel.alignment = TextAnchor.MiddleLeft;
|
||||||
|
|
||||||
Color normal = new Color(0.11f, 0.11f, 0.11f);
|
// Sibling index input
|
||||||
Color highlight = new Color(0.25f, 0.25f, 0.25f);
|
|
||||||
Color pressed = new Color(0.05f, 0.05f, 0.05f);
|
SiblingIndex = UIFactory.CreateInputField(this.UIRoot, "SiblingIndexInput", string.Empty);
|
||||||
Color disabled = new Color(1, 1, 1, 0);
|
SiblingIndex.Component.textComponent.fontSize = 11;
|
||||||
RuntimeProvider.Instance.SetColorBlock(ExpandButton.Component, normal, highlight, pressed, disabled);
|
SiblingIndex.Component.textComponent.alignment = TextAnchor.MiddleRight;
|
||||||
RuntimeProvider.Instance.SetColorBlock(NameButton.Component, normal, highlight, pressed, disabled);
|
Image siblingImage = SiblingIndex.GameObject.GetComponent<Image>();
|
||||||
|
siblingImage.color = new(0f, 0f, 0f, 0.25f);
|
||||||
|
UIFactory.SetLayoutElement(SiblingIndex.GameObject, 35, 20, 0, 0);
|
||||||
|
SiblingIndex.Component.GetOnEndEdit().AddListener(OnSiblingIndexEndEdit);
|
||||||
|
|
||||||
|
// Setup selectables
|
||||||
|
|
||||||
|
Color normal = new(0.11f, 0.11f, 0.11f);
|
||||||
|
Color highlight = new(0.25f, 0.25f, 0.25f);
|
||||||
|
Color pressed = new(0.05f, 0.05f, 0.05f);
|
||||||
|
Color disabled = new(1, 1, 1, 0);
|
||||||
|
RuntimeHelper.SetColorBlock(ExpandButton.Component, normal, highlight, pressed, disabled);
|
||||||
|
RuntimeHelper.SetColorBlock(NameButton.Component, normal, highlight, pressed, disabled);
|
||||||
|
|
||||||
NameButton.OnClick += OnMainButtonClicked;
|
NameButton.OnClick += OnMainButtonClicked;
|
||||||
ExpandButton.OnClick += OnExpandClicked;
|
ExpandButton.OnClick += OnExpandClicked;
|
||||||
|
@ -2,12 +2,11 @@
|
|||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Specialized;
|
using System.Collections.Specialized;
|
||||||
using System.Linq;
|
using System.Diagnostics;
|
||||||
using System.Text;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
using UniverseLib.UI.Widgets;
|
using UniverseLib.UI.Widgets.ScrollView;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Widgets
|
namespace UnityExplorer.UI.Widgets
|
||||||
{
|
{
|
||||||
@ -18,22 +17,36 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
|
|
||||||
public ScrollPool<TransformCell> ScrollPool;
|
public ScrollPool<TransformCell> ScrollPool;
|
||||||
|
|
||||||
|
// IMPORTANT CAVEAT WITH OrderedDictionary:
|
||||||
|
// While the performance is mostly good, there are two methods we should NEVER use:
|
||||||
|
// - Remove(object)
|
||||||
|
// - set_Item[object]
|
||||||
|
// These two methods have extremely bad performance due to using IndexOfKey(), which iterates the whole dictionary.
|
||||||
|
// Currently we do not use either of these methods, so everything should be constant time lookups.
|
||||||
|
// We DO make use of get_Item[object], get_Item[index], Add, Insert, Contains and RemoveAt, which OrderedDictionary meets our needs for.
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Key: UnityEngine.Transform instance ID<br/>
|
/// Key: UnityEngine.Transform instance ID<br/>
|
||||||
/// Value: CachedTransform
|
/// Value: CachedTransform
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal readonly OrderedDictionary cachedTransforms = new OrderedDictionary();
|
internal readonly OrderedDictionary cachedTransforms = new();
|
||||||
|
|
||||||
// for keeping track of which actual transforms are expanded or not, outside of the cache data.
|
// for keeping track of which actual transforms are expanded or not, outside of the cache data.
|
||||||
private readonly HashSet<int> expandedInstanceIDs = new HashSet<int>();
|
private readonly HashSet<int> expandedInstanceIDs = new();
|
||||||
private readonly HashSet<int> autoExpandedIDs = new HashSet<int>();
|
private readonly HashSet<int> autoExpandedIDs = new();
|
||||||
|
|
||||||
private readonly HashSet<int> visited = new HashSet<int>();
|
// state for Traverse parse
|
||||||
private bool needRefresh;
|
private readonly HashSet<int> visited = new();
|
||||||
|
private bool needRefreshUI;
|
||||||
private int displayIndex;
|
private int displayIndex;
|
||||||
|
int prevDisplayIndex;
|
||||||
|
|
||||||
public int ItemCount => cachedTransforms.Count;
|
private Coroutine refreshCoroutine;
|
||||||
|
private readonly Stopwatch traversedThisFrame = new();
|
||||||
|
|
||||||
|
// ScrollPool item count. PrevDisplayIndex is the highest index + 1 from our last traverse.
|
||||||
|
public int ItemCount => prevDisplayIndex;
|
||||||
|
|
||||||
|
// Search filter
|
||||||
public bool Filtering => !string.IsNullOrEmpty(currentFilter);
|
public bool Filtering => !string.IsNullOrEmpty(currentFilter);
|
||||||
private bool wasFiltering;
|
private bool wasFiltering;
|
||||||
|
|
||||||
@ -60,44 +73,24 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
GetRootEntriesMethod = getRootEntriesMethod;
|
GetRootEntriesMethod = getRootEntriesMethod;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnCellBorrowed(TransformCell cell)
|
// Initialize and reset
|
||||||
{
|
|
||||||
cell.OnExpandToggled += OnCellExpandToggled;
|
|
||||||
cell.OnGameObjectClicked += OnGameObjectClicked;
|
|
||||||
cell.OnEnableToggled += OnCellEnableToggled;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnGameObjectClicked(GameObject obj)
|
|
||||||
{
|
|
||||||
if (OnClickOverrideHandler != null)
|
|
||||||
OnClickOverrideHandler.Invoke(obj);
|
|
||||||
else
|
|
||||||
InspectorManager.Inspect(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnCellExpandToggled(CachedTransform cache)
|
|
||||||
{
|
|
||||||
var instanceID = cache.InstanceID;
|
|
||||||
if (expandedInstanceIDs.Contains(instanceID))
|
|
||||||
expandedInstanceIDs.Remove(instanceID);
|
|
||||||
else
|
|
||||||
expandedInstanceIDs.Add(instanceID);
|
|
||||||
|
|
||||||
RefreshData(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnCellEnableToggled(CachedTransform cache)
|
|
||||||
{
|
|
||||||
cache.Value.gameObject.SetActive(!cache.Value.gameObject.activeSelf);
|
|
||||||
|
|
||||||
RefreshData(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Must be called externally from owner of this TransformTree
|
||||||
public void Init()
|
public void Init()
|
||||||
{
|
{
|
||||||
ScrollPool.Initialize(this);
|
ScrollPool.Initialize(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Called to completely reset the tree, ie. switching inspected GameObject
|
||||||
|
public void Rebuild()
|
||||||
|
{
|
||||||
|
autoExpandedIDs.Clear();
|
||||||
|
expandedInstanceIDs.Clear();
|
||||||
|
|
||||||
|
RefreshData(true, true, true, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called to completely wipe our data (ie, GameObject inspector returning to pool)
|
||||||
public void Clear()
|
public void Clear()
|
||||||
{
|
{
|
||||||
this.cachedTransforms.Clear();
|
this.cachedTransforms.Clear();
|
||||||
@ -105,14 +98,21 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
autoExpandedIDs.Clear();
|
autoExpandedIDs.Clear();
|
||||||
expandedInstanceIDs.Clear();
|
expandedInstanceIDs.Clear();
|
||||||
this.ScrollPool.Refresh(true, true);
|
this.ScrollPool.Refresh(true, true);
|
||||||
|
if (refreshCoroutine != null)
|
||||||
|
{
|
||||||
|
RuntimeHelper.StopCoroutine(refreshCoroutine);
|
||||||
|
refreshCoroutine = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsCellExpanded(int instanceID)
|
// Checks if the given Instance ID is expanded or not
|
||||||
|
public bool IsTransformExpanded(int instanceID)
|
||||||
{
|
{
|
||||||
return Filtering ? autoExpandedIDs.Contains(instanceID)
|
return Filtering ? autoExpandedIDs.Contains(instanceID)
|
||||||
: expandedInstanceIDs.Contains(instanceID);
|
: expandedInstanceIDs.Contains(instanceID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Jumps to a specific Transform in the tree and highlights it.
|
||||||
public void JumpAndExpandToTransform(Transform transform)
|
public void JumpAndExpandToTransform(Transform transform)
|
||||||
{
|
{
|
||||||
// make sure all parents of the object are expanded
|
// make sure all parents of the object are expanded
|
||||||
@ -126,8 +126,9 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
parent = parent.parent;
|
parent = parent.parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Refresh cached transforms (no UI rebuild yet)
|
// Refresh cached transforms (no UI rebuild yet).
|
||||||
RefreshData(false);
|
// Stop existing coroutine and do it oneshot.
|
||||||
|
RefreshData(false, false, true, true);
|
||||||
|
|
||||||
int transformID = transform.GetInstanceID();
|
int transformID = transform.GetInstanceID();
|
||||||
|
|
||||||
@ -145,7 +146,7 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
|
|
||||||
private void OnCellJumpedTo(TransformCell cell)
|
private void OnCellJumpedTo(TransformCell cell)
|
||||||
{
|
{
|
||||||
RuntimeProvider.Instance.StartCoroutine(HighlightCellCoroutine(cell));
|
RuntimeHelper.StartCoroutine(HighlightCellCoroutine(cell));
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerator HighlightCellCoroutine(TransformCell cell)
|
private IEnumerator HighlightCellCoroutine(TransformCell cell)
|
||||||
@ -160,81 +161,119 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
button.OnDeselect(null);
|
button.OnDeselect(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Rebuild()
|
// Perform a Traverse and optionally refresh the ScrollPool as well.
|
||||||
|
// If oneShot, then this happens instantly with no yield.
|
||||||
|
public void RefreshData(bool andRefreshUI, bool jumpToTop, bool stopExistingCoroutine, bool oneShot)
|
||||||
{
|
{
|
||||||
autoExpandedIDs.Clear();
|
if (refreshCoroutine != null)
|
||||||
expandedInstanceIDs.Clear();
|
{
|
||||||
|
if (stopExistingCoroutine)
|
||||||
|
{
|
||||||
|
RuntimeHelper.StopCoroutine(refreshCoroutine);
|
||||||
|
refreshCoroutine = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
RefreshData(true, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void RefreshData(bool andReload = false, bool jumpToTop = false)
|
|
||||||
{
|
|
||||||
visited.Clear();
|
visited.Clear();
|
||||||
displayIndex = 0;
|
displayIndex = 0;
|
||||||
needRefresh = false;
|
needRefreshUI = false;
|
||||||
|
traversedThisFrame.Reset();
|
||||||
|
traversedThisFrame.Start();
|
||||||
|
|
||||||
var rootObjects = GetRootEntriesMethod.Invoke();
|
refreshCoroutine = RuntimeHelper.StartCoroutine(RefreshCoroutine(andRefreshUI, jumpToTop, oneShot));
|
||||||
|
}
|
||||||
|
|
||||||
//int displayIndex = 0;
|
IEnumerator RefreshCoroutine(bool andRefreshUI, bool jumpToTop, bool oneShot)
|
||||||
foreach (var obj in rootObjects)
|
{
|
||||||
if (obj) Traverse(obj.transform);
|
// Instead of doing string.IsNullOrEmpty(CurrentFilter) many times, let's just do it once per update.
|
||||||
|
bool filtering = Filtering;
|
||||||
|
|
||||||
|
IEnumerable<GameObject> rootObjects = GetRootEntriesMethod();
|
||||||
|
foreach (var gameObj in rootObjects)
|
||||||
|
{
|
||||||
|
if (!gameObj)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
IEnumerator enumerator = Traverse(gameObj.transform, null, 0, oneShot, filtering);
|
||||||
|
while (enumerator.MoveNext())
|
||||||
|
{
|
||||||
|
if (!oneShot)
|
||||||
|
yield return enumerator.Current;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Prune displayed transforms that we didnt visit in that traverse
|
// Prune displayed transforms that we didnt visit in that traverse
|
||||||
for (int i = cachedTransforms.Count - 1; i >= 0; i--)
|
for (int i = cachedTransforms.Count - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
var obj = (CachedTransform)cachedTransforms[i];
|
var cached = (CachedTransform)cachedTransforms[i];
|
||||||
if (!visited.Contains(obj.InstanceID))
|
if (!visited.Contains(cached.InstanceID))
|
||||||
{
|
{
|
||||||
cachedTransforms.Remove(obj.InstanceID);
|
cachedTransforms.RemoveAt(i);
|
||||||
needRefresh = true;
|
needRefreshUI = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!needRefresh)
|
if (andRefreshUI && needRefreshUI)
|
||||||
return;
|
ScrollPool.Refresh(true, jumpToTop);
|
||||||
|
|
||||||
//displayedObjects.Clear();
|
prevDisplayIndex = displayIndex;
|
||||||
|
refreshCoroutine = null;
|
||||||
|
}
|
||||||
|
|
||||||
if (andReload)
|
// Recursive method to check a Transform and its children (if expanded).
|
||||||
{
|
// Parent and depth can be null/default.
|
||||||
if (!jumpToTop)
|
private IEnumerator Traverse(Transform transform, CachedTransform parent, int depth, bool oneShot, bool filtering)
|
||||||
ScrollPool.Refresh(true);
|
|
||||||
else
|
|
||||||
ScrollPool.Refresh(true, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Traverse(Transform transform, CachedTransform parent = null, int depth = 0)
|
|
||||||
{
|
{
|
||||||
|
// Let's only tank 2ms of each frame (60->53fps)
|
||||||
|
if (traversedThisFrame.ElapsedMilliseconds > 2)
|
||||||
|
{
|
||||||
|
yield return null;
|
||||||
|
traversedThisFrame.Reset();
|
||||||
|
traversedThisFrame.Start();
|
||||||
|
}
|
||||||
|
|
||||||
int instanceID = transform.GetInstanceID();
|
int instanceID = transform.GetInstanceID();
|
||||||
|
|
||||||
|
// Unlikely, but since this method is async it could theoretically happen in extremely rare circumstances
|
||||||
if (visited.Contains(instanceID))
|
if (visited.Contains(instanceID))
|
||||||
return;
|
yield break;
|
||||||
|
|
||||||
if (Filtering)
|
if (filtering)
|
||||||
{
|
{
|
||||||
if (!FilterHierarchy(transform))
|
if (!FilterHierarchy(transform))
|
||||||
return;
|
yield break;
|
||||||
|
|
||||||
visited.Add(instanceID);
|
|
||||||
|
|
||||||
if (!autoExpandedIDs.Contains(instanceID))
|
if (!autoExpandedIDs.Contains(instanceID))
|
||||||
autoExpandedIDs.Add(instanceID);
|
autoExpandedIDs.Add(instanceID);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
visited.Add(instanceID);
|
visited.Add(instanceID);
|
||||||
|
|
||||||
CachedTransform cached;
|
CachedTransform cached;
|
||||||
if (cachedTransforms.Contains(instanceID))
|
if (cachedTransforms.Contains(instanceID))
|
||||||
{
|
{
|
||||||
cached = (CachedTransform)cachedTransforms[(object)instanceID];
|
cached = (CachedTransform)cachedTransforms[(object)instanceID];
|
||||||
|
int prevSiblingIdx = cached.SiblingIndex;
|
||||||
if (cached.Update(transform, depth))
|
if (cached.Update(transform, depth))
|
||||||
needRefresh = true;
|
{
|
||||||
|
needRefreshUI = true;
|
||||||
|
|
||||||
|
// If the sibling index changed, we need to shuffle it in our cached transforms list.
|
||||||
|
if (prevSiblingIdx != cached.SiblingIndex)
|
||||||
|
{
|
||||||
|
cachedTransforms.Remove(instanceID);
|
||||||
|
if (cachedTransforms.Count <= displayIndex)
|
||||||
|
cachedTransforms.Add(instanceID, cached);
|
||||||
|
else
|
||||||
|
cachedTransforms.Insert(displayIndex, instanceID, cached);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
needRefresh = true;
|
needRefreshUI = true;
|
||||||
cached = new CachedTransform(this, transform, depth, parent);
|
cached = new CachedTransform(this, transform, depth, parent);
|
||||||
if (cachedTransforms.Count <= displayIndex)
|
if (cachedTransforms.Count <= displayIndex)
|
||||||
cachedTransforms.Add(instanceID, cached);
|
cachedTransforms.Add(instanceID, cached);
|
||||||
@ -244,10 +283,19 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
|
|
||||||
displayIndex++;
|
displayIndex++;
|
||||||
|
|
||||||
if (IsCellExpanded(instanceID) && cached.Value.childCount > 0)
|
if (IsTransformExpanded(instanceID) && cached.Value.childCount > 0)
|
||||||
{
|
{
|
||||||
|
ExplorerCore.Log($"Traversing expanded transform {cached.Value.name} ({cached.InstanceID})");
|
||||||
|
|
||||||
for (int i = 0; i < transform.childCount; i++)
|
for (int i = 0; i < transform.childCount; i++)
|
||||||
Traverse(transform.GetChild(i), cached, depth + 1);
|
{
|
||||||
|
var enumerator = Traverse(transform.GetChild(i), cached, depth + 1, oneShot, filtering);
|
||||||
|
while (enumerator.MoveNext())
|
||||||
|
{
|
||||||
|
if (!oneShot)
|
||||||
|
yield return enumerator.Current;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -270,17 +318,50 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
{
|
{
|
||||||
if (index < cachedTransforms.Count)
|
if (index < cachedTransforms.Count)
|
||||||
{
|
{
|
||||||
cell.ConfigureCell((CachedTransform)cachedTransforms[index], index);
|
cell.ConfigureCell((CachedTransform)cachedTransforms[index]);
|
||||||
if (Filtering)
|
if (Filtering)
|
||||||
{
|
{
|
||||||
if (cell.cachedTransform.Name.ContainsIgnoreCase(currentFilter))
|
if (cell.cachedTransform.Name.ContainsIgnoreCase(currentFilter))
|
||||||
{
|
|
||||||
cell.NameButton.ButtonText.color = Color.green;
|
cell.NameButton.ButtonText.color = Color.green;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
cell.Disable();
|
cell.Disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void OnCellBorrowed(TransformCell cell)
|
||||||
|
{
|
||||||
|
cell.OnExpandToggled += OnCellExpandToggled;
|
||||||
|
cell.OnGameObjectClicked += OnGameObjectClicked;
|
||||||
|
cell.OnEnableToggled += OnCellEnableToggled;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnGameObjectClicked(GameObject obj)
|
||||||
|
{
|
||||||
|
if (OnClickOverrideHandler != null)
|
||||||
|
OnClickOverrideHandler.Invoke(obj);
|
||||||
|
else
|
||||||
|
InspectorManager.Inspect(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnCellExpandToggled(CachedTransform cache)
|
||||||
|
{
|
||||||
|
ExplorerCore.Log($"OnCellExpandToggled: {cache.Value.name} ({cache.InstanceID})");
|
||||||
|
|
||||||
|
var instanceID = cache.InstanceID;
|
||||||
|
if (expandedInstanceIDs.Contains(instanceID))
|
||||||
|
expandedInstanceIDs.Remove(instanceID);
|
||||||
|
else
|
||||||
|
expandedInstanceIDs.Add(instanceID);
|
||||||
|
|
||||||
|
RefreshData(true, false, true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnCellEnableToggled(CachedTransform cache)
|
||||||
|
{
|
||||||
|
cache.Value.gameObject.SetActive(!cache.Value.gameObject.activeSelf);
|
||||||
|
|
||||||
|
RefreshData(true, false, true, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
409
src/UI/Widgets/UnityObjects/AudioClipWidget.cs
Normal file
409
src/UI/Widgets/UnityObjects/AudioClipWidget.cs
Normal file
@ -0,0 +1,409 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
using UnityExplorer.Config;
|
||||||
|
using UnityExplorer.Inspectors;
|
||||||
|
using UniverseLib;
|
||||||
|
using UniverseLib.UI;
|
||||||
|
using UniverseLib.UI.Models;
|
||||||
|
using UniverseLib.UI.ObjectPool;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
|
namespace UnityExplorer.UI.Widgets
|
||||||
|
{
|
||||||
|
public class AudioClipWidget : UnityObjectWidget
|
||||||
|
{
|
||||||
|
static GameObject AudioPlayerObject;
|
||||||
|
static AudioSource Source;
|
||||||
|
static AudioClipWidget CurrentlyPlaying;
|
||||||
|
static Coroutine CurrentlyPlayingCoroutine;
|
||||||
|
static readonly string zeroLengthString = GetLengthString(0f);
|
||||||
|
|
||||||
|
public AudioClip RefAudioClip;
|
||||||
|
private string fullLengthText;
|
||||||
|
|
||||||
|
private ButtonRef toggleButton;
|
||||||
|
private bool audioPlayerWanted;
|
||||||
|
|
||||||
|
private GameObject audioPlayerRoot;
|
||||||
|
private ButtonRef playStopButton;
|
||||||
|
private Text progressLabel;
|
||||||
|
private GameObject saveObjectRow;
|
||||||
|
private InputFieldRef savePathInput;
|
||||||
|
private GameObject cantSaveRow;
|
||||||
|
|
||||||
|
public override void OnBorrowed(object target, Type targetType, ReflectionInspector inspector)
|
||||||
|
{
|
||||||
|
base.OnBorrowed(target, targetType, inspector);
|
||||||
|
|
||||||
|
this.audioPlayerRoot.transform.SetParent(inspector.UIRoot.transform);
|
||||||
|
this.audioPlayerRoot.transform.SetSiblingIndex(inspector.UIRoot.transform.childCount - 2);
|
||||||
|
|
||||||
|
RefAudioClip = target.TryCast<AudioClip>();
|
||||||
|
this.fullLengthText = GetLengthString(RefAudioClip.length);
|
||||||
|
|
||||||
|
if (RefAudioClip.loadType == AudioClipLoadType.DecompressOnLoad)
|
||||||
|
{
|
||||||
|
cantSaveRow.SetActive(false);
|
||||||
|
saveObjectRow.SetActive(true);
|
||||||
|
SetDefaultSavePath();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cantSaveRow.SetActive(true);
|
||||||
|
saveObjectRow.SetActive(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
ResetProgressLabel();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnReturnToPool()
|
||||||
|
{
|
||||||
|
RefAudioClip = null;
|
||||||
|
|
||||||
|
if (audioPlayerWanted)
|
||||||
|
ToggleAudioWidget();
|
||||||
|
|
||||||
|
if (CurrentlyPlaying == this)
|
||||||
|
StopClip();
|
||||||
|
|
||||||
|
this.audioPlayerRoot.transform.SetParent(Pool<AudioClipWidget>.Instance.InactiveHolder.transform);
|
||||||
|
|
||||||
|
base.OnReturnToPool();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ToggleAudioWidget()
|
||||||
|
{
|
||||||
|
if (audioPlayerWanted)
|
||||||
|
{
|
||||||
|
audioPlayerWanted = false;
|
||||||
|
|
||||||
|
toggleButton.ButtonText.text = "Show Player";
|
||||||
|
audioPlayerRoot.SetActive(false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
audioPlayerWanted = true;
|
||||||
|
|
||||||
|
toggleButton.ButtonText.text = "Hide Player";
|
||||||
|
audioPlayerRoot.SetActive(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetDefaultSavePath()
|
||||||
|
{
|
||||||
|
string name = RefAudioClip.name;
|
||||||
|
if (string.IsNullOrEmpty(name))
|
||||||
|
name = "untitled";
|
||||||
|
savePathInput.Text = Path.Combine(ConfigManager.Default_Output_Path.Value, $"{name}.wav");
|
||||||
|
}
|
||||||
|
|
||||||
|
static string GetLengthString(float seconds)
|
||||||
|
{
|
||||||
|
TimeSpan ts = TimeSpan.FromSeconds(seconds);
|
||||||
|
|
||||||
|
StringBuilder sb = new();
|
||||||
|
|
||||||
|
if (ts.Hours > 0)
|
||||||
|
sb.Append($"{ts.Hours}:");
|
||||||
|
|
||||||
|
sb.Append($"{ts.Minutes:00}:");
|
||||||
|
sb.Append($"{ts.Seconds:00}:");
|
||||||
|
sb.Append($"{ts.Milliseconds:000}");
|
||||||
|
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ResetProgressLabel()
|
||||||
|
{
|
||||||
|
this.progressLabel.text = $"{zeroLengthString} / {fullLengthText}";
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnPlayStopClicked()
|
||||||
|
{
|
||||||
|
SetupAudioPlayer();
|
||||||
|
|
||||||
|
if (CurrentlyPlaying == this)
|
||||||
|
{
|
||||||
|
// we are playing a clip. stop it.
|
||||||
|
StopClip();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// If something else is playing a clip, stop that.
|
||||||
|
if (CurrentlyPlaying != null)
|
||||||
|
CurrentlyPlaying.StopClip();
|
||||||
|
|
||||||
|
// we want to start playing a clip.
|
||||||
|
CurrentlyPlayingCoroutine = RuntimeHelper.StartCoroutine(PlayClipCoroutine());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SetupAudioPlayer()
|
||||||
|
{
|
||||||
|
if (AudioPlayerObject)
|
||||||
|
return;
|
||||||
|
|
||||||
|
AudioPlayerObject = new GameObject("UnityExplorer.AudioPlayer");
|
||||||
|
UnityEngine.Object.DontDestroyOnLoad(AudioPlayerObject);
|
||||||
|
AudioPlayerObject.hideFlags = HideFlags.HideAndDontSave;
|
||||||
|
AudioPlayerObject.transform.position = new(int.MinValue, int.MinValue); // move it as far away as possible
|
||||||
|
#if CPP
|
||||||
|
Source = AudioPlayerObject.AddComponent(UnhollowerRuntimeLib.Il2CppType.Of<AudioSource>()).TryCast<AudioSource>();
|
||||||
|
#else
|
||||||
|
Source = AudioPlayerObject.AddComponent<AudioSource>();
|
||||||
|
#endif
|
||||||
|
AudioPlayerObject.AddComponent<AudioListener>();
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerator PlayClipCoroutine()
|
||||||
|
{
|
||||||
|
playStopButton.ButtonText.text = "Stop Clip";
|
||||||
|
CurrentlyPlaying = this;
|
||||||
|
Source.clip = this.RefAudioClip;
|
||||||
|
Source.Play();
|
||||||
|
|
||||||
|
while (Source.isPlaying)
|
||||||
|
{
|
||||||
|
progressLabel.text = $"{GetLengthString(Source.time)} / {fullLengthText}";
|
||||||
|
yield return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
CurrentlyPlayingCoroutine = null;
|
||||||
|
StopClip();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void StopClip()
|
||||||
|
{
|
||||||
|
if (CurrentlyPlayingCoroutine != null)
|
||||||
|
RuntimeHelper.StopCoroutine(CurrentlyPlayingCoroutine);
|
||||||
|
|
||||||
|
Source.Stop();
|
||||||
|
CurrentlyPlaying = null;
|
||||||
|
CurrentlyPlayingCoroutine = null;
|
||||||
|
playStopButton.ButtonText.text = "Play Clip";
|
||||||
|
|
||||||
|
ResetProgressLabel();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnSaveClipClicked()
|
||||||
|
{
|
||||||
|
if (!RefAudioClip)
|
||||||
|
{
|
||||||
|
ExplorerCore.LogWarning("AudioClip is null, maybe it was destroyed?");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(savePathInput.Text))
|
||||||
|
{
|
||||||
|
ExplorerCore.LogWarning("Save path cannot be empty!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string path = savePathInput.Text;
|
||||||
|
if (!path.EndsWith(".wav", StringComparison.InvariantCultureIgnoreCase))
|
||||||
|
path += ".wav";
|
||||||
|
|
||||||
|
path = IOUtility.EnsureValidFilePath(path);
|
||||||
|
|
||||||
|
if (File.Exists(path))
|
||||||
|
File.Delete(path);
|
||||||
|
|
||||||
|
SavWav.Save(RefAudioClip, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override GameObject CreateContent(GameObject uiRoot)
|
||||||
|
{
|
||||||
|
GameObject ret = base.CreateContent(uiRoot);
|
||||||
|
|
||||||
|
// Toggle Button
|
||||||
|
|
||||||
|
toggleButton = UIFactory.CreateButton(UIRoot, "AudioWidgetToggleButton", "Show Player", new Color(0.2f, 0.3f, 0.2f));
|
||||||
|
toggleButton.Transform.SetSiblingIndex(0);
|
||||||
|
UIFactory.SetLayoutElement(toggleButton.Component.gameObject, minHeight: 25, minWidth: 170);
|
||||||
|
toggleButton.OnClick += ToggleAudioWidget;
|
||||||
|
|
||||||
|
// Actual widget
|
||||||
|
|
||||||
|
audioPlayerRoot = UIFactory.CreateVerticalGroup(uiRoot, "AudioWidget", false, false, true, true, spacing: 5);
|
||||||
|
UIFactory.SetLayoutElement(audioPlayerRoot, flexibleWidth: 9999, flexibleHeight: 50);
|
||||||
|
audioPlayerRoot.SetActive(false);
|
||||||
|
|
||||||
|
// Player
|
||||||
|
|
||||||
|
GameObject playerRow = UIFactory.CreateHorizontalGroup(audioPlayerRoot, "PlayerWidget", false, false, true, true,
|
||||||
|
spacing: 5, padding: new() { x = 3f, w = 3f, y = 3f, z = 3f });
|
||||||
|
|
||||||
|
playStopButton = UIFactory.CreateButton(playerRow, "PlayerButton", "Play", normalColor: new(0.2f, 0.4f, 0.2f));
|
||||||
|
playStopButton.OnClick += OnPlayStopClicked;
|
||||||
|
UIFactory.SetLayoutElement(playStopButton.GameObject, minWidth: 60, minHeight: 25);
|
||||||
|
|
||||||
|
progressLabel = UIFactory.CreateLabel(playerRow, "ProgressLabel", "0 / 0");
|
||||||
|
UIFactory.SetLayoutElement(progressLabel.gameObject, flexibleWidth: 9999, minHeight: 25);
|
||||||
|
|
||||||
|
ResetProgressLabel();
|
||||||
|
|
||||||
|
// Save helper
|
||||||
|
|
||||||
|
saveObjectRow = UIFactory.CreateHorizontalGroup(audioPlayerRoot, "SaveRow", false, false, true, true, 2, new Vector4(2, 2, 2, 2),
|
||||||
|
new Color(0.1f, 0.1f, 0.1f));
|
||||||
|
|
||||||
|
ButtonRef saveBtn = UIFactory.CreateButton(saveObjectRow, "SaveButton", "Save .WAV", new Color(0.2f, 0.25f, 0.2f));
|
||||||
|
UIFactory.SetLayoutElement(saveBtn.Component.gameObject, minHeight: 25, minWidth: 100, flexibleWidth: 0);
|
||||||
|
saveBtn.OnClick += OnSaveClipClicked;
|
||||||
|
|
||||||
|
savePathInput = UIFactory.CreateInputField(saveObjectRow, "SaveInput", "...");
|
||||||
|
UIFactory.SetLayoutElement(savePathInput.UIRoot, minHeight: 25, minWidth: 100, flexibleWidth: 9999);
|
||||||
|
|
||||||
|
// cant save label
|
||||||
|
cantSaveRow = UIFactory.CreateHorizontalGroup(audioPlayerRoot, "CantSaveRow", true, true, true, true);
|
||||||
|
UIFactory.SetLayoutElement(cantSaveRow, minHeight: 25, flexibleWidth: 9999);
|
||||||
|
UIFactory.CreateLabel(
|
||||||
|
cantSaveRow,
|
||||||
|
"CantSaveLabel",
|
||||||
|
"Cannot save this AudioClip as the data is compressed or streamed. Try a tool such as AssetRipper to unpack it.",
|
||||||
|
color: Color.grey);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#region SavWav
|
||||||
|
|
||||||
|
// Copyright (c) 2012 Calvin Rien
|
||||||
|
// http://the.darktable.com
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied warranty. In
|
||||||
|
// no event will the authors be held liable for any damages arising from the use
|
||||||
|
// of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it freely,
|
||||||
|
// subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not claim
|
||||||
|
// that you wrote the original software. If you use this software in a product,
|
||||||
|
// an acknowledgment in the product documentation would be appreciated but is not
|
||||||
|
// required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
// misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
//
|
||||||
|
// =============================================================================
|
||||||
|
//
|
||||||
|
// derived from Gregorio Zanon's script
|
||||||
|
// http://forum.unity3d.com/threads/119295-Writing-AudioListener.GetOutputData-to-wav-problem?p=806734&viewfull=1#post806734
|
||||||
|
|
||||||
|
public static class SavWav
|
||||||
|
{
|
||||||
|
public const int HEADER_SIZE = 44;
|
||||||
|
public const float RESCALE_FACTOR = 32767; // to convert float to Int16
|
||||||
|
|
||||||
|
public static void Save(AudioClip clip, string filepath)
|
||||||
|
{
|
||||||
|
using FileStream fileStream = CreateEmpty(filepath);
|
||||||
|
|
||||||
|
ConvertAndWrite(fileStream, clip);
|
||||||
|
WriteHeader(fileStream, clip);
|
||||||
|
}
|
||||||
|
|
||||||
|
static FileStream CreateEmpty(string filepath)
|
||||||
|
{
|
||||||
|
FileStream fileStream = new(filepath, FileMode.Create);
|
||||||
|
byte emptyByte = default;
|
||||||
|
|
||||||
|
for (int i = 0; i < HEADER_SIZE; i++) //preparing the header
|
||||||
|
fileStream.WriteByte(emptyByte);
|
||||||
|
|
||||||
|
return fileStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ConvertAndWrite(FileStream fileStream, AudioClip clip)
|
||||||
|
{
|
||||||
|
#if CPP
|
||||||
|
UnhollowerBaseLib.Il2CppStructArray<float> samples = new float[clip.samples * clip.channels];
|
||||||
|
AudioClip.GetData(clip, samples, clip.samples, 0);
|
||||||
|
#else
|
||||||
|
float[] samples = new float[clip.samples * clip.channels];
|
||||||
|
clip.GetData(samples, 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int len = samples.Length;
|
||||||
|
|
||||||
|
// converting in 2 float[] steps to Int16[], then Int16[] to Byte[]
|
||||||
|
short[] intData = new short[len];
|
||||||
|
|
||||||
|
// bytesData array is twice the size of dataSource array because a float converted in Int16 is 2 bytes.
|
||||||
|
byte[] bytesData = new byte[len * 2];
|
||||||
|
|
||||||
|
for (int i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
intData[i] = (short)(samples[i] * RESCALE_FACTOR);
|
||||||
|
byte[] byteArr = BitConverter.GetBytes(intData[i]);
|
||||||
|
byteArr.CopyTo(bytesData, i * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
fileStream.Write(bytesData, 0, bytesData.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WriteHeader(FileStream stream, AudioClip clip)
|
||||||
|
{
|
||||||
|
int hz = clip.frequency;
|
||||||
|
int channels = clip.channels;
|
||||||
|
int samples = clip.samples;
|
||||||
|
|
||||||
|
stream.Seek(0, SeekOrigin.Begin);
|
||||||
|
|
||||||
|
byte[] riff = Encoding.UTF8.GetBytes("RIFF");
|
||||||
|
stream.Write(riff, 0, 4);
|
||||||
|
|
||||||
|
byte[] chunkSize = BitConverter.GetBytes(stream.Length - 8);
|
||||||
|
stream.Write(chunkSize, 0, 4);
|
||||||
|
|
||||||
|
byte[] wave = Encoding.ASCII.GetBytes("WAVE");
|
||||||
|
stream.Write(wave, 0, 4);
|
||||||
|
|
||||||
|
byte[] fmt = Encoding.ASCII.GetBytes("fmt ");
|
||||||
|
stream.Write(fmt, 0, 4);
|
||||||
|
|
||||||
|
byte[] subChunk1 = BitConverter.GetBytes(16);
|
||||||
|
stream.Write(subChunk1, 0, 4);
|
||||||
|
|
||||||
|
byte[] audioFormat = BitConverter.GetBytes(1);
|
||||||
|
stream.Write(audioFormat, 0, 2);
|
||||||
|
|
||||||
|
byte[] numChannels = BitConverter.GetBytes(channels);
|
||||||
|
stream.Write(numChannels, 0, 2);
|
||||||
|
|
||||||
|
byte[] sampleRate = BitConverter.GetBytes(hz);
|
||||||
|
stream.Write(sampleRate, 0, 4);
|
||||||
|
|
||||||
|
byte[] byteRate = BitConverter.GetBytes(hz * channels * 2); // sampleRate * bytesPerSample*number of channels, here 44100*2*2
|
||||||
|
stream.Write(byteRate, 0, 4);
|
||||||
|
|
||||||
|
ushort blockAlign = (ushort)(channels * 2);
|
||||||
|
stream.Write(BitConverter.GetBytes(blockAlign), 0, 2);
|
||||||
|
|
||||||
|
ushort bps = 16;
|
||||||
|
byte[] bitsPerSample = BitConverter.GetBytes(bps);
|
||||||
|
stream.Write(bitsPerSample, 0, 2);
|
||||||
|
|
||||||
|
byte[] datastring = Encoding.UTF8.GetBytes("data");
|
||||||
|
stream.Write(datastring, 0, 4);
|
||||||
|
|
||||||
|
byte[] subChunk2 = BitConverter.GetBytes(samples * channels * 2);
|
||||||
|
stream.Write(subChunk2, 0, 4);
|
||||||
|
|
||||||
|
stream.Seek(0, SeekOrigin.Begin);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
244
src/UI/Widgets/UnityObjects/Texture2DWidget.cs
Normal file
244
src/UI/Widgets/UnityObjects/Texture2DWidget.cs
Normal file
@ -0,0 +1,244 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
using UnityExplorer.Config;
|
||||||
|
using UnityExplorer.Inspectors;
|
||||||
|
using UnityExplorer.UI.Panels;
|
||||||
|
using UniverseLib;
|
||||||
|
using UniverseLib.Runtime;
|
||||||
|
using UniverseLib.UI;
|
||||||
|
using UniverseLib.UI.Models;
|
||||||
|
using UniverseLib.UI.ObjectPool;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
|
namespace UnityExplorer.UI.Widgets
|
||||||
|
{
|
||||||
|
public class Texture2DWidget : UnityObjectWidget
|
||||||
|
{
|
||||||
|
private Texture2D TextureRef;
|
||||||
|
private float realWidth;
|
||||||
|
private float realHeight;
|
||||||
|
|
||||||
|
private bool textureViewerWanted;
|
||||||
|
private ButtonRef toggleButton;
|
||||||
|
|
||||||
|
private GameObject textureViewerRoot;
|
||||||
|
private InputFieldRef savePathInput;
|
||||||
|
private Image image;
|
||||||
|
private LayoutElement imageLayout;
|
||||||
|
|
||||||
|
public override void OnBorrowed(object target, Type targetType, ReflectionInspector inspector)
|
||||||
|
{
|
||||||
|
base.OnBorrowed(target, targetType, inspector);
|
||||||
|
|
||||||
|
TextureRef = target.TryCast<Texture2D>();
|
||||||
|
|
||||||
|
realWidth = TextureRef.width;
|
||||||
|
realHeight = TextureRef.height;
|
||||||
|
|
||||||
|
if (this.textureViewerRoot)
|
||||||
|
this.textureViewerRoot.transform.SetParent(inspector.UIRoot.transform);
|
||||||
|
|
||||||
|
InspectorPanel.Instance.Dragger.OnFinishResize += OnInspectorFinishResize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnReturnToPool()
|
||||||
|
{
|
||||||
|
InspectorPanel.Instance.Dragger.OnFinishResize -= OnInspectorFinishResize;
|
||||||
|
|
||||||
|
TextureRef = null;
|
||||||
|
|
||||||
|
if (image.sprite)
|
||||||
|
GameObject.Destroy(image.sprite);
|
||||||
|
|
||||||
|
if (textureViewerWanted)
|
||||||
|
ToggleTextureViewer();
|
||||||
|
|
||||||
|
if (this.textureViewerRoot)
|
||||||
|
this.textureViewerRoot.transform.SetParent(Pool<Texture2DWidget>.Instance.InactiveHolder.transform);
|
||||||
|
|
||||||
|
base.OnReturnToPool();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ToggleTextureViewer()
|
||||||
|
{
|
||||||
|
if (textureViewerWanted)
|
||||||
|
{
|
||||||
|
// disable
|
||||||
|
textureViewerWanted = false;
|
||||||
|
textureViewerRoot.SetActive(false);
|
||||||
|
toggleButton.ButtonText.text = "View Texture";
|
||||||
|
|
||||||
|
ParentInspector.mainContentHolder.SetActive(true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// enable
|
||||||
|
if (!image.sprite)
|
||||||
|
SetupTextureViewer();
|
||||||
|
|
||||||
|
SetImageSize();
|
||||||
|
|
||||||
|
textureViewerWanted = true;
|
||||||
|
textureViewerRoot.SetActive(true);
|
||||||
|
toggleButton.ButtonText.text = "Hide Texture";
|
||||||
|
|
||||||
|
ParentInspector.mainContentHolder.gameObject.SetActive(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetupTextureViewer()
|
||||||
|
{
|
||||||
|
if (!this.TextureRef)
|
||||||
|
return;
|
||||||
|
|
||||||
|
string name = TextureRef.name;
|
||||||
|
if (string.IsNullOrEmpty(name))
|
||||||
|
name = "untitled";
|
||||||
|
savePathInput.Text = Path.Combine(ConfigManager.Default_Output_Path.Value, $"{name}.png");
|
||||||
|
|
||||||
|
Sprite sprite = TextureHelper.CreateSprite(TextureRef);
|
||||||
|
image.sprite = sprite;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnInspectorFinishResize(RectTransform _)
|
||||||
|
{
|
||||||
|
SetImageSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetImageSize()
|
||||||
|
{
|
||||||
|
if (!imageLayout)
|
||||||
|
return;
|
||||||
|
|
||||||
|
RuntimeHelper.StartCoroutine(SetImageSizeCoro());
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerator SetImageSizeCoro()
|
||||||
|
{
|
||||||
|
// let unity rebuild layout etc
|
||||||
|
yield return null;
|
||||||
|
|
||||||
|
RectTransform imageRect = InspectorPanel.Instance.Rect;
|
||||||
|
|
||||||
|
float rectWidth = imageRect.rect.width - 25;
|
||||||
|
float rectHeight = imageRect.rect.height - 196;
|
||||||
|
|
||||||
|
// If our image is smaller than the viewport, just use 100% scaling
|
||||||
|
if (realWidth < rectWidth && realHeight < rectHeight)
|
||||||
|
{
|
||||||
|
imageLayout.minWidth = realWidth;
|
||||||
|
imageLayout.minHeight = realHeight;
|
||||||
|
}
|
||||||
|
else // we will need to scale down the image to fit
|
||||||
|
{
|
||||||
|
// get the ratio of our viewport dimensions to width and height
|
||||||
|
float viewWidthRatio = (float)((decimal)rectWidth / (decimal)realWidth);
|
||||||
|
float viewHeightRatio = (float)((decimal)rectHeight / (decimal)realHeight);
|
||||||
|
|
||||||
|
// if width needs to be scaled more than height
|
||||||
|
if (viewWidthRatio < viewHeightRatio)
|
||||||
|
{
|
||||||
|
imageLayout.minWidth = realWidth * viewWidthRatio;
|
||||||
|
imageLayout.minHeight = realHeight * viewWidthRatio;
|
||||||
|
}
|
||||||
|
else // if height needs to be scaled more than width
|
||||||
|
{
|
||||||
|
imageLayout.minWidth = realWidth * viewHeightRatio;
|
||||||
|
imageLayout.minHeight = realHeight * viewHeightRatio;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnSaveTextureClicked()
|
||||||
|
{
|
||||||
|
if (!TextureRef)
|
||||||
|
{
|
||||||
|
ExplorerCore.LogWarning("Texture is null, maybe it was destroyed?");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(savePathInput.Text))
|
||||||
|
{
|
||||||
|
ExplorerCore.LogWarning("Save path cannot be empty!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string path = savePathInput.Text;
|
||||||
|
if (!path.EndsWith(".png", StringComparison.InvariantCultureIgnoreCase))
|
||||||
|
path += ".png";
|
||||||
|
|
||||||
|
path = IOUtility.EnsureValidFilePath(path);
|
||||||
|
|
||||||
|
if (File.Exists(path))
|
||||||
|
File.Delete(path);
|
||||||
|
|
||||||
|
Texture2D tex = TextureRef;
|
||||||
|
if (!TextureHelper.IsReadable(tex))
|
||||||
|
tex = TextureHelper.ForceReadTexture(tex);
|
||||||
|
|
||||||
|
byte[] data = TextureHelper.EncodeToPNG(tex);
|
||||||
|
File.WriteAllBytes(path, data);
|
||||||
|
|
||||||
|
if (tex != TextureRef)
|
||||||
|
{
|
||||||
|
// cleanup temp texture if we had to force-read it.
|
||||||
|
GameObject.Destroy(tex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override GameObject CreateContent(GameObject uiRoot)
|
||||||
|
{
|
||||||
|
GameObject ret = base.CreateContent(uiRoot);
|
||||||
|
|
||||||
|
// Button
|
||||||
|
|
||||||
|
toggleButton = UIFactory.CreateButton(UIRoot, "TextureButton", "View Texture", new Color(0.2f, 0.3f, 0.2f));
|
||||||
|
toggleButton.Transform.SetSiblingIndex(0);
|
||||||
|
UIFactory.SetLayoutElement(toggleButton.Component.gameObject, minHeight: 25, minWidth: 150);
|
||||||
|
toggleButton.OnClick += ToggleTextureViewer;
|
||||||
|
|
||||||
|
// Texture viewer
|
||||||
|
|
||||||
|
textureViewerRoot = UIFactory.CreateVerticalGroup(uiRoot, "TextureViewer", false, false, true, true, 2, new Vector4(5, 5, 5, 5),
|
||||||
|
new Color(0.1f, 0.1f, 0.1f), childAlignment: TextAnchor.UpperLeft);
|
||||||
|
UIFactory.SetLayoutElement(textureViewerRoot, flexibleWidth: 9999, flexibleHeight: 9999);
|
||||||
|
|
||||||
|
// Save helper
|
||||||
|
|
||||||
|
GameObject saveRowObj = UIFactory.CreateHorizontalGroup(textureViewerRoot, "SaveRow", false, false, true, true, 2, new Vector4(2, 2, 2, 2),
|
||||||
|
new Color(0.1f, 0.1f, 0.1f));
|
||||||
|
|
||||||
|
ButtonRef saveBtn = UIFactory.CreateButton(saveRowObj, "SaveButton", "Save .PNG", new Color(0.2f, 0.25f, 0.2f));
|
||||||
|
UIFactory.SetLayoutElement(saveBtn.Component.gameObject, minHeight: 25, minWidth: 100, flexibleWidth: 0);
|
||||||
|
saveBtn.OnClick += OnSaveTextureClicked;
|
||||||
|
|
||||||
|
savePathInput = UIFactory.CreateInputField(saveRowObj, "SaveInput", "...");
|
||||||
|
UIFactory.SetLayoutElement(savePathInput.UIRoot, minHeight: 25, minWidth: 100, flexibleWidth: 9999);
|
||||||
|
|
||||||
|
// Actual texture viewer
|
||||||
|
|
||||||
|
GameObject imageViewport = UIFactory.CreateVerticalGroup(textureViewerRoot, "ImageViewport", false, false, true, true,
|
||||||
|
bgColor: new(1,1,1,0), childAlignment: TextAnchor.MiddleCenter);
|
||||||
|
UIFactory.SetLayoutElement(imageViewport, flexibleWidth: 9999, flexibleHeight: 9999);
|
||||||
|
|
||||||
|
GameObject imageHolder = UIFactory.CreateUIObject("ImageHolder", imageViewport);
|
||||||
|
imageLayout = UIFactory.SetLayoutElement(imageHolder, 1, 1, 0, 0);
|
||||||
|
|
||||||
|
var actualImageObj = UIFactory.CreateUIObject("ActualImage", imageHolder);
|
||||||
|
var actualRect = actualImageObj.GetComponent<RectTransform>();
|
||||||
|
actualRect.anchorMin = new(0, 0);
|
||||||
|
actualRect.anchorMax = new(1, 1);
|
||||||
|
image = actualImageObj.AddComponent<Image>();
|
||||||
|
|
||||||
|
textureViewerRoot.SetActive(false);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
131
src/UI/Widgets/UnityObjects/UnityObjectWidget.cs
Normal file
131
src/UI/Widgets/UnityObjects/UnityObjectWidget.cs
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
using System;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
using UnityExplorer.Inspectors;
|
||||||
|
using UniverseLib;
|
||||||
|
using UniverseLib.UI;
|
||||||
|
using UniverseLib.UI.Models;
|
||||||
|
using UniverseLib.UI.ObjectPool;
|
||||||
|
|
||||||
|
namespace UnityExplorer.UI.Widgets
|
||||||
|
{
|
||||||
|
public class UnityObjectWidget : IPooledObject
|
||||||
|
{
|
||||||
|
public UnityEngine.Object UnityObjectRef;
|
||||||
|
public Component ComponentRef;
|
||||||
|
public ReflectionInspector ParentInspector;
|
||||||
|
|
||||||
|
protected ButtonRef gameObjectButton;
|
||||||
|
protected InputFieldRef nameInput;
|
||||||
|
protected InputFieldRef instanceIdInput;
|
||||||
|
|
||||||
|
// IPooledObject
|
||||||
|
public GameObject UIRoot { get; set; }
|
||||||
|
public float DefaultHeight => -1;
|
||||||
|
|
||||||
|
public static UnityObjectWidget GetUnityWidget(object target, Type targetType, ReflectionInspector inspector)
|
||||||
|
{
|
||||||
|
if (!typeof(UnityEngine.Object).IsAssignableFrom(targetType))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
UnityObjectWidget widget = target switch
|
||||||
|
{
|
||||||
|
Texture2D => Pool<Texture2DWidget>.Borrow(),
|
||||||
|
AudioClip => Pool<AudioClipWidget>.Borrow(),
|
||||||
|
_ => Pool<UnityObjectWidget>.Borrow()
|
||||||
|
};
|
||||||
|
|
||||||
|
widget.OnBorrowed(target, targetType, inspector);
|
||||||
|
|
||||||
|
return widget;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void OnBorrowed(object target, Type targetType, ReflectionInspector inspector)
|
||||||
|
{
|
||||||
|
this.ParentInspector = inspector ?? throw new ArgumentNullException(nameof(inspector));
|
||||||
|
|
||||||
|
if (!this.UIRoot)
|
||||||
|
CreateContent(inspector.UIRoot);
|
||||||
|
else
|
||||||
|
this.UIRoot.transform.SetParent(inspector.UIRoot.transform);
|
||||||
|
|
||||||
|
this.UIRoot.transform.SetSiblingIndex(inspector.UIRoot.transform.childCount - 2);
|
||||||
|
|
||||||
|
UnityObjectRef = target.TryCast<UnityEngine.Object>();
|
||||||
|
UIRoot.SetActive(true);
|
||||||
|
|
||||||
|
nameInput.Text = UnityObjectRef.name;
|
||||||
|
instanceIdInput.Text = UnityObjectRef.GetInstanceID().ToString();
|
||||||
|
|
||||||
|
if (typeof(Component).IsAssignableFrom(targetType))
|
||||||
|
{
|
||||||
|
ComponentRef = (Component)target.TryCast(typeof(Component));
|
||||||
|
gameObjectButton.Component.gameObject.SetActive(true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
gameObjectButton.Component.gameObject.SetActive(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void OnReturnToPool()
|
||||||
|
{
|
||||||
|
UnityObjectRef = null;
|
||||||
|
ComponentRef = null;
|
||||||
|
ParentInspector = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update
|
||||||
|
|
||||||
|
public virtual void Update()
|
||||||
|
{
|
||||||
|
if (this.UnityObjectRef)
|
||||||
|
{
|
||||||
|
nameInput.Text = UnityObjectRef.name;
|
||||||
|
ParentInspector.Tab.TabText.text = $"{ParentInspector.currentBaseTabText} \"{UnityObjectRef.name}\"";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// UI Listeners
|
||||||
|
|
||||||
|
private void OnGameObjectButtonClicked()
|
||||||
|
{
|
||||||
|
if (!ComponentRef)
|
||||||
|
{
|
||||||
|
ExplorerCore.LogWarning("Component reference is null or destroyed!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
InspectorManager.Inspect(ComponentRef.gameObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
// UI construction
|
||||||
|
|
||||||
|
public virtual GameObject CreateContent(GameObject uiRoot)
|
||||||
|
{
|
||||||
|
UIRoot = UIFactory.CreateUIObject("UnityObjectRow", uiRoot);
|
||||||
|
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(UIRoot, false, false, true, true, 5);
|
||||||
|
UIFactory.SetLayoutElement(UIRoot, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999);
|
||||||
|
|
||||||
|
var nameLabel = UIFactory.CreateLabel(UIRoot, "NameLabel", "Name:", TextAnchor.MiddleLeft, Color.grey);
|
||||||
|
UIFactory.SetLayoutElement(nameLabel.gameObject, minHeight: 25, minWidth: 45, flexibleWidth: 0);
|
||||||
|
|
||||||
|
nameInput = UIFactory.CreateInputField(UIRoot, "NameInput", "untitled");
|
||||||
|
UIFactory.SetLayoutElement(nameInput.UIRoot, minHeight: 25, minWidth: 100, flexibleWidth: 1000);
|
||||||
|
nameInput.Component.readOnly = true;
|
||||||
|
|
||||||
|
gameObjectButton = UIFactory.CreateButton(UIRoot, "GameObjectButton", "Inspect GameObject", new Color(0.2f, 0.2f, 0.2f));
|
||||||
|
UIFactory.SetLayoutElement(gameObjectButton.Component.gameObject, minHeight: 25, minWidth: 160);
|
||||||
|
gameObjectButton.OnClick += OnGameObjectButtonClicked;
|
||||||
|
|
||||||
|
var instanceLabel = UIFactory.CreateLabel(UIRoot, "InstanceLabel", "Instance ID:", TextAnchor.MiddleRight, Color.grey);
|
||||||
|
UIFactory.SetLayoutElement(instanceLabel.gameObject, minHeight: 25, minWidth: 100, flexibleWidth: 0);
|
||||||
|
|
||||||
|
instanceIdInput = UIFactory.CreateInputField(UIRoot, "InstanceIDInput", "ERROR");
|
||||||
|
UIFactory.SetLayoutElement(instanceIdInput.UIRoot, minHeight: 25, minWidth: 100, flexibleWidth: 0);
|
||||||
|
instanceIdInput.Component.readOnly = true;
|
||||||
|
|
||||||
|
UIRoot.SetActive(false);
|
||||||
|
|
||||||
|
return UIRoot;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -106,8 +106,11 @@
|
|||||||
<HintPath>..\lib\mcs-unity\mcs\bin\Release\mcs.dll</HintPath>
|
<HintPath>..\lib\mcs-unity\mcs\bin\Release\mcs.dll</HintPath>
|
||||||
<Private>False</Private>
|
<Private>False</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="INIFileParser, Version=2.5.2.0, Culture=neutral, PublicKeyToken=79af7b307b65cf3c, processorArchitecture=MSIL">
|
</ItemGroup>
|
||||||
<HintPath>packages\ini-parser.2.5.2\lib\net20\INIFileParser.dll</HintPath>
|
<!-- Non-MelonLoader (it includes Tomlet) -->
|
||||||
|
<ItemGroup Condition="'$(IsMelonLoader)'=='false'">
|
||||||
|
<Reference Include="Tomlet, Version=3.1.3.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<HintPath>packages\Samboy063.Tomlet.3.1.3\lib\net35\Tomlet.dll</HintPath>
|
||||||
<Private>False</Private>
|
<Private>False</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
@ -172,16 +175,16 @@
|
|||||||
<Private>False</Private>
|
<Private>False</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="UniverseLib.Mono">
|
<Reference Include="UniverseLib.Mono">
|
||||||
<HintPath>packages\UniverseLib.1.0.6\lib\net35\UniverseLib.Mono.dll</HintPath>
|
<HintPath>packages\UniverseLib.1.2.18\lib\net35\UniverseLib.Mono.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<!-- Il2Cpp refs -->
|
<!-- Il2Cpp refs -->
|
||||||
<ItemGroup Condition="'$(IsCpp)'=='true'">
|
<ItemGroup Condition="'$(IsCpp)'=='true'">
|
||||||
<Reference Include="UniverseLib.IL2CPP">
|
<Reference Include="UniverseLib.IL2CPP">
|
||||||
<HintPath>packages\UniverseLib.1.0.6\lib\net472\UniverseLib.IL2CPP.dll</HintPath>
|
<HintPath>packages\UniverseLib.1.2.18\lib\net472\UniverseLib.IL2CPP.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="UnhollowerBaseLib">
|
<Reference Include="UnhollowerBaseLib, Version=0.4.22.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<HintPath>..\lib\Il2CppAssemblyUnhollower\UnhollowerBaseLib\bin\Release\net4.7.2\UnhollowerBaseLib.dll</HintPath>
|
<HintPath>packages\Il2CppAssemblyUnhollower.BaseLib.0.4.22\lib\net472\UnhollowerBaseLib.dll</HintPath>
|
||||||
<Private>False</Private>
|
<Private>False</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Il2Cppmscorlib">
|
<Reference Include="Il2Cppmscorlib">
|
||||||
@ -196,6 +199,10 @@
|
|||||||
<HintPath>..\lib\unhollowed\UnityEngine.dll</HintPath>
|
<HintPath>..\lib\unhollowed\UnityEngine.dll</HintPath>
|
||||||
<Private>False</Private>
|
<Private>False</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
<Reference Include="UnityEngine.AudioModule">
|
||||||
|
<HintPath>..\lib\unhollowed\UnityEngine.AudioModule.dll</HintPath>
|
||||||
|
<Private>False</Private>
|
||||||
|
</Reference>
|
||||||
<Reference Include="UnityEngine.CoreModule">
|
<Reference Include="UnityEngine.CoreModule">
|
||||||
<HintPath>..\lib\unhollowed\UnityEngine.CoreModule.dll</HintPath>
|
<HintPath>..\lib\unhollowed\UnityEngine.CoreModule.dll</HintPath>
|
||||||
<Private>False</Private>
|
<Private>False</Private>
|
||||||
@ -222,6 +229,8 @@
|
|||||||
</Reference>
|
</Reference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Include="CacheObject\CacheConstructor.cs" />
|
||||||
|
<Compile Include="CacheObject\CacheMemberFactory.cs" />
|
||||||
<Compile Include="Hooks\HookCell.cs" />
|
<Compile Include="Hooks\HookCell.cs" />
|
||||||
<Compile Include="Hooks\HookInstance.cs" />
|
<Compile Include="Hooks\HookInstance.cs" />
|
||||||
<Compile Include="Hooks\HookManager.cs" />
|
<Compile Include="Hooks\HookManager.cs" />
|
||||||
@ -243,7 +252,7 @@
|
|||||||
<Compile Include="Inspectors\GameObjectWidgets\ComponentCell.cs" />
|
<Compile Include="Inspectors\GameObjectWidgets\ComponentCell.cs" />
|
||||||
<Compile Include="Inspectors\GameObjectWidgets\ComponentList.cs" />
|
<Compile Include="Inspectors\GameObjectWidgets\ComponentList.cs" />
|
||||||
<Compile Include="Inspectors\GameObjectWidgets\GameObjectControls.cs" />
|
<Compile Include="Inspectors\GameObjectWidgets\GameObjectControls.cs" />
|
||||||
<Compile Include="Inspectors\InspectUnderMouse.cs" />
|
<Compile Include="Inspectors\MouseInspector.cs" />
|
||||||
<Compile Include="CSConsole\ConsoleController.cs" />
|
<Compile Include="CSConsole\ConsoleController.cs" />
|
||||||
<Compile Include="CacheObject\CacheField.cs" />
|
<Compile Include="CacheObject\CacheField.cs" />
|
||||||
<Compile Include="CacheObject\CacheKeyValuePair.cs" />
|
<Compile Include="CacheObject\CacheKeyValuePair.cs" />
|
||||||
@ -256,6 +265,10 @@
|
|||||||
<Compile Include="CacheObject\Views\CacheListEntryCell.cs" />
|
<Compile Include="CacheObject\Views\CacheListEntryCell.cs" />
|
||||||
<Compile Include="CacheObject\Views\CacheMemberCell.cs" />
|
<Compile Include="CacheObject\Views\CacheMemberCell.cs" />
|
||||||
<Compile Include="CacheObject\Views\CacheObjectCell.cs" />
|
<Compile Include="CacheObject\Views\CacheObjectCell.cs" />
|
||||||
|
<Compile Include="Loader\Standalone\Editor\ExplorerEditorBehaviour.cs" />
|
||||||
|
<Compile Include="Loader\Standalone\Editor\ExplorerEditorLoader.cs" />
|
||||||
|
<Compile Include="Runtime\UnityCrashPrevention.cs" />
|
||||||
|
<Compile Include="UI\DisplayManager.cs" />
|
||||||
<Compile Include="UI\Notification.cs" />
|
<Compile Include="UI\Notification.cs" />
|
||||||
<Compile Include="UI\Panels\ClipboardPanel.cs" />
|
<Compile Include="UI\Panels\ClipboardPanel.cs" />
|
||||||
<Compile Include="UI\Widgets\AutoComplete\EnumCompleter.cs" />
|
<Compile Include="UI\Widgets\AutoComplete\EnumCompleter.cs" />
|
||||||
@ -287,9 +300,9 @@
|
|||||||
<Compile Include="Config\ConfigHandler.cs" />
|
<Compile Include="Config\ConfigHandler.cs" />
|
||||||
<Compile Include="Config\ConfigManager.cs" />
|
<Compile Include="Config\ConfigManager.cs" />
|
||||||
<Compile Include="Config\IConfigElement.cs" />
|
<Compile Include="Config\IConfigElement.cs" />
|
||||||
<Compile Include="Runtime\Il2CppProvider.cs" />
|
<Compile Include="Runtime\Il2CppHelper.cs" />
|
||||||
<Compile Include="Runtime\MonoProvider.cs" />
|
<Compile Include="Runtime\MonoHelper.cs" />
|
||||||
<Compile Include="Runtime\RuntimeHelper.cs" />
|
<Compile Include="Runtime\UERuntimeHelper.cs" />
|
||||||
<Compile Include="ObjectExplorer\SceneHandler.cs" />
|
<Compile Include="ObjectExplorer\SceneHandler.cs" />
|
||||||
<Compile Include="ObjectExplorer\SearchProvider.cs" />
|
<Compile Include="ObjectExplorer\SearchProvider.cs" />
|
||||||
<Compile Include="Tests\TestClass.cs" />
|
<Compile Include="Tests\TestClass.cs" />
|
||||||
@ -307,7 +320,7 @@
|
|||||||
<Compile Include="UI\Panels\ObjectExplorerPanel.cs" />
|
<Compile Include="UI\Panels\ObjectExplorerPanel.cs" />
|
||||||
<Compile Include="UI\UIManager.cs" />
|
<Compile Include="UI\UIManager.cs" />
|
||||||
<Compile Include="UI\Panels\PanelDragger.cs" />
|
<Compile Include="UI\Panels\PanelDragger.cs" />
|
||||||
<Compile Include="UI\Widgets\AutoComplete\AutoCompleteModal.cs" />
|
<Compile Include="UI\Panels\AutoCompleteModal.cs" />
|
||||||
<Compile Include="UI\Widgets\AutoComplete\TypeCompleter.cs" />
|
<Compile Include="UI\Widgets\AutoComplete\TypeCompleter.cs" />
|
||||||
<Compile Include="ObjectExplorer\ObjectSearch.cs" />
|
<Compile Include="ObjectExplorer\ObjectSearch.cs" />
|
||||||
<Compile Include="ObjectExplorer\SceneExplorer.cs" />
|
<Compile Include="ObjectExplorer\SceneExplorer.cs" />
|
||||||
@ -317,12 +330,18 @@
|
|||||||
<Compile Include="UI\Widgets\TransformTree\CachedTransform.cs" />
|
<Compile Include="UI\Widgets\TransformTree\CachedTransform.cs" />
|
||||||
<Compile Include="UI\Widgets\TransformTree\TransformCell.cs" />
|
<Compile Include="UI\Widgets\TransformTree\TransformCell.cs" />
|
||||||
<Compile Include="UI\Widgets\TransformTree\TransformTree.cs" />
|
<Compile Include="UI\Widgets\TransformTree\TransformTree.cs" />
|
||||||
|
<Compile Include="UI\Widgets\UnityObjects\AudioClipWidget.cs" />
|
||||||
|
<Compile Include="UI\Widgets\UnityObjects\Texture2DWidget.cs" />
|
||||||
|
<Compile Include="UI\Widgets\UnityObjects\UnityObjectWidget.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="ILRepack.targets" />
|
<None Include="ILRepack.targets" />
|
||||||
|
<None Include="nuget.config" />
|
||||||
<None Include="packages.config" />
|
<None Include="packages.config" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup />
|
<ItemGroup>
|
||||||
|
<Analyzer Include="packages\UniverseLib.Analyzers.1.0.3\analyzers\dotnet\cs\UniverseLib.Analyzers.dll" />
|
||||||
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.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')" />
|
<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">
|
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||||
|
@ -3,8 +3,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00
|
|||||||
# Visual Studio Version 16
|
# Visual Studio Version 16
|
||||||
VisualStudioVersion = 16.0.30128.74
|
VisualStudioVersion = 16.0.30128.74
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
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}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "mcs", "..\lib\mcs-unity\mcs\mcs.csproj", "{E4989E4C-0875-4528-9031-08E2C0E70103}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnityExplorer", "UnityExplorer.csproj", "{B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnityExplorer", "UnityExplorer.csproj", "{B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}"
|
||||||
@ -20,20 +18,6 @@ Global
|
|||||||
Release_STANDALONE_Mono|Any CPU = Release_STANDALONE_Mono|Any CPU
|
Release_STANDALONE_Mono|Any CPU = Release_STANDALONE_Mono|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
{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
|
|
||||||
{7B7E5024-385D-4A46-9196-A6AF8F7FBDD5}.Release_BIE5_Mono|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{7B7E5024-385D-4A46-9196-A6AF8F7FBDD5}.Release_BIE6_Mono|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{7B7E5024-385D-4A46-9196-A6AF8F7FBDD5}.Release_BIE6_Mono|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{7B7E5024-385D-4A46-9196-A6AF8F7FBDD5}.Release_ML_Cpp|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{7B7E5024-385D-4A46-9196-A6AF8F7FBDD5}.Release_ML_Cpp|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{7B7E5024-385D-4A46-9196-A6AF8F7FBDD5}.Release_ML_Mono|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{7B7E5024-385D-4A46-9196-A6AF8F7FBDD5}.Release_ML_Mono|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{7B7E5024-385D-4A46-9196-A6AF8F7FBDD5}.Release_STANDALONE_Cpp|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{7B7E5024-385D-4A46-9196-A6AF8F7FBDD5}.Release_STANDALONE_Cpp|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{7B7E5024-385D-4A46-9196-A6AF8F7FBDD5}.Release_STANDALONE_Mono|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{7B7E5024-385D-4A46-9196-A6AF8F7FBDD5}.Release_STANDALONE_Mono|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{E4989E4C-0875-4528-9031-08E2C0E70103}.Release_BIE_Cpp|Any CPU.ActiveCfg = Release|Any CPU
|
{E4989E4C-0875-4528-9031-08E2C0E70103}.Release_BIE_Cpp|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{E4989E4C-0875-4528-9031-08E2C0E70103}.Release_BIE_Cpp|Any CPU.Build.0 = Release|Any CPU
|
{E4989E4C-0875-4528-9031-08E2C0E70103}.Release_BIE_Cpp|Any CPU.Build.0 = Release|Any CPU
|
||||||
{E4989E4C-0875-4528-9031-08E2C0E70103}.Release_BIE5_Mono|Any CPU.ActiveCfg = Release|Any CPU
|
{E4989E4C-0875-4528-9031-08E2C0E70103}.Release_BIE5_Mono|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
19
src/nuget.config
Normal file
19
src/nuget.config
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<configuration>
|
||||||
|
<config>
|
||||||
|
<add key="dependencyVersion" value="Lowest" />
|
||||||
|
</config>
|
||||||
|
|
||||||
|
<packageRestore>
|
||||||
|
<!-- Allow NuGet to download missing packages -->
|
||||||
|
<add key="enabled" value="True" />
|
||||||
|
|
||||||
|
<!-- Automatically check for missing packages during build in Visual Studio -->
|
||||||
|
<add key="automatic" value="True" />
|
||||||
|
</packageRestore>
|
||||||
|
|
||||||
|
<packageSources>
|
||||||
|
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
|
||||||
|
<add key="BepInEx" value="https://nuget.bepinex.dev/v3/index.json" />
|
||||||
|
</packageSources>
|
||||||
|
</configuration>
|
@ -1,8 +1,11 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<packages>
|
<packages>
|
||||||
<package id="HarmonyX" version="2.5.2" targetFramework="net35" />
|
<package id="HarmonyX" version="2.5.2" targetFramework="net35" />
|
||||||
|
<package id="Iced" version="1.15.0" targetFramework="net472" />
|
||||||
|
<package id="Il2CppAssemblyUnhollower.BaseLib" version="0.4.22" targetFramework="net472" />
|
||||||
<package id="ILRepack.Lib.MSBuild.Task" version="2.0.18.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" />
|
<package id="Mono.Cecil" version="0.10.4" targetFramework="net35" />
|
||||||
<package id="UniverseLib" version="1.0.6" targetFramework="net35" />
|
<package id="Samboy063.Tomlet" version="3.1.3" targetFramework="net472" />
|
||||||
|
<package id="UniverseLib" version="1.2.18" targetFramework="net35" />
|
||||||
|
<package id="UniverseLib.Analyzers" version="1.0.3" targetFramework="net35" developmentDependency="true" />
|
||||||
</packages>
|
</packages>
|
Reference in New Issue
Block a user