Advertisement
Guest User

libbuffer.lua

a guest
Jun 24th, 2018
88
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 5.93 KB | None | 0 0
  1. local c       = require( "component" )
  2. local gpu     = c.gpu
  3.  
  4. buffer   = {
  5.   [ "drawBuffer" ] = { },
  6.   [ "changeBuffer" ] = { },
  7.   [ "oldBuffer" ] = { },
  8.   [ "bufferW" ] = 0,
  9.   [ "bufferH" ] = 0,
  10.  
  11.   [ "new" ] = function ()
  12.     local o = {
  13.       drawBuffer = { },
  14.       changeBuffer = { },
  15.       oldBuffer = { },
  16.       bufferW = 0,
  17.       bufferH = 0
  18.     }
  19.  
  20.     local buffer_mt = { __index = buffer }
  21.     return setmetatable( o, buffer_mt )
  22.   end
  23. }
  24.  
  25. function isInf(v)
  26.   return v == 1/0
  27. end
  28.  
  29. function buffer:fillChangeBuffer(assumeNilColor)
  30.   local color = default( assumeNilColor, 0x000000 )
  31.   local w, h  = buffer:resolution()
  32.  
  33.   for y = 1, h do
  34.     -- create new change buffer row
  35.     if ( self.oldBuffer[ y ] or self.drawBuffer[ y ] ) then
  36.       self.changeBuffer[ y ] = { }
  37.     end
  38.  
  39.     -- compare cell by cell
  40.     if self.oldBuffer[ y ] and self.drawBuffer[ y ] then
  41.       for x = 1, w do
  42.         self.changeBuffer[ y ][ x ] = not( self.oldBuffer[ y ][ x ] == self.drawBuffer[ y ][ x ] )
  43.       end
  44.     end
  45.  
  46.     -- assume changes only to elements that were there before
  47.     if self.oldBuffer[ y ] and not self.drawBuffer[ y ] then
  48.       for x, _ in pairs( self.oldBuffer[ y ] ) do
  49.         self.changeBuffer[ y ][ x ] = true
  50.       end
  51.     end
  52.  
  53.     -- assume changes only to elements that are there now
  54.     if not self.oldBuffer[ y ] and self.drawBuffer[ y ] then
  55.       for x, _ in pairs( self.drawBuffer[ y ] ) do
  56.         self.changeBuffer[ y ][ x ] = true
  57.       end
  58.     end
  59.   end
  60. end
  61.  
  62. function buffer:resolution()
  63.   local w, h = gpu.getResolution()
  64.   return w, h * 2
  65. end
  66.  
  67. function buffer:clear()
  68.   self:storeBuffer()
  69.   self.drawBuffer = { }
  70. end
  71.  
  72. function buffer:storeBuffer()
  73.   self.changeBuffer = { }
  74.   self.oldBuffer = { }
  75.  
  76.   for y, row in pairs( self.drawBuffer ) do
  77.     for x, color in pairs( row ) do
  78.       if not self.oldBuffer[ y ] then
  79.         self.oldBuffer[ y ] = { }
  80.       end
  81.  
  82.       self.oldBuffer[ y ][ x ] = color
  83.     end
  84.   end
  85. end
  86.  
  87. function buffer:clearToColor(color)
  88.   self:storeBuffer()
  89.  
  90.   color = default( color, 0x000000 )
  91.  
  92.   for y, row in pairs( self.drawBuffer ) do
  93.     for x, _ in pairs( row ) do
  94.       self:drawXY( x, y, color )
  95.     end
  96.   end
  97. end
  98.  
  99. function default(v, def)
  100.   if v == nil then
  101.     return def
  102.   else
  103.     return v
  104.   end
  105. end
  106.  
  107. function buffer:renderBuffer(ox, oy, useChange, changeBufferBackgroundColor)
  108.   local w, h                  = self:resolution()
  109.   local yBias                 = 0
  110.   local char                  = "▄"
  111.   ox                          = default(x, 0)
  112.   oy                          = default(y, 0)
  113.   h                           = h - ox
  114.   w                           = w - oy * 2
  115.   useChange                   = default( useChange, false )
  116.   changeBufferBackgroundColor = default( changeBufferBackgroundColor, 0x000000 )
  117.  
  118.   if useChange then
  119.     self:fillChangeBuffer( changeBufferBackgroundColor )
  120.   end
  121.  
  122.   --TODO iterate over changeBuffer instead of resolution if changeBuffer is requested
  123.   --TODO possibly find and fill large single-color surfaces instead of setting each pixel
  124.   for y = 1, h, 2 do
  125.     local row     = self.drawBuffer[ y ]
  126.     local nextRow = self.drawBuffer[ y + 1 ]
  127.     nextRow       = default( nextRow, { } )
  128.  
  129.     if not( row == nil ) then
  130.       for x = 1, w do
  131.         local top = row[ x ]
  132.         local bot = nextRow[ x ]
  133.         if not( top == nil ) or not ( bot == nil ) then
  134.           top = default( top, 0x000000 )
  135.           bot = default( bot, 0x000000 )
  136.  
  137.           gpu.setBackground( top )
  138.           gpu.setForeground( bot )
  139.  
  140.           if not useChange or ( useChange and self.changeBuffer[ y ][ x ] ) then
  141.             -- optimization: use clear action where applicable
  142.             if bot == top then
  143.               gpu.set( ox + x, oy + y - yBias, ' ' )
  144.             else
  145.               gpu.set( ox + x, oy + y - yBias, char )
  146.             end
  147.           end
  148.         end
  149.       end
  150.     end
  151.  
  152.     yBias = yBias + 1
  153.   end
  154. end
  155.  
  156. function buffer:drawXY( x, y, color )
  157.   local w, h = self:resolution()
  158.  
  159.   if x > 0 and x <= w then
  160.     if y > 0 and y <= h then
  161.       if self.drawBuffer[ y ] == nil then
  162.         self.drawBuffer[ y ] = { }
  163.       end
  164.  
  165.       self.drawBuffer[ y ][ x ] = color
  166.     end
  167.   end
  168. end
  169.  
  170. local function round( num, decs )
  171.   if decs and decs > 0 then
  172.     local mult = 10^decs
  173.     return math.floor( num * mult + 0.5 ) / mult
  174.   end
  175.  
  176.   return math.floor( num + 0.5 )
  177. end
  178.  
  179. local function sum(...)
  180.   local sum = 0
  181.   for i,v in pairs({...}) do
  182.     sum = sum + v
  183.   end
  184.   return sum
  185. end
  186.  
  187. local function avg(...)
  188.   return sum(...) / #arg
  189. end
  190.  
  191. local function avgPoint( x1, y1, x2, y2 )
  192.   return avg( x1, x2 ), avg( y1, y2 )
  193. end
  194.  
  195. local function roundPoint(point)
  196.   return round(point[0]), round(point[1])
  197. end
  198.  
  199. function buffer:drawLine( x1, y1, x2, y2, color )
  200.   local dx = x2 - x1
  201.   local dy = y2 - y1
  202.   local m  = dy / dx
  203.   local n  = (m * x1 - y1) * -1
  204.  
  205.   if isInf( m ) then
  206.     for y = y1, y2 do
  207.       self:drawXY( x1, y, color )
  208.     end
  209.  
  210.     return
  211.   end
  212.  
  213.   for x = x1, x2 do
  214.     local y = round( m * x + n )
  215.     self:drawXY( x, y, color )
  216.   end  
  217. end
  218.  
  219. function buffer:drawRectEx( x1, y1, w, h, color )
  220.   local x2 = x1 + w
  221.   local y2 = y1 + h
  222.  
  223.   self:drawRect( x1, x2, y1, y2, color )
  224. end
  225.  
  226. function buffer:drawRect( x1, y1, x2, y2, color )
  227.   for y = y1, y2 do
  228.     for x = x1, x2 do
  229.       self:drawXY( x, y, color )
  230.     end
  231.   end
  232. end
  233.  
  234. function buffer:drawOutlineRectEx( x1, y1, w, h, color, thickness )
  235.   thickness = default( thickness, 1 )
  236.  
  237.   self:drawLine( x1, y1, x1 + w, y1, color )  -- Top left - top right
  238.   self:drawLine( x1, y1, x1, y1 + h, color )  -- Top left - bottom left
  239.   self:drawLine( x1, y1 + h, x1 + w, y1 + h, color ) -- Bottom left - bottom right
  240.   self:drawLine( x1 + w, y1, x1 + w, y1 + h, color ) -- Top right - bottom right
  241.  
  242.   if thickness > 1 then
  243.     self:drawOutlineRectEx( x1 + 1, y1 + 1, w - 2, h - 2, thickness - 1 )
  244.   end
  245. end
  246.  
  247. function buffer:drawOutlineRect( x1, y1, x2, y2, color, thickness )
  248.   local w = x2 - x1
  249.   local h = y2 - y1
  250.   thickness = default( thickness, 1 )
  251.  
  252.   self:drawOutlineRectEx( x1, y1, w, h, color, thickness )  
  253. end
  254.  
  255. return buffer
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement