mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-23 05:58:26 +02:00
skins fixerino
This commit is contained in:
+5
-1
@@ -1955,7 +1955,11 @@ function Game2:applyOptions()
|
||||
local options = self.options or {}
|
||||
Music.applyOptions(options)
|
||||
require("src.core.Sound").applyOptions(options)
|
||||
require("src.render.Zoom").applyOptions(options)
|
||||
local Zoom = require("src.render.Zoom")
|
||||
Zoom.applyOptions(options)
|
||||
local caps = require("src.core.Performance").applyOptions(options)
|
||||
Zoom.allowSurvey = caps.survey
|
||||
if not caps.survey and Zoom.offset < 0 then Zoom.offset = 0 end
|
||||
require("src.render.Tilt").applyOptions(options)
|
||||
require("src.render.GbcPalette").applyOptions(options)
|
||||
-- engine/gfx/load_font.asm:29 LoadFrame, off options.lua's wTextboxFrame.
|
||||
|
||||
@@ -86,8 +86,11 @@ function Performance.detect()
|
||||
local cores = processorCount()
|
||||
|
||||
-- PortMaster-style ARM Linux handhelds (e.g. the RG34XXSP the project
|
||||
-- already ships a build for): the weakest target here.
|
||||
if isArm and os ~= "Android" and os ~= "iOS" then
|
||||
-- already ships a build for): the weakest target here. Desktop ARM
|
||||
-- (Apple Silicon "OS X", Windows-on-ARM) is not a handheld — those
|
||||
-- used to resolve AUTO → LOW, which stripped survey zoom-out from
|
||||
-- OPTIONS so the ZOOM row only offered IN.
|
||||
if isArm and os == "Linux" then
|
||||
return "low"
|
||||
end
|
||||
-- Phones and tablets: GBC FX is already force-disabled here (issue #136);
|
||||
|
||||
@@ -12,10 +12,12 @@ function ScreenPosition.normalize(v)
|
||||
end
|
||||
|
||||
function ScreenPosition.label(v)
|
||||
if ScreenPosition.skinActive() then return "SKIN" end
|
||||
return LABELS[ScreenPosition.normalize(v)]
|
||||
end
|
||||
|
||||
function ScreenPosition.cycle(v, dir)
|
||||
if ScreenPosition.skinActive() then return ScreenPosition.normalize(v) end
|
||||
v = ScreenPosition.normalize(v)
|
||||
local modes = ScreenPosition.MODES
|
||||
local cur = 1
|
||||
@@ -44,6 +46,9 @@ end
|
||||
function ScreenPosition.skinActive(w, h)
|
||||
local ok, TouchSkin = pcall(require, "src.core.TouchSkin")
|
||||
if not ok or type(TouchSkin.viewport) ~= "function" then return false end
|
||||
if (not w or not h) and love and love.graphics and love.graphics.getDimensions then
|
||||
w, h = love.graphics.getDimensions()
|
||||
end
|
||||
local okv, x = pcall(TouchSkin.viewport, w, h)
|
||||
return okv and x ~= nil
|
||||
end
|
||||
|
||||
@@ -293,7 +293,9 @@ function TouchControls:applyOptions(opts)
|
||||
-- launcher editor round-trips through config() (#806)
|
||||
self.haptics = TouchControls.normalizeHaptics(opts and opts.haptics)
|
||||
TouchSkin.setOverlayLive(self.active)
|
||||
self:selectSkin(cfg.skin)
|
||||
-- Off means off everywhere: do not leave a hidden selected skin behind to
|
||||
-- influence renderer placement on desktop or with a controller attached.
|
||||
self:selectSkin(cfg.enabled and cfg.skin or nil)
|
||||
self.layouts = cfg.layouts
|
||||
self.layoutW, self.layoutH = nil, nil
|
||||
self.layoutOx, self.layoutOy = nil, nil
|
||||
@@ -335,7 +337,10 @@ function TouchControls:visible()
|
||||
local art = TouchSkin.active ~= nil or self.img ~= nil
|
||||
if self.preview then return art end
|
||||
if self.enabled == false or not art then return false end
|
||||
if TouchSkin.active and TouchSkin.decorativeOnly() then return true end
|
||||
-- A selected skin is also a desktop/TV bezel. Input remains gated in
|
||||
-- touchpressed, but the artwork must not disappear when a controller is
|
||||
-- connected or the platform is not touch-first.
|
||||
if TouchSkin.active then return true end
|
||||
return self.active and not self.controllerHidden
|
||||
end
|
||||
|
||||
@@ -778,12 +783,19 @@ local function drawIcon(img, zone, pressed, alphaMul)
|
||||
zone.cy - img:getHeight() * scale / 2, 0, scale, scale)
|
||||
end
|
||||
|
||||
local function drawStretched(img, x, y, w, h, alpha)
|
||||
local function drawCovered(img, x, y, w, h, alpha)
|
||||
if not img or alpha <= 0 then return end
|
||||
local iw, ih = img:getWidth(), img:getHeight()
|
||||
if iw <= 0 or ih <= 0 then return end
|
||||
-- Cover the assigned box with one uniform scale and crop the excess. The
|
||||
-- old independent X/Y scale made portrait art visibly squash on wide
|
||||
-- displays (and vice versa).
|
||||
local s = math.max(w / iw, h / ih)
|
||||
local dw, dh = iw * s, ih * s
|
||||
love.graphics.setColor(1, 1, 1, math.min(1, alpha))
|
||||
love.graphics.draw(img, x, y, 0, w / iw, h / ih)
|
||||
love.graphics.setScissor(x, y, w, h)
|
||||
love.graphics.draw(img, x + (w - dw) * 0.5, y + (h - dh) * 0.5, 0, s, s)
|
||||
love.graphics.setScissor()
|
||||
end
|
||||
|
||||
function TouchControls:drawSkin(alphaMul)
|
||||
@@ -795,7 +807,7 @@ function TouchControls:drawSkin(alphaMul)
|
||||
|
||||
love.graphics.push("all")
|
||||
love.graphics.origin()
|
||||
drawStretched(page.image, bx, by, bw, bh, opacity)
|
||||
drawCovered(page.image, bx, by, bw, bh, opacity)
|
||||
|
||||
local pressed = {}
|
||||
for _, touch in pairs(self.touches or {}) do
|
||||
@@ -810,7 +822,7 @@ function TouchControls:drawSkin(alphaMul)
|
||||
TouchSkin.controlGeometry(page, ctl, ww, wh, sox, soy)
|
||||
local alpha = opacity
|
||||
if down and not ctl.pressedImage then alpha = opacity * ctl.alphaMod end
|
||||
drawStretched(img, cx - halfW, cy - halfH, halfW * 2, halfH * 2, alpha)
|
||||
drawCovered(img, cx - halfW, cy - halfH, halfW * 2, halfH * 2, alpha)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
+56
-3
@@ -636,6 +636,19 @@ local function applyPixelScale(page)
|
||||
return true
|
||||
end
|
||||
|
||||
-- An overlay image is its own design canvas. Older RetroArch cfg files often
|
||||
-- omit `aspect_ratio`; reading the dimensions here keeps that legacy art and
|
||||
-- all of its normalized controls on the same uniform scale.
|
||||
function TouchSkin.applyImageAspect(page)
|
||||
if not page or page.aspectFromCfg or not page.image
|
||||
or not page.image.getDimensions then return false end
|
||||
local iw, ih = page.image:getDimensions()
|
||||
if not iw or not ih or iw <= 0 or ih <= 0 then return false end
|
||||
page.aspect = iw / ih
|
||||
page.aspectFromImage = true
|
||||
return true
|
||||
end
|
||||
|
||||
function TouchSkin.load(root, id)
|
||||
local cfgPath, format, prefix = findConfig(root)
|
||||
if not cfgPath then return nil, "no skin.lua, .cfg or info.json in " .. root end
|
||||
@@ -665,6 +678,7 @@ function TouchSkin.load(root, id)
|
||||
elseif page.pdfPath then
|
||||
rasterizePdfPage(page, root)
|
||||
end
|
||||
TouchSkin.applyImageAspect(page)
|
||||
if not applyPixelScale(page) then
|
||||
return nil, "could not read " .. tostring(page.imagePath)
|
||||
.. ", which " .. page.name .. " measures its coordinates against"
|
||||
@@ -771,6 +785,28 @@ function TouchSkin.find(id)
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Remove only a user-installed skin. Bundled skins are shipped with the
|
||||
-- game and intentionally have no delete affordance.
|
||||
function TouchSkin.remove(id)
|
||||
local entry = TouchSkin.find(id)
|
||||
if not entry then return nil, "no skin " .. tostring(id) end
|
||||
if entry.source ~= "user" then return nil, "bundled skins cannot be deleted" end
|
||||
if not (love and love.filesystem and love.filesystem.remove) then
|
||||
return nil, "no writable filesystem"
|
||||
end
|
||||
local function removeTree(path)
|
||||
if isDir(path) and love.filesystem.getDirectoryItems then
|
||||
for _, name in ipairs(love.filesystem.getDirectoryItems(path)) do
|
||||
local ok, err = removeTree(path .. "/" .. name)
|
||||
if not ok then return nil, err end
|
||||
end
|
||||
end
|
||||
local ok, err = love.filesystem.remove(path)
|
||||
return ok and true or nil, err
|
||||
end
|
||||
return removeTree(entry.archive or (TouchSkin.USER_ROOT .. "/" .. entry.id))
|
||||
end
|
||||
|
||||
function TouchSkin.assetPaths(skin)
|
||||
local out, seen = {}, {}
|
||||
local function add(rel)
|
||||
@@ -1284,7 +1320,7 @@ function TouchSkin.pageBox(page, w, h, ox, oy)
|
||||
-- full_screen means "relative to the window, not the game viewport".
|
||||
-- When the cfg also names an aspect_ratio, that window is then fitted
|
||||
-- to the overlay's design aspect so buttons do not stretch. #1503
|
||||
local fit = ((not page.fullScreen) or page.aspectFromCfg)
|
||||
local fit = ((not page.fullScreen) or page.aspectFromCfg or page.aspectFromImage)
|
||||
and page.aspect and page.aspect > 0 and h > 0
|
||||
if fit then
|
||||
local displayAspect = w / h
|
||||
@@ -1306,6 +1342,11 @@ function TouchSkin.pageBox(page, w, h, ox, oy)
|
||||
by = oy + extra
|
||||
elseif anchor == "top" then
|
||||
by = oy
|
||||
elseif page.aspect < 1 then
|
||||
-- A portrait bezel with controls is a controller deck. On an
|
||||
-- unusually tall display, pin the deck to the lower edge and leave
|
||||
-- the additional room for the game above it.
|
||||
by = oy + extra
|
||||
else
|
||||
by = oy + extra * 0.5
|
||||
end
|
||||
@@ -1359,8 +1400,10 @@ function TouchSkin.decorativeOnly()
|
||||
end
|
||||
|
||||
function TouchSkin.drawable()
|
||||
if not TouchSkin.active then return false end
|
||||
return TouchSkin.overlayLive or TouchSkin.decorativeOnly()
|
||||
-- A selected skin is a presentation choice, not a mobile-only input mode.
|
||||
-- Its artwork and screen placement therefore belong on every platform;
|
||||
-- `overlayLive` still controls whether touch input is available.
|
||||
return TouchSkin.active ~= nil
|
||||
end
|
||||
|
||||
function TouchSkin.hasViewport()
|
||||
@@ -1410,6 +1453,16 @@ function TouchSkin.pageViewport(page, w, h, ox, oy)
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Centre of the page's screen cutout. The renderer fits the 160x144
|
||||
-- picture into that rect; this helper is for the studio preview.
|
||||
function TouchSkin.screenCenter(w, h, ox, oy, page)
|
||||
page = page or TouchSkin.page()
|
||||
if not page then return nil end
|
||||
local x, y, vw, vh = TouchSkin.pageViewport(page, w, h, ox, oy)
|
||||
if not x then return nil end
|
||||
return x + vw * 0.5, y + vh * 0.5
|
||||
end
|
||||
|
||||
function TouchSkin.viewport(w, h, ox, oy)
|
||||
local page = TouchSkin.page()
|
||||
if not page or not TouchSkin.drawable() then return nil end
|
||||
|
||||
Reference in New Issue
Block a user