v1.13.4 SmartLine Controller revised

This commit is contained in:
Joachim Stolberg 2018-09-08 18:17:43 +02:00
parent d764a5d4cc
commit 8300e7bde4
6 changed files with 119 additions and 221 deletions

@ -90,11 +90,11 @@ sl.icta_register_action("print", {
{ {
type = "label", type = "label",
name = "lbl", name = "lbl",
label = "Hint: Use a '*' character as reference to any\ncondition state", label = "Use a '*' character as reference to any\ncondition state",
}, },
}, },
button = function(data, environ) button = function(data, environ)
return 'print(...)' return 'print("'..data.text:sub(1,12)..'")'
end, end,
code = function(data, environ) code = function(data, environ)
local s1 = 'local text = string.gsub("'..(smartline.escape(data.text))..'", "*", env.result[#])' local s1 = 'local text = string.gsub("'..(smartline.escape(data.text))..'", "*", env.result[#])'

@ -29,36 +29,36 @@ function smartline.balancer_condition(number1, number2, ratio1, ratio2, owner)
end end
smartline.icta_register_condition("ratio", { smartline.icta_register_condition("ratio", {
title = "Balancer ratio", title = "balancer ratio",
formspec = { formspec = {
{ {
type = "numbers", type = "numbers",
name = "number1", name = "number1",
label = "Pusher1", label = "Pusher1 number",
default = "", default = "",
}, },
{ {
type = "digits", type = "digits",
name = "ratio1", name = "ratio1",
label = "Ratio1", label = "Ratio1 value",
default = "", default = "",
}, },
{ {
type = "numbers", type = "numbers",
name = "number2", name = "number2",
label = "Pusher2", label = "Pusher2 number",
default = "", default = "",
}, },
{ {
type = "digits", type = "digits",
name = "ratio2", name = "ratio2",
label = "Ratio1", label = "Ratio1 value",
default = "", default = "",
}, },
{ {
type = "label", type = "label",
name = "lbl", name = "lbl",
label = "Hint: Pusher1:Pusher2 shall have a\nitem counter ratio of Ratio1:Ratio2.", label = "Hint: Pusher1:Pusher2 shall have an\nitem counter ratio of Ratio1:Ratio2.",
}, },
}, },
-- Return two chunks of executable Lua code for the controller, according: -- Return two chunks of executable Lua code for the controller, according:
@ -68,17 +68,18 @@ smartline.icta_register_condition("ratio", {
return s:format(data.number1, data.number2, data.ratio1, data.ratio2, environ.owner), '~= nil' return s:format(data.number1, data.number2, data.ratio1, data.ratio2, environ.owner), '~= nil'
end, end,
button = function(data, environ) button = function(data, environ)
return "ratio("..(data.ratio1 or "???").."/"..(data.ratio2 or "???")..")" return "ratio("..smartline.fmt_number(data.number1)..","..
smartline.fmt_number(data.number2)..","..data.ratio1..":"..data.ratio2..')'
end, end,
}) })
smartline.icta_register_action("balancer", { smartline.icta_register_action("balancer", {
title = "Balancer Control", title = "balancer action",
formspec = { formspec = {
{ {
type = "label", type = "label",
name = "lbl", name = "lbl",
label = "Hint: Stop one Pusher and start\nit again after 'after' seconds.", label = "Hint: Action part of the balancer rule.",
}, },
}, },
button = function(data, environ) button = function(data, environ)
@ -91,28 +92,29 @@ smartline.icta_register_action("balancer", {
}) })
smartline.icta_register_action("clearcounter", { smartline.icta_register_action("clearcounter", {
title = "Balancer clear counter", title = "balancer clear counter",
formspec = { formspec = {
{ {
type = "numbers", type = "numbers",
name = "number1", name = "number1",
label = "Pusher1", label = "Pusher1 number",
default = "", default = "",
}, },
{ {
type = "numbers", type = "numbers",
name = "number2", name = "number2",
label = "Pusher2", label = "Pusher2 number",
default = "", default = "",
}, },
{ {
type = "label", type = "label",
name = "lbl", name = "lbl",
label = "Hint: Clear both Pusher counters.", label = "Hint: Clear both Pusher counters\ne.g. after controller start.",
}, },
}, },
button = function(data, environ) button = function(data, environ)
return 'balancer()' return 'clear cnt('..smartline.fmt_number(data.number1)..","..
smartline.fmt_number(data.number2)..')'
end, end,
code = function(data, environ) code = function(data, environ)
local s = [[tubelib.send_message("%s", "%s", nil, "clear_counter", nil) local s = [[tubelib.send_message("%s", "%s", nil, "clear_counter", nil)

@ -26,6 +26,14 @@ function sl.operand(s)
end end
end end
function sl.fmt_number(num)
local mtch = num:match('^(%d+).*')
if mtch and num ~= mtch then
return mtch.."..."
end
return num
end
-- '#' is used as placeholder for rule numbers and has to be escaped -- '#' is used as placeholder for rule numbers and has to be escaped
function smartline.escape(s) function smartline.escape(s)
s = tostring(s) s = tostring(s)
@ -33,13 +41,13 @@ function smartline.escape(s)
end end
smartline.icta_register_condition("once", { smartline.icta_register_condition("initial", {
title = "once", title = "initial",
formspec = { formspec = {
{ {
type = "label", type = "label",
name = "lbl", name = "lbl",
label = "Hint: Once after start.", label = "Condition is true only after\ncontroller start.",
}, },
}, },
-- Return two chunks of executable Lua code for the controller, according: -- Return two chunks of executable Lua code for the controller, according:
@ -47,7 +55,7 @@ smartline.icta_register_condition("once", {
code = function(data, environ) code = function(data, environ)
return 'env.ticks', '== 1' return 'env.ticks', '== 1'
end, end,
button = function(data, environ) return "once" end, button = function(data, environ) return "Initial after start" end,
}) })
smartline.icta_register_condition("true", { smartline.icta_register_condition("true", {
@ -56,7 +64,7 @@ smartline.icta_register_condition("true", {
{ {
type = "label", type = "label",
name = "lbl", name = "lbl",
label = "Hint: Condition is always true.", label = "Condition is always true.",
}, },
}, },
code = function(data, environ) code = function(data, environ)
@ -66,25 +74,26 @@ smartline.icta_register_condition("true", {
}) })
smartline.icta_register_condition("condition", { smartline.icta_register_condition("condition", {
title = "Condition", title = "condition",
formspec = { formspec = {
{ {
type = "textlist", type = "textlist",
name = "condition", name = "condition",
label = "the action is executed, if", label = "condition row number",
choices = "condition 1,condition 2,condition 3,condition 4,condition 5,condition 6,condition 7,condition 8", choices = "1,2,3,4,5,6,7,8",
default = "", default = "",
}, },
{ {
type = "textlist", type = "textlist",
name = "operand", name = "operand",
label = "condition",
choices = "was true, was not true", choices = "was true, was not true",
default = "was true", default = "was true",
}, },
{ {
type = "label", type = "label",
name = "lbl", name = "lbl",
label = "Hint: Execute two or several actions\nbased on one condition.", label = "Used to execute two or several\nactions based on one condition.",
}, },
}, },
code = function(data, environ) code = function(data, environ)
@ -95,7 +104,7 @@ smartline.icta_register_condition("condition", {
end end
return "env.condition["..idx.."]", expected_result return "env.condition["..idx.."]", expected_result
end, end,
button = function(data, environ) return data.condition or "???" end, button = function(data, environ) return "cond("..data.condition:sub(-1,-1)..","..data.operand..")" end,
}) })
smartline.icta_register_condition("input", { smartline.icta_register_condition("input", {
@ -104,7 +113,7 @@ smartline.icta_register_condition("input", {
{ {
type = "digits", type = "digits",
name = "number", name = "number",
label = "input from node with number", label = "node number",
default = "", default = "",
}, },
{ {
@ -122,11 +131,11 @@ smartline.icta_register_condition("input", {
{ {
type = "label", type = "label",
name = "lbl", name = "lbl",
label = "Hint: An input is only available,\nif a nodes sends on/of\ncommands to the controller.", label = "An input is only available,\nif a nodes sends on/off\ncommands to the controller.",
}, },
}, },
button = function(data, environ) -- default button label button = function(data, environ) -- default button label
return 'input('..(data.number or "???")..')' return 'inp('..sl.fmt_number(data.number)..','..data.operand.." "..data.value..')'
end, end,
code = function(data, environ) code = function(data, environ)
return 'env.input["'..data.number..'"]', return 'env.input["'..data.number..'"]',
@ -140,7 +149,7 @@ smartline.icta_register_condition("state", {
{ {
type = "digits", type = "digits",
name = "number", name = "number",
label = "state from node with number", label = "node number",
default = "", default = "",
}, },
{ {
@ -160,11 +169,12 @@ smartline.icta_register_condition("state", {
{ {
type = "label", type = "label",
name = "lbl", name = "lbl",
label = "Hint: Read the state from another node.\nWorks for Pusher, Harvester, Quarry,\nand others.", label = "Read the state from a node.\nWorks for Pusher, Harvester, Quarry,\n"..
"and other similar nodes.",
}, },
}, },
button = function(data, environ) -- default button label button = function(data, environ) -- default button label
return 'state('..(data.number or "???")..')' return 'sts('..sl.fmt_number(data.number)..","..data.operand..' '..data.value..')'
end, end,
code = function(data, environ) code = function(data, environ)
return 'tubelib.send_request("'..data.number..'", "state", "")', return 'tubelib.send_request("'..data.number..'", "state", "")',
@ -178,7 +188,7 @@ smartline.icta_register_condition("fuel", {
{ {
type = "digits", type = "digits",
name = "number", name = "number",
label = "fuel state from node with number", label = "node number",
default = "", default = "",
}, },
{ {
@ -198,11 +208,12 @@ smartline.icta_register_condition("fuel", {
{ {
type = "label", type = "label",
name = "lbl", name = "lbl",
label = "Hint: Read the fuel state from another node.\nWorks for Harvester and Quarry", label = "Read the fuel state from a node.\nWorks for Harvester, Quarry,\n"..
"and other fuel consuming nodes.",
}, },
}, },
button = function(data, environ) button = function(data, environ)
return 'fuel('..(data.number or "???")..')' return 'fuel('..sl.fmt_number(data.number)..","..data.operand..' '..data.value..')'
end, end,
code = function(data, environ) code = function(data, environ)
return 'tubelib.send_request("'..data.number..'", "fuel", "")', return 'tubelib.send_request("'..data.number..'", "fuel", "")',
@ -216,31 +227,29 @@ smartline.icta_register_condition("signaltower", {
{ {
type = "digits", type = "digits",
name = "number", name = "number",
label = "state from Signal Tower with number", label = "Signal Tower number",
default = "", default = "",
}, },
{ {
type = "textlist", type = "textlist",
name = "operand", name = "operand",
label = "",
choices = "is,is not", choices = "is,is not",
default = "is", default = "is",
}, },
{ {
type = "textlist", type = "textlist",
name = "value", name = "value",
label = "",
choices = "off,green,amber,red", choices = "off,green,amber,red",
default = "off", default = "off",
}, },
{ {
type = "label", type = "label",
name = "lbl", name = "lbl",
label = "Hint: Read the state from a Signal Tower.", label = "Read the color state\nfrom a Signal Tower.",
}, },
}, },
button = function(data, environ) -- default button label button = function(data, environ) -- default button label
return 'tower('..(data.number or "???")..')' return 'tower('..sl.fmt_number(data.number)..","..data.operand..' '..data.value..')'
end, end,
code = function(data, environ) code = function(data, environ)
return 'tubelib.send_request("'..data.number..'", "state", "")', return 'tubelib.send_request("'..data.number..'", "state", "")',
@ -254,24 +263,24 @@ smartline.icta_register_action("signaltower", {
{ {
type = "numbers", type = "numbers",
name = "number", name = "number",
label = "set Signal Tower with number", label = "Signal Tower number",
default = "", default = "",
}, },
{ {
type = "textlist", type = "textlist",
name = "value", name = "value",
label = "to color", label = "lamp color",
choices = "off,green,amber,red", choices = "off,green,amber,red",
default = "red", default = "red",
}, },
{ {
type = "label", type = "label",
name = "lbl", name = "lbl",
label = "Hint: Turn on a lamp from a Signal Tower.", label = "Turn on/off a Signal Tower lamp.",
}, },
}, },
button = function(data, environ) button = function(data, environ)
return 'tower('..(data.value or "???")..')' return 'tower('..sl.fmt_number(data.number)..","..data.value..')'
end, end,
code = function(data, environ) code = function(data, environ)
local s = 'tubelib.send_message("%s", "%s", nil, "%s", nil)' local s = 'tubelib.send_message("%s", "%s", nil, "%s", nil)'
@ -280,29 +289,29 @@ smartline.icta_register_action("signaltower", {
}) })
smartline.icta_register_action("switch", { smartline.icta_register_action("switch", {
title = "node on/off command", title = "turn node on/off",
formspec = { formspec = {
{ {
type = "numbers", type = "numbers",
name = "number", name = "number",
label = "set node with number", label = "node number(s)",
default = "", default = "",
}, },
{ {
type = "textlist", type = "textlist",
name = "value", name = "value",
label = "to state", label = "state",
choices = "on,off", choices = "on,off",
default = "on", default = "on",
}, },
{ {
type = "label", type = "label",
name = "lbl", name = "lbl",
label = "Hint: Used for pushers, lamps, machines, gates,...", label = "Used for pushers, lamps, machines, gates,...",
}, },
}, },
button = function(data, environ) button = function(data, environ)
return 'turn('..(data.value or "???")..')' return 'turn('..sl.fmt_number(data.number)..","..data.value..')'
end, end,
code = function(data, environ) code = function(data, environ)
local s = 'tubelib.send_message("%s", "%s", nil, "%s", nil)' local s = 'tubelib.send_message("%s", "%s", nil, "%s", nil)'
@ -316,7 +325,7 @@ smartline.icta_register_action("display", {
{ {
type = "numbers", type = "numbers",
name = "number", name = "number",
label = "output to Display with number", label = "Display number",
default = "", default = "",
}, },
{ {
@ -329,13 +338,13 @@ smartline.icta_register_action("display", {
{ {
type = "ascii", type = "ascii",
name = "text", name = "text",
label = "the following text", label = "text",
default = "", default = "",
}, },
{ {
type = "label", type = "label",
name = "lbl", name = "lbl",
label = "Hint: Use a '*' character as reference to any\ncondition state", label = "Use a '*' character as reference\nto any condition result",
}, },
}, },
code = function(data, environ) code = function(data, environ)
@ -345,7 +354,7 @@ smartline.icta_register_action("display", {
return s1.."\n\t"..s2.."\n\t"..s3 return s1.."\n\t"..s2.."\n\t"..s3
end, end,
button = function(data, environ) button = function(data, environ)
return "display("..(data.number or "???")..")" return "lcd("..sl.fmt_number(data.number)..","..data.row..',"'..data.text..'")'
end, end,
}) })
@ -363,7 +372,7 @@ smartline.icta_register_action("cleardisplay", {
return 'tubelib.send_message("'..data.number..'", "'..environ.owner..'", nil, "clear", nil)' return 'tubelib.send_message("'..data.number..'", "'..environ.owner..'", nil, "clear", nil)'
end, end,
button = function(data, environ) button = function(data, environ)
return "clear("..(data.number or "???")..")" return "clear lcd("..sl.fmt_number(data.number)..")"
end, end,
}) })
@ -373,20 +382,20 @@ smartline.icta_register_action("chat", {
{ {
type = "ascii", type = "ascii",
name = "text", name = "text",
label = "send the message", label = "message",
default = "", default = "",
}, },
{ {
type = "label", type = "label",
name = "lbl", name = "lbl",
label = "Hint: The chat message is send to the\nController owner, only.", label = "The chat message is send to the\nController owner, only.",
}, },
}, },
code = function(data, environ) code = function(data, environ)
return 'minetest.chat_send_player("'..environ.owner..'", "[SmartLine Controller] '..data.text..'")' return 'minetest.chat_send_player("'..environ.owner..'", "[SmartLine Controller] '..data.text..'")'
end, end,
button = function(data, environ) button = function(data, environ)
return "chat(...)" return 'chat("'..data.text:sub(1,12)..'")'
end, end,
}) })
@ -420,56 +429,52 @@ smartline.icta_register_action("door", {
{ {
type = "textlist", type = "textlist",
name = "door_state", name = "door_state",
label = "set", label = "door state",
choices = "open,close", choices = "open,close",
default = "open", default = "open",
}, },
{ {
type = "label", type = "label",
name = "lbl1", name = "lbl",
label = "For standard doors like the Steel Doors.", label = "For standard doors like the Steel Doors.\n"..
}, "Use the Tubelib Programmer to\neasily determine a door position.",
{
type = "label",
name = "lbl2",
label = "Hint: Use the Tubelib Programmer to\ndetermine the door position.",
}, },
}, },
code = function(data, environ) code = function(data, environ)
return 'smartline.icta_door_toggle("'..data.pos..'", "'..environ.owner..'", "'..data.door_state..'")' return 'smartline.icta_door_toggle("'..data.pos..'", "'..environ.owner..'", "'..data.door_state..'")'
end, end,
button = function(data, environ) button = function(data, environ)
return "door("..(data.door_state or "???")..")" return 'door("'..data.pos..'",'..data.door_state..")"
end, end,
}) })
function smartline.icta_player_detect(number, name) function smartline.icta_player_detect(number, name)
local state = tubelib.send_request(number, "name", nil) local state = tubelib.send_request(number, "name", nil)
if (name == "*" and state ~= "") or state == name then if (name == "*" and state ~= "") or string.find(name, state) then
return state return state
end end
return nil return nil
end end
smartline.icta_register_condition("playerdetector", { smartline.icta_register_condition("playerdetector", {
title = "Player Detector: name request", title = "Player Detector name request",
formspec = { formspec = {
{ {
type = "digits", type = "digits",
name = "number", name = "number",
label = "name from player detector with number", label = "Player Detector number",
default = "", default = "",
}, },
{ {
type = "ascii", type = "ascii",
name = "name", name = "name",
label = "is", label = "player name(s) or * for all",
default = "", default = "",
}, },
{ {
type = "label", type = "label",
name = "lbl", name = "lbl",
label = "Hint: Read and check the name\nfrom a Player Detector.\n Use a '*' character for all player names.", label = "Read and check the name\nfrom a Player Detector.\n Use a '*' character for all player names.",
}, },
}, },
@ -477,6 +482,6 @@ smartline.icta_register_condition("playerdetector", {
return 'smartline.icta_player_detect("'..data.number..'", "'..data.name..'")', "~= nil" return 'smartline.icta_player_detect("'..data.number..'", "'..data.name..'")', "~= nil"
end, end,
button = function(data, environ) button = function(data, environ)
return "detector()" return "detector("..sl.fmt_number(data.number)..","..data.name:sub(1,8)..")"
end, end,
}) })

@ -44,10 +44,12 @@ local Cache = {}
local FS_DATA = gen_table(smartline.NUM_RULES, {}) local FS_DATA = gen_table(smartline.NUM_RULES, {})
local function output(pos, text) local function output(pos, text, flush_buffer)
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
text = meta:get_string("output") .. "\n" .. (text or "") if not flush_buffer then
text = text:sub(-500,-1) text = meta:get_string("output") .. "\n" .. (text or "")
text = text:sub(-500,-1)
end
meta:set_string("output", text) meta:set_string("output", text)
meta:set_string("formspec", smartline.formspecOutput(meta)) meta:set_string("formspec", smartline.formspecOutput(meta))
end end
@ -336,6 +338,10 @@ local function on_receive_fields(pos, formname, fields, player)
elseif fields.clear then elseif fields.clear then
meta:set_string("output", "<press update>") meta:set_string("output", "<press update>")
meta:set_string("formspec", smartline.formspecOutput(meta)) meta:set_string("formspec", smartline.formspecOutput(meta))
elseif fields.list then
local fs_data = minetest.deserialize(meta:get_string("fs_data")) or FS_DATA
local s = smartline.listing(fs_data)
output(pos, s, true)
elseif fields.tab == "1" then elseif fields.tab == "1" then
local fs_data = minetest.deserialize(meta:get_string("fs_data")) or FS_DATA local fs_data = minetest.deserialize(meta:get_string("fs_data")) or FS_DATA
meta:set_string("formspec", smartline.formspecRules(meta, fs_data, sOUTPUT)) meta:set_string("formspec", smartline.formspecRules(meta, fs_data, sOUTPUT))

@ -38,12 +38,12 @@ Actions are:
The controller executes all rules cyclically. The controller executes all rules cyclically.
The cycle time for each rule is configurable The cycle time for each rule is configurable
(1..1000 sec). (1..1000 sec).
0 means, the rule will only be called, when 0 means, the rule will only be called, if
the controller received a command from the controller received a command from
another node, like buttons. another node, such as buttons.
Actions can be deleyed. Therefore, the Actions can be delayed. Therefore, the
after value can be set (0..1000 sec). 'after' value can be set (0..1000 sec).
Edit command examples: Edit command examples:
- 'x 1 8' exchange rows 1 with row 8 - 'x 1 8' exchange rows 1 with row 8
@ -97,17 +97,27 @@ local function button(data)
end end
end end
function smartline.listing(fs_data)
local tbl = {}
for idx = 1,smartline.NUM_RULES do
tbl[#tbl+1] = idx.." ("..fs_data[idx].cycle.."s): IF "..button(fs_data[idx].cond)
tbl[#tbl+1] = " THEN "..button(fs_data[idx].actn).." after "..fs_data[idx].after.."s\n"
end
return table.concat(tbl)
end
local function formspec_rules(fs_data) local function formspec_rules(fs_data)
local tbl = {"field[0,0;0,0;_type_;;main]".. local tbl = {"field[0,0;0,0;_type_;;main]"..
"label[0.8,0;Cycle/s:]label[2.8,0;IF cond:]label[7,0;THEN action:]label[11.4,0;after/s:]"} "label[0.4,0;Cycle/s:]label[2.5,0;IF cond:]label[7,0;THEN action:]label[11.5,0;after/s:]"}
for idx = 1,smartline.NUM_RULES do for idx = 1,smartline.NUM_RULES do
local ypos = idx * 0.75 - 0.4 local ypos = idx * 0.75 - 0.4
tbl[#tbl+1] = "label[0,"..(0.2+ypos)..";"..idx.."]" tbl[#tbl+1] = "label[0,"..(0.2+ypos)..";"..idx.."]"
tbl[#tbl+1] = "field[0.9,"..(0.3+ypos)..";1.8,1;cycle"..idx..";;"..(fs_data[idx].cycle or "").."]" tbl[#tbl+1] = "field[0.7,"..(0.3+ypos)..";1.4,1;cycle"..idx..";;"..(fs_data[idx].cycle or "").."]"
tbl[#tbl+1] = "button[2.5,"..ypos..";4.3,1;cond"..idx..";"..button(fs_data[idx].cond).."]" tbl[#tbl+1] = "button[1.9,"..ypos..";4.9,1;cond"..idx..";"..minetest.formspec_escape(button(fs_data[idx].cond)).."]"
tbl[#tbl+1] = "button[6.8,"..ypos..";4.3,1;actn"..idx..";"..button(fs_data[idx].actn).."]" tbl[#tbl+1] = "button[6.8,"..ypos..";4.9,1;actn"..idx..";"..minetest.formspec_escape(button(fs_data[idx].actn)).."]"
tbl[#tbl+1] = "field[11.4,"..(0.3+ypos)..";1.8,1;after"..idx..";;"..(fs_data[idx].after or "").."]" tbl[#tbl+1] = "field[12,"..(0.3+ypos)..";1.4,1;after"..idx..";;"..(fs_data[idx].after or "").."]"
end end
return table.concat(tbl) return table.concat(tbl)
end end
@ -198,6 +208,7 @@ function smartline.formspecOutput(meta)
default.gui_slots.. default.gui_slots..
"tabheader[0,0;tab;rules,outp,notes,help;2;;true]".. "tabheader[0,0;tab;rules,outp,notes,help;2;;true]"..
"textarea[0.3,0.2;13,8.3;output;Output:;"..output.."]".. "textarea[0.3,0.2;13,8.3;output;Output:;"..output.."]"..
"button[5.5,7.5;1.8,1;list;List]"..
"button[7.4,7.5;1.8,1;clear;Clear]".. "button[7.4,7.5;1.8,1;clear;Clear]"..
"button[9.3,7.5;1.8,1;update;Update]".. "button[9.3,7.5;1.8,1;update;Update]"..
"button[11.2,7.5;1.8,1;"..cmnd.."]" "button[11.2,7.5;1.8,1;"..cmnd.."]"
@ -229,132 +240,3 @@ function smartline.formspecHelp(offs)
--"label[0.2,0;test]".. --"label[0.2,0;test]"..
"scrollbar[12,1;0.5,7;vertical;sb_help;"..offs.."]" "scrollbar[12,1;0.5,7;vertical;sb_help;"..offs.."]"
end end
--local function my_on_receive_fields(pos, formname, fields, player)
-- local meta = minetest.get_meta(pos)
-- local owner = meta:get_string("owner")
-- local state = meta:get_int("state")
-- if not player or not player:is_player() then
-- return
-- end
-- local fs_data = minetest.deserialize(meta:get_string("fs_data")) or {}
-- local output = ""
-- local readonly = player:get_player_name() ~= owner
-- print("fields", dump(fields))
-- -- FIRST: test if command entered?
-- if fields.ok then
-- if not readonly then
-- output = edit_command(fs_data, fields.cmnd)
-- smartline.stop_controller(pos, fs_data)
-- meta:set_string("formspec", formspec_main(tubelib.STOPPED, fs_data, output))
-- meta:set_string("fs_data", minetest.serialize(fs_data))
-- end
-- -- SECOND: eval none edit events (events based in __type__)?
-- elseif fields.help then
-- meta:set_string("formspec", formspec_help(1))
---- elseif fields.state then
---- meta:set_string("formspec", formspec_state(meta, fs_data))
---- elseif fields.update then
---- meta:set_string("formspec", formspec_state(meta, fs_data))
-- elseif fields._cancel_ then
-- fs_data = minetest.deserialize(meta:get_string("fs_old"))
-- meta:set_string("formspec", formspec_main(state, fs_data, sOUTPUT))
-- elseif fields.close then
-- meta:set_string("formspec", formspec_main(state, fs_data, sOUTPUT))
---- elseif fields.sb_help then
---- local evt = minetest.explode_scrollbar_event(fields.sb_help)
---- if evt.type == "CHG" then
---- meta:set_string("formspec", formspec_help(evt.value))
---- end
---- elseif fields.button then
---- if not readonly then
---- local number = meta:get_string("number")
---- local state = meta:get_int("state")
---- if state == tubelib.RUNNING then
---- smartline.stop_controller(pos, fs_data)
---- meta:set_string("formspec", formspec_main(tubelib.STOPPED, fs_data, sOUTPUT))
---- else
---- formspec2runtime_rule(number, owner, fs_data)
---- start_controller(pos, number, fs_data)
---- meta:set_string("formspec", formspec_main(tubelib.RUNNING, fs_data, sOUTPUT))
---- end
---- end
---- -- THIRD: evaluate edit events from sub-menus
-- elseif fields._col_ == "cond" then
-- local row = tonumber(fields._row_ or 1)
-- fs_data["cond"..row] = smartline.cond_eval_input(fs_data["cond"..row], fields)
-- meta:set_string("formspec", smartline.cond_formspec(row, fs_data["cond"..row]))
-- meta:set_string("fs_data", minetest.serialize(fs_data))
-- elseif fields._type_ == "main" then
-- fs_data = eval_formspec_main(meta, fs_data, fields, readonly)
-- meta:set_string("fs_data", minetest.serialize(fs_data))
---- elseif fields._type_ == "label" then
---- fs_data = eval_formspec_label(meta, fs_data, fields, readonly)
---- meta:set_string("fs_data", minetest.serialize(fs_data))
---- elseif fields._type_ == "cond" then
---- fs_data = eval_formspec_cond(meta, fs_data, fields, readonly)
---- meta:set_string("fs_data", minetest.serialize(fs_data))
---- elseif fields._type_ == "oprnd" then
---- fs_data = eval_formspec_oprnd(meta, fs_data, fields, readonly)
---- meta:set_string("fs_data", minetest.serialize(fs_data))
---- elseif fields._type_ == "actn" then
---- fs_data = eval_formspec_actn(meta, fs_data, fields, readonly)
---- meta:set_string("fs_data", minetest.serialize(fs_data))
---- elseif fields._type_ == "help" then
---- meta:set_string("formspec", formspec_main(state, fs_data, sOUTPUT))
---- elseif fields._type_ == "state" then
---- meta:set_string("formspec", formspec_main(state, fs_data, sOUTPUT))
-- end
-- -- FOURTH: back to main menu
-- if fields._exit_ then
-- meta:set_string("formspec", formspec_main(state, fs_data, sOUTPUT))
-- end
--end
--function smartline.on_receive_fields(pos, formname, fields, player)
-- local meta = minetest.get_meta(pos)
-- local owner = meta:get_string("owner")
-- if not player or not player:is_player() then
-- return
-- end
-- local readonly = player:get_player_name() ~= owner
-- print("fields", dump(fields))
-- if fields.cancel == nil then
-- if fields.rules then
-- --meta:set_string("rules", fields.rules)
-- meta:set_string("formspec", smartline.formspecRules(meta))
-- elseif fields.notes then
-- meta:set_string("notes", fields.notes)
-- meta:set_string("formspec", formspecNotes(meta))
-- end
-- end
-- if fields.update then
-- meta:set_string("formspec", formspecOutput(meta))
-- elseif fields.clear then
-- meta:set_string("output", "<press update>")
-- meta:set_string("formspec", formspecOutput(meta))
-- elseif fields.tab == "1" then
-- meta:set_string("formspec", smartline.formspecRules(meta))
-- elseif fields.tab == "2" then
-- meta:set_string("formspec", formspecOutput(meta))
-- elseif fields.tab == "3" then
-- meta:set_string("formspec", formspecNotes(meta))
-- elseif fields.tab == "4" then
-- meta:set_string("formspec", formspecHelp(1))
-- elseif fields.start == "Start" then
-- start_controller(pos)
-- minetest.log("action", player:get_player_name() ..
-- " starts the sl_controller at ".. minetest.pos_to_string(pos))
-- elseif fields.stop == "Stop" then
-- stop_controller(pos)
-- end
--end

@ -31,20 +31,23 @@ local function add_controls_to_table(tbl, kvDefinition, kvSelect)
if kvDefinition[kvSelect.choice] then if kvDefinition[kvSelect.choice] then
local lControls = kvDefinition[kvSelect.choice].formspec local lControls = kvDefinition[kvSelect.choice].formspec
for idx,elem in ipairs(lControls) do for idx,elem in ipairs(lControls) do
if elem.label and elem.label ~= "" then if elem.type == "label" then
tbl[#tbl+1] = "label[0,"..offs..";"..elem.label.."]" tbl[#tbl+1] = "label[0,"..offs..";Description:\n"..elem.label.."]"
offs = offs + 0.4
elseif elem.label and elem.label ~= "" then
tbl[#tbl+1] = "label[0,"..offs..";"..elem.label..":]"
offs = offs + 0.4 offs = offs + 0.4
end end
if elem.type == "numbers" or elem.type == "digits" or elem.type == "letters" if elem.type == "numbers" or elem.type == "digits" or elem.type == "letters"
or elem.type == "ascii" then or elem.type == "ascii" then
val = kvSelect[elem.name] or elem.default val = kvSelect[elem.name] or elem.default
tbl[#tbl+1] = "field[0.3,"..(offs+0.2)..";8,1;"..elem.name..";;"..val.."]" tbl[#tbl+1] = "field[0.3,"..(offs+0.2)..";8,1;"..elem.name..";;"..val.."]"
offs = offs + 1 offs = offs + 0.9
elseif elem.type == "textlist" then elseif elem.type == "textlist" then
local l = elem.choices:split(",") local l = elem.choices:split(",")
val = index(l, kvSelect[elem.name]) or elem.default val = index(l, kvSelect[elem.name]) or elem.default
tbl[#tbl+1] = "dropdown[0.0,"..(offs)..";8.5,1.4;"..elem.name..";"..elem.choices..";"..val.."]" tbl[#tbl+1] = "dropdown[0.0,"..(offs)..";8.5,1.4;"..elem.name..";"..elem.choices..";"..val.."]"
offs = offs + 1 offs = offs + 0.9
end end
end end
end end
@ -161,9 +164,9 @@ function smartline.submenu_generate_formspec(row, col, title, lKeys, lChoice, kv
kvSelect = {choice = "default"} kvSelect = {choice = "default"}
end end
local tbl = {"size[8.2,9]".. local tbl = {"size[8.2,9]"..
--default.gui_bg.. TODO default.gui_bg..
--default.gui_bg_img.. default.gui_bg_img..
--default.gui_slots.. default.gui_slots..
"field[0,0;0,0;_row_;;"..row.."]".. "field[0,0;0,0;_row_;;"..row.."]"..
"field[0,0;0,0;_col_;;"..col.."]"} "field[0,0;0,0;_col_;;"..col.."]"}
@ -172,7 +175,7 @@ function smartline.submenu_generate_formspec(row, col, title, lKeys, lChoice, kv
tbl[#tbl+1] = "label[0,0;"..title..":]" tbl[#tbl+1] = "label[0,0;"..title..":]"
tbl[#tbl+1] = "dropdown[0,0.5;8.5,1;choice;"..sChoice..";"..idx.."]" tbl[#tbl+1] = "dropdown[0,0.5;8.5,1;choice;"..sChoice..";"..idx.."]"
tbl = add_controls_to_table(tbl, kvDefinition, kvSelect) tbl = add_controls_to_table(tbl, kvDefinition, kvSelect)
tbl[#tbl+1] = "field[0.2,8.7;4,1;_button_;Button text;"..(kvSelect._button_ or "").."]" tbl[#tbl+1] = "field[0.2,8.7;4,1;_button_;Alternative button text;"..(kvSelect._button_ or "").."]"
tbl[#tbl+1] = "button[4,8.4;2,1;_cancel_;cancel]" tbl[#tbl+1] = "button[4,8.4;2,1;_cancel_;cancel]"
tbl[#tbl+1] = "button[6,8.4;2,1;_exit_;ok]" tbl[#tbl+1] = "button[6,8.4;2,1;_exit_;ok]"
return table.concat(tbl) return table.concat(tbl)