aboutsummaryrefslogtreecommitdiff
path: root/advtrains_interlocking/signal_aspect_ui.lua
diff options
context:
space:
mode:
Diffstat (limited to 'advtrains_interlocking/signal_aspect_ui.lua')
-rw-r--r--advtrains_interlocking/signal_aspect_ui.lua262
1 files changed, 262 insertions, 0 deletions
diff --git a/advtrains_interlocking/signal_aspect_ui.lua b/advtrains_interlocking/signal_aspect_ui.lua
new file mode 100644
index 0000000..a81b7fe
--- /dev/null
+++ b/advtrains_interlocking/signal_aspect_ui.lua
@@ -0,0 +1,262 @@
+local F = advtrains.formspec
+local players_aspsel = {}
+
+local function describe_main_aspect(spv)
+ if spv == 0 then
+ return attrans("Danger (halt)")
+ elseif spv == -1 then
+ return attrans("Continue at maximum speed")
+ elseif not spv then
+ return attrans("Continue with current speed limit")
+ else
+ return attrans("Continue with the speed limit of @1", tostring(spv))
+ end
+end
+
+local function describe_shunt_aspect(shunt)
+ if shunt then
+ return attrans("Shunting allowed")
+ else
+ return attrans("No shunting")
+ end
+end
+
+local function describe_distant_aspect(spv)
+ if spv == 0 then
+ return attrans("Expect to stop at the next signal")
+ elseif spv == -1 then
+ return attrans("Expect to continue at maximum speed")
+ elseif not spv then
+ return attrans("No distant signal information")
+ else
+ return attrans("Expect to continue with a speed limit of @1", tostring(spv))
+ end
+end
+
+advtrains.interlocking.describe_main_aspect = describe_main_aspect
+advtrains.interlocking.describe_shunt_aspect = describe_shunt_aspect
+advtrains.interlocking.describe_distant_aspect = describe_distant_aspect
+
+local function dsel(p, q, x, y)
+ if p == nil then
+ if q then
+ return x
+ else
+ return y
+ end
+ elseif p then
+ return x
+ else
+ return y
+ end
+end
+
+local function describe_supported_aspects(suppasp, isasp)
+ local t = {}
+
+ local entries = {attrans("Use default value")}
+ local selid = 0
+ local mainasps = suppasp.main
+ if type(mainasps) ~= "table" then
+ mainasps = {mainasps}
+ end
+ for idx, spv in ipairs(mainasps) do
+ if isasp and spv == rawget(isasp, "main") then
+ selid = idx
+ end
+ entries[idx+1] = describe_main_aspect(spv)
+ end
+ t.main = entries
+ t.main_current = selid+1
+ t.main_string = tostring(isasp.main)
+ if t.main == nil then
+ t.main_string = ""
+ end
+
+ t.shunt = {
+ attrans("No shunting"),
+ attrans("Shunting allowed"),
+ attrans("Proceed as main"),
+ }
+
+ t.shunt_current = dsel(suppasp.shunt, isasp.shunt, 2, 1)
+ if dsel(suppasp.proceed_as_main, isasp.proceed_as_main, t.shunt_current == 1) then
+ t.shunt_current = 3
+ end
+ t.shunt_const = suppasp.shunt ~= nil
+
+ if suppasp.group then
+ local gdef = advtrains.interlocking.aspect.get_group_definition(suppasp.group)
+ if gdef then
+ t.group = suppasp.group
+ t.groupdef = gdef
+ local entries = {}
+ local selid = 1
+ for idx, name in ipairs(suppasp.name or {}) do
+ entries[idx] = gdef.aspects[name].label
+ if suppasp.group == isasp.group and name == isasp.name then
+ selid = idx
+ end
+ end
+ t.name = entries
+ t.name_current = selid
+ end
+ end
+
+ return t
+end
+
+advtrains.interlocking.describe_supported_aspects = describe_supported_aspects
+
+local function make_signal_aspect_selector(suppasp, purpose, isasp)
+ local t = describe_supported_aspects(suppasp, isasp)
+ local formmode = 1
+
+ local pos
+ if type(purpose) == "table" then
+ formmode = 2
+ pos = purpose.pos
+ end
+
+ local form = {
+ "formspec_version[4]",
+ string.format("size[8,%f]", ({5.75, 10.75})[formmode]),
+ F.S_label(0.5, 0.5, "Select signal aspect"),
+ }
+ local h0 = ({0, 1.5})[formmode]
+ form[#form+1] = F.S_label(0.5, 1.5+h0, "Main aspect")
+ form[#form+1] = F.S_label(0.5, 3+h0, "Shunt aspect")
+ form[#form+1] = F.S_button_exit(0.5, 4.5+h0, 7, "asp_save", "Save signal aspect")
+ if formmode == 1 then
+ form[#form+1] = F.label(0.5, 1, purpose)
+ form[#form+1] = F.field(0.5, 2, 7, "asp_mainval", "", t.main_string)
+ elseif formmode == 2 then
+ if t.group then
+ form[#form+1] = F.S_label(0.5, 1.5, "Signal aspect group: @1", t.groupdef.label)
+ form[#form+1] = F.dropdown(0.5, 2, 7, "asp_namesel", t.name, t.name_current, true)
+ else
+ form[#form+1] = F.S_label(0.5, 1.5, "This signal does not belong to a signal aspect group.")
+ form[#form+1] = F.S_label(0.5, 2, "You can not use a predefined signal aspect.")
+ end
+ form[#form+1] = F.S_label(0.5, 1, "Signal at @1", minetest.pos_to_string(pos))
+ form[#form+1] = F.dropdown(0.5, 3.5, 7, "asp_mainsel", t.main, t.main_current, true)
+ form[#form+1] = advtrains.interlocking.make_ip_formspec_component(pos, 0.5, 7, 7)
+ form[#form+1] = advtrains.interlocking.make_short_dst_formspec_component(pos, 0.5, 8.5, 7)
+ end
+
+ if formmode == 2 and t.shunt_const then
+ form[#form+1] = F.label(0.5, 3.5+h0, t.shunt[t.shunt_current])
+ form[#form+1] = F.S_label(0.5, 4+h0, "The shunt aspect cannot be changed.")
+ else
+ form[#form+1] = F.dropdown(0.5, 3.5+h0, 7, "asp_shunt", t.shunt, t.shunt_current, true)
+ end
+
+ return table.concat(form)
+end
+
+function advtrains.interlocking.show_signal_aspect_selector(pname, p_suppasp, p_purpose, callback, isasp)
+ local suppasp = p_suppasp or {
+ main = {0, -1},
+ dst = {false},
+ shunt = false,
+ info = {},
+ }
+ local purpose = p_purpose or ""
+ local pos
+ if type(p_purpose) == "table" then
+ pos = p_purpose
+ purpose = {pname = pname, pos = pos}
+ end
+
+ local form = make_signal_aspect_selector(suppasp, purpose, isasp)
+ if not form then
+ return
+ end
+
+ local token = advtrains.random_id()
+ minetest.show_formspec(pname, "at_il_sigaspdia_"..token, form)
+ minetest.after(0, function()
+ players_aspsel[pname] = {
+ purpose = purpose,
+ suppasp = suppasp,
+ callback = callback,
+ token = token,
+ }
+ end)
+end
+
+local function usebool(sup, val, free)
+ if sup == nil then
+ return val == free
+ else
+ return sup
+ end
+end
+
+local function get_aspect_from_formspec(suppasp, fields, psl)
+ local namei, group, name = tonumber(fields.asp_namesel), suppasp.group, nil
+ local gdef = advtrains.interlocking.aspect.get_group_definition(group)
+ if gdef then
+ local names = suppasp.name or {}
+ name = names[namei] or names[names]
+ else
+ group = nil
+ end
+ local maini = tonumber(fields.asp_mainsel)
+ local main = (suppasp.main or {})[(maini or 0)-1]
+ if not maini then
+ local mainval = fields.asp_mainval
+ if mainval == "-1" then
+ main = -1
+ elseif mainval == "x" then
+ main = false
+ elseif string.match(mainval, "^%d+$") then
+ main = tonumber(mainval)
+ else
+ main = nil
+ end
+ elseif maini <= 1 then
+ main = nil
+ end
+ local shunti = tonumber(fields.asp_shunt)
+ local shunt = suppasp.shunt
+ if shunt == nil then
+ shunt = shunti == 2
+ end
+ local proceed_as_main = suppasp.proceed_as_main
+ if proceed_as_main == nil then
+ proceed_as_main = shunti == 3
+ end
+ return advtrains.interlocking.aspect {
+ main = main,
+ shunt = shunt,
+ proceed_as_main = proceed_as_main,
+ info = {},
+ name = name,
+ group = group,
+ }
+end
+
+minetest.register_on_player_receive_fields(function(player, formname, fields)
+ local pname = player:get_player_name()
+ local psl = players_aspsel[pname]
+ if psl then
+ if formname == "at_il_sigaspdia_"..psl.token then
+ local suppasp = psl.suppasp
+ if fields.asp_save then
+ local asp
+ asp = get_aspect_from_formspec(suppasp, fields, psl)
+ if asp then
+ psl.callback(pname, asp)
+ end
+ end
+ if type(psl.purpose) == "table" then
+ local pos = psl.purpose.pos
+ advtrains.interlocking.handle_ip_formspec_fields(pname, pos, fields)
+ advtrains.interlocking.handle_dst_formspec_fields(pname, pos, fields)
+ end
+ else
+ players_aspsel[pname] = nil
+ end
+ end
+end)