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 
20 /** \file
21  * \ingroup edtransform
22  */
23 
24 #include "DNA_anim_types.h"
25 #include "DNA_space_types.h"
26 
27 #include "MEM_guardedalloc.h"
28 
29 #include "BLI_listbase.h"
30 #include "BLI_math.h"
31 
32 #include "BKE_context.h"
33 #include "BKE_nla.h"
34 
35 #include "ED_anim_api.h"
36 #include "ED_markers.h"
37 
38 #include "WM_api.h"
39 
40 #include "RNA_access.h"
41 
42 #include "transform.h"
43 #include "transform_convert.h"
44 
45 /** Used for NLA transform (stored in #TransData.extra pointer). */
46 typedef struct TransDataNla {
47   /** ID-block NLA-data is attached to. */
48   ID *id;
49 
50   /** Original NLA-Track that the strip belongs to. */
51   struct NlaTrack *oldTrack;
52   /** Current NLA-Track that the strip belongs to. */
53   struct NlaTrack *nlt;
54 
55   /** NLA-strip this data represents. */
56   struct NlaStrip *strip;
57 
58   /* dummy values for transform to write in - must have 3 elements... */
59   /** start handle. */
60   float h1[3];
61   /** end handle. */
62   float h2[3];
63 
64   /** index of track that strip is currently in. */
65   int trackIndex;
66   /** handle-index: 0 for dummy entry, -1 for start, 1 for end, 2 for both ends. */
67   int handle;
68 } TransDataNla;
69 
70 /* -------------------------------------------------------------------- */
71 /** \name NLA Transform Creation
72  *
73  * \{ */
74 
createTransNlaData(bContext * C,TransInfo * t)75 void createTransNlaData(bContext *C, TransInfo *t)
76 {
77   Scene *scene = t->scene;
78   SpaceNla *snla = NULL;
79   TransData *td = NULL;
80   TransDataNla *tdn = NULL;
81 
82   bAnimContext ac;
83   ListBase anim_data = {NULL, NULL};
84   bAnimListElem *ale;
85   int filter;
86 
87   int count = 0;
88 
89   TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
90 
91   /* determine what type of data we are operating on */
92   if (ANIM_animdata_get_context(C, &ac) == 0) {
93     return;
94   }
95   snla = (SpaceNla *)ac.sl;
96 
97   /* filter data */
98   filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
99   ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
100 
101   /* which side of the current frame should be allowed */
102   if (t->mode == TFM_TIME_EXTEND) {
103     t->frame_side = transform_convert_frame_side_dir_get(t, (float)CFRA);
104   }
105   else {
106     /* normal transform - both sides of current frame are considered */
107     t->frame_side = 'B';
108   }
109 
110   /* loop 1: count how many strips are selected (consider each strip as 2 points) */
111   for (ale = anim_data.first; ale; ale = ale->next) {
112     NlaTrack *nlt = (NlaTrack *)ale->data;
113     NlaStrip *strip;
114 
115     /* make some meta-strips for chains of selected strips */
116     BKE_nlastrips_make_metas(&nlt->strips, 1);
117 
118     /* only consider selected strips */
119     for (strip = nlt->strips.first; strip; strip = strip->next) {
120       /* TODO: we can make strips have handles later on. */
121       /* transition strips can't get directly transformed */
122       if (strip->type != NLASTRIP_TYPE_TRANSITION) {
123         if (strip->flag & NLASTRIP_FLAG_SELECT) {
124           if (FrameOnMouseSide(t->frame_side, strip->start, (float)CFRA)) {
125             count++;
126           }
127           if (FrameOnMouseSide(t->frame_side, strip->end, (float)CFRA)) {
128             count++;
129           }
130         }
131       }
132     }
133   }
134 
135   /* stop if trying to build list if nothing selected */
136   if (count == 0) {
137     /* clear temp metas that may have been created but aren't needed now
138      * because they fell on the wrong side of CFRA
139      */
140     for (ale = anim_data.first; ale; ale = ale->next) {
141       NlaTrack *nlt = (NlaTrack *)ale->data;
142       BKE_nlastrips_clear_metas(&nlt->strips, 0, 1);
143     }
144 
145     /* cleanup temp list */
146     ANIM_animdata_freelist(&anim_data);
147     return;
148   }
149 
150   /* allocate memory for data */
151   tc->data_len = count;
152 
153   tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransData(NLA Editor)");
154   td = tc->data;
155   tc->custom.type.data = tdn = MEM_callocN(tc->data_len * sizeof(TransDataNla),
156                                            "TransDataNla (NLA Editor)");
157   tc->custom.type.use_free = true;
158 
159   /* loop 2: build transdata array */
160   for (ale = anim_data.first; ale; ale = ale->next) {
161     /* only if a real NLA-track */
162     if (ale->type == ANIMTYPE_NLATRACK) {
163       AnimData *adt = ale->adt;
164       NlaTrack *nlt = (NlaTrack *)ale->data;
165       NlaStrip *strip;
166 
167       /* only consider selected strips */
168       for (strip = nlt->strips.first; strip; strip = strip->next) {
169         /* TODO: we can make strips have handles later on. */
170         /* transition strips can't get directly transformed */
171         if (strip->type != NLASTRIP_TYPE_TRANSITION) {
172           if (strip->flag & NLASTRIP_FLAG_SELECT) {
173             /* our transform data is constructed as follows:
174              * - only the handles on the right side of the current-frame get included
175              * - td structs are transform-elements operated on by the transform system
176              *   and represent a single handle. The storage/pointer used (val or loc) depends on
177              *   whether we're scaling or transforming. Ultimately though, the handles
178              *   the td writes to will simply be a dummy in tdn
179              * - for each strip being transformed, a single tdn struct is used, so in some
180              *   cases, there will need to be 1 of these tdn elements in the array skipped...
181              */
182             float center[3], yval;
183 
184             /* firstly, init tdn settings */
185             tdn->id = ale->id;
186             tdn->oldTrack = tdn->nlt = nlt;
187             tdn->strip = strip;
188             tdn->trackIndex = BLI_findindex(&adt->nla_tracks, nlt);
189 
190             yval = (float)(tdn->trackIndex * NLACHANNEL_STEP(snla));
191 
192             tdn->h1[0] = strip->start;
193             tdn->h1[1] = yval;
194             tdn->h2[0] = strip->end;
195             tdn->h2[1] = yval;
196 
197             center[0] = (float)CFRA;
198             center[1] = yval;
199             center[2] = 0.0f;
200 
201             /* set td's based on which handles are applicable */
202             if (FrameOnMouseSide(t->frame_side, strip->start, (float)CFRA)) {
203               /* just set tdn to assume that it only has one handle for now */
204               tdn->handle = -1;
205 
206               /* now, link the transform data up to this data */
207               if (ELEM(t->mode, TFM_TRANSLATION, TFM_TIME_EXTEND)) {
208                 td->loc = tdn->h1;
209                 copy_v3_v3(td->iloc, tdn->h1);
210 
211                 /* store all the other gunk that is required by transform */
212                 copy_v3_v3(td->center, center);
213                 memset(td->axismtx, 0, sizeof(td->axismtx));
214                 td->axismtx[2][2] = 1.0f;
215 
216                 td->ext = NULL;
217                 td->val = NULL;
218 
219                 td->flag |= TD_SELECTED;
220                 td->dist = 0.0f;
221 
222                 unit_m3(td->mtx);
223                 unit_m3(td->smtx);
224               }
225               else {
226                 /* time scaling only needs single value */
227                 td->val = &tdn->h1[0];
228                 td->ival = tdn->h1[0];
229               }
230 
231               td->extra = tdn;
232               td++;
233             }
234             if (FrameOnMouseSide(t->frame_side, strip->end, (float)CFRA)) {
235               /* if tdn is already holding the start handle,
236                * then we're doing both, otherwise, only end */
237               tdn->handle = (tdn->handle) ? 2 : 1;
238 
239               /* now, link the transform data up to this data */
240               if (ELEM(t->mode, TFM_TRANSLATION, TFM_TIME_EXTEND)) {
241                 td->loc = tdn->h2;
242                 copy_v3_v3(td->iloc, tdn->h2);
243 
244                 /* store all the other gunk that is required by transform */
245                 copy_v3_v3(td->center, center);
246                 memset(td->axismtx, 0, sizeof(td->axismtx));
247                 td->axismtx[2][2] = 1.0f;
248 
249                 td->ext = NULL;
250                 td->val = NULL;
251 
252                 td->flag |= TD_SELECTED;
253                 td->dist = 0.0f;
254 
255                 unit_m3(td->mtx);
256                 unit_m3(td->smtx);
257               }
258               else {
259                 /* time scaling only needs single value */
260                 td->val = &tdn->h2[0];
261                 td->ival = tdn->h2[0];
262               }
263 
264               td->extra = tdn;
265               td++;
266             }
267 
268             /* If both handles were used, skip the next tdn (i.e. leave it blank)
269              * since the counting code is dumb.
270              * Otherwise, just advance to the next one.
271              */
272             if (tdn->handle == 2) {
273               tdn += 2;
274             }
275             else {
276               tdn++;
277             }
278           }
279         }
280       }
281     }
282   }
283 
284   /* cleanup temp list */
285   ANIM_animdata_freelist(&anim_data);
286 }
287 
288 /* helper for recalcData() - for NLA Editor transforms */
recalcData_nla(TransInfo * t)289 void recalcData_nla(TransInfo *t)
290 {
291   SpaceNla *snla = (SpaceNla *)t->area->spacedata.first;
292   Scene *scene = t->scene;
293   double secf = FPS;
294   int i;
295 
296   TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
297   TransDataNla *tdn = tc->custom.type.data;
298 
299   /* For each strip we've got, perform some additional validation of the values
300    * that got set before using RNA to set the value (which does some special
301    * operations when setting these values to make sure that everything works ok).
302    */
303   for (i = 0; i < tc->data_len; i++, tdn++) {
304     NlaStrip *strip = tdn->strip;
305     PointerRNA strip_ptr;
306     short pExceeded, nExceeded, iter;
307     int delta_y1, delta_y2;
308 
309     /* if this tdn has no handles, that means it is just a dummy that should be skipped */
310     if (tdn->handle == 0) {
311       continue;
312     }
313 
314     /* set refresh tags for objects using this animation,
315      * BUT only if realtime updates are enabled
316      */
317     if ((snla->flag & SNLA_NOREALTIMEUPDATES) == 0) {
318       ANIM_id_update(CTX_data_main(t->context), tdn->id);
319     }
320 
321     /* if canceling transform, just write the values without validating, then move on */
322     if (t->state == TRANS_CANCEL) {
323       /* clear the values by directly overwriting the originals, but also need to restore
324        * endpoints of neighboring transition-strips
325        */
326 
327       /* start */
328       strip->start = tdn->h1[0];
329 
330       if ((strip->prev) && (strip->prev->type == NLASTRIP_TYPE_TRANSITION)) {
331         strip->prev->end = tdn->h1[0];
332       }
333 
334       /* end */
335       strip->end = tdn->h2[0];
336 
337       if ((strip->next) && (strip->next->type == NLASTRIP_TYPE_TRANSITION)) {
338         strip->next->start = tdn->h2[0];
339       }
340 
341       /* flush transforms to child strips (since this should be a meta) */
342       BKE_nlameta_flush_transforms(strip);
343 
344       /* restore to original track (if needed) */
345       if (tdn->oldTrack != tdn->nlt) {
346         /* Just append to end of list for now,
347          * since strips get sorted in special_aftertrans_update(). */
348         BLI_remlink(&tdn->nlt->strips, strip);
349         BLI_addtail(&tdn->oldTrack->strips, strip);
350       }
351 
352       continue;
353     }
354 
355     /* firstly, check if the proposed transform locations would overlap with any neighboring strips
356      * (barring transitions) which are absolute barriers since they are not being moved
357      *
358      * this is done as a iterative procedure (done 5 times max for now)
359      */
360     for (iter = 0; iter < 5; iter++) {
361       pExceeded = ((strip->prev) && (strip->prev->type != NLASTRIP_TYPE_TRANSITION) &&
362                    (tdn->h1[0] < strip->prev->end));
363       nExceeded = ((strip->next) && (strip->next->type != NLASTRIP_TYPE_TRANSITION) &&
364                    (tdn->h2[0] > strip->next->start));
365 
366       if ((pExceeded && nExceeded) || (iter == 4)) {
367         /* both endpoints exceeded (or iteration ping-pong'd meaning that we need a compromise)
368          * - Simply crop strip to fit within the bounds of the strips bounding it
369          * - If there were no neighbors, clear the transforms
370          *   (make it default to the strip's current values).
371          */
372         if (strip->prev && strip->next) {
373           tdn->h1[0] = strip->prev->end;
374           tdn->h2[0] = strip->next->start;
375         }
376         else {
377           tdn->h1[0] = strip->start;
378           tdn->h2[0] = strip->end;
379         }
380       }
381       else if (nExceeded) {
382         /* move backwards */
383         float offset = tdn->h2[0] - strip->next->start;
384 
385         tdn->h1[0] -= offset;
386         tdn->h2[0] -= offset;
387       }
388       else if (pExceeded) {
389         /* more forwards */
390         float offset = strip->prev->end - tdn->h1[0];
391 
392         tdn->h1[0] += offset;
393         tdn->h2[0] += offset;
394       }
395       else { /* all is fine and well */
396         break;
397       }
398     }
399 
400     /* handle auto-snapping
401      * NOTE: only do this when transform is still running, or we can't restore
402      */
403     if (t->state != TRANS_CANCEL) {
404       switch (snla->autosnap) {
405         case SACTSNAP_FRAME: /* snap to nearest frame */
406         case SACTSNAP_STEP:  /* frame step - this is basically the same,
407                               * since we don't have any remapping going on */
408         {
409           tdn->h1[0] = floorf(tdn->h1[0] + 0.5f);
410           tdn->h2[0] = floorf(tdn->h2[0] + 0.5f);
411           break;
412         }
413 
414         case SACTSNAP_SECOND: /* snap to nearest second */
415         case SACTSNAP_TSTEP:  /* second step - this is basically the same,
416                                * since we don't have any remapping going on */
417         {
418           /* This case behaves differently from the rest, since lengths of strips
419            * may not be multiples of a second. If we just naively resize adjust
420            * the handles, things may not work correctly. Instead, we only snap
421            * the first handle, and move the other to fit.
422            *
423            * FIXME: we do run into problems here when user attempts to negatively
424            *        scale the strip, as it then just compresses down and refuses
425            *        to expand out the other end.
426            */
427           float h1_new = (float)(floor(((double)tdn->h1[0] / secf) + 0.5) * secf);
428           float delta = h1_new - tdn->h1[0];
429 
430           tdn->h1[0] = h1_new;
431           tdn->h2[0] += delta;
432           break;
433         }
434 
435         case SACTSNAP_MARKER: /* snap to nearest marker */
436         {
437           tdn->h1[0] = (float)ED_markers_find_nearest_marker_time(&t->scene->markers, tdn->h1[0]);
438           tdn->h2[0] = (float)ED_markers_find_nearest_marker_time(&t->scene->markers, tdn->h2[0]);
439           break;
440         }
441       }
442     }
443 
444     /* Use RNA to write the values to ensure that constraints on these are obeyed
445      * (e.g. for transition strips, the values are taken from the neighbors)
446      *
447      * NOTE: we write these twice to avoid truncation errors which can arise when
448      * moving the strips a large distance using numeric input T33852.
449      */
450     RNA_pointer_create(NULL, &RNA_NlaStrip, strip, &strip_ptr);
451 
452     RNA_float_set(&strip_ptr, "frame_start", tdn->h1[0]);
453     RNA_float_set(&strip_ptr, "frame_end", tdn->h2[0]);
454 
455     RNA_float_set(&strip_ptr, "frame_start", tdn->h1[0]);
456     RNA_float_set(&strip_ptr, "frame_end", tdn->h2[0]);
457 
458     /* flush transforms to child strips (since this should be a meta) */
459     BKE_nlameta_flush_transforms(strip);
460 
461     /* Now, check if we need to try and move track:
462      * - we need to calculate both,
463      *   as only one may have been altered by transform if only 1 handle moved.
464      */
465     delta_y1 = ((int)tdn->h1[1] / NLACHANNEL_STEP(snla) - tdn->trackIndex);
466     delta_y2 = ((int)tdn->h2[1] / NLACHANNEL_STEP(snla) - tdn->trackIndex);
467 
468     if (delta_y1 || delta_y2) {
469       NlaTrack *track;
470       int delta = (delta_y2) ? delta_y2 : delta_y1;
471       int n;
472 
473       /* Move in the requested direction,
474        * checking at each layer if there's space for strip to pass through,
475        * stopping on the last track available or that we're able to fit in.
476        */
477       if (delta > 0) {
478         for (track = tdn->nlt->next, n = 0; (track) && (n < delta); track = track->next, n++) {
479           /* check if space in this track for the strip */
480           if (BKE_nlatrack_has_space(track, strip->start, strip->end)) {
481             /* move strip to this track */
482             BLI_remlink(&tdn->nlt->strips, strip);
483             BKE_nlatrack_add_strip(track, strip);
484 
485             tdn->nlt = track;
486             tdn->trackIndex++;
487           }
488           else { /* can't move any further */
489             break;
490           }
491         }
492       }
493       else {
494         /* make delta 'positive' before using it, since we now know to go backwards */
495         delta = -delta;
496 
497         for (track = tdn->nlt->prev, n = 0; (track) && (n < delta); track = track->prev, n++) {
498           /* check if space in this track for the strip */
499           if (BKE_nlatrack_has_space(track, strip->start, strip->end)) {
500             /* move strip to this track */
501             BLI_remlink(&tdn->nlt->strips, strip);
502             BKE_nlatrack_add_strip(track, strip);
503 
504             tdn->nlt = track;
505             tdn->trackIndex--;
506           }
507           else { /* can't move any further */
508             break;
509           }
510         }
511       }
512     }
513   }
514 }
515 
516 /** \} */
517 
518 /* -------------------------------------------------------------------- */
519 /** \name Special After Transform NLA
520  * \{ */
521 
special_aftertrans_update__nla(bContext * C,TransInfo * UNUSED (t))522 void special_aftertrans_update__nla(bContext *C, TransInfo *UNUSED(t))
523 {
524   bAnimContext ac;
525 
526   /* initialize relevant anim-context 'context' data */
527   if (ANIM_animdata_get_context(C, &ac) == 0) {
528     return;
529   }
530 
531   if (ac.datatype) {
532     ListBase anim_data = {NULL, NULL};
533     bAnimListElem *ale;
534     short filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT);
535 
536     /* get channels to work on */
537     ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
538 
539     for (ale = anim_data.first; ale; ale = ale->next) {
540       NlaTrack *nlt = (NlaTrack *)ale->data;
541 
542       /* make sure strips are in order again */
543       BKE_nlatrack_sort_strips(nlt);
544 
545       /* remove the temp metas */
546       BKE_nlastrips_clear_metas(&nlt->strips, 0, 1);
547     }
548 
549     /* free temp memory */
550     ANIM_animdata_freelist(&anim_data);
551 
552     /* perform after-transfrom validation */
553     ED_nla_postop_refresh(&ac);
554   }
555 }
556 
557 /** \} */
558