Since there are multiple issues with our current formspec system (see https://github.com/minetest/minetest/issues/6527), I propose a different layouting scheme for a new one. To test my proposals, I modified the current formspec renderer. This, however, comes with multiple limitations:
- I completely removed any interactivity (for now). Buttons show interaction, but no response is send to the server.
- This won't compile for Android since I left the Android code in place but removed code it depended on.
- There will probably be some issues if you try to display an old and a new formspec at the same time.
- The formspec strings can get pretty long, especially autogenerated float values take up far more space than necessary. A binary format would be preferable.
- We work in normalised coordinates. This means, positions are in the range [0,1] and are relative to a parent object.
- Everything you see is a rect. Every rect can have multiple appearance changing modifiers (like background color/image...) and up to one behaviour changing modifiers (like button, inventory...)
- Every rect can have multiple child rects. Coordinates of the child rect are relative to it's parent.
To facilitate creating forms I created a small mod (see below) which offers an object oriented interface to formspecs. To create the initial window, you would call:
Code: Select all
local window = formatter.create()
Code: Select all
window:set_size(.5, .5)
window:set_pos(.25, .25)
Code: Select all
window:set_aspect(16,9)
To actually see anything, you have to either set a background color or an image to the window:
Code: Select all
window:set_background_color("#FFFFFF") -- currently only strings are accepted
window:set_image("modname_texturename.png")
Code: Select all
window:set_absolute_size(width, height)
Code: Select all
window:inventory(spec)
window:button(spec)
window:image(spec)
window:label(spec)
Code: Select all
spec = {
x = 0, -- position relative to the parent
y = 0,
width = 1, -- size relative to the parent
height = 1,
image = "modname_texturename.png", -- image spec (image only)
text = "your text", -- text to display on the element (button and label only)
name = "b1", -- id of the button (button only)
location = "current_player", -- inventory location (inventory only)
list = "main", -- inventory list (inventory only)
columns = 8, -- number of inventory columns (inventory only)
rows = 4 -- number of inventory rows (inventory only)
}
To display the formspec you would have to call:
Code: Select all
minetest.show_formspec_new(name, "formname", window:generate())
Formspec format
- general Element (Image/Label ...)
Create a new rectangle spanning from (x0, y0) to (x1, y1) in relation to it's parent.
Code: Select all
{ rect = { "x0" : 0, "y0" : 0, "x1" : 1, "y1" : 1 }, bgcolor = "#FFFFFF", image = "modname_texture.png", aspect = {"x" : 16, "y" : 9 }, text = "some text", children = [{ ... }, ... ], style = { "style_name" : "style_value" } }
Styles:- text_align, specifies the alignment of the text can be one of: center, top, topright, right, bottomright, bottom, bottomleft, left, topleft
The text is automaticly word wrapped. Enabling this will become an option later on.
Also, text clashes with the basic design principles of this new formspec. It doesn't scale with the rest of the gui and may get outside of the rect. Suggestions on how to fix this are welcome. - Inventory
converts the parent rect into an inventory.
Code: Select all
{ ... see above "type" = "inventory", "columns" = 1, "rows" = 1, "location" = "current_player", "list" = "main" }
The inventory completely fills the rect and touches the border at all four sides. Inventory slots are square and have a padding of at least 2/13 inventory slots in x-direction and 1/4 inventory slot in y-direction.
The old formspec drew a one pixel border on the outside of every slot. Since this clashes with my design, the border is now drawn on the inside and the image is scaled down appropriately.
Styles:- inventory_background_color, specifies the color of the slot background
- inventory_border_color, specifies the color of the slot border
- inventory_border_width, specifies the width of the slot border
- Button
converts the parent rect into a button.
Code: Select all
{ ... see above "type" : "button", "id" : "unique identifier" }
The button background is draw according to it's style. Background images and colors are ignored for now (this will probably change).
The id will be set in the answer when the button ist pressed (not implemented yet).
Styles:- button_standard, set it to a texture to change the default appearance of the button
- button_hover, set it to a texture to change the appearance of the button when the cursor is inside it's rect
- button_pressed, set it to a texture to change the appearance of the button when it get's pressed
Links:
Lua API: https://github.com/TeTpaAka/formatter
Core modifications: https://github.com/TeTpaAka/minetest/tree/formspec
By issueing the chatcommand "/testform" you can see an example gui I created.
The example gui uses images from https://opengameart.org/content/ui-pack-rpg-extension.
TODO:
- Add element for text input.
Code: Select all
input[name]
- port the field sending methods from the old formspec
- split the gui elements into their own file
- split the parsing into it's own file
- add error and sanity checks to core and Lua API
- Add more elements like checkboxes, dropdowns, radiobuttons, ...
- Add scrollable rects