DrawObject.cs 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. using UnityEngine;
  2. using UnityEngine.UI;
  3. using System;
  4. using UnityEngine.Events;
  5. using System.Collections.Generic;
  6. namespace WXB
  7. {
  8. [RequireComponent(typeof(RectTransform))]
  9. [RequireComponent(typeof(CanvasRenderer))]
  10. [ExecuteInEditMode]
  11. public class DrawObject : MonoBehaviour, Draw, IClippable, ICanvasElement
  12. {
  13. private RectMask2D m_ParentMask;
  14. [Serializable]
  15. public class CullStateChangedEvent : UnityEvent<bool> { }
  16. // Event delegates triggered on click.
  17. [SerializeField]
  18. private CullStateChangedEvent m_OnCullStateChanged = new CullStateChangedEvent();
  19. /// <summary>
  20. /// Callback issued when culling changes.
  21. /// </summary>
  22. /// <remarks>
  23. /// Called whene the culling state of this MaskableGraphic either becomes culled or visible. You can use this to control other elements of your UI as culling happens.
  24. /// </remarks>
  25. public CullStateChangedEvent onCullStateChanged
  26. {
  27. get { return m_OnCullStateChanged; }
  28. set { m_OnCullStateChanged = value; }
  29. }
  30. private Canvas m_Canvas;
  31. /// <summary>
  32. /// A reference to the Canvas this Graphic is rendering to.
  33. /// </summary>
  34. /// <remarks>
  35. /// In the situation where the Graphic is used in a hierarchy with multiple Canvases, the Canvas closest to the root will be used.
  36. /// </remarks>
  37. public Canvas canvas
  38. {
  39. get
  40. {
  41. if (m_Canvas == null)
  42. CacheCanvas();
  43. return m_Canvas;
  44. }
  45. }
  46. private void CacheCanvas()
  47. {
  48. var list = ListPool<Canvas>.Get();
  49. gameObject.GetComponentsInParent(false, list);
  50. if (list.Count > 0)
  51. {
  52. // Find the first active and enabled canvas.
  53. for (int i = 0; i < list.Count; ++i)
  54. {
  55. if (list[i].isActiveAndEnabled)
  56. {
  57. m_Canvas = list[i];
  58. break;
  59. }
  60. }
  61. }
  62. else
  63. {
  64. m_Canvas = null;
  65. }
  66. ListPool<Canvas>.Release(list);
  67. }
  68. readonly Vector3[] m_Corners = new Vector3[4];
  69. private Rect rootCanvasRect
  70. {
  71. get
  72. {
  73. if (rectTransform == null)
  74. {
  75. return new Rect(Vector2.zero, Vector2.zero);
  76. }
  77. rectTransform.GetWorldCorners(m_Corners);
  78. if (canvas)
  79. {
  80. Matrix4x4 mat = canvas.rootCanvas.transform.worldToLocalMatrix;
  81. for (int i = 0; i < 4; ++i)
  82. m_Corners[i] = mat.MultiplyPoint(m_Corners[i]);
  83. }
  84. // bounding box is now based on the min and max of all corners (case 1013182)
  85. Vector2 min = m_Corners[0];
  86. Vector2 max = m_Corners[0];
  87. for (int i = 1; i < 4; i++)
  88. {
  89. min.x = Mathf.Min(m_Corners[i].x, min.x);
  90. min.y = Mathf.Min(m_Corners[i].y, min.y);
  91. max.x = Mathf.Max(m_Corners[i].x, max.x);
  92. max.y = Mathf.Max(m_Corners[i].y, max.y);
  93. }
  94. return new Rect(min, max - min);
  95. }
  96. }
  97. protected virtual void OnTransformParentChanged()
  98. {
  99. if (!isActiveAndEnabled)
  100. return;
  101. UpdateRect(Vector2.zero);
  102. UpdateClipParent();
  103. }
  104. protected virtual void OnDisable()
  105. {
  106. if (canvasRenderer == null)
  107. return;
  108. canvasRenderer.Clear();
  109. UpdateClipParent();
  110. }
  111. protected void OnEnable()
  112. {
  113. UpdateRect(Vector2.zero);
  114. UpdateClipParent();
  115. }
  116. public void OnInit()
  117. {
  118. enabled = true;
  119. UpdateRect(Vector2.zero);
  120. }
  121. protected void Start()
  122. {
  123. UpdateRect(Vector2.zero);
  124. }
  125. protected virtual void Init()
  126. {
  127. }
  128. protected void Awake()
  129. {
  130. canvasRenderer = GetComponent<CanvasRenderer>();
  131. rectTransform = GetComponent<RectTransform>();
  132. Init();
  133. }
  134. public RectTransform rectTransform { get; private set; }
  135. public virtual DrawType type { get { return DrawType.Default; } }
  136. public virtual long key { get; set; }
  137. public CanvasRenderer canvasRenderer
  138. {
  139. get;
  140. private set;
  141. }
  142. protected void UpdateRect(Vector2 offset)
  143. {
  144. Tools.UpdateRect(rectTransform, offset);
  145. }
  146. public virtual void UpdateSelf(float deltaTime)
  147. {
  148. }
  149. Material m_Material;
  150. Texture m_Texture;
  151. public Material srcMat { get { return m_Material; } set { m_Material = value; } }
  152. public Texture texture
  153. {
  154. get { return m_Texture; }
  155. set { m_Texture = value; }
  156. }
  157. public void FillMesh(Mesh workerMesh)
  158. {
  159. canvasRenderer.SetMesh(workerMesh);
  160. }
  161. public virtual void UpdateMaterial(Material mat)
  162. {
  163. canvasRenderer.materialCount = 1;
  164. canvasRenderer.SetMaterial(mat, 0);
  165. canvasRenderer.SetTexture(m_Texture);
  166. }
  167. public virtual void Release()
  168. {
  169. m_Material = null;
  170. m_Texture = null;
  171. key = 0;
  172. if (canvasRenderer != null)
  173. {
  174. canvasRenderer.Clear();
  175. }
  176. }
  177. public void DestroySelf()
  178. {
  179. Tools.Destroy(gameObject);
  180. }
  181. private void UpdateClipParent()
  182. {
  183. var newParent = MaskUtilities.GetRectMaskForClippable(this);
  184. // if the new parent is different OR is now inactive
  185. if (m_ParentMask != null && (newParent != m_ParentMask || !newParent.IsActive()))
  186. {
  187. m_ParentMask.RemoveClippable(this);
  188. UpdateCull(false);
  189. }
  190. // don't re-add it if the newparent is inactive
  191. if (newParent != null && newParent.IsActive())
  192. newParent.AddClippable(this);
  193. m_ParentMask = newParent;
  194. }
  195. /// <summary>
  196. /// See IClippable.RecalculateClipping
  197. /// </summary>
  198. public virtual void RecalculateClipping()
  199. {
  200. UpdateClipParent();
  201. }
  202. /// <summary>
  203. /// See IClippable.Cull
  204. /// </summary>
  205. public virtual void Cull(Rect clipRect, bool validRect)
  206. {
  207. var cull = !validRect || !clipRect.Overlaps(rootCanvasRect, true);
  208. UpdateCull(cull);
  209. }
  210. private void UpdateCull(bool cull)
  211. {
  212. if (canvasRenderer == null) return;
  213. if (canvasRenderer.cull != cull)
  214. {
  215. canvasRenderer.cull = cull;
  216. UISystemProfilerApi.AddMarker("MaskableGraphic.cullingChanged", this);
  217. m_OnCullStateChanged.Invoke(cull);
  218. //OnCullingChanged();
  219. if (!canvasRenderer.cull && !CanvasUpdateRegistry.IsRebuildingGraphics() && !CanvasUpdateRegistry.IsRebuildingLayout())
  220. {
  221. /// When we were culled, we potentially skipped calls to <c>Rebuild</c>.
  222. CanvasUpdateRegistry.RegisterCanvasElementForGraphicRebuild(this);
  223. }
  224. }
  225. }
  226. /// <summary>
  227. /// See IClippable.SetClipRect
  228. /// </summary>
  229. public virtual void SetClipRect(Rect clipRect, bool validRect)
  230. {
  231. if (canvasRenderer == null) return;
  232. if (validRect)
  233. canvasRenderer.EnableRectClipping(clipRect);
  234. else
  235. canvasRenderer.DisableRectClipping();
  236. }
  237. public virtual void Rebuild(CanvasUpdate executing)
  238. {
  239. }
  240. public virtual void LayoutComplete()
  241. {
  242. }
  243. public virtual void GraphicUpdateComplete()
  244. {
  245. }
  246. public virtual bool IsDestroyed()
  247. {
  248. return this == null;
  249. }
  250. public void SetClipSoftness(Vector2 clipSoftness)
  251. {
  252. }
  253. }
  254. }