[DesktopVRSwitch] Minor changes

This commit is contained in:
NotAKidoS 2023-08-03 00:05:45 -05:00
parent 6d17085f21
commit 4c09f9bd57
25 changed files with 359 additions and 205 deletions

View file

@ -1,2 +1,11 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk" /> <Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<Reference Include="BTKUILib">
<HintPath>$(MsBuildThisFileDirectory)\..\.ManagedLibs\BTKUILib.dll</HintPath>
<Private>False</Private>
</Reference>
</ItemGroup>
</Project>

View file

@ -3,6 +3,8 @@ using ABI_RC.Core.Savior;
using ABI_RC.Core.Util.Object_Behaviour; using ABI_RC.Core.Util.Object_Behaviour;
using ABI_RC.Systems.IK; using ABI_RC.Systems.IK;
using ABI_RC.Systems.IK.TrackingModules; using ABI_RC.Systems.IK.TrackingModules;
using cohtml;
using cohtml.Net;
using HarmonyLib; using HarmonyLib;
using NAK.DesktopVRSwitch.Patches; using NAK.DesktopVRSwitch.Patches;
using NAK.DesktopVRSwitch.VRModeTrackers; 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 internal class SteamVRBehaviourPatches
{ {
[HarmonyPrefix] [HarmonyPrefix]
[HarmonyPatch(typeof(SteamVR_Behaviour), nameof(SteamVR_Behaviour.OnQuit))] [HarmonyPatch(typeof(SteamVR_Behaviour), nameof(SteamVR_Behaviour.OnQuit))]
private static bool Prefix_SteamVR_Behaviour_OnQuit() private static bool Prefix_SteamVR_Behaviour_OnQuit()
{ {
if (!DesktopVRSwitch.EntrySwitchToDesktopOnExit.Value) if (!ModSettings.EntrySwitchToDesktopOnExit.Value)
return true; return true;
// If we don't switch fast enough, SteamVR will force close. // If we don't switch fast enough, SteamVR will force close.

View file

@ -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<bool> entry)
{
category.AddToggle(entry.DisplayName, entry.Description, entry.Value).OnValueUpdated += b => entry.Value = b;
}
private static void AddMelonSlider(ref Page page, MelonLoader.MelonPreferences_Entry<float> 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
}

View file

@ -9,21 +9,6 @@ public class DesktopVRSwitch : MelonMod
{ {
internal static MelonLogger.Instance Logger; internal static MelonLogger.Instance Logger;
public static readonly MelonPreferences_Category Category =
MelonPreferences.CreateCategory(nameof(DesktopVRSwitch));
public static readonly MelonPreferences_Entry<bool> 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<bool> EntryUseTransitionOnSwitch =
Category.CreateEntry("Use Transition on Switch", true, description: "Should the world transition play on VRMode switch?");
//public static readonly MelonPreferences_Entry<bool> 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<bool> EntrySwitchToDesktopOnExit =
Category.CreateEntry("Switch to Desktop on SteamVR Exit", false, description: "Should the game switch to Desktop when SteamVR quits?");
public override void OnInitializeMelon() public override void OnInitializeMelon()
{ {
Logger = LoggerInstance; Logger = LoggerInstance;
@ -41,8 +26,13 @@ public class DesktopVRSwitch : MelonMod
// post processing fixes // post processing fixes
ApplyPatches(typeof(HarmonyPatches.CVRWorldPatches)); ApplyPatches(typeof(HarmonyPatches.CVRWorldPatches));
// fuck you
ApplyPatches(typeof(HarmonyPatches.CohtmlUISystemPatches));
// prevent steamvr behaviour from closing game // prevent steamvr behaviour from closing game
ApplyPatches(typeof(HarmonyPatches.SteamVRBehaviourPatches)); ApplyPatches(typeof(HarmonyPatches.SteamVRBehaviourPatches));
InitializeIntegration("BTKUILib", Integrations.BTKUIAddon.Initialize);
} }
public override void OnUpdate() public override void OnUpdate()
@ -84,6 +74,15 @@ public class DesktopVRSwitch : MelonMod
VRModeSwitchManager.RegisterVRModeTracker(new CVRWorldTracker()); 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) private void ApplyPatches(Type type)
{ {
try try

View file

@ -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<bool> 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<bool> EntryUseTransitionOnSwitch =
Category.CreateEntry("Use Transition on Switch", true, description: "Should the world transition play on VRMode switch?");
public static readonly MelonPreferences_Entry<bool> EntrySwitchToDesktopOnExit =
Category.CreateEntry("Switch to Desktop on SteamVR Exit", false, description: "Should the game switch to Desktop when SteamVR quits?");
}

View file

@ -9,7 +9,7 @@ using UnityEngine.Rendering.PostProcessing;
namespace NAK.DesktopVRSwitch.Patches; namespace NAK.DesktopVRSwitch.Patches;
internal class ReferenceCameraPatch internal static class ReferenceCameraPatch
{ {
public static void OnWorldLoad() public static void OnWorldLoad()
{ {
@ -31,13 +31,15 @@ internal class ReferenceCameraPatch
inactiveCam.depthTextureMode = activeCam.depthTextureMode; inactiveCam.depthTextureMode = activeCam.depthTextureMode;
// We cant copy this because we set it to 0 with ThirdPerson // We cant copy this because we set it to 0 with ThirdPerson
inactiveCam.cullingMask &= -32769; var cullingMask = inactiveCam.cullingMask;
inactiveCam.cullingMask |= 256; cullingMask &= -32769;
inactiveCam.cullingMask |= 512; cullingMask |= 256;
inactiveCam.cullingMask |= 32; cullingMask |= 512;
inactiveCam.cullingMask &= -4097; cullingMask |= 32;
inactiveCam.cullingMask |= 1024; cullingMask &= -4097;
inactiveCam.cullingMask |= 8192; cullingMask |= 1024;
cullingMask |= 8192;
inactiveCam.cullingMask = cullingMask;
// Copy post processing if added // Copy post processing if added
PostProcessLayer ppLayerActiveCam = activeCam.GetComponent<PostProcessLayer>(); PostProcessLayer ppLayerActiveCam = activeCam.GetComponent<PostProcessLayer>();

View file

@ -2,47 +2,22 @@
using NAK.DesktopVRSwitch.VRModeTrackers; using NAK.DesktopVRSwitch.VRModeTrackers;
using System.Collections; using System.Collections;
using UnityEngine; using UnityEngine;
using UnityEngine.Events;
using UnityEngine.XR;
using UnityEngine.XR.Management; 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; namespace NAK.DesktopVRSwitch;
public class VRModeSwitchManager : MonoBehaviour public class VRModeSwitchManager : MonoBehaviour
{ {
#region Static
public static VRModeSwitchManager Instance { get; private set; } public static VRModeSwitchManager Instance { get; private set; }
// I don't think I *need* this. Only using cause I don't want stuff just existing. public static void RegisterVRModeTracker(VRModeTracker observer) => observer.TrackerInit();
private static readonly List<VRModeTracker> _vrModeTrackers = new List<VRModeTracker>(); public static void UnregisterVRModeTracker(VRModeTracker observer) => observer.TrackerDestroy();
public static event UnityAction<bool> OnPreVRModeSwitch; #endregion
public static event UnityAction<bool> OnPostVRModeSwitch;
public static event UnityAction<bool> OnFailVRModeSwitch;
private const string XRSETTINGS_DEVICE = "OpenVR";
public static void RegisterVRModeTracker(VRModeTracker observer) #region Variables
{
_vrModeTrackers.Add(observer);
observer.TrackerInit();
}
public static void UnregisterVRModeTracker(VRModeTracker observer)
{
_vrModeTrackers.Remove(observer);
observer.TrackerDestroy();
}
// Settings // Settings
public bool UseWorldTransition = true; public bool UseWorldTransition = true;
@ -50,6 +25,10 @@ public class VRModeSwitchManager : MonoBehaviour
public bool SwitchInProgress { get; private set; } public bool SwitchInProgress { get; private set; }
#endregion
#region Unity Methods
private void Awake() private void Awake()
{ {
if (Instance != null) if (Instance != null)
@ -60,125 +39,120 @@ public class VRModeSwitchManager : MonoBehaviour
Instance = this; Instance = this;
} }
public void AttemptSwitch() #endregion
{
StartCoroutine(StartSwitchCoroutine());
}
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; yield break;
}
SwitchInProgress = true; SwitchInProgress = true;
yield return null; yield return null;
if (UseWorldTransition) if (UseWorldTransition)
{ // start visual transition and wait for it to complete yield return StartCoroutine(StartTransition());
WorldTransitionSystem.Instance.StartTransition();
yield return new WaitForSeconds(WorldTransitionSystem.Instance.CurrentInLength);
}
// Check if OpenVR is running
bool isUsingVr = IsInXR(); bool isUsingVr = IsInXR();
InvokeOnPreSwitch(isUsingVr); InvokeOnPreSwitch(isUsingVr);
// Start switch yield return StartCoroutine(XRAndReloadAvatar(!isUsingVr));
if (!isUsingVr)
yield return StartCoroutine(StartXR());
else
StopXR();
// Check for updated VR mode if (UseWorldTransition)
if (isUsingVr != IsInXR()) yield return StartCoroutine(ContinueTransition());
SwitchInProgress = false;
}
private IEnumerator XRAndReloadAvatar(bool start)
{ {
// reload the local avatar yield return StartCoroutine(start ? XRHandler.StartXR() : XRHandler.StopXR());
if (ReloadLocalAvatar)
bool isUsingVr = IsInXR();
if (isUsingVr == start)
{ {
ReloadAvatar();
InvokeOnPostSwitch(start);
}
else
{
InvokeOnFailedSwitch(start);
}
}
private void ReloadAvatar()
{
if (!ReloadLocalAvatar)
return;
Utils.ClearLocalAvatar(); Utils.ClearLocalAvatar();
Utils.ReloadLocalAvatar(); Utils.ReloadLocalAvatar();
} }
InvokeOnPostSwitch(!isUsingVr); #endregion
}
else #region Transition Coroutines
private IEnumerator StartTransition()
{ {
InvokeOnFailedSwitch(!isUsingVr); if (WorldTransitionSystem.Instance == null) yield break;
WorldTransitionSystem.Instance.StartTransition();
yield return new WaitForSeconds(WorldTransitionSystem.Instance.CurrentInLength);
} }
if (UseWorldTransition) private IEnumerator ContinueTransition()
{ // would be cool to have out length {
if (WorldTransitionSystem.Instance == null) yield break;
WorldTransitionSystem.Instance.ContinueTransition(); WorldTransitionSystem.Instance.ContinueTransition();
yield return new WaitForSeconds(WorldTransitionSystem.Instance.CurrentInLength); yield return new WaitForSeconds(WorldTransitionSystem.Instance.CurrentInLength);
} }
SwitchInProgress = false; #endregion
yield break;
#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;
}
} }
private void SafeInvokeUnityEvent(UnityAction<bool> switchEvent, bool isUsingVr) public static event EventHandler<VRModeEventArgs> OnPreVRModeSwitch;
public static event EventHandler<VRModeEventArgs> OnPostVRModeSwitch;
public static event EventHandler<VRModeEventArgs> 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<VRModeEventArgs> switchEvent, bool isUsingVr)
{ {
try try
{ {
switchEvent.Invoke(isUsingVr); var playerCamera = Utils.GetPlayerCameraObject(isUsingVr).GetComponent<Camera>();
switchEvent?.Invoke(this, new VRModeEventArgs(isUsingVr, playerCamera));
} }
catch (Exception e) catch (Exception e)
{ {
Debug.Log($"Error in event handler: {e}"); DesktopVRSwitch.Logger.Error($"Error in event handler: {e}");
} }
} }
private void InvokeOnPreSwitch(bool isUsingVr) #endregion
{
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()
}
} }

View file

@ -15,10 +15,10 @@ public class CVRGestureRecognizerTracker : VRModeTracker
VRModeSwitchManager.OnPostVRModeSwitch -= OnPostSwitch; 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."); DesktopVRSwitch.Logger.Msg("Updating CVRGestureRecognizer _camera to active camera.");
CVRGestureRecognizer.Instance._camera = Utils.GetPlayerCameraObject(intoVR).GetComponent<Camera>(); CVRGestureRecognizer.Instance._camera = args.PlayerCamera;
} }
} }

