123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290 |
- -- Written by Pedro Gimeno.
- -- This work is in the public domain if your jurisdiction allows it.
- -- If not, the author allows anyone to do anything with this work, to the
- -- maximum extent allowed by law.
- if not love.graphics.isActive then
- function love.graphics.isActive()
- return true
- end
- end
- local fbcanvas
- local script
- local started = false
- local corosc -- coroutine for the script
- local huge = math.huge
- local wait = {}
- local peek = {}
- local curEventName
- local curEventData = {0}
- local lg = love.graphics
- local timerTime = huge
- local sleepTime = huge
- local saveCanvas = false
- local function pack_n(...)
- curEventData[1] = select('#', ...)
- for i = 1, curEventData[1] do
- curEventData[i + 1] = (select(i, ...))
- end
- end
- local unpack_n
- do
- local function unpack_count(x, n)
- if n == x[1] + 1 then
- return
- end
- n = n + 1
- return x[n], unpack_count(x, n)
- end
- function unpack_n(a)
- return unpack_count(a, 1)
- end
- end
- local function nullFunc() end
- local function handleEvent(event, ...)
- if event == "update" then
- timerTime = timerTime - ...
- sleepTime = sleepTime - ...
- if sleepTime <= 0 then
- sleepTime = huge
- curEventName = "sleep"
- assert(coroutine.resume(corosc))
- end
- if timerTime <= 0 then
- timerTime = huge
- handleEvent("timer")
- end
- end
- curEventName = event
- pack_n(...)
- if coroutine.status(corosc) == "suspended" then
- return select(2, assert(coroutine.resume(corosc)))
- end
- end
- -- Handlers not in love.handlers
- function love.load(...)
- handleEvent("load", ...)
- -- Hack: love.event.pump() can't work with a canvas active.
- -- The first time it's executed is immediately after this.
- if love.graphics.isActive() then
- saveCanvas = love.graphics.getCanvas()
- love.graphics.setCanvas()
- else
- saveCanvas = nil -- shouldn't be false
- end
- end
- do
- local savePump = love.event.pump
- -- Replace love.event.pump to restore the canvas
- local function afterPump(...)
- if saveCanvas ~= false then
- if love.graphics.isActive() then
- love.graphics.setCanvas(saveCanvas)
- saveCanvas = false -- This distinguishes pump() calls from love.run
- -- from pump() calls from user code.
- end
- -- if we saved it, it means we're in a new frame
- handleEvent("newframe")
- end
- return ...
- end
- function love.event.pump(...)
- return afterPump(savePump(...))
- end
- -- Replace love.graphics.setMode to (re)create the canvas and activate it
- local origSetMode = love.window.setMode
- function love.window.setMode(...)
- if fbcanvas then
- if love.graphics.isActive() then
- love.graphics.setCanvas()
- end
- fbcanvas:release()
- end
- origSetMode(...)
- fbcanvas = love.graphics.newCanvas()
- _G.fbcanvas = fbcanvas
- love.graphics.clear(0, 0, 0, 255)
- love.graphics.setCanvas(fbcanvas)
- end
- local origClear
- function love.update(...)
- handleEvent("update", ...)
- if love.graphics.isActive() then -- love.draw isn't called otherwise
- -- To prevent the internal call to love.graphics.clear from clearing the
- -- framebuffer, we patch it here to do nothing.
- origClear = love.graphics.clear
- love.graphics.clear = nullFunc
- love.graphics.push()
- end
- end
- function love.draw(...)
- love.graphics.clear = origClear
- saveCanvas = love.graphics.getCanvas()
- love.graphics.setCanvas()
- local r,g,b,a = love.graphics.getColor()
- local rgbmode, alphamode = love.graphics.getBlendMode()
- love.graphics.setColor(255, 255, 255, 255)
- love.graphics.setBlendMode("replace", "premultiplied")
- love.graphics.draw(fbcanvas)
- love.graphics.setBlendMode(rgbmode, alphamode)
- love.graphics.setColor(r, g, b, a)
- love.graphics.pop()
- -- Notify about the event. Unfortunately we have to restore the canvas;
- -- otherwise stuff drawn by user code during this event will be lost.
- love.graphics.setCanvas(saveCanvas)
- handleEvent("draw")
- saveCanvas = love.graphics.getCanvas()
- love.graphics.setCanvas() -- for present/pump
- end
- end
- local function waitEvent(event, ...)
- coroutine.yield(...)
- while curEventName ~= event do
- coroutine.yield()
- end
- return unpack_n(curEventData)
- end
- local function peekEvent(event)
- if event == curEventName then
- return true, unpack_n(curEventData)
- end
- end
- local function poll(...)
- coroutine.yield(...)
- end
- local function quit()
- love.event.quit()
- waitEvent("quit")
- coroutine.yield()
- end
- local function getEvent(...)
- poll(...)
- return curEventName, unpack_n(curEventData)
- end
- local function startTimer(time)
- timerTime = time + 0
- end
- local function pause(time, ...)
- if time == nil then
- time = huge
- end
- sleepTime = time + 0
- poll(...)
- repeat
- local ret, k = peekEvent("keypressed")
- if k == "escape" then
- quit()
- end
- if ret then
- break
- end
- if peekEvent("mousepressed") then
- break
- end
- if curEventName =="sleep" then
- break
- end
- poll()
- until false
- sleepTime = huge
- end
- local function sleep(time)
- sleepTime = time + 0
- waitEvent("sleep")
- end
- -- Assign the default love2d handlers
- for k in next, love.handlers do
- love[k] = function(...)
- return handleEvent(k, ...)
- end
- wait[k] = function () return waitEvent(k) end
- peek[k] = function () return peekEvent(k) end
- end
- -- Special events
- wait.load = function () return waitEvent("load") end
- peek.load = function () return peekEvent("load") end
- wait.update = function () return waitEvent("update") end
- peek.update = function () return peekEvent("update") end
- wait.draw = function () return waitEvent("draw") end
- peek.draw = function () return peekEvent("draw") end
- wait.newframe = function () return waitEvent("newframe") end
- peek.newframe = function () return peekEvent("newframe") end
- wait.timer = function () return waitEvent("timer") end
- peek.timer = function () return peekEvent("timer") end
- -- Special functions that aren't events
- wait.event = waitEvent
- peek.event = peekEvent
- -- Set the API globals
- _G.fbcanvas = fbcanvas
- _G.wait = wait
- _G.peek = peek
- _G.sleep = sleep
- _G.pause = pause
- _G.event = getEvent
- _G.poll = poll
- _G.timer = startTimer
- _G.quit = quit
- -- Load the script
- do
- local scriptName = arg[2] or 'mycode.lua'
- script = love.filesystem.load(arg[love.filesystem.isFused() and 1 or 2] or 'mycode.lua')
- if script == nil then
- love.window.showMessageBox("Error: Script not found",
- "Script not found: " .. scriptName, "error", false)
- end
- end
- -- Prepare the coroutine and start it
- corosc = coroutine.create(script)
- assert(coroutine.resume(corosc))
|