summaryrefslogtreecommitdiff
path: root/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/Graphic.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/Graphic.cs')
-rw-r--r--Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/Graphic.cs669
1 files changed, 669 insertions, 0 deletions
diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/Graphic.cs b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/Graphic.cs
new file mode 100644
index 0000000..21acfb4
--- /dev/null
+++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/Graphic.cs
@@ -0,0 +1,669 @@
+using System;
+#if UNITY_EDITOR
+using System.Reflection;
+#endif
+using UnityEngine.Events;
+using UnityEngine.EventSystems;
+using UnityEngine.Serialization;
+using UnityEngine.UI.CoroutineTween;
+
+namespace UnityEngine.UI
+{
+ /// <summary>
+ /// Base class for all UI components that should be derived from when creating new Graphic types.
+ /// </summary>
+ [DisallowMultipleComponent]
+ [RequireComponent(typeof(CanvasRenderer))]
+ [RequireComponent(typeof(RectTransform))]
+ [ExecuteInEditMode]
+ public abstract class Graphic
+ : UIBehaviour,
+ ICanvasElement
+ {
+ static protected Material s_DefaultUI = null;
+ static protected Texture2D s_WhiteTexture = null;
+
+ /// <summary>
+ /// Default material used to draw everything if no explicit material was specified.
+ /// </summary>
+
+ static public Material defaultGraphicMaterial
+ {
+ get
+ {
+ if (s_DefaultUI == null)
+ s_DefaultUI = Canvas.GetDefaultCanvasMaterial();
+ return s_DefaultUI;
+ }
+ }
+
+ // Cached and saved values
+ [FormerlySerializedAs("m_Mat")]
+ [SerializeField] protected Material m_Material;
+
+ [SerializeField] private Color m_Color = Color.white;
+ public virtual Color color { get { return m_Color; } set { if (SetPropertyUtility.SetColor(ref m_Color, value)) SetVerticesDirty(); } }
+
+ [SerializeField] private bool m_RaycastTarget = true;
+ public virtual bool raycastTarget { get { return m_RaycastTarget; } set { m_RaycastTarget = value; } }
+
+ [NonSerialized] private RectTransform m_RectTransform;
+ [NonSerialized] private CanvasRenderer m_CanvasRender;
+ [NonSerialized] private Canvas m_Canvas;
+
+ [NonSerialized] private bool m_VertsDirty;
+ [NonSerialized] private bool m_MaterialDirty;
+
+ [NonSerialized] protected UnityAction m_OnDirtyLayoutCallback;
+ [NonSerialized] protected UnityAction m_OnDirtyVertsCallback;
+ [NonSerialized] protected UnityAction m_OnDirtyMaterialCallback;
+
+ [NonSerialized] protected static Mesh s_Mesh;
+ [NonSerialized] private static readonly VertexHelper s_VertexHelper = new VertexHelper();
+
+ // Tween controls for the Graphic
+ [NonSerialized]
+ private readonly TweenRunner<ColorTween> m_ColorTweenRunner;
+
+ protected bool useLegacyMeshGeneration { get; set; }
+
+ // Called by Unity prior to deserialization,
+ // should not be called by users
+ protected Graphic()
+ {
+ if (m_ColorTweenRunner == null)
+ m_ColorTweenRunner = new TweenRunner<ColorTween>();
+ m_ColorTweenRunner.Init(this);
+ useLegacyMeshGeneration = true;
+ }
+
+ public virtual void SetAllDirty()
+ {
+ SetLayoutDirty();
+ SetVerticesDirty();
+ SetMaterialDirty();
+ }
+
+ public virtual void SetLayoutDirty()
+ {
+ if (!IsActive())
+ return;
+
+ LayoutRebuilder.MarkLayoutForRebuild(rectTransform);
+
+ if (m_OnDirtyLayoutCallback != null)
+ m_OnDirtyLayoutCallback();
+ }
+
+ public virtual void SetVerticesDirty()
+ {
+ if (!IsActive())
+ return;
+
+ m_VertsDirty = true;
+ CanvasUpdateRegistry.RegisterCanvasElementForGraphicRebuild(this);
+
+ if (m_OnDirtyVertsCallback != null)
+ m_OnDirtyVertsCallback();
+ }
+
+ public virtual void SetMaterialDirty()
+ {
+ if (!IsActive())
+ return;
+
+ m_MaterialDirty = true;
+ CanvasUpdateRegistry.RegisterCanvasElementForGraphicRebuild(this);
+
+ if (m_OnDirtyMaterialCallback != null)
+ m_OnDirtyMaterialCallback();
+ }
+
+ protected override void OnRectTransformDimensionsChange()
+ {
+ if (gameObject.activeInHierarchy)
+ {
+ // prevent double dirtying...
+ if (CanvasUpdateRegistry.IsRebuildingLayout())
+ SetVerticesDirty();
+ else
+ {
+ SetVerticesDirty();
+ SetLayoutDirty();
+ }
+ }
+ }
+
+ protected override void OnBeforeTransformParentChanged()
+ {
+ GraphicRegistry.UnregisterGraphicForCanvas(canvas, this);
+ LayoutRebuilder.MarkLayoutForRebuild(rectTransform);
+ }
+
+ protected override void OnTransformParentChanged()
+ {
+ base.OnTransformParentChanged();
+
+ m_Canvas = null;
+
+ if (!IsActive())
+ return;
+
+ CacheCanvas();
+ GraphicRegistry.RegisterGraphicForCanvas(canvas, this);
+ SetAllDirty();
+ }
+
+ // 在hierachy里的深度,依次增加
+ /// <summary>
+ /// Absolute depth of the graphic, used by rendering and events -- lowest to highest.
+ /// </summary>
+ public int depth { get { return canvasRenderer.absoluteDepth; } }
+
+ /// <summary>
+ /// Transform gets cached for speed.
+ /// </summary>
+ public RectTransform rectTransform
+ {
+ get { return m_RectTransform ?? (m_RectTransform = GetComponent<RectTransform>()); }
+ }
+
+ public Canvas canvas
+ {
+ get
+ {
+ if (m_Canvas == null)
+ CacheCanvas();
+ return m_Canvas;
+ }
+ }
+
+ // 找到父节点中最近的canvas
+ private void CacheCanvas()
+ {
+ var list = ListPool<Canvas>.Get();
+ // 找到所有父节点中所有canvas,从里到外
+ gameObject.GetComponentsInParent(false, list);
+ if (list.Count > 0)
+ {
+ // Find the first active and enabled canvas.
+ for (int i = 0; i < list.Count; ++i)
+ {
+ if (list[i].isActiveAndEnabled)
+ {
+ m_Canvas = list[i];
+ break;
+ }
+ }
+ }
+ else
+ m_Canvas = null;
+ ListPool<Canvas>.Release(list);
+ }
+
+ /// <summary>
+ /// UI Renderer component.
+ /// </summary>
+ public CanvasRenderer canvasRenderer
+ {
+ get
+ {
+ if (m_CanvasRender == null)
+ m_CanvasRender = GetComponent<CanvasRenderer>();
+ return m_CanvasRender;
+ }
+ }
+
+ public virtual Material defaultMaterial
+ {
+ get { return defaultGraphicMaterial; }
+ }
+
+ /// <summary>
+ /// Returns the material used by this Graphic.
+ /// </summary>
+ public virtual Material material
+ {
+ get
+ {
+ return (m_Material != null) ? m_Material : defaultMaterial;
+ }
+ set
+ {
+ if (m_Material == value)
+ return;
+
+ m_Material = value;
+ SetMaterialDirty();
+ }
+ }
+
+ /// <summary>
+ /// 提交到CanvasRenderer用这个,要应用IMaterialModifier的修改结果
+ /// </summary>
+ public virtual Material materialForRendering
+ {
+ get
+ {
+ // 在这里调用IMaterialModifier的修改
+ var components = ListPool<Component>.Get();
+ GetComponents(typeof(IMaterialModifier), components);
+
+ var currentMat = material;
+ for (var i = 0; i < components.Count; i++)
+ currentMat = (components[i] as IMaterialModifier).GetModifiedMaterial(currentMat);
+ ListPool<Component>.Release(components);
+ return currentMat;
+ }
+ }
+
+ /// <summary>
+ /// Returns the texture used to draw this Graphic.
+ /// </summary>
+ public virtual Texture mainTexture
+ {
+ get
+ {
+ return s_WhiteTexture;
+ }
+ }
+
+ /// <summary>
+ /// Mark the Graphic and the canvas as having been changed.
+ /// </summary>
+ protected override void OnEnable()
+ {
+ base.OnEnable();
+ CacheCanvas();
+ GraphicRegistry.RegisterGraphicForCanvas(canvas, this);
+
+#if UNITY_EDITOR
+ GraphicRebuildTracker.TrackGraphic(this);
+#endif
+ if (s_WhiteTexture == null)
+ s_WhiteTexture = Texture2D.whiteTexture;
+
+ SetAllDirty();
+ }
+
+ /// <summary>
+ /// Clear references.
+ /// </summary>
+ protected override void OnDisable()
+ {
+#if UNITY_EDITOR
+ GraphicRebuildTracker.UnTrackGraphic(this);
+#endif
+ GraphicRegistry.UnregisterGraphicForCanvas(canvas, this);
+ CanvasUpdateRegistry.UnRegisterCanvasElementForRebuild(this);
+
+ if (canvasRenderer != null)
+ canvasRenderer.Clear();
+
+ LayoutRebuilder.MarkLayoutForRebuild(rectTransform);
+
+ base.OnDisable();
+ }
+
+ protected override void OnCanvasHierarchyChanged()
+ {
+ // Use m_Cavas so we dont auto call CacheCanvas
+ Canvas currentCanvas = m_Canvas;
+
+ // Clear the cached canvas. Will be fetched below if active.
+ m_Canvas = null;
+
+ if (!IsActive())
+ return;
+
+ CacheCanvas();
+
+ if (currentCanvas != m_Canvas)
+ {
+ GraphicRegistry.UnregisterGraphicForCanvas(currentCanvas, this);
+
+ // Only register if we are active and enabled as OnCanvasHierarchyChanged can get called
+ // during object destruction and we dont want to register ourself and then become null.
+ if (IsActive())
+ GraphicRegistry.RegisterGraphicForCanvas(canvas, this);
+ }
+ }
+
+ // canvas重建
+ public virtual void Rebuild(CanvasUpdate update)
+ {
+ if (canvasRenderer.cull)
+ return;
+
+ switch (update)
+ {
+ case CanvasUpdate.PreRender:
+ if (m_VertsDirty)
+ {
+ UpdateGeometry();
+ m_VertsDirty = false;
+ }
+ if (m_MaterialDirty)
+ {
+ UpdateMaterial();
+ m_MaterialDirty = false;
+ }
+ break;
+ }
+ }
+
+ public virtual void LayoutComplete()
+ {}
+
+ public virtual void GraphicUpdateComplete()
+ {}
+
+ /// <summary>
+ /// Update the renderer's material.
+ /// </summary>
+ protected virtual void UpdateMaterial()
+ {
+ if (!IsActive())
+ return;
+
+ canvasRenderer.materialCount = 1;
+ canvasRenderer.SetMaterial(materialForRendering, 0);
+ canvasRenderer.SetTexture(mainTexture); // 设置_MainTex,会覆盖材质上设置的_MainTex
+ }
+
+ //c 顶点重建
+ /// <summary>
+ /// Update the renderer's vertices.
+ /// </summary>
+ protected virtual void UpdateGeometry()
+ {
+ if (useLegacyMeshGeneration)
+ DoLegacyMeshGeneration();
+ else
+ DoMeshGeneration();
+ }
+
+ // 顶点重建,生成mesh
+ private void DoMeshGeneration()
+ {
+ if (rectTransform != null && rectTransform.rect.width >= 0 && rectTransform.rect.height >= 0)
+ OnPopulateMesh(s_VertexHelper); // 填充vertexHelper
+ else
+ s_VertexHelper.Clear(); // clear the vertex helper so invalid graphics dont draw.
+
+ // 可以通过实现IMeshModifer修改mesh
+ var components = ListPool<Component>.Get();
+ GetComponents(typeof(IMeshModifier), components);
+
+ for (var i = 0; i < components.Count; i++)
+ ((IMeshModifier)components[i]).ModifyMesh(s_VertexHelper);
+
+ ListPool<Component>.Release(components);
+
+ s_VertexHelper.FillMesh(workerMesh);
+
+ // 传入canvasRenderer作为mesh
+ canvasRenderer.SetMesh(workerMesh);
+ }
+
+ private void DoLegacyMeshGeneration()
+ {
+ if (rectTransform != null && rectTransform.rect.width >= 0 && rectTransform.rect.height >= 0)
+ {
+#pragma warning disable 618
+ OnPopulateMesh(workerMesh);
+#pragma warning restore 618
+ }
+ else
+ {
+ workerMesh.Clear();
+ }
+
+ // 自定义流程
+ var components = ListPool<Component>.Get();
+ GetComponents(typeof(IMeshModifier), components);
+
+ for (var i = 0; i < components.Count; i++)
+ {
+#pragma warning disable 618
+ ((IMeshModifier)components[i]).ModifyMesh(workerMesh);
+#pragma warning restore 618
+ }
+
+ ListPool<Component>.Release(components);
+ canvasRenderer.SetMesh(workerMesh);
+ }
+
+ protected static Mesh workerMesh
+ {
+ get
+ {
+ if (s_Mesh == null)
+ {
+ s_Mesh = new Mesh();
+ s_Mesh.name = "Shared UI Mesh";
+ s_Mesh.hideFlags = HideFlags.HideAndDontSave;
+ }
+ return s_Mesh;
+ }
+ }
+
+ [Obsolete("Use OnPopulateMesh instead.", true)]
+ protected virtual void OnFillVBO(System.Collections.Generic.List<UIVertex> vbo) {}
+
+ [Obsolete("Use OnPopulateMesh(VertexHelper vh) instead.", false)]
+ protected virtual void OnPopulateMesh(Mesh m)
+ {
+ OnPopulateMesh(s_VertexHelper);
+ s_VertexHelper.FillMesh(m);
+ }
+
+ /// <summary>
+ /// Fill the vertex buffer data.
+ /// </summary>
+ protected virtual void OnPopulateMesh(VertexHelper vh)
+ {
+ var r = GetPixelAdjustedRect();
+ var v = new Vector4(r.x, r.y, r.x + r.width, r.y + r.height);
+
+ Color32 color32 = color;
+ vh.Clear();
+ vh.AddVert(new Vector3(v.x, v.y), color32, new Vector2(0f, 0f));
+ vh.AddVert(new Vector3(v.x, v.w), color32, new Vector2(0f, 1f));
+ vh.AddVert(new Vector3(v.z, v.w), color32, new Vector2(1f, 1f));
+ vh.AddVert(new Vector3(v.z, v.y), color32, new Vector2(1f, 0f));
+
+ vh.AddTriangle(0, 1, 2);
+ vh.AddTriangle(2, 3, 0);
+ }
+
+#if UNITY_EDITOR
+ public virtual void OnRebuildRequested()
+ {
+ // when rebuild is requested we need to rebuild all the graphics /
+ // and associated components... The correct way to do this is by
+ // calling OnValidate... Because MB's don't have a common base class
+ // we do this via reflection. It's nasty and ugly... Editor only.
+ var mbs = gameObject.GetComponents<MonoBehaviour>();
+ foreach (var mb in mbs)
+ {
+ if (mb == null)
+ continue;
+ var methodInfo = mb.GetType().GetMethod("OnValidate", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
+ if (methodInfo != null)
+ methodInfo.Invoke(mb, null);
+ }
+ }
+
+ protected override void Reset()
+ {
+ SetAllDirty();
+ }
+
+#endif
+
+ // Call from unity if animation properties have changed
+
+ protected override void OnDidApplyAnimationProperties()
+ {
+ SetAllDirty();
+ }
+
+ /// <summary>
+ /// Make the Graphic have the native size of its content.
+ /// </summary>
+ public virtual void SetNativeSize() {}
+ public virtual bool Raycast(Vector2 sp, Camera eventCamera)
+ {
+ if (!isActiveAndEnabled)
+ return false;
+
+ var t = transform;
+ var components = ListPool<Component>.Get();
+
+ bool ignoreParentGroups = false;
+ bool continueTraversal = true;
+
+ while (t != null)
+ {
+ t.GetComponents(components);
+ for (var i = 0; i < components.Count; i++)
+ {
+ var canvas = components[i] as Canvas;
+ if (canvas != null && canvas.overrideSorting)
+ continueTraversal = false;
+
+ // 如果实现了这个接口再进一步判断一下
+ var filter = components[i] as ICanvasRaycastFilter;
+
+ if (filter == null)
+ continue;
+
+ var raycastValid = true;
+
+ var group = components[i] as CanvasGroup;
+ if (group != null)
+ {
+ if (ignoreParentGroups == false && group.ignoreParentGroups)
+ {
+ ignoreParentGroups = true;
+ raycastValid = filter.IsRaycastLocationValid(sp, eventCamera);
+ }
+ else if (!ignoreParentGroups)
+ raycastValid = filter.IsRaycastLocationValid(sp, eventCamera);
+ }
+ else
+ {
+ raycastValid = filter.IsRaycastLocationValid(sp, eventCamera);
+ }
+
+ if (!raycastValid)
+ {
+ ListPool<Component>.Release(components);
+ return false;
+ }
+ }
+ t = continueTraversal ? t.parent : null;
+ }
+ ListPool<Component>.Release(components);
+ return true;
+ }
+
+#if UNITY_EDITOR
+ protected override void OnValidate()
+ {
+ base.OnValidate();
+ SetAllDirty();
+ }
+
+#endif
+
+ public Vector2 PixelAdjustPoint(Vector2 point)
+ {
+ if (!canvas || canvas.renderMode == RenderMode.WorldSpace || canvas.scaleFactor == 0.0f || !canvas.pixelPerfect)
+ return point;
+ else
+ {
+ return RectTransformUtility.PixelAdjustPoint(point, transform, canvas);
+ }
+ }
+
+ public Rect GetPixelAdjustedRect()
+ {
+ if (!canvas || canvas.renderMode == RenderMode.WorldSpace || canvas.scaleFactor == 0.0f || !canvas.pixelPerfect)
+ return rectTransform.rect;
+ else
+ return RectTransformUtility.PixelAdjustRect(rectTransform, canvas);
+ }
+
+ public virtual void CrossFadeColor(Color targetColor, float duration, bool ignoreTimeScale, bool useAlpha)
+ {
+ CrossFadeColor(targetColor, duration, ignoreTimeScale, useAlpha, true);
+ }
+
+ public virtual void CrossFadeColor(Color targetColor, float duration, bool ignoreTimeScale, bool useAlpha, bool useRGB)
+ {
+ if (canvasRenderer == null || (!useRGB && !useAlpha))
+ return;
+
+ Color currentColor = canvasRenderer.GetColor();
+ if (currentColor.Equals(targetColor))
+ {
+ m_ColorTweenRunner.StopTween();
+ return;
+ }
+
+ ColorTween.ColorTweenMode mode = (useRGB && useAlpha ?
+ ColorTween.ColorTweenMode.All :
+ (useRGB ? ColorTween.ColorTweenMode.RGB : ColorTween.ColorTweenMode.Alpha));
+
+ var colorTween = new ColorTween {duration = duration, startColor = canvasRenderer.GetColor(), targetColor = targetColor};
+ colorTween.AddOnChangedCallback(canvasRenderer.SetColor);
+ colorTween.ignoreTimeScale = ignoreTimeScale;
+ colorTween.tweenMode = mode;
+ m_ColorTweenRunner.StartTween(colorTween);
+ }
+
+ static private Color CreateColorFromAlpha(float alpha)
+ {
+ var alphaColor = Color.black;
+ alphaColor.a = alpha;
+ return alphaColor;
+ }
+
+ public virtual void CrossFadeAlpha(float alpha, float duration, bool ignoreTimeScale)
+ {
+ CrossFadeColor(CreateColorFromAlpha(alpha), duration, ignoreTimeScale, true, false);
+ }
+
+ public void RegisterDirtyLayoutCallback(UnityAction action)
+ {
+ m_OnDirtyLayoutCallback += action;
+ }
+
+ public void UnregisterDirtyLayoutCallback(UnityAction action)
+ {
+ m_OnDirtyLayoutCallback -= action;
+ }
+
+ public void RegisterDirtyVerticesCallback(UnityAction action)
+ {
+ m_OnDirtyVertsCallback += action;
+ }
+
+ public void UnregisterDirtyVerticesCallback(UnityAction action)
+ {
+ m_OnDirtyVertsCallback -= action;
+ }
+
+ public void RegisterDirtyMaterialCallback(UnityAction action)
+ {
+ m_OnDirtyMaterialCallback += action;
+ }
+
+ public void UnregisterDirtyMaterialCallback(UnityAction action)
+ {
+ m_OnDirtyMaterialCallback -= action;
+ }
+ }
+}