diff options
-rw-r--r-- | release/scripts/ui/space_nla.py | 1 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/nla.c | 6 | ||||
-rw-r--r-- | source/blender/editors/space_nla/nla_edit.c | 158 | ||||
-rw-r--r-- | source/blender/editors/space_nla/nla_intern.h | 1 | ||||
-rw-r--r-- | source/blender/editors/space_nla/nla_ops.c | 4 |
5 files changed, 167 insertions, 3 deletions
diff --git a/release/scripts/ui/space_nla.py b/release/scripts/ui/space_nla.py index 5994b1dcc01..2dc3474ec9c 100644 --- a/release/scripts/ui/space_nla.py +++ b/release/scripts/ui/space_nla.py @@ -139,6 +139,7 @@ class NLA_MT_edit(bpy.types.Menu): layout.operator("nla.clear_scale") layout.separator() + layout.operator("nla.swap") layout.operator("nla.move_up") layout.operator("nla.move_down") diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index 595614ef1e7..ea2948f305e 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -514,7 +514,7 @@ short BKE_nlastrips_has_space (ListBase *strips, float start, float end) /* if start frame of strip is past the target end-frame, that means that * we've gone past the window we need to check for, so things are fine */ - if (strip->start > end) + if (strip->start >= end) return 1; /* if the end of the strip is greater than either of the boundaries, the range @@ -591,7 +591,7 @@ short BKE_nlastrips_add_strip (ListBase *strips, NlaStrip *strip) /* find the right place to add the strip to the nominated track */ for (ns= strips->first; ns; ns= ns->next) { /* if current strip occurs after the new strip, add it before */ - if (ns->start > strip->end) { + if (ns->start >= strip->end) { BLI_insertlinkbefore(strips, ns, strip); not_added= 0; break; @@ -683,7 +683,7 @@ void BKE_nlastrips_clear_metastrip (ListBase *strips, NlaStrip *strip) } /* free the meta-strip now */ - BLI_freelinkN(strips, strip); + free_nlastrip(strips, strip); } /* Remove meta-strips (i.e. flatten the list of strips) from the top-level of the list of strips diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c index d1417d69ae3..921660b0b8b 100644 --- a/source/blender/editors/space_nla/nla_edit.c +++ b/source/blender/editors/space_nla/nla_edit.c @@ -1006,6 +1006,164 @@ void NLA_OT_mute_toggle (wmOperatorType *ot) ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; } +/* ******************** Swap Strips Operator ************************** */ +/* Tries to exchange strips within their owner tracks */ + +static int nlaedit_swap_exec (bContext *C, wmOperator *op) +{ + bAnimContext ac; + + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + /* get a list of the editable tracks being shown in the NLA */ + filter= (ANIMFILTER_VISIBLE | ANIMFILTER_NLATRACKS | ANIMFILTER_FOREDIT); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + /* consider each track in turn */ + for (ale= anim_data.first; ale; ale= ale->next) { + NlaTrack *nlt= (NlaTrack *)ale->data; + + NlaStrip *strip, *stripN=NULL; + NlaStrip *sa=NULL, *sb=NULL; + + /* make temporary metastrips so that entire islands of selections can be moved around */ + BKE_nlastrips_make_metas(&nlt->strips, 1); + + /* special case: if there is only 1 island (i.e. temp meta BUT NOT unselected/normal/normal-meta strips) left after this, + * and this island has two strips inside it, then we should be able to just swap these still... + */ + if (nlt->strips.first == nlt->strips.last) { + NlaStrip *mstrip = (NlaStrip *)nlt->strips.first; + + if ((mstrip->flag & NLASTRIP_FLAG_TEMP_META) && (BLI_countlist(&mstrip->strips) == 2)) + { + /* remove this temp meta, so that we can see the strips inside */ + BKE_nlastrips_clear_metas(&nlt->strips, 0, 1); + } + } + + /* get two selected strips only (these will be metas due to prev step) to operate on + * - only allow swapping 2, as with more the context becomes unclear + */ + for (strip = nlt->strips.first; strip; strip = stripN) { + stripN = strip->next; + + if (strip->flag & NLASTRIP_FLAG_SELECT) { + /* first or second strip? */ + if (sa == NULL) { + /* store as first */ + sa = strip; + } + else if (sb == NULL) { + /* store as second */ + sb = strip; + } + else { + /* too many selected */ + break; + } + } + } + + if (strip) { + /* too many selected warning */ + BKE_reportf(op->reports, RPT_WARNING, + "Too many clusters of strips selected in NLA Track (%s). Needs exactly 2 to be selected.", + nlt->name); + } + else if (sa == NULL) { + /* no warning as this is just a common case, and it may get annoying when doing multiple tracks */ + } + else if (sb == NULL) { + /* too few selected warning */ + BKE_reportf(op->reports, RPT_WARNING, + "Too few clusters of strips selected in NLA Track (%s). Needs exactly 2 to be selected.", + nlt->name); + } + else { + float nsa[2], nsb[2]; + + /* remove these strips from the track, so that we can test if they can fit in the proposed places */ + BLI_remlink(&nlt->strips, sa); + BLI_remlink(&nlt->strips, sb); + + /* calculate new extents for strips */ + /* a --> b */ + nsa[0] = sb->start; + nsa[1] = sb->start + (sa->end - sa->start); + /* b --> a */ + nsb[0] = sa->start; + nsb[1] = sa->start + (sb->end - sb->start); + + /* check if the track has room for the strips to be swapped */ + if (BKE_nlastrips_has_space(&nlt->strips, nsa[0], nsa[1]) && + BKE_nlastrips_has_space(&nlt->strips, nsb[0], nsb[1])) + { + /* set new extents for strips then */ + sa->start = nsa[0]; + sa->end = nsa[1]; + BKE_nlameta_flush_transforms(sa); + + sb->start = nsb[0]; + sb->end = nsb[1]; + BKE_nlameta_flush_transforms(sb); + } + else { + /* not enough room to swap, so show message */ + if ((sa->flag & NLASTRIP_FLAG_TEMP_META) || (sb->flag & NLASTRIP_FLAG_TEMP_META)) { + BKE_report(op->reports, RPT_WARNING, + "Cannot swap selected strips as they will not be able to fit in their new places"); + } + else { + BKE_reportf(op->reports, RPT_WARNING, + "Cannot swap '%s' and '%s' as one or both will not be able to fit in their new places", + sa->name, sb->name); + } + } + + /* add strips back to track now */ + BKE_nlatrack_add_strip(nlt, sa); + BKE_nlatrack_add_strip(nlt, sb); + } + + /* clear (temp) metastrips */ + BKE_nlastrips_clear_metas(&nlt->strips, 0, 1); + } + + /* free temp data */ + BLI_freelistN(&anim_data); + + /* refresh auto strip properties */ + ED_nla_postop_refresh(&ac); + + /* set notifier that things have changed */ + WM_event_add_notifier(C, NC_ANIMATION|ND_NLA|NA_EDITED, NULL); + + /* done */ + return OPERATOR_FINISHED; +} + +void NLA_OT_swap (wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Swap Strips"; + ot->idname= "NLA_OT_swap"; + ot->description= "Swap order of selected strips within tracks"; + + /* api callbacks */ + ot->exec= nlaedit_swap_exec; + ot->poll= nlaop_poll_tweakmode_off; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + /* ******************** Move Strips Up Operator ************************** */ /* Tries to move the selected strips into the track above if possible. */ diff --git a/source/blender/editors/space_nla/nla_intern.h b/source/blender/editors/space_nla/nla_intern.h index 5bf81658fdf..b2ff0e107b3 100644 --- a/source/blender/editors/space_nla/nla_intern.h +++ b/source/blender/editors/space_nla/nla_intern.h @@ -100,6 +100,7 @@ void NLA_OT_split(wmOperatorType *ot); void NLA_OT_mute_toggle(wmOperatorType *ot); +void NLA_OT_swap(wmOperatorType *ot); void NLA_OT_move_up(wmOperatorType *ot); void NLA_OT_move_down(wmOperatorType *ot); diff --git a/source/blender/editors/space_nla/nla_ops.c b/source/blender/editors/space_nla/nla_ops.c index c5d6cde62c6..6a32f02c8ad 100644 --- a/source/blender/editors/space_nla/nla_ops.c +++ b/source/blender/editors/space_nla/nla_ops.c @@ -139,6 +139,7 @@ void nla_operatortypes(void) WM_operatortype_append(NLA_OT_mute_toggle); + WM_operatortype_append(NLA_OT_swap); WM_operatortype_append(NLA_OT_move_up); WM_operatortype_append(NLA_OT_move_down); @@ -225,6 +226,9 @@ static void nla_keymap_main (wmKeyConfig *keyconf, wmKeyMap *keymap) /* toggles */ WM_keymap_add_item(keymap, "NLA_OT_mute_toggle", HKEY, KM_PRESS, 0, 0); + /* swap */ + WM_keymap_add_item(keymap, "NLA_OT_swap", FKEY, KM_PRESS, KM_ALT, 0); + /* move up */ WM_keymap_add_item(keymap, "NLA_OT_move_up", PAGEUPKEY, KM_PRESS, 0, 0); /* move down */ |