From 3084644c4fdfdfdccfcf31013e7280b5cd1a0bf3 Mon Sep 17 00:00:00 2001 From: Simon Jackson Date: Mon, 24 Jul 2017 21:36:23 +0100 Subject: [PATCH] Updated Line Renderer to work with Textures better. Also now uses Sprite Boxing / slicing --- Scripts/Primitives/UILineRenderer.cs | 86 +++++++++++++++++---------- Scripts/Primitives/UIPrimitiveBase.cs | 84 +++++++++++++++++++++++--- 2 files changed, 129 insertions(+), 41 deletions(-) diff --git a/Scripts/Primitives/UILineRenderer.cs b/Scripts/Primitives/UILineRenderer.cs index c8899d3..d933c53 100644 --- a/Scripts/Primitives/UILineRenderer.cs +++ b/Scripts/Primitives/UILineRenderer.cs @@ -15,6 +15,7 @@ namespace UnityEngine.UI.Extensions Start, Middle, End, + Full, } public enum JoinType @@ -38,20 +39,10 @@ namespace UnityEngine.UI.Extensions // there is no overlapping. private const float MIN_BEVEL_NICE_JOIN = 30 * Mathf.Deg2Rad; - private static readonly Vector2 UV_TOP_LEFT = Vector2.zero; - private static readonly Vector2 UV_BOTTOM_LEFT = new Vector2(0, 1); - private static readonly Vector2 UV_TOP_CENTER = new Vector2(0.5f, 0); - private static readonly Vector2 UV_BOTTOM_CENTER = new Vector2(0.5f, 1); - private static readonly Vector2 UV_TOP_RIGHT = new Vector2(1, 0); - private static readonly Vector2 UV_BOTTOM_RIGHT = new Vector2(1, 1); + private static Vector2 UV_TOP_LEFT, UV_BOTTOM_LEFT, UV_TOP_CENTER_LEFT, UV_TOP_CENTER_RIGHT, UV_BOTTOM_CENTER_LEFT, UV_BOTTOM_CENTER_RIGHT, UV_TOP_RIGHT, UV_BOTTOM_RIGHT; + private static Vector2[] startUvs, middleUvs, endUvs, fullUvs; - private static readonly Vector2[] startUvs = new[] { UV_TOP_LEFT, UV_BOTTOM_LEFT, UV_BOTTOM_CENTER, UV_TOP_CENTER }; - private static readonly Vector2[] middleUvs = new[] { UV_TOP_CENTER, UV_BOTTOM_CENTER, UV_BOTTOM_CENTER, UV_TOP_CENTER }; - private static readonly Vector2[] endUvs = new[] { UV_TOP_CENTER, UV_BOTTOM_CENTER, UV_BOTTOM_RIGHT, UV_TOP_RIGHT }; - - [SerializeField] - internal Rect m_UVRect = new Rect(0f, 0f, 1f, 1f); - [SerializeField] + [SerializeField] internal Vector2[] m_points; [SerializeField] @@ -102,24 +93,6 @@ namespace UnityEngine.UI.Extensions [HideInInspector] public bool drivenExternally = false; - /// - /// UV rectangle used by the texture. - /// - public Rect uvRect - { - get - { - return m_UVRect; - } - - set - { - if (m_UVRect == value) - return; - m_UVRect = value; - SetVerticesDirty(); - } - } /// /// Points to be drawn in the line. @@ -144,6 +117,7 @@ namespace UnityEngine.UI.Extensions { if (m_points == null) return; + GeneratedUVs(); Vector2[] pointsToDraw = m_points; //If Bezier is desired, pick the implementation if (BezierMode != BezierType.None && m_points.Length > 3) @@ -198,9 +172,10 @@ namespace UnityEngine.UI.Extensions segments.Add(CreateLineCap(start, end, SegmentType.Start)); } + //segments.Add(CreateLineSegment(start, end, SegmentType.Full)); segments.Add(CreateLineSegment(start, end, SegmentType.Middle)); - if (lineCaps) + if (lineCaps) { segments.Add(CreateLineCap(start, end, SegmentType.End)); } @@ -221,6 +196,7 @@ namespace UnityEngine.UI.Extensions } segments.Add(CreateLineSegment(start, end, SegmentType.Middle)); + //segments.Add(CreateLineSegment(start, end, SegmentType.Full)); if (lineCaps && i == pointsToDraw.Length - 1) { @@ -314,6 +290,7 @@ namespace UnityEngine.UI.Extensions private UIVertex[] CreateLineSegment(Vector2 start, Vector2 end, SegmentType type) { Vector2 offset = new Vector2((start.y - end.y), end.x - start.x).normalized * lineThickness / 2; + var v1 = start - offset; var v2 = start + offset; var v3 = end + offset; @@ -325,9 +302,54 @@ namespace UnityEngine.UI.Extensions return SetVbo(new[] { v1, v2, v3, v4 }, startUvs); case SegmentType.End: return SetVbo(new[] { v1, v2, v3, v4 }, endUvs); + case SegmentType.Full: + return SetVbo(new[] { v1, v2, v3, v4 }, fullUvs); default: return SetVbo(new[] { v1, v2, v3, v4 }, middleUvs); } } + + protected override void GeneratedUVs() + { + if (activeSprite != null) + { + var outer = Sprites.DataUtility.GetOuterUV(activeSprite); + var inner = Sprites.DataUtility.GetInnerUV(activeSprite); + UV_TOP_LEFT = new Vector2(outer.x, outer.y); + UV_BOTTOM_LEFT = new Vector2(outer.x, outer.w); + UV_TOP_CENTER_LEFT = new Vector2(inner.x, inner.y); + UV_TOP_CENTER_RIGHT = new Vector2(inner.z, inner.y); + UV_BOTTOM_CENTER_LEFT = new Vector2(inner.x, inner.w); + UV_BOTTOM_CENTER_RIGHT = new Vector2(inner.z, inner.w); + UV_TOP_RIGHT = new Vector2(outer.z, outer.y); + UV_BOTTOM_RIGHT = new Vector2(outer.z, outer.w); + } + else + { + UV_TOP_LEFT = Vector2.zero; + UV_BOTTOM_LEFT = new Vector2(0, 1); + UV_TOP_CENTER_LEFT = new Vector2(0.5f, 0); + UV_TOP_CENTER_RIGHT = new Vector2(0.5f, 0); + UV_BOTTOM_CENTER_LEFT = new Vector2(0.5f, 1); + UV_BOTTOM_CENTER_RIGHT = new Vector2(0.5f, 1); + UV_TOP_RIGHT = new Vector2(1, 0); + UV_BOTTOM_RIGHT = Vector2.one; + } + + + startUvs = new[] { UV_TOP_LEFT, UV_BOTTOM_LEFT, UV_BOTTOM_CENTER_LEFT, UV_TOP_CENTER_LEFT }; + middleUvs = new[] { UV_TOP_CENTER_LEFT, UV_BOTTOM_CENTER_LEFT, UV_BOTTOM_CENTER_RIGHT, UV_TOP_CENTER_RIGHT }; + endUvs = new[] { UV_TOP_CENTER_RIGHT, UV_BOTTOM_CENTER_RIGHT, UV_BOTTOM_RIGHT, UV_TOP_RIGHT }; + fullUvs = new[] { UV_TOP_LEFT, UV_BOTTOM_LEFT, UV_BOTTOM_RIGHT, UV_TOP_RIGHT }; + } + + protected override void ResolutionToNativeSize(float distance) + { + if (UseNativeSize) + { + m_Resolution = distance / (activeSprite.rect.width / pixelsPerUnit); + lineThickness = activeSprite.rect.height / pixelsPerUnit; + } + } } } \ No newline at end of file diff --git a/Scripts/Primitives/UIPrimitiveBase.cs b/Scripts/Primitives/UIPrimitiveBase.cs index 6af851a..54e534d 100644 --- a/Scripts/Primitives/UIPrimitiveBase.cs +++ b/Scripts/Primitives/UIPrimitiveBase.cs @@ -12,14 +12,16 @@ namespace UnityEngine.UI.Extensions public class UIPrimitiveBase : MaskableGraphic, ILayoutElement, ICanvasRaycastFilter { + static protected Material s_ETC1DefaultUI = null; - [SerializeField] - private Sprite m_Sprite; - public Sprite sprite { get { return m_Sprite; } set { if (SetPropertyUtility.SetClass(ref m_Sprite, value)) SetAllDirty(); } } + [SerializeField] private Sprite m_Sprite; + public Sprite sprite { get { return m_Sprite; } set { if (SetPropertyUtility.SetClass(ref m_Sprite, value)) ; GeneratedUVs(); SetAllDirty(); } } [NonSerialized] private Sprite m_OverrideSprite; - public Sprite overrideSprite { get { return m_OverrideSprite == null ? sprite : m_OverrideSprite; } set { if (SetPropertyUtility.SetClass(ref m_OverrideSprite, value)) SetAllDirty(); } } + public Sprite overrideSprite { get { return activeSprite; } set { if (SetPropertyUtility.SetClass(ref m_OverrideSprite, value)) GeneratedUVs(); SetAllDirty(); } } + + protected Sprite activeSprite { get { return m_OverrideSprite != null ? m_OverrideSprite : sprite; } } // Not serialized until we support read-enabled sprites better. internal float m_EventAlphaThreshold = 1; @@ -30,10 +32,31 @@ namespace UnityEngine.UI.Extensions public ResolutionMode ImproveResolution { get { return m_improveResolution; } set { m_improveResolution = value; SetAllDirty(); } } [SerializeField] - private float m_Resolution; + protected float m_Resolution; public float Resoloution { get { return m_Resolution; } set { m_Resolution = value; SetAllDirty(); } } + [SerializeField] + private bool m_useNativeSize; + public bool UseNativeSize { get { return m_useNativeSize; } set { m_useNativeSize = value; SetAllDirty(); } } + protected UIPrimitiveBase() + { + useLegacyMeshGeneration = false; + } + + /// + /// Default material used to draw everything if no explicit material was specified. + /// + + static public Material defaultETC1GraphicMaterial + { + get + { + if (s_ETC1DefaultUI == null) + s_ETC1DefaultUI = Canvas.GetETC1SupportedCanvasMaterial(); + return s_ETC1DefaultUI; + } + } /// /// Image's texture comes from the UnityEngine.Image. @@ -42,7 +65,7 @@ namespace UnityEngine.UI.Extensions { get { - if (overrideSprite == null) + if (activeSprite == null) { if (material != null && material.mainTexture != null) { @@ -51,7 +74,24 @@ namespace UnityEngine.UI.Extensions return s_WhiteTexture; } - return overrideSprite.texture; + return activeSprite.texture; + } + } + + /// + /// Whether the Image has a border to work with. + /// + + public bool hasBorder + { + get + { + if (activeSprite != null) + { + Vector4 v = activeSprite.border; + return v.sqrMagnitude > 0f; + } + return false; } } @@ -60,8 +100,8 @@ namespace UnityEngine.UI.Extensions get { float spritePixelsPerUnit = 100; - if (sprite) - spritePixelsPerUnit = sprite.pixelsPerUnit; + if (activeSprite) + spritePixelsPerUnit = activeSprite.pixelsPerUnit; float referencePixelsPerUnit = 100; if (canvas) @@ -71,6 +111,25 @@ namespace UnityEngine.UI.Extensions } } + 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; + } + } + protected UIVertex[] SetVbo(Vector2[] vertices, Vector2[] uvs) { @@ -98,6 +157,7 @@ namespace UnityEngine.UI.Extensions { totalDistance += Vector2.Distance(input[i], input[i + 1]); } + ResolutionToNativeSize(totalDistance); increments = totalDistance / m_Resolution; var incrementCount = 0; for (int i = 0; i < input.Length - 1; i++) @@ -121,6 +181,7 @@ namespace UnityEngine.UI.Extensions var p1 = input[i]; outputList.Add(p1); var p2 = input[i + 1]; + ResolutionToNativeSize(Vector2.Distance(p1, p2)); increments = 1f / m_Resolution; for (Single j = 1; j < m_Resolution; j++) { @@ -133,6 +194,11 @@ namespace UnityEngine.UI.Extensions return outputList.ToArray(); } + protected virtual void GeneratedUVs() { } + + protected virtual void ResolutionToNativeSize(float distance) { } + + #region ILayoutElement Interface public virtual void CalculateLayoutInputHorizontal() { }