Add style[] support
This commit is contained in:
parent
668a2f3460
commit
5ac492eefe
|
@ -53,6 +53,7 @@ The following elements are supported:
|
||||||
- The label has the same limitations as the `label` element.
|
- The label has the same limitations as the `label` element.
|
||||||
- The `noclip` option is ignored.
|
- The `noclip` option is ignored.
|
||||||
- Item image buttons have the same limitations as `item_image`.
|
- Item image buttons have the same limitations as `item_image`.
|
||||||
|
- `style`
|
||||||
|
|
||||||
All valid formspec elements not listed above are ignored.
|
All valid formspec elements not listed above are ignored.
|
||||||
|
|
||||||
|
|
132
init.lua
132
init.lua
|
@ -32,7 +32,7 @@ end
|
||||||
hud_fs.colorstring_to_number = colorstring_to_number
|
hud_fs.colorstring_to_number = colorstring_to_number
|
||||||
|
|
||||||
-- Hacks to allow colorize() to work to some extent on labels
|
-- Hacks to allow colorize() to work to some extent on labels
|
||||||
local function get_label_number(label)
|
local function get_label_number(label, style)
|
||||||
local number, text = label:match("^\027%(c@([^%)]+)%)(.*)$")
|
local number, text = label:match("^\027%(c@([^%)]+)%)(.*)$")
|
||||||
|
|
||||||
-- Remove trailing escape sequence added by minetest.colorize().
|
-- Remove trailing escape sequence added by minetest.colorize().
|
||||||
|
@ -40,7 +40,8 @@ local function get_label_number(label)
|
||||||
text = text:gsub("\027%(c@[^%)]+%)$", "")
|
text = text:gsub("\027%(c@[^%)]+%)$", "")
|
||||||
end
|
end
|
||||||
|
|
||||||
return text or label, number and colorstring_to_number(number) or 0xFFFFFF
|
return text or label, number and colorstring_to_number(number) or
|
||||||
|
(style.textcolor and colorstring_to_number(style.textcolor) or 0xFFFFFF)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Disable the race condition workaround in 5.4.1 singleplayer
|
-- Disable the race condition workaround in 5.4.1 singleplayer
|
||||||
|
@ -55,14 +56,78 @@ if minetest.is_singleplayer() then
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local PLUS, TIMES = ("+*"):byte(1, 2)
|
||||||
|
local function get_font_size(style)
|
||||||
|
local size = style.font_size
|
||||||
|
if not size then return end
|
||||||
|
|
||||||
|
local first_char = size:byte(1)
|
||||||
|
if first_char == TIMES then
|
||||||
|
size = tonumber(size:sub(2))
|
||||||
|
else
|
||||||
|
-- Approximate a multiple size based on the font size
|
||||||
|
if first_char == PLUS then
|
||||||
|
size = tonumber(size:sub(2))
|
||||||
|
if size then
|
||||||
|
size = size + 16
|
||||||
|
end
|
||||||
|
else
|
||||||
|
size = tonumber(size)
|
||||||
|
end
|
||||||
|
|
||||||
|
if size then
|
||||||
|
size = size / 16
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return size and {x = size, y = 0}
|
||||||
|
end
|
||||||
|
|
||||||
|
local empty_table = {}
|
||||||
|
local function get_style(node, styles_by_name, styles_by_type)
|
||||||
|
local style = styles_by_name[node.name]
|
||||||
|
if not style then
|
||||||
|
return styles_by_type[node.type] or empty_table
|
||||||
|
end
|
||||||
|
|
||||||
|
return setmetatable(style, {__index = styles_by_type[node.type]})
|
||||||
|
end
|
||||||
|
|
||||||
|
local function style_is_yes(value, default)
|
||||||
|
if value == nil then
|
||||||
|
return default
|
||||||
|
elseif type(value) == "string" then
|
||||||
|
return minetest.is_yes(value)
|
||||||
|
else
|
||||||
|
return value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local font_style_flags = {"bold", "italic", "mono"}
|
||||||
|
local function get_style_flags(style)
|
||||||
|
local flags = 0
|
||||||
|
if style.font then
|
||||||
|
local options = style.font:split(",")
|
||||||
|
for i, flag in ipairs(font_style_flags) do
|
||||||
|
if table.indexof(options, flag) > 0 then
|
||||||
|
flags = flags + 2 ^ (i - 1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return flags
|
||||||
|
end
|
||||||
|
|
||||||
local nodes = {}
|
local nodes = {}
|
||||||
function nodes.label(node, scale)
|
function nodes.label(node, scale, _, _, _, _, styles_by_type)
|
||||||
local text, number = get_label_number(node.label)
|
local style = styles_by_type.label or empty_table
|
||||||
|
local text, number = get_label_number(node.label, style)
|
||||||
local elem = {
|
local elem = {
|
||||||
hud_elem_type = "text",
|
hud_elem_type = "text",
|
||||||
text = text,
|
text = text,
|
||||||
alignment = {x = 1, y = 0},
|
alignment = {x = 1, y = 0},
|
||||||
number = number
|
number = number,
|
||||||
|
size = get_font_size(style),
|
||||||
|
style = get_style_flags(style),
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Hack for newlines. This will unfortunately break if the font size is
|
-- Hack for newlines. This will unfortunately break if the font size is
|
||||||
|
@ -132,7 +197,8 @@ function nodes.box(node, scale)
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
function nodes.textarea(node, scale, add_node)
|
function nodes.textarea(node, scale, add_node, _, _, styles_by_name,
|
||||||
|
styles_by_type)
|
||||||
-- Add in separate nodes for the label and background
|
-- Add in separate nodes for the label and background
|
||||||
if node.label and node.label ~= "" then
|
if node.label and node.label ~= "" then
|
||||||
add_node("label", {
|
add_node("label", {
|
||||||
|
@ -141,7 +207,9 @@ function nodes.textarea(node, scale, add_node)
|
||||||
label = node.label
|
label = node.label
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
if node.name and node.name ~= "" then
|
|
||||||
|
local style = get_style(node, styles_by_name, styles_by_type)
|
||||||
|
if node.name and node.name ~= "" and style_is_yes(style.border, true) then
|
||||||
add_node("box", {
|
add_node("box", {
|
||||||
x = node.x,
|
x = node.x,
|
||||||
y = node.y,
|
y = node.y,
|
||||||
|
@ -162,7 +230,9 @@ function nodes.textarea(node, scale, add_node)
|
||||||
text = table.concat(lines, "\n"),
|
text = table.concat(lines, "\n"),
|
||||||
alignment = {x = 1, y = 1},
|
alignment = {x = 1, y = 1},
|
||||||
number = 0xFFFFFF,
|
number = 0xFFFFFF,
|
||||||
scale = {x = node.w * scale, y = node.h * scale}
|
scale = {x = node.w * scale, y = node.h * scale},
|
||||||
|
size = get_font_size(style),
|
||||||
|
style = get_style_flags(style),
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -197,9 +267,12 @@ function nodes.item_image(node, ...)
|
||||||
return nodes.image(node, ...)
|
return nodes.image(node, ...)
|
||||||
end
|
end
|
||||||
|
|
||||||
function nodes.button(node, _, add_node)
|
function nodes.button(node, _, add_node, _, _, styles_by_name, styles_by_type)
|
||||||
|
local style = get_style(node, styles_by_name, styles_by_type)
|
||||||
|
|
||||||
-- This function is used by image_button and item_image_button as well
|
-- This function is used by image_button and item_image_button as well
|
||||||
if node.drawborder == nil or node.drawborder then
|
if node.drawborder or (node.drawborder == nil and
|
||||||
|
style_is_yes(style.border, true)) then
|
||||||
add_node("box", {
|
add_node("box", {
|
||||||
x = node.x,
|
x = node.x,
|
||||||
y = node.y,
|
y = node.y,
|
||||||
|
@ -208,6 +281,17 @@ function nodes.button(node, _, add_node)
|
||||||
color = "#515151FF"
|
color = "#515151FF"
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if style.bgimg then
|
||||||
|
add_node("image", {
|
||||||
|
x = node.x,
|
||||||
|
y = node.y,
|
||||||
|
w = node.w,
|
||||||
|
h = node.h,
|
||||||
|
texture_name = style.bgimg,
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
if node.texture_name and node.texture_name ~= "" then
|
if node.texture_name and node.texture_name ~= "" then
|
||||||
add_node("image", node)
|
add_node("image", node)
|
||||||
elseif node.item_name and node.item_name ~= "" then
|
elseif node.item_name and node.item_name ~= "" then
|
||||||
|
@ -215,12 +299,14 @@ function nodes.button(node, _, add_node)
|
||||||
end
|
end
|
||||||
node.x = node.x + node.w / 2
|
node.x = node.x + node.w / 2
|
||||||
node.y = node.y + node.h / 2
|
node.y = node.y + node.h / 2
|
||||||
local text, number = get_label_number(node.label)
|
local text, number = get_label_number(node.label, style)
|
||||||
return {
|
return {
|
||||||
hud_elem_type = "text",
|
hud_elem_type = "text",
|
||||||
text = text,
|
text = text,
|
||||||
alignment = {x = 0, y = 0},
|
alignment = {x = 0, y = 0},
|
||||||
number = number
|
number = number,
|
||||||
|
size = get_font_size(style),
|
||||||
|
style = get_style_flags(style),
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
nodes.button_exit = nodes.button
|
nodes.button_exit = nodes.button
|
||||||
|
@ -254,10 +340,13 @@ local function render(tree, possibly_using_gles, scale, z_index, window)
|
||||||
scale = scale or DEFAULT_SCALE
|
scale = scale or DEFAULT_SCALE
|
||||||
z_index = z_index or DEFAULT_Z_INDEX
|
z_index = z_index or DEFAULT_Z_INDEX
|
||||||
|
|
||||||
|
local styles_by_name = {}
|
||||||
|
local styles_by_type = {}
|
||||||
local client_hud_scale = window and window.real_hud_scaling or 1
|
local client_hud_scale = window and window.real_hud_scaling or 1
|
||||||
local function add_node(node_type, node)
|
local function add_node(node_type, node)
|
||||||
local elem = nodes[node_type](node, scale, add_node,
|
local elem = nodes[node_type](node, scale, add_node,
|
||||||
possibly_using_gles, client_hud_scale)
|
possibly_using_gles, client_hud_scale, styles_by_name,
|
||||||
|
styles_by_type)
|
||||||
elem.position = pos
|
elem.position = pos
|
||||||
elem.z_index = z_index
|
elem.z_index = z_index
|
||||||
elem.offset = {
|
elem.offset = {
|
||||||
|
@ -299,6 +388,23 @@ local function render(tree, possibly_using_gles, scale, z_index, window)
|
||||||
window.size.x * (1 - node.x * 2) / size_w,
|
window.size.x * (1 - node.x * 2) / size_w,
|
||||||
window.size.y * (1 - node.y * 2) / size_h
|
window.size.y * (1 - node.y * 2) / size_h
|
||||||
) / client_hud_scale
|
) / client_hud_scale
|
||||||
|
elseif node_type == "style" or node_type == "style_type" then
|
||||||
|
local styles = node_type == "style" and styles_by_name or
|
||||||
|
styles_by_type
|
||||||
|
for _, name in ipairs(node.selectors or {node.name}) do
|
||||||
|
local props = styles[name]
|
||||||
|
if not props then
|
||||||
|
props = {}
|
||||||
|
styles[name] = props
|
||||||
|
end
|
||||||
|
for k, v in pairs(node.props) do
|
||||||
|
if v == "" then
|
||||||
|
props[k] = nil
|
||||||
|
else
|
||||||
|
props[k] = v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
elseif nodes[node_type] then
|
elseif nodes[node_type] then
|
||||||
add_node(node_type, node)
|
add_node(node_type, node)
|
||||||
elseif node_type == nil and node.hud_elem_type then
|
elseif node_type == nil and node.hud_elem_type then
|
||||||
|
|
Loading…
Reference in New Issue