Typewriter autoscroll - account for margins

Announcements, support questions, and discussion for the Dialogue System.
Post Reply
VoodooDetective
Posts: 222
Joined: Wed Jan 22, 2020 10:48 pm

Typewriter autoscroll - account for margins

Post by VoodooDetective »

Would you be willing to have the typewriter auto scroll function account for the margins?
Right now it's setting the layout element preferred height like this:

Code: Select all

layoutElement.preferredHeight = textComponent.textBounds.size.y
and I'm proposing something like this:

Code: Select all

layoutElement.preferredHeight = textComponent.textBounds.size.y + textComponent.margin.y + textComponent.margin.z;


SIDE QUESTION:
I noticed that the first frame after the text appears, the text container stretches to the full text height. Could it be that the autoscroller isn't called soon enough?
User avatar
Tony Li
Posts: 22162
Joined: Thu Jul 18, 2013 1:27 pm

Re: Typewriter autoscroll - account for margins

Post by Tony Li »

Hi,

I'll make TextMeshProTypewriterEffect.HandleAutoScroll virtual so you can override it to handle margins and anything else you need.
VoodooDetective wrote: Wed May 12, 2021 10:26 pmI noticed that the first frame after the text appears, the text container stretches to the full text height. Could it be that the autoscroller isn't called soon enough?
I'm not sure what could be causing this. As a test, after line 252 (textComponent.ForceMeshUpdate();), please add this line:

Code: Select all

HandleAutoScroll();
Let me know if that resolves the issue.
VoodooDetective
Posts: 222
Joined: Wed Jan 22, 2020 10:48 pm

Re: Typewriter autoscroll - account for margins

Post by VoodooDetective »

Awesome, thanks! That'll be perfect if it's virtual!
I figured out what the other issue is too and I think I found a little mistake in the code:


Issue
The issue is that StandardUISubtitlePanel.SetContent() will call this before typing starts:

Code: Select all

TypewriterUtility.StopTyping(subtitleText);
Which triggers HandleAutoScroll(). Because textComponent.text is empty,

Code: Select all

textComponent.textBounds.size.y
ends up being a crazy negative number.

So I'm just doing this:

Code: Select all

Mathf.Max(0f, textComponent.textBounds.size.y);
Possible Mistake
I just noticed that there's an unused property called "layoutElement" in TextMeshProTypewriterEffect. The getter is duplicated in HandleAutoScroll.
User avatar
Tony Li
Posts: 22162
Joined: Thu Jul 18, 2013 1:27 pm

Re: Typewriter autoscroll - account for margins

Post by Tony Li »

Okay, the version of the file in this patch will also be in DS 2.2.17:

DS_TMPTypewriterPatch_2021-05-13.unitypackage

Changes:
  • HandleAutoScroll() is virtual.
  • Removed redundant local layoutElement variable from HandleAutoScroll().
  • Added Mathf.Max(0f, textComponent.textBounds.size.y); bounds handler.
Thanks for your help on those items!
VoodooDetective
Posts: 222
Joined: Wed Jan 22, 2020 10:48 pm

Re: Typewriter autoscroll - account for margins

Post by VoodooDetective »

Awesome! Thanks so much!


Incidentally, I noticed one other issue I'm working out right now.
The first frame that maxVisibleCharacters increases to the point that a new line is added, the text will extend beyond the size of the LayoutElement.preferredHeight we've been setting.

This is because textBounds is updated at the culling stage, right before render. So the value reflected by the textBounds is effectively for the previous frame.

To force those updates to happen immediately, I _believe_ it should be safe/efficient to call:

Code: Select all

ForceMeshUpdate();
to ensure those changes happen immediately. I'm still verifying that this is efficient with Stephan_B. He'd said:
[...]when calling ForceMeshUpdate() all properties that have been changed will be processed and if no further changes are made before culling takes place then this object will skip its normal update.
I'll verify that means what I think it means and report back.
VoodooDetective
Posts: 222
Joined: Wed Jan 22, 2020 10:48 pm

Re: Typewriter autoscroll - account for margins

Post by VoodooDetective »

Looks like it's safe to use force update!
ForceMeshUpdate() simply forces the text object to be updated immediately instead of later in the frame. So provided you don't make any other property changes after that, the text object will not be updated again that frame thus making this as efficient.
VoodooDetective
Posts: 222
Joined: Wed Jan 22, 2020 10:48 pm

Re: Typewriter autoscroll - account for margins

Post by VoodooDetective »

I just wanted to give a quick update for posterity on an efficient way to calculate the height without regenerating the bounds every time:

Code: Select all

        protected override void HandleAutoScroll()
        {
            if (!autoScrollSettings.autoScrollEnabled) return;

            // Make sure we have a valid range of typed characters.
            if (charactersTyped == 0 || charactersTyped - 1 > textComponent.textInfo.characterCount)
                return;

            // Determine the line number of the current character.
            int currentLine = textComponent.textInfo.characterInfo[charactersTyped - 1].lineNumber;

            // Compute the height of the text
            // This corresponds to the first line Ascender to current line Descender.
            float textAscender = textComponent.textInfo.lineInfo[0].ascender;
            float textDescender = textComponent.textInfo.lineInfo[currentLine].descender;
            float textHeight = textAscender - textDescender + textComponent.margin.y + textComponent.margin.z;

            // Set Height
            layoutElement.preferredHeight = textHeight;

            // Scroll
            if (autoScrollSettings.scrollRect != null)
            {
                autoScrollSettings.scrollRect.normalizedPosition = Vector2.zero;
            }
            if (autoScrollSettings.scrollbarEnabler != null)
            {
                autoScrollSettings.scrollbarEnabler.CheckScrollbar();
            }
        }
Post Reply