From 0e00d9d33d5289bb2e8c2f0a6645c7724871bb69 Mon Sep 17 00:00:00 2001 From: Signal Date: Mon, 26 Jan 2026 15:28:26 -0500 Subject: [PATCH] Fix models and buttons, and let containers handle inventories properly. --- README.md | 6 +++--- init.lua | 60 +++++++++++++++++++++++++++++++++++++++---------------- 2 files changed, 46 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 8afdf10..98e940e 100644 --- a/README.md +++ b/README.md @@ -278,9 +278,9 @@ Creates a model element. Methods: * `:style([state, ]props)`: Applies the styling properties `props` to the model when in the `state` state. If omitted, `state` is `"default"`. -* `:rotation(rotation[, continuous])`: Set the rotation of the model in the view, and optionally whether it is continuous. +* `:rotation(rotation_x[, rotation_y[, continuous]])`: Set the X and Y rotation of the model in the view, and optionally whether it is continuous. * `:mouse_control(state)`: Passing `false` will prevent the user from changing the model's rotation by clicking and dragging. -* `:animated(frames, speed)`: Sets an animation on the model defined by the given frame range and speed. +* `:animated(start, end_, speed)`: Sets an animation on the model defined by the given frame range and speed. ### `imfs.button(x, y, width, height, label)` @@ -295,7 +295,7 @@ Methods: ### `imfs.list(x, y, width, height, location = "current_player", list = "main"[, start])` -Creates an inventory element. +Creates an inventory element. Note that `width` and `height` are in units of inventory slots; when set to flex ratios, however, they will resolve to the maximum number of slots that can be displayed in their assigned width. `imfs.inventory` is an alias for this element. diff --git a/init.lua b/init.lua index 8cad266..9088fdc 100644 --- a/init.lua +++ b/init.lua @@ -163,9 +163,18 @@ local function get(e, x) local item = e[x] local mt = getmetatable(item) if mt == state or mt == DerivedState then - return fe(item()) + return fe(tostring(item())) end - return fe(item) + return fe(tostring(item)) +end + +local function get_raw(e, x) + local item = e[x] + local mt = getmetatable(item) + if mt == state or mt == DerivedState then + return item() + end + return item end -- MARK: Elements @@ -361,28 +370,46 @@ local fs_model = { for _, x in pairs(e._styles) do out[#out +1] = x:render() end + + local textures = get_raw(e, "textures") + if type(textures) ~= "string" then + textures = table.concat(textures, ",") + end + + local as = get(e, "_animation_start") + local ae = get(e, "_animation_end") + local animation = "" + if as and ae then + animation = string.format("%s,%s", fe(as), fe(ae)) + end + out[#out +1] = string.format( - "model[%f,%f;%f,%f;%s;%s;%s;%f;%s;%s;%s;%f]", + "model[%f,%f;%f,%f;%s;%s;%s;%s,%s;%s;%s;%s;%s]", x or get(e, "x"), y or get(e, "y"), w or get(e, "w"), h or get(e, "h"), e.__id, - get(e, "mesh"), get(e, "textures"), - get(e, "_rotation") or "", get(e, "_continuous") or "", - get(e, "_mouse_control"), - get(e, "_animation") or "", get(e, "_animation_speed") + get(e, "mesh"), textures, + get(e, "_rotation_x") or "", get(e, "_rotation_y") or "", get(e, "_continuous") or "", + get(e, "_mouse_control") or "", + animation, get(e, "_animation_speed") or "1" ) return table.concat(out) end, - rotation = function(e, rot, continuous) - e._rotation = rot + rotation = function(e, x, y, continuous) + e._rotation_x = x + e._rotation_y = y or 0 e._continuous = continuous + return e end, mouse_control = function(e, mouse_control) e._mouse_control = mouse_control ~= false and true or false + return e end, - animated = function(frames, speed) - e._animation = frames + animated = function(start, end_, speed) + e._animation_start = start + e._animation_end = end_ e._animation_speed = speed or 1 + return e end, style = add_elem_style, tooltip = add_elem_tooltip, @@ -390,7 +417,7 @@ local fs_model = { fs_model.__index = fs_model setmetatable(fs_model, { __call = function(_, x, y, w, h, mesh, textures) - local e = {x = x, y = y, w = w, h = h, mesh = mesh, textures = textures, mouse_control = true} + local e = {x = x, y = y, w = w, h = h, mesh = mesh, textures = textures, _mouse_control = true, _styles = {}} e.__id = new_id() setmetatable(e, fs_model) table.insert(ctx, e) @@ -421,12 +448,15 @@ local fs_button = { image = function(e, img, pressed_img) e._image = img e._image_pressed = pressed_img + return e end, item_image = function(e, item) e._item = item + return e end, exit = function(e) e._exit = true + return e end, onclick = function(e, fn) ctx._events.on_click[e.__id] = fn @@ -472,17 +502,13 @@ local fs_list = { w = w or get(e, "w") h = h or get(e, "h") - -- These lines will cause `w` and `h` to be interpreted as formspec coordinates rather than numbers of slots. - -- w = w -((w -1) /4) - -- h = h -((h -1) /4) - return string.format("list[%s;%s;%f,%f;%d,%d;%s]", get(e, "location"), get(e, "list"), x or get(e, "x"), y or get(e, "y"), w, h, get(e, "start")) end } fs_list.__index = fs_list setmetatable(fs_list, { __call = function(_, x, y, w, h, location, list, start) - local e = {x = x, y = y, w = w, h = h, location = location or "current_player", list = list or "main", start = start or ""} + local e = {x = x, y = y, w = type(w == "string") and w or w +((w -1) /4), h = type(h) == "string" and h or h +((h -1) /4), location = location or "current_player", list = list or "main", start = start or ""} e.__id = new_id() setmetatable(e, fs_list) table.insert(ctx, e)