diff options
Diffstat (limited to 'source/blender/editors/transform/transform_generics.c')
-rw-r--r-- | source/blender/editors/transform/transform_generics.c | 176 |
1 files changed, 130 insertions, 46 deletions
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index e228dc2b13a..9928aea21d0 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -340,67 +340,151 @@ void recalcData(TransInfo *t) } } else if (t->spacetype == SPACE_NLA) { - TransData *td= t->data; + TransDataNla *tdn= (TransDataNla *)t->customData; int i; - /* for each point we've captured, look at its 'extra' data, which is basically a wrapper around the strip - * it is for + some extra storage for the values that get set, and use RNA to set this value (performing validation - * work so that we don't need to repeat it here) + /* for each strip we've got, perform some additional validation of the values that got set before + * using RNA to set the value (which does some special operations when setting these values to make + * sure that everything works ok) */ - for (i = 0; i < t->total; i++, td++) - { - if (td->extra) - { - TransDataNla *tdn= td->extra; - NlaStrip *strip= tdn->strip; + for (i = 0; i < t->total; i++, tdn++) { + NlaStrip *strip= tdn->strip; + PointerRNA strip_ptr; + short pExceeded, nExceeded, iter; + int delta_y1, delta_y2; + + /* if this tdn has no handles, that means it is just a dummy that should be skipped */ + if (tdn->handle == 0) + continue; - /* if we're just cancelling (i.e. the user aborted the transform), - * just restore the data by directly overwriting the values with the original - * ones (i.e. don't go through RNA), as we get some artifacts... + /* if cancelling transform, just write the values without validating, then move on */ + if (t->state == TRANS_CANCEL) { + /* clear the values by directly overwriting the originals, but also need to restore + * endpoints of neighboring transition-strips */ - if (t->state == TRANS_CANCEL) { - /* clear the values by directly overwriting the originals, but also need to restore - * endpoints of neighboring transition-strips + + /* start */ + strip->start= tdn->h1[0]; + + if ((strip->prev) && (strip->prev->type == NLASTRIP_TYPE_TRANSITION)) + strip->prev->end= tdn->h1[0]; + + /* end */ + strip->end= tdn->h2[0]; + + if ((strip->next) && (strip->next->type == NLASTRIP_TYPE_TRANSITION)) + strip->next->start= tdn->h2[0]; + + /* restore to original track (if needed) */ + if (tdn->oldTrack != tdn->nlt) { + /* just append to end of list for now, since strips get sorted in special_aftertrans_update() */ + BLI_remlink(&tdn->nlt->strips, strip); + BLI_addtail(&tdn->oldTrack->strips, strip); + } + + continue; + } + + /* firstly, check if the proposed transform locations would overlap with any neighbouring strips + * (barring transitions) which are absolute barriers since they are not being moved + * + * this is done as a iterative procedure (done 5 times max for now) + */ + for (iter=0; iter < 5; iter++) { + pExceeded= ((strip->prev) && (strip->prev->type != NLASTRIP_TYPE_TRANSITION) && (tdn->h1[0] < strip->prev->end)); + nExceeded= ((strip->next) && (strip->next->type != NLASTRIP_TYPE_TRANSITION) && (tdn->h2[0] > strip->next->start)); + + if ((pExceeded && nExceeded) || (iter == 4) ) { + /* both endpoints exceeded (or iteration ping-pong'd meaning that we need a compromise) + * - simply crop strip to fit within the bounds of the strips bounding it + * - if there were no neighbours, clear the transforms (make it default to the strip's current values) */ - if (tdn->handle) { - strip->end= tdn->val; - - if ((strip->next) && (strip->next->type == NLASTRIP_TYPE_TRANSITION)) - strip->next->start= tdn->val; + if (strip->prev && strip->next) { + tdn->h1[0]= strip->prev->end; + tdn->h2[0]= strip->next->start; } else { - strip->start= tdn->val; - - if ((strip->prev) && (strip->prev->type == NLASTRIP_TYPE_TRANSITION)) - strip->prev->end= tdn->val; + tdn->h1[0]= strip->start; + tdn->h2[0]= strip->end; } } - else { - PointerRNA strip_ptr; + else if (nExceeded) { + /* move backwards */ + float offset= tdn->h2[0] - strip->next->start; - /* make RNA-pointer */ - RNA_pointer_create(NULL, &RNA_NlaStrip, strip, &strip_ptr); + tdn->h1[0] -= offset; + tdn->h2[0] -= offset; + } + else if (pExceeded) { + /* more forwards */ + float offset= strip->prev->end - tdn->h1[0]; - /* write the value set by the transform tools to the appropriate property using RNA */ - if (tdn->handle) - RNA_float_set(&strip_ptr, "end_frame", tdn->val); - else - RNA_float_set(&strip_ptr, "start_frame", tdn->val); + tdn->h1[0] += offset; + tdn->h2[0] += offset; } + else /* all is fine and well */ + break; } - } - - /* loop over the TransDataNla again, flushing the transforms (since we use Metas to make transforms easier) */ - td= t->data; - for (i = 0; i < t->total; i++, td++) - { - if (td->extra) - { - TransDataNla *tdn= td->extra; - NlaStrip *strip= tdn->strip; + + /* use RNA to write the values... */ + // TODO: do we need to write in 2 passes to make sure that no truncation goes on? + RNA_pointer_create(NULL, &RNA_NlaStrip, strip, &strip_ptr); + + RNA_float_set(&strip_ptr, "start_frame", tdn->h1[0]); + RNA_float_set(&strip_ptr, "end_frame", tdn->h2[0]); + + /* flush transforms to child strips (since this should be a meta) */ + BKE_nlameta_flush_transforms(strip); + + + /* now, check if we need to try and move track + * - we need to calculate both, as only one may have been altered by transform if only 1 handle moved + */ + // FIXME: the conversion from vertical distance to track index needs work! + delta_y1= ((int)tdn->h1[0] / NLACHANNEL_SKIP - tdn->trackIndex); + delta_y2= ((int)tdn->h2[0] / NLACHANNEL_SKIP - tdn->trackIndex); + + if (delta_y1 || delta_y2) { + NlaTrack *track; + int delta = (delta_y2) ? delta_y2 : delta_y1; + int n; - // TODO: this may flush some things twice, but that's fine as there's no impact from that - BKE_nlameta_flush_transforms(strip); + /* move in the requested direction, checking at each layer if there's space for strip to pass through, + * stopping on the last track available or that we're able to fit in + */ + if (delta > 0) { + for (track=tdn->nlt->next, n=0; (track) && (n < delta); track=track->next, n++) { + /* check if space in this track for the strip */ + if (BKE_nlatrack_has_space(track, strip->start, strip->end)) { + /* move strip to this track */ + BLI_remlink(&tdn->nlt->strips, strip); + BKE_nlatrack_add_strip(track, strip); + + tdn->nlt= track; + tdn->trackIndex += (n + 1); /* + 1, since n==0 would mean that we didn't change track */ + } + else /* can't move any further */ + break; + } + } + else { + /* make delta 'positive' before using it, since we now know to go backwards */ + delta= -delta; + + for (track=tdn->nlt->prev, n=0; (track) && (n < delta); track=track->prev, n++) { + /* check if space in this track for the strip */ + if (BKE_nlatrack_has_space(track, strip->start, strip->end)) { + /* move strip to this track */ + BLI_remlink(&tdn->nlt->strips, strip); + BKE_nlatrack_add_strip(track, strip); + + tdn->nlt= track; + tdn->trackIndex -= (n - 1); /* - 1, since n==0 would mean that we didn't change track */ + } + else /* can't move any further */ + break; + } + } } } } |