aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authororwell <orwell@bleipb.de>2024-12-05 23:31:11 +0100
committerorwell <orwell@bleipb.de>2024-12-05 23:31:11 +0100
commitced8d8998de6b2cb6a758224641c125d02efea41 (patch)
tree025a83e2a7b15ea07b8a0b99f92d570b8a2d954c
parentb2889e33ba389c936b9d6b1ca5be27ef8f147280 (diff)
downloadadvtrains-ced8d8998de6b2cb6a758224641c125d02efea41.tar.gz
advtrains-ced8d8998de6b2cb6a758224641c125d02efea41.tar.bz2
advtrains-ced8d8998de6b2cb6a758224641c125d02efea41.zip
Route Edit: Support aspect selection per signal, support call-on routes
-rw-r--r--advtrains_interlocking/route_ui.lua148
-rw-r--r--advtrains_interlocking/routesetting.lua23
-rwxr-xr-xadvtrains_interlocking/tcb_ts_ui.lua4
3 files changed, 125 insertions, 50 deletions
diff --git a/advtrains_interlocking/route_ui.lua b/advtrains_interlocking/route_ui.lua
index 2b79f68..2b7e2e5 100644
--- a/advtrains_interlocking/route_ui.lua
+++ b/advtrains_interlocking/route_ui.lua
@@ -11,9 +11,10 @@ local function sigd_to_string(sigd)
return minetest.pos_to_string(sigd.p).." / "..lntrans[sigd.s]
end
+-- indexed by pname
+local sel_rpartcache = {}
-
-function atil.show_route_edit_form(pname, sigd, routeid)
+function atil.show_route_edit_form(pname, sigd, routeid, sel_rpartidx)
if not minetest.check_player_privs(pname, {train_operator=true, interlocking=true}) then
minetest.chat_send_player(pname, "Insufficient privileges to use this!")
@@ -31,10 +32,12 @@ function atil.show_route_edit_form(pname, sigd, routeid)
-- construct textlist for route information
local tab = {}
- local function itab(t)
+ local tabref = {}
+ local function itab(rseg, t, rty, rpara)
tab[#tab+1] = minetest.formspec_escape(string.gsub(t, ",", " "))
+ tabref[#tab] = { [rty] = true, param = rpara, seg = rseg, idx = #tab }
end
- itab("("..(tcbs.signal_name or "+")..") Route #"..routeid)
+ itab(1, "("..(tcbs.signal_name or "+")..") Route #"..routeid, "signal", sigd)
-- this code is partially copy-pasted from routesetting.lua
-- we start at the tc designated by signal
@@ -44,12 +47,12 @@ function atil.show_route_edit_form(pname, sigd, routeid)
while c_sigd and i<=#route do
c_tcbs = ildb.get_tcbs(c_sigd)
if not c_tcbs then
- itab("-!- No TCBS at "..sigd_to_string(c_sigd)..". Please reconfigure route!")
+ itab(i, "-!- No TCBS at "..sigd_to_string(c_sigd)..". Please reconfigure route!", "err", nil)
break
end
c_ts_id = c_tcbs.ts_id
if not c_ts_id then
- itab("-!- No track section adjacent to "..sigd_to_string(c_sigd)..". Please reconfigure route!")
+ itab(i, "-!- No track section adjacent to "..sigd_to_string(c_sigd)..". Please reconfigure route!", "err", nil)
break
end
c_ts = ildb.get_ts(c_ts_id)
@@ -57,16 +60,18 @@ function atil.show_route_edit_form(pname, sigd, routeid)
c_rseg = route[i]
c_lckp = {}
- itab(""..i.." "..sigd_to_string(c_sigd))
- itab("= "..(c_ts and c_ts.name or "-").." =")
+ local signame = "-"
+ if c_tcbs and c_tcbs.signal then signame = c_tcbs.signal_name or "o" end
+ itab(i, ""..i.." "..sigd_to_string(c_sigd).." ("..signame..")", "signal", c_sigd)
+ itab(i, "= "..(c_ts and c_ts.name or c_ts_id).." ="..(c_rseg.call_on and " [CO]" or ""), "section", c_ts_id)
if c_rseg.locks then
for pts, state in pairs(c_rseg.locks) do
local pos = minetest.string_to_pos(pts)
- itab("L "..pts.." -> "..state)
+ itab(i, "L "..pts.." -> "..state, "lock", pos)
if not advtrains.is_passive(pos) then
- itab("-!- No passive component at "..pts..". Please reconfigure route!")
+ itab(i, "-!- No passive component at "..pts..". Please reconfigure route!", "err", nil)
break
end
end
@@ -78,31 +83,61 @@ function atil.show_route_edit_form(pname, sigd, routeid)
if c_sigd then
local e_tcbs = ildb.get_tcbs(c_sigd)
local signame = "-"
- if e_tcbs and e_tcbs.signal then signame = e_tcbs.signal_name or "+" end
- itab("E "..sigd_to_string(c_sigd).." ("..signame..")")
+ if e_tcbs and e_tcbs.signal then signame = e_tcbs.signal_name or "o" end
+ itab(i, "E "..sigd_to_string(c_sigd).." ("..signame..")", "end", c_sigd)
else
- itab("E (none)")
+ itab(i, "E (none)", "end", nil)
end
- form = form.."textlist[0.5,2;3.5,3.9;rtelog;"..table.concat(tab, ",").."]"
+ if not sel_rpartidx then sel_rpartidx = 1 end
+ form = form.."textlist[0.5,2;3.5,3.9;routelog;"..table.concat(tab, ",")..";"..(sel_rpartidx or 1)..";false]"
+
+ -- to the right of rtelog, controls are displayed for the thing in focus
+ -- What is in focus is determined by the parameter sel_rpartidx
+
+ local sel_rpart = tabref[sel_rpartidx]
+ atdebug("sel rpart",sel_rpart)
- -- to the right of rtelog a signal aspect selection for the start signal
- form = form..F.label(4.5, 2, "Signal Aspect:")
- -- main aspect list
- local signalpos = tcbs.signal
- local ndef = signalpos and advtrains.ndb.get_ndef(signalpos)
- if ndef and ndef.advtrains and ndef.advtrains.main_aspects then
- local entries = { "<Default Aspect>" }
- local sel = 1
- for i, mae in ipairs(ndef.advtrains.main_aspects) do
- entries[i+1] = mae.description
- if mae.name == route.main_aspect then
- sel = i+1
+ if sel_rpart and sel_rpart.signal then
+ -- get TCBS here and rseg selected
+ local s_tcbs = ildb.get_tcbs(sel_rpart.param)
+ local rseg = route[sel_rpart.seg]
+ -- main aspect list
+ local signalpos = s_tcbs and s_tcbs.signal
+ if signalpos and rseg then
+ form = form..F.label(4.5, 2, "Signal Aspect:")
+ local ndef = signalpos and advtrains.ndb.get_ndef(signalpos)
+ if ndef and ndef.advtrains and ndef.advtrains.main_aspects then
+ local entries = { "<Default Aspect>" }
+ local sel = 1
+ for i, mae in ipairs(ndef.advtrains.main_aspects) do
+ entries[i+1] = mae.description
+ if mae.name == rseg.main_aspect then
+ sel = i+1
+ end
+ end
+ form = form..F.dropdown(4.5, 3.0, 4, "sa_main_aspect", entries, sel, true)
+ end
+ -- checkbox for assign distant signal
+ local assign_dst = rseg.assign_dst
+ if assign_dst == nil then
+ assign_dst = (sel_rpart.seg~=1) -- special behavior when assign_dst is nil (and not false):
+ -- defaults to false for the very first signal and true for all others (= minimal user configuration overhead)
+ -- Note: on save, the value will be fixed at either false or true
end
+ form = form..string.format("checkbox[4.5,4.0;sa_distant;Announce distant signal;%s]", assign_dst)
+ else
+ form = form..F.label(4.5, 2, "No Signal at this TCB")
end
- form = form..F.dropdown(4.5, 3.0, 4, "sa_main_aspect", entries, sel, true)
- -- checkbox for assign distant signal
- form = form..string.format("checkbox[4.5,4.0;sa_distant;Announce distant signal;%s]", route.assign_dst)
+ elseif sel_rpart and sel_rpart.section then
+ local rseg = route[sel_rpart.seg]
+ if rseg then
+ form = form..F.label(4.5, 2, "Section Options:")
+ -- checkbox for call-on
+ form = form..string.format("checkbox[4.5,4.0;se_callon;Call-on (section may be occupied);%s]", rseg.call_on)
+ end
+ else
+ form = form..F.label(4.5, 2, "<< Select a route part to edit options")
end
form = form.."button[0.5,6;1,1;prev;<<<]"
@@ -123,13 +158,18 @@ function atil.show_route_edit_form(pname, sigd, routeid)
form = form.."textarea[0.8,8.3;5,3;ars;ARS Rule List;"..atil.ars_to_text(route.ars).."]"
form = form.."button[5.5,8.23;3,1;savears;Save ARS List]"
- minetest.show_formspec(pname, "at_il_routeedit_"..minetest.pos_to_string(sigd.p).."_"..sigd.s.."_"..routeid, form)
-
+ local formname = "at_il_routeedit_"..minetest.pos_to_string(sigd.p).."_"..sigd.s.."_"..routeid
+ minetest.show_formspec(pname, formname, form)
+ -- record selected entry from routelog for receive fields callback
+ sel_rpartcache[pname] = sel_rpart
end
minetest.register_on_player_receive_fields(function(player, formname, fields)
local pname = player:get_player_name()
+ -- retreive sel_rpart from the cache in any case and clear it out
+ local sel_rpart = sel_rpartcache[pname]
+ sel_rpartcache[pname] = nil
if not minetest.check_player_privs(pname, {train_operator=true, interlocking=true}) then
return
end
@@ -163,19 +203,34 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
route.name = fields.name
end
- if fields.sa_main_aspect then
+ if fields.sa_main_aspect and sel_rpart and sel_rpart.signal then
local idx = tonumber(fields.sa_main_aspect)
- route.main_aspect = nil
- if idx > 1 then
- local signalpos = tcbs.signal
- local ndef = signalpos and advtrains.ndb.get_ndef(signalpos)
- if ndef and ndef.advtrains and ndef.advtrains.main_aspects then
- route.main_aspect = ndef.advtrains.main_aspects[idx - 1].name
+ -- get TCBS here and rseg selected
+ local s_tcbs = ildb.get_tcbs(sel_rpart.param)
+ local rseg = route[sel_rpart.seg]
+ -- main aspect list
+ local signalpos = s_tcbs and s_tcbs.signal
+ if rseg then
+ rseg.main_aspect = nil
+ if idx > 1 then
+ local ndef = signalpos and advtrains.ndb.get_ndef(signalpos)
+ if ndef and ndef.advtrains and ndef.advtrains.main_aspects then
+ rseg.main_aspect = ndef.advtrains.main_aspects[idx - 1].name
+ end
end
end
end
- if fields.sa_distant then
- route.assign_dst = minetest.is_yes(fields.sa_distant)
+ if fields.sa_distant and sel_rpart and sel_rpart.signal then
+ local rseg = route[sel_rpart.seg]
+ if rseg then
+ rseg.assign_dst = minetest.is_yes(fields.sa_distant)
+ end
+ end
+ if fields.se_callon and sel_rpart and sel_rpart.section then
+ local rseg = route[sel_rpart.seg]
+ if rseg then
+ rseg.call_on = minetest.is_yes(fields.se_callon)
+ end
end
if fields.noautogen then
@@ -214,6 +269,19 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
if fields.back then
advtrains.interlocking.show_signalling_form(sigd, pname)
+ return
+ end
+
+ -- if an entry was selected in the textlist (and its not the current one) update the form
+ if fields.routelog then
+ local prev_idx = sel_rpart and sel_rpart.idx or 1
+ local tev = minetest.explode_textlist_event(fields.routelog)
+ local new_idx = tev and tev.index
+ atdebug("routelog sel",prev_idx,new_idx)
+ if new_idx and new_idx ~= prev_idx then
+ atil.show_route_edit_form(pname, sigd, routeid, new_idx)
+ return
+ end
end
end
diff --git a/advtrains_interlocking/routesetting.lua b/advtrains_interlocking/routesetting.lua
index 669a604..95ca63c 100644
--- a/advtrains_interlocking/routesetting.lua
+++ b/advtrains_interlocking/routesetting.lua
@@ -45,7 +45,7 @@ function ilrs.set_route(signal, route, try)
local rtename = route.name
local signalname = (ildb.get_tcbs(signal).signal_name or "") .. sigd_to_string(signal)
local c_tcbs, c_ts_id, c_ts, c_rseg, c_lckp
- -- signals = { { pos = ., tcbs_ref = <tcbs>, role = "main_distant", masp_override = nil, dst_type = "next_main" or "none" }
+ -- signals = { { pos = ., tcbs_ref = <tcbs>, role = "main_distant", main_aspect = nil, dst_type = "next_main" or "none" }
local signals = {}
local nodst
while c_sigd and i<=#route do
@@ -71,8 +71,12 @@ function ilrs.set_route(signal, route, try)
return false, "Section '"..(c_ts.name or c_ts_id).."' already has route set from "..sigd_to_string(c_ts.route.origin)..":\n"..c_ts.route.rsn, c_ts_id, nil
end
if c_ts.trains and #c_ts.trains>0 then
- if not try then atwarn("Encountered ts occupied during a real run of routesetting routine, at ts=",c_ts_id,"while setting route",rtename,"of",signal) end
- return false, "Section '"..(c_ts.name or c_ts_id).."' is occupied!", c_ts_id, nil
+ if c_rseg.call_on then
+ --atdebug("Routesetting: Call-on situation in", c_ts_id)
+ else
+ if not try then atwarn("Encountered ts occupied during a real run of routesetting routine, at ts=",c_ts_id,"while setting route",rtename,"of",signal) end
+ return false, "Section '"..(c_ts.name or c_ts_id).."' is occupied!", c_ts_id, nil
+ end
end
-- collect locks from rs cache and from route def
@@ -142,12 +146,17 @@ function ilrs.set_route(signal, route, try)
c_tcbs.route_origin = signal
-- determine route role
local ndef = advtrains.ndb.get_ndef(c_tcbs.signal)
+ local assign_dst = c_rseg.assign_dst
+ if assign_dst == nil then
+ assign_dst = (i~=1) -- special behavior when assign_dst is nil (and not false):
+ -- defaults to false for the very first signal and true for all others (= minimal user configuration overhead)
+ end
local sig_table = {
pos = c_tcbs.signal,
tcbs_ref = c_tcbs,
role = ndef and ndef.advtrains and ndef.advtrains.route_role,
- masp_override = c_rseg.masp_override, --TODO implement masp_override on UI side
- assign_dst = (i~=1) or route.assign_dst -- Behavior: for first signal assign depending on route.assign_dst, all others always assign
+ main_aspect = c_rseg.main_aspect,
+ assign_dst = assign_dst
}
signals[#signals+1] = sig_table
end
@@ -171,7 +180,7 @@ function ilrs.set_route(signal, route, try)
-- note the signals are iterated backwards. Switch depending on the role
local sig = signals[i]
-- apply mainaspect
- sig.tcbs_ref.route_aspect = sig.masp_override or "_default" -- or route.main_aspect : TODO this does not work if a distant signal is on the path! Implement per-sig aspects!
+ sig.tcbs_ref.route_aspect = sig.main_aspect or "_default" -- or route.main_aspect : TODO this does not work if a distant signal is on the path! Implement per-sig aspects!
if sig.role == "distant" or sig.role == "distant_repeater" or sig.role == "main_distant" then
if last_mainsig then
-- assign the remote as the last mainsig if desired
@@ -192,8 +201,6 @@ function ilrs.set_route(signal, route, try)
-- update the signal aspect on map
advtrains.interlocking.signal.update_route_aspect(sig.tcbs_ref, i ~= 1)
end
- -- Only for the first signal on the route, set route aspect. TODO: remove when masp_overrides are implemented
- signal.route_aspect = route.main_aspect or "_default"
return true
end
diff --git a/advtrains_interlocking/tcb_ts_ui.lua b/advtrains_interlocking/tcb_ts_ui.lua
index bc52339..dfb2714 100755
--- a/advtrains_interlocking/tcb_ts_ui.lua
+++ b/advtrains_interlocking/tcb_ts_ui.lua
@@ -1008,12 +1008,12 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
name = "BS",
[1] = {
next = e_sigd, -- of the next (note: next) TCB on the route
- locks = {} -- route locks of this route segment
+ locks = {}, -- route locks of this route segment
+ assign_dst = fields.setupblockshort and true, -- assign dst, if short block was selected
},
terminal = e_sigd,
use_rscache = true,
-- main_aspect = <use default>
- assign_dst = fields.setupblockshort and true, -- assign dst, if short block was selected
default_autoworking = true,
}
local rid = #tcbs.routes + 1 -- typically 1