ditch love-imgui in favour of my own home-rolled implementation

tile editor improvements and cleanup
This commit is contained in:
Jeremy Penner 2020-10-17 23:52:41 -04:00
parent a761ed8d5a
commit aa326c30df
7 changed files with 83 additions and 96 deletions

47
editor/imstate.fnl Normal file
View file

@ -0,0 +1,47 @@
(fn attach-imstate [view]
(set view.imstate {:x (love.mouse.getX) :y (love.mouse.getY)})
(local cls view.__index)
(fn view.on_mouse_pressed [self button x y clicks]
(tset self.imstate button :pressed)
(set self.imstate.x x)
(set self.imstate.y y)
(cls.on_mouse_pressed self button x y clicks))
(fn view.on_mouse_moved [self x y dx dy]
(set self.imstate.x x)
(set self.imstate.y y)
(cls.on_mouse_moved self x y dx dy))
(fn view.on_mouse_released [self button x y]
(tset self.imstate button :released)
(set self.imstate.x x)
(set self.imstate.y y)
(cls.on_mouse_released self button x y))
(fn view.draw [self]
(cls.draw self)
(when (= self.imstate.left :released)
(set self.imstate.active nil))
(each [_ button (pairs [:left :middle :right])]
(tset self.imstate button
(match (. self.imstate button)
:pressed :down
:down :down
:released nil)))))
(fn make-tag [tag]
(match (type tag)
:string tag
:table (table.concat tag "::")
_ (tostring tag)))
(fn mouse-inside [view x y w h]
(and (>= view.imstate.x x) (<= view.imstate.x (+ x w)) (>= view.imstate.y y) (<= view.imstate.y (+ y h))))
(fn activate [view tag x y w h]
(when (and (= view.imstate.left :pressed) (mouse-inside view x y w h))
(set view.imstate.active (make-tag tag))
true))
(fn active? [view tag] (= view.imstate.active (make-tag tag)))
(fn button [view tag x y w h]
(activate view tag x y w h)
(and (active? view tag) (= view.imstate.left :released) (mouse-inside view x y w h)))
{: attach-imstate : mouse-inside : activate : active? : button}

View file

@ -1,46 +0,0 @@
local imgui = require("imgui")
local enqueue_love_event = system.enqueue_love_event
function system.enqueue_love_event(ev, a, b, c, d, e, f)
local keyevents = {
textinput = function() imgui.TextInput(a) end,
keypressed = function() imgui.KeyPressed(a) end,
keyreleased = function() imgui.KeyReleased(a) end,
}
local mouseevents = {
mousemoved = function() imgui.MouseMoved(a, b) end,
mousepressed = function() imgui.MousePressed(c) end,
mousereleased = function() imgui.MouseReleased(c) end,
wheelmoved = function() imgui.WheelMoved(b) end
}
local pass_event_to_lite = true
if keyevents[ev] then
keyevents[ev]()
pass_event_to_lite = not imgui.GetWantCaptureKeyboard()
elseif mouseevents[ev] then
mouseevents[ev]()
pass_event_to_lite = not imgui.GetWantCaptureMouse()
elseif ev == 'quit' then
imgui.ShutDown()
end
if pass_event_to_lite then enqueue_love_event(ev, a, b, c, d, e, f) end
end
local View = require("core.view")
local ImView = View:extend()
function ImView.gui(self)
end
function ImView.draw(self)
imgui.NewFrame()
imgui.SetNextWindowPos(self.position.x, self.position.y, "Always")
imgui.SetNextWindowSize(self.size.x, self.size.y, "Always")
imgui.Begin(self:get_name(), nil, { "NoTitleBar", "NoResize", "NoMove", "NoCollapse" })
self:gui()
imgui.End()
imgui.EndFrame()
imgui.Render()
end
return ImView

View file

@ -54,6 +54,7 @@
(putpixel x y color))) (putpixel x y color)))
(love.graphics.setCanvas) (love.graphics.setCanvas)
(love.graphics.setScissor (table.unpack scissor)) (love.graphics.setScissor (table.unpack scissor))
(love.graphics.setColor 1 1 1 1)
canvas) canvas)
{: tile-to-sprite : pal-from-bit : pal-from-byte} {: tile-to-sprite : pal-from-bit : pal-from-byte}

View file

