250 lines
		
	
	
		
			8.5 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
		
		
			
		
	
	
			250 lines
		
	
	
		
			8.5 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
|  | using UnityEngine; | |||
|  | using Unity.Profiling; | |||
|  | using UnityEngine.UI; | |||
|  | using System.Collections.Generic; | |||
|  | 
 | |||
|  | 
 | |||
|  | namespace TMPro | |||
|  | { | |||
|  | 
 | |||
|  |     public class TMP_UpdateManager | |||
|  |     { | |||
|  |         private static TMP_UpdateManager s_Instance; | |||
|  | 
 | |||
|  |         private readonly HashSet<int> m_LayoutQueueLookup = new HashSet<int>(); | |||
|  |         private readonly List<TMP_Text> m_LayoutRebuildQueue = new List<TMP_Text>(); | |||
|  | 
 | |||
|  |         private readonly HashSet<int> m_GraphicQueueLookup = new HashSet<int>(); | |||
|  |         private readonly List<TMP_Text> m_GraphicRebuildQueue = new List<TMP_Text>(); | |||
|  | 
 | |||
|  |         private readonly HashSet<int> m_InternalUpdateLookup = new HashSet<int>(); | |||
|  |         private readonly List<TMP_Text> m_InternalUpdateQueue = new List<TMP_Text>(); | |||
|  | 
 | |||
|  |         private readonly HashSet<int> m_CullingUpdateLookup = new HashSet<int>(); | |||
|  |         private readonly List<TMP_Text> m_CullingUpdateQueue = new List<TMP_Text>(); | |||
|  | 
 | |||
|  |         // Profiler Marker declarations | |||
|  |         private static ProfilerMarker k_RegisterTextObjectForUpdateMarker = new ProfilerMarker("TMP.RegisterTextObjectForUpdate"); | |||
|  |         private static ProfilerMarker k_RegisterTextElementForGraphicRebuildMarker = new ProfilerMarker("TMP.RegisterTextElementForGraphicRebuild"); | |||
|  |         private static ProfilerMarker k_RegisterTextElementForCullingUpdateMarker = new ProfilerMarker("TMP.RegisterTextElementForCullingUpdate"); | |||
|  |         private static ProfilerMarker k_UnregisterTextObjectForUpdateMarker = new ProfilerMarker("TMP.UnregisterTextObjectForUpdate"); | |||
|  |         private static ProfilerMarker k_UnregisterTextElementForGraphicRebuildMarker = new ProfilerMarker("TMP.UnregisterTextElementForGraphicRebuild"); | |||
|  | 
 | |||
|  |         /// <summary> | |||
|  |         /// Get a singleton instance of the registry | |||
|  |         /// </summary> | |||
|  |         static TMP_UpdateManager instance | |||
|  |         { | |||
|  |             get | |||
|  |             { | |||
|  |                 if (s_Instance == null) | |||
|  |                     s_Instance = new TMP_UpdateManager(); | |||
|  | 
 | |||
|  |                 return s_Instance; | |||
|  |             } | |||
|  |         } | |||
|  | 
 | |||
|  |         /// <summary> | |||
|  |         /// Register to receive rendering callbacks. | |||
|  |         /// </summary> | |||
|  |         TMP_UpdateManager() | |||
|  |         { | |||
|  |             Canvas.willRenderCanvases += DoRebuilds; | |||
|  |         } | |||
|  | 
 | |||
|  |         /// <summary> | |||
|  |         /// Function used as a replacement for LateUpdate() to handle SDF Scale updates and Legacy Animation updates. | |||
|  |         /// </summary> | |||
|  |         /// <param name="textObject"></param> | |||
|  |         internal static void RegisterTextObjectForUpdate(TMP_Text textObject) | |||
|  |         { | |||
|  |             k_RegisterTextObjectForUpdateMarker.Begin(); | |||
|  | 
 | |||
|  |             instance.InternalRegisterTextObjectForUpdate(textObject); | |||
|  | 
 | |||
|  |             k_RegisterTextObjectForUpdateMarker.End(); | |||
|  |         } | |||
|  | 
 | |||
|  |         private void InternalRegisterTextObjectForUpdate(TMP_Text textObject) | |||
|  |         { | |||
|  |             int id = textObject.GetInstanceID(); | |||
|  | 
 | |||
|  |             if (m_InternalUpdateLookup.Contains(id)) | |||
|  |                 return; | |||
|  | 
 | |||
|  |             m_InternalUpdateLookup.Add(id); | |||
|  |             m_InternalUpdateQueue.Add(textObject); | |||
|  |         } | |||
|  | 
 | |||
|  |         /// <summary> | |||
|  |         /// Function to register elements which require a layout rebuild. | |||
|  |         /// </summary> | |||
|  |         /// <param name="element"></param> | |||
|  |         public static void RegisterTextElementForLayoutRebuild(TMP_Text element) | |||
|  |         { | |||
|  |             instance.InternalRegisterTextElementForLayoutRebuild(element); | |||
|  |         } | |||
|  | 
 | |||
|  |         private void InternalRegisterTextElementForLayoutRebuild(TMP_Text element) | |||
|  |         { | |||
|  |             int id = element.GetInstanceID(); | |||
|  | 
 | |||
|  |             if (m_LayoutQueueLookup.Contains(id)) | |||
|  |                 return; | |||
|  | 
 | |||
|  |             m_LayoutQueueLookup.Add(id); | |||
|  |             m_LayoutRebuildQueue.Add(element); | |||
|  |         } | |||
|  | 
 | |||
|  |         /// <summary> | |||
|  |         /// Function to register elements which require a layout rebuild. | |||
|  |         /// </summary> | |||
|  |         /// <param name="element"></param> | |||
|  |         public static void RegisterTextElementForGraphicRebuild(TMP_Text element) | |||
|  |         { | |||
|  |             k_RegisterTextElementForGraphicRebuildMarker.Begin(); | |||
|  | 
 | |||
|  |             instance.InternalRegisterTextElementForGraphicRebuild(element); | |||
|  | 
 | |||
|  |             k_RegisterTextElementForGraphicRebuildMarker.End(); | |||
|  |         } | |||
|  | 
 | |||
|  |         private void InternalRegisterTextElementForGraphicRebuild(TMP_Text element) | |||
|  |         { | |||
|  |             int id = element.GetInstanceID(); | |||
|  | 
 | |||
|  |             if (m_GraphicQueueLookup.Contains(id)) | |||
|  |                 return; | |||
|  | 
 | |||
|  |             m_GraphicQueueLookup.Add(id); | |||
|  |             m_GraphicRebuildQueue.Add(element); | |||
|  |         } | |||
|  | 
 | |||
|  |         public static void RegisterTextElementForCullingUpdate(TMP_Text element) | |||
|  |         { | |||
|  |             k_RegisterTextElementForCullingUpdateMarker.Begin(); | |||
|  | 
 | |||
|  |             instance.InternalRegisterTextElementForCullingUpdate(element); | |||
|  | 
 | |||
|  |             k_RegisterTextElementForCullingUpdateMarker.End(); | |||
|  |         } | |||
|  | 
 | |||
|  |         private void InternalRegisterTextElementForCullingUpdate(TMP_Text element) | |||
|  |         { | |||
|  |             int id = element.GetInstanceID(); | |||
|  | 
 | |||
|  |             if (m_CullingUpdateLookup.Contains(id)) | |||
|  |                 return; | |||
|  | 
 | |||
|  |             m_CullingUpdateLookup.Add(id); | |||
|  |             m_CullingUpdateQueue.Add(element); | |||
|  |         } | |||
|  | 
 | |||
|  |         /// <summary> | |||
|  |         /// Callback which occurs just before the cam is rendered. | |||
|  |         /// </summary> | |||
|  |         void OnCameraPreCull() | |||
|  |         { | |||
|  |             DoRebuilds(); | |||
|  |         } | |||
|  | 
 | |||
|  |         /// <summary> | |||
|  |         /// Process the rebuild requests in the rebuild queues. | |||
|  |         /// </summary> | |||
|  |         void DoRebuilds() | |||
|  |         { | |||
|  |             // Handle text objects the require an update either as a result of scale changes or legacy animation. | |||
|  |             for (int i = 0; i < m_InternalUpdateQueue.Count; i++) | |||
|  |             { | |||
|  |                 m_InternalUpdateQueue[i].InternalUpdate(); | |||
|  |             } | |||
|  | 
 | |||
|  |             // Handle Layout Rebuild Phase | |||
|  |             for (int i = 0; i < m_LayoutRebuildQueue.Count; i++) | |||
|  |             { | |||
|  |                 m_LayoutRebuildQueue[i].Rebuild(CanvasUpdate.Prelayout); | |||
|  |             } | |||
|  | 
 | |||
|  |             if (m_LayoutRebuildQueue.Count > 0) | |||
|  |             { | |||
|  |                 m_LayoutRebuildQueue.Clear(); | |||
|  |                 m_LayoutQueueLookup.Clear(); | |||
|  |             } | |||
|  | 
 | |||
|  |             // Handle Graphic Rebuild Phase | |||
|  |             for (int i = 0; i < m_GraphicRebuildQueue.Count; i++) | |||
|  |             { | |||
|  |                 m_GraphicRebuildQueue[i].Rebuild(CanvasUpdate.PreRender); | |||
|  |             } | |||
|  | 
 | |||
|  |             // If there are no objects in the queue, we don't need to clear the lists again. | |||
|  |             if (m_GraphicRebuildQueue.Count > 0) | |||
|  |             { | |||
|  |                 m_GraphicRebuildQueue.Clear(); | |||
|  |                 m_GraphicQueueLookup.Clear(); | |||
|  |             } | |||
|  | 
 | |||
|  |             // Handle Culling Update | |||
|  |             for (int i = 0; i < m_CullingUpdateQueue.Count; i++) | |||
|  |             { | |||
|  |                 m_CullingUpdateQueue[i].UpdateCulling(); | |||
|  |             } | |||
|  | 
 | |||
|  |             // If there are no objects in the queue, we don't need to clear the lists again. | |||
|  |             if (m_CullingUpdateQueue.Count > 0) | |||
|  |             { | |||
|  |                 m_CullingUpdateQueue.Clear(); | |||
|  |                 m_CullingUpdateLookup.Clear(); | |||
|  |             } | |||
|  |         } | |||
|  | 
 | |||
|  |         internal static void UnRegisterTextObjectForUpdate(TMP_Text textObject) | |||
|  |         { | |||
|  |             k_UnregisterTextObjectForUpdateMarker.Begin(); | |||
|  | 
 | |||
|  |             instance.InternalUnRegisterTextObjectForUpdate(textObject); | |||
|  | 
 | |||
|  |             k_UnregisterTextObjectForUpdateMarker.End(); | |||
|  |         } | |||
|  | 
 | |||
|  |         /// <summary> | |||
|  |         /// Function to unregister elements which no longer require a rebuild. | |||
|  |         /// </summary> | |||
|  |         /// <param name="element"></param> | |||
|  |         public static void UnRegisterTextElementForRebuild(TMP_Text element) | |||
|  |         { | |||
|  |             instance.InternalUnRegisterTextElementForGraphicRebuild(element); | |||
|  |             instance.InternalUnRegisterTextElementForLayoutRebuild(element); | |||
|  |             instance.InternalUnRegisterTextObjectForUpdate(element); | |||
|  |         } | |||
|  | 
 | |||
|  |         private void InternalUnRegisterTextElementForGraphicRebuild(TMP_Text element) | |||
|  |         { | |||
|  |             k_UnregisterTextElementForGraphicRebuildMarker.Begin(); | |||
|  | 
 | |||
|  |             int id = element.GetInstanceID(); | |||
|  | 
 | |||
|  |             m_GraphicRebuildQueue.Remove(element); | |||
|  |             m_GraphicQueueLookup.Remove(id); | |||
|  | 
 | |||
|  |             k_UnregisterTextElementForGraphicRebuildMarker.End(); | |||
|  |         } | |||
|  | 
 | |||
|  |         private void InternalUnRegisterTextElementForLayoutRebuild(TMP_Text element) | |||
|  |         { | |||
|  |             int id = element.GetInstanceID(); | |||
|  | 
 | |||
|  |             m_LayoutRebuildQueue.Remove(element); | |||
|  |             m_LayoutQueueLookup.Remove(id); | |||
|  |         } | |||
|  | 
 | |||
|  |         private void InternalUnRegisterTextObjectForUpdate(TMP_Text textObject) | |||
|  |         { | |||
|  |             int id = textObject.GetInstanceID(); | |||
|  | 
 | |||
|  |             m_InternalUpdateQueue.Remove(textObject); | |||
|  |             m_InternalUpdateLookup.Remove(id); | |||
|  |         } | |||
|  |     } | |||
|  | } |