From 8aa0d5bc1a5fd5c13174d3225cc2989f9d7e85d6 Mon Sep 17 00:00:00 2001 From: LDDestroier Date: Wed, 11 Sep 2019 18:23:26 -0400 Subject: [PATCH] Add files via upload --- trash.lua | 1108 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1108 insertions(+) create mode 100644 trash.lua diff --git a/trash.lua b/trash.lua new file mode 100644 index 0000000..794e71f --- /dev/null +++ b/trash.lua @@ -0,0 +1,1108 @@ +local tArg = {...} + +local scr_x, scr_y = term.getSize() + +local images = { + handOpen = { { " €ƒƒ ", "—ƒƒ„€€€€€•", "ŒŒ€€€€€€•", "ƒƒŒŒ€€€€€Ÿ…", "Š‡ƒŸ€€‡ ", " —€Ÿ ", " ‚ƒ ", }, { " 00ffff ", "fffff000000", "ffff0000000", " ff0000000", " f000 ", " f000 ", " 00 ", }, { " f00000 ", "0000000000f", "0000000000f", " 0000000ff", " 000f ", " 00ff ", " ff ", }}, + handClosed = { { "  ", " ŸŒ€€€€€€•", " Œ€€€€€€€•", " ŒŒ€€€€€Ÿ…", " ‚ŒŒ†€€‡ ", " ƒƒƒ ", }, { " fffff ", " fff0000000", " ff00000000", " ff00000000", " 0fff000 ", " 0000 ", }, { " 00000 ", " 000000000f", " 000000000f", " 0000000fff", " f00000f ", " ffff ", }}, + trashCan = { { "€‚ƒƒƒƒƒƒ€", "•€œ“ƒƒœ“ƒƒœ“€…", "‚€‚‚€€••€€€ ", " €€••€ŸŸ€• ", " •€••€••€••€ ", " €€€€••€€€— ", " ”€””••——€ ", " Š€Š…••Š…Ÿ ", " … ", }, { "888ffffffff888", "f8877787778788", "8878888788878 ", " f88788788788 ", " f8878878878 ", " 8878878788 ", " f887878788 ", " 887787778 ", " 88888888 ", }, { "7788888888887f", "8878887888788f", " 887887888788 ", " 88788788788f ", " 88788788788 ", " 887878878f ", " 887878788f ", " f8887888f ", " ffffffff ", }}, + trashLid = { { " Ÿ", "ƒ€€€€ƒƒ€€€€ƒ", }, { " fffffff8", "f888877778888f", }, { " 8888888f", "88888888888888", }} +} + +-- start up lddterm +local lddterm = {} +lddterm.alwaysRender = false -- renders after any and all screen-changing functions. +lddterm.useColors = true -- normal computers do not allow color, but this variable doesn't do anything yet +lddterm.baseTerm = term.current() -- will draw to this terminal +lddterm.transformation = nil -- will modify the current buffer as an NFT image before rendering +lddterm.cursorTransformation = nil -- will modify the cursor position +lddterm.drawFunction = nil -- will draw using this function instead of basic NFT drawing +lddterm.adjustX = 0 -- moves entire screen X +lddterm.adjustY = 0 -- moves entire screen Y +lddterm.selectedWindow = 1 -- determines which window controls the cursor +lddterm.windows = {} + +-- converts hex colors to colors api, and back +local to_colors, to_blit = { + [' '] = 0, + ['0'] = 1, + ['1'] = 2, + ['2'] = 4, + ['3'] = 8, + ['4'] = 16, + ['5'] = 32, + ['6'] = 64, + ['7'] = 128, + ['8'] = 256, + ['9'] = 512, + ['a'] = 1024, + ['b'] = 2048, + ['c'] = 4096, + ['d'] = 8192, + ['e'] = 16384, + ['f'] = 32768, +}, {} +for k,v in pairs(to_colors) do + to_blit[v] = k +end + +-- separates string into table based on divider +local explode = function(div, str, replstr, includeDiv) + if (div == '') then + return false + end + local pos, arr = 0, {} + for st, sp in function() return string.find(str, div, pos, false) end do + table.insert(arr, string.sub(replstr or str, pos, st - 1 + (includeDiv and #div or 0))) + pos = sp + 1 + end + table.insert(arr, string.sub(replstr or str, pos)) + return arr +end + +-- determines the size of the terminal before rendering always +local determineScreenSize = function() + scr_x, scr_y = lddterm.baseTerm.getSize() + lddterm.screenWidth = scr_x + lddterm.screenHeight = scr_y +end + +determineScreenSize() + +-- takes two or more windows and checks if the first of them overlap the other(s) +lddterm.checkWindowOverlap = function(window, ...) + if #lddterm.windows < 2 then + return false + end + local list, win = {...} + for i = 1, #list do + win = list[i] + if win ~= window then + + if ( + window.x < win.x + win.width and + win.x < window.x + window.width and + window.y < win.y + win.height and + win.y < window.y + window.height + ) then + return true + end + + end + end + return false +end + +local fixCursorPos = function() + local cx, cy + if lddterm.windows[lddterm.selectedWindow] then + if lddterm.cursorTransformation then + cx, cy = lddterm.cursorTransformation( + lddterm.windows[lddterm.selectedWindow].cursor[1], + lddterm.windows[lddterm.selectedWindow].cursor[2] + ) + lddterm.baseTerm.setCursorPos( + cx + lddterm.windows[lddterm.selectedWindow].x - 1, + cy + lddterm.windows[lddterm.selectedWindow].y - 1 + ) + else + lddterm.baseTerm.setCursorPos( + -1 + lddterm.windows[lddterm.selectedWindow].cursor[1] + lddterm.windows[lddterm.selectedWindow].x, + lddterm.windows[lddterm.selectedWindow].cursor[2] + lddterm.windows[lddterm.selectedWindow].y - 1 + ) + end + lddterm.baseTerm.setCursorBlink(lddterm.windows[lddterm.selectedWindow].blink) + end +end + +-- renders the screen with optional transformation function +lddterm.render = function(transformation, drawFunction) + -- determine new screen size and change lddterm screen to fit + old_scr_x, old_scr_y = scr_x, scr_y + determineScreenSize() + if old_scr_x ~= scr_x or old_scr_y ~= scr_y then + lddterm.baseTerm.clear() + end + local image = lddterm.screenshot() + if type(transformation) == "function" then + image = transformation(image) + end + if drawFunction then + drawFunction(image, lddterm.baseTerm) + else + for y = 1, #image[1] do + lddterm.baseTerm.setCursorPos(1 + lddterm.adjustX, y + lddterm.adjustY) + lddterm.baseTerm.blit(image[1][y], image[2][y], image[3][y]) + end + end + fixCursorPos() +end + +lddterm.newWindow = function(width, height, x, y, meta) + meta = meta or {} + local window = { + width = math.floor(width), + height = math.floor(height), + blink = true, + cursor = meta.cursor or {1, 1}, + colors = meta.colors or {"0", "f"}, + clearChar = meta.clearChar or " ", + visible = meta.visible or true, + x = math.floor(x) or 1, + y = math.floor(y) or 1, + buffer = {{},{},{}}, + } + for y = 1, height do + window.buffer[1][y] = {} + window.buffer[2][y] = {} + window.buffer[3][y] = {} + for x = 1, width do + window.buffer[1][y][x] = window.clearChar + window.buffer[2][y][x] = window.colors[1] + window.buffer[3][y][x] = window.colors[2] + end + end + + window.handle = {} + window.handle.setCursorPos = function(x, y) + window.cursor = {x, y} + fixCursorPos() + end + window.handle.getCursorPos = function() + return window.cursor[1], window.cursor[2] + end + window.handle.setCursorBlink = function(blink) + window.blink = blink or false + end + window.handle.getCursorBlink = function() + return window.blink + end + window.handle.scroll = function(amount) + if amount > 0 then + for i = 1, amount do + for c = 1, 3 do + table.remove(window.buffer[c], 1) + window.buffer[c][window.height] = {} + for xx = 1, width do + window.buffer[c][window.height][xx] = ( + c == 1 and window.clearChar or + c == 2 and window.colors[1] or + c == 3 and window.colors[2] + ) + end + end + end + elseif amount < 0 then + for i = 1, -amount do + for c = 1, 3 do + window.buffer[c][window.height] = nil + table.insert(window.buffer[c], 1, {}) + for xx = 1, width do + window.buffer[c][1][xx] = ( + c == 1 and window.clearChar or + c == 2 and window.colors[1] or + c == 3 and window.colors[2] + ) + end + end + end + end + if lddterm.alwaysRender then + lddterm.render(lddterm.transformation, lddterm.drawFunction) + end + end + window.handle.scrollX = function(amount) + if amount > 0 then + for i = 1, amount do + for c = 1, 3 do + for y = 1, window.height do + table.remove(window.buffer[c][y], 1) + window.buffer[c][y][window.width] = ( + c == 1 and window.clearChar or + c == 2 and window.colors[1] or + c == 3 and window.colors[2] + ) + end + end + end + elseif amount < 0 then + for i = 1, -amount do + for c = 1, 3 do + for y = 1, window.height do + window.buffer[c][y][window.width] = nil + table.insert(window.buffer[c][y], 1, ( + c == 1 and window.clearChar or + c == 2 and window.colors[1] or + c == 3 and window.colors[2] + )) + end + end + end + end + if lddterm.alwaysRender then + lddterm.render(lddterm.transformation, lddterm.drawFunction) + end + end + window.handle.write = function(text, x, y, ignoreAlwaysRender) + assert(text ~= nil, "expected string 'text'") + text = tostring(text) + local cx = math.floor(tonumber(x) or window.cursor[1]) + local cy = math.floor(tonumber(y) or window.cursor[2]) + text = text:sub(math.max(0, -cx - 1)) + for i = 1, #text do + if cx >= 1 and cx <= window.width and cy >= 1 and cy <= window.height then + window.buffer[1][cy][cx] = text:sub(i,i) + window.buffer[2][cy][cx] = window.colors[1] + window.buffer[3][cy][cx] = window.colors[2] + end + cx = math.min(cx + 1, window.width + 1) + end + window.cursor = {cx, cy} + if lddterm.alwaysRender and not ignoreAlwaysRender then + lddterm.render(lddterm.transformation, lddterm.drawFunction) + end + end + window.handle.writeWrap = function(text, x, y, ignoreAlwaysRender) + local words = explode(" ", text, nil, true) + local cx, cy = x or window.cursor[1], y or window.cursor[2] + for i = 1, #words do + if cx + #words[i] > window.width + 1 then + cx = 1 + if cy >= window.height then + window.handle.scroll(1) + cy = window.height + else + cy = cy + 1 + end + end + window.handle.write(words[i], cx, cy, true) + cx = cx + #words[i] + end + if lddterm.alwaysRender and not ignoreAlwaysRender then + lddterm.render(lddterm.transformation, lddterm.drawFunction) + end + end + window.handle.blit = function(char, textCol, backCol, x, y) + if type(char) == "number" then + char = tostring(char) + end + if type(textCol) == "number" then + textCol = tostring(textCol) + end + if type(backCol) == "number" then + backCol = tostring(backCol) + end + assert(char ~= nil, "expected string 'char'") + local cx = math.floor(tonumber(x) or window.cursor[1]) + local cy = math.floor(tonumber(y) or window.cursor[2]) + char = char:sub(math.max(0, -cx - 1)) + for i = 1, #char do + if cx >= 1 and cx <= window.width and cy >= 1 and cy <= window.height then + window.buffer[1][cy][cx] = char:sub(i,i) + window.buffer[2][cy][cx] = textCol:sub(i,i) + window.buffer[3][cy][cx] = backCol:sub(i,i) + end + cx = cx + 1 + end + window.cursor = {cx, cy} + if lddterm.alwaysRender and not ignoreAlwaysRender then + lddterm.render(lddterm.transformation, lddterm.drawFunction) + end + end + window.handle.print = function(text, x, y) + text = text and tostring(text) + window.handle.write(text, x, y, true) + window.cursor[1] = 1 + if window.cursor[2] >= window.height then + window.handle.scroll(1) + else + window.cursor[2] = window.cursor[2] + 1 + if lddterm.alwaysRender then + lddterm.render(lddterm.transformation, lddterm.drawFunction) + end + end + end + window.handle.clear = function(char, ignoreAlwaysRender) + local cx = 1 + for y = 1, window.height do + for x = 1, window.width do + if char then + cx = (x % #char) + 1 + end + window.buffer[1][y][x] = char and char:sub(cx, cx) or window.clearChar + window.buffer[2][y][x] = window.colors[1] + window.buffer[3][y][x] = window.colors[2] + end + end + if lddterm.alwaysRender and not ignoreAlwaysRender then + lddterm.render(lddterm.transformation, lddterm.drawFunction) + end + end + window.handle.clearLine = function(cy, char, ignoreAlwaysRender) + cy = math.floor(cy or window.cursor[2]) + local cx = 1 + for x = 1, window.width do + if char then + cx = (x % #char) + 1 + end + window.buffer[1][cy or window.cursor[2]][x] = char and char:sub(cx, cx) or window.clearChar + window.buffer[2][cy or window.cursor[2]][x] = window.colors[1] + window.buffer[3][cy or window.cursor[2]][x] = window.colors[2] + end + if lddterm.alwaysRender and not ignoreAlwaysRender then + lddterm.render(lddterm.transformation, lddterm.drawFunction) + end + end + window.handle.clearColumn = function(cx, char, ignoreAlwaysRender) + cx = math.floor(cx) + char = char and char:sub(1,1) + for y = 1, window.height do + window.buffer[1][y][cx or window.cursor[1]] = char and char or window.clearChar + window.buffer[2][y][cx or window.cursor[1]] = window.colors[1] + window.buffer[3][y][cx or window.cursor[1]] = window.colors[2] + end + if lddterm.alwaysRender and not ignoreAlwaysRender then + lddterm.render(lddterm.transformation, lddterm.drawFunction) + end + end + window.handle.getSize = function() + return window.width, window.height + end + window.handle.isColor = function() + return lddterm.useColors + end + window.handle.isColour = window.handle.isColor + window.handle.setTextColor = function(color) + if to_blit[color] then + window.colors[1] = to_blit[color] + end + end + window.handle.setTextColour = window.handle.setTextColor + window.handle.setBackgroundColor = function(color) + if to_blit[color] then + window.colors[2] = to_blit[color] + end + end + window.handle.setBackgroundColour = window.handle.setBackgroundColor + window.handle.getTextColor = function() + return to_colors[window.colors[1]] or colors.white + end + window.handle.getTextColour = window.handle.getTextColor + window.handle.getBackgroundColor = function() + return to_colors[window.colors[2]] or colors.black + end + window.handle.getBackgroundColour = window.handle.getBackgroundColor + window.handle.reposition = function(x, y) + window.x = math.floor(x or window.x) + window.y = math.floor(y or window.y) + if lddterm.alwaysRender then + lddterm.render(lddterm.transformation, lddterm.drawFunction) + end + end + window.handle.setPaletteColor = function(...) + return lddterm.baseTerm.setPaletteColor(...) + end + window.handle.setPaletteColour = window.handle.setPaletteColor + window.handle.getPaletteColor = function(...) + return lddterm.baseTerm.getPaletteColor(...) + end + window.handle.getPaletteColour = window.handle.getPaletteColor + window.handle.getPosition = function() + return window.x, window.y + end + window.handle.restoreCursor = function() + lddterm.baseTerm.setCursorPos( + -1 + window.cursor[1] + window.x, + window.cursor[2] + window.y - 1 + ) + end + window.handle.setVisible = function(visible) + window.visible = visible or false + end + + window.handle.redraw = lddterm.render + window.handle.current = window.handle + + window.layer = #lddterm.windows + 1 + lddterm.windows[window.layer] = window + + return window, window.layer +end + +lddterm.setLayer = function(window, _layer) + local layer = math.max(1, math.min(#lddterm.windows, _layer)) + + local win = window + table.remove(lddterm.windows, win.layer) + table.insert(lddterm.windows, layer, win) + + if lddterm.alwaysRender then + lddterm.render(lddterm.transformation, lddterm.drawFunction) + end + return true +end + +-- if the screen changes size, the effect is broken +local old_scr_x, old_scr_y + +-- gets screenshot of whole lddterm desktop, OR a single window +lddterm.screenshot = function(window) + local output = {{},{},{}} + local line + if window then + for y = 1, #window.buffer do + line = {"","",""} + for x = 1, #window.buffer do + line = { + line[1] .. window.buffer[1][y][x], + line[2] .. window.buffer[2][y][x], + line[3] .. window.buffer[3][y][x] + } + end + output[1][y] = line[1] + output[2][y] = line[2] + output[3][y] = line[3] + end + else + for y = 1, scr_y do + line = {"","",""} + for x = 1, scr_x do + + c = "." + lt, lb = t, b + t, b = "0", "f" + for l = 1, #lddterm.windows do + if lddterm.windows[l].visible then + sx = 1 + x - lddterm.windows[l].x + sy = 1 + y - lddterm.windows[l].y + if lddterm.windows[l].buffer[1][sy] then + if lddterm.windows[l].buffer[1][sy][sx] then + c = lddterm.windows[l].buffer[1][sy][sx] or c + t = lddterm.windows[l].buffer[2][sy][sx] or t + b = lddterm.windows[l].buffer[3][sy][sx] or b + break + end + end + end + end + line = { + line[1] .. c, + line[2] .. t, + line[3] .. b + } + end + output[1][y] = line[1] + output[2][y] = line[2] + output[3][y] = line[3] + end + end + return output +end + +-- load an abbridged NFTE API + +local nfte = {} + +local tchar = string.char(31) -- for text colors +local bchar = string.char(30) -- for background colors +local nchar = string.char(29) -- for differentiating multiple frames in ANFT + +local round = function(num) + return math.floor(num + 0.5) +end + +local deepCopy +deepCopy = function(tbl) + local output = {} + for k,v in pairs(tbl) do + if type(v) == "table" then + output[k] = deepCopy(v) + else + output[k] = v + end + end + return output +end + +local function stringWrite(str,pos,ins,exc) + str, ins = tostring(str), tostring(ins) + local output, fn1, fn2 = str:sub(1,pos-1)..ins..str:sub(pos+#ins) + if exc then + repeat + fn1, fn2 = str:find(exc,fn2 and fn2+1 or 1) + if fn1 then + output = stringWrite(output,fn1,str:sub(fn1,fn2)) + end + until not fn1 + end + return output +end + +local checkValid = function(image) + if type(image) == "table" then + if #image == 3 then + return (#image[1] == #image[2] and #image[2] == #image[3]) + end + end + return false +end + +local checkIfANFT = function(image) + if type(image) == "table" then + return type(image[1][1]) == "table" + elseif type(image) == "string" then + return image:find(nchar) and true or false + end +end + +local bl = { -- blit + [' '] = 0, + ['0'] = 1, + ['1'] = 2, + ['2'] = 4, + ['3'] = 8, + ['4'] = 16, + ['5'] = 32, + ['6'] = 64, + ['7'] = 128, + ['8'] = 256, + ['9'] = 512, + ['a'] = 1024, + ['b'] = 2048, + ['c'] = 4096, + ['d'] = 8192, + ['e'] = 16384, + ['f'] = 32768, +} +local lb = {} -- tilb +for k,v in pairs(bl) do + lb[v] = k +end + +local ldchart = { -- converts colors into a lighter shade + ["0"] = "0", + ["1"] = "4", + ["2"] = "6", + ["3"] = "0", + ["4"] = "0", + ["5"] = "0", + ["6"] = "0", + ["7"] = "8", + ["8"] = "0", + ["9"] = "3", + ["a"] = "2", + ["b"] = "9", + ["c"] = "1", + ["d"] = "5", + ["e"] = "2", + ["f"] = "7" +} + +local dlchart = { -- converts colors into a darker shade + ["0"] = "8", + ["1"] = "c", + ["2"] = "a", + ["3"] = "9", + ["4"] = "1", + ["5"] = "d", + ["6"] = "2", + ["7"] = "f", + ["8"] = "7", + ["9"] = "b", + ["a"] = "7", + ["b"] = "7", + ["c"] = "7", + ["d"] = "7", + ["e"] = "7", + ["f"] = "f" +} + +local getSizeNFP = function(image) + local xsize = 0 + if type(image) ~= "table" then return 0,0 end + for y = 1, #image do xsize = math.max(xsize, #image[y]) end + return xsize, #image +end + +-- returns (x, y) size of a loaded NFT image +nfte.getSize = function(image) + assert(checkValid(image), "Invalid image.") + local x, y = 0, #image[1] + for y = 1, #image[1] do + x = math.max(x, #image[1][y]) + end + return x, y +end + +local loadImageDataNFT = function(image, background) -- string image + local output = {{},{},{}} -- char, text, back + local y = 1 + background = (background or " "):sub(1,1) + local text, back = " ", background + local doSkip, c1, c2 = false + local maxX = 0 + local bx + for i = 1, #image do + if doSkip then + doSkip = false + else + output[1][y] = output[1][y] or "" + output[2][y] = output[2][y] or "" + output[3][y] = output[3][y] or "" + c1, c2 = image:sub(i,i), image:sub(i+1,i+1) + if c1 == tchar then + text = c2 + doSkip = true + elseif c1 == bchar then + back = c2 + doSkip = true + elseif c1 == "\n" then + maxX = math.max(maxX, #output[1][y]) + y = y + 1 + text, back = " ", background + else + output[1][y] = output[1][y]..c1 + output[2][y] = output[2][y]..text + output[3][y] = output[3][y]..back + end + end + end + for y = 1, #output[1] do + output[1][y] = output[1][y] .. (" "):rep(maxX - #output[1][y]) + output[2][y] = output[2][y] .. (" "):rep(maxX - #output[2][y]) + output[3][y] = output[3][y] .. (background):rep(maxX - #output[3][y]) + end + return output +end + +local loadImageDataNFP = function(image, background) + local output = {} + local x, y = 1, 1 + for i = 1, #image do + output[y] = output[y] or {} + if bl[image:sub(i,i)] then + output[y][x] = bl[image:sub(i,i)] + x = x + 1 + elseif image:sub(i,i) == "\n" then + x, y = 1, y + 1 + end + end + return output +end + +-- takes a loaded image and returns a loaded NFT image +nfte.convertFromNFP = function(image, background) + background = background or " " + local output = {{},{},{}} + if type(image) == "string" then + image = loadImageDataNFP(image) + end + local imageX, imageY = getSizeNFP(image) + local bx + for y = 1, imageY do + output[1][y] = "" + output[2][y] = "" + output[3][y] = "" + for x = 1, imageX do + if image[y][x] then + bx = (x % #background) + 1 + output[1][y] = output[1][y]..lb[image[y][x] or background:sub(bx,bx)] + output[2][y] = output[2][y]..lb[image[y][x] or background:sub(bx,bx)] + output[3][y] = output[3][y]..lb[image[y][x] or background:sub(bx,bx)] + end + end + end + return output +end + +-- loads the raw string NFT image data +nfte.loadImageData = function(image, background) + assert(type(image) == "string", "NFT image data must be string.") + local output = {} + -- images can be ANFT, which means they have multiple layers + if checkIfANFT(image) then + local L, R = 1, 1 + while L do + R = (image:find(nchar, L + 1) or 0) + output[#output+1] = loadImageDataNFT(image:sub(L, R - 1), background) + L = image:find(nchar, R + 1) + if L then L = L + 2 end + end + return output, "anft" + elseif image:find(tchar) or image:find(bchar) then + return loadImageDataNFT(image, background), "nft" + else + return convertFromNFP(image), "nfp" + end +end + +-- loads an image file. will convert from NFP if necessary +nfte.loadImage = function(path, background) + local file = io.open(path, "r") + if file then + io.input(file) + local output, format = loadImageData(io.read("*all"), background) + io.close() + return output, format + else + error("No such file exists, or is directory.") + end +end + +local unloadImageNFT = function(image) + assert(checkValid(image), "Invalid image.") + local output = "" + local text, back = " ", " " + local c, t, b + for y = 1, #image[1] do + for x = 1, #image[1][y] do + c, t, b = image[1][y]:sub(x,x), image[2][y]:sub(x,x), image[3][y]:sub(x,x) + if (t ~= text) or (x == 1) then + output = output..tchar..t + text = t + end + if (b ~= back) or (x == 1) then + output = output..bchar..b + back = b + end + output = output..c + end + if y ~= #image[1] then + output = output.."\n" + text, back = " ", " " + end + end + return output +end + +-- takes a loaded NFT image and converts it back into regular NFT (or ANFT) +nfte.unloadImage = function(image) + assert(checkValid(image), "Invalid image.") + local output = "" + if checkIfANFT(image) then + for i = 1, #image do + output = output .. unloadImageNFT(image[i]) + if i ~= #image then + output = output .. nchar .. "\n" + end + end + else + output = unloadImageNFT(image) + end + return output +end + +-- draws an image with the topleft corner at (x, y) +nfte.drawImage = function(image, x, y, terminal) + assert(checkValid(image), "Invalid image.") + assert(type(x) == "number", "x value must be number, got " .. type(x)) + assert(type(y) == "number", "y value must be number, got " .. type(y)) + terminal = terminal or term.current() + local cx, cy = terminal.getCursorPos() + for iy = 1, #image[1] do + terminal.setCursorPos(x, y + (iy - 1)) + terminal.blit(image[1][iy], image[2][iy], image[3][iy]) + end + terminal.setCursorPos(cx,cy) +end + +-- draws an image with the topleft corner at (x, y), with transparency +nfte.drawImageTransparent = function(image, x, y, terminal) + assert(checkValid(image), "Invalid image.") + assert(type(x) == "number", "x value must be number, got " .. type(x)) + assert(type(y) == "number", "y value must be number, got " .. type(y)) + terminal = terminal or term.current() + local cx, cy = terminal.getCursorPos() + local c, t, b + for iy = 1, #image[1] do + for ix = 1, #image[1][iy] do + c, t, b = image[1][iy]:sub(ix,ix), image[2][iy]:sub(ix,ix), image[3][iy]:sub(ix,ix) + if b ~= " " or c ~= " " then + terminal.setCursorPos(x + (ix - 1), y + (iy - 1)) + terminal.blit(c, t, b) + end + end + end + terminal.setCursorPos(cx,cy) +end + +-- draws an image centered at (x, y) or center screen +nfte.drawImageCenter = function(image, x, y, terminal) + terminal = terminal or term.current() + local scr_x, scr_y = terminal.getSize() + local imageX, imageY = nfte.getSize(image) + return nfte.drawImage( + image, + round(0.5 + (x and x or (scr_x/2)) - imageX/2), + round(0.5 + (y and y or (scr_y/2)) - imageY/2), + terminal + ), round(0.5 + (x and x or (scr_x/2)) - imageX/2), round(0.5 + (y and y or (scr_y/2)) - imageY/2) +end + +-- draws an image centered at (x, y) or center screen, with transparency +nfte.drawImageCenterTransparent = function(image, x, y, terminal) + terminal = terminal or term.current() + local scr_x, scr_y = terminal.getSize() + local imageX, imageY = getSize(image) + return nfte.drawImageTransparent( + image, + round(0.5 + (x and x or (scr_x/2)) - imageX/2), + round(0.5 + (y and y or (scr_y/2)) - imageY/2), + terminal + ) +end + +-- stretches an image so that its new height and width are (sx, sy). +-- if noRepeat, it will only draw one of each character for each pixel +-- in the original image, so as to not mess up text in images. +nfte.stretchImage = function(_image, sx, sy, noRepeat) + assert(checkValid(_image), "Invalid image.") + local output = {{},{},{}} + local image = deepCopy(_image) + if sx < 0 then image = flipX(image) end + if sy < 0 then image = flipY(image) end + sx, sy = math.abs(sx), math.abs(sy) + local imageX, imageY = nfte.getSize(image) + local tx, ty + if sx == 0 or sy == 0 then + for y = 1, math.max(sy, 1) do + output[1][y] = "" + output[2][y] = "" + output[3][y] = "" + end + return output + else + for y = 1, sy do + for x = 1, sx do + tx = round((x / sx) * imageX) + ty = math.ceil((y / sy) * imageY) + if not noRepeat then + output[1][y] = (output[1][y] or "")..image[1][ty]:sub(tx,tx) + else + output[1][y] = (output[1][y] or "").." " + end + output[2][y] = (output[2][y] or "")..image[2][ty]:sub(tx,tx) + output[3][y] = (output[3][y] or "")..image[3][ty]:sub(tx,tx) + end + end + if noRepeat then + for y = 1, imageY do + for x = 1, imageX do + if image[1][y]:sub(x,x) ~= " " then + tx = round(((x / imageX) * sx) - ((0.5 / imageX) * sx)) + ty = round(((y / imageY) * sy) - ((0.5 / imageY) * sx)) + output[1][ty] = stringWrite(output[1][ty], tx, image[1][y]:sub(x,x)) + end + end + end + end + return output + end +end + +local rotatePoint = function(x, y, angle, originX, originY) + return + round( (x-originX) * math.cos(angle) - (y-originY) * math.sin(angle) ) + originX, + round( (x-originX) * math.sin(angle) + (y-originY) * math.cos(angle) ) + originY +end + +-- rotates an image around (originX, originY) or its center, by angle radians +nfte.rotateImage = function(image, angle, originX, originY) + assert(checkValid(image), "Invalid image.") + if imageX == 0 or imageY == 0 then + return image + end + local output = {{},{},{}} + local realOutput = {{},{},{}} + local tx, ty, corners + local imageX, imageY = nfte.getSize(image) + local originX, originY = originX or math.floor(imageX / 2), originY or math.floor(imageY / 2) + corners = { + {rotatePoint(1, 1, angle, originX, originY)}, + {rotatePoint(imageX, 1, angle, originX, originY)}, + {rotatePoint(1, imageY, angle, originX, originY)}, + {rotatePoint(imageX, imageY, angle, originX, originY)}, + } + local minX = math.min(corners[1][1], corners[2][1], corners[3][1], corners[4][1]) + local maxX = math.max(corners[1][1], corners[2][1], corners[3][1], corners[4][1]) + local minY = math.min(corners[1][2], corners[2][2], corners[3][2], corners[4][2]) + local maxY = math.max(corners[1][2], corners[2][2], corners[3][2], corners[4][2]) + + for y = 1, (maxY - minY) + 1 do + output[1][y] = {} + output[2][y] = {} + output[3][y] = {} + for x = 1, (maxX - minX) + 1 do + tx, ty = rotatePoint(x + minX - 1, y + minY - 1, -angle, originX, originY) + output[1][y][x] = " " + output[2][y][x] = " " + output[3][y][x] = " " + if image[1][ty] then + if tx >= 1 and tx <= #image[1][ty] then + output[1][y][x] = image[1][ty]:sub(tx,tx) + output[2][y][x] = image[2][ty]:sub(tx,tx) + output[3][y][x] = image[3][ty]:sub(tx,tx) + end + end + end + end + for y = 1, #output[1] do + output[1][y] = table.concat(output[1][y]) + output[2][y] = table.concat(output[2][y]) + output[3][y] = table.concat(output[3][y]) + end + return output, math.ceil(minX), math.ceil(minY) +end + +local tWindow = lddterm.newWindow(scr_x, scr_y, 1, 1) +tWindow.blink = false +local tOriginal = term.redirect(tWindow.handle) + +local program = tArg[1] or "/rom/programs/shell.lua" + +local rendTimer = os.startTimer(0.05) + +parallel.waitForAny(function() + shell.run(program) +end, function() + local evt + local keysDown = {} + while true do + evt = {os.pullEvent()} + if evt[1] == "timer" and evt[2] == rendTimer then + lddterm.render() + rendTimer = os.startTimer(0.05) + elseif evt[1] == "key" then + keysDown[evt[2]] = true + if keysDown[keys.leftCtrl] and keysDown[keys.leftShift] and evt[2] == keys.backspace then + return + end + elseif evt[1] == "key_up" then + keysDown[evt[2]] = false + end + end +end) + +term.setCursorBlink(false) + +local fullScreenshot = lddterm.screenshot() +local screenshot +local screenshot_X, screenshot_Y = nfte.getSize(fullScreenshot) + +term.setBackgroundColor(colors.black) + +for i = screenshot_X, math.floor(screenshot_X / 4), -2 do + screenshot = nfte.stretchImage(fullScreenshot, i, i / (screenshot_X / screenshot_Y)) + term.clear() + nfte.drawImageCenter(screenshot) + lddterm.render() + sleep(0.05) +end + +local handX, handY = scr_x, -5 +for x = scr_x, math.floor(scr_x / 2) + 1, -2 do + term.clear() + nfte.drawImageCenter(screenshot) + nfte.drawImageTransparent(images.handOpen, handX, handY) + lddterm.render() + sleep(0.05) + handX = handX - 2.0 + handY = handY + 1 +end + +handX, handY = math.floor(handX), math.floor(handY) +local anchorX, anchorY = handX, handY +local scrollX, scrollY = 0, 0 + +term.clear() +local _, imageX, imageY = nfte.drawImageCenter(screenshot) +nfte.drawImageTransparent(images.handClosed, handX, handY) +lddterm.render() +sleep(0.5) + +for i = 1, 10 do + handX = handX + 0.5 + handY = handY + 0.4 + term.clear() + nfte.drawImage(screenshot, imageX + (handX - anchorX), imageY + (handY - anchorY)) + nfte.drawImageTransparent(images.handClosed, handX, handY) + lddterm.render() + sleep(0.05) +end + +sleep(0.4) + +for i = 1, 10 do + handX = handX - (0.6 + (i / 8)) + handY = handY - (0.1 + (i / 12)) + if i >= 2 then + scrollX = scrollX + 1 + end + term.clear() + nfte.drawImage(screenshot, scrollX + imageX + (handX - anchorX), scrollY + imageY + (handY - anchorY)) + nfte.drawImageTransparent(images.handClosed, scrollX + handX, scrollY + handY) + lddterm.render() + sleep(0.05) +end +local imageYvel = -0.9 +local imageRotate = 0 +imageX = imageX + (handX - anchorX) +imageY = imageY + (handY - anchorY) + +local rImage, rX, rY + +for i = 1, 41 do + if i <= 5 then + handX = handX - 1 + handY = handY - 0.8 + end + term.clear() + rImage, rX, rY = nfte.rotateImage(screenshot, imageRotate) + nfte.drawImage(rImage, scrollX + imageX, scrollY + imageY) + if i < 25 then + nfte.drawImageTransparent(images.handOpen, scrollX + handX, scrollY + handY) + else + nfte.drawImageTransparent(images.trashCan, scrollX - 150, scrollY + 32) + end + lddterm.render() + + sleep(0.05) + + imageRotate = imageRotate + 0.12 + scrollX = scrollX + 4 + if i < 20 then + scrollY = scrollY - 0.25 + else + scrollY = scrollY - 0.8 + end + imageX = imageX - 4 + imageY = imageY + imageYvel + + imageYvel = imageYvel + 0.07 +end + +sleep(0.5) + +local scene = lddterm.screenshot() + +for i = 1, 5 do + nfte.drawImage(scene, 1, 1) + nfte.drawImageTransparent(images.trashLid, (scr_x/2) - 4, i - 4) + lddterm.render() + sleep(0.05) +end + +local lidAngle, rotLid = 0 + +for i = 1, 10 do + lidAngle = lidAngle + 0.053 + rotLid = nfte.rotateImage(images.trashLid, lidAngle) + nfte.drawImage(scene, 1, 1) + nfte.drawImageTransparent(rotLid, (scr_x/2) - 4, 1) + lddterm.render() + sleep(0.05) +end + +sleep(0.5) + +term.redirect(tOriginal)