diff --git a/DesktopVRSwitch/DesktopVRSwitch.csproj b/DesktopVRSwitch/DesktopVRSwitch.csproj index 66a50a8..e94f9dc 100644 --- a/DesktopVRSwitch/DesktopVRSwitch.csproj +++ b/DesktopVRSwitch/DesktopVRSwitch.csproj @@ -1,2 +1,2 @@ - + diff --git a/DesktopVRSwitch/DesktopVRSwitcher.cs b/DesktopVRSwitch/DesktopVRSwitcher.cs index 50b565b..1fb5a15 100644 --- a/DesktopVRSwitch/DesktopVRSwitcher.cs +++ b/DesktopVRSwitch/DesktopVRSwitcher.cs @@ -1,4 +1,6 @@ -using NAK.DesktopVRSwitch.Patches; +/** + +using NAK.DesktopVRSwitch.Patches; using System.Collections; using UnityEngine; using UnityEngine.XR; @@ -16,7 +18,7 @@ using ABI_RC.Core; QualitySettings.vSyncCount = 0; Time.fixedDeltaTime = Time.timeScale / hmd_DisplayFrequency; -**/ +** namespace NAK.DesktopVRSwitch; @@ -130,35 +132,36 @@ public class DesktopVRSwitcher : MonoBehaviour public void PostVRModeSwitch(bool enableVR) { if (_softVRSwitch) return; - //close the menus - TryCatchHell.CloseCohtmlMenus(); - //the base of VR checks - TryCatchHell.SetCheckVR(enableVR); - TryCatchHell.SetMetaPort(enableVR); - - //game basics for functional gameplay post switch - TryCatchHell.RepositionCohtmlHud(enableVR); - TryCatchHell.UpdateHudOperations(enableVR); - TryCatchHell.DisableMirrorCanvas(); - TryCatchHell.SwitchActiveCameraRigs(enableVR); - TryCatchHell.ResetCVRInputManager(); - TryCatchHell.UpdateRichPresence(); - TryCatchHell.UpdateGestureReconizerCam(); - TryCatchHell.UpdateMenuCoreData(enableVR); - - //let tracked objects know we switched - VRModeSwitchTracker.PostVRModeSwitch(enableVR); - - //reload avatar by default, optional for debugging - if (_reloadLocalAvatar) - { - TryCatchHell.ReloadLocalAvatar(); - } + SetupVR(enableVR); _switchInProgress = false; } + public void SetupVR(bool intoVR) + { + List actions = new List + { + TryCatchHell.SetCheckVR, + TryCatchHell.SetMetaPort, + TryCatchHell.RepositionCohtmlHud, + TryCatchHell.UpdateHudOperations, + TryCatchHell.DisableMirrorCanvas, + TryCatchHell.SwitchActiveCameraRigs, + TryCatchHell.ResetCVRInputManager, + TryCatchHell.UpdateRichPresence, + TryCatchHell.UpdateGestureReconizerCam, + TryCatchHell.UpdateMenuCoreData, + }; + + foreach (var action in actions) + { + TryCatchHell.TryExecute(action, intoVR); + } + + TryCatchHell.TryExecute(VRModeSwitchTracker.PostVRModeSwitch, intoVR); + } + public void ResetSteamVROverrides() { // Reset physics time to Desktop default @@ -193,3 +196,6 @@ public class DesktopVRSwitcher : MonoBehaviour } } + + +**/ \ No newline at end of file diff --git a/DesktopVRSwitch/HarmonyPatches.cs b/DesktopVRSwitch/HarmonyPatches.cs index ce8c9b6..6cb7c27 100644 --- a/DesktopVRSwitch/HarmonyPatches.cs +++ b/DesktopVRSwitch/HarmonyPatches.cs @@ -1,12 +1,11 @@ using ABI.CCK.Components; -using ABI_RC.Core.Player; using ABI_RC.Core.Savior; using ABI_RC.Core.Util.Object_Behaviour; using ABI_RC.Systems.IK; using ABI_RC.Systems.IK.TrackingModules; -using ABI_RC.Systems.MovementSystem; using HarmonyLib; using NAK.DesktopVRSwitch.Patches; +using NAK.DesktopVRSwitch.VRModeTrackers; using UnityEngine; namespace NAK.DesktopVRSwitch.HarmonyPatches; @@ -15,87 +14,24 @@ class CheckVRPatches { [HarmonyPostfix] [HarmonyPatch(typeof(CheckVR), nameof(CheckVR.Start))] - private static void Postfix_CheckVR_Start(ref CheckVR __instance) + static void Postfix_CheckVR_Start(ref CheckVR __instance) { - __instance.gameObject.AddComponent(); - } -} - -class MovementSystemPatches -{ - [HarmonyPostfix] - [HarmonyPatch(typeof(MovementSystem), nameof(MovementSystem.Start))] - private static void Postfix_MovementSystem_Start(ref MovementSystem __instance) - { - __instance.gameObject.AddComponent(); - } -} - -class CVRPickupObjectPatches -{ - [HarmonyPrefix] - [HarmonyPatch(typeof(CVRPickupObject), nameof(CVRPickupObject.Start))] - private static void Prefix_CVRPickupObject_Start(ref CVRPickupObject __instance) - { - if (__instance.gripType == CVRPickupObject.GripType.Free) return; - - Transform vrOrigin = __instance.gripOrigin; - Transform desktopOrigin = __instance.gripOrigin.Find("[Desktop]"); - if (vrOrigin != null && desktopOrigin != null) - { - var tracker = __instance.gameObject.AddComponent(); - tracker.pickupObject = __instance; - tracker.storedGripOrigin = (!MetaPort.Instance.isUsingVr ? vrOrigin : desktopOrigin); - } - } -} - -class CVRWorldPatches -{ - [HarmonyPostfix] - [HarmonyPatch(typeof(CVRWorld), nameof(CVRWorld.SetDefaultCamValues))] - private static void Postfix_CVRWorld_SetDefaultCamValues() - { - ReferenceCameraPatch.OnWorldLoad(); - } - - [HarmonyPostfix] - [HarmonyPatch(typeof(CVRWorld), nameof(CVRWorld.CopyRefCamValues))] - private static void Postfix_CVRWorld_CopyRefCamValues() - { - ReferenceCameraPatch.OnWorldLoad(); - } -} - -class CameraFacingObjectPatches -{ - [HarmonyPostfix] - [HarmonyPatch(typeof(CameraFacingObject), nameof(CameraFacingObject.Start))] - private static void Postfix_CameraFacingObject_Start(ref CameraFacingObject __instance) - { - __instance.gameObject.AddComponent(); + __instance.gameObject.AddComponent(); } } class IKSystemPatches { - [HarmonyPostfix] - [HarmonyPatch(typeof(IKSystem), nameof(IKSystem.Start))] - private static void Postfix_IKSystem_Start(ref IKSystem __instance) - { - __instance.gameObject.AddComponent(); - } - [HarmonyPostfix] //lazy fix so i dont need to wait few frames [HarmonyPatch(typeof(TrackingPoint), nameof(TrackingPoint.Initialize))] - private static void Postfix_TrackingPoint_Initialize(ref TrackingPoint __instance) + static void Postfix_TrackingPoint_Initialize(ref TrackingPoint __instance) { __instance.referenceTransform.localScale = Vector3.one; } [HarmonyPostfix] //lazy fix so device indecies can change properly [HarmonyPatch(typeof(SteamVRTrackingModule), nameof(SteamVRTrackingModule.ModuleDestroy))] - private static void Postfix_SteamVRTrackingModule_ModuleDestroy(ref SteamVRTrackingModule __instance) + static void Postfix_SteamVRTrackingModule_ModuleDestroy(ref SteamVRTrackingModule __instance) { for (int i = 0; i < __instance.TrackingPoints.Count; i++) { @@ -105,12 +41,29 @@ class IKSystemPatches } } -class VRTrackerManagerPatches +class CVRWorldPatches { [HarmonyPostfix] - [HarmonyPatch(typeof(VRTrackerManager), nameof(VRTrackerManager.Start))] - private static void Postfix_VRTrackerManager_Start(ref VRTrackerManager __instance) + [HarmonyPatch(typeof(CVRWorld), nameof(CVRWorld.SetDefaultCamValues))] + static void Postfix_CVRWorld_SetDefaultCamValues() { - __instance.gameObject.AddComponent(); + ReferenceCameraPatch.OnWorldLoad(); + } + + [HarmonyPostfix] + [HarmonyPatch(typeof(CVRWorld), nameof(CVRWorld.CopyRefCamValues))] + static void Postfix_CVRWorld_CopyRefCamValues() + { + ReferenceCameraPatch.OnWorldLoad(); + } +} + +class CameraFacingObjectPatches +{ + [HarmonyPostfix] + [HarmonyPatch(typeof(CameraFacingObject), nameof(CameraFacingObject.Start))] + static void Postfix_CameraFacingObject_Start(ref CameraFacingObject __instance) + { + __instance.gameObject.AddComponent(); } } \ No newline at end of file diff --git a/DesktopVRSwitch/Main.cs b/DesktopVRSwitch/Main.cs index 181ae57..134bc8c 100644 --- a/DesktopVRSwitch/Main.cs +++ b/DesktopVRSwitch/Main.cs @@ -1,4 +1,6 @@ using MelonLoader; +using NAK.DesktopVRSwitch.VRModeTrackers; +using UnityEngine; /** I know the TryCatchHell thing might be a bit exessive, but it is @@ -18,23 +20,66 @@ 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 override void OnInitializeMelon() { Logger = LoggerInstance; + + RegisterVRModeTrackers(); + + // main manager ApplyPatches(typeof(HarmonyPatches.CheckVRPatches)); - ApplyPatches(typeof(HarmonyPatches.CVRPickupObjectPatches)); - ApplyPatches(typeof(HarmonyPatches.CVRWorldPatches)); + // nameplate fixes ApplyPatches(typeof(HarmonyPatches.CameraFacingObjectPatches)); + // lazy fix to reset iksystem ApplyPatches(typeof(HarmonyPatches.IKSystemPatches)); - ApplyPatches(typeof(HarmonyPatches.MovementSystemPatches)); - ApplyPatches(typeof(HarmonyPatches.VRTrackerManagerPatches)); + // post processing fixes + ApplyPatches(typeof(HarmonyPatches.CVRWorldPatches)); + } + + public override void OnUpdate() + { + if (Input.GetKeyDown(KeyCode.F6) && Input.GetKey(KeyCode.LeftControl)) + { + VRModeSwitchManager.Instance?.StartSwitch(); + } + } + + void RegisterVRModeTrackers() + { + // Core trackers + VRModeSwitchManager.RegisterVRModeTracker(new CheckVRTracker()); + VRModeSwitchManager.RegisterVRModeTracker(new MetaPortTracker()); + + // HUD trackers + VRModeSwitchManager.RegisterVRModeTracker(new CohtmlHudTracker()); + VRModeSwitchManager.RegisterVRModeTracker(new HudOperationsTracker()); + + // Player trackers + VRModeSwitchManager.RegisterVRModeTracker(new PlayerSetupTracker()); + VRModeSwitchManager.RegisterVRModeTracker(new MovementSystemTracker()); + VRModeSwitchManager.RegisterVRModeTracker(new IKSystemTracker()); + + // Menu trackers + VRModeSwitchManager.RegisterVRModeTracker(new CVR_MenuManagerTracker()); + VRModeSwitchManager.RegisterVRModeTracker(new ViewManagerTracker()); + + // Interaction trackers + VRModeSwitchManager.RegisterVRModeTracker(new CVRInputManagerTracker()); + VRModeSwitchManager.RegisterVRModeTracker(new CVR_InteractableManagerTracker()); + VRModeSwitchManager.RegisterVRModeTracker(new CVRGestureRecognizerTracker()); + + // Portable camera tracker + VRModeSwitchManager.RegisterVRModeTracker(new PortableCameraTracker()); } void ApplyPatches(Type type) diff --git a/DesktopVRSwitch/Patches/CVRPickupObjectTracker.cs b/DesktopVRSwitch/Patches/CVRPickupObjectTracker.cs deleted file mode 100644 index f37acd1..0000000 --- a/DesktopVRSwitch/Patches/CVRPickupObjectTracker.cs +++ /dev/null @@ -1,31 +0,0 @@ -using ABI.CCK.Components; -using UnityEngine; - -//Thanks Ben! I was scared of transpiler so I reworked a bit... - -namespace NAK.DesktopVRSwitch.Patches; - -public class CVRPickupObjectTracker : MonoBehaviour -{ - public CVRPickupObject pickupObject; - public Transform storedGripOrigin; - - void Start() - { - VRModeSwitchTracker.OnPostVRModeSwitch += PostVRModeSwitch; - } - - void OnDestroy() - { - VRModeSwitchTracker.OnPostVRModeSwitch -= PostVRModeSwitch; - } - - public void PostVRModeSwitch(bool enableVR, Camera activeCamera) - { - if (pickupObject != null) - { - if (pickupObject._controllerRay != null) pickupObject._controllerRay.DropObject(true); - (storedGripOrigin, pickupObject.gripOrigin) = (pickupObject.gripOrigin, storedGripOrigin); - } - } -} diff --git a/DesktopVRSwitch/Patches/CameraFacingObjectTracker.cs b/DesktopVRSwitch/Patches/CameraFacingObjectTracker.cs deleted file mode 100644 index 89bb90e..0000000 --- a/DesktopVRSwitch/Patches/CameraFacingObjectTracker.cs +++ /dev/null @@ -1,25 +0,0 @@ -using ABI_RC.Core.Util.Object_Behaviour; -using UnityEngine; - -namespace NAK.DesktopVRSwitch.Patches; - -public class CameraFacingObjectTracker : MonoBehaviour -{ - public CameraFacingObject cameraFacingObject; - - void Start() - { - cameraFacingObject = GetComponent(); - VRModeSwitchTracker.OnPostVRModeSwitch += PostVRModeSwitch; - } - - void OnDestroy() - { - VRModeSwitchTracker.OnPostVRModeSwitch -= PostVRModeSwitch; - } - - public void PostVRModeSwitch(bool enableVR, Camera activeCamera) - { - cameraFacingObject.m_Camera = activeCamera; - } -} \ No newline at end of file diff --git a/DesktopVRSwitch/Patches/IKSystemTracker.cs b/DesktopVRSwitch/Patches/IKSystemTracker.cs deleted file mode 100644 index 36d8c0c..0000000 --- a/DesktopVRSwitch/Patches/IKSystemTracker.cs +++ /dev/null @@ -1,87 +0,0 @@ -using ABI_RC.Systems.IK; -using ABI_RC.Systems.IK.SubSystems; -using ABI_RC.Systems.IK.TrackingModules; -using UnityEngine; - -namespace NAK.DesktopVRSwitch.Patches; - -public class IKSystemTracker : MonoBehaviour -{ - public IKSystem ikSystem; - - void Start() - { - ikSystem = GetComponent(); - VRModeSwitchTracker.OnPreVRModeSwitch += PreVRModeSwitch; - VRModeSwitchTracker.OnFailVRModeSwitch += FailedVRModeSwitch; - VRModeSwitchTracker.OnPostVRModeSwitch += PostVRModeSwitch; - } - void OnDestroy() - { - VRModeSwitchTracker.OnPreVRModeSwitch -= PreVRModeSwitch; - VRModeSwitchTracker.OnFailVRModeSwitch -= FailedVRModeSwitch; - VRModeSwitchTracker.OnPostVRModeSwitch -= PostVRModeSwitch; - } - - public void PreVRModeSwitch(bool enableVR, Camera activeCamera) - { - BodySystem.TrackingEnabled = false; - BodySystem.TrackingPositionWeight = 0f; - BodySystem.TrackingLocomotionEnabled = false; - if (IKSystem.vrik != null) - IKSystem.vrik.enabled = false; - } - - public void FailedVRModeSwitch(bool enableVR, Camera activeCamera) - { - BodySystem.TrackingEnabled = true; - BodySystem.TrackingPositionWeight = 1f; - BodySystem.TrackingLocomotionEnabled = true; - if (IKSystem.vrik != null) - IKSystem.vrik.enabled = true; - } - - public void PostVRModeSwitch(bool enableVR, Camera activeCamera) - { - if (IKSystem.vrik != null) - DestroyImmediate(IKSystem.vrik); - - //make sure you are fully tracking - BodySystem.TrackingEnabled = true; - BodySystem.TrackingPositionWeight = 1f; - BodySystem.TrackingLocomotionEnabled = true; - BodySystem.isCalibratedAsFullBody = false; - BodySystem.isCalibrating = false; - BodySystem.isRecalibration = false; - //make it so you dont instantly end up in FBT from Desktop - IKSystem.firstAvatarLoaded = DesktopVRSwitch.EntryEnterCalibrationOnSwitch.Value; - //turn of finger tracking just in case user switched controllers - ikSystem.FingerSystem.controlActive = false; - - //vrik should be deleted by avatar switch - - SetupSteamVRTrackingModule(enableVR); - } - - void SetupSteamVRTrackingModule(bool enableVR) - { - var openVRModule = ikSystem._trackingModules.OfType().FirstOrDefault(); - - if (openVRModule != null) - { - if (enableVR) - { - openVRModule.ModuleStart(); - } - else - { - openVRModule.ModuleDestroy(); - } - } - else if (enableVR) - { - var newVRModule = new SteamVRTrackingModule(); - ikSystem.AddTrackingModule(newVRModule); - } - } -} \ No newline at end of file diff --git a/DesktopVRSwitch/Patches/MovementSystemTracker.cs b/DesktopVRSwitch/Patches/MovementSystemTracker.cs deleted file mode 100644 index ddfed75..0000000 --- a/DesktopVRSwitch/Patches/MovementSystemTracker.cs +++ /dev/null @@ -1,54 +0,0 @@ -using ABI_RC.Systems.MovementSystem; -using UnityEngine; - -namespace NAK.DesktopVRSwitch.Patches; - -public class MovementSystemTracker : MonoBehaviour -{ - public MovementSystem movementSystem; - public Vector3 preSwitchWorldPosition; - public Quaternion preSwitchWorldRotation; - - void Start() - { - movementSystem = GetComponent(); - VRModeSwitchTracker.OnPreVRModeSwitch += PreVRModeSwitch; - VRModeSwitchTracker.OnPostVRModeSwitch += PostVRModeSwitch; - } - - void OnDestroy() - { - VRModeSwitchTracker.OnPreVRModeSwitch -= PreVRModeSwitch; - VRModeSwitchTracker.OnPostVRModeSwitch -= PostVRModeSwitch; - } - - public void PreVRModeSwitch(bool enableVR, Camera activeCamera) - { - //correct rotationPivot y position, so we dont teleport up/down - Vector3 position = movementSystem.rotationPivot.transform.position; - position.y = movementSystem.transform.position.y; - preSwitchWorldPosition = position; - preSwitchWorldRotation = movementSystem.rotationPivot.transform.rotation; - //ChilloutVR does not use VRIK root right, so avatar root is VR player root. - //This causes desync between VR and Desktop positions & collision on switch. - - //I correct for this in lazy way, but i use rotationPivot instead of avatar root, - //so the user can still switch even if avatar is null (if it failed to load for example). - - movementSystem.ChangeCrouch(false); - movementSystem.ChangeProne(false); - } - - public void PostVRModeSwitch(bool enableVR, Camera activeCamera) - { - //immediatly update camera to new camera transform - movementSystem.rotationPivot = activeCamera.transform; - //lazy way of correcting Desktop & VR offset issue (game does the maths) - movementSystem.TeleportToPosRot(preSwitchWorldPosition, preSwitchWorldRotation, false); - //recenter desktop collision to player object - if (!enableVR) movementSystem.UpdateColliderCenter(movementSystem.transform.position); - - movementSystem.ChangeCrouch(false); - movementSystem.ChangeProne(false); - } -} \ No newline at end of file diff --git a/DesktopVRSwitch/Patches/VRModeSwitchTracker.cs b/DesktopVRSwitch/Patches/VRModeSwitchTracker.cs deleted file mode 100644 index 74822a0..0000000 --- a/DesktopVRSwitch/Patches/VRModeSwitchTracker.cs +++ /dev/null @@ -1,45 +0,0 @@ -using ABI_RC.Core.Player; -using UnityEngine; -using UnityEngine.Events; - -namespace NAK.DesktopVRSwitch.Patches; - -public class VRModeSwitchTracker -{ - public static event UnityAction OnPreVRModeSwitch; - public static event UnityAction OnPostVRModeSwitch; - public static event UnityAction OnFailVRModeSwitch; - - public static void PreVRModeSwitch(bool enableVR) - { - TryCatchHell.TryCatchWrapper(() => - { - DesktopVRSwitch.Logger.Msg("Invoking VRModeSwitchTracker.OnPreVRModeSwitch."); - Camera activeCamera = PlayerSetup.Instance.GetActiveCamera().GetComponent(); - VRModeSwitchTracker.OnPreVRModeSwitch?.Invoke(enableVR, activeCamera); - }, - "Error while invoking VRModeSwitchTracker.OnPreVRModeSwitch. Did someone do a fucky?"); - } - - public static void PostVRModeSwitch(bool enableVR) - { - TryCatchHell.TryCatchWrapper(() => - { - DesktopVRSwitch.Logger.Msg("Invoking VRModeSwitchTracker.OnPostVRModeSwitch."); - Camera activeCamera = PlayerSetup.Instance.GetActiveCamera().GetComponent(); - VRModeSwitchTracker.OnPostVRModeSwitch?.Invoke(enableVR, activeCamera); - }, - "Error while invoking VRModeSwitchTracker.OnPostVRModeSwitch. Did someone do a fucky?"); - } - - public static void FailVRModeSwitch(bool enableVR) - { - TryCatchHell.TryCatchWrapper(() => - { - DesktopVRSwitch.Logger.Msg("Invoking VRModeSwitchTracker.OnFailVRModeSwitch."); - Camera activeCamera = PlayerSetup.Instance.GetActiveCamera().GetComponent(); - VRModeSwitchTracker.OnFailVRModeSwitch?.Invoke(enableVR, activeCamera); - }, - "Error while invoking OnFailVRModeSwitch.OnPreVRModeSwitch. Did someone do a fucky?"); - } -} \ No newline at end of file diff --git a/DesktopVRSwitch/Patches/VRTrackerManagerTracker.cs b/DesktopVRSwitch/Patches/VRTrackerManagerTracker.cs deleted file mode 100644 index 3cbaa46..0000000 --- a/DesktopVRSwitch/Patches/VRTrackerManagerTracker.cs +++ /dev/null @@ -1,31 +0,0 @@ -using ABI_RC.Core.Player; -using HarmonyLib; -using UnityEngine; - -namespace NAK.DesktopVRSwitch.Patches; - -public class VRTrackerManagerTracker : MonoBehaviour -{ - public VRTrackerManager vrTrackerManager; - - void Start() - { - vrTrackerManager = GetComponent(); - VRModeSwitchTracker.OnPostVRModeSwitch += PostVRModeSwitch; - } - void OnDestroy() - { - VRModeSwitchTracker.OnPostVRModeSwitch -= PostVRModeSwitch; - } - - public void PostVRModeSwitch(bool enableVR, Camera activeCamera) - { - //force the VRTrackerManager to reset anything its stored - //this makes it get correct Left/Right hand if entering VR with different controllers - //or if you restarted SteamVR and controllers are now in swapped index - vrTrackerManager.poses = null; - vrTrackerManager.leftHand = null; - vrTrackerManager.rightHand = null; - vrTrackerManager.hasCheckedForKnuckles = false; - } -} \ No newline at end of file diff --git a/DesktopVRSwitch/TryCatchHell.cs b/DesktopVRSwitch/TryCatchHell.cs index 92ff333..51f258b 100644 --- a/DesktopVRSwitch/TryCatchHell.cs +++ b/DesktopVRSwitch/TryCatchHell.cs @@ -1,188 +1,67 @@ -using ABI_RC.Core; -using ABI_RC.Core.EventSystem; -using ABI_RC.Core.InteractionSystem; -using ABI_RC.Core.Player; -using ABI_RC.Core.Savior; -using ABI_RC.Core.UI; -using ABI_RC.Systems.Camera; -using UnityEngine; +using UnityEngine; namespace NAK.DesktopVRSwitch; internal class TryCatchHell { - internal static void TryCatchWrapper(Action action, string errorMsg, params object[] msgArgs) + public delegate void TryAction(bool intoVR); + + public static void TryExecute(TryAction action, bool intoVR) { try { - action(); + action(intoVR); } catch (Exception ex) { - DesktopVRSwitch.Logger.Error(string.Format(errorMsg, msgArgs)); - DesktopVRSwitch.Logger.Msg(ex.Message); + Debug.LogError($"Error executing action: {ex.Message}"); } } - internal static void CloseCohtmlMenus() + internal static void CloseCohtmlMenus(bool intoVR) { - TryCatchWrapper(() => - { - DesktopVRSwitch.Logger.Msg("Closing ViewManager & CVR_MenuManager menus."); - ViewManager.Instance.UiStateToggle(false); - CVR_MenuManager.Instance.ToggleQuickMenu(false); - }, - "Setting CheckVR hasVrDeviceLoaded failed."); + + } - internal static void SetCheckVR(bool enableVR) + internal static void RepositionCohtmlHud(bool intoVR) { - TryCatchWrapper(() => - { - DesktopVRSwitch.Logger.Msg($"Setting CheckVR hasVrDeviceLoaded to {enableVR}."); - CheckVR.Instance.hasVrDeviceLoaded = enableVR; - }, - "Setting CheckVR hasVrDeviceLoaded failed."); + } - internal static void SetMetaPort(bool enableVR) + internal static void UpdateHudOperations(bool intoVR) { - TryCatchWrapper(() => - { - DesktopVRSwitch.Logger.Msg($"Setting MetaPort isUsingVr to {enableVR}."); - MetaPort.Instance.isUsingVr = enableVR; - }, - "Setting MetaPort isUsingVr failed."); + } - internal static void RepositionCohtmlHud(bool enableVR) + internal static void DisableMirrorCanvas(bool intoVR) { - TryCatchWrapper(() => - { - DesktopVRSwitch.Logger.Msg("Configuring new hud affinity for CohtmlHud."); - CohtmlHud.Instance.gameObject.transform.parent = enableVR ? PlayerSetup.Instance.vrCamera.transform : PlayerSetup.Instance.desktopCamera.transform; - CVRTools.ConfigureHudAffinity(); - CohtmlHud.Instance.gameObject.transform.localScale = new Vector3(1.2f, 1f, 1.2f); - }, - "Error parenting CohtmlHud to active camera."); + } - internal static void UpdateHudOperations(bool enableVR) + internal static void SwitchActiveCameraRigs(bool intoVR) { - TryCatchWrapper(() => - { - DesktopVRSwitch.Logger.Msg("Switching HudOperations worldLoadingItem & worldLoadStatus."); - HudOperations.Instance.worldLoadingItem = enableVR ? HudOperations.Instance.worldLoadingItemVr : HudOperations.Instance.worldLoadingItemDesktop; - HudOperations.Instance.worldLoadStatus = enableVR ? HudOperations.Instance.worldLoadStatusVr : HudOperations.Instance.worldLoadStatusDesktop; - }, - "Failed switching HudOperations objects."); + + } - internal static void DisableMirrorCanvas() + internal static void PauseInputInteractions(bool intoVR) { - TryCatchWrapper(() => - { - DesktopVRSwitch.Logger.Msg("Forcing PortableCamera canvas mirroring off."); - //tell the game we are in mirror mode so itll disable it (if enabled) - PortableCamera.Instance.mode = MirroringMode.Mirror; - PortableCamera.Instance.ChangeMirroring(); - }, - "Failed to disable PortableCamera canvas mirroring."); + } - internal static void SwitchActiveCameraRigs(bool enableVR) + internal static void ReloadLocalAvatar(bool intoVR) { - TryCatchWrapper(() => - { - DesktopVRSwitch.Logger.Msg("Switching active PlayerSetup camera rigs. Updating Desktop camera FOV."); - PlayerSetup.Instance.desktopCameraRig.SetActive(!enableVR); - PlayerSetup.Instance.vrCameraRig.SetActive(enableVR); - CVR_DesktopCameraController.UpdateFov(); - //uicamera has script that copies fov from desktop cam - //toggling the cameras on/off resets aspect ratio - //so when rigs switch, that is already handled - }, - "Failed to switch active camera rigs or update Desktop camera FOV."); + } - internal static void PauseInputInteractions(bool toggle) + internal static void UpdateGestureReconizerCam(bool intoVR) { - TryCatchWrapper(() => - { - DesktopVRSwitch.Logger.Msg($"Setting CVRInputManager inputEnabled & CVR_InteractableManager enableInteractions to {!toggle}"); - CVRInputManager.Instance.inputEnabled = !toggle; - CVR_InteractableManager.enableInteractions = !toggle; - }, - "Failed to toggle CVRInputManager inputEnabled & CVR_InteractableManager enableInteractions."); + } - internal static void ResetCVRInputManager() + internal static void UpdateMenuCoreData(bool intoVR) { - TryCatchWrapper(() => - { - DesktopVRSwitch.Logger.Msg("Resetting CVRInputManager inputs."); - //just in case - CVRInputManager.Instance.blockedByUi = false; - //sometimes head can get stuck, so just in case - CVRInputManager.Instance.independentHeadToggle = false; - //just nice to load into desktop with idle gesture - CVRInputManager.Instance.gestureLeft = 0f; - CVRInputManager.Instance.gestureLeftRaw = 0f; - CVRInputManager.Instance.gestureRight = 0f; - CVRInputManager.Instance.gestureRightRaw = 0f; - //turn off finger tracking input - CVRInputManager.Instance.individualFingerTracking = false; - }, - "Failed to reset CVRInputManager inputs."); - } - internal static void ReloadLocalAvatar() - { - TryCatchWrapper(() => - { - DesktopVRSwitch.Logger.Msg("Attempting to reload current local avatar from GUID."); - AssetManagement.Instance.LoadLocalAvatar(MetaPort.Instance.currentAvatarGuid); - }, - "Failed to reload local avatar."); - } - - internal static void UpdateRichPresence() - { - TryCatchWrapper(() => - { - if (MetaPort.Instance.settings.GetSettingsBool("ImplementationRichPresenceDiscordEnabled", true)) - { - DesktopVRSwitch.Logger.Msg("Forcing Discord Rich Presence update."); - MetaPort.Instance.settings.SetSettingsBool("ImplementationRichPresenceDiscordEnabled", false); - MetaPort.Instance.settings.SetSettingsBool("ImplementationRichPresenceDiscordEnabled", true); - } - if (MetaPort.Instance.settings.GetSettingsBool("ImplementationRichPresenceSteamEnabled", true)) - { - DesktopVRSwitch.Logger.Msg("Forcing Steam Rich Presence update."); - MetaPort.Instance.settings.SetSettingsBool("ImplementationRichPresenceSteamEnabled", false); - MetaPort.Instance.settings.SetSettingsBool("ImplementationRichPresenceSteamEnabled", true); - } - }, - "Failed to update Discord & Steam Rich Presence."); - } - - internal static void UpdateGestureReconizerCam() - { - TryCatchWrapper(() => - { - DesktopVRSwitch.Logger.Msg("Updating CVRGestureRecognizer _camera to active camera."); - CVRGestureRecognizer.Instance._camera = PlayerSetup.Instance.GetActiveCamera().GetComponent(); - }, - "Failed to update CVRGestureRecognizer camera."); - } - - internal static void UpdateMenuCoreData(bool enableVR) - { - TryCatchWrapper(() => - { - DesktopVRSwitch.Logger.Msg("Updating CVR_Menu_Data core data."); - CVR_MenuManager.Instance.coreData.core.inVr = enableVR; - }, - "Failed to update CVR_Menu_Data core data."); } } diff --git a/DesktopVRSwitch/Utils.cs b/DesktopVRSwitch/Utils.cs new file mode 100644 index 0000000..626e2af --- /dev/null +++ b/DesktopVRSwitch/Utils.cs @@ -0,0 +1,24 @@ +using ABI_RC.Core.EventSystem; +using ABI_RC.Core.Player; +using ABI_RC.Core.Savior; +using UnityEngine; + +namespace NAK.DesktopVRSwitch; + +internal static class Utils +{ + internal static GameObject GetPlayerCameraObject(bool intoVR) + { + if (intoVR) + { + return PlayerSetup.Instance.vrCamera; + } + return PlayerSetup.Instance.desktopCamera; + } + + internal static void ReloadLocalAvatar() + { + DesktopVRSwitch.Logger.Msg("Attempting to reload current local avatar from GUID."); + AssetManagement.Instance.LoadLocalAvatar(MetaPort.Instance.currentAvatarGuid); + } +} diff --git a/DesktopVRSwitch/VRModeTrackers/CVRGestureRecognizerTracker.cs b/DesktopVRSwitch/VRModeTrackers/CVRGestureRecognizerTracker.cs new file mode 100644 index 0000000..b87a7d7 --- /dev/null +++ b/DesktopVRSwitch/VRModeTrackers/CVRGestureRecognizerTracker.cs @@ -0,0 +1,30 @@ +using ABI_RC.Core.Savior; +using UnityEngine; + +namespace NAK.DesktopVRSwitch.VRModeTrackers; + +public class CVRGestureRecognizerTracker : VRModeTracker +{ + public override void TrackerInit() + { + VRModeSwitchManager.OnPostVRModeSwitch += OnPostSwitch; + } + + public override void TrackerDestroy() + { + VRModeSwitchManager.OnPostVRModeSwitch -= OnPostSwitch; + } + + private void OnPostSwitch(bool intoVR) + { + CVRGestureRecognizer _cvrGestureRecognizer = CVRGestureRecognizer.Instance; + if (_cvrGestureRecognizer == null) + { + DesktopVRSwitch.Logger.Error("Error while getting CVRGestureRecognizer!"); + return; + } + DesktopVRSwitch.Logger.Msg("Updating CVRGestureRecognizer _camera to active camera."); + + _cvrGestureRecognizer._camera = Utils.GetPlayerCameraObject(intoVR).GetComponent(); + } +} \ No newline at end of file diff --git a/DesktopVRSwitch/VRModeTrackers/CVRInputManagerTracker.cs b/DesktopVRSwitch/VRModeTrackers/CVRInputManagerTracker.cs new file mode 100644 index 0000000..7ff3ddc --- /dev/null +++ b/DesktopVRSwitch/VRModeTrackers/CVRInputManagerTracker.cs @@ -0,0 +1,41 @@ +using ABI_RC.Core.Savior; + +namespace NAK.DesktopVRSwitch.VRModeTrackers; + +public class CVRInputManagerTracker : VRModeTracker +{ + public override void TrackerInit() + { + VRModeSwitchManager.OnPostVRModeSwitch += OnPostSwitch; + } + + public override void TrackerDestroy() + { + VRModeSwitchManager.OnPostVRModeSwitch -= OnPostSwitch; + } + + void OnPostSwitch(bool intoVR) + { + CVRInputManager _cvrInputManager = CVRInputManager.Instance; + if (_cvrInputManager == null) + { + DesktopVRSwitch.Logger.Error("Error while getting CVRInputManager!"); + return; + } + DesktopVRSwitch.Logger.Msg("Resetting CVRInputManager inputs."); + + _cvrInputManager.inputEnabled = true; + + //just in case + _cvrInputManager.blockedByUi = false; + //sometimes head can get stuck, so just in case + _cvrInputManager.independentHeadToggle = false; + //just nice to load into desktop with idle gesture + _cvrInputManager.gestureLeft = 0f; + _cvrInputManager.gestureLeftRaw = 0f; + _cvrInputManager.gestureRight = 0f; + _cvrInputManager.gestureRightRaw = 0f; + //turn off finger tracking input + _cvrInputManager.individualFingerTracking = false; + } +} \ No newline at end of file diff --git a/DesktopVRSwitch/VRModeTrackers/CVRPickupObjectTracker.cs b/DesktopVRSwitch/VRModeTrackers/CVRPickupObjectTracker.cs new file mode 100644 index 0000000..42f9fe4 --- /dev/null +++ b/DesktopVRSwitch/VRModeTrackers/CVRPickupObjectTracker.cs @@ -0,0 +1,34 @@ +using ABI.CCK.Components; +using UnityEngine; + +namespace NAK.DesktopVRSwitch.VRModeTrackers; + +public class CVRPickupObjectTracker : MonoBehaviour +{ + private CVRPickupObject _pickupObject; + private Transform _storedGripOrigin; + + public CVRPickupObjectTracker(CVRPickupObject pickupObject, Transform storedGripOrigin) + { + this._pickupObject = pickupObject; + this._storedGripOrigin = storedGripOrigin; + } + + private void OnDestroy() + { + + } + + public void OnPostSwitch(bool intoVR) + { + if (_pickupObject != null) + { + // Drop the object if it is being held locally + if (_pickupObject._controllerRay != null) + _pickupObject._controllerRay.DropObject(true); + + // Swap the grip origins + (_storedGripOrigin, _pickupObject.gripOrigin) = (_pickupObject.gripOrigin, _storedGripOrigin); + } + } +} \ No newline at end of file diff --git a/DesktopVRSwitch/VRModeTrackers/CVR_InteractableManagerTracker.cs b/DesktopVRSwitch/VRModeTrackers/CVR_InteractableManagerTracker.cs new file mode 100644 index 0000000..824d72a --- /dev/null +++ b/DesktopVRSwitch/VRModeTrackers/CVR_InteractableManagerTracker.cs @@ -0,0 +1,29 @@ +using ABI_RC.Core.InteractionSystem; + +namespace NAK.DesktopVRSwitch.VRModeTrackers; + +public class CVR_InteractableManagerTracker : VRModeTracker +{ + public override void TrackerInit() + { + VRModeSwitchManager.OnPostVRModeSwitch += OnPostSwitch; + } + + public override void TrackerDestroy() + { + VRModeSwitchManager.OnPostVRModeSwitch -= OnPostSwitch; + } + + private void OnPostSwitch(bool intoVR) + { + CVR_InteractableManager _cvrInteractableManager = CVR_InteractableManager.Instance; + if (_cvrInteractableManager == null) + { + DesktopVRSwitch.Logger.Error("Error while getting CVR_InteractableManager!"); + return; + } + DesktopVRSwitch.Logger.Msg($"Setting CVRInputManager inputEnabled & CVR_InteractableManager enableInteractions to {!intoVR}"); + + CVR_InteractableManager.enableInteractions = !intoVR; + } +} \ No newline at end of file diff --git a/DesktopVRSwitch/VRModeTrackers/CVR_MenuManagerTracker.cs b/DesktopVRSwitch/VRModeTrackers/CVR_MenuManagerTracker.cs new file mode 100644 index 0000000..dcf18c6 --- /dev/null +++ b/DesktopVRSwitch/VRModeTrackers/CVR_MenuManagerTracker.cs @@ -0,0 +1,44 @@ +using ABI_RC.Core.InteractionSystem; + +namespace NAK.DesktopVRSwitch.VRModeTrackers; + +public class CVR_MenuManagerTracker : VRModeTracker +{ + public override void TrackerInit() + { + VRModeSwitchManager.OnPreVRModeSwitch += OnPreSwitch; + VRModeSwitchManager.OnPostVRModeSwitch += OnPostSwitch; + } + + public override void TrackerDestroy() + { + VRModeSwitchManager.OnPreVRModeSwitch -= OnPreSwitch; + VRModeSwitchManager.OnPostVRModeSwitch -= OnPostSwitch; + } + + private void OnPreSwitch(bool intoVR) + { + CVR_MenuManager _cvrMenuManager = CVR_MenuManager.Instance; + if (_cvrMenuManager == null) + { + DesktopVRSwitch.Logger.Error("Error while getting CVR_MenuManager!"); + return; + } + DesktopVRSwitch.Logger.Msg("Closing CVR_MenuManager - Quick Menu."); + + _cvrMenuManager.ToggleQuickMenu(false); + } + + private void OnPostSwitch(bool intoVR) + { + CVR_MenuManager _cvrMenuManager = CVR_MenuManager.Instance; + if (_cvrMenuManager == null) + { + DesktopVRSwitch.Logger.Error("Error while getting CVR_MenuManager!"); + return; + } + DesktopVRSwitch.Logger.Msg("Updating CVR_Menu_Data core data."); + + _cvrMenuManager.coreData.core.inVr = intoVR; + } +} \ No newline at end of file diff --git a/DesktopVRSwitch/VRModeTrackers/CameraFacingObjectTracker.cs b/DesktopVRSwitch/VRModeTrackers/CameraFacingObjectTracker.cs new file mode 100644 index 0000000..504b76a --- /dev/null +++ b/DesktopVRSwitch/VRModeTrackers/CameraFacingObjectTracker.cs @@ -0,0 +1,27 @@ +using ABI_RC.Core.Util.Object_Behaviour; +using UnityEngine; + +namespace NAK.DesktopVRSwitch.VRModeTrackers; + +public class CameraFacingObjectTracker : MonoBehaviour +{ + private CameraFacingObject _cameraFacingObject; + + public CameraFacingObjectTracker(CameraFacingObject cameraFacingObject) + { + this._cameraFacingObject = cameraFacingObject; + } + + private void OnDestroy() + { + } + + public void OnPreSwitch(bool intoVR) { } + + public void OnFailedSwitch(bool intoVR) { } + + public void OnPostSwitch(bool intoVR) + { + _cameraFacingObject.m_Camera = Utils.GetPlayerCameraObject(intoVR).GetComponent(); + } +} \ No newline at end of file diff --git a/DesktopVRSwitch/VRModeTrackers/CheckVRTracker.cs b/DesktopVRSwitch/VRModeTrackers/CheckVRTracker.cs new file mode 100644 index 0000000..7dfa7e4 --- /dev/null +++ b/DesktopVRSwitch/VRModeTrackers/CheckVRTracker.cs @@ -0,0 +1,29 @@ +using ABI_RC.Core.Savior; + +namespace NAK.DesktopVRSwitch.VRModeTrackers; + +public class CheckVRTracker : VRModeTracker +{ + public override void TrackerInit() + { + VRModeSwitchManager.OnPostVRModeSwitch += OnPostSwitch; + } + + public override void TrackerDestroy() + { + VRModeSwitchManager.OnPostVRModeSwitch -= OnPostSwitch; + } + + private void OnPostSwitch(bool intoVR) + { + CheckVR _checkVR = CheckVR.Instance; + if (_checkVR == null) + { + DesktopVRSwitch.Logger.Error("Error while getting CheckVR!"); + return; + } + DesktopVRSwitch.Logger.Msg($"Setting CheckVR hasVrDeviceLoaded to {intoVR}."); + + _checkVR.hasVrDeviceLoaded = intoVR; + } +} \ No newline at end of file diff --git a/DesktopVRSwitch/VRModeTrackers/CohtmlHudTracker.cs b/DesktopVRSwitch/VRModeTrackers/CohtmlHudTracker.cs new file mode 100644 index 0000000..e58baef --- /dev/null +++ b/DesktopVRSwitch/VRModeTrackers/CohtmlHudTracker.cs @@ -0,0 +1,34 @@ +using ABI_RC.Core.Player; +using ABI_RC.Core.UI; +using UnityEngine; + +namespace NAK.DesktopVRSwitch.VRModeTrackers; + +public class CohtmlHudTracker : VRModeTracker +{ + public override void TrackerInit() + { + VRModeSwitchManager.OnPostVRModeSwitch += OnPostSwitch; + } + + public override void TrackerDestroy() + { + VRModeSwitchManager.OnPostVRModeSwitch -= OnPostSwitch; + } + + private void OnPostSwitch(bool intoVR) + { + CohtmlHud _cohtmlHud = CohtmlHud.Instance; + if (_cohtmlHud == null) + { + DesktopVRSwitch.Logger.Error("Error while getting CohtmlHud!"); + return; + } + DesktopVRSwitch.Logger.Msg("Configuring new hud affinity for CohtmlHud."); + + _cohtmlHud.gameObject.transform.parent = intoVR ? PlayerSetup.Instance.vrCamera.transform : PlayerSetup.Instance.desktopCamera.transform; + // This handles rotation and position + ABI_RC.Core.CVRTools.ConfigureHudAffinity(); + _cohtmlHud.gameObject.transform.localScale = new Vector3(1.2f, 1f, 1.2f); + } +} \ No newline at end of file diff --git a/DesktopVRSwitch/VRModeTrackers/HudOperationsTracker.cs b/DesktopVRSwitch/VRModeTrackers/HudOperationsTracker.cs new file mode 100644 index 0000000..f25a03a --- /dev/null +++ b/DesktopVRSwitch/VRModeTrackers/HudOperationsTracker.cs @@ -0,0 +1,30 @@ +using ABI_RC.Core.Player; + +namespace NAK.DesktopVRSwitch.VRModeTrackers; + +public class HudOperationsTracker : VRModeTracker +{ + public override void TrackerInit() + { + VRModeSwitchManager.OnPostVRModeSwitch += OnPostSwitch; + } + + public override void TrackerDestroy() + { + VRModeSwitchManager.OnPostVRModeSwitch -= OnPostSwitch; + } + + private void OnPostSwitch(bool intoVR) + { + HudOperations _hudOperations = HudOperations.Instance; + if (_hudOperations == null) + { + DesktopVRSwitch.Logger.Error("Error while getting HudOperations!"); + return; + } + DesktopVRSwitch.Logger.Msg("Switching HudOperations worldLoadingItem & worldLoadStatus."); + + _hudOperations.worldLoadingItem = intoVR ? _hudOperations.worldLoadingItemVr : _hudOperations.worldLoadingItemDesktop; + _hudOperations.worldLoadStatus = intoVR ? _hudOperations.worldLoadStatusVr : _hudOperations.worldLoadStatusDesktop; + } +} \ No newline at end of file diff --git a/DesktopVRSwitch/VRModeTrackers/IKSystemTracker.cs b/DesktopVRSwitch/VRModeTrackers/IKSystemTracker.cs new file mode 100644 index 0000000..9e3a300 --- /dev/null +++ b/DesktopVRSwitch/VRModeTrackers/IKSystemTracker.cs @@ -0,0 +1,87 @@ +using ABI_RC.Systems.IK; +using ABI_RC.Systems.IK.SubSystems; +using ABI_RC.Systems.IK.TrackingModules; + +namespace NAK.DesktopVRSwitch.VRModeTrackers; + +public class IKSystemTracker : VRModeTracker +{ + public override void TrackerInit() + { + VRModeSwitchManager.OnPreVRModeSwitch += OnPreSwitch; + VRModeSwitchManager.OnFailVRModeSwitch += OnFailedSwitch; + VRModeSwitchManager.OnPostVRModeSwitch += OnPostSwitch; + } + + public override void TrackerDestroy() + { + VRModeSwitchManager.OnPreVRModeSwitch -= OnPreSwitch; + VRModeSwitchManager.OnFailVRModeSwitch -= OnFailedSwitch; + VRModeSwitchManager.OnPostVRModeSwitch -= OnPostSwitch; + } + + private void OnPreSwitch(bool intoVR) + { + BodySystem.TrackingEnabled = false; + BodySystem.TrackingPositionWeight = 0f; + BodySystem.TrackingLocomotionEnabled = false; + + if (IKSystem.vrik != null) + IKSystem.vrik.enabled = false; + } + + private void OnFailedSwitch(bool intoVR) + { + BodySystem.TrackingEnabled = true; + BodySystem.TrackingPositionWeight = 1f; + BodySystem.TrackingLocomotionEnabled = true; + + if (IKSystem.vrik != null) + IKSystem.vrik.enabled = true; + } + + private void OnPostSwitch(bool intoVR) + { + if (IKSystem.vrik != null) + UnityEngine.Object.DestroyImmediate(IKSystem.vrik); + + // Make sure you are fully tracking + BodySystem.TrackingEnabled = true; + BodySystem.TrackingPositionWeight = 1f; + BodySystem.TrackingLocomotionEnabled = true; + BodySystem.isCalibratedAsFullBody = false; + BodySystem.isCalibrating = false; + BodySystem.isRecalibration = false; + + // Make it so you don't instantly end up in FBT from Desktop + IKSystem.firstAvatarLoaded = DesktopVRSwitch.EntryEnterCalibrationOnSwitch.Value; + + // Turn off finger tracking just in case the user switched controllers + if (IKSystem.Instance != null) + IKSystem.Instance.FingerSystem.controlActive = false; + + SetupSteamVRTrackingModule(intoVR); + } + + private void SetupSteamVRTrackingModule(bool enableVR) + { + var openVRModule = IKSystem.Instance._trackingModules.OfType().FirstOrDefault(); + + if (openVRModule != null) + { + if (enableVR) + { + openVRModule.ModuleStart(); + } + else + { + openVRModule.ModuleDestroy(); + } + } + else if (enableVR) + { + var newVRModule = new SteamVRTrackingModule(); + IKSystem.Instance.AddTrackingModule(newVRModule); + } + } +} \ No newline at end of file diff --git a/DesktopVRSwitch/VRModeTrackers/MetaPortTracker.cs b/DesktopVRSwitch/VRModeTrackers/MetaPortTracker.cs new file mode 100644 index 0000000..d767221 --- /dev/null +++ b/DesktopVRSwitch/VRModeTrackers/MetaPortTracker.cs @@ -0,0 +1,44 @@ +using ABI_RC.Core.Savior; + +namespace NAK.DesktopVRSwitch.VRModeTrackers; + +public class MetaPortTracker : VRModeTracker +{ + public override void TrackerInit() + { + VRModeSwitchManager.OnPostVRModeSwitch += OnPostSwitch; + } + + public override void TrackerDestroy() + { + VRModeSwitchManager.OnPostVRModeSwitch -= OnPostSwitch; + } + + private void OnPostSwitch(bool intoVR) + { + MetaPort _metaPort = MetaPort.Instance; + if (_metaPort == null) + { + DesktopVRSwitch.Logger.Error("Error while getting MetaPort!"); + return; + } + DesktopVRSwitch.Logger.Msg($"Setting MetaPort isUsingVr to {intoVR}."); + + // Main thing most of the game checks for if using VR + _metaPort.isUsingVr = intoVR; + + // Hacky way of updating rich presence + if (_metaPort.settings.GetSettingsBool("ImplementationRichPresenceDiscordEnabled", true)) + { + DesktopVRSwitch.Logger.Msg("Forcing Discord Rich Presence update."); + _metaPort.settings.SetSettingsBool("ImplementationRichPresenceDiscordEnabled", false); + _metaPort.settings.SetSettingsBool("ImplementationRichPresenceDiscordEnabled", true); + } + if (_metaPort.settings.GetSettingsBool("ImplementationRichPresenceSteamEnabled", true)) + { + DesktopVRSwitch.Logger.Msg("Forcing Steam Rich Presence update."); + _metaPort.settings.SetSettingsBool("ImplementationRichPresenceSteamEnabled", false); + _metaPort.settings.SetSettingsBool("ImplementationRichPresenceSteamEnabled", true); + } + } +} \ No newline at end of file diff --git a/DesktopVRSwitch/VRModeTrackers/MovementSystemTracker.cs b/DesktopVRSwitch/VRModeTrackers/MovementSystemTracker.cs new file mode 100644 index 0000000..a704162 --- /dev/null +++ b/DesktopVRSwitch/VRModeTrackers/MovementSystemTracker.cs @@ -0,0 +1,48 @@ +using ABI_RC.Systems.MovementSystem; +using UnityEngine; + +namespace NAK.DesktopVRSwitch.VRModeTrackers; + +public class MovementSystemTracker : VRModeTracker +{ + private MovementSystem _movementSystem; + private Vector3 preSwitchWorldPosition; + private Quaternion preSwitchWorldRotation; + + public override void TrackerInit() + { + VRModeSwitchManager.OnPreVRModeSwitch += OnPreSwitch; + VRModeSwitchManager.OnPostVRModeSwitch += OnPostSwitch; + } + + public override void TrackerDestroy() + { + VRModeSwitchManager.OnPreVRModeSwitch -= OnPreSwitch; + VRModeSwitchManager.OnPostVRModeSwitch -= OnPostSwitch; + } + + private void OnPreSwitch(bool intoVR) + { + _movementSystem = MovementSystem.Instance; + + Vector3 position = _movementSystem.rotationPivot.transform.position; + position.y = _movementSystem.transform.position.y; + preSwitchWorldPosition = position; + preSwitchWorldRotation = _movementSystem.rotationPivot.transform.rotation; + + _movementSystem.ChangeCrouch(false); + _movementSystem.ChangeProne(false); + } + + private void OnPostSwitch(bool intoVR) + { + _movementSystem.rotationPivot = Utils.GetPlayerCameraObject(intoVR).transform; + _movementSystem.TeleportToPosRot(preSwitchWorldPosition, preSwitchWorldRotation, false); + + if (!intoVR) + _movementSystem.UpdateColliderCenter(_movementSystem.transform.position); + + _movementSystem.ChangeCrouch(false); + _movementSystem.ChangeProne(false); + } +} \ No newline at end of file diff --git a/DesktopVRSwitch/VRModeTrackers/PlayerSetupTracker.cs b/DesktopVRSwitch/VRModeTrackers/PlayerSetupTracker.cs new file mode 100644 index 0000000..675a41d --- /dev/null +++ b/DesktopVRSwitch/VRModeTrackers/PlayerSetupTracker.cs @@ -0,0 +1,38 @@ +using ABI_RC.Core.Player; + +namespace NAK.DesktopVRSwitch.VRModeTrackers; + +public class PlayerSetupTracker : VRModeTracker +{ + public override void TrackerInit() + { + VRModeSwitchManager.OnPostVRModeSwitch += OnPostSwitch; + } + + public override void TrackerDestroy() + { + VRModeSwitchManager.OnPostVRModeSwitch -= OnPostSwitch; + } + + private void OnPostSwitch(bool intoVR) + { + PlayerSetup _playerSetup = PlayerSetup.Instance; + if (_playerSetup == null) + { + DesktopVRSwitch.Logger.Error("Error while getting PlayerSetup!"); + return; + } + DesktopVRSwitch.Logger.Msg("Switching active PlayerSetup camera rigs. Updating Desktop camera FOV."); + + _playerSetup.desktopCameraRig.SetActive(!intoVR); + _playerSetup.vrCameraRig.SetActive(intoVR); + + // This might error if we started in VR. + // '_cam' is not set until Start(). + CVR_DesktopCameraController.UpdateFov(); + + // UICamera has a script that copies the FOV from the desktop cam. + // Toggling the cameras on/off resets the aspect ratio, + // so when rigs switch, that is already handled. + } +} \ No newline at end of file diff --git a/DesktopVRSwitch/VRModeTrackers/PortableCameraTracker.cs b/DesktopVRSwitch/VRModeTrackers/PortableCameraTracker.cs new file mode 100644 index 0000000..f2a616e --- /dev/null +++ b/DesktopVRSwitch/VRModeTrackers/PortableCameraTracker.cs @@ -0,0 +1,31 @@ +using ABI_RC.Systems.Camera; + +namespace NAK.DesktopVRSwitch.VRModeTrackers; + +public class PortableCameraTracker : VRModeTracker +{ + public override void TrackerInit() + { + VRModeSwitchManager.OnPostVRModeSwitch += OnPostSwitch; + } + + public override void TrackerDestroy() + { + VRModeSwitchManager.OnPostVRModeSwitch -= OnPostSwitch; + } + + private void OnPostSwitch(bool intoVR) + { + PortableCamera _portableCamera = PortableCamera.Instance; + if (_portableCamera == null) + { + DesktopVRSwitch.Logger.Error("Error while getting PortableCamera!"); + return; + } + DesktopVRSwitch.Logger.Msg("Forcing PortableCamera canvas mirroring off."); + + // Tell the game we are in mirror mode so it'll disable it (if enabled) + _portableCamera.mode = MirroringMode.Mirror; + _portableCamera.ChangeMirroring(); + } +} diff --git a/DesktopVRSwitch/VRModeTrackers/VRModeSwitchManager.cs b/DesktopVRSwitch/VRModeTrackers/VRModeSwitchManager.cs new file mode 100644 index 0000000..d5864de --- /dev/null +++ b/DesktopVRSwitch/VRModeTrackers/VRModeSwitchManager.cs @@ -0,0 +1,185 @@ +using ABI_RC.Systems.UI; +using System.Collections; +using UnityEngine; +using UnityEngine.Events; +using UnityEngine.XR; +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.VRModeTrackers; + +public class VRModeSwitchManager : MonoBehaviour +{ + public static VRModeSwitchManager Instance { get; private set; } + + // I don't think I *need* this. Only using cause I don't want stuff just floating off. + private static readonly List _vrModeTrackers = new List(); + + public static event UnityAction OnPreVRModeSwitch; + public static event UnityAction OnPostVRModeSwitch; + public static event UnityAction OnFailVRModeSwitch; + + public static void RegisterVRModeTracker(VRModeTracker observer) + { + _vrModeTrackers.Add(observer); + observer.TrackerInit(); + } + + public static void UnregisterVRModeTracker(VRModeTracker observer) + { + _vrModeTrackers.Remove(observer); + observer.TrackerDestroy(); + } + + // Settings + private bool _useWorldTransition = true; + private bool _reloadLocalAvatar = true; + + // Internal + private bool _switchInProgress = false; + + void Awake() + { + if (Instance != null) + { + DestroyImmediate(this); + return; + } + + Instance = this; + } + + public void StartSwitch() + { + StartCoroutine(StartSwitchCoroutine()); + } + + private IEnumerator StartSwitchCoroutine() + { + if (_switchInProgress) + { + yield break; + } + _switchInProgress = true; + yield return null; + + + if (_useWorldTransition) // start visual transition and wait for it to complete + yield return WorldTransitionSystem.Instance.StartTransitionCoroutine(); + + // Check if OpenVR is running + bool isUsingVr = IsInVR(); + + InvokeOnPreSwitch(isUsingVr); + + // Start switch + if (!isUsingVr) + { + yield return StartCoroutine(StartOpenVR()); + } + else + { + yield return StartCoroutine(StopOpenVR()); + } + + // Check for updated VR mode + if (isUsingVr != IsInVR()) + { + InvokeOnPostSwitch(!isUsingVr); + + // reload the local avatar + // only reload on success + if (_reloadLocalAvatar) + Utils.ReloadLocalAvatar(); + } + else + { + InvokeOnFailedSwitch(!isUsingVr); + } + + if (_useWorldTransition) // finish the visual transition and wait + yield return WorldTransitionSystem.Instance.ContinueTransitionCoroutine(); + + _switchInProgress = false; + yield break; + } + + private void SafeInvokeUnityEvent(UnityAction switchEvent, bool isUsingVr) + { + try + { + switchEvent.Invoke(isUsingVr); + } + catch (Exception e) + { + Debug.Log($"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 IsInVR() => XRSettings.enabled; + + private IEnumerator StartOpenVR() + { + XRSettings.LoadDeviceByName("OpenVR"); + yield return null; //wait a frame before checking + + if (!string.IsNullOrEmpty(XRSettings.loadedDeviceName)) + { + DesktopVRSwitch.Logger.Msg("Starting SteamVR..."); + XRSettings.enabled = true; + SteamVR_Input.Initialize(true); + yield return null; + yield break; + } + + DesktopVRSwitch.Logger.Error("Initializing VR Failed. Is there no VR device connected?"); + yield return null; + yield break; + } + + private IEnumerator StopOpenVR() + { + SteamVR_Behaviour.instance.enabled = false; + + yield return null; + + if (!string.IsNullOrEmpty(XRSettings.loadedDeviceName)) + { + SteamVR_Input.actionSets[0].Deactivate(SteamVR_Input_Sources.Any); + XRSettings.LoadDeviceByName(""); + XRSettings.enabled = false; + + yield return null; + yield break; + } + + DesktopVRSwitch.Logger.Error("Attempted to exit VR without a VR device loaded."); + yield return null; + yield break; + } +} \ No newline at end of file diff --git a/DesktopVRSwitch/VRModeTrackers/VRModeTracker.cs b/DesktopVRSwitch/VRModeTrackers/VRModeTracker.cs new file mode 100644 index 0000000..3b8ede8 --- /dev/null +++ b/DesktopVRSwitch/VRModeTrackers/VRModeTracker.cs @@ -0,0 +1,7 @@ +namespace NAK.DesktopVRSwitch.VRModeTrackers; + +public class VRModeTracker +{ + public virtual void TrackerInit() { } + public virtual void TrackerDestroy() { } +} diff --git a/DesktopVRSwitch/VRModeTrackers/VRTrackerManagerTracker.cs b/DesktopVRSwitch/VRModeTrackers/VRTrackerManagerTracker.cs new file mode 100644 index 0000000..cbe079c --- /dev/null +++ b/DesktopVRSwitch/VRModeTrackers/VRTrackerManagerTracker.cs @@ -0,0 +1,32 @@ +using ABI_RC.Core.Player; + +namespace NAK.DesktopVRSwitch.VRModeTrackers; + +public class VRTrackerManagerTracker : VRModeTracker +{ + public override void TrackerInit() + { + VRModeSwitchManager.OnPostVRModeSwitch += OnPostSwitch; + } + + public override void TrackerDestroy() + { + VRModeSwitchManager.OnPostVRModeSwitch -= OnPostSwitch; + } + + private void OnPostSwitch(bool intoVR) + { + VRTrackerManager _vrTrackerManager = VRTrackerManager.Instance; + if (_vrTrackerManager == null) + { + DesktopVRSwitch.Logger.Error("Error while getting VRTrackerManager!"); + return; + } + DesktopVRSwitch.Logger.Msg($"Resetting VRTrackerManager."); + + _vrTrackerManager.poses = null; + _vrTrackerManager.leftHand = null; + _vrTrackerManager.rightHand = null; + _vrTrackerManager.hasCheckedForKnuckles = false; + } +} \ No newline at end of file diff --git a/DesktopVRSwitch/VRModeTrackers/ViewManagerTracker.cs b/DesktopVRSwitch/VRModeTrackers/ViewManagerTracker.cs new file mode 100644 index 0000000..1014b4d --- /dev/null +++ b/DesktopVRSwitch/VRModeTrackers/ViewManagerTracker.cs @@ -0,0 +1,29 @@ +using ABI_RC.Core.InteractionSystem; + +namespace NAK.DesktopVRSwitch.VRModeTrackers; + +public class ViewManagerTracker : VRModeTracker +{ + public override void TrackerInit() + { + VRModeSwitchManager.OnPreVRModeSwitch += OnPreSwitch; + } + + public override void TrackerDestroy() + { + VRModeSwitchManager.OnPreVRModeSwitch -= OnPreSwitch; + } + + public void OnPreSwitch(bool intoVR) + { + ViewManager _viewManager = ViewManager.Instance; + if (_viewManager == null) + { + DesktopVRSwitch.Logger.Error("Error while getting ViewManager!"); + return; + } + DesktopVRSwitch.Logger.Msg("Closing ViewManager - Main Menu."); + + _viewManager.UiStateToggle(false); + } +} \ No newline at end of file