diff --git a/editor/8bitsy.fnl b/editor/8bitsy.fnl index c04df16..388b139 100644 --- a/editor/8bitsy.fnl +++ b/editor/8bitsy.fnl @@ -1,41 +1,40 @@ (local util (require :lib.util)) (local actions (require :editor.actions)) -(local {: textbox : dropdown : textfield} (util.require :editor.imstate)) +(local {: textbox : dropdown : textfield : label : under : right-of : reform : group-wrapper} (util.require :editor.imgui)) (local files (require :game.files)) (local lume (require :lib.lume)) (local style (require :core.style)) (actions.register :say - (fn [action view x y w i] - (let [characters (lume.map files.game.portraits #$1.label) + (fn [action form i] + (let [characters (lume.map (or files.game.portraits []) #$1.label) character (or action.character (. characters 1)) lines (or action.lines []) - (character y) (dropdown view [:say :char i] character characters x (+ y style.padding.y) w) - (line1 y) (textbox view [:say :line1 i] (or (. lines 1) "") x (+ y style.padding.y) w) - (line2 y) (textbox view [:say :line2 i] (or (. lines 2) "") x y w) - (line3 y) (textbox view [:say :line3 i] (or (. lines 3) "") x y w) - (line4 y) (textbox view [:say :line4 i] (or (. lines 4) "") x y w)] + character (dropdown (under form {:tag [:say :char i] :w form.w}) character characters) + line1 (textbox (under form {:tag [:say :line1 i] :w form.w}) (or (. lines 1) "")) + line2 (textbox (under form {:tag [:say :line2 i] :w form.w}) (or (. lines 2) "")) + line3 (textbox (under form {:tag [:say :line3 i] :w form.w}) (or (. lines 3) "")) + line4 (textbox (under form {:tag [:say :line4 i] :w form.w}) (or (. lines 4) ""))] (set action.character character) (util.nested-tset action [:lines 1] (line1:sub 1 33)) (util.nested-tset action [:lines 2] (line2:sub 1 33)) (util.nested-tset action [:lines 3] (line3:sub 1 33)) - (util.nested-tset action [:lines 4] (line4:sub 1 33)) - y)) + (util.nested-tset action [:lines 4] (line4:sub 1 33)))) (fn [action vm] (local {: say} (require :bitsy.defs)) (say action.character (table.unpack (lume.map action.lines #($1:upper)))))) (actions.register :warp - (fn [action view x y w i] - (let [maps (icollect [imap _ (ipairs files.game.levels)] (.. :map imap)) + (fn [action form i] + (let [g (group-wrapper form) + maps (icollect [imap _ (ipairs files.game.levels)] (.. :map imap)) map (or action.map (. maps 1)) - y (+ y style.padding.y) - map (dropdown view [:warp :map i] map maps x y (* 100 SCALE)) - (position-string y) (textbox view [:warp :loc i] (string.format "%x" (or action.position 0)) (+ x (* 150 SCALE)) y (* 150 SCALE)) + map (g dropdown (under form {:tag [:warp :map i] :w (- (/ form.w 2) form.xpad)}) map maps) + position-string (g textbox (right-of form {:tag [:warp :loc i] :w form.w}) (string.format "%x" (or action.position 0))) position (or (tonumber position-string 16) action.position)] (set action.map map) (set action.position position) - y)) + (g))) (fn [action vm] (values :move-to-responder action.position :lit action.map :map-player-yx-ptr :set :lit action.map :next-level :set))) @@ -43,20 +42,17 @@ (actions.register-const :disappear :disappear) (actions.register :set-flag - (fn [action view x y w i] - (let [y (+ y style.padding.y) - x (renderer.draw_text style.font "Set " x y style.text) - flag (or action.flag (. files.game.flags 1)) - flag (dropdown view [:set-flag :flag i] flag files.game.flags x y (* 100 SCALE)) - x (renderer.draw_text style.font " to " (+ x (* 100 SCALE)) y style.text) + (fn [action form i] + (let [g (group-wrapper form) options (lume.concat [{:label "" :value 0xffff} {:label "" :value 0}] (icollect [_ flag (ipairs files.game.flags)] {:label flag :value (.. :cond- flag)})) - rhs (or action.rhs (. options 1)) - (rhs y) (dropdown view [:set-flag :rhs i] rhs options x y (* 100 SCALE))] - (set action.flag flag) - (set action.rhs rhs) - y)) + rhs (or action.rhs (. options 1))] + (g label (reform form) "Set ") + (set action.flag (g dropdown (right-of form {:tag [:set-flag :flag i] :w (* 100 SCALE)}) action.flag files.game.flags)) + (g label (right-of form) " to ") + (set action.rhs (g dropdown (right-of form {:tag [:set-flag :rhs i] :w (* 100 SCALE)}) rhs options)) + (g))) (fn [action vm] (values action.rhs.value (.. :cond-var- action.flag) :set))) diff --git a/editor/actions.fnl b/editor/actions.fnl index 5604731..762def6 100644 --- a/editor/actions.fnl +++ b/editor/actions.fnl @@ -7,7 +7,7 @@ (set actions.edit (defmulti #$1.action :edit ...)) (set actions.generate (defmulti #$1.action :generate ...)) -(defmethod actions.edit :default (fn [action view x y w i] y)) +(defmethod actions.edit :default (fn [action form i])) (fn actions.register [key edit generate] (when (= actions.actionlist nil) @@ -18,6 +18,6 @@ (defmethod actions.generate key generate)) (fn actions.register-const [key generated-value] - (actions.register key (fn [action view x y w i] y) #generated-value)) + (actions.register key (fn [action form i]) #generated-value)) actions.hot diff --git a/editor/imgui.fnl b/editor/imgui.fnl index 37bbfed..69f5e43 100644 --- a/editor/imgui.fnl +++ b/editor/imgui.fnl @@ -97,12 +97,7 @@ (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))) - +;; styling and layout (fn form-defaults [form k v ...] (when (= (. form k) nil) (let [v (if (= (type v) :function) (v form) v)] @@ -114,6 +109,71 @@ (fn with-style [form ...] (form-defaults form :font style.font :color style.text :xpad style.padding.x :ypad style.padding.y ...)) +(local form-preserved-keys (collect [_ key (ipairs [:view :x :y :font :color :xpad :ypad])] key true)) +(fn reform [form overrides] + (if (and overrides overrides.into (not= overrides.into form)) + (reform (lume.extend (lume.clear overrides.into) form) overrides) + (do (each [key (pairs form)] + (when (= (. form-preserved-keys key) nil) + (tset form key nil))) + (lume.extend form (or overrides {}))))) + +(fn under [form overrides] (reform form (lume.merge (or overrides {}) {:y (+ form.y (or form.h 0) (or form.ypad 0))}))) +(fn right-of [form overrides] (reform form (lume.merge (or overrides {}) {:x (+ form.x (or form.w 0) (or form.xpad 0))}))) + +(fn group-wrapper [orig-form] + (let [group {} + update-dimension + (fn [form coord-key size-key] + (let [coord-group (. group coord-key) size-group (. group size-key) + coord-form (. form coord-key) size-form (. form size-key)] + (if (= coord-group nil) ; container takes on the size of its first item + (do (tset group coord-key coord-form) + (tset group size-key size-form)) + + (> coord-group coord-form) ; we have an item that is outside the bounds to the left / up; reduce the starting point and extend the size + (do (tset group coord-key coord-form) + (tset group size-key (- (math.max (+ coord-form size-form) (+ coord-group size-group)) coord-form))) + + ; extend the size if the new item is outside the bounds to the right / down + (tset group size-key (- (math.max (+ coord-form size-form) (+ coord-group size-group)) coord-group))) + form)) + update-dimensions (fn [form] (update-dimension form :x :w) (update-dimension form :y :h))] + + (fn [?viewfn-or-form ?form ...] + (match [(type ?viewfn-or-form) ?viewfn-or-form] + [:function viewfn] (let [result [(viewfn ?form ...)]] + (update-dimensions ?form) + (table.unpack result)) + [:table form] (update-dimensions form) + [:nil] (do (lume.extend orig-form group) + (lume.clear group) + orig-form))))) + +(fn horiz-wrapper [{:x orig-x :w orig-w}] + (fn [{: x : y : w : h : xpad : ypad &as form} overrides] + (if (> (+ x (or w 0) xpad (or w 0)) (+ orig-x orig-w)) + (reform form (lume.merge (or overrides {}) {:x orig-x :y (+ y (or h 0) (or ypad 0))})) + (right-of form overrides)))) + +;; widgets and widget helpers +(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 label [form text] + (let [{: x : y : w : h : halign : valign : font : color} + (with-style form + :w #($1.font:get_width text) + :h #($1.font:get_height) + :halign :left + :valign :center) + x (match halign :left x :center (+ x (/ (- w (font:get_width text)) 2)) :right (+ x w (- (font:get_width text)))) + y (match valign :top y :center (+ y (/ (- h (font:get_height)) 2)) :bottom (+ y h (- (font:get_height))))] + (renderer.draw_text font text x y color))) + (fn textbutton [form label] (let [{: x : y : w : h : xpad : ypad : font : color : bg} (with-style form @@ -317,55 +377,8 @@ (set form.h form-dropdown.h) selection)) -(local form-preserved-keys (collect [_ key (ipairs [:view :x :y :font :color :xpad :ypad])] key true)) -(fn reform [form overrides] - (if (and overrides overrides.into (not= overrides.into form)) - (reform (lume.extend (lume.clear overrides.into) form) overrides) - (do (each [key (pairs form)] - (when (= (. form-preserved-keys key) nil) - (tset form key nil))) - (lume.extend form (or overrides {}))))) - -(fn under [form overrides] (reform form (lume.merge (or overrides {}) {:y (+ form.y (or form.h 0) (or form.ypad 0))}))) -(fn right-of [form overrides] (reform form (lume.merge (or overrides {}) {:x (+ form.x (or form.w 0) (or form.xpad 0))}))) - -(fn group-wrapper [orig-form] - (let [group {} - update-dimension - (fn [form coord-key size-key] - (let [coord-group (. group coord-key) size-group (. group size-key) - coord-form (. form coord-key) size-form (. form size-key)] - (if (= coord-group nil) ; container takes on the size of its first item - (do (tset group coord-key coord-form) - (tset group size-key size-form)) - - (> coord-group coord-form) ; we have an item that is outside the bounds to the left / up; reduce the starting point and extend the size - (do (tset group coord-key coord-form) - (tset group size-key (- (math.max (+ coord-form size-form) (+ coord-group size-group)) coord-form))) - - ; extend the size if the new item is outside the bounds to the right / down - (tset group size-key (- (math.max (+ coord-form size-form) (+ coord-group size-group)) coord-group))) - form)) - update-dimensions (fn [form] (update-dimension form :x :w) (update-dimension form :y :h))] - - (fn [?viewfn-or-form ?form ...] - (match [(type ?viewfn-or-form) ?viewfn-or-form] - [:function viewfn] (let [result [(viewfn ?form ...)]] - (update-dimensions ?form) - (table.unpack result)) - [:table form] (update-dimensions form) - [:nil] (do (lume.extend orig-form group) - (lume.clear group) - orig-form))))) - -(fn horiz-wrapper [{:x orig-x :w orig-w}] - (fn [{: x : y : w : h : xpad : ypad &as form} overrides] - (if (> (+ x (or w 0) xpad (or w 0)) (+ orig-x orig-w)) - (reform form (lume.merge (or overrides {}) {:x orig-x :y (+ y (or h 0) (or ypad 0))})) - (right-of form overrides)))) - {: attach-imstate : cmd-predicate : postpone : mouse-inside : activate : active? - : button : checkbox : textbox : textfield : textbutton : dropdown : labelled-dropdown + : button : checkbox : textbox : textfield : textbutton : dropdown : labelled-dropdown : label : reform : under : right-of : horiz-wrapper : group-wrapper : with-style : form-defaults} diff --git a/editor/mapedit.fnl b/editor/mapedit.fnl index ec4d9e6..46430a8 100644 --- a/editor/mapedit.fnl +++ b/editor/mapedit.fnl @@ -231,11 +231,12 @@ (var istep-to-delete nil) (when (not object.steps) (set object.steps [])) (each [istep step (ipairs object.steps)] - (when (textbutton (reform form {:x (+ form.x (* 280 SCALE))}) "X") + (when (textbutton (reform form {:x (+ form.x (* 280 SCALE)) :into {}}) "X") (set istep-to-delete istep)) - (set step.condition (. (dropdown (reform form {:x (+ form.x (* 100 SCALE)) :w (* 100 SCALE) :tag [:code-condition istep]}) (condition-label step.condition) (condition-options)) :flag)) - (set step.action (dropdown (under form {:w (* 100 SCALE) :tag [:code-action istep]}) (or step.action (. actions.actionlist 1)) actions.actionlist)) - (actions.edit (under form {:w (* 300 SCALE)}) istep)) + (set step.condition (. (dropdown (reform form {:x (+ form.x (* 150 SCALE)) :w (* 100 SCALE) :tag [:code-condition istep] :into {}}) (condition-label step.condition) (condition-options)) :flag)) + (set step.action (dropdown (reform form {:w (* 100 SCALE) :tag [:code-action istep]}) (or step.action (. actions.actionlist 1)) actions.actionlist)) + (actions.edit step (under form {:w (* 300 SCALE)}) istep) + (under form)) (when istep-to-delete (table.remove object.steps istep-to-delete)) (when (textbutton (under form) "+ New Step") (table.insert object.steps {})))