Patch provided by Matt Ebb, cut sequence strips (patch tracker).
authorTon Roosendaal <ton@blender.org>
Sun, 14 Aug 2005 10:31:14 +0000 (10:31 +0000)
committerTon Roosendaal <ton@blender.org>
Sun, 14 Aug 2005 10:31:14 +0000 (10:31 +0000)
There were a couple of issues with the implementation:

- there was no proper test if selected strips would be cut or not
- cutting meta strips could go very wrong... for example when the cut
  of meta was in an internal gap. With meta's being recursive, and too
  complex, I've disabled Meta-cutting
- added an OK menu for hotkey K
- added warnings when no cut was done

This is the first time in 6 years I do work in sequencer... man, this has
grown into a messy bizz! Like sequence variables... using names like:
start, startdisp, startstill, startoffs... totally confusing here. Could
use giant cleanup! Implementation was weak from scratch though, Mea Culpa!

source/blender/include/BIF_editseq.h
source/blender/src/editseq.c
source/blender/src/header_seq.c
source/blender/src/space.c

index 48a7ca3467272b85da913dcfb546cb73e298191c..fb85a3290c275ef9135a42b6734d6c442985b275 100644 (file)
@@ -57,6 +57,7 @@ void                          swap_select_seq(void);
 void                           touch_seq_files(void);
 void                           transform_seq(int mode, int context);
 void                           un_meta(void);
+void                           seq_cut(short cutframe);
 
 /* drawseq.c */
 void do_seqbuttons(short);
index c9aff9b42cc8d855bfc72ae656dedd64df511e47..14d545a7262d9d72e1d3edf66947f0ff6a82dde3 100644 (file)
@@ -1754,7 +1754,9 @@ void enter_meta(void)
 typedef struct TransSeq {
        int start, machine;
        int startstill, endstill;
+       int startdisp, enddisp;
        int startofs, endofs;
+       int len;
 } TransSeq;
 
 void transform_seq(int mode, int context)
@@ -2074,6 +2076,136 @@ void clever_numbuts_seq(void)
        }
 }
 
