From 8eebfa007c60f210a365c91af029152a4a0c689d Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Thu, 25 Oct 2012 12:15:18 +0400 Subject: [PATCH] Tweak the workflow gui script to make the UI operate smoother. --- library/lua/utils.lua | 17 +++++ plugins/lua/workflow.lua | 51 ++++++++++++-- plugins/workflow.cpp | 21 +++--- scripts/gui/workflow.lua | 125 +++++++++++------------------------ scripts/gui/workshop-job.lua | 38 ++++++++--- 5 files changed, 144 insertions(+), 108 deletions(-) diff --git a/library/lua/utils.lua b/library/lua/utils.lua index 8070b85de..e7267038c 100644 --- a/library/lua/utils.lua +++ b/library/lua/utils.lua @@ -283,7 +283,11 @@ function clone_with_default(obj,default,force) return rv end +-- Parse an integer value into a bitfield table function parse_bitfield_int(value, type_ref) + if value == 0 then + return nil + end local res = {} for i,v in ipairs(type_ref) do if bit32.extract(value, i) ~= 0 then @@ -293,6 +297,19 @@ function parse_bitfield_int(value, type_ref) return res end +-- List the enabled flag names in the bitfield table +function list_bitfield_flags(bitfield, list) + list = list or {} + if bitfield then + for name,val in pairs(bitfield) do + if val then + table.insert(list, name) + end + end + end + return list +end + -- Sort a vector or lua table function sort_vector(vector,field,cmp) local fcmp = compare_field(field,cmp) diff --git a/plugins/lua/workflow.lua b/plugins/lua/workflow.lua index 598bf8841..391045a96 100644 --- a/plugins/lua/workflow.lua +++ b/plugins/lua/workflow.lua @@ -9,7 +9,7 @@ local utils = require 'utils' * isEnabled() * setEnabled(enable) * listConstraints([job]) -> {...} - * setConstraint(token, by_count, goal[, gap]) -> {...} + * setConstraint(token[, by_count, goal, gap]) -> {...} * deleteConstraint(token) -> true/false --]] @@ -40,6 +40,10 @@ local job_outputs = {} function job_outputs.CustomReaction(callback, job) local rid, r = get_reaction(job.reaction_name) + if not r then + return + end + for i,prod in ipairs(r.products) do if df.reaction_product_itemst:is_instance(prod) then local mat_type, mat_index = prod.mat_type, prod.mat_index @@ -239,11 +243,7 @@ function constraintToToken(cspec) end local mask_part if cspec.mat_mask then - local lst = {} - for n,v in pairs(cspec.mat_mask) do - if v then table.insert(lst,n) end - end - mask_part = table.concat(lst, ',') + mask_part = table.concat(utils.list_bitfield_flags(cspec.mat_mask), ',') end local mat_part if cspec.mat_type and cspec.mat_type >= 0 then @@ -272,4 +272,43 @@ function constraintToToken(cspec) return token end +function listWeakenedConstraints(outputs) + local variants = {} + local known = {} + local function register(cons) + cons.token = constraintToToken(cons) + if not known[cons.token] then + known[cons.token] = true + table.insert(variants, cons) + end + end + + local generic = {} + local anymat = {} + for i,cons in ipairs(outputs) do + local mask = cons.mat_mask + if (cons.mat_type or -1) >= 0 then + cons.mat_mask = nil + end + register(cons) + if mask then + table.insert(generic, { + item_type = cons.item_type, + item_subtype = cons.item_subtype, + is_craft = cons.is_craft, + mat_mask = mask + }) + end + table.insert(anymat, { + item_type = cons.item_type, + item_subtype = cons.item_subtype, + is_craft = cons.is_craft + }) + end + for i,cons in ipairs(generic) do register(cons) end + for i,cons in ipairs(anymat) do register(cons) end + + return variants +end + return _ENV diff --git a/plugins/workflow.cpp b/plugins/workflow.cpp index a6bb3a41a..19709b68c 100644 --- a/plugins/workflow.cpp +++ b/plugins/workflow.cpp @@ -1452,19 +1452,23 @@ static void push_constraint(lua_State *L, ItemConstraint *cv) static int listConstraints(lua_State *L) { auto job = Lua::CheckDFObject(L, 1); - ProtectedJob *pj = NULL; - if (job) - pj = get_known(job->id); - if (!enabled || (job && !pj)) - { - lua_pushnil(L); + lua_pushnil(L); + + if (!enabled || (job && !isSupportedJob(job))) return 1; - } color_ostream &out = *Lua::GetOutput(L); update_data_structures(out); + ProtectedJob *pj = NULL; + if (job) + { + pj = get_known(job->id); + if (!pj) + return 1; + } + lua_newtable(L); auto &vec = (pj ? pj->constraints : constraints); @@ -1491,7 +1495,8 @@ static int setConstraint(lua_State *L) if (!icv) luaL_error(L, "invalid constraint: %s", token); - icv->setGoalByCount(by_count); + if (!lua_isnil(L, 2)) + icv->setGoalByCount(by_count); if (!lua_isnil(L, 3)) icv->setGoalCount(count); if (!lua_isnil(L, 4)) diff --git a/scripts/gui/workflow.lua b/scripts/gui/workflow.lua index 9dfb7dd76..b0a01a37c 100644 --- a/scripts/gui/workflow.lua +++ b/scripts/gui/workflow.lua @@ -26,6 +26,23 @@ function check_enabled(cb,...) end end +function check_repeat(job, cb) + if job.flags['repeat'] then + return cb(job) + else + dlg.showYesNoPrompt( + 'Not Repeat Job', + { 'Workflow only tracks repeating jobs.', NEWLINE, NEWLINE, + 'Press ', { key = 'MENU_CONFIRM' }, ' to make this one repeat.' }, + COLOR_YELLOW, + function() + job.flags['repeat'] = true + return cb(job) + end + ) + end +end + JobConstraints = defclass(JobConstraints, guidm.MenuOverlay) JobConstraints.focus_path = 'workflow-job' @@ -41,14 +58,6 @@ local null_cons = { goal_value = 0, goal_gap = 0, goal_by_count = false } function JobConstraints:init(args) self.building = dfhack.job.getHolder(self.job) - local status = { text = 'No worker', pen = COLOR_DARKGREY } - local worker = dfhack.job.getWorker(self.job) - if self.job.flags.suspend then - status = { text = 'Suspended', pen = COLOR_RED } - elseif worker then - status = { text = dfhack.TranslateName(dfhack.units.getVisibleName(worker)), pen = COLOR_GREEN } - end - self:addviews{ widgets.Label{ frame = { l = 0, t = 0 }, @@ -160,19 +169,7 @@ function describe_material(iobj) return matline end -function list_flags(bitfield) - local list = {} - if bitfield then - for name,val in pairs(bitfield) do - if val then - table.insert(list, name) - end - end - end - return list -end - -function JobConstraints:initListChoices(clist) +function JobConstraints:initListChoices(clist, sel_token) clist = clist or workflow.listConstraints(self.job) local choices = {} @@ -199,7 +196,7 @@ function JobConstraints:initListChoices(clist) end local matstr = describe_material(cons) local matflagstr = '' - local matflags = list_flags(cons.mat_mask) + local matflags = utils.list_bitfield_flags(cons.mat_mask) if #matflags > 0 then matflags[1] = 'any '..matflags[1] if matstr == 'any material' then @@ -216,11 +213,17 @@ function JobConstraints:initListChoices(clist) goal, ' ', { text = '(now '..curval..')', pen = order_pen }, NEWLINE, ' ', itemstr, NEWLINE, ' ', matstr, NEWLINE, ' ', matflagstr }, + token = cons.token, obj = cons }) end - self.subviews.list:setChoices(choices) + local selidx = nil + if sel_token then + selidx = utils.linear_index(choices, sel_token, 'token') + end + + self.subviews.list:setChoices(choices, selidx) end function JobConstraints:isAnySelected() @@ -232,18 +235,9 @@ function JobConstraints:getCurConstraint() if v then return v.obj end end -function JobConstraints:getCurUnit() - local cons = self:getCurConstraint() - if cons and cons.goal_by_count then - return 'stacks' - else - return 'items' - end -end - function JobConstraints:saveConstraint(cons) - workflow.setConstraint(cons.token, cons.goal_by_count, cons.goal_value, cons.goal_gap) - self:initListChoices() + local out = workflow.setConstraint(cons.token, cons.goal_by_count, cons.goal_value, cons.goal_gap) + self:initListChoices(nil, out.token) end function JobConstraints:onChangeUnit() @@ -285,45 +279,6 @@ function JobConstraints:onIncRange(field, delta) self:saveConstraint(cons) end -function make_constraint_variants(outputs) - local variants = {} - local known = {} - local function register(cons) - cons.token = workflow.constraintToToken(cons) - if not known[cons.token] then - known[cons.token] = true - table.insert(variants, cons) - end - end - - local generic = {} - local anymat = {} - for i,cons in ipairs(outputs) do - local mask = cons.mat_mask - if (cons.mat_type or -1) >= 0 then - cons.mat_mask = nil - end - register(cons) - if mask then - table.insert(generic, { - item_type = cons.item_type, - item_subtype = cons.item_subtype, - is_craft = cons.is_craft, - mat_mask = mask - }) - end - table.insert(anymat, { - item_type = cons.item_type, - item_subtype = cons.item_subtype, - is_craft = cons.is_craft - }) - end - for i,cons in ipairs(generic) do register(cons) end - for i,cons in ipairs(anymat) do register(cons) end - - return variants -end - function JobConstraints:onNewConstraint() local outputs = workflow.listJobOutputs(self.job) if #outputs == 0 then @@ -331,13 +286,13 @@ function JobConstraints:onNewConstraint() return end - local variants = make_constraint_variants(outputs) + local variants = workflow.listWeakenedConstraints(outputs) local choices = {} for i,cons in ipairs(variants) do local itemstr = describe_item_type(cons) local matstr = describe_material(cons) - local matflags = list_flags(cons.mat_mask or {}) + local matflags = utils.list_bitfield_flags(cons.mat_mask) if #matflags > 0 then local fstr = table.concat(matflags, '/') if matstr == 'any material' then @@ -352,7 +307,7 @@ function JobConstraints:onNewConstraint() dlg.showListPrompt( 'Job Outputs', - 'Select one of the job outputs:', + 'Select one of the possible outputs:', COLOR_WHITE, choices, function(idx,item) @@ -390,15 +345,13 @@ end check_enabled(function() local job = dfhack.gui.getSelectedJob() - if not job.flags['repeat'] then - dlg.showMessage('Not Supported', 'Workflow only tracks repeat jobs.', COLOR_LIGHTRED) - return - end - local clist = workflow.listConstraints(job) - if not clist then - dlg.showMessage('Not Supported', 'This type of job is not supported by workflow.', COLOR_LIGHTRED) - return - end - JobConstraints{ job = job, clist = clist }:show() + check_repeat(job, function(job) + local clist = workflow.listConstraints(job) + if not clist then + dlg.showMessage('Not Supported', 'This type of job is not supported by workflow.', COLOR_LIGHTRED) + return + end + JobConstraints{ job = job, clist = clist }:show() + end) end) diff --git a/scripts/gui/workshop-job.lua b/scripts/gui/workshop-job.lua index 74e33595f..c4e203614 100644 --- a/scripts/gui/workshop-job.lua +++ b/scripts/gui/workshop-job.lua @@ -220,18 +220,40 @@ function JobDetails:setMaterial(obj, mat_type, mat_index) obj.iobj.mat_index = mat_index end +function JobDetails:findUnambiguousItem(iobj) + local count = 0 + local itype + + for i = 0,df.item_type._last_item do + if dfhack.job.isSuitableItem(iobj, i, -1) then + count = count + 1 + if count > 1 then return nil end + itype = i + end + end + + return itype +end + function JobDetails:onChangeMat() local idx, obj = self.subviews.list:getSelected() if obj.iobj.item_type == -1 and obj.iobj.mat_type == -1 then - dlg.showMessage( - 'Bug Alert', - { 'Please set a specific item type first.\n\n', - 'Otherwise the material will be matched\n', - 'incorrectly due to a limitation in DF code.' }, - COLOR_YELLOW - ) - return + -- If the job allows only one specific item type, use it + local vitype = self:findUnambiguousItem(obj.iobj) + + if vitype then + obj.iobj.item_type = vitype + else + dlg.showMessage( + 'Bug Alert', + { 'Please set a specific item type first.\n\n', + 'Otherwise the material will be matched\n', + 'incorrectly due to a limitation in DF code.' }, + COLOR_YELLOW + ) + return + end end guimat.MaterialDialog{