View file

@ -16,14 +16,14 @@ public class CVRInputManagerTracker : VRModeTracker
VRModeSwitchManager.OnPostVRModeSwitch -= OnPostSwitch; VRModeSwitchManager.OnPostVRModeSwitch -= OnPostSwitch;
} }
private void OnPostSwitch(bool intoVR) private void OnPostSwitch(object sender, VRModeSwitchManager.VRModeEventArgs args)
{ {
DesktopVRSwitch.Logger.Msg("Resetting CVRInputManager inputs."); DesktopVRSwitch.Logger.Msg("Resetting CVRInputManager inputs.");
CVRInputManager.Instance.inputEnabled = true; CVRInputManager.Instance.inputEnabled = true;
// IM CRYING // IM CRYING
CVRInputManager.Instance.reload = true; //CVRInputManager.Instance.reload = true;
//just in case //just in case
CVRInputManager.Instance.textInputFocused = false; CVRInputManager.Instance.textInputFocused = false;
@ -42,6 +42,6 @@ public class CVRInputManagerTracker : VRModeTracker
CVRInputManager.Instance.AddInputModule(CVRInputManager._moduleXR = new CVRInputModule_XR()); CVRInputManager.Instance.AddInputModule(CVRInputManager._moduleXR = new CVRInputModule_XR());
//enable xr input or whatnot //enable xr input or whatnot
CVRInputManager._moduleXR.InputEnabled = intoVR; CVRInputManager._moduleXR.InputEnabled = args.IsUsingVr;
} }
} }

