sprite.lua 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403
  1. local s = {}
  2. local basexx = require("libraries.basexx")
  3. local img, mflag
  4. local imgw, imgh = 8, 8 --Image Width, Image Height
  5. local psize = 10 --Zoomed Pixel Size
  6. local imgdraw = {3+1,8+3+1,0,psize,psize} --Image Location
  7. local imgrecto = {3,3+8,psize*imgw+2,psize*imgh+2,1}
  8. local imggrid = {3+1,8+3+1,psize*imgw,psize*imgh,imgw,imgh}
  9. local sprsrecto = {1,128-(8+24+1),192,24+2, 1} --SpriteSheet Outline Rect
  10. local sprsdraw = {1,128-(8+24)} --SpriteSheet Draw Location
  11. local sprsgrid = {1,128-(8+24),192,8*3,24,3}
  12. local sprssrect = {0,128-(8+24+1),8+2,8+2,8} --SpriteSheet Select Rect
  13. local sprsidrect = {192-(36+13),128-(8+24+9),13,7,7,14}
  14. local sprsbanksY = 128 - (8+24+9)
  15. local sprsbanksgrid = {192-32,sprsbanksY+1,8*4,8,4,1}
  16. local sprsid = 1 --SpriteSheet Selected ID
  17. local sprsmflag = false
  18. local sprsbquads = {} --SpriteSheets 4 BanksQuads
  19. local sprsbank = 1 --Current Selected Bank
  20. for i = 1, 4 do
  21. sprsbquads[i] = api.SpriteMap:image():quad(1,(i*8*3-8*3)+1,_,3*8)
  22. end
  23. local temp = 0
  24. local palpsize = 13
  25. local palimg = api.Image(api.ImageData(4,4):map(function() temp = temp + 1 return temp end ))
  26. local palrecto = {192-(palpsize*4+3),8+3,palpsize*4+2,palpsize*4+2,1}
  27. local paldraw = {192-(palpsize*4+2),8+3+1,0,palpsize,palpsize}
  28. local palgrid = {192-(palpsize*4+2),8+3+1,palpsize*4,palpsize*4,4,4}
  29. local colsrectL = {192-(palpsize*4+3),8+3,palpsize+2,palpsize+2,8}
  30. local colsrectR = {192-(palpsize*4+2),8+3+1,palpsize,palpsize,1}
  31. local colsL = 0 --Color Select Left
  32. local colsR = 0 --Color Select Right
  33. local toolsdraw = {104, 192-102,sprsbanksY-2, 5,1, 1,1, api.EditorSheet} --Tools Draw Config
  34. local toolsgrid = {toolsdraw[2],toolsdraw[3], toolsdraw[4]*8,toolsdraw[5]*8, toolsdraw[4],toolsdraw[5]} --Tools Selection Grid
  35. local stool = 1
  36. local tbtimer = 0
  37. local tbtime = 0.1125
  38. local tbflag = false
  39. local transdraw = {109, 192-105,sprsbanksY-15, 5,1, 1,1, api.EditorSheet} --Transformations Draw Config
  40. local transgrid = {transdraw[2],transdraw[3], transdraw[4]*8, transdraw[5]*8, transdraw[4], transdraw[5]} --Transformations Selection Grid
  41. local strans --Selected Transformation
  42. local transtimer
  43. local transtime = 0.1125
  44. local infotimer = 0 --The info timer, 0 if no info.
  45. local infotext = "" --The info text to display
  46. local toolshold = {true,true,false,false,false} --Is it a button (Clone, Stamp, Delete) or a tool (Pencil, fill)
  47. local tools = {
  48. function(self,cx,cy,b) --Pencil (Default)
  49. local data = api.SpriteMap:data()
  50. local qx,qy = api.SpriteMap:rect(sprsid)
  51. local col = (b == 1 or api.isMDown(1)) and colsL or colsR
  52. data:setPixel(qx+cx-1,qy+cy-1,col)
  53. api.SpriteMap.img = data:image()
  54. end,
  55. function(self,cx,cy,b) --Fill (Bucket)
  56. local data = api.SpriteMap:data()
  57. local qx,qy = api.SpriteMap:rect(sprsid)
  58. local col = (b == 1 or api.isMDown(1)) and colsL or colsR
  59. local tofill = data:getPixel(qx+cx-1,qy+cy-1)
  60. if tofill == col then return end
  61. local function spixel(x,y) if x >= qx and x <= qx+7 and y >= qy and y <= qy+7 then data:setPixel(x,y,col) end end
  62. local function gpixel(x,y) if x >= qx and x <= qx+7 and y >= qy and y <= qy+7 then return data:getPixel(x,y) else return false end end
  63. local function mapPixel(x,y)
  64. if gpixel(x,y) and gpixel(x,y) == tofill then spixel(x,y) end
  65. if gpixel(x+1,y) and gpixel(x+1,y) == tofill then mapPixel(x+1,y) end
  66. if gpixel(x-1,y) and gpixel(x-1,y) == tofill then mapPixel(x-1,y) end
  67. if gpixel(x,y+1) and gpixel(x,y+1) == tofill then mapPixel(x,y+1) end
  68. if gpixel(x,y-1) and gpixel(x,y-1) == tofill then mapPixel(x,y-1) end
  69. end
  70. mapPixel(qx+cx-1,qy+cy-1)
  71. api.SpriteMap.img = data:image()
  72. end,
  73. function(self) --Clone (Copy)
  74. self:copy()
  75. end,
  76. function(self) --Stamp (Paste)
  77. self:paste()
  78. end,
  79. function(self) --Delete (Erase)
  80. local data = api.SpriteMap:data()
  81. local qx,qy = api.SpriteMap:rect(sprsid)
  82. for px = 0, 7 do for py = 0, 7 do
  83. data:setPixel(qx+px,qy+py,0)
  84. end end
  85. api.SpriteMap.img = data:image()
  86. infotimer, infotext = 2,"DELETED SPRITE "..sprsid s:redrawINFO()
  87. end
  88. }
  89. local function transform(tfunc)
  90. local current = api.SpriteMap:extract(sprsid)
  91. local new = api.ImageData(current:width(),current:height())
  92. current:map(function(x,y,c)
  93. local nx,ny,nc = tfunc(x,y,c,current:width(),current:height())
  94. new:setPixel(nx or x,ny or y,nc or c)
  95. end)
  96. local x,y = api.SpriteMap:rect(sprsid)
  97. local data = api.SpriteMap:data()
  98. data:paste(new,x,y)
  99. api.SpriteMap.img = data:image()
  100. end
  101. local transformations = {
  102. function(x,y,c,w,h) return h+1-y,x end, --Rotate right
  103. function(x,y,c,w,h) return y, w+1-x end, --Rotate left
  104. function(x,y,c,w,h) return w+1-x,y end, --Flip horizental
  105. function(x,y,c,w,h) return x,h+1-y end, --Flip vertical
  106. function(x,y,c,w,h) return w+1-x,h+1-y end --Flip horizentaly + verticaly
  107. }
  108. function s:_switch()
  109. img = api.ImageData(imgw,imgh):map(function() return 0 end)
  110. mflag = false
  111. end
  112. function s:export(path)
  113. local FileData = api.SpriteMap:data():export(path)
  114. if not path then
  115. return basexx.to_base64(FileData:getString())
  116. end
  117. end
  118. function s:copy()
  119. api.setclip(basexx.to_base64(api.SpriteMap:extract(sprsid):export():getString()))
  120. infotimer = 2 --Show info for 2 seconds
  121. infotext = "COPIED SPRITE "..sprsid
  122. self:redrawINFO()
  123. end
  124. function s:paste()
  125. local ok, err = pcall(function()
  126. local imd = api.ImageData(api.getclip() or "")
  127. local dx,dy,dw,dh = api.SpriteMap:rect(sprsid)
  128. local sheetdata = api.SpriteMap:data()
  129. sheetdata:paste(imd,dx,dy,1,1,dw,dh)
  130. api.SpriteMap.img = sheetdata:image()
  131. self:_redraw()
  132. end)
  133. if not ok then
  134. infotimer = 5 --Display error msg for 5 seconds
  135. infotext = "PASTE ERR: "..(err or "nil")
  136. else
  137. infotimer = 2 --Display info for 2 seconds
  138. infotext = "PASTED TO SPRITE "..sprsid
  139. end
  140. self:redrawINFO()
  141. end
  142. function s:load(path)
  143. if path then
  144. api.SpriteMap = api.SpriteSheet(api.Image("/"..path..".png"),24,12)
  145. else
  146. api.SpriteMap = api.SpriteSheet(api.ImageData(24*8,12*8):image(),24,12)
  147. end
  148. end
  149. function s:redrawCP() --Redraw color pallete
  150. api.rect_line(unpack(palrecto))
  151. palimg:draw(unpack(paldraw))
  152. api.rect_line(unpack(colsrectR))
  153. api.rect_line(unpack(colsrectL))
  154. end
  155. function s:redrawSPRS()
  156. api.rect(unpack(sprsrecto))
  157. api.SpriteMap:image():draw(sprsdraw[1],sprsdraw[2],sprsdraw[3],sprsdraw[4],sprsdraw[5],sprsbquads[sprsbank])
  158. api.rect_line(unpack(sprssrect))
  159. api.rect(unpack(sprsidrect))
  160. api.color(sprsidrect[6])
  161. local id = sprsid if id < 10 then id = "00"..id elseif id < 100 then id = "0"..id end
  162. api.print(id,sprsidrect[1]+1,sprsidrect[2]+1)
  163. api.SpriteGroup(97,192-32,sprsbanksY,4,1,1,1,api.EditorSheet)
  164. api.EditorSheet:draw(sprsbank+72,192-(40-sprsbank*8),sprsbanksY)
  165. end
  166. function s:redrawSPR()
  167. api.rect(unpack(imgrecto))
  168. api.SpriteMap:image():draw(imgdraw[1],imgdraw[2],imgdraw[3],imgdraw[4],imgdraw[5],api.SpriteMap:quad(sprsid))
  169. api.rect(sprsidrect[1]-9,sprsidrect[2]-1,8,8,1)
  170. api.SpriteMap:image():draw(sprsidrect[1]-9,sprsidrect[2]-1,0,1,1,api.SpriteMap:quad(sprsid))
  171. end
  172. function s:redrawTOOLS()
  173. --Tools
  174. api.SpriteGroup(unpack(toolsdraw))
  175. api.Sprite((toolsdraw[1]+(stool-1))-24,toolsdraw[2]+(stool-1)*8,toolsdraw[3],0,toolsdraw[6],toolsdraw[7],api.EditorSheet)
  176. --Transformations
  177. api.SpriteGroup(unpack(transdraw))
  178. if strans then api.Sprite((transdraw[1]+(strans-1))-24,transdraw[2]+(strans-1)*8,transdraw[3],0,transdraw[6],transdraw[7],api.EditorSheet) end
  179. end
  180. function s:redrawFLAG()
  181. api.SpriteGroup(126,192-64,sprsbanksY-18,8,1,1,1,api.EditorSheet)
  182. api.SpriteGroup(126,192-64,sprsbanksY-10,8,1,1,1,api.EditorSheet)
  183. end
  184. function s:redrawINFO()
  185. api.rect(1,128-7,192,8,10)
  186. if infotimer > 0 then
  187. api.color(5)
  188. api.print(infotext or "",2,128-5)
  189. end
  190. end
  191. function s:_redraw()
  192. self:redrawCP()
  193. self:redrawSPR()
  194. self:redrawSPRS()
  195. self:redrawFLAG()
  196. self:redrawTOOLS()
  197. end
  198. function s:_update(dt)
  199. if tbflag then
  200. tbtimer = tbtimer + dt
  201. if tbtime <= tbtimer then
  202. stool = tbflag
  203. tbflag = false
  204. self:redrawTOOLS()
  205. end
  206. end
  207. if transtimer then
  208. transtimer = transtimer + dt
  209. if transtimer > transtime then
  210. transtimer, strans = nil, nil
  211. self:redrawTOOLS()
  212. end
  213. end
  214. if infotimer > 0 then
  215. infotimer = infotimer - dt
  216. if infotimer < 0 then
  217. infotimer = 0
  218. self:redrawINFO()
  219. end
  220. end
  221. end
  222. function s:_mpress(x,y,b,it)
  223. --if api.isInRect(x,y,{1,1,192,8}) then api.SpriteMap:data():export("editorsheet") end
  224. --Pallete Color Selection
  225. local cx, cy = api.whereInGrid(x,y,palgrid)
  226. if cx then
  227. if b == 1 then
  228. colsL = (cy-1)*4+cx if colsL == 1 then colsL = 0 end
  229. local cx, cy = cx-1, cy-1
  230. colsrectL[1] = 192-(palpsize*4+3)+palpsize*cx
  231. colsrectL[2] = 8+3+palpsize*cy
  232. elseif b == 2 then
  233. colsR = (cy-1)*4+cx if colsR == 1 then colsR = 0 end
  234. local cx, cy = cx-1, cy-1
  235. colsrectR[1] = 192-(palpsize*4+2)+palpsize*cx
  236. colsrectR[2] = 8+3+1+palpsize*cy
  237. end
  238. self:redrawCP()
  239. end
  240. --Bank selection
  241. local cx = api.whereInGrid(x,y,sprsbanksgrid)
  242. if cx then
  243. sprsbank = cx
  244. local idbank = api.floor((sprsid-1)/(24*3))+1
  245. if idbank > sprsbank then sprsid = sprsid-(idbank-sprsbank)*24*3 elseif sprsbank > idbank then sprsid = sprsid+(sprsbank-idbank)*24*3 end
  246. self:redrawSPRS() self:redrawSPR()
  247. end
  248. --Sprite Selection
  249. local cx, cy = api.whereInGrid(x,y,sprsgrid)
  250. if cx then
  251. sprsid = (cy-1)*24+cx+(sprsbank*24*3-24*3)
  252. local cx, cy = cx-1, cy-1
  253. sprssrect[1] = cx*8
  254. sprssrect[2] = 128-(8+24+1)+cy*8
  255. self:redrawSPRS() self:redrawSPR() sprsmflag = true
  256. end
  257. --Tool Selection
  258. local cx, cy = api.whereInGrid(x,y,toolsgrid)
  259. if cx then
  260. if toolshold[cx] then
  261. stool = cx
  262. self:redrawTOOLS()
  263. self:redrawSPRS() self:redrawSPR()
  264. else
  265. tools[cx](self)
  266. tbflag, tbtimer = stool, 0
  267. stool = cx
  268. self:redrawSPRS() self:redrawSPR() self:redrawTOOLS()
  269. end
  270. end
  271. --Transformation Selection
  272. local cx, cy = api.whereInGrid(x,y,transgrid)
  273. if cx and transformations[cx] then
  274. transform(transformations[cx]) transtimer, strans = 0, cx
  275. self:redrawSPRS() self:redrawSPR() self:redrawTOOLS()
  276. end
  277. --Image Drawing
  278. local cx, cy = api.whereInGrid(x,y,imggrid)
  279. if cx then
  280. if not it then mflag = true end
  281. tools[stool](self,cx,cy,b)
  282. self:redrawSPR() self:redrawSPRS()
  283. end
  284. end
  285. function s:_mmove(x,y,dx,dy,it,iw)
  286. if iw then return end
  287. --Image Drawing
  288. if (not it and mflag) or it then
  289. local cx, cy = api.whereInGrid(x,y,imggrid)
  290. if cx then
  291. tools[stool](self,cx,cy)
  292. self:redrawSPR() self:redrawSPRS()
  293. end
  294. end
  295. --Sprite Selection
  296. if (not it and sprsmflag) or it then
  297. local cx, cy = api.whereInGrid(x,y,sprsgrid)
  298. if cx then
  299. sprsid = (cy-1)*24+cx+(sprsbank*24*3-24*3)
  300. local cx, cy = cx-1, cy-1
  301. sprssrect[1] = cx*8
  302. sprssrect[2] = 128-(8+24+1)+cy*8
  303. self:redrawSPRS() self:redrawSPR()
  304. end
  305. end
  306. end
  307. function s:_mrelease(x,y,b,it)
  308. --Image Drawing
  309. if (not it and mflag) or it then
  310. local cx, cy = api.whereInGrid(x,y,imggrid)
  311. if cx then
  312. tools[stool](self,cx,cy,b)
  313. self:redrawSPR() self:redrawSPRS()
  314. end
  315. end
  316. mflag = false
  317. --Sprite Selection
  318. if (not it and sprsmflag) or it then
  319. local cx, cy = api.whereInGrid(x,y,sprsgrid)
  320. if cx then
  321. sprsid = (cy-1)*24+cx+(sprsbank*24*3-24*3)
  322. local cx, cy = cx-1, cy-1
  323. sprssrect[1] = cx*8
  324. sprssrect[2] = 128-(8+24+1)+cy*8
  325. self:redrawSPRS() self:redrawSPR()
  326. end
  327. end
  328. sprsmflag = false
  329. end
  330. local bank = function(bank)
  331. return function()
  332. local idbank = api.floor((sprsid-1)/(24*3))+1
  333. sprsbank = bank
  334. if idbank > sprsbank then
  335. sprsid = sprsid-(idbank-sprsbank)*24*3
  336. elseif sprsbank > idbank then
  337. sprsid = sprsid+(sprsbank-idbank)*24*3
  338. end
  339. s:redrawSPRS() s:redrawSPR()
  340. end
  341. end
  342. s.keymap = {
  343. ["ctrl-c"] = s.copy,
  344. ["ctrl-v"] = s.paste,
  345. ["1"] = bank(1), ["2"] = bank(2), ["3"] = bank(3), ["4"] = bank(4),
  346. ["z"] = function() stool=1 s:redrawTOOLS() end,
  347. ["x"] = function() stool=2 s:redrawTOOLS() end,
  348. ["delete"] = function() tools[5](s) s:redrawSPRS() s:redrawSPR() end,
  349. }
  350. return s