using System; using System.Collections; using System.Collections.Generic; using System.Runtime.CompilerServices; using BITKit; using BITKit.StateMachine; using PaintIn3D; 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; } } } /// /// 填充笔刷,用于填充应该被裁剪的区域,类似油漆桶 /// [Serializable] public sealed class CuttingFillBrush : CuttingToolBrush { [SerializeField] private Transform transform; public override string Name => "填充切削"; public override string Description => "仅在该程序中使用,用于预览被裁剪的区域"; [Export(name:"自动填充")] private void AutoFill() { var p3dTexture = transform.GetComponentInChildren(); var texture = p3dTexture.Current.ToTexture2D(); var colors = texture.GetPixels(); var size = new float2(texture.width, texture.height); //洪水填充 throw new InGameException("暂未实现,算法有些复杂"); } } /// /// 印花笔刷,用于在表面上印花 /// [Serializable] public sealed class DecalBrush : CuttingToolBrush { public override string Name => "印花笔刷"; public override string Description => "在表面上印花,例如预览打印文字或者Logo,图案等"; [Inject] private IDecalTool _decalTool; private ITransform _previewTransform; public override void OnStateEntry(IState old) { base.OnStateEntry(old); _previewTransform = _decalTool.Create(string.Empty); } public override void OnStateExit(IState old, IState newState) { base.OnStateExit(old, newState); _previewTransform.Dispose(); } public override void HandlePoint(bool isPreview, float3 normal, float3 point) { if (isPreview is false) return; _previewTransform.Position = point+(float3)Vector3.up*0.1f; _previewTransform.Rotation = Quaternion.LookRotation(normal); } [Export(name:"选择图片")] private void SelectImage() { throw new InGameException("暂未实现",new NotImplementedException("需要一些小小的base64转换才能储存,暂未实现")); } } }