Compare commits

..

8 Commits

Author SHA1 Message Date
DramaticShape 6e9b787e41 Merge pull request #70 from DramaticShape/dev
ios fixes
2026-08-02 21:16:15 -04:00
DramaticShape 399a10a124 Merge pull request #48 from castdrian/ios
fix(ios): pin voxel render target scale & fix shadows
2026-08-02 21:10:55 -04:00
DramaticShape 2ce44586c2 Merge pull request #64 from DramaticShape/pcvr
Added PC VR mode. Enable SteamVR, launch the game, toggle the VR menu option to "ON". Tested over virtual desktop/Quest 3. Standalone VR is not supported (too potato).

| control | does |
| --- | --- |
| left stick | move — grid-walks the diorama, free-walks 1ST |
| A / B (X / Y on the left hand) | A / B |
| either trigger | START |
| left stick click | step the VOXEL angle ladder (same as the "3" key) |
| right stick up / down | *diorama only* — zoom the model |
| right stick left / right | *1ST only* — snap-turn 45° |
| grip squeeze + raise / lower that hand | *diorama only* — drag the table's height |
| head | *1ST and battles* — look; FreeMove walks where you look |
| left hand | *1ST and battles* — the Pokédex: menus, dialogs and the 2D battle screen on its screen |
2026-08-02 13:18:09 -04:00
DramaticShape b0d37cd8e6 Merge pull request #56 from DramaticShape/back-sprite-transparency-fix
v1.5.0
2026-08-02 01:23:13 -04:00
DramaticShape c82598b24c Merge pull request #51 from DramaticShape/back-sprite-transparency-fix
Back sprite transparency fix
2026-08-01 16:44:57 -04:00
Adrian Castro 3cd3fe431d fix(ios): preserve battle hud colors 2026-08-01 14:58:40 +02:00
Adrian Castro acb2eadeb4 fix(ios): use decal shadows on Metal 2026-08-01 14:37:22 +02:00
Adrian Castro 1a69489305 fix(ios): pin voxel render target scale 2026-08-01 13:29:51 +02:00
5 changed files with 41 additions and 6 deletions
+22 -2
View File
@@ -326,6 +326,10 @@ end
-- not nest.
local session = nil
local function isIOS()
return love.system and love.system.getOS and love.system.getOS() == "iOS"
end
local function game()
return require("src.core.Game")
end
@@ -540,11 +544,15 @@ function OverworldBattle.update(dt)
-- reason the scene is: it binds a canvas of its own. After the frost, so
-- the glass is frosted from the world alone and never from the glyphs
-- about to sit on it.
local okHud, up = pcall(OverworldBattle.snapHUDs, session.battle, shot)
local ios = isIOS()
local okHud, up = false, false
if not ios then
okHud, up = pcall(OverworldBattle.snapHUDs, session.battle, shot)
end
session.snapped = (okHud and up) and true or false
-- once per battle, not once per frame: a driver that cannot do this cannot
-- do it sixty times a second either, and the fallback is silent and fine
if not okHud and not session.hudWarned then
if not ios and not okHud and not session.hudWarned then
session.hudWarned = true
V.mod.log:warn("overworld battle HUD snap failed: %s -- the HUDs draw "
.. "in the battle frame this battle", tostring(up))
@@ -1090,6 +1098,7 @@ function OverworldBattle.install()
local innerText = BattleState.drawTextArea
function BattleState:drawTextArea()
if not self.dramaticShapeShot then return innerText(self) end
if isIOS() then return innerText(self) end
local battle = self
if not self.dramaticShapeDark then return withoutBoxFill(battle, innerText) end
BattleHud.flipGlyphs(BattleScene.GB_W, BattleScene.GB_H, function()
@@ -1315,6 +1324,17 @@ function OverworldBattle.drawHudPanels(battle)
local shot = battle.dramaticShapeShot
battle.dramaticShapeDark = nil
if not shot then return end
if isIOS() then
local slide = (battle.introSlide or 0) * 4
local enemy, player = OverworldBattle.hudLive(battle, slide)
local rect = OverworldBattle.HUD_RECT
love.graphics.setColor(1, 1, 1, 0.84)
if enemy then love.graphics.rectangle("fill", rect.enemy[1], rect.enemy[2], rect.enemy[3], rect.enemy[4]) end
if player then love.graphics.rectangle("fill", rect.player[1], rect.player[2], rect.player[3], rect.player[4]) end
love.graphics.setColor(1, 1, 1, 1)
battle.dramaticShapeDark = nil
return
end
if snapped() then
battle.dramaticShapeDark = session and session.dark or nil
return
+9
View File
@@ -0,0 +1,9 @@
local V = ...
local PixelCanvas = {}
function PixelCanvas.new(w, h)
return pcall(love.graphics.newCanvas, w, h, { dpiscale = 1 })
end
return PixelCanvas
+4 -1
View File
@@ -186,7 +186,7 @@ end
local function getCanvas(res)
if canvas == false then return nil end
if canvas and canvasRes == res then return canvas end
local ok, c = pcall(love.graphics.newCanvas, res, res)
local ok, c = V.require("PixelCanvas").new(res, res)
if not (ok and c) then
canvas = false
return nil
@@ -221,6 +221,9 @@ end
-- where the canvas cannot be made -- VoxelScene then keeps the flat decal
-- shadows, which need nothing but a quad.
function ShadowMap.available()
if love.system and love.system.getOS and love.system.getOS() == "iOS" then
return false
end
if not (love.graphics and love.graphics.newCanvas
and love.graphics.setDepthMode) then
return false
+4 -2
View File
@@ -25,6 +25,7 @@
-- failure -- headless, no shader support) apply() hands the canvas back
-- untouched, so every other path is byte-for-byte what it always was.
local V = ...
local TiltShift = {}
TiltShift.level = 0
@@ -85,9 +86,10 @@ end
local function getCanvases(w, h)
if not ping or cw ~= w or ch ~= h then
local ok, a = pcall(love.graphics.newCanvas, w, h)
local PixelCanvas = V.require("PixelCanvas")
local ok, a = PixelCanvas.new(w, h)
if not ok then return nil end
local okB, b = pcall(love.graphics.newCanvas, w, h)
local okB, b = PixelCanvas.new(w, h)
if not okB then return nil end
-- the gaussian's fractional tap offsets need linear filtering
a:setFilter("linear", "linear")
+2 -1
View File
@@ -33,6 +33,7 @@ local WorldCurve = V.require("WorldCurve")
local Sky = V.require("Sky")
local DayNight = V.require("DayNight")
local GlassMask = V.require("GlassMask")
local PixelCanvas = V.require("PixelCanvas")
local Voxel3D = {}
@@ -820,7 +821,7 @@ function Voxel3D.beginScene(w, h, cx, cy, vw, vh, sky, slot)
local name = slot or "world"
local slotHeld = slots[name]
if not (slotHeld and slotHeld.w == w and slotHeld.h == h) then
local ok, c = pcall(love.graphics.newCanvas, w, h)
local ok, c = PixelCanvas.new(w, h)
if not ok then return false end
c:setFilter("nearest", "nearest")
if slotHeld then releaseSlot(slotHeld) end