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