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 DoWords(List <string> paramList, TokenType previousTokenType) { if (!CheckParamCount(paramList, 1)) { yield break; } string param = paramList[0].Replace("\\n", "\n"); // Trim whitespace after a {wc} or {c} tag if (previousTokenType == TokenType.WaitForInputAndClear || previousTokenType == TokenType.Clear) { param = param.TrimStart(' ', '\t', '\r', '\n'); } // Start with the visible portion of any existing displayed text. string startText = ""; if (visibleCharacterCount > 0 && visibleCharacterCount <= textAdapter.Text.Length) { startText = textAdapter.Text.Substring(0, visibleCharacterCount); } UpdateOpenMarkup(); UpdateCloseMarkup(); float timeAccumulator = Time.deltaTime; float invWritingSpeed = 1f / currentWritingSpeed; //refactor this, its mostly the same 30 lines of code if (textAdapter.SupportsHiddenCharacters()) { //pausing for 1 frame means we can get better first data, but is conflicting with animation ? // or is it something else inserting the color alpha invis yield return(null); //this works for first thing being shown but then no subsequent, as the char counts have not been update // by tmpro after the set to "" var startingReveal = Mathf.Min(readAheadStartIndex, textAdapter.CharactersToReveal); PartitionString(writeWholeWords, param, param.Length + 1); ConcatenateString(startText); textAdapter.Text = outputString.ToString(); NotifyGlyph(); textAdapter.RevealedCharacters = startingReveal; yield return(null); while (textAdapter.RevealedCharacters < Mathf.Min(readAheadStartIndex, textAdapter.CharactersToReveal)) { // No delay if user has clicked and Instant Complete is enabled if (instantComplete && inputFlag) { textAdapter.RevealedCharacters = textAdapter.CharactersToReveal; } if (currentWritingSpeed > 0f) { textAdapter.RevealedCharacters++; timeAccumulator -= invWritingSpeed; if (timeAccumulator <= 0f) { var waitTime = Mathf.Max(invWritingSpeed, Time.deltaTime); yield return(new WaitForSeconds(waitTime)); timeAccumulator += waitTime; } } } } else { for (int i = 0; i < param.Length + 1; ++i) { if (exitFlag) { break; } // Pause mid sentence if Paused is set while (Paused) { yield return(null); } PartitionString(writeWholeWords, param, i); ConcatenateString(startText); textAdapter.Text = outputString.ToString(); NotifyGlyph(); // No delay if user has clicked and Instant Complete is enabled if (instantComplete && inputFlag) { continue; } // Punctuation pause if (leftString.Length > 0 && rightString.Length > 0 && IsPunctuation(leftString.ToString(leftString.Length - 1, 1)[0])) { //timeAccumulator -= currentPunctuationPause; ??? yield return(StartCoroutine(DoWait(currentPunctuationPause))); } // Delay between characters if (currentWritingSpeed > 0f) { timeAccumulator -= invWritingSpeed; if (timeAccumulator <= 0f) { var waitTime = Mathf.Max(invWritingSpeed, Time.deltaTime); yield return(new WaitForSeconds(waitTime)); timeAccumulator += waitTime; } } } } }