[DesktopVRSwitch] - > DesktopXRSwitch

This commit is contained in:
NotAKidoS 2023-05-17 12:06:48 -05:00
parent 37fcf6ece1
commit 05374459be
21 changed files with 441 additions and 352 deletions

View file

@ -0,0 +1,31 @@
using ABI.CCK.Components;
using UnityEngine;
//Thanks Ben! I was scared of transpiler so I reworked a bit...
namespace NAK.Melons.DesktopXRSwitch.Patches;
public class CVRPickupObjectTracker : MonoBehaviour
{
public CVRPickupObject pickupObject;
public Transform storedGripOrigin;
void Start()
{
XRModeSwitchTracker.OnPostXRModeSwitch += PostXRModeSwitch;
}
void OnDestroy()
{
XRModeSwitchTracker.OnPostXRModeSwitch -= PostXRModeSwitch;
}
public void PostXRModeSwitch(bool isXR, Camera activeCamera)
{
if (pickupObject != null)
{
if (pickupObject._controllerRay != null) pickupObject._controllerRay.DropObject(true);
(storedGripOrigin, pickupObject.gripOrigin) = (pickupObject.gripOrigin, storedGripOrigin);
}
}
}

View file

@ -0,0 +1,24 @@
using ABI_RC.Core.Util.Object_Behaviour;
using UnityEngine;
namespace NAK.Melons.DesktopXRSwitch.Patches;
public class CameraFacingObjectTracker : MonoBehaviour
{
public CameraFacingObject cameraFacingObject;
void Start()
{
cameraFacingObject = GetComponent<CameraFacingObject>();
XRModeSwitchTracker.OnPostXRModeSwitch += PostXRModeSwitch;
}
void OnDestroy()
{
XRModeSwitchTracker.OnPostXRModeSwitch -= PostXRModeSwitch;
}
public void PostXRModeSwitch(bool isXR, Camera activeCamera)
{
cameraFacingObject.m_Camera = activeCamera;
}
}

View file

@ -0,0 +1,89 @@
using ABI_RC.Systems.IK;
using ABI_RC.Systems.IK.SubSystems;
using ABI_RC.Systems.IK.TrackingModules;
using UnityEngine;
namespace NAK.Melons.DesktopXRSwitch.Patches;
public class IKSystemTracker : MonoBehaviour
{
public IKSystem ikSystem;
void Start()
{
ikSystem = GetComponent<IKSystem>();
XRModeSwitchTracker.OnPreXRModeSwitch += PreXRModeSwitch;
XRModeSwitchTracker.OnFailXRModeSwitch += FailedXRModeSwitch;
XRModeSwitchTracker.OnPostXRModeSwitch += PostXRModeSwitch;
}
void OnDestroy()
{
XRModeSwitchTracker.OnPreXRModeSwitch -= PreXRModeSwitch;
XRModeSwitchTracker.OnFailXRModeSwitch -= FailedXRModeSwitch;
XRModeSwitchTracker.OnPostXRModeSwitch -= PostXRModeSwitch;
}
public void PreXRModeSwitch(bool inXR, Camera activeCamera)
{
BodySystem.TrackingEnabled = false;
BodySystem.TrackingPositionWeight = 0f;
BodySystem.TrackingLocomotionEnabled = false;
if (IKSystem.vrik != null)
IKSystem.vrik.enabled = false;
}
public void FailedXRModeSwitch(bool inXR, Camera activeCamera)
{
BodySystem.TrackingEnabled = true;
BodySystem.TrackingPositionWeight = 1f;
BodySystem.TrackingLocomotionEnabled = true;
if (IKSystem.vrik != null)
IKSystem.vrik.enabled = true;
}
public void PostXRModeSwitch(bool inXR, 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 = DesktopXRSwitch.EntryEnterCalibrationOnSwitch.Value;
//turn of finger tracking just in case user switched controllers
ikSystem.FingerSystem.controlActive = false;
//vrik should be deleted by avatar switch
SetupOpenXRTrackingModule(inXR);
}
void SetupOpenXRTrackingModule(bool enableVR)
{
var openXRTrackingModule = ikSystem._trackingModules.OfType<OpenXRTrackingModule>().FirstOrDefault();
if (openXRTrackingModule != null)
{
if (enableVR)
{
openXRTrackingModule.ModuleStart();
}
else
{
openXRTrackingModule.ModuleDestroy();
if (openXRTrackingModule != null)
ikSystem._trackingModules.Remove(openXRTrackingModule);
}
}
else if (enableVR)
{
var newVRModule = new OpenXRTrackingModule();
ikSystem.AddTrackingModule(newVRModule);
}
}
}

