summaryrefslogtreecommitdiff
path: root/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/RectMask2D.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/RectMask2D.cs')
-rw-r--r--Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/RectMask2D.cs198
1 files changed, 198 insertions, 0 deletions
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
+
+ }
+}