For scons: Add "-DWITH_DDS" to compile flags when dds is enabled.
[blender-staging.git] / source / blender / src / editipo_mods.c
1 /**
2  * $Id: 
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * Contributor(s): Blender Foundation, 2005. Full recode
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28
29 /* ********** Selection and set Handle code for editing Ipos in Blender ************* */
30 /*
31   mouse_select_ipo() is in editipo.c
32 */
33
34 #include <stdlib.h>
35 #include <string.h>
36 #include <math.h>
37
38 #ifndef WIN32
39 #include <unistd.h>
40 #else
41 #include <io.h>
42 #endif   
43
44 #include "BLI_blenlib.h"
45 #include "BLI_arithb.h"
46
47 #include "DNA_curve_types.h"
48 #include "DNA_ipo_types.h"
49 #include "DNA_key_types.h"
50 #include "DNA_object_types.h"
51 #include "DNA_space_types.h"
52 #include "DNA_scene_types.h"
53 #include "DNA_view3d_types.h"
54
55 #include "BKE_global.h"
56 #include "BKE_action.h"
57 #include "BKE_ipo.h"
58 #include "BKE_key.h"
59 #include "BKE_utildefines.h"
60
61 #include "BIF_interface.h"
62 #include "BIF_screen.h"
63 #include "BIF_space.h"
64 #include "BIF_toolbox.h"
65
66 #include "BSE_edit.h"
67 #include "BSE_editipo_types.h"
68 #include "BSE_editipo.h"
69 #include "BSE_drawipo.h"
70 #include "BSE_trans_types.h"
71 #include "BSE_time.h"
72
73 #include "BDR_drawobject.h"
74
75 #include "blendef.h"
76 #include "mydevice.h"
77
78 extern int totipo_edit, totipo_sel, totipo_vertsel, totipo_vis;
79
80 void ipo_toggle_showkey(void) 
81 {
82         if(G.sipo->showkey) G.sipo->showkey= 0;
83         else G.sipo->showkey= 1;
84
85         free_ipokey(&G.sipo->ipokey);
86         if(G.sipo->ipo) G.sipo->ipo->showkey= G.sipo->showkey;
87         
88         BIF_undo_push("Toggle Show Key Ipo");
89 }
90
91 void swap_selectall_editipo(void)
92 {
93         Object *ob;
94         EditIpo *ei;
95         IpoKey *ik;
96         BezTriple *bezt;
97         int a, b; /*  , sel=0; */
98         
99         get_status_editipo();
100         
101         if(G.sipo->showkey) {
102                 ik= G.sipo->ipokey.first;
103                 while(ik) {
104                         if(totipo_vertsel) ik->flag &= ~1;
105                         else ik->flag |= 1;
106                         ik= ik->next;
107                 }
108                 update_editipo_flags();
109                 
110                 if(G.sipo->showkey && G.sipo->blocktype==ID_OB ) {
111                         ob= OBACT;
112                         if(ob && (ob->ipoflag & OB_DRAWKEY)) draw_object_ext(BASACT);
113                 }
114         }
115         else if(totipo_edit==0) {
116                 ei= G.sipo->editipo;
117                 if (ei){
118                         for(a=0; a<G.sipo->totipo; a++) {
119                                 if( ei->flag & IPO_VISIBLE ) {
120                                         if(totipo_sel) ei->flag &= ~IPO_SELECT;
121                                         else ei->flag |= IPO_SELECT;
122                                 }
123                                 ei++;
124                         }
125                         update_editipo_flags();
126                 }
127                 get_status_editipo();
128         }
129         else {
130                 ei= G.sipo->editipo;
131                 for(a=0; a<G.sipo->totipo; a++) {
132                         if (ISPOIN3(ei, flag & IPO_VISIBLE, flag & IPO_EDIT, icu )) {
133                                 bezt= ei->icu->bezt;
134                                 if(bezt) {
135                                         b= ei->icu->totvert;
136                                         while(b--) {
137                                                 if(totipo_vertsel) {
138                                                         bezt->f1= bezt->f2= bezt->f3= 0;
139                                                 }
140                                                 else {
141                                                         bezt->f1= bezt->f2= bezt->f3= 1;
142                                                 }
143                                                 bezt++;
144                                         }
145                                 }
146                         }
147                         ei++;
148                 }
149                 
150         }
151         
152         BIF_undo_push("Swap Select All Ipo");
153         scrarea_queue_winredraw(curarea);
154         
155 }
156
157 void swap_visible_editipo(void)
158 {
159         EditIpo *ei;
160         Object *ob;
161         int a; /*  , sel=0; */
162         
163         get_status_editipo();
164         
165         
166         ei= G.sipo->editipo;
167         for(a=0; a<G.sipo->totipo; a++) {
168                 if(totipo_vis==0) {
169                         if(ei->icu) {
170                                 ei->flag |= IPO_VISIBLE;
171                                 ei->flag |= IPO_SELECT;
172                         }
173                 }
174                 else 
175                         ei->flag &= ~IPO_VISIBLE;
176                 ei++;
177         }
178         
179         update_editipo_flags();
180         
181         if(G.sipo->showkey) {
182                 
183                 make_ipokey();
184                 
185                 ob= OBACT;
186                 if(ob && (ob->ipoflag & OB_DRAWKEY)) allqueue(REDRAWVIEW3D, 0);
187         }
188         
189         scrarea_queue_winredraw(curarea);
190         BIF_undo_push("Swap Visible Ipo");      
191 }
192
193 void deselectall_editipo(void)
194 {
195         EditIpo *ei;
196         IpoKey *ik;
197         BezTriple *bezt;
198         int a, b; /*  , sel=0; */
199         
200         get_status_editipo();
201         
202         if(G.sipo->showkey) {
203                 ik= G.sipo->ipokey.first;
204                 while(ik) {
205                         ik->flag &= ~1;
206                         ik= ik->next;
207                 }
208                 update_editipo_flags();
209                 
210         }
211         else if(totipo_edit==0) {
212                 
213                 ei= G.sipo->editipo;
214                 for(a=0; a<G.sipo->totipo; a++) {
215                         if( ei->flag & IPO_VISIBLE ) {
216                                 ei->flag &= ~IPO_SELECT;
217                         }
218                         ei++;
219                 }
220                 update_editipo_flags();
221         }
222         else {
223                 ei= G.sipo->editipo;
224                 for(a=0; a<G.sipo->totipo; a++) {
225                         if (ISPOIN3(ei, flag & IPO_VISIBLE, flag & IPO_EDIT, icu )) {
226                                 if(ei->icu->bezt) {
227                                         bezt= ei->icu->bezt;
228                                         b= ei->icu->totvert;
229                                         while(b--) {
230                                                 bezt->f1= bezt->f2= bezt->f3= 0;
231                                                 bezt++;
232                                         }
233                                 }
234                         }
235                         ei++;
236                 }
237         }
238         
239         BIF_undo_push("(De)select all Ipo");
240         scrarea_queue_winredraw(curarea);
241 }
242
243
244 static int icu_keys_bezier_loop(IpoCurve *icu,
245                          int (*bezier_function)(BezTriple *),
246                          void (ipocurve_function)(struct IpoCurve *icu)) 
247 {
248     /*  This loops through the beziers in the Ipocurve, and executes 
249      *  the generic user provided 'bezier_function' on each one. 
250      *  Optionally executes the generic function ipocurve_function on the 
251      *  IPO curve after looping (eg. calchandles_ipocurve)
252      */
253
254     int b;
255     BezTriple *bezt;
256
257     b    = icu->totvert;
258     bezt = icu->bezt;
259
260     /* if bezier_function has been specified
261      * then loop through each bezier executing
262      * it.
263      */
264
265     if (bezier_function != NULL) {
266         while(b--) {
267             /* exit with return code 1 if the bezier function 
268              * returns 1 (good for when you are only interested
269              * in finding the first bezier that
270              * satisfies a condition).
271              */
272             if (bezier_function(bezt)) return 1;
273             bezt++;
274         }
275     }
276
277     /* if ipocurve_function has been specified 
278      * then execute it
279      */
280     if (ipocurve_function != NULL)
281         ipocurve_function(icu);
282
283     return 0;
284
285 }
286
287 static int ipo_keys_bezier_loop(Ipo *ipo,
288                          int (*bezier_function)(BezTriple *),
289                          void (ipocurve_function)(struct IpoCurve *icu))
290 {
291     /*  This loops through the beziers that are attached to
292      *  the selected keys on the Ipocurves of the Ipo, and executes 
293      *  the generic user provided 'bezier_function' on each one. 
294      *  Optionally executes the generic function ipocurve_function on a 
295      *  IPO curve after looping (eg. calchandles_ipocurve)
296      */
297
298     IpoCurve *icu;
299         
300         if(ipo==NULL) return 0;
301         
302     /* Loop through each curve in the Ipo
303      */
304     for (icu=ipo->curve.first; icu; icu=icu->next){
305         if (icu_keys_bezier_loop(icu,bezier_function, ipocurve_function))
306             return 1;
307     }
308
309     return 0;
310 }
311
312 static int selected_bezier_loop(int (*looptest)(EditIpo *),
313                          int (*bezier_function)(BezTriple *),
314                          void (ipocurve_function)(struct IpoCurve *icu))
315 {
316         /*  This loops through the beziers that are attached to
317          *  selected keys in editmode in the IPO window, and executes 
318          *  the generic user-provided 'bezier_function' on each one 
319          *  that satisfies the 'looptest' function. Optionally executes
320          *  the generic function ipocurve_function on a IPO curve
321          *  after looping (eg. calchandles_ipocurve)
322          */
323
324         EditIpo *ei;
325         BezTriple *bezt;
326         int a, b;
327
328         /* Get the first Edit Ipo from the selected Ipos
329          */
330         ei= G.sipo->editipo;
331
332         /* Loop throught all of the selected Ipo's
333          */
334         for(a=0; a<G.sipo->totipo; a++, ei++) {
335                 /* Do a user provided test on the Edit Ipo
336                  * to determine whether we want to process it
337                  */
338                 if (looptest(ei)) {
339                         /* Loop through the selected
340                          * beziers on the Edit Ipo
341                          */
342                         bezt = ei->icu->bezt;
343                         b    = ei->icu->totvert;
344                         
345                         /* if bezier_function has been specified
346                          * then loop through each bezier executing
347                          * it.
348                          */
349                         if (bezier_function != NULL) {
350                                 while(b--) {
351                                         /* exit with return code 1 if the bezier function 
352                                          * returns 1 (good for when you are only interested
353                                          * in finding the first bezier that
354                                          * satisfies a condition).
355                                          */
356                                         if (bezier_function(bezt)) return 1;
357                                         bezt++;
358                                 }
359                         }
360
361                         /* if ipocurve_function has been specified 
362                          * then execute it
363                          */
364                         if (ipocurve_function != NULL)
365                                 ipocurve_function(ei->icu);
366                 }
367                 /* nufte flourdje zim ploopydu <-- random dutch looking comment ;) */
368                 /* looks more like russian to me! (ton) */
369         }
370
371         return 0;
372 }
373
374 int select_bezier_add(BezTriple *bezt) 
375 {
376         /* Select the bezier triple */
377         bezt->f1 |= 1;
378         bezt->f2 |= 1;
379         bezt->f3 |= 1;
380         return 0;
381 }
382
383 int select_bezier_subtract(BezTriple *bezt) 
384 {
385         /* Deselect the bezier triple */
386         bezt->f1 &= ~1;
387         bezt->f2 &= ~1;
388         bezt->f3 &= ~1;
389         return 0;
390 }
391
392 int select_bezier_invert(BezTriple *bezt) 
393 {
394         /* Invert the selection for the bezier triple */
395         bezt->f2 ^= 1;
396         if ( bezt->f2 & 1 ) {
397                 bezt->f1 |= 1;
398                 bezt->f3 |= 1;
399         }
400         else {
401                 bezt->f1 &= ~1;
402                 bezt->f3 &= ~1;
403         }
404         return 0;
405 }
406
407 static int set_bezier_auto(BezTriple *bezt) 
408 {
409         /* Sets the selected bezier handles to type 'auto' 
410          */
411
412         /* is a handle selected? If so
413          * set it to type auto
414          */
415         if(bezt->f1 || bezt->f3) {
416                 if(bezt->f1) bezt->h1= 1; /* the secret code for auto */
417                 if(bezt->f3) bezt->h2= 1;
418
419                 /* if the handles are not of the same type, set them
420                  * to type free
421                  */
422                 if(bezt->h1!=bezt->h2) {
423                         if ELEM(bezt->h1, HD_ALIGN, HD_AUTO) bezt->h1= HD_FREE;
424                         if ELEM(bezt->h2, HD_ALIGN, HD_AUTO) bezt->h2= HD_FREE;
425                 }
426         }
427         return 0;
428 }
429
430 static int set_bezier_vector(BezTriple *bezt) 
431 {
432         /* Sets the selected bezier handles to type 'vector' 
433          */
434
435         /* is a handle selected? If so
436          * set it to type vector
437          */
438         if(bezt->f1 || bezt->f3) {
439                 if(bezt->f1) bezt->h1= 2; /* the code for vector */
440                 if(bezt->f3) bezt->h2= 2;
441     
442                 /* if the handles are not of the same type, set them
443                  * to type free
444                  */
445                 if(bezt->h1!=bezt->h2) {
446                         if ELEM(bezt->h1, HD_ALIGN, HD_AUTO) bezt->h1= HD_FREE;
447                         if ELEM(bezt->h2, HD_ALIGN, HD_AUTO) bezt->h2= HD_FREE;
448                 }
449         }
450         return 0;
451 }
452
453 static int bezier_isfree(BezTriple *bezt) 
454 {
455         /* queries whether the handle should be set
456          * to type 'free' (I think)
457          */
458         if(bezt->f1 && bezt->h1) return 1;
459         if(bezt->f3 && bezt->h2) return 1;
460         return 0;
461 }
462
463 static int set_bezier_free(BezTriple *bezt) 
464 {
465         /* Sets selected bezier handles to type 'free' 
466          */
467         if(bezt->f1) bezt->h1= HD_FREE;
468         if(bezt->f3) bezt->h2= HD_FREE;
469         return 0;
470 }
471
472 static int set_bezier_align(BezTriple *bezt) 
473 {
474         /* Sets selected bezier handles to type 'align' 
475          */
476         if(bezt->f1) bezt->h1= HD_ALIGN;
477         if(bezt->f3) bezt->h2= HD_ALIGN;
478         return 0;
479 }
480
481 static int vis_edit_icu_bez(EditIpo *ei) 
482 {
483         /* A 4 part test for an EditIpo :
484          *   is it a) visible
485          *         b) in edit mode
486          *         c) does it contain an Ipo Curve
487          *         d) does that ipo curve have a bezier
488          *
489          * (The reason why I don't just use the macro
490          * is I need a pointer to a function.)
491          */
492         return (ISPOIN4(ei, flag & IPO_VISIBLE, flag & IPO_EDIT, icu, icu->bezt));
493 }
494
495 void select_ipo_bezier_keys(Ipo *ipo, int selectmode)
496 {
497         /* Select all of the beziers in all
498         * of the Ipo curves belonging to the
499         * Ipo, using the selection mode.
500         */
501         switch (selectmode) {
502                 case SELECT_ADD:
503                         ipo_keys_bezier_loop(ipo, select_bezier_add, NULL);
504                         break;
505                 case SELECT_SUBTRACT:
506                         ipo_keys_bezier_loop(ipo, select_bezier_subtract, NULL);
507                         break;
508                 case SELECT_INVERT:
509                         ipo_keys_bezier_loop(ipo, select_bezier_invert, NULL);
510                         break;
511         }
512 }
513
514 void select_icu_bezier_keys(IpoCurve *icu, int selectmode)
515 {
516         /* Select all of the beziers in all
517         * of the Ipo curves belonging to the
518         * Ipo, using the selection mode.
519         */
520         switch (selectmode) {
521                 case SELECT_ADD:
522                         icu_keys_bezier_loop(icu, select_bezier_add, NULL);
523                         break;
524                 case SELECT_SUBTRACT:
525                         icu_keys_bezier_loop(icu, select_bezier_subtract, NULL);
526                         break;
527                 case SELECT_INVERT:
528                         icu_keys_bezier_loop(icu, select_bezier_invert, NULL);
529                         break;
530         }
531 }
532
533 void sethandles_ipo_keys(Ipo *ipo, int code)
534 {
535         /* this function lets you set bezier handles all to
536          * one type for some Ipo's (e.g. with hotkeys through
537          * the action window).
538          */ 
539
540         /* code==1: set autohandle */
541         /* code==2: set vectorhandle */
542         /* als code==3 (HD_ALIGN) toggelt het, vectorhandles worden HD_FREE */
543         
544         switch(code) {
545         case 1:
546                 /*** Set to auto ***/
547                 ipo_keys_bezier_loop(ipo, set_bezier_auto,
548                                                          calchandles_ipocurve);
549                 break;
550         case 2:
551                 /*** Set to vector ***/
552                 ipo_keys_bezier_loop(ipo, set_bezier_vector,
553                          calchandles_ipocurve);
554                 break;
555         default:
556                 if ( ipo_keys_bezier_loop(ipo, bezier_isfree, NULL) ) {
557                         /*** Set to free ***/
558                         ipo_keys_bezier_loop(ipo, set_bezier_free,
559                            calchandles_ipocurve);
560                 }
561                 else {
562                         /*** Set to align ***/
563                         ipo_keys_bezier_loop(ipo, set_bezier_align,
564                            calchandles_ipocurve);
565                 }
566                 break;
567         }
568 }
569
570 static int snap_bezier_nearest(BezTriple *bezt)
571 {
572         if(bezt->f2 & SELECT)
573                 bezt->vec[1][0]= (float)(floor(bezt->vec[1][0]+0.5));
574         return 0;
575 }
576
577 static int snap_bezier_cframe(BezTriple *bezt)
578 {
579         if(bezt->f2 & SELECT)
580                 bezt->vec[1][0]= (float)CFRA;
581         return 0;
582 }
583
584 static int snap_bezier_nearmarker(BezTriple *bezt)
585 {
586         if(bezt->f2 & SELECT)
587                 bezt->vec[1][0]= (float)find_nearest_marker_time(bezt->vec[1][0]);
588         
589         return 0;
590 }
591
592 void snap_ipo_keys(Ipo *ipo, short snaptype)
593 {
594         switch (snaptype) {
595                 case 1: /* snap to nearest */
596                         ipo_keys_bezier_loop(ipo, snap_bezier_nearest, calchandles_ipocurve);
597                         break;
598                 case 2: /* snap to current frame */
599                         ipo_keys_bezier_loop(ipo, snap_bezier_cframe, calchandles_ipocurve);
600                         break;
601                 case 3: /* snap to nearest marker */
602                         ipo_keys_bezier_loop(ipo, snap_bezier_nearmarker, calchandles_ipocurve);
603                         break;
604                 default: /* just in case */
605                         ipo_keys_bezier_loop(ipo, snap_bezier_nearest, calchandles_ipocurve);
606                         break;
607         }
608 }
609
610 static int mirror_bezier_cframe(BezTriple *bezt)
611 {
612         float diff;
613         
614         if(bezt->f2 & SELECT) {
615                 diff= ((float)CFRA - bezt->vec[1][0]);
616                 bezt->vec[1][0]= ((float)CFRA + diff);
617         }
618         
619         return 0;
620 }
621
622 static int mirror_bezier_yaxis(BezTriple *bezt)
623 {
624         float diff;
625         
626         if(bezt->f2 & SELECT) {
627                 diff= (0.0f - bezt->vec[1][0]);
628                 bezt->vec[1][0]= (0.0f + diff);
629         }
630         
631         return 0;
632 }
633
634 static int mirror_bezier_xaxis(BezTriple *bezt)
635 {
636         float diff;
637         
638         if(bezt->f2 & SELECT) {
639                 diff= (0.0f - bezt->vec[1][1]);
640                 bezt->vec[1][1]= (0.0f + diff);
641         }
642         
643         return 0;
644 }
645
646 static int mirror_bezier_marker(BezTriple *bezt)
647 {
648         static TimeMarker *marker;
649         static short initialised = 0;
650         float diff;
651         
652         /* In order for this mirror function to work without
653          * any extra arguments being added, we use the case
654          * of bezt==NULL to denote that we should find the 
655          * marker to mirror over. The static pointer is safe
656          * to use this way, as it will be set to null after 
657          * each cycle in which this is called.
658          */
659         
660         if (bezt) {
661                 /* mirroring time */
662                 if((bezt->f2 & SELECT) && (marker)) {
663                         diff= (marker->frame - bezt->vec[1][0]);
664                         bezt->vec[1][0]= (marker->frame + diff);
665                 }
666         }
667         else {
668                 /* initialisation time */
669                 if (initialised) {
670                         /* reset everything for safety */
671                         marker = NULL;
672                         initialised = 0;
673                 }
674                 else {
675                         /* try to find a marker */
676                         for (marker= G.scene->markers.first; marker; marker=marker->next) {
677                                 if (marker->flag & SELECT) {
678                                         initialised = 1;
679                                         break;
680                                 }
681                         }
682                         
683                         if (initialised == 0) 
684                                 marker = NULL;
685                 }
686         }
687         
688         return 0;
689 }
690
691 void mirror_ipo_keys(Ipo *ipo, short mirror_type)
692 {
693         switch (mirror_type) {
694                 case 1: /* mirror over current frame */
695                         ipo_keys_bezier_loop(ipo, mirror_bezier_cframe, calchandles_ipocurve);
696                         break;
697                 case 2: /* mirror over frame 0 */
698                         ipo_keys_bezier_loop(ipo, mirror_bezier_yaxis, calchandles_ipocurve);
699                         break;
700                 case 3: /* mirror over value 0 */
701                         ipo_keys_bezier_loop(ipo, mirror_bezier_xaxis, calchandles_ipocurve);
702                         break;
703                 case 4: /* mirror over marker */
704                         mirror_bezier_marker(NULL);
705                         ipo_keys_bezier_loop(ipo, mirror_bezier_marker, calchandles_ipocurve);
706                         mirror_bezier_marker(NULL);
707                         break;
708                 default: /* just in case */
709                         ipo_keys_bezier_loop(ipo, mirror_bezier_yaxis, calchandles_ipocurve);
710                         break;
711         }
712 }
713
714 /* currently only used by some action editor tools, but may soon get used by ipo editor */
715 /* restore = whether to map points back to ipo-time 
716  * only_keys = whether to only adjust the location of the center point of beztriples
717  */
718 void actstrip_map_ipo_keys(Object *ob, Ipo *ipo, short restore, short only_keys)
719 {
720         IpoCurve *icu;
721         BezTriple *bezt;
722         int a;
723         
724         if (ipo==NULL) return;
725         
726         /* loop through all ipo curves, adjusting the times of the selected keys */
727         for (icu= ipo->curve.first; icu; icu= icu->next) {
728                 for (a=0, bezt=icu->bezt; a<icu->totvert; a++, bezt++) {
729                         /* are the times being adjusted for editing, or has editing finished */
730                         if (restore) {
731                                 if (only_keys == 0) {
732                                         bezt->vec[0][0]= get_action_frame(ob, bezt->vec[0][0]);
733                                         bezt->vec[2][0]= get_action_frame(ob, bezt->vec[2][0]);
734                                 }                                       
735                                 bezt->vec[1][0]= get_action_frame(ob, bezt->vec[1][0]);
736                         }
737                         else {
738                                 if (only_keys == 0) {
739                                         bezt->vec[0][0]= get_action_frame_inv(ob, bezt->vec[0][0]);
740                                         bezt->vec[2][0]= get_action_frame_inv(ob, bezt->vec[2][0]);
741                                 }
742                                 bezt->vec[1][0]= get_action_frame_inv(ob, bezt->vec[1][0]);
743                         }
744                 }
745         }
746 }
747
748 static void ipo_curves_auto_horiz(void)
749 {
750     EditIpo *ei;
751         int a, set= 1;
752         
753         ei= G.sipo->editipo;
754         for(a=0; a<G.sipo->totipo; a++, ei++) {
755                 if (ISPOIN3(ei, flag & IPO_VISIBLE, flag & IPO_SELECT, icu))
756                         if(ei->flag & IPO_AUTO_HORIZ) set= 0;
757         }
758         
759         ei= G.sipo->editipo;
760         for(a=0; a<G.sipo->totipo; a++, ei++) {
761                 if (ISPOIN3(ei, flag & IPO_VISIBLE, flag & IPO_SELECT, icu)) {
762                         if(set) ei->flag |= IPO_AUTO_HORIZ;
763                         else ei->flag &= ~IPO_AUTO_HORIZ;
764                 }
765         }
766         update_editipo_flags();
767 }
768
769 void sethandles_ipo(int code)
770 {
771         /* this function lets you set bezier handles all to
772          * one type for some selected keys in edit mode in the
773          * IPO window (e.g. with hotkeys)
774          */ 
775
776         /* code==1: set autohandle */
777         /* code==2: set vectorhandle */
778         /* als code==3 (HD_ALIGN) toggelt het, vectorhandles worden HD_FREE */
779
780         if(G.sipo->ipo && G.sipo->ipo->id.lib) return;
781
782         switch(code) {
783         case HD_AUTO:
784                 /*** Set to auto ***/
785                 selected_bezier_loop(vis_edit_icu_bez, set_bezier_auto,
786                          calchandles_ipocurve);
787                 break;
788         case HD_VECT:
789                 /*** Set to vector ***/
790                 selected_bezier_loop(vis_edit_icu_bez, set_bezier_vector,
791                          calchandles_ipocurve);
792                 break;
793         case HD_AUTO_ANIM:
794                 /* set to enforce autohandles to be horizontal on extremes */
795                 ipo_curves_auto_horiz();
796                 
797                 break;
798         default:
799                 if (selected_bezier_loop(vis_edit_icu_bez, bezier_isfree, NULL) ) {
800                         /*** Set to free ***/
801                         selected_bezier_loop(vis_edit_icu_bez, set_bezier_free,
802                                                                  calchandles_ipocurve);
803                 }
804                 else {
805                         /*** Set to align ***/
806                         selected_bezier_loop(vis_edit_icu_bez, set_bezier_align,
807                                                                  calchandles_ipocurve);
808                 }
809                 break;
810         }
811
812         editipo_changed(G.sipo, 1);
813         BIF_undo_push("Set handles Ipo");
814 }
815
816
817 static void set_ipocurve_constant(struct IpoCurve *icu) {
818         /* Sets the type of the IPO curve to constant
819          */
820         icu->ipo= IPO_CONST;
821 }
822
823 static void set_ipocurve_linear(struct IpoCurve *icu) {
824         /* Sets the type of the IPO curve to linear
825          */
826         icu->ipo= IPO_LIN;
827 }
828
829 static void set_ipocurve_bezier(struct IpoCurve *icu) {
830         /* Sets the type of the IPO curve to bezier
831          */
832         
833         /* dont regenerate hendels for bezier ipo curves */
834         if (icu->ipo==IPO_BEZ) return;
835         
836         /* curve handels aren't generated for non bezier curve types */
837         icu->ipo= IPO_BEZ;
838         calchandles_ipocurve(icu);
839 }
840
841
842 void setipotype_ipo(Ipo *ipo, int code)
843 {
844         /* Sets the type of the each ipo curve in the
845          * Ipo to a value based on the code
846          */
847         switch (code) {
848         case 1:
849                 ipo_keys_bezier_loop(ipo, NULL, set_ipocurve_constant);
850                 break;
851         case 2:
852                 ipo_keys_bezier_loop(ipo, NULL, set_ipocurve_linear);
853                 break;
854         case 3:
855                 ipo_keys_bezier_loop(ipo, NULL, set_ipocurve_bezier);
856                 break;
857         }
858 }
859
860 void setexprap_ipoloop(Ipo *ipo, int code)
861 {
862         IpoCurve *icu;
863
864         /* Loop through each curve in the Ipo
865         */
866         for (icu=ipo->curve.first; icu; icu=icu->next)
867                 icu->extrap= code;
868 }
869
870 void set_ipotype(void)
871 {
872         EditIpo *ei;
873         int a;
874         short event;
875
876         if(G.sipo->ipo && G.sipo->ipo->id.lib) return;
877         if(G.sipo->showkey) return;
878         get_status_editipo();
879         
880         if(G.sipo->blocktype==ID_KE && totipo_edit==0 && totipo_sel==0) {
881                 Key *key= ob_get_key((Object *)G.sipo->from);
882                 Object *ob= OBACT;
883                 KeyBlock *kb;
884                 
885                 if(key==NULL) return;
886                 kb= BLI_findlink(&key->block, ob->shapenr-1);
887                 if(kb==NULL) return;
888                 
889                 event= pupmenu("Key Type %t|Linear %x1|Cardinal %x2|B Spline %x3");
890                 if(event < 1) return;
891
892                 kb->type= 0;
893                 if(event==1) kb->type= KEY_LINEAR;
894                 if(event==2) kb->type= KEY_CARDINAL;
895                 if(event==3) kb->type= KEY_BSPLINE;
896         }
897         else {
898                 event= pupmenu("Ipo Type %t|Constant %x1|Linear %x2|Bezier %x3");
899                 if(event < 1) return;
900                 
901                 ei= G.sipo->editipo;
902                 for(a=0; a<G.sipo->totipo; a++, ei++) {
903                         if (ISPOIN3(ei, flag & IPO_VISIBLE, flag & IPO_SELECT, icu)) {
904                                 if(event==1) ei->icu->ipo= IPO_CONST;
905                                 else if(event==2) ei->icu->ipo= IPO_LIN;
906                                 else ei->icu->ipo= IPO_BEZ;
907                         }
908                 }
909         }
910         BIF_undo_push("Set ipo type");
911         scrarea_queue_winredraw(curarea);
912 }
913
914 void borderselect_ipo(void)
915 {
916         EditIpo *ei;
917         IpoKey *ik;
918         BezTriple *bezt;
919         rcti rect;
920         rctf rectf;
921         int a, b, val;
922         short mval[2];
923
924         get_status_editipo();
925         
926         val= get_border(&rect, 3);
927
928         if(val) {
929                 /* map ipo-points for editing if scaled ipo */
930                 if (OBACT && OBACT->action && G.sipo->pin==0 && G.sipo->actname) {
931                         actstrip_map_ipo_keys(OBACT, G.sipo->ipo, 0, 0);
932                 }
933                 
934                 mval[0]= rect.xmin;
935                 mval[1]= rect.ymin;
936                 areamouseco_to_ipoco(G.v2d, mval, &rectf.xmin, &rectf.ymin);
937                 mval[0]= rect.xmax;
938                 mval[1]= rect.ymax;
939                 areamouseco_to_ipoco(G.v2d, mval, &rectf.xmax, &rectf.ymax);
940                 
941                 if(G.sipo->showkey) {
942                         ik= G.sipo->ipokey.first;
943                         while(ik) {
944                                 if(rectf.xmin<ik->val && rectf.xmax>ik->val) {
945                                         if(val==LEFTMOUSE) ik->flag |= 1;
946                                         else ik->flag &= ~1;
947                                 }
948                                 ik= ik->next;
949                         }
950                         update_editipo_flags();
951                 }
952                 else if(totipo_edit==0) {
953                         if(rect.xmin<rect.xmax && rect.ymin<rect.ymax)
954                                 select_proj_ipo(&rectf, val);
955                 }
956                 else {
957                         
958                         ei= G.sipo->editipo;
959                         for(a=0; a<G.sipo->totipo; a++, ei++) {
960                                 if (ISPOIN3(ei, flag & IPO_VISIBLE, flag & IPO_EDIT, icu)) {
961                                         if(ei->icu->bezt) {
962                                                 b= ei->icu->totvert;
963                                                 bezt= ei->icu->bezt;
964                                                 while(b--) {
965                                                         int bit= (val==LEFTMOUSE);
966                                                         
967                                                         if(BLI_in_rctf(&rectf, bezt->vec[0][0], bezt->vec[0][1]))
968                                                                 bezt->f1 = (bezt->f1&~1) | bit;
969                                                         if(BLI_in_rctf(&rectf, bezt->vec[1][0], bezt->vec[1][1]))
970                                                                 bezt->f2 = (bezt->f2&~1) | bit;
971                                                         if(BLI_in_rctf(&rectf, bezt->vec[2][0], bezt->vec[2][1]))
972                                                                 bezt->f3 = (bezt->f3&~1) | bit;
973
974                                                         bezt++;
975                                                 }
976                                         }
977                                 }
978                         }
979                 }
980                 
981                 /* undo mapping of ipo-points for drawing if scaled ipo */
982                 if (OBACT && OBACT->action && G.sipo->pin==0 && G.sipo->actname) {
983                         actstrip_map_ipo_keys(OBACT, G.sipo->ipo, 1, 0);
984                 }
985                 
986                 BIF_undo_push("Border select Ipo");
987                 allqueue(REDRAWIPO, 0);
988                 allqueue(REDRAWACTION, 0);
989                 allqueue(REDRAWNLA, 0);
990         }
991 }
992
993
994
995 void nextkey(ListBase *elems, int dir)
996 {
997         IpoKey *ik, *previk;
998         int totsel;
999         
1000         if(dir==1) ik= elems->last;
1001         else ik= elems->first;
1002         previk= 0;
1003         totsel= 0;
1004         
1005         while(ik) {
1006                 
1007                 if(ik->flag) totsel++;
1008                 
1009                 if(previk) {
1010                         if(G.qual & LR_SHIFTKEY) {
1011                                 if(ik->flag) previk->flag= 1;
1012                         }
1013                         else previk->flag= ik->flag;
1014                 }
1015                 
1016                 previk= ik;
1017                 if(dir==1) ik= ik->prev;
1018                 else ik= ik->next;
1019                 
1020                 if(G.qual & LR_SHIFTKEY);
1021                 else if(ik==0) previk->flag= 0;
1022         }
1023         
1024         /* when no key select: */
1025         if(totsel==0) {
1026                 if(dir==1) ik= elems->first;
1027                 else ik= elems->last;
1028                 
1029                 if(ik) ik->flag= 1;
1030         }
1031 }
1032
1033
1034 void nextkey_ipo(int dir)                       /* call from ipo queue */
1035 {
1036         IpoKey *ik;
1037         int a;
1038         
1039         if(G.sipo->showkey==0) return;
1040         
1041         nextkey(&G.sipo->ipokey, dir);
1042         
1043         /* copy to beziers */
1044         ik= G.sipo->ipokey.first;
1045         while(ik) {
1046                 for(a=0; a<G.sipo->totipo; a++) {
1047                         if(ik->data[a]) ik->data[a]->f1= ik->data[a]->f2= ik->data[a]->f3= ik->flag;
1048                 }
1049                 ik= ik->next;
1050         }               
1051         
1052         allqueue(REDRAWNLA, 0);
1053         allqueue(REDRAWACTION, 0);
1054         allqueue(REDRAWIPO, 0);
1055         if(G.sipo->blocktype == ID_OB) allqueue(REDRAWVIEW3D, 0);
1056 }
1057
1058 void nextkey_obipo(int dir)             /* only call external from view3d queue */
1059 {
1060         Base *base;
1061         Object *ob;
1062         ListBase elems;
1063         IpoKey *ik;
1064         int a;
1065         
1066         if (!G.vd) {
1067                 error("Can't do this! Open a 3D window");
1068                 return;
1069         }
1070         
1071         /* problem: this doesnt work when you mix dLoc keys with Loc keys */
1072         
1073         base= FIRSTBASE;
1074         while(base) {
1075                 if TESTBASE(base) {
1076                         ob= base->object;
1077                         if( (ob->ipoflag & OB_DRAWKEY) && ob->ipo && ob->ipo->showkey) {
1078                                 elems.first= elems.last= 0;
1079                                 make_ipokey_transform(ob, &elems, 0);
1080                                 
1081                                 if(elems.first) {
1082                                         
1083                                         nextkey(&elems, dir);
1084                                         
1085                                         /* copy to beziers */
1086                                         ik= elems.first;
1087                                         while(ik) {
1088                                                 for(a=0; a<OB_TOTIPO; a++) {
1089                                                         if(ik->data[a]) ik->data[a]->f1= ik->data[a]->f2= ik->data[a]->f3= ik->flag;
1090                                                 }
1091                                                 ik= ik->next;
1092                                         }
1093                                         
1094                                         free_ipokey(&elems);
1095                                 }
1096                         }
1097                 }
1098                 
1099                 base= base->next;
1100         }
1101         allqueue(REDRAWNLA, 0);
1102         allqueue(REDRAWACTION, 0);
1103         allqueue(REDRAWVIEW3D, 0);
1104         allspace(REMAKEIPO, 0);
1105         allqueue(REDRAWIPO, 0);
1106 }
1107
1108 int is_ipo_key_selected(Ipo *ipo)
1109 {
1110         int i;
1111         IpoCurve *icu;
1112         
1113         if (!ipo)
1114                 return 0;
1115         
1116         for (icu=ipo->curve.first; icu; icu=icu->next){
1117                 for (i=0; i<icu->totvert; i++)
1118                         if (BEZSELECTED(&icu->bezt[i]))
1119                                 return 1;
1120         }
1121         
1122         return 0;
1123 }
1124
1125 void set_ipo_key_selection(Ipo *ipo, int sel)
1126 {
1127         int i;
1128         IpoCurve *icu;
1129         
1130         if (!ipo)
1131                 return;
1132         
1133         for (icu=ipo->curve.first; icu; icu=icu->next){
1134                 for (i=0; i<icu->totvert; i++){
1135                         if (sel == 2) {
1136                                 icu->bezt[i].f1^=1;
1137                                 icu->bezt[i].f2^=1;
1138                                 icu->bezt[i].f3^=1;
1139                         }
1140                         else if (sel == 1){
1141                                 icu->bezt[i].f1|=1;
1142                                 icu->bezt[i].f2|=1;
1143                                 icu->bezt[i].f3|=1;
1144                         }
1145                         else{
1146                                 icu->bezt[i].f1&=~1;
1147                                 icu->bezt[i].f2&=~1;
1148                                 icu->bezt[i].f3&=~1;
1149                         }
1150                 }
1151         }
1152 }
1153
1154 int fullselect_ipo_keys(Ipo *ipo)
1155 {
1156         int i;
1157         IpoCurve *icu;
1158         int tvtot = 0;
1159         
1160         if (!ipo)
1161                 return tvtot;
1162         
1163         for (icu=ipo->curve.first; icu; icu=icu->next) {
1164                 for (i=0; i<icu->totvert; i++){
1165                         if (icu->bezt[i].f2 & 1){
1166                                 tvtot+=3;
1167                                 icu->bezt[i].f1 |= 1;
1168                                 icu->bezt[i].f3 |= 1;
1169                         }
1170                 }
1171         }
1172         
1173         return tvtot;
1174 }
1175
1176
1177 void borderselect_icu_key(IpoCurve *icu, float xmin, float xmax, 
1178                                                   int (*select_function)(BezTriple *))
1179 {
1180         /* Selects all bezier triples in the Ipocurve 
1181         * between times xmin and xmax, using the selection
1182         * function.
1183         */
1184         
1185         int i;
1186         
1187         /* loop through all of the bezier triples in
1188         * the Ipocurve -- if the triple occurs between
1189         * times xmin and xmax then select it using the selection
1190         * function
1191         */
1192         for (i=0; i<icu->totvert; i++){
1193                 if (icu->bezt[i].vec[1][0] > xmin && icu->bezt[i].vec[1][0] < xmax ){
1194                         select_function(&(icu->bezt[i]));
1195                 }
1196         }
1197 }
1198
1199 void borderselect_ipo_key(Ipo *ipo, float xmin, float xmax, int selectmode)
1200 {
1201         /* Selects all bezier triples in each Ipocurve of the
1202          * Ipo between times xmin and xmax, using the selection mode.
1203          */
1204         
1205         IpoCurve *icu;
1206         int (*select_function)(BezTriple *);
1207         
1208         /* If the ipo is no good then return */
1209         if (!ipo)
1210                 return;
1211         
1212         /* Set the selection function based on the
1213          * selection mode.
1214          */
1215         switch(selectmode) {
1216                 case SELECT_ADD:
1217                         select_function = select_bezier_add;
1218                         break;
1219                 case SELECT_SUBTRACT:
1220                         select_function = select_bezier_subtract;
1221                         break;
1222                 case SELECT_INVERT:
1223                         select_function = select_bezier_invert;
1224                         break;
1225                 default:
1226                         return;
1227         }
1228         
1229         /* loop through all of the bezier triples in all
1230                 * of the Ipocurves -- if the triple occurs between
1231                 * times xmin and xmax then select it using the selection
1232                 * function
1233                 */
1234         for (icu=ipo->curve.first; icu; icu=icu->next){
1235                 borderselect_icu_key(icu, xmin, xmax, select_function);
1236         }
1237 }
1238
1239 void select_ipo_key(Ipo *ipo, float selx, int selectmode)
1240 {
1241         /* Selects all bezier triples in each Ipocurve of the
1242         * Ipo at time selx, using the selection mode.
1243         */
1244         int i;
1245         IpoCurve *icu;
1246         int (*select_function)(BezTriple *);
1247         
1248         /* If the ipo is no good then return */
1249         if (!ipo)
1250                 return;
1251         
1252         /* Set the selection function based on the
1253                 * selection mode.
1254                 */
1255         switch(selectmode) {
1256                 case SELECT_ADD:
1257                         select_function = select_bezier_add;
1258                         break;
1259                 case SELECT_SUBTRACT:
1260                         select_function = select_bezier_subtract;
1261                         break;
1262                 case SELECT_INVERT:
1263                         select_function = select_bezier_invert;
1264                         break;
1265                 default:
1266                         return;
1267         }
1268         
1269         /* loop through all of the bezier triples in all
1270                 * of the Ipocurves -- if the triple occurs at
1271                 * time selx then select it using the selection
1272                 * function
1273                 */
1274         for (icu=ipo->curve.first; icu; icu=icu->next){
1275                 for (i=0; i<icu->totvert; i++){
1276                         if (icu->bezt[i].vec[1][0]==selx){
1277                                 select_function(&(icu->bezt[i]));
1278                         }
1279                 }
1280         }
1281 }
1282
1283 void select_icu_key(IpoCurve *icu, float selx, int selectmode)
1284 {
1285     /* Selects all bezier triples in the Ipocurve
1286         * at time selx, using the selection mode.
1287         * This is kind of sloppy the obvious similarities
1288         * with the above function, forgive me ...
1289         */
1290     int i;
1291     int (*select_function)(BezTriple *);
1292         
1293     /* If the icu is no good then return */
1294     if (!icu)
1295         return;
1296         
1297     /* Set the selection function based on the
1298                 * selection mode.
1299                 */
1300     switch(selectmode) {
1301                 case SELECT_ADD:
1302                         select_function = select_bezier_add;
1303                         break;
1304                 case SELECT_SUBTRACT:
1305                         select_function = select_bezier_subtract;
1306                         break;
1307                 case SELECT_INVERT:
1308                         select_function = select_bezier_invert;
1309                         break;
1310                 default:
1311                         return;
1312     }
1313         
1314     /* loop through all of the bezier triples in
1315                 * the Ipocurve -- if the triple occurs at
1316                 * time selx then select it using the selection
1317                 * function
1318                 */
1319     for (i=0; i<icu->totvert; i++){
1320         if (icu->bezt[i].vec[1][0]==selx){
1321             select_function(&(icu->bezt[i]));
1322         }
1323     }
1324 }
1325
1326 void set_exprap_ipo(int mode)
1327 {
1328         EditIpo *ei;
1329         int a;
1330         
1331         if(G.sipo->ipo && G.sipo->ipo->id.lib) return;
1332         /* in case of keys: always ok */
1333         
1334         ei= G.sipo->editipo;
1335         for(a=0; a<G.sipo->totipo; a++, ei++) {
1336                 if (ISPOIN(ei, flag & IPO_VISIBLE, icu)) {
1337                         if( (ei->flag & IPO_EDIT) || (ei->flag & IPO_SELECT) || (G.sipo->showkey) ) {
1338                                 ei->icu->extrap= mode;
1339                         }
1340                 }
1341         }
1342         
1343         editipo_changed(G.sipo, 1);
1344         BIF_undo_push("Set extrapolation Ipo");
1345 }