diff --git a/src/CppExplorer.cs b/src/CppExplorer.cs
index e69e20d..a6694ad 100644
--- a/src/CppExplorer.cs
+++ b/src/CppExplorer.cs
@@ -13,7 +13,7 @@ namespace Explorer
public class CppExplorer : MelonMod
{
public const string NAME = "CppExplorer";
- public const string VERSION = "1.6.8";
+ public const string VERSION = "1.6.9";
public const string AUTHOR = "Sinai";
public const string GUID = "com.sinai.cppexplorer";
@@ -24,51 +24,30 @@ namespace Explorer
get => m_showMenu;
set => SetShowMenu(value);
}
- private static bool m_showMenu;
-
- public static bool ForceUnlockMouse
- {
- get => m_forceUnlock;
- set => SetForceUnlock(value);
- }
- private static bool m_forceUnlock;
- private static CursorLockMode m_lastLockMode;
- private static bool m_lastVisibleState;
- private static bool m_currentlySettingCursor = false;
-
- public static bool ShouldForceMouse => ShowMenu && ForceUnlockMouse;
+ public static bool m_showMenu;
private static void SetShowMenu(bool show)
{
m_showMenu = show;
- UpdateCursorControl();
- }
-
- private static void SetForceUnlock(bool unlock)
- {
- m_forceUnlock = unlock;
- UpdateCursorControl();
+ CursorControl.UpdateCursorControl();
}
public override void OnApplicationStart()
{
Instance = this;
+ // First, load config
ModConfig.OnLoad();
+ // Setup InputHelper class (UnityEngine.Input)
InputHelper.Init();
+ // Create CppExplorer modules
new MainMenu();
new WindowManager();
- // Get current cursor state and enable cursor
- m_lastLockMode = Cursor.lockState;
- m_lastVisibleState = Cursor.visible;
-
- // Enable ShowMenu and ForceUnlockMouse
- // (set m_showMenu directly to not call UpdateCursorState twice)
- m_showMenu = true;
- ForceUnlockMouse = true;
+ // Init cursor control
+ CursorControl.Init();
MelonLogger.Log($"CppExplorer {VERSION} initialized.");
}
@@ -89,15 +68,11 @@ namespace Explorer
if (ShowMenu)
{
- // Check Force-Unlock input
- if (InputHelper.GetKeyDown(KeyCode.LeftAlt))
- {
- ForceUnlockMouse = !ForceUnlockMouse;
- }
+ CursorControl.Update();
+ InspectUnderMouse.Update();
MainMenu.Instance.Update();
WindowManager.Instance.Update();
- InspectUnderMouse.Update();
}
}
@@ -105,93 +80,14 @@ namespace Explorer
{
if (!ShowMenu) return;
+ var origSkin = GUI.skin;
+ GUI.skin = UIStyles.WindowSkin;
+
MainMenu.Instance.OnGUI();
WindowManager.Instance.OnGUI();
InspectUnderMouse.OnGUI();
- }
- private static void UpdateCursorControl()
- {
- m_currentlySettingCursor = true;
- if (ShouldForceMouse)
- {
- Cursor.lockState = CursorLockMode.None;
- Cursor.visible = true;
- }
- else
- {
- Cursor.lockState = m_lastLockMode;
- Cursor.visible = m_lastVisibleState;
- }
- m_currentlySettingCursor = false;
- }
-
- // 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.
-
- [HarmonyPatch(typeof(Cursor), nameof(Cursor.lockState), MethodType.Setter)]
- public class Cursor_set_lockState
- {
- [HarmonyPrefix]
- public static void Prefix(ref CursorLockMode value)
- {
- if (!m_currentlySettingCursor)
- {
- m_lastLockMode = value;
-
- if (ShouldForceMouse)
- {
- value = CursorLockMode.None;
- }
- }
- }
- }
-
- [HarmonyPatch(typeof(Cursor), nameof(Cursor.visible), MethodType.Setter)]
- public class Cursor_set_visible
- {
- [HarmonyPrefix]
- public static void Prefix(ref bool value)
- {
- if (!m_currentlySettingCursor)
- {
- m_lastVisibleState = value;
-
- if (ShouldForceMouse)
- {
- value = true;
- }
- }
- }
- }
-
- // Make it appear as though UnlockMouse is disabled to the rest of the application.
-
- [HarmonyPatch(typeof(Cursor), nameof(Cursor.lockState), MethodType.Getter)]
- public class Cursor_get_lockState
- {
- [HarmonyPostfix]
- public static void Postfix(ref CursorLockMode __result)
- {
- if (ShouldForceMouse)
- {
- __result = m_lastLockMode;
- }
- }
- }
-
- [HarmonyPatch(typeof(Cursor), nameof(Cursor.visible), MethodType.Getter)]
- public class Cursor_get_visible
- {
- [HarmonyPostfix]
- public static void Postfix(ref bool __result)
- {
- if (ShouldForceMouse)
- {
- __result = m_lastVisibleState;
- }
- }
+ GUI.skin = origSkin;
}
}
}
diff --git a/src/CppExplorer.csproj b/src/CppExplorer.csproj
index 6a568db..467c78e 100644
--- a/src/CppExplorer.csproj
+++ b/src/CppExplorer.csproj
@@ -93,6 +93,7 @@
+
@@ -101,24 +102,24 @@
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Helpers/InputHelper.cs b/src/Helpers/InputHelper.cs
index c38e43c..ca0ebef 100644
--- a/src/Helpers/InputHelper.cs
+++ b/src/Helpers/InputHelper.cs
@@ -88,7 +88,8 @@ namespace Explorer
{
MelonLogger.Log("UnityEngine.Input is null, trying to load manually....");
- if ((TryLoad("UnityEngine.InputLegacyModule.dll") || TryLoad("UnityEngine.CoreModule.dll")) && Input != null)
+ if ((ReflectionHelpers.LoadModule("UnityEngine.InputLegacyModule.dll") || ReflectionHelpers.LoadModule("UnityEngine.CoreModule.dll"))
+ && Input != null)
{
MelonLogger.Log("Ok!");
return true;
@@ -98,23 +99,6 @@ namespace Explorer
MelonLogger.Log("Could not load Input module!");
return false;
}
-
- bool TryLoad(string module)
- {
- var path = $@"MelonLoader\Managed\{module}";
- if (!File.Exists(path)) return false;
-
- try
- {
- Assembly.Load(File.ReadAllBytes(path));
- return true;
- }
- catch (Exception e)
- {
- MelonLogger.Log(e.GetType() + ", " + e.Message);
- return false;
- }
- }
}
}
}
diff --git a/src/Helpers/ReflectionHelpers.cs b/src/Helpers/ReflectionHelpers.cs
index afc24c5..80bd93b 100644
--- a/src/Helpers/ReflectionHelpers.cs
+++ b/src/Helpers/ReflectionHelpers.cs
@@ -3,6 +3,8 @@ using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
+using System.IO;
+using MelonLoader;
using UnhollowerBaseLib;
using UnhollowerRuntimeLib;
using UnityEngine;
@@ -122,6 +124,23 @@ namespace Explorer
return list.ToArray();
}
+ public static bool LoadModule(string module)
+ {
+ var path = $@"MelonLoader\Managed\{module}";
+ if (!File.Exists(path)) return false;
+
+ try
+ {
+ Assembly.Load(File.ReadAllBytes(path));
+ return true;
+ }
+ catch (Exception e)
+ {
+ MelonLogger.Log(e.GetType() + ", " + e.Message);
+ return false;
+ }
+ }
+
public static string ExceptionToString(Exception e)
{
if (IsFailedGeneric(e))
diff --git a/src/Menu/CursorControl.cs b/src/Menu/CursorControl.cs
new file mode 100644
index 0000000..9f255aa
--- /dev/null
+++ b/src/Menu/CursorControl.cs
@@ -0,0 +1,238 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using UnityEngine;
+using Harmony;
+using MelonLoader;
+using System.Reflection;
+
+namespace Explorer
+{
+ public class CursorControl
+ {
+ public static bool ForceUnlockMouse
+ {
+ get => m_forceUnlock;
+ set => SetForceUnlock(value);
+ }
+ private static bool m_forceUnlock;
+ private static CursorLockMode m_lastLockMode;
+ private static bool m_lastVisibleState;
+ private static bool m_currentlySettingCursor = false;
+
+ public static bool ShouldForceMouse => CppExplorer.ShowMenu && ForceUnlockMouse;
+
+ public static void Init()
+ {
+ try
+ {
+ // Check if Cursor class is loaded
+ if (ReflectionHelpers.GetTypeByName("UnityEngine.Cursor") == null)
+ {
+ MelonLogger.Log("Trying to manually load Cursor module...");
+
+ if (ReflectionHelpers.LoadModule("UnityEngine.CoreModule"))
+ {
+ MelonLogger.Log("Ok!");
+ }
+ else
+ {
+ throw new Exception("Could not load UnityEngine.Cursor module!");
+ }
+ }
+
+ // Get current cursor state and enable cursor
+ m_lastLockMode = Cursor.lockState;
+ m_lastVisibleState = Cursor.visible;
+
+ TryPatch("lockState", new HarmonyMethod(typeof(CursorControl).GetMethod(nameof(Prefix_set_lockState))), false, false);
+ TryPatch("visible", new HarmonyMethod(typeof(CursorControl).GetMethod(nameof(Prefix_set_visible))), false, false);
+
+ TryPatch("lockState", new HarmonyMethod(typeof(CursorControl).GetMethod(nameof(Postfix_get_lockState))), true, true);
+ TryPatch("visible", new HarmonyMethod(typeof(CursorControl).GetMethod(nameof(Postfix_get_visible))), true, true);
+ }
+ catch (Exception e)
+ {
+ MelonLogger.Log($"Exception on CursorControl.Init! {e.GetType()}, {e.Message}");
+ }
+
+ // Enable ShowMenu and ForceUnlockMouse
+ // (set m_showMenu directly to not call UpdateCursorState twice)
+ CppExplorer.m_showMenu = true;
+ ForceUnlockMouse = true;
+ }
+
+ private static void TryPatch(string property, HarmonyMethod patch, bool getter = true, bool postfix = false)
+ {
+ // Setup Harmony Patches
+ try
+ {
+ var harmony = CppExplorer.Instance.harmonyInstance;
+
+ var prop = typeof(Cursor).GetProperty(property);
+
+ harmony.Patch(getter ? prop.GetGetMethod() : prop.GetSetMethod(),
+ postfix ? null : patch,
+ postfix ? patch : null);
+ }
+ catch (Exception e)
+ {
+ MelonLogger.Log($"[NON-FATAL] Couldn't patch a method: {e.Message}");
+ }
+ }
+
+ private static void SetForceUnlock(bool unlock)
+ {
+ m_forceUnlock = unlock;
+ UpdateCursorControl();
+ }
+
+ public static void Update()
+ {
+ // Check Force-Unlock input
+ if (InputHelper.GetKeyDown(KeyCode.LeftAlt))
+ {
+ ForceUnlockMouse = !ForceUnlockMouse;
+ }
+ }
+
+ 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)
+ {
+ MelonLogger.Log($"Exception setting Cursor state: {e.GetType()}, {e.Message}");
+ }
+ }
+
+ // 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;
+ }
+ }
+ }
+
+ [HarmonyPrefix]
+ public static void Postfix_get_lockState(ref CursorLockMode __result)
+ {
+ if (ShouldForceMouse)
+ {
+ __result = m_lastLockMode;
+ }
+ }
+
+ [HarmonyPrefix]
+ public static void Postfix_get_visible(ref bool __result)
+ {
+ if (ShouldForceMouse)
+ {
+ __result = m_lastVisibleState;
+ }
+ }
+
+ //[HarmonyPatch(typeof(Cursor), nameof(Cursor.lockState), MethodType.Setter)]
+ //public class Cursor_set_lockState
+ //{
+ // [HarmonyPrefix]
+ // public static void Prefix(ref CursorLockMode value)
+ // {
+ // if (!m_currentlySettingCursor)
+ // {
+ // m_lastLockMode = value;
+
+ // if (ShouldForceMouse)
+ // {
+ // value = CursorLockMode.None;
+ // }
+ // }
+ // }
+ //}
+
+ //[HarmonyPatch(typeof(Cursor), nameof(Cursor.visible), MethodType.Setter)]
+ //public class Cursor_set_visible
+ //{
+ // [HarmonyPrefix]
+ // public static void Prefix(ref bool value)
+ // {
+ // if (!m_currentlySettingCursor)
+ // {
+ // m_lastVisibleState = value;
+
+ // if (ShouldForceMouse)
+ // {
+ // value = true;
+ // }
+ // }
+ // }
+ //}
+
+ //// Make it appear as though UnlockMouse is disabled to the rest of the application.
+
+ //[HarmonyPatch(typeof(Cursor), nameof(Cursor.lockState), MethodType.Getter)]
+ //public class Cursor_get_lockState
+ //{
+ // [HarmonyPostfix]
+ // public static void Postfix(ref CursorLockMode __result)
+ // {
+ // if (ShouldForceMouse)
+ // {
+ // __result = m_lastLockMode;
+ // }
+ // }
+ //}
+
+ //[HarmonyPatch(typeof(Cursor), nameof(Cursor.visible), MethodType.Getter)]
+ //public class Cursor_get_visible
+ //{
+ // [HarmonyPostfix]
+ // public static void Postfix(ref bool __result)
+ // {
+ // if (ShouldForceMouse)
+ // {
+ // __result = m_lastVisibleState;
+ // }
+ // }
+ //}
+ }
+}
diff --git a/src/MainMenu/InspectUnderMouse.cs b/src/Menu/MainMenu/InspectUnderMouse.cs
similarity index 100%
rename from src/MainMenu/InspectUnderMouse.cs
rename to src/Menu/MainMenu/InspectUnderMouse.cs
diff --git a/src/MainMenu/MainMenu.cs b/src/Menu/MainMenu/MainMenu.cs
similarity index 92%
rename from src/MainMenu/MainMenu.cs
rename to src/Menu/MainMenu/MainMenu.cs
index 5784392..447f436 100644
--- a/src/MainMenu/MainMenu.cs
+++ b/src/Menu/MainMenu/MainMenu.cs
@@ -52,12 +52,7 @@ namespace Explorer
public void OnGUI()
{
- var origSkin = GUI.skin;
- GUI.skin = UIStyles.WindowSkin;
-
MainRect = GUI.Window(MainWindowID, MainRect, (GUI.WindowFunction)MainWindow, CppExplorer.NAME);
-
- GUI.skin = origSkin;
}
private void MainWindow(int id)
@@ -108,9 +103,9 @@ namespace Explorer
GUI.color = Color.white;
InspectUnderMouse.EnableInspect = GUILayout.Toggle(InspectUnderMouse.EnableInspect, "Inspect Under Mouse (Shift + RMB)", null);
- bool mouseState = CppExplorer.ForceUnlockMouse;
+ bool mouseState = CursorControl.ForceUnlockMouse;
bool setMouse = GUILayout.Toggle(mouseState, "Force Unlock Mouse (Left Alt)", null);
- if (setMouse != mouseState) CppExplorer.ForceUnlockMouse = setMouse;
+ if (setMouse != mouseState) CursorControl.ForceUnlockMouse = setMouse;
WindowManager.TabView = GUILayout.Toggle(WindowManager.TabView, "Tab View", null);
GUILayout.EndHorizontal();
diff --git a/src/MainMenu/Pages/Console/REPL.cs b/src/Menu/MainMenu/Pages/Console/REPL.cs
similarity index 100%
rename from src/MainMenu/Pages/Console/REPL.cs
rename to src/Menu/MainMenu/Pages/Console/REPL.cs
diff --git a/src/MainMenu/Pages/Console/REPLHelper.cs b/src/Menu/MainMenu/Pages/Console/REPLHelper.cs
similarity index 100%
rename from src/MainMenu/Pages/Console/REPLHelper.cs
rename to src/Menu/MainMenu/Pages/Console/REPLHelper.cs
diff --git a/src/MainMenu/Pages/ConsolePage.cs b/src/Menu/MainMenu/Pages/ConsolePage.cs
similarity index 100%
rename from src/MainMenu/Pages/ConsolePage.cs
rename to src/Menu/MainMenu/Pages/ConsolePage.cs
diff --git a/src/MainMenu/Pages/ScenePage.cs b/src/Menu/MainMenu/Pages/ScenePage.cs
similarity index 100%
rename from src/MainMenu/Pages/ScenePage.cs
rename to src/Menu/MainMenu/Pages/ScenePage.cs
diff --git a/src/MainMenu/Pages/SearchPage.cs b/src/Menu/MainMenu/Pages/SearchPage.cs
similarity index 100%
rename from src/MainMenu/Pages/SearchPage.cs
rename to src/Menu/MainMenu/Pages/SearchPage.cs
diff --git a/src/MainMenu/Pages/WindowPage.cs b/src/Menu/MainMenu/Pages/WindowPage.cs
similarity index 100%
rename from src/MainMenu/Pages/WindowPage.cs
rename to src/Menu/MainMenu/Pages/WindowPage.cs
diff --git a/src/Helpers/UIStyles.cs b/src/Menu/UIStyles.cs
similarity index 100%
rename from src/Helpers/UIStyles.cs
rename to src/Menu/UIStyles.cs
diff --git a/src/Windows/GameObjectWindow.cs b/src/Menu/Windows/GameObjectWindow.cs
similarity index 100%
rename from src/Windows/GameObjectWindow.cs
rename to src/Menu/Windows/GameObjectWindow.cs
diff --git a/src/Windows/ReflectionWindow.cs b/src/Menu/Windows/ReflectionWindow.cs
similarity index 100%
rename from src/Windows/ReflectionWindow.cs
rename to src/Menu/Windows/ReflectionWindow.cs
diff --git a/src/Windows/ResizeDrag.cs b/src/Menu/Windows/ResizeDrag.cs
similarity index 100%
rename from src/Windows/ResizeDrag.cs
rename to src/Menu/Windows/ResizeDrag.cs
diff --git a/src/Windows/TabViewWindow.cs b/src/Menu/Windows/TabViewWindow.cs
similarity index 100%
rename from src/Windows/TabViewWindow.cs
rename to src/Menu/Windows/TabViewWindow.cs
diff --git a/src/Windows/UIWindow.cs b/src/Menu/Windows/UIWindow.cs
similarity index 85%
rename from src/Windows/UIWindow.cs
rename to src/Menu/Windows/UIWindow.cs
index 31d2af8..1e0ae55 100644
--- a/src/Windows/UIWindow.cs
+++ b/src/Menu/Windows/UIWindow.cs
@@ -49,15 +49,7 @@ namespace Explorer
public void OnGUI()
{
- if (CppExplorer.ShowMenu)
- {
- var origSkin = GUI.skin;
-
- GUI.skin = UIStyles.WindowSkin;
- m_rect = GUI.Window(windowID, m_rect, (GUI.WindowFunction)WindowFunction, Title);
-
- GUI.skin = origSkin;
- }
+ m_rect = GUI.Window(windowID, m_rect, (GUI.WindowFunction)WindowFunction, Title);
}
public void Header()
diff --git a/src/Windows/WindowManager.cs b/src/Menu/Windows/WindowManager.cs
similarity index 100%
rename from src/Windows/WindowManager.cs
rename to src/Menu/Windows/WindowManager.cs