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, Campbell Barton 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 "BLI_blenlib.h" 00043 #include "BLI_math.h" 00044 #include "BLI_utildefines.h" 00045 00046 #include "DNA_scene_types.h" 00047 00048 #include "BKE_context.h" 00049 #include "BKE_report.h" 00050 #include "BKE_sequencer.h" 00051 00052 #include "WM_api.h" 00053 #include "WM_types.h" 00054 00055 #include "RNA_define.h" 00056 00057 /* for menu/popup icons etc etc*/ 00058 00059 #include "ED_types.h" 00060 #include "ED_screen.h" 00061 00062 #include "UI_view2d.h" 00063 00064 /* own include */ 00065 #include "sequencer_intern.h" 00066 static void *find_nearest_marker(int UNUSED(d1), int UNUSED(d2)) {return NULL;} 00067 00068 static void select_surrounding_handles(Scene *scene, Sequence *test) /* XXX BRING BACK */ 00069 { 00070 Sequence *neighbor; 00071 00072 neighbor=find_neighboring_sequence(scene, test, SEQ_SIDE_LEFT, -1); 00073 if (neighbor) { 00074 neighbor->flag |= SELECT; 00075 recurs_sel_seq(neighbor); 00076 neighbor->flag |= SEQ_RIGHTSEL; 00077 } 00078 neighbor=find_neighboring_sequence(scene, test, SEQ_SIDE_RIGHT, -1); 00079 if (neighbor) { 00080 neighbor->flag |= SELECT; 00081 recurs_sel_seq(neighbor); 00082 neighbor->flag |= SEQ_LEFTSEL; 00083 } 00084 test->flag |= SELECT; 00085 } 00086 00087 /* used for mouse selection and for SEQUENCER_OT_select_active_side() */ 00088 static void select_active_side(ListBase *seqbase, int sel_side, int channel, int frame) 00089 { 00090 Sequence *seq; 00091 00092 for(seq= seqbase->first; seq; seq=seq->next) { 00093 if(channel==seq->machine) { 00094 switch(sel_side) { 00095 case SEQ_SIDE_LEFT: 00096 if (frame > (seq->startdisp)) { 00097 seq->flag &= ~(SEQ_RIGHTSEL|SEQ_LEFTSEL); 00098 seq->flag |= SELECT; 00099 } 00100 break; 00101 case SEQ_SIDE_RIGHT: 00102 if (frame < (seq->startdisp)) { 00103 seq->flag &= ~(SEQ_RIGHTSEL|SEQ_LEFTSEL); 00104 seq->flag |= SELECT; 00105 } 00106 break; 00107 case SEQ_SIDE_BOTH: 00108 seq->flag &= ~(SEQ_RIGHTSEL|SEQ_LEFTSEL); 00109 break; 00110 } 00111 } 00112 } 00113 } 00114 00115 /* used for mouse selection and for SEQUENCER_OT_select_active_side() */ 00116 static void select_linked_time(ListBase *seqbase, Sequence *seq_link) 00117 { 00118 Sequence *seq; 00119 00120 for(seq= seqbase->first; seq; seq=seq->next) { 00121 if(seq_link->machine != seq->machine) { 00122 int left_match = (seq->startdisp == seq_link->startdisp) ? 1:0; 00123 int right_match = (seq->enddisp == seq_link->enddisp) ? 1:0; 00124 00125 if(left_match && right_match) { 00126 /* a direct match, copy the selection settinhs */ 00127 seq->flag &= ~(SELECT|SEQ_LEFTSEL|SEQ_RIGHTSEL); 00128 seq->flag |= seq_link->flag & (SELECT|SEQ_LEFTSEL|SEQ_RIGHTSEL); 00129 00130 recurs_sel_seq(seq); 00131 } 00132 else if(seq_link->flag & SELECT && (left_match || right_match)) { 00133 00134 /* clear for reselection */ 00135 seq->flag &= ~(SEQ_LEFTSEL|SEQ_RIGHTSEL); 00136 00137 if(left_match && seq_link->flag & SEQ_LEFTSEL) 00138 seq->flag |= SELECT|SEQ_LEFTSEL; 00139 00140 if(right_match && seq_link->flag & SEQ_RIGHTSEL) 00141 seq->flag |= SELECT|SEQ_RIGHTSEL; 00142 00143 recurs_sel_seq(seq); 00144 } 00145 } 00146 } 00147 } 00148 00149 #if 0 // BRING BACK 00150 void select_surround_from_last(Scene *scene) 00151 { 00152 Sequence *seq=get_last_seq(scene); 00153 00154 if (seq==NULL) 00155 return; 00156 00157 select_surrounding_handles(scene, seq); 00158 } 00159 #endif 00160 00161 00162 static void UNUSED_FUNCTION(select_single_seq)(Scene *scene, Sequence *seq, int deselect_all) /* BRING BACK */ 00163 { 00164 Editing *ed= seq_give_editing(scene, FALSE); 00165 00166 if(deselect_all) 00167 deselect_all_seq(scene); 00168 seq_active_set(scene, seq); 00169 00170 if((seq->type==SEQ_IMAGE) || (seq->type==SEQ_MOVIE)) { 00171 if(seq->strip) 00172 BLI_strncpy(ed->act_imagedir, seq->strip->dir, FILE_MAXDIR); 00173 } 00174 else if(seq->type==SEQ_SOUND) { 00175 if(seq->strip) 00176 BLI_strncpy(ed->act_sounddir, seq->strip->dir, FILE_MAXDIR); 00177 } 00178 seq->flag|= SELECT; 00179 recurs_sel_seq(seq); 00180 } 00181 00182 #if 0 00183 static void select_neighbor_from_last(Scene *scene, int lr) 00184 { 00185 Sequence *seq= seq_active_get(scene); 00186 Sequence *neighbor; 00187 int change = 0; 00188 if (seq) { 00189 neighbor=find_neighboring_sequence(scene, seq, lr, -1); 00190 if (neighbor) { 00191 switch (lr) { 00192 case SEQ_SIDE_LEFT: 00193 neighbor->flag |= SELECT; 00194 recurs_sel_seq(neighbor); 00195 neighbor->flag |= SEQ_RIGHTSEL; 00196 seq->flag |= SEQ_LEFTSEL; 00197 break; 00198 case SEQ_SIDE_RIGHT: 00199 neighbor->flag |= SELECT; 00200 recurs_sel_seq(neighbor); 00201 neighbor->flag |= SEQ_LEFTSEL; 00202 seq->flag |= SEQ_RIGHTSEL; 00203 break; 00204 } 00205 seq->flag |= SELECT; 00206 change = 1; 00207 } 00208 } 00209 if (change) { 00210 } 00211 } 00212 #endif 00213 00214 /* (de)select operator */ 00215 static int sequencer_de_select_all_exec(bContext *C, wmOperator *op) 00216 { 00217 int action = RNA_enum_get(op->ptr, "action"); 00218 00219 Scene *scene = CTX_data_scene(C); 00220 Editing *ed = seq_give_editing(scene, FALSE); 00221 Sequence *seq; 00222 00223 if (action == SEL_TOGGLE) { 00224 action = SEL_SELECT; 00225 for (seq = ed->seqbasep->first; seq; seq = seq->next) { 00226 if (seq->flag & SEQ_ALLSEL) { 00227 action = SEL_DESELECT; 00228 break; 00229 } 00230 } 00231 } 00232 00233 for (seq = ed->seqbasep->first; seq; seq = seq->next) { 00234 switch (action) { 00235 case SEL_SELECT: 00236 seq->flag &= ~(SEQ_LEFTSEL + SEQ_RIGHTSEL); 00237 seq->flag |= SELECT; 00238 break; 00239 case SEL_DESELECT: 00240 seq->flag &= ~SEQ_ALLSEL; 00241 break; 00242 case SEL_INVERT: 00243 if (seq->flag & SEQ_ALLSEL) { 00244 seq->flag &= ~SEQ_ALLSEL; 00245 } 00246 else { 00247 seq->flag &= ~(SEQ_LEFTSEL + SEQ_RIGHTSEL); 00248 seq->flag |= SELECT; 00249 } 00250 break; 00251 } 00252 } 00253 00254 WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene); 00255 00256 return OPERATOR_FINISHED; 00257 } 00258 00259 void SEQUENCER_OT_select_all(struct wmOperatorType *ot) 00260 { 00261 /* identifiers */ 00262 ot->name= "Select or Deselect All"; 00263 ot->idname= "SEQUENCER_OT_select_all"; 00264 ot->description="Select or deselect all strips"; 00265 00266 /* api callbacks */ 00267 ot->exec= sequencer_de_select_all_exec; 00268 ot->poll= sequencer_edit_poll; 00269 00270 /* flags */ 00271 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00272 00273 WM_operator_properties_select_all(ot); 00274 } 00275 00276 00277 /* (de)select operator */ 00278 static int sequencer_select_inverse_exec(bContext *C, wmOperator *UNUSED(op)) 00279 { 00280 Scene *scene= CTX_data_scene(C); 00281 Editing *ed= seq_give_editing(scene, FALSE); 00282 Sequence *seq; 00283 00284 for(seq= ed->seqbasep->first; seq; seq=seq->next) { 00285 if (seq->flag & SELECT) { 00286 seq->flag &= ~SEQ_ALLSEL; 00287 } 00288 else { 00289 seq->flag &= ~(SEQ_LEFTSEL+SEQ_RIGHTSEL); 00290 seq->flag |= SELECT; 00291 } 00292 } 00293 00294 WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER|NA_SELECTED, scene); 00295 00296 return OPERATOR_FINISHED; 00297 } 00298 00299 void SEQUENCER_OT_select_inverse(struct wmOperatorType *ot) 00300 { 00301 /* identifiers */ 00302 ot->name= "Select Inverse"; 00303 ot->idname= "SEQUENCER_OT_select_inverse"; 00304 ot->description="Select unselected strips"; 00305 00306 /* api callbacks */ 00307 ot->exec= sequencer_select_inverse_exec; 00308 ot->poll= sequencer_edit_poll; 00309 00310 /* flags */ 00311 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00312 } 00313 00314 static int sequencer_select_invoke(bContext *C, wmOperator *op, wmEvent *event) 00315 { 00316 View2D *v2d= UI_view2d_fromcontext(C); 00317 Scene *scene= CTX_data_scene(C); 00318 Editing *ed= seq_give_editing(scene, FALSE); 00319 short extend= RNA_boolean_get(op->ptr, "extend"); 00320 short linked_handle= RNA_boolean_get(op->ptr, "linked_handle"); 00321 short left_right= RNA_boolean_get(op->ptr, "left_right"); 00322 short linked_time= RNA_boolean_get(op->ptr, "linked_time"); 00323 00324 Sequence *seq,*neighbor, *act_orig; 00325 int hand,sel_side; 00326 TimeMarker *marker; 00327 00328 if(ed==NULL) 00329 return OPERATOR_CANCELLED; 00330 00331 marker=find_nearest_marker(SCE_MARKERS, 1); //XXX - dummy function for now 00332 00333 seq= find_nearest_seq(scene, v2d, &hand, event->mval); 00334 00335 // XXX - not nice, Ctrl+RMB needs to do left_right only when not over a strip 00336 if(seq && linked_time && left_right) 00337 left_right= FALSE; 00338 00339 00340 if (marker) { 00341 int oldflag; 00342 /* select timeline marker */ 00343 if (extend) { 00344 oldflag= marker->flag; 00345 if (oldflag & SELECT) 00346 marker->flag &= ~SELECT; 00347 else 00348 marker->flag |= SELECT; 00349 } 00350 else { 00351 /* deselect_markers(0, 0); */ /* XXX, in 2.4x, seq selection used to deselect all, need to re-thnik this for 2.5 */ 00352 marker->flag |= SELECT; 00353 } 00354 00355 } else if (left_right) { 00356 /* use different logic for this */ 00357 float x; 00358 deselect_all_seq(scene); 00359 UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &x, NULL); 00360 00361 SEQP_BEGIN(ed, seq) { 00362 if (x < CFRA) { 00363 if(seq->enddisp < CFRA) { 00364 seq->flag |= SELECT; 00365 recurs_sel_seq(seq); 00366 } 00367 } 00368 else { 00369 if(seq->startdisp > CFRA) { 00370 seq->flag |= SELECT; 00371 recurs_sel_seq(seq); 00372 } 00373 } 00374 } 00375 SEQ_END 00376 00377 { 00378 SpaceSeq *sseq= CTX_wm_space_seq(C); 00379 if (sseq && sseq->flag & SEQ_MARKER_TRANS) { 00380 TimeMarker *tmarker; 00381 00382 for (tmarker= scene->markers.first; tmarker; tmarker= tmarker->next) { 00383 if( ((x < CFRA) && tmarker->frame < CFRA) || 00384 ((x >= CFRA) && tmarker->frame >= CFRA) 00385 ) { 00386 tmarker->flag |= SELECT; 00387 } 00388 else { 00389 tmarker->flag &= ~SELECT; 00390 } 00391 } 00392 } 00393 } 00394 } else { 00395 // seq= find_nearest_seq(scene, v2d, &hand, mval); 00396 00397 act_orig= ed->act_seq; 00398 00399 if(extend == 0 && linked_handle==0) 00400 deselect_all_seq(scene); 00401 00402 if(seq) { 00403 seq_active_set(scene, seq); 00404 00405 if ((seq->type == SEQ_IMAGE) || (seq->type == SEQ_MOVIE)) { 00406 if(seq->strip) { 00407 BLI_strncpy(ed->act_imagedir, seq->strip->dir, FILE_MAXDIR); 00408 } 00409 } else 00410 if (seq->type == SEQ_SOUND) { 00411 if(seq->strip) { 00412 BLI_strncpy(ed->act_sounddir, seq->strip->dir, FILE_MAXDIR); 00413 } 00414 } 00415 00416 if(extend && (seq->flag & SELECT) && ed->act_seq == act_orig ) { 00417 switch(hand) { 00418 case SEQ_SIDE_NONE: 00419 if (linked_handle==0) 00420 seq->flag &= ~SEQ_ALLSEL; 00421 break; 00422 case SEQ_SIDE_LEFT: 00423 seq->flag ^= SEQ_LEFTSEL; 00424 break; 00425 case SEQ_SIDE_RIGHT: 00426 seq->flag ^= SEQ_RIGHTSEL; 00427 break; 00428 } 00429 } 00430 else { 00431 seq->flag |= SELECT; 00432 if(hand==SEQ_SIDE_LEFT) seq->flag |= SEQ_LEFTSEL; 00433 if(hand==SEQ_SIDE_RIGHT) seq->flag |= SEQ_RIGHTSEL; 00434 } 00435 00436 /* On Alt selection, select the strip and bordering handles */ 00437 if (linked_handle && !ELEM(hand, SEQ_SIDE_LEFT, SEQ_SIDE_RIGHT)) { 00438 if(extend==0) deselect_all_seq(scene); 00439 seq->flag |= SELECT; 00440 select_surrounding_handles(scene, seq); 00441 } 00442 else if (linked_handle && ELEM(hand, SEQ_SIDE_LEFT, SEQ_SIDE_RIGHT) && (seq->flag & SELECT)) { 00443 /* 00444 * First click selects adjacent handles on that side. 00445 * Second click selects all strips in that direction. 00446 * If there are no adjacent strips, it just selects all in that direction. 00447 */ 00448 sel_side= hand; 00449 neighbor=find_neighboring_sequence(scene, seq, sel_side, -1); 00450 if (neighbor) { 00451 switch (sel_side) { 00452 case SEQ_SIDE_LEFT: 00453 if ((seq->flag & SEQ_LEFTSEL) && (neighbor->flag & SEQ_RIGHTSEL)) { 00454 if(extend==0) deselect_all_seq(scene); 00455 seq->flag |= SELECT; 00456 00457 select_active_side(ed->seqbasep, SEQ_SIDE_LEFT, seq->machine, seq->startdisp); 00458 } else { 00459 if(extend==0) deselect_all_seq(scene); 00460 seq->flag |= SELECT; 00461 00462 neighbor->flag |= SELECT; 00463 recurs_sel_seq(neighbor); 00464 neighbor->flag |= SEQ_RIGHTSEL; 00465 seq->flag |= SEQ_LEFTSEL; 00466 } 00467 break; 00468 case SEQ_SIDE_RIGHT: 00469 if ((seq->flag & SEQ_RIGHTSEL) && (neighbor->flag & SEQ_LEFTSEL)) { 00470 if(extend==0) deselect_all_seq(scene); 00471 seq->flag |= SELECT; 00472 00473 select_active_side(ed->seqbasep, SEQ_SIDE_RIGHT, seq->machine, seq->startdisp); 00474 } else { 00475 if(extend==0) deselect_all_seq(scene); 00476 seq->flag |= SELECT; 00477 00478 neighbor->flag |= SELECT; 00479 recurs_sel_seq(neighbor); 00480 neighbor->flag |= SEQ_LEFTSEL; 00481 seq->flag |= SEQ_RIGHTSEL; 00482 } 00483 break; 00484 } 00485 } else { 00486 if(extend==0) deselect_all_seq(scene); 00487 select_active_side(ed->seqbasep, sel_side, seq->machine, seq->startdisp); 00488 } 00489 } 00490 recurs_sel_seq(seq); 00491 00492 if(linked_time) { 00493 select_linked_time(ed->seqbasep, seq); 00494 } 00495 } 00496 } 00497 00498 /* marker transform */ 00499 #if 0 // XXX probably need to redo this differently for 2.5 00500 if (marker) { 00501 int mval[2], xo, yo; 00502 // getmouseco_areawin(mval); 00503 xo= mval[0]; 00504 yo= mval[1]; 00505 00506 while(get_mbut()) { 00507 // getmouseco_areawin(mval); 00508 if(abs(mval[0]-xo)+abs(mval[1]-yo) > 4) { 00509 transform_markers('g', 0); 00510 return; 00511 } 00512 } 00513 } 00514 #endif 00515 00516 WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER|NA_SELECTED, scene); 00517 00518 /* allowing tweaks */ 00519 return OPERATOR_FINISHED|OPERATOR_PASS_THROUGH; 00520 } 00521 00522 void SEQUENCER_OT_select(wmOperatorType *ot) 00523 { 00524 /* identifiers */ 00525 ot->name= "Activate/Select"; 00526 ot->idname= "SEQUENCER_OT_select"; 00527 ot->description="Select a strip (last selected becomes the \"active strip\")"; 00528 00529 /* api callbacks */ 00530 ot->invoke= sequencer_select_invoke; 00531 ot->poll= ED_operator_sequencer_active; 00532 00533 /* flags */ 00534 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00535 00536 /* properties */ 00537 RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend the selection"); 00538 RNA_def_boolean(ot->srna, "linked_handle", 0, "Linked Handle", "Select handles next to the active strip"); 00539 /* for animation this is an enum but atm having an enum isnt useful for us */ 00540 RNA_def_boolean(ot->srna, "left_right", 0, "Left/Right", "Select based on the current frame side the cursor is on"); 00541 RNA_def_boolean(ot->srna, "linked_time", 0, "Linked Time", "Select other strips at the same time"); 00542 } 00543 00544 00545 00546 00547 /* run recursively to select linked */ 00548 static int select_more_less_seq__internal(Scene *scene, int sel, int linked) 00549 { 00550 Editing *ed= seq_give_editing(scene, FALSE); 00551 Sequence *seq, *neighbor; 00552 int change=0; 00553 int isel; 00554 00555 if(ed==NULL) return 0; 00556 00557 if (sel) { 00558 sel = SELECT; 00559 isel = 0; 00560 } else { 00561 sel = 0; 00562 isel = SELECT; 00563 } 00564 00565 if (!linked) { 00566 /* if not linked we only want to touch each seq once, newseq */ 00567 for(seq= ed->seqbasep->first; seq; seq= seq->next) { 00568 seq->tmp = NULL; 00569 } 00570 } 00571 00572 for(seq= ed->seqbasep->first; seq; seq= seq->next) { 00573 if((int)(seq->flag & SELECT) == sel) { 00574 if ((linked==0 && seq->tmp)==0) { 00575 /* only get unselected nabours */ 00576 neighbor = find_neighboring_sequence(scene, seq, SEQ_SIDE_LEFT, isel); 00577 if (neighbor) { 00578 if (sel) {neighbor->flag |= SELECT; recurs_sel_seq(neighbor);} 00579 else neighbor->flag &= ~SELECT; 00580 if (linked==0) neighbor->tmp = (Sequence *)1; 00581 change = 1; 00582 } 00583 neighbor = find_neighboring_sequence(scene, seq, SEQ_SIDE_RIGHT, isel); 00584 if (neighbor) { 00585 if (sel) {neighbor->flag |= SELECT; recurs_sel_seq(neighbor);} 00586 else neighbor->flag &= ~SELECT; 00587 if (linked==0) neighbor->tmp = (void *)1; 00588 change = 1; 00589 } 00590 } 00591 } 00592 } 00593 00594 return change; 00595 } 00596 00597 00598 00599 /* select more operator */ 00600 static int sequencer_select_more_exec(bContext *C, wmOperator *UNUSED(op)) 00601 { 00602 Scene *scene= CTX_data_scene(C); 00603 00604 if(!select_more_less_seq__internal(scene, 0, 0)) 00605 return OPERATOR_CANCELLED; 00606 00607 WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER|NA_SELECTED, scene); 00608 00609 return OPERATOR_FINISHED; 00610 } 00611 00612 void SEQUENCER_OT_select_more(wmOperatorType *ot) 00613 { 00614 /* identifiers */ 00615 ot->name= "Select More"; 00616 ot->idname= "SEQUENCER_OT_select_more"; 00617 ot->description="Select more strips adjacent to the current selection"; 00618 00619 /* api callbacks */ 00620 ot->exec= sequencer_select_more_exec; 00621 ot->poll= sequencer_edit_poll; 00622 00623 /* flags */ 00624 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00625 00626 /* properties */ 00627 } 00628 00629 00630 /* select less operator */ 00631 static int sequencer_select_less_exec(bContext *C, wmOperator *UNUSED(op)) 00632 { 00633 Scene *scene= CTX_data_scene(C); 00634 00635 if(!select_more_less_seq__internal(scene, 1, 0)) 00636 return OPERATOR_CANCELLED; 00637 00638 WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER|NA_SELECTED, scene); 00639 00640 return OPERATOR_FINISHED; 00641 } 00642 00643 void SEQUENCER_OT_select_less(wmOperatorType *ot) 00644 { 00645 /* identifiers */ 00646 ot->name= "Select Less"; 00647 ot->idname= "SEQUENCER_OT_select_less"; 00648 ot->description="Shrink the current selection of adjacent selected strips"; 00649 00650 /* api callbacks */ 00651 ot->exec= sequencer_select_less_exec; 00652 ot->poll= sequencer_edit_poll; 00653 00654 /* flags */ 00655 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00656 00657 /* properties */ 00658 } 00659 00660 00661 /* select pick linked operator (uses the mouse) */ 00662 static int sequencer_select_linked_pick_invoke(bContext *C, wmOperator *op, wmEvent *event) 00663 { 00664 Scene *scene= CTX_data_scene(C); 00665 View2D *v2d= UI_view2d_fromcontext(C); 00666 00667 short extend= RNA_boolean_get(op->ptr, "extend"); 00668 00669 Sequence *mouse_seq; 00670 int selected, hand; 00671 00672 /* this works like UV, not mesh */ 00673 mouse_seq= find_nearest_seq(scene, v2d, &hand, event->mval); 00674 if (!mouse_seq) 00675 return OPERATOR_FINISHED; /* user error as with mesh?? */ 00676 00677 if (extend==0) 00678 deselect_all_seq(scene); 00679 00680 mouse_seq->flag |= SELECT; 00681 recurs_sel_seq(mouse_seq); 00682 00683 selected = 1; 00684 while (selected) { 00685 selected = select_more_less_seq__internal(scene, 1, 1); 00686 } 00687 00688 WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER|NA_SELECTED, scene); 00689 00690 return OPERATOR_FINISHED; 00691 } 00692 00693 void SEQUENCER_OT_select_linked_pick(wmOperatorType *ot) 00694 { 00695 /* identifiers */ 00696 ot->name= "Select pick linked"; 00697 ot->idname= "SEQUENCER_OT_select_linked_pick"; 00698 ot->description="Select a chain of linked strips nearest to the mouse pointer"; 00699 00700 /* api callbacks */ 00701 ot->invoke= sequencer_select_linked_pick_invoke; 00702 ot->poll= ED_operator_sequencer_active; 00703 00704 /* flags */ 00705 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00706 00707 /* properties */ 00708 RNA_def_boolean(ot->srna, "extend", 0, "Extend", "extend the selection"); 00709 } 00710 00711 00712 /* select linked operator */ 00713 static int sequencer_select_linked_exec(bContext *C, wmOperator *UNUSED(op)) 00714 { 00715 Scene *scene= CTX_data_scene(C); 00716 int selected; 00717 00718 selected = 1; 00719 while (selected) { 00720 selected = select_more_less_seq__internal(scene, 1, 1); 00721 } 00722 00723 WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER|NA_SELECTED, scene); 00724 00725 return OPERATOR_FINISHED; 00726 } 00727 00728 void SEQUENCER_OT_select_linked(wmOperatorType *ot) 00729 { 00730 /* identifiers */ 00731 ot->name= "Select linked"; 00732 ot->idname= "SEQUENCER_OT_select_linked"; 00733 ot->description="Select all strips adjacent to the current selection"; 00734 00735 /* api callbacks */ 00736 ot->exec= sequencer_select_linked_exec; 00737 ot->poll= sequencer_edit_poll; 00738 00739 /* flags */ 00740 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00741 00742 /* properties */ 00743 } 00744 00745 00746 /* select handles operator */ 00747 static int sequencer_select_handles_exec(bContext *C, wmOperator *op) 00748 { 00749 Scene *scene= CTX_data_scene(C); 00750 Editing *ed= seq_give_editing(scene, 0); 00751 Sequence *seq; 00752 int sel_side= RNA_enum_get(op->ptr, "side"); 00753 00754 00755 for(seq= ed->seqbasep->first; seq; seq=seq->next) { 00756 if (seq->flag & SELECT) { 00757 switch(sel_side) { 00758 case SEQ_SIDE_LEFT: 00759 seq->flag &= ~SEQ_RIGHTSEL; 00760 seq->flag |= SEQ_LEFTSEL; 00761 break; 00762 case SEQ_SIDE_RIGHT: 00763 seq->flag &= ~SEQ_LEFTSEL; 00764 seq->flag |= SEQ_RIGHTSEL; 00765 break; 00766 case SEQ_SIDE_BOTH: 00767 seq->flag |= SEQ_LEFTSEL+SEQ_RIGHTSEL; 00768 break; 00769 } 00770 } 00771 } 00772 00773 WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER|NA_SELECTED, scene); 00774 00775 return OPERATOR_FINISHED; 00776 } 00777 00778 void SEQUENCER_OT_select_handles(wmOperatorType *ot) 00779 { 00780 /* identifiers */ 00781 ot->name= "Select Handles"; 00782 ot->idname= "SEQUENCER_OT_select_handles"; 00783 ot->description="Select manipulator handles on the sides of the selected strip"; 00784 00785 /* api callbacks */ 00786 ot->exec= sequencer_select_handles_exec; 00787 ot->poll= sequencer_edit_poll; 00788 00789 /* flags */ 00790 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00791 00792 /* properties */ 00793 RNA_def_enum(ot->srna, "side", prop_side_types, SEQ_SIDE_BOTH, "Side", "The side of the handle that is selected"); 00794 } 00795 00796 /* select side operator */ 00797 static int sequencer_select_active_side_exec(bContext *C, wmOperator *op) 00798 { 00799 Scene *scene= CTX_data_scene(C); 00800 Editing *ed= seq_give_editing(scene, 0); 00801 Sequence *seq_act= seq_active_get(scene); 00802 00803 if (ed==NULL || seq_act==NULL) 00804 return OPERATOR_CANCELLED; 00805 00806 seq_act->flag |= SELECT; 00807 00808 select_active_side(ed->seqbasep, RNA_enum_get(op->ptr, "side"), seq_act->machine, seq_act->startdisp); 00809 00810 WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER|NA_SELECTED, scene); 00811 00812 return OPERATOR_FINISHED; 00813 } 00814 00815 void SEQUENCER_OT_select_active_side(wmOperatorType *ot) 00816 { 00817 /* identifiers */ 00818 ot->name= "Select Active Side"; 00819 ot->idname= "SEQUENCER_OT_select_active_side"; 00820 ot->description="Select strips on the nominated side of the active strip"; 00821 00822 /* api callbacks */ 00823 ot->exec= sequencer_select_active_side_exec; 00824 ot->poll= sequencer_edit_poll; 00825 00826 /* flags */ 00827 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00828 00829 /* properties */ 00830 RNA_def_enum(ot->srna, "side", prop_side_types, SEQ_SIDE_BOTH, "Side", "The side of the handle that is selected"); 00831 } 00832 00833 00834 /* borderselect operator */ 00835 static int sequencer_borderselect_exec(bContext *C, wmOperator *op) 00836 { 00837 Scene *scene= CTX_data_scene(C); 00838 Editing *ed= seq_give_editing(scene, FALSE); 00839 View2D *v2d= UI_view2d_fromcontext(C); 00840 00841 Sequence *seq; 00842 rcti rect; 00843 rctf rectf, rq; 00844 short selecting = (RNA_int_get(op->ptr, "gesture_mode")==GESTURE_MODAL_SELECT); 00845 int extend = RNA_boolean_get(op->ptr, "extend"); 00846 int mval[2]; 00847 00848 if(ed==NULL) 00849 return OPERATOR_CANCELLED; 00850 00851 rect.xmin= RNA_int_get(op->ptr, "xmin"); 00852 rect.ymin= RNA_int_get(op->ptr, "ymin"); 00853 rect.xmax= RNA_int_get(op->ptr, "xmax"); 00854 rect.ymax= RNA_int_get(op->ptr, "ymax"); 00855 00856 mval[0]= rect.xmin; 00857 mval[1]= rect.ymin; 00858 UI_view2d_region_to_view(v2d, mval[0], mval[1], &rectf.xmin, &rectf.ymin); 00859 mval[0]= rect.xmax; 00860 mval[1]= rect.ymax; 00861 UI_view2d_region_to_view(v2d, mval[0], mval[1], &rectf.xmax, &rectf.ymax); 00862 00863 for(seq= ed->seqbasep->first; seq; seq= seq->next) { 00864 seq_rectf(seq, &rq); 00865 00866 if(BLI_isect_rctf(&rq, &rectf, NULL)) { 00867 if(selecting) seq->flag |= SELECT; 00868 else seq->flag &= ~SEQ_ALLSEL; 00869 recurs_sel_seq(seq); 00870 } 00871 else if(!extend) { 00872 seq->flag &= ~SEQ_ALLSEL; 00873 recurs_sel_seq(seq); 00874 } 00875 } 00876 00877 WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER|NA_SELECTED, scene); 00878 00879 return OPERATOR_FINISHED; 00880 } 00881 00882 00883 /* ****** Border Select ****** */ 00884 void SEQUENCER_OT_select_border(wmOperatorType *ot) 00885 { 00886 /* identifiers */ 00887 ot->name= "Border Select"; 00888 ot->idname= "SEQUENCER_OT_select_border"; 00889 ot->description="Enable border select mode"; 00890 00891 /* api callbacks */ 00892 ot->invoke= WM_border_select_invoke; 00893 ot->exec= sequencer_borderselect_exec; 00894 ot->modal= WM_border_select_modal; 00895 ot->cancel= WM_border_select_cancel; 00896 00897 ot->poll= ED_operator_sequencer_active; 00898 00899 /* flags */ 00900 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00901 00902 /* rna */ 00903 WM_operator_properties_gesture_border(ot, TRUE); 00904 } 00905 00906 /* ****** Selected Grouped ****** */ 00907 00908 static EnumPropertyItem sequencer_prop_select_grouped_types[] = { 00909 {1, "TYPE", 0, "Type", "Shared strip type"}, 00910 {2, "TYPE_BASIC", 0, "Global Type", "All strips of same basic type (Graphical or Sound)"}, 00911 {3, "TYPE_EFFECT", 0, "Effect Type", 00912 "Shared strip effect type (if active strip is not an effect one, select all non-effect strips)"}, 00913 {4, "DATA", 0, "Data", "Shared data (scene, image, sound, etc.)"}, 00914 {5, "EFFECT", 0, "Effect", "Shared effects"}, 00915 {6, "EFFECT_LINK", 0, "Effect/Linked", 00916 "Other strips affected by the active one (sharing some time, and below or effect-assigned)"}, 00917 {7, "OVERLAP", 0, "Overlap", "Overlapping time"}, 00918 {0, NULL, 0, NULL, NULL} 00919 }; 00920 00921 #define SEQ_IS_SOUND(_seq) ((_seq->type & SEQ_SOUND) && !(_seq->type & SEQ_EFFECT)) 00922 00923 #define SEQ_IS_EFFECT(_seq) (_seq->type & SEQ_EFFECT) 00924 00925 #define SEQ_USE_DATA(_seq) (_seq->type == SEQ_SCENE || SEQ_HAS_PATH(_seq)) 00926 00927 static short select_grouped_type(Editing *ed, Sequence *actseq) 00928 { 00929 Sequence *seq; 00930 short changed = FALSE; 00931 00932 SEQP_BEGIN(ed, seq) { 00933 if (seq->type == actseq->type) { 00934 seq->flag |= SELECT; 00935 changed = TRUE; 00936 } 00937 } 00938 SEQ_END; 00939 00940 return changed; 00941 } 00942 00943 static short select_grouped_type_basic(Editing *ed, Sequence *actseq) 00944 { 00945 Sequence *seq; 00946 short changed = FALSE; 00947 short is_sound = SEQ_IS_SOUND(actseq); 00948 00949 SEQP_BEGIN(ed, seq) { 00950 if (is_sound ? SEQ_IS_SOUND(seq) : !SEQ_IS_SOUND(seq)) { 00951 seq->flag |= SELECT; 00952 changed = TRUE; 00953 } 00954 } 00955 SEQ_END; 00956 00957 return changed; 00958 } 00959 00960 static short select_grouped_type_effect(Editing *ed, Sequence *actseq) 00961 { 00962 Sequence *seq; 00963 short changed = FALSE; 00964 short is_effect = SEQ_IS_EFFECT(actseq); 00965 00966 SEQP_BEGIN(ed, seq) { 00967 if (is_effect ? SEQ_IS_EFFECT(seq) : !SEQ_IS_EFFECT(seq)) { 00968 seq->flag |= SELECT; 00969 changed = TRUE; 00970 } 00971 } 00972 SEQ_END; 00973 00974 return changed; 00975 } 00976 00977 static short select_grouped_data(Editing *ed, Sequence *actseq) 00978 { 00979 Sequence *seq; 00980 short changed = FALSE; 00981 Scene *sce = actseq->scene; 00982 char *dir = actseq->strip ? actseq->strip->dir : NULL; 00983 00984 if (!SEQ_USE_DATA(actseq)) 00985 return changed; 00986 00987 if (SEQ_HAS_PATH(actseq) && dir) { 00988 SEQP_BEGIN(ed, seq) { 00989 if (SEQ_HAS_PATH(seq) && seq->strip && strcmp(seq->strip->dir, dir) == 0) { 00990 seq->flag |= SELECT; 00991 changed = TRUE; 00992 } 00993 } 00994 SEQ_END; 00995 } 00996 else { 00997 SEQP_BEGIN(ed, seq) { 00998 if (seq->type == SEQ_SCENE && seq->scene == sce) { 00999 seq->flag |= SELECT; 01000 changed = TRUE; 01001 } 01002 } 01003 SEQ_END; 01004 } 01005 01006 return changed; 01007 } 01008 01009 static short select_grouped_effect(Editing *ed, Sequence *actseq) 01010 { 01011 Sequence *seq; 01012 short changed = FALSE; 01013 short effects[SEQ_EFFECT_MAX+1]; 01014 int i; 01015 01016 for (i = 0; i <= SEQ_EFFECT_MAX; i++) 01017 effects[i] = FALSE; 01018 01019 SEQP_BEGIN(ed, seq) { 01020 if (ELEM3(actseq, seq->seq1, seq->seq2, seq->seq3)) { 01021 effects[seq->type] = TRUE; 01022 } 01023 } 01024 SEQ_END; 01025 01026 SEQP_BEGIN(ed, seq) { 01027 if (effects[seq->type]) { 01028 if(seq->seq1) seq->seq1->flag |= SELECT; 01029 if(seq->seq2) seq->seq2->flag |= SELECT; 01030 if(seq->seq3) seq->seq3->flag |= SELECT; 01031 changed = TRUE; 01032 } 01033 } 01034 SEQ_END; 01035 01036 return changed; 01037 } 01038 01039 static short select_grouped_time_overlap(Editing *ed, Sequence *actseq) 01040 { 01041 Sequence *seq; 01042 short changed = FALSE; 01043 01044 SEQP_BEGIN(ed, seq) { 01045 if (!((seq->startdisp >= actseq->enddisp) || (seq->enddisp < actseq->startdisp))) { 01046 seq->flag |= SELECT; 01047 changed = TRUE; 01048 } 01049 } 01050 SEQ_END; 01051 01052 return changed; 01053 } 01054 01055 static short select_grouped_effect_link(Editing *ed, Sequence *actseq) 01056 { 01057 Sequence *seq = NULL; 01058 short changed = FALSE; 01059 short is_audio = ((actseq->type == SEQ_META) || SEQ_IS_SOUND(actseq)); 01060 int startdisp = actseq->startdisp; 01061 int enddisp = actseq->enddisp; 01062 int machine = actseq->machine; 01063 SeqIterator iter; 01064 01065 SEQP_BEGIN(ed, seq) { 01066 seq->tmp= NULL; 01067 } 01068 SEQ_END; 01069 01070 actseq->tmp= SET_INT_IN_POINTER(TRUE); 01071 01072 for(seq_begin(ed, &iter, 1); iter.valid; seq_next(&iter)) { 01073 seq = iter.seq; 01074 01075 /* Ignore all seqs already selected! */ 01076 /* Ignore all seqs not sharing some time with active one. */ 01077 /* Ignore all seqs of incompatible types (audio vs video). */ 01078 if ((seq->flag & SELECT) || (seq->startdisp >= enddisp) || (seq->enddisp < startdisp) 01079 || (!is_audio && SEQ_IS_SOUND(seq)) 01080 || (is_audio && !((seq->type == SEQ_META) || SEQ_IS_SOUND(seq)))) 01081 continue; 01082 01083 /* If the seq is an effect one, we need extra cheking! */ 01084 if (SEQ_IS_EFFECT(seq) && ((seq->seq1 && seq->seq1->tmp) || 01085 (seq->seq2 && seq->seq2->tmp) || 01086 (seq->seq3 && seq->seq3->tmp))) 01087 { 01088 if (startdisp > seq->startdisp) startdisp = seq->startdisp; 01089 if (enddisp < seq->enddisp) enddisp = seq->enddisp; 01090 if (machine < seq->machine) machine = seq->machine; 01091 01092 seq->tmp= SET_INT_IN_POINTER(TRUE); 01093 01094 seq->flag |= SELECT; 01095 changed = TRUE; 01096 01097 /* Unfortunately, we must restart checks from the begining. */ 01098 seq_end(&iter); 01099 seq_begin(ed, &iter, 1); 01100 } 01101 01102 /* Video strips bellow active one, or any strip for audio (order do no matters here!). */ 01103 else if (seq->machine < machine || is_audio) { 01104 seq->flag |= SELECT; 01105 changed = TRUE; 01106 } 01107 } 01108 seq_end(&iter); 01109 01110 return changed; 01111 } 01112 01113 static int sequencer_select_grouped_exec(bContext *C, wmOperator *op) 01114 { 01115 Scene *scene = CTX_data_scene(C); 01116 Editing *ed = seq_give_editing(scene, 0); 01117 Sequence *seq, *actseq = seq_active_get(scene); 01118 int type = RNA_enum_get(op->ptr, "type"); 01119 short changed = 0, extend; 01120 01121 extend = RNA_boolean_get(op->ptr, "extend"); 01122 01123 if (actseq == NULL) { 01124 BKE_report(op->reports, RPT_ERROR, "No Active Sequence!"); 01125 return OPERATOR_CANCELLED; 01126 } 01127 01128 if (extend == 0) { 01129 SEQP_BEGIN(ed, seq) { 01130 seq->flag &= ~SELECT; 01131 changed = TRUE; 01132 } 01133 SEQ_END; 01134 } 01135 01136 if(type==1) changed |= select_grouped_type(ed, actseq); 01137 else if(type==2) changed |= select_grouped_type_basic(ed, actseq); 01138 else if(type==3) changed |= select_grouped_type_effect(ed, actseq); 01139 else if(type==4) changed |= select_grouped_data(ed, actseq); 01140 else if(type==5) changed |= select_grouped_effect(ed, actseq); 01141 else if(type==6) changed |= select_grouped_effect_link(ed, actseq); 01142 else if(type==7) changed |= select_grouped_time_overlap(ed, actseq); 01143 01144 if (changed) { 01145 WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER|NA_SELECTED, scene); 01146 return OPERATOR_FINISHED; 01147 } 01148 01149 return OPERATOR_CANCELLED; 01150 } 01151 01152 void SEQUENCER_OT_select_grouped(wmOperatorType *ot) 01153 { 01154 /* identifiers */ 01155 ot->name = "Select Grouped"; 01156 ot->description = "Select all strips grouped by various properties"; 01157 ot->idname = "SEQUENCER_OT_select_grouped"; 01158 01159 /* api callbacks */ 01160 ot->invoke = WM_menu_invoke; 01161 ot->exec = sequencer_select_grouped_exec; 01162 ot->poll = sequencer_edit_poll; 01163 01164 /* flags */ 01165 ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; 01166 01167 /* properties */ 01168 RNA_def_boolean(ot->srna, "extend", FALSE, "Extend", "Extend selection instead of deselecting everything first"); 01169 ot->prop = RNA_def_enum(ot->srna, "type", sequencer_prop_select_grouped_types, 0, "Type", ""); 01170 } 01171