1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2004 the VideoLAN team
7 * Authors: Cyril Deguet <asmax@videolan.org>
8 * code from projectM http://xmms-projectm.sourceforge.net
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
31 #include "param_types.h"
34 #include "expr_types.h"
37 #include "splaytree_types.h"
38 #include "splaytree.h"
39 #include "tree_types.h"
41 #include "per_frame_eqn_types.h"
42 #include "per_frame_eqn.h"
44 #include "init_cond_types.h"
45 #include "init_cond.h"
47 #include "preset_types.h"
49 #include "custom_shape_types.h"
50 #include "custom_shape.h"
52 #include "init_cond_types.h"
53 #include "init_cond.h"
55 custom_shape_t * interface_shape = NULL;
56 int cwave_interface_id = 0;
57 extern preset_t * active_preset;
58 static inline void eval_custom_shape_init_conds(custom_shape_t * custom_shape);
59 void load_unspec_init_cond_shape(param_t * param);
61 void destroy_param_db_tree_shape(splaytree_t * tree);
62 void destroy_per_frame_eqn_tree_shape(splaytree_t * tree);
63 void destroy_per_frame_init_eqn_tree_shape(splaytree_t * tree);
64 void destroy_init_cond_tree_shape(splaytree_t * tree);
66 custom_shape_t * new_custom_shape(int id) {
68 custom_shape_t * custom_shape;
71 if ((custom_shape = (custom_shape_t*)malloc(sizeof(custom_shape_t))) == NULL)
74 custom_shape->id = id;
75 custom_shape->per_frame_count = 0;
76 custom_shape->per_frame_eqn_string_index = 0;
77 custom_shape->per_frame_init_eqn_string_index = 0;
79 /* Initialize tree data structures */
81 if ((custom_shape->param_tree =
82 create_splaytree(compare_string, copy_string, free_string)) == NULL) {
83 free_custom_shape(custom_shape);
87 if ((custom_shape->per_frame_eqn_tree =
88 create_splaytree(compare_int, copy_int, free_int)) == NULL) {
89 free_custom_shape(custom_shape);
93 if ((custom_shape->init_cond_tree =
94 create_splaytree(compare_string, copy_string, free_string)) == NULL) {
95 free_custom_shape(custom_shape);
99 if ((custom_shape->per_frame_init_eqn_tree =
100 create_splaytree(compare_string, copy_string, free_string)) == NULL) {
101 free_custom_shape(custom_shape);
105 /* Start: Load custom shape parameters */
107 if ((param = new_param_double("r", P_FLAG_NONE, &custom_shape->r, NULL, 1.0, 0.0, .5)) == NULL) {
108 free_custom_shape(custom_shape);
112 if (insert_param(param, custom_shape->param_tree) < 0) {
113 free_custom_shape(custom_shape);
117 if ((param = new_param_double("g", P_FLAG_NONE, &custom_shape->g, NULL, 1.0, 0.0, .5)) == NULL){
118 free_custom_shape(custom_shape);
122 if (insert_param(param, custom_shape->param_tree) < 0) {
123 free_custom_shape(custom_shape);
127 if ((param = new_param_double("b", P_FLAG_NONE, &custom_shape->b, NULL, 1.0, 0.0, .5)) == NULL){
128 free_custom_shape(custom_shape);
132 if (insert_param(param, custom_shape->param_tree) < 0) {
133 free_custom_shape(custom_shape);
137 if ((param = new_param_double("a", P_FLAG_NONE, &custom_shape->a, NULL, 1.0, 0.0, .5)) == NULL){
138 free_custom_shape(custom_shape);
142 if (insert_param(param, custom_shape->param_tree) < 0) {
143 free_custom_shape(custom_shape);
147 if ((param = new_param_double("border_r", P_FLAG_NONE, &custom_shape->border_r, NULL, 1.0, 0.0, .5)) == NULL) {
148 free_custom_shape(custom_shape);
152 if (insert_param(param, custom_shape->param_tree) < 0) {
153 free_custom_shape(custom_shape);
157 if ((param = new_param_double("border_g", P_FLAG_NONE, &custom_shape->border_g, NULL, 1.0, 0.0, .5)) == NULL){
158 free_custom_shape(custom_shape);
162 if (insert_param(param, custom_shape->param_tree) < 0) {
163 free_custom_shape(custom_shape);
167 if ((param = new_param_double("border_b", P_FLAG_NONE, &custom_shape->border_b, NULL, 1.0, 0.0, .5)) == NULL){
168 free_custom_shape(custom_shape);
172 if (insert_param(param, custom_shape->param_tree) < 0) {
173 free_custom_shape(custom_shape);
177 if ((param = new_param_double("border_a", P_FLAG_NONE, &custom_shape->border_a, NULL, 1.0, 0.0, .5)) == NULL){
178 free_custom_shape(custom_shape);
182 if (insert_param(param, custom_shape->param_tree) < 0) {
183 free_custom_shape(custom_shape);
187 if ((param = new_param_double("r2", P_FLAG_NONE, &custom_shape->r2, NULL, 1.0, 0.0, .5)) == NULL) {
188 free_custom_shape(custom_shape);
192 if (insert_param(param, custom_shape->param_tree) < 0) {
193 free_custom_shape(custom_shape);
197 if ((param = new_param_double("g2", P_FLAG_NONE, &custom_shape->g2, NULL, 1.0, 0.0, .5)) == NULL){
198 free_custom_shape(custom_shape);
202 if (insert_param(param, custom_shape->param_tree) < 0) {
203 free_custom_shape(custom_shape);
207 if ((param = new_param_double("b2", P_FLAG_NONE, &custom_shape->b2, NULL, 1.0, 0.0, .5)) == NULL){
208 free_custom_shape(custom_shape);
212 if (insert_param(param, custom_shape->param_tree) < 0) {
213 free_custom_shape(custom_shape);
217 if ((param = new_param_double("a2", P_FLAG_NONE, &custom_shape->a2, NULL, 1.0, 0.0, .5)) == NULL){
218 free_custom_shape(custom_shape);
222 if (insert_param(param, custom_shape->param_tree) < 0) {
223 free_custom_shape(custom_shape);
227 if ((param = new_param_double("x", P_FLAG_NONE, &custom_shape->x, NULL, 1.0, 0.0, .5)) == NULL) {
228 free_custom_shape(custom_shape);
232 if (insert_param(param, custom_shape->param_tree) < 0) {
233 free_custom_shape(custom_shape);
237 if ((param = new_param_double("y", P_FLAG_NONE, &custom_shape->y, NULL, 1.0, 0.0, .5)) == NULL) {
238 free_custom_shape(custom_shape);
242 if (insert_param(param, custom_shape->param_tree) < 0) {
243 free_custom_shape(custom_shape);
247 if ((param = new_param_bool("thickOutline", P_FLAG_NONE, &custom_shape->thickOutline, 1, 0, 0)) == NULL) {
248 free_custom_shape(custom_shape);
252 if (insert_param(param, custom_shape->param_tree) < 0) {
253 free_custom_shape(custom_shape);
257 if ((param = new_param_bool("enabled", P_FLAG_NONE, &custom_shape->enabled, 1, 0, 0)) == NULL) {
258 free_custom_shape(custom_shape);
262 if (insert_param(param, custom_shape->param_tree) < 0) {
263 free_custom_shape(custom_shape);
267 if ((param = new_param_int("sides", P_FLAG_NONE, &custom_shape->sides, 100, 3, 3)) == NULL) {
268 free_custom_shape(custom_shape);
272 if (insert_param(param, custom_shape->param_tree) < 0) {
273 free_custom_shape(custom_shape);
277 if ((param = new_param_bool("additive", P_FLAG_NONE, &custom_shape->additive, 1, 0, 0)) == NULL) {
278 free_custom_shape(custom_shape);
282 if (insert_param(param, custom_shape->param_tree) < 0) {
283 free_custom_shape(custom_shape);
287 if ((param = new_param_bool("textured", P_FLAG_NONE, &custom_shape->textured, 1, 0, 0)) == NULL) {
288 free_custom_shape(custom_shape);
292 if (insert_param(param, custom_shape->param_tree) < 0) {
293 free_custom_shape(custom_shape);
297 if ((param = new_param_double("rad", P_FLAG_NONE, &custom_shape->rad, NULL, MAX_DOUBLE_SIZE, 0, 0.0)) == NULL) {
298 free_custom_shape(custom_shape);
302 if (insert_param(param, custom_shape->param_tree) < 0) {
303 free_custom_shape(custom_shape);
307 if ((param = new_param_double("ang", P_FLAG_NONE, &custom_shape->ang, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
308 free_custom_shape(custom_shape);
312 if (insert_param(param, custom_shape->param_tree) < 0) {
313 free_custom_shape(custom_shape);
317 if ((param = new_param_double("tex_zoom", P_FLAG_NONE, &custom_shape->tex_zoom, NULL, MAX_DOUBLE_SIZE, .00000000001, 0.0)) == NULL) {
318 free_custom_shape(custom_shape);
322 if (insert_param(param, custom_shape->param_tree) < 0) {
323 free_custom_shape(custom_shape);
327 if ((param = new_param_double("tex_ang", P_FLAG_NONE, &custom_shape->tex_ang, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
328 free_custom_shape(custom_shape);
332 if (insert_param(param, custom_shape->param_tree) < 0) {
333 free_custom_shape(custom_shape);
336 if ((param = new_param_double("t1", P_FLAG_TVAR, &custom_shape->t1, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
337 free_custom_shape(custom_shape);
341 if (insert_param(param, custom_shape->param_tree) < 0) {
342 free_custom_shape(custom_shape);
346 if ((param = new_param_double("t2", P_FLAG_TVAR, &custom_shape->t2, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
347 free_custom_shape(custom_shape);
351 if (insert_param(param, custom_shape->param_tree) < 0) {
352 free_custom_shape(custom_shape);
356 if ((param = new_param_double("t3", P_FLAG_TVAR, &custom_shape->t3, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
357 free_custom_shape(custom_shape);
361 if (insert_param(param, custom_shape->param_tree) < 0) {
362 free_custom_shape(custom_shape);
365 if ((param = new_param_double("t4", P_FLAG_TVAR, &custom_shape->t4, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
366 free_custom_shape(custom_shape);
370 if (insert_param(param, custom_shape->param_tree) < 0) {
371 free_custom_shape(custom_shape);
374 if ((param = new_param_double("t5", P_FLAG_TVAR, &custom_shape->t5, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
375 free_custom_shape(custom_shape);
379 if (insert_param(param, custom_shape->param_tree) < 0) {
380 free_custom_shape(custom_shape);
383 if ((param = new_param_double("t6", P_FLAG_TVAR, &custom_shape->t6, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
384 free_custom_shape(custom_shape);
388 if (insert_param(param, custom_shape->param_tree) < 0) {
389 free_custom_shape(custom_shape);
392 if ((param = new_param_double("t7", P_FLAG_TVAR, &custom_shape->t7, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
393 free_custom_shape(custom_shape);
397 if (insert_param(param, custom_shape->param_tree) < 0) {
398 free_custom_shape(custom_shape);
402 if ((param = new_param_double("t8", P_FLAG_TVAR, &custom_shape->t8, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
403 free_custom_shape(custom_shape);
407 if (insert_param(param, custom_shape->param_tree) < 0) {
408 free_custom_shape(custom_shape);
412 /* End of parameter loading. Note that the read only parameters associated
413 with custom shapes (ie, sample) are global variables, and not specific to
414 the custom shape datastructure. */
422 void destroy_per_frame_init_eqn_tree_shape(splaytree_t * tree) {
427 splay_traverse(free_init_cond, tree);
428 destroy_splaytree(tree);
434 void destroy_init_cond_tree_shape(splaytree_t * tree) {
439 splay_traverse(free_init_cond, tree);
440 destroy_splaytree(tree);
444 void destroy_per_frame_eqn_tree_shape(splaytree_t * tree) {
450 splay_traverse(free_per_frame_eqn, tree);
451 destroy_splaytree(tree);
456 void destroy_param_db_tree_shape(splaytree_t * tree) {
461 splay_traverse(free_param, tree);
462 destroy_splaytree(tree);
466 /* Frees a custom shape form object */
467 void free_custom_shape(custom_shape_t * custom_shape) {
469 if (custom_shape == NULL)
472 if (custom_shape->param_tree == NULL)
475 destroy_per_frame_eqn_tree_shape(custom_shape->per_frame_eqn_tree);
476 destroy_init_cond_tree_shape(custom_shape->init_cond_tree);
477 destroy_param_db_tree_shape(custom_shape->param_tree);
478 destroy_per_frame_init_eqn_tree_shape(custom_shape->per_frame_init_eqn_tree);
487 custom_shape_t * find_custom_shape(int id, preset_t * preset, int create_flag) {
489 custom_shape_t * custom_shape = NULL;
494 if ((custom_shape = splay_find(&id, preset->custom_shape_tree)) == NULL) {
496 if (CUSTOM_SHAPE_DEBUG) { printf("find_custom_shape: creating custom shape (id = %d)...", id);fflush(stdout);}
498 if (create_flag == FALSE) {
499 if (CUSTOM_SHAPE_DEBUG) printf("you specified not to (create flag = false), returning null\n");
503 if ((custom_shape = new_custom_shape(id)) == NULL) {
504 if (CUSTOM_SHAPE_DEBUG) printf("failed...out of memory?\n");
508 if (CUSTOM_SHAPE_DEBUG) { printf("success.Inserting..."); fflush(stdout);}
510 if (splay_insert(custom_shape, &custom_shape->id, preset->custom_shape_tree) < 0) {
511 if (CUSTOM_SHAPE_DEBUG) printf("failed, probably a duplicated!!\n");
512 free_custom_shape(custom_shape);
516 if (CUSTOM_SHAPE_DEBUG) printf("done.\n");
522 void evalCustomShapeInitConditions() {
523 splay_traverse(eval_custom_shape_init_conds, active_preset->custom_shape_tree);
527 static inline void eval_custom_shape_init_conds(custom_shape_t * custom_shape) {
528 splay_traverse(eval_init_cond, custom_shape->init_cond_tree);
529 splay_traverse(eval_init_cond, custom_shape->per_frame_init_eqn_tree);
533 void load_unspecified_init_conds_shape(custom_shape_t * custom_shape) {
535 interface_shape = custom_shape;
536 splay_traverse(load_unspec_init_cond_shape, interface_shape->param_tree);
537 interface_shape = NULL;
541 void load_unspec_init_cond_shape(param_t * param) {
543 init_cond_t * init_cond;
546 /* Don't count read only parameters as initial conditions */
547 if (param->flags & P_FLAG_READONLY)
549 if (param->flags & P_FLAG_QVAR)
551 if (param->flags & P_FLAG_TVAR)
553 if (param->flags & P_FLAG_USERDEF)
556 /* If initial condition was not defined by the preset file, force a default one
557 with the following code */
558 if ((init_cond = splay_find(param->name, interface_shape->init_cond_tree)) == NULL) {
560 /* Make sure initial condition does not exist in the set of per frame initial equations */
561 if ((init_cond = splay_find(param->name, interface_shape->per_frame_init_eqn_tree)) != NULL)
564 if (param->type == P_TYPE_BOOL)
565 init_val.bool_val = 0;
567 else if (param->type == P_TYPE_INT)
568 init_val.int_val = *(int*)param->engine_val;
570 else if (param->type == P_TYPE_DOUBLE)
571 init_val.double_val = *(double*)param->engine_val;
573 //printf("%s\n", param->name);
574 /* Create new initial condition */
575 if ((init_cond = new_init_cond(param, init_val)) == NULL)
578 /* Insert the initial condition into this presets tree */
579 if (splay_insert(init_cond, init_cond->param->name, interface_shape->init_cond_tree) < 0) {
580 free_init_cond(init_cond);
589 /* Interface function. Makes another custom shape the current
590 concern for per frame / point equations */
591 custom_shape_t * nextCustomShape() {
593 if ((interface_shape = splay_find(&cwave_interface_id, active_preset->custom_shape_tree)) == NULL) {
594 cwave_interface_id = 0;
598 cwave_interface_id++;
600 /* Evaluate all per frame equations associated with this shape */
601 splay_traverse(eval_per_frame_eqn, interface_shape->per_frame_eqn_tree);
602 return interface_shape;