(local core (require :core)) (local command (require :core.command)) (local style (require :core.style)) (local View (require :core.view)) (local tile (require :game.tile)) (local lume (require :lib.lume)) (local TileView (View:extend)) (local pixel-size 24) (local xy-to-ibit []) (for [x 0 15] (tset xy-to-ibit x [])) (for [y 0 15] (tset (. xy-to-ibit 0) y (+ (* y 8) 7)) (for [ibit 0 6] (tset (. xy-to-ibit (+ ibit 1)) y (+ (* y 8) ibit)))) (for [y 0 15] (for [x 0 7] (tset (. xy-to-ibit (+ x 8)) y (+ (* (+ y 16) 8) x)))) (fn map-bitxy [x y] (when (and (>= x 0) (< x 16) (>= y 0) (< y 16)) (local ibit (. xy-to-ibit x y)) (values (math.floor (/ ibit 8)) (% ibit 8)))) (fn map-bit [x y] (local bitx (math.floor (/ x (+ 1 pixel-size)))) (local bity (math.floor (/ y (+ 1 pixel-size)))) (map-bitxy bitx bity)) (fn get-byte [tile ibyte] (: (tile:sub (+ ibyte 1) (+ ibyte 1)) :byte)) (fn get-bit [tile ibyte ibit] (not= 0 (bit.band (get-byte tile ibyte) (bit.lshift 1 ibit)))) (fn set-bit [tile ibyte ibit is-set] (local orval (bit.lshift 1 ibit)) (-> (get-byte tile ibyte) (bit.band (bit.bnot orval)) (bit.bor (if is-set orval 0)))) (fn set-tile-bit [tile ibyte ibit is-set] (.. (tile:sub 1 ibyte) (string.char (set-bit tile ibyte ibit is-set)) (tile:sub (+ ibyte 2)))) (fn draw-bit-color [bit x y] (local (bgcolor color) (if bit (values [20 207 253] [255 106 60]) (values [255 68 253] [20 245 60]))) (renderer.draw_rect x y pixel-size pixel-size bgcolor) (renderer.draw_rect (+ x 3) (+ y 3) (- pixel-size 6) (- pixel-size 6) color)) (fn draw-bit [bit x y even] (renderer.draw_rect x y pixel-size pixel-size (if bit [255 255 255] [0 0 0]))) (fn draw-tile [tile x y] (for [bitx 0 15] (for [bity 0 15] (local bit (get-bit tile (map-bitxy bitx bity))) (local (px py) (values (+ x (* bitx (+ pixel-size 1))) (+ y (* bity (+ pixel-size 1))))) (if (or (= bitx 0) (= bitx 15)) (draw-bit-color bit px py) (draw-bit bit px py (= (% bitx 2) 1)))))) (fn TileView.new [self] (self.super.new self) (set self.tiles (tile.loadtiles)) (set self.itile 1)) (fn TileView.tile [self] (or (. self.tiles self.itile) (string.rep "\0" 32))) (fn TileView.update-tile [self newtile] (tset self.tiles self.itile newtile)) (fn TileView.set-bit [self ibyte ibit bit-set] (set self.ibyte ibyte) (set self.ibit ibit) (set self.bit-set bit-set) (self:update-tile (set-tile-bit (self:tile) ibyte ibit bit-set)) true) (fn TileView.save [self] (tile.savetiles self.tiles)) (fn TileView.select-rel [self ditile] (local itile (+ self.itile ditile)) (when (>= itile 1) (set self.itile itile))) (fn TileView.draw [self] (self:draw_background style.background) (local (x y) (values (+ self.position.x 10) (+ self.position.y 10))) (local ybelow (draw-tile (self:tile) x y)) (local (byte bit) (map-bit (- (love.mouse.getX) x) (- (love.mouse.getY) y))) (when (and byte bit) (renderer.draw_text style.font (: "%d, %d" :format byte bit) x ybelow style.text))) (fn TileView.selected-bit [self mx my] (local (x y) (values (+ self.position.x 10) (+ self.position.y 10))) (values (map-bit (- mx x) (- my y)))) (fn TileView.on_mouse_pressed [self button mx my clicks] (if (self.super.on_mouse_pressed self button mx my clicks) true (do (local (ibyte ibit) (self:selected-bit mx my)) (if (not (and ibyte ibit)) false (self:set-bit ibyte ibit (not (get-bit (self:tile) ibyte ibit))))))) (fn TileView.on_mouse_moved [self mx my dx dy] (self.super.on_mouse_moved self mx my dx dy) (when (and self.ibyte self.ibit) (local (ibyte ibit) (self:selected-bit mx my)) (when (and ibyte ibit (or (not= ibyte self.ibyte) (not= ibit self.ibit))) (self:set-bit ibyte ibit self.bit-set)))) (fn TileView.on_mouse_released [self button x y] (self.super.on_mouse_released self button x y) (set self.ibyte nil) (set self.ibit nil) (set self.bit-set nil)) (fn TileView.get_name [self] "Tile Editor") TileView