Blender  V3.3
sequencer_select.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2001-2002 NaN Holding BV. All rights reserved. */
3 
8 #include <math.h>
9 #include <stdlib.h>
10 #include <string.h>
11 
12 #include "MEM_guardedalloc.h"
13 
14 #include "BLI_blenlib.h"
15 #include "BLI_math.h"
16 #include "BLI_utildefines.h"
17 
18 #include "DNA_scene_types.h"
19 
20 #include "BKE_context.h"
21 #include "BKE_report.h"
22 
23 #include "WM_api.h"
24 #include "WM_types.h"
25 
26 #include "RNA_define.h"
27 
28 #include "SEQ_channels.h"
29 #include "SEQ_iterator.h"
30 #include "SEQ_relations.h"
31 #include "SEQ_select.h"
32 #include "SEQ_sequencer.h"
33 #include "SEQ_time.h"
34 #include "SEQ_transform.h"
35 #include "SEQ_utils.h"
36 
37 /* For menu, popup, icons, etc. */
38 
39 #include "ED_outliner.h"
40 #include "ED_screen.h"
41 #include "ED_select_utils.h"
42 #include "ED_sequencer.h"
43 
44 #include "UI_view2d.h"
45 
46 /* Own include. */
47 #include "sequencer_intern.h"
48 
49 /* -------------------------------------------------------------------- */
54 {
57  ListBase *seqbase = SEQ_active_seqbase_get(ed);
59 
60  const bool is_preview = sequencer_view_has_preview_poll(C);
61  if (is_preview) {
62  return SEQ_query_rendered_strips(scene, channels, seqbase, scene->r.cfra, 0);
63  }
64 
65  return SEQ_query_all_strips(seqbase);
66 }
67 
69 {
72  ListBase *seqbase = SEQ_active_seqbase_get(ed);
74 
75  const bool is_preview = sequencer_view_has_preview_poll(C);
76  if (is_preview) {
79  return strips;
80  }
81 
82  return SEQ_query_selected_strips(seqbase);
83 }
84 
85 static void select_surrounding_handles(Scene *scene, Sequence *test) /* XXX BRING BACK */
86 {
87  Sequence *neighbor;
88 
89  neighbor = find_neighboring_sequence(scene, test, SEQ_SIDE_LEFT, -1);
90  if (neighbor) {
91  /* Only select neighbor handle if matching handle from test seq is also selected,
92  * or if neighbor was not selected at all up till now.
93  * Otherwise, we get odd mismatch when shift-alt-rmb selecting neighbor strips... */
94  if (!(neighbor->flag & SELECT) || (test->flag & SEQ_LEFTSEL)) {
95  neighbor->flag |= SEQ_RIGHTSEL;
96  }
97  neighbor->flag |= SELECT;
98  recurs_sel_seq(neighbor);
99  }
100  neighbor = find_neighboring_sequence(scene, test, SEQ_SIDE_RIGHT, -1);
101  if (neighbor) {
102  if (!(neighbor->flag & SELECT) || (test->flag & SEQ_RIGHTSEL)) { /* See comment above. */
103  neighbor->flag |= SEQ_LEFTSEL;
104  }
105  neighbor->flag |= SELECT;
106  recurs_sel_seq(neighbor);
107  }
108 }
109 
110 /* Used for mouse selection in SEQUENCER_OT_select. */
111 static void select_active_side(
112  const Scene *scene, ListBase *seqbase, int sel_side, int channel, int frame)
113 {
114  Sequence *seq;
115 
116  for (seq = seqbase->first; seq; seq = seq->next) {
117  if (channel == seq->machine) {
118  switch (sel_side) {
119  case SEQ_SIDE_LEFT:
120  if (frame > (SEQ_time_left_handle_frame_get(scene, seq))) {
121  seq->flag &= ~(SEQ_RIGHTSEL | SEQ_LEFTSEL);
122  seq->flag |= SELECT;
123  }
124  break;
125  case SEQ_SIDE_RIGHT:
126  if (frame < (SEQ_time_left_handle_frame_get(scene, seq))) {
127  seq->flag &= ~(SEQ_RIGHTSEL | SEQ_LEFTSEL);
128  seq->flag |= SELECT;
129  }
130  break;
131  case SEQ_SIDE_BOTH:
132  seq->flag &= ~(SEQ_RIGHTSEL | SEQ_LEFTSEL);
133  seq->flag |= SELECT;
134  break;
135  }
136  }
137  }
138 }
139 
140 /* Used for mouse selection in SEQUENCER_OT_select_side. */
142  ListBase *seqbase,
143  const int sel_side,
144  const int frame_ranges[MAXSEQ],
145  const int frame_ignore)
146 {
147  Sequence *seq;
148 
149  for (seq = seqbase->first; seq; seq = seq->next) {
150  if (seq->machine < MAXSEQ) {
151  const int frame = frame_ranges[seq->machine];
152  if (frame == frame_ignore) {
153  continue;
154  }
155  switch (sel_side) {
156  case SEQ_SIDE_LEFT:
157  if (frame > (SEQ_time_left_handle_frame_get(scene, seq))) {
158  seq->flag &= ~(SEQ_RIGHTSEL | SEQ_LEFTSEL);
159  seq->flag |= SELECT;
160  }
161  break;
162  case SEQ_SIDE_RIGHT:
163  if (frame < (SEQ_time_left_handle_frame_get(scene, seq))) {
164  seq->flag &= ~(SEQ_RIGHTSEL | SEQ_LEFTSEL);
165  seq->flag |= SELECT;
166  }
167  break;
168  case SEQ_SIDE_BOTH:
169  seq->flag &= ~(SEQ_RIGHTSEL | SEQ_LEFTSEL);
170  seq->flag |= SELECT;
171  break;
172  }
173  }
174  }
175 }
176 
177 /* Used for mouse selection in SEQUENCER_OT_select */
178 static void select_linked_time(const Scene *scene, ListBase *seqbase, Sequence *seq_link)
179 {
180  Sequence *seq;
181 
182  for (seq = seqbase->first; seq; seq = seq->next) {
183  if (seq_link->machine != seq->machine) {
184  int left_match = (SEQ_time_left_handle_frame_get(scene, seq) == seq_link->startdisp) ? 1 : 0;
185  int right_match = (SEQ_time_right_handle_frame_get(scene, seq) == seq_link->enddisp) ? 1 : 0;
186 
187  if (left_match && right_match) {
188  /* Direct match, copy the selection settings. */
189  seq->flag &= ~(SELECT | SEQ_LEFTSEL | SEQ_RIGHTSEL);
190  seq->flag |= seq_link->flag & (SELECT | SEQ_LEFTSEL | SEQ_RIGHTSEL);
191 
192  recurs_sel_seq(seq);
193  }
194  else if (seq_link->flag & SELECT && (left_match || right_match)) {
195 
196  /* Clear for reselection. */
197  seq->flag &= ~(SEQ_LEFTSEL | SEQ_RIGHTSEL);
198 
199  if (left_match && seq_link->flag & SEQ_LEFTSEL) {
200  seq->flag |= SELECT | SEQ_LEFTSEL;
201  }
202 
203  if (right_match && seq_link->flag & SEQ_RIGHTSEL) {
204  seq->flag |= SELECT | SEQ_RIGHTSEL;
205  }
206 
207  recurs_sel_seq(seq);
208  }
209  }
210  }
211 }
212 
213 #if 0 /* BRING BACK */
214 void select_surround_from_last(Scene *scene)
215 {
216  Sequence *seq = get_last_seq(scene);
217 
218  if (seq == NULL) {
219  return;
220  }
221 
223 }
224 #endif
225 
227 {
229 
230  if (deselect_all) {
232  }
233 
235 
236  if (ELEM(seq->type, SEQ_TYPE_IMAGE, SEQ_TYPE_MOVIE)) {
237  if (seq->strip) {
239  }
240  }
241  else if (seq->type == SEQ_TYPE_SOUND_RAM) {
242  if (seq->strip) {
244  }
245  }
246  seq->flag |= SELECT;
247  recurs_sel_seq(seq);
248 }
249 
250 void seq_rectf(const Scene *scene, Sequence *seq, rctf *rect)
251 {
254  rect->ymin = seq->machine + SEQ_STRIP_OFSBOTTOM;
255  rect->ymax = seq->machine + SEQ_STRIP_OFSTOP;
256 }
257 
259 {
260  /* sel: 0==unselected, 1==selected, -1==don't care. */
261  Sequence *seq;
263 
264  if (ed == NULL) {
265  return NULL;
266  }
267 
268  if (sel > 0) {
269  sel = SELECT;
270  }
271 
272  for (seq = ed->seqbasep->first; seq; seq = seq->next) {
273  if ((seq != test) && (test->machine == seq->machine) &&
274  ((sel == -1) || (sel && (seq->flag & SELECT)) ||
275  (sel == 0 && (seq->flag & SELECT) == 0))) {
276  switch (lr) {
277  case SEQ_SIDE_LEFT:
280  return seq;
281  }
282  break;
283  case SEQ_SIDE_RIGHT:
286  return seq;
287  }
288  break;
289  }
290  }
291  }
292  return NULL;
293 }
294 
295 Sequence *find_nearest_seq(Scene *scene, View2D *v2d, int *hand, const int mval[2])
296 {
297  Sequence *seq;
299  float x, y;
300  float pixelx;
301  float handsize;
302  float displen;
303  *hand = SEQ_SIDE_NONE;
304 
305  if (ed == NULL) {
306  return NULL;
307  }
308 
309  pixelx = BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask);
310 
311  UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y);
312 
313  seq = ed->seqbasep->first;
314 
315  while (seq) {
316  if (seq->machine == (int)y) {
317  /* Check for both normal strips, and strips that have been flipped horizontally. */
327 
328  /* Clamp handles to defined size in pixel space. */
329  handsize = 2.0f * sequence_handle_size_get_clamped(scene, seq, pixelx);
330  displen = (float)abs(SEQ_time_left_handle_frame_get(scene, seq) -
332 
333  /* Don't even try to grab the handles of small strips. */
334  if (displen / pixelx > 16) {
335 
336  /* Set the max value to handle to 1/3 of the total len when its
337  * less than 28. This is important because otherwise selecting
338  * handles happens even when you click in the middle. */
339  if ((displen / 3) < 30 * pixelx) {
340  handsize = displen / 3;
341  }
342  else {
343  CLAMP(handsize, 7 * pixelx, 30 * pixelx);
344  }
345 
346  if (handsize + SEQ_time_left_handle_frame_get(scene, seq) >= x) {
347  *hand = SEQ_SIDE_LEFT;
348  }
349  else if (-handsize + SEQ_time_right_handle_frame_get(scene, seq) <= x) {
350  *hand = SEQ_SIDE_RIGHT;
351  }
352  }
353  }
354  return seq;
355  }
356  }
357  seq = seq->next;
358  }
359  return NULL;
360 }
361 
362 #if 0
363 static void select_neighbor_from_last(Scene *scene, int lr)
364 {
366  Sequence *neighbor;
367  bool changed = false;
368  if (seq) {
369  neighbor = find_neighboring_sequence(scene, seq, lr, -1);
370  if (neighbor) {
371  switch (lr) {
372  case SEQ_SIDE_LEFT:
373  neighbor->flag |= SELECT;
374  recurs_sel_seq(neighbor);
375  neighbor->flag |= SEQ_RIGHTSEL;
376  seq->flag |= SEQ_LEFTSEL;
377  break;
378  case SEQ_SIDE_RIGHT:
379  neighbor->flag |= SELECT;
380  recurs_sel_seq(neighbor);
381  neighbor->flag |= SEQ_LEFTSEL;
382  seq->flag |= SEQ_RIGHTSEL;
383  break;
384  }
385  seq->flag |= SELECT;
386  changed = true;
387  }
388  }
389  if (changed) {
390  /* Pass. */
391  }
392 }
393 #endif
394 
395 void recurs_sel_seq(Sequence *seq_meta)
396 {
397  Sequence *seq;
398 
399  seq = seq_meta->seqbase.first;
400  while (seq) {
401 
402  if (seq_meta->flag & (SEQ_LEFTSEL + SEQ_RIGHTSEL)) {
403  seq->flag &= ~SEQ_ALLSEL;
404  }
405  else if (seq_meta->flag & SELECT) {
406  seq->flag |= SELECT;
407  }
408  else {
409  seq->flag &= ~SEQ_ALLSEL;
410  }
411 
412  if (seq->seqbase.first) {
413  recurs_sel_seq(seq);
414  }
415 
416  seq = seq->next;
417  }
418 }
419 
420 static bool seq_point_image_isect(const Scene *scene, const Sequence *seq, float point[2])
421 {
422  float seq_image_quad[4][2];
423  SEQ_image_transform_final_quad_get(scene, seq, seq_image_quad);
424  return isect_point_quad_v2(
425  point, seq_image_quad[0], seq_image_quad[1], seq_image_quad[2], seq_image_quad[3]);
426 }
427 
429 {
432 }
433 
436 /* -------------------------------------------------------------------- */
441 {
442  int action = RNA_enum_get(op->ptr, "action");
444 
446  return OPERATOR_CANCELLED;
447  }
448 
450  Sequence *seq;
451 
452  if (action == SEL_TOGGLE) {
453  action = SEL_SELECT;
454  SEQ_ITERATOR_FOREACH (seq, strips) {
455  if (seq->flag & SEQ_ALLSEL) {
456  action = SEL_DESELECT;
457  break;
458  }
459  }
460  }
461 
462  SEQ_ITERATOR_FOREACH (seq, strips) {
463  switch (action) {
464  case SEL_SELECT:
465  seq->flag &= ~(SEQ_LEFTSEL + SEQ_RIGHTSEL);
466  seq->flag |= SELECT;
467  break;
468  case SEL_DESELECT:
469  seq->flag &= ~SEQ_ALLSEL;
470  break;
471  case SEL_INVERT:
472  if (seq->flag & SEQ_ALLSEL) {
473  seq->flag &= ~SEQ_ALLSEL;
474  }
475  else {
476  seq->flag &= ~(SEQ_LEFTSEL + SEQ_RIGHTSEL);
477  seq->flag |= SELECT;
478  }
479  break;
480  }
481  }
482 
483  SEQ_collection_free(strips);
484 
487 
488  return OPERATOR_FINISHED;
489 }
490 
492 {
493  /* Identifiers. */
494  ot->name = "(De)select All";
495  ot->idname = "SEQUENCER_OT_select_all";
496  ot->description = "Select or deselect all strips";
497 
498  /* Api callbacks. */
501 
502  /* Flags. */
503  ot->flag = OPTYPE_UNDO;
504 
506 }
507 
510 /* -------------------------------------------------------------------- */
515 {
517 
519  return OPERATOR_CANCELLED;
520  }
521 
523  Sequence *seq;
524 
525  SEQ_ITERATOR_FOREACH (seq, strips) {
526  if (seq->flag & SELECT) {
527  seq->flag &= ~SEQ_ALLSEL;
528  }
529  else {
530  seq->flag &= ~(SEQ_LEFTSEL + SEQ_RIGHTSEL);
531  seq->flag |= SELECT;
532  }
533  }
534 
535  SEQ_collection_free(strips);
536 
539 
540  return OPERATOR_FINISHED;
541 }
542 
544 {
545  /* Identifiers. */
546  ot->name = "Select Inverse";
547  ot->idname = "SEQUENCER_OT_select_inverse";
548  ot->description = "Select unselected strips";
549 
550  /* Api callbacks. */
553 
554  /* Flags. */
555  ot->flag = OPTYPE_UNDO;
556 }
557 
560 /* -------------------------------------------------------------------- */
565 {
567 
569 
570  if (ELEM(seq->type, SEQ_TYPE_IMAGE, SEQ_TYPE_MOVIE)) {
571  if (seq->strip) {
573  }
574  }
575  else if (seq->type == SEQ_TYPE_SOUND_RAM) {
576  if (seq->strip) {
578  }
579  }
580  recurs_sel_seq(seq);
581 }
582 
584  const View2D *v2d,
585  const int mval[2],
586  Scene *scene)
587 {
589 
590  const float x = UI_view2d_region_to_view_x(v2d, mval[0]);
592  if (((x < scene->r.cfra) &&
593  (SEQ_time_right_handle_frame_get(scene, seq_iter) <= scene->r.cfra)) ||
594  ((x >= scene->r.cfra) &&
595  (SEQ_time_left_handle_frame_get(scene, seq_iter) >= scene->r.cfra))) {
596  /* Select left or right. */
597  seq_iter->flag |= SELECT;
598  recurs_sel_seq(seq_iter);
599  }
600  }
601 
602  {
603  SpaceSeq *sseq = CTX_wm_space_seq(C);
604  if (sseq && sseq->flag & SEQ_MARKER_TRANS) {
605  TimeMarker *tmarker;
606 
607  for (tmarker = scene->markers.first; tmarker; tmarker = tmarker->next) {
608  if (((x < scene->r.cfra) && (tmarker->frame <= scene->r.cfra)) ||
609  ((x >= scene->r.cfra) && (tmarker->frame >= scene->r.cfra))) {
610  tmarker->flag |= SELECT;
611  }
612  else {
613  tmarker->flag &= ~SELECT;
614  }
615  }
616  }
617  }
618 }
619 
621  Sequence *seq,
622  const int handle_clicked)
623 {
626  if (!ELEM(handle_clicked, SEQ_SIDE_LEFT, SEQ_SIDE_RIGHT)) {
627  /* First click selects the strip and its adjacent handles (if valid).
628  * Second click selects the strip,
629  * both of its handles and its adjacent handles (if valid). */
630  const bool is_striponly_selected = ((seq->flag & SEQ_ALLSEL) == SELECT);
631  seq->flag &= ~SEQ_ALLSEL;
632  seq->flag |= is_striponly_selected ? SEQ_ALLSEL : SELECT;
634  }
635  else {
636  /* Always select the strip under the cursor. */
637  seq->flag |= SELECT;
638 
639  /* First click selects adjacent handles on that side.
640  * Second click selects all strips in that direction.
641  * If there are no adjacent strips, it just selects all in that direction.
642  */
643  int sel_side = handle_clicked;
644  Sequence *neighbor = find_neighboring_sequence(scene, seq, sel_side, -1);
645  if (neighbor) {
646  switch (sel_side) {
647  case SEQ_SIDE_LEFT:
648  if ((seq->flag & SEQ_LEFTSEL) && (neighbor->flag & SEQ_RIGHTSEL)) {
649  seq->flag |= SELECT;
651  ed->seqbasep,
653  seq->machine,
655  }
656  else {
657  seq->flag |= SELECT;
658  neighbor->flag |= SELECT;
659  recurs_sel_seq(neighbor);
660  neighbor->flag |= SEQ_RIGHTSEL;
661  seq->flag |= SEQ_LEFTSEL;
662  }
663  break;
664  case SEQ_SIDE_RIGHT:
665  if ((seq->flag & SEQ_RIGHTSEL) && (neighbor->flag & SEQ_LEFTSEL)) {
666  seq->flag |= SELECT;
668  ed->seqbasep,
670  seq->machine,
672  }
673  else {
674  seq->flag |= SELECT;
675  neighbor->flag |= SELECT;
676  recurs_sel_seq(neighbor);
677  neighbor->flag |= SEQ_LEFTSEL;
678  seq->flag |= SEQ_RIGHTSEL;
679  }
680  break;
681  }
682  }
683  else {
684 
686  scene, ed->seqbasep, sel_side, seq->machine, SEQ_time_left_handle_frame_get(scene, seq));
687  }
688  }
689 }
690 
697 };
698 
699 static int seq_sort_for_depth_select(const void *a, const void *b)
700 {
701  const struct SeqSelect_Link *slink_a = a;
702  const struct SeqSelect_Link *slink_b = b;
703 
704  /* Exactly overlapping strips, sort by machine (so the top-most is first). */
705  if (slink_a->seq->machine < slink_b->seq->machine) {
706  return 1;
707  }
708  if (slink_a->seq->machine > slink_b->seq->machine) {
709  return -1;
710  }
711  return 0;
712 }
713 
714 static int seq_sort_for_center_select(const void *a, const void *b)
715 {
716  const struct SeqSelect_Link *slink_a = a;
717  const struct SeqSelect_Link *slink_b = b;
718  if (slink_a->center_dist_sq > slink_b->center_dist_sq) {
719  return 1;
720  }
721  if (slink_a->center_dist_sq < slink_b->center_dist_sq) {
722  return -1;
723  }
724 
725  /* Exactly overlapping strips, use depth. */
726  return seq_sort_for_depth_select(a, b);
727 }
728 
735  const bContext *C, const int mval[2], const bool toggle, const bool extend, const bool center)
736 {
739  ListBase *seqbase = SEQ_active_seqbase_get(ed);
741  SpaceSeq *sseq = CTX_wm_space_seq(C);
743 
744  float mouseco_view[2];
745  UI_view2d_region_to_view(v2d, mval[0], mval[1], &mouseco_view[0], &mouseco_view[1]);
746 
747  /* Always update the coordinates (check extended after). */
748  const bool use_cycle = (!WM_cursor_test_motion_and_update(mval) || extend || toggle);
749 
751  scene, channels, seqbase, scene->r.cfra, sseq->chanshown);
752 
753  /* Allow strips this far from the closest center to be included.
754  * This allows cycling over center points which are near enough
755  * to overlapping from the users perspective. */
756  const float center_dist_sq_max = square_f(75.0f * U.pixelsize);
757  const float center_scale_px[2] = {
760  };
761 
762  struct SeqSelect_Link *slink_active = NULL;
763  Sequence *seq_active = SEQ_select_active_get(scene);
764  ListBase strips_ordered = {NULL};
765  Sequence *seq;
766  SEQ_ITERATOR_FOREACH (seq, strips) {
767  bool isect = false;
768  float center_dist_sq_test = 0.0f;
769  if (center) {
770  /* Detect overlapping center points (scaled by the zoom level). */
771  float co[2];
773  sub_v2_v2(co, mouseco_view);
774  mul_v2_v2(co, center_scale_px);
775  center_dist_sq_test = len_squared_v2(co);
776  isect = center_dist_sq_test <= center_dist_sq_max;
777  if (isect) {
778  /* Use an active strip penalty for "center" selection when cycle is enabled. */
779  if (use_cycle && (seq == seq_active) && (seq_active->flag & SELECT)) {
780  center_dist_sq_test = square_f(sqrtf(center_dist_sq_test) + (3.0f * U.pixelsize));
781  }
782  }
783  }
784  else {
785  isect = seq_point_image_isect(scene, seq, mouseco_view);
786  }
787 
788  if (isect) {
789  struct SeqSelect_Link *slink = MEM_callocN(sizeof(*slink), __func__);
790  slink->seq = seq;
791  slink->center_dist_sq = center_dist_sq_test;
792  BLI_addtail(&strips_ordered, slink);
793 
794  if (seq == seq_active) {
795  slink_active = slink;
796  }
797  }
798  }
799  SEQ_collection_free(strips);
800 
801  BLI_listbase_sort(&strips_ordered,
803 
804  struct SeqSelect_Link *slink_select = strips_ordered.first;
805  Sequence *seq_select = NULL;
806  if (slink_select != NULL) {
807  /* Only use special behavior for the active strip when it's selected. */
808  if ((center == false) && slink_active && (seq_active->flag & SELECT)) {
809  if (use_cycle) {
810  if (slink_active->next) {
811  slink_select = slink_active->next;
812  }
813  }
814  else {
815  /* Match object selection behavior: keep the current active item unless cycle is enabled.
816  * Clicking again in the same location will cycle away from the active object. */
817  slink_select = slink_active;
818  }
819  }
820  seq_select = slink_select->seq;
821  }
822 
823  BLI_freelistN(&strips_ordered);
824 
825  return seq_select;
826 }
827 
828 static bool element_already_selected(const Sequence *seq, const int handle_clicked)
829 {
830  const bool handle_already_selected = ((handle_clicked == SEQ_SIDE_LEFT) &&
831  (seq->flag & SEQ_LEFTSEL)) ||
832  ((handle_clicked == SEQ_SIDE_RIGHT) &&
833  (seq->flag & SEQ_RIGHTSEL));
834  return ((seq->flag & SELECT) && handle_clicked == SEQ_SIDE_NONE) || handle_already_selected;
835 }
836 
837 static void sequencer_select_strip_impl(const Editing *ed,
838  Sequence *seq,
839  const int handle_clicked,
840  const bool extend,
841  const bool deselect,
842  const bool toggle)
843 {
844  const bool is_active = (ed->act_seq == seq);
845 
846  /* Exception for active strip handles. */
847  if ((handle_clicked != SEQ_SIDE_NONE) && (seq->flag & SELECT) && is_active && toggle) {
848  switch (handle_clicked) {
849  case SEQ_SIDE_LEFT:
850  seq->flag ^= SEQ_LEFTSEL;
851  break;
852  case SEQ_SIDE_RIGHT:
853  seq->flag ^= SEQ_RIGHTSEL;
854  break;
855  }
856  return;
857  }
858 
859  /* Select strip. */
860  /* Match object selection behavior. */
861  int action = -1;
862  if (extend) {
863  action = 1;
864  }
865  else if (deselect) {
866  action = 0;
867  }
868  else {
869  if (!((seq->flag & SELECT) && is_active)) {
870  action = 1;
871  }
872  else if (toggle) {
873  action = 0;
874  }
875  }
876 
877  if (action == 1) {
878  seq->flag |= SELECT;
879  if (handle_clicked == SEQ_SIDE_LEFT) {
880  seq->flag |= SEQ_LEFTSEL;
881  }
882  if (handle_clicked == SEQ_SIDE_RIGHT) {
883  seq->flag |= SEQ_RIGHTSEL;
884  }
885  }
886  else if (action == 0) {
887  seq->flag &= ~SEQ_ALLSEL;
888  }
889 }
890 
892 {
896  ARegion *region = CTX_wm_region(C);
897 
898  if (ed == NULL) {
899  return OPERATOR_CANCELLED;
900  }
901 
902  if (region->regiontype == RGN_TYPE_PREVIEW) {
904  return OPERATOR_CANCELLED;
905  }
906  const SpaceSeq *sseq = CTX_wm_space_seq(C);
907  if (sseq->mainb != SEQ_DRAW_IMG_IMBUF) {
908  return OPERATOR_CANCELLED;
909  }
910  }
911 
912  bool extend = RNA_boolean_get(op->ptr, "extend");
913  bool deselect = RNA_boolean_get(op->ptr, "deselect");
914  bool deselect_all = RNA_boolean_get(op->ptr, "deselect_all");
915  bool toggle = RNA_boolean_get(op->ptr, "toggle");
916  bool center = RNA_boolean_get(op->ptr, "center");
917 
918  int mval[2];
919  mval[0] = RNA_int_get(op->ptr, "mouse_x");
920  mval[1] = RNA_int_get(op->ptr, "mouse_y");
921 
922  int handle_clicked = SEQ_SIDE_NONE;
923  Sequence *seq = NULL;
924  if (region->regiontype == RGN_TYPE_PREVIEW) {
925  seq = seq_select_seq_from_preview(C, mval, toggle, extend, center);
926  }
927  else {
928  seq = find_nearest_seq(scene, v2d, &handle_clicked, mval);
929  }
930 
931  /* NOTE: `side_of_frame` and `linked_time` functionality is designed to be shared on one keymap,
932  * therefore both properties can be true at the same time. */
933  if (seq && RNA_boolean_get(op->ptr, "linked_time")) {
934  if (!extend && !toggle) {
936  }
937  sequencer_select_strip_impl(ed, seq, handle_clicked, extend, deselect, toggle);
941  return OPERATOR_FINISHED;
942  }
943 
944  /* Select left, right or overlapping the current frame. */
945  if (RNA_boolean_get(op->ptr, "side_of_frame")) {
946  if (!extend && !toggle) {
948  }
951  return OPERATOR_FINISHED;
952  }
953 
954  /* On Alt selection, select the strip and bordering handles. */
955  if (seq && RNA_boolean_get(op->ptr, "linked_handle")) {
956  if (!extend && !toggle) {
958  }
959  sequencer_select_linked_handle(C, seq, handle_clicked);
962  return OPERATOR_FINISHED;
963  }
964 
965  const bool wait_to_deselect_others = RNA_boolean_get(op->ptr, "wait_to_deselect_others");
966 
967  /* Clicking on already selected element falls on modal operation.
968  * All strips are deselected on mouse button release unless extend mode is used. */
969  if (seq && element_already_selected(seq, handle_clicked) && wait_to_deselect_others && !toggle) {
970  return OPERATOR_RUNNING_MODAL;
971  }
972 
973  bool changed = false;
974 
975  /* Deselect everything */
976  if (deselect_all || (seq && ((extend == false && deselect == false && toggle == false)))) {
978  changed = true;
979  }
980 
981  /* Nothing to select, but strips could be deselected. */
982  if (!seq) {
983  if (changed) {
985  }
986  return changed ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
987  }
988 
989  /* Do actual selection. */
990  sequencer_select_strip_impl(ed, seq, handle_clicked, extend, deselect, toggle);
991 
994  return OPERATOR_FINISHED;
995 }
996 
997 static int sequencer_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
998 {
999  const int retval = WM_generic_select_invoke(C, op, event);
1000  ARegion *region = CTX_wm_region(C);
1001  if (region && (region->regiontype == RGN_TYPE_PREVIEW)) {
1002  return WM_operator_flag_only_pass_through_on_press(retval, event);
1003  }
1004  return retval;
1005 }
1006 
1008 {
1009  PropertyRNA *prop;
1010 
1011  /* Identifiers. */
1012  ot->name = "Select";
1013  ot->idname = "SEQUENCER_OT_select";
1014  ot->description = "Select a strip (last selected becomes the \"active strip\")";
1015 
1016  /* Api callbacks. */
1022 
1023  /* Flags. */
1024  ot->flag = OPTYPE_UNDO;
1025 
1026  /* Properties. */
1028 
1030 
1031  prop = RNA_def_boolean(
1032  ot->srna,
1033  "center",
1034  0,
1035  "Center",
1036  "Use the object center when selecting, in edit mode used to extend object selection");
1038 
1039  prop = RNA_def_boolean(ot->srna,
1040  "linked_handle",
1041  false,
1042  "Linked Handle",
1043  "Select handles next to the active strip");
1045 
1046  prop = RNA_def_boolean(
1047  ot->srna, "linked_time", false, "Linked Time", "Select other strips at the same time");
1049 
1050  prop = RNA_def_boolean(
1051  ot->srna,
1052  "side_of_frame",
1053  false,
1054  "Side of Frame",
1055  "Select all strips on same side of the current frame as the mouse cursor");
1057 }
1058 
1061 /* -------------------------------------------------------------------- */
1065 /* Run recursively to select linked. */
1067 {
1068  Editing *ed = SEQ_editing_get(scene);
1069 
1070  if (ed == NULL) {
1071  return false;
1072  }
1073 
1074  bool changed = false;
1075 
1077  if ((seq->flag & SELECT) == 0) {
1078  continue;
1079  }
1080  /* Only get unselected neighbors. */
1082  if (neighbor) {
1083  neighbor->flag |= SELECT;
1084  recurs_sel_seq(neighbor);
1085  changed = true;
1086  }
1088  if (neighbor) {
1089  neighbor->flag |= SELECT;
1090  recurs_sel_seq(neighbor);
1091  changed = true;
1092  }
1093  }
1094 
1095  return changed;
1096 }
1097 
1098 /* Select only one linked strip on each side. */
1099 static bool select_more_less_seq__internal(Scene *scene, bool select_more)
1100 {
1101  Editing *ed = SEQ_editing_get(scene);
1102 
1103  if (ed == NULL) {
1104  return false;
1105  }
1106 
1107  GSet *neighbors = BLI_gset_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "Linked strips");
1108  const int neighbor_selection_filter = select_more ? 0 : SELECT;
1109  const int selection_filter = select_more ? SELECT : 0;
1110 
1112  if ((seq->flag & SELECT) != selection_filter) {
1113  continue;
1114  }
1115  Sequence *neighbor = find_neighboring_sequence(
1116  scene, seq, SEQ_SIDE_LEFT, neighbor_selection_filter);
1117  if (neighbor) {
1118  BLI_gset_add(neighbors, neighbor);
1119  }
1120  neighbor = find_neighboring_sequence(scene, seq, SEQ_SIDE_RIGHT, neighbor_selection_filter);
1121  if (neighbor) {
1122  BLI_gset_add(neighbors, neighbor);
1123  }
1124  }
1125 
1126  bool changed = false;
1127  GSetIterator gsi;
1128  BLI_gsetIterator_init(&gsi, neighbors);
1129  while (!BLI_gsetIterator_done(&gsi)) {
1130  Sequence *neighbor = BLI_gsetIterator_getKey(&gsi);
1131  if (select_more) {
1132  neighbor->flag |= SELECT;
1133  recurs_sel_seq(neighbor);
1134  }
1135  else {
1136  neighbor->flag &= ~SELECT;
1137  }
1138  changed = true;
1139  BLI_gsetIterator_step(&gsi);
1140  }
1141 
1142  BLI_gset_free(neighbors, NULL);
1143  return changed;
1144 }
1145 
1147 {
1149 
1150  if (!select_more_less_seq__internal(scene, true)) {
1151  return OPERATOR_CANCELLED;
1152  }
1153 
1155 
1157 
1158  return OPERATOR_FINISHED;
1159 }
1160 
1162 {
1163  /* Identifiers. */
1164  ot->name = "Select More";
1165  ot->idname = "SEQUENCER_OT_select_more";
1166  ot->description = "Select more strips adjacent to the current selection";
1167 
1168  /* Api callbacks. */
1171 
1172  /* Flags. */
1174 }
1175 
1178 /* -------------------------------------------------------------------- */
1183 {
1185 
1186  if (!select_more_less_seq__internal(scene, false)) {
1187  return OPERATOR_CANCELLED;
1188  }
1189 
1191 
1193 
1194  return OPERATOR_FINISHED;
1195 }
1196 
1198 {
1199  /* Identifiers. */
1200  ot->name = "Select Less";
1201  ot->idname = "SEQUENCER_OT_select_less";
1202  ot->description = "Shrink the current selection of adjacent selected strips";
1203 
1204  /* Api callbacks. */
1207 
1208  /* Flags. */
1210 }
1211 
1214 /* -------------------------------------------------------------------- */
1219 {
1221  View2D *v2d = UI_view2d_fromcontext(C);
1222 
1223  bool extend = RNA_boolean_get(op->ptr, "extend");
1224 
1225  Sequence *mouse_seq;
1226  int selected, hand;
1227 
1228  /* This works like UV, not mesh. */
1229  mouse_seq = find_nearest_seq(scene, v2d, &hand, event->mval);
1230  if (!mouse_seq) {
1231  return OPERATOR_FINISHED; /* User error as with mesh?? */
1232  }
1233 
1234  if (extend == 0) {
1236  }
1237 
1238  mouse_seq->flag |= SELECT;
1239  recurs_sel_seq(mouse_seq);
1240 
1241  selected = 1;
1242  while (selected) {
1243  selected = select_linked_internal(scene);
1244  }
1245 
1247 
1249 
1250  return OPERATOR_FINISHED;
1251 }
1252 
1254 {
1255  /* Identifiers. */
1256  ot->name = "Select Pick Linked";
1257  ot->idname = "SEQUENCER_OT_select_linked_pick";
1258  ot->description = "Select a chain of linked strips nearest to the mouse pointer";
1259 
1260  /* Api callbacks. */
1263 
1264  /* Flags. */
1266 
1267  /* Properties. */
1268  PropertyRNA *prop;
1269  prop = RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend the selection");
1271 }
1272 
1275 /* -------------------------------------------------------------------- */
1280 {
1282  bool selected;
1283 
1284  selected = true;
1285  while (selected) {
1286  selected = select_linked_internal(scene);
1287  }
1288 
1290 
1292 
1293  return OPERATOR_FINISHED;
1294 }
1295 
1297 {
1298  /* Identifiers. */
1299  ot->name = "Select Linked";
1300  ot->idname = "SEQUENCER_OT_select_linked";
1301  ot->description = "Select all strips adjacent to the current selection";
1302 
1303  /* Api callbacks. */
1306 
1307  /* Flags. */
1309 }
1310 
1313 /* -------------------------------------------------------------------- */
1317 enum {
1324 };
1325 
1327  {SEQ_SELECT_HANDLES_SIDE_LEFT, "LEFT", 0, "Left", ""},
1328  {SEQ_SELECT_HANDLES_SIDE_RIGHT, "RIGHT", 0, "Right", ""},
1329  {SEQ_SELECT_HANDLES_SIDE_BOTH, "BOTH", 0, "Both", ""},
1330  {SEQ_SELECT_HANDLES_SIDE_LEFT_NEIGHBOR, "LEFT_NEIGHBOR", 0, "Left Neighbor", ""},
1331  {SEQ_SELECT_HANDLES_SIDE_RIGHT_NEIGHBOR, "RIGHT_NEIGHBOR", 0, "Right Neighbor", ""},
1332  {SEQ_SELECT_HANDLES_SIDE_BOTH_NEIGHBORS, "BOTH_NEIGHBORS", 0, "Both Neighbors", ""},
1333  {0, NULL, 0, NULL, NULL},
1334 };
1335 
1337 {
1339  Editing *ed = SEQ_editing_get(scene);
1340  Sequence *seq;
1341  int sel_side = RNA_enum_get(op->ptr, "side");
1342 
1343  for (seq = ed->seqbasep->first; seq; seq = seq->next) {
1344  if (seq->flag & SELECT) {
1347 
1348  switch (sel_side) {
1350  seq->flag &= ~SEQ_RIGHTSEL;
1351  seq->flag |= SEQ_LEFTSEL;
1352  break;
1354  seq->flag &= ~SEQ_LEFTSEL;
1355  seq->flag |= SEQ_RIGHTSEL;
1356  break;
1359  break;
1361  if (l_neighbor) {
1362  if (!(l_neighbor->flag & SELECT)) {
1363  l_neighbor->flag |= SEQ_RIGHTSEL;
1364  }
1365  }
1366  break;
1368  if (r_neighbor) {
1369  if (!(r_neighbor->flag & SELECT)) {
1370  r_neighbor->flag |= SEQ_LEFTSEL;
1371  }
1372  }
1373  break;
1375  if (l_neighbor) {
1376  if (!(l_neighbor->flag & SELECT)) {
1377  l_neighbor->flag |= SEQ_RIGHTSEL;
1378  }
1379  }
1380  if (r_neighbor) {
1381  if (!(r_neighbor->flag & SELECT)) {
1382  r_neighbor->flag |= SEQ_LEFTSEL;
1383  }
1384  break;
1385  }
1386  }
1387  }
1388  }
1389  /* Select strips */
1390  for (seq = ed->seqbasep->first; seq; seq = seq->next) {
1391  if ((seq->flag & SEQ_LEFTSEL) || (seq->flag & SEQ_RIGHTSEL)) {
1392  if (!(seq->flag & SELECT)) {
1393  seq->flag |= SELECT;
1395  }
1396  }
1397  }
1398 
1400 
1402 
1403  return OPERATOR_FINISHED;
1404 }
1405 
1407 {
1408  /* Identifiers. */
1409  ot->name = "Select Handles";
1410  ot->idname = "SEQUENCER_OT_select_handles";
1411  ot->description = "Select gizmo handles on the sides of the selected strip";
1412 
1413  /* Api callbacks. */
1416 
1417  /* Flags. */
1419 
1420  /* Properties. */
1421  RNA_def_enum(ot->srna,
1422  "side",
1425  "Side",
1426  "The side of the handle that is selected");
1427 }
1428 
1431 /* -------------------------------------------------------------------- */
1436 {
1438  Editing *ed = SEQ_editing_get(scene);
1439  const bool extend = RNA_boolean_get(op->ptr, "extend");
1440  const int side = RNA_enum_get(op->ptr, "side");
1441 
1442  if (ed == NULL) {
1443  return OPERATOR_CANCELLED;
1444  }
1445  if (extend == false) {
1447  }
1448  const int timeline_frame = scene->r.cfra;
1450  bool test = false;
1451  switch (side) {
1452  case -1:
1453  test = (timeline_frame >= SEQ_time_right_handle_frame_get(scene, seq));
1454  break;
1455  case 1:
1456  test = (timeline_frame <= SEQ_time_left_handle_frame_get(scene, seq));
1457  break;
1458  case 2:
1459  test = SEQ_time_strip_intersects_frame(scene, seq, timeline_frame);
1460  break;
1461  }
1462 
1463  if (test) {
1464  seq->flag |= SELECT;
1466  }
1467  }
1468 
1470 
1472 
1473  return OPERATOR_FINISHED;
1474 }
1475 
1477 {
1478  static const EnumPropertyItem sequencer_select_left_right_types[] = {
1479  {-1, "LEFT", 0, "Left", "Select to the left of the current frame"},
1480  {1, "RIGHT", 0, "Right", "Select to the right of the current frame"},
1481  {2, "CURRENT", 0, "Current Frame", "Select intersecting with the current frame"},
1482  {0, NULL, 0, NULL, NULL},
1483  };
1484 
1485  /* Identifiers. */
1486  ot->name = "Select Side of Frame";
1487  ot->idname = "SEQUENCER_OT_select_side_of_frame";
1488  ot->description = "Select strips relative to the current frame";
1489 
1490  /* Api callbacks. */
1493 
1494  /* Flags. */
1495  ot->flag = OPTYPE_UNDO;
1496 
1497  /* Properties. */
1498  PropertyRNA *prop;
1499  prop = RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend the selection");
1501  ot->prop = RNA_def_enum(ot->srna, "side", sequencer_select_left_right_types, 0, "Side", "");
1502 }
1503 
1506 /* -------------------------------------------------------------------- */
1511 {
1513  Editing *ed = SEQ_editing_get(scene);
1514 
1515  const int sel_side = RNA_enum_get(op->ptr, "side");
1516  const int frame_init = sel_side == SEQ_SIDE_LEFT ? INT_MIN : INT_MAX;
1517  int frame_ranges[MAXSEQ];
1518  bool selected = false;
1519 
1520  copy_vn_i(frame_ranges, ARRAY_SIZE(frame_ranges), frame_init);
1521 
1523  if (UNLIKELY(seq->machine >= MAXSEQ)) {
1524  continue;
1525  }
1526  int *frame_limit_p = &frame_ranges[seq->machine];
1527  if (seq->flag & SELECT) {
1528  selected = true;
1529  if (sel_side == SEQ_SIDE_LEFT) {
1530  *frame_limit_p = max_ii(*frame_limit_p, SEQ_time_left_handle_frame_get(scene, seq));
1531  }
1532  else {
1533  *frame_limit_p = min_ii(*frame_limit_p, SEQ_time_left_handle_frame_get(scene, seq));
1534  }
1535  }
1536  }
1537 
1538  if (selected == false) {
1539  return OPERATOR_CANCELLED;
1540  }
1541 
1542  select_active_side_range(scene, ed->seqbasep, sel_side, frame_ranges, frame_init);
1543 
1545 
1547 
1548  return OPERATOR_FINISHED;
1549 }
1550 
1552 {
1553  /* Identifiers. */
1554  ot->name = "Select Side";
1555  ot->idname = "SEQUENCER_OT_select_side";
1556  ot->description = "Select strips on the nominated side of the selected strips";
1557 
1558  /* Api callbacks. */
1561 
1562  /* Flags. */
1564 
1565  /* Properties. */
1566  RNA_def_enum(ot->srna,
1567  "side",
1569  SEQ_SIDE_BOTH,
1570  "Side",
1571  "The side to which the selection is applied");
1572 }
1573 
1576 /* -------------------------------------------------------------------- */
1580 static bool seq_box_select_rect_image_isect(const Scene *scene, const Sequence *seq, rctf *rect)
1581 {
1582  float seq_image_quad[4][2];
1583  SEQ_image_transform_final_quad_get(scene, seq, seq_image_quad);
1584  float rect_quad[4][2] = {{rect->xmax, rect->ymax},
1585  {rect->xmax, rect->ymin},
1586  {rect->xmin, rect->ymin},
1587  {rect->xmin, rect->ymax}};
1588 
1589  return seq_point_image_isect(scene, seq, rect_quad[0]) ||
1590  seq_point_image_isect(scene, seq, rect_quad[1]) ||
1591  seq_point_image_isect(scene, seq, rect_quad[2]) ||
1592  seq_point_image_isect(scene, seq, rect_quad[3]) ||
1594  seq_image_quad[0], rect_quad[0], rect_quad[1], rect_quad[2], rect_quad[3]) ||
1596  seq_image_quad[1], rect_quad[0], rect_quad[1], rect_quad[2], rect_quad[3]) ||
1598  seq_image_quad[2], rect_quad[0], rect_quad[1], rect_quad[2], rect_quad[3]) ||
1600  seq_image_quad[3], rect_quad[0], rect_quad[1], rect_quad[2], rect_quad[3]);
1601 }
1602 
1603 static void seq_box_select_seq_from_preview(const bContext *C, rctf *rect, const eSelectOp mode)
1604 {
1606  Editing *ed = SEQ_editing_get(scene);
1607  ListBase *seqbase = SEQ_active_seqbase_get(ed);
1609  SpaceSeq *sseq = CTX_wm_space_seq(C);
1610 
1612  scene, channels, seqbase, scene->r.cfra, sseq->chanshown);
1613  Sequence *seq;
1614  SEQ_ITERATOR_FOREACH (seq, strips) {
1615  if (!seq_box_select_rect_image_isect(scene, seq, rect)) {
1616  continue;
1617  }
1618 
1619  if (ELEM(mode, SEL_OP_ADD, SEL_OP_SET)) {
1620  seq->flag |= SELECT;
1621  }
1622  else {
1623  BLI_assert(mode == SEL_OP_SUB);
1624  seq->flag &= ~SELECT;
1625  }
1626  }
1627 
1628  SEQ_collection_free(strips);
1629 }
1630 
1632 {
1634  View2D *v2d = UI_view2d_fromcontext(C);
1635  Editing *ed = SEQ_editing_get(scene);
1636 
1637  if (ed == NULL) {
1638  return OPERATOR_CANCELLED;
1639  }
1640 
1641  const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode");
1642  const bool handles = RNA_boolean_get(op->ptr, "include_handles");
1643  const bool select = (sel_op != SEL_OP_SUB);
1644 
1645  if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
1647  }
1648 
1649  rctf rectf;
1651  UI_view2d_region_to_view_rctf(v2d, &rectf, &rectf);
1652 
1653  ARegion *region = CTX_wm_region(C);
1654  if (region->regiontype == RGN_TYPE_PREVIEW) {
1656  return OPERATOR_CANCELLED;
1657  }
1658  seq_box_select_seq_from_preview(C, &rectf, sel_op);
1660  return OPERATOR_FINISHED;
1661  }
1662 
1664  rctf rq;
1665  seq_rectf(scene, seq, &rq);
1666  if (BLI_rctf_isect(&rq, &rectf, NULL)) {
1667  if (handles) {
1668  /* Get the handles draw size. */
1669  float pixelx = BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask);
1670  float handsize = sequence_handle_size_get_clamped(scene, seq, pixelx);
1671 
1672  /* Right handle. */
1673  if (rectf.xmax > (SEQ_time_right_handle_frame_get(scene, seq) - handsize)) {
1674  if (select) {
1675  seq->flag |= SELECT | SEQ_RIGHTSEL;
1676  }
1677  else {
1678  /* Deselect the strip if it's left with no handles selected. */
1679  if ((seq->flag & SEQ_RIGHTSEL) && ((seq->flag & SEQ_LEFTSEL) == 0)) {
1680  seq->flag &= ~SELECT;
1681  }
1682  seq->flag &= ~SEQ_RIGHTSEL;
1683  }
1684  }
1685  /* Left handle. */
1686  if (rectf.xmin < (SEQ_time_left_handle_frame_get(scene, seq) + handsize)) {
1687  if (select) {
1688  seq->flag |= SELECT | SEQ_LEFTSEL;
1689  }
1690  else {
1691  /* Deselect the strip if it's left with no handles selected. */
1692  if ((seq->flag & SEQ_LEFTSEL) && ((seq->flag & SEQ_RIGHTSEL) == 0)) {
1693  seq->flag &= ~SELECT;
1694  }
1695  seq->flag &= ~SEQ_LEFTSEL;
1696  }
1697  }
1698  }
1699 
1700  /* Regular box selection. */
1701  else {
1703  seq->flag &= ~(SEQ_LEFTSEL | SEQ_RIGHTSEL);
1704  }
1705  }
1706  }
1707 
1709 
1710  return OPERATOR_FINISHED;
1711 }
1712 
1714 {
1716  View2D *v2d = &CTX_wm_region(C)->v2d;
1717  ARegion *region = CTX_wm_region(C);
1718 
1720  return OPERATOR_CANCELLED;
1721  }
1722 
1723  const bool tweak = RNA_boolean_get(op->ptr, "tweak");
1724 
1725  if (tweak) {
1726  int hand_dummy;
1727  int mval[2];
1728  WM_event_drag_start_mval(event, region, mval);
1729  Sequence *seq = find_nearest_seq(scene, v2d, &hand_dummy, mval);
1730  if (seq != NULL) {
1732  }
1733  }
1734 
1735  return WM_gesture_box_invoke(C, op, event);
1736 }
1737 
1739 {
1740  PropertyRNA *prop;
1741 
1742  /* Identifiers. */
1743  ot->name = "Box Select";
1744  ot->idname = "SEQUENCER_OT_select_box";
1745  ot->description = "Select strips using box selection";
1746 
1747  /* Api callbacks. */
1752 
1754 
1755  /* Flags. */
1756  ot->flag = OPTYPE_UNDO;
1757 
1758  /* Properties. */
1761 
1762  prop = RNA_def_boolean(
1763  ot->srna, "tweak", 0, "Tweak", "Operator has been activated using a click-drag event");
1765  prop = RNA_def_boolean(
1766  ot->srna, "include_handles", 0, "Select Handles", "Select the strips and their handles");
1768 }
1769 
1772 /* -------------------------------------------------------------------- */
1776 enum {
1784 };
1785 
1787  {SEQ_SELECT_GROUP_TYPE, "TYPE", 0, "Type", "Shared strip type"},
1789  "TYPE_BASIC",
1790  0,
1791  "Global Type",
1792  "All strips of same basic type (graphical or sound)"},
1794  "TYPE_EFFECT",
1795  0,
1796  "Effect Type",
1797  "Shared strip effect type (if active strip is not an effect one, select all non-effect "
1798  "strips)"},
1799  {SEQ_SELECT_GROUP_DATA, "DATA", 0, "Data", "Shared data (scene, image, sound, etc.)"},
1800  {SEQ_SELECT_GROUP_EFFECT, "EFFECT", 0, "Effect", "Shared effects"},
1802  "EFFECT_LINK",
1803  0,
1804  "Effect/Linked",
1805  "Other strips affected by the active one (sharing some time, and below or "
1806  "effect-assigned)"},
1807  {SEQ_SELECT_GROUP_OVERLAP, "OVERLAP", 0, "Overlap", "Overlapping time"},
1808  {0, NULL, 0, NULL, NULL},
1809 };
1810 
1811 #define SEQ_IS_SOUND(_seq) ((_seq->type & SEQ_TYPE_SOUND_RAM) && !(_seq->type & SEQ_TYPE_EFFECT))
1812 
1813 #define SEQ_IS_EFFECT(_seq) ((_seq->type & SEQ_TYPE_EFFECT) != 0)
1814 
1815 #define SEQ_USE_DATA(_seq) \
1816  (ELEM(_seq->type, SEQ_TYPE_SCENE, SEQ_TYPE_MOVIECLIP, SEQ_TYPE_MASK) || SEQ_HAS_PATH(_seq))
1817 
1818 #define SEQ_CHANNEL_CHECK(_seq, _chan) (ELEM((_chan), 0, (_seq)->machine))
1819 
1821  ListBase *UNUSED(seqbase),
1822  Sequence *actseq,
1823  const int channel)
1824 {
1825  bool changed = false;
1826 
1827  Sequence *seq;
1828  SEQ_ITERATOR_FOREACH (seq, strips) {
1829  if (SEQ_CHANNEL_CHECK(seq, channel) && seq->type == actseq->type) {
1830  seq->flag |= SELECT;
1831  changed = true;
1832  }
1833  }
1834 
1835  return changed;
1836 }
1837 
1839  ListBase *UNUSED(seqbase),
1840  Sequence *actseq,
1841  const int channel)
1842 {
1843  bool changed = false;
1844  const bool is_sound = SEQ_IS_SOUND(actseq);
1845 
1846  Sequence *seq;
1847  SEQ_ITERATOR_FOREACH (seq, strips) {
1848  if (SEQ_CHANNEL_CHECK(seq, channel) && (is_sound ? SEQ_IS_SOUND(seq) : !SEQ_IS_SOUND(seq))) {
1849  seq->flag |= SELECT;
1850  changed = true;
1851  }
1852  }
1853 
1854  return changed;
1855 }
1856 
1858  ListBase *UNUSED(seqbase),
1859  Sequence *actseq,
1860  const int channel)
1861 {
1862  bool changed = false;
1863  const bool is_effect = SEQ_IS_EFFECT(actseq);
1864 
1865  Sequence *seq;
1866  SEQ_ITERATOR_FOREACH (seq, strips) {
1867  if (SEQ_CHANNEL_CHECK(seq, channel) &&
1868  (is_effect ? SEQ_IS_EFFECT(seq) : !SEQ_IS_EFFECT(seq))) {
1869  seq->flag |= SELECT;
1870  changed = true;
1871  }
1872  }
1873 
1874  return changed;
1875 }
1876 
1878  ListBase *UNUSED(seqbase),
1879  Sequence *actseq,
1880  const int channel)
1881 {
1882  bool changed = false;
1883  const char *dir = actseq->strip ? actseq->strip->dir : NULL;
1884 
1885  if (!SEQ_USE_DATA(actseq)) {
1886  return changed;
1887  }
1888 
1889  Sequence *seq;
1890 
1891  if (SEQ_HAS_PATH(actseq) && dir) {
1892  SEQ_ITERATOR_FOREACH (seq, strips) {
1893  if (SEQ_CHANNEL_CHECK(seq, channel) && SEQ_HAS_PATH(seq) && seq->strip &&
1894  STREQ(seq->strip->dir, dir)) {
1895  seq->flag |= SELECT;
1896  changed = true;
1897  }
1898  }
1899  }
1900  else if (actseq->type == SEQ_TYPE_SCENE) {
1901  Scene *sce = actseq->scene;
1902  SEQ_ITERATOR_FOREACH (seq, strips) {
1903  if (SEQ_CHANNEL_CHECK(seq, channel) && seq->type == SEQ_TYPE_SCENE && seq->scene == sce) {
1904  seq->flag |= SELECT;
1905  changed = true;
1906  }
1907  }
1908  }
1909  else if (actseq->type == SEQ_TYPE_MOVIECLIP) {
1910  MovieClip *clip = actseq->clip;
1911  SEQ_ITERATOR_FOREACH (seq, strips) {
1912  if (SEQ_CHANNEL_CHECK(seq, channel) && seq->type == SEQ_TYPE_MOVIECLIP &&
1913  seq->clip == clip) {
1914  seq->flag |= SELECT;
1915  changed = true;
1916  }
1917  }
1918  }
1919  else if (actseq->type == SEQ_TYPE_MASK) {
1920  struct Mask *mask = actseq->mask;
1921  SEQ_ITERATOR_FOREACH (seq, strips) {
1922  if (SEQ_CHANNEL_CHECK(seq, channel) && seq->type == SEQ_TYPE_MASK && seq->mask == mask) {
1923  seq->flag |= SELECT;
1924  changed = true;
1925  }
1926  }
1927  }
1928 
1929  return changed;
1930 }
1931 
1933  ListBase *UNUSED(seqbase),
1934  Sequence *actseq,
1935  const int channel)
1936 {
1937  bool changed = false;
1938  bool effects[SEQ_TYPE_MAX + 1];
1939 
1940  for (int i = 0; i <= SEQ_TYPE_MAX; i++) {
1941  effects[i] = false;
1942  }
1943 
1944  Sequence *seq;
1945  SEQ_ITERATOR_FOREACH (seq, strips) {
1946  if (SEQ_CHANNEL_CHECK(seq, channel) && (seq->type & SEQ_TYPE_EFFECT) &&
1947  SEQ_relation_is_effect_of_strip(seq, actseq)) {
1948  effects[seq->type] = true;
1949  }
1950  }
1951 
1952  SEQ_ITERATOR_FOREACH (seq, strips) {
1953  if (SEQ_CHANNEL_CHECK(seq, channel) && effects[seq->type]) {
1954  if (seq->seq1) {
1955  seq->seq1->flag |= SELECT;
1956  }
1957  if (seq->seq2) {
1958  seq->seq2->flag |= SELECT;
1959  }
1960  if (seq->seq3) {
1961  seq->seq3->flag |= SELECT;
1962  }
1963  changed = true;
1964  }
1965  }
1966 
1967  return changed;
1968 }
1969 
1971  SeqCollection *strips,
1972  ListBase *UNUSED(seqbase),
1973  Sequence *actseq)
1974 {
1975  bool changed = false;
1976 
1977  Sequence *seq;
1978  SEQ_ITERATOR_FOREACH (seq, strips) {
1983  seq->flag |= SELECT;
1984  changed = true;
1985  }
1986  }
1987 
1988  return changed;
1989 }
1990 
1991 /* Query strips that are in lower channel and intersect in time with seq_reference. */
1993  Sequence *seq_reference,
1994  ListBase *seqbase,
1995  SeqCollection *collection)
1996 {
1997  LISTBASE_FOREACH (Sequence *, seq_test, seqbase) {
1998  if (seq_test->machine > seq_reference->machine) {
1999  continue; /* Not lower channel. */
2000  }
2001  if (SEQ_time_right_handle_frame_get(scene, seq_test) <=
2002  SEQ_time_left_handle_frame_get(scene, seq_reference) ||
2004  SEQ_time_right_handle_frame_get(scene, seq_reference)) {
2005  continue; /* Not intersecting in time. */
2006  }
2007  SEQ_collection_append_strip(seq_test, collection);
2008  }
2009 }
2010 
2011 /* Select all strips within time range and with lower channel of initial selection. Then select
2012  * effect chains of these strips. */
2014  SeqCollection *strips,
2015  ListBase *seqbase,
2016  Sequence *UNUSED(actseq),
2017  const int UNUSED(channel))
2018 {
2019  /* Get collection of strips. */
2021  const int selected_strip_count = SEQ_collection_len(strips);
2022  // XXX this uses scene as arg, so it does not work with iterator :( I had thought about this, but
2023  // expand function is just so useful... I can just add scene and inject it I guess.....
2026 
2027  /* Check if other strips will be affected. */
2028  const bool changed = SEQ_collection_len(strips) > selected_strip_count;
2029 
2030  /* Actual logic. */
2031  Sequence *seq;
2032  SEQ_ITERATOR_FOREACH (seq, strips) {
2033  seq->flag |= SELECT;
2034  }
2035 
2036  return changed;
2037 }
2038 
2039 #undef SEQ_IS_SOUND
2040 #undef SEQ_IS_EFFECT
2041 #undef SEQ_USE_DATA
2042 
2044 {
2048 
2049  const bool is_preview = sequencer_view_has_preview_poll(C);
2050  if (is_preview && !sequencer_view_preview_only_poll(C)) {
2051  return OPERATOR_CANCELLED;
2052  }
2053 
2055 
2056  if (actseq == NULL || (is_preview && !SEQ_collection_has_strip(actseq, strips))) {
2057  BKE_report(op->reports, RPT_ERROR, "No active sequence!");
2058  return OPERATOR_CANCELLED;
2059  }
2060 
2061  const int type = RNA_enum_get(op->ptr, "type");
2062  const int channel = RNA_boolean_get(op->ptr, "use_active_channel") ? actseq->machine : 0;
2063  const bool extend = RNA_boolean_get(op->ptr, "extend");
2064 
2065  bool changed = false;
2066 
2067  if (!extend) {
2068  LISTBASE_FOREACH (Sequence *, seq, seqbase) {
2069  seq->flag &= ~SELECT;
2070  changed = true;
2071  }
2072  }
2073 
2074  switch (type) {
2075  case SEQ_SELECT_GROUP_TYPE:
2076  changed |= select_grouped_type(strips, seqbase, actseq, channel);
2077  break;
2079  changed |= select_grouped_type_basic(strips, seqbase, actseq, channel);
2080  break;
2082  changed |= select_grouped_type_effect(strips, seqbase, actseq, channel);
2083  break;
2084  case SEQ_SELECT_GROUP_DATA:
2085  changed |= select_grouped_data(strips, seqbase, actseq, channel);
2086  break;
2088  changed |= select_grouped_effect(strips, seqbase, actseq, channel);
2089  break;
2091  changed |= select_grouped_effect_link(scene, strips, seqbase, actseq, channel);
2092  break;
2094  changed |= select_grouped_time_overlap(scene, strips, seqbase, actseq);
2095  break;
2096  default:
2097  BLI_assert(0);
2098  break;
2099  }
2100 
2101  SEQ_collection_free(strips);
2102 
2103  if (changed) {
2106  return OPERATOR_FINISHED;
2107  }
2108 
2109  return OPERATOR_CANCELLED;
2110 }
2111 
2113 {
2114  /* Identifiers. */
2115  ot->name = "Select Grouped";
2116  ot->idname = "SEQUENCER_OT_select_grouped";
2117  ot->description = "Select all strips grouped by various properties";
2118 
2119  /* Api callbacks. */
2123 
2124  /* Flags. */
2126 
2127  /* Properties. */
2128  ot->prop = RNA_def_enum(ot->srna, "type", sequencer_prop_select_grouped_types, 0, "Type", "");
2130  "extend",
2131  false,
2132  "Extend",
2133  "Extend selection instead of deselecting everything first");
2135  "use_active_channel",
2136  false,
2137  "Same Channel",
2138  "Only consider strips on the same channel as the active one");
2139 }
2140 
typedef float(TangentPoint)[2]
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1090
struct SpaceSeq * CTX_wm_space_seq(const bContext *C)
Definition: context.c:851
struct ARegion * CTX_wm_region(const bContext *C)
Definition: context.c:749
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition: report.c:83
#define BLI_assert(a)
Definition: BLI_assert.h:46
struct GSet GSet
Definition: BLI_ghash.h:340
unsigned int BLI_ghashutil_ptrhash(const void *key)
GSet * BLI_gset_new(GSetHashFP hashfp, GSetCmpFP cmpfp, const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:947
BLI_INLINE bool BLI_gsetIterator_done(const GSetIterator *gsi)
Definition: BLI_ghash.h:466
bool BLI_ghashutil_ptrcmp(const void *a, const void *b)
BLI_INLINE void BLI_gsetIterator_init(GSetIterator *gsi, GSet *gs)
Definition: BLI_ghash.h:450
void BLI_gset_free(GSet *gs, GSetKeyFreeFP keyfreefp)
Definition: BLI_ghash.c:1037
BLI_INLINE void BLI_gsetIterator_step(GSetIterator *gsi)
Definition: BLI_ghash.h:462
BLI_INLINE void * BLI_gsetIterator_getKey(GSetIterator *gsi)
Definition: BLI_ghash.h:458
bool BLI_gset_add(GSet *gs, void *key)
Definition: BLI_ghash.c:969
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition: listbase.c:466
void void BLI_listbase_sort(struct ListBase *listbase, int(*cmp)(const void *, const void *)) ATTR_NONNULL(1
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:80
MINLINE int min_ii(int a, int b)
MINLINE int max_ii(int a, int b)
MINLINE float square_f(float a)
int isect_point_quad_v2(const float p[2], const float v1[2], const float v2[2], const float v3[2], const float v4[2])
Definition: math_geom.c:1536
MINLINE float len_squared_v2(const float v[2]) ATTR_WARN_UNUSED_RESULT
MINLINE void sub_v2_v2(float r[2], const float a[2])
MINLINE void mul_v2_v2(float r[2], const float a[2])
void copy_vn_i(int *array_tar, int size, int val)
Definition: math_vector.c:1223
#define FILE_MAXDIR
bool BLI_rctf_isect(const struct rctf *src1, const struct rctf *src2, struct rctf *dest)
BLI_INLINE int BLI_rcti_size_x(const struct rcti *rct)
Definition: BLI_rect.h:186
BLI_INLINE float BLI_rctf_size_x(const struct rctf *rct)
Definition: BLI_rect.h:194
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL()
Definition: string.c:64
#define ARRAY_SIZE(arr)
#define UNUSED(x)
#define SET_FLAG_FROM_TEST(value, test, flag)
#define UNLIKELY(x)
#define ELEM(...)
#define STREQ(a, b)
@ RGN_TYPE_PREVIEW
@ SEQ_TYPE_SOUND_RAM
@ SEQ_TYPE_MAX
@ SEQ_TYPE_SCENE
@ SEQ_TYPE_MOVIECLIP
@ SEQ_TYPE_IMAGE
@ SEQ_TYPE_EFFECT
@ SEQ_TYPE_MOVIE
@ SEQ_TYPE_MASK
#define SEQ_HAS_PATH(_seq)
#define SEQ_ALLSEL
@ SEQ_RIGHTSEL
@ SEQ_LEFTSEL
#define SEQ_STRIP_OFSBOTTOM
#define MAXSEQ
#define SEQ_STRIP_OFSTOP
@ SEQ_DRAW_IMG_IMBUF
@ SEQ_MARKER_TRANS
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
@ OPERATOR_PASS_THROUGH
void ED_outliner_select_sync_from_sequence_tag(struct bContext *C)
bool ED_operator_sequencer_active(struct bContext *C)
Definition: screen_ops.c:334
#define SEL_OP_USE_PRE_DESELECT(sel_op)
@ SEL_SELECT
@ SEL_INVERT
@ SEL_DESELECT
@ SEL_TOGGLE
void const char * ED_select_pick_get_name(struct wmOperatorType *ot, PointerRNA *ptr)
eSelectOp
@ SEL_OP_ADD
@ SEL_OP_SUB
@ SEL_OP_SET
void ED_sequencer_deselect_all(struct Scene *scene)
NSNotificationCenter * center
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble GLdouble r _GL_VOID_RET _GL_VOID GLfloat GLfloat r _GL_VOID_RET _GL_VOID GLint GLint r _GL_VOID_RET _GL_VOID GLshort GLshort r _GL_VOID_RET _GL_VOID GLdouble GLdouble r
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
Read Guarded memory(de)allocation.
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position CLAMP
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Sky Generate a procedural sky texture Noise Generate fractal Perlin noise Wave Generate procedural bands or rings with noise Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a point
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert a producing a negative Combine Generate a color from its and blue channels(Deprecated)") DefNode(ShaderNode
@ PROP_SKIP_SAVE
Definition: RNA_types.h:218
#define C
Definition: RandGen.cpp:25
#define SEQ_ITERATOR_FOREACH(var, collection)
Definition: SEQ_iterator.h:35
@ SEQ_SIDE_RIGHT
Definition: SEQ_sequencer.h:32
@ SEQ_SIDE_BOTH
Definition: SEQ_sequencer.h:33
@ SEQ_SIDE_LEFT
Definition: SEQ_sequencer.h:31
@ SEQ_SIDE_NONE
Definition: SEQ_sequencer.h:30
struct View2D * UI_view2d_fromcontext(const struct bContext *C)
void UI_view2d_region_to_view_rctf(const struct View2D *v2d, const struct rctf *rect_src, struct rctf *rect_dst) ATTR_NONNULL()
float UI_view2d_scale_get_y(const struct View2D *v2d)
void UI_view2d_region_to_view(const struct View2D *v2d, float x, float y, float *r_view_x, float *r_view_y) ATTR_NONNULL()
float UI_view2d_region_to_view_x(const struct View2D *v2d, float x)
Definition: view2d.cc:1655
float UI_view2d_scale_get_x(const struct View2D *v2d)
#define ND_SEQUENCER
Definition: WM_types.h:385
@ OPTYPE_UNDO
Definition: WM_types.h:148
@ OPTYPE_REGISTER
Definition: WM_types.h:146
#define NC_SCENE
Definition: WM_types.h:328
#define NA_SELECTED
Definition: WM_types.h:528
__forceinline const avxb select(const avxb &m, const avxb &t, const avxb &f)
Definition: avxb.h:154
unsigned int U
Definition: btGjkEpa3.h:78
ListBase * SEQ_channels_displayed_get(Editing *ed)
Definition: channels.c:23
#define SELECT
Scene scene
SeqCollection * SEQ_query_rendered_strips(const Scene *scene, ListBase *channels, ListBase *seqbase, const int timeline_frame, const int displayed_channel)
Definition: iterator.c:309
uint SEQ_collection_len(const SeqCollection *collection)
Definition: iterator.c:95
void SEQ_filter_selected_strips(SeqCollection *collection)
Definition: iterator.c:366
void SEQ_query_strip_effect_chain(const Scene *scene, Sequence *seq_reference, ListBase *seqbase, SeqCollection *collection)
Definition: iterator.c:335
void SEQ_collection_expand(const Scene *scene, ListBase *seqbase, SeqCollection *collection, void seq_query_func(const Scene *scene, Sequence *seq_reference, ListBase *seqbase, SeqCollection *collection))
Definition: iterator.c:151
SeqCollection * SEQ_query_selected_strips(ListBase *seqbase)
Definition: iterator.c:215
SeqCollection * SEQ_query_all_strips(ListBase *seqbase)
Definition: iterator.c:206
bool SEQ_collection_append_strip(Sequence *seq, SeqCollection *collection)
Definition: iterator.c:117
bool SEQ_collection_has_strip(const Sequence *seq, const SeqCollection *collection)
Definition: iterator.c:100
void SEQ_collection_free(SeqCollection *collection)
Definition: iterator.c:81
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
ccl_device_inline float4 mask(const int4 &mask, const float4 &a)
Definition: math_float4.h:513
#define sqrtf(x)
Definition: metal/compat.h:243
static unsigned a[3]
Definition: RandGen.cpp:78
T abs(const T &a)
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
int RNA_int_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4910
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4863
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:5004
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, bool default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3493
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
Definition: rna_define.c:1490
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, int default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3783
ListBase * SEQ_active_seqbase_get(const Editing *ed)
Definition: sequencer.c:388
Editing * SEQ_editing_get(const Scene *scene)
Definition: sequencer.c:241
static bool is_sound(wmDrag *drag)
float sequence_handle_size_get_clamped(const Scene *scene, Sequence *seq, const float pixelx)
bool sequencer_view_preview_only_poll(const bContext *C)
bool sequencer_view_has_preview_poll(bContext *C)
EnumPropertyItem prop_side_types[]
bool sequencer_edit_poll(bContext *C)
static int seq_sort_for_center_select(const void *a, const void *b)
static int sequencer_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static int sequencer_box_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
#define SEQ_USE_DATA(_seq)
static void select_active_side(const Scene *scene, ListBase *seqbase, int sel_side, int channel, int frame)
static void sequencer_select_do_updates(bContext *C, Scene *scene)
void recurs_sel_seq(Sequence *seq_meta)
static int sequencer_box_select_exec(bContext *C, wmOperator *op)
void SEQUENCER_OT_select_side_of_frame(wmOperatorType *ot)
void SEQUENCER_OT_select_more(wmOperatorType *ot)
static bool select_grouped_type(SeqCollection *strips, ListBase *UNUSED(seqbase), Sequence *actseq, const int channel)
SeqCollection * selected_strips_from_context(bContext *C)
#define SEQ_CHANNEL_CHECK(_seq, _chan)
static int sequencer_select_handles_exec(bContext *C, wmOperator *op)
static void select_surrounding_handles(Scene *scene, Sequence *test)
void ED_sequencer_select_sequence_single(Scene *scene, Sequence *seq, bool deselect_all)
static int sequencer_de_select_all_exec(bContext *C, wmOperator *op)
void SEQUENCER_OT_select_linked_pick(wmOperatorType *ot)
static Sequence * seq_select_seq_from_preview(const bContext *C, const int mval[2], const bool toggle, const bool extend, const bool center)
void SEQUENCER_OT_select_box(wmOperatorType *ot)
@ SEQ_SELECT_HANDLES_SIDE_LEFT_NEIGHBOR
@ SEQ_SELECT_HANDLES_SIDE_LEFT
@ SEQ_SELECT_HANDLES_SIDE_BOTH
@ SEQ_SELECT_HANDLES_SIDE_BOTH_NEIGHBORS
@ SEQ_SELECT_HANDLES_SIDE_RIGHT_NEIGHBOR
@ SEQ_SELECT_HANDLES_SIDE_RIGHT
static bool select_grouped_time_overlap(const Scene *scene, SeqCollection *strips, ListBase *UNUSED(seqbase), Sequence *actseq)
static int seq_sort_for_depth_select(const void *a, const void *b)
static void sequencer_select_set_active(Scene *scene, Sequence *seq)
static int sequencer_select_linked_exec(bContext *C, wmOperator *UNUSED(op))
#define SEQ_IS_EFFECT(_seq)
static const EnumPropertyItem sequencer_prop_select_grouped_types[]
void SEQUENCER_OT_select_linked(wmOperatorType *ot)
static bool select_grouped_type_basic(SeqCollection *strips, ListBase *UNUSED(seqbase), Sequence *actseq, const int channel)
static bool select_grouped_effect_link(const Scene *scene, SeqCollection *strips, ListBase *seqbase, Sequence *UNUSED(actseq), const int UNUSED(channel))
static void sequencer_select_strip_impl(const Editing *ed, Sequence *seq, const int handle_clicked, const bool extend, const bool deselect, const bool toggle)
void SEQUENCER_OT_select_side(wmOperatorType *ot)
static int sequencer_select_less_exec(bContext *C, wmOperator *UNUSED(op))
Sequence * find_nearest_seq(Scene *scene, View2D *v2d, int *hand, const int mval[2])
static bool select_linked_internal(Scene *scene)
void seq_rectf(const Scene *scene, Sequence *seq, rctf *rect)
void SEQUENCER_OT_select(wmOperatorType *ot)
static int sequencer_select_more_exec(bContext *C, wmOperator *UNUSED(op))
static void seq_box_select_seq_from_preview(const bContext *C, rctf *rect, const eSelectOp mode)
static bool element_already_selected(const Sequence *seq, const int handle_clicked)
static bool seq_box_select_rect_image_isect(const Scene *scene, const Sequence *seq, rctf *rect)
static bool select_grouped_data(SeqCollection *strips, ListBase *UNUSED(seqbase), Sequence *actseq, const int channel)
static void query_lower_channel_strips(const Scene *scene, Sequence *seq_reference, ListBase *seqbase, SeqCollection *collection)
void SEQUENCER_OT_select_grouped(wmOperatorType *ot)
void SEQUENCER_OT_select_handles(wmOperatorType *ot)
void SEQUENCER_OT_select_all(struct wmOperatorType *ot)
Sequence * find_neighboring_sequence(Scene *scene, Sequence *test, int lr, int sel)
static const EnumPropertyItem prop_select_handles_side_types[]
static void select_linked_time(const Scene *scene, ListBase *seqbase, Sequence *seq_link)
static int sequencer_select_grouped_exec(bContext *C, wmOperator *op)
static bool select_grouped_type_effect(SeqCollection *strips, ListBase *UNUSED(seqbase), Sequence *actseq, const int channel)
void SEQUENCER_OT_select_inverse(struct wmOperatorType *ot)
void SEQUENCER_OT_select_less(wmOperatorType *ot)
static int sequencer_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static int sequencer_select_inverse_exec(bContext *C, wmOperator *UNUSED(op))
@ SEQ_SELECT_GROUP_TYPE_EFFECT
@ SEQ_SELECT_GROUP_TYPE_BASIC
@ SEQ_SELECT_GROUP_EFFECT_LINK
@ SEQ_SELECT_GROUP_EFFECT
@ SEQ_SELECT_GROUP_OVERLAP
@ SEQ_SELECT_GROUP_TYPE
@ SEQ_SELECT_GROUP_DATA
static void sequencer_select_linked_handle(const bContext *C, Sequence *seq, const int handle_clicked)
static int sequencer_select_side_exec(bContext *C, wmOperator *op)
static bool seq_point_image_isect(const Scene *scene, const Sequence *seq, float point[2])
static int sequencer_select_side_of_frame_exec(bContext *C, wmOperator *op)
static int sequencer_select_exec(bContext *C, wmOperator *op)
static void sequencer_select_side_of_frame(const bContext *C, const View2D *v2d, const int mval[2], Scene *scene)
static void select_active_side_range(const Scene *scene, ListBase *seqbase, const int sel_side, const int frame_ranges[MAXSEQ], const int frame_ignore)
SeqCollection * all_strips_from_context(bContext *C)
static bool select_grouped_effect(SeqCollection *strips, ListBase *UNUSED(seqbase), Sequence *actseq, const int channel)
static bool select_more_less_seq__internal(Scene *scene, bool select_more)
#define SEQ_IS_SOUND(_seq)
bool SEQ_relation_is_effect_of_strip(const Sequence *effect, const Sequence *input)
Sequence * SEQ_select_active_get(Scene *scene)
Definition: strip_select.c:18
void SEQ_select_active_set(Scene *scene, Sequence *seq)
Definition: strip_select.c:29
int SEQ_time_left_handle_frame_get(const Scene *UNUSED(scene), const Sequence *seq)
Definition: strip_time.c:506
bool SEQ_time_strip_intersects_frame(const Scene *scene, const Sequence *seq, const int timeline_frame)
Definition: strip_time.c:437
int SEQ_time_right_handle_frame_get(const Scene *scene, const Sequence *seq)
Definition: strip_time.c:515
void SEQ_image_transform_origin_offset_pixelspace_get(const Scene *scene, const Sequence *seq, float r_origin[2])
void SEQ_image_transform_final_quad_get(const Scene *scene, const Sequence *seq, float r_quad[4][2])
bool SEQ_transform_sequence_can_be_translated(Sequence *seq)
short regiontype
ListBase * seqbasep
Sequence * act_seq
char act_sounddir[1024]
char act_imagedir[1024]
void * first
Definition: DNA_listBase.h:31
struct RenderData r
ListBase markers
struct MovieClip * clip
struct Scene * scene
struct Sequence * seq3
struct Mask * mask
ListBase seqbase
struct Sequence * seq1
struct Sequence * seq2
struct Sequence * next
short chanshown
char dir[768]
unsigned int flag
struct TimeMarker * next
float xmax
Definition: DNA_vec_types.h:69
float xmin
Definition: DNA_vec_types.h:69
float ymax
Definition: DNA_vec_types.h:70
float ymin
Definition: DNA_vec_types.h:70
int mval[2]
Definition: WM_types.h:684
int(* invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:919
const char * name
Definition: WM_types.h:888
int(* modal)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:935
const char * idname
Definition: WM_types.h:890
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:943
void(* cancel)(struct bContext *, struct wmOperator *)
Definition: WM_types.h:927
struct StructRNA * srna
Definition: WM_types.h:969
const char * description
Definition: WM_types.h:893
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:903
PropertyRNA * prop
Definition: WM_types.h:981
const char *(* get_name)(struct wmOperatorType *, struct PointerRNA *)
Definition: WM_types.h:960
struct ReportList * reports
struct PointerRNA * ptr
ParamHandle ** handles
void WM_event_drag_start_mval(const wmEvent *event, const ARegion *region, int r_mval[2])
bool WM_cursor_test_motion_and_update(const int mval[2])
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
wmOperatorType * ot
Definition: wm_files.c:3479
void WM_gesture_box_cancel(bContext *C, wmOperator *op)
int WM_gesture_box_invoke(bContext *C, wmOperator *op, const wmEvent *event)
int WM_gesture_box_modal(bContext *C, wmOperator *op, const wmEvent *event)
void WM_operator_properties_gesture_box(wmOperatorType *ot)
void WM_operator_properties_select_operation_simple(wmOperatorType *ot)
void WM_operator_properties_generic_select(wmOperatorType *ot)
void WM_operator_properties_select_all(wmOperatorType *ot)
void WM_operator_properties_border_to_rctf(struct wmOperator *op, rctf *rect)
void WM_operator_properties_mouse_select(wmOperatorType *ot)
int WM_operator_flag_only_pass_through_on_press(int retval, const struct wmEvent *event)
int WM_generic_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
Definition: wm_operators.c:962
int WM_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
int WM_generic_select_modal(bContext *C, wmOperator *op, const wmEvent *event)
Definition: wm_operators.c:903