From 66a14ecc7471e147a98c07b4466233e997021166 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Fri, 17 Feb 2023 19:16:45 -0800 Subject: [PATCH] get UI semi-finalized, prep for item choosing --- plugins/buildingplan/buildingplan.cpp | 27 ++++++-- plugins/buildingplan/buildingplan.h | 2 + plugins/buildingplan/buildingplan_cycle.cpp | 8 +-- plugins/lua/buildingplan.lua | 75 +++++++++++++-------- 4 files changed, 77 insertions(+), 35 deletions(-) diff --git a/plugins/buildingplan/buildingplan.cpp b/plugins/buildingplan/buildingplan.cpp index 687f46705..2dbceba1f 100644 --- a/plugins/buildingplan/buildingplan.cpp +++ b/plugins/buildingplan/buildingplan.cpp @@ -319,12 +319,15 @@ static bool registerPlannedBuilding(color_ostream &out, PlannedBuilding & pb) { DEBUG(status,out).print("unexpected number of jobs: want 1, got %zu\n", bld->jobs.size()); return false; } + auto job_items = bld->jobs[0]->job_items; - int num_job_items = job_items.size(); - if (num_job_items < 1) { - DEBUG(status,out).print("unexpected number of job items: want >0, got %d\n", num_job_items); - return false; + if (isJobReady(out, job_items)) { + // all items are already attached + finalizeBuilding(out, bld); + return true; } + + int num_job_items = job_items.size(); int32_t id = bld->id; for (int job_item_idx = 0; job_item_idx < num_job_items; ++job_item_idx) { auto job_item = job_items[job_item_idx]; @@ -520,6 +523,19 @@ static int countAvailableItems(color_ostream &out, df::building_type type, int16 return count; } +static bool hasFilter(color_ostream &out, df::building_type type, int16_t subtype, int32_t custom, int index) { + DEBUG(status,out).print("entering hasFilter\n"); + return false; +} + +static void setFilter(color_ostream &out, df::building_type type, int16_t subtype, int32_t custom, int index) { + DEBUG(status,out).print("entering setFilter\n"); +} + +static void clearFilter(color_ostream &out, df::building_type type, int16_t subtype, int32_t custom, int index) { + DEBUG(status,out).print("entering clearFilter\n"); +} + static bool validate_pb(color_ostream &out, df::building *bld, int index) { if (!isPlannedBuilding(out, bld) || bld->jobs.size() != 1) return false; @@ -616,6 +632,9 @@ DFHACK_PLUGIN_LUA_FUNCTIONS { DFHACK_LUA_FUNCTION(doCycle), DFHACK_LUA_FUNCTION(scheduleCycle), DFHACK_LUA_FUNCTION(countAvailableItems), + DFHACK_LUA_FUNCTION(hasFilter), + DFHACK_LUA_FUNCTION(setFilter), + DFHACK_LUA_FUNCTION(clearFilter), DFHACK_LUA_FUNCTION(getDescString), DFHACK_LUA_FUNCTION(getQueuePosition), DFHACK_LUA_FUNCTION(makeTopPriority), diff --git a/plugins/buildingplan/buildingplan.h b/plugins/buildingplan/buildingplan.h index 7fe2478aa..01c72e370 100644 --- a/plugins/buildingplan/buildingplan.h +++ b/plugins/buildingplan/buildingplan.h @@ -31,3 +31,5 @@ void set_config_bool(DFHack::PersistentDataItem &c, int index, bool value); std::vector getVectorIds(DFHack::color_ostream &out, df::job_item *job_item); bool itemPassesScreen(df::item * item); bool matchesFilters(df::item * item, df::job_item * job_item); +bool isJobReady(DFHack::color_ostream &out, const std::vector &jitems); +void finalizeBuilding(DFHack::color_ostream &out, df::building *bld); diff --git a/plugins/buildingplan/buildingplan_cycle.cpp b/plugins/buildingplan/buildingplan_cycle.cpp index 6d5e4a405..069787f39 100644 --- a/plugins/buildingplan/buildingplan_cycle.cpp +++ b/plugins/buildingplan/buildingplan_cycle.cpp @@ -72,9 +72,9 @@ bool matchesFilters(df::item * item, df::job_item * job_item) { item->getType()); } -static bool isJobReady(color_ostream &out, df::job * job) { +bool isJobReady(color_ostream &out, const std::vector &jitems) { int needed_items = 0; - for (auto job_item : job->job_items) { needed_items += job_item->quantity; } + for (auto job_item : jitems) { needed_items += job_item->quantity; } if (needed_items) { DEBUG(cycle,out).print("building needs %d more item(s)\n", needed_items); return false; @@ -91,7 +91,7 @@ static bool job_item_idx_lt(df::job_item_ref *a, df::job_item_ref *b) { // now all at 0, so there is no risk of having extra items attached. we don't // remove them to keep the "finalize with buildingplan active" path as similar // as possible to the "finalize with buildingplan disabled" path. -static void finalizeBuilding(color_ostream &out, df::building * bld) { +void finalizeBuilding(color_ostream &out, df::building *bld) { DEBUG(cycle,out).print("finalizing building %d\n", bld->id); auto job = bld->jobs[0]; @@ -194,7 +194,7 @@ static void doVector(color_ostream &out, df::job_item_vector_id vector_id, // be completed with the correct number of items. --job->job_items[filter_idx]->quantity; task_queue.pop_front(); - if (isJobReady(out, job)) { + if (isJobReady(out, job->job_items)) { finalizeBuilding(out, bld); planned_buildings.at(id).remove(out); } diff --git a/plugins/lua/buildingplan.lua b/plugins/lua/buildingplan.lua index b9be7e800..b6c13d5a7 100644 --- a/plugins/lua/buildingplan.lua +++ b/plugins/lua/buildingplan.lua @@ -198,13 +198,6 @@ function ItemLine:init() auto_width=true, visible=self.is_selected_fn, }, - widgets.Label{ - frame={t=0, r=0}, - text='*', - auto_width=true, - visible=self.is_selected_fn, - on_click=self.on_filter, - }, widgets.Label{ frame={t=0, l=25}, text={ @@ -228,7 +221,7 @@ function ItemLine:init() text={ {width=21, text=self:callback('get_item_line_text')}, {gap=3, text='filter', pen=COLOR_GREEN}, - {gap=2, text='x', pen=COLOR_GREEN}, + {gap=2, text='x', pen=self:callback('get_x_pen')}, {gap=3, text=function() return self.note end, pen=function() return self.note_pen end}, }, @@ -248,6 +241,10 @@ function ItemLine:onInput(keys) return ItemLine.super.onInput(self, keys) end +function ItemLine:get_x_pen() + return hasFilter(uibs.building_type, uibs.building_subtype, uibs.custom_type, self.idx) and COLOR_GREEN or COLOR_GREY +end + function get_desc(filter) local desc = 'Unknown' if filter.has_tool_use and filter.has_tool_use > -1 then @@ -414,32 +411,52 @@ function PlannerOverlay:init() subviews={ widgets.HotkeyLabel{ frame={b=1, l=0}, - key='SELECT', - label='Choose item', - on_activate=function() self:choose(self.selected) end, - enabled=function() - return (self.subviews['item'..self.selected].available or 0) > 0 - end, + key='STRING_A042', + enabled=function() return #get_cur_filters() > 1 end, + on_activate=function() self.selected = ((self.selected - 2) % #get_cur_filters()) + 1 end, + }, + widgets.HotkeyLabel{ + frame={b=1, l=1}, + key='STRING_A047', + label='Prev/next item', + enabled=function() return #get_cur_filters() > 1 end, + on_activate=function() self.selected = (self.selected % #get_cur_filters()) + 1 end, }, widgets.HotkeyLabel{ frame={b=1, l=21}, key='CUSTOM_F', - label='Filter', + label='Set filter', on_activate=function() self:filter(self.selected) end, }, widgets.HotkeyLabel{ - frame={b=1, l=33}, + frame={b=1, l=37}, key='CUSTOM_X', label='Clear filter', on_activate=function() self:clear_filter(self.selected) end, }, + widgets.CycleHotkeyLabel{ + view_id='choose', + frame={b=0, l=0}, + key='CUSTOM_I', + label='Choose exact items:', + options={{label='Yes', value=true}, + {label='No', value=false}}, + initial_option=false, + enabled=function() + for idx = 1,4 do + if (self.subviews['item'..idx].available or 0) > 0 then + return true + end + end + end, + }, widgets.CycleHotkeyLabel{ view_id='safety', - frame={b=0, l=2}, + frame={b=0, l=29}, key='CUSTOM_G', - label='Safety: ', + label='Building safety:', options={ - {label='None', value='none'}, + {label='Any', value='none'}, {label='Magma', value='magma'}, {label='Fire', value='fire'}, }, @@ -484,10 +501,6 @@ function PlannerOverlay:reset() reset_counts_flag = false end -function PlannerOverlay:choose(idx) - print('choose', idx) -end - function PlannerOverlay:filter(idx) print('filter', idx) end @@ -504,6 +517,8 @@ function PlannerOverlay:onInput(keys) return true end self.selected = 1 + self.subviews.choose:setOption(false) + self.subviews.safety:setOption('none') self:reset() return false end @@ -527,10 +542,6 @@ function PlannerOverlay:onInput(keys) if #get_cur_filters() == 0 then return false -- we don't add value; let the game place it end - self.subviews.item1:reduce_quantity() - self.subviews.item2:reduce_quantity() - self.subviews.item3:reduce_quantity() - self.subviews.item4:reduce_quantity() self:place_building() uibs.selection_pos:clear() return true @@ -607,6 +618,11 @@ function PlannerOverlay:place_building() max_y = min_y + height - 1 max_z = math.max(uibs.selection_pos.z, uibs.pos.z) end + if self.subviews.choose:getOptionValue() then + -- TODO + -- open dialog, showing all items (restricted to current filters) + -- select items (doesn't have to be all required items) + end local blds = {} local subtype = uibs.building_subtype for z=min_z,max_z do for y=min_y,max_y do for x=min_x,max_x do @@ -660,7 +676,12 @@ function PlannerOverlay:place_building() end table.insert(blds, bld) end end end + self.subviews.item1:reduce_quantity() + self.subviews.item2:reduce_quantity() + self.subviews.item3:reduce_quantity() + self.subviews.item4:reduce_quantity() for _,bld in ipairs(blds) do + -- TODO: attach chosen items and reduce job_item quantity addPlannedBuilding(bld) end scheduleCycle()