6.2 KiB
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:
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.
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:
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 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
andsize
elements aren't included in the returned formspec and are included in a third return value. Setstandalone
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, whererender_to_formspec_string
should be called and the newprocess_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:
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.
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:
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.