| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220 |
- using System.Collections.Generic;
- using UnityEngine.EventSystems;
- namespace UnityEngine.UI
- {
- /// <summary>
- /// Mask related utility class. This class provides masking-specific utility functions.
- /// </summary>
- public class MaskUtilities
- {
- /// <summary>
- /// Notify all IClippables under the given component that they need to recalculate clipping.
- /// </summary>
- /// <param name="mask">The object thats changed for whose children should be notified.</param>
- public static void Notify2DMaskStateChanged(Component mask)
- {
- var components = ListPool<Component>.Get();
- mask.GetComponentsInChildren(components);
- for (var i = 0; i < components.Count; i++)
- {
- if (components[i] == null || components[i].gameObject == mask.gameObject)
- continue;
- var toNotify = components[i] as IClippable;
- if (toNotify != null)
- toNotify.RecalculateClipping();
- }
- ListPool<Component>.Release(components);
- }
- /// <summary>
- /// Notify all IMaskable under the given component that they need to recalculate masking.
- /// </summary>
- /// <param name="mask">The object thats changed for whose children should be notified.</param>
- public static void NotifyStencilStateChanged(Component mask)
- {
- var components = ListPool<Component>.Get();
- mask.GetComponentsInChildren(components);
- for (var i = 0; i < components.Count; i++)
- {
- if (components[i] == null || components[i].gameObject == mask.gameObject)
- continue;
- var toNotify = components[i] as IMaskable;
- if (toNotify != null)
- toNotify.RecalculateMasking();
- }
- ListPool<Component>.Release(components);
- }
- /// <summary>
- /// Find a root Canvas.
- /// </summary>
- /// <param name="start">Transform to start the search at going up the hierarchy.</param>
- /// <returns>Finds either the most root canvas, or the first canvas that overrides sorting.</returns>
- public static Transform FindRootSortOverrideCanvas(Transform start)
- {
- var canvasList = ListPool<Canvas>.Get();
- start.GetComponentsInParent(false, canvasList);
- Canvas canvas = null;
- for (int i = 0; i < canvasList.Count; ++i)
- {
- canvas = canvasList[i];
- // We found the canvas we want to use break
- if (canvas.overrideSorting)
- break;
- }
- ListPool<Canvas>.Release(canvasList);
- return canvas != null ? canvas.transform : null;
- }
- /// <summary>
- /// Find the stencil depth for a given element.
- /// </summary>
- /// <param name="transform">The starting transform to search.</param>
- /// <param name="stopAfter">Where the search of parents should stop</param>
- /// <returns>What the proper stencil buffer index should be.</returns>
- public static int GetStencilDepth(Transform transform, Transform stopAfter)
- {
- var depth = 0;
- if (transform == stopAfter)
- return depth;
- var t = transform.parent;
- var components = ListPool<Mask>.Get();
- while (t != null)
- {
- t.GetComponents<Mask>(components);
- for (var i = 0; i < components.Count; ++i)
- {
- if (components[i] != null && components[i].MaskEnabled() && components[i].graphic.IsActive())
- {
- ++depth;
- break;
- }
- }
- if (t == stopAfter)
- break;
- t = t.parent;
- }
- ListPool<Mask>.Release(components);
- return depth;
- }
- /// <summary>
- /// Helper function to determine if the child is a descendant of father or is father.
- /// </summary>
- /// <param name="father">The transform to compare against.</param>
- /// <param name="child">The starting transform to search up the hierarchy.</param>
- /// <returns>Is child equal to father or is a descendant.</returns>
- public static bool IsDescendantOrSelf(Transform father, Transform child)
- {
- if (father == null || child == null)
- return false;
- if (father == child)
- return true;
- while (child.parent != null)
- {
- if (child.parent == father)
- return true;
- child = child.parent;
- }
- return false;
- }
- /// <summary>
- /// Find the correct RectMask2D for a given IClippable.
- /// </summary>
- /// <param name="clippable">Clippable to search from.</param>
- /// <returns>The Correct RectMask2D</returns>
- public static RectMask2D GetRectMaskForClippable(IClippable clippable)
- {
- List<RectMask2D> rectMaskComponents = ListPool<RectMask2D>.Get();
- List<Canvas> canvasComponents = ListPool<Canvas>.Get();
- RectMask2D componentToReturn = null;
- clippable.gameObject.GetComponentsInParent(false, rectMaskComponents);
- if (rectMaskComponents.Count > 0)
- {
- for (int rmi = 0; rmi < rectMaskComponents.Count; rmi++)
- {
- componentToReturn = rectMaskComponents[rmi];
- if (componentToReturn.gameObject == clippable.gameObject)
- {
- componentToReturn = null;
- continue;
- }
- if (!componentToReturn.isActiveAndEnabled)
- {
- componentToReturn = null;
- continue;
- }
- clippable.gameObject.GetComponentsInParent(false, canvasComponents);
- for (int i = canvasComponents.Count - 1; i >= 0; i--)
- {
- if (!IsDescendantOrSelf(canvasComponents[i].transform, componentToReturn.transform) && canvasComponents[i].overrideSorting)
- {
- componentToReturn = null;
- break;
- }
- }
- break;
- }
- }
- ListPool<RectMask2D>.Release(rectMaskComponents);
- ListPool<Canvas>.Release(canvasComponents);
- return componentToReturn;
- }
- /// <summary>
- /// Search for all RectMask2D that apply to the given RectMask2D (includes self).
- /// </summary>
- /// <param name="clipper">Starting clipping object.</param>
- /// <param name="masks">The list of Rect masks</param>
- public static void GetRectMasksForClip(RectMask2D clipper, List<RectMask2D> masks)
- {
- masks.Clear();
- List<Canvas> canvasComponents = ListPool<Canvas>.Get();
- List<RectMask2D> rectMaskComponents = ListPool<RectMask2D>.Get();
- clipper.transform.GetComponentsInParent(false, rectMaskComponents);
- if (rectMaskComponents.Count > 0)
- {
- clipper.transform.GetComponentsInParent(false, canvasComponents);
- for (int i = rectMaskComponents.Count - 1; i >= 0; i--)
- {
- if (!rectMaskComponents[i].IsActive())
- continue;
- bool shouldAdd = true;
- for (int j = canvasComponents.Count - 1; j >= 0; j--)
- {
- if (!IsDescendantOrSelf(canvasComponents[j].transform, rectMaskComponents[i].transform) && canvasComponents[j].overrideSorting)
- {
- shouldAdd = false;
- break;
- }
- }
- if (shouldAdd)
- masks.Add(rectMaskComponents[i]);
- }
- }
- ListPool<RectMask2D>.Release(rectMaskComponents);
- ListPool<Canvas>.Release(canvasComponents);
- }
- }
- }
|