libpsys

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