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, const char *pname);
15 static long io_read(void *buf, size_t bytes, void *uptr);
16 static void del_rbnode(struct rbnode *node, void *cls);
19 int dsys_init(const char *fname)
22 struct ts_io io = {0};
23 struct ts_node *ts, *tsnode;
24 struct demoscreen *scr;
26 memset(&dsys, 0, sizeof dsys);
27 if(!(dsys.trackmap = rb_create(RB_KEY_STRING))) {
30 rb_set_delete_func(dsys.trackmap, del_rbnode, 0);
32 dsys.track = darr_alloc(0, sizeof *dsys.track);
33 dsys.value = darr_alloc(0, sizeof *dsys.value);
38 for(i=0; i<dsys.num_screens; i++) {
39 if(dsys.screens[i]->init() == -1) {
40 fprintf(stderr, "failed to initialize demo screen: %s\n", dsys.screens[i]->name);
45 if(!fname || !(io.data = ass_fopen(fname, "rb"))) {
46 dsys_run_screen(dsys.screens[0]);
51 if(!(ts = ts_load_io(&io)) || strcmp(ts->name, "demo") != 0) {
53 fprintf(stderr, "failed to read demoscript\n");
57 tsnode = ts->child_list;
59 if(strcmp(tsnode->name, "screen") == 0 &&
60 (scr = dsys_find_screen(ts_get_attr_str(tsnode, "name", 0)))) {
61 proc_screen_script(scr, tsnode);
63 } else if(strcmp(tsnode->name, "track") == 0) {
64 proc_track(tsnode, 0);
66 tsnode = tsnode->next;
73 static void proc_screen_script(struct demoscreen *scr, struct ts_node *node)
79 attr = node->attr_list;
81 if(sscanf(attr->name, "key_%ld", &tm) == 1 && attr->val.type == TS_NUMBER) {
82 anm_set_value(&scr->track, tm, attr->val.fnum);
87 sub = node->child_list;
89 if(strcmp(sub->name, "track") == 0) {
90 proc_track(sub, scr->name);
96 static void proc_track(struct ts_node *node, const char *pname)
102 struct anm_track *trk;
104 if(!(name = (char*)ts_get_attr_str(node, "name", 0))) {
108 buf = alloca(strlen(name) + strlen(pname) + 2);
109 sprintf(buf, "%s.%s", pname, name);
113 if((tidx = dsys_add_track(name)) == -1) {
116 trk = dsys.track + tidx;
118 attr = node->attr_list;
120 if(sscanf(attr->name, "key_%ld", &tm) == 1 && attr->val.type == TS_NUMBER) {
121 anm_set_value(trk, tm, attr->val.fnum);
127 static long io_read(void *buf, size_t bytes, void *uptr)
129 return ass_fread(buf, 1, bytes, uptr);
133 void dsys_destroy(void)
137 for(i=0; i<dsys.num_screens; i++) {
138 anm_destroy_track(&dsys.screens[i]->track);
139 if(dsys.screens[i]->destroy) {
140 dsys.screens[i]->destroy();
143 dsys.num_screens = 0;
145 darr_free(dsys.track);
146 darr_free(dsys.value);
147 rb_free(dsys.trackmap);
150 void dsys_update(void)
152 int i, j, sort_needed = 0;
153 struct demoscreen *scr;
155 dsys.tmsec = time_msec;
157 /* evaluate tracks */
158 for(i=0; i<dsys.num_tracks; i++) {
159 dsys.value[i] = anm_get_value(dsys.track + i, dsys.tmsec);
162 if(dsys.scr_override) {
163 scr = dsys.scr_override;
165 if(scr->update) scr->update(dsys.tmsec);
170 for(i=0; i<dsys.num_screens; i++) {
171 scr = dsys.screens[i];
172 scr->vis = anm_get_value(&scr->track, dsys.tmsec);
174 if(scr->vis > 0.0f) {
176 if(scr->start) scr->start();
179 if(scr->update) scr->update(dsys.tmsec);
181 if(dsys.num_act && scr->prio != dsys.act[dsys.num_act - 1]->prio) {
184 dsys.act[dsys.num_act++] = scr;
187 if(scr->stop) scr->stop();
194 for(i=0; i<dsys.num_act; i++) {
195 for(j=i+1; j<dsys.num_act; j++) {
196 if(dsys.act[j]->prio > dsys.act[j - 1]->prio) {
197 void *tmp = dsys.act[j];
198 dsys.act[j] = dsys.act[j - 1];
199 dsys.act[j - 1] = tmp;
206 /* TODO: do something about draw ordering of the active screens */
211 if(dsys.scr_override) {
212 dsys.scr_override->draw();
216 for(i=0; i<dsys.num_act; i++) {
229 void dsys_seek_abs(long tm)
233 void dsys_seek_rel(long dt)
237 void dsys_seek_norm(float t)
242 struct demoscreen *dsys_find_screen(const char *name)
248 for(i=0; i<dsys.num_screens; i++) {
249 if(strcmp(dsys.screens[i]->name, name) == 0) {
250 return dsys.screens[i];
256 void dsys_run_screen(struct demoscreen *scr)
261 if(dsys.scr_override) {
262 scr = dsys.scr_override;
263 if(scr->stop) scr->stop();
265 dsys.scr_override = 0;
269 for(i=0; i<dsys.num_act; i++) {
270 if(dsys.act[i]->stop) dsys.act[i]->stop();
271 dsys.act[i]->active = 0;
275 dsys.scr_override = scr;
277 if(scr->start) scr->start();
282 int dsys_add_screen(struct demoscreen *scr)
284 if(!scr->name || !scr->init || !scr->draw) {
285 fprintf(stderr, "dsys_add_screen: invalid screen\n");
288 if(anm_init_track(&scr->track) == -1) {
289 fprintf(stderr, "dsys_add_screen: failed to initialize keyframe track\n");
292 anm_set_track_interpolator(&scr->track, ANM_INTERP_LINEAR);
293 anm_set_track_extrapolator(&scr->track, ANM_EXTRAP_CLAMP);
294 anm_set_track_default(&scr->track, 0);
296 dsys.screens[dsys.num_screens++] = scr;
300 int dsys_add_track(const char *name)
302 struct anm_track trk;
305 if(rb_find(dsys.trackmap, (char*)name)) {
306 fprintf(stderr, "ignoring duplicate track: %s\n", name);
310 idx = darr_size(dsys.track);
311 darr_push(dsys.track, &trk);
312 darr_pushf(dsys.value, 0);
314 anm_init_track(dsys.track + idx);
316 if(rb_insert(dsys.trackmap, (char*)strdup_nf(name), (void*)(intptr_t)idx) == -1) {
317 fprintf(stderr, "failed to insert to track map: %s\n", name);
320 dsys.num_tracks = idx + 1;
324 int dsys_find_track(const char *name)
326 struct rbnode *n = rb_find(dsys.trackmap, (char*)name);
329 return (intptr_t)n->data;
332 float dsys_value(const char *name)
334 int idx = dsys_find_track(name);
335 return idx == -1 ? 0.0f : dsys.value[idx];
338 static void del_rbnode(struct rbnode *node, void *cls)