Files
XericLibrary-Publish/Runtime/HorizonLineOrbit/DrawTerminalLine2T3_OpSlot.cs
2025-04-10 15:32:00 +08:00

365 lines
12 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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
}
}