From 15e3488a04f1d299d99632fb76c29f2609cf210b Mon Sep 17 00:00:00 2001 From: masterdraco Date: Fri, 25 Sep 2026 21:52:43 +0200 Subject: [PATCH] =?UTF-8?q?feat(marker):=20fanen=20Marker=20=E2=80=94=20ta?= =?UTF-8?q?bel,=20detalje=20(plan/k=C3=B8rsel/riv/tving=20lager/marksiloer?= =?UTF-8?q?),=20markfl=C3=A5de,=20Start=20nu/Stop?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FS25_ADSmartPickup/adFieldJobs.lua | 4 + FS25_ADSmartPickup/adFieldModel.lua | 8 + FS25_ADSmartPickup/adSmartPickup.lua | 1 + .../gui/SmartPickupFieldTab.lua | 254 ++++++++++++++++++ FS25_ADSmartPickup/gui/SmartPickupFlowTab.lua | 9 +- FS25_ADSmartPickup/gui/SmartPickupFrame.lua | 50 +++- FS25_ADSmartPickup/gui/SmartPickupFrame.xml | 9 + FS25_ADSmartPickup/l10n/l10n_da.xml | 48 ++++ FS25_ADSmartPickup/l10n/l10n_en.xml | 48 ++++ tests/test_adFieldModel.lua | 4 + 10 files changed, 422 insertions(+), 13 deletions(-) create mode 100644 FS25_ADSmartPickup/gui/SmartPickupFieldTab.lua diff --git a/FS25_ADSmartPickup/adFieldJobs.lua b/FS25_ADSmartPickup/adFieldJobs.lua index 334f946..156849f 100644 --- a/FS25_ADSmartPickup/adFieldJobs.lua +++ b/FS25_ADSmartPickup/adFieldJobs.lua @@ -91,6 +91,10 @@ local function note(fieldId, changes) setField(ADFieldModel.with(ADFieldJobs.getField(fieldId), changes)) end +function ADFieldJobs.forceReady(id) + setField(ADFieldModel.forceReady(ADFieldJobs.getField(id))) +end + function ADFieldJobs.toggleFleet(vehicleId) ADFieldJobs.state.fleet = ADFieldFleet.toggle(ADFieldJobs.state.fleet, vehicleId) ADFieldJobs.save() diff --git a/FS25_ADSmartPickup/adFieldModel.lua b/FS25_ADSmartPickup/adFieldModel.lua index 1afdeb7..5d12a57 100644 --- a/FS25_ADSmartPickup/adFieldModel.lua +++ b/FS25_ADSmartPickup/adFieldModel.lua @@ -77,6 +77,14 @@ function ADFieldModel.shouldStart(field) return field.stage == "ready" and (field.plan.mode == "auto" or field.startRequested == true) end +-- Start nu fra menuen på en mark der ikke er nået 90 %: den behandles som klar. +function ADFieldModel.forceReady(field) + if field.stage == "idle" or field.stage == "done" then + return ADFieldModel.with(field, {stage = "ready"}) + end + return field +end + function ADFieldModel.start(field) local copy = copyField(field) copy.stage = ADFieldModel.workStages(field.plan)[1] diff --git a/FS25_ADSmartPickup/adSmartPickup.lua b/FS25_ADSmartPickup/adSmartPickup.lua index c9e1108..f312591 100644 --- a/FS25_ADSmartPickup/adSmartPickup.lua +++ b/FS25_ADSmartPickup/adSmartPickup.lua @@ -17,6 +17,7 @@ if ADSmartPickup.dir ~= nil and source ~= nil then source(ADSmartPickup.dir .. "gui/SmartPickupOutboundTab.lua") source(ADSmartPickup.dir .. "gui/SmartPickupStorageTab.lua") source(ADSmartPickup.dir .. "gui/SmartPickupFlowTab.lua") + source(ADSmartPickup.dir .. "gui/SmartPickupFieldTab.lua") end -- Markøren er dér hvor trækkerens næse stopper; læssetriggeren ligger et diff --git a/FS25_ADSmartPickup/gui/SmartPickupFieldTab.lua b/FS25_ADSmartPickup/gui/SmartPickupFieldTab.lua new file mode 100644 index 0000000..2c6b5d0 --- /dev/null +++ b/FS25_ADSmartPickup/gui/SmartPickupFieldTab.lua @@ -0,0 +1,254 @@ +-- Smart Pickup — fanen Marker +-- Tabel over gårdens slåafgrøde-marker (Mark · Afgrøde · Plan · Auto/Man. · Status · Maskiner); klik på +-- en række viser markens detaljer under tabellen (plan, kørsel, riv, tving lager, marksiloer). Nederst +-- markflåden: foreslåede sæt med flueben. Al logik ligger i ADFieldJobs/ADFieldModel/ADFieldView. +-- Funktionerne lægges på SmartPickupFrame (indlæses efter SmartPickupFrame.lua). + +SmartPickupFrame.FIELD_ROW_KINDS = { + showAllFields = true, fieldProduct = true, fieldMode = true, fieldRake = true, fieldStore = true, fleetVehicle = true, +} +SmartPickupFrame.ROLE_KEYS = {mower = "spu_field_role_mower", tedder = "spu_field_role_tedder", rake = "spu_field_role_rake", collector = "spu_field_role_collector"} + +-- ---- tekster ---- + +function SmartPickupFrame:fieldReasonText(reason) + if type(reason) ~= "table" then return nil end + if reason.text ~= nil then return reason.text end + local role = reason.role ~= nil and self.i18n:getText(SmartPickupFrame.ROLE_KEYS[reason.role] or "spu_field_role_mower") or "" + local template = self.i18n:getText(reason.key) + local args = reason.args or {} + local ok, text = pcall(string.format, template, role, args[1] or 0, args[2] or 0) + return ok and text or template +end + +function SmartPickupFrame:fieldStatusText(field, info) + local text = self.i18n:getText(ADFieldView.statusKey(field, info)) + if info.markerId == nil then + return string.format(text, info.id) + end + if (field.stage == "idle" or field.stage == "ready") and info.mowable then + text = string.format("%s %d %%", text, math.floor((info.readyRatio or 0) * 100 + 0.5)) + end + local reason = self:fieldReasonText(field.reason) + if reason ~= nil then text = text .. ": " .. reason end + return text +end + +function SmartPickupFrame:fieldPlanText(field) + local text = self.i18n:getText(field.plan.product == "hay" and "spu_field_plan_hay" or "spu_field_plan_silage") + if field.plan.product == "hay" and field.plan.rake then + text = text .. " + " .. self.i18n:getText("spu_field_plan_rake") + end + return text +end + +function SmartPickupFrame:fieldCells(row) + local info, field = row.info, row.field + local names = {} + for _, assignment in ipairs(ADFieldJobs.assignmentsFor(info.id)) do + table.insert(names, ADRuns.vehicleLabel(assignment.vehicle)) + end + local name = string.format("%s%sF%d", info.id == self.selectedFieldId and "> " or "", info.markerId == nil and "! " or "", info.id) + return { + name, info.cropTitle or "-", info.mowable and self:fieldPlanText(field) or "-", + self.i18n:getText(field.plan.mode == "auto" and "spu_field_mode_auto" or "spu_field_mode_manual"), + info.mowable and self:fieldStatusText(field, info) or self.i18n:getText("spu_field_notMowable"), + ADFlowView.joinCounted(names, ", ", "-"), + } +end + +-- ---- opbygning ---- + +function SmartPickupFrame:fillFieldRows(adEnv) + self.fieldRows = {} + local i18n = self.i18n + local infos = ADFields.list() + if #infos == 0 then + self:addTextRow(i18n:getText("spu_field_scanning")) + else + self:addTextRow(i18n:getText("spu_field_hint")) + local hidden = ADFieldView.hiddenCount(infos, self.showAllFields == true) + if hidden > 0 or self.showAllFields then + self:addToggleRow("showAllFields", string.format(i18n:getText("spu_field_showAll"), hidden), {i18n:getText("ui_no"), i18n:getText("ui_yes")}, self.showAllFields == true) + end + self:addCellRow(self.fieldPrefab, {i18n:getText("spu_col_field"), i18n:getText("spu_col_crop"), i18n:getText("spu_col_plan"), i18n:getText("spu_col_mode"), i18n:getText("spu_col_status"), i18n:getText("spu_col_tractors")}) + for _, row in ipairs(ADFieldView.rows(infos, ADFieldJobs.state.fields, self.showAllFields == true)) do + local cells = self:addCellRow(self.fieldPrefab, self:fieldCells(row)) + local fieldId = row.info.id + if cells[1] ~= nil and cells[1].parent ~= nil then + self:makeRowClickable(cells[1].parent, function(frame) + frame.selectedFieldId = fieldId + frame:requestRebuild() + end) + end + table.insert(self.fieldRows, {id = fieldId, cells = cells}) + end + end + local selected = self.selectedFieldId ~= nil and ADFields.getInfo(self.selectedFieldId) or nil + if selected ~= nil then + self:fillFieldDetail(adEnv, selected) + end + self:fillFleetRows(adEnv) +end + +function SmartPickupFrame:fillFieldDetail(adEnv, info) + local i18n = self.i18n + local field = ADFieldJobs.getField(info.id) + self:addTextRow(string.format(i18n:getText("spu_field_section"), info.id, tostring(info.cropTitle or "-"))) + if not info.mowable then + self:addTextRow(" " .. i18n:getText("spu_field_notMowable")) + return + end + local isHay = field.plan.product == "hay" + self:addToggleRow("fieldProduct", i18n:getText("spu_field_plan"), {i18n:getText("spu_field_plan_silage"), i18n:getText("spu_field_plan_hay")}, isHay) + self:addToggleRow("fieldMode", i18n:getText("spu_field_mode"), {i18n:getText("spu_field_mode_manual"), i18n:getText("spu_field_mode_auto")}, field.plan.mode == "auto") + if isHay then + self:addToggleRow("fieldRake", i18n:getText("spu_field_rake"), {i18n:getText("ui_no"), i18n:getText("ui_yes")}, field.plan.rake == true) + end + if info.markerId ~= nil then + self:addTextRow(string.format(i18n:getText("spu_field_marker"), tostring(info.markerName), info.markerDistance or 0)) + else + self:addTextRow(" " .. string.format(i18n:getText("spu_field_noMarker"), info.id)) + end + if field.mowWidth ~= nil then + self:addTextRow(string.format(i18n:getText("spu_field_mowWidth"), field.mowWidth)) + end + self:fillFieldStoreRows(adEnv, info, field) +end + +-- Tving lager: siloer der tager markens vare (skår ved ensilage, tørskår ved hø); valgte først. +function SmartPickupFrame:fillFieldStoreRows(adEnv, info, field) + local i18n = self.i18n + self:addTextRow(i18n:getText("spu_field_section_store")) + local fillType = field.plan.product == "hay" and info.hay or info.windrow + local chosen = {} + for _, id in ipairs(field.plan.storeBuildingIds) do chosen[id] = true end + local farmId = g_currentMission:getFarmId() + local fieldSilos = {} + for _, building in ipairs(ADFields.fieldSilos(adEnv, farmId, info)) do fieldSilos[building.id] = building end + local count = 0 + for _, building in ipairs(ADBuildings.list(adEnv, farmId)) do + if building.kind == "silo" and (chosen[building.id] or ADRunsController.canStoreAt(adEnv, building, {{fillType = fillType, isPallet = false}})) then + count = count + 1 + local row = self:addRow(self.ingredientPrefab, {kind = "fieldStore", buildingId = building.id}) + local suffix = fieldSilos[building.id] ~= nil and (" (" .. i18n:getText("spu_field_fieldSilo") .. ")") or "" + row:getDescendantByName("title"):setText(" " .. tostring(building.name) .. suffix) + row:getDescendantByName("option"):setState(chosen[building.id] and SmartPickupFrame.STATE_ON or SmartPickupFrame.STATE_OFF, false) + end + end + if count == 0 then + self:addTextRow(" " .. i18n:getText("spu_field_noStore")) + elseif #field.plan.storeBuildingIds == 0 then + self:addTextRow(" " .. i18n:getText("spu_field_storeAuto")) + end + -- marksiloer skal tømmes hjem af et udkørselsflow + for id, building in pairs(fieldSilos) do + local emptied = false + for _, run in ipairs(ADRunsController.store.runs) do + for _, sourceId in ipairs(run.kind == "outbound" and run.sourceBuildingIds or {}) do + if sourceId == id then emptied = true end + end + end + if not emptied then + self:addTextRow(" " .. string.format(i18n:getText("spu_field_fieldSiloNotEmptied"), tostring(building.name))) + end + end +end + +function SmartPickupFrame:fillFleetRows(adEnv) + local i18n = self.i18n + self:addTextRow(i18n:getText("spu_field_section_fleet")) + local rigs = ADFieldJobs.getRigs(adEnv) + table.sort(rigs, function(a, b) + if a.role ~= b.role then return a.role < b.role end + return ADFlowView.naturalLess(a.label, b.label) + end) + for _, rig in ipairs(rigs) do + local row = self:addRow(self.vehiclePrefab, {kind = "fleetVehicle", vehicleId = rig.id}) + local title = string.format(" %s — %s, %.1f m", tostring(rig.label), i18n:getText(SmartPickupFrame.ROLE_KEYS[rig.role]), rig.width or 0) + if (rig.width or 0) > ADFieldModel.CP_MAX_WIDTH then + title = title .. " — " .. i18n:getText("spu_field_tooWideShort") + end + local assignment = ADFieldJobs.state.assignments[rig.id] + if assignment ~= nil then + title = title .. string.format(" — F%d", assignment.fieldId) + end + row:getDescendantByName("title"):setText(title) + row:getDescendantByName("option"):setState(rig.enabled and SmartPickupFrame.STATE_ON or SmartPickupFrame.STATE_OFF, false) + end + if #rigs == 0 then + self:addTextRow(" " .. i18n:getText("spu_field_noRigs")) + end +end + +-- ---- live ---- + +function SmartPickupFrame:refreshFieldRows(adEnv) + local rowsById = {} + for _, row in ipairs(ADFieldView.rows(ADFields.list(), ADFieldJobs.state.fields, true)) do rowsById[row.info.id] = row end + local working, total = 0, 0 + for _, entry in ipairs(self.fieldRows or {}) do + local row = rowsById[entry.id] + if row ~= nil then + SmartPickupFrame.setCells(entry.cells, self:fieldCells(row)) + if row.info.mowable then total = total + 1 end + if ADFieldModel.isWorking(row.field) then working = working + 1 end + end + end + self:setStatusText(self.statusOverride or string.format(self.i18n:getText("spu_field_status"), working, total)) + local selected = self.selectedFieldId ~= nil and ADFieldJobs.getField(self.selectedFieldId) or nil + local info = self.selectedFieldId ~= nil and ADFields.getInfo(self.selectedFieldId) or nil + local isWorking = selected ~= nil and ADFieldModel.isWorking(selected) + self.fieldStartButtonInfo.text = self.i18n:getText(isWorking and "spu_field_button_stop" or "spu_field_button_start") + self.fieldStartButtonInfo.disabled = selected == nil or info == nil or not info.mowable + or (not isWorking and (info.markerId == nil or (info.readyRatio or 0) < ADFieldModel.CUT_RATIO)) +end + +-- ---- klik ---- + +function SmartPickupFrame:onClickFieldRow(state, data) + self:safe(function(frame) + local isOn = state == SmartPickupFrame.STATE_ON + local id = frame.selectedFieldId + if data.kind == "showAllFields" then + frame.showAllFields = isOn + elseif data.kind == "fleetVehicle" then + ADFieldJobs.toggleFleet(data.vehicleId) + elseif id == nil then + return + elseif data.kind == "fieldProduct" then + ADFieldJobs.setPlan(id, {product = isOn and "hay" or "silage"}) + elseif data.kind == "fieldMode" then + ADFieldJobs.setPlan(id, {mode = isOn and "auto" or "manual"}) + elseif data.kind == "fieldRake" then + ADFieldJobs.setPlan(id, {rake = isOn}) + elseif data.kind == "fieldStore" then + local ids = {} + for _, buildingId in ipairs(ADFieldJobs.getField(id).plan.storeBuildingIds) do + if buildingId ~= data.buildingId then table.insert(ids, buildingId) end + end + if isOn then table.insert(ids, data.buildingId) end + ADFieldJobs.setPlan(id, {storeBuildingIds = ids}) + end + frame:requestRebuild() + end) +end + +function SmartPickupFrame:onClickFieldStartStop() + self:safe(function(frame) + local id = frame.selectedFieldId + if id == nil then return end + local field = ADFieldJobs.getField(id) + if ADFieldModel.isWorking(field) then + ADFieldJobs.stopField(frame.getAdEnv(), id) + else + if field.stage ~= "ready" then + ADFieldJobs.forceReady(id) + end + ADFieldJobs.requestStart(id) + frame.statusOverride = string.format(frame.i18n:getText("spu_field_startRequested"), id) + frame.statusOverrideTicks = SmartPickupFrame.STATUS_OVERRIDE_TICKS + end + frame:requestRebuild() + end) +end diff --git a/FS25_ADSmartPickup/gui/SmartPickupFlowTab.lua b/FS25_ADSmartPickup/gui/SmartPickupFlowTab.lua index dd493b2..4d3ad52 100644 --- a/FS25_ADSmartPickup/gui/SmartPickupFlowTab.lua +++ b/FS25_ADSmartPickup/gui/SmartPickupFlowTab.lua @@ -65,7 +65,7 @@ function SmartPickupFrame:flowCells(adEnv, run) end -- Hele rækken klikbar med musen (Bitmap-rækker har ingen onClick). Klikket gemmes kun som --- pendingJumpRunId; hoppet sker i update(), fordi genopbygningen sletter netop denne række. +-- pendingClick; handlingen køres i update(), fordi genopbygningen sletter netop denne række. local MOUSE_LEFT = Input ~= nil and Input.MOUSE_BUTTON_LEFT or 1 local function isInside(element, posX, posY) @@ -74,7 +74,7 @@ local function isInside(element, posX, posY) return posX >= position[1] and posX <= position[1] + size[1] and posY >= position[2] and posY <= position[2] + size[2] end -function SmartPickupFrame:makeRowClickable(row, runId) +function SmartPickupFrame:makeRowClickable(row, action) local frame = self local baseMouseEvent = row.mouseEvent row.mouseEvent = function(element, posX, posY, isDown, isUp, button, eventUsed) @@ -82,7 +82,7 @@ function SmartPickupFrame:makeRowClickable(row, runId) -- også inden for listens synlige udsnit: rækker scrollet ud af syne må ikke fange klik if not used and not eventUsed and isUp and button == MOUSE_LEFT and (element.getIsVisible == nil or element:getIsVisible()) and isInside(element, posX, posY) and isInside(frame.boxLayout, posX, posY) then - frame.pendingJumpRunId = runId + frame.pendingClick = action return true end return used @@ -100,7 +100,8 @@ function SmartPickupFrame:fillOverviewRows(adEnv) for _, run in ipairs(group.runs) do local cells = self:addCellRow(self.flowPrefab, self:flowCells(adEnv, run)) if cells[1] ~= nil and cells[1].parent ~= nil then - self:makeRowClickable(cells[1].parent, run.id) + local runId = run.id + self:makeRowClickable(cells[1].parent, function(frame) frame:openFlow(runId) end) end table.insert(self.overviewRows, {runId = run.id, cells = cells}) end diff --git a/FS25_ADSmartPickup/gui/SmartPickupFrame.lua b/FS25_ADSmartPickup/gui/SmartPickupFrame.lua index d829a0b..dfafc55 100644 --- a/FS25_ADSmartPickup/gui/SmartPickupFrame.lua +++ b/FS25_ADSmartPickup/gui/SmartPickupFrame.lua @@ -11,10 +11,10 @@ SmartPickupFrame.STATUS_OVERRIDE_TICKS = 6 SmartPickupFrame.MAX_STATUS_REASONS = 3 SmartPickupFrame.LOG_PREFIX = "ADSmartPickup: " SmartPickupFrame.STATE_OFF, SmartPickupFrame.STATE_ON = 1, 2 -SmartPickupFrame.TAB_OVERVIEW, SmartPickupFrame.TAB_FLOWS = 1, 2 +SmartPickupFrame.TAB_OVERVIEW, SmartPickupFrame.TAB_FLOWS, SmartPickupFrame.TAB_FIELDS = 1, 2, 3 -- Lagerfaner: én pr. bygningstype (indeks -> kind i ADSources.getFarmInventory) -SmartPickupFrame.TAB_NAMES = {"spu_tab_overview", "spu_tab_flows", "spu_tab_factories", "spu_tab_silos", "spu_tab_barns", "spu_tab_sheds"} -SmartPickupFrame.TAB_KINDS = {[3] = "factory", [4] = "silo", [5] = "husbandry", [6] = "objectStorage"} +SmartPickupFrame.TAB_NAMES = {"spu_tab_overview", "spu_tab_flows", "spu_tab_fields", "spu_tab_factories", "spu_tab_silos", "spu_tab_barns", "spu_tab_sheds"} +SmartPickupFrame.TAB_KINDS = {[4] = "factory", [5] = "silo", [6] = "husbandry", [7] = "objectStorage"} function SmartPickupFrame.getTabKind(tab) return SmartPickupFrame.TAB_KINDS[tab] @@ -51,6 +51,9 @@ function SmartPickupFrame.new(i18n, getAdEnv) self.stopAllButtonInfo = {inputAction = InputAction.MENU_EXTRA_2, text = i18n:getText("spu_button_stopAll"), callback = function() self:onClickStopAll() end} self.flowButtons = {self.backButtonInfo, self.startButtonInfo, self.newButtonInfo, self.renameButtonInfo, self.deleteButtonInfo} self.overviewButtons = {self.backButtonInfo, self.startAllButtonInfo, self.stopAllButtonInfo, self.newButtonInfo} + -- Marker: Start nu / Stop for den valgte mark + self.fieldStartButtonInfo = {inputAction = InputAction.MENU_ACTIVATE, text = i18n:getText("spu_field_button_start"), callback = function() self:onClickFieldStartStop() end} + self.fieldButtons = {self.backButtonInfo, self.fieldStartButtonInfo} -- Egen reference til listen: fallback'en i refreshButtons skal kunne sende den igen. self.menuButtonInfo = self.overviewButtons self:setMenuButtonInfo(self.menuButtonInfo) @@ -68,7 +71,7 @@ end -- Prefabs skal ud af layoutet før de klones, ellers vises de selv som rækker. function SmartPickupFrame:initialize() - for _, name in ipairs({"ingredientPrefab", "vehiclePrefab", "textPrefab", "productPrefab", "statPrefab", "gridPrefab", "flowPrefab"}) do + for _, name in ipairs({"ingredientPrefab", "vehiclePrefab", "textPrefab", "productPrefab", "statPrefab", "gridPrefab", "flowPrefab", "fieldPrefab"}) do local prefab = self[name] if prefab ~= nil then prefab:unlinkElement() @@ -201,10 +204,10 @@ end -- dets egen klik-håndtering, hopper værdien frem og tilbage og fokus ryger. function SmartPickupFrame:update(dt) SmartPickupFrame:superClass().update(self, dt) - if self.pendingJumpRunId ~= nil then - local runId = self.pendingJumpRunId - self.pendingJumpRunId = nil - self:safe(function(frame) frame:openFlow(runId) end) + if self.pendingClick ~= nil then + local action = self.pendingClick + self.pendingClick = nil + self:safe(action) elseif self.pendingRebuild then self.pendingRebuild = false self:safe(self.rebuild) @@ -380,6 +383,17 @@ function SmartPickupFrame:rebuild() self:refreshLive() return end + if self.currentTab == SmartPickupFrame.TAB_FIELDS then + if adEnv ~= nil then + self:fillFieldRows(adEnv) + end + self.statusRow = self:addTextRow("") + self:colorRows() + self.boxLayout:invalidateLayout() + self:refreshLive() + self:restoreFocusIfLost() + return + end if self.currentTab == SmartPickupFrame.TAB_OVERVIEW then if adEnv ~= nil then self:fillOverviewRows(adEnv) @@ -642,7 +656,12 @@ end -- setMenuButtonInfoDirty findes i FS22/25's TabbedMenuFrameElement; mangler den, -- sendes listen igen. Kaldes hvert sekund, så den må aldrig kaste. function SmartPickupFrame:refreshButtons() - local wanted = self.currentTab == SmartPickupFrame.TAB_OVERVIEW and self.overviewButtons or self.flowButtons + local wanted = self.flowButtons + if self.currentTab == SmartPickupFrame.TAB_OVERVIEW then + wanted = self.overviewButtons + elseif self.currentTab == SmartPickupFrame.TAB_FIELDS then + wanted = self.fieldButtons + end if self.menuButtonInfo ~= wanted then self.menuButtonInfo = wanted self:setMenuButtonInfo(wanted) @@ -666,6 +685,13 @@ function SmartPickupFrame:refreshLive() if isOverview then self:refreshOverview(adEnv) end + if self.currentTab == SmartPickupFrame.TAB_FIELDS then + self:refreshFieldRows(adEnv) + self.statusOverrideTicks = (self.statusOverrideTicks or 0) - 1 + if self.statusOverrideTicks <= 0 then self.statusOverride = nil end + self:refreshButtons() + return + end self:refreshStorageRows(adEnv) local isRunning = false if isOverview then @@ -738,6 +764,8 @@ function SmartPickupFrame:onClickIngredient(state, element) if data.kind == "showAllVehicles" then self.showAllVehicles = isOn else self.showAllBuildings = isOn end self:requestRebuild() return + elseif data ~= nil and SmartPickupFrame.FIELD_ROW_KINDS[data.kind] then + return self:onClickFieldRow(state, data) elseif data ~= nil and (data.kind == "sourceBuilding" or data.kind == "targetBuilding" or data.kind == "storeBuilding") then return self:onClickBuilding(state, element) end @@ -764,6 +792,10 @@ function SmartPickupFrame:onClickWaitPool(state) end function SmartPickupFrame:onClickVehicle(state, element) + local clicked = self.rowData[element] + if clicked ~= nil and clicked.kind == "fleetVehicle" then + return self:onClickFieldRow(state, clicked) + end self:safe(function(frame) local run, data = frame:getRun(), frame.rowData[element] if run == nil or data == nil or data.locked then return end diff --git a/FS25_ADSmartPickup/gui/SmartPickupFrame.xml b/FS25_ADSmartPickup/gui/SmartPickupFrame.xml index 0a13383..85d8da5 100644 --- a/FS25_ADSmartPickup/gui/SmartPickupFrame.xml +++ b/FS25_ADSmartPickup/gui/SmartPickupFrame.xml @@ -81,6 +81,15 @@ + + + + + + + + + diff --git a/FS25_ADSmartPickup/l10n/l10n_da.xml b/FS25_ADSmartPickup/l10n/l10n_da.xml index f341903..69882ec 100644 --- a/FS25_ADSmartPickup/l10n/l10n_da.xml +++ b/FS25_ADSmartPickup/l10n/l10n_da.xml @@ -39,6 +39,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FS25_ADSmartPickup/l10n/l10n_en.xml b/FS25_ADSmartPickup/l10n/l10n_en.xml index 6ae257e..5567613 100644 --- a/FS25_ADSmartPickup/l10n/l10n_en.xml +++ b/FS25_ADSmartPickup/l10n/l10n_en.xml @@ -39,6 +39,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/test_adFieldModel.lua b/tests/test_adFieldModel.lua index 2737a70..aa9688a 100644 --- a/tests/test_adFieldModel.lua +++ b/tests/test_adFieldModel.lua @@ -95,5 +95,9 @@ check("M9 grund", noted.reason.text, "x"); check("M9 pause", noted.retryAt, 5) check("M9 plan flettet", noted.plan.product, "hay"); check("M9 mode bevaret", noted.plan.mode, "manual") check("M9 trin bevaret", noted.stage, "mowing"); check("M9 original urørt", base.plan.product, "silage") +-- M10: Start nu på en mark der ikke er helt klar -> klar; arbejdende mark røres ikke +check("M10 venter -> klar", M.forceReady(M.newField(2)).stage, "ready") +check("M10 arbejdende uændret", M.forceReady(base).stage, "mowing") + print(failures == 0 and "\nALLE TESTS OK" or ("\n" .. failures .. " FEJL")) os.exit(failures == 0 and 0 or 1)