Mesh Animation + Depsgraph Tweaks:
[blender-staging.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_DSMESH:
620                         {
621                                 Mesh *me= (Mesh *)data;
622                                 AnimData *adt= me->adt;
623                                 
624                                 ale->flag= FILTER_MESH_OBJD(me);
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_DSSKEY:
633                         {
634                                 Key *key= (Key *)data;
635                                 AnimData *adt= key->adt;
636                                 
637                                 ale->flag= FILTER_SKE_OBJD(key); 
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_DSWOR:
646                         {
647                                 World *wo= (World *)data;
648                                 AnimData *adt= wo->adt;
649                                 
650                                 ale->flag= FILTER_WOR_SCED(wo); 
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_DSNTREE:
659                         {
660                                 bNodeTree *ntree= (bNodeTree *)data;
661                                 AnimData *adt= ntree->adt;
662                                 
663                                 ale->flag= FILTER_NTREE_SCED(ntree); 
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                         case ANIMTYPE_DSPART:
672                         {
673                                 ParticleSettings *part= (ParticleSettings*)ale->data;
674                                 AnimData *adt= part->adt;
675                                 
676                                 ale->flag= FILTER_PART_OBJD(part); 
677                                 
678                                 ale->key_data= (adt) ? adt->action : NULL;
679                                 ale->datatype= ALE_ACT;
680                                 
681                                 ale->adt= BKE_animdata_from_id(data);
682                         }
683                                 break;
684                                 
685                         case ANIMTYPE_GROUP:
686                         {
687                                 bActionGroup *agrp= (bActionGroup *)data;
688                                 
689                                 ale->flag= agrp->flag;
690                                 
691                                 ale->key_data= NULL;
692                                 ale->datatype= ALE_GROUP;
693                         }
694                                 break;
695                         case ANIMTYPE_FCURVE:
696                         {
697                                 FCurve *fcu= (FCurve *)data;
698                                 
699                                 ale->flag= fcu->flag;
700                                 
701                                 ale->key_data= fcu;
702                                 ale->datatype= ALE_FCURVE;
703                         }
704                                 break;
705                                 
706                         case ANIMTYPE_SHAPEKEY:
707                         {
708                                 KeyBlock *kb= (KeyBlock *)data;
709                                 Key *key= (Key *)ale->id;
710                                 
711                                 ale->flag= kb->flag;
712                                 
713                                 /* whether we have keyframes depends on whether there is a Key block to find it from */
714                                 if (key) {
715                                         /* index of shapekey is defined by place in key's list */
716                                         ale->index= BLI_findindex(&key->block, kb);
717                                         
718                                         /* the corresponding keyframes are from the animdata */
719                                         if (ale->adt && ale->adt->action) {
720                                                 bAction *act= ale->adt->action;
721                                                 char *rna_path = key_get_curValue_rnaPath(key, kb);
722                                                 
723                                                 /* try to find the F-Curve which corresponds to this exactly,
724                                                  * then free the MEM_alloc'd string
725                                                  */
726                                                 if (rna_path) {
727                                                         ale->key_data= (void *)list_find_fcurve(&act->curves, rna_path, 0);
728                                                         MEM_freeN(rna_path);
729                                                 }
730                                         }
731                                         ale->datatype= (ale->key_data)? ALE_FCURVE : ALE_NONE;
732                                 }
733                         }       
734                                 break;
735                         
736                         case ANIMTYPE_GPLAYER:
737                         {
738                                 bGPDlayer *gpl= (bGPDlayer *)data;
739                                 
740                                 ale->flag= gpl->flag;
741                                 
742                                 ale->key_data= NULL;
743                                 ale->datatype= ALE_GPFRAME;
744                         }
745                                 break;
746                                 
747                         case ANIMTYPE_NLATRACK:
748                         {
749                                 NlaTrack *nlt= (NlaTrack *)data;
750                                 
751                                 ale->flag= nlt->flag;
752                                 
753                                 ale->key_data= &nlt->strips;
754                                 ale->datatype= ALE_NLASTRIP;
755                         }
756                                 break;
757                         case ANIMTYPE_NLAACTION:
758                         {
759                                 /* nothing to include for now... nothing editable from NLA-perspective here */
760                                 ale->key_data= NULL;
761                                 ale->datatype= ALE_NONE;
762                         }
763                                 break;
764                 }
765         }
766         
767         /* return created datatype */
768         return ale;
769 }
770  
771 /* ----------------------------------------- */
772
773 static int skip_fcurve_selected_data(FCurve *fcu, ID *owner_id)
774 {
775         if (GS(owner_id->name) == ID_OB) {
776                 Object *ob= (Object *)owner_id;
777                 
778                 /* only consider if F-Curve involves pose.bones */
779                 if ((fcu->rna_path) && strstr(fcu->rna_path, "pose.bones")) {
780                         bPoseChannel *pchan;
781                         char *bone_name;
782                         
783                         /* get bone-name, and check if this bone is selected */
784                         bone_name= BLI_getQuotedStr(fcu->rna_path, "pose.bones[");
785                         pchan= get_pose_channel(ob->pose, bone_name);
786                         if (bone_name) MEM_freeN(bone_name);
787                         
788                         /* can only add this F-Curve if it is selected */
789                         if ((pchan) && (pchan->bone) && (pchan->bone->flag & BONE_SELECTED)==0)
790                                 return 1;
791                 }
792         }
793         else if (GS(owner_id->name) == ID_SCE) {
794                 Scene *scene = (Scene *)owner_id;
795                 
796                 /* only consider if F-Curve involves sequence_editor.sequences */
797                 if ((fcu->rna_path) && strstr(fcu->rna_path, "sequences_all")) {
798                         Editing *ed= seq_give_editing(scene, FALSE);
799                         Sequence *seq;
800                         char *seq_name;
801                         
802                         /* get strip name, and check if this strip is selected */
803                         seq_name= BLI_getQuotedStr(fcu->rna_path, "sequences_all[");
804                         seq = get_seq_by_name(ed->seqbasep, seq_name, FALSE);
805                         if (seq_name) MEM_freeN(seq_name);
806                         
807                         /* can only add this F-Curve if it is selected */
808                         if (seq==NULL || (seq->flag & SELECT)==0)
809                                 return 1;
810                 }
811         }
812         else if (GS(owner_id->name) == ID_NT) {
813                 bNodeTree *ntree = (bNodeTree *)owner_id;
814                 
815                 /* check for selected  nodes */
816                 if ((fcu->rna_path) && strstr(fcu->rna_path, "nodes")) {
817                         bNode *node;
818                         char *node_name;
819                         
820                         /* get strip name, and check if this strip is selected */
821                         node_name= BLI_getQuotedStr(fcu->rna_path, "nodes[");
822                         node = nodeFindNodebyName(ntree, node_name);
823                         if (node_name) MEM_freeN(node_name);
824                         
825                         /* can only add this F-Curve if it is selected */
826                         if ((node) && (node->flag & NODE_SELECT)==0)
827                                 return 1;
828                 }
829         }
830         return 0;
831 }
832
833 /* find the next F-Curve that is usable for inclusion */
834 static FCurve *animdata_filter_fcurve_next (bDopeSheet *ads, FCurve *first, bActionGroup *grp, int filter_mode, ID *owner_id)
835 {
836         FCurve *fcu = NULL;
837         
838         /* loop over F-Curves - assume that the caller of this has already checked that these should be included 
839          * NOTE: we need to check if the F-Curves belong to the same group, as this gets called for groups too...
840          */
841         for (fcu= first; ((fcu) && (fcu->grp==grp)); fcu= fcu->next) {
842                 /* special exception for Pose-Channel Based F-Curves:
843                  *      - the 'Only Selected' data filter should be applied to Pose-Channel data too, but those are
844                  *        represented as F-Curves. The way the filter for objects worked was to be the first check
845                  *        after 'normal' visibility, so this is done first here too...
846                  *      - we currently use an 'approximate' method for getting these F-Curves that doesn't require
847                  *        carefully checking the entire path
848                  *      - this will also affect things like Drivers, and also works for Bone Constraints
849                  */
850                 if ( ((ads) && (ads->filterflag & ADS_FILTER_ONLYSEL)) && (owner_id) ) {
851                         if (skip_fcurve_selected_data(fcu, owner_id))
852                                 continue;
853                 }
854                                 
855                 /* only include if visible (Graph Editor check, not channels check) */
856                 if (!(filter_mode & ANIMFILTER_CURVEVISIBLE) || (fcu->flag & FCURVE_VISIBLE)) {
857                         /* only work with this channel and its subchannels if it is editable */
858                         if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_FCU(fcu)) {
859                                 /* only include this curve if selected in a way consistent with the filtering requirements */
860                                 if ( ANIMCHANNEL_SELOK(SEL_FCU(fcu)) && ANIMCHANNEL_SELEDITOK(SEL_FCU(fcu)) ) {
861                                         /* only include if this curve is active */
862                                         if (!(filter_mode & ANIMFILTER_ACTIVE) || (fcu->flag & FCURVE_ACTIVE)) {
863                                                 /* this F-Curve can be used, so return it */
864                                                 return fcu;
865                                         }
866                                 }
867                         }
868                 }
869         }
870         
871         /* no (more) F-Curves from the list are suitable... */
872         return NULL;
873 }
874
875 static int animdata_filter_fcurves (ListBase *anim_data, bDopeSheet *ads, FCurve *first, bActionGroup *grp, void *owner, short ownertype, int filter_mode, ID *owner_id)
876 {
877         FCurve *fcu;
878         int items = 0;
879         
880         /* loop over every F-Curve able to be included 
881          *      - this for-loop works like this: 
882          *              1) the starting F-Curve is assigned to the fcu pointer so that we have a starting point to search from
883          *              2) the first valid F-Curve to start from (which may include the one given as 'first') in the remaining 
884          *                 list of F-Curves is found, and verified to be non-null
885          *              3) the F-Curve referenced by fcu pointer is added to the list
886          *              4) the fcu pointer is set to the F-Curve after the one we just added, so that we can keep going through 
887          *                 the rest of the F-Curve list without an eternal loop. Back to step 2 :)
888          */
889         for (fcu=first; ( (fcu = animdata_filter_fcurve_next(ads, fcu, grp, filter_mode, owner_id)) ); fcu=fcu->next)
890         {
891                 bAnimListElem *ale = make_new_animlistelem(fcu, ANIMTYPE_FCURVE, owner, ownertype, owner_id);
892                 
893                 if (ale) {
894                         BLI_addtail(anim_data, ale);
895                         items++;
896                 }
897         }
898         
899         /* return the number of items added to the list */
900         return items;
901 }
902
903 static int animdata_filter_action (ListBase *anim_data, bDopeSheet *ads, bAction *act, int filter_mode, void *owner, short ownertype, ID *owner_id)
904 {
905         bAnimListElem *ale=NULL;
906         bActionGroup *agrp;
907         FCurve *lastchan=NULL;
908         int items = 0;
909         
910         /* loop over groups */
911         // TODO: in future, should we expect to need nested groups?
912         for (agrp= act->groups.first; agrp; agrp= agrp->next) {
913                 FCurve *first_fcu;
914                 
915                 /* store reference to last channel of group */
916                 if (agrp->channels.last) 
917                         lastchan= agrp->channels.last;
918                 
919                 /* get the first F-Curve in this group we can start to use, 
920                  * and if there isn't any F-Curve to start from, then don't 
921                  * this group at all...
922                  *
923                  * exceptions for when we might not care whether there's anything inside this group or not
924                  *      - if we're interested in channels and their selections, in which case group channel should get considered too
925                  *        even if all its sub channels are hidden...
926                  */
927                 first_fcu = animdata_filter_fcurve_next(ads, agrp->channels.first, agrp, filter_mode, owner_id);
928                 
929                 if ( (filter_mode & (ANIMFILTER_SEL|ANIMFILTER_UNSEL)) ||
930                          (first_fcu) ) 
931                 {
932                         /* add this group as a channel first */
933                         if ((filter_mode & ANIMFILTER_CHANNELS) || !(filter_mode & ANIMFILTER_CURVESONLY)) {
934                                 /* check if filtering by selection */
935                                 if ( ANIMCHANNEL_SELOK(SEL_AGRP(agrp)) ) {
936                                         ale= make_new_animlistelem(agrp, ANIMTYPE_GROUP, NULL, ANIMTYPE_NONE, owner_id);
937                                         if (ale) {
938                                                 BLI_addtail(anim_data, ale);
939                                                 items++;
940                                         }
941                                 }
942                         }
943                         
944                         /* there are some situations, where only the channels of the action group should get considered */
945                         if (!(filter_mode & ANIMFILTER_ACTGROUPED) || (agrp->flag & AGRP_ACTIVE)) {
946                                 /* filters here are a bit convoulted...
947                                  *      - groups show a "summary" of keyframes beside their name which must accessable for tools which handle keyframes
948                                  *      - groups can be collapsed (and those tools which are only interested in channels rely on knowing that group is closed)
949                                  *
950                                  * cases when we should include F-Curves inside group:
951                                  *      - we don't care about visibility
952                                  *      - group is expanded
953                                  *      - we just need the F-Curves present
954                                  */
955                                 if ( (!(filter_mode & ANIMFILTER_VISIBLE) || EXPANDED_AGRP(agrp)) || (filter_mode & ANIMFILTER_CURVESONLY) ) 
956                                 {
957                                         /* for the Graph Editor, curves may be set to not be visible in the view to lessen clutter,
958                                          * but to do this, we need to check that the group doesn't have it's not-visible flag set preventing 
959                                          * all its sub-curves to be shown
960                                          */
961                                         if ( !(filter_mode & ANIMFILTER_CURVEVISIBLE) || !(agrp->flag & AGRP_NOTVISIBLE) )
962                                         {
963                                                 if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_AGRP(agrp)) {
964                                                         items += animdata_filter_fcurves(anim_data, ads, first_fcu, agrp, owner, ownertype, filter_mode, owner_id);
965                                                 }
966                                         }
967                                 }
968                         }
969                 }
970         }
971         
972         /* loop over un-grouped F-Curves (only if we're not only considering those channels in the animive group) */
973         if (!(filter_mode & ANIMFILTER_ACTGROUPED))  {
974                 // XXX the 'owner' info here needs review...
975                 items += animdata_filter_fcurves(anim_data, ads, (lastchan)?(lastchan->next):(act->curves.first), NULL, owner, ownertype, filter_mode, owner_id);
976         }
977         
978         /* return the number of items added to the list */
979         return items;
980 }
981
982 /* Include NLA-Data for NLA-Editor:
983  *      - when ANIMFILTER_CHANNELS is used, that means we should be filtering the list for display
984  *        Although the evaluation order is from the first track to the last and then apply the Action on top,
985  *        we present this in the UI as the Active Action followed by the last track to the first so that we 
986  *        get the evaluation order presented as per a stack.
987  *      - for normal filtering (i.e. for editing), we only need the NLA-tracks but they can be in 'normal' evaluation
988  *        order, i.e. first to last. Otherwise, some tools may get screwed up.
989  */
990 static int animdata_filter_nla (ListBase *anim_data, bDopeSheet *ads, AnimData *adt, int filter_mode, void *owner, short ownertype, ID *owner_id)
991 {
992         bAnimListElem *ale;
993         NlaTrack *nlt;
994         NlaTrack *first=NULL, *next=NULL;
995         int items = 0;
996         
997         /* if showing channels, include active action */
998         if (filter_mode & ANIMFILTER_CHANNELS) {
999                 /* there isn't really anything editable here, so skip if need editable */
1000                 // TODO: currently, selection isn't checked since it doesn't matter
1001                 if ((filter_mode & ANIMFILTER_FOREDIT) == 0) { 
1002                         /* just add the action track now (this MUST appear for drawing)
1003                          *      - as AnimData may not have an action, we pass a dummy pointer just to get the list elem created, then
1004                          *        overwrite this with the real value - REVIEW THIS...
1005                          */
1006                         ale= make_new_animlistelem((void *)(&adt->action), ANIMTYPE_NLAACTION, owner, ownertype, owner_id);
1007                         ale->data= (adt->action) ? adt->action : NULL;
1008                                 
1009                         if (ale) {
1010                                 BLI_addtail(anim_data, ale);
1011                                 items++;
1012                         }
1013                 }
1014                 
1015                 /* first track to include will be the last one if we're filtering by channels */
1016                 first= adt->nla_tracks.last;
1017         }
1018         else {
1019                 /* first track to include will the the first one (as per normal) */
1020                 first= adt->nla_tracks.first;
1021         }
1022         
1023         /* loop over NLA Tracks - assume that the caller of this has already checked that these should be included */
1024         for (nlt= first; nlt; nlt= next) {
1025                 /* 'next' NLA-Track to use depends on whether we're filtering for drawing or not */
1026                 if (filter_mode & ANIMFILTER_CHANNELS) 
1027                         next= nlt->prev;
1028                 else
1029                         next= nlt->next;
1030                 
1031                 /* if we're in NLA-tweakmode, don't show this track if it was disabled (due to tweaking) for now 
1032                  *      - active track should still get shown though (even though it has disabled flag set)
1033                  */
1034                 // FIXME: the channels after should still get drawn, just 'differently', and after an active-action channel
1035                 if ((adt->flag & ADT_NLA_EDIT_ON) && (nlt->flag & NLATRACK_DISABLED) && !(nlt->flag & NLATRACK_ACTIVE))
1036                         continue;
1037                 
1038                 /* only work with this channel and its subchannels if it is editable */
1039                 if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_NLT(nlt)) {
1040                         /* only include this track if selected in a way consistent with the filtering requirements */
1041                         if ( ANIMCHANNEL_SELOK(SEL_NLT(nlt)) ) {
1042                                 /* only include if this track is active */
1043                                 if (!(filter_mode & ANIMFILTER_ACTIVE) || (nlt->flag & NLATRACK_ACTIVE)) {
1044                                         ale= make_new_animlistelem(nlt, ANIMTYPE_NLATRACK, owner, ownertype, owner_id);
1045                                                 
1046                                         if (ale) {
1047                                                 BLI_addtail(anim_data, ale);
1048                                                 items++;
1049                                         }
1050                                 }
1051                         }
1052                 }
1053         }
1054         
1055         /* return the number of items added to the list */
1056         return items;
1057 }
1058
1059 /* Include ShapeKey Data for ShapeKey Editor */
1060 static int animdata_filter_shapekey (ListBase *anim_data, Key *key, int filter_mode)
1061 {
1062         bAnimListElem *ale;
1063         int items = 0;
1064         
1065         /* check if channels or only F-Curves */
1066         if ((filter_mode & ANIMFILTER_CURVESONLY) == 0) {
1067                 KeyBlock *kb;
1068                 
1069                 /* loop through the channels adding ShapeKeys as appropriate */
1070                 for (kb= key->block.first; kb; kb= kb->next) {
1071                         /* skip the first one, since that's the non-animateable basis */
1072                         // XXX maybe in future this may become handy?
1073                         if (kb == key->block.first) continue;
1074                         
1075                         /* only work with this channel and its subchannels if it is editable */
1076                         if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_SHAPEKEY(kb)) {
1077                                 /* only include this track if selected in a way consistent with the filtering requirements */
1078                                 if ( ANIMCHANNEL_SELOK(SEL_SHAPEKEY(kb)) ) {
1079                                         // TODO: consider 'active' too?
1080                                         
1081                                         /* owner-id here must be key so that the F-Curve can be resolved... */
1082                                         ale= make_new_animlistelem(kb, ANIMTYPE_SHAPEKEY, NULL, ANIMTYPE_NONE, (ID *)key);
1083                                         
1084                                         if (ale) {
1085                                                 BLI_addtail(anim_data, ale);
1086                                                 items++;
1087                                         }
1088                                 }
1089                         }
1090                 }
1091         }
1092         else {
1093                 /* just use the action associated with the shapekey */
1094                 // FIXME: is owner-id and having no owner/dopesheet really fine?
1095                 if (key->adt) {
1096                         if (filter_mode & ANIMFILTER_ANIMDATA)
1097                                 ANIMDATA_ADD_ANIMDATA(key)
1098                         else if (key->adt->action)
1099                                 items= animdata_filter_action(anim_data, NULL, key->adt->action, filter_mode, NULL, ANIMTYPE_NONE, (ID *)key);
1100                 }
1101         }
1102         
1103         /* return the number of items added to the list */
1104         return items;
1105 }
1106
1107 #if 0
1108 // FIXME: switch this to use the bDopeSheet...
1109 static int animdata_filter_gpencil (ListBase *anim_data, bScreen *sc, int filter_mode)
1110 {
1111         bAnimListElem *ale;
1112         ScrArea *sa, *curarea;
1113         bGPdata *gpd;
1114         bGPDlayer *gpl;
1115         int items = 0;
1116         
1117         /* check if filtering types are appropriate */
1118         {
1119                 /* special hack for fullscreen area (which must be this one then):
1120                  *      - we use the curarea->full as screen to get spaces from, since the
1121                  *        old (pre-fullscreen) screen was stored there...
1122                  *      - this is needed as all data would otherwise disappear
1123                  */
1124                 // XXX need to get new alternative for curarea
1125                 if ((curarea->full) && (curarea->spacetype==SPACE_ACTION))
1126                         sc= curarea->full;
1127                 
1128                 /* loop over spaces in current screen, finding gpd blocks (could be slow!) */
1129                 for (sa= sc->areabase.first; sa; sa= sa->next) {
1130                         /* try to get gp data */
1131                         // XXX need to put back grease pencil api...
1132                         gpd= gpencil_data_get_active(sa);
1133                         if (gpd == NULL) continue;
1134                         
1135                         /* add gpd as channel too (if for drawing, and it has layers) */
1136                         if ((filter_mode & ANIMFILTER_CHANNELS) && (gpd->layers.first)) {
1137                                 /* add to list */
1138                                 ale= make_new_animlistelem(gpd, ANIMTYPE_GPDATABLOCK, sa, ANIMTYPE_SPECIALDATA);
1139                                 if (ale) {
1140                                         BLI_addtail(anim_data, ale);
1141                                         items++;
1142                                 }
1143                         }
1144                         
1145                         /* only add layers if they will be visible (if drawing channels) */
1146                         if ( !(filter_mode & ANIMFILTER_VISIBLE) || (EXPANDED_GPD(gpd)) ) {
1147                                 /* loop over layers as the conditions are acceptable */
1148                                 for (gpl= gpd->layers.first; gpl; gpl= gpl->next) {
1149                                         /* only if selected */
1150                                         if ( ANIMCHANNEL_SELOK(SEL_GPL(gpl)) ) {
1151                                                 /* only if editable */
1152                                                 if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_GPL(gpl)) {
1153                                                         /* add to list */
1154                                                         ale= make_new_animlistelem(gpl, ANIMTYPE_GPLAYER, gpd, ANIMTYPE_GPDATABLOCK);
1155                                                         if (ale) {
1156                                                                 BLI_addtail(anim_data, ale);
1157                                                                 items++;
1158                                                         }
1159                                                 }
1160                                         }
1161                                 }
1162                         }
1163                 }
1164         }
1165         
1166         /* return the number of items added to the list */
1167         return items;
1168 }
1169 #endif 
1170
1171
1172 static int animdata_filter_dopesheet_mats (ListBase *anim_data, bDopeSheet *ads, Base *base, int filter_mode)
1173 {
1174         ListBase mats = {NULL, NULL};
1175         LinkData *ld;
1176         
1177         bAnimListElem *ale=NULL;
1178         Object *ob= base->object;
1179         int items=0, a=0;
1180         
1181         /* firstly check that we actuallly have some materials, by gathering all materials in a temp list */
1182         for (a=0; a < ob->totcol; a++) {
1183                 Material *ma= give_current_material(ob, a);
1184                 short ok = 0;
1185                 
1186                 /* for now, if no material returned, skip (this shouldn't confuse the user I hope) */
1187                 if (ELEM(NULL, ma, ma->adt)) 
1188                         continue;
1189                 
1190                 /* check if ok */
1191                 ANIMDATA_FILTER_CASES(ma, 
1192                         { /* AnimData blocks - do nothing... */ },
1193                         ok=1;, 
1194                         ok=1;, 
1195                         ok=1;)
1196                 if (ok == 0) continue;
1197                 
1198                 /* make a temp list elem for this */
1199                 ld= MEM_callocN(sizeof(LinkData), "DopeSheet-MaterialCache");
1200                 ld->data= ma;
1201                 BLI_addtail(&mats, ld);
1202         }
1203         
1204         /* if there were no channels found, no need to carry on */
1205         if (mats.first == NULL)
1206                 return 0;
1207         
1208         /* include materials-expand widget? */
1209         if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
1210                 ale= make_new_animlistelem(ob, ANIMTYPE_FILLMATD, base, ANIMTYPE_OBJECT, (ID *)ob);
1211                 if (ale) {
1212                         BLI_addtail(anim_data, ale);
1213                         items++;
1214                 }
1215         }
1216         
1217         /* add materials? */
1218         if (FILTER_MAT_OBJC(ob) || (filter_mode & ANIMFILTER_CURVESONLY)) {
1219                 /* for each material in cache, add channels  */
1220                 for (ld= mats.first; ld; ld= ld->next) {
1221                         Material *ma= (Material *)ld->data;
1222                         
1223                         /* include material-expand widget? */
1224                         // hmm... do we need to store the index of this material in the array anywhere?
1225                         if (filter_mode & ANIMFILTER_CHANNELS) {
1226                                 /* check if filtering by active status */
1227                                 if ANIMCHANNEL_ACTIVEOK(ma) {
1228                                         ale= make_new_animlistelem(ma, ANIMTYPE_DSMAT, base, ANIMTYPE_OBJECT, (ID *)ma);
1229                                         if (ale) {
1230                                                 BLI_addtail(anim_data, ale);
1231                                                 items++;
1232                                         }
1233                                 }
1234                         }
1235                         
1236                         /* add material's animation data */
1237                         if (!(filter_mode & ANIMFILTER_VISIBLE) || FILTER_MAT_OBJD(ma) || (filter_mode & ANIMFILTER_CURVESONLY)) {
1238                                 ANIMDATA_FILTER_CASES(ma, 
1239                                         { /* AnimData blocks - do nothing... */ },
1240                                         items += animdata_filter_nla(anim_data, ads, ma->adt, filter_mode, ma, ANIMTYPE_DSMAT, (ID *)ma);, 
1241                                         items += animdata_filter_fcurves(anim_data, ads, ma->adt->drivers.first, NULL, ma, ANIMTYPE_DSMAT, filter_mode, (ID *)ma);, 
1242                                         items += animdata_filter_action(anim_data, ads, ma->adt->action, filter_mode, ma, ANIMTYPE_DSMAT, (ID *)ma);)
1243                         }
1244                 }
1245         }
1246         
1247         /* free cache */
1248         BLI_freelistN(&mats);
1249         
1250         /* return the number of items added to the list */
1251         return items;
1252 }
1253
1254 static int animdata_filter_dopesheet_particles (ListBase *anim_data, bDopeSheet *ads, Base *base, int filter_mode)
1255 {
1256         bAnimListElem *ale=NULL;
1257         Object *ob= base->object;
1258         ParticleSystem *psys = ob->particlesystem.first;
1259         int items= 0, first = 1;
1260
1261         for(; psys; psys=psys->next) {
1262                 short ok = 0;
1263
1264                 if(ELEM(NULL, psys->part, psys->part->adt))
1265                         continue;
1266
1267                 ANIMDATA_FILTER_CASES(psys->part,
1268                         { /* AnimData blocks - do nothing... */ },
1269                         ok=1;, 
1270                         ok=1;, 
1271                         ok=1;)
1272                 if (ok == 0) continue;
1273
1274                 /* include particles-expand widget? */
1275                 if (first && (filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
1276                         ale= make_new_animlistelem(ob, ANIMTYPE_FILLPARTD, base, ANIMTYPE_OBJECT, (ID *)ob);
1277                         if (ale) {
1278                                 BLI_addtail(anim_data, ale);
1279                                 items++;
1280                         }
1281                         first = 0;
1282                 }
1283                 
1284                 /* add particle settings? */
1285                 if (FILTER_PART_OBJC(ob) || (filter_mode & ANIMFILTER_CURVESONLY)) {
1286                         if ((filter_mode & ANIMFILTER_CHANNELS)) {
1287                                 /* check if filtering by active status */
1288                                 if ANIMCHANNEL_ACTIVEOK(psys->part) {
1289                                         ale = make_new_animlistelem(psys->part, ANIMTYPE_DSPART, base, ANIMTYPE_OBJECT, (ID *)psys->part);
1290                                         if (ale) {
1291                                                 BLI_addtail(anim_data, ale);
1292                                                 items++;
1293                                         }
1294                                 }
1295                         }
1296                         
1297                         if (!(filter_mode & ANIMFILTER_VISIBLE) || FILTER_PART_OBJD(psys->part) || (filter_mode & ANIMFILTER_CURVESONLY)) {
1298                                 ANIMDATA_FILTER_CASES(psys->part,
1299                                         { /* AnimData blocks - do nothing... */ },
1300                                         items += animdata_filter_nla(anim_data, ads, psys->part->adt, filter_mode, psys->part, ANIMTYPE_DSPART, (ID *)psys->part);, 
1301                                         items += animdata_filter_fcurves(anim_data, ads, psys->part->adt->drivers.first, NULL, psys->part, ANIMTYPE_DSPART, filter_mode, (ID *)psys->part);, 
1302                                         items += animdata_filter_action(anim_data, ads, psys->part->adt->action, filter_mode, psys->part, ANIMTYPE_DSPART, (ID *)psys->part);)
1303                         }
1304                 }
1305         }
1306         
1307         /* return the number of items added to the list */
1308         return items;
1309 }
1310
1311 static int animdata_filter_dopesheet_obdata (ListBase *anim_data, bDopeSheet *ads, Base *base, int filter_mode)
1312 {
1313         bAnimListElem *ale=NULL;
1314         Object *ob= base->object;
1315         IdAdtTemplate *iat= ob->data;
1316         AnimData *adt= iat->adt;
1317         short type=0, expanded=0;
1318         int items= 0;
1319         
1320         /* get settings based on data type */
1321         switch (ob->type) {
1322                 case OB_CAMERA: /* ------- Camera ------------ */
1323                 {
1324                         Camera *ca= (Camera *)ob->data;
1325                         
1326                         type= ANIMTYPE_DSCAM;
1327                         expanded= FILTER_CAM_OBJD(ca);
1328                 }
1329                         break;
1330                 case OB_LAMP: /* ---------- Lamp ----------- */
1331                 {
1332                         Lamp *la= (Lamp *)ob->data;
1333                         
1334                         type= ANIMTYPE_DSLAM;
1335                         expanded= FILTER_LAM_OBJD(la);
1336                 }
1337                         break;
1338                 case OB_CURVE: /* ------- Curve ---------- */
1339                 case OB_SURF: /* ------- Nurbs Surface ---------- */
1340                 case OB_FONT: /* ------- Text Curve ---------- */
1341                 {
1342                         Curve *cu= (Curve *)ob->data;
1343                         
1344                         type= ANIMTYPE_DSCUR;
1345                         expanded= FILTER_CUR_OBJD(cu);
1346                 }
1347                         break;
1348                 case OB_MBALL: /* ------- MetaBall ---------- */
1349                 {
1350                         MetaBall *mb= (MetaBall *)ob->data;
1351                         
1352                         type= ANIMTYPE_DSMBALL;
1353                         expanded= FILTER_MBALL_OBJD(mb);
1354                 }
1355                         break;
1356                 case OB_ARMATURE: /* ------- Armature ---------- */
1357                 {
1358                         bArmature *arm= (bArmature *)ob->data;
1359                         
1360                         type= ANIMTYPE_DSARM;
1361                         expanded= FILTER_ARM_OBJD(arm);
1362                 }
1363                         break;
1364                 case OB_MESH: /* ------- Mesh ---------- */
1365                 {
1366                         Mesh *me= (Mesh *)ob->data;
1367                         
1368                         type= ANIMTYPE_DSMESH;
1369                         expanded= FILTER_MESH_OBJD(me);
1370                 }
1371                         break;
1372         }
1373         
1374         /* special exception for drivers instead of action */
1375         if (ads->filterflag & ADS_FILTER_ONLYDRIVERS)
1376                 expanded= EXPANDED_DRVD(adt);
1377         
1378         /* include data-expand widget? */
1379         if ((filter_mode & ANIMFILTER_CURVESONLY) == 0) {       
1380                 /* check if filtering by active status */
1381                 if ANIMCHANNEL_ACTIVEOK(iat) {
1382                         ale= make_new_animlistelem(iat, type, base, ANIMTYPE_OBJECT, (ID *)iat);
1383                         if (ale) BLI_addtail(anim_data, ale);
1384                 }
1385         }
1386         
1387         /* add object-data animation channels? */
1388         if (!(filter_mode & ANIMFILTER_VISIBLE) || (expanded) || (filter_mode & ANIMFILTER_CURVESONLY)) {
1389                 /* filtering for channels - nla, drivers, keyframes */
1390                 ANIMDATA_FILTER_CASES(iat, 
1391                         { /* AnimData blocks - do nothing... */ },
1392                         items+= animdata_filter_nla(anim_data, ads, iat->adt, filter_mode, iat, type, (ID *)iat);,
1393                         items+= animdata_filter_fcurves(anim_data, ads, adt->drivers.first, NULL, iat, type, filter_mode, (ID *)iat);, 
1394                         items += animdata_filter_action(anim_data, ads, iat->adt->action, filter_mode, iat, type, (ID *)iat);)
1395         }
1396         
1397         /* return the number of items added to the list */
1398         return items;
1399 }
1400
1401 static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, Base *base, int filter_mode)
1402 {
1403         bAnimListElem *ale=NULL;
1404         AnimData *adt = NULL;
1405         Object *ob= base->object;
1406         Key *key= ob_get_key(ob);
1407         short obdata_ok = 0;
1408         int items = 0;
1409         
1410         /* add this object as a channel first */
1411         if ((filter_mode & (ANIMFILTER_CURVESONLY|ANIMFILTER_NLATRACKS)) == 0) {
1412                 /* check if filtering by selection */
1413                 if ANIMCHANNEL_SELOK((base->flag & SELECT)) {
1414                         /* check if filtering by active status */
1415                         if ANIMCHANNEL_ACTIVEOK(ob) {
1416                                 ale= make_new_animlistelem(base, ANIMTYPE_OBJECT, NULL, ANIMTYPE_NONE, (ID *)ob);
1417                                 if (ale) {
1418                                         BLI_addtail(anim_data, ale);
1419                                         items++;
1420                                 }
1421                         }
1422                 }
1423         }
1424         
1425         /* if collapsed, don't go any further (unless adding keyframes only) */
1426         if ( ((filter_mode & ANIMFILTER_VISIBLE) && EXPANDED_OBJC(ob) == 0) &&
1427                  !(filter_mode & (ANIMFILTER_CURVESONLY|ANIMFILTER_NLATRACKS)) )
1428                 return items;
1429         
1430         /* Action, Drivers, or NLA */
1431         if (ob->adt) {
1432                 adt= ob->adt;
1433                 ANIMDATA_FILTER_CASES(ob,
1434                         { /* AnimData blocks - do nothing... */ },
1435                         { /* nla */
1436                                 /* add NLA tracks */
1437                                 items += animdata_filter_nla(anim_data, ads, adt, filter_mode, ob, ANIMTYPE_OBJECT, (ID *)ob);
1438                         },
1439                         { /* drivers */
1440                                 /* include drivers-expand widget? */
1441                                 if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
1442                                         ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLDRIVERS, base, ANIMTYPE_OBJECT, (ID *)ob);
1443                                         if (ale) {
1444                                                 BLI_addtail(anim_data, ale);
1445                                                 items++;
1446                                         }
1447                                 }
1448                                 
1449                                 /* add F-Curve channels (drivers are F-Curves) */
1450                                 if (!(filter_mode & ANIMFILTER_VISIBLE) || EXPANDED_DRVD(adt) || !(filter_mode & ANIMFILTER_CHANNELS)) {
1451                                         // need to make the ownertype normal object here... (maybe type should be a separate one for clarity?)
1452                                         items += animdata_filter_fcurves(anim_data, ads, adt->drivers.first, NULL, ob, ANIMTYPE_OBJECT, filter_mode, (ID *)ob);
1453                                 }
1454                         },
1455                         { /* action (keyframes) */
1456                                 /* include action-expand widget? */
1457                                 if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
1458                                         ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLACTD, base, ANIMTYPE_OBJECT, (ID *)ob);
1459                                         if (ale) {
1460                                                 BLI_addtail(anim_data, ale);
1461                                                 items++;
1462                                         }
1463                                 }
1464                                 
1465                                 /* add F-Curve channels? */
1466                                 if (!(filter_mode & ANIMFILTER_VISIBLE) || EXPANDED_ACTC(adt->action) || !(filter_mode & ANIMFILTER_CHANNELS)) {
1467                                         // need to make the ownertype normal object here... (maybe type should be a separate one for clarity?)
1468                                         items += animdata_filter_action(anim_data, ads, adt->action, filter_mode, ob, ANIMTYPE_OBJECT, (ID *)ob); 
1469                                 }
1470                         }
1471                 );
1472         }
1473         
1474         
1475         /* ShapeKeys? */
1476         if ((key) && !(ads->filterflag & ADS_FILTER_NOSHAPEKEYS)) {
1477                 adt= key->adt;
1478                 ANIMDATA_FILTER_CASES(key,
1479                         { /* AnimData blocks - do nothing... */ },
1480                         { /* nla */
1481                                 /* include shapekey-expand widget? */
1482                                 if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
1483                                         /* check if filtering by active status */
1484                                         if ANIMCHANNEL_ACTIVEOK(key) {
1485                                                 ale= make_new_animlistelem(key, ANIMTYPE_DSSKEY, base, ANIMTYPE_OBJECT, (ID *)ob);
1486                                                 if (ale) {
1487                                                         BLI_addtail(anim_data, ale);
1488                                                         items++;
1489                                                 }
1490                                         }
1491                                 }
1492                                 
1493                                 /* add NLA tracks - only if expanded or so */
1494                                 if (!(filter_mode & ANIMFILTER_VISIBLE) || FILTER_SKE_OBJD(key) || (filter_mode & ANIMFILTER_CURVESONLY))
1495                                         items += animdata_filter_nla(anim_data, ads, adt, filter_mode, ob, ANIMTYPE_OBJECT, (ID *)ob);
1496                         },
1497                         { /* drivers */
1498                                 /* include shapekey-expand widget? */
1499                                 if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
1500                                         ale= make_new_animlistelem(key, ANIMTYPE_DSSKEY, base, ANIMTYPE_OBJECT, (ID *)ob);
1501                                         if (ale) {
1502                                                 BLI_addtail(anim_data, ale);
1503                                                 items++;
1504                                         }
1505                                 }
1506                                 
1507                                 /* add channels */
1508                                 if (!(filter_mode & ANIMFILTER_VISIBLE) || FILTER_SKE_OBJD(key) || (filter_mode & ANIMFILTER_CURVESONLY)) {
1509                                         items += animdata_filter_fcurves(anim_data, ads, adt->drivers.first, NULL, key, ANIMTYPE_DSSKEY, filter_mode, (ID *)key);
1510                                 }
1511                         },
1512                         { /* action (keyframes) */
1513                                 /* include shapekey-expand widget? */
1514                                 if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
1515                                         /* check if filtering by active status */
1516                                         if ANIMCHANNEL_ACTIVEOK(key) {
1517                                                 ale= make_new_animlistelem(key, ANIMTYPE_DSSKEY, base, ANIMTYPE_OBJECT, (ID *)ob);
1518                                                 if (ale) {
1519                                                         BLI_addtail(anim_data, ale);
1520                                                         items++;
1521                                                 }
1522                                         }
1523                                 }
1524                                 
1525                                 /* add channels */
1526                                 if (!(filter_mode & ANIMFILTER_VISIBLE) || FILTER_SKE_OBJD(key) || (filter_mode & ANIMFILTER_CURVESONLY)) {
1527                                         items += animdata_filter_action(anim_data, ads, adt->action, filter_mode, key, ANIMTYPE_DSSKEY, (ID *)key); 
1528                                 }
1529                         }
1530                 );
1531         }
1532
1533         /* Materials? */
1534         if ((ob->totcol) && !(ads->filterflag & ADS_FILTER_NOMAT))
1535                 items += animdata_filter_dopesheet_mats(anim_data, ads, base, filter_mode);
1536         
1537         /* Object Data */
1538         switch (ob->type) {
1539                 case OB_CAMERA: /* ------- Camera ------------ */
1540                 {
1541                         Camera *ca= (Camera *)ob->data;
1542                         
1543                         if ((ads->filterflag & ADS_FILTER_NOCAM) == 0) {
1544                                 ANIMDATA_FILTER_CASES(ca,
1545                                         { /* AnimData blocks - do nothing... */ },
1546                                         obdata_ok= 1;,
1547                                         obdata_ok= 1;,
1548                                         obdata_ok= 1;)
1549                         }
1550                 }
1551                         break;
1552                 case OB_LAMP: /* ---------- Lamp ----------- */
1553                 {
1554                         Lamp *la= (Lamp *)ob->data;
1555                         
1556                         if ((ads->filterflag & ADS_FILTER_NOLAM) == 0) {
1557                                 ANIMDATA_FILTER_CASES(la,
1558                                         { /* AnimData blocks - do nothing... */ },
1559                                         obdata_ok= 1;,
1560                                         obdata_ok= 1;,
1561                                         obdata_ok= 1;)
1562                         }
1563                 }
1564                         break;
1565                 case OB_CURVE: /* ------- Curve ---------- */
1566                 case OB_SURF: /* ------- Nurbs Surface ---------- */
1567                 case OB_FONT: /* ------- Text Curve ---------- */
1568                 {
1569                         Curve *cu= (Curve *)ob->data;
1570                         
1571                         if ((ads->filterflag & ADS_FILTER_NOCUR) == 0) {
1572                                 ANIMDATA_FILTER_CASES(cu,
1573                                         { /* AnimData blocks - do nothing... */ },
1574                                         obdata_ok= 1;,
1575                                         obdata_ok= 1;,
1576                                         obdata_ok= 1;)
1577                         }
1578                 }
1579                         break;
1580                 case OB_MBALL: /* ------- MetaBall ---------- */
1581                 {
1582                         MetaBall *mb= (MetaBall *)ob->data;
1583                         
1584                         if ((ads->filterflag & ADS_FILTER_NOMBA) == 0) {
1585                                 ANIMDATA_FILTER_CASES(mb,
1586                                         { /* AnimData blocks - do nothing... */ },
1587                                         obdata_ok= 1;,
1588                                         obdata_ok= 1;,
1589                                         obdata_ok= 1;)
1590                         }
1591                 }
1592                         break;
1593                 case OB_ARMATURE: /* ------- Armature ---------- */
1594                 {
1595                         bArmature *arm= (bArmature *)ob->data;
1596                         
1597                         if ((ads->filterflag & ADS_FILTER_NOARM) == 0) {
1598                                 ANIMDATA_FILTER_CASES(arm,
1599                                         { /* AnimData blocks - do nothing... */ },
1600                                         obdata_ok= 1;,
1601                                         obdata_ok= 1;,
1602                                         obdata_ok= 1;)
1603                         }
1604                 }
1605                         break;
1606                 case OB_MESH: /* ------- Mesh ---------- */
1607                 {
1608                         Mesh *me= (Mesh *)ob->data;
1609                         
1610                         if ((ads->filterflag & ADS_FILTER_NOMESH) == 0) {
1611                                 ANIMDATA_FILTER_CASES(me,
1612                                         { /* AnimData blocks - do nothing... */ },
1613                                         obdata_ok= 1;,
1614                                         obdata_ok= 1;,
1615                                         obdata_ok= 1;)
1616                         }
1617                 }
1618                         break;
1619         }
1620         if (obdata_ok) 
1621                 items += animdata_filter_dopesheet_obdata(anim_data, ads, base, filter_mode);
1622
1623         /* particles */
1624         if (ob->particlesystem.first && !(ads->filterflag & ADS_FILTER_NOPART))
1625                 items += animdata_filter_dopesheet_particles(anim_data, ads, base, filter_mode);
1626         
1627         /* return the number of items added to the list */
1628         return items;
1629 }       
1630
1631 static int animdata_filter_dopesheet_scene (ListBase *anim_data, bDopeSheet *ads, Scene *sce, int filter_mode)
1632 {
1633         World *wo= sce->world;
1634         bNodeTree *ntree= sce->nodetree;
1635         AnimData *adt= NULL;
1636         bAnimListElem *ale;
1637         int items = 0;
1638         
1639         /* add scene as a channel first (even if we aren't showing scenes we still need to show the scene's sub-data */
1640         if ((filter_mode & (ANIMFILTER_CURVESONLY|ANIMFILTER_NLATRACKS)) == 0) {
1641                 /* check if filtering by selection */
1642                 if (ANIMCHANNEL_SELOK( (sce->flag & SCE_DS_SELECTED) )) {
1643                         ale= make_new_animlistelem(sce, ANIMTYPE_SCENE, NULL, ANIMTYPE_NONE, NULL);
1644                         if (ale) {
1645                                 BLI_addtail(anim_data, ale);
1646                                 items++;
1647                         }
1648                 }
1649         }
1650         
1651         /* if collapsed, don't go any further (unless adding keyframes only) */
1652         if ( (EXPANDED_SCEC(sce) == 0) && !(filter_mode & (ANIMFILTER_CURVESONLY|ANIMFILTER_NLATRACKS)) )
1653                 return items;
1654                 
1655         /* Action, Drivers, or NLA for Scene */
1656         if ((ads->filterflag & ADS_FILTER_NOSCE) == 0) {
1657                 adt= sce->adt;
1658                 ANIMDATA_FILTER_CASES(sce,
1659                         { /* AnimData blocks - do nothing... */ },
1660                         { /* nla */
1661                                 /* add NLA tracks */
1662                                 items += animdata_filter_nla(anim_data, ads, adt, filter_mode, sce, ANIMTYPE_SCENE, (ID *)sce);
1663                         },
1664                         { /* drivers */
1665                                 /* include drivers-expand widget? */
1666                                 if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
1667                                         ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLDRIVERS, sce, ANIMTYPE_SCENE, (ID *)sce);
1668                                         if (ale) {
1669                                                 BLI_addtail(anim_data, ale);
1670                                                 items++;
1671                                         }
1672                                 }
1673                                 
1674                                 /* add F-Curve channels (drivers are F-Curves) */
1675                                 if (EXPANDED_DRVD(adt) || !(filter_mode & ANIMFILTER_CHANNELS)) {
1676                                         items += animdata_filter_fcurves(anim_data, ads, adt->drivers.first, NULL, sce, ANIMTYPE_SCENE, filter_mode, (ID *)sce);
1677                                 }
1678                         },
1679                         { /* action */
1680                                 /* include action-expand widget? */
1681                                 if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
1682                                         ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLACTD, sce, ANIMTYPE_SCENE, (ID *)sce);
1683                                         if (ale) {
1684                                                 BLI_addtail(anim_data, ale);
1685                                                 items++;
1686                                         }
1687                                 }
1688                                 
1689                                 /* add F-Curve channels? */
1690                                 if (EXPANDED_ACTC(adt->action) || !(filter_mode & ANIMFILTER_CHANNELS)) {
1691                                         items += animdata_filter_action(anim_data, ads, adt->action, filter_mode, sce, ANIMTYPE_SCENE, (ID *)sce); 
1692                                 }
1693                         }
1694                 )
1695         }
1696         
1697         /* world */
1698         if ((wo && wo->adt) && !(ads->filterflag & ADS_FILTER_NOWOR)) {
1699                 /* Action, Drivers, or NLA for World */
1700                 adt= wo->adt;
1701                 ANIMDATA_FILTER_CASES(wo,
1702                         { /* AnimData blocks - do nothing... */ },
1703                         { /* nla */
1704                                 /* add NLA tracks */
1705                                 items += animdata_filter_nla(anim_data, ads, adt, filter_mode, wo, ANIMTYPE_DSWOR, (ID *)wo);
1706                         },
1707                         { /* drivers */
1708                                 /* include world-expand widget? */
1709                                 if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
1710                                         ale= make_new_animlistelem(wo, ANIMTYPE_DSWOR, sce, ANIMTYPE_SCENE, (ID *)wo);
1711                                         if (ale) {
1712                                                 BLI_addtail(anim_data, ale);
1713                                                 items++;
1714                                         }
1715                                 }
1716                                 
1717                                 /* add F-Curve channels (drivers are F-Curves) */
1718                                 if (FILTER_WOR_SCED(wo)/*EXPANDED_DRVD(adt)*/ || !(filter_mode & ANIMFILTER_CHANNELS)) {
1719                                         // XXX owner info is messed up now...
1720                                         items += animdata_filter_fcurves(anim_data, ads, adt->drivers.first, NULL, wo, ANIMTYPE_DSWOR, filter_mode, (ID *)wo);
1721                                 }
1722                         },
1723                         { /* action */
1724                                 /* include world-expand widget? */
1725                                 if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
1726                                         ale= make_new_animlistelem(wo, ANIMTYPE_DSWOR, sce, ANIMTYPE_SCENE, (ID *)sce);
1727                                         if (ale) {
1728                                                 BLI_addtail(anim_data, ale);
1729                                                 items++;
1730                                         }
1731                                 }
1732                                 
1733                                 /* add channels */
1734                                 if (FILTER_WOR_SCED(wo) || (filter_mode & ANIMFILTER_CURVESONLY)) {
1735                                         items += animdata_filter_action(anim_data, ads, adt->action, filter_mode, wo, ANIMTYPE_DSWOR, (ID *)wo); 
1736                                 }
1737                         }
1738                 )
1739         }
1740         /* nodetree */
1741         if ((ntree && ntree->adt) && !(ads->filterflag & ADS_FILTER_NONTREE)) {
1742                 /* Action, Drivers, or NLA for Nodetree */
1743                 adt= ntree->adt;
1744                 ANIMDATA_FILTER_CASES(ntree,
1745                         { /* AnimData blocks - do nothing... */ },
1746                         { /* nla */
1747                                 /* add NLA tracks */
1748                                 items += animdata_filter_nla(anim_data, ads, adt, filter_mode, ntree, ANIMTYPE_DSNTREE, (ID *)ntree);
1749                         },
1750                         { /* drivers */
1751                                 /* include nodetree-expand widget? */
1752                                 if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
1753                                         ale= make_new_animlistelem(ntree, ANIMTYPE_DSNTREE, sce, ANIMTYPE_SCENE, (ID *)ntree);
1754                                         if (ale) {
1755                                                 BLI_addtail(anim_data, ale);
1756                                                 items++;
1757                                         }
1758                                 }
1759                                 
1760                                 /* add F-Curve channels (drivers are F-Curves) */
1761                                 if (FILTER_NTREE_SCED(ntree)/*EXPANDED_DRVD(adt)*/ || !(filter_mode & ANIMFILTER_CHANNELS)) {
1762                                         // XXX owner info is messed up now...
1763                                         items += animdata_filter_fcurves(anim_data, ads, adt->drivers.first, NULL, ntree, ANIMTYPE_DSNTREE, filter_mode, (ID *)ntree);
1764                                 }
1765                         },
1766                         { /* action */
1767                                 /* include nodetree-expand widget? */
1768                                 if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
1769                                         ale= make_new_animlistelem(ntree, ANIMTYPE_DSNTREE, sce, ANIMTYPE_SCENE, (ID *)sce);
1770                                         if (ale) {
1771                                                 BLI_addtail(anim_data, ale);
1772                                                 items++;
1773                                         }
1774                                 }
1775                                 
1776                                 /* add channels */
1777                                 if (FILTER_NTREE_SCED(ntree) || (filter_mode & ANIMFILTER_CURVESONLY)) {
1778                                         items += animdata_filter_action(anim_data, ads, adt->action, filter_mode, ntree, ANIMTYPE_DSNTREE, (ID *)ntree); 
1779                                 }
1780                         }
1781                 )
1782         }
1783
1784         
1785         // TODO: scene compositing nodes (these aren't standard node-trees)
1786         
1787         /* return the number of items added to the list */
1788         return items;
1789 }
1790
1791 // 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)
1792 static int animdata_filter_dopesheet (ListBase *anim_data, bAnimContext *ac, bDopeSheet *ads, int filter_mode)
1793 {
1794         Scene *sce= (Scene *)ads->source;
1795         Base *base;
1796         bAnimListElem *ale;
1797         int items = 0;
1798         
1799         /* check that we do indeed have a scene */
1800         if ((ads->source == NULL) || (GS(ads->source->name)!=ID_SCE)) {
1801                 printf("DopeSheet Error: Not scene!\n");
1802                 if (G.f & G_DEBUG)
1803                         printf("\tPointer = %p, Name = '%s' \n", ads->source, (ads->source)?ads->source->name:NULL);
1804                 return 0;
1805         }
1806         
1807         /* scene-linked animation */
1808         // TODO: sequencer, composite nodes - are we to include those here too?
1809         {
1810                 short sceOk= 0, worOk= 0, nodeOk=0;
1811                 
1812                 /* check filtering-flags if ok */
1813                 ANIMDATA_FILTER_CASES(sce, 
1814                         {
1815                                 /* for the special AnimData blocks only case, we only need to add
1816                                  * the block if it is valid... then other cases just get skipped (hence ok=0)
1817                                  */
1818                                 ANIMDATA_ADD_ANIMDATA(sce);
1819                                 sceOk=0;
1820                         },
1821                         sceOk= !(ads->filterflag & ADS_FILTER_NOSCE);, 
1822                         sceOk= !(ads->filterflag & ADS_FILTER_NOSCE);, 
1823                         sceOk= !(ads->filterflag & ADS_FILTER_NOSCE);)
1824                 if (sce->world) {
1825                         ANIMDATA_FILTER_CASES(sce->world, 
1826                                 {
1827                                         /* for the special AnimData blocks only case, we only need to add
1828                                          * the block if it is valid... then other cases just get skipped (hence ok=0)
1829                                          */
1830                                         ANIMDATA_ADD_ANIMDATA(sce->world);
1831                                         worOk=0;
1832                                 },
1833                                 worOk= !(ads->filterflag & ADS_FILTER_NOWOR);, 
1834                                 worOk= !(ads->filterflag & ADS_FILTER_NOWOR);, 
1835                                 worOk= !(ads->filterflag & ADS_FILTER_NOWOR);)
1836                 }
1837                 if (sce->nodetree) {
1838                         ANIMDATA_FILTER_CASES(sce->nodetree, 
1839                                 {
1840                                         /* for the special AnimData blocks only case, we only need to add
1841                                          * the block if it is valid... then other cases just get skipped (hence ok=0)
1842                                          */
1843                                         ANIMDATA_ADD_ANIMDATA(sce->nodetree);
1844                                         nodeOk=0;
1845                                 },
1846                                 nodeOk= !(ads->filterflag & ADS_FILTER_NONTREE);, 
1847                                 nodeOk= !(ads->filterflag & ADS_FILTER_NONTREE);, 
1848                                 nodeOk= !(ads->filterflag & ADS_FILTER_NONTREE);)
1849                 }
1850                 
1851                 /* if only F-Curves with visible flags set can be shown, check that 
1852                  * datablocks haven't been set to invisible 
1853                  */
1854                 if (filter_mode & ANIMFILTER_CURVEVISIBLE) {
1855                         if ((sce->adt) && (sce->adt->flag & ADT_CURVES_NOT_VISIBLE))
1856                                 sceOk= worOk= nodeOk= 0;
1857                 }
1858                 
1859                 /* check if not all bad (i.e. so there is something to show) */
1860                 if ( !(!sceOk && !worOk && !nodeOk) ) {
1861                         /* add scene data to the list of filtered channels */
1862                         items += animdata_filter_dopesheet_scene(anim_data, ads, sce, filter_mode);
1863                 }
1864         }
1865         
1866         
1867         /* loop over all bases in the scene */
1868         for (base= sce->base.first; base; base= base->next) {
1869                 /* check if there's an object (all the relevant checks are done in the ob-function) */
1870                 if (base->object) {
1871                         Object *ob= base->object;
1872                         Key *key= ob_get_key(ob);
1873                         short actOk=1, keyOk=1, dataOk=1, matOk=1, partOk=1;
1874                         
1875                         /* firstly, check if object can be included, by the following factors:
1876                          *      - if only visible, must check for layer and also viewport visibility
1877                          *      - if only selected, must check if object is selected 
1878                          *      - there must be animation data to edit
1879                          */
1880                         // TODO: if cache is implemented, just check name here, and then 
1881                         if (filter_mode & ANIMFILTER_VISIBLE) {
1882                                 /* layer visibility - we check both object and base, since these may not be in sync yet */
1883                                 if ((sce->lay & (ob->lay|base->lay))==0) continue;
1884                                 
1885                                 /* outliner restrict-flag */
1886                                 if (ob->restrictflag & OB_RESTRICT_VIEW) continue;
1887                         }
1888                         
1889                         /* if only F-Curves with visible flags set can be shown, check that 
1890                          * datablock hasn't been set to invisible 
1891                          */
1892                         if (filter_mode & ANIMFILTER_CURVEVISIBLE) {
1893                                 if ((ob->adt) && (ob->adt->flag & ADT_CURVES_NOT_VISIBLE))
1894                                         continue;
1895                         }
1896                         
1897                         /* additionally, dopesheet filtering also affects what objects to consider */
1898                         if (ads->filterflag) {
1899                                 /* check selection and object type filters */
1900                                 if ( (ads->filterflag & ADS_FILTER_ONLYSEL) && !((base->flag & SELECT) /*|| (base == sce->basact)*/) )  {
1901                                         /* only selected should be shown */
1902                                         continue;
1903                                 }
1904                                 
1905                                 /* check filters for datatypes */
1906                                         /* object */
1907                                 actOk= 0;
1908                                 keyOk= 0;
1909                                 ANIMDATA_FILTER_CASES(ob, 
1910                                         {
1911                                                 /* for the special AnimData blocks only case, we only need to add
1912                                                  * the block if it is valid... then other cases just get skipped (hence ok=0)
1913                                                  */
1914                                                 ANIMDATA_ADD_ANIMDATA(ob);
1915                                                 actOk=0;
1916                                         },
1917                                         actOk= 1;, 
1918                                         actOk= 1;, 
1919                                         actOk= 1;)
1920                                 if (key) {
1921                                         /* shapekeys */
1922                                         ANIMDATA_FILTER_CASES(key, 
1923                                                 {
1924                                                         /* for the special AnimData blocks only case, we only need to add
1925                                                          * the block if it is valid... then other cases just get skipped (hence ok=0)
1926                                                          */
1927                                                         ANIMDATA_ADD_ANIMDATA(key);
1928                                                         keyOk=0;
1929                                                 },
1930                                                 keyOk= 1;, 
1931                                                 keyOk= 1;, 
1932                                                 keyOk= 1;)
1933                                 }
1934                                 
1935                                 /* materials - only for geometric types */
1936                                 matOk= 0; /* by default, not ok... */
1937                                 if ( !(ads->filterflag & ADS_FILTER_NOMAT) && (ob->totcol) && 
1938                                          ELEM5(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL) ) 
1939                                 {
1940                                         int a;
1941                                         
1942                                         /* firstly check that we actuallly have some materials */
1943                                         for (a=0; a < ob->totcol; a++) {
1944                                                 Material *ma= give_current_material(ob, a);
1945                                                 
1946                                                 if (ma) {
1947                                                         /* if material has relevant animation data, break */
1948                                                         ANIMDATA_FILTER_CASES(ma, 
1949                                                                 {
1950                                                                         /* for the special AnimData blocks only case, we only need to add
1951                                                                          * the block if it is valid... then other cases just get skipped (hence ok=0)
1952                                                                          */
1953                                                                         ANIMDATA_ADD_ANIMDATA(ma);
1954                                                                         matOk=0;
1955                                                                 },
1956                                                                 matOk= 1;, 
1957                                                                 matOk= 1;, 
1958                                                                 matOk= 1;)
1959                                                 }
1960                                                         
1961                                                 if (matOk) 
1962                                                         break;
1963                                         }
1964                                 }
1965                                 
1966                                 /* data */
1967                                 switch (ob->type) {
1968                                         case OB_CAMERA: /* ------- Camera ------------ */
1969                                         {
1970                                                 Camera *ca= (Camera *)ob->data;
1971                                                 dataOk= 0;
1972                                                 ANIMDATA_FILTER_CASES(ca, 
1973                                                         if ((ads->filterflag & ADS_FILTER_NOCAM)==0) {
1974                                                                 /* for the special AnimData blocks only case, we only need to add
1975                                                                  * the block if it is valid... then other cases just get skipped (hence ok=0)
1976                                                                  */
1977                                                                 ANIMDATA_ADD_ANIMDATA(ca);
1978                                                                 dataOk=0;
1979                                                         },
1980                                                         dataOk= !(ads->filterflag & ADS_FILTER_NOCAM);, 
1981                                                         dataOk= !(ads->filterflag & ADS_FILTER_NOCAM);, 
1982                                                         dataOk= !(ads->filterflag & ADS_FILTER_NOCAM);)
1983                                         }
1984                                                 break;
1985                                         case OB_LAMP: /* ---------- Lamp ----------- */
1986                                         {
1987                                                 Lamp *la= (Lamp *)ob->data;
1988                                                 dataOk= 0;
1989                                                 ANIMDATA_FILTER_CASES(la, 
1990                                                         if ((ads->filterflag & ADS_FILTER_NOLAM)==0) {
1991                                                                 /* for the special AnimData blocks only case, we only need to add
1992                                                                  * the block if it is valid... then other cases just get skipped (hence ok=0)
1993                                                                  */
1994                                                                 ANIMDATA_ADD_ANIMDATA(la);
1995                                                                 dataOk=0;
1996                                                         },
1997                                                         dataOk= !(ads->filterflag & ADS_FILTER_NOLAM);, 
1998                                                         dataOk= !(ads->filterflag & ADS_FILTER_NOLAM);, 
1999                                                         dataOk= !(ads->filterflag & ADS_FILTER_NOLAM);)
2000                                         }
2001                                                 break;
2002                                         case OB_CURVE: /* ------- Curve ---------- */
2003                                         case OB_SURF: /* ------- Nurbs Surface ---------- */
2004                                         case OB_FONT: /* ------- Text Curve ---------- */
2005                                         {
2006                                                 Curve *cu= (Curve *)ob->data;
2007                                                 dataOk= 0;
2008                                                 ANIMDATA_FILTER_CASES(cu, 
2009                                                         if ((ads->filterflag & ADS_FILTER_NOCUR)==0) {
2010                                                                 /* for the special AnimData blocks only case, we only need to add
2011                                                                  * the block if it is valid... then other cases just get skipped (hence ok=0)
2012                                                                  */
2013                                                                 ANIMDATA_ADD_ANIMDATA(cu);
2014                                                                 dataOk=0;
2015                                                         },
2016                                                         dataOk= !(ads->filterflag & ADS_FILTER_NOCUR);, 
2017                                                         dataOk= !(ads->filterflag & ADS_FILTER_NOCUR);, 
2018                                                         dataOk= !(ads->filterflag & ADS_FILTER_NOCUR);)
2019                                         }
2020                                                 break;
2021                                         case OB_MBALL: /* ------- MetaBall ---------- */
2022                                         {
2023                                                 MetaBall *mb= (MetaBall *)ob->data;
2024                                                 dataOk= 0;
2025                                                 ANIMDATA_FILTER_CASES(mb, 
2026                                                         if ((ads->filterflag & ADS_FILTER_NOMBA)==0) {
2027                                                                 /* for the special AnimData blocks only case, we only need to add
2028                                                                  * the block if it is valid... then other cases just get skipped (hence ok=0)
2029                                                                  */
2030                                                                 ANIMDATA_ADD_ANIMDATA(mb);
2031                                                                 dataOk=0;
2032                                                         },
2033                                                         dataOk= !(ads->filterflag & ADS_FILTER_NOMBA);, 
2034                                                         dataOk= !(ads->filterflag & ADS_FILTER_NOMBA);, 
2035                                                         dataOk= !(ads->filterflag & ADS_FILTER_NOMBA);)
2036                                         }
2037                                                 break;
2038                                         case OB_ARMATURE: /* ------- Armature ---------- */
2039                                         {
2040                                                 bArmature *arm= (bArmature *)ob->data;
2041                                                 dataOk= 0;
2042                                                 ANIMDATA_FILTER_CASES(arm, 
2043                                                         if ((ads->filterflag & ADS_FILTER_NOARM)==0) {
2044                                                                 /* for the special AnimData blocks only case, we only need to add
2045                                                                  * the block if it is valid... then other cases just get skipped (hence ok=0)
2046                                                                  */
2047                                                                 ANIMDATA_ADD_ANIMDATA(arm);
2048                                                                 dataOk=0;
2049                                                         },
2050                                                         dataOk= !(ads->filterflag & ADS_FILTER_NOARM);, 
2051                                                         dataOk= !(ads->filterflag & ADS_FILTER_NOARM);, 
2052                                                         dataOk= !(ads->filterflag & ADS_FILTER_NOARM);)
2053                                         }
2054                                                 break;
2055                                         case OB_MESH: /* ------- Mesh ---------- */
2056                                         {
2057                                                 Mesh *me= (Mesh *)ob->data;
2058                                                 dataOk= 0;
2059                                                 ANIMDATA_FILTER_CASES(me, 
2060                                                         if ((ads->filterflag & ADS_FILTER_NOMESH)==0) {
2061                                                                 /* for the special AnimData blocks only case, we only need to add
2062                                                                  * the block if it is valid... then other cases just get skipped (hence ok=0)
2063                                                                  */
2064                                                                 ANIMDATA_ADD_ANIMDATA(me);
2065                                                                 dataOk=0;
2066                                                         },
2067                                                         dataOk= !(ads->filterflag & ADS_FILTER_NOMESH);, 
2068                                                         dataOk= !(ads->filterflag & ADS_FILTER_NOMESH);, 
2069                                                         dataOk= !(ads->filterflag & ADS_FILTER_NOMESH);)
2070                                         }
2071                                                 break;
2072                                         default: /* --- other --- */
2073                                                 dataOk= 0;
2074                                                 break;
2075                                 }
2076                                 
2077                                 /* particles */
2078                                 partOk = 0;
2079                                 if (!(ads->filterflag & ADS_FILTER_NOPART) && ob->particlesystem.first) {
2080                                         ParticleSystem *psys = ob->particlesystem.first;
2081                                         for(; psys; psys=psys->next) {
2082                                                 if (psys->part) {
2083                                                         /* if particlesettings has relevant animation data, break */
2084                                                         ANIMDATA_FILTER_CASES(psys->part, 
2085                                                                 {
2086                                                                         /* for the special AnimData blocks only case, we only need to add
2087                                                                          * the block if it is valid... then other cases just get skipped (hence ok=0)
2088                                                                          */
2089                                                                         ANIMDATA_ADD_ANIMDATA(psys->part);
2090                                                                         partOk=0;
2091                                                                 },
2092                                                                 partOk= 1;, 
2093                                                                 partOk= 1;, 
2094                                                                 partOk= 1;)
2095                                                 }
2096                                                         
2097                                                 if (partOk) 
2098                                                         break;
2099                                         }
2100                                 }
2101                                 
2102                                 /* check if all bad (i.e. nothing to show) */
2103                                 if (!actOk && !keyOk && !dataOk && !matOk && !partOk)
2104                                         continue;
2105                         }
2106                         else {
2107                                 /* check data-types */
2108                                 actOk= ANIMDATA_HAS_KEYS(ob);
2109                                 keyOk= (key != NULL);
2110                                 
2111                                 /* materials - only for geometric types */
2112                                 matOk= 0; /* by default, not ok... */
2113                                 if (ELEM5(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL) && (ob->totcol)) 
2114                                 {
2115                                         int a;
2116                                         
2117                                         /* firstly check that we actuallly have some materials */
2118                                         for (a=0; a < ob->totcol; a++) {
2119                                                 Material *ma= give_current_material(ob, a);
2120                                                 
2121                                                 if ((ma) && ANIMDATA_HAS_KEYS(ma)) {
2122                                                         matOk= 1;
2123                                                         break;
2124                                                 }
2125                                         }
2126                                 }
2127                                 
2128                                 /* data */
2129                                 switch (ob->type) {
2130                                         case OB_CAMERA: /* ------- Camera ------------ */
2131                                         {
2132                                                 Camera *ca= (Camera *)ob->data;
2133                                                 dataOk= ANIMDATA_HAS_KEYS(ca);                                          
2134                                         }
2135                                                 break;
2136                                         case OB_LAMP: /* ---------- Lamp ----------- */
2137                                         {
2138                                                 Lamp *la= (Lamp *)ob->data;
2139                                                 dataOk= ANIMDATA_HAS_KEYS(la);  
2140                                         }
2141                                                 break;
2142                                         case OB_CURVE: /* ------- Curve ---------- */
2143                                         case OB_SURF: /* ------- Nurbs Surface ---------- */
2144                                         case OB_FONT: /* ------- Text Curve ---------- */
2145                                         {
2146                                                 Curve *cu= (Curve *)ob->data;
2147                                                 dataOk= ANIMDATA_HAS_KEYS(cu);  
2148                                         }
2149                                                 break;
2150                                         case OB_MBALL: /* -------- Metas ---------- */
2151                                         {
2152                                                 MetaBall *mb= (MetaBall *)ob->data;
2153                                                 dataOk= ANIMDATA_HAS_KEYS(mb);  
2154                                         }
2155                                                 break;
2156                                         case OB_ARMATURE: /* -------- Armature ---------- */
2157                                         {
2158                                                 bArmature *arm= (bArmature *)ob->data;
2159                                                 dataOk= ANIMDATA_HAS_KEYS(arm); 
2160                                         }
2161                                                 break;
2162                                         case OB_MESH: /* -------- Mesh ---------- */
2163                                         {
2164                                                 Mesh *me= (Mesh *)ob->data;
2165                                                 dataOk= ANIMDATA_HAS_KEYS(me);  
2166                                         }
2167                                                 break;
2168                                         default: /* --- other --- */
2169                                                 dataOk= 0;
2170                                                 break;
2171                                 }
2172                                 
2173                                 /* particles */
2174                                 partOk = 0;
2175                                 if (ob->particlesystem.first) {
2176                                         ParticleSystem *psys = ob->particlesystem.first;
2177                                         for(; psys; psys=psys->next) {
2178                                                 if(psys->part && ANIMDATA_HAS_KEYS(psys->part)) {
2179                                                         partOk = 1;
2180                                                         break;
2181                                                 }
2182                                         }
2183                                 }
2184                                 
2185                                 /* check if all bad (i.e. nothing to show) */
2186                                 if (!actOk && !keyOk && !dataOk && !matOk && !partOk)
2187                                         continue;
2188                         }
2189                         
2190                         /* since we're still here, this object should be usable */
2191                         items += animdata_filter_dopesheet_ob(anim_data, ads, base, filter_mode);
2192                 }
2193         }
2194         
2195         /* return the number of items in the list */
2196         return items;
2197 }
2198
2199 /* Summary track for DopeSheet/Action Editor 
2200  *      - return code is whether the summary lets the other channels get drawn
2201  */
2202 static short animdata_filter_dopesheet_summary (bAnimContext *ac, ListBase *anim_data, int filter_mode, int *items)
2203 {
2204         bDopeSheet *ads = NULL;
2205         
2206         /* get the DopeSheet information to use 
2207          *      - we should only need to deal with the DopeSheet/Action Editor, 
2208          *        since all the other Animation Editors won't have this concept
2209          *        being applicable.
2210          */
2211         if ((ac && ac->sa) && (ac->sa->spacetype == SPACE_ACTION)) {
2212                 SpaceAction *saction= (SpaceAction *)ac->sa->spacedata.first;
2213                 ads= &saction->ads;
2214         }
2215         else {
2216                 /* invalid space type - skip this summary channels */
2217                 return 1;
2218         }
2219         
2220         /* dopesheet summary 
2221          *      - only for drawing and/or selecting keyframes in channels, but not for real editing 
2222          *      - only useful for DopeSheet Editor, where the summary is useful
2223          */
2224         // TODO: we should really check if some other prohibited filters are also active, but that can be for later
2225         if ((filter_mode & ANIMFILTER_CHANNELS) && (ads->filterflag & ADS_FILTER_SUMMARY)) {
2226                 bAnimListElem *ale= make_new_animlistelem(ac, ANIMTYPE_SUMMARY, NULL, ANIMTYPE_NONE, NULL);
2227                 if (ale) {
2228                         BLI_addtail(anim_data, ale);
2229                         (*items)++;
2230                 }
2231                 
2232                 /* if summary is collapsed, don't show other channels beneath this 
2233                  *      - this check is put inside the summary check so that it doesn't interfere with normal operation
2234                  */ 
2235                 if (ads->flag & ADS_FLAG_SUMMARY_COLLAPSED)
2236                         return 0;
2237         }
2238         
2239         /* the other channels beneath this can be shown */
2240         return 1;
2241 }  
2242
2243 /* ----------- Public API --------------- */
2244
2245 /* This function filters the active data source to leave only animation channels suitable for
2246  * usage by the caller. It will return the length of the list 
2247  * 
2248  *      *anim_data: is a pointer to a ListBase, to which the filtered animation channels
2249  *              will be placed for use.
2250  *      filter_mode: how should the data be filtered - bitmapping accessed flags
2251  */
2252 int ANIM_animdata_filter (bAnimContext *ac, ListBase *anim_data, int filter_mode, void *data, short datatype)
2253 {
2254         int items = 0;
2255         
2256         /* only filter data if there's somewhere to put it */
2257         if (data && anim_data) {
2258                 bAnimListElem *ale, *next;
2259                 Object *obact= (ac) ? ac->obact : NULL;
2260                 
2261                 /* firstly filter the data */
2262                 switch (datatype) {
2263                         case ANIMCONT_ACTION:   /* 'Action Editor' */
2264                         {
2265                                 /* the check for the DopeSheet summary is included here since the summary works here too */
2266                                 if (animdata_filter_dopesheet_summary(ac, anim_data, filter_mode, &items))
2267                                         items += animdata_filter_action(anim_data, NULL, data, filter_mode, NULL, ANIMTYPE_NONE, (ID *)obact);
2268                         }
2269                                 break;
2270                                 
2271                         case ANIMCONT_SHAPEKEY: /* 'ShapeKey Editor' */
2272                         {
2273                                 /* the check for the DopeSheet summary is included here since the summary works here too */
2274                                 if (animdata_filter_dopesheet_summary(ac, anim_data, filter_mode, &items))
2275                                         items= animdata_filter_shapekey(anim_data, data, filter_mode);
2276                         }
2277                                 break;
2278                                 
2279                         case ANIMCONT_GPENCIL:
2280                         {
2281                                 //items= animdata_filter_gpencil(anim_data, data, filter_mode);
2282                         }
2283                                 break;
2284                                 
2285                         case ANIMCONT_DOPESHEET: /* 'DopeSheet Editor' */
2286                         {
2287                                 /* the DopeSheet editor is the primary place where the DopeSheet summaries are useful */
2288                                 if (animdata_filter_dopesheet_summary(ac, anim_data, filter_mode, &items))
2289                                         items += animdata_filter_dopesheet(anim_data, ac, data, filter_mode);
2290                         }
2291                                 break;
2292                                 
2293                         case ANIMCONT_FCURVES: /* Graph Editor -> FCurves/Animation Editing */
2294                         case ANIMCONT_DRIVERS: /* Graph Editor -> Drivers Editing */
2295                         case ANIMCONT_NLA: /* NLA Editor */
2296                         {
2297                                 /* all of these editors use the basic DopeSheet data for filtering options, but don't have all the same features */
2298                                 items = animdata_filter_dopesheet(anim_data, ac, data, filter_mode);
2299                         }
2300                                 break;
2301                 }
2302                         
2303                 /* remove any weedy entries */
2304                 // XXX this is weedy code!
2305                 for (ale= anim_data->first; ale; ale= next) {
2306                         next= ale->next;
2307                         
2308                         if (ale->type == ANIMTYPE_NONE) {
2309                                 items--;
2310                                 BLI_freelinkN(anim_data, ale);
2311                         }
2312                 }
2313         }
2314         
2315         /* return the number of items in the list */
2316         return items;
2317 }
2318
2319 /* ************************************************************ */