summaryrefslogtreecommitdiff
path: root/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask
diff options
context:
space:
mode:
Diffstat (limited to 'Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask')
-rw-r--r--Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/IMask.cs11
-rw-r--r--Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/IMask.cs.meta11
-rw-r--r--Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/IMaskable.cs9
-rw-r--r--Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/IMaskable.cs.meta11
-rw-r--r--Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/Mask.cs203
-rw-r--r--Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/Mask.cs.meta11
-rw-r--r--Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/MaskUtilities.cs187
-rw-r--r--Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/MaskUtilities.cs.meta11
-rw-r--r--Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/RectMask2D.cs198
-rw-r--r--Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/RectMask2D.cs.meta11
-rw-r--r--Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/StencilMaterial.cs169
-rw-r--r--Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/StencilMaterial.cs.meta11
12 files changed, 843 insertions, 0 deletions
diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/IMask.cs b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/IMask.cs
new file mode 100644
index 0000000..ffe7aed
--- /dev/null
+++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/IMask.cs
@@ -0,0 +1,11 @@
+using System;
+
+namespace UnityEngine.UI
+{
+ [Obsolete("Not supported anymore.", true)]
+ public interface IMask
+ {
+ bool Enabled();
+ RectTransform rectTransform { get; }
+ }
+}
diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/IMask.cs.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/IMask.cs.meta
new file mode 100644
index 0000000..2eab58a
--- /dev/null
+++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/IMask.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: d54c702726ac4fa4daf18719b41de69f
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/IMaskable.cs b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/IMaskable.cs
new file mode 100644
index 0000000..8f8a28c
--- /dev/null
+++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/IMaskable.cs
@@ -0,0 +1,9 @@
+using System;
+
+namespace UnityEngine.UI
+{
+ public interface IMaskable
+ {
+ void RecalculateMasking();
+ }
+}
diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/IMaskable.cs.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/IMaskable.cs.meta
new file mode 100644
index 0000000..298aac8
--- /dev/null
+++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/IMaskable.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 5775a30dcbc6e484c8795bb7e18ada44
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
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
+
+ }
+}
diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/Mask.cs.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/Mask.cs.meta
new file mode 100644
index 0000000..50caa3d
--- /dev/null
+++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/Mask.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: bfc675de41855c44aaedb7af695ba899
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/MaskUtilities.cs b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/MaskUtilities.cs
new file mode 100644
index 0000000..6abce5a
--- /dev/null
+++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/MaskUtilities.cs
@@ -0,0 +1,187 @@
+using System.Collections.Generic;
+using UnityEngine.EventSystems;
+
+namespace UnityEngine.UI
+{
+ public class MaskUtilities
+ {
+ 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);
+ }
+
+ 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);
+ }
+
+ //从下往上找到第一个OverrideSorting的canvas或者root(即null)
+ 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;
+ }
+
+ // 返回Mask在canvas下(canvas下所有的masks下)的深度
+ 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;
+ }
+
+ // father是child的祖先节点或者father == child
+ 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;
+ }
+
+ public static RectMask2D GetRectMaskForClippable(IClippable clippable)
+ {
+ List<RectMask2D> rectMaskComponents = ListPool<RectMask2D>.Get();
+ List<Canvas> canvasComponents = ListPool<Canvas>.Get();
+ RectMask2D componentToReturn = null;
+
+ clippable.rectTransform.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.rectTransform.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;
+ }
+ }
+ return componentToReturn;
+ }
+ }
+
+ ListPool<RectMask2D>.Release(rectMaskComponents);
+ ListPool<Canvas>.Release(canvasComponents);
+
+ return componentToReturn;
+ }
+
+ 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--)
+ {
+ // 如果rectMask2D是canvas的祖先节点且这个canvas勾选了OverrideSorting,那么这个rectMask2D就会失效
+ 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);
+ }
+ }
+}
diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/MaskUtilities.cs.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/MaskUtilities.cs.meta
new file mode 100644
index 0000000..5e7829c
--- /dev/null
+++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/MaskUtilities.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 469f0aa53de5d4c4fb69e83419090a01
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/RectMask2D.cs b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/RectMask2D.cs
new file mode 100644
index 0000000..d973b34
--- /dev/null
+++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/RectMask2D.cs
@@ -0,0 +1,198 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine.EventSystems;
+
+namespace UnityEngine.UI
+{
+ [AddComponentMenu("UI/Rect Mask 2D", 13)]
+ [ExecuteInEditMode]
+ [DisallowMultipleComponent]
+ [RequireComponent(typeof(RectTransform))]
+ public class RectMask2D : UIBehaviour, IClipper, ICanvasRaycastFilter
+ {
+ [NonSerialized]
+ private readonly RectangularVertexClipper m_VertexClipper = new RectangularVertexClipper();
+
+ [NonSerialized]
+ private RectTransform m_RectTransform;
+
+ // 可裁剪的Graphics
+ [NonSerialized]
+ private HashSet<IClippable> m_ClipTargets = new HashSet<IClippable>();
+
+ [NonSerialized]
+ private bool m_ShouldRecalculateClipRects;
+
+ // 父节点的所有RectMask2D,用来算交集
+ [NonSerialized]
+ private List<RectMask2D> m_Clippers = new List<RectMask2D>();
+
+ [NonSerialized]
+ private Rect m_LastClipRectCanvasSpace;
+ [NonSerialized]
+ private bool m_LastValidClipRect;
+ [NonSerialized]
+ private bool m_ForceClip;
+
+ public Rect canvasRect
+ {
+ get
+ {
+ Canvas canvas = null;
+ var list = ListPool<Canvas>.Get();
+ gameObject.GetComponentsInParent(false, list);
+ if (list.Count > 0)
+ canvas = list[list.Count - 1];
+ ListPool<Canvas>.Release(list);
+
+ return m_VertexClipper.GetCanvasRect(rectTransform, canvas);
+ }
+ }
+
+ public RectTransform rectTransform
+ {
+ get { return m_RectTransform ?? (m_RectTransform = GetComponent<RectTransform>()); }
+ }
+
+ protected RectMask2D()
+ {}
+
+ protected override void OnEnable()
+ {
+ base.OnEnable();
+ m_ShouldRecalculateClipRects = true;
+ ClipperRegistry.Register(this);
+ MaskUtilities.Notify2DMaskStateChanged(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();
+ m_ClipTargets.Clear();
+ m_Clippers.Clear();
+ ClipperRegistry.Unregister(this);
+ MaskUtilities.Notify2DMaskStateChanged(this);
+ }
+
+#if UNITY_EDITOR
+ protected override void OnValidate()
+ {
+ base.OnValidate();
+ m_ShouldRecalculateClipRects = true;
+
+ if (!IsActive())
+ return;
+
+ MaskUtilities.Notify2DMaskStateChanged(this);
+ }
+
+#endif
+
+ public virtual bool IsRaycastLocationValid(Vector2 sp, Camera eventCamera)
+ {
+ if (!isActiveAndEnabled)
+ return true;
+
+ return RectTransformUtility.RectangleContainsScreenPoint(rectTransform, sp, eventCamera);
+ }
+
+ public virtual void PerformClipping()
+ {
+ //TODO See if an IsActive() test would work well here or whether it might cause unexpected side effects (re case 776771)
+
+ // if the parents are changed
+ // or something similar we
+ // do a recalculate here
+ if (m_ShouldRecalculateClipRects)
+ {
+ MaskUtilities.GetRectMasksForClip(this, m_Clippers);
+ m_ShouldRecalculateClipRects = false;
+ }
+
+ // 裁剪
+
+ // get the compound rects from
+ // the clippers that are valid
+ bool validRect = true;
+ Rect clipRect = Clipping.FindCullAndClipWorldRect(m_Clippers, out validRect);
+ bool clipRectChanged = clipRect != m_LastClipRectCanvasSpace;
+ if (clipRectChanged || m_ForceClip)
+ {
+ foreach (IClippable clipTarget in m_ClipTargets)
+ clipTarget.SetClipRect(clipRect, validRect);
+
+ m_LastClipRectCanvasSpace = clipRect;
+ m_LastValidClipRect = validRect;
+ }
+
+ // 剔除
+
+ foreach (IClippable clipTarget in m_ClipTargets)
+ {
+ var maskable = clipTarget as MaskableGraphic;
+ if (maskable != null && !maskable.canvasRenderer.hasMoved && !clipRectChanged)
+ continue;
+
+ clipTarget.Cull(m_LastClipRectCanvasSpace, m_LastValidClipRect);
+ }
+ }
+
+ public void AddClippable(IClippable clippable)
+ {
+ if (clippable == null)
+ return;
+ m_ShouldRecalculateClipRects = true;
+ if (!m_ClipTargets.Contains(clippable))
+ m_ClipTargets.Add(clippable);
+
+ m_ForceClip = true;
+ }
+
+ public void RemoveClippable(IClippable clippable)
+ {
+ if (clippable == null)
+ return;
+
+ m_ShouldRecalculateClipRects = true;
+ clippable.SetClipRect(new Rect(), false);
+ m_ClipTargets.Remove(clippable);
+
+ m_ForceClip = true;
+ }
+
+ protected override void OnTransformParentChanged()
+ {
+ base.OnTransformParentChanged();
+ m_ShouldRecalculateClipRects = true;
+ }
+
+ protected override void OnCanvasHierarchyChanged()
+ {
+ base.OnCanvasHierarchyChanged();
+ m_ShouldRecalculateClipRects = true;
+ }
+
+
+ #region UGUI_DEBUG
+
+ Vector3[] cornors = new Vector3[4];
+
+ void OnDrawGizmos()
+ {
+ Rect rect = rectTransform.rect;
+ Gizmos.color = Color.red;
+ rectTransform.GetWorldCorners(cornors);
+ for (int i = 0; i < cornors.Length; ++i)
+ {
+ Gizmos.DrawLine(cornors[i], cornors[(i + 1) % cornors.Length]);
+ }
+ }
+
+ #endregion
+
+ }
+}
diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/RectMask2D.cs.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/RectMask2D.cs.meta
new file mode 100644
index 0000000..3f31967
--- /dev/null
+++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/RectMask2D.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: c06d6b758f7cbc148afa25153c439510
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/StencilMaterial.cs b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/StencilMaterial.cs
new file mode 100644
index 0000000..c12f209
--- /dev/null
+++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/StencilMaterial.cs
@@ -0,0 +1,169 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine.Rendering;
+
+namespace UnityEngine.UI
+{
+ /// <summary>
+ /// Dynamic material class makes it possible to create custom materials on the fly on a per-Graphic basis,
+ /// and still have them get cleaned up correctly.
+ /// </summary>
+ public static class StencilMaterial
+ {
+ private class MatEntry
+ {
+ public Material baseMat;
+ public Material customMat;
+ public int count;
+
+ public int stencilId;
+ public StencilOp operation = StencilOp.Keep;
+ public CompareFunction compareFunction = CompareFunction.Always;
+ public int readMask;
+ public int writeMask;
+ public bool useAlphaClip;
+ public ColorWriteMask colorMask;
+ }
+
+ private static List<MatEntry> m_List = new List<MatEntry>();
+
+ [Obsolete("Use Material.Add instead.", true)]
+ public static Material Add(Material baseMat, int stencilID) { return null; }
+
+ /// <summary>
+ /// Add a new material using the specified base and stencil ID.
+ /// </summary>
+ public static Material Add(Material baseMat, int stencilID, StencilOp operation, CompareFunction compareFunction, ColorWriteMask colorWriteMask)
+ {
+ return Add(baseMat, stencilID, operation, compareFunction, colorWriteMask, 255, 255);
+ }
+
+ /// <summary>
+ /// Add a new material using the specified base and stencil ID.
+ /// </summary>
+ public static Material Add(Material baseMat, int stencilID, StencilOp operation, CompareFunction compareFunction, ColorWriteMask colorWriteMask, int readMask, int writeMask)
+ {
+ if ((stencilID <= 0 && colorWriteMask == ColorWriteMask.All) || baseMat == null)
+ return baseMat;
+
+ if (!baseMat.HasProperty("_Stencil"))
+ {
+ Debug.LogWarning("Material " + baseMat.name + " doesn't have _Stencil property", baseMat);
+ return baseMat;
+ }
+ if (!baseMat.HasProperty("_StencilOp"))
+ {
+ Debug.LogWarning("Material " + baseMat.name + " doesn't have _StencilOp property", baseMat);
+ return baseMat;
+ }
+ if (!baseMat.HasProperty("_StencilComp"))
+ {
+ Debug.LogWarning("Material " + baseMat.name + " doesn't have _StencilComp property", baseMat);
+ return baseMat;
+ }
+ if (!baseMat.HasProperty("_StencilReadMask"))
+ {
+ Debug.LogWarning("Material " + baseMat.name + " doesn't have _StencilReadMask property", baseMat);
+ return baseMat;
+ }
+ if (!baseMat.HasProperty("_StencilWriteMask"))
+ {
+ Debug.LogWarning("Material " + baseMat.name + " doesn't have _StencilWriteMask property", baseMat);
+ return baseMat;
+ }
+ if (!baseMat.HasProperty("_ColorMask"))
+ {
+ Debug.LogWarning("Material " + baseMat.name + " doesn't have _ColorMask property", baseMat);
+ return baseMat;
+ }
+
+ for (int i = 0; i < m_List.Count; ++i)
+ {
+ MatEntry ent = m_List[i];
+
+ if (ent.baseMat == baseMat
+ && ent.stencilId == stencilID
+ && ent.operation == operation
+ && ent.compareFunction == compareFunction
+ && ent.readMask == readMask
+ && ent.writeMask == writeMask
+ && ent.colorMask == colorWriteMask)
+ {
+ ++ent.count;
+ return ent.customMat;
+ }
+ }
+
+ var newEnt = new MatEntry();
+ newEnt.count = 1;
+ newEnt.baseMat = baseMat;
+ newEnt.customMat = new Material(baseMat);
+ newEnt.customMat.hideFlags = HideFlags.HideAndDontSave;
+ newEnt.stencilId = stencilID;
+ newEnt.operation = operation;
+ newEnt.compareFunction = compareFunction;
+ newEnt.readMask = readMask;
+ newEnt.writeMask = writeMask;
+ newEnt.colorMask = colorWriteMask;
+ newEnt.useAlphaClip = operation != StencilOp.Keep && writeMask > 0;
+
+ newEnt.customMat.name = string.Format("Stencil Id:{0}, Op:{1}, Comp:{2}, WriteMask:{3}, ReadMask:{4}, ColorMask:{5} AlphaClip:{6} ({7})", stencilID, operation, compareFunction, writeMask, readMask, colorWriteMask, newEnt.useAlphaClip, baseMat.name);
+
+ newEnt.customMat.SetInt("_Stencil", stencilID);
+ newEnt.customMat.SetInt("_StencilOp", (int)operation);
+ newEnt.customMat.SetInt("_StencilComp", (int)compareFunction);
+ newEnt.customMat.SetInt("_StencilReadMask", readMask);
+ newEnt.customMat.SetInt("_StencilWriteMask", writeMask);
+ newEnt.customMat.SetInt("_ColorMask", (int)colorWriteMask);
+
+ // left for backwards compatability
+ if (newEnt.customMat.HasProperty("_UseAlphaClip"))
+ newEnt.customMat.SetInt("_UseAlphaClip", newEnt.useAlphaClip ? 1 : 0);
+
+ if (newEnt.useAlphaClip)
+ newEnt.customMat.EnableKeyword("UNITY_UI_ALPHACLIP");
+ else
+ newEnt.customMat.DisableKeyword("UNITY_UI_ALPHACLIP");
+
+ m_List.Add(newEnt);
+ return newEnt.customMat;
+ }
+
+ /// <summary>
+ /// Remove an existing material, automatically cleaning it up if it's no longer in use.
+ /// </summary>
+ public static void Remove(Material customMat)
+ {
+ if (customMat == null)
+ return;
+
+ for (int i = 0; i < m_List.Count; ++i)
+ {
+ MatEntry ent = m_List[i];
+
+ if (ent.customMat != customMat)
+ continue;
+
+ if (--ent.count == 0)
+ {
+ Misc.DestroyImmediate(ent.customMat);
+ ent.baseMat = null;
+ m_List.RemoveAt(i);
+ }
+ return;
+ }
+ }
+
+ public static void ClearAll()
+ {
+ for (int i = 0; i < m_List.Count; ++i)
+ {
+ MatEntry ent = m_List[i];
+
+ Misc.DestroyImmediate(ent.customMat);
+ ent.baseMat = null;
+ }
+ m_List.Clear();
+ }
+ }
+}
diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/StencilMaterial.cs.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/StencilMaterial.cs.meta
new file mode 100644
index 0000000..3fd6a69
--- /dev/null
+++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/StencilMaterial.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 2d445d28188ffd745990df17f1ce8914
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant: