wesnoth/data/lua/core.lua
Celtic Minstrel c0f926e2ed Move all WML and variable manipulator functions into new wml table
(The old functions in wesnoth and helper are still available,
but they are now deprecated.)
2017-05-22 17:31:14 -04:00

271 lines
6.7 KiB
Lua

-- Note: This file is loaded automatically by the engine.
function wesnoth.alert(title, msg)
if not msg then
msg = title;
title = "";
end
wesnoth.show_message_box(title, msg, "ok", true)
end
function wesnoth.confirm(title, msg)
if not msg then
msg = title;
title = "";
end
return wesnoth.show_message_box(title, msg, "yes_no", true)
end
wml = {}
wml.variable = {}
--[========[Config Manipulation Functions]========]
wml.tovconfig = wesnoth.tovconfig
wml.tostring = wesnoth.debug
local function ensure_config(cfg)
if type(cfg) == 'table' then
return true
end
if type(cfg) == 'userdata' then
if getmetatable(cfg) == 'wml object' then return true end
error("Expected a table or wml object but got " .. getmetatable(cfg), 3)
else
error("Expected a table or wml object but got " .. type(cfg), 3)
end
return false
end
--! Returns the first subtag of @a cfg with the given @a name.
--! If @a id is not nil, the "id" attribute of the subtag has to match too.
--! The function also returns the index of the subtag in the array.
function wml.get_child(cfg, name, id)
ensure_config(cfg)
for i,v in ipairs(cfg) do
if v[1] == name then
local w = v[2]
if not id or w.id == id then return w, i end
end
end
end
--! Returns the nth subtag of @a cfg with the given @a name.
--! (Indices start at 1, as always with Lua.)
--! The function also returns the index of the subtag in the array.
function wml.get_nth_child(cfg, name, n)
ensure_config(cfg)
for i,v in ipairs(cfg) do
if v[1] == name then
n = n - 1
if n == 0 then return v[2], i end
end
end
end
--! Returns the number of subtags of @a with the given @a name.
function wml.child_count(cfg, name)
ensure_config(cfg)
local n = 0
for i,v in ipairs(cfg) do
if v[1] == name then
n = n + 1
end
end
return n
end
--! Returns an iterator over all the subtags of @a cfg with the given @a name.
function wml.child_range(cfg, tag)
ensure_config(cfg)
local iter, state, i = ipairs(cfg)
local function f(s)
local c
repeat
i,c = iter(s,i)
if not c then return end
until c[1] == tag
return c[2]
end
return f, state
end
--! Returns an array from the subtags of @a cfg with the given @a name
function wml.child_array(cfg, tag)
ensure_config(cfg)
local result = {}
for val in helper.child_range(cfg, tag) do
table.insert(result, val)
end
return result
end
--[========[WML Tag Creation Table]========]
local create_tag_mt = {
__metatable = "WML tag builder",
__index = function(self, n)
return function(cfg) return { n, cfg } end
end
}
wml.tag = setmetatable({}, create_tag_mt)
--[========[Config / Vconfig Unified Handling]========]
function wml.literal(cfg)
if type(cfg) == "userdata" then
return cfg.__literal
else
return cfg or {}
end
end
function wml.parsed(cfg)
if type(cfg) == "userdata" then
return cfg.__parsed
else
return cfg or {}
end
end
function wml.shallow_literal(cfg)
if type(cfg) == "userdata" then
return cfg.__shallow_literal
else
return cfg or {}
end
end
function wml.shallow_parsed(cfg)
if type(cfg) == "userdata" then
return cfg.__shallow_parsed
else
return cfg or {}
end
end
--[========[Basic variable access]========]
wml.variable.get = wesnoth.get_variable
wml.variable.set = wesnoth.set_variable
wml.variable.get_all = wesnoth.get_all_vars
--[========[Variable Proxy Table]========]
local variable_mt = {
__metatable = "WML variable proxy"
}
local function get_variable_proxy(k)
local v = wesnoth.get_variable(k, true)
if type(v) == "table" then
v = setmetatable({ __varname = k }, variable_mt)
end
return v
end
local function set_variable_proxy(k, v)
if getmetatable(v) == "WML variable proxy" then
v = wesnoth.get_variable(v.__varname)
end
wesnoth.set_variable(k, v)
end
function variable_mt.__index(t, k)
local i = tonumber(k)
if i then
k = t.__varname .. '[' .. i .. ']'
else
k = t.__varname .. '.' .. k
end
return get_variable_proxy(k)
end
function variable_mt.__newindex(t, k, v)
local i = tonumber(k)
if i then
k = t.__varname .. '[' .. i .. ']'
else
k = t.__varname .. '.' .. k
end
set_variable_proxy(k, v)
end
local root_variable_mt = {
__metatable = "WML variables",
__index = function(t, k) return get_variable_proxy(k) end,
__newindex = function(t, k, v)
if type(v) == "function" then
-- User-friendliness when _G is overloaded early.
-- FIXME: It should be disabled outside the "preload" event.
rawset(t, k, v)
else
set_variable_proxy(k, v)
end
end
}
wml.variable.proxy = setmetatable({}, root_variable_mt)
--[========[Variable Array Access]========]
local function resolve_variable_context(ctx, err_hint)
if ctx == nil then
return {get = wesnoth.get_variable, set = wesnoth.set_variable}
elseif type(ctx) == 'number' and ctx > 0 and ctx <= #wesnoth.sides then
return resolve_variable_context(wesnoth.sides[ctx])
elseif type(ctx) == 'string' then
-- TODO: Treat it as a namespace for a global (persistent) variable
-- (Need Lua API for accessing them first, though.)
elseif getmetatable(ctx) == "unit" then
return {
get = function(path) return ctx.variables[path] end,
set = function(path, val) ctx.variables[path] = val end,
}
elseif getmetatable(ctx) == "side" then
return {
get = function(path) return wesnoth.get_side_variable(ctx.side, path) end,
set = function(path, val) wesnoth.set_side_variable(ctx.side, path, val) end,
}
elseif getmetatable(ctx) == "unit variables" or getmetatable(ctx) == "side variables" then
return {
get = function(path) return ctx[path] end,
set = function(path, val) ctx[path] = val end,
}
end
error(string.format("Invalid context for %s: expected nil, side, or unit", err_hint), 3)
end
--! Fetches all the WML container variables with name @a var.
--! @returns a table containing all the variables (starting at index 1).
function wml.variable.get_array(var, context)
context = resolve_variable_context(context, "get_variable_array")
local result = {}
for i = 1, context.get(var .. ".length") do
result[i] = context.get(string.format("%s[%d]", var, i - 1))
end
return result
end
--! Puts all the elements of table @a t inside a WML container with name @a var.
function wml.variable.set_array(var, t, context)
context = resolve_variable_context(context, "set_variable_array")
context.set(var)
for i, v in ipairs(t) do
context.set(string.format("%s[%d]", var, i - 1), v)
end
end
--! Creates proxies for all the WML container variables with name @a var.
--! This is similar to helper.get_variable_array, except that the elements
--! can be used for writing too.
--! @returns a table containing all the variable proxies (starting at index 1).
function wml.get_proxy_array(var)
local result = {}
for i = 1, wesnoth.get_variable(var .. ".length") do
result[i] = get_variable_proxy(string.format("%s[%d]", var, i - 1))
end
return result
end