I use meta_clicked to show players what Turn Sequence means. This is sample RichText bbCode value. All works great when players click the “hyperlink”
But I would like to make this “hyperlink” more interactive. When user hovers mouse on the “Turn Sequence” from above, I would like it to change color. The tricky part is I do not want to change color of entire RichText , but only the actual “hyperlink”.
Signals work. But what should I do to actually change the color of the hyperlink? (or give some other visual that will tell players this field can be clicked or is interactive).
I tried to look into documentation of meta_push , but I could not make it work .
* [color={{meta1}}][url=meta1]Something like this[/url][/color]: Thing here
* [color={{meta2}}][url=meta2]Something like this[/url][/color]: Thing here
extends RichTextLabel
@export var hover_colors: Dictionary[String, Color]
@onready var original_text = text
func _ready() -> void:
_set_meta_color(null)
meta_hover_started.connect(_set_meta_color.bind(true))
meta_hover_ended.connect(_set_meta_color.bind(false))
func _set_meta_color(meta: Variant, hovering: bool = false, default_color: Color = Color.RED) -> void:
var colors = {}
for key in hover_colors.keys():
if hovering and meta == key:
colors.set(key, hover_colors[key].to_html())
else:
colors.set(key, default_color.to_html())
text = original_text.format(colors, "{{_}}")
But it may not work fine in some cases or may cause the layout to shift. In the video below it’s the one on the top.
Another option is to implement a RichTextEffect and update it when needed. This method will fail to change the color of the underline though.
The RichTextLabel.text is:
* [meta_hover on=blue off=red meta=meta1][url=meta1]Something like this[/url][/meta_hover]: Thing here
* [meta_hover on=green off=yellow meta=meta2][url=meta2]Something like this[/url][/meta_hover]: Thing here
extends RichTextLabel
var meta_hover_effect := MetaHoverEffect.new()
func _ready() -> void:
install_effect(meta_hover_effect)
meta_hover_started.connect(func(meta: Variant):
if not meta_hover_effect.current_metas.has(meta):
meta_hover_effect.current_metas.append(meta)
)
meta_hover_ended.connect(func(meta: Variant):
meta_hover_effect.current_metas.erase(meta)
)
class MetaHoverEffect extends RichTextEffect:
var bbcode = "meta_hover"
var current_metas: Array[String]
func _process_custom_fx(char_fx: CharFXTransform) -> bool:
var meta = char_fx.env.get("meta", null)
var on = char_fx.env.get("on", "red")
var off = char_fx.env.get("off", "red")
if current_metas.has(meta):
char_fx.color = Color.from_string(on, Color.RED)
else:
char_fx.color = Color.from_string(off, Color.RED)
return true
one more question, how would you suggest modifying 2nd method , so it also changes to 3rd color on press? it does not seem there is MetaHoverEffect equivalent for Press or Click
* [meta_hover on=blue off=red click=magenta meta=meta1][url=meta1]Something like this[/url][/meta_hover]: Thing here
* [meta_hover on=green off=yellow click=orange meta=meta2][url=meta2]Something like this[/url][/meta_hover]: Thing here
extends RichTextLabel
var meta_hover_effect := MetaHoverEffect.new()
func _ready() -> void:
install_effect(meta_hover_effect)
meta_hover_started.connect(func(meta: Variant):
if not meta_hover_effect.current_metas.has(meta):
meta_hover_effect.current_metas.append(meta)
)
meta_hover_ended.connect(func(meta: Variant):
meta_hover_effect.current_metas.erase(meta)
)
func _gui_input(event: InputEvent) -> void:
if event is InputEventMouseButton:
if event.button_index == MOUSE_BUTTON_LEFT:
meta_hover_effect.meta_is_clicked = event.pressed
class MetaHoverEffect extends RichTextEffect:
var bbcode = "meta_hover"
var current_metas: Array[String]
var meta_is_clicked: bool = false
func _process_custom_fx(char_fx: CharFXTransform) -> bool:
var meta = char_fx.env.get("meta", null)
var on = char_fx.env.get("on", "red")
var off = char_fx.env.get("off", "red")
var click = char_fx.env.get("click", "red")
if current_metas.has(meta):
if meta_is_clicked:
char_fx.color = Color.from_string(click, Color.RED)
else:
char_fx.color = Color.from_string(on, Color.RED)
else:
char_fx.color = Color.from_string(off, Color.RED)
return true