-- Type-to-search move picker. The inspector used to change moves by cycling -- the catalog one tap at a time -- 165 taps to walk Gen1 -- which is the same -- class of friction the species arrows had before #541. This is the -- replacement: one modal list, filtered as you type, committing through -- Ops.setMove so an unusable / scalar id refuses instead of asserting. -- -- Modal is literal. Kit hit-tests without a z-order, so App.draw raises -- Kit.blockClicks over the chrome and the panel while this is open and lowers -- it only for this overlay; nothing underneath can take the same tap. local Theme = require("Theme") local Ops = require("Ops") local PickerChrome = require("PickerChrome") local PAL = Theme.PAL local Picker = {} local FIELD_ID = "move-picker" function Picker.results(S) local p = S.movePicker return Ops.moveSearch(S, p and p.query or "") end local function commit(S, id) local p = S.movePicker if not p then return false end return Ops.setMove(S, S.editingMon, p.slot, id) end -- Enter commits the top match, which is the whole point of a search field. function Picker.commitFirst(S, Kit) local hits = Picker.results(S) if not hits[1] then return Ops.say(S, "No move matches that") end local ok = commit(S, hits[1]) if ok then Ops.closeMovePicker(S, Kit) end return ok end function Picker.draw(S, Kit, width, height) local p = S.movePicker if not p then return end local s = Kit.scale -- The click that opened the picker is still the frame's click: the -- inspector dispatches earlier in App.draw than this overlay does, so -- without swallowing it the scrim below would read it as a tap outside and -- shut the picker in the same frame it went up. App re-raises the shield -- at the top of the next frame, so leaving it up here is safe. if p.opened then p.opened = nil Kit.blockClicks = true end -- the scrim doubles as the "tap outside to cancel" target; it covers the -- full window so unsafe bands (notch / home indicator) stay dimmed too Theme.col(PAL.bgBot, 0.72) love.graphics.rectangle("fill", 0, 0, width, height) -- Card fills / centres in SafeArea so phones and RGxxx landscapes keep a -- usable list (#917 / #715). local x, y, w, h, pad = PickerChrome.card(Kit, width, height) if Kit.press(0, 0, width, height) and not Kit.hit(x, y, w, h) then Ops.closeMovePicker(S, Kit) return end Kit.card(x, y, w, h) local cx, cy = x + pad, y + pad local inner = w - 2 * pad local closeW = PickerChrome.closeSize(Kit) local captionH = Kit.textHeight("caption") local headH = math.max(captionH, closeW) Kit.caption(cx, cy + (headH - captionH) / 2, ("CHOOSE MOVE %d"):format(p.slot or 1)) if Kit.button(x + w - pad - closeW, cy + (headH - closeW) / 2, closeW, closeW, "x", { font = "small", radius = 7 * s }) then Ops.closeMovePicker(S, Kit) return end cy = cy + headH + 10 * s local fieldH = PickerChrome.fieldH(Kit) p.query = Kit.textfield(FIELD_ID, cx, cy, inner, fieldH, p.query, "type a name, an id, or a type") cy = cy + fieldH + 10 * s local hits = Picker.results(S) local listH, rowH, rowGap, pagerH = PickerChrome.listMetrics(Kit, y, h, pad, cy) local perPage = math.max(1, math.floor((listH + rowGap) / (rowH + rowGap))) p.offset = Theme.clamp(p.offset or 0, 0, math.max(0, #hits - perPage)) -- wheel / touch drag scroll the modal list too; the shield is already -- lowered for this layer, so Kit.scroll works here and only here (#715) p.offset = Kit.scroll(cx, cy, inner, listH, p.offset, #hits, perPage) local mon = S.editingMon local currentId = mon and mon.moves and mon.moves[p.slot] and mon.moves[p.slot].id if #hits == 0 then Kit.emptyBox(cx, cy, inner, listH, "Nothing matches that.") else Kit.pushClip(cx, cy, inner, listH) for i = 1, perPage do local id = hits[p.offset + i] if not id then break end local ry = cy + (i - 1) * (rowH + rowGap) local def = S.data.moves[id] local usable = Ops.moveUsable(S, id) local current = currentId == id if Kit.row(cx, ry, inner, rowH, current, PAL.green, 9 * s) then if commit(S, id) then Ops.closeMovePicker(S, Kit) Kit.popClip() return end end local typ = usable and tostring(def and def.type or "?") or "no data" local pp = usable and ("PP %d"):format(tonumber(def and def.pp) or 0) or "" local tail = pp ~= "" and (typ .. " " .. pp) or typ local tailW = Kit.textWidth("tiny", tail) Kit.text("monoRow", Kit.ellipsize("monoRow", id, inner - tailW - 28 * s), cx + 12 * s, ry + (rowH - Kit.textHeight("monoRow")) / 2, usable and PAL.text or PAL.faint) Kit.textRight("tiny", tail, cx + inner - 10 * s, ry + (rowH - Kit.textHeight("tiny")) / 2, PAL.caption) end Kit.popClip() Kit.scrollbar(cx, cy, inner, listH, p.offset, #hits, perPage) end p.offset = Kit.pager(cx, y + h - pad - pagerH, inner, p.offset, #hits, perPage) end return Picker