BBCode en RichTextLabel

Introducción

Los nodos de la etiqueta son geniales para mostrar el texto básico, pero tienen límites. Si quieres cambiar el color del texto, o su alineación, ese cambio afecta a todo el texto del nodo Label. No puedes hacer que sólo una parte del texto sea de un color, o que sólo una parte del texto esté centrada. Para sortear esta limitación usarías un RichTextLabel.

RichTextLabel permite la visualización de marcas de texto complejas en un Control. Tiene una API incorporada para generar el marcado, pero también puede analizar un BBCode.

Nótese que las etiquetas de BBCode también pueden ser usadas, hasta cierto punto, en el XML source of the class reference.

Usando BBCode

Para un texto con formato uniforme se puede escribir en la propiedad "Text", pero si se desea utilizar el marcado BBCode se debe utilizar la propiedad "Text" en la sección "Bb Code" (bbcode_text). Al escribir en esta propiedad se activará el análisis sintáctico de su marcado para dar formato al texto según lo solicitado. Antes de que esto ocurra, necesita activar la casilla de verificación "Enabled" en la sección "Bb Code" (bbcode_enabled).

../../_images/bbcodeText.png

Por ejemplo, "BBCode [color=blue]blue[/color]`` haría que la palabra "blue" tuviera un color azul.

../../_images/bbcodeDemo.png

Notarán que después de escribir en la propiedad "Texto" del BBCode, la propiedad "Texto" normal ahora tiene el texto sin el BBCode. Mientras que la propiedad "Text" será actualizada por la propiedad BBCode, no puedes editar la propiedad texto o perderás el marcado BBCode. Todos los cambios en el texto deben hacerse en el parámetro BBCode.

Nota

Para que las etiquetas BBCode como [b] (negrita), [i] (cursiva) o [código] funcionen, debes configurar primero las fuentes personalizadas para el nodo RichTextLabel.

Todavía no hay etiquetas BBCode para controlar el centrado vertical del texto.

Referencia

Comando

Etiqueta

Descripción

negrita

[b]{text}[/b]

Hace {text} más oscuro.

cursiva

[i]{text}[/i]

Hace {text) cursiva.

Subrayado

[u]{text}[/u]

Subraya el {text}.

tachado

[s]{text}[/s]

Tachar el {text).

codigo

[code]{text}[/code]

Hace que {text} utilice la fuente del código (que es típicamente monoespacio).

centrado

[center]{text}[/center]

Centra horizontalmente el {text}.

derecho

[right]{text}[/right]

Centra horizontalmente al {text} a la derecha.

llenar

[fill]{text}[/fill]

Hace que el {text} se expanda a lo ancho del RchTextLabel.

indentar

[indent]{text}[/indent]

Aumentar el nivel de indentación del {text}.

url

[url]{url}[/url]

Mostrar {url} como tal, subrayarlo y hacerlo clickable. Debe ser manejado con la señal "meta_clicked" para tener efecto. Ver El manejo de clics de la etiqueta [url].

url (ref)

[url=<url>]{text}[/url]

Hace que {texto} haga referencia a <url> (subrayado y clickeable). Debe ser manejado con la señal "meta_clicked" para tener efecto. Ver El manejo de clics de la etiqueta [url].

imagen

[img]{path}[/img]

Inserte la imagen en el recurso {path}.

imagen redimensionada

[img=<width>]{path}[/img]

Insertar la imagen en el recurso {path} usando <width> (mantiene la proporción).

imagen redimensionada

[img=<ancho>x<altura>]{path}[/img]

Insertar la imagen en el recurso {path} usando <ancho>×<alto>.

fuente

[font=<path>]{texto}[/font]

Usa la fuente personalizada en <path> para {text}.

color

[color=<code/name>]{text}[/color]

Cambia el color del {text}; usa el nombre o el formato #, como #ff00ff.

tabla

[table=<number>]]{cells}[/table]

Crea una tabla con un <number> de columnas.

celda

[cell]{text}[/cell]

Añade celdas con el {texto} a la tabla.

Nombres de colores incorporados

Lista de nombres de colores válidos para la etiqueta [color=<nombre>]:

  • agua

  • negro

  • azul

  • fucsia

  • gris

  • verde

  • lima

  • granate

  • azul marino

  • violeta

  • red

  • plata

  • verde azulado

  • Blanco

  • Amarillo

Códigos Hexadecimales de color

