Blender  V2.59
sequencer_select.c
Go to the documentation of this file.
00001 /*
00002  *
00003  * ***** BEGIN GPL LICENSE BLOCK *****
00004  *
00005  * This program is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU General Public License
00007  * as published by the Free Software Foundation; either version 2
00008  * of the License, or (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software Foundation,
00017  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00018  *
00019  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00020  * All rights reserved.
00021  *
00022  * Contributor(s): Blender Foundation, 2003-2009, Campbell Barton
00023  *
00024  * ***** END GPL LICENSE BLOCK *****
00025  */
00026 
00032 #include <stdlib.h>
00033 #include <math.h>
00034 #include <string.h>
00035 
00036 #ifndef WIN32
00037 #include <unistd.h>
00038 #else
00039 #include <io.h>
00040 #endif
00041 #include <sys/types.h>
00042 
00043 #include "BLI_blenlib.h"
00044 #include "BLI_math.h"
00045 #include "BLI_utildefines.h"
00046 
00047 #include "DNA_scene_types.h"
00048 
00049 #include "BKE_context.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 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                         strncpy(ed->act_imagedir, seq->strip->dir, FILE_MAXDIR-1);
00173         }
00174         else if(seq->type==SEQ_SOUND) {
00175                 if(seq->strip)
00176                         strncpy(ed->act_sounddir, seq->strip->dir, FILE_MAXDIR-1);
00177         }
00178         seq->flag|= SELECT;
00179         recurs_sel_seq(seq);
00180 }
00181 
00182 // remove this function, replace with invert operator
00183 //void swap_select_seq(Scene *scene)
00184 #if 0
00185 static void select_neighbor_from_last(Scene *scene, int lr)
00186 {
00187         Sequence *seq= seq_active_get(scene);
00188         Sequence *neighbor;
00189         int change = 0;
00190         if (seq) {
00191                 neighbor=find_neighboring_sequence(scene, seq, lr, -1);
00192                 if (neighbor) {
00193                         switch (lr) {
00194                         case SEQ_SIDE_LEFT:
00195                                 neighbor->flag |= SELECT;
00196                                 recurs_sel_seq(neighbor);
00197                                 neighbor->flag |= SEQ_RIGHTSEL;
00198                                 seq->flag |= SEQ_LEFTSEL;
00199                                 break;
00200                         case SEQ_SIDE_RIGHT:
00201                                 neighbor->flag |= SELECT;
00202                                 recurs_sel_seq(neighbor);
00203                                 neighbor->flag |= SEQ_LEFTSEL;
00204                                 seq->flag |= SEQ_RIGHTSEL;
00205                                 break;
00206                         }
00207                 seq->flag |= SELECT;
00208                 change = 1;
00209                 }
00210         }
00211         if (change) {
00212         }
00213 }
00214 #endif
00215 
00216 /* (de)select operator */
00217 static int sequencer_deselect_exec(bContext *C, wmOperator *UNUSED(op))
00218 {
00219         Scene *scene= CTX_data_scene(C);
00220         Editing *ed= seq_give_editing(scene, FALSE);
00221         Sequence *seq;
00222         int desel = 0;
00223 
00224         for(seq= ed->seqbasep->first; seq; seq=seq->next) {
00225                 if(seq->flag & SEQ_ALLSEL) {
00226                         desel= 1;
00227                         break;
00228                 }
00229         }
00230 
00231         for(seq= ed->seqbasep->first; seq; seq=seq->next) {
00232                 if (desel) {
00233                         seq->flag &= ~SEQ_ALLSEL;
00234                 }
00235                 else {
00236                         seq->flag &= ~(SEQ_LEFTSEL+SEQ_RIGHTSEL);
00237                         seq->flag |= SELECT;
00238                 }
00239         }
00240 
00241         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER|NA_SELECTED, scene);
00242         
00243         return OPERATOR_FINISHED;
00244 }
00245 
00246 void SEQUENCER_OT_select_all_toggle(struct wmOperatorType *ot)
00247 {
00248         /* identifiers */
00249         ot->name= "Select or Deselect All";
00250         ot->idname= "SEQUENCER_OT_select_all_toggle";
00251         ot->description="Select or deselect all strips";
00252         
00253         /* api callbacks */
00254         ot->exec= sequencer_deselect_exec;
00255         ot->poll= sequencer_edit_poll;
00256         
00257         /* flags */
00258         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00259 }
00260 
00261 
00262 /* (de)select operator */
00263 static int sequencer_select_inverse_exec(bContext *C, wmOperator *UNUSED(op))
00264 {
00265         Scene *scene= CTX_data_scene(C);
00266         Editing *ed= seq_give_editing(scene, FALSE);
00267         Sequence *seq;
00268 
00269         for(seq= ed->seqbasep->first; seq; seq=seq->next) {
00270                 if (seq->flag & SELECT) {
00271                         seq->flag &= ~SEQ_ALLSEL;
00272                 }
00273                 else {
00274                         seq->flag &= ~(SEQ_LEFTSEL+SEQ_RIGHTSEL);
00275                         seq->flag |= SELECT;
00276                 }
00277         }
00278 
00279         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER|NA_SELECTED, scene);
00280         
00281         return OPERATOR_FINISHED;
00282 }
00283 
00284 void SEQUENCER_OT_select_inverse(struct wmOperatorType *ot)
00285 {
00286         /* identifiers */
00287         ot->name= "Select Inverse";
00288         ot->idname= "SEQUENCER_OT_select_inverse";
00289         ot->description="Select unselected strips";
00290         
00291         /* api callbacks */
00292         ot->exec= sequencer_select_inverse_exec;
00293         ot->poll= sequencer_edit_poll;
00294         
00295         /* flags */
00296         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00297 }
00298 
00299 static int sequencer_select_invoke(bContext *C, wmOperator *op, wmEvent *event)
00300 {
00301         View2D *v2d= UI_view2d_fromcontext(C);
00302         Scene *scene= CTX_data_scene(C);
00303         Editing *ed= seq_give_editing(scene, FALSE);
00304         short extend= RNA_boolean_get(op->ptr, "extend");
00305         short linked_handle= RNA_boolean_get(op->ptr, "linked_handle");
00306         short left_right= RNA_boolean_get(op->ptr, "left_right");
00307         short linked_time= RNA_boolean_get(op->ptr, "linked_time");
00308         
00309         Sequence *seq,*neighbor, *act_orig;
00310         int hand,sel_side;
00311         TimeMarker *marker;
00312 
00313         if(ed==NULL)
00314                 return OPERATOR_CANCELLED;
00315         
00316         marker=find_nearest_marker(SCE_MARKERS, 1); //XXX - dummy function for now
00317         
00318         seq= find_nearest_seq(scene, v2d, &hand, event->mval);
00319 
00320         // XXX - not nice, Ctrl+RMB needs to do left_right only when not over a strip
00321         if(seq && linked_time && left_right)
00322                 left_right= FALSE;
00323 
00324 
00325         if (marker) {
00326                 int oldflag;
00327                 /* select timeline marker */
00328                 if (extend) {
00329                         oldflag= marker->flag;
00330                         if (oldflag & SELECT)
00331                                 marker->flag &= ~SELECT;
00332                         else
00333                                 marker->flag |= SELECT;
00334                 }
00335                 else {
00336                         /* deselect_markers(0, 0); */ /* XXX, in 2.4x, seq selection used to deselect all, need to re-thnik this for 2.5 */
00337                         marker->flag |= SELECT;                         
00338                 }
00339                 
00340         } else if (left_right) {
00341                 /* use different logic for this */
00342                 float x;
00343                 deselect_all_seq(scene);
00344                 UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &x, NULL);
00345 
00346                 SEQP_BEGIN(ed, seq) {
00347                         if (x < CFRA) {
00348                                 if(seq->enddisp < CFRA) {
00349                                         seq->flag |= SELECT;
00350                                         recurs_sel_seq(seq);
00351                                 }
00352                         }
00353                         else {
00354                                 if(seq->startdisp > CFRA) {
00355                                         seq->flag |= SELECT;
00356                                         recurs_sel_seq(seq);
00357                                 }
00358                         }
00359                 }
00360                 SEQ_END
00361                 
00362                 {
00363                         SpaceSeq *sseq= CTX_wm_space_seq(C);
00364                         if (sseq && sseq->flag & SEQ_MARKER_TRANS) {
00365                                 TimeMarker *tmarker;
00366 
00367                                 for (tmarker= scene->markers.first; tmarker; tmarker= tmarker->next) {
00368                                         if(     ((x < CFRA) && tmarker->frame < CFRA) ||
00369                                                 ((x >= CFRA) && tmarker->frame >= CFRA)
00370                                         ) {
00371                                                 tmarker->flag |= SELECT;
00372                                         }
00373                                         else {
00374                                                 tmarker->flag &= ~SELECT;
00375                                         }
00376                                 }
00377                         }
00378                 }
00379         } else {
00380                 // seq= find_nearest_seq(scene, v2d, &hand, mval);
00381 
00382                 act_orig= ed->act_seq;
00383 
00384                 if(extend == 0 && linked_handle==0)
00385                         deselect_all_seq(scene);
00386         
00387                 if(seq) {
00388                         seq_active_set(scene, seq);
00389         
00390                         if ((seq->type == SEQ_IMAGE) || (seq->type == SEQ_MOVIE)) {
00391                                 if(seq->strip) {
00392                                         strncpy(ed->act_imagedir, seq->strip->dir, FILE_MAXDIR-1);
00393                                 }
00394                         } else
00395                         if (seq->type == SEQ_SOUND) {
00396                                 if(seq->strip) {
00397                                         strncpy(ed->act_sounddir, seq->strip->dir, FILE_MAXDIR-1);
00398                                 }
00399                         }
00400         
00401                         if(extend && (seq->flag & SELECT) && ed->act_seq == act_orig ) {
00402                                 switch(hand) {
00403                                 case SEQ_SIDE_NONE:
00404                                         if (linked_handle==0)
00405                                                 seq->flag &= ~SEQ_ALLSEL;
00406                                         break;
00407                                 case SEQ_SIDE_LEFT:
00408                                         seq->flag ^= SEQ_LEFTSEL;
00409                                         break;
00410                                 case SEQ_SIDE_RIGHT:
00411                                         seq->flag ^= SEQ_RIGHTSEL;
00412                                         break;
00413                                 }
00414                         }
00415                         else {
00416                                 seq->flag |= SELECT;
00417                                 if(hand==SEQ_SIDE_LEFT)         seq->flag |= SEQ_LEFTSEL;
00418                                 if(hand==SEQ_SIDE_RIGHT)        seq->flag |= SEQ_RIGHTSEL;
00419                         }
00420                         
00421                         /* On Alt selection, select the strip and bordering handles */
00422                         if (linked_handle && !ELEM(hand, SEQ_SIDE_LEFT, SEQ_SIDE_RIGHT)) {
00423                                 if(extend==0) deselect_all_seq(scene);
00424                                 seq->flag |= SELECT;
00425                                 select_surrounding_handles(scene, seq);
00426                         }
00427                         else if (linked_handle && ELEM(hand, SEQ_SIDE_LEFT, SEQ_SIDE_RIGHT) && (seq->flag & SELECT)) {
00428                                 /*
00429                                  * First click selects adjacent handles on that side.
00430                                  * Second click selects all strips in that direction.
00431                                  * If there are no adjacent strips, it just selects all in that direction.
00432                                  */
00433                                 sel_side= hand;
00434                                 neighbor=find_neighboring_sequence(scene, seq, sel_side, -1);
00435                                 if (neighbor) {
00436                                         switch (sel_side) {
00437                                         case SEQ_SIDE_LEFT:
00438                                                 if ((seq->flag & SEQ_LEFTSEL) && (neighbor->flag & SEQ_RIGHTSEL)) {
00439                                                         if(extend==0) deselect_all_seq(scene);
00440                                                         seq->flag |= SELECT;
00441                                                         
00442                                                         select_active_side(ed->seqbasep, SEQ_SIDE_LEFT, seq->machine, seq->startdisp);
00443                                                 } else {
00444                                                         if(extend==0) deselect_all_seq(scene);
00445                                                         seq->flag |= SELECT;
00446 
00447                                                         neighbor->flag |= SELECT;
00448                                                         recurs_sel_seq(neighbor);
00449                                                         neighbor->flag |= SEQ_RIGHTSEL;
00450                                                         seq->flag |= SEQ_LEFTSEL;
00451                                                 }
00452                                                 break;
00453                                         case SEQ_SIDE_RIGHT:
00454                                                 if ((seq->flag & SEQ_RIGHTSEL) && (neighbor->flag & SEQ_LEFTSEL)) {
00455                                                         if(extend==0) deselect_all_seq(scene);
00456                                                         seq->flag |= SELECT;
00457 
00458                                                         select_active_side(ed->seqbasep, SEQ_SIDE_RIGHT, seq->machine, seq->startdisp);
00459                                                 } else {
00460                                                         if(extend==0) deselect_all_seq(scene);
00461                                                         seq->flag |= SELECT;
00462 
00463                                                         neighbor->flag |= SELECT;
00464                                                         recurs_sel_seq(neighbor);
00465                                                         neighbor->flag |= SEQ_LEFTSEL;
00466                                                         seq->flag |= SEQ_RIGHTSEL;
00467                                                 }
00468                                                 break;
00469                                         }
00470                                 } else {
00471                                         if(extend==0) deselect_all_seq(scene);
00472                                         select_active_side(ed->seqbasep, sel_side, seq->machine, seq->startdisp);
00473                                 }
00474                         }
00475                         recurs_sel_seq(seq);
00476 
00477                         if(linked_time) {
00478                                 select_linked_time(ed->seqbasep, seq);
00479                         }
00480                 }
00481         }
00482         
00483         /* marker transform */
00484 #if 0 // XXX probably need to redo this differently for 2.5
00485         if (marker) {
00486                 int mval[2], xo, yo;
00487 //              getmouseco_areawin(mval);
00488                 xo= mval[0]; 
00489                 yo= mval[1];
00490                 
00491                 while(get_mbut()) {             
00492 //                      getmouseco_areawin(mval);
00493                         if(abs(mval[0]-xo)+abs(mval[1]-yo) > 4) {
00494                                 transform_markers('g', 0);
00495                                 return;
00496                         }
00497                 }
00498         }
00499 #endif
00500         
00501         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER|NA_SELECTED, scene);
00502 
00503         /* allowing tweaks */
00504         return OPERATOR_FINISHED|OPERATOR_PASS_THROUGH;
00505 }
00506 
00507 void SEQUENCER_OT_select(wmOperatorType *ot)
00508 {
00509         /* identifiers */
00510         ot->name= "Activate/Select";
00511         ot->idname= "SEQUENCER_OT_select";
00512         ot->description="Select a strip (last selected becomes the \"active strip\")";
00513         
00514         /* api callbacks */
00515         ot->invoke= sequencer_select_invoke;
00516         ot->poll= ED_operator_sequencer_active;
00517         
00518         /* flags */
00519         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00520         
00521         /* properties */
00522         RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend the selection.");
00523         RNA_def_boolean(ot->srna, "linked_handle", 0, "Linked Handle", "Select handles next to the active strip.");
00524         /* for animation this is an enum but atm having an enum isnt useful for us */
00525         RNA_def_boolean(ot->srna, "left_right", 0, "Left/Right", "select based on the frame side the cursor is on.");
00526         RNA_def_boolean(ot->srna, "linked_time", 0, "Linked Time", "Select other strips at the same time.");
00527 }
00528 
00529 
00530 
00531 
00532 /* run recursivly to select linked */
00533 static int select_more_less_seq__internal(Scene *scene, int sel, int linked) {
00534         Editing *ed= seq_give_editing(scene, FALSE);
00535         Sequence *seq, *neighbor;
00536         int change=0;
00537         int isel;
00538         
00539         if(ed==NULL) return 0;
00540         
00541         if (sel) {
00542                 sel = SELECT;
00543                 isel = 0;
00544         } else {
00545                 sel = 0;
00546                 isel = SELECT;
00547         }
00548         
00549         if (!linked) {
00550                 /* if not linked we only want to touch each seq once, newseq */
00551                 for(seq= ed->seqbasep->first; seq; seq= seq->next) {
00552                         seq->tmp = NULL;
00553                 }
00554         }
00555         
00556         for(seq= ed->seqbasep->first; seq; seq= seq->next) {
00557                 if((int)(seq->flag & SELECT) == sel) {
00558                         if ((linked==0 && seq->tmp)==0) {
00559                                 /* only get unselected nabours */
00560                                 neighbor = find_neighboring_sequence(scene, seq, SEQ_SIDE_LEFT, isel);
00561                                 if (neighbor) {
00562                                         if (sel) {neighbor->flag |= SELECT; recurs_sel_seq(neighbor);}
00563                                         else            neighbor->flag &= ~SELECT;
00564                                         if (linked==0) neighbor->tmp = (Sequence *)1;
00565                                         change = 1;
00566                                 }
00567                                 neighbor = find_neighboring_sequence(scene, seq, SEQ_SIDE_RIGHT, isel);
00568                                 if (neighbor) {
00569                                         if (sel) {neighbor->flag |= SELECT; recurs_sel_seq(neighbor);}
00570                                         else            neighbor->flag &= ~SELECT;
00571                                         if (linked==0) neighbor->tmp = (void *)1;
00572                                         change = 1;
00573                                 }
00574                         }
00575                 }
00576         }
00577         
00578         return change;
00579 }
00580 
00581 
00582 
00583 /* select more operator */
00584 static int sequencer_select_more_exec(bContext *C, wmOperator *UNUSED(op))
00585 {
00586         Scene *scene= CTX_data_scene(C);
00587         
00588         if(!select_more_less_seq__internal(scene, 0, 0))
00589                 return OPERATOR_CANCELLED;
00590 
00591         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER|NA_SELECTED, scene);
00592         
00593         return OPERATOR_FINISHED;
00594 }
00595 
00596 void SEQUENCER_OT_select_more(wmOperatorType *ot)
00597 {
00598         /* identifiers */
00599         ot->name= "Select More";
00600         ot->idname= "SEQUENCER_OT_select_more";
00601         ot->description="Select more strips adjacent to the current selection";
00602         
00603         /* api callbacks */
00604         ot->exec= sequencer_select_more_exec;
00605         ot->poll= sequencer_edit_poll;
00606         
00607         /* flags */
00608         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00609         
00610         /* properties */
00611 }
00612 
00613 
00614 /* select less operator */
00615 static int sequencer_select_less_exec(bContext *C, wmOperator *UNUSED(op))
00616 {
00617         Scene *scene= CTX_data_scene(C);
00618         
00619         if(!select_more_less_seq__internal(scene, 1, 0))
00620                 return OPERATOR_CANCELLED;
00621  
00622         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER|NA_SELECTED, scene);
00623         
00624         return OPERATOR_FINISHED;
00625 }
00626 
00627 void SEQUENCER_OT_select_less(wmOperatorType *ot)
00628 {
00629         /* identifiers */
00630         ot->name= "Select less";
00631         ot->idname= "SEQUENCER_OT_select_less";
00632         ot->description="Shrink the current selection of adjacent selected strips";
00633         
00634         /* api callbacks */
00635         ot->exec= sequencer_select_less_exec;
00636         ot->poll= sequencer_edit_poll;
00637         
00638         /* flags */
00639         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00640         
00641         /* properties */
00642 }
00643 
00644 
00645 /* select pick linked operator (uses the mouse) */
00646 static int sequencer_select_linked_pick_invoke(bContext *C, wmOperator *op, wmEvent *event)
00647 {
00648         Scene *scene= CTX_data_scene(C);
00649         View2D *v2d= UI_view2d_fromcontext(C);
00650         
00651         short extend= RNA_boolean_get(op->ptr, "extend");
00652         
00653         Sequence *mouse_seq;
00654         int selected, hand;
00655 
00656         /* this works like UV, not mesh */
00657         mouse_seq= find_nearest_seq(scene, v2d, &hand, event->mval);
00658         if (!mouse_seq)
00659                 return OPERATOR_FINISHED; /* user error as with mesh?? */
00660         
00661         if (extend==0)
00662                 deselect_all_seq(scene);
00663         
00664         mouse_seq->flag |= SELECT;
00665         recurs_sel_seq(mouse_seq);
00666         
00667         selected = 1;
00668         while (selected) {
00669                 selected = select_more_less_seq__internal(scene, 1, 1);
00670         }
00671         
00672         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER|NA_SELECTED, scene);
00673         
00674         return OPERATOR_FINISHED;
00675 }
00676 
00677 void SEQUENCER_OT_select_linked_pick(wmOperatorType *ot)
00678 {
00679         /* identifiers */
00680         ot->name= "Select pick linked";
00681         ot->idname= "SEQUENCER_OT_select_linked_pick";
00682         ot->description="Select a chain of linked strips nearest to the mouse pointer";
00683         
00684         /* api callbacks */
00685         ot->invoke= sequencer_select_linked_pick_invoke;
00686         ot->poll= ED_operator_sequencer_active;
00687         
00688         /* flags */
00689         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00690         
00691         /* properties */
00692         RNA_def_boolean(ot->srna, "extend", 0, "Extend", "extend the selection");
00693 }
00694 
00695 
00696 /* select linked operator */
00697 static int sequencer_select_linked_exec(bContext *C, wmOperator *UNUSED(op))
00698 {
00699         Scene *scene= CTX_data_scene(C);
00700         int selected;
00701 
00702         selected = 1;
00703         while (selected) {
00704                 selected = select_more_less_seq__internal(scene, 1, 1);
00705         }
00706 
00707         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER|NA_SELECTED, scene);
00708 
00709         return OPERATOR_FINISHED;
00710 }
00711 
00712 void SEQUENCER_OT_select_linked(wmOperatorType *ot)
00713 {
00714         /* identifiers */
00715         ot->name= "Select linked";
00716         ot->idname= "SEQUENCER_OT_select_linked";
00717         ot->description="Select all strips adjacent to the current selection";
00718         
00719         /* api callbacks */
00720         ot->exec= sequencer_select_linked_exec;
00721         ot->poll= sequencer_edit_poll;
00722         
00723         /* flags */
00724         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00725         
00726         /* properties */
00727 }
00728 
00729 
00730 /* select handles operator */
00731 static int sequencer_select_handles_exec(bContext *C, wmOperator *op)
00732 {
00733         Scene *scene= CTX_data_scene(C);
00734         Editing *ed= seq_give_editing(scene, 0);
00735         Sequence *seq;
00736         int sel_side= RNA_enum_get(op->ptr, "side");
00737 
00738 
00739         for(seq= ed->seqbasep->first; seq; seq=seq->next) {
00740                 if (seq->flag & SELECT) {
00741                         switch(sel_side) {
00742                         case SEQ_SIDE_LEFT:
00743                                 seq->flag &= ~SEQ_RIGHTSEL;
00744                                 seq->flag |= SEQ_LEFTSEL;
00745                                 break;
00746                         case SEQ_SIDE_RIGHT:
00747                                 seq->flag &= ~SEQ_LEFTSEL;
00748                                 seq->flag |= SEQ_RIGHTSEL;
00749                                 break;
00750                         case SEQ_SIDE_BOTH:
00751                                 seq->flag |= SEQ_LEFTSEL+SEQ_RIGHTSEL;
00752                                 break;
00753                         }
00754                 }
00755         }
00756 
00757         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER|NA_SELECTED, scene);
00758 
00759         return OPERATOR_FINISHED;
00760 }
00761 
00762 void SEQUENCER_OT_select_handles(wmOperatorType *ot)
00763 {
00764         /* identifiers */
00765         ot->name= "Select Handles";
00766         ot->idname= "SEQUENCER_OT_select_handles";
00767         ot->description="Select manipulator handles on the sides of the selected strip";
00768         
00769         /* api callbacks */
00770         ot->exec= sequencer_select_handles_exec;
00771         ot->poll= sequencer_edit_poll;
00772         
00773         /* flags */
00774         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00775         
00776         /* properties */
00777         RNA_def_enum(ot->srna, "side", prop_side_types, SEQ_SIDE_BOTH, "Side", "The side of the handle that is selected");
00778 }
00779 
00780 /* select side operator */
00781 static int sequencer_select_active_side_exec(bContext *C, wmOperator *op)
00782 {
00783         Scene *scene= CTX_data_scene(C);
00784         Editing *ed= seq_give_editing(scene, 0);
00785         Sequence *seq_act= seq_active_get(scene);
00786 
00787         if (ed==NULL || seq_act==NULL)
00788                 return OPERATOR_CANCELLED;
00789 
00790         seq_act->flag |= SELECT;
00791 
00792         select_active_side(ed->seqbasep, RNA_enum_get(op->ptr, "side"), seq_act->machine, seq_act->startdisp);
00793 
00794         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER|NA_SELECTED, scene);
00795 
00796         return OPERATOR_FINISHED;
00797 }
00798 
00799 void SEQUENCER_OT_select_active_side(wmOperatorType *ot)
00800 {
00801         /* identifiers */
00802         ot->name= "Select Active Side";
00803         ot->idname= "SEQUENCER_OT_select_active_side";
00804         ot->description="Select strips on the nominated side of the active strip";
00805         
00806         /* api callbacks */
00807         ot->exec= sequencer_select_active_side_exec;
00808         ot->poll= sequencer_edit_poll;
00809 
00810         /* flags */
00811         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00812 
00813         /* properties */
00814         RNA_def_enum(ot->srna, "side", prop_side_types, SEQ_SIDE_BOTH, "Side", "The side of the handle that is selected");
00815 }
00816 
00817 
00818 /* borderselect operator */
00819 static int sequencer_borderselect_exec(bContext *C, wmOperator *op)
00820 {
00821         Scene *scene= CTX_data_scene(C);
00822         Editing *ed= seq_give_editing(scene, FALSE);
00823         View2D *v2d= UI_view2d_fromcontext(C);
00824         
00825         Sequence *seq;
00826         rcti rect;
00827         rctf rectf, rq;
00828         short selecting = (RNA_int_get(op->ptr, "gesture_mode")==GESTURE_MODAL_SELECT);
00829         int mval[2];
00830 
00831         if(ed==NULL)
00832                 return OPERATOR_CANCELLED;
00833 
00834         rect.xmin= RNA_int_get(op->ptr, "xmin");
00835         rect.ymin= RNA_int_get(op->ptr, "ymin");
00836         rect.xmax= RNA_int_get(op->ptr, "xmax");
00837         rect.ymax= RNA_int_get(op->ptr, "ymax");
00838         
00839         mval[0]= rect.xmin;
00840         mval[1]= rect.ymin;
00841         UI_view2d_region_to_view(v2d, mval[0], mval[1], &rectf.xmin, &rectf.ymin);
00842         mval[0]= rect.xmax;
00843         mval[1]= rect.ymax;
00844         UI_view2d_region_to_view(v2d, mval[0], mval[1], &rectf.xmax, &rectf.ymax);
00845 
00846         for(seq= ed->seqbasep->first; seq; seq= seq->next) {
00847                 seq_rectf(seq, &rq);
00848                 
00849                 if(BLI_isect_rctf(&rq, &rectf, 0)) {
00850                         if(selecting)           seq->flag |= SELECT;
00851                         else                            seq->flag &= ~SEQ_ALLSEL;
00852                         recurs_sel_seq(seq);
00853                 }
00854         }
00855 
00856         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER|NA_SELECTED, scene);
00857 
00858         return OPERATOR_FINISHED;
00859 } 
00860 
00861 
00862 /* ****** Border Select ****** */
00863 void SEQUENCER_OT_select_border(wmOperatorType *ot)
00864 {
00865         /* identifiers */
00866         ot->name= "Border Select";
00867         ot->idname= "SEQUENCER_OT_select_border";
00868         ot->description="Enable border select mode";
00869         
00870         /* api callbacks */
00871         ot->invoke= WM_border_select_invoke;
00872         ot->exec= sequencer_borderselect_exec;
00873         ot->modal= WM_border_select_modal;
00874         ot->cancel= WM_border_select_cancel;
00875         
00876         ot->poll= ED_operator_sequencer_active;
00877         
00878         /* flags */
00879         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00880         
00881         /* rna */
00882         WM_operator_properties_gesture_border(ot, FALSE);
00883 }