+void seq_cut(short cutframe)
+{
+       Editing *ed;
+       Sequence *seq;
+       TransSeq *ts, *transmain;
+       int tot=0;
+       ListBase newlist;
+       
+       ed= G.scene->ed;
+       if(ed==0) return;
+       
+       /* test for validity */
+       for(seq= ed->seqbasep->first; seq; seq= seq->next) {
+               if(seq->flag & SELECT) {
+                       if(cutframe > seq->startdisp && cutframe < seq->enddisp)
+                               if(seq->type==SEQ_META) break;
+               }
+       }
+       if(seq) {
+               error("Cannot cut Meta strips");
+               return;
+       }
+       
+       /* we build an array of TransSeq, to denote which strips take part in cutting */
+       for(seq= ed->seqbasep->first; seq; seq= seq->next) {
+               if(seq->flag & SELECT) {
+                       if(cutframe > seq->startdisp && cutframe < seq->enddisp)
+                               tot++;
+                       else
+                               seq->flag &= ~SELECT;   // bad code, but we need it for recurs_dupli_seq... note that this ~SELECT assumption is used in loops below too (ton)
+               }
+       }
+       
+       if(tot==0) {
+               error("No strips to cut");
+               return;
+       }
+       
+       ts=transmain= MEM_callocN(tot*sizeof(TransSeq), "transseq");
+       
+       for(seq= ed->seqbasep->first; seq; seq= seq->next) {
+               if(seq->flag & SELECT) {
+                       
+                       ts->start= seq->start;
+                       ts->machine= seq->machine;
+                       ts->startstill= seq->startstill;
+                       ts->endstill= seq->endstill;
+                       ts->startdisp= seq->startdisp;
+                       ts->enddisp= seq->enddisp;
+                       ts->startofs= seq->startofs;
+                       ts->endofs= seq->endofs;
+                       ts->len= seq->len;
+                       
+                       ts++;
+               }
+       }
+               
+       for(seq= ed->seqbasep->first; seq; seq= seq->next) {
+               if(seq->flag & SELECT) {
+                       
+                       /* strips with extended stillframes before */
+                       if ((seq->startstill) && (cutframe <seq->start)) {
+                               seq->start= cutframe -1;
+                               seq->startstill= cutframe -seq->startdisp -1;
+                               seq->len= 1;
+                               seq->endstill= 0;
+                       }
+                       
+                       /* normal strip */
+                       else if ((cutframe >=seq->start)&&(cutframe <=(seq->start+seq->len))) {
+                               seq->endofs = (seq->start+seq->len) - cutframe;
+                       }
+                       
+                       /* strips with extended stillframes after */
+                       else if (((seq->start+seq->len) < cutframe) && (seq->endstill)) {
+                               seq->endstill -= seq->enddisp - cutframe;
+                       }
+                       
+                       calc_sequence(seq);
+               }
+       }
+               
+       newlist.first= newlist.last= NULL;
+       
+       /* now we duplicate the cut strip and move it into place afterwards */
+       recurs_dupli_seq(ed->seqbasep, &newlist);
+       addlisttolist(ed->seqbasep, &newlist);
+       
+       ts= transmain;
+       
+       /* go through all the strips and correct them based on their stored values */
+       for(seq= ed->seqbasep->first; seq; seq= seq->next) {
+               if(seq->flag & SELECT) {
+
+                       /* strips with extended stillframes before */
+                       if ((seq->startstill) && (cutframe == seq->start + 1)) {
+                               seq->start = ts->start;
+                               seq->startstill= ts->start- cutframe;
+                               seq->len = ts->len;
+                               seq->endstill = ts->endstill;
+                       }
+                       
+                       /* normal strip */
+                       else if ((cutframe>=seq->start)&&(cutframe<=(seq->start+seq->len))) {
+                               seq->startstill = 0;
+                               seq->startofs = cutframe - ts->start;
+                               seq->endofs = ts->endofs;
+                               seq->endstill = ts->endstill;
+                       }                               
+                       
+                       /* strips with extended stillframes after */
+                       else if (((seq->start+seq->len) < cutframe) && (seq->endstill)) {
+                               seq->start = cutframe - ts->len +1;
+                               seq->startofs = ts->len-1;
+                               seq->endstill = ts->enddisp - cutframe -1;
+                               seq->startstill = 0;
+                       }
+                       calc_sequence(seq);
+                       
+                       ts++;
+               }
+       }
+               
+       /* as last: */  
+       sort_seq();
+       MEM_freeN(transmain);
+       
+       allqueue(REDRAWSEQ, 0);
+}
+
 void seq_snap_menu(void)
 {
        short event;
index b38aba31a8eee0a208b34194cfbac2809be7792e..cd65317145b3b409cfc99cc1e8a5e87a92d6abc4 100644 (file)
@@ -325,7 +325,10 @@ static void do_seq_editmenu(void *arg, int event)
                break;
        case 12: /* Snap to Current Frame */
                seq_snap(event);
-           break;
+               break;
+       case 13: /* Cut at Current Frame */
+               seq_cut(CFRA);
+               break;
        }
 }
 
@@ -345,6 +348,10 @@ static uiBlock *seq_editmenu(void *arg_unused)
        uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Grab/Move|G", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 11, "");
        uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Snap to Current Frame|Shift S, 1", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 12, "");
 
+       uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+       
+       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Cut at Current Frame|K", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 13, "");
+       
        uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
 
        uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Duplicate|Shift D", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 5, "");
index 259eee7b30045fe820d7d427e8818f22bdf42734..a91841afe7c2db5d4468beef57db5b29dad12025 100644 (file)
@@ -3438,6 +3438,11 @@ static void winqreadseqspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
                        if((G.qual==0))
                                transform_seq('g', 0);
                        break;
+               case KKEY:
+                       if((G.qual==0)) { /* Cut at current frame */
+                               if(okee("Cut strips")) seq_cut(CFRA);
+                       }
+                       break;
                case MKEY:
                        if(G.qual==LR_ALTKEY)
                                un_meta();