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 *****************************************************************************/
32 #include "param_types.h"
35 #include "expr_types.h"
38 #include "splaytree_types.h"
39 #include "splaytree.h"
40 #include "tree_types.h"
42 #include "per_frame_eqn_types.h"
43 #include "per_frame_eqn.h"
45 #include "init_cond_types.h"
46 #include "init_cond.h"
48 #include "preset_types.h"
50 #include "custom_shape_types.h"
51 #include "custom_shape.h"
53 #include "init_cond_types.h"
54 #include "init_cond.h"
56 custom_shape_t * interface_shape = NULL;
57 int cwave_interface_id = 0;
58 extern preset_t * active_preset;
59 inline void eval_custom_shape_init_conds(custom_shape_t * custom_shape);
60 void load_unspec_init_cond_shape(param_t * param);
62 void destroy_param_db_tree_shape(splaytree_t * tree);
63 void destroy_per_frame_eqn_tree_shape(splaytree_t * tree);
64 void destroy_per_frame_init_eqn_tree_shape(splaytree_t * tree);
65 void destroy_init_cond_tree_shape(splaytree_t * tree);
67 custom_shape_t * new_custom_shape(int id) {
69 custom_shape_t * custom_shape;
72 if ((custom_shape = (custom_shape_t*)malloc(sizeof(custom_shape_t))) == NULL)
75 custom_shape->id = id;
76 custom_shape->per_frame_count = 0;
77 custom_shape->per_frame_eqn_string_index = 0;
78 custom_shape->per_frame_init_eqn_string_index = 0;
80 /* Initialize tree data structures */
82 if ((custom_shape->param_tree =
83 create_splaytree(compare_string, copy_string, free_string)) == NULL) {
84 free_custom_shape(custom_shape);
88 if ((custom_shape->per_frame_eqn_tree =
89 create_splaytree(compare_int, copy_int, free_int)) == NULL) {
90 free_custom_shape(custom_shape);
94 if ((custom_shape->init_cond_tree =
95 create_splaytree(compare_string, copy_string, free_string)) == NULL) {
96 free_custom_shape(custom_shape);
100 if ((custom_shape->per_frame_init_eqn_tree =
101 create_splaytree(compare_string, copy_string, free_string)) == NULL) {
102 free_custom_shape(custom_shape);
106 /* Start: Load custom shape parameters */
108 if ((param = new_param_double("r", P_FLAG_NONE, &custom_shape->r, NULL, 1.0, 0.0, .5)) == NULL) {
109 free_custom_shape(custom_shape);
113 if (insert_param(param, custom_shape->param_tree) < 0) {
114 free_custom_shape(custom_shape);
118 if ((param = new_param_double("g", P_FLAG_NONE, &custom_shape->g, NULL, 1.0, 0.0, .5)) == NULL){
119 free_custom_shape(custom_shape);
123 if (insert_param(param, custom_shape->param_tree) < 0) {
124 free_custom_shape(custom_shape);
128 if ((param = new_param_double("b", P_FLAG_NONE, &custom_shape->b, NULL, 1.0, 0.0, .5)) == NULL){
129 free_custom_shape(custom_shape);
133 if (insert_param(param, custom_shape->param_tree) < 0) {
134 free_custom_shape(custom_shape);
138 if ((param = new_param_double("a", P_FLAG_NONE, &custom_shape->a, NULL, 1.0, 0.0, .5)) == NULL){
139 free_custom_shape(custom_shape);
143 if (insert_param(param, custom_shape->param_tree) < 0) {
144 free_custom_shape(custom_shape);
148 if ((param = new_param_double("border_r", P_FLAG_NONE, &custom_shape->border_r, NULL, 1.0, 0.0, .5)) == NULL) {
149 free_custom_shape(custom_shape);
153 if (insert_param(param, custom_shape->param_tree) < 0) {
154 free_custom_shape(custom_shape);
158 if ((param = new_param_double("border_g", P_FLAG_NONE, &custom_shape->border_g, NULL, 1.0, 0.0, .5)) == NULL){
159 free_custom_shape(custom_shape);
163 if (insert_param(param, custom_shape->param_tree) < 0) {
164 free_custom_shape(custom_shape);
168 if ((param = new_param_double("border_b", P_FLAG_NONE, &custom_shape->border_b, NULL, 1.0, 0.0, .5)) == NULL){
169 free_custom_shape(custom_shape);
173 if (insert_param(param, custom_shape->param_tree) < 0) {
174 free_custom_shape(custom_shape);
178 if ((param = new_param_double("border_a", P_FLAG_NONE, &custom_shape->border_a, NULL, 1.0, 0.0, .5)) == NULL){
179 free_custom_shape(custom_shape);
183 if (insert_param(param, custom_shape->param_tree) < 0) {
184 free_custom_shape(custom_shape);
188 if ((param = new_param_double("r2", P_FLAG_NONE, &custom_shape->r2, NULL, 1.0, 0.0, .5)) == NULL) {
189 free_custom_shape(custom_shape);
193 if (insert_param(param, custom_shape->param_tree) < 0) {
194 free_custom_shape(custom_shape);
198 if ((param = new_param_double("g2", P_FLAG_NONE, &custom_shape->g2, NULL, 1.0, 0.0, .5)) == NULL){
199 free_custom_shape(custom_shape);
203 if (insert_param(param, custom_shape->param_tree) < 0) {
204 free_custom_shape(custom_shape);
208 if ((param = new_param_double("b2", P_FLAG_NONE, &custom_shape->b2, NULL, 1.0, 0.0, .5)) == NULL){
209 free_custom_shape(custom_shape);
213 if (insert_param(param, custom_shape->param_tree) < 0) {
214 free_custom_shape(custom_shape);
218 if ((param = new_param_double("a2", P_FLAG_NONE, &custom_shape->a2, NULL, 1.0, 0.0, .5)) == NULL){
219 free_custom_shape(custom_shape);
223 if (insert_param(param, custom_shape->param_tree) < 0) {
224 free_custom_shape(custom_shape);
228 if ((param = new_param_double("x", P_FLAG_NONE, &custom_shape->x, NULL, 1.0, 0.0, .5)) == NULL) {
229 free_custom_shape(custom_shape);
233 if (insert_param(param, custom_shape->param_tree) < 0) {
234 free_custom_shape(custom_shape);
238 if ((param = new_param_double("y", P_FLAG_NONE, &custom_shape->y, NULL, 1.0, 0.0, .5)) == NULL) {
239 free_custom_shape(custom_shape);
243 if (insert_param(param, custom_shape->param_tree) < 0) {
244 free_custom_shape(custom_shape);
248 if ((param = new_param_bool("thickOutline", P_FLAG_NONE, &custom_shape->thickOutline, 1, 0, 0)) == NULL) {
249 free_custom_shape(custom_shape);
253 if (insert_param(param, custom_shape->param_tree) < 0) {
254 free_custom_shape(custom_shape);
258 if ((param = new_param_bool("enabled", P_FLAG_NONE, &custom_shape->enabled, 1, 0, 0)) == NULL) {
259 free_custom_shape(custom_shape);
263 if (insert_param(param, custom_shape->param_tree) < 0) {
264 free_custom_shape(custom_shape);
268 if ((param = new_param_int("sides", P_FLAG_NONE, &custom_shape->sides, 100, 3, 3)) == NULL) {
269 free_custom_shape(custom_shape);
273 if (insert_param(param, custom_shape->param_tree) < 0) {
274 free_custom_shape(custom_shape);
278 if ((param = new_param_bool("additive", P_FLAG_NONE, &custom_shape->additive, 1, 0, 0)) == NULL) {
279 free_custom_shape(custom_shape);
283 if (insert_param(param, custom_shape->param_tree) < 0) {
284 free_custom_shape(custom_shape);
288 if ((param = new_param_bool("textured", P_FLAG_NONE, &custom_shape->textured, 1, 0, 0)) == NULL) {
289 free_custom_shape(custom_shape);
293 if (insert_param(param, custom_shape->param_tree) < 0) {
294 free_custom_shape(custom_shape);
298 if ((param = new_param_double("rad", P_FLAG_NONE, &custom_shape->rad, NULL, MAX_DOUBLE_SIZE, 0, 0.0)) == NULL) {
299 free_custom_shape(custom_shape);
303 if (insert_param(param, custom_shape->param_tree) < 0) {
304 free_custom_shape(custom_shape);
308 if ((param = new_param_double("ang", P_FLAG_NONE, &custom_shape->ang, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
309 free_custom_shape(custom_shape);
313 if (insert_param(param, custom_shape->param_tree) < 0) {
314 free_custom_shape(custom_shape);
318 if ((param = new_param_double("tex_zoom", P_FLAG_NONE, &custom_shape->tex_zoom, NULL, MAX_DOUBLE_SIZE, .00000000001, 0.0)) == NULL) {
319 free_custom_shape(custom_shape);
323 if (insert_param(param, custom_shape->param_tree) < 0) {
324 free_custom_shape(custom_shape);
328 if ((param = new_param_double("tex_ang", P_FLAG_NONE, &custom_shape->tex_ang, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
329 free_custom_shape(custom_shape);
333 if (insert_param(param, custom_shape->param_tree) < 0) {
334 free_custom_shape(custom_shape);
337 if ((param = new_param_double("t1", P_FLAG_TVAR, &custom_shape->t1, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
338 free_custom_shape(custom_shape);
342 if (insert_param(param, custom_shape->param_tree) < 0) {
343 free_custom_shape(custom_shape);
347 if ((param = new_param_double("t2", P_FLAG_TVAR, &custom_shape->t2, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
348 free_custom_shape(custom_shape);
352 if (insert_param(param, custom_shape->param_tree) < 0) {
353 free_custom_shape(custom_shape);
357 if ((param = new_param_double("t3", P_FLAG_TVAR, &custom_shape->t3, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
358 free_custom_shape(custom_shape);
362 if (insert_param(param, custom_shape->param_tree) < 0) {
363 free_custom_shape(custom_shape);
366 if ((param = new_param_double("t4", P_FLAG_TVAR, &custom_shape->t4, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
367 free_custom_shape(custom_shape);
371 if (insert_param(param, custom_shape->param_tree) < 0) {
372 free_custom_shape(custom_shape);
375 if ((param = new_param_double("t5", P_FLAG_TVAR, &custom_shape->t5, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
376 free_custom_shape(custom_shape);
380 if (insert_param(param, custom_shape->param_tree) < 0) {
381 free_custom_shape(custom_shape);
384 if ((param = new_param_double("t6", P_FLAG_TVAR, &custom_shape->t6, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
385 free_custom_shape(custom_shape);
389 if (insert_param(param, custom_shape->param_tree) < 0) {
390 free_custom_shape(custom_shape);
393 if ((param = new_param_double("t7", P_FLAG_TVAR, &custom_shape->t7, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
394 free_custom_shape(custom_shape);
398 if (insert_param(param, custom_shape->param_tree) < 0) {
399 free_custom_shape(custom_shape);
403 if ((param = new_param_double("t8", P_FLAG_TVAR, &custom_shape->t8, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL) {
404 free_custom_shape(custom_shape);
408 if (insert_param(param, custom_shape->param_tree) < 0) {
409 free_custom_shape(custom_shape);
413 /* End of parameter loading. Note that the read only parameters associated
414 with custom shapes (ie, sample) are global variables, and not specific to
415 the custom shape datastructure. */
423 void destroy_per_frame_init_eqn_tree_shape(splaytree_t * tree) {
428 splay_traverse(free_init_cond, tree);
429 destroy_splaytree(tree);
435 void destroy_init_cond_tree_shape(splaytree_t * tree) {
440 splay_traverse(free_init_cond, tree);
441 destroy_splaytree(tree);
445 void destroy_per_frame_eqn_tree_shape(splaytree_t * tree) {
451 splay_traverse(free_per_frame_eqn, tree);
452 destroy_splaytree(tree);
457 void destroy_param_db_tree_shape(splaytree_t * tree) {
462 splay_traverse(free_param, tree);
463 destroy_splaytree(tree);
467 /* Frees a custom shape form object */
468 void free_custom_shape(custom_shape_t * custom_shape) {
470 if (custom_shape == NULL)
473 if (custom_shape->param_tree == NULL)
476 destroy_per_frame_eqn_tree_shape(custom_shape->per_frame_eqn_tree);
477 destroy_init_cond_tree_shape(custom_shape->init_cond_tree);
478 destroy_param_db_tree_shape(custom_shape->param_tree);
479 destroy_per_frame_init_eqn_tree_shape(custom_shape->per_frame_init_eqn_tree);
488 custom_shape_t * find_custom_shape(int id, preset_t * preset, int create_flag) {
490 custom_shape_t * custom_shape = NULL;
495 if ((custom_shape = splay_find(&id, preset->custom_shape_tree)) == NULL) {
497 if (CUSTOM_SHAPE_DEBUG) { printf("find_custom_shape: creating custom shape (id = %d)...", id);fflush(stdout);}
499 if (create_flag == FALSE) {
500 if (CUSTOM_SHAPE_DEBUG) printf("you specified not to (create flag = false), returning null\n");
504 if ((custom_shape = new_custom_shape(id)) == NULL) {
505 if (CUSTOM_SHAPE_DEBUG) printf("failed...out of memory?\n");
509 if (CUSTOM_SHAPE_DEBUG) { printf("success.Inserting..."); fflush(stdout);}
511 if (splay_insert(custom_shape, &custom_shape->id, preset->custom_shape_tree) < 0) {
512 if (CUSTOM_SHAPE_DEBUG) printf("failed, probably a duplicated!!\n");
513 free_custom_shape(custom_shape);
517 if (CUSTOM_SHAPE_DEBUG) printf("done.\n");
523 inline void evalCustomShapeInitConditions() {
524 splay_traverse(eval_custom_shape_init_conds, active_preset->custom_shape_tree);
528 inline void eval_custom_shape_init_conds(custom_shape_t * custom_shape) {
529 splay_traverse(eval_init_cond, custom_shape->init_cond_tree);
530 splay_traverse(eval_init_cond, custom_shape->per_frame_init_eqn_tree);
534 void load_unspecified_init_conds_shape(custom_shape_t * custom_shape) {
536 interface_shape = custom_shape;
537 splay_traverse(load_unspec_init_cond_shape, interface_shape->param_tree);
538 interface_shape = NULL;
542 void load_unspec_init_cond_shape(param_t * param) {
544 init_cond_t * init_cond;
547 /* Don't count read only parameters as initial conditions */
548 if (param->flags & P_FLAG_READONLY)
550 if (param->flags & P_FLAG_QVAR)
552 if (param->flags & P_FLAG_TVAR)
554 if (param->flags & P_FLAG_USERDEF)
557 /* If initial condition was not defined by the preset file, force a default one
558 with the following code */
559 if ((init_cond = splay_find(param->name, interface_shape->init_cond_tree)) == NULL) {
561 /* Make sure initial condition does not exist in the set of per frame initial equations */
562 if ((init_cond = splay_find(param->name, interface_shape->per_frame_init_eqn_tree)) != NULL)
565 if (param->type == P_TYPE_BOOL)
566 init_val.bool_val = 0;
568 else if (param->type == P_TYPE_INT)
569 init_val.int_val = *(int*)param->engine_val;
571 else if (param->type == P_TYPE_DOUBLE)
572 init_val.double_val = *(double*)param->engine_val;
574 //printf("%s\n", param->name);
575 /* Create new initial condition */
576 if ((init_cond = new_init_cond(param, init_val)) == NULL)
579 /* Insert the initial condition into this presets tree */
580 if (splay_insert(init_cond, init_cond->param->name, interface_shape->init_cond_tree) < 0) {
581 free_init_cond(init_cond);
590 /* Interface function. Makes another custom shape the current
591 concern for per frame / point equations */
592 inline custom_shape_t * nextCustomShape() {
594 if ((interface_shape = splay_find(&cwave_interface_id, active_preset->custom_shape_tree)) == NULL) {
595 cwave_interface_id = 0;
599 cwave_interface_id++;
601 /* Evaluate all per frame equations associated with this shape */
602 splay_traverse(eval_per_frame_eqn, interface_shape->per_frame_eqn_tree);
603 return interface_shape;