Indie game storeFree gamesFun gamesHorror games
Game developmentAssetsComics
SalesBundles
Jobs
Tags

STMTextInfo reporting incorrect (?) pos after rebuild

A topic by Scarlet String Studios created Dec 09, 2021 Views: 99 Replies: 4
Viewing posts 1 to 5

Hey,

A while ago you had helped me come up with a script that could place an input caret at the end of a STM component to simulate typing. The script works by grabbing the STMTextInfo of stm.latestNumber and using that letter's pos as a starting point.

After updating to 1.12, it seems that this is no longer working when I rebuild the text. I have a backspacing effect where I loop through the text and delete the last letter up to a point - then I change the text to a new string, and call Rebuild to type out the new string instead. The reading works correctly, but when I change the text, the pos of latestNumber is always at the end of the sentence. So the caret gets stuck at the end while the text reads out to eventually catch up to it.

The rebuilding part of the method is just this:

theMesh.readDelay = originalReadDelay;
theMesh.text = originalStr.Remove(backspaceStart, charsToDel);
theMesh.Rebuild(readTime, true);

Did anything change with STMTextInfo or latestNumber in the past few versions?

Developer

Hmm... looking back at what's changed, could it maybe be the autoRead setting of the mesh? I fixed an error where setting .text would ignore the mesh's autoread settings. But it looks like you're forcing it to read with that Rebuild() anyway, so I don't think it's this... but try setting ._text in that 2nd row anyway, to see if it makes a difference! It's possible that the readTime value is being overwritten...?


I've been meaning to add a backspacing effect myself for years now, but I think one miiight be possible with the new UndoContinue() tag and inverting STM's drawOrder? I can look into this more in a bit! I'm going through my docs and git history to find changes with STMTextInfo and latestNumber.

Hey, you're right! Setting ._text instead of .text did the trick. It's working now. This is what it looks like: https://streamable.com/3333xm

What's the reason for this exactly? You said something about readTime getting overwritten?

Developer

Wow, that looks incredible!! I was always really hoping that STM could pull off an effect like this, but I never tried it myself!

._text will set the text value without automatically calling Rebuild(). Calling .text will automatically call Rebuild(), passing along the autoRead value. So I think it might have been getting the previous time wrong... what I meant was, where were you grabbing the "theMesh.Rebuild(readTime, true);"'s readTime value from? If it was theMesh.totalReadTime, the previous .text set call would have overwritten it

(2 edits)

Thank you! Yeah, STM ended up becoming a pretty big part of this project.

I see what you mean now. The float "readTime" was cached from "theMesh.currentReadTime" on the first frame that the <e> event was triggered. Basically it's the read time of the STM at the point before the text to be backspaced begins. After the <e> event, we continue reading for a few letters, then backspace, then rebuild and continue reading where we left off.

The implementation is not ideal, and I wrote it a couple years ago. There are a couple of yield return nulls that I'm not sure are necessary. But I can see why setting .text might have messed with the read time values.

Without all the print statements and whatnot, it's sort of like...

float readTime = theMesh.currentReadTime;
//wait for mesh to read through the letters that we want to delete
while (theMesh.latestNumber < (backspaceEnd - 1))
{
    yield return null;
}
//cut out the rest of the line and pause for a moment
string originalStr = theMesh.text;
float originalReadDelay = theMesh.readDelay;
theMesh.readDelay = 0f;
yield return null; //for some reason we need this here?
theMesh.text = originalStr.RemoveFromIndexToEnd(backspaceEnd + 1);
theMesh.Rebuild(1f, true);
yield return null; //we need this pause to make sure the text stops reading here
theMesh.SkipToEnd();
yield return new WaitForSeconds(1f);
//delete some chars
int counter = 0;
while (counter < charsToDel)
{
    counter++;
    theMesh.Text = theMesh.text.RemoveFromEnd(1);
    theMesh.Rebuild();
    yield return new WaitForSeconds(currTypeSpeed);
}
yield return new WaitForSeconds(waitTime);
//resume reading
theMesh.readDelay = originalReadDelay;
theMesh._text = originalStr.Remove(backspaceStart, charsToDel);
theMesh.Rebuild(readTime, true);

EDIT: The code formatting is removing my linebreaks for some reason, so this is a little hard to read. But you get the idea.