Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- Surface API version 1.1 by CrazedProgrammer
- -- You can find info and documentation on these pages:
- -- http://www.computercraft.info/forums2/index.php?/topic/22397-surface-api/
- -- You may use this in your ComputerCraft programs and modify it without asking.
- -- However, you may not publish this API under your name without asking me.
- -- If you have any suggestions, bug reports or questions then please send an email to:
- -- crazedprogrammer@gmail.com
- function create(width, height, char, backcolor, textcolor)
- local surf = { }
- surf.width = width
- surf.height = height
- surf.x1 = 1
- surf.y1 = 1
- surf.x2 = width
- surf.y2 = height
- surf.overwrite = false
- surf.buffer = { }
- surf.setBounds = setBounds
- surf.save = save
- surf.render = render
- surf.clear = clear
- surf.drawPixel = drawPixel
- surf.getPixel = getPixel
- surf.drawText = drawText
- surf.drawLine = drawLine
- surf.drawRect = drawRect
- surf.fillRect = fillRect
- surf.drawTriangle = drawTriangle
- surf.fillTriangle = fillTriangle
- surf.drawEllipse = drawEllipse
- surf.fillEllipse = fillEllipse
- surf.floodFill = floodFill
- surf.drawSurface = drawSurface
- surf.drawSurfacePart = drawSurfacePart
- surf.drawSurfaceScaled = drawSurfaceScaled
- for i=1,width*height,1 do
- surf.buffer[(i - 1) * 3 + 1] = char
- surf.buffer[(i - 1) * 3 + 2] = backcolor
- surf.buffer[(i - 1) * 3 + 3] = textcolor
- end
- return surf
- end
- function load(path)
- local lines = { }
- local f = fs.open(path, "r")
- local line = f.readLine()
- while line do
- table.insert(lines, line)
- line = f.readLine()
- end
- f.close()
- local height = #lines
- if lines[1]:byte(1) == 30 then
- local width = 0
- local i = 1
- while i <= #lines[1] do
- local char = lines[1]:byte(i)
- if char == 30 or char == 31 then
- i = i + 1
- else
- width = width + 1
- end
- i = i + 1
- end
- local surf = surface.create(width, height)
- local backcolor = nil
- local testcolor = nil
- for j=1,height,1 do
- local i = 1
- local px = 1
- while i <= #lines[j] do
- local char = lines[j]:byte(i)
- if char == 30 then
- i = i + 1
- char = lines[j]:byte(i)
- local color = tonumber(lines[j]:sub(i, i), 16)
- if color then
- backcolor = 2^color
- else
- backcolor = nil
- end
- elseif char == 31 then
- i = i + 1
- char = lines[j]:byte(i)
- local color = tonumber(lines[j]:sub(i, i), 16)
- if color then
- textcolor = 2^color
- else
- textcolor = nil
- end
- else
- surf.buffer[((j - 1) * surf.width + px - 1) * 3 + 1] = lines[j]:sub(i, i)
- surf.buffer[((j - 1) * surf.width + px - 1) * 3 + 2] = backcolor
- surf.buffer[((j - 1) * surf.width + px - 1) * 3 + 3] = textcolor
- px = px + 1
- end
- i = i + 1
- end
- end
- return surf
- else
- local width = #lines[1]
- local surf = surface.create(width, height)
- for j=1,height,1 do
- for i=1,width,1 do
- local color = tonumber(lines[j]:sub(i, i), 16)
- if color then
- surf.buffer[((j - 1) * surf.width + i - 1) * 3 + 2] = 2 ^ color
- end
- end
- end
- return surf
- end
- end
- function setBounds(surf, x1, y1, x2, y2)
- if x2 < x1 then
- local temp = x1
- x1 = x2
- x2 = temp
- end
- if y2 < y1 then
- local temp = y1
- y1 = y2
- y2 = temp
- end
- if x2 < 1 then return end
- if x1 > surf.width then return end
- if y2 < 1 then return end
- if y1 > surf.height then return end
- if x1 < 1 then x1 = 1 end
- if x2 > surf.width then x2 = surf.width end
- if y1 < 1 then y1 = 1 end
- if y2 > surf.height then y2 = surf.height end
- surf.x1 = x1
- surf.y1 = y1
- surf.x2 = x2
- surf.y2 = y2
- end
- function save(surf, path, type)
- type = type or "nft"
- local f = fs.open(path, "w")
- if type == "nfp" then
- for j=1,surf.height,1 do
- if j > 1 then f.write("\n") end
- for i=1,surf.width,1 do
- f.write(colorToHex(surf.buffer[((j - 1) * surf.width + i - 1) * 3 + 2]))
- end
- end
- elseif type == "nft" then
- for j=1,surf.height,1 do
- backcolor = -1
- textcolor = -1
- if j > 1 then f.write("\n") end
- for i=1,surf.width,1 do
- if backcolor ~= surf.buffer[((j - 1) * surf.width + i - 1) * 3 + 2] then
- f.write(string.char(30))
- backcolor = surf.buffer[((j - 1) * surf.width + i - 1) * 3 + 2]
- f.write(_colorToHex(backcolor))
- end
- if textcolor ~= surf.buffer[((j - 1) * surf.width + i - 1) * 3 + 3] then
- f.write(string.char(31))
- textcolor = surf.buffer[((j - 1) * surf.width + i - 1) * 3 + 3]
- f.write(_colorToHex(textcolor))
- end
- if surf.buffer[((j - 1) * surf.width + i - 1) * 3 + 1] then
- f.write(surf.buffer[((j - 1) * surf.width + i - 1) * 3 + 1])
- else
- f.write(" ")
- end
- end
- end
- end
- f.close()
- end
- function render(surf, display, x, y, sx1, sy1, sx2, sy2)
- x = x or 1
- y = y or 1
- sx1 = sx1 or 1
- sy1 = sy1 or 1
- sx2 = sx2 or surf.width
- sy2 = sy2 or surf.height
- local cmd = { }
- local str = ""
- local backcolor = 0
- local textcolor = 0
- for j=sy1,sy2,1 do
- cmd[#cmd + 1] = 1
- cmd[#cmd + 1] = y + j - sy1
- for i=sx1,sx2,1 do
- if surf.buffer[((j - 1) * surf.width + i - 1) * 3 + 2] ~= backcolor then
- backcolor = surf.buffer[((j - 1) * surf.width + i - 1) * 3 + 2]
- if str ~= "" then
- cmd[#cmd + 1] = 4
- cmd[#cmd + 1] = str
- str = ""
- end
- cmd[#cmd + 1] = 2
- cmd[#cmd + 1] = backcolor
- end
- if surf.buffer[((j - 1) * surf.width + i - 1) * 3 + 3] ~= textcolor then
- textcolor = surf.buffer[((j - 1) * surf.width + i - 1) * 3 + 3]
- if str ~= "" then
- cmd[#cmd + 1] = 4
- cmd[#cmd + 1] = str
- str = ""
- end
- cmd[#cmd + 1] = 3
- cmd[#cmd + 1] = textcolor
- end
- str = str..surf.buffer[((j - 1) * surf.width + i - 1) * 3 + 1]
- end
- cmd[#cmd + 1] = 4
- cmd[#cmd + 1] = str
- str = ""
- end
- for i=1,#cmd/2,1 do
- local c = cmd[(i - 1) * 2 + 1]
- local a = cmd[(i - 1) * 2 + 2]
- if c == 1 then
- display.setCursorPos(x, a)
- elseif c == 2 then
- display.setBackgroundColor(a)
- elseif c == 3 then
- display.setTextColor(a)
- elseif c == 4 then
- display.write(a)
- end
- end
- end
- function clear(surf, char, backcolor, textcolor)
- local overwrite = surf.overwrite
- surf.overwrite = true
- surf:fillRect(surf.x1, surf.y1, surf.x2, surf.y2, char, backcolor, textcolor)
- surf.overwrite = overwrite
- end
- function drawPixel(surf, x, y, char, backcolor, textcolor)
- if x < surf.x1 or y < surf.y1 or x > surf.x2 or y > surf.y2 then return end
- if char or surf.overwrite then
- surf.buffer[((y - 1) * surf.width + x - 1) * 3 + 1] = char
- end
- if backcolor or surf.overwrite then
- surf.buffer[((y - 1) * surf.width + x - 1) * 3 + 2] = backcolor
- end
- if textcolor or surf.overwrite then
- surf.buffer[((y - 1) * surf.width + x - 1) * 3 + 3] = textcolor
- end
- end
- function getPixel(surf, x, y)
- if x < surf.x1 or y < surf.y1 or x > surf.x2 or y > surf.y2 then return end
- return surf.buffer[((y - 1) * surf.width + x - 1) * 3 + 1], surf.buffer[((y - 1) * surf.width + x - 1) * 3 + 2], surf.buffer[((y - 1) * surf.width + x - 1) * 3 + 3]
- end
- function drawText(surf, x, y, text, backcolor, textcolor)
- local px = x
- for i=1,#text,1 do
- if text:sub(i, i) ~= "\n" then
- surf:drawPixel(x, y, text:sub(i, i), backcolor, textcolor)
- else
- x = px - 1
- y = y + 1
- end
- x = x + 1
- end
- end
- function drawLine(surf, x1, y1, x2, y2, char, backcolor, textcolor)
- local delta_x = x2 - x1
- local ix = delta_x > 0 and 1 or -1
- delta_x = 2 * math.abs(delta_x)
- local delta_y = y2 - y1
- local iy = delta_y > 0 and 1 or -1
- delta_y = 2 * math.abs(delta_y)
- surf:drawPixel(x1, y1, char, backcolor, textcolor)
- if delta_x >= delta_y then
- local error = delta_y - delta_x / 2
- while x1 ~= x2 do
- if (error >= 0) and ((error ~= 0) or (ix > 0)) then
- error = error - delta_x
- y1 = y1 + iy
- end
- error = error + delta_y
- x1 = x1 + ix
- surf:drawPixel(x1, y1, char, backcolor, textcolor)
- end
- else
- local error = delta_x - delta_y / 2
- while y1 ~= y2 do
- if (error >= 0) and ((error ~= 0) or (iy > 0)) then
- error = error - delta_y
- x1 = x1 + ix
- end
- error = error + delta_x
- y1 = y1 + iy
- surf:drawPixel(x1, y1, char, backcolor, textcolor)
- end
- end
- end
- function drawRect(surf, x1, y1, x2, y2, char, backcolor, textcolor)
- surf:drawLine(x1, y1, x2, y1, char, backcolor, textcolor)
- surf:drawLine(x1, y1, x1, y2, char, backcolor, textcolor)
- surf:drawLine(x1, y2, x2, y2, char, backcolor, textcolor)
- surf:drawLine(x2, y1, x2, y2, char, backcolor, textcolor)
- end
- function fillRect(surf, x1, y1, x2, y2, char, backcolor, textcolor)
- if x2 < x1 then
- local temp = x1
- x1 = x2
- x2 = temp
- end
- if y2 < y1 then
- local temp = y1
- y1 = y2
- y2 = temp
- end
- if x2 < surf.x1 then return end
- if x1 > surf.x2 then return end
- if y2 < surf.y1 then return end
- if y1 > surf.y2 then return end
- if x1 < surf.x1 then x1 = surf.x1 end
- if x2 > surf.x2 then x2 = surf.x2 end
- if y1 < surf.y1 then y1 = surf.y1 end
- if y2 > surf.y2 then y2 = surf.y2 end
- if char or surf.overwrite then
- for y=y1,y2,1 do
- for x=x1,x2,1 do
- surf.buffer[((y-1) * surf.width + (x-1)) * 3 + 1] = char
- end
- end
- end
- if backcolor or surf.overwrite then
- for y=y1,y2,1 do
- for x=x1,x2,1 do
- surf.buffer[((y-1) * surf.width + (x-1)) * 3 + 2] = backcolor
- end
- end
- end
- if textcolor or surf.overwrite then
- for y=y1,y2,1 do
- for x=x1,x2,1 do
- surf.buffer[((y-1) * surf.width + (x-1)) * 3 + 3] = textcolor
- end
- end
- end
- end
- function drawTriangle(surf, x1, y1, x2, y2, x3, y3, char, backcolor, textcolor)
- surf:drawLine(x1, y1, x2, y2, char, backcolor, textcolor)
- surf:drawLine(x2, y2, x3, y3, char, backcolor, textcolor)
- surf:drawLine(x3, y3, x1, y1, char, backcolor, textcolor)
- end
- function fillTriangle(surf, x1, y1, x2, y2, x3, y3, char, backcolor, textcolor)
- local minX = x1
- local minY = y1
- local maxX = x1
- local maxY = y1
- if x2 < minX then minX = x2 end
- if x3 < minX then minX = x3 end
- if y2 < minY then minY = y2 end
- if y3 < minY then minY = y3 end
- if x2 > maxX then maxX = x2 end
- if x3 > maxX then maxX = x3 end
- if y2 > maxY then maxY = y2 end
- if y3 > maxY then maxY = y3 end
- local width = maxX - minX + 1
- local height = maxY - minY + 1
- local buffer = { }
- _bufferLine(buffer, width, x1 - minX + 1, y1 - minY + 1, x2 - minX + 1, y2 - minY + 1)
- _bufferLine(buffer, width, x2 - minX + 1, y2 - minY + 1, x3 - minX + 1, y3 - minY + 1)
- _bufferLine(buffer, width, x3 - minX + 1, y3 - minY + 1, x1 - minX + 1, y1 - minY + 1)
- _bufferFill(buffer, width, height)
- for i=1,width,1 do
- for j=1,height,1 do
- if buffer[(j - 1) * width + i] then
- surf:drawPixel(minX + i - 1, minY + j - 1, char, backcolor, textcolor)
- end
- end
- end
- end
- function drawEllipse(surf, x1, y1, x2, y2, char, backcolor, textcolor)
- if x2 < x1 then
- local temp = x1
- x1 = x2
- x2 = temp
- end
- if y2 < y1 then
- local temp = y1
- y1 = y2
- y2 = temp
- end
- local resolution = 12
- local step = (math.pi * 2) / resolution
- local midX = (x1 + x2) / 2
- local midY = (y1 + y2) / 2
- local width = (x2 - x1) / 2
- local height = (y2 - y1) / 2
- local lastX = 1
- local lastY = 1
- for i=1,resolution+1,1 do
- local x = math.floor((midX + math.cos(step * i) * width) + 0.5)
- local y = math.floor((midY + math.sin(step * i) * height) + 0.5)
- if i > 1 then
- surf:drawLine(lastX, lastY, x, y, char, backcolor, textcolor)
- end
- lastX = x
- lastY = y
- end
- end
- function fillEllipse(surf, x1, y1, x2, y2, char, backcolor, textcolor)
- if x2 < x1 then
- local temp = x1
- x1 = x2
- x2 = temp
- end
- if y2 < y1 then
- local temp = y1
- y1 = y2
- y2 = temp
- end
- local resolution = 12
- local step = (math.pi * 2) / resolution
- local midX = (x1 + x2) / 2
- local midY = (y1 + y2) / 2
- local width = (x2 - x1) / 2
- local height = (y2 - y1) / 2
- local lastX = 1
- local lastY = 1
- local minX = x1
- local minY = y1
- local maxX = x2
- local maxY = y2
- local bwidth = maxX - minX + 1
- local bheight = maxY - minY + 1
- local buffer = { }
- for i=1,resolution+1,1 do
- local x = math.floor((midX + math.cos(step * i) * width) + 0.5)
- local y = math.floor((midY + math.sin(step * i) * height) + 0.5)
- if i > 1 then
- _bufferLine(buffer, bwidth, lastX - minX + 1, lastY - minY + 1, x - minX + 1, y - minY + 1)
- end
- lastX = x
- lastY = y
- end
- _bufferFill(buffer, bwidth, bheight)
- for i=1,bwidth,1 do
- for j=1,bheight,1 do
- if buffer[(j - 1) * bwidth + i] then
- surf:drawPixel(minX + i - 1, minY + j - 1, char, backcolor, textcolor)
- end
- end
- end
- end
- function floodFill(surf, x, y, char, backcolor, textcolor)
- local stack = { x, y }
- local tchar, tbackcolor, ttextcolor = surf:getPixel(x, y)
- if (tchar == char) and (tbackcolor == backcolor) and (ttextcolor == textcolor) then return end
- while #stack > 0 do
- local cx = stack[1]
- table.remove(stack, 1)
- local cy = stack[1]
- table.remove(stack, 1)
- if not (cx < surf.x1 or cy < surf.y1 or cx > surf.x2 or cy > surf.y2) then
- local cchar, cbackcolor, ctextcolor = surf:getPixel(cx, cy)
- if (tchar == cchar) and (tbackcolor == cbackcolor) and (ttextcolor == ctextcolor) then
- surf:drawPixel(cx, cy, char, backcolor, textcolor)
- table.insert(stack, cx - 1)
- table.insert(stack, cy)
- table.insert(stack, cx + 1)
- table.insert(stack, cy)
- table.insert(stack, cx)
- table.insert(stack, cy - 1)
- table.insert(stack, cx)
- table.insert(stack, cy + 1)
- end
- end
- end
- end
- function drawSurface(surf, x, y, surf2)
- for j=1,surf2.height,1 do
- for i=1,surf2.width,1 do
- surf:drawPixel(i + x - 1, j + y - 1, surf2.buffer[((j-1) * surf2.width + (i-1)) * 3 + 1], surf2.buffer[((j-1) * surf2.width + (i-1)) * 3 + 2], surf2.buffer[((j-1) * surf2.width + (i-1)) * 3 + 3])
- end
- end
- end
- function drawSurfacePart(surf, x, y, sx1, sy1, sx2, sy2, surf2)
- if sx2 < sx1 then
- local temp = sx1
- sx1 = sx2
- sx2 = temp
- end
- if sy2 < sy1 then
- local temp = sy1
- sy1 = sy2
- sy2 = temp
- end
- if sx2 < 1 then return end
- if sx1 > surface.width then return end
- if sy2 < 1 then return end
- if sy1 > surface.width then return end
- if sx1 < 1 then sx1 = 1 end
- if sx2 > surface.width then sx2 = surface.width end
- if sy1 < 1 then sy1 = 1 end
- if sy2 > surface.width then sy2 = surface.height end
- for j=sy1,sy2,1 do
- for i=sx1,sx2,1 do
- surf:drawPixel(x + i - sx1, y + j - sy1, surf2.buffer[((j-1) * surf2.width + (i-1)) * 3 + 1], surf2.buffer[((j-1) * surf2.width + (i-1)) * 3 + 2], surf2.buffer[((j-1) * surf2.width + (i-1)) * 3 + 3])
- end
- end
- end
- function drawSurfaceScaled(surf, x1, y1, x2, y2, surf2)
- local x = 0
- local width = 0
- local xinv = false
- local y = 0
- local height = 0
- local yinv = false
- if x2 >= x1 then
- x = x1
- width = x2 - x1 + 1
- else
- x = x2
- width = x1 - x2 + 1
- xinv = true
- end
- if y2 >= y1 then
- y = y1
- height = y2 - y1 + 1
- else
- y = y2
- height = y1 - y2 + 1
- yinv = true
- end
- local xscale = width / surf2.width
- local yscale = height / surf2.height
- for j=1,height,1 do
- for i=1,width,1 do
- local ii = i
- local jj = j
- if xinv then ii = width - ii + 1 end
- if yinv then jj = height - jj + 1 end
- local px = math.floor((ii - 0.5) / xscale) + 1
- local py = math.floor((jj - 0.5) / yscale) + 1
- surf:drawPixel(x + i - 1, y + j - 1, surf2.buffer[((py-1) * surf2.width + (px-1)) * 3 + 1], surf2.buffer[((py-1) * surf2.width + (px-1)) * 3 + 2], surf2.buffer[((py-1) * surf2.width + (px-1)) * 3 + 3])
- end
- end
- end
- function _colorToHex(color)
- if color then
- return string.format("%x", math.log(color)/math.log(2))
- else
- return " "
- end
- end
- function _bufferLine(buffer, width, x1, y1, x2, y2)
- local delta_x = x2 - x1
- local ix = delta_x > 0 and 1 or -1
- delta_x = 2 * math.abs(delta_x)
- local delta_y = y2 - y1
- local iy = delta_y > 0 and 1 or -1
- delta_y = 2 * math.abs(delta_y)
- buffer[(y1 - 1) * width + x1] = true
- if delta_x >= delta_y then
- local error = delta_y - delta_x / 2
- while x1 ~= x2 do
- if (error >= 0) and ((error ~= 0) or (ix > 0)) then
- error = error - delta_x
- y1 = y1 + iy
- end
- error = error + delta_y
- x1 = x1 + ix
- buffer[(y1 - 1) * width + x1] = true
- end
- else
- local error = delta_x - delta_y / 2
- while y1 ~= y2 do
- if (error >= 0) and ((error ~= 0) or (iy > 0)) then
- error = error - delta_y
- x1 = x1 + ix
- end
- error = error + delta_x
- y1 = y1 + iy
- buffer[(y1 - 1) * width + x1] = true
- end
- end
- end
- function _bufferFill(buffer, width, height)
- for j=1,height,1 do
- local lines = 0
- local wait = false
- for i=1,width,1 do
- local cur = buffer[(j - 1) * width + i]
- if cur and not wait then
- lines = lines + 1
- wait = true
- end
- if not cur and wait then
- wait = false
- end
- end
- if lines > 1 then
- local write = false
- local wait = false
- for i=1,width,1 do
- local cur = buffer[(j - 1) * width + i]
- if cur then
- wait = true
- else
- if wait then
- wait = false
- write = not write
- end
- if write then
- cur = true
- end
- end
- buffer[(j - 1) * width + i] = cur
- end
- end
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement