Browse Source

添加剧情对话渐变

leiyasi 1 year ago
parent
commit
29751c610e

+ 3 - 1
GameClient/Assets/Game/HotUpdate/Data/StoryDialogDataManager.cs

@@ -14,11 +14,13 @@ namespace GFGGame
 
 
         private bool _waitPicFade = false;
         private bool _waitPicFade = false;
         private bool _waitBgChange = false;
         private bool _waitBgChange = false;
-
+        private float _dialogShowDelay = 0.0f;
 
 
         // Dialog wait pic's animation finished 
         // Dialog wait pic's animation finished 
         public bool waitPicFade { get { return _waitPicFade; } set { _waitPicFade = value; } }
         public bool waitPicFade { get { return _waitPicFade; } set { _waitPicFade = value; } }
         public bool waitBgChange { get { return _waitBgChange; } set { _waitBgChange = value; } }
         public bool waitBgChange { get { return _waitBgChange; } set { _waitBgChange = value; } }
+        public float dialogShowDelay { get { return _dialogShowDelay; } set { _dialogShowDelay = value; } }
+
     }
     }
 }
 }
 
 

+ 2 - 0
GameClient/Assets/Game/HotUpdate/DressUp/SceneController.cs

@@ -65,6 +65,7 @@ namespace GFGGame
                 else
                 else
                 {
                 {
                     StoryDialogDataManager.Instance.waitBgChange = true;
                     StoryDialogDataManager.Instance.waitBgChange = true;
+                    StoryDialogDataManager.Instance.dialogShowDelay = 0.4f;
                     SetSpriteRendererAlpha(bgSpr, 1f);
                     SetSpriteRendererAlpha(bgSpr, 1f);
                     bgNextSpr.sprite = sp;
                     bgNextSpr.sprite = sp;
                     FairyGUI.Timers.inst.StartCoroutine(LastBgFadeOut());
                     FairyGUI.Timers.inst.StartCoroutine(LastBgFadeOut());
@@ -141,6 +142,7 @@ namespace GFGGame
                         }
                         }
                         yield return new WaitForEndOfFrame();
                         yield return new WaitForEndOfFrame();
                     }
                     }
+                    StoryDialogDataManager.Instance.waitPicFade = false;
                 }
                 }
             }
             }
         }
         }

+ 30 - 24
GameClient/Assets/Game/HotUpdate/Views/MainStory/StoryDialogView.cs

@@ -37,6 +37,8 @@ namespace GFGGame
         private string _currentWords;
         private string _currentWords;
         private string _storyStartID;
         private string _storyStartID;
         private string lastTextFieldType;   // 上一段文本框的类型
         private string lastTextFieldType;   // 上一段文本框的类型
+        TypingFadeEffect _typingEffect;
+
 
 
         //屏幕效果中
         //屏幕效果中
         private Action<object> _onScreenEffectComplete;
         private Action<object> _onScreenEffectComplete;
@@ -61,7 +63,7 @@ namespace GFGGame
             EffectUIPool.Recycle(_effectUI1);
             EffectUIPool.Recycle(_effectUI1);
             _effectUI1 = null;
             _effectUI1 = null;
             _onScreenEffectComplete = null;
             _onScreenEffectComplete = null;
-            Timers.inst.Remove(UpdateLetters);
+            _typingEffect = null;
             if (_ui != null)
             if (_ui != null)
             {
             {
                 _ui.Dispose();
                 _ui.Dispose();
@@ -155,7 +157,6 @@ namespace GFGGame
         protected override void OnHide()
         protected override void OnHide()
         {
         {
             base.OnHide();
             base.OnHide();
-            Timers.inst.Remove(UpdateLetters);
             Timers.inst.Remove(UpdateShake);
             Timers.inst.Remove(UpdateShake);
             Timers.inst.Remove(OnScreenEffectComplete);
             Timers.inst.Remove(OnScreenEffectComplete);
             Timers.inst.Remove(ShowNextWords);
             Timers.inst.Remove(ShowNextWords);
@@ -305,6 +306,7 @@ namespace GFGGame
                 delay = delay / 1000f;
                 delay = delay / 1000f;
                 _onScreenEffectComplete = OnScreenEffectComplete;
                 _onScreenEffectComplete = OnScreenEffectComplete;
                 Timers.inst.Add(delay, 1, OnScreenEffectComplete);
                 Timers.inst.Add(delay, 1, OnScreenEffectComplete);
+                StoryDialogDataManager.Instance.dialogShowDelay = 0.6f;
             }
             }
             else
             else
             {
             {
@@ -341,14 +343,15 @@ namespace GFGGame
             string content = storyDialogCfg.content;
             string content = storyDialogCfg.content;
             content = storyDialogCfg.content.Replace("self", RoleDataManager.roleName);
             content = storyDialogCfg.content.Replace("self", RoleDataManager.roleName);
 
 
-            bool delay = StoryDialogDataManager.Instance.waitBgChange;
             while (StoryDialogDataManager.Instance.waitBgChange)
             while (StoryDialogDataManager.Instance.waitBgChange)
             {
             {
                 yield return new WaitForEndOfFrame();
                 yield return new WaitForEndOfFrame();
             }
             }
-            if (delay)
+
+            if(StoryDialogDataManager.Instance.dialogShowDelay > 0)
             {
             {
-                yield return new WaitForSeconds(0.4f);
+                yield return new WaitForSeconds(StoryDialogDataManager.Instance.dialogShowDelay);
+                StoryDialogDataManager.Instance.dialogShowDelay = 0f;
             }
             }
 
 
             _canClickBtnNext = true;
             _canClickBtnNext = true;
@@ -500,6 +503,8 @@ namespace GFGGame
             }
             }
             _wordList = Regex.Split(words, "&&");
             _wordList = Regex.Split(words, "&&");
             _wordIndex = 0;
             _wordIndex = 0;
+            _typingEffect = new TypingFadeEffect(_wordTextField);
+            _typingEffect.typeFinishedAction = ShowCurrentWords;
 
 
             ShowNextDialog();
             ShowNextDialog();
         }
         }
@@ -532,7 +537,9 @@ namespace GFGGame
         private void ShowCurrentWords()
         private void ShowCurrentWords()
         {
         {
             _arrow.target.visible = true;
             _arrow.target.visible = true;
-            Timers.inst.Remove(UpdateLetters);
+            //Timers.inst.Remove(UpdateLetters);
+            StopTyping();
+            _typingEffect?.Cancel();
             _wordTextField.text = _currentWords;
             _wordTextField.text = _currentWords;
             _dialogListLookBack.Add(_currentWords);
             _dialogListLookBack.Add(_currentWords);
             _isShowLetters = false;
             _isShowLetters = false;
@@ -573,33 +580,30 @@ namespace GFGGame
             _wordTextField.verticalAlign = VertAlignType.Top;
             _wordTextField.verticalAlign = VertAlignType.Top;
             _wordTextField.text = "";
             _wordTextField.text = "";
             ArrayList letters = StoryUtil.GetLettersList(_currentWords);
             ArrayList letters = StoryUtil.GetLettersList(_currentWords);
+            _canClickBtnNext = false;
 
 
-            if (StoryDialogDataManager.Instance.waitPicFade)
+            while (StoryDialogDataManager.Instance.waitPicFade)
             {
             {
-                StoryDialogDataManager.Instance.waitPicFade = false;
-                _canClickBtnNext = false;
-                yield return new WaitForSeconds(0.4f);
-                _canClickBtnNext = true;
+                yield return new WaitForEndOfFrame();
             }
             }
 
 
-            Timers.inst.Add(GameConst.LETTERS_INTERVAL_MAX / _speedAutoPlay, 0, UpdateLetters, letters);
+            _canClickBtnNext = true;
+            _wordTextField.text = _currentWords;
+            StartTyping();
         }
         }
 
 
