| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299 | using System.Collections;using System.Collections.Generic;using UnityEngine;using FairyGUI;using System;using System.Threading.Tasks;using System.Threading;namespace GFGGame{    /// <summary>    /// 使用异步函数实现多个字同时渐变    /// </summary>    public class TypingFadeEffectPro: TypingEffect    {        protected Color32[] _backupColor32s;        protected Color32[] _color32s;        public Action typeFinishedAction;        // 出现下一个字符的间隔        protected float showNextWordInternal = 0.06f;        // 字符渐变时间        protected float charFadeDuration = 0.15f;        // 异步函数的取消控制        private CancellationTokenSource _cancellationTokenSource;        /// <summary>        ///         /// </summary>        /// <param name="textField"></param>        public TypingFadeEffectPro(TextField textField) : base(textField) { }        /// <summary>        ///         /// </summary>        /// <param name="textField"></param>        public TypingFadeEffectPro(GTextField textField) : base(textField) { }        /// <summary>        /// 开始打字效果。可以重复调用重复启动。        /// </summary>        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;            _cancellationTokenSource = new CancellationTokenSource();            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<TextField.CharPosition> 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;            StopMyAsyncFunction();            _started = false;            _textField.graphics.meshModifier -= OnMeshModified;            _textField.graphics.SetMeshDirty();        }        /// <summary>        /// 当打字过程中,文本可能会由于字体纹理更改而发生字体重建,要处理这种情况。        /// 图片对象不需要处理,因为HtmlElement.status里设定的隐藏标志不会因为Mesh更新而被冲掉。        /// </summary>        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<TextField.CharPosition> charPositions = _textField.charPositions;            int listCnt = charPositions.Count;            float timer = 0;            //for(int i=0;i<= listCnt - 1; i++)            //{            //    PrintFade(i, 0, _vertIndex);            //    _vertIndex += charPositions[_printIndex].vertCount;            //}            //_vertIndex = 0;            while (true)            {                if (!_started)                    break;                if(timer>= showNextWordInternal)                {                    timer = 0;                    if (_printIndex >= listCnt - 1)                    {                        Cancel();                        typeFinishedAction.Invoke();                        break;                    }                    else                    {                        UpdateFadeProgressSingle(_printIndex, _vertIndex, _cancellationTokenSource.Token);                        ++_printIndex;                        if(_printIndex < listCnt - 1 && _printIndex < charPositions.Count)                        {                            _vertIndex += charPositions[_printIndex].vertCount;                        }                    }                }                timer += Time.deltaTime;                yield return new WaitForEndOfFrame();            }        }        async Task UpdateFadeProgressSingle(int printIndex, int vertIndex, CancellationToken cancellationToken)        {            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, cancellationToken);            }        }        // 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;            charFadeDuration = showNextWordInternal + 0.05f;        }        // 取消异步函数        public void StopMyAsyncFunction()        {            if (_cancellationTokenSource != null)            {                _cancellationTokenSource.Cancel();                _cancellationTokenSource.Dispose();                _cancellationTokenSource = null;            }        }    }}
 |