iFactory.Cutting.Unity/Assets/Artists/Scripts/UnityCuttingToolService.cs

129 lines
3.3 KiB
C#

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
{
/// 切削笔刷服务,主要由用户控制,通过<see cref="ICuttingTool"/>进行切削
/// <inheritdoc cref="ICuttingToolService"/>
public class CuttingToolService : StateBasedBehavior<ICuttingToolBrush>,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<ICuttingToolService>(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; }
}
}