diff --git a/Assets/Scripts/Messaging/Message.cs b/Assets/Scripts/Messaging/Message.cs index 9752e58..3c85a43 100644 --- a/Assets/Scripts/Messaging/Message.cs +++ b/Assets/Scripts/Messaging/Message.cs @@ -1,20 +1,33 @@ using System; using TMPro; using UnityEngine; +using Utilities; namespace Messaging { - public class Message : MonoBehaviour{ + public class Message : MonoBehaviour { public RectTransform RectTransform { private set; get; } public string Text => messageText.text; [SerializeField] private TMP_Text messageText; + private TextTyper _textTyper; + private Coroutine _typingCoroutine; + private void Awake() { RectTransform = GetComponent(); + _textTyper = new TextTyper(messageText); } - public void SetMessageText(string text) { - messageText.text = text; + public void SetMessageText(string text, bool animate) { + if (_textTyper.IsMessageAnimating()) { + _textTyper.SkipToEndOfCurrentMessage(); + } + this.EnsureCoroutineStopped(ref _typingCoroutine); + + if (animate) + _typingCoroutine = StartCoroutine(_textTyper.AnimateTextIn(text, null)); + else + messageText.text = text; } } } \ No newline at end of file diff --git a/Assets/Scripts/Messaging/MessageManager.cs b/Assets/Scripts/Messaging/MessageManager.cs index c791868..f5eb7c2 100644 --- a/Assets/Scripts/Messaging/MessageManager.cs +++ b/Assets/Scripts/Messaging/MessageManager.cs @@ -1,3 +1,5 @@ +using System; +using System.Threading.Tasks; using UnityEngine; namespace Messaging { @@ -10,16 +12,34 @@ namespace Messaging { _messages = messageStructureGenerator.GenerateMessages(); } + private async void Start() { + await Task.Delay(2000); + CreateMessage("asl;dkrhjufioe qvnfioeqlcnnmcuq"); + await Task.Delay(2000); + CreateMessage("asl;dkrhjufioe qvnfioeqlcnnmcuq"); + await Task.Delay(2000); + CreateMessage("asl;dkrhjufioe qvnfioeqlcnnmcuq"); + await Task.Delay(2000); + CreateMessage("asl;dkrhjufioe qvnfioeqlcnnmcuq"); + await Task.Delay(2000); + CreateMessage("asl;dkrhjufioe qvnfioeqlcnnmcuq"); + } + public void CreateMessage(string message) { ModifyMessageText(message, _messages.Length - 1); } private void ModifyMessageText(string message, int index) { + ModifyPreviousMessageText(_messages[index].Text, index - 1); + _messages[index].SetMessageText(message, true); + } + + private void ModifyPreviousMessageText(string message, int index) { if(index < 0) return; - ModifyMessageText(_messages[index].Text, index - 1); + ModifyPreviousMessageText(_messages[index].Text, index - 1); - _messages[index].SetMessageText(message); + _messages[index].SetMessageText(message, false); } } } \ No newline at end of file diff --git a/Assets/Scripts/Messaging/TextTyper.cs b/Assets/Scripts/Messaging/TextTyper.cs index bd74167..9757761 100644 --- a/Assets/Scripts/Messaging/TextTyper.cs +++ b/Assets/Scripts/Messaging/TextTyper.cs @@ -9,6 +9,9 @@ namespace Messaging { private bool _stopAnimating; private readonly TMP_Text _textBox; + + static readonly Color32 Clear = new(0, 0, 0, 0); + private const float SecondsPerCharacter = 1f / 60f; public TextTyper(TMP_Text textBox) { _textBox = textBox; @@ -16,7 +19,7 @@ namespace Messaging { public IEnumerator AnimateTextIn(string processedMessage, Action onFinish) { _textAnimating = true; - float secondsPerCharacter = 1f / 150f; + _stopAnimating = false; float timeOfLastCharacter = 0; TMP_TextInfo textInfo = _textBox.textInfo; @@ -50,10 +53,10 @@ namespace Messaging { visibleCharacterIndex = charCount; FinishAnimating(onFinish); } - if (ShouldShowNextCharacter(secondsPerCharacter, timeOfLastCharacter)) { + if (ShouldShowNextCharacter(SecondsPerCharacter, timeOfLastCharacter)) { if (visibleCharacterIndex <= charCount) { if (visibleCharacterIndex < charCount && - ShouldShowNextCharacter(secondsPerCharacter, timeOfLastCharacter)) { + ShouldShowNextCharacter(SecondsPerCharacter, timeOfLastCharacter)) { charAnimStartTimes[visibleCharacterIndex] = Time.unscaledTime; visibleCharacterIndex++; timeOfLastCharacter = Time.unscaledTime; @@ -64,6 +67,20 @@ namespace Messaging { } } + for (int j = 0; j < charCount; j++) { + TMP_CharacterInfo charInfo = textInfo.characterInfo[j]; + if (!charInfo.isVisible) continue; + + int vertexIndex = charInfo.vertexIndex; + int materialIndex = charInfo.materialReferenceIndex; + Color32[] destinationColors = textInfo.meshInfo[materialIndex].colors32; + Color32 theColor = j < visibleCharacterIndex ? originalColors[materialIndex][vertexIndex] : Clear; + destinationColors[vertexIndex + 0] = theColor; + destinationColors[vertexIndex + 1] = theColor; + destinationColors[vertexIndex + 2] = theColor; + destinationColors[vertexIndex + 3] = theColor; + } + _textBox.UpdateVertexData(TMP_VertexDataUpdateFlags.Colors32); for (int i = 0; i < textInfo.meshInfo.Length; i++) { TMP_MeshInfo theInfo = textInfo.meshInfo[i]; diff --git a/Assets/Scripts/Utilities.meta b/Assets/Scripts/Utilities.meta new file mode 100644 index 0000000..909e798 --- /dev/null +++ b/Assets/Scripts/Utilities.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 1edc85165243485db8a6f414074b8f6c +timeCreated: 1706301321 \ No newline at end of file diff --git a/Assets/Scripts/Utilities/MonoBehaviourExtensions.cs b/Assets/Scripts/Utilities/MonoBehaviourExtensions.cs new file mode 100644 index 0000000..037e282 --- /dev/null +++ b/Assets/Scripts/Utilities/MonoBehaviourExtensions.cs @@ -0,0 +1,11 @@ +using UnityEngine; + +namespace Utilities { + public static class MonoBehaviourExtensions { + public static void EnsureCoroutineStopped(this MonoBehaviour value, ref Coroutine routine) { + if (routine == null) return; + value.StopCoroutine(routine); + routine = null; + } + } +} \ No newline at end of file diff --git a/Assets/Scripts/Utilities/MonoBehaviourExtensions.cs.meta b/Assets/Scripts/Utilities/MonoBehaviourExtensions.cs.meta new file mode 100644 index 0000000..5f7ae3e --- /dev/null +++ b/Assets/Scripts/Utilities/MonoBehaviourExtensions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6950117e9f384976acc9489f6f1ae482 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: