UITransitionEffect.cs 10 KB

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