| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257 |
- local editors = require'editors'
- local modifiers = {ctrl = false, alt = false, shift = false}
- local mounted_project
- local errhand
- -- PUC Lua 5.1 doesn't support function arguments in xpcall
- local xpacall = function(fn, err, ...)
- local args = {...}
- return xpcall(function() return fn(unpack(args)) end, err)
- end
- -- copy example project to save dir if it doesn't exist
- if not lovr.filesystem.isDirectory('projects') then
- lovr.filesystem.createDirectory('example')
- end
- if not lovr.filesystem.isFile('projects/example/main.lua') then
- print('copying example project into directory', lovr.filesystem.getSaveDirectory())
- local content = lovr.filesystem.read('seed/main.lua')
- lovr.filesystem.createDirectory('projects/example')
- local success = lovr.filesystem.write('projects/example/main.lua', content)
- if not success then print('! could not write to save directory') end
- end
- -- contained callbacks that loaded user project tried to register
- -- init'ed as stubs, overwritten on user project load
- local callbacks = {
- draw = function (pass) end,
- update = function (dt) end,
- keypressed = function (key, scancode, isrepeat) end,
- keyreleased = function (key, scancode) end,
- textinput = function (k) end,
- }
- local function runProject()
- local stored = {
- load = lovr.load,
- draw = lovr.draw,
- update = lovr.update,
- keypressed = lovr.keypressed,
- keyreleased = lovr.keyreleased,
- textinput = lovr.textinput,
- }
- package.loaded['main'] = nil
- -- loading user project will overwrite some of indeck's callbacks
- xpacall(require, errhand, 'main')
- -- reinstate indeck's callbacks store the user project callbacks for event forwarding
- for _, fname in ipairs({'draw', 'update', 'keypressed', 'keyreleased', 'textinput'}) do
- if stored[fname] ~= lovr[fname] then
- lovr[fname], callbacks[fname] = stored[fname], lovr[fname] -- the switch
- end
- end
- if stored.load ~= lovr.load then -- call user's load() once and forget about it
- xpacall(lovr.load, errhand)
- end
- end
- local function pauseProject()
- print('pausing project')
- callbacks = {
- draw = function (pass) end,
- update = function (dt) end,
- keypressed = function (key, scancode, isrepeat) end,
- keyreleased = function (key, scancode) end,
- textinput = function (k) end,
- }
- end
- local function switchToProject(project_dir)
- if mounted_project then
- lovr.filesystem.unmount(mounted_project)
- end
- -- reloading the user project
- local full_path = lovr.filesystem.getSaveDirectory() .. '/projects/' .. project_dir
- print('loading user project', full_path)
- local success = lovr.filesystem.mount(full_path, '', false)
- if not success then
- print('! unsucessful; does project dir exist?')
- return
- end
- mounted_project = full_path
- runProject()
- -- open project's main.lua in active editor
- local path_to_main = 'projects/' .. project_dir .. '/main.lua'
- if lovr.filesystem.isFile(path_to_main) and editors.active then
- editors.active:openFile(path_to_main)
- else
- print(lovr.filesystem.isFile(path_to_main), path_to_main)
- end
- end
- function lovr.load()
- if lovr.headset then lovr.headset.update() end
- lovr.filesystem.unmount(lovr.filesystem.getSource())
- lovr.filesystem.mount('lovr-api', 'help')
- local editor = editors.new(120, 60, switchToProject)
- editor:listFiles('')
- end
- function lovr.update(dt)
- xpacall(callbacks.update, errhand, dt)
- end
- function lovr.draw(pass)
- -- main pass rendering
- for _, editor in ipairs(editors) do
- editor:draw(pass)
- end
- pass:setColor(1,1,1)
- local _, skip = xpacall(callbacks.draw, errhand, pass)
- -- drawing to texture in separate passes per editor
- local passes = {}
- for _, editor in ipairs(editors) do
- local editor_pass = editor:drawToTexture()
- table.insert(passes, editor_pass)
- end
- if not skip then
- table.insert(passes, pass)
- end
- return lovr.graphics.submit(passes)
- end
- function lovr.keypressed(key, scancode, isrepeat)
- if key == 'lctrl' or key == 'rctrl' then
- modifiers.ctrl = true
- return
- elseif key == 'lalt' or key == 'ralt' then
- modifiers.alt = true
- return
- elseif key == 'lshift' or key == 'rshift' then
- modifiers.shift = true
- return
- end
- local combo = string.format('%s%s%s%s',
- modifiers.ctrl and 'ctrl+' or '',
- modifiers.alt and 'alt+' or '',
- modifiers.shift and 'shift+' or '',
- key)
- if combo == 'ctrl+p' then -- spawn new editor
- local editor = editors.new(120, 60, switchToProject)
- editor:listFiles()
- elseif combo =='ctrl+r' then -- restart project
- if editors.active then editors.active:saveFile() end
- runProject()
- elseif combo =='ctrl+shift+r' then
- lovr.event.push('restart')
- elseif combo =='escape' then
- lovr.event.push('quit')
- end
- editors.keypressed(combo)
- xpacall(callbacks.keypressed, errhand, key, scancode, isrepeat, combo)
- end
- function lovr.keyreleased(key, scancode)
- if key == 'lctrl' or key == 'rctrl' then
- modifiers.ctrl = false
- return
- elseif key == 'lalt' or key == 'ralt' then
- modifiers.alt = false
- return
- elseif key == 'lshift' or key == 'rshift' then
- modifiers.shift = false
- return
- end
- xpacall(callbacks.keyreleased, errhand, key, scancode)
- end
- function lovr.textinput(k)
- if k:match('[^\n]') then
- editors.textinput(k)
- end
- xpacall(callbacks.textinput, errhand, k)
- end
- local function wrap(str, limit)
- limit = limit or 60
- local position = 1
- local function check(sp, st, word, fi)
- if fi - position > limit then
- position = st
- return "\n" .. word
- end
- end
- return str:gsub("(%s+)()(%S+)()", check)
- end
- local function showStackTrace(info)
- local prev_active = editors.active
- local traceback_editor = editors.new(60, 30)
- editors.active = prev_active or editors.active
- traceback_editor:setText(wrap(info, traceback_editor.cols))
- traceback_editor.transform:translate(-1,0,-0.4)
- traceback_editor.transform:rotate(-math.rad(40), 0,1,0)
- end
- local function continueRunning()
- if lovr.event then
- lovr.event.pump()
- for name, a, b, c, d in lovr.event.poll() do
- if name == 'restart' then
- local cookie = lovr.restart and lovr.restart()
- return 'restart', cookie
- elseif name == 'quit' and (not lovr.quit or not lovr.quit(a)) then
- return a or 0
- end
- if lovr.handlers[name] then lovr.handlers[name](a, b, c, d) end
- end
- end
- local dt = 0
- if lovr.timer then dt = lovr.timer.step() end
- if lovr.headset then dt = lovr.headset.update() end
- if lovr.update then lovr.update(dt) end
- if lovr.graphics then
- if lovr.headset then
- local pass = lovr.headset.getPass()
- if pass then
- local skip = lovr.draw and lovr.draw(pass)
- if not skip then lovr.graphics.submit(pass) end
- end
- end
- if lovr.system.isWindowOpen() then
- if lovr.mirror then
- local pass = lovr.graphics.getWindowPass()
- local skip = not pass or lovr.mirror(pass)
- if not skip then lovr.graphics.submit(pass) end
- end
- lovr.graphics.present()
- end
- end
- if lovr.headset then lovr.headset.submit() end
- if lovr.math then lovr.math.drain() end
- end
- errhand = function(message, traceback)
- traceback = traceback or debug.traceback('', 3)
- local error_message = message .. '\n' .. traceback
- print('! runtime error')
- print(error_message)
- pauseProject()
- showStackTrace(error_message)
- return continueRunning
- end
|