diff options
| author | chai <chaifix@163.com> | 2021-04-07 21:33:14 +0800 | 
|---|---|---|
| committer | chai <chaifix@163.com> | 2021-04-07 21:33:14 +0800 | 
| commit | c47b92e92cf33ae8bf2f38929e137294397e4735 (patch) | |
| tree | c67ae3419eaf15e84f1679186e107f598de33978 /Assets/Scripts/UIShadow.cs | |
Diffstat (limited to 'Assets/Scripts/UIShadow.cs')
| -rw-r--r-- | Assets/Scripts/UIShadow.cs | 383 | 
1 files changed, 383 insertions, 0 deletions
| diff --git a/Assets/Scripts/UIShadow.cs b/Assets/Scripts/UIShadow.cs new file mode 100644 index 0000000..42ec596 --- /dev/null +++ b/Assets/Scripts/UIShadow.cs @@ -0,0 +1,383 @@ +using System; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.Serialization; +using UnityEngine.UI; +#if UNITY_EDITOR +using System.IO; +using System.Linq; +using UnityEditor; + +#endif + +namespace Coffee.UIEffects +{ +    /// <summary> +    /// UIEffect. +    /// </summary> +    [RequireComponent(typeof(Graphic))] +    [AddComponentMenu("UI/UIEffects/UIShadow", 100)] +    public class UIShadow : BaseMeshEffect, IParameterTexture +    { +        static readonly List<UIShadow> tmpShadows = new List<UIShadow>(); +        static readonly List<UIVertex> s_Verts = new List<UIVertex>(4096); + +        int _graphicVertexCount; +        UIEffect _uiEffect; + +        [Tooltip("How far is the blurring shadow from the graphic.")] +        [FormerlySerializedAs("m_Blur")] +        [SerializeField] +        [Range(0, 1)] +        float m_BlurFactor = 1; + +        [Tooltip("Shadow effect style.")] [SerializeField] +        ShadowStyle m_Style = ShadowStyle.Shadow; + +        [SerializeField] private Color m_EffectColor = new Color(0f, 0f, 0f, 0.5f); + +        [SerializeField] private Vector2 m_EffectDistance = new Vector2(1f, -1f); + +        [SerializeField] private bool m_UseGraphicAlpha = true; + +        private const float kMaxEffectDistance = 600f; + +        public Color effectColor +        { +            get { return m_EffectColor; } +            set +            { +                if (m_EffectColor == value) return; +                m_EffectColor = value; +                SetVerticesDirty(); +            } +        } + +        public Vector2 effectDistance +        { +            get { return m_EffectDistance; } +            set +            { +                if (value.x > kMaxEffectDistance) +                    value.x = kMaxEffectDistance; +                if (value.x < -kMaxEffectDistance) +                    value.x = -kMaxEffectDistance; + +                if (value.y > kMaxEffectDistance) +                    value.y = kMaxEffectDistance; +                if (value.y < -kMaxEffectDistance) +                    value.y = -kMaxEffectDistance; + +                if (m_EffectDistance == value) return; +                m_EffectDistance = value; +                SetEffectParamsDirty(); +            } +        } + +        public bool useGraphicAlpha +        { +            get { return m_UseGraphicAlpha; } +            set +            { +                if (m_UseGraphicAlpha == value) return; +                m_UseGraphicAlpha = value; +                SetEffectParamsDirty(); +            } +        } + +        /// <summary> +        /// How far is the blurring shadow from the graphic. +        /// </summary> +        public float blurFactor +        { +            get { return m_BlurFactor; } +            set +            { +                value = Mathf.Clamp(value, 0, 2); +                if (Mathf.Approximately(m_BlurFactor, value)) return; +                m_BlurFactor = value; +                SetEffectParamsDirty(); +            } +        } + +        /// <summary> +        /// Shadow effect style. +        /// </summary> +        public ShadowStyle style +        { +            get { return m_Style; } +            set +            { +                if (m_Style == value) return; +                m_Style = value; +                SetEffectParamsDirty(); +            } +        } + +        /// <summary> +        /// Gets or sets the parameter index. +        /// </summary> +        public int parameterIndex { get; set; } + +        /// <summary> +        /// Gets the parameter texture. +        /// </summary> +        public ParameterTexture paramTex { get; private set; } + +        protected override void OnEnable() +        { +            base.OnEnable(); + +            _uiEffect = GetComponent<UIEffect>(); +            if (!_uiEffect) return; + +            paramTex = _uiEffect.paramTex; +            paramTex.Register(this); +        } + +        protected override void OnDisable() +        { +            base.OnDisable(); + +            _uiEffect = null; +            if (paramTex == null) return; + +            paramTex.Unregister(this); +            paramTex = null; +        } + + +// #if UNITY_EDITOR +//         protected override void OnValidate() +//         { +//             effectDistance = m_EffectDistance; +//             base.OnValidate(); +//         } +// #endif + +        // #if TMP_PRESENT +        // protected void OnCullStateChanged (bool state) +        // { +        // 	SetVerticesDirty (); +        // } +        // +        // Vector2 res; +        // protected override void LateUpdate () +        // { +        // 	if (res.x != Screen.width || res.y != Screen.height) +        // 	{ +        // 		res.x = Screen.width; +        // 		res.y = Screen.height; +        // 		SetVerticesDirty (); +        // 	} +        // 	if (textMeshPro && transform.hasChanged) +        // 	{ +        // 		transform.hasChanged = false; +        // 	} +        // 	base.LateUpdate (); +        // } +        // #endif + +        /// <summary> +        /// Modifies the mesh. +        /// </summary> +        public override void ModifyMesh(VertexHelper vh, Graphic graphic) +        { +            if (!isActiveAndEnabled || vh.currentVertCount <= 0 || m_Style == ShadowStyle.None) +            { +                return; +            } + +            vh.GetUIVertexStream(s_Verts); + +            GetComponents<UIShadow>(tmpShadows); + +            foreach (var s in tmpShadows) +            { +                if (!s.isActiveAndEnabled) continue; +                if (s == this) +                { +                    foreach (var s2 in tmpShadows) +                    { +                        s2._graphicVertexCount = s_Verts.Count; +                    } +                } + +                break; +            } + +            tmpShadows.Clear(); + +            //================================ +            // Append shadow vertices. +            //================================ +            { +                _uiEffect = _uiEffect ? _uiEffect : GetComponent<UIEffect>(); +                var start = s_Verts.Count - _graphicVertexCount; +                var end = s_Verts.Count; + +                if (paramTex != null && _uiEffect && _uiEffect.isActiveAndEnabled) +                { +                    paramTex.SetData(this, 0, _uiEffect.effectFactor); // param.x : effect factor +                    paramTex.SetData(this, 1, 255); // param.y : color factor +                    paramTex.SetData(this, 2, m_BlurFactor); // param.z : blur factor +                } + +                ApplyShadow(s_Verts, effectColor, ref start, ref end, effectDistance, style, useGraphicAlpha); +            } + +            vh.Clear(); +            vh.AddUIVertexTriangleStream(s_Verts); + +            s_Verts.Clear(); +        } + +        /// <summary> +        /// Append shadow vertices. +        /// * It is similar to Shadow component implementation. +        /// </summary> +        private void ApplyShadow(List<UIVertex> verts, Color color, ref int start, ref int end, Vector2 distance, +            ShadowStyle style, bool alpha) +        { +            if (style == ShadowStyle.None || color.a <= 0) +                return; + +            var x = distance.x; +            var y = distance.y; +            // Append Shadow. +            ApplyShadowZeroAlloc(verts, color, ref start, ref end, x, y, alpha); + +            switch (style) +            { +                // Append Shadow3. +                case ShadowStyle.Shadow3: +                    ApplyShadowZeroAlloc(verts, color, ref start, ref end, x, 0, alpha); +                    ApplyShadowZeroAlloc(verts, color, ref start, ref end, 0, y, alpha); +                    break; +                // Append Outline. +                case ShadowStyle.Outline: +                    ApplyShadowZeroAlloc(verts, color, ref start, ref end, x, -y, alpha); +                    ApplyShadowZeroAlloc(verts, color, ref start, ref end, -x, y, alpha); +                    ApplyShadowZeroAlloc(verts, color, ref start, ref end, -x, -y, alpha); +                    break; +                // Append Outline8. +                case ShadowStyle.Outline8: +                    ApplyShadowZeroAlloc(verts, color, ref start, ref end, x, -y, alpha); +                    ApplyShadowZeroAlloc(verts, color, ref start, ref end, -x, y, alpha); +                    ApplyShadowZeroAlloc(verts, color, ref start, ref end, -x, -y, alpha); +                    ApplyShadowZeroAlloc(verts, color, ref start, ref end, -x, 0, alpha); +                    ApplyShadowZeroAlloc(verts, color, ref start, ref end, 0, -y, alpha); +                    ApplyShadowZeroAlloc(verts, color, ref start, ref end, x, 0, alpha); +                    ApplyShadowZeroAlloc(verts, color, ref start, ref end, 0, y, alpha); +                    break; +            } +        } + +        /// <summary> +        /// Append shadow vertices. +        /// * It is similar to Shadow component implementation. +        /// </summary> +        private void ApplyShadowZeroAlloc(List<UIVertex> verts, Color color, ref int start, ref int end, float x, +            float y, bool alpha) +        { +            // Check list capacity. +            var count = end - start; +            var neededCapacity = verts.Count + count; +            if (verts.Capacity < neededCapacity) +                verts.Capacity *= 2; + +            var normalizedIndex = paramTex != null && _uiEffect && _uiEffect.isActiveAndEnabled +                ? paramTex.GetNormalizedIndex(this) +                : -1; + +            // Add +            var vt = default(UIVertex); +            for (var i = 0; i < count; i++) +            { +                verts.Add(vt); +            } + +            // Move +            for (var i = verts.Count - 1; count <= i; i--) +            { +                verts[i] = verts[i - count]; +            } + +            // Append shadow vertices to the front of list. +            // * The original vertex is pushed backward. +            for (var i = 0; i < count; ++i) +            { +                vt = verts[i + start + count]; + +                var v = vt.position; +                vt.position.Set(v.x + x, v.y + y, v.z); + +                var vertColor = effectColor; +                vertColor.a = alpha ? color.a * vt.color.a / 255 : color.a; +                vt.color = vertColor; + + +                // Set UIEffect parameters +                if (0 <= normalizedIndex) +                { +                    vt.uv0 = new Vector2( +                        vt.uv0.x, +                        normalizedIndex +                    ); +                } + +                verts[i] = vt; +            } + +            // Update next shadow offset. +            start = end; +            end = verts.Count; +        } + +        /// <summary> +        /// Mark the UIEffect as dirty. +        /// </summary> +        // void _SetDirty() +        // { +        //     if (graphic) +        //         graphic.SetVerticesDirty(); +        // } + +// #if UNITY_EDITOR +//         public void OnBeforeSerialize() +//         { +//         } +// +//         public void OnAfterDeserialize() +//         { +//             EditorApplication.delayCall += UpgradeIfNeeded; +//         } +// +// +// #pragma warning disable 0612 +//         void UpgradeIfNeeded() +//         { +//             if (0 < m_AdditionalShadows.Count) +//             { +//                 foreach (var s in m_AdditionalShadows) +//                 { +//                     if (s.style == ShadowStyle.None) +//                     { +//                         continue; +//                     } +// +//                     var shadow = gameObject.AddComponent<UIShadow>(); +//                     shadow.style = s.style; +//                     shadow.effectDistance = s.effectDistance; +//                     shadow.effectColor = s.effectColor; +//                     shadow.useGraphicAlpha = s.useGraphicAlpha; +//                     shadow.blurFactor = s.blur; +//                 } +// +//                 m_AdditionalShadows = null; +//             } +//         } +// #pragma warning restore 0612 +// #endif +    } +} | 
