diff --git a/README.md b/README.md index 1b98b4f..749b918 100644 --- a/README.md +++ b/README.md @@ -566,4 +566,31 @@ call `form:render_to_formspec_string(player, ctx, standalone)`. > [!CAUTION] > 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) +``` +
diff --git a/embed.lua b/embed.lua index 05076ca..151594c 100644 --- a/embed.lua +++ b/embed.lua @@ -2,30 +2,32 @@ local embed_create_ctx_mt = {} function embed_create_ctx_mt:__index(key) -- rawget ensures we don't do recursion - local form = rawget(self, "_flow_embed_parent_form") + local ctx = rawget(self, "_flow_embed_parent_ctx") local prefix = rawget(self, "_flow_embed_prefix") - return form[prefix .. key] + return ctx.form[prefix .. key] end function embed_create_ctx_mt:__newindex(key, value) - local form = rawget(self, "_flow_embed_parent_form") + local ctx = rawget(self, "_flow_embed_parent_ctx") local prefix = rawget(self, "_flow_embed_prefix") - form[prefix .. key] = value + ctx.form[prefix .. key] = value end -local function embed_create_ctx(ctx, name, prefix) - if not ctx[name] then - ctx[name] = {} +local function embed_create_ctx(parent_ctx, name, prefix) + if not parent_ctx[name] then + parent_ctx[name] = {} end - if not ctx[name].form then - ctx[name].form = {} + local new_ctx = parent_ctx[name] + if not new_ctx.form then + new_ctx.form = {} end - if getmetatable(ctx[name].form) ~= embed_create_ctx_mt then - ctx[name].form._flow_embed_prefix = prefix - ctx[name].form._flow_embed_parent_form = ctx.form - ctx[name].form = setmetatable(ctx[name].form, embed_create_ctx_mt) + + if getmetatable(new_ctx.form) ~= embed_create_ctx_mt then + new_ctx.form._flow_embed_prefix = prefix + new_ctx.form._flow_embed_parent_ctx = parent_ctx + setmetatable(new_ctx.form, embed_create_ctx_mt) end - return ctx[name] + return new_ctx end local function embed_wrap_callback_func(func, name, prefix)