libpsys
view src/pattr.c @ 14:4f36bbbcc82f
really started writting the parser... god I hate ad-hoc parsing...
author | John Tsiombikas <nuclear@mutantstargoat.com> |
---|---|
date | Mon, 10 Sep 2012 05:58:03 +0300 |
parents | 1b0db53d5b5b |
children | 5678915dc2c7 |
line source
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <errno.h>
5 #include "pattr.h"
6 #include "psys_gl.h"
8 enum {
9 OPT_STR,
10 OPT_NUM,
11 OPT_NUM_RANGE,
12 OPT_VEC,
13 OPT_VEC_RANGE
14 };
16 struct cfgopt {
17 char *name;
18 int type;
19 long tm;
20 char *valstr;
21 vec3_t val, valrng;
22 };
24 static int init_particle_attr(struct psys_particle_attributes *pattr);
25 static void destroy_particle_attr(struct psys_particle_attributes *pattr);
26 static char *stripspace(char *str);
28 static void *tex_cls;
29 static unsigned int (*load_texture)(const char*, void*) = psys_gl_load_texture;
30 static void (*unload_texture)(unsigned int, void*) = psys_gl_unload_texture;
33 void psys_texture_loader(unsigned int (*load)(const char*, void*), void (*unload)(unsigned int, void*), void *cls)
34 {
35 load_texture = load;
36 unload_texture = unload;
37 tex_cls = cls;
38 }
40 int psys_init_attr(struct psys_attributes *attr)
41 {
42 memset(attr, 0, sizeof *attr);
44 if(psys_init_track3(&attr->spawn_range) == -1)
45 goto err;
46 if(psys_init_track(&attr->rate) == -1)
47 goto err;
48 if(psys_init_anm_rnd(&attr->life) == -1)
49 goto err;
50 if(psys_init_anm_rnd(&attr->size) == -1)
51 goto err;
52 if(psys_init_anm_rnd3(&attr->dir) == -1)
53 goto err;
54 if(psys_init_track3(&attr->grav) == -1)
55 goto err;
57 if(init_particle_attr(&attr->part_attr) == -1)
58 goto err;
60 attr->max_particles = -1;
62 anm_set_track_default(&attr->size.value.trk, 1.0);
63 anm_set_track_default(&attr->life.value.trk, 1.0);
65 return 0;
67 err:
68 psys_destroy_attr(attr);
69 return -1;
70 }
73 static int init_particle_attr(struct psys_particle_attributes *pattr)
74 {
75 if(psys_init_track3(&pattr->color) == -1) {
76 return -1;
77 }
78 if(psys_init_track(&pattr->alpha) == -1) {
79 psys_destroy_track3(&pattr->color);
80 return -1;
81 }
82 if(psys_init_track(&pattr->size) == -1) {
83 psys_destroy_track3(&pattr->color);
84 psys_destroy_track(&pattr->alpha);
85 return -1;
86 }
88 anm_set_track_default(&pattr->color.x, 1.0);
89 anm_set_track_default(&pattr->color.y, 1.0);
90 anm_set_track_default(&pattr->color.z, 1.0);
91 anm_set_track_default(&pattr->alpha.trk, 1.0);
92 anm_set_track_default(&pattr->size.trk, 1.0);
93 return 0;
94 }
97 void psys_destroy_attr(struct psys_attributes *attr)
98 {
99 psys_destroy_track3(&attr->spawn_range);
100 psys_destroy_track(&attr->rate);
101 psys_destroy_anm_rnd(&attr->life);
102 psys_destroy_anm_rnd(&attr->size);
103 psys_destroy_anm_rnd3(&attr->dir);
104 psys_destroy_track3(&attr->grav);
106 destroy_particle_attr(&attr->part_attr);
108 if(attr->tex && unload_texture) {
109 unload_texture(attr->tex, tex_cls);
110 }
111 }
113 static void destroy_particle_attr(struct psys_particle_attributes *pattr)
114 {
115 psys_destroy_track3(&pattr->color);
116 psys_destroy_track(&pattr->alpha);
117 psys_destroy_track(&pattr->size);
118 }
120 void psys_eval_attr(struct psys_attributes *attr, anm_time_t tm)
121 {
122 psys_eval_track3(&attr->spawn_range, tm);
123 psys_eval_track(&attr->rate, tm);
124 psys_eval_anm_rnd(&attr->life, tm);
125 psys_eval_anm_rnd(&attr->size, tm);
126 psys_eval_anm_rnd3(&attr->dir, tm);
127 psys_eval_track3(&attr->grav, tm);
128 }
130 int psys_load_attr(struct psys_attributes *attr, const char *fname)
131 {
132 FILE *fp;
133 int res;
135 if(!(fp = fopen(fname, "r"))) {
136 fprintf(stderr, "%s: failed to read file: %s: %s\n", __func__, fname, strerror(errno));
137 return -1;
138 }
139 res = psys_load_attr_stream(attr, fp);
140 fclose(fp);
141 return res;
142 }
144 int psys_load_attr_stream(struct psys_attributes *attr, FILE *fp)
145 {
146 int lineno = 0;
147 char buf[512];
149 psys_init_attr(attr);
151 while(fgets(buf, sizeof buf, fp)) {
152 struct cfgopt opt;
154 lineno++;
156 if(get_cfg_opt(buf, &opt) == -1) {
157 goto err;
158 }
160 if(strcmp(opt.name, "texture")) {
161 if(opt.type != OPT_STR) {
162 goto err;
163 }
164 /* XXX cont. */
165 }
166 }
168 err:
169 fprintf(stderr, "Line %d: error parsing particle definition\n", lineno);
170 psys_destroy_attr(attr);
171 return -1;
172 }
174 /* strdup on the stack with alloca */
175 #define strdup_stack(s) \
176 do { \
177 size_t len = strlen(s); \
178 char *res = alloca(len + 1); \
179 memcpy(res, s, len + 1); \
180 } while(0)
182 static int get_cfg_opt(const char *line, struct cfgopt *opt)
183 {
184 char *buf;
185 float tmsec;
187 line = stripspace(line);
188 if(line[0] == '#' || !line[0]) {
189 return 0; /* skip empty lines and comments */
190 }
191 if(!(opt->valstr = strchr(line, '='))) {
192 return -1;
193 }
194 *opt->valstr++ = 0;
195 opt->valstr = stripspace(opt->valstr);
197 /* allocate a working buffer on the stack that could fit the current line */
198 buf = alloca(strlen(line) + 1);
200 if(sscanf(line, "%s(%fs)", buf, &tmsec) == 2) {
201 opt->tm = (long)(tmsec * 1000.0f);
202 opt->name = strdup_stack(buf);
203 } else if(sscanf(line, "%s(%ld)", buf, &opt->tm) == 2) {
204 opt->name = strdup_stack(buf);
205 } else {
206 opt->name = strdup_stack(buf);
207 opt->tm = 0;
208 }
210 if(sscanf(opt->valstr, "[%f %f %f] ~ [%f %f %f]", &opt->val.x, &opt->val.y, &opt->val.z,
211 &opt->valrng.x, &opt->valrng.y, &opt->valrng.z) == 6) {
212 /* value is a vector range */
213 opt->type = OPT_VEC_RANGE;
215 } else if(sscanf(opt->valstr, "%f ~ %f", &opt->val.x, &opt->valrng.x) == 2) {
216 /* value is a number range */
217 opt->type = OPT_NUM_RANGE;
218 opt->val.y = opt->val.z = opt->val.x;
219 opt->valrng.y = opt->valrng.z = opt->valrgn.x;
221 } else if(sscanf(opt->valstr, "[%f %f %f]", &opt->val.x, &opt->val.y, &opt->val.z) == 3) {
222 /* value is a vector */
223 opt->type = OPT_VEC;
224 opt->valrng.x = opt->valrng.y = opt->valrng.z = 0.0f;
226 } else if(sscanf(opt->valstr, "%f", &opt->val.x) == 1) {
227 /* value is a number */
228 opt->type = OPT_NUM;
229 opt->val.y = opt->val.z = opt->val.x;
230 opt->valrng.x = opt->valrng.y = opt->valrng.z = 0.0f;
232 } else if(sscanf(opt->valstr, "\"%s\"", buf) == 1) {
233 /* just a string... strip the quotes */
234 opt->type = OPT_STR;
235 opt->valstr = strdup_stack(buf);
236 } else {
237 /* fuck it ... */
238 return -1;
239 }
241 return 0;
242 }
246 int psys_save_attr(struct psys_attributes *attr, const char *fname)
247 {
248 FILE *fp;
249 int res;
251 if(!(fp = fopen(fname, "w"))) {
252 fprintf(stderr, "%s: failed to write file: %s: %s\n", __func__, fname, strerror(errno));
253 return -1;
254 }
255 res = psys_save_attr_stream(attr, fp);
256 fclose(fp);
257 return res;
258 }
260 int psys_save_attr_stream(struct psys_attributes *attr, FILE *fp)
261 {
262 return -1; /* TODO */
263 }
266 static char *stripspace(char *str)
267 {
268 char *end;
270 while(*str && isspace(*str)) {
271 str++;
272 }
274 end = str + strlen(str);
275 while(end >= str && isspace(*end)) {
276 *end-- = 0;
277 }
278 return str;
279 }