View file

@ -18,7 +18,7 @@ public class CVRPickupObjectTracker : MonoBehaviour
VRModeSwitchManager.OnPostVRModeSwitch -= OnPostSwitch; VRModeSwitchManager.OnPostVRModeSwitch -= OnPostSwitch;
} }
public void OnPostSwitch(bool intoVR) public void OnPostSwitch(object sender, VRModeSwitchManager.VRModeEventArgs args)
{ {
if (_pickupObject != null) if (_pickupObject != null)
{ {

View file

@ -17,7 +17,7 @@ public class CVRWorldTracker : VRModeTracker
VRModeSwitchManager.OnPostVRModeSwitch -= OnPostSwitch; 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."); DesktopVRSwitch.Logger.Msg("Configuring CVRWorld. Updating PostProcessing & DesktopCameraController FOV settings.");

View file

@ -14,10 +14,10 @@ public class CVR_InteractableManagerTracker : VRModeTracker
VRModeSwitchManager.OnPostVRModeSwitch -= OnPostSwitch; 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;
} }
} }

View file

@ -17,18 +17,18 @@ public class CVR_MenuManagerTracker : VRModeTracker
VRModeSwitchManager.OnPostVRModeSwitch -= OnPostSwitch; VRModeSwitchManager.OnPostVRModeSwitch -= OnPostSwitch;
} }
private void OnPreSwitch(bool intoVR) private void OnPreSwitch(object sender, VRModeSwitchManager.VRModeEventArgs args)
{ {
DesktopVRSwitch.Logger.Msg("Closing CVR_MenuManager - Quick Menu."); DesktopVRSwitch.Logger.Msg("Closing CVR_MenuManager - Quick Menu.");
CVR_MenuManager.Instance.ToggleQuickMenu(false); 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."); 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.localPosition = Vector3.zero;
CVR_MenuManager.Instance.quickMenu.transform.localRotation = Quaternion.identity; CVR_MenuManager.Instance.quickMenu.transform.localRotation = Quaternion.identity;
} }

