Graphic.cs 35 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025
  1. using System;
  2. #if UNITY_EDITOR
  3. using System.Reflection;
  4. #endif
  5. using System.Collections.Generic;
  6. using UnityEngine.Events;
  7. using UnityEngine.EventSystems;
  8. using UnityEngine.Serialization;
  9. using UnityEngine.UI.CoroutineTween;
  10. namespace UnityEngine.UI
  11. {
  12. /// <summary>
  13. /// Base class for all UI components that should be derived from when creating new Graphic types.
  14. /// </summary>
  15. [DisallowMultipleComponent]
  16. [RequireComponent(typeof(RectTransform))]
  17. [ExecuteAlways]
  18. /// <summary>
  19. /// Base class for all visual UI Component.
  20. /// When creating visual UI components you should inherit from this class.
  21. /// </summary>
  22. /// <example>
  23. /// Below is a simple example that draws a colored quad inside the Rect Transform area.
  24. /// <code>
  25. /// using UnityEngine;
  26. /// using UnityEngine.UI;
  27. ///
  28. /// [ExecuteInEditMode]
  29. /// public class SimpleImage : Graphic
  30. /// {
  31. /// protected override void OnPopulateMesh(VertexHelper vh)
  32. /// {
  33. /// Vector2 corner1 = Vector2.zero;
  34. /// Vector2 corner2 = Vector2.zero;
  35. ///
  36. /// corner1.x = 0f;
  37. /// corner1.y = 0f;
  38. /// corner2.x = 1f;
  39. /// corner2.y = 1f;
  40. ///
  41. /// corner1.x -= rectTransform.pivot.x;
  42. /// corner1.y -= rectTransform.pivot.y;
  43. /// corner2.x -= rectTransform.pivot.x;
  44. /// corner2.y -= rectTransform.pivot.y;
  45. ///
  46. /// corner1.x *= rectTransform.rect.width;
  47. /// corner1.y *= rectTransform.rect.height;
  48. /// corner2.x *= rectTransform.rect.width;
  49. /// corner2.y *= rectTransform.rect.height;
  50. ///
  51. /// vh.Clear();
  52. ///
  53. /// UIVertex vert = UIVertex.simpleVert;
  54. ///
  55. /// vert.position = new Vector2(corner1.x, corner1.y);
  56. /// vert.color = color;
  57. /// vh.AddVert(vert);
  58. ///
  59. /// vert.position = new Vector2(corner1.x, corner2.y);
  60. /// vert.color = color;
  61. /// vh.AddVert(vert);
  62. ///
  63. /// vert.position = new Vector2(corner2.x, corner2.y);
  64. /// vert.color = color;
  65. /// vh.AddVert(vert);
  66. ///
  67. /// vert.position = new Vector2(corner2.x, corner1.y);
  68. /// vert.color = color;
  69. /// vh.AddVert(vert);
  70. ///
  71. /// vh.AddTriangle(0, 1, 2);
  72. /// vh.AddTriangle(2, 3, 0);
  73. /// }
  74. /// }
  75. /// </code>
  76. /// </example>
  77. public abstract class Graphic
  78. : UIBehaviour,
  79. ICanvasElement
  80. {
  81. static protected Material s_DefaultUI = null;
  82. static protected Texture2D s_WhiteTexture = null;
  83. /// <summary>
  84. /// Default material used to draw UI elements if no explicit material was specified.
  85. /// </summary>
  86. static public Material defaultGraphicMaterial
  87. {
  88. get
  89. {
  90. if (s_DefaultUI == null)
  91. s_DefaultUI = Canvas.GetDefaultCanvasMaterial();
  92. return s_DefaultUI;
  93. }
  94. }
  95. // Cached and saved values
  96. [FormerlySerializedAs("m_Mat")]
  97. [SerializeField] protected Material m_Material;
  98. [SerializeField] private Color m_Color = Color.white;
  99. [NonSerialized] protected bool m_SkipLayoutUpdate;
  100. [NonSerialized] protected bool m_SkipMaterialUpdate;
  101. /// <summary>
  102. /// Base color of the Graphic.
  103. /// </summary>
  104. /// <remarks>
  105. /// The builtin UI Components use this as their vertex color. Use this to fetch or change the Color of visual UI elements, such as an Image.
  106. /// </remarks>
  107. /// <example>
  108. /// <code>
  109. /// //Place this script on a GameObject with a Graphic component attached e.g. a visual UI element (Image).
  110. ///
  111. /// using UnityEngine;
  112. /// using UnityEngine.UI;
  113. ///
  114. /// public class Example : MonoBehaviour
  115. /// {
  116. /// Graphic m_Graphic;
  117. /// Color m_MyColor;
  118. ///
  119. /// void Start()
  120. /// {
  121. /// //Fetch the Graphic from the GameObject
  122. /// m_Graphic = GetComponent<Graphic>();
  123. /// //Create a new Color that starts as red
  124. /// m_MyColor = Color.red;
  125. /// //Change the Graphic Color to the new Color
  126. /// m_Graphic.color = m_MyColor;
  127. /// }
  128. ///
  129. /// // Update is called once per frame
  130. /// void Update()
  131. /// {
  132. /// //When the mouse button is clicked, change the Graphic Color
  133. /// if (Input.GetKey(KeyCode.Mouse0))
  134. /// {
  135. /// //Change the Color over time between blue and red while the mouse button is pressed
  136. /// m_MyColor = Color.Lerp(Color.red, Color.blue, Mathf.PingPong(Time.time, 1));
  137. /// }
  138. /// //Change the Graphic Color to the new Color
  139. /// m_Graphic.color = m_MyColor;
  140. /// }
  141. /// }
  142. /// </code>
  143. /// </example>
  144. public virtual Color color { get { return m_Color; } set { if (SetPropertyUtility.SetColor(ref m_Color, value)) SetVerticesDirty(); } }
  145. [SerializeField] private bool m_RaycastTarget = true;
  146. /// <summary>
  147. /// Should this graphic be considered a target for raycasting?
  148. /// </summary>
  149. public virtual bool raycastTarget
  150. {
  151. get
  152. {
  153. return m_RaycastTarget;
  154. }
  155. set
  156. {
  157. if (value != m_RaycastTarget)
  158. {
  159. if (m_RaycastTarget)
  160. GraphicRegistry.UnregisterRaycastGraphicForCanvas(canvas, this);
  161. m_RaycastTarget = value;
  162. if (m_RaycastTarget && isActiveAndEnabled)
  163. GraphicRegistry.RegisterRaycastGraphicForCanvas(canvas, this);
  164. }
  165. }
  166. }
  167. [SerializeField]
  168. private Vector4 m_RaycastPadding = new Vector4();
  169. /// <summary>
  170. /// Padding to be applied to the masking
  171. /// X = Left
  172. /// Y = Bottom
  173. /// Z = Right
  174. /// W = Top
  175. /// </summary>
  176. public Vector4 raycastPadding
  177. {
  178. get { return m_RaycastPadding; }
  179. set
  180. {
  181. m_RaycastPadding = value;
  182. }
  183. }
  184. [NonSerialized] private RectTransform m_RectTransform;
  185. [NonSerialized] private CanvasRenderer m_CanvasRenderer;
  186. [NonSerialized] private Canvas m_Canvas;
  187. [NonSerialized] private bool m_VertsDirty;
  188. [NonSerialized] private bool m_MaterialDirty;
  189. [NonSerialized] protected UnityAction m_OnDirtyLayoutCallback;
  190. [NonSerialized] protected UnityAction m_OnDirtyVertsCallback;
  191. [NonSerialized] protected UnityAction m_OnDirtyMaterialCallback;
  192. [NonSerialized] protected static Mesh s_Mesh;
  193. [NonSerialized] private static readonly VertexHelper s_VertexHelper = new VertexHelper();
  194. [NonSerialized] protected Mesh m_CachedMesh;
  195. [NonSerialized] protected Vector2[] m_CachedUvs;
  196. // Tween controls for the Graphic
  197. [NonSerialized]
  198. private readonly TweenRunner<ColorTween> m_ColorTweenRunner;
  199. protected bool useLegacyMeshGeneration { get; set; }
  200. // Called by Unity prior to deserialization,
  201. // should not be called by users
  202. protected Graphic()
  203. {
  204. if (m_ColorTweenRunner == null)
  205. m_ColorTweenRunner = new TweenRunner<ColorTween>();
  206. m_ColorTweenRunner.Init(this);
  207. useLegacyMeshGeneration = true;
  208. }
  209. /// <summary>
  210. /// Set all properties of the Graphic dirty and needing rebuilt.
  211. /// Dirties Layout, Vertices, and Materials.
  212. /// </summary>
  213. public virtual void SetAllDirty()
  214. {
  215. // Optimization: Graphic layout doesn't need recalculation if
  216. // the underlying Sprite is the same size with the same texture.
  217. // (e.g. Sprite sheet texture animation)
  218. if (m_SkipLayoutUpdate)
  219. {
  220. m_SkipLayoutUpdate = false;
  221. }
  222. else
  223. {
  224. SetLayoutDirty();
  225. }
  226. if (m_SkipMaterialUpdate)
  227. {
  228. m_SkipMaterialUpdate = false;
  229. }
  230. else
  231. {
  232. SetMaterialDirty();
  233. }
  234. SetVerticesDirty();
  235. }
  236. /// <summary>
  237. /// Mark the layout as dirty and needing rebuilt.
  238. /// </summary>
  239. /// <remarks>
  240. /// Send a OnDirtyLayoutCallback notification if any elements are registered. See RegisterDirtyLayoutCallback
  241. /// </remarks>
  242. public virtual void SetLayoutDirty()
  243. {
  244. if (!IsActive())
  245. return;
  246. LayoutRebuilder.MarkLayoutForRebuild(rectTransform);
  247. if (m_OnDirtyLayoutCallback != null)
  248. m_OnDirtyLayoutCallback();
  249. }
  250. /// <summary>
  251. /// Mark the vertices as dirty and needing rebuilt.
  252. /// </summary>
  253. /// <remarks>
  254. /// Send a OnDirtyVertsCallback notification if any elements are registered. See RegisterDirtyVerticesCallback
  255. /// </remarks>
  256. public virtual void SetVerticesDirty()
  257. {
  258. if (!IsActive())
  259. return;
  260. m_VertsDirty = true;
  261. CanvasUpdateRegistry.RegisterCanvasElementForGraphicRebuild(this);
  262. if (m_OnDirtyVertsCallback != null)
  263. m_OnDirtyVertsCallback();
  264. }
  265. /// <summary>
  266. /// Mark the material as dirty and needing rebuilt.
  267. /// </summary>
  268. /// <remarks>
  269. /// Send a OnDirtyMaterialCallback notification if any elements are registered. See RegisterDirtyMaterialCallback
  270. /// </remarks>
  271. public virtual void SetMaterialDirty()
  272. {
  273. if (!IsActive())
  274. return;
  275. m_MaterialDirty = true;
  276. CanvasUpdateRegistry.RegisterCanvasElementForGraphicRebuild(this);
  277. if (m_OnDirtyMaterialCallback != null)
  278. m_OnDirtyMaterialCallback();
  279. }
  280. protected override void OnRectTransformDimensionsChange()
  281. {
  282. if (gameObject.activeInHierarchy)
  283. {
  284. // prevent double dirtying...
  285. if (CanvasUpdateRegistry.IsRebuildingLayout())
  286. SetVerticesDirty();
  287. else
  288. {
  289. SetVerticesDirty();
  290. SetLayoutDirty();
  291. }
  292. }
  293. }
  294. protected override void OnBeforeTransformParentChanged()
  295. {
  296. GraphicRegistry.UnregisterGraphicForCanvas(canvas, this);
  297. LayoutRebuilder.MarkLayoutForRebuild(rectTransform);
  298. }
  299. protected override void OnTransformParentChanged()
  300. {
  301. base.OnTransformParentChanged();
  302. m_Canvas = null;
  303. if (!IsActive())
  304. return;
  305. CacheCanvas();
  306. GraphicRegistry.RegisterGraphicForCanvas(canvas, this);
  307. SetAllDirty();
  308. }
  309. /// <summary>
  310. /// Absolute depth of the graphic, used by rendering and events -- lowest to highest.
  311. /// </summary>
  312. /// <example>
  313. /// The depth is relative to the first root canvas.
  314. ///
  315. /// Canvas
  316. /// Graphic - 1
  317. /// Graphic - 2
  318. /// Nested Canvas
  319. /// Graphic - 3
  320. /// Graphic - 4
  321. /// Graphic - 5
  322. ///
  323. /// This value is used to determine draw and event ordering.
  324. /// </example>
  325. public int depth { get { return canvasRenderer.absoluteDepth; } }
  326. /// <summary>
  327. /// The RectTransform component used by the Graphic. Cached for speed.
  328. /// </summary>
  329. public RectTransform rectTransform
  330. {
  331. get
  332. {
  333. // The RectTransform is a required component that must not be destroyed. Based on this assumption, a
  334. // null-reference check is sufficient.
  335. if (ReferenceEquals(m_RectTransform, null))
  336. {
  337. m_RectTransform = GetComponent<RectTransform>();
  338. }
  339. return m_RectTransform;
  340. }
  341. }
  342. /// <summary>
  343. /// A reference to the Canvas this Graphic is rendering to.
  344. /// </summary>
  345. /// <remarks>
  346. /// In the situation where the Graphic is used in a hierarchy with multiple Canvases, the Canvas closest to the root will be used.
  347. /// </remarks>
  348. public Canvas canvas
  349. {
  350. get
  351. {
  352. if (m_Canvas == null)
  353. CacheCanvas();
  354. return m_Canvas;
  355. }
  356. }
  357. private void CacheCanvas()
  358. {
  359. var list = ListPool<Canvas>.Get();
  360. gameObject.GetComponentsInParent(false, list);
  361. if (list.Count > 0)
  362. {
  363. // Find the first active and enabled canvas.
  364. for (int i = 0; i < list.Count; ++i)
  365. {
  366. if (list[i].isActiveAndEnabled)
  367. {
  368. m_Canvas = list[i];
  369. break;
  370. }
  371. // if we reached the end and couldn't find an active and enabled canvas, we should return null . case 1171433
  372. if (i == list.Count - 1)
  373. m_Canvas = null;
  374. }
  375. }
  376. else
  377. {
  378. m_Canvas = null;
  379. }
  380. ListPool<Canvas>.Release(list);
  381. }
  382. /// <summary>
  383. /// A reference to the CanvasRenderer populated by this Graphic.
  384. /// </summary>
  385. public CanvasRenderer canvasRenderer
  386. {
  387. get
  388. {
  389. // The CanvasRenderer is a required component that must not be destroyed. Based on this assumption, a
  390. // null-reference check is sufficient.
  391. if (ReferenceEquals(m_CanvasRenderer, null))
  392. {
  393. m_CanvasRenderer = GetComponent<CanvasRenderer>();
  394. if (ReferenceEquals(m_CanvasRenderer, null))
  395. {
  396. m_CanvasRenderer = gameObject.AddComponent<CanvasRenderer>();
  397. }
  398. }
  399. return m_CanvasRenderer;
  400. }
  401. }
  402. /// <summary>
  403. /// Returns the default material for the graphic.
  404. /// </summary>
  405. public virtual Material defaultMaterial
  406. {
  407. get { return defaultGraphicMaterial; }
  408. }
  409. /// <summary>
  410. /// The Material set by the user
  411. /// </summary>
  412. public virtual Material material
  413. {
  414. get
  415. {
  416. return (m_Material != null) ? m_Material : defaultMaterial;
  417. }
  418. set
  419. {
  420. if (m_Material == value)
  421. return;
  422. m_Material = value;
  423. SetMaterialDirty();
  424. }
  425. }
  426. /// <summary>
  427. /// The material that will be sent for Rendering (Read only).
  428. /// </summary>
  429. /// <remarks>
  430. /// This is the material that actually gets sent to the CanvasRenderer. By default it's the same as [[Graphic.material]]. When extending Graphic you can override this to send a different material to the CanvasRenderer than the one set by Graphic.material. This is useful if you want to modify the user set material in a non destructive manner.
  431. /// </remarks>
  432. public virtual Material materialForRendering
  433. {
  434. get
  435. {
  436. var components = ListPool<Component>.Get();
  437. GetComponents(typeof(IMaterialModifier), components);
  438. var currentMat = material;
  439. for (var i = 0; i < components.Count; i++)
  440. currentMat = (components[i] as IMaterialModifier).GetModifiedMaterial(currentMat);
  441. ListPool<Component>.Release(components);
  442. return currentMat;
  443. }
  444. }
  445. /// <summary>
  446. /// The graphic's texture. (Read Only).
  447. /// </summary>
  448. /// <remarks>
  449. /// This is the Texture that gets passed to the CanvasRenderer, Material and then Shader _MainTex.
  450. ///
  451. /// When implementing your own Graphic you can override this to control which texture goes through the UI Rendering pipeline.
  452. ///
  453. /// Bear in mind that Unity tries to batch UI elements together to improve performance, so its ideal to work with atlas to reduce the number of draw calls.
  454. /// </remarks>
  455. public virtual Texture mainTexture
  456. {
  457. get
  458. {
  459. return s_WhiteTexture;
  460. }
  461. }
  462. /// <summary>
  463. /// Mark the Graphic and the canvas as having been changed.
  464. /// </summary>
  465. protected override void OnEnable()
  466. {
  467. base.OnEnable();
  468. CacheCanvas();
  469. GraphicRegistry.RegisterGraphicForCanvas(canvas, this);
  470. #if UNITY_EDITOR
  471. GraphicRebuildTracker.TrackGraphic(this);
  472. #endif
  473. if (s_WhiteTexture == null)
  474. s_WhiteTexture = Texture2D.whiteTexture;
  475. SetAllDirty();
  476. }
  477. /// <summary>
  478. /// Clear references.
  479. /// </summary>
  480. protected override void OnDisable()
  481. {
  482. #if UNITY_EDITOR
  483. GraphicRebuildTracker.UnTrackGraphic(this);
  484. #endif
  485. GraphicRegistry.UnregisterGraphicForCanvas(canvas, this);
  486. CanvasUpdateRegistry.UnRegisterCanvasElementForRebuild(this);
  487. if (canvasRenderer != null)
  488. canvasRenderer.Clear();
  489. LayoutRebuilder.MarkLayoutForRebuild(rectTransform);
  490. base.OnDisable();
  491. }
  492. protected override void OnDestroy()
  493. {
  494. if (m_CachedMesh)
  495. Destroy(m_CachedMesh);
  496. m_CachedMesh = null;
  497. base.OnDestroy();
  498. }
  499. protected override void OnCanvasHierarchyChanged()
  500. {
  501. // Use m_Cavas so we dont auto call CacheCanvas
  502. Canvas currentCanvas = m_Canvas;
  503. // Clear the cached canvas. Will be fetched below if active.
  504. m_Canvas = null;
  505. if (!IsActive())
  506. return;
  507. CacheCanvas();
  508. if (currentCanvas != m_Canvas)
  509. {
  510. GraphicRegistry.UnregisterGraphicForCanvas(currentCanvas, this);
  511. // Only register if we are active and enabled as OnCanvasHierarchyChanged can get called
  512. // during object destruction and we dont want to register ourself and then become null.
  513. if (IsActive())
  514. GraphicRegistry.RegisterGraphicForCanvas(canvas, this);
  515. }
  516. }
  517. /// <summary>
  518. /// This method must be called when <c>CanvasRenderer.cull</c> is modified.
  519. /// </summary>
  520. /// <remarks>
  521. /// This can be used to perform operations that were previously skipped because the <c>Graphic</c> was culled.
  522. /// </remarks>
  523. public virtual void OnCullingChanged()
  524. {
  525. if (!canvasRenderer.cull && (m_VertsDirty || m_MaterialDirty))
  526. {
  527. /// When we were culled, we potentially skipped calls to <c>Rebuild</c>.
  528. CanvasUpdateRegistry.RegisterCanvasElementForGraphicRebuild(this);
  529. }
  530. }
  531. /// <summary>
  532. /// Rebuilds the graphic geometry and its material on the PreRender cycle.
  533. /// </summary>
  534. /// <param name="update">The current step of the rendering CanvasUpdate cycle.</param>
  535. /// <remarks>
  536. /// See CanvasUpdateRegistry for more details on the canvas update cycle.
  537. /// </remarks>
  538. public virtual void Rebuild(CanvasUpdate update)
  539. {
  540. if (canvasRenderer == null || canvasRenderer.cull)
  541. return;
  542. switch (update)
  543. {
  544. case CanvasUpdate.PreRender:
  545. if (m_VertsDirty)
  546. {
  547. UpdateGeometry();
  548. m_VertsDirty = false;
  549. }
  550. if (m_MaterialDirty)
  551. {
  552. UpdateMaterial();
  553. m_MaterialDirty = false;
  554. }
  555. break;
  556. }
  557. }
  558. public virtual void LayoutComplete()
  559. {}
  560. public virtual void GraphicUpdateComplete()
  561. {}
  562. /// <summary>
  563. /// Call to update the Material of the graphic onto the CanvasRenderer.
  564. /// </summary>
  565. protected virtual void UpdateMaterial()
  566. {
  567. if (!IsActive())
  568. return;
  569. canvasRenderer.materialCount = 1;
  570. canvasRenderer.SetMaterial(materialForRendering, 0);
  571. canvasRenderer.SetTexture(mainTexture);
  572. }
  573. /// <summary>
  574. /// Call to update the geometry of the Graphic onto the CanvasRenderer.
  575. /// </summary>
  576. protected virtual void UpdateGeometry()
  577. {
  578. if (useLegacyMeshGeneration)
  579. {
  580. DoLegacyMeshGeneration();
  581. }
  582. else
  583. {
  584. DoMeshGeneration();
  585. }
  586. }
  587. private void DoMeshGeneration()
  588. {
  589. if (rectTransform != null && rectTransform.rect.width >= 0 && rectTransform.rect.height >= 0)
  590. OnPopulateMesh(s_VertexHelper);
  591. else
  592. s_VertexHelper.Clear(); // clear the vertex helper so invalid graphics dont draw.
  593. var components = ListPool<Component>.Get();
  594. GetComponents(typeof(IMeshModifier), components);
  595. for (var i = 0; i < components.Count; i++)
  596. ((IMeshModifier)components[i]).ModifyMesh(s_VertexHelper);
  597. ListPool<Component>.Release(components);
  598. s_VertexHelper.FillMesh(workerMesh);
  599. canvasRenderer.SetMesh(workerMesh);
  600. }
  601. private void DoLegacyMeshGeneration()
  602. {
  603. if (rectTransform != null && rectTransform.rect.width >= 0 && rectTransform.rect.height >= 0)
  604. {
  605. #pragma warning disable 618
  606. OnPopulateMesh(workerMesh);
  607. #pragma warning restore 618
  608. }
  609. else
  610. {
  611. workerMesh.Clear();
  612. }
  613. var components = ListPool<Component>.Get();
  614. GetComponents(typeof(IMeshModifier), components);
  615. for (var i = 0; i < components.Count; i++)
  616. {
  617. #pragma warning disable 618
  618. ((IMeshModifier)components[i]).ModifyMesh(workerMesh);
  619. #pragma warning restore 618
  620. }
  621. ListPool<Component>.Release(components);
  622. canvasRenderer.SetMesh(workerMesh);
  623. }
  624. protected static Mesh workerMesh
  625. {
  626. get
  627. {
  628. if (s_Mesh == null)
  629. {
  630. s_Mesh = new Mesh();
  631. s_Mesh.name = "Shared UI Mesh";
  632. s_Mesh.hideFlags = HideFlags.HideAndDontSave;
  633. }
  634. return s_Mesh;
  635. }
  636. }
  637. [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
  638. [Obsolete("Use OnPopulateMesh instead.", true)]
  639. protected virtual void OnFillVBO(System.Collections.Generic.List<UIVertex> vbo) {}
  640. [Obsolete("Use OnPopulateMesh(VertexHelper vh) instead.", false)]
  641. /// <summary>
  642. /// Callback function when a UI element needs to generate vertices. Fills the vertex buffer data.
  643. /// </summary>
  644. /// <param name="m">Mesh to populate with UI data.</param>
  645. /// <remarks>
  646. /// Used by Text, UI.Image, and RawImage for example to generate vertices specific to their use case.
  647. /// </remarks>
  648. protected virtual void OnPopulateMesh(Mesh m)
  649. {
  650. OnPopulateMesh(s_VertexHelper);
  651. s_VertexHelper.FillMesh(m);
  652. }
  653. /// <summary>
  654. /// Callback function when a UI element needs to generate vertices. Fills the vertex buffer data.
  655. /// </summary>
  656. /// <param name="vh">VertexHelper utility.</param>
  657. /// <remarks>
  658. /// Used by Text, UI.Image, and RawImage for example to generate vertices specific to their use case.
  659. /// </remarks>
  660. protected virtual void OnPopulateMesh(VertexHelper vh)
  661. {
  662. var r = GetPixelAdjustedRect();
  663. var v = new Vector4(r.x, r.y, r.x + r.width, r.y + r.height);
  664. Color32 color32 = color;
  665. vh.Clear();
  666. vh.AddVert(new Vector3(v.x, v.y), color32, new Vector2(0f, 0f));
  667. vh.AddVert(new Vector3(v.x, v.w), color32, new Vector2(0f, 1f));
  668. vh.AddVert(new Vector3(v.z, v.w), color32, new Vector2(1f, 1f));
  669. vh.AddVert(new Vector3(v.z, v.y), color32, new Vector2(1f, 0f));
  670. vh.AddTriangle(0, 1, 2);
  671. vh.AddTriangle(2, 3, 0);
  672. }
  673. #if UNITY_EDITOR
  674. /// <summary>
  675. /// Editor-only callback that is issued by Unity if a rebuild of the Graphic is required.
  676. /// Currently sent when an asset is reimported.
  677. /// </summary>
  678. public virtual void OnRebuildRequested()
  679. {
  680. // when rebuild is requested we need to rebuild all the graphics /
  681. // and associated components... The correct way to do this is by
  682. // calling OnValidate... Because MB's don't have a common base class
  683. // we do this via reflection. It's nasty and ugly... Editor only.
  684. m_SkipLayoutUpdate = true;
  685. var mbs = gameObject.GetComponents<MonoBehaviour>();
  686. foreach (var mb in mbs)
  687. {
  688. if (mb == null)
  689. continue;
  690. var methodInfo = mb.GetType().GetMethod("OnValidate", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
  691. if (methodInfo != null)
  692. methodInfo.Invoke(mb, null);
  693. }
  694. m_SkipLayoutUpdate = false;
  695. }
  696. protected override void Reset()
  697. {
  698. SetAllDirty();
  699. }
  700. #endif
  701. // Call from unity if animation properties have changed
  702. protected override void OnDidApplyAnimationProperties()
  703. {
  704. SetAllDirty();
  705. }
  706. /// <summary>
  707. /// Make the Graphic have the native size of its content.
  708. /// </summary>
  709. public virtual void SetNativeSize() {}
  710. /// <summary>
  711. /// When a GraphicRaycaster is raycasting into the scene it does two things. First it filters the elements using their RectTransform rect. Then it uses this Raycast function to determine the elements hit by the raycast.
  712. /// </summary>
  713. /// <param name="sp">Screen point being tested</param>
  714. /// <param name="eventCamera">Camera that is being used for the testing.</param>
  715. /// <returns>True if the provided point is a valid location for GraphicRaycaster raycasts.</returns>
  716. public virtual bool Raycast(Vector2 sp, Camera eventCamera)
  717. {
  718. if (!isActiveAndEnabled)
  719. return false;
  720. var t = transform;
  721. var components = ListPool<Component>.Get();
  722. bool ignoreParentGroups = false;
  723. bool continueTraversal = true;
  724. while (t != null)
  725. {
  726. t.GetComponents(components);
  727. for (var i = 0; i < components.Count; i++)
  728. {
  729. var canvas = components[i] as Canvas;
  730. if (canvas != null && canvas.overrideSorting)
  731. continueTraversal = false;
  732. var filter = components[i] as ICanvasRaycastFilter;
  733. if (filter == null)
  734. continue;
  735. var raycastValid = true;
  736. var group = components[i] as CanvasGroup;
  737. if (group != null)
  738. {
  739. if (ignoreParentGroups == false && group.ignoreParentGroups)
  740. {
  741. ignoreParentGroups = true;
  742. raycastValid = filter.IsRaycastLocationValid(sp, eventCamera);
  743. }
  744. else if (!ignoreParentGroups)
  745. raycastValid = filter.IsRaycastLocationValid(sp, eventCamera);
  746. }
  747. else
  748. {
  749. raycastValid = filter.IsRaycastLocationValid(sp, eventCamera);
  750. }
  751. if (!raycastValid)
  752. {
  753. ListPool<Component>.Release(components);
  754. return false;
  755. }
  756. }
  757. t = continueTraversal ? t.parent : null;
  758. }
  759. ListPool<Component>.Release(components);
  760. return true;
  761. }
  762. #if UNITY_EDITOR
  763. protected override void OnValidate()
  764. {
  765. base.OnValidate();
  766. SetAllDirty();
  767. }
  768. #endif
  769. ///<summary>
  770. ///Adjusts the given pixel to be pixel perfect.
  771. ///</summary>
  772. ///<param name="point">Local space point.</param>
  773. ///<returns>Pixel perfect adjusted point.</returns>
  774. ///<remarks>
  775. ///Note: This is only accurate if the Graphic root Canvas is in Screen Space.
  776. ///</remarks>
  777. public Vector2 PixelAdjustPoint(Vector2 point)
  778. {
  779. if (!canvas || canvas.renderMode == RenderMode.WorldSpace || canvas.scaleFactor == 0.0f || !canvas.pixelPerfect)
  780. return point;
  781. else
  782. {
  783. return RectTransformUtility.PixelAdjustPoint(point, transform, canvas);
  784. }
  785. }
  786. /// <summary>
  787. /// Returns a pixel perfect Rect closest to the Graphic RectTransform.
  788. /// </summary>
  789. /// <remarks>
  790. /// Note: This is only accurate if the Graphic root Canvas is in Screen Space.
  791. /// </remarks>
  792. /// <returns>A Pixel perfect Rect.</returns>
  793. public Rect GetPixelAdjustedRect()
  794. {
  795. if (!canvas || canvas.renderMode == RenderMode.WorldSpace || canvas.scaleFactor == 0.0f || !canvas.pixelPerfect)
  796. return rectTransform.rect;
  797. else
  798. return RectTransformUtility.PixelAdjustRect(rectTransform, canvas);
  799. }
  800. ///<summary>
  801. ///Tweens the CanvasRenderer color associated with this Graphic.
  802. ///</summary>
  803. ///<param name="targetColor">Target color.</param>
  804. ///<param name="duration">Tween duration.</param>
  805. ///<param name="ignoreTimeScale">Should ignore Time.scale?</param>
  806. ///<param name="useAlpha">Should also Tween the alpha channel?</param>
  807. public virtual void CrossFadeColor(Color targetColor, float duration, bool ignoreTimeScale, bool useAlpha)
  808. {
  809. CrossFadeColor(targetColor, duration, ignoreTimeScale, useAlpha, true);
  810. }
  811. ///<summary>
  812. ///Tweens the CanvasRenderer color associated with this Graphic.
  813. ///</summary>
  814. ///<param name="targetColor">Target color.</param>
  815. ///<param name="duration">Tween duration.</param>
  816. ///<param name="ignoreTimeScale">Should ignore Time.scale?</param>
  817. ///<param name="useAlpha">Should also Tween the alpha channel?</param>
  818. /// <param name="useRGB">Should the color or the alpha be used to tween</param>
  819. public virtual void CrossFadeColor(Color targetColor, float duration, bool ignoreTimeScale, bool useAlpha, bool useRGB)
  820. {
  821. if (canvasRenderer == null || (!useRGB && !useAlpha))
  822. return;
  823. Color currentColor = canvasRenderer.GetColor();
  824. if (currentColor.Equals(targetColor))
  825. {
  826. m_ColorTweenRunner.StopTween();
  827. return;
  828. }
  829. ColorTween.ColorTweenMode mode = (useRGB && useAlpha ?
  830. ColorTween.ColorTweenMode.All :
  831. (useRGB ? ColorTween.ColorTweenMode.RGB : ColorTween.ColorTweenMode.Alpha));
  832. var colorTween = new ColorTween {duration = duration, startColor = canvasRenderer.GetColor(), targetColor = targetColor};
  833. colorTween.AddOnChangedCallback(canvasRenderer.SetColor);
  834. colorTween.ignoreTimeScale = ignoreTimeScale;
  835. colorTween.tweenMode = mode;
  836. m_ColorTweenRunner.StartTween(colorTween);
  837. }
  838. static private Color CreateColorFromAlpha(float alpha)
  839. {
  840. var alphaColor = Color.black;
  841. alphaColor.a = alpha;
  842. return alphaColor;
  843. }
  844. ///<summary>
  845. ///Tweens the alpha of the CanvasRenderer color associated with this Graphic.
  846. ///</summary>
  847. ///<param name="alpha">Target alpha.</param>
  848. ///<param name="duration">Duration of the tween in seconds.</param>
  849. ///<param name="ignoreTimeScale">Should ignore [[Time.scale]]?</param>
  850. public virtual void CrossFadeAlpha(float alpha, float duration, bool ignoreTimeScale)
  851. {
  852. CrossFadeColor(CreateColorFromAlpha(alpha), duration, ignoreTimeScale, true, false);
  853. }
  854. /// <summary>
  855. /// Add a listener to receive notification when the graphics layout is dirtied.
  856. /// </summary>
  857. /// <param name="action">The method to call when invoked.</param>
  858. public void RegisterDirtyLayoutCallback(UnityAction action)
  859. {
  860. m_OnDirtyLayoutCallback += action;
  861. }
  862. /// <summary>
  863. /// Remove a listener from receiving notifications when the graphics layout are dirtied
  864. /// </summary>
  865. /// <param name="action">The method to call when invoked.</param>
  866. public void UnregisterDirtyLayoutCallback(UnityAction action)
  867. {
  868. m_OnDirtyLayoutCallback -= action;
  869. }
  870. /// <summary>
  871. /// Add a listener to receive notification when the graphics vertices are dirtied.
  872. /// </summary>
  873. /// <param name="action">The method to call when invoked.</param>
  874. public void RegisterDirtyVerticesCallback(UnityAction action)
  875. {
  876. m_OnDirtyVertsCallback += action;
  877. }
  878. /// <summary>
  879. /// Remove a listener from receiving notifications when the graphics vertices are dirtied
  880. /// </summary>
  881. /// <param name="action">The method to call when invoked.</param>
  882. public void UnregisterDirtyVerticesCallback(UnityAction action)
  883. {
  884. m_OnDirtyVertsCallback -= action;
  885. }
  886. /// <summary>
  887. /// Add a listener to receive notification when the graphics material is dirtied.
  888. /// </summary>
  889. /// <param name="action">The method to call when invoked.</param>
  890. public void RegisterDirtyMaterialCallback(UnityAction action)
  891. {
  892. m_OnDirtyMaterialCallback += action;
  893. }
  894. /// <summary>
  895. /// Remove a listener from receiving notifications when the graphics material are dirtied
  896. /// </summary>
  897. /// <param name="action">The method to call when invoked.</param>
  898. public void UnregisterDirtyMaterialCallback(UnityAction action)
  899. {
  900. m_OnDirtyMaterialCallback -= action;
  901. }
  902. }
  903. }