using Code.D.Cleaning; using Code.D.Player; using Code.Infrastructure.Camera; using Code.Infrastructure.Input; using Cysharp.Threading.Tasks; using R3; using Reflex.Attributes; using UnityEngine; using UnityEngine.InputSystem; namespace Code.Game.Gameplay.Player { public class PlayerDetailMaskDrawer : MonoBehaviour { private IInputService _inputService; private Transform _cameraTransform; private bool _cleaning, _cleaningUnder; private LayerMask _layerMask; private TagHandle _surfaceTag; private CleanableSurface _lastCleaned; [SerializeField] private float cleaningDistance = 5f; [SerializeField] private PlayerEquipment playerEquipment; private void Awake() { _surfaceTag = TagHandle.GetExistingTag("CleanableSurface"); _layerMask = LayerMask.GetMask("Cleanable"); GetComponent().IsSliding.Subscribe(SlideToggle).AddTo(destroyCancellationToken); } [Inject] private void Construct(IInputService inputService, CameraStateMachine cameraStateMachine) { _cameraTransform = cameraStateMachine.Camera.transform; _inputService = inputService; _inputService.BindActionPerformed((int)ActionMappings.Cleaning, (int)CleaningActions.Clean, DrawPerformed); _inputService.BindActionCancelled((int)ActionMappings.Cleaning, (int)CleaningActions.Clean, DrawCancelled); } private void SlideToggle(bool isSliding) => _cleaningUnder = isSliding; private void DrawPerformed(InputAction.CallbackContext obj) => _cleaning = true; private void DrawCancelled(InputAction.CallbackContext obj) => _cleaning = false; private void FixedUpdate() { if (_cleaning) CleanInFront(); if (_cleaningUnder) CleanUnder(); } private void CleanUnder() { if (!Physics.Raycast( _cameraTransform.position, -transform.up, out var info, 5f, layerMask: _layerMask)) return; if (info.collider.CompareTag(_surfaceTag)) CleanSurface(info); } private void CleanInFront() { if (!Physics.Raycast( _cameraTransform.position, _cameraTransform.forward, out var info, cleaningDistance, layerMask: _layerMask)) return; if (info.collider.CompareTag(_surfaceTag)) CleanSurface(info); else CleanAsset(info); } private void CleanAsset(RaycastHit info) { var cleanable = info.collider.GetComponent(); cleanable.Clean(); } private void CleanSurface(RaycastHit info) { CleanableSurface cleanable; if (_lastCleaned is not null && info.collider.GetEntityId() == _lastCleaned.GetEntityId()) cleanable = _lastCleaned; else { cleanable = info.collider.GetComponent(); _lastCleaned = cleanable; } cleanable.Clean(info, playerEquipment.CurrentTool.Use(), _cameraTransform); } private void OnDestroy() { _inputService.UnbindActionPerformed((int)ActionMappings.Cleaning, (int)CleaningActions.Clean, DrawPerformed); _inputService.UnbindActionCancelled((int)ActionMappings.Cleaning, (int)CleaningActions.Clean, DrawCancelled); } } }