mirror of
https://github.com/minetest/minetest.git
synced 2024-11-26 17:43:45 +01:00
Rewrite the gamebar (#13768)
This commit is contained in:
parent
294ad98776
commit
83b85ba16a
@ -81,3 +81,9 @@ files["builtin/common/tests"] = {
|
||||
"assert",
|
||||
},
|
||||
}
|
||||
|
||||
files["builtin/fstk"] = {
|
||||
read_globals = {
|
||||
"TOUCHSCREEN_GUI",
|
||||
},
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
--Minetest
|
||||
--Copyright (C) 2014 sapier
|
||||
--Copyright (C) 2023 Gregor Parzefall
|
||||
--
|
||||
--This program is free software; you can redistribute it and/or modify
|
||||
--it under the terms of the GNU Lesser General Public License as published by
|
||||
@ -16,116 +17,101 @@
|
||||
--51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
|
||||
local function buttonbar_formspec(self)
|
||||
local BASE_SPACING = 0.1
|
||||
local SCROLL_BTN_WIDTH = TOUCHSCREEN_GUI and 0.8 or 0.5
|
||||
|
||||
local function buttonbar_formspec(self)
|
||||
if self.hidden then
|
||||
return ""
|
||||
end
|
||||
|
||||
local formspec = "style_type[box;noclip=true]" ..
|
||||
string.format("box[%f,%f;%f,%f;%s]", self.pos.x, self.pos.y, self.size.x, self.size.y, self.bgcolor) ..
|
||||
"style_type[box;noclip=false]"
|
||||
local formspec = {
|
||||
"style_type[box;noclip=true]",
|
||||
string.format("box[%f,%f;%f,%f;%s]", self.pos.x, self.pos.y, self.size.x,
|
||||
self.size.y, self.bgcolor),
|
||||
"style_type[box;noclip=false]",
|
||||
}
|
||||
|
||||
for i=self.startbutton,#self.buttons,1 do
|
||||
local btn_name = self.buttons[i].name
|
||||
local btn_pos = {}
|
||||
local btn_size = self.size.y - 2*BASE_SPACING
|
||||
|
||||
if self.orientation == "horizontal" then
|
||||
btn_pos.x = self.pos.x + --base pos
|
||||
(i - self.startbutton) * self.btn_size * 1.25 + --button offset
|
||||
self.btn_initial_offset
|
||||
else
|
||||
btn_pos.x = self.pos.x + self.size.x / 2 - self.btn_size / 2
|
||||
-- Spacing works like CSS Flexbox with `justify-content: space-evenly;`.
|
||||
-- `BASE_SPACING` is used as the minimum spacing, like `gap` in CSS Flexbox.
|
||||
|
||||
-- The number of buttons per page is always calculated as if the scroll
|
||||
-- buttons were visible.
|
||||
local avail_space = self.size.x - 2*BASE_SPACING - 2*SCROLL_BTN_WIDTH
|
||||
local btns_per_page = math.floor((avail_space - BASE_SPACING) / (btn_size + BASE_SPACING))
|
||||
|
||||
self.num_pages = math.ceil(#self.buttons / btns_per_page)
|
||||
self.cur_page = math.min(self.cur_page, self.num_pages)
|
||||
local first_btn = (self.cur_page - 1) * btns_per_page + 1
|
||||
|
||||
local show_scroll_btns = self.num_pages > 1
|
||||
|
||||
-- In contrast, the button spacing calculation takes hidden scroll buttons
|
||||
-- into account.
|
||||
local real_avail_space = show_scroll_btns and avail_space or self.size.x
|
||||
local btn_spacing = (real_avail_space - btns_per_page * btn_size) / (btns_per_page + 1)
|
||||
|
||||
local btn_start_x = self.pos.x + btn_spacing
|
||||
if show_scroll_btns then
|
||||
btn_start_x = btn_start_x + BASE_SPACING + SCROLL_BTN_WIDTH
|
||||
end
|
||||
|
||||
if self.orientation == "vertical" then
|
||||
btn_pos.y = self.pos.y + --base pos
|
||||
(i - self.startbutton) * self.btn_size * 1.25 + --button offset
|
||||
self.btn_initial_offset
|
||||
else
|
||||
btn_pos.y = self.pos.y + self.size.y / 2 - self.btn_size / 2
|
||||
end
|
||||
|
||||
if (self.orientation == "vertical" and
|
||||
(btn_pos.y + self.btn_size <= self.pos.y + self.size.y)) or
|
||||
(self.orientation == "horizontal" and
|
||||
(btn_pos.x + self.btn_size <= self.pos.x + self.size.x)) then
|
||||
|
||||
local borders="true"
|
||||
|
||||
if self.buttons[i].image ~= nil then
|
||||
borders="false"
|
||||
end
|
||||
|
||||
formspec = formspec ..
|
||||
string.format("image_button[%f,%f;%f,%f;%s;%s;%s;true;%s]tooltip[%s;%s]",
|
||||
btn_pos.x, btn_pos.y, self.btn_size, self.btn_size,
|
||||
self.buttons[i].image, btn_name, self.buttons[i].caption,
|
||||
borders, btn_name, self.buttons[i].tooltip)
|
||||
else
|
||||
--print("end of displayable buttons: orientation: " .. self.orientation)
|
||||
--print( "button_end: " .. (btn_pos.y + self.btn_size - (self.btn_size * 0.05)))
|
||||
--print( "bar_end: " .. (self.pos.x + self.size.x))
|
||||
for i = first_btn, first_btn + btns_per_page - 1 do
|
||||
local btn = self.buttons[i]
|
||||
if btn == nil then
|
||||
break
|
||||
end
|
||||
|
||||
local btn_pos = {
|
||||
x = btn_start_x + (i - first_btn) * (btn_size + btn_spacing),
|
||||
y = self.pos.y + BASE_SPACING,
|
||||
}
|
||||
|
||||
table.insert(formspec, string.format("image_button[%f,%f;%f,%f;%s;%s;%s;true;false]tooltip[%s;%s]",
|
||||
btn_pos.x, btn_pos.y, btn_size, btn_size, btn.image, btn.name,
|
||||
btn.caption, btn.name, btn.tooltip))
|
||||
end
|
||||
|
||||
if (self.have_move_buttons) then
|
||||
local btn_dec_pos = {}
|
||||
btn_dec_pos.x = self.pos.x + (self.btn_size * 0.05)
|
||||
btn_dec_pos.y = self.pos.y + (self.btn_size * 0.05)
|
||||
local btn_inc_pos = {}
|
||||
local btn_size = {}
|
||||
if show_scroll_btns then
|
||||
local btn_prev_pos = {
|
||||
x = self.pos.x + BASE_SPACING,
|
||||
y = self.pos.y + BASE_SPACING,
|
||||
}
|
||||
local btn_next_pos = {
|
||||
x = self.pos.x + self.size.x - BASE_SPACING - SCROLL_BTN_WIDTH,
|
||||
y = self.pos.y + BASE_SPACING,
|
||||
}
|
||||
|
||||
if self.orientation == "horizontal" then
|
||||
btn_size.x = 0.5
|
||||
btn_size.y = self.btn_size
|
||||
btn_inc_pos.x = self.pos.x + self.size.x - 0.5
|
||||
btn_inc_pos.y = self.pos.y + (self.btn_size * 0.05)
|
||||
else
|
||||
btn_size.x = self.btn_size
|
||||
btn_size.y = 0.5
|
||||
btn_inc_pos.x = self.pos.x + (self.btn_size * 0.05)
|
||||
btn_inc_pos.y = self.pos.y + self.size.y - 0.5
|
||||
table.insert(formspec, string.format("style[%s,%s;noclip=true]",
|
||||
self.btn_prev_name, self.btn_next_name))
|
||||
|
||||
table.insert(formspec, string.format("button[%f,%f;%f,%f;%s;<]",
|
||||
btn_prev_pos.x, btn_prev_pos.y, SCROLL_BTN_WIDTH, btn_size,
|
||||
self.btn_prev_name))
|
||||
|
||||
table.insert(formspec, string.format("button[%f,%f;%f,%f;%s;>]",
|
||||
btn_next_pos.x, btn_next_pos.y, SCROLL_BTN_WIDTH, btn_size,
|
||||
self.btn_next_name))
|
||||
end
|
||||
|
||||
local text_dec = "<"
|
||||
local text_inc = ">"
|
||||
if self.orientation == "vertical" then
|
||||
text_dec = "^"
|
||||
text_inc = "v"
|
||||
end
|
||||
|
||||
formspec = formspec ..
|
||||
string.format("image_button[%f,%f;%f,%f;;btnbar_dec_%s;%s;true;true]",
|
||||
btn_dec_pos.x, btn_dec_pos.y, btn_size.x, btn_size.y,
|
||||
self.name, text_dec)
|
||||
|
||||
formspec = formspec ..
|
||||
string.format("image_button[%f,%f;%f,%f;;btnbar_inc_%s;%s;true;true]",
|
||||
btn_inc_pos.x, btn_inc_pos.y, btn_size.x, btn_size.y,
|
||||
self.name, text_inc)
|
||||
end
|
||||
|
||||
return formspec
|
||||
return table.concat(formspec)
|
||||
end
|
||||
|
||||
local function buttonbar_buttonhandler(self, fields)
|
||||
|
||||
if fields["btnbar_inc_" .. self.name] ~= nil and
|
||||
self.startbutton < #self.buttons then
|
||||
|
||||
self.startbutton = self.startbutton + 1
|
||||
if fields[self.btn_prev_name] and self.cur_page > 1 then
|
||||
self.cur_page = self.cur_page - 1
|
||||
return true
|
||||
end
|
||||
|
||||
if fields["btnbar_dec_" .. self.name] ~= nil and self.startbutton > 1 then
|
||||
self.startbutton = self.startbutton - 1
|
||||
if fields[self.btn_next_name] and self.cur_page < self.num_pages then
|
||||
self.cur_page = self.cur_page + 1
|
||||
return true
|
||||
end
|
||||
|
||||
for i=1,#self.buttons,1 do
|
||||
if fields[self.buttons[i].name] ~= nil then
|
||||
for _, btn in ipairs(self.buttons) do
|
||||
if fields[btn.name] then
|
||||
return self.userbuttonhandler(fields)
|
||||
end
|
||||
end
|
||||
@ -146,71 +132,41 @@ local buttonbar_metatable = {
|
||||
if image == nil then image = "" end
|
||||
if tooltip == nil then tooltip = "" end
|
||||
|
||||
self.buttons[#self.buttons + 1] = {
|
||||
table.insert(self.buttons, {
|
||||
name = name,
|
||||
caption = caption,
|
||||
image = image,
|
||||
tooltip = tooltip
|
||||
}
|
||||
if self.orientation == "horizontal" then
|
||||
if ( (self.btn_size * #self.buttons) + (self.btn_size * 0.05 *2)
|
||||
> self.size.x ) then
|
||||
|
||||
self.btn_initial_offset = self.btn_size * 0.05 + 0.5
|
||||
self.have_move_buttons = true
|
||||
end
|
||||
else
|
||||
if ((self.btn_size * #self.buttons) + (self.btn_size * 0.05 *2)
|
||||
> self.size.y ) then
|
||||
|
||||
self.btn_initial_offset = self.btn_size * 0.05 + 0.5
|
||||
self.have_move_buttons = true
|
||||
end
|
||||
end
|
||||
end,
|
||||
|
||||
set_bgparams = function(self, bgcolor)
|
||||
if (type(bgcolor) == "string") then
|
||||
self.bgcolor = bgcolor
|
||||
end
|
||||
tooltip = tooltip,
|
||||
})
|
||||
end,
|
||||
}
|
||||
|
||||
buttonbar_metatable.__index = buttonbar_metatable
|
||||
|
||||
function buttonbar_create(name, cbf_buttonhandler, pos, orientation, size)
|
||||
assert(name ~= nil)
|
||||
assert(cbf_buttonhandler ~= nil)
|
||||
assert(orientation == "vertical" or orientation == "horizontal")
|
||||
assert(pos ~= nil and type(pos) == "table")
|
||||
assert(size ~= nil and type(size) == "table")
|
||||
function buttonbar_create(name, pos, size, bgcolor, cbf_buttonhandler)
|
||||
assert(type(name) == "string" )
|
||||
assert(type(pos) == "table" )
|
||||
assert(type(size) == "table" )
|
||||
assert(type(bgcolor) == "string" )
|
||||
assert(type(cbf_buttonhandler) == "function")
|
||||
|
||||
local self = {}
|
||||
self.name = name
|
||||
self.type = "addon"
|
||||
self.bgcolor = "#000000"
|
||||
self.name = name
|
||||
self.pos = pos
|
||||
self.size = size
|
||||
self.orientation = orientation
|
||||
self.startbutton = 1
|
||||
self.have_move_buttons = false
|
||||
self.hidden = false
|
||||
|
||||
if self.btn_initial_offset == nil then
|
||||
self.btn_initial_offset = 0.375
|
||||
end
|
||||
|
||||
if self.orientation == "horizontal" then
|
||||
self.btn_size = self.size.y - 2*0.1
|
||||
else
|
||||
self.btn_size = self.size.x - 2*0.1
|
||||
end
|
||||
|
||||
|
||||
self.bgcolor = bgcolor
|
||||
self.userbuttonhandler = cbf_buttonhandler
|
||||
self.buttons = {}
|
||||
|
||||
setmetatable(self,buttonbar_metatable)
|
||||
self.hidden = false
|
||||
self.buttons = {}
|
||||
self.num_pages = 1
|
||||
self.cur_page = 1
|
||||
|
||||
self.btn_prev_name = "btnbar_prev_" .. self.name
|
||||
self.btn_next_name = "btnbar_next_" .. self.name
|
||||
|
||||
setmetatable(self, buttonbar_metatable)
|
||||
|
||||
ui.add(self)
|
||||
return self
|
||||
|
@ -81,9 +81,8 @@ function singleplayer_refresh_gamebar()
|
||||
end
|
||||
end
|
||||
|
||||
local btnbar = buttonbar_create("game_button_bar",
|
||||
game_buttonbar_button_handler,
|
||||
{x=0,y=7.475}, "horizontal", {x=15.5,y=1.25})
|
||||
local btnbar = buttonbar_create("game_button_bar", {x = 0, y = 7.475},
|
||||
{x = 15.5, y = 1.25}, "#000000", game_buttonbar_button_handler)
|
||||
|
||||
for _, game in ipairs(pkgmgr.games) do
|
||||
local btn_name = "game_btnbar_" .. game.id
|
||||
|
@ -126,30 +126,27 @@ members:
|
||||
File: fst/buttonbar.lua
|
||||
-----------------------
|
||||
|
||||
buttonbar_create(name, cbf_buttonhandler, pos, orientation, size)
|
||||
buttonbar_create(name, pos, size, bgcolor, cbf_buttonhandler)
|
||||
^ create a buttonbar
|
||||
^ name: name of component (unique per ui)
|
||||
^ cbf_buttonhandler: function to be called on button pressed
|
||||
function(buttonbar,buttonname,buttondata)
|
||||
^ pos: position relative to upper left of current shown formspec
|
||||
{
|
||||
x,
|
||||
y
|
||||
}
|
||||
^ orientation: "vertical" or "horizontal"
|
||||
^ size: size of bar
|
||||
{
|
||||
width,
|
||||
height
|
||||
x,
|
||||
y
|
||||
}
|
||||
^ bgcolor: background color as `ColorString`
|
||||
^ cbf_buttonhandler: function to be called on button pressed
|
||||
function(fields)
|
||||
|
||||
Class reference buttonbar:
|
||||
|
||||
methods:
|
||||
- add_button(btn_id, caption, button_image)
|
||||
- set_parent(parent)
|
||||
^ set parent to attach a buttonbar to
|
||||
^ parent: component to attach to
|
||||
- add_button(name, caption, image, tooltip)
|
||||
- show()
|
||||
^ show buttonbar
|
||||
- hide()
|
||||
|
Loading…
Reference in New Issue
Block a user