| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383 |
- 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
- }
- }
|