diff --git a/src/Core/Config/ConfigManager.cs b/src/Core/Config/ConfigManager.cs index 7382af2..1091a25 100644 --- a/src/Core/Config/ConfigManager.cs +++ b/src/Core/Config/ConfigManager.cs @@ -18,6 +18,8 @@ namespace UnityExplorer.Core.Config public static ConfigElement Main_Menu_Toggle; public static ConfigElement Force_Unlock_Mouse; + public static ConfigElement Force_Unlock_Keybind; + public static ConfigElement Aggressive_Force_Unlock; //public static ConfigElement Default_Tab; public static ConfigElement Default_Page_Limit; public static ConfigElement Default_Output_Path; @@ -76,6 +78,18 @@ namespace UnityExplorer.Core.Config "Should UnityExplorer be hidden on startup?", false); + Force_Unlock_Mouse = new ConfigElement("Force Unlock Mouse", + "Force the Cursor to be unlocked (visible) when the UnityExplorer menu is open.", + true); + + Force_Unlock_Keybind = new ConfigElement("Force Unlock Keybind", + "The keybind to toggle the 'Force Unlock Mouse' setting. Only usable when UnityExplorer is open.", + KeyCode.F6); + + Aggressive_Force_Unlock = new ConfigElement("Aggressive Mouse Unlock", + "Use Camera.onPostRender callback to aggressively force the Mouse to be unlocked (requires game restart).", + false); + //Default_Tab = new ConfigElement("Default Tab", // "The default menu page when starting the game.", // MenuPages.Home); @@ -84,10 +98,6 @@ namespace UnityExplorer.Core.Config "Should UnityEngine.Debug.Log messages be printed to UnityExplorer's log?", false); - Force_Unlock_Mouse = new ConfigElement("Force Unlock Mouse", - "Force the Cursor to be unlocked (visible) when the UnityExplorer menu is open.", - true); - Default_Page_Limit = new ConfigElement("Default Page Limit", "The default maximum number of elements per 'page' in UnityExplorer.", 25); diff --git a/src/Core/Input/CursorUnlocker.cs b/src/Core/Input/CursorUnlocker.cs index 6ef9bba..0ad7f37 100644 --- a/src/Core/Input/CursorUnlocker.cs +++ b/src/Core/Input/CursorUnlocker.cs @@ -41,6 +41,9 @@ namespace UnityExplorer.Core.Input public static void Init() { + if (ConfigManager.Aggressive_Force_Unlock.Value) + RuntimeProvider.Instance.SetupCameraDelegate(); + SetupPatches(); UpdateCursorControl(); @@ -49,6 +52,20 @@ namespace UnityExplorer.Core.Input ConfigManager.Force_Unlock_Mouse.OnValueChanged += (bool val) => { Unlock = val; }; } + public static void OnCameraPostRender(Camera _) + { + if (!UIManager.ShowMenu) + return; + UpdateIfNeeded(); + } + + public static void UpdateIfNeeded() + { + if ((!ShouldActuallyUnlock && (Cursor.visible || Cursor.lockState == CursorLockMode.None)) + || (ShouldActuallyUnlock && (!Cursor.visible || Cursor.lockState != CursorLockMode.None))) + UpdateCursorControl(); + } + public static void UpdateCursorControl() { try diff --git a/src/Core/Runtime/Il2Cpp/Il2CppProvider.cs b/src/Core/Runtime/Il2Cpp/Il2CppProvider.cs index 8cc50f4..02136ce 100644 --- a/src/Core/Runtime/Il2Cpp/Il2CppProvider.cs +++ b/src/Core/Runtime/Il2Cpp/Il2CppProvider.cs @@ -26,6 +26,24 @@ namespace UnityExplorer.Core.Runtime.Il2Cpp TextureUtil = new Il2CppTextureUtil(); } + public override void SetupCameraDelegate() + { + try + { + var action = new Action(CursorUnlocker.OnCameraPostRender); + var _delegate = DelegateSupport.ConvertDelegate(action); + if (Camera.onPostRender == null) + Camera.onPostRender = _delegate; + else + Camera.onPostRender = Camera.onPostRender.CombineImpl(_delegate).TryCast(); + + } + catch (Exception ex) + { + ExplorerCore.LogWarning($"Exception setting up Camera.onPostRender callback: {ex}"); + } + } + public override void SetupEvents() { try diff --git a/src/Core/Runtime/Mono/MonoProvider.cs b/src/Core/Runtime/Mono/MonoProvider.cs index bf6a918..b1afedf 100644 --- a/src/Core/Runtime/Mono/MonoProvider.cs +++ b/src/Core/Runtime/Mono/MonoProvider.cs @@ -12,6 +12,7 @@ using UnityEngine.SceneManagement; using UnityEngine.UI; using UnityExplorer.Core; using UnityExplorer.Core.CSharp; +using UnityExplorer.Core.Input; namespace UnityExplorer.Core.Runtime.Mono { @@ -26,6 +27,11 @@ namespace UnityExplorer.Core.Runtime.Mono DummyBehaviour.Setup(); } + public override void SetupCameraDelegate() + { + Camera.onPostRender += CursorUnlocker.OnCameraPostRender; + } + public override void SetupEvents() { Application.logMessageReceived += Application_logMessageReceived; diff --git a/src/Core/Runtime/RuntimeProvider.cs b/src/Core/Runtime/RuntimeProvider.cs index 60cb6f9..affb02b 100644 --- a/src/Core/Runtime/RuntimeProvider.cs +++ b/src/Core/Runtime/RuntimeProvider.cs @@ -35,6 +35,8 @@ namespace UnityExplorer public abstract void Initialize(); + public abstract void SetupCameraDelegate(); + public abstract void SetupEvents(); public abstract void StartCoroutine(IEnumerator routine); diff --git a/src/ExplorerCore.cs b/src/ExplorerCore.cs index dd72b26..3df602a 100644 --- a/src/ExplorerCore.cs +++ b/src/ExplorerCore.cs @@ -80,7 +80,7 @@ namespace UnityExplorer UIManager.Update(); } - #region LOGGING +#region LOGGING public static void Log(object message) => Log(message, LogType.Log, false); @@ -119,6 +119,6 @@ namespace UnityExplorer } } - #endregion +#endregion } } diff --git a/src/UI/UIManager.cs b/src/UI/UIManager.cs index 0b5dccf..f8d1db2 100644 --- a/src/UI/UIManager.cs +++ b/src/UI/UIManager.cs @@ -83,6 +83,9 @@ namespace UnityExplorer.UI if (!ShowMenu) return; + if (InputManager.GetKeyDown(ConfigManager.Force_Unlock_Keybind.Value)) + CursorUnlocker.Unlock = !CursorUnlocker.Unlock; + UIBehaviourModel.UpdateInstances(); if (EventSystem.current != EventSys)