Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/blenkernel/BKE_nla.h8
-rw-r--r--source/blender/blenkernel/intern/anim_sys.c47
-rw-r--r--source/blender/blenkernel/intern/nla.c213
-rw-r--r--source/blender/blenloader/intern/readfile.c75
-rw-r--r--source/blender/blenloader/intern/writefile.c30
-rw-r--r--source/blender/editors/space_nla/nla_edit.c120
-rw-r--r--source/blender/editors/space_nla/nla_intern.h11
-rw-r--r--source/blender/makesdna/DNA_anim_types.h9
8 files changed, 385 insertions, 128 deletions
diff --git a/source/blender/blenkernel/BKE_nla.h b/source/blender/blenkernel/BKE_nla.h
index e2b1dd89deb..efa0591bd53 100644
--- a/source/blender/blenkernel/BKE_nla.h
+++ b/source/blender/blenkernel/BKE_nla.h
@@ -53,6 +53,13 @@ struct NlaStrip *add_nlastrip_to_stack(struct AnimData *adt, struct bAction *act
/* ----------------------------- */
/* API */
+short BKE_nlastrips_has_space(ListBase *strips, float start, float end);
+void BKE_nlastrips_sort_strips(ListBase *strips);
+
+short BKE_nlastrips_add_strip(ListBase *strips, struct NlaStrip *strip);
+
+/* ............ */
+
struct NlaTrack *BKE_nlatrack_find_active(ListBase *tracks);
void BKE_nlatrack_set_active(ListBase *tracks, struct NlaTrack *nlt);
@@ -63,6 +70,7 @@ void BKE_nlatrack_sort_strips(struct NlaTrack *nlt);
short BKE_nlatrack_add_strip(struct NlaTrack *nlt, struct NlaStrip *strip);
+/* ............ */
struct NlaStrip *BKE_nlastrip_find_active(struct NlaTrack *nlt);
short BKE_nlastrip_within_bounds(struct NlaStrip *strip, float min, float max);
diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c
index 9befe9dc9cb..1d10744ac80 100644
--- a/source/blender/blenkernel/intern/anim_sys.c
+++ b/source/blender/blenkernel/intern/anim_sys.c
@@ -628,15 +628,13 @@ static void nlastrip_evaluate_controls (NlaStrip *strip, float ctime)
}
-/* gets the strip active at the current time for a track for evaluation purposes */
-static void nlatrack_ctime_get_strip (ListBase *list, NlaTrack *nlt, short index, float ctime)
+/* gets the strip active at the current time for a given list of strips */
+static NlaStrip *ctime_get_strip (ListBase *strips, short *side, float ctime)
{
NlaStrip *strip, *estrip=NULL;
- NlaEvalStrip *nes;
- short side= 0;
/* loop over strips, checking if they fall within the range */
- for (strip= nlt->strips.first; strip; strip= strip->next) {
+ for (strip= strips->first; strip; strip= strip->next) {
/* check if current time occurs within this strip */
if (IN_RANGE_INCL(ctime, strip->start, strip->end)) {
/* this strip is active, so try to use it */
@@ -647,13 +645,13 @@ static void nlatrack_ctime_get_strip (ListBase *list, NlaTrack *nlt, short index
/* if time occurred before current strip... */
if (ctime < strip->start) {
- if (strip == nlt->strips.first) {
+ if (strip == strips->first) {
/* before first strip - only try to use it if it extends backwards in time too */
if (strip->extendmode == NLASTRIP_EXTEND_HOLD)
estrip= strip;
/* side is 'before' regardless of whether there's a useful strip */
- side= NES_TIME_BEFORE;
+ *side= NES_TIME_BEFORE;
}
else {
/* before next strip - previous strip has ended, but next hasn't begun,
@@ -665,7 +663,7 @@ static void nlatrack_ctime_get_strip (ListBase *list, NlaTrack *nlt, short index
if (strip->extendmode != NLASTRIP_EXTEND_NOTHING)
estrip= strip;
- side= NES_TIME_AFTER;
+ *side= NES_TIME_AFTER;
}
break;
}
@@ -673,11 +671,11 @@ static void nlatrack_ctime_get_strip (ListBase *list, NlaTrack *nlt, short index
/* if time occurred after current strip... */
if (ctime > strip->end) {
/* only if this is the last strip should we do anything, and only if that is being held */
- if (strip == nlt->strips.last) {
+ if (strip == strips->last) {
if (strip->extendmode != NLASTRIP_EXTEND_NOTHING)
estrip= strip;
- side= NES_TIME_AFTER;
+ *side= NES_TIME_AFTER;
break;
}
@@ -685,6 +683,35 @@ static void nlatrack_ctime_get_strip (ListBase *list, NlaTrack *nlt, short index
}
}
+ /* return the matching strip found */
+ return estrip;
+}
+
+/* gets the strip active at the current time for a track for evaluation purposes */
+static void nlatrack_ctime_get_strip (ListBase *list, NlaTrack *nlt, short index, float ctime)
+{
+ ListBase *strips= &nlt->strips;
+ NlaStrip *strip, *estrip=NULL;
+ NlaEvalStrip *nes;
+ short side= 0;
+
+ /* keep looping over hierarchy of strips until one which fits for the current time is found */
+ while (strips->first) {
+ /* try to get the strip at this frame for this strip */
+ strip= ctime_get_strip(strips, &side, ctime);
+
+ /* if a strip was found, make this the new estrip, otherwise, stop trying */
+ if (strip) {
+ /* set new estrip */
+ estrip= strip;
+
+ /* check children (only available if this is a meta-strip) for better match */
+ strips= &strip->strips;
+ }
+ else
+ break;
+ }
+
/* check if a valid strip was found
* - must not be muted (i.e. will have contribution
*/
diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c
index 1244b2900fd..d01fa2c1965 100644
--- a/source/blender/blenkernel/intern/nla.c
+++ b/source/blender/blenkernel/intern/nla.c
@@ -68,10 +68,18 @@
*/
void free_nlastrip (ListBase *strips, NlaStrip *strip)
{
+ NlaStrip *cs, *csn;
+
/* sanity checks */
if (strip == NULL)
return;
+ /* free child-strips */
+ for (cs= strip->strips.first; cs; cs= csn) {
+ csn= cs->next;
+ free_nlastrip(&strip->strips, cs);
+ }
+
/* remove reference to action */
if (strip->act)
strip->act->id.us--;
@@ -144,6 +152,7 @@ void free_nladata (ListBase *tracks)
NlaStrip *copy_nlastrip (NlaStrip *strip)
{
NlaStrip *strip_d;
+ NlaStrip *cs, *cs_d;
/* sanity check */
if (strip == NULL)
@@ -161,6 +170,14 @@ NlaStrip *copy_nlastrip (NlaStrip *strip)
copy_fcurves(&strip_d->fcurves, &strip->fcurves);
copy_fmodifiers(&strip_d->modifiers, &strip->modifiers);
+ /* make a copy of all the child-strips, one at a time */
+ strip_d->strips.first= strip_d->strips.last= NULL;
+
+ for (cs= strip->strips.first; cs; cs= cs->next) {
+ cs_d= copy_nlastrip(cs);
+ BLI_addtail(&strip_d->strips, cs_d);
+ }
+
/* return the strip */
return strip_d;
}
@@ -435,6 +452,7 @@ static float nlastrip_get_frame_transition (NlaStrip *strip, float cframe, short
float nlastrip_get_frame (NlaStrip *strip, float cframe, short mode)
{
switch (strip->type) {
+ case NLASTRIP_TYPE_META: /* meta (is just a container for other strips, so shouldn't use the action-clip method) */
case NLASTRIP_TYPE_TRANSITION: /* transition */
return nlastrip_get_frame_transition(strip, cframe, mode);
@@ -487,6 +505,117 @@ float BKE_nla_tweakedit_remap (AnimData *adt, float cframe, short mode)
/* *************************************************** */
/* Basic Utilities */
+/* List of Strips ------------------------------------ */
+/* (these functions are used for NLA-Tracks and also for nested/meta-strips) */
+
+/* Check if there is any space in the given list to add the given strip */
+short BKE_nlastrips_has_space (ListBase *strips, float start, float end)
+{
+ NlaStrip *strip;
+
+ /* sanity checks */
+ if ((strips == NULL) || IS_EQ(start, end))
+ return 0;
+ if (start > end) {
+ puts("BKE_nlastrips_has_space() error... start and end arguments swapped");
+ SWAP(float, start, end);
+ }
+
+ /* loop over NLA strips checking for any overlaps with this area... */
+ for (strip= strips->first; strip; strip= strip->next) {
+ /* 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)
+ return 1;
+
+ /* if the end of the strip is greater than either of the boundaries, the range
+ * must fall within the extents of the strip
+ */
+ if ((strip->end > start) || (strip->end > end))
+ return 0;
+ }
+
+ /* if we are still here, we haven't encountered any overlapping strips */
+ return 1;
+}
+
+/* Rearrange the strips in the track so that they are always in order
+ * (usually only needed after a strip has been moved)
+ */
+void BKE_nlastrips_sort_strips (ListBase *strips)
+{
+ ListBase tmp = {NULL, NULL};
+ NlaStrip *strip, *sstrip;
+
+ /* sanity checks */
+ if ELEM(NULL, strips, strips->first)
+ return;
+
+ /* we simply perform insertion sort on this list, since it is assumed that per track,
+ * there are only likely to be at most 5-10 strips
+ */
+ for (strip= strips->first; strip; strip= strip->next) {
+ short not_added = 1;
+
+ /* remove this strip from the list, and add it to the new list, searching from the end of
+ * the list, assuming that the lists are in order
+ */
+ BLI_remlink(strips, strip);
+
+ for (sstrip= tmp.last; not_added && sstrip; sstrip= sstrip->prev) {
+ /* check if add after */
+ if (sstrip->end < strip->start) {
+ BLI_insertlinkafter(&tmp, sstrip, strip);
+ not_added= 0;
+ break;
+ }
+ }
+
+ /* add before first? */
+ if (not_added)
+ BLI_addhead(&tmp, strip);
+ }
+
+ /* reassign the start and end points of the strips */
+ strips->first= tmp.first;
+ strips->last= tmp.last;
+}
+
+/* Add the given NLA-Strip to the given list of strips, assuming that it
+ * isn't currently a member of another list
+ */
+short BKE_nlastrips_add_strip (ListBase *strips, NlaStrip *strip)
+{
+ NlaStrip *ns;
+ short not_added = 1;
+
+ /* sanity checks */
+ if ELEM(NULL, strips, strip)
+ return 0;
+
+ /* check if any space to add */
+ if (BKE_nlastrips_has_space(strips, strip->start, strip->end)==0)
+ return 0;
+
+ /* 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) {
+ BLI_insertlinkbefore(strips, ns, strip);
+ not_added= 0;
+ break;
+ }
+ }
+ if (not_added) {
+ /* just add to the end of the list of the strips then... */
+ BLI_addtail(strips, strip);
+ }
+
+ /* added... */
+ return 1;
+}
+
/* NLA-Tracks ---------------------------------------- */
/* Find the active NLA-track for the given stack */
@@ -560,36 +689,20 @@ void BKE_nlatrack_set_active (ListBase *tracks, NlaTrack *nlt_a)
nlt_a->flag |= NLATRACK_ACTIVE;
}
-/* Check if there is any space in the last track to add the given strip */
+
+/* Check if there is any space in the given track to add a strip of the given length */
short BKE_nlatrack_has_space (NlaTrack *nlt, float start, float end)
{
- NlaStrip *strip;
-
/* sanity checks */
if ((nlt == NULL) || IS_EQ(start, end))
return 0;
if (start > end) {
- puts("BKE_nlatrack_has_space error... start and end arguments swapped");
+ puts("BKE_nlatrack_has_space() error... start and end arguments swapped");
SWAP(float, start, end);
}
- /* loop over NLA strips checking for any overlaps with this area... */
- for (strip= nlt->strips.first; strip; strip= strip->next) {
- /* 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)
- return 1;
-
- /* if the end of the strip is greater than either of the boundaries, the range
- * must fall within the extents of the strip
- */
- if ((strip->end > start) || (strip->end > end))
- return 0;
- }
-
- /* if we are still here, we haven't encountered any overlapping strips */
- return 1;
+ /* check if there's any space left in the track for a strip of the given length */
+ return BKE_nlastrips_has_space(&nlt->strips, start, end);
}
/* Rearrange the strips in the track so that they are always in order
@@ -597,41 +710,12 @@ short BKE_nlatrack_has_space (NlaTrack *nlt, float start, float end)
*/
void BKE_nlatrack_sort_strips (NlaTrack *nlt)
{
- ListBase tmp = {NULL, NULL};
- NlaStrip *strip, *sstrip;
-
/* sanity checks */
if ELEM(NULL, nlt, nlt->strips.first)
return;
-
- /* we simply perform insertion sort on this list, since it is assumed that per track,
- * there are only likely to be at most 5-10 strips
- */
- for (strip= nlt->strips.first; strip; strip= strip->next) {
- short not_added = 1;
-
- /* remove this strip from the list, and add it to the new list, searching from the end of
- * the list, assuming that the lists are in order
- */
- BLI_remlink(&nlt->strips, strip);
-
- for (sstrip= tmp.last; not_added && sstrip; sstrip= sstrip->prev) {
- /* check if add after */
- if (sstrip->end < strip->start) {
- BLI_insertlinkafter(&tmp, sstrip, strip);
- not_added= 0;
- break;
- }
- }
-
- /* add before first? */
- if (not_added)
- BLI_addhead(&tmp, strip);
- }
- /* reassign the start and end points of the strips */
- nlt->strips.first= tmp.first;
- nlt->strips.last= tmp.last;
+ /* sort the strips with a more generic function */
+ BKE_nlastrips_sort_strips(&nlt->strips);
}
/* Add the given NLA-Strip to the given NLA-Track, assuming that it
@@ -639,33 +723,12 @@ void BKE_nlatrack_sort_strips (NlaTrack *nlt)
*/
short BKE_nlatrack_add_strip (NlaTrack *nlt, NlaStrip *strip)
{
- NlaStrip *ns;
- short not_added = 1;
-
/* sanity checks */
if ELEM(NULL, nlt, strip)
return 0;
- /* check if any space to add */
- if (BKE_nlatrack_has_space(nlt, strip->start, strip->end)==0)
- return 0;
-
- /* find the right place to add the strip to the nominated track */
- for (ns= nlt->strips.first; ns; ns= ns->next) {
- /* if current strip occurs after the new strip, add it before */
- if (ns->start > strip->end) {
- BLI_insertlinkbefore(&nlt->strips, ns, strip);
- not_added= 0;
- break;
- }
- }
- if (not_added) {
- /* just add to the end of the list of the strips then... */
- BLI_addtail(&nlt->strips, strip);
- }
-
- /* added... */
- return 1;
+ /* try to add the strip to the track using a more generic function */
+ return BKE_nlastrips_add_strip(&nlt->strips, strip);
}
/* NLA Strips -------------------------------------- */
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index beebf58b6c0..956c8e0042e 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -1826,18 +1826,48 @@ static void direct_link_action(FileData *fd, bAction *act)
}
}
+static void lib_link_nladata_strips(FileData *fd, ID *id, ListBase *list)
+{
+ NlaStrip *strip;
+
+ for (strip= list->first; strip; strip= strip->next) {
+ /* check strip's children */
+ lib_link_nladata_strips(fd, id, &strip->strips);
+
+ /* reassign the counted-reference to action */
+ strip->act = newlibadr_us(fd, id->lib, strip->act);
+ }
+}
-static void lib_link_nladata (FileData *fd, ID *id, ListBase *list)
+static void lib_link_nladata(FileData *fd, ID *id, ListBase *list)
{
NlaTrack *nlt;
- NlaStrip *strip;
- /* we only acare about the NLA strips inside the tracks */
+ /* we only care about the NLA strips inside the tracks */
for (nlt= list->first; nlt; nlt= nlt->next) {
- for (strip= nlt->strips.first; strip; strip= strip->next) {
- /* reassign the counted-reference to action */
- strip->act = newlibadr_us(fd, id->lib, strip->act);
- }
+ lib_link_nladata_strips(fd, id, &nlt->strips);
+ }
+}
+
+/* This handles Animato NLA-Strips linking
+ * NOTE: this assumes that link_list has already been called on the list
+ */
+static void direct_link_nladata_strips(FileData *fd, ListBase *list)
+{
+ NlaStrip *strip;
+
+ for (strip= list->first; strip; strip= strip->next) {
+ /* strip's child strips */
+ link_list(fd, &strip->strips);
+ direct_link_nladata_strips(fd, &strip->strips);
+
+ /* strip's F-Curves */
+ link_list(fd, &strip->fcurves);
+ direct_link_fcurves(fd, &strip->fcurves);
+
+ /* strip's F-Modifiers */
+ link_list(fd, &strip->modifiers);
+ direct_link_fcurves(fd, &strip->modifiers);
}
}
@@ -1845,22 +1875,13 @@ static void lib_link_nladata (FileData *fd, ID *id, ListBase *list)
static void direct_link_nladata(FileData *fd, ListBase *list)
{
NlaTrack *nlt;
- NlaStrip *strip;
for (nlt= list->first; nlt; nlt= nlt->next) {
/* relink list of strips */
link_list(fd, &nlt->strips);
/* relink strip data */
- for (strip= nlt->strips.first; strip; strip= strip->next) {
- /* strip's F-Curves */
- link_list(fd, &strip->fcurves);
- direct_link_fcurves(fd, &strip->fcurves);
-
- /* strip's F-Modifiers */
- link_list(fd, &strip->modifiers);
- direct_link_fcurves(fd, &strip->modifiers);
- }
+ direct_link_nladata_strips(fd, &nlt->strips);
}
}
@@ -9560,11 +9581,23 @@ static void expand_keyingsets(FileData *fd, Main *mainvar, ListBase *list)
}
}
+static void expand_animdata_nlastrips(FileData *fd, Main *mainvar, ListBase *list)
+{
+ NlaStrip *strip;
+
+ for (strip= list->first; strip; strip= strip->next) {
+ /* check child strips */
+ expand_animdata_nlastrips(fd, mainvar, &strip->strips);
+
+ /* relink referenced action */
+ expand_doit(fd, mainvar, strip->act);
+ }
+}
+
static void expand_animdata(FileData *fd, Main *mainvar, AnimData *adt)
{
FCurve *fcd;
NlaTrack *nlt;
- NlaStrip *strip;
/* own action */
expand_doit(fd, mainvar, adt->action);
@@ -9580,10 +9613,8 @@ static void expand_animdata(FileData *fd, Main *mainvar, AnimData *adt)
}
/* nla-data - referenced actions */
- for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) {
- for (strip= nlt->strips.first; strip; strip= strip->next)
- expand_doit(fd, mainvar, strip->act);
- }
+ for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next)
+ expand_animdata_nlastrips(fd, mainvar, &nlt->strips);
}
static void expand_particlesettings(FileData *fd, Main *mainvar, ParticleSettings *part)
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index 80d1d78257b..bfdd89e38b1 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -916,26 +916,34 @@ static void write_keyingsets(WriteData *wd, ListBase *list)
}
}
+static void write_nlastrips(WriteData *wd, ListBase *strips)
+{
+ NlaStrip *strip;
+
+ for (strip= strips->first; strip; strip= strip->next) {
+ /* write the strip first */
+ writestruct(wd, DATA, "NlaStrip", 1, strip);
+
+ /* write the strip's F-Curves and modifiers */
+ write_fcurves(wd, &strip->fcurves);
+ write_fmodifiers(wd, &strip->modifiers);
+
+ /* write the strip's children */
+ write_nlastrips(wd, &strip->strips);
+ }
+}
+
static void write_nladata(WriteData *wd, ListBase *nlabase)
{
NlaTrack *nlt;
- NlaStrip *strip;
/* write all the tracks */
for (nlt= nlabase->first; nlt; nlt= nlt->next) {
/* write the track first */
writestruct(wd, DATA, "NlaTrack", 1, nlt);
- for (strip= nlt->strips.first; strip; strip= strip->next) {
- /* write the strip first */
- writestruct(wd, DATA, "NlaStrip", 1, strip);
-
- /* write the strip's F-Curves and modifiers */
- write_fcurves(wd, &strip->fcurves);
- write_fmodifiers(wd, &strip->modifiers);
-
- // TODO write the remaps
- }
+ /* write the track's strips */
+ write_nlastrips(wd, &nlt->strips);
}
}
diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c
index 10b25beddff..e95d0b1a50a 100644
--- a/source/blender/editors/space_nla/nla_edit.c
+++ b/source/blender/editors/space_nla/nla_edit.c
@@ -734,8 +734,6 @@ static int nlaedit_move_up_exec (bContext *C, wmOperator *op)
bAnimListElem *ale;
int filter;
- BeztEditData bed;
-
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
return OPERATOR_CANCELLED;
@@ -744,9 +742,6 @@ static int nlaedit_move_up_exec (bContext *C, wmOperator *op)
filter= (ANIMFILTER_VISIBLE | ANIMFILTER_NLATRACKS | ANIMFILTER_FOREDIT);
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
- /* init the editing data */
- memset(&bed, 0, sizeof(BeztEditData));
-
/* since we're potentially moving strips from lower tracks to higher tracks, we should
* loop over the tracks in reverse order to avoid moving earlier strips up multiple tracks
*/
@@ -811,8 +806,6 @@ static int nlaedit_move_down_exec (bContext *C, wmOperator *op)
bAnimListElem *ale;
int filter;
- BeztEditData bed;
-
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
return OPERATOR_CANCELLED;
@@ -821,9 +814,6 @@ static int nlaedit_move_down_exec (bContext *C, wmOperator *op)
filter= (ANIMFILTER_VISIBLE | ANIMFILTER_NLATRACKS | ANIMFILTER_FOREDIT);
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
- /* init the editing data */
- memset(&bed, 0, sizeof(BeztEditData));
-
/* loop through the tracks in normal order, since we're pushing strips down,
* strips won't get operated on twice
*/
@@ -1037,6 +1027,116 @@ void NLA_OT_clear_scale (wmOperatorType *ot)
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
}
+/* ******************** Snap Strips Operator ************************** */
+/* Moves the start-point of the selected strips to the specified places */
+
+/* defines for snap keyframes tool */
+EnumPropertyItem prop_nlaedit_snap_types[] = {
+ {NLAEDIT_SNAP_CFRA, "CFRA", 0, "Current frame", ""},
+ {NLAEDIT_SNAP_NEAREST_FRAME, "NEAREST_FRAME", 0, "Nearest Frame", ""}, // XXX as single entry?
+ {NLAEDIT_SNAP_NEAREST_SECOND, "NEAREST_SECOND", 0, "Nearest Second", ""}, // XXX as single entry?
+ {NLAEDIT_SNAP_NEAREST_MARKER, "NEAREST_MARKER", 0, "Nearest Marker", ""},
+ {0, NULL, 0, NULL, NULL}
+};
+
+static int nlaedit_snap_exec (bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ Scene *scene= ac.scene;
+ int mode = RNA_enum_get(op->ptr, "type");
+ const float secf = (float)FPS;
+
+ /* 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);
+
+ /* since we may add tracks, perform this in reverse order */
+ for (ale= anim_data.last; ale; ale= ale->prev) {
+ ListBase tmp_strips = {NULL, NULL};
+ NlaTrack *nlt= (NlaTrack *)ale->data;
+ NlaStrip *strip, *stripn;
+
+ /* first pass: move all selected strips to a separate buffer, and apply snapping to them */
+ for (strip= nlt->strips.first; strip; strip= stripn) {
+ stripn= strip->next;
+
+ if (strip->flag & NLASTRIP_FLAG_SELECT) {
+ float start, end;
+
+ /* get the existing end-points */
+ start= strip->start;
+ end= strip->end;
+
+ /* calculate new start position based on snapping mode */
+ switch (mode) {
+ case NLAEDIT_SNAP_CFRA: /* to current frame */
+ strip->start= (float)CFRA;
+ break;
+ case NLAEDIT_SNAP_NEAREST_FRAME: /* to nearest frame */
+ strip->start= (float)(floor(start+0.5));
+ break;
+ case NLAEDIT_SNAP_NEAREST_SECOND: /* to nearest second */
+ strip->start= ((float)floor(start/secf + 0.5f) * secf);
+ break;
+ case NLAEDIT_SNAP_NEAREST_MARKER: /* to nearest marker */
+ strip->start= (float)ED_markers_find_nearest_marker_time(ac.markers, start);
+ break;
+ default: /* just in case... no snapping */
+ strip->start= start;
+ break;
+ }
+
+ /* get new endpoint based on start-point (and old length) */
+ strip->end= strip->start + (end - start);
+
+ /* remove strip from track, and add to the temp buffer */
+ BLI_remlink(&nlt->strips, strip);
+ BLI_addtail(&tmp_strips, strip);
+ }
+ }
+
+ // TODO: finish this...
+ }
+
+ /* free temp data */
+ BLI_freelistN(&anim_data);
+
+ /* set notifier that things have changed */
+ ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH);
+ WM_event_add_notifier(C, NC_SCENE, NULL);
+
+ /* done */
+ return OPERATOR_FINISHED;
+}
+
+void NLA_OT_snap (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Snap Strips";
+ ot->idname= "NLA_OT_snap";
+ ot->description= "Move start of strips to specified time.";
+
+ /* api callbacks */
+ ot->invoke= WM_menu_invoke;
+ ot->exec= nlaedit_snap_exec;
+ ot->poll= nlaop_poll_tweakmode_off;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_enum(ot->srna, "type", prop_nlaedit_snap_types, 0, "Type", "");
+}
+
/* *********************************************** */
/* NLA Modifiers */
diff --git a/source/blender/editors/space_nla/nla_intern.h b/source/blender/editors/space_nla/nla_intern.h
index 5921b8a75ce..422686bb424 100644
--- a/source/blender/editors/space_nla/nla_intern.h
+++ b/source/blender/editors/space_nla/nla_intern.h
@@ -87,6 +87,17 @@ void NLA_OT_click_select(wmOperatorType *ot);
/* **************************************** */
/* nla_edit.c */
+/* defines for snap strips
+ */
+enum {
+ NLAEDIT_SNAP_CFRA = 1,
+ NLAEDIT_SNAP_NEAREST_FRAME,
+ NLAEDIT_SNAP_NEAREST_SECOND,
+ NLAEDIT_SNAP_NEAREST_MARKER,
+} eNlaEdit_Snap_Mode;
+
+/* --- */
+
void NLA_OT_tweakmode_enter(wmOperatorType *ot);
void NLA_OT_tweakmode_exit(wmOperatorType *ot);
diff --git a/source/blender/makesdna/DNA_anim_types.h b/source/blender/makesdna/DNA_anim_types.h
index a90fad983c4..a8220099a11 100644
--- a/source/blender/makesdna/DNA_anim_types.h
+++ b/source/blender/makesdna/DNA_anim_types.h
@@ -438,11 +438,13 @@ typedef struct AnimMapper {
typedef struct NlaStrip {
struct NlaStrip *next, *prev;
+ ListBase strips; /* 'Child' strips (used for 'meta' strips) */
bAction *act; /* Action that is referenced by this strip (strip is 'user' of the action) */
AnimMapper *remap; /* Remapping info this strip (for tweaking correspondance of action with context) */
ListBase fcurves; /* F-Curves for controlling this strip's influence and timing */ // TODO: move out?
ListBase modifiers; /* F-Curve modifiers to be applied to the entire strip's referenced F-Curves */
+
float influence; /* Influence of strip */
float strip_time; /* Current 'time' within action being used (automatically evaluated, but can be overridden) */
@@ -505,6 +507,11 @@ enum {
NLASTRIP_FLAG_MUTED = (1<<12),
/* NLA strip length is synced to the length of the referenced action */
NLASTRIP_FLAG_SYNC_LENGTH = (1<<13),
+
+ /* temporary editing flags */
+ /* NLA-Strip is really just a temporary meta used to facilitate easier transform code */
+ NLASTRIP_FLAG_TEMP_META = (1<<30),
+ NLASTRIP_FLAG_EDIT_TOUCHED = (1<<31),
} eNlaStrip_Flag;
/* NLA Strip Type */
@@ -513,6 +520,8 @@ enum {
NLASTRIP_TYPE_CLIP = 0,
/* 'transition' - blends between the adjacent strips */
NLASTRIP_TYPE_TRANSITION,
+ /* 'meta' - a strip which acts as a container for a few others */
+ NLASTRIP_TYPE_META,
} eNlaStrip_Type;
/* NLA Tracks ------------------------------------- */