Update Rich text style params

This commit is contained in:
Insality 2023-08-05 19:01:06 +03:00
parent 5a0cf42e3d
commit 628723386e
8 changed files with 123 additions and 83 deletions

View File

@ -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

1 date sha version build_size build_time platform mode is_cache_using commits_count
12 2023-07-05T20:19:22Z d0062c2a78e618871ebb4c8ee66b1509b763f069 0.10.671 3292 12 x86_64-linux headless true 671
13 2023-07-13T18:37:07Z 1cbe57376397a8352bbafcc67de0b6f95ae37b35 0.10.682 2496 53 js-web release true 682
14 2023-07-13T19:31:47Z ea185622702e6691275187741b1e2ee0c7f079ec 0.11.686 2452 51 js-web release true 686
15 2023-07-15T12:56:18Z 556e1a9bae620e2df290b10287fa8d0f64d47293 0.11.690 2468 51 js-web release true 690

View File

@ -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!
[![Github-sponsors](https://img.shields.io/badge/sponsor-30363D?style=for-the-badge&logo=GitHub-Sponsors&logoColor=#EA4AAA)](https://github.com/sponsors/insality) [![Ko-Fi](https://img.shields.io/badge/Ko--fi-F16061?style=for-the-badge&logo=ko-fi&logoColor=white)](https://ko-fi.com/insality) [![BuyMeACoffee](https://img.shields.io/badge/Buy%20Me%20a%20Coffee-ffdd00?style=for-the-badge&logo=buy-me-a-coffee&logoColor=black)](https://www.buymeacoffee.com/insality)
Thanks for my the supporters:
- [Defold Foundation](https://defold.com)
- [Ragetto](https://forum.defold.com/u/ragetto)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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