Compare commits

...

44 Commits
4.0.6 ... 4.1.1

Author SHA1 Message Date
a5f56cf5a3 Prevent very large Texture images from overflowing outside the Texture Viewer 2021-05-31 19:10:05 +10:00
8c822b2ee9 Simplify ci workflow 2021-05-30 04:50:37 +10:00
4681b7e192 Update README -noci 2021-05-29 19:46:39 +10:00
97093733d8 Update README -noci 2021-05-29 19:42:12 +10:00
615f77979f Update README -noci 2021-05-29 19:41:14 +10:00
ba3cf970d9 Update README.md 2021-05-29 19:30:08 +10:00
b2fb571b18 Testing ci skip -noci 2021-05-29 19:15:28 +10:00
67ce6f946a Update dotnet.yml 2021-05-29 19:13:30 +10:00
1b82ccb49f Bump version 2021-05-29 19:07:44 +10:00
480eb5afd5 Use HarmonyX NuGet package 2021-05-29 19:07:26 +10:00
88ea2a09c9 Update README.md 2021-05-29 18:46:17 +10:00
a678aa4d78 Update dotnet.yml 2021-05-29 18:30:52 +10:00
eaf478e314 Using temporary manual HarmonyX reference 2021-05-29 18:27:40 +10:00
d391968b32 Update dotnet.yml 2021-05-29 17:50:59 +10:00
70349ad7c7 Update dotnet.yml 2021-05-29 17:48:02 +10:00
78f2d1070f Update dotnet.yml 2021-05-29 17:46:59 +10:00
51307563ab Update dotnet.yml 2021-05-29 17:41:08 +10:00
185d1aaa0f Update dotnet.yml 2021-05-29 17:38:21 +10:00
3d6e8fcbf8 Update dotnet.yml 2021-05-29 17:36:56 +10:00
1daf4fade4 Use HarmonyX NuGet instead of submodule 2021-05-29 17:36:07 +10:00
d92fb3f83f Update dotnet.yml 2021-05-29 17:27:52 +10:00
fe24b68fe2 Update dotnet.yml 2021-05-29 17:24:53 +10:00
6bf92b9a96 Update dotnet.yml 2021-05-29 17:20:42 +10:00
9f1cab019d Create dotnet.yml 2021-05-29 17:18:09 +10:00
a131404ac7 Cleanup 2021-05-29 14:50:27 +10:00
773900d749 Fix CacheProperty not resetting Exception state when it has arguments 2021-05-29 14:50:21 +10:00
342fc6bdb8 Maintain last timeScale value 2021-05-28 18:48:55 +10:00
e85ea6ac3a Make Il2CppProvider actually process FixedUpdate coroutines 2021-05-28 18:23:45 +10:00
af889e64cb Fix exception when inspecting UnityObject classes with static reflection 2021-05-28 18:23:30 +10:00
0274022ce4 Make sure WaitForEndOfFrame object is never null 2021-05-28 18:23:07 +10:00
211576e0f8 Fallback to LateUpdate if OnPostRender listener failed 2021-05-28 18:22:44 +10:00
3e42d7479f Update README.md 2021-05-28 16:59:22 +10:00
df4dea20c1 Update README.md 2021-05-28 16:55:01 +10:00
ece0c43067 Add Time.timeScale helper on main navbar 2021-05-28 16:39:42 +10:00
6311c8d09a Bump version 2021-05-28 15:51:09 +10:00
04739d0be8 Separate default reflection blacklist from user list, add try/catch 2021-05-28 15:51:03 +10:00
a46acba265 Better JumpToIndex height calculation 2021-05-27 19:44:17 +10:00
5515b2eae4 Bump version 2021-05-27 19:31:01 +10:00
9992029e28 Set DataViewInfo struct back to array in rebuild, cleanup 2021-05-27 19:30:55 +10:00
14105785f0 Fix SceneExplorer not properly detecting scene changes sometimes 2021-05-27 19:30:19 +10:00
365269b0dd Clear GameObject Component and Transform lists properly on close 2021-05-27 19:29:00 +10:00
0b973393d1 Cleanup 2021-05-27 19:28:22 +10:00
701d4431ae Delete explorerui.legacy.bundle.bak.5.3.8 2021-05-27 16:00:42 +10:00
bfa73bcb55 Cleanup Pool.cs 2021-05-26 19:42:56 +10:00
30 changed files with 562 additions and 322 deletions

113
.github/workflows/dotnet.yml vendored Normal file
View File

