Table cleanup part 2 - use gui api

This commit is contained in:
Hugues Ross 2020-06-07 18:09:58 -04:00
parent 06b509ed94
commit c26265e2c3
3 changed files with 467 additions and 116 deletions

View File

@ -1,15 +1,32 @@
local gui = {};
function gui.formspec(args)
local data = string.format("formspec_version[%d] size[%f,%f]", args.version or 3, args.w, args.h);
if args.bg then
data = data .. gui.bg9 {
skin = args.bg,
fullsize = true,
};
end
return data;
end
function gui.bg9(args)
return string.format("background9[%f,%f;%f,%f;%s;%s;%s]",
args.x, args.y,
args.w, args.h,
args.x or 0, args.y or 0,
args.w or 1 * (args.size or 1), args.h or 1 * (args.size or 1),
args.skin.texture .. ".png",
args.fullsize or false,
tostring(args.skin.radius));
end
function gui.button(args)
if args.disabled then
return string.format("button[%f,%f;%f,%f;disabled_button;%s]", args.x, args.y, args.w, args.h, args.text);
end
local data = string.format("button[%f,%f;%f,%f;%s;%s]", args.x, args.y, args.w, args.h, args.id, args.text);
if args.tooltip then
@ -22,6 +39,19 @@ function gui.button(args)
return data;
end
function gui.container(args)
local data = string.format("container[%f,%f]", args.x, args.y);
for _,element in ipairs(args) do
data = data .. element;
end
return data .. "container_end[]";
end
function gui.image(args)
return string.format("image[%f,%f;%f,%f;%s]", args.x, args.y, args.w, args.h, args.image);
end
function gui.image_button(args)
local data = string.format("image_button[%f,%f;%f,%f;%s;%s;%s]",
args.x, args.y,
@ -40,7 +70,46 @@ function gui.image_button(args)
return data;
end
function gui.inventory(args)
local data = "";
if args.bg then
for i = 0,args.w - 1 do
for j = 0,args.h - 1 do
data = data .. gui.bg9 {
x = args.x + (i * 1.25),
y = args.y + (j * 1.25),
skin = args.bg,
};
end
end
end
data = data .. string.format("list[%s;%s;%f,%f;%f,%f;]", args.location, args.id, args.x, args.y, args.w, args.h);
if args.tooltip then
data = data .. gui.tooltip {
x = args.x,
y = args.y,
w = args.w,
h = args.h,
text = args.tooltip,
};
end
return data;
end
function gui.label(args)
if args.textcolor then
return string.format("label[%f,%f;%s%s]",
args.x,
args.y,
minetest.get_color_escape_sequence(args.textcolor),
args.text);
end
return string.format("label[%f,%f;%s]", args.x, args.y, args.text);
end
@ -61,7 +130,11 @@ function gui.style_type(args)
end
function gui.tooltip(args)
return string.format("tooltip[%s;%s]", args.id, args.text);
if args.id then
return string.format("tooltip[%s;%s]", args.id, args.text);
else
return string.format("tooltip[%f,%f;%f,%f;%s]", args.x, args.y, args.w, args.h, args.text);
end
end
return gui;

View File

@ -58,4 +58,4 @@ loadfile(modpath .. "/items.lua") ();
_cartographer.generate_marker_formspec = loadfile(modpath .. "/marker_formspec.lua") (_cartographer.marker_lookup, cartographer.gui);
loadfile(modpath .. "/map_formspec.lua") (map_data);
loadfile(modpath .. "/commands.lua") ();
loadfile(modpath .. "/table.lua") (_cartographer.materials_by_name, _cartographer.materials_by_group, cartographer.skin);
loadfile(modpath .. "/table.lua") (_cartographer.materials_by_name, _cartographer.materials_by_group, cartographer.gui, cartographer.skin);

502
table.lua
View File

@ -1,4 +1,4 @@
local materials_by_name, materials_by_group, gui_skin = ...;
local materials_by_name, materials_by_group, gui, gui_skin = ...;
local MAP_SIZE = 40;
local SCALE_SMALL = 1;
@ -6,28 +6,6 @@ local SCALE_MEDIUM = 2;
local SCALE_LARGE = 4;
local SCALE_HUGE = 8;
-- Draw background elements in the same arrangement as inventory slots
-- x: The x position of the inventory
-- y: The y position of the inventory
-- cols: The width of the inventory, in columns
-- rows: The height of the inventory, in rows
-- skin: A 9-slice background skin table
--
-- Returns a formspec string
local function inventory_bg(x, y, cols, rows, skin)
local data = "";
for i = 0,cols - 1 do
for j = 0,rows - 1 do
data = data .. string.format("background9[%f,%f;1,1;%s.png;false;%s]",
x + (i * 1.25), y + (j * 1.25),
skin.texture,
tostring(skin.radius));
end
end
return data;
end
-- Get the material cost for the given map scale and detail level
-- scale: The map scale
-- detail: The detail level
@ -63,7 +41,8 @@ local function get_craft_material_cost(meta)
if stack:get_name() == "cartographer:map" then
local smeta = stack:get_meta();
local sub_cost = get_material_cost(smeta:get_int("cartographer:scale") or SCALE_SMALL, (smeta:get_int("cartographer:detail") or 1) - 1);
local sub_cost = get_material_cost(smeta:get_int("cartographer:scale") or SCALE_SMALL,
(smeta:get_int("cartographer:detail") or 1) - 1);
is_positive = cost.paper >= sub_cost.paper and cost.pigment >= sub_cost.pigment;
cost.paper = math.max(cost.paper - sub_cost.paper, 0);
cost.pigment = math.max(cost.pigment - sub_cost.pigment, 0);
@ -142,31 +121,20 @@ end
local fs = {};
-- Draw a button, with support for enabled/disabled states
-- x: The x position of the button
-- y: The y position of the button
-- w: The width of the button
-- h: The height of the button
-- id: The element id
-- text: The text to display in the button
-- enabled: Whether or not the button is enabled
--
-- Returns a formspec string
function fs.button(x, y, w, h, id, text, enabled)
if enabled then
return string.format("button[%f,%f;%f,%f;%s;%s]", x, y, w, h, id, text);
end
return string.format("button[%f,%f;%f,%f;disabled_button;%s]", x, y, w, h, text);
end
-- Draw a 1px thick horizontal separator formspec element
-- y: The y position of the separator
-- skin: A 9-slice background skin table
--
-- Returns a formspec string
function fs.separator(y, skin)
return string.format("background9[0.1,%f;10.05,0.01;%s.png;false;%s]", y, skin.texture, tostring(skin.radius))
return gui.bg9 {
x = 0.1,
y = y,
w = 10.05,
h = 0.01,
skin = skin,
};
end
-- Draw all the essential formspec data (size, background, styles, tabs)
@ -178,21 +146,106 @@ end
--
-- Returns a formspec string
function fs.header(w, h, rank, tab, skin)
local data = "formspec_version[3]"
.. string.format("size[%f,%f]", w, h)
.. string.format("background9[-0.1,0;1,1;%s.png;true;%s]", skin.background.texture, tostring(skin.background.radius))
.. string.format("background9[0.0625,0.125;%f,%f;%s.png;false;%s]", w - 0.125, h - 0.25, skin.inner_background.texture, tostring(skin.inner_background.radius))
.. string.format("style_type[button;noclip=true;border=false;bgimg=%s.png;bgimg_hovered=%s.png;bgimg_pressed=%s.png;bgimg_middle=%s;textcolor=%s]", skin.tab.texture, skin.tab.hovered_texture, skin.tab.pressed_texture, tostring(skin.tab.radius), skin.tab.font_color)
.. string.format("style[tab%d;noclip=true;border=false;bgimg=%s.png;bgimg_hovered=%s.png;bgimg_pressed=%s.png;bgimg_middle=%s;textcolor=%s]", tab, skin.tab.selected_texture, skin.tab.selected_texture, skin.tab.selected_texture, tostring(skin.tab.radius), skin.tab.font_color)
.. string.format("button[0.25,-0.425;1.5,0.55;tab1;Materials]", tab)
.. string.format("button[1.75,-0.425;1.5,0.55;tab2;Create Map]", tab);
local data = {
gui.formspec {
w = w,
h = h,
bg = skin.background,
},
gui.bg9 {
x = 0.0625,
y = 0.125,
w = w - 0.125,
h = h - 0.25,
skin = skin.inner_background,
},
gui.style_type {
selector = "button",
properties = {
noclip = true,
border = false,
bgimg = skin.tab.texture .. ".png",
bgimg_hovered = skin.tab.hovered_texture .. ".png",
bgimg_pressed = skin.tab.pressed_texture .. ".png",
bgimg_middle = skin.tab.radius,
textcolor = skin.tab.font_color,
}
},
gui.style {
selector = "tab" .. tostring(tab),
properties = {
bgimg = skin.tab.selected_texture .. ".png",
bgimg_hovered = skin.tab.selected_texture .. ".png",
bgimg_pressed = skin.tab.selected_texture .. ".png",
}
},
gui.button {
x = 0.25,
y = -0.425,
w = 1.5,
h = 0.55,
id = "tab1",
text = "Materials"
},
gui.button {
x = 1.75,
y = -0.425,
w = 1.5,
h = 0.55,
id = "tab2",
text = "Create Map"
},
};
if rank >= 2 then
data = data .. string.format("button[3.25,-0.425;1.5,0.55;tab3;Copy Map]", tab);
table.insert(data, gui.button {
x = 3.25,
y = -0.425,
w = 1.5,
h = 0.55,
id = "tab3",
text = "Copy Map"
});
end
return data .. string.format("style_type[button;border=false;bgimg=%s.png;bgimg_hovered=%s.png;bgimg_pressed=%s.png;bgimg_middle=%s;textcolor=%s]", skin.button.texture, skin.button.hovered_texture, skin.button.pressed_texture, tostring(skin.button.radius), skin.button.font_color)
.. string.format("style[disabled_button;bgimg=;bgimg_hovered=;bgimg_pressed=;textcolor=%s]", skin.button.disabled_font_color);
table.insert(data, gui.style_type {
selector = "button",
properties = {
bgimg = skin.button.texture .. ".png",
bgimg_hovered = skin.button.hovered_texture .. ".png",
bgimg_pressed = skin.button.pressed_texture .. ".png",
bgimg_middle = skin.button.radius,
textcolor = skin.button.font_color,
},
});
table.insert(data, gui.style {
selector = "disabled_button",
properties = {
bgimg = "",
bgimg_hovered = "",
bgimg_pressed = "",
textcolor = skin.button.disabled_font_color,
},
});
return table.concat(data);
end
-- Draw material counters from a table's metadata
@ -203,41 +256,116 @@ end
--
-- Returns a formspec string
function fs.materials(x, y, meta, skin)
return string.format("container[%f,%f]", x, y)
.. "formspec_version[3]"
.. string.format("background9[0,0.125;1,0.25;%s.png;false;%s]", skin.label.texture, tostring(skin.label.radius))
.. string.format("image[0.125,0.125;0.25,0.25;%s.png]", skin.paper_texture)
.. string.format("label[0.375,0.25;%sx %d]", minetest.get_color_escape_sequence(skin.label.font_color), meta:get_int("paper"))
.. string.format("background9[1.25,0.125;1,0.25;%s.png;false;%s]", skin.label.texture, tostring(skin.label.radius))
.. string.format("image[1.375,0.125;0.25,0.25;%s.png]", skin.pigment_texture)
.. string.format("label[1.625,0.25;%sx %d]", minetest.get_color_escape_sequence(skin.label.font_color), meta:get_int("pigment"))
.. "container_end[]";
return gui.container {
x = x,
y = y,
gui.bg9 {
x = 0,
y = 0.125,
w = 1.0,
h = 0.25,
skin = skin.label,
},
gui.image {
x = 0.125,
y = 0.125,
w = 0.25,
h = 0.25,
image = skin.paper_texture .. ".png",
},
gui.label {
x = 0.375,
y = 0.25,
textcolor = skin.label.font_color,
text = string.format("x %d", meta:get_int("paper")),
},
gui.bg9 {
x = 1.25,
y = 0.125,
w = 1.0,
h = 0.25,
skin = skin.label,
},
gui.image {
x = 1.375,
y = 0.125,
w = 0.25,
h = 0.25,
image = skin.pigment_texture .. ".png",
},
gui.label {
x = 1.625,
y = 0.25,
textcolor = skin.label.font_color,
text = string.format("x %d", meta:get_int("pigment")),
},
};
end
-- Draw a label with material costs from a table
-- x: The x position of the interface
-- y: The y position of the interface
-- cost: A table of material costs, with string keys for the material
-- names and iteger values
-- names and integer values
-- skin: A formspec skin table
--
-- Returns a formspec string
function fs.cost(x, y, cost, skin)
local data = string.format("background9[%f,%f;1,0.5;%s.png;false;%s]", x, y - 0.125, skin.label.texture, tostring(skin.label.radius));
local i = 0;
local data = {
gui.bg9 {
x = x,
y = y - 0.125,
w = 1,
h = 0.5,
skin = skin.label,
},
}
local i = 0;
for name,value in pairs(cost) do
local texture = "";
if name == "paper" then
data = data .. string.format("image[%f,%f;0.25,0.25;%s.png]", x + 0.125, y + (i * 0.25) - 0.125, skin.paper_texture)
texture = skin.paper_texture .. ".png";
elseif name == "pigment" then
data = data .. string.format("image[%f,%f;0.25,0.25;%s.png]", x + 0.125, y + (i * 0.25) - 0.125, skin.pigment_texture)
texture = skin.pigment_texture .. ".png";
end
data = data .. string.format("label[%f,%f;%sx %d]", x + 0.375, y + (i * 0.25), minetest.get_color_escape_sequence(skin.label.font_color), value);
table.insert(data, gui.image {
x = x + 0.125,
y = y + (i * 0.25) - 0.125,
w = 0.25,
h = 0.25,
image = texture,
});
table.insert(data, gui.label {
x = x + 0.375,
y = y + (i * 0.25);
w = 0.25,
h = 0.25,
textcolor = skin.label.font_color,
text = string.format("x %d", value);
});
i = i + 1;
end
return data;
return table.concat(data);
end
-- Draw the material conversion tab UI
@ -251,14 +379,35 @@ function fs.convert(x, y, pos, skin)
local meta = minetest.get_meta(pos);
local value = cartographer.get_material_value(meta:get_inventory():get_stack("input", 1));
return string.format("container[%f,%f]", x, y)
.. "formspec_version[3]"
.. inventory_bg(0, 0, 1, 1, skin.slot)
.. string.format("list[nodemeta:%d,%d,%d;input;0,0;1,1;]", pos.x, pos.y, pos.z)
.. "tooltip[0,0;1,1;Place items here to convert\nthem into mapmaking materials]"
.. fs.button(2.5, 0.25, 2, 0.5, "convert", "Convert Materials", value.paper + value.pigment > 0)
.. fs.cost(1.25, 0.375, value, skin)
.. "container_end[]";
return gui.container {
x = x,
y = y,
gui.inventory {
x = 0,
y = 0,
w = 1,
h = 1,
location = string.format("nodemeta:%d,%d,%d", pos.x, pos.y, pos.z),
id = "input",
bg = skin.slot,
tooltip = "Place items here to convert\nthem into mapmaking materials",
},
gui.button {
x = 2.5,
y = 0.25,
w = 2,
h = 0.5,
id = "convert",
text = "Convert Materials",
disabled = value.paper + value.pigment <= 0,
},
fs.cost(1.25, 0.375, value, skin),
};
end
-- Draw the map crafting tab UI
@ -272,38 +421,135 @@ end
-- Returns a formspec string
function fs.craft(x, y, pos, rank, meta, skin)
local cost, is_positive = get_craft_material_cost(meta);
local data = string.format("container[%f,%f]", x, y)
.. "formspec_version[3]"
.. inventory_bg(0, 1, 1, 1, skin.slot)
.. string.format("list[nodemeta:%d,%d,%d;output;0,1;1,1;]", pos.x, pos.y, pos.z)
.. "tooltip[0,1;1,1;Place a map here to upgrade it,\nor leave empty to craft]"
.. fs.button(2.5, 1.25, 2, 0.5, "craft", "Craft Map", is_positive and can_afford(cost, meta))
.. fs.cost(1.25, 1.375, cost, skin);
local data = {
x = x,
y = y,
gui.inventory {
x = 0,
y = 1,
w = 1,
h = 1,
location = string.format("nodemeta:%d,%d,%d", pos.x, pos.y, pos.z),
id = "output",
bg = skin.slot,
tooltip = "Place a map here to upgrade it,\nor leave empty to craft",
},
gui.button {
x = 2.5,
y = 1.25,
w = 2,
h = 0.5,
id = "craft",
text = "Craft Map",
disabled = not (is_positive and can_afford(cost, meta)),
},
fs.cost(1.25, 1.375, cost, skin),
gui.style {
selector = string.format("%dx,%d", meta:get_int("scale"), meta:get_int("detail") + 1),
properties = {
bgimg = skin.button.selected_texture .. ".png",
bgimg_hovered = skin.button.selected_texture .. ".png",
bgimg_pressed = skin.button.selected_texture .. ".png",
},
},
gui.label {
x = 0,
y = 0,
text = "Detail Level",
textcolor = skin.label.font_color,
},
};
if rank > 1 then
data = data .. string.format("style[%dx;bgimg=%s.png;bgimg_hovered=%s.png;bgimg_pressed=%s.png]", meta:get_int("scale"), skin.button.selected_texture, skin.button.selected_texture, skin.button.selected_texture)
.. string.format("label[2.5,0;%sMap Scale]", minetest.get_color_escape_sequence(skin.label.font_color))
.. "button[2.5,0.25;0.5,0.5;1x;1x]"
.. "button[3.0,0.25;0.5,0.5;2x;2x]";
table.insert(data, gui.button {
x = 2.5,
y = 0.25,
w = 0.5,
h = 0.5,
id = "1x",
text = "1x",
});
table.insert(data, gui.button {
x = 3.0,
y = 0.25,
w = 0.5,
h = 0.5,
id = "2x",
text = "2x",
});
if rank > 2 then
data = data .. "button[3.5,0.25;0.5,0.5;4x;4x]"
.. "button[4.0,0.25;0.5,0.5;8x;8x]";
table.insert(data, gui.button {
x = 3.5,
y = 0.25,
w = 0.5,
h = 0.5,
id = "4x",
text = "4x",
});
table.insert(data, gui.button {
x = 4.0,
y = 0.25,
w = 0.5,
h = 0.5,
id = "8x",
text = "8x",
});
end
end
data = data .. string.format("style[%d;bgimg=%s.png;bgimg_hovered=%s.png;bgimg_pressed=%s.png]", meta:get_int("detail") + 1, skin.button.selected_texture, skin.button.selected_texture, skin.button.selected_texture)
.. string.format("label[0,0;%sDetail Level]", minetest.get_color_escape_sequence(skin.label.font_color))
.. "button[0.0,0.25;0.5,0.5;1;1]"
.. "button[0.5,0.25;0.5,0.5;2;2]";
table.insert(data, gui.button {
x = 0,
y = 0.25,
w = 0.5,
h = 0.5,
id = "1",
text = "1",
});
table.insert(data, gui.button {
x = 0.5,
y = 0.25,
w = 0.5,
h = 0.5,
id = "2",
text = "2",
});
if rank > 1 then
data = data .. "button[1.0,0.25;0.5,0.5;3;3]";
table.insert(data, gui.button {
x = 1.0,
y = 0.25,
w = 0.5,
h = 0.5,
id = "3",
text = "3",
});
if rank > 2 then
data = data .. "button[1.5,0.25;0.5,0.5;4;4]";
table.insert(data, gui.button {
x = 1.5,
y = 0.25,
w = 0.5,
h = 0.5,
id = "4",
text = "4",
});
end
end
return data .. "container_end[]";
return gui.container(data);
end
-- Draw the map copying tab UI
@ -317,15 +563,42 @@ function fs.copy(x, y, pos, skin)
local meta = minetest.get_meta(pos);
local costs = get_copy_material_cost(meta);
return string.format("container[%f,%f]", x, y)
.. "formspec_version[3]"
.. inventory_bg(0, 0, 1, 1, skin.slot)
.. string.format("list[nodemeta:%d,%d,%d;copy_input;0,0;1,1;]", pos.x, pos.y, pos.z)
.. fs.button(2.5, 0.25, 2, 0.5, "copy", "Copy Map", can_afford(costs, meta))
.. fs.cost(1.25, 0.375, costs, skin)
.. inventory_bg(8.75, 0, 1, 1, skin.slot)
.. string.format("list[nodemeta:%d,%d,%d;copy_output;8.75,0;1,1;]", pos.x, pos.y, pos.z)
.. "container_end[]";
return gui.container {
x = x,
y = y,
gui.inventory {
x = 0,
y = 0,
w = 1,
h = 1,
location = string.format("nodemeta:%d,%d,%d", pos.x, pos.y, pos.z),
id = "copy_input",
bg = skin.slot,
},
gui.inventory {
x = 8.75,
y = 0,
w = 1,
h = 1,
location = string.format("nodemeta:%d,%d,%d", pos.x, pos.y, pos.z),
id = "copy_output",
bg = skin.slot,
},
gui.button {
x = 2.5,
y = 0.25,
w = 2,
h = 0.5,
id = "copy",
text = "Copy Map",
disabled = not can_afford(costs, meta),
},
fs.cost(1.25, 0.375, costs, skin),
};
end
-- Draw the player's inventory
@ -335,11 +608,16 @@ end
--
-- Returns a formspec string
function fs.inv(x, y, skin)
return string.format("container[%f,%f]", x, y)
.. "formspec_version[3]"
.. inventory_bg(0, 0, 8, 4, skin.slot)
.. "list[current_player;main;0,0;8,4;]"
.. "container_end[]";
return gui.inventory {
x = x,
y = y,
w = 8,
h = 4,
location = "current_player",
id = "main",
bg = skin.slot,
};
end
local player_tables = {};