mirror of
https://github.com/Insality/druid.git
synced 2025-06-27 02:17:52 +02:00
Update Rich text style params
This commit is contained in:
parent
5a0cf42e3d
commit
628723386e
@ -12,3 +12,4 @@ date,sha,version,build_size,build_time,platform,mode,is_cache_using,commits_coun
|
||||
2023-07-05T20:19:22Z,d0062c2a78e618871ebb4c8ee66b1509b763f069,0.10.671,3292,12,x86_64-linux,headless,true,671
|
||||
2023-07-13T18:37:07Z,1cbe57376397a8352bbafcc67de0b6f95ae37b35,0.10.682,2496,53,js-web,release,true,682
|
||||
2023-07-13T19:31:47Z,ea185622702e6691275187741b1e2ee0c7f079ec,0.11.686,2452,51,js-web,release,true,686
|
||||
2023-07-15T12:56:18Z,556e1a9bae620e2df290b10287fa8d0f64d47293,0.11.690,2468,51,js-web,release,true,690
|
||||
|
|
@ -453,38 +453,52 @@ Hello! What a wonderful day for the new **Druid** update!
|
||||
|
||||
Alright, let's get straight to the point. Look at what I have for you!
|
||||
|
||||
**Druid Rich Text** has finally been released. The main difference from the existing **Bjorn's** Rich Text is that all visual parameters are customizable directly in the GUI. This allows you to integrate Rich Text more accurately and quickly. Additionally, this Rich Text aligns pixel perfect (well, almost) with regular GUI text node.
|
||||
**Druid Rich Text** has finally been released. The main difference from the existing **Bjorn's** Rich Text is that all visual parameters are customizable directly in the GUI. This allows you to integrate **Rich Text** more accurately and quickly. Additionally, this **Rich Text** aligns pixel perfect (well, [almost](https://github.com/defold/defold/issues/7197)) with regular GUI text node.
|
||||
|
||||
This version is the most basic one. Honestly, just wanna to publish current version for your and polish it later.
|
||||
This version is the most basic one. Honestly, just wanna to publish current version for your and polish it later. Read [RichText API here](https://insality.github.io/druid/modules/RichText.html)
|
||||
|
||||
Another addition is the ability to enable the "HTML mode" for the Button component. In this mode, the button's action occurs in the context of `user action`, allowing operations like "copy and paste text" "show the keyboard" and more. However, in this mode, the button only responds to regular clicks due to the technical implementation of it (so no double clicks or long taps).
|
||||
Another addition is the ability to enable the "HTML mode" for the Button component. In this mode, the button's action occurs in the context of `user action`, allowing operations like "copy and paste text" "show the keyboard" and more. However, in this mode, the button only responds to regular clicks due to the technical implementation of it (so no double clicks or long taps for this button).
|
||||
|
||||
The huge work was done on documentation. Now it's more clear and have more examples. All documentation now moved to the API section. The separate `componentd.md` file will be deleted soon as all documentation will be moved to the API section.
|
||||
The huge work was done on documentation. Now it's more clear and have more examples. All documentation now moved to the API section. The separate `componentd.md` manual will be deleted soon as all documentation will be moved to the API section.
|
||||
|
||||
The API section now filled with overview and usage examples. I've started with the basic modules, in future I will add more examples for all modules.
|
||||
|
||||
Also, I've added the Unit Tests. It's not cover all **Druid** code, but it's a good start! 🎉
|
||||
Also, I've added the **Unit Tests**. It's not cover all **Druid** code, but it's a good start! 🎉
|
||||
|
||||
I have the feedback form for you, please fill it if you have a free minute. It will help me to improve **Druid** in future. %LINK HERE%
|
||||
|
||||
Have a good day!
|
||||
|
||||
|
||||
**Changelog 0.11.0**
|
||||
|
||||
---
|
||||
|
||||
- **#191**: [RichText] Finally add Druid Rich Text custom component. Component is used to make formatted text in your's GUI. This Rich Text mostly adjusted visually in GUI and have almost pixel-perfect match with similar GUI text node
|
||||
- **#39**: [System] Finally add Unit Tests. Yeah, it cover not all **Druid** code, but it's a good start! 🎉
|
||||
- **#219**: [System] UTF-8 performance optimization. Now Druid will try to use utf8 native extension over lua utf8 library if exists.
|
||||
- **#156**: [Button] Now button can work in HTML5 with html5.set_interaction_listener.
|
||||
- **#191**: [RichText] Finally add **Druid [Rich Text](https://insality.github.io/druid/modules/RichText.html)** custom component. Component is used to make formatted text in your's GUI. This Rich Text mostly adjusted visually in GUI and have almost pixel-perfect match with similar GUI text node
|
||||
- **#39**: [System] Finally add **Unit Tests**. Yeah, it cover not all **Druid** code, but it's a good start! 🎉
|
||||
- **#219**: [System] UTF-8 performance optimization. Now Druid will try to use *utf8* native extension over lua utf8 library if exists. If you wanna use native utf8, just [add the extension](https://github.com/d954mas/defold-utf8) in your `game.project` dependency.
|
||||
- **#156**: [Button] Now button can work in HTML5 with `html5.set_interaction_listener`.
|
||||
- The API is `button:set_html5_user_interaction(true)`. In HTML5 mode button have several restrictions. Basically, only the single tap event will work.
|
||||
- **#227**: Update current URL in HTML5 example
|
||||
- Now if you will open the example from direct URL, it will be updated to the current URL. So now it's much easier to share the example link with each other.
|
||||
- **#183**: Documentation about GUI in World Space
|
||||
- Now if you will open the example from direct URL, it will be updated to the current URL in your browser. So now it's much easier to share the example link with each other.
|
||||
- **#183**: Documentation about [GUI in World Space](https://forum.defold.com/t/how-to-gui-in-defold/73256#gui-in-world-coordinates-49)
|
||||
- Also not only the GUI in World Space, but overall How to GUI in Defold article.
|
||||
- **#234**: [BREAKING][Blocker] Now `blocker:set_enabled` and `blocker:is_enabled` affects only inner state of component. To consume input, the blocker component should be enabled and the node itself should be enabled.
|
||||
- **#235**: [Drag] Fix Drag coordinates on streched screen
|
||||
- **#236**: [Hover] Fix nil return in `hover:on_input`
|
||||
- **#237**: [Layout] Add `layout:set_max_gui_upscale` function
|
||||
- **#238**: [System] Add Helper documentation
|
||||
- **#235**: [Drag] Fix Drag coordinates on streched screen.
|
||||
- **#236**: [Hover] Fix nil return in `hover:on_input`.
|
||||
- **#237**: [Layout] Add `layout:set_max_gui_upscale` function.
|
||||
- This functions will scale down element, if current GUI scale is bigger than `max_gui_upscale` value. It can be useful for adapt mobile device to desktop screen.
|
||||
- **#238**: [System] Add Helper documentation.
|
||||
- [System] Now the documentation contains the **Druid** size. The current size as dependency is around **67KB**. It counted without extended components, which is not included by default in the build.
|
||||
|
||||
If you like **Druid**, please, consider to support me!
|
||||
|
||||
❤️ Support ❤️
|
||||
|
||||
Please support me if you like this project! It will help me keep engaged to update **Druid** and make it even better!
|
||||
|
||||
[](https://github.com/sponsors/insality) [](https://ko-fi.com/insality) [](https://www.buymeacoffee.com/insality)
|
||||
|
||||
|
||||
Thanks for my the supporters:
|
||||
- [Defold Foundation](https://defold.com)
|
||||
- [Ragetto](https://forum.defold.com/u/ragetto)
|
||||
|
@ -13,9 +13,6 @@ local utf8 = utf8 or utf8_lua
|
||||
|
||||
local M = {}
|
||||
|
||||
M.ADJUST_STEPS = 20
|
||||
M.ADJUST_SCALE_DELTA = 0.02
|
||||
|
||||
-- Trim spaces on string start
|
||||
local function ltrim(text)
|
||||
return text:match('^%s*(.*)')
|
||||
@ -144,12 +141,13 @@ local function measure_node(word, settings, previous_word)
|
||||
end
|
||||
|
||||
|
||||
--- Create rich text gui nodes from text
|
||||
-- @param text The text to create rich text nodes from
|
||||
-- @param settings Optional settings table (refer to documentation for details)
|
||||
-- @return words
|
||||
-- @return metrics
|
||||
function M.create(text, settings)
|
||||
-- Create rich text gui nodes from text
|
||||
--- @param text string The text to create rich text nodes from
|
||||
--- @param settings table Optional settings table (refer to documentation for details)
|
||||
--- @param style druid.rich_text.style
|
||||
--- @return words
|
||||
--- @return metrics
|
||||
function M.create(text, settings, style)
|
||||
assert(text, "You must provide a text")
|
||||
|
||||
-- default settings for a word
|
||||
@ -178,12 +176,11 @@ function M.create(text, settings)
|
||||
image_color = gui.get_color(settings.node_prefab),
|
||||
default_animation = nil,
|
||||
-- Tags
|
||||
anchor = nil,
|
||||
br = nil,
|
||||
nobr = nil,
|
||||
}
|
||||
|
||||
local parsed_words = parser.parse(text, word_params)
|
||||
local parsed_words = parser.parse(text, word_params, style)
|
||||
local lines = M._split_on_lines(parsed_words, settings)
|
||||
local lines_metrics = M._position_lines(lines, settings)
|
||||
M._update_nodes(lines, settings)
|
||||
@ -450,7 +447,8 @@ end
|
||||
---@param words druid.rich_text.word[]
|
||||
---@param settings druid.rich_text.settings
|
||||
---@param lines_metrics druid.rich_text.lines_metrics
|
||||
function M.adjust_to_area(words, settings, lines_metrics)
|
||||
---@param style druid.rich_text.style
|
||||
function M.adjust_to_area(words, settings, lines_metrics, style)
|
||||
local last_line_metrics = lines_metrics
|
||||
|
||||
if not settings.is_multiline then
|
||||
@ -459,7 +457,7 @@ function M.adjust_to_area(words, settings, lines_metrics)
|
||||
end
|
||||
else
|
||||
-- Multiline adjusting is very tricky stuff...
|
||||
-- It's do a lot of calculations, beware!
|
||||
-- It's doing a lot of calculations, beware!
|
||||
if lines_metrics.text_width > settings.width or lines_metrics.text_height > settings.height then
|
||||
local scale_koef = math.sqrt(settings.height / lines_metrics.text_height)
|
||||
if lines_metrics.text_width * scale_koef > settings.width then
|
||||
@ -469,9 +467,9 @@ function M.adjust_to_area(words, settings, lines_metrics)
|
||||
|
||||
local lines = M.apply_scale_without_update(words, settings, adjust_scale)
|
||||
local is_fit = M.is_fit_info_area(lines, settings)
|
||||
local step = is_fit and M.ADJUST_SCALE_DELTA or -M.ADJUST_SCALE_DELTA
|
||||
local step = is_fit and style.ADJUST_SCALE_DELTA or -style.ADJUST_SCALE_DELTA
|
||||
|
||||
for i = 1, M.ADJUST_STEPS do
|
||||
for i = 1, style.ADJUST_STEPS do
|
||||
-- Grow down to check if we fit
|
||||
if step < 0 and is_fit then
|
||||
last_line_metrics = M.set_text_scale(words, settings, adjust_scale)
|
||||
@ -487,7 +485,7 @@ function M.adjust_to_area(words, settings, lines_metrics)
|
||||
lines = M.apply_scale_without_update(words, settings, adjust_scale)
|
||||
is_fit = M.is_fit_info_area(lines, settings)
|
||||
|
||||
if i == M.ADJUST_STEPS then
|
||||
if i == style.ADJUST_STEPS then
|
||||
last_line_metrics = M.set_text_scale(words, settings, adjust_scale)
|
||||
end
|
||||
end
|
||||
|
@ -3,44 +3,47 @@
|
||||
-- Modified by: Insality
|
||||
|
||||
local M = {}
|
||||
local cache = {}
|
||||
|
||||
function M.parse_hex(hex)
|
||||
if cache[hex] then
|
||||
return cache[hex]
|
||||
end
|
||||
|
||||
local r,g,b,a = hex:match("#?(%x%x)(%x%x)(%x%x)(%x?%x?)")
|
||||
if a == "" then a = "ff" end
|
||||
if r and g and b and a then
|
||||
return vmath.vector4(
|
||||
local color = vmath.vector4(
|
||||
tonumber(r, 16) / 255,
|
||||
tonumber(g, 16) / 255,
|
||||
tonumber(b, 16) / 255,
|
||||
tonumber(a, 16) / 255)
|
||||
tonumber(a, 16) / 255
|
||||
)
|
||||
|
||||
cache[hex] = color
|
||||
return color
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
function M.parse_decimal(dec)
|
||||
if cache[dec] then
|
||||
return cache[dec]
|
||||
end
|
||||
|
||||
local r,g,b,a = dec:match("(%d*%.?%d*),(%d*%.?%d*),(%d*%.?%d*),(%d*%.?%d*)")
|
||||
if r and g and b and a then
|
||||
return vmath.vector4(tonumber(r), tonumber(g), tonumber(b), tonumber(a))
|
||||
local color = vmath.vector4(tonumber(r), tonumber(g), tonumber(b), tonumber(a))
|
||||
cache[dec] = color
|
||||
return color
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
function M.add(name, color)
|
||||
if type(color) == "string" then
|
||||
color = M.parse_hex(color) or M.parse_decimal(color)
|
||||
end
|
||||
assert(type(color) == "userdata" and color.x and color.y and color.z and color.w, "Unable to add color")
|
||||
M.COLORS[name] = color
|
||||
end
|
||||
|
||||
|
||||
M.COLORS = {}
|
||||
|
||||
|
||||
function M.parse(c)
|
||||
return M.COLORS[c] or M.parse_hex(c) or M.parse_decimal(c)
|
||||
return M.parse_hex(c) or M.parse_decimal(c)
|
||||
end
|
||||
|
||||
|
||||
|
@ -8,9 +8,9 @@ local utf8 = utf8 or utf8_lua
|
||||
|
||||
local M = {}
|
||||
|
||||
local function parse_tag(tag, params)
|
||||
local function parse_tag(tag, params, style)
|
||||
local settings = { tags = { [tag] = params }, tag = tag }
|
||||
if not tags.apply(tag, params, settings) then
|
||||
if not tags.apply(tag, params, settings, style) then
|
||||
settings[tag] = params
|
||||
end
|
||||
|
||||
@ -110,8 +110,9 @@ end
|
||||
--- Parse the text into individual words
|
||||
-- @param text The text to parse
|
||||
-- @param default_settings Default settings for each word
|
||||
-- @param color_aliases Color aliases table
|
||||
-- @return List of all words
|
||||
function M.parse(text, default_settings)
|
||||
function M.parse(text, default_settings, style)
|
||||
assert(text)
|
||||
assert(default_settings)
|
||||
|
||||
@ -151,12 +152,12 @@ function M.parse(text, default_settings)
|
||||
if is_empty then
|
||||
-- empty tag, ie tag without content
|
||||
-- example <br/> and <img=texture:image/>
|
||||
local empty_tag_settings = parse_tag(name, params)
|
||||
local empty_tag_settings = parse_tag(name, params, style)
|
||||
merge_tags(empty_tag_settings, word_settings)
|
||||
add_word("", empty_tag_settings, all_words)
|
||||
elseif not is_endtag then
|
||||
-- open tag - parse and add it
|
||||
local tag_settings = parse_tag(name, params)
|
||||
local tag_settings = parse_tag(name, params, style)
|
||||
open_tags[#open_tags + 1] = tag_settings
|
||||
else
|
||||
-- end tag - remove it from the list of open tags
|
||||
|
@ -5,17 +5,16 @@
|
||||
local color = require("druid.custom.rich_text.module.rt_color")
|
||||
|
||||
local M = {}
|
||||
|
||||
local tags = {}
|
||||
|
||||
|
||||
function M.apply(tag, params, settings)
|
||||
function M.apply(tag, params, settings, style)
|
||||
local fn = tags[tag]
|
||||
if not fn then
|
||||
return false
|
||||
end
|
||||
|
||||
fn(params, settings)
|
||||
fn(params, settings, style)
|
||||
return true
|
||||
end
|
||||
|
||||
@ -44,17 +43,20 @@ end
|
||||
-- Format: <color=[#]{HEX_VALUE}>{Text}</color>
|
||||
-- Format: <color={COLOR_NAME}>{Text}</color>
|
||||
-- Example: <color=FF0000>Rich Text</color>
|
||||
M.register("color", function(params, settings)
|
||||
M.register("color", function(params, settings, style)
|
||||
params = style.COLORS[params] or params
|
||||
settings.color = color.parse(params)
|
||||
end)
|
||||
|
||||
|
||||
M.register("shadow", function(params, settings)
|
||||
M.register("shadow", function(params, settings, style)
|
||||
params = style.COLORS[params] or params
|
||||
settings.shadow = color.parse(params)
|
||||
end)
|
||||
|
||||
|
||||
M.register("outline", function(params, settings)
|
||||
M.register("outline", function(params, settings, style)
|
||||
params = style.COLORS[params] or params
|
||||
settings.outline = color.parse(params)
|
||||
end)
|
||||
|
||||
@ -69,11 +71,6 @@ M.register("size", function(params, settings)
|
||||
end)
|
||||
|
||||
|
||||
M.register("a", function(params, settings)
|
||||
settings.anchor = true
|
||||
end)
|
||||
|
||||
|
||||
-- Example: </br>
|
||||
M.register("br", function(params, settings)
|
||||
settings.br = true
|
||||
|
@ -59,7 +59,6 @@
|
||||
-- font: string,
|
||||
-- image: druid.rich_text.image,
|
||||
-- default_animation: string,
|
||||
-- anchor: number,
|
||||
-- br: boolean,
|
||||
-- nobr: boolean,
|
||||
-- }
|
||||
@ -125,6 +124,21 @@ function RichText.init(self, template, nodes)
|
||||
end
|
||||
|
||||
|
||||
--- Component style params.
|
||||
-- You can override this component styles params in Druid styles table
|
||||
-- or create your own style
|
||||
-- @table style
|
||||
-- @tfield[opt={}] table COLORS Rich Text color aliases
|
||||
-- @tfield[opt=20] number ADJUST_STEPS Amount steps of attemps text adjust by height
|
||||
-- @tfield[opt=0.02] number ADJUST_SCALE_DELTA Scale step on each height adjust step
|
||||
function RichText.on_style_change(self, style)
|
||||
self.style = {}
|
||||
self.style.COLORS = style.COLORS or {}
|
||||
self.style.ADJUST_STEPS = style.ADJUST_STEPS or 20
|
||||
self.style.ADJUST_SCALE_DELTA = style.ADJUST_SCALE_DELTA or 0.02
|
||||
end
|
||||
|
||||
|
||||
--- Set text for Rich Text
|
||||
-- @tparam RichText self @{RichText}
|
||||
-- @tparam string text The text to set
|
||||
@ -174,10 +188,10 @@ end
|
||||
-- <img=texture:image,size/>
|
||||
-- <img=texture:image,width,height/>
|
||||
function RichText.set_text(self, text)
|
||||
self:clean()
|
||||
self:clear()
|
||||
|
||||
local words, settings, line_metrics = rich_text.create(text, self._settings)
|
||||
line_metrics = rich_text.adjust_to_area(words, settings, line_metrics)
|
||||
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
|
||||
@ -187,13 +201,22 @@ end
|
||||
|
||||
|
||||
function RichText:on_remove()
|
||||
self:clean()
|
||||
self:clear()
|
||||
end
|
||||
|
||||
|
||||
--- Get all words, which has a passed tag
|
||||
--- Clear all created words.
|
||||
function RichText:clear()
|
||||
if self._words then
|
||||
rich_text.remove(self._words)
|
||||
self._words = nil
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--- Get all words, which has a passed tag.
|
||||
-- @tparam string tag
|
||||
-- @treturn table Words
|
||||
-- @treturn druid.rich_text.word[] words
|
||||
function RichText:tagged(tag)
|
||||
if not self._words then
|
||||
return
|
||||
@ -204,12 +227,19 @@ end
|
||||
|
||||
|
||||
--- Get all current words.
|
||||
-- @treturn table Words
|
||||
-- @treturn table druid.rich_text.word[]
|
||||
function RichText:get_words()
|
||||
return self._words
|
||||
end
|
||||
|
||||
|
||||
--- Get current line metrics
|
||||
--- @treturn druid.rich_text.lines_metrics
|
||||
function RichText:get_line_metric()
|
||||
return self._line_metrics
|
||||
end
|
||||
|
||||
|
||||
function RichText:_create_settings()
|
||||
local root_size = gui.get_size(self.root)
|
||||
return {
|
||||
@ -219,7 +249,7 @@ function RichText:_create_settings()
|
||||
parent = self.root,
|
||||
width = root_size.x,
|
||||
height = root_size.y,
|
||||
combine_words = false,
|
||||
combine_words = false, -- disabled now
|
||||
text_prefab = self.text_prefab,
|
||||
node_prefab = self.icon_prefab,
|
||||
|
||||
@ -231,7 +261,7 @@ function RichText:_create_settings()
|
||||
is_multiline = gui.get_line_break(self.text_prefab),
|
||||
|
||||
-- Image settings
|
||||
image_pixel_grid_snap = false,
|
||||
image_pixel_grid_snap = false, -- disabled now
|
||||
node_scale = gui.get_scale(self.icon_prefab),
|
||||
image_scale = gui.get_scale(self.icon_prefab),
|
||||
default_animation = gui.get_flipbook(self.icon_prefab),
|
||||
@ -239,13 +269,4 @@ function RichText:_create_settings()
|
||||
end
|
||||
|
||||
|
||||
--- Clear all created words.
|
||||
function RichText:clean()
|
||||
if self._words then
|
||||
rich_text.remove(self._words)
|
||||
self._words = nil
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
return RichText
|
||||
|
@ -1,5 +1,10 @@
|
||||
-- Manual Annotations --
|
||||
|
||||
---@class druid.rich_text.style
|
||||
---@field COLORS table
|
||||
---@field ADJUST_STEPS number
|
||||
---@field ADJUST_SCALE_DELTA number
|
||||
|
||||
---@class druid.rich_text.metrics
|
||||
---@field width number
|
||||
---@field height number
|
||||
|
Loading…
x
Reference in New Issue
Block a user