using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using FairyGUI;
using System;
using System.Threading.Tasks;
namespace GFGGame
{
///
/// 使用异步函数实现多个字同时渐变
///
public class TypingFadeEffectPro: TypingEffect
{
protected Color32[] _backupColor32s;
protected Color32[] _color32s;
public Action typeFinishedAction;
// 出现下一个字符的间隔
public float showNextWordInternal = 0.06f;
// 字符渐变时间
protected float charFadeDuration = 0.08f;
///
///
///
///
public TypingFadeEffectPro(TextField textField) : base(textField) { }
///
///
///
///
public TypingFadeEffectPro(GTextField textField) : base(textField) { }
///
/// 开始打字效果。可以重复调用重复启动。
///
public new void Start()
{
_textField.graphics.meshModifier -= OnMeshModified;
_textField.Redraw();
_textField.graphics.meshModifier += OnMeshModified;
_stroke = false;
_shadow = false;
_strokeDrawDirs = 4;
_mainLayerStart = 0;
_mainLayerVertCount = 0;
_printIndex = 0;
_vertIndex = 0;
_started = true;
int vertCount = _textField.graphics.mesh.vertexCount;
UpdateBackUp();
// Clear mesh info
if (_vertices == null || _vertices.Length != vertCount)
_vertices = new Vector3[vertCount];
if (_color32s == null || _color32s.Length != vertCount)
{
_color32s = new Color32[vertCount];
}
Vector3 zero = Vector3.zero;
for (int i = 0; i < vertCount; i++)
_vertices[i] = zero;
_textField.graphics.mesh.vertices = _vertices;
//隐藏所有混排的对象
if (_textField.richTextField != null)
{
int ec = _textField.richTextField.htmlElementCount;
for (int i = 0; i < ec; i++)
_textField.richTextField.ShowHtmlObject(i, false);
}
int charCount = _textField.charPositions.Count;
for (int i = 0; i < charCount; i++)
{
TextField.CharPosition cp = _textField.charPositions[i];
_mainLayerVertCount += cp.vertCount;
}
if (_mainLayerVertCount < vertCount) //说明有描边或者阴影
{
int repeat = vertCount / _mainLayerVertCount;
_stroke = repeat > 2;
_shadow = repeat % 2 == 0;
_mainLayerStart = vertCount - vertCount / repeat;
_strokeLayerStart = _shadow ? (vertCount / repeat) : 0;
_strokeDrawDirs = repeat > 8 ? 8 : 4;
}
Timers.inst.StartCoroutine(UpdateFadeProgress());
}
public void PrintFade(int printIndex, byte alpha, int vertIndex)
{
TextField.CharPosition cp;
List charPositions = _textField.charPositions;
int listCnt = charPositions.Count;
cp = charPositions[printIndex];
if (cp.vertCount > 0)
output(cp.vertCount, alpha, vertIndex);
if (cp.imgIndex > 0) //这是一个图片
{
_textField.richTextField.ShowHtmlObject(cp.imgIndex - 1, true);
return;
}
else if (!char.IsWhiteSpace(_textField.parsedText[Mathf.Max(printIndex - 1, 0)]))
return;
}
private void output(int vertCount, byte alpha, int vertIndex)
{
int start, end;
start = _mainLayerStart + vertIndex;
end = start + vertCount;
//Vector3[] vertices = new Vector3[end - start];
for (int i = start; i < end; i++)
{
_vertices[i] = _backupVerts[i];
_color32s[i] = _backupColor32s[i];
_color32s[i].a = alpha;
}
if (_stroke)
{
start = _strokeLayerStart + vertIndex;
end = start + vertCount;
for (int i = start; i < end; i++)
{
for (int j = 0; j < _strokeDrawDirs; j++)
{
int k = i + _mainLayerVertCount * j;
_vertices[k] = _backupVerts[k];
}
}
}
if (_shadow)
{
start = vertIndex;
end = start + vertCount;
for (int i = start; i < end; i++)
{
_vertices[i] = _backupVerts[i];
}
}
_textField.graphics.mesh.vertices = _vertices;
_textField.graphics.mesh.colors32 = _color32s;
}
public new void Cancel()
{
if (!_started)
return;
_started = false;
_textField.graphics.meshModifier -= OnMeshModified;
_textField.graphics.SetMeshDirty();
}
///
/// 当打字过程中,文本可能会由于字体纹理更改而发生字体重建,要处理这种情况。
/// 图片对象不需要处理,因为HtmlElement.status里设定的隐藏标志不会因为Mesh更新而被冲掉。
///
void OnMeshModified()
{
if (_textField.graphics.mesh.vertexCount != _backupVerts.Length) //可能文字都改了
{
Cancel();
return;
}
UpdateBackUp();
int vertCount = _vertices.Length;
Vector3 zero = Vector3.zero;
for (int i = 0; i < vertCount; i++)
{
if (_vertices[i] != zero)
_vertices[i] = _backupVerts[i];
}
_textField.graphics.mesh.vertices = _vertices;
}
IEnumerator UpdateFadeProgress()
{
List charPositions = _textField.charPositions;
int listCnt = charPositions.Count;
float timer = 0;
//for(int i = 0; i < listCnt - 1; i++)
//{
// PrintFade(i, 0, charPositions[i].vertCount);
// yield return new WaitForEndOfFrame();
//}
while (true)
{
if (!_started)
break;
if(timer>= showNextWordInternal)
{
timer = 0;
if (_printIndex >= listCnt - 1)
{
Cancel();
typeFinishedAction.Invoke();
break;
}
else
{
UpdateFadeProgressSingle(_printIndex, _vertIndex);
++_printIndex;
_vertIndex += charPositions[_printIndex].vertCount;
}
}
timer += Time.deltaTime;
yield return new WaitForEndOfFrame();
//yield return new WaitForSeconds(progressShowNextWord);
}
}
async Task UpdateFadeProgressSingle(int printIndex, int vertIndex)
{
float _currentCharFadeTime = 0;
while (true)
{
if (!_started)
break;
_currentCharFadeTime += 0.016f;
float progress = _currentCharFadeTime / charFadeDuration;
if (progress >= 1)
{
PrintFade(printIndex, 255, vertIndex);
break;
}
else
{
byte alpha = (byte)(progress * 255);
PrintFade(printIndex, alpha, vertIndex);
}
await Task.Delay(16);
}
}
// Back up origin text info
protected void UpdateBackUp()
{
_backupVerts = _textField.graphics.mesh.vertices;
_backupColor32s = _textField.graphics.mesh.colors32;
}
public void SetSpeed(float speed)
{
charFadeDuration /= speed;
showNextWordInternal /= speed;
}
}
}