View file

@ -0,0 +1,54 @@
using ABI_RC.Systems.MovementSystem;
using UnityEngine;
namespace NAK.Melons.DesktopXRSwitch.Patches;
public class MovementSystemTracker : MonoBehaviour
{
public MovementSystem movementSystem;
public Vector3 preSwitchWorldPosition;
public Quaternion preSwitchWorldRotation;
void Start()
{
movementSystem = GetComponent<MovementSystem>();
XRModeSwitchTracker.OnPreXRModeSwitch += PreXRModeSwitch;
XRModeSwitchTracker.OnPostXRModeSwitch += PostXRModeSwitch;
}
void OnDestroy()
{
XRModeSwitchTracker.OnPreXRModeSwitch -= PreXRModeSwitch;
XRModeSwitchTracker.OnPostXRModeSwitch -= PostXRModeSwitch;
}
public void PreXRModeSwitch(bool isXR, 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 PostXRModeSwitch(bool isXR, 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 (!isXR) movementSystem.UpdateColliderCenter(movementSystem.transform.position);
movementSystem.ChangeCrouch(false);
movementSystem.ChangeProne(false);
}
}

View file

@ -0,0 +1,142 @@
using ABI.CCK.Components;
using ABI_RC.Core.Base;
using ABI_RC.Core.Player;
using ABI_RC.Systems.IK;
using HarmonyLib;
using RootMotion.FinalIK;
using System.Reflection;
using UnityEngine;
namespace NAK.Melons.DesktopXRSwitch.Patches;
public class PlayerSetupTracker : MonoBehaviour
{
public static PlayerSetupTracker Instance;
public PlayerSetup playerSetup;
public Traverse _initialCameraPosTraverse;
public Traverse _lookIKTraverse;
public Traverse _lastScaleTraverse;
public HumanPose avatarInitialHumanPose;
public HumanPoseHandler avatarHumanPoseHandler;
public GameObject avatarObject;
public CVRAvatar avatarDescriptor;
public Animator avatarAnimator;
public Vector3 initialPosition;
public Quaternion initialRotation;
void Start()
{
Instance = this;
playerSetup = GetComponent<PlayerSetup>();
_initialCameraPosTraverse = Traverse.Create(playerSetup).Field("initialCameraPos");
_lookIKTraverse = Traverse.Create(playerSetup).Field("lookIK");
_lastScaleTraverse = Traverse.Create(playerSetup).Field("lastScale");
}
public void OnSetupAvatar(GameObject avatar)
{
avatarObject = avatar;
avatarDescriptor = avatarObject.GetComponent<CVRAvatar>();
avatarAnimator = avatarObject.GetComponent<Animator>();
initialPosition = avatarObject.transform.localPosition;
initialRotation = avatarObject.transform.localRotation;
if (avatarHumanPoseHandler == null)
{
avatarHumanPoseHandler = new HumanPoseHandler(avatarAnimator.avatar, avatarAnimator.transform);
}
avatarHumanPoseHandler.GetHumanPose(ref avatarInitialHumanPose);
}
public void OnClearAvatar()
{
avatarObject = null;
avatarDescriptor = null;
avatarAnimator = null;
initialPosition = Vector3.one;
initialRotation = Quaternion.identity;
avatarHumanPoseHandler = null;
}
public void ConfigureAvatarIK(bool isVR)
{
bool StateOnDisable = avatarAnimator.keepAnimatorStateOnDisable;
avatarAnimator.keepAnimatorStateOnDisable = true;
avatarAnimator.enabled = false;
//reset avatar offsets
avatarObject.transform.localPosition = initialPosition;
avatarObject.transform.localRotation = initialRotation;
avatarHumanPoseHandler.SetHumanPose(ref avatarInitialHumanPose);
if (isVR)
{
SwitchAvatarVr();
}
else
{
SwitchAvatarDesktop();
}
//lazy fix
_lastScaleTraverse.SetValue(Vector3.zero);
MethodInfo setPlaySpaceScaleMethod = playerSetup.GetType().GetMethod("CheckUpdateAvatarScaleToPlaySpaceRelation", BindingFlags.NonPublic | BindingFlags.Instance);
setPlaySpaceScaleMethod.Invoke(playerSetup, null);
avatarAnimator.keepAnimatorStateOnDisable = StateOnDisable;
avatarAnimator.enabled = true;
}
private void SwitchAvatarVr()
{
if (avatarDescriptor == null) return;
//remove LookAtIK if found
LookAtIK avatarLookAtIK = avatarObject.GetComponent<LookAtIK>();
if (avatarLookAtIK != null) DestroyImmediate(avatarLookAtIK);
//have IKSystem set up avatar for VR
//a good chunk of IKSystem initialization checks for existing
//stuff & if it is set up, so game is ready to handle it
if (avatarAnimator != null && avatarAnimator.isHuman)
{
IKSystem.Instance.InitializeAvatar(avatarDescriptor);
}
}
private void SwitchAvatarDesktop()
{
if (avatarDescriptor == null) return;
//remove VRIK & VRIKRootController if found
VRIK avatarVRIK = avatarObject.GetComponent<VRIK>();
VRIKRootController avatarVRIKRootController = avatarObject.GetComponent<VRIKRootController>();
if (avatarVRIK != null) DestroyImmediate(avatarVRIK);
if (avatarVRIKRootController != null) DestroyImmediate(avatarVRIKRootController);
//remove all TwistRelaxer components
TwistRelaxer[] avatarTwistRelaxers = avatarObject.GetComponentsInChildren<TwistRelaxer>();
for (int i = 0; i < avatarTwistRelaxers.Length; i++)
{
DestroyImmediate(avatarTwistRelaxers[i]);
}
Transform headTransform = avatarAnimator.GetBoneTransform(HumanBodyBones.Head);
if (headTransform != null)
{
//set DesktopCameraRig to head bone pos
playerSetup.desktopCameraRig.transform.position = headTransform.position;
//add LookAtIK & Configure
LookAtIK lookAtIK = avatarObject.AddComponentIfMissing<LookAtIK>();
lookAtIK.solver.head = new IKSolverLookAt.LookAtBone(headTransform);
lookAtIK.solver.headWeight = 0.75f;
lookAtIK.solver.target = playerSetup.desktopCameraTarget.transform;
_lookIKTraverse.SetValue(lookAtIK);
}
//set camera position & initial position for headbob (both modes end up with same number)
playerSetup.desktopCamera.transform.localPosition = (Vector3)_initialCameraPosTraverse.GetValue();
}
}

View file

@ -0,0 +1,91 @@
using ABI_RC.Core.Base;
using ABI_RC.Core.Player;
using ABI_RC.Core.Savior;
using Aura2API;
using BeautifyEffect;
using UnityEngine;
using UnityEngine.AzureSky;
using UnityEngine.Rendering.PostProcessing;
using Object = UnityEngine.Object;
namespace NAK.Melons.DesktopXRSwitch.Patches;
internal class ReferenceCameraPatch
{
internal static void OnWorldLoad()
{
Camera activeCamera = (MetaPort.Instance.isUsingVr ? PlayerSetup.Instance.vrCamera : PlayerSetup.Instance.desktopCamera).GetComponent<Camera>();
Camera inactiveCamera = (MetaPort.Instance.isUsingVr ? PlayerSetup.Instance.desktopCamera : PlayerSetup.Instance.vrCamera).GetComponent<Camera>();
CopyToInactiveCam(activeCamera, inactiveCamera);
}
internal static void CopyToInactiveCam(Camera activeCam, Camera inactiveCam)
{
DesktopXRSwitch.Logger.Msg("Copying active camera settings & components to inactive camera.");
//steal basic settings
inactiveCam.farClipPlane = activeCam.farClipPlane;
inactiveCam.nearClipPlane = activeCam.nearClipPlane;
inactiveCam.cullingMask = activeCam.cullingMask;
inactiveCam.depthTextureMode = activeCam.depthTextureMode;
//steal post processing if added
PostProcessLayer ppLayerActiveCam = activeCam.GetComponent<PostProcessLayer>();
PostProcessLayer ppLayerInactiveCam = inactiveCam.AddComponentIfMissing<PostProcessLayer>();
if (ppLayerActiveCam != null && ppLayerInactiveCam != null)
{
ppLayerInactiveCam.enabled = ppLayerActiveCam.enabled;
ppLayerInactiveCam.volumeLayer = ppLayerActiveCam.volumeLayer;
}
//what even is this aura camera stuff
AuraCamera auraActiveCam = activeCam.GetComponent<AuraCamera>();
AuraCamera auraInactiveCam = inactiveCam.AddComponentIfMissing<AuraCamera>();
if (auraActiveCam != null && auraInactiveCam != null)
{
auraInactiveCam.enabled = auraActiveCam.enabled;
auraInactiveCam.frustumSettings = auraActiveCam.frustumSettings;
}
else
{
auraInactiveCam.enabled = false;
}
//flare layer thing? the sun :_:_:_:_:_:
FlareLayer flareActiveCam = activeCam.GetComponent<FlareLayer>();
FlareLayer flareInactiveCam = inactiveCam.AddComponentIfMissing<FlareLayer>();
if (flareActiveCam != null && flareInactiveCam != null)
{
flareInactiveCam.enabled = flareActiveCam.enabled;
}
else
{
flareInactiveCam.enabled = false;
}
//and now what the fuck is fog scattering
AzureFogScattering azureFogActiveCam = activeCam.GetComponent<AzureFogScattering>();
AzureFogScattering azureFogInactiveCam = inactiveCam.AddComponentIfMissing<AzureFogScattering>();
if (azureFogActiveCam != null && azureFogInactiveCam != null)
{
azureFogInactiveCam.fogScatteringMaterial = azureFogActiveCam.fogScatteringMaterial;
}
else
{
Object.Destroy(inactiveCam.GetComponent<AzureFogScattering>());
}
//why is there so many thingsssssssss
Beautify beautifyActiveCam = activeCam.GetComponent<Beautify>();
Beautify beautifyInactiveCam = inactiveCam.AddComponentIfMissing<Beautify>();
if (beautifyActiveCam != null && beautifyInactiveCam != null)
{
beautifyInactiveCam.quality = beautifyActiveCam.quality;
beautifyInactiveCam.profile = beautifyActiveCam.profile;
}
else
{
Object.Destroy(inactiveCam.gameObject.GetComponent<Beautify>());
}
}
}

View file

@ -0,0 +1,45 @@
using ABI_RC.Core.Player;
using UnityEngine;
using UnityEngine.Events;
namespace NAK.Melons.DesktopXRSwitch.Patches;
public class XRModeSwitchTracker
{
public static event UnityAction<bool, Camera> OnPreXRModeSwitch;
public static event UnityAction<bool, Camera> OnPostXRModeSwitch;
public static event UnityAction<bool, Camera> OnFailXRModeSwitch;
public static void PreXRModeSwitch(bool isXR)
{
TryCatchHell.TryCatchWrapper(() =>
{
DesktopXRSwitch.Logger.Msg("Invoking XRModeSwitchTracker.OnPreXRModeSwitch.");
Camera activeCamera = PlayerSetup.Instance.GetActiveCamera().GetComponent<Camera>();
XRModeSwitchTracker.OnPreXRModeSwitch?.Invoke(isXR, activeCamera);
},
"Error while invoking XRModeSwitchTracker.OnPreXRModeSwitch. Did someone do a fucky?");
}
public static void PostXRModeSwitch(bool isXR)
{
TryCatchHell.TryCatchWrapper(() =>
{
DesktopXRSwitch.Logger.Msg("Invoking XRModeSwitchTracker.OnPostXRModeSwitch.");
Camera activeCamera = PlayerSetup.Instance.GetActiveCamera().GetComponent<Camera>();
XRModeSwitchTracker.OnPostXRModeSwitch?.Invoke(isXR, activeCamera);
},
"Error while invoking XRModeSwitchTracker.OnPostXRModeSwitch. Did someone do a fucky?");
}
public static void FailXRModeSwitch(bool isXR)
{
TryCatchHell.TryCatchWrapper(() =>
{
DesktopXRSwitch.Logger.Msg("Invoking XRModeSwitchTracker.OnFailXRModeSwitch.");
Camera activeCamera = PlayerSetup.Instance.GetActiveCamera().GetComponent<Camera>();
XRModeSwitchTracker.OnFailXRModeSwitch?.Invoke(isXR, activeCamera);
},
"Error while invoking OnFailXRModeSwitch.OnPreXRModeSwitch. Did someone do a fucky?");
}
}