using System; using System.Collections; using System.Collections.Generic; using System.Runtime.CompilerServices; using BITKit; using BITKit.StateMachine; using Unity.Collections.LowLevel.Unsafe; using Unity.Mathematics; using UnityEngine; // ReSharper disable UnassignedField.Local namespace BITFactory.Cutting { [Serializable] public sealed class CuttingBlankBrush : CuttingToolBrush { public override string Name => "无笔刷"; public override string Description => "用于观察切削结果"; } [Serializable] public sealed class CuttingPointBrush : CuttingToolBrush { public override string Name => "点切削"; public override string Description => "按住鼠标左键进行画笔切削"; [BITKit.Export("切削半径")] public float Radius = 0; public override unsafe void* GetExport(string name) { return name == nameof(Radius) ? UnsafeUtility.AddressOf(ref Radius) : base.GetExport(name); } public override void HandlePoint(bool isPreview, float3 normal, float3 point) { if (!isPreview) return; if (Radius is 0) { cuttingTool.CutPlanePoint(true, normal, point); } else { cuttingTool.CutPlantSphere(true, normal, point, Radius); } } public override void ReleasePoint(float3 normal, float3 point) { if (Radius is 0) { cuttingTool.Execute(new CuttingPointCommand() { PlaneNormal = normal, PlanePoint = point, }); } else { cuttingTool.Execute(new CuttingSphereCommand() { PlaneNormal = normal, PlanePoint = point, Radius = Radius }); } } } [Serializable] public sealed class CuttingLineBrush : CuttingToolBrush { public override string Name => "线切削"; public override string Description=>"在两点之间切削,需要确认切削"; [Export,SerializeField] private float snapDifference=0.05f; private readonly List _points = new(); private float3[] _previewPoints = Array.Empty(); private float3 _normal=Vector3.up; private readonly IntervalUpdate _interrupt = new(0.1f); public override unsafe void* GetExport(string name) { return name switch { nameof(snapDifference)=>UnsafeUtility.AddressOf(ref snapDifference), _ => base.GetExport(name) }; } public override void OnStateExit(IState old, IState newState) { base.OnStateExit(old, newState); _points.Clear(); _previewPoints = Array.Empty(); } public override void ReleasePoint(float3 normal, float3 point) { Snap(ref point); _points.Add(point); _previewPoints = new float3[_points.Count+1]; Array.Copy(_points.ToArray(),_previewPoints,_points.Count); } public override void OnStateUpdate(float deltaTime) { if (_points.Count is 0) { } else { cuttingTool.CutPlaneLine(true, _normal, _interrupt.AllowUpdateWithoutReset ? _points.ToArray() : _previewPoints); } } public override void HandlePoint(bool isPreview, float3 normal, float3 point) { _normal = normal; _interrupt.Reset(); if (_points.Count is 0) { cuttingTool.CutPlanePoint(true, _normal, point); } else { Snap(ref point); _previewPoints[^1] = point; } } [BITKit.Export("确认切削")] private void Release() { if (_points.Count <= 0) return; cuttingTool.Execute(new CuttingLineCommand() { PlaneNormal = _normal, Line = _points.ToArray() }); Cancel(); } [Export("取消")] private void Cancel() { if (_points.Count <= 0) return; _points.Clear(); _previewPoints = Array.Empty(); } private void Snap(ref float3 point) { // ReSharper disable once ForeachCanBePartlyConvertedToQueryUsingAnotherGetEnumerator foreach (var x in _points) { if (!(Vector3.Distance(x, point) <= snapDifference)) continue; point = x; break; } } } }