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

246 lines
6.2 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.CompilerServices;
using BITKit;
using BITKit.StateMachine;
using Newtonsoft.Json;
using PaintIn3D;
using Unity.Collections;
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 => "按住鼠标左键进行画笔切削";
[Export("切削半径")]
public float Radius = 0;
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 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;
}
}
}
/// <summary>
/// 填充笔刷,用于填充应该被裁剪的区域,类似油漆桶
/// </summary>
[Serializable]
public sealed class CuttingFillBrush : CuttingToolBrush
{
[SerializeField] private Transform transform;
public override string Name => "填充切削";
public override string Description => "仅在该程序中使用,用于预览被裁剪的区域\n事实上现在用于测试运行时序列化字段";
[Export(name:"字符串列表")] private List<string> stringList = new();
[Export(name:"单浮点列表")] private List<float> floatList = new();
[Export(name:"整数列表")] private List<int> intList = new();
[Export(name:"字符串数组")] private string[] stringArray = Array.Empty<string>();
[Export(name:"单浮点数组")] private float[] floatArray = Array.Empty<float>();
[Export(name:"整数数组")] private int[] intArray = Array.Empty<int>();
[Export(name:"float3数组")] private float3 position;
public override void ReleasePoint(float3 normal, float3 point)
{
base.ReleasePoint(normal, point);
stringList.Add(JsonConvert.SerializeObject((Vector3)point));
}
[Export(name:"自动填充")]
private void AutoFill()
{
var p3dTexture = transform.GetComponentInChildren<P3dPaintableTexture>();
var texture = p3dTexture.Current.ToTexture2D();
var colors = texture.GetPixels();
var size = new float2(texture.width, texture.height);
//洪水填充
throw new InGameException("暂未实现,算法有些复杂");
}
}
/// <summary>
/// 印花笔刷,用于在表面上印花
/// </summary>
[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转换才能储存,暂未实现"));
}
}
}