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_fcurve.h2
-rw-r--r--source/blender/blenkernel/BKE_nla.h2
-rw-r--r--source/blender/blenkernel/intern/anim_sys.c156
-rw-r--r--source/blender/blenkernel/intern/fcurve.c36
-rw-r--r--source/blender/blenkernel/intern/nla.c72
-rw-r--r--source/blender/editors/space_nla/nla_buttons.c65
-rw-r--r--source/blender/editors/space_nla/nla_draw.c23
-rw-r--r--source/blender/editors/space_nla/nla_edit.c229
-rw-r--r--source/blender/editors/space_nla/nla_header.c5
-rw-r--r--source/blender/editors/space_nla/nla_intern.h3
-rw-r--r--source/blender/editors/space_nla/nla_ops.c7
11 files changed, 536 insertions, 64 deletions
diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h
index 7058b9d236a..af272e892f2 100644
--- a/source/blender/blenkernel/BKE_fcurve.h
+++ b/source/blender/blenkernel/BKE_fcurve.h
@@ -112,6 +112,8 @@ void fcurve_free_modifiers(struct FCurve *fcu);
struct FModifier *fcurve_find_active_modifier(struct FCurve *fcu);
void fcurve_set_active_modifier(struct FCurve *fcu, struct FModifier *fcm);
+short fcurve_has_suitable_modifier(FCurve *fcu, int mtype, short acttype);
+
float evaluate_time_fmodifiers(ListBase *modifiers, struct FCurve *fcu, float cvalue, float evaltime);
void evaluate_value_fmodifiers(ListBase *modifiers, struct FCurve *fcu, float *cvalue, float evaltime);
diff --git a/source/blender/blenkernel/BKE_nla.h b/source/blender/blenkernel/BKE_nla.h
index 078c1ba52bb..5200ca6d4d7 100644
--- a/source/blender/blenkernel/BKE_nla.h
+++ b/source/blender/blenkernel/BKE_nla.h
@@ -61,6 +61,8 @@ void BKE_nlatrack_solo_toggle(struct AnimData *adt, struct NlaTrack *nlt);
short BKE_nlatrack_has_space(struct NlaTrack *nlt, float start, float end);
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 a864e3d4e87..2efb4f2b2d3 100644
--- a/source/blender/blenkernel/intern/anim_sys.c
+++ b/source/blender/blenkernel/intern/anim_sys.c
@@ -558,13 +558,20 @@ typedef struct NlaEvalStrip {
short track_index; /* the index of the track within the list */
short strip_mode; /* which end of the strip are we looking at */
+
+ float strip_time; /* time at which which strip is being evaluated */
} NlaEvalStrip;
/* NlaEvalStrip->strip_mode */
enum {
+ /* standard evaluation */
NES_TIME_BEFORE = -1,
NES_TIME_WITHIN,
NES_TIME_AFTER,
+
+ /* transition-strip evaluations */
+ NES_TIME_TRANSITION_START,
+ NES_TIME_TRANSITION_END,
} eNlaEvalStrip_StripMode;
@@ -583,10 +590,10 @@ typedef struct NlaEvalChannel {
/* ---------------------- */
-/* non clipped mapping for strip-time <-> global time
+/* non clipped mapping for strip-time <-> global time (for Action-Clips)
* invert = convert action-strip time to global time
*/
-static float nlastrip_get_frame (NlaStrip *strip, float cframe, short invert)
+static float nlastrip_get_frame_actionclip (NlaStrip *strip, float cframe, short invert)
{
float length, actlength, repeat, scale;
@@ -603,8 +610,8 @@ static float nlastrip_get_frame (NlaStrip *strip, float cframe, short invert)
if (IS_EQ(actlength, 0.0f)) actlength = 1.0f;
/* length of strip */
- length = strip->end - strip->start;
- if (IS_EQ(length, 0.0f)) length= actlength * scale * repeat;
+ length= actlength * scale * repeat;
+ if (IS_EQ(length, 0.0f)) length= strip->end - strip->start;
/* reversed = play strip backwards */
if (strip->flag & NLASTRIP_FLAG_REVERSE) {
@@ -623,6 +630,48 @@ static float nlastrip_get_frame (NlaStrip *strip, float cframe, short invert)
}
}
+/* non clipped mapping for strip-time <-> global time (for Transitions)
+ * invert = convert action-strip time to global time
+ */
+static float nlastrip_get_frame_transition (NlaStrip *strip, float cframe, short invert)
+{
+ float length;
+
+ /* length of strip */
+ length= strip->end - strip->start;
+
+ /* reversed = play strip backwards */
+ if (strip->flag & NLASTRIP_FLAG_REVERSE) {
+ /* invert = convert within-strip-time to global time */
+ if (invert)
+ return strip->end - (length * cframe);
+ else
+ return (strip->end - cframe) / length;
+ }
+ else {
+ /* invert = convert within-strip-time to global time */
+ if (invert)
+ return (length * cframe) + strip->start;
+ else
+ return (cframe - strip->start) / length;
+ }
+}
+
+/* non clipped mapping for strip-time <-> global time
+ * invert = convert action-strip time to global time
+ */
+static float nlastrip_get_frame (NlaStrip *strip, float cframe, short invert)
+{
+ switch (strip->type) {
+ case NLASTRIP_TYPE_TRANSITION: /* transition */
+ return nlastrip_get_frame_transition(strip, cframe, invert);
+
+ case NLASTRIP_TYPE_CLIP: /* action-clip (default) */
+ default:
+ return nlastrip_get_frame_actionclip(strip, cframe, invert);
+ }
+}
+
/* calculate influence of strip based for given frame based on blendin/out values */
static float nlastrip_get_influence (NlaStrip *strip, float cframe)
{
@@ -631,7 +680,6 @@ static float nlastrip_get_influence (NlaStrip *strip, float cframe)
strip->blendout= (float)fabs(strip->blendout);
/* result depends on where frame is in respect to blendin/out values */
- // the +0.0001 factors are to combat rounding errors
if (IS_EQ(strip->blendin, 0)==0 && (cframe <= (strip->start + strip->blendin))) {
/* there is some blend-in */
return (float)fabs(cframe - strip->start) / (strip->blendin);
@@ -746,12 +794,13 @@ static void nlatrack_ctime_get_strip (ListBase *list, NlaTrack *nlt, short index
* - negative influence is not supported yet... how would that be defined?
*/
// TODO: this sounds a bit hacky having a few isolated F-Curves stuck on some data it operates on...
- // TODO: should we clamp the time to only be on the endpoints of the strip?
nlastrip_evaluate_controls(estrip, ctime);
if (estrip->influence <= 0.0f) // XXX is it useful to invert the strip?
return;
- /* check if strip has valid data to evaluate */
+ /* check if strip has valid data to evaluate,
+ * and/or perform any additional type-specific actions
+ */
switch (estrip->type) {
case NLASTRIP_TYPE_CLIP:
/* clip must have some action to evaluate */
@@ -760,9 +809,12 @@ static void nlatrack_ctime_get_strip (ListBase *list, NlaTrack *nlt, short index
break;
case NLASTRIP_TYPE_TRANSITION:
/* there must be strips to transition from and to (i.e. prev and next required) */
- // TODO: what happens about cross-track transitions?
if (ELEM(NULL, estrip->prev, estrip->next))
return;
+
+ /* evaluate controls for the relevant extents of the bordering strips... */
+ nlastrip_evaluate_controls(estrip->prev, estrip->start);
+ nlastrip_evaluate_controls(estrip->next, estrip->end);
break;
}
@@ -773,6 +825,7 @@ static void nlatrack_ctime_get_strip (ListBase *list, NlaTrack *nlt, short index
nes->strip= estrip;
nes->strip_mode= side;
nes->track_index= index;
+ nes->strip_time= estrip->strip_time;
BLI_addtail(list, nes);
}
@@ -847,6 +900,8 @@ static NlaEvalChannel *nlaevalchan_verify (PointerRNA *ptr, ListBase *channels,
nec->prop= prop;
nec->index= fcu->array_index;
}
+ else
+ *newChan= 0;
/* we can now return */
return nec;
@@ -856,6 +911,7 @@ static NlaEvalChannel *nlaevalchan_verify (PointerRNA *ptr, ListBase *channels,
static void nlaevalchan_accumulate (NlaEvalChannel *nec, NlaEvalStrip *nes, short newChan, float value)
{
NlaStrip *strip= nes->strip;
+ short blendmode= strip->blendmode;
float inf= strip->influence;
/* if channel is new, just store value regardless of blending factors, etc. */
@@ -863,13 +919,19 @@ static void nlaevalchan_accumulate (NlaEvalChannel *nec, NlaEvalStrip *nes, shor
nec->value= value;
return;
}
+
+ /* if this is being performed as part of transition evaluation, incorporate
+ * an additional weighting factor for the influence
+ */
+ if (nes->strip_mode == NES_TIME_TRANSITION_END)
+ inf *= nes->strip_time;
/* premultiply the value by the weighting factor */
if (IS_EQ(inf, 0)) return;
value *= inf;
/* perform blending */
- switch (strip->blendmode) {
+ switch (blendmode) {
case NLASTRIP_MODE_ADD:
/* simply add the scaled value on to the stack */
nec->value += value;
@@ -938,8 +1000,80 @@ static void nlastrip_evaluate_actionclip (PointerRNA *ptr, ListBase *channels, N
}
}
+/* evaluate transition strip */
+static void nlastrip_evaluate_transition (PointerRNA *ptr, ListBase *channels, NlaEvalStrip *nes)
+{
+ ListBase tmp_channels = {NULL, NULL};
+ NlaEvalChannel *nec, *necn, *necd;
+ NlaEvalStrip tmp_nes;
+ NlaStrip *s1, *s2;
+
+ /* get the two strips to operate on
+ * - we use the endpoints of the strips directly flanking our strip
+ * using these as the endpoints of the transition (destination and source)
+ * - these should have already been determined to be valid...
+ * - if this strip is being played in reverse, we need to swap these endpoints
+ * otherwise they will be interpolated wrong
+ */
+ if (nes->strip->flag & NLASTRIP_FLAG_REVERSE) {
+ s1= nes->strip->next;
+ s2= nes->strip->prev;
+ }
+ else {
+ s1= nes->strip->prev;
+ s2= nes->strip->next;
+ }
+
+ /* prepare template for 'evaluation strip'
+ * - based on the transition strip's evaluation strip data
+ * - strip_mode is NES_TIME_TRANSITION_* based on which endpoint
+ * - strip_time is the 'normalised' (i.e. in-strip) time for evaluation,
+ * which doubles up as an additional weighting factor for the strip influences
+ * which allows us to appear to be 'interpolating' between the two extremes
+ */
+ tmp_nes= *nes;
+
+ /* evaluate these strips into a temp-buffer (tmp_channels) */
+ /* first strip */
+ tmp_nes.strip_mode= NES_TIME_TRANSITION_START;
+ tmp_nes.strip= s1;
+ nlastrip_evaluate_actionclip(ptr, &tmp_channels, &tmp_nes);
+
+ /* second strip */
+ tmp_nes.strip_mode= NES_TIME_TRANSITION_END;
+ tmp_nes.strip= s2;
+ nlastrip_evaluate_actionclip(ptr, &tmp_channels, &tmp_nes);
+
+
+ /* optimise - abort if no channels */
+ if (tmp_channels.first == NULL)
+ return;
+
+
+ /* accumulate results in tmp_channels buffer to the accumulation buffer */
+ for (nec= tmp_channels.first; nec; nec= necn) {
+ /* get pointer to next channel in case we remove the current channel from the temp-buffer */
+ necn= nec->next;
+
+ /* try to find an existing matching channel for this setting in the accumulation buffer */
+ necd= nlaevalchan_find_match(channels, &nec->ptr, nec->prop, nec->index);
+
+ /* if there was a matching channel already in the buffer, accumulate to it,
+ * otherwise, add the current channel to the buffer for efficiency
+ */
+ if (necd)
+ nlaevalchan_accumulate(necd, nes, 0, nec->value);
+ else {
+ BLI_remlink(&tmp_channels, nec);
+ BLI_addtail(channels, nec);
+ }
+ }
+
+ /* free temp-channels that haven't been assimilated into the buffer */
+ BLI_freelistN(&tmp_channels);
+}
+
/* evaluates the given evaluation strip */
-// TODO: only evaluate here, but flush in one go using the accumulated channels at end...
static void nlastrip_evaluate (PointerRNA *ptr, ListBase *channels, NlaEvalStrip *nes)
{
/* actions to take depend on the type of strip */
@@ -948,7 +1082,7 @@ static void nlastrip_evaluate (PointerRNA *ptr, ListBase *channels, NlaEvalStrip
nlastrip_evaluate_actionclip(ptr, channels, nes);
break;
case NLASTRIP_TYPE_TRANSITION: /* transition */
- // XXX code this...
+ nlastrip_evaluate_transition(ptr, channels, nes);
break;
}
}
diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c
index 5820761234c..d8b5135a1b1 100644
--- a/source/blender/blenkernel/intern/fcurve.c
+++ b/source/blender/blenkernel/intern/fcurve.c
@@ -2242,6 +2242,42 @@ void fcurve_set_active_modifier (FCurve *fcu, FModifier *fcm)
fcm->flag |= FMODIFIER_FLAG_ACTIVE;
}
+/* Do we have any modifiers which match certain criteria
+ * - mtype - type of modifier (if 0, doesn't matter)
+ * - acttype - type of action to perform (if -1, doesn't matter)
+ */
+short fcurve_has_suitable_modifier (FCurve *fcu, int mtype, short acttype)
+{
+ FModifier *fcm;
+
+ /* if there are no specific filtering criteria, just skip */
+ if ((mtype == 0) && (acttype == 0))
+ return (fcu && fcu->modifiers.first);
+
+ /* sanity checks */
+ if ELEM(NULL, fcu, fcu->modifiers.first)
+ return 0;
+
+ /* find the first mdifier fitting these criteria */
+ for (fcm= fcu->modifiers.first; fcm; fcm= fcm->next) {
+ FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
+ short mOk=1, aOk=1; /* by default 1, so that when only one test, won't fail */
+
+ /* check if applicable ones are fullfilled */
+ if (mtype)
+ mOk= (fcm->type == mtype);
+ if (acttype > -1)
+ aOk= (fmi->acttype == acttype);
+
+ /* if both are ok, we've found a hit */
+ if (mOk && aOk)
+ return 1;
+ }
+
+ /* no matches */
+ return 0;
+}
+
/* Evaluation API --------------------------- */
/* evaluate time modifications imposed by some F-Curve Modifiers
diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c
index cef14128032..0684d943754 100644
--- a/source/blender/blenkernel/intern/nla.c
+++ b/source/blender/blenkernel/intern/nla.c
@@ -293,9 +293,8 @@ NlaStrip *add_nlastrip (bAction *act)
/* Add new NLA-strip to the top of the NLA stack - i.e. into the last track if space, or a new one otherwise */
NlaStrip *add_nlastrip_to_stack (AnimData *adt, bAction *act)
{
- NlaStrip *strip, *ns;
+ NlaStrip *strip;
NlaTrack *nlt;
- short not_added = 1;
/* sanity checks */
if ELEM(NULL, adt, act)
@@ -306,36 +305,15 @@ NlaStrip *add_nlastrip_to_stack (AnimData *adt, bAction *act)
if (strip == NULL)
return NULL;
- /* check if the last NLA-track (if it exists) has any space for this strip:
- * - if so, add this strip to that track
- */
- if ( (adt->nla_tracks.last == NULL) ||
- (BKE_nlatrack_has_space(adt->nla_tracks.last, strip->start, strip->end)==0) )
- {
- /* no space, so add to a new track... */
+ /* firstly try adding strip to last track, but if that fails, add to a new track */
+ if (BKE_nlatrack_add_strip(adt->nla_tracks.last, strip) == 0) {
+ /* trying to add to the last track failed (no track or no space),
+ * so add a new track to the stack, and add to that...
+ */
nlt= add_nlatrack(adt, NULL);
- }
- else
- {
- /* there's some space, so add to this track... */
- nlt= adt->nla_tracks.last;
+ BKE_nlatrack_add_strip(nlt, strip);
}
- /* 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);
- }
-
-
/* returns the strip added */
return strip;
}
@@ -490,6 +468,40 @@ void BKE_nlatrack_sort_strips (NlaTrack *nlt)
nlt->strips.last= tmp.last;
}
+/* Add the given NLA-Strip to the given NLA-Track, assuming that it
+ * isn't currently attached to another one
+ */
+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;
+}
+
/* NLA Strips -------------------------------------- */
/* Find the active NLA-strip within the given track */
@@ -571,7 +583,7 @@ short nlastrip_is_first (AnimData *adt, NlaStrip *strip)
/* should be first now */
return 1;
}
-
+
/* Tools ------------------------------------------- */
/* For the given AnimData block, add the active action to the NLA
diff --git a/source/blender/editors/space_nla/nla_buttons.c b/source/blender/editors/space_nla/nla_buttons.c
index cb21dd66934..cb76f7fc735 100644
--- a/source/blender/editors/space_nla/nla_buttons.c
+++ b/source/blender/editors/space_nla/nla_buttons.c
@@ -144,11 +144,38 @@ static int nla_panel_context(const bContext *C, PointerRNA *nlt_ptr, PointerRNA
return found;
}
+#if 0
static int nla_panel_poll(const bContext *C, PanelType *pt)
{
return nla_panel_context(C, NULL, NULL);
}
+#endif
+static int nla_track_panel_poll(const bContext *C, PanelType *pt)
+{
+ PointerRNA ptr;
+ return (nla_panel_context(C, &ptr, NULL) && (ptr.data != NULL));
+}
+
+static int nla_strip_panel_poll(const bContext *C, PanelType *pt)
+{
+ PointerRNA ptr;
+ return (nla_panel_context(C, NULL, &ptr) && (ptr.data != NULL));
+}
+
+static int nla_strip_actclip_panel_poll(const bContext *C, PanelType *pt)
+{
+ PointerRNA ptr;
+ NlaStrip *strip;
+
+ if (!nla_panel_context(C, NULL, &ptr))
+ return 0;
+ if (ptr.data == NULL)
+ return 0;
+
+ strip= ptr.data;
+ return (strip->type == NLASTRIP_TYPE_CLIP);
+}
/* -------------- */
@@ -163,8 +190,6 @@ static void nla_panel_track (const bContext *C, Panel *pa)
/* check context and also validity of pointer */
if (!nla_panel_context(C, &nlt_ptr, NULL))
return;
- if (nlt_ptr.data == NULL)
- return;
block= uiLayoutGetBlock(layout);
uiBlockSetHandleFunc(block, do_nla_region_buttons, NULL);
@@ -185,8 +210,6 @@ static void nla_panel_properties(const bContext *C, Panel *pa)
/* check context and also validity of pointer */
if (!nla_panel_context(C, NULL, &strip_ptr))
return;
- if (strip_ptr.data == NULL)
- return;
block= uiLayoutGetBlock(layout);
uiBlockSetHandleFunc(block, do_nla_region_buttons, NULL);
@@ -239,8 +262,6 @@ static void nla_panel_actclip(const bContext *C, Panel *pa)
/* check context and also validity of pointer */
if (!nla_panel_context(C, NULL, &strip_ptr))
return;
- if (strip_ptr.data == NULL)
- return;
// XXX FIXME: move this check into a poll callback
if (RNA_enum_get(&strip_ptr, "type") != NLASTRIP_TYPE_CLIP)
@@ -279,8 +300,6 @@ static void nla_panel_evaluation(const bContext *C, Panel *pa)
/* check context and also validity of pointer */
if (!nla_panel_context(C, NULL, &strip_ptr))
return;
- if (strip_ptr.data == NULL)
- return;
block= uiLayoutGetBlock(layout);
uiBlockSetHandleFunc(block, do_nla_region_buttons, NULL);
@@ -291,6 +310,24 @@ static void nla_panel_evaluation(const bContext *C, Panel *pa)
// animated_time
}
+/* F-Modifiers for active NLA-Strip */
+static void nla_panel_modifiers(const bContext *C, Panel *pa)
+{
+ PointerRNA strip_ptr;
+ uiLayout *layout= pa->layout;
+ //uiLayout *column, *row, *subcol;
+ uiBlock *block;
+
+ /* check context and also validity of pointer */
+ if (!nla_panel_context(C, NULL, &strip_ptr))
+ return;
+
+ block= uiLayoutGetBlock(layout);
+ uiBlockSetHandleFunc(block, do_nla_region_buttons, NULL);
+
+ // TODO...
+}
+
/* ******************* general ******************************** */
@@ -302,35 +339,35 @@ void nla_buttons_register(ARegionType *art)
strcpy(pt->idname, "NLA_PT_track");
strcpy(pt->label, "Active Track");
pt->draw= nla_panel_track;
- pt->poll= nla_panel_poll;
+ pt->poll= nla_track_panel_poll;
BLI_addtail(&art->paneltypes, pt);
pt= MEM_callocN(sizeof(PanelType), "spacetype nla panel properties");
strcpy(pt->idname, "NLA_PT_properties");
strcpy(pt->label, "Active Strip");
pt->draw= nla_panel_properties;
- pt->poll= nla_panel_poll;
+ pt->poll= nla_strip_panel_poll;
BLI_addtail(&art->paneltypes, pt);
pt= MEM_callocN(sizeof(PanelType), "spacetype nla panel properties");
strcpy(pt->idname, "NLA_PT_actionclip");
strcpy(pt->label, "Action Clip");
pt->draw= nla_panel_actclip;
- pt->poll= nla_panel_poll; // XXX need a special one to check for 'action clip' types only
+ pt->poll= nla_strip_actclip_panel_poll;
BLI_addtail(&art->paneltypes, pt);
pt= MEM_callocN(sizeof(PanelType), "spacetype nla panel evaluation");
strcpy(pt->idname, "NLA_PT_evaluation");
strcpy(pt->label, "Evaluation");
pt->draw= nla_panel_evaluation;
- pt->poll= nla_panel_poll;
+ pt->poll= nla_strip_panel_poll;
BLI_addtail(&art->paneltypes, pt);
pt= MEM_callocN(sizeof(PanelType), "spacetype nla panel modifiers");
strcpy(pt->idname, "NLA_PT_modifiers");
strcpy(pt->label, "Modifiers");
- //pt->draw= nla_panel_modifiers;
- pt->poll= nla_panel_poll;
+ pt->draw= nla_panel_modifiers;
+ pt->poll= nla_strip_panel_poll;
BLI_addtail(&art->paneltypes, pt);
}
diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c
index 8d417a150aa..3a3f86bb5a3 100644
--- a/source/blender/editors/space_nla/nla_draw.c
+++ b/source/blender/editors/space_nla/nla_draw.c
@@ -202,11 +202,20 @@ static void nla_draw_strip_text (NlaTrack *nlt, NlaStrip *strip, int index, View
char str[256];
rctf rect;
- /* for now, just init the string with a fixed-format */
- if (strip->act)
- sprintf(str, "%d | Act: %s | %.2f <-> %.2f", index, strip->act->id.name+2, strip->start, strip->end);
- else
- sprintf(str, "%d | Act: <NONE>", index);
+ /* for now, just init the string with fixed-formats */
+ switch (strip->type) {
+ case NLASTRIP_TYPE_TRANSITION: /* Transition */
+ sprintf(str, "%d | Transition | %.2f <-> %.2f", index, strip->start, strip->end);
+ break;
+
+ case NLASTRIP_TYPE_CLIP: /* Action-Clip (default) */
+ default:
+ if (strip->act)
+ sprintf(str, "%d | Act: %s | %.2f <-> %.2f", index, strip->act->id.name+2, strip->start, strip->end);
+ else
+ sprintf(str, "%d | Act: <NONE>", index); // xxx... need a better format?
+ break;
+ }
/* set text colour - if colours (see above) are light, draw black text, otherwise draw white */
if (strip->flag & (NLASTRIP_FLAG_ACTIVE|NLASTRIP_FLAG_SELECT|NLASTRIP_FLAG_TWEAKUSER))
@@ -295,7 +304,9 @@ void draw_nla_main_data (bAnimContext *ac, SpaceNla *snla, ARegion *ar)
{
AnimData *adt= BKE_animdata_from_id(ale->id);
- /* just draw a semi-shaded rect spanning the width of the viewable area if there's data */
+ /* just draw a semi-shaded rect spanning the width of the viewable area if there's data,
+ * and a second darker rect within which we draw keyframe indicator dots if there's data
+ */
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c
index e8af67aebd1..2996a005177 100644
--- a/source/blender/editors/space_nla/nla_edit.c
+++ b/source/blender/editors/space_nla/nla_edit.c
@@ -48,6 +48,8 @@
#include "BKE_animsys.h"
#include "BKE_nla.h"
#include "BKE_context.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
#include "BKE_report.h"
#include "BKE_screen.h"
#include "BKE_utildefines.h"
@@ -215,6 +217,229 @@ void NLAEDIT_OT_tweakmode_exit (wmOperatorType *ot)
/* *********************************************** */
/* NLA Editing Operations */
+/* ******************** Add Action-Clip Operator ***************************** */
+/* Add a new Action-Clip strip to the active track (or the active block if no space in the track) */
+
+/* pop up menu allowing user to choose the action to use */
+static int nlaedit_add_actionclip_invoke (bContext *C, wmOperator *op, wmEvent *evt)
+{
+ Main *m= CTX_data_main(C);
+ bAction *act;
+ uiPopupMenu *pup;
+ uiLayout *layout;
+
+ pup= uiPupMenuBegin(C, "Add Action Clip", 0);
+ layout= uiPupMenuLayout(pup);
+
+ /* loop through Actions in Main database, adding as items in the menu */
+ for (act= m->action.first; act; act= act->id.next)
+ uiItemStringO(layout, act->id.name+2, 0, "NLAEDIT_OT_add_actionclip", "action", act->id.name);
+ uiItemS(layout);
+
+ uiPupMenuEnd(C, pup);
+
+ return OPERATOR_CANCELLED;
+}
+
+/* add the specified action as new strip */
+static int nlaedit_add_actionclip_exec (bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+ Scene *scene;
+
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter, items;
+
+ bAction *act = NULL;
+ char actname[22];
+ float cfra;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ scene= ac.scene;
+ cfra= (float)CFRA;
+
+ /* get action to use */
+ RNA_string_get(op->ptr, "action", actname);
+ act= (bAction *)find_id("AC", actname+2);
+
+ if (act == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No valid Action to add.");
+ //printf("Add strip - actname = '%s' \n", actname);
+ return OPERATOR_CANCELLED;
+ }
+
+ /* get a list of the editable tracks being shown in the NLA
+ * - this is limited to active ones for now, but could be expanded to
+ */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_ACTIVE | ANIMFILTER_NLATRACKS | ANIMFILTER_FOREDIT);
+ items= ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ if (items == 0) {
+ BKE_report(op->reports, RPT_ERROR, "No active track(s) to add strip to.");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* for every active track, try to add strip to free space in track or to the top of the stack if no space */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ NlaTrack *nlt= (NlaTrack *)ale->data;
+ AnimData *adt= BKE_animdata_from_id(ale->id);
+ NlaStrip *strip= NULL;
+
+ /* create a new strip, and offset it to start on the current frame */
+ strip= add_nlastrip(act);
+
+ strip->end += (cfra - strip->start);
+ strip->start = cfra;
+
+ /* firstly try adding strip to our current track, but if that fails, add to a new track */
+ if (BKE_nlatrack_add_strip(nlt, strip) == 0) {
+ /* trying to add to the current failed (no space),
+ * so add a new track to the stack, and add to that...
+ */
+ nlt= add_nlatrack(adt, NULL);
+ BKE_nlatrack_add_strip(nlt, strip);
+ }
+ }
+
+ /* 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 NLAEDIT_OT_add_actionclip (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Add Action Strip";
+ ot->idname= "NLAEDIT_OT_add_actionclip";
+ ot->description= "Add an Action-Clip strip (i.e. an NLA Strip referencing an Action) to the active track.";
+
+ /* api callbacks */
+ ot->invoke= nlaedit_add_actionclip_invoke;
+ ot->exec= nlaedit_add_actionclip_exec;
+ ot->poll= nlaop_poll_tweakmode_off;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ // TODO: this would be nicer as an ID-pointer...
+ RNA_def_string(ot->srna, "action", "", 21, "Action", "Name of Action to add as a new Action-Clip Strip.");
+}
+
+/* ******************** Add Transition Operator ***************************** */
+/* Add a new transition strip between selected strips */
+
+/* add the specified action as new strip */
+static int nlaedit_add_transition_exec (bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ int done = 0;
+
+ /* 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);
+
+ /* for each track, find pairs of strips to add transitions to */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ NlaTrack *nlt= (NlaTrack *)ale->data;
+ NlaStrip *s1, *s2;
+
+ /* get initial pair of strips */
+ if ELEM(nlt->strips.first, NULL, nlt->strips.last)
+ continue;
+ s1= nlt->strips.first;
+ s2= s1->next;
+
+ /* loop over strips */
+ for (; s1 && s2; s1=s2, s2=s2->next) {
+ NlaStrip *strip;
+
+ /* check if both are selected */
+ if ELEM(0, (s1->flag & NLASTRIP_FLAG_SELECT), (s2->flag & NLASTRIP_FLAG_SELECT))
+ continue;
+ /* check if there's space between the two */
+ if (IS_EQ(s1->end, s2->start))
+ continue;
+
+ /* allocate new strip */
+ strip= MEM_callocN(sizeof(NlaStrip), "NlaStrip");
+ BLI_insertlinkafter(&nlt->strips, s1, strip);
+
+ /* set the type */
+ strip->type= NLASTRIP_TYPE_TRANSITION;
+
+ /* generic settings
+ * - selected flag to highlight this to the user
+ * - auto-blends to ensure that blend in/out values are automatically
+ * determined by overlaps of strips
+ */
+ strip->flag = NLASTRIP_FLAG_SELECT|NLASTRIP_FLAG_AUTO_BLENDS;
+
+ /* range is simply defined as the endpoints of the adjacent strips */
+ strip->start = s1->end;
+ strip->end = s2->start;
+
+ /* scale and repeat aren't of any use, but shouldn't ever be 0 */
+ strip->scale= 1.0f;
+ strip->repeat = 1.0f;
+
+ /* make note of this */
+ done++;
+ }
+ }
+
+ /* free temp data */
+ BLI_freelistN(&anim_data);
+
+ /* was anything added? */
+ if (done) {
+ /* 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;
+ }
+ else {
+ BKE_report(op->reports, RPT_ERROR, "Needs at least a pair of adjacent selected strips.");
+ return OPERATOR_CANCELLED;
+ }
+}
+
+void NLAEDIT_OT_add_transition (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Add Transition";
+ ot->idname= "NLAEDIT_OT_add_transition";
+ ot->description= "Add a transition strip between two adjacent selected strips.";
+
+ /* api callbacks */
+ ot->exec= nlaedit_add_transition_exec;
+ ot->poll= nlaop_poll_tweakmode_off;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
/* ******************** Delete Strips Operator ***************************** */
/* Deletes the selected NLA-Strips */
@@ -230,7 +455,7 @@ static int nlaedit_delete_exec (bContext *C, wmOperator *op)
if (ANIM_animdata_get_context(C, &ac) == 0)
return OPERATOR_CANCELLED;
- /* get a list of the AnimData blocks being shown in the NLA */
+ /* 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);
@@ -292,7 +517,7 @@ static int nlaedit_split_exec (bContext *C, wmOperator *op)
if (ANIM_animdata_get_context(C, &ac) == 0)
return OPERATOR_CANCELLED;
- /* get a list of the AnimData blocks being shown in the NLA */
+ /* get a list of 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);
diff --git a/source/blender/editors/space_nla/nla_header.c b/source/blender/editors/space_nla/nla_header.c
index 0d42c544a3f..970d602c0af 100644
--- a/source/blender/editors/space_nla/nla_header.c
+++ b/source/blender/editors/space_nla/nla_header.c
@@ -110,7 +110,7 @@ static void nla_viewmenu(bContext *C, uiLayout *layout, void *arg_unused)
uiItemS(layout);
- uiItemO(layout, NULL, 0, "NLA_OT_view_all");
+ //uiItemO(layout, NULL, 0, "NLA_OT_view_all");
if (sa->full)
uiItemO(layout, NULL, 0, "SCREEN_OT_screen_full_area"); // "Tile Window", Ctrl UpArrow
@@ -146,6 +146,9 @@ static void nla_editmenu(bContext *C, uiLayout *layout, void *arg_unused)
uiItemO(layout, NULL, 0, "NLA_OT_add_tracks");
uiItemBooleanO(layout, "Add Tracks Above Selected", 0, "NLA_OT_add_tracks", "above_selected", 1);
+ uiItemO(layout, NULL, 0, "NLA_OT_add_actionclip");
+ uiItemO(layout, NULL, 0, "NLA_OT_add_transition");
+
uiItemO(layout, NULL, 0, "NLAEDIT_OT_split");
uiItemS(layout);
diff --git a/source/blender/editors/space_nla/nla_intern.h b/source/blender/editors/space_nla/nla_intern.h
index 5c6670cfd6f..f1bde40f4ab 100644
--- a/source/blender/editors/space_nla/nla_intern.h
+++ b/source/blender/editors/space_nla/nla_intern.h
@@ -92,6 +92,9 @@ void NLAEDIT_OT_tweakmode_exit(wmOperatorType *ot);
/* --- */
+void NLAEDIT_OT_add_actionclip(wmOperatorType *ot);
+void NLAEDIT_OT_add_transition(wmOperatorType *ot);
+
void NLAEDIT_OT_delete(wmOperatorType *ot);
void NLAEDIT_OT_split(wmOperatorType *ot);
diff --git a/source/blender/editors/space_nla/nla_ops.c b/source/blender/editors/space_nla/nla_ops.c
index 981ef9a4f87..a9b7022157e 100644
--- a/source/blender/editors/space_nla/nla_ops.c
+++ b/source/blender/editors/space_nla/nla_ops.c
@@ -134,6 +134,9 @@ void nla_operatortypes(void)
WM_operatortype_append(NLAEDIT_OT_tweakmode_enter);
WM_operatortype_append(NLAEDIT_OT_tweakmode_exit);
+ WM_operatortype_append(NLAEDIT_OT_add_actionclip);
+ WM_operatortype_append(NLAEDIT_OT_add_transition);
+
WM_operatortype_append(NLAEDIT_OT_delete);
WM_operatortype_append(NLAEDIT_OT_split);
}
@@ -208,6 +211,10 @@ static void nla_keymap_main (wmWindowManager *wm, ListBase *keymap)
WM_keymap_add_item(keymap, "NLAEDIT_OT_tweakmode_enter", TABKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "NLAEDIT_OT_tweakmode_exit", TABKEY, KM_PRESS, 0, 0);
+ /* add strips */
+ WM_keymap_add_item(keymap, "NLAEDIT_OT_add_actionclip", AKEY, KM_PRESS, KM_SHIFT, 0);
+ WM_keymap_add_item(keymap, "NLAEDIT_OT_add_transition", TKEY, KM_PRESS, KM_SHIFT, 0);
+
/* delete */
WM_keymap_add_item(keymap, "NLAEDIT_OT_delete", XKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "NLAEDIT_OT_delete", DELKEY, KM_PRESS, 0, 0);