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
path: root/source
diff options
context:
space:
mode:
authorJoshua Leung <aligorith@gmail.com>2009-06-05 09:18:07 +0400
committerJoshua Leung <aligorith@gmail.com>2009-06-05 09:18:07 +0400
commit5c21c176fa0a571f3ba47af8ad2c7906a5dc375f (patch)
treee20d22f19ad35ade19954bf55a7dab65204f2f51 /source
parentf6cac5bec7418b58fe250c65293e85a8f0095cb2 (diff)
NLA SoC: Operators for 'tweaking' strip actions (TAB-Key for both)
In this commit, I've introduced the mechanism by which actions already referenced by strips used in the NLA can be edited (or 'tweaked'). To use, simply select a strip you wish to edit, and hit that TAB key to start tweaking that strip's action, and hit TAB again once you're done. What happens when you enter 'tweak mode': 1) The action of the active strip temporarily becomes the 'active action' of the AnimData block. You are now able to edit this in one of the Animation Editors (DopeSheet/Action, Graph Editors) as per normal (i.e. sliding keyframes around, inserting keyframes, etc.). The 'action-line' will therefore get drawn immediately above the active track containing the active strip, so that it's clear that that's what we're editing. 2) All the NLA-tracks (and all the strips within them) that occur after the track that the active strip lived in get disabled while you're in tweakmode. This is equivalent to travelling back to an earlier state in a construction history stack. 3) The active NLA track also gets disabled while in tweakmode, since it would otherwise interfere with the correct functioning of the tweaking for the action of interest. 4) The 'real' active action (i.e. the one displaced by the active strip's action) gets put into temp storage, and will be restored after you exit tweakmode. 5) Any strips which also reference the action being tweaked will get highlighted in red shading to indicate that you may be making some changes to the action which you don't really want to make for the other users too. Please note though, that this is only a rough prototype of this functionality, with some niceties still to come. i.e.: * NLA-tracks after the active track should still get drawn above the 'tweaking action line', but perhaps with different appearance? * Various tools will still need awareness of this to prevent corrupting operations from taking place. How to proceed is still undecided... * When exiting tweak-mode, the strip the action came from still needs some form of syncing with the modified action... there are a few tricky issues here that will need to be solved * Evaluation code doesn't totally take this into account yet... --- Also, fixed a number of bugs with various code (notably selection, and also a few drawing bugs)
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenkernel/BKE_nla.h4
-rw-r--r--source/blender/blenkernel/intern/anim_sys.c15
-rw-r--r--source/blender/blenkernel/intern/nla.c100
-rw-r--r--source/blender/editors/animation/anim_channels.c12
-rw-r--r--source/blender/editors/animation/anim_filter.c118
-rw-r--r--source/blender/editors/include/ED_anim_api.h6
-rw-r--r--source/blender/editors/include/ED_screen.h1
-rw-r--r--source/blender/editors/screen/screen_ops.c6
-rw-r--r--source/blender/editors/space_action/action_select.c4
-rw-r--r--source/blender/editors/space_graph/graph_select.c2
-rw-r--r--source/blender/editors/space_nla/nla_channels.c2
-rw-r--r--source/blender/editors/space_nla/nla_draw.c81
-rw-r--r--source/blender/editors/space_nla/nla_edit.c137
-rw-r--r--source/blender/editors/space_nla/nla_intern.h8
-rw-r--r--source/blender/editors/space_nla/nla_ops.c56
-rw-r--r--source/blender/editors/space_nla/nla_select.c3
-rw-r--r--source/blender/makesdna/DNA_action_types.h1
-rw-r--r--source/blender/makesdna/DNA_anim_types.h11
-rw-r--r--source/blender/makesdna/DNA_scene_types.h1
19 files changed, 514 insertions, 54 deletions
diff --git a/source/blender/blenkernel/BKE_nla.h b/source/blender/blenkernel/BKE_nla.h
index 3c3abe11da3..89e5f1af7e1 100644
--- a/source/blender/blenkernel/BKE_nla.h
+++ b/source/blender/blenkernel/BKE_nla.h
@@ -59,9 +59,13 @@ void BKE_nlatrack_set_active(ListBase *tracks, struct NlaTrack *nlt);
short BKE_nlatrack_has_space(struct NlaTrack *nlt, float start, float end);
void BKE_nlatrack_sort_strips(struct NlaTrack *nlt);
+struct NlaStrip *BKE_nlastrip_find_active(struct NlaTrack *nlt);
short BKE_nlastrip_within_bounds(struct NlaStrip *strip, float min, float max);
void BKE_nla_action_pushdown(struct AnimData *adt);
+short BKE_nla_tweakmode_enter(struct AnimData *adt);
+void BKE_nla_tweakmode_exit(struct AnimData *adt);
+
#endif
diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c
index 652f733d553..dbc38d2fc7e 100644
--- a/source/blender/blenkernel/intern/anim_sys.c
+++ b/source/blender/blenkernel/intern/anim_sys.c
@@ -118,6 +118,9 @@ void BKE_free_animdata (ID *id)
/* unlink action (don't free, as it's in its own list) */
if (adt->action)
adt->action->id.us--;
+ /* same goes for the temporarily displaced action */
+ if (adt->tmpact)
+ adt->tmpact->id.us--;
/* free nla data */
free_nladata(&adt->nla_tracks);
@@ -151,6 +154,7 @@ AnimData *BKE_copy_animdata (AnimData *adt)
// XXX review this... it might not be optimal behaviour yet...
//id_us_plus((ID *)dadt->action);
dadt->action= copy_action(adt->action);
+ dadt->tmpact= copy_action(adt->action);
/* duplicate NLA data */
copy_nladata(&dadt->nla_tracks, &adt->nla_tracks);
@@ -595,7 +599,7 @@ static float nlastrip_get_frame (NlaStrip *strip, float cframe, short invert)
scale = (float)fabs(strip->scale); /* scale must be positive - we've got a special flag for reversing */
/* length of referenced action */
- actlength = strip->actend-strip->actstart;
+ actlength = strip->actend - strip->actstart;
if (actlength == 0.0f) actlength = 1.0f;
/* length of strip */
@@ -630,11 +634,11 @@ static float nlastrip_get_influence (NlaStrip *strip, float cframe)
// 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) + 0.0001) / (strip->blendin);
+ return (float)fabs(cframe - strip->start) / (strip->blendin);
}
else if (IS_EQ(strip->blendout, 0)==0 && (cframe >= (strip->end - strip->blendout))) {
/* there is some blend-out */
- return (float)(fabs(strip->end - cframe) + 0.0001) / (strip->blendout);
+ return (float)fabs(strip->end - cframe) / (strip->blendout);
}
else {
/* in the middle of the strip, we should be full strength */
@@ -674,8 +678,8 @@ static void nlatrack_ctime_get_strip (ListBase *list, NlaTrack *nlt, short index
NlaEvalStrip *nes;
short side= 0;
- /* skip if track is muted */
- if (nlt->flag & NLATRACK_MUTED)
+ /* skip if track is muted or disabled */
+ if (nlt->flag & (NLATRACK_MUTED|NLATRACK_DISABLED))
return;
/* loop over strips, checking if they fall within the range */
@@ -1104,6 +1108,7 @@ void BKE_animsys_evaluate_animdata (ID *id, AnimData *adt, float ctime, short re
* - NLA before Active Action, as Active Action behaves as 'tweaking track'
* that overrides 'rough' work in NLA
*/
+ // TODO: need to double check that this all works correctly
if ((recalc & ADT_RECALC_ANIM) || (adt->recalc & ADT_RECALC_ANIM))
{
/* evaluate NLA data */
diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c
index 6235ec58d40..84f98096364 100644
--- a/source/blender/blenkernel/intern/nla.c
+++ b/source/blender/blenkernel/intern/nla.c
@@ -583,4 +583,104 @@ void BKE_nla_action_pushdown (AnimData *adt)
}
}
+
+/* Find the active strip + track combo, and set them up as the tweaking track,
+ * and return if successful or not.
+ */
+short BKE_nla_tweakmode_enter (AnimData *adt)
+{
+ NlaTrack *nlt, *activeTrack=NULL;
+ NlaStrip *strip, *activeStrip=NULL;
+
+ /* verify that data is valid */
+ if ELEM(NULL, adt, adt->nla_tracks.first)
+ return 0;
+
+ /* if block is already in tweakmode, just leave, but we should report
+ * that this block is in tweakmode (as our returncode)
+ */
+ // FIXME: hopefully the flag is correct!
+ if (adt->flag & ADT_NLA_EDIT_ON)
+ return 1;
+
+ /* go over the tracks, finding the active one, and its active strip
+ * - if we cannot find both, then there's nothing to do
+ */
+ for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) {
+ /* check if active */
+ if (nlt->flag & NLATRACK_ACTIVE) {
+ /* store reference to this active track */
+ activeTrack= nlt;
+
+ /* now try to find active strip */
+ activeStrip= BKE_nlastrip_find_active(nlt);
+ break;
+ }
+ }
+ if ELEM3(NULL, activeTrack, activeStrip, activeStrip->act) {
+ printf("NLA tweakmode enter - neither active requirement found \n");
+ return 0;
+ }
+
+ /* go over all the tracks up to the active one, tagging each strip that uses the same
+ * action as the active strip, but leaving everything else alone
+ */
+ for (nlt= activeTrack->prev; nlt; nlt= nlt->prev) {
+ for (strip= nlt->strips.first; strip; strip= strip->next) {
+ if (strip->act == activeStrip->act)
+ strip->flag |= NLASTRIP_FLAG_TWEAKUSER;
+ else
+ strip->flag &= ~NLASTRIP_FLAG_TWEAKUSER; // XXX probably don't need to clear this...
+ }
+ }
+
+
+ /* go over all the tracks after AND INCLUDING the active one, tagging them as being disabled
+ * - the active track needs to also be tagged, otherwise, it'll overlap with the tweaks going on
+ */
+ for (nlt= activeTrack; nlt; nlt= nlt->next)
+ nlt->flag |= NLATRACK_DISABLED;
+
+ /* handle AnimData level changes:
+ * - 'real' active action to temp storage (no need to change user-counts)
+ * - action of active strip set to be the 'active action'
+ * - editing-flag for this AnimData block should also get turned on (for more efficient restoring)
+ */
+ adt->tmpact= adt->action;
+ adt->action= activeStrip->act;
+ adt->flag |= ADT_NLA_EDIT_ON;
+
+ /* done! */
+ return 1;
+}
+
+/* Exit tweakmode for this AnimData block */
+void BKE_nla_tweakmode_exit (AnimData *adt)
+{
+ NlaTrack *nlt;
+
+ /* verify that data is valid */
+ if ELEM(NULL, adt, adt->nla_tracks.first)
+ return;
+
+ /* hopefully the flag is correct - skip if not on */
+ if ((adt->flag & ADT_NLA_EDIT_ON) == 0)
+ return;
+
+ // TODO: need to sync the user-strip with the new state of the action!
+
+ /* for all NLA-tracks, clear the 'disabled' flag */
+ for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next)
+ nlt->flag &= ~NLATRACK_DISABLED;
+
+ /* handle AnimData level changes:
+ * - 'real' active action is restored from storage
+ * - storage pointer gets cleared (to avoid having bad notes hanging around)
+ * - editing-flag for this AnimData block should also get turned off
+ */
+ adt->action= adt->tmpact;
+ adt->tmpact= NULL;
+ adt->flag &= ~ADT_NLA_EDIT_ON;
+}
+
/* *************************************************** */
diff --git a/source/blender/editors/animation/anim_channels.c b/source/blender/editors/animation/anim_channels.c
index 658bff73978..59fb56f3c35 100644
--- a/source/blender/editors/animation/anim_channels.c
+++ b/source/blender/editors/animation/anim_channels.c
@@ -90,14 +90,13 @@
/* -------------------------- Exposed API ----------------------------------- */
/* Set the given animation-channel as the active one for the active context */
-void ANIM_set_active_channel (void *data, short datatype, int filter, void *channel_data, short channel_type)
+void ANIM_set_active_channel (bAnimContext *ac, void *data, short datatype, int filter, void *channel_data, short channel_type)
{
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
/* try to build list of filtered items */
- // XXX we don't need/supply animcontext for now, since in this case, there's nothing really essential there that isn't already covered
- ANIM_animdata_filter(NULL, &anim_data, filter, data, datatype);
+ ANIM_animdata_filter(ac, &anim_data, filter, data, datatype);
if (anim_data.first == NULL)
return;
@@ -151,8 +150,7 @@ void ANIM_set_active_channel (void *data, short datatype, int filter, void *chan
case ANIMTYPE_NLATRACK:
{
NlaTrack *nlt= (NlaTrack *)channel_data;
-
- ACHANNEL_SET_FLAG(nlt, ACHANNEL_SETFLAG_CLEAR, NLATRACK_ACTIVE);
+ nlt->flag |= NLATRACK_ACTIVE;
}
break;
}
@@ -1474,7 +1472,7 @@ static void mouse_anim_channels (bAnimContext *ac, float x, int channel_index, s
/* if group is selected now, make group the 'active' one in the visible list */
if (agrp->flag & AGRP_SELECTED)
- ANIM_set_active_channel(ac->data, ac->datatype, filter, agrp, ANIMTYPE_GROUP);
+ ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, agrp, ANIMTYPE_GROUP);
}
}
break;
@@ -1520,7 +1518,7 @@ static void mouse_anim_channels (bAnimContext *ac, float x, int channel_index, s
/* if F-Curve is selected now, make F-Curve the 'active' one in the visible list */
if (fcu->flag & FCURVE_SELECTED)
- ANIM_set_active_channel(ac->data, ac->datatype, filter, fcu, ANIMTYPE_FCURVE);
+ ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, fcu, ANIMTYPE_FCURVE);
}
}
break;
diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c
index ed526bd99a0..32405571b57 100644
--- a/source/blender/editors/animation/anim_filter.c
+++ b/source/blender/editors/animation/anim_filter.c
@@ -343,19 +343,33 @@ short ANIM_animdata_get_context (const bContext *C, bAnimContext *ac)
/* quick macro to test if AnimData is usable for NLA */
#define ANIMDATA_HAS_NLA(id) ((id)->adt && (id)->adt->nla_tracks.first)
-/* quick macro to test for all three avove usability tests, performing the appropriate provided
+
+/* Quick macro to test for all three avove usability tests, performing the appropriate provided
* action for each when the AnimData context is appropriate.
*
- * Priority order for this goes (most important, to least): NLA, Drivers, Keyframes
+ * Priority order for this goes (most important, to least): AnimData blocks, NLA, Drivers, Keyframes.
+ *
+ * For this to work correctly, a standard set of data needs to be available within the scope that this
+ * gets called in:
+ * - ListBase anim_data;
+ * - bDopeSheet *ads;
+ * - bAnimListElem *ale;
+ * - int items;
*
* - id: ID block which should have an AnimData pointer following it immediately, to use
+ * - adtOk: line or block of code to execute for AnimData-blocks case (usually ANIMDATA_ADD_ANIMDATA)
* - nlaOk: line or block of code to execute for NLA case
* - driversOk: line or block of code to execute for Drivers case
* - keysOk: line or block of code for Keyframes case
*/
-#define ANIMDATA_FILTER_CASES(id, nlaOk, driversOk, keysOk) \
+#define ANIMDATA_FILTER_CASES(id, adtOk, nlaOk, driversOk, keysOk) \
{\
- if (ads->filterflag & ADS_FILTER_ONLYNLA) {\
+ if (filter_mode & ANIMFILTER_ANIMDATA) {\
+ if ((id)->adt) {\
+ adtOk\
+ }\
+ }\
+ else if (ads->filterflag & ADS_FILTER_ONLYNLA) {\
if (ANIMDATA_HAS_NLA(id)) {\
nlaOk\
}\
@@ -376,6 +390,18 @@ short ANIM_animdata_get_context (const bContext *C, bAnimContext *ac)
}
+/* quick macro to add a pointer to an AnimData block as a channel */
+#define ANIMDATA_ADD_ANIMDATA(id) \
+ {\
+ ale= make_new_animlistelem((id)->adt, ANIMTYPE_ANIMDATA, NULL, ANIMTYPE_NONE, (ID *)id);\
+ if (ale) {\
+ BLI_addtail(anim_data, ale);\
+ items++;\
+ }\
+ }
+
+
+
/* quick macro to test if a anim-channel (F-Curve, Group, etc.) is selected in an acceptable way */
#define ANIMCHANNEL_SELOK(test_func) \
( !(filter_mode & (ANIMFILTER_SEL|ANIMFILTER_UNSEL)) || \
@@ -713,6 +739,11 @@ static int animdata_filter_nla (ListBase *anim_data, AnimData *adt, int filter_m
items++;
}
}
+
+ /* if we're in NLA-tweakmode, if this track was active, that means that it was the last active one */
+ // FIXME: the channels after should still get drawn, just 'differently', and after an active-action channel
+ if ((adt->flag & ADT_NLA_EDIT_ON) && (nlt->flag & NLATRACK_ACTIVE))
+ break;
}
}
}
@@ -890,6 +921,7 @@ static int animdata_filter_dopesheet_mats (ListBase *anim_data, bDopeSheet *ads,
/* check if ok */
ANIMDATA_FILTER_CASES(ma,
+ { /* AnimData blocks - do nothing... */ },
ok=1;,
ok=1;,
ok=1;)
@@ -933,6 +965,7 @@ static int animdata_filter_dopesheet_mats (ListBase *anim_data, bDopeSheet *ads,
/* add material's animation data */
if (FILTER_MAT_OBJD(ma) || (filter_mode & ANIMFILTER_CURVESONLY)) {
ANIMDATA_FILTER_CASES(ma,
+ { /* AnimData blocks - do nothing... */ },
items += animdata_filter_nla(anim_data, ma->adt, filter_mode, ma, ANIMTYPE_DSMAT, (ID *)ma);,
items += animdata_filter_fcurves(anim_data, ma->adt->drivers.first, NULL, ma, ANIMTYPE_DSMAT, filter_mode, (ID *)ma);,
items += animdata_filter_action(anim_data, ma->adt->action, filter_mode, ma, ANIMTYPE_DSMAT, (ID *)ma);)
@@ -998,6 +1031,7 @@ static int animdata_filter_dopesheet_obdata (ListBase *anim_data, bDopeSheet *ad
if ((expanded) || (filter_mode & ANIMFILTER_CURVESONLY)) {
/* filtering for channels - nla, drivers, keyframes */
ANIMDATA_FILTER_CASES(iat,
+ { /* AnimData blocks - do nothing... */ },
items+= animdata_filter_nla(anim_data, iat->adt, filter_mode, iat, type, (ID *)iat);,
items+= animdata_filter_fcurves(anim_data, adt->drivers.first, NULL, iat, type, filter_mode, (ID *)iat);,
items += animdata_filter_action(anim_data, iat->adt->action, filter_mode, iat, type, (ID *)iat);)
@@ -1036,6 +1070,7 @@ static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, B
if (ob->adt) {
adt= ob->adt;
ANIMDATA_FILTER_CASES(ob,
+ { /* AnimData blocks - do nothing... */ },
{ /* nla */
#if 0
/* include nla-expand widget? */
@@ -1091,6 +1126,7 @@ static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, B
if ((key) && !(ads->filterflag & ADS_FILTER_NOSHAPEKEYS)) {
adt= key->adt;
ANIMDATA_FILTER_CASES(key,
+ { /* AnimData blocks - do nothing... */ },
{ /* nla */
#if 0
/* include nla-expand widget? */
@@ -1151,6 +1187,7 @@ static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, B
if ((ads->filterflag & ADS_FILTER_NOCAM) == 0) {
ANIMDATA_FILTER_CASES(ca,
+ { /* AnimData blocks - do nothing... */ },
obdata_ok= 1;,
obdata_ok= 1;,
obdata_ok= 1;)
@@ -1163,6 +1200,7 @@ static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, B
if ((ads->filterflag & ADS_FILTER_NOLAM) == 0) {
ANIMDATA_FILTER_CASES(la,
+ { /* AnimData blocks - do nothing... */ },
obdata_ok= 1;,
obdata_ok= 1;,
obdata_ok= 1;)
@@ -1175,6 +1213,7 @@ static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, B
if ((ads->filterflag & ADS_FILTER_NOCUR) == 0) {
ANIMDATA_FILTER_CASES(cu,
+ { /* AnimData blocks - do nothing... */ },
obdata_ok= 1;,
obdata_ok= 1;,
obdata_ok= 1;)
@@ -1216,6 +1255,7 @@ static int animdata_filter_dopesheet_scene (ListBase *anim_data, bDopeSheet *ads
if ((ads->filterflag & ADS_FILTER_NOSCE) == 0) {
adt= sce->adt;
ANIMDATA_FILTER_CASES(sce,
+ { /* AnimData blocks - do nothing... */ },
{ /* nla */
#if 0
/* include nla-expand widget? */
@@ -1266,9 +1306,10 @@ static int animdata_filter_dopesheet_scene (ListBase *anim_data, bDopeSheet *ads
/* world */
if ((wo && wo->adt) && !(ads->filterflag & ADS_FILTER_NOWOR)) {
- /* Action, Drivers, or NLA for World */
+ /* Action, Drivers, or NLA for World */
adt= wo->adt;
ANIMDATA_FILTER_CASES(wo,
+ { /* AnimData blocks - do nothing... */ },
{ /* nla */
#if 0
/* include nla-expand widget? */
@@ -1327,6 +1368,7 @@ static int animdata_filter_dopesheet (ListBase *anim_data, bDopeSheet *ads, int
{
Scene *sce= (Scene *)ads->source;
Base *base;
+ bAnimListElem *ale;
int items = 0;
/* check that we do indeed have a scene */
@@ -1342,11 +1384,25 @@ static int animdata_filter_dopesheet (ListBase *anim_data, bDopeSheet *ads, int
/* check filtering-flags if ok */
ANIMDATA_FILTER_CASES(sce,
+ {
+ /* for the special AnimData blocks only case, we only need to add
+ * the block if it is valid... then other cases just get skipped (hence ok=0)
+ */
+ ANIMDATA_ADD_ANIMDATA(sce);
+ sceOk=0;
+ },
sceOk= !(ads->filterflag & ADS_FILTER_NOSCE);,
sceOk= !(ads->filterflag & ADS_FILTER_NOSCE);,
sceOk= !(ads->filterflag & ADS_FILTER_NOSCE);)
if (sce->world) {
ANIMDATA_FILTER_CASES(sce->world,
+ {
+ /* for the special AnimData blocks only case, we only need to add
+ * the block if it is valid... then other cases just get skipped (hence ok=0)
+ */
+ ANIMDATA_ADD_ANIMDATA(sce->world);
+ worOk=0;
+ },
worOk= !(ads->filterflag & ADS_FILTER_NOWOR);,
worOk= !(ads->filterflag & ADS_FILTER_NOWOR);,
worOk= !(ads->filterflag & ADS_FILTER_NOWOR);)
@@ -1395,12 +1451,26 @@ static int animdata_filter_dopesheet (ListBase *anim_data, bDopeSheet *ads, int
actOk= 0;
keyOk= 0;
ANIMDATA_FILTER_CASES(ob,
+ {
+ /* for the special AnimData blocks only case, we only need to add
+ * the block if it is valid... then other cases just get skipped (hence ok=0)
+ */
+ ANIMDATA_ADD_ANIMDATA(ob);
+ actOk=0;
+ },
actOk= 1;,
actOk= 1;,
actOk= 1;)
if (key) {
/* shapekeys */
ANIMDATA_FILTER_CASES(key,
+ {
+ /* for the special AnimData blocks only case, we only need to add
+ * the block if it is valid... then other cases just get skipped (hence ok=0)
+ */
+ ANIMDATA_ADD_ANIMDATA(key);
+ keyOk=0;
+ },
keyOk= 1;,
keyOk= 1;,
keyOk= 1;)
@@ -1419,6 +1489,13 @@ static int animdata_filter_dopesheet (ListBase *anim_data, bDopeSheet *ads, int
/* if material has relevant animation data, break */
ANIMDATA_FILTER_CASES(ma,
+ {
+ /* for the special AnimData blocks only case, we only need to add
+ * the block if it is valid... then other cases just get skipped (hence ok=0)
+ */
+ ANIMDATA_ADD_ANIMDATA(ma);
+ matOk=0;
+ },
matOk= 1;,
matOk= 1;,
matOk= 1;)
@@ -1435,6 +1512,13 @@ static int animdata_filter_dopesheet (ListBase *anim_data, bDopeSheet *ads, int
Camera *ca= (Camera *)ob->data;
dataOk= 0;
ANIMDATA_FILTER_CASES(ca,
+ if ((ads->filterflag & ADS_FILTER_NOCAM)==0) {
+ /* for the special AnimData blocks only case, we only need to add
+ * the block if it is valid... then other cases just get skipped (hence ok=0)
+ */
+ ANIMDATA_ADD_ANIMDATA(ca);
+ dataOk=0;
+ },
dataOk= !(ads->filterflag & ADS_FILTER_NOCAM);,
dataOk= !(ads->filterflag & ADS_FILTER_NOCAM);,
dataOk= !(ads->filterflag & ADS_FILTER_NOCAM);)
@@ -1445,11 +1529,35 @@ static int animdata_filter_dopesheet (ListBase *anim_data, bDopeSheet *ads, int
Lamp *la= (Lamp *)ob->data;
dataOk= 0;
ANIMDATA_FILTER_CASES(la,
+ if ((ads->filterflag & ADS_FILTER_NOLAM)==0) {
+ /* for the special AnimData blocks only case, we only need to add
+ * the block if it is valid... then other cases just get skipped (hence ok=0)
+ */
+ ANIMDATA_ADD_ANIMDATA(la);
+ dataOk=0;
+ },
dataOk= !(ads->filterflag & ADS_FILTER_NOLAM);,
dataOk= !(ads->filterflag & ADS_FILTER_NOLAM);,
dataOk= !(ads->filterflag & ADS_FILTER_NOLAM);)
}
break;
+ case OB_CURVE: /* ------- Curve ---------- */
+ {
+ Curve *cu= (Curve *)ob->data;
+ dataOk= 0;
+ ANIMDATA_FILTER_CASES(cu,
+ if ((ads->filterflag & ADS_FILTER_NOCUR)==0) {
+ /* for the special AnimData blocks only case, we only need to add
+ * the block if it is valid... then other cases just get skipped (hence ok=0)
+ */
+ ANIMDATA_ADD_ANIMDATA(cu);
+ dataOk=0;
+ },
+ dataOk= !(ads->filterflag & ADS_FILTER_NOCUR);,
+ dataOk= !(ads->filterflag & ADS_FILTER_NOCUR);,
+ dataOk= !(ads->filterflag & ADS_FILTER_NOCUR);)
+ }
+ break;
default: /* --- other --- */
dataOk= 0;
break;
diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h
index cdd8b5c368c..dcaabb4b369 100644
--- a/source/blender/editors/include/ED_anim_api.h
+++ b/source/blender/editors/include/ED_anim_api.h
@@ -107,6 +107,7 @@ typedef struct bAnimListElem {
// XXX was ACTTYPE_*
typedef enum eAnim_ChannelType {
ANIMTYPE_NONE= 0,
+ ANIMTYPE_ANIMDATA,
ANIMTYPE_SPECIALDATA,
ANIMTYPE_SCENE,
@@ -162,6 +163,7 @@ typedef enum eAnimFilter_Flags {
ANIMFILTER_ACTGROUPED = (1<<6), /* belongs to the active actiongroup */
ANIMFILTER_CURVEVISIBLE = (1<<7), /* F-Curve is visible for editing/viewing in Graph Editor */
ANIMFILTER_ACTIVE = (1<<8), /* channel should be 'active' */ // FIXME: this is only relevant for F-Curves for now
+ ANIMFILTER_ANIMDATA = (1<<9), /* only return the underlying AnimData blocks (not the tracks, etc.) data comes from */
} eAnimFilter_Flags;
@@ -254,7 +256,7 @@ short ANIM_animdata_context_getdata(bAnimContext *ac);
void ANIM_deselect_anim_channels(void *data, short datatype, short test, short sel);
/* Set the 'active' channel of type channel_type, in the given action */
-void ANIM_set_active_channel(void *data, short datatype, int filter, void *channel_data, short channel_type);
+void ANIM_set_active_channel(bAnimContext *ac, void *data, short datatype, int filter, void *channel_data, short channel_type);
/* --------------- Settings and/or Defines -------------- */
@@ -308,6 +310,8 @@ void ipo_rainbow(int cur, int tot, float *out);
/* ------------- NLA-Mapping ----------------------- */
/* anim_draw.c */
+// XXX these are soon to be depreceated?
+
/* Obtain the Object providing NLA-scaling for the given channel if applicable */
struct Object *ANIM_nla_mapping_get(bAnimContext *ac, bAnimListElem *ale);
diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h
index c2beb34e7b5..e3b6572c03a 100644
--- a/source/blender/editors/include/ED_screen.h
+++ b/source/blender/editors/include/ED_screen.h
@@ -118,6 +118,7 @@ int ED_operator_node_active(struct bContext *C);
int ED_operator_ipo_active(struct bContext *C);
int ED_operator_sequencer_active(struct bContext *C);
int ED_operator_image_active(struct bContext *C);
+int ED_operator_nla_active(struct bContext *C);
int ED_operator_object_active(struct bContext *C);
int ED_operator_editmesh(struct bContext *C);
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c
index be952558b6c..db1a39ed056 100644
--- a/source/blender/editors/screen/screen_ops.c
+++ b/source/blender/editors/screen/screen_ops.c
@@ -164,6 +164,7 @@ int ED_operator_node_active(bContext *C)
return 0;
}
+// XXX rename
int ED_operator_ipo_active(bContext *C)
{
return ed_spacetype_test(C, SPACE_IPO);
@@ -179,6 +180,11 @@ int ED_operator_image_active(bContext *C)
return ed_spacetype_test(C, SPACE_IMAGE);
}
+int ED_operator_nla_active(bContext *C)
+{
+ return ed_spacetype_test(C, SPACE_NLA);
+}
+
int ED_operator_object_active(bContext *C)
{
return NULL != CTX_data_active_object(C);
diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c
index f64cd0f707c..d8ed3fd1068 100644
--- a/source/blender/editors/space_action/action_select.c
+++ b/source/blender/editors/space_action/action_select.c
@@ -862,13 +862,13 @@ static void mouse_action_keys (bAnimContext *ac, int mval[2], short select_mode,
bActionGroup *agrp= ale->data;
agrp->flag |= AGRP_SELECTED;
- ANIM_set_active_channel(ac->data, ac->datatype, filter, agrp, ANIMTYPE_GROUP);
+ ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, agrp, ANIMTYPE_GROUP);
}
else if (ale->type == ANIMTYPE_FCURVE) {
FCurve *fcu= ale->data;
fcu->flag |= FCURVE_SELECTED;
- ANIM_set_active_channel(ac->data, ac->datatype, filter, fcu, ANIMTYPE_FCURVE);
+ ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, fcu, ANIMTYPE_FCURVE);
}
}
else if (ac->datatype == ANIMCONT_GPENCIL) {
diff --git a/source/blender/editors/space_graph/graph_select.c b/source/blender/editors/space_graph/graph_select.c
index bb923ca6f95..21320b60ead 100644
--- a/source/blender/editors/space_graph/graph_select.c
+++ b/source/blender/editors/space_graph/graph_select.c
@@ -722,7 +722,7 @@ static void mouse_graph_keys (bAnimContext *ac, int mval[], short select_mode, s
/* set active F-Curve (NOTE: sync the filter flags with findnearest_fcurve_vert) */
if (fcu->flag & FCURVE_SELECTED) {
filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE | ANIMFILTER_CURVESONLY);
- ANIM_set_active_channel(ac->data, ac->datatype, filter, fcu, ANIMTYPE_FCURVE);
+ ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, fcu, ANIMTYPE_FCURVE);
}
}
diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c
index a839ccbf3d6..8db85ffa0b1 100644
--- a/source/blender/editors/space_nla/nla_channels.c
+++ b/source/blender/editors/space_nla/nla_channels.c
@@ -349,7 +349,7 @@ static void mouse_nla_channels (bAnimContext *ac, float x, int channel_index, sh
/* if NLA-Track is selected now, make NLA-Track the 'active' one in the visible list */
if (nlt->flag & NLATRACK_SELECTED)
- ANIM_set_active_channel(ac->data, ac->datatype, filter, nlt, ANIMTYPE_NLATRACK);
+ ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, nlt, ANIMTYPE_NLATRACK);
}
}
break;
diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c
index 85bf733df87..6c4c64ea272 100644
--- a/source/blender/editors/space_nla/nla_draw.c
+++ b/source/blender/editors/space_nla/nla_draw.c
@@ -137,7 +137,7 @@ static void nla_draw_strip (AnimData *adt, NlaTrack *nlt, NlaStrip *strip, View2
/* only need to draw here if there's no strip before since
* it only applies in such a situation
*/
- if (strip->prev) {
+ if (strip->prev == NULL) {
/* set the drawing color to the color of the strip, but with very faint alpha */
glColor4f(color[0], color[1], color[2], 0.15f);
@@ -563,15 +563,20 @@ void draw_nla_channel_list (bAnimContext *ac, SpaceNla *snla, ARegion *ar)
else
special= ICON_LAYER_USED;
- if (nlt->flag & NLATRACK_MUTED)
- mute = ICON_MUTE_IPO_ON;
- else
- mute = ICON_MUTE_IPO_OFF;
-
- if (EDITABLE_NLT(nlt))
- protect = ICON_UNLOCKED;
- else
- protect = ICON_LOCKED;
+ /* if this track is active and we're tweaking it, don't draw these toggles */
+ // TODO: need a special macro for this...
+ if ( ((nlt->flag & NLATRACK_ACTIVE) && (nlt->flag & NLATRACK_DISABLED)) == 0 )
+ {
+ if (nlt->flag & NLATRACK_MUTED)
+ mute = ICON_MUTE_IPO_ON;
+ else
+ mute = ICON_MUTE_IPO_OFF;
+
+ if (EDITABLE_NLT(nlt))
+ protect = ICON_UNLOCKED;
+ else
+ protect = ICON_LOCKED;
+ }
sel = SEL_NLT(nlt);
strcpy(name, nlt->name);
@@ -636,18 +641,29 @@ void draw_nla_channel_list (bAnimContext *ac, SpaceNla *snla, ARegion *ar)
}
else if (group == 5) {
/* Action Line */
- if (ale->data)
- glColor3f(0.8f, 0.2f, 0.0f); // reddish color - hardcoded for now
- else
- glColor3f(0.6f, 0.5f, 0.5f); // greyish-red color - hardcoded for now
-
+ AnimData *adt= BKE_animdata_from_id(ale->id);
+
+ // TODO: if tweaking some action, use the same color as for the tweaked track (quick hack done for now)
+ if (adt && (adt->flag & ADT_NLA_EDIT_ON)) {
+ // greenish color (same as tweaking strip) - hardcoded for now
+ glColor3f(0.3f, 0.95f, 0.1f);
+ }
+ else {
+ if (ale->data)
+ glColor3f(0.8f, 0.2f, 0.0f); // reddish color - hardcoded for now
+ else
+ glColor3f(0.6f, 0.5f, 0.5f); // greyish-red color - hardcoded for now
+ }
+
offset += 7 * indent;
/* only on top two corners, to show that this channel sits on top of the preceeding ones */
uiSetRoundBox((1|2));
- /* draw slightly shifted up vertically to look like it has more separtion from other channels */
- gl_round_box(GL_POLYGON, x+offset, yminc+NLACHANNEL_SKIP, (float)NLACHANNEL_NAMEWIDTH, ymaxc+NLACHANNEL_SKIP, 8);
+ /* draw slightly shifted up vertically to look like it has more separtion from other channels,
+ * but we then need to slightly shorten it so that it doesn't look like it overlaps
+ */
+ gl_round_box(GL_POLYGON, x+offset, yminc+NLACHANNEL_SKIP, (float)NLACHANNEL_NAMEWIDTH, ymaxc+NLACHANNEL_SKIP-1, 8);
/* clear group value, otherwise we cause errors... */
group = 0;
@@ -709,20 +725,29 @@ void draw_nla_channel_list (bAnimContext *ac, SpaceNla *snla, ARegion *ar)
UI_icon_draw((float)(NLACHANNEL_NAMEWIDTH-offset), ydatac, mute);
}
- /* draw action 'push-down' - only for NLA-Action lines, and only when there's an action */
+ /* draw NLA-action line 'status-icons' - only when there's an action */
if ((ale->type == ANIMTYPE_NLAACTION) && (ale->data)) {
- offset += 16;
+ AnimData *adt= BKE_animdata_from_id(ale->id);
- /* XXX firstly draw a little rect to help identify that it's different from the toggles */
- glBegin(GL_LINE_LOOP);
- glVertex2f((float)NLACHANNEL_NAMEWIDTH-offset-1, y-7);
- glVertex2f((float)NLACHANNEL_NAMEWIDTH-offset-1, y+9);
- glVertex2f((float)NLACHANNEL_NAMEWIDTH-1, y+9);
- glVertex2f((float)NLACHANNEL_NAMEWIDTH-1, y-7);
- glEnd(); // GL_LINES
+ offset += 16;
- /* now draw the icon */
- UI_icon_draw((float)NLACHANNEL_NAMEWIDTH-offset, ydatac, ICON_FREEZE);
+ /* now draw some indicator icons */
+ if ((adt) && (adt->flag & ADT_NLA_EDIT_ON)) {
+ /* 'tweaking action' - not a button */
+ UI_icon_draw((float)NLACHANNEL_NAMEWIDTH-offset, ydatac, ICON_EDIT);
+ }
+ else {
+ /* XXX firstly draw a little rect to help identify that it's different from the toggles */
+ glBegin(GL_LINE_LOOP);
+ glVertex2f((float)NLACHANNEL_NAMEWIDTH-offset-1, y-7);
+ glVertex2f((float)NLACHANNEL_NAMEWIDTH-offset-1, y+9);
+ glVertex2f((float)NLACHANNEL_NAMEWIDTH-1, y+9);
+ glVertex2f((float)NLACHANNEL_NAMEWIDTH-1, y-7);
+ glEnd(); // GL_LINES
+
+ /* 'push down' icon for normal active-actions */
+ UI_icon_draw((float)NLACHANNEL_NAMEWIDTH-offset, ydatac, ICON_FREEZE);
+ }
}
glDisable(GL_BLEND);
diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c
index ce9ae7de7a9..f7053957667 100644
--- a/source/blender/editors/space_nla/nla_edit.c
+++ b/source/blender/editors/space_nla/nla_edit.c
@@ -68,6 +68,143 @@
#include "nla_intern.h" // own include
/* *********************************************** */
+/* General Editing */
+
+/* ******************** Tweak-Mode Operators ***************************** */
+/* 'Tweak mode' allows the action referenced by the active NLA-strip to be edited
+ * as if it were the normal Active-Action of its AnimData block.
+ */
+
+static int nlaedit_enable_tweakmode_exec (bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+ int ok=0;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* get a list of the AnimData blocks being shown in the NLA */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_ANIMDATA);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ /* if no blocks, popup error? */
+ if (anim_data.first == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No AnimData blocks to enter tweakmode for");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* for each AnimData block with NLA-data, try setting it in tweak-mode */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ AnimData *adt= ale->data;
+
+ /* try entering tweakmode if valid */
+ ok += BKE_nla_tweakmode_enter(adt);
+ }
+
+ /* free temp data */
+ BLI_freelistN(&anim_data);
+
+ /* if we managed to enter tweakmode on at least one AnimData block,
+ * set the flag for this in the active scene and send notifiers
+ */
+ if (ac.scene && ok) {
+ /* set editing flag */
+ ac.scene->flag |= SCE_NLA_EDIT_ON;
+
+ /* 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_tweakmode_enter (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Enter Tweak Mode";
+ ot->idname= "NLAEDIT_OT_tweakmode_enter";
+ ot->description= "Enter tweaking mode for the action referenced by the active strip.";
+
+ /* api callbacks */
+ ot->exec= nlaedit_enable_tweakmode_exec;
+ ot->poll= nlaop_poll_tweakmode_off;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/* ------------- */
+
+static int nlaedit_disable_tweakmode_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 AnimData blocks being shown in the NLA */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_ANIMDATA);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ /* if no blocks, popup error? */
+ if (anim_data.first == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No AnimData blocks to enter tweakmode for");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* for each AnimData block with NLA-data, try exitting tweak-mode */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ AnimData *adt= ale->data;
+
+ /* try entering tweakmode if valid */
+ BKE_nla_tweakmode_exit(adt);
+ }
+
+ /* free temp data */
+ BLI_freelistN(&anim_data);
+
+ /* if we managed to enter tweakmode on at least one AnimData block,
+ * set the flag for this in the active scene and send notifiers
+ */
+ if (ac.scene) {
+ /* clear editing flag */
+ ac.scene->flag &= ~SCE_NLA_EDIT_ON;
+
+ /* 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_tweakmode_exit (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Exit Tweak Mode";
+ ot->idname= "NLAEDIT_OT_tweakmode_exit";
+ ot->description= "Exit tweaking mode for the action referenced by the active strip.";
+
+ /* api callbacks */
+ ot->exec= nlaedit_disable_tweakmode_exec;
+ ot->poll= nlaop_poll_tweakmode_on;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
/* *********************************************** */
diff --git a/source/blender/editors/space_nla/nla_intern.h b/source/blender/editors/space_nla/nla_intern.h
index 448b823bd4b..a7188a7cccd 100644
--- a/source/blender/editors/space_nla/nla_intern.h
+++ b/source/blender/editors/space_nla/nla_intern.h
@@ -76,6 +76,9 @@ void NLAEDIT_OT_click_select(wmOperatorType *ot);
/* **************************************** */
/* nla_edit.c */
+void NLAEDIT_OT_tweakmode_enter(wmOperatorType *ot);
+void NLAEDIT_OT_tweakmode_exit(wmOperatorType *ot);
+
/* **************************************** */
/* nla_channels.c */
@@ -85,6 +88,11 @@ void NLA_OT_channels_click(wmOperatorType *ot);
/* **************************************** */
/* nla_ops.c */
+int nlaop_poll_tweakmode_off(bContext *C);
+int nlaop_poll_tweakmode_on (bContext *C);
+
+/* --- */
+
void nla_operatortypes(void);
void nla_keymap(wmWindowManager *wm);
diff --git a/source/blender/editors/space_nla/nla_ops.c b/source/blender/editors/space_nla/nla_ops.c
index 167686c99f9..057e4b05656 100644
--- a/source/blender/editors/space_nla/nla_ops.c
+++ b/source/blender/editors/space_nla/nla_ops.c
@@ -65,6 +65,51 @@
#include "nla_intern.h" // own include
+/* ************************** poll callbacks for operators **********************************/
+
+/* tweakmode is NOT enabled */
+int nlaop_poll_tweakmode_off (bContext *C)
+{
+ Scene *scene;
+
+ /* for now, we check 2 things:
+ * 1) active editor must be NLA
+ * 2) tweakmode is currently set as a 'per-scene' flag
+ * so that it will affect entire NLA data-sets,
+ * but not all AnimData blocks will be in tweakmode for
+ * various reasons
+ */
+ if (ED_operator_nla_active(C) == 0)
+ return 0;
+
+ scene= CTX_data_scene(C);
+ if ((scene == NULL) || (scene->flag & SCE_NLA_EDIT_ON))
+ return 0;
+
+ return 1;
+}
+
+/* tweakmode IS enabled */
+int nlaop_poll_tweakmode_on (bContext *C)
+{
+ Scene *scene;
+
+ /* for now, we check 2 things:
+ * 1) active editor must be NLA
+ * 2) tweakmode is currently set as a 'per-scene' flag
+ * so that it will affect entire NLA data-sets,
+ * but not all AnimData blocks will be in tweakmode for
+ * various reasons
+ */
+ if (ED_operator_nla_active(C) == 0)
+ return 0;
+
+ scene= CTX_data_scene(C);
+ if ((scene == NULL) || !(scene->flag & SCE_NLA_EDIT_ON))
+ return 0;
+
+ return 1;
+}
/* ************************** registration - operator types **********************************/
@@ -77,6 +122,10 @@ void nla_operatortypes(void)
/* select */
WM_operatortype_append(NLAEDIT_OT_click_select);
WM_operatortype_append(NLAEDIT_OT_select_all_toggle);
+
+ /* edit */
+ WM_operatortype_append(NLAEDIT_OT_tweakmode_enter);
+ WM_operatortype_append(NLAEDIT_OT_tweakmode_exit);
}
/* ************************** registration - keymaps **********************************/
@@ -130,6 +179,13 @@ static void nla_keymap_main (wmWindowManager *wm, ListBase *keymap)
WM_keymap_add_item(keymap, "NLAEDIT_OT_select_all_toggle", AKEY, KM_PRESS, 0, 0);
RNA_boolean_set(WM_keymap_add_item(keymap, "NLAEDIT_OT_select_all_toggle", IKEY, KM_PRESS, KM_CTRL, 0)->ptr, "invert", 1);
+ /* editing */
+ /* tweakmode
+ * - enter and exit are separate operators with the same hotkey...
+ * This works as they use different poll()'s
+ */
+ 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);
/* transform system */
//transform_keymap_for_space(wm, keymap, SPACE_NLA);
diff --git a/source/blender/editors/space_nla/nla_select.c b/source/blender/editors/space_nla/nla_select.c
index 0626d9febe4..2e3d5572711 100644
--- a/source/blender/editors/space_nla/nla_select.c
+++ b/source/blender/editors/space_nla/nla_select.c
@@ -300,8 +300,7 @@ static void mouse_nla_strips (bAnimContext *ac, int mval[2], short select_mode)
NlaTrack *nlt= (NlaTrack *)ale->data;
nlt->flag |= NLATRACK_SELECTED;
- if (nlt->flag & NLATRACK_SELECTED)
- ANIM_set_active_channel(ac->data, ac->datatype, filter, nlt, ANIMTYPE_NLATRACK);
+ ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, nlt, ANIMTYPE_NLATRACK);
}
}
diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h
index e41ab5ac492..a566f733978 100644
--- a/source/blender/makesdna/DNA_action_types.h
+++ b/source/blender/makesdna/DNA_action_types.h
@@ -269,6 +269,7 @@ typedef enum eAction_Flags {
/* flags for evaluation/editing */
ACT_MUTED = (1<<9),
ACT_PROTECTED = (1<<10),
+ ACT_DISABLED = (1<<11),
} eAction_Flags;
diff --git a/source/blender/makesdna/DNA_anim_types.h b/source/blender/makesdna/DNA_anim_types.h
index ffc1561e7ab..c19318629f6 100644
--- a/source/blender/makesdna/DNA_anim_types.h
+++ b/source/blender/makesdna/DNA_anim_types.h
@@ -506,6 +506,9 @@ enum {
NLATRACK_SOLO = (1<<3),
/* track's settings (and strips) cannot be edited (to guard against unwanted changes) */
NLATRACK_PROTECTED = (1<<4),
+
+ /* track is not allowed to execute, usually as result of tweaking being enabled (internal flag) */
+ NLATRACK_DISABLED = (1<<10),
} eNlaTrack_Flag;
@@ -648,11 +651,15 @@ typedef struct AnimOverride {
* blocks may override local settings.
*
* This datablock should be placed immediately after the ID block where it is used, so that
- * the code which retrieves this data can do so in an easier manner. See blenkernel/internal/anim_sys.c for details.
+ * the code which retrieves this data can do so in an easier manner. See blenkernel/intern/anim_sys.c for details.
*/
typedef struct AnimData {
/* active action - acts as the 'tweaking track' for the NLA */
- bAction *action;
+ bAction *action;
+ /* temp-storage for the 'real' active action (i.e. the one used before the tweaking-action
+ * took over to be edited in the Animation Editors)
+ */
+ bAction *tmpact;
/* remapping-info for active action - should only be used if needed
* (for 'foreign' actions that aren't working correctly)
*/
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index 6f88a98fee8..8acefdad9a2 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -832,6 +832,7 @@ typedef struct Scene {
/* sce->flag */
#define SCE_DS_SELECTED (1<<0)
#define SCE_DS_COLLAPSED (1<<1)
+#define SCE_NLA_EDIT_ON (1<<2)
/* return flag next_object function */