36ce88c744433965d459dd8cf267a32bcf8d6555
[faros-demo] / src / seq.cc
1 #include <stdio.h>
2 #include <string.h>
3 #include <vector>
4 #include <treestore.h>
5 #include "seq.h"
6 #include "track.h"
7
8 struct SeqTrack {
9         char *name;
10         Track *track;
11 };
12
13 static std::vector<SeqTrack> tracks;
14
15
16 static Track *load_track(struct ts_node *tnode);
17 static InterpMode str2interp(const char *str);
18 static ExtrapMode str2extrap(const char *str);
19
20
21 bool init_seq()
22 {
23         return true;
24 }
25
26 void destroy_seq()
27 {
28         int ntrk = tracks.size();
29         for(int i=0; i<ntrk; i++) {
30                 delete tracks[i].track;
31                 delete [] tracks[i].name;
32         }
33         tracks.clear();
34 }
35
36 int add_seq_track(const char *name, InterpMode inmode, ExtrapMode exmode, float defval)
37 {
38         int idx = find_seq_track(name);
39         if(idx >= 0) return idx;
40
41         SeqTrack st;
42         st.name = new char[strlen(name) + 1];
43         strcpy(st.name, name);
44         st.track = new Track;
45         st.track->defval = defval;
46         st.track->interp = inmode;
47         st.track->extrap = exmode;
48         tracks.push_back(st);
49         return tracks.size() - 1;
50 }
51
52 int find_seq_track(const char *name)
53 {
54         int ntrk = tracks.size();
55         for(int i=0; i<ntrk; i++) {
56                 if(strcmp(tracks[i].name, name) == 0) {
57                         return i;
58                 }
59         }
60         return -1;
61 }
62
63 Track *get_seq_track(int idx)
64 {
65         return tracks[idx].track;
66 }
67
68 void clear_seq_track(int idx)
69 {
70         tracks[idx].track->clear();
71 }
72
73 void clear_seq_track(const char *name)
74 {
75         int idx = find_seq_track(name);
76         if(idx >= 0) {
77                 tracks[idx].track->clear();
78         }
79 }
80
81 bool seq_track_empty(int idx)
82 {
83         return tracks[idx].track->empty();
84 }
85
86 bool seq_track_empty(const char *name)
87 {
88         int idx = find_seq_track(name);
89         if(idx >= 0) {
90                 return tracks[idx].track->empty();
91         }
92         return true;
93 }
94
95 void set_seq_value(int idx, long tm, float val)
96 {
97         tracks[idx].track->set_value(tm, val);
98         printf("track(%d): set keyframe %ld -> %f\n", idx, tm, val);
99 }
100
101 void set_seq_value(const char *name, long tm, float val)
102 {
103         int idx = find_seq_track(name);
104         if(idx >= 0) {
105                 set_seq_value(idx, tm, val);
106         }
107 }
108
109 float get_seq_value(int idx, long tm)
110 {
111         return (*tracks[idx].track)(tm);
112 }
113
114 float get_seq_value(const char *name, long tm)
115 {
116         int idx = find_seq_track(name);
117         if(idx < 0) {
118                 return 0.0f;
119         }
120         return (*tracks[idx].track)(tm);
121 }
122
123 bool load_seq(const char *fname)
124 {
125         struct ts_node *tree;
126         if(!(tree = ts_load(fname))) {
127                 return false;
128         }
129         if(strcmp(tree->name, "faros") != 0) {
130                 fprintf(stderr, "invalid sequence file: %s\n", fname);
131                 ts_free_tree(tree);
132                 return false;
133         }
134
135         struct ts_node *node = tree->child_list;
136         while(node) {
137                 if(strcmp(node->name, "track") == 0) {
138                         Track *track = load_track(node);
139                         const char *name = ts_get_attr_str(node, "name", 0);
140                         if(!name) {
141                                 char buf[64];
142                                 static int foo;
143                                 sprintf(buf, "unnamed%03d", foo++);
144                                 name = buf;
145                         }
146
147                         int idx = find_seq_track(name);
148                         if(idx == -1) {
149                                 SeqTrack st;
150                                 st.track = track;
151                                 st.name = new char[strlen(name) + 1];
152                                 strcpy(st.name, name);
153                                 tracks.push_back(st);
154                         } else {
155                                 delete tracks[idx].track;
156                                 tracks[idx].track = track;
157                         }
158                 }
159
160                 node = node->next;
161         }
162
163         ts_free_tree(tree);
164         return true;
165 }
166
167 static Track *load_track(struct ts_node *tnode)
168 {
169         Track *track = new Track;
170         track->defval = ts_get_attr_num(tnode, "default", 0.0f);
171         track->interp = str2interp(ts_get_attr_str(tnode, "interpolation", ""));
172         track->extrap = str2extrap(ts_get_attr_str(tnode, "extrapolation", ""));
173
174         struct ts_node *keynode = tnode->child_list;
175         while(keynode) {
176                 long tm = ts_get_attr_int(keynode, "time", 0);
177                 float val = ts_get_attr_num(keynode, "value", 0.0f);
178                 track->set_value(tm, val);
179                 keynode = keynode->next;
180         }
181
182         return track;
183 }
184
185 static InterpMode str2interp(const char *str)
186 {
187         if(strcmp(str, "step") == 0) {
188                 return INTERP_STEP;
189         } else if(strcmp(str, "sigmoid") == 0) {
190                 return INTERP_SIGMOID;
191         }
192         return INTERP_LINEAR;
193 }
194
195 static ExtrapMode str2extrap(const char *str)
196 {
197         if(strcmp(str, "repeat") == 0) {
198                 return EXTRAP_REPEAT;
199         }
200         return EXTRAP_CLAMP;
201 }
202
203 bool dump_seq(const char *fname)
204 {
205         FILE *fp = fopen(fname, "w");
206         if(!fp) {
207                 perror("failed to open sequence dump file");
208                 return false;
209         }
210
211         fprintf(fp, "faros {\n");
212         int ntrk = tracks.size();
213         for(int i=0; i<ntrk; i++) {
214                 int nkeys = tracks[i].track->get_num_keys();
215                 if(!nkeys) continue;
216
217                 fprintf(fp, "\ttrack {\n");
218                 fprintf(fp, "\t\tname = \"%s\"\n", tracks[i].name);
219                 for(int j=0; j<nkeys; j++) {
220                         TrackKey key = (*tracks[i].track)[j];
221                         fprintf(fp, "\t\tkey {\n");
222                         fprintf(fp, "\t\t\ttime = %ld\n", key.time);
223                         fprintf(fp, "\t\t\tvalue = %g\n", key.value);
224                         fprintf(fp, "\t\t}\n");
225                 }
226                 fprintf(fp, "\t}\n\n");
227         }
228         fprintf(fp, "}\n");
229         fclose(fp);
230         return true;
231 }