diff options
Diffstat (limited to 'Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/Mask.cs')
-rw-r--r-- | Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/Mask.cs | 203 |
1 files changed, 203 insertions, 0 deletions
diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/Mask.cs b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/Mask.cs new file mode 100644 index 0000000..c67ec42 --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/Mask.cs @@ -0,0 +1,203 @@ +using System; +using UnityEngine; +using UnityEngine.EventSystems; +using UnityEngine.Rendering; +using UnityEngine.Serialization; + +namespace UnityEngine.UI +{ + [AddComponentMenu("UI/Mask", 13)] + [ExecuteInEditMode] + [RequireComponent(typeof(RectTransform))] + [DisallowMultipleComponent] + public class Mask : UIBehaviour, ICanvasRaycastFilter, IMaterialModifier + { + [NonSerialized] + private RectTransform m_RectTransform; + public RectTransform rectTransform + { + get { return m_RectTransform ?? (m_RectTransform = GetComponent<RectTransform>()); } + } + + [SerializeField] + [FormerlySerializedAs("m_ShowGraphic")] + private bool m_ShowMaskGraphic = true; + 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; + 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(); + } + + 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; + } + + 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) + 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) // 不支持8层及以上的mask, 0-7支持,这是因为stencilRef和stencilMask只有一个字节 + { + Debug.LogError("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) // 最上层的mask + {
+ // Ref = 1
+ // Op = Replace
+ // Func = Always
+ // ReadMask = 255
+ // WriteMask = 255
+ var maskMaterial = StencilMaterial.Add(baseMaterial, 1, StencilOp.Replace, CompareFunction.Always, m_ShowMaskGraphic ? ColorWriteMask.All : 0); + StencilMaterial.Remove(m_MaskMaterial); + m_MaskMaterial = maskMaterial;
+
+ // Ref = 1
+ // Op = Zero
+ // Func = Always
+ // ReadMask = 255
+ // WriteMask = 255
+ 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; + } + + // Ref = desiredStencilBit | (desiredStencilBit - 1) + // Op = Replace + // Func = Equal + // ReadMask = desiredStencilBit - 1 + // WriteMask = desiredStencilBit | (desiredStencilBit - 1) + + //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; + + // Ref = desiredStencilBit - 1 + // Op = Replace + // Func = Equal + // ReadMask = desiredStencilBit - 1 + // WriteMask = desiredStencilBit | (desiredStencilBit - 1) + 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; + }
+
+
+ #region UGUI_DEBUG +
+ Vector3[] cornors = new Vector3[4];
+ + void OnDrawGizmos()
+ {
+ Rect rect = rectTransform.rect;
+ Gizmos.color = Color.yellow;
+ rectTransform.GetWorldCorners(cornors);
+ for (int i = 0; i < cornors.Length; ++i)
+ {
+ Gizmos.DrawLine(cornors[i], cornors[(i + 1) % cornors.Length]);
+ }
+ } + + #endregion + + } +} |