From e205747c13b4af5a6a9c5e074e24276bfcdf983d Mon Sep 17 00:00:00 2001 From: "Simon (darkside) Jackson" Date: Wed, 25 May 2016 00:50:10 +0100 Subject: [PATCH] Updated Primatives for issue: https://bitbucket.org/ddreaper/unity-ui-extensions/issues/57/use-of-texture-instead-of-sprite-eg-in Refactored all primatives to use a new common base Updated primatives (using base) to align with current Unity Image component, including: * Using Sprites not textures (aka above issue) * Added ILayoutElement Interface * Added ICanvasRaycastFilter interface (experimental, can be overridden), includes basic alpha checking. --HG-- branch : develop_5.3 --- Scripts/Editor/UIExtensionsMenuOptions.cs | 16 +- Scripts/Primitives/DiamondGraph.cs | 4 +- Scripts/Primitives/UICircle.cs | 49 +---- Scripts/Primitives/UICornerCut.cs | 11 +- Scripts/Primitives/UILineRenderer.cs | 46 +---- Scripts/Primitives/UILineTextureRenderer.cs | 46 +---- Scripts/Primitives/UIPolygon.cs | 40 +--- Scripts/Primitives/UIPrimativeBase.cs | 217 ++++++++++++++++++++ Scripts/Primitives/UIPrimativeBase.cs.meta | 12 ++ 9 files changed, 253 insertions(+), 188 deletions(-) create mode 100644 Scripts/Primitives/UIPrimativeBase.cs create mode 100644 Scripts/Primitives/UIPrimativeBase.cs.meta diff --git a/Scripts/Editor/UIExtensionsMenuOptions.cs b/Scripts/Editor/UIExtensionsMenuOptions.cs index eef2dd1..8f53522 100644 --- a/Scripts/Editor/UIExtensionsMenuOptions.cs +++ b/Scripts/Editor/UIExtensionsMenuOptions.cs @@ -1103,21 +1103,29 @@ namespace UnityEditor.UI Selection.activeGameObject = go; } - [MenuItem("GameObject/UI/Extensions/Primitives/Diamond Graph", false)] + [MenuItem("GameObject/UI/Extensions/Primitives/UI Diamond Graph", false)] static public void AddDiamondGraph(MenuCommand menuCommand) { - GameObject go = CreateUIElementRoot("Diamond Graph", menuCommand, s_ImageGUIElementSize); + GameObject go = CreateUIElementRoot("UI Diamond Graph", menuCommand, s_ImageGUIElementSize); go.AddComponent(); Selection.activeGameObject = go; } - [MenuItem("GameObject/UI/Extensions/Primitives/Cut Corners", false)] + [MenuItem("GameObject/UI/Extensions/Primitives/UI Cut Corners", false)] static public void AddCutCorners(MenuCommand menuCommand) { - GameObject go = CreateUIElementRoot("Cut Corners", menuCommand, s_ImageGUIElementSize); + GameObject go = CreateUIElementRoot("UI Cut Corners", menuCommand, s_ImageGUIElementSize); go.AddComponent(); Selection.activeGameObject = go; } + + [MenuItem("GameObject/UI/Extensions/Primitives/UI Polygon", false)] + static public void AddPolygon(MenuCommand menuCommand) + { + GameObject go = CreateUIElementRoot("UI Polygon", menuCommand, s_ImageGUIElementSize); + go.AddComponent(); + Selection.activeGameObject = go; + } #endregion #region Re-Orderable Lists diff --git a/Scripts/Primitives/DiamondGraph.cs b/Scripts/Primitives/DiamondGraph.cs index 4f63516..4efcb72 100644 --- a/Scripts/Primitives/DiamondGraph.cs +++ b/Scripts/Primitives/DiamondGraph.cs @@ -1,14 +1,12 @@ /// Credit koohddang /// Sourced from - http://forum.unity3d.com/threads/onfillvbo-to-onpopulatemesh-help.353977/#post-2299311 -using System.Collections.Generic; using System; namespace UnityEngine.UI.Extensions { - [ExecuteInEditMode] [AddComponentMenu("UI/Extensions/Primitives/Diamond Graph")] - public class DiamondGraph : Graphic + public class DiamondGraph : UIPrimativeBase { public float a = 1; public float b = 1; diff --git a/Scripts/Primitives/UICircle.cs b/Scripts/Primitives/UICircle.cs index b054fbe..c87a957 100644 --- a/Scripts/Primitives/UICircle.cs +++ b/Scripts/Primitives/UICircle.cs @@ -5,10 +5,8 @@ namespace UnityEngine.UI.Extensions { [AddComponentMenu("UI/Extensions/Primitives/UI Circle")] - public class UICircle : MaskableGraphic + public class UICircle : UIPrimativeBase { - [SerializeField] - Texture m_Texture; [Tooltip("The circular fill percentage of the primitive, affected by FixedToSegments")] [Range(0, 100)] public int fillPercent = 100; @@ -21,54 +19,12 @@ namespace UnityEngine.UI.Extensions [Tooltip("The number of segments to draw the primitive, more segments = smoother primitive")] [Range(0, 360)] public int segments = 360; - - public override Texture mainTexture - { - get - { - return m_Texture == null ? s_WhiteTexture : m_Texture; - } - } - - /// - /// Texture to be used. - /// - public Texture texture - { - get - { - return m_Texture; - } - set - { - if (m_Texture == value) - return; - - m_Texture = value; - SetVerticesDirty(); - SetMaterialDirty(); - } - } - + void Update() { this.thickness = (float)Mathf.Clamp(this.thickness, 0, rectTransform.rect.width / 2); } - protected UIVertex[] SetVbo(Vector2[] vertices, Vector2[] uvs) - { - UIVertex[] vbo = new UIVertex[4]; - for (int i = 0; i < vertices.Length; i++) - { - var vert = UIVertex.simpleVert; - vert.color = color; - vert.position = vertices[i]; - vert.uv0 = uvs[i]; - vbo[i] = vert; - } - return vbo; - } - protected override void OnPopulateMesh(VertexHelper vh) { float outer = -rectTransform.pivot.x * rectTransform.rect.width; @@ -156,5 +112,6 @@ namespace UnityEngine.UI.Extensions prevX = pos1; prevY = pos2; } + } } \ No newline at end of file diff --git a/Scripts/Primitives/UICornerCut.cs b/Scripts/Primitives/UICornerCut.cs index 2e6bd88..6342441 100644 --- a/Scripts/Primitives/UICornerCut.cs +++ b/Scripts/Primitives/UICornerCut.cs @@ -15,14 +15,13 @@ /// http://rumorgames.com/hide-in-inspector/ /// /// - + namespace UnityEngine.UI.Extensions { - [ExecuteInEditMode] [AddComponentMenu("UI/Extensions/Primitives/Cut Corners")] - public class UICornerCut : MaskableGraphic { - - public Vector2 cornerSize = new Vector2(16, 16); - + public class UICornerCut : UIPrimativeBase + { + public Vector2 cornerSize = new Vector2(16, 16); + [Header("Corners to cut")] public bool cutUL = true; public bool cutUR; diff --git a/Scripts/Primitives/UILineRenderer.cs b/Scripts/Primitives/UILineRenderer.cs index a4a6996..2ddaa7c 100644 --- a/Scripts/Primitives/UILineRenderer.cs +++ b/Scripts/Primitives/UILineRenderer.cs @@ -7,7 +7,7 @@ using System.Collections.Generic; namespace UnityEngine.UI.Extensions { [AddComponentMenu("UI/Extensions/Primitives/UILineRenderer")] - public class UILineRenderer : MaskableGraphic + public class UILineRenderer : UIPrimativeBase { private enum SegmentType { @@ -47,9 +47,6 @@ namespace UnityEngine.UI.Extensions 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] - private Texture m_Texture; [SerializeField] private Rect m_UVRect = new Rect(0f, 0f, 1f, 1f); [SerializeField] @@ -68,34 +65,6 @@ namespace UnityEngine.UI.Extensions public BezierType BezierMode = BezierType.None; public int BezierSegmentsPerCurve = 10; - public override Texture mainTexture - { - get - { - return m_Texture == null ? s_WhiteTexture : m_Texture; - } - } - - /// - /// Texture to be used. - /// - public Texture texture - { - get - { - return m_Texture; - } - set - { - if (m_Texture == value) - return; - - m_Texture = value; - SetVerticesDirty(); - SetMaterialDirty(); - } - } - /// /// UV rectangle used by the texture. /// @@ -320,18 +289,5 @@ namespace UnityEngine.UI.Extensions return SetVbo(new[] { v1, v2, v3, v4 }, uvs); } - protected UIVertex[] SetVbo(Vector2[] vertices, Vector2[] uvs) - { - UIVertex[] vbo = new UIVertex[4]; - for (int i = 0; i < vertices.Length; i++) - { - var vert = UIVertex.simpleVert; - vert.color = color; - vert.position = vertices[i]; - vert.uv0 = uvs[i]; - vbo[i] = vert; - } - return vbo; - } } } \ No newline at end of file diff --git a/Scripts/Primitives/UILineTextureRenderer.cs b/Scripts/Primitives/UILineTextureRenderer.cs index fcb88c1..13bb071 100644 --- a/Scripts/Primitives/UILineTextureRenderer.cs +++ b/Scripts/Primitives/UILineTextureRenderer.cs @@ -7,10 +7,8 @@ using System.Collections.Generic; namespace UnityEngine.UI.Extensions { [AddComponentMenu("UI/Extensions/Primitives/UILineTextureRenderer")] - public class UILineTextureRenderer : MaskableGraphic + public class UILineTextureRenderer : UIPrimativeBase { - [SerializeField] - Texture m_Texture; [SerializeField] Rect m_UVRect = new Rect(0f, 0f, 1f, 1f); [SerializeField] @@ -21,34 +19,6 @@ namespace UnityEngine.UI.Extensions public Vector2 Margin; public bool relativeSize; - public override Texture mainTexture - { - get - { - return m_Texture == null ? s_WhiteTexture : m_Texture; - } - } - - /// - /// Texture to be used. - /// - public Texture texture - { - get - { - return m_Texture; - } - set - { - if (m_Texture == value) - return; - - m_Texture = value; - SetVerticesDirty(); - SetMaterialDirty(); - } - } - /// /// UV rectangle used by the texture. /// @@ -178,20 +148,6 @@ namespace UnityEngine.UI.Extensions } } - protected UIVertex[] SetVbo(Vector2[] vertices, Vector2[] uvs) - { - UIVertex[] vbo = new UIVertex[4]; - for (int i = 0; i < vertices.Length; i++) - { - var vert = UIVertex.simpleVert; - vert.color = color; - vert.position = vertices[i]; - vert.uv0 = uvs[i]; - vbo[i] = vert; - } - return vbo; - } - public Vector3 RotatePointAroundPivot(Vector3 point, Vector3 pivot, Vector3 angles) { Vector3 dir = point - pivot; // get point direction relative to pivot diff --git a/Scripts/Primitives/UIPolygon.cs b/Scripts/Primitives/UIPolygon.cs index d939924..f9ba09f 100644 --- a/Scripts/Primitives/UIPolygon.cs +++ b/Scripts/Primitives/UIPolygon.cs @@ -1,15 +1,11 @@ /// Credit CiaccoDavide /// Sourced from - http://ciaccodavi.de/unity/UIPolygon -using System.Collections.Generic; - namespace UnityEngine.UI.Extensions { [AddComponentMenu("UI/Extensions/Primitives/UI Polygon")] - public class UIPolygon : MaskableGraphic + public class UIPolygon : UIPrimativeBase { - [SerializeField] - Texture m_Texture; public bool fill = true; public float thickness = 5; [Range(3, 360)] @@ -20,27 +16,6 @@ namespace UnityEngine.UI.Extensions public float[] VerticesDistances = new float[3]; private float size = 0; - public override Texture mainTexture - { - get - { - return m_Texture == null ? s_WhiteTexture : m_Texture; - } - } - public Texture texture - { - get - { - return m_Texture; - } - set - { - if (m_Texture == value) return; - m_Texture = value; - SetVerticesDirty(); - SetMaterialDirty(); - } - } public void DrawPolygon(int _sides) { sides = _sides; @@ -69,19 +44,6 @@ namespace UnityEngine.UI.Extensions size = rectTransform.rect.width; thickness = (float)Mathf.Clamp(thickness, 0, size / 2); } - protected UIVertex[] SetVbo(Vector2[] vertices, Vector2[] uvs) - { - UIVertex[] vbo = new UIVertex[4]; - for (int i = 0; i < vertices.Length; i++) - { - var vert = UIVertex.simpleVert; - vert.color = color; - vert.position = vertices[i]; - vert.uv0 = uvs[i]; - vbo[i] = vert; - } - return vbo; - } protected override void OnPopulateMesh(VertexHelper vh) { diff --git a/Scripts/Primitives/UIPrimativeBase.cs b/Scripts/Primitives/UIPrimativeBase.cs new file mode 100644 index 0000000..b99e737 --- /dev/null +++ b/Scripts/Primitives/UIPrimativeBase.cs @@ -0,0 +1,217 @@ +using System; + +namespace UnityEngine.UI.Extensions +{ + public class UIPrimativeBase : MaskableGraphic, ILayoutElement, ICanvasRaycastFilter + { + + [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 m_OverrideSprite == null ? sprite : m_OverrideSprite; } set { if (SetPropertyUtility.SetClass(ref m_OverrideSprite, value)) SetAllDirty(); } } + + // Not serialized until we support read-enabled sprites better. + internal float m_EventAlphaThreshold = 1; + public float eventAlphaThreshold { get { return m_EventAlphaThreshold; } set { m_EventAlphaThreshold = value; } } + + + + /// + /// Image's texture comes from the UnityEngine.Image. + /// + public override Texture mainTexture + { + get + { + if (overrideSprite == null) + { + if (material != null && material.mainTexture != null) + { + return material.mainTexture; + } + return s_WhiteTexture; + } + + return overrideSprite.texture; + } + } + + public float pixelsPerUnit + { + get + { + float spritePixelsPerUnit = 100; + if (sprite) + spritePixelsPerUnit = sprite.pixelsPerUnit; + + float referencePixelsPerUnit = 100; + if (canvas) + referencePixelsPerUnit = canvas.referencePixelsPerUnit; + + return spritePixelsPerUnit / referencePixelsPerUnit; + } + } + + + protected UIVertex[] SetVbo(Vector2[] vertices, Vector2[] uvs) + { + UIVertex[] vbo = new UIVertex[4]; + for (int i = 0; i < vertices.Length; i++) + { + var vert = UIVertex.simpleVert; + vert.color = color; + vert.position = vertices[i]; + vert.uv0 = uvs[i]; + vbo[i] = vert; + } + return vbo; + } + + + #region ILayoutElement Interface + + public virtual void CalculateLayoutInputHorizontal() { } + public virtual void CalculateLayoutInputVertical() { } + + public virtual float minWidth { get { return 0; } } + + public virtual float preferredWidth + { + get + { + if (overrideSprite == null) + return 0; + return overrideSprite.rect.size.x / pixelsPerUnit; + } + } + + public virtual float flexibleWidth { get { return -1; } } + + public virtual float minHeight { get { return 0; } } + + public virtual float preferredHeight + { + get + { + if (overrideSprite == null) + return 0; + return overrideSprite.rect.size.y / pixelsPerUnit; + } + } + + public virtual float flexibleHeight { get { return -1; } } + + public virtual int layoutPriority { get { return 0; } } + + #endregion + + #region ICanvasRaycastFilter Interface + public virtual bool IsRaycastLocationValid(Vector2 screenPoint, Camera eventCamera) + { + if (m_EventAlphaThreshold >= 1) + return true; + + Sprite sprite = overrideSprite; + if (sprite == null) + return true; + + Vector2 local; + RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, screenPoint, eventCamera, out local); + + 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 = sprite.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) / sprite.texture.width; + float y = Mathf.Lerp(spriteRect.y, spriteRect.yMax, normalized.y) / sprite.texture.height; + + try + { + return sprite.texture.GetPixelBilinear(x, y).a >= m_EventAlphaThreshold; + } + catch (UnityException e) + { + Debug.LogError("Using clickAlphaThreshold lower than 1 on Image whose sprite texture cannot be read. " + e.Message + " Also make sure to disable sprite packing for this sprite.", this); + return true; + } + } + + /// + /// Return image adjusted position + /// **Copied from Unity's Image component for now and simplified for UI Extensions primatives + /// + /// + /// + /// + private Vector2 MapCoordinate(Vector2 local, Rect rect) + { + Rect spriteRect = sprite.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 = sprite.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; + } + + Vector4 GetAdjustedBorders(Vector4 border, Rect rect) + { + for (int axis = 0; axis <= 1; axis++) + { + // 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 (rect.size[axis] < combinedBorders && combinedBorders != 0) + { + float borderScaleRatio = rect.size[axis] / combinedBorders; + border[axis] *= borderScaleRatio; + border[axis + 2] *= borderScaleRatio; + } + } + return border; + } + + #endregion + + + } +} diff --git a/Scripts/Primitives/UIPrimativeBase.cs.meta b/Scripts/Primitives/UIPrimativeBase.cs.meta new file mode 100644 index 0000000..a630cc9 --- /dev/null +++ b/Scripts/Primitives/UIPrimativeBase.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 65af11d29c6cb8c45b3d78d97d98440d +timeCreated: 1464131942 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: