diff --git a/halyde/apps/helpdb/rtest.txt b/halyde/apps/helpdb/rtest.txt index 04b4173..321919f 100644 --- a/halyde/apps/helpdb/rtest.txt +++ b/halyde/apps/helpdb/rtest.txt @@ -1 +1,3 @@ -Ergonomics \ No newline at end of file +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABB +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDD +EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFF \ No newline at end of file diff --git a/halyde/apps/rtest.lua b/halyde/apps/rtest.lua index 9413569..825e54f 100644 --- a/halyde/apps/rtest.lua +++ b/halyde/apps/rtest.lua @@ -1,5 +1,91 @@ local raster = import("raster") -raster.drawPixel(4, 3, 0xFFFF00) -raster.drawPixel(40, 34, nil, 0xFF00F) -raster.drawPixel(3, 1) \ No newline at end of file +raster.init() + +--[[for i=4,20 do + raster.set(i,i) + raster.set(i,i+4,0xFF00FF) +end]] + +--[[ for x=4,20 do + for y=4,20 do + if (x+y)%2==0 then + raster.set(x,y,0xFF00FF) + end + end +end ]] + +local event = import("event") +local x=0 +local y=0 +local vx=1 +local vy=1 +local col = 0x808080 +local i=0 + +while event.pull("key_down",0)==nil do + i = i + 1 + raster.set(x,y,col) + + x = x + vx + y = y + vy + + if x>raster.displayWidth then + x=raster.displayWidth + vx = -math.abs(vx) + col = math.random(0,0xFFFFFF) + end + if x<1 then + x=1 + vx = math.abs(vx) + col = math.random(0,0xFFFFFF) + end + if y>raster.displayHeight-6 then + y=raster.displayHeight-6 + vy = -math.abs(vy) + col = math.random(0,0xFFFFFF) + end + if y<1 then + y=1 + vy = math.abs(vy) + col = math.random(0,0xFFFFFF) + end + + if i>10 and i%15>0 then + while true do + local tries=0 + local dx,dy=math.random(1,raster.displayWidth),math.random(1,raster.displayHeight-6) + if raster.get(dx,dy)~=0 then + raster.set(dx,dy,0) + break + end + tries = tries + 1 + if tries>20 then + break + end + end + end + + if i%10==0 then + raster.update() + coroutine.yield() + end +end + +--[[ for i=0,360,4 do + local angle = i/180*math.pi + if false then + local x1,y1,x2,y2=raster.displayWidth/2,raster.displayHeight/2,raster.displayWidth/2+math.sin(angle)*80,raster.displayHeight/2+math.cos(angle)*80 + raster.fillEllipse(x1,y1,x2,y2,0xFF00FF) + raster.update() + raster.fillEllipse(x1,y1,x2,y2,0x000000) + else + local x,y,c=raster.displayWidth/2,raster.displayHeight/2,math.abs(math.sin(angle)*100) + raster.drawCircle(x,y,c,0xFF00FF) + raster.update() + raster.drawCircle(x,y,c,0x000000) + end +end ]] + +raster.free() +termlib.cursorPosY=1 \ No newline at end of file diff --git a/halyde/core/boot.lua b/halyde/core/boot.lua index bdf6166..5565300 100644 --- a/halyde/core/boot.lua +++ b/halyde/core/boot.lua @@ -1,7 +1,7 @@ local loadfile = ... local filesystem = loadfile("/halyde/lib/filesystem.lua")(loadfile) -_G._OSVERSION = "Halyde 0.8.3" +_G._OSVERSION = "Halyde 0.9.0" function _G.import(module, ...) local args = table.pack(...) diff --git a/halyde/lib/raster.lua b/halyde/lib/raster.lua index 27cf0f2..a3719b5 100644 --- a/halyde/lib/raster.lua +++ b/halyde/lib/raster.lua @@ -1,35 +1,411 @@ -local raster = {} +local raster = { + ["units"]={}, + ["defaultBackgroundColor"]=0x000000, + ["defaultForegroundColor"]=0xFFFFFF, + ["displayWidth"]=0, + ["displayHeight"]=0, + ["charWidth"]=0, + ["charHeight"]=0 +} -local ocelot = component.proxy(component.list("ocelot")()) +-- local ocelot = component.proxy(component.list("ocelot")()) local gpu = component.proxy(component.list("gpu")()) -function raster.drawPixel(x, y, newbg, newfg) - -- get original character for "merging" - local char, fg, bg = gpu.get(x, y) -- thx wah - ocelot.log(char) - char = string.byte(char) -- convert from char to char code - ocelot.log(tostring(char)) - if char < 0x2800 or char > 0x28ff then -- check if char is not a braille character - char = 0 -- yes +local display = {} +local chunksAffected = {} + +local renderBuffer = nil + +-- braille rendering + +function raster.units.charToBraille(x,y) + return x*2,y*4 +end + +function raster.units.brailleToChar(x,y) + return math.ceil(x/2),math.ceil(y/4) +end + +function raster.init(width, height, bgcolor) + -- NOTE: Width and height are in characters, not pixels in braille. + -- If the width and height are nil, the entire screen will be used. + if width==nil and height==nil then + width, height = gpu.getResolution() end - ocelot.log(tostring(char)) - local newi = (x%2)+(y%4)*2 -- original unmodified location in the char - if x%2==1 and (newi>1 and newi<6) then -- modify it - newi = newi+1 -- trust me bro this works - elseif x%2==0 and (newi>1 and newi<6) then - newi = newi-1 + + for i = 1, width*height do + chunksAffected[i] = true + end + raster.charWidth = width + raster.charHeight = height + + width, height = raster.units.charToBraille(width, height) + + bgcolor = bgcolor or raster.defaultBackgroundColor; + + for i = 1, width*height do + display[i] = bgcolor + end + raster.displayWidth = width + raster.displayHeight = height + + pcall(function() + renderBuffer = gpu.allocateBuffer() + end) +end + +function raster.set(x, y, color) + if x<1 or x>raster.displayWidth or y<1 or y>raster.displayHeight then + return false + end + + color = color or raster.defaultForegroundColor + local i = x+y*raster.displayWidth + display[i] = color + + local ci = math.floor((x-1)/2)+math.floor((y-1)/4)*raster.charWidth+1 + -- ocelot.log(x..","..y..":"..ci) + chunksAffected[ci] = true + + return true +end + +function raster.get(x, y) + local i = x+y*raster.displayWidth + return display[i] or 0 +end + +local function stats(arr) + local out = {} + for i=1,#arr do + local v = arr[i] + if out[v]==nil then + out[v]=1 + else + out[v] = out[v] + 1 + end + end + return out +end + +local function getKeys(t) + local keys = {} + for key, _ in pairs(t) do + table.insert(keys, key) + end + return keys +end + +local function colorDifference(a,b) + return ((a>>16)&255)-((b>>16)&255)+((a>>8)&255)-((b>>8)&255)+(a&255)-(b&255) +end + +local function limitTwoColors(arr) + local colors = getKeys(stats(arr)) + for i=1,#arr do + local v=arr[i] + if v==colors[1] then + arr[i]=0 + goto continue + elseif v==colors[2] then + arr[i]=1 + goto continue + else + --error("Pixel is not in the two colors (raster.lua:90)") + -- get closest color so atleast it kinda shows + if colorDifference(v,colors[1]) -dy then + err = err - dy + x1 = x1 + sx + end + + if e2 < dx then + err = err + dx + y1 = y1 + sy + end + end +end + +function raster.drawRect(x1,y1,x2,y2,col) + x1, y1, x2, y2 = math.floor(x1), math.floor(y1), math.floor(x2), math.floor(y2) + if x1 > x2 then x1, x2 = x2, x1 end + if y1 > y2 then y1, y2 = y2, y1 end + for x=x1,x2 do + raster.set(x,y1,col) + raster.set(x,y2,col) + end + for y=y1+1,y2-1 do + raster.set(x1,y,col) + raster.set(x2,y,col) + end +end + +function raster.fillRect(x1,y1,x2,y2,col) + x1, y1, x2, y2 = math.floor(x1), math.floor(y1), math.floor(x2), math.floor(y2) + if x1 > x2 then x1, x2 = x2, x1 end + if y1 > y2 then y1, y2 = y2, y1 end + for x=x1,x2 do + for y=y1,y2 do + raster.set(x,y,col) + end + end +end + +function raster.drawCircle(xc, yc, radius, color) + xc=math.floor(xc) + yc=math.floor(yc) + radius=math.floor(radius) + local x = 0 + local y = radius + local d = 3 - 2 * radius + + while y >= x do + -- Draw 8 symmetric points + raster.set(xc + x, yc + y, color) + raster.set(xc - x, yc + y, color) + raster.set(xc + x, yc - y, color) + raster.set(xc - x, yc - y, color) + raster.set(xc + y, yc + x, color) + raster.set(xc - y, yc + x, color) + raster.set(xc + y, yc - x, color) + raster.set(xc - y, yc - x, color) + + if d < 0 then + d = d + 4 * x + 6 + else + d = d + 4 * (x - y) + 10 + y = y - 1 + end + x = x + 1 + end +end + +function raster.drawEllipse(x1, y1, x2, y2, color) + if x1 > x2 then x1, x2 = x2, x1 end + if y1 > y2 then y1, y2 = y2, y1 end + + local xc = math.floor((x1 + x2) / 2) + local yc = math.floor((y1 + y2) / 2) + + local a = math.floor((x2 - x1) / 2) + local b = math.floor((y2 - y1) / 2) + + if a <= 0 or b <= 0 then + return + end + + if a == b then + raster.drawCircle(xc, yc, a, color) + return + end + + if a <= 1 and b <= 1 then + raster.set(xc, yc, color) + return + elseif a <= 1 then + for y = yc - b, yc + b do + raster.set(xc, y, color) + end + return + elseif b <= 1 then + for x = xc - a, xc + a do + raster.set(x, yc, color) + end + return + end + + local x = 0 + local y = b + local a2 = a * a + local b2 = b * b + + local d1 = b2 - (a2 * b) + (0.25 * a2) + local dx = 2 * b2 * x + local dy = 2 * a2 * y + + while dx < dy do + raster.set(xc + x, yc + y, color) + raster.set(xc - x, yc + y, color) + raster.set(xc + x, yc - y, color) + raster.set(xc - x, yc - y, color) + + if d1 < 0 then + x = x + 1 + dx = dx + (2 * b2) + d1 = d1 + dx + b2 + else + x = x + 1 + y = y - 1 + dx = dx + (2 * b2) + dy = dy - (2 * a2) + d1 = d1 + dx - dy + b2 + end + end + + local d2 = b2 * (x + 0.5) * (x + 0.5) + a2 * (y - 1) * (y - 1) - a2 * b2 + + while y >= 0 do + raster.set(xc + x, yc + y, color) + raster.set(xc - x, yc + y, color) + raster.set(xc + x, yc - y, color) + raster.set(xc - x, yc - y, color) + + if d2 > 0 then + y = y - 1 + dy = dy - (2 * a2) + d2 = d2 - dy + a2 + else + y = y - 1 + x = x + 1 + dx = dx + (2 * b2) + dy = dy - (2 * a2) + d2 = d2 + dx - dy + a2 + end + end +end + +function raster.fillCircle(x, y, r, color) + x, y = math.floor(x + 0.5), math.floor(y + 0.5) + r = math.floor(r + 0.5) + + if r <= 0 then return end + + local minX, maxX = x - r, x + r + local minY, maxY = y - r, y + r + + for py = minY, maxY do + for px = minX, maxX do + local dx, dy = px - x, py - y + local distSquared = dx*dx + dy*dy + + if distSquared <= r*r then + raster.set(px, py, color) + end + end + end +end + +function raster.fillEllipse(x1, y1, x2, y2, color) + local centerX = (x1 + x2) / 2 + local centerY = (y1 + y2) / 2 + + local a = math.abs(x2 - x1) / 2 + local b = math.abs(y2 - y1) / 2 + + centerX = math.floor(centerX + 0.5) + centerY = math.floor(centerY + 0.5) + a = math.floor(a + 0.5) + b = math.floor(b + 0.5) + + if a <= 0 or b <= 0 then return end + + if a == b then + raster.fillCircle(centerX, centerY, a, color) + return + end + + local minX = centerX - a + local maxX = centerX + a + local minY = centerY - b + local maxY = centerY + b + + for y = minY, maxY do + for x = minX, maxX do + local dx = x - centerX + local dy = y - centerY + local value = (dx*dx)/(a*a) + (dy*dy)/(b*b) + + if value <= 1 then + raster.set(x, y, color) + end + end end - ocelot.log(tostring(newi)) - newchar = char|(1<