View file

@ -18,9 +18,8 @@ public class CameraFacingObjectTracker : MonoBehaviour
VRModeSwitchManager.OnPostVRModeSwitch -= OnPostSwitch; VRModeSwitchManager.OnPostVRModeSwitch -= OnPostSwitch;
} }
public void OnPostSwitch(bool intoVR) public void OnPostSwitch(object sender, VRModeSwitchManager.VRModeEventArgs args)
{ {
// TODO: cache camera _cameraFacingObject.m_Camera = args.PlayerCamera;
_cameraFacingObject.m_Camera = Utils.GetPlayerCameraObject(intoVR).GetComponent<Camera>();
} }
} }

View file

@ -14,8 +14,8 @@ public class CheckVRTracker : VRModeTracker
VRModeSwitchManager.OnPostVRModeSwitch -= OnPostSwitch; 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;
} }
} }

View file

@ -16,11 +16,11 @@ public class CohtmlHudTracker : VRModeTracker
VRModeSwitchManager.OnPostVRModeSwitch -= OnPostSwitch; 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."); 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 // This handles rotation and position
CVRTools.ConfigureHudAffinity(); CVRTools.ConfigureHudAffinity();
CohtmlHud.Instance.gameObject.transform.localScale = new Vector3(1.2f, 1f, 1.2f); CohtmlHud.Instance.gameObject.transform.localScale = new Vector3(1.2f, 1f, 1.2f);

