365 lines
12 KiB
C#
365 lines
12 KiB
C#
using System;
|
||
using System.Collections;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using Deconstruction.Element;
|
||
using Deconstruction.Interface;
|
||
using Deconstruction.Manager;
|
||
using Deconstruction.Tool;
|
||
using Deconstruction.Trajectory;
|
||
using Deconstruction.Type.DMToolSlot;
|
||
using Deconstruction.Type.Linkable;
|
||
using UnityEngine;
|
||
using XericLibrary.Runtime.MacroLibrary;
|
||
|
||
namespace SesothoLine
|
||
{
|
||
using LineSegment2 = Deconstruction.Element.PromptLine2.LineSegment2;
|
||
|
||
/// <summary>
|
||
/// 绘制轨迹线的操作
|
||
/// <code>
|
||
/// 当从其他WaitForUserInput_OpSlot到达此处时,将创建TerminalLine2T3用于线路的绘制,
|
||
/// 同时在线路的两端有两个TerminalPoint用于线路的相连。
|
||
///
|
||
/// 支持常规的线路连续绘制,起点吸附,终点吸附。
|
||
/// 不支持首尾相连。
|
||
/// </code>
|
||
/// </summary>
|
||
public class DrawTerminalLine2T3_OpSlot : WaitForUserInput_OpSlot
|
||
{
|
||
#region 字段属性
|
||
|
||
/// <summary>
|
||
/// 上一步的坐标
|
||
/// </summary>
|
||
private Vector3 _lastPointPosition;
|
||
|
||
/// <summary>
|
||
/// 上一步的对齐轨迹计算器
|
||
/// </summary>
|
||
private Vector3 _lastPointNormal;
|
||
|
||
/// <summary>
|
||
/// 下一步的坐标
|
||
/// </summary>
|
||
private Vector3 _helperPosition = Vector3.zero;
|
||
|
||
/// <summary>
|
||
/// 下一步的法向
|
||
/// </summary>
|
||
private Vector3 _helperNormal = Vector3.zero;
|
||
|
||
/// <summary>
|
||
/// 操作的轨迹线
|
||
/// </summary>
|
||
private TerminalLine2T3 _line;
|
||
|
||
/// <summary>
|
||
/// 起点
|
||
/// </summary>
|
||
private TerminalPoint _startPoint;
|
||
|
||
/// <summary>
|
||
/// 操作的点,也是终点
|
||
/// </summary>
|
||
private TerminalPoint _endPoint;
|
||
|
||
/// <summary>
|
||
/// 在场上找到的其他的点
|
||
/// </summary>
|
||
private TerminalPoint _otherPoint;
|
||
|
||
/// <summary>
|
||
/// 起点是用上一步的终点替代的
|
||
/// </summary>
|
||
private bool _isStartPointSubstitute = false;
|
||
|
||
/// <summary>
|
||
/// 绘制时,终点是自由点
|
||
/// </summary>
|
||
private bool _isFreeEndPoint;
|
||
|
||
// public SesothoArrangementWiresTool myWiresTool;
|
||
// myWiresTool = targetTool as SesothoArrangementWiresTool;
|
||
|
||
#endregion
|
||
|
||
#region 引用封装
|
||
|
||
/// <summary>
|
||
/// 创建自己的工具
|
||
/// </summary>
|
||
private SesothoArrangementWiresTool selfWiresTool => SesothoPeManager.WiresTool;
|
||
|
||
#endregion
|
||
|
||
#region 生命周期
|
||
|
||
protected override void OnStart()
|
||
{
|
||
base.OnStart();
|
||
|
||
// 检查抵达此处的流程是否正确
|
||
if (!HasLastNode)
|
||
{
|
||
Debug.LogError(
|
||
$"绘制节点行为树顺序错误,必须从其他任意WaitForUserInput_OpSlot中抵达此处");
|
||
RemoveThis();
|
||
return;
|
||
}
|
||
|
||
if (Last is not WaitForUserInput_OpSlot)
|
||
{
|
||
Debug.LogError(
|
||
$"绘制节点行为树顺序错误,应该是 WaitForUserInput_OpSlot -> {nameof(DrawTerminalLine2T3_OpSlot)},而不是{Last.GetType().Name}");
|
||
RemoveThis();
|
||
return;
|
||
}
|
||
|
||
// 设置先决条件
|
||
InitPrecondition();
|
||
}
|
||
|
||
protected override void OnEnd()
|
||
{
|
||
base.OnEnd();
|
||
}
|
||
|
||
protected override void Update()
|
||
{
|
||
// 阻止基类的默认操作
|
||
// base.Update();
|
||
|
||
// 线的绘制计算,包括空间点吸附,链接等
|
||
DrawingProcess();
|
||
// 计算完毕后执行渲染,这里调用有可能会带来空引用问题
|
||
// 但在此之前的阶段已经对此进行过了处理所以没有关系,如果要在其他地方照抄的话需要注意。
|
||
_line.UpdateRender();
|
||
|
||
// 下一步
|
||
if (IsReleaseContinueKey())
|
||
{
|
||
_helperNormal = _line.TrajectoryCalculator.GetEndPointNormal.UpwardPlaneToVector3();
|
||
|
||
// 起点链接
|
||
if (_isStartPointSubstitute)
|
||
{
|
||
// 在开始时已经做过转换了
|
||
// var dtlt_Slot = Last as DrawTerminalLine2T3_OpSlot;
|
||
_line.LinkedDataAddPolarity(_startPoint, LinkType.Import);
|
||
}
|
||
else
|
||
{
|
||
_line.LinkedDataAddPolarity(_startPoint, LinkType.Import);
|
||
selfWiresTool.PersistentElement(_startPoint);
|
||
selfWiresTool.AddPeToNeighborGrid(_startPoint);
|
||
}
|
||
|
||
// 终点链接
|
||
if (_otherPoint is null) // || _endPoint.gameObject.activeSelf
|
||
{
|
||
_line.LinkedDataAddPolarity(_endPoint, LinkType.Export);
|
||
selfWiresTool.PersistentElement(_endPoint);
|
||
selfWiresTool.AddPeToNeighborGrid(_endPoint);
|
||
}
|
||
// 如果存在吸附目标
|
||
else
|
||
{
|
||
selfWiresTool.DeleteElement(_endPoint);
|
||
_line.LinkedDataAddPolarity(_otherPoint, LinkType.Export);
|
||
}
|
||
|
||
// 保存线
|
||
_line.ReapplyOrigin();
|
||
selfWiresTool.PersistentElement(_line);
|
||
selfWiresTool.AddBulkPeToNeighborGrid(_line);
|
||
|
||
// 下一步
|
||
ReplaceThis(new DrawTerminalLine2T3_OpSlot());
|
||
}
|
||
// 取消
|
||
else if (IsReleaseCanelKey())
|
||
{
|
||
RemoveThis();
|
||
EndPrecondition();
|
||
}
|
||
// todo: 回到上一步
|
||
/*
|
||
* 操作栈的结构使得操作与对象的更新可以分离,
|
||
* 就是撤回的过程可能有点复杂,
|
||
* 需要分为工具运行期间撤回和常规撤回。
|
||
*/
|
||
}
|
||
|
||
protected override void AsyncBeforeUpdate()
|
||
{
|
||
base.AsyncBeforeUpdate();
|
||
}
|
||
|
||
protected override void AsyncUpdate()
|
||
{
|
||
base.AsyncUpdate();
|
||
}
|
||
|
||
protected override void AsyncAfterUpdate()
|
||
{
|
||
base.AsyncAfterUpdate();
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 方法
|
||
|
||
/// <summary>
|
||
/// 设置先决属性
|
||
/// </summary>
|
||
private void InitPrecondition()
|
||
{
|
||
switch (Last)
|
||
{
|
||
// 使用来自前者的元素
|
||
case DrawTerminalLine2T3_OpSlot dtlt_Slot:
|
||
_isStartPointSubstitute = true;
|
||
_startPoint = dtlt_Slot._endPoint;
|
||
_lastPointPosition = dtlt_Slot._helperPosition;
|
||
_lastPointNormal = dtlt_Slot._helperNormal;
|
||
break;
|
||
// 新建,或从空间中继承
|
||
case WaitForUserInput_OpSlot wfui_Slot:
|
||
if (SesothoArrangementWiresTool.GetNearestObjectAsPoint(out var terminalPoint))
|
||
{
|
||
_isStartPointSubstitute = true;
|
||
_startPoint = terminalPoint;
|
||
_lastPointPosition = terminalPoint.GetPosition3();
|
||
if (SesothoArrangementWiresTool.GetNearestObjectAsLine(terminalPoint, out var terminalLine,
|
||
out var normal))
|
||
_lastPointNormal = normal;
|
||
else
|
||
{
|
||
Debug.LogError("错误:当前绘制的线路准备吸附的目标并非一个完整的链路,或类型错误,正在退出。");
|
||
RemoveThis();
|
||
}
|
||
}
|
||
else
|
||
{
|
||
_isStartPointSubstitute = false;
|
||
selfWiresTool.GetElement(out _startPoint);
|
||
_lastPointPosition = SesothoArrangementWiresTool.OpKey_IgnoreNeighborAdsorption.Getkey() ?
|
||
wfui_Slot.MouseHelperPosition :
|
||
CameraMouseInputHelper.Inst.GetGridAdsorb(wfui_Slot.MouseHelperPosition);
|
||
_lastPointNormal = default;
|
||
}
|
||
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
|
||
selfWiresTool.GetElement(out _line);
|
||
selfWiresTool.GetElement(out _endPoint);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 结束清理属性
|
||
/// </summary>
|
||
private void EndPrecondition()
|
||
{
|
||
selfWiresTool.DeleteElement(_line);
|
||
// 不能把别人的东西给回收了
|
||
if (!_isStartPointSubstitute)
|
||
selfWiresTool.DeleteElement(_startPoint);
|
||
selfWiresTool.DeleteElement(_endPoint);
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 线路绘制过程
|
||
/// </summary>
|
||
private void DrawingProcess()
|
||
{
|
||
// 获取当前的坐标
|
||
_helperPosition = PlaceElementManager.Inst.InputHelper.CurrentGridPosition;
|
||
|
||
_startPoint.transform.position = _lastPointPosition;
|
||
|
||
_isFreeEndPoint = true;
|
||
// 如果吸附到任意物体,或者用按键忽略这一过程
|
||
if (SesothoPeManager.NearestObject is not null &&
|
||
SesothoArrangementWiresTool.GetNearestObjectAsPoint(out _otherPoint) &&
|
||
!SesothoArrangementWiresTool.OpKey_IgnoreNeighborAdsorption.Getkey())
|
||
{
|
||
_isFreeEndPoint = false;
|
||
if (_endPoint.gameObject.activeSelf)
|
||
_endPoint.gameObject.SetActive(false);
|
||
|
||
_helperPosition = SesothoPeManager.NearestPoint;
|
||
_endPoint.transform.position = SesothoPeManager.NearestPoint;
|
||
if (SesothoArrangementWiresTool.GetNearestObjectAsLine(_otherPoint, out var terminalLine,
|
||
out var normal))
|
||
_helperNormal = normal;
|
||
}
|
||
// 如果吸附到任意切线
|
||
// else if (NearestLineTangentObject != null)
|
||
// {
|
||
// NearestLineTangentPoint
|
||
// }
|
||
|
||
// 否则自由点
|
||
if (_isFreeEndPoint)
|
||
{
|
||
if (!_endPoint.gameObject.activeSelf)
|
||
_endPoint.gameObject.SetActive(true);
|
||
_otherPoint = null;
|
||
_helperNormal = default;
|
||
_endPoint.transform.position = _helperPosition;
|
||
}
|
||
|
||
_line.SetLineSegment(
|
||
_lastPointPosition, _helperPosition,
|
||
_lastPointNormal, _helperNormal
|
||
);
|
||
|
||
// 如果当前线的线计算器是圆弧计算器,那么获取它的角度
|
||
// if (_line.NowCalculator is RoundTrajectory2 arc)
|
||
// {
|
||
// Debug.Log($"角度{arc.Angle} {arc.AngleExact}");
|
||
// }
|
||
|
||
var forceStr = SesothoArrangementWiresTool.OpKey_ForceStr.Getkey();
|
||
if (forceStr)
|
||
_line.DrawStraightLine();
|
||
else
|
||
{
|
||
var force90Arc = SesothoArrangementWiresTool.OpKey_90Arc.Getkey();
|
||
var force180Arc = SesothoArrangementWiresTool.OpKey_180Arc.Getkey();
|
||
var forceRevCisoid = SesothoArrangementWiresTool.OpKey_RevCisoid.Getkey();
|
||
|
||
|
||
var angle = -1;
|
||
if (force90Arc || force180Arc)
|
||
{
|
||
angle = 0;
|
||
if (force90Arc)
|
||
angle += 90;
|
||
if (force180Arc)
|
||
angle += 180;
|
||
}
|
||
|
||
_line.AutomaticDrawCircularLine(angle, forceRevCisoid);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取光标下的起点
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
private bool GetCurrentObject()
|
||
{
|
||
// SesothoPeManager.
|
||
return false;
|
||
}
|
||
|
||
#endregion
|
||
}
|
||
} |