mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-19 12:15:31 +02:00
importer for skins now w file picker
This commit is contained in:
+73
-33
@@ -2017,6 +2017,23 @@ local function buildSkinsPanel(imp, x, y, w, availH, m)
|
|||||||
local gap = m.gap
|
local gap = m.gap
|
||||||
local cy = y
|
local cy = y
|
||||||
|
|
||||||
|
local title = Strings("Skins/Borders")
|
||||||
|
local bh = m.btnH
|
||||||
|
local importLabel = imp:_skinsImportButtonLabel()
|
||||||
|
local importW = Kit.textWidth("small", importLabel) + math.floor(24 * m.s)
|
||||||
|
if Kit.textWidth("button", title) + importW + math.floor(24 * m.s) > w then
|
||||||
|
importLabel = Strings("Import")
|
||||||
|
importW = Kit.textWidth("small", importLabel) + math.floor(20 * m.s)
|
||||||
|
end
|
||||||
|
local place = Layout.rightCluster(x, w, math.floor(6 * m.s))
|
||||||
|
btn(imp, place(importW), cy, importW, bh, "skins-import", importLabel, {
|
||||||
|
kind = "accent", font = "small",
|
||||||
|
action = function() imp:chooseSkin() end })
|
||||||
|
Kit.text("button", Kit.ellipsize("button", title,
|
||||||
|
math.max(0, w - importW - math.floor(12 * m.s))), x,
|
||||||
|
cy + math.floor((bh - Kit.textHeight("button")) / 2), PAL.heading)
|
||||||
|
cy = cy + bh + math.floor(8 * m.s)
|
||||||
|
|
||||||
if imp._skinNotice then
|
if imp._skinNotice then
|
||||||
cy = cy + Kit.textWrapped("small", imp._skinNotice.text, x, cy, w,
|
cy = cy + Kit.textWrapped("small", imp._skinNotice.text, x, cy, w,
|
||||||
imp._skinNotice.ok and PAL.green or PAL.red, 2) + math.floor(8 * m.s)
|
imp._skinNotice.ok and PAL.green or PAL.red, 2) + math.floor(8 * m.s)
|
||||||
@@ -2075,30 +2092,57 @@ local function buildSkinsPanel(imp, x, y, w, availH, m)
|
|||||||
cy = cy + rowH + math.floor(4 * m.s)
|
cy = cy + rowH + math.floor(4 * m.s)
|
||||||
end
|
end
|
||||||
|
|
||||||
skinRow("skin-none", nil, Strings("Built-in pad"),
|
local entries = { false }
|
||||||
Strings("The default on-screen buttons."), active == nil,
|
for _, entry in ipairs(skins) do entries[#entries + 1] = entry end
|
||||||
imp.onEditTouchControls and function()
|
|
||||||
imp.onEditTouchControls(imp.modScope or "red")
|
|
||||||
end or nil)
|
|
||||||
|
|
||||||
for _, entry in ipairs(skins) do
|
local TouchSkin = require("src.core.TouchSkin")
|
||||||
local bits = {}
|
local hint = Strings(
|
||||||
bits[#bits + 1] = entry.source == "user" and Strings("installed")
|
"You can also drop a skin .zip on this window, or put a folder in %s/ of your save directory. RetroArch overlay .cfg files work as-is.",
|
||||||
or Strings("bundled")
|
TouchSkin.USER_ROOT)
|
||||||
if entry.controls > 0 then
|
local hintH = Kit.wrapHeight("small", hint, w, 3)
|
||||||
bits[#bits + 1] = entry.controls .. " " .. Strings("buttons")
|
local importH = math.floor(10 * m.s) + hintH
|
||||||
|
|
||||||
|
local rowGap = math.floor(4 * m.s)
|
||||||
|
local pagerH = math.max(Kit.tapMin(), math.floor(30 * m.s))
|
||||||
|
local listTop = cy
|
||||||
|
local listH = availH - (cy - y) - importH
|
||||||
|
local perPage = Kit.rowsThatFit(listH, rowH, rowGap, 1, 20)
|
||||||
|
if #entries > perPage then
|
||||||
|
perPage = Kit.rowsThatFit(listH - pagerH - gap, rowH, rowGap, 1, 20)
|
||||||
|
end
|
||||||
|
local first, last, cur, pages = Kit.pageBounds(page(imp, "skins"),
|
||||||
|
#entries, perPage)
|
||||||
|
setPage(imp, "skins", cur)
|
||||||
|
setPage(imp, "skins",
|
||||||
|
Kit.wheelPage(x, listTop, w, listH, cur, #entries, perPage))
|
||||||
|
|
||||||
|
for i = first, last do
|
||||||
|
local entry = entries[i]
|
||||||
|
if not entry then
|
||||||
|
skinRow("skin-none", nil, Strings("Built-in pad"),
|
||||||
|
Strings("The default on-screen buttons."), active == nil,
|
||||||
|
imp.onEditTouchControls and function()
|
||||||
|
imp.onEditTouchControls(imp.modScope or "red")
|
||||||
|
end or nil)
|
||||||
else
|
else
|
||||||
bits[#bits + 1] = Strings("bezel only")
|
local bits = {}
|
||||||
|
bits[#bits + 1] = entry.source == "user" and Strings("installed")
|
||||||
|
or Strings("bundled")
|
||||||
|
if entry.controls > 0 then
|
||||||
|
bits[#bits + 1] = entry.controls .. " " .. Strings("buttons")
|
||||||
|
else
|
||||||
|
bits[#bits + 1] = Strings("bezel only")
|
||||||
|
end
|
||||||
|
if entry.pages > 1 then
|
||||||
|
bits[#bits + 1] = entry.pages .. " " .. Strings("pages")
|
||||||
|
end
|
||||||
|
if entry.screen then bits[#bits + 1] = Strings("screen cutout") end
|
||||||
|
local configure = imp.onOpenSkinStudio and function()
|
||||||
|
imp.onOpenSkinStudio(imp.modScope or "red", entry.id)
|
||||||
|
end or nil
|
||||||
|
skinRow("skin-" .. entry.id, entry.id, entry.id,
|
||||||
|
table.concat(bits, " \194\183 "), active == entry.id, configure)
|
||||||
end
|
end
|
||||||
if entry.pages > 1 then
|
|
||||||
bits[#bits + 1] = entry.pages .. " " .. Strings("pages")
|
|
||||||
end
|
|
||||||
if entry.screen then bits[#bits + 1] = Strings("screen cutout") end
|
|
||||||
local configure = imp.onOpenSkinStudio and function()
|
|
||||||
imp.onOpenSkinStudio(imp.modScope or "red", entry.id)
|
|
||||||
end or nil
|
|
||||||
skinRow("skin-" .. entry.id, entry.id, entry.id,
|
|
||||||
table.concat(bits, " \194\183 "), active == entry.id, configure)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if #skins == 0 then
|
if #skins == 0 then
|
||||||
@@ -2107,18 +2151,14 @@ local function buildSkinsPanel(imp, x, y, w, availH, m)
|
|||||||
cy = cy + math.floor(72 * m.s) + gap
|
cy = cy + math.floor(72 * m.s) + gap
|
||||||
end
|
end
|
||||||
|
|
||||||
cy = cy + math.floor(6 * m.s)
|
if pages > 1 then
|
||||||
local TouchSkin = require("src.core.TouchSkin")
|
setPage(imp, "skins",
|
||||||
Kit.caption(x, cy, Strings("IMPORT"))
|
Kit.pager(x, cy, w, cur, #entries, perPage, "skins"))
|
||||||
cy = cy + Kit.textHeight("small") + math.floor(6 * m.s)
|
cy = cy + pagerH + gap
|
||||||
local boxH = math.floor(76 * m.s)
|
end
|
||||||
Kit.card(x, cy, w, boxH, "muted")
|
|
||||||
Kit.textWrapped("small", Strings(
|
cy = cy + math.floor(10 * m.s)
|
||||||
"Drop a skin .zip on this window to install it, or put a folder in the skins folder of your save directory. RetroArch overlay .cfg files work as-is."),
|
Kit.textWrapped("small", hint, x, cy, w, PAL.muted, 3)
|
||||||
x + math.floor(14 * m.s), cy + math.floor(12 * m.s),
|
|
||||||
w - math.floor(28 * m.s), PAL.muted, 3)
|
|
||||||
Kit.text("small", TouchSkin.USER_ROOT .. "/", x + math.floor(14 * m.s),
|
|
||||||
cy + boxH - Kit.textHeight("small") - math.floor(10 * m.s), PAL.faint)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local function buildFindPanel(imp, x, y, w, availH, m)
|
local function buildFindPanel(imp, x, y, w, availH, m)
|
||||||
|
|||||||
+116
-5
@@ -1089,6 +1089,39 @@ local function chooseZip()
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function chooseSkinZip()
|
||||||
|
local prompt = shellSafe(Strings("Choose a skin .zip"))
|
||||||
|
local platform = love.system.getOS()
|
||||||
|
if platform == "OS X" then
|
||||||
|
return commandOutput(
|
||||||
|
([[osascript -e 'POSIX path of (choose file with prompt "%s" of type {"zip"})' 2>/dev/null]])
|
||||||
|
:format(prompt))
|
||||||
|
elseif platform == "Windows" then
|
||||||
|
local script = table.concat({
|
||||||
|
"Add-Type -AssemblyName System.Windows.Forms;",
|
||||||
|
"$d=New-Object System.Windows.Forms.OpenFileDialog;",
|
||||||
|
"$d.Title='" .. prompt .. "';",
|
||||||
|
"$d.Filter='Skin archive (*.zip)|*.zip|All files (*.*)|*.*';",
|
||||||
|
"if($d.ShowDialog() -eq 'OK'){",
|
||||||
|
"$n=[IO.Path]::GetFileName($d.FileName) -replace '[^\\x20-\\x7E]','_';",
|
||||||
|
"$t=Join-Path $env:TEMP $n;",
|
||||||
|
"Copy-Item -LiteralPath $d.FileName -Destination $t -Force;",
|
||||||
|
"[Console]::OutputEncoding=[Text.Encoding]::UTF8;",
|
||||||
|
"[Console]::Write($t)}",
|
||||||
|
})
|
||||||
|
return commandOutput(
|
||||||
|
'powershell -NoProfile -STA -Command "' .. script .. '"')
|
||||||
|
elseif platform == "Linux" then
|
||||||
|
local path = commandOutput(
|
||||||
|
([[zenity --file-selection --title="%s" --file-filter="Skin archive | *.zip" 2>/dev/null]])
|
||||||
|
:format(prompt))
|
||||||
|
if path then return path end
|
||||||
|
return commandOutput(
|
||||||
|
[[kdialog --getopenfilename "$HOME" "*.zip|Skin archive" 2>/dev/null]])
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
-- Open a native picker for a raw .sav battery save (mirrors chooseZip's per-OS
|
-- Open a native picker for a raw .sav battery save (mirrors chooseZip's per-OS
|
||||||
-- dialogs). Returns the chosen absolute path or nil. Android uses
|
-- dialogs). Returns the chosen absolute path or nil. Android uses
|
||||||
-- love.system.pickFile("sav") instead -- see RomImporter:chooseSaveImport.
|
-- love.system.pickFile("sav") instead -- see RomImporter:chooseSaveImport.
|
||||||
@@ -1478,7 +1511,12 @@ function RomImporter:focus(f)
|
|||||||
self.pickerPendingModId = nil
|
self.pickerPendingModId = nil
|
||||||
self.pickerPendingImportId = nil
|
self.pickerPendingImportId = nil
|
||||||
elseif pickError:find("picked_mod", 1, true) then
|
elseif pickError:find("picked_mod", 1, true) then
|
||||||
self.modNotice = { ok = false, text = text }
|
if self.pickerPendingKind == "skin" then
|
||||||
|
self.pickerPendingKind = nil
|
||||||
|
self._skinNotice = { ok = false, text = text }
|
||||||
|
else
|
||||||
|
self.modNotice = { ok = false, text = text }
|
||||||
|
end
|
||||||
elseif pickError:find("picked_save", 1, true) then
|
elseif pickError:find("picked_save", 1, true) then
|
||||||
local version = self.androidPendingVersion or self:_savedropTarget()
|
local version = self.androidPendingVersion or self:_savedropTarget()
|
||||||
self.androidPendingVersion = nil
|
self.androidPendingVersion = nil
|
||||||
@@ -1504,6 +1542,13 @@ function RomImporter:focus(f)
|
|||||||
end
|
end
|
||||||
local modName = findPendingMod(false, self.pickSkip)
|
local modName = findPendingMod(false, self.pickSkip)
|
||||||
if modName then
|
if modName then
|
||||||
|
if self.pickerPendingKind == "skin" then
|
||||||
|
self.pickerPendingKind = nil
|
||||||
|
self:_installSkinZip(modName)
|
||||||
|
consumePick(self, modName, "picked_mod.zip",
|
||||||
|
self._skinNotice and self._skinNotice.ok)
|
||||||
|
return
|
||||||
|
end
|
||||||
self:_installMod(modName)
|
self:_installMod(modName)
|
||||||
consumePick(self, modName, "picked_mod.zip",
|
consumePick(self, modName, "picked_mod.zip",
|
||||||
self.modNotice and self.modNotice.ok)
|
self.modNotice and self.modNotice.ok)
|
||||||
@@ -2498,6 +2543,11 @@ function RomImporter:update(dt)
|
|||||||
if Platform.isUWP() and self.modNotice and self.modNotice.ok then
|
if Platform.isUWP() and self.modNotice and self.modNotice.ok then
|
||||||
os.remove(path)
|
os.remove(path)
|
||||||
end
|
end
|
||||||
|
elseif kind == "skin" then
|
||||||
|
self:_installSkinZip(path)
|
||||||
|
if Platform.isUWP() and self._skinNotice and self._skinNotice.ok then
|
||||||
|
os.remove(path)
|
||||||
|
end
|
||||||
elseif kind == "sav" then
|
elseif kind == "sav" then
|
||||||
local target = version or self:_savedropTarget()
|
local target = version or self:_savedropTarget()
|
||||||
self:_importSave(target, path)
|
self:_importSave(target, path)
|
||||||
@@ -2520,6 +2570,8 @@ function RomImporter:update(dt)
|
|||||||
self.pickerPendingModId, self.pickerPendingImportId = nil, nil
|
self.pickerPendingModId, self.pickerPendingImportId = nil, nil
|
||||||
elseif kind == "mod" then
|
elseif kind == "mod" then
|
||||||
self.modNotice = { ok = false, text = errorText }
|
self.modNotice = { ok = false, text = errorText }
|
||||||
|
elseif kind == "skin" then
|
||||||
|
self._skinNotice = { ok = false, text = errorText }
|
||||||
elseif kind == "sav" then
|
elseif kind == "sav" then
|
||||||
self.saveNotice[version] = { ok = false, text = errorText }
|
self.saveNotice[version] = { ok = false, text = errorText }
|
||||||
else
|
else
|
||||||
@@ -3047,13 +3099,27 @@ function RomImporter:_useSkin(id)
|
|||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
function RomImporter:_installSkinZip(file)
|
function RomImporter:_installSkinZip(source)
|
||||||
|
if self.workState == "working" then return end
|
||||||
|
self.tab = "skins"
|
||||||
local TouchSkin = require("src.core.TouchSkin")
|
local TouchSkin = require("src.core.TouchSkin")
|
||||||
local name = file:getFilename() or ""
|
local name, data, readError
|
||||||
local data, readError = readDroppedFile(file)
|
if type(source) == "string" then
|
||||||
|
name = source
|
||||||
|
if not source:match("^/") and not source:match("^%a:[/\\]")
|
||||||
|
and not source:match("^[Ss][Dd][Mm][Cc]:") then
|
||||||
|
data = love.filesystem.read(source)
|
||||||
|
end
|
||||||
|
if not data then data, readError = readExternalPath(source) end
|
||||||
|
if not data then data = love.filesystem.read(source) end
|
||||||
|
else
|
||||||
|
name = source:getFilename() or ""
|
||||||
|
data, readError = readDroppedFile(source)
|
||||||
|
end
|
||||||
if not data then
|
if not data then
|
||||||
self._skinNotice = { ok = false,
|
self._skinNotice = { ok = false,
|
||||||
text = "Could not read the dropped file: " .. tostring(readError) }
|
text = "Could not read the skin archive: "
|
||||||
|
.. tostring(readError or name) }
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local id, err = TouchSkin.installArchive(name, data)
|
local id, err = TouchSkin.installArchive(name, data)
|
||||||
@@ -3065,6 +3131,51 @@ function RomImporter:_installSkinZip(file)
|
|||||||
self._skinNotice = { ok = true, text = "Imported " .. id }
|
self._skinNotice = { ok = true, text = "Imported " .. id }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function RomImporter:_skinsImportButtonLabel()
|
||||||
|
if self.isNX then return Strings("Scan again") end
|
||||||
|
return Strings("Import skin .zip")
|
||||||
|
end
|
||||||
|
|
||||||
|
function RomImporter:chooseSkin()
|
||||||
|
if self.workState == "working" then return end
|
||||||
|
if self.isNX then
|
||||||
|
local found = #self:_ensureSkins(true)
|
||||||
|
self._skinNotice = { ok = true, text = Strings(
|
||||||
|
"%d skins found. Copy a skin .zip into %s/ over MTP, then scan again.",
|
||||||
|
found, require("src.core.TouchSkin").USER_ROOT) }
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if self.nativePicker and love.system.getPickedFile then
|
||||||
|
self.pickerPendingKind = "skin"
|
||||||
|
if not pickFile("mod") then
|
||||||
|
self.pickerPendingKind = nil
|
||||||
|
self._skinNotice = { ok = false, text = "Could not open the file picker." }
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if self.android then
|
||||||
|
local name = findPendingMod(true, self.pickSkip)
|
||||||
|
if name then
|
||||||
|
self:_installSkinZip(name)
|
||||||
|
consumePick(self, name, "picked_mod.zip",
|
||||||
|
self._skinNotice and self._skinNotice.ok)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
self.pickerPendingKind = "skin"
|
||||||
|
if not pickFile("mod") then
|
||||||
|
self.pickerPendingKind = nil
|
||||||
|
self._skinNotice = { ok = false,
|
||||||
|
text = "Could not open the file picker. Copy a skin .zip via USB." }
|
||||||
|
else
|
||||||
|
self.pickPending = true
|
||||||
|
self.pickTimer = 0
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local path = chooseSkinZip()
|
||||||
|
if path then self:_installSkinZip(path) end
|
||||||
|
end
|
||||||
|
|
||||||
function RomImporter:_toggleFindSearchFocus()
|
function RomImporter:_toggleFindSearchFocus()
|
||||||
self._findSearchFocus = not self._findSearchFocus
|
self._findSearchFocus = not self._findSearchFocus
|
||||||
if self._findSearchFocus then
|
if self._findSearchFocus then
|
||||||
|
|||||||
@@ -94,6 +94,21 @@ return function(game)
|
|||||||
imp:_useSkin(nil)
|
imp:_useSkin(nil)
|
||||||
shot("skins_tab_imported.png")
|
shot("skins_tab_imported.png")
|
||||||
|
|
||||||
|
-- import button: the picker hands back an absolute host path, not a drop
|
||||||
|
local picked = dir .. "/picked_skin.zip"
|
||||||
|
local pf = io.open(picked, "wb")
|
||||||
|
pf:write(raw)
|
||||||
|
pf:close()
|
||||||
|
imp:_installSkinZip(picked)
|
||||||
|
U.log("path import notice:", imp._skinNotice.text)
|
||||||
|
U.log("picked_skin found:", tostring(TouchSkin.find("picked_skin") ~= nil))
|
||||||
|
U.log("import label:", imp:_skinsImportButtonLabel())
|
||||||
|
shot("skins_tab_path_imported.png")
|
||||||
|
|
||||||
|
love.window.setMode(520, 760, { resizable = true, highdpi = true })
|
||||||
|
U.wait(3)
|
||||||
|
shot("skins_tab_narrow.png")
|
||||||
|
|
||||||
U.log("done")
|
U.log("done")
|
||||||
love.event.quit()
|
love.event.quit()
|
||||||
while true do coroutine.yield() end
|
while true do coroutine.yield() end
|
||||||
|
|||||||
@@ -0,0 +1,118 @@
|
|||||||
|
-- Skins tab Import button: picker plumbing + path/drop install (SKINIMP-01..05).
|
||||||
|
package.path = "./?.lua;./?/init.lua;" .. package.path
|
||||||
|
if not _G.love then _G.love = require("tests.love_stub") end
|
||||||
|
|
||||||
|
local S = require("tests.harness").suite("skin import picker")
|
||||||
|
local eq = S.eq
|
||||||
|
local check = S.check
|
||||||
|
|
||||||
|
local RomImporter = require("src.import.RomImporter")
|
||||||
|
local TouchSkin = require("src.core.TouchSkin")
|
||||||
|
|
||||||
|
love.system = love.system or {}
|
||||||
|
local saved = {
|
||||||
|
pickFile = love.system.pickFile,
|
||||||
|
getPickedFile = love.system.getPickedFile,
|
||||||
|
getPickError = love.system.getPickError,
|
||||||
|
installArchive = TouchSkin.installArchive,
|
||||||
|
}
|
||||||
|
|
||||||
|
local installed
|
||||||
|
TouchSkin.installArchive = function(name, data)
|
||||||
|
installed = { name = name, data = data }
|
||||||
|
if not data or data == "" then return nil, "empty archive" end
|
||||||
|
return (name:match("([^/\\]+)$") or name):gsub("%.[Zz][Ii][Pp]$", "")
|
||||||
|
end
|
||||||
|
|
||||||
|
local function freshImporter(fields)
|
||||||
|
local imp = RomImporter.new(function() end, { launcher = true })
|
||||||
|
imp.tab = "skins"
|
||||||
|
imp._skins = {}
|
||||||
|
imp._ensureSkins = function(self) return self._skins end
|
||||||
|
for k, v in pairs(fields or {}) do imp[k] = v end
|
||||||
|
return imp
|
||||||
|
end
|
||||||
|
|
||||||
|
-- SKINIMP-01: a picker path installs as a skin, not a mod
|
||||||
|
installed = nil
|
||||||
|
local imp = freshImporter()
|
||||||
|
local tmp = os.tmpname() .. ".zip"
|
||||||
|
local f = assert(io.open(tmp, "wb"))
|
||||||
|
f:write("PK\3\4skin-archive")
|
||||||
|
f:close()
|
||||||
|
imp:_installSkinZip(tmp)
|
||||||
|
os.remove(tmp)
|
||||||
|
check(installed ~= nil, "an absolute picker path reaches TouchSkin.installArchive")
|
||||||
|
eq(installed.data, "PK\3\4skin-archive", "the picked file's bytes are installed")
|
||||||
|
check(imp._skinNotice and imp._skinNotice.ok, "a good pick reports success")
|
||||||
|
|
||||||
|
-- SKINIMP-02: a dropped file still installs, and both paths land on the tab
|
||||||
|
installed = nil
|
||||||
|
imp = freshImporter({ tab = "red" })
|
||||||
|
imp:filedropped({
|
||||||
|
getFilename = function() return "/tmp/dropped_skin.zip" end,
|
||||||
|
getSize = function() return 4 end,
|
||||||
|
open = function() return true end,
|
||||||
|
read = function() return "PKZP" end,
|
||||||
|
close = function() return true end,
|
||||||
|
})
|
||||||
|
check(installed == nil, "a zip dropped off the skins tab is still a mod")
|
||||||
|
installed = nil
|
||||||
|
imp = freshImporter()
|
||||||
|
imp:filedropped({
|
||||||
|
getFilename = function() return "/tmp/dropped_skin.zip" end,
|
||||||
|
getSize = function() return 4 end,
|
||||||
|
open = function() return true end,
|
||||||
|
read = function() return "PKZP" end,
|
||||||
|
close = function() return true end,
|
||||||
|
})
|
||||||
|
eq(installed and installed.name, "/tmp/dropped_skin.zip",
|
||||||
|
"a zip dropped on the skins tab installs as a skin")
|
||||||
|
eq(imp.tab, "skins", "the skin install stays on the skins tab")
|
||||||
|
|
||||||
|
-- SKINIMP-03: the mobile bridge borrows the mod picker kind
|
||||||
|
local requestedKind
|
||||||
|
love.system.pickFile = function(kind)
|
||||||
|
requestedKind = kind
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
love.system.getPickedFile = function() return nil end
|
||||||
|
love.system.getPickError = function() return nil end
|
||||||
|
imp = freshImporter({ nativePicker = true })
|
||||||
|
imp:chooseSkin()
|
||||||
|
eq(requestedKind, "mod", "chooseSkin opens the .zip picker")
|
||||||
|
eq(imp.pickerPendingKind, "skin", "the pending pick is routed to the skins tab")
|
||||||
|
|
||||||
|
-- SKINIMP-04: the picked file comes back through update() as a skin
|
||||||
|
installed = nil
|
||||||
|
love.system.getPickedFile = function()
|
||||||
|
love.system.getPickedFile = function() return nil end
|
||||||
|
return "/picked/from_bridge.zip"
|
||||||
|
end
|
||||||
|
imp._installSkinZip = function(self, source)
|
||||||
|
self.installedSource = source
|
||||||
|
self._skinNotice = { ok = true, text = "Imported from_bridge" }
|
||||||
|
end
|
||||||
|
imp:update(0)
|
||||||
|
eq(imp.installedSource, "/picked/from_bridge.zip",
|
||||||
|
"update() hands the picked path to the skin installer")
|
||||||
|
eq(imp.pickerPendingKind, nil, "the pending kind clears once consumed")
|
||||||
|
|
||||||
|
-- SKINIMP-05: a picker error lands on the skins notice, not the mods one
|
||||||
|
love.system.getPickedFile = function() return nil end
|
||||||
|
love.system.getPickError = function()
|
||||||
|
love.system.getPickError = function() return nil end
|
||||||
|
return "picker refused"
|
||||||
|
end
|
||||||
|
imp = freshImporter({ nativePicker = true, pickerPendingKind = "skin" })
|
||||||
|
imp:update(0)
|
||||||
|
check(imp._skinNotice and not imp._skinNotice.ok,
|
||||||
|
"a failed skin pick reports on the skins tab")
|
||||||
|
eq(imp.modNotice, nil, "a failed skin pick leaves the mods notice alone")
|
||||||
|
|
||||||
|
love.system.pickFile = saved.pickFile
|
||||||
|
love.system.getPickedFile = saved.getPickedFile
|
||||||
|
love.system.getPickError = saved.getPickError
|
||||||
|
TouchSkin.installArchive = saved.installArchive
|
||||||
|
|
||||||
|
S.finish()
|
||||||
Reference in New Issue
Block a user