Advertisement
KaychenHH

DoubleBuffering.lua

Mar 22nd, 2022 (edited)
18
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 22.05 KB | None | 0 0
  1. local component = require("component")
  2. local unicode = require("unicode")
  3. local color = require("color")
  4. local image = require("image")
  5.  
  6. --------------------------------------------------------------------------------
  7.  
  8. local bufferWidth, bufferHeight
  9. local currentFrameBackgrounds, currentFrameForegrounds, currentFrameSymbols, newFrameBackgrounds, newFrameForegrounds, newFrameSymbols
  10. local drawLimitX1, drawLimitX2, drawLimitY1, drawLimitY2
  11. local GPUProxy, GPUProxyGetResolution, GPUProxySetResolution, GPUProxyBind, GPUProxyGetBackground, GPUProxyGetForeground, GPUProxySetBackground, GPUProxySetForeground, GPUProxyGet, GPUProxySet, GPUProxyFill
  12.  
  13. local mathCeil, mathFloor, mathModf, mathAbs = math.ceil, math.floor, math.modf, math.abs
  14. local tableInsert, tableConcat = table.insert, table.concat
  15. local colorBlend = color.blend
  16. local unicodeLen, unicodeSub = unicode.len, unicode.sub
  17.  
  18. --------------------------------------------------------------------------------
  19.  
  20. local function getIndex(x, y)
  21.     return bufferWidth * (y - 1) + x
  22. end
  23.  
  24. local function getCurrentFrameTables()
  25.     return currentFrameBackgrounds, currentFrameForegrounds, currentFrameSymbols
  26. end
  27.  
  28. local function getNewFrameTables()
  29.     return newFrameBackgrounds, newFrameForegrounds, newFrameSymbols
  30. end
  31.  
  32. --------------------------------------------------------------------------------
  33.  
  34. local function setDrawLimit(x1, y1, x2, y2)
  35.     drawLimitX1, drawLimitY1, drawLimitX2, drawLimitY2 = x1, y1, x2, y2
  36. end
  37.  
  38. local function resetDrawLimit()
  39.     drawLimitX1, drawLimitY1, drawLimitX2, drawLimitY2 = 1, 1, bufferWidth, bufferHeight
  40. end
  41.  
  42. local function getDrawLimit()
  43.     return drawLimitX1, drawLimitY1, drawLimitX2, drawLimitY2
  44. end
  45.  
  46. --------------------------------------------------------------------------------
  47.  
  48. local function flush(width, height)
  49.     if not width or not height then
  50.         width, height = GPUProxyGetResolution()
  51.     end
  52.  
  53.     currentFrameBackgrounds, currentFrameForegrounds, currentFrameSymbols, newFrameBackgrounds, newFrameForegrounds, newFrameSymbols = {}, {}, {}, {}, {}, {}
  54.     bufferWidth = width
  55.     bufferHeight = height
  56.     resetDrawLimit()
  57.  
  58.     for y = 1, bufferHeight do
  59.         for x = 1, bufferWidth do
  60.             tableInsert(currentFrameBackgrounds, 0x010101)
  61.             tableInsert(currentFrameForegrounds, 0xFEFEFE)
  62.             tableInsert(currentFrameSymbols, " ")
  63.  
  64.             tableInsert(newFrameBackgrounds, 0x010101)
  65.             tableInsert(newFrameForegrounds, 0xFEFEFE)
  66.             tableInsert(newFrameSymbols, " ")
  67.         end
  68.     end
  69. end
  70.  
  71. local function setResolution(width, height)
  72.     GPUProxySetResolution(width, height)
  73.     flush(width, height)
  74. end
  75.  
  76. local function getResolution()
  77.     return bufferWidth, bufferHeight
  78. end
  79.  
  80. local function getWidth()
  81.     return bufferWidth
  82. end
  83.  
  84. local function getHeight()
  85.     return bufferHeight
  86. end
  87.  
  88. local function bindScreen(...)
  89.     GPUProxyBind(...)
  90.     flush(GPUProxyGetResolution())
  91. end
  92.  
  93. local function getGPUProxy()
  94.     return GPUProxy
  95. end
  96.  
  97. local function updateGPUProxyMethods()
  98.     GPUProxyGet = GPUProxy.get
  99.     GPUProxyGetResolution = GPUProxy.getResolution
  100.     GPUProxyGetBackground = GPUProxy.getBackground
  101.     GPUProxyGetForeground = GPUProxy.getForeground
  102.  
  103.     GPUProxySet = GPUProxy.set
  104.     GPUProxySetResolution = GPUProxy.setResolution
  105.     GPUProxySetBackground = GPUProxy.setBackground
  106.     GPUProxySetForeground = GPUProxy.setForeground
  107.  
  108.     GPUProxyBind = GPUProxy.bind
  109.     GPUProxyFill = GPUProxy.fill
  110. end
  111.  
  112. local function bindGPU(address)
  113.     GPUProxy = component.proxy(address)
  114.     updateGPUProxyMethods()
  115.     flush(GPUProxyGetResolution())
  116. end
  117.  
  118. --------------------------------------------------------------------------------
  119.  
  120. local function rawSet(index, background, foreground, symbol)
  121.     newFrameBackgrounds[index], newFrameForegrounds[index], newFrameSymbols[index] = background, foreground, symbol
  122. end
  123.  
  124. local function rawGet(index)
  125.     return newFrameBackgrounds[index], newFrameForegrounds[index], newFrameSymbols[index]
  126. end
  127.  
  128. local function get(x, y)
  129.     if x >= 1 and y >= 1 and x <= bufferWidth and y <= bufferHeight then
  130.         local index = bufferWidth * (y - 1) + x
  131.         return newFrameBackgrounds[index], newFrameForegrounds[index], newFrameSymbols[index]
  132.     else
  133.         return 0x000000, 0x000000, " "
  134.     end
  135. end
  136.  
  137. local function set(x, y, background, foreground, symbol)
  138.     if x >= drawLimitX1 and y >= drawLimitY1 and x <= drawLimitX2 and y <= drawLimitY2 then
  139.         local index = bufferWidth * (y - 1) + x
  140.         newFrameBackgrounds[index], newFrameForegrounds[index], newFrameSymbols[index] = background, foreground, symbol
  141.     end
  142. end
  143.  
  144. local function drawRectangle(x, y, width, height, background, foreground, symbol, transparency)
  145.     local index, indexStepOnReachOfSquareWidth = bufferWidth * (y - 1) + x, bufferWidth - width
  146.     for j = y, y + height - 1 do
  147.         if j >= drawLimitY1 and j <= drawLimitY2 then
  148.             for i = x, x + width - 1 do
  149.                 if i >= drawLimitX1 and i <= drawLimitX2 then
  150.                     if transparency then
  151.                         newFrameBackgrounds[index], newFrameForegrounds[index] =
  152.                             colorBlend(newFrameBackgrounds[index], background, transparency),
  153.                             colorBlend(newFrameForegrounds[index], background, transparency)
  154.                     else
  155.                         newFrameBackgrounds[index], newFrameForegrounds[index], newFrameSymbols[index] = background, foreground, symbol
  156.                     end
  157.                 end
  158.  
  159.                 index = index + 1
  160.             end
  161.  
  162.             index = index + indexStepOnReachOfSquareWidth
  163.         else
  164.             index = index + bufferWidth
  165.         end
  166.     end
  167. end
  168.  
  169. local function clear(color, transparency)
  170.     drawRectangle(1, 1, bufferWidth, bufferHeight, color or 0x0, 0x000000, " ", transparency)
  171. end
  172.  
  173. local function copy(x, y, width, height)
  174.     local copyArray, index = { width, height }
  175.  
  176.     for j = y, y + height - 1 do
  177.         for i = x, x + width - 1 do
  178.             if i >= 1 and j >= 1 and i <= bufferWidth and j <= bufferHeight then
  179.                 index = bufferWidth * (j - 1) + i
  180.                 tableInsert(copyArray, newFrameBackgrounds[index])
  181.                 tableInsert(copyArray, newFrameForegrounds[index])
  182.                 tableInsert(copyArray, newFrameSymbols[index])
  183.             else
  184.                 tableInsert(copyArray, 0x0)
  185.                 tableInsert(copyArray, 0x0)
  186.                 tableInsert(copyArray, " ")
  187.             end
  188.         end
  189.     end
  190.  
  191.     return copyArray
  192. end
  193.  
  194. local function paste(startX, startY, picture)
  195.     local imageWidth = picture[1]
  196.     local bufferIndex, pictureIndex, bufferIndexStepOnReachOfImageWidth = bufferWidth * (startY - 1) + startX, 3, bufferWidth - imageWidth
  197.  
  198.     for y = startY, startY + picture[2] - 1 do
  199.         if y >= drawLimitY1 and y <= drawLimitY2 then
  200.             for x = startX, startX + imageWidth - 1 do
  201.                 if x >= drawLimitX1 and x <= drawLimitX2 then
  202.                     newFrameBackgrounds[bufferIndex] = picture[pictureIndex]
  203.                     newFrameForegrounds[bufferIndex] = picture[pictureIndex + 1]
  204.                     newFrameSymbols[bufferIndex] = picture[pictureIndex + 2]
  205.                 end
  206.  
  207.                 bufferIndex, pictureIndex = bufferIndex + 1, pictureIndex + 3
  208.             end
  209.  
  210.             bufferIndex = bufferIndex + bufferIndexStepOnReachOfImageWidth
  211.         else
  212.             bufferIndex, pictureIndex = bufferIndex + bufferWidth, pictureIndex + imageWidth * 3
  213.         end
  214.     end
  215. end
  216.  
  217. local function rasterizeLine(x1, y1, x2, y2, method)
  218.     local inLoopValueFrom, inLoopValueTo, outLoopValueFrom, outLoopValueTo, isReversed, inLoopValueDelta, outLoopValueDelta = x1, x2, y1, y2, false, mathAbs(x2 - x1), mathAbs(y2 - y1)
  219.     if inLoopValueDelta < outLoopValueDelta then
  220.         inLoopValueFrom, inLoopValueTo, outLoopValueFrom, outLoopValueTo, isReversed, inLoopValueDelta, outLoopValueDelta = y1, y2, x1, x2, true, outLoopValueDelta, inLoopValueDelta
  221.     end
  222.  
  223.     if outLoopValueFrom > outLoopValueTo then
  224.         outLoopValueFrom, outLoopValueTo = outLoopValueTo, outLoopValueFrom
  225.         inLoopValueFrom, inLoopValueTo = inLoopValueTo, inLoopValueFrom
  226.     end
  227.  
  228.     local outLoopValue, outLoopValueCounter, outLoopValueTriggerIncrement = outLoopValueFrom, 1, inLoopValueDelta / outLoopValueDelta
  229.     local outLoopValueTrigger = outLoopValueTriggerIncrement
  230.     for inLoopValue = inLoopValueFrom, inLoopValueTo, inLoopValueFrom < inLoopValueTo and 1 or -1 do
  231.         if isReversed then
  232.             method(outLoopValue, inLoopValue)
  233.         else
  234.             method(inLoopValue, outLoopValue)
  235.         end
  236.  
  237.         outLoopValueCounter = outLoopValueCounter + 1
  238.         if outLoopValueCounter > outLoopValueTrigger then
  239.             outLoopValue, outLoopValueTrigger = outLoopValue + 1, outLoopValueTrigger + outLoopValueTriggerIncrement
  240.         end
  241.     end
  242. end
  243.  
  244. local function rasterizeEllipse(centerX, centerY, radiusX, radiusY, method)
  245.     local function rasterizeEllipsePoints(XP, YP)
  246.         method(centerX + XP, centerY + YP)
  247.         method(centerX - XP, centerY + YP)
  248.         method(centerX - XP, centerY - YP)
  249.         method(centerX + XP, centerY - YP)
  250.     end
  251.  
  252.     local x, y, changeX, changeY, ellipseError, twoASquare, twoBSquare = radiusX, 0, radiusY * radiusY * (1 - 2 * radiusX), radiusX * radiusX, 0, 2 * radiusX * radiusX, 2 * radiusY * radiusY
  253.     local stoppingX, stoppingY = twoBSquare * radiusX, 0
  254.  
  255.     while stoppingX >= stoppingY do
  256.         rasterizeEllipsePoints(x, y)
  257.        
  258.         y, stoppingY, ellipseError = y + 1, stoppingY + twoASquare, ellipseError + changeY
  259.         changeY = changeY + twoASquare
  260.  
  261.         if (2 * ellipseError + changeX) > 0 then
  262.             x, stoppingX, ellipseError = x - 1, stoppingX - twoBSquare, ellipseError + changeX
  263.             changeX = changeX + twoBSquare
  264.         end
  265.     end
  266.  
  267.     x, y, changeX, changeY, ellipseError, stoppingX, stoppingY = 0, radiusY, radiusY * radiusY, radiusX * radiusX * (1 - 2 * radiusY), 0, 0, twoASquare * radiusY
  268.  
  269.     while stoppingX <= stoppingY do
  270.         rasterizeEllipsePoints(x, y)
  271.        
  272.         x, stoppingX, ellipseError = x + 1, stoppingX + twoBSquare, ellipseError + changeX
  273.         changeX = changeX + twoBSquare
  274.        
  275.         if (2 * ellipseError + changeY) > 0 then
  276.             y, stoppingY, ellipseError = y - 1, stoppingY - twoASquare, ellipseError + changeY
  277.             changeY = changeY + twoASquare
  278.         end
  279.     end
  280. end
  281.  
  282. local function drawLine(x1, y1, x2, y2, background, foreground, symbol)
  283.     rasterizeLine(x1, y1, x2, y2, function(x, y)
  284.         set(x, y, background, foreground, symbol)
  285.     end)
  286. end
  287.  
  288. local function drawEllipse(centerX, centerY, radiusX, radiusY, background, foreground, symbol)
  289.     rasterizeEllipse(centerX, centerY, radiusX, radiusY, function(x, y)
  290.         set(x, y, background, foreground, symbol)
  291.     end)
  292. end
  293.  
  294. local function drawText(x, y, textColor, data, transparency)
  295.     if y >= drawLimitY1 and y <= drawLimitY2 then
  296.         local charIndex, bufferIndex = 1, bufferWidth * (y - 1) + x
  297.        
  298.         for charIndex = 1, unicodeLen(data) do
  299.             if x >= drawLimitX1 and x <= drawLimitX2 then
  300.                 if transparency then
  301.                     newFrameForegrounds[bufferIndex] = colorBlend(newFrameBackgrounds[bufferIndex], textColor, transparency)
  302.                 else
  303.                     newFrameForegrounds[bufferIndex] = textColor
  304.                 end
  305.  
  306.                 newFrameSymbols[bufferIndex] = unicodeSub(data, charIndex, charIndex)
  307.             end
  308.  
  309.             x, bufferIndex = x + 1, bufferIndex + 1
  310.         end
  311.     end
  312. end
  313.  
  314. local function drawImage(startX, startY, picture, blendForeground)
  315.     local bufferIndex, pictureIndex, imageWidth, backgrounds, foregrounds, alphas, symbols = bufferWidth * (startY - 1) + startX, 1, picture[1], picture[3], picture[4], picture[5], picture[6]
  316.     local bufferIndexStepOnReachOfImageWidth = bufferWidth - imageWidth
  317.  
  318.     for y = startY, startY + picture[2] - 1 do
  319.         if y >= drawLimitY1 and y <= drawLimitY2 then
  320.             for x = startX, startX + imageWidth - 1 do
  321.                 if x >= drawLimitX1 and x <= drawLimitX2 then
  322.                     if alphas[pictureIndex] == 0 then
  323.                         newFrameBackgrounds[bufferIndex], newFrameForegrounds[bufferIndex] = backgrounds[pictureIndex], foregrounds[pictureIndex]
  324.                     elseif alphas[pictureIndex] > 0 and alphas[pictureIndex] < 1 then
  325.                         newFrameBackgrounds[bufferIndex] = colorBlend(newFrameBackgrounds[bufferIndex], backgrounds[pictureIndex], alphas[pictureIndex])
  326.                        
  327.                         if blendForeground then
  328.                             newFrameForegrounds[bufferIndex] = colorBlend(newFrameForegrounds[bufferIndex], foregrounds[pictureIndex], alphas[pictureIndex])
  329.                         else
  330.                             newFrameForegrounds[bufferIndex] = foregrounds[pictureIndex]
  331.                         end
  332.                     elseif alphas[pictureIndex] == 1 and symbols[pictureIndex] ~= " " then
  333.                         newFrameForegrounds[bufferIndex] = foregrounds[pictureIndex]
  334.                     end
  335.  
  336.                     newFrameSymbols[bufferIndex] = symbols[pictureIndex]
  337.                 end
  338.  
  339.                 bufferIndex, pictureIndex = bufferIndex + 1, pictureIndex + 1
  340.             end
  341.  
  342.             bufferIndex = bufferIndex + bufferIndexStepOnReachOfImageWidth
  343.         else
  344.             bufferIndex, pictureIndex = bufferIndex + bufferWidth, pictureIndex + imageWidth
  345.         end
  346.     end
  347. end
  348.  
  349. local function drawFrame(x, y, width, height, color)
  350.     local stringUp, stringDown, x2 = "┌" .. string.rep("─", width - 2) .. "┐", "└" .. string.rep("─", width - 2) .. "┘", x + width - 1
  351.    
  352.     drawText(x, y, color, stringUp); y = y + 1
  353.     for i = 1, height - 2 do
  354.         drawText(x, y, color, "│")
  355.         drawText(x2, y, color, "│")
  356.         y = y + 1
  357.     end
  358.     drawText(x, y, color, stringDown)
  359. end
  360.  
  361. --------------------------------------------------------------------------------
  362.  
  363. local function semiPixelRawSet(index, color, yPercentTwoEqualsZero)
  364.     local upperPixel, lowerPixel, bothPixel = "▀", "▄", " "
  365.     local background, foreground, symbol = newFrameBackgrounds[index], newFrameForegrounds[index], newFrameSymbols[index]
  366.  
  367.     if yPercentTwoEqualsZero then
  368.         if symbol == upperPixel then
  369.             if color == foreground then
  370.                 newFrameBackgrounds[index], newFrameForegrounds[index], newFrameSymbols[index] = color, foreground, bothPixel
  371.             else
  372.                 newFrameBackgrounds[index], newFrameForegrounds[index], newFrameSymbols[index] = color, foreground, symbol
  373.             end
  374.         elseif symbol == bothPixel then
  375.             if color ~= background then
  376.                 newFrameBackgrounds[index], newFrameForegrounds[index], newFrameSymbols[index] = background, color, lowerPixel
  377.             end
  378.         else
  379.             newFrameBackgrounds[index], newFrameForegrounds[index], newFrameSymbols[index] = background, color, lowerPixel
  380.         end
  381.     else
  382.         if symbol == lowerPixel then
  383.             if color == foreground then
  384.                 newFrameBackgrounds[index], newFrameForegrounds[index], newFrameSymbols[index] = color, foreground, bothPixel
  385.             else
  386.                 newFrameBackgrounds[index], newFrameForegrounds[index], newFrameSymbols[index] = color, foreground, symbol
  387.             end
  388.         elseif symbol == bothPixel then
  389.             if color ~= background then
  390.                 newFrameBackgrounds[index], newFrameForegrounds[index], newFrameSymbols[index] = background, color, upperPixel
  391.             end
  392.         else
  393.             newFrameBackgrounds[index], newFrameForegrounds[index], newFrameSymbols[index] = background, color, upperPixel
  394.         end
  395.     end
  396. end
  397.  
  398. local function semiPixelSet(x, y, color)
  399.     local yFixed = mathCeil(y / 2)
  400.     if x >= drawLimitX1 and yFixed >= drawLimitY1 and x <= drawLimitX2 and yFixed <= drawLimitY2 then
  401.         semiPixelRawSet(bufferWidth * (yFixed - 1) + x, color, y % 2 == 0)
  402.     end
  403. end
  404.  
  405. local function drawSemiPixelRectangle(x, y, width, height, color)
  406.     local index, evenYIndexStep, oddYIndexStep, realY, evenY =
  407.         bufferWidth * (mathCeil(y / 2) - 1) + x,
  408.         (bufferWidth - width),
  409.         width
  410.  
  411.     for pseudoY = y, y + height - 1 do
  412.         realY = mathCeil(pseudoY / 2)
  413.  
  414.         if realY >= drawLimitY1 and realY <= drawLimitY2 then
  415.             evenY = pseudoY % 2 == 0
  416.            
  417.             for pseudoX = x, x + width - 1 do
  418.                 if pseudoX >= drawLimitX1 and pseudoX <= drawLimitX2 then
  419.                     semiPixelRawSet(index, color, evenY)
  420.                 end
  421.  
  422.                 index = index + 1
  423.             end
  424.         else
  425.             index = index + width
  426.         end
  427.  
  428.         if evenY then
  429.             index = index + evenYIndexStep
  430.         else
  431.             index = index - oddYIndexStep
  432.         end
  433.     end
  434. end
  435.  
  436. local function drawSemiPixelLine(x1, y1, x2, y2, color)
  437.     rasterizeLine(x1, y1, x2, y2, function(x, y)
  438.         semiPixelSet(x, y, color)
  439.     end)
  440. end
  441.  
  442. local function drawSemiPixelEllipse(centerX, centerY, radiusX, radiusY, color)
  443.     rasterizeEllipse(centerX, centerY, radiusX, radiusY, function(x, y)
  444.         semiPixelSet(x, y, color)
  445.     end)
  446. end
  447.  
  448. --------------------------------------------------------------------------------
  449.  
  450. local function getPointTimedPosition(firstPoint, secondPoint, time)
  451.     return {
  452.         x = firstPoint.x + (secondPoint.x - firstPoint.x) * time,
  453.         y = firstPoint.y + (secondPoint.y - firstPoint.y) * time
  454.     }
  455. end
  456.  
  457. local function getConnectionPoints(points, time)
  458.     local connectionPoints = {}
  459.     for point = 1, #points - 1 do
  460.         tableInsert(connectionPoints, getPointTimedPosition(points[point], points[point + 1], time))
  461.     end
  462.     return connectionPoints
  463. end
  464.  
  465. local function getMainPointPosition(points, time)
  466.     if #points > 1 then
  467.         return getMainPointPosition(getConnectionPoints(points, time), time)
  468.     else
  469.         return points[1]
  470.     end
  471. end
  472.  
  473. local function drawSemiPixelCurve(points, color, precision)
  474.     local linePoints = {}
  475.     for time = 0, 1, precision or 0.01 do
  476.         tableInsert(linePoints, getMainPointPosition(points, time))
  477.     end
  478.    
  479.     for point = 1, #linePoints - 1 do
  480.         drawSemiPixelLine(mathFloor(linePoints[point].x), mathFloor(linePoints[point].y), mathFloor(linePoints[point + 1].x), mathFloor(linePoints[point + 1].y), color)
  481.     end
  482. end
  483.  
  484. --------------------------------------------------------------------------------
  485.  
  486. local function drawChanges(force)  
  487.     local index, indexStepOnEveryLine, changes = bufferWidth * (drawLimitY1 - 1) + drawLimitX1, (bufferWidth - drawLimitX2 + drawLimitX1 - 1), {}
  488.     local x, equalChars, equalCharsIndex, charX, charIndex, currentForeground
  489.     local currentFrameBackground, currentFrameForeground, currentFrameSymbol, changesCurrentFrameBackground, changesCurrentFrameBackgroundCurrentFrameForeground
  490.  
  491.     local changesCurrentFrameBackgroundCurrentFrameForegroundIndex
  492.  
  493.     for y = drawLimitY1, drawLimitY2 do
  494.         x = drawLimitX1
  495.         while x <= drawLimitX2 do          
  496.             -- Determine if some pixel data was changed (or if <force> argument was passed)
  497.             if
  498.                 currentFrameBackgrounds[index] ~= newFrameBackgrounds[index] or
  499.                 currentFrameForegrounds[index] ~= newFrameForegrounds[index] or
  500.                 currentFrameSymbols[index] ~= newFrameSymbols[index] or
  501.                 force
  502.             then
  503.                 -- Make pixel at both frames equal
  504.                 currentFrameBackground, currentFrameForeground, currentFrameSymbol = newFrameBackgrounds[index], newFrameForegrounds[index], newFrameSymbols[index]
  505.                 currentFrameBackgrounds[index] = currentFrameBackground
  506.                 currentFrameForegrounds[index] = currentFrameForeground
  507.                 currentFrameSymbols[index] = currentFrameSymbol
  508.  
  509.                 -- Look for pixels with equal chars from right of current pixel
  510.                 equalChars, equalCharsIndex, charX, charIndex = {currentFrameSymbol}, 2, x + 1, index + 1
  511.                 while charX <= drawLimitX2 do
  512.                     -- Pixels becomes equal only if they have same background and (whitespace char or same foreground)
  513.                     if 
  514.                         currentFrameBackground == newFrameBackgrounds[charIndex] and
  515.                         (
  516.                             newFrameSymbols[charIndex] == " " or
  517.                             currentFrameForeground == newFrameForegrounds[charIndex]
  518.                         )
  519.                     then
  520.                         -- Make pixel at both frames equal
  521.                         currentFrameBackgrounds[charIndex] = newFrameBackgrounds[charIndex]
  522.                         currentFrameForegrounds[charIndex] = newFrameForegrounds[charIndex]
  523.                         currentFrameSymbols[charIndex] = newFrameSymbols[charIndex]
  524.  
  525.                         equalChars[equalCharsIndex], equalCharsIndex = currentFrameSymbols[charIndex], equalCharsIndex + 1
  526.                     else
  527.                         break
  528.                     end
  529.  
  530.                     charX, charIndex = charX + 1, charIndex + 1
  531.                 end
  532.  
  533.                 -- Group pixels that need to be drawn by background and foreground
  534.                 changes[currentFrameBackground] = changes[currentFrameBackground] or {}
  535.                 changesCurrentFrameBackground = changes[currentFrameBackground]
  536.                 changesCurrentFrameBackground[currentFrameForeground] = changesCurrentFrameBackground[currentFrameForeground] or {index = 1}
  537.                 changesCurrentFrameBackgroundCurrentFrameForeground = changesCurrentFrameBackground[currentFrameForeground]
  538.                 changesCurrentFrameBackgroundCurrentFrameForegroundIndex = changesCurrentFrameBackgroundCurrentFrameForeground.index
  539.                
  540.                 changesCurrentFrameBackgroundCurrentFrameForeground[changesCurrentFrameBackgroundCurrentFrameForegroundIndex], changesCurrentFrameBackgroundCurrentFrameForegroundIndex = x, changesCurrentFrameBackgroundCurrentFrameForegroundIndex + 1
  541.                 changesCurrentFrameBackgroundCurrentFrameForeground[changesCurrentFrameBackgroundCurrentFrameForegroundIndex], changesCurrentFrameBackgroundCurrentFrameForegroundIndex = y, changesCurrentFrameBackgroundCurrentFrameForegroundIndex + 1
  542.                 changesCurrentFrameBackgroundCurrentFrameForeground[changesCurrentFrameBackgroundCurrentFrameForegroundIndex], changesCurrentFrameBackgroundCurrentFrameForegroundIndex = tableConcat(equalChars), changesCurrentFrameBackgroundCurrentFrameForegroundIndex + 1
  543.                
  544.                 x, index, changesCurrentFrameBackgroundCurrentFrameForeground.index = x + equalCharsIndex - 2, index + equalCharsIndex - 2, changesCurrentFrameBackgroundCurrentFrameForegroundIndex
  545.             end
  546.  
  547.             x, index = x + 1, index + 1
  548.         end
  549.  
  550.         index = index + indexStepOnEveryLine
  551.     end
  552.    
  553.     -- Draw grouped pixels on screen
  554.     for background, foregrounds in pairs(changes) do
  555.         GPUProxySetBackground(background)
  556.  
  557.         for foreground, pixels in pairs(foregrounds) do
  558.             if currentForeground ~= foreground then
  559.                 GPUProxySetForeground(foreground)
  560.                 currentForeground = foreground
  561.             end
  562.  
  563.             for i = 1, #pixels, 3 do
  564.                 GPUProxySet(pixels[i], pixels[i + 1], pixels[i + 2])
  565.             end
  566.         end
  567.     end
  568.  
  569.     changes = nil
  570. end
  571.  
  572. --------------------------------------------------------------------------------
  573.  
  574. bindGPU(component.getPrimary("gpu").address)
  575.  
  576. return {
  577.     getCoordinates = getCoordinates,
  578.     getIndex = getIndex,
  579.     setDrawLimit = setDrawLimit,
  580.     resetDrawLimit = resetDrawLimit,
  581.     getDrawLimit = getDrawLimit,
  582.     flush = flush,
  583.     setResolution = setResolution,
  584.     bindScreen = bindScreen,
  585.     bindGPU = bindGPU,
  586.     getGPUProxy = getGPUProxy,
  587.     getResolution = getResolution,
  588.     getWidth = getWidth,
  589.     getHeight = getHeight,
  590.     getCurrentFrameTables = getCurrentFrameTables,
  591.     getNewFrameTables = getNewFrameTables,
  592.  
  593.     rawSet = rawSet,
  594.     rawGet = rawGet,
  595.     get = get,
  596.     set = set,
  597.     clear = clear,
  598.     copy = copy,
  599.     paste = paste,
  600.     rasterizeLine = rasterizeLine,
  601.     rasterizeEllipse = rasterizeEllipse,
  602.     semiPixelRawSet = semiPixelRawSet,
  603.     semiPixelSet = semiPixelSet,
  604.     drawChanges = drawChanges,
  605.  
  606.     drawRectangle = drawRectangle,
  607.     drawLine = drawLine,
  608.     drawEllipse = drawEllipse,
  609.     drawText = drawText,
  610.     drawImage = drawImage,
  611.     drawFrame = drawFrame,
  612.  
  613.     drawSemiPixelRectangle = drawSemiPixelRectangle,
  614.     drawSemiPixelLine = drawSemiPixelLine,
  615.     drawSemiPixelEllipse = drawSemiPixelEllipse,
  616.     drawSemiPixelCurve = drawSemiPixelCurve,
  617. }
  618.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement