2019-12-09 08:53:52 +00:00
-- Windon't
-- enhanced window API by LDDestroier
2019-12-09 07:30:33 +00:00
-- intended for general use within all me new programs
--
-- Unique features:
-- + Transparency within windows
-- + Built-in window layering
2019-12-14 01:12:53 +00:00
-- stores all local values to make drag-and-dropping into other programs less conflict-prone
local lval = {
to_blit = { } ,
to_colors = { } ,
2020-01-30 04:55:19 +00:00
oldScreenBuffer = { } ,
2019-12-14 01:12:53 +00:00
2019-12-16 02:47:19 +00:00
expect = function ( value , default , valueType )
if value == nil or ( valueType and type ( value ) ~= valueType ) then
return default
else
return value
end
end ,
2019-12-14 01:12:53 +00:00
getTime = function ( )
return 24 * os.day ( ) + os.time ( )
end ,
-- check if space on screenBuffer is transparent
2020-01-06 07:54:05 +00:00
check = function ( buffer , x , y , blitLayer )
if buffer [ blitLayer or 1 ] [ y ] then
if blitLayer then
return ( buffer [ blitLayer ] [ y ] [ x ] and buffer [ blitLayer ] [ y ] [ x ] ~= " - " )
else
if ( not buffer [ 2 ] [ y ] [ x ] or buffer [ 2 ] [ y ] [ x ] == " - " ) and ( not buffer [ 3 ] [ y ] [ x ] or buffer [ 3 ] [ y ] [ x ] == " - " ) then
return false
elseif ( not buffer [ 3 ] [ y ] [ x ] or buffer [ 3 ] [ y ] [ x ] == " - " ) and buffer [ 1 ] [ y ] [ x ] == " " then
return false
else
2020-01-12 06:42:47 +00:00
return buffer [ 1 ] [ y ] [ x ] and buffer [ 2 ] [ y ] [ x ] and buffer [ 3 ] [ y ] [ x ]
2020-01-06 07:54:05 +00:00
end
end
2019-12-16 02:47:19 +00:00
end
2019-12-14 01:12:53 +00:00
end
}
2019-12-09 07:30:33 +00:00
2020-01-06 07:54:05 +00:00
local table_insert = table.insert
2020-01-30 04:55:19 +00:00
local table_concat = table.concat
2020-01-06 07:54:05 +00:00
local math_floor = math.floor
2019-12-14 01:12:53 +00:00
for i = 1 , 16 do
lval.to_blit [ 2 ^ ( i - 1 ) ] = ( " 0123456789abcdef " ) : sub ( i , i )
lval.to_colors [ ( " 0123456789abcdef " ) : sub ( i , i ) ] = 2 ^ ( i - 1 )
2019-12-11 05:29:30 +00:00
end
2019-12-14 01:12:53 +00:00
lval.to_blit [ 0 ] , lval.to_colors [ " - " ] = " - " , 0
2019-12-09 07:30:33 +00:00
2019-12-11 05:29:30 +00:00
local windont = {
2019-12-16 02:47:19 +00:00
doClearScreen = false , -- if true, will clear the screen during render
2020-01-30 06:50:15 +00:00
ignoreUnchangedLines = true , -- if true, the render function will check each line it renders against the last framebuffer and ignore it if they are the same
2020-01-12 07:30:28 +00:00
useSetVisible = false , -- if true, sets the base terminal's visibility to false before rendering
2019-12-16 02:47:19 +00:00
default = {
baseTerm = term.current ( ) , -- default base terminal for all windows
textColor = " 0 " , -- default text color (what " " corresponds to in term.blit's second argument)
backColor = " f " , -- default background color (what " " corresponds to in term.blit's third argument)
blink = true ,
visible = true ,
alwaysRender = true , -- if true, new windows will always render if they are written to
2019-12-11 05:29:30 +00:00
} ,
info = {
BLIT_CALLS = 0 , -- amount of term.blit calls during the last render
LAST_RENDER_TIME = 0 , -- last time in which render was called
LAST_RENDER_AMOUNT = 0 , -- amount of windows drawn during last render
LAST_RENDER_WINDOWS = { } , -- table of the last window objects that were rendered
}
2019-12-09 08:53:52 +00:00
}
2019-12-11 05:29:30 +00:00
-- draws one or more windon't objects
-- should not draw over any terminal space that isn't occupied by a window
2020-01-30 04:55:19 +00:00
windont.render = function ( options , ... )
2020-01-30 06:50:15 +00:00
-- potential options:
-- number: onlyX1
-- number: onlyX2
-- number: onlyY
-- boolean: force (forces render / ignores optimiztaion that compares current framebuffer to old one)
-- terminal: baseTerm (forces to render onto this terminal instead of the window's base terminal)
2019-12-09 07:30:33 +00:00
local windows = { ... }
2020-01-30 04:55:19 +00:00
options = options or { }
local bT , scr_x , scr_y
-- checks if "options" is actually the first window, just in case
if type ( options.meta ) == " table " then
if (
type ( options.meta . buffer ) == " table " and
type ( options.meta . x ) == " number " and
type ( options.meta . y ) == " number " and
type ( options.meta . newBuffer ) == " function "
) then
table_insert ( windows , 1 , options )
end
end
2019-12-14 01:12:53 +00:00
local check = lval.check
2020-01-06 07:54:05 +00:00
2019-12-09 07:30:33 +00:00
local screenBuffer = { { } , { } , { } }
local blitList = { } -- list of blit commands per line
local c = 1 -- current blitList entry
2019-12-14 01:12:53 +00:00
local cTime = lval.getTime ( )
2019-12-11 05:29:30 +00:00
local AMNT_OF_BLITS = 0 -- how many blit calls are there?
2020-01-06 07:54:05 +00:00
local cx , cy -- each window's absolute X and Y
local char_cx , text_cx , back_cx -- each window's transformed absolute X's in table form
local char_cy , text_cy , back_cy -- each window's transformed absolute X's in table form
local buffer -- each window's buffer
local newChar , newText , newBack -- if the transformation function declares a new dot, this is it
local oriChar , oriText , oriBack
2019-12-09 07:30:33 +00:00
2019-12-11 09:26:37 +00:00
local baseTerms = { }
2020-01-30 06:50:15 +00:00
if type ( options.baseTerm ) == " table " then
for i = 1 , # windows do
baseTerms [ options.baseTerm ] = baseTerms [ options.baseTerm ] or { }
baseTerms [ options.baseTerm ] [ i ] = true
end
else
for i = 1 , # windows do
baseTerms [ windows [ i ] . meta.baseTerm ] = baseTerms [ windows [ i ] . meta.baseTerm ] or { }
baseTerms [ windows [ i ] . meta.baseTerm ] [ i ] = true
end
2019-12-11 09:26:37 +00:00
end
2019-12-11 07:37:13 +00:00
2019-12-11 09:26:37 +00:00
for bT , bT_list in pairs ( baseTerms ) do
2019-12-14 00:46:33 +00:00
if bT == output then
bT = output.meta . baseTerm
end
2020-01-12 07:30:28 +00:00
if windont.useSetVisible and bT.setVisible then
bT.setVisible ( false )
end
2019-12-11 09:26:37 +00:00
scr_x , scr_y = bT.getSize ( )
2020-01-06 07:54:05 +00:00
-- try entire buffer transformations
for i = # windows , 1 , - 1 do
if bT_list [ i ] then
if windows [ i ] . meta.metaTransformation then
-- metaTransformation functions needn't return a value
windows [ i ] . meta.metaTransformation ( windows [ i ] . meta )
end
end
end
2020-01-30 04:55:19 +00:00
for y = options.onlyY or 1 , options.onlyY or scr_y do
2019-12-11 09:26:37 +00:00
screenBuffer [ 1 ] [ y ] = { }
screenBuffer [ 2 ] [ y ] = { }
screenBuffer [ 3 ] [ y ] = { }
blitList = { }
c = 1
2020-01-30 04:55:19 +00:00
for x = options.onlyX1 or 1 , math.min ( scr_x , options.onlyX2 or scr_x ) do
2019-12-11 09:26:37 +00:00
for i = # windows , 1 , - 1 do
if bT_list [ i ] then
2020-01-06 07:54:05 +00:00
newChar , newText , newBack = nil
2019-12-11 09:26:37 +00:00
if windows [ i ] . meta.visible then
buffer = windows [ i ] . meta.buffer
2019-12-24 03:34:25 +00:00
2019-12-16 02:47:19 +00:00
cx = 1 + x + - windows [ i ] . meta.x
cy = 1 + y + - windows [ i ] . meta.y
2019-12-11 09:26:37 +00:00
char_cx , text_cx , back_cx = cx , cx , cx
char_cy , text_cy , back_cy = cy , cy , cy
2020-01-06 07:54:05 +00:00
oriChar = ( buffer [ 1 ] [ cy ] or { } ) [ cx ]
oriText = ( buffer [ 2 ] [ cy ] or { } ) [ cx ]
oriBack = ( buffer [ 3 ] [ cy ] or { } ) [ cx ]
2019-12-11 09:26:37 +00:00
-- try char transformation
if windows [ i ] . meta.charTransformation then
2020-01-06 07:54:05 +00:00
char_cx , char_cy , newChar = windows [ i ] . meta.charTransformation ( cx , cy , { oriChar , oriText , oriBack } , windows [ i ] . meta )
if char_cx ~= math_floor ( char_cx ) or char_cy ~= math_floor ( char_cy ) then
2019-12-11 09:26:37 +00:00
newChar = " "
end
2020-01-06 07:54:05 +00:00
char_cx = math_floor ( char_cx or cx )
char_cy = math_floor ( char_cy or cy )
2019-12-11 09:26:37 +00:00
end
-- try text transformation
if windows [ i ] . meta.textTransformation then
2020-01-06 07:54:05 +00:00
text_cx , text_cy , newText = windows [ i ] . meta.textTransformation ( cx , cy , { oriChar , oriText , oriBack } , windows [ i ] . meta )
text_cx = math_floor ( text_cx or cx )
text_cy = math_floor ( text_cy or cy )
2019-12-11 09:26:37 +00:00
end
-- try back transformation
if windows [ i ] . meta.backTransformation then
2020-01-06 07:54:05 +00:00
back_cx , back_cy , newBack = windows [ i ] . meta.backTransformation ( cx , cy , { oriChar , oriText , oriBack } , windows [ i ] . meta )
back_cx = math_floor ( back_cx or cx )
back_cy = math_floor ( back_cy or cy )
2019-12-11 09:26:37 +00:00
end
if check ( buffer , char_cx , char_cy ) or check ( buffer , text_cx , text_cy ) or check ( buffer , back_cx , back_cy ) then
screenBuffer [ 1 ] [ y ] [ x ] = newChar or check ( buffer , char_cx , char_cy ) and ( buffer [ 1 ] [ char_cy ] [ char_cx ] ) or screenBuffer [ 1 ] [ y ] [ x ]
screenBuffer [ 2 ] [ y ] [ x ] = newText or check ( buffer , text_cx , text_cy , 2 ) and ( buffer [ 2 ] [ text_cy ] [ text_cx ] ) or screenBuffer [ 3 ] [ y ] [ x ]
screenBuffer [ 3 ] [ y ] [ x ] = newBack or check ( buffer , back_cx , back_cy , 3 ) and ( buffer [ 3 ] [ back_cy ] [ back_cx ] ) or screenBuffer [ 3 ] [ y ] [ x ]
end
end
2019-12-11 07:37:13 +00:00
end
2019-12-11 09:26:37 +00:00
end
2019-12-11 07:37:13 +00:00
2019-12-16 02:47:19 +00:00
if windont.doClearScreen then
2019-12-11 09:26:37 +00:00
screenBuffer [ 1 ] [ y ] [ x ] = screenBuffer [ 1 ] [ y ] [ x ] or " "
end
2019-12-16 02:47:19 +00:00
screenBuffer [ 2 ] [ y ] [ x ] = screenBuffer [ 2 ] [ y ] [ x ] or windont.default . backColor -- intentionally not the default text color
screenBuffer [ 3 ] [ y ] [ x ] = screenBuffer [ 3 ] [ y ] [ x ] or windont.default . backColor
2019-12-11 09:26:37 +00:00
if check ( screenBuffer , x , y ) then
2020-01-06 07:54:05 +00:00
if check ( screenBuffer , - 1 + x , y ) then
2019-12-11 09:26:37 +00:00
blitList [ c ] [ 1 ] = blitList [ c ] [ 1 ] .. screenBuffer [ 1 ] [ y ] [ x ]
blitList [ c ] [ 2 ] = blitList [ c ] [ 2 ] .. screenBuffer [ 2 ] [ y ] [ x ]
blitList [ c ] [ 3 ] = blitList [ c ] [ 3 ] .. screenBuffer [ 3 ] [ y ] [ x ]
else
c = x
blitList [ c ] = {
screenBuffer [ 1 ] [ y ] [ x ] ,
screenBuffer [ 2 ] [ y ] [ x ] ,
screenBuffer [ 3 ] [ y ] [ x ]
}
2019-12-09 08:53:52 +00:00
end
2019-12-09 07:30:33 +00:00
end
end
2020-01-30 06:50:15 +00:00
if ( not lval.oldScreenBuffer [ bT ] ) or ( not windont.ignoreUnchangedLines ) or ( options.force ) or (
2020-01-30 04:55:19 +00:00
table_concat ( screenBuffer [ 1 ] [ y ] ) ~= table_concat ( lval.oldScreenBuffer [ bT ] [ 1 ] [ y ] ) or
table_concat ( screenBuffer [ 2 ] [ y ] ) ~= table_concat ( lval.oldScreenBuffer [ bT ] [ 2 ] [ y ] ) or
table_concat ( screenBuffer [ 3 ] [ y ] ) ~= table_concat ( lval.oldScreenBuffer [ bT ] [ 3 ] [ y ] )
) then
for k , v in pairs ( blitList ) do
bT.setCursorPos ( k , y )
bT.blit ( v [ 1 ] , v [ 2 ] , v [ 3 ] )
AMNT_OF_BLITS = 1 + AMNT_OF_BLITS
end
2019-12-09 07:30:33 +00:00
end
end
2020-01-30 04:55:19 +00:00
lval.oldScreenBuffer [ bT ] = screenBuffer
2020-01-12 07:30:28 +00:00
if windont.useSetVisible and bT.setVisible then
2020-01-13 04:52:52 +00:00
if not multishell then
bT.setVisible ( true )
elseif multishell.getFocus ( ) == multishell.getCurrent ( ) then
bT.setVisible ( true )
end
2020-01-12 07:30:28 +00:00
end
2019-12-09 07:30:33 +00:00
end
2019-12-11 05:29:30 +00:00
windont.info . LAST_RENDER_AMOUNT = # windows
2019-12-16 02:47:19 +00:00
windont.info . BLIT_CALLS = AMNT_OF_BLITS
2019-12-11 05:29:30 +00:00
windont.info . LAST_RENDER_WINDOWS = windows
windont.info . LAST_RENDER_TIME = cTime
2020-01-06 07:54:05 +00:00
windont.info . LAST_RENDER_DURATION = lval.getTime ( ) + - cTime
2019-12-11 05:29:30 +00:00
2019-12-09 07:30:33 +00:00
end
2019-12-11 05:29:30 +00:00
-- creates a new windon't object that can be manipulated the same as a regular window
2019-12-09 07:30:33 +00:00
windont.newWindow = function ( x , y , width , height , misc )
-- check argument types
assert ( type ( x ) == " number " , " argument #1 must be number, got " .. type ( x ) )
assert ( type ( y ) == " number " , " argument #2 must be number, got " .. type ( y ) )
assert ( type ( width ) == " number " , " argument #3 must be number, got " .. type ( width ) )
assert ( type ( height ) == " number " , " argument #4 must be number, got " .. type ( height ) )
-- check argument validity
assert ( x > 0 , " x position must be above zero " )
assert ( y > 0 , " y position must be above zero " )
assert ( width > 0 , " width must be above zero " )
assert ( height > 0 , " height must be above zero " )
local output = { }
misc = misc or { }
local meta = {
2020-01-06 07:54:05 +00:00
x = lval.expect ( x , 1 ) , -- x position of the window
y = lval.expect ( y , 1 ) , -- y position of the window
width = width , -- width of the buffer
height = height , -- height of the buffer
2019-12-16 02:47:19 +00:00
buffer = lval.expect ( misc.buffer , { } , " table " ) , -- stores contents of terminal in buffer[1][y][x] format
renderBuddies = lval.expect ( misc.renderBuddies , { } , " table " ) , -- renders any other window objects stored here after rendering here
baseTerm = lval.expect ( misc.baseTerm , windont.default . baseTerm , " table " ) , -- base terminal for which this window draws on
isColor = lval.expect ( misc.isColor , term.isColor ( ) , " boolean " ) , -- if true, then it's an advanced computer
2019-12-09 08:53:52 +00:00
2019-12-16 02:47:19 +00:00
charTransformation = lval.expect ( misc.charTransformation , nil , " function " ) , -- function that transforms the characters of the window
textTransformation = lval.expect ( misc.textTransformation , nil , " function " ) , -- function that transforms the text colors of the window
backTransformation = lval.expect ( misc.backTransformation , nil , " function " ) , -- function that transforms the BG colors of the window
2020-01-06 07:54:05 +00:00
metaTransformation = lval.expect ( misc.miscTransformation , nil , " function " ) , -- function that transforms the whole output.meta function
2019-12-11 07:37:13 +00:00
2019-12-16 02:47:19 +00:00
cursorX = lval.expect ( misc.cursorX , 1 ) ,
cursorY = lval.expect ( misc.cursorY , 1 ) ,
2019-12-09 08:53:52 +00:00
2020-01-06 07:54:05 +00:00
textColor = lval.expect ( misc.textColor , windont.default . textColor , " string " ) , -- current text color
backColor = lval.expect ( misc.backColor , windont.default . backColor , " string " ) , -- current background color
2019-12-09 08:53:52 +00:00
2019-12-16 02:47:19 +00:00
blink = lval.expect ( misc.blink , windont.default . blink , " boolean " ) , -- cursor blink
alwaysRender = lval.expect ( misc.alwaysRender , windont.default . alwaysRender , " boolean " ) , -- render after every terminal operation
visible = lval.expect ( misc.visible , windont.default . visible , " boolean " ) , -- if false, don't render ever
2019-12-09 08:53:52 +00:00
-- make a new buffer (optionally uses an existing buffer as a reference)
2019-12-09 07:30:33 +00:00
newBuffer = function ( width , height , char , text , back , drawAtop )
local output = drawAtop or { { } , { } , { } }
for y = 1 , height do
output [ 1 ] [ y ] = output [ 1 ] [ y ] or { }
output [ 2 ] [ y ] = output [ 2 ] [ y ] or { }
output [ 3 ] [ y ] = output [ 3 ] [ y ] or { }
for x = 1 , width do
2019-12-14 00:46:33 +00:00
output [ 1 ] [ y ] [ x ] = output [ 1 ] [ y ] [ x ] or ( char or " " )
output [ 2 ] [ y ] [ x ] = output [ 2 ] [ y ] [ x ] or ( text or " 0 " )
output [ 3 ] [ y ] [ x ] = output [ 3 ] [ y ] [ x ] or ( back or " f " )
2019-12-09 07:30:33 +00:00
end
end
return output
end
}
2019-12-11 09:26:37 +00:00
bT = meta.baseTerm
2019-12-09 08:53:52 +00:00
-- initialize the buffer
2019-12-09 07:30:33 +00:00
meta.buffer = meta.newBuffer ( meta.width , meta.height , " " , meta.textColor , meta.backColor )
2019-12-11 05:29:30 +00:00
output.meta = meta
2019-12-09 07:30:33 +00:00
output.write = function ( text )
2019-12-16 02:47:19 +00:00
assert ( type ( text ) == " string " or type ( text ) == " number " , " expected string, got " .. type ( text ) )
local initX = meta.cursorX
for i = 1 , # tostring ( text ) do
2019-12-09 07:30:33 +00:00
if meta.cursorX >= 1 and meta.cursorX <= meta.width and meta.cursorY >= 1 and meta.cursorY <= meta.height then
2019-12-16 02:47:19 +00:00
if not meta.buffer [ 1 ] then
error ( " what the fuck happened " )
end
meta.buffer [ 1 ] [ meta.cursorY ] [ meta.cursorX ] = tostring ( text ) : sub ( i , i )
2019-12-09 07:30:33 +00:00
meta.buffer [ 2 ] [ meta.cursorY ] [ meta.cursorX ] = meta.textColor
meta.buffer [ 3 ] [ meta.cursorY ] [ meta.cursorX ] = meta.backColor
end
2019-12-16 02:47:19 +00:00
meta.cursorX = meta.cursorX + 1
2019-12-09 07:30:33 +00:00
end
2019-12-09 08:53:52 +00:00
if meta.alwaysRender then
2020-01-06 07:54:05 +00:00
output.redraw (
- 1 + meta.x + initX ,
- 1 + meta.x + meta.cursorX ,
- 1 + meta.y + meta.cursorY
)
2019-12-09 08:53:52 +00:00
end
2019-12-09 07:30:33 +00:00
end
output.blit = function ( char , text , back )
assert ( type ( char ) == " string " and type ( text ) == " string " and type ( back ) == " string " , " all arguments must be strings " )
assert ( # char == # text and # text == # back , " arguments must be same length " )
2019-12-16 02:47:19 +00:00
local initX = meta.cursorX
2019-12-09 07:30:33 +00:00
for i = 1 , # char do
if meta.cursorX >= 1 and meta.cursorX <= meta.width and meta.cursorY >= 1 and meta.cursorY <= meta.height then
meta.buffer [ 1 ] [ meta.cursorY ] [ meta.cursorX ] = char : sub ( i , i )
2019-12-16 02:47:19 +00:00
meta.buffer [ 2 ] [ meta.cursorY ] [ meta.cursorX ] = text : sub ( i , i ) == " " and windont.default . textColor or text : sub ( i , i )
meta.buffer [ 3 ] [ meta.cursorY ] [ meta.cursorX ] = back : sub ( i , i ) == " " and windont.default . backColor or back : sub ( i , i )
2019-12-09 07:30:33 +00:00
meta.cursorX = meta.cursorX + 1
end
end
2019-12-09 08:53:52 +00:00
if meta.alwaysRender then
2020-01-06 07:54:05 +00:00
output.redraw (
- 1 + meta.x + initX ,
- 1 + meta.x + meta.cursorX ,
- 1 + meta.y + meta.cursorY
)
2019-12-09 08:53:52 +00:00
end
2019-12-09 07:30:33 +00:00
end
output.setCursorPos = function ( x , y )
assert ( type ( x ) == " number " , " argument #1 must be number, got " .. type ( x ) )
assert ( type ( y ) == " number " , " argument #2 must be number, got " .. type ( y ) )
2020-01-06 02:55:51 +00:00
meta.cursorX , meta.cursorY = math.floor ( x ) , math.floor ( y )
2019-12-09 07:30:33 +00:00
if meta.alwaysRender then
2019-12-14 00:35:01 +00:00
if bT == output then
bT = output.meta . baseTerm
end
2020-01-06 07:54:05 +00:00
bT.setCursorPos (
- 1 + meta.x + meta.cursorX ,
- 1 + meta.y + meta.cursorY
)
2019-12-09 07:30:33 +00:00
end
end
output.getCursorPos = function ( )
return meta.cursorX , meta.cursorY
end
output.setTextColor = function ( color )
2019-12-14 01:12:53 +00:00
if lval.to_blit [ color ] then
meta.textColor = lval.to_blit [ color ]
2019-12-09 07:30:33 +00:00
else
error ( " Invalid color (got " .. color .. " ) " )
end
end
output.setTextColour = output.setTextColor
output.setBackgroundColor = function ( color )
2019-12-14 01:12:53 +00:00
if lval.to_blit [ color ] then
meta.backColor = lval.to_blit [ color ]
2019-12-09 07:30:33 +00:00
else
error ( " Invalid color (got " .. color .. " ) " )
end
end
output.setBackgroundColour = output.setBackgroundColor
output.getTextColor = function ( )
2019-12-14 01:12:53 +00:00
return lval.to_colors [ meta.textColor ]
2019-12-09 07:30:33 +00:00
end
output.getTextColour = output.getTextColor
output.getBackgroundColor = function ( )
2019-12-14 01:12:53 +00:00
return lval.to_colors [ meta.backColor ]
2019-12-09 07:30:33 +00:00
end
output.getBackgroundColour = output.getBackgroundColor
output.setVisible = function ( visible )
2020-01-12 08:31:16 +00:00
assert ( type ( visible ) == " boolean " , " bad argument #1 (expected boolean, got " .. type ( visible ) .. " ) " )
2019-12-09 07:30:33 +00:00
meta.visible = visible and true or false
end
output.clear = function ( )
meta.buffer = meta.newBuffer ( meta.width , meta.height , " " , meta.textColor , meta.backColor )
2019-12-14 00:35:01 +00:00
if meta.alwaysRender then
output.redraw ( )
end
2019-12-09 07:30:33 +00:00
end
output.clearLine = function ( )
2019-12-16 02:47:19 +00:00
meta.buffer [ 1 ] [ meta.cursorY ] = nil
meta.buffer [ 2 ] [ meta.cursorY ] = nil
meta.buffer [ 3 ] [ meta.cursorY ] = nil
2019-12-09 07:30:33 +00:00
meta.buffer = meta.newBuffer ( meta.width , meta.height , " " , meta.textColor , meta.backColor , meta.buffer )
if meta.alwaysRender then
2020-01-06 07:54:05 +00:00
bT.setCursorPos ( meta.x , - 1 + meta.y + meta.cursorY )
bT.blit (
( " " ) : rep ( meta.width ) ,
( meta.textColor ) : rep ( meta.width ) ,
( meta.backColor ) : rep ( meta.width )
)
2019-12-09 07:30:33 +00:00
end
end
output.getLine = function ( y )
assert ( type ( y ) == " number " , " bad argument #1 (expected number, got " .. type ( y ) .. " ) " )
2019-12-11 05:29:30 +00:00
assert ( meta.buffer [ 1 ] [ y ] , " Line is out of range. " )
2020-01-30 04:55:19 +00:00
return table_concat ( meta.buffer [ 1 ] [ y ] ) , table_concat ( meta.buffer [ 2 ] [ y ] ) , table_concat ( meta.buffer [ 3 ] [ y ] )
2019-12-09 07:30:33 +00:00
end
2019-12-11 05:29:30 +00:00
output.scroll = function ( amplitude )
2019-12-14 01:12:53 +00:00
if math.abs ( amplitude ) < meta.height then -- minor optimization
2019-12-16 02:47:19 +00:00
local blank = { { } , { } , { } }
for x = 1 , meta.width do
blank [ 1 ] [ x ] = " "
blank [ 2 ] [ x ] = meta.textColor
blank [ 3 ] [ x ] = meta.backColor
end
for y = 1 , meta.height do
meta.buffer [ 1 ] [ y ] = meta.buffer [ 1 ] [ y + amplitude ] or blank [ 1 ]
meta.buffer [ 2 ] [ y ] = meta.buffer [ 2 ] [ y + amplitude ] or blank [ 2 ]
meta.buffer [ 3 ] [ y ] = meta.buffer [ 3 ] [ y + amplitude ] or blank [ 3 ]
2019-12-09 07:30:33 +00:00
end
else
2019-12-14 01:12:53 +00:00
meta.buffer = meta.newBuffer ( meta.width , meta.height , " " , meta.textColor , meta.backColor )
2019-12-09 07:30:33 +00:00
end
if meta.alwaysRender then
2020-01-06 07:54:05 +00:00
if math_floor ( amplitude ) ~= 0 then
2019-12-14 01:12:53 +00:00
output.redraw ( )
end
2019-12-09 07:30:33 +00:00
end
end
output.getSize = function ( )
2019-12-11 09:26:37 +00:00
return width , height
2019-12-09 07:30:33 +00:00
end
output.isColor = function ( )
return meta.isColor
end
output.isColour = output.isColor
output.reposition = function ( x , y , width , height )
assert ( type ( x ) == " number " , " bad argument #1 (expected number, got " .. type ( x ) .. " ) " )
assert ( type ( y ) == " number " , " bad argument #2 (expected number, got " .. type ( y ) .. " ) " )
2020-01-06 07:54:05 +00:00
meta.x = math_floor ( x )
meta.y = math_floor ( y )
2019-12-09 07:30:33 +00:00
if width then
assert ( type ( width ) == " number " , " bad argument #3 (expected number, got " .. type ( width ) .. " ) " )
assert ( type ( height ) == " number " , " bad argument #4 (expected number, got " .. type ( height ) .. " ) " )
meta.width = width
meta.height = height
meta.buffer = meta.newBuffer ( meta.width , meta.height , " " , meta.textColor , meta.backColor , meta.buffer )
end
if meta.alwaysRender then
output.redraw ( )
end
end
output.restoreCursor = function ( )
2019-12-14 00:35:01 +00:00
bT.setCursorPos (
2020-01-06 07:54:05 +00:00
math.max ( 0 , - 1 + meta.x + meta.cursorX ) ,
math.max ( 0 , - 1 + meta.y + meta.cursorY )
2019-12-14 00:35:01 +00:00
)
2019-12-09 07:30:33 +00:00
bT.setCursorBlink ( meta.blink )
end
output.getPosition = function ( )
return meta.x , meta.y
end
output.setCursorBlink = function ( blink )
meta.blink = blink and true or false
end
output.getCursorBlink = function ( blink )
return meta.blink
end
output.setPaletteColor = bT.setPaletteColor
output.setPaletteColour = bT.setPaletteColour
output.getPaletteColor = bT.getPaletteColor
output.getPaletteColour = bT.getPaletteColour
2019-12-16 02:47:19 +00:00
output.redraw = function ( x1 , x2 , y )
2019-12-11 05:29:30 +00:00
if # meta.renderBuddies > 0 then
2020-01-30 04:55:19 +00:00
windont.render ( { onlyX1 = x1 , onlyX2 = x2 , onlyY = y } , output , table.unpack ( meta.renderBuddies ) )
2019-12-11 05:29:30 +00:00
else
2020-01-30 04:55:19 +00:00
windont.render ( { onlyX1 = x1 , onlyX2 = x2 , onlyY = y } , output )
2019-12-11 05:29:30 +00:00
end
2019-12-16 02:47:19 +00:00
output.restoreCursor ( )
2019-12-09 07:30:33 +00:00
end
2019-12-14 00:46:33 +00:00
if meta.alwaysRender then
output.redraw ( )
end
2019-12-09 07:30:33 +00:00
return output
end
return windont