forked from your-land-mirror/minetest-flow
180 lines
6.2 KiB
Markdown
180 lines
6.2 KiB
Markdown
# Experimental features
|
|
|
|
These features might be broken in the future.
|
|
|
|
## `no_prepend[]`
|
|
|
|
You can set `no_prepend = true` on the "root" element to disable formspec
|
|
prepends.
|
|
|
|
Example:
|
|
|
|
```lua
|
|
local my_gui = flow.make_gui(function(player, ctx)
|
|
return gui.VBox{
|
|
no_prepend = true,
|
|
|
|
gui.Button{label = "Button 1"},
|
|
|
|
-- There will be an empty space where the second button would be
|
|
gui.Button{label = "Button 2", visible = false},
|
|
|
|
gui.Button{label = "Button 3"},
|
|
}
|
|
end)
|
|
```
|
|
|
|

|
|
|
|
## `bgcolor[]`
|
|
|
|
You can set `bgcolor = "#123"`, `fbgcolor = "#123"`, and
|
|
`bg_fullscreen = true` on the root element to set a background colour. The
|
|
values for these correspond to the [`bgcolor` formspec element](https://api.luanti.org/formspec/#bgcolorbgcolorfullscreenfbgcolor).
|
|
|
|
## Putting the form somewhere else on the screen (likely required for most HUDs)
|
|
|
|
These values allow the position of the displayed form to be moved around and
|
|
adjust how it is scaled.
|
|
|
|
Example:
|
|
|
|
```lua
|
|
local my_gui = flow.make_gui(function(player, ctx)
|
|
return gui.VBox{
|
|
-- Adjusts where on the screen the form/HUD is rendered.
|
|
-- 0 is the top/left, 1 is the bottom/right
|
|
-- You probably want to set `window_position` and `window_anchor` to
|
|
-- the same value.
|
|
-- This puts the form in the bottom-right corner.
|
|
window_position = {x = 1, y = 1},
|
|
window_anchor = {x = 1, y = 1},
|
|
|
|
-- Equivalent to padding[0.1,0.2], adjusts the minimum amount of
|
|
-- padding around the form in terms of total screen size. If the form
|
|
-- is too big, it will be scaled down
|
|
-- Default for formspecs: {x = 0.05, y = 0.05} (i.e. 5% of screen size)
|
|
-- HUDs default to a hardcoded pixel size, if you want them to roughly
|
|
-- line up with formspecs then you may explicitly specify this.
|
|
window_padding = {x = 0.1, y = 0.2},
|
|
|
|
gui.Label{label = "Hello world"},
|
|
}
|
|
end)
|
|
```
|
|
|
|
See [the formspec documentation](https://api.luanti.org/formspec/#positionxy)
|
|
for more information.
|
|
|
|
## Rendering to a formspec
|
|
|
|
This API should only be used when necessary and may have breaking changes in
|
|
the future.
|
|
|
|
Some APIs in other mods, such as sfinv, expect formspec strings. You can use
|
|
this API to embed flow forms inside them. To use flow with these mods, you can
|
|
call `form:render_to_formspec_string(player, ctx, standalone)`.
|
|
|
|
- By default the the `formspec_version` and `size` elements aren't included in
|
|
the returned formspec and are included in a third return value. Set
|
|
`standalone` to include them in the returned formspec string. The third
|
|
return value will not be returned.
|
|
- Returns `formspec, process_event[, info]`
|
|
- The `process_event(fields)` callback will return true if the formspec should
|
|
be redrawn, where `render_to_formspec_string` should be called and the new
|
|
`process_event` should be used in the future. This function may return true
|
|
even if fields.quit is sent.
|
|
|
|
|
|
> **Warning:**
|
|
> Do not use this API with node meta formspecs, it can and will break!
|
|
|
|
## Embedding a form into another form
|
|
|
|
You can embed form objects inside others like this:
|
|
|
|
```lua
|
|
local parent_form = flow.make_gui(function(player, ctx)
|
|
return gui.VBox{
|
|
gui.Label{label = "Hello world"},
|
|
other_form:embed{
|
|
-- Passing in the player is required for now. You must use the same
|
|
-- player object that you get sent by flow to avoid breakages in
|
|
-- the future if this becomes optional.
|
|
player = player,
|
|
|
|
-- A name for the embed. If this is specified, the embedded form
|
|
-- will get its own context (accessible at ctx.my_embed_name) and
|
|
-- field names will be rewritten to avoid conflicts with the
|
|
-- parent form. If name is not specified, the embedded form will
|
|
-- share ctx and ctx.form with the parent, and will not have field
|
|
-- names rewritten.
|
|
name = "my_embed_name",
|
|
},
|
|
}
|
|
end)
|
|
```
|
|
|
|
Special characters (excluding `-` and `_`) are not allowed in embed names.
|
|
|
|
## Running code when a form is closed
|
|
|
|
`gui.Container`, `gui.HBox`, `gui.VBox`, and `gui.Stack` elements support an
|
|
`on_quit` callback which gets run when a player closes a form.
|
|
|
|
Note that this function is not called in some cases, such as when the player
|
|
leaves without closing the form or when another form/formspec is shown.
|
|
|
|
This function must not return anything, behaviour may get added to return
|
|
values in the future.
|
|
|
|
```lua
|
|
local parent_form = flow.make_gui(function(player, ctx)
|
|
return gui.VBox{
|
|
on_quit = function(player, ctx)
|
|
core.chat_send_player(player:get_player_name(), "Form closed!")
|
|
end,
|
|
}
|
|
end)
|
|
```
|
|
|
|
If multiple `on_quit` callbacks are specified in different elements, they will
|
|
all get called.
|
|
|
|
## Handling enter keypresses in fields
|
|
|
|
`gui.Field` and `gui.Pwdfield` support an `on_key_enter` callback that gets
|
|
called if enter is pressed:
|
|
|
|
```lua
|
|
local form = flow.make_gui(function(player, ctx)
|
|
return gui.VBox{
|
|
gui.Field{
|
|
label = "Press enter!",
|
|
name = "field",
|
|
on_key_enter = function(player, ctx)
|
|
core.chat_send_player(player:get_player_name(),
|
|
"Field value: " .. dump(ctx.form.field))
|
|
end,
|
|
|
|
-- You can also specify close_on_enter to close the form when enter
|
|
-- is pressed.
|
|
close_on_enter = true,
|
|
},
|
|
}
|
|
end)
|
|
```
|
|
|
|
Notes:
|
|
|
|
- If you're using this callback, please make sure there's some other way to
|
|
trigger the enter action (like a button) to support older flow versions and
|
|
in case I replace this API with a better one in the future.
|
|
- If you want recent mobile clients to call this callback when editing text,
|
|
add `enter_after_edit = true` to the field definition.
|
|
- The similarly named `on_event` gets called whenever the client submits the
|
|
field to the server, which could be at any time, and is not very useful, but
|
|
is still supported for compatibility (and there may be uses for it, such as
|
|
sanitising field values). Be careful not to accidentally use the wrong
|
|
callback.
|