NAK_CVR_Mods/.Deprecated/ControlToUnlockEyes/Main.cs
2025-12-28 20:30:00 -06:00

169 lines
No EOL
6 KiB
C#

using ABI_RC.Core;
using ABI_RC.Core.InteractionSystem;
using ABI_RC.Core.Player;
using ABI_RC.Core.Savior;
using ABI_RC.Systems.FaceTracking;
using ABI_RC.Systems.InputManagement;
using MelonLoader;
using UnityEngine;
namespace NAK.ControlToUnlockEyes;
public class ControlToUnlockEyesMod : MelonMod
{
public override void OnInitializeMelon()
{
HarmonyInstance.Patch(
typeof(FaceTrackingManager).GetMethod(nameof(FaceTrackingManager.RegisterBuiltinModules),
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance),
postfix: new HarmonyLib.HarmonyMethod(typeof(ControlToUnlockEyesMod).GetMethod(nameof(OnPostFaceTrackingManagerRegisterBuiltinModules),
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static))
);
}
private static void OnPostFaceTrackingManagerRegisterBuiltinModules(FaceTrackingManager __instance)
=> __instance.RegisterEyeModule(new DefaultEyeModule());
public class DefaultEyeModule : IEyeTrackingModule
{
private const float FixedDistance = 10f;
private bool _useFixedDistance = true;
private readonly EyeTrackingData _eyeTrackingData = new();
private bool _dataAvailable;
private bool _running;
private ControllerRay _activeRay;
private Transform _rayDirectionTransform;
private CVRHand lastInteractHand = CVRHand.Right;
public bool Start(bool vr)
{
_running = true;
return true;
}
public void Stop()
{
_running = false;
}
public void Update()
{
if (!PlayerSetup.Instance)
return;
UpdateLastInteractHand();
UpdateFakedEyeTrackingData();
}
private void UpdateLastInteractHand()
{
ControllerRay leftRay = PlayerSetup.Instance.vrRayLeft;
ControllerRay rightRay = PlayerSetup.Instance.vrRayRight;
if (!MetaPort.Instance.isUsingVr)
{
_activeRay = PlayerSetup.Instance.desktopRay;
_rayDirectionTransform = _activeRay.rayDirectionTransform;
return;
}
bool leftAvailable = IsHandAvailable(leftRay, CVRHand.Left);
bool rightAvailable = IsHandAvailable(rightRay, CVRHand.Right);
if (CVRInputManager.Instance.interactLeftDown && leftAvailable)
lastInteractHand = CVRHand.Left;
else if (CVRInputManager.Instance.interactRightDown && rightAvailable)
lastInteractHand = CVRHand.Right;
_activeRay = GetLastInteractRay();
_rayDirectionTransform = _activeRay.rayDirectionTransform;
}
private void UpdateFakedEyeTrackingData()
{
_dataAvailable = _activeRay.CanSelectPlayersAndProps();
if (!_dataAvailable)
return;
_eyeTrackingData.blinking = false;
Transform ourCameraTransform = PlayerSetup.Instance.activeCam.transform;
Vector3 rayForward = _rayDirectionTransform.forward;
float rayDistance = _useFixedDistance ? FixedDistance : _activeRay.Hit.distance;
// TODO: dot product check to flip direction if behind camera
// Convert to camera-local *direction* (normalized) and multiply by selected distance so the gazePoint
// is on a sphere around the camera rather than mapped to a "square".
Vector3 localDir = ourCameraTransform.InverseTransformDirection(rayForward).normalized;
Vector3 localGazePoint = localDir * rayDistance;
_eyeTrackingData.gazePoint = localGazePoint;
}
private ControllerRay GetLastInteractRay()
{
if (!MetaPort.Instance.isUsingVr)
return PlayerSetup.Instance.desktopRay;
ControllerRay leftRay = PlayerSetup.Instance.vrRayLeft;
ControllerRay rightRay = PlayerSetup.Instance.vrRayRight;
if (lastInteractHand == CVRHand.Left && IsHandAvailable(leftRay, CVRHand.Left))
return leftRay;
if (lastInteractHand == CVRHand.Right && IsHandAvailable(rightRay, CVRHand.Right))
return rightRay;
return GetBestAvailableHand();
}
private ControllerRay GetBestAvailableHand()
{
if (!MetaPort.Instance.isUsingVr)
return PlayerSetup.Instance.desktopRay;
ControllerRay leftRay = PlayerSetup.Instance.vrRayLeft;
ControllerRay rightRay = PlayerSetup.Instance.vrRayRight;
bool leftAvailable = IsHandAvailable(leftRay, CVRHand.Left);
bool rightAvailable = IsHandAvailable(rightRay, CVRHand.Right);
if (CVRInputManager.Instance.interactLeftDown && leftAvailable)
return leftRay;
if (CVRInputManager.Instance.interactRightDown && rightAvailable)
return rightRay;
if (lastInteractHand == CVRHand.Left && leftAvailable)
return leftRay;
if (lastInteractHand == CVRHand.Right && rightAvailable)
return rightRay;
if (rightAvailable) return rightRay;
if (leftAvailable) return leftRay;
return rightRay;
}
private static bool IsHandAvailable(ControllerRay ray, CVRHand hand)
{
if (ray.grabbedObject)
return false;
if (CVR_MenuManager.Instance.IsViewShown &&
CVR_MenuManager.Instance.SelectedQuickMenuHand == hand)
return false;
return true;
}
public bool IsRunning() => _running;
public bool IsDataAvailable() => _dataAvailable;
public EyeTrackingData GetTrackingData() => _eyeTrackingData;
public string GetModuleName() => "None";
public string GetModuleShortName() => "None";
}
}