UIDissolve.cs 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. using System;
  2. using UnityEngine;
  3. using UnityEditor;
  4. using UnityEngine.UI;
  5. using UnityEngine.Serialization;
  6. using System.Text;
  7. using System.Linq;
  8. using System.IO;
  9. namespace Coffee.UIEffects
  10. {
  11. /// <summary>
  12. /// Dissolve effect for uGUI.
  13. /// </summary>
  14. [AddComponentMenu("UI/UIEffects/UIDissolve", 3)]
  15. public class UIDissolve : BaseMaterialEffect, IMaterialModifier
  16. {
  17. private const uint k_ShaderId = 0 << 3;
  18. private static readonly ParameterTexture s_ParamTex = new ParameterTexture(8, 128, "_ParamTex");
  19. private static readonly int k_TransitionTexId = Shader.PropertyToID("_TransitionTex");
  20. private bool _lastKeepAspectRatio;
  21. private EffectArea _lastEffectArea;
  22. private static Texture _defaultTransitionTexture;
  23. [Tooltip("Current location[0-1] for dissolve effect. 0 is not dissolved, 1 is completely dissolved.")]
  24. [FormerlySerializedAs("m_Location")]
  25. [SerializeField]
  26. [Range(0, 1)]
  27. float m_EffectFactor = 0.5f;
  28. [Tooltip("Edge width.")] [SerializeField] [Range(0, 1)]
  29. float m_Width = 0.5f;
  30. [Tooltip("Edge softness.")] [SerializeField] [Range(0, 1)]
  31. float m_Softness = 0.5f;
  32. [Tooltip("Edge color.")] [SerializeField] [ColorUsage(false)]
  33. Color m_Color = new Color(0.0f, 0.25f, 1.0f);
  34. [Tooltip("Edge color effect mode.")] [SerializeField]
  35. ColorMode m_ColorMode = ColorMode.Add;
  36. [Tooltip("Noise texture for dissolving (single channel texture).")]
  37. [SerializeField]
  38. [FormerlySerializedAs("m_NoiseTexture")]
  39. Texture m_TransitionTexture;
  40. [Header("Advanced Option")] [Tooltip("The area for effect.")] [SerializeField]
  41. protected EffectArea m_EffectArea;
  42. [Tooltip("Keep effect aspect ratio.")] [SerializeField]
  43. bool m_KeepAspectRatio;
  44. [Header("Effect Player")] [SerializeField]
  45. EffectPlayer m_Player;
  46. [Tooltip("Reverse the dissolve effect.")] [FormerlySerializedAs("m_ReverseAnimation")] [SerializeField]
  47. bool m_Reverse = false;
  48. /// <summary>
  49. /// Effect factor between 0(start) and 1(end).
  50. /// </summary>
  51. public float effectFactor
  52. {
  53. get { return m_EffectFactor; }
  54. set
  55. {
  56. value = Mathf.Clamp(value, 0, 1);
  57. if (Mathf.Approximately(m_EffectFactor, value)) return;
  58. m_EffectFactor = value;
  59. SetEffectParamsDirty();
  60. }
  61. }
  62. /// <summary>
  63. /// Edge width.
  64. /// </summary>
  65. public float width
  66. {
  67. get { return m_Width; }
  68. set
  69. {
  70. value = Mathf.Clamp(value, 0, 1);
  71. if (Mathf.Approximately(m_Width, value)) return;
  72. m_Width = value;
  73. SetEffectParamsDirty();
  74. }
  75. }
  76. /// <summary>
  77. /// Edge softness.
  78. /// </summary>
  79. public float softness
  80. {
  81. get { return m_Softness; }
  82. set
  83. {
  84. value = Mathf.Clamp(value, 0, 1);
  85. if (Mathf.Approximately(m_Softness, value)) return;
  86. m_Softness = value;
  87. SetEffectParamsDirty();
  88. }
  89. }
  90. /// <summary>
  91. /// Edge color.
  92. /// </summary>
  93. public Color color
  94. {
  95. get { return m_Color; }
  96. set
  97. {
  98. if (m_Color == value) return;
  99. m_Color = value;
  100. SetEffectParamsDirty();
  101. }
  102. }
  103. /// <summary>
  104. /// Noise texture.
  105. /// </summary>
  106. public Texture transitionTexture
  107. {
  108. get
  109. {
  110. return m_TransitionTexture
  111. ? m_TransitionTexture
  112. : defaultTransitionTexture;
  113. }
  114. set
  115. {
  116. if (m_TransitionTexture == value) return;
  117. m_TransitionTexture = value;
  118. SetMaterialDirty();
  119. }
  120. }
  121. private static Texture defaultTransitionTexture
  122. {
  123. get
  124. {
  125. return _defaultTransitionTexture
  126. ? _defaultTransitionTexture
  127. : (_defaultTransitionTexture = Resources.Load<Texture>("Default-Transition"));
  128. }
  129. }
  130. /// <summary>
  131. /// The area for effect.
  132. /// </summary>
  133. public EffectArea effectArea
  134. {
  135. get { return m_EffectArea; }
  136. set
  137. {
  138. if (m_EffectArea == value) return;
  139. m_EffectArea = value;
  140. SetVerticesDirty();
  141. }
  142. }
  143. /// <summary>
  144. /// Keep aspect ratio.
  145. /// </summary>
  146. public bool keepAspectRatio
  147. {
  148. get { return m_KeepAspectRatio; }
  149. set
  150. {
  151. if (m_KeepAspectRatio == value) return;
  152. m_KeepAspectRatio = value;
  153. SetVerticesDirty();
  154. }
  155. }
  156. /// <summary>
  157. /// Color effect mode.
  158. /// </summary>
  159. public ColorMode colorMode
  160. {
  161. get { return m_ColorMode; }
  162. set
  163. {
  164. if (m_ColorMode == value) return;
  165. m_ColorMode = value;
  166. SetMaterialDirty();
  167. }
  168. }
  169. /// <summary>
  170. /// Gets the parameter texture.
  171. /// </summary>
  172. public override ParameterTexture paramTex
  173. {
  174. get { return s_ParamTex; }
  175. }
  176. public EffectPlayer effectPlayer
  177. {
  178. get { return m_Player ?? (m_Player = new EffectPlayer()); }
  179. }
  180. public override Hash128 GetMaterialHash(Material material)
  181. {
  182. if (!isActiveAndEnabled || !material || !material.shader)
  183. return k_InvalidHash;
  184. var shaderVariantId = (uint) ((int) m_ColorMode << 6);
  185. var resourceId = (uint) transitionTexture.GetInstanceID();
  186. return new Hash128(
  187. (uint) material.GetInstanceID(),
  188. k_ShaderId + shaderVariantId,
  189. resourceId,
  190. 0
  191. );
  192. }
  193. public override void ModifyMaterial(Material newMaterial, Graphic graphic)
  194. {
  195. var connector = GraphicConnector.FindConnector(graphic);
  196. newMaterial.shader = Shader.Find(string.Format("Hidden/{0} (UIDissolve)", newMaterial.shader.name));
  197. SetShaderVariants(newMaterial, m_ColorMode);
  198. newMaterial.SetTexture(k_TransitionTexId, transitionTexture);
  199. paramTex.RegisterMaterial(newMaterial);
  200. }
  201. /// <summary>
  202. /// Modifies the mesh.
  203. /// </summary>
  204. public override void ModifyMesh(VertexHelper vh, Graphic graphic)
  205. {
  206. if (!isActiveAndEnabled)
  207. return;
  208. // bool isText = isTMPro || graphic is Text;
  209. var normalizedIndex = paramTex.GetNormalizedIndex(this);
  210. // rect.
  211. var tex = transitionTexture;
  212. var aspectRatio = m_KeepAspectRatio && tex ? ((float) tex.width) / tex.height : -1;
  213. var rect = m_EffectArea.GetEffectArea(vh, rectTransform.rect, aspectRatio);
  214. // Calculate vertex position.
  215. var vertex = default(UIVertex);
  216. var count = vh.currentVertCount;
  217. for (var i = 0; i < count; i++)
  218. {
  219. vh.PopulateUIVertex(ref vertex, i);
  220. float x;
  221. float y;
  222. connector.GetPositionFactor(m_EffectArea, i, rect, vertex.position, out x, out y);
  223. vertex.uv0 = new Vector2(
  224. Packer.ToFloat(vertex.uv0.x, vertex.uv0.y),
  225. Packer.ToFloat(x, y, normalizedIndex)
  226. );
  227. vh.SetUIVertex(vertex, i);
  228. }
  229. }
  230. protected override void SetEffectParamsDirty()
  231. {
  232. paramTex.SetData(this, 0, m_EffectFactor); // param1.x : location
  233. paramTex.SetData(this, 1, m_Width); // param1.y : width
  234. paramTex.SetData(this, 2, m_Softness); // param1.z : softness
  235. paramTex.SetData(this, 4, m_Color.r); // param2.x : red
  236. paramTex.SetData(this, 5, m_Color.g); // param2.y : green
  237. paramTex.SetData(this, 6, m_Color.b); // param2.z : blue
  238. }
  239. protected override void SetVerticesDirty()
  240. {
  241. base.SetVerticesDirty();
  242. _lastKeepAspectRatio = m_KeepAspectRatio;
  243. _lastEffectArea = m_EffectArea;
  244. }
  245. protected override void OnDidApplyAnimationProperties()
  246. {
  247. base.OnDidApplyAnimationProperties();
  248. if (_lastKeepAspectRatio != m_KeepAspectRatio
  249. || _lastEffectArea != m_EffectArea)
  250. SetVerticesDirty();
  251. }
  252. /// <summary>
  253. /// Play effect.
  254. /// </summary>
  255. public void Play(bool reset = true)
  256. {
  257. effectPlayer.Play(reset);
  258. }
  259. /// <summary>
  260. /// Stop effect.
  261. /// </summary>
  262. public void Stop(bool reset = true)
  263. {
  264. effectPlayer.Stop(reset);
  265. }
  266. protected override void OnEnable()
  267. {
  268. base.OnEnable();
  269. effectPlayer.OnEnable((f) => effectFactor = m_Reverse ? 1f - f : f);
  270. }
  271. protected override void OnDisable()
  272. {
  273. base.OnDisable();
  274. effectPlayer.OnDisable();
  275. }
  276. }
  277. }