-- The 3D viewport (FORGE.md milestone 2): a room with a scene3d layer is shown as the scene, -- built from the kinds' 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