Advertisement
PaymentOption

Faster buffer experiment

Dec 28th, 2013
120
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 8.01 KB | None | 0 0
  1. local BufferMetatable = { __index = getfenv() }
  2.  
  3. --[[
  4.     Returns the given hex value in decimal. This is used for unserializing the colors.
  5. ]]
  6. local function hexToDecimal (hexString)
  7.     return math.pow (2, tonumber (hexString, 16))
  8. end
  9.  
  10. --[[
  11.     Returns the given decimal number in a hex format. This is for serializing the colors.
  12. ]]
  13. local function decimalToHex (num)
  14.     return string.format ("%x", math.log (num) / math.log (2))
  15. end
  16.  
  17. --[[
  18.     Copies the contents of the buffer (text, text colors, and background colors) and
  19.     returns them along with the original buffer object.
  20. ]]
  21. function copyBuffer (self)
  22.     local function copyTable (_table)
  23.         local copy = {}
  24.        
  25.         for key, value in pairs (_table) do
  26.             copy[key] = value
  27.         end
  28.        
  29.         return copy
  30.     end
  31.    
  32.     return {
  33.         text       = copyTable (self.text),
  34.         textColors = copyTable (self.textColors),
  35.         backColors = copyTable (self.backColors)
  36.     },
  37.     self
  38. end
  39.  
  40. function getSize (self)
  41.     return self.width, self.height, self
  42. end
  43.  
  44. function clearLine (self)
  45.     self.textColors[self.cursorY] = self.textColor:rep (self.width)
  46.     self.backColors[self.cursorY] = self.backColor:rep (self.width)
  47.     self.text[self.cursorY]       = (" "):rep (self.width)
  48.    
  49.     return self
  50. end
  51.  
  52. function init (self)
  53.     for lineNumber = 1, self.height do
  54.         self.cursorY = lineNumber
  55.         self:clearLine()
  56.     end
  57.    
  58.     self.cursorY = 1
  59.     return self
  60. end
  61. clear = init
  62.  
  63. function setCursorBlink (self, shouldCursorBlink)
  64.     self.shouldCursorBlink = shouldCursorBlink
  65.     return self
  66. end
  67.  
  68. function isColor (self)
  69.     return self.isColor, self
  70. end
  71. isColour = isColor
  72.  
  73. function setCursorPos (self, x, y)
  74.     -- We might NaN or something. Had it happen before. Scary stuff.
  75.     self.cursorX = math.floor (x) or self.cursorX
  76.     self.cursorY = math.floor (y) or self.cursorY
  77.    
  78.     return self
  79. end
  80.  
  81. function getCursorPos (self)
  82.     return self.cursorX, self.cursorY, self
  83. end
  84.  
  85. function setTextColor (self, textColor)
  86.     self.textColor = decimalToHex (textColor)
  87.     return self
  88. end
  89. setTextColour = setTextColor
  90.  
  91. function setBackgroundColor (self, backColor)
  92.     self.backColor = decimalToHex (backColor)
  93.     return self
  94. end
  95. setBackgroundColour = setBackgroundColor
  96.  
  97. function scroll (self, numScrolls)
  98.     for timesScrolled = 1, math.abs (numScrolls) do
  99.         if numScrolls > 0 then
  100.             for lineNumber = 1, self.height do
  101.                 self.text[lineNumber]       = self.text[lineNumber + 1] or (" "):rep (self.width)
  102.                 self.textColors[lineNumber] = self.textColors[lineNumber + 1] or self.textColor:rep (self.width)
  103.                 self.backColors[lineNumber] = self.backColors[lineNumber + 1] or self.backColor:rep (self.width)
  104.             end
  105.         elseif numScrolls < 0 then
  106.             for lineNumber = self.height, 1, -1 do
  107.                 self.text[lineNumber]       = self.text[lineNumber - 1] or (" "):rep (self.width)
  108.                 self.textColors[lineNumber] = self.textColors[lineNumber - 1] or self.textColor:rep (self.width)
  109.                 self.backColors[lineNumber] = self.backColors[lineNumber - 1] or self.backColor:rep (self.width)
  110.             end
  111.         end
  112.     end
  113.    
  114.     return self
  115. end
  116.  
  117. function write (self, text)
  118.     text = ((text == nil) and "" or text):gsub ("\t", " "):gsub ("%c", "?")
  119.    
  120.     -- Something wrong with truncation, probably. When starting off screen, we get the truncated part on the right of the screen.
  121.     if self.cursorX < 1 then
  122.         local oldCursorX = self.cursorX
  123.        
  124.         self.cursorX = (oldCursorX + text:len() > 1) and 1 or oldCursorX + text:len()
  125.         text         = text:sub (math.max (1, 2 - oldCursorX))
  126.     end
  127.     if self.cursorX + text:len() > self.width + 1 then
  128.         text = text:sub (1, text:len() - (self.cursorX + text:len() - self.width))
  129.     end
  130.    
  131.     if self.cursorY > 0 and self.cursorY <= self.height and self.cursorX < self.width + 1 and self.cursorX > 0 then
  132.         self.text[self.cursorY]       = self.text[self.cursorY]:sub (1, self.cursorX - 1) .. text .. self.text[self.cursorY]:sub (self.cursorX + text:len())
  133.         self.textColors[self.cursorY] = self.textColors[self.cursorY]:sub (1, self.cursorX - 1) .. self.textColor:rep (text:len()) .. self.textColors[self.cursorY]:sub (self.cursorX + text:len())
  134.         self.backColors[self.cursorY] = self.backColors[self.cursorY]:sub (1, self.cursorX - 1) .. self.backColor:rep (text:len()) .. self.backColors[self.cursorY]:sub (self.cursorX + text:len())
  135.     end
  136.    
  137.     self.cursorX = self.cursorX + text:len()
  138.     return self
  139. end
  140.  
  141. --[[
  142.     Renders the contents of the buffer at the given coordinates.
  143. ]]
  144. function render (self, x, y)
  145.     local lastTextColor;
  146.     local lastBackColor;
  147.    
  148.     local backColor;
  149.     local textColor;
  150.    
  151.     local character;
  152.     local charactersToWriteX = 1
  153.     local charactersToWrite  = ""
  154.    
  155.     local function renderLine (lineNumber, line)
  156.         for posInLine = 1, self.width do
  157.             character = line:sub (posInLine, posInLine)
  158.             backColor = hexToDecimal (self.backColors[lineNumber]:sub (posInLine, posInLine))
  159.             textColor = hexToDecimal (self.textColors[lineNumber]:sub (posInLine, posInLine))
  160.            
  161.             if backColor ~= lastBackColor or textColor ~= lastTextColor then
  162.                 if charactersToWriteX ~= nil then
  163.                     term.native.setCursorPos (x + charactersToWriteX - 1, y + lineNumber - 1)
  164.                     term.native.write (charactersToWrite)
  165.                    
  166.                     charactersToWrite  = character
  167.                 end
  168.                 charactersToWriteX = posInLine
  169.                
  170.                 if backColor ~= lastBackColor then
  171.                     term.native.setBackgroundColor (backColor)
  172.                     lastBackColor = backColor
  173.                 end
  174.                 if textColor ~= lastTextColor then
  175.                     term.native.setTextColor (textColor)
  176.                     lastTextColor = textColor
  177.                 end
  178.             else
  179.                 charactersToWrite  = charactersToWrite .. character
  180.             end
  181.         end
  182.        
  183.         term.native.setCursorPos (x + charactersToWriteX - 1, y + lineNumber - 1)
  184.         term.native.write (charactersToWrite)
  185.        
  186.         charactersToWrite  = ""
  187.         charactersToWriteX = 1
  188.     end
  189.    
  190.     for lineNumber, line in pairs (self.text) do
  191.         -- Check if there any inconsistencies between the copy of the buffer and the main buffer.
  192.         -- This prevents any unnecessary line updates.
  193.         if self.copy.text[lineNumber] ~= self.text[lineNumber]
  194.         or self.copy.textColors[lineNumber] ~= self.textColors[lineNumber]
  195.         or self.copy.backColors[lineNumber] ~= self.backColors[lineNumber] then
  196.             renderLine (lineNumber, line)
  197.         end
  198.     end
  199.     -- Update the copy of the buffer with the current state of the buffer.
  200.     self.copy = self:copyBuffer()
  201.    
  202.     term.native.setCursorPos (x + self.cursorX - 1, y + self.cursorY - 1)
  203.     term.native.setCursorBlink (self.shouldCursorBlink)
  204.    
  205.     return self
  206. end
  207.  
  208. function new (width, height, isColor)
  209.     local self = {
  210.         width   = width,
  211.         height  = height,
  212.         isColor = isColor,
  213.        
  214.         cursorX = 1,
  215.         cursorY = 1,
  216.        
  217.         textColor = "0",
  218.         backColor = "f",
  219.        
  220.         shouldCursorBlink = true,
  221.        
  222.         textColors = {},
  223.         backColors = {},
  224.         text       = {},
  225.        
  226.         copy = nil
  227.     }
  228.    
  229.     setmetatable (self, BufferMetatable)
  230.     self:init()
  231.     self.copy = self:copyBuffer()
  232.    
  233.     return self
  234. end
  235.  
  236. function redirect (self)
  237.     local redirectTable = {}
  238.    
  239.     for functionName, _ in pairs (term.native) do
  240.         redirectTable[functionName] = function (...)
  241.             return self[functionName] (self, ...)
  242.         end
  243.     end
  244.    
  245.     return redirectTable, self
  246. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement