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;
///
/// 绘制轨迹线的操作
///
/// 当从其他WaitForUserInput_OpSlot到达此处时,将创建TerminalLine2T3用于线路的绘制,
/// 同时在线路的两端有两个TerminalPoint用于线路的相连。
///
/// 支持常规的线路连续绘制,起点吸附,终点吸附。
/// 不支持首尾相连。
///
///
public class DrawTerminalLine2T3_OpSlot : WaitForUserInput_OpSlot
{
#region 字段属性
///
/// 上一步的坐标
///
private Vector3 _lastPointPosition;
///
/// 上一步的对齐轨迹计算器
///
private Vector3 _lastPointNormal;
///
/// 下一步的坐标
///
private Vector3 _helperPosition = Vector3.zero;
///
/// 下一步的法向
///
private Vector3 _helperNormal = Vector3.zero;
///
/// 操作的轨迹线
///
private TerminalLine2T3 _line;
///
/// 起点
///
private TerminalPoint _startPoint;
///
/// 操作的点,也是终点
///
private TerminalPoint _endPoint;
///
/// 在场上找到的其他的点
///
private TerminalPoint _otherPoint;
///
/// 起点是用上一步的终点替代的
///
private bool _isStartPointSubstitute = false;
///
/// 绘制时,终点是自由点
///
private bool _isFreeEndPoint;
// public SesothoArrangementWiresTool myWiresTool;
// myWiresTool = targetTool as SesothoArrangementWiresTool;
#endregion
#region 引用封装
///
/// 创建自己的工具
///
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 方法
///
/// 设置先决属性
///
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);
}
///
/// 结束清理属性
///
private void EndPrecondition()
{
selfWiresTool.DeleteElement(_line);
// 不能把别人的东西给回收了
if (!_isStartPointSubstitute)
selfWiresTool.DeleteElement(_startPoint);
selfWiresTool.DeleteElement(_endPoint);
}
///
/// 线路绘制过程
///
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);
}
}
///
/// 获取光标下的起点
///
///
private bool GetCurrentObject()
{
// SesothoPeManager.
return false;
}
#endregion
}
}