Search code examples
vertical-alignmentgodotbbcode

Godot: How to vertically align bbcode


is there a way to vertically align the text like this using bbcode?

[img=16]res://icon.png[/img] Hello World

enter image description here


Solution

  • Sadly Godot does not have any BBCode tags for vertical alignment. As a result there is no straight forward way to vertically center. But there are some things we can do…


    Default: text at the bottom

    As you have seen, you get the text at the bottom of the image by default with this:

    [img=16]res://icon.png[/img]Hello World
    

    Table: text at the top

    We can get the text at the top if we use a table, like this:

    [table=2][cell][img=16]res://icon.png[/img][/cell][cell]Hello World[/cell][/table]
    

    Then you could use new lines to move it down (or you can combine this with the custom tag below). I'd argue this is more versatile solution.


    Trick to move image vertically

    The documentation suggest this trick: we can create an empty BitmapFont resource, and give it some positive ascent. Then show the image with that font.

    In my case I create a font called v.tres, so my BBCode for this is the following:

    [font=v.tres][img=16]res://icon.png[/img][/font]Hello World
    

    The result is moving the image up that many pixels as we said in ascent. And presumably you can figure out how much to move the image up to get the alignment you want (And yes, this would mean different BitmapFont resource for different values of ascent).


    Custom tag to move text vertically

    Godot allows to define custom BBCode tag, so let use that to move the text vertically.

    I will show how to make this work:

    [img=16]icon.png[/img][valign px=8]Hello World[/valign]
    

    First create a valign.gd script with this code:

    tool class_name RichTextVAlign extends RichTextEffect
    
    var bbcode := "valign"
    
    func _process_custom_fx(char_fx:CharFXTransform) -> bool:
        char_fx.offset = Vector2.UP * char_fx.env.get("px", 0.0)
        return true
    

    See that we are reading a px attribute, with default value of 0.0 with char_fx.env.get("px", 0.0), and we use that value to displace the text by setting char_fx.offset.

    And then in the RichTextLabel add a new RichTextVAlign (which is the class we created) to the custom_effects property.

    Keep in mind we are moving the baseline of the text (if you are doing this inside the table approach described earlier, you can think of it as moving the top of the text. Yes, use negatives to move it down). We have no way to get the height of the block of text.