You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

248 lines
7.4 KiB

5 years ago
5 years ago
  1. using System.Collections.Generic;
  2. using UnityEngine;
  3. using TMPro;
  4. using UnityEngine.UI;
  5. public class LogicTrayUI : LogicElementHolder
  6. {
  7. [SerializeField]
  8. protected LogicElementUI Prefab;
  9. [SerializeField]
  10. protected int insertIndex = -1;
  11. [SerializeField]
  12. private Transform content;
  13. [SerializeField]
  14. private GameObject playButton;
  15. [SerializeField]
  16. private GameObject returnButton;
  17. [SerializeField]
  18. private Image border;
  19. [SerializeField]
  20. private int maxLength = 6;
  21. [SerializeField]
  22. public BlockReader reader;
  23. [SerializeField]
  24. private List<QueueData> readerQueue = new List<QueueData>();
  25. #region Unity Functions
  26. public void Start()
  27. {
  28. readerQueue.Add(new QueueData(reader, border.color));
  29. UpdateDisplay();
  30. }
  31. protected override void OnEnable()
  32. {
  33. base.OnEnable();
  34. if (reader != null)
  35. reader.OnUpdate += UpdateDisplay;
  36. }
  37. protected override void OnDisable()
  38. {
  39. base.OnDisable();
  40. if (reader != null)
  41. reader.OnUpdate -= UpdateDisplay;
  42. }
  43. #endregion Unity Functions
  44. public void SetBlockReader(BlockReader newBlockReader)
  45. {
  46. if (reader != null)
  47. reader.OnUpdate -= UpdateDisplay;
  48. reader = newBlockReader;
  49. reader.OnUpdate += UpdateDisplay;
  50. UpdateDisplay();
  51. }
  52. public void OnClick_Return()
  53. {
  54. if (readerQueue.Count <= 1)
  55. return;
  56. QueueData lastData = readerQueue[readerQueue.Count - 1];
  57. readerQueue.RemoveAt(readerQueue.Count - 1);
  58. border.color = readerQueue[readerQueue.Count - 1].color;
  59. SetBlockReader(readerQueue[readerQueue.Count - 1].reader);
  60. UpdateDisplay();
  61. }
  62. [ContextMenu("Update Display")]
  63. public void UpdateDisplay()
  64. {
  65. if (reader == null)
  66. return;
  67. //Destroy all children
  68. int destroyedCount = content.childCount; //we need to know how many were destroyed since unity doesn't actually destroy anything until the end of the frame
  69. foreach (Transform child in content)
  70. Destroy(child.gameObject);
  71. //Instatiate logicElement prefab
  72. foreach (LogicBlock element in reader.LogicChain)
  73. {
  74. LogicElementUI elementUI = Instantiate(Prefab.gameObject, content).GetComponent<LogicElementUI>();
  75. elementUI.Initialise(element, this,false);
  76. }
  77. //Add insertIndex object if needed
  78. if (insertIndex != -1)
  79. {
  80. GameObject elementObject = Instantiate(Prefab.gameObject, content);
  81. if (reader.Length < maxLength)
  82. {
  83. elementObject.GetComponentInChildren<TextMeshProUGUI>().text = "insert";
  84. elementObject.GetComponentInChildren<Image>().color = new Color(0.5f, 0.5f, 0.5f, 0.25f);
  85. }
  86. else
  87. {
  88. elementObject.GetComponentInChildren<TextMeshProUGUI>().text = "X";
  89. elementObject.GetComponentInChildren<Image>().color = new Color(1.0f, 0.25f, 0.25f, 0.5f);
  90. }
  91. //Set sibling index to where we want it in list + add destroyedCount since technically they are still here
  92. elementObject.transform.SetSiblingIndex(destroyedCount + insertIndex);
  93. }
  94. playButton.SetActive(readerQueue.Count <= 1);
  95. returnButton.SetActive(readerQueue.Count > 1);
  96. }
  97. #region LogicElementHolder Implementation
  98. /// <summary>
  99. /// When a LogicElement has started being dragged from this Tray
  100. /// </summary>
  101. /// <param name="element">Element which is being dragged</param>
  102. public override void OnRemove(LogicElementUI element)
  103. {
  104. Vector2 offset = new Vector2(element.rectTransform.rect.width / 2, 0);
  105. int index = GetInsertIndex(element.rectTransform, offset);
  106. Debug.Log("Removing at " + index);
  107. if (index >= reader.LogicChain.Count)
  108. index = reader.LogicChain.Count - 1;
  109. reader.LogicChain.RemoveAt(index);
  110. }
  111. /// <summary>
  112. /// When a logicElement needs to be added back to this Tray
  113. /// </summary>
  114. /// <param name="element">Element to add</param>
  115. public override void OnAdd(LogicElementUI element)
  116. {
  117. Vector2 offset = new Vector2(element.rectTransform.rect.width / 2, 0);
  118. int index = GetInsertIndex(element.rectTransform,offset);
  119. reader.Insert(index, element.logicElement);
  120. Destroy(element.gameObject);
  121. }
  122. /// <summary>
  123. /// When a logic Element is hovering over this holder
  124. /// </summary>
  125. /// <param name="element">Element which is hovering</param>
  126. public override void OnHover(LogicElementUI element)
  127. {
  128. Vector2 offset = new Vector2(element.rectTransform.rect.width / 2, 0);
  129. insertIndex = GetInsertIndex(element.rectTransform, offset);
  130. UpdateDisplay();
  131. }
  132. /// <summary>
  133. /// First frame a logic Element is hovering over this holder
  134. /// </summary>
  135. /// <param name="element">Element which is hovering</param>
  136. public override void OnHoverStart(LogicElementUI element)
  137. {
  138. Debug.Log("OnHoverStart");
  139. //Create insert prefab at End
  140. insertIndex = content.childCount;
  141. UpdateDisplay();
  142. }
  143. /// <summary>
  144. /// first frame a logic Element is no longer hovering over this holder
  145. /// </summary>
  146. /// <param name="element">Element which is hovering</param>
  147. public override void OnHoverEnd(LogicElementUI element)
  148. {
  149. //Remove insert prefab
  150. insertIndex = -1;
  151. UpdateDisplay();
  152. }
  153. /// <summary>
  154. /// Called when an element in this holder is double clicked
  155. /// </summary>
  156. /// <param name="element">element which was double clicked</param>
  157. public override void OnDoubleClick(LogicElementUI element)
  158. {
  159. EditableBlock block = element.logicElement as EditableBlock;
  160. if (block == null)
  161. return;
  162. readerQueue.Add(new QueueData(block.blockReader,block.Color));
  163. border.color = block.Color;
  164. SetBlockReader(block.blockReader);
  165. }
  166. /// <summary>
  167. /// Called to check if this holder can hold the provided element;
  168. /// </summary>
  169. /// <param name="element">element to check if it can hold</param>
  170. /// <returns>returns true if this can hold the element </returns>
  171. public override bool canHold(LogicBlock element)
  172. {
  173. return readerQueue[0].reader.Length < maxLength;
  174. }
  175. #endregion LogicElementHolder Implementation
  176. #region Helper Functions
  177. public int GetInsertIndex(RectTransform rt, Vector2 offset)
  178. {
  179. Rect rect = rt.rect;
  180. rect.center += offset;
  181. rect = rt.TransformRect(rect);
  182. DebugExtensions.DrawRect(rect, Color.green);
  183. foreach (Transform child in content)
  184. {
  185. RectTransform childRect = child as RectTransform;
  186. if (rect.Overlaps(childRect.GlobalRect()))
  187. return child.GetSiblingIndex();
  188. }
  189. Debug.Log("Returning last");
  190. return reader.LogicChain.Count;
  191. }
  192. public int GetInsertIndex(RectTransform rt)
  193. {
  194. return GetInsertIndex(rt, Vector2.zero);
  195. }
  196. #endregion Helper Functions
  197. [System.Serializable]
  198. public class QueueData
  199. {
  200. public Color color;
  201. public BlockReader reader;
  202. public QueueData(BlockReader reader, Color color)
  203. {
  204. this.color = color;
  205. this.reader = reader;
  206. }
  207. }
  208. }