From db57fc1e21101afbbccc74bd86fc990f0e517ebb Mon Sep 17 00:00:00 2001 From: "Simon (darkside) Jackson" Date: Sun, 30 Aug 2015 00:31:59 +0100 Subject: [PATCH] Initial update and merge of 5.1 Extensions package Documentation next to update Example videos to be done with each control / script *Stretch Goal, filter issue requests for late additions, esp Vertical Snap --- .../Editor/AccordionElementEditor.cs | 40 +- Scripts/Accordion/Tweening/ITweenValue.cs | 24 +- Scripts/Accordion/Tweening/TweenRunner.cs | 118 +- Scripts/ComboBox/AutoCompleteComboBox.cs | 4 +- Scripts/ComboBox/ComboBox.cs | 4 +- Scripts/Editor/UIExtensionsMenuOptions.cs | 17 +- Scripts/HSVPicker/ColorPickerTester.cs | 8 +- Scripts/HSVPicker/HSVSliderEvent.cs | 4 +- Scripts/HSVPicker/HsvSliderPicker.cs | 2 +- Scripts/ImageExtended.cs | 1074 +++++++++++++++++ Scripts/ImageExtended.cs.meta | 12 + Scripts/InputFocus.cs | 83 ++ Scripts/InputFocus.cs.meta | 12 + Scripts/RescalingPanels.meta | 9 + Scripts/RescalingPanels/RescaleDragPanel.cs | 64 + .../RescalingPanels/RescaleDragPanel.cs.meta | 12 + Scripts/RescalingPanels/RescalePanel.cs | 62 + Scripts/RescalingPanels/RescalePanel.cs.meta | 12 + Scripts/RescalingPanels/ResizePanel.cs | 60 + Scripts/RescalingPanels/ResizePanel.cs.meta | 12 + Scripts/ScrollRectEx.cs | 109 ++ Scripts/ScrollRectEx.cs.meta | 12 + Scripts/ScrollRectExtensions.cs | 17 + Scripts/ScrollRectExtensions.cs.meta | 12 + Scripts/ScrollRectLinker.cs | 34 + Scripts/ScrollRectLinker.cs.meta | 12 + Scripts/ScrollRectTweener.cs | 141 +++ Scripts/ScrollRectTweener.cs.meta | 12 + Scripts/SelectionBox/ExampleSelectable.cs | 4 +- Scripts/SelectionBox/IBoxSelectable.cs | 52 +- Scripts/SetPropertyUtility.cs | 36 + Scripts/SetPropertyUtility.cs.meta | 12 + Scripts/TabNavigation.cs | 18 + Scripts/ToolTip.cs | 12 +- Scripts/UILineRenderer.cs | 181 +++ Scripts/UILineRenderer.cs.meta | 12 + Scripts/UILineTextureRenderer.cs | 182 +++ Scripts/UILineTextureRenderer.cs.meta | 12 + Scripts/UIScrollToSelection.cs | 14 +- ...kage => UnityUIExtensions-4.x.unitypackage | Bin UnityUIExtensions-4.x.unitypackage.meta | 8 + UnityUIExtensions-5.1.unitypackage | Bin 0 -> 90353 bytes UnityUIExtensions-5.1.unitypackage.meta | 8 + 43 files changed, 2391 insertions(+), 142 deletions(-) create mode 100644 Scripts/ImageExtended.cs create mode 100644 Scripts/ImageExtended.cs.meta create mode 100644 Scripts/InputFocus.cs create mode 100644 Scripts/InputFocus.cs.meta create mode 100644 Scripts/RescalingPanels.meta create mode 100644 Scripts/RescalingPanels/RescaleDragPanel.cs create mode 100644 Scripts/RescalingPanels/RescaleDragPanel.cs.meta create mode 100644 Scripts/RescalingPanels/RescalePanel.cs create mode 100644 Scripts/RescalingPanels/RescalePanel.cs.meta create mode 100644 Scripts/RescalingPanels/ResizePanel.cs create mode 100644 Scripts/RescalingPanels/ResizePanel.cs.meta create mode 100644 Scripts/ScrollRectEx.cs create mode 100644 Scripts/ScrollRectEx.cs.meta create mode 100644 Scripts/ScrollRectExtensions.cs create mode 100644 Scripts/ScrollRectExtensions.cs.meta create mode 100644 Scripts/ScrollRectLinker.cs create mode 100644 Scripts/ScrollRectLinker.cs.meta create mode 100644 Scripts/ScrollRectTweener.cs create mode 100644 Scripts/ScrollRectTweener.cs.meta create mode 100644 Scripts/SetPropertyUtility.cs create mode 100644 Scripts/SetPropertyUtility.cs.meta create mode 100644 Scripts/UILineRenderer.cs create mode 100644 Scripts/UILineRenderer.cs.meta create mode 100644 Scripts/UILineTextureRenderer.cs create mode 100644 Scripts/UILineTextureRenderer.cs.meta rename UnityUIExtensions.unitypackage => UnityUIExtensions-4.x.unitypackage (100%) create mode 100644 UnityUIExtensions-4.x.unitypackage.meta create mode 100644 UnityUIExtensions-5.1.unitypackage create mode 100644 UnityUIExtensions-5.1.unitypackage.meta 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 0000000000000000000000000000000000000000..61e4688063d8084dd84f89a5748046d4edeb433b GIT binary patch literal 90353 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

xx|13diYcjXk0nH7Qm6klFK$Sa;@DaL*- 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%0AO*buBTlI!JGvUZ^e2neTxi#D{@B@@3rZF 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 M0Zfwq{{W~806F40;Q#;t literal 0 HcmV?d00001 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: