Compare commits

..

36 Commits
4.0.7 ... 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
22 changed files with 451 additions and 212 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"]
path = lib/Il2CppAssemblyUnhollower
url = https://github.com/knah/Il2CppAssemblyUnhollower
[submodule "lib/HarmonyX"]
path = lib/HarmonyX
url = https://github.com/BepInEx/HarmonyX
[submodule "lib/mcs-unity"]
path = lib/mcs-unity
url = https://github.com/sinai-dev/mcs-unity

View File

@ -10,8 +10,9 @@
Supports most Unity games from versions 5.2 to 2020+.
</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 |
| ----------- | ------ | ---- |
| [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) |
| 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
* 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.
@ -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).
For the GameObject Inspector, you can edit any of the input fields in the inspector (excluding readonly fields) and press <b>Enter</b> to apply your changes. You can also do this to the GameObject path as a way to change the GameObject's parent. Press the <b>Escape</b> key to cancel your edits.
In the Reflection Inspectors, automatic updating is not enabled by default, and you must press Apply for any changes you make to take effect.
* 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.
### C# Console
@ -94,11 +96,18 @@ Depending on the release you are using, the config file will be found at:
## Building
If you fork the repository on GitHub you can build using the [dotnet workflow](https://github.com/sinai-dev/UnityExplorer/blob/master/.github/workflows/dotnet.yml):
0. Click on the Actions tab and enable workflows in your repository
1. Click on the "Build UnityExplorer" workflow, then click "Run Workflow" and run it manually, or make a new commit to trigger the workflow.
2. Take the artifact from the completed run.
For Visual Studio:
0. Clone the repository and run `git submodule update --init --recursive` to get the submodules.
1. Open the `src\UnityExplorer.sln` project in Visual Studio.
2. Select `Solution 'UnityExplorer' (1 of 1 project)` in the Solution Explorer panel, and set the <b>Active config</b> property to the version you want to build, then build it. Alternatively, use "Batch Build" and select all releases.
3. The DLLs are built to the `Release\` folder in the root of the repository.
4. If ILRepack complains about an error, just change the Active config to a different release and then back again. This sometimes happens for the first time you build the project.
1. Open the `src\UnityExplorer.sln` project.
2. Build `mcs`, and if using IL2CPP then build `UnhollowerBaseLib` as well.
3. Build the UnityExplorer release(s) you want to use, either by selecting the config as the Active Config, or batch-building.
## Acknowledgments

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.",
1f);
Reflection_Signature_Blacklist = new ConfigElement<string>("Reflection Signature Blacklist",
"Use this to blacklist certain member signatures if they are known to cause a crash or other issues." +
"\r\nSeperate signatures with a semicolon ';'.",
"DEFAULT");
Reflection_Signature_Blacklist = new ConfigElement<string>("Member Signature Blacklist",
"Use this to blacklist certain member signatures if they are known to cause a crash or other issues.\r\n" +
"Seperate signatures with a semicolon ';'.\r\n" +
"For example, to blacklist Camera.main, you would add 'Camera.main;'",
"");
// Internal configs (panel save data)

View File

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

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()
{
while (true)
{
yield return _waitForEndOfFrame;
yield return _waitForEndOfFrame ?? (_waitForEndOfFrame = new WaitForEndOfFrame());
if (UIManager.ShowMenu)
UpdateCursorControl();

View File

@ -520,7 +520,7 @@ namespace UnityExplorer
#region Il2cpp reflection blacklist
public override string DefaultReflectionBlacklist => string.Join(";", defaultIl2CppBlacklist);
public override string[] DefaultReflectionBlacklist => defaultIl2CppBlacklist.ToArray();
// These methods currently cause a crash in most il2cpp games,
// even from doing "GetParameters()" on the MemberInfo.

View File

@ -12,7 +12,6 @@ using UnityExplorer.Core.Config;
namespace UnityExplorer
{
public class ReflectionUtility
{
public const BF FLAGS = BF.Public | BF.Instance | BF.NonPublic | BF.Static;
@ -434,20 +433,17 @@ namespace UnityExplorer
#region Reflection Blacklist
public virtual string DefaultReflectionBlacklist => string.Empty;
public virtual string[] DefaultReflectionBlacklist => new string[0];
public static void LoadBlacklistString(string blacklist)
{
if (string.Equals(blacklist, "DEFAULT", StringComparison.InvariantCultureIgnoreCase))
try
{
blacklist = Instance.DefaultReflectionBlacklist;
ConfigManager.Reflection_Signature_Blacklist.Value = blacklist;
ConfigManager.Handler.SaveConfig();
}
if (string.IsNullOrEmpty(blacklist))
if (string.IsNullOrEmpty(blacklist) && !Instance.DefaultReflectionBlacklist.Any())
return;
try
{
var sigs = blacklist.Split(';');
foreach (var sig in sigs)
{
@ -457,9 +453,25 @@ namespace UnityExplorer
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)
{
ExplorerCore.LogWarning($"Exception setting up reflection blacklist: {ex.ReflectionExToString()}");
}
}
public static bool IsBlacklisted(MemberInfo member)
{

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -15,16 +15,16 @@ namespace UnityExplorer.UI.ObjectExplorer
/// </summary>
public static Scene? SelectedScene
{
get => m_selectedScene;
get => selectedScene;
internal set
{
if (m_selectedScene != null && m_selectedScene == value)
if (selectedScene != null && selectedScene == value)
return;
m_selectedScene = value;
OnInspectedSceneChanged?.Invoke((Scene)m_selectedScene);
selectedScene = value;
OnInspectedSceneChanged?.Invoke((Scene)selectedScene);
}
}
private static Scene? m_selectedScene;
private static Scene? selectedScene;
/// <summary>
/// The GameObjects in the currently inspected scene.
@ -62,7 +62,7 @@ namespace UnityExplorer.UI.ObjectExplorer
public static event Action<ReadOnlyCollection<Scene>> OnLoadedScenesChanged;
/// <summary>
/// Equivalent to <see cref="SceneManager.sceneCount"/> + 2, to include 'DontDestroyOnLoad'.
/// Equivalent to <see cref="SceneManager.sceneCount"/> + 2, to include 'DontDestroyOnLoad' and the 'None' scene.
/// </summary>
public static int LoadedSceneCount => SceneManager.sceneCount + 2;

View File

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

View File

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

View File

@ -193,13 +193,12 @@ namespace UnityExplorer.UI.Widgets
RuntimeProvider.Instance.StartCoroutine(InitCoroutine(onHeightChangedListener));
}
private readonly WaitForEndOfFrame waitForEndOfFrame = new WaitForEndOfFrame();
private WaitForEndOfFrame waitForEndOfFrame = new WaitForEndOfFrame();
private IEnumerator InitCoroutine(Action onHeightChangedListener)
{
ScrollRect.content.anchoredPosition = Vector2.zero;
//yield return null;
yield return waitForEndOfFrame;
yield return waitForEndOfFrame ?? (waitForEndOfFrame = new WaitForEndOfFrame());
LayoutRebuilder.ForceRebuildLayoutImmediate(Content);

View File

@ -145,7 +145,7 @@
<!-- BepInEx universal refs -->
<ItemGroup Condition="'$(IsBepInEx)'=='true'">
<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>
</Reference>
</ItemGroup>
@ -181,7 +181,7 @@
<!-- Standalone refs -->
<ItemGroup Condition="'$(IsStandalone)'=='true'">
<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>
</Reference>
</ItemGroup>
@ -366,11 +366,11 @@
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="packages\ILRepack.Lib.MSBuild.Task.2.0.18.1\build\ILRepack.Lib.MSBuild.Task.targets" Condition="Exists('packages\ILRepack.Lib.MSBuild.Task.2.0.18.1\build\ILRepack.Lib.MSBuild.Task.targets')" />
<Import Project="packages\ILRepack.Lib.MSBuild.Task.2.0.18.2\build\ILRepack.Lib.MSBuild.Task.targets" Condition="Exists('packages\ILRepack.Lib.MSBuild.Task.2.0.18.2\build\ILRepack.Lib.MSBuild.Task.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('packages\ILRepack.Lib.MSBuild.Task.2.0.18.1\build\ILRepack.Lib.MSBuild.Task.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\ILRepack.Lib.MSBuild.Task.2.0.18.1\build\ILRepack.Lib.MSBuild.Task.targets'))" />
<Error Condition="!Exists('packages\ILRepack.Lib.MSBuild.Task.2.0.18.2\build\ILRepack.Lib.MSBuild.Task.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\ILRepack.Lib.MSBuild.Task.2.0.18.2\build\ILRepack.Lib.MSBuild.Task.targets'))" />
</Target>
</Project>

View File

@ -3,8 +3,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30128.74
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Harmony", "..\lib\HarmonyX\Harmony\Harmony.csproj", "{F2D7872C-5D4D-49EB-A656-C3D496DB4204}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnhollowerBaseLib", "..\lib\Il2CppAssemblyUnhollower\UnhollowerBaseLib\UnhollowerBaseLib.csproj", "{7B7E5024-385D-4A46-9196-A6AF8F7FBDD5}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "mcs", "..\lib\mcs-unity\mcs\mcs.csproj", "{E4989E4C-0875-4528-9031-08E2C0E70103}"
@ -24,24 +22,6 @@ Global
Release_STANDALONE_Mono|Any CPU = Release_STANDALONE_Mono|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{F2D7872C-5D4D-49EB-A656-C3D496DB4204}.Release_BIE_Cpp|Any CPU.ActiveCfg = Release|Any CPU
{F2D7872C-5D4D-49EB-A656-C3D496DB4204}.Release_BIE_Cpp|Any CPU.Build.0 = Release|Any CPU
{F2D7872C-5D4D-49EB-A656-C3D496DB4204}.Release_BIE5_Mono|Any CPU.ActiveCfg = Release|Any CPU
{F2D7872C-5D4D-49EB-A656-C3D496DB4204}.Release_BIE5_Mono|Any CPU.Build.0 = Release|Any CPU
{F2D7872C-5D4D-49EB-A656-C3D496DB4204}.Release_BIE6_Mono|Any CPU.ActiveCfg = Release|Any CPU
{F2D7872C-5D4D-49EB-A656-C3D496DB4204}.Release_BIE6_Mono|Any CPU.Build.0 = Release|Any CPU
{F2D7872C-5D4D-49EB-A656-C3D496DB4204}.Release_ML_Cpp|Any CPU.ActiveCfg = Release|Any CPU
{F2D7872C-5D4D-49EB-A656-C3D496DB4204}.Release_ML_Cpp|Any CPU.Build.0 = Release|Any CPU
{F2D7872C-5D4D-49EB-A656-C3D496DB4204}.Release_ML_Mono|Any CPU.ActiveCfg = Release|Any CPU
{F2D7872C-5D4D-49EB-A656-C3D496DB4204}.Release_ML_Mono|Any CPU.Build.0 = Release|Any CPU
{F2D7872C-5D4D-49EB-A656-C3D496DB4204}.Release_MLLegacy_Cpp|Any CPU.ActiveCfg = Release|Any CPU
{F2D7872C-5D4D-49EB-A656-C3D496DB4204}.Release_MLLegacy_Cpp|Any CPU.Build.0 = Release|Any CPU
{F2D7872C-5D4D-49EB-A656-C3D496DB4204}.Release_MLLegacy_Mono|Any CPU.ActiveCfg = Release|Any CPU
{F2D7872C-5D4D-49EB-A656-C3D496DB4204}.Release_MLLegacy_Mono|Any CPU.Build.0 = Release|Any CPU
{F2D7872C-5D4D-49EB-A656-C3D496DB4204}.Release_STANDALONE_Cpp|Any CPU.ActiveCfg = Release|Any CPU
{F2D7872C-5D4D-49EB-A656-C3D496DB4204}.Release_STANDALONE_Cpp|Any CPU.Build.0 = Release|Any CPU
{F2D7872C-5D4D-49EB-A656-C3D496DB4204}.Release_STANDALONE_Mono|Any CPU.ActiveCfg = Release|Any CPU
{F2D7872C-5D4D-49EB-A656-C3D496DB4204}.Release_STANDALONE_Mono|Any CPU.Build.0 = Release|Any CPU
{7B7E5024-385D-4A46-9196-A6AF8F7FBDD5}.Release_BIE_Cpp|Any CPU.ActiveCfg = Release|Any CPU
{7B7E5024-385D-4A46-9196-A6AF8F7FBDD5}.Release_BIE_Cpp|Any CPU.Build.0 = Release|Any CPU
{7B7E5024-385D-4A46-9196-A6AF8F7FBDD5}.Release_BIE5_Mono|Any CPU.ActiveCfg = Release|Any CPU

View File

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