合并代码
This commit is contained in:
@@ -1,31 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class VIUBezierMobile : ModuleViewInputUnit {
|
||||
private Vector3 mousePosition;
|
||||
private Vector3 originalPosition;
|
||||
private readonly ModuleViewCamera viewCamera;
|
||||
private ModulePlateDesign PlateDesign => ModuleCore.I.PlateDesign;
|
||||
public VIUBezierMobile(ModuleViewCamera viewCamera) {
|
||||
this.viewCamera = viewCamera;
|
||||
}
|
||||
public override void DownMouse(DataMouseInput data) {
|
||||
PlateDesign.SelectBezierPoint(data.ScreenPosition);
|
||||
if (!PlateDesign.IsValidBezierPoint) { return; }
|
||||
mousePosition = viewCamera.ScreenToWorldPosition(data.ScreenPosition);
|
||||
originalPosition = PlateDesign.BezierPointPosition;
|
||||
}
|
||||
public override void DragMouse(DataMouseInput data) {
|
||||
if (!PlateDesign.IsValidBezierPoint) { return; }
|
||||
Vector3 current = viewCamera.ScreenToWorldPosition(data.ScreenPosition);
|
||||
Vector3 offset = current - mousePosition;
|
||||
PlateDesign.ChangeBezierPoint(originalPosition + offset);
|
||||
}
|
||||
public override void ReleaseMouse(DataMouseInput data) {
|
||||
PlateDesign.ReleaseBezierPoint();
|
||||
}
|
||||
public override void ScrollWheel(DataMouseInput data) {
|
||||
PlateDesign.ReleaseBezierPoint();
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class VIUCameraMobile : ModuleViewInputUnit {
|
||||
private Vector3 mousePosition;
|
||||
private Vector3 originalPosition;
|
||||
private readonly ModuleViewCamera viewCamera;
|
||||
public VIUCameraMobile(ModuleViewCamera viewCamera) {
|
||||
this.viewCamera = viewCamera;
|
||||
}
|
||||
public override void DownMouse(DataMouseInput data) {
|
||||
mousePosition = viewCamera.ScreenToWorldPosition(data.ScreenPosition);
|
||||
originalPosition = viewCamera.Position;
|
||||
}
|
||||
public override void DragMouse(DataMouseInput data) {
|
||||
Vector3 current = viewCamera.ScreenToWorldPosition(data.ScreenPosition);
|
||||
Vector3 offset = current - mousePosition;
|
||||
viewCamera.Position = originalPosition + offset;
|
||||
}
|
||||
public override void ReleaseMouse(DataMouseInput data) {
|
||||
|
||||
}
|
||||
public override void ScrollWheel(DataMouseInput data) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class VIUCameraRotate : ModuleViewInputUnit {
|
||||
private float mouseRotate;
|
||||
private float originalRotate;
|
||||
private readonly ModuleViewCamera viewCamera;
|
||||
public VIUCameraRotate(ModuleViewCamera viewCamera) {
|
||||
this.viewCamera = viewCamera;
|
||||
}
|
||||
public override void DownMouse(DataMouseInput data) {
|
||||
mouseRotate = viewCamera.ScreenToViewPosition(data.ScreenPosition).x;
|
||||
originalRotate = viewCamera.EulerAngles.y;
|
||||
}
|
||||
public override void DragMouse(DataMouseInput data) {
|
||||
float current = viewCamera.ScreenToViewPosition(data.ScreenPosition).x;
|
||||
float offset = (current - mouseRotate) * 360;
|
||||
viewCamera.EulerAngles = new Vector3(0, originalRotate - offset, 0);
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class VIUCameraScale : ModuleViewInputUnit {
|
||||
public enum ScaleType { Scale, Orthographic }
|
||||
private readonly ScaleType scaleType;
|
||||
private readonly ModuleViewCamera viewCamera;
|
||||
public VIUCameraScale(ModuleViewCamera viewCamera, ScaleType scaleType = ScaleType.Scale) {
|
||||
this.viewCamera = viewCamera;
|
||||
this.scaleType = scaleType;
|
||||
}
|
||||
public override void DownMouse(DataMouseInput data) {
|
||||
|
||||
}
|
||||
public override void DragMouse(DataMouseInput data) {
|
||||
|
||||
}
|
||||
public override void ReleaseMouse(DataMouseInput data) {
|
||||
|
||||
}
|
||||
public override void ScrollWheel(DataMouseInput data) {
|
||||
if (scaleType == ScaleType.Scale) {
|
||||
float size = viewCamera.LocalScale.x + data.ScrollWheel;
|
||||
size = Mathf.Clamp(size, 0.5f, 4);
|
||||
Vector3 localScale = new Vector3(size, size, size);
|
||||
viewCamera.LocalScale = Vector3.Lerp(viewCamera.LocalScale, localScale, Time.deltaTime * 20);
|
||||
}
|
||||
if (scaleType == ScaleType.Orthographic) {
|
||||
float size = viewCamera.OrthographicSize + data.ScrollWheel;
|
||||
size = Mathf.Clamp(size, 0.1f, 4);
|
||||
viewCamera.OrthographicSize = Mathf.Lerp(viewCamera.OrthographicSize, size, Time.deltaTime * 20);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class VIUDesignPointInsert : ModuleViewInputUnit {
|
||||
private readonly ModuleViewCamera viewCamera;
|
||||
private ModulePlateDesign PlateDesign => ModuleCore.I.PlateDesign;
|
||||
public VIUDesignPointInsert(ModuleViewCamera viewCamera) {
|
||||
this.viewCamera = viewCamera;
|
||||
}
|
||||
public override void DownMouse(DataMouseInput data) {
|
||||
PlateDesign.InsertDesignPoint(data.ScreenPosition);
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8b8b6a3b0a7e1e649bdcd0615dfa80ed
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,31 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class VIUDesignPointMobile : ModuleViewInputUnit {
|
||||
private Vector3 mousePosition;
|
||||
private Vector3 originalPosition;
|
||||
private readonly ModuleViewCamera viewCamera;
|
||||
private ModulePlateDesign PlateDesign => ModuleCore.I.PlateDesign;
|
||||
public VIUDesignPointMobile(ModuleViewCamera viewCamera) {
|
||||
this.viewCamera = viewCamera;
|
||||
}
|
||||
public override void DownMouse(DataMouseInput data) {
|
||||
PlateDesign.SelectDesignPoint(data.ScreenPosition);
|
||||
if (!PlateDesign.IsValidDesignPoint) { return; }
|
||||
mousePosition = viewCamera.ScreenToWorldPosition(data.ScreenPosition);
|
||||
originalPosition = PlateDesign.DesignPointPosition;
|
||||
}
|
||||
public override void DragMouse(DataMouseInput data) {
|
||||
if (!PlateDesign.IsValidDesignPoint) { return; }
|
||||
Vector3 current = viewCamera.ScreenToWorldPosition(data.ScreenPosition);
|
||||
Vector3 offset = current - mousePosition;
|
||||
PlateDesign.ChangeDesignPoint(originalPosition + offset);
|
||||
}
|
||||
public override void ReleaseMouse(DataMouseInput data) {
|
||||
PlateDesign.ReleaseDesignPoint();
|
||||
}
|
||||
public override void ScrollWheel(DataMouseInput data) {
|
||||
PlateDesign.ReleaseDesignPoint();
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: eb31bfbd0ef82f24b823836852bd846c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,22 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class VIUEdgePointAdd : ModuleViewInputUnit {
|
||||
private readonly ModuleViewCamera viewCamera;
|
||||
private ModulePlateDesign PlateDesign => ModuleCore.I.PlateDesign;
|
||||
public VIUEdgePointAdd(ModuleViewCamera viewCamera) {
|
||||
this.viewCamera = viewCamera;
|
||||
}
|
||||
public override void DownMouse(DataMouseInput data) {
|
||||
PlateDesign.InsertEdgePoint(data.ScreenPosition);
|
||||
}
|
||||
public override void MoveMouse(DataMouseInput data) {
|
||||
//Vector3 position = viewCamera.ScreenToWorldPosition(data.ScreenPosition);
|
||||
//Vector3 worldPosition = position + viewCamera.CameraWorldPosition;
|
||||
//worldPosition.z = 0;
|
||||
//Collider2D[] colliders = Physics2D.OverlapCircleAll(worldPosition, range, DefaultLayerMask);
|
||||
//if (colliders.Length == 0) { return; }
|
||||
//edgePoint = colliders[0].GetComponentInParent<PrefabEdgePoint>();
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0c0e8f369912dbb4e9d906ca3d14a628
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,31 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class VIUEdgePointMobile : ModuleViewInputUnit {
|
||||
private Vector3 mousePosition;
|
||||
private Vector3 originalPosition;
|
||||
private readonly ModuleViewCamera viewCamera;
|
||||
private ModulePlateDesign PlateDesign => ModuleCore.I.PlateDesign;
|
||||
public VIUEdgePointMobile(ModuleViewCamera viewCamera) {
|
||||
this.viewCamera = viewCamera;
|
||||
}
|
||||
public override void DownMouse(DataMouseInput data) {
|
||||
PlateDesign.SelectEdgePoint(data.ScreenPosition);
|
||||
if (!PlateDesign.IsValidEdgePoint) { return; }
|
||||
mousePosition = viewCamera.ScreenToWorldPosition(data.ScreenPosition);
|
||||
originalPosition = PlateDesign.EdgePointPosition;
|
||||
}
|
||||
public override void DragMouse(DataMouseInput data) {
|
||||
if (!PlateDesign.IsValidEdgePoint) { return; }
|
||||
Vector3 current = viewCamera.ScreenToWorldPosition(data.ScreenPosition);
|
||||
Vector3 offset = current - mousePosition;
|
||||
PlateDesign.ChangeEdgePoint(originalPosition + offset);
|
||||
}
|
||||
public override void ReleaseMouse(DataMouseInput data) {
|
||||
PlateDesign.ReleaseEdgePoint();
|
||||
}
|
||||
public override void ScrollWheel(DataMouseInput data) {
|
||||
PlateDesign.ReleaseEdgePoint();
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ae2a8f6a151f160479bd605f2c407a8d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,18 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public abstract class ModuleViewInputUnit {
|
||||
/// <summary> 核心模块 </summary>
|
||||
protected virtual ModuleCore ModuleCore => ModuleCore.I;
|
||||
/// <summary> 按下鼠标左键 </summary>
|
||||
public virtual void DownMouse(DataMouseInput data) { }
|
||||
/// <summary> 拖拽鼠标左键 </summary>
|
||||
public virtual void DragMouse(DataMouseInput data) { }
|
||||
/// <summary> 释放鼠标左键 </summary>
|
||||
public virtual void ReleaseMouse(DataMouseInput data) { }
|
||||
/// <summary> 移动鼠标 </summary>
|
||||
public virtual void MoveMouse(DataMouseInput data) { }
|
||||
/// <summary> 鼠标滚轮 </summary>
|
||||
public virtual void ScrollWheel(DataMouseInput data) { }
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 15cfd3c63263fc14fbb47c12c18447ff
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -2,9 +2,24 @@ using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public abstract class ModuleAlgorithm<Data> {
|
||||
/// <summary>
|
||||
/// 算法模块
|
||||
/// </summary>
|
||||
/// <typeparam name="Data"></typeparam>
|
||||
public abstract class ModuleAlgorithm<Data> : MonoBehaviour {
|
||||
/// <summary> 必须要初始化 </summary>
|
||||
protected abstract void Awake();
|
||||
/// <summary> 核心模块 </summary>
|
||||
protected virtual ModuleCore ModuleCore => ModuleCore.I;
|
||||
|
||||
/// <summary> 执行算法 </summary>
|
||||
public abstract void Compute(Data data);
|
||||
}
|
||||
/// <summary>
|
||||
/// 单个算法函数
|
||||
/// </summary>
|
||||
/// <typeparam name="Data"></typeparam>
|
||||
public abstract class ModuleAlgorithmFunction<Data> {
|
||||
/// <summary> 执行算法 </summary>
|
||||
public abstract void Compute(Data data);
|
||||
}
|
||||
@@ -3,14 +3,27 @@ using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// 资源模块
|
||||
/// </summary>
|
||||
/// <typeparam name="Data">绑定的资源类型</typeparam>
|
||||
public abstract class ModuleAssets<Data> : MonoBehaviour {
|
||||
[SerializeField] protected List<Data> assets;
|
||||
/// <summary> 资产列表 </summary>
|
||||
public virtual List<Data> Assets => assets;
|
||||
/// <summary> 必须要初始化 </summary>
|
||||
protected abstract void Awake();
|
||||
/// <summary> 核心模块 </summary>
|
||||
protected virtual ModuleCore ModuleCore => ModuleCore.I;
|
||||
|
||||
/// <summary> 数据计数 </summary>
|
||||
public abstract int Count { get; }
|
||||
/// <summary> 数据列表 </summary>
|
||||
public abstract List<Data> Datas { get; }
|
||||
|
||||
/// <summary> 添加数据 </summary>
|
||||
public abstract void Add(Data data);
|
||||
/// <summary> 删除数据 </summary>
|
||||
public abstract void Remove(Data data);
|
||||
/// <summary> 查询数据 </summary>
|
||||
public abstract Data Find(int index);
|
||||
/// <summary> 循环列表 </summary>
|
||||
public abstract void ForEach(Action<Data> action);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// 构造器
|
||||
/// 根据原型构造数据
|
||||
/// </summary>
|
||||
/// <typeparam name="Origin"></typeparam>
|
||||
/// <typeparam name="Data"></typeparam>
|
||||
public abstract class ModuleBuilder<Origin, Data> : MonoBehaviour {
|
||||
/// <summary> 必须要初始化 </summary>
|
||||
protected abstract void Awake();
|
||||
/// <summary> 核心模块 </summary>
|
||||
protected virtual ModuleCore ModuleCore => ModuleCore.I;
|
||||
|
||||
/// <summary> 根据原型构造数据 </summary>
|
||||
public abstract Data To(Origin origin);
|
||||
}
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 535c46cee34ae5e49802e537ad5a7a13
|
||||
guid: 37fd3673cacd6294f8a1de0ddc48768a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
@@ -4,11 +4,16 @@ using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using MuHua;
|
||||
|
||||
/// <summary>
|
||||
/// 核心模块,实现业务逻辑
|
||||
/// </summary>
|
||||
public class ModuleCore : Module<ModuleCore> {
|
||||
|
||||
#region 资产模块
|
||||
/// <summary> 预设模板资产 </summary>
|
||||
public ModuleAssets<DataPresetsPlate> PresetsPlateAssets;
|
||||
/// <summary> 板片资产 </summary>
|
||||
public ModuleAssets<DataPlate> AssetsPlate;
|
||||
/// <summary> 预设板片资产 </summary>
|
||||
public ModuleAssets<DataPlatePresets> AssetsPlatePresets;
|
||||
#endregion
|
||||
|
||||
#region 页面模块
|
||||
@@ -20,27 +25,57 @@ public class ModuleCore : Module<ModuleCore> {
|
||||
public ModuleUIWindow<Action> PresetsPlateWindow;
|
||||
#endregion
|
||||
|
||||
#region 功能模块
|
||||
/// <summary> 代理模块 </summary>
|
||||
public ModuleAgent ModuleAgent;
|
||||
/// <summary> 根据设计点生成边缘算法模块 </summary>
|
||||
public ModuleAlgorithm<DataPlate> GenerateEdge = new AlgorithmGenerateEdge();
|
||||
/// <summary> 边缘排序算法模块 </summary>
|
||||
public ModuleAlgorithm<DataPlate> EdgeSort = new AlgorithmEdge();
|
||||
/// <summary> 多边形算法模块 </summary>
|
||||
public ModuleAlgorithm<DataPlate> Polygon = new AlgorithmPolygon();
|
||||
/// <summary> 板片设计模块 </summary>
|
||||
public ModulePlateDesign PlateDesign;
|
||||
/// <summary> 板片设计相机视图 </summary>
|
||||
public ModuleViewCamera PlateDesignViewCamera;
|
||||
#region 视图模块
|
||||
/// <summary> 设计视图相机模块 </summary>
|
||||
public ModuleViewCamera ViewCameraDesign;
|
||||
/// <summary> 板片烘焙相机视图 </summary>
|
||||
public ModuleViewCamera PlateBakingViewCamera;
|
||||
public ModuleViewCamera ViewCameraBaking;
|
||||
#endregion
|
||||
|
||||
#region 控制模块
|
||||
/// <summary> 板片设计输入模块 </summary>
|
||||
public ModuleViewInput PlateDesignViewInput;
|
||||
/// <summary> 板片烘焙输入模块 </summary>
|
||||
public ModuleViewInput PlateBakingViewInput;
|
||||
#region 广播模块
|
||||
/// <summary> 广播板片数据模块 </summary>
|
||||
public ModuleSending<DataPlate> SendingPlate;
|
||||
/// <summary> 广播板片数据点模块 </summary>
|
||||
public ModuleSending<DataPoint> SendingPoint;
|
||||
/// <summary> 广播查询数据模块 </summary>
|
||||
public ModuleSending<DataFindPoint> SendingFindPoint;
|
||||
#endregion
|
||||
|
||||
#region 输入模块
|
||||
/// <summary> 设计UI输入模块 </summary>
|
||||
public ModuleUIInput<UIInputDesignUnit> UIInputDesign;
|
||||
#endregion
|
||||
|
||||
#region 转换模块
|
||||
/// <summary> 预设板片转换板片 </summary>
|
||||
public ModuleBuilder<DataPlatePresets, DataPlate> PlatePresetsToPlate;
|
||||
/// <summary> 插入点数据转换板片上的点 </summary>
|
||||
public ModuleBuilder<DataInsertPoint, DataPoint> InsertPointToPoint;
|
||||
#endregion
|
||||
|
||||
#region 可视模块
|
||||
/// <summary> 板片可视化内容生成模块 </summary>
|
||||
public ModuleVisual<DataPlate> VisualPlate;
|
||||
/// <summary> 点可视化内容生成模块 </summary>
|
||||
public ModuleVisual<DataPoint> VisualPoint;
|
||||
/// <summary> 多边形可视化内容生成模块 </summary>
|
||||
public ModuleVisual<DataPolygon> VisualPolygon;
|
||||
#endregion
|
||||
|
||||
#region 算法模块
|
||||
|
||||
/// <summary> 查询点算法模块 </summary>
|
||||
public ModuleAlgorithm<DataFindPoint> AlgorithmFindPoint;
|
||||
/// <summary> 查询贝塞尔点算法模块 </summary>
|
||||
public ModuleAlgorithm<DataFindBezier> AlgorithmFindBezier;
|
||||
|
||||
/// <summary> 插入点算法模块 </summary>
|
||||
public ModuleAlgorithm<DataInsertPoint> AlgorithmInsertPoint;
|
||||
|
||||
/// <summary> 多边形算法模块 </summary>
|
||||
public ModuleAlgorithm<DataPlate> AlgorithmPolygon;
|
||||
///// <summary> 边缘排序算法模块 </summary>
|
||||
//public ModuleAlgorithm<DataPlate> EdgeSort = new AlgorithmEdge();
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9e350a719b66eb849983fdce5dcb2025
|
||||
guid: 25f8d980388c4434381edd852a47ff9a
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
@@ -0,0 +1,18 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class ModuleInput : MonoBehaviour
|
||||
{
|
||||
// Start is called before the first frame update
|
||||
void Start()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e00fcc9528ea97040bcdee04b0279778
|
||||
guid: 890a3e1c641efcb418cc76bfb893d22e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
@@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
/// <summary>
|
||||
/// UI输入模块
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public abstract class ModuleUIInput<T> : MonoBehaviour {
|
||||
/// <summary> 必须要初始化 </summary>
|
||||
protected abstract void Awake();
|
||||
/// <summary> 核心模块 </summary>
|
||||
protected virtual ModuleCore ModuleCore => ModuleCore.I;
|
||||
|
||||
/// <summary> 当前输入单元 </summary>
|
||||
public abstract T Current { get; }
|
||||
/// <summary> 改变输入单元时触发 </summary>
|
||||
public abstract event Action<T> OnChangeInput;
|
||||
/// <summary> 改变输入单元 </summary>
|
||||
public abstract void ChangeInput(T input);
|
||||
|
||||
/// <summary> 绑定UI </summary>
|
||||
public abstract void Binding(VisualElement element);
|
||||
}
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0ba32fb2f11bf1948bdaae8823a824b2
|
||||
guid: 41107ff888d44274e9593642528ccdd6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
@@ -1,61 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public abstract class ModulePlateDesign : MonoBehaviour {
|
||||
/// <summary> 必须初始化 </summary>
|
||||
protected virtual void Awake() {
|
||||
ModuleCore.PlateDesign = this;
|
||||
}
|
||||
/// <summary> 核心模块 </summary>
|
||||
protected virtual ModuleCore ModuleCore => ModuleCore.I;
|
||||
/// <summary> 视图相机模块 </summary>
|
||||
protected virtual ModuleViewCamera ViewCamera => ModuleCore.PlateDesignViewCamera;
|
||||
|
||||
/// <summary> 添加一个板片数据 </summary>
|
||||
public abstract void AddData(DataPlate data);
|
||||
|
||||
#region 边缘点操作
|
||||
/// <summary> 是否有效的边缘点 </summary>
|
||||
public abstract bool IsValidEdgePoint { get; }
|
||||
/// <summary> 返回当前边缘点位置 </summary>
|
||||
public abstract Vector3 EdgePointPosition { get; }
|
||||
/// <summary> 选中一个边缘点 </summary>
|
||||
public abstract void SelectEdgePoint(Vector3 screenPosition);
|
||||
/// <summary> 改变边缘点位置 </summary>
|
||||
public abstract void ChangeEdgePoint(Vector3 localPosition);
|
||||
/// <summary> 插入一个边缘点 </summary>
|
||||
public abstract void InsertEdgePoint(Vector3 screenPosition);
|
||||
/// <summary> 释放边缘点 </summary>
|
||||
public abstract void ReleaseEdgePoint();
|
||||
#endregion
|
||||
|
||||
#region 设计点操作
|
||||
/// <summary> 是否有效的设计点 </summary>
|
||||
public abstract bool IsValidDesignPoint { get; }
|
||||
/// <summary> 返回当前设计点位置 </summary>
|
||||
public abstract Vector3 DesignPointPosition { get; }
|
||||
/// <summary> 选中一个设计点 </summary>
|
||||
public abstract void SelectDesignPoint(Vector3 screenPosition);
|
||||
/// <summary> 改变设计点位置 </summary>
|
||||
public abstract void ChangeDesignPoint(Vector3 localPosition);
|
||||
/// <summary> 插入一个设计点 </summary>
|
||||
public abstract void InsertDesignPoint(Vector3 screenPosition);
|
||||
/// <summary> 释放设计点 </summary>
|
||||
public abstract void ReleaseDesignPoint();
|
||||
#endregion
|
||||
|
||||
#region 贝塞尔曲线操作
|
||||
/// <summary> 是否有效的贝塞尔点 </summary>
|
||||
public abstract bool IsValidBezierPoint { get; }
|
||||
/// <summary> 返回当前贝塞尔点位置 </summary>
|
||||
public abstract Vector3 BezierPointPosition { get; }
|
||||
/// <summary> 选中一个贝塞尔点 </summary>
|
||||
public abstract void SelectBezierPoint(Vector3 screenPosition);
|
||||
/// <summary> 改变贝塞尔点位置 </summary>
|
||||
public abstract void ChangeBezierPoint(Vector3 localPosition);
|
||||
/// <summary> 释放贝塞尔点 </summary>
|
||||
public abstract void ReleaseBezierPoint();
|
||||
#endregion
|
||||
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c5b9eb7c85f467e42a3632003cc5c1c7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// 发送模块 广播数据
|
||||
/// </summary>
|
||||
public abstract class ModuleSending<T> : MonoBehaviour {
|
||||
/// <summary> 必须要初始化 </summary>
|
||||
protected abstract void Awake();
|
||||
/// <summary> 核心模块 </summary>
|
||||
protected virtual ModuleCore ModuleCore => ModuleCore.I;
|
||||
|
||||
/// <summary> 当前输入单元 </summary>
|
||||
public abstract T Current { get; }
|
||||
/// <summary> 改变输入单元时触发 </summary>
|
||||
public abstract event Action<T> OnChange;
|
||||
/// <summary> 改变输入单元 </summary>
|
||||
public abstract void Change(T obj);
|
||||
}
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a819c02b79cf50242803b88efbb134c1
|
||||
guid: eaecf945c01ab084aaa6cdb6ebcd7e0f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f5ae9284505c4b940b508a7f812159eb
|
||||
guid: 8d093e4c9062c4044bcb09ee5f5abb8b
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
@@ -0,0 +1,15 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
public abstract class ModuleUIPanel : MonoBehaviour {
|
||||
/// <summary> 绑定的页面 </summary>
|
||||
public ModuleUIPage ModuleUIPage;
|
||||
/// <summary> 必须初始化 </summary>
|
||||
public abstract void Awake();
|
||||
/// <summary> 核心模块 </summary>
|
||||
protected virtual ModuleCore ModuleCore => ModuleCore.I;
|
||||
|
||||
public abstract VisualElement Element { get; }
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d4ba0921b8d30f548ba33b96c76f2c48
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -3,6 +3,9 @@ using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
/// <summary>
|
||||
/// UI页面
|
||||
/// </summary>
|
||||
public abstract class ModuleUIPage : MonoBehaviour {
|
||||
public UIDocument document;
|
||||
/// <summary> 根目录文档 </summary>
|
||||
|
||||
@@ -2,6 +2,10 @@ using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// UI窗口
|
||||
/// </summary>
|
||||
/// <typeparam name="Data">窗口需要的数据类型</typeparam>
|
||||
public abstract class ModuleUIWindow<Data> : MonoBehaviour {
|
||||
/// <summary> 绑定的页面 </summary>
|
||||
public ModuleUIPage ModuleUIPage;
|
||||
|
||||
@@ -2,32 +2,36 @@ using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// 视图相机,把内容渲染到渲染纹理上
|
||||
/// </summary>
|
||||
public abstract class ModuleViewCamera : MonoBehaviour {
|
||||
/// <summary> 视图空间位置 </summary>
|
||||
public abstract Vector3 Position { get; set; }
|
||||
/// <summary> 视图空间旋转 </summary>
|
||||
public abstract Vector3 EulerAngles { get; set; }
|
||||
/// <summary> 视图空间缩放 </summary>
|
||||
public abstract Vector3 LocalScale { get; set; }
|
||||
/// <summary> 相机正交大小 </summary>
|
||||
public abstract float OrthographicSize { get; set; }
|
||||
/// <summary> 当前视图空间的中心点 </summary>
|
||||
public abstract Vector3 CurrentViewSpaceCenter { get; }
|
||||
/// <summary> 相机的世界位置 </summary>
|
||||
public abstract Vector3 CameraWorldPosition { get; }
|
||||
/// <summary> 必须要初始化 </summary>
|
||||
protected abstract void Awake();
|
||||
/// <summary> 核心模块 </summary>
|
||||
protected virtual ModuleCore ModuleCore => ModuleCore.I;
|
||||
|
||||
/// <summary> 视图位置 </summary>
|
||||
public abstract Vector3 position { get; set; }
|
||||
/// <summary> 视图旋转 </summary>
|
||||
public abstract Vector3 eulerAngles { get; set; }
|
||||
/// <summary> 视图缩放 </summary>
|
||||
public abstract float scale { get; set; }
|
||||
/// <summary> 渲染纹理 </summary>
|
||||
public abstract RenderTexture RenderTexture { get; }
|
||||
|
||||
protected abstract void Awake();
|
||||
|
||||
protected virtual ModuleCore ModuleCore => ModuleCore.I;
|
||||
|
||||
/// <summary> 更新渲染纹理 </summary>
|
||||
public abstract void UpdateRenderTexture(int x, int y);
|
||||
/// <summary> 屏幕坐标转换视图坐标(0-1) </summary>
|
||||
public abstract Vector3 ScreenToViewPosition(Vector3 screenPosition);
|
||||
/// <summary> 屏幕坐标转换世界坐标 </summary>
|
||||
public abstract Vector2 ScreenToWorldPosition(Vector2 screenPosition);
|
||||
/// <summary> 屏幕坐标转换世界坐标 (0-1) </summary>
|
||||
public abstract Vector2 ScreenToViewPosition(Vector2 screenPosition);
|
||||
/// <summary> 从屏幕坐标发射一条射线 </summary>
|
||||
public abstract Ray ScreenPointToRay(Vector2 screenPosition);
|
||||
public abstract Vector3 ScreenToWorldPosition(Vector3 screenPosition);
|
||||
/// <summary> 视图坐标(0-1)转换屏幕坐标 </summary>
|
||||
public abstract Vector3 ViewToScreenPosition(Vector3 screenPosition);
|
||||
/// <summary> 视图坐标(0-1)转换世界坐标 </summary>
|
||||
public abstract Vector3 ViewToWorldPosition(Vector3 screenPosition);
|
||||
/// <summary> 世界坐标转换屏幕坐标 </summary>
|
||||
public abstract Vector3 WorldToScreenPosition(Vector3 screenPosition);
|
||||
/// <summary> 世界坐标转换视图坐标(0-1) </summary>
|
||||
public abstract Vector3 WorldToViewPosition(Vector3 screenPosition);
|
||||
}
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public abstract class ModuleViewInput : MonoBehaviour {
|
||||
/// <summary> 主键输入模块类型 </summary>
|
||||
public abstract event Action<Type> OnInputType;
|
||||
/// <summary> 必须要初始化 </summary>
|
||||
protected abstract void Awake();
|
||||
/// <summary> 核心模块 </summary>
|
||||
protected virtual ModuleCore ModuleCore => ModuleCore.I;
|
||||
|
||||
public abstract void SetPrimaryKeyInput<T>(T inputUnit) where T : ModuleViewInputUnit;
|
||||
|
||||
/// <summary> 按下鼠标左键 </summary>
|
||||
public abstract void DownLeftMouse(DataMouseInput data);
|
||||
/// <summary> 拖拽鼠标左键 </summary>
|
||||
public abstract void DragLeftMouse(DataMouseInput data);
|
||||
/// <summary> 移动鼠标左键 </summary>
|
||||
public abstract void MoveLeftMouse(DataMouseInput data);
|
||||
/// <summary> 释放鼠标左键 </summary>
|
||||
public abstract void ReleaseLeftMouse(DataMouseInput data);
|
||||
|
||||
/// <summary> 按下鼠标右键 </summary>
|
||||
public abstract void DownRightMouse(DataMouseInput data);
|
||||
/// <summary> 拖拽鼠标右键 </summary>
|
||||
public abstract void DragRightMouse(DataMouseInput data);
|
||||
/// <summary> 移动鼠标右键 </summary>
|
||||
public abstract void MoveRightMouse(DataMouseInput data);
|
||||
/// <summary> 释放鼠标右键 </summary>
|
||||
public abstract void ReleaseRightMouse(DataMouseInput data);
|
||||
|
||||
/// <summary> 按下鼠标中键 </summary>
|
||||
public abstract void DownMiddleMouse(DataMouseInput data);
|
||||
/// <summary> 拖拽鼠标中键 </summary>
|
||||
public abstract void DragMiddleMouse(DataMouseInput data);
|
||||
/// <summary> 移动鼠标中键 </summary>
|
||||
public abstract void MoveMiddleMouse(DataMouseInput data);
|
||||
/// <summary> 释放鼠标中键 </summary>
|
||||
public abstract void ReleaseMiddleMouse(DataMouseInput data);
|
||||
|
||||
/// <summary> 鼠标滚轮 </summary>
|
||||
public abstract void ScrollWheel(DataMouseInput data);
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f56f94c154ec7d84eb464a1509810d78
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,16 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// 生成可视化内容模块
|
||||
/// </summary>
|
||||
public abstract class ModuleVisual<Data> : MonoBehaviour {
|
||||
/// <summary> 必须要初始化 </summary>
|
||||
protected abstract void Awake();
|
||||
/// <summary> 核心模块 </summary>
|
||||
protected virtual ModuleCore ModuleCore => ModuleCore.I;
|
||||
|
||||
/// <summary> 更新可视化 </summary>
|
||||
public abstract void UpdateVisual(Data data);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 32a3e92bdd9f12a4dbaeadda30a66075
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,15 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class DataDesignPoint {
|
||||
public readonly DataPlate dataPlate;
|
||||
public DataDesignPoint(DataPlate dataPlate) { this.dataPlate = dataPlate; }
|
||||
|
||||
public int index;
|
||||
public Vector2 postiton;
|
||||
public Vector2 leftBezier;//贝塞尔曲线左(逆时针+)
|
||||
public Vector2 rightBezier;//贝塞尔曲线右(顺时针-)
|
||||
public List<Vector2> edgePoints = new List<Vector2>();
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 215036ac2145e9f45835ea28080aee53
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,29 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class PrefabBezierPoint : MonoBehaviour {
|
||||
public LineRenderer bezierLine;
|
||||
private Vector2 position;
|
||||
private DataDesignPoint value;
|
||||
private Action<Vector2> callback;
|
||||
public DataPlate DataPlate => value.dataPlate;
|
||||
public Vector2 Position => position + value.postiton;
|
||||
public void SetValue(DataDesignPoint value, Action<Vector2> callback) {
|
||||
this.value = value;
|
||||
this.callback = callback;
|
||||
}
|
||||
public void SetPosition(Vector2 position) {
|
||||
this.position = position;
|
||||
float lx = position.x * 50;
|
||||
float ly = position.y * 50;
|
||||
transform.localPosition = new Vector3(lx, ly, transform.localPosition.z);
|
||||
bezierLine.SetPosition(1, position);
|
||||
}
|
||||
public void Change(Vector2 localPosition) {
|
||||
Vector2 position = localPosition - value.postiton;
|
||||
SetPosition(position);
|
||||
callback?.Invoke(position);
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1a3d9fd1b34a70c4ca6a4edaf6715131
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,54 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using MuHua;
|
||||
|
||||
public class PrefabDesignPoint : MonoBehaviour, ITemplate<DataDesignPoint> {
|
||||
public LineRenderer lineRenderer;
|
||||
public EdgeCollider2D edgeCollider;
|
||||
|
||||
public PrefabBezierPoint bezierPoint1;
|
||||
public PrefabBezierPoint bezierPoint2;
|
||||
|
||||
private DataDesignPoint value;
|
||||
public int Index => value.index;
|
||||
public Vector2 Position => value.postiton;
|
||||
public List<Vector2> EdgePoints => value.edgePoints;
|
||||
public DataPlate DataPlate => value.dataPlate;
|
||||
public int MaxIndex => DataPlate.designPoints.Count;
|
||||
public int NextIndex => DataPlateTool.NormalIndex(Index + 1, MaxIndex);
|
||||
public void SetValue(DataDesignPoint value) {
|
||||
this.value = value;
|
||||
bezierPoint1.SetValue(value, (obj) => { value.leftBezier = obj; });
|
||||
bezierPoint2.SetValue(value, (obj) => { value.rightBezier = obj; });
|
||||
DataPlate.OnChangeDesignPoint += DataPlate_OnChangeDesignPoint;
|
||||
DataPlate_OnChangeDesignPoint(Index);
|
||||
}
|
||||
private void OnDestroy() {
|
||||
DataPlate.OnChangeDesignPoint -= DataPlate_OnChangeDesignPoint;
|
||||
}
|
||||
private void DataPlate_OnChangeDesignPoint(int index) {
|
||||
if (index != Index) { return; }
|
||||
transform.localPosition = Position;
|
||||
//添加全部点
|
||||
int maxIndex = EdgePoints.Count + 1;
|
||||
lineRenderer.positionCount = maxIndex;
|
||||
Vector2[] vectors = new Vector2[maxIndex];
|
||||
for (int i = 0; i < EdgePoints.Count; i++) {
|
||||
Vector2 position = EdgePoints[i] - Position;
|
||||
lineRenderer.SetPosition(i, position);
|
||||
vectors[i] = position;
|
||||
}
|
||||
//添加最后一个点
|
||||
int last = maxIndex - 1;
|
||||
DataDesignPoint nextDesignPoint = DataPlate.FindDesignPoint(NextIndex);
|
||||
Vector2 position2 = nextDesignPoint.postiton - Position;
|
||||
lineRenderer.SetPosition(last, position2);
|
||||
vectors[last] = position2;
|
||||
//更新2D线段碰撞器
|
||||
edgeCollider.points = vectors;
|
||||
//更新贝塞尔曲线
|
||||
bezierPoint1.SetPosition(value.leftBezier);
|
||||
bezierPoint2.SetPosition(value.rightBezier);
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 76c13895912b8cd48a099779cbd0af65
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9ce7a65aa37a4934ba8d85a6136d8c32
|
||||
guid: 152682a505646cc41a3bb70493adf97d
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
@@ -0,0 +1,25 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class DataFindBezier {
|
||||
|
||||
/// <summary> 有效的点 </summary>
|
||||
public bool IsValid => plate != null && point != null;
|
||||
|
||||
#region 输入
|
||||
/// <summary> 位置 (需要和点同一个坐标系) </summary>
|
||||
public Vector3 position;
|
||||
/// <summary> 板片数据 </summary>
|
||||
public List<DataPlate> datas;
|
||||
#endregion
|
||||
|
||||
#region 输出
|
||||
/// <summary> 是前点(-) </summary>
|
||||
public bool isFront;
|
||||
/// <summary> 查询到的板片 </summary>
|
||||
public DataPlate plate;
|
||||
/// <summary> 查询到的点 </summary>
|
||||
public DataPoint point;
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 538ffda5b096d9d4cb1916697828a300
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,25 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class DataFindPoint {
|
||||
|
||||
/// <summary> 有效的板片 </summary>
|
||||
public bool IsValidPlate => plate != null;
|
||||
/// <summary> 有效的点 </summary>
|
||||
public bool IsValidPoint => point != null;
|
||||
|
||||
#region 输入
|
||||
/// <summary> 位置 (需要和点同一个坐标系) </summary>
|
||||
public Vector3 position;
|
||||
/// <summary> 板片数据 </summary>
|
||||
public List<DataPlate> datas;
|
||||
#endregion
|
||||
|
||||
#region 输出
|
||||
/// <summary> 查询到的板片 </summary>
|
||||
public DataPlate plate;
|
||||
/// <summary> 查询到的点 </summary>
|
||||
public DataPoint point;
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e7f89410b01930c418b1df0a10a9f4cc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,26 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class DataInsertPoint {
|
||||
|
||||
/// <summary> 有效的</summary>
|
||||
public bool IsValid => plate != null && aPoint != null && bPoint != null;
|
||||
|
||||
#region 输入
|
||||
/// <summary> 位置 (需要和点同一个坐标系) </summary>
|
||||
public Vector3 position;
|
||||
/// <summary> 板片数据 </summary>
|
||||
public List<DataPlate> datas;
|
||||
#endregion
|
||||
|
||||
#region 输出
|
||||
/// <summary> 执行操作的板片 </summary>
|
||||
public DataPlate plate;
|
||||
/// <summary> A点 </summary>
|
||||
public DataPoint aPoint;
|
||||
/// <summary> B点 </summary>
|
||||
public DataPoint bPoint;
|
||||
#endregion
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 25155dff8d9629a46a71219ab08dd82a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -4,25 +4,30 @@ using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class DataPlate {
|
||||
public Action OnChange;
|
||||
public Action<int> OnChangeDesignPoint;
|
||||
public Action<int> OnChangeEdgePoint;
|
||||
|
||||
#region 核心数据
|
||||
/// <summary> 边缘平滑度 </summary>
|
||||
public float edgeSmooth = 0.01f;
|
||||
/// <summary> 板片位置(本地坐标系) </summary>
|
||||
public Vector3 position;
|
||||
/// <summary> 设计点 </summary>
|
||||
public List<DataDesignPoint> designPoints = new List<DataDesignPoint>();
|
||||
public List<DataPoint> points = new List<DataPoint>();
|
||||
#endregion
|
||||
|
||||
/// <summary> 模型中心点偏移 </summary>
|
||||
public Vector3 centerOffset;
|
||||
#region 次要数据
|
||||
/// <summary> 平面网格 </summary>
|
||||
public Mesh polygon;
|
||||
/// <summary> 边缘点 </summary>
|
||||
public List<Vector2> edgePoints = new List<Vector2>();
|
||||
public List<Vector3> edgePoints = new List<Vector3>();
|
||||
#endregion
|
||||
|
||||
#region 可视化数据
|
||||
/// <summary> 可视化对象 </summary>
|
||||
public Transform transform;
|
||||
/// <summary> 可视化多边形网格 </summary>
|
||||
public MeshFilter polygonMeshFilter;
|
||||
/// <summary> 可视化边缘线 </summary>
|
||||
public LineRenderer edgeLineRenderer;
|
||||
#endregion
|
||||
|
||||
//平面网格数据
|
||||
/// <summary> 顶点 </summary>
|
||||
public List<Vector3> vertices = new List<Vector3>();
|
||||
/// <summary> UV </summary>
|
||||
public List<Vector2> uv = new List<Vector2>();
|
||||
/// <summary> 三角形 </summary>
|
||||
public List<int> triangles = new List<int>();
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class DataPoint {
|
||||
/// <summary> 绑定的板片 </summary>
|
||||
public readonly DataPlate plate;
|
||||
/// <summary> 初始化 </summary>
|
||||
public DataPoint(DataPlate plate) => this.plate = plate;
|
||||
|
||||
#region 核心数据
|
||||
/// <summary> 点前(-) 是否是曲线 </summary>
|
||||
public bool isCurveFront;
|
||||
/// <summary> 点后(+) 是否是曲线 </summary>
|
||||
public bool isCurveAfter;
|
||||
/// <summary> 设计点位置(本地坐标系) </summary>
|
||||
public Vector3 position;
|
||||
/// <summary> 贝塞尔曲线前(-) </summary>
|
||||
public Vector3 frontBezier;
|
||||
/// <summary> 贝塞尔曲线后(+) </summary>
|
||||
public Vector3 afterBezier;
|
||||
#endregion
|
||||
|
||||
#region 可视化数据
|
||||
/// <summary> 可视化对象 </summary>
|
||||
public Transform transform;
|
||||
/// <summary> 可视化贝塞尔点前(-) </summary>
|
||||
public Transform frontBezierTransform;
|
||||
/// <summary> 可视化贝塞尔点后(+) </summary>
|
||||
public Transform afterBezierTransform;
|
||||
/// <summary> 可视化贝塞尔线前(-) </summary>
|
||||
public LineRenderer frontBezierLineRenderer;
|
||||
/// <summary> 可视化贝塞尔线后(+) </summary>
|
||||
public LineRenderer afterBezierLineRenderer;
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 753c1b80d6d80af4baaa095760bdc3f5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,12 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class DataTriangle {
|
||||
public Vector3 a;
|
||||
public Vector3 b;
|
||||
public Vector3 c;
|
||||
public override string ToString() {
|
||||
return $"{a} , {b} , {c}";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0119f0f1ae644424b8ed9bd212d86ec1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,61 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using MuHua;
|
||||
|
||||
public class PrefabPlate : MonoBehaviour, ITemplate<DataPlate> {
|
||||
public Transform DesignPointParent;
|
||||
public Transform DesignPointTemplate;
|
||||
public Transform PlateEdgeParent;
|
||||
public Transform PlateEdgeTemplate;
|
||||
|
||||
private DataPlate value;
|
||||
private Vector3 localPosition;
|
||||
|
||||
public MeshFilter MeshFilter => GetComponent<MeshFilter>();
|
||||
public MeshCollider MeshCollider => GetComponent<MeshCollider>();
|
||||
public ModuleViewCamera viewCamera => ModuleCore.I.PlateDesignViewCamera;
|
||||
public void SetValue(DataPlate value) {
|
||||
this.value = value;
|
||||
localPosition = viewCamera.CurrentViewSpaceCenter;
|
||||
value.OnChange += DataPlate_OnChange;
|
||||
value.Compute();
|
||||
}
|
||||
private void OnDestroy() {
|
||||
value.OnChange -= DataPlate_OnChange;
|
||||
}
|
||||
public void DataPlate_OnChange() {
|
||||
CreateDesignPoint();
|
||||
//CreatePrefabEdgePoint();
|
||||
CreatePolygonMesh();
|
||||
//重置坐标
|
||||
transform.localPosition = localPosition + value.centerOffset;
|
||||
localPosition = transform.localPosition;
|
||||
}
|
||||
/// <summary> 生成设计点 </summary>
|
||||
private void CreateDesignPoint() {
|
||||
DesignPointParent.Instantiate(DesignPointTemplate, value.designPoints);
|
||||
}
|
||||
/// <summary> 生成边缘点 </summary>
|
||||
private void CreatePrefabEdgePoint() {
|
||||
PlateEdgeParent.DestroySon(PlateEdgeTemplate);
|
||||
for (int i = 0; i < value.edgePoints.Count; i++) {
|
||||
Transform temp = Instantiate(PlateEdgeTemplate, PlateEdgeParent);
|
||||
temp.gameObject.SetActive(true);
|
||||
PrefabPlateEdge plateEdge = temp.GetComponent<PrefabPlateEdge>();
|
||||
plateEdge.SetValue(i, value);
|
||||
}
|
||||
}
|
||||
/// <summary> 生成网格 </summary>
|
||||
private void CreatePolygonMesh() {
|
||||
Mesh mesh = new Mesh();
|
||||
mesh.vertices = value.vertices.ToArray();
|
||||
mesh.uv = value.uv.ToArray();
|
||||
mesh.triangles = value.triangles.ToArray();
|
||||
mesh.RecalculateBounds();
|
||||
mesh.RecalculateNormals();
|
||||
mesh.RecalculateTangents();
|
||||
MeshFilter.mesh = mesh;
|
||||
MeshCollider.sharedMesh = mesh;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: efaf2ad171011c7448092aa48eaf41c4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,34 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using MuHua;
|
||||
|
||||
public class PrefabPlateEdge : MonoBehaviour {
|
||||
public LineRenderer lineRenderer;
|
||||
public EdgeCollider2D edgeCollider;
|
||||
|
||||
[HideInInspector] public int index;
|
||||
[HideInInspector] public DataPlate value;
|
||||
|
||||
public int MaxIndex => value.edgePoints.Count;
|
||||
public int NextIndex => DataPlateTool.NormalIndex(index + 1, MaxIndex);
|
||||
public Vector3 CurrentPosition => value.FindEdgePoint(index);
|
||||
public Vector3 NextPosition => value.FindEdgePoint(NextIndex);
|
||||
public void SetValue(int index, DataPlate value) {
|
||||
this.index = index;
|
||||
this.value = value;
|
||||
value.OnChangeEdgePoint += UpdateLineRenderer;
|
||||
UpdateLineRenderer(index);
|
||||
}
|
||||
private void OnDestroy() {
|
||||
value.OnChangeEdgePoint -= UpdateLineRenderer;
|
||||
}
|
||||
public void UpdateLineRenderer(int index) {
|
||||
if (index != this.index && index != NextIndex) { return; }
|
||||
transform.localPosition = CurrentPosition;
|
||||
|
||||
Vector3 direction = NextPosition - CurrentPosition;
|
||||
lineRenderer.SetPosition(1, direction);
|
||||
edgeCollider.points = new Vector2[] { Vector2.zero, direction };
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6e74baea99ddf044c8a16b4d0eacf8ca
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
[CreateAssetMenu(fileName = "PresetsPlate", menuName = "数据模块/预设模板")]
|
||||
public class DataPlatePresets : ScriptableObject {
|
||||
public List<Vector3> designPoints;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b4c187df8599632449d401e9840a5bf9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,33 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class DataPolygon {
|
||||
private readonly DataPlate dataPlate;
|
||||
public DataPolygon(DataPlate dataPlate) => this.dataPlate = dataPlate;
|
||||
|
||||
/// <summary> 边缘平滑度 </summary>
|
||||
public float edgeSmooth => dataPlate.edgeSmooth;
|
||||
/// <summary> 设计点 </summary>
|
||||
public List<DataPoint> points => dataPlate.points;
|
||||
/// <summary> 边缘点 </summary>
|
||||
public List<Vector3> edgePoints {
|
||||
get => dataPlate.edgePoints;
|
||||
set => dataPlate.edgePoints = value;
|
||||
}
|
||||
/// <summary> 平面网格 </summary>
|
||||
public Mesh polygon {
|
||||
get => dataPlate.polygon;
|
||||
set => dataPlate.polygon = value;
|
||||
}
|
||||
|
||||
#region 参数
|
||||
|
||||
#endregion
|
||||
|
||||
#region 缓存
|
||||
/// <summary> 三角形 </summary>
|
||||
public List<DataTriangle> triangles = new List<DataTriangle>();
|
||||
#endregion
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3de8098a0297b56429874d2696f59d43
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,31 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
[CreateAssetMenu(fileName = "PresetsPlate", menuName = "数据模块/预设模板")]
|
||||
public class DataPresetsPlate : ScriptableObject {
|
||||
public List<Vector2> designPoints;
|
||||
public DataPlate ToPlate() {
|
||||
DataPlate data = new DataPlate();
|
||||
data.designPoints = new List<DataDesignPoint>();
|
||||
int maxIndex = designPoints.Count;
|
||||
for (int i = 0; i < designPoints.Count; i++) {
|
||||
Vector2 position = designPoints[i];
|
||||
int left = DataPlateTool.NormalIndex(i + 1, maxIndex);
|
||||
int right = DataPlateTool.NormalIndex(i - 1, maxIndex);
|
||||
Vector2 leftBezier = (designPoints[left] - position) * 0.5f;
|
||||
Vector2 rightBezier = (designPoints[right] - position) * 0.5f;
|
||||
DataDesignPoint designPoint = CreateDataDesignPoint(i, position, data);
|
||||
designPoint.leftBezier = leftBezier;
|
||||
designPoint.rightBezier = rightBezier;
|
||||
data.designPoints.Add(designPoint);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
private DataDesignPoint CreateDataDesignPoint(int index, Vector2 position, DataPlate data) {
|
||||
DataDesignPoint designPoint = new DataDesignPoint(data);
|
||||
designPoint.index = index;
|
||||
designPoint.postiton = position;
|
||||
return designPoint;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: de9e8e0217c52a447a49c55f818131ef
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,10 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class DataUIMouseInput {
|
||||
public float ScrollWheel;
|
||||
public Vector3 ViewPosition;
|
||||
public Vector3 WorldPosition;
|
||||
public Vector3 ScreenPosition;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: aa77786584d959a418d65b0eb3066b4d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,54 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// 算法:中心角度排序法
|
||||
/// 依据:???
|
||||
/// </summary>
|
||||
public class AlgorithmEdge : ModuleAlgorithm<DataPlate> {
|
||||
/// <summary> 算法:中心角度排序法 </summary>
|
||||
public AlgorithmEdge() { }
|
||||
|
||||
public class EdgeAngle {
|
||||
public float angle;
|
||||
public Vector3 position;
|
||||
}
|
||||
|
||||
public override void Compute(DataPlate data) {
|
||||
List<Vector2> edgePoints = data.edgePoints;
|
||||
//计算多边形中心点
|
||||
float x = edgePoints.Average((v3) => v3.x);
|
||||
float y = edgePoints.Average((v3) => v3.y);
|
||||
Vector2 center = new Vector2(x, y);
|
||||
//计算所有点的夹角
|
||||
Vector3 direction = edgePoints[0] - center;
|
||||
List<EdgeAngle> angleList = new List<EdgeAngle>();
|
||||
for (int i = 0; i < edgePoints.Count; i++) {
|
||||
Vector3 normal = edgePoints[i] - center;
|
||||
EdgeAngle edgeAngle = new EdgeAngle();
|
||||
edgeAngle.angle = Angle(direction, normal);
|
||||
edgeAngle.position = normal;
|
||||
angleList.Add(edgeAngle);
|
||||
}
|
||||
data.centerOffset = center;
|
||||
//排序
|
||||
angleList.Sort((x, y) => x.angle.CompareTo(y.angle));
|
||||
//把排序好的边缘点重新添加
|
||||
data.edgePoints = new List<Vector2>();
|
||||
for (int i = 0; i < angleList.Count; i++) {
|
||||
data.edgePoints.Add(angleList[i].position);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 计算两点夹角
|
||||
/// </summary>
|
||||
/// <param name="direction">0度点位置</param>
|
||||
/// <param name="position">目标点</param>
|
||||
/// <returns></returns>
|
||||
private float Angle(Vector3 direction, Vector3 position) {
|
||||
float angle = Vector2.SignedAngle(direction, position);
|
||||
return angle;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d17cdf61cce7657489b657640646a786
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,64 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// 算法:根据设计点来生成边缘点
|
||||
/// 依据:???
|
||||
/// </summary>
|
||||
public class AlgorithmGenerateEdge : ModuleAlgorithm<DataPlate> {
|
||||
/// <summary> 算法:根据设计点来生成边缘点 </summary>
|
||||
public AlgorithmGenerateEdge() { }
|
||||
|
||||
public override void Compute(DataPlate data) {
|
||||
data.edgePoints = new List<Vector2>();
|
||||
int maxIndex = data.designPoints.Count;
|
||||
for (int i = 0; i < maxIndex; i++) {
|
||||
DataDesignPoint designPoint = data.FindDesignPoint(i);
|
||||
DataDesignPoint nextDesignPoint = data.FindDesignPoint(i + 1);
|
||||
CreateStraightLine(data, designPoint, nextDesignPoint);
|
||||
}
|
||||
}
|
||||
public void CreateStraightLine(DataPlate data, DataDesignPoint designPoint, DataDesignPoint nextDesignPoint) {
|
||||
designPoint.edgePoints = new List<Vector2>();
|
||||
//方向,距离
|
||||
Vector2 direction = (nextDesignPoint.postiton - designPoint.postiton).normalized;
|
||||
float distance = Vector2.Distance(nextDesignPoint.postiton, designPoint.postiton);
|
||||
//求余,得商数
|
||||
int a = (int)(distance * 1000);
|
||||
int b = (int)(data.edgeSmooth * 1000);
|
||||
int quotient = Math.DivRem(a, b, out int remainder);
|
||||
//点位间距
|
||||
float segment = distance / quotient;
|
||||
Vector3 ap = designPoint.postiton;
|
||||
Vector3 bp = designPoint.leftBezier + designPoint.postiton;
|
||||
Vector3 cp = nextDesignPoint.rightBezier + nextDesignPoint.postiton;
|
||||
Vector3 dp = nextDesignPoint.postiton;
|
||||
for (int i = 0; i < quotient; i++) {
|
||||
float t = segment * i / distance;
|
||||
Vector2 position = ComputeBezier(ap, bp, cp, dp, t);
|
||||
designPoint.edgePoints.Add(position);
|
||||
}
|
||||
data.edgePoints.AddRange(designPoint.edgePoints);
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="a">起点</param>
|
||||
/// <param name="b">起点的贝塞尔点</param>
|
||||
/// <param name="c">终点的贝塞尔点</param>
|
||||
/// <param name="d">终点</param>
|
||||
/// <param name="t">进度</param>
|
||||
/// <returns></returns>
|
||||
public Vector3 ComputeBezier(Vector3 a, Vector3 b, Vector3 c, Vector3 d, float t) {
|
||||
Vector3 aa = a + (b - a) * t;
|
||||
Vector3 bb = b + (c - b) * t;
|
||||
Vector3 cc = c + (d - c) * t;
|
||||
|
||||
Vector3 aaa = aa + (bb - aa) * t;
|
||||
Vector3 bbb = bb + (cc - bb) * t;
|
||||
return aaa + (bbb - aaa) * t;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3d0c7458fc5119243b7db98671184058
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,186 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// 算法:耳切法
|
||||
/// 依据:简单多边形的双耳定理
|
||||
/// </summary>
|
||||
public class AlgorithmPolygon : ModuleAlgorithm<DataPlate> {
|
||||
/// <summary> 算法:耳切法 </summary>
|
||||
public AlgorithmPolygon() { }
|
||||
|
||||
public enum AngleType {
|
||||
/// <summary> 平角 = 180 </summary>
|
||||
StraightAngle = 0,
|
||||
/// <summary> 优角 >180 </summary>
|
||||
ReflexAngle = 1,
|
||||
/// <summary> 劣角 <180 </summary>
|
||||
InferiorAngle = 2
|
||||
}
|
||||
|
||||
public class PointNode {
|
||||
public int index;
|
||||
public Vector2 Position;
|
||||
public Vector2 PreviousPosition;
|
||||
public Vector2 NextPosition;
|
||||
}
|
||||
|
||||
public class Triangle {
|
||||
public Vector2 a;
|
||||
public Vector2 b;
|
||||
public Vector2 c;
|
||||
}
|
||||
|
||||
public override void Compute(DataPlate data) {
|
||||
List<Vector2> edgePoints = new List<Vector2>(data.edgePoints);
|
||||
List<Triangle> polygons = new List<Triangle>();
|
||||
Vector2[] allArray = edgePoints.ToArray();
|
||||
bool isClockWise = IsClockWise(allArray);
|
||||
//耳切法生成三角形
|
||||
ComputeEarTriangle(polygons, edgePoints, allArray, isClockWise);
|
||||
MergeTriangles(data, polygons);
|
||||
}
|
||||
/// <summary> 循环计算耳点 </summary>
|
||||
public void ComputeEarTriangle(List<Triangle> polygons, List<Vector2> edgePoints, Vector2[] allArray, bool isClockWise) {
|
||||
List<Triangle> temp = ComputeEarTriangle(edgePoints, allArray, isClockWise);
|
||||
if (temp.Count == 0) { return; }
|
||||
polygons.AddRange(temp);
|
||||
ComputeEarTriangle(polygons, edgePoints, allArray, isClockWise);
|
||||
}
|
||||
/// <summary> 计算一个耳点 </summary>
|
||||
public List<Triangle> ComputeEarTriangle(List<Vector2> edgePoints, Vector2[] allArray, bool isClockWise) {
|
||||
Vector2[] array = edgePoints.ToArray();
|
||||
List<Triangle> polygons = new List<Triangle>();
|
||||
for (int i = 0; i < array.Length; i++) {
|
||||
PointNode pointNode = CreatePointNode(i, array);
|
||||
AngleType angleType = GetAngleType(pointNode, isClockWise);
|
||||
// 等于180,不可能为耳点
|
||||
if (angleType == AngleType.StraightAngle) { continue; }
|
||||
// 大于180,不可能为耳点
|
||||
if (angleType == AngleType.ReflexAngle) { continue; }
|
||||
// 包含其他点,不可能为耳点
|
||||
if (IsInsideTriangle(pointNode, allArray)) { continue; }
|
||||
// 包含其他耳点,不可能成为耳点
|
||||
if (!IsInsideEarTriangle(pointNode, edgePoints)) { continue; }
|
||||
edgePoints.Remove(pointNode.Position);
|
||||
polygons.Add(CreateTriangle(pointNode));
|
||||
}
|
||||
return polygons;
|
||||
}
|
||||
/// <summary> 创建节点 </summary>
|
||||
public PointNode CreatePointNode(int index, Vector2[] array) {
|
||||
int maxIndex = array.Length;
|
||||
PointNode pointNode = new PointNode();
|
||||
pointNode.index = index;
|
||||
pointNode.PreviousPosition = array[NormalIndex(index - 1, maxIndex)];
|
||||
pointNode.Position = array[NormalIndex(index + 0, maxIndex)];
|
||||
pointNode.NextPosition = array[NormalIndex(index + 1, maxIndex)];
|
||||
return pointNode;
|
||||
}
|
||||
/// <summary> 计算三角形内是否包含其他点 </summary>
|
||||
public bool IsInsideTriangle(PointNode node, Vector2[] array) {
|
||||
for (int i = 0; i < array.Length; i++) {
|
||||
if (array[i] == node.Position) { continue; }
|
||||
if (array[i] == node.PreviousPosition) { continue; }
|
||||
if (array[i] == node.NextPosition) { continue; }
|
||||
if (IsInsideTriangle(node, array[i])) { return true; }
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/// <summary> 计算三角形内是否包含其他点 </summary>
|
||||
public bool IsInsideEarTriangle(PointNode node, List<Vector2> edgePoints) {
|
||||
if (!edgePoints.Contains(node.Position)) { return false; }
|
||||
if (!edgePoints.Contains(node.PreviousPosition)) { return false; }
|
||||
if (!edgePoints.Contains(node.NextPosition)) { return false; }
|
||||
return true;
|
||||
}
|
||||
/// <summary> 从节点创建三角形 </summary>
|
||||
public Triangle CreateTriangle(PointNode node) {
|
||||
Triangle triangle = new Triangle();
|
||||
triangle.a = node.Position;
|
||||
triangle.b = node.PreviousPosition;
|
||||
triangle.c = node.NextPosition;
|
||||
return triangle;
|
||||
}
|
||||
/// <summary> 合并三角形 </summary>
|
||||
public void MergeTriangles(DataPlate data, List<Triangle> polygons) {
|
||||
//创建数据容器
|
||||
List<Vector3> vertices = new List<Vector3>();
|
||||
List<Vector2> uv = new List<Vector2>();
|
||||
List<int> triangles = new List<int>();
|
||||
//三角形合并
|
||||
for (int i = 0; i < polygons.Count; i++) {
|
||||
Vector3 a = polygons[i].a;
|
||||
int aIndex = vertices.Count - 1;
|
||||
if (!vertices.Contains(a)) { vertices.Add(a); aIndex = vertices.Count - 1; }
|
||||
else { aIndex = vertices.IndexOf(a); }
|
||||
|
||||
Vector3 b = polygons[i].b;
|
||||
int bIndex = vertices.Count - 1;
|
||||
if (!vertices.Contains(b)) { vertices.Add(b); bIndex = vertices.Count - 1; }
|
||||
else { bIndex = vertices.IndexOf(b); }
|
||||
|
||||
Vector3 c = polygons[i].c;
|
||||
int cIndex = vertices.Count - 1;
|
||||
if (!vertices.Contains(c)) { vertices.Add(c); cIndex = vertices.Count - 1; }
|
||||
else { cIndex = vertices.IndexOf(c); }
|
||||
|
||||
triangles.Add(aIndex);
|
||||
triangles.Add(bIndex);
|
||||
triangles.Add(cIndex);
|
||||
}
|
||||
//展开uv (顶点去掉z坐标就是未缩放的平面UV)
|
||||
for (int i = 0; i < vertices.Count; i++) { uv.Add(vertices[i]); }
|
||||
//附加数据
|
||||
data.vertices = vertices;
|
||||
data.uv = uv;
|
||||
data.triangles = triangles;
|
||||
}
|
||||
|
||||
/// <summary> 头尾循环标准化索引 </summary>
|
||||
public static int NormalIndex(int index, int maxIndex) {
|
||||
if (maxIndex == 0) { Debug.LogError("错误索引:maxIndex = 0"); return 0; }
|
||||
if (index < 0) { return NormalIndex(index + maxIndex, maxIndex); }
|
||||
if (index >= maxIndex) { return NormalIndex(index - maxIndex, maxIndex); }
|
||||
return index;
|
||||
}
|
||||
/// <summary> 当前的点方向是否为顺时针 </summary>
|
||||
public static bool IsClockWise(Vector2[] array) {
|
||||
// 通过计算叉乘来确定方向
|
||||
float sum = 0f;
|
||||
double count = array.Length;
|
||||
Vector3 va, vb;
|
||||
for (int i = 0; i < array.Length; i++) {
|
||||
va = array[i];
|
||||
vb = (i == count - 1) ? array[0] : array[i + 1];
|
||||
sum += va.x * vb.y - va.y * vb.x;
|
||||
}
|
||||
return sum < 0;
|
||||
}
|
||||
/// <summary> 判断角的类型 </summary>
|
||||
public static AngleType GetAngleType(PointNode node, bool isClockWise) {
|
||||
// 角度是否小于180
|
||||
// oa & ob 之间的夹角,(右手法则)
|
||||
// 逆时针顺序是相反的
|
||||
Vector2 o = node.Position;
|
||||
Vector2 a = node.PreviousPosition;
|
||||
Vector2 b = node.NextPosition;
|
||||
float f = (a.x - o.x) * (b.y - o.y) - (a.y - o.y) * (b.x - o.x);
|
||||
bool flag = isClockWise ? f > 0 : f < 0;
|
||||
if (f == 0) { return AngleType.StraightAngle; }
|
||||
else if (flag) { return AngleType.InferiorAngle; }
|
||||
else { return AngleType.ReflexAngle; }
|
||||
}
|
||||
/// <summary> p点是否在点和其左右两个点组成的三角形内,或ca,cb边上 </summary>
|
||||
public static bool IsInsideTriangle(PointNode node, Vector2 p) {
|
||||
// p点是否在abc三角形内
|
||||
Vector2 a = node.PreviousPosition;
|
||||
Vector2 b = node.NextPosition;
|
||||
Vector2 c = node.Position;
|
||||
float c1 = (b.x - a.x) * (p.y - b.y) - (b.y - a.y) * (p.x - b.x);
|
||||
float c2 = (c.x - b.x) * (p.y - c.y) - (c.y - b.y) * (p.x - c.x);
|
||||
float c3 = (a.x - c.x) * (p.y - a.y) - (a.y - c.y) * (p.x - a.x);
|
||||
return (c1 > 0f && c2 >= 0f && c3 >= 0f) || (c1 < 0f && c2 <= 0f && c3 <= 0f);
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class AssetsPresetsPlate : ModuleAssets<DataPresetsPlate> {
|
||||
protected override void Awake() {
|
||||
ModuleCore.PresetsPlateAssets = this;
|
||||
}
|
||||
public override void ForEach(Action<DataPresetsPlate> action) {
|
||||
assets.ForEach(action);
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8198c73995924524d985c3beb338f033
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,9 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class EnumeratorAgent : ModuleAgent {
|
||||
protected override void Awake() {
|
||||
ModuleCore.ModuleAgent = this;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e79a947f40825b54a8b65cb2714fbe6e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: eda56199f140e8e41bde06c79efd4b8e
|
||||
guid: f6fbfbc1731723a4babd9d4ee59ded5b
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 46d78284a685f31429f5bd981c1f86c1
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,40 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// 查询贝塞尔点算法
|
||||
/// </summary>
|
||||
public class AlgorithmFindBezier : ModuleAlgorithm<DataFindBezier> {
|
||||
public readonly float FindRange = 0.01f;
|
||||
|
||||
protected override void Awake() => ModuleCore.AlgorithmFindBezier = this;
|
||||
|
||||
public override void Compute(DataFindBezier findBezier) {
|
||||
List<DataPlate> datas = findBezier.datas;
|
||||
for (int i = 0; i < datas.Count; i++) {
|
||||
if (FindPlatePoint(datas[i], findBezier)) { return; }
|
||||
}
|
||||
}
|
||||
/// <summary> 查询匹配的点 </summary>
|
||||
private bool FindPlatePoint(DataPlate plate, DataFindBezier findBezier) {
|
||||
List<DataPoint> points = plate.points;
|
||||
Vector3 position = findBezier.position - plate.position;
|
||||
for (int i = 0; i < points.Count; i++) {
|
||||
float f = Vector3.Distance(points[i].frontBezier, position);
|
||||
if (f <= FindRange && points[i].isCurveFront) {
|
||||
findBezier.isFront = true;
|
||||
findBezier.plate = plate;
|
||||
findBezier.point = points[i];
|
||||
return true;
|
||||
}
|
||||
float a = Vector3.Distance(points[i].afterBezier, position);
|
||||
if (a <= FindRange && points[i].isCurveAfter) {
|
||||
findBezier.plate = plate;
|
||||
findBezier.point = points[i];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4ecc5cf619be47744b8ac06557518014
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cd2aff163a310544886809b5b8590bb2
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,49 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// 查询点算法
|
||||
/// 转角法判断点是否在多边形内
|
||||
/// </summary>
|
||||
public class AlgorithmFindPoint : ModuleAlgorithm<DataFindPoint> {
|
||||
public readonly float FindRange = 0.01f;
|
||||
|
||||
protected override void Awake() => ModuleCore.AlgorithmFindPoint = this;
|
||||
|
||||
public override void Compute(DataFindPoint findPoint) {
|
||||
List<DataPlate> datas = findPoint.datas;
|
||||
for (int i = 0; i < datas.Count; i++) {
|
||||
if (FindPlatePoint(datas[i], findPoint)) { return; }
|
||||
if (FindPlateInside(datas[i], findPoint)) { findPoint.plate = datas[i]; }
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> 查询匹配的点 </summary>
|
||||
private bool FindPlatePoint(DataPlate plate, DataFindPoint findPoint) {
|
||||
List<DataPoint> points = plate.points;
|
||||
Vector3 position = findPoint.position - plate.position;
|
||||
for (int i = 0; i < points.Count; i++) {
|
||||
float distance = Vector3.Distance(points[i].position, position);
|
||||
if (distance > FindRange) { continue; }
|
||||
findPoint.plate = plate;
|
||||
findPoint.point = points[i];
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/// <summary> 转角法查询位置是否在板片内 </summary>
|
||||
private bool FindPlateInside(DataPlate plate, DataFindPoint findPoint) {
|
||||
DataPoint[] points = plate.points.ToArray();
|
||||
double angles = 0;
|
||||
Vector3 position = findPoint.position - plate.position;
|
||||
for (int i = 0; i < points.Length; i++) {
|
||||
Vector3 a = points.LoopIndex(i + 0).position - position;
|
||||
Vector3 b = points.LoopIndex(i + 1).position - position;
|
||||
float angle = Vector2.SignedAngle(a, b);
|
||||
angles += angle;
|
||||
}
|
||||
int normal = (int)(angles * 1000);
|
||||
return normal > 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 159a37d73c0c32e4cbb41b0767597000
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ce9e6ecaa5ce98843abd7070cf9adb82
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,74 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// 插入点算法
|
||||
/// </summary>
|
||||
public class AlgorithmInsertPoint : ModuleAlgorithm<DataInsertPoint> {
|
||||
public class Segment {
|
||||
public DataPlate plate;
|
||||
public DataPoint aPoint;
|
||||
public DataPoint bPoint;
|
||||
public float distance = float.MaxValue;
|
||||
}
|
||||
|
||||
protected override void Awake() => ModuleCore.AlgorithmInsertPoint = this;
|
||||
|
||||
public override void Compute(DataInsertPoint insertPoint) {
|
||||
List<DataPlate> datas = insertPoint.datas;
|
||||
List<Segment> segments = new List<Segment>();
|
||||
Vector3 position = insertPoint.position;
|
||||
|
||||
for (int i = 0; i < datas.Count; i++) {
|
||||
if (!FindSegment(datas[i], position, out Segment temp)) { continue; }
|
||||
segments.Add(temp);
|
||||
}
|
||||
|
||||
if (segments.Count <= 0) { return; }
|
||||
Segment segment = segments[0];
|
||||
for (int i = 0; i < segments.Count; i++) {
|
||||
if (segment.distance < segments[i].distance) { continue; }
|
||||
segment = segments[i];
|
||||
}
|
||||
insertPoint.plate = segment.plate;
|
||||
insertPoint.aPoint = segment.aPoint;
|
||||
insertPoint.bPoint = segment.bPoint;
|
||||
}
|
||||
/// <summary> 查询匹配的线 </summary>
|
||||
private bool FindSegment(DataPlate plate, Vector3 position, out Segment segment) {
|
||||
List<DataPoint> points = plate.points;
|
||||
Vector3 c = position - plate.position;
|
||||
segment = new Segment();
|
||||
segment.plate = plate;
|
||||
for (int i = 0; i < points.Count; i++) {
|
||||
Vector3 a = points.LoopIndex(i + 0).position;
|
||||
Vector3 b = points.LoopIndex(i + 1).position;
|
||||
float distance = ProjectDistance(a, b, c);
|
||||
if (segment.distance < distance) { continue; }
|
||||
segment.aPoint = points.LoopIndex(i + 0);
|
||||
segment.bPoint = points.LoopIndex(i + 1);
|
||||
segment.distance = distance;
|
||||
}
|
||||
return segment.distance != float.MaxValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 向量投影法
|
||||
/// 计算点c到线段ab最近的点
|
||||
/// </summary>
|
||||
/// <param name="a"></param>
|
||||
/// <param name="b"></param>
|
||||
/// <param name="c"></param>
|
||||
/// <returns>如果不在线段上返回 float.MaxValue</returns>
|
||||
private float ProjectDistance(Vector3 a, Vector3 b, Vector3 c) {
|
||||
Vector3 ab = b - a;
|
||||
Vector3 ac = c - a;
|
||||
Vector3 p = Vector3.Project(ac, ab);
|
||||
//Debug.Log($"{a} , {b} , {c} , {p} , {ab.normalized} , {p.normalized} , {ab.normalized != p.normalized} , {ab.magnitude < p.magnitude}");
|
||||
if (ab.normalized != p.normalized) { return float.MaxValue; }
|
||||
if (ab.magnitude < p.magnitude) { return float.MaxValue; }
|
||||
//Debug.Log($"{a} , {b} , {c} , {Vector3.Distance(c, p)}");
|
||||
return Vector3.Distance(c, p + a);
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6693b5fb3f035aa42bf27141ab05b01d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c315b7d2a7530784ab66ef5cc7d4d8b1
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,131 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// 多边形耳切法
|
||||
/// </summary>
|
||||
public class AFAuriculareCutting : ModuleAlgorithmFunction<DataPolygon> {
|
||||
public class Auriculare {
|
||||
public int index;
|
||||
public Vector3 aPoint;//+0
|
||||
public Vector3 bPoint;//-1
|
||||
public Vector3 cPoint;//+1
|
||||
}
|
||||
|
||||
/// <summary> 多边形耳切法 </summary>
|
||||
public AFAuriculareCutting() { }
|
||||
|
||||
public override void Compute(DataPolygon data) {
|
||||
List<Vector3> edgePoints = new List<Vector3>(data.edgePoints);
|
||||
List<DataTriangle> triangles = new List<DataTriangle>();
|
||||
Vector3[] allArray = edgePoints.ToArray();
|
||||
bool isClockWise = IsClockWise(allArray);
|
||||
//耳切法生成三角形
|
||||
ComputeAuriculare(triangles, edgePoints, allArray, isClockWise);
|
||||
data.triangles = triangles;
|
||||
}
|
||||
|
||||
#region 函数
|
||||
/// <summary> 循环计算有效的耳点 </summary>
|
||||
public static void ComputeAuriculare(List<DataTriangle> triangles, List<Vector3> edgePoints, Vector3[] allArray, bool isClockWise) {
|
||||
List<DataTriangle> temp = ComputeAuriculare(edgePoints, allArray, isClockWise);
|
||||
if (temp.Count == 0) { return; }
|
||||
triangles.AddRange(temp);
|
||||
ComputeAuriculare(triangles, edgePoints, allArray, isClockWise);
|
||||
}
|
||||
/// <summary> 计算一个有效的耳点 </summary>
|
||||
public static List<DataTriangle> ComputeAuriculare(List<Vector3> edgePoints, Vector3[] allArray, bool isClockWise) {
|
||||
Vector3[] array = edgePoints.ToArray();
|
||||
List<DataTriangle> polygons = new List<DataTriangle>();
|
||||
for (int i = 0; i < array.Length; i++) {
|
||||
Auriculare auriculare = CreateAuriculare(i, array);
|
||||
// 等于180,大于180,不可能为耳点
|
||||
if (!GetAngleType(auriculare, isClockWise)) { continue; }
|
||||
// 包含其他点,不可能为耳点
|
||||
if (IsInsideTriangle(auriculare, allArray)) { continue; }
|
||||
// 包含其他耳点,不可能成为耳点
|
||||
if (!IsInsideAuriculare(auriculare, edgePoints)) { continue; }
|
||||
edgePoints.Remove(auriculare.aPoint);
|
||||
polygons.Add(CreateAuriculareToTriangle(auriculare));
|
||||
}
|
||||
return polygons;
|
||||
}
|
||||
/// <summary> 创建点 </summary>
|
||||
public static Auriculare CreateAuriculare(int index, Vector3[] array) {
|
||||
Auriculare auriculare = new Auriculare();
|
||||
auriculare.index = index;
|
||||
auriculare.bPoint = array.LoopIndex(index - 1);
|
||||
auriculare.aPoint = array.LoopIndex(index);
|
||||
auriculare.cPoint = array.LoopIndex(index + 1);
|
||||
return auriculare;
|
||||
}
|
||||
/// <summary> 计算三角形内是否包含其他点 </summary>
|
||||
public static bool IsInsideTriangle(Auriculare auriculare, Vector3[] array) {
|
||||
for (int i = 0; i < array.Length; i++) {
|
||||
if (array[i] == auriculare.aPoint) { continue; }
|
||||
if (array[i] == auriculare.bPoint) { continue; }
|
||||
if (array[i] == auriculare.cPoint) { continue; }
|
||||
if (IsInsideTriangle(auriculare, array[i])) { return true; }
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/// <summary> 计算三角形内是否包含其他点 </summary>
|
||||
public static bool IsInsideAuriculare(Auriculare auriculare, List<Vector3> edgePoints) {
|
||||
if (!edgePoints.Contains(auriculare.aPoint)) { return false; }
|
||||
if (!edgePoints.Contains(auriculare.bPoint)) { return false; }
|
||||
if (!edgePoints.Contains(auriculare.cPoint)) { return false; }
|
||||
return true;
|
||||
}
|
||||
/// <summary> 从节点创建三角形 </summary>
|
||||
public static DataTriangle CreateAuriculareToTriangle(Auriculare auriculare) {
|
||||
DataTriangle triangle = new DataTriangle();
|
||||
triangle.a = auriculare.aPoint;
|
||||
triangle.b = auriculare.bPoint;
|
||||
triangle.c = auriculare.cPoint;
|
||||
return triangle;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 算法
|
||||
/// <summary> 当前的点方向是否为顺时针 </summary>
|
||||
public static bool IsClockWise(Vector3[] array) {
|
||||
// 通过计算叉乘来确定方向
|
||||
float sum = 0f;
|
||||
double count = array.Length;
|
||||
Vector3 va, vb;
|
||||
for (int i = 0; i < array.Length; i++) {
|
||||
va = array[i];
|
||||
vb = (i == count - 1) ? array[0] : array[i + 1];
|
||||
sum += va.x * vb.y - va.y * vb.x;
|
||||
}
|
||||
return sum < 0;
|
||||
}
|
||||
/// <summary> 判断角的类型 </summary>
|
||||
public static bool GetAngleType(Auriculare auriculare, bool isClockWise) {
|
||||
// 角度是否小于180
|
||||
// oa & ob 之间的夹角,(右手法则)
|
||||
// 逆时针顺序是相反的
|
||||
Vector2 a = auriculare.aPoint;
|
||||
Vector2 b = auriculare.bPoint;
|
||||
Vector2 c = auriculare.cPoint;
|
||||
float f = (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
|
||||
bool flag = isClockWise ? f > 0 : f < 0;
|
||||
if (f == 0) { return false;/*平角*/ }
|
||||
else if (flag) { return true;/*劣角*/ }
|
||||
else { return false;/*优角*/ }
|
||||
}
|
||||
/// <summary> p点是否在点a,b,c组成的三角形内,或边上 </summary>
|
||||
public static bool IsInsideTriangle(Auriculare auriculare, Vector2 p) {
|
||||
// p点是否在abc三角形内
|
||||
Vector2 a = auriculare.aPoint;
|
||||
Vector2 b = auriculare.bPoint;
|
||||
Vector2 c = auriculare.cPoint;
|
||||
float c1 = (b.x - a.x) * (p.y - b.y) - (b.y - a.y) * (p.x - b.x);
|
||||
float c2 = (c.x - b.x) * (p.y - c.y) - (c.y - b.y) * (p.x - c.x);
|
||||
float c3 = (a.x - c.x) * (p.y - a.y) - (a.y - c.y) * (p.x - a.x);
|
||||
return (c1 > 0f && c2 >= 0f && c3 >= 0f) || (c1 < 0f && c2 <= 0f && c3 <= 0f);
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e9b83b680d622b5409fb9f74a1eaaebf
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,76 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// 三阶贝塞尔曲线计算边缘点
|
||||
/// </summary>
|
||||
public class AFEdgePoint : ModuleAlgorithmFunction<DataPolygon> {
|
||||
|
||||
/// <summary> 三阶贝塞尔曲线计算边缘点 </summary>
|
||||
public AFEdgePoint() { }
|
||||
|
||||
public override void Compute(DataPolygon data) {
|
||||
List<DataPoint> points = new List<DataPoint>(data.points);
|
||||
List<Vector3> edgePoints = new List<Vector3>();
|
||||
for (int i = 0; i < points.Count; i++) {
|
||||
DataPoint current = points.LoopIndex(i);
|
||||
DataPoint next = points.LoopIndex(i + 1);
|
||||
edgePoints.AddRange(CreateLine(current, next, data.edgeSmooth));
|
||||
}
|
||||
data.edgePoints = edgePoints;
|
||||
}
|
||||
|
||||
#region 函数
|
||||
public List<Vector3> CreateLine(DataPoint current, DataPoint next, float edgeSmooth) {
|
||||
List<Vector3> edgePoints = new List<Vector3>();
|
||||
//方向,距离
|
||||
Vector2 direction = (next.position - current.position).normalized;
|
||||
float distance = Vector2.Distance(next.position, current.position);
|
||||
//求余,得商数
|
||||
int quotient = Quotient(distance, edgeSmooth);
|
||||
//点位间距
|
||||
float segment = distance / quotient;
|
||||
//贝塞尔曲线点
|
||||
Vector3 ap = current.position;
|
||||
Vector3 bp = current.isCurveAfter ? current.afterBezier : current.position;
|
||||
Vector3 cp = next.isCurveFront ? next.frontBezier : next.position;
|
||||
Vector3 dp = next.position;
|
||||
for (int i = 0; i < quotient; i++) {
|
||||
float t = segment * i / distance;
|
||||
Vector2 position = ComputeBezier(ap, bp, cp, dp, t);
|
||||
edgePoints.Add(position);
|
||||
}
|
||||
return edgePoints;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 算法
|
||||
/// <summary> 商数 </summary>
|
||||
public static int Quotient(float distance, float edgeSmooth) {
|
||||
int a = (int)(distance * 1000);
|
||||
int b = (int)(edgeSmooth * 1000);
|
||||
return Math.DivRem(a, b, out int remainder);
|
||||
}
|
||||
/// <summary>
|
||||
/// 三阶贝塞尔算法
|
||||
/// </summary>
|
||||
/// <param name="a">起点</param>
|
||||
/// <param name="b">起点的贝塞尔点</param>
|
||||
/// <param name="c">终点的贝塞尔点</param>
|
||||
/// <param name="d">终点</param>
|
||||
/// <param name="t">进度</param>
|
||||
/// <returns>当前进度的曲线点</returns>
|
||||
public static Vector3 ComputeBezier(Vector3 a, Vector3 b, Vector3 c, Vector3 d, float t) {
|
||||
Vector3 aa = a + (b - a) * t;
|
||||
Vector3 bb = b + (c - b) * t;
|
||||
Vector3 cc = c + (d - c) * t;
|
||||
|
||||
Vector3 aaa = aa + (bb - aa) * t;
|
||||
Vector3 bbb = bb + (cc - bb) * t;
|
||||
return aaa + (bbb - aaa) * t;
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e88d537872f0dba44ae4bda829b08c42
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,95 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// 合并三角形
|
||||
/// </summary>
|
||||
public class AFMergeTriangles : ModuleAlgorithmFunction<DataPolygon> {
|
||||
public override void Compute(DataPolygon data) {
|
||||
List<DataTriangle> triangles = new List<DataTriangle>(data.triangles);
|
||||
index = 0;
|
||||
MergeTriangles(triangles);
|
||||
data.triangles = triangles;
|
||||
ModuleCore.I.VisualPolygon.UpdateVisual(data);
|
||||
}
|
||||
private int index;
|
||||
private int maxIndex;
|
||||
/// <summary> 取一个三角形出来 匹配剩下的三角形 符合条件则合并 </summary>
|
||||
private void MergeTriangles(List<DataTriangle> triangles) {
|
||||
if (index > triangles.Count) { return; }
|
||||
|
||||
DataTriangle aT = triangles[0];
|
||||
triangles.Remove(aT);
|
||||
|
||||
maxIndex = triangles.Count;
|
||||
for (int i = 0; i < triangles.Count; i++) {
|
||||
DataTriangle bT = triangles[i];
|
||||
//ab同边
|
||||
if (MergeConditions(bT.a, bT.b, bT, ref aT)) { triangles.Remove(bT); continue; }
|
||||
//bc同边
|
||||
if (MergeConditions(bT.b, bT.c, bT, ref aT)) { triangles.Remove(bT); continue; }
|
||||
//ca同边
|
||||
if (MergeConditions(bT.c, bT.a, bT, ref aT)) { triangles.Remove(bT); continue; }
|
||||
}
|
||||
index = maxIndex == triangles.Count ? index + 1 : 0;
|
||||
Debug.Log($"{index} , {maxIndex} , {triangles.Count}");
|
||||
|
||||
triangles.Add(aT);
|
||||
MergeTriangles(triangles);
|
||||
}
|
||||
/// <summary> 匹配三角形 符合条件则合并 无法合并则返回 true </summary>
|
||||
private bool MergeTriangles(List<DataTriangle> triangles, DataTriangle aT) {
|
||||
for (int i = 0; i < triangles.Count; i++) {
|
||||
DataTriangle bT = triangles[i];
|
||||
//ab同边
|
||||
if (MergeConditions(bT.a, bT.b, bT, ref aT)) { triangles.Remove(bT); }
|
||||
//bc同边
|
||||
if (MergeConditions(bT.b, bT.c, bT, ref aT)) { triangles.Remove(bT); }
|
||||
//ca同边
|
||||
if (MergeConditions(bT.c, bT.a, bT, ref aT)) { triangles.Remove(bT); }
|
||||
}
|
||||
return true;
|
||||
}
|
||||
/// <summary> 计算三角形内是否包含其他点 </summary>
|
||||
private bool IsInsideTriangle(DataTriangle triangle, Vector3 point) {
|
||||
if (triangle.a == point) { return true; }
|
||||
if (triangle.b == point) { return true; }
|
||||
if (triangle.c == point) { return true; }
|
||||
return false;
|
||||
}
|
||||
//检测合并条件是否满足
|
||||
private bool MergeConditions(Vector3 a, Vector3 b, DataTriangle bT, ref DataTriangle aT) {
|
||||
if (!IsInsideTriangle(aT, a, b, out Vector3 o)) { return false; }
|
||||
if (!IsInsideTriangle(bT, a, b, out Vector3 c)) { return false; }
|
||||
if (IsInsideTriangle(aT, c)) { return true; }
|
||||
Vector3 oa = (o - a).normalized;
|
||||
Vector3 ob = (o - b).normalized;
|
||||
Vector3 oc = (o - c).normalized;
|
||||
if (oc == oa) { aT.a = o; aT.b = b; aT.c = c; return true; }
|
||||
if (oc == ob) { aT.a = o; aT.b = a; aT.c = c; return true; }
|
||||
return false;
|
||||
}
|
||||
/// <summary> 计算三角形内是否包含其他点 </summary>
|
||||
private bool IsInsideTriangle(DataTriangle triangle, Vector3 a, Vector3 b, out Vector3 o) {
|
||||
if (triangle.a == a && triangle.b == b) { o = triangle.c; return true; }
|
||||
if (triangle.a == b && triangle.b == a) { o = triangle.c; return true; }
|
||||
if (triangle.a == a && triangle.c == b) { o = triangle.b; return true; }
|
||||
if (triangle.a == b && triangle.c == a) { o = triangle.b; return true; }
|
||||
if (triangle.b == a && triangle.c == b) { o = triangle.a; return true; }
|
||||
if (triangle.b == b && triangle.c == a) { o = triangle.a; return true; }
|
||||
o = a; return false;
|
||||
}
|
||||
|
||||
/// <summary> p点是否在点a,b,c组成的三角形内,或边上 </summary>
|
||||
public static bool IsInsideTriangle(DataTriangle auriculare, Vector2 p) {
|
||||
// p点是否在abc三角形内
|
||||
Vector2 a = auriculare.a;
|
||||
Vector2 b = auriculare.b;
|
||||
Vector2 c = auriculare.c;
|
||||
float c1 = (b.x - a.x) * (p.y - b.y) - (b.y - a.y) * (p.x - b.x);
|
||||
float c2 = (c.x - b.x) * (p.y - c.y) - (c.y - b.y) * (p.x - c.x);
|
||||
float c3 = (a.x - c.x) * (p.y - a.y) - (a.y - c.y) * (p.x - a.x);
|
||||
return (c1 > 0f && c2 >= 0f && c3 >= 0f) || (c1 < 0f && c2 <= 0f && c3 <= 0f);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 45d3c753563f5be468680173acf8b1e8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,35 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class AFSubdivision : ModuleAlgorithmFunction<DataPolygon> {
|
||||
public override void Compute(DataPolygon data) {
|
||||
List<DataTriangle> triangles = new List<DataTriangle>(data.triangles);
|
||||
List<DataTriangle> subdivision = new List<DataTriangle>();
|
||||
for (int i = 0; i < triangles.Count; i++) {
|
||||
subdivision.AddRange(Subdivision(triangles[i]));
|
||||
}
|
||||
//subdivision.AddRange(Subdivision(triangles[121], data.edgeSmooth));
|
||||
|
||||
data.triangles = subdivision;
|
||||
}
|
||||
private List<DataTriangle> Subdivision(DataTriangle triangle) {
|
||||
float ab = Vector3.Distance(triangle.a, triangle.b);
|
||||
float bc = Vector3.Distance(triangle.b, triangle.c);
|
||||
float ca = Vector3.Distance(triangle.c, triangle.a);
|
||||
if (ab > bc && ab > ca && ab > 0.02f) { return Subdivision(triangle.c, triangle.a, triangle.b); }
|
||||
if (bc > ab && bc > ca && bc > 0.02f) { return Subdivision(triangle.a, triangle.b, triangle.c); }
|
||||
if (ca > bc && ca > ab && ca > 0.02f) { return Subdivision(triangle.b, triangle.c, triangle.a); }
|
||||
|
||||
return new List<DataTriangle> { triangle };
|
||||
}
|
||||
private List<DataTriangle> Subdivision(Vector3 a, Vector3 b, Vector3 c) {
|
||||
Vector3 direction = b - c;
|
||||
Vector3 d = c + direction * 0.5f;
|
||||
|
||||
DataTriangle aT = new DataTriangle { a = a, b = d, c = c };
|
||||
DataTriangle bT = new DataTriangle { a = a, b = b, c = d };
|
||||
return new List<DataTriangle> { aT, bT, };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bb4aa74668cf2134eb322b3a40d74c29
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,37 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// 三角形转换网格
|
||||
/// </summary>
|
||||
public class AFTriangleMesh : ModuleAlgorithmFunction<DataPolygon> {
|
||||
public override void Compute(DataPolygon data) {
|
||||
List<DataTriangle> polygons = new List<DataTriangle>(data.triangles);
|
||||
//创建数据容器
|
||||
List<Vector3> vertices = new List<Vector3>();
|
||||
List<Vector2> uv = new List<Vector2>();
|
||||
List<int> triangles = new List<int>();
|
||||
//三角形合并
|
||||
for (int i = 0; i < polygons.Count; i++) {
|
||||
triangles.Add(AddIndexOf(vertices, polygons[i].a));
|
||||
triangles.Add(AddIndexOf(vertices, polygons[i].b));
|
||||
triangles.Add(AddIndexOf(vertices, polygons[i].c));
|
||||
}
|
||||
Debug.Log(vertices.Count);
|
||||
//展开uv (顶点去掉z坐标就是未缩放的平面UV)
|
||||
for (int i = 0; i < vertices.Count; i++) { uv.Add(vertices[i]); }
|
||||
//附加数据
|
||||
data.polygon = new Mesh();
|
||||
data.polygon.vertices = vertices.ToArray();
|
||||
data.polygon.uv = uv.ToArray();
|
||||
data.polygon.triangles = triangles.ToArray();
|
||||
data.polygon.RecalculateBounds();
|
||||
data.polygon.RecalculateNormals();
|
||||
}
|
||||
//顶点列表不包含则添加点,获得索引
|
||||
private int AddIndexOf(List<Vector3> vertices, Vector3 a) {
|
||||
if (!vertices.Contains(a)) { vertices.Add(a); }
|
||||
return vertices.IndexOf(a);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e215bacbb6d0216408afb679ae863360
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,35 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// 散列点生成多边形算法
|
||||
/// </summary>
|
||||
public class AlgorithmPolygon : ModuleAlgorithm<DataPlate> {
|
||||
private ModuleAlgorithmFunction<DataPolygon> EdgePoint = new AFEdgePoint();
|
||||
private ModuleAlgorithmFunction<DataPolygon> Cutting = new AFAuriculareCutting();
|
||||
private ModuleAlgorithmFunction<DataPolygon> Subdivision = new AFSubdivision();
|
||||
private ModuleAlgorithmFunction<DataPolygon> TriangleMesh = new AFTriangleMesh();
|
||||
|
||||
protected override void Awake() => ModuleCore.AlgorithmPolygon = this;
|
||||
|
||||
public override void Compute(DataPlate data) {
|
||||
DataPolygon polygon = new DataPolygon(data);
|
||||
//计算边缘点
|
||||
EdgePoint.Compute(polygon);
|
||||
//切割三角形
|
||||
Cutting.Compute(polygon);
|
||||
//合并三角形
|
||||
Subdivision.Compute(polygon);
|
||||
Subdivision.Compute(polygon);
|
||||
Subdivision.Compute(polygon);
|
||||
Subdivision.Compute(polygon);
|
||||
Subdivision.Compute(polygon);
|
||||
Subdivision.Compute(polygon);
|
||||
Subdivision.Compute(polygon);
|
||||
Subdivision.Compute(polygon);
|
||||
Subdivision.Compute(polygon);
|
||||
//三角形转换网格
|
||||
TriangleMesh.Compute(polygon);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ad1a08fdeb67d3048a88c3668e3b6764
|
||||
guid: ef8ce839dfa79ff4d825f55925c48e7c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user