Merge with -r 22620:23107.
[blender.git] / source / blender / editors / animation / anim_filter.c
index b47211f35d14f1143cdb5ffc6509e981646fe0bf..55fb1ccace05006e7535040a369fa36b51ddcc30 100644 (file)
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  *
- * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * The Original Code is Copyright (C) 2008 Blender Foundation, Joshua Leung
  * All rights reserved.
  *
  * 
- * Contributor(s): Joshua Leung
+ * Contributor(s): Joshua Leung (original author)
  *
  * ***** END GPL LICENSE BLOCK *****
  */
  * 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.
+ * the Graph Editor also uses this for its channel list and for determining which curves
+ * are being edited. Likewise, the NLA Editor also uses this for its channel list and in
+ * its operators.
  *
  * 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
+ * -- Joshua Leung, Dec 2008 (Last revision July 2009)
  */
 
 #include <string.h>
@@ -61,7 +62,9 @@
 #include "DNA_key_types.h"
 #include "DNA_material_types.h"
 #include "DNA_mesh_types.h"
+#include "DNA_meta_types.h"
 #include "DNA_object_types.h"
+#include "DNA_particle_types.h"
 #include "DNA_space_types.h"
 #include "DNA_scene_types.h"
 #include "DNA_screen_types.h"
@@ -72,6 +75,7 @@
 
 #include "BLI_blenlib.h"
 
+#include "BKE_animsys.h"
 #include "BKE_context.h"
 #include "BKE_global.h"
 #include "BKE_key.h"
@@ -204,6 +208,12 @@ static short graphedit_get_context (bAnimContext *ac, SpaceIpo *sipo)
        if (sipo->ads == NULL)
                sipo->ads= MEM_callocN(sizeof(bDopeSheet), "GraphEdit DopeSheet");
        
+       /* set settings for Graph Editor - "Selected = Editable" */
+       if (sipo->flag & SIPO_SELCUVERTSONLY)
+               sipo->ads->filterflag |= ADS_FILTER_SELEDIT;
+       else
+               sipo->ads->filterflag &= ~ADS_FILTER_SELEDIT;
+       
        /* sync settings with current view status, then return appropriate data */
        switch (sipo->mode) {
                case SIPO_MODE_ANIMATION:       /* Animation F-Curve Editor */
@@ -364,27 +374,29 @@ short ANIM_animdata_get_context (const bContext *C, bAnimContext *ac)
  */
 #define ANIMDATA_FILTER_CASES(id, adtOk, nlaOk, driversOk, keysOk) \
        {\
-               if (filter_mode & ANIMFILTER_ANIMDATA) {\
-                       if ((id)->adt) {\
-                               adtOk\
-                       }\
-               }\
-               else if (ads->filterflag & ADS_FILTER_ONLYNLA) {\
-                       if (ANIMDATA_HAS_NLA(id)) {\
-                               nlaOk\
-                       }\
-                       else if (!(ads->filterflag & ADS_FILTER_NLA_NOACT) && ANIMDATA_HAS_KEYS(id)) {\
-                               nlaOk\
-                       }\
-               }\
-               else if (ads->filterflag & ADS_FILTER_ONLYDRIVERS) {\
-                       if (ANIMDATA_HAS_DRIVERS(id)) {\
-                               driversOk\
-                       }\
-               }\
-               else {\
-                       if (ANIMDATA_HAS_KEYS(id)) {\
-                               keysOk\
+               if ((id)->adt) {\
+                       if (!(filter_mode & ANIMFILTER_CURVEVISIBLE) || !((id)->adt->flag & ADT_CURVES_NOT_VISIBLE)) {\
+                               if (filter_mode & ANIMFILTER_ANIMDATA) {\
+                                       adtOk\
+                               }\
+                               else if (ads->filterflag & ADS_FILTER_ONLYNLA) {\
+                                       if (ANIMDATA_HAS_NLA(id)) {\
+                                               nlaOk\
+                                       }\
+                                       else if (!(ads->filterflag & ADS_FILTER_NLA_NOACT) && ANIMDATA_HAS_KEYS(id)) {\
+                                               nlaOk\
+                                       }\
+                               }\
+                               else if (ads->filterflag & ADS_FILTER_ONLYDRIVERS) {\
+                                       if (ANIMDATA_HAS_DRIVERS(id)) {\
+                                               driversOk\
+                                       }\
+                               }\
+                               else {\
+                                       if (ANIMDATA_HAS_KEYS(id)) {\
+                                               keysOk\
+                                       }\
+                               }\
                        }\
                }\
        }
@@ -402,11 +414,20 @@ short ANIM_animdata_get_context (const bContext *C, bAnimContext *ac)
        
 
 
-/* quick macro to test if a anim-channel (F-Curve, Group, etc.) is selected in an acceptable way */
+/* quick macro to test if an anim-channel (F-Curve, Group, etc.) is selected in an acceptable way */
 #define ANIMCHANNEL_SELOK(test_func) \
                ( !(filter_mode & (ANIMFILTER_SEL|ANIMFILTER_UNSEL)) || \
                  ((filter_mode & ANIMFILTER_SEL) && test_func) || \
                  ((filter_mode & ANIMFILTER_UNSEL) && test_func==0) ) 
+                 
+/* quick macro to test if an anim-channel (F-Curve) is selected ok for editing purposes 
+ *     - _SELEDIT means that only selected curves will have visible+editable keyframes
+ */
+// FIXME: this doesn't work cleanly yet...
+#define ANIMCHANNEL_SELEDITOK(test_func) \
+               ( !(filter_mode & ANIMFILTER_SELEDIT) || \
+                 (filter_mode & ANIMFILTER_CHANNELS) || \
+                 (test_func) )
 
 /* ----------- 'Private' Stuff --------------- */
 
@@ -429,6 +450,7 @@ bAnimListElem *make_new_animlistelem (void *data, short datatype, void *owner, s
                ale->ownertype= ownertype;
                
                ale->id= owner_id;
+               ale->adt= BKE_animdata_from_id(owner_id);
                
                /* do specifics */
                switch (datatype) {
@@ -440,6 +462,8 @@ bAnimListElem *make_new_animlistelem (void *data, short datatype, void *owner, s
                                
                                ale->key_data= sce;
                                ale->datatype= ALE_SCE;
+                               
+                               ale->adt= BKE_animdata_from_id(data);
                        }
                                break;
                        case ANIMTYPE_OBJECT:
@@ -451,6 +475,8 @@ bAnimListElem *make_new_animlistelem (void *data, short datatype, void *owner, s
                                
                                ale->key_data= ob;
                                ale->datatype= ALE_OB;
+                               
+                               ale->adt= BKE_animdata_from_id(&ob->id);
                        }
                                break;
                        case ANIMTYPE_FILLACTD:
@@ -480,6 +506,16 @@ bAnimListElem *make_new_animlistelem (void *data, short datatype, void *owner, s
                                
                                ale->flag= FILTER_MAT_OBJC(ob);
                                
+                               ale->key_data= NULL;
+                               ale->datatype= ALE_NONE;
+                       }
+                               break;
+                       case ANIMTYPE_FILLPARTD:
+                       {
+                               Object *ob= (Object *)data;
+                               
+                               ale->flag= FILTER_PART_OBJC(ob);
+                               
                                ale->key_data= NULL;
                                ale->datatype= ALE_NONE;
                        }
@@ -494,6 +530,8 @@ bAnimListElem *make_new_animlistelem (void *data, short datatype, void *owner, s
                                
                                ale->key_data= (adt) ? adt->action : NULL;
                                ale->datatype= ALE_ACT;
+                               
+                               ale->adt= BKE_animdata_from_id(data);
                        }
                                break;
                        case ANIMTYPE_DSLAM:
@@ -505,6 +543,8 @@ bAnimListElem *make_new_animlistelem (void *data, short datatype, void *owner, s
                                
                                ale->key_data= (adt) ? adt->action : NULL;
                                ale->datatype= ALE_ACT;
+                               
+                               ale->adt= BKE_animdata_from_id(data);
                        }
                                break;
                        case ANIMTYPE_DSCAM:
@@ -516,6 +556,8 @@ bAnimListElem *make_new_animlistelem (void *data, short datatype, void *owner, s
                                
                                ale->key_data= (adt) ? adt->action : NULL;
                                ale->datatype= ALE_ACT;
+                               
+                               ale->adt= BKE_animdata_from_id(data);
                        }
                                break;
                        case ANIMTYPE_DSCUR:
@@ -527,6 +569,8 @@ bAnimListElem *make_new_animlistelem (void *data, short datatype, void *owner, s
                                
                                ale->key_data= (adt) ? adt->action : NULL;
                                ale->datatype= ALE_ACT;
+                               
+                               ale->adt= BKE_animdata_from_id(data);
                        }
                                break;
                        case ANIMTYPE_DSSKEY:
@@ -538,6 +582,8 @@ bAnimListElem *make_new_animlistelem (void *data, short datatype, void *owner, s
                                
                                ale->key_data= (adt) ? adt->action : NULL;
                                ale->datatype= ALE_ACT;
+                               
+                               ale->adt= BKE_animdata_from_id(data);
                        }
                                break;
                        case ANIMTYPE_DSWOR:
@@ -549,6 +595,21 @@ bAnimListElem *make_new_animlistelem (void *data, short datatype, void *owner, s
                                
                                ale->key_data= (adt) ? adt->action : NULL;
                                ale->datatype= ALE_ACT;
+                               
+                               ale->adt= BKE_animdata_from_id(data);
+                       }
+                               break;
+                       case ANIMTYPE_DSPART:
+                       {
+                               ParticleSettings *part= (ParticleSettings*)ale->data;
+                               AnimData *adt= part->adt;
+                               
+                               ale->flag= FILTER_PART_OBJD(part); 
+                               
+                               ale->key_data= (adt) ? adt->action : NULL;
+                               ale->datatype= ALE_ACT;
+                               
+                               ale->adt= BKE_animdata_from_id(data);
                        }
                                break;
                                
@@ -627,7 +688,7 @@ static int animdata_filter_fcurves (ListBase *anim_data, FCurve *first, bActionG
                        /* only work with this channel and its subchannels if it is editable */
                        if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_FCU(fcu)) {
                                /* only include this curve if selected in a way consistent with the filtering requirements */
-                               if ( ANIMCHANNEL_SELOK(SEL_FCU(fcu)) ) {
+                               if ( ANIMCHANNEL_SELOK(SEL_FCU(fcu)) && ANIMCHANNEL_SELEDITOK(SEL_FCU(fcu)) ) {
                                        /* only include if this curve is active */
                                        if (!(filter_mode & ANIMFILTER_ACTIVE) || (fcu->flag & FCURVE_ACTIVE)) {
                                                ale= make_new_animlistelem(fcu, ANIMTYPE_FCURVE, owner, ownertype, owner_id);
@@ -682,25 +743,30 @@ static int animdata_filter_action (ListBase *anim_data, bAction *act, int filter
                         * cases when we should include F-Curves inside group:
                         *      - we don't care about visibility
                         *      - group is expanded
-                        *      - we're interested in keyframes, but not if they appear in selected channels
+                        *      - we just need the F-Curves present
                         */
-                       // XXX what was the selection check here for again?
-                       if ( (!(filter_mode & ANIMFILTER_VISIBLE) || EXPANDED_AGRP(agrp)) || 
-                                ( /*ANIMCHANNEL_SELOK(SEL_AGRP(agrp)) &&*/ (filter_mode & ANIMFILTER_CURVESONLY) ) ) 
+                       if ( (!(filter_mode & ANIMFILTER_VISIBLE) || EXPANDED_AGRP(agrp)) || (filter_mode & ANIMFILTER_CURVESONLY) ) 
                        {
-                               if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_AGRP(agrp)) {
-                                       // XXX the 'owner' info here needs review...
-                                       items += animdata_filter_fcurves(anim_data, agrp->channels.first, agrp, owner, ownertype, filter_mode, owner_id);
-                                       
-                                       /* 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);
-                                               items--;
+                               /* for the Graph Editor, curves may be set to not be visible in the view to lessen clutter,
+                                * but to do this, we need to check that the group doesn't have it's not-visible flag set preventing 
+                                * all its sub-curves to be shown
+                                */
+                               if ( !(filter_mode & ANIMFILTER_CURVEVISIBLE) || !(agrp->flag & AGRP_NOTVISIBLE) )
+                               {
+                                       if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_AGRP(agrp)) {
+                                               // XXX the 'owner' info here needs review...
+                                               items += animdata_filter_fcurves(anim_data, agrp->channels.first, agrp, owner, ownertype, filter_mode, owner_id);
+                                               
+                                               /* 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);
+                                                       items--;
+                                               }
                                        }
                                }
                        }
@@ -793,71 +859,6 @@ static int animdata_filter_nla (ListBase *anim_data, AnimData *adt, int filter_m
        /* return the number of items added to the list */
        return items;
 }
-
-static int animdata_filter_shapekey (ListBase *anim_data, Key *key, int filter_mode, void *owner, short ownertype, ID *owner_id)
-{
-       bAnimListElem *ale;
-       KeyBlock *kb;
-       //FCurve *fcu;
-       int i, items=0;
-       
-       /* are we filtering for display or editing */
-       if (filter_mode & ANIMFILTER_CHANNELS) {
-               /* 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 0 // XXX fixme... old system
-                       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;
-                                       }
-                               }
-                       }
-#endif // XXX fixme... old system
-                       
-                       ale->id= owner_id;
-                       
-                       BLI_addtail(anim_data, ale);
-                       items++;
-               }
-       }
-       else {
-#if 0 // XXX fixme... old system
-               /* 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);
-                                       items++;
-                               }
-                       }
-                       else {
-                               items += animdata_filter_ipocurves(anim_data, key->ipo, filter_mode, key, ANIMTYPE_SHAPEKEY, (owned)?(owner):(NULL));
-                       }
-               }
-#endif // XXX fixme... old system
-       }
-       
-       /* return the number of items added to the list */
-       return items;
-}
  
 #if 0
 // FIXME: switch this to use the bDopeSheet...
@@ -884,7 +885,7 @@ static int animdata_filter_gpencil (ListBase *anim_data, bScreen *sc, int filter
                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);
+                       gpd= gpencil_data_get_active(sa);
                        if (gpd == NULL) continue;
                        
                        /* add gpd as channel too (if for drawing, and it has layers) */
@@ -1003,6 +1004,60 @@ static int animdata_filter_dopesheet_mats (ListBase *anim_data, bDopeSheet *ads,
        return items;
 }
 
+static int animdata_filter_dopesheet_particles (ListBase *anim_data, bDopeSheet *ads, Base *base, int filter_mode)
+{
+       bAnimListElem *ale=NULL;
+       Object *ob= base->object;
+       ParticleSystem *psys = ob->particlesystem.first;
+       int items= 0, first = 1;
+
+       for(; psys; psys=psys->next) {
+               short ok = 0;
+
+               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;
+
+               /* include particles-expand widget? */
+               if (first && (filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
+                       ale= make_new_animlistelem(ob, ANIMTYPE_FILLPARTD, base, ANIMTYPE_OBJECT, (ID *)ob);
+                       if (ale) {
+                               BLI_addtail(anim_data, ale);
+                               items++;
+                       }
+                       first = 0;
+               }
+               
+               /* add particle settings? */
+               if (FILTER_PART_OBJC(ob) || (filter_mode & ANIMFILTER_CURVESONLY)) {
+                       if ((filter_mode & ANIMFILTER_CHANNELS)){
+                               ale = make_new_animlistelem(psys->part, ANIMTYPE_DSPART, base, ANIMTYPE_OBJECT, (ID *)psys->part);
+                               if (ale) {
+                                       BLI_addtail(anim_data, ale);
+                                       items++;
+                               }
+                       }
+                       
+                       if (FILTER_PART_OBJD(psys->part) || (filter_mode & ANIMFILTER_CURVESONLY)) {
+                               ANIMDATA_FILTER_CASES(psys->part,
+                                       { /* AnimData blocks - do nothing... */ },
+                                       items += animdata_filter_nla(anim_data, psys->part->adt, filter_mode, psys->part, ANIMTYPE_DSPART, (ID *)psys->part);, 
+                                       items += animdata_filter_fcurves(anim_data, psys->part->adt->drivers.first, NULL, psys->part, ANIMTYPE_DSPART, filter_mode, (ID *)psys->part);, 
+                                       items += animdata_filter_action(anim_data, psys->part->adt->action, filter_mode, psys->part, ANIMTYPE_DSPART, (ID *)psys->part);)
+                       }
+               }
+       }
+       
+       /* return the number of items added to the list */
+       return items;
+}
+
 static int animdata_filter_dopesheet_obdata (ListBase *anim_data, bDopeSheet *ads, Base *base, int filter_mode)
 {
        bAnimListElem *ale=NULL;
@@ -1038,6 +1093,14 @@ static int animdata_filter_dopesheet_obdata (ListBase *anim_data, bDopeSheet *ad
                        expanded= FILTER_CUR_OBJD(cu);
                }
                        break;
+               case OB_MBALL: /* ------- MetaBall ---------- */
+               {
+                       MetaBall *mb= (MetaBall *)ob->data;
+                       
+                       type= ANIMTYPE_DSMBALL;
+                       expanded= FILTER_MBALL_OBJD(mb);
+               }
+                       break;
        }
        
        /* special exception for drivers instead of action */
@@ -1095,17 +1158,6 @@ static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, B
                ANIMDATA_FILTER_CASES(ob,
                        { /* AnimData blocks - do nothing... */ },
                        { /* nla */
-#if 0
-                               /* include nla-expand widget? */
-                               if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_NLATRACKS)) {
-                                       ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLNLA, base, ANIMTYPE_OBJECT, (ID *)ob);
-                                       if (ale) {
-                                               BLI_addtail(anim_data, ale);
-                                               items++;
-                                       }
-                               }
-#endif
-                               
                                /* add NLA tracks */
                                items += animdata_filter_nla(anim_data, adt, filter_mode, ob, ANIMTYPE_OBJECT, (ID *)ob);
                        },
@@ -1141,7 +1193,7 @@ static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, B
                                        items += animdata_filter_action(anim_data, adt->action, filter_mode, ob, ANIMTYPE_OBJECT, (ID *)ob); 
                                }
                        }
-               )
+               );
        }
        
        
@@ -1151,17 +1203,6 @@ static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, B
                ANIMDATA_FILTER_CASES(key,
                        { /* AnimData blocks - do nothing... */ },
                        { /* nla */
-#if 0
-                               /* include nla-expand widget? */
-                               if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_NLATRACKS)) {
-                                       ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLNLA, base, ANIMTYPE_OBJECT, (ID *)ob);
-                                       if (ale) {
-                                               BLI_addtail(anim_data, ale);
-                                               items++;
-                                       }
-                               }
-#endif
-                               
                                /* add NLA tracks */
                                items += animdata_filter_nla(anim_data, adt, filter_mode, ob, ANIMTYPE_OBJECT, (ID *)ob);
                        },
@@ -1177,7 +1218,7 @@ static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, B
                                
                                /* add channels */
                                if (FILTER_SKE_OBJD(key) || (filter_mode & ANIMFILTER_CURVESONLY)) {
-                                       items += animdata_filter_shapekey(anim_data, key, filter_mode, ob, ANIMTYPE_OBJECT, (ID *)ob);
+                                       items += animdata_filter_fcurves(anim_data, adt->drivers.first, NULL, key, ANIMTYPE_DSSKEY, filter_mode, (ID *)key);
                                }
                        },
                        { /* action (keyframes) */
@@ -1192,10 +1233,10 @@ static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, B
                                
                                /* add channels */
                                if (FILTER_SKE_OBJD(key) || (filter_mode & ANIMFILTER_CURVESONLY)) {
-                                       items += animdata_filter_shapekey(anim_data, key, filter_mode, ob, ANIMTYPE_OBJECT, (ID *)ob);
+                                       items += animdata_filter_action(anim_data, adt->action, filter_mode, key, ANIMTYPE_DSSKEY, (ID *)key); 
                                }
                        }
-               )
+               );
        }
 
        /* Materials? */
