2025-03-18 21:32:11 +02:00

241 lines
6.8 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

local component = require("druid.component")
local rich_text = require("druid.custom.rich_text.module.rt")
---@class druid.rich_text.settings
---@field parent node
---@field size number
---@field fonts table<string, string>
---@field scale vector3
---@field color vector4
---@field shadow vector4
---@field outline vector4
---@field position vector3
---@field image_pixel_grid_snap boolean
---@field combine_words boolean
---@field default_animation string
---@field text_prefab node
---@field adjust_scale number
---@field default_texture string
---@field is_multiline boolean
---@field text_leading number
---@field font hash
---@field width number
---@field height number
---@class druid.rich_text.word
---@field node node
---@field relative_scale number
---@field source_text string
---@field color vector4
---@field text_color vector4
---@field position vector3
---@field offset vector3
---@field scale vector3
---@field size vector3
---@field metrics druid.rich_text.metrics
---@field pivot userdata
---@field text string
---@field shadow vector4
---@field outline vector4
---@field font string
---@field image druid.rich_text.word.image
---@field br boolean
---@field nobr boolean
---@class druid.rich_text.word.image
---@field texture string
---@field anim string
---@field width number
---@field height number
---@class druid.rich_text.style
---@field COLORS table<string, vector4>
---@field ADJUST_STEPS number
---@field ADJUST_SCALE_DELTA number
---@class druid.rich_text.lines_metrics
---@field text_width number
---@field text_height number
---@field lines table<number, druid.rich_text.metrics>
---@class druid.rich_text.metrics
---@field width number
---@field height number
---@field offset_x number|nil
---@field offset_y number|nil
---@field node_size vector3|nil
---The component that handles a rich text display, allows to custom color, size, font, etc. of the parts of the text
---@class druid.rich_text: druid.component
---@field root node The root node of the rich text
---@field text_prefab node The text prefab node
---@field private _last_value string The last value of the rich text
---@field private _settings table The settings of the rich text
local M = component.create("rich_text")
---@param text_node node|string The text node to make Rich Text
---@param value string|nil The initial text value. Default will be gui.get_text(text_node)
function M:init(text_node, value)
self.root = self:get_node(text_node)
self.text_prefab = self.root
self._last_value = value or gui.get_text(self.text_prefab)
self._settings = self:_create_settings()
gui.set_text(self.root, "")
if value then
self:set_text(value)
end
end
---@private
function M:on_layout_change()
if self._last_value then
self:set_text(self._last_value)
end
end
---@private
---@param style druid.rich_text.style
function M:on_style_change(style)
self.style = {
COLORS = style.COLORS or {},
ADJUST_STEPS = style.ADJUST_STEPS or 20,
ADJUST_SCALE_DELTA = style.ADJUST_SCALE_DELTA or 0.02,
}
end
---Set text for Rich Text
--- rich_text:set_text("color=redFoobar/color")
--- rich_text:set_text("color=1.0,0,0,1.0Foobar/color")
--- rich_text:set_text("color=#ff0000Foobar/color")
--- rich_text:set_text("color=#ff0000ffFoobar/color")
--- rich_text:set_text("shadow=redFoobar/shadow")
--- rich_text:set_text("shadow=1.0,0,0,1.0Foobar/shadow")
--- rich_text:set_text("shadow=#ff0000Foobar/shadow")
--- rich_text:set_text("shadow=#ff0000ffFoobar/shadow")
--- rich_text:set_text("outline=redFoobar/outline")
--- rich_text:set_text("outline=1.0,0,0,1.0Foobar/outline")
--- rich_text:set_text("outline=#ff0000Foobar/outline")
--- rich_text:set_text("outline=#ff0000ffFoobar/outline")
--- rich_text:set_text("font=MyCoolFontFoobar/font")
--- rich_text:set_text("size=2Twice as large/size")
--- rich_text:set_text("br/Insert a line break")
--- rich_text:set_text("nobrPrevent the text from breaking")
--- rich_text:set_text("img=texture:imageDisplay image")
--- rich_text:set_text("img=texture:image,sizeDisplay image with size")
--- rich_text:set_text("img=texture:image,width,heightDisplay image with width and height")
---@param text string|nil The text to set
---@return druid.rich_text.word[] words
---@return druid.rich_text.lines_metrics line_metrics
function M:set_text(text)
text = text or ""
self:clear()
self._last_value = text
local words, settings, line_metrics = rich_text.create(text, self._settings, self.style)
line_metrics = rich_text.adjust_to_area(words, settings, line_metrics, self.style)
self._words = words
self._line_metrics = line_metrics
return words, line_metrics
end
---Get the current text of the rich text
---@return string text The current text of the rich text
function M:get_text()
return self._last_value
end
---@private
function M:on_remove()
gui.set_scale(self.root, self._default_scale)
gui.set_size(self.root, self._default_size)
self:clear()
end
---Clear all created words.
function M:clear()
if self._words then
rich_text.remove(self._words)
self._words = nil
end
self._last_value = nil
end
---Get all words, which has a passed tag.
---@param tag string The tag to get the words for
---@return druid.rich_text.word[] words The words with the passed tag
function M:tagged(tag)
if not self._words then
return {}
end
return rich_text.tagged(self._words, tag)
end
---Get all current created words, each word is a table that contains the information about the word
---@return druid.rich_text.word[]
function M:get_words()
return self._words
end
---Get the current line metrics
---@return druid.rich_text.lines_metrics lines_metrics The line metrics of the rich text
function M:get_line_metric()
return self._line_metrics
end
---@private
---@return table settings The settings of the rich text, they are created based on the root node on the GUI scene
function M:_create_settings()
local root_size = gui.get_size(self.root)
local scale = gui.get_scale(self.root)
self._default_size = root_size
self._default_scale = scale
root_size.x = root_size.x * scale.x
root_size.y = root_size.y * scale.y
gui.set_size(self.root, root_size)
gui.set_scale(self.root, vmath.vector3(1))
return {
-- General settings
-- Adjust scale using to fit the text to the root node area
adjust_scale = 1,
parent = self.root,
scale = scale,
width = root_size.x,
height = root_size.y,
combine_words = false, -- disabled now
text_prefab = self.text_prefab,
pivot = gui.get_pivot(self.root),
-- Text Settings
shadow = gui.get_shadow(self.root),
outline = gui.get_outline(self.root),
text_leading = gui.get_leading(self.root),
is_multiline = gui.get_line_break(self.root),
-- Image settings
image_pixel_grid_snap = false, -- disabled now
}
end
return M