King0fGamesYami

Stitch

May 28th, 2015
645
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. local stitch = shell and {} or getfenv()
  2.  
  3. local string_sub, string_rep, unpack = string.sub, string.rep, unpack or table.unpack
  4.  
  5. local internalX, internalY, internalCurrentTextColor, internalCurrentBackgroundColor, internalUpdatedLines, internalText, internalTextColor, internalBackgroundColor, tMonitors, tMonitorSizes = 1, 1, colors.white, colors.black, {}, {}, {}, {}, {}, {{}}, {{}}
  6. local isPatch, bVisible = {}, true
  7.  
  8. local string_space = " "
  9.  
  10. --[[taken from window API]]
  11. local tHex = {
  12.     [ colors.white ] = "0",
  13.     [ colors.orange ] = "1",
  14.     [ colors.magenta ] = "2",
  15.     [ colors.lightBlue ] = "3",
  16.     [ colors.yellow ] = "4",
  17.     [ colors.lime ] = "5",
  18.     [ colors.pink ] = "6",
  19.     [ colors.gray ] = "7",
  20.     [ colors.lightGray ] = "8",
  21.     [ colors.cyan ] = "9",
  22.     [ colors.purple ] = "a",
  23.     [ colors.blue ] = "b",
  24.     [ colors.brown ] = "c",
  25.     [ colors.green ] = "d",
  26.     [ colors.red ] = "e",
  27.     [ colors.black ] = "f",
  28. }
  29. --[[]]
  30.  
  31. local function update()
  32.     if not bVisible then
  33.         return
  34.     end
  35.     local currentY = 1 --how far down are we in the buffer?
  36.     for y = 1, #tMonitors do --iterate through the rows of monitors
  37.         local currentX, height = 1, tMonitorSizes[ y ][ 1 ][ 2 ] --how far right are we in the buffer, how high is the current monitor row?
  38.         for x = 1, #tMonitors[ y ] do --iterate through the columns of monitors
  39.             local mon = tMonitors[ y ][ x ] --the current monitor object
  40.             local width = tMonitorSizes[ y ][ x ][ 1 ] --width of the current column
  41.             for y = currentY, currentY + height do --iterate through the buffer, starting at the last pixel of the last monitor plus one, ending at the last pixel of this monitor
  42.                 if internalUpdatedLines[ y ] then --if the line was updated, we'll blit the entire line (CC updates this way, so no performance loss)
  43.                     mon.setCursorPos( 1, y - currentY + 1 )
  44.                     mon.blit( string_sub( internalText[ y ], currentX, currentX + width ), string_sub( internalTextColor[ y ], currentX, currentX + width ), string_sub( internalBackgroundColor[ y ], currentX, currentX + width ) )
  45.                 end
  46.             end
  47.             currentX = currentX + width --add the width of the current monitor column to the currentX value
  48.         end
  49.         currentY = currentY + height --add the height of the current monitor row to the currentY value
  50.     end
  51.     internalUpdatedLines = {} --reset the lines which need to be drawn
  52. end
  53.  
  54. stitch.write = function( text ) --I'm lazy, just turn it into a problem for blit
  55.     sText = tostring( text )
  56.     local len = #sText
  57.     stitch.blit( sText, string_rep( tHex[ internalCurrentTextColor ], len ), string_rep( tHex[ internalCurrentBackgroundColor ], len ) )
  58. end
  59.  
  60. stitch.blit = function( text, textColors, backgroundColors )
  61.     local text_len = #text
  62.     if not internalText[ internalY ] or internalX + text_len < 1 then --if we're off screen; do nothing
  63.         return
  64.     end
  65.     local maxx, maxy = stitch.getSize()
  66.     local beforeMaxLen, afterMinLen = internalX - 1, internalX + text_len
  67.  
  68.     local minLen, maxLen = 2 - internalX, maxx -internalX + 1
  69.  
  70.     if internalX < 1 and maxx < internalX + text_len then
  71.         --ooh we have a really long string
  72.         internalText[ internalY ] = string_sub( text, minLen, maxLen )
  73.         internalTextColor[ internalY] = string_sub( textColors, minLen, maxLen )
  74.         internalBackgroundColor[ internalY ] = string_sub( backgroundColors, minLen, maxLen )
  75.     elseif internalX < 1 then
  76.         internalText[ internalY ] = string_sub( text, minLen ) .. string_sub( internalText[ internalY ], afterMinLen )
  77.         internalTextColor[ internalY ] = string_sub( textColors, minLen ) .. string_sub( internalTextColor[ internalY ], afterMinLen )
  78.         internalBackgroundColor[ internalY ] = string_sub( backgroundColors, minLen ) .. string_sub( internalBackgroundColor[ internalY ], afterMinLen )
  79.     elseif maxx < internalX + text_len then
  80.         internalText[ internalY ] = string_sub( internalText[ internalY ], 1, beforeMaxLen ) .. string_sub( text, 1, maxLen )
  81.         internalTextColor[ internalY ] = string_sub( internalTextColor[ internalY ], 1, beforeMaxLen ) .. string_sub( textColors, 1, maxLen )
  82.         internalBackgroundColor[ internalY ] = string_sub( internalBackgroundColor[ internalY ], 1, beforeMaxLen ) .. string_sub( backgroundColors, 1, maxLen )
  83.     else
  84.         internalText[ internalY ] = string_sub( internalText[ internalY ], 1, beforeMaxLen ) .. text .. string_sub( internalText[ internalY ], afterMinLen )
  85.         internalTextColor[ internalY ] = string_sub( internalTextColor[ internalY ], 1, beforeMaxLen ) .. textColors.. string_sub( internalTextColor[ internalY ], afterMinLen )
  86.         internalBackgroundColor[ internalY ] = string_sub( internalBackgroundColor[ internalY ], 1, beforeMaxLen ) .. backgroundColors .. string_sub( internalBackgroundColor[ internalY ], afterMinLen )
  87.     end
  88.     internalUpdatedLines[ internalY ] = true
  89. end
  90.  
  91. stitch.clear = function()
  92.     --clears the screen with the current background color/text color
  93.     local maxx, maxy = stitch.getSize()
  94.     local newLineText, newLineTextColor, newLineBackgroundColor = string_rep( string_space, maxx ), string_rep( tHex[ internalCurrentTextColor ], maxx ), string_rep( tHex[ internalCurrentBackgroundColor ], maxx )
  95.     for y = 1, maxy do
  96.         internalText[ y ] = newLineText
  97.         internalTextColor[ y ] = newLineTextColor
  98.         internalBackgroundColor[ y ] = newLineBackgroundColor
  99.         internalUpdatedLines[ y ] = true
  100.     end
  101. end
  102.  
  103. stitch.clearLine = function()
  104.     --clears the current line
  105.     local maxx, maxy = stitch.getSize()
  106.     internalText[ internalY ] = string_rep( string_space, maxx )
  107.     internalTextColor[ internalY ] = string_rep( tHex[ internalCurrentTextColor ], maxx )
  108.     internalBackgroundColor[ internalY ] = string_rep( tHex[ internalCurrentBackgroundColor ], maxx )
  109.     internalUpdatedLines[ internalY ] = true
  110. end
  111.  
  112. stitch.getCursorPos = function()
  113.     --return the current cursor position
  114.     return internalX, internalY
  115. end
  116.  
  117. stitch.setCursorPos = function( x, y )
  118.     internalX, internalY = x, y
  119.     --todo: which friggin monitor do I set this to???
  120. end
  121.  
  122. stitch.setCursorBlink = function( bool )
  123.     for y, t in ipairs( tMonitors ) do
  124.         for x, mon in ipairs( t ) do
  125.             mon.setCursorBlink( bool )
  126.         end
  127.     end
  128. end
  129.  
  130. stitch.isColor = function()
  131.     --return boolean isColor
  132.     --if all monitors support color, mine does.  Otherwise, it does not. (or rather, it does in certain places, but I'll tell you it doesn't)
  133.     for y, t in ipairs( tMonitors ) do
  134.         for x, mon in ipairs( t ) do
  135.             if not mon.isColor() then
  136.                 return false
  137.             end
  138.         end
  139.     end
  140.     return true
  141. end
  142.  
  143. stitch.setPaletteColor = function( ... )
  144.     for y, t in ipairs( tMonitors) do
  145.         for x, mo in ipairs( t ) do
  146.             mon.setPaletteColor( ... )
  147.         end
  148.     end
  149. end
  150.  
  151. stitch.setPaletteColour = stitch.setPaletteColor
  152.  
  153. stitch.isColour = stitch.isColor
  154.  
  155. stitch.getSize = function()
  156.     --return number x, number y
  157.     local maxx, maxy = 0, 0
  158.     for y, t in ipairs( tMonitorSizes ) do
  159.         maxy = maxy + t[ 1 ][ 2 ]
  160.     end
  161.     for x, mon in ipairs( tMonitorSizes[ 1 ] ) do
  162.         maxx = maxx + mon[ 1 ]
  163.     end
  164.     return maxx, maxy
  165. end
  166.  
  167. stitch.scroll = function( n )
  168.     local _internalText, _internalTextColor, _internalBackgroundColor = {}, {}, {}
  169.     local maxx, maxy = stitch.getSize()
  170.     for i = 1, maxy do
  171.         _internalText[ i ] = internalText[ i - n ] or string_rep( string_space, maxx )
  172.         _internalTextColor[ i ] = internalText[ i - n ] or tHex[ internalCurrentTextColor ]:rep( maxx )
  173.         _internalBackgroundColor[ i ] = internalText[ i - n ] or tHex[ internalCurrentBackgroundColor ]:rep( maxx )
  174.         internalUpdatedLines[ i ] = true
  175.     end
  176.     internalText, internalTextColor, internalBackgroundColor = _internalText, _internalTextColor, _internalBackgroundColor
  177. end
  178.  
  179. stitch.setTextColor = function( color )
  180.     internalCurrentTextColor = color
  181. end
  182.  
  183. stitch.setTextColour = stitch.setTextColor
  184.  
  185. stitch.getTextColor = function()
  186.     return internalCurrentTextColor
  187. end
  188.  
  189. stitch.getTextColour = stitch.getTextColor
  190.  
  191. stitch.setBackgroundColor = function( color )
  192.     internalCurrentBackgroundColor = color
  193. end
  194.  
  195. stitch.setBackgroundColour = stitch.setBackgroundColor
  196.  
  197. stitch.getBackgroundColor = function()
  198.     return internalCurrentBackgroundColor
  199. end
  200.  
  201. stitch.getBackgroundColour = stitch.getBackgroundColor
  202.  
  203. stitch.setTextScale = function( scale )
  204.     for y, t in ipairs( tMonitors ) do
  205.         tMonitorSizes[ y ] = tMonitorSizes[ y ] or {}
  206.         for x, mon in ipairs( t ) do
  207.             mon.setTextScale( scale )
  208.             tMonitorSizes[ y ][ x ] = {mon.getSize()}
  209.         end
  210.     end
  211. end
  212.  
  213. stitch.setMonitors = function( mons )
  214.     tMonitors = {}
  215.     for y, t in ipairs( mons ) do
  216.         tMonitors[ y ] = tMonitors[ y ] or {}
  217.         for x, sName in ipairs( t ) do
  218.             tMonitors[ y ][ x ] = peripheral.wrap( sName )
  219.             tMonitors[ y ][ x ].name = sName
  220.             isPatch[ sName ] = true
  221.         end
  222.     end
  223.  
  224.     stitch.setTextScale( 1 )
  225.     stitch.clear()
  226. end
  227.  
  228. local function project( name, posx, posy )
  229.     local offsetY = 0
  230.     for y, t in ipairs( tMonitors ) do
  231.         local offsetX = 0
  232.         for x, mon in ipairs( t ) do
  233.             if mon.name == name then
  234.                 return posx + offsetX, posy + offsetY
  235.             end
  236.             offsetX = offsetX + tMonitorSizes[ y ][ x ][ 1 ]
  237.         end
  238.         offsetY = offsetY + tMonitorSizes[ y ][ 1 ][ 2 ]
  239.     end
  240. end
  241.  
  242. --hacking into the event system to make stuff work
  243. local _yield, id, doAutoBuffer = coroutine.yield, os.startTimer( 0.5 ), true
  244.  
  245. _G.coroutine.yield = function( ... )
  246.     local tEventData = {_yield( ... )}
  247.     if doAutoBuffer and tEventData[ 1 ] == "timer" and tEventData[ 2 ] == id then
  248.         id = os.startTimer( 0.05 )
  249.         update()
  250.     elseif tEventData[ 1 ] == "monitor_touch" and isPatch[ tEventData[ 2 ] ] then
  251.         return "monitor_touch", "stitch", project( tEventData[ 2 ], tEventData[ 3 ], tEventData[ 4 ] )
  252.     end
  253.     return unpack( tEventData )
  254. end
  255.  
  256. stitch.disableAutoBuffer = function()
  257.     doAutoBuffer = false
  258. end
  259.  
  260. stitch.buffer = function()
  261.     update()
  262. end
  263.  
  264. stitch.setVisible = function( visible )
  265.     if visible and not bVisible then
  266.         stitch.redraw()
  267.     end
  268.     bVisible = visible
  269. end
  270.  
  271. stitch.redraw = function()
  272.     if not bVisible then
  273.         return
  274.     end
  275.     local maxx, maxy = stitch.getSize()
  276.     for y = 1, maxy do
  277.         internalUpdatedLines[ y ] = true
  278.     end
  279.     update()
  280. end
  281.  
  282. --fancy peripheral stuff
  283. local isPresent, getType, getMethods, call, wrap, find, getNames, methods = peripheral.isPresent, peripheral.getType, peripheral.getMethods, peripheral.call, peripheral.wrap, peripheral.find, peripheral.getNames, {}
  284.  
  285. for k, v in pairs( stitch ) do
  286.     methods[ #methods + 1 ] = k
  287. end
  288.  
  289. peripheral.isPresent = function( side )
  290.     --if it's a real peripheral or my virtual peripheral return true
  291.     return isPresent( side ) or side == "stitch"
  292. end
  293.  
  294. peripheral.getType = function( side )
  295.     --if it's my virtual peripheral return monitor
  296.     return getType( side ) or (side == "stitch" and "monitor")
  297. end
  298.  
  299. peripheral.getMethods = function( side )
  300.     --if it's my virtual peripheral return my list of methods
  301.     return getMethods( side ) or (side == "stitch" and methods)
  302. end
  303.  
  304. peripheral.call = function( side, method, ... )
  305.     --if it's my peripheral, call the relevent function with the relevent arguments
  306.     if side == "stitch" then
  307.         return stitch[ method ]( ... )
  308.     end
  309.     return call( side, method, ... )
  310. end
  311.  
  312. peripheral.wrap = function( side )
  313.     --if it's my virtual peripheral, return it
  314.     return wrap( side ) or (stitch and side == "stitch")
  315. end
  316.  
  317. peripheral.find = function( type, fnFilter )
  318.     --if we're looking for monitors, add mine in
  319.     if type == "monitor" then
  320.         local result = find( type, fnFilter )
  321.         result[ #result + 1 ] = fnFilter and fnFilter( "stitch", stitch ) or stitch
  322.         return unpack( result )
  323.     end
  324.     return find( type, fnFilter )
  325. end
  326.  
  327. peripheral.getNames = function()
  328.     --add my virtual peripheral to the list
  329.     local result = getNames()
  330.     result[ #result + 1 ] = "stitch"
  331.     return result
  332. end
  333.  
  334. return stitch
RAW Paste Data