summaryrefslogtreecommitdiff
path: root/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask
diff options
context:
space:
mode:
authorchai <chaifix@163.com>2021-04-07 19:10:30 +0800
committerchai <chaifix@163.com>2021-04-07 19:10:30 +0800
commite7dfbec8e8634e767d78959941daf71a96e021cf (patch)
tree58895a7c60df0bd3f316e6461051eabd1c0a51e1 /Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask
parentff5a3fbf31db349db11bbc5c60ba199d26780f19 (diff)
*移动目录
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.cs166
-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.cs182
-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/MaskableGraphic.cs229
-rw-r--r--Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/MaskableGraphic.cs.meta11
-rw-r--r--Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/RectMask2D.cs173
-rw-r--r--Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/RectMask2D.cs.meta11
12 files changed, 836 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..39dc291
--- /dev/null
+++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/Mask.cs
@@ -0,0 +1,166 @@
+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)
+ {
+ 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)
+ {
+ 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;
+ }
+ }
+}
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..c975dc6
--- /dev/null
+++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/MaskUtilities.cs
@@ -0,0 +1,182 @@
+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);
+ }
+
+ 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;
+ }
+
+ 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;
+ }
+
+ 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--)
+ {
+ 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/MaskableGraphic.cs b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/MaskableGraphic.cs
new file mode 100644
index 0000000..4995dc1
--- /dev/null
+++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/MaskableGraphic.cs
@@ -0,0 +1,229 @@
+using System;
+using UnityEngine.Events;
+using UnityEngine.Rendering;
+
+namespace UnityEngine.UI
+{
+ public abstract class MaskableGraphic : Graphic, IClippable, IMaskable, IMaterialModifier
+ {
+ [NonSerialized]
+ protected bool m_ShouldRecalculateStencil = true;
+
+ [NonSerialized]
+ protected Material m_MaskMaterial;
+
+ [NonSerialized]
+ private RectMask2D m_ParentMask;
+
+ // m_Maskable is whether this graphic is allowed to be masked or not. It has the matching public property maskable.
+ // The default for m_Maskable is true, so graphics under a mask are masked out of the box.
+ // The maskable property can be turned off from script by the user if masking is not desired.
+ // m_IncludeForMasking is whether we actually consider this graphic for masking or not - this is an implementation detail.
+ // m_IncludeForMasking should only be true if m_Maskable is true AND a parent of the graphic has an IMask component.
+ // Things would still work correctly if m_IncludeForMasking was always true when m_Maskable is, but performance would suffer.
+ [NonSerialized]
+ private bool m_Maskable = true;
+
+ [NonSerialized]
+ [Obsolete("Not used anymore.", true)]
+ protected bool m_IncludeForMasking = false;
+
+ [Serializable]
+ public class CullStateChangedEvent : UnityEvent<bool> {}
+
+ // Event delegates triggered on click.
+ [SerializeField]
+ private CullStateChangedEvent m_OnCullStateChanged = new CullStateChangedEvent();
+
+ public CullStateChangedEvent onCullStateChanged
+ {
+ get { return m_OnCullStateChanged; }
+ set { m_OnCullStateChanged = value; }
+ }
+
+ public bool maskable
+ {
+ get { return m_Maskable; }
+ set
+ {
+ if (value == m_Maskable)
+ return;
+ m_Maskable = value;
+ m_ShouldRecalculateStencil = true;
+ SetMaterialDirty();
+ }
+ }
+
+ [NonSerialized]
+ [Obsolete("Not used anymore", true)]
+ protected bool m_ShouldRecalculate = true;
+
+ [NonSerialized]
+ protected int m_StencilValue;
+
+ public virtual Material GetModifiedMaterial(Material baseMaterial)
+ {
+ var toUse = baseMaterial;
+
+ if (m_ShouldRecalculateStencil)
+ {
+ var rootCanvas = MaskUtilities.FindRootSortOverrideCanvas(transform);
+ m_StencilValue = maskable ? MaskUtilities.GetStencilDepth(transform, rootCanvas) : 0;
+ m_ShouldRecalculateStencil = false;
+ }
+
+ // if we have a enabled Mask component then it will
+ // generate the mask material. This is an optimisation
+ // it adds some coupling between components though :(
+ Mask maskComponent = GetComponent<Mask>();
+ if (m_StencilValue > 0 && (maskComponent == null || !maskComponent.IsActive()))
+ {
+ var maskMat = StencilMaterial.Add(toUse, (1 << m_StencilValue) - 1, StencilOp.Keep, CompareFunction.Equal, ColorWriteMask.All, (1 << m_StencilValue) - 1, 0);
+ StencilMaterial.Remove(m_MaskMaterial);
+ m_MaskMaterial = maskMat;
+ toUse = m_MaskMaterial;
+ }
+ return toUse;
+ }
+
+ public virtual void Cull(Rect clipRect, bool validRect)
+ {
+ var cull = !validRect || !clipRect.Overlaps(rootCanvasRect, true);
+ UpdateCull(cull);
+ }
+
+ private void UpdateCull(bool cull)
+ {
+ var cullingChanged = canvasRenderer.cull != cull;
+ canvasRenderer.cull = cull;
+
+ if (cullingChanged)
+ {
+ UISystemProfilerApi.AddMarker("MaskableGraphic.cullingChanged", this);
+ m_OnCullStateChanged.Invoke(cull);
+ SetVerticesDirty();
+ }
+ }
+
+ public virtual void SetClipRect(Rect clipRect, bool validRect)
+ {
+ if (validRect)
+ canvasRenderer.EnableRectClipping(clipRect);
+ else
+ canvasRenderer.DisableRectClipping();
+ }
+
+ protected override void OnEnable()
+ {
+ base.OnEnable();
+ m_ShouldRecalculateStencil = true;
+ UpdateClipParent();
+ SetMaterialDirty();
+
+ if (GetComponent<Mask>() != null)
+ {
+ MaskUtilities.NotifyStencilStateChanged(this);
+ }
+ }
+
+ protected override void OnDisable()
+ {
+ base.OnDisable();
+ m_ShouldRecalculateStencil = true;
+ SetMaterialDirty();
+ UpdateClipParent();
+ StencilMaterial.Remove(m_MaskMaterial);
+ m_MaskMaterial = null;
+
+ if (GetComponent<Mask>() != null)
+ {
+ MaskUtilities.NotifyStencilStateChanged(this);
+ }
+ }
+
+#if UNITY_EDITOR
+ protected override void OnValidate()
+ {
+ base.OnValidate();
+ m_ShouldRecalculateStencil = true;
+ UpdateClipParent();
+ SetMaterialDirty();
+ }
+
+#endif
+
+ protected override void OnTransformParentChanged()
+ {
+ base.OnTransformParentChanged();
+
+ if (!isActiveAndEnabled)
+ return;
+
+ m_ShouldRecalculateStencil = true;
+ UpdateClipParent();
+ SetMaterialDirty();
+ }
+
+ [Obsolete("Not used anymore.", true)]
+ public virtual void ParentMaskStateChanged() {}
+
+ protected override void OnCanvasHierarchyChanged()
+ {
+ base.OnCanvasHierarchyChanged();
+
+ if (!isActiveAndEnabled)
+ return;
+
+ m_ShouldRecalculateStencil = true;
+ UpdateClipParent();
+ SetMaterialDirty();
+ }
+
+ readonly Vector3[] m_Corners = new Vector3[4];
+ private Rect rootCanvasRect
+ {
+ get
+ {
+ rectTransform.GetWorldCorners(m_Corners);
+
+ if (canvas)
+ {
+ Canvas rootCanvas = canvas.rootCanvas;
+ for (int i = 0; i < 4; ++i)
+ m_Corners[i] = rootCanvas.transform.InverseTransformPoint(m_Corners[i]);
+ }
+
+ return new Rect(m_Corners[0].x, m_Corners[0].y, m_Corners[2].x - m_Corners[0].x, m_Corners[2].y - m_Corners[0].y);
+ }
+ }
+
+ private void UpdateClipParent()
+ {
+ var newParent = (maskable && IsActive()) ? MaskUtilities.GetRectMaskForClippable(this) : null;
+
+ // if the new parent is different OR is now inactive
+ if (m_ParentMask != null && (newParent != m_ParentMask || !newParent.IsActive()))
+ {
+ m_ParentMask.RemoveClippable(this);
+ UpdateCull(false);
+ }
+
+ // don't re-add it if the newparent is inactive
+ if (newParent != null && newParent.IsActive())
+ newParent.AddClippable(this);
+
+ m_ParentMask = newParent;
+ }
+
+ public virtual void RecalculateClipping()
+ {
+ UpdateClipParent();
+ }
+
+ public virtual void RecalculateMasking()
+ {
+ m_ShouldRecalculateStencil = true;
+ SetMaterialDirty();
+ }
+ }
+}
diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/MaskableGraphic.cs.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/MaskableGraphic.cs.meta
new file mode 100644
index 0000000..07f0d51
--- /dev/null
+++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/MaskableGraphic.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 1316d79994e789c448714be540d28f4f
+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..87d2dbf
--- /dev/null
+++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/RectMask2D.cs
@@ -0,0 +1,173 @@
+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;
+
+ [NonSerialized]
+ private HashSet<IClippable> m_ClipTargets = new HashSet<IClippable>();
+
+ [NonSerialized]
+ private bool m_ShouldRecalculateClipRects;
+
+ [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;
+ }
+ }
+}
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: