@@ -52,6 +52,23 @@ local DIRECTION_MAP = {
5252
5353local DIRECTION_MAP_REVERSE = utils .invert (DIRECTION_MAP )
5454
55+ local function swapElements (tbl , index1 , index2 )
56+ tbl [index1 ], tbl [index2 ] = tbl [index2 ], tbl [index1 ]
57+ return tbl
58+ end
59+
60+ local function reset_guide_paths (conditions )
61+ for _i , condition in ipairs (conditions ) do
62+ local gpath = condition .guide_path
63+
64+ if gpath then
65+ gpath .x :resize (0 )
66+ gpath .y :resize (0 )
67+ gpath .z :resize (0 )
68+ end
69+ end
70+ end
71+
5572TrackStopOverlay = defclass (TrackStopOverlay , overlay .OverlayWidget )
5673TrackStopOverlay .ATTRS {
5774 default_pos = {x =- 73 , y = 29 },
@@ -120,7 +137,11 @@ function TrackStopOverlay:setDumpDirection(direction)
120137end
121138
122139function TrackStopOverlay :render (dc )
123- local building = dfhack .gui .getSelectedBuilding ()
140+ local building = dfhack .gui .getSelectedBuilding (true )
141+ if not building then
142+ return
143+ end
144+
124145 local friction = building .friction
125146 local friction_cycle = self .subviews .friction
126147
@@ -201,7 +222,10 @@ function RollerOverlay:setSpeed(speed)
201222end
202223
203224function RollerOverlay :render (dc )
204- local building = dfhack .gui .getSelectedBuilding ()
225+ local building = dfhack .gui .getSelectedBuilding (true )
226+ if not building then
227+ return
228+ end
205229
206230 self .subviews .direction :setOption (DIRECTION_MAP_REVERSE [building .direction ])
207231 self .subviews .speed :setOption (SPEED_MAP_REVERSE [building .speed ])
@@ -236,7 +260,170 @@ function RollerOverlay:init()
236260 }
237261end
238262
263+ selected_stop = selected_stop or nil
264+
265+ ReorderStopsWindow = defclass (ReorderStopsWindow , widgets .Window )
266+ ReorderStopsWindow .ATTRS {
267+ frame = {t = 4 ,l = 60 ,w = 45 , h = 28 },
268+ frame_title = ' Reorder Stops' ,
269+ view_id = ' main' ,
270+ }
271+
272+ local SELECT_STOP_HINT = ' Select a stop to move'
273+ local SELECT_ANOTHER_STOP_HINT = ' Select another stop on the same route'
274+
275+ function ReorderStopsWindow :init ()
276+ self :addviews {
277+ widgets .Label {
278+ frame = {t = 0 ,l = 0 },
279+ view_id = ' hint' ,
280+ text = SELECT_STOP_HINT ,
281+ },
282+ widgets .List {
283+ view_id = ' routes' ,
284+ frame = {t = 1 ,l = 1 },
285+ choices = {},
286+ on_select = function (index , item )
287+ if not item then return end
288+ if item .type == ' stop' then
289+ local item_pos = df .global .plotinfo .hauling .routes [item .route_index ].stops [item .stop_index ].pos
290+ df .global .game .main_interface .recenter_indicator_m .x = item_pos .x
291+ df .global .game .main_interface .recenter_indicator_m .y = item_pos .y
292+ df .global .game .main_interface .recenter_indicator_m .z = item_pos .z
293+ dfhack .gui .revealInDwarfmodeMap (item_pos , true )
294+ end
295+ end ,
296+ on_submit = function (index , item )
297+ if selected_stop then
298+ local hauling = df .global .plotinfo .hauling
299+ local routes = hauling .routes
300+ local view_stops = hauling .view_stops
301+ local route = routes [item .route_index ]
302+
303+ -- rearrange stops
304+ if item .type == ' stop' then
305+ local stop_index = item .stop_index
306+
307+ -- don't allow moving stops to a different route
308+ if selected_stop .route_index ~= item .route_index then
309+ return
310+ end
311+
312+ swapElements (route .stops , stop_index , selected_stop .stop_index )
313+ swapElements (view_stops , selected_stop .list_position , index - 1 )
314+
315+ -- loop over each stop in the route, make the ids sequental and reset guide paths
316+ -- TODO: what else does this break?
317+ for i , stop in ipairs (route .stops ) do
318+ stop .id = i + 1
319+ reset_guide_paths (stop .conditions )
320+ end
321+
322+ selected_stop = nil
323+ end
324+ else
325+ if item .stop_index then
326+ selected_stop = item
327+ end
328+ end
329+
330+ self :updateList ()
331+ end ,
332+ },
333+ }
334+
335+ self :updateList ()
336+ end
337+
338+ function ReorderStopsWindow :updateList ()
339+ local routes = df .global .plotinfo .hauling .routes
340+ local choices = {}
341+ local list_position = 0
342+
343+ if selected_stop then
344+ self .subviews .hint :setText (SELECT_ANOTHER_STOP_HINT )
345+ else
346+ self .subviews .hint :setText (SELECT_STOP_HINT )
347+ end
348+
349+ for i , route in ipairs (routes ) do
350+ local stops = route .stops
351+ local route_name = route .name
352+
353+ if route_name == ' ' then
354+ route_name = ' Route ' .. route .id
355+ end
356+
357+ table.insert (choices , {text = route_name , type = ' route' , route_index = i , list_position = list_position })
358+ list_position = list_position + 1
359+
360+ for j , stop in ipairs (stops ) do
361+ local stop_name = stop .name
362+
363+ if stop_name == ' ' then
364+ stop_name = ' Stop ' .. stop .id
365+ end
366+
367+ if selected_stop and selected_stop .list_position == list_position then
368+ stop_name = ' => ' .. stop_name
369+ end
370+
371+ stop_name = ' ' .. stop_name
372+
373+ table.insert (choices , {text = stop_name , type = ' stop' , stop_index = j , route_index = i , list_position = list_position })
374+ list_position = list_position + 1
375+ end
376+ end
377+
378+ self .subviews .routes :setChoices (choices )
379+ end
380+
381+ ReorderStopsModal = defclass (ReorderStopsModal , gui .ZScreenModal )
382+
383+ ReorderStopsModal .ATTRS = {
384+ focus_path = ' ReorderStops' ,
385+ }
386+
387+ function ReorderStopsModal :init ()
388+ self :addviews {ReorderStopsWindow {}}
389+ end
390+
391+ function ReorderStopsModal :onDismiss ()
392+ reorder_stops_modal = nil
393+ selected_stop = nil
394+ df .global .game .main_interface .recenter_indicator_m .x = - 30000
395+ df .global .game .main_interface .recenter_indicator_m .y = - 30000
396+ df .global .game .main_interface .recenter_indicator_m .z = - 30000
397+ end
398+
399+ ReorderStopsOverlay = defclass (ReorderStopsOverlay , overlay .OverlayWidget )
400+ ReorderStopsOverlay .ATTRS {
401+ default_pos = {x = 6 , y = 6 },
402+ default_enabled = true ,
403+ viewscreens = ' dwarfmode/Hauling' ,
404+ frame = {w = 30 , h = 1 },
405+ frame_background = gui .CLEAR_PEN ,
406+ }
407+
408+ function ReorderStopsOverlay :init ()
409+ self :addviews {
410+ widgets .BannerPanel {
411+ subviews = {
412+ widgets .HotkeyLabel {
413+ frame = {t = 0 , l = 1 , r = 1 },
414+ label = ' DFHack reorder stops' ,
415+ key = ' CUSTOM_CTRL_E' ,
416+ on_activate = function ()
417+ reorder_stops_modal = reorder_stops_modal and reorder_stops_modal :raise () or ReorderStopsModal {}:show ()
418+ end ,
419+ },
420+ },
421+ },
422+ }
423+ end
424+
239425OVERLAY_WIDGETS = {
240426 trackstop = TrackStopOverlay ,
241427 rollers = RollerOverlay ,
428+ reorderstops = ReorderStopsOverlay ,
242429}
0 commit comments