AnimChannels Filtering Refactor - Part 4

This commit is aimed at cleaning up the filtering code by changing the
filtering idiom/pattern used. While the old code used a "check then
do" approach, the new code does a "grab then assimilate".

The main benefits are that:
* the code duplication that used to exist has now been removed, making
it easier to add new channel types for data
* a recursive "peeking" ability now means that the old problems with
data existing deep in the tree (i.e. figuring out whether a channel
should be shown based on whether it will have any descendents) should
now work much better than before.

In the process, I've found and fixed a few previously unnoticed bugs
with how some channels were constructed, so hopefully things work a
bit better now.

TODO's:
* Action-Group filtering stuff hasn't been refactored yet. This was
causing some grief in the past, so I still need to check this
carefully.
* Material Nodes support (missing in trunk) should be easy to slot in
now :)
This commit is contained in:
Joshua Leung
2011-06-26 14:50:19 +00:00
parent 5663d85e56
commit 10d775df3d
2 changed files with 589 additions and 927 deletions

View File

@@ -329,6 +329,35 @@ short ANIM_animdata_get_context (const bContext *C, bAnimContext *ac)
/* ************************************************************ */
/* Blender Data <-- Filter --> Channels to be operated on */
/* macros to use before/after getting the sub-channels of some channel,
* to abstract away some of the tricky logic involved
*
* cases:
* 1) Graph Edit main area (just data) OR channels visible in Channel List
* 2) If not showing channels, we're only interested in the data (Action Editor's editing)
* 3) We don't care what data, we just care there is some (so that a collapsed
* channel can be kept around). No need to clear channels-flag in order to
* keep expander channels with no sub-data out, as those cases should get
* dealt with by the recursive detection idiom in place.
*/
#define BEGIN_ANIMFILTER_SUBCHANNELS(expanded_check) \
{ \
int _filter = filter_mode; \
short _doSubChannels = 0; \
if (!(filter_mode & ANIMFILTER_LIST_VISIBLE) || (expanded_check)) \
_doSubChannels=1; \
else if (!(filter_mode & ANIMFILTER_LIST_CHANNELS)) \
_doSubChannels=2; \
else {\
filter_mode |= ANIMFILTER_TMP_PEEK; \
}
/* ... standard sub-channel filtering can go on here now ... */
#define END_ANIMFILTER_SUBCHANNELS \
filter_mode = _filter; \
}
/* ............................... */
/* quick macro to test if AnimData is usable */
#define ANIMDATA_HAS_KEYS(id) ((id)->adt && (id)->adt->action)
@@ -338,8 +367,7 @@ 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 above usability tests, performing the appropriate provided
* action for each when the AnimData context is appropriate.
*
* Priority order for this goes (most important, to least): AnimData blocks, NLA, Drivers, Keyframes.
@@ -395,17 +423,31 @@ 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, (ID *)id);\
/* Add a new animation channel, taking into account the "peek" flag, which is used to just check
* whether any channels will be added (but without needing them to actually get created).
*
* ! This causes the calling function to return early if we're only "peeking" for channels
*/
// XXX: ale_statement stuff is really a hack for one special case. It shouldn't really be needed...
#define ANIMCHANNEL_NEW_CHANNEL_FULL(channel_data, channel_type, owner_id, ale_statement) \
if (filter_mode & ANIMFILTER_TMP_PEEK) \
return 1; \
else { \
bAnimListElem *ale= make_new_animlistelem(channel_data, channel_type, (ID *)owner_id); \
if (ale) {\
BLI_addtail(anim_data, ale);\
items++;\
}\
BLI_addtail(anim_data, ale); \
items++; \
ale_statement \
} \
}
#define ANIMCHANNEL_NEW_CHANNEL(channel_data, channel_type, owner_id) \
ANIMCHANNEL_NEW_CHANNEL_FULL(channel_data, channel_type, owner_id, {})
/* ............................... */
/* quick macro to test if an anim-channel representing an AnimData block is suitably active */
#define ANIMCHANNEL_ACTIVEOK(ale) \
( !(filter_mode & ANIMFILTER_ACTIVE) || !(ale->adt) || (ale->adt->flag & ADT_UI_ACTIVE) )
@@ -860,7 +902,7 @@ static short skip_fcurve_with_name (bDopeSheet *ads, FCurve *fcu, ID *owner_id)
}
/* find the next F-Curve that is usable for inclusion */
static FCurve *animdata_filter_fcurve_next (bDopeSheet *ads, FCurve *first, bActionGroup *grp, int filter_mode, ID *owner_id)
static FCurve *animfilter_fcurve_next (bDopeSheet *ads, FCurve *first, bActionGroup *grp, int filter_mode, ID *owner_id)
{
FCurve *fcu = NULL;
@@ -907,7 +949,7 @@ static FCurve *animdata_filter_fcurve_next (bDopeSheet *ads, FCurve *first, bAct
return NULL;
}
static size_t animdata_filter_fcurves (ListBase *anim_data, bDopeSheet *ads, FCurve *first, bActionGroup *grp, int filter_mode, ID *owner_id)
static size_t animfilter_fcurves (ListBase *anim_data, bDopeSheet *ads, FCurve *first, bActionGroup *grp, int filter_mode, ID *owner_id)
{
FCurve *fcu;
size_t items = 0;
@@ -921,23 +963,18 @@ static size_t animdata_filter_fcurves (ListBase *anim_data, bDopeSheet *ads, FCu
* 4) the fcu pointer is set to the F-Curve after the one we just added, so that we can keep going through
* the rest of the F-Curve list without an eternal loop. Back to step 2 :)
*/
for (fcu=first; ( (fcu = animdata_filter_fcurve_next(ads, fcu, grp, filter_mode, owner_id)) ); fcu=fcu->next)
for (fcu=first; ( (fcu = animfilter_fcurve_next(ads, fcu, grp, filter_mode, owner_id)) ); fcu=fcu->next)
{
bAnimListElem *ale = make_new_animlistelem(fcu, ANIMTYPE_FCURVE, owner_id);
if (ale) {
BLI_addtail(anim_data, ale);
items++;
}
ANIMCHANNEL_NEW_CHANNEL(fcu, ANIMTYPE_FCURVE, owner_id);
}
/* return the number of items added to the list */
return items;
}
// TODO: group-filtering stuff still needs cleanup
static size_t animdata_filter_action (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, bAction *act, int filter_mode, ID *owner_id)
{
bAnimListElem *ale=NULL;
bActionGroup *agrp;
FCurve *lastchan=NULL;
size_t items = 0;
@@ -993,7 +1030,7 @@ static size_t animdata_filter_action (bAnimContext *ac, ListBase *anim_data, bDo
*
* NOTE: use filter_gmode here not filter_mode, since there may be some flags we shouldn't consider under certain circumstances
*/
first_fcu = animdata_filter_fcurve_next(ads, agrp->channels.first, agrp, filter_gmode, owner_id);
first_fcu = animfilter_fcurve_next(ads, agrp->channels.first, agrp, filter_gmode, owner_id);
/* Bug note:
* Selecting open group to toggle visbility of the group, where the F-Curves of the group are not suitable
@@ -1010,11 +1047,7 @@ static size_t animdata_filter_action (bAnimContext *ac, ListBase *anim_data, bDo
if (filter_gmode & ANIMFILTER_LIST_CHANNELS) {
/* filter selection of channel specially here again, since may be open and not subject to previous test */
if ( ANIMCHANNEL_SELOK(SEL_AGRP(agrp)) ) {
ale= make_new_animlistelem(agrp, ANIMTYPE_GROUP, owner_id);
if (ale) {
BLI_addtail(anim_data, ale);
items++;
}
ANIMCHANNEL_NEW_CHANNEL(agrp, ANIMTYPE_GROUP, owner_id);
}
}
@@ -1041,7 +1074,7 @@ static size_t animdata_filter_action (bAnimContext *ac, ListBase *anim_data, bDo
{
if (!(filter_gmode & ANIMFILTER_FOREDIT) || EDITABLE_AGRP(agrp)) {
/* NOTE: filter_gmode is used here, not standard filter_mode, since there may be some flags that shouldn't apply */
items += animdata_filter_fcurves(anim_data, ads, first_fcu, agrp, filter_gmode, owner_id);
items += animfilter_fcurves(anim_data, ads, first_fcu, agrp, filter_gmode, owner_id);
}
}
}
@@ -1052,7 +1085,7 @@ static size_t animdata_filter_action (bAnimContext *ac, ListBase *anim_data, bDo
/* loop over un-grouped F-Curves (only if we're not only considering those channels in the animive group) */
if (!(filter_mode & ANIMFILTER_ACTGROUPED)) {
// XXX the 'owner' info here needs review...
items += animdata_filter_fcurves(anim_data, ads, (lastchan)?(lastchan->next):(act->curves.first), NULL, filter_mode, owner_id);
items += animfilter_fcurves(anim_data, ads, (lastchan)?(lastchan->next):(act->curves.first), NULL, filter_mode, owner_id);
}
/* return the number of items added to the list */
@@ -1067,9 +1100,8 @@ static size_t animdata_filter_action (bAnimContext *ac, ListBase *anim_data, bDo
* - for normal filtering (i.e. for editing), we only need the NLA-tracks but they can be in 'normal' evaluation
* order, i.e. first to last. Otherwise, some tools may get screwed up.
*/
static size_t animdata_filter_nla (bAnimContext *UNUSED(ac), ListBase *anim_data, bDopeSheet *UNUSED(ads), AnimData *adt, int filter_mode, ID *owner_id)
static size_t animfilter_nla (bAnimContext *UNUSED(ac), ListBase *anim_data, bDopeSheet *UNUSED(ads), AnimData *adt, int filter_mode, ID *owner_id)
{
bAnimListElem *ale;
NlaTrack *nlt;
NlaTrack *first=NULL, *next=NULL;
size_t items = 0;
@@ -1077,19 +1109,15 @@ static size_t animdata_filter_nla (bAnimContext *UNUSED(ac), ListBase *anim_data
/* if showing channels, include active action */
if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
/* there isn't really anything editable here, so skip if need editable */
// TODO: currently, selection isn't checked since it doesn't matter
if ((filter_mode & ANIMFILTER_FOREDIT) == 0) {
/* just add the action track now (this MUST appear for drawing)
* - as AnimData may not have an action, we pass a dummy pointer just to get the list elem created, then
* overwrite this with the real value - REVIEW THIS...
*/
ale= make_new_animlistelem((void *)(&adt->action), ANIMTYPE_NLAACTION, owner_id);
ale->data= (adt->action) ? adt->action : NULL;
if (ale) {
BLI_addtail(anim_data, ale);
items++;
}
ANIMCHANNEL_NEW_CHANNEL_FULL((void *)(&adt->action), ANIMTYPE_NLAACTION, owner_id,
{
ale->data= adt->action ? adt->action : NULL;
});
}
/* first track to include will be the last one if we're filtering by channels */
@@ -1121,12 +1149,7 @@ static size_t animdata_filter_nla (bAnimContext *UNUSED(ac), ListBase *anim_data
if ( ANIMCHANNEL_SELOK(SEL_NLT(nlt)) ) {
/* only include if this track is active */
if (!(filter_mode & ANIMFILTER_ACTIVE) || (nlt->flag & NLATRACK_ACTIVE)) {
ale= make_new_animlistelem(nlt, ANIMTYPE_NLATRACK, owner_id);
if (ale) {
BLI_addtail(anim_data, ale);
items++;
}
ANIMCHANNEL_NEW_CHANNEL(nlt, ANIMTYPE_NLATRACK, owner_id);
}
}
}
@@ -1136,10 +1159,40 @@ static size_t animdata_filter_nla (bAnimContext *UNUSED(ac), ListBase *anim_data
return items;
}
/* determine what animation data from AnimData block should get displayed */
static size_t animfilter_block_data (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, ID *id, int filter_mode)
{
IdAdtTemplate *iat = (IdAdtTemplate*)id;
AnimData *adt = BKE_animdata_from_id(id);
size_t items = 0;
/* NOTE: this macro is used instead of inlining the logic here, since this sort of filtering is still needed
* in a few places in he rest of the code still - notably for the few cases where special mode-based
* different types of data expanders are required.
*/
ANIMDATA_FILTER_CASES(iat,
{ /* AnimData */
/* specifically filter animdata block */
ANIMCHANNEL_NEW_CHANNEL(adt, ANIMTYPE_ANIMDATA, id);
},
{ /* NLA */
items += animfilter_nla(ac, anim_data, ads, adt, filter_mode, id);
},
{ /* Drivers */
items += animfilter_fcurves(anim_data, ads, adt->drivers.first, NULL, filter_mode, id);
},
{ /* Keyframes */
items += animdata_filter_action(ac, anim_data, ads, adt->action, filter_mode, id);
});
return items;
}
/* Include ShapeKey Data for ShapeKey Editor */
static size_t animdata_filter_shapekey (bAnimContext *ac, ListBase *anim_data, Key *key, int filter_mode)
{
bAnimListElem *ale;
size_t items = 0;
/* check if channels or only F-Curves */
@@ -1159,12 +1212,7 @@ static size_t animdata_filter_shapekey (bAnimContext *ac, ListBase *anim_data, K
// TODO: consider 'active' too?
/* owner-id here must be key so that the F-Curve can be resolved... */
ale= make_new_animlistelem(kb, ANIMTYPE_SHAPEKEY, (ID *)key);
if (ale) {
BLI_addtail(anim_data, ale);
items++;
}
ANIMCHANNEL_NEW_CHANNEL(kb, ANIMTYPE_SHAPEKEY, key);
}
}
}
@@ -1173,10 +1221,12 @@ static size_t animdata_filter_shapekey (bAnimContext *ac, ListBase *anim_data, K
/* just use the action associated with the shapekey */
// TODO: somehow manage to pass dopesheet info down here too?
if (key->adt) {
if (filter_mode & ANIMFILTER_ANIMDATA)
ANIMDATA_ADD_ANIMDATA(key)
else if (key->adt->action)
if (filter_mode & ANIMFILTER_ANIMDATA) {
ANIMCHANNEL_NEW_CHANNEL(key->adt, ANIMTYPE_ANIMDATA, key);
}
else if (key->adt->action) {
items= animdata_filter_action(ac, anim_data, NULL, key->adt->action, filter_mode, (ID *)key);
}
}
}
@@ -1188,7 +1238,6 @@ static size_t animdata_filter_shapekey (bAnimContext *ac, ListBase *anim_data, K
// TODO: should this be amalgamated with the dopesheet filtering code?
static size_t animdata_filter_gpencil (ListBase *anim_data, void *UNUSED(data), int filter_mode)
{
bAnimListElem *ale;
bGPdata *gpd;
bGPDlayer *gpl;
size_t items = 0;
@@ -1204,11 +1253,7 @@ static size_t animdata_filter_gpencil (ListBase *anim_data, void *UNUSED(data),
/* add gpd as channel too (if for drawing, and it has layers) */
if ((filter_mode & ANIMFILTER_LIST_CHANNELS) && (gpd->layers.first)) {
/* add to list */
ale= make_new_animlistelem(gpd, ANIMTYPE_GPDATABLOCK, NULL);
if (ale) {
BLI_addtail(anim_data, ale);
items++;
}
ANIMCHANNEL_NEW_CHANNEL(gpd, ANIMTYPE_GPDATABLOCK, NULL);
}
/* only add layers if they will be visible (if drawing channels) */
@@ -1220,11 +1265,7 @@ static size_t animdata_filter_gpencil (ListBase *anim_data, void *UNUSED(data),
/* only if editable */
if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_GPL(gpl)) {
/* add to list */
ale= make_new_animlistelem(gpl, ANIMTYPE_GPLAYER, (ID*)gpd);
if (ale) {
BLI_addtail(anim_data, ale);
items++;
}
ANIMCHANNEL_NEW_CHANNEL(gpl, ANIMTYPE_GPLAYER, gpd);
}
}
}
@@ -1236,10 +1277,59 @@ static size_t animdata_filter_gpencil (ListBase *anim_data, void *UNUSED(data),
return items;
}
/* NOTE: owner_id is either material, lamp, or world block, which is the direct owner of the texture stack in question */
static size_t animdata_filter_dopesheet_texs (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, ID *owner_id, int filter_mode)
/* NOTE: owner_id is scene, material, or texture block, which is the direct owner of the node tree in question */
// TODO: how to handle group nodes is still unclear...
static size_t animdata_filter_ds_nodetree (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, ID *owner_id, bNodeTree *ntree, int filter_mode)
{
ListBase tmp_data = {NULL, NULL};
short expanded = 0;
size_t tmp_items = 0;
size_t items = 0;
/* get datatype specific data first */
if (owner_id == NULL)
return 0;
switch (GS(owner_id->name)) {
case ID_SCE: /* compositing nodes */
{
//Scene *scene = (Scene *)owner_id;
expanded = FILTER_NTREE_SCED(ntree); // XXX: this macro needs renaming... doesn't only do this for scene ones!
}
break;
}
/* add nodetree animation channels */
BEGIN_ANIMFILTER_SUBCHANNELS(expanded)
{
/* animation data filtering */
tmp_items += animfilter_block_data(ac, &tmp_data, ads, (ID *)ntree, filter_mode);
}
END_ANIMFILTER_SUBCHANNELS;
/* did we find anything? */
if (tmp_items) {
/* include data-expand widget first */
if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
/* check if filtering by active status */
if ANIMCHANNEL_ACTIVEOK(ntree) {
ANIMCHANNEL_NEW_CHANNEL(ntree, ANIMTYPE_DSNTREE, owner_id);
}
}
/* now add the list of collected channels */
BLI_movelisttolist(anim_data, &tmp_data);
BLI_assert((tmp_data.first == tmp_data.last) && (tmp_data.first == NULL));
items += tmp_items;
}
/* return the number of items added to the list */
return items;
}
/* NOTE: owner_id is either material, lamp, or world block, which is the direct owner of the texture stack in question */
static size_t animdata_filter_ds_textures (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, ID *owner_id, int filter_mode)
{
bAnimListElem *ale=NULL;
MTex **mtex = NULL;
size_t items=0;
int a=0;
@@ -1252,21 +1342,18 @@ static size_t animdata_filter_dopesheet_texs (bAnimContext *ac, ListBase *anim_d
case ID_MA:
{
Material *ma= (Material *)owner_id;
mtex= (MTex**)(&ma->mtex);
}
break;
case ID_LA:
{
Lamp *la= (Lamp *)owner_id;
mtex= (MTex**)(&la->mtex);
}
break;
case ID_WO:
{
World *wo= (World *)owner_id;
mtex= (MTex**)(&wo->mtex);
}
break;
@@ -1282,39 +1369,34 @@ static size_t animdata_filter_dopesheet_texs (bAnimContext *ac, ListBase *anim_d
/* firstly check that we actuallly have some textures, by gathering all textures in a temp list */
for (a=0; a < MAX_MTEX; a++) {
Tex *tex= (mtex[a]) ? mtex[a]->tex : NULL;
short ok = 0;
ListBase tmp_data = {NULL, NULL};
size_t tmp_items = 0;
/* for now, if no texture returned, skip (this shouldn't confuse the user I hope) */
if (ELEM(NULL, tex, tex->adt))
continue;
/* check if ok */
ANIMDATA_FILTER_CASES(tex,
{ /* AnimData blocks - do nothing... */ },
ok=1;,
ok=1;,
ok=1;)
if (ok == 0) continue;
/* add texture's animation data to temp collection */
BEGIN_ANIMFILTER_SUBCHANNELS(FILTER_TEX_DATA(tex))
{
tmp_items += animfilter_block_data(ac, &tmp_data, ads, (ID *)tex, filter_mode);
}
END_ANIMFILTER_SUBCHANNELS;
/* include texture-expand widget? */
if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
/* check if filtering by active status */
if ANIMCHANNEL_ACTIVEOK(tex) {
ale= make_new_animlistelem(tex, ANIMTYPE_DSTEX, owner_id);
if (ale) {
BLI_addtail(anim_data, ale);
items++;
/* did we find anything? */
if (tmp_items) {
/* include texture-expand widget? */
if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
/* check if filtering by active status */
if ANIMCHANNEL_ACTIVEOK(tex) {
ANIMCHANNEL_NEW_CHANNEL(tex, ANIMTYPE_DSTEX, owner_id);
}
}
}
/* add texture's animation data */
if (!(filter_mode & ANIMFILTER_LIST_VISIBLE) || FILTER_TEX_DATA(tex)) {
ANIMDATA_FILTER_CASES(tex,
{ /* AnimData blocks - do nothing... */ },
items += animdata_filter_nla(ac, anim_data, ads, tex->adt, filter_mode, (ID *)tex);,
items += animdata_filter_fcurves(anim_data, ads, tex->adt->drivers.first, NULL, filter_mode, (ID *)tex);,
items += animdata_filter_action(ac, anim_data, ads, tex->adt->action, filter_mode, (ID *)tex);)
/* now add the list of collected channels */
BLI_movelisttolist(anim_data, &tmp_data);
BLI_assert((tmp_data.first == tmp_data.last) && (tmp_data.first == NULL));
items += tmp_items;
}
}
@@ -1322,118 +1404,47 @@ static size_t animdata_filter_dopesheet_texs (bAnimContext *ac, ListBase *anim_d
return items;
}
static size_t animdata_filter_dopesheet_mats (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Object *ob, int filter_mode)
static size_t animdata_filter_ds_materials (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Object *ob, int filter_mode)
{
bAnimListElem *ale=NULL;
size_t items=0;
int a=0;
/* firstly check that we actuallly have some materials, by gathering all materials in a temp list */
for (a=1; a <= ob->totcol; a++) {
Material *ma= give_current_material(ob, a);
short ok = 0;
ListBase tmp_data = {NULL, NULL};
size_t tmp_items = 0;
/* for now, if no material returned, skip (this shouldn't confuse the user I hope) */
/* if no material returned, skip - so that we don't get weird blank entries... */
if (ma == NULL) continue;
/* check if ok */
ANIMDATA_FILTER_CASES(ma,
{ /* AnimData blocks - do nothing... */ },
ok=1;,
ok=1;,
ok=1;)
/* need to check textures */
if (ok == 0 && !(ads->filterflag & ADS_FILTER_NOTEX)) {
int mtInd;
for (mtInd=0; mtInd < MAX_MTEX; mtInd++) {
MTex *mtex = ma->mtex[mtInd];
if (mtex && mtex->tex) {
ANIMDATA_FILTER_CASES(mtex->tex,
{ /* AnimData blocks - do nothing... */ },
ok=1;,
ok=1;,
ok=1;)
}
if (ok)
break;
}
}
if (ok == 0) continue;
/* include material-expand widget? */
// hmm... do we need to store the index of this material in the array anywhere?
if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
/* check if filtering by active status */
if ANIMCHANNEL_ACTIVEOK(ma) {
ale= make_new_animlistelem(ma, ANIMTYPE_DSMAT, (ID *)ma);
if (ale) {
BLI_addtail(anim_data, ale);
items++;
}
}
}
/* add material's animation data */
if (!(filter_mode & ANIMFILTER_LIST_VISIBLE) || FILTER_MAT_OBJD(ma)) {
/* add material's animation data to temp collection */
BEGIN_ANIMFILTER_SUBCHANNELS(FILTER_MAT_OBJD(ma))
{
/* material's animation data */
ANIMDATA_FILTER_CASES(ma,
{ /* AnimData blocks - do nothing... */ },
items += animdata_filter_nla(ac, anim_data, ads, ma->adt, filter_mode, (ID *)ma);,
items += animdata_filter_fcurves(anim_data, ads, ma->adt->drivers.first, NULL, filter_mode, (ID *)ma);,
items += animdata_filter_action(ac, anim_data, ads, ma->adt->action, filter_mode, (ID *)ma);)
tmp_items += animfilter_block_data(ac, &tmp_data, ads, (ID *)ma, filter_mode);
/* textures */
if (!(ads->filterflag & ADS_FILTER_NOTEX))
items += animdata_filter_dopesheet_texs(ac, anim_data, ads, (ID *)ma, filter_mode);
tmp_items += animdata_filter_ds_textures(ac, &tmp_data, ads, (ID *)ma, filter_mode);
}
}
/* return the number of items added to the list */
return items;
}
static size_t animdata_filter_dopesheet_particles (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Object *ob, int filter_mode)
{
bAnimListElem *ale=NULL;
ParticleSystem *psys = ob->particlesystem.first;
size_t items= 0;
for(; psys; psys=psys->next) {
short ok = 0;
END_ANIMFILTER_SUBCHANNELS;
if(ELEM(NULL, psys->part, psys->part->adt))
continue;
ANIMDATA_FILTER_CASES(psys->part,
{ /* AnimData blocks - do nothing... */ },
ok=1;,
ok=1;,
ok=1;)
if (ok == 0) continue;
/* add particle settings? */
if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
/* check if filtering by active status */
if ANIMCHANNEL_ACTIVEOK(psys->part) {
ale = make_new_animlistelem(psys->part, ANIMTYPE_DSPART, (ID *)psys->part);
if (ale) {
BLI_addtail(anim_data, ale);
items++;
/* did we find anything? */
if (tmp_items) {
/* include material-expand widget first */
// hmm... do we need to store the index of this material in the array anywhere?
if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
/* check if filtering by active status */
if ANIMCHANNEL_ACTIVEOK(ma) {
ANIMCHANNEL_NEW_CHANNEL(ma, ANIMTYPE_DSMAT, ma);
}
}
}
if (!(filter_mode & ANIMFILTER_LIST_VISIBLE) || FILTER_PART_OBJD(psys->part)) {
ANIMDATA_FILTER_CASES(psys->part,
{ /* AnimData blocks - do nothing... */ },
items += animdata_filter_nla(ac, anim_data, ads, psys->part->adt, filter_mode, (ID *)psys->part);,
items += animdata_filter_fcurves(anim_data, ads, psys->part->adt->drivers.first, NULL, filter_mode, (ID *)psys->part);,
items += animdata_filter_action(ac, anim_data, ads, psys->part->adt->action, filter_mode, (ID *)psys->part);)
/* now add the list of collected channels */
BLI_movelisttolist(anim_data, &tmp_data);
BLI_assert((tmp_data.first == tmp_data.last) && (tmp_data.first == NULL));
items += tmp_items;
}
}
@@ -1441,13 +1452,56 @@ static size_t animdata_filter_dopesheet_particles (bAnimContext *ac, ListBase *a
return items;
}
static size_t animdata_filter_dopesheet_obdata (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Object *ob, int filter_mode)
static size_t animdata_filter_ds_particles (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Object *ob, int filter_mode)
{
bAnimListElem *ale=NULL;
IdAdtTemplate *iat= ob->data;
AnimData *adt= iat->adt;
short type=0, expanded=0;
ParticleSystem *psys;
size_t items= 0;
for (psys = ob->particlesystem.first; psys; psys=psys->next) {
ListBase tmp_data = {NULL, NULL};
size_t tmp_items = 0;
/* if no material returned, skip - so that we don't get weird blank entries... */
if (ELEM(NULL, psys->part, psys->part->adt))
continue;
/* add particle-system's animation data to temp collection */
BEGIN_ANIMFILTER_SUBCHANNELS(FILTER_PART_OBJD(psys->part))
{
/* material's animation data */
tmp_items += animfilter_block_data(ac, &tmp_data, ads, (ID *)psys->part, filter_mode);
}
END_ANIMFILTER_SUBCHANNELS;
/* did we find anything? */
if (tmp_items) {
/* include particle-expand widget first */
if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
/* check if filtering by active status */
if ANIMCHANNEL_ACTIVEOK(psys->part) {
ANIMCHANNEL_NEW_CHANNEL(psys->part, ANIMTYPE_DSPART, psys->part);
}
}
/* now add the list of collected channels */
BLI_movelisttolist(anim_data, &tmp_data);
BLI_assert((tmp_data.first == tmp_data.last) && (tmp_data.first == NULL));
items += tmp_items;
}
}
/* return the number of items added to the list */
return items;
}
static size_t animdata_filter_ds_obdata (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Object *ob, int filter_mode)
{
ListBase tmp_data = {NULL, NULL};
size_t tmp_items = 0;
size_t items= 0;
IdAdtTemplate *iat= ob->data;
short type=0, expanded=0;
/* get settings based on data type */
switch (ob->type) {
@@ -1455,6 +1509,9 @@ static size_t animdata_filter_dopesheet_obdata (bAnimContext *ac, ListBase *anim
{
Camera *ca= (Camera *)ob->data;
if (ads->filterflag & ADS_FILTER_NOCAM)
return 0;
type= ANIMTYPE_DSCAM;
expanded= FILTER_CAM_OBJD(ca);
}
@@ -1463,6 +1520,9 @@ static size_t animdata_filter_dopesheet_obdata (bAnimContext *ac, ListBase *anim
{
Lamp *la= (Lamp *)ob->data;
if (ads->filterflag & ADS_FILTER_NOLAM)
return 0;
type= ANIMTYPE_DSLAM;
expanded= FILTER_LAM_OBJD(la);
}
@@ -1473,6 +1533,9 @@ static size_t animdata_filter_dopesheet_obdata (bAnimContext *ac, ListBase *anim
{
Curve *cu= (Curve *)ob->data;
if (ads->filterflag & ADS_FILTER_NOCUR)
return 0;
type= ANIMTYPE_DSCUR;
expanded= FILTER_CUR_OBJD(cu);
}
@@ -1481,6 +1544,9 @@ static size_t animdata_filter_dopesheet_obdata (bAnimContext *ac, ListBase *anim
{
MetaBall *mb= (MetaBall *)ob->data;
if (ads->filterflag & ADS_FILTER_NOMBA)
return 0;
type= ANIMTYPE_DSMBALL;
expanded= FILTER_MBALL_OBJD(mb);
}
@@ -1489,6 +1555,9 @@ static size_t animdata_filter_dopesheet_obdata (bAnimContext *ac, ListBase *anim
{
bArmature *arm= (bArmature *)ob->data;
if (ads->filterflag & ADS_FILTER_NOARM)
return 0;
type= ANIMTYPE_DSARM;
expanded= FILTER_ARM_OBJD(arm);
}
@@ -1497,6 +1566,9 @@ static size_t animdata_filter_dopesheet_obdata (bAnimContext *ac, ListBase *anim
{
Mesh *me= (Mesh *)ob->data;
if (ads->filterflag & ADS_FILTER_NOMESH)
return 0;
type= ANIMTYPE_DSMESH;
expanded= FILTER_MESH_OBJD(me);
}
@@ -1505,456 +1577,356 @@ static size_t animdata_filter_dopesheet_obdata (bAnimContext *ac, ListBase *anim
{
Lattice *lt = (Lattice *)ob->data;
if (ads->filterflag & ADS_FILTER_NOLAT)
return 0;
type= ANIMTYPE_DSLAT;
expanded= FILTER_LATTICE_OBJD(lt);
}
break;
}
/* include data-expand widget? */
if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
/* check if filtering by active status */
if ANIMCHANNEL_ACTIVEOK(iat) {
ale= make_new_animlistelem(iat, type, (ID *)iat);
if (ale) BLI_addtail(anim_data, ale);
}
}
/* add object-data animation channels? */
if (!(filter_mode & ANIMFILTER_LIST_VISIBLE) || (expanded)) {
/* filtering for channels - nla, drivers, keyframes */
ANIMDATA_FILTER_CASES(iat,
{ /* AnimData blocks - do nothing... */ },
items+= animdata_filter_nla(ac, anim_data, ads, iat->adt, filter_mode, (ID *)iat);,
items+= animdata_filter_fcurves(anim_data, ads, adt->drivers.first, NULL, filter_mode, (ID *)iat);,
items+= animdata_filter_action(ac, anim_data, ads, iat->adt->action, filter_mode, (ID *)iat);)
/* add object data animation channels */
BEGIN_ANIMFILTER_SUBCHANNELS(expanded)
{
/* animation data filtering */
tmp_items += animfilter_block_data(ac, &tmp_data, ads, (ID *)iat, filter_mode);
/* sub-data filtering... */
switch (ob->type) {
case OB_LAMP: /* lamp - textures */
{
/* textures */
if (!(ads->filterflag & ADS_FILTER_NOTEX))
items += animdata_filter_dopesheet_texs(ac, anim_data, ads, ob->data, filter_mode);
tmp_items += animdata_filter_ds_textures(ac, &tmp_data, ads, ob->data, filter_mode);
}
break;
}
}
END_ANIMFILTER_SUBCHANNELS;
/* did we find anything? */
if (tmp_items) {
/* include data-expand widget first */
if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
/* check if filtering by active status */
if ANIMCHANNEL_ACTIVEOK(iat) {
ANIMCHANNEL_NEW_CHANNEL(iat, type, iat);
}
}
/* now add the list of collected channels */
BLI_movelisttolist(anim_data, &tmp_data);
BLI_assert((tmp_data.first == tmp_data.last) && (tmp_data.first == NULL));
items += tmp_items;
}
/* return the number of items added to the list */
return items;
}
static size_t animdata_filter_dopesheet_ob (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Base *base, int filter_mode)
/* shapekey-level animation */
static size_t animdata_filter_ds_keyanim (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Object *ob, Key *key, int filter_mode)
{
bAnimListElem *ale=NULL;
AnimData *adt = NULL;
Object *ob= base->object;
Key *key= ob_get_key(ob);
short obdata_ok = 0;
ListBase tmp_data = {NULL, NULL};
size_t tmp_items = 0;
size_t items = 0;
/* add this object as a channel first */
if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
/* check if filtering by selection */
if ANIMCHANNEL_SELOK((base->flag & SELECT)) {
/* check if filtering by active status */
if ANIMCHANNEL_ACTIVEOK(ob) {
ale= make_new_animlistelem(base, ANIMTYPE_OBJECT, (ID *)ob);
if (ale) {
BLI_addtail(anim_data, ale);
items++;
}
}
}
/* add shapekey-level animation channels */
BEGIN_ANIMFILTER_SUBCHANNELS(FILTER_SKE_OBJD(key))
{
/* animation data filtering */
tmp_items += animfilter_block_data(ac, &tmp_data, ads, (ID *)key, filter_mode);
}
END_ANIMFILTER_SUBCHANNELS;
/* if collapsed, don't go any further (unless adding keyframes only) */
if ((filter_mode & ANIMFILTER_LIST_VISIBLE) && EXPANDED_OBJC(ob) == 0)
return items;
/* Action, Drivers, or NLA */
if (ob->adt && !(ads->filterflag & ADS_FILTER_NOOBJ)) {
adt= ob->adt;
ANIMDATA_FILTER_CASES(ob,
{ /* AnimData blocks - do nothing... */ },
{ /* nla */
/* add NLA tracks */
items += animdata_filter_nla(ac, anim_data, ads, adt, filter_mode, (ID *)ob);
},
{ /* drivers */
/* include drivers-expand widget? */
if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
ale= make_new_animlistelem(adt, ANIMTYPE_FILLDRIVERS, (ID *)ob);
if (ale) {
BLI_addtail(anim_data, ale);
items++;
}
}
/* add F-Curve channels (drivers are F-Curves) */
if (!(filter_mode & ANIMFILTER_LIST_VISIBLE) || EXPANDED_DRVD(adt)) {
items += animdata_filter_fcurves(anim_data, ads, adt->drivers.first, NULL, filter_mode, (ID *)ob);
}
},
{ /* action (keyframes) */
/* include action-expand widget? */
if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLACTD, (ID *)ob);
if (ale) {
BLI_addtail(anim_data, ale);
items++;
}
}
/* add F-Curve channels? */
if (!(filter_mode & ANIMFILTER_LIST_VISIBLE) || EXPANDED_ACTC(adt->action)) {
items += animdata_filter_action(ac, anim_data, ads, adt->action, filter_mode, (ID *)ob);
}
/* did we find anything? */
if (tmp_items) {
/* include key-expand widget first */
if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
if ANIMCHANNEL_ACTIVEOK(key) {
ANIMCHANNEL_NEW_CHANNEL(key, ANIMTYPE_DSSKEY, ob);
}
);
}
/* now add the list of collected channels */
BLI_movelisttolist(anim_data, &tmp_data);
BLI_assert((tmp_data.first == tmp_data.last) && (tmp_data.first == NULL));
items += tmp_items;
}
/* ShapeKeys? */
if ((key) && !(ads->filterflag & ADS_FILTER_NOSHAPEKEYS)) {
adt= key->adt;
ANIMDATA_FILTER_CASES(key,
{ /* AnimData blocks - do nothing... */ },
{ /* nla */
/* include shapekey-expand widget? */
if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
/* check if filtering by active status */
if ANIMCHANNEL_ACTIVEOK(key) {
ale= make_new_animlistelem(key, ANIMTYPE_DSSKEY, (ID *)ob);
if (ale) {
BLI_addtail(anim_data, ale);
items++;
}
}
}
/* add NLA tracks - only if expanded or so */
if (!(filter_mode & ANIMFILTER_LIST_VISIBLE) || FILTER_SKE_OBJD(key))
items += animdata_filter_nla(ac, anim_data, ads, adt, filter_mode, (ID *)key);
},
{ /* drivers */
/* include shapekey-expand widget? */
if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
ale= make_new_animlistelem(key, ANIMTYPE_DSSKEY, (ID *)ob);
if (ale) {
BLI_addtail(anim_data, ale);
items++;
}
}
/* add channels */
if (!(filter_mode & ANIMFILTER_LIST_VISIBLE) || FILTER_SKE_OBJD(key)) {
items += animdata_filter_fcurves(anim_data, ads, adt->drivers.first, NULL, filter_mode, (ID *)key);
}
},
{ /* action (keyframes) */
/* include shapekey-expand widget? */
if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
/* check if filtering by active status */
if ANIMCHANNEL_ACTIVEOK(key) {
ale= make_new_animlistelem(key, ANIMTYPE_DSSKEY, (ID *)ob);
if (ale) {
BLI_addtail(anim_data, ale);
items++;
}
}
}
/* add channels */
if (!(filter_mode & ANIMFILTER_LIST_VISIBLE) || FILTER_SKE_OBJD(key)) {
items += animdata_filter_action(ac, anim_data, ads, adt->action, filter_mode, (ID *)key);
}
}
);
}
/* Materials? */
if ((ob->totcol) && !(ads->filterflag & ADS_FILTER_NOMAT))
items += animdata_filter_dopesheet_mats(ac, anim_data, ads, ob, filter_mode);
/* Object Data */
switch (ob->type) {
case OB_CAMERA: /* ------- Camera ------------ */
{
Camera *ca= (Camera *)ob->data;
if ((ads->filterflag & ADS_FILTER_NOCAM) == 0) {
ANIMDATA_FILTER_CASES(ca,
{ /* AnimData blocks - do nothing... */ },
obdata_ok= 1;,
obdata_ok= 1;,
obdata_ok= 1;)
}
}
break;
case OB_LAMP: /* ---------- Lamp ----------- */
{
Lamp *la= (Lamp *)ob->data;
if ((ads->filterflag & ADS_FILTER_NOLAM) == 0) {
ANIMDATA_FILTER_CASES(la,
{ /* AnimData blocks - do nothing... */ },
obdata_ok= 1;,
obdata_ok= 1;,
obdata_ok= 1;)
}
}
break;
case OB_CURVE: /* ------- Curve ---------- */
case OB_SURF: /* ------- Nurbs Surface ---------- */
case OB_FONT: /* ------- Text Curve ---------- */
{
Curve *cu= (Curve *)ob->data;
if ((ads->filterflag & ADS_FILTER_NOCUR) == 0) {
ANIMDATA_FILTER_CASES(cu,
{ /* AnimData blocks - do nothing... */ },
obdata_ok= 1;,
obdata_ok= 1;,
obdata_ok= 1;)
}
}
break;
case OB_MBALL: /* ------- MetaBall ---------- */
{
MetaBall *mb= (MetaBall *)ob->data;
if ((ads->filterflag & ADS_FILTER_NOMBA) == 0) {
ANIMDATA_FILTER_CASES(mb,
{ /* AnimData blocks - do nothing... */ },
obdata_ok= 1;,
obdata_ok= 1;,
obdata_ok= 1;)
}
}
break;
case OB_ARMATURE: /* ------- Armature ---------- */
{
bArmature *arm= (bArmature *)ob->data;
if ((ads->filterflag & ADS_FILTER_NOARM) == 0) {
ANIMDATA_FILTER_CASES(arm,
{ /* AnimData blocks - do nothing... */ },
obdata_ok= 1;,
obdata_ok= 1;,
obdata_ok= 1;)
}
}
break;
case OB_MESH: /* ------- Mesh ---------- */
{
Mesh *me= (Mesh *)ob->data;
if ((ads->filterflag & ADS_FILTER_NOMESH) == 0) {
ANIMDATA_FILTER_CASES(me,
{ /* AnimData blocks - do nothing... */ },
obdata_ok= 1;,
obdata_ok= 1;,
obdata_ok= 1;)
}
}
break;
case OB_LATTICE: /* ------- Lattice ---------- */
{
Lattice *lt= (Lattice *)ob->data;
if ((ads->filterflag & ADS_FILTER_NOLAT) == 0) {
ANIMDATA_FILTER_CASES(lt,
{ /* AnimData blocks - do nothing... */ },
obdata_ok= 1;,
obdata_ok= 1;,
obdata_ok= 1;)
}
}
break;
}
if (obdata_ok)
items += animdata_filter_dopesheet_obdata(ac, anim_data, ads, ob, filter_mode);
/* particles */
if (ob->particlesystem.first && !(ads->filterflag & ADS_FILTER_NOPART))
items += animdata_filter_dopesheet_particles(ac, anim_data, ads, ob, filter_mode);
/* return the number of items added to the list */
return items;
}
}
static size_t animdata_filter_dopesheet_scene (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Scene *sce, int filter_mode)
/* object-level animation */
static size_t animdata_filter_ds_obanim (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Object *ob, int filter_mode)
{
World *wo= sce->world;
bNodeTree *ntree= sce->nodetree;
AnimData *adt= NULL;
bAnimListElem *ale;
ListBase tmp_data = {NULL, NULL};
size_t tmp_items = 0;
size_t items = 0;
/* add scene as a channel first (even if we aren't showing scenes we still need to show the scene's sub-data */
if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
/* check if filtering by selection */
if (ANIMCHANNEL_SELOK( (sce->flag & SCE_DS_SELECTED) )) {
ale= make_new_animlistelem(sce, ANIMTYPE_SCENE, NULL);
if (ale) {
BLI_addtail(anim_data, ale);
items++;
AnimData *adt = ob->adt;
short type=0, expanded=1;
void *cdata = NULL;
/* determine the type of expander channels to use */
// this is the best way to do this for now...
ANIMDATA_FILTER_CASES(ob,
{/* AnimData - no channel, but consider data */},
{/* NLA - no channel, but consider data */},
{/* Drivers */
type = ANIMTYPE_FILLDRIVERS;
cdata = adt;
expanded = EXPANDED_DRVD(adt);
},
{/* Keyframes */
type = ANIMTYPE_FILLACTD;
cdata = adt->action;
expanded = EXPANDED_ACTC(adt->action);
});
/* add object-level animation channels */
BEGIN_ANIMFILTER_SUBCHANNELS(expanded)
{
/* animation data filtering */
tmp_items += animfilter_block_data(ac, &tmp_data, ads, (ID *)ob, filter_mode);
}
END_ANIMFILTER_SUBCHANNELS;
/* did we find anything? */
if (tmp_items) {
/* include anim-expand widget first */
if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
if (type != ANIMTYPE_NONE) {
/* NOTE: active-status (and the associated checks) don't apply here... */
ANIMCHANNEL_NEW_CHANNEL(cdata, type, ob);
}
}
}
/* if collapsed, don't go any further (unless adding keyframes only) */
if ((filter_mode & ANIMFILTER_LIST_VISIBLE) && (EXPANDED_SCEC(sce) == 0))
return items;
/* Action, Drivers, or NLA for Scene */
if ((ads->filterflag & ADS_FILTER_NOSCE) == 0) {
adt= sce->adt;
ANIMDATA_FILTER_CASES(sce,
{ /* AnimData blocks - do nothing... */ },
{ /* nla */
/* add NLA tracks */
items += animdata_filter_nla(ac, anim_data, ads, adt, filter_mode, (ID *)sce);
},
{ /* drivers */
/* include drivers-expand widget? */
if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLDRIVERS, (ID *)sce);
if (ale) {
BLI_addtail(anim_data, ale);
items++;
}
}
/* add F-Curve channels (drivers are F-Curves) */
if (!(filter_mode & ANIMFILTER_LIST_VISIBLE) || EXPANDED_DRVD(adt)) {
items += animdata_filter_fcurves(anim_data, ads, adt->drivers.first, NULL, filter_mode, (ID *)sce);
}
},
{ /* action */
/* include action-expand widget? */
if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLACTD, (ID *)sce);
if (ale) {
BLI_addtail(anim_data, ale);
items++;
}
}
/* add F-Curve channels? */
if (!(filter_mode & ANIMFILTER_LIST_VISIBLE) || EXPANDED_ACTC(adt->action)) {
items += animdata_filter_action(ac, anim_data, ads, adt->action, filter_mode, (ID *)sce);
}
}
)
}
/* world */
if ((wo && wo->adt) && !(ads->filterflag & ADS_FILTER_NOWOR)) {
/* Action, Drivers, or NLA for World */
adt= wo->adt;
ANIMDATA_FILTER_CASES(wo,
{ /* AnimData blocks - do nothing... */ },
{ /* nla */
/* add NLA tracks */
items += animdata_filter_nla(ac, anim_data, ads, adt, filter_mode, (ID *)wo);
},
{ /* drivers */
/* include world-expand widget? */
if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
ale= make_new_animlistelem(wo, ANIMTYPE_DSWOR, (ID *)wo);
if (ale) {
BLI_addtail(anim_data, ale);
items++;
}
}
/* add F-Curve channels (drivers are F-Curves) */
if (!(filter_mode & ANIMFILTER_LIST_VISIBLE) || FILTER_WOR_SCED(wo)/*EXPANDED_DRVD(adt)*/) {
// XXX owner info is messed up now...
items += animdata_filter_fcurves(anim_data, ads, adt->drivers.first, NULL, filter_mode, (ID *)wo);
}
},
{ /* action */
/* include world-expand widget? */
if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
ale= make_new_animlistelem(wo, ANIMTYPE_DSWOR, (ID *)sce);
if (ale) {
BLI_addtail(anim_data, ale);
items++;
}
}
/* add channels */
if (!(filter_mode & ANIMFILTER_LIST_VISIBLE) || FILTER_WOR_SCED(wo)) {
items += animdata_filter_action(ac, anim_data, ads, adt->action, filter_mode, (ID *)wo);
}
}
)
/* if expanded, check world textures too */
if (!(filter_mode & ANIMFILTER_LIST_VISIBLE) || FILTER_WOR_SCED(wo)) {
/* textures for world */
if (!(ads->filterflag & ADS_FILTER_NOTEX))
items += animdata_filter_dopesheet_texs(ac, anim_data, ads, (ID *)wo, filter_mode);
}
}
/* nodetree */
if ((ntree && ntree->adt) && !(ads->filterflag & ADS_FILTER_NONTREE)) {
/* Action, Drivers, or NLA for Nodetree */
adt= ntree->adt;
ANIMDATA_FILTER_CASES(ntree,
{ /* AnimData blocks - do nothing... */ },
{ /* nla */
/* add NLA tracks */
items += animdata_filter_nla(ac, anim_data, ads, adt, filter_mode, (ID *)ntree);
},
{ /* drivers */
/* include nodetree-expand widget? */
if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
ale= make_new_animlistelem(ntree, ANIMTYPE_DSNTREE, (ID *)ntree);
if (ale) {
BLI_addtail(anim_data, ale);
items++;
}
}
/* add F-Curve channels (drivers are F-Curves) */
if (!(filter_mode & ANIMFILTER_LIST_VISIBLE) || FILTER_NTREE_SCED(ntree)/*EXPANDED_DRVD(adt)*/) {
// XXX owner info is messed up now...
items += animdata_filter_fcurves(anim_data, ads, adt->drivers.first, NULL, filter_mode, (ID *)ntree);
}
},
{ /* action */
/* include nodetree-expand widget? */
if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
ale= make_new_animlistelem(ntree, ANIMTYPE_DSNTREE, (ID *)sce);
if (ale) {
BLI_addtail(anim_data, ale);
items++;
}
}
/* add channels */
if (!(filter_mode & ANIMFILTER_LIST_VISIBLE) || FILTER_NTREE_SCED(ntree)) {
items += animdata_filter_action(ac, anim_data, ads, adt->action, filter_mode, (ID *)ntree);
}
}
)
/* now add the list of collected channels */
BLI_movelisttolist(anim_data, &tmp_data);
BLI_assert((tmp_data.first == tmp_data.last) && (tmp_data.first == NULL));
items += tmp_items;
}
/* return the number of items added to the list */
return items;
}
/* get animation channels from object2 */
static size_t animdata_filter_dopesheet_ob (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Base *base, int filter_mode)
{
ListBase tmp_data = {NULL, NULL};
Object *ob= base->object;
size_t tmp_items = 0;
size_t items = 0;
/* filter data contained under object first */
BEGIN_ANIMFILTER_SUBCHANNELS(EXPANDED_OBJC(ob))
{
Key *key= ob_get_key(ob);
/* object-level animation */
if ((ob->adt) && !(ads->filterflag & ADS_FILTER_NOOBJ)) {
tmp_items += animdata_filter_ds_obanim(ac, &tmp_data, ads, ob, filter_mode);
}
/* shape-key */
if ((key && key->adt) && !(ads->filterflag & ADS_FILTER_NOSHAPEKEYS)) {
tmp_items += animdata_filter_ds_keyanim(ac, &tmp_data, ads, ob, key, filter_mode);
}
/* materials */
if ((ob->totcol) && !(ads->filterflag & ADS_FILTER_NOMAT)) {
tmp_items += animdata_filter_ds_materials(ac, &tmp_data, ads, ob, filter_mode);
}
/* object data */
if (ob->data) {
tmp_items += animdata_filter_ds_obdata(ac, &tmp_data, ads, ob, filter_mode);
}
/* particles */
if ((ob->particlesystem.first) && !(ads->filterflag & ADS_FILTER_NOPART)) {
tmp_items += animdata_filter_ds_particles(ac, &tmp_data, ads, ob, filter_mode);
}
}
END_ANIMFILTER_SUBCHANNELS;
/* if we collected some channels, add these to the new list... */
if (tmp_items) {
/* firstly add object expander if required */
if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
/* check if filtering by selection */
// XXX: double-check on this - most of the time, a lot of tools need to filter out these channels!
if ANIMCHANNEL_SELOK((base->flag & SELECT)) {
/* check if filtering by active status */
if (ANIMCHANNEL_ACTIVEOK(ob)) {
ANIMCHANNEL_NEW_CHANNEL(base, ANIMTYPE_OBJECT, ob);
}
}
}
/* now add the list of collected channels */
BLI_movelisttolist(anim_data, &tmp_data);
BLI_assert((tmp_data.first == tmp_data.last) && (tmp_data.first == NULL));
items += tmp_items;
}
/* return the number of items added */
return items;
}
static size_t animdata_filter_ds_world (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Scene *sce, World *wo, int filter_mode)
{
ListBase tmp_data = {NULL, NULL};
size_t tmp_items = 0;
size_t items = 0;
/* add world animation channels */
BEGIN_ANIMFILTER_SUBCHANNELS(FILTER_WOR_SCED(wo))
{
/* animation data filtering */
tmp_items += animfilter_block_data(ac, &tmp_data, ads, (ID *)wo, filter_mode);
/* textures for world */
if (!(ads->filterflag & ADS_FILTER_NOTEX))
items += animdata_filter_ds_textures(ac, &tmp_data, ads, (ID *)wo, filter_mode);
}
END_ANIMFILTER_SUBCHANNELS;
/* did we find anything? */
if (tmp_items) {
/* include data-expand widget first */
if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
/* check if filtering by active status */
if ANIMCHANNEL_ACTIVEOK(wo) {
ANIMCHANNEL_NEW_CHANNEL(wo, ANIMTYPE_DSWOR, sce);
}
}
/* now add the list of collected channels */
BLI_movelisttolist(anim_data, &tmp_data);
BLI_assert((tmp_data.first == tmp_data.last) && (tmp_data.first == NULL));
items += tmp_items;
}
/* return the number of items added to the list */
return items;
}
static size_t animdata_filter_ds_scene (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Scene *sce, int filter_mode)
{
ListBase tmp_data = {NULL, NULL};
size_t tmp_items = 0;
size_t items = 0;
AnimData *adt = sce->adt;
short type=0, expanded=1;
void *cdata = NULL;
/* determine the type of expander channels to use */
// this is the best way to do this for now...
ANIMDATA_FILTER_CASES(sce,
{/* AnimData - no channel, but consider data */},
{/* NLA - no channel, but consider data */},
{/* Drivers */
type = ANIMTYPE_FILLDRIVERS;
cdata = adt;
expanded = EXPANDED_DRVD(adt);
},
{/* Keyframes */
type = ANIMTYPE_FILLACTD;
cdata = adt->action;
expanded = EXPANDED_ACTC(adt->action);
});
/* add scene-level animation channels */
BEGIN_ANIMFILTER_SUBCHANNELS(expanded)
{
/* animation data filtering */
tmp_items += animfilter_block_data(ac, &tmp_data, ads, (ID *)sce, filter_mode);
}
END_ANIMFILTER_SUBCHANNELS;
/* did we find anything? */
if (tmp_items) {
/* include anim-expand widget first */
if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
if (type != ANIMTYPE_NONE) {
/* NOTE: active-status (and the associated checks) don't apply here... */
ANIMCHANNEL_NEW_CHANNEL(cdata, type, sce);
}
}
/* now add the list of collected channels */
BLI_movelisttolist(anim_data, &tmp_data);
BLI_assert((tmp_data.first == tmp_data.last) && (tmp_data.first == NULL));
items += tmp_items;
}
/* return the number of items added to the list */
return items;
}
static size_t animdata_filter_dopesheet_scene (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Scene *sce, int filter_mode)
{
ListBase tmp_data = {NULL, NULL};
size_t tmp_items = 0;
size_t items = 0;
/* filter data contained under object first */
BEGIN_ANIMFILTER_SUBCHANNELS(EXPANDED_SCEC(sce))
{
bNodeTree *ntree= sce->nodetree;
World *wo= sce->world;
/* Action, Drivers, or NLA for Scene */
if ((ads->filterflag & ADS_FILTER_NOSCE) == 0) {
tmp_items += animdata_filter_ds_scene(ac, &tmp_data, ads, sce, filter_mode);
}
/* world */
if ((wo && wo->adt) && !(ads->filterflag & ADS_FILTER_NOWOR)) {
tmp_items += animdata_filter_ds_world(ac, &tmp_data, ads, sce, wo, filter_mode);
}
/* nodetree */
if ((ntree && ntree->adt) && !(ads->filterflag & ADS_FILTER_NONTREE)) {
tmp_items += animdata_filter_ds_nodetree(ac, &tmp_data, ads, (ID *)sce, ntree, filter_mode);
}
// TODO: one day, when sequencer becomes its own datatype, perhaps it should be included here
}
END_ANIMFILTER_SUBCHANNELS;
/* if we collected some channels, add these to the new list... */
if (tmp_items) {
/* firstly add object expander if required */
if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
/* check if filtering by selection */
if ANIMCHANNEL_SELOK((sce->flag & SCE_DS_SELECTED)) {
/* NOTE: active-status doesn't matter for this! */
ANIMCHANNEL_NEW_CHANNEL(sce, ANIMTYPE_SCENE, sce);
}
}
/* now add the list of collected channels */
BLI_movelisttolist(anim_data, &tmp_data);
BLI_assert((tmp_data.first == tmp_data.last) && (tmp_data.first == NULL));
items += tmp_items;
}
/* return the number of items added */
return items;
}
// TODO: implement pinning... (if and when pinning is done, what we need to do is to provide freeing mechanisms - to protect against data that was deleted)
static size_t animdata_filter_dopesheet (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, int filter_mode)
{
Scene *sce= (Scene *)ads->source;
Base *base;
bAnimListElem *ale;
size_t items = 0;
/* check that we do indeed have a scene */
@@ -1973,73 +1945,14 @@ static size_t animdata_filter_dopesheet (bAnimContext *ac, ListBase *anim_data,
filter_mode |= ANIMFILTER_SELEDIT;
}
/* scene-linked animation */
// TODO: sequencer, composite nodes - are we to include those here too?
{
short sceOk= 0, worOk= 0, nodeOk=0;
/* 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);)
}
if (sce->nodetree) {
ANIMDATA_FILTER_CASES(sce->nodetree,
{
/* 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->nodetree);
nodeOk=0;
},
nodeOk= !(ads->filterflag & ADS_FILTER_NONTREE);,
nodeOk= !(ads->filterflag & ADS_FILTER_NONTREE);,
nodeOk= !(ads->filterflag & ADS_FILTER_NONTREE);)
}
/* if only F-Curves with visible flags set can be shown, check that
* datablocks haven't been set to invisible
*/
if (filter_mode & ANIMFILTER_CURVE_VISIBLE) {
if ((sce->adt) && (sce->adt->flag & ADT_CURVES_NOT_VISIBLE))
sceOk= worOk= nodeOk= 0;
}
/* check if not all bad (i.e. so there is something to show) */
if ( !(!sceOk && !worOk && !nodeOk) ) {
/* add scene data to the list of filtered channels */
items += animdata_filter_dopesheet_scene(ac, anim_data, ads, sce, filter_mode);
}
}
/* scene-linked animation - e.g. world, compositing nodes, scene anim (including sequencer currently) */
items += animdata_filter_dopesheet_scene(ac, anim_data, ads, sce, filter_mode);
/* loop over all bases in the scene */
/* loop over all bases (i.e.objects) in the scene */
for (base= sce->base.first; base; base= base->next) {
/* check if there's an object (all the relevant checks are done in the ob-function) */
if (base->object) {
Object *ob= base->object;
Key *key= ob_get_key(ob);
short actOk=1, keyOk=1, dataOk=1, matOk=1, partOk=1;
/* firstly, check if object can be included, by the following factors:
* - if only visible, must check for layer and also viewport visibility
@@ -2047,7 +1960,8 @@ static size_t animdata_filter_dopesheet (bAnimContext *ac, ListBase *anim_data,
* as user option controls whether sets of channels get included while
* tool-flag takes into account collapsed/open channels too
* - if only selected, must check if object is selected
* - there must be animation data to edit
* - there must be animation data to edit (this is done recursively as we
* try to add the channels)
*/
if ((filter_mode & ANIMFILTER_DATA_VISIBLE) && !(ads->filterflag & ADS_FILTER_INCL_HIDDEN)) {
/* layer visibility - we check both object and base, since these may not be in sync yet */
@@ -2065,275 +1979,21 @@ static size_t animdata_filter_dopesheet (bAnimContext *ac, ListBase *anim_data,
continue;
}
/* additionally, dopesheet filtering also affects what objects to consider */
{
/* check selection and object type filters */
if ( (ads->filterflag & ADS_FILTER_ONLYSEL) && !((base->flag & SELECT) /*|| (base == sce->basact)*/) ) {
/* only selected should be shown */
continue;
}
/* check if object belongs to the filtering group if option to filter
* objects by the grouped status is on
* - used to ease the process of doing multiple-character choreographies
*/
if (ads->filterflag & ADS_FILTER_ONLYOBGROUP) {
if (object_in_group(ob, ads->filter_grp) == 0)
continue;
}
/* check filters for datatypes */
/* object */
actOk= 0;
if (!(ads->filterflag & ADS_FILTER_NOOBJ)) {
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;)
}
keyOk= 0;
if ((key) && !(ads->filterflag & ADS_FILTER_NOSHAPEKEYS)) {
/* 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;)
}
/* materials - only for geometric types */
matOk= 0; /* by default, not ok... */
if ( !(ads->filterflag & ADS_FILTER_NOMAT) && (ob->totcol) &&
ELEM5(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL) )
{
int a;
/* firstly check that we actuallly have some materials */
for (a=1; a <= ob->totcol; a++) {
Material *ma= give_current_material(ob, a);
if (ma) {
/* 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;)
if (matOk)
break;
/* textures? */
// TODO: make this a macro that is used in the other checks too
// NOTE: this has little use on its own, since the actual filtering still ignores if no anim on the data
if (!(ads->filterflag & ADS_FILTER_NOTEX)) {
int mtInd;
for (mtInd= 0; mtInd < MAX_MTEX; mtInd++) {
MTex *mtex= ma->mtex[mtInd];
if (mtex && mtex->tex) {
/* if texture has relevant animation data, break */
ANIMDATA_FILTER_CASES(mtex->tex,
{
/* 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(mtex->tex);
matOk=0;
},
matOk= 1;,
matOk= 1;,
matOk= 1;)
if (matOk)
break;
}
}
}
}
}
}
/* data */
switch (ob->type) {
case OB_CAMERA: /* ------- Camera ------------ */
{
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);)
}
break;
case OB_LAMP: /* ---------- Lamp ----------- */
{
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 ---------- */
case OB_SURF: /* ------- Nurbs Surface ---------- */
case OB_FONT: /* ------- Text 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;
case OB_MBALL: /* ------- MetaBall ---------- */
{
MetaBall *mb= (MetaBall *)ob->data;
dataOk= 0;
ANIMDATA_FILTER_CASES(mb,
if ((ads->filterflag & ADS_FILTER_NOMBA)==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(mb);
dataOk=0;
},
dataOk= !(ads->filterflag & ADS_FILTER_NOMBA);,
dataOk= !(ads->filterflag & ADS_FILTER_NOMBA);,
dataOk= !(ads->filterflag & ADS_FILTER_NOMBA);)
}
break;
case OB_ARMATURE: /* ------- Armature ---------- */
{
bArmature *arm= (bArmature *)ob->data;
dataOk= 0;
ANIMDATA_FILTER_CASES(arm,
if ((ads->filterflag & ADS_FILTER_NOARM)==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(arm);
dataOk=0;
},
dataOk= !(ads->filterflag & ADS_FILTER_NOARM);,
dataOk= !(ads->filterflag & ADS_FILTER_NOARM);,
dataOk= !(ads->filterflag & ADS_FILTER_NOARM);)
}
break;
case OB_MESH: /* ------- Mesh ---------- */
{
Mesh *me= (Mesh *)ob->data;
dataOk= 0;
ANIMDATA_FILTER_CASES(me,
if ((ads->filterflag & ADS_FILTER_NOMESH)==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(me);
dataOk=0;
},
dataOk= !(ads->filterflag & ADS_FILTER_NOMESH);,
dataOk= !(ads->filterflag & ADS_FILTER_NOMESH);,
dataOk= !(ads->filterflag & ADS_FILTER_NOMESH);)
}
break;
case OB_LATTICE: /* ------- Lattice ---------- */
{
Lattice *lt= (Lattice *)ob->data;
dataOk= 0;
ANIMDATA_FILTER_CASES(lt,
if ((ads->filterflag & ADS_FILTER_NOLAT)==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(lt);
dataOk=0;
},
dataOk= !(ads->filterflag & ADS_FILTER_NOLAT);,
dataOk= !(ads->filterflag & ADS_FILTER_NOLAT);,
dataOk= !(ads->filterflag & ADS_FILTER_NOLAT);)
}
break;
default: /* --- other --- */
dataOk= 0;
break;
}
/* particles */
partOk = 0;
if (!(ads->filterflag & ADS_FILTER_NOPART) && ob->particlesystem.first) {
ParticleSystem *psys = ob->particlesystem.first;
for(; psys; psys=psys->next) {
if (psys->part) {
/* if particlesettings has relevant animation data, break */
ANIMDATA_FILTER_CASES(psys->part,
{
/* 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(psys->part);
partOk=0;
},
partOk= 1;,
partOk= 1;,
partOk= 1;)
}
if (partOk)
break;
}
}
/* check if all bad (i.e. nothing to show) */
if (!actOk && !keyOk && !dataOk && !matOk && !partOk)
continue;
/* check selection and object type filters */
if ( (ads->filterflag & ADS_FILTER_ONLYSEL) && !((base->flag & SELECT) /*|| (base == sce->basact)*/) ) {
/* only selected should be shown */
continue;
}
/* check if object belongs to the filtering group if option to filter
* objects by the grouped status is on
* - used to ease the process of doing multiple-character choreographies
*/
if (ads->filterflag & ADS_FILTER_ONLYOBGROUP) {
if (object_in_group(ob, ads->filter_grp) == 0)
continue;
}
/* since we're still here, this object should be usable */
items += animdata_filter_dopesheet_ob(ac, anim_data, ads, base, filter_mode);
}

View File

@@ -184,7 +184,6 @@ typedef enum eAnim_KeyType {
/* ----------------- Filtering -------------------- */
/* filtering flags - under what circumstances should a channel be returned */
// TODO: flag to just test if there's any channel inside worthy of being added - return 1 as soon as this is encountered, but don't add
typedef enum eAnimFilter_Flags {
/* data which channel represents is fits the dopesheet filters (i.e. scene visibility criteria) */
// XXX: it's hard to think of any examples where this *ISN'T* the case... perhaps becomes implicit?
@@ -216,7 +215,10 @@ typedef enum eAnimFilter_Flags {
ANIMFILTER_ANIMDATA = (1<<10),
/* duplicate entries for animation data attached to multi-user blocks must not occur */
ANIMFILTER_NODUPLIS = (1<<11)
ANIMFILTER_NODUPLIS = (1<<11),
/* for checking if we should keep some collapsed channel around (internal use only!) */
ANIMFILTER_TMP_PEEK = (1<<30)
} eAnimFilter_Flags;
/* ---------- Flag Checking Macros ------------ */