📋: Use plists for menus, rather than alists

This commit is contained in:
Jaidyn Ann 2023-07-02 12:40:47 -05:00
parent e26986218b
commit ff129f2d7a
2 changed files with 68 additions and 66 deletions

View File

@ -406,18 +406,20 @@ avoid triggering this."
;;; Main-menu data ;;; Main-menu data
;;; ——————————————————————————————————— ;;; ———————————————————————————————————
(defun submenu () (defun submenu ()
`(((LABEL :en "IDK") (selection . 100) (selected t)) `((:en "IDK"
((LABEL :en "GO BACK") (return . nil)))) :selection 100 :selected t)
(:en "GO BACK"
:return nil)))
(defun main-menu () (defun main-menu ()
`(((LABEL :en "PLAY" :eo "EKLUDI") `((:en "PLAY" :eo "EKLUDI"
(selection . 100) (selected . t) :selection 100 :selected t
(return . ,(🌍:make-overworld-state *casino-map*))) :return ,(🌍:make-overworld-state *casino-map*))
((LABEL :en "SUBMENU" :eo "SUBMENUO") (:en "SUBMENU" :eo "SUBMENUO"
(return . ,(📋:make-menu-state (submenu)))) :return ,(📋:make-menu-state (submenu)))
((LABEL :en "QUIT" :eo "REZIGNI") (:en "QUIT" :eo "REZIGNI"
(return . nil)))) :return nil)))

114
menu.lisp
View File

@ -29,25 +29,25 @@
(📋:menu-state matrix menu-list))) (📋:menu-state matrix menu-list)))
(defun menu-state (matrix menu-alist) (defun menu-state (matrix menu-plist)
"Render a menu in menu-alist format to the given matrix, and process user-input. "Render a menu in menu-plist format to the given matrix, and process user-input.
A state-function for use with the #'state-loop." A state-function for use with the #'state-loop."
(sleep .02) (sleep .02)
(menu-state-draw matrix menu-alist) (menu-state-draw matrix menu-plist)
(menu-state-update menu-alist)) (menu-state-update menu-plist))
(defun menu-state-draw (matrix menu-alist) (defun menu-state-draw (matrix menu-plist)
"Render a menu in menu-alist format to the given matrix. "Render a menu in menu-plist format to the given matrix.
A core part of #'menu-state." A core part of #'menu-state."
(render-menu-strip matrix menu-alist 0 0)) (render-menu-strip matrix menu-plist 0 0))
(defun menu-state-update (menu-alist) (defun menu-state-update (menu-plist)
"Update a menu that is, take user input and modify the menus alist appropriately. "Update a menu that is, take user input and modify the menus plist appropriately.
A core part of #'menu-state." A core part of #'menu-state."
(progress-menu-items menu-alist) (progress-menu-items menu-plist)
(process-menu-input menu-alist)) (process-menu-input menu-plist))
@ -61,7 +61,7 @@ A core part of #'menu-state."
of the box will be displayed as selected/highlighted. This percent is from of the box will be displayed as selected/highlighted. This percent is from
left-to-right, unless negative in which case, right-to-left." left-to-right, unless negative in which case, right-to-left."
(:render-string matrix text (list :x (+ x 1) :y (+ 1 y)) (:render-string matrix text (list :x (+ x 1) :y (+ 1 y))
:width width) ;; (- (+ x width) 1)) :width width)
;; Render the normal top and bottom bars. ;; Render the normal top and bottom bars.
(dotimes (i width) (dotimes (i width)
(setf (aref matrix y (+ x i)) #\-) (setf (aref matrix y (+ x i)) #\-)
@ -90,14 +90,14 @@ left-to-right, unless negative — in which case, right-to-left."
(defun render-menu-strip (matrix items x y &key (max-item-width 12) (height 3)) (defun render-menu-strip (matrix items x y &key (max-item-width 12) (height 3))
"Render several menu items to the matrix, starting at the given x/y coordinates, "Render several menu items to the matrix, starting at the given x/y coordinates,
maximum width for any given item, and the height of all items. maximum width for any given item, and the height of all items.
The item list should be an alist of the following format: The item list should be an plist of the following format:
(((LABEL :en BIRD :eo BIRDO)(SELECTED . T)(SELECTION . 100)) (((LABEL :en BIRD :eo BIRDO)(SELECTED . T)(SELECTION . 100))
((LABEL :en BAR :eo BARO)(SELECTION . -20)) )" ((LABEL :en BAR :eo BARO)(SELECTION . -20)) )"
(let ((x x)) (let ((x x))
(mapcar (mapcar
(lambda (item) (lambda (item)
(let* ((label (:getf-lang (cdr (assoc 'label item)))) (let* ((label (:getf-lang item))
(selection (or (cdr (assoc 'selection item)) (selection (or (getf item :selection)
0)) 0))
(width (:at-most max-item-width (width (:at-most max-item-width
(+ (length label) 2)))) (+ (length label) 2))))
@ -105,7 +105,7 @@ The item list should be an alist of the following format:
:width width :width width
:height height :height height
:selection selection :selection selection
:selected (cdr (assoc 'selected item))) :selected (getf item :selected))
(setf x (+ x width 1)))) (setf x (+ x width 1))))
items)) items))
matrix) matrix)
@ -115,91 +115,91 @@ The item list should be an alist of the following format:
;;; ——————————————————————————————————— ;;; ———————————————————————————————————
;;; Menu logic ;;; Menu logic
;;; ——————————————————————————————————— ;;; ———————————————————————————————————
(defun progress-menu-items (menu-alist) (defun progress-menu-items (menu-plist)
"Given an associative list of menu-items, decrement or increment each "Given an property list of menu-items, decrement or increment each
item's selected-percentage, so that they converge at the right percent. item's selected-percentage, so that they converge at the right percent.
That is, 0 for non-selected items and 100 for selected items." That is, 0 for non-selected items and 100 for selected items."
(mapcar (mapcar
(lambda (item) (lambda (item)
(let* ((selection (assoc 'selection item)) (let* ((selection (or (getf item :selection) 0))
(selection-num (or (cdr selection) 0)) (selectedp (getf item :selected)))
(selectedp (cdr (assoc 'selected item))))
(if selection (if selection
(setf (cdr selection) (setf (getf item :selection)
(gravitate-toward (gravitate-toward
(cond ((and selectedp (< selection-num 0) 0) (cond ((and selectedp (< selection 0) 0)
-100) -100)
(selectedp 100) (selectedp 100)
('t 0)) ('t 0))
(cdr selection) 10))))) selection 10)))))
menu-alist) menu-plist)
menu-alist) menu-plist)
(defun process-menu-input (menu-alist) (defun process-menu-input (menu-plist)
"Get and process any keyboard input, modifying the menu alist as necessary." "Get and process any keyboard input, modifying the menu plist as necessary."
(if (listen) (if (listen)
(let* ((input (:read-gamefied-char-plist)) (let* ((input (:read-gamefied-char-plist))
(selected-item (nth (selected-menu-item-position menu-alist) (selected-item (nth (selected-menu-item-position menu-plist)
menu-alist)) menu-plist))
(func (cdr (assoc 'function selected-item))) (func (getf selected-item :function))
(return-val (assoc 'return selected-item))) (return-val-p (member :return selected-item))
(return-val (getf selected-item :return)))
(case (getf input :semantic) (case (getf input :semantic)
(': (progn (select-right-menu-item menu-alist) (': (progn (select-right-menu-item menu-plist)
't)) 't))
(': (progn (select-left-menu-item menu-alist) (': (progn (select-left-menu-item menu-plist)
't)) 't))
(': (':
nil) nil)
(':🆗 (':🆗
(cond ((and func return-val) (cond ((and func return-val-p)
(apply func '()) (apply func '())
(cdr return-val)) return-val)
(func (func
(apply func '())) (apply func '()))
(return-val (return-val-p
(cdr return-val)) return-val)
('t ('t
't))) 't)))
(otherwise 't))) (otherwise 't)))
't)) 't))
(defun select-menu-item (menu-alist position) (defun select-menu-item (menu-plist position)
"Given a menu associative list, select the menu-item at the given position." "Given a menu property list, select the menu-item at the given position."
(let ((old-position (selected-menu-item-position menu-alist))) (let ((old-position (selected-menu-item-position menu-plist)))
;; The “polarity” (direction of selection) depends on the relative ;; The “polarity” (direction of selection) depends on the relative
;; direction of the previous selection. ;; direction of the previous selection.
(setf (assoc-utils:aget (nth position menu-alist) 'selection) (setf (getf (nth position menu-plist) :selection)
(if (< old-position position) 10 -10)) (if (< old-position position) 10 -10))
(setf (assoc-utils:aget (nth position menu-alist) 'selected) 't) (setf (getf (nth position menu-plist) :selected) 't)
;; Likewise for the previously-selected item. ;; Likewise for the previously-selected item.
(setf (assoc-utils:aget (nth old-position menu-alist) 'selection) (setf (getf (nth old-position menu-plist) :selection)
(if (< old-position position) -90 90)) (if (< old-position position) -90 90))
(setf (assoc-utils:aget (nth old-position menu-alist) 'selected) nil)) (setf (getf (nth old-position menu-plist) :selected) nil))
menu-alist) menu-plist)
(defun select-right-menu-item (menu-alist) (defun select-right-menu-item (menu-plist)
"Select the item to the right of the currenty-selected item." "Select the item to the right of the currenty-selected item."
(let ((new-selection (+ (selected-menu-item-position menu-alist) 1))) (let ((new-selection (+ (selected-menu-item-position menu-plist) 1)))
(if (< new-selection (length menu-alist)) (if (< new-selection (length menu-plist))
(select-menu-item menu-alist new-selection)))) (select-menu-item menu-plist new-selection))))
(defun select-left-menu-item ( menu-alist) (defun select-left-menu-item ( menu-plist)
"Select the item to the left of the currenty-selected item." "Select the item to the left of the currenty-selected item."
(let ((new-selection (- (selected-menu-item-position menu-alist) 1))) (let ((new-selection (- (selected-menu-item-position menu-plist) 1)))
(if (>= new-selection 0) (if (>= new-selection 0)
(select-menu-item menu-alist new-selection)))) (select-menu-item menu-plist new-selection))))
(defun selected-menu-item-position (menu-alist) (defun selected-menu-item-position (menu-plist)
"Returns the index of the menu alist's selected item." "Returns the index of the menu plist's selected item."
(or (position (or (position
't menu-alist 't menu-plist
:test (lambda (ignore list-item) :test (lambda (ignore list-item)
(cdr (assoc 'selected list-item)))) (getf list-item :selected)))
0)) 0))