add search and filter for slab engraving list

develop
Myk Taylor 2023-10-15 13:26:25 -07:00
parent a2066828f0
commit a04623e4fb
No known key found for this signature in database
5 changed files with 128 additions and 1 deletions

@ -62,6 +62,7 @@ Template for new versions:
- `sort`: new search widgets for location selection screen (when you're choosing what kind of guildhall or temple to dedicate)
- `sort`: new search widgets for burrow assignment screen and other unit assignment dialogs
- `sort`: new search widgets for artifacts on the world/raid screen
- `sort`: new search widgets for slab engraving menu; can filter for only units that need a slab to prevent rising as a ghost
## Fixes
- `zone`: races without specific child or baby names will now get generic child/baby names instead of an empty string

@ -135,6 +135,14 @@ search for the "spheres" associated with the deity or religion, such as
You can also choose whether to filter out temple or guildhall types that you
have already established.
Slab engraving overlay
----------------------
When choosing a unit to engrave a slab for, you can search for units by name,
either in their native language or in English (though only their native name
will be displayed). This overlay also adds a filter for showing only units that
would need a slab in order to prevent them rising as a ghost.
World overlay
-------------

@ -1291,6 +1291,7 @@ OVERLAY_WIDGETS = {
location_selector=require('plugins.sort.locationselector').LocationSelectorOverlay,
unit_selector=require('plugins.sort.unitselector').UnitSelectorOverlay,
worker_assignment=require('plugins.sort.unitselector').WorkerAssignmentOverlay,
slab=require('plugins.sort.slab').SlabOverlay,
world=require('plugins.sort.world').WorldOverlay,
}

@ -0,0 +1,117 @@
local _ENV = mkmodule('plugins.sort.slab')
local gui = require('gui')
local sortoverlay = require('plugins.sort.sortoverlay')
local widgets = require('gui.widgets')
local building = df.global.game.main_interface.building
local view_sheets = df.global.game.main_interface.view_sheets
-- ----------------------
-- SlabOverlay
--
SlabOverlay = defclass(SlabOverlay, sortoverlay.SortOverlay)
SlabOverlay.ATTRS{
default_pos={x=-40, y=12},
viewscreens='dwarfmode/ViewSheets/BUILDING/Workshop',
frame={w=57, h=3},
}
function SlabOverlay:init()
local panel = widgets.Panel{
frame_background=gui.CLEAR_PEN,
visible=self:callback('get_key'),
}
panel:addviews{
widgets.BannerPanel{
frame={l=0, t=0, r=0, h=1},
subviews={
widgets.EditField{
view_id='search',
frame={l=1, t=0, r=1},
label_text="Search: ",
key='CUSTOM_ALT_S',
on_change=function(text) self:do_search(text) end,
},
},
},
widgets.BannerPanel{
frame={l=0, t=2, r=0, h=1},
subviews={
widgets.ToggleHotkeyLabel{
view_id='only_needs_slab',
frame={l=1, t=0, r=1},
label="Show only citizens who need a slab:",
key='CUSTOM_SHIFT_E',
initial_option=false,
on_change=function() self:do_search(self.subviews.search.text, true) end,
},
},
},
}
self:addviews{panel}
self:register_handler('SLAB', building.filtered_button,
curry(sortoverlay.single_vector_search,
{
get_search_key_fn=self:callback('get_search_key'),
matches_filters_fn=self:callback('matches_filters'),
}))
end
function SlabOverlay:onInput(keys)
if SlabOverlay.super.onInput(self, keys) then return true end
if keys._MOUSE_L and self:get_key() and self:getMousePos() then
return true
end
end
function SlabOverlay:get_key()
-- DF fails to set building.category back to NONE if there are no units that
-- can be memorialized, so we have to manually check for a populated button vector
if #building.button > 0 and
building.category == df.interface_category_building.SELECT_MEMORIAL_UNIT
then
return 'SLAB'
else
if safe_index(self.state, 'SLAB', 'saved_original') then
-- elements get freed as soon as the screen changes
self.state.SLAB.saved_original = nil
end
end
end
function SlabOverlay:reset()
SlabOverlay.super.reset(self)
self.subviews.only_needs_slab:setOption(false, false)
end
local function get_unit(if_button)
local hf = df.historical_figure.find(if_button.spec_id)
return hf and df.unit.find(hf.unit_id) or nil
end
function SlabOverlay:get_search_key(if_button)
local unit = get_unit(if_button)
if not unit then return if_button.filter_str end
return ('%s %s'):format(
dfhack.units.getReadableName(unit), -- last name is in english
dfhack.TranslateName(unit.name, false, true)) -- get untranslated last name
end
local function needs_slab(if_button)
local unit = get_unit(if_button)
if not unit then return false end
if not dfhack.units.isOwnGroup(unit) then return false end
local info = dfhack.toSearchNormalized(if_button.info)
if not info:find('no slabs engraved', 1, true) then return false end
return info:find('not memorialized', 1, true) or info:find('ghost', 1, true)
end
function SlabOverlay:matches_filters(if_button)
local only_needs_slab = self.subviews.only_needs_slab:getOptionValue()
return not only_needs_slab or needs_slab(if_button)
end
return _ENV

@ -114,7 +114,7 @@ local function filter_vec(fns, flags_vec, vec, text, erase_fn)
local search_tokens = text:split()
for idx = #vec-1,0,-1 do
local flag = flags_vec and flags_vec[idx] or nil
local search_key = fns.get_search_key_fn(vec[idx], flag)
local search_key = fns.get_search_key_fn and fns.get_search_key_fn(vec[idx], flag) or nil
if (search_key and not utils.search_text(search_key, search_tokens)) or
(fns.matches_filters_fn and not fns.matches_filters_fn(vec[idx], flag))
then