-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathmain.lua
257 lines (225 loc) · 7.28 KB
/
main.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
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