@@ -1243,9 +1284,26 @@ static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, B
                        }
                }
                        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;
        }
        if (obdata_ok) 
                items += animdata_filter_dopesheet_obdata(anim_data, ads, base, filter_mode);
+
+       /* particles */
+       if (ob->particlesystem.first && !(ads->filterflag & ADS_FILTER_NOPART))
+               items += animdata_filter_dopesheet_particles(anim_data, ads, base, filter_mode);
        
        /* return the number of items added to the list */
        return items;
@@ -1280,17 +1338,6 @@ static int animdata_filter_dopesheet_scene (ListBase *anim_data, bDopeSheet *ads
                ANIMDATA_FILTER_CASES(sce,
                        { /* AnimData blocks - do nothing... */ },
                        { /* nla */
-#if 0
-                               /* include nla-expand widget? */
-                               if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_NLATRACKS)) {
-                                       ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLNLA, base, ANIMTYPE_SCENE (ID *)sce);
-                                       if (ale) {
-                                               BLI_addtail(anim_data, ale);
-                                               items++;
-                                       }
-                               }
-#endif
-                               
                                /* add NLA tracks */
                                items += animdata_filter_nla(anim_data, adt, filter_mode, sce, ANIMTYPE_SCENE, (ID *)sce);
                        },
@@ -1334,17 +1381,6 @@ static int animdata_filter_dopesheet_scene (ListBase *anim_data, bDopeSheet *ads
                ANIMDATA_FILTER_CASES(wo,
                        { /* AnimData blocks - do nothing... */ },
                        { /* nla */
-#if 0
-                               /* include nla-expand widget? */
-                               if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_NLATRACKS)) {
-                                       ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLNLA, base, ANIMTYPE_DSWOR (ID *)wo);
-                                       if (ale) {
-                                               BLI_addtail(anim_data, ale);
-                                               items++;
-                                       }
-                               }
-#endif
-                               
                                /* add NLA tracks */
                                items += animdata_filter_nla(anim_data, adt, filter_mode, wo, ANIMTYPE_DSWOR, (ID *)wo);
                        },
