1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2004 VideoLAN (Centrale Réseaux) and its contributors
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., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
23 *****************************************************************************/
35 #include "param_types.h"
38 #include "expr_types.h"
41 #include "splaytree_types.h"
42 #include "splaytree.h"
43 #include "tree_types.h"
45 #include "per_frame_eqn_types.h"
46 #include "per_frame_eqn.h"
48 #include "init_cond_types.h"
49 #include "init_cond.h"
51 #include "preset_types.h"
53 #include "custom_shape_types.h"
54 #include "custom_shape.h"
56 #include "init_cond_types.h"
57 #include "init_cond.h"
59 custom_shape_t * interface_shape = NULL;
60 int cwave_interface_id = 0;
61 extern preset_t * active_preset;
62 inline void eval_custom_shape_init_conds(custom_shape_t * custom_shape);
63 void load_unspec_init_cond_shape(param_t * param);
65 void destroy_param_db_tree_shape(splaytree_t * tree);
66 void destroy_per_frame_eqn_tree_shape(splaytree_t * tree);
67 void destroy_per_frame_init_eqn_tree_shape(splaytree_t * tree);
68 void destroy_init_cond_tree_shape(splaytree_t * tree);
70 custom_shape_t * new_custom_shape(int id) {
72 custom_shape_t * custom_shape;
75 if ((custom_shape = (custom_shape_t*)malloc(sizeof(custom_shape_t))) == NULL)
78 custom_shape->id = id;
79 custom_shape->per_frame_count = 0;
80 custom_shape->per_frame_eqn_string_index = 0;
81 custom_shape->per_frame_init_eqn_string_index = 0;
83 /* Initialize tree data structures */
85 if ((custom_shape->param_tree =
86 create_splaytree(compare_string, copy_string, free_string)) == NULL) {
87 free_custom_shape(custom_shape);
91 if ((custom_shape->per_frame_eqn_tree =
92 create_splaytree(compare_int, copy_int, free_int)) == NULL) {
93 free_custom_shape(custom_shape);
97 if ((custom_shape->init_cond_tree =
98 create_splaytree(compare_string, copy_string, free_string)) == NULL) {
99 free_custom_shape(custom_shape);
103 if ((custom_shape->per_frame_init_eqn_tree =
104 create_splaytree(compare_string, copy_string, free_string)) == NULL) {
105 free_custom_shape(custom_shape);
109 /* Start: Load custom shape parameters */
111 if ((param = new_param_double("r", P_FLAG_NONE, &custom_shape->r, NULL, 1.0, 0.0, .5)) == NULL) {
112 free_custom_shape(custom_shape);
116 if (insert_param(param, custom_shape->param_tree) < 0) {
117 free_custom_shape(custom_shape);
121 if ((param = new_param_double("g", P_FLAG_NONE, &custom_shape->g, NULL, 1.0, 0.0, .5)) == NULL){
122 free_custom_shape(custom_shape);
126 if (insert_param(param, custom_shape->param_tree) < 0) {
127 free_custom_shape(custom_shape);
131 if ((param = new_param_double("b", P_FLAG_NONE, &custom_shape->b, NULL, 1.0, 0.0, .5)) == NULL){
132 free_custom_shape(custom_shape);
136 if (insert_param(param, custom_shape->param_tree) < 0) {
137 free_custom_shape(custom_shape);
141 if ((param = new_param_double("a", P_FLAG_NONE, &custom_shape->a, NULL, 1.0, 0.0, .5)) == NULL){
142 free_custom_shape(custom_shape);
146 if (insert_param(param, custom_shape->param_tree) < 0) {
147 free_custom_shape(custom_shape);
151 if ((param = new_param_double("border_r", P_FLAG_NONE, &custom_shape->border_r, NULL, 1.0, 0.0, .5)) == NULL) {
152 free_custom_shape(custom_shape);
156 if (insert_param(param, custom_shape->param_tree) < 0) {
157 free_custom_shape(custom_shape);
161 if ((param = new_param_double("border_g", P_FLAG_NONE, &custom_shape->border_g, NULL, 1.0, 0.0, .5)) == NULL){
162 free_custom_shape(custom_shape);
166 if (insert_param(param, custom_shape->param_tree) < 0) {
167 free_custom_shape(custom_shape);
171 if ((param = new_param_double("border_b", P_FLAG_NONE, &custom_shape->border_b, NULL, 1.0, 0.0, .5)) == NULL){
172 free_custom_shape(custom_shape);
176 if (insert_param(param, custom_shape->param_tree) < 0) {
177 free_custom_shape(custom_shape);
181 if ((param = new_param_double("border_a", P_FLAG_NONE, &custom_shape->border_a, NULL, 1.0, 0.0, .5)) == NULL){
182 free_custom_shape(custom_shape);
186 if (insert_param(param, custom_shape->param_tree) < 0) {
187 free_custom_shape(custom_shape);
191 if ((param = new_param_double("r2", P_FLAG_NONE, &custom_shape->r2, NULL, 1.0, 0.0, .5)) == NULL) {
192 free_custom_shape(custom_shape);
196 if (insert_param(param, custom_shape->param_tree) < 0) {
197 free_custom_shape(custom_shape);
201 if ((param = new_param_double("g2", P_FLAG_NONE, &custom_shape->g2, NULL, 1.0, 0.0, .5)) == NULL){
202 free_custom_shape(custom_shape);
206 if (insert_param(param, custom_shape->param_tree) < 0) {
207 free_custom_shape(custom_shape);
211 if ((param = new_param_double("b2", P_FLAG_NONE, &custom_shape->b2, NULL, 1.0, 0.0, .5)) == NULL){
212 free_custom_shape(custom_shape);
216 if (insert_param(param, custom_shape->param_tree) < 0) {
217 free_custom_shape(custom_shape);
221 if ((param = new_param_double("a2", P_FLAG_NONE, &custom_shape->a2, NULL, 1.0, 0.0, .5)) == NULL){
222 free_custom_shape(custom_shape);
226 if (insert_param(param, custom_shape->param_tree) < 0) {
227 free_custom_shape(custom_shape);
231 if ((param = new_param_double("x", P_FLAG_NONE, &custom_shape->x, NULL, 1.0, 0.0, .5)) == NULL) {
232 free_custom_shape(custom_shape);
236 if (insert_param(param, custom_shape->param_tree) < 0) {
237 free_custom_shape(custom_shape);
241 if ((param = new_param_double("y", P_FLAG_NONE, &custom_shape->y, NULL, 1.0, 0.0, .5)) == NULL) {
242 free_custom_shape(custom_shape);
246 if (insert_param(param, custom_shape->param_tree) < 0) {
247 free_custom_shape(custom_shape);
251 if ((param = new_param_bool("thickOutline", P_FLAG_NONE, &custom_shape->thickOutline, 1, 0, 0)) == NULL) {
252 free_custom_shape(custom_shape);
256 if (insert_param(param, custom_shape->param_tree) < 0) {
257 free_custom_shape(custom_shape);
261 if ((param = new_param_bool("enabled", P_FLAG_NONE, &custom_shape->enabled, 1, 0, 0)) == NULL) {
262 free_custom_shape(custom_shape);
266 if (insert_param(param, custom_shape->param_tree) < 0) {
267 free_custom_shape(custom_shape);
271 if ((param = new_param_int("sides", P_FLAG_NONE, &custom_shape->sides, 100, 3, 3)) == NULL) {
272 free_custom_shape(custom_shape);
276 if (insert_param(param, custom_shape->param_tree) < 0) {
277 free_custom_shape(custom_shape);
281 if ((param = new_param_bool("additive", P_FLAG_NONE, &custom_shape->additive, 1, 0, 0)) == NULL) {
282 free_custom_shape(custom_shape);
286 if (insert_param(param, custom_shape->param_tree) < 0) {
287 free_custom_shape(custom_shape);
291 if ((param = new_param_bool("textured", P_FLAG_NONE, &custom_shape->textured, 1, 0, 0)) == NULL) {
292 free_custom_shape(custom_shape);
296 if (insert_param(param, custom_shape->param_tree) < 0) {
297 free_custom_shape(custom_shape);
301 if ((param = new_param_double("rad", P_FLAG_NONE, &custom_shape->rad, NULL, MAX_DOUBLE_SIZE, 0, 0.0)) == NULL) {
302 free_custom_shape(custom_shape);
306 if (insert_param(param, custom_shape->param_tree) < 0) {
307 free_custom_shape(custom_shape);
311 if ((param = new_param_double("ang", P_FLAG_NONE, &custom_shape->ang, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
312 free_custom_shape(custom_shape);
316 if (insert_param(param, custom_shape->param_tree) < 0) {
317 free_custom_shape(custom_shape);
321 if ((param = new_param_double("tex_zoom", P_FLAG_NONE, &custom_shape->tex_zoom, NULL, MAX_DOUBLE_SIZE, .00000000001, 0.0)) == NULL) {
322 free_custom_shape(custom_shape);
326 if (insert_param(param, custom_shape->param_tree) < 0) {
327 free_custom_shape(custom_shape);
331 if ((param = new_param_double("tex_ang", P_FLAG_NONE, &custom_shape->tex_ang, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
332 free_custom_shape(custom_shape);
336 if (insert_param(param, custom_shape->param_tree) < 0) {
337 free_custom_shape(custom_shape);
340 if ((param = new_param_double("t1", P_FLAG_TVAR, &custom_shape->t1, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
341 free_custom_shape(custom_shape);
345 if (insert_param(param, custom_shape->param_tree) < 0) {
346 free_custom_shape(custom_shape);
350 if ((param = new_param_double("t2", P_FLAG_TVAR, &custom_shape->t2, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
351 free_custom_shape(custom_shape);
355 if (insert_param(param, custom_shape->param_tree) < 0) {
356 free_custom_shape(custom_shape);
360 if ((param = new_param_double("t3", P_FLAG_TVAR, &custom_shape->t3, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
361 free_custom_shape(custom_shape);
365 if (insert_param(param, custom_shape->param_tree) < 0) {
366 free_custom_shape(custom_shape);
369 if ((param = new_param_double("t4", P_FLAG_TVAR, &custom_shape->t4, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
370 free_custom_shape(custom_shape);
374 if (insert_param(param, custom_shape->param_tree) < 0) {
375 free_custom_shape(custom_shape);
378 if ((param = new_param_double("t5", P_FLAG_TVAR, &custom_shape->t5, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
379 free_custom_shape(custom_shape);
383 if (insert_param(param, custom_shape->param_tree) < 0) {
384 free_custom_shape(custom_shape);
387 if ((param = new_param_double("t6", P_FLAG_TVAR, &custom_shape->t6, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
388 free_custom_shape(custom_shape);
392 if (insert_param(param, custom_shape->param_tree) < 0) {
393 free_custom_shape(custom_shape);
396 if ((param = new_param_double("t7", P_FLAG_TVAR, &custom_shape->t7, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
397 free_custom_shape(custom_shape);
401 if (insert_param(param, custom_shape->param_tree) < 0) {
402 free_custom_shape(custom_shape);
406 if ((param = new_param_double("t8", P_FLAG_TVAR, &custom_shape->t8, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
407 free_custom_shape(custom_shape);
411 if (insert_param(param, custom_shape->param_tree) < 0) {
412 free_custom_shape(custom_shape);
416 /* End of parameter loading. Note that the read only parameters associated
417 with custom shapes (ie, sample) are global variables, and not specific to
418 the custom shape datastructure. */
426 void destroy_per_frame_init_eqn_tree_shape(splaytree_t * tree) {
431 splay_traverse(free_init_cond, tree);
432 destroy_splaytree(tree);
438 void destroy_init_cond_tree_shape(splaytree_t * tree) {
443 splay_traverse(free_init_cond, tree);
444 destroy_splaytree(tree);
448 void destroy_per_frame_eqn_tree_shape(splaytree_t * tree) {
454 splay_traverse(free_per_frame_eqn, tree);
455 destroy_splaytree(tree);
460 void destroy_param_db_tree_shape(splaytree_t * tree) {
465 splay_traverse(free_param, tree);
466 destroy_splaytree(tree);
470 /* Frees a custom shape form object */
471 void free_custom_shape(custom_shape_t * custom_shape) {
473 if (custom_shape == NULL)
476 if (custom_shape->param_tree == NULL)
479 destroy_per_frame_eqn_tree_shape(custom_shape->per_frame_eqn_tree);
480 destroy_init_cond_tree_shape(custom_shape->init_cond_tree);
481 destroy_param_db_tree_shape(custom_shape->param_tree);
482 destroy_per_frame_init_eqn_tree_shape(custom_shape->per_frame_init_eqn_tree);
491 custom_shape_t * find_custom_shape(int id, preset_t * preset, int create_flag) {
493 custom_shape_t * custom_shape = NULL;
498 if ((custom_shape = splay_find(&id, preset->custom_shape_tree)) == NULL) {
500 if (CUSTOM_SHAPE_DEBUG) { printf("find_custom_shape: creating custom shape (id = %d)...", id);fflush(stdout);}
502 if (create_flag == FALSE) {
503 if (CUSTOM_SHAPE_DEBUG) printf("you specified not to (create flag = false), returning null\n");
507 if ((custom_shape = new_custom_shape(id)) == NULL) {
508 if (CUSTOM_SHAPE_DEBUG) printf("failed...out of memory?\n");
512 if (CUSTOM_SHAPE_DEBUG) { printf("success.Inserting..."); fflush(stdout);}
514 if (splay_insert(custom_shape, &custom_shape->id, preset->custom_shape_tree) < 0) {
515 if (CUSTOM_SHAPE_DEBUG) printf("failed, probably a duplicated!!\n");
516 free_custom_shape(custom_shape);
520 if (CUSTOM_SHAPE_DEBUG) printf("done.\n");
526 inline void evalCustomShapeInitConditions() {
527 splay_traverse(eval_custom_shape_init_conds, active_preset->custom_shape_tree);
531 inline void eval_custom_shape_init_conds(custom_shape_t * custom_shape) {
532 splay_traverse(eval_init_cond, custom_shape->init_cond_tree);
533 splay_traverse(eval_init_cond, custom_shape->per_frame_init_eqn_tree);
537 void load_unspecified_init_conds_shape(custom_shape_t * custom_shape) {
539 interface_shape = custom_shape;
540 splay_traverse(load_unspec_init_cond_shape, interface_shape->param_tree);
541 interface_shape = NULL;
545 void load_unspec_init_cond_shape(param_t * param) {
547 init_cond_t * init_cond;
550 /* Don't count read only parameters as initial conditions */
551 if (param->flags & P_FLAG_READONLY)
553 if (param->flags & P_FLAG_QVAR)
555 if (param->flags & P_FLAG_TVAR)
557 if (param->flags & P_FLAG_USERDEF)
560 /* If initial condition was not defined by the preset file, force a default one
561 with the following code */
562 if ((init_cond = splay_find(param->name, interface_shape->init_cond_tree)) == NULL) {
564 /* Make sure initial condition does not exist in the set of per frame initial equations */
565 if ((init_cond = splay_find(param->name, interface_shape->per_frame_init_eqn_tree)) != NULL)
568 if (param->type == P_TYPE_BOOL)
569 init_val.bool_val = 0;
571 else if (param->type == P_TYPE_INT)
572 init_val.int_val = *(int*)param->engine_val;
574 else if (param->type == P_TYPE_DOUBLE)
575 init_val.double_val = *(double*)param->engine_val;
577 //printf("%s\n", param->name);
578 /* Create new initial condition */
579 if ((init_cond = new_init_cond(param, init_val)) == NULL)
582 /* Insert the initial condition into this presets tree */
583 if (splay_insert(init_cond, init_cond->param->name, interface_shape->init_cond_tree) < 0) {
584 free_init_cond(init_cond);
593 /* Interface function. Makes another custom shape the current
594 concern for per frame / point equations */
595 inline custom_shape_t * nextCustomShape() {
597 if ((interface_shape = splay_find(&cwave_interface_id, active_preset->custom_shape_tree)) == NULL) {
598 cwave_interface_id = 0;
602 cwave_interface_id++;
604 /* Evaluate all per frame equations associated with this shape */
605 splay_traverse(eval_per_frame_eqn, interface_shape->per_frame_eqn_tree);
606 return interface_shape;