Merged changes in the trunk up to revision 55357.
[blender.git] / source / blender / editors / animation / anim_filter.c
index 721b347379208f9031582fd169e4983d2b3fee7f..7648d99821637fae372ccf945ede3db4f9b21482 100644 (file)
@@ -55,6 +55,9 @@
 #include "DNA_camera_types.h"
 #include "DNA_lamp_types.h"
 #include "DNA_lattice_types.h"
+#ifdef WITH_FREESTYLE
+#  include "DNA_linestyle_types.h"
+#endif
 #include "DNA_key_types.h"
 #include "DNA_mask_types.h"
 #include "DNA_material_types.h"
@@ -175,7 +178,7 @@ static short actedit_get_context(bAnimContext *ac, SpaceAction *saction)
                        return 1;
                        
                case SACTCONT_MASK: /* Mask */ /* XXX review how this mode is handled... */
-{
+               {
                        /* TODO, other methods to get the mask */
                        // Sequence *seq = BKE_sequencer_active_get(ac->scene);
                        //MovieClip *clip = ac->scene->clip;
@@ -189,7 +192,7 @@ static short actedit_get_context(bAnimContext *ac, SpaceAction *saction)
                        
                        ac->mode = saction->mode;
                        return 1;
-}
+               }
                case SACTCONT_DOPESHEET: /* DopeSheet */
                        /* update scene-pointer (no need to check for pinning yet, as not implemented) */
                        saction->ads.source = (ID *)ac->scene;
@@ -290,7 +293,7 @@ static short nlaedit_get_context(bAnimContext *ac, SpaceNla *snla)
 short ANIM_animdata_context_getdata(bAnimContext *ac)
 {
        SpaceLink *sl = ac->sl;
-       short ok = 0;
+       short ok = FALSE;
        
        /* context depends on editor we are currently in */
        if (sl) {
@@ -319,10 +322,7 @@ short ANIM_animdata_context_getdata(bAnimContext *ac)
        }
        
        /* check if there's any valid data */
-       if (ok && ac->data)
-               return 1;
-       else
-               return 0;
+       return (ok && ac->data);
 }
 
 /* Obtain current anim-data context from Blender Context info 
@@ -354,6 +354,7 @@ short ANIM_animdata_get_context(const bContext *C, bAnimContext *ac)
        ac->regiontype = (ar) ? ar->regiontype : 0;
        
        /* get data context info */
+       // XXX: if the below fails, try to grab this info from context instead... (to allow for scripting)
        return ANIM_animdata_context_getdata(ac);
 }
 
@@ -448,7 +449,7 @@ short ANIM_animdata_get_context(const bContext *C, bAnimContext *ac)
                                        if (ANIMDATA_HAS_NLA(id)) { \
                                                nlaOk \
                                        } \
-                                       else if (!(ads->filterflag & ADS_FILTER_NLA_NOACT) && ANIMDATA_HAS_KEYS(id)) { \
+                                       else if (!(ads->filterflag & ADS_FILTER_NLA_NOACT) || ANIMDATA_HAS_KEYS(id)) { \
                                                nlaOk \
                                        } \
                                } \
@@ -736,6 +737,21 @@ static bAnimListElem *make_new_animlistelem(void *data, short datatype, ID *owne
                                ale->adt = BKE_animdata_from_id(data);
                        }
                        break;
+#ifdef WITH_FREESTYLE
+                       case ANIMTYPE_DSLINESTYLE:
+                       {
+                               FreestyleLineStyle *linestyle = (FreestyleLineStyle *)data;
+                               AnimData *adt = linestyle->adt;
+                               
+                               ale->flag = FILTER_LS_SCED(linestyle); 
+                               
+                               ale->key_data = (adt) ? adt->action : NULL;
+                               ale->datatype = ALE_ACT;
+                               
+                               ale->adt = BKE_animdata_from_id(data);
+                       }
+                               break;
+#endif
                        case ANIMTYPE_DSPART:
                        {
                                ParticleSettings *part = (ParticleSettings *)ale->data;
@@ -911,13 +927,15 @@ static short skip_fcurve_selected_data(bDopeSheet *ads, FCurve *fcu, ID *owner_i
                /* only consider if F-Curve involves sequence_editor.sequences */
                if ((fcu->rna_path) && strstr(fcu->rna_path, "sequences_all")) {
                        Editing *ed = BKE_sequencer_editing_get(scene, FALSE);
-                       Sequence *seq;
+                       Sequence *seq = NULL;
                        char *seq_name;
                        
-                       /* get strip name, and check if this strip is selected */
-                       seq_name = BLI_str_quoted_substrN(fcu->rna_path, "sequences_all[");
-                       seq = BKE_sequence_get_by_name(ed->seqbasep, seq_name, FALSE);
-                       if (seq_name) MEM_freeN(seq_name);
+                       if (ed) {
+                               /* get strip name, and check if this strip is selected */
+                               seq_name = BLI_str_quoted_substrN(fcu->rna_path, "sequences_all[");
+                               seq = BKE_sequence_get_by_name(ed->seqbasep, seq_name, FALSE);
+                               if (seq_name) MEM_freeN(seq_name);
+                       }
                        
                        /* can only add this F-Curve if it is selected */
                        if (ads->filterflag & ADS_FILTER_ONLYSEL) {
@@ -983,22 +1001,39 @@ static short skip_fcurve_with_name(bDopeSheet *ads, FCurve *fcu, ID *owner_id)
 /* Check if F-Curve has errors and/or is disabled 
  * > returns: (bool) True if F-Curve has errors/is disabled
  */
-static short fcurve_has_errors(FCurve *fcu)
+static bool fcurve_has_errors(FCurve *fcu)
 {
        /* F-Curve disabled - path eval error */
        if (fcu->flag & FCURVE_DISABLED) {
-               return 1;
+               return true;
        }
        
        /* driver? */
        if (fcu->driver) {
-               /* for now, just check if the entire thing got disabled... */
-               if (fcu->driver->flag & DRIVER_FLAG_INVALID)
-                       return 1;
+               ChannelDriver *driver = fcu->driver;
+               DriverVar *dvar;
+               
+               /* error flag on driver usually means that there is an error
+                * BUT this may not hold with PyDrivers as this flag gets cleared
+                *     if no critical errors prevent the driver from working...
+                */
+               if (driver->flag & DRIVER_FLAG_INVALID)
+                       return true;
+                       
+               /* check variables for other things that need linting... */
+               // TODO: maybe it would be more efficient just to have a quick flag for this?
+               for (dvar = driver->variables.first; dvar; dvar = dvar->next) {
+                       DRIVER_TARGETS_USED_LOOPER(dvar)
+                       {
+                               if (dtar->flag & DTAR_FLAG_INVALID)
+                                       return true;
+                       }
+                       DRIVER_TARGETS_LOOPER_END
+               }
        }
        
        /* no errors found */
-       return 0;
+       return false;
 }
 
 /* find the next F-Curve that is usable for inclusion */
@@ -1042,7 +1077,7 @@ static FCurve *animfilter_fcurve_next(bDopeSheet *ads, FCurve *first, bActionGro
                                                /* error-based filtering... */
                                                if ((ads) && (ads->filterflag & ADS_FILTER_ONLY_ERRORS)) {
                                                        /* skip if no errors... */
-                                                       if (fcurve_has_errors(fcu) == 0)
+                                                       if (fcurve_has_errors(fcu) == false)
                                                                continue;
                                                }
                                                
@@ -1279,7 +1314,9 @@ static size_t animfilter_block_data(bAnimContext *ac, ListBase *anim_data, bDope
                ANIMDATA_FILTER_CASES(iat,
                        { /* AnimData */
                                /* specifically filter animdata block */
-                               ANIMCHANNEL_NEW_CHANNEL(adt, ANIMTYPE_ANIMDATA, id);
+                               if (ANIMCHANNEL_SELOK(SEL_ANIMDATA(adt)) ) {
+                                       ANIMCHANNEL_NEW_CHANNEL(adt, ANIMTYPE_ANIMDATA, id);
+                               }
                        },
                        { /* NLA */
                                items += animfilter_nla(ac, anim_data, ads, adt, filter_mode, id);
@@ -1329,7 +1366,9 @@ static size_t animdata_filter_shapekey(bAnimContext *ac, ListBase *anim_data, Ke
                // TODO: somehow manage to pass dopesheet info down here too?
                if (key->adt) {
                        if (filter_mode & ANIMFILTER_ANIMDATA) {
-                               ANIMCHANNEL_NEW_CHANNEL(key->adt, ANIMTYPE_ANIMDATA, key);
+                               if (ANIMCHANNEL_SELOK(SEL_ANIMDATA(key->adt)) ) {
+                                       ANIMCHANNEL_NEW_CHANNEL(key->adt, ANIMTYPE_ANIMDATA, key);
+                               }
                        }
                        else if (key->adt->action) {
                                items = animfilter_action(ac, anim_data, NULL, key->adt->action, filter_mode, (ID *)key);
@@ -1511,6 +1550,56 @@ static size_t animdata_filter_ds_nodetree(bAnimContext *ac, ListBase *anim_data,
        return items;
 }
 
+#ifdef WITH_FREESTYLE
+static size_t animdata_filter_ds_linestyle (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Scene *sce, int filter_mode)
+{
+       SceneRenderLayer *srl;
+       size_t items = 0;
+
+       for (srl = sce->r.layers.first; srl; srl = srl->next) {
+               FreestyleLineSet *lineset;
+
+               /* skip render layers without Freestyle enabled */
+               if (!(srl->layflag & SCE_LAY_FRS))
+                       continue;
+
+               /* loop over linesets defined in the render layer */
+               for (lineset = srl->freestyleConfig.linesets.first; lineset; lineset = lineset->next) {
+                       FreestyleLineStyle *linestyle = lineset->linestyle;
+                       ListBase tmp_data = {NULL, NULL};
+                       size_t tmp_items = 0;
+
+                       /* add scene-level animation channels */
+                       BEGIN_ANIMFILTER_SUBCHANNELS(FILTER_LS_SCED(linestyle))
+                       {
+                               /* animation data filtering */
+                               tmp_items += animfilter_block_data(ac, &tmp_data, ads, (ID *)linestyle, filter_mode);
+                       }
+                       END_ANIMFILTER_SUBCHANNELS;
+
+                       /* did we find anything? */
+                       if (tmp_items) {
+                               /* include anim-expand widget first */
+                               if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
+                                       /* check if filtering by active status */
+                                       if ANIMCHANNEL_ACTIVEOK(linestyle) {
+                                               ANIMCHANNEL_NEW_CHANNEL(linestyle, ANIMTYPE_DSLINESTYLE, sce);
+                                       }
+                               }
+                               
+                               /* now add the list of collected channels */
+                               BLI_movelisttolist(anim_data, &tmp_data);
+                               BLI_assert((tmp_data.first == tmp_data.last) && (tmp_data.first == NULL));
+                               items += tmp_items;
+                       }
+               }
+       }
+       
+       /* return the number of items added to the list */
+       return items;
+}
+#endif
+
 /* NOTE: owner_id is either material, lamp, or world block, which is the direct owner of the texture stack in question */
 static size_t animdata_filter_ds_textures(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, ID *owner_id, int filter_mode)
 {
@@ -2144,7 +2233,14 @@ static size_t animdata_filter_dopesheet_scene(bAnimContext *ac, ListBase *anim_d
                if ((ntree) && !(ads->filterflag & ADS_FILTER_NONTREE)) {
                        tmp_items += animdata_filter_ds_nodetree(ac, &tmp_data, ads, (ID *)sce, ntree, filter_mode);
                }
-
+               
+#ifdef WITH_FREESTYLE
+               /* line styles */
+               if ((ads->filterflag & ADS_FILTER_NOLINESTYLE) == 0) {
+                       tmp_items += animdata_filter_ds_linestyle(ac, &tmp_data, ads, sce, filter_mode);
+               }
+#endif
+               
                /* TODO: one day, when sequencer becomes its own datatype, perhaps it should be included here */
        }
        END_ANIMFILTER_SUBCHANNELS;
@@ -2316,6 +2412,10 @@ static size_t animdata_filter_animchan(bAnimContext *ac, ListBase *anim_data, bD
                        items += animdata_filter_dopesheet_ob(ac, anim_data, ads, channel->data, filter_mode);
                        break;
                        
+               case ANIMTYPE_ANIMDATA:
+                       items += animfilter_block_data(ac, anim_data, ads, channel->id, filter_mode);
+                       break;
+                       
                default:
                        printf("ERROR: Unsupported channel type (%d) in animdata_filter_animchan()\n", channel->type);
                        break;