4 * ***** BEGIN GPL LICENSE BLOCK *****
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.
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.
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.
20 * The Original Code is Copyright (C) 2008 Blender Foundation, Joshua Leung
21 * All rights reserved.
24 * Contributor(s): Joshua Leung (original author)
26 * ***** END GPL LICENSE BLOCK *****
29 /** \file blender/editors/animation/anim_filter.c
30 * \ingroup edanimation
34 /* This file contains a system used to provide a layer of abstraction between sources
35 * of animation data and tools in Animation Editors. The method used here involves
36 * generating a list of edit structures which enable tools to naively perform the actions
37 * they require without all the boiler-plate associated with loops within loops and checking
38 * for cases to ignore.
40 * While this is primarily used for the Action/Dopesheet Editor (and its accessory modes),
41 * the Graph Editor also uses this for its channel list and for determining which curves
42 * are being edited. Likewise, the NLA Editor also uses this for its channel list and in
45 * Note: much of the original system this was based on was built before the creation of the RNA
46 * system. In future, it would be interesting to replace some parts of this code with RNA queries,
47 * however, RNA does not eliminate some of the boiler-plate reduction benefits presented by this
48 * system, so if any such work does occur, it should only be used for the internals used here...
50 * -- Joshua Leung, Dec 2008 (Last revision July 2009)
55 #include "DNA_anim_types.h"
56 #include "DNA_armature_types.h"
57 #include "DNA_camera_types.h"
58 #include "DNA_lamp_types.h"
59 #include "DNA_lattice_types.h"
60 #include "DNA_key_types.h"
61 #include "DNA_material_types.h"
62 #include "DNA_mesh_types.h"
63 #include "DNA_meta_types.h"
64 #include "DNA_node_types.h"
65 #include "DNA_particle_types.h"
66 #include "DNA_space_types.h"
67 #include "DNA_sequence_types.h"
68 #include "DNA_scene_types.h"
69 #include "DNA_screen_types.h"
70 #include "DNA_world_types.h"
71 #include "DNA_gpencil_types.h"
72 #include "DNA_object_types.h"
74 #include "MEM_guardedalloc.h"
76 #include "BLI_blenlib.h"
77 #include "BLI_utildefines.h"
78 #include "BLI_ghash.h"
80 #include "BKE_animsys.h"
81 #include "BKE_action.h"
82 #include "BKE_fcurve.h"
83 #include "BKE_context.h"
84 #include "BKE_global.h"
85 #include "BKE_group.h"
88 #include "BKE_material.h"
90 #include "BKE_sequencer.h"
91 #include "BKE_utildefines.h"
93 #include "ED_anim_api.h"
94 #include "ED_markers.h"
96 /* ************************************************************ */
97 /* Blender Context <-> Animation Context mapping */
99 /* ----------- Private Stuff - Action Editor ------------- */
101 /* Get shapekey data being edited (for Action Editor -> ShapeKey mode) */
102 /* Note: there's a similar function in key.c (ob_get_key) */
103 static Key *actedit_get_shapekeys (bAnimContext *ac)
105 Scene *scene= ac->scene;
113 /* XXX pinning is not available in 'ShapeKey' mode... */
114 //if (saction->pin) return NULL;
116 /* shapekey data is stored with geometry data */
120 if (key->type == KEY_RELATIVE)
127 /* Get data being edited in Action Editor (depending on current 'mode') */
128 static short actedit_get_context (bAnimContext *ac, SpaceAction *saction)
130 /* sync settings with current view status, then return appropriate data */
131 switch (saction->mode) {
132 case SACTCONT_ACTION: /* 'Action Editor' */
133 /* if not pinned, sync with active object */
134 if (/*saction->pin == 0*/1) {
135 if (ac->obact && ac->obact->adt)
136 saction->action = ac->obact->adt->action;
138 saction->action= NULL;
141 ac->datatype= ANIMCONT_ACTION;
142 ac->data= saction->action;
144 ac->mode= saction->mode;
147 case SACTCONT_SHAPEKEY: /* 'ShapeKey Editor' */
148 ac->datatype= ANIMCONT_SHAPEKEY;
149 ac->data= actedit_get_shapekeys(ac);
151 ac->mode= saction->mode;
154 case SACTCONT_GPENCIL: /* Grease Pencil */ // XXX review how this mode is handled...
155 /* update scene-pointer (no need to check for pinning yet, as not implemented) */
156 saction->ads.source= (ID *)ac->scene;
158 ac->datatype= ANIMCONT_GPENCIL;
159 ac->data= &saction->ads;
161 ac->mode= saction->mode;
164 case SACTCONT_DOPESHEET: /* DopeSheet */
165 /* update scene-pointer (no need to check for pinning yet, as not implemented) */
166 saction->ads.source= (ID *)ac->scene;
168 ac->datatype= ANIMCONT_DOPESHEET;
169 ac->data= &saction->ads;
171 ac->mode= saction->mode;
174 default: /* unhandled yet */
175 ac->datatype= ANIMCONT_NONE;
183 /* ----------- Private Stuff - Graph Editor ------------- */
185 /* Get data being edited in Graph Editor (depending on current 'mode') */
186 static short graphedit_get_context (bAnimContext *ac, SpaceIpo *sipo)
188 /* init dopesheet data if non-existant (i.e. for old files) */
189 if (sipo->ads == NULL) {
190 sipo->ads= MEM_callocN(sizeof(bDopeSheet), "GraphEdit DopeSheet");
191 sipo->ads->source= (ID *)ac->scene;
194 /* set settings for Graph Editor - "Selected = Editable" */
195 if (sipo->flag & SIPO_SELCUVERTSONLY)
196 sipo->ads->filterflag |= ADS_FILTER_SELEDIT;
198 sipo->ads->filterflag &= ~ADS_FILTER_SELEDIT;
200 /* sync settings with current view status, then return appropriate data */
201 switch (sipo->mode) {
202 case SIPO_MODE_ANIMATION: /* Animation F-Curve Editor */
203 /* update scene-pointer (no need to check for pinning yet, as not implemented) */
204 sipo->ads->source= (ID *)ac->scene;
205 sipo->ads->filterflag &= ~ADS_FILTER_ONLYDRIVERS;
207 ac->datatype= ANIMCONT_FCURVES;
210 ac->mode= sipo->mode;
213 case SIPO_MODE_DRIVERS: /* Driver F-Curve Editor */
214 /* update scene-pointer (no need to check for pinning yet, as not implemented) */
215 sipo->ads->source= (ID *)ac->scene;
216 sipo->ads->filterflag |= ADS_FILTER_ONLYDRIVERS;
218 ac->datatype= ANIMCONT_DRIVERS;
221 ac->mode= sipo->mode;
224 default: /* unhandled yet */
225 ac->datatype= ANIMCONT_NONE;
233 /* ----------- Private Stuff - NLA Editor ------------- */
235 /* Get data being edited in Graph Editor (depending on current 'mode') */
236 static short nlaedit_get_context (bAnimContext *ac, SpaceNla *snla)
238 /* init dopesheet data if non-existant (i.e. for old files) */
239 if (snla->ads == NULL)
240 snla->ads= MEM_callocN(sizeof(bDopeSheet), "NlaEdit DopeSheet");
242 /* sync settings with current view status, then return appropriate data */
243 /* update scene-pointer (no need to check for pinning yet, as not implemented) */
244 snla->ads->source= (ID *)ac->scene;
245 snla->ads->filterflag |= ADS_FILTER_ONLYNLA;
247 ac->datatype= ANIMCONT_NLA;
253 /* ----------- Public API --------------- */
255 /* Obtain current anim-data context, given that context info from Blender context has already been set
256 * - AnimContext to write to is provided as pointer to var on stack so that we don't have
257 * allocation/freeing costs (which are not that avoidable with channels).
259 short ANIM_animdata_context_getdata (bAnimContext *ac)
264 /* context depends on editor we are currently in */
266 switch (sa->spacetype) {
269 SpaceAction *saction= (SpaceAction *)sa->spacedata.first;
270 ok= actedit_get_context(ac, saction);
276 SpaceIpo *sipo= (SpaceIpo *)sa->spacedata.first;
277 ok= graphedit_get_context(ac, sipo);
283 SpaceNla *snla= (SpaceNla *)sa->spacedata.first;
284 ok= nlaedit_get_context(ac, snla);
290 /* check if there's any valid data */
297 /* Obtain current anim-data context from Blender Context info
298 * - AnimContext to write to is provided as pointer to var on stack so that we don't have
299 * allocation/freeing costs (which are not that avoidable with channels).
300 * - Clears data and sets the information from Blender Context which is useful
302 short ANIM_animdata_get_context (const bContext *C, bAnimContext *ac)
304 ScrArea *sa= CTX_wm_area(C);
305 ARegion *ar= CTX_wm_region(C);
306 Scene *scene= CTX_data_scene(C);
308 /* clear old context info */
309 if (ac == NULL) return 0;
310 memset(ac, 0, sizeof(bAnimContext));
312 /* get useful default context settings from context */
315 ac->markers= ED_context_get_markers(C);
316 ac->obact= (scene->basact)? scene->basact->object : NULL;
320 ac->spacetype= (sa) ? sa->spacetype : 0;
321 ac->regiontype= (ar) ? ar->regiontype : 0;
323 /* get data context info */
324 return ANIM_animdata_context_getdata(ac);
327 /* ************************************************************ */
328 /* Blender Data <-- Filter --> Channels to be operated on */
330 /* quick macro to test if AnimData is usable */
331 #define ANIMDATA_HAS_KEYS(id) ((id)->adt && (id)->adt->action)
333 /* quick macro to test if AnimData is usable for drivers */
334 #define ANIMDATA_HAS_DRIVERS(id) ((id)->adt && (id)->adt->drivers.first)
336 /* quick macro to test if AnimData is usable for NLA */
337 #define ANIMDATA_HAS_NLA(id) ((id)->adt && (id)->adt->nla_tracks.first)
340 /* Quick macro to test for all three avove usability tests, performing the appropriate provided
341 * action for each when the AnimData context is appropriate.
343 * Priority order for this goes (most important, to least): AnimData blocks, NLA, Drivers, Keyframes.
345 * For this to work correctly, a standard set of data needs to be available within the scope that this
347 * - ListBase anim_data;
349 * - bAnimListElem *ale;
352 * - id: ID block which should have an AnimData pointer following it immediately, to use
353 * - adtOk: line or block of code to execute for AnimData-blocks case (usually ANIMDATA_ADD_ANIMDATA)
354 * - nlaOk: line or block of code to execute for NLA tracks+strips case
355 * - driversOk: line or block of code to execute for Drivers case
356 * - keysOk: line or block of code for Keyframes case
358 * The checks for the various cases are as follows:
359 * 0) top level: checks for animdata and also that all the F-Curves for the block will be visible
360 * 1) animdata check: for filtering animdata blocks only
361 * 2A) nla tracks: include animdata block's data as there are NLA tracks+strips there
362 * 2B) actions to convert to nla: include animdata block's data as there is an action that can be
363 * converted to a new NLA strip, and the filtering options allow this
364 * 3) drivers: include drivers from animdata block (for Drivers mode in Graph Editor)
365 * 4) normal keyframes: only when there is an active action
367 #define ANIMDATA_FILTER_CASES(id, adtOk, nlaOk, driversOk, keysOk) \
370 if (!(filter_mode & ANIMFILTER_CURVEVISIBLE) || !((id)->adt->flag & ADT_CURVES_NOT_VISIBLE)) {\
371 if (filter_mode & ANIMFILTER_ANIMDATA) {\
374 else if (ads->filterflag & ADS_FILTER_ONLYNLA) {\
375 if (ANIMDATA_HAS_NLA(id)) {\
378 else if (!(ads->filterflag & ADS_FILTER_NLA_NOACT) && ANIMDATA_HAS_KEYS(id)) {\
382 else if (ads->filterflag & ADS_FILTER_ONLYDRIVERS) {\
383 if (ANIMDATA_HAS_DRIVERS(id)) {\
388 if (ANIMDATA_HAS_KEYS(id)) {\
397 /* quick macro to add a pointer to an AnimData block as a channel */
398 #define ANIMDATA_ADD_ANIMDATA(id) \
400 ale= make_new_animlistelem((id)->adt, ANIMTYPE_ANIMDATA, NULL, ANIMTYPE_NONE, (ID *)id);\
402 BLI_addtail(anim_data, ale);\
407 /* quick macro to test if an anim-channel representing an AnimData block is suitably active */
408 #define ANIMCHANNEL_ACTIVEOK(ale) \
409 ( !(filter_mode & ANIMFILTER_ACTIVE) || !(ale->adt) || (ale->adt->flag & ADT_UI_ACTIVE) )
411 /* quick macro to test if an anim-channel (F-Curve, Group, etc.) is selected in an acceptable way */
412 #define ANIMCHANNEL_SELOK(test_func) \
413 ( !(filter_mode & (ANIMFILTER_SEL|ANIMFILTER_UNSEL)) || \
414 ((filter_mode & ANIMFILTER_SEL) && test_func) || \
415 ((filter_mode & ANIMFILTER_UNSEL) && test_func==0) )
417 /* quick macro to test if an anim-channel (F-Curve) is selected ok for editing purposes
418 * - _SELEDIT means that only selected curves will have visible+editable keyframes
420 * checks here work as follows:
421 * 1) seledit off - don't need to consider the implications of this option
422 * 2) foredit off - we're not considering editing, so channel is ok still
423 * 3) test_func (i.e. selection test) - only if selected, this test will pass
425 #define ANIMCHANNEL_SELEDITOK(test_func) \
426 ( !(filter_mode & ANIMFILTER_SELEDIT) || \
427 !(filter_mode & ANIMFILTER_FOREDIT) || \
430 /* ----------- 'Private' Stuff --------------- */
432 /* this function allocates memory for a new bAnimListElem struct for the
433 * provided animation channel-data.
435 static bAnimListElem *make_new_animlistelem (void *data, short datatype, void *owner, short ownertype, ID *owner_id)
437 bAnimListElem *ale= NULL;
439 /* only allocate memory if there is data to convert */
441 /* allocate and set generic data */
442 ale= MEM_callocN(sizeof(bAnimListElem), "bAnimListElem");
446 // XXX what is the point of the owner data?
447 // xxx try and use this to simplify the problem of finding whether parent channels are working...
449 ale->ownertype= ownertype;
452 ale->adt= BKE_animdata_from_id(owner_id);
456 case ANIMTYPE_SUMMARY:
458 /* nothing to include for now... this is just a dummy wrappy around all the other channels
459 * in the DopeSheet, and gets included at the start of the list
462 ale->datatype= ALE_ALL;
468 Scene *sce= (Scene *)data;
470 ale->flag= sce->flag;
473 ale->datatype= ALE_SCE;
475 ale->adt= BKE_animdata_from_id(data);
478 case ANIMTYPE_OBJECT:
480 Base *base= (Base *)data;
481 Object *ob= base->object;
486 ale->datatype= ALE_OB;
488 ale->adt= BKE_animdata_from_id(&ob->id);
491 case ANIMTYPE_FILLACTD:
493 bAction *act= (bAction *)data;
495 ale->flag= act->flag;
498 ale->datatype= ALE_ACT;
501 case ANIMTYPE_FILLDRIVERS:
503 AnimData *adt= (AnimData *)data;
505 ale->flag= adt->flag;
507 // XXX... drivers don't show summary for now
509 ale->datatype= ALE_NONE;
512 case ANIMTYPE_FILLMATD:
514 Object *ob= (Object *)data;
516 ale->flag= FILTER_MAT_OBJC(ob);
519 ale->datatype= ALE_NONE;
522 case ANIMTYPE_FILLPARTD:
524 Object *ob= (Object *)data;
526 ale->flag= FILTER_PART_OBJC(ob);
529 ale->datatype= ALE_NONE;
532 case ANIMTYPE_FILLTEXD:
536 switch (GS(id->name)) {
539 Material *ma= (Material *)id;
540 ale->flag= FILTER_TEX_MATC(ma);
545 Lamp *la= (Lamp *)id;
546 ale->flag= FILTER_TEX_LAMC(la);
551 World *wo= (World *)id;
552 ale->flag= FILTER_TEX_WORC(wo);
558 ale->datatype= ALE_NONE;
564 Material *ma= (Material *)data;
565 AnimData *adt= ma->adt;
567 ale->flag= FILTER_MAT_OBJD(ma);
569 ale->key_data= (adt) ? adt->action : NULL;
570 ale->datatype= ALE_ACT;
572 ale->adt= BKE_animdata_from_id(data);
577 Lamp *la= (Lamp *)data;
578 AnimData *adt= la->adt;
580 ale->flag= FILTER_LAM_OBJD(la);
582 ale->key_data= (adt) ? adt->action : NULL;
583 ale->datatype= ALE_ACT;
585 ale->adt= BKE_animdata_from_id(data);
590 Camera *ca= (Camera *)data;
591 AnimData *adt= ca->adt;
593 ale->flag= FILTER_CAM_OBJD(ca);
595 ale->key_data= (adt) ? adt->action : NULL;
596 ale->datatype= ALE_ACT;
598 ale->adt= BKE_animdata_from_id(data);
603 Curve *cu= (Curve *)data;
604 AnimData *adt= cu->adt;
606 ale->flag= FILTER_CUR_OBJD(cu);
608 ale->key_data= (adt) ? adt->action : NULL;
609 ale->datatype= ALE_ACT;
611 ale->adt= BKE_animdata_from_id(data);
616 bArmature *arm= (bArmature *)data;
617 AnimData *adt= arm->adt;
619 ale->flag= FILTER_ARM_OBJD(arm);
621 ale->key_data= (adt) ? adt->action : NULL;
622 ale->datatype= ALE_ACT;
624 ale->adt= BKE_animdata_from_id(data);
627 case ANIMTYPE_DSMESH:
629 Mesh *me= (Mesh *)data;
630 AnimData *adt= me->adt;
632 ale->flag= FILTER_MESH_OBJD(me);
634 ale->key_data= (adt) ? adt->action : NULL;
635 ale->datatype= ALE_ACT;
637 ale->adt= BKE_animdata_from_id(data);
642 Lattice *lt= (Lattice *)data;
643 AnimData *adt= lt->adt;
645 ale->flag= FILTER_LATTICE_OBJD(lt);
647 ale->key_data= (adt) ? adt->action : NULL;
648 ale->datatype= ALE_ACT;
650 ale->adt= BKE_animdata_from_id(data);
653 case ANIMTYPE_DSSKEY:
655 Key *key= (Key *)data;
656 AnimData *adt= key->adt;
658 ale->flag= FILTER_SKE_OBJD(key);
660 ale->key_data= (adt) ? adt->action : NULL;
661 ale->datatype= ALE_ACT;
663 ale->adt= BKE_animdata_from_id(data);
668 World *wo= (World *)data;
669 AnimData *adt= wo->adt;
671 ale->flag= FILTER_WOR_SCED(wo);
673 ale->key_data= (adt) ? adt->action : NULL;
674 ale->datatype= ALE_ACT;
676 ale->adt= BKE_animdata_from_id(data);
679 case ANIMTYPE_DSNTREE:
681 bNodeTree *ntree= (bNodeTree *)data;
682 AnimData *adt= ntree->adt;
684 ale->flag= FILTER_NTREE_SCED(ntree);
686 ale->key_data= (adt) ? adt->action : NULL;
687 ale->datatype= ALE_ACT;
689 ale->adt= BKE_animdata_from_id(data);
692 case ANIMTYPE_DSPART:
694 ParticleSettings *part= (ParticleSettings*)ale->data;
695 AnimData *adt= part->adt;
697 ale->flag= FILTER_PART_OBJD(part);
699 ale->key_data= (adt) ? adt->action : NULL;
700 ale->datatype= ALE_ACT;
702 ale->adt= BKE_animdata_from_id(data);
707 Tex *tex= (Tex *)data;
708 AnimData *adt= tex->adt;
710 ale->flag= FILTER_TEX_DATA(tex);
712 ale->key_data= (adt) ? adt->action : NULL;
713 ale->datatype= ALE_ACT;
715 ale->adt= BKE_animdata_from_id(data);
721 bActionGroup *agrp= (bActionGroup *)data;
723 ale->flag= agrp->flag;
726 ale->datatype= ALE_GROUP;
729 case ANIMTYPE_FCURVE:
731 FCurve *fcu= (FCurve *)data;
733 ale->flag= fcu->flag;
736 ale->datatype= ALE_FCURVE;
740 case ANIMTYPE_SHAPEKEY:
742 KeyBlock *kb= (KeyBlock *)data;
743 Key *key= (Key *)ale->id;
747 /* whether we have keyframes depends on whether there is a Key block to find it from */
749 /* index of shapekey is defined by place in key's list */
750 ale->index= BLI_findindex(&key->block, kb);
752 /* the corresponding keyframes are from the animdata */
753 if (ale->adt && ale->adt->action) {
754 bAction *act= ale->adt->action;
755 char *rna_path = key_get_curValue_rnaPath(key, kb);
757 /* try to find the F-Curve which corresponds to this exactly,
758 * then free the MEM_alloc'd string
761 ale->key_data= (void *)list_find_fcurve(&act->curves, rna_path, 0);
765 ale->datatype= (ale->key_data)? ALE_FCURVE : ALE_NONE;
770 case ANIMTYPE_GPLAYER:
772 bGPDlayer *gpl= (bGPDlayer *)data;
774 ale->flag= gpl->flag;
777 ale->datatype= ALE_GPFRAME;
781 case ANIMTYPE_NLATRACK:
783 NlaTrack *nlt= (NlaTrack *)data;
785 ale->flag= nlt->flag;
787 ale->key_data= &nlt->strips;
788 ale->datatype= ALE_NLASTRIP;
791 case ANIMTYPE_NLAACTION:
793 /* nothing to include for now... nothing editable from NLA-perspective here */
795 ale->datatype= ALE_NONE;
801 /* return created datatype */
805 /* ----------------------------------------- */
807 /* 'Only Selected' selected data filtering
808 * NOTE: when this function returns true, the F-Curve is to be skipped
810 static int skip_fcurve_selected_data (bDopeSheet *ads, FCurve *fcu, ID *owner_id, int filter_mode)
812 if (GS(owner_id->name) == ID_OB) {
813 Object *ob= (Object *)owner_id;
815 /* only consider if F-Curve involves pose.bones */
816 if ((fcu->rna_path) && strstr(fcu->rna_path, "pose.bones")) {
820 /* get bone-name, and check if this bone is selected */
821 bone_name= BLI_getQuotedStr(fcu->rna_path, "pose.bones[");
822 pchan= get_pose_channel(ob->pose, bone_name);
823 if (bone_name) MEM_freeN(bone_name);
825 /* check whether to continue or skip */
826 if ((pchan) && (pchan->bone)) {
827 /* if only visible channels, skip if bone not visible unless user wants channels from hidden data too */
828 if ((filter_mode & ANIMFILTER_VISIBLE) && !(ads->filterflag & ADS_FILTER_INCL_HIDDEN)) {
829 bArmature *arm= (bArmature *)ob->data;
831 if ((arm->layer & pchan->bone->layer) == 0)
835 /* can only add this F-Curve if it is selected */
836 if ((pchan->bone->flag & BONE_SELECTED) == 0)
841 else if (GS(owner_id->name) == ID_SCE) {
842 Scene *scene = (Scene *)owner_id;
844 /* only consider if F-Curve involves sequence_editor.sequences */
845 if ((fcu->rna_path) && strstr(fcu->rna_path, "sequences_all")) {
846 Editing *ed= seq_give_editing(scene, FALSE);
850 /* get strip name, and check if this strip is selected */
851 seq_name= BLI_getQuotedStr(fcu->rna_path, "sequences_all[");
852 seq = get_seq_by_name(ed->seqbasep, seq_name, FALSE);
853 if (seq_name) MEM_freeN(seq_name);
855 /* can only add this F-Curve if it is selected */
856 if (seq==NULL || (seq->flag & SELECT)==0)
860 else if (GS(owner_id->name) == ID_NT) {
861 bNodeTree *ntree = (bNodeTree *)owner_id;
863 /* check for selected nodes */
864 if ((fcu->rna_path) && strstr(fcu->rna_path, "nodes")) {
868 /* get strip name, and check if this strip is selected */
869 node_name= BLI_getQuotedStr(fcu->rna_path, "nodes[");
870 node = nodeFindNodebyName(ntree, node_name);
871 if (node_name) MEM_freeN(node_name);
873 /* can only add this F-Curve if it is selected */
874 if ((node) && (node->flag & NODE_SELECT)==0)
881 /* (Display-)Name-based F-Curve filtering
882 * NOTE: when this function returns true, the F-Curve is to be skipped
884 static short skip_fcurve_with_name (bDopeSheet *ads, FCurve *fcu, ID *owner_id)
886 bAnimListElem ale_dummy = {0};
887 bAnimChannelType *acf;
889 /* create a dummy wrapper for the F-Curve */
890 ale_dummy.type = ANIMTYPE_FCURVE;
891 ale_dummy.id = owner_id;
892 ale_dummy.data = fcu;
894 /* get type info for channel */
895 acf = ANIM_channel_get_typeinfo(&ale_dummy);
896 if (acf && acf->name) {
897 char name[256]; /* hopefully this will be enough! */
900 acf->name(&ale_dummy, name);
902 /* check for partial match with the match string, assuming case insensitive filtering
903 * if match, this channel shouldn't be ignored!
905 return BLI_strcasestr(name, ads->searchstr) == NULL;
908 /* just let this go... */
912 /* find the next F-Curve that is usable for inclusion */
913 static FCurve *animdata_filter_fcurve_next (bDopeSheet *ads, FCurve *first, bActionGroup *grp, int filter_mode, ID *owner_id)
917 /* loop over F-Curves - assume that the caller of this has already checked that these should be included
918 * NOTE: we need to check if the F-Curves belong to the same group, as this gets called for groups too...
920 for (fcu= first; ((fcu) && (fcu->grp==grp)); fcu= fcu->next) {
921 /* special exception for Pose-Channel/Sequence-Strip/Node Based F-Curves:
922 * - the 'Only Selected' data filter should be applied to Pose-Channel data too, but those are
923 * represented as F-Curves. The way the filter for objects worked was to be the first check
924 * after 'normal' visibility, so this is done first here too...
925 * - we currently use an 'approximate' method for getting these F-Curves that doesn't require
926 * carefully checking the entire path
927 * - this will also affect things like Drivers, and also works for Bone Constraints
929 if ( ((ads) && (ads->filterflag & ADS_FILTER_ONLYSEL)) && (owner_id) ) {
930 if (skip_fcurve_selected_data(ads, fcu, owner_id, filter_mode))
934 /* only include if visible (Graph Editor check, not channels check) */
935 if (!(filter_mode & ANIMFILTER_CURVEVISIBLE) || (fcu->flag & FCURVE_VISIBLE)) {
936 /* only work with this channel and its subchannels if it is editable */
937 if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_FCU(fcu)) {
938 /* only include this curve if selected in a way consistent with the filtering requirements */
939 if ( ANIMCHANNEL_SELOK(SEL_FCU(fcu)) && ANIMCHANNEL_SELEDITOK(SEL_FCU(fcu)) ) {
940 /* only include if this curve is active */
941 if (!(filter_mode & ANIMFILTER_ACTIVE) || (fcu->flag & FCURVE_ACTIVE)) {
942 /* name based filtering... */
943 if ( ((ads) && (ads->filterflag & ADS_FILTER_BY_FCU_NAME)) && (owner_id) ) {
944 if (skip_fcurve_with_name(ads, fcu, owner_id))
948 /* this F-Curve can be used, so return it */
956 /* no (more) F-Curves from the list are suitable... */
960 static int animdata_filter_fcurves (ListBase *anim_data, bDopeSheet *ads, FCurve *first, bActionGroup *grp, void *owner, short ownertype, int filter_mode, ID *owner_id)
965 /* loop over every F-Curve able to be included
966 * - this for-loop works like this:
967 * 1) the starting F-Curve is assigned to the fcu pointer so that we have a starting point to search from
968 * 2) the first valid F-Curve to start from (which may include the one given as 'first') in the remaining
969 * list of F-Curves is found, and verified to be non-null
970 * 3) the F-Curve referenced by fcu pointer is added to the list
971 * 4) the fcu pointer is set to the F-Curve after the one we just added, so that we can keep going through
972 * the rest of the F-Curve list without an eternal loop. Back to step 2 :)
974 for (fcu=first; ( (fcu = animdata_filter_fcurve_next(ads, fcu, grp, filter_mode, owner_id)) ); fcu=fcu->next)
976 bAnimListElem *ale = make_new_animlistelem(fcu, ANIMTYPE_FCURVE, owner, ownertype, owner_id);
979 BLI_addtail(anim_data, ale);
984 /* return the number of items added to the list */
988 static int animdata_filter_action (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, bAction *act, int filter_mode, void *owner, short ownertype, ID *owner_id)
990 bAnimListElem *ale=NULL;
992 FCurve *lastchan=NULL;
995 /* don't include anything from this action if it is linked in from another file,
996 * and we're getting stuff for editing...
998 // TODO: need a way of tagging other channels that may also be affected...
999 if ((filter_mode & ANIMFILTER_FOREDIT) && (act->id.lib))
1002 /* loop over groups */
1003 // TODO: in future, should we expect to need nested groups?
1004 for (agrp= act->groups.first; agrp; agrp= agrp->next) {
1008 /* store reference to last channel of group */
1009 if (agrp->channels.last)
1010 lastchan= agrp->channels.last;
1013 /* make a copy of filtering flags for use by the sub-channels of this group */
1014 filter_gmode= filter_mode;
1016 /* if we care about the selection status of the channels,
1017 * but the group isn't expanded...
1019 if ( (filter_mode & (ANIMFILTER_SEL|ANIMFILTER_UNSEL)) && /* care about selection status */
1020 (EXPANDED_AGRP(ac, agrp)==0) ) /* group isn't expanded */
1022 /* if the group itself isn't selected appropriately, we shouldn't consider it's children either */
1023 if (ANIMCHANNEL_SELOK(SEL_AGRP(agrp)) == 0)
1026 /* if we're still here, then the selection status of the curves within this group should not matter,
1027 * since this creates too much overhead for animators (i.e. making a slow workflow)
1029 * Tools affected by this at time of coding (2010 Feb 09):
1030 * - inserting keyframes on selected channels only
1031 * - pasting keyframes
1032 * - creating ghost curves in Graph Editor
1034 filter_gmode &= ~(ANIMFILTER_SEL|ANIMFILTER_UNSEL);
1038 /* get the first F-Curve in this group we can start to use, and if there isn't any F-Curve to start from,
1039 * then don't use this group at all...
1041 * NOTE: use filter_gmode here not filter_mode, since there may be some flags we shouldn't consider under certain circumstances
1043 first_fcu = animdata_filter_fcurve_next(ads, agrp->channels.first, agrp, filter_gmode, owner_id);
1046 * Selecting open group to toggle visbility of the group, where the F-Curves of the group are not suitable
1047 * for inclusion due to their selection status (vs visibility status of bones/etc., as is usually the case),
1048 * will not work, since the group gets skipped. However, fixing this can easily reintroduce the bugs whereby
1049 * hidden groups (due to visibility status of bones/etc.) that were selected before becoming invisible, can
1050 * easily get deleted accidentally as they'd be included in the list filtered for that purpose.
1052 * So, for now, best solution is to just leave this note here, and hope to find a solution at a later date.
1053 * -- Joshua Leung, 2010 Feb 10
1056 /* add this group as a channel first */
1057 if ((filter_mode & ANIMFILTER_CHANNELS) || !(filter_mode & ANIMFILTER_CURVESONLY)) {
1058 /* filter selection of channel specially here again, since may be open and not subject to previous test */
1059 if ( ANIMCHANNEL_SELOK(SEL_AGRP(agrp)) ) {
1060 ale= make_new_animlistelem(agrp, ANIMTYPE_GROUP, NULL, ANIMTYPE_NONE, owner_id);
1062 BLI_addtail(anim_data, ale);
1068 /* there are some situations, where only the channels of the action group should get considered */
1069 if (!(filter_mode & ANIMFILTER_ACTGROUPED) || (agrp->flag & AGRP_ACTIVE)) {
1070 /* filters here are a bit convoulted...
1071 * - groups show a "summary" of keyframes beside their name which must accessable for tools which handle keyframes
1072 * - groups can be collapsed (and those tools which are only interested in channels rely on knowing that group is closed)
1074 * cases when we should include F-Curves inside group:
1075 * - we don't care about visibility
1076 * - group is expanded
1077 * - we just need the F-Curves present
1079 if ( (!(filter_mode & ANIMFILTER_VISIBLE) || EXPANDED_AGRP(ac, agrp)) || (filter_mode & ANIMFILTER_CURVESONLY) )
1081 /* for the Graph Editor, curves may be set to not be visible in the view to lessen clutter,
1082 * but to do this, we need to check that the group doesn't have it's not-visible flag set preventing
1083 * all its sub-curves to be shown
1085 if ( !(filter_mode & ANIMFILTER_CURVEVISIBLE) || !(agrp->flag & AGRP_NOTVISIBLE) )
1087 if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_AGRP(agrp)) {
1088 /* NOTE: filter_gmode is used here, not standard filter_mode, since there may be some flags that shouldn't apply */
1089 items += animdata_filter_fcurves(anim_data, ads, first_fcu, agrp, owner, ownertype, filter_gmode, owner_id);
1097 /* loop over un-grouped F-Curves (only if we're not only considering those channels in the animive group) */
1098 if (!(filter_mode & ANIMFILTER_ACTGROUPED)) {
1099 // XXX the 'owner' info here needs review...
1100 items += animdata_filter_fcurves(anim_data, ads, (lastchan)?(lastchan->next):(act->curves.first), NULL, owner, ownertype, filter_mode, owner_id);
1103 /* return the number of items added to the list */
1107 /* Include NLA-Data for NLA-Editor:
1108 * - when ANIMFILTER_CHANNELS is used, that means we should be filtering the list for display
1109 * Although the evaluation order is from the first track to the last and then apply the Action on top,
1110 * we present this in the UI as the Active Action followed by the last track to the first so that we
1111 * get the evaluation order presented as per a stack.
1112 * - for normal filtering (i.e. for editing), we only need the NLA-tracks but they can be in 'normal' evaluation
1113 * order, i.e. first to last. Otherwise, some tools may get screwed up.
1115 static int animdata_filter_nla (bAnimContext *UNUSED(ac), ListBase *anim_data, bDopeSheet *UNUSED(ads), AnimData *adt, int filter_mode, void *owner, short ownertype, ID *owner_id)
1119 NlaTrack *first=NULL, *next=NULL;
1122 /* if showing channels, include active action */
1123 if (filter_mode & ANIMFILTER_CHANNELS) {
1124 /* there isn't really anything editable here, so skip if need editable */
1125 // TODO: currently, selection isn't checked since it doesn't matter
1126 if ((filter_mode & ANIMFILTER_FOREDIT) == 0) {
1127 /* just add the action track now (this MUST appear for drawing)
1128 * - as AnimData may not have an action, we pass a dummy pointer just to get the list elem created, then
1129 * overwrite this with the real value - REVIEW THIS...
1131 ale= make_new_animlistelem((void *)(&adt->action), ANIMTYPE_NLAACTION, owner, ownertype, owner_id);
1132 ale->data= (adt->action) ? adt->action : NULL;
1135 BLI_addtail(anim_data, ale);
1140 /* first track to include will be the last one if we're filtering by channels */
1141 first= adt->nla_tracks.last;
1144 /* first track to include will the the first one (as per normal) */
1145 first= adt->nla_tracks.first;
1148 /* loop over NLA Tracks - assume that the caller of this has already checked that these should be included */
1149 for (nlt= first; nlt; nlt= next) {
1150 /* 'next' NLA-Track to use depends on whether we're filtering for drawing or not */
1151 if (filter_mode & ANIMFILTER_CHANNELS)
1156 /* if we're in NLA-tweakmode, don't show this track if it was disabled (due to tweaking) for now
1157 * - active track should still get shown though (even though it has disabled flag set)
1159 // FIXME: the channels after should still get drawn, just 'differently', and after an active-action channel
1160 if ((adt->flag & ADT_NLA_EDIT_ON) && (nlt->flag & NLATRACK_DISABLED) && !(nlt->flag & NLATRACK_ACTIVE))
1163 /* only work with this channel and its subchannels if it is editable */
1164 if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_NLT(nlt)) {
1165 /* only include this track if selected in a way consistent with the filtering requirements */
1166 if ( ANIMCHANNEL_SELOK(SEL_NLT(nlt)) ) {
1167 /* only include if this track is active */
1168 if (!(filter_mode & ANIMFILTER_ACTIVE) || (nlt->flag & NLATRACK_ACTIVE)) {
1169 ale= make_new_animlistelem(nlt, ANIMTYPE_NLATRACK, owner, ownertype, owner_id);
1172 BLI_addtail(anim_data, ale);
1180 /* return the number of items added to the list */
1184 /* Include ShapeKey Data for ShapeKey Editor */
1185 static int animdata_filter_shapekey (bAnimContext *ac, ListBase *anim_data, Key *key, int filter_mode)
1190 /* check if channels or only F-Curves */
1191 if ((filter_mode & ANIMFILTER_CURVESONLY) == 0) {
1194 /* loop through the channels adding ShapeKeys as appropriate */
1195 for (kb= key->block.first; kb; kb= kb->next) {
1196 /* skip the first one, since that's the non-animateable basis */
1197 // XXX maybe in future this may become handy?
1198 if (kb == key->block.first) continue;
1200 /* only work with this channel and its subchannels if it is editable */
1201 if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_SHAPEKEY(kb)) {
1202 /* only include this track if selected in a way consistent with the filtering requirements */
1203 if ( ANIMCHANNEL_SELOK(SEL_SHAPEKEY(kb)) ) {
1204 // TODO: consider 'active' too?
1206 /* owner-id here must be key so that the F-Curve can be resolved... */
1207 ale= make_new_animlistelem(kb, ANIMTYPE_SHAPEKEY, NULL, ANIMTYPE_NONE, (ID *)key);
1210 BLI_addtail(anim_data, ale);
1218 /* just use the action associated with the shapekey */
1219 // FIXME: is owner-id and having no owner/dopesheet really fine?
1221 if (filter_mode & ANIMFILTER_ANIMDATA)
1222 ANIMDATA_ADD_ANIMDATA(key)
1223 else if (key->adt->action)
1224 items= animdata_filter_action(ac, anim_data, NULL, key->adt->action, filter_mode, NULL, ANIMTYPE_NONE, (ID *)key);
1228 /* return the number of items added to the list */
1232 /* Grab all Grase Pencil datablocks in file */
1233 // TODO: should this be amalgamated with the dopesheet filtering code?
1234 static int animdata_filter_gpencil (ListBase *anim_data, void *UNUSED(data), int filter_mode)
1241 /* check if filtering types are appropriate */
1242 if (!(filter_mode & (ANIMFILTER_ACTGROUPED|ANIMFILTER_CURVESONLY)))
1244 /* for now, grab grease pencil datablocks directly from main*/
1245 for (gpd = G.main->gpencil.first; gpd; gpd = gpd->id.next) {
1246 /* only show if gpd is used by something... */
1247 if (ID_REAL_USERS(gpd) < 1)
1250 /* add gpd as channel too (if for drawing, and it has layers) */
1251 if ((filter_mode & ANIMFILTER_CHANNELS) && (gpd->layers.first)) {
1253 ale= make_new_animlistelem(gpd, ANIMTYPE_GPDATABLOCK, NULL, ANIMTYPE_NONE, NULL);
1255 BLI_addtail(anim_data, ale);
1260 /* only add layers if they will be visible (if drawing channels) */
1261 if ( !(filter_mode & ANIMFILTER_VISIBLE) || (EXPANDED_GPD(gpd)) ) {
1262 /* loop over layers as the conditions are acceptable */
1263 for (gpl= gpd->layers.first; gpl; gpl= gpl->next) {
1264 /* only if selected */
1265 if ( ANIMCHANNEL_SELOK(SEL_GPL(gpl)) ) {
1266 /* only if editable */
1267 if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_GPL(gpl)) {
1269 ale= make_new_animlistelem(gpl, ANIMTYPE_GPLAYER, gpd, ANIMTYPE_GPDATABLOCK, (ID*)gpd);
1271 BLI_addtail(anim_data, ale);
1281 /* return the number of items added to the list */
1285 /* NOTE: owner_id is either material, lamp, or world block, which is the direct owner of the texture stack in question */
1286 static int animdata_filter_dopesheet_texs (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, ID *owner_id, int filter_mode)
1288 ListBase texs = {NULL, NULL};
1292 int ownertype = ANIMTYPE_NONE;
1294 bAnimListElem *ale=NULL;
1297 /* get datatype specific data first */
1298 if (owner_id == NULL)
1301 switch (GS(owner_id->name)) {
1304 Material *ma= (Material *)owner_id;
1306 mtex= (MTex**)(&ma->mtex);
1307 expanded= FILTER_TEX_MATC(ma);
1308 ownertype= ANIMTYPE_DSMAT;
1313 Lamp *la= (Lamp *)owner_id;
1315 mtex= (MTex**)(&la->mtex);
1316 expanded= FILTER_TEX_LAMC(la);
1317 ownertype= ANIMTYPE_DSLAM;
1322 World *wo= (World *)owner_id;
1324 mtex= (MTex**)(&wo->mtex);
1325 expanded= FILTER_TEX_WORC(wo);
1326 ownertype= ANIMTYPE_DSWOR;
1331 /* invalid/unsupported option */
1333 printf("ERROR: unsupported owner_id (i.e. texture stack) for filter textures - %s \n", owner_id->name);
1338 /* firstly check that we actuallly have some textures, by gathering all textures in a temp list */
1339 for (a=0; a < MAX_MTEX; a++) {
1340 Tex *tex= (mtex[a]) ? mtex[a]->tex : NULL;
1343 /* for now, if no texture returned, skip (this shouldn't confuse the user I hope) */
1344 if (ELEM(NULL, tex, tex->adt))
1348 ANIMDATA_FILTER_CASES(tex,
1349 { /* AnimData blocks - do nothing... */ },
1353 if (ok == 0) continue;
1355 /* make a temp list elem for this */
1356 ld= MEM_callocN(sizeof(LinkData), "DopeSheet-TextureCache");
1358 BLI_addtail(&texs, ld);
1361 /* if there were no channels found, no need to carry on */
1362 if (texs.first == NULL)
1365 /* include textures-expand widget? */
1366 if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
1367 ale= make_new_animlistelem(owner_id, ANIMTYPE_FILLTEXD, owner_id, ownertype, owner_id);
1369 BLI_addtail(anim_data, ale);
1375 if ((expanded) || (filter_mode & ANIMFILTER_CURVESONLY)) {
1376 /* for each texture in cache, add channels */
1377 for (ld= texs.first; ld; ld= ld->next) {
1378 Tex *tex= (Tex *)ld->data;
1380 /* include texture-expand widget? */
1381 if (filter_mode & ANIMFILTER_CHANNELS) {
1382 /* check if filtering by active status */
1383 if ANIMCHANNEL_ACTIVEOK(tex) {
1384 ale= make_new_animlistelem(tex, ANIMTYPE_DSTEX, owner_id, ownertype, owner_id);
1386 BLI_addtail(anim_data, ale);
1392 /* add texture's animation data
1393 * NOTE: for these, we make the owner/ownertype the material/lamp/etc. not the texture, otherwise the
1394 * drawing code cannot resolve the indention easily
1396 if (!(filter_mode & ANIMFILTER_VISIBLE) || FILTER_TEX_DATA(tex) || (filter_mode & ANIMFILTER_CURVESONLY)) {
1397 ANIMDATA_FILTER_CASES(tex,
1398 { /* AnimData blocks - do nothing... */ },
1399 items += animdata_filter_nla(ac, anim_data, ads, tex->adt, filter_mode, owner_id, ownertype, (ID *)tex);,
1400 items += animdata_filter_fcurves(anim_data, ads, tex->adt->drivers.first, NULL, owner_id, ownertype, filter_mode, (ID *)tex);,
1401 items += animdata_filter_action(ac, anim_data, ads, tex->adt->action, filter_mode, owner_id, ownertype, (ID *)tex);)
1407 BLI_freelistN(&texs);
1409 /* return the number of items added to the list */
1413 static int animdata_filter_dopesheet_mats (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Base *base, int filter_mode)
1415 ListBase mats = {NULL, NULL};
1418 bAnimListElem *ale=NULL;
1419 Object *ob= base->object;
1422 /* firstly check that we actuallly have some materials, by gathering all materials in a temp list */
1423 for (a=1; a <= ob->totcol; a++) {
1424 Material *ma= give_current_material(ob, a);
1427 /* for now, if no material returned, skip (this shouldn't confuse the user I hope) */
1428 if (ma == NULL) continue;
1431 ANIMDATA_FILTER_CASES(ma,
1432 { /* AnimData blocks - do nothing... */ },
1437 /* need to check textures */
1438 if (ok == 0 && !(ads->filterflag & ADS_FILTER_NOTEX)) {
1441 for (mtInd=0; mtInd < MAX_MTEX; mtInd++) {
1442 MTex *mtex = ma->mtex[mtInd];
1444 if(mtex && mtex->tex) {
1445 ANIMDATA_FILTER_CASES(mtex->tex,
1446 { /* AnimData blocks - do nothing... */ },
1457 if (ok == 0) continue;
1459 /* make a temp list elem for this */
1460 ld= MEM_callocN(sizeof(LinkData), "DopeSheet-MaterialCache");
1462 BLI_addtail(&mats, ld);
1465 /* if there were no channels found, no need to carry on */
1466 if (mats.first == NULL)
1469 /* include materials-expand widget? */
1470 if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
1471 ale= make_new_animlistelem(ob, ANIMTYPE_FILLMATD, base, ANIMTYPE_OBJECT, (ID *)ob);
1473 BLI_addtail(anim_data, ale);
1478 /* add materials? */
1479 if (FILTER_MAT_OBJC(ob) || (filter_mode & ANIMFILTER_CURVESONLY)) {
1480 /* for each material in cache, add channels */
1481 for (ld= mats.first; ld; ld= ld->next) {
1482 Material *ma= (Material *)ld->data;
1484 /* include material-expand widget? */
1485 // hmm... do we need to store the index of this material in the array anywhere?
1486 if (filter_mode & ANIMFILTER_CHANNELS) {
1487 /* check if filtering by active status */
1488 if ANIMCHANNEL_ACTIVEOK(ma) {
1489 ale= make_new_animlistelem(ma, ANIMTYPE_DSMAT, base, ANIMTYPE_OBJECT, (ID *)ma);
1491 BLI_addtail(anim_data, ale);
1497 /* add material's animation data */
1498 if (!(filter_mode & ANIMFILTER_VISIBLE) || FILTER_MAT_OBJD(ma) || (filter_mode & ANIMFILTER_CURVESONLY)) {
1499 /* material's animation data */
1500 ANIMDATA_FILTER_CASES(ma,
1501 { /* AnimData blocks - do nothing... */ },
1502 items += animdata_filter_nla(ac, anim_data, ads, ma->adt, filter_mode, ma, ANIMTYPE_DSMAT, (ID *)ma);,
1503 items += animdata_filter_fcurves(anim_data, ads, ma->adt->drivers.first, NULL, ma, ANIMTYPE_DSMAT, filter_mode, (ID *)ma);,
1504 items += animdata_filter_action(ac, anim_data, ads, ma->adt->action, filter_mode, ma, ANIMTYPE_DSMAT, (ID *)ma);)
1507 if (!(ads->filterflag & ADS_FILTER_NOTEX))
1508 items += animdata_filter_dopesheet_texs(ac, anim_data, ads, (ID *)ma, filter_mode);
1514 BLI_freelistN(&mats);
1516 /* return the number of items added to the list */
1520 static int animdata_filter_dopesheet_particles (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Base *base, int filter_mode)
1522 bAnimListElem *ale=NULL;
1523 Object *ob= base->object;
1524 ParticleSystem *psys = ob->particlesystem.first;
1525 int items= 0, first = 1;
1527 for(; psys; psys=psys->next) {
1530 if(ELEM(NULL, psys->part, psys->part->adt))
1533 ANIMDATA_FILTER_CASES(psys->part,
1534 { /* AnimData blocks - do nothing... */ },
1538 if (ok == 0) continue;
1540 /* include particles-expand widget? */
1541 if (first && (filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
1542 ale= make_new_animlistelem(ob, ANIMTYPE_FILLPARTD, base, ANIMTYPE_OBJECT, (ID *)ob);
1544 BLI_addtail(anim_data, ale);
1550 /* add particle settings? */
1551 if (FILTER_PART_OBJC(ob) || (filter_mode & ANIMFILTER_CURVESONLY)) {
1552 if ((filter_mode & ANIMFILTER_CHANNELS)) {
1553 /* check if filtering by active status */
1554 if ANIMCHANNEL_ACTIVEOK(psys->part) {
1555 ale = make_new_animlistelem(psys->part, ANIMTYPE_DSPART, base, ANIMTYPE_OBJECT, (ID *)psys->part);
1557 BLI_addtail(anim_data, ale);
1563 if (!(filter_mode & ANIMFILTER_VISIBLE) || FILTER_PART_OBJD(psys->part) || (filter_mode & ANIMFILTER_CURVESONLY)) {
1564 ANIMDATA_FILTER_CASES(psys->part,
1565 { /* AnimData blocks - do nothing... */ },
1566 items += animdata_filter_nla(ac, anim_data, ads, psys->part->adt, filter_mode, psys->part, ANIMTYPE_DSPART, (ID *)psys->part);,
1567 items += animdata_filter_fcurves(anim_data, ads, psys->part->adt->drivers.first, NULL, psys->part, ANIMTYPE_DSPART, filter_mode, (ID *)psys->part);,
1568 items += animdata_filter_action(ac, anim_data, ads, psys->part->adt->action, filter_mode, psys->part, ANIMTYPE_DSPART, (ID *)psys->part);)
1573 /* return the number of items added to the list */
1577 static int animdata_filter_dopesheet_obdata (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Base *base, int filter_mode)
1579 bAnimListElem *ale=NULL;
1580 Object *ob= base->object;
1581 IdAdtTemplate *iat= ob->data;
1582 AnimData *adt= iat->adt;
1583 short type=0, expanded=0;
1586 /* get settings based on data type */
1588 case OB_CAMERA: /* ------- Camera ------------ */
1590 Camera *ca= (Camera *)ob->data;
1592 type= ANIMTYPE_DSCAM;
1593 expanded= FILTER_CAM_OBJD(ca);
1596 case OB_LAMP: /* ---------- Lamp ----------- */
1598 Lamp *la= (Lamp *)ob->data;
1600 type= ANIMTYPE_DSLAM;
1601 expanded= FILTER_LAM_OBJD(la);
1604 case OB_CURVE: /* ------- Curve ---------- */
1605 case OB_SURF: /* ------- Nurbs Surface ---------- */
1606 case OB_FONT: /* ------- Text Curve ---------- */
1608 Curve *cu= (Curve *)ob->data;
1610 type= ANIMTYPE_DSCUR;
1611 expanded= FILTER_CUR_OBJD(cu);
1614 case OB_MBALL: /* ------- MetaBall ---------- */
1616 MetaBall *mb= (MetaBall *)ob->data;
1618 type= ANIMTYPE_DSMBALL;
1619 expanded= FILTER_MBALL_OBJD(mb);
1622 case OB_ARMATURE: /* ------- Armature ---------- */
1624 bArmature *arm= (bArmature *)ob->data;
1626 type= ANIMTYPE_DSARM;
1627 expanded= FILTER_ARM_OBJD(arm);
1630 case OB_MESH: /* ------- Mesh ---------- */
1632 Mesh *me= (Mesh *)ob->data;
1634 type= ANIMTYPE_DSMESH;
1635 expanded= FILTER_MESH_OBJD(me);
1638 case OB_LATTICE: /* ---- Lattice ---- */
1640 Lattice *lt = (Lattice *)ob->data;
1642 type= ANIMTYPE_DSLAT;
1643 expanded= FILTER_LATTICE_OBJD(lt);
1648 /* special exception for drivers instead of action */
1649 if (ads->filterflag & ADS_FILTER_ONLYDRIVERS)
1650 expanded= EXPANDED_DRVD(adt);
1652 /* include data-expand widget? */
1653 if ((filter_mode & ANIMFILTER_CURVESONLY) == 0) {
1654 /* check if filtering by active status */
1655 if ANIMCHANNEL_ACTIVEOK(iat) {
1656 ale= make_new_animlistelem(iat, type, base, ANIMTYPE_OBJECT, (ID *)iat);
1657 if (ale) BLI_addtail(anim_data, ale);
1661 /* add object-data animation channels? */
1662 if (!(filter_mode & ANIMFILTER_VISIBLE) || (expanded) || (filter_mode & ANIMFILTER_CURVESONLY)) {
1663 /* filtering for channels - nla, drivers, keyframes */
1664 ANIMDATA_FILTER_CASES(iat,
1665 { /* AnimData blocks - do nothing... */ },
1666 items+= animdata_filter_nla(ac, anim_data, ads, iat->adt, filter_mode, iat, type, (ID *)iat);,
1667 items+= animdata_filter_fcurves(anim_data, ads, adt->drivers.first, NULL, iat, type, filter_mode, (ID *)iat);,
1668 items+= animdata_filter_action(ac, anim_data, ads, iat->adt->action, filter_mode, iat, type, (ID *)iat);)
1670 /* sub-data filtering... */
1672 case OB_LAMP: /* lamp - textures */
1675 if (!(ads->filterflag & ADS_FILTER_NOTEX))
1676 items += animdata_filter_dopesheet_texs(ac, anim_data, ads, ob->data, filter_mode);
1682 /* return the number of items added to the list */
1686 static int animdata_filter_dopesheet_ob (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Base *base, int filter_mode)
1688 bAnimListElem *ale=NULL;
1689 AnimData *adt = NULL;
1690 Object *ob= base->object;
1691 Key *key= ob_get_key(ob);
1692 short obdata_ok = 0;
1695 /* add this object as a channel first */
1696 if ((filter_mode & (ANIMFILTER_CURVESONLY|ANIMFILTER_NLATRACKS)) == 0) {
1697 /* check if filtering by selection */
1698 if ANIMCHANNEL_SELOK((base->flag & SELECT)) {
1699 /* check if filtering by active status */
1700 if ANIMCHANNEL_ACTIVEOK(ob) {
1701 ale= make_new_animlistelem(base, ANIMTYPE_OBJECT, NULL, ANIMTYPE_NONE, (ID *)ob);
1703 BLI_addtail(anim_data, ale);
1710 /* if collapsed, don't go any further (unless adding keyframes only) */
1711 if ( ((filter_mode & ANIMFILTER_VISIBLE) && EXPANDED_OBJC(ob) == 0) &&
1712 !(filter_mode & (ANIMFILTER_CURVESONLY|ANIMFILTER_NLATRACKS)) )
1715 /* Action, Drivers, or NLA */
1716 if (ob->adt && !(ads->filterflag & ADS_FILTER_NOOBJ)) {
1718 ANIMDATA_FILTER_CASES(ob,
1719 { /* AnimData blocks - do nothing... */ },
1721 /* add NLA tracks */
1722 items += animdata_filter_nla(ac, anim_data, ads, adt, filter_mode, ob, ANIMTYPE_OBJECT, (ID *)ob);
1725 /* include drivers-expand widget? */
1726 if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
1727 ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLDRIVERS, base, ANIMTYPE_OBJECT, (ID *)ob);
1729 BLI_addtail(anim_data, ale);
1734 /* add F-Curve channels (drivers are F-Curves) */
1735 if (!(filter_mode & ANIMFILTER_VISIBLE) || EXPANDED_DRVD(adt) || !(filter_mode & ANIMFILTER_CHANNELS)) {
1736 // need to make the ownertype normal object here... (maybe type should be a separate one for clarity?)
1737 items += animdata_filter_fcurves(anim_data, ads, adt->drivers.first, NULL, ob, ANIMTYPE_OBJECT, filter_mode, (ID *)ob);
1740 { /* action (keyframes) */
1741 /* include action-expand widget? */
1742 if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
1743 ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLACTD, base, ANIMTYPE_OBJECT, (ID *)ob);
1745 BLI_addtail(anim_data, ale);
1750 /* add F-Curve channels? */
1751 if (!(filter_mode & ANIMFILTER_VISIBLE) || EXPANDED_ACTC(adt->action) || !(filter_mode & ANIMFILTER_CHANNELS)) {
1752 // need to make the ownertype normal object here... (maybe type should be a separate one for clarity?)
1753 items += animdata_filter_action(ac, anim_data, ads, adt->action, filter_mode, ob, ANIMTYPE_OBJECT, (ID *)ob);
1761 if ((key) && !(ads->filterflag & ADS_FILTER_NOSHAPEKEYS)) {
1763 ANIMDATA_FILTER_CASES(key,
1764 { /* AnimData blocks - do nothing... */ },
1766 /* include shapekey-expand widget? */
1767 if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
1768 /* check if filtering by active status */
1769 if ANIMCHANNEL_ACTIVEOK(key) {
1770 ale= make_new_animlistelem(key, ANIMTYPE_DSSKEY, base, ANIMTYPE_OBJECT, (ID *)ob);
1772 BLI_addtail(anim_data, ale);
1778 /* add NLA tracks - only if expanded or so */
1779 if (!(filter_mode & ANIMFILTER_VISIBLE) || FILTER_SKE_OBJD(key) || (filter_mode & ANIMFILTER_CURVESONLY))
1780 items += animdata_filter_nla(ac, anim_data, ads, adt, filter_mode, ob, ANIMTYPE_OBJECT, (ID *)key);
1783 /* include shapekey-expand widget? */
1784 if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
1785 ale= make_new_animlistelem(key, ANIMTYPE_DSSKEY, base, ANIMTYPE_OBJECT, (ID *)ob);
1787 BLI_addtail(anim_data, ale);
1793 if (!(filter_mode & ANIMFILTER_VISIBLE) || FILTER_SKE_OBJD(key) || (filter_mode & ANIMFILTER_CURVESONLY)) {
1794 items += animdata_filter_fcurves(anim_data, ads, adt->drivers.first, NULL, key, ANIMTYPE_DSSKEY, filter_mode, (ID *)key);
1797 { /* action (keyframes) */
1798 /* include shapekey-expand widget? */
1799 if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
1800 /* check if filtering by active status */
1801 if ANIMCHANNEL_ACTIVEOK(key) {
1802 ale= make_new_animlistelem(key, ANIMTYPE_DSSKEY, base, ANIMTYPE_OBJECT, (ID *)ob);
1804 BLI_addtail(anim_data, ale);
1811 if (!(filter_mode & ANIMFILTER_VISIBLE) || FILTER_SKE_OBJD(key) || (filter_mode & ANIMFILTER_CURVESONLY)) {
1812 items += animdata_filter_action(ac, anim_data, ads, adt->action, filter_mode, key, ANIMTYPE_DSSKEY, (ID *)key);
1819 if ((ob->totcol) && !(ads->filterflag & ADS_FILTER_NOMAT))
1820 items += animdata_filter_dopesheet_mats(ac, anim_data, ads, base, filter_mode);
1824 case OB_CAMERA: /* ------- Camera ------------ */
1826 Camera *ca= (Camera *)ob->data;
1828 if ((ads->filterflag & ADS_FILTER_NOCAM) == 0) {
1829 ANIMDATA_FILTER_CASES(ca,
1830 { /* AnimData blocks - do nothing... */ },
1837 case OB_LAMP: /* ---------- Lamp ----------- */
1839 Lamp *la= (Lamp *)ob->data;
1841 if ((ads->filterflag & ADS_FILTER_NOLAM) == 0) {
1842 ANIMDATA_FILTER_CASES(la,
1843 { /* AnimData blocks - do nothing... */ },
1850 case OB_CURVE: /* ------- Curve ---------- */
1851 case OB_SURF: /* ------- Nurbs Surface ---------- */
1852 case OB_FONT: /* ------- Text Curve ---------- */
1854 Curve *cu= (Curve *)ob->data;
1856 if ((ads->filterflag & ADS_FILTER_NOCUR) == 0) {
1857 ANIMDATA_FILTER_CASES(cu,
1858 { /* AnimData blocks - do nothing... */ },
1865 case OB_MBALL: /* ------- MetaBall ---------- */
1867 MetaBall *mb= (MetaBall *)ob->data;
1869 if ((ads->filterflag & ADS_FILTER_NOMBA) == 0) {
1870 ANIMDATA_FILTER_CASES(mb,
1871 { /* AnimData blocks - do nothing... */ },
1878 case OB_ARMATURE: /* ------- Armature ---------- */
1880 bArmature *arm= (bArmature *)ob->data;
1882 if ((ads->filterflag & ADS_FILTER_NOARM) == 0) {
1883 ANIMDATA_FILTER_CASES(arm,
1884 { /* AnimData blocks - do nothing... */ },
1891 case OB_MESH: /* ------- Mesh ---------- */
1893 Mesh *me= (Mesh *)ob->data;
1895 if ((ads->filterflag & ADS_FILTER_NOMESH) == 0) {
1896 ANIMDATA_FILTER_CASES(me,
1897 { /* AnimData blocks - do nothing... */ },
1904 case OB_LATTICE: /* ------- Lattice ---------- */
1906 Lattice *lt= (Lattice *)ob->data;
1908 if ((ads->filterflag & ADS_FILTER_NOLAT) == 0) {
1909 ANIMDATA_FILTER_CASES(lt,
1910 { /* AnimData blocks - do nothing... */ },
1919 items += animdata_filter_dopesheet_obdata(ac, anim_data, ads, base, filter_mode);
1922 if (ob->particlesystem.first && !(ads->filterflag & ADS_FILTER_NOPART))
1923 items += animdata_filter_dopesheet_particles(ac, anim_data, ads, base, filter_mode);
1925 /* return the number of items added to the list */
1929 static int animdata_filter_dopesheet_scene (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Scene *sce, int filter_mode)
1931 World *wo= sce->world;
1932 bNodeTree *ntree= sce->nodetree;
1933 AnimData *adt= NULL;
1937 /* add scene as a channel first (even if we aren't showing scenes we still need to show the scene's sub-data */
1938 if ((filter_mode & (ANIMFILTER_CURVESONLY|ANIMFILTER_NLATRACKS)) == 0) {
1939 /* check if filtering by selection */
1940 if (ANIMCHANNEL_SELOK( (sce->flag & SCE_DS_SELECTED) )) {
1941 ale= make_new_animlistelem(sce, ANIMTYPE_SCENE, NULL, ANIMTYPE_NONE, NULL);
1943 BLI_addtail(anim_data, ale);
1949 /* if collapsed, don't go any further (unless adding keyframes only) */
1950 if ( (EXPANDED_SCEC(sce) == 0) && !(filter_mode & (ANIMFILTER_CURVESONLY|ANIMFILTER_NLATRACKS)) )
1953 /* Action, Drivers, or NLA for Scene */
1954 if ((ads->filterflag & ADS_FILTER_NOSCE) == 0) {
1956 ANIMDATA_FILTER_CASES(sce,
1957 { /* AnimData blocks - do nothing... */ },
1959 /* add NLA tracks */
1960 items += animdata_filter_nla(ac, anim_data, ads, adt, filter_mode, sce, ANIMTYPE_SCENE, (ID *)sce);
1963 /* include drivers-expand widget? */
1964 if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
1965 ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLDRIVERS, sce, ANIMTYPE_SCENE, (ID *)sce);
1967 BLI_addtail(anim_data, ale);
1972 /* add F-Curve channels (drivers are F-Curves) */
1973 if (EXPANDED_DRVD(adt) || !(filter_mode & ANIMFILTER_CHANNELS)) {
1974 items += animdata_filter_fcurves(anim_data, ads, adt->drivers.first, NULL, sce, ANIMTYPE_SCENE, filter_mode, (ID *)sce);
1978 /* include action-expand widget? */
1979 if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
1980 ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLACTD, sce, ANIMTYPE_SCENE, (ID *)sce);
1982 BLI_addtail(anim_data, ale);
1987 /* add F-Curve channels? */
1988 if (EXPANDED_ACTC(adt->action) || !(filter_mode & ANIMFILTER_CHANNELS)) {
1989 items += animdata_filter_action(ac, anim_data, ads, adt->action, filter_mode, sce, ANIMTYPE_SCENE, (ID *)sce);
1996 if ((wo && wo->adt) && !(ads->filterflag & ADS_FILTER_NOWOR)) {
1997 /* Action, Drivers, or NLA for World */
1999 ANIMDATA_FILTER_CASES(wo,
2000 { /* AnimData blocks - do nothing... */ },
2002 /* add NLA tracks */
2003 items += animdata_filter_nla(ac, anim_data, ads, adt, filter_mode, wo, ANIMTYPE_DSWOR, (ID *)wo);
2006 /* include world-expand widget? */
2007 if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
2008 ale= make_new_animlistelem(wo, ANIMTYPE_DSWOR, sce, ANIMTYPE_SCENE, (ID *)wo);
2010 BLI_addtail(anim_data, ale);
2015 /* add F-Curve channels (drivers are F-Curves) */
2016 if (FILTER_WOR_SCED(wo)/*EXPANDED_DRVD(adt)*/ || !(filter_mode & ANIMFILTER_CHANNELS)) {
2017 // XXX owner info is messed up now...
2018 items += animdata_filter_fcurves(anim_data, ads, adt->drivers.first, NULL, wo, ANIMTYPE_DSWOR, filter_mode, (ID *)wo);
2022 /* include world-expand widget? */
2023 if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
2024 ale= make_new_animlistelem(wo, ANIMTYPE_DSWOR, sce, ANIMTYPE_SCENE, (ID *)sce);
2026 BLI_addtail(anim_data, ale);
2032 if (FILTER_WOR_SCED(wo) || (filter_mode & ANIMFILTER_CURVESONLY)) {
2033 items += animdata_filter_action(ac, anim_data, ads, adt->action, filter_mode, wo, ANIMTYPE_DSWOR, (ID *)wo);
2038 /* if expanded, check world textures too */
2039 if (FILTER_WOR_SCED(wo) || (filter_mode & ANIMFILTER_CURVESONLY)) {
2040 /* textures for world */
2041 if (!(ads->filterflag & ADS_FILTER_NOTEX))
2042 items += animdata_filter_dopesheet_texs(ac, anim_data, ads, (ID *)wo, filter_mode);
2046 if ((ntree && ntree->adt) && !(ads->filterflag & ADS_FILTER_NONTREE)) {
2047 /* Action, Drivers, or NLA for Nodetree */
2049 ANIMDATA_FILTER_CASES(ntree,
2050 { /* AnimData blocks - do nothing... */ },
2052 /* add NLA tracks */
2053 items += animdata_filter_nla(ac, anim_data, ads, adt, filter_mode, ntree, ANIMTYPE_DSNTREE, (ID *)ntree);
2056 /* include nodetree-expand widget? */
2057 if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
2058 ale= make_new_animlistelem(ntree, ANIMTYPE_DSNTREE, sce, ANIMTYPE_SCENE, (ID *)ntree);
2060 BLI_addtail(anim_data, ale);
2065 /* add F-Curve channels (drivers are F-Curves) */
2066 if (FILTER_NTREE_SCED(ntree)/*EXPANDED_DRVD(adt)*/ || !(filter_mode & ANIMFILTER_CHANNELS)) {
2067 // XXX owner info is messed up now...
2068 items += animdata_filter_fcurves(anim_data, ads, adt->drivers.first, NULL, ntree, ANIMTYPE_DSNTREE, filter_mode, (ID *)ntree);
2072 /* include nodetree-expand widget? */
2073 if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
2074 ale= make_new_animlistelem(ntree, ANIMTYPE_DSNTREE, sce, ANIMTYPE_SCENE, (ID *)sce);
2076 BLI_addtail(anim_data, ale);
2082 if (FILTER_NTREE_SCED(ntree) || (filter_mode & ANIMFILTER_CURVESONLY)) {
2083 items += animdata_filter_action(ac, anim_data, ads, adt->action, filter_mode, ntree, ANIMTYPE_DSNTREE, (ID *)ntree);
2090 // TODO: scene compositing nodes (these aren't standard node-trees)
2092 /* return the number of items added to the list */
2096 // 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)
2097 static int animdata_filter_dopesheet (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, int filter_mode)
2099 Scene *sce= (Scene *)ads->source;
2104 /* check that we do indeed have a scene */
2105 if ((ads->source == NULL) || (GS(ads->source->name)!=ID_SCE)) {
2106 printf("DopeSheet Error: Not scene!\n");
2108 printf("\tPointer = %p, Name = '%s' \n", (void *)ads->source, (ads->source)?ads->source->name:NULL);
2112 /* augment the filter-flags with settings based on the dopesheet filterflags
2113 * so that some temp settings can get added automagically...
2115 if (ads->filterflag & ADS_FILTER_SELEDIT) {
2116 /* only selected F-Curves should get their keyframes considered for editability */
2117 filter_mode |= ANIMFILTER_SELEDIT;
2120 /* scene-linked animation */
2121 // TODO: sequencer, composite nodes - are we to include those here too?
2123 short sceOk= 0, worOk= 0, nodeOk=0;
2125 /* check filtering-flags if ok */
2126 ANIMDATA_FILTER_CASES(sce,
2128 /* for the special AnimData blocks only case, we only need to add
2129 * the block if it is valid... then other cases just get skipped (hence ok=0)
2131 ANIMDATA_ADD_ANIMDATA(sce);
2134 sceOk= !(ads->filterflag & ADS_FILTER_NOSCE);,
2135 sceOk= !(ads->filterflag & ADS_FILTER_NOSCE);,
2136 sceOk= !(ads->filterflag & ADS_FILTER_NOSCE);)
2138 ANIMDATA_FILTER_CASES(sce->world,
2140 /* for the special AnimData blocks only case, we only need to add
2141 * the block if it is valid... then other cases just get skipped (hence ok=0)
2143 ANIMDATA_ADD_ANIMDATA(sce->world);
2146 worOk= !(ads->filterflag & ADS_FILTER_NOWOR);,
2147 worOk= !(ads->filterflag & ADS_FILTER_NOWOR);,
2148 worOk= !(ads->filterflag & ADS_FILTER_NOWOR);)
2150 if (sce->nodetree) {
2151 ANIMDATA_FILTER_CASES(sce->nodetree,
2153 /* for the special AnimData blocks only case, we only need to add
2154 * the block if it is valid... then other cases just get skipped (hence ok=0)
2156 ANIMDATA_ADD_ANIMDATA(sce->nodetree);
2159 nodeOk= !(ads->filterflag & ADS_FILTER_NONTREE);,
2160 nodeOk= !(ads->filterflag & ADS_FILTER_NONTREE);,
2161 nodeOk= !(ads->filterflag & ADS_FILTER_NONTREE);)
2164 /* if only F-Curves with visible flags set can be shown, check that
2165 * datablocks haven't been set to invisible
2167 if (filter_mode & ANIMFILTER_CURVEVISIBLE) {
2168 if ((sce->adt) && (sce->adt->flag & ADT_CURVES_NOT_VISIBLE))
2169 sceOk= worOk= nodeOk= 0;
2172 /* check if not all bad (i.e. so there is something to show) */
2173 if ( !(!sceOk && !worOk && !nodeOk) ) {
2174 /* add scene data to the list of filtered channels */
2175 items += animdata_filter_dopesheet_scene(ac, anim_data, ads, sce, filter_mode);
2180 /* loop over all bases in the scene */
2181 for (base= sce->base.first; base; base= base->next) {
2182 /* check if there's an object (all the relevant checks are done in the ob-function) */
2184 Object *ob= base->object;
2185 Key *key= ob_get_key(ob);
2186 short actOk=1, keyOk=1, dataOk=1, matOk=1, partOk=1;
2188 /* firstly, check if object can be included, by the following factors:
2189 * - if only visible, must check for layer and also viewport visibility
2190 * --> while tools may demand only visible, user setting takes priority
2191 * as user option controls whether sets of channels get included while
2192 * tool-flag takes into account collapsed/open channels too
2193 * - if only selected, must check if object is selected
2194 * - there must be animation data to edit
2196 // TODO: if cache is implemented, just check name here, and then
2197 if ((filter_mode & ANIMFILTER_VISIBLE) && !(ads->filterflag & ADS_FILTER_INCL_HIDDEN)) {
2198 /* layer visibility - we check both object and base, since these may not be in sync yet */
2199 if ((sce->lay & (ob->lay|base->lay))==0) continue;
2201 /* outliner restrict-flag */
2202 if (ob->restrictflag & OB_RESTRICT_VIEW) continue;
2205 /* if only F-Curves with visible flags set can be shown, check that
2206 * datablock hasn't been set to invisible
2208 if (filter_mode & ANIMFILTER_CURVEVISIBLE) {
2209 if ((ob->adt) && (ob->adt->flag & ADT_CURVES_NOT_VISIBLE))
2213 /* additionally, dopesheet filtering also affects what objects to consider */
2215 /* check selection and object type filters */
2216 if ( (ads->filterflag & ADS_FILTER_ONLYSEL) && !((base->flag & SELECT) /*|| (base == sce->basact)*/) ) {
2217 /* only selected should be shown */
2221 /* check if object belongs to the filtering group if option to filter
2222 * objects by the grouped status is on
2223 * - used to ease the process of doing multiple-character choreographies
2225 if (ads->filterflag & ADS_FILTER_ONLYOBGROUP) {
2226 if (object_in_group(ob, ads->filter_grp) == 0)
2230 /* check filters for datatypes */
2233 if (!(ads->filterflag & ADS_FILTER_NOOBJ)) {
2234 ANIMDATA_FILTER_CASES(ob,
2236 /* for the special AnimData blocks only case, we only need to add
2237 * the block if it is valid... then other cases just get skipped (hence ok=0)
2239 ANIMDATA_ADD_ANIMDATA(ob);
2248 if ((key) && !(ads->filterflag & ADS_FILTER_NOSHAPEKEYS)) {
2250 ANIMDATA_FILTER_CASES(key,
2252 /* for the special AnimData blocks only case, we only need to add
2253 * the block if it is valid... then other cases just get skipped (hence ok=0)
2255 ANIMDATA_ADD_ANIMDATA(key);
2263 /* materials - only for geometric types */
2264 matOk= 0; /* by default, not ok... */
2265 if ( !(ads->filterflag & ADS_FILTER_NOMAT) && (ob->totcol) &&
2266 ELEM5(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL) )
2270 /* firstly check that we actuallly have some materials */
2271 for (a=1; a <= ob->totcol; a++) {
2272 Material *ma= give_current_material(ob, a);
2275 /* if material has relevant animation data, break */
2276 ANIMDATA_FILTER_CASES(ma,
2278 /* for the special AnimData blocks only case, we only need to add
2279 * the block if it is valid... then other cases just get skipped (hence ok=0)
2281 ANIMDATA_ADD_ANIMDATA(ma);
2292 // TODO: make this a macro that is used in the other checks too
2293 // NOTE: this has little use on its own, since the actual filtering still ignores if no anim on the data
2294 if (!(ads->filterflag & ADS_FILTER_NOTEX)) {
2297 for (mtInd= 0; mtInd < MAX_MTEX; mtInd++) {
2298 MTex *mtex= ma->mtex[mtInd];
2300 if (mtex && mtex->tex) {
2301 /* if texture has relevant animation data, break */
2302 ANIMDATA_FILTER_CASES(mtex->tex,
2304 /* for the special AnimData blocks only case, we only need to add
2305 * the block if it is valid... then other cases just get skipped (hence ok=0)
2307 ANIMDATA_ADD_ANIMDATA(mtex->tex);
2326 case OB_CAMERA: /* ------- Camera ------------ */
2328 Camera *ca= (Camera *)ob->data;
2330 ANIMDATA_FILTER_CASES(ca,
2331 if ((ads->filterflag & ADS_FILTER_NOCAM)==0) {
2332 /* for the special AnimData blocks only case, we only need to add
2333 * the block if it is valid... then other cases just get skipped (hence ok=0)
2335 ANIMDATA_ADD_ANIMDATA(ca);
2338 dataOk= !(ads->filterflag & ADS_FILTER_NOCAM);,
2339 dataOk= !(ads->filterflag & ADS_FILTER_NOCAM);,
2340 dataOk= !(ads->filterflag & ADS_FILTER_NOCAM);)
2343 case OB_LAMP: /* ---------- Lamp ----------- */
2345 Lamp *la= (Lamp *)ob->data;
2347 ANIMDATA_FILTER_CASES(la,
2348 if ((ads->filterflag & ADS_FILTER_NOLAM)==0) {
2349 /* for the special AnimData blocks only case, we only need to add
2350 * the block if it is valid... then other cases just get skipped (hence ok=0)
2352 ANIMDATA_ADD_ANIMDATA(la);
2355 dataOk= !(ads->filterflag & ADS_FILTER_NOLAM);,
2356 dataOk= !(ads->filterflag & ADS_FILTER_NOLAM);,
2357 dataOk= !(ads->filterflag & ADS_FILTER_NOLAM);)
2360 case OB_CURVE: /* ------- Curve ---------- */
2361 case OB_SURF: /* ------- Nurbs Surface ---------- */
2362 case OB_FONT: /* ------- Text Curve ---------- */
2364 Curve *cu= (Curve *)ob->data;
2366 ANIMDATA_FILTER_CASES(cu,
2367 if ((ads->filterflag & ADS_FILTER_NOCUR)==0) {
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)
2371 ANIMDATA_ADD_ANIMDATA(cu);
2374 dataOk= !(ads->filterflag & ADS_FILTER_NOCUR);,
2375 dataOk= !(ads->filterflag & ADS_FILTER_NOCUR);,
2376 dataOk= !(ads->filterflag & ADS_FILTER_NOCUR);)
2379 case OB_MBALL: /* ------- MetaBall ---------- */
2381 MetaBall *mb= (MetaBall *)ob->data;
2383 ANIMDATA_FILTER_CASES(mb,
2384 if ((ads->filterflag & ADS_FILTER_NOMBA)==0) {
2385 /* for the special AnimData blocks only case, we only need to add
2386 * the block if it is valid... then other cases just get skipped (hence ok=0)
2388 ANIMDATA_ADD_ANIMDATA(mb);
2391 dataOk= !(ads->filterflag & ADS_FILTER_NOMBA);,
2392 dataOk= !(ads->filterflag & ADS_FILTER_NOMBA);,
2393 dataOk= !(ads->filterflag & ADS_FILTER_NOMBA);)
2396 case OB_ARMATURE: /* ------- Armature ---------- */
2398 bArmature *arm= (bArmature *)ob->data;
2400 ANIMDATA_FILTER_CASES(arm,
2401 if ((ads->filterflag & ADS_FILTER_NOARM)==0) {
2402 /* for the special AnimData blocks only case, we only need to add
2403 * the block if it is valid... then other cases just get skipped (hence ok=0)
2405 ANIMDATA_ADD_ANIMDATA(arm);
2408 dataOk= !(ads->filterflag & ADS_FILTER_NOARM);,
2409 dataOk= !(ads->filterflag & ADS_FILTER_NOARM);,
2410 dataOk= !(ads->filterflag & ADS_FILTER_NOARM);)
2413 case OB_MESH: /* ------- Mesh ---------- */
2415 Mesh *me= (Mesh *)ob->data;
2417 ANIMDATA_FILTER_CASES(me,
2418 if ((ads->filterflag & ADS_FILTER_NOMESH)==0) {
2419 /* for the special AnimData blocks only case, we only need to add
2420 * the block if it is valid... then other cases just get skipped (hence ok=0)
2422 ANIMDATA_ADD_ANIMDATA(me);
2425 dataOk= !(ads->filterflag & ADS_FILTER_NOMESH);,
2426 dataOk= !(ads->filterflag & ADS_FILTER_NOMESH);,
2427 dataOk= !(ads->filterflag & ADS_FILTER_NOMESH);)
2430 case OB_LATTICE: /* ------- Lattice ---------- */
2432 Lattice *lt= (Lattice *)ob->data;
2434 ANIMDATA_FILTER_CASES(lt,
2435 if ((ads->filterflag & ADS_FILTER_NOLAT)==0) {
2436 /* for the special AnimData blocks only case, we only need to add
2437 * the block if it is valid... then other cases just get skipped (hence ok=0)
2439 ANIMDATA_ADD_ANIMDATA(lt);
2442 dataOk= !(ads->filterflag & ADS_FILTER_NOLAT);,
2443 dataOk= !(ads->filterflag & ADS_FILTER_NOLAT);,
2444 dataOk= !(ads->filterflag & ADS_FILTER_NOLAT);)
2447 default: /* --- other --- */
2454 if (!(ads->filterflag & ADS_FILTER_NOPART) && ob->particlesystem.first) {
2455 ParticleSystem *psys = ob->particlesystem.first;
2456 for(; psys; psys=psys->next) {
2458 /* if particlesettings has relevant animation data, break */
2459 ANIMDATA_FILTER_CASES(psys->part,
2461 /* for the special AnimData blocks only case, we only need to add
2462 * the block if it is valid... then other cases just get skipped (hence ok=0)
2464 ANIMDATA_ADD_ANIMDATA(psys->part);
2477 /* check if all bad (i.e. nothing to show) */
2478 if (!actOk && !keyOk && !dataOk && !matOk && !partOk)
2482 /* since we're still here, this object should be usable */
2483 items += animdata_filter_dopesheet_ob(ac, anim_data, ads, base, filter_mode);
2487 /* return the number of items in the list */
2491 /* Summary track for DopeSheet/Action Editor
2492 * - return code is whether the summary lets the other channels get drawn
2494 static short animdata_filter_dopesheet_summary (bAnimContext *ac, ListBase *anim_data, int filter_mode, int *items)
2496 bDopeSheet *ads = NULL;
2498 /* get the DopeSheet information to use
2499 * - we should only need to deal with the DopeSheet/Action Editor,
2500 * since all the other Animation Editors won't have this concept
2503 if ((ac && ac->sa) && (ac->sa->spacetype == SPACE_ACTION)) {
2504 SpaceAction *saction= (SpaceAction *)ac->sa->spacedata.first;
2508 /* invalid space type - skip this summary channels */
2512 /* dopesheet summary
2513 * - only for drawing and/or selecting keyframes in channels, but not for real editing
2514 * - only useful for DopeSheet/Action/etc. editors where it is actually useful
2516 // TODO: we should really check if some other prohibited filters are also active, but that can be for later
2517 if ((filter_mode & ANIMFILTER_CHANNELS) && (ads->filterflag & ADS_FILTER_SUMMARY)) {
2518 bAnimListElem *ale= make_new_animlistelem(ac, ANIMTYPE_SUMMARY, NULL, ANIMTYPE_NONE, NULL);
2520 BLI_addtail(anim_data, ale);
2524 /* if summary is collapsed, don't show other channels beneath this
2525 * - this check is put inside the summary check so that it doesn't interfere with normal operation
2527 if (ads->flag & ADS_FLAG_SUMMARY_COLLAPSED)