· 5 years ago · Mar 15, 2020, 04:52 PM
1local modelsPath = shell.dir().."/models/"
2local curFile = nil
3local curData = nil
4
5-- Holds common editor functions
6local editor = {
7 vX = 0,
8 vY = 0,
9 layer = 0,
10 slot = 1
11}
12
13local function clear(xPos, yPos)
14 term.setCursorPos(xPos or 1,yPos or 1)
15 term.setBackgroundColor(colors.black)
16 term.setTextColor(colors.white)
17 term.clear()
18end
19
20local function drawTopBar(sInfo)
21 clear()
22 term.setBackgroundColor(colors.blue)
23 term.clearLine()
24 term.write("xLayer Editor v1.0 | "..sInfo)
25 term.setBackgroundColor(colors.black)
26 term.setCursorPos(1,3)
27end
28
29local function openBlueprint()
30 local h = fs.open(curFile or error("Open : Invalid operation : file name is nil"), "r")
31 curData = textutils.unserialize(h.readAll())
32 h.close()
33 if not curData then
34 printError("Could not open blueprint, unrecognized contents.")
35 sleep(2)
36 end
37end
38
39local function saveBlueprint()
40 local h = fs.open(curFile or error("Save : Invalid operation : file name is nil"), "w")
41 h.write(textutils.serialize(curData))
42 h.close()
43end
44
45local function newFilePrompt()
46 drawTopBar("New File")
47 print("Choose a file name.")
48 write("#> ")
49 local fName = read(nil, nil, function(i)
50 return fs.complete(i, "") end,
51 modelsPath
52 )
53
54 -- Basic checks
55 if fs.isDir(fName) then
56 printError("That's a directory. Please choose a file name.")
57 sleep(2)
58 return
59 end
60 if fs.exists(fName) then
61 printError("This file already exists.")
62 sleep(1.5)
63 return
64 end
65
66 print("\nChoose blueprint size.")
67 write("#> ")
68 local nSize = tonumber(read(nil, nil,
69 function(i)
70 local ix, iy = term.getCursorPos()
71 if tonumber(i) and i % 1 == 0 then
72 print("\n")
73 term.clearLine()
74 print("Size : "..i.."x"..i.." ("..(i*i).." cells)")
75 else
76 print("\n")
77 term.clearLine()
78 print("Input must be an integer (non-decimal) number.")
79 end
80 term.setCursorPos(ix,iy)
81 end
82 ))
83
84 print()
85 term.clearLine()
86
87 if not nSize then
88 printError("Blueprint size must be a integer number.")
89 sleep(2)
90 return
91 end
92
93 -- Create a file
94 if string.sub(fName, -4) ~= ".xlf" then
95 fName = fName..".xlf"
96 end
97 curFile = fName
98 -- Create table skeleton
99 curData = {{}}
100 for r=1, nSize do
101 table.insert(curData[1], {})
102 for c=1, nSize do
103 table.insert(curData[1][r], "0")
104 end
105 end
106
107 saveBlueprint()
108end
109
110local function openFilePrompt()
111 drawTopBar("Open Existing File")
112 print("Choose a file name.")
113
114 write("#> ")
115 local fName = read(nil, nil, function(i)
116 return fs.complete(i, "") end,
117 modelsPath
118 )
119
120 -- Basic checks
121 if fs.isDir(fName) then
122 printError("That's a directory. Please choose a file name.")
123 sleep(2)
124 return
125 end
126 if not fs.exists(fName) then
127 printError("This file does not exist.")
128 sleep(1.5)
129 return
130 end
131
132 -- Open file
133 curFile = fName
134 openBlueprint()
135end
136
137-- Draws the blueprint area
138editor.drawBpArea = function()
139 if not curData[editor.layer] then
140 print("No layer selected.")
141 print("Use the ctrl menu to add or select a layer.")
142 return
143 end
144
145 local mX = #curData[editor.layer] > 45 and 45 + editor.vX or #curData[editor.layer] + editor.vX
146 local mY = #curData[editor.layer] > 13 and 13 + editor.vY or #curData[editor.layer] + editor.vY
147
148 -- Draw frame
149 term.setTextColor(colors.red)
150 for i=3, mY - editor.vY + 3 do
151 term.setCursorPos(2, i)
152 for j=editor.vX + 3, mX + 3 do
153 if i == 3 and j % 5 == 0 then
154 term.write("|")
155 else
156 term.write(string.char(127))
157 end
158 end
159 end
160 term.setTextColor(colors.white)
161
162 -- Draw actual data
163 for r=editor.vY + 1, mY do
164 term.setCursorPos(3, r - editor.vY + 3)
165 for c=editor.vX + 1, mX do
166 term.write(curData[editor.layer][r][c])
167 end
168 end
169end
170
171editor.drawBottomArea = function()
172 local _,h = term.getSize()
173
174 term.setBackgroundColor(colors.gray)
175 term.setTextColor(colors.lightGray)
176 term.setCursorPos(1, h-1)
177 term.clearLine()
178 term.write("[+/-] Change slot | [pgUp/pgDwn] Change layer")
179
180 term.setCursorPos(1,h)
181 term.clearLine()
182 term.write("Press ctrl for menu | Layer "..editor.layer.."/"..#curData.." | Slot "..string.format("%X", editor.slot))
183 term.setBackgroundColor(colors.black)
184 term.setTextColor(colors.white)
185end
186
187editor.menu = function()
188 drawTopBar("Editing File...")
189 editor.drawBpArea()
190
191 local _,h = term.getSize()
192 term.setCursorPos(1,h-2)
193 print("[1] Save | [3] New Layer | [5] Layer ++")
194 print("[2] Exit | [4] Delete Layer | [6] Layer --")
195 term.write("#> ")
196 local opt = tonumber(read())
197
198 if not opt then return end
199
200 if opt < 1 or opt > 6 then
201 term.setCursorPos(1,h)
202 term.clearLine()
203 term.write("Invalid option '"..opt.."'.")
204 sleep(1)
205 return
206 end
207
208 if opt == 1 then
209 saveBlueprint()
210 elseif opt == 2 then
211 return true
212 elseif opt == 3 then
213 table.insert(curData, {})
214 for i=1, #curData[1] do
215 table.insert(curData[#curData], {})
216 for j=1, #curData[1] do
217 table.insert(curData[#curData][i], "0")
218 end
219 end
220 elseif opt == 4 and editor.layer > 0 and #curData > 1 then
221 table.remove(curData, editor.layer)
222 elseif opt == 5 and editor.layer < #curData then
223 editor.layer = editor.layer + 1
224 elseif opt == 6 and editor.layer > 1 then
225 editor.layer = editor.layer - 1
226 end
227end
228
229-- Draws everything
230editor.draw = function()
231 drawTopBar("Editing File...")
232
233 editor.drawBpArea()
234 editor.drawBottomArea()
235end
236
237-- Enter editing mode
238editor.start = function()
239 editor.layer = 0
240 editor.draw()
241
242 while true do
243 local e, a1, a2, a3 = os.pullEvent()
244
245 if e == "key" then
246 if a1 == keys.left and editor.vX > 0 then
247 editor.vX = editor.vX - 1
248 editor.draw()
249 end
250 if a1 == keys.right and editor.vX < #curData[editor.layer] - 45 then
251 editor.vX = editor.vX + 1
252 editor.draw()
253 end
254 if a1 == keys.up and editor.vY > 0 then
255 editor.vY = editor.vY - 1
256 editor.draw()
257 end
258 if a1 == keys.down and editor.vY < #curData[editor.layer] - 13 then
259 editor.vY = editor.vY + 1
260 editor.draw()
261 end
262 if a1 == keys.pageUp and editor.layer < #curData then
263 editor.layer = editor.layer + 1
264 editor.draw()
265 end
266 if a1 == keys.pageDown and editor.layer > 1 then
267 editor.layer = editor.layer - 1
268 editor.draw()
269 end
270 if a1 == keys.numPadAdd then
271 editor.slot = (editor.slot + 1) % 16
272 editor.draw()
273 end
274 if a1 == keys.numPadSubtract then
275 editor.slot = (editor.slot - 1) % 16
276 editor.draw()
277 end
278 if a1 == keys.leftCtrl then
279 local res = editor.menu()
280 if res then break end
281 editor.draw()
282 end
283 end
284
285 if e == "mouse_click" and a1 == 1 then
286 local cx = a2 - (editor.vX + 2)
287 local cy = a3 - (editor.vY + 3)
288
289 if curData[editor.layer] then
290 if curData[editor.layer][cy] ~= nil and curData[editor.layer][cy][cx] then
291 curData[editor.layer][cy][cx] = string.format("%X", editor.slot)
292 editor.draw()
293 end
294 end
295 end
296 end
297end
298
299-- Main program
300local bExit = false
301
302while not bExit do
303 drawTopBar("Main Menu")
304 print("[1] New File")
305 print("[2] Open File")
306 print("[3] Exit\n")
307 write("#> ")
308
309 local choice = tonumber(read())
310 if choice == 1 then
311 newFilePrompt()
312 editor.start()
313 elseif choice == 2 then
314 openFilePrompt()
315 editor.start()
316 elseif choice == 3 then
317 clear()
318 break
319 else
320 printError("Invalid option.")
321 sleep(1)
322 end
323end