7ef4478d642108fb05690fc529807d3b5d68bc36
[andemo] / src / demosys.c
1 #include <stdio.h>
2 #include <string.h>
3 #include "demo.h"
4 #include "demosys.h"
5 #include "treestore.h"
6 #include "assfile.h"
7
8 void regscr_testa(void);
9 void regscr_testb(void);
10
11 static void proc_screen_script(struct demoscreen *scr, struct ts_node *node);
12 static long io_read(void *buf, size_t bytes, void *uptr);
13
14
15 int dsys_init(const char *fname)
16 {
17         int i;
18         struct ts_io io = {0};
19         struct ts_node *ts, *tsnode;
20         struct demoscreen *scr;
21
22         regscr_testa();
23         regscr_testb();
24
25         for(i=0; i<dsys_num_screens; i++) {
26                 if(dsys_screens[i]->init() == -1) {
27                         fprintf(stderr, "failed to initialize demo screen: %s\n", dsys_screens[i]->name);
28                         return -1;
29                 }
30         }
31
32         if(!fname || !(io.data = ass_fopen(fname, "rb"))) {
33                 dsys_run_screen(dsys_screens[0]);
34                 return 0;
35         }
36         io.read = io_read;
37
38         if(!(ts = ts_load_io(&io)) || strcmp(ts->name, "demo") != 0) {
39                 ass_fclose(io.data);
40                 fprintf(stderr, "failed to read demoscript\n");
41                 return -1;
42         }
43
44         tsnode = ts->child_list;
45         while(tsnode) {
46                 if(strcmp(tsnode->name, "screen") == 0 &&
47                                 (scr = dsys_find_screen(ts_get_attr_str(tsnode, "name", 0)))) {
48                         proc_screen_script(scr, tsnode);
49                 }
50                 tsnode = tsnode->next;
51         }
52
53         ass_fclose(io.data);
54         return 0;
55 }
56
57 static void proc_screen_script(struct demoscreen *scr, struct ts_node *node)
58 {
59         struct ts_attr *attr;
60         long tm;
61
62         attr = node->attr_list;
63         while(attr) {
64                 if(sscanf(attr->name, "key_%ld", &tm) == 1 && attr->val.type == TS_NUMBER) {
65                         anm_set_value(&scr->track, tm, attr->val.fnum);
66                 }
67                 attr = attr->next;
68         }
69 }
70
71 static long io_read(void *buf, size_t bytes, void *uptr)
72 {
73         return ass_fread(buf, 1, bytes, uptr);
74 }
75
76
77 void dsys_destroy(void)
78 {
79         int i;
80
81         for(i=0; i<dsys_num_screens; i++) {
82                 anm_destroy_track(&dsys_screens[i]->track);
83                 if(dsys_screens[i]->destroy) {
84                         dsys_screens[i]->destroy();
85                 }
86         }
87         dsys_num_screens = 0;
88 }
89
90 void dsys_update(void)
91 {
92         int i, j, sort_needed = 0;
93         struct demoscreen *scr;
94
95         dsys_time = time_msec;
96
97         dsys_num_act = 0;
98         for(i=0; i<dsys_num_screens; i++) {
99                 scr = dsys_screens[i];
100                 scr->vis = anm_get_value(&scr->track, dsys_time);
101
102                 if(scr->vis > 0.0f) {
103                         if(!scr->active) {
104                                 if(scr->start) scr->start();
105                                 scr->active = 1;
106                         }
107                         if(scr->update) scr->update(dsys_time);
108
109                         if(dsys_num_act && scr->prio != dsys_act[dsys_num_act - 1]->prio) {
110                                 sort_needed = 1;
111                         }
112                         dsys_act[dsys_num_act++] = scr;
113                 } else {
114                         if(scr->active) {
115                                 if(scr->stop) scr->stop();
116                                 scr->active = 0;
117                         }
118                 }
119         }
120
121         if(sort_needed) {
122                 for(i=0; i<dsys_num_act; i++) {
123                         for(j=i+1; j<dsys_num_act; j++) {
124                                 if(dsys_act[j]->prio > dsys_act[j - 1]->prio) {
125                                         void *tmp = dsys_act[j];
126                                         dsys_act[j] = dsys_act[j - 1];
127                                         dsys_act[j - 1] = tmp;
128                                 }
129                         }
130                 }
131         }
132 }
133
134 /* TODO: do something about draw ordering of the active screens */
135 void dsys_draw(void)
136 {
137         int i;
138         for(i=0; i<dsys_num_act; i++) {
139                 dsys_act[i]->draw();
140         }
141 }
142
143 void dsys_run(void)
144 {
145 }
146
147 void dsys_stop(void)
148 {
149 }
150
151 void dsys_seek_abs(long tm)
152 {
153 }
154
155 void dsys_seek_rel(long dt)
156 {
157 }
158
159 void dsys_seek_norm(float t)
160 {
161 }
162
163
164 struct demoscreen *dsys_find_screen(const char *name)
165 {
166         int i;
167
168         if(!name) return 0;
169
170         for(i=0; i<dsys_num_screens; i++) {
171                 if(strcmp(dsys_screens[i]->name, name) == 0) {
172                         return dsys_screens[i];
173                 }
174         }
175         return 0;
176 }
177
178 void dsys_run_screen(struct demoscreen *scr)
179 {
180         int i;
181
182         if(!scr) return;
183         if(dsys_num_act == 1 && dsys_act[0] == scr) return;
184
185         for(i=0; i<dsys_num_act; i++) {
186                 if(dsys_act[i]->stop) dsys_act[i]->stop();
187                 dsys_act[i]->active = 0;
188         }
189
190         dsys_act[0] = scr;
191         dsys_num_act = 1;
192
193         if(scr->start) scr->start();
194         scr->active = 1;
195 }
196
197
198 int dsys_add_screen(struct demoscreen *scr)
199 {
200         if(!scr->name || !scr->init || !scr->draw) {
201                 fprintf(stderr, "dsys_add_screen: invalid screen\n");
202                 return -1;
203         }
204         if(anm_init_track(&scr->track) == -1) {
205                 fprintf(stderr, "dsys_add_screen: failed to initialize keyframe track\n");
206                 return -1;
207         }
208         anm_set_track_interpolator(&scr->track, ANM_INTERP_LINEAR);
209         anm_set_track_extrapolator(&scr->track, ANM_EXTRAP_CLAMP);
210         anm_set_track_default(&scr->track, 0);
211
212         dsys_screens[dsys_num_screens++] = scr;
213         return 0;
214 }