/// <summary>
        /// Shows remains letters dynamically
        /// </summary>
        /// <param name="text"></param>
        /// <returns></returns>
        private IEnumerator ShowRemainingCharacters()
        {
            if (!textAnimator.allLettersShown)
            {
                isInsideRoutine = true;
                wantsToSkip     = false;

                onTypewriterStart?.Invoke();

                IEnumerator WaitTime(float time)
                {
                    if (time > 0)
                    {
                        float t = 0;
                        while (t <= time)
                        {
                            t += textAnimator.time.deltaTime;
                            yield return(null);
                        }
                    }
                }

                float timeToWait;
                char  characterShown;

                if (resetTypingSpeedAtStartup)
                {
                    typewriterPlayerSpeed = 1;
                }

                float typewriterTagsSpeed = 1;

                bool HasSkipped()
                {
                    return(canSkipTypewriter && wantsToSkip);
                }

                float timePassed = 0;

                float deltaTime;
                UpdateDeltaTime();

                void UpdateDeltaTime()
                {
                    deltaTime = textAnimator.time.deltaTime * typewriterPlayerSpeed * typewriterTagsSpeed;
                }

                //Shows character by character until all are shown
                while (!textAnimator.allLettersShown)
                {
                    //searches for actions [before the character, incl. at the very start of the text]
                    if (textAnimator.hasActions)
                    {
                        //loops until features ended (there could be multiple ones in the same text position, example: when two tags are next to eachother without spaces
                        while (textAnimator.TryGetAction(out TypewriterAction action))
                        {
                            //Default features
                            switch (action.actionID)
                            {
                            case "waitfor":
                                float waitTime;
                                FormatUtils.TryGetFloat(action.parameters, 0, 1f, out waitTime);
                                yield return(WaitTime(waitTime));

                                break;

                            case "waitinput":
                                yield return(WaitInput());

                                break;

                            case "speed":
                                FormatUtils.TryGetFloat(action.parameters, 0, 1, out typewriterTagsSpeed);

                                //clamps speed (time cannot go backwards!)
                                if (typewriterTagsSpeed <= 0)
                                {
                                    typewriterTagsSpeed = 0.001f;
                                }

                                break;

                            //Action is custom
                            default:
                                yield return(DoCustomAction(action));

                                break;
                            }
                        }
                    }


                    //increases the visible chars count and stores the new one
                    characterShown = textAnimator.IncreaseVisibleChars();
                    UpdateDeltaTime();

                    //triggers event unless it's a space
                    if (characterShown != ' ')
                    {
                        onCharacterVisible?.Invoke(characterShown);
                    }

                    //gets the time to wait based on the newly character showed
                    timeToWait = WaitTimeOf(characterShown);

                    //waiting less time than a frame, we don't wait yet
                    if (timeToWait < deltaTime)
                    {
                        timePassed += timeToWait;

                        if (timePassed >= deltaTime) //waits only if we "surpassed" a frame duration
                        {
                            yield return(null);

                            timePassed %= deltaTime;
                        }
                    }
                    else
                    {
                        while (timePassed < timeToWait && !HasSkipped())
                        {
                            OnTypewriterCharDelay();
                            timePassed += deltaTime;
                            yield return(null);

                            UpdateDeltaTime();
                        }

                        timePassed %= timeToWait;
                    }

                    //Skips typewriter
                    if (HasSkipped())
                    {
                        textAnimator.ShowAllCharacters(hideAppearancesOnSkip);

                        if (triggerEventsOnSkip)
                        {
                            textAnimator.TriggerRemainingEvents();
                        }

                        break;
                    }
                }

                // triggers the events at the end of the text
                //
                // the typewriter is arrived here without skipping
                // meaning that all events were triggered and we only
                // have to fire the ones at the very end
                // (outside tmpro's characters count length)
                if (!canSkipTypewriter || !wantsToSkip)
                {
                    textAnimator.TriggerRemainingEvents();
                }

                isInsideRoutine = false;

                textToShow = string.Empty; //text has been showed, no need to store it now

                onTextShowed?.Invoke();
            }
        }
Esempio n. 2
0
        /// <summary>
        /// Typewriter effect
        /// </summary>
        /// <param name="text"></param>
        /// <returns></returns>
        private IEnumerator ShowVisibleCharacters()
        {
            if (!textAnimator.allLettersShown)
            {
                isInsideRoutine = true;
                wantsToSkip     = false;
                float t;

                onTypewriterStart?.Invoke();

#pragma warning disable 0618 //temp obsolete warning disable or any user that did not implement it will have a warning as well
                OnTypeWriterStart();
#pragma warning restore 0618

                IEnumerator WaitTime(float time)
                {
                    if (time > 0)
                    {
                        t = 0;
                        while (t <= time)
                        {
                            t += textAnimator.deltaTime;
                            yield return(null);
                        }
                    }
                }

                float timeToWait;
                char  characterShown = ' ';

                typewriterPlayerSpeed = 1;

                float typewriterTagsSpeed = 1;
                //Shows character by character until all are shown
                while (!textAnimator.allLettersShown)
                {
                    //searches for features
                    if (textAnimator.hasFeatures)
                    {
                        //loops until features ended (there could be multiple ones in the same text position, example: when two tags are next to eachother without spaces
                        while (textAnimator.TryGetFeature(out TextAnimator.CustomTag feature))
                        {
                            //Default features
                            switch (feature.defaultFeature)
                            {
                            case DefaultFeature.WaitFor:
                                float waitTime;
                                FormatUtils.TryGetFloat(feature.parameters, 0, 1f, out waitTime);
                                yield return(WaitTime(waitTime));

                                break;

                            case DefaultFeature.WaitInput:
                                yield return(WaitInput());

                                break;

                            case DefaultFeature.TypewriterSpeedMult:
                                FormatUtils.TryGetFloat(feature.parameters, 0, 1, out typewriterTagsSpeed);

                                //clamps speed (time cannot go backwards!)
                                if (typewriterTagsSpeed <= 0)
                                {
                                    typewriterTagsSpeed = 0.001f;
                                }

                                break;
                            }

                            //Custom features
                            if (feature.customFeature != CustomFeature.NotImplemented)
                            {
                                yield return(DoCustomFeature(feature.customFeature, feature.parameters));
                            }
                        }
                    }

                    characterShown = textAnimator.IncreaseVisibleChars();

                    t          = 0;
                    timeToWait = WaitTimeOf( //get the wait time based
                        characterShown       //increases characters
                        );


                    //triggers event unless it's a space
                    if (characterShown != ' ')
                    {
                        onCharacterVisible?.Invoke(characterShown);
                    }

                    while (t <= timeToWait && !(canSkipTypewriter && wantsToSkip))
                    {
                        UpdateTypeWriterInput();

                        t += textAnimator.deltaTime * typewriterPlayerSpeed * typewriterTagsSpeed;

                        yield return(null);
                    }


                    //Skips typewriter
                    if (canSkipTypewriter && wantsToSkip)
                    {
                        textAnimator.ShowAllCharacters(hideAppearancesOnSkip);
                        break;
                    }
                }

                isInsideRoutine = false;

                textToShow = string.Empty; //text has been showed, no need to store it now

                onTextShowed?.Invoke();

#pragma warning disable 0618 //temp obsolete warning disable or any user that did not implement it will have a warning as well
                onTypeWriterEnded?.Invoke();
#pragma warning restore 0618
            }
        }