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

312 lines
7.4 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using BITKit;
using BITKit.CommandPattern;
using BITKit.Entities;
using BITKit.IO;
using Cysharp.Threading.Tasks;
using PaintIn3D;
using Unity.Mathematics;
using UnityEngine;
namespace BITFactory.Cutting
{
[Serializable]
public sealed class DIUnityCuttingTool : InjectFromDI<ICuttingTool>,ICuttingTool
{
private ICuttingTool _cuttingToolImplementation => Value;
public ICommand[] Commands => _cuttingToolImplementation.Commands;
public event Action<ICommand> OnExecute
{
add => _cuttingToolImplementation.OnExecute += value;
remove => _cuttingToolImplementation.OnExecute -= value;
}
public event Action<ICommand> OnClear
{
add => _cuttingToolImplementation.OnClear += value;
remove => _cuttingToolImplementation.OnClear -= value;
}
public event Action<ICommand> OnUndo
{
add => _cuttingToolImplementation.OnUndo += value;
remove => _cuttingToolImplementation.OnUndo -= value;
}
public event Action<ICommand[]> OnRelease
{
add => _cuttingToolImplementation.OnRelease += value;
remove => _cuttingToolImplementation.OnRelease -= value;
}
public void Execute(ICommand command)
{
_cuttingToolImplementation.Execute(command);
}
public void Undo()
{
_cuttingToolImplementation.Undo();
}
public void Undo(int count)
{
_cuttingToolImplementation.Undo(count);
}
public void Redo()
{
_cuttingToolImplementation.Redo();
}
public void Trace(ICommand command)
{
_cuttingToolImplementation.Trace(command);
}
public void Clear()
{
_cuttingToolImplementation.Clear();
}
public void Rebuild() => _cuttingToolImplementation.Rebuild();
public void Release() => _cuttingToolImplementation.Release();
public void CutPlanePoint(bool preview, float3 planeNormal, float3 planePoint)
{
_cuttingToolImplementation.CutPlanePoint(preview, planeNormal, planePoint);
}
public void CutPlantSphere(bool preview, float3 planeNormal, float3 planePoint, float radius)
{
_cuttingToolImplementation.CutPlantSphere(preview, planeNormal, planePoint, radius);
}
public void CutPlaneBox(bool preview, float3 planeNormal, float3 planePoint, float3 boxSize)
{
_cuttingToolImplementation.CutPlaneBox(preview, planeNormal, planePoint, boxSize);
}
public void CutPlaneLine(bool preview, float3 planeNormal, float3[] line)
{
_cuttingToolImplementation.CutPlaneLine(preview, planeNormal, line);
}
public void FillPlanePoint(bool preview, float3 planeNormal, float3 planePoint)
{
_cuttingToolImplementation.FillPlanePoint(preview, planeNormal, planePoint);
}
}
[CustomType(typeof(ICuttingTool),true)]
public class UnityCuttingTool : EntityBehavior,ICuttingTool
{
[SerializeField] private float defaultPointRadius = 0.1f;
[SerializeReference, SubclassSelector] private IApplicationFile applicationFile;
private P3dPaintSphere paintSphere
{
get
{
if (!_paintSphere)
{
_paintSphere = GetComponentInChildren<P3dPaintSphere>();
}
return _paintSphere;
}
}
private P3dPaintSphere _paintSphere;
private readonly CommandSequence _commands=new();
private readonly CommandSequence _executedCommands=new();
private void Awake()
{
DI.Register<ICuttingTool>(this);
}
private void OnEnable()
{
applicationFile.DataHandle += OnDataHandle;
applicationFile.AddListener(nameof(UnityCuttingTool),OnData);
}
private void OnDisable()
{
applicationFile.DataHandle -= OnDataHandle;
applicationFile.RemoveListener(nameof(UnityCuttingTool),OnData);
}
private (string, byte[]) OnDataHandle()
{
return new(nameof(UnityCuttingTool), BITBinary.WriteAsBytes(_executedCommands));
}
private async void OnData(byte[] obj)
{
await UniTask.NextFrame();
if (destroyCancellationToken.IsCancellationRequested) return;
Clear();
var seq = BITBinary.Read<CommandSequence>(obj);
_commands.AddRange(seq);
_executedCommands.AddRange(seq);
Rebuild();
}
public void CutPlanePoint(bool preview, float3 planeNormal, float3 planePoint)
{
paintSphere.Radius = defaultPointRadius;
paintSphere.HandleHitLine(
preview,
0,
1.0f,
0,
planePoint+planeNormal*1,
planePoint-planeNormal*1,
Quaternion.LookRotation(planeNormal),true);
}
public void CutPlantSphere(bool preview, float3 planeNormal, float3 planePoint, float radius)
{
paintSphere.Radius = radius;
paintSphere.HandleHitLine(
preview,
0,
1.0f,
0,
planePoint+planeNormal*1,
planePoint-planeNormal*1,
Quaternion.LookRotation(planeNormal),true);
}
public void CutPlaneBox(bool preview, float3 planeNormal, float3 planePoint, float3 boxSize)
{
throw new System.NotImplementedException();
}
public void CutPlaneLine(bool preview, float3 planeNormal, float3[] line)
{
paintSphere.Radius = defaultPointRadius;
var lastPoint = line[0];
foreach (var pos in line)
{
paintSphere.HandleHitLine(
preview,
0,
1.0f,
0,
lastPoint,
pos,
Quaternion.LookRotation(planeNormal),true);
lastPoint = pos;
}
}
public void FillPlanePoint(bool preview, float3 planeNormal, float3 planePoint)
{
var texture = (Texture2D)_paintSphere.TargetTexture.Texture;
}
public ICommand[] Commands =>_executedCommands.ToArray();
public event Action<ICommand> OnExecute;
public event Action<ICommand> OnClear;
public event Action<ICommand> OnUndo;
public event Action<ICommand[]> OnRelease;
public void Execute(ICommand command)
{
_commands.Add(command);
OnExecute?.Invoke(command);
_executedCommands.Add(command);
ExecuteInternal(command);
}
public void Undo()
{
if(_executedCommands.Count==0)return;
var command = _executedCommands[^1];
command.Undo();
_executedCommands.RemoveAt(_executedCommands.Count-1);
OnClear?.Invoke(null);
paintSphere.TargetTexture.Clear();
foreach (var x in _executedCommands)
{
ExecuteInternal(x);
OnExecute?.Invoke(x);
}
}
public void Undo(int count)
{
throw new System.NotImplementedException();
}
public void Redo()
{
throw new System.NotImplementedException();
}
public void Trace(ICommand command)
{
var index = _commands.IndexOf(command);
paintSphere.TargetTexture.Clear();
OnClear?.Invoke(command);
_executedCommands.Clear();
_executedCommands.AddRange(_commands.GetRange(0, index));
foreach (var x in _executedCommands)
{
ExecuteInternal(x);
OnExecute?.Invoke(x);
}
}
public void Clear()
{
OnClear?.Invoke(null);
_executedCommands.Clear();
_commands.Clear();
paintSphere.TargetTexture.Clear();
}
public void Rebuild()
{
OnClear?.Invoke(null);
foreach (var x in _executedCommands)
{
ExecuteInternal(x);
OnExecute?.Invoke(x);
}
}
public void Release()
{
OnRelease?.Invoke(_executedCommands.ToArray());
}
private void ExecuteInternal(ICommand command)
{
switch (command)
{
case CuttingPointCommand cuttingPointCommand:
CutPlanePoint(false,cuttingPointCommand.PlaneNormal,cuttingPointCommand.PlanePoint);
break;
case CuttingSphereCommand sphereCommand:
CutPlantSphere(false,sphereCommand.PlaneNormal,sphereCommand.PlanePoint,sphereCommand.Radius);
break;
case CuttingLineCommand lineCommand:
CutPlaneLine(false,lineCommand.PlaneNormal,lineCommand.Line);
break;
}
}
}
}