From 4c09f9bd577a3ceba1540a00bc3e4db0721fbb7b Mon Sep 17 00:00:00 2001 From: NotAKidoS <37721153+NotAKidOnSteam@users.noreply.github.com> Date: Thu, 3 Aug 2023 00:05:45 -0500 Subject: [PATCH] [DesktopVRSwitch] Minor changes --- DesktopVRSwitch/DesktopVRSwitch.csproj | 11 +- DesktopVRSwitch/HarmonyPatches.cs | 27 +- DesktopVRSwitch/Integrations/BTKUIAddon.cs | 64 +++++ DesktopVRSwitch/Main.cs | 31 ++- DesktopVRSwitch/ModSettings.cs | 20 ++ .../Patches/ReferenceCameraPatch.cs | 18 +- DesktopVRSwitch/VRModeSwitchManager.cs | 232 ++++++++---------- .../CVRGestureRecognizerTracker.cs | 6 +- .../VRModeTrackers/CVRInputManagerTracker.cs | 6 +- .../VRModeTrackers/CVRPickupObjectTracker.cs | 4 +- .../VRModeTrackers/CVRWorldTracker.cs | 2 +- .../CVR_InteractableManagerTracker.cs | 6 +- .../VRModeTrackers/CVR_MenuManagerTracker.cs | 8 +- .../CameraFacingObjectTracker.cs | 5 +- .../VRModeTrackers/CheckVRTracker.cs | 4 +- .../VRModeTrackers/CohtmlHudTracker.cs | 4 +- .../VRModeTrackers/HudOperationsTracker.cs | 6 +- .../VRModeTrackers/IKSystemTracker.cs | 14 +- .../VRModeTrackers/MetaPortTracker.cs | 8 +- .../VRModeTrackers/MovementSystemTracker.cs | 8 +- .../VRModeTrackers/PlayerSetupTracker.cs | 6 +- .../VRModeTrackers/PortableCameraTracker.cs | 2 +- .../VRModeTrackers/VRModeTracker.cs | 4 +- .../VRModeTrackers/ViewManagerTracker.cs | 2 +- DesktopVRSwitch/XRHandler.cs | 66 +++++ 25 files changed, 359 insertions(+), 205 deletions(-) create mode 100644 DesktopVRSwitch/Integrations/BTKUIAddon.cs create mode 100644 DesktopVRSwitch/ModSettings.cs create mode 100644 DesktopVRSwitch/XRHandler.cs diff --git a/DesktopVRSwitch/DesktopVRSwitch.csproj b/DesktopVRSwitch/DesktopVRSwitch.csproj index e94f9dc..4463620 100644 --- a/DesktopVRSwitch/DesktopVRSwitch.csproj +++ b/DesktopVRSwitch/DesktopVRSwitch.csproj @@ -1,2 +1,11 @@ - + + + + + $(MsBuildThisFileDirectory)\..\.ManagedLibs\BTKUILib.dll + False + + + + diff --git a/DesktopVRSwitch/HarmonyPatches.cs b/DesktopVRSwitch/HarmonyPatches.cs index 7dc00bb..7c61cdb 100644 --- a/DesktopVRSwitch/HarmonyPatches.cs +++ b/DesktopVRSwitch/HarmonyPatches.cs @@ -3,6 +3,8 @@ using ABI_RC.Core.Savior; using ABI_RC.Core.Util.Object_Behaviour; using ABI_RC.Systems.IK; using ABI_RC.Systems.IK.TrackingModules; +using cohtml; +using cohtml.Net; using HarmonyLib; using NAK.DesktopVRSwitch.Patches; using NAK.DesktopVRSwitch.VRModeTrackers; @@ -117,13 +119,36 @@ internal class CVRPickupObjectPatches } } +internal class CohtmlUISystemPatches +{ + [HarmonyPrefix] + [HarmonyPatch(typeof(UISystem), nameof(UISystem.RegisterGamepad))] + [HarmonyPatch(typeof(UISystem), nameof(UISystem.UnregisterGamepad))] + [HarmonyPatch(typeof(UISystem), nameof(UISystem.UpdateGamepadState))] + private static bool Prefix_UISystem_FuckOff() + { + /** + GameFace Version 1.34.0.4 – released 10 Nov 2022 + Fixed a crash when registering and unregistering gamepads + Fix Fixed setting a gamepad object when creating GamepadEvent from JavaScript + Fix Fixed a crash when unregistering a gamepad twice + Fix Fixed a GamepadEvent related crash during garbage collector tracing + + it is not fixed you fucking piece of shit + **/ + + // dont + return false; + } +} + internal class SteamVRBehaviourPatches { [HarmonyPrefix] [HarmonyPatch(typeof(SteamVR_Behaviour), nameof(SteamVR_Behaviour.OnQuit))] private static bool Prefix_SteamVR_Behaviour_OnQuit() { - if (!DesktopVRSwitch.EntrySwitchToDesktopOnExit.Value) + if (!ModSettings.EntrySwitchToDesktopOnExit.Value) return true; // If we don't switch fast enough, SteamVR will force close. diff --git a/DesktopVRSwitch/Integrations/BTKUIAddon.cs b/DesktopVRSwitch/Integrations/BTKUIAddon.cs new file mode 100644 index 0000000..c19e2b3 --- /dev/null +++ b/DesktopVRSwitch/Integrations/BTKUIAddon.cs @@ -0,0 +1,64 @@ +using BTKUILib; +using BTKUILib.UIObjects; +using System.Runtime.CompilerServices; +using ABI_RC.Core.Base; + +namespace NAK.DesktopVRSwitch.Integrations; + +public static class BTKUIAddon +{ + #region Initialization + + [MethodImpl(MethodImplOptions.NoInlining)] + public static void Initialize() + { + // Add mod to the Misc Menu + Page miscPage = QuickMenuAPI.MiscTabPage; + Category vrSwitchMiscCategory = miscPage.AddCategory(ModSettings.SettingsCategory); + + vrSwitchMiscCategory.AddButton("Switch VR Mode", "", "Switch to Desktop/VR.").OnPress += + () => + { + QuickMenuAPI.ShowConfirm( + title: "Switch VR Mode", + content: "Are you sure you want to switch to Desktop/VR?", + onYes: () => VRModeSwitchManager.Instance.AttemptSwitch() + ); + }; + + SetupSwitchConfigurationPage(ref vrSwitchMiscCategory); + } + + #endregion + + #region Pages Setup + + private static void SetupSwitchConfigurationPage(ref Category parentCategory) + { + Page vrSwitchPage = parentCategory.AddPage("DesktopVRSwitch Settings", "", "Configure the settings for DesktopVRSwitch.", ModSettings.SettingsCategory); + vrSwitchPage.MenuTitle = "DesktopVRSwitch Settings"; + Category vrSwitchCategory = vrSwitchPage.AddCategory(vrSwitchPage.MenuTitle); + + AddMelonToggle(ref vrSwitchCategory, ModSettings.EntryEnterCalibrationOnSwitch); + + AddMelonToggle(ref vrSwitchCategory, ModSettings.EntryUseTransitionOnSwitch); + + AddMelonToggle(ref vrSwitchCategory, ModSettings.EntrySwitchToDesktopOnExit); + } + + #endregion + + #region Melon Pref Helpers + + private static void AddMelonToggle(ref Category category, MelonLoader.MelonPreferences_Entry entry) + { + category.AddToggle(entry.DisplayName, entry.Description, entry.Value).OnValueUpdated += b => entry.Value = b; + } + + private static void AddMelonSlider(ref Page page, MelonLoader.MelonPreferences_Entry entry, float min, float max, int decimalPlaces = 2) + { + page.AddSlider(entry.DisplayName, entry.Description, entry.Value, min, max, decimalPlaces).OnValueUpdated += f => entry.Value = f; + } + + #endregion +} \ No newline at end of file diff --git a/DesktopVRSwitch/Main.cs b/DesktopVRSwitch/Main.cs index f50922d..93d54b0 100644 --- a/DesktopVRSwitch/Main.cs +++ b/DesktopVRSwitch/Main.cs @@ -8,22 +8,7 @@ namespace NAK.DesktopVRSwitch; public class DesktopVRSwitch : MelonMod { internal static MelonLogger.Instance Logger; - - public static readonly MelonPreferences_Category Category = - MelonPreferences.CreateCategory(nameof(DesktopVRSwitch)); - - public static readonly MelonPreferences_Entry EntryEnterCalibrationOnSwitch = - Category.CreateEntry("Enter Calibration on Switch", true, description: "Should you automatically be placed into calibration after switch if FBT is available? Overridden by Save Calibration IK setting."); - - public static readonly MelonPreferences_Entry EntryUseTransitionOnSwitch = - Category.CreateEntry("Use Transition on Switch", true, description: "Should the world transition play on VRMode switch?"); - - //public static readonly MelonPreferences_Entry EntryRenderVRGameView = - // Category.CreateEntry("Render VR Game View", true, description: "Should the VR view be displayed in the game window after VRMode switch?"); - - public static readonly MelonPreferences_Entry EntrySwitchToDesktopOnExit = - Category.CreateEntry("Switch to Desktop on SteamVR Exit", false, description: "Should the game switch to Desktop when SteamVR quits?"); - + public override void OnInitializeMelon() { Logger = LoggerInstance; @@ -40,9 +25,14 @@ public class DesktopVRSwitch : MelonMod ApplyPatches(typeof(HarmonyPatches.IKSystemPatches)); // post processing fixes ApplyPatches(typeof(HarmonyPatches.CVRWorldPatches)); + + // fuck you + ApplyPatches(typeof(HarmonyPatches.CohtmlUISystemPatches)); // prevent steamvr behaviour from closing game ApplyPatches(typeof(HarmonyPatches.SteamVRBehaviourPatches)); + + InitializeIntegration("BTKUILib", Integrations.BTKUIAddon.Initialize); } public override void OnUpdate() @@ -83,6 +73,15 @@ public class DesktopVRSwitch : MelonMod // CVRWorld tracker - Must come after PlayerSetupTracker VRModeSwitchManager.RegisterVRModeTracker(new CVRWorldTracker()); } + + private static void InitializeIntegration(string modName, Action integrationAction) + { + if (RegisteredMelons.All(it => it.Info.Name != modName)) + return; + + Logger.Msg($"Initializing {modName} integration."); + integrationAction.Invoke(); + } private void ApplyPatches(Type type) { diff --git a/DesktopVRSwitch/ModSettings.cs b/DesktopVRSwitch/ModSettings.cs new file mode 100644 index 0000000..15fa80f --- /dev/null +++ b/DesktopVRSwitch/ModSettings.cs @@ -0,0 +1,20 @@ +using MelonLoader; + +namespace NAK.DesktopVRSwitch; + +public static class ModSettings +{ + internal const string SettingsCategory = nameof(DesktopVRSwitch); + + public static readonly MelonPreferences_Category Category = + MelonPreferences.CreateCategory(SettingsCategory); + + public static readonly MelonPreferences_Entry EntryEnterCalibrationOnSwitch = + Category.CreateEntry("Enter Calibration on Switch", true, description: "Should you automatically be placed into calibration after switch if FBT is available? Overridden by Save Calibration IK setting."); + + public static readonly MelonPreferences_Entry EntryUseTransitionOnSwitch = + Category.CreateEntry("Use Transition on Switch", true, description: "Should the world transition play on VRMode switch?"); + + public static readonly MelonPreferences_Entry EntrySwitchToDesktopOnExit = + Category.CreateEntry("Switch to Desktop on SteamVR Exit", false, description: "Should the game switch to Desktop when SteamVR quits?"); +} \ No newline at end of file diff --git a/DesktopVRSwitch/Patches/ReferenceCameraPatch.cs b/DesktopVRSwitch/Patches/ReferenceCameraPatch.cs index 0b4d584..2bcb39e 100644 --- a/DesktopVRSwitch/Patches/ReferenceCameraPatch.cs +++ b/DesktopVRSwitch/Patches/ReferenceCameraPatch.cs @@ -9,7 +9,7 @@ using UnityEngine.Rendering.PostProcessing; namespace NAK.DesktopVRSwitch.Patches; -internal class ReferenceCameraPatch +internal static class ReferenceCameraPatch { public static void OnWorldLoad() { @@ -31,13 +31,15 @@ internal class ReferenceCameraPatch inactiveCam.depthTextureMode = activeCam.depthTextureMode; // We cant copy this because we set it to 0 with ThirdPerson - inactiveCam.cullingMask &= -32769; - inactiveCam.cullingMask |= 256; - inactiveCam.cullingMask |= 512; - inactiveCam.cullingMask |= 32; - inactiveCam.cullingMask &= -4097; - inactiveCam.cullingMask |= 1024; - inactiveCam.cullingMask |= 8192; + var cullingMask = inactiveCam.cullingMask; + cullingMask &= -32769; + cullingMask |= 256; + cullingMask |= 512; + cullingMask |= 32; + cullingMask &= -4097; + cullingMask |= 1024; + cullingMask |= 8192; + inactiveCam.cullingMask = cullingMask; // Copy post processing if added PostProcessLayer ppLayerActiveCam = activeCam.GetComponent(); diff --git a/DesktopVRSwitch/VRModeSwitchManager.cs b/DesktopVRSwitch/VRModeSwitchManager.cs index ed1c03b..a9983ee 100644 --- a/DesktopVRSwitch/VRModeSwitchManager.cs +++ b/DesktopVRSwitch/VRModeSwitchManager.cs @@ -2,47 +2,22 @@ using NAK.DesktopVRSwitch.VRModeTrackers; using System.Collections; using UnityEngine; -using UnityEngine.Events; -using UnityEngine.XR; using UnityEngine.XR.Management; -using Valve.VR; - -/** - - I am unsure about this observer approach as only a few things need OnPre and OnFailed switch. - Those wouldn't be needed if I can start OpenVR before all that anyways. - - Or... I just start OpenVR and see if it worked. OnPreSwitch would only be needed by menus & transition. - - I think I should just use Unity Events as they would allow easier mod support. Subscribe to what you need. - -**/ namespace NAK.DesktopVRSwitch; public class VRModeSwitchManager : MonoBehaviour { + #region Static + public static VRModeSwitchManager Instance { get; private set; } + + public static void RegisterVRModeTracker(VRModeTracker observer) => observer.TrackerInit(); + public static void UnregisterVRModeTracker(VRModeTracker observer) => observer.TrackerDestroy(); + + #endregion - // I don't think I *need* this. Only using cause I don't want stuff just existing. - private static readonly List _vrModeTrackers = new List(); - - public static event UnityAction OnPreVRModeSwitch; - public static event UnityAction OnPostVRModeSwitch; - public static event UnityAction OnFailVRModeSwitch; - private const string XRSETTINGS_DEVICE = "OpenVR"; - - public static void RegisterVRModeTracker(VRModeTracker observer) - { - _vrModeTrackers.Add(observer); - observer.TrackerInit(); - } - - public static void UnregisterVRModeTracker(VRModeTracker observer) - { - _vrModeTrackers.Remove(observer); - observer.TrackerDestroy(); - } + #region Variables // Settings public bool UseWorldTransition = true; @@ -50,6 +25,10 @@ public class VRModeSwitchManager : MonoBehaviour public bool SwitchInProgress { get; private set; } + #endregion + + #region Unity Methods + private void Awake() { if (Instance != null) @@ -60,125 +39,120 @@ public class VRModeSwitchManager : MonoBehaviour Instance = this; } - public void AttemptSwitch() - { - StartCoroutine(StartSwitchCoroutine()); - } + #endregion - private IEnumerator StartSwitchCoroutine() + #region Public Methods + + public static bool IsInXR() => XRGeneralSettings.Instance.Manager.activeLoader != null; + + public void AttemptSwitch() => StartCoroutine(StartSwitchInternal()); + + #endregion + + #region Private Methods + + private IEnumerator StartSwitchInternal() { - if (SwitchInProgress) - { + if (SwitchInProgress) yield break; - } + SwitchInProgress = true; yield return null; - - + if (UseWorldTransition) - { // start visual transition and wait for it to complete - WorldTransitionSystem.Instance.StartTransition(); - yield return new WaitForSeconds(WorldTransitionSystem.Instance.CurrentInLength); - } + yield return StartCoroutine(StartTransition()); - // Check if OpenVR is running bool isUsingVr = IsInXR(); InvokeOnPreSwitch(isUsingVr); - // Start switch - if (!isUsingVr) - yield return StartCoroutine(StartXR()); - else - StopXR(); - - // Check for updated VR mode - if (isUsingVr != IsInXR()) - { - // reload the local avatar - if (ReloadLocalAvatar) - { - Utils.ClearLocalAvatar(); - Utils.ReloadLocalAvatar(); - } - - InvokeOnPostSwitch(!isUsingVr); - } - else - { - InvokeOnFailedSwitch(!isUsingVr); - } + yield return StartCoroutine(XRAndReloadAvatar(!isUsingVr)); if (UseWorldTransition) - { // would be cool to have out length - WorldTransitionSystem.Instance.ContinueTransition(); - yield return new WaitForSeconds(WorldTransitionSystem.Instance.CurrentInLength); - } + yield return StartCoroutine(ContinueTransition()); SwitchInProgress = false; - yield break; + } + + private IEnumerator XRAndReloadAvatar(bool start) + { + yield return StartCoroutine(start ? XRHandler.StartXR() : XRHandler.StopXR()); + + bool isUsingVr = IsInXR(); + if (isUsingVr == start) + { + ReloadAvatar(); + InvokeOnPostSwitch(start); + } + else + { + InvokeOnFailedSwitch(start); + } + } + + private void ReloadAvatar() + { + if (!ReloadLocalAvatar) + return; + + Utils.ClearLocalAvatar(); + Utils.ReloadLocalAvatar(); } - private void SafeInvokeUnityEvent(UnityAction switchEvent, bool isUsingVr) + #endregion + + #region Transition Coroutines + + private IEnumerator StartTransition() + { + if (WorldTransitionSystem.Instance == null) yield break; + WorldTransitionSystem.Instance.StartTransition(); + yield return new WaitForSeconds(WorldTransitionSystem.Instance.CurrentInLength); + } + + private IEnumerator ContinueTransition() + { + if (WorldTransitionSystem.Instance == null) yield break; + WorldTransitionSystem.Instance.ContinueTransition(); + yield return new WaitForSeconds(WorldTransitionSystem.Instance.CurrentInLength); + } + + #endregion + + #region Event Handling + + public class VRModeEventArgs : EventArgs + { + public bool IsUsingVr { get; } + public Camera PlayerCamera { get; } + + public VRModeEventArgs(bool isUsingVr, Camera playerCamera) + { + IsUsingVr = isUsingVr; + PlayerCamera = playerCamera; + } + } + + public static event EventHandler OnPreVRModeSwitch; + public static event EventHandler OnPostVRModeSwitch; + public static event EventHandler OnFailVRModeSwitch; + + private void InvokeOnPreSwitch(bool isUsingVr) => SafeInvokeUnityEvent(OnPreVRModeSwitch, isUsingVr); + private void InvokeOnPostSwitch(bool isUsingVr) => SafeInvokeUnityEvent(OnPostVRModeSwitch, isUsingVr); + private void InvokeOnFailedSwitch(bool isUsingVr) => SafeInvokeUnityEvent(OnFailVRModeSwitch, isUsingVr); + + private void SafeInvokeUnityEvent(EventHandler switchEvent, bool isUsingVr) { try { - switchEvent.Invoke(isUsingVr); + var playerCamera = Utils.GetPlayerCameraObject(isUsingVr).GetComponent(); + switchEvent?.Invoke(this, new VRModeEventArgs(isUsingVr, playerCamera)); } catch (Exception e) { - Debug.Log($"Error in event handler: {e}"); + DesktopVRSwitch.Logger.Error($"Error in event handler: {e}"); } } - - private void InvokeOnPreSwitch(bool isUsingVr) - { - SafeInvokeUnityEvent(OnPreVRModeSwitch, isUsingVr); - } - - private void InvokeOnPostSwitch(bool isUsingVr) - { - SafeInvokeUnityEvent(OnPostVRModeSwitch, isUsingVr); - } - - private void InvokeOnFailedSwitch(bool isUsingVr) - { - SafeInvokeUnityEvent(OnFailVRModeSwitch, isUsingVr); - } - - public bool IsInXR() => XRGeneralSettings.Instance.Manager.activeLoader != null; - - private IEnumerator StartXR() - { - yield return null; // wait a frame before checking - yield return XRGeneralSettings.Instance.Manager.InitializeLoader(); - - if (XRGeneralSettings.Instance.Manager.activeLoader != null) - { - XRGeneralSettings.Instance.Manager.StartSubsystems(); - } - - yield return null; - yield break; - } - - private void StopXR() - { - if (!XRGeneralSettings.Instance.Manager.isInitializationComplete) - return; - - // Forces SteamVR to reinitialize SteamVR_Input next switch - SteamVR_ActionSet_Manager.DisableAllActionSets(); - SteamVR_Input.initialized = false; - - // Remove SteamVR behaviour & render - DestroyImmediate(SteamVR_Behaviour.instance.gameObject); - SteamVR.enabled = false; // disposes SteamVR - - // Disable UnityXR - XRGeneralSettings.Instance.Manager.StopSubsystems(); - XRGeneralSettings.Instance.Manager.DeinitializeLoader(); - - // We don't really need to wait a frame on Stop() - } + + #endregion } \ No newline at end of file diff --git a/DesktopVRSwitch/VRModeTrackers/CVRGestureRecognizerTracker.cs b/DesktopVRSwitch/VRModeTrackers/CVRGestureRecognizerTracker.cs index fa4dc6a..b094001 100644 --- a/DesktopVRSwitch/VRModeTrackers/CVRGestureRecognizerTracker.cs +++ b/DesktopVRSwitch/VRModeTrackers/CVRGestureRecognizerTracker.cs @@ -15,10 +15,10 @@ public class CVRGestureRecognizerTracker : VRModeTracker VRModeSwitchManager.OnPostVRModeSwitch -= OnPostSwitch; } - private void OnPostSwitch(bool intoVR) + private void OnPostSwitch(object sender, VRModeSwitchManager.VRModeEventArgs args) { DesktopVRSwitch.Logger.Msg("Updating CVRGestureRecognizer _camera to active camera."); - CVRGestureRecognizer.Instance._camera = Utils.GetPlayerCameraObject(intoVR).GetComponent(); + CVRGestureRecognizer.Instance._camera = args.PlayerCamera; } -} \ No newline at end of file +} diff --git a/DesktopVRSwitch/VRModeTrackers/CVRInputManagerTracker.cs b/DesktopVRSwitch/VRModeTrackers/CVRInputManagerTracker.cs index 1d70794..74cf766 100644 --- a/DesktopVRSwitch/VRModeTrackers/CVRInputManagerTracker.cs +++ b/DesktopVRSwitch/VRModeTrackers/CVRInputManagerTracker.cs @@ -16,14 +16,14 @@ public class CVRInputManagerTracker : VRModeTracker VRModeSwitchManager.OnPostVRModeSwitch -= OnPostSwitch; } - private void OnPostSwitch(bool intoVR) + private void OnPostSwitch(object sender, VRModeSwitchManager.VRModeEventArgs args) { DesktopVRSwitch.Logger.Msg("Resetting CVRInputManager inputs."); CVRInputManager.Instance.inputEnabled = true; // IM CRYING - CVRInputManager.Instance.reload = true; + //CVRInputManager.Instance.reload = true; //just in case CVRInputManager.Instance.textInputFocused = false; @@ -42,6 +42,6 @@ public class CVRInputManagerTracker : VRModeTracker CVRInputManager.Instance.AddInputModule(CVRInputManager._moduleXR = new CVRInputModule_XR()); //enable xr input or whatnot - CVRInputManager._moduleXR.InputEnabled = intoVR; + CVRInputManager._moduleXR.InputEnabled = args.IsUsingVr; } } \ No newline at end of file diff --git a/DesktopVRSwitch/VRModeTrackers/CVRPickupObjectTracker.cs b/DesktopVRSwitch/VRModeTrackers/CVRPickupObjectTracker.cs index a5577c3..5b3674b 100644 --- a/DesktopVRSwitch/VRModeTrackers/CVRPickupObjectTracker.cs +++ b/DesktopVRSwitch/VRModeTrackers/CVRPickupObjectTracker.cs @@ -18,7 +18,7 @@ public class CVRPickupObjectTracker : MonoBehaviour VRModeSwitchManager.OnPostVRModeSwitch -= OnPostSwitch; } - public void OnPostSwitch(bool intoVR) + public void OnPostSwitch(object sender, VRModeSwitchManager.VRModeEventArgs args) { if (_pickupObject != null) { @@ -30,4 +30,4 @@ public class CVRPickupObjectTracker : MonoBehaviour (_storedGripOrigin, _pickupObject.gripOrigin) = (_pickupObject.gripOrigin, _storedGripOrigin); } } -} \ No newline at end of file +} diff --git a/DesktopVRSwitch/VRModeTrackers/CVRWorldTracker.cs b/DesktopVRSwitch/VRModeTrackers/CVRWorldTracker.cs index daceab3..f312c8f 100644 --- a/DesktopVRSwitch/VRModeTrackers/CVRWorldTracker.cs +++ b/DesktopVRSwitch/VRModeTrackers/CVRWorldTracker.cs @@ -17,7 +17,7 @@ public class CVRWorldTracker : VRModeTracker VRModeSwitchManager.OnPostVRModeSwitch -= OnPostSwitch; } - private void OnPostSwitch(bool intoVR) + private void OnPostSwitch(object sender, VRModeSwitchManager.VRModeEventArgs args) { DesktopVRSwitch.Logger.Msg("Configuring CVRWorld. Updating PostProcessing & DesktopCameraController FOV settings."); diff --git a/DesktopVRSwitch/VRModeTrackers/CVR_InteractableManagerTracker.cs b/DesktopVRSwitch/VRModeTrackers/CVR_InteractableManagerTracker.cs index 954862f..a3ae264 100644 --- a/DesktopVRSwitch/VRModeTrackers/CVR_InteractableManagerTracker.cs +++ b/DesktopVRSwitch/VRModeTrackers/CVR_InteractableManagerTracker.cs @@ -14,10 +14,10 @@ public class CVR_InteractableManagerTracker : VRModeTracker VRModeSwitchManager.OnPostVRModeSwitch -= OnPostSwitch; } - private void OnPostSwitch(bool intoVR) + private void OnPostSwitch(object sender, VRModeSwitchManager.VRModeEventArgs args) { - DesktopVRSwitch.Logger.Msg($"Setting CVRInputManager inputEnabled & CVR_InteractableManager enableInteractions to {!intoVR}"); + DesktopVRSwitch.Logger.Msg($"Setting CVRInputManager inputEnabled & CVR_InteractableManager enableInteractions to {!args.IsUsingVr}"); - CVR_InteractableManager.enableInteractions = !intoVR; + CVR_InteractableManager.enableInteractions = !args.IsUsingVr; } } \ No newline at end of file diff --git a/DesktopVRSwitch/VRModeTrackers/CVR_MenuManagerTracker.cs b/DesktopVRSwitch/VRModeTrackers/CVR_MenuManagerTracker.cs index 6323efc..75e850c 100644 --- a/DesktopVRSwitch/VRModeTrackers/CVR_MenuManagerTracker.cs +++ b/DesktopVRSwitch/VRModeTrackers/CVR_MenuManagerTracker.cs @@ -17,19 +17,19 @@ public class CVR_MenuManagerTracker : VRModeTracker VRModeSwitchManager.OnPostVRModeSwitch -= OnPostSwitch; } - private void OnPreSwitch(bool intoVR) + private void OnPreSwitch(object sender, VRModeSwitchManager.VRModeEventArgs args) { DesktopVRSwitch.Logger.Msg("Closing CVR_MenuManager - Quick Menu."); CVR_MenuManager.Instance.ToggleQuickMenu(false); } - private void OnPostSwitch(bool intoVR) + private void OnPostSwitch(object sender, VRModeSwitchManager.VRModeEventArgs args) { DesktopVRSwitch.Logger.Msg("Updating CVR_Menu_Data core data."); - CVR_MenuManager.Instance.coreData.core.inVr = intoVR; + CVR_MenuManager.Instance.coreData.core.inVr = args.IsUsingVr; CVR_MenuManager.Instance.quickMenu.transform.localPosition = Vector3.zero; CVR_MenuManager.Instance.quickMenu.transform.localRotation = Quaternion.identity; } -} \ No newline at end of file +} diff --git a/DesktopVRSwitch/VRModeTrackers/CameraFacingObjectTracker.cs b/DesktopVRSwitch/VRModeTrackers/CameraFacingObjectTracker.cs index d05568d..5998f2a 100644 --- a/DesktopVRSwitch/VRModeTrackers/CameraFacingObjectTracker.cs +++ b/DesktopVRSwitch/VRModeTrackers/CameraFacingObjectTracker.cs @@ -18,9 +18,8 @@ public class CameraFacingObjectTracker : MonoBehaviour VRModeSwitchManager.OnPostVRModeSwitch -= OnPostSwitch; } - public void OnPostSwitch(bool intoVR) + public void OnPostSwitch(object sender, VRModeSwitchManager.VRModeEventArgs args) { - // TODO: cache camera - _cameraFacingObject.m_Camera = Utils.GetPlayerCameraObject(intoVR).GetComponent(); + _cameraFacingObject.m_Camera = args.PlayerCamera; } } \ No newline at end of file diff --git a/DesktopVRSwitch/VRModeTrackers/CheckVRTracker.cs b/DesktopVRSwitch/VRModeTrackers/CheckVRTracker.cs index 15abb85..d957c86 100644 --- a/DesktopVRSwitch/VRModeTrackers/CheckVRTracker.cs +++ b/DesktopVRSwitch/VRModeTrackers/CheckVRTracker.cs @@ -14,8 +14,8 @@ public class CheckVRTracker : VRModeTracker VRModeSwitchManager.OnPostVRModeSwitch -= OnPostSwitch; } - private void OnPostSwitch(bool intoVR) + private void OnPostSwitch(object sender, VRModeSwitchManager.VRModeEventArgs args) { - CheckVR.Instance.hasVrDeviceLoaded = intoVR; + CheckVR.Instance.hasVrDeviceLoaded = args.IsUsingVr; } } \ No newline at end of file diff --git a/DesktopVRSwitch/VRModeTrackers/CohtmlHudTracker.cs b/DesktopVRSwitch/VRModeTrackers/CohtmlHudTracker.cs index 024ce93..e7073ac 100644 --- a/DesktopVRSwitch/VRModeTrackers/CohtmlHudTracker.cs +++ b/DesktopVRSwitch/VRModeTrackers/CohtmlHudTracker.cs @@ -16,11 +16,11 @@ public class CohtmlHudTracker : VRModeTracker VRModeSwitchManager.OnPostVRModeSwitch -= OnPostSwitch; } - private void OnPostSwitch(bool intoVR) + private void OnPostSwitch(object sender, VRModeSwitchManager.VRModeEventArgs args) { DesktopVRSwitch.Logger.Msg("Configuring new hud affinity for CohtmlHud."); - CohtmlHud.Instance.gameObject.transform.parent = Utils.GetPlayerCameraObject(intoVR).transform; + CohtmlHud.Instance.gameObject.transform.parent = Utils.GetPlayerCameraObject(args.IsUsingVr).transform; // This handles rotation and position CVRTools.ConfigureHudAffinity(); CohtmlHud.Instance.gameObject.transform.localScale = new Vector3(1.2f, 1f, 1.2f); diff --git a/DesktopVRSwitch/VRModeTrackers/HudOperationsTracker.cs b/DesktopVRSwitch/VRModeTrackers/HudOperationsTracker.cs index d0a4574..b9b0deb 100644 --- a/DesktopVRSwitch/VRModeTrackers/HudOperationsTracker.cs +++ b/DesktopVRSwitch/VRModeTrackers/HudOperationsTracker.cs @@ -14,11 +14,11 @@ public class HudOperationsTracker : VRModeTracker VRModeSwitchManager.OnPostVRModeSwitch -= OnPostSwitch; } - private void OnPostSwitch(bool intoVR) + private void OnPostSwitch(object sender, VRModeSwitchManager.VRModeEventArgs args) { DesktopVRSwitch.Logger.Msg("Switching HudOperations worldLoadingItem & worldLoadStatus."); - HudOperations.Instance.worldLoadingItem = intoVR ? HudOperations.Instance.worldLoadingItemVr : HudOperations.Instance.worldLoadingItemDesktop; - HudOperations.Instance.worldLoadStatus = intoVR ? HudOperations.Instance.worldLoadStatusVr : HudOperations.Instance.worldLoadStatusDesktop; + HudOperations.Instance.worldLoadingItem = args.IsUsingVr ? HudOperations.Instance.worldLoadingItemVr : HudOperations.Instance.worldLoadingItemDesktop; + HudOperations.Instance.worldLoadStatus = args.IsUsingVr ? HudOperations.Instance.worldLoadStatusVr : HudOperations.Instance.worldLoadStatusDesktop; } } \ No newline at end of file diff --git a/DesktopVRSwitch/VRModeTrackers/IKSystemTracker.cs b/DesktopVRSwitch/VRModeTrackers/IKSystemTracker.cs index fe8dc28..6c88bc9 100644 --- a/DesktopVRSwitch/VRModeTrackers/IKSystemTracker.cs +++ b/DesktopVRSwitch/VRModeTrackers/IKSystemTracker.cs @@ -20,7 +20,7 @@ public class IKSystemTracker : VRModeTracker VRModeSwitchManager.OnPostVRModeSwitch -= OnPostSwitch; } - private void OnPreSwitch(bool intoVR) + private void OnPreSwitch(object sender, VRModeSwitchManager.VRModeEventArgs args) { BodySystem.TrackingEnabled = false; BodySystem.TrackingPositionWeight = 0f; @@ -30,7 +30,7 @@ public class IKSystemTracker : VRModeTracker IKSystem.vrik.enabled = false; } - private void OnFailedSwitch(bool intoVR) + private void OnFailedSwitch(object sender, VRModeSwitchManager.VRModeEventArgs args) { BodySystem.TrackingEnabled = true; BodySystem.TrackingPositionWeight = 1f; @@ -40,7 +40,7 @@ public class IKSystemTracker : VRModeTracker IKSystem.vrik.enabled = true; } - private void OnPostSwitch(bool intoVR) + private void OnPostSwitch(object sender, VRModeSwitchManager.VRModeEventArgs args) { if (IKSystem.vrik != null) UnityEngine.Object.DestroyImmediate(IKSystem.vrik); @@ -54,12 +54,12 @@ public class IKSystemTracker : VRModeTracker BodySystem.isRecalibration = false; // Make it so you don't instantly end up in FBT from Desktop - IKSystem.firstAvatarLoaded = DesktopVRSwitch.EntryEnterCalibrationOnSwitch.Value; + IKSystem.firstAvatarLoaded = ModSettings.EntryEnterCalibrationOnSwitch.Value; // Turn off finger tracking just in case the user switched controllers IKSystem.Instance.FingerSystem.controlActive = false; - SetupSteamVRTrackingModule(intoVR); + SetupSteamVRTrackingModule(args.IsUsingVr); } private void SetupSteamVRTrackingModule(bool enableVR) @@ -69,13 +69,9 @@ public class IKSystemTracker : VRModeTracker if (openVRModule != null) { if (enableVR) - { openVRModule.ModuleStart(); - } else - { openVRModule.ModuleDestroy(); - } } else if (enableVR) { diff --git a/DesktopVRSwitch/VRModeTrackers/MetaPortTracker.cs b/DesktopVRSwitch/VRModeTrackers/MetaPortTracker.cs index 1f5e851..acc7e87 100644 --- a/DesktopVRSwitch/VRModeTrackers/MetaPortTracker.cs +++ b/DesktopVRSwitch/VRModeTrackers/MetaPortTracker.cs @@ -17,16 +17,16 @@ public class MetaPortTracker : VRModeTracker VRModeSwitchManager.OnPostVRModeSwitch -= OnPostSwitch; } - private void OnPostSwitch(bool intoVR) + private void OnPostSwitch(object sender, VRModeSwitchManager.VRModeEventArgs args) { - DesktopVRSwitch.Logger.Msg($"Setting MetaPort isUsingVr to {intoVR}."); + DesktopVRSwitch.Logger.Msg($"Setting MetaPort isUsingVr to {args.IsUsingVr}."); // Main thing most of the game checks for if using VR - MetaPort.Instance.isUsingVr = intoVR; + MetaPort.Instance.isUsingVr = args.IsUsingVr; // replace UpdateRichPresence(); - ResetSteamVROverrides(intoVR); + ResetSteamVROverrides(args.IsUsingVr); } private void UpdateRichPresence() diff --git a/DesktopVRSwitch/VRModeTrackers/MovementSystemTracker.cs b/DesktopVRSwitch/VRModeTrackers/MovementSystemTracker.cs index 0337bb7..8a7646b 100644 --- a/DesktopVRSwitch/VRModeTrackers/MovementSystemTracker.cs +++ b/DesktopVRSwitch/VRModeTrackers/MovementSystemTracker.cs @@ -23,7 +23,7 @@ public class MovementSystemTracker : VRModeTracker VRModeSwitchManager.OnPostVRModeSwitch -= OnPostSwitch; } - private void OnPreSwitch(bool intoVR) + private void OnPreSwitch(object sender, VRModeSwitchManager.VRModeEventArgs args) { DesktopVRSwitch.Logger.Msg("Storing player world position and rotation."); @@ -39,17 +39,17 @@ public class MovementSystemTracker : VRModeTracker } - private void OnFailedSwitch(bool intoVR) + private void OnFailedSwitch(object sender, VRModeSwitchManager.VRModeEventArgs args) { DesktopVRSwitch.Logger.Msg("Resetting MovementSystem mobility."); MovementSystem.Instance.SetImmobilized(false); } - private void OnPostSwitch(bool intoVR) + private void OnPostSwitch(object sender, VRModeSwitchManager.VRModeEventArgs args) { // Lazy - MelonLoader.MelonCoroutines.Start(TeleportFrameAfter(intoVR)); + MelonLoader.MelonCoroutines.Start(TeleportFrameAfter(args.IsUsingVr)); } private IEnumerator TeleportFrameAfter(bool intoVR) diff --git a/DesktopVRSwitch/VRModeTrackers/PlayerSetupTracker.cs b/DesktopVRSwitch/VRModeTrackers/PlayerSetupTracker.cs index 0568589..a600670 100644 --- a/DesktopVRSwitch/VRModeTrackers/PlayerSetupTracker.cs +++ b/DesktopVRSwitch/VRModeTrackers/PlayerSetupTracker.cs @@ -14,11 +14,11 @@ public class PlayerSetupTracker : VRModeTracker VRModeSwitchManager.OnPostVRModeSwitch -= OnPostSwitch; } - private void OnPostSwitch(bool intoVR) + private void OnPostSwitch(object sender, VRModeSwitchManager.VRModeEventArgs args) { DesktopVRSwitch.Logger.Msg("Switching active PlayerSetup camera rigs. Updating Desktop camera FOV."); - PlayerSetup.Instance.desktopCameraRig.SetActive(!intoVR); - PlayerSetup.Instance.vrCameraRig.SetActive(intoVR); + PlayerSetup.Instance.desktopCameraRig.SetActive(!args.IsUsingVr); + PlayerSetup.Instance.vrCameraRig.SetActive(args.IsUsingVr); } } \ No newline at end of file diff --git a/DesktopVRSwitch/VRModeTrackers/PortableCameraTracker.cs b/DesktopVRSwitch/VRModeTrackers/PortableCameraTracker.cs index 4a4f145..6710420 100644 --- a/DesktopVRSwitch/VRModeTrackers/PortableCameraTracker.cs +++ b/DesktopVRSwitch/VRModeTrackers/PortableCameraTracker.cs @@ -14,7 +14,7 @@ public class PortableCameraTracker : VRModeTracker VRModeSwitchManager.OnPostVRModeSwitch -= OnPostSwitch; } - private void OnPostSwitch(bool intoVR) + private void OnPostSwitch(object sender, VRModeSwitchManager.VRModeEventArgs args) { DesktopVRSwitch.Logger.Msg("Forcing PortableCamera canvas mirroring off."); diff --git a/DesktopVRSwitch/VRModeTrackers/VRModeTracker.cs b/DesktopVRSwitch/VRModeTrackers/VRModeTracker.cs index 3b8ede8..d78dfba 100644 --- a/DesktopVRSwitch/VRModeTrackers/VRModeTracker.cs +++ b/DesktopVRSwitch/VRModeTrackers/VRModeTracker.cs @@ -1,7 +1,7 @@ namespace NAK.DesktopVRSwitch.VRModeTrackers; -public class VRModeTracker +public abstract class VRModeTracker { public virtual void TrackerInit() { } public virtual void TrackerDestroy() { } -} +} \ No newline at end of file diff --git a/DesktopVRSwitch/VRModeTrackers/ViewManagerTracker.cs b/DesktopVRSwitch/VRModeTrackers/ViewManagerTracker.cs index e7556a5..31d38fc 100644 --- a/DesktopVRSwitch/VRModeTrackers/ViewManagerTracker.cs +++ b/DesktopVRSwitch/VRModeTrackers/ViewManagerTracker.cs @@ -14,7 +14,7 @@ public class ViewManagerTracker : VRModeTracker VRModeSwitchManager.OnPreVRModeSwitch -= OnPreSwitch; } - private void OnPreSwitch(bool intoVR) + private void OnPreSwitch(object sender, VRModeSwitchManager.VRModeEventArgs args) { DesktopVRSwitch.Logger.Msg("Closing ViewManager - Main Menu."); diff --git a/DesktopVRSwitch/XRHandler.cs b/DesktopVRSwitch/XRHandler.cs new file mode 100644 index 0000000..ba8f1c5 --- /dev/null +++ b/DesktopVRSwitch/XRHandler.cs @@ -0,0 +1,66 @@ +using System.Collections; +using System.Reflection; +using ABI_RC.Core.Savior; +using Unity.XR.OpenVR; +using UnityEngine; +using UnityEngine.XR.Management; +using UnityEngine.XR.OpenXR; +using Valve.VR; + +namespace NAK.DesktopVRSwitch; + +internal static class XRHandler +{ + internal static IEnumerator StartXR() + { + yield return XRGeneralSettings.Instance.Manager.InitializeLoader(); + + if (XRGeneralSettings.Instance.Manager.activeLoader != null) + XRGeneralSettings.Instance.Manager.StartSubsystems(); + else + StopXR(); + + yield return null; + } + + internal static IEnumerator StopXR() + { + if (!XRGeneralSettings.Instance.Manager.isInitializationComplete) + yield break; + + // Forces SteamVR to reinitialize SteamVR_Input next switch + SteamVR_ActionSet_Manager.DisableAllActionSets(); + SteamVR_Input.initialized = false; + + // Remove SteamVR behaviour & render + UnityEngine.Object.DestroyImmediate(SteamVR_Behaviour.instance.gameObject); + SteamVR.enabled = false; // disposes SteamVR + + // Disable UnityXR + XRGeneralSettings.Instance.Manager.StopSubsystems(); + XRGeneralSettings.Instance.Manager.DeinitializeLoader(); + + // We don't really need to wait a frame on Stop() + yield return null; + } + + internal static void SwitchLoader() + { + XRLoader item; + + if (!CheckVR.Instance.forceOpenXr) + { + item = ScriptableObject.CreateInstance(); + DesktopVRSwitch.Logger.Msg("Using XR Loader: SteamVR"); + } + else + { + item = ScriptableObject.CreateInstance(); + DesktopVRSwitch.Logger.Msg("Using XR Loader: OpenXR"); + } + + typeof(XRManagerSettings) + .GetField("m_Loaders", BindingFlags.Instance | BindingFlags.NonPublic) + ?.SetValue(XRGeneralSettings.Instance.Manager, new List { item }); + } +}