Advertisement
Piorjade

OpenComputers Double Buffering API [VER 2.0]

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