using UnityEngine; using System.Collections; using System.Collections.Generic; namespace Fungus { public class Glyph { public float hideTimer; public string character; public bool boldActive; public bool italicActive; public bool colorActive; public string colorText; public bool hasPunctuationPause; } public class DialogText { protected List glyphs = new List(); public bool boldActive { get; set; } public bool italicActive { get; set; } public bool colorActive { get; set; } public string colorText { get; set; } public float writingSpeed { get; set; } public float punctuationPause { get; set; } public AudioSource typingAudio { get; set; } public virtual void Clear() { glyphs.Clear(); } public virtual void Append(string words) { if (typingAudio != null) { typingAudio.Stop(); typingAudio.Play(); } float hideTimer = 0f; if (writingSpeed > 0f) { hideTimer = 1f / writingSpeed; } bool doPunctuationPause = false; for (int i = 0; i < words.Length; ++i) { char c = words[i]; // Ignore leading newlines if (glyphs.Count == 0 && c == '\n') { continue; } Glyph glyph = new Glyph(); glyph.hideTimer = hideTimer; if (doPunctuationPause) { glyph.hasPunctuationPause = true; glyph.hideTimer += punctuationPause; doPunctuationPause = false; } glyph.character = c.ToString(); glyph.boldActive = boldActive; glyph.italicActive = italicActive; glyph.colorActive = colorActive; glyph.colorText = colorText; glyphs.Add(glyph); if (i < words.Length - 1 && IsPunctuation(c)) // No punctuation pause on last character, or if next character is also punctuation { doPunctuationPause = true; } // Special case: pause just before open parentheses if (i < words.Length - 2) { if (words[i + 1] == '(') { doPunctuationPause = true; } } } } protected virtual bool IsPunctuation(char character) { return character == '.' || character == '?' || character == '!' || character == ',' || character == ':' || character == ';' || character == ')'; } /** * Returns true when all glyphs are visible. */ public virtual bool UpdateGlyphs(bool instantComplete) { float elapsedTime = Time.deltaTime; foreach (Glyph glyph in glyphs) { if (instantComplete) { glyph.hideTimer = 0f; continue; } if (glyph.hideTimer > 0f) { if (typingAudio != null && glyph.hasPunctuationPause) { typingAudio.volume = 0f; } bool finished = false; if (elapsedTime > glyph.hideTimer) { elapsedTime -= glyph.hideTimer; glyph.hideTimer = 0f; // Some elapsed time left over, so carry on to next glyph } else { glyph.hideTimer -= elapsedTime; glyph.hideTimer = Mathf.Max(glyph.hideTimer, 0f); finished = true; } // Check if we need to restore audio after a punctuation pause if (typingAudio != null && glyph.hideTimer == 0f && typingAudio.volume == 0f) { typingAudio.volume = 1f; } if (finished) { return false; // Glyph is still hidden } } } if (typingAudio != null) { typingAudio.Stop(); } return true; } public virtual string GetDialogText() { string outputText = ""; bool hideGlyphs = false; foreach (Glyph glyph in glyphs) { // Wrap each individual character in rich text markup tags (if required) string start = ""; string end = ""; if (glyph.boldActive) { start += ""; end += ""; } if (glyph.italicActive) { start += ""; end = "" + end; // Have to nest tags correctly } if (!hideGlyphs && glyph.hideTimer > 0f) { hideGlyphs = true; outputText += ""; } if (!hideGlyphs && glyph.colorActive) { start += ""; end += ""; } outputText += start + glyph.character + end; } if (hideGlyphs) { outputText += ""; } return outputText; } } }