@ -5,11 +5,13 @@
(local tiles (require :game.tiles)) (local tiles (require :game.tiles))
(local tiledraw (require :editor.tiledraw)) (local tiledraw (require :editor.tiledraw))
(local lume (require :lib.lume)) (local lume (require :lib.lume))
(local util (require :lib.util))
(local {: attach-imstate : mouse-inside : activate : active? : button} (util.require :editor.imstate))
(local TileView (View:extend)) (local TileView (View:extend))
(local pixel-size 24) (local pixel-size 24)
(local sprite-scale 4) (local sprite-scale 4)
(local xy-to-ibit []) (local xy-to-ibit [])
(for [x 0 15] (tset xy-to-ibit x [])) (for [x 0 15] (tset xy-to-ibit x []))
(for [y 0 15] (for [y 0 15]
@ -22,10 +24,6 @@
(when (and (>= x 0) (< x 16) (>= y 0) (< y 16)) (when (and (>= x 0) (< x 16) (>= y 0) (< y 16))
(local ibit (. xy-to-ibit x y)) (local ibit (. xy-to-ibit x y))
(values (math.floor (/ ibit 8)) (% ibit 8)))) (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] (fn get-byte [tile ibyte]
(: (tile:sub (+ ibyte 1) (+ ibyte 1)) :byte)) (: (tile:sub (+ ibyte 1) (+ ibyte 1)) :byte))
@ -51,30 +49,36 @@
(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 draw-tile [tile x y] (fn TileView.new [self]
(TileView.super.new self)
(set self.tiles (tiles.loadtiles))
(set self.itile 1)
(set self.tilesprites [])
(attach-imstate self))
(fn TileView.tile [self] (or (. self.tiles self.itile) (string.rep "\0" 32)))
(fn TileView.draw-tile [self tile x y]
(when (not (active? self :tile))
(set self.bit nil))
(activate self :tile x y (* (+ pixel-size 1) 16) (* (+ pixel-size 1) 16))
(for [bitx 0 15] (for [bity 0 15] (for [bitx 0 15] (for [bity 0 15]
(local bit (get-bit tile (map-bitxy bitx bity))) (local (ibyte ibit) (map-bitxy bitx bity))
(local bit (get-bit tile ibyte ibit))
(local (px py) (values (+ x (* bitx (+ pixel-size 1))) (+ y (* bity (+ pixel-size 1))))) (local (px py) (values (+ x (* bitx (+ pixel-size 1))) (+ y (* bity (+ pixel-size 1)))))
(if (or (= bitx 0) (= bitx 15)) (if (or (= bitx 0) (= bitx 15))
(draw-bit-color bit px py) (draw-bit-color bit px py)
(draw-bit bit px py (= (% bitx 2) 1)))))) (draw-bit bit px py (= (% bitx 2) 1)))
(when (and (active? self :tile) (mouse-inside self px py pixel-size pixel-size))
(when (= self.bit nil) (set self.bit (not bit)))
(when (not= self.bit bit)
(self:update-tile (set-tile-bit tile ibyte ibit self.bit))))))
(love.graphics.setColor 1 1 1 1))
(fn TileView.new [self]
(self.super.new self)
(set self.tiles (tiles.loadtiles))
(set self.itile 1)
(set self.tilesprites []))
(fn TileView.tile [self] (or (. self.tiles self.itile) (string.rep "\0" 32)))
(fn TileView.update-tile [self newtile] (fn TileView.update-tile [self newtile]
(tset self.tiles self.itile newtile) (tset self.tiles self.itile newtile)
(tset self.tilesprites self.itile nil)) (tset self.tilesprites self.itile nil))
(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] (tiles.savetiles self.tiles)) (fn TileView.save [self] (tiles.savetiles self.tiles))
(fn TileView.select-rel [self ditile] (fn TileView.select-rel [self ditile]
(local itile (+ self.itile ditile)) (local itile (+ self.itile ditile))
@ -88,37 +92,20 @@
(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)))
(draw-tile (self:tile) x y) (self:draw-tile (self:tile) x y)
(love.graphics.setColor 1 1 1 1)
(var tilex (+ self.position.x 10)) (var tilex (+ self.position.x 10))
(var tiley (+ self.position.y (* 18 (+ pixel-size 1)))) (var tiley (+ self.position.y (* 18 (+ pixel-size 1))))
(local tile-size (* 16 sprite-scale))
(each [itile _ (ipairs self.tiles)] (each [itile _ (ipairs self.tiles)]
(love.graphics.draw (self:tilesprite itile) tilex tiley 0 sprite-scale sprite-scale) (love.graphics.draw (self:tilesprite itile) tilex tiley 0 sprite-scale sprite-scale)
(set tilex (+ tilex (* 16 sprite-scale))))) (when (= itile self.itile)
(love.graphics.rectangle :line (- tilex 2) (- tiley 2) (+ (* 14 sprite-scale) 4) (+ tile-size 4)))
(fn TileView.selected-bit [self mx my] (when (button self [:tile itile] tilex tiley tile-size tile-size)
(local (x y) (values (+ self.position.x 10) (+ self.position.y 10))) (set self.itile itile))
(values (map-bit (- mx x) (- my y)))) (set tilex (+ tilex tile-size))
(when (>= (+ tilex tile-size) (+ self.position.x self.size.x -10))
(fn TileView.on_mouse_pressed [self button mx my clicks] (set tilex (+ self.position.x 10))
(if (self.super.on_mouse_pressed self button mx my clicks) true (set tiley (+ tiley tile-size 4)))))
(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") (fn TileView.get_name [self] "Tile Editor")

BIN
imgui.so

Binary file not shown.

View file

@ -5,7 +5,6 @@ fv = require("lib.fennelview")
pp = function(x) print(fv(x)) end pp = function(x) print(fv(x)) end
lume = require("lib.lume") lume = require("lib.lume")
-- these set global variables and can't be required after requiring core.strict -- these set global variables and can't be required after requiring core.strict
imgui = require("imgui")
luars232 = require("luars232") luars232 = require("luars232")
_coroutine_resume = coroutine.resume _coroutine_resume = coroutine.resume

View file

@ -1,7 +1,6 @@
(require "editor") (require "editor")
(local util (require "lib.util")) (local util (require "lib.util"))
(local lume (require "lib.lume")) (local lume (require "lib.lume"))
(local imgui (require "imgui"))
(local link (require "link")) (local link (require "link"))
(local core (require "core")) (local core (require "core"))
(local command (require "core.command")) (local command (require "core.command"))