Files
flutter_lua_runtime/assets/runtime/lua/runtime_ui.lua
2026-06-07 22:53:58 +08:00

428 lines
10 KiB
Lua

---@class RuntimeUi
local runtime_ui = {}
---@generic T: table
---@param base? T
---@param opts? table
---@return T
local function merge(base, opts)
local result = {}
for key, value in pairs(base or {}) do
result[key] = value
end
if opts ~= nil then
for key, value in pairs(opts) do
result[key] = value
end
end
return result
end
---@param value any
---@return boolean
local function is_table(value)
return type(value) == "table"
end
---@param opts? table
---@return table
local function normalize_opts(opts)
local source = opts or {}
local result = {}
for key, value in pairs(source) do
if key ~= "w" and key ~= "h" and key ~= "size" and key ~= "handler" and key ~= "onClick" then
result[key] = value
end
end
if result.width == nil then
result.width = source.w or source.size
end
if result.height == nil then
result.height = source.h or source.size
end
if result.onTap == nil then
result.onTap = source.handler or source.onClick
end
return result
end
---@param base table
---@param opts? table
---@return table
local function node_opts(base, opts)
return merge(base, normalize_opts(opts))
end
---@param base? RuntimeNodeProps
---@param opts? RuntimeNodeProps
---@return RuntimeNodeProps
function runtime_ui.style(base, opts)
return merge(base or {}, opts)
end
---@param parent string
---@param opts? RuntimeNodeProps
---@return RuntimeNodeProps
function runtime_ui.with_parent(parent, opts)
return merge(opts or {}, { parent = parent })
end
---@param node_type RuntimeNodeType
---@param id string
---@param opts? RuntimeNodeProps
---@return RuntimeNode
function runtime_ui.node(node_type, id, opts)
return node_opts({ id = id, type = node_type }, opts)
end
---@param id string
---@param x number|RuntimeNodeInit
---@param y? number
---@param width? number
---@param height? number
---@param opts? RuntimeNodeInit
---@return RuntimeNode
function runtime_ui.panel(id, x, y, width, height, opts)
if is_table(x) then
return runtime_ui.node("panel", id, node_opts({ x = 0, y = 0, width = 0, height = 0 }, x))
end
return runtime_ui.node("panel", id, node_opts({
x = x,
y = y,
width = width,
height = height
}, opts))
end
---@param id string
---@param x number|RuntimeNodeInit
---@param y? number
---@param width? number
---@param height? number
---@param opts? RuntimeNodeInit
---@return RuntimeNode
function runtime_ui.rect(id, x, y, width, height, opts)
if is_table(x) then
return runtime_ui.node("rect", id, node_opts({ x = 0, y = 0, width = 0, height = 0 }, x))
end
return runtime_ui.node("rect", id, node_opts({
x = x,
y = y,
width = width,
height = height
}, opts))
end
---@param id string
---@param x number|RuntimeNodeInit
---@param y? number
---@param size? number
---@param opts? RuntimeNodeInit
---@return RuntimeNode
function runtime_ui.circle(id, x, y, size, opts)
if is_table(x) then
return runtime_ui.node("circle", id, node_opts({ x = 0, y = 0, width = 0, height = 0 }, x))
end
return runtime_ui.node("circle", id, node_opts({
x = x,
y = y,
width = size,
height = size
}, opts))
end
---@param id string
---@param x number|RuntimeNodeInit
---@param y? number
---@param width? number
---@param height? number
---@param opts? RuntimeNodeInit
---@return RuntimeNode
function runtime_ui.line(id, x, y, width, height, opts)
if is_table(x) then
return runtime_ui.node("line", id, node_opts({ x = 0, y = 0, width = 0, height = 0 }, x))
end
return runtime_ui.node("line", id, node_opts({
x = x,
y = y,
width = width,
height = height
}, opts))
end
---@param id string
---@param x number|RuntimeNodeInit
---@param y? number
---@param width? number
---@param height? number
---@param value? number
---@param opts? RuntimeNodeInit
---@return RuntimeNode
function runtime_ui.progress(id, x, y, width, height, value, opts)
if is_table(x) then
return runtime_ui.node("progress", id, node_opts({ x = 0, y = 0, width = 0, height = 0, value = 0 }, x))
end
return runtime_ui.node("progress", id, node_opts({
x = x,
y = y,
width = width,
height = height,
value = value
}, opts))
end
---@param id string
---@param x number|RuntimeNodeInit
---@param y? number
---@param width? number
---@param height? number
---@param opts? RuntimeNodeInit
---@return RuntimeNode
function runtime_ui.particle(id, x, y, width, height, opts)
if is_table(x) then
return runtime_ui.node("particle", id, node_opts({ x = 0, y = 0, width = 0, height = 0 }, x))
end
return runtime_ui.node("particle", id, node_opts({
x = x,
y = y,
width = width,
height = height
}, opts))
end
---@param id string
---@param text string|RuntimeNodeInit
---@param x? number
---@param y? number
---@param width? number
---@param height? number
---@param opts? RuntimeNodeInit
---@return RuntimeNode
function runtime_ui.text(id, text, x, y, width, height, opts)
if is_table(text) then
return runtime_ui.node("text", id, node_opts({ text = "", x = 0, y = 0, width = 0, height = 0 }, text))
end
return runtime_ui.node("text", id, node_opts({
text = text,
x = x,
y = y,
width = width,
height = height
}, opts))
end
---@param id string
---@param text string|RuntimeNodeInit
---@param x? number
---@param y? number
---@param width? number
---@param height? number
---@param handler? string
---@param opts? RuntimeNodeInit
---@return RuntimeNode
function runtime_ui.button(id, text, x, y, width, height, handler, opts)
if is_table(text) then
return runtime_ui.node("button", id, node_opts({
text = "",
x = 0,
y = 0,
width = 0,
height = 0,
interactive = true
}, text))
end
return runtime_ui.node("button", id, node_opts({
text = text,
x = x,
y = y,
width = width,
height = height,
interactive = true,
onTap = handler
}, opts))
end
---@param id string
---@param x number|RuntimeNodeInit
---@param y? number
---@param width? number
---@param height? number
---@param opts? RuntimeNodeInit
---@return RuntimeNode
function runtime_ui.list_view(id, x, y, width, height, opts)
if is_table(x) then
return runtime_ui.node("listView", id, node_opts({ x = 0, y = 0, width = 0, height = 0 }, x))
end
return runtime_ui.node("listView", id, node_opts({
x = x,
y = y,
width = width,
height = height
}, opts))
end
---@param id string
---@param asset string|RuntimeNodeInit
---@param x? number
---@param y? number
---@param width? number
---@param height? number
---@param opts? RuntimeNodeInit
---@return RuntimeNode
function runtime_ui.image(id, asset, x, y, width, height, opts)
if is_table(asset) then
return runtime_ui.node("image", id, node_opts({ asset = "", x = 0, y = 0, width = 0, height = 0 }, asset))
end
return runtime_ui.node("image", id, node_opts({
asset = asset,
x = x,
y = y,
width = width,
height = height
}, opts))
end
---@param id string
---@param asset string|RuntimeNodeInit
---@param x? number
---@param y? number
---@param width? number
---@param height? number
---@param opts? RuntimeNodeInit
---@return RuntimeNode
function runtime_ui.sprite(id, asset, x, y, width, height, opts)
if is_table(asset) then
return runtime_ui.node("sprite", id, node_opts({ asset = "", x = 0, y = 0, width = 0, height = 0 }, asset))
end
return runtime_ui.node("sprite", id, node_opts({
asset = asset,
x = x,
y = y,
width = width,
height = height
}, opts))
end
---@param id string
---@param asset string|RuntimeNodeInit
---@param x? number
---@param y? number
---@param width? number
---@param height? number
---@param animation? string
---@param opts? RuntimeNodeInit
---@return RuntimeNode
function runtime_ui.spine(id, asset, x, y, width, height, animation, opts)
if is_table(asset) then
return runtime_ui.node("spine", id, node_opts({ asset = "", x = 0, y = 0, width = 0, height = 0, loop = true }, asset))
end
return runtime_ui.node("spine", id, node_opts({
asset = asset,
x = x,
y = y,
width = width,
height = height,
animation = animation,
loop = true
}, opts))
end
---@param id string
---@param props RuntimeNodeInit
---@return RuntimeNodeUpdate
function runtime_ui.update(id, props)
return { id = id, props = normalize_opts(props or {}) }
end
---@param id string
---@param text string
---@return RuntimeNodeUpdate
function runtime_ui.text_update(id, text)
return runtime_ui.update(id, { text = text })
end
---@param id string
---@param visible boolean
---@return RuntimeNodeUpdate
function runtime_ui.visible_update(id, visible)
return runtime_ui.update(id, { visible = visible })
end
---@param id string
---@param alpha number
---@return RuntimeNodeUpdate
function runtime_ui.alpha_update(id, alpha)
return runtime_ui.update(id, { alpha = alpha })
end
---@param id string
---@param scale number
---@return RuntimeNodeUpdate
function runtime_ui.scale_update(id, scale)
return runtime_ui.update(id, { scale = scale })
end
---@param id string
---@param x number
---@param y number
---@return RuntimeNodeUpdate
function runtime_ui.position_update(id, x, y)
return runtime_ui.update(id, { x = x, y = y })
end
---@param id string
---@param width number
---@param height number
---@return RuntimeNodeUpdate
function runtime_ui.size_update(id, width, height)
return runtime_ui.update(id, { width = width, height = height })
end
---@param id string
---@param x number
---@param y number
---@param scale number
---@param rotation number
---@return RuntimeNodeUpdate
function runtime_ui.transform_update(id, x, y, scale, rotation)
return runtime_ui.update(id, {
x = x,
y = y,
scale = scale,
rotation = rotation
})
end
---@param ids string[]
---@param props RuntimeNodeInit
---@return RuntimeNodeUpdate[]
function runtime_ui.batch_update(ids, props)
local updates = {}
for _, id in ipairs(ids) do
table.insert(updates, runtime_ui.update(id, props))
end
return updates
end
---@param nodes RuntimeNode[]
---@param node RuntimeNode
---@return RuntimeNode[]
function runtime_ui.append(nodes, node)
table.insert(nodes, node)
return nodes
end
---@param nodes RuntimeNode[]
---@param extra_nodes RuntimeNode[]
---@return RuntimeNode[]
function runtime_ui.append_all(nodes, extra_nodes)
for _, node in ipairs(extra_nodes) do
table.insert(nodes, node)
end
return nodes
end
return runtime_ui