honeylisp/editor/tileedit.fnl

118 lines
4 KiB
Fennel

(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