2.5 - Animation Editors - Filtering API
authorJoshua Leung <aligorith@gmail.com>
Sun, 21 Dec 2008 04:11:19 +0000 (04:11 +0000)
committerJoshua Leung <aligorith@gmail.com>
Sun, 21 Dec 2008 04:11:19 +0000 (04:11 +0000)
Brought back the Filtering API for Animation Editors. This is the 'backbone' of the current Action/Dopesheet Editor code, so it is essential to have this working.

source/blender/editors/animation/anim_filter.c
source/blender/editors/animation/anim_keyframing.c
source/blender/editors/include/ED_anim_api.h
source/blender/editors/include/ED_keyframing.h

index edd89ac7f2f84f9cd9a3d6d352465d1844aee31b..19dafc439dc07458488c9c56f9672f823b229884 100644 (file)
  * ***** END GPL LICENSE BLOCK *****
  */
 
-/* This file defines the system for filtering data into a form suitable for
- * use by the Animation Editors, thus acting as a means by which the Animation 
- * Editors maintain a level of abstraction from the data they actually manipulate.
- * Thus, they only need to check on the type of the data they're manipulating, and
- * NOT worry about various layers of context/hierarchy checks.
+/* This file contains a system used to provide a layer of abstraction between sources
+ * of animation data and tools in Animation Editors. The method used here involves 
+ * generating a list of edit structures which enable tools to naively perform the actions 
+ * they require without all the boiler-plate associated with loops within loops and checking 
+ * for cases to ignore. 
  *
  * While this is primarily used for the Action/Dopesheet Editor (and its accessory modes),
  * the IPO Editor also uses this for it's channel list and for determining which curves
  * are being edited.
  *
+ * Note: much of the original system this was based on was built before the creation of the RNA
+ * system. In future, it would be interesting to replace some parts of this code with RNA queries,
+ * however, RNA does not eliminate some of the boiler-plate reduction benefits presented by this 
+ * system, so if any such work does occur, it should only be used for the internals used here...
+ *
  * -- Joshua Leung, Dec 2008
  */
 
 #include "DNA_listBase.h"
 #include "DNA_ID.h"
 #include "DNA_action_types.h"
+#include "DNA_constraint_types.h"
 #include "DNA_camera_types.h"
 #include "DNA_curve_types.h"
+#include "DNA_gpencil_types.h"
 #include "DNA_ipo_types.h"
+#include "DNA_lamp_types.h"
 #include "DNA_lattice_types.h"
 #include "DNA_key_types.h"
+#include "DNA_material_types.h"
 #include "DNA_mesh_types.h"
 #include "DNA_object_types.h"
 #include "DNA_space_types.h"
@@ -63,6 +72,9 @@
 
 #include "BKE_context.h"
 #include "BKE_global.h"
+#include "BKE_key.h"
+#include "BKE_object.h"
+#include "BKE_material.h"
 #include "BKE_screen.h"
 #include "BKE_utildefines.h"
 
@@ -97,7 +109,7 @@ Key *actedit_get_shapekeys (const bContext *C, SpaceAction *saction)
     if (ob == NULL) 
                return NULL;
        
-       /* pinning is not available in 'ShapeKey' mode... */
+       /* XXX pinning is not available in 'ShapeKey' mode... */
        //if (saction->pin) return NULL;
        
        /* shapekey data is stored with geometry data */
@@ -215,6 +227,958 @@ void *ANIM_animdata_get_context (const bContext *C, short *datatype)
 
 /* ----------- 'Private' Stuff --------------- */
 
