10 void regscr_testa(void);
11 void regscr_testb(void);
13 static void proc_screen_script(struct demoscreen *scr, struct ts_node *node);
14 static void proc_track(struct ts_node *node, struct demoscreen *pscr);
15 static long io_read(void *buf, size_t bytes, void *uptr);
18 int dsys_init(const char *fname)
21 struct ts_io io = {0};
22 struct ts_node *ts, *tsnode;
23 struct demoscreen *scr;
25 memset(&dsys, 0, sizeof dsys);
26 if(!(dsys.trackmap = rb_create(RB_KEY_STRING))) {
30 dsys.ev = darr_alloc(0, sizeof *dsys.ev);
35 for(i=0; i<dsys.num_screens; i++) {
36 if(dsys.screens[i]->init() == -1) {
37 fprintf(stderr, "failed to initialize demo screen: %s\n", dsys.screens[i]->name);
42 if(!fname || !(io.data = ass_fopen(fname, "rb"))) {
43 dsys_run_screen(dsys.screens[0]);
48 if(!(ts = ts_load_io(&io)) || strcmp(ts->name, "demo") != 0) {
50 fprintf(stderr, "failed to read demoscript\n");
54 tsnode = ts->child_list;
56 if(strcmp(tsnode->name, "screen") == 0 &&
57 (scr = dsys_find_screen(ts_get_attr_str(tsnode, "name", 0)))) {
58 proc_screen_script(scr, tsnode);
60 } else if(strcmp(tsnode->name, "track") == 0) {
61 proc_track(tsnode, 0);
63 tsnode = tsnode->next;
70 static void proc_screen_script(struct demoscreen *scr, struct ts_node *node)
76 attr = node->attr_list;
78 if(sscanf(attr->name, "key_%ld", &tm) == 1 && attr->val.type == TS_NUMBER) {
79 anm_set_value(&scr->track, tm, attr->val.fnum);
84 sub = node->child_list;
86 if(strcmp(sub->name, "track") == 0) {
93 static void proc_track(struct ts_node *node, struct demoscreen *pscr)
101 if(!(name = (char*)ts_get_attr_str(node, "name", 0))) {
105 buf = alloca(strlen(name) + strlen(pscr->name) + 2);
106 sprintf(buf, "%s.%s", pscr->name, name);
110 if((idx = dsys_add_event(name)) == -1) {
116 attr = node->attr_list;
118 if(sscanf(attr->name, "key_%ld", &tm) == 1 && attr->val.type == TS_NUMBER) {
119 anm_set_value(&ev->track, tm, attr->val.fnum);
125 static long io_read(void *buf, size_t bytes, void *uptr)
127 return ass_fread(buf, 1, bytes, uptr);
131 void dsys_destroy(void)
135 for(i=0; i<dsys.num_screens; i++) {
136 anm_destroy_track(&dsys.screens[i]->track);
137 if(dsys.screens[i]->destroy) {
138 dsys.screens[i]->destroy();
141 dsys.num_screens = 0;
144 rb_free(dsys.trackmap);
147 void dsys_update(void)
149 int i, j, sort_needed = 0;
151 struct demoscreen *scr;
153 dsys.tmsec = time_msec;
155 /* evaluate tracks */
156 for(i=0; i<dsys.num_ev; i++) {
158 if((scr = dsys.ev[i].scr) && scr->start_time >= 0) {
159 tm -= dsys.ev[i].scr->start_time;
161 dsys.ev[i].value = anm_get_value(&dsys.ev[i].track, tm);
164 if(dsys.scr_override) {
165 scr = dsys.scr_override;
167 if(scr->update) scr->update(dsys.tmsec);
172 for(i=0; i<dsys.num_screens; i++) {
173 scr = dsys.screens[i];
174 scr->vis = anm_get_value(&scr->track, dsys.tmsec);
176 if(scr->vis > 0.0f) {
177 if(scr->start_time < 0) {
178 if(scr->start) scr->start();
179 scr->start_time = dsys.tmsec;
181 if(scr->update) scr->update(dsys.tmsec);
183 if(dsys.num_act && scr->prio != dsys.act[dsys.num_act - 1]->prio) {
186 dsys.act[dsys.num_act++] = scr;
188 if(scr->start_time >= 0) {
189 if(scr->stop) scr->stop();
190 scr->start_time = -1;
196 for(i=0; i<dsys.num_act; i++) {
197 for(j=i+1; j<dsys.num_act; j++) {
198 if(dsys.act[j]->prio > dsys.act[j - 1]->prio) {
199 void *tmp = dsys.act[j];
200 dsys.act[j] = dsys.act[j - 1];
201 dsys.act[j - 1] = tmp;
208 /* TODO: do something about draw ordering of the active screens */
213 if(dsys.scr_override) {
214 dsys.scr_override->draw();
218 for(i=0; i<dsys.num_act; i++) {
231 void dsys_seek_abs(long tm)
235 void dsys_seek_rel(long dt)
239 void dsys_seek_norm(float t)
244 struct demoscreen *dsys_find_screen(const char *name)
250 for(i=0; i<dsys.num_screens; i++) {
251 if(strcmp(dsys.screens[i]->name, name) == 0) {
252 return dsys.screens[i];
258 void dsys_run_screen(struct demoscreen *scr)
263 if(dsys.scr_override) {
264 scr = dsys.scr_override;
265 if(scr->stop) scr->stop();
267 dsys.scr_override = 0;
271 for(i=0; i<dsys.num_act; i++) {
272 if(dsys.act[i]->stop) dsys.act[i]->stop();
273 dsys.act[i]->start_time = -1;
277 dsys.scr_override = scr;
279 if(scr->start) scr->start();
280 scr->start_time = dsys.tmsec;
284 int dsys_add_screen(struct demoscreen *scr)
286 if(!scr->name || !scr->init || !scr->draw) {
287 fprintf(stderr, "dsys_add_screen: invalid screen\n");
290 if(anm_init_track(&scr->track) == -1) {
291 fprintf(stderr, "dsys_add_screen: failed to initialize keyframe track\n");
294 anm_set_track_interpolator(&scr->track, ANM_INTERP_LINEAR);
295 anm_set_track_extrapolator(&scr->track, ANM_EXTRAP_CLAMP);
296 anm_set_track_default(&scr->track, 0);
298 dsys.screens[dsys.num_screens++] = scr;
302 int dsys_add_event(const char *name)
304 struct demoevent ev = {0};
307 if(rb_find(dsys.trackmap, (char*)name)) {
308 fprintf(stderr, "ignoring duplicate track: %s\n", name);
312 ev.name = strdup_nf(name);
313 anm_init_track(&ev.track);
314 anm_set_track_interpolator(&ev.track, ANM_INTERP_LINEAR);
315 anm_set_track_extrapolator(&ev.track, ANM_EXTRAP_CLAMP);
316 anm_set_track_default(&ev.track, 0);
318 idx = darr_size(dsys.ev);
319 darr_push(dsys.ev, &ev);
322 if(rb_insert(dsys.trackmap, ev.name, (void*)(intptr_t)idx) == -1) {
323 fprintf(stderr, "failed to insert to track map: %s\n", name);
326 dsys.num_ev = idx + 1;
330 int dsys_find_event(const char *name)
332 struct rbnode *n = rb_find(dsys.trackmap, (char*)name);
335 return (intptr_t)n->data;
338 float dsys_value(const char *name)
340 int idx = dsys_find_event(name);
341 return idx == -1 ? 0.0f : dsys.ev[idx].value;