Use 9-slicing to build inventory-type backgrounds

This way the slots are all nice and crisp regardless of GUI scale or
image size, and we only need the single slot and its bright version.

This also makes the standard crafting grid into a style table entry that
can be referenced to insert the crafting grid at its proper
style-specific position in any formspec.

And it also makes the craft grid arrow, its X position, and the crafting
grid's result slot X position into style table entries.

Includes a few public helper functions to do most of the work:

`ui.single_slot(xpos, ypos, bright)`

    Does just what it sounds like: it returns a single slot image.
    `xpos` and `ypos` are normal coordinates in slots, as you'd use in
    `image[]` element.  `bright` is a flag that switches to the brighter
    version of the slot image.

`ui.make_trash_slot(xpos, ypos)`

    Creates a single slot, with a one-item `list[]` and a trash can icon
    overlay.

`ui.make_inv_img_grid(xpos, ypos, width, height, bright)`

    Generates a `width` by `height` grid of slot images, using the
    single_slot function above, starting at (`xpos`,`ypos`) for the
    top-left.  Position is as in any `image[]` element, and dimensions
    are in integer numbers of slots (so 8,4 would be a standard inventory).
    `bright` is as above.

All three return a string that can be directly inserted into a formspec.
This commit is contained in:
Vanessa Dannenberg 2021-03-08 12:14:31 -05:00
parent d063af1d27
commit ea4151dfa7
11 changed files with 67 additions and 42 deletions

25
api.lua

@ -303,8 +303,31 @@ function ui.register_button(name, def)
table.insert(ui.buttons, def) table.insert(ui.buttons, def)
end end
function ui.is_creative(playername) function ui.is_creative(playername)
return minetest.check_player_privs(playername, {creative=true}) return minetest.check_player_privs(playername, {creative=true})
or minetest.settings:get_bool("creative_mode") or minetest.settings:get_bool("creative_mode")
end end
function ui.single_slot(xpos, ypos, bright)
return string.format("background9[%f,%f;%f,%f;ui_single_slot%s.png;false;16]",
xpos, ypos, ui.imgscale, ui.imgscale, (bright and "_bright" or "") )
end
function ui.make_trash_slot(xpos, ypos)
return
ui.single_slot(xpos, ypos)..
"image["..xpos..","..ypos..";1.25,1.25;ui_trash_slot_icon.png^[opacity:95]"..
"list[detached:trash;main;"..xpos..","..ypos..";1,1;]"
end
function ui.make_inv_img_grid(xpos, ypos, width, height, bright)
local tiled = {}
local n=1
for y = 0, (height - 1) do
for x = 0, (width -1) do
tiled[n] = ui.single_slot(xpos + (ui.imgscale * x), ypos + (ui.imgscale * y), bright)
n = n + 1
end
end
return table.concat(tiled)
end

