///<summary> /// This is an element that can live on a Canvas. ///</summary> publicinterfaceICanvasElement { ///<summary> /// Rebuild the element for the given stage. ///</summary> ///<param name="executing">The current CanvasUpdate stage being rebuild.</param> voidRebuild(CanvasUpdate executing);
///<summary> /// Get the transform associated with the ICanvasElement. ///</summary> Transform transform { get; }
///<summary> /// Callback sent when this ICanvasElement has completed layout. ///</summary> voidLayoutComplete();
///<summary> /// Callback sent when this ICanvasElement has completed Graphic rebuild. ///</summary> voidGraphicUpdateComplete();
///<summary> /// Used if the native representation has been destroyed. ///</summary> ///<returns>Return true if the element is considered destroyed.</returns> boolIsDestroyed(); }
///<summary> /// Values of 'update' called on a Canvas update. ///</summary> publicenum CanvasUpdate { ///<summary> /// Called before layout. ///</summary> Prelayout = 0, ///<summary> /// Called for layout. ///</summary> Layout = 1, ///<summary> /// Called after layout. ///</summary> PostLayout = 2, ///<summary> /// Called before rendering. ///</summary> PreRender = 3, ///<summary> /// Called late, before render. ///</summary> LatePreRender = 4, ///<summary> /// Max enum value. Always last. ///</summary> MaxUpdateValue = 5 }
// now layout is complete do culling... ClipperRegistry.instance.Cull();
m_PerformingGraphicUpdate = true; for (var i = (int)CanvasUpdate.PreRender; i < (int)CanvasUpdate.MaxUpdateValue; i++) { for (var k = 0; k < instance.m_GraphicRebuildQueue.Count; k++) { try { var element = instance.m_GraphicRebuildQueue[k]; if (ObjectValidForUpdate(element)) element.Rebuild((CanvasUpdate)i); } catch (Exception e) { Debug.LogException(e, instance.m_GraphicRebuildQueue[k].transform); } } }
for (int i = 0; i < m_GraphicRebuildQueue.Count; ++i) m_GraphicRebuildQueue[i].GraphicUpdateComplete();
Graphics.cs ///<summary> /// Mark the layout as dirty and needing rebuilt. ///</summary> ///<remarks> /// Send a OnDirtyLayoutCallback notification if any elements are registered. See RegisterDirtyLayoutCallback ///</remarks> publicvirtualvoidSetLayoutDirty() { if (!IsActive()) return;
if (m_OnDirtyLayoutCallback != null) m_OnDirtyLayoutCallback(); }
///<summary> /// Mark the vertices as dirty and needing rebuilt. ///</summary> ///<remarks> /// Send a OnDirtyVertsCallback notification if any elements are registered. See RegisterDirtyVerticesCallback ///</remarks> publicvirtualvoidSetVerticesDirty() { if (!IsActive()) return;
if (m_OnDirtyVertsCallback != null) m_OnDirtyVertsCallback(); }
///<summary> /// Mark the material as dirty and needing rebuilt. ///</summary> ///<remarks> /// Send a OnDirtyMaterialCallback notification if any elements are registered. See RegisterDirtyMaterialCallback ///</remarks> publicvirtualvoidSetMaterialDirty() { if (!IsActive()) return;
if (m_OnDirtyMaterialCallback != null) m_OnDirtyMaterialCallback(); }
LayoutRebuilder.cs privatestaticvoidMarkLayoutRootForRebuild(RectTransform controller) { if (controller == null) return;
var rebuilder = s_Rebuilders.Get(); rebuilder.Initialize(controller); if (!CanvasUpdateRegistry.TryRegisterCanvasElementForLayoutRebuild(rebuilder)) s_Rebuilders.Release(rebuilder); }
CanvasUpdateRegistry.cs ///<summary> /// Try and add the given element to the layout rebuild list. ///</summary> ///<param name="element">The element that is needing rebuilt.</param> ///<returns> /// True if the element was successfully added to the rebuilt list. /// False if either already inside a Graphic Update loop OR has already been added to the list. ///</returns> publicstaticboolTryRegisterCanvasElementForLayoutRebuild(ICanvasElement element) { return instance.InternalRegisterCanvasElementForLayoutRebuild(element); }
privateboolInternalRegisterCanvasElementForLayoutRebuild(ICanvasElement element) { if (m_LayoutRebuildQueue.Contains(element)) returnfalse;
/* TODO: this likely should be here but causes the error to show just resizing the game view (case 739376) if (m_PerformingLayoutUpdate) { Debug.LogError(string.Format("Trying to add {0} for layout rebuild while we are already inside a layout rebuild loop. This is not supported.", element)); return false; }*/
return m_LayoutRebuildQueue.AddUnique(element); }
///<summary> /// Try and add the given element to the rebuild list. /// Will not return if successfully added. ///</summary> ///<param name="element">The element that is needing rebuilt.</param> publicstaticvoidRegisterCanvasElementForGraphicRebuild(ICanvasElement element) { instance.InternalRegisterCanvasElementForGraphicRebuild(element); }
///<summary> /// Try and add the given element to the rebuild list. ///</summary> ///<param name="element">The element that is needing rebuilt.</param> ///<returns> /// True if the element was successfully added to the rebuilt list. /// False if either already inside a Graphic Update loop OR has already been added to the list. ///</returns> publicstaticboolTryRegisterCanvasElementForGraphicRebuild(ICanvasElement element) { return instance.InternalRegisterCanvasElementForGraphicRebuild(element); }
privateboolInternalRegisterCanvasElementForGraphicRebuild(ICanvasElement element) { if (m_PerformingGraphicUpdate) { Debug.LogError(string.Format("Trying to add {0} for graphic rebuild while we are already inside a graphic rebuild loop. This is not supported.", element)); returnfalse; }
///<summary> /// Rebuilds the graphic geometry and its material on the PreRender cycle. ///</summary> ///<param name="update">The current step of the rendering CanvasUpdate cycle.</param> ///<remarks> /// See CanvasUpdateRegistry for more details on the canvas update cycle. ///</remarks> publicvirtualvoidRebuild(CanvasUpdate update) { if (canvasRenderer == null || canvasRenderer.cull) return;
switch (update) { case CanvasUpdate.PreRender: if (m_VertsDirty) { UpdateGeometry(); m_VertsDirty = false; } if (m_MaterialDirty) { UpdateMaterial(); m_MaterialDirty = false; } break; } }
[Obsolete("Use OnPopulateMesh(VertexHelper vh) instead.", false)] ///<summary> /// Callback function when a UI element needs to generate vertices. Fills the vertex buffer data. ///</summary> ///<param name="m">Mesh to populate with UI data.</param> ///<remarks> /// Used by Text, UI.Image, and RawImage for example to generate vertices specific to their use case. ///</remarks> protectedvirtualvoidOnPopulateMesh(Mesh m) { OnPopulateMesh(s_VertexHelper); s_VertexHelper.FillMesh(m); }
///<summary> /// Callback function when a UI element needs to generate vertices. Fills the vertex buffer data. ///</summary> ///<param name="vh">VertexHelper utility.</param> ///<remarks> /// Used by Text, UI.Image, and RawImage for example to generate vertices specific to their use case. ///</remarks> protectedvirtualvoidOnPopulateMesh(VertexHelper vh) { var r = GetPixelAdjustedRect(); var v = new Vector4(r.x, r.y, r.x + r.width, r.y + r.height);
Color32 color32 = color; vh.Clear(); vh.AddVert(new Vector3(v.x, v.y), color32, new Vector2(0f, 0f)); vh.AddVert(new Vector3(v.x, v.w), color32, new Vector2(0f, 1f)); vh.AddVert(new Vector3(v.z, v.w), color32, new Vector2(1f, 1f)); vh.AddVert(new Vector3(v.z, v.y), color32, new Vector2(1f, 0f));
///<summary> /// Call to update the geometry of the Graphic onto the CanvasRenderer. ///</summary> protectedvirtualvoidUpdateGeometry() { if (useLegacyMeshGeneration) { DoLegacyMeshGeneration(); } else { DoMeshGeneration(); } }
privatevoidDoMeshGeneration() { if (rectTransform != null && rectTransform.rect.width >= 0 && rectTransform.rect.height >= 0) OnPopulateMesh(s_VertexHelper); else s_VertexHelper.Clear(); // clear the vertex helper so invalid graphics dont draw.
var components = ListPool<Component>.Get(); GetComponents(typeof(IMeshModifier), components);
for (var i = 0; i < components.Count; i++) ((IMeshModifier)components[i]).ModifyMesh(s_VertexHelper);