Mercurial > audlegacy-plugins
comparison src/paranormal/xform.c @ 336:8554beb862c0 trunk
[svn] - implement AVS-like Trans / Dynamic Movement
author | nenolod |
---|---|
date | Tue, 05 Dec 2006 14:10:31 -0800 |
parents | a9f1bd76a3e6 |
children | 5d12ef0b97a5 |
comparison
equal
deleted
inserted
replaced
335:015513ad27d2 | 336:8554beb862c0 |
---|---|
562 "xform_movement", "Movement Transform", | 562 "xform_movement", "Movement Transform", |
563 "A customizable blitter.", | 563 "A customizable blitter.", |
564 0, xform_movement_opts, | 564 0, xform_movement_opts, |
565 xform_movement_init, xform_movement_cleanup, xform_movement_exec | 565 xform_movement_init, xform_movement_cleanup, xform_movement_exec |
566 }; | 566 }; |
567 | |
568 /* **************** xform_dynmovement **************** */ | |
569 struct pn_actuator_option_desc xform_dynmovement_opts[] = | |
570 { | |
571 { "init_script", "The formula to evaluate on init.", | |
572 OPT_TYPE_STRING, { sval: "" } }, | |
573 { "frame_script", "The formula to evaluate on each frame.", | |
574 OPT_TYPE_STRING, { sval: "" } }, | |
575 { "point_script", "The formula to evaluate.", | |
576 OPT_TYPE_STRING, { sval: "d = 0.15;" } }, | |
577 { NULL } | |
578 }; | |
579 | |
580 typedef struct { | |
581 int width, height; /* Previous width and height. */ | |
582 expression_t *expr_init; | |
583 expression_t *expr_frame; | |
584 expression_t *expr_point; | |
585 symbol_dict_t *dict; | |
586 struct xform_vector *vfield; | |
587 } PnDynMovementData; | |
588 | |
589 static void | |
590 xform_dynmovement_init (gpointer *data) | |
591 { | |
592 *data = g_new0(PnDynMovementData, 1); | |
593 } | |
594 | |
595 static void | |
596 xform_dynmovement_cleanup (gpointer data) | |
597 { | |
598 PnDynMovementData *d = (PnDynMovementData *) data; | |
599 | |
600 if (d) | |
601 { | |
602 if (d->expr_init) | |
603 expression_free (d->expr_init); | |
604 if (d->expr_frame) | |
605 expression_free (d->expr_frame); | |
606 if (d->expr_point) | |
607 expression_free (d->expr_point); | |
608 if (d->dict) | |
609 dict_free (d->dict); | |
610 if (d->vfield) | |
611 g_free (d->vfield); | |
612 g_free (d); | |
613 } | |
614 } | |
615 | |
616 static void | |
617 xform_dynmovement_exec (const struct pn_actuator_option *opts, | |
618 gpointer odata) | |
619 { | |
620 PnDynMovementData *d = (PnDynMovementData *) odata; | |
621 gint i, j; | |
622 gdouble *rf, *df; | |
623 gdouble xf, yf; | |
624 gint xn, yn; | |
625 | |
626 if (d->width != pn_image_data->width | |
627 || d->height != pn_image_data->height) | |
628 { | |
629 d->width = pn_image_data->width; | |
630 d->height = pn_image_data->height; | |
631 | |
632 if (d->vfield) | |
633 { | |
634 g_free (d->vfield); | |
635 d->vfield = NULL; | |
636 } | |
637 | |
638 if (opts[2].val.sval == NULL) | |
639 return; | |
640 | |
641 if (!d->dict) | |
642 d->dict = dict_new(); | |
643 else | |
644 { | |
645 dict_free(d->dict); | |
646 d->dict = dict_new(); | |
647 } | |
648 | |
649 rf = dict_variable(d->dict, "r"); | |
650 df = dict_variable(d->dict, "d"); | |
651 | |
652 if (d->expr_init) | |
653 { | |
654 expression_free(d->expr_init); | |
655 d->expr_init = NULL; | |
656 } | |
657 | |
658 /* initialize */ | |
659 d->expr_init = expr_compile_string(opts[0].val.sval, d->dict); | |
660 | |
661 if (d->expr_init != NULL) | |
662 { | |
663 expr_execute(d->expr_init, d->dict); | |
664 } | |
665 | |
666 d->expr_frame = expr_compile_string(opts[1].val.sval, d->dict); | |
667 d->expr_point = expr_compile_string(opts[2].val.sval, d->dict); | |
668 | |
669 d->vfield = g_malloc (sizeof(struct xform_vector) | |
670 * d->width * d->height); | |
671 } | |
672 | |
673 /* run the on-frame script. */ | |
674 if (d->expr_frame != NULL) | |
675 expr_execute(d->expr_frame, d->dict); | |
676 | |
677 for (j = 0; j < pn_image_data->height; j++) | |
678 for (i = 0; i < pn_image_data->width; i++) | |
679 { | |
680 /* Points (xf, yf) must be in a (-1..1) square. */ | |
681 xf = 2.0 * i / (pn_image_data->width - 1) - 1.0; | |
682 yf = 2.0 * j / (pn_image_data->height - 1) - 1.0; | |
683 | |
684 /* Now, convert to polar coordinates r and d. */ | |
685 *rf = hypot(xf, yf); | |
686 *df = atan2(yf, xf); | |
687 | |
688 /* Run the script. */ | |
689 if (d->expr_point != NULL) | |
690 expr_execute(d->expr_point, d->dict); | |
691 | |
692 /* Back to (-1..1) square. */ | |
693 xf = (*rf) * cos ((*df)); | |
694 yf = (*rf) * sin ((*df)); | |
695 | |
696 /* Convert back to physical coordinates. */ | |
697 xn = (int)(((xf + 1.0) * (pn_image_data->width - 1) / 2) + 0.5); | |
698 yn = (int)(((yf + 1.0) * (pn_image_data->height - 1) / 2) + 0.5); | |
699 | |
700 if (xn < 0 || xn >= pn_image_data->width || yn < 0 || yn >= pn_image_data->height) | |
701 { | |
702 xn = i; yn = j; | |
703 } | |
704 | |
705 xfvec (xn, yn, &d->vfield[PN_IMG_INDEX (i, j)]); | |
706 } | |
707 | |
708 apply_xform (d->vfield); | |
709 pn_swap_surfaces (); | |
710 } | |
711 | |
712 struct pn_actuator_desc builtin_xform_dynmovement = | |
713 { | |
714 "xform_dynmovement", "Dynamic Movement Transform", | |
715 "A customizable blitter.", | |
716 0, xform_dynmovement_opts, | |
717 xform_dynmovement_init, xform_dynmovement_cleanup, xform_dynmovement_exec | |
718 }; |