1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
|
-- route_ui.lua
-- User interface for showing and editing routes
local atil = advtrains.interlocking
local ildb = atil.db
local F = advtrains.formspec
-- TODO duplicate
local lntrans = { "A", "B" }
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, 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!")
return
end
local tcbs = atil.db.get_tcbs(sigd)
if not tcbs then return end
local route = tcbs.routes[routeid]
if not route then return end
local form = "size[9,11]label[0.5,0.2;Route overview]"
form = form.."field[0.8,1.2;6.5,1;name;Route name;"..minetest.formspec_escape(route.name).."]"
form = form.."button[7.0,0.9;1.5,1;setname;Set]"
-- construct textlist for route information
local tab = {}
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(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
local c_sigd = sigd
local i = 1
local c_tcbs, c_ts_id, c_ts, c_rseg
while c_sigd and i<=#route do
c_tcbs = ildb.get_tcbs(c_sigd)
if not c_tcbs then
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(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)
c_rseg = route[i]
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(i, "L "..pts.." -> "..state, "lock", pos)
if not advtrains.is_passive(pos) then
itab(i, "-!- No passive component at "..pts..". Please reconfigure route!", "err", nil)
break
end
end
end
-- sanity check, is section at next the same as the current?
local nvar = c_rseg.next
if nvar then
local re_tcbs = ildb.get_tcbs({p = nvar.p, s = (nvar.s==1) and 2 or 1})
if not re_tcbs or not re_tcbs.ts_id or re_tcbs.ts_id~=c_ts_id then
itab(i, "-!- At "..sigd_to_string(c_sigd)..".Section Start and End do not match!", "err", nil)
break
end
end
-- advance
c_sigd = nvar
i = i + 1
end
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 "o" end
itab(i, "E "..sigd_to_string(c_sigd).." ("..signame..")", "end", c_sigd)
else
itab(i, "E (none)", "end", nil)
end
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)
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
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
elseif sel_rpart and sel_rpart.err then
form = form.."textarea[4.5,2.5;4,4;errorta;Error:;"..tab[sel_rpartidx].."]"
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;<<<]"
form = form.."button[1.5,6;1,1;back;"..routeid.."/"..#tcbs.routes.."]"
form = form.."button[2.5,6;1,1;next;>>>]"
--if route.smartroute_generated or route.default_autoworking then
-- form = form.."button[3.5,6;2,1;noautogen;Clr Autogen]"
--end
form = form.."button[5.5,6;3,1;delete;Delete Route]"
form = form.."button[0.5,7;3,1;back;Back to signal]"
form = form.."button[3.5,7;2,1;clone;Clone Route]"
form = form.."button[5.5,7;3,1;newfrom;New From Route]"
--atdebug(route.ars)
form = form.."style[ars;font=mono]"
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]"
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]
if not minetest.check_player_privs(pname, {train_operator=true, interlocking=true}) then
return
end
local pts, connids, routeids = string.match(formname, "^at_il_routeedit_([^_]+)_(%d)_(%d+)$")
local pos, connid, routeid
if pts then
pos = minetest.string_to_pos(pts)
connid = tonumber(connids)
routeid = tonumber(routeids)
if not connid or connid<1 or connid>2 then return end
if not routeid then return end
end
if pos and connid and routeid and not fields.quit then
local sigd = {p=pos, s=connid}
local tcbs = ildb.get_tcbs(sigd)
if not tcbs then return end
local route = tcbs.routes[routeid]
if not route then return end
if fields.prev then
atil.show_route_edit_form(pname, sigd, routeid - 1)
return
end
if fields.next then
atil.show_route_edit_form(pname, sigd, routeid + 1)
return
end
if fields.setname and fields.name then
route.name = fields.name
end
if fields.sa_main_aspect and sel_rpart and sel_rpart.signal then
local idx = tonumber(fields.sa_main_aspect)
-- 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 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)
-- reshow form to update CO marker
atil.show_route_edit_form(pname, sigd, routeid, sel_rpart.idx)
return
end
end
--if fields.noautogen then
-- route.smartroute_generated = nil
-- route.default_autoworking = nil
-- -- reshow form for the button to disappear
-- atil.show_route_edit_form(pname, sigd, routeid, sel_rpart and sel_rpart.idx)
-- return
--end
if fields.delete then
-- if something set the route in the meantime, make sure this doesn't break.
atil.route.update_route(sigd, tcbs, nil, true)
table.remove(tcbs.routes, routeid)
advtrains.interlocking.show_signalling_form(sigd, pname)
-- cleanup
sel_rpartcache[pname] = nil
return
end
if fields.clone then
-- if something set the route in the meantime, make sure this doesn't break.
atil.route.update_route(sigd, tcbs, nil, true)
local rcopy = table.copy(route)
rcopy.name = route.name.."_copy"
rcopy.smartroute_generated = nil
table.insert(tcbs.routes, routeid+1, rcopy)
advtrains.interlocking.show_signalling_form(sigd, pname)
-- cleanup
sel_rpartcache[pname] = nil
return
end
if fields.newfrom then
advtrains.interlocking.init_route_prog(pname, sigd, route)
minetest.close_formspec(pname, formname)
tcbs.ars_ignore_next = nil
-- cleanup
sel_rpartcache[pname] = nil
return
end
if fields.ars and fields.savears then
route.ars = atil.text_to_ars(fields.ars)
--atdebug(route.ars)
end
if fields.back then
advtrains.interlocking.show_signalling_form(sigd, pname)
-- cleanup
sel_rpartcache[pname] = nil
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
if new_idx and new_idx ~= prev_idx then
atil.show_route_edit_form(pname, sigd, routeid, new_idx)
return
end
end
if fields.quit then
-- cleanup
sel_rpartcache[pname] = nil
end
end
end)
|