Para colores RGB opacos, se admiten códigos hexadecimales válidos de 6 dígitos, por ejemplo, [color=#ffffff]blanco[/color]. También se admiten códigos de color RGB cortos como #6f2 (equivalente a #66ff22).

Para colores RGB transparentes, se puede usar cualquier código hexadecimal de 8 dígitos, por ejemplo, [color=#88ffffff]blanco translúcido[/color]. En este caso, debes tener en cuenta que el canal alfa es el primero componente del código de color, no el último. También se admiten códigos de color RGBA cortos como #86f2 (equivalente a #8866ff22).

El manejo de clics de la etiqueta [url]

Por defecto, las etiquetas [url] no hacen nada cuando se hace clic en ellas. Esto permite un uso flexible de las etiquetas [url] en lugar de limitarlas a la apertura de URL en un navegador web.

Para manejar las etiquetas [url] cuando se hace clic en ellas, conecta la señal meta_clicked del nodo RichTextLabel a una función de script.

Por ejemplo, el siguiente método puede ser conectado a meta_clicked para abrir las URLs clickeadas utilizando el navegador web predeterminado del usuario:

# This assumes RichTextLabel's `meta_clicked` signal was connected to
# the function below using the signal connection dialog.
func _richtextlabel_on_meta_clicked(meta):
    # `meta` is not guaranteed to be a String, so convert it to a String
    # to avoid script errors at run-time.
    OS.shell_open(str(meta))

Para casos de uso más avanzados, también es posible almacenar JSON en la opción de una etiqueta [url] y analizarlo en la función que maneja la señal meta_clicked. Por ejemplo: [url={"ejemplo": "valor"}]JSON[/url]

Desplazamiento vertical de la imagen

Utilizas una fuente personalizada para tu imagen para alinearla verticalmente.

  1. Crear un recurso BitmapFont

  2. Ponga esta fuente de mapa de bits con un valor positivo para la propiedad ascent, que es su desplazamiento de altura

  3. Ponga la etiqueta BBCode de esta manera: [font=<font-path>][img]{image-path}[/img][/font]

Efectos de animación

BBCode también puede ser usado para crear diferentes efectos de animación de texto. Se proporcionan cinco efectos personalizables fuera de la caja, y puedes crear fácilmente los tuyos propios.

Ola

../../_images/wave.png

La onda hace que el texto suba y baje. Su formato de etiqueta es [wave amp=50 freq=2][/wave]. amp controla cuán alto y bajo va el efecto, y freq controla cuán rápido el texto sube y baja.

Tornado

../../_images/tornado.png

El tornado hace que el texto se mueva en un círculo. Su formato de etiqueta es [tornado radius=5 freq=2][/tornado]. radius es el radio del círculo que controla el desplazamiento, freq es la velocidad con la que el texto se mueve en un círculo.

Agitado

../../_images/shake.png

Agitar hace que el texto tiemble. Su formato de etiqueta es [Shake rate=5 level=10][/shake]. rate controla la rapidez con que el texto se agita, level controla la distancia del texto desde el origen.

Desaparecer

../../_images/fade.png

El fundido crea un efecto de desvanecimiento sobre el texto que no está animado. Su formato de etiqueta es [fade start=4 length=14][/fade]. start controla la posición inicial de la caída relativa a donde se inserta el comando fade, length controla sobre cuántos caracteres debe tener lugar el desvanecimiento.

Arcoiris

../../_images/rainbow.png

El arcoiris le da al texto un color de arco iris que cambia con el tiempo. Su formato de etiqueta es [rainbow freq=0.2 sat=10 val=20][/rainbow]. "freq" es el número de ciclos completos del arcoiris por segundo, "sat" es la saturación del arcoiris, "val" es el valor del arcoiris.

Etiquetas BBCode personalizadas y efectos de texto

Puedes extender el tipo de recurso RichTextEffect para crear tus propias etiquetas personalizadas de BBCode. Comienza extendiendo el tipo de recurso RichTextEffect. Agrega el prefijo tool a tu archivo GDScript si deseas que estos efectos personalizados se ejecuten dentro del propio editor. El RichTextLabel no necesita tener un script adjunto, ni tampoco necesita estar en modo tool. El nuevo efecto se podrá activar en el Inspector a través de la propiedad Efectos Personalizados (Custom Effects).

Advertencia

Si el efecto personalizado no está registrado dentro de la propiedad Efectos Personalizados (Custom Effects) de RichTextLabel, no se mostrará ningún efecto y la etiqueta original se mantendrá como está.

Sólo hay una función que necesita extenderse: _process_custom_fx(char_fx). Opcionalmente, también puede proporcionar un identificador personalizado de BBCode simplemente añadiendo un nombre de miembro bbcode. El código comprobará la propiedad bbcode automáticamente o utilizará el nombre del archivo para determinar cuál debe ser la etiqueta BBCode.

_process_custom_fx

Aquí es donde la lógica de cada efecto tiene lugar y se llama una vez por carácter durante la fase de dibujo de la representación del texto. Esto pasa en un objeto CharFXTransform, que contiene unas pocas variables para controlar cómo se renderiza el carácter asociado:

  • identity especifica qué efecto personalizado se está procesando. Deberías usar eso para el control del flujo de códigos.

  • relative_index te dice cuán lejos estás en un bloque de efectos personalizados como índice.

  • absolute_index te dice dónde estás en el texto completo como un índice absoluto.

  • elapsed_time es la cantidad total de tiempo que el efecto de texto ha estado funcionando.

  • visible te dirá si el personaje es visible o no y también te permitirá ocultar una parte determinada del texto.

  • offset es una posición de desplazamiento relativa a donde el carácter dado debe presentarse en circunstancias normales.

  • El color es el color de un personaje determinado.

  • Por último, env es un Dictionary de parámetros asignados a un efecto personalizado dado. Puede utilizar get() con un valor predeterminado opcional para recuperar cada parámetro, si así lo especifica el usuario. Por ejemplo [custom_fx spread=0.5 color=#FFFF00]test[/custom_fx] tendría un parámetro real spread y de color color en su diccionario env. Vea abajo para más ejemplos de uso.

Lo último que hay que señalar de esta función es que es necesario devolver un valor booleano true para verificar que el efecto se procesó correctamente. De esta manera, si hay un problema con la renderización de un carácter dado, se retirará por completo de la renderización de los efectos personalizados hasta que el usuario arregle cualquier error surgido en su lógica de efectos personalizados.

Aquí hay unos ejemplos de efectos personalizados:

Fantasma

tool
extends RichTextEffect
class_name RichTextGhost

# Syntax: [ghost freq=5.0 span=10.0][/ghost]

# Define the tag name.
var bbcode = "ghost"

func _process_custom_fx(char_fx):
    # Get parameters, or use the provided default value if missing.
    var speed = char_fx.env.get("freq", 5.0)
    var span = char_fx.env.get("span", 10.0)

    var alpha = sin(char_fx.elapsed_time * speed + (char_fx.absolute_index / span)) * 0.5 + 0.5
    char_fx.color.a = alpha
    return true

Pulso

tool
extends RichTextEffect
class_name RichTextPulse

# Syntax: [pulse color=#00FFAA height=0.0 freq=2.0][/pulse]

# Define the tag name.
var bbcode = "pulse"

func _process_custom_fx(char_fx):
    # Get parameters, or use the provided default value if missing.
    var color = char_fx.env.get("color", char_fx.color)
    var height = char_fx.env.get("height", 0.0)
    var freq = char_fx.env.get("freq", 2.0)

    var sined_time = (sin(char_fx.elapsed_time * freq) + 1.0) / 2.0
    var y_off = sined_time * height
    color.a = 1.0
    char_fx.color = char_fx.color.linear_interpolate(color, sined_time)
    char_fx.offset = Vector2(0, -1) * y_off
    return true

Matriz

tool
extends RichTextEffect
class_name RichTextMatrix

# Syntax: [matrix clean=2.0 dirty=1.0 span=50][/matrix]

# Define the tag name.
var bbcode = "matrix"

func _process_custom_fx(char_fx):
    # Get parameters, or use the provided default value if missing.
    var clear_time = char_fx.env.get("clean", 2.0)
    var dirty_time = char_fx.env.get("dirty", 1.0)
    var text_span = char_fx.env.get("span", 50)

    var value = char_fx.character

    var matrix_time = fmod(char_fx.elapsed_time + (char_fx.absolute_index / float(text_span)), \
                           clear_time + dirty_time)

    matrix_time = 0.0 if matrix_time < clear_time else \
                  (matrix_time - clear_time) / dirty_time

    if value >= 65 && value < 126 && matrix_time > 0.0:
        value -= 65
        value = value + int(1 * matrix_time * (126 - 65))
        value %= (126 - 65)
        value += 65
    char_fx.character = value
    return true

Esto agregará unos nuevos comandos BBCode que pueden ser usados de este modo:

[center][ghost]This is a custom [matrix]effect[/matrix][/ghost] made in
[pulse freq=5.0 height=2.0][pulse color=#00FFAA freq=2.0]GDScript[/pulse][/pulse].[/center]