From 03c2e4d81fb286dd873023743354404d2145e3c1 Mon Sep 17 00:00:00 2001 From: "Simon (darkside) Jackson" Date: Sat, 28 May 2016 00:04:08 +0100 Subject: [PATCH] Numerous fixes to HSS / VSS - added warning not to use scrollbars Added fix for reorderable list last item issue Fixed UI Vertical scroller demo - swapped year and day round as it was confusing UI Selectable fix for onDisable to set as unpressed Added new Shine Effect control 1.1 release coding done. Next update release notes and test --HG-- branch : develop_5.3 --- Scripts/Effects/ShineEffect.cs | 95 +++++++ Scripts/Effects/ShineEffect.cs.meta | 12 + Scripts/Effects/ShineEffector.cs | 115 +++++++++ Scripts/Effects/ShineEffector.cs.meta | 12 + Scripts/Effects/UIParticleSystem.cs | 234 ++++++++++++++++++ Scripts/Effects/UIParticleSystem.cs.meta | 12 + Scripts/Layout/HorizontalScrollSnap.cs | 6 + .../Scenes/VerticalCalendar.unity | 12 +- Scripts/Layout/VerticalScrollSnap.cs | 8 +- .../ReorderableList/ReorderableListElement.cs | 5 +- Scripts/Utilities/UISelectableExtension.cs | 9 +- 11 files changed, 510 insertions(+), 10 deletions(-) create mode 100644 Scripts/Effects/ShineEffect.cs create mode 100644 Scripts/Effects/ShineEffect.cs.meta create mode 100644 Scripts/Effects/ShineEffector.cs create mode 100644 Scripts/Effects/ShineEffector.cs.meta create mode 100644 Scripts/Effects/UIParticleSystem.cs create mode 100644 Scripts/Effects/UIParticleSystem.cs.meta diff --git a/Scripts/Effects/ShineEffect.cs b/Scripts/Effects/ShineEffect.cs new file mode 100644 index 0000000..410ed27 --- /dev/null +++ b/Scripts/Effects/ShineEffect.cs @@ -0,0 +1,95 @@ +/// Credit ömer faruk sayılır +/// Sourced from - https://bitbucket.org/snippets/Lordinarius/nrn4L + +namespace UnityEngine.UI.Extensions +{ + public class ShineEffect : MaskableGraphic + { + + [SerializeField] + float yoffset = -1; + + public float Yoffset + { + get + { + return yoffset; + } + set + { + SetVerticesDirty(); + yoffset = value; + } + } + + [SerializeField] + float width = 1; + + public float Width + { + get + { + return width; + } + set + { + SetAllDirty(); + width = value; + } + } + + protected override void OnPopulateMesh(VertexHelper vh) + { + var r = GetPixelAdjustedRect(); + var v = new Vector4(r.x, r.y, r.x + r.width, r.y + r.height); + float dif = (v.w - v.y) * 2; + Color32 color32 = color; + vh.Clear(); + + color32.a = (byte)0; + vh.AddVert(new Vector3(v.x - 50, width * v.y + yoffset * dif), color32, new Vector2(0f, 0f)); + vh.AddVert(new Vector3(v.z + 50, width * v.y + yoffset * dif), color32, new Vector2(1f, 0f)); + + color32.a = (byte)(color.a * 255); + vh.AddVert(new Vector3(v.x - 50, width * (v.y / 4) + yoffset * dif), color32, new Vector2(0f, 1f)); + vh.AddVert(new Vector3(v.z + 50, width * (v.y / 4) + yoffset * dif), color32, new Vector2(1f, 1f)); + + color32.a = (byte)(color.a * 255); + vh.AddVert(new Vector3(v.x - 50, width * (v.w / 4) + yoffset * dif), color32, new Vector2(0f, 1f)); + vh.AddVert(new Vector3(v.z + 50, width * (v.w / 4) + yoffset * dif), color32, new Vector2(1f, 1f)); + color32.a = (byte)(color.a * 255); + + color32.a = (byte)0; + vh.AddVert(new Vector3(v.x - 50, width * v.w + yoffset * dif), color32, new Vector2(0f, 1f)); + vh.AddVert(new Vector3(v.z + 50, width * v.w + yoffset * dif), color32, new Vector2(1f, 1f)); + + vh.AddTriangle(0, 1, 2); + vh.AddTriangle(2, 3, 1); + + vh.AddTriangle(2, 3, 4); + vh.AddTriangle(4, 5, 3); + + vh.AddTriangle(4, 5, 6); + vh.AddTriangle(6, 7, 5); + } + + public void Triangulate(VertexHelper vh) + { + int triangleCount = vh.currentVertCount - 2; + Debug.Log(triangleCount); + for (int i = 0; i <= triangleCount / 2 + 1; i += 2) + { + vh.AddTriangle(i, i + 1, i + 2); + vh.AddTriangle(i + 2, i + 3, i + 1); + } + } + +#if UNITY_EDITOR + public override void OnRebuildRequested() + { + base.OnRebuildRequested(); + } +#endif + + } +} \ No newline at end of file diff --git a/Scripts/Effects/ShineEffect.cs.meta b/Scripts/Effects/ShineEffect.cs.meta new file mode 100644 index 0000000..b2bbb2c --- /dev/null +++ b/Scripts/Effects/ShineEffect.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 453baf32313c0bc41a532c409ec25177 +timeCreated: 1464388954 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/Effects/ShineEffector.cs b/Scripts/Effects/ShineEffector.cs new file mode 100644 index 0000000..11a4b3e --- /dev/null +++ b/Scripts/Effects/ShineEffector.cs @@ -0,0 +1,115 @@ +/// Credit ömer faruk sayılır +/// Sourced from - https://bitbucket.org/snippets/Lordinarius/nrn4L + +namespace UnityEngine.UI.Extensions +{ + [ExecuteInEditMode, RequireComponent(typeof(Image))] + [AddComponentMenu("UI/Effects/Extensions/Shining Effect")] + public class ShineEffector : MonoBehaviour + { + + public ShineEffect effector; + [SerializeField, HideInInspector] + GameObject effectRoot; + [Range(-1, 1)] + public float yOffset = -1; + + public float YOffset + { + get + { + return yOffset; + } + set + { + ChangeVal(value); + yOffset = value; + } + } + + [Range(0.1f, 1)] + public float width = 0.5f; + RectTransform effectorRect; + void OnEnable() + { + if (effector == null) + { + GameObject effectorobj = new GameObject("effector"); + + effectRoot = new GameObject("ShineEffect"); + effectRoot.transform.SetParent(this.transform); + effectRoot.AddComponent().sprite = gameObject.GetComponent().sprite; + effectRoot.GetComponent().type = gameObject.GetComponent().type; + effectRoot.AddComponent().showMaskGraphic = false; + effectRoot.transform.localScale = Vector3.one; + effectRoot.GetComponent().anchoredPosition3D = Vector3.zero; + effectRoot.GetComponent().anchorMax = Vector2.one; + effectRoot.GetComponent().anchorMin = Vector2.zero; + effectRoot.GetComponent().offsetMax = Vector2.zero; + effectRoot.GetComponent().offsetMin = Vector2.zero; + effectRoot.transform.SetAsFirstSibling(); + + effectorobj.AddComponent(); + effectorobj.transform.SetParent(effectRoot.transform); + effectorRect = effectorobj.GetComponent(); + effectorRect.localScale = Vector3.one; + effectorRect.anchoredPosition3D = Vector3.zero; + + effectorRect.gameObject.AddComponent(); + effectorRect.anchorMax = Vector2.one; + effectorRect.anchorMin = Vector2.zero; + + effectorRect.Rotate(0, 0, -8); + effector = effectorobj.GetComponent(); + effectorRect.offsetMax = Vector2.zero; + effectorRect.offsetMin = Vector2.zero; + OnValidate(); + } + } + + void OnValidate() + { + effector.Yoffset = yOffset; + effector.Width = width; + + if (yOffset <= -1 || yOffset >= 1) + { + effectRoot.SetActive(false); + } + else if (!effectRoot.activeSelf) + { + effectRoot.SetActive(true); + } + { + + } + } + + void ChangeVal(float value) + { + effector.Yoffset = value; + if (value <= -1 || value >= 1) + { + effectRoot.SetActive(false); + } + else if (!effectRoot.activeSelf) + { + effectRoot.SetActive(true); + } + { + + } + } + void OnDestroy() + { + if (!Application.isPlaying) + { + DestroyImmediate(effectRoot); + } + else + { + Destroy(effectRoot); + } + } + } +} \ No newline at end of file diff --git a/Scripts/Effects/ShineEffector.cs.meta b/Scripts/Effects/ShineEffector.cs.meta new file mode 100644 index 0000000..01586bb --- /dev/null +++ b/Scripts/Effects/ShineEffector.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: ced63edd65f3aed41a6c4125a5f54217 +timeCreated: 1464388991 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/Effects/UIParticleSystem.cs b/Scripts/Effects/UIParticleSystem.cs new file mode 100644 index 0000000..9b8a7e6 --- /dev/null +++ b/Scripts/Effects/UIParticleSystem.cs @@ -0,0 +1,234 @@ +/// Credit glennpow +/// Sourced from - http://forum.unity3d.com/threads/free-script-particle-systems-in-ui-screen-space-overlay.406862/ + +namespace UnityEngine.UI.Extensions +{ +#if UNITY_5_3_OR_NEWER + [ExecuteInEditMode] + [RequireComponent(typeof(CanvasRenderer))] + [RequireComponent(typeof(ParticleSystem))] + [AddComponentMenu("UI/Effects/Extensions/UI Particle System")] + public class UIParticleSystem : MaskableGraphic { + + public Texture particleTexture; + public Sprite particleSprite; + + private Transform _transform; + private ParticleSystem _particleSystem; + private ParticleSystem.Particle[] _particles; + private UIVertex[] _quad = new UIVertex[4]; + private Vector4 _uv = Vector4.zero; + private ParticleSystem.TextureSheetAnimationModule _textureSheetAnimation; + private int _textureSheetAnimationFrames; + private Vector2 _textureSheedAnimationFrameSize; + + public override Texture mainTexture { + get { + if (particleTexture) { + return particleTexture; + } + + if (particleSprite) { + return particleSprite.texture; + } + + return null; + } + } + + protected bool Initialize() { + // initialize members + if (_transform == null) { + _transform = transform; + } + if (_particleSystem == null) { + _particleSystem = GetComponent(); + + if (_particleSystem == null) { + return false; + } + + // automatically set material to UI/Particles/Hidden shader, and get previous texture + ParticleSystemRenderer renderer = _particleSystem.GetComponent(); + if (renderer == null) { + renderer = _particleSystem.gameObject.AddComponent(); + } + Material currentMaterial = renderer.sharedMaterial; + if (currentMaterial && currentMaterial.HasProperty("_MainTex")) { + particleTexture = currentMaterial.mainTexture; + } + Material material = new Material(Shader.Find("UI/Particles/Hidden")); // TODO - You should create this discard shader + if (Application.isPlaying) { + renderer.material = material; + } +#if UNITY_EDITOR + else { + material.hideFlags = HideFlags.DontSave; + renderer.sharedMaterial = material; + } +#endif + + // automatically set scaling + _particleSystem.scalingMode = ParticleSystemScalingMode.Hierarchy; + + _particles = null; + } + if (_particles == null) { + _particles = new ParticleSystem.Particle[_particleSystem.maxParticles]; + } + + // prepare uvs + if (particleTexture) { + _uv = new Vector4(0, 0, 1, 1); + } else if (particleSprite) { + _uv = UnityEngine.Sprites.DataUtility.GetOuterUV(particleSprite); + } + + // prepare texture sheet animation + _textureSheetAnimation = _particleSystem.textureSheetAnimation; + _textureSheetAnimationFrames = 0; + _textureSheedAnimationFrameSize = Vector2.zero; + if (_textureSheetAnimation.enabled) { + _textureSheetAnimationFrames = _textureSheetAnimation.numTilesX * _textureSheetAnimation.numTilesY; + _textureSheedAnimationFrameSize = new Vector2(1f / _textureSheetAnimation.numTilesX, 1f / _textureSheetAnimation.numTilesY); + } + + return true; + } + + protected override void Awake() { + base.Awake(); + + if (!Initialize()) { + enabled = false; + } + } + + protected override void OnPopulateMesh(VertexHelper vh) { +#if UNITY_EDITOR + if (!Application.isPlaying) { + if (!Initialize()) { + return; + } + } +#endif + + // prepare vertices + vh.Clear(); + + if (!gameObject.activeInHierarchy) { + return; + } + + // iterate through current particles + int count = _particleSystem.GetParticles(_particles); + + for (int i = 0; i < count; ++i) { + ParticleSystem.Particle particle = _particles[i]; + + // get particle properties + Vector2 position = (_particleSystem.simulationSpace == ParticleSystemSimulationSpace.Local ? particle.position : _transform.InverseTransformPoint(particle.position)); + float rotation = -particle.rotation * Mathf.Deg2Rad; + float rotation90 = rotation + Mathf.PI / 2; + Color32 color = particle.GetCurrentColor(_particleSystem); + float size = particle.GetCurrentSize(_particleSystem) * 0.5f; + + // apply scale + if (_particleSystem.scalingMode == ParticleSystemScalingMode.Shape) { + position /= canvas.scaleFactor; + } + + // apply texture sheet animation + Vector4 particleUV = _uv; + if (_textureSheetAnimation.enabled) { + float frameProgress = 1 - (particle.lifetime / particle.startLifetime); + // float frameProgress = textureSheetAnimation.frameOverTime.curveMin.Evaluate(1 - (particle.lifetime / particle.startLifetime)); // TODO - once Unity allows MinMaxCurve reading + frameProgress = Mathf.Repeat(frameProgress * _textureSheetAnimation.cycleCount, 1); + int frame = 0; + + switch (_textureSheetAnimation.animation) { + + case ParticleSystemAnimationType.WholeSheet: + frame = Mathf.FloorToInt(frameProgress * _textureSheetAnimationFrames); + break; + + case ParticleSystemAnimationType.SingleRow: + frame = Mathf.FloorToInt(frameProgress * _textureSheetAnimation.numTilesX); + + int row = _textureSheetAnimation.rowIndex; + // if (textureSheetAnimation.useRandomRow) { // FIXME - is this handled internally by rowIndex? + // row = Random.Range(0, textureSheetAnimation.numTilesY, using: particle.randomSeed); + // } + frame += row * _textureSheetAnimation.numTilesX; + break; + + } + + frame %= _textureSheetAnimationFrames; + + particleUV.x = (frame % _textureSheetAnimation.numTilesX) * _textureSheedAnimationFrameSize.x; + particleUV.y = Mathf.FloorToInt(frame / _textureSheetAnimation.numTilesX) * _textureSheedAnimationFrameSize.y; + particleUV.z = particleUV.x + _textureSheedAnimationFrameSize.x; + particleUV.w = particleUV.y + _textureSheedAnimationFrameSize.y; + } + + _quad[0] = UIVertex.simpleVert; + _quad[0].color = color; + _quad[0].uv0 = new Vector2(particleUV.x, particleUV.y); + + _quad[1] = UIVertex.simpleVert; + _quad[1].color = color; + _quad[1].uv0 = new Vector2(particleUV.x, particleUV.w); + + _quad[2] = UIVertex.simpleVert; + _quad[2].color = color; + _quad[2].uv0 = new Vector2(particleUV.z, particleUV.w); + + _quad[3] = UIVertex.simpleVert; + _quad[3].color = color; + _quad[3].uv0 = new Vector2(particleUV.z, particleUV.y); + + if (rotation == 0) { + // no rotation + Vector2 corner1 = new Vector2(position.x - size, position.y - size); + Vector2 corner2 = new Vector2(position.x + size, position.y + size); + + _quad[0].position = new Vector2(corner1.x, corner1.y); + _quad[1].position = new Vector2(corner1.x, corner2.y); + _quad[2].position = new Vector2(corner2.x, corner2.y); + _quad[3].position = new Vector2(corner2.x, corner1.y); + } else { + // apply rotation + Vector2 right = new Vector2(Mathf.Cos(rotation), Mathf.Sin(rotation)) * size; + Vector2 up = new Vector2(Mathf.Cos(rotation90), Mathf.Sin(rotation90)) * size; + + _quad[0].position = position - right - up; + _quad[1].position = position - right + up; + _quad[2].position = position + right + up; + _quad[3].position = position + right - up; + } + + vh.AddUIVertexQuad(_quad); + } + } + + void Update() { + if (Application.isPlaying) { + // unscaled animation within UI + _particleSystem.Simulate(Time.unscaledDeltaTime, false, false); + + SetAllDirty(); + } + } + +#if UNITY_EDITOR + void LateUpdate() { + if (!Application.isPlaying) { + SetAllDirty(); + } + } +#endif + + } +#endif +} \ No newline at end of file diff --git a/Scripts/Effects/UIParticleSystem.cs.meta b/Scripts/Effects/UIParticleSystem.cs.meta new file mode 100644 index 0000000..1acf04d --- /dev/null +++ b/Scripts/Effects/UIParticleSystem.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: f5f85388e938d9e4599afc6d9441ed57 +timeCreated: 1464383716 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/Layout/HorizontalScrollSnap.cs b/Scripts/Layout/HorizontalScrollSnap.cs index 8c10a26..8800843 100644 --- a/Scripts/Layout/HorizontalScrollSnap.cs +++ b/Scripts/Layout/HorizontalScrollSnap.cs @@ -66,6 +66,12 @@ namespace UnityEngine.UI.Extensions void Start() { _scroll_rect = gameObject.GetComponent(); + + if (_scroll_rect.horizontalScrollbar || _scroll_rect.verticalScrollbar) + { + Debug.LogWarning("Warning, using scrollbors with the Scroll Snap controls is not advised as it causes unpredictable results"); + } + _screensContainer = _scroll_rect.content; if (PageStep == 0) { diff --git a/Scripts/Layout/UIVerticalScrollerDemo/Scenes/VerticalCalendar.unity b/Scripts/Layout/UIVerticalScrollerDemo/Scenes/VerticalCalendar.unity index 380b943..0d5ee87 100644 --- a/Scripts/Layout/UIVerticalScrollerDemo/Scenes/VerticalCalendar.unity +++ b/Scripts/Layout/UIVerticalScrollerDemo/Scenes/VerticalCalendar.unity @@ -803,9 +803,9 @@ RectTransform: - {fileID: 2121923045} m_Father: {fileID: 674720969} m_RootOrder: 4 - m_AnchorMin: {x: 1, y: 1} - m_AnchorMax: {x: 1, y: 1} - m_AnchoredPosition: {x: -120, y: -20} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 120, y: -20} m_SizeDelta: {x: 80, y: 50} m_Pivot: {x: 1, y: 1} --- !u!114 &321020790 @@ -1782,9 +1782,9 @@ RectTransform: - {fileID: 1871797415} m_Father: {fileID: 674720969} m_RootOrder: 2 - m_AnchorMin: {x: 0, y: 1} - m_AnchorMax: {x: 0, y: 1} - m_AnchoredPosition: {x: 120, y: -20} + m_AnchorMin: {x: 1, y: 1} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: -120, y: -20} m_SizeDelta: {x: 80, y: 50} m_Pivot: {x: 0, y: 1} --- !u!114 &945015714 diff --git a/Scripts/Layout/VerticalScrollSnap.cs b/Scripts/Layout/VerticalScrollSnap.cs index 81dd390..78d525c 100644 --- a/Scripts/Layout/VerticalScrollSnap.cs +++ b/Scripts/Layout/VerticalScrollSnap.cs @@ -63,6 +63,12 @@ namespace UnityEngine.UI.Extensions void Start() { _scroll_rect = gameObject.GetComponent(); + + if (_scroll_rect.horizontalScrollbar || _scroll_rect.verticalScrollbar) + { + Debug.LogWarning("Warning, using scrollbors with the Scroll Snap controls is not advised as it causes unpredictable results"); + } + _screensContainer = _scroll_rect.content; if (PageStep == 0) { @@ -213,7 +219,7 @@ namespace UnityEngine.UI.Extensions } //used for changing between screen resolutions - private void DistributePages() + public void DistributePages() { float _offset = 0; float _dimension = 0; diff --git a/Scripts/ReorderableList/ReorderableListElement.cs b/Scripts/ReorderableList/ReorderableListElement.cs index 6d964be..a0f7a21 100644 --- a/Scripts/ReorderableList/ReorderableListElement.cs +++ b/Scripts/ReorderableList/ReorderableListElement.cs @@ -1,5 +1,6 @@ -/// Credit Ziboo +/// Credit Ziboo, Andrew Quesenberry /// Sourced from - http://forum.unity3d.com/threads/free-reorderable-list.364600/ +/// Last Child Fix - https://bitbucket.org/ddreaper/unity-ui-extensions/issues/70/all-re-orderable-lists-cause-a-transform using System.Collections.Generic; using UnityEngine.EventSystems; @@ -217,7 +218,7 @@ namespace UnityEngine.UI.Extensions { Vector2 size = _draggingObjectOriginalSize; - if (_currentReorderableListRaycasted != null && _currentReorderableListRaycasted.IsDropable) + if (_currentReorderableListRaycasted != null && _currentReorderableListRaycasted.IsDropable && _currentReorderableListRaycasted.Content.childCount > 0) { var firstChild = _currentReorderableListRaycasted.Content.GetChild(0); if (firstChild != null) diff --git a/Scripts/Utilities/UISelectableExtension.cs b/Scripts/Utilities/UISelectableExtension.cs index 0f73cf1..b677019 100644 --- a/Scripts/Utilities/UISelectableExtension.cs +++ b/Scripts/Utilities/UISelectableExtension.cs @@ -1,5 +1,6 @@ -/// Credit AriathTheWise +/// Credit AriathTheWise, Sfyne /// Sourced from - http://forum.unity3d.com/threads/scripts-useful-4-6-scripts-collection.264161/page-2#post-1796783 +/// Additional disabled - https://bitbucket.org/ddreaper/unity-ui-extensions/issues/47/uiselectableextension-_pressed-bug /// Extended to include a HELD state that continually fires while the button is held down. /// Refactored so it can be added to any button and expose the events in the editor. @@ -108,5 +109,11 @@ namespace UnityEngine.UI.Extensions Debug.Log("Control Held"); #endif } + + //Fixed UISelectableExtension inactive bug (if gameObject becomes inactive while button is held down it never goes back to _pressed = false) + void OnDisable() + { + _pressed = false; + } } } \ No newline at end of file