##// END OF EJS Templates
Sounds, save/load UI buttons
naryl -
r12:77651167 default
parent child Browse files
Show More
@@ -1,15 +1,19 b''
1 1
2 2 <div id="qsp">
3 3 <div class="qsp-col qsp-col1">
4 4 <div id="qsp-main" class="qsp-frame">&nbsp;</div>
5 5 <div id="qsp-acts" class="qsp-frame">&nbsp;</div>
6 6 <input id="qsp-input" class="qsp-frame">
7 7 </div>
8 8 <div class="qsp-col qsp-col2">
9 9 <div id="qsp-stat" class="qsp-frame">&nbsp;</div>
10 10 <div id="qsp-objs" class="qsp-frame">&nbsp;</div>
11 11 </div>
12 <div class="qsp-col qsp-col3">
13 <a href="javascript:SugarQSP.lib.savegame()"><img id="qsp-btn-save"></a>
14 <a href="javascript:SugarQSP.lib.opengame()"><img id="qsp-btn-load"></a>
15 </div>
12 16 </div>
13 17
14 18 <div id="qsp-dropdown">
15 19 </div>
@@ -1,84 +1,103 b''
1 1
2 2 .qsp-frame {
3 3 border: 1px solid black;
4 4 overflow: auto;
5 5 padding: 5px;
6 6 box-sizing: border-box;
7 7 }
8 8
9 9 #qsp {
10 10 position: absolute;
11 11 display: flex;
12 12 flex-flow: row;
13 13 top: 0;
14 14 left: 0;
15 15 width: 100%;
16 16 height: 100%;
17 17 }
18 18
19 19 .qsp-col {
20 20 display: flex;
21 21 flex-flow: column;
22 22 }
23 23
24 24 .qsp-col1 {
25 25 flex: 7 7 70px;
26 26 }
27 27
28 28 .qsp-col2 {
29 29 flex: 3 3 30px;
30 30 }
31 31
32 .qsp-col3 {
33 flex: 0 0 40px;
34 }
35
32 36 #qsp-main {
33 37 flex: 6 6 60px;
34 38 }
35 39
36 40 #qsp-acts {
37 41 flex: 4 4 40px;
38 42 }
39 43
40 44 #qsp-input {
41 45 }
42 46
43 47 #qsp-stat {
44 48 flex: 5 5 50px;
45 49 }
46 50
47 51 #qsp-objs {
48 52 flex: 5 5 50px;
49 53 }
50 54
51 55 .qsp-act {
52 56 display: block;
53 57 padding: 2px;
54 58 font-size: large;
55 59 }
56 60
57 61 .qsp-act:hover {
58 62 outline: #9E9E9E outset 3px
59 63 }
60 64
61 // Dropdown
65 /* Dropdown */
62 66
63 67 #qsp-dropdown {
64 68 display: none;
65 69 position: absolute;
66 70 background-color: #f1f1f1;
67 71 min-width: 160px;
68 72 overflow: auto;
69 73 box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
70 74 z-index: 1;
71 75 margin: auto;
72 76 top: 200;
73 77 }
74 78
75 79 #qsp-dropdown a {
76 80 color: black;
77 81 padding: 12px 16px;
78 82 text-decoration: none;
79 83 display: block;
80 84 }
81 85
82 86 #qsp-dropdown a:hover {
83 87 background-color: #ddd;
84 88 }
89
90 /* Buttons */
91
92 .qsp-col3 a, .qsp-col3 img {
93 width: 50px;
94 height: 50px;
95 }
96
97 #qsp-btn-save {
98 background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAABmJLR0QA/wD/AP+gvaeTAAACSklEQVRoge3ZPWgUQRjG8V/iRRFU/GoEQdSohSgWWqQSooVgK9iJFiKCnYV2BkFQsBRBQQwWVsHKIoWxEOzEwmhhogbRMhhFicTvYm+JCUlmZzabRLN/OPaWeZ+ZeW7feXf2lpqampqamnRaImKP4hA2VjCP27hbpoNGwbib2IPreB+IPYY7M7SvxWYM4QNO4QqWyQxVRgdeYnnB+K5A+wUcbB7z+O14hxPx08toLRDTgfv4mjrIJFrwwMS0HsABXMTxlE6LpNYqfE7pPJIBdOKhLM1uxIiLrpG5YtC4GSLMVGGkLdD+GpfxAuvxaVL7oCzN+jCG7iKDVmHkKS5hSSBuJ3bg6hRt+Zrpa553z8bEuoQrUVXk1exwKLBI1ZpPBnAL+0KBqanVim1Ykaifji+yNfIrVphipB1n8BgjCfqZ2IrTuIZXMcIUIydxFj8TtEW4JysW52JEKWtkVHUm4EdzjChSrkgLlmJXghb6m8ep9MN4K25XjvTF3sCaElrT6McS+0w2Mirb+JWhrH4CC/0+UpjUK7Ia5/86f4IeHMHeEvPJ+4km1chHE43k9KROpCyLPrViym8/vjW/b5Jt3acjL7/RzEX5bRg3sjKg+2fK7/PmZ9aZzdTqxwYzp06IBZFaDeHUCbFgUquy1Anx35TfRWXkd+WzCBOcQxEjQ7JH0PmiHW9CQUWM9Mr+Y+osO6ME8nF7Q4FFn8T2y14VDMt2vsFfqCRbZBvTdbLXFI9CgphHyjbsVu4+EcMInuH7HI1XU1NTU7OI+QMFe2N82rtssgAAAABJRU5ErkJggg==');
99 }
100
101 #qsp-btn-load {
102 background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAABmJLR0QA/wD/AP+gvaeTAAACCklEQVRoge3Yz6sNYRzH8deVexNxSaEoroWFUuomOceSPVnIwsbSxs6Psrgphf9AsrZR7kJWsroUlrZKKZRSl4USGouZk9Npzp1n5pm5x4/nXdNzpvP9Pp/v95nv82OGRCKRSCQS/w8zuIn3yGpe37CEQ6sedQk38BA7G/jO4BQ+YEebQZUxVfH/OxzGVSxX2D4o2mO4jmt4jpNFe6d5mPFkRbvQ0H9h6OqUtR33/xXr0celGn4/sYjXoQ5dJ3ILB7AOW2r4bcIj7GsrkEFpXWyrwwbaf15nXWqv6SqK1abuHDmPjV0EMobhBWIZt8cZVu0j2ZDNHF7gblRozdiO49g1zqDOEzmKJ7gcGVQTzmLDSgZ1Eunh2dD9aewpsXtctH3cwzn5ALysoVWlXZvhleMV5ovfU8J363mciAliRLsRg0Q244vfT3A/zgT2cQHbImIY1S4ldPk9Ii+NH8V9H08DfbfiY6BtiHYpoYmMBr4bbwN9YzfVoEELnew9+blpwBv5u0oI9wPtQrUbkWFaXqOzsZ01IFg7pLQOyp/A58igmhCsHZJInYndNsHa/0wiVWTy9/a5NjprQGvag0Qmwd462iGltdQ8lihqlVVIIn/9/CAvrajDWgTRB8VhMt1/aSljVr4RToc6hJTWioe1jujJD4rfQx2qRvuTyX1JuTIh3UQikUgkEhPnF+1xZ9hHnLjAAAAAAElFTkSuQmCC');
103 }
@@ -1,200 +1,210 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 ;; To be used in saving game
25 25 (defm (root api stash-state) ()
26 26 (setf (root state-stash)
27 27 (*j-s-o-n.stringify
28 28 (ps:create vars (root vars)
29 29 objs (root objs)
30 30 next-location (root current-location))))
31 31 (values))
32 32
33 33 (defm (root api state-to-base64) ()
34 34 (btoa (encode-u-r-i-component (root state-stash))))
35 35
36 36 (defm (root api base64-to-state) (data)
37 37 (setf (root state-stash) (decode-u-r-i-component (atob data)))
38 38 (let ((data (*j-s-o-n.parse (root state-stash))))
39 (api-call clear-id :qsp-main)
40 (api-call clear-id :qsp-stat)
39 41 (api-call clear-act)
40 42 (setf (root vars) (ps:@ data vars))
41 43 (setf (root objs) (ps:@ data objs))
42 44 (setf (root current-location) (ps:@ data next-location))
43 45 (funcall (root locs (root current-location)))
44 46 (api-call update-objs)
45 47 (values)))
46 48
47 49 ;;; Misc
48 50
49 51 (defm (root api clear-id) (id)
50 52 (setf (ps:chain document (get-element-by-id id) inner-text) ""))
51 53
52 54 (defm (root api get-id) (id)
53 55 (if (var "USEHTML" 0)
54 56 (ps:chain (document.get-element-by-id id) inner-h-t-m-l)
55 57 (ps:chain (document.get-element-by-id id) inner-text)))
56 58
57 59 (defm (root api set-id) (id contents)
58 60 (if (var "USEHTML" 0)
59 61 (setf (ps:chain (document.get-element-by-id id) inner-h-t-m-l) contents)
60 62 (setf (ps:chain (document.get-element-by-id id) inner-text) contents)))
61 63
62 64 (defm (root api append-id) (id contents)
63 65 (if (var "USEHTML" 0)
64 66 (incf (ps:chain (document.get-element-by-id id) inner-h-t-m-l) contents)
65 67 (incf (ps:chain (document.get-element-by-id id) inner-text) contents)))
66 68
67 69 ;;; Function calls
68 70
69 71 (defm (root api init-args) (args)
70 72 (dotimes (i (length args))
71 73 (if (numberp (elt args i))
72 74 (set (var args i) (elt args i))
73 75 (set (var $args i) (elt args i)))))
74 76
75 77 (defm (root api get-result) ()
76 78 (if (not (equal "" (var $result 0)))
77 79 (var $result 0)
78 80 (var result 0)))
79 81
80 82 ;;; Text windows
81 83
82 84 (defm (root api key-to-id) (key)
83 85 (case key
84 86 (:main "qsp-main")
85 87 (:stat "qsp-stat")
86 88 (:objs "qsp-objs")
87 89 (:acts "qsp-acts")
88 90 (:input "qsp-input")
89 91 (:dropdown "qsp-dropdown")
90 92 (t (report-error "Internal error!"))))
91 93
92 94 (defm (root api get-frame) (key)
93 95 (document.get-element-by-id (api-call key-to-id key)))
94 96
95 97 (defm (root api add-text) (key text)
96 98 (api-call append-id (api-call key-to-id key) text))
97 99
98 100 (defm (root api get-text) (key)
99 101 (api-call get-id (api-call key-to-id key)))
100 102
101 103 (defm (root api clear-text) (key)
102 104 (api-call clear-id (api-call key-to-id key)))
103 105
104 106 (defm (root api newline) (key)
105 107 (let ((div (api-call get-frame key)))
106 108 (ps:chain div (append-child (document.create-element "br")))))
107 109
108 110 (defm (root api enable-frame) (key enable)
109 111 (let ((clss (ps:getprop (api-call get-frame key) 'class-list)))
110 112 (setf clss.style.display (if enable "block" "none"))
111 113 (values)))
112 114
113 115 ;;; Actions
114 116
115 117 (defm (root api add-act) (title img act)
116 118 (setf (ps:getprop (root acts) title)
117 119 (ps:create :img img :act act))
118 120 (api-call update-acts))
119 121
120 122 (defm (root api del-act) (title)
121 123 (delete (ps:getprop (root acts) title))
122 124 (api-call update-acts))
123 125
124 126 (defm (root api clear-act) ()
125 127 (setf (root acts) (ps:create))
126 128 (api-call clear-id "qsp-acts"))
127 129
128 130 (defm (root api update-acts) ()
129 131 (api-call clear-id "qsp-acts")
130 132 (ps:for-in (title (root acts))
131 133 (let ((obj (ps:getprop (root acts) title)))
132 134 (api-call append-id "qsp-acts"
133 135 (api-call make-act-html title (ps:getprop obj :img))))))
134 136
135 137 ;;; Variables
136 138
137 139 (defm (root api var-slot) (name)
138 140 (if (= (ps:@ name 0) #\$)
139 141 :str
140 142 :num))
141 143
142 144 (defm (root api var-real-name) (name)
143 145 (if (= (ps:@ name 0) #\$)
144 146 (ps:chain name (substr 1))
145 147 name))
146 148
147 149 (defm (root api ensure-var) (name index)
148 150 (unless (in name (root vars))
149 151 (setf (ps:getprop (root vars) name)
150 152 (ps:create)))
151 153 (unless (in index (ps:getprop (root vars) name))
152 154 (setf (ps:getprop (root vars) name index)
153 155 (ps:create :num 0 :str "")))
154 156 (values))
155 157
156 158 (defm (root api get-var) (name index)
157 159 (let ((var-name (api-call var-real-name name)))
158 160 (api-call ensure-var var-name index)
159 161 (ps:getprop (root vars) var-name index
160 162 (api-call var-slot name))))
161 163
162 164 (defm (root api set-var) (name index value)
163 165 (let ((var-name (api-call var-real-name name)))
164 166 (api-call ensure-var var-name index)
165 167 (setf (ps:getprop (root vars) var-name index
166 168 (api-call var-slot name))
167 169 value)
168 170 (values)))
169 171
170 172 (defm (root api get-array) (name type)
171 173 (ps:getprop (root vars) (api-call var-real-name name)))
172 174
173 175 (defm (root api kill-var) (name index)
174 176 (if (eq index :whole)
175 177 (ps:delete (ps:getprop (root vars) name))
176 178 (ps:delete (ps:getprop (root vars) name index)))
177 179 (values))
178 180
179 181 (defm (root api array-size) (name)
180 182 (ps:getprop (root vars) (api-call var-real-name name) 'length))
181 183
182 184 ;;; Objects
183 185
184 186 (defm (root api update-objs) ()
185 187 (let ((elt (document.get-element-by-id "qsp-objs")))
186 188 (setf elt.inner-h-t-m-l "<ul>")
187 189 (loop :for obj :in (root objs)
188 190 :do (incf elt.inner-h-t-m-l (+ "<li>" obj)))
189 191 (incf elt.inner-h-t-m-l "</ul>")))
190 192
191 193 ;;; Menu
192 194
193 195 (defm (root api menu) (menu-data)
194 196 (let ((elt (document.get-element-by-id "qsp-dropdown"))
195 197 (i 0))
196 198 (setf elt.inner-h-t-m-l "")
197 199 (loop :for item :in menu-data
198 200 :do (incf i)
199 201 :do (incf elt.inner-h-t-m-l (api-call make-menu-item-html i item.text item.icon item.loc)))
200 202 (setf elt.style.display "block")))
203
204 ;;; Content
205
206 (defm (root api clean-audio) ()
207 (loop :for k :in (*object.keys (root playing))
208 :for v := (ps:getprop (root playing) k)
209 :do (when (ps:@ v ended)
210 (ps:delete (ps:@ (root playing) k)))))
@@ -1,137 +1,140 b''
1 1
2 2 (in-package sugar-qsp)
3 3
4 4 ;;;; Macros implementing some intrinsics where it makes sense
5 5 ;;;; E.g. an equivalent JS function exists, or it's a direct API call
6 6
7 7 ;;; 1loc
8 8
9 9 ;;; 2var
10 10
11 11 (ps:defpsmacro killvar (varname &optional (index :whole))
12 12 `(api-call kill-var ,varname ,index))
13 13
14 14 (ps:defpsmacro killall ()
15 15 `(api-call kill-all))
16 16
17 17 ;;; 3expr
18 18
19 19 (ps:defpsmacro obj (name)
20 20 `(funcall (root objs includes) ,name))
21 21
22 22 (ps:defpsmacro loc (name)
23 23 `(funcall (root locs includes) ,name))
24 24
25 25 (ps:defpsmacro no (arg)
26 26 `(- -1 ,arg))
27 27
28 28 ;;; 4code
29 29
30 30 (ps:defpsmacro qspver ()
31 31 "0.0.1")
32 32
33 33 (ps:defpsmacro curloc ()
34 34 `(root current-location))
35 35
36 36 (ps:defpsmacro rnd ()
37 37 `(funcall (root lib rand) 1 1000))
38 38
39 39 (ps:defpsmacro qspmax (&rest args)
40 40 `(max ,@args))
41 41
42 42 (ps:defpsmacro qspmin (&rest args)
43 43 `(min ,@args))
44 44
45 45 ;;; 5arrays
46 46
47 47 (ps:defpsmacro arrsize (name)
48 48 `(api-call array-size ,name))
49 49
50 50 ;;; 6str
51 51
52 52 (ps:defpsmacro len (s)
53 53 `(length ,s))
54 54
55 55 (ps:defpsmacro mid (s from &optional count)
56 56 `(ps:chain ,s (substring ,from ,count)))
57 57
58 58 (ps:defpsmacro ucase (s)
59 59 `(ps:chain ,s (to-upper-case)))
60 60
61 61 (ps:defpsmacro lcase (s)
62 62 `(ps:chain ,s (to-lower-case)))
63 63
64 64 (ps:defpsmacro trim (s)
65 65 `(ps:chain ,s (trim)))
66 66
67 67 (ps:defpsmacro replace (s from to)
68 68 `(ps:chain ,s (replace ,from ,to)))
69 69
70 70 (ps:defpsmacro val (s)
71 71 `(parse-int ,s 10))
72 72
73 73 (ps:defpsmacro qspstr (n)
74 74 `(ps:chain ,n (to-string)))
75 75
76 76 ;;; 7if
77 77
78 78 ;;; 8sub
79 79
80 80 ;;; 9loops
81 81
82 82 ;; JUMP is in ps-macros.lisp (because it's a part of a huge kludge)
83 83
84 84 (ps:defpsmacro exit ()
85 85 `(return-from nil (values)))
86 86
87 87 ;;; 10dynamic
88 88
89 89 ;;; 11main
90 90
91 91 (ps:defpsmacro desc (s)
92 92 (declare (ignore s))
93 93 "")
94 94
95 95 ;;; 12stat
96 96
97 97 (ps:defpsmacro showstat (enable)
98 98 `(api-call enable-frame :stat ,enable))
99 99
100 100 ;;; 13diag
101 101
102 102 (ps:defpsmacro msg (text)
103 103 `(alert ,text))
104 104
105 105 ;;; 14act
106 106
107 107 (ps:defpsmacro showacts (enable)
108 108 `(api-call enable-frame :acts ,enable))
109 109
110 110 (ps:defpsmacro delact (name)
111 111 `(api-call del-act ,name))
112 112
113 113 (ps:defpsmacro cla ()
114 114 `(api-call clear-act))
115 115
116 116 ;;; 15objs
117 117
118 118 (ps:defpsmacro showobjs (enable)
119 119 `(api-call enable-frame :objs ,enable))
120 120
121 121 (ps:defpsmacro countobj ()
122 122 `(length (root objs)))
123 123
124 124 (ps:defpsmacro getobj (index)
125 125 `(or (elt (root objs) ,index) ""))
126 126
127 127 ;;; 16menu
128 128
129 129 ;;; 17sound
130 130
131 (ps:defpsmacro isplay (filename)
132 `(funcall (root playing includes) ,filename))
133
131 134 ;;; 18img
132 135
133 136 ;;; 19input
134 137
135 138 ;;; 20time
136 139
137 140 ;;; misc
@@ -1,313 +1,321 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 &rest args)
13 13 (api-call clear-text :main)
14 14 (apply (root lib xgoto) target args))
15 15
16 16 (defm (root lib xgoto) (target &rest args)
17 17 (api-call clear-act)
18 18 (api-call init-args args)
19 19 (setf (root current-location) (ps:chain target (to-upper-case)))
20 20 (api-call stash-state)
21 21 (funcall (ps:getprop (root locs) (root current-location))))
22 22
23 23 ;;; 2var
24 24
25 25 ;;; 3expr
26 26
27 27 ;;; 4code
28 28
29 29 (defm (root lib rand) (a &optional (b 1))
30 30 (let ((min (min a b))
31 31 (max (max a b)))
32 32 (+ min (ps:chain *math (random (- max min))))))
33 33
34 34 ;;; 5arrays
35 35
36 36 (defm (root lib copyarr) (to from start count)
37 37 (ps:for ((i start))
38 38 ((< i (min (api-call array-size from)
39 39 (+ start count))))
40 40 ((incf i))
41 41 (api-call set-var to (+ start i)
42 42 (api-call get-var from (+ start i)))))
43 43
44 44 (defm (root lib arrpos) (name value &optional (start 0))
45 45 (ps:for ((i start)) ((< i (api-call array-size name))) ((incf i))
46 46 (when (eq (api-call get-var name i) value)
47 47 (return i)))
48 48 -1)
49 49
50 50 (defm (root lib arrcomp) (name pattern &optional (start 0))
51 51 (ps:for ((i start)) ((< i (api-call array-size name))) ((incf i))
52 52 (when (funcall (ps:getprop (api-call get-var name i) 'match) pattern)
53 53 (return i)))
54 54 -1)
55 55
56 56 ;;; 6str
57 57
58 58 (defm (root lib instr) (s subs &optional (start 1))
59 59 (+ start (ps:chain s (substring (- start 1)) (search subs))))
60 60
61 61 (defm (root lib isnum) (s)
62 62 (if (is-na-n s)
63 63 0
64 64 -1))
65 65
66 66 (defm (root lib strcomp) (s pattern)
67 67 (if (s.match pattern)
68 68 -1
69 69 0))
70 70
71 71 (defm (root lib strfind) (s pattern group)
72 72 (let* ((re (ps:new (*reg-exp pattern)))
73 73 (match (re.exec s)))
74 74 (match.group group)))
75 75
76 76 (defm (root lib strpos) (s pattern &optional (group 0))
77 77 (let* ((re (ps:new (*reg-exp pattern)))
78 78 (match (re.exec s))
79 79 (found (match.group group)))
80 80 (if found
81 81 (s.search found)
82 82 0)))
83 83
84 84 ;;; 7if
85 85
86 86 ;; Has to be a function because it always evaluates all three of its
87 87 ;; arguments
88 88 (defm (root lib iif) (cond-expr then-expr else-expr)
89 89 (if cond-expr then-expr else-expr))
90 90
91 91 ;;; 8sub
92 92
93 93 (defm (root lib gosub) (target &rest args)
94 94 (conserving-vars (args result)
95 95 (api-call init-args args)
96 96 (funcall (ps:getprop (root locs) target))
97 97 (values)))
98 98
99 99 (defm (root lib func) (target &rest args)
100 100 (conserving-vars (args result)
101 101 (api-call init-args args)
102 102 (funcall (ps:getprop (root locs) target))
103 103 (api-call get-result)))
104 104
105 105 ;;; 9loops
106 106
107 107 ;;; 10dynamic
108 108
109 109 (defm (root lib dyneval) (block &rest args)
110 110 (conserving-vars (args result)
111 111 (api-call init-args args)
112 112 (funcall block)
113 113 (api-call get-result)))
114 114
115 115 (defm (root lib dynamic) (&rest args)
116 116 (conserving-vars (args result)
117 117 (api-call init-args args)
118 118 (funcall block)
119 119 (values)))
120 120
121 121 ;;; 11main
122 122
123 123 (defm (root lib main-p) (s)
124 124 (api-call add-text :main s)
125 125 (values))
126 126
127 127 (defm (root lib main-pl) (s)
128 128 (api-call add-text :main s)
129 129 (api-call newline :main)
130 130 (values))
131 131
132 132 (defm (root lib main-nl) (s)
133 133 (api-call newline :main)
134 134 (api-call add-text :main s)
135 135 (values))
136 136
137 137 (defm (root lib maintxt) (s)
138 138 (api-call get-text :main)
139 139 (values))
140 140
141 141 ;; For clarity (it leaves a lib.desc() call in JS)
142 142 (defm (root lib desc) (s)
143 143 "")
144 144
145 145 (defm (root lib main-clear) ()
146 146 (api-call clear-text :main)
147 147 (values))
148 148
149 149 ;;; 12stat
150 150
151 151 (defm (root lib stat-p) (s)
152 152 (api-call add-text :stat s)
153 153 (values))
154 154
155 155 (defm (root lib stat-pl) (s)
156 156 (api-call add-text :stat s)
157 157 (api-call newline :stat)
158 158 (values))
159 159
160 160 (defm (root lib stat-nl) (s)
161 161 (api-call newline :stat)
162 162 (api-call add-text :stat s)
163 163 (values))
164 164
165 165 (defm (root lib stattxt) (s)
166 166 (api-call get-text :stat)
167 167 (values))
168 168
169 169 (defm (root lib stat-clear) ()
170 170 (api-call clear-text :stat)
171 171 (values))
172 172
173 173 (defm (root lib cls) ()
174 174 (funcall (root lib stat-clear))
175 175 (funcall (root lib main-clear))
176 176 (funcall (root lib cla))
177 177 (funcall (root lib cmdclear))
178 178 (values))
179 179
180 180 ;;; 13diag
181 181
182 182 ;;; 14act
183 183
184 184 (defm (root lib curacts) ()
185 185 (let ((acts (root acts)))
186 186 (lambda ()
187 187 (setf (root acts) acts)
188 188 (values))))
189 189
190 190 ;;; 15objs
191 191
192 192 (defm (root lib addobj) (name)
193 193 (ps:chain (root objs) (push name))
194 194 (api-call update-objs)
195 195 (values))
196 196
197 197 (defm (root lib delobj) (name)
198 198 (let ((index (ps:chain (root objs) (index-of name))))
199 199 (when (> index -1)
200 (funcall (root lib killobj) index)))
200 (funcall (root lib killobj) (1+ index))))
201 201 (values))
202 202
203 (defm (root lib killobj) (&optional num)
204 (if num
205 (ps:chain (root objs) (splice (1+ num) 1))
206 (setf (root objs) (list)))
203 (defm (root lib killobj) (&optional (num nil))
204 (if (eq nil num)
205 (setf (root objs) (list))
206 (ps:chain (root objs) (splice (1- num) 1)))
207 207 (api-call update-objs)
208 208 (values))
209 209
210 210 ;;; 16menu
211 211
212 212 (defm (root lib menu) (menu-name)
213 213 (let ((menu-data (list)))
214 214 (loop :for item :in (api-call get-array menu-name)
215 215 :do (cond ((string= item "")
216 216 (break))
217 217 ((string= item "-:-")
218 218 (ps:chain menu-data (push :delimiter)))
219 219 (t
220 220 (let* ((tokens (ps:chain item (split ":"))))
221 221 (when (= (length tokens) 2)
222 222 (tokens.push ""))
223 223 (let* ((text (ps:chain tokens (splice 0 (- tokens.length 2)) (join ":")))
224 224 (loc (ps:getprop tokens (- tokens.length 2)))
225 225 (icon (ps:getprop tokens (- tokens.length 1))))
226 226 (ps:chain menu-data
227 227 (push (ps:create text text
228 228 loc loc
229 229 icon icon))))))))
230 230 (api-call menu menu-data)
231 231 (values)))
232 232
233 233 ;;; 17sound
234 234
235 (defm (root lib play) ())
236
237 (defm (root lib isplay) ())
235 (defm (root lib play) (filename &optional (volume 100))
236 (let ((audio (ps:new (*audio filename))))
237 (setf (ps:getprop (root playing) filename) audio)
238 (setf (ps:@ audio volume) (* volume 0.01))
239 (ps:chain audio (play))))
238 240
239 (defm (root lib close) ())
241 (defm (root lib close) (filename)
242 (funcall (root playing filename) stop)
243 (ps:delete (root playing filename)))
240 244
241 (defm (root lib closeall) ())
245 (defm (root lib closeall) ()
246 (loop :for k :in (*object.keys (root playing))
247 :for v := (ps:getprop (root playing) k)
248 :do (funcall v stop))
249 (setf (root playing) (ps:create)))
242 250
243 251 ;;; 18img
244 252
245 253 (defm (root lib refint) ())
246 254
247 255 (defm (root lib view) ())
248 256
249 257 ;;; 19input
250 258
251 259 (defm (root lib showinput) ())
252 260
253 261 (defm (root lib usertxt) ())
254 262
255 263 (defm (root lib cmdclear) ())
256 264
257 265 (defm (root lib input) ())
258 266
259 267 ;;; 20time
260 268
261 269 ;; I wonder if there's a better solution than busy-wait
262 270 (defm (root lib wait) (msec)
263 271 (let* ((now (ps:new (*date)))
264 272 (exit-time (+ (funcall now.get-time) msec)))
265 273 (loop :while (< (funcall now.get-time) exit-time))))
266 274
267 275 (defm (root lib msecscount) ())
268 276
269 277 (defm (root lib settimer) ())
270 278
271 279 ;;; misc
272 280
273 281 (defm (root lib rgb) ())
274 282
275 283 (defm (root lib openqst) ())
276 284
277 285 (defm (root lib addqst) ())
278 286
279 287 (defm (root lib killqst) ())
280 288
281 289 (defm (root lib opengame) (&optional filename)
282 290 (let ((element (document.create-element :input)))
283 291 (element.set-attribute :type :file)
284 292 (element.set-attribute :id :qsp-opengame)
285 293 (element.set-attribute :tabindex -1)
286 294 (element.set-attribute "aria-hidden" t)
287 295 (setf element.style.display :block)
288 296 (setf element.style.visibility :hidden)
289 297 (setf element.style.position :fixed)
290 298 (setf element.onchange
291 299 (lambda (event)
292 300 (let* ((file (elt event.target.files 0))
293 301 (reader (ps:new (*file-reader))))
294 302 (setf reader.onload
295 303 (lambda (ev)
296 304 (block nil
297 305 (let ((target ev.current-target))
298 306 (unless target.result
299 307 (return))
300 308 (api-call base64-to-state target.result)))))
301 309 (reader.read-as-text file))))
302 310 (document.body.append-child element)
303 311 (element.click)
304 312 (document.body.remove-child element)))
305 313
306 314 (defm (root lib savegame) (&optional filename)
307 315 (let ((element (document.create-element :a)))
308 316 (element.set-attribute :href (+ "data:text/plain;charset=utf-8," (api-call state-to-base64)))
309 317 (element.set-attribute :download "savegame.sav")
310 318 (setf element.style.display :none)
311 319 (document.body.append-child element)
312 320 (element.click)
313 321 (document.body.remove-child element)))
@@ -1,21 +1,32 b''
1 1
2 2 (in-package sugar-qsp)
3 3
4 4 (setf (root)
5 (ps:create vars (ps:create)
6 objs (list)
7 state-stash (ps:create)
8 acts (ps:create)
9 locs (ps:create)))
5 (ps:create
6 ;;; Game session state
7 ;; Variables
8 vars (ps:create)
9 ;; Inventory (objects)
10 objs (list)
11 ;;; Transient state
12 ;; Savegame data
13 state-stash (ps:create)
14 ;; List of audio files being played
15 playing (ps:create)
16 ;;; Game data
17 ;; ACTions
18 acts (ps:create)
19 ;; Locations
20 locs (ps:create)))
10 21
11 22 ;; Launch the game from the first location
12 23 (setf window.onload
13 24 (lambda ()
14 25 (funcall (ps:getprop (root locs)
15 26 (ps:chain *object (keys (root locs)) 0)))
16 27 (values)))
17 28
18 29 ;; Close the dropdown on any click
19 30 (setf window.onclick
20 31 (lambda (event)
21 32 (setf (ps:@ (api-call get-frame :dropdown) style display) "none")))
General Comments 0
You need to be logged in to leave comments. Login now