0 votes

This is a very in-the-weeds kind of question. The TLDR is that I want to know how to return the number of characters that aren't printed (e.g. tags) in a given slice of bb_code. As far as I can see, there is no easy way to do this.

Long question: I wanted to set up typewriter effects for a RichTextLabel using inline commands. I came up with the format of :

[command name=speed param=3][/command]

Using some inelegant code, the game iterates over the RichTextLabel, increasing the visiblecharacter property by 1 each time so text is slowly revealed. However, if a piece of RegEx picks up this command, it sweeps it off and translates it into a function. This one speeds up the text reveal three times faster. The idea is that each command shuttles off into a different function so that it can create effects in time with the text. (e.g. "A door opens [command name=soundplay param=door_sound][/command]..." would play a door sound effect a the same time the word "opens" is revealed.)

The system works well except I noticed that the effect would be offset a few character later every time. After some investigation, I discovered that issue was with this function:

commandMatch = commandRegex.search(outputBox.bbcode_text.right(outputBox.visible_characters + offset))

"Visible characters" only count the characters that are actively rendered, so that the ones in the bbcode tags don't count. But, the bbcodetext property includes those tags. So what I need to do is offset the visible_characters by the characters used in bbcode tags, except as far as I can see there's no easy way to do this. The only way I can think of is to make another RegEx which captures all square bracketed text to the left, but to do that, I need to know the index of last visible character on the raw bbcode, which there's no method for and can't be calculated without knowing how many character were used in tags... so it's a recursive problem.

A different illustration of the issue: This is what the player would see:

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

If I retrieved the visible characters and used it as an index on the raw bb_code, it would quickly desynchronize. 123 characters looks like this:

Lorem ipsum dolor sit amet, consectetur [i]adipiscing[/i] elit, sed do eiusmod [i]tempor[/i] incididunt ut [i]labore[/i] et

If I wanted an inline command to play a sfx at the end of the sentence, it would instead appear to the player like it plays in the middle of the second sentence.

I guess the only way I can do this is to keep a variable which stores the .length() of all square bracketed text and use that as my offset. I don't know... it seems like there should be an easier, more elegant solution, especially because it would create issues when there's bracketed text that's supposed to be visible. Maybe I just answered my own question, but I'm interested on what the experts think.

Thanks for your time.

Godot version 3.4.4
in Engine by (37 points)

1 Answer

+1 vote
Best answer

Ok, so you have a string like var string = "123\t123" and you want to count the not visible characters. A regular expression should do the trick hopefully:

print(len(string.replace("/[^a-z0-9-]/g", "")))

Confession: I stopped reading after the first paragraph as the tldr seemed pretty clear. Also, I didn't test anything and, it's regex, everyone gets the first attempt wrong. My excuse is it's Friday evening. :)

by (1,877 points)
selected by

Thank you! An implementation of this ended up being the solution I needed.

Delighted to hear it!

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.