protected virtual IEnumerator ProcessTokens(List <TextTagToken> tokens, bool stopAudio, Action onComplete) { // Reset control members boldActive = false; italicActive = false; colorActive = false; sizeActive = false; colorText = ""; sizeValue = 16f; currentPunctuationPause = punctuationPause; currentWritingSpeed = writingSpeed; exitFlag = false; isWriting = true; TokenType previousTokenType = TokenType.Invalid; foreach (TextTagToken token in tokens) { switch (token.type) { case TokenType.Words: yield return(StartCoroutine(DoWords(token.paramList, previousTokenType))); break; case TokenType.BoldStart: boldActive = true; break; case TokenType.BoldEnd: boldActive = false; break; case TokenType.ItalicStart: italicActive = true; break; case TokenType.ItalicEnd: italicActive = false; break; case TokenType.ColorStart: if (CheckParamCount(token.paramList, 1)) { colorActive = true; colorText = token.paramList[0]; } break; case TokenType.ColorEnd: colorActive = false; break; case TokenType.SizeStart: if (TryGetSingleParam(token.paramList, 0, 16f, out sizeValue)) { sizeActive = true; } break; case TokenType.SizeEnd: sizeActive = false; break; case TokenType.Wait: yield return(StartCoroutine(DoWait(token.paramList))); break; case TokenType.WaitForInputNoClear: yield return(StartCoroutine(DoWaitForInput(false))); break; case TokenType.WaitForInputAndClear: yield return(StartCoroutine(DoWaitForInput(true))); break; case TokenType.WaitOnPunctuationStart: TryGetSingleParam(token.paramList, 0, punctuationPause, out currentPunctuationPause); break; case TokenType.WaitOnPunctuationEnd: currentPunctuationPause = punctuationPause; break; case TokenType.Clear: text = ""; break; case TokenType.SpeedStart: TryGetSingleParam(token.paramList, 0, writingSpeed, out currentWritingSpeed); break; case TokenType.SpeedEnd: currentWritingSpeed = writingSpeed; break; case TokenType.Exit: exitFlag = true; break; case TokenType.Message: if (CheckParamCount(token.paramList, 1)) { Flowchart.BroadcastFungusMessage(token.paramList[0]); } break; case TokenType.VerticalPunch: { float vintensity; float time; TryGetSingleParam(token.paramList, 0, 10.0f, out vintensity); TryGetSingleParam(token.paramList, 1, 0.5f, out time); Punch(new Vector3(0, vintensity, 0), time); } break; case TokenType.HorizontalPunch: { float hintensity; float time; TryGetSingleParam(token.paramList, 0, 10.0f, out hintensity); TryGetSingleParam(token.paramList, 1, 0.5f, out time); Punch(new Vector3(hintensity, 0, 0), time); } break; case TokenType.Punch: { float intensity; float time; TryGetSingleParam(token.paramList, 0, 10.0f, out intensity); TryGetSingleParam(token.paramList, 1, 0.5f, out time); Punch(new Vector3(intensity, intensity, 0), time); } break; case TokenType.Flash: float flashDuration; TryGetSingleParam(token.paramList, 0, 0.2f, out flashDuration); Flash(flashDuration); break; case TokenType.Audio: { AudioSource audioSource = null; if (CheckParamCount(token.paramList, 1)) { audioSource = FindAudio(token.paramList[0]); } if (audioSource != null) { audioSource.PlayOneShot(audioSource.clip); } } break; case TokenType.AudioLoop: { AudioSource audioSource = null; if (CheckParamCount(token.paramList, 1)) { audioSource = FindAudio(token.paramList[0]); } if (audioSource != null) { audioSource.Play(); audioSource.loop = true; } } break; case TokenType.AudioPause: { AudioSource audioSource = null; if (CheckParamCount(token.paramList, 1)) { audioSource = FindAudio(token.paramList[0]); } if (audioSource != null) { audioSource.Pause(); } } break; case TokenType.AudioStop: { AudioSource audioSource = null; if (CheckParamCount(token.paramList, 1)) { audioSource = FindAudio(token.paramList[0]); } if (audioSource != null) { audioSource.Stop(); } } break; } previousTokenType = token.type; if (exitFlag) { break; } } inputFlag = false; exitFlag = false; isWaitingForInput = false; isWriting = false; NotifyEnd(stopAudio); if (onComplete != null) { onComplete(); } }
protected virtual IEnumerator ProcessTokens(List <TextTagToken> tokens, bool stopAudio, System.Action onComplete) { // Reset control members boldActive = false; italicActive = false; colorActive = false; sizeActive = false; WordTokensFound = tokens.Count(x => x.type == TokenType.Words); WordTokensProcessed = 0; colorText = ""; sizeValue = 16f; currentPunctuationPause = punctuationPause; currentWritingSpeed = writingSpeed; exitFlag = false; isWriting = true; TokenType previousTokenType = TokenType.Invalid; for (int i = 0; i < tokens.Count; ++i) { // Pause between tokens if Paused is set while (Paused) { yield return(null); } var token = tokens[i]; // Notify listeners about new token WriterSignals.DoTextTagToken(this, token, i, tokens.Count); // Update the read ahead string buffer. This contains the text for any // Word tags which are further ahead in the list. if (doReadAheadText && !textAdapter.SupportsHiddenCharacters()) { readAheadString.Length = 0; for (int j = i + 1; j < tokens.Count; ++j) { var readAheadToken = tokens[j]; if (readAheadToken.type == TokenType.Words && readAheadToken.paramList.Count == 1) { readAheadString.Append(readAheadToken.paramList[0]); } else if (readAheadToken.type == TokenType.WaitForInputAndClear) { break; } } } switch (token.type) { case TokenType.Words: yield return(StartCoroutine(DoWords(token.paramList, previousTokenType))); WordTokensProcessed++; break; case TokenType.BoldStart: boldActive = true; break; case TokenType.BoldEnd: boldActive = false; break; case TokenType.ItalicStart: italicActive = true; break; case TokenType.ItalicEnd: italicActive = false; break; case TokenType.ColorStart: if (CheckParamCount(token.paramList, 1)) { colorActive = true; colorText = token.paramList[0]; } break; case TokenType.ColorEnd: colorActive = false; break; case TokenType.LinkStart: if (CheckParamCount(token.paramList, 1)) { linkActive = true; linkText = token.paramList[0]; } break; case TokenType.LinkEnd: linkActive = false; break; case TokenType.SizeStart: if (TryGetSingleParam(token.paramList, 0, 16f, out sizeValue)) { sizeActive = true; } break; case TokenType.SizeEnd: sizeActive = false; break; case TokenType.Wait: yield return(StartCoroutine(DoWait(token.paramList))); break; case TokenType.WaitForInputNoClear: yield return(StartCoroutine(DoWaitForInput(false))); break; case TokenType.WaitForInputAndClear: yield return(StartCoroutine(DoWaitForInput(true))); break; case TokenType.WaitForVoiceOver: yield return(StartCoroutine(DoWaitVO())); break; case TokenType.WaitOnPunctuationStart: TryGetSingleParam(token.paramList, 0, punctuationPause, out currentPunctuationPause); break; case TokenType.WaitOnPunctuationEnd: currentPunctuationPause = punctuationPause; break; case TokenType.Clear: textAdapter.Text = ""; break; case TokenType.SpeedStart: TryGetSingleParam(token.paramList, 0, writingSpeed, out currentWritingSpeed); break; case TokenType.SpeedEnd: currentWritingSpeed = writingSpeed; break; case TokenType.Exit: exitFlag = true; break; case TokenType.Message: if (CheckParamCount(token.paramList, 1)) { Flowchart.BroadcastFungusMessage(token.paramList[0]); } break; case TokenType.VerticalPunch: { float vintensity; float time; TryGetSingleParam(token.paramList, 0, 10.0f, out vintensity); TryGetSingleParam(token.paramList, 1, 0.5f, out time); Punch(new Vector3(0, vintensity, 0), time); } break; case TokenType.HorizontalPunch: { float hintensity; float time; TryGetSingleParam(token.paramList, 0, 10.0f, out hintensity); TryGetSingleParam(token.paramList, 1, 0.5f, out time); Punch(new Vector3(hintensity, 0, 0), time); } break; case TokenType.Punch: { float intensity; float time; TryGetSingleParam(token.paramList, 0, 10.0f, out intensity); TryGetSingleParam(token.paramList, 1, 0.5f, out time); Punch(new Vector3(intensity, intensity, 0), time); } break; case TokenType.Flash: float flashDuration; TryGetSingleParam(token.paramList, 0, 0.2f, out flashDuration); Flash(flashDuration); break; case TokenType.Audio: { AudioSource audioSource = null; if (CheckParamCount(token.paramList, 1)) { audioSource = FindAudio(token.paramList[0]); } if (audioSource != null) { audioSource.PlayOneShot(audioSource.clip); } } break; case TokenType.AudioLoop: { AudioSource audioSource = null; if (CheckParamCount(token.paramList, 1)) { audioSource = FindAudio(token.paramList[0]); } if (audioSource != null) { audioSource.Play(); audioSource.loop = true; } } break; case TokenType.AudioPause: { AudioSource audioSource = null; if (CheckParamCount(token.paramList, 1)) { audioSource = FindAudio(token.paramList[0]); } if (audioSource != null) { audioSource.Pause(); } } break; case TokenType.AudioStop: { AudioSource audioSource = null; if (CheckParamCount(token.paramList, 1)) { audioSource = FindAudio(token.paramList[0]); } if (audioSource != null) { audioSource.Stop(); } } break; } previousTokenType = token.type; if (exitFlag) { break; } } inputFlag = false; exitFlag = false; isWaitingForInput = false; isWriting = false; NotifyEnd(stopAudio); if (onComplete != null) { onComplete(); } }
protected virtual IEnumerator WriteText(string text, Action onWritingComplete, Action onExitTag) { storyText.text = ""; // Parse the story text & tag markup to produce a list of tokens for processing DialogParser parser = new DialogParser(); parser.Tokenize(text); if (parser.tokens.Count == 0) { if (onWritingComplete != null) { onWritingComplete(); } yield break; } DialogText dialogText = new DialogText(); dialogText.parentDialog = this; dialogText.writingSpeed = writingSpeed; dialogText.punctuationPause = punctuationPause; dialogText.beepPerCharacter = beepPerCharacter; dialogText.slowBeepsAt = slowBeepsAt; dialogText.fastBeepsAt = fastBeepsAt; AudioSource typingAudio = GetComponent <AudioSource>(); if (characterTypingSound != null || writingSound != null) { if (characterTypingSound != null) { typingAudio.clip = characterTypingSound; } else if (writingSound != null) { typingAudio.clip = writingSound; } typingAudio.loop = loopWritingSound; // Start at full volume typingAudio.volume = writingVolume; SetTypingSoundVolume(true); typingAudio.Play(); } foreach (Token token in parser.tokens) { switch (token.type) { case TokenType.Words: dialogText.Append(token.param); break; case TokenType.BoldStart: dialogText.boldActive = true; break; case TokenType.BoldEnd: dialogText.boldActive = false; break; case TokenType.ItalicStart: dialogText.italicActive = true; break; case TokenType.ItalicEnd: dialogText.italicActive = false; break; case TokenType.ColorStart: dialogText.colorActive = true; dialogText.colorText = token.param; break; case TokenType.ColorEnd: dialogText.colorActive = false; break; case TokenType.Wait: float duration = 1f; if (!Single.TryParse(token.param, out duration)) { duration = 1f; } yield return(StartCoroutine(WaitForSecondsOrInput(duration))); break; case TokenType.WaitForInputNoClear: OnWaitForInputTag(true); yield return(StartCoroutine(WaitForInput(null))); OnWaitForInputTag(false); break; case TokenType.WaitForInputAndClear: OnWaitForInputTag(true); yield return(StartCoroutine(WaitForInput(null))); OnWaitForInputTag(false); currentSpeed = writingSpeed; dialogText.Clear(); StopVoiceOver(); break; case TokenType.WaitOnPunctuationStart: float newPunctuationPause = 0f; if (!Single.TryParse(token.param, out newPunctuationPause)) { newPunctuationPause = 0f; } dialogText.punctuationPause = newPunctuationPause; break; case TokenType.WaitOnPunctuationEnd: dialogText.punctuationPause = punctuationPause; break; case TokenType.Clear: dialogText.Clear(); break; case TokenType.SpeedStart: float newSpeed = 0; if (!Single.TryParse(token.param, out newSpeed)) { newSpeed = 0f; } dialogText.writingSpeed = newSpeed; break; case TokenType.SpeedEnd: dialogText.writingSpeed = writingSpeed; break; case TokenType.Exit: if (onExitTag != null) { prevStoryText = storyText.text; SetTypingSoundVolume(false); onExitTag(); } yield break; case TokenType.Message: Flowchart.BroadcastFungusMessage(token.param); break; case TokenType.VerticalPunch: float vPunchIntensity = 0; if (!Single.TryParse(token.param, out vPunchIntensity)) { vPunchIntensity = 0f; } VerticalPunch(vPunchIntensity); break; case TokenType.HorizontalPunch: float hPunchIntensity = 0; if (!Single.TryParse(token.param, out hPunchIntensity)) { hPunchIntensity = 0f; } HorizontalPunch(hPunchIntensity); break; case TokenType.Shake: float shakeIntensity = 0; if (!Single.TryParse(token.param, out shakeIntensity)) { shakeIntensity = 0f; } Shake(shakeIntensity); break; case TokenType.Shiver: float shiverIntensity = 0; if (!Single.TryParse(token.param, out shiverIntensity)) { shiverIntensity = 0f; } Shiver(shiverIntensity); break; case TokenType.Flash: float flashDuration = 0; if (!Single.TryParse(token.param, out flashDuration)) { flashDuration = 0f; } Flash(flashDuration); break; case TokenType.Audio: { AudioSource audioSource = FindAudio(token.param); if (audioSource != null) { audioSource.PlayOneShot(audioSource.clip); } } break; case TokenType.AudioLoop: { AudioSource audioSource = FindAudio(token.param); if (audioSource != null) { audioSource.Play(); audioSource.loop = true; } } break; case TokenType.AudioPause: { AudioSource audioSource = FindAudio(token.param); if (audioSource != null) { audioSource.Pause(); } } break; case TokenType.AudioStop: { AudioSource audioSource = FindAudio(token.param); if (audioSource != null) { audioSource.Pause(); } } break; } // Update text writing while (!dialogText.UpdateGlyphs(wasPointerClicked)) { storyText.text = dialogText.GetDialogText(); yield return(null); } storyText.text = dialogText.GetDialogText(); wasPointerClicked = false; // Now process next token } prevStoryText = storyText.text; SetTypingSoundVolume(false); if (onWritingComplete != null) { onWritingComplete(); } yield break; }
protected virtual IEnumerator ProcessTokens(List <TextTagParser.Token> tokens, Action onComplete) { // Reset control members boldActive = false; italicActive = false; colorActive = false; colorText = ""; currentPunctuationPause = punctuationPause; currentWritingSpeed = writingSpeed; exitFlag = false; isWriting = true; foreach (TextTagParser.Token token in tokens) { switch (token.type) { case TextTagParser.TokenType.Words: yield return(StartCoroutine(DoWords(token.param))); break; case TextTagParser.TokenType.BoldStart: boldActive = true; break; case TextTagParser.TokenType.BoldEnd: boldActive = false; break; case TextTagParser.TokenType.ItalicStart: italicActive = true; break; case TextTagParser.TokenType.ItalicEnd: italicActive = false; break; case TextTagParser.TokenType.ColorStart: colorActive = true; colorText = token.param; break; case TextTagParser.TokenType.ColorEnd: colorActive = false; break; case TextTagParser.TokenType.Wait: yield return(StartCoroutine(DoWait(token.param))); break; case TextTagParser.TokenType.WaitForInputNoClear: yield return(StartCoroutine(DoWaitForInput(false))); break; case TextTagParser.TokenType.WaitForInputAndClear: yield return(StartCoroutine(DoWaitForInput(true))); break; case TextTagParser.TokenType.WaitOnPunctuationStart: if (!Single.TryParse(token.param, out currentPunctuationPause)) { currentPunctuationPause = punctuationPause; } break; case TextTagParser.TokenType.WaitOnPunctuationEnd: currentPunctuationPause = punctuationPause; break; case TextTagParser.TokenType.Clear: text = ""; break; case TextTagParser.TokenType.SpeedStart: if (!Single.TryParse(token.param, out currentWritingSpeed)) { currentWritingSpeed = writingSpeed; } break; case TextTagParser.TokenType.SpeedEnd: currentWritingSpeed = writingSpeed; break; case TextTagParser.TokenType.Exit: exitFlag = true; break; case TextTagParser.TokenType.Message: Flowchart.BroadcastFungusMessage(token.param); break; case TextTagParser.TokenType.VerticalPunch: float vintensity; if (!Single.TryParse(token.param, out vintensity)) { vintensity = 10f; } Punch(new Vector3(0, vintensity, 0), 0.5f); break; case TextTagParser.TokenType.HorizontalPunch: float hintensity; if (!Single.TryParse(token.param, out hintensity)) { hintensity = 10f; } Punch(new Vector3(hintensity, 0, 0), 0.5f); break; case TextTagParser.TokenType.Punch: float intensity; if (!Single.TryParse(token.param, out intensity)) { intensity = 10f; } Punch(new Vector3(intensity, intensity, 0), 0.5f); break; case TextTagParser.TokenType.Flash: float flashDuration; if (!Single.TryParse(token.param, out flashDuration)) { flashDuration = 0.2f; } Flash(flashDuration); break; case TextTagParser.TokenType.Audio: { AudioSource audioSource = FindAudio(token.param); if (audioSource != null) { audioSource.PlayOneShot(audioSource.clip); } } break; case TextTagParser.TokenType.AudioLoop: { AudioSource audioSource = FindAudio(token.param); if (audioSource != null) { audioSource.Play(); audioSource.loop = true; } } break; case TextTagParser.TokenType.AudioPause: { AudioSource audioSource = FindAudio(token.param); if (audioSource != null) { audioSource.Pause(); } } break; case TextTagParser.TokenType.AudioStop: { AudioSource audioSource = FindAudio(token.param); if (audioSource != null) { audioSource.Stop(); } } break; } if (exitFlag) { break; } } inputFlag = false; exitFlag = false; isWaitingForInput = false; isWriting = false; NotifyEnd(); if (onComplete != null) { onComplete(); } }
// 处理Token序列 protected virtual IEnumerator ProcessTokens(List <TextTagToken> tokens, bool stopAudio, Action onComplete) { // Reset control members boldActive = false; italicActive = false; colorActive = false; sizeActive = false; colorText = ""; sizeValue = 16f; currentPunctuationPause = punctuationPause; currentWritingSpeed = writingSpeed; exitFlag = false; isWriting = true; TokenType previousTokenType = TokenType.Invalid; // 开始, // 遍历所有Token for (int i = 0; i < tokens.Count; ++i) { // 持续保持暂停 // Pause between tokens if Paused is set while (Paused) { yield return(null); } var token = tokens[i]; // Notify listeners about new token WriterSignals.DoTextTagToken(this, token, i, tokens.Count); // Update the read ahead string buffer. This contains the text for any // Word tags which are further ahead in the list. readAheadString.Length = 0; // 向后查看Token // 获取到所有的Words Token for (int j = i + 1; j < tokens.Count; ++j) { var readAheadToken = tokens[j]; // work token的paramList: // * 只有一个参数 // * 就是要显示的文本 if (readAheadToken.type == TokenType.Words && readAheadToken.paramList.Count == 1) { readAheadString.Append(readAheadToken.paramList[0]); } else if (readAheadToken.type == TokenType.WaitForInputAndClear) { break; } } // 这里有时间长度的操作,都是Coroutine操作 // 一路从SayDialog.DoSay // * Writer.Write // * Writer.ProcessTokens switch (token.type) { // 显示文本 case TokenType.Words: yield return(StartCoroutine(DoWords(token.paramList, previousTokenType))); break; // 处理<b></b> case TokenType.BoldStart: boldActive = true; break; case TokenType.BoldEnd: boldActive = false; break; // 处理斜体 case TokenType.ItalicStart: italicActive = true; break; case TokenType.ItalicEnd: italicActive = false; break; // 处理颜色 case TokenType.ColorStart: if (CheckParamCount(token.paramList, 1)) { colorActive = true; // 取出颜色参数 colorText = token.paramList[0]; } break; case TokenType.ColorEnd: colorActive = false; break; // 处理Size标签 case TokenType.SizeStart: if (TryGetSingleParam(token.paramList, 0, 16f, out sizeValue)) { sizeActive = true; } break; case TokenType.SizeEnd: sizeActive = false; break; // 等待 case TokenType.Wait: yield return(StartCoroutine(DoWait(token.paramList))); break; // 等待输入 case TokenType.WaitForInputNoClear: yield return(StartCoroutine(DoWaitForInput(false))); break; case TokenType.WaitForInputAndClear: yield return(StartCoroutine(DoWaitForInput(true))); break; // 等待语音结束 case TokenType.WaitForVoiceOver: yield return(StartCoroutine(DoWaitVO())); break; // 等待标点 case TokenType.WaitOnPunctuationStart: TryGetSingleParam(token.paramList, 0, punctuationPause, out currentPunctuationPause); break; case TokenType.WaitOnPunctuationEnd: currentPunctuationPause = punctuationPause; break; // 清屏 case TokenType.Clear: textAdapter.Text = ""; break; // 更改 // 字符出现速度 case TokenType.SpeedStart: TryGetSingleParam(token.paramList, 0, writingSpeed, out currentWritingSpeed); break; case TokenType.SpeedEnd: currentWritingSpeed = writingSpeed; break; // 结束 case TokenType.Exit: exitFlag = true; break; // 发送消息 case TokenType.Message: if (CheckParamCount(token.paramList, 1)) { Flowchart.BroadcastFungusMessage(token.paramList[0]); } break; // 震屏 case TokenType.VerticalPunch: { float vintensity; float time; TryGetSingleParam(token.paramList, 0, 10.0f, out vintensity); TryGetSingleParam(token.paramList, 1, 0.5f, out time); Punch(new Vector3(0, vintensity, 0), time); } break; case TokenType.HorizontalPunch: { float hintensity; float time; TryGetSingleParam(token.paramList, 0, 10.0f, out hintensity); TryGetSingleParam(token.paramList, 1, 0.5f, out time); Punch(new Vector3(hintensity, 0, 0), time); } break; case TokenType.Punch: { float intensity; float time; TryGetSingleParam(token.paramList, 0, 10.0f, out intensity); TryGetSingleParam(token.paramList, 1, 0.5f, out time); Punch(new Vector3(intensity, intensity, 0), time); } break; // 闪屏 case TokenType.Flash: float flashDuration; TryGetSingleParam(token.paramList, 0, 0.2f, out flashDuration); Flash(flashDuration); break; // 播放音效 case TokenType.Audio: { AudioSource audioSource = null; if (CheckParamCount(token.paramList, 1)) { audioSource = FindAudio(token.paramList[0]); } if (audioSource != null) { audioSource.PlayOneShot(audioSource.clip); } } break; // 循环播放音效 case TokenType.AudioLoop: { AudioSource audioSource = null; if (CheckParamCount(token.paramList, 1)) { audioSource = FindAudio(token.paramList[0]); } if (audioSource != null) { audioSource.Play(); audioSource.loop = true; } } break; // 暂停播放音效 case TokenType.AudioPause: { AudioSource audioSource = null; if (CheckParamCount(token.paramList, 1)) { audioSource = FindAudio(token.paramList[0]); } if (audioSource != null) { audioSource.Pause(); } } break; // 停止播放音效 case TokenType.AudioStop: { AudioSource audioSource = null; if (CheckParamCount(token.paramList, 1)) { audioSource = FindAudio(token.paramList[0]); } if (audioSource != null) { audioSource.Stop(); } } break; } // 记录当前的 // Token类型 previousTokenType = token.type; if (exitFlag) { break; } // 最后判断 } inputFlag = false; exitFlag = false; isWaitingForInput = false; isWriting = false; // 通知结束 NotifyEnd(stopAudio); if (onComplete != null) { onComplete(); } }