commit 2f38abe0d47aedccbe94ee626ed865c3adfa3d23 Author: Kistaro Windrider Date: Fri Aug 4 16:38:36 2023 -0700 initial commit. diff --git a/README.md b/README.md new file mode 100644 index 0000000..764a57f --- /dev/null +++ b/README.md @@ -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. diff --git a/kistaro-compositor.lua b/kistaro-compositor.lua new file mode 100644 index 0000000..6dc544a --- /dev/null +++ b/kistaro-compositor.lua @@ -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 +-- +-- 000:0222220021111110212121102122211021121110211111100111110000000000 +-- 001:0bbbbb00b9999980b999b980b99bb980b9bbb980b99999800888880000000000 +-- 002:0555550056666670565566705655567056655670566666700777770000000000 +-- 003:0444440043333320433433204344432043434320433333200222220000000000 +-- 004:0ddddd00deeeeef0dededef0deedeef0dededef0deeeeef00fffff0000000000 +-- + +-- +-- 000:00000000ffffffff00000000ffffffff +-- 001:0123456789abcdeffedcba9876543210 +-- 002:0123456789abcdef0123456789abcdef +-- + +-- +-- 000:000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000304000000000 +-- + +-- +-- 000:100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +-- + +-- +-- 000:1a1c2c5d275db13e53ef7d57ffcd75a7f07038b76425717929366f3b5dc941a6f673eff7f4f4f4be69ce61309940205d +-- + diff --git a/kistaro-compositor.tic b/kistaro-compositor.tic new file mode 100644 index 0000000..e0a2869 Binary files /dev/null and b/kistaro-compositor.tic differ