Advertisement
Griffi

OpenComputers Graphics Lib

Sep 22nd, 2020 (edited)
266
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. local Graphics = {version=6}
  2. local gpu = require'component'.gpu
  3. local unicode = require'unicode'
  4.  
  5. local function expect(v,...)
  6.   local exp = {...}
  7.   local got = type(v)
  8.   local tx  = ''
  9.   local ok  = false
  10.   for i,v in ipairs(exp) do
  11.     tx=tx..v
  12.     if not(i>=#exp) then
  13.       tx=tx..' or '
  14.     end
  15.     if got==v then
  16.       ok=true
  17.     end
  18.   end
  19.   return ok , ('Expected '..tx..', but got '..got)
  20. end
  21. local function getIndex(x,y,w)
  22.   return w*(y-1)+x
  23. end
  24. local function getXY(i,w)
  25.   local x=(i-1)%w+1
  26.   return x,(i-x)/w+1
  27. end
  28. --local y=math.floor(i/(w+1))
  29. --return ((i-1)%w)+1,y+1  --OLD CODE
  30.  
  31. local function cn(v)
  32.   if type(v)=='number' then
  33.     return v
  34.   elseif v then
  35.     return 1
  36.   else
  37.     return 0
  38.   end
  39. end
  40. local function toBits(num,bits)
  41.   local t={}    
  42.   for b = bits, 1, -1 do
  43.     t[b] = math.fmod(num, 2)
  44.     num = math.floor((num - t[b]) / 2)
  45.   end
  46.   return t
  47. end
  48.  
  49.  
  50. local cstack={}
  51. local function pushColor()
  52.   table.insert(cstack,{gpu.getBackground(),gpu.getForeground()})
  53. end
  54. local function popColor()
  55.   local bg,fg=table.unpack(table.remove(cstack))
  56.   gpu.setBackground(bg)
  57.   gpu.setForeground(fg)
  58. end
  59.  
  60. function Graphics:getWidth()
  61.   assert(expect(self,'table'))
  62.   return self.w*2
  63. end
  64.  
  65. function Graphics:getHeight()
  66.   assert(expect(self,'table'))
  67.   return self.h*4
  68. end
  69.  
  70. function Graphics:getDimensions()
  71.   assert(expect(self,'table'))
  72.   return self:getWidth(),self:getHeight()
  73. end
  74.  
  75. function Graphics:_px(x,y,v)
  76.   assert(expect(self,'table'))
  77.   assert(expect(x,'number'))
  78.   assert(expect(y,'number'))
  79.   --assert(expect(v,'number','boolean','nil'))
  80.  
  81.   local w,h=self:getDimensions()
  82.   if not(x>w or x<1 or y>h or y<1)then
  83.     local ew,eh=2,4
  84.     local fx,fy=math.ceil(x/ew),math.ceil(y/eh)
  85.     local lx,ly=x-(fx-1)*ew,y-(fy-1)*eh
  86.     local iA,iB=getIndex(fx,fy,self.w),getIndex(ly,lx,eh)
  87.     if v~=nil then
  88.       local oldv=self.s[iA][iB]
  89.       local newv=cn(v)
  90.       if not(oldv==newv) then
  91.         self.s[iA][iB]=newv
  92.         self.u[iA]=true
  93.       end
  94.     else
  95.       return self.s[iA][iB]
  96.     end
  97.   end
  98. end
  99.  
  100. function Graphics:setPixel(x,y,v)
  101.   if v==nil then v=false end
  102.   self:_px(x,y,v)
  103. end
  104.  
  105. function Graphics:getPixel(x,y)
  106.   return self:_px(x,y,nil)
  107. end
  108.  
  109. function Graphics:fastLine(x,y,vx,vy,l,rem)
  110.   assert(expect(self,'table'))
  111.   assert(expect(x ,'number')) assert(expect(y ,'number'))
  112.   assert(expect(vx,'number')) assert(expect(vy,'number'))
  113.   assert(expect(l ,'number'))
  114.   for i=0,l do
  115.     self:setPixel(
  116.       math.ceil(x+i*vx),
  117.       math.ceil(y+i*vy),
  118.       not(rem)
  119.     )
  120.   end
  121. end
  122.  
  123. function Graphics:oldLine(x1,y1,x2,y2,rem)
  124.   assert(expect(self,'table'))
  125.   assert(expect(x1,'number')) assert(expect(x2,'number'))
  126.   assert(expect(y1,'number')) assert(expect(y2,'number'))
  127.   local a=math.atan2(x1-x2,y1-y2)
  128.   local vx,vy=-math.sin(a),-math.cos(a)
  129.   local l=math.sqrt((x2-x1)^2+(y2-y1)^2)
  130.   self:fastLine(x1,y1,vx,vy,l,rem)
  131. end
  132.  
  133. function Graphics:drawLine(x1,y1,x2,y2,rem)
  134.   assert(expect(self,'table'))
  135.   assert(expect(x1,'number')) assert(expect(x2,'number'))
  136.   assert(expect(y1,'number')) assert(expect(y2,'number'))
  137.   y1,y2=y1+1,y2+1
  138.   local dx = math.abs(x2-x1)
  139.     local dy = -math.abs(y2-y1)
  140.   local sx,sy
  141.     if x1<x2 then
  142.         sx=1  
  143.     else
  144.         sx=-1
  145.     end
  146.     if y1<y2 then
  147.         sy=1
  148.     else
  149.         sy=-1
  150.     end
  151.   local err = dx+dy
  152.   while true do
  153.     self:setPixel(x1,y1,not(rem))
  154.     if x1==x2 and y1==y2 then
  155.             break
  156.         end
  157.     local e2 = 2*err
  158.     if e2 >= dy then
  159.       err = err+dy
  160.       x1 = x1+sx
  161.     end
  162.     if e2 <= dx then
  163.       err = err+dx
  164.       y1 = y1+sy
  165.     end
  166.   end
  167. end
  168.  
  169. local function fixRect(x,y,w,h)
  170.   if w<0 then
  171.     x,w=x+w,math.abs(w)
  172.   end
  173.   if h<0 then
  174.     y,h=y+h,math.abs(h)
  175.   end
  176.   return x,y,w,h
  177. end
  178.  
  179. function Graphics:drawRect(x,y,w,h,fill,rem)
  180.   assert(expect(self,'table'))
  181.   assert(expect(x,'number')) assert(expect(y,'number'))
  182.   assert(expect(w,'number')) assert(expect(h,'number'))
  183.   x,y,w,h=fixRect(x,y,w,h)
  184.   if fill then
  185.     for i=0,w-1 do
  186.       for j=0,h-1 do
  187.         self:setPixel(x+i,y+j,not(rem))
  188.       end
  189.     end
  190.   else
  191.     self:fastLine(x,y,1,0,w-1,rem)--top
  192.     self:fastLine(x,y+h-1,1,0,w-1,rem)--bottom
  193.     self:fastLine(x,y,0,1,h-1,rem)--left
  194.     self:fastLine(x+w-1,y,0,1,h-1,rem)--right
  195.   end
  196. end
  197.  
  198. local Sprite={}
  199.  
  200. function Sprite:getWidth()
  201.   assert(expect(self,'table'))
  202.   return self.w
  203. end
  204.  
  205. function Sprite:getHeight()
  206.   assert(expect(self,'table'))
  207.   return self.h
  208. end
  209.  
  210. function Sprite:getDimensions()
  211.   assert(expect(self,'table'))
  212.   return Sprite:getWidth(),Sprite:getHeight()
  213. end
  214.  
  215. --TODO SPRITE SET PIX/GET PIX
  216.  
  217. function Graphics:newSprite(spriteData)
  218.   assert(expect(spriteData,'string'))
  219.   local t={
  220.     w=spriteData:byte(1),
  221.     h=spriteData:byte(2),
  222.     data={}
  223.   }
  224.   local d={spriteData:byte(3,#spriteData)}
  225.   for i=1,#d do
  226.     local b=toBits(d[i],8)
  227.     for j=1,#b do
  228.       if #t.data<=t.w*t.h then
  229.         t.data[#t.data+1]=(b[j]==1)
  230.       else
  231.         break
  232.       end
  233.     end
  234.   end
  235.   setmetatable(t,{__index=Sprite})
  236.   return t
  237. end
  238.  
  239. function Graphics:drawSprite(sprite,x,y)
  240.   assert(expect(self,'table'))
  241.   assert(expect(x,'number'))
  242.   assert(expect(y,'number'))
  243.   local px,py=0,0
  244.   local d=sprite.data
  245.   for i=1,#d do
  246.     self:setPixel(x+px,y+py,d[i])
  247.     px=px+1
  248.     if px>=sprite.w then
  249.       px=0
  250.       py=py+1
  251.     end
  252.   end
  253. end
  254.  
  255. function Graphics:_draw(i,x,y,shd)
  256.   x=x or 0
  257.   y=y or 0
  258.  
  259.   pushColor()
  260.   local v=self.s[i]
  261.   local xp,yp=getXY(i,self.w)
  262.   local sxp,syp=xp+x,yp+y
  263.   local gw,gh=gpu.getResolution()
  264.  
  265.   local r=false
  266.  
  267.   if sxp>=1 and syp>=1 and sxp<=gw and syp<=gh then
  268.     local schr,sfg,sbg=gpu.get(sxp,syp)
  269.     local chr=self:char(v)
  270.     local fg,bg=table.unpack(v.color)
  271.     if chr~=schr or sfg~=fg or sbg~=bg then --:gsub(' ','')
  272.       gpu.setForeground(fg)
  273.       gpu.setBackground(bg)
  274.       gpu.set(sxp,syp,chr)
  275.       r=true
  276.     end
  277.   end
  278.   popColor()
  279.   return r
  280. end
  281.  
  282. function Graphics:redraw(x,y,shd)
  283.   assert(expect(self,'table'))
  284.   assert(expect(x,'number','nil'))
  285.   assert(expect(y,'number','nil'))
  286.   assert(expect(shd,'function','nil'))
  287.   for i=1,self.w*self.h do --old
  288.     self:_draw(i,x,y,shd)
  289.   end
  290. end
  291.  
  292. function Graphics:draw(x,y)
  293.   assert(expect(self,'table'))
  294.   assert(expect(x,'number','nil'))
  295.   assert(expect(y,'number','nil'))
  296.   for i,v in next,self.u do
  297.     self:_draw(i,x,y)
  298.   end
  299.   self.u={}
  300. end
  301.  
  302. function Graphics:_reset(UPUSH)
  303.   self.u={}
  304.   for i=1,self.w*self.h do
  305.     if UPUSH and self:char(self.s[i])~=' ' then
  306.       self.u[i]=true
  307.     end
  308.     self.s[i]={
  309.       0,0,0,0,0,0,0,0,
  310.       color={0xFFFFFF,0x000000}
  311.     }
  312.   end
  313. end
  314.  
  315. function Graphics:reset()
  316.   assert(expect(self,'table'))
  317.   self:_reset(true)
  318. end
  319.  
  320. function Graphics:char(s)
  321.   assert(expect(s,'table'))
  322.   local n=s[1]+s[2]*2+s[3]*4+s[4]*64+s[5]*8+s[6]*16+s[7]*32+s[8]*128
  323.   --local n=tonumber(table.concat(s):reverse(),2)
  324.   if n>0 then
  325.     return unicode.char(10240+n)
  326.   else
  327.     return ' '
  328.   end
  329. end
  330.  
  331. function Graphics:new(w,h)
  332.   assert(expect(self,'table'))
  333.   assert(expect(w,'number','nil'))
  334.   assert(expect(h,'number','nil'))
  335.  
  336.   local gpuw,gpuh=gpu.getResolution()
  337.   w,h = w or gpuw, h or gpuh
  338.  
  339.   local g={
  340.     w=w,
  341.     h=h,
  342.     u={},
  343.     s={}
  344.   }
  345.   setmetatable(g,{__index=Graphics})
  346.   g:_reset()
  347.   return g
  348. end
  349.  
  350. return setmetatable(
  351.   Graphics,
  352.   {
  353.     __call=Graphics.new,
  354.     __newindex=function()end
  355.   }
  356. )
Advertisement
RAW Paste Data Copied
Advertisement