旧工作内容移动至示例

This commit is contained in:
2025-06-09 17:04:40 +08:00
parent f79ea6bd00
commit cc5ddb194e
52 changed files with 1652 additions and 7 deletions
-8
View File
@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: f8777f3ce94f12747a9c712730114c5b
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -1,365 +0,0 @@
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
}
}
@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: d957a4fb102b5a649b52cd9f76b57f93
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -1,24 +0,0 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace SesothoLine
{
/// <summary>
/// 可链接的对象,表示此成员内包含一个链表的节点,可用于链表跟踪
/// </summary>
public interface ILinkconfident<T>
{
/// <summary>
/// 获取链接点
/// </summary>
/// <param name="node"></param>
/// <returns></returns>
public bool GetLinkedNode(out LinkedListNode<T> node);
/// <summary>
/// 设置连接点
/// </summary>
/// <param name="node"></param>
public void SetLinkedNode(LinkedListNode<T> node);
}
}
@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 99f791f3c433086449c6544bc265841d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -1,13 +0,0 @@
using System.Collections;
using System.Collections.Generic;
using Deconstruction.Element;
using UnityEngine;
namespace SesothoLine
{
/// <summary>
/// 可链接的对象,表示此成员内包含一个链表的节点,可用于链表跟踪
/// </summary>
public interface ILinkconfidentPe : ILinkconfident<PlacementBase>
{ }
}
@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 9723e804f97bc024c8e1e1d6f8bc80a1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -1,558 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using Deconstruction.Element;
using Deconstruction.Interface;
using Deconstruction.Manager;
using Deconstruction.Tool;
using Deconstruction.Type;
using Deconstruction.Type.DMToolSlot;
using Deconstruction.Type.Linkable;
using SerializerHelper.Type;
using UnityEngine;
using UnityEngine.Pool;
using XericLibrary.Runtime.MacroLibrary;
using XericLibrary.Runtime.Nav;
namespace SesothoLine
{
/// <summary>
/// 线路绘制工具类
/// </summary>
public class SesothoArrangementWiresTool : DecisionMakerToolBase
{
#region 事件委托
/// <summary>
/// 工具中成员变更委托
/// </summary>
public delegate void ToolMemberChange(PlacementBase obj);
/// <summary>
/// 工具中成员添加事件
/// </summary>
public event ToolMemberChange OnAdditional;
/// <summary>
/// 工具中成员移除事件
/// </summary>
public event ToolMemberChange OnDecreasing;
/// <summary>
/// 当任意元素苏醒
/// </summary>
public event ToolMemberChange OnAnyVivification;
/// <summary>
/// 当任意元素休眠
/// </summary>
public event ToolMemberChange OnAnyDormancy;
#endregion
#region 快捷键
/*
* 1 控制强制直线
* 2,3 控制圆弧的角度为90和180度
* R 反转圆弧
* shift+b 忽略对象吸附
* shift+n 忽略网格吸附
*/
/// <summary>
/// 强制直线
/// </summary>
public static KeyPack OpKey_ForceStr = new KeyPack(KeyCode.Alpha1);
/// <summary>
/// 强制90度圆弧
/// </summary>
public static KeyPack OpKey_90Arc = new KeyPack(KeyCode.Alpha2);
/// <summary>
/// 强制180度圆弧
/// </summary>
public static KeyPack OpKey_180Arc = new KeyPack(KeyCode.Alpha3);
/// <summary>
/// 反转顺向,比如单圆弧的方向翻转。
/// 话说shift+alt+r是英伟达的一个快捷键呢,有点冲突
/// </summary>
public static KeyPack OpKey_RevCisoid = new KeyPack(KeyCode.R);
/// <summary>
/// 忽略吸附功能
/// </summary>
public static KeyPack OpKey_IgnoreNeighborAdsorption = new KeyPack(KeyCode.LeftShift, KeyCode.B);
/// <summary>
/// 忽略网格吸附
/// </summary>
public static KeyPack OpKey_IgnoreGridAdsorption = new KeyPack(KeyCode.LeftShift, KeyCode.N);
#endregion
#region 字段属性
private ObjectPool<TerminalLine2T3> _linePool;
private ObjectPool<TerminalPoint> _pointPool;
#endregion
#region 获取转换
/// <summary>
/// 获取光标下最近的对象为点
/// </summary>
/// <param name="point"></param>
/// <returns></returns>
public static bool GetNearestObjectAsPoint(out TerminalPoint point)
{
if (SesothoPeManager.NearestObject is not null &&
SesothoPeManager.NearestObject is TerminalPoint terminalPoint)
{
point = terminalPoint;
return true;
}
point = null;
return false;
}
/// <summary>
/// 获取光标下最近的对象为线
/// </summary>
/// <param name="line"></param>
/// <returns></returns>
public static bool GetNearestObjectAsLine(out TerminalLine2T3 line)
{
if (SesothoPeManager.NearestObject is not null &&
SesothoPeManager.NearestObject is TerminalPoint terminalPoint &&
terminalPoint.LinkedData.GetOpposite(LinkType.Export) is TerminalLine2T3 terminalLine)
{
line = terminalLine;
return true;
}
line = null;
return false;
}
/// <summary>
/// 获取以给定点上与最近的相切线相对
/// </summary>
/// <param name="point"></param>
/// <param name="line"></param>
/// <param name="normal"></param>
/// <returns></returns>
public static bool GetNearestObjectAsLine(TerminalPoint point, out TerminalLine2T3 line, out Vector3 normal)
{
if (point is null)
goto End;
// 检查最近线切线是否有效,是否相连
if (SesothoPeManager.NearestLineTangentObject is TerminalLine2T3 otherLine &&
point.TryGetLinkLineNormal(otherLine, out normal))
{
line = otherLine;
return true;
}
End:
line = null;
normal = default;
return false;
}
#endregion
#region 生命周期
protected override void Awake()
{
base.Awake();
_linePool = new ObjectPool<TerminalLine2T3>(
createFunc: CreatElement<TerminalLine2T3>,
actionOnGet: ElementActive,
actionOnRelease: ElementInactive,
actionOnDestroy: a =>
{ },
collectionCheck: true,
defaultCapacity: 10,
maxSize: 10000);
_pointPool = new ObjectPool<TerminalPoint>(
createFunc: CreatElement<TerminalPoint>,
actionOnGet: ElementActive,
actionOnRelease: ElementInactive,
actionOnDestroy: a =>
{ },
collectionCheck: true,
defaultCapacity: 10,
maxSize: 10000);
}
protected override void OnEnableTool()
{
// 启用时创建一个输入等待行为,随后进入绘制行为
var target = GenerateOperateSlot<WaitForUserInput_OpSlot>();
target.InitializeNextTodo(() => new DrawTerminalLine2T3_OpSlot());
Debug.Log("激活线路绘制工具");
}
protected override void OnDisableTool()
{
}
protected override void OnFinalEnd()
{
base.OnFinalEnd();
EnableTool = false;
}
#endregion
#region 序列化
public override SerializeUnion ToolSerializeDispost()
{
base.ToolSerializeDispost();
foreach (var element in PlaceElementManager.Inst.StructuralLinkedList)
{
var union = element.SerializedOccurs();
// 索引是后面用来标识类的
union.Index = TypeConsignMap.AddMapIndex(element.GetType());
union.RefreshSerializedContext();
SerializeTemp.Add(union);
}
SerializeTemp.RefreshSerializedContext();
return SerializeTemp;
}
public override bool ToolDiserializDispost(SerializeUnion context)
{
if (!base.ToolDiserializDispost(context))
return false;
var deserializeList = new List<(PlacementBase, SerializeUnion)>();
var safeCount = ushort.MaxValue;
Debug.Log("反序列化过程开始创建对象");
while (0 <-- safeCount && SerializeTemp.IndexMoveToNext(out var block))
{
var union = SerializeTemp.GetDeserializeObject<SerializeUnion>();
var type = TypeConsignMap.GetMapType(union.Index);
if (GetElement(type, out var obj))
{
deserializeList.Add((obj, union));
union.RefreshDeserializeContext();
union.IndexMoveToStart();
obj.DeserializeOccurs(union);
// switch (obj)
// {
// case TerminalLine2T3 line:
// line.DeserializeOccurs(union);
// break;
// case TerminalPoint point:
// point.DeserializeOccurs(union);
// break;
// }
}
else
Debug.LogError($"无法创建序列化元素,原因是类型不支持{type}");
if (block) break;
}
Debug.Log("反序列化过程开始恢复链接关系");
foreach (var item in deserializeList)
item.Item1.DeserializeHysteresisOccurs(item.Item2);
return true;
}
#endregion
#region 方法
/// <summary>
/// 创建元素
/// </summary>
/// <returns></returns>
private T CreatElement<T>()
where T : PlacementBase, ILinkconfidentPe
{
var obj = CreatPlacementObject<T>();
obj.OnPlancementDestory += a =>
{
if (a is null)
{
Debug.LogError("元素已经被销毁,无法回收链表元素");
return;
}
if (a is T b &&
b.GetLinkedNode(out var node))
SesothoPeManager.Inst.RemoveLinkedTarget(node);
else
Debug.LogError("元素并非工具元素类型,或者其中的链表节点已丢失,导致无法回收链表元素");
};
return obj;
}
/// <summary>
/// 池对象激活
/// </summary>
/// <param name="obj"></param>
/// <typeparam name="T"></typeparam>
private void ElementActive<T>(T obj)
where T : PlacementBase, ILinkconfidentPe
{
obj.gameObject.SetActive(true);
OnAnyVivification?.Invoke(obj);
}
/// <summary>
/// 池对象取消激活
/// </summary>
/// <param name="obj"></param>
/// <typeparam name="T"></typeparam>
private void ElementInactive<T>(T obj)
where T : PlacementBase, ILinkconfidentPe
{
obj.gameObject.SetActive(false);
OnAnyDormancy?.Invoke(obj);
}
/// <summary>
/// 获取元素
/// </summary>
/// <returns></returns>
public bool GetElement<T>(out T obj)
where T : PlacementBase, ILinkconfidentPe
{
var name = typeof(T).Name;
switch (name)
{
case nameof(TerminalLine2T3):
obj = _linePool.Get() as T;
return true;
case nameof(TerminalPoint):
obj = _pointPool.Get() as T;
return true;
default:
Debug.LogError($"给定的元素类型({name})并非预期,这将跳过对象池过程");
break;
}
obj = null;
return false;
}
/// <summary>
/// 获取元素
/// </summary>
/// <param name="type"></param>
/// <param name="obj"></param>
/// <returns></returns>
public bool GetElement(Type type, out PlacementBase obj)
{
var name = type.Name;
switch (name)
{
case nameof(TerminalLine2T3):
obj = _linePool.Get();
return true;
case nameof(TerminalPoint):
obj = _pointPool.Get();
return true;
default:
Debug.LogError($"给定的元素类型({name})并非预期,这将跳过对象池过程");
break;
}
obj = null;
return false;
}
/// <summary>
/// 删除元素
/// </summary>
/// <param name="obj"></param>
/// <typeparam name="T"></typeparam>
public void DeleteElement<T>(T obj)
where T : PlacementBase,
ILinkconfidentPe
{
var name = typeof(T).Name;
switch (name)
{
case nameof(TerminalLine2T3):
_linePool.Release(obj as TerminalLine2T3);
break;
case nameof(TerminalPoint):
_pointPool.Release(obj as TerminalPoint);
break;
default:
Debug.LogError($"给定的元素类型({name})并非预期,这将跳过对象池过程");
break;
}
}
/// <summary>
/// 保存元素链,在创建并常态化元素后都需要执行的操作 (注意不是在创建后立刻保存)
/// <code>
/// 如果这是一个线,那么还应该调用 AddBulkLineToNeighborGrid;
/// 如果这是一个点,那么应该调用 AddPeToNeighborGrid。
/// </code>
/// </summary>
public void PersistentElement<T>(T obj)
where T : PlacementBase,
ILinkconfidentPe
{
// 保存链表结构,反过来也持有这个节点,便于后续查找
var lineNode = SesothoPeManager.Inst.AddLinkedTarget(obj);
obj.SetLinkedNode(lineNode);
}
/// <summary>
/// 移除元素链
/// </summary>
/// <param name="obj"></param>
/// <typeparam name="T"></typeparam>
public void ExcisionElement<T>(T obj)
where T : PlacementBase,
ILinkconfidentPe
{
if (obj.GetLinkedNode(out var node))
SesothoPeManager.Inst.RemoveLinkedTarget(node);
}
/// <summary>
/// 添加小型元素到网格中
/// </summary>
/// <param name="obj"></param>
/// <typeparam name="T"></typeparam>
public void AddPeToNeighborGrid<T>(T obj)
where T : PlacementBase,
ILinkconfidentPe
{
if (obj.NeighborGridIndex != null)
{
Debug.LogError("无法重复插入元素:当前向管理器中插入的的元素,可能已经存在于其他管理器内,请先退出其他管理器后重试。");
return;
}
SesothoPeManager.Inst.InsertNeighbor(obj, out var index);
obj.NeighborGridIndex = index;
// 回调事件
OnAdditional?.Invoke(obj);
}
/// <summary>
/// 添加大型元素到网格中
/// </summary>
public void AddBulkPeToNeighborGrid<T>(T obj)
where T : PlacementBase,
ILinkconfidentPe,
IPossessorTrajectory2
{
if (obj.NeighborGridIndex != null)
{
Debug.LogError("无法重复插入元素:当前向管理器中插入的的元素,可能已经存在于其他管理器内,请先退出其他管理器后重试。");
return;
}
SesothoPeManager.Inst.InsertGiantNeighbor<T>(obj, out var index);
obj.NeighborGridIndex = index;
// 回调事件
OnAdditional?.Invoke(obj);
}
/// <summary>
/// 移除这个小元素
/// </summary>
/// <param name="obj"></param>
/// <typeparam name="T"></typeparam>
public void RemovePeToNeighborGrid<T>(T obj)
where T : PlacementBase,
ILinkconfidentPe
{
if (obj.NeighborGridIndex != null &&
obj.NeighborGridIndex.GetAsIndex(out var index))
SesothoPeManager.Inst.RemoveNeighbor(index);
else
SesothoPeManager.Inst.RemoveNeighbor(obj);
ExcisionElement(obj);
// 回调事件
OnDecreasing?.Invoke(obj);
}
/// <summary>
/// 移除这个大型元素
/// </summary>
public void RemoveBulkPeFormNeighborGrid<T>(T obj)
where T : PlacementBase,
ILinkconfidentPe,
IPossessorTrajectory2
{
if (obj.NeighborGridIndex != null &&
obj.NeighborGridIndex.GetAsMappingIndex(out var index))
SesothoPeManager.Inst.RemoveGiantNeighbor(index);
else
SesothoPeManager.Inst.RemoveGiantNeighbor<T>(obj);
ExcisionElement(obj);
// 回调事件
OnDecreasing?.Invoke(obj);
}
#endregion
#region 绘制寻路
/*
* 没写完,如果不嫌麻烦可以看看Astart类,或者自己实现。
*
* 主要提供绘制线路时的多段线拟合,障碍物避让
*/
/// <summary>
/// 获取一个可以通过的路径
/// <code>
/// 这是一个只在向上的二维平面上有效的路径。
/// 寻路的规则是仅避开建筑物,贪婪算法。
/// </code>
/// </summary>
/// <param name="startPoint">起点</param>
/// <param name="endPoint">终点</param>
/// <param name="avoidRadius">避让半径,在遭遇碰撞时将沿法向退回这个距离</param>
public DrawWayPoints GetPassThroughRouteShortcut(Vector3 startPoint, Vector3 endPoint, float avoidRadius)
{
var result = new DrawWayPoints();
Debug.LogError("此方法未完成");
return result;
}
/// <summary>
/// 获取一个可以通过的路径的迭代器;
/// </summary>
/// <param name="startPoint">起点</param>
/// <param name="endPoint">终点</param>
/// <param name="avoidRadius">避让半径,在遭遇障碍时将沿法向退回这个距离</param>
/// <param name="layer">检查碰撞对象的层</param>
/// <returns></returns>
protected IEnumerable<Vector3> GetPassThroughRoute(Vector3 startPoint, Vector3 endPoint, float avoidRadius, LayerMask layer)
{
yield return Vector3.zero;
}
/// <summary>
/// 使用给定的路径创建一段工具拟合的路径
/// </summary>
/// <param name="wayPoints">一段路径</param>
public void BuildPaths(DrawWayPoints wayPoints)
{
new AStart2();
}
#endregion
}
}
@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: de244510f627b4846a80a7402e13d3de
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -1,187 +0,0 @@
#define _DEBUG_
// #undef _DEBUG_
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Deconstruction.Element;
using UnityEngine;
using Deconstruction.Manager;
using Deconstruction.Tool;
using Deconstruction.Type.Area;
using Deconstruction.Type.Serialize;
using Newtonsoft.Json;
using SerializerHelper.Type;
using UnityEngine.UI;
using XericLibrary.Runtime.Debuger;
using XericLibrary.Runtime.MacroLibrary;
namespace SesothoLine
{
/// <summary>
/// 主要管理器
/// <code>
/// 不建议继续封装管理器类
/// </code>
/// </summary>
public sealed class SesothoPeManager : PlaceElementManager
{
#region 静态成员
/// <summary>
/// 此处提供的单例与父类单例是独立的
/// </summary>
public new static SesothoPeManager Inst => _inst;
private static SesothoPeManager _inst;
/// <summary>
/// 线路绘制工具
/// </summary>
public static SesothoArrangementWiresTool WiresTool => _wiresTool;
private static SesothoArrangementWiresTool _wiresTool;
/// <summary>
/// 光标下最近的线上交点
/// </summary>
public static Vector3 NearestLineTangentPoint => _lineTangentTraceTool.NearsetPoint;
/// <summary>
/// 光标下最近的线
/// </summary>
public static PlacementBase NearestLineTangentObject => _lineTangentTraceTool.NearsetObject;
/// <summary>
/// 光标下最近的对象原点
/// </summary>
public static Vector3 NearestPoint => TrackingTool.TrackingCurrentPosition;
/// <summary>
/// 光标下最近的对象
/// </summary>
public static PlacementBase NearestObject => TrackingTool.TrackingCurrentTarget;
private static TrajectoryTrackingTool.TrackPersistentCommunicate _lineTangentTraceTool;
#endregion
#region 调试功能
#if UNITY_EDITOR
public bool EnableGridDebugDraw = false;
public void DebugFunc()
{
if (EnableGridDebugDraw)
{
PlacementNeighbor.DebugDrawGrid();
}
}
#endif
#endregion
#region 生命周期
protected override void Awake()
{
base.Awake();
_inst = this;
if (LineMaterial == null)
Debug.LogError("需要给管理器提供一个线段材质");
if (PointMaterial == null)
Debug.LogError("需要给管理器提供一个点材质");
// 初始化画线工具
_wiresTool = new SesothoArrangementWiresTool();
_wiresTool.InitializeParent(transform);
_lineTangentTraceTool = TrackingTool.InstantiationTrackCaculate(PlaceholdersAreaType.LinearContinuity);
// 手动开启代理更新
EnableUpdate = true;
}
protected override void Start()
{
base.Start();
}
private NeighborGrid<PlacementBase>.NeighborGridIndex index;
protected override void Update()
{
base.Update();
#if UNITY_EDITOR
DebugFunc();
#endif
if (Input.GetMouseButtonDown(2))
{
index = PlacementNeighbor.GetNeighborIndex(null);
index.SetDrivenAsWorld(InputHelper.CurrentPosition);
Debug.Log($"{index.GetDrivenAsLinear()} => {index.GetNeighbor().FirstOrDefault()}");
}
// new SerializeUnion();
}
private string serializeContext = null;
protected override void LateUpdate()
{
base.LateUpdate();
// if (DecisionMakerToolBase.ActiveDecisionMaker == null ||
// !DecisionMakerToolBase.ActiveDecisionMaker.EnableTool)
#if !UNITY_EDITOR || !_DEBUG_
return;
#endif
// 工具功能测试
if (Input.GetKeyDown(KeyCode.L))
{
_wiresTool.EnableTool = !_wiresTool.EnableTool;
Debug.Log($"{(_wiresTool.EnableTool ? "绘制工具已激活" : "工具已取消激活")}");
}
// 存档功能测试
if (Input.GetKeyDown(KeyCode.S))
{
var obj = _wiresTool.ToolSerializeDispost();
serializeContext = JsonConvert.SerializeObject(obj);
Debug.Log(obj.ToString());
}
if (Input.GetKeyDown(KeyCode.D))
{
if (serializeContext == null)
{
Debug.Log("反序列化内容为空");
return;
}
var obj = JsonConvert.DeserializeObject<SerializeUnion>(serializeContext);
_wiresTool.ToolDiserializDispost(obj);
}
if (Input.GetKeyDown(KeyCode.A))
{
_wiresTool.EnableCompress = !_wiresTool.EnableCompress;
if (_wiresTool.EnableCompress )
Debug.Log("开启压缩");
else
Debug.Log("关闭压缩");
}
// 绘制一下吸附的目标位置
if (TrackingTool.EnableTool || TrackingTool._enableAuxiliaryTool)
{
MacroDebugDraw.DrawDownArrow(NearestPoint, Quaternion.identity, Color.magenta);
MacroDebugDraw.DrawDownArrow(NearestLineTangentPoint, Quaternion.identity, Color.green);
}
}
#endregion
}
}
@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 7825d9ef51f777c48aa66f3c83640259
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
-224
View File
@@ -1,224 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using Deconstruction.Element;
using Deconstruction.Interface;
#if UNITY_EDITOR
using UnityEditor;
#endif
using UnityEngine;
using UnityEngine.Serialization;
using XericLibrary.Runtime.Debuger;
using XericLibrary.Runtime.MacroLibrary;
using XericLibrary.Runtime.Type;
namespace SesothoLine
{
using LineSegment2 = Deconstruction.Element.PromptLine2.LineSegment2;
/// <summary>
/// 线终端执行脚本,使用二维线计算器,驱动三维线渲染器。
/// </summary>
public class TerminalLine2T3 : PromptLine2,
ILinkconfidentPe // 链表跟踪
{
#region 字段属性
private LinkedListNode<PlacementBase> _linkNode;
/// <summary>
/// 本地缓存
/// </summary>
private LineSegment2 _lineSegment = new LineSegment2();
public bool DebugDrawGrid = false;
#endregion
#region 生命周期
protected override void Start()
{
base.Start();
InitPromptLine<LineRendererUnbodied>();
}
protected override void OnEnable()
{
base.OnEnable();
SesothoPeManager.Inst.AddEmbedded(this);
}
protected override void OnDisable()
{
base.OnDisable();
SesothoPeManager.Inst.RemoveEmbedded(this);
}
protected virtual void OnDestroy()
{
}
protected override void AgencyOnEnable()
{
base.AgencyOnEnable();
}
protected override void AgencyOnDisable()
{
base.AgencyOnDisable();
}
protected override void AgencyMainUpdate()
{
base.AgencyMainUpdate();
// 绘制线路本身在网格中的索引位置
if (DebugDrawGrid &&
NeighborGridIndex.SafeGetAsMappingIndex(out var indexs))
{
foreach (var index in indexs.Indexs)
{
MacroDebugDraw.DrawDownArrow(
index.GetCellWorldIndexPosition() + MacroMath.RandomVector3(0.1f, Identifier), Quaternion.identity,
Color.red);
}
}
}
protected override void AgencyAsyncBeforeUpdate()
{
base.AgencyAsyncBeforeUpdate();
}
protected override void AgencyAsyncUpdate()
{
base.AgencyAsyncUpdate();
}
protected override void AgencyAsyncAfterUpdate()
{
base.AgencyAsyncAfterUpdate();
}
#endregion
#region 线路构建
/// <summary>
/// 创建合理坐标空间
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
/// <param name="ah"></param>
/// <param name="bh"></param>
/// <returns></returns>
public LineSegment2 SetLineSegment(Vector3 a, Vector3 b, Vector3 ah = default, Vector3 bh = default)
{
_lineSegment.SetValue(
a.UpwardPlaneToVector2(),
b.UpwardPlaneToVector2(),
ah.UpwardPlaneToVector2(),
bh.UpwardPlaneToVector2());
// ah?.GetEndPointNormal ?? default,
// bh?.GetStartPointNormal ?? default);
return _lineSegment;
}
public void AutomaticDrawCircularLine(float constraintAngle = -1, bool fullArc = false)
{
AutomaticDrawCircularLine(_lineSegment, constraintAngle, fullArc);
}
private LineSegment2 straightLine = new LineSegment2();
public void DrawStraightLine()
{
straightLine.SetValue(_lineSegment.pointA, _lineSegment.pointB);
AutomaticDrawCircularLine(straightLine);
}
/// <summary>
/// 重新计算原点
/// <code>
/// 如果此轨迹的原点在零点,那么通过此方法可以将原点设置到起点和终点之间。
/// 注意:使用前需要将轨迹设为本地坐标
/// </code>
/// </summary>
public void ReapplyOrigin()
{
if (TrajectoryRenderer == null || TrajectoryCalculator == null)
{
Debug.LogError("当前轨迹或线渲染器无效,无法计算原点");
return;
}
// 假定其中的轨迹是本地坐标的
// 期望的本地零点
var center = ((TrajectoryCalculator.GetStartPointPosition + TrajectoryCalculator.GetEndPointPosition) / 2).UpwardPlaneToVector3();
// 本地原点
var local = TrajectoryCalculator.Origin.UpwardPlaneToVector3();
// 期望偏移
var offset = local - center;
TrajectoryCalculator.Origin = offset.UpwardPlaneToVector2();
transform.position += center;
// 更新
UpdateRender();
}
#endregion
#region 实现 - ILinkconfidentPe
public bool GetLinkedNode(out LinkedListNode<PlacementBase> node)
{
if (_linkNode == null)
{
node = null;
return false;
}
node = _linkNode;
return true;
}
public void SetLinkedNode(LinkedListNode<PlacementBase> node)
{
_linkNode = node;
}
#endregion
#region 重写 - ISerializablePost
public override SerializerHelper.Type.SerializeUnion SerializedOccurs()
{
return base.SerializedOccurs();
}
public override bool CheckDeserializeUnion(SerializerHelper.Type.SerializeUnion context)
{
return base.CheckDeserializeUnion(context);
}
public override void DeserializeOccurs(SerializerHelper.Type.SerializeUnion context)
{
base.DeserializeOccurs(context);
}
public override void DeserializeHysteresisOccurs(SerializerHelper.Type.SerializeUnion context)
{
base.DeserializeHysteresisOccurs(context);
}
#endregion
}
}
@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: d376a769768d6b44d8759b7e7ab9f327
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
-72
View File
@@ -1,72 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using Deconstruction.Element;
using UnityEngine;
using XericLibrary.Runtime.Debuger;
using XericLibrary.Runtime.MacroLibrary;
using Random = System.Random;
namespace SesothoLine
{
/// <summary>
/// 点,承担连接的责任
/// </summary>
public class TerminalPoint : Deconstruction.Element.ContactPoint,
ILinkconfidentPe // 链表跟踪
{
private LinkedListNode<PlacementBase> _linkNode;
#region 生命周期
// 调试绘制一下位置
// private void Update()
// {
// MacroDebugDraw.DrawDownArrow(transform.position + MacroMath.RandomVector3(0.1f, Identifier), Color.green);
// }
#endregion
#region 实现 - ILinkconfidentPe
public bool GetLinkedNode(out LinkedListNode<PlacementBase> node)
{
if (_linkNode == null)
{
node = null;
return false;
}
node = _linkNode;
return true;
}
public void SetLinkedNode(LinkedListNode<PlacementBase> node)
{
_linkNode = node;
}
#endregion
#region 重写 - ISerializablePost
public override SerializerHelper.Type.SerializeUnion SerializedOccurs()
{
return base.SerializedOccurs();
}
public override bool CheckDeserializeUnion(SerializerHelper.Type.SerializeUnion context)
{
return base.CheckDeserializeUnion(context);
}
public override void DeserializeOccurs(SerializerHelper.Type.SerializeUnion context)
{
base.DeserializeOccurs(context);
}
public override void DeserializeHysteresisOccurs(SerializerHelper.Type.SerializeUnion context)
{
base.DeserializeHysteresisOccurs(context);
}
#endregion
}
}
@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: afcf586b1fc68ab4bac3cd8438b48ea7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: