##// END OF EJS Templates
Bugfixes
naryl -
r22:d1c8a2bd default
parent child Browse files
Show More
@@ -1,11 +1,15 b''
1 1
2 * Remove cl-uglify-js (no support for ES6 at all and no way to monkey-patch it reliably)
3 * Use Parenscript's async/await
4 * Use Parenscript's minifier
5 * WAIT and MENU with async/await
2 6 * Special locations
3 7 * Special variables
4 8 * CLI build for Linux
5 9 * CLI build for Windows
6 10
7 11 * Build Istreblenie
8 12 * Windows GUI (for the compiler)
9 13 * Save-load game in slots
10 14 * Resizable frames
11 ** modifying it to suit compiler specifics No newline at end of file
15 ** modifying it to suit compiler specifics
@@ -1,387 +1,390 b''
1 1
2 2 (in-package sugar-qsp)
3 3
4 4 ;;; API deals with DOM manipulation and some bookkeeping for the
5 5 ;;; intrinsics, namely variables
6 6 ;;; API is an implementation detail and has no QSP documentation. It
7 7 ;;; doesn't call intrinsics
8 8
9 9 (setf (root api) (ps:create))
10 10
11 11 ;;; Utils
12 12
13 13 (defm (root api make-act-html) (title img)
14 14 (+ "<a class='qsp-act' href='#' onclick='SugarQSP.acts[\"" title "\"].act();'>"
15 15 title
16 16 "</a>"))
17 17
18 18 (defm (root api make-menu-item-html) (num title img loc)
19 19 (+ "<a href='#' onclick='SugarQSP.api.runMenu(" num ", \"" loc "\")();'>"
20 20 "<img src='" img "'>"
21 21 title
22 22 "</a>"))
23 23
24 24 (defm (root api report-error) (text)
25 25 (alert text))
26 26
27 27 (defm (root api init-dom) ()
28 28 ;; Save/load buttons
29 29 (let ((btn (document.get-element-by-id "qsp-btn-save")))
30 30 (setf (ps:@ btn onclick) this.savegame)
31 31 (setf (ps:@ btn href) "#"))
32 32 (let ((btn (document.get-element-by-id "qsp-btn-open")))
33 33 (setf (ps:@ btn onclick) this.opengame)
34 34 (setf (ps:@ btn href) "#"))
35 35 ;; Close image on click
36 36 (setf (ps:@ (document.get-element-by-id "qsp-image-container") onclick)
37 37 (this.show-image nil))
38 38 ;; Close the dropdown on any click
39 39 (setf window.onclick
40 40 (lambda (event)
41 41 (setf (ps:@ (api-call get-frame :dropdown) style display) "none"))))
42 42
43 43 (defm (root api call-serv-loc) (var-name &rest args)
44 44 (let ((loc-name (api-call get-var name 0 :str)))
45 45 (when loc-name
46 46 (let ((loc (ps:getprop (root locs) loc-name)))
47 47 (when loc
48 48 (funcall loc args))))))
49 49
50 50 ;;; Misc
51 51
52 (defm (root api newline) (key)
53 (this.append-id (this.key-to-id key) "<br>" t))
54
52 55 (defm (root api clear-id) (id)
53 (setf (ps:chain document (get-element-by-id id) inner-text) ""))
56 (setf (ps:chain document (get-element-by-id id) inner-h-t-m-l) ""))
57
58 (setf (root api text-escaper) (document.create-element :textarea))
59
60 (defm (root api prepare-contents) (s &optional force-html)
61 (if (or force-html (var "USEHTML" 0 :num))
62 s
63 (progn
64 (setf (ps:@ (root api text-escaper) text-content) s)
65 (ps:@ (root api text-escaper) inner-h-t-m-l))))
54 66
55 67 (defm (root api get-id) (id &optional force-html)
56 (if (or force-html (var "USEHTML" 0 :num))
57 (ps:chain (document.get-element-by-id id) inner-h-t-m-l)
58 (ps:chain (document.get-element-by-id id) inner-text)))
68 (ps:chain (document.get-element-by-id id) inner-h-t-m-l))
59 69
60 70 (defm (root api set-id) (id contents &optional force-html)
61 (if (or force-html (var "USEHTML" 0 :num))
62 (setf (ps:chain (document.get-element-by-id id) inner-h-t-m-l) contents)
63 (setf (ps:chain (document.get-element-by-id id) inner-text) contents)))
71 (setf (ps:chain (document.get-element-by-id id) inner-h-t-m-l) (this.prepare-contents contents force-html)))
64 72
65 73 (defm (root api append-id) (id contents &optional force-html)
66 (if (or force-html (var "USEHTML" 0 :num))
67 (incf (ps:chain (document.get-element-by-id id) inner-h-t-m-l) contents)
68 (incf (ps:chain (document.get-element-by-id id) inner-text) contents)))
74 (when contents
75 (incf (ps:chain (document.get-element-by-id id) inner-h-t-m-l) (this.prepare-contents contents force-html))))
69 76
70 77 ;;; Function calls
71 78
72 79 (defm (root api init-args) (args)
73 80 (dotimes (i (length args))
74 81 (let ((arg (elt args i)))
75 82 (if (numberp arg)
76 83 (this.set-var args i :num arg)
77 84 (this.set-var args i :str arg)))))
78 85
79 86 (defm (root api get-result) ()
80 87 (if (not (equal "" (var result 0 :str)))
81 88 (var result 0 :str)
82 89 (var result 0 :num)))
83 90
84 91 (defm (root api call-loc) (name args)
85 92 (funcall (ps:getprop (root locs) name) args))
86 93
87 94 ;;; Text windows
88 95
89 96 (defm (root api key-to-id) (key)
90 97 (case key
91 98 (:main "qsp-main")
92 99 (:stat "qsp-stat")
93 100 (:objs "qsp-objs")
94 101 (:acts "qsp-acts")
95 102 (:input "qsp-input")
96 103 (:dropdown "qsp-dropdown")
97 104 (t (this.report-error "Internal error!"))))
98 105
99 106 (defm (root api get-frame) (key)
100 107 (document.get-element-by-id (this.key-to-id key)))
101 108
102 109 (defm (root api add-text) (key text)
103 110 (this.append-id (this.key-to-id key) text))
104 111
105 112 (defm (root api get-text) (key)
106 113 (this.get-id (this.key-to-id key)))
107 114
108 115 (defm (root api clear-text) (key)
109 116 (this.clear-id (this.key-to-id key)))
110 117
111 (defm (root api newline) (key)
112 (let ((div (this.get-frame key)))
113 (ps:chain div (append-child (document.create-element "br")))))
114
115 118 (defm (root api enable-frame) (key enable)
116 119 (let ((obj (this.get-frame key)))
117 120 (setf obj.style.display (if enable "block" "none"))
118 121 (values)))
119 122
120 123 ;;; Actions
121 124
122 125 (defm (root api add-act) (title img act)
123 126 (setf (ps:getprop (root acts) title)
124 127 (ps:create :img img :act act))
125 128 (this.update-acts))
126 129
127 130 (defm (root api del-act) (title)
128 131 (delete (ps:getprop (root acts) title))
129 132 (this.update-acts))
130 133
131 134 (defm (root api clear-act) ()
132 135 (setf (root acts) (ps:create))
133 136 (this.clear-id "qsp-acts"))
134 137
135 138 (defm (root api update-acts) ()
136 139 (this.clear-id "qsp-acts")
137 140 (let ((elt (document.get-element-by-id "qsp-acts")))
138 141 (ps:for-in (title (root acts))
139 142 (let ((obj (ps:getprop (root acts) title)))
140 143 (incf elt.inner-h-t-m-l (this.make-act-html title (ps:getprop obj :img)))))))
141 144
142 145
143 146 ;;; "Syntax"
144 147
145 148 (defm (root api qspfor) (name index from to step body)
146 149 (block nil
147 150 (ps:for ((i from))
148 151 ((< i to))
149 152 ((incf i step))
150 153 (this.set-var name index :num i)
151 154 (unless (funcall body)
152 155 (return)))))
153 156
154 157 ;;; Variable class
155 158
156 159 (defm (root api *var) (name)
157 160 ;; From strings to numbers
158 161 (setf this.indexes (ps:create))
159 162 ;; From numbers to {num: 0, str: ""} objects
160 163 (setf this.values (list))
161 164 (values))
162 165
163 166 (defm (root api *var prototype new-value) ()
164 167 (ps:create :num 0 :str ""))
165 168
166 169 (defm (root api *var prototype index-num) (index)
167 170 (let ((num-index
168 171 (if (stringp index)
169 172 (if (in index this.indexes)
170 173 (ps:getprop this.indexes index)
171 174 (let ((n (length this.values)))
172 175 (setf (ps:getprop this.indexes index) n)
173 176 n))
174 177 index)))
175 178 (unless (in num-index this.values)
176 179 (setf (elt this.values num-index) (this.new-value)))
177 180 num-index))
178 181
179 182 (defm (root api *var prototype get) (index slot)
180 183 (unless (or index (= 0 index))
181 184 (setf index (1- (length this.values))))
182 185 (ps:getprop this.values (this.index-num index) slot))
183 186
184 187 (defm (root api *var prototype set) (index slot value)
185 188 (unless (or index (= 0 index))
186 189 (setf index (length store)))
187 190 (case slot
188 191 (:num (setf value (ps:chain *number (parse-int value))))
189 192 (:str (setf value (ps:chain value (to-string)))))
190 193 (setf (ps:getprop this.values (this.index-num index) slot) value)
191 194 (values))
192 195
193 196 (defm (root api *var prototype kill) (index)
194 197 (setf (elt this.values (this.index-num index)) (this.new-value)))
195 198
196 199 ;;; Variables
197 200
198 201 (defm (root api var-real-name) (name)
199 202 (if (= (ps:@ name 0) #\$)
200 203 (values (ps:chain name (substr 1)) :str)
201 204 (values name :num)))
202 205
203 206 (defm (root api ensure-var) (name)
204 207 (let ((store (this.var-ref name)))
205 208 (unless store
206 209 (setf store (ps:new (this.-var name)))
207 210 (setf (ps:getprop (root vars) name) store))
208 211 store))
209 212
210 213 (defm (root api var-ref) (name)
211 214 (let ((local-store (this.current-local-frame)))
212 215 (cond ((and local-store (in name local-store))
213 216 (ps:getprop local-store name))
214 217 ((in name (root vars))
215 218 (ps:getprop (root vars) name))
216 219 (t nil))))
217 220
218 221 (defm (root api get-var) (name index slot)
219 222 (ps:chain (this.ensure-var name) (get index slot)))
220 223
221 224 (defm (root api set-var) (name index slot value)
222 225 (ps:chain (this.ensure-var name) (set index slot value))
223 226 (values))
224 227
225 228 (defm (root api get-array) (name)
226 229 (this.var-ref name))
227 230
228 231 (defm (root api set-array) (name value)
229 232 (let ((store (this.var-ref name)))
230 233 (setf (ps:@ store values) (ps:@ value values))
231 234 (setf (ps:@ store indexes) (ps:@ value indexes)))
232 235 (values))
233 236
234 237 (defm (root api kill-var) (name &optional index)
235 238 (if (and index (not (= 0 index)))
236 239 (ps:chain (ps:getprop (root vars) name) (kill index))
237 240 (ps:delete (ps:getprop (root vars) name)))
238 241 (values))
239 242
240 243 (defm (root api array-size) (name)
241 244 (ps:getprop (this.var-ref name) 'length))
242 245
243 246 ;;; Locals
244 247
245 248 (defm (root api push-local-frame) ()
246 249 (ps:chain (root locals) (push (ps:create)))
247 250 (values))
248 251
249 252 (defm (root api pop-local-frame) ()
250 253 (ps:chain (root locals) (pop))
251 254 (values))
252 255
253 256 (defm (root api current-local-frame) ()
254 257 (elt (root locals) (1- (length (root locals)))))
255 258
256 259 (defm (root api new-local) (name)
257 260 (let ((frame (this.current-local-frame)))
258 261 (unless (in name frame)
259 262 (setf (ps:getprop frame name) (ps:create)))
260 263 (values)))
261 264
262 265 ;;; Objects
263 266
264 267 (defm (root api update-objs) ()
265 268 (let ((elt (document.get-element-by-id "qsp-objs")))
266 269 (setf elt.inner-h-t-m-l "<ul>")
267 270 (loop :for obj :in (root objs)
268 271 :do (incf elt.inner-h-t-m-l (+ "<li>" obj)))
269 272 (incf elt.inner-h-t-m-l "</ul>")))
270 273
271 274 ;;; Menu
272 275
273 276 (defm (root api menu) (menu-data)
274 277 (let ((elt (document.get-element-by-id "qsp-dropdown"))
275 278 (i 0))
276 279 (setf elt.inner-h-t-m-l "")
277 280 (loop :for item :in menu-data
278 281 :do (incf i)
279 282 :do (incf elt.inner-h-t-m-l (this.make-menu-item-html i item.text item.icon item.loc)))
280 283 (setf elt.style.display "block")))
281 284
282 285 ;;; Content
283 286
284 287 (defm (root api clean-audio) ()
285 288 (loop :for k :in (*object.keys (root playing))
286 289 :for v := (ps:getprop (root playing) k)
287 290 :do (when (ps:@ v ended)
288 291 (ps:delete (ps:@ (root playing) k)))))
289 292
290 293 (defm (root api show-image) (path)
291 294 (let ((img (document.get-element-by-id "qsp-image")))
292 295 (cond (path
293 296 (setf img.src path)
294 297 (setf img.style.display "flex"))
295 298 (t
296 299 (setf img.src "")
297 300 (setf img.style.display "hidden")))))
298 301
299 302 ;;; Saves
300 303
301 304 (defm (root api opengame) ()
302 305 (let ((element (document.create-element :input)))
303 306 (element.set-attribute :type :file)
304 307 (element.set-attribute :id :qsp-opengame)
305 308 (element.set-attribute :tabindex -1)
306 309 (element.set-attribute "aria-hidden" t)
307 310 (setf element.style.display :block)
308 311 (setf element.style.visibility :hidden)
309 312 (setf element.style.position :fixed)
310 313 (setf element.onchange
311 314 (lambda (event)
312 315 (let* ((file (elt event.target.files 0))
313 316 (reader (ps:new (*file-reader))))
314 317 (setf reader.onload
315 318 (lambda (ev)
316 319 (block nil
317 320 (let ((target ev.current-target))
318 321 (unless target.result
319 322 (return))
320 323 (api-call base64-to-state target.result)
321 324 (api-call unstash-state)))))
322 325 (reader.read-as-text file))))
323 326 (document.body.append-child element)
324 327 (element.click)
325 328 (document.body.remove-child element)))
326 329
327 330 (defm (root api savegame) ()
328 331 (let ((element (document.create-element :a)))
329 332 (element.set-attribute :href (+ "data:text/plain;charset=utf-8," (api-call state-to-base64)))
330 333 (element.set-attribute :download "savegame.sav")
331 334 (setf element.style.display :none)
332 335 (document.body.append-child element)
333 336 (element.click)
334 337 (document.body.remove-child element)))
335 338
336 339 (defm (root api stash-state) (args)
337 340 (api-call call-serv-loc "ONGSAVE")
338 341 (setf (root state-stash)
339 342 (*j-s-o-n.stringify
340 343 (ps:create vars (root vars)
341 344 objs (root objs)
342 345 loc-args args
343 346 msecs (- (*date.now) (root started-at))
344 347 main-html (ps:@
345 348 (document.get-element-by-id :qsp-main)
346 349 inner-h-t-m-l)
347 350 stat-html (ps:@
348 351 (document.get-element-by-id :qsp-stat)
349 352 inner-h-t-m-l)
350 353 next-location (root current-location))))
351 354 (values))
352 355
353 356 (defm (root api unstash-state) ()
354 357 (let ((data (*j-s-o-n.parse (root state-stash))))
355 358 (this.clear-act)
356 359 (setf (root vars) (ps:@ data vars))
357 360 (loop :for k :in (*object.keys (root vars))
358 361 :do (*object.set-prototype-of (ps:getprop (root vars) k)
359 362 (root api *var prototype)))
360 363 (setf (root started-at) (- (*date.now) (ps:@ data msecs)))
361 364 (setf (root objs) (ps:@ data objs))
362 365 (setf (root current-location) (ps:@ data next-location))
363 366 (setf (ps:@ (document.get-element-by-id :qsp-main) inner-h-t-m-l)
364 367 (ps:@ data main-html))
365 368 (setf (ps:@ (document.get-element-by-id :qsp-stat) inner-h-t-m-l)
366 369 (ps:@ data stat-html))
367 370 (this.update-objs)
368 371 (api-call call-serv-loc "ONGLOAD")
369 372 (api-call call-loc (root current-location) (ps:@ data loc-args))
370 373 (values)))
371 374
372 375 (defm (root api state-to-base64) ()
373 376 (btoa (encode-u-r-i-component (root state-stash))))
374 377
375 378 (defm (root api base64-to-state) (data)
376 379 (setf (root state-stash) (decode-u-r-i-component (atob data))))
377 380
378 381 ;;; Timers
379 382
380 383 (defm (root api set-timer) (interval)
381 384 (setf (root timer-interval) interval)
382 385 (clear-interval (root timer-obj))
383 386 (setf (root timer-obj)
384 387 (set-interval
385 388 (lambda ()
386 389 (api-call call-serv-loc "COUNTER"))
387 390 interval)))
@@ -1,302 +1,307 b''
1 1
2 2 (in-package sugar-qsp)
3 3
4 4 ;;;; Functions and procedures defined by the QSP language.
5 5 ;;;; They can call api and deal with locations and other data directly.
6 6 ;;;; Except vars. Use VAR and SET or GET-VAR and SET-VAR api calls.
7 7
8 8 (setf (root lib) (ps:create))
9 9
10 10 ;;; 1loc
11 11
12 12 (defm (root lib goto) (target args)
13 13 (api-call clear-text :main)
14 14 (funcall (root lib xgoto) target (or args (list)))
15 15 (values))
16 16
17 17 (defm (root lib xgoto) (target args)
18 18 (api-call clear-act)
19 19 (setf (root current-location) (ps:chain target (to-upper-case)))
20 20 (api-call stash-state args)
21 21 (funcall (ps:getprop (root locs) (root current-location))
22 22 (or args (list)))
23 23 (values))
24 24
25 25 ;;; 2var
26 26
27 27 ;;; 3expr
28 28
29 29 ;;; 4code
30 30
31 31 (defm (root lib rand) (a &optional (b 1))
32 32 (let ((min (min a b))
33 33 (max (max a b)))
34 34 (+ min (ps:chain *math (random (- max min))))))
35 35
36 36 ;;; 5arrays
37 37
38 38 (defm (root lib copyarr) (to from start count)
39 39 (multiple-value-bind (to-name to-slot)
40 40 (api-call var-real-name to)
41 41 (multiple-value-bind (from-name from-slot)
42 42 (api-call var-real-name from)
43 43 (ps:for ((i start))
44 44 ((< i (min (api-call array-size from-name)
45 45 (+ start count))))
46 46 ((incf i))
47 47 (api-call set-var to-name (+ start i) to-slot
48 48 (api-call get-var from-name (+ start i) from-slot))))))
49 49
50 50 (defm (root lib arrpos) (name value &optional (start 0))
51 51 (multiple-value-bind (real-name slot)
52 52 (api-call var-real-name name)
53 53 (ps:for ((i start)) ((< i (api-call array-size name))) ((incf i))
54 54 (when (eq (api-call get-var real-name i slot) value)
55 55 (return i))))
56 56 -1)
57 57
58 58 (defm (root lib arrcomp) (name pattern &optional (start 0))
59 59 (multiple-value-bind (real-name slot)
60 60 (api-call var-real-name name)
61 61 (ps:for ((i start)) ((< i (api-call array-size name))) ((incf i))
62 62 (when (funcall (ps:getprop (api-call get-var real-name i slot) 'match) pattern)
63 63 (return i))))
64 64 -1)
65 65
66 66 ;;; 6str
67 67
68 68 (defm (root lib instr) (s subs &optional (start 1))
69 69 (+ start (ps:chain s (substring (- start 1)) (search subs))))
70 70
71 71 (defm (root lib isnum) (s)
72 72 (if (is-na-n s)
73 73 0
74 74 -1))
75 75
76 76 (defm (root lib strcomp) (s pattern)
77 77 (if (s.match pattern)
78 78 -1
79 79 0))
80 80
81 81 (defm (root lib strfind) (s pattern group)
82 82 (let* ((re (ps:new (*reg-exp pattern)))
83 83 (match (re.exec s)))
84 84 (match.group group)))
85 85
86 86 (defm (root lib strpos) (s pattern &optional (group 0))
87 87 (let* ((re (ps:new (*reg-exp pattern)))
88 88 (match (re.exec s))
89 89 (found (match.group group)))
90 90 (if found
91 91 (s.search found)
92 92 0)))
93 93
94 94 ;;; 7if
95 95
96 96 ;; Has to be a function because it always evaluates all three of its
97 97 ;; arguments
98 98 (defm (root lib iif) (cond-expr then-expr else-expr)
99 99 (if cond-expr then-expr else-expr))
100 100
101 101 ;;; 8sub
102 102
103 103 (defm (root lib gosub) (target &rest args)
104 104 (funcall (ps:getprop (root locs) target) args)
105 105 (values))
106 106
107 107 (defm (root lib func) (target &rest args)
108 108 (funcall (ps:getprop (root locs) target) args))
109 109
110 110 ;;; 9loops
111 111
112 112 ;;; 10dynamic
113 113
114 114 (defm (root lib dynamic) (block &rest args)
115 115 (when (stringp block)
116 116 (api-call report-error "DYNAMIC can't evaluate arbitrary strings.\nUse {braces} to create blocks for DYNAMIC."))
117 117 (funcall block args)
118 118 (values))
119 119
120 120 (defm (root lib dyneval) (block &rest args)
121 121 (when (stringp block)
122 122 (api-call report-error "DYNEVAL can't evaluate arbitrary strings.\nUse {braces} to create blocks for DYNEVAL."))
123 123 (funcall block args))
124 124
125 125 ;;; 11main
126 126
127 127 (defm (root lib main-p) (s)
128 128 (api-call add-text :main s)
129 129 (values))
130 130
131 131 (defm (root lib main-pl) (s)
132 132 (api-call add-text :main s)
133 133 (api-call newline :main)
134 134 (values))
135 135
136 136 (defm (root lib main-nl) (s)
137 137 (api-call newline :main)
138 138 (api-call add-text :main s)
139 139 (values))
140 140
141 141 (defm (root lib maintxt) (s)
142 142 (api-call get-text :main)
143 143 (values))
144 144
145 145 ;; For clarity (it leaves a lib.desc() call in JS)
146 146 (defm (root lib desc) (s)
147 147 "")
148 148
149 149 (defm (root lib main-clear) ()
150 150 (api-call clear-text :main)
151 151 (values))
152 152
153 153 ;;; 12stat
154 154
155 155 (defm (root lib stat-p) (s)
156 156 (api-call add-text :stat s)
157 157 (values))
158 158
159 159 (defm (root lib stat-pl) (s)
160 160 (api-call add-text :stat s)
161 161 (api-call newline :stat)
162 162 (values))
163 163
164 164 (defm (root lib stat-nl) (s)
165 165 (api-call newline :stat)
166 166 (api-call add-text :stat s)
167 167 (values))
168 168
169 169 (defm (root lib stattxt) (s)
170 170 (api-call get-text :stat)
171 171 (values))
172 172
173 173 (defm (root lib stat-clear) ()
174 174 (api-call clear-text :stat)
175 175 (values))
176 176
177 177 (defm (root lib cls) ()
178 178 (funcall (root lib stat-clear))
179 179 (funcall (root lib main-clear))
180 180 (funcall (root lib cla))
181 181 (funcall (root lib cmdclear))
182 182 (values))
183 183
184 184 ;;; 13diag
185 185
186 186 ;;; 14act
187 187
188 188 (defm (root lib curacts) ()
189 189 (let ((acts (root acts)))
190 190 (lambda ()
191 191 (setf (root acts) acts)
192 192 (values))))
193 193
194 194 ;;; 15objs
195 195
196 196 (defm (root lib addobj) (name)
197 197 (ps:chain (root objs) (push name))
198 198 (api-call update-objs)
199 199 (values))
200 200
201 201 (defm (root lib delobj) (name)
202 202 (let ((index (ps:chain (root objs) (index-of name))))
203 203 (when (> index -1)
204 204 (funcall (root lib killobj) (1+ index))))
205 205 (values))
206 206
207 207 (defm (root lib killobj) (&optional (num nil))
208 208 (if (eq nil num)
209 209 (setf (root objs) (list))
210 210 (ps:chain (root objs) (splice (1- num) 1)))
211 211 (api-call update-objs)
212 212 (values))
213 213
214 214 ;;; 16menu
215 215
216 216 (defm (root lib menu) (menu-name)
217 217 (let ((menu-data (list)))
218 218 (loop :for item :in (api-call get-array (api-call var-real-name menu-name))
219 219 :do (cond ((string= item "")
220 220 (break))
221 221 ((string= item "-:-")
222 222 (ps:chain menu-data (push :delimiter)))
223 223 (t
224 224 (let* ((tokens (ps:chain item (split ":"))))
225 225 (when (= (length tokens) 2)
226 226 (tokens.push ""))
227 227 (let* ((text (ps:chain tokens (splice 0 (- tokens.length 2)) (join ":")))
228 228 (loc (ps:getprop tokens (- tokens.length 2)))
229 229 (icon (ps:getprop tokens (- tokens.length 1))))
230 230 (ps:chain menu-data
231 231 (push (ps:create text text
232 232 loc loc
233 233 icon icon))))))))
234 234 (api-call menu menu-data)
235 235 (values)))
236 236
237 237 ;;; 17sound
238 238
239 239 (defm (root lib play) (filename &optional (volume 100))
240 240 (let ((audio (ps:new (*audio filename))))
241 241 (setf (ps:getprop (root playing) filename) audio)
242 242 (setf (ps:@ audio volume) (* volume 0.01))
243 243 (ps:chain audio (play))))
244 244
245 245 (defm (root lib close) (filename)
246 246 (funcall (root playing filename) stop)
247 247 (ps:delete (root playing filename)))
248 248
249 249 (defm (root lib closeall) ()
250 250 (loop :for k :in (*object.keys (root playing))
251 251 :for v := (ps:getprop (root playing) k)
252 252 :do (funcall v stop))
253 253 (setf (root playing) (ps:create)))
254 254
255 255 ;;; 18img
256 256
257 257 (defm (root lib refint) ()
258 258 ;; "Force interface update" Uh... what exactly do we do here?
259 259 (api-call report-error "REFINT is not supported")
260 260 )
261 261
262 262 ;;; 19input
263 263
264 264 (defm (root lib usertxt) ()
265 265 (let ((input (document.get-element-by-id "qsp-input")))
266 266 (ps:@ input value)))
267 267
268 268 (defm (root lib cmdclear) ()
269 269 (let ((input (document.get-element-by-id "qsp-input")))
270 270 (setf (ps:@ input value) "")))
271 271
272 272 (defm (root lib input) (text)
273 273 (window.prompt text))
274 274
275 275 ;;; 20time
276 276
277 277 ;; I wonder if there's a better solution than busy-wait
278 278 (defm (root lib wait) (msec)
279 279 (let* ((now (ps:new (*date)))
280 280 (exit-time (+ (funcall now.get-time) msec)))
281 281 (loop :while (< (funcall now.get-time) exit-time))))
282 282
283 283 (defm (root lib msecscount) ()
284 284 (- (*date.now) (root started-at)))
285 285
286 286 ;;; 21local
287 287
288 288 ;;; 22for
289 289
290 290 ;;; misc
291 291
292 (defm (root lib rgb) ()
293 (api-call report-error "RGB is not implemented."))
292 (defm (root lib rgb) (red green blue)
293 (flet ((rgb-to-hex (comp)
294 (let ((hex (ps:chain (*number comp) (to-string 16))))
295 (if (< (length hex) 2)
296 (+ "0" hex)
297 hex))))
298 (+ "#" (rgb-to-hex red) (rgb-to-hex green) (rgb-to-hex red))))
294 299
295 300 (defm (root lib openqst) ()
296 301 (api-call report-error "OPENQST is not supported."))
297 302
298 303 (defm (root lib addqst) ()
299 304 (api-call report-error "ADDQST is not supported. Bundle the library with the main game."))
300 305
301 306 (defm (root lib killqst) ()
302 307 (api-call report-error "KILLQST is not supported."))
@@ -1,13 +1,14 b''
1 1
2 2 (defsystem sugar-qsp
3 3 :description "QSP compiler to monolithic HTML page"
4 4 :depends-on (:alexandria :esrap
5 5 :parenscript :parse-js :cl-uglify-js :flute)
6 6 :pathname "src/"
7 7 :serial t
8 8 :components ((:file "package")
9 (:file "patches")
9 10 (:file "ps-macros")
10 11 (:file "intrinsic-macros")
11 12 (:file "class")
12 13 (:file "main")
13 14 (:file "parser")))
General Comments 0
You need to be logged in to leave comments. Login now