Sound clip NLA Strips for Nexyon
authorJoshua Leung <aligorith@gmail.com>
Sun, 7 Aug 2011 12:27:20 +0000 (12:27 +0000)
committerJoshua Leung <aligorith@gmail.com>
Sun, 7 Aug 2011 12:27:20 +0000 (12:27 +0000)
These are basically just for specifying when a speaker should fire off
it's soundclip, and as such, many NLA operations are irrelevant for
it. They can only be specified on object-level for speaker objects.

I've still got some UI tweaks I'll need to work on in order for these
to be able to be added even when the speaker doesn't have any NLA
tracks yet. (EDIT: while typing this, I had an idea for how to do
this, but that'll be for next commit). In the mean time, you'll need
to add a single keyframe for the object, snowflake that action and
delete the NLA strip before you can start editing.

12 files changed:
release/scripts/startup/bl_ui/space_nla.py
source/blender/blenkernel/BKE_nla.h
source/blender/blenkernel/intern/anim_sys.c
source/blender/blenkernel/intern/nla.c
source/blender/editors/animation/anim_filter.c
source/blender/editors/space_nla/nla_buttons.c
source/blender/editors/space_nla/nla_draw.c
source/blender/editors/space_nla/nla_edit.c
source/blender/editors/space_nla/nla_intern.h
source/blender/editors/space_nla/nla_ops.c
source/blender/makesdna/DNA_anim_types.h
source/blender/makesrna/intern/rna_nla.c

index 78489db63177046921579cb5ff8320c59bb1cd76..b6c2d078960feefc55bceee600ec049dcdc971da 100644 (file)
@@ -173,6 +173,7 @@ class NLA_MT_add(bpy.types.Menu):
         layout.column()
         layout.operator("nla.actionclip_add")
         layout.operator("nla.transition_add")
+        layout.operator("nla.soundclip_add")
 
         layout.separator()
         layout.operator("nla.meta_add")
index 0206756a1ad0a097321dbbb76e4591674a496500..49c1f8acd24781f7dc9e8c7c1365d3756ca37111 100644 (file)
@@ -39,6 +39,8 @@ struct AnimData;
 struct NlaStrip;
 struct NlaTrack;
 struct bAction;
+struct Scene;
+struct Speaker;
 
 /* ----------------------------- */
 /* Data Management */
@@ -54,6 +56,7 @@ void copy_nladata(ListBase *dst, ListBase *src);
 struct NlaTrack *add_nlatrack(struct AnimData *adt, struct NlaTrack *prev);
 struct NlaStrip *add_nlastrip(struct bAction *act);
 struct NlaStrip *add_nlastrip_to_stack(struct AnimData *adt, struct bAction *act);
+struct NlaStrip *add_nla_soundstrip(struct Scene *scene, struct Speaker *spk);
 
 /* ----------------------------- */
 /* API */
index a43cdc8143e03c87ff3bb7050958d1ef162ef6d9..832d13c9c2fc3a93cfa44c54f85faec6f4a693d7 100644 (file)
@@ -1921,6 +1921,9 @@ void nlastrip_evaluate (PointerRNA *ptr, ListBase *channels, ListBase *modifiers
                case NLASTRIP_TYPE_META: /* meta */
                        nlastrip_evaluate_meta(ptr, channels, modifiers, nes);
                        break;
+                       
+               default: /* do nothing */
+                       break;
        }
        
        /* clear temp recursion safe-check */
index f2ce8e4e6f1e045fbc732a03a83aacd4de263791..dad496466227a0bbe312979df6654ec7a72bc5a1 100644 (file)
@@ -46,6 +46,8 @@
 
 #include "DNA_anim_types.h"
 #include "DNA_scene_types.h"
+#include "DNA_sound_types.h"
+#include "DNA_speaker_types.h"
 
 #include "BKE_action.h"
 #include "BKE_fcurve.h"
@@ -53,6 +55,9 @@
 #include "BKE_global.h"
 #include "BKE_library.h"
 
+#ifdef WITH_AUDASPACE
+#  include "AUD_C-API.h"
+#endif
 
 #include "RNA_access.h"
 #include "nla_private.h"
@@ -337,6 +342,41 @@ NlaStrip *add_nlastrip_to_stack (AnimData *adt, bAction *act)
        return strip;
 }
 
+/* Add a NLA Strip referencing the given speaker's sound */
+NlaStrip *add_nla_soundstrip (Scene *scene, Speaker *speaker)
+{
+       NlaStrip *strip = MEM_callocN(sizeof(NlaStrip), "NlaSoundStrip");
+       
+       /* if speaker has a sound, set the strip length to the length of the sound,
+        * otherwise default to length of 10 frames
+        */
+#ifdef WITH_AUDASPACE
+       if (speaker->sound) 
+       {
+               AUD_SoundInfo info = AUD_getInfo(speaker->sound->playback_handle);
+               
+               strip->end = ceil(info.length * FPS);
+       }
+       else 
+#endif
+       {
+               strip->end = 10.0f;
+       }
+       
+       /* general settings */
+       strip->type = NLASTRIP_TYPE_SOUND;
+       
+       strip->flag = NLASTRIP_FLAG_SELECT;
+       strip->extendmode = NLASTRIP_EXTEND_NOTHING; /* nothing to extend... */
+       
+       /* strip should be referenced as-is */
+       strip->scale= 1.0f;
+       strip->repeat = 1.0f;
+       
+       /* return this strip */
+       return strip;
+}
+
 /* *************************************************** */
 /* NLA Evaluation <-> Editing Stuff */
 
index 4927b0f097aa05b96e0ad60c811ee4073933c412..b4d1253c764669e299f5b33ab505089e3198c622 100644 (file)
@@ -397,6 +397,7 @@ short ANIM_animdata_get_context (const bContext *C, bAnimContext *ac)
  *     2A) nla tracks: include animdata block's data as there are NLA tracks+strips there
  *     2B) actions to convert to nla: include animdata block's data as there is an action that can be 
  *             converted to a new NLA strip, and the filtering options allow this
+ *     2C) allow non-animated datablocks to be included so that datablocks can be added
  *     3) drivers: include drivers from animdata block (for Drivers mode in Graph Editor)
  *     4) normal keyframes: only when there is an active action
  */
@@ -1625,7 +1626,7 @@ static size_t animdata_filter_ds_obdata (bAnimContext *ac, ListBase *anim_data,
                case OB_SPEAKER: /* ---------- Speaker ----------- */
                {
                        Speaker *spk= (Speaker *)ob->data;
-
+                       
                        type= ANIMTYPE_DSSPK;
                        expanded= FILTER_SPK_OBJD(spk);
                }
index b6de8e7fb5942bfb7e8378a32979d45ea9bfa9e2..0f0662d84b1a859e23a6b9604ae33ec0d760e91e 100644 (file)
@@ -213,6 +213,24 @@ static int nla_strip_actclip_panel_poll(const bContext *C, PanelType *UNUSED(pt)
        return (strip->type == NLASTRIP_TYPE_CLIP);
 }
 
+static int nla_strip_eval_panel_poll(const bContext *C, PanelType *UNUSED(pt))
+{
+       PointerRNA ptr;
+       NlaStrip *strip;
+       
+       if (!nla_panel_context(C, NULL, NULL, &ptr))
+               return 0;
+       if (ptr.data == NULL)
+               return 0;
+       
+       strip= ptr.data;
+       
+       if (strip->type == NLASTRIP_TYPE_SOUND)
+               return 0;
+               
+       return 1;
+}
+
 /* -------------- */
 
 /* active AnimData */
@@ -278,6 +296,7 @@ static void nla_panel_properties(const bContext *C, Panel *pa)
        uiLayout *layout= pa->layout;
        uiLayout *column, *row, *subcol;
        uiBlock *block;
+       short showEvalProps = 1;
        
        if (!nla_panel_context(C, NULL, NULL, &strip_ptr))
                return;
@@ -297,32 +316,41 @@ static void nla_panel_properties(const bContext *C, Panel *pa)
                uiItemR(column, &strip_ptr, "frame_start", 0, NULL, ICON_NONE);
                uiItemR(column, &strip_ptr, "frame_end", 0, NULL, ICON_NONE);
        
-       /* extrapolation */
-       row= uiLayoutRow(layout, 1);
-               uiItemR(row, &strip_ptr, "extrapolation", 0, NULL, ICON_NONE);
+       /* Evaluation-Related Strip Properties ------------------ */
        
-       /* blending */
-       row= uiLayoutRow(layout, 1);
-               uiItemR(row, &strip_ptr, "blend_type", 0, NULL, ICON_NONE);
-               
-       /* blend in/out + autoblending
-        *      - blend in/out can only be set when autoblending is off
-        */
-       column= uiLayoutColumn(layout, 1);
-               uiLayoutSetActive(column, RNA_boolean_get(&strip_ptr, "use_animated_influence")==0); 
-               uiItemR(column, &strip_ptr, "use_auto_blend", 0, NULL, ICON_NONE); // XXX as toggle?
-               
-               subcol= uiLayoutColumn(column, 1);
-                       uiLayoutSetActive(subcol, RNA_boolean_get(&strip_ptr, "use_auto_blend")==0); 
-                       uiItemR(subcol, &strip_ptr, "blend_in", 0, NULL, ICON_NONE);
-                       uiItemR(subcol, &strip_ptr, "blend_out", 0, NULL, ICON_NONE);
+       /* sound properties strips don't have these settings */
+       if (RNA_enum_get(&strip_ptr, "type") == NLASTRIP_TYPE_SOUND)
+               showEvalProps = 0;
+       
+       /* only show if allowed to... */
+       if (showEvalProps) {
+               /* extrapolation */
+               row= uiLayoutRow(layout, 1);
+                       uiItemR(row, &strip_ptr, "extrapolation", 0, NULL, ICON_NONE);
                
-       /* settings */
-       column= uiLayoutColumn(layout, 1);
-               uiLayoutSetActive(column, !(RNA_boolean_get(&strip_ptr, "use_animated_influence") || RNA_boolean_get(&strip_ptr, "use_animated_time"))); 
-               uiItemL(column, "Playback Settings:", ICON_NONE);
-               uiItemR(column, &strip_ptr, "mute", 0, NULL, ICON_NONE);
-               uiItemR(column, &strip_ptr, "use_reverse", 0, NULL, ICON_NONE);
+               /* blending */
+               row= uiLayoutRow(layout, 1);
+                       uiItemR(row, &strip_ptr, "blend_type", 0, NULL, ICON_NONE);
+                       
+               /* blend in/out + autoblending
+                *      - blend in/out can only be set when autoblending is off
+                */
+               column= uiLayoutColumn(layout, 1);
+                       uiLayoutSetActive(column, RNA_boolean_get(&strip_ptr, "use_animated_influence")==0); 
+                       uiItemR(column, &strip_ptr, "use_auto_blend", 0, NULL, ICON_NONE); // XXX as toggle?
+                       
+                       subcol= uiLayoutColumn(column, 1);
+                               uiLayoutSetActive(subcol, RNA_boolean_get(&strip_ptr, "use_auto_blend")==0); 
+                               uiItemR(subcol, &strip_ptr, "blend_in", 0, NULL, ICON_NONE);
+                               uiItemR(subcol, &strip_ptr, "blend_out", 0, NULL, ICON_NONE);
+                       
+               /* settings */
+               column= uiLayoutColumn(layout, 1);
+                       uiLayoutSetActive(column, !(RNA_boolean_get(&strip_ptr, "use_animated_influence") || RNA_boolean_get(&strip_ptr, "use_animated_time"))); 
+                       uiItemL(column, "Playback Settings:", ICON_NONE);
+                       uiItemR(column, &strip_ptr, "mute", 0, NULL, ICON_NONE);
+                       uiItemR(column, &strip_ptr, "use_reverse", 0, NULL, ICON_NONE);
+       }
 }
 
 
@@ -476,14 +504,14 @@ void nla_buttons_register(ARegionType *art)
        strcpy(pt->idname, "NLA_PT_evaluation");
        strcpy(pt->label, "Evaluation");
        pt->draw= nla_panel_evaluation;
-       pt->poll= nla_strip_panel_poll;
+       pt->poll= nla_strip_eval_panel_poll;
        BLI_addtail(&art->paneltypes, pt);
        
        pt= MEM_callocN(sizeof(PanelType), "spacetype nla panel modifiers");
        strcpy(pt->idname, "NLA_PT_modifiers");
        strcpy(pt->label, "Modifiers");
        pt->draw= nla_panel_modifiers;
-       pt->poll= nla_strip_panel_poll;
+       pt->poll= nla_strip_eval_panel_poll;
        BLI_addtail(&art->paneltypes, pt);
 }
 
index bc0b9616836a40406d57d128df4fb059ce2b4e2f..eb9529b518694c2db6bc7b17944bdea17d33bc99 100644 (file)
@@ -198,7 +198,24 @@ static void nla_strip_get_color_inside (AnimData *adt, NlaStrip *strip, float co
                        color[1]= 0.15f;
                        color[2]= 0.26f;
                }
-       }       
+       }
+       else if (strip->type == NLASTRIP_TYPE_SOUND) {
+               /* Sound Clip */
+               if (strip->flag & NLASTRIP_FLAG_SELECT) {
+                       /* selected - use a bright teal color */
+                       // FIXME: hardcoded temp-hack colors
+                       color[0]= 0.12f;
+                       color[1]= 0.48f;
+                       color[2]= 0.48f;
+               }
+               else {
+                       /* normal, unselected strip - use (hardly noticable) teal tinge */
+                       // FIXME: hardcoded temp-hack colors
+                       color[0]= 0.17f;
+                       color[1]= 0.24f;
+                       color[2]= 0.24f;
+               }
+       }
        else {
                /* Action Clip (default/normal type of strip) */
                if ((strip->flag & NLASTRIP_FLAG_ACTIVE) && (adt && (adt->flag & ADT_NLA_EDIT_ON))) {
index eb22495c977de3ad6aceed02a3b133aa08d4b56a..fa24bd2f895480803d5b35df7df1f9edf0d272ce 100644 (file)
@@ -36,6 +36,7 @@
 #include <math.h>
 
 #include "DNA_anim_types.h"
+#include "DNA_object_types.h"
 #include "DNA_scene_types.h"
 
 #include "MEM_guardedalloc.h"
@@ -536,12 +537,15 @@ static int nlaedit_add_transition_exec (bContext *C, wmOperator *op)
                        /* check if there's space between the two */
                        if (IS_EQ(s1->end, s2->start))
                                continue;
-                       /* make neither one is a transition 
+                       /* make sure neither one is a transition 
                         *      - although this is impossible to create with the standard tools, 
                         *        the user may have altered the settings
                         */
                        if (ELEM(NLASTRIP_TYPE_TRANSITION, s1->type, s2->type))
                                continue;
+                       /* also make sure neither one is a soundclip */
+                       if (ELEM(NLASTRIP_TYPE_SOUND, s1->type, s2->type))
+                               continue;
                                
                        /* allocate new strip */
                        strip= MEM_callocN(sizeof(NlaStrip), "NlaStrip");
@@ -608,6 +612,91 @@ void NLA_OT_transition_add (wmOperatorType *ot)
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 }
 
+/* ******************** Add Sound Clip Operator ***************************** */
+/* Add a new sound clip */
+
+static int nlaedit_add_sound_exec (bContext *C, wmOperator *op)
+{
+       bAnimContext ac;
+       
+       ListBase anim_data = {NULL, NULL};
+       bAnimListElem *ale;
+       int filter;
+       
+       Scene *scene;
+       int cfra;
+       
+       /* get editor data */
+       if (ANIM_animdata_get_context(C, &ac) == 0)
+               return OPERATOR_CANCELLED;
+       
+       scene = ac.scene;
+       cfra = CFRA;
+       
+       /* get a list of the editable tracks being shown in the NLA */
+       filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_FOREDIT);
+       ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+       
+       /* for each track, add sound clips if it belongs to a speaker */
+       // TODO: what happens if there aren't any tracks... well that's a more general problem for later
+       for (ale= anim_data.first; ale; ale= ale->next) {
+               Object *ob = (Object *)ale->id; /* may not be object until we actually check! */
+               
+               AnimData *adt = ale->adt;
+               NlaTrack *nlt= (NlaTrack *)ale->data;
+               NlaStrip *strip;
+               
+               /* does this belong to speaker - assumed to live on Object level only */
+               if ((GS(ale->id->name) != ID_OB) || (ob->type != OB_SPEAKER))
+                       continue;
+                       
+               /* create a new strip, and offset it to start on the current frame */
+               strip= add_nla_soundstrip(ac.scene, ob->data); 
+               
+               strip->start    += cfra;
+               strip->end              += cfra;
+               
+               /* firstly try adding strip to our current track, but if that fails, add to a new track */
+               if (BKE_nlatrack_add_strip(nlt, strip) == 0) {
+                       /* trying to add to the current failed (no space), 
+                        * so add a new track to the stack, and add to that...
+                        */
+                       nlt= add_nlatrack(adt, NULL);
+                       BKE_nlatrack_add_strip(nlt, strip);
+               }
+               
+               /* auto-name it */
+               BKE_nlastrip_validate_name(adt, strip);
+       }
+       
+       /* free temp data */
+       BLI_freelistN(&anim_data);
+       
+       /* refresh auto strip properties */
+       ED_nla_postop_refresh(&ac);
+       
+       /* set notifier that things have changed */
+       WM_event_add_notifier(C, NC_ANIMATION|ND_NLA|NA_EDITED, NULL);
+       
+       /* done */
+       return OPERATOR_FINISHED;
+}
+
+void NLA_OT_soundclip_add (wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Add Sound Clip";
+       ot->idname= "NLA_OT_soundclip_add";
+       ot->description= "Add a strip for controlling when speaker plays its sound clip";
+       
+       /* api callbacks */
+       ot->exec= nlaedit_add_sound_exec;
+       ot->poll= nlaop_poll_tweakmode_off;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
 /* ******************** Add Meta-Strip Operator ***************************** */
 /* Add new meta-strips incorporating the selected strips */
 
@@ -1923,6 +2012,10 @@ static int nla_fmodifier_add_exec(bContext *C, wmOperator *op)
                                        continue;
                        }
                        
+                       /* sound clips are not affected by FModifiers */
+                       if (strip->type == NLASTRIP_TYPE_SOUND)
+                               continue;
+                       
                        /* add F-Modifier of specified type to selected, and make it the active one */
                        fcm= add_fmodifier(&strip->modifiers, type);
                        
index 43ef5beb216b2a6efa0032376accb98da0cc92b5..bd76d2484ddab32130cee3b5c0d2c76d3b7aca7c 100644 (file)
@@ -99,6 +99,7 @@ void NLA_OT_view_selected(wmOperatorType *ot);
 
 void NLA_OT_actionclip_add(wmOperatorType *ot);
 void NLA_OT_transition_add(wmOperatorType *ot);
+void NLA_OT_soundclip_add(wmOperatorType *ot);
 
 void NLA_OT_meta_add(wmOperatorType *ot);
 void NLA_OT_meta_remove(wmOperatorType *ot);
index 38e12c46060ded60a3c73f1d8588a9b6ae85495e..8ed117755c73551a11027e808105ee434fba6de8 100644 (file)
@@ -140,6 +140,7 @@ void nla_operatortypes(void)
        
        WM_operatortype_append(NLA_OT_actionclip_add);
        WM_operatortype_append(NLA_OT_transition_add);
+       WM_operatortype_append(NLA_OT_soundclip_add);
        
        WM_operatortype_append(NLA_OT_meta_add);
        WM_operatortype_append(NLA_OT_meta_remove);
@@ -233,6 +234,7 @@ static void nla_keymap_main (wmKeyConfig *keyconf, wmKeyMap *keymap)
                /* add strips */
        WM_keymap_add_item(keymap, "NLA_OT_actionclip_add", AKEY, KM_PRESS, KM_SHIFT, 0);
        WM_keymap_add_item(keymap, "NLA_OT_transition_add", TKEY, KM_PRESS, KM_SHIFT, 0);
+       WM_keymap_add_item(keymap, "NLA_OT_soundclip_add", KKEY, KM_PRESS, KM_SHIFT, 0);
        
                /* meta-strips */
        WM_keymap_add_item(keymap, "NLA_OT_meta_add", GKEY, KM_PRESS, KM_SHIFT, 0);
index 374799ecf08a6ef2f3d7154a2865019ae6110d90..5a031e04fe492756902edb8834b01f236d673309 100644 (file)
@@ -651,7 +651,10 @@ typedef enum eNlaStrip_Type {
                /* 'transition' - blends between the adjacent strips */
        NLASTRIP_TYPE_TRANSITION,
                /* 'meta' - a strip which acts as a container for a few others */
-       NLASTRIP_TYPE_META
+       NLASTRIP_TYPE_META,     
+       
+               /* 'emit sound' - a strip which is used for timing when speaker emits sounds */
+       NLASTRIP_TYPE_SOUND
 } eNlaStrip_Type;
 
 /* NLA Tracks ------------------------------------- */
index 01bfbc0e13316cef1a10cf45fe3aeb2409c5b32c..5756044d12b0e5310f76c9fe561f9504f38f08b8 100644 (file)
@@ -380,6 +380,7 @@ static void rna_def_nlastrip(BlenderRNA *brna)
                {NLASTRIP_TYPE_CLIP, "CLIP", 0, "Action Clip", "NLA Strip references some Action"},
                {NLASTRIP_TYPE_TRANSITION, "TRANSITION", 0, "Transition", "NLA Strip 'transitions' between adjacent strips"},
                {NLASTRIP_TYPE_META, "META", 0, "Meta", "NLA Strip acts as a container for adjacent strips"},
+               {NLASTRIP_TYPE_SOUND, "SOUND", 0, "Sound Clip", "NLA Strip representing a sound event for speakers"},
                {0, NULL, 0, NULL, NULL}};
        
        /* struct definition */
@@ -447,7 +448,6 @@ static void rna_def_nlastrip(BlenderRNA *brna)
        RNA_def_property_update(prop, NC_ANIMATION|ND_NLA, NULL); /* this will do? */
        
        /* Action */
-       // TODO: this should only be editable if it is not being edited atm...
        prop= RNA_def_property(srna, "action", PROP_POINTER, PROP_NONE);
        RNA_def_property_pointer_sdna(prop, NULL, "act");
        RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_Action_id_poll");