##// END OF EJS Templates
API call for FOR loop to make the main code less cluttered
API call for FOR loop to make the main code less cluttered

File last commit:

r19:c40f6d7d default
r19:c40f6d7d default
Show More
api.ps
359 lines | 11.1 KiB | application/postscript | PostScriptLexer
100% parser, 100% macros, 50% intrinsics, 10% api, 0% misc
r1
(in-package sugar-qsp)
;;; API deals with DOM manipulation and some bookkeeping for the
;;; intrinsics, namely variables
;;; API is an implementation detail and has no QSP documentation. It
;;; doesn't call intrinsics
(setf (root api) (ps:create))
Tutorial game works!
r6 ;;; Utils
(defm (root api make-act-html) (title img)
(+ "<a class='qsp-act' href='#' onclick='SugarQSP.acts[\"" title "\"].act();'>"
title
"</a>"))
Menu, game saving
r11 (defm (root api make-menu-item-html) (num title img loc)
(+ "<a href='#' onclick='SugarQSP.api.runMenu(" num ", \"" loc "\")();'>"
"<img src='" img "'>"
title
"</a>"))
Some DOM stuff, VIEW
r18 (defm (root api init-dom) ()
;; Save/load buttons
(let ((btn (document.get-element-by-id "qsp-btn-save")))
(setf (ps:@ btn onclick) this.savegame)
(setf (ps:@ btn href) "#"))
(let ((btn (document.get-element-by-id "qsp-btn-open")))
(setf (ps:@ btn onclick) this.opengame)
(setf (ps:@ btn href) "#"))
;; Close image on click
(setf (ps:@ (document.get-element-by-id "qsp-image-container") onclick)
(this.show-image nil))
;; Close the dropdown on any click
(setf window.onclick
(lambda (event)
(setf (ps:@ (api-call get-frame :dropdown) style display) "none"))))
Use flex in html
r10 ;; To be used in saving game
Properly handle stringly-indexed arrays
r16 (defm (root api stash-state) (args)
Use flex in html
r10 (setf (root state-stash)
Menu, game saving
r11 (*j-s-o-n.stringify
(ps:create vars (root vars)
objs (root objs)
Properly handle stringly-indexed arrays
r16 loc-args args
main-html (ps:@
(document.get-element-by-id :qsp-main)
inner-h-t-m-l)
stat-html (ps:@
(document.get-element-by-id :qsp-stat)
inner-h-t-m-l)
Menu, game saving
r11 next-location (root current-location))))
Use flex in html
r10 (values))
Tutorial game works!
r6
Properly handle stringly-indexed arrays
r16 (defm (root api unstash-state) ()
(let ((data (*j-s-o-n.parse (root state-stash))))
(this.clear-act)
(setf (root vars) (ps:@ data vars))
(loop :for k :in (*object.keys (root vars))
:do (*object.set-prototype-of (ps:getprop (root vars) k)
(root api *var prototype)))
(setf (root objs) (ps:@ data objs))
(setf (root current-location) (ps:@ data next-location))
(setf (ps:@ (document.get-element-by-id :qsp-main) inner-h-t-m-l)
(ps:@ data main-html))
(setf (ps:@ (document.get-element-by-id :qsp-stat) inner-h-t-m-l)
(ps:@ data stat-html))
(funcall (root locs (root current-location)) (ps:@ data loc-args))
(this.update-objs)
(values)))
Menu, game saving
r11 (defm (root api state-to-base64) ()
(btoa (encode-u-r-i-component (root state-stash))))
(defm (root api base64-to-state) (data)
Properly handle stringly-indexed arrays
r16 (setf (root state-stash) (decode-u-r-i-component (atob data))))
Menu, game saving
r11
A better UI
r9 ;;; Misc
(defm (root api clear-id) (id)
(setf (ps:chain document (get-element-by-id id) inner-text) ""))
(defm (root api get-id) (id)
Properly handle stringly-indexed arrays
r16 (if (var "USEHTML" 0 :num)
A better UI
r9 (ps:chain (document.get-element-by-id id) inner-h-t-m-l)
(ps:chain (document.get-element-by-id id) inner-text)))
(defm (root api set-id) (id contents)
Properly handle stringly-indexed arrays
r16 (if (var "USEHTML" 0 :num)
A better UI
r9 (setf (ps:chain (document.get-element-by-id id) inner-h-t-m-l) contents)
(setf (ps:chain (document.get-element-by-id id) inner-text) contents)))
(defm (root api append-id) (id contents)
Properly handle stringly-indexed arrays
r16 (if (var "USEHTML" 0 :num)
A better UI
r9 (incf (ps:chain (document.get-element-by-id id) inner-h-t-m-l) contents)
(incf (ps:chain (document.get-element-by-id id) inner-text) contents)))
100% parser, 100% macros, 50% intrinsics, 10% api, 0% misc
r1 ;;; Function calls
(defm (root api init-args) (args)
(dotimes (i (length args))
Properly handle stringly-indexed arrays
r16 (let ((arg (elt args i)))
(if (numberp arg)
(this.set-var args i :num arg)
(this.set-var args i :str arg)))))
100% parser, 100% macros, 50% intrinsics, 10% api, 0% misc
r1
(defm (root api get-result) ()
Properly handle stringly-indexed arrays
r16 (if (not (equal "" (var result 0 :str)))
(var result 0 :str)
(var result 0 :num)))
100% parser, 100% macros, 50% intrinsics, 10% api, 0% misc
r1
;;; Text windows
Tutorial game works!
r6 (defm (root api key-to-id) (key)
(case key
(:main "qsp-main")
(:stat "qsp-stat")
Menu, game saving
r11 (:objs "qsp-objs")
(:acts "qsp-acts")
(:input "qsp-input")
(:dropdown "qsp-dropdown")
Tutorial game works!
r6 (t (report-error "Internal error!"))))
Menu, game saving
r11 (defm (root api get-frame) (key)
A bit shorter call
r15 (document.get-element-by-id (this.key-to-id key)))
Menu, game saving
r11
Tutorial game works!
r6 (defm (root api add-text) (key text)
A bit shorter call
r15 (this.append-id (this.key-to-id key) text))
Tutorial game works!
r6
(defm (root api get-text) (key)
A bit shorter call
r15 (this.get-id (this.key-to-id key)))
Tutorial game works!
r6
(defm (root api clear-text) (key)
A bit shorter call
r15 (this.clear-id (this.key-to-id key)))
Tutorial game works!
r6
(defm (root api newline) (key)
A bit shorter call
r15 (let ((div (this.get-frame key)))
Tutorial game works!
r6 (ps:chain div (append-child (document.create-element "br")))))
100% parser, 100% macros, 50% intrinsics, 10% api, 0% misc
r1
Menu, game saving
r11 (defm (root api enable-frame) (key enable)
A bit shorter call
r15 (let ((clss (ps:getprop (this.get-frame key) 'class-list)))
Menu, game saving
r11 (setf clss.style.display (if enable "block" "none"))
(values)))
100% parser, 100% macros, 50% intrinsics, 10% api, 0% misc
r1 ;;; Actions
Tutorial game works!
r6 (defm (root api add-act) (title img act)
(setf (ps:getprop (root acts) title)
Menu, game saving
r11 (ps:create :img img :act act))
A bit shorter call
r15 (this.update-acts))
Tutorial game works!
r6
(defm (root api del-act) (title)
(delete (ps:getprop (root acts) title))
A bit shorter call
r15 (this.update-acts))
Tutorial game works!
r6
(defm (root api clear-act) ()
(setf (root acts) (ps:create))
A bit shorter call
r15 (this.clear-id "qsp-acts"))
Tutorial game works!
r6
(defm (root api update-acts) ()
A bit shorter call
r15 (this.clear-id "qsp-acts")
Tutorial game works!
r6 (ps:for-in (title (root acts))
(let ((obj (ps:getprop (root acts) title)))
A bit shorter call
r15 (this.append-id "qsp-acts"
(this.make-act-html title (ps:getprop obj :img))))))
100% parser, 100% macros, 50% intrinsics, 10% api, 0% misc
r1
API call for FOR loop to make the main code less cluttered
r19 ;;; "Syntax"
(defm (root api qspfor) (name index from to step body)
(block nil
(ps:for ((i from))
((< i to))
((incf i step))
(this.set-var name index :num i)
(unless (funcall body)
(return)))))
Properly handle stringly-indexed arrays
r16 ;;; Variable class
(defm (root api *var) (name)
;; From strings to numbers
(setf this.indexes (ps:create))
;; From numbers to {num: 0, str: ""} objects
(setf this.values (list))
(values))
(defm (root api *var prototype new-value) ()
(ps:create :num 0 :str ""))
100% parser, 100% macros, 50% intrinsics, 10% api, 0% misc
r1
Properly handle stringly-indexed arrays
r16 (defm (root api *var prototype index-num) (index)
(let ((num-index
(if (stringp index)
(if (in index this.indexes)
(ps:getprop this.indexes index)
(let ((n (length this.values)))
(setf (ps:getprop this.indexes index) n)
n))
index)))
(unless (in num-index this.values)
(setf (elt this.values num-index) (this.new-value)))
num-index))
(defm (root api *var prototype get) (index slot)
(unless (or index (= 0 index))
(setf index (1- (length this.values))))
(ps:getprop this.values (this.index-num index) slot))
(defm (root api *var prototype set) (index slot value)
(unless (or index (= 0 index))
(setf index (length store)))
(case slot
(:num (setf value (ps:chain *number (parse-int value))))
(:str (setf value (ps:chain value (to-string)))))
(setf (ps:getprop this.values (this.index-num index) slot) value)
(values))
(defm (root api *var prototype kill) (index)
(setf (elt this.values (this.index-num index)) (this.new-value)))
;;; Variables
Tutorial game works!
r6
(defm (root api var-real-name) (name)
(if (= (ps:@ name 0) #\$)
Properly handle stringly-indexed arrays
r16 (values (ps:chain name (substr 1)) :str)
(values name :num)))
Tutorial game works!
r6
Properly handle stringly-indexed arrays
r16 (defm (root api ensure-var) (name)
A bit shorter call
r15 (let ((store (this.var-ref name)))
Locals
r14 (unless store
Properly handle stringly-indexed arrays
r16 (setf store (ps:new (this.-var name)))
(setf (ps:getprop (root vars) name) store))
store))
Tutorial game works!
r6
Locals
r14 (defm (root api var-ref) (name)
Properly handle stringly-indexed arrays
r16 (let ((local-store (this.current-local-frame)))
(cond ((in name local-store)
(ps:getprop local-store name))
((in name (root vars))
(ps:getprop (root vars) name))
Locals
r14 (t nil))))
Properly handle stringly-indexed arrays
r16 (defm (root api get-var) (name index slot)
(ps:chain (this.ensure-var name) (get index slot)))
Tutorial game works!
r6
Properly handle stringly-indexed arrays
r16 (defm (root api set-var) (name index slot value)
(ps:chain (this.ensure-var name) (set index slot value))
(values))
Tutorial game works!
r6
Locals
r14 (defm (root api get-array) (name)
Properly handle stringly-indexed arrays
r16 (this.var-ref name))
Menu, game saving
r11
Locals
r14 (defm (root api set-array) (name value)
Properly handle stringly-indexed arrays
r16 (let ((store (this.var-ref name)))
(setf (ps:@ store values) (ps:@ value values))
(setf (ps:@ store indexes) (ps:@ value indexes)))
(values))
Locals
r14
(defm (root api kill-var) (name &optional index)
Properly handle stringly-indexed arrays
r16 (if (and index (not (= 0 index)))
(ps:chain (ps:getprop (root vars) name) (kill index))
Locals
r14 (ps:delete (ps:getprop (root vars) name)))
Tutorial game works!
r6 (values))
Menu, game saving
r11 (defm (root api array-size) (name)
Properly handle stringly-indexed arrays
r16 (ps:getprop (this.var-ref name) 'length))
;;; Locals
(defm (root api push-local-frame) ()
(ps:chain (root locals) (push (ps:create)))
(values))
(defm (root api pop-local-frame) ()
(ps:chain (root locals) (pop))
(values))
(defm (root api current-local-frame) ()
(elt (root locals) (1- (length (root locals)))))
(defm (root api new-local) (name)
(let ((frame (this.current-local-frame)))
(unless (in name frame)
(setf (ps:getprop frame name) (ps:create)))
(values)))
Menu, game saving
r11
Tutorial game works!
r6 ;;; Objects
(defm (root api update-objs) ()
(let ((elt (document.get-element-by-id "qsp-objs")))
(setf elt.inner-h-t-m-l "<ul>")
(loop :for obj :in (root objs)
:do (incf elt.inner-h-t-m-l (+ "<li>" obj)))
(incf elt.inner-h-t-m-l "</ul>")))
Menu, game saving
r11
;;; Menu
(defm (root api menu) (menu-data)
(let ((elt (document.get-element-by-id "qsp-dropdown"))
(i 0))
(setf elt.inner-h-t-m-l "")
(loop :for item :in menu-data
:do (incf i)
A bit shorter call
r15 :do (incf elt.inner-h-t-m-l (this.make-menu-item-html i item.text item.icon item.loc)))
Menu, game saving
r11 (setf elt.style.display "block")))
Sounds, save/load UI buttons
r12
;;; Content
(defm (root api clean-audio) ()
(loop :for k :in (*object.keys (root playing))
:for v := (ps:getprop (root playing) k)
:do (when (ps:@ v ended)
(ps:delete (ps:@ (root playing) k)))))
Locals
r14
Some DOM stuff, VIEW
r18 (defm (root api show-image) (path)
(let ((img (document.get-element-by-id "qsp-image")))
(cond (path
(setf img.src path)
(setf img.style.display "flex"))
(t
(setf img.src "")
(setf img.style.display "hidden")))))
;;; Saves
(defm (root api opengame) ()
(let ((element (document.create-element :input)))
(element.set-attribute :type :file)
(element.set-attribute :id :qsp-opengame)
(element.set-attribute :tabindex -1)
(element.set-attribute "aria-hidden" t)
(setf element.style.display :block)
(setf element.style.visibility :hidden)
(setf element.style.position :fixed)
(setf element.onchange
(lambda (event)
(let* ((file (elt event.target.files 0))
(reader (ps:new (*file-reader))))
(setf reader.onload
(lambda (ev)
(block nil
(let ((target ev.current-target))
(unless target.result
(return))
(api-call base64-to-state target.result)
(api-call unstash-state)))))
(reader.read-as-text file))))
(document.body.append-child element)
(element.click)
(document.body.remove-child element)))
(defm (root api savegame) ()
(let ((element (document.create-element :a)))
(element.set-attribute :href (+ "data:text/plain;charset=utf-8," (api-call state-to-base64)))
(element.set-attribute :download "savegame.sav")
(setf element.style.display :none)
(document.body.append-child element)
(element.click)
(document.body.remove-child element)))