Blender  V2.93
strip_transform.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
17  * All rights reserved.
18  *
19  * - Blender Foundation, 2003-2009
20  * - Peter Schlaile <peter [at] schlaile [dot] de> 2005/2006
21  */
22 
27 #include "DNA_scene_types.h"
28 #include "DNA_sequence_types.h"
29 
30 #include "BLI_listbase.h"
31 #include "BLI_math.h"
32 
33 #include "BKE_scene.h"
34 #include "BKE_sound.h"
35 
36 #include "SEQ_effects.h"
37 #include "SEQ_relations.h"
38 #include "SEQ_sequencer.h"
39 #include "SEQ_time.h"
40 #include "SEQ_transform.h"
41 
42 static int seq_tx_get_start(Sequence *seq)
43 {
44  return seq->start;
45 }
46 static int seq_tx_get_end(Sequence *seq)
47 {
48  return seq->start + seq->len;
49 }
50 
52 {
53  if (metaclip && seq->tmp) {
54  /* return the range clipped by the parents range */
57  }
58 
59  return (seq->start - seq->startstill) + seq->startofs;
60 }
62 {
63  if (metaclip && seq->tmp) {
64  /* return the range clipped by the parents range */
67  }
68 
69  return ((seq->start + seq->len) + seq->endstill) - seq->endofs;
70 }
71 
73 {
74  if (val < (seq)->start) {
75  seq->startstill = abs(val - (seq)->start);
76  seq->startofs = 0;
77  }
78  else {
79  seq->startofs = abs(val - (seq)->start);
80  seq->startstill = 0;
81  }
82 }
83 
85 {
86  if (val > (seq)->start + (seq)->len) {
87  seq->endstill = abs(val - (seq->start + (seq)->len));
88  seq->endofs = 0;
89  }
90  else {
91  seq->endofs = abs(val - ((seq)->start + (seq)->len));
92  seq->endstill = 0;
93  }
94 }
95 
96 /* used so we can do a quick check for single image seq
97  * since they work a bit differently to normal image seq's (during transform) */
99 {
100  return ((seq->len == 1) &&
101  (seq->type == SEQ_TYPE_IMAGE ||
102  ((seq->type & SEQ_TYPE_EFFECT) && SEQ_effect_get_num_inputs(seq->type) == 0)));
103 }
104 
105 /* check if the selected seq's reference unselected seq's */
107 {
108  Sequence *seq;
109  /* is there more than 1 select */
110  bool ok = false;
111 
112  for (seq = seqbase->first; seq; seq = seq->next) {
113  if (seq->flag & SELECT) {
114  ok = true;
115  break;
116  }
117  }
118 
119  if (ok == false) {
120  return false;
121  }
122 
123  /* test relationships */
124  for (seq = seqbase->first; seq; seq = seq->next) {
125  if ((seq->type & SEQ_TYPE_EFFECT) == 0) {
126  continue;
127  }
128 
129  if (seq->flag & SELECT) {
130  if ((seq->seq1 && (seq->seq1->flag & SELECT) == 0) ||
131  (seq->seq2 && (seq->seq2->flag & SELECT) == 0) ||
132  (seq->seq3 && (seq->seq3->flag & SELECT) == 0)) {
133  return false;
134  }
135  }
136  else {
137  if ((seq->seq1 && (seq->seq1->flag & SELECT)) || (seq->seq2 && (seq->seq2->flag & SELECT)) ||
138  (seq->seq3 && (seq->seq3->flag & SELECT))) {
139  return false;
140  }
141  }
142  }
143 
144  return true;
145 }
146 
151 void SEQ_transform_handle_xlimits(Sequence *seq, int leftflag, int rightflag)
152 {
153  if (leftflag) {
154  if (SEQ_transform_get_left_handle_frame(seq, false) >=
157  SEQ_transform_get_right_handle_frame(seq, false) - 1);
158  }
159 
160  if (SEQ_transform_single_image_check(seq) == 0) {
161  if (SEQ_transform_get_left_handle_frame(seq, false) >= seq_tx_get_end(seq)) {
163  }
164 
165  /* doesn't work now - TODO */
166 #if 0
167  if (seq_tx_get_start(seq) >= seq_tx_get_final_right(seq, 0)) {
168  int ofs;
169  ofs = seq_tx_get_start(seq) - seq_tx_get_final_right(seq, 0);
170  seq->start -= ofs;
171  seq_tx_set_final_left(seq, seq_tx_get_final_left(seq, 0) + ofs);
172  }
173 #endif
174  }
175  }
176 
177  if (rightflag) {
178  if (SEQ_transform_get_right_handle_frame(seq, false) <=
181  SEQ_transform_get_left_handle_frame(seq, false) + 1);
182  }
183 
184  if (SEQ_transform_single_image_check(seq) == 0) {
185  if (SEQ_transform_get_right_handle_frame(seq, false) <= seq_tx_get_start(seq)) {
187  }
188  }
189  }
190 
191  /* sounds cannot be extended past their endpoints */
192  if (seq->type == SEQ_TYPE_SOUND_RAM) {
193  seq->startstill = 0;
194  seq->endstill = 0;
195  }
196 }
197 
199 {
200  int left, start, offset;
202  return;
203  }
204 
205  /* make sure the image is always at the start since there is only one,
206  * adjusting its start should be ok */
208  start = seq->start;
209  if (start != left) {
210  offset = left - start;
212  SEQ_transform_get_left_handle_frame(seq, false) - offset);
214  seq, SEQ_transform_get_right_handle_frame(seq, false) - offset);
215  seq->start += offset;
216  }
217 }
218 
220 {
221  return !(seq->type & SEQ_TYPE_EFFECT) || (SEQ_effect_get_num_inputs(seq->type) == 0);
222 }
223 
224 static bool seq_overlap(Sequence *seq1, Sequence *seq2)
225 {
226  return (seq1 != seq2 && seq1->machine == seq2->machine &&
227  ((seq1->enddisp <= seq2->startdisp) || (seq1->startdisp >= seq2->enddisp)) == 0);
228 }
229 
231 {
232  Sequence *seq;
233 
234  seq = seqbasep->first;
235  while (seq) {
236  if (seq_overlap(test, seq)) {
237  return true;
238  }
239 
240  seq = seq->next;
241  }
242  return false;
243 }
244 
245 void SEQ_transform_translate_sequence(Scene *evil_scene, Sequence *seq, int delta)
246 {
247  if (delta == 0) {
248  return;
249  }
250 
251  SEQ_offset_animdata(evil_scene, seq, delta);
252  seq->start += delta;
253 
254  if (seq->type == SEQ_TYPE_META) {
255  Sequence *seq_child;
256  for (seq_child = seq->seqbase.first; seq_child; seq_child = seq_child->next) {
257  SEQ_transform_translate_sequence(evil_scene, seq_child, delta);
258  }
259  }
260 
261  SEQ_time_update_sequence_bounds(evil_scene, seq);
262 }
263 
264 /* return 0 if there weren't enough space */
266  Sequence *test,
267  Scene *evil_scene,
268  int channel_delta)
269 {
270  const int orig_machine = test->machine;
271  BLI_assert(ELEM(channel_delta, -1, 1));
272 
273  test->machine += channel_delta;
274  SEQ_time_update_sequence(evil_scene, test);
275  while (SEQ_transform_test_overlap(seqbasep, test)) {
276  if ((channel_delta > 0) ? (test->machine >= MAXSEQ) : (test->machine < 1)) {
277  break;
278  }
279 
280  test->machine += channel_delta;
282  evil_scene,
283  test); // XXX - I don't think this is needed since were only moving vertically, Campbell.
284  }
285 
286  if ((test->machine < 1) || (test->machine > MAXSEQ)) {
287  /* Blender 2.4x would remove the strip.
288  * nicer to move it to the end */
289 
290  Sequence *seq;
291  int new_frame = test->enddisp;
292 
293  for (seq = seqbasep->first; seq; seq = seq->next) {
294  if (seq->machine == orig_machine) {
295  new_frame = max_ii(new_frame, seq->enddisp);
296  }
297  }
298 
299  test->machine = orig_machine;
300  new_frame = new_frame + (test->start - test->startdisp); /* adjust by the startdisp */
301  SEQ_transform_translate_sequence(evil_scene, test, new_frame - test->start);
302 
303  SEQ_time_update_sequence(evil_scene, test);
304  return false;
305  }
306 
307  return true;
308 }
309 
310 bool SEQ_transform_seqbase_shuffle(ListBase *seqbasep, Sequence *test, Scene *evil_scene)
311 {
312  return SEQ_transform_seqbase_shuffle_ex(seqbasep, test, evil_scene, 1);
313 }
314 
315 static int shuffle_seq_time_offset_test(ListBase *seqbasep, char dir)
316 {
317  int offset = 0;
318  Sequence *seq, *seq_other;
319 
320  for (seq = seqbasep->first; seq; seq = seq->next) {
321  if (seq->tmp) {
322  for (seq_other = seqbasep->first; seq_other; seq_other = seq_other->next) {
323  if (!seq_other->tmp && seq_overlap(seq, seq_other)) {
324  if (dir == 'L') {
325  offset = min_ii(offset, seq_other->startdisp - seq->enddisp);
326  }
327  else {
328  offset = max_ii(offset, seq_other->enddisp - seq->startdisp);
329  }
330  }
331  }
332  }
333  }
334  return offset;
335 }
336 
337 static int shuffle_seq_time_offset(Scene *scene, ListBase *seqbasep, char dir)
338 {
339  int ofs = 0;
340  int tot_ofs = 0;
341  Sequence *seq;
342  while ((ofs = shuffle_seq_time_offset_test(seqbasep, dir))) {
343  for (seq = seqbasep->first; seq; seq = seq->next) {
344  if (seq->tmp) {
345  /* seq_test_overlap only tests display values */
346  seq->startdisp += ofs;
347  seq->enddisp += ofs;
348  }
349  }
350 
351  tot_ofs += ofs;
352  }
353 
354  for (seq = seqbasep->first; seq; seq = seq->next) {
355  if (seq->tmp) {
356  SEQ_time_update_sequence_bounds(scene, seq); /* corrects dummy startdisp/enddisp values */
357  }
358  }
359 
360  return tot_ofs;
361 }
362 
364  Scene *evil_scene,
365  ListBase *markers,
366  const bool use_sync_markers)
367 {
368  /* note: seq->tmp is used to tag strips to move */
369 
370  Sequence *seq;
371 
372  int offset_l = shuffle_seq_time_offset(evil_scene, seqbasep, 'L');
373  int offset_r = shuffle_seq_time_offset(evil_scene, seqbasep, 'R');
374  int offset = (-offset_l < offset_r) ? offset_l : offset_r;
375 
376  if (offset) {
377  for (seq = seqbasep->first; seq; seq = seq->next) {
378  if (seq->tmp) {
379  SEQ_transform_translate_sequence(evil_scene, seq, offset);
380  seq->flag &= ~SEQ_OVERLAP;
381  }
382  }
383 
384  if (use_sync_markers && !(evil_scene->toolsettings->lock_markers) && (markers != NULL)) {
385  TimeMarker *marker;
386  /* affect selected markers - it's unlikely that we will want to affect all in this way? */
387  for (marker = markers->first; marker; marker = marker->next) {
388  if (marker->flag & SELECT) {
389  marker->frame += offset;
390  }
391  }
392  }
393  }
394 
395  return offset ? false : true;
396 }
397 
407  ListBase *seqbase,
408  const int delta,
409  const int timeline_frame)
410 {
411  LISTBASE_FOREACH (Sequence *, seq, seqbase) {
412  if (seq->startdisp >= timeline_frame) {
416  }
417  }
418 
420  LISTBASE_FOREACH (TimeMarker *, marker, &scene->markers) {
421  if (marker->frame >= timeline_frame) {
422  marker->frame += delta;
423  }
424  }
425  }
426 }
#define BLI_assert(a)
Definition: BLI_assert.h:58
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:172
MINLINE int min_ii(int a, int b)
MINLINE int max_ii(int a, int b)
#define ELEM(...)
@ SEQ_OVERLAP
#define MAXSEQ
@ SEQ_TYPE_SOUND_RAM
@ SEQ_TYPE_META
@ SEQ_TYPE_IMAGE
@ SEQ_TYPE_EFFECT
#define SELECT
Scene scene
int SEQ_effect_get_num_inputs(int seq_type)
Definition: effects.c:4328
const vector< Marker > & markers
static int left
void SEQ_offset_animdata(Scene *scene, Sequence *seq, int ofs)
Definition: sequencer.c:620
void SEQ_relations_invalidate_cache_preprocessed(Scene *scene, Sequence *seq)
void SEQ_time_update_sequence_bounds(Scene *scene, Sequence *seq)
Definition: strip_time.c:150
void SEQ_time_update_sequence(Scene *scene, Sequence *seq)
Definition: strip_time.c:197
bool SEQ_transform_seqbase_isolated_sel_check(ListBase *seqbase)
bool SEQ_transform_seqbase_shuffle_ex(ListBase *seqbasep, Sequence *test, Scene *evil_scene, int channel_delta)
static int seq_tx_get_end(Sequence *seq)
bool SEQ_transform_seqbase_shuffle(ListBase *seqbasep, Sequence *test, Scene *evil_scene)
bool SEQ_transform_sequence_can_be_translated(Sequence *seq)
bool SEQ_transform_test_overlap(ListBase *seqbasep, Sequence *test)
void SEQ_transform_handle_xlimits(Sequence *seq, int leftflag, int rightflag)
void SEQ_transform_fix_single_image_seq_offsets(Sequence *seq)
static bool seq_overlap(Sequence *seq1, Sequence *seq2)
static int shuffle_seq_time_offset(Scene *scene, ListBase *seqbasep, char dir)
void SEQ_transform_set_right_handle_frame(Sequence *seq, int val)
void SEQ_transform_translate_sequence(Scene *evil_scene, Sequence *seq, int delta)
bool SEQ_transform_single_image_check(Sequence *seq)
int SEQ_transform_get_right_handle_frame(Sequence *seq, bool metaclip)
bool SEQ_transform_seqbase_shuffle_time(ListBase *seqbasep, Scene *evil_scene, ListBase *markers, const bool use_sync_markers)
void SEQ_transform_set_left_handle_frame(Sequence *seq, int val)
static int seq_tx_get_start(Sequence *seq)
int SEQ_transform_get_left_handle_frame(Sequence *seq, bool metaclip)
static int shuffle_seq_time_offset_test(ListBase *seqbasep, char dir)
void SEQ_transform_offset_after_frame(Scene *scene, ListBase *seqbase, const int delta, const int timeline_frame)
void * first
Definition: DNA_listBase.h:47
struct ToolSettings * toolsettings
ListBase markers
struct Sequence * seq3
ListBase seqbase
struct Sequence * seq1
struct Sequence * seq2
struct Sequence * next
unsigned int flag
struct TimeMarker * next
__forceinline const avxi abs(const avxi &a)
Definition: util_avxi.h:186
uint len