TypingFadeEffect.cs 7.7 KB

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