initial commit.
This commit is contained in:
		
							
								
								
									
										3
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| # Kistaro's tic-80 compositor | ||||
|  | ||||
| TIC-80 port of my Pico-8 compositor, including a lot of Pico-8 camera and clip behaviors that aren't available in TIC-80.  | ||||
							
								
								
									
										255
									
								
								kistaro-compositor.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										255
									
								
								kistaro-compositor.lua
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,255 @@ | ||||
| -- title:   kistaro-compositor | ||||
| -- author:  Kistaro Windrider (kistaro@gmail.com) | ||||
| -- desc:    Rendering compositor library. Includes Pico-8 camera features. | ||||
| -- site:    https://dragon.style/@kistaro | ||||
| -- license: MIT License | ||||
| -- version: 0.1 | ||||
| -- script:  lua | ||||
|  | ||||
|  | ||||
| function BOOT() | ||||
| end | ||||
|  | ||||
| function TIC() | ||||
| end | ||||
|  | ||||
| --stdlib-- | ||||
|  | ||||
| -- generate standard "overlay" | ||||
| -- constructor for type tt. | ||||
| -- if more is defined, generated | ||||
| -- new calls more(ret) after ret is | ||||
| -- definitely not nil, before calling | ||||
| -- setmetatable. Use to initialize | ||||
| -- mutable items. | ||||
| function MkNew(tt, more) | ||||
| 	local mt = {__index=tt} | ||||
| 	-- check "more" only once ever | ||||
| 	if more then | ||||
| 	 tt.new = function(ret) | ||||
| 		 ret = ret or {} | ||||
| 			more(ret) | ||||
| 			setmetatable(ret, mt) | ||||
| 			return ret | ||||
| 		end | ||||
| 	else | ||||
| 	 tt.new = function(ret) | ||||
| 	 	ret = ret or {} | ||||
| 	 	setmetatable(ret, mt) | ||||
| 	  return ret | ||||
| 		end | ||||
| 	end | ||||
| end | ||||
|  | ||||
| --Window compositor-- | ||||
|  | ||||
| CamCtl = { | ||||
|  XOff = 0, | ||||
|  YOff = 0, | ||||
|  XAbsClip = 0, | ||||
|  YAbsClip = 0, | ||||
|  W = 240, | ||||
|  H = 136, | ||||
|  OriginStack = {}, | ||||
|  ClipStack = {}, | ||||
| } | ||||
|  | ||||
| -- Overwrite current camera origin. | ||||
| -- (0, 0) is now this pixel coordinate. | ||||
| function CamCtl:SetAbsOrigin(x, y) | ||||
|  self.XOff, self.YOff = x, y | ||||
| end | ||||
|  | ||||
| -- Push current camera origin onto | ||||
| -- the history stack and set the | ||||
| -- new origin. | ||||
| function CamCtl:PushAbsOrigin(x, y) | ||||
|  table.insert(self.OriginStack, {self.XOff, self.YOff}) | ||||
|  self.XOff, self.YOff = x, y | ||||
| end | ||||
|  | ||||
| function CamCtl:SetRelOrigin(x, y) | ||||
|  self.XOff = self.XOff + x | ||||
|  self.YOff = self.Yoff + y | ||||
| end | ||||
|  | ||||
| function CamCtl:PushRelOrigin(x, y) | ||||
|  table.insert(self.OriginStack, {self.XOff, self.YOff}) | ||||
|  self.XOff = self.XOff + x | ||||
|  self.YOff = self.YOff + Y | ||||
| end | ||||
|  | ||||
| function CamCtl:SetAbsCam(x, y) | ||||
|  self.XOff, self.YOff = -x, -y | ||||
| end | ||||
|  | ||||
| function CamCtl:PushAbsCam(x, y) | ||||
|  table.insert(self.OriginStack, {self.XOff, self.YOff}) | ||||
|  self.XOff, self.YOff = -x, -y | ||||
| end | ||||
|  | ||||
| function CamCtl:SetRelCam(x, y) | ||||
|  self.XOff = self.XOff - x | ||||
|  self.YOff = self.YOff - y | ||||
| end | ||||
|  | ||||
| function CamCtl:PushRelCam(x, y) | ||||
|  table.insert(self.OriginStack, {self.XOff, self.YOff}) | ||||
|  self.XOff = self.XOff - x | ||||
|  self.YOff = self.YOff - y | ||||
| end  | ||||
|  | ||||
| function CamCtl:PopOrigin() | ||||
|  if #self.OriginStack == 0 then | ||||
|   self.XOff, self.YOff = 0, 0 | ||||
|   return | ||||
|  end | ||||
|  self.XOff, self.YOff = unpack(table.Remove(self.OriginStack)) | ||||
| end | ||||
| CamCtl.PopCam = CamCtl.PopOrigin | ||||
|  | ||||
| function CamCtl:SetNewClip(x, y, w, h) | ||||
|  if x then | ||||
|   self.XAbsClip = self.XOff + x | ||||
|   self.YAbsClip = self.YOff + y | ||||
|   self.W, self.H = w, h | ||||
|   clip(self.XAbsClip, self.YAbsClip, self.W, self.H) | ||||
|   return | ||||
|  end | ||||
|  self.XAbsClip, self.YAbsClip, self.W, self.H = 0,0,240,136 | ||||
|  clip() | ||||
| end | ||||
|  | ||||
| function CamCtl:PushNewClip(x, y, w, h) | ||||
|  table.insert(self.ClipStack, {self.XAbsClip, self.YAbsClip, self.W, self.H} | ||||
|  self:SetNewClip(x, y, w, h) | ||||
| end | ||||
|  | ||||
| function CamCtl:SetReClip(x,y,w,h) | ||||
|  if not x then | ||||
|   return | ||||
|  end | ||||
|   | ||||
|  x = x + self.XOff | ||||
|  local x2 = math.min(x + w, self.XAbsClip + self.W) | ||||
|  self.XAbsClip = math.max(x, self.XAbsClip) | ||||
|  self.W = max(0, x2 - self.XAbsClip) | ||||
|   | ||||
|  y = y + self.YOff | ||||
|  local y2 = math.min(y+h, self.YAbsClip + self.H) | ||||
|  self.YAbsClip = math.max(y, self.YAbsClip) | ||||
|  self.H = max(0, y2 - self.YAbsClip) | ||||
|  | ||||
|  clip(self.XAbsClip, self.YAbsClip, self.W, self.H) | ||||
| end | ||||
|  | ||||
| function CamCtl:PushReClip(x,y,w,h) | ||||
|  table.insert(self.ClipStack, {self.XAbsClip, self.YAbsClip, self.W, self.H} | ||||
|  self.SetReClip(x,y,w,h) | ||||
| end | ||||
|  | ||||
| function CamCtl:PopClip() | ||||
|  if #self.ClipStack == 0 then | ||||
|   self.XAbsClip, self.YAbsClip, self.W, self.H = 0,0,240,136 | ||||
|   clip() | ||||
|   return | ||||
|  end | ||||
|  local x,y,w,h = unpack(table.remove(self.ClipStack))) | ||||
|  self.XAbsClip, self.YAbsClip, self.W, self.H = x,y,w,h | ||||
|  clip(x,y,w,h) | ||||
| end | ||||
| -- Install | ||||
| -- (swizzle all drawing functions!) | ||||
|  | ||||
| function CamCtl:Install() | ||||
|  local adjust_leading_2 = { | ||||
|   "circ", "circb", | ||||
|   "elli", "ellib", | ||||
|   "pix", | ||||
|   "rect", "rectb", | ||||
|  } | ||||
|  for _, fn in ipairs(adjust_leading_2) do | ||||
|   local f_orig = _G[fn] | ||||
|   _G[fn] = function(x, y, ...) | ||||
|    return f_orig(x + self.XOff, y + self.YOff, ...) | ||||
|   end | ||||
|  end | ||||
|   | ||||
|  local keep_first_adjust_2_opt = { | ||||
|   "spr", "font", "print" | ||||
|  } | ||||
|  for _, fn in ipairs(keep_first_adjust_2_opt) do | ||||
|   local f_orig = _G[fn] | ||||
|   _G[fn] = function(v, x, y, ...) | ||||
|    if x then | ||||
|     x = x + self.XOff | ||||
|    end | ||||
|    if y then | ||||
|     y = y + self.YOff | ||||
|    end | ||||
|    return f_orig(v, x, y, ...) | ||||
|   end | ||||
|  end | ||||
|  | ||||
|  local tri_family = {"tri", "trib", "textri"} | ||||
|   | ||||
|  for _, fn in ipairs(tri_family) do | ||||
|   local f_orig = _G[fn] | ||||
|   _G[fn] = function(x1, y1, x2, y2, x3, y3, ...) | ||||
|    return f_orig( | ||||
|     x1 + self.XOff, y1 + self.YOff, | ||||
|     x2 + self.XOff, y2 + self.YOff, | ||||
|     x3 + self.XOff, y3 + self.YOff, | ||||
|     ... | ||||
|    ) | ||||
|   end | ||||
|  end | ||||
|   | ||||
|  local map_orig = map | ||||
|  map = function(mx, my, w, h, sx, sy, ...) | ||||
|   XXX(kistaro): implement! | ||||
|   -- if called with no args, calculate new map | ||||
|   -- coordinates, clipping at 0, to respect | ||||
|   -- camera movement! this will require full tile | ||||
|   -- movement to be reflected in mx/my, w and h to | ||||
|   -- stay 30 x 17 unless they go to 31 x 18 for | ||||
|   -- partial tiles at edges, and sx and sy to become | ||||
|   -- offsets. If sx and sy are provided, do the | ||||
|   -- obvious thing instead, which is much easier. | ||||
|  end | ||||
|   | ||||
|  local line_orig = line | ||||
|  line = function(x0, y0, x1, y1, color) | ||||
|   return line_orig( | ||||
|    x0 + self.XOff, y0 + self.YOff, | ||||
|    x1 + self.XOff, y1 + self.YOff, | ||||
|    color | ||||
|   ) | ||||
|  end | ||||
| end | ||||
| -- <SPRITES> | ||||
| -- 000:0222220021111110212121102122211021121110211111100111110000000000 | ||||
| -- 001:0bbbbb00b9999980b999b980b99bb980b9bbb980b99999800888880000000000 | ||||
| -- 002:0555550056666670565566705655567056655670566666700777770000000000 | ||||
| -- 003:0444440043333320433433204344432043434320433333200222220000000000 | ||||
| -- 004:0ddddd00deeeeef0dededef0deedeef0dededef0deeeeef00fffff0000000000 | ||||
| -- </SPRITES> | ||||
|  | ||||
| -- <WAVES> | ||||
| -- 000:00000000ffffffff00000000ffffffff | ||||
| -- 001:0123456789abcdeffedcba9876543210 | ||||
| -- 002:0123456789abcdef0123456789abcdef | ||||
| -- </WAVES> | ||||
|  | ||||
| -- <SFX> | ||||
| -- 000:000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000304000000000 | ||||
| -- </SFX> | ||||
|  | ||||
| -- <TRACKS> | ||||
| -- 000:100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 | ||||
| -- </TRACKS> | ||||
|  | ||||
| -- <PALETTE> | ||||
| -- 000:1a1c2c5d275db13e53ef7d57ffcd75a7f07038b76425717929366f3b5dc941a6f673eff7f4f4f4be69ce61309940205d | ||||
| -- </PALETTE> | ||||
|  | ||||
							
								
								
									
										
											BIN
										
									
								
								kistaro-compositor.tic
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								kistaro-compositor.tic
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
		Reference in New Issue
	
	Block a user