diff options
author | chai <chaifix@163.com> | 2020-10-08 09:50:33 +0800 |
---|---|---|
committer | chai <chaifix@163.com> | 2020-10-08 09:50:33 +0800 |
commit | 00dae1bd426d892dff73a50f1c505afd1ac00a90 (patch) | |
tree | 5d75f8495406f5b8dd01595e3dd9216887996a34 /Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/CanvasUpdateRegistry.cs |
+init
Diffstat (limited to 'Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/CanvasUpdateRegistry.cs')
-rw-r--r-- | Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/CanvasUpdateRegistry.cs | 275 |
1 files changed, 275 insertions, 0 deletions
diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/CanvasUpdateRegistry.cs b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/CanvasUpdateRegistry.cs new file mode 100644 index 0000000..bc7263b --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/CanvasUpdateRegistry.cs @@ -0,0 +1,275 @@ +using System; +using System.Collections.Generic; +using UnityEngine.UI.Collections; + +namespace UnityEngine.UI +{ + public enum CanvasUpdate + { + Prelayout = 0, + Layout = 1, + PostLayout = 2, + PreRender = 3, + LatePreRender = 4, + MaxUpdateValue = 5 + } + + public interface ICanvasElement + { + void Rebuild(CanvasUpdate executing); + Transform transform { get; } + void LayoutComplete(); + void GraphicUpdateComplete(); + // due to unity overriding null check + // we need this as something may not be null + // but may be destroyed + bool IsDestroyed(); + } + + public class CanvasUpdateRegistry + { + private static CanvasUpdateRegistry s_Instance; + + private bool m_PerformingLayoutUpdate; + private bool m_PerformingGraphicUpdate; + + private readonly IndexedSet<ICanvasElement> m_LayoutRebuildQueue = new IndexedSet<ICanvasElement>(); + private readonly IndexedSet<ICanvasElement> m_GraphicRebuildQueue = new IndexedSet<ICanvasElement>(); + + protected CanvasUpdateRegistry() + { + Canvas.willRenderCanvases += PerformUpdate; + } + + public static CanvasUpdateRegistry instance + { + get + { + if (s_Instance == null) + s_Instance = new CanvasUpdateRegistry(); + return s_Instance; + } + } + + private bool ObjectValidForUpdate(ICanvasElement element) + { + var valid = element != null; + + var isUnityObject = element is Object; + if (isUnityObject) + valid = (element as Object) != null; //Here we make use of the overloaded UnityEngine.Object == null, that checks if the native object is alive. + + return valid; + } + + private void CleanInvalidItems() + { + // So MB's override the == operator for null equality, which checks + // if they are destroyed. This is fine if you are looking at a concrete + // mb, but in this case we are looking at a list of ICanvasElement + // this won't forward the == operator to the MB, but just check if the + // interface is null. IsDestroyed will return if the backend is destroyed. + + for (int i = m_LayoutRebuildQueue.Count - 1; i >= 0; --i) + { + var item = m_LayoutRebuildQueue[i]; + if (item == null) + { + m_LayoutRebuildQueue.RemoveAt(i); + continue; + } + + if (item.IsDestroyed()) + { + m_LayoutRebuildQueue.RemoveAt(i); + item.LayoutComplete(); + } + } + + for (int i = m_GraphicRebuildQueue.Count - 1; i >= 0; --i) + { + var item = m_GraphicRebuildQueue[i]; + if (item == null) + { + m_GraphicRebuildQueue.RemoveAt(i); + continue; + } + + if (item.IsDestroyed()) + { + m_GraphicRebuildQueue.RemoveAt(i); + item.GraphicUpdateComplete(); + } + } + } + + private static readonly Comparison<ICanvasElement> s_SortLayoutFunction = SortLayoutList; + private void PerformUpdate() + { + UISystemProfilerApi.BeginSample(UISystemProfilerApi.SampleType.Layout); + CleanInvalidItems(); + + m_PerformingLayoutUpdate = true; + + m_LayoutRebuildQueue.Sort(s_SortLayoutFunction); + for (int i = 0; i <= (int)CanvasUpdate.PostLayout; i++) + { + for (int j = 0; j < m_LayoutRebuildQueue.Count; j++) + { + var rebuild = instance.m_LayoutRebuildQueue[j]; + try + { + if (ObjectValidForUpdate(rebuild)) + rebuild.Rebuild((CanvasUpdate)i); + } + catch (Exception e) + { + Debug.LogException(e, rebuild.transform); + } + } + } + + for (int i = 0; i < m_LayoutRebuildQueue.Count; ++i) + m_LayoutRebuildQueue[i].LayoutComplete(); + + instance.m_LayoutRebuildQueue.Clear(); + m_PerformingLayoutUpdate = false; + + // 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(); + + instance.m_GraphicRebuildQueue.Clear(); + m_PerformingGraphicUpdate = false; + UISystemProfilerApi.EndSample(UISystemProfilerApi.SampleType.Layout); + } + + private static int ParentCount(Transform child) + { + if (child == null) + return 0; + + var parent = child.parent; + int count = 0; + while (parent != null) + { + count++; + parent = parent.parent; + } + return count; + } + + private static int SortLayoutList(ICanvasElement x, ICanvasElement y) + { + Transform t1 = x.transform; + Transform t2 = y.transform; + + return ParentCount(t1) - ParentCount(t2); + } + + public static void RegisterCanvasElementForLayoutRebuild(ICanvasElement element) + { + instance.InternalRegisterCanvasElementForLayoutRebuild(element); + } + + public static bool TryRegisterCanvasElementForLayoutRebuild(ICanvasElement element) + { + return instance.InternalRegisterCanvasElementForLayoutRebuild(element); + } + + private bool InternalRegisterCanvasElementForLayoutRebuild(ICanvasElement element) + { + if (m_LayoutRebuildQueue.Contains(element)) + return false; + + /* 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); + } + + public static void RegisterCanvasElementForGraphicRebuild(ICanvasElement element) + { + instance.InternalRegisterCanvasElementForGraphicRebuild(element); + } + + public static bool TryRegisterCanvasElementForGraphicRebuild(ICanvasElement element) + { + return instance.InternalRegisterCanvasElementForGraphicRebuild(element); + } + + private bool InternalRegisterCanvasElementForGraphicRebuild(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)); + return false; + } + + return m_GraphicRebuildQueue.AddUnique(element); + } + + public static void UnRegisterCanvasElementForRebuild(ICanvasElement element) + { + instance.InternalUnRegisterCanvasElementForLayoutRebuild(element); + instance.InternalUnRegisterCanvasElementForGraphicRebuild(element); + } + + private void InternalUnRegisterCanvasElementForLayoutRebuild(ICanvasElement element) + { + if (m_PerformingLayoutUpdate) + { + Debug.LogError(string.Format("Trying to remove {0} from rebuild list while we are already inside a rebuild loop. This is not supported.", element)); + return; + } + + element.LayoutComplete(); + instance.m_LayoutRebuildQueue.Remove(element); + } + + private void InternalUnRegisterCanvasElementForGraphicRebuild(ICanvasElement element) + { + if (m_PerformingGraphicUpdate) + { + Debug.LogError(string.Format("Trying to remove {0} from rebuild list while we are already inside a rebuild loop. This is not supported.", element)); + return; + } + element.GraphicUpdateComplete(); + instance.m_GraphicRebuildQueue.Remove(element); + } + + public static bool IsRebuildingLayout() + { + return instance.m_PerformingLayoutUpdate; + } + + public static bool IsRebuildingGraphics() + { + return instance.m_PerformingGraphicUpdate; + } + } +} |