-
-
Notifications
You must be signed in to change notification settings - Fork 21.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RichTextLabel - New Real Time Text Effects and Custom BBCode Extensions #23658
Conversation
dac90f7
to
9d57a7c
Compare
Instead of overriding functions of RichTextLabel and checking the name of the effect each time, why not define a Resource type which you can extend with GDScript? This way you will be able to have one script per effect if you want, and no need to check the name of the effect in your code. |
a37ef18
to
755bb12
Compare
Yeah I've been considering doing something like that to help make it a bit simpler. I may try messing with something along those lines a bit tonight. Is it strange or out of character for resources to be used in a way where they're mostly used for the functionality instead of the data though? |
@Zylann Is there actually a way to make it so that I check for any custom resource script that exists within a project? So if you define a custom effect resource in gdscript (Let's say Also, is there a good example in the code for dealing with adding custom resources that you can think of? |
Sorry Godot generally avoids doing global file walks to accomplish auto-registration like you suggest (I once proposed that for custom loaders but was told no). Also it's better to register it in this case because otherwise every RichTextLabel would end up doing that and always registering every effect without control. For custom resources like that, I guess in your case RichTextFX would be a resource. For an example, I made a voxel module in which you can define your own terrain provider (as a resource) https://github.com/Zylann/godot_voxel/blob/master/voxel_provider.cpp (nevermind Just suggestions to make it easier to share, I'm not particularly in this kind of effects but I find your PR interesting^^ |
Hey @Zylann thanks for taking the time to help me out here. I have one more quick question... What is the best way to expose this type of behavior to the editor? I have it working by doing basically what you had above ( |
@THEYOKAI to expose it to the editor you could expose an array of resources to the inspector, it was improved recently so you can certainly show this with an easy to use UI.
|
I'm going to push up what I have (it mostly works) but I think there's a few problems with the resource method atm. I'll detail it more in a response... |
158c0dc
to
6a4776c
Compare
Quick update, I have made text effects a resource type now named There are a few issues I'm having right now regarding how to streamline the user experience of making and sharing text effects though. Ideally, I'd actually like to be able to let users attach scripts to a I've also added a Let me know what you think of these changes. The example project has also been updated to reflect the new system, but please let me know if you're having problems with that testing project. |
6676845
to
eb0e5e1
Compare
Very nice. X) I wish things like these were also modules so it wouldn't have to wait for 3.2. |
(I'm not sure if you're allowed to leave comments on pull requests so forgive me if I'm being rude but since @avencherus posted one I now have an excuse) |
looks really cool, |
Since text effects themselves are resources, you should be able to easily share your own rendering style with other users and across projects that use a RichTextLabel node. Any more advanced rendering needs can be handled as a plugin but it should be noted that the RichTextEffect resource is a very simple class that could be reused for any custom text rendering system you have designed. There could be gains to simplifying the RichTextLabel class for more predictable behaviour and better extensibility, but I believe that this solution for text effects is simple enough that any redesign or fork could use the same basic logic. The only issue I have right now is that the user experience of making a Resource + Script could be streamlined a tad, I'll continue to look into that. |
this is absolutely fantastic! :) would be very excited to see it in godot. |
eb0e5e1
to
d85bd93
Compare
I've gone ahead and fixed the merge conflicts. Now that 3.1 is out and about, I'll continue to push changes to this branch to try to make the user experience better. @Zylann , sorry to request for more help, but I was hoping to get your opinion on something. Currently the resource method works, but it sometimes feels a bit overkill to make a The alternative solution I have to simply allow a list of gd script files, and manually attach them to |
@THEYOKAI if added by code (with |
@THEYOKAI Haven't had the fullest opportunity to test it, but in the demo when you turn off the time related parameter, the results stop. Wondering if maybe you'd want to reset the time in those case. Like in Shake text, turned the shake rate to 0. |
Corrected some of the snake_casing that I missed in my previous commit. @akien-mga Regarding the stress testing, I have actually tested by animating visible_character and I haven't found any major slowdown caused by the animation of any parameters. Examples of this, including a project with variable sized texts, can be found in my test project. Regarding Chinese text, I can try, though I'm not actually sure how Chinese text should change the performance outside of maybe taking slightly more time to draw due to slightly larger datatype size (UTF8 vs UTF16, I would presume?). I haven't tried that yet though, so I may as well give it a try and see how it changes anything / if it changes anything. Of course, the important part of the testing I've done so far is that if you don't use any rich text effects, you will not endure any of the performance cost that comes with the real time effects. Also, having a lot of different effects at once may affect performance since manually running each script comes with an inherit runtime cost. I would assume that GDNative implementations of text effect would similarly be less costly though, so I don't think that it should be an issue. edit: Also, yes, I will squash all of the commits. I will probably do that soon now that I no longer need the revision history (I tend to squash as I get reassured I won't have to step back, which I'm getting there now.) |
Added a new ItemFX type to RichTextLabel which supports dynamic text effects. RichTextEffect Resource Type was added which can be extended for more real time text effects.
3623bbe
to
feedd6c
Compare
This branch has now been rebased / cleaned. I've tested it a few different ways and I don't seem to have any significant problems on my end. |
Thanks! |
This looks awesome thanks! I just want to ask, how are making the text display one character at a time? |
I have a timer set up to increment the visible text number on every tick. If you want to fully explore it, you can find the example project source code on my git repository: https://github.com/Eoin-ONeill-Yokai/Godot-Rich-Text-Effect-Test-Project |
@Eoin-ONeill-Yokai We should add a project to godot-demo-projects to demonstrate the new RichTextLabel features 🙂 How many changes would be required for it to become an official demo? |
I'm sure it could be done. I imagine I could just pull the godot example
projects repository and add my project repo as a sub repo. I'll try that
later tonight.
…On Wed, Sep 4, 2019, 4:32 PM Hugo Locurcio ***@***.***> wrote:
@Eoin-ONeill-Yokai <https://github.com/Eoin-ONeill-Yokai> We should add a
project to demonstrate the new RichTextLabel features to the
godot-demo-projects <https://github.com/godotengine/godot-demo-projects>
repository 🙂
How many changes would be required for it to become an official demo?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#23658?email_source=notifications&email_token=AAXGIYCDV3O6MZYCHDFWGX3QIBAPDA5CNFSM4GDDERLKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD55KKVI#issuecomment-528131413>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAXGIYDLXHDRGYZVLNFIYG3QIBAPDANCNFSM4GDDERLA>
.
|
@Eoin-ONeill-Yokai Out of curiosity, what purpose does |
Indeed, it might not be necessary. In @skyace65's PR adding the above examples to the docs, the docs actually didn't work as The PR #20627 adding that Dictionary method was merged a few days after this PR, which can explain why @Eoin-ONeill-Yokai missed it and implemented it ad hoc in |
Yeah, it can be removed now. I simply implemented it on my own as I didn't have it available to me at the time. Nice catch @Calinou and @akien-mga. It does mean that you'll have to |
@Calinou or @akien-mga , Should I personally handle the removal of the duplicate |
Thanks for the reminder, I'll do it. (Otherwise it would be fine for you or anyone else to do a PR too, but now that I'm on it I'll just push the removal.) |
See #23658 (comment) The method was implemented back when Dictionary.get(key, default) did not exist, but now that it does we do not need a custom method in CharFXTransform. It's a new feature in 3.2, so does not break compat with 3.1.x.
Ok... I'll probably get to updating some of my example code on my repository to work with the changes in the future (This weekend?). |
See godotengine#23658 (comment) The method was implemented back when Dictionary.get(key, default) did not exist, but now that it does we do not need a custom method in CharFXTransform. It's a new feature in 3.2, so does not break compat with 3.1.x.
Are there instructions on how to add custom effects to a project? This tutorial doesn't work for me: https://www.youtube.com/watch?v=o-cLQ7J1mc8 |
@naturally-intelligent You might want to take a look at my repository of example scripts. I think there are definitely ways the process could be streamlined though. |
Thanks Eoin, I have studied your project! My problem is I don't understand the process of adding a custom effect script to a Godot project so that it is recognized by a RichTextLabel. |
…eviously identical) Confusingly, these two properties had identical descriptions even though they measure different things. "relative_index" measures character count from the custom effect's bbcode opening tag. "absolute_index" measures character count from the start of the bbcode text that includes the custom effect. See the code author's own explanation here: godotengine#23658 NOTE: Doco for CharFXTransform.xml has changed significantly in 4.0, where terminology has changed to "glyph". Therefore, proposing this change for 3.x branch only. (cherry picked from commit 89cebd7)
Summary
This PR adds a new
ItemFX
type toRichTextLabel
which supports real time text effects. This also adds the ability to add additional bbcode commands using customRichTextEffect
extensions (inspired by: #23135 ).I will need to write more documentation on this when/if it gets approved as a new feature. Here's a quick rundown of the two features:
You can download the example project for this commit here: RichTextEffects.zip. This is the best way to experience the changes made via this commit, but some gfycat examples are linked below.
New Real Time Text Effects
Real time effects will update and draw every frame.
ItemFX
typed effects will automatically enableset_process
when found in a bbcode string. This means that theRichTextLabel
will only need to process every frame if a dynamic text effect is being used.Wave
[center]Here's a look at the [wave amp=50 freq=2]wave text effect[/wave].[/center]
Text will wave up and down on the Y axis based on its relative X position.
amp=
The amplitude of the wave.freq=
The frequency of the wave.Tornado
[center]Here's a look at the [tornado radius=5 freq=5]tornado[/tornado] text effect.[/center]
Text will move in a circular fashion. Each characters position on the circumference will be determined by their x position, creating an interesting ripple effect.
radius=
The radius of the circle which controls its offset.freq=
The frequency of full circle motions.Shake
[center]Here's a look at the [shake rate=15 level=10]shake[/shake] text effect.[/center]
rate=
How often the text relocateslevel=
How far the text is offset from its originFade
[center]Here's a look at the [fade start=4 length=14]fade text effect...[/fade][/center]
Fades out the text based on a starting position and a length value.
start=
The starting position the falloff. Relative to where fade command is inserted.length=
Over how many characters should the fade out take place. (Rough falloff control.)Rainbow
[center]Here's a look at the [rainbow freq=0.2]rainbow[/rainbow] text effect.[/center]
Gives the text a rainbow color assignment based on x position and time.
freq=
The number of full rainbow cycles per second.sat=
Saturation of rainbow.val=
Value (e.g. brightness) of rainbow.Custom BBCodes and Text Effects
You can now extend the
RichTextEffect
resource type to create your own custom BBCodes. You can view the example project for better details, but here's a rough example below.Extend:
You begin by extending the
RichTextEffect
resource type. Add thetool
prefix to your gdscript file if you wish to have these custom effects run within the editor itself. The RichTextLabel does not need to have a script attached, nor does it need to be running intool
mode.Here are some examples of custom effects:
Ghost
Pulse
Matrix
There is only one function you need to extend named
_process_custom_fx(char_fx)
. Optionally, you can also provide a custom bbcode identifier simply by adding a member name bbcode. The code will check the bbcode automagically or will simply use the name of the file to determine what the bbcode should be._process_custom_fx
.This is where the logic of each effect takes place and is called once per character during the draw phase of text rendering. This passes in a
CharFXTransform
object, which holds a few variables that control how the associated character is rendered. The first isidentity
, which will specify which custom effect is being processed. You should use that for code flow control.relative_index
will tell you how far into a given custom effect block you are in as an index.absolute_index
will tell you how far into the entire text you are as an index.elapsed_time
is the total amount of time the text effect has been running.visible
will tell you whether the character is visible or not and will also allow you to hide a given portion of text.offset
is an offset position relative to where given character should render under normal circumstances.color
is the color of a given character. There's alsoenv
which is a dictionary of variables assigned to a given custom effect (for an example look at the code above). The last thing to note about this function is that it is necessary to return a booleantrue
value to verify that the effect processed correctly. This way, if there's a problem with rendering a given character, it will back out of rendering custom effects entirely until the user fixes whatever error cropped up in their custom effect logic.This will add a few new bbcode commands, which can be used like so: