Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP Add reorderstops overlay #889

Draft
wants to merge 5 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion changelog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@ Template for new versions:

## New Tools
- `sync-windmills`: synchronize or randomize movement of active windmills
- `trackstop`: new overlay to allow changing track stop dump direction and friction and roller direction and speed after construction
- `trackstop`: provides 3 new overlays:
- trackstop: allow changing track stop dump direction and friction
- rollers: allow changing roller direction and speed
- reorderstops: reorder stops in hauling routes
Comment on lines +31 to +34
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this kind of formatting doesn't translate well to the final rendered changelog. each line should be independent. If you start each of them with `trackstop`: then they will get combined into a list similar to your intention here


## New Features
- `gui/design`: show selected dimensions next to the mouse cursor when designating with vanilla tools, for example when painting a burrow or designating digging
Expand Down
3 changes: 2 additions & 1 deletion docs/trackstop.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ trackstop
:summary: Add dynamic configuration options for track stops.
:tags: fort buildings interface

This script provides 2 overlays that are managed by the `overlay` framework. The script does nothing when executed.
This script provides 3 overlays that are managed by the `overlay` framework. The script does nothing when executed.
The trackstop overlay allows the player to change the friction and dump direction of a selected track stop after it has been constructed.
The rollers overlay allows the player to change the roller direction and speed of a selected roller after it has been constructed.
The reorderstops overlay allows the player to change the order of stops in a hauling route.
191 changes: 189 additions & 2 deletions trackstop.lua
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,23 @@ local DIRECTION_MAP = {

local DIRECTION_MAP_REVERSE = utils.invert(DIRECTION_MAP)

local function swapElements(tbl, index1, index2)
tbl[index1], tbl[index2] = tbl[index2], tbl[index1]
return tbl
end

local function reset_guide_paths(conditions)
for _i, condition in ipairs(conditions) do
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for unused variables, the Lua convention is just to use an underscore with no other characters.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yeah that's it. Was wondering why it still showed greyed out in the editor but hadn't looked into it yet. ty!

local gpath = condition.guide_path

if gpath then
gpath.x:resize(0)
gpath.y:resize(0)
gpath.z:resize(0)
end
end
end

TrackStopOverlay = defclass(TrackStopOverlay, overlay.OverlayWidget)
TrackStopOverlay.ATTRS{
default_pos={x=-73, y=29},
Expand Down Expand Up @@ -120,7 +137,11 @@ function TrackStopOverlay:setDumpDirection(direction)
end

function TrackStopOverlay:render(dc)
local building = dfhack.gui.getSelectedBuilding()
local building = dfhack.gui.getSelectedBuilding(true)
if not building then
return
end

local friction = building.friction
local friction_cycle = self.subviews.friction

Expand Down Expand Up @@ -201,7 +222,10 @@ function RollerOverlay:setSpeed(speed)
end

function RollerOverlay:render(dc)
local building = dfhack.gui.getSelectedBuilding()
local building = dfhack.gui.getSelectedBuilding(true)
if not building then
return
end

self.subviews.direction:setOption(DIRECTION_MAP_REVERSE[building.direction])
self.subviews.speed:setOption(SPEED_MAP_REVERSE[building.speed])
Expand Down Expand Up @@ -236,7 +260,170 @@ function RollerOverlay:init()
}
end

selected_stop = selected_stop or nil
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why does this need to be a global instead of an instance variable in ReorderStopsWindow?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can fix!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess with the way modals work I don't need the other global variable either. Nice. Removed that too.


ReorderStopsWindow = defclass(ReorderStopsWindow, widgets.Window)
ReorderStopsWindow.ATTRS {
frame={t=4,l=60,w=45, h=28},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since this window contains a list with a variable number of elements, it would be useful to set resizable=true

frame_title='Reorder Stops',
view_id='main',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since this is never referenced, you don't need to give it an explicit view_id

}

local SELECT_STOP_HINT = 'Select a stop to move'
local SELECT_ANOTHER_STOP_HINT = 'Select another stop on the same route'

function ReorderStopsWindow:init()
self:addviews{
widgets.Label{
frame={t=0,l=0},
view_id='hint',
text=SELECT_STOP_HINT,
},
widgets.List{
view_id='routes',
frame={t=1,l=1},
choices={},
on_select=function(index, item)
if not item then return end
if item.type == 'stop' then
local item_pos = df.global.plotinfo.hauling.routes[item.route_index].stops[item.stop_index].pos
df.global.game.main_interface.recenter_indicator_m.x = item_pos.x
df.global.game.main_interface.recenter_indicator_m.y = item_pos.y
df.global.game.main_interface.recenter_indicator_m.z = item_pos.z
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pass another , true to revealInDwarfmodeMap to get this for free

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Siick

dfhack.gui.revealInDwarfmodeMap(item_pos, true)
end
end,
on_submit=function(index, item)
if selected_stop then
local hauling = df.global.plotinfo.hauling
local routes = hauling.routes
local view_stops = hauling.view_stops
local route = routes[item.route_index]

-- rearrange stops
if item.type == 'stop' then
local stop_index = item.stop_index

-- don't allow moving stops to a different route
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah this might be fine, I'll revisit it for sure.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now possible

if selected_stop.route_index ~= item.route_index then
return
end

swapElements(route.stops, stop_index, selected_stop.stop_index)
swapElements(view_stops, selected_stop.list_position, index - 1)

-- loop over each stop in the route, make the ids sequental and reset guide paths
-- TODO: what else does this break?
for i, stop in ipairs(route.stops) do
stop.id = i + 1
reset_guide_paths(stop.conditions)
end

selected_stop = nil
end
else
if item.stop_index then
selected_stop = item
end
end

self:updateList()
end,
},
}

self:updateList()
end

function ReorderStopsWindow:updateList()
local routes = df.global.plotinfo.hauling.routes
local choices = {}
local list_position = 0

if selected_stop then
self.subviews.hint:setText(SELECT_ANOTHER_STOP_HINT)
else
self.subviews.hint:setText(SELECT_STOP_HINT)
end

for i, route in ipairs(routes) do
local stops = route.stops
local route_name = route.name

if route_name == '' then
route_name = 'Route ' .. route.id
end

table.insert(choices, {text=route_name, type='route', route_index=i, list_position=list_position})
list_position = list_position + 1

for j, stop in ipairs(stops) do
local stop_name = stop.name

if stop_name == '' then
stop_name = 'Stop ' .. stop.id
end

if selected_stop and selected_stop.list_position == list_position then
stop_name = '=> ' .. stop_name
end

stop_name = ' ' .. stop_name

table.insert(choices, {text=stop_name, type='stop', stop_index=j, route_index=i, list_position=list_position})
list_position = list_position + 1
end
end

self.subviews.routes:setChoices(choices)
end

ReorderStopsModal = defclass(ReorderStopsModal, gui.ZScreenModal)

ReorderStopsModal.ATTRS = {
focus_path = 'ReorderStops',
}

function ReorderStopsModal:init()
self:addviews{ReorderStopsWindow{}}
end

function ReorderStopsModal:onDismiss()
reorder_stops_modal = nil
selected_stop = nil
df.global.game.main_interface.recenter_indicator_m.x = -30000
df.global.game.main_interface.recenter_indicator_m.y = -30000
df.global.game.main_interface.recenter_indicator_m.z = -30000
end

ReorderStopsOverlay = defclass(ReorderStopsOverlay, overlay.OverlayWidget)
ReorderStopsOverlay.ATTRS{
default_pos={x=6, y=6},
default_enabled=true,
viewscreens='dwarfmode/Hauling',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this specific enough, or should it disappear on hauling subscreens? We might need to extend Gui.cpp if this is the case

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like it's okay on all of them except them item selection one. Will fix.

frame={w=30, h=1},
frame_background=gui.CLEAR_PEN,
}

function ReorderStopsOverlay:init()
self:addviews{
widgets.BannerPanel{
subviews = {
widgets.HotkeyLabel{
frame={t=0, l=1, r=1},
label='DFHack reorder stops',
key='CUSTOM_CTRL_E',
on_activate=function()
reorder_stops_modal = reorder_stops_modal and reorder_stops_modal:raise() or ReorderStopsModal{}:show()
end,
},
},
},
}
end

OVERLAY_WIDGETS = {
trackstop=TrackStopOverlay,
rollers=RollerOverlay,
reorderstops=ReorderStopsOverlay,
}