Advertisement
CometWolf

Turtle Architect V1.3

Jan 8th, 2014
2,090
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 132.47 KB | None | 0 0
  1. --[[
  2. --------------------------------------------------------------------------------------------------------------
  3. |                                              Turtle Architect                                              |
  4. |                                                by CometWolf                                                |
  5. --------------------------------------------------------------------------------------------------------------
  6.  
  7. --------------------------------------------------------------------------------------------------------------
  8. |                                                Program tables                                              |
  9. --------------------------------------------------------------------------------------------------------------
  10. --]]
  11. local env = {  --new enviroment
  12.   ["tFile"] = {
  13.   --file path table
  14.     ["program"] = shell.getRunningProgram(), --must be done prior to changing enviroment
  15.     ["cTurtle"] = "/cTurtle", --cTurtle API,downloaded automatically if missing
  16.     ["ongoingBuild"] = "/ArchitectOngoingBuild" --Info file for the currently ongoing build
  17.   }
  18. }
  19. setmetatable(env, {__index = getfenv()}) --inherit global
  20. setfenv(1, env)    --set it
  21. local tArg = {...} --store program arguments
  22.  
  23. local tTimer = {
  24. --timer settings table, change timers here
  25.   ["rednet"] = 60, --time before sending location info over rednet when in need of materials
  26.   ["enderChest"] = 120 --time between ender chest checks when out of materials
  27. }
  28.  
  29. local tColors = {
  30. --color table, change color settings here
  31.   ["menuBar"] = colors.blue, --top menu bar
  32.   ["menuButton"] = colors.lightBlue, -- menu button on the left
  33.   ["menuText"] = colors.white, -- text on the menu button
  34.   ["menuDropDownPri"] = colors.lightBlue, --primary drop down menu color
  35.   ["menuDropDownSec"] = colors.cyan, --secondary drop down menu color
  36.   ["contextMenuText"] = colors.white, -- right click menu text
  37.   ["contextMenuPri"] = colors.lightBlue, --right click menu primary
  38.   ["contextMenuSec"] = colors.cyan, -- right click menu secondary
  39.   ["box"] = colors.blue, -- info, choice and input boxes color
  40.   ["boxBorder"] = colors.lightBlue, -- box borders
  41.   ["boxText"] = colors.yellow, --box text
  42.   ["boxButton"] = colors.cyan, -- box buttons
  43.   ["boxButtonText"] = colors.yellow, -- buttons text in boxes
  44.   ["inputText"] = colors.white, --input text
  45.   ["inputBackground"] = colors.black, --input field
  46.   ["infoText"] = colors.white, --box text
  47.   ["gridBorder"] = colors.blue, --gridMode bottm and right borde ron screen
  48.   ["gridBorderText"] = colors.white, -- grideMode border text
  49.   ["gridBackground"] = colors.white, -- grid mode background
  50.   ["gridBackgroundText"] = colors.blue, -- grid markers
  51.   ["backgroundLayer"] = colors.gray, -- background layer
  52.   ["selector"] = colors.lightGray, -- selector tool selection color
  53.   ["builtMark"] = colors.white, -- built render mode mark
  54. }
  55.  
  56. --numerical color table for rendering canvas colors
  57. tColorNums = {
  58.   a = 2 ^ 1,
  59.   b = 2 ^ 2,
  60.   c = 2 ^ 3,
  61.   d = 2 ^ 4,
  62.   e = 2 ^ 5,
  63.   f = 2 ^ 6,
  64.   g = 2 ^ 7,
  65.   h = 2 ^ 8,
  66.   i = 2 ^ 9,
  67.   j = 2 ^ 10,
  68.   k = 2 ^ 11,
  69.   l = 2 ^ 12,
  70.   m = 2 ^ 13,
  71.   n = 2 ^ 14,
  72.   o = 2 ^ 15,
  73. }
  74. tColorNumsRev = {}
  75. for k,v in pairs(tColorNums) do
  76.   tColorNumsRev[v] = k
  77. end
  78. for k,v in pairs(tColorNums) do
  79.   tColorNums[k:upper()] = v
  80. end
  81. tColorNums[" "] = 1 --blank
  82. tColorNumsRev[1] = " "
  83. tColorNums.x = 1 --break
  84. tColorNums.X = 1
  85. local built = "%u" --uppercase pattern, marks built blocks
  86. local unbuilt = "%l" --lowercase pattern, marks unbuilt blocks
  87.  
  88. -- color strings indexed by color values, reverse of the colors table pretty much
  89. local tColorString = {}
  90.  
  91. --contains what slots to use for what colors when building
  92. local tColorSlots = {}
  93.  
  94. --somewhat relevant bits of strings, for simplified changes
  95. local tText = {
  96.   ["menuButton"] = "Menu"
  97. }
  98.  
  99. --blueprint table, holds current blueprint
  100. local tBlueprint = {}
  101.  
  102. --contains ongoing build data
  103. local tOngoing = {}
  104.  
  105. --contains build starting point
  106. local tOrigin = {}
  107.  
  108. tPaste = {
  109. --pastebin codes and functions
  110.   ["program"] = "Kt4D8uyE",
  111.   ["cTurtle"] = "JRPN0P8x",
  112.   ["key"] = "0ec2eb25b6166c0c27a394ae118ad829", -- pastbin dev key, cc default
  113.   ["get"] = function(code,file,blueprint) --downloads files pastebin
  114.     local response = http.get("http://pastebin.com/raw.php?i="..code)
  115.     local paste, tRetBlueprint,tRetColorSlots,tRetOrigin
  116.     if response then
  117.       --sucesss
  118.       if blueprint then
  119.         if response.readLine() == "Blueprint file for CometWolf's Turtle Architect. Pastebin: "..tPaste.program then
  120.           tRetBlueprint = {}
  121.           local line = response.readLine()
  122.           while line:match"Layer %d+" do
  123.             local layer = tonumber(line:match"%d+")
  124.             tRetBlueprint[layer] = {}
  125.             line = response.readLine()
  126.             while line:match"X%d+" do
  127.               local x = tonumber(line:match"X(%d+)")
  128.               tRetBlueprint[layer][x] = {}
  129.               for block in line:gmatch" (%d+)" do
  130.                 table.insert(tRetBlueprint[layer][x],tonumber(block))
  131.               end
  132.               line = response.readLine()
  133.             end
  134.           end
  135.           if line:match"Color slots table:" then
  136.             tRetColors = textutils.unserialize(response.readLine())
  137.             line = response.readLine() or ""
  138.           end
  139.           if line:match"Build origin data:" then
  140.             tRetOrigin = textutils.unserialize(response.readLine())
  141.           end
  142.           return tRetBlueprint, tRetColors or {},tRetOrigin or {}
  143.         else
  144.           return false
  145.         end
  146.       end
  147.       paste = response.readAll()
  148.       response.close()
  149.       if file then
  150.         --save to file
  151.         local file = fs.open(file,"w")
  152.         file.writeLine(paste)
  153.         file.close()
  154.         return true
  155.       end
  156.       --save to variable
  157.       return paste
  158.     else
  159.       --failure
  160.       return false
  161.     end
  162.   end,
  163. --note that the put function is just a slightly modified version of the original.
  164.   ["put"] = function(file,name) --uploads files to pastebin
  165.     local upload
  166.     name = name or "Untitled"
  167.     if type(file) == "string" then
  168.       --local file
  169.       file = fs.open("file","r")
  170.       upload = file.readAll()
  171.       file.close()
  172.     elseif type(file) == "table" then
  173.       --current blueprint
  174.       upload = "Blueprint file for CometWolf's Turtle Architect. Pastebin: "..tPaste.program
  175.       for layer=1,#tBlueprint do
  176.         upload = upload.."\nLayer "..layer.." :"
  177.         for x=1,#tBlueprint[layer] do
  178.           local line = "X"..x..string.rep(" ",#string.format(#tBlueprint[layer])-#string.format(x))..": "
  179.           for z=1,#tBlueprint[layer][x] do
  180.             local block = tBlueprint[layer][x][z] or "0"
  181.             line = line..block..string.rep(" ",3-#string.format(block))
  182.           end
  183.           upload = upload.."\n"..line
  184.         end
  185.       end
  186.       if tColorSlots then
  187.         upload = upload.."\nColor slots table:\n"..textutils.serialize(tColorSlots)
  188.       end
  189.       if tOrigin then
  190.         upload = upload.."\nBuild origin data:\n"..textutils.serialize(tOrigin)
  191.       end
  192.     end
  193.     local key = tPaste.key
  194.     local response = http.post(
  195.         "http://pastebin.com/api/api_post.php",
  196.         "api_option=paste&"..
  197.         "api_dev_key="..key.."&"..
  198.         "api_paste_format=text&"..
  199.         "api_paste_name="..textutils.urlEncode(name).."&"..
  200.         "api_paste_code="..textutils.urlEncode(upload)
  201.     )
  202.     if response then
  203.       --sucess
  204.       local sResponse = response.readAll()
  205.       response.close()      
  206.       local sCode = string.match( sResponse, "[^/]+$" )
  207.       return sResponse, sCode
  208.     else
  209.       --failure
  210.       return false
  211.     end
  212.   end
  213. }
  214.  
  215. local tTool = {
  216.   --tool table, tool info for the respective mouse buttons
  217.   [1] = {  --left mouse tool
  218.     ["tool"] = "Brush",
  219.     ["size"] = 1,
  220.     ["color"] = "o" --black
  221.   },
  222.   [2] = {  --right mouse tool
  223.     ["tool"] = "Brush",
  224.     ["size"] = 1,
  225.     ["color"] = " " --white
  226.   },
  227.   ["overwrite"] = true, --overwrite mode
  228.   ["built"] = false, --built mode
  229.   ["selector"] = { --selector tool info
  230.     ["enabled"] = false --wether to render the selection or not
  231.   },
  232.   ["circle"] = {
  233.     [1] = {},
  234.     [2] = {}
  235.   }
  236. }
  237.  
  238. local tScroll = {
  239.   --scroll table, holds current veiwing area info
  240.   ["x"] = {  --left right
  241.     ["value"] = 0
  242.   },
  243.   ["y"] = {  --up down
  244.     ["value"] = 0
  245.   },
  246.   ["layer"] = 1,  --layer
  247. }
  248.  
  249. local tTerm = {}
  250. --terminal sizes table, to make my life easier
  251. tTerm.x,tTerm.y = term.getSize()
  252. tTerm.xMid = math.ceil(tTerm.x/2)
  253. tTerm.yMid = math.ceil(tTerm.y/2)
  254. tTerm.xCanvas = tTerm.x --total x veiwing area
  255. tTerm.zCanvas = tTerm.y-1 --total y veiwing area, accounts for the menubar on top
  256. tTerm.grid = false --grid mode
  257. tTerm.built = false -- built render mode
  258. tTerm.isColor = term.isColor() --color support
  259. tMon = "" -- monitor table
  260.  
  261. local paintutils = {
  262. -- custom paintutils, to simplify monitor usage
  263.   ["drawPixel"] = function(xPos,yPos,color,monitor)
  264.     if monitor then
  265.     --monitors
  266.       for i=1,#tMon do
  267.         if color then
  268.           tMon[i]["setBackgroundColor"](color)
  269.         end
  270.         tMon[i]["setCursorPos"](xPos,yPos)
  271.         tMon[i]["write"](" ")
  272.       end
  273.     else
  274.     --terminal
  275.       if color then
  276.         term.setBackgroundColor(color)
  277.       end
  278.       term.setCursorPos(xPos,yPos)
  279.       term.write" "
  280.     end
  281.   end,
  282.   ["drawLine"] = function(startX,startY,endX,endY,color,monitor)
  283.     if color then
  284.       term.setBackgroundColor(color)
  285.       if monitor then
  286.         for i=1,#tMon do
  287.           tMon[i]["setBackgroundColor"](color)
  288.         end
  289.       end
  290.     end
  291.     startX = math.floor(startX)
  292.     startY = math.floor(startY)
  293.     endX = math.floor(endX)
  294.     endY = math.floor(endY)
  295.     if startX == endX and startY == endY then
  296.       paintutils.drawPixel(startX,startY,monitor)
  297.       return
  298.     end
  299.     local minX = math.min(startX,endX)
  300.     if minX == startX then
  301.       minY = startY
  302.       maxX = endX
  303.       maxY = endY
  304.     else
  305.       minY = endY
  306.       maxX = startX
  307.       maxY = startY
  308.     end
  309.     local xDiff = maxX-minX
  310.     local yDiff = maxY-minY
  311.     if xDiff > math.abs(yDiff) then
  312.       local y = minY
  313.       local dy = yDiff/xDiff
  314.       for x=minX,maxX do
  315.         paintutils.drawPixel(x,math.floor(y+0.5),monitor)
  316.         y = y+dy
  317.       end
  318.     else
  319.       local x = minX
  320.       local dx = xDiff/yDiff
  321.       if maxY >= minY then
  322.         for y=minY,maxY do
  323.           paintutils.drawPixel(math.floor(x+0.5),y,monitor)
  324.           x = x+dx
  325.         end
  326.       else
  327.         for y=minY,maxY,-1 do
  328.           paintutils.drawPixel(math.floor(x+0.5),y,monitor)
  329.           x = x-dx
  330.         end
  331.       end
  332.     end
  333.   end
  334. }
  335.  
  336. tInput = {
  337.   --table for input fields
  338.   ["cursX"] = 1, --cursor location
  339.   ["enabled"] = false, --input enabled
  340.   ["render"] = function(num,startX,endX,lineY,fieldName,text)
  341.     --creates/clears and renders the given (num) inputfield, from (startX) to (endX) at (lineY)
  342.     --optionally puts (fieldName) infront of the input area and renders (text) on the input area
  343.       fieldName = string.format(fieldName or "")
  344.     tInput[num] = {
  345.       ["scrollX"] = 0,
  346.       ["startX"] = startX+#fieldName,
  347.       ["endX"] = endX,
  348.       ["lineY"] = lineY,
  349.       ["fieldName"] = fieldName or "",
  350.       ["text"] = string.format(text or "")
  351.     }
  352.     paintutils.drawLine(startX,lineY,endX,lineY,tColors.inputBackground)
  353.     term.setTextColor(tColors.inputText)
  354.     term.setBackgroundColor(tColors.inputBackground)
  355.     term.setCursorPos(startX,lineY)
  356.     term.write(tInput[num]["fieldName"]..tInput[num]["text"]:sub(tInput[num]["scrollX"],endX+tInput[num]["scrollX"]))
  357.     tInput.cursX = #tInput[num]["text"]+1
  358.     term.setCursorPos(tInput[num]["startX"]+tInput.cursX,lineY)
  359.   end,
  360.   ["reRender"] = function(num)
  361.     --updates the given (num) input field
  362.     if not tInput[num] then
  363.       error("ERROR: input field "..num.." does not exist!")
  364.     end
  365.     paintutils.drawLine(tInput[num]["startX"],tInput[num]["lineY"],tInput[num]["endX"],tInput[num]["lineY"],tColors.inputBackground)
  366.     term.setTextColor(tColors.inputText)
  367.     term.setBackgroundColor(tColors.inputBackground)
  368.     term.setCursorPos(tInput[num]["startX"],tInput[num]["lineY"])
  369.     term.write(tInput[num]["text"]:sub(tInput[num]["scrollX"],tInput[num]["endX"]-tInput[num]["startX"]+tInput[num]["scrollX"]))
  370.     term.setCursorPos(tInput[num]["startX"]+tInput.cursX-1,tInput[num]["lineY"])
  371.   end
  372. }
  373.  
  374. tBox = {
  375.   --box table, holds functions and values related to pop-up boxes
  376.   ["render"] = function(startX,endX,message,buttons,textInputs,acceptedInput,...)
  377.     --creates a pop-up box in the given (startX) (endX) area
  378.     --Height is calculated automatically
  379.     --message is rendered below the borders
  380.     --then renders the given (button) of buttons,
  381.     --if (textInputs) is given then textFields will be added aswell
  382.     --which only accepts (acceptedInput), use "." to accept anything
  383.     --every value afterwards is the name of each inputField, this will appear infront of the input area
  384.     local tArgs = {...}
  385.     local tFieldName = {}
  386.     local tFieldText = {}
  387.     buttons = buttons or 1
  388.     textInputs = textInputs or 0
  389.     acceptedInput = acceptedInput or "."
  390.     for i=1+buttons,buttons+textInputs do
  391.       tFieldName[i-buttons] = tArgs[i] or ""
  392.       tFieldText[i-buttons] = tArgs[i+textInputs] or ""
  393.     end
  394.     local tLines = {}
  395.     local lineLength = (endX-startX-1)
  396.     if type(message) == "table" then
  397.       --converts message to string if it's a table
  398.       message = table.concat(message,"|")
  399.     end
  400.     while #message > 0 do
  401.       local line = message:sub(1,lineLength)
  402.       local newLine = string.find(line.."","|") --check for new line character
  403.       if newLine then
  404.         line = line:sub(1,newLine-1)
  405.         message = message:sub(#line+2,#message)
  406.       elseif #line == lineLength then
  407.         local endSpace = string.find(line.."","%s$") or string.find(line.."","%s%S-$") or lineLength
  408.         line = line:sub(1,endSpace)
  409.         message = message:sub(#line+1,#message)
  410.       else
  411.         message = ""
  412.       end
  413.       table.insert(tLines,line)
  414.     end
  415.     local totY = #tLines+2+textInputs
  416.     tBox.startX = startX
  417.     tBox.endX = endX
  418.     tBox.startY = tTerm.yMid-math.floor(totY/2)
  419.     tBox.endY = tBox.startY+totY
  420.     tBox.midX = math.ceil((endX-startX)/2)+startX
  421.     for i=tBox.startY+1,tBox.endY-1 do
  422.       --draws box
  423.       paintutils.drawLine(startX+1,i,endX-1,i,tColors.box)
  424.     end
  425.     --draws border
  426.     paintutils.drawLine(startX,tBox.startY,endX,tBox.startY,tColors.boxBorder)
  427.     paintutils.drawLine(endX,tBox.startY,endX,tBox.endY,tColors.boxBorder)
  428.     paintutils.drawLine(endX,tBox.endY,startX,tBox.endY,tColors.boxBorder)
  429.     paintutils.drawLine(startX,tBox.endY,startX,tBox.startY,tColors.boxBorder)
  430.     --renders message
  431.     term.setBackgroundColor(tColors.box)
  432.     term.setTextColor(tColors.boxText)
  433.     for i=1,#tLines do
  434.       term.setCursorPos(math.ceil(tBox.midX-(#tLines[i]/2)),tBox.startY+i)
  435.       term.write(tLines[i])
  436.     end
  437.     --draws button
  438.     tBox.button = {}
  439.     local totalButtonSpace = 0
  440.     for i=1,buttons do
  441.       tBox.button[i] = {}
  442.       tBox.button[i]["name"] = tArgs[i] or "Ok"
  443.       tBox.button[i]["size"] = #tBox.button[i]["name"]+2
  444.       totalButtonSpace = totalButtonSpace+tBox.button[i]["size"]+2
  445.     end
  446.     local nextButton = tBox.midX-math.ceil(totalButtonSpace/2)+tBox.startX
  447.     for i=1,#tBox.button do
  448.       tBox.button[i]["startX"] = nextButton
  449.       tBox.button[i]["endX"] = nextButton+tBox.button[i]["size"]
  450.       tBox.button[i]["lineY"] = tBox.endY-1
  451.       term.setCursorPos(tBox.button[i]["startX"],tBox.button[i]["lineY"])
  452.       term.setBackgroundColor(tColors.boxButton)
  453.       term.setTextColor(tColors.boxButtonText)
  454.       term.write(" "..tBox.button[i]["name"].." ")  --add spaces for appearances
  455.       nextButton = nextButton+tBox.button[i]["size"]+2
  456.     end
  457.     --renders input boxes
  458.     if textInputs > 0 then
  459.       for i=1,#tInput do
  460.         tInput[i] = nil
  461.       end
  462.       for i=textInputs,1,-1 do
  463.         tInput[i] = {}
  464.         tInput.render(i,3,tTerm.x-2,tBox.endY-2-textInputs+i,tFieldName[i] or "",tFieldText[i] or "")
  465.       end
  466.       term.setCursorBlink(true)
  467.       tInput.enabled = 1
  468.       tInput.cursX = #tInput[tInput.enabled]["text"]+1
  469.       term.setCursorPos(tInput[1]["startX"]+tInput.cursX-1,tInput[1]["lineY"])
  470.     else
  471.       tInput.enabled = false
  472.     end
  473.     --user events
  474.     while true do
  475.       local tEvent = {os.pullEvent()}
  476.       if tEvent[1] == "monitor_touch" then
  477.         tEvent[1] = "mouse_click"
  478.         tEvent[2] = 1
  479.       end
  480.       if tEvent[1] == "mouse_click" then
  481.         --clicks
  482.         if tEvent[2] == 1 then
  483.         --left clicks
  484.           local input = tInput[tEvent[4]-(tBox.endY-#tInput-2)] or false --clicked input bar
  485.           local button = tBox.click(tEvent[3],tEvent[4]) or false
  486.           if input and tInput.enabled
  487.           and tEvent[3] <= input["endX"] and tEvent[3] >= input["startX"] --x
  488.           and #input["text"] > 0 then --text
  489.             --input bar click
  490.             tInput.enabled = tEvent[4]-(tBox.endY-#tInput-2)
  491.             tInput.cursX = math.min(tEvent[3]-input["startX"],#input["text"]-input.scrollX)
  492.             term.setCursorPos(input["startX"]+tInput.cursX,tEvent[4])
  493.           elseif button then
  494.             if tInput.enabled then
  495.               local tRet = {button}
  496.               for i=1,#tInput do
  497.                 if string.match(tInput[i]["text"],"^%d+$") then
  498.                   tInput[i]["text"] = tonumber(tInput[i]["text"])
  499.                 end
  500.                 tRet[#tRet+1] = tInput[i]["text"]
  501.               end
  502.               tInput.enabled = false
  503.               tMenuBar.render()
  504.               term.setCursorBlink(false)
  505.               return unpack(tRet)
  506.             else
  507.               tMenuBar.render()
  508.               term.setCursorBlink(false)
  509.               return button
  510.             end
  511.           end
  512.         end
  513.       elseif tEvent[1] == "char" then
  514.         --letter input
  515.         if tEvent[2] == "%"
  516.         or tEvent[2] == "["
  517.         or not tEvent[2]:match(acceptedInput) then
  518.           --skip to avoid crashes
  519.         elseif tInput.enabled then
  520.           tInput[tInput.enabled]["text"] = string.format(tInput[tInput.enabled]["text"]:sub(1,tInput.cursX+tInput[tInput.enabled]["scrollX"]-1)..tEvent[2]..tInput[tInput.enabled]["text"]:sub(tInput.cursX+tInput[tInput.enabled]["scrollX"],#tInput[tInput.enabled]["text"]))
  521.           tInput.cursX = tInput.cursX+1
  522.           if tInput.cursX > tInput[tInput.enabled]["endX"]-tInput[tInput.enabled]["startX"] then
  523.             tInput[tInput.enabled]["scrollX"] = tInput[tInput.enabled]["scrollX"]+1
  524.             tInput.cursX = tInput[tInput.enabled]["endX"]-tInput[tInput.enabled]["startX"]
  525.           end
  526.           tInput.reRender(tInput.enabled)
  527.         end
  528.       elseif tEvent[1] == "key" then
  529.       --special keyes input
  530.         local key = tEvent[2]
  531.         if tInput.enabled then
  532.           --input box
  533.           if key == 14
  534.           and (tInput.cursX > 1 or tInput[tInput.enabled]["scrollX"] > 0) then
  535.             --backspace
  536.             tInput[tInput.enabled]["text"] = string.format(tInput[tInput.enabled]["text"]:sub(1,tInput.cursX+tInput[tInput.enabled]["scrollX"]-2)..tInput[tInput.enabled]["text"]:sub(tInput.cursX+tInput[tInput.enabled]["scrollX"],#tInput[tInput.enabled]["text"]))
  537.             if tInput[tInput.enabled]["scrollX"] > 0 then
  538.               tInput[tInput.enabled]["scrollX"] = tInput[tInput.enabled]["scrollX"]-1
  539.             else
  540.               tInput.cursX = tInput.cursX-1
  541.             end
  542.           elseif key == 205 then --right arrow
  543.             tInput.cursX = tInput.cursX+1
  544.           elseif key == 203 then --left arrow
  545.             tInput.cursX = tInput.cursX-1
  546.           elseif key == 200 then --up arrow
  547.             tInput.enabled = math.max(1,tInput.enabled-1)
  548.           elseif key == 208 then --down arrow
  549.             tInput.enabled = math.min(#tInput,tInput.enabled+1)
  550.           elseif key == 211 then --delete
  551.             if #tInput[tInput.enabled]["text"] <= 1 and tInput.cursX == 1 then
  552.               tInput[tInput.enabled]["text"] = ""
  553.             else
  554.               tInput[tInput.enabled]["text"] = string.format(tInput[tInput.enabled]["text"]:sub(1,tInput.cursX+tInput[tInput.enabled]["scrollX"])..tInput[tInput.enabled]["text"]:sub(tInput.cursX+tInput[tInput.enabled]["scrollX"]+2,#tInput[tInput.enabled]["text"]))
  555.             end
  556.           elseif key == 207 then --end
  557.             tInput.cursX = #tInput[tInput.enabled]["text"]+1
  558.             tInput[tInput.enabled]["scrollX"] = math.max(0,#tInput[tInput.enabled]["text"]-tInput[tInput.enabled]["endX"])
  559.           elseif key == 199 then --home
  560.             tInput.cursX = 1
  561.             tInput[tInput.enabled]["scrollX"] = 0
  562.           elseif key == 28 then --enter
  563.             if tInput.enabled >= #tInput then
  564.               local tRet = {(tBox.button[2] or tBox.button[1])["name"]} --prefer right button
  565.               for i=1,#tInput do
  566.                 if string.match(tInput[i]["text"],"^%d+$") then
  567.                   tInput[i]["text"] = tonumber(tInput[i]["text"])
  568.                 end
  569.                 tRet[#tRet+1] = tInput[i]["text"]
  570.               end
  571.               tInput.enabled = false
  572.               term.setCursorBlink(false)
  573.               tMenuBar.render()
  574.               return unpack(tRet)
  575.             else
  576.               tInput.enabled = math.min(#tInput,tInput.enabled+1)
  577.             end
  578.           end
  579.           if tInput.cursX < 1 then
  580.             tInput.cursX = 1
  581.             if tInput[tInput.enabled]["scrollX"] > 0 then
  582.               tInput[tInput.enabled]["scrollX"] = tInput[tInput.enabled]["scrollX"]-1
  583.             end
  584.           elseif tInput.cursX > tInput[tInput.enabled]["endX"]-tInput[tInput.enabled]["startX"] then
  585.             tInput.cursX = tInput[tInput.enabled]["endX"]-tInput[tInput.enabled]["startX"]
  586.             if #tInput[tInput.enabled]["text"] > tInput.cursX+tInput[tInput.enabled]["scrollX"] then
  587.               tInput[tInput.enabled]["scrollX"] = tInput[tInput.enabled]["scrollX"]+1
  588.             end
  589.           elseif tInput.cursX+tInput[tInput.enabled]["scrollX"] > #string.format(tInput[tInput.enabled]["text"])+1 then
  590.             if tInput[tInput.enabled]["scrollX"] > 0 then
  591.               tInput[tInput.enabled]["scrollX"] = tInput[tInput.enabled]["scrollX"]-1
  592.             else
  593.               tInput.cursX = math.min(#string.format(tInput[tInput.enabled]["text"])+1,tInput[tInput.enabled]["endX"]-1-tInput[tInput.enabled]["startX"])
  594.             end
  595.           end
  596.           tInput.reRender(tInput.enabled)
  597.         else
  598.           --message box
  599.           if key == 28 then --enter
  600.             tMenuBar.render()
  601.             renderLayer(tScroll.layer)
  602.             return (tBox.button[2] or tBox.button[1])["name"]
  603.           end
  604.         end
  605.       end
  606.     end
  607.   end,
  608.   ["click"] = function(clickX,clickY)
  609.     for i=1,#tBox.button do
  610.       if clickY == tBox.button[i]["lineY"]
  611.       and clickX >= tBox.button[i]["startX"]
  612.       and clickX <= tBox.button[i]["endX"] then
  613.         return tBox.button[i]["name"]
  614.       end
  615.     end
  616.   end
  617. }
  618.  
  619. tContextMenu = {
  620.   [1] = {
  621.     ["item"] = "Select",
  622.     ["func"] = function()
  623.       if tTool.selector[1] then
  624.         tTool.selector.selection = true
  625.         tContextMenu.open = false
  626.         renderLayer(tScroll.layer)
  627.       end
  628.     end
  629.   },
  630.   [2] = {
  631.     ["item"] = "Clear sel",
  632.     ["func"] = function()
  633.       if tTool.selector[1] or tTool.selector[2] or tTool.selector.copy then
  634.         tTool.selector = {
  635.           ["enabled"] = true
  636.         }
  637.         tContextMenu.open = false
  638.         renderLayer(tScroll.layer)
  639.       end
  640.     end
  641.   },
  642.   [3] = {
  643.     ["item"] = "Cut",
  644.     ["func"] = function()
  645.       if tTool.selector[1] and not tTool.selector.copy then
  646.         local t1 = tTool.selector[1]
  647.         local t2 = tTool.selector[2] or t1
  648.         tTool.selector.copy = selectorCopy(t1.x,t1.z,t2.x,t2.z,t1.layer,true)
  649.         tTool.selector.selection = true
  650.         tContextMenu.open = false
  651.         renderLayer(tScroll.layer)
  652.       end
  653.     end
  654.   },
  655.   [4] = {
  656.     ["item"] = "Copy",
  657.     ["func"] = function()
  658.       if tTool.selector[1] and not tTool.selector.copy then
  659.         local t1 = tTool.selector[1]
  660.         local t2 = tTool.selector[2] or t1
  661.         tTool.selector.copy = selectorCopy(t1.x,t1.z,t2.x,t2.z,t1.layer,false)
  662.         tTool.selector.selection = true
  663.         tContextMenu.open = false
  664.         renderLayer(tScroll.layer)
  665.       end
  666.     end
  667.   },
  668.   [5] = {
  669.     ["item"] = "Paste",
  670.     ["func"] = function()
  671.       if tTool.selector.copy then
  672.         selectorPaste(tTool.selector[1]["x"],tTool.selector[1]["z"],tTool.selector.copy)
  673.         tContextMenu.open = false
  674.         renderLayer(tScroll.layer)
  675.       end
  676.     end
  677.   },
  678.   [6] = {
  679.     ["item"] = "Delete",
  680.     ["func"] = function()
  681.       if tTool.selector[1] and not tTool.selector.copy then
  682.         local t1 = tTool.selector[1]
  683.         local t2 = tTool.selector[2] or t1
  684.         selectorCopy(t1.x,t1.z,t2.x,t2.z,t1.layer,true)
  685.         tContextMenu.open = false
  686.         renderLayer(tScroll.layer)
  687.       end
  688.     end
  689.   },
  690.   [7] = {
  691.     ["item"] = "Recolor",
  692.     ["func"] = function()
  693.       if tTool.selector[1] then
  694.         tContextMenu.open = false
  695.         tMenuBar.render"Recolor"
  696.       end
  697.     end
  698.   },
  699.   [8] = {
  700.     ["item"] = "Flip hori",
  701.     ["func"] = function()
  702.       if tTool.selector.copy then
  703.         tTool.selector.copy = flipLayer(tTool.selector.copy,"x")
  704.         renderLayer(tScroll.layer)
  705.       elseif tTool.selector[1] then
  706.         local t1 = tTool.selector[1]
  707.         local t2 = tTool.selector[2] or t1
  708.        selectorPaste(t1.x,t1.z,flipLayer(selectorCopy(t1.x,t1.z,t2.x,t2.z,tScroll.layer,true),"x"),tScroll.layer)
  709.         renderLayer(tScroll.layer)
  710.       end
  711.     end
  712.   },
  713.   [9] = {
  714.     ["item"] = "Flip vert",
  715.     ["func"] = function()
  716.       if tTool.selector.copy then
  717.         tTool.selector.copy = flipLayer(tTool.selector.copy,"z")
  718.         renderLayer(tScroll.layer)
  719.       elseif tTool.selector[1] then
  720.         local t1 = tTool.selector[1]
  721.         local t2 = tTool.selector[2] or t1
  722.        selectorPaste(t1.x,t1.z,flipLayer(selectorCopy(t1.x,t1.z,t2.x,t2.z,tScroll.layer,true),"z"),tScroll.layer)
  723.         renderLayer(tScroll.layer)
  724.       end
  725.     end
  726.   },
  727.   ["open"] = false
  728. }
  729. for i=1,#tContextMenu do
  730.   --find longest drop down selection for rendering purposes
  731.   tContextMenu.length = math.max(tContextMenu.length or 0,#tContextMenu[i].item)
  732. end
  733. for i=1,#tContextMenu do
  734.  --equalize length of the dropdown menu names by adding spaces
  735.  local item = tContextMenu[i]["item"]
  736.  tContextMenu[i]["item"] = " "..item..string.rep(" ",math.max(0,tContextMenu.length-#string.format(item)))
  737. end
  738.  
  739. tMenuBar = {
  740. --top menu table, biggest godamn table i've ever made.
  741. --Holds menu names and their respective functions
  742. --it's execution is handled in the event handler
  743.   ["Turtle"] = {
  744.   --general turtle functions
  745.     [1] = {
  746.       ["item"] = "Move to...",
  747.       ["func"] = function()
  748.         local button,coords,axis = tBox.render(1,tTerm.x,"Move turtle to Coords(-999999-999999) on Axis(x/y/z)",2,2,".","Cancel","Ok","Coords:","Axis:")
  749.         if button == "Cancel" then
  750.           --cancel button
  751.           return
  752.         elseif not string.match(coords,"^%-?%d+$") or not axis:match"^[xyzXYZ]$" then
  753.           tBox.render(1,tTerm.x,"Faulty parameters given!")
  754.         else
  755.           cTurtle.moveTo(coords,axis)
  756.           tMenuBar.render()
  757.           renderLayer(tScroll.layer)
  758.         end
  759.       end
  760.     },
  761.     [2] = {
  762.       ["item"] = "Turn...",
  763.       ["func"] = function()
  764.         local button,dir = tBox.render(1,tTerm.x,"Turn turtle, accepts north, x+, right, back, etc.",2,1,".","Cancel","Ok")
  765.         if button == "Cancel" then
  766.           --cancel button
  767.           return
  768.         elseif cTurtle.dirStandardize(dir) then
  769.           cTurtle.renderMove = false
  770.           cTurtle.turn(dir)
  771.           cTurtle.renderMove = true
  772.           tBox.render(1,tTerm.x,"Turned turtle "..dir)
  773.         else
  774.           tBox.render(1,tTerm.x,dir.." is not a valid direction!")
  775.         end
  776.       end
  777.     },
  778.     [3] = {
  779.       ["item"] = "Scan layer...",
  780.       ["func"] = function()
  781.         local button,layer,x,z = tBox.render(1,tTerm.x,"Input new layer number and layer sizes. The color on tool 1 will be used to render.",2,3,"%d","Cancel","Ok","Layer:","X:","Z:",#tBlueprint+1,tTerm.xCanvas,tTerm.zCanvas)
  782.         if button == "Cancel" then
  783.           return
  784.         end
  785.         layer = layer or #tBlueprint+1
  786.         x = x or tTerm.x-1
  787.         z = z or tTerm.y-2
  788.         scan(x,z,layer)
  789.         tBox.render(1,tTerm.x,"Layer("..layer..") scan complete.")
  790.       end
  791.     },
  792.     [4] = {
  793.       ["item"] = "Build layer",
  794.       ["func"] = function()
  795.         local path,button = tFile.curBlueprint
  796.         if path then
  797.           saveBlueprint(path)
  798.         else
  799.           button,path = tBox.render(1,tTerm.x,"Blueprint must be saved locally prior to building! Input file path:",2,1,".","Cancel","Ok","/")
  800.           if button == "Cancel" then
  801.             --cancel
  802.             return
  803.           else
  804.             path = "/"..path
  805.             local dir = ""
  806.             for directory in path:gmatch"/.-/" do
  807.               dir = dir..directory
  808.               if not fs.exists(dir) then
  809.                 fs.makeDir(dir)
  810.               end
  811.             end
  812.             saveBlueprint(path)
  813.           end
  814.         end
  815.         tBox.render(1,tTerm.x,"Saved file: "..path)
  816.         tFile.curBlueprint = path
  817.         buildBlueprint(tScroll.layer,tScroll.layer)
  818.       end
  819.     },
  820.     [5] = {
  821.       ["item"] = "Build blueprint",
  822.       ["func"] = function()
  823.         local path,button = tFile.curBlueprint
  824.         if path then
  825.           saveBlueprint(path)
  826.         else
  827.           button,path = tBox.render(1,tTerm.x,"Blueprint must be saved locally prior to building! Input file path:",2,1,".","Cancel","Ok","/")
  828.           if button == "Cancel" then
  829.             --cancel
  830.             return
  831.           else
  832.             path = "/"..path
  833.             local dir = ""
  834.             for directory in path:gmatch"/.-/" do
  835.               dir = dir..directory
  836.               if not fs.exists(dir) then
  837.                 fs.makeDir(dir)
  838.               end
  839.             end
  840.             saveBlueprint(path)
  841.           end
  842.         end
  843.         tBox.render(1,tTerm.x,"Saved file: "..path)
  844.         tFile.curBlueprint = path
  845.         buildBlueprint(1,#tBlueprint)
  846.       end
  847.     },
  848.     [6] = {
  849.       ["item"] = "Configure enderchest",
  850.       ["func"] = function()
  851.         local button,slot
  852.         if tOngoing.enderChest then
  853.           button,slot = tBox.render(1,tTerm.x,"Use an enderchest for automatic restocking of materials, note that the same slot numbers apply to the chest.",3,1,"%d","Cancel","Change","Disable","Slot:",tOngoing.enderChest)
  854.         else
  855.           button,slot = tBox.render(1,tTerm.x,"Use an enderchest for automatic restocking of materials, note that the same slot numbers used by the turtle apply to the chest as well.",2,1,"%d","Cancel","Enable","Slot:",16)
  856.         end
  857.         if button == "Cancel" then
  858.           return
  859.         elseif button == "Disable" then
  860.           tOngoing.enderChest = false
  861.           cTurtle.tSettings.enderFuel = false
  862.         else
  863.           if not slot or slot > 16 or slot < 1 then
  864.             tBox.render(1,tTerm.x,"Faulty slot number given!")
  865.             return
  866.           else
  867.             tOngoing.enderChest = slot
  868.             cTurtle.tSettings.enderFuel = slot
  869.           end
  870.         end
  871.       end
  872.     },
  873.     [7] = {
  874.       ["item"] = "Configure break mode",
  875.       ["func"] = function()
  876.         local button,slot
  877.         if tOngoing.breakMode then
  878.           button,slot = tBox.render(1,tTerm.x,"The turtle will break all blocks in it's path, and always keep a minimum of 1 block in each slot, to avoid picking up new blocks.|Current mode: ON",2,0,".","Cancel","Disable")
  879.         else
  880.           button,slot = tBox.render(1,tTerm.x,"The turtle will break all blocks in it's path, and always keep a minimum of 1 block in each slot, to avoid picking up new blocks.|Current mode: OFF",2,0,".","Cancel","Enable")
  881.         end
  882.         if button == "Cancel" then
  883.           return
  884.         elseif button == "Disable" then
  885.           tOngoing.breakMode = false
  886.         else
  887.           tOngoing.breakMode = true
  888.         end
  889.       end
  890.     },
  891.     [8] = {
  892.       ["item"] = "Edit GPS data...",
  893.       ["func"] = function()
  894.         cTurtle.input()
  895.         renderLayer(tScroll.layer)
  896.         tMenuBar.render()
  897.       end
  898.     },
  899.     [9] = {
  900.       ["item"] = "Edit Origin point...",
  901.       ["func"] = function()
  902.         local path,button = tFile.curBlueprint
  903.         if not path then
  904.           button,path = tBox.render(1,tTerm.x,"Blueprint must be saved locally prior to editing origin point! Input file path:",2,1,".","Cancel","Ok","/")
  905.           if button == "Cancel" then
  906.             --cancel
  907.             return
  908.           else
  909.             path = "/"..path
  910.             local dir = ""
  911.             for directory in path:gmatch"/.-/" do
  912.               dir = dir..directory
  913.               if not fs.exists(dir) then
  914.                 fs.makeDir(dir)
  915.               end
  916.             end
  917.           end
  918.         end
  919.         tFile.curBlueprint = path
  920.         local button,x,y,z,xDir,zDir,yDir = tBox.render(1,tTerm.x,"Edit current build starting point",2,6,"[0-9%+%-]","Cancel","Ok","X:","Y:","Z:","X dir:","Z dir:","Y dir:",tOrigin.x or cTurtle.tPos.x, tOrigin.y or cTurtle.tPos.y, tOrigin.z or cTurtle.tPos.z,tOrigin.xDir or "+",tOrigin.zDir or "+",tOrigin.yDir or "+")
  921.         if button == "Cancel" then
  922.           return --cancel
  923.         end
  924.         tOrigin.x = x or cTurtle.tPos.x
  925.         tOrigin.y = y or cTurtle.tPos.y
  926.         tOrigin.z = z or cTurtle.tPos.z
  927.         tOrigin.xDir = xDir or "+"
  928.         tOrigin.zDir = zDir or "+"
  929.         tOrigin.yDir = yDir or "+"
  930.         saveBlueprint(path)
  931.       end
  932.     }
  933.   },
  934.   ["Blueprint"] = {
  935.   --creation of new blueprints, loading, saving etc...
  936.     [1] = {
  937.       ["item"] = "New...",
  938.       ["func"] = function()
  939.         local button = tBox.render(1,tTerm.x,"All unsaved work will be lost, continue?",2,0,".","Cancel","Ok")
  940.         if button == "Cancel" then
  941.           --cancel
  942.           return
  943.         end
  944.         tBlueprint = {}
  945.         createLayer(tTerm.xCanvas,tTerm.zCanvas,1)
  946.         tFile.curBlueprint = false
  947.         tScroll.layer = 1
  948.         tScroll.x.value = 0
  949.         tScroll.y.value = 0
  950.         renderLayer(1)
  951.         tBox.render(1,tTerm.x,"New file creation complete.")
  952.       end
  953.     },
  954.     [2] = {
  955.       ["item"] = "Load...",
  956.       ["func"] = function()
  957.         local newBlueprint,newColorSlots,newOrigins
  958.         local button, path = tBox.render(1,tTerm.x,"Load blueprint from file path:",3,1,".","Cancel","Ok","Pastebin","/",tFile.curBlueprint or "")
  959.         if button == "Cancel" then
  960.           return
  961.         elseif button == "Pastebin" then
  962.           newBlueprint,newColorSlots,newOrigin = tPaste.get(path,false,true)
  963.           if not newBlueprint then
  964.             tBox.render(1,tTerm.x,"Pastebin download "..path.." failed!")
  965.             return
  966.           end
  967.         elseif not fs.exists("/"..path) then
  968.           tBox.render(1,tTerm.x,"/"..path.." does not exist!")
  969.           return
  970.         else
  971.           newBlueprint,newColorSlots,newOrigin = loadBlueprint("/"..path)
  972.           if not newBlueprint then
  973.             tBox.render(1,tTerm.x,"/"..path.." is not a Turtle Architect file!")
  974.             return
  975.           else
  976.             tFile.curBlueprint = "/"..path
  977.           end
  978.         end
  979.         tOrigin = newOrigin or {}
  980.         tColorSlots = newColorSlots or {}
  981.         tBlueprint = {}
  982.         for k,v in pairs(newBlueprint) do
  983.           tBlueprint[k] = {}
  984.           for k2,v2 in pairs(newBlueprint[k]) do
  985.             tBlueprint[k][k2] = v2
  986.           end
  987.         end
  988.         tScroll.x.value = 0
  989.         tScroll.y.value = 0
  990.         tScroll.layer = 1
  991.         renderLayer(tScroll.layer)
  992.         tBox.render(1,tTerm.x,"/"..path.." loaded")
  993.       end
  994.     },
  995.     [3] = {
  996.       ["item"] = "Save",
  997.       ["func"] = function()
  998.         local path,button = tFile.curBlueprint
  999.         if not path then
  1000.           button,path = tBox.render(1,tTerm.x,"Input save path:",2,1,".","Cancel","Ok","/")
  1001.           if button == "Cancel" then
  1002.             --cancel
  1003.             return
  1004.           else
  1005.             tFile.curBlueprint = path
  1006.             path = "/"..path
  1007.             local dir = ""
  1008.             for directory in path:gmatch"/.-/" do
  1009.               dir = dir..directory
  1010.               if not fs.exists(dir) then
  1011.                 fs.makeDir(dir)
  1012.               end
  1013.             end
  1014.           end
  1015.         end
  1016.         saveBlueprint(path)
  1017.         tBox.render(1,tTerm.x,"Saved file: "..path)
  1018.       end,
  1019.     },
  1020.     [4] = {
  1021.       ["item"] = "Save as...",
  1022.       ["func"] = function()
  1023.         local button,path = tBox.render(1,tTerm.x,"Save as:",3,1,".","Cancel","Local","Pastebin","/",tFile.curBlueprint or "")
  1024.         if button == "Cancel" then
  1025.           --cancel
  1026.           return
  1027.         elseif button == "Local" then
  1028.           path = "/"..path
  1029.           local dir = ""
  1030.           for directory in path:gmatch"/.-/" do
  1031.             dir = dir..directory
  1032.             if not fs.exists(dir) then
  1033.               local button = tBox.render(1,tTerm.x,"The directory "..dir.." does not exist! Create?",2,0,".","Cancel","Create")
  1034.               if button == "Create" then
  1035.                 fs.makeDir(dir)
  1036.               else
  1037.                 tBox.render(1,tTerm.x,"Saving "..path.." failed!")
  1038.                 return
  1039.               end
  1040.             end
  1041.           end
  1042.           saveBlueprint(path)
  1043.           tBox.render(1,tTerm.x,"Saved as: "..path)
  1044.           tFile.curBlueprint = path
  1045.         elseif button == "Pastebin" then
  1046.           trimBlueprint(tBlueprint)
  1047.           local url, code = tPaste.put(tBlueprint,path)
  1048.           if not url then
  1049.             tBox.render(1,tTerm.x,"Pastebin upload "..path.." failed!")
  1050.             return
  1051.           end
  1052.           tBox.render(1,tTerm.x,"Pastebin upload sucesssfull! "..url..".")
  1053.         end
  1054.       end
  1055.     },
  1056.     [5] = {
  1057.       ["item"] = "Flip...",
  1058.       ["func"] = function()
  1059.         local button = tBox.render(1,tTerm.x,"Flip blueprint Horizontinal or Vertical?",3,0,".","Cancel","Hori","Vert")
  1060.         if button == "Cancel" then
  1061.           return --cancel
  1062.         elseif button == "Hori" then
  1063.           button = "x"
  1064.         else
  1065.           button = "z"
  1066.         end
  1067.         fattenBlueprint(tBlueprint)
  1068.         for i=1,#tBlueprint do
  1069.           layerPaste(flipLayer(tBlueprint[i],button),i,true)
  1070.         end
  1071.         renderLayer(tScroll.layer)
  1072.       end
  1073.     },
  1074.     [6] = {
  1075.       ["item"] = "Edit slot data...",
  1076.       ["func"] = function()
  1077.         tMenuBar.render("SlotColors")
  1078.       end
  1079.     },
  1080.     [7] = {
  1081.       ["item"] = "Mark as built",
  1082.       ["func"] = function()
  1083.         local button = tBox.render(1,tTerm.x,"This will mark the entire blueprint as built, so the turtle will skip it.",2,0,".","Cancel","Ok")
  1084.         if button == "Cancel" then
  1085.           return --cancel
  1086.         end
  1087.         for il=1,#tBlueprint do
  1088.           for ix=1,#tBlueprint[il] do
  1089.             for iz=1,#tBlueprint[il][ix] do
  1090.               local block = tBlueprint[il][ix][iz] or " "
  1091.               if block ~= " "
  1092.               and block:match(unbuilt) then
  1093.                 tBlueprint[il][ix][iz] = block:upper()
  1094.               end
  1095.             end
  1096.           end
  1097.         end
  1098.       end
  1099.     },
  1100.     [8] = {
  1101.       ["item"] = "Mark as not built",
  1102.       ["func"] = function()
  1103.         local button = tBox.render(1,tTerm.x,"This will mark the entire blueprint as not built, so the turtle will build it.",2,0,".","Cancel","Ok")
  1104.         if button == "Cancel" then
  1105.           return --cancel
  1106.         end
  1107.         for il=1,#tBlueprint do
  1108.           for ix=1,#tBlueprint[il] do
  1109.             for iz=1,#tBlueprint[il][ix] do
  1110.               local block = tBlueprint[il][ix][iz] or " "
  1111.               tBlueprint[il][ix][iz] = block:upper()
  1112.             end
  1113.           end
  1114.         end
  1115.       end
  1116.     },
  1117.     [9] = {
  1118.       ["item"] = "Check usage",
  1119.       ["func"] = function()
  1120.         local button,from,to = tBox.render(1,tTerm.x,"Input layer range to check for fuel and block usage",2,2,".","Cancel","Ok","From:","To:",1,#tBlueprint)
  1121.         if button == "Cancel" then
  1122.           return --cancel
  1123.         elseif from > to
  1124.         or to > #tBlueprint
  1125.         or from < 1 then
  1126.           tBox.render(1,tTerm.x,"Faulty layer range "..from.."-"..to.." given!")
  1127.           return
  1128.         end
  1129.         local fuelUsage,tBlockUsage = checkUsage(from,to)
  1130.         tBox.render(1,tTerm.x,"Required fuel: "..fuelUsage..".")
  1131.         local tUsageLines = {[1] = "Blocks required:"}
  1132.         local tUsageLines2 = {}
  1133.         for k,v in pairs(tBlockUsage) do
  1134.           if k:match(built) then
  1135.             --skip
  1136.           else
  1137.             table.insert(tUsageLines,tColorString[tColorNums[k]]..": "..v..".")
  1138.           end
  1139.         end
  1140.         while #tUsageLines >= tTerm.y-3 do
  1141.           table.insert(tUsageLines2,table.remove(tUsageLines,#tUsageLines))
  1142.         end
  1143.         tBox.render(1,tTerm.x,tUsageLines)
  1144.         if #tUsageLines2 > 0 then
  1145.           tBox.render(1,tTerm.x,tUsageLines2)
  1146.         end
  1147.       end
  1148.     },
  1149.   },
  1150.   ["Layer"] = {
  1151.   --layer actions, duplicating, moving and what have you
  1152.     [1] = {
  1153.       ["item"] = "New...",
  1154.       ["func"] = function()
  1155.         local button,layerNum = tBox.render(1,tTerm.x,"Input new layer number:",2,1,"%d","Cancel","Ok","",#tBlueprint+1)
  1156.         if button == "Cancel" then
  1157.           --cancel
  1158.           return
  1159.         end
  1160.         if layerNum <= #tBlueprint then
  1161.           local button = tBox.render(1,tTerm.x,"Layer "..layerNum.." already exists! Overwrite or insert?",3,0,".","Cancel","Insert","Overwrite")
  1162.           if button == "Cancel" then
  1163.             return
  1164.           elseif button == "Insert" then
  1165.             createLayer(tTerm.xCanvas,tTerm.zCanvas,layerNum)
  1166.           elseif button == "Overwrite" then
  1167.             createLayer(tTerm.xCanvas,tTerm.zCanvas,layerNum,true)
  1168.           end
  1169.         else
  1170.           for i=#tBlueprint+1,layerNum do
  1171.             createLayer(tTerm.xCanvas,tTerm.zCanvas,i,true)
  1172.           end
  1173.         end
  1174.         tScroll.x.value = 0
  1175.         tScroll.y.value = 0
  1176.         tScroll.layer = layerNum
  1177.         renderLayer(tScroll.layer)
  1178.       end
  1179.     },
  1180.     [2] = {
  1181.       ["item"] = "Import...",
  1182.       ["func"] = function()
  1183.         local importBlueprint
  1184.         local button, path,from,to,layer = tBox.render(1,tTerm.x,"Import layers from local path or pastebin code:",3,4,".","Cancel","Ok","Pastebin","/","From layer:","To:","Import to:","","","",#tBlueprint+1)
  1185.         if button == "Cancel" then
  1186.           return
  1187.         elseif button == "Pastebin" then
  1188.           local paste = tPaste.get(path)
  1189.           if not paste then
  1190.             tBox.render(1,tTerm.x,"Pastebin download "..path.." failed!")
  1191.             return
  1192.           elseif not paste:match("Blueprint file for CometWolf's Turtle Architect. Pastebin: "..tPaste.program) then
  1193.             tBox.render(1,tTerm.x,path.." is not a Turtle Architect file!")
  1194.             return
  1195.           end
  1196.           importBlueprint = textutils.unserialize(paste:sub(#("Blueprint file for CometWolf's Turtle Architect. Pastebin: "..tPaste.program)+1,#paste))
  1197.         elseif not fs.exists("/"..path) then
  1198.           tBox.render(1,tTerm.x,"/"..path.." does not exist!")
  1199.           return
  1200.         else
  1201.           importBlueprint = loadBlueprint("/"..path)
  1202.           if not importBlueprint then
  1203.             tBox.render(1,tTerm.x,"/"..path.." is not a Turtle Architect file!")
  1204.             return
  1205.           end
  1206.         end
  1207.         if #importBlueprint < to then
  1208.           tBox.render(1,tTerm.x,"The specified layers "..from.."-"..to.." do not exist in the given blueprint("..path..")")
  1209.           return
  1210.         elseif layer <= #tBlueprint then
  1211.           local button = tBox.render(1,tTerm.x,"Layers already exist in the range "..layer.."-"..(layer+(to-from)).."! Overwrite or insert?",3,0,".","Cancel","Insert","Overwrite")
  1212.           if button == "Cancel" then
  1213.             return
  1214.           elseif button == "Insert" then
  1215.             for i=from,to do
  1216.               layerPaste(importBlueprint[i],layer+(i-from),false)
  1217.             end
  1218.           elseif button == "Overwrite" then
  1219.             for i=from,to do
  1220.               layerPaste(importBlueprint[i],layer+(i-from),true)
  1221.             end
  1222.           end
  1223.         else
  1224.           for i=#tBlueprint+1,layer-1 do
  1225.             createLayer(tTerm.xCanvas,tTerm.zCanvas,i,true)
  1226.           end
  1227.           for i=from,to do
  1228.             layerPaste(importBlueprint[i],layer+(i-from),true)
  1229.           end
  1230.         end
  1231.         tScroll.x.value = math.min(tScroll.x.value,math.max(0,#tBlueprint[tScroll.layer]-tTerm.xCanvas))
  1232.         tScroll.y.value = math.min(tScroll.y.value,math.max(0,#tBlueprint[tScroll.layer][1]-tTerm.zCanvas))
  1233.         renderLayer(tScroll.layer)
  1234.         tBox.render(1,tTerm.x,"Layers "..from.."-"..to.." Imported from "..path.." to "..layer.."-"..(layer+(to-from))..".")
  1235.       end
  1236.     },
  1237.     [3] = {
  1238.       ["item"] = "Delete current layer",
  1239.       ["func"] = function()
  1240.         local delLayer = tScroll.layer
  1241.         local button = tBox.render(1,tTerm.x,"Are you sure you wish to delete "..delLayer.."?",2,0,".","Cancel","Ok")
  1242.         if button == "Cancel" then
  1243.           return --cancel
  1244.         end
  1245.         if #tBlueprint <= 1 then
  1246.           createLayer(tTerm.xCanvas,tTerm.zCanvas,1,true)
  1247.         else
  1248.           table.remove(tBlueprint,delLayer)
  1249.         end
  1250.         tScroll.layer = math.min(math.max(1,tScroll.layer-1),#tBlueprint)
  1251.         tScroll.x.value = math.min(tScroll.x.value,#tBlueprint[tScroll.layer]-tTerm.xCanvas)
  1252.         tScroll.y.value = math.min(tScroll.y.value,#tBlueprint[tScroll.layer][1]-tTerm.zCanvas)
  1253.         renderLayer(tScroll.layer)
  1254.         tBox.render(1,tTerm.x,"Deleted layer "..delLayer..".")
  1255.       end
  1256.     },
  1257.     [4] = {
  1258.       ["item"] = "Delete layer range",
  1259.       ["func"] = function()
  1260.         local button,from,to = tBox.render(1,tTerm.x,"Delete layers",2,2,"%d","Cancel","Ok","From:","To:",tScroll.layer,#tBlueprint)
  1261.         if button == "Cancel" then
  1262.           return --cancel
  1263.         end
  1264.         if #tBlueprint <= 1 then
  1265.           createLayer(tTerm.xCanvas,tTerm.zCanvas,1,true)
  1266.         else
  1267.           for i=math.max(to,from),math.min(from,to),-1 do
  1268.             table.remove(tBlueprint,i)
  1269.           end
  1270.         end
  1271.         tScroll.layer = math.min(math.max(1,tScroll.layer-1),#tBlueprint)
  1272.         tScroll.x.value = math.min(tScroll.x.value,#tBlueprint[tScroll.layer]-tTerm.xCanvas)
  1273.         tScroll.y.value = math.min(tScroll.y.value,#tBlueprint[tScroll.layer][1]-tTerm.zCanvas)
  1274.         renderLayer(tScroll.layer)
  1275.         tBox.render(1,tTerm.x,"Deleted layers "..from.."-"..to..".")
  1276.       end
  1277.     },
  1278.     [5] = {
  1279.       ["item"] = "Move to...",
  1280.       ["func"] = function()
  1281.         local button,layerNum = tBox.render(1,tTerm.x,"Move current layer("..tScroll.layer..") to...",2,1,"%d","Cancel","Ok","",#tBlueprint+1)
  1282.         if button == "Cancel" then
  1283.           return  --cancel
  1284.         end
  1285.         if layerNum <= #tBlueprint then
  1286.           local button = tBox.render(1,tTerm.x,"A layer already exists at"..layerNum.."! Overwrite or insert?",3,0,".","Cancel","Insert","Overwrite")
  1287.           if button == "Cancel" then
  1288.             return
  1289.           elseif button == "Insert" then
  1290.             layerPaste(copyLayer(tScroll.layer),layerNum,false)
  1291.           elseif button == "Overwrite" then
  1292.             layerPaste(copyLayer(tScroll.layer),layerNum,true)
  1293.           end
  1294.         else
  1295.           for i=#tBlueprint+1,layerNum-1 do
  1296.             createLayer(tTerm.xCanvas,tTerm.zCanvas,i,true)
  1297.           end
  1298.           layerPaste(copyLayer(tScroll.layer),layerNum,true)
  1299.         end
  1300.         createLayer(tTerm.xCanvas,tTerm.zCanvas,tScroll.layer,true)
  1301.         tBox.render(1,tTerm.x,"Moved layer "..tScroll.layer.." to "..layerNum..".")
  1302.         tScroll.layer = layerNum
  1303.         renderLayer(tScroll.layer)
  1304.       end
  1305.     },
  1306.     [6] = {
  1307.       ["item"] = "Copy to...",
  1308.       ["func"] = function()
  1309.         local button,layerNum = tBox.render(1,tTerm.x,"Copy current layer("..tScroll.layer..") to...",2,1,"%d","Cancel","Ok","",#tBlueprint+1)
  1310.         if button == "Cancel" then
  1311.           --cancel
  1312.           return
  1313.         elseif layerNum <= #tBlueprint then
  1314.           local button = tBox.render(1,tTerm.x,"A layer already exists at"..layerNum.."! Overwrite or insert?",3,0,"Cancel","Insert","Overwrite")
  1315.           if button == "Cancel" then
  1316.             return
  1317.           elseif button == "Insert" then
  1318.             layerPaste(copyLayer(tScroll.layer),layerNum,false)
  1319.           elseif button == "Overwrite" then
  1320.             layerPaste(copyLayer(tScroll.layer),layerNum,true)
  1321.           end
  1322.         else
  1323.           for i=#tBlueprint+1,layerNum-1 do
  1324.             createLayer(tTerm.xCanvas,tTerm.zCanvas,i)
  1325.           end
  1326.           layerPaste(copyLayer(tScroll.layer),layerNum,true)
  1327.         end
  1328.         tBox.render(1,tTerm.x,"Copied layer "..tScroll.layer.." to "..layerNum..".")
  1329.       end
  1330.     },
  1331.     [7] = {
  1332.       ["item"] = "Stretch copy...",
  1333.       ["func"] = function()
  1334.         local button,from,to = tBox.render(1,tTerm.x,"Stretch current layer("..tScroll.layer..") ...",2,2,"%d","Cancel","Ok","From:","To:",tScroll.layer+1)
  1335.         to = to or from or 0
  1336.         if button == "Cancel" or to <= 0 then
  1337.           --cancel button
  1338.           return
  1339.         end
  1340.         local layerCopy = copyLayer(tScroll.layer)
  1341.         if from <= #tBlueprint
  1342.         or to <= #tBlueprint then
  1343.           local button = tBox.render(1,tTerm.x,"Layers already exist between the range "..from.."-"..to.."! Overwrite or insert?",3,0,".","Cancel","Insert","Overwrite")
  1344.           if button == "Cancel" then
  1345.             return
  1346.           elseif button == "Insert" then
  1347.             for i=from,to do
  1348.               layerPaste(layerCopy,i)
  1349.             end
  1350.           elseif button == "Overwrite" then
  1351.             for i=from,to do
  1352.               layerPaste(layerCopy,i,true)
  1353.             end
  1354.           end
  1355.         else
  1356.           for i=#tBlueprint+1,from-1 do
  1357.             createLayer(tTerm.xCanvas,tTerm.zCanvas,i)
  1358.           end
  1359.           for i=from,to do
  1360.             layerPaste(layerCopy,i,true)
  1361.           end
  1362.         end
  1363.         tBox.render(1,tTerm.x,"stretched "..tScroll.layer.." from "..from.." to "..to..".")
  1364.       end
  1365.     },
  1366.     [8] = {
  1367.       ["item"] = "Copy range...",
  1368.       ["func"] = function()
  1369.         local button,from,to,layer = tBox.render(1,tTerm.x,"Copy the given range of layers to:",2,3,"%d","Cancel","Ok","From layer:","To:","Paste to:",tScroll.layer,#tBlueprint,#tBlueprint+1)
  1370.         if button == "Cancel" then
  1371.           return
  1372.         elseif layer <= #tBlueprint then
  1373.           local button = tBox.render(1,tTerm.x,"Layers already exist in the range "..layer.."-"..(layer+(to-from)).."! Overwrite or insert?",3,0,".","Cancel","Insert","Overwrite")
  1374.           if button == "Cancel" then
  1375.             return
  1376.           elseif button == "Insert" then
  1377.             for i=math.max(to,from),math.min(from,to),-1 do
  1378.               layerPaste(tBlueprint[i],layer+(i-from),false)
  1379.             end
  1380.           elseif button == "Overwrite" then
  1381.             for i=math.min(from,to),math.max(to,from) do
  1382.               layerPaste(tBlueprint[i],layer+(i-from),true)
  1383.             end
  1384.           end
  1385.         else
  1386.           for i=#tBlueprint+1,layer-1 do
  1387.             createLayer(tTerm.xCanvas,tTerm.zCanvas,i,true)
  1388.           end
  1389.           for i=math.min(from,to),math.max(to,from) do
  1390.             layerPaste(tBlueprint[i],layer+(i-from),true)
  1391.           end
  1392.         end
  1393.         tScroll.x.value = math.min(tScroll.x.value,#tBlueprint[tScroll.layer]-tTerm.xCanvas)
  1394.         tScroll.y.value = math.min(tScroll.y.value,#tBlueprint[tScroll.layer][1]-tTerm.zCanvas)
  1395.         renderLayer(tScroll.layer)
  1396.         tBox.render(1,tTerm.x,"Layers "..from.."-"..to.." copied to "..layer.."-"..(layer+(to-from))..".")
  1397.       end
  1398.     },
  1399.     [9] = {
  1400.       ["item"] = "Merge...",
  1401.       ["func"] = function()
  1402.         local button,from,to = tBox.render(1,tTerm.x,"Merge the layer range...",2,2,"%d","Cancel","Ok","From:","To:",tScroll.layer)
  1403.         if button == "Cancel" then
  1404.           return --cancel
  1405.         elseif not from or not to or to < from then
  1406.           tBox.render(1,tTerm.x,"Unable to merge those layers")
  1407.           return
  1408.         end
  1409.         local button = tBox.render(1,tTerm.x,"Merging the layer range "..from.."-"..to..". Keep original colors?",2,0,".","No","Yes")
  1410.         if button == "Yes" then
  1411.           layerPaste(layerCombine(from,to),from,true)
  1412.         else
  1413.           layerPaste(layerCombine(from,to,true),from,true)
  1414.         end
  1415.         for i=to,from+1,-1 do
  1416.           table.remove(tBlueprint,i)
  1417.         end
  1418.         tScroll.layer = math.min(#tBlueprint,tScroll.layer)
  1419.         tScroll.x.value = math.min(tScroll.x.value,#tBlueprint[tScroll.layer]-tTerm.xCanvas)
  1420.         tScroll.y.value = math.min(tScroll.y.value,#tBlueprint[tScroll.layer][1]-tTerm.zCanvas)
  1421.         renderLayer(tScroll.layer)
  1422.       end
  1423.     },
  1424.     [10] = {
  1425.       ["item"] = "Flip...",
  1426.       ["func"] = function()
  1427.         local button = tBox.render(1,tTerm.x,"Flip current layer("..tScroll.layer..") Horizontally or Vertically?",3,0,".","Cancel","Hori","Vert")
  1428.         if button == "Cancel" then
  1429.           return --cancel
  1430.         end
  1431.         if button == "Hori" then
  1432.           button = "x"
  1433.         else
  1434.           button = "z"
  1435.         end
  1436.         layerPaste(flipLayer(tBlueprint[tScroll.layer],button),tScroll.layer,true)
  1437.         renderLayer(tScroll.layer)
  1438.       end
  1439.     },
  1440.     [11] = {
  1441.       ["item"] = "Mark as built",
  1442.       ["func"] = function()
  1443.         local button = tBox.render(1,tTerm.x,"This will mark the current layer("..tScroll.layer..") as built, so the turtle will skip it.",2,0,".","Cancel","Ok")
  1444.         if button == "Cancel" then
  1445.           return --cancel
  1446.         end
  1447.         for ix=1,#tBlueprint[tScroll.layer] do
  1448.           for iz=1,#tBlueprint[tScroll.layer][ix] do
  1449.             local block = tBlueprint[tScroll.layer][ix][iz] or " "
  1450.             if block ~= " "
  1451.             and not block:match(built) then
  1452.               tBlueprint[tScroll.layer][ix][iz] = block:upper()
  1453.             end
  1454.           end
  1455.         end
  1456.       end
  1457.     },
  1458.     [12] = {
  1459.       ["item"] = "Mark as not built",
  1460.       ["func"] = function()
  1461.         local button = tBox.render(1,tTerm.x,"This will mark the current layer("..tScroll.layer..") as not built, so the turtle will build it.",2,0,".","Cancel","Ok")
  1462.         if button == "Cancel" then
  1463.           return --cancel
  1464.         end
  1465.         for ix=1,#tBlueprint[tScroll.layer] do
  1466.           for iz=1,#tBlueprint[tScroll.layer][ix] do
  1467.             local block = tBlueprint[tScroll.layer][ix][iz] or " "
  1468.             tBlueprint[tScroll.layer][ix][iz] = block:lower()
  1469.           end
  1470.         end
  1471.       end
  1472.     },
  1473.     [13] = {
  1474.       ["item"] = "Goto...",
  1475.       ["func"] = function()
  1476.         local button,layer,x,z = tBox.render(1,tTerm.x,"Goto layer, X, Z...",4,3,"%d","Cancel","Ok","Top","Bottom","Layer:","X:","Z:",tScroll.layer,tScroll.x.value,tScroll.y.value)
  1477.         if button == "Cancel" then
  1478.           return --cancel
  1479.         elseif button == "Top" then
  1480.           layer = #tBlueprint
  1481.         elseif button == "Bottom" then
  1482.           layer = 1
  1483.         elseif layer > #tBlueprint then
  1484.           local button = tBox.render(1,tTerm.x,"That layer does not exist! The top layer is "..#tBlueprint..". Go there?",2,0,".","Cancel","Ok")
  1485.           if button == "Cancel" then
  1486.             return
  1487.           else
  1488.             layer = #tBlueprint
  1489.           end
  1490.         end
  1491.         tScroll.layer = layer or tScroll.layer
  1492.         tScroll.x.value = x
  1493.         tScroll.y.value = z
  1494.         renderLayer(tScroll.layer)
  1495.       end
  1496.     },
  1497.     [14] = {
  1498.       ["item"] = "Go up 1",
  1499.       ["func"] = function()
  1500.         if tScroll.layer >= #tBlueprint then
  1501.           local button = tBox.render(1,tTerm.x,"Last layer reached! Create new?",2,0,".","Cancel","Ok")
  1502.           if button == "Cancel" then
  1503.             return --cancel
  1504.           else
  1505.             createLayer(tTerm.xCanvas,tTerm.zCanvas,#tBlueprint+1)
  1506.             tScroll.x.value = 0
  1507.             tScroll.y.value = 0
  1508.           end
  1509.         end
  1510.         tScroll.layer = tScroll.layer+1
  1511.         renderLayer(tScroll.layer)
  1512.       end
  1513.     },
  1514.     [15] = {
  1515.       ["item"] = "Go down 1",
  1516.       ["func"] = function()
  1517.         if tScroll.layer <= 1 then
  1518.           local button,layer = tBox.render(1,tTerm.x,"Unable to go below layer 1!")
  1519.           return
  1520.         end
  1521.         tScroll.layer = math.max(tScroll.layer-1,1)
  1522.         renderLayer(tScroll.layer)
  1523.       end
  1524.     }
  1525.   },
  1526.   ["Settings"] = {
  1527.   --program settings, for whatever modes i can come up with and other random bits and bobs
  1528.     [1] = {
  1529.       ["item"] = "Update",
  1530.       ["func"] = function()
  1531.         fs.delete(tFile.program)
  1532.         if tPaste.get(tPaste.program,tFile.program) then
  1533.           tBox.render(1,tTerm.x,"Update sucessful! Rebooting...")
  1534.           os.reboot()
  1535.         else
  1536.           tBox.render(1,tTerm.x,"Update failed. Returning to program")
  1537.           return
  1538.         end
  1539.       end
  1540.     },
  1541.     [2] = {
  1542.       ["item"] = "About",
  1543.       ["func"] = function()
  1544.         tBox.render(1,tTerm.x,"Turtle Architect is a turtle blueprint drawing and building program. Created by CometWolf.")
  1545.       end
  1546.     },
  1547.     [3] = {
  1548.       ["item"] = "Overwrite mode",
  1549.       ["func"] = function()
  1550.         local mode,buttonText
  1551.         if tTool.overwrite == true then
  1552.           mode = "on"
  1553.           buttonText = "Off"
  1554.         else
  1555.           mode = "off"
  1556.           buttonText = "On"
  1557.         end
  1558.         local button = tBox.render(1,tTerm.x,"Overwrite mode allowes any color to be painted onto any color. If it is off, all colors may be painted on white, but only white may be painted on any other color. Current mode: "..mode..".",2,0,".","Cancel",buttonText)
  1559.         if button == "On" then
  1560.           tTool.overwrite = true
  1561.         elseif button == "Off" then
  1562.           tTool.overwrite = false
  1563.         end
  1564.       end
  1565.     },
  1566.     [4] = {
  1567.       ["item"] = "Draw built mode",
  1568.       ["func"] = function()
  1569.         local mode,buttonText
  1570.         if tTool.built == true then
  1571.           mode = "on"
  1572.           buttonText = "Off"
  1573.         else
  1574.           mode = "off"
  1575.           buttonText = "On"
  1576.         end
  1577.         local button = tBox.render(1,tTerm.x,"This mode will allow you to draw blocks the turtle will consider already built, thus skipping them. Current mode: "..mode..".",2,0,".","Cancel",buttonText)
  1578.         if button == "On" then
  1579.           tTool.built = true
  1580.         elseif button == "Off" then
  1581.           tTool.built = false
  1582.         end
  1583.       end
  1584.     },
  1585.     [5] = {
  1586.       ["item"] = "Render built mode",
  1587.       ["func"] = function()
  1588.         local mode,buttonText
  1589.         if tTerm.built == true then
  1590.           mode = "on"
  1591.           buttonText = "Off"
  1592.         else
  1593.           mode = "off"
  1594.           buttonText = "On"
  1595.         end
  1596.         local button = tBox.render(1,tTerm.x,'This mode will render any blocks marked as built with a "B". These blocks will be skipped when a turtle builds the blueprint. Current mode: '..mode..".",2,0,".","Cancel",buttonText)
  1597.         if button == "On" then
  1598.           tTerm.built = true
  1599.         elseif button == "Off" then
  1600.           tTerm.built = false
  1601.         else
  1602.           return --cancel
  1603.         end
  1604.         renderLayer(tScroll.layer)
  1605.       end
  1606.     },
  1607.     [6] = {
  1608.       ["item"] = "Grid mode",
  1609.       ["func"] = function()
  1610.         local mode,buttonText
  1611.         if tTerm.grid == true then
  1612.           mode = "on"
  1613.           buttonText = "Off"
  1614.         else
  1615.           mode = "off"
  1616.           buttonText = "On"
  1617.         end
  1618.         local button = tBox.render(1,tTerm.x,"This mode draws a grid overlay on the canvas. Current mode: "..mode..".",2,0,".","Cancel",buttonText)
  1619.         if button == "On" then
  1620.           tTerm.grid = true
  1621.           renderLayer(tScroll.layer)
  1622.         elseif button == "Off" then
  1623.           tTerm.grid = false
  1624.           renderLayer(tScroll.layer)
  1625.         end
  1626.       end
  1627.     },
  1628.     [7] = {
  1629.       ["item"] = "Monitor mode",
  1630.       ["func"] = function()
  1631.         local mode,buttonText
  1632.         if #tMon > 0 then
  1633.           mode = "on"
  1634.           buttonText = "Off"
  1635.         else
  1636.           mode = "off"
  1637.           buttonText = "On"
  1638.         end
  1639.         local button = tBox.render(1,tTerm.x,"This mode displays the canvas on connected monitors aswell as the terminal, thus allowing input on both. Current mode: "..mode..".",2,0,".","Cancel",buttonText)
  1640.         if button == "On" then
  1641.           local tSides = rs.getSides()
  1642.           tMon = {}
  1643.           for is=1,#tSides do
  1644.             if peripheral.getType(tSides[is]) == "monitor" and peripheral.call(tSides[is],"isColor") then
  1645.               local button = tBox.render(1,tTerm.x,"Monitor on "..tSides[is].." found! Connect?",2,0,".","No","Yes")
  1646.               if button == "Yes" then
  1647.                 tMon[#tMon+1] = peripheral.wrap(tSides[is])
  1648.                 tMon[#tMon]["side"] = tSides[is]
  1649.                 tMon[#tMon]["x"],tMon[#tMon]["y"] = tMon[#tMon]["getSize"]()
  1650.                 tMon[#tMon]["xMid"] = math.ceil(tMon[#tMon]["x"]/2)
  1651.                 tMon[#tMon]["yMid"] = math.ceil(tMon[#tMon]["y"]/2)
  1652.                 tMon[#tMon]["xCanvas"] = tMon[#tMon]["x"] --total x veiwing area
  1653.                 tMon[#tMon]["zCanvas"] = tMon[#tMon]["y"] --total y veiwing area
  1654.               end
  1655.             elseif peripheral.getType(tSides[is]) == "modem"
  1656.             and not peripheral.call(tSides[is],"isWireless") then
  1657.               local tPeripherals = peripheral.call(tSides[is],"getNamesRemote")
  1658.               for ip=1,#tPeripherals do
  1659.                 if string.match(tPeripherals[ip],"monitor")
  1660.                 and peripheral.call(tPeripherals[ip],"isColor") then
  1661.                   local button = tBox.render(1,tTerm.x,"Monitor "..tPeripherals[ip].." found! Connect?",2,0,".","No","Yes")
  1662.                   if button == "Yes" then
  1663.                     tMon[#tMon+1] = peripheral.wrap(tPeripherals[ip])
  1664.                     tMon[#tMon]["side"] = tPeripherals[ip]
  1665.                     tMon[#tMon]["x"],tMon[#tMon]["y"] = tMon[#tMon]["getSize"]()
  1666.                     tMon[#tMon]["xMid"] = math.ceil(tMon[#tMon]["x"]/2)
  1667.                     tMon[#tMon]["yMid"] = math.ceil(tMon[#tMon]["y"]/2)
  1668.                     tMon[#tMon]["xCanvas"] = tMon[#tMon]["x"] --total x veiwing area
  1669.                     tMon[#tMon]["zCanvas"] = tMon[#tMon]["y"] --total y veiwing area
  1670.                   end
  1671.                 end
  1672.               end
  1673.             end
  1674.           end  
  1675.           if #tMon < 1 then
  1676.             tBox.render(1,tTerm.x,"No monitor connected!")
  1677.             tMon = ""
  1678.             return
  1679.           end
  1680.           tMenuBar.render()
  1681.           renderLayer(tScroll.layer)
  1682.         elseif button == "Off" then
  1683.           for i=1,#tMon do
  1684.             tMon[i]["setBackgroundColor"](colors.black)
  1685.             tMon[i]["clear"]()
  1686.           end
  1687.           tMon = ""
  1688.           tMenuBar.render()
  1689.           renderLayer(tScroll.layer)
  1690.         end
  1691.       end
  1692.     },
  1693.     [8] = {
  1694.       ["item"] = "Background layer",
  1695.       ["func"] = function()
  1696.         local button,layerNum
  1697.         if tTerm.bgLayer then
  1698.           button,layerNum = tBox.render(1,tTerm.x,"This mode renders the selected layer below the one currently displayed, for easier visualization. Current mode: on, layer "..tTerm.bgNum..".",3,1,"%d","Cancel","Change","Off","Layer:",tTerm.bgNum)
  1699.         else
  1700.           button,layerNum = tBox.render(1,tTerm.x,"This mode renders the selected layer below the one currently displayed, for easier visualization. Current mode: Off.",2,1,"%d","Cancel","On","Layer:",math.max(tScroll.layer-1,1))
  1701.         end
  1702.         if button == "On" or button == "Change" then
  1703.           if layerNum > #tBlueprint then
  1704.             tBox.render(1,tTerm.x,"Layer "..layerNum.." does not exist!")
  1705.             return
  1706.           end
  1707.           tTerm.bgLayer = tBlueprint[layerNum]
  1708.           tTerm.bgNum = layerNum
  1709.         else
  1710.           tTerm.bgLayer = nil
  1711.           tTerm.bgNum = nil
  1712.         end
  1713.         renderLayer(tScroll.layer)
  1714.       end
  1715.     },
  1716.     [9] = {
  1717.       ["item"] = "Quit",
  1718.       ["func"] = function()
  1719.         local button = tBox.render(1,tTerm.x,"Are you sure you wish to quite? All unsaved work will be lost!",2,0,".","Cancel","Quit")
  1720.         if button == "Cancel" then
  1721.           return --cancel
  1722.         else
  1723.           for i=1,#tMon do
  1724.             tMon[i]["setBackgroundColor"](colors.black)
  1725.             tMon[i]["clear"]()
  1726.           end
  1727.           term.setBackgroundColor(colors.black)
  1728.           term.clear()
  1729.           term.setCursorPos(1,1)
  1730.           error()
  1731.         end
  1732.       end
  1733.     }
  1734.   },
  1735.   ["Tools"] = {
  1736.   --Tools menu, for chosing tools and colors
  1737.     [1] = {
  1738.       ["item"] = "Brush",
  1739.       ["func"] = function(button)
  1740.         tTool[button]["tool"] = "Brush"
  1741.         tTool.selector = {["enabled"] = disabled}
  1742.         tMenuBar.render("Size")
  1743.       end
  1744.     },
  1745.     [2] = {
  1746.       ["item"] = "Dragger",
  1747.       ["func"] = function(button)
  1748.         tTool[button]["tool"] = "Dragger"
  1749.         tTool.selector = {["enabled"] = disabled}
  1750.         tMenuBar.render()
  1751.       end
  1752.     },
  1753.     [3] = {
  1754.       ["item"] = "Fill",
  1755.       ["func"] = function(button)
  1756.         tTool[button]["tool"] = "Fill"
  1757.         tTool.selector = {["enabled"] = disabled}
  1758.         tMenuBar.render("Color")
  1759.       end
  1760.     },
  1761.     [4] = {
  1762.       ["item"] = "Square",
  1763.       ["func"] = function(button)
  1764.         tTool[button]["tool"] = "Square"
  1765.         tTool.selector = {["enabled"] = disabled}
  1766.         tMenuBar.render("Size")
  1767.       end
  1768.     },
  1769.     [5] = {
  1770.       ["item"] = "Circle",
  1771.       ["func"] = function(button)
  1772.         tTool[button]["tool"] = "Circle"
  1773.         tTool.selector = {["enabled"] = disabled}
  1774.         tTool.circle = {
  1775.           [1] = {},
  1776.           [2] = {}
  1777.         }
  1778.         tMenuBar.render("Color")
  1779.       end
  1780.     },
  1781.     [6] = {
  1782.       ["item"] = "Selector",
  1783.       ["func"] = function(button)
  1784.         tTool.selector = {["enabled"] = true}
  1785.         tTool[1]["tool"] = "Selector"
  1786.         tTool[2]["tool"] = "None"
  1787.         tMenuBar.render()
  1788.       end
  1789.     },
  1790.   },
  1791.   ["open"] = false, --currently open dropdown menu
  1792.   ["mainButton"] = " "..tText.menuButton.." ", --main menu button text
  1793.   ["Main"] = {},
  1794.   ["Size"] = {}
  1795. }
  1796. for i=1,9 do
  1797.   tMenuBar.Size[i] = {
  1798.     ["item"] = string.format(i),
  1799.     ["func"] = function(button)
  1800.       tTool[button]["size"] = i
  1801.       tMenuBar.render("Color")
  1802.     end
  1803.   }
  1804. end
  1805. tMenuBar.Color = {}
  1806. tMenuBar.SlotColors = {}
  1807. tMenuBar.Recolor = {}
  1808. for k,v in pairs(colors) do
  1809.   if type(v) == "number" then
  1810.     tMenuBar.Color[#tMenuBar.Color+1] = {
  1811.       ["item"] = k:gsub("(^.)(%u)", function(l) if l:match"%u" then return " "..l:lower() else return l:upper() end end),
  1812.       ["func"] = function(button)
  1813.         tTool[button]["color"] = tColorNumsRev[v]
  1814.         tMenuBar.render()
  1815.       end,
  1816.       ["color"] = v,
  1817.       ["textColor"] = tColors.menuText,
  1818.       ["num"] = tColorNumsRev[v]
  1819.     }
  1820.     tColorString[v] = k
  1821.     tMenuBar.SlotColors[#tMenuBar.SlotColors+1] = {
  1822.       ["item"] = tMenuBar.Color[#tMenuBar.Color]["item"],
  1823.       ["textColor"] = tColors.menuText,
  1824.       ["color"] = v,
  1825.       ["func"] = function()
  1826.         colorSlots(tColorNumsRev[v])
  1827.       end
  1828.     }
  1829.     tMenuBar.Recolor[#tMenuBar.Recolor+1] = {
  1830.       ["item"] = tMenuBar.Color[#tMenuBar.Color]["item"],
  1831.       ["textColor"] = tColors.menuText,
  1832.       ["color"] = v,
  1833.       ["func"] = function()
  1834.         local t1 = tTool.selector[1]
  1835.         local t2 = tTool.selector[2] or t1
  1836.         selectorRecolor(tColorNumsRev[v],t1.x,t1.z,t2.x,t2.z,tScroll.layer)
  1837.       end
  1838.     }
  1839.     if k == "white" or k == "yellow" then
  1840.       tMenuBar.Color[#tMenuBar.Color]["textColor"] = colors.black
  1841.       tMenuBar.SlotColors[#tMenuBar.SlotColors]["textColor"] = colors.black
  1842.       tMenuBar.Recolor[#tMenuBar.Recolor]["textColor"] = colors.black
  1843.     end
  1844.   end
  1845. end
  1846. tMenuBar.Color[#tMenuBar.Color+1] = {
  1847.   ["item"] = "Break",
  1848.   ["func"] = function(button)
  1849.     tTool[button]["color"] = "x"
  1850.       tMenuBar.render()
  1851.     end,
  1852.   ["color"] = colors.lightGray,
  1853.   ["textColor"] = colors.red,
  1854.   ["num"] = "x"
  1855. }
  1856. tColorString.x = "break"
  1857. tMenuBar.SlotColors[#tMenuBar.SlotColors+1] = {
  1858.   ["item"] = tMenuBar.Color[#tMenuBar.Color]["item"],
  1859.   ["textColor"] = tMenuBar.Color[#tMenuBar.Color]["textColor"],
  1860.   ["color"] = tMenuBar.Color[#tMenuBar.Color]["color"],
  1861.   ["func"] = function()
  1862.     colorSlots"x"
  1863.   end
  1864. }
  1865. tMenuBar.Recolor[#tMenuBar.Recolor+1] = {
  1866.   ["item"] = tMenuBar.Color[#tMenuBar.Color]["item"],
  1867.   ["textColor"] = tMenuBar.Color[#tMenuBar.Color]["textColor"],
  1868.   ["color"] = tMenuBar.Color[#tMenuBar.Color]["color"],
  1869.   ["func"] = function()
  1870.     local t1 = tTool.selector[1]
  1871.     local t2 = tTool.selector[2] or t1
  1872.     selectorRecolor("x",t1.x,t1.z,t2.x,t2.z,tScroll.layer)
  1873.   end
  1874. }
  1875. for k,v in pairs(tMenuBar) do
  1876.   --automatically makes rendering info for menus
  1877.   if k == "open"
  1878.   or k == "Main"
  1879.   or k == "mainButton"
  1880.   or type(v) == "function"
  1881.   or k == "Turtle" and not turtle then
  1882.     --skip string, open, and function keyes
  1883.     --will also skip turtle keyes if not running on a turtle
  1884.   else
  1885.     local longest = 0
  1886.     for i=1,#tMenuBar[k] do
  1887.       --find longest drop down selection for rendering purposes
  1888.       longest = math.max(longest,#tMenuBar[k][i]["item"])
  1889.     end
  1890.     tMenuBar[k]["length"] = math.max(longest,#k)+1
  1891.     tMenuBar[k]["startX"] = 1
  1892.     tMenuBar.Main.length = math.max(#k+1,tMenuBar.Main.length or 0)
  1893.     for i=1,#tMenuBar[k] do
  1894.       --equalize length of the dropdown menu names by adding spaces
  1895.       local item = tMenuBar[k][i]["item"]
  1896.       tMenuBar[k][i]["item"] = " "..item..string.rep(" ",math.max(0,tMenuBar[k]["length"]-#string.format(item)))
  1897.     end
  1898.     if k ~= "Size" and not k:lower():match"color" then
  1899.       table.insert(tMenuBar.Main,{
  1900.         ["item"] = " "..k,
  1901.         ["func"] = function()
  1902.           tMenuBar.render(k)
  1903.         end
  1904.       })
  1905.     end
  1906.   end
  1907. end
  1908. tMenuBar.Main.startX = 1
  1909. tMenuBar.Size.startX = 1
  1910. for i=1,#tMenuBar.Main do
  1911.   tMenuBar.Main[i]["item"] = tMenuBar.Main[i]["item"]..string.rep(" ",math.max(0,tMenuBar.Main.length-#tMenuBar.Main[i]["item"])).." >"
  1912. end
  1913.  
  1914. --[[
  1915. --------------------------------------------------------------------------------------------------------------
  1916. |                                              Program functions                                             |
  1917. --------------------------------------------------------------------------------------------------------------
  1918. --]]
  1919. function debug(tVar,time)
  1920.   term.setBackgroundColor(colors.black)
  1921.   term.setTextColor(colors.white)
  1922.   term.clear()
  1923.   term.setCursorPos(1,1)
  1924.   for k,v in pairs(tVar or {}) do
  1925.     print(k..": "..v)
  1926.   end
  1927.   local timer = os.startTimer(time or 5)
  1928.   while true do
  1929.     local event = os.pullEventRaw()
  1930.     if event == "key" or event == "timer" then
  1931.       return
  1932.     end
  1933.   end
  1934. end
  1935.  
  1936. function trimBlueprint(blueprint)
  1937.   --cleans blueprint files prior to saving, by removing empty x lines and trailing white spaces
  1938.   blueprint = blueprint or tBlueprint
  1939.   for layer = 1,#blueprint do
  1940.     for x = #blueprint[layer],1,-1 do
  1941.       local lastColor = 0
  1942.       for z = 1,#blueprint[layer][x] do
  1943.         local block = blueprint[layer][x][z] or " "
  1944.         if block ~= " " then
  1945.           lastColor = z+1
  1946.         end
  1947.       end
  1948.       if lastColor == 0 and #blueprint[layer] <= x then
  1949.         blueprint[layer][x] = nil
  1950.       else
  1951.         for i=lastColor,#blueprint[layer][x] do
  1952.           blueprint[layer][x][i] = nil
  1953.         end
  1954.       end
  1955.     end
  1956.   end
  1957. end
  1958.  
  1959. function fattenBlueprint(blueprint)
  1960.   --readds empty sapces to blueprint for flipping
  1961.   blueprint = blueprint or tBlueprint
  1962.   local largeX = 0
  1963.   local largeZ = 0
  1964.   for layer = 1,#blueprint do
  1965.     largeX = math.max(largeX,#blueprint[layer])
  1966.     for x = 1,#blueprint[layer] do
  1967.       largeZ = math.max(largeZ,#blueprint[layer][x])
  1968.     end
  1969.   end
  1970.   for layer=1,#blueprint do
  1971.     for x = 1,largeX do
  1972.       blueprint[layer][x] = blueprint[layer][x] or {}
  1973.       for z = 1,largeZ do
  1974.         blueprint[layer][x][z] = blueprint[layer][x][z] or " "
  1975.       end
  1976.     end
  1977.   end
  1978. end
  1979.  
  1980. function scan(x,z,layer,color)
  1981.   --Turtle function, scans a layer in the given measurements (x)x(z)
  1982.   --opionally loads it into the given layer, otherwise loads it into the first non-occupied layer
  1983.   layer = layer or tScroll.layer
  1984.   color = color or tTool[1]["color"]
  1985.   color = color:upper()
  1986.   local forward = cTurtle.dirStandardize"forward"
  1987.   local right = cTurtle.dirStandardize"right"
  1988.   tBlueprint[layer] = {}
  1989.   for ix=1,x do
  1990.     tBlueprint[layer][ix] = {}
  1991.     for iz=1,z do
  1992.       if turtle.detectDown() then
  1993.         tBlueprint[layer][ix][iz] = color
  1994.       else
  1995.         tBlueprint[layer][ix][iz] = " "
  1996.       end
  1997.       if iz < z then
  1998.         cTurtle.move(forward)
  1999.       end
  2000.     end
  2001.     if ix < x then
  2002.       cTurtle.move(right)
  2003.       forward = -forward
  2004.     end
  2005.   end
  2006.   renderLayer(tScroll.layer)
  2007. end
  2008.  
  2009. function colorCheck(from,to)
  2010.   --check layers for colors, returned as table[canvasColorCode] = colorString
  2011.   from = from or 1
  2012.   to = to or #tBlueprint
  2013.   local tColor = {}
  2014.   for il=from,to do
  2015.     for ix=1,#tBlueprint[il] do
  2016.       for iz=1,#tBlueprint[il][ix] do
  2017.         local color = tBlueprint[il][ix][iz] or " "
  2018.         if color ~= " " then
  2019.           if color:match(built) then
  2020.             color = color:lower()
  2021.           end
  2022.           if not tColor[color] then
  2023.             if color == "x" then
  2024.               tColor[color] = "break"
  2025.             else
  2026.               for k,v in pairs(colors) do
  2027.                 if type(v) == "number" then
  2028.                   if tColorNumsRev[v] == color then
  2029.                     tColor[color] = k
  2030.                     break
  2031.                   end
  2032.                 end
  2033.               end
  2034.             end
  2035.           end
  2036.         end
  2037.       end
  2038.     end
  2039.   end
  2040.   return tColor
  2041. end
  2042.  
  2043. function colorSlots(color)
  2044.   --edit color slots
  2045.   tColorSlots[color] = tColorSlots[color] or {}
  2046.   local from,to
  2047.   if tTerm.isColor then
  2048.     local button
  2049.     if color == "x" then
  2050.       if not tOngoing.breakMode then
  2051.         button,from = tBox.render(1,tTerm.x,"Input slot number for broken blocks. This slot will be used to pick up blocks and drop them instantly.",2,1,"%d","Cancel","Ok","Slot:",tColorSlots[color][1] or "15")
  2052.         to = from
  2053.       else
  2054.         return
  2055.       end
  2056.     else
  2057.       button,from,to = tBox.render(1,tTerm.x,"Input slot range for "..tColorString[tColorNums[color]]..".",2,2,"%d","Cancel","Ok","From:","To:",tColorSlots[color][1] or "1",tColorSlots[color][#tColorSlots[color]] or "16")
  2058.     end
  2059.     if button == "Cancel" then
  2060.       return false --cancel
  2061.     end
  2062.   else
  2063.     --non-color turtles
  2064.     term.setBackgroundColor(colors.black)
  2065.     term.setTextColor(colors.white)
  2066.     term.clear()
  2067.     term.setCursorPos(1,1)
  2068.     if color == "x" then
  2069.       if not tOngoing.breakMode then
  2070.         print("Input slot number for broken blocks. This slot will be used to pick up blocks and drop them instantly.")
  2071.         term.write"From: "
  2072.         from = tonumber(read())
  2073.         to = from
  2074.       else
  2075.         return
  2076.       end
  2077.     else
  2078.       print("Input slot range for "..tColorString[tColorNums[color]]..".")
  2079.       term.write"From: "
  2080.       local cursX,cursY = term.getCursorPos()
  2081.       term.setCursorPos(1,cursY+1)
  2082.       term.write"To: "
  2083.       term.setCursorPos(cursX,cursY)
  2084.       from = tonumber(read())
  2085.       term.setCursorPos(5,cursY+1)
  2086.       to = tonumber(read())
  2087.     end
  2088.   end
  2089.   if from > to
  2090.   or to > 16
  2091.   or from < 1 then
  2092.     if tTerm.isColor then
  2093.       tBox.render(1,tTerm.x,"Faulty slot range "..from.."-"..to.." given!")
  2094.     else
  2095.       print("Faulty slot range "..from.."-"..to.." given!")
  2096.     end
  2097.     return
  2098.   end
  2099.   tColorSlots[color] = {}
  2100.   while from <= to do
  2101.     table.insert(tColorSlots[color],from)
  2102.     from = from+1
  2103.   end
  2104.   tColorSlots[color]["sColor"] = tColorString[tColorNums[color]]
  2105.   return true
  2106. end
  2107.  
  2108. function selectColor(colorNum)
  2109.   --turtle function, checks the slot range for the given color for blocks.
  2110.   --if none is found,a refill from the player is requested.
  2111.   while true do
  2112.     for i=1,#tColorSlots[colorNum] do
  2113.       local slot = tColorSlots[colorNum][i]
  2114.       if not tOngoing.breakMode and turtle.getItemCount(slot) > 0
  2115.       or tOngoing.breakMode and turtle.getItemCount(slot) > 1 then
  2116.         turtle.select(slot)
  2117.         return true
  2118.       end
  2119.     end
  2120.     local enderChestTimer
  2121.     if tOngoing.enderChest then
  2122.       if cTurtle.enderRestock(tOngoing.enderChest,tColorSlots[colorNum],tColorSlots[colorNum]) then
  2123.         for i=1,#tColorSlots[colorNum] do
  2124.           local slot = tColorSlots[colorNum][i]
  2125.           if turtle.getItemCount(slot) > 0 then
  2126.             turtle.select(slot)
  2127.             return true
  2128.           end
  2129.         end
  2130.       else
  2131.         enderChestTimer = os.startTimer(tTimer.enderChest)
  2132.       end
  2133.     end
  2134.     if tTerm.isColor then
  2135.       renderLayer(tScroll.layer)
  2136.       tMenuBar.render()
  2137.       local button = tBox.render(1,tTerm.x,"More blocks required in the "..tColorSlots[colorNum]["sColor"].." slot range "..tColorSlots[colorNum][1].."-"..tColorSlots[colorNum][#tColorSlots[colorNum]]..".",2,0,".","Cancel","Ok")
  2138.       if button == "cancel" then
  2139.         return false --cancel
  2140.       end
  2141.     else
  2142.       --input on non-color turtle
  2143.       term.setBackgroundColor(colors.black)
  2144.       term.setTextColor(colors.white)
  2145.       term.clear()
  2146.       term.setCursorPos(1,1)
  2147.       print("More blocks required in the "..tColorSlots[colorNum]["sColor"].." slot range "..tColorSlots[colorNum][1].."-"..tColorSlots[colorNum][#tColorSlots[colorNum]]..[[.
  2148. Press enter to recheck.
  2149. Press backspace to quit build.]])
  2150.       local rednetTimer
  2151.       if modem then
  2152.         rednet.broadcast("More blocks required in the "..tColorSlots[colorNum]["sColor"].." slot range "..tColorSlots[colorNum][1].."-"..tColorSlots[colorNum][#tColorSlots[colorNum]]..[[.
  2153. X: ]]..cTurtle.tPos.x..[[
  2154. Y: ]]..cTurtle.tPos.y..[[
  2155. Z: ]]..cTurtle.tPos.z)
  2156.         rednetTimer = os.startTimer(tTimer.rednet)
  2157.       end
  2158.       while true do
  2159.         local tEvent = {os.pullEvent()}
  2160.         if tEvent[1] == "key" then
  2161.           local key = tEvent[2]
  2162.           if key == 28 then --enter
  2163.             break
  2164.           elseif key == 14 then --backspace
  2165.             return
  2166.           end
  2167.         elseif tEvent[1] == "rednet_message" then
  2168.           local message = tEvent[3]
  2169.           if message ==  "" then
  2170.           end
  2171.         elseif tEvent[1] == "timer" then
  2172.           local timerID = tEvent[2]
  2173.           if timerID == rednetTimer then
  2174.             rednet.broadcast("More blocks required in the "..tColorSlots[colorNum]["sColor"].." slot range "..tColorSlots[colorNum][1].."-"..tColorSlots[colorNum][#tColorSlots[colorNum]]..[[.
  2175. X: ]]..cTurtle.tPos.x..[[
  2176. Y: ]]..cTurtle.tPos.y..[[
  2177. Z: ]]..cTurtle.tPos.z)
  2178.           elseif timerID == enderChestTimer then
  2179.             break
  2180.           end
  2181.         end
  2182.       end
  2183.     end
  2184.   end
  2185. end
  2186.  
  2187. function checkUsage(startLayer,endLayer)
  2188.   --calculates fuel and block usage for the given layer range
  2189.   startLayer = startLayer or 1
  2190.   endLayer = endLayer or #tBlueprint
  2191.   local fuelUsage = 0
  2192.   local tColorBlocks = {}
  2193.   local ixFrom = 1
  2194.   local ixTo = #tBlueprint[startLayer]
  2195.   local ixAdd = 1
  2196.   local izFrom = 1
  2197.   local izTo = #tBlueprint[startLayer][1]
  2198.   local izAdd = 1
  2199.   local curX = 0
  2200.   local curY = 0
  2201.   local curZ = 0
  2202.   for layer=startLayer,endLayer do
  2203.     if layer%2 == 0 then
  2204.       ixFrom = #tBlueprint[layer]
  2205.       ixTo = 1
  2206.       ixAdd = -1
  2207.     else
  2208.       ixFrom = 1
  2209.       ixTo = #tBlueprint[layer]
  2210.       ixAdd = 1
  2211.     end
  2212.     for x=ixFrom,ixTo,ixAdd do
  2213.       if x%2 == 0 then
  2214.         izFrom = #tBlueprint[layer][x]
  2215.         izTo = 1
  2216.         izAdd = -1
  2217.       else
  2218.         izFrom = 1
  2219.         izTo = #tBlueprint[layer][x]
  2220.         izAdd = 1
  2221.       end
  2222.       for z=izFrom,izTo,izAdd do
  2223.         local block = tBlueprint[layer][x][z] or " "
  2224.         if block ~= " " then --checks for none white, racist turtle!
  2225.           tColorBlocks[block] = (tColorBlocks[block] or 0)+1
  2226.           if block:match(unbuilt) then --checks for built blocks
  2227.             fuelUsage = fuelUsage+math.abs(curX-x)+math.abs(curZ-z)
  2228.             curX = x
  2229.             curZ = z
  2230.           end
  2231.         end
  2232.       end
  2233.     end
  2234.     if layer < endLayer then
  2235.       if layer > curY then
  2236.         fuelUsage = fuelUsage+1
  2237.         curY = curY+1
  2238.       end
  2239.     end
  2240.   end
  2241.   return fuelUsage,tColorBlocks
  2242. end
  2243.  
  2244. function buildBlueprint(startLayer,endLayer,recovery)
  2245.   --turtle function, build the given layers
  2246.   --builds all layers if none is given
  2247.   startLayer = startLayer or 1
  2248.   endLayer = endLayer or #tBlueprint
  2249.   local colorTable = colorCheck(startLayer,endLayer)
  2250.   for k,v in pairs(colorTable) do
  2251.     if not tColorSlots[k] then
  2252.       if not colorSlots(k) then
  2253.         return
  2254.       end
  2255.     end
  2256.   end
  2257.   tOngoing.blueprint = tFile.curBlueprint
  2258.   tOngoing.startLayer = startLayer
  2259.   tOngoing.endLayer = endLayer
  2260.   tOngoing.enderChest = tOngoing.enderChest or false
  2261.   cTurtle.tSettings.enderFuel = tOngoing.enderChest
  2262.   --saves tOngoing
  2263.   local file = fs.open(tFile.ongoingBuild,"w")
  2264.   file.writeLine(textutils.serialize(tOngoing))
  2265.   file.close()
  2266.   if tOrigin.x and not recovery then
  2267.     if tOrigin.x ~= cTurtle.tPos.x
  2268.     or tOrigin.y ~= cTurtle.tPos.y
  2269.     or tOrigin.z ~= cTurtle.tPos.z then
  2270.       local button
  2271.       if tTerm.isColor then
  2272.         button = tBox.render(1,tTerm.x,"Use current build origin point|X: "..tOrigin.x.."|Y: "..tOrigin.y.."|Z: "..tOrigin.z.."|X dir: "..tOrigin.xDir.."|Z dir: "..tOrigin.zDir.."|Y dir: "..tOrigin.yDir.."|Or use current location?",3,0,".","Cancel","Current","Cur. loc")
  2273.       else
  2274.         button = noColorInput("Use current build origin point\nX: "..tOrigin.x.."\nY: "..tOrigin.y.."\nZ: "..tOrigin.z.."\nX dir: "..tOrigin.xDir.."\nZ dir: "..tOrigin.zDir.."\nY dir: "..tOrigin.yDir.."\nOr use current location?","Cancel","Current orgin","Cur. loc")
  2275.       end
  2276.       if button == "Cancel" then
  2277.         return
  2278.       elseif button == "Cur. loc" then
  2279.         tOrigin.x = cTurtle.tPos.x
  2280.         tOrigin.y = cTurtle.tPos.y
  2281.         tOrigin.z = cTurtle.tPos.z
  2282.       else
  2283.         cTurtle.moveTo(tOrigin.y,"y")
  2284.       end
  2285.     end
  2286.   elseif recovery then
  2287.     --skip
  2288.   else
  2289.     tOrigin.x = cTurtle.tPos.x
  2290.     tOrigin.y = cTurtle.tPos.y
  2291.     tOrigin.z = cTurtle.tPos.z
  2292.     tOrigin.xDir = "+"
  2293.     tOrigin.zDir = "+"
  2294.     tOrigin.yDir = "+"
  2295.   end
  2296.   saveBlueprint(tFile.curBlueprint)
  2297.   local ixFrom = 1
  2298.   local ixTo = #tBlueprint[startLayer]
  2299.   local ixAdd = 1
  2300.   local izFrom = 1
  2301.   local izTo = #tBlueprint[startLayer][1]
  2302.   local izAdd = 1
  2303.   local curSlot = 1
  2304.   local iLayerFrom
  2305.   local iLayerTo
  2306.   local iLayerAdd
  2307.   local placeFunc
  2308.   local compareFunc
  2309.   local digFunc
  2310.   if tOrigin.yDir == "-" then
  2311.     iLayerFrom = endLayer
  2312.     iLayerTo = startLayer
  2313.     iLayerAdd = -1
  2314.     down = true
  2315.     placeFunc = turtle.placeUp
  2316.     compareFunc = turtle.compareUp
  2317.     digFunc = turtle.digUp
  2318.   else
  2319.     iLayerFrom = startLayer
  2320.     iLayerTo = endLayer
  2321.     iLayerAdd = 1
  2322.     down = false
  2323.     placeFunc = turtle.placeDown
  2324.     compareFunc = turtle.compareDown
  2325.     digFunc = turtle.digDown
  2326.   end
  2327.   for layer=iLayerFrom,iLayerTo,iLayerAdd do
  2328.     if layer%2 == 0 then
  2329.       ixFrom = #tBlueprint[layer]
  2330.       ixTo = 1
  2331.       ixAdd = -1
  2332.     else
  2333.       ixFrom = 1
  2334.       ixTo = #tBlueprint[layer]
  2335.       ixAdd = 1
  2336.     end
  2337.     for x=ixFrom,ixTo,ixAdd do
  2338.       if x%2 == 0 then
  2339.         izFrom = #tBlueprint[layer][x]
  2340.         izTo = 1
  2341.         izAdd = -1
  2342.       else
  2343.         izFrom = 0
  2344.         izTo = #tBlueprint[layer][x]
  2345.         izAdd = 1
  2346.       end
  2347.       for z=izFrom,izTo,izAdd do
  2348.         local block = tBlueprint[layer][x][z] or " "
  2349.         if block ~= " " --checks for none white, racist turtle!
  2350.         and block:match(unbuilt) then --checks for built blocks
  2351.           if tOrigin.xDir == "-" then
  2352.             cTurtle.moveTo(tOrigin.x-x+1,"x",tOngoing.breakMode)
  2353.           else
  2354.             cTurtle.moveTo(tOrigin.x+x-1,"x",tOngoing.breakMode)
  2355.           end
  2356.           if tOrigin.zDir == "-" then
  2357.             cTurtle.moveTo(tOrigin.z-z+1,"z",tOngoing.breakMode)
  2358.           else
  2359.             cTurtle.moveTo(tOrigin.z+z-1,"z",tOngoing.breakMode)
  2360.           end
  2361.           if block == "x" then
  2362.             if not tOngoing.breakMode then
  2363.               turtle.select(tColorSlots.x[1])
  2364.             end
  2365.             while turtle.detectDown() do
  2366.               turtle.digDown()
  2367.               if not tOngoing.breakMode then
  2368.                 turtle.dropDown(64)
  2369.               end
  2370.             end
  2371.           else
  2372.             if not selectColor(block) then
  2373.               return --cancel
  2374.             end
  2375.             if not compareFunc() then
  2376.               while not placeFunc() do
  2377.                 digFunc()
  2378.               end
  2379.             end
  2380.           end
  2381.           tBlueprint[layer][x][z] = block:upper() --marks this block as built
  2382.           saveBlueprint(tFile.curBlueprint)
  2383.         end
  2384.       end
  2385.     end
  2386.     if not down and layer < iLayerTo then
  2387.       if tOrigin.y+layer > cTurtle.tPos.y then
  2388.         cTurtle.moveTo(tOrigin.y+layer,"y",tOngoing.breakMode)
  2389.       end
  2390.     elseif down and layer > iLayerTo then
  2391.       if tOrigin.y+layer-iLayerFrom-1 < cTurtle.tPos.y then
  2392.         cTurtle.moveTo(tOrigin.y+layer-iLayerFrom-1,"y",tOngoing.breakMode)
  2393.       end
  2394.     else
  2395.       cTurtle.moveTo(tOrigin.x,"x")
  2396.       cTurtle.moveTo(tOrigin.z,"z")
  2397.       cTurtle.moveTo(tOrigin.y,"y")
  2398.     end
  2399.   end
  2400.   fs.delete(tFile.ongoingBuild) --clears ongoing build
  2401.   if tTerm.isColor then
  2402.     tMenuBar.render()
  2403.     renderLayer(tScroll.layer)
  2404.   end
  2405. end
  2406.  
  2407. function createLayer(x,z,layerNum,overwrite)
  2408.   --simple layer creation function
  2409.   if overwrite then
  2410.     tBlueprint[layerNum or #tBlueprint+1] = {}
  2411.   else
  2412.     table.insert(tBlueprint,layerNum or #tBlueprint+1,{})
  2413.   end
  2414.   x = math.max(x or 0,tTerm.xCanvas)
  2415.   z = math.max(z or 0,tTerm.zCanvas)
  2416.   for ix=1,x do
  2417.     tBlueprint[layerNum][ix] = {}
  2418.     for iz=1,z do
  2419.       tBlueprint[layerNum][ix][iz] = " "
  2420.     end
  2421.   end
  2422. end
  2423.  
  2424. function copyLayer(layer)
  2425.   --creates a copy layer
  2426.   local layerCopy = {}
  2427.   for ix=1,#tBlueprint[layer] do
  2428.     layerCopy[ix] = {}
  2429.     for iz=1,#tBlueprint[layer][ix] do
  2430.       layerCopy[ix][iz] = tBlueprint[tScroll.layer][ix][iz] or " "
  2431.     end
  2432.   end
  2433.   return layerCopy
  2434. end
  2435.  
  2436. function flipLayer(layer,direction)
  2437.   --flips layer vertically or horizontally
  2438.   local layerFlipped = {}
  2439.   if direction == "x" then
  2440.     for ix=#layer,1,-1 do
  2441.       layerFlipped[#layerFlipped+1] = {}
  2442.       for iz=1,#layer[ix] do
  2443.         layerFlipped[#layerFlipped][iz] = layer[ix][iz] or " "
  2444.       end
  2445.     end
  2446.   else
  2447.     for ix=1,#layer do
  2448.       layerFlipped[ix] = {}
  2449.       for iz=#layer[ix],1,-1 do
  2450.         layerFlipped[ix][#layerFlipped[ix]+1] = layer[ix][iz] or " "
  2451.       end
  2452.     end
  2453.   end
  2454.   return layerFlipped
  2455. end
  2456.  
  2457. function layerPaste(layer,num,overwrite)
  2458.   --pastes layer into tBlueprint, this is used to avoid recursive tables
  2459.   if overwrite then
  2460.     tBlueprint[num] = {}
  2461.   else
  2462.     table.insert(tBlueprint,num,{})
  2463.   end
  2464.   for ix=1,#layer do
  2465.     tBlueprint[num][ix] = {}
  2466.     for iz=1,#layer[ix] do
  2467.       tBlueprint[num][ix][iz] = layer[ix][iz]
  2468.     end
  2469.   end
  2470. end
  2471.  
  2472. function layerCombine(from,to,recolor)
  2473.   --combines layers in the range (from) (to), optionally gives them each an unique color
  2474.   local layerComb = {}
  2475.   for i=from,to do
  2476.     local color = i-from+1
  2477.     while color > 15 do
  2478.       color = color-15
  2479.     end
  2480.     if color > 9 then
  2481.       if color-9 == 1 then
  2482.         color = "a"
  2483.       elseif color-9 == 2 then
  2484.         color = "b"
  2485.       elseif color-9 == 3 then
  2486.         color = "c"
  2487.       elseif color-9 == 4 then
  2488.         color = "d"
  2489.       elseif color-9 == 5 then
  2490.         color = "e"
  2491.       elseif color-9 == 6 then
  2492.         color = "f"
  2493.       end
  2494.     else
  2495.       color = string.format(color)
  2496.     end
  2497.     for ix=1,#tBlueprint[i] do
  2498.       layerComb[ix] = layerComb[ix] or {}
  2499.       for iz=1,#tBlueprint[i][ix] do
  2500.         if tBlueprint[i][ix][iz] > " " then
  2501.           if recolor then
  2502.             layerComb[ix][iz] = color
  2503.           else
  2504.             layerComb[ix][iz] = tBlueprint[i][ix][iz]
  2505.           end
  2506.         else
  2507.           layerComb[ix][iz] = layerComb[ix][iz] or " "
  2508.         end
  2509.       end
  2510.     end
  2511.   end
  2512.   return layerComb
  2513. end
  2514.      
  2515. function renderLayer(layer)
  2516.   --Renders the give layer on the canvas
  2517.   --if none, renders currently viewed layer
  2518.   layer = layer or tScroll.layer
  2519.   if not tBlueprint[layer] then
  2520.     createLayer(tTerm.xCanvas,tTerm.zCanvas,layer,true)
  2521.   end
  2522.   local canvasX = tTerm.xCanvas
  2523.   local canvasZ = tTerm.zCanvas
  2524.   local gridLine = "1234567890"
  2525.   if tTerm.grid then
  2526.     --terminal grid line rendering
  2527.     canvasX = canvasX-1
  2528.     canvasZ = canvasZ-1
  2529.     term.setCursorPos(1,tTerm.y)
  2530.     term.setBackgroundColor(tColors.gridBorder)
  2531.     term.setTextColor(tColors.gridBorderText)
  2532.     term.write(gridLine:rep(math.ceil(canvasX/#gridLine)).." ")
  2533.     gridLine = 1
  2534.     for i=2,tTerm.y-1 do
  2535.       term.setCursorPos(tTerm.x,i)
  2536.       term.write(gridLine)
  2537.       gridLine = gridLine+1
  2538.       if gridLine > 9 then
  2539.         gridLine = 0
  2540.       end
  2541.     end
  2542.     for im=1,#tMon do
  2543.       --monitor gird line rendering
  2544.       gridLine = "1234567890"
  2545.       tMon[im]["setCursorPos"](1,tMon[im]["y"])
  2546.       tMon[im]["setBackgroundColor"](tColors.gridBorder)
  2547.       tMon[im]["setTextColor"](tColors.gridBorderText)
  2548.       tMon[im]["write"](gridLine:rep(math.ceil(tMon[im]["xCanvas"]/#gridLine)).." ")
  2549.       gridLine = 1
  2550.       for iy=1,tMon[im]["y"]-1 do
  2551.         tMon[im]["setCursorPos"](tMon[im]["x"],iy)
  2552.         tMon[im]["write"](gridLine)
  2553.         gridLine = gridLine+1
  2554.         if gridLine > 9 then
  2555.           gridLine = 0
  2556.         end
  2557.       end
  2558.     end
  2559.   end
  2560.   for x=1+tScroll.x.value,canvasX+tScroll.x.value do -- render current layer on terminal
  2561.     tBlueprint[layer][x] = tBlueprint[layer][x] or {}
  2562.     if tTerm.bgLayer then
  2563.       tTerm.bgLayer[x] = tTerm.bgLayer[x] or {}
  2564.     end
  2565.     for z=1+tScroll.y.value,canvasZ+tScroll.y.value do
  2566.       tBlueprint[layer][x][z] = tBlueprint[layer][x][z] or " "
  2567.       local color = tBlueprint[layer][x][z]
  2568.       local bgColor
  2569.       if tTerm.bgLayer then
  2570.         bgColor = tTerm.bgLayer[x][z] or " "
  2571.       end
  2572.       if tTerm.grid then
  2573.         --grid mode
  2574.         if color == " " then
  2575.           term.setTextColor(tColors.gridBackgroundText)
  2576.           if bgColor and bgColor ~= " " then
  2577.             --layer background
  2578.             term.setBackgroundColor(tColors.backgroundLayer)
  2579.           else
  2580.             term.setBackgroundColor(tColors.gridBackground)
  2581.           end
  2582.         elseif tTerm.built and color:match(built) then
  2583.           term.setTextColor(tColors.builtMark)
  2584.           term.setBackgroundColor(tColorNums[color])
  2585.         else
  2586.           term.setTextColor(tColors.gridBackgroundText)
  2587.           term.setBackgroundColor(tColorNums[color])
  2588.         end
  2589.         term.setCursorPos(x-tScroll.x.value,z-tScroll.y.value+1)
  2590.         if tTerm.built and color:match(built) and color ~= "X" then
  2591.           --built render mode
  2592.           term.write"B"
  2593.         elseif color == "x" then
  2594.           term.setTextColor(colors.lightGray)
  2595.           term.write"X"
  2596.         else
  2597.           term.write"+"
  2598.         end
  2599.       else
  2600.       --non grid mode
  2601.         if color == " " and bgColor and bgColor ~= " " then
  2602.           --layer background
  2603.           term.setBackgroundColor(tColors.backgroundLayer)
  2604.         else
  2605.           term.setBackgroundColor(tColorNums[color])
  2606.         end
  2607.         term.setCursorPos(x-tScroll.x.value,z-tScroll.y.value+1)
  2608.         if tTerm.built and color:match(built) and color ~= "X" then
  2609.           term.setTextColor(tColors.builtMark)
  2610.           term.write"B"
  2611.         elseif color == "x" then
  2612.           term.setTextColor(colors.lightGray)
  2613.           term.write"X"
  2614.         else
  2615.           term.write" "
  2616.         end
  2617.       end
  2618.     end
  2619.   end
  2620.   for i=1,#tMon do
  2621.     local xCanvas = tMon[i]["xCanvas"]
  2622.     local zCanvas = tMon[i]["zCanvas"]
  2623.     if tTerm.grid then
  2624.       --grid mode prep
  2625.       xCanvas = xCanvas-1
  2626.       zCanvas = zCanvas-1
  2627.       tMon[i]["setTextColor"](tColors.gridBackgroundText)
  2628.     end
  2629.     for x=1+tScroll.x.value,xCanvas+tScroll.x.value do
  2630.       tBlueprint[layer][x] = tBlueprint[layer][x] or {}
  2631.       for z=1+tScroll.y.value,zCanvas+tScroll.y.value do
  2632.         tBlueprint[layer][x][z] = tBlueprint[layer][x][z] or " "
  2633.         if tTerm.grid then
  2634.         --grid mode
  2635.           local marker = "+"
  2636.           if tBlueprint[layer][x][z] == " " then
  2637.             if tTerm.bgLayer and tTerm.bgLayer[x][z] ~= " " then
  2638.               --layer background
  2639.               tMon[i]["setBackgroundColor"](tColors.backgroundLayer)
  2640.             else
  2641.               tMon[i]["setBackgroundColor"](tColors.gridBackground)
  2642.             end
  2643.           else
  2644.             tMon[i]["setBackgroundColor"](tColorNums[tBlueprint[layer][x][z]])
  2645.             marker = "X"
  2646.           end
  2647.           tMon[i]["setCursorPos"](x-tScroll.x.value,z-tScroll.y.value)
  2648.           tMon[i]["write"](marker)
  2649.         else
  2650.           --non grid mode
  2651.           local color = tBlueprint[layer][x][z]
  2652.           if color == " " and tTerm.bgLayer and tTerm.bgLayer[x][z] ~= " " then
  2653.             --layer background
  2654.             color = tColors.backgroundLayer
  2655.           else
  2656.             color = tColorNums[color]
  2657.           end
  2658.           paintutils.drawPixel(x-tScroll.x.value,z-tScroll.y.value,color,true)
  2659.         end
  2660.       end
  2661.     end
  2662.   end
  2663.   selectorRender()
  2664.   circleRender()
  2665.   --update menuBar info
  2666.   tMenuBar.infoString = "X:"..tScroll.x.value.." Y:"..layer.." Z:"..tScroll.y.value
  2667.   paintutils.drawLine(tMenuBar.Main.length+2,1,tTerm.x,1,tColors.menuBar)
  2668.   term.setBackgroundColor(tColors.menuBar)
  2669.   term.setTextColor(tColors.infoText)
  2670.   term.setCursorPos(tTerm.x-#tMenuBar.infoString,1)
  2671.   term.write(tMenuBar.infoString)
  2672.   term.setCursorPos(#tMenuBar.mainButton+2,1)
  2673.   term.setBackgroundColor(tColors.menuBar)
  2674.   term.write"1: "
  2675.   if tColorNums[tTool[1]["color"]] ~= tColors.menuBar and tTool[1]["tool"] ~= "Selector" then
  2676.     term.setTextColor(tColorNums[tTool[1]["color"]])
  2677.   end
  2678.   term.write(tTool[1]["tool"])
  2679.   term.setTextColor(tColors.infoText)
  2680.   if tTool.selector.enabled then
  2681.     return
  2682.   elseif tTool[1]["tool"] ~= "Dragger"
  2683.   and tTool[1]["tool"] ~= "Fill"
  2684.   and tTool[1]["tool"] ~= "Circle" then
  2685.     term.write(":"..tTool[1]["size"].." 2: ")
  2686.   else
  2687.     term.write(" 2: ")
  2688.   end
  2689.   if tColorNums[tTool[2]["color"]] ~= tColors.menuBar then
  2690.     term.setTextColor(tColorNums[tTool[2]["color"]])
  2691.   end
  2692.   term.write(tTool[2]["tool"])
  2693.   if tTool[2]["tool"] ~= "Dragger"
  2694.   and tTool[2]["tool"] ~= "Fill"
  2695.   and tTool[2]["tool"] ~= "Circle" then
  2696.   term.setTextColor(tColors.infoText)
  2697.     term.write(":"..tTool[2]["size"])
  2698.   end
  2699. end
  2700.  
  2701. function renderPoint(x,z,color,replace)
  2702.   --base rendering functions, this is used for everything except full canvas rendering
  2703.   local canvasX = tTerm.xCanvas
  2704.   local canvasZ = tTerm.zCanvas
  2705.   local marker = " "
  2706.   if tTerm.grid then
  2707.     canvasX = canvasX-1
  2708.     canvasZ = canvasZ-1
  2709.     term.setTextColor(tColors.gridBackgroundText)
  2710.     marker = "+"
  2711.   end
  2712.   if x < 1
  2713.   or z < 1 then
  2714.     return
  2715.   end
  2716.   replace = replace or tTool.overwrite
  2717.   local layer = tScroll.layer
  2718.   if tTool.built and color ~= " " and color ~= "x" then --built mode
  2719.     color = color:upper()
  2720.   end
  2721.   if tTerm.built and color:match(built) and color ~= "X" then
  2722.     term.setTextColor(tColors.builtMark)
  2723.     marker = "B"
  2724.   elseif color == "x" then
  2725.     term.setTextColor(colors.lightGray)
  2726.     marker = "X"
  2727.   end
  2728.   xP = x+tScroll.x.value
  2729.   zP = z+tScroll.y.value
  2730.   tBlueprint[layer][xP] = tBlueprint[layer][xP] or {}
  2731.   tBlueprint[layer][xP][zP] = tBlueprint[layer][xP][zP] or " "
  2732.   if replace --overwrite mode enabled
  2733.   or tBlueprint[layer][xP][zP] == " " --or point color is white
  2734.   or color == " " then --or current color is white
  2735.     tBlueprint[layer][xP][zP] = color or tBlueprint[layer][xP][zP]
  2736.     if tTerm.grid then
  2737.       if color == " " then
  2738.         local color = tColors.gridBackground
  2739.         if tTerm.bgLayer and tTerm.bgLayer[xP][zP] ~= " " then
  2740.           color = tColors.backgroundLayer
  2741.           marker = " "
  2742.         end
  2743.         term.setBackgroundColor(color)
  2744.         for i=1,#tMon do
  2745.           tMon[i]["setBackgroundColor"](color)
  2746.         end
  2747.       else
  2748.         term.setBackgroundColor(tColorNums[color])
  2749.         for i=1,#tMon do
  2750.           tMon[i]["setBackgroundColor"](tColorNums[color])
  2751.         end
  2752.       end
  2753.       if x <= tTerm.xCanvas-1
  2754.       and z <= tTerm.zCanvas-1 then
  2755.         term.setCursorPos(x,z+1)
  2756.         term.write(marker)
  2757.       end
  2758.       for i=1,#tMon do
  2759.         if x <= tMon[i]["xCanvas"]-1
  2760.         and z <= tMon[i]["zCanvas"]-1 then
  2761.           tMon[i]["setCursorPos"](x,z)
  2762.           tMon[i]["write"](marker)
  2763.         end
  2764.       end
  2765.     else
  2766.       if color == " " and tTerm.bgLayer and tTerm.bgLayer[xP][zP] ~= " " then
  2767.         color = tColors.backgroundLayer
  2768.       else
  2769.         color = tColorNums[color] or tColorNums[tBlueprint[layer][xP][zP]]
  2770.       end
  2771.       term.setBackgroundColor(color)
  2772.       term.setCursorPos(x,z+1)
  2773.       term.write(marker)
  2774.       for i=1,#tMon do
  2775.         tMon[i]["setBackgroundColor"](color)
  2776.         tMon[i]["setCursorPos"](x,z)
  2777.         tMon[i]["write"](marker)
  2778.       end
  2779.     end
  2780.   end
  2781. end
  2782.  
  2783. function renderLine(startX,endX,z,color)
  2784.   --renders horizontinal canvas lines
  2785.   for i=startX,endX do
  2786.     renderPoint(i,z,color)
  2787.   end
  2788. end
  2789.  
  2790. local function renderWall(startZ,endZ,x,color)
  2791.   --renders vertical canvas lines
  2792.   for i=startZ,endZ do
  2793.     renderPoint(x,i,color)
  2794.   end
  2795. end
  2796.  
  2797. function saveBlueprint(fileName)
  2798.   --saves the blueprint to file
  2799.   trimBlueprint(tBlueprint)
  2800.   local file = fs.open(fileName,"w")
  2801.   file.writeLine("Blueprint file for CometWolf's Turtle Architect. Pastebin: "..tPaste.program)
  2802.   for layer=1,#tBlueprint do
  2803.     file.writeLine("Layer "..layer.." :")
  2804.     for x=1,#tBlueprint[layer] do
  2805.       local line = "X"..x..string.rep(" ",#string.format(#tBlueprint[layer])-#string.format(x))..": "
  2806.       for z=1,#tBlueprint[layer][x] do
  2807.         local block = tBlueprint[layer][x][z] or " "
  2808.         line = line..block
  2809.       end
  2810.       file.writeLine(line)
  2811.     end
  2812.   end
  2813.   if tColorSlots then
  2814.     file.writeLine"Color slots table:"
  2815.     file.writeLine(textutils.serialize(tColorSlots))
  2816.   end
  2817.   if tOrigin then
  2818.     file.writeLine"Build origin data:"
  2819.     file.writeLine(textutils.serialize(tOrigin))
  2820.   end
  2821.   file.close()
  2822. end
  2823.  
  2824. function loadBlueprint(fileName)
  2825.   --loads blueprint from file
  2826.   local file = fs.open(fileName,"r")
  2827.   local tRetBlueprint = {}
  2828.   local tRetColors
  2829.   local tRetOrigin
  2830.   if file.readLine() == "Blueprint file for CometWolf's Turtle Architect. Pastebin: "..tPaste.program then
  2831.     local line = file.readLine()
  2832.     while line:match"Layer %d+" do
  2833.       local layer = tonumber(line:match"%d+")
  2834.       tRetBlueprint[layer] = {}
  2835.       line = file.readLine()
  2836.       while line:match"X%d+" do
  2837.         local x = tonumber(line:match"X(%d+)")
  2838.         line = line:match"X%d+%s?:%s(.+)" or ""
  2839.         tRetBlueprint[layer][x] = {}
  2840.         for block in line:gmatch"." do
  2841.           tRetBlueprint[layer][x][#tRetBlueprint[layer][x]+1] = string.format(block)
  2842.         end
  2843.         line = file.readLine()
  2844.       end
  2845.     end
  2846.     if line:match"Color slots table:" then
  2847.       tRetColors = textutils.unserialize(file.readLine())
  2848.       line = file.readLine() or ""
  2849.     end
  2850.     if line:match"Build origin data:" then
  2851.       tRetOrigin = textutils.unserialize(file.readLine())
  2852.     end
  2853.   end
  2854.   file.close()
  2855.   if #tRetBlueprint <= 0 then
  2856.     tRetBlueprint = false
  2857.   end
  2858.   return tRetBlueprint, tRetColors or {}, tRetOrigin or {}
  2859. end
  2860.  
  2861. function loadOldBlueprint(fileName)
  2862.   --loads blueprint from file
  2863.   local file = fs.open(fileName,"r")
  2864.   local tRetBlueprint
  2865.   local tRetColors
  2866.   if file.readLine() == "Blueprint file for CometWolf's Turtle Architect. Pastebin: "..tPaste.program then
  2867.     tRetBlueprint = textutils.unserialize(file.readLine())
  2868.     tRetColors = file.readLine()
  2869.     if tRetColors then
  2870.       tRetColors = textutils.unserialize(tRetColors)
  2871.     end
  2872.   end
  2873.   file.close()
  2874.   return tRetBlueprint or false, tRetColors or false
  2875. end
  2876.  
  2877. function noColorInput(text,...)
  2878.   term.clear()
  2879.   term.setCursorPos(1,1)
  2880.   print(text)
  2881.   local cursX,cursY = term.getCursorPos()
  2882.   local button = 1
  2883.   local tButtons = {...}
  2884.   while true do
  2885.     for i=1,#tButtons do
  2886.       local menuText = tButtons[i]
  2887.       if button == i then
  2888.         menuText = "["..menuText.."]"
  2889.       end
  2890.       term.setCursorPos(1,cursY+i-1)
  2891.       term.clearLine()
  2892.       term.setCursorPos(tTerm.xMid-math.floor(#menuText/2),cursY+i-1)
  2893.       term.write(menuText)
  2894.     end
  2895.     local _e,key = os.pullEvent"key"
  2896.     if key == 28 then --enter
  2897.       return tButtons[button]
  2898.     elseif key == 208 then --down arrow
  2899.       button = button+1
  2900.     elseif key == 200 then --up arrow
  2901.       button = button-1
  2902.     end
  2903.     if button > #tButtons then
  2904.       button = 1
  2905.     elseif button < 1 then
  2906.       button = #tButtons
  2907.     end
  2908.   end
  2909. end
  2910.  
  2911. function tMenuBar.render(menu)
  2912.   --renders top bar menu, and dropdown (menu)
  2913.   local func
  2914.   if type(menu) == "function" then
  2915.     func = menu
  2916.     menu = nil
  2917.   end
  2918.   renderLayer(tScroll.layer)
  2919.   tMenuBar.infoString = "X:"..tScroll.x.value.." Y:"..tScroll.layer.." Z:"..tScroll.y.value
  2920.   paintutils.drawLine(1,1,tTerm.x,1,tColors.menuBar)
  2921.   term.setBackgroundColor(tColors.menuBar)
  2922.   term.setTextColor(tColors.infoText)
  2923.   term.setCursorPos(tTerm.x-#tMenuBar.infoString,1)
  2924.   term.write(tMenuBar.infoString)
  2925.   if not menu then
  2926.     tMenuBar.open = false
  2927.     term.setTextColor(tColors.menuText)
  2928.     term.setBackgroundColor(tColors.menuButton)
  2929.     term.setCursorPos(1,1)
  2930.     term.write(" "..tText.menuButton.." ")
  2931.     tMenuBar.mainButton = " "..tText.menuButton.." "
  2932.   else
  2933.     --dropdown menu
  2934.     tMenuBar.open = menu
  2935.     term.setCursorPos(1,1)
  2936.     term.setBackgroundColor(tColors.menuDropDownPri)
  2937.     local menuString = "["..menu..string.rep(" ",math.max(0,tMenuBar.Main.length-#menu-1)).."]"
  2938.     term.write(menuString)
  2939.     tMenuBar.mainButton = menuString
  2940.     for i=1,#tMenuBar[menu] do
  2941.       if tMenuBar[menu][i]["color"] then
  2942.         term.setBackgroundColor(tMenuBar[menu][i]["color"])
  2943.         term.setTextColor(tMenuBar[menu][i]["textColor"])
  2944.       elseif i%2 == 0 then
  2945.         term.setBackgroundColor(tColors.menuDropDownPri)
  2946.       else
  2947.         term.setBackgroundColor(tColors.menuDropDownSec)
  2948.       end
  2949.       local cursX,cursY = tMenuBar[menu]["startX"], i+1
  2950.       if cursY > tTerm.y then
  2951.         cursY = cursY-(tTerm.y-1)
  2952.         cursX = #tMenuBar[menu][i]["item"]+1
  2953.       end
  2954.       term.setCursorPos(cursX,cursY)
  2955.       term.write(tMenuBar[menu][i]["item"])
  2956.     end
  2957.   end
  2958.   --menu bar info
  2959.   term.setTextColor(tColors.infoText)
  2960.   term.setCursorPos(#tMenuBar.mainButton+2,1)
  2961.   term.setBackgroundColor(tColors.menuBar)
  2962.   term.write"1: "
  2963.   if tColorNums[tTool[1]["color"]] ~= tColors.menuBar and tTool[1]["tool"] ~= "Selector" then
  2964.     term.setTextColor(tColorNums[tTool[1]["color"]])
  2965.   end
  2966.   term.write(tTool[1]["tool"])
  2967.   term.setTextColor(tColors.infoText)
  2968.   if tTool.selector.enabled then
  2969.     return
  2970.   elseif tTool[1]["tool"] ~= "Dragger"
  2971.   and tTool[1]["tool"] ~= "Fill"
  2972.   and tTool[1]["tool"] ~= "Circle" then
  2973.     term.write(":"..tTool[1]["size"].." 2: ")
  2974.   else
  2975.     term.write(" 2: ")
  2976.   end
  2977.   if tColorNums[tTool[2]["color"]] ~= tColors.menuBar then
  2978.     term.setTextColor(tColorNums[tTool[2]["color"]])
  2979.   end
  2980.   term.write(tTool[2]["tool"])
  2981.   if tTool[2]["tool"] ~= "Dragger"
  2982.   and tTool[2]["tool"] ~= "Fill"
  2983.   and tTool[2]["tool"] ~= "Selector"
  2984.   and tTool[2]["tool"] ~= "Circle" then
  2985.   term.setTextColor(tColors.infoText)
  2986.     term.write(":"..tTool[2]["size"])
  2987.   end
  2988.   if func then
  2989.     func()
  2990.   end
  2991. end
  2992.  
  2993. function tContextMenu.render(x,y)
  2994.   renderLayer(tScroll.layer)
  2995.   x = math.min(x,tTerm.x-tContextMenu.length)
  2996.   y = math.min(y,tTerm.y-#tContextMenu+1)
  2997.   for i=1,#tContextMenu do
  2998.     term.setCursorPos(x,y+i-1)
  2999.     if i%2 == 0 then
  3000.       term.setBackgroundColor(tColors.contextMenuPri)
  3001.     else
  3002.       term.setBackgroundColor(tColors.contextMenuSec)
  3003.     end
  3004.     if tContextMenu[i]["item"]:match"Paste" then
  3005.       if not tTool.selector.copy then
  3006.         term.setTextColor(colors.lightGray)
  3007.       else
  3008.         term.setTextColor(tColors.contextMenuText)
  3009.       end
  3010.     elseif tContextMenu[i]["item"]:match"Copy"
  3011.     or tContextMenu[i]["item"]:match"Cut"
  3012.     or tContextMenu[i]["item"]:match"Select"
  3013.     or tContextMenu[i]["item"]:match"Delete"
  3014.     or tContextMenu[i]["item"]:match"Recolor" then
  3015.       if not tTool.selector[1]
  3016.       or tTool.selector.copy then
  3017.         term.setTextColor(colors.lightGray)
  3018.       else
  3019.         term.setTextColor(tColors.contextMenuText)
  3020.       end
  3021.     elseif not tTool.selector[1] and not tTool.selector.paste then
  3022.       term.setTextColor(colors.lightGray)
  3023.     else
  3024.       term.setTextColor(tColors.contextMenuText)
  3025.     end
  3026.     term.write(tContextMenu[i]["item"])
  3027.   end
  3028.   tContextMenu.x = x
  3029.   tContextMenu.y = y
  3030.   tContextMenu.open = true
  3031. end
  3032.  
  3033. function getFunc(menu,func)
  3034. --gets the desired function from the menu table
  3035.   local menu = tMenuBar[menu]
  3036.   for i=1,#menu do
  3037.     if menu[i]["item"]:match(func) then
  3038.       return menu[i]["func"]
  3039.     end
  3040.   end
  3041. end
  3042.  
  3043. function tMenuBar.click(clickX,clickY)
  3044.   --determines what menu was clicked, if any
  3045.   local open = tMenuBar.open
  3046.   if clickY == 1 then
  3047.     if clickX <= #tMenuBar.mainButton then
  3048.       return "Main"
  3049.     elseif clickX >= tTerm.x-#tMenuBar.infoString then
  3050.       return getFunc("Layer","Goto...")
  3051.     end
  3052.   elseif open then
  3053.     --drop down menu click
  3054.     if tMenuBar[open]["startX"] <= clickX and tMenuBar[open]["startX"]+tMenuBar[open]["length"]+1 >= clickX
  3055.     and #tMenuBar[open] >= clickY-1 then
  3056.       return tMenuBar[open][clickY-1]["func"]
  3057.     elseif #tMenuBar[open] > tTerm.y-1  and tMenuBar[open]["startX"]+tMenuBar[open]["length"]+1 <= clickX
  3058.     and clickX <= tMenuBar[open]["startX"]+(tMenuBar[open]["length"]*2)+1
  3059.     and #tMenuBar[open]-(tTerm.y-1) >= clickY-1 then
  3060.       return tMenuBar[open][clickY-2+tTerm.y]["func"]
  3061.     end
  3062.   end
  3063.   return false
  3064.   --no menu clicked
  3065. end
  3066.  
  3067. function tContextMenu.click(clickX,clickY)
  3068.   --determines what menu was clicked, if any
  3069.   if not tContextMenu.open then
  3070.     return false
  3071.   end
  3072.   if clickY == 1 then
  3073.     if clickX <= #tMenuBar.mainButton then
  3074.       return tMenuBar.render"main"
  3075.     elseif clickX >= tTerm.x-#tMenuBar.infoString then
  3076.       return getFunc("Layer","Goto...")
  3077.     end
  3078.   else
  3079.     --drop down menu click
  3080.     if tContextMenu.x <= clickX and tContextMenu.x+tContextMenu.length+1 >= clickX
  3081.     and tContextMenu[clickY-tContextMenu.y+1] then
  3082.       return tContextMenu[clickY-tContextMenu.y+1]["func"]
  3083.     end
  3084.   end
  3085.   return false
  3086.   --no menu clicked
  3087. end
  3088.  
  3089. function brushExpand(tPointData,color)
  3090.   --brush tool function
  3091.   local tAffectedPoints = {}
  3092.   for i=1,#tPointData do
  3093.     local layer = tPointData[i]["layer"]
  3094.     local x = tPointData[i]["x"]+1
  3095.     local z = tPointData[i]["z"]
  3096.     if tBlueprint[layer][x] and tBlueprint[layer][x][z] then
  3097.       renderPoint(x-tScroll.x.value,z-tScroll.y.value,color)
  3098.       table.insert(tAffectedPoints,{["layer"] = layer,["x"] = x,["z"] = z})
  3099.     end
  3100.     x = tPointData[i]["x"]-1
  3101.     if tBlueprint[layer][x] and tBlueprint[layer][x][z] then
  3102.       renderPoint(x-tScroll.x.value,z-tScroll.y.value,color)
  3103.       table.insert(tAffectedPoints,{["layer"] = layer,["x"] = x,["z"] = z})
  3104.     end
  3105.     x = tPointData[i]["x"]
  3106.     z = tPointData[i]["z"]+1
  3107.     if tBlueprint[layer][x] and tBlueprint[layer][x][z] then
  3108.       renderPoint(x-tScroll.x.value,z-tScroll.y.value,color)
  3109.       table.insert(tAffectedPoints,{["layer"] = layer,["x"] = x,["z"] = z})
  3110.     end
  3111.     z = tPointData[i]["z"]-1
  3112.     if tBlueprint[layer][x] and tBlueprint[layer][x][z] then
  3113.       renderPoint(x-tScroll.x.value,z-tScroll.y.value,color)
  3114.       table.insert(tAffectedPoints,{["layer"] = layer,["x"] = x,["z"] = z})
  3115.     end
  3116.   end
  3117.   return tAffectedPoints
  3118. end
  3119.  
  3120. function squareExpand(x,z,color,size)
  3121.   --square tool function
  3122.   renderPoint(x,z,color)
  3123.   if size == 2 then
  3124.     renderPoint(x+1,z,color)
  3125.     renderPoint(x+1,z+1,color)
  3126.     renderPoint(x,z+1,color)
  3127.   elseif size > 2 then
  3128.     for i=1,size-2 do
  3129.       renderWall(z-i,z+i,x+i,color)
  3130.       renderWall(z-i,z+i,x-i,color)
  3131.       renderLine(x-i,x+i,z+i,color)
  3132.       renderLine(x-i,x+i,z-i,color)
  3133.     end
  3134.   end
  3135. end
  3136.  
  3137. function fillExpand(x,z,layer,replaceColor,fillColor)
  3138.   --fill tool function
  3139.   if fillColor == replaceColor then
  3140.     return
  3141.   end
  3142.   renderPoint(x,z,fillColor,true)
  3143.   local tAffectedPoints = {}
  3144.   tAffectedPoints[1] = {["x"] = x+tScroll.x.value, ["z"] = z+tScroll.y.value}
  3145.   local loops = 0
  3146.   local tPoints = {}
  3147.   while #tAffectedPoints > 0 do
  3148.     if loops%50 == 0 then
  3149.       sleep(0.05)
  3150.     end
  3151.     local x = tAffectedPoints[1]["x"]+1
  3152.     local z = tAffectedPoints[1]["z"]
  3153.     if not (tPoints[x] and tPoints[x][z])
  3154.     and tBlueprint[layer][x] and tBlueprint[layer][x][z] and tBlueprint[layer][x][z] == replaceColor then
  3155.       renderPoint(x-tScroll.x.value,z-tScroll.y.value,fillColor,true)
  3156.       tPoints[x] = tPoints[x] or {}
  3157.       tPoints[x][z] = true
  3158.       table.insert(tAffectedPoints,{["x"] = x,["z"] = z})
  3159.     end
  3160.     x = tAffectedPoints[1]["x"]-1
  3161.     if not (tPoints[x] and tPoints[x][z])
  3162.     and tBlueprint[layer][x] and tBlueprint[layer][x][z] and tBlueprint[layer][x][z] == replaceColor then
  3163.       renderPoint(x-tScroll.x.value,z-tScroll.y.value,fillColor,true)
  3164.       tPoints[x] = tPoints[x] or {}
  3165.       tPoints[x][z] = true
  3166.       table.insert(tAffectedPoints,{["x"] = x,["z"] = z})
  3167.     end
  3168.     x = tAffectedPoints[1]["x"]
  3169.     z = tAffectedPoints[1]["z"]+1
  3170.     if not (tPoints[x] and tPoints[x][z])
  3171.     and tBlueprint[layer][x] and tBlueprint[layer][x][z] and tBlueprint[layer][x][z] == replaceColor then
  3172.       renderPoint(x-tScroll.x.value,z-tScroll.y.value,fillColor,true)
  3173.       tPoints[x] = tPoints[x] or {}
  3174.       tPoints[x][z] = true
  3175.       table.insert(tAffectedPoints,{["x"] = x,["z"] = z})
  3176.     end
  3177.     z = tAffectedPoints[1]["z"]-1
  3178.     if not (tPoints[x] and tPoints[x][z])
  3179.     and tBlueprint[layer][x] and tBlueprint[layer][x][z] and tBlueprint[layer][x][z] == replaceColor then
  3180.       renderPoint(x-tScroll.x.value,z-tScroll.y.value,fillColor,true)
  3181.       tPoints[x] = tPoints[x] or {}
  3182.       tPoints[x][z] = true
  3183.       table.insert(tAffectedPoints,{["x"] = x,["z"] = z})
  3184.     end
  3185.     table.remove(tAffectedPoints,1)
  3186.     loops = loops+1
  3187.   end
  3188. end
  3189.  
  3190. function selectorRender(x,y)
  3191.   --renders paste or selection on canvas
  3192.   if not tTool.selector[1] or not tTool.selector.enabled then
  3193.     return
  3194.   elseif not tTool.selector[2] then
  3195.     tTool.selector[2] = {
  3196.       ["x"] = tTool.selector[1]["x"],
  3197.       ["z"] = tTool.selector[1]["z"]
  3198.     }
  3199.   end
  3200.   local x1 = tTool.selector[1]["x"]-tScroll.x.value+(x or 0)
  3201.   local x2 = tTool.selector[2]["x"]-tScroll.x.value+(x or 0)
  3202.   local z1 = tTool.selector[1]["z"]-tScroll.y.value+(y or 0)+1
  3203.   local z2 = tTool.selector[2]["z"]-tScroll.y.value+(y or 0)+1
  3204.   local canvasEdge = tTerm.y
  3205.   if tTerm.grid then
  3206.     canvasEdge = canvasEdge-1
  3207.   end
  3208.   local paste = tTool.selector.copy
  3209.   if paste then
  3210.     local x = (x or x1)-1
  3211.     local z = (y or z1)-1
  3212.     for ix=1,#paste do
  3213.       for iz=1,#paste[ix] do
  3214.         local color = paste[ix][iz]
  3215.         if color ~= " " and iz+z >= 2 and iz+z <= canvasEdge  then
  3216.           paintutils.drawPixel(ix+x,iz+z,tColorNums[color])
  3217.         end
  3218.       end
  3219.     end
  3220.   else
  3221.     if z1 >= 2 and z1 <= canvasEdge then
  3222.       paintutils.drawLine(x1,z1,x2,z1,tColors.selector)
  3223.       if z2 >= 2 and z2 <= canvasEdge then
  3224.         paintutils.drawLine(x2,z2,x1,z2,tColors.selector)
  3225.       else
  3226.         z2 = canvasEdge
  3227.       end
  3228.       paintutils.drawLine(x2,z1,x2,z2,tColors.selector)
  3229.       paintutils.drawLine(x1,z2,x1,z1,tColors.selector)
  3230.     elseif z2 >= 2 and z2 <= canvasEdge then
  3231.       paintutils.drawLine(x2,2,x2,z2,tColors.selector)
  3232.       paintutils.drawLine(x1,z2,x1,2,tColors.selector)
  3233.       paintutils.drawLine(x2,z2,x1,z2,tColors.selector)
  3234.     else
  3235.       paintutils.drawLine(x2,2,x2,canvasEdge,tColors.selector)
  3236.       paintutils.drawLine(x1,canvasEdge,x1,2,tColors.selector)
  3237.     end
  3238.   end
  3239.   if x then
  3240.     tTool.selector[2]["x"] = tTool.selector[2]["x"]+x-tTool.selector[1]["x"]
  3241.     tTool.selector[1]["x"] = x+tScroll.x.value
  3242.     tTool.selector[2]["z"] = tTool.selector[2]["z"]+y-tTool.selector[1]["z"]
  3243.     tTool.selector[1]["z"] = y+tScroll.y.value
  3244.   end
  3245. end
  3246.  
  3247. function selectorCopy(_x1,_z1,_x2,_z2,layer,CUT)
  3248.   layer = layer or tScroll.layer
  3249.   local tRet = {}
  3250.   x1 = math.min(_x1,_x2)
  3251.   x2 = math.max(_x1,_x2)
  3252.   z1 = math.min(_z1,_z2)
  3253.   z2 = math.max(_z1,_z2)
  3254.   for ix=x1,x2 do
  3255.     tRet[#tRet+1] = {}
  3256.     for iz=z1,z2 do
  3257.       tRet[#tRet][#tRet[#tRet]+1] = tBlueprint[layer][ix][iz] or " "
  3258.       if CUT then
  3259.         tBlueprint[layer][ix][iz] = " "
  3260.       end
  3261.     end
  3262.   end
  3263.   return tRet
  3264. end
  3265.  
  3266. function selectorPaste(x,z,paste,num)
  3267.   --pastes selection into layer at x,z
  3268.   z = z-1
  3269.   x = x-1
  3270.   num = num or tScroll.layer
  3271.   for ix=1,#paste do
  3272.     tBlueprint[num][x+ix] = tBlueprint[num][x+ix] or {}
  3273.     for iz=1,#paste[ix] do
  3274.       local color = paste[ix][iz]
  3275.       if color ~= " " then
  3276.         tBlueprint[num][x+ix][z+iz] = color
  3277.       end
  3278.     end
  3279.   end
  3280. end
  3281.  
  3282. function selectorRecolor(color,x1,z1,x2,z2,layer)
  3283.   layer = layer or tScroll.layer
  3284.   local tRet = {}
  3285.   for ix=x1,x2 do
  3286.     tBlueprint[layer][ix] = tBlueprint[layer][ix] or {}
  3287.     for iz=z1,z2 do
  3288.       if tBlueprint[layer][ix][iz] ~= " " then
  3289.         tBlueprint[layer][ix][iz] = color
  3290.       end
  3291.     end
  3292.   end
  3293.   renderLayer(layer)
  3294. end
  3295.  
  3296. function circleRender(color,draw)
  3297.   if tTool[1].tool ~= "Circle"
  3298.   and tTool[2].tool ~= "Circle" then
  3299.     return
  3300.   end
  3301.   local x1 = tTool.circle[1].x
  3302.   local x2 = tTool.circle[2].x
  3303.   local y1 = tTool.circle[1].y
  3304.   local y2 = tTool.circle[2].y
  3305.   if not (x1 and x2 and y1 and y2) then
  3306.     return
  3307.   end
  3308.   color = color or tTool.circle[2].color
  3309.   local function round(num)
  3310.     if num+0.5 > math.ceil(num) then
  3311.       return math.ceil(num)
  3312.     else
  3313.       return math.floor(num)
  3314.     end
  3315.   end
  3316.   local x = {
  3317.     max = math.max(x1,x2)-tScroll.x.value,
  3318.     min = math.min(x1,x2)-tScroll.x.value
  3319.   }
  3320.   x.rad = round((x.max-x.min)/2)
  3321.   x.center = x.rad+x.min
  3322.   local y = {
  3323.     max = math.max(y1,y2)-tScroll.y.value+1,
  3324.     min = math.min(y1,y2)-tScroll.y.value+1
  3325.   }
  3326.   y.rad = round((y.max-y.min)/2)
  3327.   y.center = y.rad+y.min
  3328.   local tPoints = {}
  3329.   local canvasEdgeY = tTerm.y
  3330.   local canvasEdgeX = tTerm.xCanvas
  3331.   if tTerm.grid then
  3332.     canvasEdgeX = canvasEdgeX-1
  3333.     canvasEdgeY = canvasEdgeY-1
  3334.   end
  3335.   local radStep = 1/((1.5*x.rad)+(1.5*y.rad)/2)
  3336.   for angle = 1, math.pi+radStep, radStep do
  3337.     local pX = round(math.cos(angle)*x.rad)
  3338.     local pY = round(math.sin(angle)*y.rad)
  3339.     tPoints[pX] = tPoints[pX] or {}
  3340.     tPoints[pX][pY] = true
  3341.   end
  3342.   if draw then
  3343.     for pX,yT in pairs(tPoints) do
  3344.       for pY in pairs(yT) do
  3345.         for i=-1,1,2 do
  3346.           for j=-1,1,2 do
  3347.             local layer = tBlueprint[tScroll.layer]
  3348.             local pX = x.center + i*pX + tScroll.x.value
  3349.             local pY = y.center + j*pY + tScroll.y.value
  3350.             layer[pX] = layer[pX] or {}
  3351.             layer[pX][pY-1] = color
  3352.             if pX > tScroll.x.value and pX <= canvasEdgeX+tScroll.x.value
  3353.             and pY > tScroll.y.value and pY <= canvasEdgeY+tScroll.y.value then
  3354.               paintutils.drawPixel(pX,pY,tColorNums[color])
  3355.             end
  3356.           end
  3357.         end
  3358.         tTool.circle = {
  3359.           [1] = {},
  3360.           [2] = {}
  3361.         }
  3362.       end
  3363.     end
  3364.   else
  3365.     for pX,yT in pairs(tPoints) do
  3366.       for pY in pairs(yT) do
  3367.         for i=-1,1,2 do
  3368.           for j=-1,1,2 do
  3369.             local pX = x.center + i*pX
  3370.             local pY = y.center + j*pY
  3371.             if pX <= canvasEdgeX
  3372.             and pY <= canvasEdgeY and pY > 1 then
  3373.               paintutils.drawPixel(pX,pY,tColorNums[color])
  3374.             end
  3375.           end
  3376.         end
  3377.       end
  3378.     end
  3379.   end
  3380. end
  3381. --[[
  3382. --------------------------------------------------------------------------------------------------------------
  3383. |                                              Actual program                                                |
  3384. --------------------------------------------------------------------------------------------------------------
  3385. --]]
  3386. --turtle specific files
  3387. if turtle then
  3388.   if not fs.exists"cTurtle" then
  3389.     tPaste.get(tPaste.cTurtle,"/cTurtle")
  3390.   end
  3391.   if not cTurtle then
  3392.     os.loadAPI(tFile.cTurtle) --Complete turtle API, by CometWolf -Paste code JRPN0P8x
  3393.   end
  3394.   if peripheral.getType"right" == "modem" and peripheral.call("right","isWireless") then
  3395.     modem = peripheral.wrap"right"
  3396.     rednet.open"right"
  3397.     rednet.broadcast"Architect turtle"
  3398.   end
  3399. end
  3400. --file load
  3401. if tArg[1] and tArg[1] ~= "-a" then
  3402.   if fs.exists(tArg[1]) then
  3403.     tBlueprint,tColorSlots,tOrigin = loadBlueprint(tArg[1])
  3404.     if not tBlueprint then
  3405.       print(tArg[1].." is not a Turtle Architect file!") --wrong file format
  3406.       return
  3407.     end
  3408.   end
  3409.   tFile.curBlueprint = tArg[1]
  3410. elseif fs.exists(tFile.ongoingBuild) then
  3411.   local file = fs.open(tFile.ongoingBuild,"r")
  3412.   tOngoing = textutils.unserialize(file.readAll())
  3413.   file.close()
  3414. end
  3415. --machine check
  3416. if not tTerm.isColor then
  3417.   if not turtle then
  3418.     --turtle check
  3419.     error"This program may only be used on regular turtles or advanced computers/turtles!"
  3420.   elseif tArg[1] then
  3421.   --regular turtle program
  3422.     term.setBackgroundColor(colors.black)
  3423.     term.setTextColor(colors.white)
  3424.     local status = tArg[1].." loaded"
  3425.     while true do
  3426.       local enderAction
  3427.       if tOngoing.enderChest then
  3428.         enderAction = "Disable ender chest("..tOngoing.enderChest..")"
  3429.       else
  3430.         enderAction = "Enable ender chest"
  3431.       end
  3432.       term.clear()
  3433.       term.setCursorPos(1,1)
  3434.       local button = noColorInput(status,"Commence build","Check usage",enderAction,"Edit origin point","Mark as not built","Quit")
  3435.       if button == "Commence build" then
  3436.         buildBlueprint(1,#tBlueprint)
  3437.         status = "Finished construction of "..tArg[1]
  3438.       elseif button == "Check usage" then
  3439.         local fuelUsage, tColorBlocks = checkUsage(1,#tBlueprint)
  3440.         term.clear()
  3441.         term.setCursorPos(1,1)
  3442.         print("Fuel: "..fuelUsage)
  3443.         for k,v in pairs(tColorBlocks) do
  3444.           print(tColorString[tColorNums[k]]..": "..v)
  3445.         end
  3446.         print"Press any key to continue"
  3447.         os.pullEvent"key"
  3448.       elseif button == "Enable ender chest" then
  3449.         term.clear()
  3450.         term.setCursorPos(1,1)
  3451.         print"Input ender chest slot:"
  3452.         tOngoing.enderChest = tonumber(read())
  3453.         cTurtle.tSettings.enderFuel = tOngoing.enderChest
  3454.         status = "Enabled ender chest in slot "..tOngoing.enderChest
  3455.       elseif button:match"Disable ender chest" then
  3456.         tOngoing.enderChest = false
  3457.         cTurtle.tSettings.enderFuel = false
  3458.         status = "Disabled ender chest"
  3459.       elseif button == "Edit origin point" then
  3460.         term.clear()
  3461.         term.setCursorPos(1,1)
  3462.         print("Editing origin point")
  3463.         term.write"X: "
  3464.         local cursX,cursY = term.getCursorPos()
  3465.         term.setCursorPos(1,cursY+1)
  3466.         term.write"Y: "
  3467.         term.setCursorPos(1,cursY+2)
  3468.         term.write"Z: "
  3469.         term.setCursorPos(1,cursY+3)
  3470.         term.write"X dir: "
  3471.         term.setCursorPos(1,cursY+4)
  3472.         term.write"Z dir: "
  3473.         term.setCursorPos(1,cursY+5)
  3474.         term.write"Y dir: "
  3475.         term.setCursorPos(4,cursY)
  3476.         tOrigin.x = read()
  3477.         term.setCursorPos(4,cursY+1)
  3478.         tOrigin.y = read()
  3479.         term.setCursorPos(4,cursY+2)
  3480.         tOrigin.z = read()
  3481.         term.setCursorPos(9,cursY+3)
  3482.         tOrigin.xDir = read()
  3483.         term.setCursorPos(9,cursY+4)
  3484.         tOrigin.zDir = read()
  3485.         term.setCursorPos(9,cursY+5)
  3486.         tOrigin.yDir = read()
  3487.         saveBlueprint(tFile.curBlueprint)
  3488.         status = "Updated origin point for "..tArg[1]
  3489.       elseif button == "Mark as not built" then
  3490.         for il=1,#tBlueprint do
  3491.           for ix=1,#tBlueprint[il] do
  3492.             for iz=1,#tBlueprint[il][ix] do
  3493.               local pointNum = tBlueprint[il][ix][iz] or 0
  3494.               if pointNum > 15 then
  3495.                 tBlueprint[il][ix][iz] = pointNum-15
  3496.               end
  3497.             end
  3498.           end
  3499.         end
  3500.         saveBlueprint(tFile.curBlueprint)
  3501.         status = "Marked "..tArg[1].." as not built"
  3502.       else --quit
  3503.         term.clear()
  3504.         term.setCursorPos(1,1)
  3505.         return
  3506.       end
  3507.     end
  3508.   elseif tOngoing.blueprint then --checks for ongoing build
  3509.     local status = "Ongoing build "..tOngoing.blueprint.." found!"
  3510.     while true do
  3511.       local enderAction
  3512.       if tOngoing.enderChest then
  3513.         enderAction = "Disable ender chest("..tOngoing.enderChest..")"
  3514.       else
  3515.         enderAction = "Enable ender chest"
  3516.       end
  3517.       local button = noColorInput(status,"Resume","Restart",enderAction,"Cancel")
  3518.       if button == "Resume" then
  3519.         tFile.curBlueprint = tOngoing.blueprint
  3520.         tBlueprint,tColorSlots,tOrigin = loadBlueprint(tFile.curBlueprint)
  3521.         buildBlueprint(tOngoing.startLayer,tOngoing.endLayer,true)
  3522.         return
  3523.       elseif button == "Restart" then
  3524.         tFile.curBlueprint = tOngoing.blueprint
  3525.         tBlueprint,tColorSlots,tOrigin = loadBlueprint(tFile.curBlueprint)
  3526.         for il=1,#tBlueprint do
  3527.           for ix=1,#tBlueprint[il] do
  3528.             for iz=1,#tBlueprint[il][ix] do
  3529.               local pointNum = tBlueprint[il][ix][iz]
  3530.               if pointNum > 15 then
  3531.                 tBlueprint[il][ix][iz] = pointNum-15
  3532.               end
  3533.             end
  3534.           end
  3535.         end
  3536.         buildBlueprint(tOngoing.startLayer,tOngoing.endLayer)
  3537.         return
  3538.       elseif button == "Enable ender chest" then
  3539.         term.clear()
  3540.         term.setCursorPos(1,1)
  3541.         print"Input ender chest slot:"
  3542.         tOngoing.enderChest = tonumber(read())
  3543.         cTurtle.tSettings.enderFuel = tOngoing.enderChest
  3544.         status = "Enabled ender chest in slot "..tOngoing.enderChest
  3545.       elseif button:match"Disable ender chest" then
  3546.         tOngoing.enderChest = false
  3547.         cTurtle.tSettings.enderFuel = false
  3548.         status = "Disabled ender chest"
  3549.       end
  3550.     end
  3551.     term.setBackgroundColor(colors.black)
  3552.     term.setTextColor(colors.white)
  3553.     term.clear()
  3554.     term.setCursorPos(1,1)
  3555.   else
  3556.     print("Usage: "..tFile.program.." /filePath") --no file path given
  3557.   end
  3558.   return
  3559. end
  3560. --color program begins
  3561. if not tBlueprint[1] then
  3562.   createLayer(tTerm.xCanvas,tTerm.zCanvas,1)
  3563. end
  3564. tMenuBar.render()
  3565. renderLayer(1)
  3566. if tOngoing.blueprint and (tArg[1] == "-a" or not tArg[1]) then --checks for ongoing build
  3567.   local file = fs.open(tFile.ongoingBuild,"r")
  3568.   tOngoing = textutils.unserialize(file.readAll())
  3569.   file.close()
  3570.   tFile.curBlueprint = tOngoing.blueprint
  3571.   local button
  3572.   if not tArg[1] then
  3573.     button = tBox.render(1,tTerm.x,"Ongoing build "..tOngoing.blueprint.." found!",4,0,".","Erase","Resume","Edit","Restart") -- requests action
  3574.   else
  3575.     button = "Resume"
  3576.   end
  3577.   if button == "Resume" then
  3578.     tBlueprint,tColorSlots,tOrigin = loadBlueprint(tFile.curBlueprint)
  3579.       buildBlueprint(tOngoing.startLayer,tOngoing.endLayer,true)
  3580.   elseif button == "Edit" then
  3581.     tBlueprint,tColorSlots,tOrigin = loadBlueprint(tFile.curBlueprint)
  3582.     tMenuBar.render()
  3583.     renderLayer(1)  
  3584.   elseif button == "Restart" then
  3585.     tBlueprint,tColorSlots,tOrigin = loadBlueprint(tFile.curBlueprint)
  3586.     for il=1,#tBlueprint do
  3587.       for ix=1,#tBlueprint[il] do
  3588.         for iz=1,#tBlueprint[il][ix] do
  3589.           local pointNum = tBlueprint[il][ix][iz]
  3590.           if pointNum > 15 then
  3591.             tBlueprint[il][ix][iz] = pointNum-15
  3592.           end
  3593.         end
  3594.       end
  3595.     end
  3596.     buildBlueprint(tOngoing.startLayer,tOngoing.endLayer)
  3597.   end
  3598. end
  3599.  
  3600. --auto monitor connection mode
  3601. if tArg[2] == "-m" then
  3602.   local tSides = rs.getSides()
  3603.   tMon = {}
  3604.   for is=1,#tSides do
  3605.     if peripheral.getType(tSides[is]) == "monitor" and peripheral.call(tSides[is],"isColor") then
  3606.       tMon[#tMon+1] = peripheral.wrap(tSides[is])
  3607.       tMon[#tMon]["side"] = tSides[is]
  3608.       tMon[#tMon]["x"],tMon[#tMon]["y"] = tMon[#tMon]["getSize"]()
  3609.       tMon[#tMon]["xMid"] = math.ceil(tMon[#tMon]["x"]/2)
  3610.       tMon[#tMon]["yMid"] = math.ceil(tMon[#tMon]["y"]/2)
  3611.       tMon[#tMon]["xCanvas"] = tMon[#tMon]["x"] --total x veiwing area
  3612.       tMon[#tMon]["zCanvas"] = tMon[#tMon]["y"] --total y veiwing area
  3613.     elseif peripheral.getType(tSides[is]) == "modem"
  3614.     and not peripheral.call(tSides[is],"isWireless") then
  3615.       local tPeripherals = peripheral.call(tSides[is],"getNamesRemote")
  3616.       for ip=1,#tPeripherals do
  3617.         if string.match(tPeripherals[ip],"monitor")
  3618.         and peripheral.call(tPeripherals[ip],"isColor") then
  3619.           tMon[#tMon+1] = peripheral.wrap(tPeripherals[ip])
  3620.           tMon[#tMon]["side"] = tPeripherals[ip]
  3621.           tMon[#tMon]["x"],tMon[#tMon]["y"] = tMon[#tMon]["getSize"]()
  3622.           tMon[#tMon]["xMid"] = math.ceil(tMon[#tMon]["x"]/2)
  3623.           tMon[#tMon]["yMid"] = math.ceil(tMon[#tMon]["y"]/2)
  3624.           tMon[#tMon]["xCanvas"] = tMon[#tMon]["x"] --total x veiwing area
  3625.           tMon[#tMon]["zCanvas"] = tMon[#tMon]["y"] --total y veiwing area
  3626.         end
  3627.       end
  3628.     end
  3629.   end
  3630.   if #tMon > 0 then
  3631.     renderLayer(1)
  3632.   end
  3633. end
  3634.    
  3635. while true do
  3636.   --Event handling
  3637.   tEvent = {os.pullEvent()}
  3638.   local xCanvas = tTerm.xCanvas
  3639.   local zCanvas = tTerm.zCanvas+1
  3640.   if tEvent[1] == "monitor_touch" then
  3641.     for i=1,#tMon do
  3642.       if tMon[i]["side"] == tEvent[2] then
  3643.         xCanvas = tMon[i]["xCanvas"]
  3644.         zCanvas = tMon[i]["zCanvas"]
  3645.         break
  3646.       end
  3647.     end
  3648.     tEvent[1] = "mouse_click"
  3649.     tEvent[2] = 1
  3650.     tEvent[4] = tEvent[4]+1
  3651.   end
  3652.   if tTerm.grid then
  3653.     xCanvas = xCanvas-1
  3654.     zCanvas = zCanvas-1
  3655.   end
  3656.   if not tMenuBar.open and (tEvent[1] == "mouse_drag" or tEvent[1] == "mouse_click")
  3657.   and tEvent[4] <= zCanvas+1 and tEvent[4] > 1
  3658.   and tEvent[3] <= xCanvas then
  3659.     --canvas input
  3660.     local t = tTool[tEvent[2]]
  3661.     if t.tool == "Brush" then
  3662.       if t.size <= 2 then
  3663.         renderPoint(tEvent[3],tEvent[4]-1,t.color)
  3664.       end
  3665.       if t.size >= 2 then
  3666.         local tPoints = {
  3667.           [1] = {
  3668.             ["layer"] = tScroll.layer,
  3669.             ["x"] = tEvent[3]+tScroll.x.value,
  3670.             ["z"] = tEvent[4]+tScroll.y.value-1
  3671.           }
  3672.         }
  3673.         for i=1,t.size-1 do
  3674.           tPoints = brushExpand(tPoints,t.color)
  3675.         end
  3676.       end
  3677.     elseif t.tool == "Dragger" then
  3678.       if tEvent[1] == "mouse_click" then
  3679.         tTool.dragPoint = {
  3680.           ["x"] = tEvent[3],
  3681.           ["y"] = tEvent[4]
  3682.         }
  3683.       else --mouse drag
  3684.         tScroll.x.value = math.max(0,tScroll.x.value+(tTool.dragPoint.x-tEvent[3]))
  3685.         tScroll.y.value = math.max(0,tScroll.y.value+(tTool.dragPoint.y-tEvent[4]))
  3686.         tTool.dragPoint = {
  3687.           ["x"] = tEvent[3],
  3688.           ["y"] = tEvent[4]
  3689.         }
  3690.       end
  3691.       renderLayer(tScroll.layer)
  3692.     elseif tTool.selector.enabled then
  3693.       if tEvent[2] == 1 then
  3694.         if tContextMenu.open then
  3695.           if tEvent[1] == "mouse_click" then
  3696.             local clicked = tContextMenu.click(tEvent[3],tEvent[4])
  3697.             if clicked then
  3698.               clicked(tEvent[4],tEvent[4])
  3699.             else
  3700.               tContextMenu.open = false
  3701.               renderLayer(tScroll.layer)
  3702.             end
  3703.           end
  3704.         else
  3705.           if tEvent[1] == "mouse_click" then
  3706.             tTool.selector[1] = {
  3707.               ["x"] = tEvent[3]+tScroll.x.value,
  3708.               ["z"] = tEvent[4]+tScroll.y.value-1,
  3709.               ["layer"] = tScroll.layer
  3710.             }
  3711.             tTool.selector[2] = nil
  3712.           else --mouse drag
  3713.             tTool.selector[2] = {
  3714.               ["x"] = tEvent[3]+tScroll.x.value,
  3715.               ["z"] = tEvent[4]+tScroll.y.value-1
  3716.             }
  3717.           end
  3718.           renderLayer(tScroll.layer)
  3719.         end
  3720.       elseif tEvent[2] == 2 then
  3721.         if tEvent[1] == "mouse_click" then
  3722.           tContextMenu.render(tEvent[3],tEvent[4])
  3723.         end
  3724.       end
  3725.     elseif t.tool == "Line" then
  3726.      
  3727.     elseif t.tool == "Fill" then
  3728.       fillExpand(tEvent[3],tEvent[4]-1,tScroll.layer,tBlueprint[tScroll.layer][tEvent[3]+tScroll.x.value][tEvent[4]+tScroll.y.value-1],t.color)
  3729.     elseif t.tool == "Square" then
  3730.       squareExpand(tEvent[3],tEvent[4],t.color,t.size)
  3731.     elseif t.tool == "Circle" then
  3732.       if tEvent[1] == "mouse_click" then
  3733.         tTool.circle[1] = {
  3734.           x = tEvent[3]+tScroll.x.value,
  3735.           y = tEvent[4]+tScroll.y.value-1
  3736.         }
  3737.         if tTool.circle[2].x then
  3738.           tTool.circle[2] = {}
  3739.           renderLayer(tScroll.layer)
  3740.         end
  3741.       else
  3742.         tTool.circle[2] = {
  3743.           x = tEvent[3]+tScroll.x.value,
  3744.           y = tEvent[4]+tScroll.y.value-1,
  3745.           color = t.color
  3746.         }
  3747.         tTool.circle[1].color = t.color
  3748.         renderLayer(tScroll.layer)
  3749.       end
  3750.     end
  3751.   elseif tEvent[1] == "mouse_click" then
  3752.     --non-canvas mouse clicks
  3753.     if tEvent[4] == 1 then
  3754.       --top bar menu clicks
  3755.       tMenuBar.render(tMenuBar.click(tEvent[3],tEvent[4]))
  3756.     elseif tMenuBar.open then
  3757.       --dropdown menu open
  3758.       local clicked = tMenuBar.click(tEvent[3],tEvent[4])
  3759.       tMenuBar.render()
  3760.       --closes drop down menu
  3761.       if clicked then
  3762.         --runs clicked function
  3763.         clicked(tEvent[2])
  3764.       end
  3765.     end
  3766.   elseif tEvent[1] == "mouse_scroll" and not tMenuBar.open then
  3767.     --mouse scroll
  3768.     tScroll.y.value = math.max(0,tScroll.y.value+tEvent[2])
  3769.     renderLayer(tScroll.layer)
  3770.   elseif tEvent[1] == "key" then
  3771.     --key inputs
  3772.     local key = tEvent[2]
  3773.     if not tMenuBar.open then
  3774.       local renderMenu
  3775.       if key == 205 then --right arrow
  3776.         tScroll.x.value = tScroll.x.value+1
  3777.       elseif key == 203 then --left arrow
  3778.         tScroll.x.value = math.max(0,tScroll.x.value-1)
  3779.       elseif key == 200 then --up arrow
  3780.         tScroll.y.value = math.max(0,tScroll.y.value-1)
  3781.       elseif key == 208 then --down arrow
  3782.         tScroll.y.value = tScroll.y.value+1
  3783.       elseif key == 209 then --page down
  3784.         tScroll.layer = math.max(1,tScroll.layer-1)
  3785.       elseif key == 201 then --page up
  3786.         tScroll.layer = math.min(#tBlueprint,tScroll.layer+1)
  3787.       elseif key == 211 then --delete
  3788.         getFunc("Layer","Delete current layer")()
  3789.       elseif key == 199 then --home
  3790.         tScroll.layer = 1
  3791.       elseif key == 28 then --enter
  3792.         if tTool[1].tool == "Circle" then
  3793.           circleRender(false,true)
  3794.         end
  3795.       elseif key == 207 then --end
  3796.         tScroll.layer = #tBlueprint
  3797.       elseif key == 31 then --S
  3798.         getFunc("Blueprint","Save  ")() --double space to differnetiate between save and save as...
  3799.       elseif key == 33 then --F
  3800.         tTool.selector = {}
  3801.         if tTool[1]["tool"] ~= "Fill" then
  3802.           tTool[1]["tool"] = "Fill"
  3803.         else
  3804.           tTool[1]["tool"] = "Brush"
  3805.         end
  3806.       elseif key == 46 then --C
  3807.         renderMenu = "Color"
  3808.       elseif key == 20 then --T
  3809.         renderMenu = getFunc("Main","Tools")
  3810.       elseif key == 48 then --B
  3811.         renderMenu = getFunc("Main","Blueprint")
  3812.       elseif key == 38 then --L
  3813.         renderMenu = getFunc("Main","Layer")
  3814.       elseif key == 31 then --S
  3815.         renderMenu = getFunc("Main","Settings")
  3816.       elseif key == 49 then --N
  3817.         getFunc("Layer","New...")()
  3818.       elseif key == 34 then --G
  3819.         getFunc("Layer","Goto...")()
  3820.       elseif key == 32 then --D
  3821.         tTool.selector = {}
  3822.         if tTool[1]["tool"] ~= "Dragger" then
  3823.           tTool[1]["tool"] = "Dragger"
  3824.         else
  3825.           tTool[1]["tool"] = "Brush"
  3826.         end
  3827.       end
  3828.       if renderMenu then
  3829.         tMenuBar.render(renderMenu)
  3830.       else
  3831.         renderLayer(tScroll.layer)
  3832.       end
  3833.     end
  3834.   elseif tEvent[1] == "char" then
  3835.     --character input, nothing here yet
  3836.   elseif tEvent[1] == "monitor_resize" and tMon then
  3837.     --monitor changed size
  3838.     for i=1,#tMon do
  3839.       tMon[i]["x"],tMon[i]["y"] = tMon[i]["getSize"]()
  3840.       tMon[i]["xMid"] = math.ceil(tMon[i]["x"]/2)
  3841.       tMon[i]["yMid"] = math.ceil(tMon[i]["y"]/2)
  3842.       tMon[i]["xCanvas"] = tMon[i]["x"] --total x veiwing area
  3843.       tMon[i]["zCanvas"] = tMon[i]["y"] --total y veiwing area, accounts for the menubar on top
  3844.     end
  3845.     tMenuBar.render(tMenuBar.open)
  3846.     renderLayer(tScroll.layer)
  3847.   end
  3848. end
  3849.  
  3850. --[[
  3851. --------------------------------------------------------------------------------------------------------------
  3852. |                                               Program end                                                  |
  3853. --------------------------------------------------------------------------------------------------------------
  3854. --]]
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement