diff --git a/editor/gfxedit2.fnl b/editor/gfxedit2.fnl new file mode 100644 index 0000000..18dc2ce --- /dev/null +++ b/editor/gfxedit2.fnl @@ -0,0 +1,69 @@ +(local View (require :core.view)) +(local tiles (require :game.tiles)) +(local tiledraw (require :editor.tiledraw)) +(local util (require :lib.util)) +(local files (require :game.files)) +(local {: attach-imstate : button : vert} (util.require :editor.imgui)) + +(local GraphicsEditView (View:extend)) + +(local sprite-scale 4) +(set GraphicsEditView.sprite-scale sprite-scale) + +(fn GraphicsEditView.new [self] + (GraphicsEditView.super.new self) + (self:set-style (self:initial-style)) + (set self.scrollheight math.huge) + (set self.scrollable true) + (attach-imstate self)) +(fn GraphicsEditView.get_scrollable_size [self] self.scrollheight) +(fn GraphicsEditView.initial-style [self] :tiles) +(fn GraphicsEditView.tilesize [self] + (let [style (tiles.style self.style)] + (values (or style.editw style.tilew) (or style.edith style.tileh)))) +(fn GraphicsEditView.set-style [self key] + (set self.style key) + (set self.tilecache (files.cache key)) + (set self.itile 1)) +(fn GraphicsEditView.reload [self] (files.reload)) +(fn GraphicsEditView.save [self] (files.save)) + +(fn GraphicsEditView.select-rel [self ditile] + (when self.itile + (local itile (+ self.itile ditile)) + (when (>= itile 1) (set self.itile itile)))) + +(fn GraphicsEditView.draw-sprite [self x y itile ?key] + (let [sprite (self.tilecache:sprite itile ?key)] + (when sprite + (love.graphics.setColor 1 1 1) + (love.graphics.draw sprite x y 0 self.sprite-scale self.sprite-scale) + (values (* (sprite:getWidth) self.sprite-scale) (* (sprite:getHeight) self.sprite-scale))))) + +(fn tile-selector [{: view : x : y : w : scale &as form} chosen-itile ?key] + (var tilex x) + (var tiley y) + (var selected-itile nil) + (var (pixw pixh) (view:tilesize)) + (when (= files.game.platform :ii) (set pixw (* (/ pixw 8) 7))) + (local tilew (* scale pixw)) + (local tileh (* scale pixh)) + (for [itile 1 (length view.tilecache.tiles)] + (view:draw-sprite tilex tiley itile ?key) + (when (= itile chosen-itile) + (love.graphics.rectangle :line (- tilex 2) (- tiley 2) (+ tilew 4) (+ tileh 4))) + (when (button {: view :tag [:tile itile] :x tilex :y tiley :w tilew :h tileh}) + (set selected-itile itile)) + (set tilex (+ tilex tilew 4)) + (when (>= (+ tilex tilew) (+ x w)) + (set tilex x) + (set tiley (+ tiley tileh 4)))) + (set form.h (+ tiley tileh (- y))) + selected-itile) + +(fn GraphicsEditView.draw-tile-selector [self form ?key] + (match (vert form tile-selector {:scale self.sprite-scale :w form.w} (when (= self.tilekey ?key) self.itile) ?key) + selected-itile (do (set self.itile selected-itile) + (set self.tilekey ?key)))) + +GraphicsEditView diff --git a/editor/imgui.fnl b/editor/imgui.fnl new file mode 100644 index 0000000..93a6ee4 --- /dev/null +++ b/editor/imgui.fnl @@ -0,0 +1,338 @@ +(local core (require :core)) +(local config (require :core.config)) +(local command (require :core.command)) +(local keymap (require :core.keymap)) +(local style (require :core.style)) +(local lume (require :lib.lume)) + +(fn attach-imstate [view] + (set view.imstate {}) + (fn view.on_mouse_pressed [self button x y clicks] + (tset self.imstate button :pressed) + (self.__index.on_mouse_pressed self button x y clicks)) + (fn view.on_mouse_released [self button x y] + (tset self.imstate button :released) + (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.form [self ?overrides] + (lume.merge {:x (+ self.position.x style.padding.x (- self.scroll.x)) + :y (+ self.position.y style.padding.y (- self.scroll.y)) + :view self} + (or ?overrides {}))) + (fn view.end-scroll [self {: y : h}] + (set self.scrollheight (- (+ y (or h 0) style.padding.y) (+ self.position.y style.padding.y (- self.scroll.y))))) + (fn view.draw [self] + (set self.cursor nil) + (self.__index.draw self) + (when self.imstate.postponed + (each [_ action (ipairs self.imstate.postponed)] + (action)) + (set self.imstate.postponed nil)) + (when (= self.cursor nil) (set self.cursor :arrow)) + (set self.imstate.keys nil) + (set self.imstate.text nil) + (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 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 + :ctrl+left :ctrl+right :ctrl+shift+left :ctrl+shift+right :ctrl+c :ctrl+v]) + +(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 postpone [view f] + (when (= view.imstate.postponed nil) + (set view.imstate.postponed [])) + (table.insert view.imstate.postponed f)) + +(fn make-tag [tag] + (match (type tag) + :string tag + :table (table.concat tag "::") + _ (tostring tag))) + +(fn mouse-inside [x y w h] + (local (mx my) (values (love.mouse.getX) (love.mouse.getY))) + (and (>= mx x) (<= mx (+ x w)) (>= my y) (<= my (+ y h)))) + +(fn consume-pressed [view button] + (when (= (. view.imstate button) :pressed) + (tset view.imstate button :down) + true)) + +(fn activate [{: view : tag : x : y : w : h}] + (when (and (mouse-inside x y w h) (consume-pressed view :left)) + (set view.imstate.active (make-tag tag)) + true)) + +(fn set-cursor [view cursor] + (when (= view.cursor nil) (set view.cursor cursor))) + +(fn active? [view tag] (= view.imstate.active (make-tag tag))) +(fn button [{: view : tag : x : y : w : h &as form}] + (when (mouse-inside x y w h) (set-cursor view :hand)) + (activate form) + (and (active? view tag) (= view.imstate.left :released) (mouse-inside x y w h))) + +(fn form-defaults [form k v ...] + (when (= (. form k) nil) + (let [v (if (= (type v) :function) (v form) v)] + (tset form k v))) + (if (>= (select :# ...) 2) (form-defaults form ...) + (do (when form.tag (set form.tag (make-tag form.tag))) ; fix up tag + form))) + +(fn with-style [form ...] + (form-defaults form :font style.font :color style.text :xpad style.padding.x :ypad style.padding.y ...)) + +(fn textbutton [form label] + (let [{: x : y : w : h : xpad : ypad : font : color : bg} + (with-style form + :bg style.selection + :tag label + :w #(+ ($1.font:get_width label) $1.xpad) + :h #(+ ($1.font:get_height) $1.ypad))] + (renderer.draw_rect x y w h bg) + (renderer.draw_text font label (+ x (/ xpad 2)) (+ y (/ ypad 2)) color) + (button form))) + +(fn checkbox [form name isset] + (let [{: x : y : w : h : font : color : x-label} + (with-style form + :tag name + :h (* 12 SCALE) + :x-label #(+ $1.x $1.h $1.xpad) + :w #(+ $1.x-label ($1.font:get_width name)))] + (love.graphics.rectangle (if isset :fill :line) x y h h) + (renderer.draw_text font name x-label y color) + (love.graphics.setColor 1 1 1 1) + (button form))) ; whose idea was this?? should return (not isset) >:/ + +(fn focused? [view tag] (= (make-tag tag) (-?> view.imstate.focus (. :tag)))) +(fn focus [{: view : tag : x : y : w : h &as form} opts] + (if (activate form) + (set view.imstate.focus + (doto (lume.clone (or opts {})) + (tset :tag (make-tag tag)))) + + (and (= view.imstate.left :released) (focused? view tag) (not (mouse-inside x y w h))) + (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 next-match [text i di pred] + (local imax (+ (length text) 1)) + (local inext (+ i di)) + (if (<= inext 1) 1 + (> inext imax) imax + (pred (text:sub inext inext)) (if (< di 0) i inext) + (next-match text inext di pred))) +(fn is-nonword-char [char] (config.non_word_chars:find char nil true)) +(fn next-word [text i di] + (let [iwordboundary (next-match text i di #(is-nonword-char $1))] + (next-match text iwordboundary di #(not (is-nonword-char $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)) + :ctrl+left (next-word text i -1) + :ctrl+right (next-word text 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 selection-text [view text] + (local (iStart iLim) (selection-span view)) + (text:sub iStart (- iLim 1))) + +(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 [form text] + (local {: font : color : w : h : x : y : xpad : ypad : color : view : tag} + (with-style form :h #(+ ($1.font:get_height) $1.xpad))) + (var textNew (or text "")) + (local (hText xText yText) (values (font:get_height) (+ x (/ xpad 2)) (+ y (/ ypad 2)))) + (local initial-press (= view.imstate.left :pressed)) + + ; handle key events + (when (focus form {:i 1 :iAnchor 1 :blink (love.timer.getTime)}) + (local f view.imstate.focus) + (when (> f.i (+ (length textNew) 1)) (set f.i (+ (length textNew) 1))) + (when (> f.iAnchor (+ (length textNew) 1)) (set f.iAnchor (+ (length textNew) 1))) + (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 :ctrl+c) (system.set_clipboard (selection-text view textNew)) + (= key :ctrl+v) (set textNew (replace-selection view textNew (system.get_clipboard))) + (key:find "shift%+") (set f.i (or (textnav (key:gsub "shift%+" "") f.i textNew) f.i)) + (let [iNav (textnav key f.i textNew)] + (when iNav + (set f.i iNav) + (set f.iAnchor iNav)) + (when (or (= key :delete) (= key :backspace)) + (local (iStartDel iLimDel) + (if (not= f.i f.iAnchor) (selection-span view) + (= key :delete) (values f.i (+ f.i 1)) + (= key :backspace) (values (math.max 1 (- f.i 1)) f.i))) + (set textNew (replace-selection view textNew "" iStartDel iLimDel))))))) + + ; handle mouse events + (when (mouse-inside x y w h) (set-cursor view :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 initial-press + (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 font (textNew:sub 1 (- iStart 1)) xText yText color) + sSelect (textNew:sub iStart (- iLim 1)) + wSelect (font:get_width sSelect) + xTail (+ xSelect wSelect)] + (when (> wSelect 0) + (renderer.draw_rect xSelect yText wSelect hText style.selection) + (renderer.draw_text font sSelect xSelect yText color)) + (renderer.draw_text font (textNew:sub iLim) xTail yText color) + (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 font) yText style.caret_width hText style.caret))) + ; just draw the text + (renderer.draw_text font textNew xText yText color)) + (love.graphics.setColor 1 1 1) + textNew) + +(fn textfield [form label text] + (let [{: x : y : w : wlabel : wtext : font : color} + (with-style form :wlabel #(+ ($1.font:get_width label) $1.xpad) + :wtext (* 150 SCALE) + :w #(+ $1.wlabel $1.wtext) + :tag label) + form-textbox (lume.merge form {:w wtext :x (+ x wlabel)}) + _ (renderer.draw_text font label x y color) + text (textbox form-textbox text)] + (set form.h form-textbox.h) + text)) + +(fn option-text [option] + (match (type option) + :string option + :table (or option.label (tostring option)) + _ (tostring option))) + +(fn dropdown [form selection options] + (let [{: x : y : w :h row-h : font : color : bg : xpad : ypad : view : tag} + (with-style form :h #(+ ($1.font:get_height) $1.ypad) + :bg style.selection)] + (var new-selection nil) + + (renderer.draw_rect x y w row-h bg) + (renderer.draw_text style.font (option-text selection) (+ x xpad) (+ y (/ ypad 2)) color) + (renderer.draw_text style.icon_font "-" (+ x w (- xpad)) (+ y (/ ypad 2)) color) + + (when (focused? view tag) + (var row-y (+ y row-h)) + (each [i option (ipairs options)] + (when (button (lume.merge form {:tag [(make-tag tag) i] :y row-y})) + (set new-selection option)) + (set row-y (+ row-y row-h))) + (postpone view (fn [] + (var row-y (+ y row-h)) + (each [i option (ipairs options)] + (renderer.draw_rect x row-y w row-h bg) + (renderer.draw_text font (option-text option) (+ x xpad) (+ row-y (/ ypad 2)) color) + (set row-y (+ row-y row-h)))))) + (focus form) + (or new-selection selection))) + +(local form-preserved-keys (collect [_ key (ipairs [:view :x :y :font :color :xpad :ypad])] key true)) +(fn prepare-form [form overrides] + (each [key (pairs form)] + (when (= (. form-preserved-keys key) nil) + (tset form key nil))) + (lume.extend form overrides) + form) + +(fn vert [form viewfn overrides ...] + (let [result [(viewfn (prepare-form form overrides) ...)]] + (set form.y (+ form.y (or form.h 0) (or form.ypad 0))) + (table.unpack result))) + +(fn horiz [form viewfn overrides ...] + (let [result [(viewfn (prepare-form form overrides) ...)]] + (set form.x (+ form.x (or form.w 0) (or form.xpad 0))) + (table.unpack result))) + +(fn horiz-wrapper [{: x : w &as form}] + (set form.w nil) + (fn [viewfn overrides ...] + (let [result [(viewfn (prepare-form form overrides) ...)]] + (set form.x (+ form.x (or form.w 0) (or form.xpad 0))) + (when (> form.x (+ x w)) + (set form.x x) + (set form.y (+ form.y form.h (or form.ypad 0)))) + (table.unpack result)))) + +{: attach-imstate : cmd-predicate : postpone : mouse-inside : activate : active? + : button : checkbox : textbox : textfield : textbutton : dropdown + : vert : horiz : horiz-wrapper + : with-style : prepare-form : form-defaults} + diff --git a/editor/tileedit/init.fnl b/editor/tileedit/init.fnl index d7731a2..89a0bb5 100644 --- a/editor/tileedit/init.fnl +++ b/editor/tileedit/init.fnl @@ -1,9 +1,10 @@ -(local GraphicsEditView (require :editor.gfxedit)) +(local GraphicsEditView (require :editor.gfxedit2)) (local style (require :core.style)) (local tiles (require :game.tiles)) (local files (require :game.files)) (local util (require :lib.util)) -(local {: mouse-inside : activate : active? : checkbox : textfield : button : dropdown} (util.require :editor.imstate)) +(local lume (require :lib.lume)) +(local {: mouse-inside : activate : active? : checkbox : textfield : button : dropdown : with-style : form-defaults : vert : horiz-wrapper} (util.require :editor.imgui)) (local TileView (GraphicsEditView:extend)) @@ -47,92 +48,105 @@ (renderer.draw_rect x y pixel-size pixel-size colorbg) (when ?colorfg (renderer.draw_rect (+ x 3) (+ y 3) (- pixel-size 6) (- pixel-size 6) ?colorfg))) -(fn TileView.draw-tile-editor [self tile x y] - (when (not (active? self :tile)) (self:draw-off)) +(fn tile-editor [{:view self : x : y &as form} tile] + (local {: tag} (with-style form :tag :tile)) + (when (not (active? self tag)) (self:draw-off)) (local (w h) (self:tilesize)) - (local editor-w (* (+ pixel-size 1) w)) - (local editor-h (* (+ pixel-size 1) h)) - (activate self :tile x y editor-w editor-h) + (set form.w (* (+ pixel-size 1) w)) + (set form.h (* (+ pixel-size 1) h)) + (activate form) (for [bitx 0 (- w 1)] (for [bity 0 (- h 1)] (local (ibyte ibit mask) (self:map-bitxy bitx bity w h)) (local b (get-bits tile ibyte ibit mask)) (local (px py) (values (+ x (* bitx (+ pixel-size 1))) (+ y (* bity (+ pixel-size 1))))) (local (colorbg colorfg) (self:pixel-color b ibyte ibit)) (self:draw-pixel px py colorbg colorfg) - (when (and (active? self :tile) (mouse-inside px py pixel-size pixel-size)) + (when (and (active? self tag) (mouse-inside px py pixel-size pixel-size)) (self:draw-on b) (local bits (self:draw-bits)) (when (not= bits b) (self:update-tile (set-tile-bits tile ibyte ibit mask bits)))))) - (love.graphics.setColor 1 1 1 1) - (values editor-w editor-h)) + (love.graphics.setColor 1 1 1 1)) -(fn TileView.draw-tile-flag [self flagname x y] - (local flags (-?> self.tilecache.tiles (. self.itile) (. :flags))) - (local flagset (if flags (. flags flagname) false)) - (let [(checked yNew) (checkbox self flagname flagset x y)] - (when checked (tset flags flagname (if flagset nil true))) - yNew)) +(fn TileView.draw-tile-editor [self form tile] (vert form tile-editor {} tile)) -(fn TileView.draw-tile-flags [self x y] - (local tile (-?> self.tilecache.tiles (. self.itile))) - (var y y) - (when tile - (set (tile.word y) (textfield self "Default word" tile.word x (+ y style.padding.y) (* 100 SCALE) (* 200 SCALE))) - (set (tile.label y) (textfield self "Label" tile.label x (+ y style.padding.y) (* 100 SCALE) (* 200 SCALE)))) - (each [iflag flagname (ipairs (tiles.flags))] - (set y (self:draw-tile-flag flagname x (+ y style.padding.y)))) - y) +(fn tile-flag [form tile flagname] + (local flagset (?. tile :flags flagname)) + (when (checkbox form flagname flagset) + (tset tile :flags flagname (if flagset nil true)))) -(fn TileView.draw-tile-preview [self x y] +(fn TileView.draw-tile-flags [self form] + (let [tile (-?> self.tilecache.tiles (. self.itile)) + fieldform {:wlabel (* 100 SCALE) :wtext (* 200 SCALE)}] + (when tile + (set tile.word (vert form textfield fieldform "Default word" tile.word)) + (set tile.label (vert form textfield fieldform "Label" tile.label))) + (each [iflag flagname (ipairs (tiles.flags))] + (vert form tile-flag {} tile flagname)))) + +(fn tile-preview [{:view self : x : y &as form} itile tilekey] (each [_ [tx ty] (ipairs (self:preview-locations))] - (self:draw-sprite (+ x (* tx self.sprite-scale)) (+ y (* ty self.sprite-scale)) self.itile self.tilekey))) + (let [dx (* tx self.sprite-scale) dy (* ty self.sprite-scale) + (w h) (self:draw-sprite (+ x dx) (+ y dy) itile tilekey)] + (when (and w (or (= form.w nil) (< form.w (+ w dx)))) (set form.w (+ w dx))) + (when (and h (or (= form.h nil) (< form.h (+ h dy)))) (set form.h (+ h dy)))))) +(fn TileView.draw-tile-preview [self form] (vert form tile-preview {} self.itile self.tilekey)) -(fn TileView.draw-tile-palette [self x y w] - (local pal (self:palette)) - (if pal - (do (var cx x) - (var cy y) - (each [icolor color (ipairs pal)] - (when (>= cx w) - (set cx x) - (set cy (+ cy pixel-size style.padding.y))) - (when (button self [:pal icolor] cx cy pixel-size pixel-size) - (set self.icolor icolor)) - (renderer.draw_rect cx cy pixel-size pixel-size color) - (when (= icolor self.icolor) - (love.graphics.setColor 1 1 1 1) - (love.graphics.rectangle :line (- cx 2) (- cy 2) (+ pixel-size 4) (+ pixel-size 4))) - (set cx (+ cx pixel-size style.padding.x))) - (+ pixel-size style.padding.y)) - 0)) +(fn tile-palette [{:view self : x : y : w &as form} pal selected-color] + (let [wrap (horiz-wrapper (with-style form))] + (var selected-color selected-color) + (each [icolor color (ipairs pal)] + (renderer.draw_rect form.x form.y pixel-size pixel-size color) + (when (= icolor selected-color) + (love.graphics.setColor 1 1 1 1) + (love.graphics.rectangle :line (- form.x 2) (- form.y 2) (+ pixel-size 4) (+ pixel-size 4))) + (when (wrap button {:tag [:pal icolor] :w pixel-size :h pixel-size}) + (set selected-color icolor))) + (set form.w w) ;; todo: some kind of "group" combinator that does this for us + (set form.h (+ (- form.y y) pixel-size)) + (set form.x x) + (set form.y y) + selected-color)) + +(fn TileView.draw-tile-palette [self form] + (match (self:palette) + pal (set self.icolor (vert form tile-palette {:w form.w} pal self.icolor)))) (fn TileView.update-tile [self newtile] (self.tilecache:update-tile self.itile newtile self.tilekey)) -(fn TileView.draw-style-selector [self x y] - (renderer.draw_text style.font "Style" x (+ y (/ style.padding.y 2)) style.text) - (let [(selection yNext) (dropdown self :layer-selector self.style (tiles.tile-styles) (+ x (* 50 SCALE)) y (* 100 SCALE)) ] - (when (not= self.style selection) - (self:set-style selection)) - (- yNext y))) +(fn style-selector [form current-style] + (let [{:view self : x : y : font : color : ypad} (with-style form) + form-drop (lume.merge form {:x (+ x (* 50 SCALE)) :w (* 100 SCALE) :tag :layer-selector}) + selection (dropdown form-drop current-style (tiles.tile-styles))] + (renderer.draw_text font "Style" x (+ y (/ ypad 2)) color) + (set form.w (- (+ form-drop.x form-drop.w) x)) + (set form.h form-drop.h) + (when (not= current-style selection) selection))) + +(fn TileView.draw-style-selector [self form] + (match (vert form style-selector {} self.style) + new-style (self:set-style new-style))) (fn TileView.draw [self] (self:draw_background style.background) (self:draw_scrollbar) - (local (x y) (values (+ self.position.x style.padding.x (- self.scroll.x)) - (+ self.position.y style.padding.y (- self.scroll.y)))) - (local (editor-w editor-h) (self:draw-tile-editor (self:tile) x y)) - (local preview-y (self:draw-tile-flags (+ x editor-w pixel-size) y)) - (self:draw-tile-preview (+ x editor-w pixel-size) (+ preview-y style.padding.y)) - (var selector-y (+ y editor-h pixel-size)) - (set selector-y (+ selector-y (self:draw-tile-palette x selector-y (- self.size.x 20)))) - (when (> (length (tiles.tile-styles)) 1) - (set selector-y (+ selector-y (self:draw-style-selector x selector-y) style.padding.y))) - (each [_ key (ipairs (self:tilekeys))] - (local selector-h (self:draw-tile-selector x selector-y (- self.size.x 20) key)) - (set selector-y (+ selector-y selector-h pixel-size))) - (set self.scrollheight (- selector-y y))) + (let [form (self:form) + form-side (self:form)] + (self:draw-tile-editor form (self:tile)) + + ; layout sidebar + (set form-side.x (+ form.x form.w form.xpad)) + (self:draw-tile-flags form-side) + (self:draw-tile-preview form-side) + + ; continue laying out under tile editor + (self:draw-tile-palette (lume.extend form {:w (- self.size.x 20)})) + (when (> (length (tiles.tile-styles)) 1) + (self:draw-style-selector form)) + (each [_ key (ipairs (self:tilekeys))] + (self:draw-tile-selector (lume.extend form {:w (- self.size.x 20)}) key)) + (self:end-scroll form))) (fn TileView.initial-style [self] :tiles) (fn TileView.get_name [self] "Tile Editor")