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:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 ------------ */
|
||||
|
||||
Reference in New Issue
Block a user