Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local c = require( "component" )
- local gpu = c.gpu
- buffer = {
- [ "drawBuffer" ] = { },
- [ "changeBuffer" ] = { },
- [ "oldBuffer" ] = { },
- [ "bufferW" ] = 0,
- [ "bufferH" ] = 0,
- [ "new" ] = function ()
- local o = {
- drawBuffer = { },
- changeBuffer = { },
- oldBuffer = { },
- bufferW = 0,
- bufferH = 0
- }
- local buffer_mt = { __index = buffer }
- return setmetatable( o, buffer_mt )
- end
- }
- function isInf(v)
- return v == 1/0
- end
- function buffer:fillChangeBuffer(assumeNilColor)
- local color = default( assumeNilColor, 0x000000 )
- local w, h = buffer:resolution()
- for y = 1, h do
- -- create new change buffer row
- if ( self.oldBuffer[ y ] or self.drawBuffer[ y ] ) then
- self.changeBuffer[ y ] = { }
- end
- -- compare cell by cell
- if self.oldBuffer[ y ] and self.drawBuffer[ y ] then
- for x = 1, w do
- self.changeBuffer[ y ][ x ] = not( self.oldBuffer[ y ][ x ] == self.drawBuffer[ y ][ x ] )
- end
- end
- -- assume changes only to elements that were there before
- if self.oldBuffer[ y ] and not self.drawBuffer[ y ] then
- for x, _ in pairs( self.oldBuffer[ y ] ) do
- self.changeBuffer[ y ][ x ] = true
- end
- end
- -- assume changes only to elements that are there now
- if not self.oldBuffer[ y ] and self.drawBuffer[ y ] then
- for x, _ in pairs( self.drawBuffer[ y ] ) do
- self.changeBuffer[ y ][ x ] = true
- end
- end
- end
- end
- function buffer:resolution()
- local w, h = gpu.getResolution()
- return w, h * 2
- end
- function buffer:clear()
- self:storeBuffer()
- self.drawBuffer = { }
- end
- function buffer:storeBuffer()
- self.changeBuffer = { }
- self.oldBuffer = { }
- for y, row in pairs( self.drawBuffer ) do
- for x, color in pairs( row ) do
- if not self.oldBuffer[ y ] then
- self.oldBuffer[ y ] = { }
- end
- self.oldBuffer[ y ][ x ] = color
- end
- end
- end
- function buffer:clearToColor(color)
- self:storeBuffer()
- color = default( color, 0x000000 )
- for y, row in pairs( self.drawBuffer ) do
- for x, _ in pairs( row ) do
- self:drawXY( x, y, color )
- end
- end
- end
- function default(v, def)
- if v == nil then
- return def
- else
- return v
- end
- end
- function buffer:renderBuffer(ox, oy, useChange, changeBufferBackgroundColor)
- local w, h = self:resolution()
- local yBias = 0
- local char = "▄"
- ox = default(x, 0)
- oy = default(y, 0)
- h = h - ox
- w = w - oy * 2
- useChange = default( useChange, false )
- changeBufferBackgroundColor = default( changeBufferBackgroundColor, 0x000000 )
- if useChange then
- self:fillChangeBuffer( changeBufferBackgroundColor )
- end
- --TODO iterate over changeBuffer instead of resolution if changeBuffer is requested
- --TODO possibly find and fill large single-color surfaces instead of setting each pixel
- for y = 1, h, 2 do
- local row = self.drawBuffer[ y ]
- local nextRow = self.drawBuffer[ y + 1 ]
- nextRow = default( nextRow, { } )
- if not( row == nil ) then
- for x = 1, w do
- local top = row[ x ]
- local bot = nextRow[ x ]
- if not( top == nil ) or not ( bot == nil ) then
- top = default( top, 0x000000 )
- bot = default( bot, 0x000000 )
- gpu.setBackground( top )
- gpu.setForeground( bot )
- if not useChange or ( useChange and self.changeBuffer[ y ][ x ] ) then
- -- optimization: use clear action where applicable
- if bot == top then
- gpu.set( ox + x, oy + y - yBias, ' ' )
- else
- gpu.set( ox + x, oy + y - yBias, char )
- end
- end
- end
- end
- end
- yBias = yBias + 1
- end
- end
- function buffer:drawXY( x, y, color )
- local w, h = self:resolution()
- if x > 0 and x <= w then
- if y > 0 and y <= h then
- if self.drawBuffer[ y ] == nil then
- self.drawBuffer[ y ] = { }
- end
- self.drawBuffer[ y ][ x ] = color
- end
- end
- end
- local function round( num, decs )
- if decs and decs > 0 then
- local mult = 10^decs
- return math.floor( num * mult + 0.5 ) / mult
- end
- return math.floor( num + 0.5 )
- end
- local function sum(...)
- local sum = 0
- for i,v in pairs({...}) do
- sum = sum + v
- end
- return sum
- end
- local function avg(...)
- return sum(...) / #arg
- end
- local function avgPoint( x1, y1, x2, y2 )
- return avg( x1, x2 ), avg( y1, y2 )
- end
- local function roundPoint(point)
- return round(point[0]), round(point[1])
- end
- function buffer:drawLine( x1, y1, x2, y2, color )
- local dx = x2 - x1
- local dy = y2 - y1
- local m = dy / dx
- local n = (m * x1 - y1) * -1
- if isInf( m ) then
- for y = y1, y2 do
- self:drawXY( x1, y, color )
- end
- return
- end
- for x = x1, x2 do
- local y = round( m * x + n )
- self:drawXY( x, y, color )
- end
- end
- function buffer:drawRectEx( x1, y1, w, h, color )
- local x2 = x1 + w
- local y2 = y1 + h
- self:drawRect( x1, x2, y1, y2, color )
- end
- function buffer:drawRect( x1, y1, x2, y2, color )
- for y = y1, y2 do
- for x = x1, x2 do
- self:drawXY( x, y, color )
- end
- end
- end
- function buffer:drawOutlineRectEx( x1, y1, w, h, color, thickness )
- thickness = default( thickness, 1 )
- self:drawLine( x1, y1, x1 + w, y1, color ) -- Top left - top right
- self:drawLine( x1, y1, x1, y1 + h, color ) -- Top left - bottom left
- self:drawLine( x1, y1 + h, x1 + w, y1 + h, color ) -- Bottom left - bottom right
- self:drawLine( x1 + w, y1, x1 + w, y1 + h, color ) -- Top right - bottom right
- if thickness > 1 then
- self:drawOutlineRectEx( x1 + 1, y1 + 1, w - 2, h - 2, thickness - 1 )
- end
- end
- function buffer:drawOutlineRect( x1, y1, x2, y2, color, thickness )
- local w = x2 - x1
- local h = y2 - y1
- thickness = default( thickness, 1 )
- self:drawOutlineRectEx( x1, y1, w, h, color, thickness )
- end
- return buffer
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement