mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-20 20:50:21 +02:00
skins and skin studio
This commit is contained in:
+123
-11
@@ -18,6 +18,7 @@
|
||||
|
||||
local SaveData = require("src.core.SaveData")
|
||||
local TouchControls = require("src.core.TouchControls")
|
||||
local TouchSkin = require("src.core.TouchSkin")
|
||||
local PadCursor = require("src.ui.PadCursor")
|
||||
local GamepadMap = require("src.core.GamepadMap")
|
||||
|
||||
@@ -46,6 +47,15 @@ local function roundRect(mode, x, y, w, h, r)
|
||||
love.graphics.rectangle(mode, x, y, w, h, r, r)
|
||||
end
|
||||
|
||||
local function fitText(font, text, maxW)
|
||||
text = tostring(text)
|
||||
if maxW <= 0 or font:getWidth(text) <= maxW then return text end
|
||||
while #text > 1 and font:getWidth(text .. "...") > maxW do
|
||||
text = text:sub(1, #text - 1)
|
||||
end
|
||||
return text .. "..."
|
||||
end
|
||||
|
||||
function Editor.load(opts)
|
||||
opts = opts or {}
|
||||
Editor.onClose = opts.onClose
|
||||
@@ -74,9 +84,52 @@ function Editor.load(opts)
|
||||
TouchControls:applyOptions(applied)
|
||||
TouchControls:setPreview(true)
|
||||
Editor.enabled = TouchControls.enabled ~= false
|
||||
Editor.skins = TouchSkin.list()
|
||||
Editor.exportMsg = nil
|
||||
PadCursor.reset()
|
||||
end
|
||||
|
||||
function Editor.skinIndex()
|
||||
for i, entry in ipairs(Editor.skins or {}) do
|
||||
if entry.id == TouchControls.skinId then return i + 1 end
|
||||
end
|
||||
return 1
|
||||
end
|
||||
|
||||
function Editor.skinLabel()
|
||||
local entry = (Editor.skins or {})[Editor.skinIndex() - 1]
|
||||
if not entry then return "Built-in pad" end
|
||||
local skin = TouchSkin.active
|
||||
local pages = skin and #skin.pages or 1
|
||||
if pages > 1 then return entry.id .. " (" .. pages .. " pages)" end
|
||||
return entry.id
|
||||
end
|
||||
|
||||
function Editor.cycleSkin(dir)
|
||||
local n = #(Editor.skins or {}) + 1
|
||||
local idx = ((Editor.skinIndex() - 1 + (dir or 1)) % n) + 1
|
||||
local entry = Editor.skins[idx - 1]
|
||||
Editor.exportMsg = nil
|
||||
TouchControls:selectSkin(entry and entry.id or nil)
|
||||
TouchControls:ensureImages()
|
||||
end
|
||||
|
||||
function Editor.exportSkin()
|
||||
local skin = TouchSkin.active
|
||||
if not skin then return end
|
||||
local path, missing = TouchSkin.export(skin)
|
||||
if not path then
|
||||
Editor.exportMsg = "Export failed: " .. tostring(missing)
|
||||
return
|
||||
end
|
||||
Editor.exportMsg = "Exported to " .. path .. " in your save folder."
|
||||
if type(missing) == "table" and missing[1] then
|
||||
Editor.exportMsg = Editor.exportMsg
|
||||
.. " " .. #missing .. " image(s) were missing and left out."
|
||||
end
|
||||
Editor.skins = TouchSkin.list()
|
||||
end
|
||||
|
||||
function Editor.unload()
|
||||
TouchControls:setPreview(false)
|
||||
TouchControls:reset()
|
||||
@@ -93,6 +146,7 @@ local function persist()
|
||||
local cfg = TouchControls:config()
|
||||
local block = {
|
||||
enabled = cfg.enabled,
|
||||
skin = cfg.skin,
|
||||
layouts = cfg.layouts,
|
||||
}
|
||||
if Editor.version == "gold" then
|
||||
@@ -158,6 +212,8 @@ function Editor.draw()
|
||||
col(PAL.bgTop, 0.85)
|
||||
love.graphics.circle("fill", ox + ww * 0.5, oy + wh * 0.15, math.max(ww, wh) * 0.55)
|
||||
|
||||
if TouchSkin.active then TouchControls:draw() end
|
||||
|
||||
local pad = 18 * s
|
||||
local barH = 56 * s
|
||||
local btnH = 40 * s
|
||||
@@ -170,16 +226,18 @@ function Editor.draw()
|
||||
love.graphics.setLineWidth(1)
|
||||
love.graphics.line(0, oy + barH + pad, fullW, oy + barH + pad)
|
||||
|
||||
love.graphics.setFont(Editor.fonts.title)
|
||||
col(PAL.white)
|
||||
love.graphics.print("Touch Controls", ox + pad, oy + pad + 4 * s)
|
||||
|
||||
-- Done / Reset
|
||||
local done = { x = ox + ww - pad - btnW, y = oy + pad + (barH - btnH) / 2,
|
||||
w = btnW, h = btnH }
|
||||
local reset = { x = done.x - 10 * s - btnW, y = done.y, w = btnW, h = btnH }
|
||||
Editor.rects.done, Editor.rects.reset = done, reset
|
||||
|
||||
love.graphics.setFont(Editor.fonts.title)
|
||||
col(PAL.white)
|
||||
love.graphics.print(
|
||||
fitText(Editor.fonts.title, "Touch Controls", reset.x - 10 * s - (ox + pad)),
|
||||
ox + pad, oy + pad + 4 * s)
|
||||
|
||||
local function chromeBtn(r, label, fill)
|
||||
col(fill, 0.9)
|
||||
roundRect("fill", r.x, r.y, r.w, r.h, 8 * s)
|
||||
@@ -223,9 +281,48 @@ function Editor.draw()
|
||||
chromeBtn(toggle, on and "Disable" or "Enable",
|
||||
on and PAL.red or PAL.green)
|
||||
|
||||
local skinY = cardY + cardH + 10 * s
|
||||
col(PAL.card, 0.88)
|
||||
roundRect("fill", cardX, skinY, cardW, cardH, 12 * s)
|
||||
col(PAL.stroke, 0.4)
|
||||
roundRect("line", cardX, skinY, cardW, cardH, 12 * s)
|
||||
|
||||
local stepW = 52 * s
|
||||
local skinNext = { x = cardX + cardW - 16 * s - stepW,
|
||||
y = skinY + (cardH - btnH) / 2, w = stepW, h = btnH }
|
||||
local skinPrev = { x = skinNext.x - 10 * s - stepW, y = skinNext.y,
|
||||
w = stepW, h = btnH }
|
||||
Editor.rects.skinNext, Editor.rects.skinPrev = skinNext, skinPrev
|
||||
|
||||
local leftmost = skinPrev.x
|
||||
if TouchSkin.active then
|
||||
local expW = 86 * s
|
||||
local export = { x = skinPrev.x - 10 * s - expW, y = skinPrev.y,
|
||||
w = expW, h = btnH }
|
||||
Editor.rects.export = export
|
||||
leftmost = export.x
|
||||
else
|
||||
Editor.rects.export = nil
|
||||
end
|
||||
|
||||
local skinTextW = leftmost - 10 * s - (cardX + 16 * s)
|
||||
love.graphics.setFont(Editor.fonts.body)
|
||||
col(PAL.label)
|
||||
love.graphics.print("Skin", cardX + 16 * s, skinY + 12 * s)
|
||||
love.graphics.setFont(Editor.fonts.btn)
|
||||
col(TouchControls.skinId and PAL.green or PAL.white)
|
||||
love.graphics.print(fitText(Editor.fonts.btn, Editor.skinLabel(), skinTextW),
|
||||
cardX + 16 * s, skinY + 34 * s)
|
||||
|
||||
chromeBtn(skinPrev, "<", { 60, 70, 110 })
|
||||
chromeBtn(skinNext, ">", { 60, 70, 110 })
|
||||
if Editor.rects.export then
|
||||
chromeBtn(Editor.rects.export, "Export", { 60, 70, 110 })
|
||||
end
|
||||
|
||||
-- size card (#633): -/+ resize every control in the orientation on
|
||||
-- screen; the heading names it so it is plain the other one is untouched
|
||||
local sizeY = cardY + cardH + 10 * s
|
||||
local sizeY = skinY + cardH + 10 * s
|
||||
col(PAL.card, 0.88)
|
||||
roundRect("fill", cardX, sizeY, cardW, cardH, 12 * s)
|
||||
col(PAL.stroke, 0.4)
|
||||
@@ -243,7 +340,6 @@ function Editor.draw()
|
||||
string.format("%d%%", math.floor((bucket.scale or 1) * 100 + 0.5)),
|
||||
cardX + 16 * s, sizeY + 34 * s)
|
||||
|
||||
local stepW = 52 * s
|
||||
local plus = { x = cardX + cardW - 16 * s - stepW,
|
||||
y = sizeY + (cardH - btnH) / 2, w = stepW, h = btnH }
|
||||
local minus = { x = plus.x - 10 * s - stepW, y = plus.y, w = stepW, h = btnH }
|
||||
@@ -254,13 +350,19 @@ function Editor.draw()
|
||||
-- hint
|
||||
love.graphics.setFont(Editor.fonts.body)
|
||||
col(PAL.label, 0.9)
|
||||
local hint = on
|
||||
and "Drag each button to reposition, -/+ to resize. Portrait and landscape are saved separately when you tap Done."
|
||||
or "Controls are hidden in-game. Enable them to show and edit the layout."
|
||||
local hint
|
||||
if Editor.exportMsg then
|
||||
hint = Editor.exportMsg
|
||||
elseif not on then
|
||||
hint = "Controls are hidden in-game. Enable them to show and edit the layout."
|
||||
elseif TouchSkin.active then
|
||||
hint = "This skin owns its own art, hitboxes and screen position, so size and dragging are off. Drop a RetroArch overlay folder or .zip into the skins folder of your save directory to add more."
|
||||
else
|
||||
hint = "Drag each button to reposition, -/+ to resize. Portrait and landscape are saved separately when you tap Done."
|
||||
end
|
||||
love.graphics.printf(hint, ox + pad, sizeY + cardH + 12 * s, ww - 2 * pad, "left")
|
||||
|
||||
-- the overlay itself (preview mode; dimmed when disabled)
|
||||
TouchControls:draw()
|
||||
if not TouchSkin.active then TouchControls:draw() end
|
||||
|
||||
-- highlight the control under drag
|
||||
if Editor.drag then
|
||||
@@ -282,6 +384,9 @@ local function beginDrag(id, x, y)
|
||||
if inside(Editor.rects.done, x, y) then close(); return end
|
||||
if inside(Editor.rects.reset, x, y) then resetLayout(); return end
|
||||
if inside(Editor.rects.toggle, x, y) then toggleEnabled(); return end
|
||||
if inside(Editor.rects.skinPrev, x, y) then Editor.cycleSkin(-1); return end
|
||||
if inside(Editor.rects.skinNext, x, y) then Editor.cycleSkin(1); return end
|
||||
if inside(Editor.rects.export, x, y) then Editor.exportSkin(); return end
|
||||
if inside(Editor.rects.sizeDown, x, y) then
|
||||
TouchControls:nudgeScale(-TouchControls.SCALE_STEP); return
|
||||
end
|
||||
@@ -289,6 +394,7 @@ local function beginDrag(id, x, y)
|
||||
TouchControls:nudgeScale(TouchControls.SCALE_STEP); return
|
||||
end
|
||||
|
||||
if TouchSkin.active then return end
|
||||
local name = TouchControls:hitTest(x, y)
|
||||
if not name then return end
|
||||
local zone = TouchControls:layout()[name]
|
||||
@@ -439,6 +545,12 @@ function Editor.keypressed(key)
|
||||
close()
|
||||
elseif key == "r" then
|
||||
resetLayout()
|
||||
elseif key == "[" then
|
||||
Editor.cycleSkin(-1)
|
||||
elseif key == "]" then
|
||||
Editor.cycleSkin(1)
|
||||
elseif key == "e" then
|
||||
Editor.exportSkin()
|
||||
-- desktop shortcuts for the size -/+ (POKEPORT_TOUCH=1 testing, #633)
|
||||
elseif key == "-" or key == "kp-" then
|
||||
TouchControls:nudgeScale(-TouchControls.SCALE_STEP)
|
||||
|
||||
Reference in New Issue
Block a user