sequencer fcurve anim filtering: sequence strips fcurves in meta's were showing up...
[blender.git] / source / blender / editors / animation / anim_filter.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. 
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2008 Blender Foundation, Joshua Leung
21  * All rights reserved.
22  *
23  * 
24  * Contributor(s): Joshua Leung (original author)
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29 /* This file contains a system used to provide a layer of abstraction between sources
30  * of animation data and tools in Animation Editors. The method used here involves 
31  * generating a list of edit structures which enable tools to naively perform the actions 
32  * they require without all the boiler-plate associated with loops within loops and checking 
33  * for cases to ignore. 
34  *
35  * While this is primarily used for the Action/Dopesheet Editor (and its accessory modes),
36  * the Graph Editor also uses this for its channel list and for determining which curves
37  * are being edited. Likewise, the NLA Editor also uses this for its channel list and in
38  * its operators.
39  *
40  * Note: much of the original system this was based on was built before the creation of the RNA
41  * system. In future, it would be interesting to replace some parts of this code with RNA queries,
42  * however, RNA does not eliminate some of the boiler-plate reduction benefits presented by this 
43  * system, so if any such work does occur, it should only be used for the internals used here...
44  *
45  * -- Joshua Leung, Dec 2008 (Last revision July 2009)
46  */
47
48 #include <string.h>
49 #include <stdio.h>
50
51 #include "DNA_listBase.h"
52 #include "DNA_ID.h"
53 #include "DNA_anim_types.h"
54 #include "DNA_action_types.h"
55 #include "DNA_armature_types.h"
56 #include "DNA_constraint_types.h"
57 #include "DNA_camera_types.h"
58 #include "DNA_curve_types.h"
59 #include "DNA_gpencil_types.h"
60 #include "DNA_ipo_types.h"
61 #include "DNA_lamp_types.h"
62 #include "DNA_lattice_types.h"
63 #include "DNA_key_types.h"
64 #include "DNA_material_types.h"
65 #include "DNA_mesh_types.h"
66 #include "DNA_meta_types.h"
67 #include "DNA_node_types.h"
68 #include "DNA_object_types.h"
69 #include "DNA_particle_types.h"
70 #include "DNA_space_types.h"
71 #include "DNA_sequence_types.h"
72 #include "DNA_scene_types.h"
73 #include "DNA_screen_types.h"
74 #include "DNA_windowmanager_types.h"
75 #include "DNA_world_types.h"
76
77 #include "MEM_guardedalloc.h"
78
79 #include "BLI_blenlib.h"
80
81 #include "BKE_animsys.h"
82 #include "BKE_action.h"
83 #include "BKE_fcurve.h"
84 #include "BKE_context.h"
85 #include "BKE_global.h"
86 #include "BKE_key.h"
87 #include "BKE_object.h"
88 #include "BKE_material.h"
89 #include "BKE_node.h"
90 #include "BKE_sequencer.h"
91 #include "BKE_screen.h"
92 #include "BKE_utildefines.h"
93
94 #include "ED_anim_api.h"
95 #include "ED_types.h"
96 #include "ED_util.h"
97
98 #include "WM_api.h"
99 #include "WM_types.h"
100
101 #include "BIF_gl.h"
102 #include "BIF_glutil.h"
103
104 #include "UI_interface.h"
105 #include "UI_resources.h"
106 #include "UI_view2d.h"
107
108 /* ************************************************************ */
109 /* Blender Context <-> Animation Context mapping */
110
111 /* ----------- Private Stuff - Action Editor ------------- */
112
113 /* Get shapekey data being edited (for Action Editor -> ShapeKey mode) */
114 /* Note: there's a similar function in key.c (ob_get_key) */
115 Key *actedit_get_shapekeys (bAnimContext *ac, SpaceAction *saction) 
116 {
117     Scene *scene= ac->scene;
118     Object *ob;
119     Key *key;
120         
121     ob = OBACT;
122     if (ob == NULL) 
123                 return NULL;
124         
125         /* XXX pinning is not available in 'ShapeKey' mode... */
126         //if (saction->pin) return NULL;
127         
128         /* shapekey data is stored with geometry data */
129         switch (ob->type) {
130                 case OB_MESH:
131                         key= ((Mesh *)ob->data)->key;
132                         break;
133                         
134                 case OB_LATTICE:
135                         key= ((Lattice *)ob->data)->key;
136                         break;
137                         
138                 case OB_CURVE:
139                 case OB_SURF:
140                         key= ((Curve *)ob->data)->key;
141                         break;
142                         
143                 default:
144                         return NULL;
145         }
146         
147         if (key) {
148                 if (key->type == KEY_RELATIVE)
149                         return key;
150         }
151         
152     return NULL;
153 }
154
155 /* Get data being edited in Action Editor (depending on current 'mode') */
156 static short actedit_get_context (bAnimContext *ac, SpaceAction *saction)
157 {
158         /* sync settings with current view status, then return appropriate data */
159         switch (saction->mode) {
160                 case SACTCONT_ACTION: /* 'Action Editor' */
161                         /* if not pinned, sync with active object */
162                         if (saction->pin == 0) {
163                                 if (ac->obact && ac->obact->adt)
164                                         saction->action = ac->obact->adt->action;
165                                 else
166                                         saction->action= NULL;
167                         }
168                         
169                         ac->datatype= ANIMCONT_ACTION;
170                         ac->data= saction->action;
171                         
172                         ac->mode= saction->mode;
173                         return 1;
174                         
175                 case SACTCONT_SHAPEKEY: /* 'ShapeKey Editor' */
176                         ac->datatype= ANIMCONT_SHAPEKEY;
177                         ac->data= actedit_get_shapekeys(ac, saction);
178                         
179                         ac->mode= saction->mode;
180                         return 1;
181                         
182                 case SACTCONT_GPENCIL: /* Grease Pencil */ // XXX review how this mode is handled...
183                         ac->datatype=ANIMCONT_GPENCIL;
184                         //ac->data= CTX_wm_screen(C); // FIXME: add that dopesheet type thing here!
185                         ac->data= NULL; // !!!
186                         
187                         ac->mode= saction->mode;
188                         return 1;
189                         
190                 case SACTCONT_DOPESHEET: /* DopeSheet */
191                         /* update scene-pointer (no need to check for pinning yet, as not implemented) */
192                         saction->ads.source= (ID *)ac->scene;
193                         
194                         ac->datatype= ANIMCONT_DOPESHEET;
195                         ac->data= &saction->ads;
196                         
197                         ac->mode= saction->mode;
198                         return 1;
199                 
200                 default: /* unhandled yet */
201                         ac->datatype= ANIMCONT_NONE;
202                         ac->data= NULL;
203                         
204                         ac->mode= -1;
205                         return 0;
206         }
207 }
208
209 /* ----------- Private Stuff - Graph Editor ------------- */
210
211 /* Get data being edited in Graph Editor (depending on current 'mode') */
212 static short graphedit_get_context (bAnimContext *ac, SpaceIpo *sipo)
213 {
214         /* init dopesheet data if non-existant (i.e. for old files) */
215         if (sipo->ads == NULL) {
216                 sipo->ads= MEM_callocN(sizeof(bDopeSheet), "GraphEdit DopeSheet");
217                 sipo->ads->source= (ID *)ac->scene;
218         }
219         
220         /* set settings for Graph Editor - "Selected = Editable" */
221         if (sipo->flag & SIPO_SELCUVERTSONLY)
222                 sipo->ads->filterflag |= ADS_FILTER_SELEDIT;
223         else
224                 sipo->ads->filterflag &= ~ADS_FILTER_SELEDIT;
225         
226         /* sync settings with current view status, then return appropriate data */
227         switch (sipo->mode) {
228                 case SIPO_MODE_ANIMATION:       /* Animation F-Curve Editor */
229                         /* update scene-pointer (no need to check for pinning yet, as not implemented) */
230                         sipo->ads->source= (ID *)ac->scene;
231                         sipo->ads->filterflag &= ~ADS_FILTER_ONLYDRIVERS;
232                         
233                         ac->datatype= ANIMCONT_FCURVES;
234                         ac->data= sipo->ads;
235                         
236                         ac->mode= sipo->mode;
237                         return 1;
238                 
239                 case SIPO_MODE_DRIVERS:         /* Driver F-Curve Editor */
240                         /* update scene-pointer (no need to check for pinning yet, as not implemented) */
241                         sipo->ads->source= (ID *)ac->scene;
242                         sipo->ads->filterflag |= ADS_FILTER_ONLYDRIVERS;
243                         
244                         ac->datatype= ANIMCONT_DRIVERS;
245                         ac->data= sipo->ads;
246                         
247                         ac->mode= sipo->mode;
248                         return 1;
249                 
250                 default: /* unhandled yet */
251                         ac->datatype= ANIMCONT_NONE;
252                         ac->data= NULL;
253                         
254                         ac->mode= -1;
255                         return 0;
256         }
257 }
258
259 /* ----------- Private Stuff - NLA Editor ------------- */
260
261 /* Get data being edited in Graph Editor (depending on current 'mode') */
262 static short nlaedit_get_context (bAnimContext *ac, SpaceNla *snla)
263 {
264         /* init dopesheet data if non-existant (i.e. for old files) */
265         if (snla->ads == NULL)
266                 snla->ads= MEM_callocN(sizeof(bDopeSheet), "NlaEdit DopeSheet");
267         
268         /* sync settings with current view status, then return appropriate data */
269         /* update scene-pointer (no need to check for pinning yet, as not implemented) */
270         snla->ads->source= (ID *)ac->scene;
271         snla->ads->filterflag |= ADS_FILTER_ONLYNLA;
272         
273         ac->datatype= ANIMCONT_NLA;
274         ac->data= snla->ads;
275         
276         return 1;
277 }
278
279 /* ----------- Public API --------------- */
280
281 /* Obtain current anim-data context, given that context info from Blender context has already been set 
282  *      - AnimContext to write to is provided as pointer to var on stack so that we don't have
283  *        allocation/freeing costs (which are not that avoidable with channels).
284  */
285 short ANIM_animdata_context_getdata (bAnimContext *ac)
286 {
287         ScrArea *sa= ac->sa;
288         short ok= 0;
289         
290         /* context depends on editor we are currently in */
291         if (sa) {
292                 switch (sa->spacetype) {
293                         case SPACE_ACTION:
294                         {
295                                 SpaceAction *saction= (SpaceAction *)sa->spacedata.first;
296                                 ok= actedit_get_context(ac, saction);
297                         }
298                                 break;
299                                 
300                         case SPACE_IPO:
301                         {
302                                 SpaceIpo *sipo= (SpaceIpo *)sa->spacedata.first;
303                                 ok= graphedit_get_context(ac, sipo);
304                         }
305                                 break;
306                                 
307                         case SPACE_NLA:
308                         {
309                                 SpaceNla *snla= (SpaceNla *)sa->spacedata.first;
310                                 ok= nlaedit_get_context(ac, snla);
311                         }
312                                 break;
313                 }
314         }
315         
316         /* check if there's any valid data */
317         if (ok && ac->data)
318                 return 1;
319         else
320                 return 0;
321 }
322
323 /* Obtain current anim-data context from Blender Context info 
324  *      - AnimContext to write to is provided as pointer to var on stack so that we don't have
325  *        allocation/freeing costs (which are not that avoidable with channels).
326  *      - Clears data and sets the information from Blender Context which is useful
327  */
328 short ANIM_animdata_get_context (const bContext *C, bAnimContext *ac)
329 {
330         ScrArea *sa= CTX_wm_area(C);
331         ARegion *ar= CTX_wm_region(C);
332         Scene *scene= CTX_data_scene(C);
333         
334         /* clear old context info */
335         if (ac == NULL) return 0;
336         memset(ac, 0, sizeof(bAnimContext));
337         
338         /* get useful default context settings from context */
339         ac->scene= scene;
340         if (scene) {
341                 ac->markers= &scene->markers;           
342                 ac->obact= (scene->basact)?  scene->basact->object : NULL;
343         }
344         ac->sa= sa;
345         ac->ar= ar;
346         ac->spacetype= (sa) ? sa->spacetype : 0;
347         ac->regiontype= (ar) ? ar->regiontype : 0;
348         
349         /* get data context info */
350         return ANIM_animdata_context_getdata(ac);
351 }
352
353 /* ************************************************************ */
354 /* Blender Data <-- Filter --> Channels to be operated on */
355
356 /* quick macro to test if AnimData is usable */
357 #define ANIMDATA_HAS_KEYS(id) ((id)->adt && (id)->adt->action)
358
359 /* quick macro to test if AnimData is usable for drivers */
360 #define ANIMDATA_HAS_DRIVERS(id) ((id)->adt && (id)->adt->drivers.first)
361
362 /* quick macro to test if AnimData is usable for NLA */
363 #define ANIMDATA_HAS_NLA(id) ((id)->adt && (id)->adt->nla_tracks.first)
364
365
366 /* Quick macro to test for all three avove usability tests, performing the appropriate provided 
367  * action for each when the AnimData context is appropriate. 
368  *
369  * Priority order for this goes (most important, to least): AnimData blocks, NLA, Drivers, Keyframes.
370  *
371  * For this to work correctly, a standard set of data needs to be available within the scope that this
372  * gets called in: 
373  *      - ListBase anim_data;
374  *      - bDopeSheet *ads;
375  *      - bAnimListElem *ale;
376  *      - int items;
377  *
378  *      - id: ID block which should have an AnimData pointer following it immediately, to use
379  *      - adtOk: line or block of code to execute for AnimData-blocks case (usually ANIMDATA_ADD_ANIMDATA)
380  *      - nlaOk: line or block of code to execute for NLA tracks+strips case
381  *      - driversOk: line or block of code to execute for Drivers case
382  *      - keysOk: line or block of code for Keyframes case
383  *
384  * The checks for the various cases are as follows:
385  *      0) top level: checks for animdata and also that all the F-Curves for the block will be visible
386  *      1) animdata check: for filtering animdata blocks only
387  *      2A) nla tracks: include animdata block's data as there are NLA tracks+strips there
388  *      2B) actions to convert to nla: include animdata block's data as there is an action that can be 
389  *              converted to a new NLA strip, and the filtering options allow this
390  *      3) drivers: include drivers from animdata block (for Drivers mode in Graph Editor)
391  *      4) normal keyframes: only when there is an active action
392  */
393 #define ANIMDATA_FILTER_CASES(id, adtOk, nlaOk, driversOk, keysOk) \
394         {\
395                 if ((id)->adt) {\
396                         if (!(filter_mode & ANIMFILTER_CURVEVISIBLE) || !((id)->adt->flag & ADT_CURVES_NOT_VISIBLE)) {\
397                                 if (filter_mode & ANIMFILTER_ANIMDATA) {\
398                                         adtOk\
399                                 }\
400                                 else if (ads->filterflag & ADS_FILTER_ONLYNLA) {\
401                                         if (ANIMDATA_HAS_NLA(id)) {\
402                                                 nlaOk\
403                                         }\
404                                         else if (!(ads->filterflag & ADS_FILTER_NLA_NOACT) && ANIMDATA_HAS_KEYS(id)) {\
405                                                 nlaOk\
406                                         }\
407                                 }\
408                                 else if (ads->filterflag & ADS_FILTER_ONLYDRIVERS) {\
409                                         if (ANIMDATA_HAS_DRIVERS(id)) {\
410                                                 driversOk\
411                                         }\
412                                 }\
413                                 else {\
414                                         if (ANIMDATA_HAS_KEYS(id)) {\
415                                                 keysOk\
416                                         }\
417                                 }\
418                         }\
419                 }\
420         }
421
422
423 /* quick macro to add a pointer to an AnimData block as a channel */
424 #define ANIMDATA_ADD_ANIMDATA(id) \
425         {\
426                 ale= make_new_animlistelem((id)->adt, ANIMTYPE_ANIMDATA, NULL, ANIMTYPE_NONE, (ID *)id);\
427                 if (ale) {\
428                         BLI_addtail(anim_data, ale);\
429                         items++;\
430                 }\
431         }
432         
433 /* quick macro to test if an anim-channel representing an AnimData block is suitably active */
434 #define ANIMCHANNEL_ACTIVEOK(ale) \
435         ( !(filter_mode & ANIMFILTER_ACTIVE) || !(ale->adt) || (ale->adt->flag & ADT_UI_ACTIVE) )
436
437 /* quick macro to test if an anim-channel (F-Curve, Group, etc.) is selected in an acceptable way */
438 #define ANIMCHANNEL_SELOK(test_func) \
439                 ( !(filter_mode & (ANIMFILTER_SEL|ANIMFILTER_UNSEL)) || \
440                   ((filter_mode & ANIMFILTER_SEL) && test_func) || \
441                   ((filter_mode & ANIMFILTER_UNSEL) && test_func==0) ) 
442                   
443 /* quick macro to test if an anim-channel (F-Curve) is selected ok for editing purposes 
444  *      - _SELEDIT means that only selected curves will have visible+editable keyframes
445  */
446 // FIXME: this doesn't work cleanly yet...
447 #define ANIMCHANNEL_SELEDITOK(test_func) \
448                 ( !(filter_mode & ANIMFILTER_SELEDIT) || \
449                   (filter_mode & ANIMFILTER_CHANNELS) || \
450                   (test_func) )
451
452 /* ----------- 'Private' Stuff --------------- */
453
454 /* this function allocates memory for a new bAnimListElem struct for the 
455  * provided animation channel-data. 
456  */
457 bAnimListElem *make_new_animlistelem (void *data, short datatype, void *owner, short ownertype, ID *owner_id)
458 {
459         bAnimListElem *ale= NULL;
460         
461         /* only allocate memory if there is data to convert */
462         if (data) {
463                 /* allocate and set generic data */
464                 ale= MEM_callocN(sizeof(bAnimListElem), "bAnimListElem");
465                 
466                 ale->data= data;
467                 ale->type= datatype;
468                         // XXX what is the point of the owner data?
469                 ale->owner= owner;
470                 ale->ownertype= ownertype;
471                 
472                 ale->id= owner_id;
473                 ale->adt= BKE_animdata_from_id(owner_id);
474                 
475                 /* do specifics */
476                 switch (datatype) {
477                         case ANIMTYPE_SUMMARY:
478                         {
479                                 /* nothing to include for now... this is just a dummy wrappy around all the other channels 
480                                  * in the DopeSheet, and gets included at the start of the list
481                                  */
482                                 ale->key_data= NULL;
483                                 ale->datatype= ALE_ALL;
484                         }
485                                 break;
486                         
487                         case ANIMTYPE_SCENE:
488                         {
489                                 Scene *sce= (Scene *)data;
490                                 
491                                 ale->flag= sce->flag;
492                                 
493                                 ale->key_data= sce;
494                                 ale->datatype= ALE_SCE;
495                                 
496                                 ale->adt= BKE_animdata_from_id(data);
497                         }
498                                 break;
499                         case ANIMTYPE_OBJECT:
500                         {
501                                 Base *base= (Base *)data;
502                                 Object *ob= base->object;
503                                 
504                                 ale->flag= ob->flag;
505                                 
506                                 ale->key_data= ob;
507                                 ale->datatype= ALE_OB;
508                                 
509                                 ale->adt= BKE_animdata_from_id(&ob->id);
510                         }
511                                 break;
512                         case ANIMTYPE_FILLACTD:
513                         {
514                                 bAction *act= (bAction *)data;
515                                 
516                                 ale->flag= act->flag;
517                                 
518                                 ale->key_data= act;
519                                 ale->datatype= ALE_ACT;
520                         }
521                                 break;
522                         case ANIMTYPE_FILLDRIVERS:
523                         {
524                                 AnimData *adt= (AnimData *)data;
525                                 
526                                 ale->flag= adt->flag;
527                                 
528                                         // XXX... drivers don't show summary for now
529                                 ale->key_data= NULL;
530                                 ale->datatype= ALE_NONE;
531                         }
532                                 break;
533                         case ANIMTYPE_FILLMATD:
534                         {
535                                 Object *ob= (Object *)data;
536                                 
537                                 ale->flag= FILTER_MAT_OBJC(ob);
538                                 
539                                 ale->key_data= NULL;
540                                 ale->datatype= ALE_NONE;
541                         }
542                                 break;
543                         case ANIMTYPE_FILLPARTD:
544                         {
545                                 Object *ob= (Object *)data;
546                                 
547                                 ale->flag= FILTER_PART_OBJC(ob);
548                                 
549                                 ale->key_data= NULL;
550                                 ale->datatype= ALE_NONE;
551                         }
552                                 break;
553                         
554                         case ANIMTYPE_DSMAT:
555                         {
556                                 Material *ma= (Material *)data;
557                                 AnimData *adt= ma->adt;
558                                 
559                                 ale->flag= FILTER_MAT_OBJD(ma);
560                                 
561                                 ale->key_data= (adt) ? adt->action : NULL;
562                                 ale->datatype= ALE_ACT;
563                                 
564                                 ale->adt= BKE_animdata_from_id(data);
565                         }
566                                 break;
567                         case ANIMTYPE_DSLAM:
568                         {
569                                 Lamp *la= (Lamp *)data;
570                                 AnimData *adt= la->adt;
571                                 
572                                 ale->flag= FILTER_LAM_OBJD(la);
573                                 
574                                 ale->key_data= (adt) ? adt->action : NULL;
575                                 ale->datatype= ALE_ACT;
576                                 
577                                 ale->adt= BKE_animdata_from_id(data);
578                         }
579                                 break;
580                         case ANIMTYPE_DSCAM:
581                         {
582                                 Camera *ca= (Camera *)data;
583                                 AnimData *adt= ca->adt;
584                                 
585                                 ale->flag= FILTER_CAM_OBJD(ca);
586                                 
587                                 ale->key_data= (adt) ? adt->action : NULL;
588                                 ale->datatype= ALE_ACT;
589                                 
590                                 ale->adt= BKE_animdata_from_id(data);
591                         }
592                                 break;
593                         case ANIMTYPE_DSCUR:
594                         {
595                                 Curve *cu= (Curve *)data;
596                                 AnimData *adt= cu->adt;
597                                 
598                                 ale->flag= FILTER_CUR_OBJD(cu);
599                                 
600                                 ale->key_data= (adt) ? adt->action : NULL;
601                                 ale->datatype= ALE_ACT;
602                                 
603                                 ale->adt= BKE_animdata_from_id(data);
604                         }
605                                 break;
606                         case ANIMTYPE_DSARM:
607                         {
608                                 bArmature *arm= (bArmature *)data;
609                                 AnimData *adt= arm->adt;
610                                 
611                                 ale->flag= FILTER_ARM_OBJD(arm);
612                                 
613                                 ale->key_data= (adt) ? adt->action : NULL;
614                                 ale->datatype= ALE_ACT;
615                                 
616                                 ale->adt= BKE_animdata_from_id(data);
617                         }
618                                 break;
619                         case ANIMTYPE_DSSKEY:
620                         {
621                                 Key *key= (Key *)data;
622                                 AnimData *adt= key->adt;
623                                 
624                                 ale->flag= FILTER_SKE_OBJD(key); 
625                                 
626                                 ale->key_data= (adt) ? adt->action : NULL;
627                                 ale->datatype= ALE_ACT;
628                                 
629                                 ale->adt= BKE_animdata_from_id(data);
630                         }
631                                 break;
632                         case ANIMTYPE_DSWOR:
633                         {
634                                 World *wo= (World *)data;
635                                 AnimData *adt= wo->adt;
636                                 
637                                 ale->flag= FILTER_WOR_SCED(wo); 
638                                 
639                                 ale->key_data= (adt) ? adt->action : NULL;
640                                 ale->datatype= ALE_ACT;
641                                 
642                                 ale->adt= BKE_animdata_from_id(data);
643                         }
644                                 break;
645                         case ANIMTYPE_DSNTREE:
646                         {
647                                 bNodeTree *ntree= (bNodeTree *)data;
648                                 AnimData *adt= ntree->adt;
649                                 
650                                 ale->flag= FILTER_NTREE_SCED(ntree); 
651                                 
652                                 ale->key_data= (adt) ? adt->action : NULL;
653                                 ale->datatype= ALE_ACT;
654                                 
655                                 ale->adt= BKE_animdata_from_id(data);
656                         }
657                                 break;
658                         case ANIMTYPE_DSPART:
659                         {
660                                 ParticleSettings *part= (ParticleSettings*)ale->data;
661                                 AnimData *adt= part->adt;
662                                 
663                                 ale->flag= FILTER_PART_OBJD(part); 
664                                 
665                                 ale->key_data= (adt) ? adt->action : NULL;
666                                 ale->datatype= ALE_ACT;
667                                 
668                                 ale->adt= BKE_animdata_from_id(data);
669                         }
670                                 break;
671                                 
672                         case ANIMTYPE_GROUP:
673                         {
674                                 bActionGroup *agrp= (bActionGroup *)data;
675                                 
676                                 ale->flag= agrp->flag;
677                                 
678                                 ale->key_data= NULL;
679                                 ale->datatype= ALE_GROUP;
680                         }
681                                 break;
682                         case ANIMTYPE_FCURVE:
683                         {
684                                 FCurve *fcu= (FCurve *)data;
685                                 
686                                 ale->flag= fcu->flag;
687                                 
688                                 ale->key_data= fcu;
689                                 ale->datatype= ALE_FCURVE;
690                         }
691                                 break;
692                                 
693                         case ANIMTYPE_SHAPEKEY:
694                         {
695                                 KeyBlock *kb= (KeyBlock *)data;
696                                 Key *key= (Key *)ale->id;
697                                 
698                                 ale->flag= kb->flag;
699                                 
700                                 /* whether we have keyframes depends on whether there is a Key block to find it from */
701                                 if (key) {
702                                         /* index of shapekey is defined by place in key's list */
703                                         ale->index= BLI_findindex(&key->block, kb);
704                                         
705                                         /* the corresponding keyframes are from the animdata */
706                                         if (ale->adt && ale->adt->action) {
707                                                 bAction *act= ale->adt->action;
708                                                 char *rna_path = key_get_curValue_rnaPath(key, kb);
709                                                 
710                                                 /* try to find the F-Curve which corresponds to this exactly,
711                                                  * then free the MEM_alloc'd string
712                                                  */
713                                                 if (rna_path) {
714                                                         ale->key_data= (void *)list_find_fcurve(&act->curves, rna_path, 0);
715                                                         MEM_freeN(rna_path);
716                                                 }
717                                         }
718                                         ale->datatype= (ale->key_data)? ALE_FCURVE : ALE_NONE;
719                                 }
720                         }       
721                                 break;
722                         
723                         case ANIMTYPE_GPLAYER:
724                         {
725                                 bGPDlayer *gpl= (bGPDlayer *)data;
726                                 
727                                 ale->flag= gpl->flag;
728                                 
729                                 ale->key_data= NULL;
730                                 ale->datatype= ALE_GPFRAME;
731                         }
732                                 break;
733                                 
734                         case ANIMTYPE_NLATRACK:
735                         {
736                                 NlaTrack *nlt= (NlaTrack *)data;
737                                 
738                                 ale->flag= nlt->flag;
739                                 
740                                 ale->key_data= &nlt->strips;
741                                 ale->datatype= ALE_NLASTRIP;
742                         }
743                                 break;
744                         case ANIMTYPE_NLAACTION:
745                         {
746                                 /* nothing to include for now... nothing editable from NLA-perspective here */
747                                 ale->key_data= NULL;
748                                 ale->datatype= ALE_NONE;
749                         }
750                                 break;
751                 }
752         }
753         
754         /* return created datatype */
755         return ale;
756 }
757  
758 /* ----------------------------------------- */
759
760 static int skip_fcurve_selected_data(FCurve *fcu, ID *owner_id)
761 {
762         if (GS(owner_id->name) == ID_OB) {
763                 Object *ob= (Object *)owner_id;
764                 
765                 /* only consider if F-Curve involves pose.bones */
766                 if ((fcu->rna_path) && strstr(fcu->rna_path, "bones")) {
767                         bPoseChannel *pchan;
768                         char *bone_name;
769                         
770                         /* get bone-name, and check if this bone is selected */
771                         bone_name= BLI_getQuotedStr(fcu->rna_path, "bones[");
772                         pchan= get_pose_channel(ob->pose, bone_name);
773                         if (bone_name) MEM_freeN(bone_name);
774                         
775                         /* can only add this F-Curve if it is selected */
776                         if ((pchan) && (pchan->bone) && (pchan->bone->flag & BONE_SELECTED)==0)
777                                 return 1;
778                 }
779         }
780         else if (GS(owner_id->name) == ID_SCE) {
781                 Scene *scene = (Scene *)owner_id;
782                 
783                 /* only consider if F-Curve involves sequence_editor.sequences */
784                 if ((fcu->rna_path) && strstr(fcu->rna_path, "sequences_all")) {
785                         Editing *ed= seq_give_editing(scene, FALSE);
786                         Sequence *seq;
787                         char *seq_name;
788                         
789                         /* get strip name, and check if this strip is selected */
790                         seq_name= BLI_getQuotedStr(fcu->rna_path, "sequences_all[");
791                         seq = get_seq_by_name(ed->seqbasep, seq_name, FALSE);
792                         if (seq_name) MEM_freeN(seq_name);
793                         
794                         /* can only add this F-Curve if it is selected */
795                         if (seq==NULL || (seq->flag & SELECT)==0)
796                                 return 1;
797                 }
798         }
799         else if (GS(owner_id->name) == ID_NT) {
800                 bNodeTree *ntree = (bNodeTree *)owner_id;
801                 
802                 /* check for selected  nodes */
803                 if ((fcu->rna_path) && strstr(fcu->rna_path, "nodes")) {
804                         bNode *node;
805                         char *node_name;
806                         
807                         /* get strip name, and check if this strip is selected */
808                         node_name= BLI_getQuotedStr(fcu->rna_path, "nodes[");
809                         node = nodeFindNodebyName(ntree, node_name);
810                         if (node_name) MEM_freeN(node_name);
811                         
812                         /* can only add this F-Curve if it is selected */
813                         if ((node) && (node->flag & NODE_SELECT)==0)
814                                 return 1;
815                 }
816         }
817         return 0;
818 }
819
820 /* find the next F-Curve that is usable for inclusion */
821 static FCurve *animdata_filter_fcurve_next (bDopeSheet *ads, FCurve *first, bActionGroup *grp, int filter_mode, ID *owner_id)
822 {
823         FCurve *fcu = NULL;
824         
825         /* loop over F-Curves - assume that the caller of this has already checked that these should be included 
826          * NOTE: we need to check if the F-Curves belong to the same group, as this gets called for groups too...
827          */
828         for (fcu= first; ((fcu) && (fcu->grp==grp)); fcu= fcu->next) {
829                 /* special exception for Pose-Channel Based F-Curves:
830                  *      - the 'Only Selected' data filter should be applied to Pose-Channel data too, but those are
831                  *        represented as F-Curves. The way the filter for objects worked was to be the first check
832                  *        after 'normal' visibility, so this is done first here too...
833                  *      - we currently use an 'approximate' method for getting these F-Curves that doesn't require
834                  *        carefully checking the entire path
835                  *      - this will also affect things like Drivers, and also works for Bone Constraints
836                  */
837                 if ( ((ads) && (ads->filterflag & ADS_FILTER_ONLYSEL)) && (owner_id) ) {
838                         if (skip_fcurve_selected_data(fcu, owner_id))
839                                 continue;
840                 }
841                                 
842                 /* only include if visible (Graph Editor check, not channels check) */
843                 if (!(filter_mode & ANIMFILTER_CURVEVISIBLE) || (fcu->flag & FCURVE_VISIBLE)) {
844                         /* only work with this channel and its subchannels if it is editable */
845                         if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_FCU(fcu)) {
846                                 /* only include this curve if selected in a way consistent with the filtering requirements */
847                                 if ( ANIMCHANNEL_SELOK(SEL_FCU(fcu)) && ANIMCHANNEL_SELEDITOK(SEL_FCU(fcu)) ) {
848                                         /* only include if this curve is active */
849                                         if (!(filter_mode & ANIMFILTER_ACTIVE) || (fcu->flag & FCURVE_ACTIVE)) {
850                                                 /* this F-Curve can be used, so return it */
851                                                 return fcu;
852                                         }
853                                 }
854                         }
855                 }
856         }
857         
858         /* no (more) F-Curves from the list are suitable... */
859         return NULL;
860 }
861
862 static int animdata_filter_fcurves (ListBase *anim_data, bDopeSheet *ads, FCurve *first, bActionGroup *grp, void *owner, short ownertype, int filter_mode, ID *owner_id)
863 {
864         FCurve *fcu;
865         int items = 0;
866         
867         /* loop over every F-Curve able to be included 
868          *      - this for-loop works like this: 
869          *              1) the starting F-Curve is assigned to the fcu pointer so that we have a starting point to search from
870          *              2) the first valid F-Curve to start from (which may include the one given as 'first') in the remaining 
871          *                 list of F-Curves is found, and verified to be non-null
872          *              3) the F-Curve referenced by fcu pointer is added to the list
873          *              4) the fcu pointer is set to the F-Curve after the one we just added, so that we can keep going through 
874          *                 the rest of the F-Curve list without an eternal loop. Back to step 2 :)
875          */
876         for (fcu=first; ( (fcu = animdata_filter_fcurve_next(ads, fcu, grp, filter_mode, owner_id)) ); fcu=fcu->next)
877         {
878                 bAnimListElem *ale = make_new_animlistelem(fcu, ANIMTYPE_FCURVE, owner, ownertype, owner_id);
879                 
880                 if (ale) {
881                         BLI_addtail(anim_data, ale);
882                         items++;
883                 }
884         }
885         
886         /* return the number of items added to the list */
887         return items;
888 }
889
890 static int animdata_filter_action (ListBase *anim_data, bDopeSheet *ads, bAction *act, int filter_mode, void *owner, short ownertype, ID *owner_id)
891 {
892         bAnimListElem *ale=NULL;
893         bActionGroup *agrp;
894         FCurve *lastchan=NULL;
895         int items = 0;
896         
897         /* loop over groups */
898         // TODO: in future, should we expect to need nested groups?
899         for (agrp= act->groups.first; agrp; agrp= agrp->next) {
900                 FCurve *first_fcu;
901                 
902                 /* store reference to last channel of group */
903                 if (agrp->channels.last) 
904                         lastchan= agrp->channels.last;
905                 
906                 /* get the first F-Curve in this group we can start to use, 
907                  * and if there isn't any F-Curve to start from, then don't 
908                  * this group at all...
909                  *
910                  * exceptions for when we might not care whether there's anything inside this group or not
911                  *      - if we're interested in channels and their selections, in which case group channel should get considered too
912                  *        even if all its sub channels are hidden...
913                  */
914                 first_fcu = animdata_filter_fcurve_next(ads, agrp->channels.first, agrp, filter_mode, owner_id);
915                 
916                 if ( (filter_mode & (ANIMFILTER_SEL|ANIMFILTER_UNSEL)) ||
917                          (first_fcu) ) 
918                 {
919                         /* add this group as a channel first */
920                         if ((filter_mode & ANIMFILTER_CHANNELS) || !(filter_mode & ANIMFILTER_CURVESONLY)) {
921                                 /* check if filtering by selection */
922                                 if ( ANIMCHANNEL_SELOK(SEL_AGRP(agrp)) ) {
923                                         ale= make_new_animlistelem(agrp, ANIMTYPE_GROUP, NULL, ANIMTYPE_NONE, owner_id);
924                                         if (ale) {
925                                                 BLI_addtail(anim_data, ale);
926                                                 items++;
927                                         }
928                                 }
929                         }
930                         
931                         /* there are some situations, where only the channels of the action group should get considered */
932                         if (!(filter_mode & ANIMFILTER_ACTGROUPED) || (agrp->flag & AGRP_ACTIVE)) {
933                                 /* filters here are a bit convoulted...
934                                  *      - groups show a "summary" of keyframes beside their name which must accessable for tools which handle keyframes
935                                  *      - groups can be collapsed (and those tools which are only interested in channels rely on knowing that group is closed)
936                                  *
937                                  * cases when we should include F-Curves inside group:
938                                  *      - we don't care about visibility
939                                  *      - group is expanded
940                                  *      - we just need the F-Curves present
941                                  */
942                                 if ( (!(filter_mode & ANIMFILTER_VISIBLE) || EXPANDED_AGRP(agrp)) || (filter_mode & ANIMFILTER_CURVESONLY) ) 
943                                 {
944                                         /* for the Graph Editor, curves may be set to not be visible in the view to lessen clutter,
945                                          * but to do this, we need to check that the group doesn't have it's not-visible flag set preventing 
946                                          * all its sub-curves to be shown
947                                          */
948                                         if ( !(filter_mode & ANIMFILTER_CURVEVISIBLE) || !(agrp->flag & AGRP_NOTVISIBLE) )
949                                         {
950                                                 if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_AGRP(agrp)) {
951                                                         items += animdata_filter_fcurves(anim_data, ads, first_fcu, agrp, owner, ownertype, filter_mode, owner_id);
952                                                 }
953                                         }
954                                 }
955                         }
956                 }
957         }
958         
959         /* loop over un-grouped F-Curves (only if we're not only considering those channels in the animive group) */
960         if (!(filter_mode & ANIMFILTER_ACTGROUPED))  {
961                 // XXX the 'owner' info here needs review...
962                 items += animdata_filter_fcurves(anim_data, ads, (lastchan)?(lastchan->next):(act->curves.first), NULL, owner, ownertype, filter_mode, owner_id);
963         }
964         
965         /* return the number of items added to the list */
966         return items;
967 }
968
969 /* Include NLA-Data for NLA-Editor:
970  *      - when ANIMFILTER_CHANNELS is used, that means we should be filtering the list for display
971  *        Although the evaluation order is from the first track to the last and then apply the Action on top,
972  *        we present this in the UI as the Active Action followed by the last track to the first so that we 
973  *        get the evaluation order presented as per a stack.
974  *      - for normal filtering (i.e. for editing), we only need the NLA-tracks but they can be in 'normal' evaluation
975  *        order, i.e. first to last. Otherwise, some tools may get screwed up.
976  */
977 static int animdata_filter_nla (ListBase *anim_data, bDopeSheet *ads, AnimData *adt, int filter_mode, void *owner, short ownertype, ID *owner_id)
978 {
979         bAnimListElem *ale;
980         NlaTrack *nlt;
981         NlaTrack *first=NULL, *next=NULL;
982         int items = 0;
983         
984         /* if showing channels, include active action */
985         if (filter_mode & ANIMFILTER_CHANNELS) {
986                 /* there isn't really anything editable here, so skip if need editable */
987                 // TODO: currently, selection isn't checked since it doesn't matter
988                 if ((filter_mode & ANIMFILTER_FOREDIT) == 0) { 
989                         /* just add the action track now (this MUST appear for drawing)
990                          *      - as AnimData may not have an action, we pass a dummy pointer just to get the list elem created, then
991                          *        overwrite this with the real value - REVIEW THIS...
992                          */
993                         ale= make_new_animlistelem((void *)(&adt->action), ANIMTYPE_NLAACTION, owner, ownertype, owner_id);
994                         ale->data= (adt->action) ? adt->action : NULL;
995                                 
996                         if (ale) {
997                                 BLI_addtail(anim_data, ale);
998                                 items++;
999                         }
1000                 }
1001                 
1002                 /* first track to include will be the last one if we're filtering by channels */
1003                 first= adt->nla_tracks.last;
1004         }
1005         else {
1006                 /* first track to include will the the first one (as per normal) */
1007                 first= adt->nla_tracks.first;
1008         }
1009         
1010         /* loop over NLA Tracks - assume that the caller of this has already checked that these should be included */
1011         for (nlt= first; nlt; nlt= next) {
1012                 /* 'next' NLA-Track to use depends on whether we're filtering for drawing or not */
1013                 if (filter_mode & ANIMFILTER_CHANNELS) 
1014                         next= nlt->prev;
1015                 else
1016                         next= nlt->next;
1017                 
1018                 /* if we're in NLA-tweakmode, don't show this track if it was disabled (due to tweaking) for now 
1019                  *      - active track should still get shown though (even though it has disabled flag set)
1020                  */
1021                 // FIXME: the channels after should still get drawn, just 'differently', and after an active-action channel
1022                 if ((adt->flag & ADT_NLA_EDIT_ON) && (nlt->flag & NLATRACK_DISABLED) && !(nlt->flag & NLATRACK_ACTIVE))
1023                         continue;
1024                 
1025                 /* only work with this channel and its subchannels if it is editable */
1026                 if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_NLT(nlt)) {
1027                         /* only include this track if selected in a way consistent with the filtering requirements */
1028                         if ( ANIMCHANNEL_SELOK(SEL_NLT(nlt)) ) {
1029                                 /* only include if this track is active */
1030                                 if (!(filter_mode & ANIMFILTER_ACTIVE) || (nlt->flag & NLATRACK_ACTIVE)) {
1031                                         ale= make_new_animlistelem(nlt, ANIMTYPE_NLATRACK, owner, ownertype, owner_id);
1032                                                 
1033                                         if (ale) {
1034                                                 BLI_addtail(anim_data, ale);
1035                                                 items++;
1036                                         }
1037                                 }
1038                         }
1039                 }
1040         }
1041         
1042         /* return the number of items added to the list */
1043         return items;
1044 }
1045
1046 /* Include ShapeKey Data for ShapeKey Editor */
1047 static int animdata_filter_shapekey (ListBase *anim_data, Key *key, int filter_mode)
1048 {
1049         bAnimListElem *ale;
1050         int items = 0;
1051         
1052         /* check if channels or only F-Curves */
1053         if ((filter_mode & ANIMFILTER_CURVESONLY) == 0) {
1054                 KeyBlock *kb;
1055                 
1056                 /* loop through the channels adding ShapeKeys as appropriate */
1057                 for (kb= key->block.first; kb; kb= kb->next) {
1058                         /* skip the first one, since that's the non-animateable basis */
1059                         // XXX maybe in future this may become handy?
1060                         if (kb == key->block.first) continue;
1061                         
1062                         /* only work with this channel and its subchannels if it is editable */
1063                         if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_SHAPEKEY(kb)) {
1064                                 /* only include this track if selected in a way consistent with the filtering requirements */
1065                                 if ( ANIMCHANNEL_SELOK(SEL_SHAPEKEY(kb)) ) {
1066                                         // TODO: consider 'active' too?
1067                                         
1068                                         /* owner-id here must be key so that the F-Curve can be resolved... */
1069                                         ale= make_new_animlistelem(kb, ANIMTYPE_SHAPEKEY, NULL, ANIMTYPE_NONE, (ID *)key);
1070                                         
1071                                         if (ale) {
1072                                                 BLI_addtail(anim_data, ale);
1073                                                 items++;
1074                                         }
1075                                 }
1076                         }
1077                 }
1078         }
1079         else {
1080                 /* just use the action associated with the shapekey */
1081                 // FIXME: is owner-id and having no owner/dopesheet really fine?
1082                 if (key->adt) {
1083                         if (filter_mode & ANIMFILTER_ANIMDATA)
1084                                 ANIMDATA_ADD_ANIMDATA(key)
1085                         else if (key->adt->action)
1086                                 items= animdata_filter_action(anim_data, NULL, key->adt->action, filter_mode, NULL, ANIMTYPE_NONE, (ID *)key);
1087                 }
1088         }
1089         
1090         /* return the number of items added to the list */
1091         return items;
1092 }
1093
1094 #if 0
1095 // FIXME: switch this to use the bDopeSheet...
1096 static int animdata_filter_gpencil (ListBase *anim_data, bScreen *sc, int filter_mode)
1097 {
1098         bAnimListElem *ale;
1099         ScrArea *sa, *curarea;
1100         bGPdata *gpd;
1101         bGPDlayer *gpl;
1102         int items = 0;
1103         
1104         /* check if filtering types are appropriate */
1105         {
1106                 /* special hack for fullscreen area (which must be this one then):
1107                  *      - we use the curarea->full as screen to get spaces from, since the
1108                  *        old (pre-fullscreen) screen was stored there...
1109                  *      - this is needed as all data would otherwise disappear
1110                  */
1111                 // XXX need to get new alternative for curarea
1112                 if ((curarea->full) && (curarea->spacetype==SPACE_ACTION))
1113                         sc= curarea->full;
1114                 
1115                 /* loop over spaces in current screen, finding gpd blocks (could be slow!) */
1116                 for (sa= sc->areabase.first; sa; sa= sa->next) {
1117                         /* try to get gp data */
1118                         // XXX need to put back grease pencil api...
1119                         gpd= gpencil_data_get_active(sa);
1120                         if (gpd == NULL) continue;
1121                         
1122                         /* add gpd as channel too (if for drawing, and it has layers) */
1123                         if ((filter_mode & ANIMFILTER_CHANNELS) && (gpd->layers.first)) {
1124                                 /* add to list */
1125                                 ale= make_new_animlistelem(gpd, ANIMTYPE_GPDATABLOCK, sa, ANIMTYPE_SPECIALDATA);
1126                                 if (ale) {
1127                                         BLI_addtail(anim_data, ale);
1128                                         items++;
1129                                 }
1130                         }
1131                         
1132                         /* only add layers if they will be visible (if drawing channels) */
1133                         if ( !(filter_mode & ANIMFILTER_VISIBLE) || (EXPANDED_GPD(gpd)) ) {
1134                                 /* loop over layers as the conditions are acceptable */
1135                                 for (gpl= gpd->layers.first; gpl; gpl= gpl->next) {
1136                                         /* only if selected */
1137                                         if ( ANIMCHANNEL_SELOK(SEL_GPL(gpl)) ) {
1138                                                 /* only if editable */
1139                                                 if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_GPL(gpl)) {
1140                                                         /* add to list */
1141                                                         ale= make_new_animlistelem(gpl, ANIMTYPE_GPLAYER, gpd, ANIMTYPE_GPDATABLOCK);
1142                                                         if (ale) {
1143                                                                 BLI_addtail(anim_data, ale);
1144                                                                 items++;
1145                                                         }
1146                                                 }
1147                                         }
1148                                 }
1149                         }
1150                 }
1151         }
1152         
1153         /* return the number of items added to the list */
1154         return items;
1155 }
1156 #endif 
1157
1158
1159 static int animdata_filter_dopesheet_mats (ListBase *anim_data, bDopeSheet *ads, Base *base, int filter_mode)
1160 {
1161         ListBase mats = {NULL, NULL};
1162         LinkData *ld;
1163         
1164         bAnimListElem *ale=NULL;
1165         Object *ob= base->object;
1166         int items=0, a=0;
1167         
1168         /* firstly check that we actuallly have some materials, by gathering all materials in a temp list */
1169         for (a=0; a < ob->totcol; a++) {
1170                 Material *ma= give_current_material(ob, a);
1171                 short ok = 0;
1172                 
1173                 /* for now, if no material returned, skip (this shouldn't confuse the user I hope) */
1174                 if (ELEM(NULL, ma, ma->adt)) 
1175                         continue;
1176                 
1177                 /* check if ok */
1178                 ANIMDATA_FILTER_CASES(ma, 
1179                         { /* AnimData blocks - do nothing... */ },
1180                         ok=1;, 
1181                         ok=1;, 
1182                         ok=1;)
1183                 if (ok == 0) continue;
1184                 
1185                 /* make a temp list elem for this */
1186                 ld= MEM_callocN(sizeof(LinkData), "DopeSheet-MaterialCache");
1187                 ld->data= ma;
1188                 BLI_addtail(&mats, ld);
1189         }
1190         
1191         /* if there were no channels found, no need to carry on */
1192         if (mats.first == NULL)
1193                 return 0;
1194         
1195         /* include materials-expand widget? */
1196         if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
1197                 ale= make_new_animlistelem(ob, ANIMTYPE_FILLMATD, base, ANIMTYPE_OBJECT, (ID *)ob);
1198                 if (ale) {
1199                         BLI_addtail(anim_data, ale);
1200                         items++;
1201                 }
1202         }
1203         
1204         /* add materials? */
1205         if (FILTER_MAT_OBJC(ob) || (filter_mode & ANIMFILTER_CURVESONLY)) {
1206                 /* for each material in cache, add channels  */
1207                 for (ld= mats.first; ld; ld= ld->next) {
1208                         Material *ma= (Material *)ld->data;
1209                         
1210                         /* include material-expand widget? */
1211                         // hmm... do we need to store the index of this material in the array anywhere?
1212                         if (filter_mode & ANIMFILTER_CHANNELS) {
1213                                 /* check if filtering by active status */
1214                                 if ANIMCHANNEL_ACTIVEOK(ma) {
1215                                         ale= make_new_animlistelem(ma, ANIMTYPE_DSMAT, base, ANIMTYPE_OBJECT, (ID *)ma);
1216                                         if (ale) {
1217                                                 BLI_addtail(anim_data, ale);
1218                                                 items++;
1219                                         }
1220                                 }
1221                         }
1222                         
1223                         /* add material's animation data */
1224                         if (!(filter_mode & ANIMFILTER_VISIBLE) || FILTER_MAT_OBJD(ma) || (filter_mode & ANIMFILTER_CURVESONLY)) {
1225                                 ANIMDATA_FILTER_CASES(ma, 
1226                                         { /* AnimData blocks - do nothing... */ },
1227                                         items += animdata_filter_nla(anim_data, ads, ma->adt, filter_mode, ma, ANIMTYPE_DSMAT, (ID *)ma);, 
1228                                         items += animdata_filter_fcurves(anim_data, ads, ma->adt->drivers.first, NULL, ma, ANIMTYPE_DSMAT, filter_mode, (ID *)ma);, 
1229                                         items += animdata_filter_action(anim_data, ads, ma->adt->action, filter_mode, ma, ANIMTYPE_DSMAT, (ID *)ma);)
1230                         }
1231                 }
1232         }
1233         
1234         /* free cache */
1235         BLI_freelistN(&mats);
1236         
1237         /* return the number of items added to the list */
1238         return items;
1239 }
1240
1241 static int animdata_filter_dopesheet_particles (ListBase *anim_data, bDopeSheet *ads, Base *base, int filter_mode)
1242 {
1243         bAnimListElem *ale=NULL;
1244         Object *ob= base->object;
1245         ParticleSystem *psys = ob->particlesystem.first;
1246         int items= 0, first = 1;
1247
1248         for(; psys; psys=psys->next) {
1249                 short ok = 0;
1250
1251                 if(ELEM(NULL, psys->part, psys->part->adt))
1252                         continue;
1253
1254                 ANIMDATA_FILTER_CASES(psys->part,
1255                         { /* AnimData blocks - do nothing... */ },
1256                         ok=1;, 
1257                         ok=1;, 
1258                         ok=1;)
1259                 if (ok == 0) continue;
1260
1261                 /* include particles-expand widget? */
1262                 if (first && (filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
1263                         ale= make_new_animlistelem(ob, ANIMTYPE_FILLPARTD, base, ANIMTYPE_OBJECT, (ID *)ob);
1264                         if (ale) {
1265                                 BLI_addtail(anim_data, ale);
1266                                 items++;
1267                         }
1268                         first = 0;
1269                 }
1270                 
1271                 /* add particle settings? */
1272                 if (FILTER_PART_OBJC(ob) || (filter_mode & ANIMFILTER_CURVESONLY)) {
1273                         if ((filter_mode & ANIMFILTER_CHANNELS)) {
1274                                 /* check if filtering by active status */
1275                                 if ANIMCHANNEL_ACTIVEOK(psys->part) {
1276                                         ale = make_new_animlistelem(psys->part, ANIMTYPE_DSPART, base, ANIMTYPE_OBJECT, (ID *)psys->part);
1277                                         if (ale) {
1278                                                 BLI_addtail(anim_data, ale);
1279                                                 items++;
1280                                         }
1281                                 }
1282                         }
1283                         
1284                         if (!(filter_mode & ANIMFILTER_VISIBLE) || FILTER_PART_OBJD(psys->part) || (filter_mode & ANIMFILTER_CURVESONLY)) {
1285                                 ANIMDATA_FILTER_CASES(psys->part,
1286                                         { /* AnimData blocks - do nothing... */ },
1287                                         items += animdata_filter_nla(anim_data, ads, psys->part->adt, filter_mode, psys->part, ANIMTYPE_DSPART, (ID *)psys->part);, 
1288                                         items += animdata_filter_fcurves(anim_data, ads, psys->part->adt->drivers.first, NULL, psys->part, ANIMTYPE_DSPART, filter_mode, (ID *)psys->part);, 
1289                                         items += animdata_filter_action(anim_data, ads, psys->part->adt->action, filter_mode, psys->part, ANIMTYPE_DSPART, (ID *)psys->part);)
1290                         }
1291                 }
1292         }
1293         
1294         /* return the number of items added to the list */
1295         return items;
1296 }
1297
1298 static int animdata_filter_dopesheet_obdata (ListBase *anim_data, bDopeSheet *ads, Base *base, int filter_mode)
1299 {
1300         bAnimListElem *ale=NULL;
1301         Object *ob= base->object;
1302         IdAdtTemplate *iat= ob->data;
1303         AnimData *adt= iat->adt;
1304         short type=0, expanded=0;
1305         int items= 0;
1306         
1307         /* get settings based on data type */
1308         switch (ob->type) {
1309                 case OB_CAMERA: /* ------- Camera ------------ */
1310                 {
1311                         Camera *ca= (Camera *)ob->data;
1312                         
1313                         type= ANIMTYPE_DSCAM;
1314                         expanded= FILTER_CAM_OBJD(ca);
1315                 }
1316                         break;
1317                 case OB_LAMP: /* ---------- Lamp ----------- */
1318                 {
1319                         Lamp *la= (Lamp *)ob->data;
1320                         
1321                         type= ANIMTYPE_DSLAM;
1322                         expanded= FILTER_LAM_OBJD(la);
1323                 }
1324                         break;
1325                 case OB_CURVE: /* ------- Curve ---------- */
1326                 {
1327                         Curve *cu= (Curve *)ob->data;
1328                         
1329                         type= ANIMTYPE_DSCUR;
1330                         expanded= FILTER_CUR_OBJD(cu);
1331                 }
1332                         break;
1333                 case OB_MBALL: /* ------- MetaBall ---------- */
1334                 {
1335                         MetaBall *mb= (MetaBall *)ob->data;
1336                         
1337                         type= ANIMTYPE_DSMBALL;
1338                         expanded= FILTER_MBALL_OBJD(mb);
1339                 }
1340                         break;
1341                 case OB_ARMATURE: /* ------- Armature ---------- */
1342                 {
1343                         bArmature *arm= (bArmature *)ob->data;
1344                         
1345                         type= ANIMTYPE_DSARM;
1346                         expanded= FILTER_ARM_OBJD(arm);
1347                 }
1348                         break;
1349         }
1350         
1351         /* special exception for drivers instead of action */
1352         if (ads->filterflag & ADS_FILTER_ONLYDRIVERS)
1353                 expanded= EXPANDED_DRVD(adt);
1354         
1355         /* include data-expand widget? */
1356         if ((filter_mode & ANIMFILTER_CURVESONLY) == 0) {       
1357                 /* check if filtering by active status */
1358                 if ANIMCHANNEL_ACTIVEOK(iat) {
1359                         ale= make_new_animlistelem(iat, type, base, ANIMTYPE_OBJECT, (ID *)iat);
1360                         if (ale) BLI_addtail(anim_data, ale);
1361                 }
1362         }
1363         
1364         /* add object-data animation channels? */
1365         if (!(filter_mode & ANIMFILTER_VISIBLE) || (expanded) || (filter_mode & ANIMFILTER_CURVESONLY)) {
1366                 /* filtering for channels - nla, drivers, keyframes */
1367                 ANIMDATA_FILTER_CASES(iat, 
1368                         { /* AnimData blocks - do nothing... */ },
1369                         items+= animdata_filter_nla(anim_data, ads, iat->adt, filter_mode, iat, type, (ID *)iat);,
1370                         items+= animdata_filter_fcurves(anim_data, ads, adt->drivers.first, NULL, iat, type, filter_mode, (ID *)iat);, 
1371                         items += animdata_filter_action(anim_data, ads, iat->adt->action, filter_mode, iat, type, (ID *)iat);)
1372         }
1373         
1374         /* return the number of items added to the list */
1375         return items;
1376 }
1377
1378 static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, Base *base, int filter_mode)
1379 {
1380         bAnimListElem *ale=NULL;
1381         AnimData *adt = NULL;
1382         Object *ob= base->object;
1383         Key *key= ob_get_key(ob);
1384         short obdata_ok = 0;
1385         int items = 0;
1386         
1387         /* add this object as a channel first */
1388         if ((filter_mode & (ANIMFILTER_CURVESONLY|ANIMFILTER_NLATRACKS)) == 0) {
1389                 /* check if filtering by selection */
1390                 if ANIMCHANNEL_SELOK((base->flag & SELECT)) {
1391                         /* check if filtering by active status */
1392                         if ANIMCHANNEL_ACTIVEOK(ob) {
1393                                 ale= make_new_animlistelem(base, ANIMTYPE_OBJECT, NULL, ANIMTYPE_NONE, (ID *)ob);
1394                                 if (ale) {
1395                                         BLI_addtail(anim_data, ale);
1396                                         items++;
1397                                 }
1398                         }
1399                 }
1400         }
1401         
1402         /* if collapsed, don't go any further (unless adding keyframes only) */
1403         if ( ((filter_mode & ANIMFILTER_VISIBLE) && EXPANDED_OBJC(ob) == 0) &&
1404                  !(filter_mode & (ANIMFILTER_CURVESONLY|ANIMFILTER_NLATRACKS)) )
1405                 return items;
1406         
1407         /* Action, Drivers, or NLA */
1408         if (ob->adt) {
1409                 adt= ob->adt;
1410                 ANIMDATA_FILTER_CASES(ob,
1411                         { /* AnimData blocks - do nothing... */ },
1412                         { /* nla */
1413                                 /* add NLA tracks */
1414                                 items += animdata_filter_nla(anim_data, ads, adt, filter_mode, ob, ANIMTYPE_OBJECT, (ID *)ob);
1415                         },
1416                         { /* drivers */
1417                                 /* include drivers-expand widget? */
1418                                 if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
1419                                         ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLDRIVERS, base, ANIMTYPE_OBJECT, (ID *)ob);
1420                                         if (ale) {
1421                                                 BLI_addtail(anim_data, ale);
1422                                                 items++;
1423                                         }
1424                                 }
1425                                 
1426                                 /* add F-Curve channels (drivers are F-Curves) */
1427                                 if (!(filter_mode & ANIMFILTER_VISIBLE) || EXPANDED_DRVD(adt) || !(filter_mode & ANIMFILTER_CHANNELS)) {
1428                                         // need to make the ownertype normal object here... (maybe type should be a separate one for clarity?)
1429                                         items += animdata_filter_fcurves(anim_data, ads, adt->drivers.first, NULL, ob, ANIMTYPE_OBJECT, filter_mode, (ID *)ob);
1430                                 }
1431                         },
1432                         { /* action (keyframes) */
1433                                 /* include action-expand widget? */
1434                                 if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
1435                                         ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLACTD, base, ANIMTYPE_OBJECT, (ID *)ob);
1436                                         if (ale) {
1437                                                 BLI_addtail(anim_data, ale);
1438                                                 items++;
1439                                         }
1440                                 }
1441                                 
1442                                 /* add F-Curve channels? */
1443                                 if (!(filter_mode & ANIMFILTER_VISIBLE) || EXPANDED_ACTC(adt->action) || !(filter_mode & ANIMFILTER_CHANNELS)) {
1444                                         // need to make the ownertype normal object here... (maybe type should be a separate one for clarity?)
1445                                         items += animdata_filter_action(anim_data, ads, adt->action, filter_mode, ob, ANIMTYPE_OBJECT, (ID *)ob); 
1446                                 }
1447                         }
1448                 );
1449         }
1450         
1451         
1452         /* ShapeKeys? */
1453         if ((key) && !(ads->filterflag & ADS_FILTER_NOSHAPEKEYS)) {
1454                 adt= key->adt;
1455                 ANIMDATA_FILTER_CASES(key,
1456                         { /* AnimData blocks - do nothing... */ },
1457                         { /* nla */
1458                                 /* include shapekey-expand widget? */
1459                                 if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
1460                                         /* check if filtering by active status */
1461                                         if ANIMCHANNEL_ACTIVEOK(key) {
1462                                                 ale= make_new_animlistelem(key, ANIMTYPE_DSSKEY, base, ANIMTYPE_OBJECT, (ID *)ob);
1463                                                 if (ale) {
1464                                                         BLI_addtail(anim_data, ale);
1465                                                         items++;
1466                                                 }
1467                                         }
1468                                 }
1469                                 
1470                                 /* add NLA tracks - only if expanded or so */
1471                                 if (!(filter_mode & ANIMFILTER_VISIBLE) || FILTER_SKE_OBJD(key) || (filter_mode & ANIMFILTER_CURVESONLY))
1472                                         items += animdata_filter_nla(anim_data, ads, adt, filter_mode, ob, ANIMTYPE_OBJECT, (ID *)ob);
1473                         },
1474                         { /* drivers */
1475                                 /* include shapekey-expand widget? */
1476                                 if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
1477                                         ale= make_new_animlistelem(key, ANIMTYPE_DSSKEY, base, ANIMTYPE_OBJECT, (ID *)ob);
1478                                         if (ale) {
1479                                                 BLI_addtail(anim_data, ale);
1480                                                 items++;
1481                                         }
1482                                 }
1483                                 
1484                                 /* add channels */
1485                                 if (!(filter_mode & ANIMFILTER_VISIBLE) || FILTER_SKE_OBJD(key) || (filter_mode & ANIMFILTER_CURVESONLY)) {
1486                                         items += animdata_filter_fcurves(anim_data, ads, adt->drivers.first, NULL, key, ANIMTYPE_DSSKEY, filter_mode, (ID *)key);
1487                                 }
1488                         },
1489                         { /* action (keyframes) */
1490                                 /* include shapekey-expand widget? */
1491                                 if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
1492                                         /* check if filtering by active status */
1493                                         if ANIMCHANNEL_ACTIVEOK(key) {
1494                                                 ale= make_new_animlistelem(key, ANIMTYPE_DSSKEY, base, ANIMTYPE_OBJECT, (ID *)ob);
1495                                                 if (ale) {
1496                                                         BLI_addtail(anim_data, ale);
1497                                                         items++;
1498                                                 }
1499                                         }
1500                                 }
1501                                 
1502                                 /* add channels */
1503                                 if (!(filter_mode & ANIMFILTER_VISIBLE) || FILTER_SKE_OBJD(key) || (filter_mode & ANIMFILTER_CURVESONLY)) {
1504                                         items += animdata_filter_action(anim_data, ads, adt->action, filter_mode, key, ANIMTYPE_DSSKEY, (ID *)key); 
1505                                 }
1506                         }
1507                 );
1508         }
1509
1510         /* Materials? */
1511         if ((ob->totcol) && !(ads->filterflag & ADS_FILTER_NOMAT))
1512                 items += animdata_filter_dopesheet_mats(anim_data, ads, base, filter_mode);
1513         
1514         /* Object Data */
1515         switch (ob->type) {
1516                 case OB_CAMERA: /* ------- Camera ------------ */
1517                 {
1518                         Camera *ca= (Camera *)ob->data;
1519                         
1520                         if ((ads->filterflag & ADS_FILTER_NOCAM) == 0) {
1521                                 ANIMDATA_FILTER_CASES(ca,
1522                                         { /* AnimData blocks - do nothing... */ },
1523                                         obdata_ok= 1;,
1524                                         obdata_ok= 1;,
1525                                         obdata_ok= 1;)
1526                         }
1527                 }
1528                         break;
1529                 case OB_LAMP: /* ---------- Lamp ----------- */
1530                 {
1531                         Lamp *la= (Lamp *)ob->data;
1532                         
1533                         if ((ads->filterflag & ADS_FILTER_NOLAM) == 0) {
1534                                 ANIMDATA_FILTER_CASES(la,
1535                                         { /* AnimData blocks - do nothing... */ },
1536                                         obdata_ok= 1;,
1537                                         obdata_ok= 1;,
1538                                         obdata_ok= 1;)
1539                         }
1540                 }
1541                         break;
1542                 case OB_CURVE: /* ------- Curve ---------- */
1543                 {
1544                         Curve *cu= (Curve *)ob->data;
1545                         
1546                         if ((ads->filterflag & ADS_FILTER_NOCUR) == 0) {
1547                                 ANIMDATA_FILTER_CASES(cu,
1548                                         { /* AnimData blocks - do nothing... */ },
1549                                         obdata_ok= 1;,
1550                                         obdata_ok= 1;,
1551                                         obdata_ok= 1;)
1552                         }
1553                 }
1554                         break;
1555                 case OB_MBALL: /* ------- MetaBall ---------- */
1556                 {
1557                         MetaBall *mb= (MetaBall *)ob->data;
1558                         
1559                         if ((ads->filterflag & ADS_FILTER_NOMBA) == 0) {
1560                                 ANIMDATA_FILTER_CASES(mb,
1561                                         { /* AnimData blocks - do nothing... */ },
1562                                         obdata_ok= 1;,
1563                                         obdata_ok= 1;,
1564                                         obdata_ok= 1;)
1565                         }
1566                 }
1567                         break;
1568                 case OB_ARMATURE: /* ------- Armature ---------- */
1569                 {
1570                         bArmature *arm= (bArmature *)ob->data;
1571                         
1572                         if ((ads->filterflag & ADS_FILTER_NOARM) == 0) {
1573                                 ANIMDATA_FILTER_CASES(arm,
1574                                         { /* AnimData blocks - do nothing... */ },
1575                                         obdata_ok= 1;,
1576                                         obdata_ok= 1;,
1577                                         obdata_ok= 1;)
1578                         }
1579                 }
1580                         break;
1581         }
1582         if (obdata_ok) 
1583                 items += animdata_filter_dopesheet_obdata(anim_data, ads, base, filter_mode);
1584
1585         /* particles */
1586         if (ob->particlesystem.first && !(ads->filterflag & ADS_FILTER_NOPART))
1587                 items += animdata_filter_dopesheet_particles(anim_data, ads, base, filter_mode);
1588         
1589         /* return the number of items added to the list */
1590         return items;
1591 }       
1592
1593 static int animdata_filter_dopesheet_scene (ListBase *anim_data, bDopeSheet *ads, Scene *sce, int filter_mode)
1594 {
1595         World *wo= sce->world;
1596         bNodeTree *ntree= sce->nodetree;
1597         AnimData *adt= NULL;
1598         bAnimListElem *ale;
1599         int items = 0;
1600         
1601         /* add scene as a channel first (even if we aren't showing scenes we still need to show the scene's sub-data */
1602         if ((filter_mode & (ANIMFILTER_CURVESONLY|ANIMFILTER_NLATRACKS)) == 0) {
1603                 /* check if filtering by selection */
1604                 if (ANIMCHANNEL_SELOK( (sce->flag & SCE_DS_SELECTED) )) {
1605                         ale= make_new_animlistelem(sce, ANIMTYPE_SCENE, NULL, ANIMTYPE_NONE, NULL);
1606                         if (ale) {
1607                                 BLI_addtail(anim_data, ale);
1608                                 items++;
1609                         }
1610                 }
1611         }
1612         
1613         /* if collapsed, don't go any further (unless adding keyframes only) */
1614         if ( (EXPANDED_SCEC(sce) == 0) && !(filter_mode & (ANIMFILTER_CURVESONLY|ANIMFILTER_NLATRACKS)) )
1615                 return items;
1616                 
1617         /* Action, Drivers, or NLA for Scene */
1618         if ((ads->filterflag & ADS_FILTER_NOSCE) == 0) {
1619                 adt= sce->adt;
1620                 ANIMDATA_FILTER_CASES(sce,
1621                         { /* AnimData blocks - do nothing... */ },
1622                         { /* nla */
1623                                 /* add NLA tracks */
1624                                 items += animdata_filter_nla(anim_data, ads, adt, filter_mode, sce, ANIMTYPE_SCENE, (ID *)sce);
1625                         },
1626                         { /* drivers */
1627                                 /* include drivers-expand widget? */
1628                                 if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
1629                                         ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLDRIVERS, sce, ANIMTYPE_SCENE, (ID *)sce);
1630                                         if (ale) {
1631                                                 BLI_addtail(anim_data, ale);
1632                                                 items++;
1633                                         }
1634                                 }
1635                                 
1636                                 /* add F-Curve channels (drivers are F-Curves) */
1637                                 if (EXPANDED_DRVD(adt) || !(filter_mode & ANIMFILTER_CHANNELS)) {
1638                                         items += animdata_filter_fcurves(anim_data, ads, adt->drivers.first, NULL, sce, ANIMTYPE_SCENE, filter_mode, (ID *)sce);
1639                                 }
1640                         },
1641                         { /* action */
1642                                 /* include action-expand widget? */
1643                                 if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
1644                                         ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLACTD, sce, ANIMTYPE_SCENE, (ID *)sce);
1645                                         if (ale) {
1646                                                 BLI_addtail(anim_data, ale);
1647                                                 items++;
1648                                         }
1649                                 }
1650                                 
1651                                 /* add F-Curve channels? */
1652                                 if (EXPANDED_ACTC(adt->action) || !(filter_mode & ANIMFILTER_CHANNELS)) {
1653                                         items += animdata_filter_action(anim_data, ads, adt->action, filter_mode, sce, ANIMTYPE_SCENE, (ID *)sce); 
1654                                 }
1655                         }
1656                 )
1657         }
1658         
1659         /* world */
1660         if ((wo && wo->adt) && !(ads->filterflag & ADS_FILTER_NOWOR)) {
1661                 /* Action, Drivers, or NLA for World */
1662                 adt= wo->adt;
1663                 ANIMDATA_FILTER_CASES(wo,
1664                         { /* AnimData blocks - do nothing... */ },
1665                         { /* nla */
1666                                 /* add NLA tracks */
1667                                 items += animdata_filter_nla(anim_data, ads, adt, filter_mode, wo, ANIMTYPE_DSWOR, (ID *)wo);
1668                         },
1669                         { /* drivers */
1670                                 /* include world-expand widget? */
1671                                 if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
1672                                         ale= make_new_animlistelem(wo, ANIMTYPE_DSWOR, sce, ANIMTYPE_SCENE, (ID *)wo);
1673                                         if (ale) {
1674                                                 BLI_addtail(anim_data, ale);
1675                                                 items++;
1676                                         }
1677                                 }
1678                                 
1679                                 /* add F-Curve channels (drivers are F-Curves) */
1680                                 if (FILTER_WOR_SCED(wo)/*EXPANDED_DRVD(adt)*/ || !(filter_mode & ANIMFILTER_CHANNELS)) {
1681                                         // XXX owner info is messed up now...
1682                                         items += animdata_filter_fcurves(anim_data, ads, adt->drivers.first, NULL, wo, ANIMTYPE_DSWOR, filter_mode, (ID *)wo);
1683                                 }
1684                         },
1685                         { /* action */
1686                                 /* include world-expand widget? */
1687                                 if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
1688                                         ale= make_new_animlistelem(wo, ANIMTYPE_DSWOR, sce, ANIMTYPE_SCENE, (ID *)sce);
1689                                         if (ale) {
1690                                                 BLI_addtail(anim_data, ale);
1691                                                 items++;
1692                                         }
1693                                 }
1694                                 
1695                                 /* add channels */
1696                                 if (FILTER_WOR_SCED(wo) || (filter_mode & ANIMFILTER_CURVESONLY)) {
1697                                         items += animdata_filter_action(anim_data, ads, adt->action, filter_mode, wo, ANIMTYPE_DSWOR, (ID *)wo); 
1698                                 }
1699                         }
1700                 )
1701         }
1702         /* nodetree */
1703         if ((ntree && ntree->adt) && !(ads->filterflag & ADS_FILTER_NONTREE)) {
1704                 /* Action, Drivers, or NLA for Nodetree */
1705                 adt= ntree->adt;
1706                 ANIMDATA_FILTER_CASES(ntree,
1707                         { /* AnimData blocks - do nothing... */ },
1708                         { /* nla */
1709                                 /* add NLA tracks */
1710                                 items += animdata_filter_nla(anim_data, ads, adt, filter_mode, ntree, ANIMTYPE_DSNTREE, (ID *)ntree);
1711                         },
1712                         { /* drivers */
1713                                 /* include nodetree-expand widget? */
1714                                 if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
1715                                         ale= make_new_animlistelem(ntree, ANIMTYPE_DSNTREE, sce, ANIMTYPE_SCENE, (ID *)ntree);
1716                                         if (ale) {
1717                                                 BLI_addtail(anim_data, ale);
1718                                                 items++;
1719                                         }
1720                                 }
1721                                 
1722                                 /* add F-Curve channels (drivers are F-Curves) */
1723                                 if (FILTER_NTREE_SCED(ntree)/*EXPANDED_DRVD(adt)*/ || !(filter_mode & ANIMFILTER_CHANNELS)) {
1724                                         // XXX owner info is messed up now...
1725                                         items += animdata_filter_fcurves(anim_data, ads, adt->drivers.first, NULL, ntree, ANIMTYPE_DSNTREE, filter_mode, (ID *)ntree);
1726                                 }
1727                         },
1728                         { /* action */
1729                                 /* include nodetree-expand widget? */
1730                                 if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
1731                                         ale= make_new_animlistelem(ntree, ANIMTYPE_DSNTREE, sce, ANIMTYPE_SCENE, (ID *)sce);
1732                                         if (ale) {
1733                                                 BLI_addtail(anim_data, ale);
1734                                                 items++;
1735                                         }
1736                                 }
1737                                 
1738                                 /* add channels */
1739                                 if (FILTER_NTREE_SCED(ntree) || (filter_mode & ANIMFILTER_CURVESONLY)) {
1740                                         items += animdata_filter_action(anim_data, ads, adt->action, filter_mode, ntree, ANIMTYPE_DSNTREE, (ID *)ntree); 
1741                                 }
1742                         }
1743                 )
1744         }
1745
1746         
1747         // TODO: scene compositing nodes (these aren't standard node-trees)
1748         
1749         /* return the number of items added to the list */
1750         return items;
1751 }
1752
1753 // 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)
1754 static int animdata_filter_dopesheet (ListBase *anim_data, bAnimContext *ac, bDopeSheet *ads, int filter_mode)
1755 {
1756         Scene *sce= (Scene *)ads->source;
1757         Base *base;
1758         bAnimListElem *ale;
1759         int items = 0;
1760         
1761         /* check that we do indeed have a scene */
1762         if ((ads->source == NULL) || (GS(ads->source->name)!=ID_SCE)) {
1763                 printf("DopeSheet Error: Not scene!\n");
1764                 if (G.f & G_DEBUG)
1765                         printf("\tPointer = %p, Name = '%s' \n", ads->source, (ads->source)?ads->source->name:NULL);
1766                 return 0;
1767         }
1768         
1769         /* scene-linked animation */
1770         // TODO: sequencer, composite nodes - are we to include those here too?
1771         {
1772                 short sceOk= 0, worOk= 0, nodeOk=0;
1773                 
1774                 /* check filtering-flags if ok */
1775                 ANIMDATA_FILTER_CASES(sce, 
1776                         {
1777                                 /* for the special AnimData blocks only case, we only need to add
1778                                  * the block if it is valid... then other cases just get skipped (hence ok=0)
1779                                  */
1780                                 ANIMDATA_ADD_ANIMDATA(sce);
1781                                 sceOk=0;
1782                         },
1783                         sceOk= !(ads->filterflag & ADS_FILTER_NOSCE);, 
1784                         sceOk= !(ads->filterflag & ADS_FILTER_NOSCE);, 
1785                         sceOk= !(ads->filterflag & ADS_FILTER_NOSCE);)
1786                 if (sce->world) {
1787                         ANIMDATA_FILTER_CASES(sce->world, 
1788                                 {
1789                                         /* for the special AnimData blocks only case, we only need to add
1790                                          * the block if it is valid... then other cases just get skipped (hence ok=0)
1791                                          */
1792                                         ANIMDATA_ADD_ANIMDATA(sce->world);
1793                                         worOk=0;
1794                                 },
1795                                 worOk= !(ads->filterflag & ADS_FILTER_NOWOR);, 
1796                                 worOk= !(ads->filterflag & ADS_FILTER_NOWOR);, 
1797                                 worOk= !(ads->filterflag & ADS_FILTER_NOWOR);)
1798                 }
1799                 if (sce->nodetree) {
1800                         ANIMDATA_FILTER_CASES(sce->nodetree, 
1801                                 {
1802                                         /* for the special AnimData blocks only case, we only need to add
1803                                          * the block if it is valid... then other cases just get skipped (hence ok=0)
1804                                          */
1805                                         ANIMDATA_ADD_ANIMDATA(sce->nodetree);
1806                                         nodeOk=0;
1807                                 },
1808                                 nodeOk= !(ads->filterflag & ADS_FILTER_NONTREE);, 
1809                                 nodeOk= !(ads->filterflag & ADS_FILTER_NONTREE);, 
1810                                 nodeOk= !(ads->filterflag & ADS_FILTER_NONTREE);)
1811                 }
1812                 
1813                 /* if only F-Curves with visible flags set can be shown, check that 
1814                  * datablocks haven't been set to invisible 
1815                  */
1816                 if (filter_mode & ANIMFILTER_CURVEVISIBLE) {
1817                         if ((sce->adt) && (sce->adt->flag & ADT_CURVES_NOT_VISIBLE))
1818                                 sceOk= worOk= nodeOk= 0;
1819                 }
1820                 
1821                 /* check if not all bad (i.e. so there is something to show) */
1822                 if ( !(!sceOk && !worOk && !nodeOk) ) {
1823                         /* add scene data to the list of filtered channels */
1824                         items += animdata_filter_dopesheet_scene(anim_data, ads, sce, filter_mode);
1825                 }
1826         }
1827         
1828         
1829         /* loop over all bases in the scene */
1830         for (base= sce->base.first; base; base= base->next) {
1831                 /* check if there's an object (all the relevant checks are done in the ob-function) */
1832                 if (base->object) {
1833                         Object *ob= base->object;
1834                         Key *key= ob_get_key(ob);
1835                         short actOk=1, keyOk=1, dataOk=1, matOk=1, partOk=1;
1836                         
1837                         /* firstly, check if object can be included, by the following factors:
1838                          *      - if only visible, must check for layer and also viewport visibility
1839                          *      - if only selected, must check if object is selected 
1840                          *      - there must be animation data to edit
1841                          */
1842                         // TODO: if cache is implemented, just check name here, and then 
1843                         if (filter_mode & ANIMFILTER_VISIBLE) {
1844                                 /* layer visibility - we check both object and base, since these may not be in sync yet */
1845                                 if ((sce->lay & (ob->lay|base->lay))==0) continue;
1846                                 
1847                                 /* outliner restrict-flag */
1848                                 if (ob->restrictflag & OB_RESTRICT_VIEW) continue;
1849                         }
1850                         
1851                         /* if only F-Curves with visible flags set can be shown, check that 
1852                          * datablock hasn't been set to invisible 
1853                          */
1854                         if (filter_mode & ANIMFILTER_CURVEVISIBLE) {
1855                                 if ((ob->adt) && (ob->adt->flag & ADT_CURVES_NOT_VISIBLE))
1856                                         continue;
1857                         }
1858                         
1859                         /* additionally, dopesheet filtering also affects what objects to consider */
1860                         if (ads->filterflag) {
1861                                 /* check selection and object type filters */
1862                                 if ( (ads->filterflag & ADS_FILTER_ONLYSEL) && !((base->flag & SELECT) /*|| (base == sce->basact)*/) )  {
1863                                         /* only selected should be shown */
1864                                         continue;
1865                                 }
1866                                 
1867                                 /* check filters for datatypes */
1868                                         /* object */
1869                                 actOk= 0;
1870                                 keyOk= 0;
1871                                 ANIMDATA_FILTER_CASES(ob, 
1872                                         {
1873                                                 /* for the special AnimData blocks only case, we only need to add
1874                                                  * the block if it is valid... then other cases just get skipped (hence ok=0)
1875                                                  */
1876                                                 ANIMDATA_ADD_ANIMDATA(ob);
1877                                                 actOk=0;
1878                                         },
1879                                         actOk= 1;, 
1880                                         actOk= 1;, 
1881                                         actOk= 1;)
1882                                 if (key) {
1883                                         /* shapekeys */
1884                                         ANIMDATA_FILTER_CASES(key, 
1885                                                 {
1886                                                         /* for the special AnimData blocks only case, we only need to add
1887                                                          * the block if it is valid... then other cases just get skipped (hence ok=0)
1888                                                          */
1889                                                         ANIMDATA_ADD_ANIMDATA(key);
1890                                                         keyOk=0;
1891                                                 },
1892                                                 keyOk= 1;, 
1893                                                 keyOk= 1;, 
1894                                                 keyOk= 1;)
1895                                 }
1896                                 
1897                                 /* materials - only for geometric types */
1898                                 matOk= 0; /* by default, not ok... */
1899                                 if ( !(ads->filterflag & ADS_FILTER_NOMAT) && (ob->totcol) && 
1900                                          ELEM5(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL) ) 
1901                                 {
1902                                         int a;
1903                                         
1904                                         /* firstly check that we actuallly have some materials */
1905                                         for (a=0; a < ob->totcol; a++) {
1906                                                 Material *ma= give_current_material(ob, a);
1907                                                 
1908                                                 if (ma) {
1909                                                         /* if material has relevant animation data, break */
1910                                                         ANIMDATA_FILTER_CASES(ma, 
1911                                                                 {
1912                                                                         /* for the special AnimData blocks only case, we only need to add
1913                                                                          * the block if it is valid... then other cases just get skipped (hence ok=0)
1914                                                                          */
1915                                                                         ANIMDATA_ADD_ANIMDATA(ma);
1916                                                                         matOk=0;
1917                                                                 },
1918                                                                 matOk= 1;, 
1919                                                                 matOk= 1;, 
1920                                                                 matOk= 1;)
1921                                                 }
1922                                                         
1923                                                 if (matOk) 
1924                                                         break;
1925                                         }
1926                                 }
1927                                 
1928                                 /* data */
1929                                 switch (ob->type) {
1930                                         case OB_CAMERA: /* ------- Camera ------------ */
1931                                         {
1932                                                 Camera *ca= (Camera *)ob->data;
1933                                                 dataOk= 0;
1934                                                 ANIMDATA_FILTER_CASES(ca, 
1935                                                         if ((ads->filterflag & ADS_FILTER_NOCAM)==0) {
1936                                                                 /* for the special AnimData blocks only case, we only need to add
1937                                                                  * the block if it is valid... then other cases just get skipped (hence ok=0)
1938                                                                  */
1939                                                                 ANIMDATA_ADD_ANIMDATA(ca);
1940                                                                 dataOk=0;
1941                                                         },
1942                                                         dataOk= !(ads->filterflag & ADS_FILTER_NOCAM);, 
1943                                                         dataOk= !(ads->filterflag & ADS_FILTER_NOCAM);, 
1944                                                         dataOk= !(ads->filterflag & ADS_FILTER_NOCAM);)
1945                                         }
1946                                                 break;
1947                                         case OB_LAMP: /* ---------- Lamp ----------- */
1948                                         {
1949                                                 Lamp *la= (Lamp *)ob->data;
1950                                                 dataOk= 0;
1951                                                 ANIMDATA_FILTER_CASES(la, 
1952                                                         if ((ads->filterflag & ADS_FILTER_NOLAM)==0) {
1953                                                                 /* for the special AnimData blocks only case, we only need to add
1954                                                                  * the block if it is valid... then other cases just get skipped (hence ok=0)
1955                                                                  */
1956                                                                 ANIMDATA_ADD_ANIMDATA(la);
1957                                                                 dataOk=0;
1958                                                         },
1959                                                         dataOk= !(ads->filterflag & ADS_FILTER_NOLAM);, 
1960                                                         dataOk= !(ads->filterflag & ADS_FILTER_NOLAM);, 
1961                                                         dataOk= !(ads->filterflag & ADS_FILTER_NOLAM);)
1962                                         }
1963                                                 break;
1964                                         case OB_CURVE: /* ------- Curve ---------- */
1965                                         {
1966                                                 Curve *cu= (Curve *)ob->data;
1967                                                 dataOk= 0;
1968                                                 ANIMDATA_FILTER_CASES(cu, 
1969                                                         if ((ads->filterflag & ADS_FILTER_NOCUR)==0) {
1970                                                                 /* for the special AnimData blocks only case, we only need to add
1971                                                                  * the block if it is valid... then other cases just get skipped (hence ok=0)
1972                                                                  */
1973                                                                 ANIMDATA_ADD_ANIMDATA(cu);
1974                                                                 dataOk=0;
1975                                                         },
1976                                                         dataOk= !(ads->filterflag & ADS_FILTER_NOCUR);, 
1977                                                         dataOk= !(ads->filterflag & ADS_FILTER_NOCUR);, 
1978                                                         dataOk= !(ads->filterflag & ADS_FILTER_NOCUR);)
1979                                         }
1980                                                 break;
1981                                         case OB_MBALL: /* ------- MetaBall ---------- */
1982                                         {
1983                                                 MetaBall *mb= (MetaBall *)ob->data;
1984                                                 dataOk= 0;
1985                                                 ANIMDATA_FILTER_CASES(mb, 
1986                                                         if ((ads->filterflag & ADS_FILTER_NOMBA)==0) {
1987                                                                 /* for the special AnimData blocks only case, we only need to add
1988                                                                  * the block if it is valid... then other cases just get skipped (hence ok=0)
1989                                                                  */
1990                                                                 ANIMDATA_ADD_ANIMDATA(mb);
1991                                                                 dataOk=0;
1992                                                         },
1993                                                         dataOk= !(ads->filterflag & ADS_FILTER_NOMBA);, 
1994                                                         dataOk= !(ads->filterflag & ADS_FILTER_NOMBA);, 
1995                                                         dataOk= !(ads->filterflag & ADS_FILTER_NOMBA);)
1996                                         }
1997                                                 break;
1998                                         case OB_ARMATURE: /* ------- Armature ---------- */
1999                                         {
2000                                                 bArmature *arm= (bArmature *)ob->data;
2001                                                 dataOk= 0;
2002                                                 ANIMDATA_FILTER_CASES(arm, 
2003                                                         if ((ads->filterflag & ADS_FILTER_NOARM)==0) {
2004                                                                 /* for the special AnimData blocks only case, we only need to add
2005                                                                  * the block if it is valid... then other cases just get skipped (hence ok=0)
2006                                                                  */
2007                                                                 ANIMDATA_ADD_ANIMDATA(arm);
2008                                                                 dataOk=0;
2009                                                         },
2010                                                         dataOk= !(ads->filterflag & ADS_FILTER_NOARM);, 
2011                                                         dataOk= !(ads->filterflag & ADS_FILTER_NOARM);, 
2012                                                         dataOk= !(ads->filterflag & ADS_FILTER_NOARM);)
2013                                         }
2014                                                 break;
2015                                         default: /* --- other --- */
2016                                                 dataOk= 0;
2017                                                 break;
2018                                 }
2019                                 
2020                                 /* particles */
2021                                 partOk = 0;
2022                                 if (!(ads->filterflag & ADS_FILTER_NOPART) && ob->particlesystem.first) {
2023                                         ParticleSystem *psys = ob->particlesystem.first;
2024                                         for(; psys; psys=psys->next) {
2025                                                 if (psys->part) {
2026                                                         /* if particlesettings has relevant animation data, break */
2027                                                         ANIMDATA_FILTER_CASES(psys->part, 
2028                                                                 {
2029                                                                         /* for the special AnimData blocks only case, we only need to add
2030                                                                          * the block if it is valid... then other cases just get skipped (hence ok=0)
2031                                                                          */
2032                                                                         ANIMDATA_ADD_ANIMDATA(psys->part);
2033                                                                         partOk=0;
2034                                                                 },
2035                                                                 partOk= 1;, 
2036                                                                 partOk= 1;, 
2037                                                                 partOk= 1;)
2038                                                 }
2039                                                         
2040                                                 if (partOk) 
2041                                                         break;
2042                                         }
2043                                 }
2044                                 
2045                                 /* check if all bad (i.e. nothing to show) */
2046                                 if (!actOk && !keyOk && !dataOk && !matOk && !partOk)
2047                                         continue;
2048                         }
2049                         else {
2050                                 /* check data-types */
2051                                 actOk= ANIMDATA_HAS_KEYS(ob);
2052                                 keyOk= (key != NULL);
2053                                 
2054                                 /* materials - only for geometric types */
2055                                 matOk= 0; /* by default, not ok... */
2056                                 if (ELEM5(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL) && (ob->totcol)) 
2057                                 {
2058                                         int a;
2059                                         
2060                                         /* firstly check that we actuallly have some materials */
2061                                         for (a=0; a < ob->totcol; a++) {
2062                                                 Material *ma= give_current_material(ob, a);
2063                                                 
2064                                                 if ((ma) && ANIMDATA_HAS_KEYS(ma)) {
2065                                                         matOk= 1;
2066                                                         break;
2067                                                 }
2068                                         }
2069                                 }
2070                                 
2071                                 /* data */
2072                                 switch (ob->type) {
2073                                         case OB_CAMERA: /* ------- Camera ------------ */
2074                                         {
2075                                                 Camera *ca= (Camera *)ob->data;
2076                                                 dataOk= ANIMDATA_HAS_KEYS(ca);                                          
2077                                         }
2078                                                 break;
2079                                         case OB_LAMP: /* ---------- Lamp ----------- */
2080                                         {
2081                                                 Lamp *la= (Lamp *)ob->data;
2082                                                 dataOk= ANIMDATA_HAS_KEYS(la);  
2083                                         }
2084                                                 break;
2085                                         case OB_CURVE: /* -------- Curve ---------- */
2086                                         {
2087                                                 Curve *cu= (Curve *)ob->data;
2088                                                 dataOk= ANIMDATA_HAS_KEYS(cu);  
2089                                         }
2090                                                 break;
2091                                         case OB_MBALL: /* -------- Metas ---------- */
2092                                         {
2093                                                 MetaBall *mb= (MetaBall *)ob->data;
2094                                                 dataOk= ANIMDATA_HAS_KEYS(mb);  
2095                                         }
2096                                                 break;
2097                                         case OB_ARMATURE: /* -------- Armature ---------- */
2098                                         {
2099                                                 bArmature *arm= (bArmature *)ob->data;
2100                                                 dataOk= ANIMDATA_HAS_KEYS(arm); 
2101                                         }
2102                                                 break;
2103                                         default: /* --- other --- */
2104                                                 dataOk= 0;
2105                                                 break;
2106                                 }
2107                                 
2108                                 /* particles */
2109                                 partOk = 0;
2110                                 if (ob->particlesystem.first) {
2111                                         ParticleSystem *psys = ob->particlesystem.first;
2112                                         for(; psys; psys=psys->next) {
2113                                                 if(psys->part && ANIMDATA_HAS_KEYS(psys->part)) {
2114                                                         partOk = 1;
2115                                                         break;
2116                                                 }
2117                                         }
2118                                 }
2119                                 
2120                                 /* check if all bad (i.e. nothing to show) */
2121                                 if (!actOk && !keyOk && !dataOk && !matOk && !partOk)
2122                                         continue;
2123                         }
2124                         
2125                         /* since we're still here, this object should be usable */
2126                         items += animdata_filter_dopesheet_ob(anim_data, ads, base, filter_mode);
2127                 }
2128         }
2129         
2130         /* return the number of items in the list */
2131         return items;
2132 }
2133
2134 /* Summary track for DopeSheet/Action Editor 
2135  *      - return code is whether the summary lets the other channels get drawn
2136  */
2137 static short animdata_filter_dopesheet_summary (bAnimContext *ac, ListBase *anim_data, int filter_mode, int *items)
2138 {
2139         bDopeSheet *ads = NULL;
2140         
2141         /* get the DopeSheet information to use 
2142          *      - we should only need to deal with the DopeSheet/Action Editor, 
2143          *        since all the other Animation Editors won't have this concept
2144          *        being applicable.
2145          */
2146         if ((ac && ac->sa) && (ac->sa->spacetype == SPACE_ACTION)) {
2147                 SpaceAction *saction= (SpaceAction *)ac->sa->spacedata.first;
2148                 ads= &saction->ads;
2149         }
2150         else {
2151                 /* invalid space type - skip this summary channels */
2152                 return 1;
2153         }
2154         
2155         /* dopesheet summary 
2156          *      - only for drawing and/or selecting keyframes in channels, but not for real editing 
2157          *      - only useful for DopeSheet Editor, where the summary is useful
2158          */
2159         // TODO: we should really check if some other prohibited filters are also active, but that can be for later
2160         if ((filter_mode & ANIMFILTER_CHANNELS) && (ads->filterflag & ADS_FILTER_SUMMARY)) {
2161                 bAnimListElem *ale= make_new_animlistelem(ac, ANIMTYPE_SUMMARY, NULL, ANIMTYPE_NONE, NULL);
2162                 if (ale) {
2163                         BLI_addtail(anim_data, ale);
2164                         (*items)++;
2165                 }
2166                 
2167                 /* if summary is collapsed, don't show other channels beneath this 
2168                  *      - this check is put inside the summary check so that it doesn't interfere with normal operation
2169                  */ 
2170                 if (ads->flag & ADS_FLAG_SUMMARY_COLLAPSED)
2171                         return 0;
2172         }
2173         
2174         /* the other channels beneath this can be shown */
2175         return 1;
2176 }  
2177
2178 /* ----------- Public API --------------- */
2179
2180 /* This function filters the active data source to leave only animation channels suitable for
2181  * usage by the caller. It will return the length of the list 
2182  * 
2183  *      *anim_data: is a pointer to a ListBase, to which the filtered animation channels
2184  *              will be placed for use.
2185  *      filter_mode: how should the data be filtered - bitmapping accessed flags
2186  */
2187 int ANIM_animdata_filter (bAnimContext *ac, ListBase *anim_data, int filter_mode, void *data, short datatype)
2188 {
2189         int items = 0;
2190         
2191         /* only filter data if there's somewhere to put it */
2192         if (data && anim_data) {
2193                 bAnimListElem *ale, *next;
2194                 Object *obact= (ac) ? ac->obact : NULL;
2195                 
2196                 /* firstly filter the data */
2197                 switch (datatype) {
2198                         case ANIMCONT_ACTION:   /* 'Action Editor' */
2199                         {
2200                                 /* the check for the DopeSheet summary is included here since the summary works here too */
2201                                 if (animdata_filter_dopesheet_summary(ac, anim_data, filter_mode, &items))
2202                                         items += animdata_filter_action(anim_data, NULL, data, filter_mode, NULL, ANIMTYPE_NONE, (ID *)obact);
2203                         }
2204                                 break;
2205                                 
2206                         case ANIMCONT_SHAPEKEY: /* 'ShapeKey Editor' */
2207                         {
2208                                 /* the check for the DopeSheet summary is included here since the summary works here too */
2209                                 if (animdata_filter_dopesheet_summary(ac, anim_data, filter_mode, &items))
2210                                         items= animdata_filter_shapekey(anim_data, data, filter_mode);
2211                         }
2212                                 break;
2213                                 
2214                         case ANIMCONT_GPENCIL:
2215                         {
2216                                 //items= animdata_filter_gpencil(anim_data, data, filter_mode);
2217                         }
2218                                 break;
2219                                 
2220                         case ANIMCONT_DOPESHEET: /* 'DopeSheet Editor' */
2221                         {
2222                                 /* the DopeSheet editor is the primary place where the DopeSheet summaries are useful */
2223                                 if (animdata_filter_dopesheet_summary(ac, anim_data, filter_mode, &items))
2224                                         items += animdata_filter_dopesheet(anim_data, ac, data, filter_mode);
2225                         }
2226                                 break;
2227                                 
2228                         case ANIMCONT_FCURVES: /* Graph Editor -> FCurves/Animation Editing */
2229                         case ANIMCONT_DRIVERS: /* Graph Editor -> Drivers Editing */
2230                         case ANIMCONT_NLA: /* NLA Editor */
2231                         {
2232                                 /* all of these editors use the basic DopeSheet data for filtering options, but don't have all the same features */
2233                                 items = animdata_filter_dopesheet(anim_data, ac, data, filter_mode);
2234                         }
2235                                 break;
2236                 }
2237                         
2238                 /* remove any weedy entries */
2239                 // XXX this is weedy code!
2240                 for (ale= anim_data->first; ale; ale= next) {
2241                         next= ale->next;
2242                         
2243                         if (ale->type == ANIMTYPE_NONE) {
2244                                 items--;
2245                                 BLI_freelinkN(anim_data, ale);
2246                         }
2247                 }
2248         }
2249         
2250         /* return the number of items in the list */
2251         return items;
2252 }
2253
2254 /* ************************************************************ */