Grid.cs 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using UnityEngine;
  5. using Utils = KairoEngine.Utility.Utilities;
  6. using TMPro;
  7. namespace KairoEngine.Grids
  8. {
  9. public enum GridPlane
  10. {
  11. XY,
  12. XZ,
  13. YZ
  14. }
  15. public class Grid<TGridObject>
  16. {
  17. private int width;
  18. private int height;
  19. private float cellSize;
  20. private Vector3 originPosition;
  21. private bool debug = false;
  22. private GridPlane plane = GridPlane.XY;
  23. private TGridObject[,] gridArray;
  24. private TextMesh[,] debugTextArray;
  25. public event EventHandler<OnGridObjectChangedEventArgs> OnGridObjectChanged;
  26. public class OnGridObjectChangedEventArgs : EventArgs
  27. {
  28. public int x;
  29. public int y;
  30. }
  31. public Grid(int width, int height, float cellSize, Vector3 originPosition, Func<Grid<TGridObject>, int, int, TGridObject> createGridObject,
  32. GridPlane plane = GridPlane.XY, bool debug = false)
  33. {
  34. this.width = width;
  35. this.height = height;
  36. this.cellSize = cellSize;
  37. this.originPosition = originPosition;
  38. this.gridArray = new TGridObject[width, height];
  39. this.debug = debug;
  40. this.plane = plane;
  41. for (int x = 0; x < gridArray.GetLength(0); x++)
  42. {
  43. for (int y = 0; y < gridArray.GetLength(1); y++)
  44. {
  45. gridArray[x, y] = createGridObject(this, x, y);
  46. }
  47. }
  48. UpdateDebugView();
  49. }
  50. public int GetWidth() => width;
  51. public int GetHeight() => height;
  52. public float GetCellSize() => cellSize;
  53. public Vector3 GetWorldPosition(int x, int y)
  54. {
  55. switch(plane)
  56. {
  57. case GridPlane.XY:
  58. return new Vector3(x, y, 0) * cellSize + originPosition;
  59. case GridPlane.XZ:
  60. return new Vector3(x, 0, y) * cellSize + originPosition;
  61. case GridPlane.YZ:
  62. return new Vector3(0, x, y) * cellSize + originPosition;
  63. default:
  64. return new Vector3();
  65. }
  66. }
  67. public void GetGridPosition(Vector3 worldPosition, out int x, out int y)
  68. {
  69. x = 0;
  70. y = 0;
  71. switch(plane)
  72. {
  73. case GridPlane.XY:
  74. x = Mathf.FloorToInt((worldPosition - originPosition).x/ cellSize);
  75. y = Mathf.FloorToInt((worldPosition - originPosition).y / cellSize);
  76. break;
  77. case GridPlane.XZ:
  78. x = Mathf.FloorToInt((worldPosition - originPosition).x/ cellSize);
  79. y = Mathf.FloorToInt((worldPosition - originPosition).z / cellSize);
  80. break;
  81. case GridPlane.YZ:
  82. x = Mathf.FloorToInt((worldPosition - originPosition).y/ cellSize);
  83. y = Mathf.FloorToInt((worldPosition - originPosition).z / cellSize);
  84. break;
  85. default:
  86. break;
  87. }
  88. }
  89. public bool IsPositionInsideGrid(Vector2Int gridPosition)
  90. {
  91. if(gridPosition.x < 0) return false;
  92. if(gridPosition.x > width - 1) return false;
  93. if(gridPosition.y < 0) return false;
  94. if(gridPosition.y > height - 1) return false;
  95. return true;
  96. }
  97. public bool IsPositionInsideGrid(Vector3 worldPosition)
  98. {
  99. float maxWidth, maxHeight;
  100. switch(plane)
  101. {
  102. case GridPlane.XY:
  103. maxWidth = originPosition.x + (cellSize * width);
  104. maxHeight = originPosition.y + (cellSize * height);
  105. if(worldPosition.x > maxWidth) return false;
  106. if(worldPosition.x < originPosition.x) return false;
  107. if(worldPosition.y > maxHeight) return false;
  108. if(worldPosition.y < originPosition.y) return false;
  109. break;
  110. case GridPlane.XZ:
  111. maxWidth = originPosition.x + (cellSize * width);
  112. maxHeight = originPosition.z + (cellSize * height);
  113. if(worldPosition.x > maxWidth) return false;
  114. if(worldPosition.x < originPosition.x) return false;
  115. if(worldPosition.z > maxHeight) return false;
  116. if(worldPosition.z < originPosition.z) return false;
  117. break;
  118. case GridPlane.YZ:
  119. maxWidth = originPosition.y + (cellSize * width);
  120. maxHeight = originPosition.z + (cellSize * height);
  121. if(worldPosition.y > maxWidth) return false;
  122. if(worldPosition.y < originPosition.y) return false;
  123. if(worldPosition.z > maxHeight) return false;
  124. if(worldPosition.z < originPosition.z) return false;
  125. break;
  126. default:
  127. break;
  128. }
  129. return true;
  130. }
  131. public void SetObject(int x, int y, TGridObject value)
  132. {
  133. if(x >= 0 && y >= 0 && x < width && y < height)
  134. {
  135. gridArray[x, y] = value;
  136. if(debug) debugTextArray[x, y].text = gridArray[x, y].ToString();
  137. TriggerGridObjectChanged(x, y);
  138. }
  139. }
  140. public void SetObject(Vector3 worldPosition, TGridObject value)
  141. {
  142. int x, y;
  143. GetGridPosition(worldPosition, out x, out y);
  144. SetObject(x, y, value);
  145. }
  146. public TGridObject GetObject(int x, int y)
  147. {
  148. if(x >= 0 && y >= 0 && x < width && y < height)
  149. {
  150. return gridArray[x, y];
  151. }
  152. else return default(TGridObject);
  153. }
  154. public TGridObject GetObject(Vector3 worldPosition)
  155. {
  156. int x, y;
  157. GetGridPosition(worldPosition, out x, out y);
  158. return GetObject(x, y);
  159. }
  160. public Vector3 GetQuadSize()
  161. {
  162. switch(plane)
  163. {
  164. case GridPlane.XY:
  165. return new Vector3(1, 1, 0) * GetCellSize();
  166. case GridPlane.XZ:
  167. return new Vector3(1, 0, 1) * GetCellSize();
  168. case GridPlane.YZ:
  169. return new Vector3(0, 1, 1) * GetCellSize();
  170. default:
  171. return new Vector3(0, 0, 0);
  172. }
  173. }
  174. public GridPlane GetGridPlane() => plane;
  175. public void TriggerGridObjectChanged(int x, int y)
  176. {
  177. if(OnGridObjectChanged != null) OnGridObjectChanged(this, new OnGridObjectChangedEventArgs {x = x, y = y});
  178. UpdateDebugView();
  179. }
  180. private void UpdateDebugView()
  181. {
  182. DestroyDebugText();
  183. if(debug)
  184. {
  185. this.debugTextArray = new TextMesh[width, height];
  186. for (int x = 0; x < gridArray.GetLength(0); x++)
  187. {
  188. for (int y = 0; y < gridArray.GetLength(1); y++)
  189. {
  190. debugTextArray[x, y] = Utils.CreateWorldText(gridArray[x,y]?.ToString(), null, GetWorldPosition(x, y) + GetQuadSize() * .5f,
  191. 12, Color.white, TextAnchor.MiddleCenter);
  192. Debug.DrawLine(GetWorldPosition(x, y), GetWorldPosition(x, y + 1), Color.white, 100f);
  193. Debug.DrawLine(GetWorldPosition(x, y), GetWorldPosition(x + 1, y), Color.white, 100f);
  194. }
  195. }
  196. Debug.DrawLine(GetWorldPosition(0, height), GetWorldPosition(width, height), Color.white, 100f);
  197. Debug.DrawLine(GetWorldPosition(width, 0), GetWorldPosition(width, height), Color.white, 100f);
  198. }
  199. }
  200. private void DestroyDebugText()
  201. {
  202. if(this.debugTextArray != null)
  203. {
  204. for (int x = 0; x < this.debugTextArray.GetLength(0); x++)
  205. {
  206. for (int y = 0; y < this.debugTextArray.GetLength(1); y++)
  207. {
  208. GameObject.Destroy(debugTextArray[x,y].gameObject);
  209. }
  210. }
  211. }
  212. }
  213. }
  214. }