2020-09-11 18:53:17 +10:00
|
|
|
|
using System;
|
2020-09-18 18:38:11 +10:00
|
|
|
|
using UnityEngine;
|
2020-11-03 20:59:13 +11:00
|
|
|
|
using UnityExplorer.Helpers;
|
2020-10-23 01:50:33 +11:00
|
|
|
|
using UnityEngine.EventSystems;
|
2020-11-03 20:59:13 +11:00
|
|
|
|
using UnityExplorer.Input;
|
2020-10-24 20:18:42 +11:00
|
|
|
|
using BF = System.Reflection.BindingFlags;
|
2020-11-08 21:04:41 +11:00
|
|
|
|
using UnityExplorer.Config;
|
2020-09-27 22:04:23 +10:00
|
|
|
|
#if ML
|
|
|
|
|
using Harmony;
|
|
|
|
|
#else
|
|
|
|
|
using HarmonyLib;
|
|
|
|
|
#endif
|
2020-09-11 18:53:17 +10:00
|
|
|
|
|
2020-11-03 20:59:13 +11:00
|
|
|
|
namespace UnityExplorer.UI
|
2020-09-11 18:53:17 +10:00
|
|
|
|
{
|
2020-10-08 06:15:42 +11:00
|
|
|
|
public class ForceUnlockCursor
|
2020-09-11 18:53:17 +10:00
|
|
|
|
{
|
2020-10-08 06:15:42 +11:00
|
|
|
|
public static bool Unlock
|
2020-09-11 18:53:17 +10:00
|
|
|
|
{
|
|
|
|
|
get => m_forceUnlock;
|
|
|
|
|
set => SetForceUnlock(value);
|
|
|
|
|
}
|
|
|
|
|
private static bool m_forceUnlock;
|
2020-10-08 06:15:42 +11:00
|
|
|
|
|
2020-10-23 01:50:33 +11:00
|
|
|
|
private static void SetForceUnlock(bool unlock)
|
|
|
|
|
{
|
|
|
|
|
m_forceUnlock = unlock;
|
|
|
|
|
UpdateCursorControl();
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-11 22:57:46 +11:00
|
|
|
|
public static bool ShouldForceMouse => ExplorerCore.ShowMenu && Unlock;
|
|
|
|
|
|
2020-09-11 18:53:17 +10:00
|
|
|
|
private static CursorLockMode m_lastLockMode;
|
|
|
|
|
private static bool m_lastVisibleState;
|
|
|
|
|
|
2020-10-11 22:57:46 +11:00
|
|
|
|
private static bool m_currentlySettingCursor = false;
|
2020-09-11 18:53:17 +10:00
|
|
|
|
|
2020-10-23 01:50:33 +11:00
|
|
|
|
private static Type CursorType
|
|
|
|
|
=> m_cursorType
|
2020-10-11 22:57:46 +11:00
|
|
|
|
?? (m_cursorType = ReflectionHelpers.GetTypeByName("UnityEngine.Cursor"));
|
2020-09-12 00:59:59 +10:00
|
|
|
|
private static Type m_cursorType;
|
|
|
|
|
|
2020-09-11 18:53:17 +10:00
|
|
|
|
public static void Init()
|
2020-11-08 21:04:41 +11:00
|
|
|
|
{
|
|
|
|
|
ModConfig.OnConfigChanged += ModConfig_OnConfigChanged;
|
|
|
|
|
|
|
|
|
|
SetupPatches();
|
|
|
|
|
|
|
|
|
|
Unlock = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal static void ModConfig_OnConfigChanged()
|
|
|
|
|
{
|
|
|
|
|
Unlock = ModConfig.Instance.Force_Unlock_Mouse;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void SetupPatches()
|
2020-09-11 18:53:17 +10:00
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
2020-09-12 00:59:59 +10:00
|
|
|
|
if (CursorType == null)
|
2020-09-11 18:53:17 +10:00
|
|
|
|
{
|
2020-10-11 22:57:46 +11:00
|
|
|
|
throw new Exception("Could not find Type 'UnityEngine.Cursor'!");
|
2020-09-11 18:53:17 +10:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Get current cursor state and enable cursor
|
2020-10-24 20:18:42 +11:00
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
//m_lastLockMode = Cursor.lockState;
|
|
|
|
|
m_lastLockMode = (CursorLockMode?)typeof(Cursor).GetProperty("lockState", BF.Public | BF.Static)?.GetValue(null, null)
|
|
|
|
|
?? CursorLockMode.None;
|
|
|
|
|
|
|
|
|
|
//m_lastVisibleState = Cursor.visible;
|
|
|
|
|
m_lastVisibleState = (bool?)typeof(Cursor).GetProperty("visible", BF.Public | BF.Static)?.GetValue(null, null)
|
|
|
|
|
?? false;
|
|
|
|
|
}
|
|
|
|
|
catch { }
|
2020-09-11 18:53:17 +10:00
|
|
|
|
|
2020-09-12 00:59:59 +10:00
|
|
|
|
// Setup Harmony Patches
|
2020-11-08 21:04:41 +11:00
|
|
|
|
TryPatch(typeof(Cursor),
|
|
|
|
|
"lockState",
|
|
|
|
|
new HarmonyMethod(typeof(ForceUnlockCursor).GetMethod(nameof(Prefix_set_lockState))),
|
|
|
|
|
true);
|
|
|
|
|
|
|
|
|
|
TryPatch(typeof(Cursor),
|
|
|
|
|
"visible",
|
|
|
|
|
new HarmonyMethod(typeof(ForceUnlockCursor).GetMethod(nameof(Prefix_set_visible))),
|
|
|
|
|
true);
|
2020-11-19 00:55:17 +11:00
|
|
|
|
|
|
|
|
|
#if BIE
|
|
|
|
|
#if CPP
|
|
|
|
|
// temporarily disabling this patch in BepInEx il2cpp as it's causing a crash in some games.
|
|
|
|
|
return;
|
|
|
|
|
#endif
|
|
|
|
|
#endif
|
|
|
|
|
TryPatch(typeof(EventSystem),
|
|
|
|
|
"current",
|
|
|
|
|
new HarmonyMethod(typeof(ForceUnlockCursor).GetMethod(nameof(Prefix_EventSystem_set_current))),
|
|
|
|
|
true);
|
2020-09-11 18:53:17 +10:00
|
|
|
|
}
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
{
|
2020-11-20 17:12:40 +11:00
|
|
|
|
ExplorerCore.Log($"Exception on ForceUnlockCursor.Init! {e.GetType()}, {e.Message}");
|
2020-09-11 18:53:17 +10:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-23 01:50:33 +11:00
|
|
|
|
private static void TryPatch(Type type, string property, HarmonyMethod patch, bool setter)
|
2020-09-11 18:53:17 +10:00
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
2020-10-28 20:52:40 +11:00
|
|
|
|
var harmony =
|
2020-09-27 22:04:23 +10:00
|
|
|
|
#if ML
|
2020-09-29 05:40:06 +10:00
|
|
|
|
ExplorerMelonMod.Instance.harmonyInstance;
|
2020-09-27 22:04:23 +10:00
|
|
|
|
#else
|
2020-09-29 05:40:06 +10:00
|
|
|
|
ExplorerBepInPlugin.HarmonyInstance;
|
2020-09-27 22:04:23 +10:00
|
|
|
|
#endif
|
|
|
|
|
|
2020-10-28 06:39:26 +11:00
|
|
|
|
System.Reflection.PropertyInfo prop = type.GetProperty(property);
|
2020-09-11 18:53:17 +10:00
|
|
|
|
|
2020-11-08 21:04:41 +11:00
|
|
|
|
if (setter) // setter is prefix
|
2020-09-12 00:59:59 +10:00
|
|
|
|
{
|
2020-10-08 06:15:42 +11:00
|
|
|
|
harmony.Patch(prop.GetSetMethod(), prefix: patch);
|
2020-09-12 00:59:59 +10:00
|
|
|
|
}
|
2020-11-08 21:04:41 +11:00
|
|
|
|
else // getter is postfix
|
2020-09-12 00:59:59 +10:00
|
|
|
|
{
|
2020-10-08 06:15:42 +11:00
|
|
|
|
harmony.Patch(prop.GetGetMethod(), postfix: patch);
|
2020-09-12 00:59:59 +10:00
|
|
|
|
}
|
2020-09-11 18:53:17 +10:00
|
|
|
|
}
|
2020-11-19 00:55:17 +11:00
|
|
|
|
catch (Exception e)
|
2020-09-11 18:53:17 +10:00
|
|
|
|
{
|
2020-11-19 00:55:17 +11:00
|
|
|
|
string suf = setter ? "set_" : "get_";
|
|
|
|
|
ExplorerCore.Log($"Unable to patch {type.Name}.{suf}{property}: {e.Message}");
|
2020-09-11 18:53:17 +10:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void UpdateCursorControl()
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
m_currentlySettingCursor = true;
|
|
|
|
|
if (ShouldForceMouse)
|
|
|
|
|
{
|
|
|
|
|
Cursor.lockState = CursorLockMode.None;
|
|
|
|
|
Cursor.visible = true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Cursor.lockState = m_lastLockMode;
|
|
|
|
|
Cursor.visible = m_lastVisibleState;
|
|
|
|
|
}
|
|
|
|
|
m_currentlySettingCursor = false;
|
|
|
|
|
}
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
{
|
2020-09-27 22:04:23 +10:00
|
|
|
|
ExplorerCore.Log($"Exception setting Cursor state: {e.GetType()}, {e.Message}");
|
2020-09-11 18:53:17 +10:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-08 21:04:41 +11:00
|
|
|
|
// Event system overrides
|
2020-10-23 01:50:33 +11:00
|
|
|
|
|
|
|
|
|
private static bool m_settingEventSystem;
|
|
|
|
|
private static EventSystem m_lastEventSystem;
|
|
|
|
|
private static BaseInputModule m_lastInputModule;
|
|
|
|
|
|
|
|
|
|
public static void SetEventSystem()
|
|
|
|
|
{
|
2020-11-20 17:12:40 +11:00
|
|
|
|
if (InputManager.CurrentType == InputType.InputSystem)
|
|
|
|
|
return;
|
|
|
|
|
|
2020-10-23 01:50:33 +11:00
|
|
|
|
m_settingEventSystem = true;
|
2020-11-20 17:12:40 +11:00
|
|
|
|
EventSystem.current = UIManager.EventSys;
|
|
|
|
|
InputManager.ActivateUIModule();
|
2020-10-23 01:50:33 +11:00
|
|
|
|
m_settingEventSystem = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void ReleaseEventSystem()
|
|
|
|
|
{
|
2020-11-20 17:12:40 +11:00
|
|
|
|
if (InputManager.CurrentType == InputType.InputSystem)
|
|
|
|
|
return;
|
|
|
|
|
|
2020-10-23 01:50:33 +11:00
|
|
|
|
if (m_lastEventSystem)
|
|
|
|
|
{
|
|
|
|
|
m_settingEventSystem = true;
|
|
|
|
|
EventSystem.current = m_lastEventSystem;
|
|
|
|
|
m_lastInputModule?.ActivateModule();
|
|
|
|
|
m_settingEventSystem = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[HarmonyPrefix]
|
|
|
|
|
public static void Prefix_EventSystem_set_current(ref EventSystem value)
|
|
|
|
|
{
|
|
|
|
|
if (!m_settingEventSystem)
|
|
|
|
|
{
|
|
|
|
|
m_lastEventSystem = value;
|
|
|
|
|
m_lastInputModule = value?.currentInputModule;
|
|
|
|
|
|
|
|
|
|
if (ExplorerCore.ShowMenu)
|
|
|
|
|
{
|
|
|
|
|
value = UIManager.EventSys;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-11 18:53:17 +10:00
|
|
|
|
// Force mouse to stay unlocked and visible while UnlockMouse and ShowMenu are true.
|
|
|
|
|
// Also keep track of when anything else tries to set Cursor state, this will be the
|
|
|
|
|
// value that we set back to when we close the menu or disable force-unlock.
|
|
|
|
|
|
|
|
|
|
[HarmonyPrefix]
|
|
|
|
|
public static void Prefix_set_lockState(ref CursorLockMode value)
|
|
|
|
|
{
|
|
|
|
|
if (!m_currentlySettingCursor)
|
|
|
|
|
{
|
|
|
|
|
m_lastLockMode = value;
|
|
|
|
|
|
|
|
|
|
if (ShouldForceMouse)
|
|
|
|
|
{
|
|
|
|
|
value = CursorLockMode.None;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[HarmonyPrefix]
|
|
|
|
|
public static void Prefix_set_visible(ref bool value)
|
|
|
|
|
{
|
|
|
|
|
if (!m_currentlySettingCursor)
|
|
|
|
|
{
|
|
|
|
|
m_lastVisibleState = value;
|
|
|
|
|
|
|
|
|
|
if (ShouldForceMouse)
|
|
|
|
|
{
|
|
|
|
|
value = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|