| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192 |
- using System;
- using UnityEngine;
- using UnityEngine.EventSystems;
- using UnityEngine.Rendering;
- using UnityEngine.Serialization;
- namespace UnityEngine.UI
- {
- [AddComponentMenu("UI/Mask", 13)]
- [ExecuteAlways]
- [RequireComponent(typeof(RectTransform))]
- [DisallowMultipleComponent]
- /// <summary>
- /// A component for masking children elements.
- /// </summary>
- /// <remarks>
- /// By using this element any children elements that have masking enabled will mask where a sibling Graphic would write 0 to the stencil buffer.
- /// </remarks>
- public class Mask : UIBehaviour, ICanvasRaycastFilter, IMaterialModifier
- {
- [NonSerialized]
- private RectTransform m_RectTransform;
- public RectTransform rectTransform
- {
- get { return m_RectTransform ?? (m_RectTransform = GetComponent<RectTransform>()); }
- }
- [SerializeField]
- private bool m_ShowMaskGraphic = true;
- /// <summary>
- /// Show the graphic that is associated with the Mask render area.
- /// </summary>
- public bool showMaskGraphic
- {
- get { return m_ShowMaskGraphic; }
- set
- {
- if (m_ShowMaskGraphic == value)
- return;
- m_ShowMaskGraphic = value;
- if (graphic != null)
- graphic.SetMaterialDirty();
- }
- }
- [NonSerialized]
- private Graphic m_Graphic;
- /// <summary>
- /// The graphic associated with the Mask.
- /// </summary>
- public Graphic graphic
- {
- get { return m_Graphic ?? (m_Graphic = GetComponent<Graphic>()); }
- }
- [NonSerialized]
- private Material m_MaskMaterial;
- [NonSerialized]
- private Material m_UnmaskMaterial;
- protected Mask()
- {}
- public virtual bool MaskEnabled() { return IsActive() && graphic != null; }
- [Obsolete("Not used anymore.")]
- public virtual void OnSiblingGraphicEnabledDisabled() {}
- protected override void OnEnable()
- {
- base.OnEnable();
- if (graphic != null)
- {
- graphic.canvasRenderer.hasPopInstruction = true;
- graphic.SetMaterialDirty();
- // Default the graphic to being the maskable graphic if its found.
- if (graphic is MaskableGraphic)
- (graphic as MaskableGraphic).isMaskingGraphic = true;
- }
- MaskUtilities.NotifyStencilStateChanged(this);
- }
- protected override void OnDisable()
- {
- // we call base OnDisable first here
- // as we need to have the IsActive return the
- // correct value when we notify the children
- // that the mask state has changed.
- base.OnDisable();
- if (graphic != null)
- {
- graphic.SetMaterialDirty();
- graphic.canvasRenderer.hasPopInstruction = false;
- graphic.canvasRenderer.popMaterialCount = 0;
- if (graphic is MaskableGraphic)
- (graphic as MaskableGraphic).isMaskingGraphic = false;
- }
- StencilMaterial.Remove(m_MaskMaterial);
- m_MaskMaterial = null;
- StencilMaterial.Remove(m_UnmaskMaterial);
- m_UnmaskMaterial = null;
- MaskUtilities.NotifyStencilStateChanged(this);
- }
- #if UNITY_EDITOR
- protected override void OnValidate()
- {
- base.OnValidate();
- if (!IsActive())
- return;
- if (graphic != null)
- {
- // Default the graphic to being the maskable graphic if its found.
- if (graphic is MaskableGraphic)
- (graphic as MaskableGraphic).isMaskingGraphic = true;
- graphic.SetMaterialDirty();
- }
- MaskUtilities.NotifyStencilStateChanged(this);
- }
- #endif
- public virtual bool IsRaycastLocationValid(Vector2 sp, Camera eventCamera)
- {
- if (!isActiveAndEnabled)
- return true;
- return RectTransformUtility.RectangleContainsScreenPoint(rectTransform, sp, eventCamera);
- }
- /// Stencil calculation time!
- public virtual Material GetModifiedMaterial(Material baseMaterial)
- {
- if (!MaskEnabled())
- return baseMaterial;
- var rootSortCanvas = MaskUtilities.FindRootSortOverrideCanvas(transform);
- var stencilDepth = MaskUtilities.GetStencilDepth(transform, rootSortCanvas);
- if (stencilDepth >= 8)
- {
- Debug.LogWarning("Attempting to use a stencil mask with depth > 8", gameObject);
- return baseMaterial;
- }
- int desiredStencilBit = 1 << stencilDepth;
- // if we are at the first level...
- // we want to destroy what is there
- if (desiredStencilBit == 1)
- {
- var maskMaterial = StencilMaterial.Add(baseMaterial, 1, StencilOp.Replace, CompareFunction.Always, m_ShowMaskGraphic ? ColorWriteMask.All : 0);
- StencilMaterial.Remove(m_MaskMaterial);
- m_MaskMaterial = maskMaterial;
- var unmaskMaterial = StencilMaterial.Add(baseMaterial, 1, StencilOp.Zero, CompareFunction.Always, 0);
- StencilMaterial.Remove(m_UnmaskMaterial);
- m_UnmaskMaterial = unmaskMaterial;
- graphic.canvasRenderer.popMaterialCount = 1;
- graphic.canvasRenderer.SetPopMaterial(m_UnmaskMaterial, 0);
- return m_MaskMaterial;
- }
- //otherwise we need to be a bit smarter and set some read / write masks
- var maskMaterial2 = StencilMaterial.Add(baseMaterial, desiredStencilBit | (desiredStencilBit - 1), StencilOp.Replace, CompareFunction.Equal, m_ShowMaskGraphic ? ColorWriteMask.All : 0, desiredStencilBit - 1, desiredStencilBit | (desiredStencilBit - 1));
- StencilMaterial.Remove(m_MaskMaterial);
- m_MaskMaterial = maskMaterial2;
- graphic.canvasRenderer.hasPopInstruction = true;
- var unmaskMaterial2 = StencilMaterial.Add(baseMaterial, desiredStencilBit - 1, StencilOp.Replace, CompareFunction.Equal, 0, desiredStencilBit - 1, desiredStencilBit | (desiredStencilBit - 1));
- StencilMaterial.Remove(m_UnmaskMaterial);
- m_UnmaskMaterial = unmaskMaterial2;
- graphic.canvasRenderer.popMaterialCount = 1;
- graphic.canvasRenderer.SetPopMaterial(m_UnmaskMaterial, 0);
- return m_MaskMaterial;
- }
- }
- }
|