@ -8,14 +8,16 @@ License: GPLv3
local S = minetest.get_translator("unified_inventory") local S = minetest.get_translator("unified_inventory")
local F = minetest.formspec_escape local F = minetest.formspec_escape
local ui = unified_inventory local ui = unified_inventory
local bags_inv_bg = "image[0.3,1.5;"..(ui.imgscale*8)..",%f;%s]"
ui.register_page("bags", { ui.register_page("bags", {
get_formspec = function(player) get_formspec = function(player)
local player_name = player:get_player_name() local player_name = player:get_player_name()
return { formspec = table.concat({ return { formspec = table.concat({
ui.style_full.standard_inv_bg, ui.style_full.standard_inv_bg,
string.format(bags_inv_bg, ui.imgscale, "ui_bags_header.png"), ui.single_slot(0.925, 1.5),
ui.single_slot(3.425, 1.5),
ui.single_slot(5.925, 1.5),
ui.single_slot(8.425, 1.5),
"label["..ui.style_full.form_header_x..","..ui.style_full.form_header_y..";" .. F(S("Bags")) .. "]", "label["..ui.style_full.form_header_x..","..ui.style_full.form_header_y..";" .. F(S("Bags")) .. "]",
"button[0.6125,2.75;1.875,0.75;bag1;" .. F(S("Bag @1", 1)) .. "]", "button[0.6125,2.75;1.875,0.75;bag1;" .. F(S("Bag @1", 1)) .. "]",
"button[3.1125,2.75;1.875,0.75;bag2;" .. F(S("Bag @1", 2)) .. "]", "button[3.1125,2.75;1.875,0.75;bag2;" .. F(S("Bag @1", 2)) .. "]",
@ -49,34 +51,27 @@ for bag_i = 1, 4 do
get_formspec = function(player) get_formspec = function(player)
local stack = get_player_bag_stack(player, bag_i) local stack = get_player_bag_stack(player, bag_i)
local image = stack:get_definition().inventory_image local image = stack:get_definition().inventory_image
local slots = stack:get_definition().groups.bagslots
local formspec = { local formspec = {
ui.style_full.standard_inv_bg, ui.style_full.standard_inv_bg,
ui.make_inv_img_grid(0.3, 1.5, 8, slots/8),
"image[9.2,0.4;1,1;" .. image .. "]", "image[9.2,0.4;1,1;" .. image .. "]",
"label[0.3,0.65;" .. F(S("Bag @1", bag_i)) .. "]", "label[0.3,0.65;" .. F(S("Bag @1", bag_i)) .. "]",
"listcolors[#00000000;#00000000]", "listcolors[#00000000;#00000000]",
"listring[current_player;main]", "listring[current_player;main]",
string.format("list[current_player;bag%icontents;%f,%f;8,3;]",
bag_i, 0.3 + ui.list_img_offset, 1.5 + ui.list_img_offset),
"listring[current_name;bag" .. bag_i .. "contents]",
} }
local n = 6 local n = #formspec + 1
local slots = stack:get_definition().groups.bagslots
if slots == 8 then
formspec[n] = string.format(bags_inv_bg, ui.imgscale, "ui_bags_inv_small.png")
elseif slots == 16 then
formspec[n] = string.format(bags_inv_bg, ui.imgscale*2, "ui_bags_inv_medium.png")
elseif slots == 24 then
formspec[n] = string.format(bags_inv_bg, ui.imgscale*3, "ui_bags_inv_large.png")
end
formspec[n+1] = "list[current_player;bag" .. bag_i .. "contents;0.45,1.65;8,3;]"
formspec[n+2] = "listring[current_name;bag" .. bag_i .. "contents]"
n = n + 3
local player_name = player:get_player_name() -- For if statement. local player_name = player:get_player_name() -- For if statement.
if ui.trash_enabled if ui.trash_enabled
or ui.is_creative(player_name) or ui.is_creative(player_name)
or minetest.get_player_privs(player_name).give then or minetest.get_player_privs(player_name).give then
formspec[n] = "image[7.8,0.25;"..ui.trash_slot_img.."]" formspec[n] = ui.make_trash_slot(7.8, 0.25)
formspec[n+1] = "list[detached:trash;main;7.95,0.25;1,1;]" n = n + 1
n = n + 2
end end
local inv = player:get_inventory() local inv = player:get_inventory()
for i = 1, 4 do for i = 1, 4 do

@ -36,6 +36,7 @@ unified_inventory = {
-- Trash enabled -- Trash enabled
trash_enabled = (minetest.settings:get_bool("unified_inventory_trash") ~= false), trash_enabled = (minetest.settings:get_bool("unified_inventory_trash") ~= false),
imgscale = 1.25, imgscale = 1.25,
list_img_offset = 0.13,
standard_background = "background9[0,0;1,1;ui_formbg_9_sliced.png;true;16]", standard_background = "background9[0,0;1,1;ui_formbg_9_sliced.png;true;16]",
} }
@ -92,19 +93,31 @@ ui.style_lite = {
std_inv_y = 4.6, std_inv_y = 4.6,
} }
dofile(modpath.."/api.lua")
for _, style in ipairs({ui.style_full, ui.style_lite}) do for _, style in ipairs({ui.style_full, ui.style_lite}) do
style.items_per_page = style.pagecols * style.pagerows style.items_per_page = style.pagecols * style.pagerows
style.standard_inv = string.format("list[current_player;main;%f,%f;8,4;]", style.standard_inv = string.format("list[current_player;main;%f,%f;8,4;]",
style.std_inv_x+0.15, style.std_inv_y+0.15) style.std_inv_x+0.13, style.std_inv_y+0.13)
style.standard_inv_bg = string.format("image[%f,%f;%f,%f;ui_main_inventory.png]", style.standard_inv_bg = ui.make_inv_img_grid(style.std_inv_x, style.std_inv_y, 8, 1, true)..
style.std_inv_x, style.std_inv_y, ui.make_inv_img_grid(style.std_inv_x, style.std_inv_y + ui.imgscale, 8, 3)
ui.imgscale*8, ui.imgscale*4)
style.craftarrow_x = style.craft_x + 3.75
style.craftarrow = string.format("image[%f,%f;%f,%f;ui_crafting_arrow.png]",
style.craftarrow_x, style.craft_y, ui.imgscale, ui.imgscale)
style.craftresult_x = style.craft_x + 5
style.craft_grid = table.concat({
ui.make_inv_img_grid(style.craft_x, style.craft_y, 3, 3),
ui.single_slot(style.craft_x + ui.imgscale*4, style.craft_y), -- the craft result slot
style.craftarrow,
string.format("list[current_player;craft;%f,%f;3,3;]",
style.craft_x + ui.list_img_offset, style.craft_y + ui.list_img_offset),
string.format("list[current_player;craftpreview;%f,%f;1,1;]",
style.craftresult_x + ui.list_img_offset, style.craft_y + ui.list_img_offset)
})
end end
ui.trash_slot_img = string.format("%f,%f;ui_single_slot.png^(ui_trash_slot_icon.png^[opacity:95)",
ui.imgscale, ui.imgscale)
-- Disable default creative inventory -- Disable default creative inventory
local creative = rawget(_G, "creative") or rawget(_G, "creative_inventory") local creative = rawget(_G, "creative") or rawget(_G, "creative_inventory")
if creative then if creative then
@ -120,7 +133,6 @@ if sfinv then
end end
dofile(modpath.."/group.lua") dofile(modpath.."/group.lua")
dofile(modpath.."/api.lua")
dofile(modpath.."/internal.lua") dofile(modpath.."/internal.lua")
dofile(modpath.."/callbacks.lua") dofile(modpath.."/callbacks.lua")
dofile(modpath.."/match_craft.lua") dofile(modpath.."/match_craft.lua")

@ -174,12 +174,10 @@ ui.register_page("craft", {
local player_name = player:get_player_name() local player_name = player:get_player_name()
local formspec = { local formspec = {
string.format("image[%f,%f;%f,%f;ui_crafting_form.png]", craftx, crafty, ui.imgscale*6, ui.imgscale*3),
perplayer_formspec.standard_inv_bg, perplayer_formspec.standard_inv_bg,
perplayer_formspec.craft_grid,
"label["..formheaderx..","..formheadery..";" ..F(S("Crafting")).."]", "label["..formheaderx..","..formheadery..";" ..F(S("Crafting")).."]",
"listcolors[#00000000;#00000000]", "listcolors[#00000000;#00000000]",
"list[current_player;craftpreview;"..(craftresultx+0.15)..","..(crafty+0.15)..";1,1;]",
"list[current_player;craft;"..(craftx+0.15)..","..(crafty+0.15)..";3,3;]",
"listring[current_name;craft]", "listring[current_name;craft]",
"listring[current_player;main]" "listring[current_player;main]"
} }
@ -187,18 +185,15 @@ ui.register_page("craft", {
if ui.trash_enabled or ui.is_creative(player_name) or minetest.get_player_privs(player_name).give then if ui.trash_enabled or ui.is_creative(player_name) or minetest.get_player_privs(player_name).give then
formspec[n] = string.format("label[%f,%f;%s]", craftx + 6.45, crafty + 2.4, F(S("Trash:"))) formspec[n] = string.format("label[%f,%f;%s]", craftx + 6.45, crafty + 2.4, F(S("Trash:")))
formspec[n+1] = string.format("image[%f,%f;%s]", craftx+6.25, crafty + 2.5, ui.trash_slot_img) formspec[n+1] = ui.make_trash_slot(craftx + 6.25, crafty + 2.5)
formspec[n+2] = string.format("list[detached:trash;main;%f,%f;1,1;]", craftx + 6.4, crafty + 2.65) n=n + 2
n=n+3
end end
if ui.is_creative(player_name) then if ui.is_creative(player_name) then
formspec[n] = string.format("image[%f,%f;%f,%f;ui_single_slot.png]", formspec[n] = ui.single_slot(craftx - 2.5, crafty + 2.5)
perplayer_formspec.craft_x - 2.5, perplayer_formspec.craft_y + 2.5,
ui.imgscale, ui.imgscale)
formspec[n+1] = string.format("label[%f,%f;%s]", craftx - 2.3, crafty + 2.4,F(S("Refill:"))) formspec[n+1] = string.format("label[%f,%f;%s]", craftx - 2.3, crafty + 2.4,F(S("Refill:")))
formspec[n+2] = string.format("list[detached:%srefill;main;%f,%f;1,1;]", formspec[n+2] = string.format("list[detached:%srefill;main;%f,%f;1,1;]",
F(player_name), craftx - 2.35, crafty + 2.65) F(player_name), craftx - 2.2 - ui.list_img_offset, crafty + 2.5 + ui.list_img_offset)
end end
return {formspec=table.concat(formspec)} return {formspec=table.concat(formspec)}
end, end,
@ -275,8 +270,8 @@ ui.register_page("craftguide", {
local craftx = perplayer_formspec.craft_x local craftx = perplayer_formspec.craft_x
local crafty = perplayer_formspec.craft_y local crafty = perplayer_formspec.craft_y
local craftarrowx = craftx + 3.75 local craftarrowx = perplayer_formspec.craftarrow_x
local craftresultx = craftx + 5 local craftresultx = perplayer_formspec.craftresult_x
local formheaderx = perplayer_formspec.form_header_x local formheaderx = perplayer_formspec.form_header_x
local formheadery = perplayer_formspec.form_header_y local formheadery = perplayer_formspec.form_header_y
local give_x = perplayer_formspec.give_btn_x local give_x = perplayer_formspec.give_btn_x
@ -317,7 +312,7 @@ ui.register_page("craftguide", {
end end
local has_give = player_privs.give or ui.is_creative(player_name) local has_give = player_privs.give or ui.is_creative(player_name)
formspec[n] = "image["..craftarrowx..","..crafty..";1.25,1.25;ui_crafting_arrow.png]" formspec[n] = perplayer_formspec.craftarrow
formspec[n+1] = string.format("textarea[%f,%f;10,1;;%s: %s;]", formspec[n+1] = string.format("textarea[%f,%f;10,1;;%s: %s;]",
craftx-2.3, perplayer_formspec.resultstr_y, F(role_text[dir]), item_name_shown) craftx-2.3, perplayer_formspec.resultstr_y, F(role_text[dir]), item_name_shown)
n = n + 2 n = n + 2

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB