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.cs659
-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.cs288
-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.cs76
-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.cs1165
-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/RawImage.cs121
-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
-rw-r--r--Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/StencilMaterial.cs169
-rw-r--r--Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/StencilMaterial.cs.meta11
-rw-r--r--Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/Text.cs571
-rw-r--r--Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/Text.cs.meta11
20 files changed, 3240 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..4bbabc7
--- /dev/null
+++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/Graphic.cs
@@ -0,0 +1,659 @@
+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();
+ }
+
+ /// <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;
+ }
+ }
+
+ private void CacheCanvas()
+ {
+ var list = ListPool<Canvas>.Get();
+ 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();
+ }
+ }
+
+ public virtual Material materialForRendering
+ {
+ get
+ {
+ 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);
+ }
+
+ //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);
+ 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..2582204
--- /dev/null
+++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/GraphicRaycaster.cs
@@ -0,0 +1,288 @@
+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..ca7eddf
--- /dev/null
+++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/GraphicRegistry.cs
@@ -0,0 +1,76 @@
+using System.Collections.Generic;
+using UnityEngine.UI.Collections;
+
+namespace UnityEngine.UI
+{
+ public class GraphicRegistry
+ {
+ private static GraphicRegistry s_Instance;
+
+ 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..cae7667
--- /dev/null
+++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/Image.cs
@@ -0,0 +1,1165 @@
+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() {}
+
+ 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;
+ }
+
+ Texture2D alphaTex = activeSprite.associatedAlphaSplitTexture;
+
+ if (alphaTex != null)
+ {
+ canvasRenderer.SetAlphaTexture(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/RawImage.cs b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/RawImage.cs
new file mode 100644
index 0000000..35f0508
--- /dev/null
+++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/RawImage.cs
@@ -0,0 +1,121 @@
+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:
diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/StencilMaterial.cs b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/StencilMaterial.cs
new file mode 100644
index 0000000..c12f209
--- /dev/null
+++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/StencilMaterial.cs
@@ -0,0 +1,169 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine.Rendering;
+
+namespace UnityEngine.UI
+{
+ /// <summary>
+ /// Dynamic material class makes it possible to create custom materials on the fly on a per-Graphic basis,
+ /// and still have them get cleaned up correctly.
+ /// </summary>
+ public static class StencilMaterial
+ {
+ private class MatEntry
+ {
+ public Material baseMat;
+ public Material customMat;
+ public int count;
+
+ public int stencilId;
+ public StencilOp operation = StencilOp.Keep;
+ public CompareFunction compareFunction = CompareFunction.Always;
+ public int readMask;
+ public int writeMask;
+ public bool useAlphaClip;
+ public ColorWriteMask colorMask;
+ }
+
+ private static List<MatEntry> m_List = new List<MatEntry>();
+
+ [Obsolete("Use Material.Add instead.", true)]
+ public static Material Add(Material baseMat, int stencilID) { return null; }
+
+ /// <summary>
+ /// Add a new material using the specified base and stencil ID.
+ /// </summary>
+ public static Material Add(Material baseMat, int stencilID, StencilOp operation, CompareFunction compareFunction, ColorWriteMask colorWriteMask)
+ {
+ return Add(baseMat, stencilID, operation, compareFunction, colorWriteMask, 255, 255);
+ }
+
+ /// <summary>
+ /// Add a new material using the specified base and stencil ID.
+ /// </summary>
+ public static Material Add(Material baseMat, int stencilID, StencilOp operation, CompareFunction compareFunction, ColorWriteMask colorWriteMask, int readMask, int writeMask)
+ {
+ if ((stencilID <= 0 && colorWriteMask == ColorWriteMask.All) || baseMat == null)
+ return baseMat;
+
+ if (!baseMat.HasProperty("_Stencil"))
+ {
+ Debug.LogWarning("Material " + baseMat.name + " doesn't have _Stencil property", baseMat);
+ return baseMat;
+ }
+ if (!baseMat.HasProperty("_StencilOp"))
+ {
+ Debug.LogWarning("Material " + baseMat.name + " doesn't have _StencilOp property", baseMat);
+ return baseMat;
+ }
+ if (!baseMat.HasProperty("_StencilComp"))
+ {
+ Debug.LogWarning("Material " + baseMat.name + " doesn't have _StencilComp property", baseMat);
+ return baseMat;
+ }
+ if (!baseMat.HasProperty("_StencilReadMask"))
+ {
+ Debug.LogWarning("Material " + baseMat.name + " doesn't have _StencilReadMask property", baseMat);
+ return baseMat;
+ }
+ if (!baseMat.HasProperty("_StencilWriteMask"))
+ {
+ Debug.LogWarning("Material " + baseMat.name + " doesn't have _StencilWriteMask property", baseMat);
+ return baseMat;
+ }
+ if (!baseMat.HasProperty("_ColorMask"))
+ {
+ Debug.LogWarning("Material " + baseMat.name + " doesn't have _ColorMask property", baseMat);
+ return baseMat;
+ }
+
+ for (int i = 0; i < m_List.Count; ++i)
+ {
+ MatEntry ent = m_List[i];
+
+ if (ent.baseMat == baseMat
+ && ent.stencilId == stencilID
+ && ent.operation == operation
+ && ent.compareFunction == compareFunction
+ && ent.readMask == readMask
+ && ent.writeMask == writeMask
+ && ent.colorMask == colorWriteMask)
+ {
+ ++ent.count;
+ return ent.customMat;
+ }
+ }
+
+ var newEnt = new MatEntry();
+ newEnt.count = 1;
+ newEnt.baseMat = baseMat;
+ newEnt.customMat = new Material(baseMat);
+ newEnt.customMat.hideFlags = HideFlags.HideAndDontSave;
+ newEnt.stencilId = stencilID;
+ newEnt.operation = operation;
+ newEnt.compareFunction = compareFunction;
+ newEnt.readMask = readMask;
+ newEnt.writeMask = writeMask;
+ newEnt.colorMask = colorWriteMask;
+ newEnt.useAlphaClip = operation != StencilOp.Keep && writeMask > 0;
+
+ newEnt.customMat.name = string.Format("Stencil Id:{0}, Op:{1}, Comp:{2}, WriteMask:{3}, ReadMask:{4}, ColorMask:{5} AlphaClip:{6} ({7})", stencilID, operation, compareFunction, writeMask, readMask, colorWriteMask, newEnt.useAlphaClip, baseMat.name);
+
+ newEnt.customMat.SetInt("_Stencil", stencilID);
+ newEnt.customMat.SetInt("_StencilOp", (int)operation);
+ newEnt.customMat.SetInt("_StencilComp", (int)compareFunction);
+ newEnt.customMat.SetInt("_StencilReadMask", readMask);
+ newEnt.customMat.SetInt("_StencilWriteMask", writeMask);
+ newEnt.customMat.SetInt("_ColorMask", (int)colorWriteMask);
+
+ // left for backwards compatability
+ if (newEnt.customMat.HasProperty("_UseAlphaClip"))
+ newEnt.customMat.SetInt("_UseAlphaClip", newEnt.useAlphaClip ? 1 : 0);
+
+ if (newEnt.useAlphaClip)
+ newEnt.customMat.EnableKeyword("UNITY_UI_ALPHACLIP");
+ else
+ newEnt.customMat.DisableKeyword("UNITY_UI_ALPHACLIP");
+
+ m_List.Add(newEnt);
+ return newEnt.customMat;
+ }
+
+ /// <summary>
+ /// Remove an existing material, automatically cleaning it up if it's no longer in use.
+ /// </summary>
+ public static void Remove(Material customMat)
+ {
+ if (customMat == null)
+ return;
+
+ for (int i = 0; i < m_List.Count; ++i)
+ {
+ MatEntry ent = m_List[i];
+
+ if (ent.customMat != customMat)
+ continue;
+
+ if (--ent.count == 0)
+ {
+ Misc.DestroyImmediate(ent.customMat);
+ ent.baseMat = null;
+ m_List.RemoveAt(i);
+ }
+ return;
+ }
+ }
+
+ public static void ClearAll()
+ {
+ for (int i = 0; i < m_List.Count; ++i)
+ {
+ MatEntry ent = m_List[i];
+
+ Misc.DestroyImmediate(ent.customMat);
+ ent.baseMat = null;
+ }
+ m_List.Clear();
+ }
+ }
+}
diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/StencilMaterial.cs.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/StencilMaterial.cs.meta
new file mode 100644
index 0000000..3fd6a69
--- /dev/null
+++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/StencilMaterial.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 2d445d28188ffd745990df17f1ce8914
+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/Text.cs b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/Text.cs
new file mode 100644
index 0000000..c087983
--- /dev/null
+++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/Text.cs
@@ -0,0 +1,571 @@
+using System;
+using System.Collections.Generic;
+
+namespace UnityEngine.UI
+{
+ /// <summary>
+ /// Labels are graphics that display text.
+ /// </summary>
+
+ [AddComponentMenu("UI/Text", 10)]
+ public class Text : MaskableGraphic, ILayoutElement
+ {
+ [SerializeField] private FontData m_FontData = FontData.defaultFontData;
+
+#if UNITY_EDITOR
+ // needed to track font changes from the inspector
+ private Font m_LastTrackedFont;
+#endif
+
+ [TextArea(3, 10)][SerializeField] protected string m_Text = String.Empty;
+
+ private TextGenerator m_TextCache;
+ private TextGenerator m_TextCacheForLayout;
+
+ static protected Material s_DefaultText = null;
+
+ // We use this flag instead of Unregistering/Registering the callback to avoid allocation.
+ [NonSerialized] protected bool m_DisableFontTextureRebuiltCallback = false;
+
+ protected Text()
+ {
+ useLegacyMeshGeneration = false;
+ }
+
+ /// <summary>
+ /// Get or set the material used by this Text.
+ /// </summary>
+
+ public TextGenerator cachedTextGenerator
+ {
+ get { return m_TextCache ?? (m_TextCache = (m_Text.Length != 0 ? new TextGenerator(m_Text.Length) : new TextGenerator())); }
+ }
+
+ public TextGenerator cachedTextGeneratorForLayout
+ {
+ get { return m_TextCacheForLayout ?? (m_TextCacheForLayout = new TextGenerator()); }
+ }
+
+ /// <summary>
+ /// Text's texture comes from the font.
+ /// </summary>
+ public override Texture mainTexture
+ {
+ get
+ {
+ if (font != null && font.material != null && font.material.mainTexture != null)
+ return font.material.mainTexture;
+
+ if (m_Material != null)
+ return m_Material.mainTexture;
+
+ return base.mainTexture;
+ }
+ }
+
+ public void FontTextureChanged()
+ {
+ // Only invoke if we are not destroyed.
+ if (!this)
+ return;
+
+ if (m_DisableFontTextureRebuiltCallback)
+ return;
+
+ cachedTextGenerator.Invalidate();
+
+ if (!IsActive())
+ return;
+
+ // this is a bit hacky, but it is currently the
+ // cleanest solution....
+ // if we detect the font texture has changed and are in a rebuild loop
+ // we just regenerate the verts for the new UV's
+ if (CanvasUpdateRegistry.IsRebuildingGraphics() || CanvasUpdateRegistry.IsRebuildingLayout())
+ UpdateGeometry();
+ else
+ SetAllDirty();
+ }
+
+ public Font font
+ {
+ get
+ {
+ return m_FontData.font;
+ }
+ set
+ {
+ if (m_FontData.font == value)
+ return;
+
+ FontUpdateTracker.UntrackText(this);
+
+ m_FontData.font = value;
+
+ FontUpdateTracker.TrackText(this);
+
+#if UNITY_EDITOR
+ // needed to track font changes from the inspector
+ m_LastTrackedFont = value;
+#endif
+
+ SetAllDirty();
+ }
+ }
+
+ /// <summary>
+ /// Text that's being displayed by the Text.
+ /// </summary>
+
+ public virtual string text
+ {
+ get
+ {
+ return m_Text;
+ }
+ set
+ {
+ if (String.IsNullOrEmpty(value))
+ {
+ if (String.IsNullOrEmpty(m_Text))
+ return;
+ m_Text = "";
+ SetVerticesDirty();
+ }
+ else if (m_Text != value)
+ {
+ m_Text = value;
+ SetVerticesDirty();
+ SetLayoutDirty();
+ }
+ }
+ }
+
+ /// <summary>
+ /// Whether this Text will support rich text.
+ /// </summary>
+
+ public bool supportRichText
+ {
+ get
+ {
+ return m_FontData.richText;
+ }
+ set
+ {
+ if (m_FontData.richText == value)
+ return;
+ m_FontData.richText = value;
+ SetVerticesDirty();
+ SetLayoutDirty();
+ }
+ }
+
+ /// <summary>
+ /// Wrap mode used by the text.
+ /// </summary>
+
+ public bool resizeTextForBestFit
+ {
+ get
+ {
+ return m_FontData.bestFit;
+ }
+ set
+ {
+ if (m_FontData.bestFit == value)
+ return;
+ m_FontData.bestFit = value;
+ SetVerticesDirty();
+ SetLayoutDirty();
+ }
+ }
+
+ public int resizeTextMinSize
+ {
+ get
+ {
+ return m_FontData.minSize;
+ }
+ set
+ {
+ if (m_FontData.minSize == value)
+ return;
+ m_FontData.minSize = value;
+
+ SetVerticesDirty();
+ SetLayoutDirty();
+ }
+ }
+
+ public int resizeTextMaxSize
+ {
+ get
+ {
+ return m_FontData.maxSize;
+ }
+ set
+ {
+ if (m_FontData.maxSize == value)
+ return;
+ m_FontData.maxSize = value;
+
+ SetVerticesDirty();
+ SetLayoutDirty();
+ }
+ }
+
+ /// <summary>
+ /// Alignment anchor used by the text.
+ /// </summary>
+
+ public TextAnchor alignment
+ {
+ get
+ {
+ return m_FontData.alignment;
+ }
+ set
+ {
+ if (m_FontData.alignment == value)
+ return;
+ m_FontData.alignment = value;
+
+ SetVerticesDirty();
+ SetLayoutDirty();
+ }
+ }
+
+ public bool alignByGeometry
+ {
+ get
+ {
+ return m_FontData.alignByGeometry;
+ }
+ set
+ {
+ if (m_FontData.alignByGeometry == value)
+ return;
+ m_FontData.alignByGeometry = value;
+
+ SetVerticesDirty();
+ }
+ }
+
+ public int fontSize
+ {
+ get
+ {
+ return m_FontData.fontSize;
+ }
+ set
+ {
+ if (m_FontData.fontSize == value)
+ return;
+ m_FontData.fontSize = value;
+
+ SetVerticesDirty();
+ SetLayoutDirty();
+ }
+ }
+
+ public HorizontalWrapMode horizontalOverflow
+ {
+ get
+ {
+ return m_FontData.horizontalOverflow;
+ }
+ set
+ {
+ if (m_FontData.horizontalOverflow == value)
+ return;
+ m_FontData.horizontalOverflow = value;
+
+ SetVerticesDirty();
+ SetLayoutDirty();
+ }
+ }
+
+ public VerticalWrapMode verticalOverflow
+ {
+ get
+ {
+ return m_FontData.verticalOverflow;
+ }
+ set
+ {
+ if (m_FontData.verticalOverflow == value)
+ return;
+ m_FontData.verticalOverflow = value;
+
+ SetVerticesDirty();
+ SetLayoutDirty();
+ }
+ }
+
+ public float lineSpacing
+ {
+ get
+ {
+ return m_FontData.lineSpacing;
+ }
+ set
+ {
+ if (m_FontData.lineSpacing == value)
+ return;
+ m_FontData.lineSpacing = value;
+
+ SetVerticesDirty();
+ SetLayoutDirty();
+ }
+ }
+
+ /// <summary>
+ /// Font style used by the Text's text.
+ /// </summary>
+
+ public FontStyle fontStyle
+ {
+ get
+ {
+ return m_FontData.fontStyle;
+ }
+ set
+ {
+ if (m_FontData.fontStyle == value)
+ return;
+ m_FontData.fontStyle = value;
+
+ SetVerticesDirty();
+ SetLayoutDirty();
+ }
+ }
+
+ public float pixelsPerUnit
+ {
+ get
+ {
+ var localCanvas = canvas;
+ if (!localCanvas)
+ return 1;
+ // For dynamic fonts, ensure we use one pixel per pixel on the screen.
+ if (!font || font.dynamic)
+ return localCanvas.scaleFactor;
+ // For non-dynamic fonts, calculate pixels per unit based on specified font size relative to font object's own font size.
+ if (m_FontData.fontSize <= 0 || font.fontSize <= 0)
+ return 1;
+ return font.fontSize / (float)m_FontData.fontSize;
+ }
+ }
+
+ protected override void OnEnable()
+ {
+ base.OnEnable();
+ cachedTextGenerator.Invalidate();
+ FontUpdateTracker.TrackText(this);
+ }
+
+ protected override void OnDisable()
+ {
+ FontUpdateTracker.UntrackText(this);
+ base.OnDisable();
+ }
+
+ protected override void UpdateGeometry()
+ {
+ if (font != null)
+ {
+ base.UpdateGeometry();
+ }
+ }
+
+#if UNITY_EDITOR
+ protected override void Reset()
+ {
+ AssignDefaultFont();
+ }
+
+#endif
+ internal void AssignDefaultFont()
+ {
+ font = Resources.GetBuiltinResource<Font>("Arial.ttf");
+ }
+
+ public TextGenerationSettings GetGenerationSettings(Vector2 extents)
+ {
+ var settings = new TextGenerationSettings();
+
+ settings.generationExtents = extents;
+ if (font != null && font.dynamic)
+ {
+ settings.fontSize = m_FontData.fontSize;
+ settings.resizeTextMinSize = m_FontData.minSize;
+ settings.resizeTextMaxSize = m_FontData.maxSize;
+ }
+
+ // Other settings
+ settings.textAnchor = m_FontData.alignment;
+ settings.alignByGeometry = m_FontData.alignByGeometry;
+ settings.scaleFactor = pixelsPerUnit;
+ settings.color = color;
+ settings.font = font;
+ settings.pivot = rectTransform.pivot;
+ settings.richText = m_FontData.richText;
+ settings.lineSpacing = m_FontData.lineSpacing;
+ settings.fontStyle = m_FontData.fontStyle;
+ settings.resizeTextForBestFit = m_FontData.bestFit;
+ settings.updateBounds = false;
+ settings.horizontalOverflow = m_FontData.horizontalOverflow;
+ settings.verticalOverflow = m_FontData.verticalOverflow;
+
+ return settings;
+ }
+
+ static public Vector2 GetTextAnchorPivot(TextAnchor anchor)
+ {
+ switch (anchor)
+ {
+ case TextAnchor.LowerLeft: return new Vector2(0, 0);
+ case TextAnchor.LowerCenter: return new Vector2(0.5f, 0);
+ case TextAnchor.LowerRight: return new Vector2(1, 0);
+ case TextAnchor.MiddleLeft: return new Vector2(0, 0.5f);
+ case TextAnchor.MiddleCenter: return new Vector2(0.5f, 0.5f);
+ case TextAnchor.MiddleRight: return new Vector2(1, 0.5f);
+ case TextAnchor.UpperLeft: return new Vector2(0, 1);
+ case TextAnchor.UpperCenter: return new Vector2(0.5f, 1);
+ case TextAnchor.UpperRight: return new Vector2(1, 1);
+ default: return Vector2.zero;
+ }
+ }
+
+ readonly UIVertex[] m_TempVerts = new UIVertex[4];
+ protected override void OnPopulateMesh(VertexHelper toFill)
+ {
+ if (font == null)
+ return;
+
+ // We don't care if we the font Texture changes while we are doing our Update.
+ // The end result of cachedTextGenerator will be valid for this instance.
+ // Otherwise we can get issues like Case 619238.
+ m_DisableFontTextureRebuiltCallback = true;
+
+ Vector2 extents = rectTransform.rect.size;
+
+ var settings = GetGenerationSettings(extents);
+ cachedTextGenerator.PopulateWithErrors(text, settings, gameObject);
+
+ // Apply the offset to the vertices
+ IList<UIVertex> verts = cachedTextGenerator.verts;
+ float unitsPerPixel = 1 / pixelsPerUnit;
+ //Last 4 verts are always a new line... (\n)
+ int vertCount = verts.Count - 4;
+
+ Vector2 roundingOffset = new Vector2(verts[0].position.x, verts[0].position.y) * unitsPerPixel;
+ roundingOffset = PixelAdjustPoint(roundingOffset) - roundingOffset;
+ toFill.Clear();
+ if (roundingOffset != Vector2.zero)
+ {
+ for (int i = 0; i < vertCount; ++i)
+ {
+ int tempVertsIndex = i & 3;
+ m_TempVerts[tempVertsIndex] = verts[i];
+ m_TempVerts[tempVertsIndex].position *= unitsPerPixel;
+ m_TempVerts[tempVertsIndex].position.x += roundingOffset.x;
+ m_TempVerts[tempVertsIndex].position.y += roundingOffset.y;
+ if (tempVertsIndex == 3)
+ toFill.AddUIVertexQuad(m_TempVerts);
+ }
+ }
+ else
+ {
+ for (int i = 0; i < vertCount; ++i)
+ {
+ int tempVertsIndex = i & 3;
+ m_TempVerts[tempVertsIndex] = verts[i];
+ m_TempVerts[tempVertsIndex].position *= unitsPerPixel;
+ if (tempVertsIndex == 3)
+ toFill.AddUIVertexQuad(m_TempVerts);
+ }
+ }
+
+ m_DisableFontTextureRebuiltCallback = false;
+ }
+
+ public virtual void CalculateLayoutInputHorizontal() {}
+ public virtual void CalculateLayoutInputVertical() {}
+
+ public virtual float minWidth
+ {
+ get { return 0; }
+ }
+
+ public virtual float preferredWidth
+ {
+ get
+ {
+ var settings = GetGenerationSettings(Vector2.zero);
+ return cachedTextGeneratorForLayout.GetPreferredWidth(m_Text, settings) / pixelsPerUnit;
+ }
+ }
+
+ public virtual float flexibleWidth { get { return -1; } }
+
+ public virtual float minHeight
+ {
+ get { return 0; }
+ }
+
+ public virtual float preferredHeight
+ {
+ get
+ {
+ var settings = GetGenerationSettings(new Vector2(GetPixelAdjustedRect().size.x, 0.0f));
+ return cachedTextGeneratorForLayout.GetPreferredHeight(m_Text, settings) / pixelsPerUnit;
+ }
+ }
+
+ public virtual float flexibleHeight { get { return -1; } }
+
+ public virtual int layoutPriority { get { return 0; } }
+
+#if UNITY_EDITOR
+ public override void OnRebuildRequested()
+ {
+ // After a Font asset gets re-imported the managed side gets deleted and recreated,
+ // that means the delegates are not persisted.
+ // so we need to properly enforce a consistent state here.
+ FontUpdateTracker.UntrackText(this);
+ FontUpdateTracker.TrackText(this);
+
+ // Also the textgenerator is no longer valid.
+ cachedTextGenerator.Invalidate();
+
+ base.OnRebuildRequested();
+ }
+
+ // The Text inspector editor can change the font, and we need a way to track changes so that we get the appropriate rebuild callbacks
+ // We can intercept changes in OnValidate, and keep track of the previous font reference
+ protected override void OnValidate()
+ {
+ if (!IsActive())
+ {
+ base.OnValidate();
+ return;
+ }
+
+ if (m_FontData.font != m_LastTrackedFont)
+ {
+ Font newFont = m_FontData.font;
+ m_FontData.font = m_LastTrackedFont;
+ FontUpdateTracker.UntrackText(this);
+ m_FontData.font = newFont;
+ FontUpdateTracker.TrackText(this);
+
+ m_LastTrackedFont = newFont;
+ }
+ base.OnValidate();
+ }
+
+#endif // if UNITY_EDITOR
+ }
+}
diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/Text.cs.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/Text.cs.meta
new file mode 100644
index 0000000..ea6d1d8
--- /dev/null
+++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/Text.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 48696ad002dcb2146ab8d6ad72d455d7
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant: