summaryrefslogtreecommitdiff
path: root/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics
diff options
context:
space:
mode:
Diffstat (limited to 'Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics')
-rw-r--r--Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/Graphic.cs669
-rw-r--r--Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/Graphic.cs.meta11
-rw-r--r--Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/GraphicRaycaster.cs290
-rw-r--r--Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/GraphicRaycaster.cs.meta11
-rw-r--r--Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/GraphicRebuildTracker.cs38
-rw-r--r--Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/GraphicRebuildTracker.cs.meta11
-rw-r--r--Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/GraphicRegistry.cs78
-rw-r--r--Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/GraphicRegistry.cs.meta11
-rw-r--r--Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/IGraphicEnabledDisabled.cs10
-rw-r--r--Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/IGraphicEnabledDisabled.cs.meta11
-rw-r--r--Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/Image.cs1171
-rw-r--r--Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/Image.cs.meta11
-rw-r--r--Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/MaskableGraphic.cs235
-rw-r--r--Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/MaskableGraphic.cs.meta11
-rw-r--r--Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/RawImage.cs120
-rw-r--r--Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/RawImage.cs.meta11
-rw-r--r--Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/SpriteState.cs33
-rw-r--r--Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/SpriteState.cs.meta11
18 files changed, 2743 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;
+ }
+ }
+}
diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/Graphic.cs.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/Graphic.cs.meta
new file mode 100644
index 0000000..e02d697
--- /dev/null
+++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/Graphic.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 3acb46ac7ba14ff4e938138943716b11
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/GraphicRaycaster.cs b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/GraphicRaycaster.cs
new file mode 100644
index 0000000..303689a
--- /dev/null
+++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/GraphicRaycaster.cs
@@ -0,0 +1,290 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using UnityEngine.EventSystems;
+using UnityEngine.Serialization;
+
+namespace UnityEngine.UI
+{
+ [AddComponentMenu("Event/Graphic Raycaster")]
+ [RequireComponent(typeof(Canvas))]
+ public class GraphicRaycaster : BaseRaycaster
+ {
+ protected const int kNoEventMaskSet = -1;
+ public enum BlockingObjects
+ {
+ None = 0,
+ TwoD = 1,
+ ThreeD = 2,
+ All = 3,
+ }
+
+ public override int sortOrderPriority
+ {
+ get
+ {
+ // We need to return the sorting order here as distance will all be 0 for overlay.
+ if (canvas.renderMode == RenderMode.ScreenSpaceOverlay)
+ return canvas.sortingOrder;
+
+ return base.sortOrderPriority;
+ }
+ }
+
+ public override int renderOrderPriority
+ {
+ get
+ {
+ // We need to return the sorting order here as distance will all be 0 for overlay.
+ if (canvas.renderMode == RenderMode.ScreenSpaceOverlay)
+ return canvas.rootCanvas.renderOrder;
+
+ return base.renderOrderPriority;
+ }
+ }
+
+ [FormerlySerializedAs("ignoreReversedGraphics")]
+ [SerializeField]
+ private bool m_IgnoreReversedGraphics = true;
+ [FormerlySerializedAs("blockingObjects")]
+ [SerializeField]
+ private BlockingObjects m_BlockingObjects = BlockingObjects.None;
+
+ public bool ignoreReversedGraphics { get {return m_IgnoreReversedGraphics; } set { m_IgnoreReversedGraphics = value; } }
+ public BlockingObjects blockingObjects { get {return m_BlockingObjects; } set { m_BlockingObjects = value; } }
+
+ [SerializeField]
+ protected LayerMask m_BlockingMask = kNoEventMaskSet;
+
+ private Canvas m_Canvas;
+
+ protected GraphicRaycaster()
+ {}
+
+ private Canvas canvas
+ {
+ get
+ {
+ if (m_Canvas != null)
+ return m_Canvas;
+
+ m_Canvas = GetComponent<Canvas>();
+ return m_Canvas;
+ }
+ }
+
+ [NonSerialized] private List<Graphic> m_RaycastResults = new List<Graphic>();
+ public override void Raycast(PointerEventData eventData, List<RaycastResult> resultAppendList)
+ {
+ if (canvas == null)
+ return;
+
+ // 拿到canvas下的所有graphic
+ var canvasGraphics = GraphicRegistry.GetGraphicsForCanvas(canvas);
+ if (canvasGraphics == null || canvasGraphics.Count == 0)
+ return;
+
+ int displayIndex;
+ var currentEventCamera = eventCamera; // Propery can call Camera.main, so cache the reference
+
+ if (canvas.renderMode == RenderMode.ScreenSpaceOverlay || currentEventCamera == null)
+ displayIndex = canvas.targetDisplay;
+ else
+ displayIndex = currentEventCamera.targetDisplay;
+
+ var eventPosition = Display.RelativeMouseAt(eventData.position);
+ if (eventPosition != Vector3.zero)
+ {
+ // We support multiple display and display identification based on event position.
+
+ int eventDisplayIndex = (int)eventPosition.z;
+
+ // Discard events that are not part of this display so the user does not interact with multiple displays at once.
+ if (eventDisplayIndex != displayIndex)
+ return;
+ }
+ else
+ {
+ // The multiple display system is not supported on all platforms, when it is not supported the returned position
+ // will be all zeros so when the returned index is 0 we will default to the event data to be safe.
+ eventPosition = eventData.position;
+
+ // We dont really know in which display the event occured. We will process the event assuming it occured in our display.
+ }
+
+ // Convert to view space
+ Vector2 pos;
+ if (currentEventCamera == null)
+ {
+ // Multiple display support only when not the main display. For display 0 the reported
+ // resolution is always the desktops resolution since its part of the display API,
+ // so we use the standard none multiple display method. (case 741751)
+ float w = Screen.width;
+ float h = Screen.height;
+ if (displayIndex > 0 && displayIndex < Display.displays.Length)
+ {
+ w = Display.displays[displayIndex].systemWidth;
+ h = Display.displays[displayIndex].systemHeight;
+ }
+ pos = new Vector2(eventPosition.x / w, eventPosition.y / h);
+ }
+ else
+ pos = currentEventCamera.ScreenToViewportPoint(eventPosition);
+
+ // If it's outside the camera's viewport, do nothing
+ if (pos.x < 0f || pos.x > 1f || pos.y < 0f || pos.y > 1f)
+ return;
+
+ float hitDistance = float.MaxValue;
+
+ Ray ray = new Ray();
+
+ if (currentEventCamera != null)
+ ray = currentEventCamera.ScreenPointToRay(eventPosition);
+
+ if (canvas.renderMode != RenderMode.ScreenSpaceOverlay && blockingObjects != BlockingObjects.None)
+ {
+ float distanceToClipPlane = 100.0f;
+
+ if (currentEventCamera != null)
+ {
+ float projectionDirection = ray.direction.z;
+ distanceToClipPlane = Mathf.Approximately(0.0f, projectionDirection)
+ ? Mathf.Infinity
+ : Mathf.Abs((currentEventCamera.farClipPlane - currentEventCamera.nearClipPlane) / projectionDirection);
+ }
+
+ if (blockingObjects == BlockingObjects.ThreeD || blockingObjects == BlockingObjects.All)
+ {
+ if (ReflectionMethodsCache.Singleton.raycast3D != null)
+ {
+ var hits = ReflectionMethodsCache.Singleton.raycast3DAll(ray, distanceToClipPlane, (int)m_BlockingMask);
+ if (hits.Length > 0)
+ hitDistance = hits[0].distance;
+ }
+ }
+
+ if (blockingObjects == BlockingObjects.TwoD || blockingObjects == BlockingObjects.All)
+ {
+ if (ReflectionMethodsCache.Singleton.raycast2D != null)
+ {
+ var hits = ReflectionMethodsCache.Singleton.getRayIntersectionAll(ray, distanceToClipPlane, (int)m_BlockingMask);
+ if (hits.Length > 0)
+ hitDistance = hits[0].distance;
+ }
+ }
+ }
+
+ m_RaycastResults.Clear();
+ Raycast(canvas, currentEventCamera, eventPosition, canvasGraphics, m_RaycastResults);
+
+ int totalCount = m_RaycastResults.Count;
+ for (var index = 0; index < totalCount; index++)
+ {
+ var go = m_RaycastResults[index].gameObject;
+ bool appendGraphic = true;
+
+ if (ignoreReversedGraphics)
+ {
+ if (currentEventCamera == null)
+ {
+ // If we dont have a camera we know that we should always be facing forward
+ var dir = go.transform.rotation * Vector3.forward;
+ appendGraphic = Vector3.Dot(Vector3.forward, dir) > 0;
+ }
+ else
+ {
+ // If we have a camera compare the direction against the cameras forward.
+ var cameraFoward = currentEventCamera.transform.rotation * Vector3.forward;
+ var dir = go.transform.rotation * Vector3.forward;
+ appendGraphic = Vector3.Dot(cameraFoward, dir) > 0;
+ }
+ }
+
+ if (appendGraphic)
+ {
+ float distance = 0;
+
+ if (currentEventCamera == null || canvas.renderMode == RenderMode.ScreenSpaceOverlay)
+ distance = 0;
+ else
+ {
+ Transform trans = go.transform;
+ Vector3 transForward = trans.forward;
+ // http://geomalgorithms.com/a06-_intersect-2.html
+ distance = (Vector3.Dot(transForward, trans.position - currentEventCamera.transform.position) / Vector3.Dot(transForward, ray.direction));
+
+ // Check to see if the go is behind the camera.
+ if (distance < 0)
+ continue;
+ }
+
+ if (distance >= hitDistance)
+ continue;
+
+ var castResult = new RaycastResult
+ {
+ gameObject = go,
+ module = this,
+ distance = distance,
+ screenPosition = eventPosition,
+ index = resultAppendList.Count,
+ depth = m_RaycastResults[index].depth,
+ sortingLayer = canvas.sortingLayerID,
+ sortingOrder = canvas.sortingOrder
+ };
+ resultAppendList.Add(castResult);
+ }
+ }
+ }
+
+ public override Camera eventCamera
+ {
+ get
+ {
+ if (canvas.renderMode == RenderMode.ScreenSpaceOverlay || (canvas.renderMode == RenderMode.ScreenSpaceCamera && canvas.worldCamera == null))
+ return null;
+
+ return canvas.worldCamera != null ? canvas.worldCamera : Camera.main;
+ }
+ }
+
+ //
+ /// <summary>
+ /// Perform a raycast into the screen and collect all graphics underneath it.
+ /// </summary>
+ [NonSerialized] static readonly List<Graphic> s_SortedGraphics = new List<Graphic>();
+ private static void Raycast(Canvas canvas, Camera eventCamera, Vector2 pointerPosition, IList<Graphic> foundGraphics, List<Graphic> results)
+ {
+ // Debug.Log("ttt" + pointerPoision + ":::" + camera);
+ // Necessary for the event system
+ int totalCount = foundGraphics.Count;
+ for (int i = 0; i < totalCount; ++i)
+ {
+ Graphic graphic = foundGraphics[i];
+
+ // -1 means it hasn't been processed by the canvas, which means it isn't actually drawn
+ if (graphic.depth == -1 || !graphic.raycastTarget || graphic.canvasRenderer.cull)
+ continue;
+
+ if (!RectTransformUtility.RectangleContainsScreenPoint(graphic.rectTransform, pointerPosition, eventCamera))
+ continue;
+
+ if (graphic.Raycast(pointerPosition, eventCamera))
+ {
+ s_SortedGraphics.Add(graphic);
+ }
+ }
+
+ // 从高到低,所以会以深度优先。越深的越先响应。
+ s_SortedGraphics.Sort((g1, g2) => g2.depth.CompareTo(g1.depth));
+ // StringBuilder cast = new StringBuilder();
+ totalCount = s_SortedGraphics.Count;
+ for (int i = 0; i < totalCount; ++i)
+ results.Add(s_SortedGraphics[i]);
+ // Debug.Log (cast.ToString());
+
+ s_SortedGraphics.Clear();
+ }
+ }
+}
diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/GraphicRaycaster.cs.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/GraphicRaycaster.cs.meta
new file mode 100644
index 0000000..d51fee9
--- /dev/null
+++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/GraphicRaycaster.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 0dc7198a94080b64e9e51e6f934b3e35
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/GraphicRebuildTracker.cs b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/GraphicRebuildTracker.cs
new file mode 100644
index 0000000..c081269
--- /dev/null
+++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/GraphicRebuildTracker.cs
@@ -0,0 +1,38 @@
+#if UNITY_EDITOR
+using System.Collections.Generic;
+using UnityEngine.UI.Collections;
+
+namespace UnityEngine.UI
+{
+ public static class GraphicRebuildTracker
+ {
+ static IndexedSet<Graphic> m_Tracked = new IndexedSet<Graphic>();
+ static bool s_Initialized;
+
+ public static void TrackGraphic(Graphic g)
+ {
+ if (!s_Initialized)
+ {
+ CanvasRenderer.onRequestRebuild += OnRebuildRequested;
+ s_Initialized = true;
+ }
+
+ m_Tracked.AddUnique(g);
+ }
+
+ public static void UnTrackGraphic(Graphic g)
+ {
+ m_Tracked.Remove(g);
+ }
+
+ static void OnRebuildRequested()
+ {
+ StencilMaterial.ClearAll();
+ for (int i = 0; i < m_Tracked.Count; i++)
+ {
+ m_Tracked[i].OnRebuildRequested();
+ }
+ }
+ }
+}
+#endif // if UNITY_EDITOR
diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/GraphicRebuildTracker.cs.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/GraphicRebuildTracker.cs.meta
new file mode 100644
index 0000000..d0fff87
--- /dev/null
+++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/GraphicRebuildTracker.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 40f1f16390b7d7842b9e0c5df6baa9d8
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/GraphicRegistry.cs b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/GraphicRegistry.cs
new file mode 100644
index 0000000..0642792
--- /dev/null
+++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/GraphicRegistry.cs
@@ -0,0 +1,78 @@
+using System.Collections.Generic;
+using UnityEngine.UI.Collections;
+
+namespace UnityEngine.UI
+{
+ // 游戏中只有一份单例
+ public class GraphicRegistry
+ {
+ private static GraphicRegistry s_Instance;
+
+ // 按Canvas分类统计Graphic
+ private readonly Dictionary<Canvas, IndexedSet<Graphic>> m_Graphics = new Dictionary<Canvas, IndexedSet<Graphic>>();
+
+ protected GraphicRegistry()
+ {
+ // This is needed for AOT on IOS. Without it the compile doesn't get the definition of the Dictionarys
+#pragma warning disable 168
+ Dictionary<Graphic, int> emptyGraphicDic;
+ Dictionary<ICanvasElement, int> emptyElementDic;
+#pragma warning restore 168
+ }
+
+ public static GraphicRegistry instance
+ {
+ get
+ {
+ if (s_Instance == null)
+ s_Instance = new GraphicRegistry();
+ return s_Instance;
+ }
+ }
+
+ public static void RegisterGraphicForCanvas(Canvas c, Graphic graphic)
+ {
+ if (c == null)
+ return;
+
+ IndexedSet<Graphic> graphics;
+ instance.m_Graphics.TryGetValue(c, out graphics);
+
+ if (graphics != null)
+ {
+ graphics.AddUnique(graphic);
+ return;
+ }
+
+ // Dont need to AddUnique as we know its the only item in the list
+ graphics = new IndexedSet<Graphic>();
+ graphics.Add(graphic);
+ instance.m_Graphics.Add(c, graphics);
+ }
+
+ public static void UnregisterGraphicForCanvas(Canvas c, Graphic graphic)
+ {
+ if (c == null)
+ return;
+
+ IndexedSet<Graphic> graphics;
+ if (instance.m_Graphics.TryGetValue(c, out graphics))
+ {
+ graphics.Remove(graphic);
+
+ if (graphics.Count == 0)
+ instance.m_Graphics.Remove(c);
+ }
+ }
+
+ private static readonly List<Graphic> s_EmptyList = new List<Graphic>();
+ public static IList<Graphic> GetGraphicsForCanvas(Canvas canvas)
+ {
+ IndexedSet<Graphic> graphics;
+ if (instance.m_Graphics.TryGetValue(canvas, out graphics))
+ return graphics;
+
+ return s_EmptyList;
+ }
+ }
+}
diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/GraphicRegistry.cs.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/GraphicRegistry.cs.meta
new file mode 100644
index 0000000..bc0ed05
--- /dev/null
+++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/GraphicRegistry.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: b0a078c41319d0f4ab759c3ad44fd733
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/IGraphicEnabledDisabled.cs b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/IGraphicEnabledDisabled.cs
new file mode 100644
index 0000000..f2becbb
--- /dev/null
+++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/IGraphicEnabledDisabled.cs
@@ -0,0 +1,10 @@
+using System;
+
+namespace UnityEngine.UI
+{
+ [Obsolete("Not supported anymore")]
+ interface IGraphicEnabledDisabled
+ {
+ void OnSiblingGraphicEnabledDisabled();
+ }
+}
diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/IGraphicEnabledDisabled.cs.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/IGraphicEnabledDisabled.cs.meta
new file mode 100644
index 0000000..24c8266
--- /dev/null
+++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/IGraphicEnabledDisabled.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: b6892dbec884b7b4482fe7cdb11bc565
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/Image.cs b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/Image.cs
new file mode 100644
index 0000000..65e0cfd
--- /dev/null
+++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/Image.cs
@@ -0,0 +1,1171 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using UnityEngine.Serialization;
+
+namespace UnityEngine.UI
+{
+ /// <summary>
+ /// Image is a textured element in the UI hierarchy.
+ /// </summary>
+
+ [AddComponentMenu("UI/Image", 11)]
+ public class Image : MaskableGraphic, ISerializationCallbackReceiver, ILayoutElement, ICanvasRaycastFilter
+ {
+ public enum Type
+ {
+ Simple,
+ Sliced,
+ Tiled,
+ Filled
+ }
+
+ public enum FillMethod
+ {
+ Horizontal,
+ Vertical,
+ Radial90,
+ Radial180,
+ Radial360,
+ }
+
+ public enum OriginHorizontal
+ {
+ Left,
+ Right,
+ }
+
+ public enum OriginVertical
+ {
+ Bottom,
+ Top,
+ }
+
+ public enum Origin90
+ {
+ BottomLeft,
+ TopLeft,
+ TopRight,
+ BottomRight,
+ }
+
+ public enum Origin180
+ {
+ Bottom,
+ Left,
+ Top,
+ Right,
+ }
+
+ public enum Origin360
+ {
+ Bottom,
+ Right,
+ Top,
+ Left,
+ }
+
+ static protected Material s_ETC1DefaultUI = null;
+
+ [FormerlySerializedAs("m_Frame")]
+ [SerializeField] private Sprite m_Sprite;
+ public Sprite sprite { get { return m_Sprite; } set { if (SetPropertyUtility.SetClass(ref m_Sprite, value)) SetAllDirty(); } }
+
+ [NonSerialized]
+ private Sprite m_OverrideSprite;
+ public Sprite overrideSprite { get { return activeSprite; } set { if (SetPropertyUtility.SetClass(ref m_OverrideSprite, value)) SetAllDirty(); } }
+
+ private Sprite activeSprite { get { return m_OverrideSprite != null ? m_OverrideSprite : sprite; } }
+
+ /// How the Image is drawn.
+ [SerializeField] private Type m_Type = Type.Simple;
+ public Type type { get { return m_Type; } set { if (SetPropertyUtility.SetStruct(ref m_Type, value)) SetVerticesDirty(); } }
+
+ [SerializeField] private bool m_PreserveAspect = false;
+ public bool preserveAspect { get { return m_PreserveAspect; } set { if (SetPropertyUtility.SetStruct(ref m_PreserveAspect, value)) SetVerticesDirty(); } }
+
+ [SerializeField] private bool m_FillCenter = true;
+ public bool fillCenter { get { return m_FillCenter; } set { if (SetPropertyUtility.SetStruct(ref m_FillCenter, value)) SetVerticesDirty(); } }
+
+ /// Filling method for filled sprites.
+ [SerializeField] private FillMethod m_FillMethod = FillMethod.Radial360;
+ public FillMethod fillMethod { get { return m_FillMethod; } set { if (SetPropertyUtility.SetStruct(ref m_FillMethod, value)) { SetVerticesDirty(); m_FillOrigin = 0; } } }
+
+ /// Amount of the Image shown. 0-1 range with 0 being nothing shown, and 1 being the full Image.
+ [Range(0, 1)]
+ [SerializeField] private float m_FillAmount = 1.0f;
+ public float fillAmount { get { return m_FillAmount; } set { if (SetPropertyUtility.SetStruct(ref m_FillAmount, Mathf.Clamp01(value))) SetVerticesDirty(); } }
+
+ /// Whether the Image should be filled clockwise (true) or counter-clockwise (false).
+ [SerializeField] private bool m_FillClockwise = true;
+ public bool fillClockwise { get { return m_FillClockwise; } set { if (SetPropertyUtility.SetStruct(ref m_FillClockwise, value)) SetVerticesDirty(); } }
+
+ /// Controls the origin point of the Fill process. Value means different things with each fill method.
+ [SerializeField] private int m_FillOrigin;
+ public int fillOrigin { get { return m_FillOrigin; } set { if (SetPropertyUtility.SetStruct(ref m_FillOrigin, value)) SetVerticesDirty(); } }
+
+ // Not serialized until we support read-enabled sprites better.
+ private float m_AlphaHitTestMinimumThreshold = 0;
+
+ [Obsolete("eventAlphaThreshold has been deprecated. Use eventMinimumAlphaThreshold instead (UnityUpgradable) -> alphaHitTestMinimumThreshold")]
+ public float eventAlphaThreshold { get { return 1 - alphaHitTestMinimumThreshold; } set { alphaHitTestMinimumThreshold = 1 - value; } }
+ public float alphaHitTestMinimumThreshold { get { return m_AlphaHitTestMinimumThreshold; } set { m_AlphaHitTestMinimumThreshold = value; } }
+
+ protected Image()
+ {
+ useLegacyMeshGeneration = false;
+ }
+
+ /// <summary>
+ /// Default material used to draw everything if no explicit material was specified.
+ /// </summary>
+
+ static public Material defaultETC1GraphicMaterial
+ {
+ get
+ {
+ if (s_ETC1DefaultUI == null)
+ s_ETC1DefaultUI = Canvas.GetETC1SupportedCanvasMaterial();
+ return s_ETC1DefaultUI;
+ }
+ }
+
+ /// <summary>
+ /// Image's texture comes from the UnityEngine.Image.
+ /// </summary>
+ public override Texture mainTexture
+ {
+ get
+ {
+ if (activeSprite == null)
+ {
+ if (material != null && material.mainTexture != null)
+ {
+ return material.mainTexture;
+ }
+ return s_WhiteTexture;
+ }
+
+ return activeSprite.texture;
+ }
+ }
+
+ /// <summary>
+ /// Whether the Image has a border to work with.
+ /// </summary>
+
+ public bool hasBorder
+ {
+ get
+ {
+ if (activeSprite != null)
+ {
+ Vector4 v = activeSprite.border;
+ return v.sqrMagnitude > 0f;
+ }
+ return false;
+ }
+ }
+
+ public float pixelsPerUnit
+ {
+ get
+ {
+ float spritePixelsPerUnit = 100;
+ if (activeSprite)
+ spritePixelsPerUnit = activeSprite.pixelsPerUnit;
+
+ float referencePixelsPerUnit = 100;
+ if (canvas)
+ referencePixelsPerUnit = canvas.referencePixelsPerUnit;
+
+ return spritePixelsPerUnit / referencePixelsPerUnit;
+ }
+ }
+
+ public override Material material
+ {
+ get
+ {
+ if (m_Material != null)
+ return m_Material;
+
+ if (activeSprite && activeSprite.associatedAlphaSplitTexture != null)
+ return defaultETC1GraphicMaterial;
+
+ return defaultMaterial;
+ }
+
+ set
+ {
+ base.material = value;
+ }
+ }
+
+ public virtual void OnBeforeSerialize()
+ {
+ //Debug.Log("OnBeforeSerialize");
+ }
+
+ // 序列化之后,即修改了序列化参数之后。校正一下结果
+ public virtual void OnAfterDeserialize()
+ {
+ if (m_FillOrigin < 0)
+ m_FillOrigin = 0;
+ else if (m_FillMethod == FillMethod.Horizontal && m_FillOrigin > 1)
+ m_FillOrigin = 0;
+ else if (m_FillMethod == FillMethod.Vertical && m_FillOrigin > 1)
+ m_FillOrigin = 0;
+ else if (m_FillOrigin > 3)
+ m_FillOrigin = 0;
+
+ m_FillAmount = Mathf.Clamp(m_FillAmount, 0f, 1f);
+ }
+
+ /// Image's dimensions used for drawing. X = left, Y = bottom, Z = right, W = top.
+ private Vector4 GetDrawingDimensions(bool shouldPreserveAspect)
+ {
+ var padding = activeSprite == null ? Vector4.zero : Sprites.DataUtility.GetPadding(activeSprite);
+ var size = activeSprite == null ? Vector2.zero : new Vector2(activeSprite.rect.width, activeSprite.rect.height);
+
+ Rect r = GetPixelAdjustedRect();
+ // Debug.Log(string.Format("r:{2}, size:{0}, padding:{1}", size, padding, r));
+
+ int spriteW = Mathf.RoundToInt(size.x);
+ int spriteH = Mathf.RoundToInt(size.y);
+
+ var v = new Vector4(
+ padding.x / spriteW,
+ padding.y / spriteH,
+ (spriteW - padding.z) / spriteW,
+ (spriteH - padding.w) / spriteH);
+
+ if (shouldPreserveAspect && size.sqrMagnitude > 0.0f)
+ {
+ var spriteRatio = size.x / size.y;
+ var rectRatio = r.width / r.height;
+
+ if (spriteRatio > rectRatio)
+ {
+ var oldHeight = r.height;
+ r.height = r.width * (1.0f / spriteRatio);
+ r.y += (oldHeight - r.height) * rectTransform.pivot.y;
+ }
+ else
+ {
+ var oldWidth = r.width;
+ r.width = r.height * spriteRatio;
+ r.x += (oldWidth - r.width) * rectTransform.pivot.x;
+ }
+ }
+
+ v = new Vector4(
+ r.x + r.width * v.x,
+ r.y + r.height * v.y,
+ r.x + r.width * v.z,
+ r.y + r.height * v.w
+ );
+
+ return v;
+ }
+
+ public override void SetNativeSize()
+ {
+ if (activeSprite != null)
+ {
+ float w = activeSprite.rect.width / pixelsPerUnit;
+ float h = activeSprite.rect.height / pixelsPerUnit;
+ rectTransform.anchorMax = rectTransform.anchorMin;
+ rectTransform.sizeDelta = new Vector2(w, h);
+ SetAllDirty();
+ }
+ }
+
+ /// <summary>
+ /// Update the UI renderer mesh.
+ /// </summary>
+ protected override void OnPopulateMesh(VertexHelper toFill)
+ {
+ if (activeSprite == null)
+ {
+ base.OnPopulateMesh(toFill);
+ return;
+ }
+
+ switch (type)
+ {
+ case Type.Simple:
+ GenerateSimpleSprite(toFill, m_PreserveAspect);
+ break;
+ case Type.Sliced:
+ GenerateSlicedSprite(toFill);
+ break;
+ case Type.Tiled:
+ GenerateTiledSprite(toFill);
+ break;
+ case Type.Filled:
+ GenerateFilledSprite(toFill, m_PreserveAspect);
+ break;
+ }
+ }
+
+ /// <summary>
+ /// Update the renderer's material.
+ /// </summary>
+
+ protected override void UpdateMaterial()
+ {
+ base.UpdateMaterial();
+
+ // check if this sprite has an associated alpha texture (generated when splitting RGBA = RGB + A as two textures without alpha)
+
+ if (activeSprite == null)
+ {
+ canvasRenderer.SetAlphaTexture(null);
+ return;
+ }
+
+ //如果是ETC压缩格式,会生成一份alphaTex只保存透明度信息,不在_MainTex里
+ Texture2D alphaTex = activeSprite.associatedAlphaSplitTexture;
+
+ if (alphaTex != null)
+ {
+ canvasRenderer.SetAlphaTexture(alphaTex); // _AlphaTex
+ }
+ }
+
+ /// <summary>
+ /// Generate vertices for a simple Image.
+ /// </summary>
+ void GenerateSimpleSprite(VertexHelper vh, bool lPreserveAspect)
+ {
+ Vector4 v = GetDrawingDimensions(lPreserveAspect);
+ var uv = (activeSprite != null) ? Sprites.DataUtility.GetOuterUV(activeSprite) : Vector4.zero;
+
+ var color32 = color;
+ vh.Clear();
+ vh.AddVert(new Vector3(v.x, v.y), color32, new Vector2(uv.x, uv.y));
+ vh.AddVert(new Vector3(v.x, v.w), color32, new Vector2(uv.x, uv.w));
+ vh.AddVert(new Vector3(v.z, v.w), color32, new Vector2(uv.z, uv.w));
+ vh.AddVert(new Vector3(v.z, v.y), color32, new Vector2(uv.z, uv.y));
+
+ vh.AddTriangle(0, 1, 2);
+ vh.AddTriangle(2, 3, 0);
+ }
+
+ /// <summary>
+ /// Generate vertices for a 9-sliced Image.
+ /// </summary>
+
+ static readonly Vector2[] s_VertScratch = new Vector2[4];
+ static readonly Vector2[] s_UVScratch = new Vector2[4];
+
+ private void GenerateSlicedSprite(VertexHelper toFill)
+ {
+ if (!hasBorder)
+ {
+ GenerateSimpleSprite(toFill, false);
+ return;
+ }
+
+ Vector4 outer, inner, padding, border;
+
+ if (activeSprite != null)
+ {
+ outer = Sprites.DataUtility.GetOuterUV(activeSprite);
+ inner = Sprites.DataUtility.GetInnerUV(activeSprite);
+ padding = Sprites.DataUtility.GetPadding(activeSprite);
+ border = activeSprite.border;
+ }
+ else
+ {
+ outer = Vector4.zero;
+ inner = Vector4.zero;
+ padding = Vector4.zero;
+ border = Vector4.zero;
+ }
+
+ Rect rect = GetPixelAdjustedRect();
+ Vector4 adjustedBorders = GetAdjustedBorders(border / pixelsPerUnit, rect);
+ padding = padding / pixelsPerUnit;
+
+ s_VertScratch[0] = new Vector2(padding.x, padding.y);
+ s_VertScratch[3] = new Vector2(rect.width - padding.z, rect.height - padding.w);
+
+ s_VertScratch[1].x = adjustedBorders.x;
+ s_VertScratch[1].y = adjustedBorders.y;
+
+ s_VertScratch[2].x = rect.width - adjustedBorders.z;
+ s_VertScratch[2].y = rect.height - adjustedBorders.w;
+
+ for (int i = 0; i < 4; ++i)
+ {
+ s_VertScratch[i].x += rect.x;
+ s_VertScratch[i].y += rect.y;
+ }
+
+ s_UVScratch[0] = new Vector2(outer.x, outer.y);
+ s_UVScratch[1] = new Vector2(inner.x, inner.y);
+ s_UVScratch[2] = new Vector2(inner.z, inner.w);
+ s_UVScratch[3] = new Vector2(outer.z, outer.w);
+
+ toFill.Clear();
+
+ for (int x = 0; x < 3; ++x)
+ {
+ int x2 = x + 1;
+
+ for (int y = 0; y < 3; ++y)
+ {
+ if (!m_FillCenter && x == 1 && y == 1)
+ continue;
+
+ int y2 = y + 1;
+
+
+ AddQuad(toFill,
+ new Vector2(s_VertScratch[x].x, s_VertScratch[y].y),
+ new Vector2(s_VertScratch[x2].x, s_VertScratch[y2].y),
+ color,
+ new Vector2(s_UVScratch[x].x, s_UVScratch[y].y),
+ new Vector2(s_UVScratch[x2].x, s_UVScratch[y2].y));
+ }
+ }
+ }
+
+ /// <summary>
+ /// Generate vertices for a tiled Image.
+ /// </summary>
+
+ void GenerateTiledSprite(VertexHelper toFill)
+ {
+ Vector4 outer, inner, border;
+ Vector2 spriteSize;
+
+ if (activeSprite != null)
+ {
+ outer = Sprites.DataUtility.GetOuterUV(activeSprite);
+ inner = Sprites.DataUtility.GetInnerUV(activeSprite);
+ border = activeSprite.border;
+ spriteSize = activeSprite.rect.size;
+ }
+ else
+ {
+ outer = Vector4.zero;
+ inner = Vector4.zero;
+ border = Vector4.zero;
+ spriteSize = Vector2.one * 100;
+ }
+
+ Rect rect = GetPixelAdjustedRect();
+ float tileWidth = (spriteSize.x - border.x - border.z) / pixelsPerUnit;
+ float tileHeight = (spriteSize.y - border.y - border.w) / pixelsPerUnit;
+ border = GetAdjustedBorders(border / pixelsPerUnit, rect);
+
+ var uvMin = new Vector2(inner.x, inner.y);
+ var uvMax = new Vector2(inner.z, inner.w);
+
+ // Min to max max range for tiled region in coordinates relative to lower left corner.
+ float xMin = border.x;
+ float xMax = rect.width - border.z;
+ float yMin = border.y;
+ float yMax = rect.height - border.w;
+
+ toFill.Clear();
+ var clipped = uvMax;
+
+ // if either width is zero we cant tile so just assume it was the full width.
+ if (tileWidth <= 0)
+ tileWidth = xMax - xMin;
+
+ if (tileHeight <= 0)
+ tileHeight = yMax - yMin;
+
+ if (activeSprite != null && (hasBorder || activeSprite.packed || activeSprite.texture.wrapMode != TextureWrapMode.Repeat))
+ {
+ // Sprite has border, or is not in repeat mode, or cannot be repeated because of packing.
+ // We cannot use texture tiling so we will generate a mesh of quads to tile the texture.
+
+ // Evaluate how many vertices we will generate. Limit this number to something sane,
+ // especially since meshes can not have more than 65000 vertices.
+
+ long nTilesW = 0;
+ long nTilesH = 0;
+ if (m_FillCenter)
+ {
+ nTilesW = (long)Math.Ceiling((xMax - xMin) / tileWidth);
+ nTilesH = (long)Math.Ceiling((yMax - yMin) / tileHeight);
+
+ double nVertices = 0;
+ if (hasBorder)
+ {
+ nVertices = (nTilesW + 2.0) * (nTilesH + 2.0) * 4.0; // 4 vertices per tile
+ }
+ else
+ {
+ nVertices = nTilesW * nTilesH * 4.0; // 4 vertices per tile
+ }
+
+ if (nVertices > 65000.0)
+ {
+ Debug.LogError("Too many sprite tiles on Image \"" + name + "\". The tile size will be increased. To remove the limit on the number of tiles, convert the Sprite to an Advanced texture, remove the borders, clear the Packing tag and set the Wrap mode to Repeat.", this);
+
+ double maxTiles = 65000.0 / 4.0; // Max number of vertices is 65000; 4 vertices per tile.
+ double imageRatio;
+ if (hasBorder)
+ {
+ imageRatio = (nTilesW + 2.0) / (nTilesH + 2.0);
+ }
+ else
+ {
+ imageRatio = (double)nTilesW / nTilesH;
+ }
+
+ double targetTilesW = Math.Sqrt(maxTiles / imageRatio);
+ double targetTilesH = targetTilesW * imageRatio;
+ if (hasBorder)
+ {
+ targetTilesW -= 2;
+ targetTilesH -= 2;
+ }
+
+ nTilesW = (long)Math.Floor(targetTilesW);
+ nTilesH = (long)Math.Floor(targetTilesH);
+ tileWidth = (xMax - xMin) / nTilesW;
+ tileHeight = (yMax - yMin) / nTilesH;
+ }
+ }
+ else
+ {
+ if (hasBorder)
+ {
+ // Texture on the border is repeated only in one direction.
+ nTilesW = (long)Math.Ceiling((xMax - xMin) / tileWidth);
+ nTilesH = (long)Math.Ceiling((yMax - yMin) / tileHeight);
+ double nVertices = (nTilesH + nTilesW + 2.0 /*corners*/) * 2.0 /*sides*/ * 4.0 /*vertices per tile*/;
+ if (nVertices > 65000.0)
+ {
+ Debug.LogError("Too many sprite tiles on Image \"" + name + "\". The tile size will be increased. To remove the limit on the number of tiles, convert the Sprite to an Advanced texture, remove the borders, clear the Packing tag and set the Wrap mode to Repeat.", this);
+
+ double maxTiles = 65000.0 / 4.0; // Max number of vertices is 65000; 4 vertices per tile.
+ double imageRatio = (double)nTilesW / nTilesH;
+ double targetTilesW = (maxTiles - 4 /*corners*/) / (2 * (1.0 + imageRatio));
+ double targetTilesH = targetTilesW * imageRatio;
+
+ nTilesW = (long)Math.Floor(targetTilesW);
+ nTilesH = (long)Math.Floor(targetTilesH);
+ tileWidth = (xMax - xMin) / nTilesW;
+ tileHeight = (yMax - yMin) / nTilesH;
+ }
+ }
+ else
+ {
+ nTilesH = nTilesW = 0;
+ }
+ }
+
+ if (m_FillCenter)
+ {
+ // TODO: we could share vertices between quads. If vertex sharing is implemented. update the computation for the number of vertices accordingly.
+ for (long j = 0; j < nTilesH; j++)
+ {
+ float y1 = yMin + j * tileHeight;
+ float y2 = yMin + (j + 1) * tileHeight;
+ if (y2 > yMax)
+ {
+ clipped.y = uvMin.y + (uvMax.y - uvMin.y) * (yMax - y1) / (y2 - y1);
+ y2 = yMax;
+ }
+ clipped.x = uvMax.x;
+ for (long i = 0; i < nTilesW; i++)
+ {
+ float x1 = xMin + i * tileWidth;
+ float x2 = xMin + (i + 1) * tileWidth;
+ if (x2 > xMax)
+ {
+ clipped.x = uvMin.x + (uvMax.x - uvMin.x) * (xMax - x1) / (x2 - x1);
+ x2 = xMax;
+ }
+ AddQuad(toFill, new Vector2(x1, y1) + rect.position, new Vector2(x2, y2) + rect.position, color, uvMin, clipped);
+ }
+ }
+ }
+ if (hasBorder)
+ {
+ clipped = uvMax;
+ for (long j = 0; j < nTilesH; j++)
+ {
+ float y1 = yMin + j * tileHeight;
+ float y2 = yMin + (j + 1) * tileHeight;
+ if (y2 > yMax)
+ {
+ clipped.y = uvMin.y + (uvMax.y - uvMin.y) * (yMax - y1) / (y2 - y1);
+ y2 = yMax;
+ }
+ AddQuad(toFill,
+ new Vector2(0, y1) + rect.position,
+ new Vector2(xMin, y2) + rect.position,
+ color,
+ new Vector2(outer.x, uvMin.y),
+ new Vector2(uvMin.x, clipped.y));
+ AddQuad(toFill,
+ new Vector2(xMax, y1) + rect.position,
+ new Vector2(rect.width, y2) + rect.position,
+ color,
+ new Vector2(uvMax.x, uvMin.y),
+ new Vector2(outer.z, clipped.y));
+ }
+
+ // Bottom and top tiled border
+ clipped = uvMax;
+ for (long i = 0; i < nTilesW; i++)
+ {
+ float x1 = xMin + i * tileWidth;
+ float x2 = xMin + (i + 1) * tileWidth;
+ if (x2 > xMax)
+ {
+ clipped.x = uvMin.x + (uvMax.x - uvMin.x) * (xMax - x1) / (x2 - x1);
+ x2 = xMax;
+ }
+ AddQuad(toFill,
+ new Vector2(x1, 0) + rect.position,
+ new Vector2(x2, yMin) + rect.position,
+ color,
+ new Vector2(uvMin.x, outer.y),
+ new Vector2(clipped.x, uvMin.y));
+ AddQuad(toFill,
+ new Vector2(x1, yMax) + rect.position,
+ new Vector2(x2, rect.height) + rect.position,
+ color,
+ new Vector2(uvMin.x, uvMax.y),
+ new Vector2(clipped.x, outer.w));
+ }
+
+ // Corners
+ AddQuad(toFill,
+ new Vector2(0, 0) + rect.position,
+ new Vector2(xMin, yMin) + rect.position,
+ color,
+ new Vector2(outer.x, outer.y),
+ new Vector2(uvMin.x, uvMin.y));
+ AddQuad(toFill,
+ new Vector2(xMax, 0) + rect.position,
+ new Vector2(rect.width, yMin) + rect.position,
+ color,
+ new Vector2(uvMax.x, outer.y),
+ new Vector2(outer.z, uvMin.y));
+ AddQuad(toFill,
+ new Vector2(0, yMax) + rect.position,
+ new Vector2(xMin, rect.height) + rect.position,
+ color,
+ new Vector2(outer.x, uvMax.y),
+ new Vector2(uvMin.x, outer.w));
+ AddQuad(toFill,
+ new Vector2(xMax, yMax) + rect.position,
+ new Vector2(rect.width, rect.height) + rect.position,
+ color,
+ new Vector2(uvMax.x, uvMax.y),
+ new Vector2(outer.z, outer.w));
+ }
+ }
+ else
+ {
+ // Texture has no border, is in repeat mode and not packed. Use texture tiling.
+ Vector2 uvScale = new Vector2((xMax - xMin) / tileWidth, (yMax - yMin) / tileHeight);
+
+ if (m_FillCenter)
+ {
+ AddQuad(toFill, new Vector2(xMin, yMin) + rect.position, new Vector2(xMax, yMax) + rect.position, color, Vector2.Scale(uvMin, uvScale), Vector2.Scale(uvMax, uvScale));
+ }
+ }
+ }
+
+ static void AddQuad(VertexHelper vertexHelper, Vector3[] quadPositions, Color32 color, Vector3[] quadUVs)
+ {
+ int startIndex = vertexHelper.currentVertCount;
+
+ for (int i = 0; i < 4; ++i)
+ vertexHelper.AddVert(quadPositions[i], color, quadUVs[i]);
+
+ vertexHelper.AddTriangle(startIndex, startIndex + 1, startIndex + 2);
+ vertexHelper.AddTriangle(startIndex + 2, startIndex + 3, startIndex);
+ }
+
+ static void AddQuad(VertexHelper vertexHelper, Vector2 posMin, Vector2 posMax, Color32 color, Vector2 uvMin, Vector2 uvMax)
+ {
+ int startIndex = vertexHelper.currentVertCount;
+
+ vertexHelper.AddVert(new Vector3(posMin.x, posMin.y, 0), color, new Vector2(uvMin.x, uvMin.y));
+ vertexHelper.AddVert(new Vector3(posMin.x, posMax.y, 0), color, new Vector2(uvMin.x, uvMax.y));
+ vertexHelper.AddVert(new Vector3(posMax.x, posMax.y, 0), color, new Vector2(uvMax.x, uvMax.y));
+ vertexHelper.AddVert(new Vector3(posMax.x, posMin.y, 0), color, new Vector2(uvMax.x, uvMin.y));
+
+ vertexHelper.AddTriangle(startIndex, startIndex + 1, startIndex + 2);
+ vertexHelper.AddTriangle(startIndex + 2, startIndex + 3, startIndex);
+ }
+
+ private Vector4 GetAdjustedBorders(Vector4 border, Rect adjustedRect)
+ {
+ Rect originalRect = rectTransform.rect;
+
+ for (int axis = 0; axis <= 1; axis++)
+ {
+ float borderScaleRatio;
+
+ // The adjusted rect (adjusted for pixel correctness)
+ // may be slightly larger than the original rect.
+ // Adjust the border to match the adjustedRect to avoid
+ // small gaps between borders (case 833201).
+ if (originalRect.size[axis] != 0)
+ {
+ borderScaleRatio = adjustedRect.size[axis] / originalRect.size[axis];
+ border[axis] *= borderScaleRatio;
+ border[axis + 2] *= borderScaleRatio;
+ }
+
+ // If the rect is smaller than the combined borders, then there's not room for the borders at their normal size.
+ // In order to avoid artefacts with overlapping borders, we scale the borders down to fit.
+ float combinedBorders = border[axis] + border[axis + 2];
+ if (adjustedRect.size[axis] < combinedBorders && combinedBorders != 0)
+ {
+ borderScaleRatio = adjustedRect.size[axis] / combinedBorders;
+ border[axis] *= borderScaleRatio;
+ border[axis + 2] *= borderScaleRatio;
+ }
+ }
+ return border;
+ }
+
+ /// <summary>
+ /// Generate vertices for a filled Image.
+ /// </summary>
+
+ static readonly Vector3[] s_Xy = new Vector3[4];
+ static readonly Vector3[] s_Uv = new Vector3[4];
+ void GenerateFilledSprite(VertexHelper toFill, bool preserveAspect)
+ {
+ toFill.Clear();
+
+ if (m_FillAmount < 0.001f)
+ return;
+
+ Vector4 v = GetDrawingDimensions(preserveAspect);
+ Vector4 outer = activeSprite != null ? Sprites.DataUtility.GetOuterUV(activeSprite) : Vector4.zero;
+ UIVertex uiv = UIVertex.simpleVert;
+ uiv.color = color;
+
+ float tx0 = outer.x;
+ float ty0 = outer.y;
+ float tx1 = outer.z;
+ float ty1 = outer.w;
+
+ // Horizontal and vertical filled sprites are simple -- just end the Image prematurely
+ if (m_FillMethod == FillMethod.Horizontal || m_FillMethod == FillMethod.Vertical)
+ {
+ if (fillMethod == FillMethod.Horizontal)
+ {
+ float fill = (tx1 - tx0) * m_FillAmount;
+
+ if (m_FillOrigin == 1)
+ {
+ v.x = v.z - (v.z - v.x) * m_FillAmount;
+ tx0 = tx1 - fill;
+ }
+ else
+ {
+ v.z = v.x + (v.z - v.x) * m_FillAmount;
+ tx1 = tx0 + fill;
+ }
+ }
+ else if (fillMethod == FillMethod.Vertical)
+ {
+ float fill = (ty1 - ty0) * m_FillAmount;
+
+ if (m_FillOrigin == 1)
+ {
+ v.y = v.w - (v.w - v.y) * m_FillAmount;
+ ty0 = ty1 - fill;
+ }
+ else
+ {
+ v.w = v.y + (v.w - v.y) * m_FillAmount;
+ ty1 = ty0 + fill;
+ }
+ }
+ }
+
+ s_Xy[0] = new Vector2(v.x, v.y);
+ s_Xy[1] = new Vector2(v.x, v.w);
+ s_Xy[2] = new Vector2(v.z, v.w);
+ s_Xy[3] = new Vector2(v.z, v.y);
+
+ s_Uv[0] = new Vector2(tx0, ty0);
+ s_Uv[1] = new Vector2(tx0, ty1);
+ s_Uv[2] = new Vector2(tx1, ty1);
+ s_Uv[3] = new Vector2(tx1, ty0);
+
+ {
+ if (m_FillAmount < 1f && m_FillMethod != FillMethod.Horizontal && m_FillMethod != FillMethod.Vertical)
+ {
+ if (fillMethod == FillMethod.Radial90)
+ {
+ if (RadialCut(s_Xy, s_Uv, m_FillAmount, m_FillClockwise, m_FillOrigin))
+ AddQuad(toFill, s_Xy, color, s_Uv);
+ }
+ else if (fillMethod == FillMethod.Radial180)
+ {
+ for (int side = 0; side < 2; ++side)
+ {
+ float fx0, fx1, fy0, fy1;
+ int even = m_FillOrigin > 1 ? 1 : 0;
+
+ if (m_FillOrigin == 0 || m_FillOrigin == 2)
+ {
+ fy0 = 0f;
+ fy1 = 1f;
+ if (side == even)
+ {
+ fx0 = 0f;
+ fx1 = 0.5f;
+ }
+ else
+ {
+ fx0 = 0.5f;
+ fx1 = 1f;
+ }
+ }
+ else
+ {
+ fx0 = 0f;
+ fx1 = 1f;
+ if (side == even)
+ {
+ fy0 = 0.5f;
+ fy1 = 1f;
+ }
+ else
+ {
+ fy0 = 0f;
+ fy1 = 0.5f;
+ }
+ }
+
+ s_Xy[0].x = Mathf.Lerp(v.x, v.z, fx0);
+ s_Xy[1].x = s_Xy[0].x;
+ s_Xy[2].x = Mathf.Lerp(v.x, v.z, fx1);
+ s_Xy[3].x = s_Xy[2].x;
+
+ s_Xy[0].y = Mathf.Lerp(v.y, v.w, fy0);
+ s_Xy[1].y = Mathf.Lerp(v.y, v.w, fy1);
+ s_Xy[2].y = s_Xy[1].y;
+ s_Xy[3].y = s_Xy[0].y;
+
+ s_Uv[0].x = Mathf.Lerp(tx0, tx1, fx0);
+ s_Uv[1].x = s_Uv[0].x;
+ s_Uv[2].x = Mathf.Lerp(tx0, tx1, fx1);
+ s_Uv[3].x = s_Uv[2].x;
+
+ s_Uv[0].y = Mathf.Lerp(ty0, ty1, fy0);
+ s_Uv[1].y = Mathf.Lerp(ty0, ty1, fy1);
+ s_Uv[2].y = s_Uv[1].y;
+ s_Uv[3].y = s_Uv[0].y;
+
+ float val = m_FillClockwise ? fillAmount * 2f - side : m_FillAmount * 2f - (1 - side);
+
+ if (RadialCut(s_Xy, s_Uv, Mathf.Clamp01(val), m_FillClockwise, ((side + m_FillOrigin + 3) % 4)))
+ {
+ AddQuad(toFill, s_Xy, color, s_Uv);
+ }
+ }
+ }
+ else if (fillMethod == FillMethod.Radial360)
+ {
+ for (int corner = 0; corner < 4; ++corner)
+ {
+ float fx0, fx1, fy0, fy1;
+
+ if (corner < 2)
+ {
+ fx0 = 0f;
+ fx1 = 0.5f;
+ }
+ else
+ {
+ fx0 = 0.5f;
+ fx1 = 1f;
+ }
+
+ if (corner == 0 || corner == 3)
+ {
+ fy0 = 0f;
+ fy1 = 0.5f;
+ }
+ else
+ {
+ fy0 = 0.5f;
+ fy1 = 1f;
+ }
+
+ s_Xy[0].x = Mathf.Lerp(v.x, v.z, fx0);
+ s_Xy[1].x = s_Xy[0].x;
+ s_Xy[2].x = Mathf.Lerp(v.x, v.z, fx1);
+ s_Xy[3].x = s_Xy[2].x;
+
+ s_Xy[0].y = Mathf.Lerp(v.y, v.w, fy0);
+ s_Xy[1].y = Mathf.Lerp(v.y, v.w, fy1);
+ s_Xy[2].y = s_Xy[1].y;
+ s_Xy[3].y = s_Xy[0].y;
+
+ s_Uv[0].x = Mathf.Lerp(tx0, tx1, fx0);
+ s_Uv[1].x = s_Uv[0].x;
+ s_Uv[2].x = Mathf.Lerp(tx0, tx1, fx1);
+ s_Uv[3].x = s_Uv[2].x;
+
+ s_Uv[0].y = Mathf.Lerp(ty0, ty1, fy0);
+ s_Uv[1].y = Mathf.Lerp(ty0, ty1, fy1);
+ s_Uv[2].y = s_Uv[1].y;
+ s_Uv[3].y = s_Uv[0].y;
+
+ float val = m_FillClockwise ?
+ m_FillAmount * 4f - ((corner + m_FillOrigin) % 4) :
+ m_FillAmount * 4f - (3 - ((corner + m_FillOrigin) % 4));
+
+ if (RadialCut(s_Xy, s_Uv, Mathf.Clamp01(val), m_FillClockwise, ((corner + 2) % 4)))
+ AddQuad(toFill, s_Xy, color, s_Uv);
+ }
+ }
+ }
+ else
+ {
+ AddQuad(toFill, s_Xy, color, s_Uv);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Adjust the specified quad, making it be radially filled instead.
+ /// </summary>
+
+ static bool RadialCut(Vector3[] xy, Vector3[] uv, float fill, bool invert, int corner)
+ {
+ // Nothing to fill
+ if (fill < 0.001f) return false;
+
+ // Even corners invert the fill direction
+ if ((corner & 1) == 1) invert = !invert;
+
+ // Nothing to adjust
+ if (!invert && fill > 0.999f) return true;
+
+ // Convert 0-1 value into 0 to 90 degrees angle in radians
+ float angle = Mathf.Clamp01(fill);
+ if (invert) angle = 1f - angle;
+ angle *= 90f * Mathf.Deg2Rad;
+
+ // Calculate the effective X and Y factors
+ float cos = Mathf.Cos(angle);
+ float sin = Mathf.Sin(angle);
+
+ RadialCut(xy, cos, sin, invert, corner);
+ RadialCut(uv, cos, sin, invert, corner);
+ return true;
+ }
+
+ /// <summary>
+ /// Adjust the specified quad, making it be radially filled instead.
+ /// </summary>
+
+ static void RadialCut(Vector3[] xy, float cos, float sin, bool invert, int corner)
+ {
+ int i0 = corner;
+ int i1 = ((corner + 1) % 4);
+ int i2 = ((corner + 2) % 4);
+ int i3 = ((corner + 3) % 4);
+
+ if ((corner & 1) == 1)
+ {
+ if (sin > cos)
+ {
+ cos /= sin;
+ sin = 1f;
+
+ if (invert)
+ {
+ xy[i1].x = Mathf.Lerp(xy[i0].x, xy[i2].x, cos);
+ xy[i2].x = xy[i1].x;
+ }
+ }
+ else if (cos > sin)
+ {
+ sin /= cos;
+ cos = 1f;
+
+ if (!invert)
+ {
+ xy[i2].y = Mathf.Lerp(xy[i0].y, xy[i2].y, sin);
+ xy[i3].y = xy[i2].y;
+ }
+ }
+ else
+ {
+ cos = 1f;
+ sin = 1f;
+ }
+
+ if (!invert) xy[i3].x = Mathf.Lerp(xy[i0].x, xy[i2].x, cos);
+ else xy[i1].y = Mathf.Lerp(xy[i0].y, xy[i2].y, sin);
+ }
+ else
+ {
+ if (cos > sin)
+ {
+ sin /= cos;
+ cos = 1f;
+
+ if (!invert)
+ {
+ xy[i1].y = Mathf.Lerp(xy[i0].y, xy[i2].y, sin);
+ xy[i2].y = xy[i1].y;
+ }
+ }
+ else if (sin > cos)
+ {
+ cos /= sin;
+ sin = 1f;
+
+ if (invert)
+ {
+ xy[i2].x = Mathf.Lerp(xy[i0].x, xy[i2].x, cos);
+ xy[i3].x = xy[i2].x;
+ }
+ }
+ else
+ {
+ cos = 1f;
+ sin = 1f;
+ }
+
+ if (invert) xy[i3].y = Mathf.Lerp(xy[i0].y, xy[i2].y, sin);
+ else xy[i1].x = Mathf.Lerp(xy[i0].x, xy[i2].x, cos);
+ }
+ }
+
+ public virtual void CalculateLayoutInputHorizontal() {}
+ public virtual void CalculateLayoutInputVertical() {}
+
+ public virtual float minWidth { get { return 0; } }
+
+ public virtual float preferredWidth
+ {
+ get
+ {
+ if (activeSprite == null)
+ return 0;
+ if (type == Type.Sliced || type == Type.Tiled)
+ return Sprites.DataUtility.GetMinSize(activeSprite).x / pixelsPerUnit;
+ return activeSprite.rect.size.x / pixelsPerUnit;
+ }
+ }
+
+ public virtual float flexibleWidth { get { return -1; } }
+
+ public virtual float minHeight { get { return 0; } }
+
+ public virtual float preferredHeight
+ {
+ get
+ {
+ if (activeSprite == null)
+ return 0;
+ if (type == Type.Sliced || type == Type.Tiled)
+ return Sprites.DataUtility.GetMinSize(activeSprite).y / pixelsPerUnit;
+ return activeSprite.rect.size.y / pixelsPerUnit;
+ }
+ }
+
+ public virtual float flexibleHeight { get { return -1; } }
+
+ public virtual int layoutPriority { get { return 0; } }
+
+ //会根据透明度做更细致的射线检测,透明的地方不算
+ public virtual bool IsRaycastLocationValid(Vector2 screenPoint, Camera eventCamera)
+ {
+ if (alphaHitTestMinimumThreshold <= 0)
+ return true;
+
+ if (alphaHitTestMinimumThreshold > 1)
+ return false;
+
+ if (activeSprite == null)
+ return true;
+
+ Vector2 local;
+ if (!RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, screenPoint, eventCamera, out local))
+ return false;
+
+ Rect rect = GetPixelAdjustedRect();
+
+ // Convert to have lower left corner as reference point.
+ local.x += rectTransform.pivot.x * rect.width;
+ local.y += rectTransform.pivot.y * rect.height;
+
+ local = MapCoordinate(local, rect);
+
+ // Normalize local coordinates.
+ Rect spriteRect = activeSprite.textureRect;
+ Vector2 normalized = new Vector2(local.x / spriteRect.width, local.y / spriteRect.height);
+
+ // Convert to texture space.
+ float x = Mathf.Lerp(spriteRect.x, spriteRect.xMax, normalized.x) / activeSprite.texture.width;
+ float y = Mathf.Lerp(spriteRect.y, spriteRect.yMax, normalized.y) / activeSprite.texture.height;
+
+ try
+ {
+ return activeSprite.texture.GetPixelBilinear(x, y).a >= alphaHitTestMinimumThreshold;
+ }
+ catch (UnityException e)
+ {
+ Debug.LogError("Using alphaHitTestMinimumThreshold greater than 0 on Image whose sprite texture cannot be read. " + e.Message + " Also make sure to disable sprite packing for this sprite.", this);
+ return true;
+ }
+ }
+
+ private Vector2 MapCoordinate(Vector2 local, Rect rect)
+ {
+ Rect spriteRect = activeSprite.rect;
+ if (type == Type.Simple || type == Type.Filled)
+ return new Vector2(local.x * spriteRect.width / rect.width, local.y * spriteRect.height / rect.height);
+
+ Vector4 border = activeSprite.border;
+ Vector4 adjustedBorder = GetAdjustedBorders(border / pixelsPerUnit, rect);
+
+ for (int i = 0; i < 2; i++)
+ {
+ if (local[i] <= adjustedBorder[i])
+ continue;
+
+ if (rect.size[i] - local[i] <= adjustedBorder[i + 2])
+ {
+ local[i] -= (rect.size[i] - spriteRect.size[i]);
+ continue;
+ }
+
+ if (type == Type.Sliced)
+ {
+ float lerp = Mathf.InverseLerp(adjustedBorder[i], rect.size[i] - adjustedBorder[i + 2], local[i]);
+ local[i] = Mathf.Lerp(border[i], spriteRect.size[i] - border[i + 2], lerp);
+ continue;
+ }
+ else
+ {
+ local[i] -= adjustedBorder[i];
+ local[i] = Mathf.Repeat(local[i], spriteRect.size[i] - border[i] - border[i + 2]);
+ local[i] += border[i];
+ continue;
+ }
+ }
+
+ return local;
+ }
+ }
+}
diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/Image.cs.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/Image.cs.meta
new file mode 100644
index 0000000..91ab591
--- /dev/null
+++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/Image.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 0cba8e295482e184f9f6a5a8f2b559c3
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/MaskableGraphic.cs b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/MaskableGraphic.cs
new file mode 100644
index 0000000..0d0f327
--- /dev/null
+++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/MaskableGraphic.cs
@@ -0,0 +1,235 @@
+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);
+ // Graphic在masks下的深度,如果不是0且没有mask组件意味着是普通的非mask用graphic(如果是0一定是mask用的graphic)
+ 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()))
+ {
+ // Ref = (1 << stencilValue) - 1
+ // Op = Keep
+ // Func = Equal
+ // ReadMask = (1 << stencilValue) - 1
+ // WriteMask = 0
+ 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(); // 这里需要更新一下canvasRenderer的网格数据
+ }
+ }
+
+ 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/Graphics/MaskableGraphic.cs.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/MaskableGraphic.cs.meta
new file mode 100644
index 0000000..07f0d51
--- /dev/null
+++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/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/Graphics/RawImage.cs b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/RawImage.cs
new file mode 100644
index 0000000..e6dab1b
--- /dev/null
+++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/RawImage.cs
@@ -0,0 +1,120 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine.Serialization;
+
+namespace UnityEngine.UI
+{
+ /// <summary>
+ /// If you don't have or don't wish to create an atlas, you can simply use this script to draw a texture.
+ /// Keep in mind though that this will create an extra draw call with each RawImage present, so it's
+ /// best to use it only for backgrounds or temporary visible graphics.
+ /// </summary>
+ [AddComponentMenu("UI/Raw Image", 12)]
+ public class RawImage : MaskableGraphic
+ {
+ [FormerlySerializedAs("m_Tex")]
+ [SerializeField] Texture m_Texture;
+ [SerializeField] Rect m_UVRect = new Rect(0f, 0f, 1f, 1f);
+
+ protected RawImage()
+ {
+ useLegacyMeshGeneration = false;
+ }
+
+ /// <summary>
+ /// Returns the texture used to draw this Graphic.
+ /// </summary>
+ public override Texture mainTexture
+ {
+ get
+ {
+ if (m_Texture == null)
+ {
+ if (material != null && material.mainTexture != null)
+ {
+ return material.mainTexture;
+ }
+ return s_WhiteTexture;
+ }
+ return m_Texture;
+ }
+ }
+
+ /// <summary>
+ /// Texture to be used.
+ /// </summary>
+ public Texture texture
+ {
+ get
+ {
+ return m_Texture;
+ }
+ set
+ {
+ if (m_Texture == value)
+ return;
+
+ m_Texture = value;
+ SetVerticesDirty();
+ SetMaterialDirty();
+ }
+ }
+
+ /// <summary>
+ /// UV rectangle used by the texture.
+ /// </summary>
+ public Rect uvRect
+ {
+ get
+ {
+ return m_UVRect;
+ }
+ set
+ {
+ if (m_UVRect == value)
+ return;
+ m_UVRect = value;
+ SetVerticesDirty();
+ }
+ }
+
+ /// <summary>
+ /// Adjust the scale of the Graphic to make it pixel-perfect.
+ /// </summary>
+
+ public override void SetNativeSize()
+ {
+ Texture tex = mainTexture;
+ if (tex != null)
+ {
+ int w = Mathf.RoundToInt(tex.width * uvRect.width);
+ int h = Mathf.RoundToInt(tex.height * uvRect.height);
+ rectTransform.anchorMax = rectTransform.anchorMin;
+ rectTransform.sizeDelta = new Vector2(w, h);
+ }
+ }
+
+ protected override void OnPopulateMesh(VertexHelper vh)
+ {
+ Texture tex = mainTexture;
+ vh.Clear();
+ if (tex != null)
+ {
+ var r = GetPixelAdjustedRect();
+ var v = new Vector4(r.x, r.y, r.x + r.width, r.y + r.height);
+ var scaleX = tex.width * tex.texelSize.x;
+ var scaleY = tex.height * tex.texelSize.y;
+ {
+ var color32 = color;
+ vh.AddVert(new Vector3(v.x, v.y), color32, new Vector2(m_UVRect.xMin * scaleX, m_UVRect.yMin * scaleY));
+ vh.AddVert(new Vector3(v.x, v.w), color32, new Vector2(m_UVRect.xMin * scaleX, m_UVRect.yMax * scaleY));
+ vh.AddVert(new Vector3(v.z, v.w), color32, new Vector2(m_UVRect.xMax * scaleX, m_UVRect.yMax * scaleY));
+ vh.AddVert(new Vector3(v.z, v.y), color32, new Vector2(m_UVRect.xMax * scaleX, m_UVRect.yMin * scaleY));
+
+ vh.AddTriangle(0, 1, 2);
+ vh.AddTriangle(2, 3, 0);
+ }
+ }
+ }
+ }
+}
diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/RawImage.cs.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/RawImage.cs.meta
new file mode 100644
index 0000000..2a70e35
--- /dev/null
+++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/RawImage.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 570773b73e8b0334fb410b7457eb8b6a
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/SpriteState.cs b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/SpriteState.cs
new file mode 100644
index 0000000..c95e146
--- /dev/null
+++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/SpriteState.cs
@@ -0,0 +1,33 @@
+using System;
+using UnityEngine.Serialization;
+
+namespace UnityEngine.UI
+{
+ [Serializable]
+ public struct SpriteState : IEquatable<SpriteState>
+ {
+ [FormerlySerializedAs("highlightedSprite")]
+ [FormerlySerializedAs("m_SelectedSprite")]
+ [SerializeField]
+ private Sprite m_HighlightedSprite;
+
+ [FormerlySerializedAs("pressedSprite")]
+ [SerializeField]
+ private Sprite m_PressedSprite;
+
+ [FormerlySerializedAs("disabledSprite")]
+ [SerializeField]
+ private Sprite m_DisabledSprite;
+
+ public Sprite highlightedSprite { get { return m_HighlightedSprite; } set { m_HighlightedSprite = value; } }
+ public Sprite pressedSprite { get { return m_PressedSprite; } set { m_PressedSprite = value; } }
+ public Sprite disabledSprite { get { return m_DisabledSprite; } set { m_DisabledSprite = value; } }
+
+ public bool Equals(SpriteState other)
+ {
+ return highlightedSprite == other.highlightedSprite &&
+ pressedSprite == other.pressedSprite &&
+ disabledSprite == other.disabledSprite;
+ }
+ }
+}
diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/SpriteState.cs.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/SpriteState.cs.meta
new file mode 100644
index 0000000..b389ded
--- /dev/null
+++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/SpriteState.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: cc6d0c85730bc354697c6b7d971eda44
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant: