singe/testScripts/scene63.singe
2026-09-14 22:32:53 -05:00

139 lines
4.2 KiB
Text

-- The 3D viewport (FORGE.md milestone 2): a room with a scene3d layer is shown as the scene,
-- built from the types' looks under an orbiting editor camera. Entities are picked and dragged
-- by where they project, the camera orbits by key, and a rail point is put where the camera
-- stands.
FORGE_LIBRARY = true
dofile("Forge/Forge.singe")
local font = fontLoad("Singe/FreeSansBold.ttf", 15)
local out = singeGetDataPath()
local work = out .. "rail.game"
fontSelect(font)
fontQuality(FONT_QUALITY_BLENDED)
overlaySetResolution(720, 480)
local source = assert(io.open("testScripts/author/railshooter.game", "r"))
local copy = assert(io.open(work, "w"))
copy:write(source:read("a"))
source:close()
copy:close()
if not forgeBegin(work) then
debugPrint("VIEW FAIL could not open " .. work)
singeQuit()
end
local frames = 0
local stage = 0
local wall = nil
local function key(code, character)
forgeKey(character or 0, code.value)
end
local function step()
local room = forgeRoom()
if stage == 1 then
local built = 0
for _ in pairs(FORGE.scene and FORGE.scene.nodes or {}) do
built = built + 1
end
debugPrint("VIEW the preview holds " .. built .. " of " .. #room.entities .. " entities")
if built ~= #room.entities then
debugPrint("VIEW FAIL the preview is incomplete")
end
elseif stage == 2 then
-- Pick the left wall by where it projects.
for index, entry in ipairs(room.entities) do
if entry.id == "wallL" then
wall = index
end
end
local entry = room.entities[wall]
local sx, sy, _, inFront = sceneProject(entry.x, entry.y, entry.z)
forgePress(sx, sy)
if FORGE.selected == wall then
debugPrint("VIEW picked " .. entry.id .. " at its projection " .. math.floor(sx) .. "," .. math.floor(sy))
else
debugPrint("VIEW FAIL the press at the wall selected " .. tostring(FORGE.selected) .. " (in front " .. tostring(inFront) .. ")")
end
-- Drag it a little to the right on screen and let go: it moves across the floor.
forgeDrag(sx + 40, sy)
forgeRelease()
if (entry.y == 1.5) and ((entry.x ~= -6) or (entry.z ~= -12)) then
debugPrint(string.format("VIEW dragged it to %.1f, %.1f, %.1f, staying on its floor", entry.x, entry.y, entry.z))
else
debugPrint(string.format("VIEW FAIL the drag left it at %.1f, %.1f, %.1f", entry.x, entry.y, entry.z))
end
elseif stage == 3 then
local yaw = FORGE.scene.yaw
local far = FORGE.scene.distance
key(SCANCODE.J)
key(SCANCODE.J)
key(SCANCODE.I)
debugPrint(string.format("VIEW orbit: yaw %d to %d, distance %.1f to %.1f", yaw, FORGE.scene.yaw, far, FORGE.scene.distance))
elseif stage == 4 then
-- A rail point where the camera stands, at a typed time.
key(SCANCODE.TAB)
key(SCANCODE.TAB)
key(SCANCODE.TAB)
local track = room.tracks[1]
local count = #track.points
key(SCANCODE.K)
key(SCANCODE.RETURN) -- at
for c in string.gmatch("20", ".") do
key(SCANCODE.A, string.byte(c))
end
key(SCANCODE.RETURN) -- commits at, moves on to x
key(SCANCODE.ESCAPE)
track = forgeRoom().tracks[1]
local last = track.points[#track.points]
if (#track.points == count + 1) and (last.at == 20) and (last.look ~= nil) then
debugPrint(string.format("VIEW a rail point went in at %d: %.1f, %.1f, %.1f looking at %s", last.at, last.x, last.y, last.z, tostring(last.look[1] or last.look.x)))
else
debugPrint("VIEW FAIL the rail has " .. #track.points .. " points; the last is at " .. tostring(last and last.at))
end
elseif stage == 5 then
key(SCANCODE.S)
local reloaded = authorLoad(work)
local built = forgeBuild(out .. "rail.singe")
local text = assert(io.open(built, "r")):read("a")
debugPrint("VIEW saved: the rail has " .. #reloaded.rooms[1].tracks[1].points .. " points on disc; compiled carries at = 20: " .. tostring(text:find("at = 20") ~= nil))
debugPrint("VIEW RESULT done")
end
end
function onOverlayUpdate()
frames = frames + 1
if frames % 14 == 0 and stage < 6 then
stage = stage + 1
step()
end
forgeDraw(nil, nil)
colorForeground(255, 255, 255, 255)
fontPrint(210, 8, "3D viewport, stage " .. stage)
if frames == 20 or frames == 50 or frames == 80 then
singeScreenshot()
end
if frames > 100 then
singeQuit()
end
return OVERLAY_UPDATED
end