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

178 lines
3.8 KiB
C#

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<float3> _points = new();
private float3[] _previewPoints = Array.Empty<float3>();
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<float3>();
}
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<float3>();
}
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;
}
}
}
}