SCGridLayoutGroup.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485
  1. 
  2. using UnityEngine;
  3. using UnityEditor;
  4. using Unity.Collections;
  5. namespace SC.XR.Unity
  6. {
  7. [ExecuteAlways]//Script will run in any circumstance
  8. public class SCGridLayoutGroup : SCBaseLayoutGroup
  9. {
  10. /// <summary>
  11. /// The layout of the set of type
  12. /// </summary>
  13. [SerializeField]
  14. private LayoutTypes layoutType = LayoutTypes.Horizontal;
  15. public LayoutTypes LayoutType
  16. {
  17. get { return layoutType; }
  18. set { layoutType = value; }
  19. }
  20. /// <summary>
  21. /// Less than a row when the child object alignment
  22. /// </summary>
  23. [SerializeField]
  24. private GroupHorizontalAlignment groupHorizontalAlign = GroupHorizontalAlignment.Left;
  25. public GroupHorizontalAlignment GroupHorizontalAlign
  26. {
  27. get { return groupHorizontalAlign; }
  28. set { groupHorizontalAlign = value; }
  29. }
  30. /// <summary>
  31. /// Less than a column when the child object alignment
  32. /// </summary>
  33. [SerializeField]
  34. private GroupVerticalAlignment groupVerticalAlign = GroupVerticalAlignment.Top;
  35. public GroupVerticalAlignment GroupVerticalAlign
  36. {
  37. get { return groupVerticalAlign; }
  38. set { groupVerticalAlign = value; }
  39. }
  40. /// <summary>
  41. /// The child object types of formation
  42. /// </summary>
  43. [SerializeField]
  44. private GroupArrayTypes groupArrayType =
  45. GroupArrayTypes.Plane;
  46. public GroupArrayTypes GroupArrayType
  47. {
  48. get { return groupArrayType; }
  49. set { groupArrayType = value; }
  50. }
  51. /// <summary>
  52. /// The position of the group anchor point relative to the base class
  53. /// </summary>
  54. [SerializeField]
  55. private AnchorRelativeBase anchorLayout = AnchorRelativeBase.MiddleCenter;
  56. public AnchorRelativeBase AnchorLayout
  57. {
  58. get { return anchorLayout; }
  59. set { anchorLayout = value; }
  60. }
  61. /// <summary>
  62. /// The child object oriented
  63. /// </summary>
  64. [SerializeField]
  65. private ObjFacingTypes facingType = ObjFacingTypes.None;
  66. public ObjFacingTypes FacingType
  67. {
  68. get { return facingType; }
  69. set { facingType = value; }
  70. }
  71. /// <summary>
  72. /// The number of columns
  73. /// </summary>
  74. [SerializeField]
  75. private int columns = 2;
  76. public int Columns
  77. {
  78. get { return columns; }
  79. set
  80. {
  81. if (LayoutType == LayoutTypes.Vertical)
  82. {
  83. return;
  84. }
  85. columns = value;
  86. }
  87. }
  88. /// <summary>
  89. /// The number of rows
  90. /// </summary>
  91. [SerializeField]
  92. private int rows = 2;
  93. public int Rows
  94. {
  95. get { return rows; }
  96. set
  97. {
  98. if (LayoutType == LayoutTypes.Horizontal)
  99. {
  100. return;
  101. }
  102. rows = value;
  103. }
  104. }
  105. /// <summary>
  106. /// Horizontal spacing
  107. /// </summary>
  108. [SerializeField]
  109. private float spaceX = 2f;
  110. public float SpaceX
  111. {
  112. get { return spaceX; }
  113. set { spaceX = value; }
  114. }
  115. /// <summary>
  116. /// The vertical spacing
  117. /// </summary>
  118. [SerializeField]
  119. private float spaceY = 2f;
  120. public float SpaceY
  121. {
  122. get { return spaceY; }
  123. set { spaceY = value; }
  124. }
  125. [SerializeField]
  126. [Range(-100f, 100f)]
  127. private float childOffsetX = 0f;
  128. public float ChildOffsetX
  129. {
  130. get { return childOffsetX; }
  131. set { childOffsetX = value; }
  132. }
  133. [SerializeField]
  134. [Range(-100f, 100f)]
  135. private float childOffsetY = 0f;
  136. public float ChildOffsetY
  137. {
  138. get { return childOffsetY; }
  139. set { childOffsetY = value; }
  140. }
  141. /// <summary>
  142. /// The location of the child object Z axis relative to the base class
  143. /// </summary>
  144. [SerializeField]
  145. [Range(-100f, 100f)]
  146. private float childOffsetZ = 0f;
  147. public float ChildOffsetZ
  148. {
  149. get { return childOffsetZ; }
  150. set { childOffsetZ = value; }
  151. }
  152. /// <summary>
  153. /// The radius
  154. /// </summary>
  155. [SerializeField]
  156. [Range(0.05f, 200)]
  157. private float radius = 2f;
  158. public float Radius
  159. {
  160. get { return radius; }
  161. set { radius = value; }
  162. }
  163. /// <summary>
  164. /// Radiation Angle
  165. /// </summary>
  166. [SerializeField]
  167. [Range(5f, 360f)]
  168. private float radialRange = 180f;
  169. public float RadialRange
  170. {
  171. get { return radialRange; }
  172. set { radialRange = value; }
  173. }
  174. /// <summary>
  175. /// If the anchor point with the shaft alignment
  176. /// </summary>
  177. [SerializeField]
  178. private bool isAnchorWithAxis = false;
  179. public bool IsAnchorWithAxis
  180. {
  181. get { return isAnchorWithAxis; }
  182. set { isAnchorWithAxis = value; }
  183. }
  184. private GroupObj tempobj;
  185. private Vector3[] childPos;
  186. private Vector3 newPos;
  187. private int objCount;
  188. private int rowMax;
  189. private int colMax;
  190. private float acnhoroffsetX;
  191. private float anchoroffsetY;
  192. private float shortOffsetX;
  193. private float shortOffsetY;
  194. private void Init()//The initialization value
  195. {
  196. childPos = new Vector3[ObjList.Count];
  197. newPos = Vector3.zero;
  198. objCount = 0;
  199. rowMax = 0;
  200. colMax = 0;
  201. acnhoroffsetX = 0;
  202. anchoroffsetY = 0;
  203. shortOffsetX = 0;
  204. shortOffsetY = 0;
  205. }
  206. protected override void LayoutChildren()
  207. {
  208. Init();
  209. SetObjPos();
  210. ArrayType();
  211. }
  212. private void Update()
  213. {
  214. }
  215. private void SetObjPos()//The location of the object
  216. {
  217. switch (LayoutType)
  218. {
  219. case LayoutTypes.Horizontal:
  220. colMax = Columns;
  221. rowMax = Mathf.CeilToInt((float)ObjList.Count / Columns);
  222. break;
  223. case LayoutTypes.Vertical:
  224. rowMax = Rows;
  225. colMax = Mathf.CeilToInt((float)ObjList.Count / Rows);
  226. break;
  227. }
  228. acnhoroffsetX = (colMax * 0.5f * SpaceX);
  229. if (AnchorLayout == AnchorRelativeBase.LowerLeft || AnchorLayout == AnchorRelativeBase.UpperLeft || AnchorLayout == AnchorRelativeBase.MiddleLeft)
  230. {
  231. acnhoroffsetX = IsAnchorWithAxis ? 0.5f * SpaceX : 0;
  232. }
  233. else if (AnchorLayout == AnchorRelativeBase.LowerRight || AnchorLayout == AnchorRelativeBase.UpperRight || AnchorLayout == AnchorRelativeBase.MiddleRight)
  234. {
  235. acnhoroffsetX = IsAnchorWithAxis ? (colMax - 0.5f) * SpaceX : colMax * SpaceX;
  236. }
  237. anchoroffsetY = (rowMax * 0.5f * SpaceY);
  238. if (AnchorLayout == AnchorRelativeBase.UpperLeft || AnchorLayout == AnchorRelativeBase.UpperCenter || AnchorLayout == AnchorRelativeBase.UpperRight)
  239. {
  240. anchoroffsetY = IsAnchorWithAxis ? 0.5f * SpaceY : 0;
  241. }
  242. else if (AnchorLayout == AnchorRelativeBase.LowerLeft || AnchorLayout == AnchorRelativeBase.LowerCenter || AnchorLayout == AnchorRelativeBase.LowerRight)
  243. {
  244. anchoroffsetY = IsAnchorWithAxis ? (rowMax - 0.5f) * SpaceY : rowMax * SpaceY;
  245. }
  246. if (LayoutType == LayoutTypes.Horizontal)
  247. {
  248. for (int i = 0; i < rowMax; i++)
  249. {
  250. for (int j = 0; j < colMax; j++)
  251. {
  252. if (i == rowMax - 1)
  253. {
  254. if (GroupHorizontalAlign == GroupHorizontalAlignment.Left)
  255. {
  256. shortOffsetX = 0;
  257. }
  258. else if (GroupHorizontalAlign == GroupHorizontalAlignment.Center)
  259. {
  260. shortOffsetX = SpaceX * ((colMax - (ObjList.Count % colMax)) % colMax) * 0.5f;
  261. }
  262. else if (GroupHorizontalAlign == GroupHorizontalAlignment.Right)
  263. {
  264. shortOffsetX = SpaceX * ((colMax - (ObjList.Count % colMax)) % colMax);
  265. }
  266. }
  267. if (objCount < ObjList.Count)
  268. {
  269. childPos[objCount].Set(0.5f * SpaceX * (1 + 2 * j) - acnhoroffsetX + shortOffsetX + ChildOffsetX, (0.5f * SpaceY * (-1 - 2 * i)) + anchoroffsetY + shortOffsetY + ChildOffsetY, 0.0f);
  270. }
  271. objCount++;
  272. }
  273. }
  274. }
  275. else
  276. {
  277. for (int i = 0; i < colMax; i++)
  278. {
  279. for (int j = 0; j < rowMax; j++)
  280. {
  281. if (i == colMax - 1)
  282. {
  283. if (GroupVerticalAlign == GroupVerticalAlignment.Top)
  284. {
  285. shortOffsetY = 0;
  286. }
  287. else if (GroupVerticalAlign == GroupVerticalAlignment.Middle)
  288. {
  289. shortOffsetY = -SpaceY * ((rowMax - (ObjList.Count % rowMax)) % rowMax) * 0.5f;
  290. }
  291. else if (GroupVerticalAlign == GroupVerticalAlignment.Bottom)
  292. {
  293. shortOffsetY = -SpaceY * ((rowMax - (ObjList.Count % rowMax)) % rowMax);
  294. }
  295. }
  296. if (objCount < ObjList.Count)
  297. {
  298. childPos[objCount].Set(0.5f * SpaceX * (1 + 2 * i) - acnhoroffsetX + shortOffsetX + ChildOffsetX, (0.5f * SpaceY * (-1 - 2 * j)) + anchoroffsetY + shortOffsetY + childOffsetY, 0.0f);
  299. }
  300. objCount++;
  301. }
  302. }
  303. }
  304. }
  305. private void ArrayType()//Give the child object position
  306. {
  307. switch (GroupArrayType)
  308. {
  309. case GroupArrayTypes.Plane:
  310. for (int i = 0; i < ObjList.Count; i++)
  311. {
  312. tempobj = ObjList[i];
  313. newPos = childPos[i];
  314. newPos.z = ChildOffsetZ;
  315. tempobj.Transform.localPosition = newPos;
  316. ObjFacing(tempobj);
  317. ObjList[i] = tempobj;
  318. }
  319. break;
  320. case GroupArrayTypes.Cylinder:
  321. for (int i = 0; i < ObjList.Count; i++)
  322. {
  323. tempobj = ObjList[i];
  324. newPos = CylinderArray(childPos[i], radius);
  325. tempobj.Transform.localPosition = newPos;
  326. ObjFacing(tempobj);
  327. ObjList[i] = tempobj;
  328. }
  329. break;
  330. case GroupArrayTypes.Radial:
  331. int tempColumn = 0;
  332. int tempRow = 1;
  333. for (int i = 0; i < ObjList.Count; i++)
  334. {
  335. tempobj = ObjList[i];
  336. newPos = RadialArray(childPos[i], radius, radialRange, tempRow, rowMax, tempColumn, colMax);
  337. if (tempColumn == columns - 1)
  338. {
  339. tempColumn = 0;
  340. tempRow++;
  341. }
  342. else
  343. {
  344. tempColumn++;
  345. }
  346. tempobj.Transform.localPosition = newPos;
  347. ObjFacing(tempobj);
  348. ObjList[i] = tempobj;
  349. }
  350. break;
  351. case GroupArrayTypes.Sphere:
  352. for (int i = 0; i < ObjList.Count; i++)
  353. {
  354. tempobj = ObjList[i];
  355. newPos = SphereArray(childPos[i], radius);
  356. tempobj.Transform.localPosition = newPos;
  357. ObjFacing(tempobj);
  358. ObjList[i] = tempobj;
  359. }
  360. break;
  361. case GroupArrayTypes.Round:
  362. for (int i = 0; i < ObjList.Count; i++)
  363. {
  364. tempobj = ObjList[i];
  365. newPos = RoundArray(childPos[i], radius, i + 1, ObjList.Count);
  366. newPos.Set(newPos.x + ChildOffsetX, newPos.y + ChildOffsetY, newPos.z + ChildOffsetZ);
  367. tempobj.Transform.localPosition = newPos;
  368. ObjFacing(tempobj);
  369. ObjList[i] = tempobj;
  370. }
  371. break;
  372. }
  373. }
  374. private Vector3 CylinderArray(Vector3 objPos, float radius)
  375. {
  376. float circ = 2.0f * Mathf.PI * radius;
  377. float xAngle = (objPos.x / circ) * 360f;
  378. objPos.Set(0.0f, objPos.y, radius);
  379. Quaternion rot = Quaternion.Euler(0.0f, xAngle, 0.0f);
  380. objPos = rot * objPos;
  381. return objPos;
  382. }
  383. private Vector3 SphereArray(Vector3 objPos, float radius)
  384. {
  385. float circ = 2.0f * Mathf.PI * radius;
  386. float XAngle = (objPos.x / circ) * 360f;
  387. float YAngle = -(objPos.y / circ) * 360f;
  388. objPos.Set(0.0f, 0.0f, radius);
  389. Quaternion rot = Quaternion.Euler(YAngle, XAngle, 0.0f);
  390. objPos = rot * objPos;
  391. return objPos;
  392. }
  393. private Vector3 RadialArray(Vector3 objPos, float radius, float radialRange, int row, int rowMax, int column, int colMax)
  394. {
  395. float radialSpaceAngle = radialRange / colMax;
  396. objPos.Set(0.0f, 0.0f, (radius / rowMax) * row);
  397. float YAngle = radialSpaceAngle * (column - (colMax * 0.5f)) + (radialSpaceAngle * .5f);
  398. Quaternion rot = Quaternion.Euler(0.0f, YAngle, 0.0f);
  399. objPos = rot * objPos;
  400. return objPos;
  401. }
  402. private Vector3 RoundArray(Vector3 objPos, float radius, int i, int totalCount)
  403. {
  404. float angle = (360f * i) / totalCount;
  405. float x = radius * Mathf.Cos(angle * Mathf.PI / 180f);
  406. float y = radius * Mathf.Sin(angle * Mathf.PI / 180f);
  407. objPos.Set(x, 0, y);
  408. return objPos;
  409. }
  410. private void ObjFacing(GroupObj obj)//The child object toward
  411. {
  412. Vector3 centerPos;
  413. Vector3 FacingNode;
  414. switch (FacingType)
  415. {
  416. case ObjFacingTypes.None:
  417. obj.Transform.transform.localEulerAngles = Vector3.zero;
  418. break;
  419. case ObjFacingTypes.FaceOrigin:
  420. obj.Transform.rotation = Quaternion.LookRotation(obj.Transform.position - transform.position, transform.up);
  421. break;
  422. case ObjFacingTypes.FaceOriginReversed:
  423. obj.Transform.rotation = Quaternion.LookRotation(transform.position - obj.Transform.position, transform.up);
  424. break;
  425. case ObjFacingTypes.FaceCenterAxis:
  426. centerPos = Vector3.Project(obj.Transform.position - transform.position, transform.up);//Returns a vector projection on the specified axis
  427. FacingNode = transform.position + centerPos;
  428. obj.Transform.rotation = Quaternion.LookRotation(obj.Transform.position - FacingNode, transform.up);
  429. break;
  430. case ObjFacingTypes.FaceCenterAxisReversed:
  431. centerPos = Vector3.Project(obj.Transform.position - transform.position, transform.up);//Returns a vector projection on the specified axis
  432. FacingNode = transform.position + centerPos;
  433. obj.Transform.rotation = Quaternion.LookRotation(FacingNode - obj.Transform.position, transform.up);
  434. break;
  435. case ObjFacingTypes.FaceParentDown:
  436. obj.Transform.forward = transform.rotation * Vector3.down;
  437. break;
  438. case ObjFacingTypes.FaceParentUp:
  439. obj.Transform.forward = transform.rotation * Vector3.up;
  440. break;
  441. case ObjFacingTypes.FaceParentFoward:
  442. obj.Transform.forward = transform.rotation * Vector3.forward;
  443. break;
  444. case ObjFacingTypes.FaceParentBack:
  445. obj.Transform.forward = transform.rotation * Vector3.back;
  446. break;
  447. }
  448. }
  449. private void setNull()
  450. {
  451. tempobj = null;
  452. childPos = null;
  453. }
  454. private void OnDestroy()
  455. {
  456. setNull();
  457. }
  458. }
  459. }