-- The timeline (FORGE.md milestone 1): hitbox tracks keyed to disc frames, edited in Forge. The -- cursor is stepped, keys are made at it, one is picked up off the canvas and dragged, one is -- deleted, and the compiled game carries what was drawn. The description names its video, so the -- editor has a frame to show under the cursor. FORGE_LIBRARY = true dofile("Forge/Forge.singe") local font = fontLoad("Singe/FreeSansBold.ttf", 15) local out = singeGetDataPath() local work = out .. "timeline.game" fontSelect(font) fontQuality(FONT_QUALITY_BLENDED) overlaySetResolution(720, 480) local source = assert(io.open("testScripts/author/gunvideo.game", "r")) local copy = assert(io.open(work, "w")) copy:write(source:read("a")) source:close() copy:close() if not forgeBegin(work) then debugPrint("TIMELINE FAIL could not open " .. work) singeQuit() end local frames = 0 local stage = 0 local function key(code, character) forgeKey(character or 0, code.value) end local function step() local track = forgeRoom().tracks[1] if stage == 1 then debugPrint("TIMELINE video loaded: " .. tostring(FORGE.video ~= nil) .. "; track '" .. track.name .. "' has " .. #track.boxes .. " keys") key(SCANCODE.TAB) key(SCANCODE.TAB) key(SCANCODE.TAB) if FORGE.mode ~= "tracks" then debugPrint("TIMELINE FAIL three tabs did not reach the tracks: " .. FORGE.mode) end elseif stage == 2 then -- Step and leap the cursor to frame 170, halfway between the bandit's two keys. for _ = 1, 17 do key(SCANCODE.RIGHTBRACKET) end local box = forgeCursorBox() debugPrint(string.format("TIMELINE cursor at %d, the bandit box is at x=%.0f (halfway from 100 to 400)", FORGE.cursor, box.x)) if math.abs(box.x - 250) > 1 then debugPrint("TIMELINE FAIL interpolation at the cursor") end elseif stage == 3 then -- A key at the cursor takes the interpolated box, and the list stays sorted. key(SCANCODE.K) if #track.boxes == 3 and track.boxes[2].at == 170 and track.boxes[2].x == 250 then debugPrint("TIMELINE a key at 170 went in between the two, at x=250") else debugPrint("TIMELINE FAIL after K the track has " .. #track.boxes .. " keys; second at " .. tostring(track.boxes[2] and track.boxes[2].at)) end elseif stage == 4 then -- Pick the box up off the canvas and drag it, the way a pointer would. local box = forgeCursorBox() forgePress(box.x + 5, box.y + 5) forgeDrag(box.x + 65, box.y + 25) forgeRelease() if track.boxes[2].x == 310 and track.boxes[2].y == 220 then debugPrint("TIMELINE dragged the key to " .. track.boxes[2].x .. "," .. track.boxes[2].y) else debugPrint("TIMELINE FAIL the drag left the key at " .. tostring(track.boxes[2].x) .. "," .. tostring(track.boxes[2].y)) end elseif stage == 5 then -- Type the key's height, then step back a frame: the box between keys follows the new one. key(SCANCODE.RETURN) -- at key(SCANCODE.RETURN) -- x key(SCANCODE.RETURN) -- y key(SCANCODE.RETURN) -- w key(SCANCODE.RETURN) -- h for c in string.gmatch("40", ".") do key(SCANCODE.A, string.byte(c)) end key(SCANCODE.RETURN) key(SCANCODE.ESCAPE) key(SCANCODE.COMMA) local box = forgeCursorBox() debugPrint(string.format("TIMELINE key height typed to %d; at frame %d the box is %.0f tall", track.boxes[2].h, FORGE.cursor, box.h)) elseif stage == 6 then -- Undo the typing and the drag, then delete the key. Undo puts a copy of the description -- in place, so the track is looked up again afterwards. key(SCANCODE.U) key(SCANCODE.U) track = forgeRoom().tracks[1] if track.boxes[2].x ~= 250 then debugPrint("TIMELINE FAIL undo did not bring the key back to x=250: " .. tostring(track.boxes[2].x)) end FORGE.key = 2 key(SCANCODE.DELETE) debugPrint("TIMELINE after two undos and a delete the track has " .. #track.boxes .. " keys") elseif stage == 7 then -- And a new key in a new track reaches the compiled game. key(SCANCODE.N) key(SCANCODE.K) key(SCANCODE.S) local built = forgeBuild(out .. "timeline.singe") local text = assert(io.open(built, "r")):read("a") if text:find('name = "track3"') and text:find("at = " .. FORGE.cursor) then debugPrint("TIMELINE the compiled game carries the new track and its key") else debugPrint("TIMELINE FAIL the new track is missing from the compiled game") end debugPrint("TIMELINE RESULT done") end end function onOverlayUpdate() frames = frames + 1 if frames % 14 == 0 and stage < 8 then stage = stage + 1 step() end forgeDraw(nil, nil) colorForeground(255, 255, 255, 255) fontPrint(210, 8, "timeline, stage " .. stage) if frames == 44 or frames == 72 or frames == 100 then singeScreenshot() end if frames > 130 then singeQuit() end return OVERLAY_UPDATED end