-        private void UpdateLetters(object param)
+        private void StartTyping()
         {
         {
-            ArrayList letters = (ArrayList)param;
-            if (letters == null || letters.Count <= 0)
-            {
-                ShowCurrentWords();
-            }
-            else
-            {
-                string letter = (string)letters[0];
-                letters.RemoveAt(0);
-                _wordTextField.text = _wordTextField.text + letter;
-            }
+            _typingEffect.SetSpeed(GameConst.LETTERS_INTERVAL_MAX / _speedAutoPlay);
+            _typingEffect.Start();
+        }
+
+        private void StopTyping()
+        {
+            _typingEffect.Cancel();
         }
         }
 
 
+
         private void UpdateBg(string value)
         private void UpdateBg(string value)
         {
         {
             if (value.Length > 0)
             if (value.Length > 0)
@@ -712,6 +716,8 @@ namespace GFGGame
             {
             {
                 _ui.m_btnSpeedUp.text = "";
                 _ui.m_btnSpeedUp.text = "";
             }
             }
+
+            _typingEffect?.SetSpeed(GameConst.LETTERS_INTERVAL_MAX / _speedAutoPlay);
         }
         }
 
 
         private void StopAutoPlay()
         private void StopAutoPlay()

+ 260 - 0
GameClient/Assets/Game/HotUpdate/Views/MainStory/TypingFadeEffect.cs

@@ -0,0 +1,260 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using FairyGUI;
+using System;
+
+namespace GFGGame
+{
+    public class TypingFadeEffect : TypingEffect
+    {
+        protected Color32[] _backupColor32s;
+        protected Color32[] _color32s;
+        protected float charFadeDuration = 0.1f;
+
+
+        private float _currentCharFadeTime;
+
+        public Action typeFinishedAction;
+        public float progressShowNextWord = 0.8f;
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="textField"></param>
+        public TypingFadeEffect(TextField textField) : base(textField) { }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="textField"></param>
+        public TypingFadeEffect(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;
+            _currentCharFadeTime = 0.0f;
+            _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 bool PrintFade(byte alpha)
+        {
+            if (!_started)
+                return false;
+
+            TextField.CharPosition cp;
+            List<TextField.CharPosition> charPositions = _textField.charPositions;
+            int listCnt = charPositions.Count;
+
+            while (_printIndex < listCnt - 1) //最后一个是占位的,无效的,所以-1
+            {
+                cp = charPositions[_printIndex];
+                if (cp.vertCount > 0)
+                    output(cp.vertCount, alpha);
+                if (cp.imgIndex > 0) //这是一个图片
+                {
+                    _textField.richTextField.ShowHtmlObject(cp.imgIndex - 1, true);
+                    return true;
+                }
+                else if (!char.IsWhiteSpace(_textField.parsedText[Mathf.Max(_printIndex - 1, 0)]))
+                    return true;
+            }
+
+            Cancel();
+            typeFinishedAction.Invoke();
+            return false;
+        }
+
+
+        private void output(int vertCount, byte alpha)
+        {
+            int start, end;
+
+            start = _mainLayerStart + _vertIndex;
+            end = start + vertCount;
+            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;
+
+
+            if (alpha == 255)
+            {
+                _vertIndex += vertCount;
+            }
+        }
+
+
+        public new void Cancel()
+        {
+            if (!_started)
+                return;
+
+            _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()
+        {
+            while (true)
+            {
+                if (!_started)
+                    break;
+
+                _currentCharFadeTime += Time.deltaTime;
+                float progress = _currentCharFadeTime / charFadeDuration;
+                if(progress > progressShowNextWord)
+                {
+                    PrintFade(255);
+                    ++_printIndex;
+                    _currentCharFadeTime = 0.0f;
+
+                    int listCnt = _textField.charPositions.Count;
+                    if (_printIndex >= listCnt - 1)
+                    {
+                        typeFinishedAction.Invoke();
+                        break;
+                    }
+                }
+                else 
+                {
+                    byte alpha = (byte)(progress * 255);
+                    PrintFade(alpha);
+                }
+
+                yield return new WaitForEndOfFrame();
+            }
+        }
+
+        // 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;
+        }
+
+    }
+
+}
+
+

+ 11 - 0
GameClient/Assets/Game/HotUpdate/Views/MainStory/TypingFadeEffect.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: e86ab80b7f2d43a4787aeafa14ad0b71
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: