Files
Dawn-Godot/ui/component/advancedrichtext/AdvancedRichText.gd
2025-09-15 00:40:58 -05:00

105 lines
2.7 KiB
GDScript

@tool
class_name AdvancedRichText extends RichTextLabel
@export_multiline var userText:String = "" # The text the user is asking for
@export_multiline var finalText:String = "" # The final text after processing (translation, wrapping, etc.)
# Hides the original RichTextLabel text property
func _set(property: StringName, value) -> bool:
if property == "text":
userText = value
_recalcText()
return true
elif property == "richtextlabel_text":
text = value
return true
return false
func _get(property: StringName):
if property == "text":
return userText
elif property == "richtextlabel_text":
return text
return null
@export var translate:bool = true:
set(value):
translate = value
_recalcText()
get():
return translate
@export var smartWrap:bool = true:
set(value):
smartWrap = value
_recalcText()
get():
return smartWrap
func _init() -> void:
_recalcText()
func _enter_tree() -> void:
_recalcText()
self.resized.connect(_recalcText)
func _exit_tree() -> void:
self.resized.disconnect(_recalcText)
func _recalcText() -> void:
if userText.is_empty():
self.richtextlabel_text = ""
return
# Translate if needed
var textTranslated = userText
if self.translate:
textTranslated = tr(textTranslated)
# Replace input bb tags.
var regex = RegEx.new()
regex.compile(r"\[input action=(.*?)\](.*?)\[/input\]")
var inputIconText = textTranslated
for match in regex.search_all(textTranslated):
var action = match.get_string(1).to_lower()
var height:int = get_theme_font_size("normal_font_size")
# var device = get_current_device_type()
# var icon_path = get_icon_for_action(action, device)
var img_tag = "[img height=%d valign=center,center]res://ui/input/%s.tres[/img]" % [ height, action ]
inputIconText = inputIconText.replace(match.get_string(0), img_tag)
# Perform smart wrapping
var wrappedText = inputIconText
if smartWrap:
var unwrappedText = wrappedText.strip_edges()
self.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART;
self.richtextlabel_text = unwrappedText
self.visible_characters = -1;
self.fit_content = true;
var newlineIndexes = [];
# Determine where the wrapped newlines are
var line = 0;
var wasNewLine = false;
for i in range(0, unwrappedText.length()):
var tLine = self.get_character_line(i);
if tLine == line || tLine == -1:
wasNewLine = false
if unwrappedText[i] == "\n":
wasNewLine = true
continue;
if !wasNewLine:
newlineIndexes.append(i);
line = tLine;
# Create fake pre-wrapped text.
wrappedText = "";
for i in range(0, unwrappedText.length()):
if newlineIndexes.find(i) != -1 and i != 0:
wrappedText += "\n";
wrappedText += unwrappedText[i];
finalText = wrappedText
self.richtextlabel_text = wrappedText