Advertisement
theTANCO

telepaint.lua

Jul 10th, 2023 (edited)
797
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 25.84 KB | None | 0 0
  1. -- The following APIs are required for this program:
  2. -- pastebin get Rac6Jxjg /API/LibAppend.lua
  3. -- pastebin get t2TvSiSU /API/Class.lua
  4. -- pastebin get KA2dK07y /API/Events.lua
  5.  
  6. -- Attribution: The file saving and loading functions have taken inspiration
  7. -- from this program:
  8. -- • https://www.computercraft.info/forums2/index.php?/topic/27331-micropaint-experimental-painting-program-for-tiny-pixels/
  9.  
  10. -- More info at: https://forums.computercraft.cc/index.php?topic=536.0
  11. -- For some reason, images aren't showing up for me on the forum post no matter
  12. -- what I do to try and update it, so here's an imgur album:
  13. -- https://imgur.com/a/M9vQ2lS
  14.  
  15. require("/API/Events")
  16. require("/API/bpi")
  17.  
  18. local termSize = vector.new(term.getSize())
  19. local event = Events()
  20. local image, color, menu
  21.  
  22. image = Class(function()
  23.     local ro = {}
  24.  
  25.     local filePath
  26.     local symbols = {
  27.         [128] = {{1, 1}, {1, 1}, {1, 1}},
  28.         [129] = {{0, 1}, {1, 1}, {1, 1}},
  29.         [130] = {{1, 0}, {1, 1}, {1, 1}},
  30.         [131] = {{0, 0}, {1, 1}, {1, 1}},
  31.         [132] = {{1, 1}, {0, 1}, {1, 1}},
  32.         [133] = {{0, 1}, {0, 1}, {1, 1}},
  33.         [134] = {{1, 0}, {0, 1}, {1, 1}},
  34.         [135] = {{0, 0}, {0, 1}, {1, 1}},
  35.         [136] = {{1, 1}, {1, 0}, {1, 1}},
  36.         [137] = {{0, 1}, {1, 0}, {1, 1}},
  37.         [138] = {{1, 0}, {1, 0}, {1, 1}},
  38.         [139] = {{0, 0}, {1, 0}, {1, 1}},
  39.         [140] = {{1, 1}, {0, 0}, {1, 1}},
  40.         [141] = {{0, 1}, {0, 0}, {1, 1}},
  41.         [142] = {{1, 0}, {0, 0}, {1, 1}},
  42.         [143] = {{0, 0}, {0, 0}, {1, 1}},
  43.         [144] = {{1, 1}, {1, 1}, {0, 1}},
  44.         [145] = {{0, 1}, {1, 1}, {0, 1}},
  45.         [146] = {{1, 0}, {1, 1}, {0, 1}},
  46.         [147] = {{0, 0}, {1, 1}, {0, 1}},
  47.         [148] = {{1, 1}, {0, 1}, {0, 1}},
  48.         [149] = {{0, 1}, {0, 1}, {0, 1}},
  49.         [150] = {{1, 0}, {0, 1}, {0, 1}},
  50.         [151] = {{0, 0}, {0, 1}, {0, 1}},
  51.         [152] = {{1, 1}, {1, 0}, {0, 1}},
  52.         [153] = {{0, 1}, {1, 0}, {0, 1}},
  53.         [154] = {{1, 0}, {1, 0}, {0, 1}},
  54.         [155] = {{0, 0}, {1, 0}, {0, 1}},
  55.         [156] = {{1, 1}, {0, 0}, {0, 1}},
  56.         [157] = {{0, 1}, {0, 0}, {0, 1}},
  57.         [158] = {{1, 0}, {0, 0}, {0, 1}},
  58.         [159] = {{0, 0}, {0, 0}, {0, 1}}
  59.     }
  60.  
  61.     local source = {}
  62.     source.image = {}
  63.     source.scroll = vector.new()
  64.  
  65.     local teletext = {}
  66.     teletext.image = {}
  67.     teletext.scroll = vector.new()
  68.     teletext.select = vector.new()
  69.  
  70.     local startDrag = vector.new()
  71.  
  72.     ro.resize = function()
  73.         source.pos = vector.new(1, 1)
  74.         source.size = vector.new(math.floor((termSize.x-1)*2/3), termSize.y)
  75.         source.win = window.create(term.current(), 1, 1, source.size.x, source.size.y)
  76.         teletext.pos = vector.new(source.size.x+2, 1)
  77.         teletext.size = vector.new(math.ceil(source.size.x/2), math.ceil(source.size.y/3))
  78.         teletext.win = window.create(term.current(), teletext.pos.x, 1, teletext.size.x, teletext.size.y)
  79.     end
  80.  
  81.     ro.sourcePos = function()
  82.         return vector.new(source.pos.x, source.pos.y)
  83.     end
  84.     ro.telePos = function()
  85.         return vector.new(teletext.pos.x, teletext.pos.y)
  86.     end
  87.     ro.sourceSize = function()
  88.         return vector.new(source.size.x, source.size.y)
  89.     end
  90.     ro.teleSize = function()
  91.         return vector.new(teletext.size.x, teletext.size.y)
  92.     end
  93.     ro.pixelPos = function()
  94.         local x, y, z = teletext.select.x, teletext.select.y
  95.         if teletext.image[y] and teletext.image[y][x] then
  96.             z = teletext.image[y][x].bCol
  97.         else
  98.             z = "f"
  99.         end
  100.         local returnPos = vector.new(
  101.             teletext.select.x - teletext.scroll.x + teletext.pos.x - 1,
  102.             teletext.select.y - teletext.scroll.y,
  103.             2 ^ (15 - tonumber(z, 16))
  104.         )
  105.         if isBetween(returnPos.x, teletext.pos.x, termSize.x, true)
  106.         and isBetween(returnPos.y, 1, teletext.size.y, true) then
  107.             return returnPos
  108.         end
  109.     end
  110.  
  111.     local drawImage = function(i)
  112.         local pos = vector.new()
  113.         for y = 1, i.size.y do
  114.             pos.y = i.scroll.y+y
  115.             for x = 1, i.size.x do
  116.                 pos.x = i.scroll.x+x
  117.                 i.win.setCursorPos(x, y)
  118.                 if i.image[pos.y] and i.image[pos.y][pos.x] then
  119.                     term.blit(i.image[pos.y][pos.x].text, i.image[pos.y][pos.x].tCol, i.image[pos.y][pos.x].bCol)
  120.                 else
  121.                     term.blit("\127", "7", "f")
  122.                 end
  123.             end
  124.         end
  125.     end
  126.     ro.drawSource = function()
  127.         drawImage(source)
  128.     end
  129.     ro.drawTele = function()
  130.         drawImage(teletext)
  131.         term.setCursorPos(teletext.pos.x-1, teletext.size.y+1)
  132.         term.setBackgroundColor(colors.gray)
  133.         term.setTextColor(colors.black)
  134.         term.write("x" .. teletext.scroll.x .. "y" .. teletext.scroll.y .. "  ")
  135.         term.setCursorPos(teletext.pos.x, teletext.size.y+2)
  136.         term.setBackgroundColor(colors.black)
  137.         local x, y, pixel = teletext.select.x, teletext.select.y
  138.         if teletext.image[y] and teletext.image[y][x] then
  139.             pixel = teletext.image[y][x]
  140.         end
  141.         if pixel then
  142.             term.blit(pixel.text, pixel.tCol, pixel.bCol)
  143.             term.setTextColor(colors.red)
  144.             term.write('  "\\' .. pixel.text:byte() .. '"')
  145.         else
  146.             term.write("         ")
  147.         end
  148.     end
  149.  
  150.     local convertPixel = function(pos)
  151.         local pixelPos = vector.new(math.ceil(pos.x/2), math.ceil(pos.y/3))
  152.         local pixelKeys = {text = 2, tCol = 0, bCol = 1}
  153.         local symbol = {[2] = "\128"}
  154.         local target = {{1, 1}, {1, 1}, {1, 1}}
  155.         local nilTarget = {{false, false}, {false, false}, {false, false}}
  156.  
  157.         if source.image[pos.y+2] and source.image[pos.y+2][pos.x+1] then
  158.             symbol[0] = source.image[pos.y+2][pos.x+1].bCol
  159.             symbol[1] = source.image[pos.y+2][pos.x+1].bCol
  160.         else
  161.             symbol[0] = color.color(1)
  162.             symbol[1] = color.color(1)
  163.         end
  164.  
  165.         for y = 0, 2 do
  166.             for x = 0, 1 do
  167.                 if source.image[pos.y+y] and source.image[pos.y+y][pos.x+x] then
  168.                     if symbol[0] == symbol[1]
  169.                     and source.image[pos.y+y][pos.x+x].bCol ~= symbol[1] then
  170.                         symbol[0] = source.image[pos.y+y][pos.x+x].bCol
  171.                     end
  172.                 else
  173.                     nilTarget[y+1][x+1] = true
  174.                 end
  175.             end
  176.         end
  177.  
  178.         for y = 0, 2 do
  179.             for x = 0, 1 do
  180.                 if source.image[pos.y+y] and source.image[pos.y+y][pos.x+x] then
  181.                     if source.image[pos.y+y][pos.x+x].bCol == symbol[0] then
  182.                         target[y+1][x+1] = 0
  183.                     elseif source.image[pos.y+y][pos.x+x].bCol == symbol[1] then
  184.                         target[y+1][x+1] = 1
  185.                     else
  186.                         target[y+1][x+1] = 1 - color.ditherMode()
  187.                     end
  188.                 end
  189.             end
  190.         end
  191.  
  192.         local targetCheck = true
  193.         for a, b in pairs(symbols) do
  194.             local sourceCheck = true
  195.             for y = 1, 3 do
  196.                 for x = 1, 2 do
  197.                     sourceCheck = sourceCheck and target[y][x] == b[y][x]
  198.                     targetCheck = targetCheck and nilTarget[y][x]
  199.                 end
  200.             end
  201.             if targetCheck then
  202.                 break
  203.             end
  204.             if sourceCheck then
  205.                 symbol[2] = string.char(a)
  206.                 break
  207.             end
  208.         end
  209.  
  210.         if targetCheck then
  211.             if teletext.image[pixelPos.y] then
  212.                 teletext.image[pixelPos.y][pixelPos.x] = nil
  213.                 if textutils.serialize(teletext.image[pixelPos.y]) == "{}" then
  214.                     teletext.image[pixelPos.y] = nil
  215.                 end
  216.             end
  217.         else
  218.             teletext.image[pixelPos.y] = teletext.image[pixelPos.y] or {}
  219.             teletext.image[pixelPos.y][pixelPos.x] = {
  220.                 text = symbol[2],
  221.                 tCol = symbol[0],
  222.                 bCol = symbol[1]
  223.             }
  224.         end
  225.         ro.drawTele()
  226.     end
  227.  
  228.     ro.convertImage = function()
  229.         for y, a in pairs(teletext.image) do
  230.             for x, b in pairs(teletext.image[y]) do
  231.                 convertPixel(vector.new(x*2-1, y*3-2))
  232.             end
  233.         end
  234.     end
  235.  
  236.     local scroll = function(x, y)
  237.         x, y = x or 0, y or 0
  238.         source.scroll = source.scroll + vector.new(x, y)
  239.         if source.scroll.x < 0 then
  240.             source.scroll.x = 0
  241.         end
  242.         if source.scroll.y < 0 then
  243.             source.scroll.y = 0
  244.         end
  245.         teletext.scroll = vector.new(
  246.             math.floor(source.scroll.x/2),
  247.             math.floor(source.scroll.y/3)
  248.         )
  249.         ro.drawSource()
  250.         ro.drawTele()
  251.     end
  252.  
  253.     local convertSource = function(sourceX, sourceY, pixel)
  254.         local charCode = pixel.text:byte()
  255.         for a, b in ipairs(symbols[charCode]) do
  256.             local y = sourceY+a-1
  257.             source.image[y] = source.image[y] or {}
  258.             for c, d in ipairs(b) do
  259.                 local x = sourceX+c-1
  260.                 source.image[y][x] = {
  261.                     text = " ",
  262.                     tCol = "0"
  263.                 }
  264.                 if d == 0 then
  265.                     source.image[y][x].bCol = pixel.tCol
  266.                 else
  267.                     source.image[y][x].bCol = pixel.bCol
  268.                 end
  269.             end
  270.         end
  271.     end
  272.  
  273.     ro.ui = function()
  274.         if OR(event[1], "mouse_click", "mouse_drag") then
  275.             if event.isPressed("key", keys.leftShift) or event.isPressed("key", keys.leftShift) then
  276.                 if startDrag.x > 0 and startDrag.y > 0 then
  277.                     local delta = startDrag - vector.new(event[3], event[4])
  278.                     if not(event[3] <= source.size.x) then
  279.                         delta.x = delta.x * 2
  280.                         delta.y = delta.y * 3
  281.                     end
  282.                     scroll(delta.x, delta.y)
  283.                 end
  284.                 startDrag = vector.new(event[3], event[4])
  285.             elseif event[3] <= source.size.x then
  286.                 local pos = vector.new(event[3]+source.scroll.x, event[4]+source.scroll.y)
  287.                 source.image[pos.y] = source.image[pos.y] or {}
  288.                 if event[2] == 2 then
  289.                     source.image[pos.y][pos.x] = nil
  290.                     if textutils.serialize(source.image[pos.y]) == "{}" then
  291.                         source.image[pos.y] = nil
  292.                     end
  293.                 elseif event[2] == 3 then
  294.                     if source.image[pos.y] and source.image[pos.y][pos.x] then
  295.                         color.color(0, source.image[pos.y][pos.x].bCol)
  296.                         color.drawColor()
  297.                     end
  298.                 else
  299.                     source.image[pos.y][pos.x] = {
  300.                         text = " ",
  301.                         tCol = "0",
  302.                         bCol = color.color(event[2]-1)
  303.                     }
  304.                 end
  305.                 convertPixel(vector.new(math.ceil(pos.x/2)*2-1, math.ceil(pos.y/3)*3-2))
  306.                 ro.drawSource()
  307.             elseif event[3] >= teletext.pos.x then
  308.                 if event[2] == 1 then
  309.                     teletext.select.x = event[3]-teletext.pos.x+teletext.scroll.x+1
  310.                     teletext.select.y = event[4]+teletext.scroll.y
  311.                 else
  312.                     teletext.select = vector.new()
  313.                 end
  314.                 ro.drawTele()
  315.             end
  316.         elseif event[1] == "mouse_up" then
  317.             startDrag = vector.new()
  318.         elseif event[1] == "mouse_scroll" then
  319.             if event[3] <= source.size.x then
  320.                 if event.isPressed("key", keys.leftShift) or event.isPressed("key", keys.rightShift) then
  321.                     scroll(event[2], 0)
  322.                 else
  323.                     scroll(0, event[2])
  324.                 end
  325.             else
  326.                 if event.isPressed("key", keys.leftShift) or event.isPressed("key", keys.rightShift) then
  327.                     scroll(event[2]*2, 0)
  328.                 else
  329.                     scroll(0, event[2]*3)
  330.                 end
  331.             end
  332.         end
  333.     end
  334.  
  335.     ro.save = function()
  336.         menu.canSave(bpi.save(teletext.image, filePath)+1)
  337.     end
  338.  
  339.     local load = function()
  340.         teletext.image = bpi.load(filePath)
  341.         for y, a in pairs(teletext.image) do
  342.             for x, b in pairs(a) do
  343.                 convertSource(x*2-1, y*3-2, b)
  344.             end
  345.         end
  346.     end
  347.  
  348.     return {
  349.         ctor = function(path)
  350.             if path == nil or path == "" then
  351.                 error("Usage: telepaint <path>", 0)
  352.             end
  353.             if path:sub(1, 1) == "/" then
  354.                 filePath = path
  355.             else
  356.                 filePath = shell.dir() .. path
  357.             end
  358.             if filePath:sub(filePath:len()-3, filePath:len()) ~= ".bpi" then
  359.                 filePath = filePath .. ".bpi"
  360.             end
  361.             if fs.exists(filePath) then
  362.                 load()
  363.             end
  364.             ro.resize()
  365.         end,
  366.         protected = true,
  367.         readOnly = ro
  368.     }
  369. end)(...)
  370.  
  371. color = Class(function()
  372.     local ro = {}
  373.     local pos = vector.new(image.telePos().x, image.teleSize().y+3)
  374.     local col = {[0] = "0", [1] = "f"}
  375.     local ditherMode = 0
  376.  
  377.     ro.resize = function()
  378.         pos = vector.new(image.telePos().x, image.teleSize().y+3)
  379.     end
  380.  
  381.     ro.pos = function()
  382.         return vector.new(pos.x, pos.y)
  383.     end
  384.  
  385.     ro.color = function(n, c)
  386.         for a = 0, 15 do
  387.             if c == tobase(a, 16):lower() then
  388.                 col[n] = c
  389.             end
  390.         end
  391.         if OR(n, 0, 1) then
  392.             return col[n]
  393.         else
  394.             return col[0], col[1]
  395.         end
  396.     end
  397.  
  398.     ro.ditherMode = function()
  399.         return ditherMode
  400.     end
  401.  
  402.     ro.drawColor = function()
  403.         for a = 0, 15 do
  404.             term.setCursorPos(pos.x+a%8, pos.y+math.floor(a/8))
  405.             term.blit(" ", "0", tobase(a, 16))
  406.         end
  407.         term.setCursorPos(pos.x+8, pos.y)
  408.         term.blit(" ", "0", col[0])
  409.         term.setCursorPos(pos.x+8, pos.y+1)
  410.         term.blit(" ", "0", col[1])
  411.         term.setCursorPos(pos.x, pos.y+2)
  412.         term.blit("Dither: " .. ditherMode, "00000000f", "ffffffff0")
  413.     end
  414.  
  415.     ro.ui = function()
  416.         if event[1] == "mouse_click" and isBetween(event[2], 0, 3)
  417.         and isBetween(event[3], pos.x, pos.x+7, true)
  418.         and isBetween(event[4], pos.y, pos.y+1, true) then
  419.             col[event[2]-1] = tobase((event[3] - pos.x) + (event[4] - pos.y) * 8, 16):lower()
  420.             ro.drawColor()
  421.             image.convertImage()
  422.         elseif event[1] == "mouse_click" and event[4] == pos.y+2 then
  423.             ditherMode = 1 - ditherMode
  424.             ro.drawColor()
  425.             image.convertImage()
  426.         elseif event[1] == "char" and OR(event[2], "0", "1") then
  427.             ditherMode = tonumber(event[2])
  428.             ro.drawColor()
  429.             image.convertImage()
  430.         end
  431.     end
  432.  
  433.     return {
  434.         protected = true,
  435.         readOnly = ro
  436.     }
  437. end)()
  438.  
  439. menu = Class(function()
  440.     local ro = {}
  441.     local pos = vector.new(image.telePos().x, image.teleSize().y+6)
  442.     local selectSave = true
  443.     local menuOpen = false
  444.     local menuText = 0
  445.     local text = {
  446.         [0] = {"Ctrl or", "click to"},
  447.         [1] = {"The file", "was saved"},
  448.         [2] = {"Unable to", "save file"},
  449.         [3] = {"File size", "too big!"},
  450.     }
  451.  
  452.     ro.resize = function()
  453.         pos = vector.new(image.telePos().x, image.teleSize().y+6)
  454.     end
  455.  
  456.     ro.pos = function()
  457.         return vector.new(pos.x, pos.y)
  458.     end
  459.  
  460.     ro.menuOpen = function()
  461.         return menuOpen
  462.     end
  463.  
  464.     ro.drawMenu = function()
  465.         term.setBackgroundColor(colors.black)
  466.         term.setTextColor(colors.yellow)
  467.         term.setCursorPos(pos.x, pos.y)
  468.         term.write(text[menuText][1])
  469.         term.setCursorPos(pos.x, pos.y+1)
  470.         term.write(text[menuText][2])
  471.         term.setCursorPos(pos.x, pos.y+2)
  472.         term.blit("Save Exit", "fffffffff", "8888f8888")
  473.         term.setTextColor(colors.white)
  474.         term.setCursorPos(pos.x+4, pos.y+2)
  475.         if menuOpen then
  476.             if selectSave then term.write("\17")
  477.             else term.write("\16") end
  478.         else
  479.             term.write(" ")
  480.         end
  481.     end
  482.  
  483.     ro.canSave = function(i)
  484.         menuText = expect.range(i, 0, #text)
  485.         ro.drawMenu()
  486.     end
  487.  
  488.     ro.ui = function()
  489.         if event[1] == "key" and OR(event[2], keys.leftCtrl, keys.rightCtrl) then
  490.             menuOpen = not menuOpen
  491.             ro.drawMenu()
  492.         elseif (event[1] == "key" and event[2] == keys.left)
  493.         or (event[1] == "mouse_click" and event[2] == 1
  494.         and isBetween(event[3], pos.x-1, pos.x+4) and event[4] == pos.y+2) then
  495.             selectSave = true
  496.             ro.drawMenu()
  497.             if event[1] == "mouse_click" then
  498.                 menuOpen = true
  499.                 event.queueEvent("key", keys.enter)
  500.             end
  501.         elseif (event[1] == "key" and event[2] == keys.right)
  502.         or (event[1] == "mouse_click" and event[2] == 1
  503.         and isBetween(event[3], pos.x+4, pos.x+9) and event[4] == pos.y+2) then
  504.             selectSave = false
  505.             ro.drawMenu()
  506.             if event[1] == "mouse_click" then
  507.                 menuOpen = true
  508.                 event.queueEvent("key", keys.enter)
  509.             end
  510.         elseif event[1] == "key" and OR(event[2], keys.enter, keys.numPadEnter) then
  511.             if selectSave then
  512.                 image.save()
  513.                 menuOpen = false
  514.                 ro.drawMenu()
  515.             else
  516.                 term.setBackgroundColor(colors.black)
  517.                 term.clear()
  518.                 term.setCursorPos(1, 1)
  519.                 error()
  520.             end
  521.         end
  522.     end
  523.  
  524.     return {
  525.         protected = true,
  526.         readOnly = ro
  527.     }
  528. end)()
  529.  
  530. local drawAll = function()
  531.     term.setBackgroundColor(colors.black)
  532.     term.clear()
  533.     term.setCursorPos(1, 1)
  534.     if termSize.x < 26 or termSize.y < 12 then
  535.         error("Minimum term size is 26x12. Actual term size is " .. termSize.x .. "x" .. termSize.y, 0)
  536.     end
  537.     paintutils.drawFilledBox(1, 1, image.sourceSize().x+1, termSize.y, colors.gray)
  538.     paintutils.drawFilledBox(image.telePos().x, 1, termSize.x, image.teleSize().y+1, colors.gray)
  539.     image.drawSource()
  540.     image.drawTele()
  541.     color.drawColor()
  542.     menu.drawMenu()
  543. end
  544.  
  545. drawAll()
  546. while true do
  547.     local pixelPos = image.pixelPos()
  548.     if pixelPos then
  549.         term.setCursorPos(pixelPos.x, pixelPos.y)
  550.         term.setTextColor(pixelPos.z)
  551.         term.setCursorBlink(true)
  552.     end
  553.     event.getEvent()
  554.     term.setCursorBlink(false)
  555.     if event[1] == "key" and OR(event[2], keys.leftCtrl, keys.rightCtrl)
  556.     or (event[1] == "mouse_click" and event[2] == 1
  557.     and isBetween(event[3], menu.pos().x, menu.pos().x+8, true)
  558.     and event[4] == menu.pos().y+2) or menu.menuOpen() then
  559.         menu.ui()
  560.  
  561.     elseif (event[1] == "mouse_click" and isBetween(event[2], 0, 3)
  562.     and isBetween(event[3], color.pos().x, color.pos().x+8, true)
  563.     and isBetween(event[4], color.pos().y, color.pos().y+3, true))
  564.     or (event[1] == "char" and OR(event[2], "0", "1")) then
  565.         color.ui()
  566.  
  567.     elseif (OR(event[1], "mouse_click", "mouse_drag", "mouse_scroll")
  568.     and (event[3] <= image.sourceSize().x
  569.     or (event[3] >= image.telePos().x and event[4] <= image.teleSize().y)))
  570.     or event[1] == "mouse_up" then
  571.         image.ui()
  572.  
  573.     elseif event[1] == "term_resize" then
  574.         termSize = vector.new(term.getSize())
  575.         image.resize()
  576.         color.resize()
  577.         menu.resize()
  578.         drawAll()
  579.     end
  580. end
  581.  
  582. --[[ Changelog
  583. 2024/09/09:
  584. • Fixed color menu not being drawn in the correct Y position when resizing
  585.   the screen.
  586.  
  587. 2024/05/14:
  588. • Changed 'doFile' to 'require'.
  589. • Added API for bpi. Files will now be saved and loaded using this API.
  590. • Added a link to an imgur album with all the screenshots since they don't seem
  591.   to want to show up in the forum post for some reason.
  592.  
  593. 2023/07/10:
  594. • One more revision to the save/load functions, hopeully the last for a while.
  595.   The .bpi file size has been reduced once again.
  596. • The length of the x and y coordinates are now only 1 byte collectively.
  597. • 4 bits for length of x, and another 4 bits for the length of y.
  598. • Posted to Pastebin and the computercraft.cc forums.
  599.  
  600. 2023/07/09:
  601. • Revised the save and load functions again. Files will no longer be limitted to
  602.   a maximum size of 256 KB.
  603.   • An extra byte will be used to tell how many bytes the x and y coordinates
  604.     are, with the max number of bytes per coordinate being 32 (256 bits).
  605.   • Coordinates whose values are less than 256 will only be one byte in the
  606.     file, less than 65536 will be two bytes, and so on.
  607.   • This also means that the file size will compound based on how big the image
  608.     is. I still can't imagine anyone making images that big, but at least now
  609.     that silly file size restriction has been removed while still keeping the
  610.     file sizes relatively low.
  611. • The main menu will now tell you if the file is too big for the remaining space
  612.   in the computer. It will also tell you this if a coordinate is more than 256
  613.   bits (which shouldn't even be possible).
  614. • The main menu will tell you if it was unable to open the file for saving for
  615.   any other reason.
  616. • The main menu will tell you if the file was saved successfuly.
  617. • The restriction to scrolling has also been removed.
  618. • The scroll position is now being printed on the border.
  619. • The colors have been moved around to make room for a new feature.
  620. • Left clicking on the output image will select a pixel. The pixel will be
  621.   highlighted with the shell cursor, and the pixel along with its character code
  622.   will be displayed at the top of the menu window.
  623. • Right or middle clicking on the output image will deselect the pixel.
  624.  
  625. 2023/07/08:
  626. • Renamed the program to "telepaint.lua" so as to not conflict with the name
  627.   of the program credited in the attribution.
  628. • All variables referencing the micro image have been renamed to 'teletext' or
  629.   'tele*'.
  630. • Changed right click to erase and middle click to pick a color on the canvas.
  631. • The second selected color is now only used for converting transparent pixels to
  632.   the background color of the output image.
  633. • The outputs of the 'tobase' function are now being converted to lower case to
  634.   prevent errors with reading the text and background colors.
  635. • Revised the save and load functions to reduce the file size.
  636. • The output image size is now limited to 256x256 characters, which is 512x768
  637.   teletext pixels. This sets the maximum file size to 256 KB which is an eighth
  638.   of the default capacity of a CC computer. That much shouldn't even be needed
  639.   for ComputerCraft, but this way the entire byte for each coordinate gets used.
  640. • Fixed the dithering effect being applied to pixels with the text and
  641.   background colors. The effect should only be applied to additional colors.
  642.  
  643. 2023/07/07:
  644. • Changing the selected colors or the dithering mode will update the entire
  645.   micro image with the new settings.
  646. • Using the scroll wheel while the mouse is over the source or micro image will
  647.   scroll the image vertically.
  648. • Holding Shift while scrolling will scroll horizontally.
  649. • Scrolling over the micro image will have a vertical magnitude of 3 and a
  650.   horizontal magnitude of 2.
  651. • Holding Shift while click anddragging the mouse on either the source or micro
  652.   image will pan the image by their respective magnitude.
  653. • Files can now be saved using the save button. Keyboard and mouse both work.
  654. • Loading a file works the same way as the built in paint program.
  655.   Usage: micropaint <path>
  656.  
  657. 2023/07/06:
  658. • "Pixels" can now be painted to the source image.
  659. • The source image will immediately be converted to the micro image when
  660.   painting.
  661. • The primary color is the color of the bottom-right most pixel in the micro
  662.   pixel.
  663. • The secondary color is the first color in the micro pixel (going from top left
  664.   to bottom right) that is not the primary color.
  665. • When the dithering mode is 0, any colors that are not the primary or secondary
  666.   are converted to the primary.
  667. • When the dithering mode is 1, any colors that are not the primary or secondary
  668.   are converted to the secondary.
  669. • If the secondary pixels are transparent, it will use the primary color for
  670.   those pixels.
  671. • If the primary pixel is transparent, it will use the color selected for right
  672.   click as the primary color.
  673.  
  674. 2023/07/05:
  675. • Created UI with all of the menu controls being functional.
  676. • The window to the left will be the source image, containing ComputerCraft
  677.   "pixels".
  678. • The window to the top right will be the micro image, containing the symbols
  679.   converted from the source image.
  680. • Transparency is represented by the character "\127" with a black background
  681.   and gray text color.
  682. • The window to the bottom right contains all of the menu options.
  683. • Clicking the color pixels with left or right click changes the selected
  684.   color for left or right click.
  685. • Clicking "Dither: #" toggles the dithering mode.
  686. • Clicking the "Save" button initiates the save function. The actual save
  687.   function has not been implemented yet.
  688. • Clicking the "Exit" button exits the program.
  689. • Pressing Ctrl toggles an arrow cursor pointing at the "Save" or "Exit"
  690.   buttons. Left or right arrow keys change what it points at, and Enter
  691.   initiates the button's action.
  692.  
  693. 2023/07/04:
  694. • Made prototype for converting ComputerCraft "pixels" to the pixel symbols
  695.   of character codes between 128 and 159.
  696. ]]
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement