code cleanup: move file string defines into BLI_path_utils.h, BKE_utildefines is...
[blender.git] / source / blender / editors / animation / anim_filter.c
index 2392b872031fede068b8a716381353b87e4d4612..c92b7ce2761e3ad2d2e7c276377afddea312f624 100644 (file)
@@ -56,6 +56,7 @@
 #include "DNA_lamp_types.h"
 #include "DNA_lattice_types.h"
 #include "DNA_key_types.h"
+#include "DNA_mask_types.h"
 #include "DNA_material_types.h"
 #include "DNA_mesh_types.h"
 #include "DNA_meta_types.h"
@@ -86,8 +87,8 @@
 #include "BKE_main.h"
 #include "BKE_material.h"
 #include "BKE_node.h"
+#include "BKE_mask.h"
 #include "BKE_sequencer.h"
-#include "BKE_utildefines.h"
 
 #include "ED_anim_api.h"
 #include "ED_markers.h"
@@ -162,17 +163,33 @@ static short actedit_get_context(bAnimContext *ac, SpaceAction *saction)
                        
                        ac->mode = saction->mode;
                        return 1;
-                       
-               case SACTCONT_GPENCIL: /* Grease Pencil */ // XXX review how this mode is handled...
+
+               case SACTCONT_GPENCIL: /* Grease Pencil */ /* XXX review how this mode is handled... */
                        /* update scene-pointer (no need to check for pinning yet, as not implemented) */
                        saction->ads.source = (ID *)ac->scene;
-                       
+
                        ac->datatype = ANIMCONT_GPENCIL;
                        ac->data = &saction->ads;
-                       
+
                        ac->mode = saction->mode;
                        return 1;
-                       
+
+               case SACTCONT_MASK: /* Grease Pencil */ /* XXX review how this mode is handled... */
+                       /* update scene-pointer (no need to check for pinning yet, as not implemented) */
+{
+                       /* TODO, other methods to get the mask */
+                       // Sequence *seq = BKE_sequencer_active_get(ac->scene);
+                       //MovieClip *clip = ac->scene->clip;
+//                     struct Mask *mask = seq ? seq->mask : NULL;
+
+                       saction->ads.source = (ID *)ac->scene;
+
+                       ac->datatype = ANIMCONT_MASK;
+                       ac->data = &saction->ads;
+
+                       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;
@@ -379,7 +396,7 @@ short ANIM_animdata_get_context(const bContext *C, bAnimContext *ac)
 /* ... standard sub-channel filtering can go on here now ... */
 #define END_ANIMFILTER_SUBCHANNELS \
                filter_mode = _filter; \
-       }
+       } (void)0
 
 /* ............................... */
 
@@ -399,16 +416,16 @@ short ANIM_animdata_get_context(const bContext *C, bAnimContext *ac)
  *
  * For this to work correctly, a standard set of data needs to be available within the scope that this
  * gets called in: 
- *     - ListBase anim_data;
- *     - bDopeSheet *ads;
- *     - bAnimListElem *ale;
+ *  - ListBase anim_data;
+ *  - bDopeSheet *ads;
+ *  - bAnimListElem *ale;
  *  - size_t items;
  *
  *  - id: ID block which should have an AnimData pointer following it immediately, to use
- *     - adtOk: line or block of code to execute for AnimData-blocks case (usually ANIMDATA_ADD_ANIMDATA)
- *     - nlaOk: line or block of code to execute for NLA tracks+strips case
- *     - driversOk: line or block of code to execute for Drivers case
- *     - keysOk: line or block of code for Keyframes case
+ *  - adtOk: line or block of code to execute for AnimData-blocks case (usually ANIMDATA_ADD_ANIMDATA)
+ *  - nlaOk: line or block of code to execute for NLA tracks+strips case
+ *  - driversOk: line or block of code to execute for Drivers case
+ *  - keysOk: line or block of code for Keyframes case
  *
  * The checks for the various cases are as follows:
  *     0) top level: checks for animdata and also that all the F-Curves for the block will be visible
@@ -447,7 +464,7 @@ short ANIM_animdata_get_context(const bContext *C, bAnimContext *ac)
                                } \
                        } \
                } \
-       }
+       } (void)0
 
 /* ............................... */
 
@@ -467,7 +484,7 @@ short ANIM_animdata_get_context(const bContext *C, bAnimContext *ac)
                        items ++; \
                        ale_statement \
                } \
-       }
+       } (void)0
        
 #define ANIMCHANNEL_NEW_CHANNEL(channel_data, channel_type, owner_id) \
        ANIMCHANNEL_NEW_CHANNEL_FULL(channel_data, channel_type, owner_id, {})
@@ -807,7 +824,18 @@ static bAnimListElem *make_new_animlistelem(void *data, short datatype, ID *owne
                                ale->datatype = ALE_GPFRAME;
                        }
                        break;
-                               
+
+                       case ANIMTYPE_MASKLAYER:
+                       {
+                               MaskLayer *masklay = (MaskLayer *)data;
+
+                               ale->flag = masklay->flag;
+
+                               ale->key_data = NULL;
+                               ale->datatype = ALE_MASKLAY;
+                       }
+                       break;
+
                        case ANIMTYPE_NLATRACK:
                        {
                                NlaTrack *nlt = (NlaTrack *)data;
@@ -851,7 +879,7 @@ static short skip_fcurve_selected_data(bDopeSheet *ads, FCurve *fcu, ID *owner_i
                        char *bone_name;
                        
                        /* get bone-name, and check if this bone is selected */
-                       bone_name = BLI_getQuotedStr(fcu->rna_path, "pose.bones[");
+                       bone_name = BLI_str_quoted_substrN(fcu->rna_path, "pose.bones[");
                        pchan = BKE_pose_channel_find_name(ob->pose, bone_name);
                        if (bone_name) MEM_freeN(bone_name);
                        
@@ -882,13 +910,13 @@ 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 = seq_give_editing(scene, FALSE);
+                       Editing *ed = BKE_sequencer_editing_get(scene, FALSE);
                        Sequence *seq;
                        char *seq_name;
                        
                        /* get strip name, and check if this strip is selected */
-                       seq_name = BLI_getQuotedStr(fcu->rna_path, "sequences_all[");
-                       seq = get_seq_by_name(ed->seqbasep, seq_name, FALSE);
+                       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 */
@@ -907,7 +935,7 @@ static short skip_fcurve_selected_data(bDopeSheet *ads, FCurve *fcu, ID *owner_i
                        char *node_name;
                        
                        /* get strip name, and check if this strip is selected */
-                       node_name = BLI_getQuotedStr(fcu->rna_path, "nodes[");
+                       node_name = BLI_str_quoted_substrN(fcu->rna_path, "nodes[");
                        node = nodeFindNodebyName(ntree, node_name);
                        if (node_name) MEM_freeN(node_name);
                        
@@ -1287,6 +1315,7 @@ static size_t animdata_filter_shapekey(bAnimContext *ac, ListBase *anim_data, Ke
        return items;
 }
 
+/* Helper for Grease Pencil - layers within a datablock */
 static size_t animdata_filter_gpencil_data(ListBase *anim_data, bGPdata *gpd, int filter_mode)
 {
        bGPDlayer *gpl;
@@ -1353,6 +1382,73 @@ static size_t animdata_filter_gpencil(ListBase *anim_data, void *UNUSED(data), i
        return items;
 }
 
+/* Helper for Mask Editing - mask layers */
+static size_t animdata_filter_mask_data(ListBase *anim_data, Mask *mask, const int filter_mode)
+{
+       MaskLayer *masklay_act = BKE_mask_layer_active(mask);
+       MaskLayer *masklay;
+       size_t items = 0;
+
+       /* loop over layers as the conditions are acceptable */
+       for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
+               /* only if selected */
+               if (ANIMCHANNEL_SELOK(SEL_MASKLAY(masklay)) ) {
+                       /* only if editable */
+//                     if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_GPL(gpl)) {
+                               /* active... */
+                               if (!(filter_mode & ANIMFILTER_ACTIVE) || (masklay_act == masklay)) {
+                                       /* add to list */
+                                       ANIMCHANNEL_NEW_CHANNEL(masklay, ANIMTYPE_MASKLAYER, mask);
+                               }
+//                     }
+               }
+       }
+
+       return items;
+}
+
+/* Grab all mask data */
+static size_t animdata_filter_mask(ListBase *anim_data, void *UNUSED(data), int filter_mode)
+{
+       Mask *mask;
+       size_t items = 0;
+       
+       /* for now, grab mask datablocks directly from main */
+       // XXX: this is not good...
+       for (mask = G.main->mask.first; mask; mask = mask->id.next) {
+               ListBase tmp_data = {NULL, NULL};
+               size_t tmp_items = 0;
+               
+               /* only show if mask is used by something... */
+               if (ID_REAL_USERS(mask) < 1)
+                       continue;
+               
+               /* add mask animation channels */
+               BEGIN_ANIMFILTER_SUBCHANNELS(EXPANDED_MASK(mask))
+               {
+                       tmp_items += animdata_filter_mask_data(&tmp_data, mask, filter_mode);
+               }
+               END_ANIMFILTER_SUBCHANNELS;
+               
+               /* did we find anything? */
+               if (tmp_items) {
+                       /* include data-expand widget first */
+                       if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
+                               /* add gpd as channel too (if for drawing, and it has layers) */
+                               ANIMCHANNEL_NEW_CHANNEL(mask, ANIMTYPE_MASKDATABLOCK, NULL);
+                       }
+                       
+                       /* 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;
+}
+
 /* NOTE: owner_id is scene, material, or texture block, which is the direct owner of the node tree in question */
 // TODO: how to handle group nodes is still unclear...
 static size_t animdata_filter_ds_nodetree(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, ID *owner_id, bNodeTree *ntree, int filter_mode)
@@ -1709,11 +1805,18 @@ static size_t animdata_filter_ds_obdata(bAnimContext *ac, ListBase *anim_data, b
                
                /* sub-data filtering... */
                switch (ob->type) {
-                       case OB_LAMP:  /* lamp - textures */
+                       case OB_LAMP:  /* lamp - textures + nodetree */
                        {
+                               Lamp *la = ob->data;
+                               bNodeTree *ntree = la->nodetree;
+
+                               /* nodetree */
+                               if ((ntree) && !(ads->filterflag & ADS_FILTER_NONTREE))
+                                       tmp_items += animdata_filter_ds_nodetree(ac, &tmp_data, ads, &la->id, ntree, filter_mode);
+
                                /* textures */
                                if (!(ads->filterflag & ADS_FILTER_NOTEX))
-                                       tmp_items += animdata_filter_ds_textures(ac, &tmp_data, ads, ob->data, filter_mode);
+                                       tmp_items += animdata_filter_ds_textures(ac, &tmp_data, ads, &la->id, filter_mode);
                        }
                        break;
                }
@@ -1784,9 +1887,9 @@ static size_t animdata_filter_ds_obanim(bAnimContext *ac, ListBase *anim_data, b
        AnimData *adt = ob->adt;
        short type = 0, expanded = 1;
        void *cdata = NULL;
-       
+
        /* determine the type of expander channels to use */
-       // this is the best way to do this for now...
+       /* this is the best way to do this for now... */
        ANIMDATA_FILTER_CASES(ob,
                { /* AnimData - no channel, but consider data */ },
                { /* NLA - no channel, but consider data */ },
@@ -2016,11 +2119,11 @@ 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);
                }
-               
-               // TODO: one day, when sequencer becomes its own datatype, perhaps it should be included here
+
+               /* TODO: one day, when sequencer becomes its own datatype, perhaps it should be included here */
        }
        END_ANIMFILTER_SUBCHANNELS;
-       
+
        /* if we collected some channels, add these to the new list... */
        if (tmp_items) {
                /* firstly add object expander if required */
@@ -2223,7 +2326,7 @@ static size_t animdata_filter_remove_duplis(ListBase *anim_data)
        /* build new hashtable to efficiently store and retrieve which entries have been 
         * encountered already while searching
         */
-       gh = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "animdata_filter_duplis_remove gh");
+       gh = BLI_ghash_ptr_new("animdata_filter_duplis_remove gh");
        
        /* loop through items, removing them from the list if a similar item occurs already */
        for (ale = anim_data->first; ale; ale = next) {
@@ -2280,7 +2383,7 @@ size_t ANIM_animdata_filter(bAnimContext *ac, ListBase *anim_data, int filter_mo
                                        items += animfilter_action(ac, anim_data, ads, data, filter_mode, (ID *)obact);
                        }
                        break;
-                               
+                       
                        case ANIMCONT_SHAPEKEY: /* 'ShapeKey Editor' */
                        {
                                /* the check for the DopeSheet summary is included here since the summary works here too */
@@ -2291,10 +2394,18 @@ size_t ANIM_animdata_filter(bAnimContext *ac, ListBase *anim_data, int filter_mo
                                
                        case ANIMCONT_GPENCIL:
                        {
-                               items = animdata_filter_gpencil(anim_data, data, filter_mode);
+                               if (animdata_filter_dopesheet_summary(ac, anim_data, filter_mode, &items))
+                                       items = animdata_filter_gpencil(anim_data, data, filter_mode);
                        }
                        break;
-                               
+                       
+                       case ANIMCONT_MASK:
+                       {
+                               if (animdata_filter_dopesheet_summary(ac, anim_data, filter_mode, &items))
+                                       items = animdata_filter_mask(anim_data, data, filter_mode);
+                       }
+                       break;
+                       
                        case ANIMCONT_DOPESHEET: /* 'DopeSheet Editor' */
                        {
                                /* the DopeSheet editor is the primary place where the DopeSheet summaries are useful */