@@ -1431,6 +1467,14 @@ static int animdata_filter_dopesheet (ListBase *anim_data, bDopeSheet *ads, int
                                worOk= !(ads->filterflag & ADS_FILTER_NOWOR);)
                }
                
+               /* if only F-Curves with visible flags set can be shown, check that 
+                * datablocks haven't been set to invisible 
+                */
+               if (filter_mode & ANIMFILTER_CURVEVISIBLE) {
+                       if ((sce->adt) && (sce->adt->flag & ADT_CURVES_NOT_VISIBLE))
+                               sceOk= worOk= 0;
+               }
+               
                /* check if not all bad (i.e. so there is something to show) */
                if ( !(!sceOk && !worOk) ) {
                        /* add scene data to the list of filtered channels */
@@ -1445,9 +1489,9 @@ static int animdata_filter_dopesheet (ListBase *anim_data, bDopeSheet *ads, int
                if (base->object) {
                        Object *ob= base->object;
                        Key *key= ob_get_key(ob);
-                       short actOk=1, keyOk=1, dataOk=1, matOk=1;
+                       short actOk=1, keyOk=1, dataOk=1, matOk=1, partOk=1;
                        
-                       /* firstly, check if object can be included, by the following fanimors:
+                       /* firstly, check if object can be included, by the following factors:
                         *      - 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
@@ -1461,6 +1505,14 @@ static int animdata_filter_dopesheet (ListBase *anim_data, bDopeSheet *ads, int
                                if (ob->restrictflag & OB_RESTRICT_VIEW) continue;
                        }
                        
+                       /* if only F-Curves with visible flags set can be shown, check that 
+                        * datablock hasn't been set to invisible 
+                        */
+                       if (filter_mode & ANIMFILTER_CURVEVISIBLE) {
+                               if ((ob->adt) && (ob->adt->flag & ADT_CURVES_NOT_VISIBLE))
+                                       continue;
+                       }
+                       
                        /* additionally, dopesheet filtering also affects what objects to consider */
                        if (ads->filterflag) {
                                /* check selection and object type filters */
@@ -1510,18 +1562,20 @@ static int animdata_filter_dopesheet (ListBase *anim_data, bDopeSheet *ads, int
                                        for (a=0; a < ob->totcol; a++) {
                                                Material *ma= give_current_material(ob, a);
                                                
-                                               /* 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 (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;
@@ -1581,13 +1635,55 @@ static int animdata_filter_dopesheet (ListBase *anim_data, bDopeSheet *ads, int
                                                        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;
                                        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)
+                               if (!actOk && !keyOk && !dataOk && !matOk && !partOk)
                                        continue;
                        }
                        else {
@@ -1632,13 +1728,31 @@ static int animdata_filter_dopesheet (ListBase *anim_data, bDopeSheet *ads, int
                                                dataOk= ANIMDATA_HAS_KEYS(cu);  
                                        }
                                                break;
+                                       case OB_MBALL: /* -------- Metas ---------- */
+                                       {
+                                               MetaBall *mb= (MetaBall *)ob->data;
+                                               dataOk= ANIMDATA_HAS_KEYS(mb);  
+                                       }
+                                               break;
                                        default: /* --- other --- */
                                                dataOk= 0;
                                                break;
                                }
                                
+                               /* particles */
+                               partOk = 0;
+                               if (ob->particlesystem.first) {
+                                       ParticleSystem *psys = ob->particlesystem.first;
+                                       for(; psys; psys=psys->next) {
+                                               if(psys->part && ANIMDATA_HAS_KEYS(psys->part)) {
+                                                       partOk = 1;
+                                                       break;
+                                               }
+                                       }
+                               }
+                               
                                /* check if all bad (i.e. nothing to show) */
-                               if (!actOk && !keyOk && !dataOk && !matOk)
+                               if (!actOk && !keyOk && !dataOk && !matOk && !partOk)
                                        continue;
                        }
                        
@@ -1676,7 +1790,7 @@ int ANIM_animdata_filter (bAnimContext *ac, ListBase *anim_data, int filter_mode
                                break;
                                
                        case ANIMCONT_SHAPEKEY:
-                               items= animdata_filter_shapekey(anim_data, data, filter_mode, NULL, ANIMTYPE_NONE, (ID *)obact);
+                               //items= animdata_filter_shapekey(anim_data, data, filter_mode, NULL, ANIMTYPE_NONE, (ID *)obact);
                                break;
                                
                        case ANIMCONT_GPENCIL: