LAST of the c code comment translations... hooray!
[blender.git] / source / blender / src / editseq.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL 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. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  */
32
33 #include <stdlib.h>
34 #include <math.h>
35 #include <string.h>
36
37 #ifdef HAVE_CONFIG_H
38 #include <config.h>
39 #endif
40
41 #ifndef WIN32
42 #include <unistd.h>
43 #else
44 #include <io.h>
45 #include "BLI_winstuff.h"
46 #endif   
47 #include <sys/types.h>
48
49 #include "MEM_guardedalloc.h"
50
51 #include "BLI_blenlib.h"
52 #include "BLI_arithb.h"
53 #include "BLI_editVert.h"
54 #include "BLI_storage_types.h"
55
56 #include "IMB_imbuf_types.h"
57 #include "IMB_imbuf.h"
58
59 #include "DNA_ipo_types.h"
60 #include "DNA_scene_types.h"
61 #include "DNA_screen_types.h"
62 #include "DNA_space_types.h"
63 #include "DNA_sequence_types.h"
64 #include "DNA_view2d_types.h"
65 #include "DNA_userdef_types.h"
66
67 #include "BKE_utildefines.h"
68 #include "BKE_plugin_types.h"
69 #include "BKE_global.h"
70 #include "BKE_image.h"
71 #include "BKE_library.h"
72 #include "BKE_main.h"
73
74 #include "BIF_space.h"
75 #include "BIF_interface.h"
76 #include "BIF_screen.h"
77 #include "BIF_drawseq.h"
78 #include "BIF_editseq.h"
79 #include "BIF_mywindow.h"
80 #include "BIF_toolbox.h"
81 #include "BIF_writemovie.h"
82 #include "BIF_editview.h"
83 #include "BIF_scrarea.h"
84
85 #include "BSE_edit.h"
86 #include "BSE_sequence.h"
87 #include "BSE_filesel.h"
88 #include "BSE_drawipo.h"
89
90 #include "BDR_editobject.h"
91
92 #include "blendef.h"
93 #include "mydevice.h"
94 #include "interface.h" /*  for button types, pupmenu */
95
96 Sequence *last_seq=0;
97 char last_imagename[80]= "/";
98
99 /*  void transform_seq(int mode); already in BIF_editseq.h */
100
101 #define SEQ_DESEL       ~(SELECT+SEQ_LEFTSEL+SEQ_RIGHTSEL)
102
103 static int test_overlap_seq(Sequence *);
104 static void shuffle_seq(Sequence *);
105
106 static void change_plugin_seq(char *str)        /* called from fileselect */
107 {
108 /*      extern Sequence *last_seq; already done few lines before !!!*/
109         
110         if(last_seq && last_seq->type!=SEQ_PLUGIN) return;
111         
112         free_plugin_seq(last_seq->plugin);
113         
114         last_seq->plugin= (PluginSeq *)add_plugin_seq(str, last_seq->name+2);
115         
116         last_seq->machine= MAX3(last_seq->seq1->machine, last_seq->seq2->machine, last_seq->seq3->machine);
117         if( test_overlap_seq(last_seq) ) shuffle_seq(last_seq);
118 }
119
120
121 void boundbox_seq(void)
122 {
123         Sequence *seq;
124         Editing *ed;
125         float min[2], max[2];
126         
127         ed= G.scene->ed;
128         if(ed==0) return;
129         
130         min[0]= 0.0;
131         max[0]= EFRA+1;
132         min[1]= 0.0;
133         max[1]= 8.0;
134         
135         seq= ed->seqbasep->first;
136         while(seq) {
137                 
138                 if( min[0] > seq->startdisp-1) min[0]= seq->startdisp-1;
139                 if( max[0] < seq->enddisp+1) max[0]= seq->enddisp+1;
140                 if( max[1] < seq->machine+2.0) max[1]= seq->machine+2.0;
141                 
142                 seq= seq->next;
143         }
144         
145         G.v2d->tot.xmin= min[0];
146         G.v2d->tot.xmax= max[0];
147         G.v2d->tot.ymin= min[1];
148         G.v2d->tot.ymax= max[1];
149         
150 }
151
152 Sequence *find_nearest_seq(int *hand)
153 {
154         Sequence *seq;
155         Editing *ed;
156         float x, y, facx, facy;
157         short mval[2];
158         
159         *hand= 0;
160         
161         ed= G.scene->ed;
162         if(ed==0) return 0;
163         
164         getmouseco_areawin(mval);
165         areamouseco_to_ipoco(G.v2d, mval, &x, &y);
166         
167         seq= ed->seqbasep->first;
168         while(seq) {
169                 if(seq->machine == (int)y) {
170                         if(seq->startdisp<=x && seq->enddisp>=x) {
171                                 
172                                 if(seq->type < SEQ_EFFECT) {
173                                         if( seq->handsize+seq->startdisp >=x ) {
174                                                 /* within triangle? */
175                                                 facx= (x-seq->startdisp)/seq->handsize;
176                                                 if( (y - (int)y) <0.5) {
177                                                         facy= (y - 0.2 - (int)y)/0.3;
178                                                         if( facx < facy ) *hand= 1;
179                                                 }
180                                                 else {
181                                                         facy= (y - 0.5 - (int)y)/0.3;
182                                                         if( facx+facy < 1.0 ) *hand= 1;
183                                                 }
184                                                 
185                                         }
186                                         else if( -seq->handsize+seq->enddisp <=x ) {
187                                                 /* within triangle? */
188                                                 facx= 1.0 - (seq->enddisp-x)/seq->handsize;
189                                                 if( (y - (int)y) <0.5) {
190                                                         facy= (y - 0.2 - (int)y)/0.3;
191                                                         if( facx+facy > 1.0 ) *hand= 2;
192                                                 }
193                                                 else {
194                                                         facy= (y - 0.5 - (int)y)/0.3;
195                                                         if( facx > facy ) *hand= 2;
196                                                 }
197                                         }
198                                 }
199                                 
200                                 return seq;
201                         }
202                 }
203                 seq= seq->next;
204         }
205         return 0;
206 }
207
208 void clear_last_seq(void)
209 {
210         /* from (example) ipo: when it is changed, also do effects with same ipo */
211         Sequence *seq;
212         Editing *ed;
213         StripElem *se;
214         int a;
215         
216         if(last_seq) {
217                 
218                 ed= G.scene->ed;
219                 if(ed==0) return;
220                 
221                 WHILE_SEQ(&ed->seqbase) {
222                         if(seq==last_seq || (last_seq->ipo && seq->ipo==last_seq->ipo)) {
223                                 a= seq->len;
224                                 se= seq->strip->stripdata;
225                                 if(se) {
226                                         while(a--) {
227                                                 if(se->ibuf) IMB_freeImBuf(se->ibuf);
228                                                 se->ibuf= 0;
229                                                 se->ok= 1;
230                                                 se++;
231                                         }
232                                 }
233                         }
234                 }
235                 END_SEQ
236         }
237 }
238
239 static int test_overlap_seq(Sequence *test)
240 {
241         Sequence *seq;
242         Editing *ed;
243
244         ed= G.scene->ed;
245         if(ed==0) return 0;
246         
247         seq= ed->seqbasep->first;
248         while(seq) {
249                 if(seq!=test) {
250                         if(test->machine==seq->machine) {
251                                 if(test->depth==seq->depth) {
252                                         if( (test->enddisp <= seq->startdisp) || (test->startdisp >= seq->enddisp) );
253                                         else return 1;
254                                 }
255                         }
256                 }
257                 seq= seq->next;
258         }
259         return 0;
260 }
261
262 static void shuffle_seq(Sequence *test)
263 {
264         Editing *ed;
265         Sequence *seq;
266         int a, start;
267
268         ed= G.scene->ed;
269         if(ed==0) return;
270
271         /* als er meerdere select zijn: alleen y shuffelen */
272         a=0;
273         seq= ed->seqbasep->first;
274         while(seq) {
275                 if(seq->flag & SELECT) a++;
276                 seq= seq->next;
277         }
278         
279         if(a<2 && test->type==SEQ_IMAGE) {
280                 start= test->start;
281                 
282                 for(a= 1; a<50; a++) {
283                         test->start= start+a;
284                         calc_sequence(test);
285                         if( test_overlap_seq(test)==0) return;
286                         test->start= start-a;
287                         calc_sequence(test);
288                         if( test_overlap_seq(test)==0) return;
289                 }
290                 test->start= start;
291         }
292         
293         test->machine++;
294         calc_sequence(test);
295         while( test_overlap_seq(test) ) {
296                 if(test->machine >= MAXSEQ) {
297                         error("No space to add sequence ");
298                         
299                         BLI_remlink(ed->seqbasep, test);
300                         free_sequence(test);
301                         return;
302                 }
303                 test->machine++;
304                 calc_sequence(test);
305         }
306 }
307
308 static void deselect_all_seq(void)
309 {
310         Sequence *seq;
311         Editing *ed;
312
313         ed= G.scene->ed;
314         if(ed==0) return;
315         
316         WHILE_SEQ(ed->seqbasep) {
317                 seq->flag &= SEQ_DESEL;
318         }
319         END_SEQ
320 }
321
322 static void recurs_sel_seq(Sequence *seqm)
323 {
324         Sequence *seq;
325         
326         seq= seqm->seqbase.first;
327         while(seq) {
328                 
329                 if(seqm->flag & (SEQ_LEFTSEL+SEQ_RIGHTSEL)) seq->flag &= SEQ_DESEL;
330                 else if(seqm->flag & SELECT) seq->flag |= SELECT;
331                 else seq->flag &= SEQ_DESEL;
332                 
333                 if(seq->seqbase.first) recurs_sel_seq(seq);
334                 
335                 seq= seq->next;
336         }
337 }
338
339 void swap_select_seq(void)
340 {
341         Sequence *seq;
342         Editing *ed;
343         int sel=0;
344         
345         ed= G.scene->ed;
346         if(ed==0) return;
347         
348         WHILE_SEQ(ed->seqbasep) {
349                 if(seq->flag & SELECT) sel= 1;
350         }
351         END_SEQ
352                 
353         WHILE_SEQ(ed->seqbasep) {
354                 /* alles voor zekerheid altijd deselecteren */
355                 seq->flag &= SEQ_DESEL;
356                 if(sel==0) seq->flag |= SELECT;
357         }
358         END_SEQ
359         
360         allqueue(REDRAWSEQ, 0);
361 }
362
363 void mouse_select_seq(void)
364 {
365         Sequence *seq;
366         int hand;
367         
368         seq= find_nearest_seq(&hand);
369         
370         if(G.qual==0) deselect_all_seq();
371         
372         if(seq) {
373                 last_seq= seq;
374                 
375                 if ELEM(seq->type, SEQ_IMAGE, SEQ_MOVIE) {
376                         if(seq->strip) strcpy(last_imagename, seq->strip->dir);
377                 }
378         
379                 if(G.qual==0) {
380                         seq->flag |= SELECT;
381                         if(hand==1) seq->flag |= SEQ_LEFTSEL;
382                         if(hand==2) seq->flag |= SEQ_RIGHTSEL;
383                 }
384                 else {
385                         if(seq->flag & SELECT) {
386                                 if(hand==0) seq->flag &= SEQ_DESEL;
387                                 else if(hand==1) {
388                                         if(seq->flag & SEQ_LEFTSEL) seq->flag &= ~SEQ_LEFTSEL;
389                                         else seq->flag |= SEQ_LEFTSEL;
390                                 }
391                                 else if(hand==2) {
392                                         if(seq->flag & SEQ_RIGHTSEL) seq->flag &= ~SEQ_RIGHTSEL;
393                                         else seq->flag |= SEQ_RIGHTSEL;
394                                 }
395                         }
396                         else {
397                                 seq->flag |= SELECT;
398                                 if(hand==1) seq->flag |= SEQ_LEFTSEL;
399                                 if(hand==2) seq->flag |= SEQ_RIGHTSEL;
400                         }
401                 }
402                 recurs_sel_seq(seq);
403         }
404         
405         force_draw();
406         
407         if(last_seq) allqueue(REDRAWIPO, 0);
408         
409         std_rmouse_transform(transform_seq);
410 }
411
412 static Sequence *alloc_sequence(int cfra, int machine)
413 {
414         Editing *ed;
415         Sequence *seq;
416         
417         ed= G.scene->ed;
418         
419         seq= MEM_callocN( sizeof(Sequence), "addseq");
420         BLI_addtail(ed->seqbasep, seq);
421         
422         last_seq= seq;
423         
424         *( (short *)seq->name )= ID_SEQ;
425         seq->name[2]= 0;
426         
427         seq->flag= SELECT;
428         seq->start= cfra;
429         seq->machine= machine;
430         
431         return seq;
432 }
433
434 static Sequence *sfile_to_sequence(SpaceFile *sfile, int cfra, int machine, int last)
435 {
436         Sequence *seq;
437         Strip *strip;
438         StripElem *se;
439         int totsel, a;
440
441         /* zijn er geselecteerde files? */
442         totsel= 0;
443         for(a=0; a<sfile->totfile; a++) {
444                 if(sfile->filelist[a].flags & ACTIVE) {
445                         if( (sfile->filelist[a].type & S_IFDIR)==0 ) {
446                                 totsel++;
447                         }
448                 }
449         }
450         
451         if(last) {
452                 /* of anders een aangegeven file? */
453                 if(totsel==0 && sfile->file[0]) totsel= 1;
454         }
455         
456         if(totsel==0) return 0;
457         
458         /* seq maken */
459         seq= alloc_sequence(cfra, machine);
460         seq->len= totsel;
461         
462         if(totsel==1) {
463                 seq->startstill= 25;
464                 seq->endstill= 24;
465         }
466
467         calc_sequence(seq);
468         
469         /* strip en stripdata */
470         seq->strip= strip= MEM_callocN(sizeof(Strip), "strip");
471         strip->len= totsel;
472         strip->us= 1;
473         strcpy(strip->dir, sfile->dir);
474         strip->stripdata= se= MEM_callocN(totsel*sizeof(StripElem), "stripelem");
475
476         for(a=0; a<sfile->totfile; a++) {
477                 if(sfile->filelist[a].flags & ACTIVE) {
478                         if( (sfile->filelist[a].type & S_IFDIR)==0 ) {
479                                 strcpy(se->name, sfile->filelist[a].relname);
480                                 se->ok= 1;
481                                 se++;
482                         }
483                 }
484         }
485         /* geen geselecteerde file: */
486         if(totsel==1 && se==strip->stripdata) {
487                 strcpy(se->name, sfile->file);
488                 se->ok= 1;
489         }
490
491         /* laatste aktieve naam */
492         strcpy(last_imagename, seq->strip->dir);
493
494         return seq;
495 }
496
497 static void sfile_to_mv_sequence(SpaceFile *sfile, int cfra, int machine)
498 {
499         Sequence *seq;
500         struct anim *anim;
501         Strip *strip;
502         StripElem *se;
503         int totframe, a;
504         char str[256];
505         
506         totframe= 0;
507
508         strcpy(str, sfile->dir);
509         strcat(str, sfile->file);
510         
511         /* is er sprake van een movie */
512         anim = openanim(str, IB_rect);
513         if(anim==0) {
514                 error("Not a movie");
515                 return;
516         }
517         
518         totframe= IMB_anim_get_duration(anim);
519         
520         /* seq maken */
521         seq= alloc_sequence(cfra, machine);
522         seq->len= totframe;
523         seq->type= SEQ_MOVIE;
524         seq->anim= anim;
525
526         calc_sequence(seq);
527         
528         /* strip en stripdata */
529         seq->strip= strip= MEM_callocN(sizeof(Strip), "strip");
530         strip->len= totframe;
531         strip->us= 1;
532         strcpy(strip->dir, sfile->dir);
533         strip->stripdata= se= MEM_callocN(totframe*sizeof(StripElem), "stripelem");
534
535         /* naam movie in eerste strip */
536         strcpy(se->name, sfile->file);
537
538         for(a=1; a<=totframe; a++, se++) {
539                 se->ok= 1;
540                 se->nr= a;
541         }
542
543         /* laatste aktieve naam */
544         strcpy(last_imagename, seq->strip->dir);
545 }
546
547 static void add_image_strips(char *name)
548 {
549         SpaceFile *sfile;
550         struct direntry *files;
551         float x, y;
552         int a, totfile, cfra, machine;
553         short mval[2];  
554
555         deselect_all_seq();
556         
557         /* restore windowmatrices */
558         areawinset(curarea->win);
559         drawseqspace(curarea, curarea->spacedata.first);
560
561         /* search sfile */
562         sfile= scrarea_find_space_of_type(curarea, SPACE_FILE);
563         if(sfile==0) return;
564
565         /* where will it be */
566         getmouseco_areawin(mval);
567         areamouseco_to_ipoco(G.v2d, mval, &x, &y);
568         cfra= (int)(x+0.5);
569         machine= (int)(y+0.5);
570
571         waitcursor(1);
572
573         /* also read contents of directories */
574         files= sfile->filelist;
575         totfile= sfile->totfile;
576         sfile->filelist= 0;
577         sfile->totfile= 0;
578
579         for(a=0; a<totfile; a++) {
580                 if(files[a].flags & ACTIVE) {
581                         if( (files[a].type & S_IFDIR) ) {
582                                 strcat(sfile->dir, files[a].relname);
583                                 strcat(sfile->dir,"/");
584                                 read_dir(sfile);
585                                 
586                                 /* select all */
587                                 swapselect_file(sfile);
588                                 
589                                 if ( sfile_to_sequence(sfile, cfra, machine, 0) ) machine++;
590                                 
591                                 parent(sfile);
592                         }
593                 }
594         }
595         
596         sfile->filelist= files;
597         sfile->totfile= totfile;
598         
599         /* read directory itself */
600         sfile_to_sequence(sfile, cfra, machine, 1);
601
602         waitcursor(0);
603         
604         transform_seq('g');
605
606
607
608 static void add_movie_strip(char *name)
609 {
610         SpaceFile *sfile;
611         float x, y;
612         int cfra, machine;
613         short mval[2];  
614
615         deselect_all_seq();
616         
617         /* restore windowmatrices */
618         areawinset(curarea->win);
619         drawseqspace(curarea, curarea->spacedata.first);
620
621         /* search sfile */
622         sfile= scrarea_find_space_of_type(curarea, SPACE_FILE);
623         if(sfile==0) return;
624
625         /* where will it be */
626         getmouseco_areawin(mval);
627         areamouseco_to_ipoco(G.v2d, mval, &x, &y);
628         cfra= (int)(x+0.5);
629         machine= (int)(y+0.5);
630
631         waitcursor(1);
632
633         /* read directory itself */
634         sfile_to_mv_sequence(sfile, cfra, machine);
635
636         waitcursor(0);
637         
638         transform_seq('g');
639
640
641
642 static void reload_image_strip(char *name)
643 {
644         Editing *ed;
645         Sequence *seq, *seqact;
646         SpaceFile *sfile;
647
648         ed= G.scene->ed;
649
650         if(last_seq==0 || last_seq->type!=SEQ_IMAGE) return;
651         seqact= last_seq;       /* last_seq changes in alloc_sequence */
652         
653         /* search sfile */
654         sfile= scrarea_find_space_of_type(curarea, SPACE_FILE);
655         if(sfile==0) return;
656
657         waitcursor(1);
658
659         seq= sfile_to_sequence(sfile, seqact->start, seqact->machine, 1);
660         if(seq && seq!=seqact) {
661                 free_strip(seqact->strip);
662
663                 seqact->strip= seq->strip;
664         
665                 seqact->len= seq->len;
666                 calc_sequence(seqact);
667                 
668                 seq->strip= 0;
669                 free_sequence(seq);
670                 BLI_remlink(ed->seqbasep, seq);
671
672                 seq= ed->seqbasep->first;
673                 while(seq) {
674                         if(seq->type & SEQ_EFFECT) {
675                                 /* new_stripdata is clear */
676                                 if(seq->seq1==seqact || seq->seq2==seqact || seq->seq3==seqact) {
677                                         calc_sequence(seq);
678                                         new_stripdata(seq);
679                                 }
680                         }
681                         seq= seq->next;
682                 }
683         }
684         waitcursor(0);
685
686         allqueue(REDRAWSEQ, 0);
687
688
689 static int event_to_efftype(int event) 
690 {
691         if(event==2) return SEQ_CROSS;
692         if(event==3) return SEQ_GAMCROSS;
693         if(event==4) return SEQ_ADD;
694         if(event==5) return SEQ_SUB;
695         if(event==6) return SEQ_MUL;
696         if(event==7) return SEQ_ALPHAOVER;
697         if(event==8) return SEQ_ALPHAUNDER;
698         if(event==9) return SEQ_OVERDROP;
699         if(event==10) return SEQ_PLUGIN;
700         return 0;
701 }
702
703 static int add_seq_effect(int type)
704 {
705         Editing *ed;
706         Sequence *seq, *seq1, *seq2, *seq3;
707         Strip *strip;
708         float x, y;
709         int cfra, machine;
710         short mval[2];  
711
712         if(G.scene->ed==0) return 0;
713         ed= G.scene->ed;
714
715         /* apart from last_seq there have to be 2 selected sequences */
716         seq1= seq3= 0;
717         seq2= last_seq;         /* last_seq changes with alloc_seq! */
718         seq= ed->seqbasep->first;
719         while(seq) {
720                 if(seq->flag & SELECT) {
721                         if(seq != seq2) {
722                                 if(seq1==0) seq1= seq;
723                                 else if(seq3==0) seq3= seq;
724                                 else {
725                                         seq1= 0;
726                                         break;
727                                 }
728                         }
729                 }
730                 seq= seq->next;
731         }
732         
733         if(type==10) {  /* plugin: minimal 1 select */
734                 if(seq2==0)  {
735                         error("Need minimum one active sequence");
736                         return 0;
737                 }
738                 if(seq1==0) seq1= seq2;
739                 if(seq3==0) seq3= seq2;
740         }
741         else {
742                 if(seq1==0 || seq2==0) {
743                         error("Need 2 selected sequences");
744                         return 0;
745                 }
746                 if(seq3==0) seq3= seq2;
747         }
748         
749         deselect_all_seq();
750
751         /* where will it be (cfra is not realy needed) */
752         getmouseco_areawin(mval);
753         areamouseco_to_ipoco(G.v2d, mval, &x, &y);
754         cfra= (int)(x+0.5);
755         machine= (int)(y+0.5);
756
757         seq= alloc_sequence(cfra, machine);
758         
759         seq->type= event_to_efftype(type);
760         
761         if(seq->type==SEQ_ALPHAUNDER || seq->type==SEQ_ALPHAOVER) {
762                 seq->seq2= seq1;
763                 seq->seq1= seq2;
764         }
765         else {
766                 seq->seq1= seq1;
767                 seq->seq2= seq2;
768         }
769         seq->seq3= seq3;
770         calc_sequence(seq);
771         
772         seq->strip= strip= MEM_callocN(sizeof(Strip), "strip");
773         strip->len= seq->len;
774         strip->us= 1;
775         if(seq->len>0) strip->stripdata= MEM_callocN(seq->len*sizeof(StripElem), "stripelem");
776                 
777         return 1;
778 }
779
780 static void load_plugin_seq(char *str)          /* called from fileselect */
781 {
782         Editing *ed;
783         
784         add_seq_effect(10);             /* this sets last_seq */
785         
786         free_plugin_seq(last_seq->plugin);
787         
788         last_seq->plugin= (PluginSeq *)add_plugin_seq(str, last_seq->name+2);
789         
790         if(last_seq->plugin==0) {
791                 ed= G.scene->ed;
792                 BLI_remlink(ed->seqbasep, last_seq);
793                 free_sequence(last_seq);
794                 last_seq= 0;
795         }
796         else {
797                 last_seq->machine= MAX3(last_seq->seq1->machine, last_seq->seq2->machine, last_seq->seq3->machine);
798                 if( test_overlap_seq(last_seq) ) shuffle_seq(last_seq);
799         
800                 transform_seq('g');
801         }
802 }
803
804 void add_sequence(int type)
805 {
806         Editing *ed;
807         Sequence *seq;
808         Strip *strip;
809         Scene *sce;
810         float x, y;
811         int cfra, machine;
812         short nr, event, mval[2];       
813         char *str;
814         
815         event= pupmenu("Add sequence%t|Images%x1|Movie%x102|Scene%x101|Plugin%x10|Cross%x2|GammaCross%x3|Add%x4|Sub%x5|Mul%x6|AlphaOver%x7|AlphaUnder%x8|AlphaOverDrop%x9");
816                 
817         if(event<1) return;
818         
819         if(G.scene->ed==0) {
820                 ed= G.scene->ed= MEM_callocN( sizeof(Editing), "addseq");
821                 ed->seqbasep= &ed->seqbase;
822         }
823         else ed= G.scene->ed;
824         
825         switch(event) {
826         case 1:
827                 
828                 activate_fileselect(FILE_SPECIAL, "SELECT IMAGES", last_imagename, add_image_strips);
829                 break;
830         case 102:
831                 
832                 activate_fileselect(FILE_SPECIAL, "SELECT MOVIE", last_imagename, add_movie_strip);
833                 break;
834         case 101:
835                 /* new menu: */
836                 IDnames_to_pupstring(&str, NULL, NULL, &G.main->scene, (ID *)G.scene, &nr);
837
838                 event= pupmenu(str);
839
840                 if(event> -1) {
841                         nr= 1;
842                         sce= G.main->scene.first;
843                         while(sce) {
844                                 if( event==nr) break;
845                                 nr++;
846                                 sce= sce->id.next;
847                         }
848                         if(sce) {
849                                 
850                                 deselect_all_seq();
851                                 
852                                 /* where ? */
853                                 getmouseco_areawin(mval);
854                                 areamouseco_to_ipoco(G.v2d, mval, &x, &y);
855                                 cfra= (int)(x+0.5);
856                                 machine= (int)(y+0.5);
857                 
858                                 seq= alloc_sequence(cfra, machine);
859                                 seq->type= SEQ_SCENE;
860                                 seq->scene= sce;
861                                 seq->sfra= sce->r.sfra;
862                                 seq->len= sce->r.efra - sce->r.sfra + 1;
863                                 
864                                 seq->strip= strip= MEM_callocN(sizeof(Strip), "strip");
865                                 strip->len= seq->len;
866                                 strip->us= 1;
867                                 if(seq->len>0) strip->stripdata= MEM_callocN(seq->len*sizeof(StripElem), "stripelem");
868                                 
869                                 transform_seq('g');
870                         }
871                 }
872                 MEM_freeN(str);
873                 
874                 break;
875         case 2:
876         case 3:
877         case 4:
878         case 5:
879         case 6:
880         case 7:
881         case 8:
882         case 9:
883         case 10:
884                 
885                 if(last_seq==0) error("Need minimum one active sequence");
886                 else if(event==10) {
887                         activate_fileselect(FILE_SPECIAL, "SELECT PLUGIN", U.plugseqdir, load_plugin_seq);
888                 }
889                 else {
890                         if( add_seq_effect(event) ) transform_seq('g');
891                 }
892                 
893                 break;
894         }
895 }
896
897 void change_sequence(void)
898 {
899         Scene *sce;
900         short event;
901         
902         if(last_seq==0) return;
903
904         if(last_seq->type & SEQ_EFFECT) {
905                 event= pupmenu("Change effect%t|Switch a-b %x1|Switch b-c %x10|Plugin%x11|Recalculate%x12|Cross%x2|GammaCross%x3|Add%x4|Sub%x5|Mul%x6|AlphaOver%x7|AlphaUnder%x8|AlphaOverdrop%x9");
906                 if(event>0) {
907                         if(event==1) {
908                                 SWAP(Sequence *, last_seq->seq1, last_seq->seq2);
909                         }
910                         else if(event==10) {
911                                 SWAP(Sequence *, last_seq->seq2, last_seq->seq3);
912                         }
913                         else if(event==11) {
914                                 activate_fileselect(FILE_SPECIAL, "SELECT PLUGIN", U.plugseqdir, change_plugin_seq);                            
915                         }
916                         else if(event==12);     /* recalculate: only new_stripdata */
917                         else {
918                                 /* to be sure, free plugin */
919                                 free_plugin_seq(last_seq->plugin);
920                                 last_seq->plugin= 0;
921                                 last_seq->type= event_to_efftype(event);
922                         }
923                         new_stripdata(last_seq);
924                         allqueue(REDRAWSEQ, 0);
925                 }
926         }
927         else if(last_seq->type == SEQ_IMAGE) {
928                 if(okee("Change images")) {
929                         activate_fileselect(FILE_SPECIAL, "SELECT IMAGES", last_imagename, reload_image_strip);
930                 }
931         }
932         else if(last_seq->type == SEQ_MOVIE) {
933                 ;
934         }
935         else if(last_seq->type == SEQ_SCENE) {
936                 event= pupmenu("Change Scene%t|Update Start and End");
937                         
938                 if(event==1) {
939                         sce= last_seq->scene;
940                         
941                         last_seq->len= sce->r.efra - sce->r.sfra + 1;
942                         last_seq->sfra= sce->r.sfra;
943                         new_stripdata(last_seq);
944                         calc_sequence(last_seq);
945                         
946                         allqueue(REDRAWSEQ, 0);
947                 }
948         }
949
950 }
951
952 static int is_a_sequence(Sequence *test)
953 {
954         Sequence *seq;
955         Editing *ed;
956         
957         ed= G.scene->ed;
958         if(ed==0 || test==0) return 0;
959         
960         seq= ed->seqbasep->first;
961         while(seq) {
962                 if(seq==test) return 1;
963                 seq= seq->next;
964         }
965         
966         return 0;
967 }
968
969 static void recurs_del_seq(ListBase *lb)
970 {
971         Sequence *seq, *seqn;
972
973         seq= lb->first;
974         while(seq) {
975                 seqn= seq->next;
976                 if(seq->flag & SELECT) {
977                         BLI_remlink(lb, seq);
978                         if(seq==last_seq) last_seq= 0;
979                         if(seq->type==SEQ_META) recurs_del_seq(&seq->seqbase);
980                         if(seq->ipo) seq->ipo->id.us--;
981                         free_sequence(seq);
982                 }
983                 seq= seqn;
984         }
985 }
986
987 void del_seq(void)
988 {
989         Sequence *seq, *seqn;
990         MetaStack *ms;
991         Editing *ed;
992         int doit;
993         
994         if(okee("Erase selected")==0) return;
995
996         ed= G.scene->ed;
997         if(ed==0) return;
998         
999         recurs_del_seq(ed->seqbasep);
1000         
1001         /* test effects */
1002         doit= 1;
1003         while(doit) {
1004                 doit= 0;
1005                 seq= ed->seqbasep->first;
1006                 while(seq) {
1007                         seqn= seq->next;
1008                         if(seq->type & SEQ_EFFECT) {
1009                                 if( is_a_sequence(seq->seq1)==0 || is_a_sequence(seq->seq2)==0 || is_a_sequence(seq->seq3)==0 ) {
1010                                         BLI_remlink(ed->seqbasep, seq);
1011                                         if(seq==last_seq) last_seq= 0;
1012                                         free_sequence(seq);
1013                                         doit= 1;
1014                                 }
1015                         }
1016                         seq= seqn;
1017                 }
1018         }
1019         
1020         /* updates lengths etc */
1021         seq= ed->seqbasep->first;
1022         while(seq) {
1023                 calc_sequence(seq);
1024                 seq= seq->next;
1025         }
1026         
1027         /* free parent metas */
1028         ms= ed->metastack.last;
1029         while(ms) {
1030                 ms->parseq->strip->len= 0;              /* force new alloc */
1031                 calc_sequence(ms->parseq);
1032                 ms= ms->prev;
1033         }
1034         
1035         allqueue(REDRAWSEQ, 0);
1036 }
1037
1038
1039
1040 static void recurs_dupli_seq(ListBase *old, ListBase *new)
1041 {
1042         Sequence *seq, *seqn;
1043         StripElem *se;
1044         int a;
1045         
1046         seq= old->first;
1047         
1048         while(seq) {
1049                 seq->newseq= 0;
1050                 if(seq->flag & SELECT) {
1051                 
1052                         if(seq->type==SEQ_META) {
1053                                 seqn= MEM_dupallocN(seq);
1054                                 seq->newseq= seqn;
1055                                 BLI_addtail(new, seqn);
1056                                 
1057                                 seqn->strip= MEM_dupallocN(seq->strip);
1058                                 
1059                                 if(seq->len>0) seq->strip->stripdata= MEM_callocN(seq->len*sizeof(StripElem), "stripelem");
1060                                 
1061                                 seq->flag &= SEQ_DESEL;
1062                                 seqn->flag &= ~(SEQ_LEFTSEL+SEQ_RIGHTSEL);
1063
1064                                 seqn->seqbase.first= seqn->seqbase.last= 0;
1065                                 recurs_dupli_seq(&seq->seqbase, &seqn->seqbase);
1066                                 
1067                         }
1068                         else if(seq->type == SEQ_SCENE) {
1069                                 seqn= MEM_dupallocN(seq);
1070                                 seq->newseq= seqn;
1071                                 BLI_addtail(new, seqn);
1072                                 
1073                                 seqn->strip= MEM_dupallocN(seq->strip);
1074                                 
1075                                 if(seq->len>0) seqn->strip->stripdata= MEM_callocN(seq->len*sizeof(StripElem), "stripelem");
1076                                 
1077                                 seq->flag &= SEQ_DESEL;
1078                                 seqn->flag &= ~(SEQ_LEFTSEL+SEQ_RIGHTSEL);
1079                         }
1080                         else if(seq->type == SEQ_MOVIE) {
1081                                 seqn= MEM_dupallocN(seq);
1082                                 seq->newseq= seqn;
1083                                 BLI_addtail(new, seqn);
1084                                 
1085                                 seqn->strip= MEM_dupallocN(seq->strip);
1086                                 seqn->anim= 0;
1087                                 
1088                                 if(seqn->len>0) {
1089                                         seqn->strip->stripdata= MEM_callocN(seq->len*sizeof(StripElem), "stripelem");
1090                                         /* copy first elem */
1091                                         *seqn->strip->stripdata= *seq->strip->stripdata;
1092                                         se= seqn->strip->stripdata;
1093                                         a= seq->len;
1094                                         while(a--) {
1095                                                 se->ok= 1;
1096                                                 se++;
1097                                         }
1098                                 }
1099                                 
1100                                 seq->flag &= SEQ_DESEL;
1101                                 seqn->flag &= ~(SEQ_LEFTSEL+SEQ_RIGHTSEL);
1102                         }
1103                         else if(seq->type < SEQ_EFFECT) {
1104                                 seqn= MEM_dupallocN(seq);
1105                                 seq->newseq= seqn;
1106                                 BLI_addtail(new, seqn);
1107                                 
1108                                 seqn->strip->us++;
1109                                 seq->flag &= SEQ_DESEL;
1110                                 
1111                                 seqn->flag &= ~(SEQ_LEFTSEL+SEQ_RIGHTSEL);
1112                         }
1113                         else {
1114                                 if(seq->seq1->newseq) {
1115                                 
1116                                         seqn= MEM_dupallocN(seq);
1117                                         seq->newseq= seqn;
1118                                         BLI_addtail(new, seqn);
1119                                         
1120                                         seqn->seq1= seq->seq1->newseq;
1121                                         if(seq->seq2 && seq->seq2->newseq) seqn->seq2= seq->seq2->newseq;
1122                                         if(seq->seq3 && seq->seq3->newseq) seqn->seq3= seq->seq3->newseq;
1123                                         
1124                                         if(seqn->ipo) seqn->ipo->id.us++;
1125                                         
1126                                         if(seq->plugin) {
1127                                                 seqn->plugin= MEM_dupallocN(seq->plugin);
1128                                                 open_plugin_seq(seqn->plugin, seqn->name+2);
1129                                         }
1130                                         seqn->strip= MEM_dupallocN(seq->strip);
1131                                         
1132                                         if(seq->len>0) seq->strip->stripdata= MEM_callocN(seq->len*sizeof(StripElem), "stripelem");
1133                                         
1134                                         seq->flag &= SEQ_DESEL;
1135                                         
1136                                         seqn->flag &= ~(SEQ_LEFTSEL+SEQ_RIGHTSEL);
1137                                 }
1138                         }
1139
1140                 }
1141                 seq= seq->next;
1142         }
1143 }
1144
1145 void add_duplicate_seq(void)
1146 {
1147         Editing *ed;
1148         ListBase new;
1149         
1150         ed= G.scene->ed;
1151         if(ed==0) return;
1152         
1153         new.first= new.last= 0;
1154         
1155         recurs_dupli_seq(ed->seqbasep, &new);
1156         addlisttolist(ed->seqbasep, &new);
1157         
1158         transform_seq('g');
1159 }
1160
1161 int insert_gap(int gap, int cfra)
1162 {
1163         Sequence *seq;
1164         Editing *ed;
1165         int done=0;
1166         
1167         /* all strips >= cfra are shifted */
1168         ed= G.scene->ed;
1169         if(ed==0) return 0;
1170         
1171         WHILE_SEQ(ed->seqbasep) {
1172                 if(seq->startdisp >= cfra) {
1173                         seq->start+= gap;
1174                         calc_sequence(seq);
1175                         done= 1;
1176                 }
1177         }
1178         END_SEQ
1179         
1180         return done;
1181 }
1182
1183 void touch_seq_files(void)
1184 {
1185         Sequence *seq;
1186         Editing *ed;
1187         char str[256];
1188         
1189         /* touch all strips with movies */
1190         ed= G.scene->ed;
1191         if(ed==0) return;
1192         
1193         if(okee("Touch & print selected Movies")==0) return;
1194         
1195         waitcursor(1);
1196         
1197         WHILE_SEQ(ed->seqbasep) {
1198                 if(seq->flag & SELECT) {
1199                         if(seq->type==SEQ_MOVIE) {
1200                                 if(seq->strip && seq->strip->stripdata) {
1201                                         BLI_make_file_string(G.sce, str, seq->strip->dir, seq->strip->stripdata->name);
1202                                         BLI_touch(seq->name);
1203                                 }
1204                         }
1205                         
1206                 }
1207         }
1208         END_SEQ
1209         
1210         waitcursor(0);
1211 }
1212
1213 void set_filter_seq(void)
1214 {
1215         Sequence *seq;
1216         Editing *ed;
1217         
1218         ed= G.scene->ed;
1219         if(ed==0) return;
1220         
1221         if(okee("Set FilterY")==0) return;
1222         
1223         WHILE_SEQ(ed->seqbasep) {
1224                 if(seq->flag & SELECT) {
1225                         if(seq->type==SEQ_MOVIE) {
1226                                 seq->flag |= SEQ_FILTERY;
1227                         }
1228                         
1229                 }
1230         }
1231         END_SEQ
1232
1233 }
1234
1235
1236
1237 void no_gaps(void)
1238 {
1239         Editing *ed;
1240         int cfra, first= 0, done;
1241         
1242         ed= G.scene->ed;
1243         if(ed==0) return;
1244         
1245         for(cfra= CFRA; cfra<=EFRA; cfra++) {
1246                 if(first==0) {
1247                         if( evaluate_seq_frame(cfra) ) first= 1;
1248                 }
1249                 else {
1250                         done= 1;
1251                         while( evaluate_seq_frame(cfra) == 0) {
1252                                 done= insert_gap(-1, cfra);
1253                                 if(done==0) break;
1254                         }
1255                         if(done==0) break;
1256                 }
1257         }
1258         allqueue(REDRAWSEQ, 0);
1259 }
1260
1261
1262 /* ****************** META ************************* */
1263
1264 void make_meta(void)
1265 {
1266         Sequence *seq, *seqm, *next;
1267         Editing *ed;
1268         int tot;
1269         
1270         ed= G.scene->ed;
1271         if(ed==0) return;
1272
1273         /* is there more than 1 select */
1274         tot= 0;
1275         seq= ed->seqbasep->first;
1276         while(seq) {
1277                 if(seq->flag & SELECT) tot++;
1278                 seq= seq->next;
1279         }
1280         if(tot < 2) return;
1281         
1282         if(okee("Make Meta")==0) return;
1283         
1284         /* test relationships */
1285         seq= ed->seqbasep->first;
1286         while(seq) {
1287                 if(seq->flag & SELECT) {
1288                         if(seq->type & SEQ_EFFECT) {
1289                                 if((seq->seq1->flag & SELECT)==0) tot= 0;
1290                                 if((seq->seq2->flag & SELECT)==0) tot= 0;
1291                                 if((seq->seq3->flag & SELECT)==0) tot= 0;
1292                         }
1293                 }
1294                 else if(seq->type & SEQ_EFFECT) {
1295                         if(seq->seq1->flag & SELECT) tot= 0;
1296                         if(seq->seq2->flag & SELECT) tot= 0;
1297                         if(seq->seq3->flag & SELECT) tot= 0;
1298                 }
1299                 if(tot==0) break;
1300                 seq= seq->next;
1301         }
1302         if(tot==0) {
1303                 error("Select all related strips");
1304                 return;
1305         }
1306
1307         /* remove all selected from main list, and put in meta */
1308
1309         seqm= alloc_sequence(1, 1);
1310         seqm->type= SEQ_META;
1311         seqm->flag= SELECT;
1312         
1313         seq= ed->seqbasep->first;
1314         while(seq) {
1315                 next= seq->next;
1316                 if(seq!=seqm && (seq->flag & SELECT)) {
1317                         BLI_remlink(ed->seqbasep, seq);
1318                         BLI_addtail(&seqm->seqbase, seq);
1319                 }
1320                 seq= next;
1321         }
1322         calc_sequence(seqm);
1323         
1324         seqm->strip= MEM_callocN(sizeof(Strip), "metastrip");
1325         seqm->strip->len= seqm->len;
1326         seqm->strip->us= 1;
1327         if(seqm->len) seqm->strip->stripdata= MEM_callocN(seqm->len*sizeof(StripElem), "metastripdata");
1328         
1329         set_meta_stripdata(seqm);
1330         
1331         allqueue(REDRAWSEQ, 0);
1332 }
1333
1334 void un_meta(void)
1335 {
1336         Editing *ed;
1337         Sequence *seq, *seqn;
1338         int doit;
1339         
1340         ed= G.scene->ed;
1341         if(ed==0) return;
1342         
1343         if(last_seq==0 || last_seq->type!=SEQ_META) return;
1344         
1345         if(okee("Un Meta")==0) return;
1346
1347         addlisttolist(ed->seqbasep, &last_seq->seqbase);
1348         
1349         last_seq->seqbase.first= 0;
1350         last_seq->seqbase.last= 0;
1351         
1352         BLI_remlink(ed->seqbasep, last_seq);
1353         free_sequence(last_seq);
1354
1355         /* test effects */
1356         doit= 1;
1357         while(doit) {
1358                 doit= 0;
1359                 seq= ed->seqbasep->first;
1360                 while(seq) {
1361                         seqn= seq->next;
1362                         if(seq->type & SEQ_EFFECT) {
1363                                 if( is_a_sequence(seq->seq1)==0 || is_a_sequence(seq->seq2)==0 || is_a_sequence(seq->seq3)==0 ) {
1364                                         BLI_remlink(ed->seqbasep, seq);
1365                                         if(seq==last_seq) last_seq= 0;
1366                                         free_sequence(seq);
1367                                         doit= 1;
1368                                 }
1369                         }
1370                         seq= seqn;
1371                 }
1372         }
1373
1374
1375         /* test for effects and overlap */
1376         WHILE_SEQ(ed->seqbasep) {
1377                 if(seq->flag & SELECT) {
1378                         seq->flag &= ~SEQ_OVERLAP;
1379                         if( test_overlap_seq(seq) ) {
1380                                 shuffle_seq(seq);
1381                         }
1382                 }
1383         }
1384         END_SEQ;
1385         
1386         allqueue(REDRAWSEQ, 0);
1387         
1388 }
1389
1390 static void exit_meta(void)
1391 {
1392         Sequence *seq;
1393         MetaStack *ms;
1394         Editing *ed;
1395         
1396         ed= G.scene->ed;
1397         if(ed==0) return;
1398         
1399         if(ed->metastack.first==0) return;
1400         
1401         ms= ed->metastack.last; 
1402         BLI_remlink(&ed->metastack, ms);
1403
1404         ed->seqbasep= ms->oldbasep;
1405
1406         /* recalc entire meta */
1407         set_meta_stripdata(ms->parseq);
1408
1409         /* recalc all: the meta can have effects connected to it */
1410         seq= ed->seqbasep->first;
1411         while(seq) {
1412                 calc_sequence(seq);
1413                 seq= seq->next;
1414         }
1415
1416         last_seq= ms->parseq;
1417         
1418         last_seq->flag= SELECT;
1419         recurs_sel_seq(last_seq);
1420         
1421         MEM_freeN(ms);
1422         allqueue(REDRAWSEQ, 0);
1423 }
1424
1425
1426 void enter_meta(void)
1427 {
1428         MetaStack *ms;
1429         Editing *ed;
1430         
1431         ed= G.scene->ed;
1432         if(ed==0) return;
1433         
1434         if(last_seq==0 || last_seq->type!=SEQ_META || last_seq->flag==0) {
1435                 exit_meta();
1436                 return;
1437         }
1438         
1439         ms= MEM_mallocN(sizeof(MetaStack), "metastack");
1440         BLI_addtail(&ed->metastack, ms);
1441         ms->parseq= last_seq;
1442         ms->oldbasep= ed->seqbasep;
1443         
1444         ed->seqbasep= &last_seq->seqbase;
1445         
1446         last_seq= 0;
1447         allqueue(REDRAWSEQ, 0);
1448 }
1449
1450
1451 /* ****************** END META ************************* */
1452
1453
1454 typedef struct TransSeq {
1455         int start, machine;
1456         int startstill, endstill;
1457         int startofs, endofs;
1458 } TransSeq;
1459
1460 void transform_seq(int mode)
1461 {
1462         Sequence *seq;
1463         Editing *ed;
1464         float dx, dy, dvec[2], div;
1465         TransSeq *transmain, *ts;
1466         int tot=0, ix, iy, firsttime=1, afbreek=0, midtog= 0, proj= 0;
1467         unsigned short event = 0;
1468         short mval[2], val, xo, yo, xn, yn;
1469         char str[32];
1470         
1471         if(mode!='g') return;   /* from gesture */
1472         
1473         /* which seqs are involved */
1474         ed= G.scene->ed;
1475         if(ed==0) return;
1476         
1477         WHILE_SEQ(ed->seqbasep) {
1478                 if(seq->flag & SELECT) tot++;
1479         }
1480         END_SEQ
1481
1482         if(tot==0) return;
1483
1484         G.moving= 1;
1485
1486         ts=transmain= MEM_callocN(tot*sizeof(TransSeq), "transseq");
1487         
1488         WHILE_SEQ(ed->seqbasep) {
1489         
1490                 if(seq->flag & SELECT) {
1491                         
1492                         ts->start= seq->start;
1493                         ts->machine= seq->machine;
1494                         ts->startstill= seq->startstill;
1495                         ts->endstill= seq->endstill;
1496                         ts->startofs= seq->startofs;
1497                         ts->endofs= seq->endofs;
1498                         
1499                         ts++;
1500                 }
1501         }
1502         END_SEQ
1503         
1504         getmouseco_areawin(mval);
1505         xo=xn= mval[0];
1506         yo=yn= mval[1];
1507         dvec[0]= dvec[1]= 0.0;
1508         
1509         while(afbreek==0) {
1510                 getmouseco_areawin(mval);
1511                 if(mval[0]!=xo || mval[1]!=yo || firsttime) {
1512                         firsttime= 0;
1513                         
1514                         if(mode=='g') {
1515                         
1516                                 dx= mval[0]- xo;
1517                                 dy= mval[1]- yo;
1518         
1519                                 div= G.v2d->mask.xmax-G.v2d->mask.xmin;
1520                                 dx= (G.v2d->cur.xmax-G.v2d->cur.xmin)*(dx)/div;
1521         
1522                                 div= G.v2d->mask.ymax-G.v2d->mask.ymin;
1523                                 dy= (G.v2d->cur.ymax-G.v2d->cur.ymin)*(dy)/div;
1524
1525                                 if(G.qual & LR_SHIFTKEY) {
1526                                         if(dx>1.0) dx= 1.0; else if(dx<-1.0) dx= -1.0;
1527                                 }
1528
1529                                 dvec[0]+= dx;
1530                                 dvec[1]+= dy;
1531                                 
1532                                 if(midtog) dvec[proj]= 0.0;
1533                                 ix= floor(dvec[0]+0.5);
1534                                 iy= floor(dvec[1]+0.5);
1535                                 
1536                                 
1537                                 ts= transmain;
1538                                 
1539                                 WHILE_SEQ(ed->seqbasep) {
1540                                         if(seq->flag & SELECT) {
1541                                                 if(seq->flag & SEQ_LEFTSEL) {
1542                                                         if(ts->startstill) {
1543                                                                 seq->startstill= ts->startstill-ix;
1544                                                                 if(seq->startstill<0) seq->startstill= 0;
1545                                                         }
1546                                                         else if(ts->startofs) {
1547                                                                 seq->startofs= ts->startofs+ix;
1548                                                                 if(seq->startofs<0) seq->startofs= 0;
1549                                                         }
1550                                                         else {
1551                                                                 if(ix>0) {
1552                                                                         seq->startofs= ix;
1553                                                                         seq->startstill= 0;
1554                                                                 }
1555                                                                 else {
1556                                                                         seq->startstill= -ix;
1557                                                                         seq->startofs= 0;
1558                                                                 }
1559                                                         }
1560                                                         if(seq->len <= seq->startofs+seq->endofs) {
1561                                                                 seq->startofs= seq->len-seq->endofs-1;
1562                                                         }
1563                                                 }
1564                                                 if(seq->flag & SEQ_RIGHTSEL) {
1565                                                         if(ts->endstill) {
1566                                                                 seq->endstill= ts->endstill+ix;
1567                                                                 if(seq->endstill<0) seq->endstill= 0;
1568                                                         }
1569                                                         else if(ts->endofs) {
1570                                                                 seq->endofs= ts->endofs-ix;
1571                                                                 if(seq->endofs<0) seq->endofs= 0;
1572                                                         }
1573                                                         else {
1574                                                                 if(ix<0) {
1575                                                                         seq->endofs= -ix;
1576                                                                         seq->endstill= 0;
1577                                                                 }
1578                                                                 else {
1579                                                                         seq->endstill= ix;
1580                                                                         seq->endofs= 0;
1581                                                                 }
1582                                                         }
1583                                                         if(seq->len <= seq->startofs+seq->endofs) {
1584                                                                 seq->endofs= seq->len-seq->startofs-1;
1585                                                         }
1586                                                 }
1587                                                 if( (seq->flag & (SEQ_LEFTSEL+SEQ_RIGHTSEL))==0 ) {
1588                                                         if(seq->type<SEQ_EFFECT) seq->start= ts->start+ ix;
1589                                                         
1590                                                         if(seq->depth==0) seq->machine= ts->machine+ iy;
1591                                                         
1592                                                         if(seq->machine<1) seq->machine= 1;
1593                                                         else if(seq->machine>= MAXSEQ) seq->machine= MAXSEQ;
1594                                                 }
1595                                                 
1596                                                 calc_sequence(seq);
1597                                                 
1598                                                 ts++;
1599                                         }
1600                                 }
1601                                 END_SEQ
1602                                 
1603                                 sprintf(str, "X: %d   Y: %d  ", ix, iy);
1604                                 headerprint(str);
1605                         }
1606                 
1607                         xo= mval[0];
1608                         yo= mval[1];
1609                         
1610                         /* test for effect and overlap */
1611                         
1612                         WHILE_SEQ(ed->seqbasep) {
1613                                 if(seq->flag & SELECT) {
1614                                         seq->flag &= ~SEQ_OVERLAP;
1615                                         if( test_overlap_seq(seq) ) {
1616                                                 seq->flag |= SEQ_OVERLAP;
1617                                         }
1618                                 }
1619                                 else if(seq->type & SEQ_EFFECT) {
1620                                         if(seq->seq1->flag & SELECT) calc_sequence(seq);
1621                                         else if(seq->seq2->flag & SELECT) calc_sequence(seq);
1622                                         else if(seq->seq3->flag & SELECT) calc_sequence(seq);
1623                                 }
1624                         }
1625                         END_SEQ;
1626                         
1627                         force_draw();
1628                 }
1629                 else BIF_wait_for_statechange();
1630                 
1631                 while(qtest()) {
1632                         event= extern_qread(&val);
1633                         if(val) {
1634                                 switch(event) {
1635                                 case ESCKEY:
1636                                 case LEFTMOUSE:
1637                                 case SPACEKEY:
1638                                         afbreek= 1;
1639                                         break;
1640                                 case MIDDLEMOUSE:
1641                                         midtog= ~midtog;
1642                                         if(midtog) {
1643                                                 if( abs(mval[0]-xn) > abs(mval[1]-yn)) proj= 1;
1644                                                 else proj= 0;
1645                                                 firsttime= 1;
1646                                         }
1647                                         break;
1648                                 default:
1649                                         arrows_move_cursor(event);
1650                                 }
1651                         }
1652                         if(afbreek) break;
1653                 }
1654         }
1655         
1656         if(event==ESCKEY) {
1657                 
1658                 ts= transmain;
1659                 WHILE_SEQ(ed->seqbasep) {
1660                         if(seq->flag & SELECT) {
1661                                 seq->start= ts->start;
1662                                 seq->machine= ts->machine;
1663                                 seq->startstill= ts->startstill;
1664                                 seq->endstill= ts->endstill;
1665                                 seq->startofs= ts->startofs;
1666                                 seq->endofs= ts->endofs;
1667
1668                                 calc_sequence(seq);
1669                                 seq->flag &= ~SEQ_OVERLAP;
1670                                 
1671                                 ts++;
1672                         } else if(seq->type & SEQ_EFFECT) {
1673                                 if(seq->seq1->flag & SELECT) calc_sequence(seq);
1674                                 else if(seq->seq2->flag & SELECT) calc_sequence(seq);
1675                                 else if(seq->seq3->flag & SELECT) calc_sequence(seq);
1676                         }
1677
1678                 }
1679                 END_SEQ
1680         }
1681         else {
1682
1683                 /* images, effects and overlap */
1684                 WHILE_SEQ(ed->seqbasep) {
1685                         if(seq->type == SEQ_META) {
1686                                 calc_sequence(seq);
1687                                 seq->flag &= ~SEQ_OVERLAP;
1688                                 if( test_overlap_seq(seq) ) shuffle_seq(seq);                   
1689                         }
1690                         else if(seq->flag & SELECT) {
1691                                 calc_sequence(seq);
1692                                 seq->flag &= ~SEQ_OVERLAP;
1693                                 if( test_overlap_seq(seq) ) shuffle_seq(seq);
1694                         }
1695                         else if(seq->type & SEQ_EFFECT) calc_sequence(seq);
1696                 }
1697                 END_SEQ
1698                 
1699                 /* as last: */
1700                 sort_seq();
1701         }
1702         
1703         G.moving= 0;
1704         MEM_freeN(transmain);
1705         
1706         allqueue(REDRAWSEQ, 0);
1707 }
1708
1709
1710 void clever_numbuts_seq(void)
1711 {
1712         PluginSeq *pis;
1713         StripElem *se;
1714         VarStruct *varstr;
1715         int a;
1716         
1717         if(last_seq==0) return;
1718         if(last_seq->type==SEQ_PLUGIN) {
1719                 pis= last_seq->plugin;
1720                 if(pis->vars==0) return;
1721                 
1722                 varstr= pis->varstr;
1723                 if(varstr) {
1724                         for(a=0; a<pis->vars; a++, varstr++) {
1725                                 add_numbut(a, varstr->type, varstr->name, varstr->min, varstr->max, &(pis->data[a]), varstr->tip);
1726                         }
1727                         
1728                         if( do_clever_numbuts(pis->pname, pis->vars, REDRAW) ) {
1729                                 new_stripdata(last_seq);
1730                                 free_imbuf_effect_spec(CFRA);
1731                                 allqueue(REDRAWSEQ, 0);
1732                         }
1733                 }
1734         }
1735         else if(last_seq->type==SEQ_MOVIE) {
1736
1737                 if(last_seq->mul==0.0) last_seq->mul= 1.0;
1738
1739                 add_numbut(0, TEX, "Name:", 0.0, 21.0, last_seq->name+2, 0);
1740                 add_numbut(1, TOG|SHO|BIT|4, "FilterY", 0.0, 1.0, &last_seq->flag, 0);
1741                 /* warning: only a single bit-button possible: we work at copied data! */
1742                 add_numbut(2, NUM|FLO, "Mul", 0.01, 5.0, &last_seq->mul, 0);
1743
1744                 if( do_clever_numbuts("Movie", 3, REDRAW) ) {
1745                         se= last_seq->curelem;
1746
1747                         if(se && se->ibuf ) {
1748                                 IMB_freeImBuf(se->ibuf);
1749                                 se->ibuf= 0;
1750                         }
1751                         allqueue(REDRAWSEQ, 0);
1752                 }
1753         }
1754         else if(last_seq->type==SEQ_META) {
1755
1756                 add_numbut(0, TEX, "Name:", 0.0, 21.0, last_seq->name+2, 0);
1757
1758                 if( do_clever_numbuts("Meta", 1, REDRAW) ) {
1759                         allqueue(REDRAWSEQ, 0);
1760                 }
1761         }
1762 }
1763
1764 void seq_snapmenu(void)
1765 {
1766         Editing *ed;
1767         Sequence *seq;
1768         short event;
1769         
1770         ed= G.scene->ed;
1771         if(ed==0) return;
1772         
1773         event= pupmenu("Snap %t|Seq to frame%x1");
1774         
1775         if(event<1) return;
1776
1777         /* problem: contents of meta's are all shifted to the same position... */
1778
1779         /* also check metas */
1780         WHILE_SEQ(ed->seqbasep) {
1781                 if(seq->flag & SELECT) {
1782                         if(seq->type<SEQ_EFFECT) seq->start= CFRA-seq->startofs+seq->startstill;
1783                         calc_sequence(seq);
1784                 }
1785         }
1786         END_SEQ
1787         
1788         
1789         /* test for effects and overlap */
1790         WHILE_SEQ(ed->seqbasep) {
1791                 if(seq->flag & SELECT) {
1792                         seq->flag &= ~SEQ_OVERLAP;
1793                         if( test_overlap_seq(seq) ) {
1794                                 shuffle_seq(seq);
1795                         }
1796                 }
1797                 else if(seq->type & SEQ_EFFECT) {
1798                         if(seq->seq1->flag & SELECT) calc_sequence(seq);
1799                         else if(seq->seq2->flag & SELECT) calc_sequence(seq);
1800                         else if(seq->seq3->flag & SELECT) calc_sequence(seq);
1801                 }
1802         }
1803         END_SEQ;
1804
1805         /* as last: */
1806         sort_seq();
1807                 
1808         allqueue(REDRAWSEQ, 0);
1809 }
1810
1811 void borderselect_seq(void)
1812 {
1813         Sequence *seq;
1814         Editing *ed;
1815         rcti rect;
1816         rctf rectf, rq;
1817         int val;
1818         short mval[2];
1819
1820         ed= G.scene->ed;
1821         if(ed==0) return;
1822         
1823         val= get_border(&rect, 3);
1824
1825         if(val) {
1826                 mval[0]= rect.xmin;
1827                 mval[1]= rect.ymin;
1828                 areamouseco_to_ipoco(G.v2d, mval, &rectf.xmin, &rectf.ymin);
1829                 mval[0]= rect.xmax;
1830                 mval[1]= rect.ymax;
1831                 areamouseco_to_ipoco(G.v2d, mval, &rectf.xmax, &rectf.ymax);
1832
1833                 seq= ed->seqbasep->first;
1834                 while(seq) {
1835                         
1836                         if(seq->startstill) rq.xmin= seq->start;
1837                         else rq.xmin= seq->startdisp;
1838                         rq.ymin= seq->machine+0.2;
1839                         if(seq->endstill) rq.xmax= seq->start+seq->len;
1840                         else rq.xmax= seq->enddisp;
1841                         rq.ymax= seq->machine+0.8;
1842                         
1843                         if(BLI_isect_rctf(&rq, &rectf, 0)) {
1844                                 if(val==LEFTMOUSE) {
1845                                         seq->flag |= SELECT;
1846                                 }
1847                                 else {
1848                                         seq->flag &= ~SELECT;
1849                                 }
1850                         }
1851                         
1852                         seq= seq->next;
1853                 }
1854
1855                 addqueue(curarea->win, REDRAW, 1);
1856         }
1857 }