using System; using System.Collections; using System.Collections.Generic; using System.Linq; using BITKit; using BITKit.Entities; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Interactions; namespace BITFactory.Cutting { /// 切削笔刷服务,主要由用户控制,通过进行切削 /// public class CuttingToolService : StateBasedBehavior,ICuttingToolService { [SerializeField] private LayerMask _layerMask; [SerializeField] private InputActionReference _cuttingAction; [SerializeField] private InputActionReference _snapAction; [SerializeField] private float _snapValue = 0.01f; [SerializeReference,SubclassSelector] private ICondition allowMouseInput; private readonly InputActionGroup _inputActionGroup = new(); private Camera _camera; private Vector3 _lastPoint; [Inject] private ICuttingTool _cuttingTool; private void Awake() { DI.Register(this); } public override void OnStart() { base.OnStart(); // ReSharper disable once Unity.PerformanceCriticalCodeCameraMain _camera = Camera.main; _inputActionGroup.RegisterCallback(_cuttingAction, OnCutting); _inputActionGroup.RegisterCallback(_snapAction, OnSnap); _inputActionGroup.allowInput.AddElement(this); } private void OnSnap(InputAction.CallbackContext obj) { IsSnapping = obj switch { { interaction: PressInteraction, performed: true } => true, { interaction: PressInteraction, canceled: true } => false, _ => IsSnapping }; } private void OnCutting(InputAction.CallbackContext obj) { IsCutting = obj switch { { interaction: PressInteraction, performed: true } => true, { interaction: PressInteraction, canceled: true } => false, _ => IsCutting }; } public override void OnUpdate(float deltaTime) { IsPreview = false; CurrentState?.OnStateUpdate(deltaTime); if (_inputActionGroup.allowInput.Allow is false) return; if(allowMouseInput is {Allow:false}) return; if (BITAppForUnity.AllowCursor.Allow is false) return; if (Physics.Raycast(_camera.ScreenPointToRay(Mouse.current.position.ReadValue()), out var hit, 1000, _layerMask) is false) return; var isClose = Vector3.Distance(_lastPoint,hit.point)<0.01f; if (IsSnapping) { hit.point = MathV.AlignToGrid(hit.point, _snapValue); isClose = false; } if (IsCutting && isClose is false) { // _cuttingTool.Execute(new CuttingPointCommand() // { // PlaneNormal = hit.normal, // PlanePoint =hit.point, // }); _lastPoint = hit.point; CurrentState?.HandlePoint(false, hit.normal, hit.point); CurrentState?.ReleasePoint(hit.normal,hit.point); } else { // _cuttingTool.CutPlanePoint(true, hit.normal, hit.point); CurrentState?.HandlePoint(true, hit.normal, hit.point); IsPreview = true; } } public override void UnRegister(ICuttingToolBrush newState) { if(CurrentState == newState) TransitionState(StateDictionary.Values.First()); base.UnRegister(newState); } public bool IsPreview { get; private set; } public bool IsCutting { get;private set; } public bool IsSnapping { get; private set; } } }