using System.Collections.Generic; using UnityEngine.UI.Collections; namespace UnityEngine.UI { /// /// Registry which maps a Graphic to the canvas it belongs to. /// public class GraphicRegistry { private static GraphicRegistry s_Instance; private readonly Dictionary> m_Graphics = new Dictionary>(); private readonly Dictionary> m_RaycastableGraphics = new Dictionary>(); protected GraphicRegistry() { // Avoid runtime generation of these types. Some platforms are AOT only and do not support // JIT. What's more we actually create a instance of the required types instead of // just declaring an unused variable which may be optimized away by some compilers (Mono vs MS). // See: 877060 System.GC.KeepAlive(new Dictionary()); System.GC.KeepAlive(new Dictionary()); System.GC.KeepAlive(new Dictionary()); } /// /// The singleton instance of the GraphicRegistry. Creates a new instance if it does not exist. /// public static GraphicRegistry instance { get { if (s_Instance == null) s_Instance = new GraphicRegistry(); return s_Instance; } } /// /// Associates a Graphic with a Canvas and stores this association in the registry. /// /// The canvas being associated with the Graphic. /// The Graphic being associated with the Canvas. public static void RegisterGraphicForCanvas(Canvas c, Graphic graphic) { if (c == null || graphic == null) return; IndexedSet graphics; instance.m_Graphics.TryGetValue(c, out graphics); if (graphics != null) { graphics.AddUnique(graphic); RegisterRaycastGraphicForCanvas(c, graphic); return; } // Dont need to AddUnique as we know its the only item in the list graphics = new IndexedSet(); graphics.Add(graphic); instance.m_Graphics.Add(c, graphics); RegisterRaycastGraphicForCanvas(c, graphic); } /// /// Associates a raycastable Graphic with a Canvas and stores this association in the registry. /// /// The canvas being associated with the Graphic. /// The Graphic being associated with the Canvas. public static void RegisterRaycastGraphicForCanvas(Canvas c, Graphic graphic) { if (c == null || graphic == null || !graphic.raycastTarget) return; IndexedSet graphics; instance.m_RaycastableGraphics.TryGetValue(c, out graphics); if (graphics != null) { graphics.AddUnique(graphic); return; } // Dont need to AddUnique as we know its the only item in the list graphics = new IndexedSet(); graphics.Add(graphic); instance.m_RaycastableGraphics.Add(c, graphics); } /// /// Dissociates a Graphic from a Canvas, removing this association from the registry. /// /// The Canvas to dissociate from the Graphic. /// The Graphic to dissociate from the Canvas. public static void UnregisterGraphicForCanvas(Canvas c, Graphic graphic) { if (c == null || graphic == null) return; IndexedSet graphics; if (instance.m_Graphics.TryGetValue(c, out graphics)) { graphics.Remove(graphic); if (graphics.Capacity == 0) instance.m_Graphics.Remove(c); UnregisterRaycastGraphicForCanvas(c, graphic); } } /// /// Dissociates a Graphic from a Canvas, removing this association from the registry. /// /// The Canvas to dissociate from the Graphic. /// The Graphic to dissociate from the Canvas. public static void UnregisterRaycastGraphicForCanvas(Canvas c, Graphic graphic) { if (c == null || graphic == null) return; IndexedSet graphics; if (instance.m_RaycastableGraphics.TryGetValue(c, out graphics)) { graphics.Remove(graphic); if (graphics.Count == 0) instance.m_RaycastableGraphics.Remove(c); } } /// /// Disables a Graphic from a Canvas, disabling this association from the registry. /// /// The Canvas to dissociate from the Graphic. /// The Graphic to dissociate from the Canvas. public static void DisableGraphicForCanvas(Canvas c, Graphic graphic) { if (c == null) return; IndexedSet graphics; if (instance.m_Graphics.TryGetValue(c, out graphics)) { graphics.DisableItem(graphic); if (graphics.Capacity == 0) instance.m_Graphics.Remove(c); DisableRaycastGraphicForCanvas(c, graphic); } } /// /// Disables the raycast for a Graphic from a Canvas, disabling this association from the registry. /// /// The Canvas to dissociate from the Graphic. /// The Graphic to dissociate from the Canvas. public static void DisableRaycastGraphicForCanvas(Canvas c, Graphic graphic) { if (c == null || !graphic.raycastTarget) return; IndexedSet graphics; if (instance.m_RaycastableGraphics.TryGetValue(c, out graphics)) { graphics.DisableItem(graphic); if (graphics.Capacity == 0) instance.m_RaycastableGraphics.Remove(c); } } private static readonly List s_EmptyList = new List(); /// /// Retrieves the list of Graphics associated with a Canvas. /// /// The Canvas to search /// Returns a list of Graphics. Returns an empty list if no Graphics are associated with the specified Canvas. public static IList GetGraphicsForCanvas(Canvas canvas) { IndexedSet graphics; if (instance.m_Graphics.TryGetValue(canvas, out graphics)) return graphics; return s_EmptyList; } /// /// Retrieves the list of Graphics that are raycastable and associated with a Canvas. /// /// The Canvas to search /// Returns a list of Graphics. Returns an empty list if no Graphics are associated with the specified Canvas. public static IList GetRaycastableGraphicsForCanvas(Canvas canvas) { IndexedSet graphics; if (instance.m_RaycastableGraphics.TryGetValue(canvas, out graphics)) return graphics; return s_EmptyList; } } }