feat: ESC-fane 'Smart Pickup' (runs: mål, varer, Wait-pulje, ture, traktorer, Start/Stop)
This commit is contained in:
@@ -10,6 +10,11 @@
|
||||
|
||||
ADSmartPickup = {}
|
||||
|
||||
ADSmartPickup.dir = g_currentModDirectory
|
||||
if ADSmartPickup.dir ~= nil and source ~= nil then
|
||||
source(ADSmartPickup.dir .. "gui/SmartPickupFrame.lua")
|
||||
end
|
||||
|
||||
-- Markøren er dér hvor trækkerens næse stopper; læssetriggeren ligger et
|
||||
-- vogntog bagved. Siloer tættere end dette regnes som "markørens silo".
|
||||
ADSmartPickup.MAX_MARKER_TO_TRIGGER_DISTANCE = 40
|
||||
@@ -671,6 +676,76 @@ local function restoreStoppedVehicles()
|
||||
end
|
||||
end
|
||||
|
||||
-- Indsætter fanen i ESC-menuen foran Statistik/Priser (mønster fra FS25_FarmOperationsDashboard).
|
||||
local function insertInGameMenuPage(frame, pageName, iconFile, uvs, position, predicate)
|
||||
local inGameMenu = g_gui ~= nil and g_gui.screenControllers ~= nil and g_gui.screenControllers[InGameMenu] or nil
|
||||
if inGameMenu == nil or inGameMenu.pagingElement == nil then
|
||||
return false
|
||||
end
|
||||
local insertAt = position
|
||||
for i = 1, #inGameMenu.pagingElement.elements do
|
||||
local child = inGameMenu.pagingElement.elements[i]
|
||||
if child == inGameMenu.pageStatistics or child == inGameMenu.pagePrices then
|
||||
insertAt = i
|
||||
break
|
||||
end
|
||||
end
|
||||
if inGameMenu.controlIDs ~= nil then
|
||||
inGameMenu.controlIDs[pageName] = nil
|
||||
end
|
||||
inGameMenu[pageName] = frame
|
||||
inGameMenu.pagingElement:addElement(frame)
|
||||
if inGameMenu.exposeControlsAsFields ~= nil then
|
||||
inGameMenu:exposeControlsAsFields(pageName)
|
||||
end
|
||||
for _, list in ipairs({inGameMenu.pagingElement.elements, inGameMenu.pageFrames}) do
|
||||
for i = 1, #list do
|
||||
if list[i] == frame then
|
||||
table.remove(list, i)
|
||||
table.insert(list, insertAt, frame)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
for i = 1, #inGameMenu.pagingElement.pages do
|
||||
if inGameMenu.pagingElement.pages[i].element == frame then
|
||||
local page = table.remove(inGameMenu.pagingElement.pages, i)
|
||||
table.insert(inGameMenu.pagingElement.pages, insertAt, page)
|
||||
break
|
||||
end
|
||||
end
|
||||
inGameMenu.pagingElement:updateAbsolutePosition()
|
||||
inGameMenu.pagingElement:updatePageMapping()
|
||||
inGameMenu:registerPage(frame, position, predicate)
|
||||
inGameMenu:addPageTab(frame, iconFile, GuiUtils.getUVs(uvs))
|
||||
inGameMenu:rebuildTabList()
|
||||
return true
|
||||
end
|
||||
|
||||
local function loadGui()
|
||||
if g_gui == nil or SmartPickupFrame == nil or ADSmartPickup.dir == nil then
|
||||
return
|
||||
end
|
||||
g_gui:loadProfiles(ADSmartPickup.dir .. "gui/guiProfiles.xml")
|
||||
local frame = SmartPickupFrame.new(g_i18n, getAutoDriveEnv)
|
||||
g_gui:loadGui(ADSmartPickup.dir .. "gui/SmartPickupFrame.xml", "smartPickupFrame", frame, true)
|
||||
local iconFile = Utils.getFilename("icon.dds", ADSmartPickup.dir)
|
||||
if not insertInGameMenuPage(frame, "smartPickupFrame", iconFile, {0, 0, 512, 512}, 2, function() return g_currentMission ~= nil end) then
|
||||
Logging.warning(ADSmartPickup.LOG_PREFIX .. "kunne ikke indsætte fanen i ESC-menuen")
|
||||
return
|
||||
end
|
||||
frame:initialize()
|
||||
ADSmartPickup.guiFrame = frame
|
||||
Logging.info(ADSmartPickup.LOG_PREFIX .. "ESC-fane 'Smart Pickup' registreret")
|
||||
end
|
||||
|
||||
function ADSmartPickup:loadMap()
|
||||
local ok, err = pcall(loadGui)
|
||||
if not ok then
|
||||
Logging.warning(ADSmartPickup.LOG_PREFIX .. "GUI kunne ikke indlæses (resten af moden virker): %s", tostring(err))
|
||||
end
|
||||
end
|
||||
|
||||
function ADSmartPickup:update(dt)
|
||||
if not isHooked then
|
||||
local adEnv = getAutoDriveEnv()
|
||||
|
||||
@@ -0,0 +1,407 @@
|
||||
-- Smart Pickup — ESC-fane
|
||||
-- Viser og redigerer runs og starter/stopper dem. Al logik ligger i ADRunsController;
|
||||
-- her oversættes kun mellem GUI-elementer og run-felter. Alt kører i pcall så en GUI-fejl
|
||||
-- aldrig tager spillet med sig.
|
||||
|
||||
SmartPickupFrame = {}
|
||||
SmartPickupFrame._mt = Class(SmartPickupFrame, TabbedMenuFrameElement)
|
||||
|
||||
SmartPickupFrame.REFRESH_INTERVAL_MS = 1000
|
||||
SmartPickupFrame.LOG_PREFIX = "ADSmartPickup: "
|
||||
SmartPickupFrame.STATE_OFF, SmartPickupFrame.STATE_ON = 1, 2
|
||||
|
||||
function SmartPickupFrame.new(i18n, getAdEnv)
|
||||
local self = SmartPickupFrame:superClass().new(nil, SmartPickupFrame._mt)
|
||||
self.name = "SmartPickupFrame"
|
||||
self.i18n = i18n
|
||||
self.getAdEnv = getAdEnv
|
||||
self.selectedRunId = nil
|
||||
self.runIds, self.targetIds, self.poolGroups = {}, {}, {}
|
||||
self.rowData = {} -- element -> {kind = "ingredient"|"vehicle", ...}
|
||||
self.clonedRows = {}
|
||||
self.refreshTimer = 0
|
||||
self.statusOverride = nil
|
||||
self.backButtonInfo = {inputAction = InputAction.MENU_BACK}
|
||||
self.startButtonInfo = {inputAction = InputAction.MENU_ACTIVATE, text = i18n:getText("spu_button_start"), callback = function() self:onClickStartStop() end}
|
||||
self.newButtonInfo = {inputAction = InputAction.MENU_EXTRA_1, text = i18n:getText("spu_button_new"), callback = function() self:onClickNew() end}
|
||||
self.renameButtonInfo = {inputAction = InputAction.MENU_EXTRA_2, text = i18n:getText("spu_button_rename"), callback = function() self:onClickRename() end}
|
||||
self.deleteButtonInfo = {inputAction = InputAction.MENU_CANCEL, text = i18n:getText("spu_button_delete"), callback = function() self:onClickDelete() end}
|
||||
self:setMenuButtonInfo({self.backButtonInfo, self.startButtonInfo, self.newButtonInfo, self.renameButtonInfo, self.deleteButtonInfo})
|
||||
return self
|
||||
end
|
||||
|
||||
function SmartPickupFrame:delete()
|
||||
SmartPickupFrame:superClass().delete(self)
|
||||
end
|
||||
|
||||
function SmartPickupFrame:copyAttributes(src)
|
||||
SmartPickupFrame:superClass().copyAttributes(self, src)
|
||||
self.i18n, self.getAdEnv = src.i18n, src.getAdEnv
|
||||
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", "poolPrefab"}) do
|
||||
local prefab = self[name]
|
||||
if prefab ~= nil then
|
||||
prefab:unlinkElement()
|
||||
FocusManager:removeElement(prefab)
|
||||
end
|
||||
end
|
||||
self.ingredientModeOption:setTexts({self.i18n:getText("spu_mode_auto"), self.i18n:getText("spu_mode_manual")})
|
||||
local loopTexts = {self.i18n:getText("spu_loops_infinite")}
|
||||
for loops = 1, ADRuns.MAX_LOOPS do
|
||||
table.insert(loopTexts, tostring(loops))
|
||||
end
|
||||
self.loopsOption:setTexts(loopTexts)
|
||||
end
|
||||
|
||||
function SmartPickupFrame:onFrameOpen()
|
||||
SmartPickupFrame:superClass().onFrameOpen(self)
|
||||
self.statusOverride = nil
|
||||
self:safe(self.rebuild)
|
||||
FocusManager:setFocus(self.runOption)
|
||||
end
|
||||
|
||||
function SmartPickupFrame:onFrameClose()
|
||||
SmartPickupFrame:superClass().onFrameClose(self)
|
||||
end
|
||||
|
||||
-- Live-opdatering af status/traktor-rækker mens siden er åben (uden at genopbygge rækkerne).
|
||||
function SmartPickupFrame:update(dt)
|
||||
SmartPickupFrame:superClass().update(self, dt)
|
||||
self.refreshTimer = self.refreshTimer + dt
|
||||
if self.refreshTimer >= SmartPickupFrame.REFRESH_INTERVAL_MS then
|
||||
self.refreshTimer = 0
|
||||
self:safe(self.refreshLive)
|
||||
end
|
||||
end
|
||||
|
||||
function SmartPickupFrame:safe(fn, ...)
|
||||
local ok, err = pcall(fn, self, ...)
|
||||
if not ok then
|
||||
Logging.warning(SmartPickupFrame.LOG_PREFIX .. "GUI-fejl: %s", tostring(err))
|
||||
self.statusOverride = string.format(self.i18n:getText("spu_status_error"), tostring(err))
|
||||
if self.statusText ~= nil then
|
||||
self.statusText:setText(self.statusOverride)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function SmartPickupFrame:getRun()
|
||||
return self.selectedRunId ~= nil and ADRuns.getRun(ADRunsController.store, self.selectedRunId) or nil
|
||||
end
|
||||
|
||||
-- ---- opbygning ----
|
||||
|
||||
function SmartPickupFrame:clearRows()
|
||||
for _, row in ipairs(self.clonedRows) do
|
||||
row:delete()
|
||||
end
|
||||
self.clonedRows, self.rowData = {}, {}
|
||||
end
|
||||
|
||||
function SmartPickupFrame:addRow(prefab, parent, data)
|
||||
local row = prefab:clone(parent)
|
||||
FocusManager:loadElementFromCustomValues(row)
|
||||
table.insert(self.clonedRows, row)
|
||||
local option = row:getDescendantByName("option")
|
||||
if option ~= nil then
|
||||
option:setTexts({self.i18n:getText("ui_no"), self.i18n:getText("ui_yes")})
|
||||
self.rowData[option] = data
|
||||
end
|
||||
return row
|
||||
end
|
||||
|
||||
function SmartPickupFrame:rebuild()
|
||||
local adEnv = self.getAdEnv()
|
||||
local store = ADRunsController.store
|
||||
if self.selectedRunId == nil or ADRuns.getRun(store, self.selectedRunId) == nil then
|
||||
self.selectedRunId = store.runs[1] ~= nil and store.runs[1].id or nil
|
||||
end
|
||||
self:clearRows()
|
||||
self:fillRunOption(adEnv)
|
||||
local run = self:getRun()
|
||||
local hasRun = run ~= nil and adEnv ~= nil
|
||||
for _, element in ipairs({self.targetOption, self.ingredientModeOption, self.waitPoolOption, self.loopsOption}) do
|
||||
element:setDisabled(not hasRun)
|
||||
end
|
||||
if hasRun then
|
||||
self:fillTargetOption(adEnv, run)
|
||||
self.ingredientModeOption:setState(run.ingredientMode == "manual" and SmartPickupFrame.STATE_ON or SmartPickupFrame.STATE_OFF, true)
|
||||
self:fillIngredientRows(adEnv, run)
|
||||
self:fillWaitPoolOption(adEnv, run)
|
||||
self.loopsOption:setState(run.loops + 1, true)
|
||||
self:fillVehicleRows(adEnv, run)
|
||||
end
|
||||
self:fillPoolRows(adEnv)
|
||||
for _, box in ipairs({self.ingredientBox, self.vehicleBox, self.poolBox, self.boxLayout}) do
|
||||
box:invalidateLayout()
|
||||
end
|
||||
self:refreshLive()
|
||||
end
|
||||
|
||||
function SmartPickupFrame:fillRunOption(adEnv)
|
||||
local texts, index = {}, 1
|
||||
self.runIds = {}
|
||||
for position, run in ipairs(ADRunsController.store.runs) do
|
||||
local status = adEnv ~= nil and ADRunsController.getRunStatus(adEnv, run) or {running = 0, total = #run.vehicleIds}
|
||||
table.insert(texts, string.format("%s (%d/%d)", run.name, status.running, status.total))
|
||||
table.insert(self.runIds, run.id)
|
||||
if run.id == self.selectedRunId then
|
||||
index = position
|
||||
end
|
||||
end
|
||||
if #texts == 0 then
|
||||
texts = {self.i18n:getText("spu_noRuns")}
|
||||
end
|
||||
self.runOption:setTexts(texts)
|
||||
self.runOption:setState(index, true)
|
||||
self.runOption:setDisabled(#self.runIds == 0)
|
||||
end
|
||||
|
||||
function SmartPickupFrame:fillTargetOption(adEnv, run)
|
||||
local texts, index = {self.i18n:getText("spu_noTarget")}, 1
|
||||
self.targetIds = {false}
|
||||
for _, marker in ipairs(ADRunsController.getTargetMarkers(adEnv, g_currentMission:getFarmId())) do
|
||||
table.insert(texts, tostring(marker.name))
|
||||
table.insert(self.targetIds, marker.id)
|
||||
if marker.id == run.targetWayPointId then
|
||||
index = #texts
|
||||
end
|
||||
end
|
||||
self.targetOption:setTexts(texts)
|
||||
self.targetOption:setState(index, true)
|
||||
end
|
||||
|
||||
function SmartPickupFrame:fillIngredientRows(adEnv, run)
|
||||
if run.ingredientMode ~= "manual" then
|
||||
return
|
||||
end
|
||||
local chosen = {}
|
||||
for _, name in ipairs(run.ingredients) do
|
||||
chosen[name] = true
|
||||
end
|
||||
for _, fillType in ipairs(ADRunsController.getTargetAcceptedFillTypes(adEnv, run)) do
|
||||
local row = self:addRow(self.ingredientPrefab, self.ingredientBox, {kind = "ingredient", name = fillType.name})
|
||||
row:getDescendantByName("title"):setText(tostring(fillType.title))
|
||||
row:getDescendantByName("option"):setState(chosen[fillType.name] and SmartPickupFrame.STATE_ON or SmartPickupFrame.STATE_OFF, true)
|
||||
end
|
||||
end
|
||||
|
||||
function SmartPickupFrame:fillWaitPoolOption(adEnv, run)
|
||||
local texts, index = {self.i18n:getText("spu_waitPool_all")}, 1
|
||||
self.poolGroups = {""}
|
||||
for _, pool in ipairs(ADRunsController.getWaitPools(adEnv)) do
|
||||
table.insert(texts, string.format("%s (%d)", pool.group, pool.count))
|
||||
table.insert(self.poolGroups, pool.group)
|
||||
if pool.group == run.waitPoolGroup then
|
||||
index = #texts
|
||||
end
|
||||
end
|
||||
self.waitPoolOption:setTexts(texts)
|
||||
self.waitPoolOption:setState(index, true)
|
||||
end
|
||||
|
||||
function SmartPickupFrame:fillVehicleRows(adEnv, run)
|
||||
local inRun = {}
|
||||
for _, id in ipairs(run.vehicleIds) do
|
||||
inRun[id] = true
|
||||
end
|
||||
for _, vehicle in ipairs(ADRunsController.getFarmVehicles(adEnv)) do
|
||||
local id = ADRunsController.getVehicleId(vehicle)
|
||||
local row = self:addRow(self.vehiclePrefab, self.vehicleBox, {kind = "vehicle", vehicle = vehicle, row = nil})
|
||||
self.rowData[row:getDescendantByName("option")].row = row
|
||||
row:getDescendantByName("option"):setState(inRun[id] and SmartPickupFrame.STATE_ON or SmartPickupFrame.STATE_OFF, true)
|
||||
row:getDescendantByName("title"):setText(self:describeVehicle(adEnv, run, vehicle, inRun[id]))
|
||||
end
|
||||
end
|
||||
|
||||
-- "Fastrac 2135 4WS (#1) — 1.000.000 l — ✔" / "… — ✖ ingen vogn"; reservationsnote fra Start bevares.
|
||||
function SmartPickupFrame:describeVehicle(adEnv, run, vehicle, isInRun)
|
||||
local label = ADRunsController.getVehicleLabel(adEnv, vehicle)
|
||||
if not isInRun then
|
||||
return label
|
||||
end
|
||||
local validation = ADRunsController.validateVehicle(adEnv, run, vehicle)
|
||||
local capacity = validation.capacity ~= nil and string.format(self.i18n:getText("spu_capacity"), g_i18n:formatNumber(validation.capacity, 0)) or nil
|
||||
local parts = {label}
|
||||
if capacity ~= nil then
|
||||
table.insert(parts, capacity)
|
||||
end
|
||||
if validation.ok then
|
||||
table.insert(parts, "✔")
|
||||
else
|
||||
table.insert(parts, "✖ " .. self.i18n:getText("spu_reason_" .. tostring(validation.reason)))
|
||||
end
|
||||
return table.concat(parts, " — ")
|
||||
end
|
||||
|
||||
function SmartPickupFrame:fillPoolRows(adEnv)
|
||||
if adEnv == nil then
|
||||
return
|
||||
end
|
||||
local occupied = {}
|
||||
for _, claim in ipairs(ADUnloadWait.getClaims()) do
|
||||
occupied[claim.marker.group] = occupied[claim.marker.group] or {}
|
||||
table.insert(occupied[claim.marker.group], ADRunsController.getVehicleLabel(adEnv, claim.vehicle))
|
||||
end
|
||||
for _, pool in ipairs(ADRunsController.getWaitPools(adEnv)) do
|
||||
local names = occupied[pool.group] or {}
|
||||
local suffix = #names > 0 and (" (" .. table.concat(names, ", ") .. ")") or ""
|
||||
local row = self:addRow(self.poolPrefab, self.poolBox, {kind = "pool"})
|
||||
row:getDescendantByName("title"):setText(string.format(self.i18n:getText("spu_waitPoolRow"), pool.group, pool.count, #names, suffix))
|
||||
end
|
||||
end
|
||||
|
||||
-- Status + Start/Stop-knappens tekst, kaldes hvert sekund.
|
||||
function SmartPickupFrame:refreshLive()
|
||||
local adEnv = self.getAdEnv()
|
||||
local run = self:getRun()
|
||||
if adEnv == nil then
|
||||
self.statusText:setText(self.i18n:getText("spu_status_noAd"))
|
||||
return
|
||||
end
|
||||
local isRunning = false
|
||||
if run ~= nil then
|
||||
local status = ADRunsController.getRunStatus(adEnv, run)
|
||||
isRunning = status.running > 0
|
||||
local text = isRunning and string.format(self.i18n:getText("spu_status_running"), status.running, status.total)
|
||||
or string.format(self.i18n:getText("spu_status_stopped"), status.total)
|
||||
self.statusText:setText(self.statusOverride or text)
|
||||
for option, data in pairs(self.rowData) do
|
||||
if data.kind == "vehicle" and data.row ~= nil then
|
||||
data.row:getDescendantByName("title"):setText(self:describeVehicle(adEnv, run, data.vehicle, option:getState() == SmartPickupFrame.STATE_ON))
|
||||
end
|
||||
end
|
||||
else
|
||||
self.statusText:setText(self.statusOverride or self.i18n:getText("spu_noRuns"))
|
||||
end
|
||||
self.startButtonInfo.text = self.i18n:getText(isRunning and "spu_button_stop" or "spu_button_start")
|
||||
self.startButtonInfo.disabled = run == nil
|
||||
self.renameButtonInfo.disabled = run == nil
|
||||
self.deleteButtonInfo.disabled = run == nil
|
||||
self:setMenuButtonInfoDirty()
|
||||
end
|
||||
|
||||
-- ---- callbacks fra XML (state = 1-baseret indeks; element = det klikkede element) ----
|
||||
|
||||
function SmartPickupFrame:onClickRun(state)
|
||||
self.selectedRunId = self.runIds[state]
|
||||
self.statusOverride = nil
|
||||
self:safe(self.rebuild)
|
||||
end
|
||||
|
||||
function SmartPickupFrame:onClickTarget(state)
|
||||
local run = self:getRun()
|
||||
if run == nil then return end
|
||||
-- targetIds[1] er false = "(vælg mål)"; modellen tolker false som "ryd målet"
|
||||
ADRunsController.updateRun(run.id, {targetWayPointId = self.targetIds[state] or false})
|
||||
self:safe(self.rebuild)
|
||||
end
|
||||
|
||||
function SmartPickupFrame:onClickIngredientMode(state)
|
||||
local run = self:getRun()
|
||||
if run == nil then return end
|
||||
ADRunsController.updateRun(run.id, {ingredientMode = state == SmartPickupFrame.STATE_ON and "manual" or "auto"})
|
||||
self:safe(self.rebuild)
|
||||
end
|
||||
|
||||
function SmartPickupFrame:onClickIngredient(state, element)
|
||||
local run, data = self:getRun(), self.rowData[element]
|
||||
if run == nil or data == nil then return end
|
||||
local names = {}
|
||||
for _, name in ipairs(run.ingredients) do
|
||||
if name ~= data.name then table.insert(names, name) end
|
||||
end
|
||||
if state == SmartPickupFrame.STATE_ON then
|
||||
table.insert(names, data.name)
|
||||
end
|
||||
ADRunsController.updateRun(run.id, {ingredients = names})
|
||||
end
|
||||
|
||||
function SmartPickupFrame:onClickWaitPool(state)
|
||||
local run = self:getRun()
|
||||
if run == nil then return end
|
||||
ADRunsController.updateRun(run.id, {waitPoolGroup = self.poolGroups[state] or ""})
|
||||
end
|
||||
|
||||
function SmartPickupFrame:onClickLoops(state)
|
||||
local run = self:getRun()
|
||||
if run == nil then return end
|
||||
ADRunsController.updateRun(run.id, {loops = state - 1})
|
||||
end
|
||||
|
||||
function SmartPickupFrame:onClickVehicle(state, element)
|
||||
local run, data = self:getRun(), self.rowData[element]
|
||||
if run == nil or data == nil then return end
|
||||
if state == SmartPickupFrame.STATE_ON then
|
||||
local previousRunId = ADRunsController.assignVehicle(run.id, data.vehicle)
|
||||
if previousRunId ~= nil then
|
||||
local previous = ADRuns.getRun(ADRunsController.store, previousRunId)
|
||||
self.statusOverride = string.format(self.i18n:getText("spu_movedFrom"), previous ~= nil and previous.name or tostring(previousRunId))
|
||||
end
|
||||
else
|
||||
ADRunsController.unassignVehicle(data.vehicle)
|
||||
end
|
||||
self:safe(self.refreshLive)
|
||||
end
|
||||
|
||||
-- ---- knapper i bundlinjen ----
|
||||
|
||||
function SmartPickupFrame:onClickStartStop()
|
||||
self:safe(function(frame)
|
||||
local adEnv, run = frame.getAdEnv(), frame:getRun()
|
||||
if adEnv == nil or run == nil then return end
|
||||
if ADRunsController.getRunStatus(adEnv, run).running > 0 then
|
||||
ADRunsController.stopRun(adEnv, run.id)
|
||||
frame.statusOverride = nil
|
||||
else
|
||||
local started, skipped = 0, 0
|
||||
for _, result in ipairs(ADRunsController.startRun(adEnv, run.id)) do
|
||||
if result.ok then started = started + 1 else skipped = skipped + 1 end
|
||||
end
|
||||
frame.statusOverride = string.format(frame.i18n:getText("spu_status_started"), started, skipped)
|
||||
end
|
||||
ADRunsController.save()
|
||||
frame:rebuild()
|
||||
end)
|
||||
end
|
||||
|
||||
function SmartPickupFrame:onClickNew()
|
||||
self:safe(function(frame)
|
||||
local run = ADRunsController.createRun(string.format(frame.i18n:getText("spu_newRunName"), ADRunsController.store.nextId - 1))
|
||||
frame.selectedRunId = run.id
|
||||
frame.statusOverride = nil
|
||||
frame:rebuild()
|
||||
end)
|
||||
end
|
||||
|
||||
function SmartPickupFrame:onClickRename()
|
||||
local run = self:getRun()
|
||||
if run == nil then return end
|
||||
TextInputDialog.show(SmartPickupFrame.onRenameResult, self, run.name, self.i18n:getText("spu_renameTitle"), nil, 30, g_i18n:getText("button_ok"))
|
||||
end
|
||||
|
||||
function SmartPickupFrame:onRenameResult(value, clickOk)
|
||||
local run = self:getRun()
|
||||
if clickOk and run ~= nil and value ~= nil and value:match("%S") then
|
||||
ADRunsController.updateRun(run.id, {name = value})
|
||||
self:safe(self.rebuild)
|
||||
end
|
||||
end
|
||||
|
||||
function SmartPickupFrame:onClickDelete()
|
||||
local run = self:getRun()
|
||||
if run == nil then return end
|
||||
YesNoDialog.show(SmartPickupFrame.onDeleteResult, self, string.format(self.i18n:getText("spu_deleteConfirm"), run.name), self.i18n:getText("spu_button_delete"))
|
||||
end
|
||||
|
||||
function SmartPickupFrame:onDeleteResult(yes)
|
||||
local run = self:getRun()
|
||||
if yes and run ~= nil then
|
||||
ADRunsController.deleteRun(run.id)
|
||||
self.selectedRunId = nil
|
||||
self:safe(self.rebuild)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,73 @@
|
||||
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||
<GUI name="smartPickupFrame">
|
||||
<GuiElement profile="fs25_menuContainer">
|
||||
<GuiElement profile="fs25_menuHeaderPanel">
|
||||
<Bitmap profile="fs25_menuHeaderIconBg">
|
||||
<Bitmap profile="spuMenuHeaderIcon"/>
|
||||
</Bitmap>
|
||||
<Text profile="fs25_menuHeaderTitle" text="$l10n_spu_title"/>
|
||||
</GuiElement>
|
||||
|
||||
<GuiElement profile="spuTabContainer">
|
||||
<ScrollingLayout profile="fs25_settingsLayout" id="boxLayout">
|
||||
<Bitmap profile="fs25_multiTextOptionContainer">
|
||||
<MultiTextOption profile="fs25_settingsMultiTextOption" onClick="onClickRun" id="runOption">
|
||||
<Text profile="fs25_multiTextOptionTooltip" name="ignore" text="$l10n_spu_run_tooltip"/>
|
||||
</MultiTextOption>
|
||||
<Text profile="fs25_settingsMultiTextOptionTitle" text="$l10n_spu_run"/>
|
||||
</Bitmap>
|
||||
<Bitmap profile="fs25_multiTextOptionContainer">
|
||||
<MultiTextOption profile="fs25_settingsMultiTextOption" onClick="onClickTarget" id="targetOption">
|
||||
<Text profile="fs25_multiTextOptionTooltip" name="ignore" text="$l10n_spu_target_tooltip"/>
|
||||
</MultiTextOption>
|
||||
<Text profile="fs25_settingsMultiTextOptionTitle" text="$l10n_spu_target"/>
|
||||
</Bitmap>
|
||||
<Bitmap profile="fs25_multiTextOptionContainer">
|
||||
<BinaryOption profile="fs25_settingsBinaryOption" onClick="onClickIngredientMode" id="ingredientModeOption">
|
||||
<Text profile="fs25_multiTextOptionTooltip" name="ignore" text="$l10n_spu_ingredientMode_tooltip"/>
|
||||
</BinaryOption>
|
||||
<Text profile="fs25_settingsMultiTextOptionTitle" text="$l10n_spu_ingredientMode"/>
|
||||
</Bitmap>
|
||||
<BoxLayout profile="fs25_settingsLayout" id="ingredientBox"/>
|
||||
<Bitmap profile="fs25_multiTextOptionContainer">
|
||||
<MultiTextOption profile="fs25_settingsMultiTextOption" onClick="onClickWaitPool" id="waitPoolOption">
|
||||
<Text profile="fs25_multiTextOptionTooltip" name="ignore" text="$l10n_spu_waitPool_tooltip"/>
|
||||
</MultiTextOption>
|
||||
<Text profile="fs25_settingsMultiTextOptionTitle" text="$l10n_spu_waitPool"/>
|
||||
</Bitmap>
|
||||
<Bitmap profile="fs25_multiTextOptionContainer">
|
||||
<MultiTextOption profile="fs25_settingsMultiTextOption" onClick="onClickLoops" id="loopsOption">
|
||||
<Text profile="fs25_multiTextOptionTooltip" name="ignore" text="$l10n_spu_loops_tooltip"/>
|
||||
</MultiTextOption>
|
||||
<Text profile="fs25_settingsMultiTextOptionTitle" text="$l10n_spu_loops"/>
|
||||
</Bitmap>
|
||||
<Bitmap profile="fs25_multiTextOptionContainer">
|
||||
<Text profile="spuSectionTitle" text="$l10n_spu_vehicles"/>
|
||||
</Bitmap>
|
||||
<BoxLayout profile="fs25_settingsLayout" id="vehicleBox"/>
|
||||
<Bitmap profile="fs25_multiTextOptionContainer">
|
||||
<Text profile="spuSectionTitle" text="$l10n_spu_waitPools"/>
|
||||
</Bitmap>
|
||||
<BoxLayout profile="fs25_settingsLayout" id="poolBox"/>
|
||||
<Bitmap profile="fs25_multiTextOptionContainer">
|
||||
<Text profile="spuInfoText" id="statusText"/>
|
||||
</Bitmap>
|
||||
</ScrollingLayout>
|
||||
|
||||
<!-- prefabs: klones pr. vare / traktor / pulje og fjernes fra layoutet ved initialize -->
|
||||
<Bitmap profile="fs25_multiTextOptionContainer" id="ingredientPrefab">
|
||||
<BinaryOption profile="fs25_settingsBinaryOption" onClick="onClickIngredient" name="option"/>
|
||||
<Text profile="fs25_settingsMultiTextOptionTitle" name="title"/>
|
||||
</Bitmap>
|
||||
<Bitmap profile="fs25_multiTextOptionContainer" id="vehiclePrefab">
|
||||
<BinaryOption profile="fs25_settingsBinaryOption" onClick="onClickVehicle" name="option">
|
||||
<Text profile="fs25_multiTextOptionTooltip" name="ignore" text="$l10n_spu_vehicle_tooltip"/>
|
||||
</BinaryOption>
|
||||
<Text profile="fs25_settingsMultiTextOptionTitle" name="title"/>
|
||||
</Bitmap>
|
||||
<Bitmap profile="fs25_multiTextOptionContainer" id="poolPrefab">
|
||||
<Text profile="spuInfoText" name="title"/>
|
||||
</Bitmap>
|
||||
</GuiElement>
|
||||
</GuiElement>
|
||||
</GUI>
|
||||
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||
<GUIProfiles>
|
||||
<Profile name="spuMenuHeaderIcon" extends="baseReference" with="anchorMiddleCenter">
|
||||
<size value="50px 50px"/>
|
||||
<imageSliceId value="gui.icon_ingameMenu_vehicles"/>
|
||||
<imageColor value="$preset_fs25_colorMainDark"/>
|
||||
</Profile>
|
||||
<Profile name="spuTabContainer" extends="emptyPanel" with="anchorStretchingYStretchingX pivotTopLeft">
|
||||
<position value="0px -90px"/>
|
||||
<absoluteSizeOffset value="0px 90px"/>
|
||||
</Profile>
|
||||
<Profile name="spuSectionTitle" extends="fs25_settingsMultiTextOptionTitle">
|
||||
<textBold value="true"/>
|
||||
<textUpperCase value="true"/>
|
||||
</Profile>
|
||||
<Profile name="spuInfoText" extends="fs25_settingsMultiTextOptionTitle">
|
||||
<textBold value="false"/>
|
||||
<size value="1400px 40px"/>
|
||||
</Profile>
|
||||
</GUIProfiles>
|
||||
@@ -0,0 +1,47 @@
|
||||
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||
<l10n>
|
||||
<texts>
|
||||
<text name="spu_title" text="Smart Pickup"/>
|
||||
<text name="spu_run" text="Run"/>
|
||||
<text name="spu_run_tooltip" text="Vælg det run du vil se eller ændre."/>
|
||||
<text name="spu_noRuns" text="Ingen runs — tryk 'Nyt run'"/>
|
||||
<text name="spu_target" text="Mål"/>
|
||||
<text name="spu_target_tooltip" text="AutoDrive-markør ved stalden eller fabrikken der skal fyldes."/>
|
||||
<text name="spu_noTarget" text="(vælg mål)"/>
|
||||
<text name="spu_ingredientMode" text="Varer"/>
|
||||
<text name="spu_ingredientMode_tooltip" text="Auto: alt målet tager (fabrik: de tændte produktioners inputs). Vælg: afkryds selv."/>
|
||||
<text name="spu_mode_auto" text="Auto"/>
|
||||
<text name="spu_mode_manual" text="Vælg"/>
|
||||
<text name="spu_waitPool" text="Wait-pulje"/>
|
||||
<text name="spu_waitPool_tooltip" text="Mappe med Wait-markører, hvor traktorer med rest-læs venter."/>
|
||||
<text name="spu_waitPool_all" text="Alle (nærmeste ledige)"/>
|
||||
<text name="spu_loops" text="Ture"/>
|
||||
<text name="spu_loops_tooltip" text="Antal ture pr. traktor; 0 = uendeligt."/>
|
||||
<text name="spu_loops_infinite" text="0 = uendeligt"/>
|
||||
<text name="spu_vehicles" text="Traktorer"/>
|
||||
<text name="spu_vehicle_tooltip" text="Ja = traktoren er med i dette run."/>
|
||||
<text name="spu_waitPools" text="Wait-puljer"/>
|
||||
<text name="spu_waitPoolRow" text="%s — %d punkter — %d optaget%s"/>
|
||||
<text name="spu_status" text="Status"/>
|
||||
<text name="spu_status_running" text="Kører (%d/%d)"/>
|
||||
<text name="spu_status_stopped" text="Stoppet (%d traktorer)"/>
|
||||
<text name="spu_status_started" text="Startet %d, sprunget over %d"/>
|
||||
<text name="spu_status_noAd" text="AutoDrive-API ikke fundet"/>
|
||||
<text name="spu_status_error" text="Fejl: %s"/>
|
||||
<text name="spu_reason_noTrailer" text="ingen vogn"/>
|
||||
<text name="spu_reason_cannotCarry" text="vognen kan ikke bære run'ets varer"/>
|
||||
<text name="spu_reason_farFromNetwork" text="for langt fra vejnettet"/>
|
||||
<text name="spu_reason_noTarget" text="intet mål"/>
|
||||
<text name="spu_reason_error" text="fejl ved start (se log)"/>
|
||||
<text name="spu_movedFrom" text="flyttet fra '%s'"/>
|
||||
<text name="spu_button_start" text="Start run"/>
|
||||
<text name="spu_button_stop" text="Stop run"/>
|
||||
<text name="spu_button_new" text="Nyt run"/>
|
||||
<text name="spu_button_rename" text="Omdøb"/>
|
||||
<text name="spu_button_delete" text="Slet run"/>
|
||||
<text name="spu_newRunName" text="Run %d"/>
|
||||
<text name="spu_renameTitle" text="Navn på run"/>
|
||||
<text name="spu_deleteConfirm" text="Slet run '%s'? Traktorerne stoppes ikke."/>
|
||||
<text name="spu_capacity" text="%s l"/>
|
||||
</texts>
|
||||
</l10n>
|
||||
@@ -0,0 +1,47 @@
|
||||
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||
<l10n>
|
||||
<texts>
|
||||
<text name="spu_title" text="Smart Pickup"/>
|
||||
<text name="spu_run" text="Run"/>
|
||||
<text name="spu_run_tooltip" text="Select the run to view or edit."/>
|
||||
<text name="spu_noRuns" text="No runs — press 'New run'"/>
|
||||
<text name="spu_target" text="Target"/>
|
||||
<text name="spu_target_tooltip" text="AutoDrive marker at the barn or factory to keep filled."/>
|
||||
<text name="spu_noTarget" text="(choose target)"/>
|
||||
<text name="spu_ingredientMode" text="Goods"/>
|
||||
<text name="spu_ingredientMode_tooltip" text="Auto: everything the target accepts (factory: inputs of enabled productions). Select: tick them yourself."/>
|
||||
<text name="spu_mode_auto" text="Auto"/>
|
||||
<text name="spu_mode_manual" text="Select"/>
|
||||
<text name="spu_waitPool" text="Wait pool"/>
|
||||
<text name="spu_waitPool_tooltip" text="Folder of Wait markers where tractors with leftover load wait."/>
|
||||
<text name="spu_waitPool_all" text="All (nearest free)"/>
|
||||
<text name="spu_loops" text="Loops"/>
|
||||
<text name="spu_loops_tooltip" text="Trips per tractor; 0 = endless."/>
|
||||
<text name="spu_loops_infinite" text="0 = endless"/>
|
||||
<text name="spu_vehicles" text="Tractors"/>
|
||||
<text name="spu_vehicle_tooltip" text="Yes = the tractor belongs to this run."/>
|
||||
<text name="spu_waitPools" text="Wait pools"/>
|
||||
<text name="spu_waitPoolRow" text="%s — %d points — %d occupied%s"/>
|
||||
<text name="spu_status" text="Status"/>
|
||||
<text name="spu_status_running" text="Running (%d/%d)"/>
|
||||
<text name="spu_status_stopped" text="Stopped (%d tractors)"/>
|
||||
<text name="spu_status_started" text="Started %d, skipped %d"/>
|
||||
<text name="spu_status_noAd" text="AutoDrive API not found"/>
|
||||
<text name="spu_status_error" text="Error: %s"/>
|
||||
<text name="spu_reason_noTrailer" text="no trailer"/>
|
||||
<text name="spu_reason_cannotCarry" text="trailer cannot carry the run's goods"/>
|
||||
<text name="spu_reason_farFromNetwork" text="too far from the road network"/>
|
||||
<text name="spu_reason_noTarget" text="no target"/>
|
||||
<text name="spu_reason_error" text="start failed (see log)"/>
|
||||
<text name="spu_movedFrom" text="moved from '%s'"/>
|
||||
<text name="spu_button_start" text="Start run"/>
|
||||
<text name="spu_button_stop" text="Stop run"/>
|
||||
<text name="spu_button_new" text="New run"/>
|
||||
<text name="spu_button_rename" text="Rename"/>
|
||||
<text name="spu_button_delete" text="Delete run"/>
|
||||
<text name="spu_newRunName" text="Run %d"/>
|
||||
<text name="spu_renameTitle" text="Run name"/>
|
||||
<text name="spu_deleteConfirm" text="Delete run '%s'? Tractors are not stopped."/>
|
||||
<text name="spu_capacity" text="%s l"/>
|
||||
</texts>
|
||||
</l10n>
|
||||
@@ -10,6 +10,7 @@
|
||||
</description>
|
||||
<iconFilename>icon.dds</iconFilename>
|
||||
<multiplayer supported="true"/>
|
||||
<l10n filenamePrefix="l10n/l10n"/>
|
||||
<extraSourceFiles>
|
||||
<sourceFile filename="adSupplyPlanner.lua"/>
|
||||
<sourceFile filename="adRuns.lua"/>
|
||||
|
||||
Reference in New Issue
Block a user