diff --git a/Scripts/Accordion/Editor/AccordionElementEditor.cs b/Scripts/Accordion/Editor/AccordionElementEditor.cs index 29e8d8e..92e53f4 100644 --- a/Scripts/Accordion/Editor/AccordionElementEditor.cs +++ b/Scripts/Accordion/Editor/AccordionElementEditor.cs @@ -1,23 +1,23 @@ -///Credit ChoMPHi +///Credit ChoMPHi ///Sourced from - http://forum.unity3d.com/threads/accordion-type-layout.271818/ -using UnityEngine.UI.Extensions; - -namespace UnityEditor.UI -{ - [CustomEditor(typeof(AccordionElement), true)] - public class AccordionElementEditor : ToggleEditor { - - public override void OnInspectorGUI() - { - this.serializedObject.Update(); - EditorGUILayout.PropertyField(this.serializedObject.FindProperty("m_MinHeight")); - this.serializedObject.ApplyModifiedProperties(); - - base.serializedObject.Update(); - EditorGUILayout.PropertyField(base.serializedObject.FindProperty("m_IsOn")); - EditorGUILayout.PropertyField(base.serializedObject.FindProperty("m_Interactable")); - base.serializedObject.ApplyModifiedProperties(); - } - } +using UnityEngine.UI.Extensions; + +namespace UnityEditor.UI +{ + [CustomEditor(typeof(AccordionElement), true)] + public class AccordionElementEditor : ToggleEditor { + + public override void OnInspectorGUI() + { + this.serializedObject.Update(); + EditorGUILayout.PropertyField(this.serializedObject.FindProperty("m_MinHeight")); + this.serializedObject.ApplyModifiedProperties(); + + base.serializedObject.Update(); + EditorGUILayout.PropertyField(base.serializedObject.FindProperty("m_IsOn")); + EditorGUILayout.PropertyField(base.serializedObject.FindProperty("m_Interactable")); + base.serializedObject.ApplyModifiedProperties(); + } + } } \ No newline at end of file diff --git a/Scripts/Accordion/Tweening/ITweenValue.cs b/Scripts/Accordion/Tweening/ITweenValue.cs index 7f09a75..25d135b 100644 --- a/Scripts/Accordion/Tweening/ITweenValue.cs +++ b/Scripts/Accordion/Tweening/ITweenValue.cs @@ -1,16 +1,16 @@ -///Credit ChoMPHi -///Sourced from - http://forum.unity3d.com/threads/accordion-type-layout.271818/ - +///Credit ChoMPHi +///Sourced from - http://forum.unity3d.com/threads/accordion-type-layout.271818/ + using System.Collections; namespace UnityEngine.UI.Extensions.Tweens -{ - internal interface ITweenValue - { - void TweenValue(float floatPercentage); - bool ignoreTimeScale { get; } - float duration { get; } - bool ValidTarget(); - void Finished(); - } +{ + internal interface ITweenValue + { + void TweenValue(float floatPercentage); + bool ignoreTimeScale { get; } + float duration { get; } + bool ValidTarget(); + void Finished(); + } } \ No newline at end of file diff --git a/Scripts/Accordion/Tweening/TweenRunner.cs b/Scripts/Accordion/Tweening/TweenRunner.cs index 3a0fe8f..8a3a8e3 100644 --- a/Scripts/Accordion/Tweening/TweenRunner.cs +++ b/Scripts/Accordion/Tweening/TweenRunner.cs @@ -1,63 +1,63 @@ -///Credit ChoMPHi -///Sourced from - http://forum.unity3d.com/threads/accordion-type-layout.271818/ - +///Credit ChoMPHi +///Sourced from - http://forum.unity3d.com/threads/accordion-type-layout.271818/ + using System.Collections; namespace UnityEngine.UI.Extensions.Tweens -{ - // Tween runner, executes the given tween. - // The coroutine will live within the given - // behaviour container. - internal class TweenRunner where T : struct, ITweenValue - { - protected MonoBehaviour m_CoroutineContainer; - protected IEnumerator m_Tween; - - // utility function for starting the tween - private static IEnumerator Start(T tweenInfo) - { - if (!tweenInfo.ValidTarget()) - yield break; - - float elapsedTime = 0.0f; - while (elapsedTime < tweenInfo.duration) - { - elapsedTime += tweenInfo.ignoreTimeScale ? Time.unscaledDeltaTime : Time.deltaTime; - var percentage = Mathf.Clamp01 (elapsedTime / tweenInfo.duration); - tweenInfo.TweenValue (percentage); - yield return null; - } - tweenInfo.TweenValue (1.0f); - tweenInfo.Finished(); - } - - public void Init(MonoBehaviour coroutineContainer) - { - m_CoroutineContainer = coroutineContainer; - } - - public void StartTween(T info) - { - if (m_CoroutineContainer == null) - { - Debug.LogWarning ("Coroutine container not configured... did you forget to call Init?"); - return; - } - - if (m_Tween != null) - { - m_CoroutineContainer.StopCoroutine (m_Tween); - m_Tween = null; - } - - if (!m_CoroutineContainer.gameObject.activeInHierarchy) - { - info.TweenValue(1.0f); - return; - } - - m_Tween = Start (info); - m_CoroutineContainer.StartCoroutine (m_Tween); - } - } +{ + // Tween runner, executes the given tween. + // The coroutine will live within the given + // behaviour container. + internal class TweenRunner where T : struct, ITweenValue + { + protected MonoBehaviour m_CoroutineContainer; + protected IEnumerator m_Tween; + + // utility function for starting the tween + private static IEnumerator Start(T tweenInfo) + { + if (!tweenInfo.ValidTarget()) + yield break; + + float elapsedTime = 0.0f; + while (elapsedTime < tweenInfo.duration) + { + elapsedTime += tweenInfo.ignoreTimeScale ? Time.unscaledDeltaTime : Time.deltaTime; + var percentage = Mathf.Clamp01 (elapsedTime / tweenInfo.duration); + tweenInfo.TweenValue (percentage); + yield return null; + } + tweenInfo.TweenValue (1.0f); + tweenInfo.Finished(); + } + + public void Init(MonoBehaviour coroutineContainer) + { + m_CoroutineContainer = coroutineContainer; + } + + public void StartTween(T info) + { + if (m_CoroutineContainer == null) + { + Debug.LogWarning ("Coroutine container not configured... did you forget to call Init?"); + return; + } + + if (m_Tween != null) + { + m_CoroutineContainer.StopCoroutine (m_Tween); + m_Tween = null; + } + + if (!m_CoroutineContainer.gameObject.activeInHierarchy) + { + info.TweenValue(1.0f); + return; + } + + m_Tween = Start (info); + m_CoroutineContainer.StartCoroutine (m_Tween); + } + } } \ No newline at end of file diff --git a/Scripts/ComboBox/AutoCompleteComboBox.cs b/Scripts/ComboBox/AutoCompleteComboBox.cs index dfdc006..41642f0 100644 --- a/Scripts/ComboBox/AutoCompleteComboBox.cs +++ b/Scripts/ComboBox/AutoCompleteComboBox.cs @@ -60,7 +60,7 @@ namespace UnityEngine.UI.Extensions } // private int scrollOffset; //offset of the selected item - private int _selectedIndex = 0; + // private int _selectedIndex = 0; [SerializeField] private int _itemsToDisplay; @@ -122,7 +122,7 @@ namespace UnityEngine.UI.Extensions _panelItems = AvailableOptions.ToList(); RebuildPanel(); - RedrawPanel(); + //RedrawPanel(); - causes an initialisation failure in U5 return success; } diff --git a/Scripts/ComboBox/ComboBox.cs b/Scripts/ComboBox/ComboBox.cs index 6a4775b..0c80757 100644 --- a/Scripts/ComboBox/ComboBox.cs +++ b/Scripts/ComboBox/ComboBox.cs @@ -59,7 +59,7 @@ namespace UnityEngine.UI.Extensions } // private int scrollOffset; //offset of the selected item - private int _selectedIndex = 0; + // private int _selectedIndex = 0; [SerializeField] private int _itemsToDisplay; @@ -120,7 +120,7 @@ namespace UnityEngine.UI.Extensions _panelItems = AvailableOptions.ToList(); RebuildPanel(); - RedrawPanel(); + //RedrawPanel(); - causes an initialisation failure in U5 return success; } diff --git a/Scripts/Editor/UIExtensionsMenuOptions.cs b/Scripts/Editor/UIExtensionsMenuOptions.cs index 33b34fb..330d2a8 100644 --- a/Scripts/Editor/UIExtensionsMenuOptions.cs +++ b/Scripts/Editor/UIExtensionsMenuOptions.cs @@ -236,7 +236,7 @@ namespace UnityEditor.UI horizontalScrollSnapRoot.AddComponent(); //Setup Content container - RectTransform rectTransformContent = childContent.AddComponent(); + RectTransform rectTransformContent = childContent.GetComponent(); rectTransformContent.anchorMin = Vector2.zero; rectTransformContent.anchorMax = new Vector2(1f, 1f); //rectTransformContent.anchoredPosition = Vector2.zero; @@ -791,6 +791,21 @@ namespace UnityEditor.UI SetDefaultColorTransitionValues(slider); } + [MenuItem("GameObject/UI/Extensions/UI Line Renderer", false)] + static public void AddUILineRenderer(MenuCommand menuCommand) + { + GameObject go = CreateUIElementRoot("UI LineRenderer", menuCommand, s_ImageGUIElementSize); + go.AddComponent(); + Selection.activeGameObject = go; + } + + [MenuItem("GameObject/UI/Extensions/UI Line Texture Renderer", false)] + static public void AddUILineTextureRenderer(MenuCommand menuCommand) + { + GameObject go = CreateUIElementRoot("UI LineTextureRenderer", menuCommand, s_ImageGUIElementSize); + go.AddComponent(); + Selection.activeGameObject = go; + } #endregion diff --git a/Scripts/HSVPicker/ColorPickerTester.cs b/Scripts/HSVPicker/ColorPickerTester.cs index 4a1d0f4..212f187 100644 --- a/Scripts/HSVPicker/ColorPickerTester.cs +++ b/Scripts/HSVPicker/ColorPickerTester.cs @@ -5,15 +5,19 @@ namespace UnityEngine.UI.Extensions { public class ColorPickerTester : MonoBehaviour { - public Renderer renderer; + public Renderer pickerRenderer; public HSVPicker picker; + void Awake() + { + pickerRenderer = GetComponent(); + } // Use this for initialization void Start() { picker.onValueChanged.AddListener(color => { - renderer.material.color = color; + pickerRenderer.material.color = color; }); } } diff --git a/Scripts/HSVPicker/HSVSliderEvent.cs b/Scripts/HSVPicker/HSVSliderEvent.cs index d76876a..5fbc5f1 100644 --- a/Scripts/HSVPicker/HSVSliderEvent.cs +++ b/Scripts/HSVPicker/HSVSliderEvent.cs @@ -1,4 +1,4 @@ -///Credit judah4 +///Credit judah4 ///Sourced from - http://forum.unity3d.com/threads/color-picker.267043/ using UnityEngine.Events; @@ -8,4 +8,4 @@ namespace UnityEngine.UI.Extensions { } -} +} diff --git a/Scripts/HSVPicker/HsvSliderPicker.cs b/Scripts/HSVPicker/HsvSliderPicker.cs index 9e6dabe..61b3a4f 100644 --- a/Scripts/HSVPicker/HsvSliderPicker.cs +++ b/Scripts/HSVPicker/HsvSliderPicker.cs @@ -1,4 +1,4 @@ -///Credit judah4 +///Credit judah4 ///Sourced from - http://forum.unity3d.com/threads/color-picker.267043/ using UnityEngine.EventSystems; diff --git a/Scripts/ImageExtended.cs b/Scripts/ImageExtended.cs new file mode 100644 index 0000000..d88f7f8 --- /dev/null +++ b/Scripts/ImageExtended.cs @@ -0,0 +1,1074 @@ +/// Credit Ges +/// Sourced from - http://forum.unity3d.com/threads/scripts-useful-4-6-scripts-collection.264161/page-2#post-2062320 + +using System; +using System.Collections.Generic; +using UnityEngine.Serialization; + +namespace UnityEngine.UI.Extensions +{ + /// + /// Image is a textured element in the UI hierarchy. + /// + + [AddComponentMenu("UI/Extensions/Image Extended")] + public class ImageExtended : 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, + } + + public enum Rotate + { + Rotate0, + Rotate90, + Rotate180, + Rotate270, + } + + [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 m_OverrideSprite == null ? sprite : m_OverrideSprite; } set { if (SetPropertyUtility.SetClass(ref m_OverrideSprite, value)) SetAllDirty(); } } + + /// 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(); } } + + [SerializeField] + private Rotate m_Rotate = Rotate.Rotate0; + public Rotate rotate { get { return m_Rotate; } set { if (SetPropertyUtility.SetStruct(ref m_Rotate, value)) SetVerticesDirty(); } } + + // Not serialized until we support read-enabled sprites better. + private float m_EventAlphaThreshold = 1; + public float eventAlphaThreshold { get { return m_EventAlphaThreshold; } set { m_EventAlphaThreshold = value; } } + + protected ImageExtended() + { } + + /// + /// Image's texture comes from the UnityEngine.Image. + /// + public override Texture mainTexture + { + get + { + return overrideSprite == null ? s_WhiteTexture : overrideSprite.texture; + } + } + + /// + /// Whether the Image has a border to work with. + /// + + public bool hasBorder + { + get + { + if (overrideSprite != null) + { + Vector4 v = overrideSprite.border; + return v.sqrMagnitude > 0f; + } + return false; + } + } + + public float pixelsPerUnit + { + get + { + float spritePixelsPerUnit = 100; + if (sprite) + spritePixelsPerUnit = sprite.pixelsPerUnit; + + float referencePixelsPerUnit = 100; + if (canvas) + referencePixelsPerUnit = canvas.referencePixelsPerUnit; + + return spritePixelsPerUnit / referencePixelsPerUnit; + } + } + + 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 = overrideSprite == null ? Vector4.zero : Sprites.DataUtility.GetPadding(overrideSprite); + var size = overrideSprite == null ? Vector2.zero : new Vector2(overrideSprite.rect.width, overrideSprite.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 = overrideSprite == null ? new Vector4(0, 0, 1, 1) : + 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 (overrideSprite != null) + { + float w = overrideSprite.rect.width / pixelsPerUnit; + float h = overrideSprite.rect.height / pixelsPerUnit; + rectTransform.anchorMax = rectTransform.anchorMin; + rectTransform.sizeDelta = new Vector2(w, h); + SetAllDirty(); + } + } + + /// + /// Update the UI renderer mesh. + /// + + protected override void OnFillVBO(List vbo) + { + switch (type) + { + case Type.Simple: + GenerateSimpleSprite(vbo, m_PreserveAspect); + break; + case Type.Sliced: + GenerateSlicedSprite(vbo); + break; + case Type.Tiled: + GenerateTiledSprite(vbo); + break; + case Type.Filled: + GenerateFilledSprite(vbo, m_PreserveAspect); + break; + } + } + + #region Various fill functions + /// + /// Generate vertices for a simple Image. + /// + + void GenerateSimpleSprite(List vbo, bool preserveAspect) + { + var vert = UIVertex.simpleVert; + vert.color = color; + + Vector4 v = GetDrawingDimensions(preserveAspect); + var uv = (overrideSprite != null) ? Sprites.DataUtility.GetOuterUV(overrideSprite) : Vector4.zero; + + AddQuad(vbo, vert, + new Vector2(v.x, v.y), new Vector2(v.z, v.w), + new Vector2(uv.x, uv.y), new Vector2(uv.z, uv.w)); + } + + /// + /// Generate vertices for a 9-sliced Image. + /// + + static readonly Vector2[] s_VertScratch = new Vector2[4]; + static readonly Vector2[] s_UVScratch = new Vector2[4]; + void GenerateSlicedSprite(List vbo) + { + if (!hasBorder) + { + GenerateSimpleSprite(vbo, false); + return; + } + + Vector4 outer, inner, padding, border; + + if (overrideSprite != null) + { + outer = Sprites.DataUtility.GetOuterUV(overrideSprite); + inner = Sprites.DataUtility.GetInnerUV(overrideSprite); + padding = Sprites.DataUtility.GetPadding(overrideSprite); + border = overrideSprite.border; + } + else + { + outer = Vector4.zero; + inner = Vector4.zero; + padding = Vector4.zero; + border = Vector4.zero; + } + + Rect rect = GetPixelAdjustedRect(); + border = GetAdjustedBorders(border / pixelsPerUnit, rect); + padding = padding / pixelsPerUnit; + + int offset = 4 - (int)rotate; + for (int i = 0; i < 4; ++i) + { + s_VertScratch[(4 - i / 2) % 4][i % 2] = padding[(i + offset) % 4]; + s_VertScratch[1 + i / 2][i % 2] = border[(i + offset) % 4]; + } + for (int i = 2; i < 4; ++i) + { + s_VertScratch[i].x = rect.width - s_VertScratch[i].x; + s_VertScratch[i].y = rect.height - s_VertScratch[i].y; + } + 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); + + var uiv = UIVertex.simpleVert; + uiv.color = color; + 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; + + int vx1 = x, vy1 = y; + int vx2 = x2, vy2 = y2; + for (int i = 0; i < (int)rotate; ++i) + { + int t1 = 4 - vy1 - 1; + vy1 = vx1; vx1 = t1; + int t2 = 4 - vy2 - 1; + vy2 = vx2; vx2 = t2; + } + int ux1 = x, uy1 = y; + int ux2 = x2, uy2 = y2; + if ((int)rotate >= 2) + { + ux1 = x2; ux2 = x; + } + if (((int)rotate + 1) % 4 >= 2) + { + uy1 = y2; uy2 = y; + } + if (Mathf.Abs(s_VertScratch[vx1].x - s_VertScratch[vx2].x) < Mathf.Epsilon) + continue; + if (Mathf.Abs(s_VertScratch[vy1].y - s_VertScratch[vy2].y) < Mathf.Epsilon) + continue; + AddQuad(vbo, uiv, + new Vector2(s_VertScratch[vx1].x, s_VertScratch[vy1].y), + new Vector2(s_VertScratch[vx2].x, s_VertScratch[vy2].y), + new Vector2(s_UVScratch[ux1].x, s_UVScratch[uy1].y), + new Vector2(s_UVScratch[ux2].x, s_UVScratch[uy2].y)); + } + } + } + + /// + /// Generate vertices for a tiled Image. + /// + + static readonly Vector2[] s_UVTiled = new Vector2[2]; + void GenerateTiledSprite(List vbo) + { + Vector4 outer, inner, border; + Vector2 spriteSize; + + if (overrideSprite != null) + { + outer = Sprites.DataUtility.GetOuterUV(overrideSprite); + inner = Sprites.DataUtility.GetInnerUV(overrideSprite); + border = overrideSprite.border; + spriteSize = overrideSprite.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); + + int offset = 4 - (int)rotate; + int rx = (0 + offset) % 4, ry = (1 + offset) % 4, rz = (2 + offset) % 4, rw = (3 + offset) % 4; + + var v = UIVertex.simpleVert; + v.color = color; + + // Min to max max range for tiled region in coordinates relative to lower left corner. + float xMin = border[rx]; + float xMax = rect.width - border[rz]; + float yMin = border[ry]; + float yMax = rect.height - border[rw]; + + // Safety check. Useful so Unity doesn't run out of memory if the sprites are too small. + // Max tiles are 100 x 100. + if ((xMax - xMin) > tileWidth * 100 || (yMax - yMin) > tileHeight * 100) + { + tileWidth = (xMax - xMin) / 100; + tileHeight = (yMax - yMin) / 100; + } + if ((int)rotate % 2 == 1) + { + float t = tileWidth; + tileWidth = tileHeight; + tileHeight = t; + } + + if (m_FillCenter) + { + for (float y1 = yMin; y1 < yMax; y1 += tileHeight) + { + s_UVTiled[0] = new Vector2(inner.x, inner.y); + s_UVTiled[1] = new Vector2(inner.z, inner.w); + float y2 = y1 + tileHeight; + if (y2 > yMax) + { + int k1 = 1 - (int)rotate / 2, k2 = 1 - (int)rotate % 2; + s_UVTiled[k1][k2] = s_UVTiled[1 - k1][k2] + (s_UVTiled[k1][k2] - s_UVTiled[1 - k1][k2]) * (yMax - y1) / (y2 - y1); + y2 = yMax; + } + for (float x1 = xMin; x1 < xMax; x1 += tileWidth) + { + float x2 = x1 + tileWidth; + if (x2 > xMax) + { + int k1 = ((int)rotate + 3) % 4 / 2, k2 = (int)rotate % 2; + s_UVTiled[k1][k2] = s_UVTiled[1 - k1][k2] + (s_UVTiled[k1][k2] - s_UVTiled[1 - k1][k2]) * (xMax - x1) / (x2 - x1); + x2 = xMax; + } + AddQuad(vbo, v, new Vector2(x1, y1) + rect.position, new Vector2(x2, y2) + rect.position, s_UVTiled[0], s_UVTiled[1]); + } + } + } + + if (!hasBorder) + return; + + // Bottom and top tiled border + for (int i = 0; i < 2; ++i) + { + float y1 = i == 0 ? 0 : yMax; + float y2 = i == 0 ? yMin : rect.height; + if (Mathf.Abs(y1 - y2) < Mathf.Epsilon) + continue; + + s_UVTiled[0] = GetRotatedUV(inner, 0, i == 0 ? outer : inner, i == 0 ? 1 : 3); + s_UVTiled[1] = GetRotatedUV(inner, 2, i == 0 ? inner : outer, i == 0 ? 1 : 3); + RotatePairUV(s_UVTiled); + for (float x1 = xMin; x1 < xMax; x1 += tileWidth) + { + float x2 = x1 + tileWidth; + if (x2 > xMax) + { + int k1 = ((int)rotate + 3) % 4 / 2, k2 = (int)rotate % 2; + s_UVTiled[k1][k2] = s_UVTiled[1 - k1][k2] + (s_UVTiled[k1][k2] - s_UVTiled[1 - k1][k2]) * (xMax - x1) / (x2 - x1); + x2 = xMax; + } + AddQuad(vbo, v, + new Vector2(x1, y1) + rect.position, + new Vector2(x2, y2) + rect.position, + s_UVTiled[0], s_UVTiled[1]); + } + } + + // Left and right tiled border + for (int i = 0; i < 2; ++i) + { + float x1 = i == 0 ? 0 : xMax; + float x2 = i == 0 ? xMin : rect.width; + if (Mathf.Abs(x1 - x2) < Mathf.Epsilon) + continue; + + s_UVTiled[0] = GetRotatedUV(i == 0 ? outer : inner, i == 0 ? 0 : 2, inner, 1); + s_UVTiled[1] = GetRotatedUV(i == 0 ? inner : outer, i == 0 ? 0 : 2, inner, 3); + RotatePairUV(s_UVTiled); + for (float y1 = yMin; y1 < yMax; y1 += tileHeight) + { + float y2 = y1 + tileHeight; + if (y2 > yMax) + { + int k1 = 1 - (int)rotate / 2, k2 = 1 - (int)rotate % 2; + s_UVTiled[k1][k2] = s_UVTiled[1 - k1][k2] + (s_UVTiled[k1][k2] - s_UVTiled[1 - k1][k2]) * (yMax - y1) / (y2 - y1); + y2 = yMax; + } + AddQuad(vbo, v, + new Vector2(x1, y1) + rect.position, + new Vector2(x2, y2) + rect.position, + s_UVTiled[0], s_UVTiled[1]); + } + } + + // Corners + if (Mathf.Abs(border[rx]) > Mathf.Epsilon && + Mathf.Abs(border[ry]) > Mathf.Epsilon) + { + s_UVTiled[0] = GetRotatedUV(outer, 0, outer, 1); + s_UVTiled[1] = GetRotatedUV(inner, 0, inner, 1); + RotatePairUV(s_UVTiled); + AddQuad(vbo, v, + new Vector2(0, 0) + rect.position, + new Vector2(xMin, yMin) + rect.position, + s_UVTiled[0], s_UVTiled[1]); + } + if (Mathf.Abs(border[rz]) > Mathf.Epsilon && + Mathf.Abs(border[ry]) > Mathf.Epsilon) + { + s_UVTiled[0] = GetRotatedUV(inner, 2, outer, 1); + s_UVTiled[1] = GetRotatedUV(outer, 2, inner, 1); + RotatePairUV(s_UVTiled); + AddQuad(vbo, v, + new Vector2(xMax, 0) + rect.position, + new Vector2(rect.width, yMin) + rect.position, + s_UVTiled[0], s_UVTiled[1]); + } + if (Mathf.Abs(border[rx]) > Mathf.Epsilon && + Mathf.Abs(border[rw]) > Mathf.Epsilon) + { + s_UVTiled[0] = GetRotatedUV(outer, 0, inner, 3); + s_UVTiled[1] = GetRotatedUV(inner, 0, outer, 3); + RotatePairUV(s_UVTiled); + AddQuad(vbo, v, + new Vector2(0, yMax) + rect.position, + new Vector2(xMin, rect.height) + rect.position, + s_UVTiled[0], s_UVTiled[1]); + } + if (Mathf.Abs(border[rz]) > Mathf.Epsilon && + Mathf.Abs(border[rw]) > Mathf.Epsilon) + { + s_UVTiled[0] = GetRotatedUV(inner, 2, inner, 3); + s_UVTiled[1] = GetRotatedUV(outer, 2, outer, 3); + RotatePairUV(s_UVTiled); + AddQuad(vbo, v, + new Vector2(xMax, yMax) + rect.position, + new Vector2(rect.width, rect.height) + rect.position, + s_UVTiled[0], s_UVTiled[1]); + } + } + + Vector2 GetRotatedUV(Vector4 sX, int iX, Vector4 sY, int iY) + { + for (int i = 0; i < (int)rotate; i++) + { + Vector4 tS = sX; + sX = sY; sY = tS; + int tI = (iX + 3) % 4; + iX = iY - 1; iY = tI; + } + return new Vector2(sX[iX], sY[iY]); + } + + void RotatePairUV(Vector2[] uv) + { + if ((int)rotate / 2 == 1) + { + float t = uv[0].x; + uv[0].x = uv[1].x; + uv[1].x = t; + } + if (((int)rotate + 1) / 2 == 1) + { + float t = uv[0].y; + uv[0].y = uv[1].y; + uv[1].y = t; + } + } + + static readonly Vector3[] s_VertQuad = new Vector3[4]; + static readonly Vector2[] s_UVQuad = new Vector2[4]; + void AddQuad(List vbo, UIVertex v, Vector2 posMin, Vector2 posMax, Vector2 uvMin, Vector2 uvMax) + { + s_VertQuad[0] = new Vector3(posMin.x, posMin.y, 0); + s_VertQuad[1] = new Vector3(posMin.x, posMax.y, 0); + s_VertQuad[2] = new Vector3(posMax.x, posMax.y, 0); + s_VertQuad[3] = new Vector3(posMax.x, posMin.y, 0); + s_UVQuad[0] = new Vector2(uvMin.x, uvMin.y); + s_UVQuad[1] = new Vector2(uvMin.x, uvMax.y); + s_UVQuad[2] = new Vector2(uvMax.x, uvMax.y); + s_UVQuad[3] = new Vector2(uvMax.x, uvMin.y); + + int offset = (int)rotate; + for (int i = 0; i < 4; i++) + { + v.position = s_VertQuad[i]; + v.uv0 = s_UVQuad[(i + offset) % 4]; + vbo.Add(v); + } + } + + 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]; + float rectSize = rect.size[(axis + (int)rotate % 2) % 2]; + if (rectSize < combinedBorders && combinedBorders != 0) + { + float borderScaleRatio = rectSize / combinedBorders; + border[axis] *= borderScaleRatio; + border[axis + 2] *= borderScaleRatio; + } + } + return border; + } + + /// + /// Generate vertices for a filled Image. + /// + + static readonly Vector2[] s_Xy = new Vector2[4]; + static readonly Vector2[] s_Uv = new Vector2[4]; + void GenerateFilledSprite(List vbo, bool preserveAspect) + { + if (m_FillAmount < 0.001f) + return; + + Vector4 v = GetDrawingDimensions(preserveAspect); + Vector4 outer = overrideSprite != null ? Sprites.DataUtility.GetOuterUV(overrideSprite) : Vector4.zero; + UIVertex uiv = UIVertex.simpleVert; + uiv.color = color; + + int offset = 4 - (int)rotate; + int rx = (0 + offset) % 4, ry = (1 + offset) % 4, rz = (2 + offset) % 4, rw = (3 + offset) % 4; + + // 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 = (outer[rz] - outer[rx]) * m_FillAmount; + + if (m_FillOrigin == 1) + { + v.x = v.z - (v.z - v.x) * m_FillAmount; + outer[rx] = outer[rz] - fill; + } + else + { + v.z = v.x + (v.z - v.x) * m_FillAmount; + outer[rz] = outer[rx] + fill; + } + } + else if (fillMethod == FillMethod.Vertical) + { + float fill = (outer[rw] - outer[ry]) * m_FillAmount; + + if (m_FillOrigin == 1) + { + v.y = v.w - (v.w - v.y) * m_FillAmount; + outer[ry] = outer[rw] - fill; + } + else + { + v.w = v.y + (v.w - v.y) * m_FillAmount; + outer[rw] = outer[ry] + 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 + offset) % 4] = new Vector2(outer.x, outer.y); + s_Uv[(1 + offset) % 4] = new Vector2(outer.x, outer.w); + s_Uv[(2 + offset) % 4] = new Vector2(outer.z, outer.w); + s_Uv[(3 + offset) % 4] = new Vector2(outer.z, outer.y); + + if (m_FillAmount < 1f) + { + float tx0 = outer.x; + float ty0 = outer.y; + float tx1 = outer.z; + float ty1 = outer.w; + if (fillMethod == FillMethod.Radial90) + { + if (RadialCut(s_Xy, s_Uv, m_FillAmount, m_FillClockwise, m_FillOrigin)) + { + for (int i = 0; i < 4; ++i) + { + uiv.position = s_Xy[i]; + uiv.uv0 = s_Uv[i]; + vbo.Add(uiv); + } + } + return; + } + + 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))) + { + for (int i = 0; i < 4; ++i) + { + uiv.position = s_Xy[i]; + uiv.uv0 = s_Uv[i]; + vbo.Add(uiv); + } + } + } + return; + } + + 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))) + { + for (int i = 0; i < 4; ++i) + { + uiv.position = s_Xy[i]; + uiv.uv0 = s_Uv[i]; + vbo.Add(uiv); + } + } + } + return; + } + } + + // Fill the buffer with the quad for the Image + for (int i = 0; i < 4; ++i) + { + uiv.position = s_Xy[i]; + uiv.uv0 = s_Uv[i]; + vbo.Add(uiv); + } + } + + /// + /// Adjust the specified quad, making it be radially filled instead. + /// + + static bool RadialCut(Vector2[] xy, Vector2[] 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; + } + + /// + /// Adjust the specified quad, making it be radially filled instead. + /// + + static void RadialCut(Vector2[] 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); + } + } + + #endregion + + 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; + if (type == Type.Sliced || type == Type.Tiled) + return Sprites.DataUtility.GetMinSize(overrideSprite).x / pixelsPerUnit; + 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; + if (type == Type.Sliced || type == Type.Tiled) + return Sprites.DataUtility.GetMinSize(overrideSprite).y / pixelsPerUnit; + return overrideSprite.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 (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; + } + } + + 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; + } + } +} \ No newline at end of file diff --git a/Scripts/ImageExtended.cs.meta b/Scripts/ImageExtended.cs.meta new file mode 100644 index 0000000..8c5d9bf --- /dev/null +++ b/Scripts/ImageExtended.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 26d9c9fa4e5a13747a6ad9c3fedb57c8 +timeCreated: 1440851346 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/InputFocus.cs b/Scripts/InputFocus.cs new file mode 100644 index 0000000..e900806 --- /dev/null +++ b/Scripts/InputFocus.cs @@ -0,0 +1,83 @@ +/// Credit Zelek +/// Sourced from - http://forum.unity3d.com/threads/inputfield-focus-and-unfocus.306634/ +/// Usage, assign component to Input field, set OnEndEdit function to the one in this script and the Click for the submit button to the buttonPressed function. + +namespace UnityEngine.UI.Extensions +{ + [RequireComponent(typeof(InputField))] + [AddComponentMenu("UI/Extensions/InputFocus")] + public class InputFocus : MonoBehaviour + { + #region Private Variables + + // The input field we use for chat + protected InputField _inputField; + + // When set to true, we will ignore the next time the "Enter" key is released + public bool _ignoreNextActivation = false; + + #endregion + + void Start() + { + _inputField = GetComponent(); + } + + void Update() + { + // Check if the "Enter" key was just released with the chat input not focused + if (Input.GetKeyUp(KeyCode.Return) && !_inputField.isFocused) + { + // If we need to ignore the keypress, do nothing - otherwise activate the input field + if (_ignoreNextActivation) + { + _ignoreNextActivation = false; + } + else + { + _inputField.Select(); + _inputField.ActivateInputField(); + } + } + } + + public void buttonPressed() + { + // Do whatever you want with the input field text here + + // Make note of whether the input string was empty, and then clear it out + bool wasEmpty = _inputField.text == ""; + _inputField.text = ""; + + // If the string was not empty, we should reactivate the input field + if (!wasEmpty) + { + _inputField.Select(); + _inputField.ActivateInputField(); + } + } + + public void OnEndEdit(string textString) + { + // If the edit ended because we clicked away, don't do anything extra + if (!Input.GetKeyDown(KeyCode.Return)) + { + return; + } + + // Do whatever you want with the input field text here + + // Make note of whether the input string was empty, and then clear it out + bool wasEmpty = _inputField.text == ""; + _inputField.text = ""; + + // if the input string was empty, then allow the field to deactivate + if (wasEmpty) + { + _ignoreNextActivation = true; + } + } + + + } +} \ No newline at end of file diff --git a/Scripts/InputFocus.cs.meta b/Scripts/InputFocus.cs.meta new file mode 100644 index 0000000..1ee5f36 --- /dev/null +++ b/Scripts/InputFocus.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: a18c7c81729dadf40aee407a0cff0462 +timeCreated: 1440843410 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/RescalingPanels.meta b/Scripts/RescalingPanels.meta new file mode 100644 index 0000000..2f656dd --- /dev/null +++ b/Scripts/RescalingPanels.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: c4c2c5317e2b50f42b0302414577a62d +folderAsset: yes +timeCreated: 1440843775 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/RescalingPanels/RescaleDragPanel.cs b/Scripts/RescalingPanels/RescaleDragPanel.cs new file mode 100644 index 0000000..d8bbcaf --- /dev/null +++ b/Scripts/RescalingPanels/RescaleDragPanel.cs @@ -0,0 +1,64 @@ +/// Credit .entity +/// Sourced from - http://forum.unity3d.com/threads/rescale-panel.309226/ + +using UnityEngine.EventSystems; + +namespace UnityEngine.UI.Extensions +{ + [AddComponentMenu("UI/Extensions/RescalePanels/RescaleDragPanel")] + public class RescaleDragPanel : MonoBehaviour, IPointerDownHandler, IDragHandler + { + private Vector2 pointerOffset; + private RectTransform canvasRectTransform; + private RectTransform panelRectTransform; + + private Transform goTransform; + + void Awake() + { + Canvas canvas = GetComponentInParent(); + if (canvas != null) + { + canvasRectTransform = canvas.transform as RectTransform; + panelRectTransform = transform.parent as RectTransform; + goTransform = transform.parent; + } + } + + public void OnPointerDown(PointerEventData data) + { + panelRectTransform.SetAsLastSibling(); + RectTransformUtility.ScreenPointToLocalPointInRectangle(panelRectTransform, data.position, data.pressEventCamera, out pointerOffset); + } + + public void OnDrag(PointerEventData data) + { + if (panelRectTransform == null) + return; + + Vector2 pointerPosition = ClampToWindow(data); + + Vector2 localPointerPosition; + if (RectTransformUtility.ScreenPointToLocalPointInRectangle( + canvasRectTransform, pointerPosition, data.pressEventCamera, out localPointerPosition + )) + { + panelRectTransform.localPosition = localPointerPosition - new Vector2(pointerOffset.x * goTransform.localScale.x, pointerOffset.y * goTransform.localScale.y); + } + } + + Vector2 ClampToWindow(PointerEventData data) + { + Vector2 rawPointerPosition = data.position; + + Vector3[] canvasCorners = new Vector3[4]; + canvasRectTransform.GetWorldCorners(canvasCorners); + + float clampedX = Mathf.Clamp(rawPointerPosition.x, canvasCorners[0].x, canvasCorners[2].x); + float clampedY = Mathf.Clamp(rawPointerPosition.y, canvasCorners[0].y, canvasCorners[2].y); + + Vector2 newPointerPosition = new Vector2(clampedX, clampedY); + return newPointerPosition; + } + } +} \ No newline at end of file diff --git a/Scripts/RescalingPanels/RescaleDragPanel.cs.meta b/Scripts/RescalingPanels/RescaleDragPanel.cs.meta new file mode 100644 index 0000000..35698ae --- /dev/null +++ b/Scripts/RescalingPanels/RescaleDragPanel.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: c210a6e68020b4349a4020e7da57826e +timeCreated: 1440843816 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/RescalingPanels/RescalePanel.cs b/Scripts/RescalingPanels/RescalePanel.cs new file mode 100644 index 0000000..917356c --- /dev/null +++ b/Scripts/RescalingPanels/RescalePanel.cs @@ -0,0 +1,62 @@ +/// Credit .entity +/// Sourced from - http://forum.unity3d.com/threads/rescale-panel.309226/ + +using UnityEngine.EventSystems; + +namespace UnityEngine.UI.Extensions +{ + [AddComponentMenu("UI/Extensions/RescalePanels/RescalePanel")] + public class RescalePanel : MonoBehaviour, IPointerDownHandler, IDragHandler + { + public Vector2 minSize; + public Vector2 maxSize; + + private RectTransform rectTransform; + private Transform goTransform; + private Vector2 currentPointerPosition; + private Vector2 previousPointerPosition; + + private RectTransform thisRectTransform; + Vector2 sizeDelta; + + void Awake() + { + rectTransform = transform.parent.GetComponent(); + goTransform = transform.parent; + + thisRectTransform = GetComponent(); + sizeDelta = thisRectTransform.sizeDelta; + } + + public void OnPointerDown(PointerEventData data) + { + rectTransform.SetAsLastSibling(); + RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, data.position, data.pressEventCamera, out previousPointerPosition); + } + + public void OnDrag(PointerEventData data) + { + if (rectTransform == null) + return; + + Vector3 scaleDelta = goTransform.localScale; + + RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, data.position, data.pressEventCamera, out currentPointerPosition); + Vector2 resizeValue = currentPointerPosition - previousPointerPosition; + + scaleDelta += new Vector3(-resizeValue.y * 0.001f, -resizeValue.y * 0.001f, 0f); + scaleDelta = new Vector3( + Mathf.Clamp(scaleDelta.x, minSize.x, maxSize.x), + Mathf.Clamp(scaleDelta.y, minSize.y, maxSize.y), + 1 + ); + + goTransform.localScale = scaleDelta; + + previousPointerPosition = currentPointerPosition; + float resizeDeltaValue = sizeDelta.x / goTransform.localScale.x; + Vector2 newSizeDelta = new Vector2(resizeDeltaValue, resizeDeltaValue); + thisRectTransform.sizeDelta = newSizeDelta; + } + } +} \ No newline at end of file diff --git a/Scripts/RescalingPanels/RescalePanel.cs.meta b/Scripts/RescalingPanels/RescalePanel.cs.meta new file mode 100644 index 0000000..3fe052f --- /dev/null +++ b/Scripts/RescalingPanels/RescalePanel.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: ff46b67332ade77459ea86ba20638d24 +timeCreated: 1440843795 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/RescalingPanels/ResizePanel.cs b/Scripts/RescalingPanels/ResizePanel.cs new file mode 100644 index 0000000..1b7c523 --- /dev/null +++ b/Scripts/RescalingPanels/ResizePanel.cs @@ -0,0 +1,60 @@ +/// Credit .entity +/// Sourced from - http://forum.unity3d.com/threads/rescale-panel.309226/ + +using UnityEngine.EventSystems; + +namespace UnityEngine.UI.Extensions +{ + [AddComponentMenu("UI/Extensions/RescalePanels/ResizePanel")] + public class ResizePanel : MonoBehaviour, IPointerDownHandler, IDragHandler + { + public Vector2 minSize; + public Vector2 maxSize; + + private RectTransform rectTransform; + private Vector2 currentPointerPosition; + private Vector2 previousPointerPosition; + + private float ratio; + + + void Awake() + { + rectTransform = transform.parent.GetComponent(); + float originalWidth; + float originalHeight; + originalWidth = rectTransform.rect.width; + originalHeight = rectTransform.rect.height; + ratio = originalHeight / originalWidth; + minSize = new Vector2(0.1f * originalWidth, 0.1f * originalHeight); + maxSize = new Vector2(10f * originalWidth, 10f * originalHeight); + } + + public void OnPointerDown(PointerEventData data) + { + rectTransform.SetAsLastSibling(); + RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, data.position, data.pressEventCamera, out previousPointerPosition); + } + + public void OnDrag(PointerEventData data) + { + if (rectTransform == null) + return; + + Vector2 sizeDelta = rectTransform.sizeDelta; + + RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, data.position, data.pressEventCamera, out currentPointerPosition); + Vector2 resizeValue = currentPointerPosition - previousPointerPosition; + + sizeDelta += new Vector2(resizeValue.x, ratio * resizeValue.x); + sizeDelta = new Vector2( + Mathf.Clamp(sizeDelta.x, minSize.x, maxSize.x), + Mathf.Clamp(sizeDelta.y, minSize.y, maxSize.y) + ); + + rectTransform.sizeDelta = sizeDelta; + + previousPointerPosition = currentPointerPosition; + } + } +} \ No newline at end of file diff --git a/Scripts/RescalingPanels/ResizePanel.cs.meta b/Scripts/RescalingPanels/ResizePanel.cs.meta new file mode 100644 index 0000000..bd57912 --- /dev/null +++ b/Scripts/RescalingPanels/ResizePanel.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: db83442065d59344c9bf6ffa63a23777 +timeCreated: 1440843837 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/ScrollRectEx.cs b/Scripts/ScrollRectEx.cs new file mode 100644 index 0000000..0cea497 --- /dev/null +++ b/Scripts/ScrollRectEx.cs @@ -0,0 +1,109 @@ +/// Credit CaptainSchnittchen +/// Credit TouchPad (OnScroll function) update - GamesRUs +/// sourced from: http://forum.unity3d.com/threads/scripts-useful-4-6-scripts-collection.264161/page-2#post-2011648 + +/*USAGE: +Simply place the script on the ScrollRect that contains the selectable children we'll be scroling to +and drag'n'drop the RectTransform of the options "container" that we'll be scrolling.*/ + +using System; +using UnityEngine.EventSystems; + +namespace UnityEngine.UI.Extensions +{ + [AddComponentMenu("UI/Extensions/ScrollRectEx")] + public class ScrollRectEx : ScrollRect + { + private bool routeToParent = false; + + /// + /// Do action for all parents + /// + private void DoForParents(Action action) where T : IEventSystemHandler + { + Transform parent = transform.parent; + while (parent != null) + { + foreach (var component in parent.GetComponents()) + { + if (component is T) + action((T)(IEventSystemHandler)component); + } + parent = parent.parent; + } + } + + /// + /// Always route initialize potential drag event to parents + /// + public override void OnInitializePotentialDrag(PointerEventData eventData) + { + DoForParents((parent) => { parent.OnInitializePotentialDrag(eventData); }); + base.OnInitializePotentialDrag(eventData); + } + + /// + /// Drag event + /// + public override void OnDrag(UnityEngine.EventSystems.PointerEventData eventData) + { + if (routeToParent) + DoForParents((parent) => { parent.OnDrag(eventData); }); + else + base.OnDrag(eventData); + } + + /// + /// Begin drag event + /// + public override void OnBeginDrag(UnityEngine.EventSystems.PointerEventData eventData) + { + if (!horizontal && Math.Abs(eventData.delta.x) > Math.Abs(eventData.delta.y)) + routeToParent = true; + else if (!vertical && Math.Abs(eventData.delta.x) < Math.Abs(eventData.delta.y)) + routeToParent = true; + else + routeToParent = false; + + if (routeToParent) + DoForParents((parent) => { parent.OnBeginDrag(eventData); }); + else + base.OnBeginDrag(eventData); + } + + /// + /// End drag event + /// + public override void OnEndDrag(UnityEngine.EventSystems.PointerEventData eventData) + { + if (routeToParent) + DoForParents((parent) => { parent.OnEndDrag(eventData); }); + else + base.OnEndDrag(eventData); + routeToParent = false; + } + + public override void OnScroll(PointerEventData eventData) + { + if (!horizontal && Math.Abs(eventData.scrollDelta.x) > Math.Abs(eventData.scrollDelta.y)) + { + routeToParent = true; + } + else if (!vertical && Math.Abs(eventData.scrollDelta.x) < Math.Abs(eventData.scrollDelta.y)) + { + routeToParent = true; + } + else + { + routeToParent = false; + } + + if (routeToParent) + DoForParents((parent) => { + parent.OnScroll(eventData); + }); + else + base.OnScroll(eventData); + } + } +} \ No newline at end of file diff --git a/Scripts/ScrollRectEx.cs.meta b/Scripts/ScrollRectEx.cs.meta new file mode 100644 index 0000000..ecaa1ba --- /dev/null +++ b/Scripts/ScrollRectEx.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 5a7b69ea2282ad240824a4bce7a65a46 +timeCreated: 1440844492 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/ScrollRectExtensions.cs b/Scripts/ScrollRectExtensions.cs new file mode 100644 index 0000000..add28d0 --- /dev/null +++ b/Scripts/ScrollRectExtensions.cs @@ -0,0 +1,17 @@ +/// Credit Feaver1968 +/// Sourced from - http://forum.unity3d.com/threads/scroll-to-the-bottom-of-a-scrollrect-in-code.310919/ + +namespace UnityEngine.UI.Extensions +{ + public static class ScrollRectExtensions + { + public static void ScrollToTop(this ScrollRect scrollRect) + { + scrollRect.normalizedPosition = new Vector2(0, 1); + } + public static void ScrollToBottom(this ScrollRect scrollRect) + { + scrollRect.normalizedPosition = new Vector2(0, 0); + } + } +} \ No newline at end of file diff --git a/Scripts/ScrollRectExtensions.cs.meta b/Scripts/ScrollRectExtensions.cs.meta new file mode 100644 index 0000000..8fe47b2 --- /dev/null +++ b/Scripts/ScrollRectExtensions.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 9abaa5d90896b4d4a937574b6b3878ab +timeCreated: 1440845965 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/ScrollRectLinker.cs b/Scripts/ScrollRectLinker.cs new file mode 100644 index 0000000..25031a5 --- /dev/null +++ b/Scripts/ScrollRectLinker.cs @@ -0,0 +1,34 @@ +/// Credit Martin Sharkbomb +/// Sourced from - http://www.sharkbombs.com/2015/08/26/unity-ui-scrollrect-tools/ + +namespace UnityEngine.UI.Extensions +{ + [RequireComponent(typeof(ScrollRect))] + [AddComponentMenu("UI/Extensions/ScrollRectLinker")] + public class ScrollRectLinker : MonoBehaviour + { + + public bool clamp = true; + + [SerializeField] + ScrollRect controllingScrollRect; + ScrollRect scrollRect; + + void Awake() + { + scrollRect = GetComponent(); + if (controllingScrollRect != null) + controllingScrollRect.onValueChanged.AddListener(MirrorPos); + } + + void MirrorPos(Vector2 scrollPos) + { + + if (clamp) + scrollRect.normalizedPosition = new Vector2(Mathf.Clamp01(scrollPos.x), Mathf.Clamp01(scrollPos.y)); + else + scrollRect.normalizedPosition = scrollPos; + } + + } +} \ No newline at end of file diff --git a/Scripts/ScrollRectLinker.cs.meta b/Scripts/ScrollRectLinker.cs.meta new file mode 100644 index 0000000..c0a1aa0 --- /dev/null +++ b/Scripts/ScrollRectLinker.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 4f1f9a7e297738d47b8c6286a737406f +timeCreated: 1440840782 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/ScrollRectTweener.cs b/Scripts/ScrollRectTweener.cs new file mode 100644 index 0000000..5f16deb --- /dev/null +++ b/Scripts/ScrollRectTweener.cs @@ -0,0 +1,141 @@ +/// Credit Martin Sharkbomb +/// Sourced from - http://www.sharkbombs.com/2015/08/26/unity-ui-scrollrect-tools/ + +using System.Collections; +using UnityEngine.EventSystems; + +namespace UnityEngine.UI.Extensions +{ + [RequireComponent(typeof(ScrollRect))] + [AddComponentMenu("UI/Extensions/ScrollRectTweener")] + public class ScrollRectTweener : MonoBehaviour, IDragHandler + { + + ScrollRect scrollRect; + Vector2 startPos; + Vector2 targetPos; + + bool wasHorizontal; + bool wasVertical; + + public float moveSpeed = 5000f; + public bool disableDragWhileTweening = false; + + void Awake() + { + scrollRect = GetComponent(); + wasHorizontal = scrollRect.horizontal; + wasVertical = scrollRect.vertical; + } + + public void ScrollHorizontal(float normalizedX) + { + Scroll(new Vector2(normalizedX, scrollRect.verticalNormalizedPosition)); + } + + public void ScrollHorizontal(float normalizedX, float duration) + { + Scroll(new Vector2(normalizedX, scrollRect.verticalNormalizedPosition), duration); + } + + public void ScrollVertical(float normalizedY) + { + Scroll(new Vector2(scrollRect.horizontalNormalizedPosition, normalizedY)); + } + + public void ScrollVertical(float normalizedY, float duration) + { + Scroll(new Vector2(scrollRect.horizontalNormalizedPosition, normalizedY), duration); + } + + public void Scroll(Vector2 normalizedPos) + { + Scroll(normalizedPos, GetScrollDuration(normalizedPos)); + } + + float GetScrollDuration(Vector2 normalizedPos) + { + Vector2 currentPos = GetCurrentPos(); + return Vector2.Distance(DeNormalize(currentPos), DeNormalize(normalizedPos)) / moveSpeed; + } + + Vector2 DeNormalize(Vector2 normalizedPos) + { + return new Vector2(normalizedPos.x * scrollRect.content.rect.width, normalizedPos.y * scrollRect.content.rect.height); + } + + Vector2 GetCurrentPos() + { + return new Vector2(scrollRect.horizontalNormalizedPosition, scrollRect.verticalNormalizedPosition); + } + + public void Scroll(Vector2 normalizedPos, float duration) + { + startPos = GetCurrentPos(); + targetPos = normalizedPos; + + if (disableDragWhileTweening) + LockScrollability(); + + StopAllCoroutines(); + StartCoroutine(DoMove(duration)); + } + + IEnumerator DoMove(float duration) + { + + // Abort if movement would be too short + if (duration < 0.05f) + yield break; + + Vector2 posOffset = targetPos - startPos; + + float currentTime = 0f; + while (currentTime < duration) + { + currentTime += Time.deltaTime; + scrollRect.normalizedPosition = EaseVector(currentTime, startPos, posOffset, duration); + yield return null; + } + + scrollRect.normalizedPosition = targetPos; + + if (disableDragWhileTweening) + RestoreScrollability(); + } + + public Vector2 EaseVector(float currentTime, Vector2 startValue, Vector2 changeInValue, float duration) + { + return new Vector2( + changeInValue.x * Mathf.Sin(currentTime / duration * (Mathf.PI / 2)) + startValue.x, + changeInValue.y * Mathf.Sin(currentTime / duration * (Mathf.PI / 2)) + startValue.y + ); + } + + public void OnDrag(PointerEventData eventData) + { + if (!disableDragWhileTweening) + StopScroll(); + } + + void StopScroll() + { + StopAllCoroutines(); + if (disableDragWhileTweening) + RestoreScrollability(); + } + + void LockScrollability() + { + scrollRect.horizontal = false; + scrollRect.vertical = false; + } + + void RestoreScrollability() + { + scrollRect.horizontal = wasHorizontal; + scrollRect.vertical = wasVertical; + } + + } +} \ No newline at end of file diff --git a/Scripts/ScrollRectTweener.cs.meta b/Scripts/ScrollRectTweener.cs.meta new file mode 100644 index 0000000..8c344e5 --- /dev/null +++ b/Scripts/ScrollRectTweener.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 37838caa3fcff7f46a5e1418b35173c2 +timeCreated: 1440840781 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/SelectionBox/ExampleSelectable.cs b/Scripts/SelectionBox/ExampleSelectable.cs index 580d3b2..da40fe5 100644 --- a/Scripts/SelectionBox/ExampleSelectable.cs +++ b/Scripts/SelectionBox/ExampleSelectable.cs @@ -1,5 +1,5 @@ -/// Original Credit Korindian -/// Sourced from - http://forum.unity3d.com/threads/rts-style-drag-selection-box.265739/ +/// Original Credit Korindian +/// Sourced from - http://forum.unity3d.com/threads/rts-style-drag-selection-box.265739/ /// Updated Credit BenZed /// Sourced from - http://forum.unity3d.com/threads/color-picker.267043/ diff --git a/Scripts/SelectionBox/IBoxSelectable.cs b/Scripts/SelectionBox/IBoxSelectable.cs index d104335..4a0b490 100644 --- a/Scripts/SelectionBox/IBoxSelectable.cs +++ b/Scripts/SelectionBox/IBoxSelectable.cs @@ -1,31 +1,31 @@ -///Original Credit Korindian -///Sourced from - http://forum.unity3d.com/threads/rts-style-drag-selection-box.265739/ +///Original Credit Korindian +///Sourced from - http://forum.unity3d.com/threads/rts-style-drag-selection-box.265739/ ///Updated Credit BenZed ///Sourced from - http://forum.unity3d.com/threads/color-picker.267043/ -namespace UnityEngine.UI.Extensions -{ - - /* - * Implement this interface on any MonoBehaviour that you'd like to be considered selectable. - */ - public interface IBoxSelectable { - bool selected { - get; - set; - } - - bool preSelected { - get; - set; - } - - //This property doesn't actually need to be implemented, as this interface should already be placed on a MonoBehaviour, which will - //already have it. Defining it here only allows us access to the transform property by casting through the selectable interface. - Transform transform { - get; - } - } - +namespace UnityEngine.UI.Extensions +{ + + /* + * Implement this interface on any MonoBehaviour that you'd like to be considered selectable. + */ + public interface IBoxSelectable { + bool selected { + get; + set; + } + + bool preSelected { + get; + set; + } + + //This property doesn't actually need to be implemented, as this interface should already be placed on a MonoBehaviour, which will + //already have it. Defining it here only allows us access to the transform property by casting through the selectable interface. + Transform transform { + get; + } + } + } \ No newline at end of file diff --git a/Scripts/SetPropertyUtility.cs b/Scripts/SetPropertyUtility.cs new file mode 100644 index 0000000..cb1da34 --- /dev/null +++ b/Scripts/SetPropertyUtility.cs @@ -0,0 +1,36 @@ +/// +/// Tool script taken from the UI source as it's set to Internal for some reason. So to use in the extensions project it is needed here also. +/// +/// +namespace UnityEngine.UI.Extensions +{ + internal static class SetPropertyUtility + { + public static bool SetColor(ref Color currentValue, Color newValue) + { + if (currentValue.r == newValue.r && currentValue.g == newValue.g && currentValue.b == newValue.b && currentValue.a == newValue.a) + return false; + + currentValue = newValue; + return true; + } + + public static bool SetStruct(ref T currentValue, T newValue) where T: struct + { + if (currentValue.Equals(newValue)) + return false; + + currentValue = newValue; + return true; + } + + public static bool SetClass(ref T currentValue, T newValue) where T: class + { + if ((currentValue == null && newValue == null) || (currentValue != null && currentValue.Equals(newValue))) + return false; + + currentValue = newValue; + return true; + } + } +} diff --git a/Scripts/SetPropertyUtility.cs.meta b/Scripts/SetPropertyUtility.cs.meta new file mode 100644 index 0000000..25637f3 --- /dev/null +++ b/Scripts/SetPropertyUtility.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: d373cce4b1f361a40a126bd74d26ebc9 +timeCreated: 1440851864 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/TabNavigation.cs b/Scripts/TabNavigation.cs index 44b6664..72e3a41 100644 --- a/Scripts/TabNavigation.cs +++ b/Scripts/TabNavigation.cs @@ -4,16 +4,22 @@ /// - bug fix to prevent crash if no control selected /// - updated to support new semantics for EventSystem in later 4.6 builds /// - autoselect "firstSelectedGameObject" since it doesn't seem to work automatically +/// Updated 08-29-15 - On request of Issue #13 on repo, added a manual navigation order. using UnityEngine.EventSystems; namespace UnityEngine.UI.Extensions { + public enum NavigationMode { Auto = 0, Manual = 1}; [RequireComponent(typeof(EventSystem))] [AddComponentMenu("Event/Extensions/Tab Navigation Helper")] public class TabNavigationHelper : MonoBehaviour { private EventSystem _system; + [Tooltip("The path to take when user is tabbing through ui components.")] + public Selectable[] NavigationPath; + [Tooltip("Use the default Unity navigation system or a manual fixed order using Navigation Path")] + public NavigationMode NavigationMode; void Start() { @@ -50,6 +56,18 @@ namespace UnityEngine.UI.Extensions next = _system.firstSelectedGameObject.GetComponent(); } } + else if(NavigationMode == NavigationMode.Manual) + { + for (var i = 0; i < NavigationPath.Length; i++) + { + if (_system.currentSelectedGameObject != NavigationPath[i].gameObject) continue; + + + next = i == (NavigationPath.Length - 1) ? NavigationPath[0] : NavigationPath[i + 1]; + + break; + } + } else if (_system.currentSelectedGameObject == null) { next = _system.firstSelectedGameObject.GetComponent(); diff --git a/Scripts/ToolTip.cs b/Scripts/ToolTip.cs index b1e2a7e..8288f88 100644 --- a/Scripts/ToolTip.cs +++ b/Scripts/ToolTip.cs @@ -32,11 +32,11 @@ namespace UnityEngine.UI.Extensions //if the tooltip is inside a UI element private bool _inside; - private bool _xShifted, _yShifted = false; + // private bool _xShifted, _yShifted = false; private float width, height, canvasWidth, canvasHeight; - private int screenWidth, screenHeight; + // private int screenWidth, screenHeight; private float YShift,xShift; @@ -57,17 +57,15 @@ namespace UnityEngine.UI.Extensions _inside = false; //size of the screen - screenWidth = Screen.width; - screenHeight = Screen.height; + // screenWidth = Screen.width; + // screenHeight = Screen.height; xShift = 0f; YShift = -30f; - _xShifted = _yShifted = false; - + // _xShifted = _yShifted = false; this.gameObject.SetActive(false); - } //Call this function externally to set the text of the template and activate the tooltip diff --git a/Scripts/UILineRenderer.cs b/Scripts/UILineRenderer.cs new file mode 100644 index 0000000..c2d0369 --- /dev/null +++ b/Scripts/UILineRenderer.cs @@ -0,0 +1,181 @@ +/// Credit jack.sydorenko +/// Sourced from - http://forum.unity3d.com/threads/new-ui-and-line-drawing.253772/ + +using System.Collections.Generic; + +namespace UnityEngine.UI.Extensions +{ + [AddComponentMenu("UI/Extensions/UILineRenderer")] + public class UILineRenderer : Graphic + { + [SerializeField] + Texture m_Texture; + [SerializeField] + Rect m_UVRect = new Rect(0f, 0f, 1f, 1f); + + public float LineThickness = 2; + public bool UseMargins; + public Vector2 Margin; + public Vector2[] Points; + 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. + /// + public Rect uvRect + { + get + { + return m_UVRect; + } + set + { + if (m_UVRect == value) + return; + m_UVRect = value; + SetVerticesDirty(); + } + } + + protected override void OnFillVBO(List vbo) + { + // requires sets of quads + if (Points == null || Points.Length < 2) + Points = new[] { new Vector2(0, 0), new Vector2(1, 1) }; + var capSize = 24; + var sizeX = rectTransform.rect.width; + var sizeY = rectTransform.rect.height; + var offsetX = -rectTransform.pivot.x * rectTransform.rect.width; + var offsetY = -rectTransform.pivot.y * rectTransform.rect.height; + + // don't want to scale based on the size of the rect, so this is switchable now + if (!relativeSize) + { + sizeX = 1; + sizeY = 1; + } + // build a new set of points taking into account the cap sizes. + // would be cool to support corners too, but that might be a bit tough :) + var pointList = new List(); + pointList.Add(Points[0]); + var capPoint = Points[0] + (Points[1] - Points[0]).normalized * capSize; + pointList.Add(capPoint); + + // should bail before the last point to add another cap point + for (int i = 1; i < Points.Length - 1; i++) + { + pointList.Add(Points[i]); + } + capPoint = Points[Points.Length - 1] - (Points[Points.Length - 1] - Points[Points.Length - 2]).normalized * capSize; + pointList.Add(capPoint); + pointList.Add(Points[Points.Length - 1]); + + var TempPoints = pointList.ToArray(); + if (UseMargins) + { + sizeX -= Margin.x; + sizeY -= Margin.y; + offsetX += Margin.x / 2f; + offsetY += Margin.y / 2f; + } + + vbo.Clear(); + + Vector2 prevV1 = Vector2.zero; + Vector2 prevV2 = Vector2.zero; + + for (int i = 1; i < TempPoints.Length; i++) + { + var prev = TempPoints[i - 1]; + var cur = TempPoints[i]; + prev = new Vector2(prev.x * sizeX + offsetX, prev.y * sizeY + offsetY); + cur = new Vector2(cur.x * sizeX + offsetX, cur.y * sizeY + offsetY); + + float angle = Mathf.Atan2(cur.y - prev.y, cur.x - prev.x) * 180f / Mathf.PI; + + var v1 = prev + new Vector2(0, -LineThickness / 2); + var v2 = prev + new Vector2(0, +LineThickness / 2); + var v3 = cur + new Vector2(0, +LineThickness / 2); + var v4 = cur + new Vector2(0, -LineThickness / 2); + + v1 = RotatePointAroundPivot(v1, prev, new Vector3(0, 0, angle)); + v2 = RotatePointAroundPivot(v2, prev, new Vector3(0, 0, angle)); + v3 = RotatePointAroundPivot(v3, cur, new Vector3(0, 0, angle)); + v4 = RotatePointAroundPivot(v4, cur, new Vector3(0, 0, angle)); + + Vector2 uvTopLeft = Vector2.zero; + Vector2 uvBottomLeft = new Vector2(0, 1); + + Vector2 uvTopCenter = new Vector2(0.5f, 0); + Vector2 uvBottomCenter = new Vector2(0.5f, 1); + + Vector2 uvTopRight = new Vector2(1, 0); + Vector2 uvBottomRight = new Vector2(1, 1); + + Vector2[] uvs = new[] { uvTopCenter, uvBottomCenter, uvBottomCenter, uvTopCenter }; + + if (i > 1) + SetVbo(vbo, new[] { prevV1, prevV2, v1, v2 }, uvs); + + if (i == 1) + uvs = new[] { uvTopLeft, uvBottomLeft, uvBottomCenter, uvTopCenter }; + else if (i == TempPoints.Length - 1) + uvs = new[] { uvTopCenter, uvBottomCenter, uvBottomRight, uvTopRight }; + + SetVbo(vbo, new[] { v1, v2, v3, v4 }, uvs); + + + prevV1 = v3; + prevV2 = v4; + } + } + + protected void SetVbo(List vbo, Vector2[] vertices, Vector2[] uvs) + { + for (int i = 0; i < vertices.Length; i++) + { + var vert = UIVertex.simpleVert; + vert.color = color; + vert.position = vertices[i]; + vert.uv0 = uvs[i]; + vbo.Add(vert); + } + } + + public Vector3 RotatePointAroundPivot(Vector3 point, Vector3 pivot, Vector3 angles) + { + Vector3 dir = point - pivot; // get point direction relative to pivot + dir = Quaternion.Euler(angles) * dir; // rotate it + point = dir + pivot; // calculate rotated point + return point; // return it + } + } +} \ No newline at end of file diff --git a/Scripts/UILineRenderer.cs.meta b/Scripts/UILineRenderer.cs.meta new file mode 100644 index 0000000..998fddb --- /dev/null +++ b/Scripts/UILineRenderer.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 5b33b2e663e78774c9f0c9af55018725 +timeCreated: 1440845580 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/UILineTextureRenderer.cs b/Scripts/UILineTextureRenderer.cs new file mode 100644 index 0000000..26685aa --- /dev/null +++ b/Scripts/UILineTextureRenderer.cs @@ -0,0 +1,182 @@ +/// Credit Martin Sharkbomb +/// Based on original LineRender script by jack.sydorenko +/// Sourced from - http://forum.unity3d.com/threads/new-ui-and-line-drawing.253772/ + +using System.Collections.Generic; + +namespace UnityEngine.UI.Extensions +{ + [AddComponentMenu("UI/Extensions/UILineTextureRenderer")] + public class UILineTextureRenderer : Graphic + { + [SerializeField] + Texture m_Texture; + [SerializeField] + Rect m_UVRect = new Rect(0f, 0f, 1f, 1f); + + public float LineThickness = 2; + public bool UseMargins; + public Vector2 Margin; + public Vector2[] Points; + 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. + /// + public Rect uvRect + { + get + { + return m_UVRect; + } + set + { + if (m_UVRect == value) + return; + m_UVRect = value; + SetVerticesDirty(); + } + } + + protected override void OnFillVBO(List vbo) + { + // requires sets of quads + if (Points == null || Points.Length < 2) + Points = new[] { new Vector2(0, 0), new Vector2(1, 1) }; + var capSize = 24; + var sizeX = rectTransform.rect.width; + var sizeY = rectTransform.rect.height; + var offsetX = -rectTransform.pivot.x * rectTransform.rect.width; + var offsetY = -rectTransform.pivot.y * rectTransform.rect.height; + + // don't want to scale based on the size of the rect, so this is switchable now + if (!relativeSize) + { + sizeX = 1; + sizeY = 1; + } + // build a new set of points taking into account the cap sizes. + // would be cool to support corners too, but that might be a bit tough :) + var pointList = new List(); + pointList.Add(Points[0]); + var capPoint = Points[0] + (Points[1] - Points[0]).normalized * capSize; + pointList.Add(capPoint); + + // should bail before the last point to add another cap point + for (int i = 1; i < Points.Length - 1; i++) + { + pointList.Add(Points[i]); + } + capPoint = Points[Points.Length - 1] - (Points[Points.Length - 1] - Points[Points.Length - 2]).normalized * capSize; + pointList.Add(capPoint); + pointList.Add(Points[Points.Length - 1]); + + var TempPoints = pointList.ToArray(); + if (UseMargins) + { + sizeX -= Margin.x; + sizeY -= Margin.y; + offsetX += Margin.x / 2f; + offsetY += Margin.y / 2f; + } + + vbo.Clear(); + + Vector2 prevV1 = Vector2.zero; + Vector2 prevV2 = Vector2.zero; + + for (int i = 1; i < TempPoints.Length; i++) + { + var prev = TempPoints[i - 1]; + var cur = TempPoints[i]; + prev = new Vector2(prev.x * sizeX + offsetX, prev.y * sizeY + offsetY); + cur = new Vector2(cur.x * sizeX + offsetX, cur.y * sizeY + offsetY); + + float angle = Mathf.Atan2(cur.y - prev.y, cur.x - prev.x) * 180f / Mathf.PI; + + var v1 = prev + new Vector2(0, -LineThickness / 2); + var v2 = prev + new Vector2(0, +LineThickness / 2); + var v3 = cur + new Vector2(0, +LineThickness / 2); + var v4 = cur + new Vector2(0, -LineThickness / 2); + + v1 = RotatePointAroundPivot(v1, prev, new Vector3(0, 0, angle)); + v2 = RotatePointAroundPivot(v2, prev, new Vector3(0, 0, angle)); + v3 = RotatePointAroundPivot(v3, cur, new Vector3(0, 0, angle)); + v4 = RotatePointAroundPivot(v4, cur, new Vector3(0, 0, angle)); + + Vector2 uvTopLeft = Vector2.zero; + Vector2 uvBottomLeft = new Vector2(0, 1); + + Vector2 uvTopCenter = new Vector2(0.5f, 0); + Vector2 uvBottomCenter = new Vector2(0.5f, 1); + + Vector2 uvTopRight = new Vector2(1, 0); + Vector2 uvBottomRight = new Vector2(1, 1); + + Vector2[] uvs = new[] { uvTopCenter, uvBottomCenter, uvBottomCenter, uvTopCenter }; + + if (i > 1) + SetVbo(vbo, new[] { prevV1, prevV2, v1, v2 }, uvs); + + if (i == 1) + uvs = new[] { uvTopLeft, uvBottomLeft, uvBottomCenter, uvTopCenter }; + else if (i == TempPoints.Length - 1) + uvs = new[] { uvTopCenter, uvBottomCenter, uvBottomRight, uvTopRight }; + + SetVbo(vbo, new[] { v1, v2, v3, v4 }, uvs); + + + prevV1 = v3; + prevV2 = v4; + } + } + + protected void SetVbo(List vbo, Vector2[] vertices, Vector2[] uvs) + { + for (int i = 0; i < vertices.Length; i++) + { + var vert = UIVertex.simpleVert; + vert.color = color; + vert.position = vertices[i]; + vert.uv0 = uvs[i]; + vbo.Add(vert); + } + } + + public Vector3 RotatePointAroundPivot(Vector3 point, Vector3 pivot, Vector3 angles) + { + Vector3 dir = point - pivot; // get point direction relative to pivot + dir = Quaternion.Euler(angles) * dir; // rotate it + point = dir + pivot; // calculate rotated point + return point; // return it + } + } +} \ No newline at end of file diff --git a/Scripts/UILineTextureRenderer.cs.meta b/Scripts/UILineTextureRenderer.cs.meta new file mode 100644 index 0000000..33e9194 --- /dev/null +++ b/Scripts/UILineTextureRenderer.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: b801876ddb189f94f905cd1646564fbf +timeCreated: 1440845581 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/UIScrollToSelection.cs b/Scripts/UIScrollToSelection.cs index aab4fda..f4da076 100644 --- a/Scripts/UIScrollToSelection.cs +++ b/Scripts/UIScrollToSelection.cs @@ -1,17 +1,19 @@ -/// sourced from: http://forum.unity3d.com/threads/scripts-useful-4-6-scripts-collection.264161/page-2#post-2011648 - -/*USAGE: -Simply place the script on the ScrollRect that contains the selectable children we'll be scroling to +/// Credit zero3growlithe +/// sourced from: http://forum.unity3d.com/threads/scripts-useful-4-6-scripts-collection.264161/page-2#post-2011648 + +/*USAGE: +Simply place the script on the ScrollRect that contains the selectable children we'll be scroling to and drag'n'drop the RectTransform of the options "container" that we'll be scrolling.*/ using UnityEngine.EventSystems; namespace UnityEngine.UI.Extensions { + [RequireComponent(typeof(ScrollRect))] public class UIScrollToSelection : MonoBehaviour { - /* ### VARIABLES ============================================================== */ + #region Variables // settings public float scrollSpeed = 10f; @@ -29,8 +31,8 @@ namespace UnityEngine.UI.Extensions private ScrollRect targetScrollRect; private EventSystem events = EventSystem.current; + #endregion - /* ### MAIN METHODS =========================================================== */ // Use this for initialization private void Start() { diff --git a/UnityUIExtensions.unitypackage b/UnityUIExtensions-4.x.unitypackage similarity index 100% rename from UnityUIExtensions.unitypackage rename to UnityUIExtensions-4.x.unitypackage diff --git a/UnityUIExtensions-4.x.unitypackage.meta b/UnityUIExtensions-4.x.unitypackage.meta new file mode 100644 index 0000000..31b0d1c --- /dev/null +++ b/UnityUIExtensions-4.x.unitypackage.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6099846579e92994a8eb58147565e5b6 +timeCreated: 1440889727 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/UnityUIExtensions-5.1.unitypackage b/UnityUIExtensions-5.1.unitypackage new file mode 100644 index 0000000..61e4688 Binary files /dev/null and b/UnityUIExtensions-5.1.unitypackage differ diff --git a/UnityUIExtensions-5.1.unitypackage.meta b/UnityUIExtensions-5.1.unitypackage.meta new file mode 100644 index 0000000..b2685d1 --- /dev/null +++ b/UnityUIExtensions-5.1.unitypackage.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ba77f83df2a458247a09d6017fed6ec2 +timeCreated: 1440890266 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: