207 lines
8.3 KiB
Fennel
207 lines
8.3 KiB
Fennel
(local GraphicsEditView (require :editor.gfxedit))
|
|
(local style (require :core.style))
|
|
(local util (require :lib.util))
|
|
(local lume (require :lib.lume))
|
|
(local {: mouse-inside : activate : active? : checkbox : textfield : textbutton} (util.require :editor.imstate))
|
|
(local {: tilestrip-to-sprite} (util.require :editor.tiledraw))
|
|
(local {: encode-yx} (util.require :game.tiles))
|
|
|
|
(local MapEditView (GraphicsEditView:extend))
|
|
(local sprite-scale 3)
|
|
(local mapw 20)
|
|
(local maph 12)
|
|
(local tilew (* sprite-scale 14))
|
|
(local tileh (* sprite-scale 16))
|
|
|
|
(fn MapEditView.new [self filename]
|
|
(MapEditView.super.new self)
|
|
(set self.sprite-scale sprite-scale)
|
|
(set self.stripcache {})
|
|
(set self.mapfilename filename)
|
|
(self:reload))
|
|
|
|
; map is stored bottom-to-top
|
|
(fn imap-from-xy [mx my]
|
|
(+ mx -1 (* mapw (- maph my))))
|
|
|
|
(fn update-map [map mx my itile]
|
|
(local imap (imap-from-xy mx my))
|
|
(local enctile
|
|
(bit.bor
|
|
(bit.lshift (bit.band (- itile 1) 0x07) 5)
|
|
(bit.rshift (bit.band (- itile 1) 0xf8) 3)))
|
|
(..
|
|
(map:sub 1 imap)
|
|
(string.char enctile)
|
|
(map:sub (+ imap 2))))
|
|
|
|
(fn MapEditView.itile-from-xy [self mx my]
|
|
(local imap (+ (imap-from-xy mx my) 1))
|
|
(local enctile (string.byte (self.level.map:sub imap imap)))
|
|
(+ 1 (bit.bor
|
|
(bit.lshift (bit.band enctile 0x1f) 3)
|
|
(bit.rshift (bit.band enctile 0xe0) 5))))
|
|
|
|
(fn MapEditView.set-tile [self mx my itile]
|
|
(set self.level.map (update-map self.level.map mx my itile)))
|
|
|
|
(fn MapEditView.iobject-from-xy [self mx my ?iobj]
|
|
(local iobj (or ?iobj 1))
|
|
(local obj (. self.level.objects iobj))
|
|
(when obj
|
|
(if (and (= obj.x mx) (= obj.y my))
|
|
iobj
|
|
(self:iobject-from-xy mx my (+ iobj 1)))))
|
|
(fn MapEditView.object [self] (. self.level.objects self.iobject))
|
|
|
|
(fn move-object [objects iobjectsrc iobjectdst]
|
|
(each [_ object (pairs objects)]
|
|
(when (= object.link iobjectsrc)
|
|
(set object.link iobjectdst)))
|
|
(tset objects iobjectdst (. objects iobjectsrc))
|
|
(tset objects iobjectsrc nil)
|
|
(when (. objects (+ iobjectsrc 1))
|
|
(move-object objects (+ iobjectsrc 1) iobjectsrc)))
|
|
|
|
(fn MapEditView.linking-obj [self] (. self.level.objects self.iobject-linking))
|
|
(fn MapEditView.draw-link-line [self x y iobjectSrc color toMouse?]
|
|
(local objectSrc (. self.level.objects iobjectSrc))
|
|
(local objectDest (. self.level.objects objectSrc.link))
|
|
(local coord (fn [c m d] (+ c (* (- m 1) d) (/ d 2))))
|
|
(local xStart (coord x objectSrc.x tilew))
|
|
(local yStart (coord y objectSrc.y tileh))
|
|
(when (or toMouse? objectDest)
|
|
(local xEnd (if toMouse? (love.mouse.getX) (coord x objectDest.x tilew)))
|
|
(local yEnd (if toMouse? (love.mouse.getY) (coord y objectDest.y tileh)))
|
|
(love.graphics.setColor (table.unpack color))
|
|
(love.graphics.line xStart yStart xEnd yEnd)
|
|
(love.graphics.circle :line xEnd yEnd (/ tilew 5))
|
|
(love.graphics.setColor 1 1 1)))
|
|
|
|
(fn MapEditView.draw-tilestrip [self x y my]
|
|
; stripcache leaks but honestly who cares
|
|
(local tilestrip [])
|
|
(var stripid "")
|
|
(for [mx 1 mapw]
|
|
(local itile (self:itile-from-xy mx my))
|
|
(local tile (. self.tilecache.tiles itile :gfx))
|
|
(table.insert tilestrip tile)
|
|
(set stripid (.. stripid (string.char itile))))
|
|
(var sprite (. self.stripcache stripid))
|
|
(when (= sprite nil)
|
|
(set sprite (tilestrip-to-sprite tilestrip))
|
|
(tset self.stripcache stripid sprite))
|
|
(love.graphics.draw sprite x y 0 self.sprite-scale self.sprite-scale))
|
|
|
|
(fn MapEditView.draw-map-editor [self x y]
|
|
(activate self :map x y (* tilew mapw) (* tileh maph))
|
|
(var iobject-over nil)
|
|
(for [my 1 maph]
|
|
(local tiley (+ y (* (- my 1) tileh)))
|
|
(self:draw-tilestrip x tiley my)
|
|
(for [mx 1 mapw]
|
|
(local tilex (+ x (* (- mx 1) tilew)))
|
|
(local itile (self:itile-from-xy mx my))
|
|
(local iobject (self:iobject-from-xy mx my))
|
|
(when (= self.itile nil)
|
|
(each [_ player (ipairs [:jaye :neut])]
|
|
(match (. self.level player)
|
|
{:x mx :y my} (renderer.draw_text style.font player tilex tiley style.text)))
|
|
(love.graphics.setColor 1 1 1))
|
|
(when (and (not= iobject nil) (= self.itile nil))
|
|
(love.graphics.setColor 1 0 (if (and (= self.itile nil) (= iobject self.iobject)) 1 0))
|
|
(love.graphics.setLineWidth 3)
|
|
(love.graphics.rectangle :line tilex tiley tilew tileh)
|
|
(love.graphics.setColor 1 1 1))
|
|
(when (mouse-inside tilex tiley tilew tileh)
|
|
(when (not= iobject nil) (set iobject-over iobject))
|
|
(renderer.draw_text style.font (string.format "%x" (encode-yx {:x mx :y my})) tilex (+ tiley 15) style.text)
|
|
(love.graphics.setColor 1 1 1))
|
|
(when (and self.itile (active? self :map) (mouse-inside tilex tiley tilew tileh) (not= itile self.itile))
|
|
(self:set-tile mx my self.itile))
|
|
(when (and (= self.itile nil) (active? self :map) (mouse-inside tilex tiley tilew tileh))
|
|
(match self.imstate.left
|
|
:pressed (set self.iobject-linking iobject)
|
|
:released
|
|
(if (and (not= iobject nil) (= self.iobject-linking iobject))
|
|
(set self.iobject iobject)
|
|
|
|
(not= self.iobject-linking nil)
|
|
(tset (self:linking-obj) :link iobject)
|
|
|
|
(not= self.playerpos nil)
|
|
(do (tset self.level self.playerpos {:x mx :y my})
|
|
(set self.playerpos nil))
|
|
|
|
(= iobject nil)
|
|
(let [tile (self.tilecache:tile itile)]
|
|
(table.insert self.level.objects {:x mx :y my :func (or tile.word "")})
|
|
(set self.iobject (length self.level.objects))))))))
|
|
(when (= self.itile nil)
|
|
(for [iobject 1 (length self.level.objects)]
|
|
(self:draw-link-line x y iobject [0 0 1 0.3]))
|
|
(when (not= iobject-over nil) (self:draw-link-line x y iobject-over [0 0.5 1] false))
|
|
(when (not= self.iobject-linking nil)
|
|
(if (= self.imstate.left :released) (set self.iobject-linking nil)
|
|
(self:draw-link-line x y self.iobject-linking [0 1 0] true)))))
|
|
|
|
(fn MapEditView.draw-object-editor [self x y]
|
|
(var y y)
|
|
(local object (self:object))
|
|
(set (object.func y) (textfield self "Word" object.func x y 100 200))
|
|
(set (object.name y) (textfield self "Name" object.name x (+ y 5) 100 200))
|
|
(set (object.linkword y) (textfield self "Link word" object.linkword x (+ y 5) 100 200))
|
|
(match (if object.link (textbutton self "Unlink" x (+ y 5)))
|
|
(unlink yNext) (do (when unlink (set object.link nil))
|
|
(set y yNext)))
|
|
(when (textbutton self "Delete" x (+ y 40))
|
|
(move-object self.level.objects (+ self.iobject 1) self.iobject)
|
|
(set self.iobject nil)))
|
|
|
|
(fn MapEditView.reload [self]
|
|
(MapEditView.super.reload self)
|
|
(local (loaded level) (pcall #(util.readjson self.mapfilename)))
|
|
(set self.level
|
|
(match (and loaded (type level))
|
|
false {:map (string.rep "\0" (* mapw maph)) :objects []}
|
|
:string {:map (level:fromhex) :objects []}
|
|
:table (doto level (tset :map (level.map:fromhex))))))
|
|
|
|
(fn MapEditView.save [self]
|
|
(util.writejson self.mapfilename
|
|
(doto (lume.clone self.level)
|
|
(tset :map (self.level.map:tohex)))))
|
|
|
|
(fn MapEditView.draw [self]
|
|
(var x (+ self.position.x 10))
|
|
(var y (+ self.position.y 10))
|
|
(self:draw_background style.background)
|
|
(love.graphics.setColor 1 1 1 1)
|
|
(self:draw-map-editor x y)
|
|
(when self.iobject
|
|
(self:draw-object-editor (+ x (* tilew mapw) 10) y))
|
|
(set y (+ y (* tileh maph) 10))
|
|
(set self.level.tickword (textfield self "Tick word" self.level.tickword x y 100 200))
|
|
(set y (+ y 30))
|
|
(set self.level.moveword (textfield self "Move word" self.level.moveword x y 100 200))
|
|
(set y (+ y 30))
|
|
(set self.level.loadword (textfield self "Load word" self.level.loadword x y 100 200))
|
|
(set y (+ y 30))
|
|
(when (checkbox self "Edit objects" (= self.itile nil) x y)
|
|
(set self.itile nil)
|
|
(set self.playerpos nil))
|
|
(set y (+ y 30))
|
|
(each [_ player (ipairs [:jaye :neut])]
|
|
(when (checkbox self (.. "Position " player) (and (= self.itile nil) (= self.playerpos player)) x y)
|
|
(set self.itile nil)
|
|
(set self.playerpos player))
|
|
(set y (+ y 30)))
|
|
(when (checkbox self "Start with Gord" self.level.gord-following x y)
|
|
(set self.level.gord-following (not self.level.gord-following)))
|
|
(set y (+ y 30))
|
|
(self:draw-tile-selector x y (- self.size.x 20)))
|
|
|
|
(fn MapEditView.get_name [self] (.. "Map: " self.mapfilename))
|
|
|
|
MapEditView
|