TypingFadeEffectPro.cs 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using FairyGUI;
  5. using System;
  6. using System.Threading.Tasks;
  7. namespace GFGGame
  8. {
  9. /// <summary>
  10. /// 使用异步函数实现多个字同时渐变
  11. /// </summary>
  12. public class TypingFadeEffectPro: TypingEffect
  13. {
  14. protected Color32[] _backupColor32s;
  15. protected Color32[] _color32s;
  16. public Action typeFinishedAction;
  17. // 出现下一个字符的间隔
  18. public float showNextWordInternal = 0.06f;
  19. // 字符渐变时间
  20. protected float charFadeDuration = 0.08f;
  21. /// <summary>
  22. ///
  23. /// </summary>
  24. /// <param name="textField"></param>
  25. public TypingFadeEffectPro(TextField textField) : base(textField) { }
  26. /// <summary>
  27. ///
  28. /// </summary>
  29. /// <param name="textField"></param>
  30. public TypingFadeEffectPro(GTextField textField) : base(textField) { }
  31. /// <summary>
  32. /// 开始打字效果。可以重复调用重复启动。
  33. /// </summary>
  34. public new void Start()
  35. {
  36. _textField.graphics.meshModifier -= OnMeshModified;
  37. _textField.Redraw();
  38. _textField.graphics.meshModifier += OnMeshModified;
  39. _stroke = false;
  40. _shadow = false;
  41. _strokeDrawDirs = 4;
  42. _mainLayerStart = 0;
  43. _mainLayerVertCount = 0;
  44. _printIndex = 0;
  45. _vertIndex = 0;
  46. _started = true;
  47. int vertCount = _textField.graphics.mesh.vertexCount;
  48. UpdateBackUp();
  49. // Clear mesh info
  50. if (_vertices == null || _vertices.Length != vertCount)
  51. _vertices = new Vector3[vertCount];
  52. if (_color32s == null || _color32s.Length != vertCount)
  53. {
  54. _color32s = new Color32[vertCount];
  55. }
  56. Vector3 zero = Vector3.zero;
  57. for (int i = 0; i < vertCount; i++)
  58. _vertices[i] = zero;
  59. _textField.graphics.mesh.vertices = _vertices;
  60. //隐藏所有混排的对象
  61. if (_textField.richTextField != null)
  62. {
  63. int ec = _textField.richTextField.htmlElementCount;
  64. for (int i = 0; i < ec; i++)
  65. _textField.richTextField.ShowHtmlObject(i, false);
  66. }
  67. int charCount = _textField.charPositions.Count;
  68. for (int i = 0; i < charCount; i++)
  69. {
  70. TextField.CharPosition cp = _textField.charPositions[i];
  71. _mainLayerVertCount += cp.vertCount;
  72. }
  73. if (_mainLayerVertCount < vertCount) //说明有描边或者阴影
  74. {
  75. int repeat = vertCount / _mainLayerVertCount;
  76. _stroke = repeat > 2;
  77. _shadow = repeat % 2 == 0;
  78. _mainLayerStart = vertCount - vertCount / repeat;
  79. _strokeLayerStart = _shadow ? (vertCount / repeat) : 0;
  80. _strokeDrawDirs = repeat > 8 ? 8 : 4;
  81. }
  82. Timers.inst.StartCoroutine(UpdateFadeProgress());
  83. }
  84. public void PrintFade(int printIndex, byte alpha, int vertIndex)
  85. {
  86. TextField.CharPosition cp;
  87. List<TextField.CharPosition> charPositions = _textField.charPositions;
  88. int listCnt = charPositions.Count;
  89. cp = charPositions[printIndex];
  90. if (cp.vertCount > 0)
  91. output(cp.vertCount, alpha, vertIndex);
  92. if (cp.imgIndex > 0) //这是一个图片
  93. {
  94. _textField.richTextField.ShowHtmlObject(cp.imgIndex - 1, true);
  95. return;
  96. }
  97. else if (!char.IsWhiteSpace(_textField.parsedText[Mathf.Max(printIndex - 1, 0)]))
  98. return;
  99. }
  100. private void output(int vertCount, byte alpha, int vertIndex)
  101. {
  102. int start, end;
  103. start = _mainLayerStart + vertIndex;
  104. end = start + vertCount;
  105. //Vector3[] vertices = new Vector3[end - start];
  106. for (int i = start; i < end; i++)
  107. {
  108. _vertices[i] = _backupVerts[i];
  109. _color32s[i] = _backupColor32s[i];
  110. _color32s[i].a = alpha;
  111. }
  112. if (_stroke)
  113. {
  114. start = _strokeLayerStart + vertIndex;
  115. end = start + vertCount;
  116. for (int i = start; i < end; i++)
  117. {
  118. for (int j = 0; j < _strokeDrawDirs; j++)
  119. {
  120. int k = i + _mainLayerVertCount * j;
  121. _vertices[k] = _backupVerts[k];
  122. }
  123. }
  124. }
  125. if (_shadow)
  126. {
  127. start = vertIndex;
  128. end = start + vertCount;
  129. for (int i = start; i < end; i++)
  130. {
  131. _vertices[i] = _backupVerts[i];
  132. }
  133. }
  134. _textField.graphics.mesh.vertices = _vertices;
  135. _textField.graphics.mesh.colors32 = _color32s;
  136. }
  137. public new void Cancel()
  138. {
  139. if (!_started)
  140. return;
  141. _started = false;
  142. _textField.graphics.meshModifier -= OnMeshModified;
  143. _textField.graphics.SetMeshDirty();
  144. }
  145. /// <summary>
  146. /// 当打字过程中,文本可能会由于字体纹理更改而发生字体重建,要处理这种情况。
  147. /// 图片对象不需要处理,因为HtmlElement.status里设定的隐藏标志不会因为Mesh更新而被冲掉。
  148. /// </summary>
  149. void OnMeshModified()
  150. {
  151. if (_textField.graphics.mesh.vertexCount != _backupVerts.Length) //可能文字都改了
  152. {
  153. Cancel();
  154. return;
  155. }
  156. UpdateBackUp();
  157. int vertCount = _vertices.Length;
  158. Vector3 zero = Vector3.zero;
  159. for (int i = 0; i < vertCount; i++)
  160. {
  161. if (_vertices[i] != zero)
  162. _vertices[i] = _backupVerts[i];
  163. }
  164. _textField.graphics.mesh.vertices = _vertices;
  165. }
  166. IEnumerator UpdateFadeProgress()
  167. {
  168. List<TextField.CharPosition> charPositions = _textField.charPositions;
  169. int listCnt = charPositions.Count;
  170. float timer = 0;
  171. while (true)
  172. {
  173. if (!_started)
  174. break;
  175. if(timer>= showNextWordInternal)
  176. {
  177. timer = 0;
  178. if (_printIndex >= listCnt - 1)
  179. {
  180. Cancel();
  181. typeFinishedAction.Invoke();
  182. break;
  183. }
  184. else
  185. {
  186. UpdateFadeProgressSingle(_printIndex, _vertIndex);
  187. ++_printIndex;
  188. if(_printIndex < listCnt - 1)
  189. {
  190. _vertIndex += charPositions[_printIndex].vertCount;
  191. }
  192. }
  193. }
  194. timer += Time.deltaTime;
  195. yield return new WaitForEndOfFrame();
  196. }
  197. }
  198. async Task UpdateFadeProgressSingle(int printIndex, int vertIndex)
  199. {
  200. float _currentCharFadeTime = 0;
  201. while (true)
  202. {
  203. if (!_started)
  204. break;
  205. _currentCharFadeTime += 0.016f;
  206. float progress = _currentCharFadeTime / charFadeDuration;
  207. if (progress >= 1)
  208. {
  209. PrintFade(printIndex, 255, vertIndex);
  210. break;
  211. }
  212. else
  213. {
  214. byte alpha = (byte)(progress * 255);
  215. PrintFade(printIndex, alpha, vertIndex);
  216. }
  217. await Task.Delay(16);
  218. }
  219. }
  220. // Back up origin text info
  221. protected void UpdateBackUp()
  222. {
  223. _backupVerts = _textField.graphics.mesh.vertices;
  224. _backupColor32s = _textField.graphics.mesh.colors32;
  225. }
  226. public void SetSpeed(float speed)
  227. {
  228. charFadeDuration /= speed;
  229. showNextWordInternal /= speed;
  230. }
  231. }
  232. }