View file

@ -14,11 +14,11 @@ public class HudOperationsTracker : VRModeTracker
VRModeSwitchManager.OnPostVRModeSwitch -= OnPostSwitch; VRModeSwitchManager.OnPostVRModeSwitch -= OnPostSwitch;
} }
private void OnPostSwitch(bool intoVR) private void OnPostSwitch(object sender, VRModeSwitchManager.VRModeEventArgs args)
{ {
DesktopVRSwitch.Logger.Msg("Switching HudOperations worldLoadingItem & worldLoadStatus."); DesktopVRSwitch.Logger.Msg("Switching HudOperations worldLoadingItem & worldLoadStatus.");
HudOperations.Instance.worldLoadingItem = intoVR ? HudOperations.Instance.worldLoadingItemVr : HudOperations.Instance.worldLoadingItemDesktop; HudOperations.Instance.worldLoadingItem = args.IsUsingVr ? HudOperations.Instance.worldLoadingItemVr : HudOperations.Instance.worldLoadingItemDesktop;
HudOperations.Instance.worldLoadStatus = intoVR ? HudOperations.Instance.worldLoadStatusVr : HudOperations.Instance.worldLoadStatusDesktop; HudOperations.Instance.worldLoadStatus = args.IsUsingVr ? HudOperations.Instance.worldLoadStatusVr : HudOperations.Instance.worldLoadStatusDesktop;
} }
} }

View file

@ -20,7 +20,7 @@ public class IKSystemTracker : VRModeTracker
VRModeSwitchManager.OnPostVRModeSwitch -= OnPostSwitch; VRModeSwitchManager.OnPostVRModeSwitch -= OnPostSwitch;
} }
private void OnPreSwitch(bool intoVR) private void OnPreSwitch(object sender, VRModeSwitchManager.VRModeEventArgs args)
{ {
BodySystem.TrackingEnabled = false; BodySystem.TrackingEnabled = false;
BodySystem.TrackingPositionWeight = 0f; BodySystem.TrackingPositionWeight = 0f;
@ -30,7 +30,7 @@ public class IKSystemTracker : VRModeTracker
IKSystem.vrik.enabled = false; IKSystem.vrik.enabled = false;
} }
private void OnFailedSwitch(bool intoVR) private void OnFailedSwitch(object sender, VRModeSwitchManager.VRModeEventArgs args)
{ {
BodySystem.TrackingEnabled = true; BodySystem.TrackingEnabled = true;
BodySystem.TrackingPositionWeight = 1f; BodySystem.TrackingPositionWeight = 1f;
@ -40,7 +40,7 @@ public class IKSystemTracker : VRModeTracker
IKSystem.vrik.enabled = true; IKSystem.vrik.enabled = true;
} }
private void OnPostSwitch(bool intoVR) private void OnPostSwitch(object sender, VRModeSwitchManager.VRModeEventArgs args)
{ {
if (IKSystem.vrik != null) if (IKSystem.vrik != null)
UnityEngine.Object.DestroyImmediate(IKSystem.vrik); UnityEngine.Object.DestroyImmediate(IKSystem.vrik);
@ -54,12 +54,12 @@ public class IKSystemTracker : VRModeTracker
BodySystem.isRecalibration = false; BodySystem.isRecalibration = false;
// Make it so you don't instantly end up in FBT from Desktop // 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 // Turn off finger tracking just in case the user switched controllers
IKSystem.Instance.FingerSystem.controlActive = false; IKSystem.Instance.FingerSystem.controlActive = false;
SetupSteamVRTrackingModule(intoVR); SetupSteamVRTrackingModule(args.IsUsingVr);
} }
private void SetupSteamVRTrackingModule(bool enableVR) private void SetupSteamVRTrackingModule(bool enableVR)
@ -69,14 +69,10 @@ public class IKSystemTracker : VRModeTracker
if (openVRModule != null) if (openVRModule != null)
{ {
if (enableVR) if (enableVR)
{
openVRModule.ModuleStart(); openVRModule.ModuleStart();
}
else else
{
openVRModule.ModuleDestroy(); openVRModule.ModuleDestroy();
} }
}
else if (enableVR) else if (enableVR)
{ {
var newVRModule = new SteamVRTrackingModule(); var newVRModule = new SteamVRTrackingModule();

View file

@ -17,16 +17,16 @@ public class MetaPortTracker : VRModeTracker
VRModeSwitchManager.OnPostVRModeSwitch -= OnPostSwitch; 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 // Main thing most of the game checks for if using VR
MetaPort.Instance.isUsingVr = intoVR; MetaPort.Instance.isUsingVr = args.IsUsingVr;
// replace // replace
UpdateRichPresence(); UpdateRichPresence();
ResetSteamVROverrides(intoVR); ResetSteamVROverrides(args.IsUsingVr);
} }
private void UpdateRichPresence() private void UpdateRichPresence()

