godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.16k stars 97 forks source link

Let RichTextEffect change the font and content #3450

Open Ryhon0 opened 3 years ago

Ryhon0 commented 3 years ago

Describe the project you are working on

BBCode input prompt that gets events from an action map, e.g. Press [action]use[/action] to use would show "Press E/(X) to use"

Describe the problem or limitation you are having in your project

There's no way to create custom BBCode tags, which would change the font or function like the [img] tag. There's also no way to modify the content of a tag, the closest thing would be the visible and character properties in CharFXTransform, however you can't make the content longer with this method.

Describe the feature / enhancement and how it helps to overcome the problem or limitation

You will be able to change the font and content of a custom text effect

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

Add a font property of the Font resource type to the CharFXTransform class and a virtual method called _process_content , which takes and returns a string and is called once before processing the custom effect for every character.

If this enhancement will not be used often, can it be worked around with a few lines of script?

It can be worked around by writing your own BBCode parser and generating a new BBCode for the RichTextLabel.

Is there a reason why this should be core and not an add-on in the asset library?

Changing the font using custom text effects feels like a basic feature, processing the content would be a nice addition.

dalexeev commented 3 years ago

Press [action]use[/action] to use would show "Press E/(X) to use"

Press {action_use} to use. There is the String.format method and other ways you can preprocess the text.

Ryhon0 commented 3 years ago

I want it to be controller button icons using a custom bitmap font

dalexeev commented 3 years ago

You can substitute any BBCode there.

var source = "Press {action_use} to use" # Or tr("PRESS_TO_USE")
$RTL.bbcode_text = source.format({
    action_use = "[img]res://icon.png[/img][font=res://font.font]" + use_key + "[/font]",
})
Qubus0 commented 2 months ago

Changing the font is possible now (tested in 4.3 stable), just a bit cumbersome and with some slight kerning issues as the new font keeps the kerning of the old one. If you use an icon font, you should be able to use it to also insert images.

image
@tool
extends RichTextEffect
class_name RichTextCustom

const bbcode := "custom"

# If it spams errors when changing the font, quickly reload the current scene before it lags
const custom_font := preload("res://some_font.ttf")

func _process_custom_fx(char_fx: CharFXTransform):
    var current_char := glyph_index_to_char(char_fx)
    char_fx.glyph_index = char_to_glyph_index(custom_font.get_rids()[0], current_char)
    char_fx.font = custom_font.get_rids()[0]

    return true

static func get_text_server():
    return TextServerManager.get_primary_interface()

static func char_to_glyph_index(font : RID, c : int) -> int:
    return get_text_server().font_get_glyph_index(font, 1, c, 0)

static func glyph_index_to_char(char_fx : CharFXTransform) -> int:
    return get_text_server().font_get_char_from_glyph_index(char_fx.font, 1, char_fx.glyph_index)

credits to https://github.com/teebarjunk/godot-text_effects for those utility methods