|  |  |  |  | using System; | 
					
						
							|  |  |  |  | using System.Collections.Generic; | 
					
						
							|  |  |  |  | using UnityEngine; | 
					
						
							|  |  |  |  | using UnityEngine.Serialization; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | namespace Game | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |     public enum EShapeType | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |         Dot, | 
					
						
							|  |  |  |  |         Circle, | 
					
						
							|  |  |  |  |         Sector, | 
					
						
							|  |  |  |  |         Box, | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     public class Shape | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |         public EShapeType Type; | 
					
						
							|  |  |  |  |         public Vector3 Offset; | 
					
						
							|  |  |  |  |         public float Height; | 
					
						
							|  |  |  |  |         public float SizeX; | 
					
						
							|  |  |  |  |         public float SizeY; | 
					
						
							|  |  |  |  |         public float Radius; | 
					
						
							|  |  |  |  |         public float Angle; | 
					
						
							|  |  |  |  |         private List<Vector3> vertices = new List<Vector3>(); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         public static Shape NewDot(Vector3 offset) | 
					
						
							|  |  |  |  |         { | 
					
						
							|  |  |  |  |             var shape = new Shape | 
					
						
							|  |  |  |  |             { | 
					
						
							|  |  |  |  |                 Type = EShapeType.Dot, | 
					
						
							|  |  |  |  |                 Offset = offset, | 
					
						
							|  |  |  |  |             }; | 
					
						
							|  |  |  |  |             return shape; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         public static Shape NewCircle(Vector3 offset, float height, float radius) | 
					
						
							|  |  |  |  |         { | 
					
						
							|  |  |  |  |             var shape = new Shape | 
					
						
							|  |  |  |  |             { | 
					
						
							|  |  |  |  |                 Type = EShapeType.Circle, | 
					
						
							|  |  |  |  |                 Offset = offset, | 
					
						
							|  |  |  |  |                 Height = height, | 
					
						
							|  |  |  |  |                 Radius = radius | 
					
						
							|  |  |  |  |             }; | 
					
						
							|  |  |  |  |             return shape; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         public static Shape NewSector(Vector3 offset, float height, float radius, float angle) | 
					
						
							|  |  |  |  |         { | 
					
						
							|  |  |  |  |             var shape = new Shape | 
					
						
							|  |  |  |  |             { | 
					
						
							|  |  |  |  |                 Type = EShapeType.Sector, | 
					
						
							|  |  |  |  |                 Offset = offset, | 
					
						
							|  |  |  |  |                 Height = height, | 
					
						
							|  |  |  |  |                 Radius = radius, | 
					
						
							|  |  |  |  |                 Angle = angle | 
					
						
							|  |  |  |  |             }; | 
					
						
							|  |  |  |  |             return shape; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         public static Shape NewBox(Vector3 offset, float height, float sizeX, float sizeY) | 
					
						
							|  |  |  |  |         { | 
					
						
							|  |  |  |  |             var shape = new Shape | 
					
						
							|  |  |  |  |             { | 
					
						
							|  |  |  |  |                 Type = EShapeType.Box, | 
					
						
							|  |  |  |  |                 Offset = offset, | 
					
						
							|  |  |  |  |                 Height = height, | 
					
						
							|  |  |  |  |                 SizeX = sizeX, | 
					
						
							|  |  |  |  |                 SizeY = sizeY | 
					
						
							|  |  |  |  |             }; | 
					
						
							|  |  |  |  |             return shape; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         public Vector4 GetAABB(Vector3 direction) | 
					
						
							|  |  |  |  |         { | 
					
						
							|  |  |  |  |             var aabb = Vector4.zero; | 
					
						
							|  |  |  |  |             switch (Type) | 
					
						
							|  |  |  |  |             { | 
					
						
							|  |  |  |  |                 case EShapeType.Circle: | 
					
						
							|  |  |  |  |                 case EShapeType.Sector: | 
					
						
							|  |  |  |  |                     aabb = new Vector4(-Radius, Radius, -Radius, Radius); | 
					
						
							|  |  |  |  |                     break; | 
					
						
							|  |  |  |  |                 case EShapeType.Box: | 
					
						
							|  |  |  |  |                     ForeachVertices(direction, (vertex) => | 
					
						
							|  |  |  |  |                     { | 
					
						
							|  |  |  |  |                         if (vertex.x < aabb.x) aabb.x = vertex.x; | 
					
						
							|  |  |  |  |                         if (vertex.x > aabb.y) aabb.y = vertex.x; | 
					
						
							|  |  |  |  |                         if (vertex.z < aabb.z) aabb.z = vertex.z; | 
					
						
							|  |  |  |  |                         if (vertex.z > aabb.w) aabb.w = vertex.z; | 
					
						
							|  |  |  |  |                     }); | 
					
						
							|  |  |  |  |                     break; | 
					
						
							|  |  |  |  |             } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |             return aabb; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         private void SetVertices(Vector3 direction) | 
					
						
							|  |  |  |  |         { | 
					
						
							|  |  |  |  |             vertices.Clear(); | 
					
						
							|  |  |  |  |             switch (Type) | 
					
						
							|  |  |  |  |             { | 
					
						
							|  |  |  |  |                 case EShapeType.Circle: | 
					
						
							|  |  |  |  |                     for (var i = 0; i < 360; i += 15) | 
					
						
							|  |  |  |  |                     { | 
					
						
							|  |  |  |  |                         var angle = i * Mathf.Deg2Rad; | 
					
						
							|  |  |  |  |                         var x = Mathf.Cos(angle) * Radius; | 
					
						
							|  |  |  |  |                         var z = Mathf.Sin(angle) * Radius; | 
					
						
							|  |  |  |  |                         vertices.Add(new Vector3(x, 0, z)); | 
					
						
							|  |  |  |  |                     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |                     break; | 
					
						
							|  |  |  |  |                 case EShapeType.Sector: | 
					
						
							|  |  |  |  |                     var rotAdd = Util.Vec3ToRot(direction); | 
					
						
							|  |  |  |  |                     vertices.Add(Vector3.zero); | 
					
						
							|  |  |  |  |                     var vertNum = Angle > 15 ? (int)(Angle / 15) : 1; | 
					
						
							|  |  |  |  |                     var anglePerVertex = Angle / vertNum; | 
					
						
							|  |  |  |  |                     for (var i = 0; i <= vertNum; i++) | 
					
						
							|  |  |  |  |                     { | 
					
						
							|  |  |  |  |                         var angle = (i * anglePerVertex + rotAdd - Angle / 2) * Mathf.Deg2Rad; | 
					
						
							|  |  |  |  |                         var x = Mathf.Cos(angle) * Radius; | 
					
						
							|  |  |  |  |                         var z = Mathf.Sin(angle) * Radius; | 
					
						
							|  |  |  |  |                         vertices.Add(new Vector3(x, 0, z)); | 
					
						
							|  |  |  |  |                     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |                     break; | 
					
						
							|  |  |  |  |                 case EShapeType.Box: | 
					
						
							|  |  |  |  |                     var (halfX, halfY) = (SizeX / 2, SizeY / 2); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |                     var up = new Vector3(direction.z, 0, -direction.x); | 
					
						
							|  |  |  |  |                     var right = new Vector3(direction.x, 0, direction.z); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |                     var topLeft = right * halfX - up * halfY; | 
					
						
							|  |  |  |  |                     var topRight = right * halfX + up * halfY; | 
					
						
							|  |  |  |  |                     var bottomLeft = -right * halfX - up * halfY; | 
					
						
							|  |  |  |  |                     var bottomRight = -right * halfX + up * halfY; | 
					
						
							|  |  |  |  |                     vertices.Add(topLeft); | 
					
						
							|  |  |  |  |                     vertices.Add(topRight); | 
					
						
							|  |  |  |  |                     vertices.Add(bottomRight); | 
					
						
							|  |  |  |  |                     vertices.Add(bottomLeft); | 
					
						
							|  |  |  |  |                     break; | 
					
						
							|  |  |  |  |             } | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         public void ForeachVertices(Vector3 direction, Action<Vector3> action) | 
					
						
							|  |  |  |  |         { | 
					
						
							|  |  |  |  |             SetVertices(direction); | 
					
						
							|  |  |  |  |             foreach (var item in vertices) | 
					
						
							|  |  |  |  |             { | 
					
						
							|  |  |  |  |                 action(item); | 
					
						
							|  |  |  |  |             } | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         public void ForeachVerticesPair(Vector3 direction, Action<Vector3, Vector3> action) | 
					
						
							|  |  |  |  |         { | 
					
						
							|  |  |  |  |             SetVertices(direction); | 
					
						
							|  |  |  |  |             for (var i = 0; i < vertices.Count; i++) | 
					
						
							|  |  |  |  |             { | 
					
						
							|  |  |  |  |                 var next = i + 1; | 
					
						
							|  |  |  |  |                 if (next >= vertices.Count) next = 0; | 
					
						
							|  |  |  |  |                 action(vertices[i], vertices[next]); | 
					
						
							|  |  |  |  |             } | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | } |