Merge with -r 22620:23107.
[blender.git] / source / blender / editors / animation / anim_filter.c
index e6b8293071f03df5dd70ac1005db4e4025f010bf..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>
@@ -49,6 +50,7 @@
 
 #include "DNA_listBase.h"
 #include "DNA_ID.h"
+#include "DNA_anim_types.h"
 #include "DNA_action_types.h"
 #include "DNA_constraint_types.h"
 #include "DNA_camera_types.h"
 #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"
 #include "DNA_windowmanager_types.h"
+#include "DNA_world_types.h"
 
 #include "MEM_guardedalloc.h"
 
 #include "BLI_blenlib.h"
 
+#include "BKE_animsys.h"
 #include "BKE_context.h"
 #include "BKE_global.h"
 #include "BKE_key.h"
@@ -147,8 +153,8 @@ static short actedit_get_context (bAnimContext *ac, SpaceAction *saction)
                case SACTCONT_ACTION: /* 'Action Editor' */
                        /* if not pinned, sync with active object */
                        if (saction->pin == 0) {
-                               if (ac->obact)
-                                       saction->action = ac->obact->action;
+                               if (ac->obact && ac->obact->adt)
+                                       saction->action = ac->obact->adt->action;
                                else
                                        saction->action= NULL;
                        }
@@ -193,13 +199,72 @@ static short actedit_get_context (bAnimContext *ac, SpaceAction *saction)
        }
 }
 
-/* ----------- Private Stuff - IPO Editor ------------- */
+/* ----------- Private Stuff - Graph Editor ------------- */
 
-/* Get data being edited in IPO Editor (depending on current 'mode') */
-static short ipoedit_get_context (bAnimContext *ac, SpaceIpo *sipo)
+/* Get data being edited in Graph Editor (depending on current 'mode') */
+static short graphedit_get_context (bAnimContext *ac, SpaceIpo *sipo)
 {
-       // XXX FIXME...
-       return 0;
+       /* init dopesheet data if non-existant (i.e. for old files) */
+       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 */
+                       /* update scene-pointer (no need to check for pinning yet, as not implemented) */
+                       sipo->ads->source= (ID *)ac->scene;
+                       sipo->ads->filterflag &= ~ADS_FILTER_ONLYDRIVERS;
+                       
+                       ac->datatype= ANIMCONT_FCURVES;
+                       ac->data= sipo->ads;
+                       
+                       ac->mode= sipo->mode;
+                       return 1;
+               
+               case SIPO_MODE_DRIVERS:         /* Driver F-Curve Editor */
+                       /* update scene-pointer (no need to check for pinning yet, as not implemented) */
+                       sipo->ads->source= (ID *)ac->scene;
+                       sipo->ads->filterflag |= ADS_FILTER_ONLYDRIVERS;
+                       
+                       ac->datatype= ANIMCONT_DRIVERS;
+                       ac->data= sipo->ads;
+                       
+                       ac->mode= sipo->mode;
+                       return 1;
+               
+               default: /* unhandled yet */
+                       ac->datatype= ANIMCONT_NONE;
+                       ac->data= NULL;
+                       
+                       ac->mode= -1;
+                       return 0;
+       }
+}
+
+/* ----------- Private Stuff - NLA Editor ------------- */
+
+/* Get data being edited in Graph Editor (depending on current 'mode') */
+static short nlaedit_get_context (bAnimContext *ac, SpaceNla *snla)
+{
+       /* init dopesheet data if non-existant (i.e. for old files) */
+       if (snla->ads == NULL)
+               snla->ads= MEM_callocN(sizeof(bDopeSheet), "NlaEdit DopeSheet");
+       
+       /* sync settings with current view status, then return appropriate data */
+       /* update scene-pointer (no need to check for pinning yet, as not implemented) */
+       snla->ads->source= (ID *)ac->scene;
+       snla->ads->filterflag |= ADS_FILTER_ONLYNLA;
+       
+       ac->datatype= ANIMCONT_NLA;
+       ac->data= snla->ads;
+       
+       return 1;
 }
 
 /* ----------- Public API --------------- */
@@ -226,7 +291,14 @@ short ANIM_animdata_context_getdata (bAnimContext *ac)
                        case SPACE_IPO:
                        {
                                SpaceIpo *sipo= (SpaceIpo *)sa->spacedata.first;
-                               ok= ipoedit_get_context(ac, sipo);
+                               ok= graphedit_get_context(ac, sipo);
+                       }
+                               break;
+                               
+                       case SPACE_NLA:
+                       {
+                               SpaceNla *snla= (SpaceNla *)sa->spacedata.first;
+                               ok= nlaedit_get_context(ac, snla);
                        }
                                break;
                }
@@ -256,7 +328,10 @@ short ANIM_animdata_get_context (const bContext *C, bAnimContext *ac)
        
        /* get useful default context settings from context */
        ac->scene= scene;
-       ac->obact= (scene && scene->basact)?  scene->basact->object : NULL;
+       if (scene) {
+               ac->markers= &scene->markers;           
+               ac->obact= (scene->basact)?  scene->basact->object : NULL;
+       }
        ac->sa= sa;
        ac->ar= ar;
        ac->spacetype= (sa) ? sa->spacetype : 0;
@@ -269,12 +344,97 @@ short ANIM_animdata_get_context (const bContext *C, bAnimContext *ac)
 /* ************************************************************ */
 /* Blender Data <-- Filter --> Channels to be operated on */
 
+/* quick macro to test if AnimData is usable */
+#define ANIMDATA_HAS_KEYS(id) ((id)->adt && (id)->adt->action)
+
+/* quick macro to test if AnimData is usable for drivers */
+#define ANIMDATA_HAS_DRIVERS(id) ((id)->adt && (id)->adt->drivers.first)
+
+/* quick macro to test if AnimData is usable for NLA */
+#define ANIMDATA_HAS_NLA(id) ((id)->adt && (id)->adt->nla_tracks.first)
+
+
+/* Quick macro to test for all three avove usability tests, performing the appropriate provided 
+ * action for each when the AnimData context is appropriate. 
+ *
+ * Priority order for this goes (most important, to least): AnimData blocks, NLA, Drivers, Keyframes.
+ *
+ * For this to work correctly, a standard set of data needs to be available within the scope that this
+ * gets called in: 
+ *     - ListBase anim_data;
+ *     - bDopeSheet *ads;
+ *     - bAnimListElem *ale;
+ *     - int items;
+ *
+ *     - id: ID block which should have an AnimData pointer following it immediately, to use
+ *     - adtOk: line or block of code to execute for AnimData-blocks case (usually ANIMDATA_ADD_ANIMDATA)
+ *     - nlaOk: line or block of code to execute for NLA case
+ *     - driversOk: line or block of code to execute for Drivers case
+ *     - keysOk: line or block of code for Keyframes case
+ */
+#define ANIMDATA_FILTER_CASES(id, adtOk, nlaOk, driversOk, 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\
+                                       }\
+                               }\
+                       }\
+               }\
+       }
+
+
+/* quick macro to add a pointer to an AnimData block as a channel */
+#define ANIMDATA_ADD_ANIMDATA(id) \
+       {\
+               ale= make_new_animlistelem((id)->adt, ANIMTYPE_ANIMDATA, NULL, ANIMTYPE_NONE, (ID *)id);\
+               if (ale) {\
+                       BLI_addtail(anim_data, ale);\
+                       items++;\
+               }\
+       }
+       
+
+
+/* quick macro to test if 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 --------------- */
 
 /* 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 *make_new_animlistelem (void *data, short datatype, void *owner, short ownertype, ID *owner_id)
 {
        bAnimListElem *ale= NULL;
        
@@ -285,18 +445,27 @@ bAnimListElem *make_new_animlistelem (void *data, short datatype, void *owner, s
                
                ale->data= data;
                ale->type= datatype;
+                       // XXX what is the point of the owner data?
                ale->owner= owner;
                ale->ownertype= ownertype;
                
-               if ((owner) && (ownertype == ANIMTYPE_ACHAN)) {
-                       bActionChannel *ochan= (bActionChannel *)owner;
-                       ale->grp= ochan->grp;
-               }
-               else 
-                       ale->grp= NULL;
+               ale->id= owner_id;
+               ale->adt= BKE_animdata_from_id(owner_id);
                
                /* do specifics */
                switch (datatype) {
+                       case ANIMTYPE_SCENE:
+                       {
+                               Scene *sce= (Scene *)data;
+                               
+                               ale->flag= sce->flag;
+                               
+                               ale->key_data= sce;
+                               ale->datatype= ALE_SCE;
+                               
+                               ale->adt= BKE_animdata_from_id(data);
+                       }
+                               break;
                        case ANIMTYPE_OBJECT:
                        {
                                Base *base= (Base *)data;
@@ -306,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:
@@ -318,31 +489,32 @@ bAnimListElem *make_new_animlistelem (void *data, short datatype, void *owner, s
                                ale->datatype= ALE_ACT;
                        }
                                break;
-                       case ANIMTYPE_FILLIPOD:
+                       case ANIMTYPE_FILLDRIVERS:
                        {
-                               Object *ob= (Object *)data;
+                               AnimData *adt= (AnimData *)data;
                                
-                               ale->flag= FILTER_IPO_OBJC(ob);
+                               ale->flag= adt->flag;
                                
-                               ale->key_data= ob->ipo;
-                               ale->datatype= ALE_IPO;
+                                       // XXX... drivers don't show summary for now
+                               ale->key_data= NULL;
+                               ale->datatype= ALE_NONE;
                        }
                                break;
-                       case ANIMTYPE_FILLCOND:
+                       case ANIMTYPE_FILLMATD:
                        {
                                Object *ob= (Object *)data;
                                
-                               ale->flag= FILTER_CON_OBJC(ob);
+                               ale->flag= FILTER_MAT_OBJC(ob);
                                
                                ale->key_data= NULL;
                                ale->datatype= ALE_NONE;
                        }
                                break;
-                       case ANIMTYPE_FILLMATD:
+                       case ANIMTYPE_FILLPARTD:
                        {
                                Object *ob= (Object *)data;
                                
-                               ale->flag= FILTER_MAT_OBJC(ob);
+                               ale->flag= FILTER_PART_OBJC(ob);
                                
                                ale->key_data= NULL;
                                ale->datatype= ALE_NONE;
@@ -352,144 +524,113 @@ bAnimListElem *make_new_animlistelem (void *data, short datatype, void *owner, s
                        case ANIMTYPE_DSMAT:
                        {
                                Material *ma= (Material *)data;
+                               AnimData *adt= ma->adt;
                                
                                ale->flag= FILTER_MAT_OBJD(ma);
                                
-                               ale->key_data= ma->ipo;
-                               ale->datatype= ALE_IPO;
+                               ale->key_data= (adt) ? adt->action : NULL;
+                               ale->datatype= ALE_ACT;
+                               
+                               ale->adt= BKE_animdata_from_id(data);
                        }
                                break;
                        case ANIMTYPE_DSLAM:
                        {
                                Lamp *la= (Lamp *)data;
+                               AnimData *adt= la->adt;
                                
                                ale->flag= FILTER_LAM_OBJD(la);
                                
-                               ale->key_data= la->ipo;
-                               ale->datatype= ALE_IPO;
+                               ale->key_data= (adt) ? adt->action : NULL;
+                               ale->datatype= ALE_ACT;
+                               
+                               ale->adt= BKE_animdata_from_id(data);
                        }
                                break;
                        case ANIMTYPE_DSCAM:
                        {
                                Camera *ca= (Camera *)data;
+                               AnimData *adt= ca->adt;
                                
                                ale->flag= FILTER_CAM_OBJD(ca);
                                
-                               ale->key_data= ca->ipo;
-                               ale->datatype= ALE_IPO;
+                               ale->key_data= (adt) ? adt->action : NULL;
+                               ale->datatype= ALE_ACT;
+                               
+                               ale->adt= BKE_animdata_from_id(data);
                        }
                                break;
                        case ANIMTYPE_DSCUR:
                        {
                                Curve *cu= (Curve *)data;
+                               AnimData *adt= cu->adt;
                                
                                ale->flag= FILTER_CUR_OBJD(cu);
                                
-                               ale->key_data= cu->ipo;
-                               ale->datatype= ALE_IPO;
+                               ale->key_data= (adt) ? adt->action : NULL;
+                               ale->datatype= ALE_ACT;
+                               
+                               ale->adt= BKE_animdata_from_id(data);
                        }
                                break;
                        case ANIMTYPE_DSSKEY:
                        {
                                Key *key= (Key *)data;
+                               AnimData *adt= key->adt;
                                
-                               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= FILTER_SKE_OBJD(key); 
                                
-                               ale->flag= agrp->flag;
+                               ale->key_data= (adt) ? adt->action : NULL;
+                               ale->datatype= ALE_ACT;
                                
-                               ale->key_data= NULL;
-                               ale->datatype= ALE_GROUP;
+                               ale->adt= BKE_animdata_from_id(data);
                        }
                                break;
-                       case ANIMTYPE_ACHAN:
+                       case ANIMTYPE_DSWOR:
                        {
-                               bActionChannel *achan= (bActionChannel *)data;
+                               World *wo= (World *)data;
+                               AnimData *adt= wo->adt;
                                
-                               ale->flag= achan->flag;
+                               ale->flag= FILTER_WOR_SCED(wo); 
                                
-                               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;
+                               ale->key_data= (adt) ? adt->action : NULL;
+                               ale->datatype= ALE_ACT;
                                
-                               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;
-                                       }
-                               }
+                               ale->adt= BKE_animdata_from_id(data);
                        }
                                break;
-                       case ANIMTYPE_ICU:
+                       case ANIMTYPE_DSPART:
                        {
-                               IpoCurve *icu= (IpoCurve *)data;
+                               ParticleSettings *part= (ParticleSettings*)ale->data;
+                               AnimData *adt= part->adt;
                                
-                               ale->flag= icu->flag;
+                               ale->flag= FILTER_PART_OBJD(part); 
                                
-                               ale->key_data= icu;
-                               ale->datatype= ALE_ICU;
+                               ale->key_data= (adt) ? adt->action : NULL;
+                               ale->datatype= ALE_ACT;
+                               
+                               ale->adt= BKE_animdata_from_id(data);
                        }
                                break;
-                       case ANIMTYPE_FILLIPO:
-                       case ANIMTYPE_FILLCON:
+                               
+                       case ANIMTYPE_GROUP:
                        {
-                               bActionChannel *achan= (bActionChannel *)data;
+                               bActionGroup *agrp= (bActionGroup *)data;
+                               
+                               ale->flag= agrp->flag;
                                
-                               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;
+                               ale->datatype= ALE_GROUP;
                        }
                                break;
-                       case ANIMTYPE_IPO:
+                       case ANIMTYPE_FCURVE:
                        {
-                               ale->flag= 0;
+                               FCurve *fcu= (FCurve *)data;
+                               
+                               ale->flag= fcu->flag;
                                
-                               ale->key_data= data;
-                               ale->datatype= ALE_IPO;
+                               ale->key_data= fcu;
+                               ale->datatype= ALE_FCURVE;
                        }
                                break;
                        
@@ -503,6 +644,25 @@ bAnimListElem *make_new_animlistelem (void *data, short datatype, void *owner, s
                                ale->datatype= ALE_GPFRAME;
                        }
                                break;
+                               
+                       case ANIMTYPE_NLATRACK:
+                       {
+                               NlaTrack *nlt= (NlaTrack *)data;
+                               
+                               ale->flag= nlt->flag;
+                               
+                                       // XXX or should this be done some other way?
+                               ale->key_data= &nlt->strips;
+                               ale->datatype= ALE_NLASTRIP;
+                       }
+                               break;
+                       case ANIMTYPE_NLAACTION:
+                       {
+                               /* nothing to include for now... nothing editable from NLA-perspective here */
+                               ale->key_data= NULL;
+                               ale->datatype= ALE_NONE;
+                       }
+                               break;
                }
        }
        
@@ -512,162 +672,57 @@ bAnimListElem *make_new_animlistelem (void *data, short datatype, void *owner, s
  
 /* ----------------------------------------- */
 
-// FIXME: use this...
-static int animdata_filter_ipocurves (ListBase *anim_data, Ipo *ipo, int filter_mode, void *owner, short ownertype, ID *owner_id)
-{
-       bAnimListElem *ale = NULL;
-       IpoCurve *icu;
-       int items = 0;
-       
-       /* loop over ipo curves - assume that the caller of this has already checked that these should be included */
-       for (icu= ipo->curve.first; icu; icu= icu->next) {
-               /* only work with this channel and its subchannels if it is editable */
-               if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_ICU(icu)) {
-                       /* only include this curve if selected or we are including all IPO-curves */
-                       if (!(filter_mode & ANIMFILTER_SEL) || (filter_mode & ANIMFILTER_ONLYICU) || (SEL_ICU(icu))) {
-                               /* owner/ownertype will be either object or action-channel, depending if it was dopesheet or part of an action */
-                               ale= make_new_animlistelem(icu, ANIMTYPE_ICU, owner, ownertype);
-                               
-                               if (ale) {
-                                       /* ID will only be Object if data to write to directly belongs there, otherwise, another pointer will be used */
-                                       ale->id= owner_id;
-                                       BLI_addtail(anim_data, ale);
-                                       items++;
-                               }
-                       }
-               }
-       }
-       
-       /* return the number of items added to the list */
-       return items;
-}
 
-static int animdata_filter_actionchannel (ListBase *anim_data, bActionChannel *achan, int filter_mode, void *owner, short ownertype)
+static int animdata_filter_fcurves (ListBase *anim_data, FCurve *first, bActionGroup *grp, void *owner, short ownertype, int filter_mode, ID *owner_id)
 {
        bAnimListElem *ale = NULL;
-       bConstraintChannel *conchan;
-       short owned= (owner && ownertype)? 1 : 0;
+       FCurve *fcu;
        int items = 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);
-                                               items++;
-                                       }
-                               }
-                       }
-                       else {
-                               /* for insert key... this check could be improved */
-                               //return;  // FIXME...
-                       }
-                       
-                       /* 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 items;
-                       }
-                               
-                       /* 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);
-                                               items++;
-                                       }
-                               }
-                               
-                               /* add ipo-curve channels? */
-                               if (FILTER_IPO_ACHAN(achan) || (filter_mode & ANIMFILTER_ONLYICU)) {
-                                       /* loop through ipo-curve channels, adding them */
-                                       items += animdata_filter_ipocurves(anim_data, achan->ipo, filter_mode, achan, ANIMTYPE_ACHAN, (owned)?(owner):(NULL));
-                               }
-                       }
-                       
-                       /* 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);
-                                               items++;
-                                       }
-                               }
-                               
-                               /* 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) {
-                                                                       ale= make_new_animlistelem(conchan, ANIMTYPE_CONCHAN2, achan, ANIMTYPE_ACHAN);
-                                                                       
-                                                                       if (ale) {
-                                                                               if (owned) ale->id= owner;
-                                                                               BLI_addtail(anim_data, ale);
-                                                                               items++;
-                                                                       }
-                                                               }
-                                                               else {
-                                                                       ale= make_new_animlistelem(conchan, ANIMTYPE_CONCHAN, achan, ANIMTYPE_ACHAN);
-                                                                       
-                                                                       if (ale) {
-                                                                               if (owned) ale->id= owner;
-                                                                               BLI_addtail(anim_data, ale);
-                                                                               items++;
-                                                                       }
-                                                               }
-                                                       }
+       /* loop over F-Curves - assume that the caller of this has already checked that these should be included 
+        * NOTE: we need to check if the F-Curves belong to the same group, as this gets called for groups too...
+        */
+       for (fcu= first; ((fcu) && (fcu->grp==grp)); fcu= fcu->next) {
+               /* only include if visible (Graph Editor check, not channels check) */
+               if (!(filter_mode & ANIMFILTER_CURVEVISIBLE) || (fcu->flag & FCURVE_VISIBLE)) {
+                       /* 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)) && 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);
+                                               
+                                               if (ale) {
+                                                       BLI_addtail(anim_data, ale);
+                                                       items++;
                                                }
                                        }
                                }
                        }
-               }               
+               }
        }
        
        /* return the number of items added to the list */
        return items;
 }
 
-static int animdata_filter_action (ListBase *anim_data, bAction *act, int filter_mode, void *owner, short ownertype)
+static int animdata_filter_action (ListBase *anim_data, bAction *act, int filter_mode, void *owner, short ownertype, ID *owner_id)
 {
        bAnimListElem *ale=NULL;
        bActionGroup *agrp;
-       bActionChannel *achan, *lastchan=NULL;
-       short owned= (owner && ownertype) ? 1 : 0;
+       FCurve *lastchan=NULL;
        int items = 0;
        
        /* loop over groups */
+       //       XXX in future, we need to be prepared for nestled 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)) {
+               if ((filter_mode & ANIMFILTER_CHANNELS) || !(filter_mode & ANIMFILTER_CURVESONLY)) {
                        /* check if filtering by selection */
-                       if ( !(filter_mode & ANIMFILTER_SEL) || SEL_AGRP(agrp) ) {
-                               ale= make_new_animlistelem(agrp, ANIMTYPE_GROUP, NULL, ANIMTYPE_NONE);
+                       if ( ANIMCHANNEL_SELOK(SEL_AGRP(agrp)) ) {
+                               ale= make_new_animlistelem(agrp, ANIMTYPE_GROUP, NULL, ANIMTYPE_NONE, owner_id);
                                if (ale) {
-                                       if (owned) ale->id= owner;
                                        BLI_addtail(anim_data, ale);
                                        items++;
                                }
@@ -679,107 +734,125 @@ static int animdata_filter_action (ListBase *anim_data, bAction *act, int filter
                        lastchan= agrp->channels.last;
                
                
-               /* there are some situations, where only the channels of the animive group should get considered */
+               /* there are some situations, where only the channels of the action 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:
+                        * 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
                         */
-                       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_VISIBLE) || EXPANDED_AGRP(agrp)) || (filter_mode & ANIMFILTER_CURVESONLY) ) 
                        {
-                               if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_AGRP(agrp)) {                                       
-                                       for (achan= agrp->channels.first; achan && achan->grp==agrp; achan= achan->next) {
-                                               items += animdata_filter_actionchannel(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);
-                                               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--;
+                                               }
                                        }
                                }
                        }
                }
        }
        
-       /* loop over un-grouped animion channels (only if we're not only considering those channels in the animive group) */
+       /* loop over un-grouped F-Curves (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) {
-                       items += animdata_filter_actionchannel(anim_data, achan, filter_mode, owner, ownertype);
-               }
+               // XXX the 'owner' info here needs review...
+               items += animdata_filter_fcurves(anim_data, (lastchan)?(lastchan->next):(act->curves.first), NULL, owner, ownertype, filter_mode, owner_id);
        }
        
        /* 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)
+/* Include NLA-Data for NLA-Editor:
+ *     - when ANIMFILTER_CHANNELS is used, that means we should be filtering the list for display
+ *       Although the evaluation order is from the first track to the last and then apply the Action on top,
+ *       we present this in the UI as the Active Action followed by the last track to the first so that we 
+ *       get the evaluation order presented as per a stack.
+ *     - for normal filtering (i.e. for editing), we only need the NLA-tracks but they can be in 'normal' evaluation
+ *       order, i.e. first to last. Otherwise, some tools may get screwed up.
+ */
+static int animdata_filter_nla (ListBase *anim_data, AnimData *adt, int filter_mode, void *owner, short ownertype, ID *owner_id)
 {
        bAnimListElem *ale;
-       KeyBlock *kb;
-       IpoCurve *icu;
-       short owned= (owner && ownertype)? 1 : 0;
-       int i, items=0;
+       NlaTrack *nlt;
+       NlaTrack *first=NULL, *next=NULL;
+       int items = 0;
        
-       /* 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 showing channels, include active action */
+       if (filter_mode & ANIMFILTER_CHANNELS) {
+               /* there isn't really anything editable here, so skip if need editable */
+               // TODO: currently, selection isn't checked since it doesn't matter
+               if ((filter_mode & ANIMFILTER_FOREDIT) == 0) { 
+                       /* just add the action track now (this MUST appear for drawing)
+                        *      - as AnimData may not have an action, we pass a dummy pointer just to get the list elem created, then
+                        *        overwrite this with the real value - REVIEW THIS...
+                        */
+                       ale= make_new_animlistelem((void *)(&adt->action), ANIMTYPE_NLAACTION, owner, ownertype, owner_id);
+                       ale->data= (adt->action) ? adt->action : NULL;
+                               
+                       if (ale) {
+                               BLI_addtail(anim_data, ale);
+                               items++;
                        }
-                       
-                       if (owned) ale->id= owner;
-                       
-                       BLI_addtail(anim_data, ale);
-                       items++;
                }
+               
+               /* first track to include will be the last one if we're filtering by channels */
+               first= adt->nla_tracks.last;
        }
        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);
-                                       items++;
+               /* first track to include will the the first one (as per normal) */
+               first= adt->nla_tracks.first;
+       }
+       
+       /* loop over NLA Tracks - assume that the caller of this has already checked that these should be included */
+       for (nlt= first; nlt; nlt= next) {
+               /* 'next' NLA-Track to use depends on whether we're filtering for drawing or not */
+               if (filter_mode & ANIMFILTER_CHANNELS) 
+                       next= nlt->prev;
+               else
+                       next= nlt->next;
+               
+               /* if we're in NLA-tweakmode, don't show this track if it was disabled (due to tweaking) for now 
+                *      - active track should still get shown though (even though it has disabled flag set)
+                */
+               // FIXME: the channels after should still get drawn, just 'differently', and after an active-action channel
+               if ((adt->flag & ADT_NLA_EDIT_ON) && (nlt->flag & NLATRACK_DISABLED) && !(nlt->flag & NLATRACK_ACTIVE))
+                       continue;
+               
+               /* only work with this channel and its subchannels if it is editable */
+               if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_NLT(nlt)) {
+                       /* only include this track if selected in a way consistent with the filtering requirements */
+                       if ( ANIMCHANNEL_SELOK(SEL_NLT(nlt)) ) {
+                               /* only include if this track is active */
+                               if (!(filter_mode & ANIMFILTER_ACTIVE) || (nlt->flag & NLATRACK_ACTIVE)) {
+                                       ale= make_new_animlistelem(nlt, ANIMTYPE_NLATRACK, owner, ownertype, owner_id);
+                                               
+                                       if (ale) {
+                                               BLI_addtail(anim_data, ale);
+                                               items++;
+                                       }
                                }
                        }
-                       else {
-                               items += animdata_filter_ipocurves(anim_data, key->ipo, filter_mode, key, ANIMTYPE_SHAPEKEY, (owned)?(owner):(NULL));
-                       }
                }
        }
        
@@ -798,7 +871,6 @@ static int animdata_filter_gpencil (ListBase *anim_data, bScreen *sc, int filter
        int items = 0;
        
        /* 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
@@ -813,11 +885,11 @@ 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) */
-                       if ((filter_mode & ANIMFILTER_FORDRAWING) && (gpd->layers.first)) {
+                       if ((filter_mode & ANIMFILTER_CHANNELS) && (gpd->layers.first)) {
                                /* add to list */
                                ale= make_new_animlistelem(gpd, ANIMTYPE_GPDATABLOCK, sa, ANIMTYPE_SPECIALDATA);
                                if (ale) {
@@ -831,7 +903,7 @@ static int animdata_filter_gpencil (ListBase *anim_data, bScreen *sc, int filter
                                /* 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)) {
+                                       if ( ANIMCHANNEL_SELOK(SEL_GPL(gpl)) ) {
                                                /* only if editable */
                                                if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_GPL(gpl)) {
                                                        /* add to list */
@@ -852,15 +924,46 @@ static int animdata_filter_gpencil (ListBase *anim_data, bScreen *sc, int filter
 }
 #endif 
 
+
 static int animdata_filter_dopesheet_mats (ListBase *anim_data, bDopeSheet *ads, Base *base, int filter_mode)
 {
+       ListBase mats = {NULL, NULL};
+       LinkData *ld;
+       
        bAnimListElem *ale=NULL;
        Object *ob= base->object;
-       int items = 0;
+       int items=0, a=0;
+       
+       /* firstly check that we actuallly have some materials, by gathering all materials in a temp list */
+       for (a=0; a < ob->totcol; a++) {
+               Material *ma= give_current_material(ob, a);
+               short ok = 0;
+               
+               /* for now, if no material returned, skip (this shouldn't confuse the user I hope) */
+               if (ELEM(NULL, ma, ma->adt)) 
+                       continue;
+               
+               /* check if ok */
+               ANIMDATA_FILTER_CASES(ma, 
+                       { /* AnimData blocks - do nothing... */ },
+                       ok=1;, 
+                       ok=1;, 
+                       ok=1;)
+               if (ok == 0) continue;
+               
+               /* make a temp list elem for this */
+               ld= MEM_callocN(sizeof(LinkData), "DopeSheet-MaterialCache");
+               ld->data= ma;
+               BLI_addtail(&mats, ld);
+       }
+       
+       /* if there were no channels found, no need to carry on */
+       if (mats.first == NULL)
+               return 0;
        
        /* 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 ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
+               ale= make_new_animlistelem(ob, ANIMTYPE_FILLMATD, base, ANIMTYPE_OBJECT, (ID *)ob);
                if (ale) {
                        BLI_addtail(anim_data, ale);
                        items++;
@@ -868,115 +971,156 @@ static int animdata_filter_dopesheet_mats (ListBase *anim_data, bDopeSheet *ads,
        }
        
        /* 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;
+       if (FILTER_MAT_OBJC(ob) || (filter_mode & ANIMFILTER_CURVESONLY)) {
+               /* for each material in cache, add channels  */
+               for (ld= mats.first; ld; ld= ld->next) {
+                       Material *ma= (Material *)ld->data;
                        
                        /* 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 (filter_mode & ANIMFILTER_CHANNELS) {
+                               ale= make_new_animlistelem(ma, ANIMTYPE_DSMAT, base, ANIMTYPE_OBJECT, (ID *)ma);
                                if (ale) {
                                        BLI_addtail(anim_data, ale);
                                        items++;
                                }
                        }
                        
-                       /* add material's ipo-curve channels? */
-                       if ( (FILTER_MAT_OBJD(ma) || (filter_mode & ANIMFILTER_ONLYICU)) && 
-                                 !(filter_mode & ANIMFILTER_IPOKEYS) ) 
-                       {
-                               items += animdata_filter_ipocurves(anim_data, ma->ipo, filter_mode, base, ANIMTYPE_OBJECT, (ID *)ma);
+                       /* add material's animation data */
+                       if (FILTER_MAT_OBJD(ma) || (filter_mode & ANIMFILTER_CURVESONLY)) {
+                               ANIMDATA_FILTER_CASES(ma, 
+                                       { /* AnimData blocks - do nothing... */ },
+                                       items += animdata_filter_nla(anim_data, ma->adt, filter_mode, ma, ANIMTYPE_DSMAT, (ID *)ma);, 
+                                       items += animdata_filter_fcurves(anim_data, ma->adt->drivers.first, NULL, ma, ANIMTYPE_DSMAT, filter_mode, (ID *)ma);, 
+                                       items += animdata_filter_action(anim_data, ma->adt->action, filter_mode, ma, ANIMTYPE_DSMAT, (ID *)ma);)
                        }
                }
-
        }
        
+       /* free cache */
+       BLI_freelistN(&mats);
+       
        /* return the number of items added to the list */
        return items;
 }
 
-static int animdata_filter_dopesheet_cam (ListBase *anim_data, bDopeSheet *ads, Base *base, int filter_mode)
+static int animdata_filter_dopesheet_particles (ListBase *anim_data, bDopeSheet *ads, Base *base, int filter_mode)
 {
        bAnimListElem *ale=NULL;
        Object *ob= base->object;
-       Camera *ca= (Camera *)ob->data;
-       int items = 0;
-       
-       /* 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);
-                       items++;
+       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);)
+                       }
                }
-       }
-       
-       /* add camera ipo-curve channels? */
-       if ( (FILTER_CAM_OBJD(ca) || (filter_mode & ANIMFILTER_ONLYICU)) && 
-                 !(filter_mode & ANIMFILTER_IPOKEYS) ) 
-       {
-               items += animdata_filter_ipocurves(anim_data, ca->ipo, filter_mode, base, ANIMTYPE_OBJECT, (ID *)ca);
        }
        
        /* return the number of items added to the list */
        return items;
 }
 
-static int animdata_filter_dopesheet_lamp (ListBase *anim_data, bDopeSheet *ads, Base *base, int filter_mode)
+static int animdata_filter_dopesheet_obdata (ListBase *anim_data, bDopeSheet *ads, Base *base, int filter_mode)
 {
        bAnimListElem *ale=NULL;
        Object *ob= base->object;
-       Lamp *la= (Lamp *)ob->data;
-       int items = 0;
+       IdAdtTemplate *iat= ob->data;
+       AnimData *adt= iat->adt;
+       short type=0, expanded=0;
+       int items= 0;
        
-       /* 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);
-                       items++;
+       /* get settings based on data type */
+       switch (ob->type) {
+               case OB_CAMERA: /* ------- Camera ------------ */
+               {
+                       Camera *ca= (Camera *)ob->data;
+                       
+                       type= ANIMTYPE_DSCAM;
+                       expanded= FILTER_CAM_OBJD(ca);
                }
+                       break;
+               case OB_LAMP: /* ---------- Lamp ----------- */
+               {
+                       Lamp *la= (Lamp *)ob->data;
+                       
+                       type= ANIMTYPE_DSLAM;
+                       expanded= FILTER_LAM_OBJD(la);
+               }
+                       break;
+               case OB_CURVE: /* ------- Curve ---------- */
+               {
+                       Curve *cu= (Curve *)ob->data;
+                       
+                       type= ANIMTYPE_DSCUR;
+                       expanded= FILTER_CUR_OBJD(cu);
+               }
+                       break;
+               case OB_MBALL: /* ------- MetaBall ---------- */
+               {
+                       MetaBall *mb= (MetaBall *)ob->data;
+                       
+                       type= ANIMTYPE_DSMBALL;
+                       expanded= FILTER_MBALL_OBJD(mb);
+               }
+                       break;
        }
        
-       /* add lamp ipo-curve channels? */
-       if ( (FILTER_LAM_OBJD(la) || (filter_mode & ANIMFILTER_ONLYICU)) && 
-                 !(filter_mode & ANIMFILTER_IPOKEYS) ) 
-       {
-               items += animdata_filter_ipocurves(anim_data, la->ipo, filter_mode, base, ANIMTYPE_OBJECT, (ID *)la);
-       }
-       
-       /* return the number of items added to the list */
-       return items;
-}
-
-static int 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;
-       int items = 0;
+       /* special exception for drivers instead of action */
+       if (ads->filterflag & ADS_FILTER_ONLYDRIVERS)
+               expanded= EXPANDED_DRVD(adt);
        
-       /* 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);
-                       items++;
-               }
+       /* include data-expand widget? */
+       if ((filter_mode & ANIMFILTER_CURVESONLY) == 0) {               
+               ale= make_new_animlistelem(iat, type, base, ANIMTYPE_OBJECT, (ID *)iat);
+               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) ) 
-       {
-               items += animdata_filter_ipocurves(anim_data, cu->ipo, filter_mode, base, ANIMTYPE_OBJECT, (ID *)cu);
+       /* add object-data animation channels? */
+       if ((expanded) || (filter_mode & ANIMFILTER_CURVESONLY)) {
+               /* filtering for channels - nla, drivers, keyframes */
+               ANIMDATA_FILTER_CASES(iat, 
+                       { /* AnimData blocks - do nothing... */ },
+                       items+= animdata_filter_nla(anim_data, iat->adt, filter_mode, iat, type, (ID *)iat);,
+                       items+= animdata_filter_fcurves(anim_data, adt->drivers.first, NULL, iat, type, filter_mode, (ID *)iat);, 
+                       items += animdata_filter_action(anim_data, iat->adt->action, filter_mode, iat, type, (ID *)iat);)
        }
        
        /* return the number of items added to the list */
@@ -986,16 +1130,17 @@ static int animdata_filter_dopesheet_curve (ListBase *anim_data, bDopeSheet *ads
 static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, Base *base, int filter_mode)
 {
        bAnimListElem *ale=NULL;
-       Scene *sce= (Scene *)ads->source;
+       AnimData *adt = NULL;
        Object *ob= base->object;
        Key *key= ob_get_key(ob);
+       short obdata_ok = 0;
        int items = 0;
        
        /* add this object as a channel first */
-       if (!(filter_mode & ANIMFILTER_ONLYICU) && !(filter_mode & ANIMFILTER_IPOKEYS)) {
+       if ((filter_mode & (ANIMFILTER_CURVESONLY|ANIMFILTER_NLATRACKS)) == 0) {
                /* 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 ANIMCHANNEL_SELOK((base->flag & SELECT)) {
+                       ale= make_new_animlistelem(base, ANIMTYPE_OBJECT, NULL, ANIMTYPE_NONE, NULL);
                        if (ale) {
                                BLI_addtail(anim_data, ale);
                                items++;
@@ -1004,64 +1149,96 @@ static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, B
        }
        
        /* if collapsed, don't go any further (unless adding keyframes only) */
-       if ( (EXPANDED_OBJC(ob) == 0) && !(filter_mode & (ANIMFILTER_IPOKEYS|ANIMFILTER_ONLYICU)) )
+       if ( (EXPANDED_OBJC(ob) == 0) && !(filter_mode & (ANIMFILTER_CURVESONLY|ANIMFILTER_NLATRACKS)) )
                return items;
        
-       /* 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);
-                               items++;
+       /* Action, Drivers, or NLA */
+       if (ob->adt) {
+               adt= ob->adt;
+               ANIMDATA_FILTER_CASES(ob,
+                       { /* AnimData blocks - do nothing... */ },
+                       { /* nla */
+                               /* add NLA tracks */
+                               items += animdata_filter_nla(anim_data, adt, filter_mode, ob, ANIMTYPE_OBJECT, (ID *)ob);
+                       },
+                       { /* drivers */
+                               /* include drivers-expand widget? */
+                               if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
+                                       ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLDRIVERS, base, ANIMTYPE_OBJECT, (ID *)ob);
+                                       if (ale) {
+                                               BLI_addtail(anim_data, ale);
+                                               items++;
+                                       }
+                               }
+                               
+                               /* add F-Curve channels (drivers are F-Curves) */
+                               if (EXPANDED_DRVD(adt) || !(filter_mode & ANIMFILTER_CHANNELS)) {
+                                       // need to make the ownertype normal object here... (maybe type should be a separate one for clarity?)
+                                       items += animdata_filter_fcurves(anim_data, adt->drivers.first, NULL, ob, ANIMTYPE_OBJECT, filter_mode, (ID *)ob);
+                               }
+                       },
+                       { /* action (keyframes) */
+                               /* include action-expand widget? */
+                               if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
+                                       ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLACTD, base, ANIMTYPE_OBJECT, (ID *)ob);
+                                       if (ale) {
+                                               BLI_addtail(anim_data, ale);
+                                               items++;
+                                       }
+                               }
+                               
+                               /* add F-Curve channels? */
+                               if (EXPANDED_ACTC(adt->action) || !(filter_mode & ANIMFILTER_CHANNELS)) {
+                                       // need to make the ownertype normal object here... (maybe type should be a separate one for clarity?)
+                                       items += animdata_filter_action(anim_data, adt->action, filter_mode, ob, ANIMTYPE_OBJECT, (ID *)ob); 
+                               }
                        }
-               }
-               
-               /* add ipo-curve channels? */
-               if ( (FILTER_IPO_OBJC(ob) || (filter_mode & ANIMFILTER_ONLYICU)) && 
-                         !(filter_mode & ANIMFILTER_IPOKEYS) ) 
-               {
-                       items += animdata_filter_ipocurves(anim_data, ob->ipo, filter_mode, base, ANIMTYPE_OBJECT, NULL); // err... why not set ob?
-               }
+               );
        }
        
-       /* 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);
-                               items++;
-                       }
-               }
-               
-               /* 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?)
-                       items += 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);
-                               items++;
+               adt= key->adt;
+               ANIMDATA_FILTER_CASES(key,
+                       { /* AnimData blocks - do nothing... */ },
+                       { /* nla */
+                               /* add NLA tracks */
+                               items += animdata_filter_nla(anim_data, adt, filter_mode, ob, ANIMTYPE_OBJECT, (ID *)ob);
+                       },
+                       { /* drivers */
+                               /* include shapekey-expand widget? */
+                               if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
+                                       ale= make_new_animlistelem(key, ANIMTYPE_DSSKEY, base, ANIMTYPE_OBJECT, (ID *)ob);
+                                       if (ale) {
+                                               BLI_addtail(anim_data, ale);
+                                               items++;
+                                       }
+                               }
+                               
+                               /* add channels */
+                               if (FILTER_SKE_OBJD(key) || (filter_mode & ANIMFILTER_CURVESONLY)) {
+                                       items += animdata_filter_fcurves(anim_data, adt->drivers.first, NULL, key, ANIMTYPE_DSSKEY, filter_mode, (ID *)key);
+                               }
+                       },
+                       { /* action (keyframes) */
+                               /* include shapekey-expand widget? */
+                               if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
+                                       ale= make_new_animlistelem(key, ANIMTYPE_DSSKEY, base, ANIMTYPE_OBJECT, (ID *)ob);
+                                       if (ale) {
+                                               BLI_addtail(anim_data, ale);
+                                               items++;
+                                       }
+                               }
+                               
+                               /* add channels */
+                               if (FILTER_SKE_OBJD(key) || (filter_mode & ANIMFILTER_CURVESONLY)) {
+                                       items += animdata_filter_action(anim_data, adt->action, filter_mode, key, ANIMTYPE_DSSKEY, (ID *)key); 
+                               }
                        }
-               }
-               
-               /* add channels */
-               if (FILTER_SKE_OBJD(key) || (filter_mode & ANIMFILTER_IPOKEYS) || (filter_mode & ANIMFILTER_ONLYICU)) {
-                       items += animdata_filter_shapekey(anim_data, key, filter_mode, ob, ANIMTYPE_OBJECT);
-               }
+               );
        }
-       
+
        /* Materials? */
        if ((ob->totcol) && !(ads->filterflag & ADS_FILTER_NOMAT))
                items += animdata_filter_dopesheet_mats(anim_data, ads, base, filter_mode);
@@ -1071,80 +1248,186 @@ static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, B
                case OB_CAMERA: /* ------- Camera ------------ */
                {
                        Camera *ca= (Camera *)ob->data;
-                       if ((ca->ipo) && !(ads->filterflag & ADS_FILTER_NOCAM))
-                               items += animdata_filter_dopesheet_cam(anim_data, ads, base, filter_mode);
+                       
+                       if ((ads->filterflag & ADS_FILTER_NOCAM) == 0) {
+                               ANIMDATA_FILTER_CASES(ca,
+                                       { /* AnimData blocks - do nothing... */ },
+                                       obdata_ok= 1;,
+                                       obdata_ok= 1;,
+                                       obdata_ok= 1;)
+                       }
                }
                        break;
                case OB_LAMP: /* ---------- Lamp ----------- */
                {
                        Lamp *la= (Lamp *)ob->data;
-                       if ((la->ipo) && !(ads->filterflag & ADS_FILTER_NOLAM))
-                               items += animdata_filter_dopesheet_lamp(anim_data, ads, base, filter_mode);
+                       
+                       if ((ads->filterflag & ADS_FILTER_NOLAM) == 0) {
+                               ANIMDATA_FILTER_CASES(la,
+                                       { /* AnimData blocks - do nothing... */ },
+                                       obdata_ok= 1;,
+                                       obdata_ok= 1;,
+                                       obdata_ok= 1;)
+                       }
                }
                        break;
                case OB_CURVE: /* ------- Curve ---------- */
                {
                        Curve *cu= (Curve *)ob->data;
-                       if ((cu->ipo) && !(ads->filterflag & ADS_FILTER_NOCUR))
-                               items += animdata_filter_dopesheet_curve(anim_data, ads, base, filter_mode);
+                       
+                       if ((ads->filterflag & ADS_FILTER_NOCUR) == 0) {
+                               ANIMDATA_FILTER_CASES(cu,
+                                       { /* AnimData blocks - do nothing... */ },
+                                       obdata_ok= 1;,
+                                       obdata_ok= 1;,
+                                       obdata_ok= 1;)
+                       }
+               }
+                       break;
+               case OB_MBALL: /* ------- MetaBall ---------- */
+               {
+                       MetaBall *mb= (MetaBall *)ob->data;
+                       
+                       if ((ads->filterflag & ADS_FILTER_NOMBA) == 0) {
+                               ANIMDATA_FILTER_CASES(mb,
+                                       { /* AnimData blocks - do nothing... */ },
+                                       obdata_ok= 1;,
+                                       obdata_ok= 1;,
+                                       obdata_ok= 1;)
+                       }
                }
                        break;
        }
+       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);
        
-       /* 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);
+       /* return the number of items added to the list */
+       return items;
+}      
+
+static int animdata_filter_dopesheet_scene (ListBase *anim_data, bDopeSheet *ads, Scene *sce, int filter_mode)
+{
+       World *wo= sce->world;
+       AnimData *adt= NULL;
+       bAnimListElem *ale;
+       int items = 0;
+       
+       /* add scene as a channel first (even if we aren't showing scenes we still need to show the scene's sub-data */
+       if ((filter_mode & (ANIMFILTER_CURVESONLY|ANIMFILTER_NLATRACKS)) == 0) {
+               /* check if filtering by selection */
+               if (ANIMCHANNEL_SELOK( (sce->flag & SCE_DS_SELECTED) )) {
+                       ale= make_new_animlistelem(sce, ANIMTYPE_SCENE, NULL, ANIMTYPE_NONE, NULL);
                        if (ale) {
                                BLI_addtail(anim_data, ale);
                                items++;
                        }
                }
+       }
+       
+       /* if collapsed, don't go any further (unless adding keyframes only) */
+       if ( (EXPANDED_SCEC(sce) == 0) && !(filter_mode & (ANIMFILTER_CURVESONLY|ANIMFILTER_NLATRACKS)) )
+               return items;
                
-               /* 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);
-                                                               items++;
-                                                       }
-                                               }
-                                               else {
-                                                       ale= make_new_animlistelem(conchan, ANIMTYPE_CONCHAN, base, ANIMTYPE_OBJECT);
-                                                       if (ale) {
-                                                               ale->id= (ID *)ob;
-                                                               BLI_addtail(anim_data, ale);
-                                                               items++;
-                                                       }
-                                               }
+       /* Action, Drivers, or NLA  for Scene */
+       if ((ads->filterflag & ADS_FILTER_NOSCE) == 0) {
+               adt= sce->adt;
+               ANIMDATA_FILTER_CASES(sce,
+                       { /* AnimData blocks - do nothing... */ },
+                       { /* nla */
+                               /* add NLA tracks */
+                               items += animdata_filter_nla(anim_data, adt, filter_mode, sce, ANIMTYPE_SCENE, (ID *)sce);
+                       },
+                       { /* drivers */
+                               /* include drivers-expand widget? */
+                               if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
+                                       ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLDRIVERS, sce, ANIMTYPE_SCENE, (ID *)sce);
+                                       if (ale) {
+                                               BLI_addtail(anim_data, ale);
+                                               items++;
+                                       }
+                               }
+                               
+                               /* add F-Curve channels (drivers are F-Curves) */
+                               if (EXPANDED_DRVD(adt) || !(filter_mode & ANIMFILTER_CHANNELS)) {
+                                       items += animdata_filter_fcurves(anim_data, adt->drivers.first, NULL, sce, ANIMTYPE_SCENE, filter_mode, (ID *)sce);
+                               }
+                       },
+                       { /* action */
+                               /* include action-expand widget? */
+                               if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
+                                       ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLACTD, sce, ANIMTYPE_SCENE, (ID *)sce);
+                                       if (ale) {
+                                               BLI_addtail(anim_data, ale);
+                                               items++;
                                        }
                                }
+                               
+                               /* add F-Curve channels? */
+                               if (EXPANDED_ACTC(adt->action) || !(filter_mode & ANIMFILTER_CHANNELS)) {
+                                       items += animdata_filter_action(anim_data, adt->action, filter_mode, sce, ANIMTYPE_SCENE, (ID *)sce); 
+                               }
                        }
-               }
+               )
+       }
+       
+       /* world */
+       if ((wo && wo->adt) && !(ads->filterflag & ADS_FILTER_NOWOR)) {
+               /* Action, Drivers, or NLA for World */
+               adt= wo->adt;
+               ANIMDATA_FILTER_CASES(wo,
+                       { /* AnimData blocks - do nothing... */ },
+                       { /* nla */
+                               /* add NLA tracks */
+                               items += animdata_filter_nla(anim_data, adt, filter_mode, wo, ANIMTYPE_DSWOR, (ID *)wo);
+                       },
+                       { /* drivers */
+                               /* include world-expand widget? */
+                               if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
+                                       ale= make_new_animlistelem(wo, ANIMTYPE_DSWOR, sce, ANIMTYPE_SCENE, (ID *)wo);
+                                       if (ale) {
+                                               BLI_addtail(anim_data, ale);
+                                               items++;
+                                       }
+                               }
+                               
+                               /* add F-Curve channels (drivers are F-Curves) */
+                               if (FILTER_WOR_SCED(wo)/*EXPANDED_DRVD(adt)*/ || !(filter_mode & ANIMFILTER_CHANNELS)) {
+                                       // XXX owner info is messed up now...
+                                       items += animdata_filter_fcurves(anim_data, adt->drivers.first, NULL, wo, ANIMTYPE_DSWOR, filter_mode, (ID *)wo);
+                               }
+                       },
+                       { /* action */
+                               /* include world-expand widget? */
+                               if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
+                                       ale= make_new_animlistelem(wo, ANIMTYPE_DSWOR, sce, ANIMTYPE_SCENE, (ID *)sce);
+                                       if (ale) {
+                                               BLI_addtail(anim_data, ale);
+                                               items++;
+                                       }
+                               }
+                               
+                               /* add channels */
+                               if (FILTER_WOR_SCED(wo) || (filter_mode & ANIMFILTER_CURVESONLY)) {
+                                       items += animdata_filter_action(anim_data, adt->action, filter_mode, wo, ANIMTYPE_DSWOR, (ID *)wo); 
+                               }
+                       }
+               )
        }
        
        /* return the number of items added to the list */
        return items;
-}      
+}
 
 // TODO: implement pinning... (if and when pinning is done, what we need to do is to provide freeing mechanisms - to protect against data that was deleted)
 static int animdata_filter_dopesheet (ListBase *anim_data, bDopeSheet *ads, int filter_mode)
 {
        Scene *sce= (Scene *)ads->source;
        Base *base;
+       bAnimListElem *ale;
        int items = 0;
        
        /* check that we do indeed have a scene */
@@ -1153,28 +1436,83 @@ static int animdata_filter_dopesheet (ListBase *anim_data, bDopeSheet *ads, int
                return 0;
        }
        
+       /* scene-linked animation */
+       // TODO: sequencer, composite nodes - are we to include those here too?
+       {
+               short sceOk= 0, worOk= 0;
+               
+               /* check filtering-flags if ok */
+               ANIMDATA_FILTER_CASES(sce, 
+                       {
+                               /* for the special AnimData blocks only case, we only need to add
+                                * the block if it is valid... then other cases just get skipped (hence ok=0)
+                                */
+                               ANIMDATA_ADD_ANIMDATA(sce);
+                               sceOk=0;
+                       },
+                       sceOk= !(ads->filterflag & ADS_FILTER_NOSCE);, 
+                       sceOk= !(ads->filterflag & ADS_FILTER_NOSCE);, 
+                       sceOk= !(ads->filterflag & ADS_FILTER_NOSCE);)
+               if (sce->world) {
+                       ANIMDATA_FILTER_CASES(sce->world, 
+                               {
+                                       /* for the special AnimData blocks only case, we only need to add
+                                        * the block if it is valid... then other cases just get skipped (hence ok=0)
+                                        */
+                                       ANIMDATA_ADD_ANIMDATA(sce->world);
+                                       worOk=0;
+                               },
+                               worOk= !(ads->filterflag & ADS_FILTER_NOWOR);, 
+                               worOk= !(ads->filterflag & ADS_FILTER_NOWOR);, 
+                               worOk= !(ads->filterflag & ADS_FILTER_NOWOR);)
+               }
+               
+               /* if 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 */
+                       items += animdata_filter_dopesheet_scene(anim_data, ads, sce, filter_mode);
+               }
+       }
+       
+       
        /* 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;
+                       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
                         */
                        // 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;
+                               /* layer visibility - we check both object and base, since these may not be in sync yet */
+                               if ((sce->lay & (ob->lay|base->lay))==0) continue;
                                
                                /* outliner restrict-flag */
                                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 */
@@ -1182,38 +1520,136 @@ static int animdata_filter_dopesheet (ListBase *anim_data, bDopeSheet *ads, int
                                        /* 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));
+                                       /* object */
+                               actOk= 0;
+                               keyOk= 0;
+                               ANIMDATA_FILTER_CASES(ob, 
+                                       {
+                                               /* for the special AnimData blocks only case, we only need to add
+                                                * the block if it is valid... then other cases just get skipped (hence ok=0)
+                                                */
+                                               ANIMDATA_ADD_ANIMDATA(ob);
+                                               actOk=0;
+                                       },
+                                       actOk= 1;, 
+                                       actOk= 1;, 
+                                       actOk= 1;)
+                               if (key) {
+                                       /* shapekeys */
+                                       ANIMDATA_FILTER_CASES(key, 
+                                               {
+                                                       /* for the special AnimData blocks only case, we only need to add
+                                                        * the block if it is valid... then other cases just get skipped (hence ok=0)
+                                                        */
+                                                       ANIMDATA_ADD_ANIMDATA(key);
+                                                       keyOk=0;
+                                               },
+                                               keyOk= 1;, 
+                                               keyOk= 1;, 
+                                               keyOk= 1;)
+                               }
                                
+                               /* materials - only for geometric types */
+                               matOk= 0; /* by default, not ok... */
+                               if ( !(ads->filterflag & ADS_FILTER_NOMAT) && (ob->totcol) && 
+                                        ELEM5(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL) ) 
+                               {
+                                       int a;
+                                       
+                                       /* firstly check that we actuallly have some materials */
+                                       for (a=0; a < ob->totcol; a++) {
+                                               Material *ma= give_current_material(ob, a);
+                                               
+                                               if (ma) {
+                                                       /* if material has relevant animation data, break */
+                                                       ANIMDATA_FILTER_CASES(ma, 
+                                                               {
+                                                                       /* for the special AnimData blocks only case, we only need to add
+                                                                        * the block if it is valid... then other cases just get skipped (hence ok=0)
+                                                                        */
+                                                                       ANIMDATA_ADD_ANIMDATA(ma);
+                                                                       matOk=0;
+                                                               },
+                                                               matOk= 1;, 
+                                                               matOk= 1;, 
+                                                               matOk= 1;)
+                                               }
+                                                       
+                                               if (matOk) 
+                                                       break;
+                                       }
+                               }
+                               
+                               /* data */
                                switch (ob->type) {
                                        case OB_CAMERA: /* ------- Camera ------------ */
                                        {
                                                Camera *ca= (Camera *)ob->data;
-                                               dataOk= ((ca->ipo) && !(ads->filterflag & ADS_FILTER_NOCAM));                                           
+                                               dataOk= 0;
+                                               ANIMDATA_FILTER_CASES(ca, 
+                                                       if ((ads->filterflag & ADS_FILTER_NOCAM)==0) {
+                                                               /* for the special AnimData blocks only case, we only need to add
+                                                                * the block if it is valid... then other cases just get skipped (hence ok=0)
+                                                                */
+                                                               ANIMDATA_ADD_ANIMDATA(ca);
+                                                               dataOk=0;
+                                                       },
+                                                       dataOk= !(ads->filterflag & ADS_FILTER_NOCAM);, 
+                                                       dataOk= !(ads->filterflag & ADS_FILTER_NOCAM);, 
+                                                       dataOk= !(ads->filterflag & ADS_FILTER_NOCAM);)
                                        }
                                                break;
                                        case OB_LAMP: /* ---------- Lamp ----------- */
                                        {
                                                Lamp *la= (Lamp *)ob->data;
-                                               dataOk= ((la->ipo) && !(ads->filterflag & ADS_FILTER_NOLAM));
+                                               dataOk= 0;
+                                               ANIMDATA_FILTER_CASES(la, 
+                                                       if ((ads->filterflag & ADS_FILTER_NOLAM)==0) {
+                                                               /* for the special AnimData blocks only case, we only need to add
+                                                                * the block if it is valid... then other cases just get skipped (hence ok=0)
+                                                                */
+                                                               ANIMDATA_ADD_ANIMDATA(la);
+                                                               dataOk=0;
+                                                       },
+                                                       dataOk= !(ads->filterflag & ADS_FILTER_NOLAM);, 
+                                                       dataOk= !(ads->filterflag & ADS_FILTER_NOLAM);, 
+                                                       dataOk= !(ads->filterflag & ADS_FILTER_NOLAM);)
                                        }
                                                break;
-                                       case OB_CURVE: /* -------- Curve ---------- */
+                                       case OB_CURVE: /* ------- Curve ---------- */
                                        {
                                                Curve *cu= (Curve *)ob->data;
-                                               dataOk= ((cu->ipo) && !(ads->filterflag & ADS_FILTER_NOCUR));
+                                               dataOk= 0;
+                                               ANIMDATA_FILTER_CASES(cu, 
+                                                       if ((ads->filterflag & ADS_FILTER_NOCUR)==0) {
+                                                               /* for the special AnimData blocks only case, we only need to add
+                                                                * the block if it is valid... then other cases just get skipped (hence ok=0)
+                                                                */
+                                                               ANIMDATA_ADD_ANIMDATA(cu);
+                                                               dataOk=0;
+                                                       },
+                                                       dataOk= !(ads->filterflag & ADS_FILTER_NOCUR);, 
+                                                       dataOk= !(ads->filterflag & ADS_FILTER_NOCUR);, 
+                                                       dataOk= !(ads->filterflag & ADS_FILTER_NOCUR);)
+                                       }
+                                               break;
+                                       case OB_MBALL: /* ------- MetaBall ---------- */
+                                       {
+                                               MetaBall *mb= (MetaBall *)ob->data;
+                                               dataOk= 0;
+                                               ANIMDATA_FILTER_CASES(mb, 
+                                                       if ((ads->filterflag & ADS_FILTER_NOMBA)==0) {
+                                                               /* for the special AnimData blocks only case, we only need to add
+                                                                * the block if it is valid... then other cases just get skipped (hence ok=0)
+                                                                */
+                                                               ANIMDATA_ADD_ANIMDATA(mb);
+                                                               dataOk=0;
+                                                       },
+                                                       dataOk= !(ads->filterflag & ADS_FILTER_NOMBA);, 
+                                                       dataOk= !(ads->filterflag & ADS_FILTER_NOMBA);, 
+                                                       dataOk= !(ads->filterflag & ADS_FILTER_NOMBA);)
                                        }
                                                break;
                                        default: /* --- other --- */
@@ -1221,34 +1657,81 @@ static int animdata_filter_dopesheet (ListBase *anim_data, bDopeSheet *ads, int
                                                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 (!ipoOk && !actOk && !constsOk && !keyOk && !dataOk)
+                               if (!actOk && !keyOk && !dataOk && !matOk && !partOk)
                                        continue;
                        }
                        else {
                                /* check data-types */
-                               ipoOk= (ob->ipo != NULL);
-                               actOk= (ob->action != NULL);
-                               constsOk= (ob->constraintChannels.first != NULL);
+                               actOk= ANIMDATA_HAS_KEYS(ob);
                                keyOk= (key != NULL);
                                
+                               /* materials - only for geometric types */
+                               matOk= 0; /* by default, not ok... */
+                               if (ELEM5(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL) && (ob->totcol)) 
+                               {
+                                       int a;
+                                       
+                                       /* firstly check that we actuallly have some materials */
+                                       for (a=0; a < ob->totcol; a++) {
+                                               Material *ma= give_current_material(ob, a);
+                                               
+                                               if ((ma) && ANIMDATA_HAS_KEYS(ma)) {
+                                                       matOk= 1;
+                                                       break;
+                                               }
+                                       }
+                               }
+                               
+                               /* data */
                                switch (ob->type) {
                                        case OB_CAMERA: /* ------- Camera ------------ */
                                        {
                                                Camera *ca= (Camera *)ob->data;
-                                               dataOk= (ca->ipo != NULL);                                              
+                                               dataOk= ANIMDATA_HAS_KEYS(ca);                                          
                                        }
                                                break;
                                        case OB_LAMP: /* ---------- Lamp ----------- */
                                        {
                                                Lamp *la= (Lamp *)ob->data;
-                                               dataOk= (la->ipo != NULL);
+                                               dataOk= ANIMDATA_HAS_KEYS(la);  
                                        }
                                                break;
                                        case OB_CURVE: /* -------- Curve ---------- */
                                        {
                                                Curve *cu= (Curve *)ob->data;
-                                               dataOk= (cu->ipo != NULL);
+                                               dataOk= ANIMDATA_HAS_KEYS(cu);  
+                                       }
+                                               break;
+                                       case OB_MBALL: /* -------- Metas ---------- */
+                                       {
+                                               MetaBall *mb= (MetaBall *)ob->data;
+                                               dataOk= ANIMDATA_HAS_KEYS(mb);  
                                        }
                                                break;
                                        default: /* --- other --- */
@@ -1256,8 +1739,20 @@ static int animdata_filter_dopesheet (ListBase *anim_data, bDopeSheet *ads, int
                                                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 (!ipoOk && !actOk && !constsOk && !keyOk && !dataOk)
+                               if (!actOk && !keyOk && !dataOk && !matOk && !partOk)
                                        continue;
                        }
                        
@@ -1275,37 +1770,39 @@ static int animdata_filter_dopesheet (ListBase *anim_data, bDopeSheet *ads, int
 /* This function filters the active data source to leave only animation channels suitable for
  * usage by the caller. It will return the length of the list 
  * 
- *     *act_data: is a pointer to a ListBase, to which the filtered animation channels
+ *     *anim_data: is a pointer to a ListBase, to which the filtered animation channels
  *             will be placed for use.
  *     filter_mode: how should the data be filtered - bitmapping accessed flags
  */
-int ANIM_animdata_filter (ListBase *anim_data, int filter_mode, void *data, short datatype)
+int ANIM_animdata_filter (bAnimContext *ac, ListBase *anim_data, int filter_mode, void *data, short datatype)
 {
        int items = 0;
        
        /* only filter data if there's somewhere to put it */
        if (data && anim_data) {
                bAnimListElem *ale, *next;
+               Object *obact= (ac) ? ac->obact : NULL;
                
                /* firstly filter the data */
                switch (datatype) {
                        case ANIMCONT_ACTION:
-                               items= animdata_filter_action(anim_data, data, filter_mode, NULL, ANIMTYPE_NONE);
+                               items= animdata_filter_action(anim_data, data, filter_mode, NULL, ANIMTYPE_NONE, (ID *)obact);
                                break;
+                               
                        case ANIMCONT_SHAPEKEY:
-                               items= animdata_filter_shapekey(anim_data, data, filter_mode, NULL, ANIMTYPE_NONE);
+                               //items= animdata_filter_shapekey(anim_data, data, filter_mode, NULL, ANIMTYPE_NONE, (ID *)obact);
                                break;
+                               
                        case ANIMCONT_GPENCIL:
                                //items= animdata_filter_gpencil(anim_data, data, filter_mode);
                                break;
+                               
                        case ANIMCONT_DOPESHEET:
+                       case ANIMCONT_FCURVES:
+                       case ANIMCONT_DRIVERS:
+                       case ANIMCONT_NLA:
                                items= animdata_filter_dopesheet(anim_data, data, filter_mode);
                                break;
-                               
-                       case ANIMCONT_IPO:
-                               // FIXME: this will be used for showing a single IPO-block (not too useful from animator perspective though!)
-                               //items= 0;
-                               break;
                }
                        
                /* remove any weedy entries */
@@ -1317,17 +1814,6 @@ int ANIM_animdata_filter (ListBase *anim_data, int filter_mode, void *data, shor
                                items--;
                                BLI_freelinkN(anim_data, ale);
                        }
-                       
-                       if (filter_mode & ANIMFILTER_IPOKEYS) {
-                               if (ale->datatype != ALE_IPO) {
-                                       items--;
-                                       BLI_freelinkN(anim_data, ale);
-                               }
-                               else if (ale->key_data == NULL) {
-                                       items--;
-                                       BLI_freelinkN(anim_data, ale);
-                               }
-                       }
                }
        }