+/* this function allocates memory for a new bAnimListElem struct for the 
+ * provided animation channel-data. 
+ */
+bAnimListElem *make_new_animlistelem (void *data, short datatype, void *owner, short ownertype)
+{
+       bAnimListElem *ale= NULL;
+       
+       /* only allocate memory if there is data to convert */
+       if (data) {
+               /* allocate and set generic data */
+               ale= MEM_callocN(sizeof(bAnimListElem), "bAnimListElem");
+               
+               ale->data= data;
+               ale->type= datatype;
+               ale->owner= owner;
+               ale->ownertype= ownertype;
+               
+               if ((owner) && (ownertype == ANIMTYPE_ACHAN)) {
+                       bActionChannel *ochan= (bActionChannel *)owner;
+                       ale->grp= ochan->grp;
+               }
+               else 
+                       ale->grp= NULL;
+               
+               /* do specifics */
+               switch (datatype) {
+                       case ANIMTYPE_OBJECT:
+                       {
+                               Base *base= (Base *)data;
+                               Object *ob= base->object;
+                               
+                               ale->flag= ob->flag;
+                               
+                               ale->key_data= ob;
+                               ale->datatype= ALE_OB;
+                       }
+                               break;
+                       case ANIMTYPE_FILLACTD:
+                       {
+                               bAction *act= (bAction *)data;
+                               
+                               ale->flag= act->flag;
+                               
+                               ale->key_data= act;
+                               ale->datatype= ALE_ACT;
+                       }
+                               break;
+                       case ANIMTYPE_FILLIPOD:
+                       {
+                               Object *ob= (Object *)data;
+                               
+                               ale->flag= FILTER_IPO_OBJC(ob);
+                               
+                               ale->key_data= ob->ipo;
+                               ale->datatype= ALE_IPO;
+                       }
+                               break;
+                       case ANIMTYPE_FILLCOND:
+                       {
+                               Object *ob= (Object *)data;
+                               
+                               ale->flag= FILTER_CON_OBJC(ob);
+                               
+                               ale->key_data= NULL;
+                               ale->datatype= ALE_NONE;
+                       }
+                               break;
+                       case ANIMTYPE_FILLMATD:
+                       {
+                               Object *ob= (Object *)data;
+                               
+                               ale->flag= FILTER_MAT_OBJC(ob);
+                               
+                               ale->key_data= NULL;
+                               ale->datatype= ALE_NONE;
+                       }
+                               break;
+                       
+                       case ANIMTYPE_DSMAT:
+                       {
+                               Material *ma= (Material *)data;
+                               
+                               ale->flag= FILTER_MAT_OBJD(ma);
+                               
+                               ale->key_data= ma->ipo;
+                               ale->datatype= ALE_IPO;
+                       }
+                               break;
+                       case ANIMTYPE_DSLAM:
+                       {
+                               Lamp *la= (Lamp *)data;
+                               
+                               ale->flag= FILTER_LAM_OBJD(la);
+                               
+                               ale->key_data= la->ipo;
+                               ale->datatype= ALE_IPO;
+                       }
+                               break;
+                       case ANIMTYPE_DSCAM:
+                       {
+                               Camera *ca= (Camera *)data;
+                               
+                               ale->flag= FILTER_CAM_OBJD(ca);
+                               
+                               ale->key_data= ca->ipo;
+                               ale->datatype= ALE_IPO;
+                       }
+                               break;
+                       case ANIMTYPE_DSCUR:
+                       {
+                               Curve *cu= (Curve *)data;
+                               
+                               ale->flag= FILTER_CUR_OBJD(cu);
+                               
+                               ale->key_data= cu->ipo;
+                               ale->datatype= ALE_IPO;
+                       }
+                               break;
+                       case ANIMTYPE_DSSKEY:
+                       {
+                               Key *key= (Key *)data;
+                               
+                               ale->flag= FILTER_SKE_OBJD(key);
+                               
+                               ale->key_data= key->ipo;
+                               ale->datatype= ALE_IPO;
+                       }
+                               break;
+                               
+                       case ANIMTYPE_GROUP:
+                       {
+                               bActionGroup *agrp= (bActionGroup *)data;
+                               
+                               ale->flag= agrp->flag;
+                               
+                               ale->key_data= NULL;
+                               ale->datatype= ALE_GROUP;
+                       }
+                               break;
+                       case ANIMTYPE_ACHAN:
+                       {
+                               bActionChannel *achan= (bActionChannel *)data;
+                               
+                               ale->flag= achan->flag;
+                               
+                               if (achan->ipo) {
+                                       ale->key_data= achan->ipo;
+                                       ale->datatype= ALE_IPO;
+                               }
+                               else {
+                                       ale->key_data= NULL;
+                                       ale->datatype= ALE_NONE;
+                               }
+                       }       
+                               break;
+                       case ANIMTYPE_CONCHAN:
+                       case ANIMTYPE_CONCHAN2:
+                       {
+                               bConstraintChannel *conchan= (bConstraintChannel *)data;
+                               
+                               ale->flag= conchan->flag;
+                               
+                               if (datatype == ANIMTYPE_CONCHAN2) {
+                                       /* CONCHAN2 is a hack so that constraint-channels keyframes can be edited */
+                                       if (conchan->ipo) {
+                                               ale->key_data= conchan->ipo;
+                                               ale->datatype= ALE_IPO;
+                                       }
+                                       else {
+                                               ale->key_data= NULL;
+                                               ale->datatype= ALE_NONE;
+                                       }
+                               }
+                               else {
+                                       if ((conchan->ipo) && (conchan->ipo->curve.first)) {
+                                               /* we assume that constraint ipo blocks only have 1 curve:
+                                                * INFLUENCE, so we pretend that a constraint channel is 
+                                                * really just a Ipo-Curve channel instead.
+                                                */
+                                               ale->key_data= conchan->ipo->curve.first;
+                                               ale->datatype= ALE_ICU;
+                                       }
+                                       else {
+                                               ale->key_data= NULL;
+                                               ale->datatype= ALE_NONE;
+                                       }
+                               }
+                       }
+                               break;
+                       case ANIMTYPE_ICU:
+                       {
+                               IpoCurve *icu= (IpoCurve *)data;
+                               
+                               ale->flag= icu->flag;
+                               ale->key_data= icu;
+                               ale->datatype= ALE_ICU;
+                       }
+                               break;
+                       case ANIMTYPE_FILLIPO:
+                       case ANIMTYPE_FILLCON:
+                       {
+                               bActionChannel *achan= (bActionChannel *)data;
+                               
+                               if (datatype == ANIMTYPE_FILLIPO)
+                                       ale->flag= FILTER_IPO_ACHAN(achan);
+                               else
+                                       ale->flag= FILTER_CON_ACHAN(achan);
+                                       
+                               ale->key_data= NULL;
+                               ale->datatype= ALE_NONE;
+                       }
+                               break;
+                       case ANIMTYPE_IPO:
+                       {
+                               ale->flag= 0;
+                               ale->key_data= data;
+                               ale->datatype= ALE_IPO;
+                       }
+                               break;
+                       
+                       case ANIMTYPE_GPLAYER:
+                       {
+                               bGPDlayer *gpl= (bGPDlayer *)data;
+                               
+                               ale->flag= gpl->flag;
+                               
+                               ale->key_data= NULL;
+                               ale->datatype= ALE_GPFRAME;
+                       }
+                               break;
+               }
+       }
+       
+       /* return created datatype */
+       return ale;
+}
+/* ----------------------------------------- */
+
+static void animdata_filter_animionchannel (ListBase *anim_data, bActionChannel *achan, int filter_mode, void *owner, short ownertype)
+{
+       bAnimListElem *ale = NULL;
+       bConstraintChannel *conchan;
+       IpoCurve *icu;
+       short owned= (owner && ownertype)? 1 : 0;
+       
+       /* only work with this channel and its subchannels if it is visible */
+       if (!(filter_mode & ANIMFILTER_VISIBLE) || VISIBLE_ACHAN(achan)) {
+               /* only work with this channel and its subchannels if it is editable */
+               if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_ACHAN(achan)) {
+                       /* check if this achan should only be included if it is selected */
+                       if (!(filter_mode & ANIMFILTER_SEL) || SEL_ACHAN(achan)) {
+                               /* are we only interested in the ipo-curves? */
+                               if ((filter_mode & ANIMFILTER_ONLYICU)==0) {
+                                       ale= make_new_animlistelem(achan, ANIMTYPE_ACHAN, achan, ANIMTYPE_ACHAN);
+                                       
+                                       if (ale) {
+                                               if (owned) ale->id= owner;
+                                               BLI_addtail(anim_data, ale);
+                                       }
+                               }
+                       }
+                       else {
+                               /* for insert key... this check could be improved */
+                               return;
+                       }
+                       
+                       /* check if expanded - if not, continue on to next animion channel */
+                       if (EXPANDED_ACHAN(achan) == 0 && (filter_mode & ANIMFILTER_ONLYICU)==0) {
+                               /* only exit if we don't need to include constraint channels for group-channel keyframes */
+                               if ( !(filter_mode & ANIMFILTER_IPOKEYS) || (achan->grp == NULL) || (EXPANDED_AGRP(achan->grp)==0) )
+                                       return;
+                       }
+                               
+                       /* ipo channels */
+                       if ((achan->ipo) && (filter_mode & ANIMFILTER_IPOKEYS)==0) {
+                               /* include ipo-expand widget? */
+                               if ((filter_mode & ANIMFILTER_CHANNELS) && (filter_mode & ANIMFILTER_ONLYICU)==0) {
+                                       ale= make_new_animlistelem(achan, ANIMTYPE_FILLIPO, achan, ANIMTYPE_ACHAN);
+                                       
+                                       if (ale) {
+                                               if (owned) ale->id= owner;
+                                               BLI_addtail(anim_data, ale);
+                                       }
+                               }
+                               
+                               /* add ipo-curve channels? */
+                               if (FILTER_IPO_ACHAN(achan) || (filter_mode & ANIMFILTER_ONLYICU)) {
+                                       /* loop through ipo-curve channels, adding them */
+                                       for (icu= achan->ipo->curve.first; icu; icu=icu->next) {
+                                               ale= make_new_animlistelem(icu, ANIMTYPE_ICU, achan, ANIMTYPE_ACHAN);
+                                               
+                                               if (ale) {
+                                                       if (owned) ale->id= owner;
+                                                       BLI_addtail(anim_data, ale); 
+                                               }
+                                       }
+                               }
+                       }
+                       
+                       /* constraint channels */
+                       if (achan->constraintChannels.first) {
+                               /* include constraint-expand widget? */
+                               if ( (filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_ONLYICU)
+                                        && !(filter_mode & ANIMFILTER_IPOKEYS) ) 
+                               {
+                                       ale= make_new_animlistelem(achan, ANIMTYPE_FILLCON, achan, ANIMTYPE_ACHAN);
+                                       
+                                       if (ale) {
+                                               if (owned) ale->id= owner;
+                                               BLI_addtail(anim_data, ale);
+                                       }
+                               }
+                               
+                               /* add constraint channels? */
+                               if (FILTER_CON_ACHAN(achan) || (filter_mode & ANIMFILTER_IPOKEYS) || (filter_mode & ANIMFILTER_ONLYICU)) {
+                                       /* loop through constraint channels, checking and adding them */
+                                       for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) {
+                                               /* only work with this channel and its subchannels if it is editable */
+                                               if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_CONCHAN(conchan)) {
+                                                       /* check if this conchan should only be included if it is selected */
+                                                       if (!(filter_mode & ANIMFILTER_SEL) || SEL_CONCHAN(conchan)) {
+                                                               if (filter_mode & ANIMFILTER_IPOKEYS) {
+                                                                       if (ale) BLI_addtail(anim_data, ale);
+                                                                       ale= make_new_animlistelem(conchan, ANIMTYPE_CONCHAN2, achan, ANIMTYPE_ACHAN);
+                                                                       
+                                                                       if (ale) {
+                                                                               if (owned) ale->id= owner;
+                                                                               BLI_addtail(anim_data, ale);
+                                                                       }
+                                                               }
+                                                               else {
+                                                                       ale= make_new_animlistelem(conchan, ANIMTYPE_CONCHAN, achan, ANIMTYPE_ACHAN);
+                                                                       
+                                                                       if (ale) {
+                                                                               if (owned) ale->id= owner;
+                                                                               BLI_addtail(anim_data, ale);
+                                                                       }
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }               
+       }
+}
+
+static void animdata_filter_action (ListBase *anim_data, bAction *act, int filter_mode, void *owner, short ownertype)
+{
+       bAnimListElem *ale=NULL;
+       bActionGroup *agrp;
+       bActionChannel *achan, *lastchan=NULL;
+       short owned= (owner && ownertype) ? 1 : 0;
+       
+       /* loop over groups */
+       for (agrp= act->groups.first; agrp; agrp= agrp->next) {
+               /* add this group as a channel first */
+               if (!(filter_mode & ANIMFILTER_ONLYICU) && !(filter_mode & ANIMFILTER_IPOKEYS)) {
+                       /* check if filtering by selection */
+                       if ( !(filter_mode & ANIMFILTER_SEL) || SEL_AGRP(agrp) ) {
+                               ale= make_new_animlistelem(agrp, ANIMTYPE_GROUP, NULL, ANIMTYPE_NONE);
+                               if (ale) {
+                                       if (owned) ale->id= owner;
+                                       BLI_addtail(anim_data, ale);
+                               }
+                       }
+               }
+               
+               /* store reference to last channel of group */
+               if (agrp->channels.last) 
+                       lastchan= agrp->channels.last;
+               
+               
+               /* there are some situations, where only the channels of the animive group should get considered */
+               if (!(filter_mode & ANIMFILTER_ACTGROUPED) || (agrp->flag & AGRP_ACTIVE)) {
+                       /* filters here are a bit convoulted...
+                        *      - groups show a "summary" of keyframes beside their name which must accessable for tools which handle keyframes
+                        *      - groups can be collapsed (and those tools which are only interested in channels rely on knowing that group is closed)
+                        *
+                        * cases when we should include animion-channels and so-forth inside group:
+                        *      - we don't care about visibility
+                        *      - group is expanded
+                        *      - we're interested in keyframes, but not if they appear in selected channels
+                        */
+                       if ( (!(filter_mode & ANIMFILTER_VISIBLE) || EXPANDED_AGRP(agrp)) || 
+                                ( ((filter_mode & ANIMFILTER_IPOKEYS) || (filter_mode & ANIMFILTER_ONLYICU)) && 
+                                  (!(filter_mode & ANIMFILTER_SEL) || (SEL_AGRP(agrp))) ) ) 
+                       {
+                               if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_AGRP(agrp)) {                                       
+                                       for (achan= agrp->channels.first; achan && achan->grp==agrp; achan= achan->next) {
+                                               animdata_filter_animionchannel(anim_data, achan, filter_mode, owner, ownertype);
+                                       }
+                                       
+                                       /* remove group from filtered list if last element is group 
+                                        * (i.e. only if group had channels, which were all hidden)
+                                        */
+                                       // XXX this is really hacky... it should be fixed in a much more elegant way!
+                                       if ( (ale) && (anim_data->last == ale) && 
+                                                (ale->data == agrp) && (agrp->channels.first) ) 
+                                       {
+                                               BLI_freelinkN(anim_data, ale);
+                                       }
+                               }
+                       }
+               }
+       }
+       
+       /* loop over un-grouped animion channels (only if we're not only considering those channels in the animive group) */
+       if (!(filter_mode & ANIMFILTER_ACTGROUPED))  {
+               for (achan=(lastchan)?lastchan->next:act->chanbase.first; achan; achan=achan->next) {
+                       animdata_filter_animionchannel(anim_data, achan, filter_mode, owner, ownertype);
+               }
+       }
+}
+
+static void animdata_filter_shapekey (ListBase *anim_data, Key *key, int filter_mode, void *owner, short ownertype)
+{
+       bAnimListElem *ale;
+       KeyBlock *kb;
+       IpoCurve *icu;
+       short owned= (owner && ownertype)? 1 : 0;
+       int i;
+       
+       /* are we filtering for display or editing */
+       if (filter_mode & ANIMFILTER_FORDRAWING) {
+               /* for display - loop over shapekeys, adding ipo-curve references where needed */
+               kb= key->block.first;
+               
+               /* loop through possible shapekeys, manually creating entries */
+               for (i= 1; i < key->totkey; i++) {
+                       ale= MEM_callocN(sizeof(bAnimListElem), "bAnimListElem");
+                       kb = kb->next; /* do this even on the first try, as the first is 'Basis' (which doesn't get included) */
+                       
+                       ale->data= kb;
+                       ale->type= ANIMTYPE_SHAPEKEY; /* 'abused' usage of this type */
+                       ale->owner= key;
+                       ale->ownertype= ANIMTYPE_SHAPEKEY;
+                       ale->datatype= ALE_NONE;
+                       ale->index = i;
+                       
+                       if (key->ipo) {
+                               for (icu= key->ipo->curve.first; icu; icu=icu->next) {
+                                       if (icu->adrcode == i) {
+                                               ale->key_data= icu;
+                                               ale->datatype= ALE_ICU;
+                                               break;
+                                       }
+                               }
+                       }
+                       
+                       if (owned) ale->id= owner;
+                       
+                       BLI_addtail(anim_data, ale);
+               }
+       }
+       else {
+               /* loop over ipo curves if present - for editing */
+               if (key->ipo) {
+                       if (filter_mode & ANIMFILTER_IPOKEYS) {
+                               ale= make_new_animlistelem(key->ipo, ANIMTYPE_IPO, key, ANIMTYPE_SHAPEKEY);
+                               if (ale) {
+                                       if (owned) ale->id= owner;
+                                       BLI_addtail(anim_data, ale);
+                               }
+                       }
+                       else {
+                               for (icu= key->ipo->curve.first; icu; icu=icu->next) {
+                                       ale= make_new_animlistelem(icu, ANIMTYPE_ICU, key, ANIMTYPE_SHAPEKEY);
+                                       if (ale) {
+                                               if (owned) ale->id= owner;
+                                               BLI_addtail(anim_data, ale);
+                                       }
+                               }
+                       }
+               }
+       }
+}
+#if 0
+// FIXME: switch this to use the bDopeSheet...
+static void animdata_filter_gpencil (ListBase *anim_data, bScreen *sc, int filter_mode)
+{
+       bAnimListElem *ale;
+       ScrArea *sa, *curarea;
+       bGPdata *gpd;
+       bGPDlayer *gpl;
+       
+       /* check if filtering types are appropriate */
+       if ( !(filter_mode & (ANIMFILTER_IPOKEYS|ANIMFILTER_ONLYICU|ANIMFILTER_ACTGROUPED)) ) 
+       {
+               /* special hack for fullscreen area (which must be this one then):
+                *      - we use the curarea->full as screen to get spaces from, since the
+                *        old (pre-fullscreen) screen was stored there...
+                *      - this is needed as all data would otherwise disappear
+                */
+               // XXX need to get new alternative for curarea
+               if ((curarea->full) && (curarea->spacetype==SPACE_ACTION))
+                       sc= curarea->full;
+               
+               /* loop over spaces in current screen, finding gpd blocks (could be slow!) */
+               for (sa= sc->areabase.first; sa; sa= sa->next) {
+                       /* try to get gp data */
+                       // XXX need to put back grease pencil api...
+                       gpd= gpencil_data_getactive(sa);
+                       if (gpd == NULL) continue;
+                       
+                       /* add gpd as channel too (if for drawing, and it has layers) */
+                       if ((filter_mode & ANIMFILTER_FORDRAWING) && (gpd->layers.first)) {
+                               /* add to list */
+                               ale= make_new_animlistelem(gpd, ANIMTYPE_GPDATABLOCK, sa, ANIMTYPE_SPECIALDATA);
+                               if (ale) BLI_addtail(anim_data, ale);
+                       }
+                       
+                       /* only add layers if they will be visible (if drawing channels) */
+                       if ( !(filter_mode & ANIMFILTER_VISIBLE) || (EXPANDED_GPD(gpd)) ) {
+                               /* loop over layers as the conditions are acceptable */
+                               for (gpl= gpd->layers.first; gpl; gpl= gpl->next) {
+                                       /* only if selected */
+                                       if (!(filter_mode & ANIMFILTER_SEL) || SEL_GPL(gpl)) {
+                                               /* only if editable */
+                                               if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_GPL(gpl)) {
+                                                       /* add to list */
+                                                       ale= make_new_animlistelem(gpl, ANIMTYPE_GPLAYER, gpd, ANIMTYPE_GPDATABLOCK);
+                                                       if (ale) BLI_addtail(anim_data, ale);
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+}
+#endif 
+
+static void animdata_filter_dopesheet_mats (ListBase *anim_data, bDopeSheet *ads, Base *base, int filter_mode)
+{
+       bAnimListElem *ale=NULL;
+       Object *ob= base->object;
+       IpoCurve *icu;
+       
+       /* include materials-expand widget? */
+       if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & (ANIMFILTER_IPOKEYS|ANIMFILTER_ONLYICU))) {
+               ale= make_new_animlistelem(ob, ANIMTYPE_FILLMATD, base, ANIMTYPE_OBJECT);
+               if (ale) BLI_addtail(anim_data, ale);
+       }
+       
+       /* add materials? */
+       if (FILTER_MAT_OBJC(ob) || (filter_mode & ANIMFILTER_IPOKEYS) || (filter_mode & ANIMFILTER_ONLYICU)) {
+               short a;
+               
+               /* for each material, either add channels separately, or as ipo-block */
+               for (a=0; a<ob->totcol; a++) {
+                       Material *ma= give_current_material(ob, a);
+                       
+                       /* for now, if no material returned, skip (this shouldn't confuse the user I hope) */
+                       if (ELEM(NULL, ma, ma->ipo)) continue;
+                       
+                       /* include material-expand widget? */
+                       // hmm... do we need to store the index of this material in the array anywhere?
+                       if (filter_mode & (ANIMFILTER_CHANNELS|ANIMFILTER_IPOKEYS)) {
+                               ale= make_new_animlistelem(ma, ANIMTYPE_DSMAT, base, ANIMTYPE_OBJECT);
+                               if (ale) BLI_addtail(anim_data, ale);
+                       }
+                       
+                       /* add material's ipo-curve channels? */
+                       if ( (FILTER_MAT_OBJD(ma) || (filter_mode & ANIMFILTER_ONLYICU)) && 
+                                 !(filter_mode & ANIMFILTER_IPOKEYS) ) 
+                       {
+                               /* loop through ipo-curve channels, adding them */
+                               for (icu= ma->ipo->curve.first; icu; icu=icu->next) {
+                                       /* only if selected (if checking for selection) */
+                                       if ( !(filter_mode & ANIMFILTER_SEL) || (SEL_ICU(icu)) ) {
+                                               ale= make_new_animlistelem(icu, ANIMTYPE_ICU, base, ANIMTYPE_OBJECT);
+                                               if (ale) {
+                                                       /* make owner the material not object, so that indent is not just object level */
+                                                       ale->id= (ID *)ma;
+                                                       BLI_addtail(anim_data, ale);
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+}
+
+static void animdata_filter_dopesheet_cam (ListBase *anim_data, bDopeSheet *ads, Base *base, int filter_mode)
+{
+       bAnimListElem *ale=NULL;
+       Object *ob= base->object;
+       Camera *ca= (Camera *)ob->data;
+       IpoCurve *icu;
+       
+       /* include camera-expand widget? */
+       if (filter_mode & (ANIMFILTER_CHANNELS|ANIMFILTER_IPOKEYS)) {
+               ale= make_new_animlistelem(ca, ANIMTYPE_DSCAM, base, ANIMTYPE_OBJECT);
+               if (ale) BLI_addtail(anim_data, ale);
+       }
+       
+       /* add camera ipo-curve channels? */
+       if ( (FILTER_CAM_OBJD(ca) || (filter_mode & ANIMFILTER_ONLYICU)) && 
+                 !(filter_mode & ANIMFILTER_IPOKEYS) ) 
+       {
+               /* loop through ipo-curve channels, adding them */
+               for (icu= ca->ipo->curve.first; icu; icu=icu->next) {
+                       /* only if selected (if checking for selection) */
+                       if ( !(filter_mode & ANIMFILTER_SEL) || (SEL_ICU(icu)) ) {
+                               ale= make_new_animlistelem(icu, ANIMTYPE_ICU, base, ANIMTYPE_OBJECT);
+                               if (ale) {
+                                       /* make owner the material not object, so that indent is not just object level */
+                                       ale->id= (ID *)ca;
+                                       BLI_addtail(anim_data, ale); 
+                               }
+                       }
+               }
+       }
+}
+
+static void animdata_filter_dopesheet_lamp (ListBase *anim_data, bDopeSheet *ads, Base *base, int filter_mode)
+{
+       bAnimListElem *ale=NULL;
+       Object *ob= base->object;
+       Lamp *la= (Lamp *)ob->data;
+       IpoCurve *icu;
+       
+       /* include lamp-expand widget? */
+       if (filter_mode & (ANIMFILTER_CHANNELS|ANIMFILTER_IPOKEYS)) {
+               ale= make_new_animlistelem(la, ANIMTYPE_DSLAM, base, ANIMTYPE_OBJECT);
+               if (ale) BLI_addtail(anim_data, ale);
+       }
+       
+       /* add lamp ipo-curve channels? */
+       if ( (FILTER_LAM_OBJD(la) || (filter_mode & ANIMFILTER_ONLYICU)) && 
+                 !(filter_mode & ANIMFILTER_IPOKEYS) ) 
+       {
+               /* loop through ipo-curve channels, adding them */
+               for (icu= la->ipo->curve.first; icu; icu=icu->next) {
+                       /* only if selected (if checking for selection) */
+                       if ( !(filter_mode & ANIMFILTER_SEL) || (SEL_ICU(icu)) ) {
+                               ale= make_new_animlistelem(icu, ANIMTYPE_ICU, base, ANIMTYPE_OBJECT);
+                               if (ale) {
+                                       /* make owner the material not object, so that indent is not just object level */
+                                       ale->id= (ID *)la;
+                                       BLI_addtail(anim_data, ale); 
+                               }
+                       }
+               }
+       }
+}
+
+static void animdata_filter_dopesheet_curve (ListBase *anim_data, bDopeSheet *ads, Base *base, int filter_mode)
+{
+       bAnimListElem *ale=NULL;
+       Object *ob= base->object;
+       Curve *cu= (Curve *)ob->data;
+       IpoCurve *icu;
+       
+       /* include curve-expand widget? */
+       if (filter_mode & (ANIMFILTER_CHANNELS|ANIMFILTER_IPOKEYS)) {
+               ale= make_new_animlistelem(cu, ANIMTYPE_DSCUR, base, ANIMTYPE_OBJECT);
+               if (ale) BLI_addtail(anim_data, ale);
+       }
+       
+       /* add curve ipo-curve channels? */
+       if ( (FILTER_CUR_OBJD(cu) || (filter_mode & ANIMFILTER_ONLYICU)) && 
+                 !(filter_mode & ANIMFILTER_IPOKEYS) ) 
+       {
+               /* loop through ipo-curve channels, adding them */
+               for (icu= cu->ipo->curve.first; icu; icu=icu->next) {
+                       /* only if selected (if checking for selection) */
+                       if ( !(filter_mode & ANIMFILTER_SEL) || (SEL_ICU(icu)) ) {
+                               ale= make_new_animlistelem(icu, ANIMTYPE_ICU, base, ANIMTYPE_OBJECT);
+                               if (ale) {
+                                       /* make owner the material not object, so that indent is not just object level */
+                                       ale->id= (ID *)cu;
+                                       BLI_addtail(anim_data, ale); 
+                               }
+                       }
+               }
+       }
+}
+
+static void animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, Base *base, int filter_mode)
+{
+       bAnimListElem *ale=NULL;
+       Scene *sce= (Scene *)ads->source;
+       Object *ob= base->object;
+       Key *key= ob_get_key(ob);
+       IpoCurve *icu;
+       
+       /* add this object as a channel first */
+       if (!(filter_mode & ANIMFILTER_ONLYICU) && !(filter_mode & ANIMFILTER_IPOKEYS)) {
+               /* check if filtering by selection */
+               if ( !(filter_mode & ANIMFILTER_SEL) || ((base->flag & SELECT) || (base == sce->basact)) ) {
+                       ale= make_new_animlistelem(base, ANIMTYPE_OBJECT, NULL, ANIMTYPE_NONE);
+                       if (ale) BLI_addtail(anim_data, ale);
+               }
+       }
+       
+       /* if collapsed, don't go any further (unless adding keyframes only) */
+       if ( (EXPANDED_OBJC(ob) == 0) && !(filter_mode & (ANIMFILTER_IPOKEYS|ANIMFILTER_ONLYICU)) )
+               return;
+       
+       /* IPO? */
+       if ((ob->ipo) && !(ads->filterflag & ADS_FILTER_NOIPOS)) {              
+               /* include ipo-expand widget? */
+               if (filter_mode & (ANIMFILTER_CHANNELS|ANIMFILTER_IPOKEYS)) {
+                       ale= make_new_animlistelem(ob, ANIMTYPE_FILLIPOD, base, ANIMTYPE_OBJECT);
+                       if (ale) BLI_addtail(anim_data, ale);
+               }
+               
+               /* add ipo-curve channels? */
+               if ( (FILTER_IPO_OBJC(ob) || (filter_mode & ANIMFILTER_ONLYICU)) && 
+                         !(filter_mode & ANIMFILTER_IPOKEYS) ) 
+               {
+                       /* loop through ipo-curve channels, adding them */
+                       for (icu= ob->ipo->curve.first; icu; icu=icu->next) {
+                               /* only if selected (if checking for selection) */
+                               if ( !(filter_mode & ANIMFILTER_SEL) || (SEL_ICU(icu)) ) {
+                                       ale= make_new_animlistelem(icu, ANIMTYPE_ICU, base, ANIMTYPE_OBJECT);
+                                       if (ale) BLI_addtail(anim_data, ale); 
+                               }
+                       }
+               }
+       }
+       
+       /* Action? */
+       if ((ob->action) && !(ads->filterflag & ADS_FILTER_NOACTS)) {
+               /* include animion-expand widget? */
+               if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & (ANIMFILTER_IPOKEYS|ANIMFILTER_ONLYICU))) {
+                       ale= make_new_animlistelem(ob->action, ANIMTYPE_FILLACTD, base, ANIMTYPE_OBJECT);
+                       if (ale) {
+                               ale->id= (ID *)ob; // err.... is this a good idea?
+                               BLI_addtail(anim_data, ale);
+                       }
+               }
+               
+               /* add ipo-curve channels? */
+               if (EXPANDED_ACTC(ob->action) || !(filter_mode & (ANIMFILTER_CHANNELS|ANIMFILTER_FORDRAWING))) {
+                       // need to make the ownertype normal object here... (maybe type should be a separate one for clarity?)
+                       animdata_filter_action(anim_data, ob->action, filter_mode, ob, ANIMTYPE_OBJECT); 
+               }
+       }
+       
+       /* ShapeKeys? */
+       if ((key) && !(ads->filterflag & ADS_FILTER_NOSHAPEKEYS)) {
+               /* include shapekey-expand widget? */
+               if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & (ANIMFILTER_IPOKEYS|ANIMFILTER_ONLYICU))) {
+                       ale= make_new_animlistelem(key, ANIMTYPE_DSSKEY, base, ANIMTYPE_OBJECT);
+                       if (ale) BLI_addtail(anim_data, ale);
+               }
+               
+               /* add channels */
+               if (FILTER_SKE_OBJD(key) || (filter_mode & ANIMFILTER_IPOKEYS) || (filter_mode & ANIMFILTER_ONLYICU)) {
+                       animdata_filter_shapekey (anim_data, key, filter_mode, ob, ANIMTYPE_OBJECT);
+               }
+       }
+       
+       /* Materials? */
+       if ((ob->totcol) && !(ads->filterflag & ADS_FILTER_NOMAT))
+               animdata_filter_dopesheet_mats(anim_data, ads, base, filter_mode);
+       
+       /* Object Data */
+       switch (ob->type) {
+               case OB_CAMERA: /* ------- Camera ------------ */
+               {
+                       Camera *ca= (Camera *)ob->data;
+                       if ((ca->ipo) && !(ads->filterflag & ADS_FILTER_NOCAM))
+                               animdata_filter_dopesheet_cam(anim_data, ads, base, filter_mode);
+               }
+                       break;
+               case OB_LAMP: /* ---------- Lamp ----------- */
+               {
+                       Lamp *la= (Lamp *)ob->data;
+                       if ((la->ipo) && !(ads->filterflag & ADS_FILTER_NOLAM))
+                               animdata_filter_dopesheet_lamp(anim_data, ads, base, filter_mode);
+               }
+                       break;
+               case OB_CURVE: /* ------- Curve ---------- */
+               {
+                       Curve *cu= (Curve *)ob->data;
+                       if ((cu->ipo) && !(ads->filterflag & ADS_FILTER_NOCUR))
+                               animdata_filter_dopesheet_curve(anim_data, ads, base, filter_mode);
+               }
+                       break;
+       }
+       
+       /* Constraint Channels? */
+       if ((ob->constraintChannels.first) && !(ads->filterflag & ADS_FILTER_NOCONSTRAINTS)) {
+               bConstraintChannel *conchan;
+               
+               /* include constraint-expand widget? */
+               if ( (filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_ONLYICU)
+                        && !(filter_mode & ANIMFILTER_IPOKEYS) ) 
+               {
+                       ale= make_new_animlistelem(ob, ANIMTYPE_FILLCOND, base, ANIMTYPE_OBJECT);
+                       if (ale) BLI_addtail(anim_data, ale);
+               }
+               
+               /* add constraint channels? */
+               if (FILTER_CON_OBJC(ob) || (filter_mode & ANIMFILTER_IPOKEYS) || (filter_mode & ANIMFILTER_ONLYICU)) {
+                       /* loop through constraint channels, checking and adding them */
+                       for (conchan=ob->constraintChannels.first; conchan; conchan=conchan->next) {
+                               /* only work with this channel and its subchannels if it is editable */
+                               if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_CONCHAN(conchan)) {
+                                       /* check if this conchan should only be included if it is selected */
+                                       if (!(filter_mode & ANIMFILTER_SEL) || SEL_CONCHAN(conchan)) {
+                                               if (filter_mode & ANIMFILTER_IPOKEYS) {
+                                                       ale= make_new_animlistelem(conchan, ANIMTYPE_CONCHAN2, base, ANIMTYPE_OBJECT);
+                                                       if (ale) {
+                                                               ale->id= (ID *)ob;
+                                                               BLI_addtail(anim_data, ale);
+                                                       }
+                                               }
+                                               else {
+                                                       ale= make_new_animlistelem(conchan, ANIMTYPE_CONCHAN, base, ANIMTYPE_OBJECT);
+                                                       if (ale) {
+                                                               ale->id= (ID *)ob;
+                                                               BLI_addtail(anim_data, ale);
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+}      
+
+// 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 void animdata_filter_dopesheet (ListBase *anim_data, bDopeSheet *ads, int filter_mode)
+{
+       Scene *sce= (Scene *)ads->source;
+       Base *base;
+       
+       /* check that we do indeed have a scene */
+       if ((ads->source == NULL) || (GS(ads->source->name)!=ID_SCE)) {
+               printf("DopeSheet Error: Not scene! \n");
+               return;
+       }
+       
+       /* loop over all bases 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 ipoOk, actOk, constsOk, keyOk, dataOk;
+                       
+                       /* firstly, check if object can be included, by the following fanimors:
+                        *      - if only visible, must check for layer and also viewport visibility
+                        *      - if only selected, must check if object is selected 
+                        *      - there must be animation data to edit
+                        */
+                       // TODO: if cache is implemented, just check name here, and then 
+                       if (filter_mode & ANIMFILTER_VISIBLE) {
+                               /* layer visibility */
+                               if ((ob->lay & sce->lay)==0) continue;
+                               
+                               /* outliner restrict-flag */
+                               if (ob->restrictflag & OB_RESTRICT_VIEW) continue;
+                       }
+                       
+                       /* additionally, dopesheet filtering also affects what objects to consider */
+                       if (ads->filterflag) {
+                               /* check selection and object type filters */
+                               if ( (ads->filterflag & ADS_FILTER_ONLYSEL) && !((base->flag & SELECT) || (base == sce->basact)) )  {
+                                       /* only selected should be shown */
+                                       continue;
+                               }
+                               if ((ads->filterflag & ADS_FILTER_NOARM) && (ob->type == OB_ARMATURE)) {
+                                       /* not showing armatures  */
+                                       continue;
+                               }
+                               if ((ads->filterflag & ADS_FILTER_NOOBJ) && (ob->type != OB_ARMATURE)) {
+                                       /* not showing objects that aren't armatures */
+                                       continue;
+                               }
+                               
+                               /* check filters for datatypes */
+                               ipoOk= ((ob->ipo) && !(ads->filterflag & ADS_FILTER_NOIPOS));
+                               actOk= ((ob->action) && !(ads->filterflag & ADS_FILTER_NOACTS));
+                               constsOk= ((ob->constraintChannels.first) && !(ads->filterflag & ADS_FILTER_NOCONSTRAINTS));
+                               keyOk= ((key) && !(ads->filterflag & ADS_FILTER_NOSHAPEKEYS));
+                               
+                               switch (ob->type) {
+                                       case OB_CAMERA: /* ------- Camera ------------ */
+                                       {
+                                               Camera *ca= (Camera *)ob->data;
+                                               dataOk= ((ca->ipo) && !(ads->filterflag & ADS_FILTER_NOCAM));                                           
+                                       }
+                                               break;
+                                       case OB_LAMP: /* ---------- Lamp ----------- */
+                                       {
+                                               Lamp *la= (Lamp *)ob->data;
+                                               dataOk= ((la->ipo) && !(ads->filterflag & ADS_FILTER_NOLAM));
+                                       }
+                                               break;
+                                       case OB_CURVE: /* -------- Curve ---------- */
+                                       {
+                                               Curve *cu= (Curve *)ob->data;
+                                               dataOk= ((cu->ipo) && !(ads->filterflag & ADS_FILTER_NOCUR));
+                                       }
+                                               break;
+                                       default: /* --- other --- */
+                                               dataOk= 0;
+                                               break;
+                               }
+                               
+                               /* check if all bad (i.e. nothing to show) */
+                               if (!ipoOk && !actOk && !constsOk && !keyOk && !dataOk)
+                                       continue;
+                       }
+                       else {
+                               /* check data-types */
+                               ipoOk= (ob->ipo != NULL);
+                               actOk= (ob->action != NULL);
+                               constsOk= (ob->constraintChannels.first != NULL);
+                               keyOk= (key != NULL);
+                               
+                               switch (ob->type) {
+                                       case OB_CAMERA: /* ------- Camera ------------ */
+                                       {
+                                               Camera *ca= (Camera *)ob->data;
+                                               dataOk= (ca->ipo != NULL);                                              
+                                       }
+                                               break;
+                                       case OB_LAMP: /* ---------- Lamp ----------- */
+                                       {
+                                               Lamp *la= (Lamp *)ob->data;
+                                               dataOk= (la->ipo != NULL);
+                                       }
+                                               break;
+                                       case OB_CURVE: /* -------- Curve ---------- */
+                                       {
+                                               Curve *cu= (Curve *)ob->data;
+                                               dataOk= (cu->ipo != NULL);
+                                       }
+                                               break;
+                                       default: /* --- other --- */
+                                               dataOk= 0;
+                                               break;
+                               }
+                               
+                               /* check if all bad (i.e. nothing to show) */
+                               if (!ipoOk && !actOk && !constsOk && !keyOk && !dataOk)
+                                       continue;
+                       }
+                       
+                       /* since we're still here, this object should be usable */
+                       animdata_filter_dopesheet_ob(anim_data, ads, base, filter_mode);
+               }
+       }
+}
 
 /* ----------- Public API --------------- */
 
@@ -233,16 +1197,16 @@ void ANIM_animdata_filter (ListBase *anim_data, int filter_mode, void *data, sho
                /* firstly filter the data */
                switch (datatype) {
                        case ANIMCONT_ACTION:
-                               //animdata_filter_action(anim_data, data, filter_mode, NULL, ANIMTYPE_NONE);
+                               animdata_filter_action(anim_data, data, filter_mode, NULL, ANIMTYPE_NONE);
                                break;
                        case ANIMCONT_SHAPEKEY:
-                               //animdata_filter_shapekey(anim_data, data, filter_mode, NULL, ANIMTYPE_NONE);
+                               animdata_filter_shapekey(anim_data, data, filter_mode, NULL, ANIMTYPE_NONE);
                                break;
                        case ANIMCONT_GPENCIL:
                                //animdata_filter_gpencil(anim_data, data, filter_mode);
                                break;
                        case ANIMCONT_DOPESHEET:
-                               //animdata_filter_dopesheet(anim_data, data, filter_mode);
+                               animdata_filter_dopesheet(anim_data, data, filter_mode);
                                break;
                }
                        
@@ -254,7 +1218,7 @@ void ANIM_animdata_filter (ListBase *anim_data, int filter_mode, void *data, sho
                        if (ale->type == ANIMTYPE_NONE)
                                BLI_freelinkN(anim_data, ale);
                        
-                       if (filter_mode & ALEFILTER_IPOKEYS) {
+                       if (filter_mode & ANIMFILTER_IPOKEYS) {
                                if (ale->datatype != ALE_IPO)
                                        BLI_freelinkN(anim_data, ale);
                                else if (ale->key_data == NULL)
index 3e303a2d26c5f4c248122131f7c3ce1066fd1dec..51dc04fa4078c5f321fcab90baadae829e662a63 100644 (file)
@@ -2100,7 +2100,7 @@ short ipo_frame_has_keyframe (Ipo *ipo, float frame, short filter)
                return 0;
                
        /* if only check non-muted, check if muted */
-       if ((filter & ANIMFILTER_MUTED) || (ipo->muteipo))
+       if ((filter & ANIMFILTER_KEYS_MUTED) || (ipo->muteipo))
                return 0;
        
        /* loop over IPO-curves, using binary-search to try to find matches 
@@ -2110,7 +2110,7 @@ short ipo_frame_has_keyframe (Ipo *ipo, float frame, short filter)
                /* only check if there are keyframes (currently only of type BezTriple) */
                if (icu->bezt) {
                        /* we either include all regardless of muting, or only non-muted  */
-                       if ((filter & ANIMFILTER_MUTED) || (icu->flag & IPO_MUTE)==0) {
+                       if ((filter & ANIMFILTER_KEYS_MUTED) || (icu->flag & IPO_MUTE)==0) {
                                short replace = -1;
                                int i = binarysearch_bezt_index(icu->bezt, frame, icu->totvert, &replace);
                                
@@ -2146,7 +2146,7 @@ short action_frame_has_keyframe (bAction *act, float frame, short filter)
                /* we either include all regardless of muting, or only non-muted 
                 *      - here we include 'hidden' channels in the muted definition
                 */
-               if ((filter & ANIMFILTER_MUTED) || (achan->flag & ACHAN_HIDDEN)==0) {
+               if ((filter & ANIMFILTER_KEYS_MUTED) || (achan->flag & ACHAN_HIDDEN)==0) {
                        if (ipo_frame_has_keyframe(achan->ipo, frame, filter))
                                return 1;
                }
@@ -2176,7 +2176,7 @@ short object_frame_has_keyframe (Object *ob, float frame, short filter)
                /* priority check here goes to pose-channel checks (for armatures) */
                if ((ob->pose) && (ob->flag & OB_POSEMODE)) {
                        /* only relevant check here is to only show active... */
-                       if (filter & ANIMFILTER_ACTIVE) {
+                       if (filter & ANIMFILTER_KEYS_ACTIVE) {
                                bPoseChannel *pchan= get_active_posechannel(ob);
                                bActionChannel *achan= (pchan) ? get_action_channel(ob->action, pchan->name) : NULL;
                                
@@ -2196,7 +2196,7 @@ short object_frame_has_keyframe (Object *ob, float frame, short filter)
        }
        
        /* try shapekey keyframes (if available, and allowed by filter) */
-       if ( !(filter & ANIMFILTER_LOCAL) && !(filter & ANIMFILTER_NOSKEY) ) {
+       if ( !(filter & ANIMFILTER_KEYS_LOCAL) && !(filter & ANIMFILTER_KEYS_NOSKEY) ) {
                Key *key= ob_get_key(ob);
                
                /* shapekeys can have keyframes ('Relative Shape Keys') 
@@ -2212,9 +2212,9 @@ short object_frame_has_keyframe (Object *ob, float frame, short filter)
        }
        
        /* try materials */
-       if ( !(filter & ANIMFILTER_LOCAL) && !(filter & ANIMFILTER_NOMAT) ) {
+       if ( !(filter & ANIMFILTER_KEYS_LOCAL) && !(filter & ANIMFILTER_KEYS_NOMAT) ) {
                /* if only active, then we can skip a lot of looping */
-               if (filter & ANIMFILTER_ACTIVE) {
+               if (filter & ANIMFILTER_KEYS_ACTIVE) {
                        Material *ma= give_current_material(ob, (ob->actcol + 1));
                        
                        /* we only retrieve the active material... */
index 2a5082e2094a1f16760a7d3fdbca995b0fc56bcf..a2786b5ed1ce8b713084c1f43cddaea28d5c60fd 100644 (file)
@@ -122,17 +122,63 @@ typedef enum eAnimCont_Types {
 /* filtering flags  - under what circumstances should a channel be added */
 // XXX was ACTFILTER_*
 typedef enum eAnimFilter_Flags {
-       ALEFILTER_VISIBLE               = (1<<0),       /* should channels be visible */
-       ALEFILTER_SEL                   = (1<<1),       /* should channels be selected */
-       ALEFILTER_FOREDIT               = (1<<2),       /* does editable status matter */
-       ALEFILTER_CHANNELS              = (1<<3),       /* do we only care that it is a channel */
-       ALEFILTER_IPOKEYS               = (1<<4),       /* only channels referencing ipo's */
-       ALEFILTER_ONLYICU               = (1<<5),       /* only reference ipo-curves */
-       ALEFILTER_FORDRAWING    = (1<<6),       /* make list for interface drawing */
-       ALEFILTER_ACTGROUPED    = (1<<7),       /* belongs to the active actiongroup */
+       ANIMFILTER_VISIBLE              = (1<<0),       /* should channels be visible */
+       ANIMFILTER_SEL                  = (1<<1),       /* should channels be selected */
+       ANIMFILTER_FOREDIT              = (1<<2),       /* does editable status matter */
+       ANIMFILTER_CHANNELS             = (1<<3),       /* do we only care that it is a channel */
+       ANIMFILTER_IPOKEYS              = (1<<4),       /* only channels referencing ipo's */
+       ANIMFILTER_ONLYICU              = (1<<5),       /* only reference ipo-curves */
+       ANIMFILTER_FORDRAWING   = (1<<6),       /* make list for interface drawing */
+       ANIMFILTER_ACTGROUPED   = (1<<7),       /* belongs to the active actiongroup */
 } eAnimFilter_Flags;
 
 
+/* ---------- Flag Checking Macros ------------ */
+
+/* Dopesheet only */
+       /* 'Object' channels */
+#define SEL_OBJC(base) ((base->flag & SELECT))
+#define EXPANDED_OBJC(ob) ((ob->nlaflag & OB_ADS_COLLAPSED)==0)
+       /* 'Sub-object' channels (flags stored in Object block) */
+#define FILTER_IPO_OBJC(ob) ((ob->nlaflag & OB_ADS_SHOWIPO))
+#define FILTER_CON_OBJC(ob) ((ob->nlaflag & OB_ADS_SHOWCONS)) 
+#define FILTER_MAT_OBJC(ob) ((ob->nlaflag & OB_ADS_SHOWMATS))
+       /* 'Sub-object' channels (flags stored in Data block) */
+#define FILTER_SKE_OBJD(key) ((key->flag & KEYBLOCK_DS_EXPAND))
+#define FILTER_MAT_OBJD(ma) ((ma->flag & MA_DS_EXPAND))
+#define FILTER_LAM_OBJD(la) ((la->flag & LA_DS_EXPAND))
+#define FILTER_CAM_OBJD(ca) ((ca->flag & CAM_DS_EXPAND))
+#define FILTER_CUR_OBJD(cu) ((cu->flag & CU_DS_EXPAND))
+       /* 'Sub-object/Action' channels (flags stored in Action) */
+#define SEL_ACTC(actc) ((actc->flag & ACTC_SELECTED))
+#define EXPANDED_ACTC(actc) ((actc->flag & ACTC_EXPANDED))
+
+/* Actions (also used for Dopesheet) */
+       /* Action Channel Group */
+#define EDITABLE_AGRP(agrp) ((agrp->flag & AGRP_PROTECTED)==0)
+#define EXPANDED_AGRP(agrp) (agrp->flag & AGRP_EXPANDED)
+#define SEL_AGRP(agrp) ((agrp->flag & AGRP_SELECTED) || (agrp->flag & AGRP_ACTIVE))
+       /* Action Channel Settings */
+#define VISIBLE_ACHAN(achan) ((achan->flag & ACHAN_HIDDEN)==0)
+#define EDITABLE_ACHAN(achan) ((VISIBLE_ACHAN(achan)) && ((achan->flag & ACHAN_PROTECTED)==0))
+#define EXPANDED_ACHAN(achan) ((VISIBLE_ACHAN(achan)) && (achan->flag & ACHAN_EXPANDED))
+#define SEL_ACHAN(achan) ((achan->flag & ACHAN_SELECTED) || (achan->flag & ACHAN_HILIGHTED))
+#define FILTER_IPO_ACHAN(achan) ((achan->flag & ACHAN_SHOWIPO))
+#define FILTER_CON_ACHAN(achan) ((achan->flag & ACHAN_SHOWCONS))
+       /* Constraint Channel Settings */
+#define EDITABLE_CONCHAN(conchan) ((conchan->flag & CONSTRAINT_CHANNEL_PROTECTED)==0)
+#define SEL_CONCHAN(conchan) (conchan->flag & CONSTRAINT_CHANNEL_SELECT)
+       /* IPO Curve Channels */
+#define EDITABLE_ICU(icu) ((icu->flag & IPO_PROTECT)==0)
+#define SEL_ICU(icu) (icu->flag & IPO_SELECT)
+
+/* Grease Pencil only */
+       /* Grease Pencil datablock settings */
+#define EXPANDED_GPD(gpd) (gpd->flag & GP_DATA_EXPAND) 
+       /* Grease Pencil Layer settings */
+#define EDITABLE_GPL(gpl) ((gpl->flag & GP_LAYER_LOCKED)==0)
+#define SEL_GPL(gpl) ((gpl->flag & GP_LAYER_ACTIVE) || (gpl->flag & GP_LAYER_SELECT))
+
 /* ---------------- API  -------------------- */
 
 /* Obtain list of filtered Animation channels to operate on */
index 29d19cd18e3b7f68954dd9f477b1fbd0ba356412..f4be3f06c6bd5efc2299fecc0313d00abf616c7e 100644 (file)
@@ -122,13 +122,13 @@ short id_frame_has_keyframe(struct ID *id, float frame, short filter);
  */
 enum {
                /* general */
-       ANIMFILTER_LOCAL        = (1<<0),               /* only include locally available anim data */
-       ANIMFILTER_MUTED        = (1<<1),               /* include muted elements */
-       ANIMFILTER_ACTIVE       = (1<<2),               /* only include active-subelements */
+       ANIMFILTER_KEYS_LOCAL   = (1<<0),               /* only include locally available anim data */
+       ANIMFILTER_KEYS_MUTED   = (1<<1),               /* include muted elements */
+       ANIMFILTER_KEYS_ACTIVE  = (1<<2),               /* only include active-subelements */
        
                /* object specific */
-       ANIMFILTER_NOMAT                = (1<<9),               /* don't include material keyframes */
-       ANIMFILTER_NOSKEY               = (1<<10),              /* don't include shape keys (for geometry) */
+       ANIMFILTER_KEYS_NOMAT           = (1<<9),               /* don't include material keyframes */
+       ANIMFILTER_KEYS_NOSKEY          = (1<<10),              /* don't include shape keys (for geometry) */
 } eAnimFilterFlags;
 
 #endif /*  BIF_KEYFRAMING_H */