add flags to tile editor, objects to map editor, textbox to imgui
This commit is contained in:
parent
dbc618acaa
commit
eb1ca6078b
|
@ -117,15 +117,13 @@
|
||||||
(fn parse-dats [block dats]
|
(fn parse-dats [block dats]
|
||||||
(each [_ dat (ipairs dats)]
|
(each [_ dat (ipairs dats)]
|
||||||
(if (= (type dat) "string")
|
(if (= (type dat) "string")
|
||||||
(do
|
(do (tset block.symbols dat (+ (length block.pdats) 1))
|
||||||
(tset block.symbols dat (+ (length block.pdats) 1))
|
|
||||||
(when (= (dat:sub 1 2) "G-")
|
(when (= (dat:sub 1 2) "G-")
|
||||||
(tset block.globals dat true)))
|
(tset block.globals dat true)))
|
||||||
(let [opcode (. dat 1)
|
(let [opcode (. dat 1)
|
||||||
parser (. dat-parser opcode)
|
parser (. dat-parser opcode)
|
||||||
pdat
|
pdat
|
||||||
(if
|
(if parser (parser dat block)
|
||||||
parser (parser dat block)
|
|
||||||
(. opcodes opcode) (dat-parser.op dat)
|
(. opcodes opcode) (dat-parser.op dat)
|
||||||
(error (.. "Unrecognized opcode " (fv opcode))))]
|
(error (.. "Unrecognized opcode " (fv opcode))))]
|
||||||
(table.insert block.pdats pdat)
|
(table.insert block.pdats pdat)
|
||||||
|
|
|
@ -15,21 +15,25 @@
|
||||||
(set self.itile 1)
|
(set self.itile 1)
|
||||||
(attach-imstate self))
|
(attach-imstate self))
|
||||||
|
|
||||||
|
(fn GraphicsEditView.reload [self]
|
||||||
|
(self.tilecache:load (tiles.loadtiles)))
|
||||||
|
|
||||||
(fn GraphicsEditView.select-rel [self ditile]
|
(fn GraphicsEditView.select-rel [self ditile]
|
||||||
|
(when self.itile
|
||||||
(local itile (+ self.itile ditile))
|
(local itile (+ self.itile ditile))
|
||||||
(when (>= itile 1) (set self.itile itile)))
|
(when (>= itile 1) (set self.itile itile))))
|
||||||
|
|
||||||
(fn GraphicsEditView.draw-sprite [self x y itile]
|
(fn GraphicsEditView.draw-sprite [self x y itile]
|
||||||
(love.graphics.draw (self.tilecache:sprite itile) x y 0 sprite-scale sprite-scale))
|
(love.graphics.draw (self.tilecache:sprite itile) x y 0 self.sprite-scale self.sprite-scale))
|
||||||
|
|
||||||
(fn GraphicsEditView.draw-tile-selector [self x y w]
|
(fn GraphicsEditView.draw-tile-selector [self x y w]
|
||||||
(var tilex x)
|
(var tilex x)
|
||||||
(var tiley y)
|
(var tiley y)
|
||||||
(local tile-size (* 16 sprite-scale))
|
(local tile-size (* 16 self.sprite-scale))
|
||||||
(for [itile 1 (length self.tilecache.tiles)]
|
(for [itile 1 (length self.tilecache.tiles)]
|
||||||
(self:draw-sprite tilex tiley itile)
|
(self:draw-sprite tilex tiley itile)
|
||||||
(when (= itile self.itile)
|
(when (= itile self.itile)
|
||||||
(love.graphics.rectangle :line (- tilex 2) (- tiley 2) (+ (* 14 sprite-scale) 4) (+ tile-size 4)))
|
(love.graphics.rectangle :line (- tilex 2) (- tiley 2) (+ (* 14 self.sprite-scale) 4) (+ tile-size 4)))
|
||||||
(when (button self [:tile itile] tilex tiley tile-size tile-size)
|
(when (button self [:tile itile] tilex tiley tile-size tile-size)
|
||||||
(set self.itile itile))
|
(set self.itile itile))
|
||||||
(set tilex (+ tilex tile-size))
|
(set tilex (+ tilex tile-size))
|
||||||
|
|
|
@ -1,3 +1,9 @@
|
||||||
|
(local core (require :core))
|
||||||
|
(local command (require :core.command))
|
||||||
|
(local keymap (require :core.keymap))
|
||||||
|
(local style (require :core.style))
|
||||||
|
(local lume (require :lib.lume))
|
||||||
|
|
||||||
(fn attach-imstate [view]
|
(fn attach-imstate [view]
|
||||||
(set view.imstate {})
|
(set view.imstate {})
|
||||||
(fn view.on_mouse_pressed [self button x y clicks]
|
(fn view.on_mouse_pressed [self button x y clicks]
|
||||||
|
@ -6,8 +12,19 @@
|
||||||
(fn view.on_mouse_released [self button x y]
|
(fn view.on_mouse_released [self button x y]
|
||||||
(tset self.imstate button :released)
|
(tset self.imstate button :released)
|
||||||
(self.__index.on_mouse_released self button x y))
|
(self.__index.on_mouse_released self button x y))
|
||||||
|
(fn view.on_key_pressed [self key]
|
||||||
|
(when (= self.imstate.keys nil)
|
||||||
|
(set self.imstate.keys []))
|
||||||
|
(table.insert self.imstate.keys key))
|
||||||
|
(fn view.on_text_input [self text]
|
||||||
|
(set self.imstate.text (.. (or self.imstate.text "") text))
|
||||||
|
(self.__index.on_text_input self text))
|
||||||
(fn view.draw [self]
|
(fn view.draw [self]
|
||||||
|
(set self.cursor nil)
|
||||||
(self.__index.draw self)
|
(self.__index.draw self)
|
||||||
|
(when (= self.cursor nil) (set self.cursor :arrow))
|
||||||
|
(set self.imstate.keys nil)
|
||||||
|
(set self.imstate.text nil)
|
||||||
(when (= self.imstate.left :released)
|
(when (= self.imstate.left :released)
|
||||||
(set self.imstate.active nil))
|
(set self.imstate.active nil))
|
||||||
(each [_ button (pairs [:left :middle :right])]
|
(each [_ button (pairs [:left :middle :right])]
|
||||||
|
@ -17,6 +34,27 @@
|
||||||
:down :down
|
:down :down
|
||||||
:released nil)))))
|
:released nil)))))
|
||||||
|
|
||||||
|
(fn register-keys [keys]
|
||||||
|
(local commands {})
|
||||||
|
(local keymaps {})
|
||||||
|
(each [_ key (ipairs keys)]
|
||||||
|
(local command-name (.. "imstate:" key))
|
||||||
|
(tset commands command-name #(core.active_view:on_key_pressed key))
|
||||||
|
(tset keymaps key command-name))
|
||||||
|
(command.add #(not= (-?> core.active_view.imstate (. :focus)) nil) commands)
|
||||||
|
(keymap.add keymaps))
|
||||||
|
|
||||||
|
(register-keys [:backspace :delete :left :right :shift+left :shift+right :home :end :shift+home :shift+end])
|
||||||
|
|
||||||
|
(fn cmd-predicate [p]
|
||||||
|
(var p-fn p)
|
||||||
|
(when (= (type p-fn) :string) (set p-fn (require p-fn)))
|
||||||
|
(when (= (type p-fn) :table)
|
||||||
|
(local cls p-fn)
|
||||||
|
(set p-fn (fn [] (core.active_view:is cls))))
|
||||||
|
(fn [] (when (= (-?> core.active_view.imstate (. :focus)) nil)
|
||||||
|
(p-fn))))
|
||||||
|
|
||||||
(fn make-tag [tag]
|
(fn make-tag [tag]
|
||||||
(match (type tag)
|
(match (type tag)
|
||||||
:string tag
|
:string tag
|
||||||
|
@ -36,4 +74,113 @@
|
||||||
(activate view tag x y w h)
|
(activate view tag x y w h)
|
||||||
(and (active? view tag) (= view.imstate.left :released) (mouse-inside x y w h)))
|
(and (active? view tag) (= view.imstate.left :released) (mouse-inside x y w h)))
|
||||||
|
|
||||||
{: attach-imstate : mouse-inside : activate : active? : button}
|
(fn checkbox [view name isset x y ?tag]
|
||||||
|
(love.graphics.rectangle (if isset :fill :line) x y 12 12)
|
||||||
|
(local xEnd (renderer.draw_text style.font name (+ x 16) y style.text))
|
||||||
|
(love.graphics.setColor 1 1 1 1)
|
||||||
|
(button view (or ?tag name) x y (- xEnd x) 12))
|
||||||
|
|
||||||
|
(fn focused? [view tag] (= tag (-?> view.imstate.focus (. :tag))))
|
||||||
|
(fn focus [view tag x y w h opts]
|
||||||
|
(if (activate view tag x y w h)
|
||||||
|
(set view.imstate.focus
|
||||||
|
(doto (lume.clone (or opts {}))
|
||||||
|
(tset :tag tag)))
|
||||||
|
|
||||||
|
(and (= view.imstate.left :released) (focused? view tag) (not (active? view tag)))
|
||||||
|
(set view.imstate.focus nil))
|
||||||
|
(focused? view tag))
|
||||||
|
|
||||||
|
(local blink_period 0.8)
|
||||||
|
(fn x-from-i [s i xLeft font]
|
||||||
|
(if (or (<= i 1) (= s "")) xLeft
|
||||||
|
(x-from-i (s:sub 2) (- i 1) (+ xLeft (font:get_width (s:sub 1 1))) font)))
|
||||||
|
(fn i-from-x [s x xLeft font ?i]
|
||||||
|
(local i (or ?i 1))
|
||||||
|
(local w (font:get_width (s:sub 1 1)))
|
||||||
|
(local xMid (+ xLeft (/ w 2)))
|
||||||
|
(if (or (<= x xMid) (= s "")) i
|
||||||
|
(i-from-x (s:sub 2) x (+ xLeft w) font (+ i 1))))
|
||||||
|
|
||||||
|
(fn textnav [key i text]
|
||||||
|
(local imax (+ (length text) 1))
|
||||||
|
(match key
|
||||||
|
:left (math.max 1 (- i 1))
|
||||||
|
:right (math.min imax (+ i 1))
|
||||||
|
:home 1
|
||||||
|
:end imax))
|
||||||
|
|
||||||
|
(fn selection-span [view]
|
||||||
|
(let [f view.imstate.focus
|
||||||
|
iStart (math.min f.i f.iAnchor)
|
||||||
|
iLim (math.max f.i f.iAnchor)]
|
||||||
|
(values iStart iLim)))
|
||||||
|
|
||||||
|
(fn replace-selection [view s replacement ?iStart ?iLim]
|
||||||
|
(local (iStart iLim) (if ?iLim (values ?iStart ?iLim) (selection-span view)))
|
||||||
|
(local text
|
||||||
|
(.. (s:sub 1 (- iStart 1))
|
||||||
|
replacement
|
||||||
|
(s:sub iLim)))
|
||||||
|
(local iNew (+ iStart (length replacement)))
|
||||||
|
(set view.imstate.focus.i iNew)
|
||||||
|
(set view.imstate.focus.iAnchor iNew)
|
||||||
|
text)
|
||||||
|
|
||||||
|
(fn textbox [view tag text x y w]
|
||||||
|
(var textNew text)
|
||||||
|
(local (h hText xText yText) (values 20 16 (+ x 2) (+ y 2)))
|
||||||
|
|
||||||
|
; handle key events
|
||||||
|
(when (focus view tag x y w h {:i 1 :iAnchor 1 :blink (love.timer.getTime)})
|
||||||
|
(local f view.imstate.focus)
|
||||||
|
(when view.imstate.text
|
||||||
|
(set textNew (replace-selection view textNew view.imstate.text)))
|
||||||
|
(each [_ key (ipairs (or view.imstate.keys []))]
|
||||||
|
(set view.imstate.focus.blink (love.timer.getTime))
|
||||||
|
(if (= (key:sub 1 6) "shift+")
|
||||||
|
(set f.i (or (textnav (key:sub 7) f.i textNew) f.i))
|
||||||
|
(let [iNav (textnav key f.i textNew)]
|
||||||
|
(when iNav
|
||||||
|
(set f.i iNav)
|
||||||
|
(set f.iAnchor iNav))
|
||||||
|
(if (= f.i f.iAnchor)
|
||||||
|
(set textNew
|
||||||
|
(match key
|
||||||
|
:delete (replace-selection view textNew "" f.i (+ f.i 1))
|
||||||
|
(:backspace ? (> f.i 1)) (replace-selection view textNew "" (- f.i 1) f.i)
|
||||||
|
_ textNew))
|
||||||
|
(when (or (= key :delete) (= key :backspace))
|
||||||
|
(set textNew (replace-selection view textNew ""))))))))
|
||||||
|
|
||||||
|
; handle mouse events
|
||||||
|
(when (mouse-inside x y w h) (set view.cursor :ibeam))
|
||||||
|
(when (and (focused? view tag) (active? view tag) (mouse-inside x y w h))
|
||||||
|
(local mouse-i (i-from-x textNew (love.mouse.getX) x style.font))
|
||||||
|
(when (= view.imstate.left :pressed)
|
||||||
|
(set view.imstate.focus.iAnchor mouse-i))
|
||||||
|
(set view.imstate.focus.i mouse-i))
|
||||||
|
|
||||||
|
; draw box
|
||||||
|
(love.graphics.setLineWidth 1)
|
||||||
|
(love.graphics.rectangle :line x y w h)
|
||||||
|
(if (focused? view tag)
|
||||||
|
; draw text with selection + caret
|
||||||
|
(let [(iStart iLim) (selection-span view)
|
||||||
|
xSelect (renderer.draw_text style.font (textNew:sub 1 (- iStart 1)) xText yText style.text)
|
||||||
|
sSelect (textNew:sub iStart (- iLim 1))
|
||||||
|
wSelect (style.font:get_width sSelect)
|
||||||
|
xTail (+ xSelect wSelect)]
|
||||||
|
(when (> wSelect 0)
|
||||||
|
(renderer.draw_rect xSelect yText wSelect hText style.selection)
|
||||||
|
(renderer.draw_text style.font sSelect xSelect yText style.text))
|
||||||
|
(renderer.draw_text style.font (textNew:sub iLim) xTail yText style.text)
|
||||||
|
(when (or (active? view tag)
|
||||||
|
(< (% (- (love.timer.getTime) view.imstate.focus.blink) (* blink_period 2)) blink_period))
|
||||||
|
(renderer.draw_rect (x-from-i textNew view.imstate.focus.i xText style.font) yText style.caret_width hText style.caret)))
|
||||||
|
; just draw the text
|
||||||
|
(renderer.draw_text style.font textNew xText yText style.text))
|
||||||
|
(love.graphics.setColor 1 1 1)
|
||||||
|
textNew)
|
||||||
|
|
||||||
|
{: attach-imstate : cmd-predicate : mouse-inside : activate : active? : button : checkbox : textbox}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
(require :editor.lite)
|
(require :editor.lite)
|
||||||
|
(local util (require :lib.util))
|
||||||
(local TileView (require :editor.tileedit))
|
(local TileView (require :editor.tileedit))
|
||||||
(local MapEditView (require :editor.mapedit))
|
(local MapEditView (require :editor.mapedit))
|
||||||
|
(local {: cmd-predicate} (util.require :editor.imstate))
|
||||||
(local core (require :core))
|
(local core (require :core))
|
||||||
(local command (require :core.command))
|
(local command (require :core.command))
|
||||||
(local keymap (require :core.keymap))
|
(local keymap (require :core.keymap))
|
||||||
|
@ -15,31 +17,25 @@
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
(command.add :editor.tileedit {
|
(command.add (cmd-predicate :editor.gfxedit) {
|
||||||
"tileedit:save" (fn [] (core.active_view:save) (core.log "Saved tiles"))
|
"graphics-editor:save" (fn [] (core.active_view:save) (core.log "Saved"))
|
||||||
"tileedit:next-tile" #(core.active_view:select-rel 1)
|
"graphics-editor:reload" (fn [] (core.active_view:reload) (core.log "Reloaded"))
|
||||||
"tileedit:previous-tile" #(core.active_view:select-rel -1)
|
"graphics-editor:next-tile" #(core.active_view:select-rel 1)
|
||||||
"tileedit:copy" #(system.set_clipboard (: (core.active_view:tile) :tohex))
|
"graphics-editor:previous-tile" #(core.active_view:select-rel -1)
|
||||||
|
})
|
||||||
|
(command.add (cmd-predicate :editor.tileedit) {
|
||||||
|
"tileedit:copy"
|
||||||
|
#(system.set_clipboard (: (core.active_view:tile) :tohex))
|
||||||
"tileedit:paste"
|
"tileedit:paste"
|
||||||
#(when (= (length (system.get_clipboard)) 64)
|
#(when (= (length (system.get_clipboard)) 64)
|
||||||
(core.active_view:update-tile (: (system.get_clipboard) :fromhex)))
|
(core.active_view:update-tile (: (system.get_clipboard) :fromhex)))
|
||||||
})
|
})
|
||||||
(keymap.add {
|
(keymap.add {
|
||||||
"ctrl+s" "tileedit:save"
|
"ctrl+s" "graphics-editor:save"
|
||||||
"left" "tileedit:previous-tile"
|
"alt+r" "graphics-editor:reload"
|
||||||
"right" "tileedit:next-tile"
|
"left" "graphics-editor:previous-tile"
|
||||||
|
"right" "graphics-editor:next-tile"
|
||||||
"ctrl+c" "tileedit:copy"
|
"ctrl+c" "tileedit:copy"
|
||||||
"ctrl+v" "tileedit:paste"
|
"ctrl+v" "tileedit:paste"
|
||||||
})
|
})
|
||||||
|
|
||||||
(command.add :editor.mapedit {
|
|
||||||
"mapedit:next-tile" #(core.active_view:select-rel 1)
|
|
||||||
"mapedit:previous-tile" #(core.active_view:select-rel -1)
|
|
||||||
"mapedit:save" (fn [] (core.active_view:save) (core.log "Saved map"))
|
|
||||||
})
|
|
||||||
(keymap.add {
|
|
||||||
"ctrl+s" "mapedit:save"
|
|
||||||
"left" "mapedit:previous-tile"
|
|
||||||
"right" "mapedit:next-tile"
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
|
@ -1,18 +1,21 @@
|
||||||
(local GraphicsEditView (require :editor.gfxedit))
|
(local GraphicsEditView (require :editor.gfxedit))
|
||||||
(local style (require :core.style))
|
(local style (require :core.style))
|
||||||
(local util (require :lib.util))
|
(local util (require :lib.util))
|
||||||
(local {: mouse-inside : activate : active?} (util.require :editor.imstate))
|
(local lume (require :lib.lume))
|
||||||
|
(local {: mouse-inside : activate : active? : checkbox : textbox} (util.require :editor.imstate))
|
||||||
|
|
||||||
(local MapEditView (GraphicsEditView:extend))
|
(local MapEditView (GraphicsEditView:extend))
|
||||||
|
(local sprite-scale 3)
|
||||||
(local mapw 20)
|
(local mapw 20)
|
||||||
(local maph 12)
|
(local maph 12)
|
||||||
(local tilew (* GraphicsEditView.sprite-scale 14))
|
(local tilew (* sprite-scale 14))
|
||||||
(local tileh (* GraphicsEditView.sprite-scale 16))
|
(local tileh (* sprite-scale 16))
|
||||||
|
|
||||||
(fn MapEditView.new [self]
|
(fn MapEditView.new [self]
|
||||||
(MapEditView.super.new self)
|
(MapEditView.super.new self)
|
||||||
(set self.map (string.rep "\0" (* mapw maph))))
|
(set self.sprite-scale sprite-scale)
|
||||||
|
(set self.testtext "Hello")
|
||||||
|
(self:reload))
|
||||||
|
|
||||||
; map is stored bottom-to-top
|
; map is stored bottom-to-top
|
||||||
(fn imap-from-xy [mx my]
|
(fn imap-from-xy [mx my]
|
||||||
|
@ -31,13 +34,21 @@
|
||||||
|
|
||||||
(fn MapEditView.itile-from-xy [self mx my]
|
(fn MapEditView.itile-from-xy [self mx my]
|
||||||
(local imap (+ (imap-from-xy mx my) 1))
|
(local imap (+ (imap-from-xy mx my) 1))
|
||||||
(local enctile (string.byte (self.map:sub imap imap)))
|
(local enctile (string.byte (self.level.map:sub imap imap)))
|
||||||
(+ 1 (bit.bor
|
(+ 1 (bit.bor
|
||||||
(bit.lshift (bit.band enctile 0x1f) 3)
|
(bit.lshift (bit.band enctile 0x1f) 3)
|
||||||
(bit.rshift (bit.band enctile 0xe0) 5))))
|
(bit.rshift (bit.band enctile 0xe0) 5))))
|
||||||
|
|
||||||
(fn MapEditView.set-tile [self mx my itile]
|
(fn MapEditView.set-tile [self mx my itile]
|
||||||
(set self.map (update-map self.map 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.draw-map-editor [self x y]
|
(fn MapEditView.draw-map-editor [self x y]
|
||||||
(activate self :map x y (* tilew mapw) (* tileh maph))
|
(activate self :map x y (* tilew mapw) (* tileh maph))
|
||||||
|
@ -45,20 +56,44 @@
|
||||||
(local tilex (+ x (* (- mx 1) tilew)))
|
(local tilex (+ x (* (- mx 1) tilew)))
|
||||||
(local tiley (+ y (* (- my 1) tileh)))
|
(local tiley (+ y (* (- my 1) tileh)))
|
||||||
(local itile (self:itile-from-xy mx my))
|
(local itile (self:itile-from-xy mx my))
|
||||||
|
(local iobject (self:iobject-from-xy mx my))
|
||||||
(self:draw-sprite tilex tiley itile)
|
(self:draw-sprite tilex tiley itile)
|
||||||
(when (and (active? self :map) (mouse-inside tilex tiley tilew tileh) (not= itile self.itile))
|
(when (not= iobject nil)
|
||||||
(self:set-tile mx my self.itile)))))
|
(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 (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) (= self.imstate.left :released))
|
||||||
|
(if (= iobject nil)
|
||||||
|
(do (table.insert self.level.objects {:x mx :y my :func ""})
|
||||||
|
(set self.iobject (length self.level.objects)))
|
||||||
|
(set self.iobject iobject))))))
|
||||||
|
|
||||||
|
(fn MapEditView.reload [self]
|
||||||
|
(MapEditView.super.reload self)
|
||||||
|
(local level (util.readjson "game/map00001.json"))
|
||||||
|
(set self.level
|
||||||
|
(match (type level)
|
||||||
|
:string {:map (level:fromhex) :objects []}
|
||||||
|
:table (doto level (tset :map (level.map:fromhex))))))
|
||||||
|
|
||||||
(fn MapEditView.save [self]
|
(fn MapEditView.save [self]
|
||||||
(util.writejson "game/map00001.json" (self.map:tohex)))
|
(util.writejson "game/map00001.json"
|
||||||
|
(doto (lume.clone self.level)
|
||||||
|
(tset :map (self.level.map:tohex)))))
|
||||||
|
|
||||||
(fn MapEditView.draw [self]
|
(fn MapEditView.draw [self]
|
||||||
(self:draw_background style.background)
|
(self:draw_background style.background)
|
||||||
(love.graphics.setColor 1 1 1 1)
|
(love.graphics.setColor 1 1 1 1)
|
||||||
(self:draw-map-editor (+ self.position.x 10) (+ self.position.y 10))
|
(self:draw-map-editor (+ self.position.x 10) (+ self.position.y 10))
|
||||||
|
(when (checkbox self "Edit objects" (= self.itile nil) (+ self.position.x 10) (+ self.position.y 20 (* tileh maph)))
|
||||||
|
(set self.itile nil))
|
||||||
|
(set self.testtext (textbox self :test self.testtext (+ self.position.x 10) (+ self.position.y 40 (* tileh maph)) 200))
|
||||||
(self:draw-tile-selector
|
(self:draw-tile-selector
|
||||||
(+ self.position.x 10)
|
(+ self.position.x 10)
|
||||||
(+ self.position.y 20 (* tileh maph))
|
(+ self.position.y 65 (* tileh maph))
|
||||||
(- self.size.x 20)))
|
(- self.size.x 20)))
|
||||||
|
|
||||||
(fn MapEditView.get_name [self] "Map Editor")
|
(fn MapEditView.get_name [self] "Map Editor")
|
||||||
|
|
|
@ -60,14 +60,24 @@
|
||||||
(fn TileCache [tiles]
|
(fn TileCache [tiles]
|
||||||
{: tiles
|
{: tiles
|
||||||
:tilesprites []
|
:tilesprites []
|
||||||
|
:tile (fn [self itile] (or (. self.tiles itile) {:flags {}}))
|
||||||
:update-tile
|
:update-tile
|
||||||
(fn [self itile tile]
|
(fn [self itile tile]
|
||||||
(tset self.tiles itile tile)
|
(tset self.tiles itile
|
||||||
|
(-> (self:tile itile)
|
||||||
|
(doto (tset :gfx tile))))
|
||||||
(tset self.tilesprites itile nil))
|
(tset self.tilesprites itile nil))
|
||||||
|
:set-flag
|
||||||
|
(fn [self itile flag clear]
|
||||||
|
(tset (. self.tiles itile :flags) flag (if clear nil true)))
|
||||||
|
:load
|
||||||
|
(fn [self tiles]
|
||||||
|
(set self.tiles tiles)
|
||||||
|
(set self.tilesprites []))
|
||||||
:sprite
|
:sprite
|
||||||
(fn [self itile]
|
(fn [self itile]
|
||||||
(when (and (= nil (. self.tilesprites itile)) (not= nil (. self.tiles itile)))
|
(when (and (= nil (. self.tilesprites itile)) (not= nil (. self.tiles itile)))
|
||||||
(tset self.tilesprites itile (tile-to-sprite (. self.tiles itile))))
|
(tset self.tilesprites itile (tile-to-sprite (. self.tiles itile :gfx))))
|
||||||
(. self.tilesprites itile))})
|
(. self.tilesprites itile))})
|
||||||
|
|
||||||
{: tile-to-sprite : pal-from-bit : pal-from-byte : TileCache}
|
{: tile-to-sprite : pal-from-bit : pal-from-byte : TileCache}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
(local tiles (require :game.tiles))
|
(local tiles (require :game.tiles))
|
||||||
(local tiledraw (require :editor.tiledraw))
|
(local tiledraw (require :editor.tiledraw))
|
||||||
(local util (require :lib.util))
|
(local util (require :lib.util))
|
||||||
(local {: mouse-inside : activate : active?} (util.require :editor.imstate))
|
(local {: mouse-inside : activate : active? : checkbox} (util.require :editor.imstate))
|
||||||
|
|
||||||
(local TileView (GraphicsEditView:extend))
|
(local TileView (GraphicsEditView:extend))
|
||||||
|
|
||||||
|
@ -42,12 +42,14 @@
|
||||||
(fn draw-bit [bit x y even]
|
(fn draw-bit [bit x y even]
|
||||||
(renderer.draw_rect x y pixel-size pixel-size (if bit [255 255 255] [0 0 0])))
|
(renderer.draw_rect x y pixel-size pixel-size (if bit [255 255 255] [0 0 0])))
|
||||||
|
|
||||||
(fn TileView.tile [self] (or (. self.tilecache.tiles self.itile) (string.rep "\0" 32)))
|
(fn TileView.tile [self]
|
||||||
|
(or (-?> self.tilecache.tiles (. self.itile) (. :gfx)) (string.rep "\0" 32)))
|
||||||
|
|
||||||
(fn TileView.draw-tile-editor [self tile x y]
|
(fn TileView.draw-tile-editor [self tile x y]
|
||||||
(when (not (active? self :tile))
|
(when (not (active? self :tile))
|
||||||
(set self.bit nil))
|
(set self.bit nil))
|
||||||
(activate self :tile x y (* (+ pixel-size 1) 16) (* (+ pixel-size 1) 16))
|
(local editor-size (* (+ pixel-size 1) 16))
|
||||||
|
(activate self :tile x y editor-size editor-size)
|
||||||
(for [bitx 0 15] (for [bity 0 15]
|
(for [bitx 0 15] (for [bity 0 15]
|
||||||
(local (ibyte ibit) (map-bitxy bitx bity))
|
(local (ibyte ibit) (map-bitxy bitx bity))
|
||||||
(local bit (get-bit tile ibyte ibit))
|
(local bit (get-bit tile ibyte ibit))
|
||||||
|
@ -59,7 +61,18 @@
|
||||||
(when (= self.bit nil) (set self.bit (not bit)))
|
(when (= self.bit nil) (set self.bit (not bit)))
|
||||||
(when (not= self.bit bit)
|
(when (not= self.bit bit)
|
||||||
(self:update-tile (set-tile-bit tile ibyte ibit self.bit))))))
|
(self:update-tile (set-tile-bit tile ibyte ibit self.bit))))))
|
||||||
(love.graphics.setColor 1 1 1 1))
|
(love.graphics.setColor 1 1 1 1)
|
||||||
|
editor-size)
|
||||||
|
|
||||||
|
(fn TileView.draw-tile-flag [self flagname x y]
|
||||||
|
(local flags (-?> self.tilecache.tiles (. self.itile) (. :flags)))
|
||||||
|
(local flagset (if flags (. flags flagname) false))
|
||||||
|
(when (checkbox self flagname flagset x y)
|
||||||
|
(tset flags flagname (if flagset nil true))))
|
||||||
|
|
||||||
|
(fn TileView.draw-tile-flags [self x y]
|
||||||
|
(each [iflag flagname (ipairs tiles.flags)]
|
||||||
|
(self:draw-tile-flag flagname x (+ y (* (- iflag 1) (+ pixel-size 4))))))
|
||||||
|
|
||||||
(fn TileView.update-tile [self newtile]
|
(fn TileView.update-tile [self newtile]
|
||||||
(self.tilecache:update-tile self.itile newtile))
|
(self.tilecache:update-tile self.itile newtile))
|
||||||
|
@ -69,7 +82,8 @@
|
||||||
(fn TileView.draw [self]
|
(fn TileView.draw [self]
|
||||||
(self:draw_background style.background)
|
(self:draw_background style.background)
|
||||||
(local (x y) (values (+ self.position.x 10) (+ self.position.y 10)))
|
(local (x y) (values (+ self.position.x 10) (+ self.position.y 10)))
|
||||||
(self:draw-tile-editor (self:tile) x y)
|
(local editor-size (self:draw-tile-editor (self:tile) x y))
|
||||||
|
(self:draw-tile-flags (+ x editor-size pixel-size) y)
|
||||||
(self:draw-tile-selector x (+ y (* 18 (+ pixel-size 1))) (- self.size.x 20)))
|
(self:draw-tile-selector x (+ y (* 18 (+ pixel-size 1))) (- self.size.x 20)))
|
||||||
|
|
||||||
(fn TileView.get_name [self] "Tile Editor")
|
(fn TileView.get_name [self] "Tile Editor")
|
||||||
|
|
|
@ -154,7 +154,6 @@
|
||||||
|
|
||||||
; 20x12 means full map is 240 bytes - we have an extra 16 bytes at the end to mess with?
|
; 20x12 means full map is 240 bytes - we have an extra 16 bytes at the end to mess with?
|
||||||
(tile.appendmaps (prg:org 0x6800))
|
(tile.appendmaps (prg:org 0x6800))
|
||||||
; (: (prg:org 0x6800) :append :map [:bytes (string.rep "\0\032\064\096\128\160\192\224\001\033\065\097\129\161\193" 17)])
|
|
||||||
|
|
||||||
(code1:append :main
|
(code1:append :main
|
||||||
[:jsr :reset]
|
[:jsr :reset]
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
"2121212141212121212121212121412121212121610261616102616161026161616161026161612161C0C0C0C0C0C0C0C0C0C0C061C0C0C0C0C0612161C0C0C0C0C0C0C0C0C0C0C081C080C0C0C0024161C0C0C0C0C0C0C0C0C0C0C0C1C0C0C0E0C0612161C0C0C0C0C0C0C0C0C0C0C06161616161616121616161616161C1816161616161C0C0C0C0C0612161C0C0C0C0C0C0C0C0C0C0C061C0C0C0C0C0022161E0C0C0C0C0C0C0C0C0C0C081C0C0C0C0C0612161C0C0C0C0C0C0C0C0C0C0C061C0C0C0C0C0614161C0C0C0C0C0C0C0C0C0C0C061C0C0C0C0C061216161616161616161228161616161616161610221"
|
{"map":"2121212141212121212121212121412121212121610261616102616161026161616161026161612161C0C0C0C0C0C0C0C0C0C0C061C0C0C0C0C0612161C0C0A282C0C0C0A2C0C0C081C080C0C0C2024161C0C0C0C0C0C0C0C0C2C0A2C1A2C0C0E082612161E2C08282C0C0C0C0A2C0C06161616161616121616161616161C1816161616161C0C0C0C0C0612161C0C0C0C0C0C0C0C0C0C0C061C0C0C0C0C0022161E08282A2C0C0C0C0C0C0C081C0C0C0C0C0612161C0C0C0C0C0C0C0C0C0C0C061C0C0C0C0C0614161C0C0C0C0C0C0C0C0C0C0C061C0C0C0C0C061216161616161616161228161616161616161610221","objects":[{"func":"","x":17,"y":8},{"func":"","x":13,"y":9},{"func":"","x":13,"y":8},{"func":"","x":13,"y":4},{"func":"","x":8,"y":6},{"func":"","x":7,"y":6},{"func":"","x":2,"y":4},{"func":"","x":9,"y":1},{"func":"","x":10,"y":1}]}
|
|
@ -1,23 +1,25 @@
|
||||||
(local util (require :lib.util))
|
(local util (require :lib.util))
|
||||||
(local lume (require :lib.lume))
|
(local lume (require :lib.lume))
|
||||||
|
|
||||||
(fn loadtiles []
|
(local flags [:walkable :neutable :debris])
|
||||||
(lume.map
|
|
||||||
(util.readjson "game/tiles.json")
|
|
||||||
#($1:fromhex)))
|
|
||||||
|
|
||||||
(fn savetiles [tiles]
|
(fn deserialize [tile]
|
||||||
(util.writejson
|
(match (type tile)
|
||||||
"game/tiles.json"
|
:string {:gfx (tile:fromhex) :flags {}}
|
||||||
(lume.map tiles #($1:tohex))))
|
:table (doto tile (tset :gfx (tile.gfx:fromhex)))))
|
||||||
|
|
||||||
|
(fn serialize [tile] (doto (lume.clone tile) (tset :gfx (tile.gfx:tohex))))
|
||||||
|
|
||||||
|
(fn loadtiles [] (lume.map (util.readjson "game/tiles.json") deserialize))
|
||||||
|
(fn savetiles [tiles] (util.writejson "game/tiles.json" (lume.map tiles serialize)))
|
||||||
|
|
||||||
(fn appendtiles [tiles org]
|
(fn appendtiles [tiles org]
|
||||||
(each [_ tile (ipairs tiles)]
|
(each [_ tile (ipairs tiles)]
|
||||||
(org:append [:bytes tile])))
|
(org:append [:bytes tile.gfx])))
|
||||||
|
|
||||||
(fn appendmaps [org]
|
(fn appendmaps [org]
|
||||||
(local map (: (util.readjson "game/map00001.json") :fromhex))
|
(local map (: (util.readjson "game/map00001.json") :fromhex))
|
||||||
(org:append :map [:bytes map]))
|
(org:append :map [:bytes map]))
|
||||||
|
|
||||||
{: loadtiles : savetiles : appendtiles : appendmaps}
|
{: loadtiles : savetiles : appendtiles : appendmaps : flags}
|
||||||
|
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
["000000020A0820404A4020080A02000000010141511005025302051051410100","00000000020A0820404A4020080A020000000101415110050253020510514101","808080C0C0C0E0C0D0C8C04040404080808083858585828A9282820A08081980","8080C0A0A0A0C0C0D0C8C0501010188080808183838782828A8A920202020380","8080E0B0B0B098C0D0D0C840404060808080878D8D8D99828A8A920202020780","8080C0E0E0E0B0C0D0C8C040404060808080838787878D828A92820202020780","80808C8080808080B08080808C808080808C80808083B0808080808080868080","007C0C0C0C0C7C007C7E7EAA88888800001F181818181F001F0F979590909000","007C2C0C0C2C7C007C7E7EAA88888800001F18191C191F001F0F979590909000","D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","D5D5D5D5D5F5F5FDDDD5D5D5D5D5D5D5AAAAAAAAAEAEBFBFBFABAAAAAAAAAAAA","FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF","FF8FA7B3B3B3B3B3B3B3B3B3B3B383FFFFF8F2E6E6E6E6E6E6E6E6E6E6E6E0FF","FF8F87838383838383838383838383FFFFF8F0E0E0E0E0E0E0E0E0E0E0E0E0FF","FFFFCFCFCFCF898183838787878FFFFFFFFCE4E4E4E4E0E0E0E0E0E0F0F8FFFF","FFFFCFCFCFCF898123232727878FFFFFFFFCE4E4E4E0E0616565656571F8FFFF","FFFF83D3D3D3D3D3D3D3D3D3D383FFFFFFFFC0CACACECACBCACACACACAC0FFFF","FFFFABFBFBFBFBBBBBFBFBFBFBABFFFFFFFFD5DFDFDFDFDDDDDFDFDFDFD5FFFF","FFFF2B7B7B7B2B6B6B2B7B7B7B2BFFFFFFFF555F5F5F555757555F5F5F55FFFF","FFF3C78FBFFCF98187BFFFFFBF9F9FC7FFCFE1F1FCFCF8FEFEFCF9F0E6CE8F9F"]
|
[{"flags":[],"gfx":"000000020A0820406A4020080A02000000010141511005025702051051410100"},{"flags":[],"gfx":"00000000020A0820406A4020080A020000000101415110050257020510514101"},{"flags":[],"gfx":"808080C0C0C0E0C0D0C8C04040404080808083858585828A9282820A08081980"},{"flags":[],"gfx":"8080C0A0A0A0C0C0D0C8C0501010188080808183838782828A8A920202020380"},{"flags":[],"gfx":"8080E0B0B0B098C0D0D0C840404060808080878D8D8D99828A8A920202020780"},{"flags":[],"gfx":"8080C0E0E0E0B0C0D0C8C040404060808080838787878D828A92820202020780"},{"flags":[],"gfx":"80808C8080808080B08080808C808080808C80808083B0808080808080868080"},{"flags":[],"gfx":"007C0C0C0C0C7C007C7E7EAA88888800001F181818181F001F0F979584848400"},{"flags":{"neutable":true},"gfx":"007C2C0C0C2C7C007C7E7EAA88888800001F18191C191F001F0F979584848400"},{"flags":[],"gfx":"D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"},{"flags":[],"gfx":"D5D5D5D5D5F5F5FDDDD5D5D5D5D5D5D5AAAAAAAAAEAEBFBFBFABAAAAAAAAAAAA"},{"flags":{"neutable":true},"gfx":"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"},{"flags":[],"gfx":"FF8FA7B3B3B3B3B3B3B3B3B3B3B383FFFFF8F2E6E6E6E6E6E6E6E6E6E6E6E0FF"},{"flags":{"walkable":true},"gfx":"FF8F87838383838383838383838383FFFFF8F0E0E0E0E0E0E0E0E0E0E0E0E0FF"},{"flags":{"neutable":true},"gfx":"FFFFCFCFCFCF898183838787878FFFFFFFFCE4E4E4E4E0E0E0E0E0E0F0F8FFFF"},{"flags":{"neutable":true},"gfx":"FFFFCFCFCFCF898123232727878FFFFFFFFCE4E4E4E0E0616565656571F8FFFF"},{"flags":[],"gfx":"FFFF83D3D3D3D3D3D3D3D3D3D383FFFFFFFFC0CACACECACBCACACACACAC0FFFF"},{"flags":{"neutable":true},"gfx":"FFFFAFEBFBFBFBBBBBFBFBFBEBAFFFFFFFFFF5D7DFDFDFDDDDDFDFDFD7F5FFFF"},{"flags":{"neutable":true},"gfx":"FFFF2F2B2B2B6B6B6B6B2B2B2B2FFFFFFFFF755555555757575755555575FFFF"},{"flags":[],"gfx":"FFF3C78FBFFCF98187BFFFFFBF9F9FC7FFCFE1F1FCFCF8FEFEFCF9F0E6CE8F9F"},{"flags":[],"gfx":"80808C80808080A8AAAAAAA888888880808C8080808380859595958584848480"},{"flags":{"debris":true},"gfx":"80808C8080A0A0A8AAAA8AA0A8808080808C8081919090848594959585858080"},{"flags":[],"gfx":"8080D0848484D0C0C0D0D4D49090B880808C8AA0A0A08A83838AAAAA88889C80"},{"flags":{"debris":true},"gfx":"808080809890D4D0C0E0E0908484D480808C808682828A8A81808288888A8280"}]
|
42
thinks.txt
42
thinks.txt
|
@ -1,38 +1,6 @@
|
||||||
GOAL:
|
Neut Tower runtime model:
|
||||||
live-program an emulator in assembly
|
- before moving, see if an object exists at that location - if so, send it a message
|
||||||
|
- otherwise, see if the space is "empty" from the current player's perspective - if so, move them there
|
||||||
- a program is a graph that is flattened into a set of bytestreams.
|
- lookup table for tiles? rol rol rol to get index, 8 bits of possible data
|
||||||
- first step: make the damn graph.
|
- objects are kept in two parallel arrays, rather than a linked list
|
||||||
|
|
||||||
APPROACH:
|
|
||||||
- program is split into "ROM" and "RAM" - ROM is code that generally doesn't change while the program is running, RAM is program data
|
|
||||||
- a program is assembled from snippets that refer to other snippets by name
|
|
||||||
- a code snippet can be marked as a "loop point", a safe spot to pause and replace a running program's code
|
|
||||||
- this is also be a good spot to take snapshots of "RAM" which we could roll back to
|
|
||||||
- this assumes an empty stack + no code references in RAM - perhaps a special typed variable is needed for snippet pointers?
|
|
||||||
- for now, we will depend on gsplus' socket-based remote debugging capabilities to poke the program into emulated memory
|
|
||||||
|
|
||||||
WHAT IS A SNIPPET
|
|
||||||
- label + block
|
|
||||||
- block = bytestring, labels (offset into instruction list), fixups (label references)
|
|
||||||
- can concatenate blocks; snippets are stored "loose" - accessed by absolute JMP or JSR
|
|
||||||
- other compositional ideas:
|
|
||||||
- "scopes" - keep labels "alive" only for a short period, for autogenerated loops, if statements, etc
|
|
||||||
- could also just gensym
|
|
||||||
|
|
||||||
(lda 13) ; immediate
|
|
||||||
(lda (addr #x2000)) ; absolute
|
|
||||||
(lda (addr #x20)) ; zero-page
|
|
||||||
(lda (off-x (addr #x20))) ; zp,x
|
|
||||||
(lda (off-y (addr #x20))) ; zp,y
|
|
||||||
(lda (off-x@ (addr #x20))) ; (zp,x)
|
|
||||||
(lda (@off-y (addr #x20))) ; (zp),y
|
|
||||||
(lda (off-x (addr #x2000))) ; abs,x
|
|
||||||
(lda (off-y (addr #x2000))) ; abs,y
|
|
||||||
|
|
||||||
label = lazy address
|
|
||||||
maybe treat zero-page and absolute as different types? we will always plan what goes into zero-page. zp has addressing modes abs doesn't.
|
|
||||||
|
|
||||||
each opcode is a function that returns a block, usually 0-3 bytes with optionally associated labels + fixups
|
|
||||||
(fixup is a tuple: local offset, label reference, and whether we're expecting an absolute, zero-page, or relative address)
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue