Advertisement
Piorjade

OpenComputers Double Buffering API [UPDATED]

Jul 27th, 2018
223
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 10.76 KB | None | 0 0
  1. --[[
  2.     OC Double Buffering Library
  3.  
  4.     Create a buffer with doublebuffer.newBuffer(x, y, width, height) which you
  5.     can use (almost) just like the gpu component API.
  6.  
  7.     Credits go to https://www.github.com/IgorTimofeev for his double buffering library
  8.     from which I found a solution for minimal RAM usage.
  9.    
  10. ~Overflwn
  11. ]]
  12.  
  13. local component = require("component")
  14. --get the first gpu found
  15. local gpu = component.proxy(component.list("gpu")())
  16. local doublebuffer = {}
  17.  
  18. function doublebuffer.toTableCoord(x, y, width)
  19.     --Convert a coordinate to a number used to index the buffer
  20.     return (y*width)-width+x
  21. end
  22.  
  23. function doublebuffer.toPixelCoord(num, width)
  24.     --Convert a number used to index the buffer to a coordinate
  25.     y = math.floor(num/width)+1
  26.     x = num%width
  27.     return x, y
  28. end
  29.  
  30. function doublebuffer.newBuffer(x, y, width, height)
  31.     local x = x
  32.     local y = y
  33.     local width = width
  34.     local height = height
  35.     local bufferFG = {}
  36.     local bufferBG = {}
  37.     local bufferChar = {}
  38.     local buf = {}
  39.     local currentbg = 0x000000
  40.     local currentfg = 0xffffff
  41.  
  42.     for i=1, width*height do
  43.         bufferFG[i] = currentfg
  44.         bufferBG[i] = currentbg
  45.         bufferChar[i] = " "
  46.     end
  47.  
  48.     function buf.getPos()
  49.         return x, y
  50.     end
  51.  
  52.     function buf.setPos(nx, ny)
  53.         x = nx
  54.         y = ny
  55.     end
  56.  
  57.     function buf.getSize()
  58.         return width, height
  59.     end
  60.  
  61.     function buf.setSize(w, h)
  62.         if w > width then
  63.             local diff = w-width
  64.             for i=1, height do
  65.                 for k=diff-1, 0, -1 do
  66.                     --[[table.insert(buffer, i*w-k, {
  67.                         bg = 0x000000,
  68.                         fg = 0xffffff,
  69.                         char = " "
  70.                     })]]
  71.                     table.insert(bufferFG, i*w-k, currentfg)
  72.                     table.insert(bufferBG, i*w-k, currentbg)
  73.                     table.insert(bufferChar, i*w-k, " ")
  74.                 end
  75.             end
  76.             width = w
  77.         elseif w < width then
  78.             local diff = width-w
  79.             for i=1, height do
  80.                 for k=1, diff do
  81.                     table.remove(bufferFG, i*w+1)
  82.                     table.remove(bufferBG, i*w+1)
  83.                     table.remove(bufferChar, i*w+1)
  84.                 end
  85.             end
  86.             width = w
  87.         end
  88.  
  89.         if h > height then
  90.             local diff = h-height
  91.             for i=0, diff-1 do
  92.                 for j=1, width do
  93.                     --[[table.insert(buffer, height*width+(i*width)+j, {
  94.                         bg = 0x000000,
  95.                         fg = 0xffffff,
  96.                         char = " "
  97.                     })]]
  98.                     table.insert(bufferBG, height*width+(i*width)+j, currentbg)
  99.                     table.insert(bufferFG, height*width+(i*width)+j, currentfg)
  100.                     table.insert(bufferChar, height*width+(i*width)+j, " ")
  101.                 end
  102.             end
  103.             height = h
  104.         elseif h < height then
  105.             local diff = height-h
  106.             local max = width*height
  107.             for i=1, diff do
  108.                 for k=0, width-1 do
  109.                     table.remove(bufferFG, (max-(i*width))+width-k)
  110.                     table.remove(bufferBG, (max-(i*width))+width-k)
  111.                     table.remove(bufferChar, (max-(i*width))+width-k)
  112.                 end
  113.             end
  114.             height = h
  115.         end
  116.     end
  117.  
  118.     local function getParts()
  119.         local used = {}
  120.         for i=1, height do
  121.             used[i] = {}
  122.             for k=1, width do
  123.                 used[i][k] = false
  124.             end
  125.         end
  126.  
  127.         local function setUsed(x, y)
  128.             used[y][x] = true
  129.         end
  130.  
  131.         local function isUsed(x, y)
  132.             return used[y][x]
  133.         end
  134.  
  135.         local parts = {}
  136.  
  137.         for cy=1, height do
  138.             for cx=1, width do
  139.                 if not isUsed(cx, cy) then
  140.                     local currentpart = {
  141.                         x = cx,
  142.                         y = cy,
  143.                         txt = " ",
  144.                         bg = currentbg,
  145.                         fg = currentfg,
  146.                         vertical = false
  147.                     }
  148.  
  149.                     local length_hor = 1
  150.                     local length_ver = 1
  151.                     local pixbg, pixfg, pixchar = buf.getPixel(cx, cy)
  152.                     --get same pixels horizontally
  153.                     for nx=cx+1, width do
  154.                         if not isUsed(nx, cy) then
  155.                             local npixbg, npixfg, npixchar = buf.getPixel(nx, cy)
  156.                             if npixbg == pixbg and (npixfg == pixfg or npixchar == " ") then
  157.                                 length_hor = length_hor+1
  158.                             else
  159.                                 break
  160.                             end
  161.                         else
  162.                             break
  163.                         end
  164.                     end
  165.  
  166.                     --get same pixels vertically
  167.                     for ny=cy+1, height do
  168.                         if not isUsed(cx, ny) then
  169.                             local npixbg, npixfg, npixchar = buf.getPixel(cx, ny)
  170.                             if npixbg == pixbg and (npixfg == pixfg or npixchar == " ") then
  171.                                 length_ver = length_ver+1
  172.                             else
  173.                                 break
  174.                             end
  175.                         else
  176.                             break
  177.                         end
  178.                     end
  179.                     if length_ver > length_hor then
  180.                         currentpart.txt = pixchar
  181.                         currentpart.bg = pixbg
  182.                         currentpart.fg = pixfg
  183.                         currentpart.vertical = true
  184.                         setUsed(cx, cy)
  185.                         for i=1, length_ver-1 do
  186.                             local npixbg, npixfg, npixchar = buf.getPixel(cx, cy+i)
  187.                             currentpart.txt = currentpart.txt..npixchar
  188.                             setUsed(cx, cy+i)
  189.                         end
  190.                     else
  191.                         currentpart.txt = pixchar
  192.                         currentpart.bg = pixbg
  193.                         currentpart.fg = pixfg
  194.                         setUsed(cx, cy)
  195.                         for i=1, length_hor-1 do
  196.                             local npixbg, npixfg, npixchar = buf.getPixel(cx+i, cy)
  197.                             currentpart.txt = currentpart.txt..npixchar
  198.                             setUsed(cx+i, cy)
  199.                         end
  200.                     end
  201.  
  202.                     table.insert(parts, currentpart)
  203.                 end
  204.             end
  205.         end
  206.  
  207.         return parts
  208.     end
  209.  
  210.     function buf.draw()
  211.         local parts = getParts()
  212.         local cbg = gpu.getBackground()
  213.         local cfg = gpu.getForeground()
  214.  
  215.         for each, part in ipairs(parts) do
  216.             if cbg ~= part.bg then
  217.                 gpu.setBackground(part.bg)
  218.                 cbg = part.bg
  219.             end
  220.  
  221.             if cfg ~= part.fg then
  222.                 gpu.setForeground(part.fg)
  223.                 cfg = part.fg
  224.             end
  225.  
  226.             gpu.set(x+part.x-1, y+part.y-1, part.txt, part.vertical)
  227.         end
  228.        
  229.     end
  230.  
  231.     function buf.set(nx, ny, text, vertical)
  232.         if not vertical then
  233.             if nx+#text-1 > width then
  234.                 local diff = nx+#text-1-width
  235.                 text = string.sub(text, 1, diff)
  236.             end
  237.  
  238.             for i=1, #text do
  239.                 local num = doublebuffer.toTableCoord(nx+i-1, ny, width)
  240.                 bufferBG[num] = currentbg
  241.                 bufferFG[num] = currentfg
  242.                 bufferChar[num] = string.sub(text, i, i)
  243.             end
  244.         else
  245.             if ny+#text-1 > height then
  246.                 local diff = ny+#text-1-height
  247.                 text = string.sub(text, 1, diff)
  248.             end
  249.  
  250.             for i=1, #text do
  251.                 local num = doublebuffer.toTableCoord(nx, ny+i-1, width)
  252.                 bufferBG[num] = currentbg
  253.                 bufferFG[num] = currentfg
  254.                 bufferChar[num] = string.sub(text, i, i)
  255.             end
  256.         end
  257.     end
  258.  
  259.     function buf.fill(nx, ny, nw, nh, char)
  260.         for j=ny, ny+nh-1 do
  261.             for i=nx, nx+nw-1 do
  262.                 if buf.getPixel(i, j) then
  263.                     local num = doublebuffer.toTableCoord(i, j, width)
  264.                     bufferBG[num] = currentbg
  265.                     bufferFG[num] = currentfg
  266.                     bufferChar[num] = char
  267.                 end
  268.             end
  269.         end
  270.     end
  271.  
  272.     function buf.getPixel(x, y)
  273.         --return buffer[doublebuffer.toTableCoord(x, y, width)]
  274.         local num = doublebuffer.toTableCoord(x, y, width)
  275.         return bufferBG[num], bufferFG[num], bufferChar[num]
  276.     end
  277.  
  278.     buf.get = buf.getPixel
  279.     buf.getResolution = buf.getSize
  280.     buf.setResolution = buf.setSize
  281.     buf.setDepth = gpu.setDepth
  282.     buf.getDepth = gpu.getDepth
  283.     buf.maxDepth = gpu.maxDepth
  284.     buf.getPaletteColor = gpu.getPaletteColor
  285.     buf.setPaletteColor = gpu.setPaletteColor
  286.  
  287.     function buf.getForeground()
  288.         return currentfg
  289.     end
  290.  
  291.     function buf.setForeground(col)
  292.         local old = currentfg
  293.         currentfg = col
  294.         return old
  295.     end
  296.  
  297.     function buf.getBackground()
  298.         return currentbg
  299.     end
  300.  
  301.     function buf.setBackground(col)
  302.         local old = currentbg
  303.         currentbg = col
  304.         return old
  305.     end
  306.  
  307.     buf.gpu = gpu
  308.  
  309.     function buf.copy(x, y, w, h, offx, offy)
  310.         local cbufBG = {}
  311.         local cbufFG = {}
  312.         local cbufChar = {}
  313.  
  314.         for i=0, h-1 do
  315.             for j=0, w-1 do
  316.                 local numa = (i*w)+j+1
  317.                 local numb = (y+i-1)*width + (x+j)
  318.                 if numb > 0 and numb <= width*height then
  319.                     cbufBG[numa] = bufferBG[num]
  320.                     cbufFG[numa] = bufferFG[num]
  321.                     cbufChar[numa] = bufferChar[num]
  322.                 end
  323.             end
  324.         end
  325.  
  326.         for i=0, h-1 do
  327.             for j=0, w-1 do
  328.                 local numa = (i*w)+j+1
  329.                 local numb = (y+i-1+offy)*width + (x+j+offx)
  330.                 if numb > 0 and numb <= width*height then
  331.                     bufferBG[numb] = cbufBG[numa]
  332.                     bufferFG[numb] = cbufFG[numa]
  333.                     bufferChar[numb] = cbufChar[numa]
  334.                 end
  335.             end
  336.         end
  337.     end
  338.  
  339.     return setmetatable(buf, {
  340.         __newindex = function(table, key, e)
  341.             error("attempt to change read-only table")
  342.         end,
  343.     })
  344.  
  345. end
  346.  
  347. return doublebuffer
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement