using ABI_RC.Core.Player.Interaction.RaycastImpl; using ABI_RC.Core.Savior; using ABI_RC.Systems.InputManagement; using UnityEngine; namespace ABI_RC.Core.Player.Interaction { public class CVRPlayerInteractionManager : MonoBehaviour { #region Singleton public static CVRPlayerInteractionManager Instance { get; private set; } #endregion Singleton #region Serialized Fields [Header("Hand Components")] [SerializeField] private CVRPlayerHand handVrLeft; [SerializeField] private CVRPlayerHand handVrRight; [SerializeField] private CVRPlayerHand handDesktopRight; // Desktop does not have a left hand [Header("Raycast Transforms")] [SerializeField] private Transform raycastTransformVrRight; [SerializeField] private Transform raycastTransformVrLeft; [SerializeField] private Transform raycastTransformDesktopRight; [Header("Settings")] [SerializeField] private bool interactionEnabled = true; [SerializeField] private LayerMask interactionLayerMask = -1; // Default to all layers, will be filtered #endregion Serialized Fields #region Properties private CVRPlayerHand _rightHand; private CVRPlayerHand _leftHand; private CVRPlayerRaycaster _rightRaycaster; private CVRPlayerRaycaster _leftRaycaster; private CVRRaycastResult _rightRaycastResult; private CVRRaycastResult _leftRaycastResult; // Input handler private CVRPlayerInputHandler _inputHandler; // Interaction flags public bool InteractionEnabled { get => interactionEnabled; set => interactionEnabled = value; } #endregion Properties #region Unity Events private void Awake() { if (Instance != null && Instance != this) { Destroy(gameObject); return; } Instance = this; // Create the input handler _inputHandler = gameObject.AddComponent(); } private void Start() { // Setup interaction for current device mode SetupInteractionForDeviceMode(); // Listen for VR mode changes MetaPort.Instance.onVRModeSwitch.AddListener(SetupInteractionForDeviceMode); } private void Update() { if (!interactionEnabled) return; // Process right hand if (_rightRaycaster != null) { // Determine raycast flags based on current mode CVRPlayerRaycaster.RaycastFlags flags = DetermineRaycastFlags(_rightHand); // Get raycast results _rightRaycastResult = _rightRaycaster.GetRaycastResults(flags); // Process input based on raycast results _inputHandler.ProcessInput(CVRHand.Right, _rightRaycastResult); } // Process left hand (if available) if (_leftRaycaster != null) { // Determine raycast flags based on current mode CVRPlayerRaycaster.RaycastFlags flags = DetermineRaycastFlags(_leftHand); // Get raycast results _leftRaycastResult = _leftRaycaster.GetRaycastResults(flags); // Process input based on raycast results _inputHandler.ProcessInput(CVRHand.Left, _leftRaycastResult); } } private void OnDestroy() { // Clean up event listener if (MetaPort.Instance != null) MetaPort.Instance.onVRModeSwitch.RemoveListener(SetupInteractionForDeviceMode); } #endregion Unity Events #region Public Methods /// /// Register a custom tool mode /// public void RegisterCustomToolMode(System.Action callback) { _inputHandler.RegisterCustomTool(callback); } /// /// Unregister the current custom tool mode /// public void UnregisterCustomToolMode() { _inputHandler.UnregisterCustomTool(); } /// /// Set the interaction mode /// public void SetInteractionMode(CVRPlayerInputHandler.InteractionMode mode) { _inputHandler.SetInteractionMode(mode); } /// /// Get the raycast result for a specific hand /// public CVRRaycastResult GetRaycastResult(CVRHand hand) { return hand == CVRHand.Left ? _leftRaycastResult : _rightRaycastResult; } #endregion Public Methods #region Private Methods private void SetupInteractionForDeviceMode() { bool isVr = MetaPort.Instance.isUsingVr; if (isVr) { // VR mode _rightHand = handVrRight; _leftHand = handVrLeft; // VR uses the controller transform for raycasting _rightRaycaster = new CVRPlayerRaycasterTransform(raycastTransformVrRight); _leftRaycaster = new CVRPlayerRaycasterTransform(raycastTransformVrLeft); } else { // Desktop mode _rightHand = handDesktopRight; _leftHand = null; // Desktop uses the mouse position for raycasting when unlocked Camera desktopCamera = PlayerSetup.Instance.desktopCam; _rightRaycaster = new CVRPlayerRaycasterMouse(raycastTransformDesktopRight, desktopCamera); _leftRaycaster = null; } // Set the layer mask for raycasters if (_rightRaycaster != null) _rightRaycaster.SetLayerMask(interactionLayerMask); if (_leftRaycaster != null) _leftRaycaster.SetLayerMask(interactionLayerMask); } private static CVRPlayerRaycaster.RaycastFlags DetermineRaycastFlags(CVRPlayerHand hand) { // Default to all flags CVRPlayerRaycaster.RaycastFlags flags = CVRPlayerRaycaster.RaycastFlags.All; // Check if hand is holding a pickup if (hand != null && hand.IsHoldingObject) { // When holding an object, only check for COHTML interaction flags = CVRPlayerRaycaster.RaycastFlags.CohtmlInteract; } // Could add more conditional flag adjustments here based on the current mode // For example, in a teleport tool mode, you might only want world hits return flags; } #endregion Private Methods } }