Blender V2.61 - r43446
|
00001 /* 00002 * ***** BEGIN GPL LICENSE BLOCK ***** 00003 * 00004 * This program is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License 00006 * as published by the Free Software Foundation; either version 2 00007 * of the License, or (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software Foundation, 00016 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 * 00018 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00019 * All rights reserved. 00020 * 00021 * Contributor(s): Blender Foundation, 2003-2009 00022 * 00023 * ***** END GPL LICENSE BLOCK ***** 00024 */ 00025 00031 #include <stdlib.h> 00032 #include <math.h> 00033 #include <string.h> 00034 00035 #ifndef WIN32 00036 #include <unistd.h> 00037 #else 00038 #include <io.h> 00039 #endif 00040 #include <sys/types.h> 00041 00042 #include "MEM_guardedalloc.h" 00043 00044 #include "BLI_blenlib.h" 00045 #include "BLI_math.h" 00046 #include "BLI_utildefines.h" 00047 #include "BLI_threads.h" 00048 00049 #include "DNA_scene_types.h" 00050 #include "DNA_userdef_types.h" 00051 00052 #include "BKE_context.h" 00053 #include "BKE_global.h" 00054 #include "BKE_main.h" 00055 #include "BKE_sequencer.h" 00056 #include "BKE_report.h" 00057 #include "BKE_sound.h" 00058 00059 #include "WM_api.h" 00060 #include "WM_types.h" 00061 00062 #include "RNA_define.h" 00063 #include "RNA_enum_types.h" 00064 00065 /* for menu/popup icons etc etc*/ 00066 00067 #include "ED_screen.h" 00068 #include "ED_transform.h" 00069 #include "ED_sequencer.h" 00070 00071 #include "UI_view2d.h" 00072 00073 /* own include */ 00074 #include "sequencer_intern.h" 00075 00076 static int okee(const char *UNUSED(dummy)) {return 0;} 00077 00078 00079 /* XXX */ 00080 /* RNA Enums, used in multiple files */ 00081 EnumPropertyItem sequencer_prop_effect_types[] = { 00082 {SEQ_CROSS, "CROSS", 0, "Crossfade", "Crossfade effect strip type"}, 00083 {SEQ_ADD, "ADD", 0, "Add", "Add effect strip type"}, 00084 {SEQ_SUB, "SUBTRACT", 0, "Subtract", "Subtract effect strip type"}, 00085 {SEQ_ALPHAOVER, "ALPHA_OVER", 0, "Alpha Over", "Alpha Over effect strip type"}, 00086 {SEQ_ALPHAUNDER, "ALPHA_UNDER", 0, "Alpha Under", "Alpha Under effect strip type"}, 00087 {SEQ_GAMCROSS, "GAMMA_CROSS", 0, "Gamma Cross", "Gamma Cross effect strip type"}, 00088 {SEQ_MUL, "MULTIPLY", 0, "Multiply", "Multiply effect strip type"}, 00089 {SEQ_OVERDROP, "OVER_DROP", 0, "Alpha Over Drop", "Alpha Over Drop effect strip type"}, 00090 {SEQ_PLUGIN, "PLUGIN", 0, "Plugin", "Plugin effect strip type"}, 00091 {SEQ_WIPE, "WIPE", 0, "Wipe", "Wipe effect strip type"}, 00092 {SEQ_GLOW, "GLOW", 0, "Glow", "Glow effect strip type"}, 00093 {SEQ_TRANSFORM, "TRANSFORM", 0, "Transform", "Transform effect strip type"}, 00094 {SEQ_COLOR, "COLOR", 0, "Color", "Color effect strip type"}, 00095 {SEQ_SPEED, "SPEED", 0, "Speed", "Color effect strip type"}, 00096 {SEQ_MULTICAM, "MULTICAM", 0, "Multicam Selector", ""}, 00097 {SEQ_ADJUSTMENT, "ADJUSTMENT", 0, "Adjustment Layer", ""}, 00098 {0, NULL, 0, NULL, NULL} 00099 }; 00100 00101 /* mute operator */ 00102 00103 EnumPropertyItem prop_side_types[] = { 00104 {SEQ_SIDE_LEFT, "LEFT", 0, "Left", ""}, 00105 {SEQ_SIDE_RIGHT, "RIGHT", 0, "Right", ""}, 00106 {SEQ_SIDE_BOTH, "BOTH", 0, "Both", ""}, 00107 {0, NULL, 0, NULL, NULL} 00108 }; 00109 00110 static EnumPropertyItem prop_side_lr_types[] = { 00111 {SEQ_SIDE_LEFT, "LEFT", 0, "Left", ""}, 00112 {SEQ_SIDE_RIGHT, "RIGHT", 0, "Right", ""}, 00113 {0, NULL, 0, NULL, NULL} 00114 }; 00115 00116 typedef struct TransSeq { 00117 int start, machine; 00118 int startstill, endstill; 00119 int startdisp, enddisp; 00120 int startofs, endofs; 00121 int anim_startofs, anim_endofs; 00122 /* int final_left, final_right; */ /* UNUSED */ 00123 int len; 00124 } TransSeq; 00125 00126 /* ********************************************************************** */ 00127 00128 /* ***************** proxy job manager ********************** */ 00129 00130 typedef struct ProxyBuildJob { 00131 Scene *scene; 00132 struct Main * main; 00133 ListBase queue; 00134 ThreadMutex queue_lock; 00135 } ProxyJob; 00136 00137 static void proxy_freejob(void *pjv) 00138 { 00139 ProxyJob *pj= pjv; 00140 Sequence * seq; 00141 00142 for (seq = pj->queue.first; seq; seq = seq->next) { 00143 BLI_remlink(&pj->queue, seq); 00144 seq_free_sequence_recurse(pj->scene, seq); 00145 } 00146 00147 BLI_mutex_end(&pj->queue_lock); 00148 00149 MEM_freeN(pj); 00150 } 00151 00152 /* only this runs inside thread */ 00153 static void proxy_startjob(void *pjv, short *stop, short *do_update, float *progress) 00154 { 00155 ProxyJob *pj = pjv; 00156 00157 while (!*stop) { 00158 Sequence * seq; 00159 00160 BLI_mutex_lock(&pj->queue_lock); 00161 00162 if (!pj->queue.first) { 00163 BLI_mutex_unlock(&pj->queue_lock); 00164 break; 00165 } 00166 00167 seq = pj->queue.first; 00168 00169 BLI_remlink(&pj->queue, seq); 00170 BLI_mutex_unlock(&pj->queue_lock); 00171 00172 seq_proxy_rebuild(pj->main, pj->scene, seq, 00173 stop, do_update, progress); 00174 seq_free_sequence_recurse(pj->scene, seq); 00175 } 00176 00177 if (*stop) { 00178 fprintf(stderr, 00179 "Canceling proxy rebuild on users request...\n"); 00180 } 00181 } 00182 00183 static void proxy_endjob(void *UNUSED(customdata)) 00184 { 00185 00186 } 00187 00188 static void seq_proxy_build_job(const bContext *C, Sequence * seq) 00189 { 00190 wmJob * steve; 00191 ProxyJob *pj; 00192 Scene *scene= CTX_data_scene(C); 00193 ScrArea * sa= CTX_wm_area(C); 00194 00195 seq = seq_dupli_recursive(scene, scene, seq, 0); 00196 00197 steve = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), 00198 sa, "Building Proxies", WM_JOB_PROGRESS); 00199 00200 pj = WM_jobs_get_customdata(steve); 00201 00202 if (!pj) { 00203 pj = MEM_callocN(sizeof(ProxyJob), "proxy rebuild job"); 00204 00205 pj->scene= scene; 00206 pj->main = CTX_data_main(C); 00207 00208 BLI_mutex_init(&pj->queue_lock); 00209 00210 WM_jobs_customdata(steve, pj, proxy_freejob); 00211 WM_jobs_timer(steve, 0.1, NC_SCENE|ND_SEQUENCER, 00212 NC_SCENE|ND_SEQUENCER); 00213 WM_jobs_callbacks(steve, proxy_startjob, NULL, NULL, 00214 proxy_endjob); 00215 } 00216 00217 BLI_mutex_lock(&pj->queue_lock); 00218 BLI_addtail(&pj->queue, seq); 00219 BLI_mutex_unlock(&pj->queue_lock); 00220 00221 if (!WM_jobs_is_running(steve)) { 00222 G.afbreek = 0; 00223 WM_jobs_start(CTX_wm_manager(C), steve); 00224 } 00225 00226 ED_area_tag_redraw(CTX_wm_area(C)); 00227 } 00228 00229 /* ********************************************************************** */ 00230 00231 void seq_rectf(Sequence *seq, rctf *rectf) 00232 { 00233 if(seq->startstill) rectf->xmin= seq->start; 00234 else rectf->xmin= seq->startdisp; 00235 rectf->ymin= seq->machine+SEQ_STRIP_OFSBOTTOM; 00236 if(seq->endstill) rectf->xmax= seq->start+seq->len; 00237 else rectf->xmax= seq->enddisp; 00238 rectf->ymax= seq->machine+SEQ_STRIP_OFSTOP; 00239 } 00240 00241 static void UNUSED_FUNCTION(change_plugin_seq)(Scene *scene, char *str) /* called from fileselect */ 00242 { 00243 Editing *ed= seq_give_editing(scene, FALSE); 00244 struct SeqEffectHandle sh; 00245 Sequence *last_seq= seq_active_get(scene); 00246 00247 if(last_seq==NULL || last_seq->type != SEQ_PLUGIN) return; 00248 00249 sh = get_sequence_effect(last_seq); 00250 sh.free(last_seq); 00251 sh.init_plugin(last_seq, str); 00252 00253 last_seq->machine = MAX3(last_seq->seq1->machine, 00254 last_seq->seq2->machine, 00255 last_seq->seq3->machine); 00256 00257 if( seq_test_overlap(ed->seqbasep, last_seq) ) shuffle_seq(ed->seqbasep, last_seq, scene); 00258 00259 } 00260 00261 00262 void boundbox_seq(Scene *scene, rctf *rect) 00263 { 00264 Sequence *seq; 00265 Editing *ed= seq_give_editing(scene, FALSE); 00266 float min[2], max[2]; 00267 00268 00269 if(ed==NULL) return; 00270 00271 min[0]= 0.0; 00272 max[0]= EFRA+1; 00273 min[1]= 0.0; 00274 max[1]= 8.0; 00275 00276 seq= ed->seqbasep->first; 00277 while(seq) { 00278 00279 if( min[0] > seq->startdisp-1) min[0]= seq->startdisp-1; 00280 if( max[0] < seq->enddisp+1) max[0]= seq->enddisp+1; 00281 if( max[1] < seq->machine+2) max[1]= seq->machine+2; 00282 00283 seq= seq->next; 00284 } 00285 00286 rect->xmin= min[0]; 00287 rect->xmax= max[0]; 00288 rect->ymin= min[1]; 00289 rect->ymax= max[1]; 00290 00291 } 00292 00293 static int mouse_frame_side(View2D *v2d, short mouse_x, int frame ) 00294 { 00295 int mval[2]; 00296 float mouseloc[2]; 00297 00298 mval[0]= mouse_x; 00299 mval[1]= 0; 00300 00301 /* choose the side based on which side of the playhead the mouse is on */ 00302 UI_view2d_region_to_view(v2d, mval[0], mval[1], &mouseloc[0], &mouseloc[1]); 00303 00304 return mouseloc[0] > frame ? SEQ_SIDE_RIGHT : SEQ_SIDE_LEFT; 00305 } 00306 00307 00308 Sequence *find_neighboring_sequence(Scene *scene, Sequence *test, int lr, int sel) 00309 { 00310 /* sel - 0==unselected, 1==selected, -1==done care*/ 00311 Sequence *seq; 00312 Editing *ed= seq_give_editing(scene, FALSE); 00313 00314 if(ed==NULL) return NULL; 00315 00316 if (sel>0) sel = SELECT; 00317 00318 for(seq= ed->seqbasep->first; seq; seq= seq->next) { 00319 if( (seq!=test) && 00320 (test->machine==seq->machine) && 00321 ((sel == -1) || (sel && (seq->flag & SELECT)) || (sel==0 && (seq->flag & SELECT)==0) )) 00322 { 00323 switch (lr) { 00324 case SEQ_SIDE_LEFT: 00325 if (test->startdisp == (seq->enddisp)) { 00326 return seq; 00327 } 00328 break; 00329 case SEQ_SIDE_RIGHT: 00330 if (test->enddisp == (seq->startdisp)) { 00331 return seq; 00332 } 00333 break; 00334 } 00335 } 00336 } 00337 return NULL; 00338 } 00339 00340 static Sequence *find_next_prev_sequence(Scene *scene, Sequence *test, int lr, int sel) 00341 { 00342 /* sel - 0==unselected, 1==selected, -1==done care*/ 00343 Sequence *seq,*best_seq = NULL; 00344 Editing *ed= seq_give_editing(scene, FALSE); 00345 00346 int dist, best_dist; 00347 best_dist = MAXFRAME*2; 00348 00349 00350 if(ed==NULL) return NULL; 00351 00352 seq= ed->seqbasep->first; 00353 while(seq) { 00354 if( (seq!=test) && 00355 (test->machine==seq->machine) && 00356 (test->depth==seq->depth) && 00357 ((sel == -1) || (sel==(seq->flag & SELECT)))) 00358 { 00359 dist = MAXFRAME*2; 00360 00361 switch (lr) { 00362 case SEQ_SIDE_LEFT: 00363 if (seq->enddisp <= test->startdisp) { 00364 dist = test->enddisp - seq->startdisp; 00365 } 00366 break; 00367 case SEQ_SIDE_RIGHT: 00368 if (seq->startdisp >= test->enddisp) { 00369 dist = seq->startdisp - test->enddisp; 00370 } 00371 break; 00372 } 00373 00374 if (dist==0) { 00375 best_seq = seq; 00376 break; 00377 } else if (dist < best_dist) { 00378 best_dist = dist; 00379 best_seq = seq; 00380 } 00381 } 00382 seq= seq->next; 00383 } 00384 return best_seq; /* can be null */ 00385 } 00386 00387 00388 Sequence *find_nearest_seq(Scene *scene, View2D *v2d, int *hand, const int mval[2]) 00389 { 00390 Sequence *seq; 00391 Editing *ed= seq_give_editing(scene, FALSE); 00392 float x, y; 00393 float pixelx; 00394 float handsize; 00395 float displen; 00396 *hand= SEQ_SIDE_NONE; 00397 00398 00399 if(ed==NULL) return NULL; 00400 00401 pixelx = (v2d->cur.xmax - v2d->cur.xmin)/(v2d->mask.xmax - v2d->mask.xmin); 00402 00403 UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y); 00404 00405 seq= ed->seqbasep->first; 00406 00407 while(seq) { 00408 if(seq->machine == (int)y) { 00409 /* check for both normal strips, and strips that have been flipped horizontally */ 00410 if( ((seq->startdisp < seq->enddisp) && (seq->startdisp<=x && seq->enddisp>=x)) || 00411 ((seq->startdisp > seq->enddisp) && (seq->startdisp>=x && seq->enddisp<=x)) ) 00412 { 00413 if(seq_tx_test(seq)) { 00414 00415 /* clamp handles to defined size in pixel space */ 00416 00417 handsize = seq->handsize; 00418 displen = (float)abs(seq->startdisp - seq->enddisp); 00419 00420 if (displen / pixelx > 16) { /* dont even try to grab the handles of small strips */ 00421 /* Set the max value to handle to 1/3 of the total len when its less then 28. 00422 * This is important because otherwise selecting handles happens even when you click in the middle */ 00423 00424 if ((displen/3) < 30*pixelx) { 00425 handsize = displen/3; 00426 } else { 00427 CLAMP(handsize, 7*pixelx, 30*pixelx); 00428 } 00429 00430 if( handsize+seq->startdisp >=x ) 00431 *hand= SEQ_SIDE_LEFT; 00432 else if( -handsize+seq->enddisp <=x ) 00433 *hand= SEQ_SIDE_RIGHT; 00434 } 00435 } 00436 return seq; 00437 } 00438 } 00439 seq= seq->next; 00440 } 00441 return NULL; 00442 } 00443 00444 00445 static int seq_is_parent(Sequence *par, Sequence *seq) 00446 { 00447 return ((par->seq1 == seq) || (par->seq2 == seq) || (par->seq3 == seq)); 00448 } 00449 00450 static int seq_is_predecessor(Sequence *pred, Sequence *seq) 00451 { 00452 if (!pred) return 0; 00453 if(pred == seq) return 0; 00454 else if(seq_is_parent(pred, seq)) return 1; 00455 else if(pred->seq1 && seq_is_predecessor(pred->seq1, seq)) return 1; 00456 else if(pred->seq2 && seq_is_predecessor(pred->seq2, seq)) return 1; 00457 else if(pred->seq3 && seq_is_predecessor(pred->seq3, seq)) return 1; 00458 00459 return 0; 00460 } 00461 00462 void deselect_all_seq(Scene *scene) 00463 { 00464 Sequence *seq; 00465 Editing *ed= seq_give_editing(scene, FALSE); 00466 00467 00468 if(ed==NULL) return; 00469 00470 SEQP_BEGIN(ed, seq) { 00471 seq->flag &= ~SEQ_ALLSEL; 00472 } 00473 SEQ_END 00474 00475 } 00476 00477 void recurs_sel_seq(Sequence *seqm) 00478 { 00479 Sequence *seq; 00480 00481 seq= seqm->seqbase.first; 00482 while(seq) { 00483 00484 if(seqm->flag & (SEQ_LEFTSEL+SEQ_RIGHTSEL)) seq->flag &= ~SEQ_ALLSEL; 00485 else if(seqm->flag & SELECT) seq->flag |= SELECT; 00486 else seq->flag &= ~SEQ_ALLSEL; 00487 00488 if(seq->seqbase.first) recurs_sel_seq(seq); 00489 00490 seq= seq->next; 00491 } 00492 } 00493 00494 int seq_effect_find_selected(Scene *scene, Sequence *activeseq, int type, Sequence **selseq1, Sequence **selseq2, Sequence **selseq3, const char **error_str) 00495 { 00496 Editing *ed = seq_give_editing(scene, FALSE); 00497 Sequence *seq1= NULL, *seq2= NULL, *seq3= NULL, *seq; 00498 00499 *error_str= NULL; 00500 00501 if (!activeseq) 00502 seq2= seq_active_get(scene); 00503 00504 for(seq=ed->seqbasep->first; seq; seq=seq->next) { 00505 if(seq->flag & SELECT) { 00506 if (seq->type == SEQ_SOUND && get_sequence_effect_num_inputs(type) != 0) { 00507 *error_str= "Can't apply effects to audio sequence strips"; 00508 return 0; 00509 } 00510 if((seq != activeseq) && (seq != seq2)) { 00511 if(seq2 == NULL) seq2= seq; 00512 else if(seq1 == NULL) seq1= seq; 00513 else if(seq3 == NULL) seq3= seq; 00514 else { 00515 *error_str= "Can't apply effect to more than 3 sequence strips"; 00516 return 0; 00517 } 00518 } 00519 } 00520 } 00521 00522 /* make sequence selection a little bit more intuitive 00523 for 3 strips: the last-strip should be sequence3 */ 00524 if (seq3 != NULL && seq2 != NULL) { 00525 Sequence *tmp = seq2; 00526 seq2 = seq3; 00527 seq3 = tmp; 00528 } 00529 00530 00531 switch(get_sequence_effect_num_inputs(type)) { 00532 case 0: 00533 *selseq1 = *selseq2 = *selseq3 = NULL; 00534 return 1; /* succsess */ 00535 case 1: 00536 if(seq2==NULL) { 00537 *error_str= "Need at least one selected sequence strip"; 00538 return 0; 00539 } 00540 if(seq1==NULL) seq1= seq2; 00541 if(seq3==NULL) seq3= seq2; 00542 case 2: 00543 if(seq1==NULL || seq2==NULL) { 00544 *error_str= "Need 2 selected sequence strips"; 00545 return 0; 00546 } 00547 if(seq3 == NULL) seq3= seq2; 00548 } 00549 00550 if (seq1==NULL && seq2==NULL && seq3==NULL) { 00551 *error_str= "TODO: in what cases does this happen?"; 00552 return 0; 00553 } 00554 00555 *selseq1= seq1; 00556 *selseq2= seq2; 00557 *selseq3= seq3; 00558 00559 return 1; 00560 } 00561 00562 static Sequence *del_seq_find_replace_recurs(Scene *scene, Sequence *seq) 00563 { 00564 Sequence *seq1, *seq2, *seq3; 00565 00566 /* try to find a replacement input sequence, and flag for later deletion if 00567 no replacement can be found */ 00568 00569 if(!seq) 00570 return NULL; 00571 else if(!(seq->type & SEQ_EFFECT)) 00572 return ((seq->flag & SELECT)? NULL: seq); 00573 else if(!(seq->flag & SELECT)) { 00574 /* try to find replacement for effect inputs */ 00575 seq1= del_seq_find_replace_recurs(scene, seq->seq1); 00576 seq2= del_seq_find_replace_recurs(scene, seq->seq2); 00577 seq3= del_seq_find_replace_recurs(scene, seq->seq3); 00578 00579 if(seq1==seq->seq1 && seq2==seq->seq2 && seq3==seq->seq3); 00580 else if(seq1 || seq2 || seq3) { 00581 seq->seq1= (seq1)? seq1: (seq2)? seq2: seq3; 00582 seq->seq2= (seq2)? seq2: (seq1)? seq1: seq3; 00583 seq->seq3= (seq3)? seq3: (seq1)? seq1: seq2; 00584 00585 update_changed_seq_and_deps(scene, seq, 1, 1); 00586 } 00587 else 00588 seq->flag |= SELECT; /* mark for delete */ 00589 } 00590 00591 if (seq->flag & SELECT) { 00592 if((seq1 = del_seq_find_replace_recurs(scene, seq->seq1))) return seq1; 00593 if((seq2 = del_seq_find_replace_recurs(scene, seq->seq2))) return seq2; 00594 if((seq3 = del_seq_find_replace_recurs(scene, seq->seq3))) return seq3; 00595 else return NULL; 00596 } 00597 else 00598 return seq; 00599 } 00600 00601 static void recurs_del_seq_flag(Scene *scene, ListBase *lb, short flag, short deleteall) 00602 { 00603 Sequence *seq, *seqn; 00604 Sequence *last_seq = seq_active_get(scene); 00605 00606 seq= lb->first; 00607 while(seq) { 00608 seqn= seq->next; 00609 if((seq->flag & flag) || deleteall) { 00610 BLI_remlink(lb, seq); 00611 if(seq==last_seq) seq_active_set(scene, NULL); 00612 if(seq->type==SEQ_META) recurs_del_seq_flag(scene, &seq->seqbase, flag, 1); 00613 seq_free_sequence(scene, seq); 00614 } 00615 seq= seqn; 00616 } 00617 } 00618 00619 00620 static Sequence *cut_seq_hard(Scene *scene, Sequence * seq, int cutframe) 00621 { 00622 TransSeq ts; 00623 Sequence *seqn = NULL; 00624 int skip_dup = FALSE; 00625 00626 /* backup values */ 00627 ts.start= seq->start; 00628 ts.machine= seq->machine; 00629 ts.startstill= seq->startstill; 00630 ts.endstill= seq->endstill; 00631 ts.startdisp= seq->startdisp; 00632 ts.enddisp= seq->enddisp; 00633 ts.startofs= seq->startofs; 00634 ts.endofs= seq->endofs; 00635 ts.anim_startofs= seq->anim_startofs; 00636 ts.anim_endofs= seq->anim_endofs; 00637 ts.len= seq->len; 00638 00639 /* First Strip! */ 00640 /* strips with extended stillfames before */ 00641 00642 if ((seq->startstill) && (cutframe <seq->start)) { 00643 /* don't do funny things with METAs ... */ 00644 if (seq->type == SEQ_META) { 00645 skip_dup = TRUE; 00646 seq->startstill = seq->start - cutframe; 00647 } else { 00648 seq->start= cutframe -1; 00649 seq->startstill= cutframe -seq->startdisp -1; 00650 seq->anim_endofs += seq->len - 1; 00651 seq->endstill= 0; 00652 } 00653 } 00654 /* normal strip */ 00655 else if ((cutframe >=seq->start)&&(cutframe <=(seq->start+seq->len))) { 00656 seq->endofs = 0; 00657 seq->endstill = 0; 00658 seq->anim_endofs += (seq->start+seq->len) - cutframe; 00659 } 00660 /* strips with extended stillframes after */ 00661 else if (((seq->start+seq->len) < cutframe) && (seq->endstill)) { 00662 seq->endstill -= seq->enddisp - cutframe; 00663 /* don't do funny things with METAs ... */ 00664 if (seq->type == SEQ_META) { 00665 skip_dup = TRUE; 00666 } 00667 } 00668 00669 reload_sequence_new_file(scene, seq, FALSE); 00670 calc_sequence(scene, seq); 00671 new_tstripdata(seq); 00672 00673 if (!skip_dup) { 00674 /* Duplicate AFTER the first change */ 00675 seqn = seq_dupli_recursive(scene, NULL, seq, SEQ_DUPE_UNIQUE_NAME | SEQ_DUPE_ANIM); 00676 } 00677 00678 if (seqn) { 00679 seqn->flag |= SELECT; 00680 00681 /* Second Strip! */ 00682 /* strips with extended stillframes before */ 00683 if ((seqn->startstill) && (cutframe == seqn->start + 1)) { 00684 seqn->start = ts.start; 00685 seqn->startstill= ts.start- cutframe; 00686 seqn->anim_endofs = ts.anim_endofs; 00687 seqn->endstill = ts.endstill; 00688 } 00689 00690 /* normal strip */ 00691 else if ((cutframe>=seqn->start)&&(cutframe<=(seqn->start+seqn->len))) { 00692 seqn->start = cutframe; 00693 seqn->startstill = 0; 00694 seqn->startofs = 0; 00695 seqn->endofs = ts.endofs; 00696 seqn->anim_startofs += cutframe - ts.start; 00697 seqn->anim_endofs = ts.anim_endofs; 00698 seqn->endstill = ts.endstill; 00699 } 00700 00701 /* strips with extended stillframes after */ 00702 else if (((seqn->start+seqn->len) < cutframe) && (seqn->endstill)) { 00703 seqn->start = cutframe; 00704 seqn->startofs = 0; 00705 seqn->anim_startofs += ts.len-1; 00706 seqn->endstill = ts.enddisp - cutframe -1; 00707 seqn->startstill = 0; 00708 } 00709 00710 reload_sequence_new_file(scene, seqn, FALSE); 00711 calc_sequence(scene, seqn); 00712 new_tstripdata(seqn); 00713 } 00714 return seqn; 00715 } 00716 00717 static Sequence *cut_seq_soft(Scene *scene, Sequence * seq, int cutframe) 00718 { 00719 TransSeq ts; 00720 Sequence *seqn = NULL; 00721 int skip_dup = FALSE; 00722 00723 /* backup values */ 00724 ts.start= seq->start; 00725 ts.machine= seq->machine; 00726 ts.startstill= seq->startstill; 00727 ts.endstill= seq->endstill; 00728 ts.startdisp= seq->startdisp; 00729 ts.enddisp= seq->enddisp; 00730 ts.startofs= seq->startofs; 00731 ts.endofs= seq->endofs; 00732 ts.anim_startofs= seq->anim_startofs; 00733 ts.anim_endofs= seq->anim_endofs; 00734 ts.len= seq->len; 00735 00736 /* First Strip! */ 00737 /* strips with extended stillfames before */ 00738 00739 if ((seq->startstill) && (cutframe <seq->start)) { 00740 /* don't do funny things with METAs ... */ 00741 if (seq->type == SEQ_META) { 00742 skip_dup = TRUE; 00743 seq->startstill = seq->start - cutframe; 00744 } else { 00745 seq->start= cutframe -1; 00746 seq->startstill= cutframe -seq->startdisp -1; 00747 seq->endofs = seq->len - 1; 00748 seq->endstill= 0; 00749 } 00750 } 00751 /* normal strip */ 00752 else if ((cutframe >=seq->start)&&(cutframe <=(seq->start+seq->len))) { 00753 seq->endofs = (seq->start+seq->len) - cutframe; 00754 } 00755 /* strips with extended stillframes after */ 00756 else if (((seq->start+seq->len) < cutframe) && (seq->endstill)) { 00757 seq->endstill -= seq->enddisp - cutframe; 00758 /* don't do funny things with METAs ... */ 00759 if (seq->type == SEQ_META) { 00760 skip_dup = TRUE; 00761 } 00762 } 00763 00764 calc_sequence(scene, seq); 00765 new_tstripdata(seq); 00766 00767 if (!skip_dup) { 00768 /* Duplicate AFTER the first change */ 00769 seqn = seq_dupli_recursive(scene, NULL, seq, SEQ_DUPE_UNIQUE_NAME | SEQ_DUPE_ANIM); 00770 } 00771 00772 if (seqn) { 00773 seqn->flag |= SELECT; 00774 00775 /* Second Strip! */ 00776 /* strips with extended stillframes before */ 00777 if ((seqn->startstill) && (cutframe == seqn->start + 1)) { 00778 seqn->start = ts.start; 00779 seqn->startstill= ts.start- cutframe; 00780 seqn->endofs = ts.endofs; 00781 seqn->endstill = ts.endstill; 00782 } 00783 00784 /* normal strip */ 00785 else if ((cutframe>=seqn->start)&&(cutframe<=(seqn->start+seqn->len))) { 00786 seqn->startstill = 0; 00787 seqn->startofs = cutframe - ts.start; 00788 seqn->endofs = ts.endofs; 00789 seqn->endstill = ts.endstill; 00790 } 00791 00792 /* strips with extended stillframes after */ 00793 else if (((seqn->start+seqn->len) < cutframe) && (seqn->endstill)) { 00794 seqn->start = cutframe - ts.len +1; 00795 seqn->startofs = ts.len-1; 00796 seqn->endstill = ts.enddisp - cutframe -1; 00797 seqn->startstill = 0; 00798 } 00799 00800 calc_sequence(scene, seqn); 00801 new_tstripdata(seqn); 00802 } 00803 return seqn; 00804 } 00805 00806 00807 /* like duplicate, but only duplicate and cut overlapping strips, 00808 * strips to the left of the cutframe are ignored and strips to the right are moved into the new list */ 00809 static int cut_seq_list(Scene *scene, ListBase *old, ListBase *new, int cutframe, 00810 Sequence * (*cut_seq)(Scene *, Sequence *, int)) 00811 { 00812 int did_something = FALSE; 00813 Sequence *seq, *seq_next_iter; 00814 00815 seq= old->first; 00816 00817 while(seq) { 00818 seq_next_iter = seq->next; /* we need this because we may remove seq */ 00819 00820 seq->tmp= NULL; 00821 if(seq->flag & SELECT) { 00822 if(cutframe > seq->startdisp && 00823 cutframe < seq->enddisp) { 00824 Sequence * seqn = cut_seq(scene, seq, cutframe); 00825 if (seqn) { 00826 BLI_addtail(new, seqn); 00827 } 00828 did_something = TRUE; 00829 } else if (seq->enddisp <= cutframe) { 00830 /* do nothing */ 00831 } else if (seq->startdisp >= cutframe) { 00832 /* move into new list */ 00833 BLI_remlink(old, seq); 00834 BLI_addtail(new, seq); 00835 } 00836 } 00837 seq = seq_next_iter; 00838 } 00839 return did_something; 00840 } 00841 00842 static int insert_gap(Scene *scene, int gap, int cfra) 00843 { 00844 Sequence *seq; 00845 Editing *ed= seq_give_editing(scene, FALSE); 00846 int done=0; 00847 00848 /* all strips >= cfra are shifted */ 00849 00850 if(ed==NULL) return 0; 00851 00852 SEQP_BEGIN(ed, seq) { 00853 if(seq->startdisp >= cfra) { 00854 seq->start+= gap; 00855 calc_sequence(scene, seq); 00856 done= 1; 00857 } 00858 } 00859 SEQ_END 00860 00861 return done; 00862 } 00863 00864 static void UNUSED_FUNCTION(touch_seq_files)(Scene *scene) 00865 { 00866 Sequence *seq; 00867 Editing *ed= seq_give_editing(scene, FALSE); 00868 char str[256]; 00869 00870 /* touch all strips with movies */ 00871 00872 if(ed==NULL) return; 00873 00874 if(okee("Touch and print selected movies")==0) return; 00875 00876 WM_cursor_wait(1); 00877 00878 SEQP_BEGIN(ed, seq) { 00879 if(seq->flag & SELECT) { 00880 if(seq->type==SEQ_MOVIE) { 00881 if(seq->strip && seq->strip->stripdata) { 00882 BLI_make_file_string(G.main->name, str, seq->strip->dir, seq->strip->stripdata->name); 00883 BLI_file_touch(seq->name); 00884 } 00885 } 00886 00887 } 00888 } 00889 SEQ_END 00890 00891 WM_cursor_wait(0); 00892 } 00893 00894 /* 00895 static void set_filter_seq(Scene *scene) 00896 { 00897 Sequence *seq; 00898 Editing *ed= seq_give_editing(scene, FALSE); 00899 00900 00901 if(ed==NULL) return; 00902 00903 if(okee("Set Deinterlace")==0) return; 00904 00905 SEQP_BEGIN(ed, seq) { 00906 if(seq->flag & SELECT) { 00907 if(seq->type==SEQ_MOVIE) { 00908 seq->flag |= SEQ_FILTERY; 00909 reload_sequence_new_file(scene, seq, FALSE); 00910 calc_sequence(scene, seq); 00911 } 00912 00913 } 00914 } 00915 SEQ_END 00916 } 00917 */ 00918 00919 static void UNUSED_FUNCTION(seq_remap_paths)(Scene *scene) 00920 { 00921 Sequence *seq, *last_seq = seq_active_get(scene); 00922 Editing *ed= seq_give_editing(scene, FALSE); 00923 char from[FILE_MAX], to[FILE_MAX], stripped[FILE_MAX]; 00924 00925 00926 if(last_seq==NULL) 00927 return; 00928 00929 BLI_strncpy(from, last_seq->strip->dir, sizeof(from)); 00930 // XXX if (0==sbutton(from, 0, sizeof(from)-1, "From: ")) 00931 // return; 00932 00933 BLI_strncpy(to, from, sizeof(to)); 00934 // XXX if (0==sbutton(to, 0, sizeof(to)-1, "To: ")) 00935 // return; 00936 00937 if (strcmp(to, from)==0) 00938 return; 00939 00940 SEQP_BEGIN(ed, seq) { 00941 if(seq->flag & SELECT) { 00942 if(strncmp(seq->strip->dir, from, strlen(from))==0) { 00943 printf("found %s\n", seq->strip->dir); 00944 00945 /* strip off the beginning */ 00946 stripped[0]= 0; 00947 BLI_strncpy(stripped, seq->strip->dir + strlen(from), FILE_MAX); 00948 00949 /* new path */ 00950 BLI_snprintf(seq->strip->dir, sizeof(seq->strip->dir), "%s%s", to, stripped); 00951 printf("new %s\n", seq->strip->dir); 00952 } 00953 } 00954 } 00955 SEQ_END 00956 00957 } 00958 00959 00960 static void UNUSED_FUNCTION(no_gaps)(Scene *scene) 00961 { 00962 Editing *ed= seq_give_editing(scene, FALSE); 00963 int cfra, first= 0, done; 00964 00965 00966 if(ed==NULL) return; 00967 00968 for(cfra= CFRA; cfra<=EFRA; cfra++) { 00969 if(first==0) { 00970 if( evaluate_seq_frame(scene, cfra) ) first= 1; 00971 } 00972 else { 00973 done= 1; 00974 while( evaluate_seq_frame(scene, cfra) == 0) { 00975 done= insert_gap(scene, -1, cfra); 00976 if(done==0) break; 00977 } 00978 if(done==0) break; 00979 } 00980 } 00981 00982 } 00983 00984 #if 0 00985 static int seq_get_snaplimit(View2D *v2d) 00986 { 00987 /* fake mouse coords to get the snap value 00988 a bit lazy but its only done once pre transform */ 00989 float xmouse, ymouse, x; 00990 int mval[2] = {24, 0}; /* 24 screen px snap */ 00991 00992 UI_view2d_region_to_view(v2d, mval[0], mval[1], &xmouse, &ymouse); 00993 x = xmouse; 00994 mval[0] = 0; 00995 UI_view2d_region_to_view(v2d, mval[0], mval[1], &xmouse, &ymouse); 00996 return (int)(x - xmouse); 00997 } 00998 #endif 00999 01000 /* Operator functions */ 01001 int sequencer_edit_poll(bContext *C) 01002 { 01003 return (seq_give_editing(CTX_data_scene(C), FALSE) != NULL); 01004 } 01005 01006 int sequencer_strip_poll(bContext *C) 01007 { 01008 Editing *ed; 01009 return (((ed= seq_give_editing(CTX_data_scene(C), FALSE)) != NULL) && (ed->act_seq != NULL)); 01010 } 01011 01012 int sequencer_strip_has_path_poll(bContext *C) 01013 { 01014 Editing *ed; 01015 Sequence *seq; 01016 return (((ed= seq_give_editing(CTX_data_scene(C), FALSE)) != NULL) && ((seq= ed->act_seq) != NULL) && (SEQ_HAS_PATH(seq))); 01017 } 01018 01019 int sequencer_view_poll(bContext *C) 01020 { 01021 SpaceSeq *sseq= CTX_wm_space_seq(C); 01022 Editing *ed= seq_give_editing(CTX_data_scene(C), FALSE); 01023 if (ed && sseq && (sseq->mainb == SEQ_DRAW_IMG_IMBUF)) 01024 return 1; 01025 01026 return 0; 01027 } 01028 01029 /* snap operator*/ 01030 static int sequencer_snap_exec(bContext *C, wmOperator *op) 01031 { 01032 Scene *scene= CTX_data_scene(C); 01033 01034 Editing *ed= seq_give_editing(scene, FALSE); 01035 Sequence *seq; 01036 int snap_frame; 01037 01038 snap_frame= RNA_int_get(op->ptr, "frame"); 01039 01040 /* also check metas */ 01041 for(seq= ed->seqbasep->first; seq; seq= seq->next) { 01042 if (seq->flag & SELECT && !(seq->depth==0 && seq->flag & SEQ_LOCK) && 01043 seq_tx_test(seq)) { 01044 if((seq->flag & (SEQ_LEFTSEL+SEQ_RIGHTSEL))==0) { 01045 /* simple but no anim update */ 01046 /* seq->start= snap_frame-seq->startofs+seq->startstill; */ 01047 01048 seq_translate(scene, seq, (snap_frame-seq->startofs+seq->startstill) - seq->start); 01049 } else { 01050 if(seq->flag & SEQ_LEFTSEL) { 01051 seq_tx_set_final_left(seq, snap_frame); 01052 } else { /* SEQ_RIGHTSEL */ 01053 seq_tx_set_final_right(seq, snap_frame); 01054 } 01055 seq_tx_handle_xlimits(seq, seq->flag & SEQ_LEFTSEL, seq->flag & SEQ_RIGHTSEL); 01056 } 01057 calc_sequence(scene, seq); 01058 } 01059 } 01060 01061 /* test for effects and overlap 01062 * dont use SEQP_BEGIN since that would be recursive */ 01063 for(seq= ed->seqbasep->first; seq; seq= seq->next) { 01064 if(seq->flag & SELECT && !(seq->depth==0 && seq->flag & SEQ_LOCK)) { 01065 seq->flag &= ~SEQ_OVERLAP; 01066 if( seq_test_overlap(ed->seqbasep, seq) ) { 01067 shuffle_seq(ed->seqbasep, seq, scene); 01068 } 01069 } 01070 else if(seq->type & SEQ_EFFECT) { 01071 if(seq->seq1 && (seq->seq1->flag & SELECT)) 01072 calc_sequence(scene, seq); 01073 else if(seq->seq2 && (seq->seq2->flag & SELECT)) 01074 calc_sequence(scene, seq); 01075 else if(seq->seq3 && (seq->seq3->flag & SELECT)) 01076 calc_sequence(scene, seq); 01077 } 01078 } 01079 01080 /* as last: */ 01081 sort_seq(scene); 01082 01083 WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene); 01084 01085 return OPERATOR_FINISHED; 01086 } 01087 01088 static int sequencer_snap_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) 01089 { 01090 Scene *scene = CTX_data_scene(C); 01091 01092 int snap_frame; 01093 01094 snap_frame= CFRA; 01095 01096 RNA_int_set(op->ptr, "frame", snap_frame); 01097 return sequencer_snap_exec(C, op); 01098 } 01099 01100 void SEQUENCER_OT_snap(struct wmOperatorType *ot) 01101 { 01102 /* identifiers */ 01103 ot->name= "Snap strips"; 01104 ot->idname= "SEQUENCER_OT_snap"; 01105 ot->description="Frame where selected strips will be snapped"; 01106 01107 /* api callbacks */ 01108 ot->invoke= sequencer_snap_invoke; 01109 ot->exec= sequencer_snap_exec; 01110 ot->poll= sequencer_edit_poll; 01111 01112 /* flags */ 01113 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01114 01115 RNA_def_int(ot->srna, "frame", 0, INT_MIN, INT_MAX, "Frame", "Frame where selected strips will be snapped", INT_MIN, INT_MAX); 01116 } 01117 01118 /* mute operator */ 01119 static int sequencer_mute_exec(bContext *C, wmOperator *op) 01120 { 01121 Scene *scene= CTX_data_scene(C); 01122 Editing *ed= seq_give_editing(scene, FALSE); 01123 Sequence *seq; 01124 int selected; 01125 01126 selected= !RNA_boolean_get(op->ptr, "unselected"); 01127 01128 for(seq= ed->seqbasep->first; seq; seq= seq->next) { 01129 if ((seq->flag & SEQ_LOCK)==0) { 01130 if(selected){ /* mute unselected */ 01131 if(seq->flag & SELECT) 01132 seq->flag |= SEQ_MUTE; 01133 } 01134 else { 01135 if((seq->flag & SELECT)==0) 01136 seq->flag |= SEQ_MUTE; 01137 } 01138 } 01139 } 01140 01141 seq_update_muting(ed); 01142 WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene); 01143 01144 return OPERATOR_FINISHED; 01145 } 01146 01147 void SEQUENCER_OT_mute(struct wmOperatorType *ot) 01148 { 01149 /* identifiers */ 01150 ot->name= "Mute Strips"; 01151 ot->idname= "SEQUENCER_OT_mute"; 01152 ot->description="Mute selected strips"; 01153 01154 /* api callbacks */ 01155 ot->exec= sequencer_mute_exec; 01156 ot->poll= sequencer_edit_poll; 01157 01158 /* flags */ 01159 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01160 01161 RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Mute unselected rather than selected strips"); 01162 } 01163 01164 01165 /* unmute operator */ 01166 static int sequencer_unmute_exec(bContext *C, wmOperator *op) 01167 { 01168 Scene *scene= CTX_data_scene(C); 01169 Editing *ed= seq_give_editing(scene, FALSE); 01170 Sequence *seq; 01171 int selected; 01172 01173 selected= !RNA_boolean_get(op->ptr, "unselected"); 01174 01175 for(seq= ed->seqbasep->first; seq; seq= seq->next) { 01176 if ((seq->flag & SEQ_LOCK)==0) { 01177 if(selected){ /* unmute unselected */ 01178 if(seq->flag & SELECT) 01179 seq->flag &= ~SEQ_MUTE; 01180 } 01181 else { 01182 if((seq->flag & SELECT)==0) 01183 seq->flag &= ~SEQ_MUTE; 01184 } 01185 } 01186 } 01187 01188 seq_update_muting(ed); 01189 WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene); 01190 01191 return OPERATOR_FINISHED; 01192 } 01193 01194 void SEQUENCER_OT_unmute(struct wmOperatorType *ot) 01195 { 01196 /* identifiers */ 01197 ot->name= "Un-Mute Strips"; 01198 ot->idname= "SEQUENCER_OT_unmute"; 01199 ot->description="Un-Mute unselected rather than selected strips"; 01200 01201 /* api callbacks */ 01202 ot->exec= sequencer_unmute_exec; 01203 ot->poll= sequencer_edit_poll; 01204 01205 /* flags */ 01206 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01207 01208 RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "UnMute unselected rather than selected strips"); 01209 } 01210 01211 01212 /* lock operator */ 01213 static int sequencer_lock_exec(bContext *C, wmOperator *UNUSED(op)) 01214 { 01215 Scene *scene= CTX_data_scene(C); 01216 Editing *ed= seq_give_editing(scene, FALSE); 01217 Sequence *seq; 01218 01219 for(seq= ed->seqbasep->first; seq; seq= seq->next) { 01220 if (seq->flag & SELECT) { 01221 seq->flag |= SEQ_LOCK; 01222 } 01223 } 01224 01225 WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene); 01226 01227 return OPERATOR_FINISHED; 01228 } 01229 01230 void SEQUENCER_OT_lock(struct wmOperatorType *ot) 01231 { 01232 /* identifiers */ 01233 ot->name= "Lock Strips"; 01234 ot->idname= "SEQUENCER_OT_lock"; 01235 ot->description="Lock the active strip so that it can't be transformed"; 01236 01237 /* api callbacks */ 01238 ot->exec= sequencer_lock_exec; 01239 ot->poll= sequencer_edit_poll; 01240 01241 /* flags */ 01242 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01243 } 01244 01245 /* unlock operator */ 01246 static int sequencer_unlock_exec(bContext *C, wmOperator *UNUSED(op)) 01247 { 01248 Scene *scene= CTX_data_scene(C); 01249 Editing *ed= seq_give_editing(scene, FALSE); 01250 Sequence *seq; 01251 01252 for(seq= ed->seqbasep->first; seq; seq= seq->next) { 01253 if (seq->flag & SELECT) { 01254 seq->flag &= ~SEQ_LOCK; 01255 } 01256 } 01257 01258 WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene); 01259 01260 return OPERATOR_FINISHED; 01261 } 01262 01263 void SEQUENCER_OT_unlock(struct wmOperatorType *ot) 01264 { 01265 /* identifiers */ 01266 ot->name= "UnLock Strips"; 01267 ot->idname= "SEQUENCER_OT_unlock"; 01268 ot->description="Unlock the active strip so that it can't be transformed"; 01269 01270 /* api callbacks */ 01271 ot->exec= sequencer_unlock_exec; 01272 ot->poll= sequencer_edit_poll; 01273 01274 /* flags */ 01275 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01276 } 01277 01278 /* reload operator */ 01279 static int sequencer_reload_exec(bContext *C, wmOperator *UNUSED(op)) 01280 { 01281 Scene *scene= CTX_data_scene(C); 01282 Editing *ed= seq_give_editing(scene, FALSE); 01283 Sequence *seq; 01284 01285 for(seq= ed->seqbasep->first; seq; seq= seq->next) { 01286 if(seq->flag & SELECT) { 01287 update_changed_seq_and_deps(scene, seq, 0, 1); 01288 } 01289 } 01290 01291 WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene); 01292 01293 return OPERATOR_FINISHED; 01294 } 01295 01296 void SEQUENCER_OT_reload(struct wmOperatorType *ot) 01297 { 01298 /* identifiers */ 01299 ot->name= "Reload Strips"; 01300 ot->idname= "SEQUENCER_OT_reload"; 01301 ot->description="Reload strips in the sequencer"; 01302 01303 /* api callbacks */ 01304 ot->exec= sequencer_reload_exec; 01305 ot->poll= sequencer_edit_poll; 01306 01307 /* flags */ 01308 ot->flag= OPTYPE_REGISTER; /* no undo, the data changed is stored outside 'main' */ 01309 } 01310 01311 /* reload operator */ 01312 static int sequencer_refresh_all_exec(bContext *C, wmOperator *UNUSED(op)) 01313 { 01314 Scene *scene= CTX_data_scene(C); 01315 Editing *ed= seq_give_editing(scene, FALSE); 01316 01317 free_imbuf_seq(scene, &ed->seqbase, FALSE, FALSE); 01318 01319 WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene); 01320 01321 return OPERATOR_FINISHED; 01322 } 01323 01324 void SEQUENCER_OT_refresh_all(struct wmOperatorType *ot) 01325 { 01326 /* identifiers */ 01327 ot->name= "Refresh Sequencer"; 01328 ot->idname= "SEQUENCER_OT_refresh_all"; 01329 ot->description="Refresh the sequencer editor"; 01330 01331 /* api callbacks */ 01332 ot->exec= sequencer_refresh_all_exec; 01333 ot->poll= sequencer_edit_poll; 01334 } 01335 01336 static int sequencer_reassign_inputs_exec(bContext *C, wmOperator *op) 01337 { 01338 Scene *scene= CTX_data_scene(C); 01339 Sequence *seq1, *seq2, *seq3, *last_seq = seq_active_get(scene); 01340 const char *error_msg; 01341 01342 if(!seq_effect_find_selected(scene, last_seq, last_seq->type, &seq1, &seq2, &seq3, &error_msg)) { 01343 BKE_report(op->reports, RPT_ERROR, error_msg); 01344 return OPERATOR_CANCELLED; 01345 } 01346 /* see reassigning would create a cycle */ 01347 if( seq_is_predecessor(seq1, last_seq) || 01348 seq_is_predecessor(seq2, last_seq) || 01349 seq_is_predecessor(seq3, last_seq) 01350 ) { 01351 BKE_report(op->reports, RPT_ERROR, "Can't reassign inputs: no cycles allowed"); 01352 return OPERATOR_CANCELLED; 01353 } 01354 01355 last_seq->seq1 = seq1; 01356 last_seq->seq2 = seq2; 01357 last_seq->seq3 = seq3; 01358 01359 update_changed_seq_and_deps(scene, last_seq, 1, 1); 01360 01361 WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene); 01362 01363 return OPERATOR_FINISHED; 01364 } 01365 01366 static int sequencer_effect_poll(bContext *C) 01367 { 01368 Scene *scene= CTX_data_scene(C); 01369 Editing *ed= seq_give_editing(scene, FALSE); 01370 01371 if(ed) { 01372 Sequence *last_seq= seq_active_get(scene); 01373 if(last_seq && (last_seq->type & SEQ_EFFECT)) { 01374 return 1; 01375 } 01376 } 01377 01378 return 0; 01379 } 01380 01381 void SEQUENCER_OT_reassign_inputs(struct wmOperatorType *ot) 01382 { 01383 /* identifiers */ 01384 ot->name= "Reassign Inputs"; 01385 ot->idname= "SEQUENCER_OT_reassign_inputs"; 01386 ot->description="Reassign the inputs for the effect strip"; 01387 01388 /* api callbacks */ 01389 ot->exec= sequencer_reassign_inputs_exec; 01390 ot->poll= sequencer_effect_poll; 01391 01392 /* flags */ 01393 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01394 } 01395 01396 01397 static int sequencer_swap_inputs_exec(bContext *C, wmOperator *op) 01398 { 01399 Scene *scene= CTX_data_scene(C); 01400 Sequence *seq, *last_seq = seq_active_get(scene); 01401 01402 if(last_seq->seq1==NULL || last_seq->seq2 == NULL) { 01403 BKE_report(op->reports, RPT_ERROR, "No valid inputs to swap"); 01404 return OPERATOR_CANCELLED; 01405 } 01406 01407 seq = last_seq->seq1; 01408 last_seq->seq1 = last_seq->seq2; 01409 last_seq->seq2 = seq; 01410 01411 update_changed_seq_and_deps(scene, last_seq, 1, 1); 01412 01413 WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene); 01414 01415 return OPERATOR_FINISHED; 01416 } 01417 void SEQUENCER_OT_swap_inputs(struct wmOperatorType *ot) 01418 { 01419 /* identifiers */ 01420 ot->name= "Swap Inputs"; 01421 ot->idname= "SEQUENCER_OT_swap_inputs"; 01422 ot->description="Swap the first two inputs for the effect strip"; 01423 01424 /* api callbacks */ 01425 ot->exec= sequencer_swap_inputs_exec; 01426 ot->poll= sequencer_effect_poll; 01427 01428 /* flags */ 01429 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01430 } 01431 01432 01433 /* cut operator */ 01434 static EnumPropertyItem prop_cut_types[] = { 01435 {SEQ_CUT_SOFT, "SOFT", 0, "Soft", ""}, 01436 {SEQ_CUT_HARD, "HARD", 0, "Hard", ""}, 01437 {0, NULL, 0, NULL, NULL} 01438 }; 01439 01440 static int sequencer_cut_exec(bContext *C, wmOperator *op) 01441 { 01442 Scene *scene= CTX_data_scene(C); 01443 Editing *ed= seq_give_editing(scene, FALSE); 01444 int cut_side, cut_hard, cut_frame; 01445 01446 ListBase newlist; 01447 int changed; 01448 01449 cut_frame= RNA_int_get(op->ptr, "frame"); 01450 cut_hard= RNA_enum_get(op->ptr, "type"); 01451 cut_side= RNA_enum_get(op->ptr, "side"); 01452 01453 newlist.first= newlist.last= NULL; 01454 01455 if (cut_hard==SEQ_CUT_HARD) { 01456 changed = cut_seq_list(scene, ed->seqbasep, &newlist, cut_frame, cut_seq_hard); 01457 } else { 01458 changed = cut_seq_list(scene, ed->seqbasep, &newlist, cut_frame, cut_seq_soft); 01459 } 01460 01461 if (newlist.first) { /* got new strips ? */ 01462 Sequence *seq; 01463 BLI_movelisttolist(ed->seqbasep, &newlist); 01464 01465 if (cut_side != SEQ_SIDE_BOTH) { 01466 SEQP_BEGIN(ed, seq) { 01467 if (cut_side==SEQ_SIDE_LEFT) { 01468 if ( seq->startdisp >= cut_frame ) { 01469 seq->flag &= ~SEQ_ALLSEL; 01470 } 01471 } else { 01472 if ( seq->enddisp <= cut_frame ) { 01473 seq->flag &= ~SEQ_ALLSEL; 01474 } 01475 } 01476 } 01477 SEQ_END; 01478 } 01479 /* as last: */ 01480 sort_seq(scene); 01481 } 01482 01483 if(changed) { 01484 WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene); 01485 return OPERATOR_FINISHED; 01486 } 01487 else { 01488 return OPERATOR_CANCELLED; 01489 } 01490 } 01491 01492 01493 static int sequencer_cut_invoke(bContext *C, wmOperator *op, wmEvent *event) 01494 { 01495 Scene *scene = CTX_data_scene(C); 01496 View2D *v2d= UI_view2d_fromcontext(C); 01497 01498 int cut_side= SEQ_SIDE_BOTH; 01499 int cut_frame= CFRA; 01500 01501 if (ED_operator_sequencer_active(C) && v2d) 01502 cut_side= mouse_frame_side(v2d, event->mval[0], cut_frame); 01503 01504 RNA_int_set(op->ptr, "frame", cut_frame); 01505 RNA_enum_set(op->ptr, "side", cut_side); 01506 /*RNA_enum_set(op->ptr, "type", cut_hard); */ /*This type is set from the key shortcut */ 01507 01508 return sequencer_cut_exec(C, op); 01509 } 01510 01511 01512 void SEQUENCER_OT_cut(struct wmOperatorType *ot) 01513 { 01514 /* identifiers */ 01515 ot->name= "Cut Strips"; 01516 ot->idname= "SEQUENCER_OT_cut"; 01517 ot->description="Cut the selected strips"; 01518 01519 /* api callbacks */ 01520 ot->invoke= sequencer_cut_invoke; 01521 ot->exec= sequencer_cut_exec; 01522 ot->poll= sequencer_edit_poll; 01523 01524 /* flags */ 01525 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01526 01527 RNA_def_int(ot->srna, "frame", 0, INT_MIN, INT_MAX, "Frame", "Frame where selected strips will be cut", INT_MIN, INT_MAX); 01528 RNA_def_enum(ot->srna, "type", prop_cut_types, SEQ_CUT_SOFT, "Type", "The type of cut operation to perform on strips"); 01529 RNA_def_enum(ot->srna, "side", prop_side_types, SEQ_SIDE_BOTH, "Side", "The side that remains selected after cutting"); 01530 } 01531 01532 /* duplicate operator */ 01533 static int apply_unique_name_cb(Sequence *seq, void *arg_pt) 01534 { 01535 Scene *scene= (Scene *)arg_pt; 01536 char name[sizeof(seq->name)-2]; 01537 01538 strcpy(name, seq->name+2); 01539 seqbase_unique_name_recursive(&scene->ed->seqbase, seq); 01540 seq_dupe_animdata(scene, name, seq->name+2); 01541 return 1; 01542 01543 } 01544 01545 static int sequencer_add_duplicate_exec(bContext *C, wmOperator *UNUSED(op)) 01546 { 01547 Scene *scene= CTX_data_scene(C); 01548 Editing *ed= seq_give_editing(scene, FALSE); 01549 01550 ListBase nseqbase= {NULL, NULL}; 01551 01552 if(ed==NULL) 01553 return OPERATOR_CANCELLED; 01554 01555 seqbase_dupli_recursive(scene, NULL, &nseqbase, ed->seqbasep, SEQ_DUPE_CONTEXT); 01556 01557 if(nseqbase.first) { 01558 Sequence * seq= nseqbase.first; 01559 /* rely on the nseqbase list being added at the end */ 01560 BLI_movelisttolist(ed->seqbasep, &nseqbase); 01561 01562 for( ; seq; seq= seq->next) 01563 seq_recursive_apply(seq, apply_unique_name_cb, scene); 01564 01565 WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene); 01566 return OPERATOR_FINISHED; 01567 } 01568 01569 return OPERATOR_CANCELLED; 01570 } 01571 01572 static int sequencer_add_duplicate_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) 01573 { 01574 sequencer_add_duplicate_exec(C, op); 01575 01576 RNA_enum_set(op->ptr, "mode", TFM_TRANSLATION); 01577 WM_operator_name_call(C, "TRANSFORM_OT_transform", WM_OP_INVOKE_REGION_WIN, op->ptr); 01578 01579 return OPERATOR_FINISHED; 01580 } 01581 01582 void SEQUENCER_OT_duplicate(wmOperatorType *ot) 01583 { 01584 /* identifiers */ 01585 ot->name= "Duplicate Strips"; 01586 ot->idname= "SEQUENCER_OT_duplicate"; 01587 ot->description="Duplicate the selected strips"; 01588 01589 /* api callbacks */ 01590 ot->invoke= sequencer_add_duplicate_invoke; 01591 ot->exec= sequencer_add_duplicate_exec; 01592 ot->poll= ED_operator_sequencer_active; 01593 01594 /* flags */ 01595 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01596 01597 /* to give to transform */ 01598 RNA_def_enum(ot->srna, "mode", transform_mode_types, TFM_TRANSLATION, "Mode", ""); 01599 } 01600 01601 /* delete operator */ 01602 static int sequencer_delete_exec(bContext *C, wmOperator *UNUSED(op)) 01603 { 01604 Scene *scene= CTX_data_scene(C); 01605 Editing *ed= seq_give_editing(scene, FALSE); 01606 Sequence *seq; 01607 MetaStack *ms; 01608 int nothingSelected = TRUE; 01609 01610 seq=seq_active_get(scene); 01611 if (seq && seq->flag & SELECT) { /* avoid a loop since this is likely to be selected */ 01612 nothingSelected = FALSE; 01613 } else { 01614 for (seq = ed->seqbasep->first; seq; seq = seq->next) { 01615 if (seq->flag & SELECT) { 01616 nothingSelected = FALSE; 01617 break; 01618 } 01619 } 01620 } 01621 01622 if (nothingSelected) 01623 return OPERATOR_FINISHED; 01624 01625 /* for effects, try to find a replacement input */ 01626 for(seq=ed->seqbasep->first; seq; seq=seq->next) 01627 if((seq->type & SEQ_EFFECT) && !(seq->flag & SELECT)) 01628 del_seq_find_replace_recurs(scene, seq); 01629 01630 /* delete all selected strips */ 01631 recurs_del_seq_flag(scene, ed->seqbasep, SELECT, 0); 01632 01633 /* updates lengths etc */ 01634 seq= ed->seqbasep->first; 01635 while(seq) { 01636 calc_sequence(scene, seq); 01637 seq= seq->next; 01638 } 01639 01640 /* free parent metas */ 01641 ms= ed->metastack.last; 01642 while(ms) { 01643 ms->parseq->strip->len= 0; /* force new alloc */ 01644 calc_sequence(scene, ms->parseq); 01645 ms= ms->prev; 01646 } 01647 01648 WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene); 01649 01650 return OPERATOR_FINISHED; 01651 } 01652 01653 01654 void SEQUENCER_OT_delete(wmOperatorType *ot) 01655 { 01656 01657 /* identifiers */ 01658 ot->name= "Erase Strips"; 01659 ot->idname= "SEQUENCER_OT_delete"; 01660 ot->description="Erase selected strips from the sequencer"; 01661 01662 /* api callbacks */ 01663 ot->invoke= WM_operator_confirm; 01664 ot->exec= sequencer_delete_exec; 01665 ot->poll= sequencer_edit_poll; 01666 01667 /* flags */ 01668 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01669 } 01670 01671 01672 /* offset clear operator */ 01673 static int sequencer_offset_clear_exec(bContext *C, wmOperator *UNUSED(op)) 01674 { 01675 Scene *scene= CTX_data_scene(C); 01676 Editing *ed= seq_give_editing(scene, FALSE); 01677 Sequence *seq; 01678 01679 /* for effects, try to find a replacement input */ 01680 for(seq=ed->seqbasep->first; seq; seq=seq->next) { 01681 if((seq->type & SEQ_EFFECT)==0 && (seq->flag & SELECT)) { 01682 seq->startofs= seq->endofs= seq->startstill= seq->endstill= 0; 01683 } 01684 } 01685 01686 /* updates lengths etc */ 01687 seq= ed->seqbasep->first; 01688 while(seq) { 01689 calc_sequence(scene, seq); 01690 seq= seq->next; 01691 } 01692 01693 for(seq=ed->seqbasep->first; seq; seq=seq->next) { 01694 if((seq->type & SEQ_EFFECT)==0 && (seq->flag & SELECT)) { 01695 if(seq_test_overlap(ed->seqbasep, seq)) { 01696 shuffle_seq(ed->seqbasep, seq, scene); 01697 } 01698 } 01699 } 01700 01701 WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene); 01702 01703 return OPERATOR_FINISHED; 01704 } 01705 01706 01707 void SEQUENCER_OT_offset_clear(wmOperatorType *ot) 01708 { 01709 01710 /* identifiers */ 01711 ot->name= "Clear Strip Offset"; 01712 ot->idname= "SEQUENCER_OT_offset_clear"; 01713 ot->description="Clear strip offsets from the start and end frames"; 01714 01715 /* api callbacks */ 01716 ot->exec= sequencer_offset_clear_exec; 01717 ot->poll= sequencer_edit_poll; 01718 01719 /* flags */ 01720 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01721 } 01722 01723 01724 /* separate_images operator */ 01725 static int sequencer_separate_images_exec(bContext *C, wmOperator *op) 01726 { 01727 Scene *scene= CTX_data_scene(C); 01728 Editing *ed= seq_give_editing(scene, FALSE); 01729 01730 Sequence *seq, *seq_new; 01731 Strip *strip_new; 01732 StripElem *se, *se_new; 01733 int start_ofs, cfra, frame_end; 01734 int step= RNA_int_get(op->ptr, "length"); 01735 01736 seq= ed->seqbasep->first; /* poll checks this is valid */ 01737 01738 while (seq) { 01739 if((seq->flag & SELECT) && (seq->type == SEQ_IMAGE) && (seq->len > 1)) { 01740 /* remove seq so overlap tests dont conflict, 01741 see seq_free_sequence below for the real free'ing */ 01742 BLI_remlink(ed->seqbasep, seq); 01743 /* if(seq->ipo) seq->ipo->id.us--; */ 01744 /* XXX, remove fcurve and assign to split image strips */ 01745 01746 start_ofs = cfra = seq_tx_get_final_left(seq, 0); 01747 frame_end = seq_tx_get_final_right(seq, 0); 01748 01749 while (cfra < frame_end) { 01750 /* new seq */ 01751 se = give_stripelem(seq, cfra); 01752 01753 seq_new= seq_dupli_recursive(scene, scene, seq, SEQ_DUPE_UNIQUE_NAME); 01754 BLI_addtail(ed->seqbasep, seq_new); 01755 01756 seq_new->start= start_ofs; 01757 seq_new->type= SEQ_IMAGE; 01758 seq_new->len = 1; 01759 seq_new->endstill = step-1; 01760 01761 /* new strip */ 01762 strip_new= seq_new->strip; 01763 strip_new->len= 1; 01764 strip_new->us= 1; 01765 01766 /* new stripdata */ 01767 se_new= strip_new->stripdata; 01768 BLI_strncpy(se_new->name, se->name, sizeof(se_new->name)); 01769 calc_sequence(scene, seq_new); 01770 01771 if(step > 1) { 01772 seq_new->flag &= ~SEQ_OVERLAP; 01773 if (seq_test_overlap(ed->seqbasep, seq_new)) { 01774 shuffle_seq(ed->seqbasep, seq_new, scene); 01775 } 01776 } 01777 01778 /* XXX, COPY FCURVES */ 01779 01780 cfra++; 01781 start_ofs += step; 01782 } 01783 01784 seq_free_sequence(scene, seq); 01785 seq = seq->next; 01786 } else { 01787 seq = seq->next; 01788 } 01789 } 01790 01791 /* as last: */ 01792 sort_seq(scene); 01793 01794 WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene); 01795 01796 return OPERATOR_FINISHED; 01797 } 01798 01799 01800 void SEQUENCER_OT_images_separate(wmOperatorType *ot) 01801 { 01802 /* identifiers */ 01803 ot->name= "Separate Images"; 01804 ot->idname= "SEQUENCER_OT_images_separate"; 01805 ot->description="On image sequence strips, it returns a strip for each image"; 01806 01807 /* api callbacks */ 01808 ot->exec= sequencer_separate_images_exec; 01809 ot->poll= sequencer_edit_poll; 01810 01811 /* flags */ 01812 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01813 01814 RNA_def_int(ot->srna, "length", 1, 1, 1000, "Length", "Length of each frame", 1, INT_MAX); 01815 } 01816 01817 01818 /* META Operators */ 01819 01820 /* separate_meta_toggle operator */ 01821 static int sequencer_meta_toggle_exec(bContext *C, wmOperator *UNUSED(op)) 01822 { 01823 Scene *scene= CTX_data_scene(C); 01824 Editing *ed= seq_give_editing(scene, FALSE); 01825 Sequence *last_seq= seq_active_get(scene); 01826 MetaStack *ms; 01827 01828 if(last_seq && last_seq->type==SEQ_META && last_seq->flag & SELECT) { 01829 /* Enter Metastrip */ 01830 ms= MEM_mallocN(sizeof(MetaStack), "metastack"); 01831 BLI_addtail(&ed->metastack, ms); 01832 ms->parseq= last_seq; 01833 ms->oldbasep= ed->seqbasep; 01834 01835 ed->seqbasep= &last_seq->seqbase; 01836 01837 seq_active_set(scene, NULL); 01838 01839 } 01840 else { 01841 /* Exit Metastrip (if possible) */ 01842 01843 Sequence *seq; 01844 01845 if(ed->metastack.first==NULL) 01846 return OPERATOR_CANCELLED; 01847 01848 ms= ed->metastack.last; 01849 BLI_remlink(&ed->metastack, ms); 01850 01851 ed->seqbasep= ms->oldbasep; 01852 01853 /* recalc all: the meta can have effects connected to it */ 01854 for(seq= ed->seqbasep->first; seq; seq= seq->next) 01855 calc_sequence(scene, seq); 01856 01857 seq_active_set(scene, ms->parseq); 01858 01859 ms->parseq->flag |= SELECT; 01860 recurs_sel_seq(ms->parseq); 01861 01862 MEM_freeN(ms); 01863 01864 } 01865 01866 seq_update_muting(ed); 01867 WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene); 01868 01869 return OPERATOR_FINISHED; 01870 } 01871 01872 void SEQUENCER_OT_meta_toggle(wmOperatorType *ot) 01873 { 01874 /* identifiers */ 01875 ot->name= "Toggle Meta Strip"; 01876 ot->idname= "SEQUENCER_OT_meta_toggle"; 01877 ot->description="Toggle a metastrip (to edit enclosed strips)"; 01878 01879 /* api callbacks */ 01880 ot->exec= sequencer_meta_toggle_exec; 01881 ot->poll= sequencer_edit_poll; 01882 01883 /* flags */ 01884 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01885 } 01886 01887 01888 /* separate_meta_make operator */ 01889 static int sequencer_meta_make_exec(bContext *C, wmOperator *op) 01890 { 01891 Scene *scene= CTX_data_scene(C); 01892 Editing *ed= seq_give_editing(scene, FALSE); 01893 01894 Sequence *seq, *seqm, *next, *last_seq = seq_active_get(scene); 01895 int channel_max= 1; 01896 01897 if(seqbase_isolated_sel_check(ed->seqbasep)==FALSE) { 01898 BKE_report(op->reports, RPT_ERROR, "Please select all related strips"); 01899 return OPERATOR_CANCELLED; 01900 } 01901 01902 /* remove all selected from main list, and put in meta */ 01903 01904 seqm= alloc_sequence(ed->seqbasep, 1, 1); /* channel number set later */ 01905 strcpy(seqm->name+2, "MetaStrip"); 01906 seqm->type= SEQ_META; 01907 seqm->flag= SELECT; 01908 01909 seq= ed->seqbasep->first; 01910 while(seq) { 01911 next= seq->next; 01912 if(seq!=seqm && (seq->flag & SELECT)) { 01913 channel_max= MAX2(seq->machine, channel_max); 01914 BLI_remlink(ed->seqbasep, seq); 01915 BLI_addtail(&seqm->seqbase, seq); 01916 } 01917 seq= next; 01918 } 01919 seqm->machine= last_seq ? last_seq->machine : channel_max; 01920 calc_sequence(scene, seqm); 01921 01922 seqm->strip= MEM_callocN(sizeof(Strip), "metastrip"); 01923 seqm->strip->len= seqm->len; 01924 seqm->strip->us= 1; 01925 01926 seq_active_set(scene, seqm); 01927 01928 if( seq_test_overlap(ed->seqbasep, seqm) ) shuffle_seq(ed->seqbasep, seqm, scene); 01929 01930 seq_update_muting(ed); 01931 01932 seqbase_unique_name_recursive(&scene->ed->seqbase, seqm); 01933 01934 WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene); 01935 01936 return OPERATOR_FINISHED; 01937 } 01938 01939 void SEQUENCER_OT_meta_make(wmOperatorType *ot) 01940 { 01941 /* identifiers */ 01942 ot->name= "Make Meta Strip"; 01943 ot->idname= "SEQUENCER_OT_meta_make"; 01944 ot->description="Group selected strips into a metastrip"; 01945 01946 /* api callbacks */ 01947 ot->invoke= WM_operator_confirm; 01948 ot->exec= sequencer_meta_make_exec; 01949 ot->poll= sequencer_edit_poll; 01950 01951 /* flags */ 01952 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01953 } 01954 01955 01956 static int seq_depends_on_meta(Sequence *seq, Sequence *seqm) 01957 { 01958 if (seq == seqm) return 1; 01959 else if (seq->seq1 && seq_depends_on_meta(seq->seq1, seqm)) return 1; 01960 else if (seq->seq2 && seq_depends_on_meta(seq->seq2, seqm)) return 1; 01961 else if (seq->seq3 && seq_depends_on_meta(seq->seq3, seqm)) return 1; 01962 else return 0; 01963 } 01964 01965 /* separate_meta_make operator */ 01966 static int sequencer_meta_separate_exec(bContext *C, wmOperator *UNUSED(op)) 01967 { 01968 Scene *scene= CTX_data_scene(C); 01969 Editing *ed= seq_give_editing(scene, FALSE); 01970 01971 Sequence *seq, *last_seq = seq_active_get(scene); /* last_seq checks ed==NULL */ 01972 01973 if(last_seq==NULL || last_seq->type!=SEQ_META) 01974 return OPERATOR_CANCELLED; 01975 01976 BLI_movelisttolist(ed->seqbasep, &last_seq->seqbase); 01977 01978 last_seq->seqbase.first= NULL; 01979 last_seq->seqbase.last= NULL; 01980 01981 BLI_remlink(ed->seqbasep, last_seq); 01982 seq_free_sequence(scene, last_seq); 01983 01984 /* emtpy meta strip, delete all effects depending on it */ 01985 for(seq=ed->seqbasep->first; seq; seq=seq->next) 01986 if((seq->type & SEQ_EFFECT) && seq_depends_on_meta(seq, last_seq)) 01987 seq->flag |= SEQ_FLAG_DELETE; 01988 01989 recurs_del_seq_flag(scene, ed->seqbasep, SEQ_FLAG_DELETE, 0); 01990 01991 /* test for effects and overlap 01992 * dont use SEQP_BEGIN since that would be recursive */ 01993 for(seq= ed->seqbasep->first; seq; seq= seq->next) { 01994 if(seq->flag & SELECT) { 01995 seq->flag &= ~SEQ_OVERLAP; 01996 if(seq_test_overlap(ed->seqbasep, seq)) { 01997 shuffle_seq(ed->seqbasep, seq, scene); 01998 } 01999 } 02000 } 02001 02002 sort_seq(scene); 02003 seq_update_muting(ed); 02004 02005 WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene); 02006 02007 return OPERATOR_FINISHED; 02008 } 02009 02010 void SEQUENCER_OT_meta_separate(wmOperatorType *ot) 02011 { 02012 /* identifiers */ 02013 ot->name= "UnMeta Strip"; 02014 ot->idname= "SEQUENCER_OT_meta_separate"; 02015 ot->description="Put the contents of a metastrip back in the sequencer"; 02016 02017 /* api callbacks */ 02018 ot->invoke= WM_operator_confirm; 02019 ot->exec= sequencer_meta_separate_exec; 02020 ot->poll= sequencer_edit_poll; 02021 02022 /* flags */ 02023 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 02024 } 02025 02026 /* view_all operator */ 02027 static int sequencer_view_all_exec(bContext *C, wmOperator *UNUSED(op)) 02028 { 02029 //Scene *scene= CTX_data_scene(C); 02030 bScreen *sc= CTX_wm_screen(C); 02031 ScrArea *area= CTX_wm_area(C); 02032 //ARegion *ar= CTX_wm_region(C); 02033 View2D *v2d= UI_view2d_fromcontext(C); 02034 02035 v2d->cur= v2d->tot; 02036 UI_view2d_curRect_validate(v2d); 02037 UI_view2d_sync(sc, area, v2d, V2D_LOCK_COPY); 02038 02039 ED_area_tag_redraw(CTX_wm_area(C)); 02040 return OPERATOR_FINISHED; 02041 } 02042 02043 void SEQUENCER_OT_view_all(wmOperatorType *ot) 02044 { 02045 /* identifiers */ 02046 ot->name= "View All"; 02047 ot->idname= "SEQUENCER_OT_view_all"; 02048 ot->description="View all the strips in the sequencer"; 02049 02050 /* api callbacks */ 02051 ot->exec= sequencer_view_all_exec; 02052 ot->poll= ED_operator_sequencer_active; 02053 02054 /* flags */ 02055 ot->flag= OPTYPE_REGISTER; 02056 } 02057 02058 /* view_all operator */ 02059 static int sequencer_view_all_preview_exec(bContext *C, wmOperator *UNUSED(op)) 02060 { 02061 bScreen *sc= CTX_wm_screen(C); 02062 ScrArea *area= CTX_wm_area(C); 02063 #if 0 02064 ARegion *ar= CTX_wm_region(C); 02065 SpaceSeq *sseq= area->spacedata.first; 02066 Scene *scene= CTX_data_scene(C); 02067 #endif 02068 View2D *v2d= UI_view2d_fromcontext(C); 02069 02070 v2d->cur= v2d->tot; 02071 UI_view2d_curRect_validate(v2d); 02072 UI_view2d_sync(sc, area, v2d, V2D_LOCK_COPY); 02073 02074 #if 0 02075 /* Like zooming on an image view */ 02076 float zoomX, zoomY; 02077 int width, height, imgwidth, imgheight; 02078 02079 width = ar->winx; 02080 height = ar->winy; 02081 02082 seq_reset_imageofs(sseq); 02083 02084 imgwidth= (scene->r.size*scene->r.xsch)/100; 02085 imgheight= (scene->r.size*scene->r.ysch)/100; 02086 02087 /* Apply aspect, dosnt need to be that accurate */ 02088 imgwidth= (int)(imgwidth * (scene->r.xasp / scene->r.yasp)); 02089 02090 if (((imgwidth >= width) || (imgheight >= height)) && 02091 ((width > 0) && (height > 0))) { 02092 02093 /* Find the zoom value that will fit the image in the image space */ 02094 zoomX = ((float)width) / ((float)imgwidth); 02095 zoomY = ((float)height) / ((float)imgheight); 02096 sseq->zoom= (zoomX < zoomY) ? zoomX : zoomY; 02097 02098 sseq->zoom = 1.0f / power_of_2(1/ MIN2(zoomX, zoomY) ); 02099 } 02100 else { 02101 sseq->zoom= 1.0f; 02102 } 02103 #endif 02104 02105 ED_area_tag_redraw(CTX_wm_area(C)); 02106 return OPERATOR_FINISHED; 02107 } 02108 02109 void SEQUENCER_OT_view_all_preview(wmOperatorType *ot) 02110 { 02111 /* identifiers */ 02112 ot->name= "View All"; 02113 ot->idname= "SEQUENCER_OT_view_all_preview"; 02114 ot->description="Zoom preview to fit in the area"; 02115 02116 /* api callbacks */ 02117 ot->exec= sequencer_view_all_preview_exec; 02118 ot->poll= ED_operator_sequencer_active; 02119 02120 /* flags */ 02121 ot->flag= OPTYPE_REGISTER; 02122 } 02123 02124 02125 static int sequencer_view_zoom_ratio_exec(bContext *C, wmOperator *op) 02126 { 02127 RenderData *r= &CTX_data_scene(C)->r; 02128 View2D *v2d= UI_view2d_fromcontext(C); 02129 02130 float ratio= RNA_float_get(op->ptr, "ratio"); 02131 02132 float winx= (int)(r->size * r->xsch)/100; 02133 float winy= (int)(r->size * r->ysch)/100; 02134 02135 float facx= (v2d->mask.xmax - v2d->mask.xmin) / winx; 02136 float facy= (v2d->mask.ymax - v2d->mask.ymin) / winy; 02137 02138 BLI_resize_rctf(&v2d->cur, (int)(winx*facx*ratio) + 1, (int)(winy*facy*ratio) + 1); 02139 02140 ED_region_tag_redraw(CTX_wm_region(C)); 02141 02142 return OPERATOR_FINISHED; 02143 } 02144 02145 void SEQUENCER_OT_view_zoom_ratio(wmOperatorType *ot) 02146 { 02147 /* identifiers */ 02148 ot->name= "Sequencer View Zoom Ratio"; 02149 ot->idname= "SEQUENCER_OT_view_zoom_ratio"; 02150 ot->description = "Change zoom ratio of sequencer preview"; 02151 02152 /* api callbacks */ 02153 ot->exec= sequencer_view_zoom_ratio_exec; 02154 ot->poll= ED_operator_sequencer_active; 02155 02156 /* properties */ 02157 RNA_def_float(ot->srna, "ratio", 1.0f, 0.0f, FLT_MAX, 02158 "Ratio", "Zoom ratio, 1.0 is 1:1, higher is zoomed in, lower is zoomed out", -FLT_MAX, FLT_MAX); 02159 } 02160 02161 02162 #if 0 02163 static EnumPropertyItem view_type_items[] = { 02164 {SEQ_VIEW_SEQUENCE, "SEQUENCER", ICON_SEQ_SEQUENCER, "Sequencer", ""}, 02165 {SEQ_VIEW_PREVIEW, "PREVIEW", ICON_SEQ_PREVIEW, "Image Preview", ""}, 02166 {SEQ_VIEW_SEQUENCE_PREVIEW, "SEQUENCER_PREVIEW", ICON_SEQ_SEQUENCER, "Sequencer and Image Preview", ""}, 02167 {0, NULL, 0, NULL, NULL}}; 02168 #endif 02169 02170 /* view_all operator */ 02171 static int sequencer_view_toggle_exec(bContext *C, wmOperator *UNUSED(op)) 02172 { 02173 SpaceSeq *sseq= (SpaceSeq *)CTX_wm_space_data(C); 02174 02175 sseq->view++; 02176 if (sseq->view > SEQ_VIEW_SEQUENCE_PREVIEW) sseq->view = SEQ_VIEW_SEQUENCE; 02177 02178 ED_area_tag_refresh(CTX_wm_area(C)); 02179 02180 return OPERATOR_FINISHED; 02181 } 02182 02183 void SEQUENCER_OT_view_toggle(wmOperatorType *ot) 02184 { 02185 /* identifiers */ 02186 ot->name= "View Toggle"; 02187 ot->idname= "SEQUENCER_OT_view_toggle"; 02188 ot->description="Toggle between sequencer views (sequence, preview, both)"; 02189 02190 /* api callbacks */ 02191 ot->exec= sequencer_view_toggle_exec; 02192 ot->poll= ED_operator_sequencer_active; 02193 02194 /* flags */ 02195 ot->flag= OPTYPE_REGISTER; 02196 } 02197 02198 02199 /* view_selected operator */ 02200 static int sequencer_view_selected_exec(bContext *C, wmOperator *UNUSED(op)) 02201 { 02202 Scene *scene= CTX_data_scene(C); 02203 View2D *v2d= UI_view2d_fromcontext(C); 02204 ScrArea *area= CTX_wm_area(C); 02205 bScreen *sc= CTX_wm_screen(C); 02206 Editing *ed= seq_give_editing(scene, FALSE); 02207 Sequence *seq; 02208 02209 int xmin= MAXFRAME*2; 02210 int xmax= -MAXFRAME*2; 02211 int ymin= MAXSEQ+1; 02212 int ymax= 0; 02213 int orig_height; 02214 int ymid; 02215 int ymargin= 1; 02216 int xmargin= FPS; 02217 02218 if(ed==NULL) 02219 return OPERATOR_CANCELLED; 02220 02221 for(seq=ed->seqbasep->first; seq; seq=seq->next) { 02222 if(seq->flag & SELECT) { 02223 xmin= MIN2(xmin, seq->startdisp); 02224 xmax= MAX2(xmax, seq->enddisp); 02225 02226 ymin= MIN2(ymin, seq->machine); 02227 ymax= MAX2(ymax, seq->machine); 02228 } 02229 } 02230 02231 if (ymax != 0) { 02232 02233 xmax += xmargin; 02234 xmin -= xmargin; 02235 ymax += ymargin; 02236 ymin -= ymargin; 02237 02238 orig_height= v2d->cur.ymax - v2d->cur.ymin; 02239 02240 v2d->cur.xmin= xmin; 02241 v2d->cur.xmax= xmax; 02242 02243 v2d->cur.ymin= ymin; 02244 v2d->cur.ymax= ymax; 02245 02246 /* only zoom out vertically */ 02247 if (orig_height > v2d->cur.ymax - v2d->cur.ymin) { 02248 ymid= (v2d->cur.ymax + v2d->cur.ymin) / 2; 02249 02250 v2d->cur.ymin= ymid - (orig_height/2); 02251 v2d->cur.ymax= ymid + (orig_height/2); 02252 } 02253 02254 UI_view2d_curRect_validate(v2d); 02255 UI_view2d_sync(sc, area, v2d, V2D_LOCK_COPY); 02256 02257 ED_area_tag_redraw(CTX_wm_area(C)); 02258 } 02259 02260 return OPERATOR_FINISHED; 02261 } 02262 02263 void SEQUENCER_OT_view_selected(wmOperatorType *ot) 02264 { 02265 /* identifiers */ 02266 ot->name= "View Selected"; 02267 ot->idname= "SEQUENCER_OT_view_selected"; 02268 ot->description="Zoom the sequencer on the selected strips"; 02269 02270 /* api callbacks */ 02271 ot->exec= sequencer_view_selected_exec; 02272 ot->poll= ED_operator_sequencer_active; 02273 02274 /* flags */ 02275 ot->flag= OPTYPE_REGISTER; 02276 } 02277 02278 02279 static int find_next_prev_edit(Scene *scene, int cfra, int side) 02280 { 02281 Editing *ed= seq_give_editing(scene, FALSE); 02282 Sequence *seq,*best_seq = NULL,*frame_seq = NULL; 02283 02284 int dist, best_dist; 02285 best_dist = MAXFRAME*2; 02286 02287 if(ed==NULL) return cfra; 02288 02289 for(seq= ed->seqbasep->first; seq; seq= seq->next) { 02290 dist = MAXFRAME*2; 02291 02292 switch (side) { 02293 case SEQ_SIDE_LEFT: 02294 if (seq->startdisp < cfra) { 02295 dist = cfra - seq->startdisp; 02296 } 02297 break; 02298 case SEQ_SIDE_RIGHT: 02299 if (seq->startdisp > cfra) { 02300 dist = seq->startdisp - cfra; 02301 } else if (seq->startdisp == cfra) { 02302 frame_seq=seq; 02303 } 02304 break; 02305 } 02306 02307 if (dist < best_dist) { 02308 best_dist = dist; 02309 best_seq = seq; 02310 } 02311 } 02312 02313 /* if no sequence to the right is found and the 02314 frame is on the start of the last sequence, 02315 move to the end of the last sequence */ 02316 if (frame_seq) cfra = frame_seq->enddisp; 02317 02318 return best_seq ? best_seq->startdisp : cfra; 02319 } 02320 02321 static int next_prev_edit_internal(Scene *scene, int side) 02322 { 02323 int change=0; 02324 int cfra = CFRA; 02325 int nfra= find_next_prev_edit(scene, cfra, side); 02326 02327 if (nfra != cfra) { 02328 CFRA = nfra; 02329 change= 1; 02330 } 02331 02332 return change; 02333 } 02334 02335 /* move frame to next edit point operator */ 02336 static int sequencer_next_edit_exec(bContext *C, wmOperator *UNUSED(op)) 02337 { 02338 Scene *scene= CTX_data_scene(C); 02339 02340 if(!next_prev_edit_internal(scene, SEQ_SIDE_RIGHT)) 02341 return OPERATOR_CANCELLED; 02342 02343 WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene); 02344 02345 return OPERATOR_FINISHED; 02346 } 02347 02348 void SEQUENCER_OT_next_edit(wmOperatorType *ot) 02349 { 02350 /* identifiers */ 02351 ot->name= "Next Edit"; 02352 ot->idname= "SEQUENCER_OT_next_edit"; 02353 ot->description="Move frame to next edit point"; 02354 02355 /* api callbacks */ 02356 ot->exec= sequencer_next_edit_exec; 02357 ot->poll= sequencer_edit_poll; 02358 02359 /* flags */ 02360 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 02361 02362 /* properties */ 02363 } 02364 02365 /* move frame to previous edit point operator */ 02366 static int sequencer_previous_edit_exec(bContext *C, wmOperator *UNUSED(op)) 02367 { 02368 Scene *scene= CTX_data_scene(C); 02369 02370 if(!next_prev_edit_internal(scene, SEQ_SIDE_LEFT)) 02371 return OPERATOR_CANCELLED; 02372 02373 WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene); 02374 02375 return OPERATOR_FINISHED; 02376 } 02377 02378 void SEQUENCER_OT_previous_edit(wmOperatorType *ot) 02379 { 02380 /* identifiers */ 02381 ot->name= "Previous Edit"; 02382 ot->idname= "SEQUENCER_OT_previous_edit"; 02383 ot->description="Move frame to previous edit point"; 02384 02385 /* api callbacks */ 02386 ot->exec= sequencer_previous_edit_exec; 02387 ot->poll= sequencer_edit_poll; 02388 02389 /* flags */ 02390 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 02391 02392 /* properties */ 02393 } 02394 02395 static void swap_sequence(Scene* scene, Sequence* seqa, Sequence* seqb) 02396 { 02397 int gap = seqb->startdisp - seqa->enddisp; 02398 seqb->start = (seqb->start - seqb->startdisp) + seqa->startdisp; 02399 calc_sequence(scene, seqb); 02400 seqa->start = (seqa->start - seqa->startdisp) + seqb->enddisp + gap; 02401 calc_sequence(scene, seqa); 02402 } 02403 02404 #if 0 02405 static Sequence* sequence_find_parent(Scene* scene, Sequence* child) 02406 { 02407 Editing *ed= seq_give_editing(scene, FALSE); 02408 Sequence *parent= NULL; 02409 Sequence *seq; 02410 02411 if(ed==NULL) return NULL; 02412 02413 for(seq= ed->seqbasep->first; seq; seq= seq->next) { 02414 if ( (seq != child) && seq_is_parent(seq, child) ) { 02415 parent = seq; 02416 break; 02417 } 02418 } 02419 02420 return parent; 02421 } 02422 #endif 02423 02424 static int sequencer_swap_exec(bContext *C, wmOperator *op) 02425 { 02426 Scene *scene= CTX_data_scene(C); 02427 Editing *ed= seq_give_editing(scene, FALSE); 02428 Sequence *active_seq = seq_active_get(scene); 02429 Sequence *seq, *iseq; 02430 int side= RNA_enum_get(op->ptr, "side"); 02431 02432 if(active_seq==NULL) return OPERATOR_CANCELLED; 02433 02434 seq = find_next_prev_sequence(scene, active_seq, side, -1); 02435 02436 if(seq) { 02437 02438 /* disallow effect strips */ 02439 if (get_sequence_effect_num_inputs(seq->type) >= 1 && (seq->effectdata || seq->seq1 || seq->seq2 || seq->seq3)) 02440 return OPERATOR_CANCELLED; 02441 if ((get_sequence_effect_num_inputs(active_seq->type) >= 1) && (active_seq->effectdata || active_seq->seq1 || active_seq->seq2 || active_seq->seq3)) 02442 return OPERATOR_CANCELLED; 02443 02444 switch (side) { 02445 case SEQ_SIDE_LEFT: 02446 swap_sequence(scene, seq, active_seq); 02447 break; 02448 case SEQ_SIDE_RIGHT: 02449 swap_sequence(scene, active_seq, seq); 02450 break; 02451 } 02452 02453 // XXX - should be a generic function 02454 for(iseq= scene->ed->seqbasep->first; iseq; iseq= iseq->next) { 02455 if((iseq->type & SEQ_EFFECT) && (seq_is_parent(iseq, active_seq) || seq_is_parent(iseq, seq))) { 02456 calc_sequence(scene, iseq); 02457 } 02458 } 02459 02460 /* do this in a new loop since both effects need to be calculated first */ 02461 for(iseq= scene->ed->seqbasep->first; iseq; iseq= iseq->next) { 02462 if((iseq->type & SEQ_EFFECT) && (seq_is_parent(iseq, active_seq) || seq_is_parent(iseq, seq))) { 02463 /* this may now overlap */ 02464 if( seq_test_overlap(ed->seqbasep, iseq) ) { 02465 shuffle_seq(ed->seqbasep, iseq, scene); 02466 } 02467 } 02468 } 02469 02470 02471 02472 sort_seq(scene); 02473 02474 WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene); 02475 02476 return OPERATOR_FINISHED; 02477 } 02478 02479 return OPERATOR_CANCELLED; 02480 } 02481 02482 void SEQUENCER_OT_swap(wmOperatorType *ot) 02483 { 02484 /* identifiers */ 02485 ot->name= "Swap Strip"; 02486 ot->idname= "SEQUENCER_OT_swap"; 02487 ot->description="Swap active strip with strip to the right or left"; 02488 02489 /* api callbacks */ 02490 ot->exec= sequencer_swap_exec; 02491 ot->poll= sequencer_edit_poll; 02492 02493 /* flags */ 02494 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 02495 02496 /* properties */ 02497 RNA_def_enum(ot->srna, "side", prop_side_lr_types, SEQ_SIDE_RIGHT, "Side", "Side of the strip to swap"); 02498 } 02499 02500 static int sequencer_rendersize_exec(bContext *C, wmOperator *UNUSED(op)) 02501 { 02502 int retval = OPERATOR_CANCELLED; 02503 Scene *scene= CTX_data_scene(C); 02504 Sequence *active_seq = seq_active_get(scene); 02505 StripElem *se = NULL; 02506 02507 if(active_seq==NULL) 02508 return OPERATOR_CANCELLED; 02509 02510 02511 if (active_seq->strip) { 02512 switch (active_seq->type) { 02513 case SEQ_IMAGE: 02514 se = give_stripelem(active_seq, scene->r.cfra); 02515 break; 02516 case SEQ_MOVIE: 02517 se = active_seq->strip->stripdata; 02518 break; 02519 case SEQ_SCENE: 02520 case SEQ_META: 02521 case SEQ_RAM_SOUND: 02522 case SEQ_HD_SOUND: 02523 default: 02524 break; 02525 } 02526 } 02527 02528 if (se) { 02529 // prevent setting the render size if sequence values aren't initialized 02530 if ( (se->orig_width > 0) && (se->orig_height > 0) ) { 02531 scene->r.xsch= se->orig_width; 02532 scene->r.ysch= se->orig_height; 02533 WM_event_add_notifier(C, NC_SCENE|ND_RENDER_OPTIONS, scene); 02534 retval = OPERATOR_FINISHED; 02535 } 02536 } 02537 02538 return retval; 02539 } 02540 02541 void SEQUENCER_OT_rendersize(wmOperatorType *ot) 02542 { 02543 /* identifiers */ 02544 ot->name= "Set Render Size"; 02545 ot->idname= "SEQUENCER_OT_rendersize"; 02546 ot->description="Set render size and aspect from active sequence"; 02547 02548 /* api callbacks */ 02549 ot->exec= sequencer_rendersize_exec; 02550 ot->poll= sequencer_edit_poll; 02551 02552 /* flags */ 02553 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 02554 02555 /* properties */ 02556 } 02557 02558 static void seq_del_sound(Scene *scene, Sequence *seq) 02559 { 02560 if(seq->type == SEQ_META) { 02561 Sequence *iseq; 02562 for(iseq= seq->seqbase.first; iseq; iseq= iseq->next) { 02563 seq_del_sound(scene, iseq); 02564 } 02565 } 02566 else if(seq->scene_sound) { 02567 sound_remove_scene_sound(scene, seq->scene_sound); 02568 seq->scene_sound = NULL; 02569 } 02570 } 02571 02572 /* TODO, validate scenes */ 02573 static int sequencer_copy_exec(bContext *C, wmOperator *op) 02574 { 02575 Scene *scene= CTX_data_scene(C); 02576 Editing *ed= seq_give_editing(scene, FALSE); 02577 Sequence *seq; 02578 02579 ListBase nseqbase= {NULL, NULL}; 02580 02581 seq_free_clipboard(); 02582 02583 if(seqbase_isolated_sel_check(ed->seqbasep)==FALSE) { 02584 BKE_report(op->reports, RPT_ERROR, "Please select all related strips"); 02585 return OPERATOR_CANCELLED; 02586 } 02587 02588 seqbase_dupli_recursive(scene, NULL, &nseqbase, ed->seqbasep, SEQ_DUPE_UNIQUE_NAME); 02589 02590 /* To make sure the copied strips have unique names between each other add 02591 * them temporarily to the end of the original seqbase. (bug 25932) 02592 */ 02593 if(nseqbase.first) { 02594 Sequence *seq, *first_seq = nseqbase.first; 02595 BLI_movelisttolist(ed->seqbasep, &nseqbase); 02596 02597 for(seq=first_seq; seq; seq=seq->next) 02598 seq_recursive_apply(seq, apply_unique_name_cb, scene); 02599 02600 seqbase_clipboard.first = first_seq; 02601 seqbase_clipboard.last = ed->seqbasep->last; 02602 02603 if(first_seq->prev) { 02604 first_seq->prev->next = NULL; 02605 ed->seqbasep->last = first_seq->prev; 02606 first_seq->prev = NULL; 02607 } 02608 } 02609 02610 seqbase_clipboard_frame= scene->r.cfra; 02611 02612 /* Need to remove anything that references the current scene */ 02613 for(seq= seqbase_clipboard.first; seq; seq= seq->next) { 02614 seq_del_sound(scene, seq); 02615 } 02616 02617 return OPERATOR_FINISHED; 02618 } 02619 02620 void SEQUENCER_OT_copy(wmOperatorType *ot) 02621 { 02622 /* identifiers */ 02623 ot->name= "Copy"; 02624 ot->idname= "SEQUENCER_OT_copy"; 02625 ot->description=""; 02626 02627 /* api callbacks */ 02628 ot->exec= sequencer_copy_exec; 02629 ot->poll= sequencer_edit_poll; 02630 02631 /* flags */ 02632 ot->flag= OPTYPE_REGISTER; 02633 02634 /* properties */ 02635 } 02636 02637 static int sequencer_paste_exec(bContext *C, wmOperator *UNUSED(op)) 02638 { 02639 Scene *scene= CTX_data_scene(C); 02640 Editing *ed= seq_give_editing(scene, TRUE); /* create if needed */ 02641 ListBase nseqbase = {NULL, NULL}; 02642 int ofs; 02643 Sequence *iseq; 02644 02645 deselect_all_seq(scene); 02646 ofs = scene->r.cfra - seqbase_clipboard_frame; 02647 02648 seqbase_dupli_recursive(scene, NULL, &nseqbase, &seqbase_clipboard, SEQ_DUPE_UNIQUE_NAME); 02649 02650 /* transform pasted strips before adding */ 02651 if(ofs) { 02652 for(iseq= nseqbase.first; iseq; iseq= iseq->next) { 02653 seq_translate(scene, iseq, ofs); 02654 seq_sound_init(scene, iseq); 02655 } 02656 } 02657 02658 iseq = nseqbase.first; 02659 02660 BLI_movelisttolist(ed->seqbasep, &nseqbase); 02661 02662 /* make sure the pasted strips have unique names between them */ 02663 for(; iseq; iseq=iseq->next) 02664 seq_recursive_apply(iseq, apply_unique_name_cb, scene); 02665 02666 WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene); 02667 02668 return OPERATOR_FINISHED; 02669 } 02670 02671 void SEQUENCER_OT_paste(wmOperatorType *ot) 02672 { 02673 /* identifiers */ 02674 ot->name= "Paste"; 02675 ot->idname= "SEQUENCER_OT_paste"; 02676 ot->description=""; 02677 02678 /* api callbacks */ 02679 ot->exec= sequencer_paste_exec; 02680 ot->poll= ED_operator_sequencer_active; 02681 02682 /* flags */ 02683 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 02684 02685 /* properties */ 02686 } 02687 02688 static int sequencer_swap_data_exec(bContext *C, wmOperator *op) 02689 { 02690 Scene *scene= CTX_data_scene(C); 02691 Sequence *seq_act; 02692 Sequence *seq_other; 02693 const char *error_msg; 02694 02695 if(seq_active_pair_get(scene, &seq_act, &seq_other) == 0) { 02696 BKE_report(op->reports, RPT_ERROR, "Must select 2 strips"); 02697 return OPERATOR_CANCELLED; 02698 } 02699 02700 if(seq_swap(seq_act, seq_other, &error_msg) == 0) { 02701 BKE_report(op->reports, RPT_ERROR, error_msg); 02702 return OPERATOR_CANCELLED; 02703 } 02704 02705 sound_remove_scene_sound(scene, seq_act->scene_sound); 02706 sound_remove_scene_sound(scene, seq_other->scene_sound); 02707 02708 seq_act->scene_sound= NULL; 02709 seq_other->scene_sound= NULL; 02710 02711 calc_sequence(scene, seq_act); 02712 calc_sequence(scene, seq_other); 02713 02714 if(seq_act->sound) sound_add_scene_sound_defaults(scene, seq_act); 02715 if(seq_other->sound) sound_add_scene_sound_defaults(scene, seq_other); 02716 02717 WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene); 02718 02719 return OPERATOR_FINISHED; 02720 } 02721 02722 void SEQUENCER_OT_swap_data(wmOperatorType *ot) 02723 { 02724 /* identifiers */ 02725 ot->name= "Sequencer Swap Data"; 02726 ot->idname= "SEQUENCER_OT_swap_data"; 02727 ot->description="Swap 2 sequencer strips"; 02728 02729 /* api callbacks */ 02730 ot->exec= sequencer_swap_data_exec; 02731 ot->poll= ED_operator_sequencer_active; 02732 02733 /* flags */ 02734 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 02735 02736 /* properties */ 02737 } 02738 02739 /* borderselect operator */ 02740 static int view_ghost_border_exec(bContext *C, wmOperator *op) 02741 { 02742 Scene *scene= CTX_data_scene(C); 02743 Editing *ed= seq_give_editing(scene, FALSE); 02744 View2D *v2d= UI_view2d_fromcontext(C); 02745 02746 rctf rect; 02747 02748 /* convert coordinates of rect to 'tot' rect coordinates */ 02749 UI_view2d_region_to_view(v2d, RNA_int_get(op->ptr, "xmin"), RNA_int_get(op->ptr, "ymin"), &rect.xmin, &rect.ymin); 02750 UI_view2d_region_to_view(v2d, RNA_int_get(op->ptr, "xmax"), RNA_int_get(op->ptr, "ymax"), &rect.xmax, &rect.ymax); 02751 02752 if(ed==NULL) 02753 return OPERATOR_CANCELLED; 02754 02755 rect.xmin /= (float)(ABS(v2d->tot.xmax - v2d->tot.xmin)); 02756 rect.ymin /= (float)(ABS(v2d->tot.ymax - v2d->tot.ymin)); 02757 02758 rect.xmax /= (float)(ABS(v2d->tot.xmax - v2d->tot.xmin)); 02759 rect.ymax /= (float)(ABS(v2d->tot.ymax - v2d->tot.ymin)); 02760 02761 rect.xmin+=0.5f; 02762 rect.xmax+=0.5f; 02763 rect.ymin+=0.5f; 02764 rect.ymax+=0.5f; 02765 02766 CLAMP(rect.xmin, 0.0f, 1.0f); 02767 CLAMP(rect.ymin, 0.0f, 1.0f); 02768 CLAMP(rect.xmax, 0.0f, 1.0f); 02769 CLAMP(rect.ymax, 0.0f, 1.0f); 02770 02771 scene->ed->over_border= rect; 02772 02773 WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene); 02774 02775 return OPERATOR_FINISHED; 02776 } 02777 02778 /* ****** Border Select ****** */ 02779 void SEQUENCER_OT_view_ghost_border(wmOperatorType *ot) 02780 { 02781 /* identifiers */ 02782 ot->name= "Border Offset View"; 02783 ot->idname= "SEQUENCER_OT_view_ghost_border"; 02784 ot->description="Enable border select mode"; 02785 02786 /* api callbacks */ 02787 ot->invoke= WM_border_select_invoke; 02788 ot->exec= view_ghost_border_exec; 02789 ot->modal= WM_border_select_modal; 02790 ot->poll= sequencer_view_poll; 02791 ot->cancel= WM_border_select_cancel; 02792 02793 /* flags */ 02794 ot->flag= 0; 02795 02796 /* rna */ 02797 WM_operator_properties_gesture_border(ot, FALSE); 02798 } 02799 02800 /* rebuild_proxy operator */ 02801 static int sequencer_rebuild_proxy_exec(bContext *C, wmOperator *UNUSED(op)) 02802 { 02803 Scene *scene = CTX_data_scene(C); 02804 Editing *ed = seq_give_editing(scene, FALSE); 02805 Sequence * seq; 02806 02807 SEQP_BEGIN(ed, seq) { 02808 if ((seq->flag & SELECT)) { 02809 seq_proxy_build_job(C, seq); 02810 } 02811 } 02812 SEQ_END 02813 02814 return OPERATOR_FINISHED; 02815 } 02816 02817 void SEQUENCER_OT_rebuild_proxy(wmOperatorType *ot) 02818 { 02819 /* identifiers */ 02820 ot->name= "Rebuild Proxy and Timecode Indices"; 02821 ot->idname= "SEQUENCER_OT_rebuild_proxy"; 02822 ot->description="Rebuild all selected proxies and timecode indeces using the job system"; 02823 02824 /* api callbacks */ 02825 ot->exec= sequencer_rebuild_proxy_exec; 02826 ot->poll= ED_operator_sequencer_active; 02827 02828 /* flags */ 02829 ot->flag= OPTYPE_REGISTER; 02830 } 02831 02832 /* change ops */ 02833 02834 static EnumPropertyItem prop_change_effect_input_types[] = { 02835 {0, "A_B", 0, "A -> B", ""}, 02836 {1, "B_C", 0, "B -> C", ""}, 02837 {2, "A_C", 0, "A -> C", ""}, 02838 {0, NULL, 0, NULL, NULL} 02839 }; 02840 02841 static int sequencer_change_effect_input_exec(bContext *C, wmOperator *op) 02842 { 02843 Scene *scene= CTX_data_scene(C); 02844 Editing *ed= seq_give_editing(scene, FALSE); 02845 Sequence *seq= seq_active_get(scene); 02846 02847 Sequence **seq_1, **seq_2; 02848 02849 switch(RNA_enum_get(op->ptr, "swap")) { 02850 case 0: 02851 seq_1= &seq->seq1; 02852 seq_2= &seq->seq2; 02853 break; 02854 case 1: 02855 seq_1= &seq->seq2; 02856 seq_2= &seq->seq3; 02857 break; 02858 default: /* 2 */ 02859 seq_1= &seq->seq1; 02860 seq_2= &seq->seq3; 02861 break; 02862 } 02863 02864 if(*seq_1 == NULL || *seq_2 == NULL) { 02865 BKE_report(op->reports, RPT_ERROR, "One of the effect inputs is unset, can't swap"); 02866 return OPERATOR_CANCELLED; 02867 } 02868 else { 02869 SWAP(Sequence *, *seq_1, *seq_2); 02870 } 02871 02872 update_changed_seq_and_deps(scene, seq, 0, 1); 02873 02874 /* important else we dont get the imbuf cache flushed */ 02875 free_imbuf_seq(scene, &ed->seqbase, FALSE, FALSE); 02876 02877 WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene); 02878 02879 return OPERATOR_FINISHED; 02880 } 02881 02882 void SEQUENCER_OT_change_effect_input(struct wmOperatorType *ot) 02883 { 02884 /* identifiers */ 02885 ot->name= "Change Effect Input"; 02886 ot->idname= "SEQUENCER_OT_change_effect_input"; 02887 ot->description=""; 02888 02889 /* api callbacks */ 02890 ot->exec= sequencer_change_effect_input_exec; 02891 ot->poll= sequencer_effect_poll; 02892 02893 /* flags */ 02894 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 02895 02896 ot->prop= RNA_def_enum(ot->srna, "swap", prop_change_effect_input_types, 0, "Swap", "The effect inputs to swap"); 02897 } 02898 02899 static int sequencer_change_effect_type_exec(bContext *C, wmOperator *op) 02900 { 02901 Scene *scene= CTX_data_scene(C); 02902 Editing *ed= seq_give_editing(scene, FALSE); 02903 Sequence *seq= seq_active_get(scene); 02904 const int new_type= RNA_enum_get(op->ptr, "type"); 02905 02906 /* free previous effect and init new effect */ 02907 struct SeqEffectHandle sh; 02908 02909 if ((seq->type & SEQ_EFFECT) == 0) { 02910 return OPERATOR_CANCELLED; 02911 } 02912 02913 /* can someone explain the logic behind only allowing to increse this, 02914 * copied from 2.4x - campbell */ 02915 if (get_sequence_effect_num_inputs(seq->type) < 02916 get_sequence_effect_num_inputs(new_type) 02917 ) { 02918 BKE_report(op->reports, RPT_ERROR, "New effect needs more input strips"); 02919 return OPERATOR_CANCELLED; 02920 } 02921 else { 02922 sh = get_sequence_effect(seq); 02923 sh.free(seq); 02924 02925 seq->type= new_type; 02926 02927 sh = get_sequence_effect(seq); 02928 sh.init(seq); 02929 } 02930 02931 /* update */ 02932 update_changed_seq_and_deps(scene, seq, 0, 1); 02933 02934 /* important else we dont get the imbuf cache flushed */ 02935 free_imbuf_seq(scene, &ed->seqbase, FALSE, FALSE); 02936 02937 WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene); 02938 02939 return OPERATOR_FINISHED; 02940 } 02941 02942 void SEQUENCER_OT_change_effect_type(struct wmOperatorType *ot) 02943 { 02944 /* identifiers */ 02945 ot->name= "Change Effect Type"; 02946 ot->idname= "SEQUENCER_OT_change_effect_type"; 02947 ot->description=""; 02948 02949 /* api callbacks */ 02950 ot->exec= sequencer_change_effect_type_exec; 02951 ot->poll= sequencer_effect_poll; 02952 02953 /* flags */ 02954 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 02955 02956 ot->prop= RNA_def_enum(ot->srna, "type", sequencer_prop_effect_types, SEQ_CROSS, "Type", "Sequencer effect type"); 02957 } 02958 02959 static int sequencer_change_path_exec(bContext *C, wmOperator *op) 02960 { 02961 Main *bmain= CTX_data_main(C); 02962 Scene *scene= CTX_data_scene(C); 02963 Editing *ed= seq_give_editing(scene, FALSE); 02964 Sequence *seq= seq_active_get(scene); 02965 const int is_relative_path= RNA_boolean_get(op->ptr, "relative_path"); 02966 02967 if(seq->type == SEQ_IMAGE) { 02968 char directory[FILE_MAX]; 02969 const int len= RNA_property_collection_length(op->ptr, RNA_struct_find_property(op->ptr, "files")); 02970 StripElem *se; 02971 02972 if(len==0) 02973 return OPERATOR_CANCELLED; 02974 02975 RNA_string_get(op->ptr, "directory", directory); 02976 if (is_relative_path) { 02977 /* TODO, shouldn't this already be relative from the filesel? 02978 * (as the 'filepath' is) for now just make relative here, 02979 * but look into changing after 2.60 - campbell */ 02980 BLI_path_rel(directory, bmain->name); 02981 } 02982 BLI_strncpy(seq->strip->dir, directory, sizeof(seq->strip->dir)); 02983 02984 if(seq->strip->stripdata) { 02985 MEM_freeN(seq->strip->stripdata); 02986 } 02987 seq->strip->stripdata= se= MEM_callocN(len*sizeof(StripElem), "stripelem"); 02988 02989 RNA_BEGIN(op->ptr, itemptr, "files") { 02990 char *filename= RNA_string_get_alloc(&itemptr, "name", NULL, 0); 02991 BLI_strncpy(se->name, filename, sizeof(se->name)); 02992 MEM_freeN(filename); 02993 se++; 02994 } 02995 RNA_END; 02996 02997 /* reset these else we wont see all the images */ 02998 seq->anim_startofs= seq->anim_endofs= 0; 02999 03000 /* correct start/end frames so we dont move 03001 * important not to set seq->len= len; allow the function to handle it */ 03002 reload_sequence_new_file(scene, seq, TRUE); 03003 03004 calc_sequence(scene, seq); 03005 03006 /* important else we dont get the imbuf cache flushed */ 03007 free_imbuf_seq(scene, &ed->seqbase, FALSE, FALSE); 03008 } 03009 else { 03010 /* lame, set rna filepath */ 03011 PointerRNA seq_ptr; 03012 PropertyRNA *prop; 03013 char filepath[FILE_MAX]; 03014 03015 RNA_pointer_create(&scene->id, &RNA_Sequence, seq, &seq_ptr); 03016 03017 RNA_string_get(op->ptr, "filepath", filepath); 03018 prop= RNA_struct_find_property(&seq_ptr, "filepath"); 03019 RNA_property_string_set(&seq_ptr, prop, filepath); 03020 RNA_property_update(C, &seq_ptr, prop); 03021 } 03022 03023 WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene); 03024 03025 return OPERATOR_FINISHED; 03026 } 03027 03028 static int sequencer_change_path_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) 03029 { 03030 Scene *scene= CTX_data_scene(C); 03031 Sequence *seq= seq_active_get(scene); 03032 03033 RNA_string_set(op->ptr, "directory", seq->strip->dir); 03034 03035 /* set default display depending on seq type */ 03036 if(seq->type == SEQ_IMAGE) { 03037 RNA_boolean_set(op->ptr, "filter_movie", FALSE); 03038 } 03039 else { 03040 RNA_boolean_set(op->ptr, "filter_image", FALSE); 03041 } 03042 03043 WM_event_add_fileselect(C, op); 03044 03045 return OPERATOR_RUNNING_MODAL; 03046 } 03047 03048 void SEQUENCER_OT_change_path(struct wmOperatorType *ot) 03049 { 03050 /* identifiers */ 03051 ot->name= "Change Data/Files"; 03052 ot->idname= "SEQUENCER_OT_change_path"; 03053 ot->description=""; 03054 03055 /* api callbacks */ 03056 ot->exec= sequencer_change_path_exec; 03057 ot->invoke= sequencer_change_path_invoke; 03058 ot->poll= sequencer_strip_has_path_poll; 03059 03060 /* flags */ 03061 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 03062 03063 WM_operator_properties_filesel(ot, FOLDERFILE|IMAGEFILE|MOVIEFILE, FILE_SPECIAL, FILE_OPENFILE, WM_FILESEL_DIRECTORY|WM_FILESEL_RELPATH|WM_FILESEL_FILEPATH|WM_FILESEL_FILES); 03064 }