@ -0,0 +1,113 @@
name: Build UnityExplorer
# Controls when the action will run.
on:
push:
branches: [master]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
jobs:
build:
runs-on: windows-latest
if: "!contains(github.event.head_commit.message, '-noci')"
steps:
# Checkout latest with submodules
- uses: actions/checkout@v2
with:
submodules: recursive
# Setup tools
- name: Setup msbuild
uses: microsoft/setup-msbuild@v1
- name: Setup nuget
uses: nuget/setup-nuget@v1
with:
nuget-api-key: ${{ secrets.NuGetAPIKey }}
nuget-version: '5.x'
# Build Il2CppAssemblyUnhollower
- run: msbuild lib\Il2CppAssemblyUnhollower\UnhollowerBaseLib\UnhollowerBaseLib.csproj -t:Restore -t:Rebuild -p:Platform="AnyCPU" -p:Configuration=Release
# Build mcs
- run: nuget restore lib\mcs-unity\mcs.sln
- run: msbuild lib\mcs-unity\mcs\mcs.csproj -t:Restore -t:Rebuild -p:Platform="AnyCPU" -p:Configuration=Release
# Build UnityExplorer releases, and upload artifacts
- run: nuget restore src\UnityExplorer.sln
# BepInEx Il2Cpp
- run: msbuild src\UnityExplorer.csproj -t:Rebuild -p:Platform="AnyCPU" -p:Configuration=Release_BIE_Cpp
- uses: actions/upload-artifact@v2
with:
name: UnityExplorer.BepInEx.Il2Cpp
path: ./Release/UnityExplorer.BepInEx.Il2Cpp/*
# BepInEx 5 Mono
- run: msbuild src\UnityExplorer.csproj -t:Rebuild -p:Platform="AnyCPU" -p:Configuration=Release_BIE5_Mono
- uses: actions/upload-artifact@v2
with:
name: UnityExplorer.BepInEx5.Mono
path: ./Release/UnityExplorer.BepInEx5.Mono/*
# BepInEx 6 Mono
- run: msbuild src\UnityExplorer.csproj -t:Rebuild -p:Platform="AnyCPU" -p:Configuration=Release_BIE6_Mono
- uses: actions/upload-artifact@v2
with:
name: UnityExplorer.BepInEx6.Mono
path: ./Release/UnityExplorer.BepInEx6.Mono/*
# MelonLoader Il2Cpp
- run: msbuild src\UnityExplorer.csproj -t:Rebuild -p:Platform="AnyCPU" -p:Configuration=Release_ML_Cpp
- uses: actions/upload-artifact@v2
with:
name: UnityExplorer.MelonLoader.Il2Cpp
path: ./Release/UnityExplorer.MelonLoader.Il2Cpp/*
# MelonLoader Mono
- run: msbuild src\UnityExplorer.csproj -t:Rebuild -p:Platform="AnyCPU" -p:Configuration=Release_ML_Mono
- uses: actions/upload-artifact@v2
with:
name: UnityExplorer.MelonLoader.Mono
path: ./Release/UnityExplorer.MelonLoader.Mono/*
# MelonLoader 0.3.0 Il2Cpp
- run: msbuild src\UnityExplorer.csproj -t:Rebuild -p:Platform="AnyCPU" -p:Configuration=Release_MLLegacy_Cpp
- uses: actions/upload-artifact@v2
with:
name: UnityExplorer.MelonLoader_Legacy.Il2Cpp
path: ./Release/UnityExplorer.MelonLoader_Legacy.Il2Cpp/*
# MelonLoader 0.3.0 Mono
- run: msbuild src\UnityExplorer.csproj -t:Rebuild -p:Platform="AnyCPU" -p:Configuration=Release_MLLegacy_Mono
- uses: actions/upload-artifact@v2
with:
name: UnityExplorer.MelonLoader_Legacy.Mono
path: ./Release/UnityExplorer.MelonLoader_Legacy.Mono/*
# Standalone Il2Cpp
- run: msbuild src\UnityExplorer.csproj -t:Rebuild -p:Platform="AnyCPU" -p:Configuration=Release_STANDALONE_Cpp
- uses: actions/upload-artifact@v2
with:
name: UnityExplorer.Standalone.Il2Cpp
path: ./Release/UnityExplorer.Standalone.Il2Cpp/*
# Standalone Mono
- run: msbuild src\UnityExplorer.csproj -t:Rebuild -p:Platform="AnyCPU" -p:Configuration=Release_STANDALONE_Mono
- uses: actions/upload-artifact@v2
with:
name: UnityExplorer.Standalone.Mono
path: ./Release/UnityExplorer.Standalone.Mono/*

3
.gitmodules vendored
View File

@ -1,9 +1,6 @@
[submodule "lib/Il2CppAssemblyUnhollower"] [submodule "lib/Il2CppAssemblyUnhollower"]
path = lib/Il2CppAssemblyUnhollower path = lib/Il2CppAssemblyUnhollower
url = https://github.com/knah/Il2CppAssemblyUnhollower url = https://github.com/knah/Il2CppAssemblyUnhollower
[submodule "lib/HarmonyX"]
path = lib/HarmonyX
url = https://github.com/BepInEx/HarmonyX
[submodule "lib/mcs-unity"] [submodule "lib/mcs-unity"]
path = lib/mcs-unity path = lib/mcs-unity
url = https://github.com/sinai-dev/mcs-unity url = https://github.com/sinai-dev/mcs-unity

View File

@ -10,8 +10,9 @@
Supports most Unity games from versions 5.2 to 2020+. Supports most Unity games from versions 5.2 to 2020+.
</p> </p>
## Releases [![](https://img.shields.io/github/release/sinai-dev/UnityExplorer.svg?label=release%20notes)](../../releases/latest) [![](https://img.shields.io/github/downloads/sinai-dev/UnityExplorer/total.svg)](../../releases) [![](https://img.shields.io/github/downloads/sinai-dev/UnityExplorer/latest/total.svg)](../../releases/latest) ## Releases [![](https://img.shields.io/github/downloads/sinai-dev/UnityExplorer/total.svg)](../../releases)
[![](https://img.shields.io/github/release/sinai-dev/UnityExplorer.svg?label=version)](../../releases/latest) [![](https://img.shields.io/github/downloads/sinai-dev/UnityExplorer/latest/total.svg)](../../releases/latest)
| Mod Loader | IL2CPP | Mono | | Mod Loader | IL2CPP | Mono |
| ----------- | ------ | ---- | | ----------- | ------ | ---- |
| [BepInEx](https://github.com/BepInEx/BepInEx) 6.X | ✅ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.BepInEx.Il2Cpp.zip) | ✅ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.BepInEx6.Mono.zip) | | [BepInEx](https://github.com/BepInEx/BepInEx) 6.X | ✅ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.BepInEx.Il2Cpp.zip) | ✅ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.BepInEx6.Mono.zip) |
@ -20,6 +21,8 @@
| [MelonLoader](https://github.com/HerpDerpinstine/MelonLoader) 0.3.0 | ✅ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.MelonLoader_Legacy.Il2Cpp.zip) | ✅ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.MelonLoader_Legacy.Mono.zip) | | [MelonLoader](https://github.com/HerpDerpinstine/MelonLoader) 0.3.0 | ✅ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.MelonLoader_Legacy.Il2Cpp.zip) | ✅ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.MelonLoader_Legacy.Mono.zip) |
| Standalone | ✅ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.Standalone.Il2Cpp.zip) | ✅ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.Standalone.Mono.zip) | | Standalone | ✅ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.Standalone.Il2Cpp.zip) | ✅ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.Standalone.Mono.zip) |
* [Click here for Bleeding Edge releases](https://github.com/sinai-dev/UnityExplorer/actions) (click on the latest workflow and scroll down to Artifacts)
### Known issues ### Known issues
* Any `MissingMethodException` or `NotSupportedException`: please report the issue and provide a copy of your mod loader log and/or Unity log. * Any `MissingMethodException` or `NotSupportedException`: please report the issue and provide a copy of your mod loader log and/or Unity log.
* In IL2CPP, some IEnumerable and IDictionary types may fail enumeration. Waiting for the Unhollower rewrite to address this any further. * In IL2CPP, some IEnumerable and IDictionary types may fail enumeration. Waiting for the Unhollower rewrite to address this any further.
@ -66,9 +69,8 @@ The standalone release can be used with any injector or loader of your choice, b
The inspector is used to see detailed information on GameObjects (GameObject Inspector), C# objects (Reflection Inspector) and C# classes (Static Inspector). The inspector is used to see detailed information on GameObjects (GameObject Inspector), C# objects (Reflection Inspector) and C# classes (Static Inspector).
For the GameObject Inspector, you can edit any of the input fields in the inspector (excluding readonly fields) and press <b>Enter</b> to apply your changes. You can also do this to the GameObject path as a way to change the GameObject's parent. Press the <b>Escape</b> key to cancel your edits. * In the GameObject Inspector, you can edit any of the input fields in the inspector (excluding readonly fields) and press <b>Enter</b> to apply your changes. You can also do this to the GameObject path as a way to change the GameObject's parent. Press the <b>Escape</b> key to cancel your edits.
* In the Reflection Inspectors, automatic updating is not enabled by default, and you must press Apply for any changes you make to take effect.
In the Reflection Inspectors, automatic updating is not enabled by default, and you must press Apply for any changes you make to take effect.
### C# Console ### C# Console
@ -94,11 +96,18 @@ Depending on the release you are using, the config file will be found at:
## Building ## Building
If you fork the repository on GitHub you can build using the [dotnet workflow](https://github.com/sinai-dev/UnityExplorer/blob/master/.github/workflows/dotnet.yml):
0. Click on the Actions tab and enable workflows in your repository
1. Click on the "Build UnityExplorer" workflow, then click "Run Workflow" and run it manually, or make a new commit to trigger the workflow.
2. Take the artifact from the completed run.
For Visual Studio:
0. Clone the repository and run `git submodule update --init --recursive` to get the submodules. 0. Clone the repository and run `git submodule update --init --recursive` to get the submodules.
1. Open the `src\UnityExplorer.sln` project in Visual Studio. 1. Open the `src\UnityExplorer.sln` project.
2. Select `Solution 'UnityExplorer' (1 of 1 project)` in the Solution Explorer panel, and set the <b>Active config</b> property to the version you want to build, then build it. Alternatively, use "Batch Build" and select all releases. 2. Build `mcs`, and if using IL2CPP then build `UnhollowerBaseLib` as well.
3. The DLLs are built to the `Release\` folder in the root of the repository. 3. Build the UnityExplorer release(s) you want to use, either by selecting the config as the Active Config, or batch-building.
4. If ILRepack complains about an error, just change the Active config to a different release and then back again. This sometimes happens for the first time you build the project.
## Acknowledgments ## Acknowledgments

Submodule lib/HarmonyX deleted from 64462b3e31

View File

@ -113,10 +113,11 @@ namespace UnityExplorer.Core.Config
"The delay on startup before the UI is created.", "The delay on startup before the UI is created.",
1f); 1f);
Reflection_Signature_Blacklist = new ConfigElement<string>("Reflection Signature Blacklist", Reflection_Signature_Blacklist = new ConfigElement<string>("Member Signature Blacklist",
"Use this to blacklist certain member signatures if they are known to cause a crash or other issues." + "Use this to blacklist certain member signatures if they are known to cause a crash or other issues.\r\n" +
"\r\nSeperate signatures with a semicolon ';'.", "Seperate signatures with a semicolon ';'.\r\n" +
"DEFAULT"); "For example, to blacklist Camera.main, you would add 'Camera.main;'",
"");
// Internal configs (panel save data) // Internal configs (panel save data)

View File

@ -32,16 +32,32 @@ namespace UnityExplorer
public ExplorerBehaviour(IntPtr ptr) : base(ptr) { } public ExplorerBehaviour(IntPtr ptr) : base(ptr) { }
#endif #endif
private static bool onPostRenderFailed;
internal void Awake() internal void Awake()
{ {
try
{
#if CPP #if CPP
Camera.onPostRender = Camera.onPostRender == null Camera.onPostRender = Camera.onPostRender == null
? new Action<Camera>(OnPostRender) ? new Action<Camera>(OnPostRender)
: Il2CppSystem.Delegate.Combine(Camera.onPostRender, (Camera.CameraCallback)new Action<Camera>(OnPostRender)).Cast<Camera.CameraCallback>(); : Il2CppSystem.Delegate.Combine(Camera.onPostRender,
(Camera.CameraCallback)new Action<Camera>(OnPostRender)).Cast<Camera.CameraCallback>();
if (Camera.onPostRender == null || Camera.onPostRender.delegates == null)
{
ExplorerCore.LogWarning("Failed to add Camera.onPostRender listener, falling back to LateUpdate instead!");
onPostRenderFailed = true;
}
#else #else
Camera.onPostRender += OnPostRender; Camera.onPostRender += OnPostRender;
#endif #endif
}
catch (Exception ex)
{
ExplorerCore.LogWarning($"Exception adding onPostRender listener: {ex.ReflectionExToString()}\r\nFalling back to LateUpdate!");
onPostRenderFailed = true;
}
} }
internal void Update() internal void Update()
@ -54,7 +70,13 @@ namespace UnityExplorer
ExplorerCore.FixedUpdate(); ExplorerCore.FixedUpdate();
} }
internal static void OnPostRender(Camera camera) internal void LateUpdate()
{
if (onPostRenderFailed)
OnPostRender(null);
}
internal static void OnPostRender(Camera _)
{ {
ExplorerCore.OnPostRender(); ExplorerCore.OnPostRender();
} }

View File

@ -62,13 +62,13 @@ namespace UnityExplorer.Core.Input
} }
} }
private static readonly WaitForEndOfFrame _waitForEndOfFrame = new WaitForEndOfFrame(); private static WaitForEndOfFrame _waitForEndOfFrame = new WaitForEndOfFrame();
private static IEnumerator AggressiveUnlockCoroutine() private static IEnumerator AggressiveUnlockCoroutine()
{ {
while (true) while (true)
{ {
yield return _waitForEndOfFrame; yield return _waitForEndOfFrame ?? (_waitForEndOfFrame = new WaitForEndOfFrame());
if (UIManager.ShowMenu) if (UIManager.ShowMenu)
UpdateCursorControl(); UpdateCursorControl();

View File

@ -44,15 +44,15 @@ namespace UnityExplorer
public static bool Il2CppTypeNotNull(Type type, out IntPtr il2cppPtr) public static bool Il2CppTypeNotNull(Type type, out IntPtr il2cppPtr)
{ {
if (cppClassPointers.TryGetValue(type.AssemblyQualifiedName, out il2cppPtr)) if (!cppClassPointers.TryGetValue(type.AssemblyQualifiedName, out il2cppPtr))
return il2cppPtr != IntPtr.Zero; {
il2cppPtr = (IntPtr)typeof(Il2CppClassPointerStore<>)
il2cppPtr = (IntPtr)typeof(Il2CppClassPointerStore<>)
.MakeGenericType(new Type[] { type }) .MakeGenericType(new Type[] { type })
.GetField("NativeClassPtr", BF.Public | BF.Static) .GetField("NativeClassPtr", BF.Public | BF.Static)
.GetValue(null); .GetValue(null);
cppClassPointers.Add(type.AssemblyQualifiedName, il2cppPtr); cppClassPointers.Add(type.AssemblyQualifiedName, il2cppPtr);
}
return il2cppPtr != IntPtr.Zero; return il2cppPtr != IntPtr.Zero;
} }
@ -242,11 +242,11 @@ namespace UnityExplorer
else if (castTo == typeof(string)) else if (castTo == typeof(string))
return UnboxString(obj); return UnboxString(obj);
// Casting from il2cpp object to il2cpp object...
if (!Il2CppTypeNotNull(castTo, out IntPtr castToPtr)) if (!Il2CppTypeNotNull(castTo, out IntPtr castToPtr))
return obj; return obj;
// Casting from il2cpp object to il2cpp object...
IntPtr castFromPtr = il2cpp_object_get_class(cppObj.Pointer); IntPtr castFromPtr = il2cpp_object_get_class(cppObj.Pointer);
if (!il2cpp_class_is_assignable_from(castToPtr, castFromPtr)) if (!il2cpp_class_is_assignable_from(castToPtr, castFromPtr))
@ -515,12 +515,12 @@ namespace UnityExplorer
return false; return false;
} }
#endregion #endregion
#region Il2cpp reflection blacklist #region Il2cpp reflection blacklist
public override string DefaultReflectionBlacklist => string.Join(";", defaultIl2CppBlacklist); public override string[] DefaultReflectionBlacklist => defaultIl2CppBlacklist.ToArray();
// These methods currently cause a crash in most il2cpp games, // These methods currently cause a crash in most il2cpp games,
// even from doing "GetParameters()" on the MemberInfo. // even from doing "GetParameters()" on the MemberInfo.

View File

@ -12,7 +12,6 @@ using UnityExplorer.Core.Config;
namespace UnityExplorer namespace UnityExplorer
{ {
public class ReflectionUtility public class ReflectionUtility
{ {
public const BF FLAGS = BF.Public | BF.Instance | BF.NonPublic | BF.Static; public const BF FLAGS = BF.Public | BF.Instance | BF.NonPublic | BF.Static;
@ -434,31 +433,44 @@ namespace UnityExplorer
#region Reflection Blacklist #region Reflection Blacklist
public virtual string DefaultReflectionBlacklist => string.Empty; public virtual string[] DefaultReflectionBlacklist => new string[0];
public static void LoadBlacklistString(string blacklist) public static void LoadBlacklistString(string blacklist)
{ {
if (string.Equals(blacklist, "DEFAULT", StringComparison.InvariantCultureIgnoreCase)) try
{ {
blacklist = Instance.DefaultReflectionBlacklist; if (string.IsNullOrEmpty(blacklist) && !Instance.DefaultReflectionBlacklist.Any())
ConfigManager.Reflection_Signature_Blacklist.Value = blacklist; return;
ConfigManager.Handler.SaveConfig();
try
{
var sigs = blacklist.Split(';');
foreach (var sig in sigs)
{
var s = sig.Trim();
if (string.IsNullOrEmpty(s))
continue;
if (!currentBlacklist.Contains(s))
currentBlacklist.Add(s);
}
}
catch (Exception ex)
{
ExplorerCore.LogWarning($"Exception parsing blacklist string: {ex.ReflectionExToString()}");
}
foreach (var sig in Instance.DefaultReflectionBlacklist)
{
if (!currentBlacklist.Contains(sig))
currentBlacklist.Add(sig);
}
Mono.CSharp.IL2CPP.Blacklist.SignatureBlacklist = currentBlacklist;
} }
catch (Exception ex)
if (string.IsNullOrEmpty(blacklist))
return;
var sigs = blacklist.Split(';');
foreach (var sig in sigs)
{ {
var s = sig.Trim(); ExplorerCore.LogWarning($"Exception setting up reflection blacklist: {ex.ReflectionExToString()}");
if (string.IsNullOrEmpty(s))
continue;
if (!currentBlacklist.Contains(s))
currentBlacklist.Add(s);
} }
Mono.CSharp.IL2CPP.Blacklist.SignatureBlacklist = currentBlacklist;
} }
public static bool IsBlacklisted(MemberInfo member) public static bool IsBlacklisted(MemberInfo member)

View File

@ -43,9 +43,9 @@ namespace UnityExplorer.Core.Runtime.Il2Cpp
ExplorerCore.LogUnity(condition, type); ExplorerCore.LogUnity(condition, type);
} }
public override void StartCoroutine(IEnumerator routine) public override void Update()
{ {
Il2CppCoroutine.Start(routine); Il2CppCoroutine.Process();
} }
internal override void ProcessOnPostRender() internal override void ProcessOnPostRender()
@ -53,9 +53,14 @@ namespace UnityExplorer.Core.Runtime.Il2Cpp
Il2CppCoroutine.ProcessWaitForEndOfFrame(); Il2CppCoroutine.ProcessWaitForEndOfFrame();
} }
public override void Update() internal override void ProcessFixedUpdate()
{ {
Il2CppCoroutine.Process(); Il2CppCoroutine.ProcessWaitForFixedUpdate();
}
public override void StartCoroutine(IEnumerator routine)
{
Il2CppCoroutine.Start(routine);
} }
public override T AddComponent<T>(GameObject obj, Type type) public override T AddComponent<T>(GameObject obj, Type type)

View File

@ -20,7 +20,7 @@ namespace UnityExplorer
public static class ExplorerCore public static class ExplorerCore
{ {
public const string NAME = "UnityExplorer"; public const string NAME = "UnityExplorer";
public const string VERSION = "4.0.6"; public const string VERSION = "4.1.1";
public const string AUTHOR = "Sinai"; public const string AUTHOR = "Sinai";
public const string GUID = "com.sinai.unityexplorer"; public const string GUID = "com.sinai.unityexplorer";

View File

@ -11,18 +11,17 @@
<!-- MonoMod for MelonLoader 0.3.0 --> <!-- MonoMod for MelonLoader 0.3.0 -->
<ItemGroup Condition="'$(IsMelonLoaderLegacy)'=='true'"> <ItemGroup Condition="'$(IsMelonLoaderLegacy)'=='true'">
<InputAssemblies Include="..\lib\HarmonyX\Harmony\bin\Release\net45\Mono.Cecil.dll" /> <InputAssemblies Include="packages\Mono.Cecil.0.10.4\lib\net35\Mono.Cecil.dll" />
<InputAssemblies Include="..\lib\HarmonyX\Harmony\bin\Release\net45\Mono.Cecil.Mdb.dll" /> <InputAssemblies Include="packages\Mono.Cecil.0.10.4\lib\net35\Mono.Cecil.Mdb.dll" />
<InputAssemblies Include="..\lib\HarmonyX\Harmony\bin\Release\net45\Mono.Cecil.Pdb.dll" /> <InputAssemblies Include="packages\Mono.Cecil.0.10.4\lib\net35\Mono.Cecil.Pdb.dll" />
<InputAssemblies Include="..\lib\HarmonyX\Harmony\bin\Release\net45\Mono.Cecil.Rocks.dll" /> <InputAssemblies Include="packages\Mono.Cecil.0.10.4\lib\net35\Mono.Cecil.Rocks.dll" />
<InputAssemblies Include="..\lib\HarmonyX\Harmony\bin\Release\net45\MonoMod.RuntimeDetour.dll" /> <InputAssemblies Include="packages\MonoMod.RuntimeDetour.20.1.1.4\lib\net35\MonoMod.RuntimeDetour.dll" />
<InputAssemblies Include="..\lib\HarmonyX\Harmony\bin\Release\net45\MonoMod.Utils.dll" /> <InputAssemblies Include="packages\MonoMod.Utils.20.1.1.4\lib\net35\MonoMod.Utils.dll" />
</ItemGroup> </ItemGroup>
<!-- Required references for ILRepack --> <!-- Required references for ILRepack -->
<ItemGroup> <ItemGroup>
<ReferenceFolders Include="..\lib\" /> <ReferenceFolders Include="packages\HarmonyX.2.4.2\lib\net35\" />
<ReferenceFolders Include="..\lib\HarmonyX\Harmony\bin\Release\net35\" />
<ReferenceFolders Include="..\lib\BepInEx.6.IL2CPP\" /> <ReferenceFolders Include="..\lib\BepInEx.6.IL2CPP\" />
<ReferenceFolders Include="..\lib\BepInEx.6.Mono\" /> <ReferenceFolders Include="..\lib\BepInEx.6.Mono\" />
<ReferenceFolders Include="..\lib\BepInEx.5\" /> <ReferenceFolders Include="..\lib\BepInEx.5\" />
@ -36,7 +35,8 @@
LibraryPath="@(ReferenceFolders)" LibraryPath="@(ReferenceFolders)"
InputAssemblies="@(InputAssemblies)" InputAssemblies="@(InputAssemblies)"
TargetKind="Dll" TargetKind="Dll"
OutputFile="$(OutputPath)$(AssemblyName).dll" /> OutputFile="$(OutputPath)$(AssemblyName).dll"
/>
</Target> </Target>
</Project> </Project>

View File

@ -28,10 +28,11 @@ namespace UnityExplorer.UI.CacheObject
{ {
try try
{ {
object ret;
if (HasArguments) if (HasArguments)
return PropertyInfo.GetValue(DeclaringInstance, this.Evaluator.TryParseArguments()); ret = PropertyInfo.GetValue(DeclaringInstance, this.Evaluator.TryParseArguments());
else
var ret = PropertyInfo.GetValue(DeclaringInstance, null); ret = PropertyInfo.GetValue(DeclaringInstance, null);
HadException = false; HadException = false;
LastException = null; LastException = null;
return ret; return ret;

View File

@ -63,7 +63,7 @@ namespace UnityExplorer.UI.Inspectors
addCompInput.Text = ""; addCompInput.Text = "";
TransformTree.Clear(); TransformTree.Clear();
ComponentList.Clear(); UpdateComponents();
} }
public override void CloseInspector() public override void CloseInspector()
@ -112,6 +112,9 @@ namespace UnityExplorer.UI.Inspectors
private IEnumerable<GameObject> GetTransformEntries() private IEnumerable<GameObject> GetTransformEntries()
{ {
if (!GOTarget)
return Enumerable.Empty<GameObject>();
cachedChildren.Clear(); cachedChildren.Clear();
for (int i = 0; i < GOTarget.transform.childCount; i++) for (int i = 0; i < GOTarget.transform.childCount; i++)
cachedChildren.Add(GOTarget.transform.GetChild(i).gameObject); cachedChildren.Add(GOTarget.transform.GetChild(i).gameObject);
@ -124,10 +127,21 @@ namespace UnityExplorer.UI.Inspectors
private readonly List<bool> behaviourEnabledStates = new List<bool>(); private readonly List<bool> behaviourEnabledStates = new List<bool>();
// ComponentList.GetRootEntriesMethod // ComponentList.GetRootEntriesMethod
private List<Component> GetComponentEntries() => componentEntries; private List<Component> GetComponentEntries() => GOTarget ? componentEntries : Enumerable.Empty<Component>().ToList();
public void UpdateComponents() public void UpdateComponents()
{ {
if (!GOTarget)
{
componentEntries.Clear();
compInstanceIDs.Clear();
behaviourEntries.Clear();
behaviourEnabledStates.Clear();
ComponentList.RefreshData();
ComponentList.ScrollPool.Refresh(true, true);
return;
}
// Check if we actually need to refresh the component cells or not. // Check if we actually need to refresh the component cells or not.
var comps = GOTarget.GetComponents<Component>(); var comps = GOTarget.GetComponents<Component>();
var behaviours = GOTarget.GetComponents<Behaviour>(); var behaviours = GOTarget.GetComponents<Behaviour>();

View File

@ -21,7 +21,8 @@ namespace UnityExplorer.UI.Inspectors
public void Clear() public void Clear()
{ {
this.currentEntries.Clear(); RefreshData();
ScrollPool.Refresh(true, true);
} }
private bool CheckShouldDisplay(Component _, string __) => true; private bool CheckShouldDisplay(Component _, string __) => true;

View File

@ -480,7 +480,7 @@ namespace UnityExplorer.UI.Inspectors
private void SetUnityTargets() private void SetUnityTargets()
{ {
if (!typeof(UnityEngine.Object).IsAssignableFrom(TargetType)) if (StaticOnly || !typeof(UnityEngine.Object).IsAssignableFrom(TargetType))
{ {
unityObjectRow.SetActive(false); unityObjectRow.SetActive(false);
textureViewer.SetActive(false); textureViewer.SetActive(false);
@ -617,12 +617,15 @@ namespace UnityExplorer.UI.Inspectors
// Actual texture viewer // Actual texture viewer
var imageObj = UIFactory.CreateUIObject("TextureViewerImage", textureViewer); var imageViewport = UIFactory.CreateVerticalGroup(textureViewer, "Viewport", false, false, true, true);
textureImage = imageObj.AddComponent<Image>(); imageViewport.GetComponent<Image>().color = Color.white;
textureImageLayout = textureImage.gameObject.AddComponent<LayoutElement>(); imageViewport.AddComponent<Mask>().showMaskGraphic = false;
var imageObj = UIFactory.CreateUIObject("Image", imageViewport);
var fitter = imageObj.AddComponent<ContentSizeFitter>(); var fitter = imageObj.AddComponent<ContentSizeFitter>();
fitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize; fitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
textureImage = imageObj.AddComponent<Image>();
textureImageLayout = UIFactory.SetLayoutElement(imageObj, flexibleWidth: 9999, flexibleHeight: 9999);
textureViewer.SetActive(false); textureViewer.SetActive(false);
} }

View File

@ -50,8 +50,8 @@ namespace UnityExplorer.UI
} }
public TextGenerator TextGenerator => Component.cachedInputTextGenerator; public TextGenerator TextGenerator => Component.cachedInputTextGenerator;
public bool ReachedMaxVerts => TextGenerator.vertexCount >= UIManager.MAX_TEXT_VERTS;
public bool ReachedMaxVerts => TextGenerator.vertexCount >= UIManager.MAX_TEXT_VERTS;
private void OnInputChanged(string value) private void OnInputChanged(string value)
{ {

View File

@ -1,19 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
namespace UnityExplorer.UI.Models
{
public interface IPooledObject
{
GameObject UIRoot { get; set; }
GameObject CreateContent(GameObject parent);
float DefaultHeight { get; }
//GameObject CreatePrototype();
}
}

View File

@ -39,7 +39,7 @@ namespace UnityExplorer.UI.ObjectExplorer
private GameObject refreshRow; private GameObject refreshRow;
private Dropdown sceneDropdown; private Dropdown sceneDropdown;
private readonly Dictionary<int, Dropdown.OptionData> sceneToDropdownOption = new Dictionary<int, Dropdown.OptionData>(); private readonly Dictionary<Scene, Dropdown.OptionData> sceneToDropdownOption = new Dictionary<Scene, Dropdown.OptionData>();
private IEnumerable<GameObject> GetRootEntries() => SceneHandler.CurrentRootObjects; private IEnumerable<GameObject> GetRootEntries() => SceneHandler.CurrentRootObjects;
@ -70,7 +70,7 @@ namespace UnityExplorer.UI.ObjectExplorer
var go = transform.gameObject; var go = transform.gameObject;
if (SceneHandler.SelectedScene != go.scene) if (SceneHandler.SelectedScene != go.scene)
{ {
int idx = sceneDropdown.options.IndexOf(sceneToDropdownOption[go.scene.handle]); int idx = sceneDropdown.options.IndexOf(sceneToDropdownOption[go.scene]);
sceneDropdown.value = idx; sceneDropdown.value = idx;
} }
@ -91,12 +91,12 @@ namespace UnityExplorer.UI.ObjectExplorer
private void SceneHandler_OnInspectedSceneChanged(Scene scene) private void SceneHandler_OnInspectedSceneChanged(Scene scene)
{ {
if (!sceneToDropdownOption.ContainsKey(scene.handle)) if (!sceneToDropdownOption.ContainsKey(scene))
PopulateSceneDropdown(); PopulateSceneDropdown();
if (sceneToDropdownOption.ContainsKey(scene.handle)) if (sceneToDropdownOption.ContainsKey(scene))
{ {
var opt = sceneToDropdownOption[scene.handle]; var opt = sceneToDropdownOption[scene];
int idx = sceneDropdown.options.IndexOf(opt); int idx = sceneDropdown.options.IndexOf(opt);
if (sceneDropdown.value != idx) if (sceneDropdown.value != idx)
sceneDropdown.value = idx; sceneDropdown.value = idx;
@ -134,7 +134,7 @@ namespace UnityExplorer.UI.ObjectExplorer
var option = new Dropdown.OptionData(name); var option = new Dropdown.OptionData(name);
sceneDropdown.options.Add(option); sceneDropdown.options.Add(option);
sceneToDropdownOption.Add(scene.handle, option); sceneToDropdownOption.Add(scene, option);
} }
} }

View File

@ -15,16 +15,16 @@ namespace UnityExplorer.UI.ObjectExplorer
/// </summary> /// </summary>
public static Scene? SelectedScene public static Scene? SelectedScene
{ {
get => m_selectedScene; get => selectedScene;
internal set internal set
{ {
if (m_selectedScene != null && m_selectedScene?.handle == value?.handle) if (selectedScene != null && selectedScene == value)
return; return;
m_selectedScene = value; selectedScene = value;
OnInspectedSceneChanged?.Invoke((Scene)m_selectedScene); OnInspectedSceneChanged?.Invoke((Scene)selectedScene);
} }
} }
private static Scene? m_selectedScene; private static Scene? selectedScene;
/// <summary> /// <summary>
/// The GameObjects in the currently inspected scene. /// The GameObjects in the currently inspected scene.
@ -37,6 +37,7 @@ namespace UnityExplorer.UI.ObjectExplorer
/// </summary> /// </summary>
public static ReadOnlyCollection<Scene> LoadedScenes => new ReadOnlyCollection<Scene>(allLoadedScenes); public static ReadOnlyCollection<Scene> LoadedScenes => new ReadOnlyCollection<Scene>(allLoadedScenes);
private static readonly List<Scene> allLoadedScenes = new List<Scene>(); private static readonly List<Scene> allLoadedScenes = new List<Scene>();
private static HashSet<Scene> previousLoadedScenes;
/// <summary> /// <summary>
/// The names of all scenes in the build settings, if they could be retrieved. /// The names of all scenes in the build settings, if they could be retrieved.
@ -61,7 +62,7 @@ namespace UnityExplorer.UI.ObjectExplorer
public static event Action<ReadOnlyCollection<Scene>> OnLoadedScenesChanged; public static event Action<ReadOnlyCollection<Scene>> OnLoadedScenesChanged;
/// <summary> /// <summary>
/// Equivalent to <see cref="SceneManager.sceneCount"/> + 2, to include 'DontDestroyOnLoad'. /// Equivalent to <see cref="SceneManager.sceneCount"/> + 2, to include 'DontDestroyOnLoad' and the 'None' scene.
/// </summary> /// </summary>
public static int LoadedSceneCount => SceneManager.sceneCount + 2; public static int LoadedSceneCount => SceneManager.sceneCount + 2;
@ -82,7 +83,7 @@ namespace UnityExplorer.UI.ObjectExplorer
} }
private static GameObject dontDestroyObject; private static GameObject dontDestroyObject;
public static bool InspectingAssetScene => !SelectedScene?.IsValid() ?? false; public static bool InspectingAssetScene => SelectedScene.HasValue && SelectedScene.Value == default;
internal static void Init() internal static void Init()
{ {
@ -110,17 +111,9 @@ namespace UnityExplorer.UI.ObjectExplorer
internal static void Update() internal static void Update()
{ {
int curHandle = SelectedScene?.handle ?? -1; // check if the loaded scenes changed. always confirm DontDestroy / HideAndDontSave
// DontDestroyOnLoad always exists, so default to true if our curHandle is that handle. int confirmedCount = 2;
// otherwise we will check while iterating. bool inspectedExists = SelectedScene == DontDestroyScene || (SelectedScene.HasValue && SelectedScene.Value == default);
bool inspectedExists = curHandle == DontDestroyHandle || curHandle == 0;
// Quick sanity check if the loaded scenes changed
bool anyChange = LoadedSceneCount != allLoadedScenes.Count;
// otherwise keep a lookup table of the previous handles to check if the list changed at all.
HashSet<int> previousHandles = null;
if (!anyChange)
previousHandles = new HashSet<int>(allLoadedScenes.Select(it => it.handle));
allLoadedScenes.Clear(); allLoadedScenes.Clear();
@ -130,20 +123,22 @@ namespace UnityExplorer.UI.ObjectExplorer
if (scene == default || !scene.isLoaded) if (scene == default || !scene.isLoaded)
continue; continue;
// If no changes yet, ensure the previous list contained this handle. // If no changes yet, ensure the previous list contained the scene
if (!anyChange && !previousHandles.Contains(scene.handle)) if (previousLoadedScenes != null && previousLoadedScenes.Contains(scene))
anyChange = true; confirmedCount++;
// If we have not yet confirmed inspectedExists, check if this scene is our currently inspected one. // If we have not yet confirmed inspectedExists, check if this scene is our currently inspected one.
if (curHandle != -1 && !inspectedExists && scene.handle == curHandle) if (!inspectedExists && scene == SelectedScene)
inspectedExists = true; inspectedExists = true;
allLoadedScenes.Add(scene); allLoadedScenes.Add(scene);
} }
// Always add the DontDestroyOnLoad scene and the "none" scene. bool anyChange = confirmedCount != allLoadedScenes.Count;
allLoadedScenes.Add(DontDestroyScene); allLoadedScenes.Add(DontDestroyScene);
allLoadedScenes.Add(default); allLoadedScenes.Add(default);
previousLoadedScenes = new HashSet<Scene>(allLoadedScenes);
// Default to first scene if none selected or previous selection no longer exists. // Default to first scene if none selected or previous selection no longer exists.
if (!inspectedExists) if (!inspectedExists)
@ -163,14 +158,14 @@ namespace UnityExplorer.UI.ObjectExplorer
else else
{ {
var allObjects = RuntimeProvider.Instance.FindObjectsOfTypeAll(typeof(GameObject)); var allObjects = RuntimeProvider.Instance.FindObjectsOfTypeAll(typeof(GameObject));
var list = new List<GameObject>(); var objects = new List<GameObject>();
foreach (var obj in allObjects) foreach (var obj in allObjects)
{ {
var go = obj.TryCast<GameObject>(); var go = obj.TryCast<GameObject>();
if (go.transform.parent == null && !go.scene.IsValid()) if (go.transform.parent == null && !go.scene.IsValid())
list.Add(go); objects.Add(go);
} }
rootObjects = list.ToArray(); rootObjects = objects.ToArray();
} }
} }
} }

View File

@ -225,7 +225,7 @@ namespace UnityExplorer.UI.Panels
{ {
// create navbar button // create navbar button
NavButton = UIFactory.CreateButton(UIManager.NavbarButtonHolder, $"Button_{PanelType}", Name); NavButton = UIFactory.CreateButton(UIManager.NavbarTabButtonHolder, $"Button_{PanelType}", Name);
var navBtn = NavButton.Component.gameObject; var navBtn = NavButton.Component.gameObject;
navBtn.AddComponent<ContentSizeFitter>().horizontalFit = ContentSizeFitter.FitMode.PreferredSize; navBtn.AddComponent<ContentSizeFitter>().horizontalFit = ContentSizeFitter.FitMode.PreferredSize;
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(navBtn, false, true, true, true, 0, 0, 0, 5, 5, TextAnchor.MiddleCenter); UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(navBtn, false, true, true, true, 0, 0, 0, 5, 5, TextAnchor.MiddleCenter);

View File

@ -4,9 +4,16 @@ using System.Linq;
using System.Text; using System.Text;
using UnityEngine; using UnityEngine;
namespace UnityExplorer.UI.Models namespace UnityExplorer.UI
{ {
// Abstract non-generic class, handles the pool dictionary and interfacing with the generic pools. public interface IPooledObject
{
GameObject UIRoot { get; set; }
float DefaultHeight { get; }
GameObject CreateContent(GameObject parent);
}
public abstract class Pool public abstract class Pool
{ {
protected static readonly Dictionary<Type, Pool> pools = new Dictionary<Type, Pool>(); protected static readonly Dictionary<Type, Pool> pools = new Dictionary<Type, Pool>();
@ -39,7 +46,6 @@ namespace UnityExplorer.UI.Models
protected abstract void TryReturn(IPooledObject obj); protected abstract void TryReturn(IPooledObject obj);
} }
// Each generic implementation has its own pool, business logic is here
public class Pool<T> : Pool where T : IPooledObject public class Pool<T> : Pool where T : IPooledObject
{ {
public static Pool<T> GetPool() => (Pool<T>)GetPool(typeof(T)); public static Pool<T> GetPool() => (Pool<T>)GetPool(typeof(T));

View File

@ -55,9 +55,15 @@ namespace UnityExplorer.UI
internal static Shader BackupShader { get; private set; } internal static Shader BackupShader { get; private set; }
public static RectTransform NavBarRect; public static RectTransform NavBarRect;
public static GameObject NavbarButtonHolder; public static GameObject NavbarTabButtonHolder;
public static Dropdown MouseInspectDropdown; public static Dropdown MouseInspectDropdown;
private static ButtonRef closeBtn;
private static ButtonRef pauseBtn;
private static InputFieldRef timeInput;
private static bool pauseButtonPausing;
private static float lastTimeScale;
// defaults // defaults
internal static readonly Color enabledButtonColor = new Color(0.2f, 0.4f, 0.28f); internal static readonly Color enabledButtonColor = new Color(0.2f, 0.4f, 0.28f);
internal static readonly Color disabledButtonColor = new Color(0.25f, 0.25f, 0.25f); internal static readonly Color disabledButtonColor = new Color(0.25f, 0.25f, 0.25f);
@ -80,6 +86,105 @@ namespace UnityExplorer.UI
} }
public static bool s_showMenu = true; public static bool s_showMenu = true;
// Initialization
internal static void InitUI()
{
LoadBundle();
UIFactory.Init();
CreateRootCanvas();
// Global UI Pool Holder
PoolHolder = new GameObject("PoolHolder");
PoolHolder.transform.parent = CanvasRoot.transform;
PoolHolder.SetActive(false);
CreateTopNavBar();
UIPanels.Add(Panels.AutoCompleter, new AutoCompleteModal());
UIPanels.Add(Panels.ObjectExplorer, new ObjectExplorerPanel());
UIPanels.Add(Panels.Inspector, new InspectorPanel());
UIPanels.Add(Panels.CSConsole, new CSConsolePanel());
UIPanels.Add(Panels.ConsoleLog, new LogPanel());
UIPanels.Add(Panels.Options, new OptionsPanel());
UIPanels.Add(Panels.MouseInspector, new InspectUnderMouse());
foreach (var panel in UIPanels.Values)
panel.ConstructUI();
ConsoleController.Init();
ShowMenu = !ConfigManager.Hide_On_Startup.Value;
lastScreenWidth = Screen.width;
lastScreenHeight = Screen.height;
Initializing = false;
}
// Main UI Update loop
private static int lastScreenWidth;
private static int lastScreenHeight;
public static void Update()
{
if (!CanvasRoot || Initializing)
return;
// if doing Mouse Inspect, update that and return.
if (InspectUnderMouse.Inspecting)
{
InspectUnderMouse.Instance.UpdateInspect();
return;
}
// check master toggle
if (InputManager.GetKeyDown(ConfigManager.Master_Toggle.Value))
ShowMenu = !ShowMenu;
// return if menu closed
if (!ShowMenu)
return;
// Check forceUnlockMouse toggle
if (InputManager.GetKeyDown(ConfigManager.Force_Unlock_Toggle.Value))
CursorUnlocker.Unlock = !CursorUnlocker.Unlock;
// check event system state
if (!ConfigManager.Disable_EventSystem_Override.Value && EventSystem.current != EventSys)
CursorUnlocker.SetEventSystem();
// update focused panel
UIPanel.UpdateFocus();
// update UI model instances
PanelDragger.UpdateInstances();
InputFieldRef.UpdateInstances();
UIBehaviourModel.UpdateInstances();
// update the timescale value
if (!timeInput.Component.isFocused && lastTimeScale != Time.timeScale)
{
if (pauseButtonPausing && Time.timeScale != 0.0f)
{
pauseButtonPausing = false;
OnPauseButtonToggled();
}
if (!pauseButtonPausing)
{
timeInput.Text = Time.timeScale.ToString("F2");
lastTimeScale = Time.timeScale;
}
}
// check screen dimension change
if (Screen.width != lastScreenWidth || Screen.height != lastScreenHeight)
OnScreenDimensionsChanged();
}
// Panels // Panels
public static UIPanel GetPanel(Panels panel) public static UIPanel GetPanel(Panels panel)
@ -120,91 +225,89 @@ namespace UnityExplorer.UI
SetPanelActive(panel, value); SetPanelActive(panel, value);
} }
// Main UI Update loop // navbar
private static int lastScreenWidth; public static void SetNavBarAnchor()
private static int lastScreenHeight;
public static void Update()
{ {
if (!CanvasRoot || Initializing) switch (NavbarAnchor)
return;
if (InspectUnderMouse.Inspecting)
{ {
InspectUnderMouse.Instance.UpdateInspect(); case VerticalAnchor.Top:
return; NavBarRect.anchorMin = new Vector2(0.5f, 1f);
} NavBarRect.anchorMax = new Vector2(0.5f, 1f);
NavBarRect.anchoredPosition = new Vector2(NavBarRect.anchoredPosition.x, 0);
NavBarRect.sizeDelta = new Vector2(1000f, 35f);
break;
if (InputManager.GetKeyDown(ConfigManager.Master_Toggle.Value)) case VerticalAnchor.Bottom:
ShowMenu = !ShowMenu; NavBarRect.anchorMin = new Vector2(0.5f, 0f);
NavBarRect.anchorMax = new Vector2(0.5f, 0f);
if (!ShowMenu) NavBarRect.anchoredPosition = new Vector2(NavBarRect.anchoredPosition.x, 35);
return; NavBarRect.sizeDelta = new Vector2(1000f, 35f);
break;
if (InputManager.GetKeyDown(ConfigManager.Force_Unlock_Toggle.Value))
CursorUnlocker.Unlock = !CursorUnlocker.Unlock;
if (!ConfigManager.Disable_EventSystem_Override.Value && EventSystem.current != EventSys)
CursorUnlocker.SetEventSystem();
UIPanel.UpdateFocus();
PanelDragger.UpdateInstances();
InputFieldRef.UpdateInstances();
UIBehaviourModel.UpdateInstances();
if (Screen.width != lastScreenWidth || Screen.height != lastScreenHeight)
{
lastScreenWidth = Screen.width;
lastScreenHeight = Screen.height;
foreach (var panel in UIPanels)
{
panel.Value.EnsureValidSize();
UIPanel.EnsureValidPosition(panel.Value.Rect);
panel.Value.Dragger.OnEndResize();
}
} }
} }
// Initialization and UI Construction // listeners
internal static void InitUI() private static void OnScreenDimensionsChanged()
{ {
LoadBundle();
UIFactory.Init();
CreateRootCanvas();
// Global UI Pool Holder
PoolHolder = new GameObject("PoolHolder");
PoolHolder.transform.parent = CanvasRoot.transform;
PoolHolder.SetActive(false);
CreateTopNavBar();
UIPanels.Add(Panels.AutoCompleter, new AutoCompleteModal());
UIPanels.Add(Panels.ObjectExplorer, new ObjectExplorerPanel());
UIPanels.Add(Panels.Inspector, new InspectorPanel());
UIPanels.Add(Panels.CSConsole, new CSConsolePanel());
UIPanels.Add(Panels.ConsoleLog, new LogPanel());
UIPanels.Add(Panels.Options, new OptionsPanel());
UIPanels.Add(Panels.MouseInspector, new InspectUnderMouse());
foreach (var panel in UIPanels.Values)
panel.ConstructUI();
ConsoleController.Init();
ShowMenu = !ConfigManager.Hide_On_Startup.Value;
lastScreenWidth = Screen.width; lastScreenWidth = Screen.width;
lastScreenHeight = Screen.height; lastScreenHeight = Screen.height;
Initializing = false; foreach (var panel in UIPanels)
{
panel.Value.EnsureValidSize();
UIPanel.EnsureValidPosition(panel.Value.Rect);
panel.Value.Dragger.OnEndResize();
}
} }
private static void OnCloseButtonClicked()
{
ShowMenu = false;
}
private static void Master_Toggle_OnValueChanged(KeyCode val)
{
closeBtn.ButtonText.text = val.ToString();
}
private static void OnTimeInputEndEdit(string val)
{
if (pauseButtonPausing)
return;
if (float.TryParse(val, out float f))
{
Time.timeScale = f;
lastTimeScale = f;
}
timeInput.Text = Time.timeScale.ToString("F2");
}
private static void OnPauseButtonClicked()
{
pauseButtonPausing = !pauseButtonPausing;
Time.timeScale = pauseButtonPausing ? 0f : lastTimeScale;
OnPauseButtonToggled();
}
private static void OnPauseButtonToggled()
{
timeInput.Component.text = Time.timeScale.ToString("F2");
timeInput.Component.readOnly = pauseButtonPausing;
timeInput.Component.textComponent.color = pauseButtonPausing ? Color.grey : Color.white;
Color color = pauseButtonPausing ? new Color(0.3f, 0.3f, 0.2f) : new Color(0.2f, 0.2f, 0.2f);
RuntimeProvider.Instance.SetColorBlock(pauseBtn.Component, color, color * 1.2f, color * 0.7f);
pauseBtn.ButtonText.text = pauseButtonPausing ? "►" : "||";
}
// UI Construction
private static void CreateRootCanvas() private static void CreateRootCanvas()
{ {
CanvasRoot = new GameObject("ExplorerCanvas"); CanvasRoot = new GameObject("ExplorerCanvas");
@ -239,30 +342,10 @@ namespace UnityExplorer.UI
PanelHolder.transform.SetAsFirstSibling(); PanelHolder.transform.SetAsFirstSibling();
} }
public static void SetNavBarAnchor()
{
switch (NavbarAnchor)
{
case VerticalAnchor.Top:
NavBarRect.anchorMin = new Vector2(0.5f, 1f);
NavBarRect.anchorMax = new Vector2(0.5f, 1f);
NavBarRect.anchoredPosition = new Vector2(NavBarRect.anchoredPosition.x, 0);
NavBarRect.sizeDelta = new Vector2(900f, 35f);
break;
case VerticalAnchor.Bottom:
NavBarRect.anchorMin = new Vector2(0.5f, 0f);
NavBarRect.anchorMax = new Vector2(0.5f, 0f);
NavBarRect.anchoredPosition = new Vector2(NavBarRect.anchoredPosition.x, 35);
NavBarRect.sizeDelta = new Vector2(900f, 35f);
break;
}
}
private static void CreateTopNavBar() private static void CreateTopNavBar()
{ {
var navbarPanel = UIFactory.CreateUIObject("MainNavbar", CanvasRoot); var navbarPanel = UIFactory.CreateUIObject("MainNavbar", CanvasRoot);
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(navbarPanel, false, true, true, true, 5, 4, 4, 4, 4, TextAnchor.MiddleCenter); UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(navbarPanel, false, false, true, true, 5, 4, 4, 4, 4, TextAnchor.MiddleCenter);
navbarPanel.AddComponent<Image>().color = new Color(0.1f, 0.1f, 0.1f); navbarPanel.AddComponent<Image>().color = new Color(0.1f, 0.1f, 0.1f);
NavBarRect = navbarPanel.GetComponent<RectTransform>(); NavBarRect = navbarPanel.GetComponent<RectTransform>();
NavBarRect.pivot = new Vector2(0.5f, 1f); NavBarRect.pivot = new Vector2(0.5f, 1f);
@ -278,14 +361,28 @@ namespace UnityExplorer.UI
// UnityExplorer title // UnityExplorer title
string titleTxt = $"{ExplorerCore.NAME} <i><color=grey>{ExplorerCore.VERSION}</color></i>"; string titleTxt = $"{ExplorerCore.NAME} <i><color=grey>{ExplorerCore.VERSION}</color></i>";
var title = UIFactory.CreateLabel(navbarPanel, "Title", titleTxt, TextAnchor.MiddleLeft, default, true, 18); var title = UIFactory.CreateLabel(navbarPanel, "Title", titleTxt, TextAnchor.MiddleLeft, default, true, 17);
UIFactory.SetLayoutElement(title.gameObject, minWidth: 180, flexibleWidth: 0); UIFactory.SetLayoutElement(title.gameObject, minWidth: 170, flexibleWidth: 0);
// Navbar // panel tabs
NavbarButtonHolder = UIFactory.CreateUIObject("NavButtonHolder", navbarPanel); NavbarTabButtonHolder = UIFactory.CreateUIObject("NavTabButtonHolder", navbarPanel);
UIFactory.SetLayoutElement(NavbarButtonHolder, flexibleHeight: 999, flexibleWidth: 999); UIFactory.SetLayoutElement(NavbarTabButtonHolder, minHeight: 25, flexibleHeight: 999, flexibleWidth: 999);
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(NavbarButtonHolder, false, true, true, true, 4, 2, 2, 2, 2); UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(NavbarTabButtonHolder, false, true, true, true, 4, 2, 2, 2, 2);
// Time controls
var timeLabel = UIFactory.CreateLabel(navbarPanel, "TimeLabel", "Time:", TextAnchor.MiddleRight, Color.grey);
UIFactory.SetLayoutElement(timeLabel.gameObject, minHeight: 25, minWidth: 50);
timeInput = UIFactory.CreateInputField(navbarPanel, "TimeInput", "timeScale");
UIFactory.SetLayoutElement(timeInput.Component.gameObject, minHeight: 25, minWidth: 40);
timeInput.Text = Time.timeScale.ToString("F2");
timeInput.Component.onEndEdit.AddListener(OnTimeInputEndEdit);
pauseBtn = UIFactory.CreateButton(navbarPanel, "PauseButton", "||", new Color(0.2f, 0.2f, 0.2f));
UIFactory.SetLayoutElement(pauseBtn.Component.gameObject, minHeight: 25, minWidth: 25);
pauseBtn.OnClick += OnPauseButtonClicked;
// Inspect under mouse dropdown // Inspect under mouse dropdown
@ -298,14 +395,13 @@ namespace UnityExplorer.UI
// Hide menu button // Hide menu button
var closeBtn = UIFactory.CreateButton(navbarPanel, "CloseButton", ConfigManager.Master_Toggle.Value.ToString()); closeBtn = UIFactory.CreateButton(navbarPanel, "CloseButton", ConfigManager.Master_Toggle.Value.ToString());
UIFactory.SetLayoutElement(closeBtn.Component.gameObject, minHeight: 25, minWidth: 80, flexibleWidth: 0); UIFactory.SetLayoutElement(closeBtn.Component.gameObject, minHeight: 25, minWidth: 80, flexibleWidth: 0);
RuntimeProvider.Instance.SetColorBlock(closeBtn.Component, new Color(0.63f, 0.32f, 0.31f), RuntimeProvider.Instance.SetColorBlock(closeBtn.Component, new Color(0.63f, 0.32f, 0.31f),
new Color(0.81f, 0.25f, 0.2f), new Color(0.6f, 0.18f, 0.16f)); new Color(0.81f, 0.25f, 0.2f), new Color(0.6f, 0.18f, 0.16f));
ConfigManager.Master_Toggle.OnValueChanged += (KeyCode val) => { closeBtn.ButtonText.text = val.ToString(); }; ConfigManager.Master_Toggle.OnValueChanged += Master_Toggle_OnValueChanged;
closeBtn.OnClick += OnCloseButtonClicked;
closeBtn.OnClick += () => { ShowMenu = false; };
} }
#region UI AssetBundle #region UI AssetBundle

View File

@ -6,31 +6,6 @@ using UnityEngine;
namespace UnityExplorer.UI.Widgets namespace UnityExplorer.UI.Widgets
{ {
public struct DataViewInfo
{
// static
public static DataViewInfo None => s_default;
private static DataViewInfo s_default = default;
public static implicit operator float(DataViewInfo it) => it.height;
// instance
public int dataIndex, normalizedSpread;
public float height, startPosition;
public override bool Equals(object obj)
{
var other = (DataViewInfo)obj;
return this.dataIndex == other.dataIndex
&& this.height == other.height
&& this.startPosition == other.startPosition
&& this.normalizedSpread == other.normalizedSpread;
}
public override int GetHashCode() => base.GetHashCode();
}
public class DataHeightCache<T> where T : ICell public class DataHeightCache<T> where T : ICell
{ {
private ScrollPool<T> ScrollPool { get; } private ScrollPool<T> ScrollPool { get; }
@ -93,11 +68,10 @@ namespace UnityExplorer.UI.Widgets
int expectedMax = expectedMin + cache.normalizedSpread - 1; int expectedMax = expectedMin + cache.normalizedSpread - 1;
if (rangeIndex < expectedMin || rangeIndex > expectedMax) if (rangeIndex < expectedMin || rangeIndex > expectedMax)
{ {
RecalculateStartPositions(Math.Max(dataIndex, expectedMax)); RecalculateStartPositions(ScrollPool.DataSource.ItemCount - 1);
rangeIndex = GetRangeFloorOfPosition(desiredHeight); rangeIndex = GetRangeFloorOfPosition(desiredHeight);
dataIndex = rangeCache[rangeIndex]; dataIndex = rangeCache[rangeIndex];
//cache = heightCache[dataIndex];
} }
return dataIndex; return dataIndex;
@ -125,17 +99,11 @@ namespace UnityExplorer.UI.Widgets
/// <summary>Append a data index to the cache with the provided height value.</summary> /// <summary>Append a data index to the cache with the provided height value.</summary>
public void Add(float value) public void Add(float value)
{ {
value = (float)Math.Floor(value);
value = Math.Max(DefaultHeight, value); value = Math.Max(DefaultHeight, value);
int spread = GetRangeSpread(totalHeight, value); int spread = GetRangeSpread(totalHeight, value);
heightCache.Add(new DataViewInfo() heightCache.Add(new DataViewInfo(heightCache.Count, value, totalHeight, spread));
{
height = value,
startPosition = TotalHeight,
normalizedSpread = spread,
});
int dataIdx = heightCache.Count - 1; int dataIdx = heightCache.Count - 1;
for (int i = 0; i < spread; i++) for (int i = 0; i < spread; i++)
@ -203,31 +171,31 @@ namespace UnityExplorer.UI.Widgets
int spread = GetRangeSpread(cache.startPosition, height); int spread = GetRangeSpread(cache.startPosition, height);
// If the previous item in the range cache is not the previous data index, there is a gap. // If the previous item in the range cache is not the previous data index, there is a gap.
if (dataIndex > 0 && rangeCache[rangeIndex - 1] != (dataIndex - 1)) if (rangeCache[rangeIndex] != dataIndex)
{ {
// Recalculate start positions up to this index. The gap could be anywhere before here. // Recalculate start positions up to this index. The gap could be anywhere before here.
RecalculateStartPositions(dataIndex + 1); RecalculateStartPositions(ScrollPool.DataSource.ItemCount - 1);
// Get the range index and spread again after rebuilding // Get the range index and spread again after rebuilding
rangeIndex = GetRangeCeilingOfPosition(cache.startPosition); rangeIndex = GetRangeCeilingOfPosition(cache.startPosition);
spread = GetRangeSpread(cache.startPosition, height); spread = GetRangeSpread(cache.startPosition, height);
} }
if (rangeCache.Count <= rangeIndex || rangeCache[rangeIndex] != dataIndex) if (rangeCache[rangeIndex] != dataIndex)
throw new Exception("ScrollPool data height cache is corrupt or invalid, rebuild failed!"); throw new IndexOutOfRangeException($"Trying to set dataIndex {dataIndex} at rangeIndex {rangeIndex}, but cache is corrupt or invalid!");
if (spread != cache.normalizedSpread) if (spread != cache.normalizedSpread)
{ {
int spreadDiff = spread - cache.normalizedSpread; int spreadDiff = spread - cache.normalizedSpread;
cache.normalizedSpread = spread; cache.normalizedSpread = spread;
SetSpread(dataIndex, rangeIndex, spreadDiff); UpdateSpread(dataIndex, rangeIndex, spreadDiff);
} }
// set the struct back to the array (TODO necessary?) // set the struct back to the array
heightCache[dataIndex] = cache; heightCache[dataIndex] = cache;
} }
private void SetSpread(int dataIndex, int rangeIndex, int spreadDiff) private void UpdateSpread(int dataIndex, int rangeIndex, int spreadDiff)
{ {
if (spreadDiff > 0) if (spreadDiff > 0)
{ {
@ -244,8 +212,6 @@ namespace UnityExplorer.UI.Widgets
rangeCache.RemoveAt(rangeIndex); rangeCache.RemoveAt(rangeIndex);
spreadDiff++; spreadDiff++;
} }
//for (int i = 0; i < -spreadDiff; i++)
// rangeCache.RemoveAt(rangeIndex);
} }
} }
@ -254,24 +220,60 @@ namespace UnityExplorer.UI.Widgets
if (heightCache.Count <= 1) if (heightCache.Count <= 1)
return; return;
rangeCache.Clear();
DataViewInfo cache; DataViewInfo cache;
DataViewInfo prev = DataViewInfo.None; DataViewInfo prev = DataViewInfo.None;
for (int i = 0; i <= toIndex && i < heightCache.Count; i++) for (int idx = 0; idx <= toIndex && idx < heightCache.Count; idx++)
{ {
cache = heightCache[i]; cache = heightCache[idx];
if (prev != DataViewInfo.None) if (!prev.Equals(DataViewInfo.None))
cache.startPosition = prev.startPosition + prev.height; cache.startPosition = prev.startPosition + prev.height;
else else
cache.startPosition = 0; cache.startPosition = 0;
var origSpread = cache.normalizedSpread;
cache.normalizedSpread = GetRangeSpread(cache.startPosition, cache.height); cache.normalizedSpread = GetRangeSpread(cache.startPosition, cache.height);
if (cache.normalizedSpread != origSpread) for (int i = 0; i < cache.normalizedSpread; i++)
SetSpread(i, GetRangeCeilingOfPosition(cache.startPosition), cache.normalizedSpread - origSpread); rangeCache.Add(cache.dataIndex);
heightCache[idx] = cache;
prev = cache; prev = cache;
} }
} }
public struct DataViewInfo
{
// static
public static DataViewInfo None => s_default;
private static DataViewInfo s_default = default;
public static implicit operator float(DataViewInfo it) => it.height;
public DataViewInfo(int index, float height, float startPos, int spread)
{
this.dataIndex = index;
this.height = height;
this.startPosition = startPos;
this.normalizedSpread = spread;
}
// instance
public int dataIndex, normalizedSpread;
public float height, startPosition;
public override bool Equals(object obj)
{
var other = (DataViewInfo)obj;
return this.dataIndex == other.dataIndex
&& this.height == other.height
&& this.startPosition == other.startPosition
&& this.normalizedSpread == other.normalizedSpread;
}
public override int GetHashCode() => base.GetHashCode();
}
} }
} }

View File

@ -142,7 +142,9 @@ namespace UnityExplorer.UI.Widgets
RefreshCells(true, true); RefreshCells(true, true);
// Slide to the normalized position of the index // Slide to the normalized position of the index
float normalized = HeightCache[index].startPosition / HeightCache.TotalHeight; var cache = HeightCache[index];
float normalized = (cache.startPosition + (cache.height * 0.5f)) / HeightCache.TotalHeight;
RuntimeProvider.Instance.StartCoroutine(ForceDelayedJump(index, normalized, onJumped)); RuntimeProvider.Instance.StartCoroutine(ForceDelayedJump(index, normalized, onJumped));
} }
@ -191,13 +193,12 @@ namespace UnityExplorer.UI.Widgets
RuntimeProvider.Instance.StartCoroutine(InitCoroutine(onHeightChangedListener)); RuntimeProvider.Instance.StartCoroutine(InitCoroutine(onHeightChangedListener));
} }
private readonly WaitForEndOfFrame waitForEndOfFrame = new WaitForEndOfFrame(); private WaitForEndOfFrame waitForEndOfFrame = new WaitForEndOfFrame();
private IEnumerator InitCoroutine(Action onHeightChangedListener) private IEnumerator InitCoroutine(Action onHeightChangedListener)
{ {
ScrollRect.content.anchoredPosition = Vector2.zero; ScrollRect.content.anchoredPosition = Vector2.zero;
//yield return null; yield return waitForEndOfFrame ?? (waitForEndOfFrame = new WaitForEndOfFrame());
yield return waitForEndOfFrame;
LayoutRebuilder.ForceRebuildLayoutImmediate(Content); LayoutRebuilder.ForceRebuildLayoutImmediate(Content);

View File

@ -83,6 +83,7 @@ namespace UnityExplorer.UI.Widgets
displayIndex = 0; displayIndex = 0;
autoExpandedIDs.Clear(); autoExpandedIDs.Clear();
expandedInstanceIDs.Clear(); expandedInstanceIDs.Clear();
this.ScrollPool.Refresh(true, true);
} }
public bool IsCellExpanded(int instanceID) public bool IsCellExpanded(int instanceID)

View File

@ -143,12 +143,12 @@
</Reference> </Reference>
</ItemGroup> </ItemGroup>
<!-- BepInEx universal refs --> <!-- BepInEx universal refs -->
<ItemGroup Condition="'$(IsBepInEx)'=='true'"> <ItemGroup Condition="'$(IsBepInEx)'=='true'">
<Reference Include="0Harmony"> <Reference Include="0Harmony">
<HintPath>..\lib\HarmonyX\Harmony\bin\Release\net35\0Harmony.dll</HintPath> <HintPath>packages\HarmonyX.2.4.2\lib\net35\0Harmony.dll</HintPath>
<Private>False</Private> <Private>False</Private>
</Reference> </Reference>
</ItemGroup> </ItemGroup>
<!-- BepInEx 5 Mono refs --> <!-- BepInEx 5 Mono refs -->
<ItemGroup Condition="'$(IsBepInEx)|$(IsCpp)|$(Configuration)'=='true|false|Release_BIE5_Mono'"> <ItemGroup Condition="'$(IsBepInEx)|$(IsCpp)|$(Configuration)'=='true|false|Release_BIE5_Mono'">
<Reference Include="BepInEx"> <Reference Include="BepInEx">
@ -180,10 +180,10 @@
</ItemGroup> </ItemGroup>
<!-- Standalone refs --> <!-- Standalone refs -->
<ItemGroup Condition="'$(IsStandalone)'=='true'"> <ItemGroup Condition="'$(IsStandalone)'=='true'">
<Reference Include="0Harmony"> <Reference Include="0Harmony">
<HintPath>..\lib\HarmonyX\Harmony\bin\Release\net35\0Harmony.dll</HintPath> <HintPath>packages\HarmonyX.2.4.2\lib\net35\0Harmony.dll</HintPath>
<Private>False</Private> <Private>False</Private>
</Reference> </Reference>
</ItemGroup> </ItemGroup>
<!-- Mono refs --> <!-- Mono refs -->
<ItemGroup Condition="'$(IsCpp)'=='false'"> <ItemGroup Condition="'$(IsCpp)'=='false'">
@ -290,8 +290,7 @@
<Compile Include="UI\Inspectors\ReflectionInspector.cs" /> <Compile Include="UI\Inspectors\ReflectionInspector.cs" />
<Compile Include="UI\CacheObject\IValues\InteractiveValueStruct.cs" /> <Compile Include="UI\CacheObject\IValues\InteractiveValueStruct.cs" />
<Compile Include="UI\Models\InputFieldRef.cs" /> <Compile Include="UI\Models\InputFieldRef.cs" />
<Compile Include="UI\Models\ObjectPool\IPooledObject.cs" /> <Compile Include="UI\Pool.cs" />
<Compile Include="UI\Models\ObjectPool\Pool.cs" />
<Compile Include="UI\Panels\LogPanel.cs" /> <Compile Include="UI\Panels\LogPanel.cs" />
<Compile Include="UI\Panels\CSConsolePanel.cs" /> <Compile Include="UI\Panels\CSConsolePanel.cs" />
<Compile Include="Core\Utility\IOUtility.cs" /> <Compile Include="Core\Utility\IOUtility.cs" />
@ -367,11 +366,11 @@
</ItemGroup> </ItemGroup>
<ItemGroup /> <ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="packages\ILRepack.Lib.MSBuild.Task.2.0.18.1\build\ILRepack.Lib.MSBuild.Task.targets" Condition="Exists('packages\ILRepack.Lib.MSBuild.Task.2.0.18.1\build\ILRepack.Lib.MSBuild.Task.targets')" /> <Import Project="packages\ILRepack.Lib.MSBuild.Task.2.0.18.2\build\ILRepack.Lib.MSBuild.Task.targets" Condition="Exists('packages\ILRepack.Lib.MSBuild.Task.2.0.18.2\build\ILRepack.Lib.MSBuild.Task.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild"> <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup> <PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText> <ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup> </PropertyGroup>
<Error Condition="!Exists('packages\ILRepack.Lib.MSBuild.Task.2.0.18.1\build\ILRepack.Lib.MSBuild.Task.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\ILRepack.Lib.MSBuild.Task.2.0.18.1\build\ILRepack.Lib.MSBuild.Task.targets'))" /> <Error Condition="!Exists('packages\ILRepack.Lib.MSBuild.Task.2.0.18.2\build\ILRepack.Lib.MSBuild.Task.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\ILRepack.Lib.MSBuild.Task.2.0.18.2\build\ILRepack.Lib.MSBuild.Task.targets'))" />
</Target> </Target>
</Project> </Project>

View File

@ -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}") = "Harmony", "..\lib\HarmonyX\Harmony\Harmony.csproj", "{F2D7872C-5D4D-49EB-A656-C3D496DB4204}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnhollowerBaseLib", "..\lib\Il2CppAssemblyUnhollower\UnhollowerBaseLib\UnhollowerBaseLib.csproj", "{7B7E5024-385D-4A46-9196-A6AF8F7FBDD5}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnhollowerBaseLib", "..\lib\Il2CppAssemblyUnhollower\UnhollowerBaseLib\UnhollowerBaseLib.csproj", "{7B7E5024-385D-4A46-9196-A6AF8F7FBDD5}"
EndProject 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}"
@ -24,24 +22,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
{F2D7872C-5D4D-49EB-A656-C3D496DB4204}.Release_BIE_Cpp|Any CPU.ActiveCfg = Release|Any CPU
{F2D7872C-5D4D-49EB-A656-C3D496DB4204}.Release_BIE_Cpp|Any CPU.Build.0 = Release|Any CPU
{F2D7872C-5D4D-49EB-A656-C3D496DB4204}.Release_BIE5_Mono|Any CPU.ActiveCfg = Release|Any CPU
{F2D7872C-5D4D-49EB-A656-C3D496DB4204}.Release_BIE5_Mono|Any CPU.Build.0 = Release|Any CPU
{F2D7872C-5D4D-49EB-A656-C3D496DB4204}.Release_BIE6_Mono|Any CPU.ActiveCfg = Release|Any CPU
{F2D7872C-5D4D-49EB-A656-C3D496DB4204}.Release_BIE6_Mono|Any CPU.Build.0 = Release|Any CPU
{F2D7872C-5D4D-49EB-A656-C3D496DB4204}.Release_ML_Cpp|Any CPU.ActiveCfg = Release|Any CPU
{F2D7872C-5D4D-49EB-A656-C3D496DB4204}.Release_ML_Cpp|Any CPU.Build.0 = Release|Any CPU
{F2D7872C-5D4D-49EB-A656-C3D496DB4204}.Release_ML_Mono|Any CPU.ActiveCfg = Release|Any CPU
{F2D7872C-5D4D-49EB-A656-C3D496DB4204}.Release_ML_Mono|Any CPU.Build.0 = Release|Any CPU
{F2D7872C-5D4D-49EB-A656-C3D496DB4204}.Release_MLLegacy_Cpp|Any CPU.ActiveCfg = Release|Any CPU
{F2D7872C-5D4D-49EB-A656-C3D496DB4204}.Release_MLLegacy_Cpp|Any CPU.Build.0 = Release|Any CPU
{F2D7872C-5D4D-49EB-A656-C3D496DB4204}.Release_MLLegacy_Mono|Any CPU.ActiveCfg = Release|Any CPU
{F2D7872C-5D4D-49EB-A656-C3D496DB4204}.Release_MLLegacy_Mono|Any CPU.Build.0 = Release|Any CPU
{F2D7872C-5D4D-49EB-A656-C3D496DB4204}.Release_STANDALONE_Cpp|Any CPU.ActiveCfg = Release|Any CPU
{F2D7872C-5D4D-49EB-A656-C3D496DB4204}.Release_STANDALONE_Cpp|Any CPU.Build.0 = Release|Any CPU
{F2D7872C-5D4D-49EB-A656-C3D496DB4204}.Release_STANDALONE_Mono|Any CPU.ActiveCfg = Release|Any CPU
{F2D7872C-5D4D-49EB-A656-C3D496DB4204}.Release_STANDALONE_Mono|Any CPU.Build.0 = Release|Any CPU
{7B7E5024-385D-4A46-9196-A6AF8F7FBDD5}.Release_BIE_Cpp|Any CPU.ActiveCfg = Release|Any CPU {7B7E5024-385D-4A46-9196-A6AF8F7FBDD5}.Release_BIE_Cpp|Any CPU.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_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.ActiveCfg = Release|Any CPU

View File

@ -1,5 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="ILRepack.Lib.MSBuild.Task" version="2.0.18.1" targetFramework="net472" /> <package id="HarmonyX" version="2.4.2" targetFramework="net35" />
<package id="ILRepack.Lib.MSBuild.Task" version="2.0.18.2" targetFramework="net35" />
<package id="ini-parser" version="2.5.2" targetFramework="net35" /> <package id="ini-parser" version="2.5.2" targetFramework="net35" />
<package id="Mono.Cecil" version="0.10.4" targetFramework="net35" />
</packages> </packages>