diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9d7fe10..ab14682 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,13 @@
# Changelog
+## [0.3.5] - 2025-05-22
+
+提供了一种自动的多平台文件写入系统。
+添加一种预设的文件序列化器。
+添加更多超驰字段重命名转换。
+修复按键宏判断逻辑,之前可能在按键委托中无法及时获取按键状态。
+修复枚举器软接口的批量类型包装错误。
+
## [0.3.4] - 2025-04-23
增加了文本格式包裹器。
diff --git a/Editor/XericLibraryEditor.dll b/Editor/XericLibraryEditor.dll
index dca0441..b02c253 100644
Binary files a/Editor/XericLibraryEditor.dll and b/Editor/XericLibraryEditor.dll differ
diff --git a/README.md b/README.md
index 2089167..ac44e23 100644
--- a/README.md
+++ b/README.md
@@ -18,122 +18,19 @@ unity通用库插件,现已转为unity 6000版本。
* SerializerHelper: 序列化库
* XericLibrary: 实用性unity宏库,包含一些实用扩展用法。
-## Deconstruction (线路绘制,暂缓更新)
-Deconstruction 部分由两个dll组成,一个是 Deconstruction,另一个是 Deconstruction Style 。
-### 线路绘制
----
-
-
-线路绘制组件支持二维,或三维的线条计算,线条继承自“可放置物”类,为了能够显示线条,需要向其提供渲染器和,同理,为了能够算出构成线的点集合,需要提供线计算器。
-为此插件内默认提供了一个使用lineRenderer组件的线渲染器,以及二维的直线和圆弧的线计算器。
-在计算平面上的CAD线路时,通过实现二维的线计算器,并实现它的坐标转换方法,即可在任意表面上实现线的绘制与保存。
-
-另外如果希望快速构建具有特制绘制规则的对象,则需要另外的可放置物管理器 PlaceElementManager ,
-它继承于 SingleMonoBase ,所以可以通过单例的方式访问它。
-
-可放置物管理器管理的是所有的可放置物对象,和决策工具类 DecisionMakerToolBase ,以及它们的生命周期。
-
-工具类则提供了细致的针对如何放置对象的操作规则,并提供了操作栈表结构,
-可以通过操作栈来实现具有链表关系的行为树,栈中的每个节点是行为树上的一个节点,
-每个节点可以访问到上一个对象和下一个对象成员的节点。
-
-每个节点可以是正在绘制的线,正在计算寻路的ai,或其他任何行为,
-在节点内可以直接通过 ReplaceThis(new Exit_OpSlot()); 方法类来切换行为树的节点到一个新的节点。
-
-* 基础规则
-建议在工具类中进行创建等操作,管理类中只进行管理操作,比如在插件的sesotho部分的非dll文件中,提供了SesothoPeManager和SesothoArrangementWiresTool,他们就是管理器与工具类的派生部分。
-
-* 按键规则
-在没有任何工具启动的情况下,管理器可以接收按键输入,直到被工具输入抢占。
-不过,管理器到工具中并没有任何抢占逻辑,所以请根据工具激活逻辑适时关闭按键处理。
-另外,在没有任何工具激活的情况下,工具本身的按键获取机制也不会激活,记得使用原生的按键获取逻辑。
-
-* 线路规则
-
-
-* 链路规则
-链路是指实现了IConterminousness接口的对象,这个接口提供了一个获取ICoterminous接口的访问器;
-ICoterminous接口通常是用于实现链接关系的抽象层,简单的通过输入和输出来定义链接的线路,在接口中可以通过GetOpposite在当前对象的链接结构上下文中访问另一个与当前访问者相对应的链接对象,通常这是与访问者同类的对象,但是会经过接口进行抽象;而GetIdentical则可以获取与访问者同类链接的对象成员。
-
-链路方向使用LinkType进行标记,也可以直接使用LinkType.SwapType()来快速反转这个链接标记;
-LinkType可以直接和LinkedPortType相互进行转换,也可以使用LinkType.ConvertType()来快速转换类型。
-链路方向通常只用在内部作为方向标识,外部无法获取,一般只在设置时进行一次标识设置即可。
-
-
-
-### 线路结构
----
-
-线路绘制组件提供了线路连接引用关系,可以将一个线连接到另一个线上,也可以用点将它们连接起来,
-默认线
-
-
-### 生命周期
-----
-
-
-由于所有的成员都是通过批处理器完成生命周期的定义,批处理器的调用时机对于后续的流程来说至关重要。
-为了便于使用,所有的批处理对象的生命周期都遵循以下规则:
-
-```
-开始和结束时间在LateUpdate阶段触发;
-主线程更新事件在Update阶段触发;
-异步更新事件在LateUpdate阶段触发;
-
-主线程事件在所有事件之后才执行;
-```
-
-* 安全检查
-在批处理期间是允许销毁的,目前的安全限制仅限在更新前会检查一遍批处理的key值是否为空,在其他时刻,可以通过其他的接口传递的安全检查来辅助更新检查。
-比如在PromptLine2中,如果太早或太迟调用UpdateRender会导致在更新期间捕获到一个空引用的报错,来源是linerenderer组件在此时还不存在,具体原理不清楚,但是只会提示一次,所以此时的渲染操作可以直接跳过。
-
-### 获取工具
-----
-
-
-如果希望获取放置物管理器中的工具:
-
-```
-// 获取当前激活的工具目标
-DecisionMakerToolBase.ActiveDecisionMaker
-// 以及这个工具目标是否有效
-DecisionMakerToolBase.HasAciveDecisionMaker
-```
-
-### 示例文件
-----
-
-
-在Runtime/HorizonLineOrbit中已经提供了基本的用例,将SesothoPeManager挂到任意一个节点上就可以了。
-运行后按下键盘L键,此时点击世界中layer为defualt的物体,就会点击处y轴为0的位置上生成一个线,移动光标,线也会跟着移动。
-
-这些脚本提供了一个基本的示例,并且几乎将所有可以进行配置修改的要素都呈现了出来,可以在后续的扩展中通过参考这些文件来进行实现。
-
-在示例脚本中主要分为对元素的实现,以及对过程的实现;
-* terminalPoint, TerminalLine2T3, TerminalIland是后续创建的实例所挂载的具有确定空间,绘制方式的实现。
-* 其他的都是管理器,工具,操作栈的实现。
-
-其中管理器,工具,操作栈类都是层层嵌套的引用结构,尽量只让相邻的两个过程进行相互的引用,比如工具应该引用管理器的实现,开放给操作栈。
-
-
-### 使用须知
-----
-
-
-现在已知的线路绘制问题:
-* 如果同时创建大量的操作栈(>500),并在之后的某个时刻中将它们全部隐式地释放掉,有可能会在之后的某个时刻带来庞大的GC占用(>90ms)
-* 逆时针绘制的曲线线路没法计算最近点。
-
## XericLibrary (主要核心库)
XericLibrary 部分由两个dll组成,一个是 Xeric Library,另一个是 Xeric Library Editor 。
+----
### 宏库
-#### 特性库
----
+#### 特性库
* CanFind$
其中包含多个特性类,用于查找类,字段,属性,方法等项目。
@@ -143,26 +40,188 @@ XericLibrary 部分由两个dll组成,一个是 Xeric Library,另一个是 X
主要作用是提供属性标签查找功能。
#### 协程宏
-#### 调试宏
+#### 调试宏
#### 模型网格宏
#### 机器标识宏
#### 摄像机宏
-#### 颜色宏
-#### 常数宏
-#### 曲线宏
-#### 枚举宏
+#### 颜色宏 (MacorColor)
+#### 常数宏 (MacroConst)
+#### 曲线宏 (MacroCurve)
+#### 枚举宏 (MacroEnum)
枚举宏包含一个缓存封装器,可以通过MacroEnum\来定义。
定义枚举结构封装将允许像列表一样访问这个枚举,或将枚举实例赋予,通过枚举封装器来操作枚举值。
-在新版中,枚举封装器可以使用单例写法访问,而不再需要手动声名保存实例了。
#### 方程宏
#### 事件宏
-#### 文件宏
+#### 文件宏 (MacroFile)
+
+文件宏包含预设常用的文件写入,读取操作,并自动解决文件不存在的问题,通过返回布尔状态来快速判断解决。
+
+原始api中,仅包含一层简单的c#文件处理封装,无法适配unity其他平台情况,这些api已经被标记为过时,但你仍然可以继续使用他们。
+新版中,添加了对多平台的支持:
+
+* 增加了CrossPlatformFileHandle文件句柄,用于处理多平台的文件写入,加载的基类。
+ 使用时,通过CrossPlatformFileHandle.ActiveHandle来获得当前平台自动对应的文件句柄,其中包括了一组同步和一组异步的读写方法,来对目标地址进行访问。
+ 下面是一个示例:
+ ```
+ // ==== 同步读取 ====
+ CrossPlatformFileHandle.ActiveFileHandle.ReadTextFromFile("absolute file path", out string content);
+
+ // ==== 同步写入 ====
+ CrossPlatformFileHandle.ActiveFileHandle.WriteTextIntoFile("absolute file path", string content);
+
+ // ==== 异步读取 ====
+ var isCompleteRead = await CrossPlatformFileHandle.ActiveFileHandle.AsyncReadTextFromFile("absolute file path",
+ s =>
+ {
+ // 成功读取文件
+ },
+ s =>
+ {
+ // 读取失败,原因是 s
+ Debug.ErrorLog(s);
+ });
+
+ // ==== 异步写入 ====
+ var isCompleteWrite = await CrossPlatformFileHandle.ActiveFileHandle.AsyncWriteTextIntoFile("absolute file path",
+ null, // 成功写入文件,但是无需处理
+ null); // 写入失败,但是无需处理
+
+ // 异步方法包含回调函数处理,也可通过返回布尔值判断文件写入是否成功。
+ ```
+ 同时,文件句柄也提供了相对路径拼接:
+ ```
+ // 返回steamingAssets下的myFile.json文件路径
+ CrossPlatformFileHandle.ActiveFileHandle.CombineStreamingAssets("myFile.json");
+ ```
+
+* 添加了XericSerializerFormatter序列化器,用于通配处理多种序列化器目标。
+ 目前默认提供了 Json格式化 和 bin格式化 。
+ 下面展示如何使用:
+ ```
+ List obj = new List() { 1, 2, 3};
+ // 序列化目标
+ var content = JsonSerializerFormatter.formatter.Serializer(obj);
+ // 反序列化目标
+ obj = JsonSerializerFormatter.Deserializer.Serializer(content);
+ ```
+
+ 为了方便使用,文件句柄支持填入序列化器来实现更多的格式:
+ ```
+ // 类型太长了可以使用声名简化
+ using static XericLibrary.Runtime.MacroLibrary.MacroFile.CrossPlatformFileHandle;
+ using static XericLibrary.Runtime.MacroLibrary.MacroFile.JsonSerializerFormatter;
+
+ ActiveFileHandle.AsyncWriteXIntoFile(
+ ActiveFileHandle.CombineStreamingAssets("myFile.json"),
+ uriConfig, null, s => Debug.LogError(s), formatter);
+ ```
+
+----
+#### 窗口宏 (MacroForm)
+
+提供User32.dll中部分函数的功能。
+
+* 获取当前进程PID:PID
+* 通过句柄查找窗口:FindWindow
+* 控制窗口化状态:ShowWindow
+* 枚举显示器信息:GetDisplayMonitorsInfo
+
+----
#### 步进宏
-#### 按键宏
-#### 集合宏
-#### 数学宏
+#### 按键宏 (MacroKey)
+
+预设了一些判断较复杂按键状态的逻辑。
+
+对于外部的常规逻辑,可以使用扩展的InsertKey逻辑。
+为了使用这些逻辑,需要定义一个KeyFlippingStampSheetStyle(简称KfsStyle)。
+```
+KeyCode.A.AsKfsStyle();
+```
+将这个作为按键索引,传入扩展的状态检查事件一同执行更新,即可做出判断。
+这会返回一个KeyFlippingStampSheet,里面包含当前按键状态的布尔值,以及按键判断时触发的委托事件。
+
+* 交叉动作与延迟触发长按
+ ```
+ var keySheet = Input.GetMouseButtonDown(0).InsertKeyStateCmet(KeyCode.A.AsKfsStyle());
+ ```
+ 使用IsPressed判断是否单击按下,如果是双击,第一次点击时当前帧还是会返回单击事件。
+ 使用IsReleased判断刚刚的单击是否释放,如果上一次是长按状态,那么这个释放事件不会触发。
+ 使用IsDoubleClick判断是否双击,双击事件会出现在第二次点击间隔小于KfsStyle中设置的双击间隔时。
+ 使用IsFirstLongPressed判断是否长按,当一次按下后不释放时间大于KfsStyle中设置的长按间隔时出现一次。
+ 使用IsLongPressedState判断是否长按,当一次按下后不释放时间大于KfsStyle中设置的长按间隔时出现。
+ 使用IsLongReleased判断刚刚长按是否释放。
+
+* 坐标保持触发
+ ```
+ var keySheet = Input.GetMouseButtonDown(0).InsertKeyStatePt(KeyCode.A.AsKfsStyle());
+ ```
+ 与上述功能一致,但可以使用拖拽事件:
+ 使用IsChangeDraggingFromLongPressed判断长按事件是否转为拖拽事件。
+ 使用IsBeginDragging判断当前是否开始拖拽。
+ 使用IsDragging判断当前是否正在拖拽。
+ 使用IsDropping判断当前是否正在丢弃。
+
+ 在拖拽期间,长按状态将继续触发,但长按事件将转为拖拽事件,长按事件。
+ 拖拽结束后,如果以拖拽结束,但以长按开始,那么长按结束事件也会触发。
+
+* 光标坐标计算:
+ 提供诸如类似GetRectangleRelativelyPoint的扩展方法,将传入的光标坐标计算为相对坐标。
+
+----
+#### 列表宏 (MacroMath)
+
+* FisherYatesShuffle: 洗牌算法,返回一个索引映射数组,同时也提供一个线程安全的蓄水池洗牌算法。
+* GetRandom: 从列表中随机获得1个或多个对象(洗牌算法)。
+* MakeIEnumberable: 将一个对象制作成枚举器。
+* LandedIndex: 从迭代器中抽出索引下的成员。
+* SelectConvert: 从非泛型迭代器转为泛型迭代器。
+* ForEachDo: 迭代器执行。
+* Adjoint: 迭代器拼接一个索引。
+* SubSegment: 仅迭代开始索引后一段数量范围内的成员。
+* Startup: 在当前迭代器之前拼接一个或多个成员(迭代器)
+* Endeavor: 在当前迭代器之后拼接一个或多个成员(迭代器)
+* Join: 将当前迭代器加入到字符串,可以设置如何开头,结尾,成员分割符。
+* Merge: 将当前迭代器合并,可以实现类似sum的操作。
+* EqualitySet: 比较两个迭代器里的成员是否相等。
+* Shift: 偏移列表,也可以使用RingShift,CyclicShift循环偏移。
+* 包含针对IList>的Add,TryAdd,AddUnique,Remove,Modify,Contains,IndexOf,GetValue,GetKey,GetKeys,GetValues方法。
+* BinarySearch: 二分法遍历
+* FindClosestIndexByBinarySearch: 基于浮点数的二分法查找方法。
+* IsIndexGreaterZeroLessCount:
+* AddByIndex: 在索引处添加目标,如果索引不存在,则用default填充;如果目标已经存在,就替换。
+* TryDoAtIndex: 尝试在索引处执行些什么,如果索引不存在,则什么都不做。
+* ReplaceList: 使用一个列表替换另一个列表,允许通过自定义增删改方法修改(和DiscrepancyOrder作用几乎一致,不过这个会因为条件不满足而产生报错)。
+* DiscrepancyOrder: 列表顺序差异,从源到目标列表的差异会通过委托开放,允许自定义删除,增加,替换来完成修改。
+* TryGetAtIndex: 尝试读取索引处的成员。
+* ForceDoAtIndex: 强制在索引处执行些什么,不论成员是否存在,永远都会执行委托。
+* ForceGetAtIndex: 强制在索引处获取成员。
+*
+----
+#### 数学宏 (MacroMath)
+
+* RandomFloat/Vector/Matrix:通过一个随机生成器快速获得随机值。
+* Pmod:在正数空间上对值取余,负数情况下仍然会保持与正数相同的曲线形状。
+* RoundToAny:将一个矢量四舍五入到任意的倍数,比如4.8舍入3.5得到3.5,6.2则得到7
+* MinPositive:获取正数空间上的最小值。
+* SmoothStep:获取t在(a,b)之间的埃尔米特过度
+* LinearStep:获取t在(a,b)之间的线性过度
+* RoundBasedOnMinimumDifference:将一个值根据最小的差值进行四舍五入
+* DiscardLeastSignificantDecimal:舍弃不重要的小数位
+* ClampWrapAngle:钳制角度
+* GetNumberOfDecimalsForMinimumDifference:获取最小插值的小数个数
+* CosineSimilarity:余弦相似度
+* FibonacciRecursive:斐波那契迭代方式计算(会产生大量循环)
+* FastInvSqrt:快速平方根倒数
+* IsPrimeNumberRw:检查一个数是否是质数(这是一个娱乐用法,利用正则表达式判断是否为质数,性能消耗较高)
+* GetCirclePoints:获取圆上的点
+* GetRayIntersectionCircle:获取切于圆的线两点坐标
+* GetHeightOfRoundArch:获取圆拱高度
+* GetListFormAToB:获取从A到B的列表
+* LerpTransform:创建lerp矩阵
+*
+----
#### 消息库
预设一些消息处理流程。
@@ -209,9 +268,38 @@ XericLibrary 部分由两个dll组成,一个是 Xeric Library,另一个是 X
提供一个方法软引用封装器,首先需要将一个可执行流程转换为CallableTarget对象。然后通过AddCallableFunction添加到全局字典中,随后可以通过TryEvocation或者Evocation调用。
方法封装器默认可以搜索所有静态,实例,私有,公共的方法
+----
+#### 对象宏 (MacroObject)
-#### 对象宏
-#### PID宏
+在gameobject或transform上快速迭代的操作库。
+
+* 场景迭代
+ * 获取当前场景中的所有根对象:GetActiveSceneRootGameObjects。
+ * 在所有已激活场景中查找组件:GetAllSceneComponents。
+* 节点迭代
+ * 获取父级迭代器:GetParents。
+ * 获取子级迭代器:GetChildren。
+ * 获取广度优先的子级迭代器:GetChildrenBFS。
+ * 获取深度优先的子级迭代器:GetChildrenRecursion。(不要使用 GetChildrenDFS,存在严重性能缺陷)
+* 组件迭代
+ * 在当前位置无论如何都获取一个组件,如果没有就创建:GetComponentAnyway。
+ * 在节点迭代器中找一个组件:GetComponent。
+ * 将节点迭代器转为一一对应的组件迭代器:GetComponentsOTO。
+ * 将节点迭代器转为组件迭代器:GetComponentsOTOD。
+ * 在当前节点的所有子成员(包含子成员的子成员)内查找多个组件:GetComponentsInRecursionChildren。
+ * 按照给定的组件顺序在节点迭代器中逐一查找:GetFavoriteComponent。
+* 家族迭代
+ * 获取当前节点的家族名称:GetFamilyName。
+ * 使用家族名称搜索节点:FindFamilyMember。(支持一次重定向,以及逐级名称模糊查找)
+
+以上仅包含大致用法,实际上包含更多的重载用法。
+
+----
+#### PID宏 (MacroMath)
+
+提供一个PID计算器,具有基本的pid计算,同时带有基本安全计算。
+
+----
#### 对象池宏
预设快速设置的对象池(CreatSimplePool)与顺序对象池(CreatObjectInOrderPool),传入预制体与父级,将直接返回一个预设的对象池。
@@ -219,22 +307,50 @@ XericLibrary 部分由两个dll组成,一个是 Xeric Library,另一个是 X
提供一个联合对象池(预设的)MacroPool.UnionSet,支持开放预制体目标与父级目标参数到inspector。
联合对象池需要手动调用Init函数进行初始化。
+----
#### 矩形变换宏
-#### 超驰宏
+#### 超驰宏 (MacroReflection)
+
+* 签名转换:通过GetFieldsRename 获取给定名称的字段在自定义的重命名特性上的名称。
+* 软接口:SoftInterface 通过名称直接设置或获取值,
+ 支持在一个对象上获取一系列名称的值,或在一系列对象上获取同一个名称的值,或是反过来设置他们。
+* 实例化:通过OverridingInstance创建给定类的实例,支持通过全名
+*
+----
+#### 正则库 (MacroRegex)
+
+提供了常用的正则匹配模式。
+
+* GeneralVector:多维矢量文本匹配
+* ObjMesh:obj模型参数匹配(匹配的同时会转换坐标系到unity)
+* RegexReplace: 直接使用编辑器常用语法进行替换,比如"$1"获取第一个匹配项并输出。
+
+----
#### 仓库宏
#### 材质宏
-#### 平滑宏
-#### 排序宏
+#### 平滑宏 (MacroSmooth)
+
+包含28个常用插值函数,可以使用SwitchEasing对一个数值计算插值,返回重新映射插值位置的数值。
+插值函数可以单独调用,或使用枚举切换。
+
+----
+#### 排序宏 (MacroSort)
c#自带的排序很好用,但是选择何种排序模式是根据数据类型自动切换的。
在这里,排序宏中提供了一些可以手动选择的排序算法。
注:没有猴子排序。
-#### 文本宏
+----
+#### 文本宏 (MacroMath)
提供:
* StringBuilderPool: 文本构建池
* join: 文本序列拼接。
+ ```
+ List