View file

@ -23,7 +23,7 @@ public class MovementSystemTracker : VRModeTracker
VRModeSwitchManager.OnPostVRModeSwitch -= OnPostSwitch; 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."); 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."); DesktopVRSwitch.Logger.Msg("Resetting MovementSystem mobility.");
MovementSystem.Instance.SetImmobilized(false); MovementSystem.Instance.SetImmobilized(false);
} }
private void OnPostSwitch(bool intoVR) private void OnPostSwitch(object sender, VRModeSwitchManager.VRModeEventArgs args)
{ {
// Lazy // Lazy
MelonLoader.MelonCoroutines.Start(TeleportFrameAfter(intoVR)); MelonLoader.MelonCoroutines.Start(TeleportFrameAfter(args.IsUsingVr));
} }
private IEnumerator TeleportFrameAfter(bool intoVR) private IEnumerator TeleportFrameAfter(bool intoVR)

View file

@ -14,11 +14,11 @@ public class PlayerSetupTracker : VRModeTracker
VRModeSwitchManager.OnPostVRModeSwitch -= OnPostSwitch; 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."); DesktopVRSwitch.Logger.Msg("Switching active PlayerSetup camera rigs. Updating Desktop camera FOV.");
PlayerSetup.Instance.desktopCameraRig.SetActive(!intoVR); PlayerSetup.Instance.desktopCameraRig.SetActive(!args.IsUsingVr);
PlayerSetup.Instance.vrCameraRig.SetActive(intoVR); PlayerSetup.Instance.vrCameraRig.SetActive(args.IsUsingVr);
} }
} }

View file

@ -14,7 +14,7 @@ public class PortableCameraTracker : VRModeTracker
VRModeSwitchManager.OnPostVRModeSwitch -= OnPostSwitch; VRModeSwitchManager.OnPostVRModeSwitch -= OnPostSwitch;
} }
private void OnPostSwitch(bool intoVR) private void OnPostSwitch(object sender, VRModeSwitchManager.VRModeEventArgs args)
{ {
DesktopVRSwitch.Logger.Msg("Forcing PortableCamera canvas mirroring off."); DesktopVRSwitch.Logger.Msg("Forcing PortableCamera canvas mirroring off.");

View file

@ -1,6 +1,6 @@
namespace NAK.DesktopVRSwitch.VRModeTrackers; namespace NAK.DesktopVRSwitch.VRModeTrackers;
public class VRModeTracker public abstract class VRModeTracker
{ {
public virtual void TrackerInit() { } public virtual void TrackerInit() { }
public virtual void TrackerDestroy() { } public virtual void TrackerDestroy() { }

View file

@ -14,7 +14,7 @@ public class ViewManagerTracker : VRModeTracker
VRModeSwitchManager.OnPreVRModeSwitch -= OnPreSwitch; VRModeSwitchManager.OnPreVRModeSwitch -= OnPreSwitch;
} }
private void OnPreSwitch(bool intoVR) private void OnPreSwitch(object sender, VRModeSwitchManager.VRModeEventArgs args)
{ {
DesktopVRSwitch.Logger.Msg("Closing ViewManager - Main Menu."); DesktopVRSwitch.Logger.Msg("Closing ViewManager - Main Menu.");

View file

@ -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<OpenVRLoader>();
DesktopVRSwitch.Logger.Msg("Using XR Loader: SteamVR");
}
else
{
item = ScriptableObject.CreateInstance<OpenXRLoader>();
DesktopVRSwitch.Logger.Msg("Using XR Loader: OpenXR");
}
typeof(XRManagerSettings)
.GetField("m_Loaders", BindingFlags.Instance | BindingFlags.NonPublic)
?.SetValue(XRGeneralSettings.Instance.Manager, new List<XRLoader> { item });
}
}